tags:

views:

190

answers:

6

Hi,

I have a simple C/CPP process running on a linux system. This is a.out.

Another process is capable to start a.out inside its code. This is b.out.

What code do I need inside a.out to understand that it is executed from the command line? Eg ./a.out

Is there a way a process to know if it started from the cmd or started from another process?

+2  A: 

You can check its parent task ID, using getppid()

Kedar Soparkar
-1: there's no such system call. If you mean `getppid`, that alone is not very helpful.
larsmans
+6  A: 

You can't find out in general whether a program was started "from the command line" (by a user's explicit command), but you can find out whether its standard input and output are talking to a terminal/command window:

#include <unistd.h>
isatty(fileno(stdin))

and stdout return whether standard input/standard output are terminals.

If you need to know what process starting your program, use the getppid system call to get the parent's process ID (ppid), then read the pseudo-file /proc/ppid/cmdline.

larsmans
If you use isatty, you'll get false for redirection at the command line. As a user, I'd be upset by a command I can't use in pipes...
AProgrammer
The correct answer depends critically on what the OP wants to do. I just listed some options. (Maybe it should only behave *differently* for terminals, e.g. give a prompt?)
larsmans
All the implementations of `ls` I've used try putting filenames into columns when called from the terminal, but have one file per line when piping output.
David Thornley
A: 

You can check whether its standard input is a terminal:

if(isatty(0)) { ... }
mouviciel
Keep in mind you'd only benefit from this if a.out gets its stdin redirected, otherwise it'll just inherit the stdin of b.out, which is a tty.
nos
+2  A: 

You can do multiple things, but none will be 100% reliable:

  • isatty(0) to check whether standard input is a TTY terminal,

  • check for the parent task ID (getppid()), then lookup the parent's PID to match it against its executable's path (using whatever you want. a call to ps and some parsing could do, or have fun using /proc/)

  • you could also just have a look at the environment variables set up. do a printout of all the values contained in the env. To do that, either use the extern environ variable:

    extern char **environ;

  • or modify your main() prototype to be:

    int main(int ac, char **av, char **environ)

haylem
`getenv` is the preferred way to read the environment. How does the environment help?
larsmans
yes, you could do that as well, but `getenv` requires you to know which key you want to read. So that could be usefull, or you may want to go through the whole thing. For the rest, sorry if I wasn't being clear enough: you could look for the differences on some particular variables (SHELL, DISPLAY...). There'll be minor differences between different kinds of execution as well. I am actually on windows right now so I cannot really try this out but I did something like that a while back. But like I said, it's not 100% reliable. Definitely not.
haylem
@larsmans: actually, come to think of it, what I was doing back then was trying to determine if my program was being executed through an SSH connection or not, but that's how I did (unreliably) determine it.
haylem
A: 

In short: you can't doing it directly.
In long: look you can check the getppid() value and compare it with the bash PID orb.out PID
TO search for a process inside the process table with Known PID with C you can do this:

1) get the PPID of a.out and search with this value in /porc and then if you find the folder check the cmdline file and check if this process is b.out or shell process.

2) you can deal with sysctl system call and dealing with kernel param's(you can google it)

3)
pid_t ppid = getppid();
system("pidof bash > text.in");

the system will get the pid of any shell process and write the result to text.in file
it contains all bash PID's space separated you can compare this values with getppid() value.
Good Luck.

Aboelnour
A: 

I would set an environment variable, in the parent process, to some value (say the parent pid), and have the child process check for it.

It is unlikely that a shell user would set this variable (call it something unlikely to name-clash), so if this variable is set to the expected value, then you know that it is being started from the parent process.

MarkR