In C/C++ how can my programs determine if there is a desktop (system or remote) or not?
My project has three separate programs running (now) in separate gnome-terminals. It is launched by the last line of .profile, so it starts whether I am at the system desktop (gnome) or remotely connecting by VPN/telnet or VPN/remote-desktop. My machine is 250 miles away at a test site, so I frequently login remotely to make changes and have to restart the program.
I'd like my program to be able to detect that it is launched from a desktop environment or from a telnet session. Preferably, I want them to continue running after the remote connection is broken.
Obviously, I need to make my programs into daemons so they will persist after I close the connection. But if I start them in a terminal on a desktop environment, where I can actually have three terminals open, I'd like to watch their progress messages. And if I disconnect the remote desktop, I'd like the daemons to detect this and turn off printing (to the now killed terms) but keep on running in normal (silent) daemon mode. Best of all, the programs could recheck for a desktop occasionally and resume printing by opening new terminals.
Is this possible? Any coding suggestions?
Thanks in advance.
You can use the isatty function. Detect if stdin is a terminal or pipe?
#include <stdio.h>
#include <io.h>
//...
if (isatty(fileno(stdin)))
printf( "stdin is a terminaln" );
else
printf( "stdin is a file or a pipen");
You can find more information at http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html
Some more code: http://pastebin.com/S3Lr9tik
The traditional solution for this problem is an option in the command
line. Such programs will typically demonize themselves unless given a
special debug option telling them not to.
Another solution would be to use a shell script to start the program as
a demon, via the nohup command (and redirecting standard input and
output to /dev/null).
As for determining whether your managing terminal is local or not, it
could be difficult; both X and telnet use virtual terminals, so if
you're running under X, you may not be able to distinguish between a
telnet session and a local xterm window. Still, it might be worth
trying... Under Linux, /proc/<procid>/fd/0 is a symbolic link to the
device connected to standard in (fd 0): using something like readlink,
you should be able to determine the actual name. Or fstat will give
you the major and minor numbers of the device. Given these, you might
be able to determine which is which. If your local terminal is not
under X, but a real terminal, it will definitely have a different minor
number than a pseudo-terminal. For xterms, it's possible that the minor
numbers of the pseudo-terminals fall in different ranges, or even that
there are distinct sets of pseudo-terminals for remote links and for X;
you'll probably have to experiment some, and there might be no working
solution. (For starters, to tty at each terminal, and see what it
says. I don't have local access to a Linux machine to check, but I seem
to remember that on Solaris, X terminals had names like /dev/ttyxx; my
remote terminals on Linux here are /dev/pts/xx. (Where xx is a
number in each case.)
Related
Hello dear Communauts,
I'm am creating a terminal animated status report for a parallel software I'm developing. I'm using NCurses.
I'm having an issue related to the restoring of the standard behavior of the terminal.
After running my software the terminal keeps having just 24 lines, no matter if I call endwin() or I don't.
Here the simplified code:
int size=10;
initscr();
refresh();
while(KeepAlive){
int j=1;
mvprintw(j,0,/*Blah blah header*/));
for(int i=0;i<size;i++){
j++;
mvprintw(j,0,/*Some blah blah*/);
}
refresh();
usleep(1000000);
}
endwin();
KeepAlive is a control variable changed by another thread (so the while is not infinite loop, but controlled loop).
After running this software my terminal has only 24 lines, echo works, but there's plenty of blank space.
Thanks a lot for your help, have fun
EDIT:
I would like to share with you some information I found while attempting to solve my issue:
curses (ncurses) is perfectly working under openMP, then you can imagine some threads doing your math calculations and one thread (only one, be aware) giving out some runtime infos.
curse (ncurses) is NOT compatible with MPI. Well, the right stating would be is "not completely" compatible with MPI. MPI is really sophisticated about stdin/stdout/stderr, since all outputs from all MPI-processes could be redirected to a display (which could be specified). Using any advanced terminal output overriding library will take to a fault of the code, or unexpected behaviors.
That's supported by the MPI faq:
Maybe. But probably not.
Open MPI provides fairly sophisticated stdin / stdout / stderr forwarding. >However, it does not work well with curses, ncurses, readline, or other >sophisticated I/O packages that generally require direct control of the terminal.
Every application and I/O library is different -- you should try to see if yours >is supported. But chances are that it won't work.
Sorry. :-(
found here (MPI reference).
What I've discovered is that even if you appoint only one MPI-process to manage all the curses output (just that process calls initscr() at the beginning and endwin() at the end of his part of code) there is no way to force curses to use the full terminal (only default UNIX 24x80 will be available).
Once MPI has been finalized your whole terminal will keep working in 24x80 mode until reset is called.
Thanks to all communauts that helped me,
Have fun
gf
One possible solution is to completely decouple your text GUI from the rest of the MPI code and make both parts talk to each other via the client/server mechanism of MPI-2. That means:
Run the GUI as singleton MPI program, i.e. one that calls MPI_Init{_thread} but is not started via mpiexec. It then should open a listening port by calling MPI_Open_port. The call returns a string port name that has to be supplied to the compute part of the application. The GUI part should then start listening for connections by calling the blocking MPI_Comm_accept.
The compute part is started as usual via mpiexec. It should connect to the GUI by calling MPI_Comm_connect given the port name from (1).
The combination of MPI_Comm_accept in the GUI and MPI_Comm_connect in the compute part establishes an intercommunicator that can be used for sending messages between the two parts. The compute part could e.g. send periodic status messages to the GUI. If necessary, the intercommunicator could be further "flattened" to an intracommunicator.
Once the computation is finished, the communication part should disconnect by calling MPI_Comm_disconnect.
The GUI should call MPI_Close_port and finish its own execution.
In that scenario, the GUI part could be a text mode curses application started locally or remotely via SSH, an X11 GUI application, or whatever else there.
It should work. The comment about "parallel" suggests multithreading, which can mean that your output is not flushed as one might expect.
Likely this is the same issue (Ncurses limited output size) for which more information was given. Neither question provides enough detail to offer more than generic advice.
I am writing some library code which will rerun the current process as an administrator/root. The problem is (for linux at least) that if the calling code is a command line application the best way would be to call sudo whereas if it is a gui application, gksudo is appropriate. For completeness sake though, solutions (or pointers to solutions) for other os's are also welcome.
Also, this is useful so that for GUI apps, I can turn off printf statements.
I'd run gksu(do) if the environment variable DISPLAY is set. It doesn't really matter if the application has a GUI or not, if there's an X-server running, and we can use it, why shouldn't we?
Doesn't allow you to determine if you should disable stdout output. However, stderr output is generally captured in .xsession-errors, even if no terminal is connected, so you might not want to disable that output afterall.
I have to write a program that intercepts data from terminal and i have to parse it. After processing when the data, i have to parse it before it goes to stdout.
I can't use tee or commands like prog > file 2>&1 as the program is going to be interactive.
For example :
If the user types ls in the terminal i have to parse it then it should go operating system and then when I get the result after processing I ll have to again parse it before it's displayed in the terminal.
I did my research and I think I can achieve it through pseudo terminal interfaces ( pty ).
Please let me know if there is a better way to achieve it.
I am using cpp and bash and the platform is *nix.
Update:
I can also use libexpect from expect.
I am not sure what do you mean here - you mean interactive program as "working in another terminal communicating with user" or even displaying GUI?
How does it specify the terminal? It is probably important what is program layout here (which program starts which).
If your application uses GUI to communicate with user, then I would simply do it this way:
start bash with sdtin and stdout attached to pipes,
your program reads & writes to it's end's of those pipes, parses data, and reads/writes on it's own stdin&stdout - so it appears on it's terminal.
If you mean controlling different terminal than your application's, it gets though since system generally does not expect program operating on multiple terminals. I don't think it's possible to filter communication between terminal and already working application attached to it. Starting another process spawning another terminal might be an option - to have basically two terminals working in sync. But then you will have to synchronize both processes by some other means (named pipes, network connection or some other IPC).
If you provide more detail on your program I might provide more directed help.
PS Don't tell me that you are writing some terminal keylogger ')
EDIT:
Your program is probably GUI based then - what i would recommend would be something similar to answer linked by banuj.
Best option will probably be to create three pipes, then fork, and in child process assign corresponding ends of pipes to stdin, stdout and stderr. Then child process should exec into shell - probably bash, although I am not sure if other shells would sound better if read out loud ;) Main process will be able to read/write other ends of mentioned pipes, parsing both inputs and outputs to bash and programs it runs.
You could also exec directly to commands user specifies, but that forces you to take over tedious job of a shell - managing current directory, environment variables, job control and so on.
Using above method might however cause some trouble - some programs (usually in security related contexts - eg. su(do) asking for password) will try to bypass stdin/stdout anyway and read directly from terminal device. I am not sure what can you do in such case - programing your own terminal emulator would be an option, but I don't know if you want to go this deep into system programming for this.
If you want some code snippet's, if you don't know how to do above, just ask ;)
I've got a program called pgm1 which create a new process using fork.
Then in this process, I launch a new program (pgm2) using the following command:
execv( exec_path_name, argv ).
But the thing is that with this method I've got both output in the same terminal.
I've been searching for a while ans the only solution i found was this one:
Open a new terminal with a system call
Attach my pgm2 to the new terminal using this soft http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/comment-page-1/#comment-27264
So my question is really simple, is there a more simple way to do that ?
Thanks in advance !
PS: Distro - Ubuntu 11.10 32bit
I can think of two possible solutions:
Do The Right Thing(TM) and send your output to a file: Each process can use a different file, providing both clear separation of the output and better record-keeping. As a bonus, you are also bound to see a performance improvement - terminal output is computationally expensive, even nowadays...
Execute a terminal emulator with the proper arguments: Most terminal emulators provide a way to execute a specific program in place of the shell. For example xterm:
$ xterm top
This will launch top in an xterm instance, without a shell. Quiting top also terminates the xterm window.
If your terminal emulator of choice supports this, you can use it simply by modifying the arguments passed to execv(). Of course, in this case you will be actually executing the terminal emulator instead of your program, which will then call your own process.
Keep in mind that, depending on the terminal emulator, any open file descriptors may not be passed correctly to your program - the terminal will at least mangle the standard file descriptors.
I need to run a linux command such as "df" from my linux daemon to know free space,used space, total size of the parition and other info. I have options like calling system,exec,popen etc..
But as this each command spawn a new process , is this not possible to run the commands in the same process from which it is invoked?
And at the same time as I need to run this command from a linux daemon, as my daemon should not hold any terminal. Will it effect my daemon behavior?
Or is their any C or C++ standard API for getting the mounted paritions information
There is no standard API, as this is an OS-specific concept.
However,
You can parse /proc/mounts (or /etc/mtab) with (non-portable) getmntent/getmntent_r helper functions.
Using information about mounted filesystems, you can get its statistics with statfs.
You may find it useful to explore the i3status program source code: http://code.stapelberg.de/git/i3status/tree/src/print_disk_info.c
To answer your other questions:
But as this each command spawn a new process , is this not possible to run the commands in the same process from which it is invoked?
No; entire 'commands' are self-contained programs that must run in their own process.
Depending upon how often you wish to execute your programs, fork();exec() is not so bad. There's no hard limits beyond which it would be better to gather data yourself vs executing a helper program. Once a minute, you're probably fine executing the commands. Once a second, you're probably better off gathering the data yourself. I'm not sure where the dividing line is.
And at the same time as I need to run this command from a linux daemon, as my daemon should not hold any terminal. Will it effect my daemon behavior?
If the command calls setsid(2), then open(2) on a terminal without including O_NOCTTY, that terminal might become the controlling terminal for that process. But that wouldn't influence your program, because your program already disowned the terminal when becoming a daemon, and as the child process is a session leader, it cannot change your process's controlling terminal.