arg0: what is my name?

How does a unix process determine the name with which it was invoked? Why is this important to know?

At present there is no direct way to do this. There is no system call that will reliably tell a process what it's name is.


argv[0] conventions
Symbolic Links
Login Shells
Interpreters
/proc
utssys()
kvm* Functions
fuser/fstat

Notes

argv[0] conventions

By convention, a process' argv[0] is the name it was called as. The exec() family of functions are usually called something like this:

execlp("/bin/ls", "ls", "-l", "/", NULL);
The first argument is the path to the executable, and the second argument becomes argv[0] of the running process. The process that invokes exec() can set this to anything:
execlp("/bin/ls", "wrong", "-l", "/", NULL);
So argv[0] is unreliable. But most of the time it can provide a clue to what the name of the executable might be. argv[0] is almost always the first step.

Try it:
Makefile
argv0wrap.c
argv0.c

Symbolic links

A program name may actually be a symbolic link. So even if the calling process sets argv[0] honestly, it still may not be the actual name of the executable. This is not really a problem until the name is used as a point of reference in a relocatable package.

Login shells

argv[0] for login shells can be prefixed with "-".

Try from a login shell:

$ echo $0
-ksh

Interpreters

Interpreters such as sh, ksh, bash do not necessarily suffer from this problem because they must always know which script they are running. Whether a script is invoked from the command line as in:

$ sh script.sh
or indirectly via shebang, the interpreter always knows exactly which script file it is executing. Getting that information from an interpreter may be another story, though. ksh and bash seem to set $0 to the full path of the script if PATH was used to find the script. Otherwise, $0 is relative to the current working directly. But other interpreters such as Perl may be different.

/proc

Many systems have a pseudo-filesystem called /proc which is used as a convenient way to access process information. Unfortunately, there are problems with /proc that hinder portability:

But even with the above limitations, /proc can sometimes be used to verify the contents of argv[0]. The path named in argv[0] can be compared to the executable named under /proc/pid.

System Pathname Description
Solaris /proc/$$/object/a.out The inode number of a.out appears to match the real inode number in the filesystem. But which filesystem is a question.
FreeBSD /proc/$$/file This is a symbolic link to the real executable.
HP/UX n/a As of 11.11, the /proc filesystem is not supported.
Linux < 2.2 /proc/$$/exe Symlink to file named for device and inode of executable. find -inum must be used to find the actual file. man find(1).
Linux >= 2.2 /proc/$$/exe Symlink to the actual path name of the executed command.
Tru64 /proc/$$ This is a file. It must be opened and then ioctl() calls must be made to get information about the running process. Not sure yet, but it looks like one of the ioctl() calls will return a structure with an element named pr_fname, which the man page describes as "last component of exec'd pathname".

utssys()

Solaris supports the utssys() system call which can return a list of processes which have a particular file open as "text", an executing process. This can be used to verify the contents of argv[0].

See "Number of processes accessing a file".

kvm* Functions

Some systems have family of system calls which can be used to access kernel virtual memory. Functions such as kvm_open() are used with /dev/kmem. These could probably give us the information we want in some system-specific sort of way. Unfortunately, the calling process usually needs to be a member of the kmem or sys group to be allowed to open /dev/kmem. In practice, this is rarely a good idea. However, the kvm functions might be used if the process already happens to have enough privilege to open /dev/kmem.

fuser/fstat

Some systems have fuser or fstat commands which can return which processes hold a file open. Usually some "text" flag is displayed indicating the process is using the file as its text file. This is exactly the information we need. The trouble is, to get this information, we must fork() and exec() to run fuser or fstat. But, if one of these programs is available, it could be used.