how to get "native window" ?
-
I don't know about the 'native window' approach. As for redirecting the output we have both the documentation: QProcess Class | Qt Core 6.6.1[^] and sample code: C++ (Cpp) QProcess::readAllStandardOutput Examples - HotExamples[^].
"In testa che avete, Signor di Ceprano?" -- Rigoletto
-
Launching a gnome terminal from QT seems like a bit of a frankenstein. Surely a better option would be a terminal widget. A quick google search seems to indicate that QT does not provide a terminal widget, but others have written them, such as this one [here](https://github.com/lxqt/qtermwidget/releases/tag/1.4.0). Failing that, you might want to pull KDE into the mix and that would get you the KDE terminal widget. Or you could use KDE Konsole as an alternative to gnome-terminal, which would keep your UI more consistent. I'm not sure why you wan to launch a terminal to run a command and capture the output. That's what QProcess, or going down a level, popen() is for. QProcess even alows you to capture stderr, which is not as easy with popen(). The only reason you'd want to launch a terminal would be if you needed to get some user input. If you don't need that, then QProcess is probably what you want.
"A little song, a little dance, a little seltzer down your pants" Chuckles the clown
-
I don't know about the 'native window' approach. As for redirecting the output we have both the documentation: QProcess Class | Qt Core 6.6.1[^] and sample code: C++ (Cpp) QProcess::readAllStandardOutput Examples - HotExamples[^].
"In testa che avete, Signor di Ceprano?" -- Rigoletto
Thanks for (unexpected ) reply. I have been trying different "waitfor..." and just cannot get response from the process. For info - I am enclosing my current code - to be deleted later. I need to have user's input and reason for using "command" is my disillusionment with library I am not allowed to mention here. I am also including current "debug" output to show there is no response... Please keep in mind this is "under construction" code....
{
result = " TEST ";#ifdef LINUX_TERMINAL
//#ifdef CONNECT
text = "TASK DEBUG LINUX_TERMINAL START ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endifQElapsedTimer \*ET = new QElapsedTimer(); text = " DEBUG terminal.... "; text += Q\_FUNC\_INFO; text += " @ line "; text += QString::number(\_\_LINE\_\_); //ui->textEdit\_2->append(text); // debug qDebug()<textEdit\_2->append(text); // text = "sudo ls " ; QProcess \*process; process = new QProcess(); //process->start("sh", QStringList() << "-c" << "xterm -e hcitool -fa 'Monospace' -fs 18"); // QP.start("sh", QStringList() << "-c" << "xterm -e hcitool "); process->start("sh", QStringList() << "-c" << "xterm"); qDebug(" QProcess waitForFinished"); if(process->Running) { qDebug(" QProcess is running... process->readAllStandardOutput() "); QByteArray output = process->readAllStandardOutput(); qDebug() << output; QString str1 = "lsusb"; QByteArray ba = str1.toLocal8Bit(); const char \*c\_str2 = ba.data(); printf("str2: %s", c\_str2); //return app.exec(); process->write(c\_str2); } else qDebug(" QProcess FAILED to start... "); return "TEST"; //#ifdef BYPASS //process->start("hcitool", QStringList() << "dev"); ET->start(); process->start("/usr/bin/gnome-terminal", QStringList() << ""); //QProcess myProcess; // myProcess.start("/bin/ls"); process->waitForFinished(); text = " process->waitForFinished() TOK "; text += Q\_FUNC\_INFO; text += " @ line "; text += QString::number(\_\_LINE\_\_); //ui->textEdit\_2->append(text); // debug qDebug()<readAllStandardOutput(); qDeb
-
Thanks for (unexpected ) reply. I have been trying different "waitfor..." and just cannot get response from the process. For info - I am enclosing my current code - to be deleted later. I need to have user's input and reason for using "command" is my disillusionment with library I am not allowed to mention here. I am also including current "debug" output to show there is no response... Please keep in mind this is "under construction" code....
{
result = " TEST ";#ifdef LINUX_TERMINAL
//#ifdef CONNECT
text = "TASK DEBUG LINUX_TERMINAL START ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endifQElapsedTimer \*ET = new QElapsedTimer(); text = " DEBUG terminal.... "; text += Q\_FUNC\_INFO; text += " @ line "; text += QString::number(\_\_LINE\_\_); //ui->textEdit\_2->append(text); // debug qDebug()<textEdit\_2->append(text); // text = "sudo ls " ; QProcess \*process; process = new QProcess(); //process->start("sh", QStringList() << "-c" << "xterm -e hcitool -fa 'Monospace' -fs 18"); // QP.start("sh", QStringList() << "-c" << "xterm -e hcitool "); process->start("sh", QStringList() << "-c" << "xterm"); qDebug(" QProcess waitForFinished"); if(process->Running) { qDebug(" QProcess is running... process->readAllStandardOutput() "); QByteArray output = process->readAllStandardOutput(); qDebug() << output; QString str1 = "lsusb"; QByteArray ba = str1.toLocal8Bit(); const char \*c\_str2 = ba.data(); printf("str2: %s", c\_str2); //return app.exec(); process->write(c\_str2); } else qDebug(" QProcess FAILED to start... "); return "TEST"; //#ifdef BYPASS //process->start("hcitool", QStringList() << "dev"); ET->start(); process->start("/usr/bin/gnome-terminal", QStringList() << ""); //QProcess myProcess; // myProcess.start("/bin/ls"); process->waitForFinished(); text = " process->waitForFinished() TOK "; text += Q\_FUNC\_INFO; text += " @ line "; text += QString::number(\_\_LINE\_\_); //ui->textEdit\_2->append(text); // debug qDebug()<readAllStandardOutput(); qDeb
process->start("sh", QStringList() << "-c" << "xterm");
It looks like you are starting a terminal session via the shell. At a guess the
xterm
process is running and the shell process that started it is waiting for it to finish. And your application will be waiting until bothxterm
and its parent shell terminate. At which time I doubt that there will be anystdout
to capture. -
Launching a gnome terminal from QT seems like a bit of a frankenstein. Surely a better option would be a terminal widget. A quick google search seems to indicate that QT does not provide a terminal widget, but others have written them, such as this one [here](https://github.com/lxqt/qtermwidget/releases/tag/1.4.0). Failing that, you might want to pull KDE into the mix and that would get you the KDE terminal widget. Or you could use KDE Konsole as an alternative to gnome-terminal, which would keep your UI more consistent. I'm not sure why you wan to launch a terminal to run a command and capture the output. That's what QProcess, or going down a level, popen() is for. QProcess even alows you to capture stderr, which is not as easy with popen(). The only reason you'd want to launch a terminal would be if you needed to get some user input. If you don't need that, then QProcess is probably what you want.
"A little song, a little dance, a little seltzer down your pants" Chuckles the clown
Here is my latest observation.
//result = BTUL->ProcessCommand\_Raw(" /usr/bin/gnome-terminal ", "",0);FAILS result = BTUL->ProcessCommand\_Raw("hcitool", "",0); OK
qDebug()<textEdit_3->append(result);
return result;then my question (still) is what is the difference ? temporary conclusion as advertised (RTFM) I should be able to write /read to/ from process and I can in case of "hcitool". I realize there are other options / tools BUT call me stubborn - I want to know why one process works and the other does not. Simple as that. And I do appreciate (constructive) contributions towards a solution.
-
Here is my latest observation.
//result = BTUL->ProcessCommand\_Raw(" /usr/bin/gnome-terminal ", "",0);FAILS result = BTUL->ProcessCommand\_Raw("hcitool", "",0); OK
qDebug()<textEdit_3->append(result);
return result;then my question (still) is what is the difference ? temporary conclusion as advertised (RTFM) I should be able to write /read to/ from process and I can in case of "hcitool". I realize there are other options / tools BUT call me stubborn - I want to know why one process works and the other does not. Simple as that. And I do appreciate (constructive) contributions towards a solution.
When you launch a program via QProcess, it maps the stdin/stdout/stderr to QT stream objects you can read and write to/from. That's fairly straight forward, and I think you understand that. Now, when you launch a terminal via QProcess, the stdin/stdout/stderr of the terminal get mapped as expected. But what the terminal does is create a pseudo tty (e.g. /dev/pts/
n
) and uses that for the stdin/stdout/stderr for the process it's running, and displays the results in its window. visually, something like:QProcess <=stdin/out=> xterm
+ pty <=stdin/out=> /bin/lsIn general, terminal emulators do not forward child program's I/O to its own stdin/out. There might be ways to do that, you'd have to check the manual pages for whatever terminal emulator to see if that's possible. So this is exactly what happens if you say
xterm -e /bin/ps
from the command line. In this case, xterm launches, it displays the output of /bin/ps to its screen, and then closes. In the original command line window, nothing gets printed - unless there's output from xterm itself. Hopefully that explains things a bit for you, and does not add to your confusion."A little song, a little dance, a little seltzer down your pants" Chuckles the clown
-
Salvatore Terress wrote:
Apparently there are at least two ways to accomplish that.
All languages, C++ or anything else, for an external app has the following communication paths. - Start Up - Command line parameters. - Running. Exit code. Which is an int value and nothing else. - Running. Stdio: stderr, stdin, stdout. Using the above I have implemented the following in the past - One computer connecting to multiple hardware devices. - Error output collected. - Logging collected. - Commands controlling each device. - Binary data sent to and from each device. An application might provide another API. But that has nothing to do with running it from the first application. And for most standard 'OS Command line' commands it will not apply. As a specific example you can start and stop IIS using command line commands. But you are definitely not going to be accessing web sites from it using exactly the same commands (if at all using a OS command.) Using a command line app and controlling it requires that one understand exactly what the app does. And that has nothing to do with the controller code from the calling app. Using a OS shell is going to make the above MUCH harder. That is because the shell must then redirect all output from any commands it runs back along the stdio path (in and out.) Getting the shell to do that has nothing to do with the calling application. One will need to figure that out by looking for command line parameter to the shell itself. Although I suspect that that it is possible to do this, at the very least I know it is difficult.
-
Salvatore Terress wrote:
Apparently there are at least two ways to accomplish that.
All languages, C++ or anything else, for an external app has the following communication paths. - Start Up - Command line parameters. - Running. Exit code. Which is an int value and nothing else. - Running. Stdio: stderr, stdin, stdout. Using the above I have implemented the following in the past - One computer connecting to multiple hardware devices. - Error output collected. - Logging collected. - Commands controlling each device. - Binary data sent to and from each device. An application might provide another API. But that has nothing to do with running it from the first application. And for most standard 'OS Command line' commands it will not apply. As a specific example you can start and stop IIS using command line commands. But you are definitely not going to be accessing web sites from it using exactly the same commands (if at all using a OS command.) Using a command line app and controlling it requires that one understand exactly what the app does. And that has nothing to do with the controller code from the calling app. Using a OS shell is going to make the above MUCH harder. That is because the shell must then redirect all output from any commands it runs back along the stdio path (in and out.) Getting the shell to do that has nothing to do with the calling application. One will need to figure that out by looking for command line parameter to the shell itself. Although I suspect that that it is possible to do this, at the very least I know it is difficult.
Thanks for all the replies. I have been thru this before and had to fix some other part of the project. Again , RTFM is little misreading...but that is not my concern. I may have said this before when my command is "hcitool dev" I get expected response (stdio)- non issue. To be able to do "hcitool info (address)" I need to have "sudo" access... Such access has NOTHING to do with Linux security. and that is when I need interactive repose and that is when SAME "shell" does not work. I'll to modify "sudo" configuration, but not sure if "hcitool info" will work.
-
Thanks for all the replies. I have been thru this before and had to fix some other part of the project. Again , RTFM is little misreading...but that is not my concern. I may have said this before when my command is "hcitool dev" I get expected response (stdio)- non issue. To be able to do "hcitool info (address)" I need to have "sudo" access... Such access has NOTHING to do with Linux security. and that is when I need interactive repose and that is when SAME "shell" does not work. I'll to modify "sudo" configuration, but not sure if "hcitool info" will work.
Salvatore Terress wrote:
I need to have "sudo" access... Such access has NOTHING to do with Linux security.
Yes, it has everything to do with Linux security, as clearly explained in the man page: https://linux.die.net/man/8/sudo[^]. And although I have not tried this myself, I strongly suspect that you cannot use it in the way you are trying to do. If you want elevated/admin permissions then you most likely need to call
sudo
before you start the original application. And this question has nothing to do with C/C++; please use the correct forums for your questions. -
Thanks for all the replies. I have been thru this before and had to fix some other part of the project. Again , RTFM is little misreading...but that is not my concern. I may have said this before when my command is "hcitool dev" I get expected response (stdio)- non issue. To be able to do "hcitool info (address)" I need to have "sudo" access... Such access has NOTHING to do with Linux security. and that is when I need interactive repose and that is when SAME "shell" does not work. I'll to modify "sudo" configuration, but not sure if "hcitool info" will work.
In today's O/S security systems, there is usually a wall between normal user processes and admin-level processes. You cannot access the streams of an admin process from a normal user process. Think about it for just 5 seconds and you'll see why this is a security risk and is now not allowed.
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles. Dave Kreskowiak
-
In today's O/S security systems, there is usually a wall between normal user processes and admin-level processes. You cannot access the streams of an admin process from a normal user process. Think about it for just 5 seconds and you'll see why this is a security risk and is now not allowed.
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles. Dave Kreskowiak
-
Thank your very much for all these "security comments" they are very helpful in resolving the issue. Appreciate that very much.
ADDENDUM This is a request for C/C++ code... This is specific application I am asking for assistance with actual code. I am still asking for assistance in actual C/C++ code to implement system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33"); hcitool cc command require root / sudo , period. hence I need to enter password WITHOUT running "terminal" which "sudo -S" option should provide. I DO NOT KNOW HOW TO ENTER PASSWORD in code USING stdin... I need help with that - I need actual C/C++ code it won't work if I run "sudo su" prior to executing my application after connection is established the code no longer needs to run as "su", it is of non issue . I am trying a solve different task, plain (Linux ) command, and having difficulty implementing the "sudo" bypass. In an essence, I should be able to "enter" password using a sudo command options -S and -ps It is unclear , to me , how to actually code it. I have this code :
system ("sudo -S su -ps q/n" );
system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33");
and this output
[sudo] password for nov25-1:
sudo: no password was provided
sudo: a password is required
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required -
ADDENDUM This is a request for C/C++ code... This is specific application I am asking for assistance with actual code. I am still asking for assistance in actual C/C++ code to implement system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33"); hcitool cc command require root / sudo , period. hence I need to enter password WITHOUT running "terminal" which "sudo -S" option should provide. I DO NOT KNOW HOW TO ENTER PASSWORD in code USING stdin... I need help with that - I need actual C/C++ code it won't work if I run "sudo su" prior to executing my application after connection is established the code no longer needs to run as "su", it is of non issue . I am trying a solve different task, plain (Linux ) command, and having difficulty implementing the "sudo" bypass. In an essence, I should be able to "enter" password using a sudo command options -S and -ps It is unclear , to me , how to actually code it. I have this code :
system ("sudo -S su -ps q/n" );
system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33");
and this output
[sudo] password for nov25-1:
sudo: no password was provided
sudo: a password is required
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is requiredI'm sure've been over this before:
$ id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users)create a new group for bluetooth users, call it btusers
$ sudo groupadd btusers
add user k5054 to the btusers group
$ sudo usermod -a -G btusers k5054
edit /etc/sudoers.d/btusers to allow any user in btusers group
to run hcitool without a password:
$ sudo visudo /etc/sudoers.d/btusers
add line %btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitoollog out and log back in again ...
$ sudo ps
[sudo] password for k5054: (CTL-D)
sudo: no password was provided
sudo: a password is requiredWe're now part of the btusers group, so we don't need a password for hcitool
id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users),1003(btusers)
sudo hcitool without needing a password
$ sudo hcitool dev
Devices:If you need to be able to run other commands you can append them as a comma separated items to the sudoers file e.g.
%btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitool,/usr/bin/hcidump
With knowledge comes great power. Use it wisely. But this should really be int the linux programming forum, or maybe System Admin.
"A little song, a little dance, a little seltzer down your pants" Chuckles the clown
-
ADDENDUM This is a request for C/C++ code... This is specific application I am asking for assistance with actual code. I am still asking for assistance in actual C/C++ code to implement system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33"); hcitool cc command require root / sudo , period. hence I need to enter password WITHOUT running "terminal" which "sudo -S" option should provide. I DO NOT KNOW HOW TO ENTER PASSWORD in code USING stdin... I need help with that - I need actual C/C++ code it won't work if I run "sudo su" prior to executing my application after connection is established the code no longer needs to run as "su", it is of non issue . I am trying a solve different task, plain (Linux ) command, and having difficulty implementing the "sudo" bypass. In an essence, I should be able to "enter" password using a sudo command options -S and -ps It is unclear , to me , how to actually code it. I have this code :
system ("sudo -S su -ps q/n" );
system ("sudo hcitool cc --role=c 98:D3:31:F8:29:33");
and this output
[sudo] password for nov25-1:
sudo: no password was provided
sudo: a password is required
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required -
I'm sure've been over this before:
$ id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users)create a new group for bluetooth users, call it btusers
$ sudo groupadd btusers
add user k5054 to the btusers group
$ sudo usermod -a -G btusers k5054
edit /etc/sudoers.d/btusers to allow any user in btusers group
to run hcitool without a password:
$ sudo visudo /etc/sudoers.d/btusers
add line %btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitoollog out and log back in again ...
$ sudo ps
[sudo] password for k5054: (CTL-D)
sudo: no password was provided
sudo: a password is requiredWe're now part of the btusers group, so we don't need a password for hcitool
id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users),1003(btusers)
sudo hcitool without needing a password
$ sudo hcitool dev
Devices:If you need to be able to run other commands you can append them as a comma separated items to the sudoers file e.g.
%btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitool,/usr/bin/hcidump
With knowledge comes great power. Use it wisely. But this should really be int the linux programming forum, or maybe System Admin.
"A little song, a little dance, a little seltzer down your pants" Chuckles the clown
-
I'm sure've been over this before:
$ id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users)create a new group for bluetooth users, call it btusers
$ sudo groupadd btusers
add user k5054 to the btusers group
$ sudo usermod -a -G btusers k5054
edit /etc/sudoers.d/btusers to allow any user in btusers group
to run hcitool without a password:
$ sudo visudo /etc/sudoers.d/btusers
add line %btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitoollog out and log back in again ...
$ sudo ps
[sudo] password for k5054: (CTL-D)
sudo: no password was provided
sudo: a password is requiredWe're now part of the btusers group, so we don't need a password for hcitool
id
uid=1002(k5054) gid=1002(k5054) groups=1002(k5054),27(sudo),100(users),1003(btusers)
sudo hcitool without needing a password
$ sudo hcitool dev
Devices:If you need to be able to run other commands you can append them as a comma separated items to the sudoers file e.g.
%btusers ALL=(ALL) NOPASSWD:/usr/bin/hcitool,/usr/bin/hcidump
With knowledge comes great power. Use it wisely. But this should really be int the linux programming forum, or maybe System Admin.
"A little song, a little dance, a little seltzer down your pants" Chuckles the clown
-
per sudo man I am trying to implement this as C++ command: -S, --stdin Write the prompt to the standard error and read the password from the standard input instead of using the terminal device. system (" sudo -S "); what am I missing ?
Salvatore Terress wrote:
what am I missing ?
It makes no difference how you run that command string, it will never work. If that command succeeds then the generated shell that runs the sudo command will be elevated to (possibly root) status. It will then terminate and return to your application which runs at non-elevated level. If you want root access in your application then you have two very simple choices: 1. Do what k5054 advised and set up your account to run at higher level. 2. Call sudo in your shell before launching your application.