14

I know the program name is passed as the first argument, and next simple example will print it to the standard output :

#include <iostream>
int main ( int argc, char *argv[] )
{
  std::cout<<argv[0]<<std::endl;
}

Is there a function to get the program name?

EDIT

I am starting the program from the shell, and the above code will always print the program name (I am using fedora 9, but I am sure it works in other distros).

I have found that /proc/self/ directory might contain what I am looking for, but I couldn't find what exactly in that directory.

MSalters
  • 173,980
  • 10
  • 155
  • 350
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • What do you mean ? Your main function already gets program name – mt_serg Oct 27 '10 at 09:28
  • 1
    What do you mean? You just said that you know the "program name" is passed as the first argument...so what else do you need? – Kricket Oct 27 '10 at 09:29
  • 3
    @mt_serg, @Kelsey Rider Well the question is pretty simple if you read the question carefully, It says "argv[0] is used for finding the program name, but Is there another function to get the program name?". No Offense : ) – Searock Oct 27 '10 at 09:33
  • 1
    @Searock Yes, you understood the question. – BЈовић Oct 27 '10 at 09:38
  • 2
    @Searock there is no offence, just misunderstanding. peace :-) – mt_serg Oct 27 '10 at 09:42
  • 2
    possible duplicate of [how to find the location of the executable in C](http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c) – Jens Gustedt Oct 27 '10 at 10:05
  • 3
    The question makes a lot of sense from a library viewpoint. – MSalters Oct 27 '10 at 11:33
  • On linux you can also try `prctl`. E.g. `char procname[256]; (prctl(PR_GET_NAME, &procname, 0, 0, 0);`. Watch-out though if your threads take on different names. – Darren Smith Nov 18 '12 at 04:25

6 Answers6

22

No, there is no such function. Linux stores the program name in __progname, but that's not a public interface. In case you want to use this for warnings/error messages, use the err(3) functions.

If you want the full path of the running program, call readlink on /proc/self/exe:

char *program_path()
{
    char *path = malloc(PATH_MAX);
    if (path != NULL) {
        if (readlink("/proc/self/exe", path, PATH_MAX) == -1) {
            free(path);
            path = NULL;
        }
    }
    return path;
}

(I believe __progname is set to the basename of argv[0]. Check out the glibc sources to be sure.)

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 1
    With readlink it works fine. Thank you. I also tried __progname, but it didn't compile. Not sure what I have to include to make it work. – BЈовић Oct 27 '10 at 10:15
  • 3
    You shouldn't use `__progname`, since it's undocumented and for internal use by the `err(3)` functions only. (If you want to cheat, declare it with `extern const char *__progname;` But really, you don't want to cheat.) – Fred Foo Oct 27 '10 at 10:22
  • `/proc/self/cmdline` should give the complete set of arguments separated with space passed to that program. – Arunprasad Rajkumar Nov 13 '14 at 11:24
13

GLIBC-specific solution:

#include <errno.h>
...
fprintf(stderr, "Program name is %s\n", program_invocation_name);

From man invocation_name:

program_invocation_name contains the name that was used to invoke the calling program. This is the same as the value of argv[0] in main(), with the difference that the scope of program_invocation_name is global.

program_invocation_short_name contains the basename component of name that was used to invoke the calling program. That is, it is the same value as program_invocation_name, with all text up to and including the final slash (/), if any, removed.

Community
  • 1
  • 1
Sauron
  • 404
  • 3
  • 14
  • 5
    In my environment, there was no `man invocation_name`. Instead, I had to refer to [`man program_invocation_name`](http://man7.org/linux/man-pages/man3/program_invocation_name.3.html). – ynn Feb 19 '20 at 02:01
9

This is not guaranteed.

Usually, argv[0] holds the executable name but one can call your executable using execve and set it to something else.

In a word: don't rely on this.

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • Moreover, at least on Windows, `argv[0]` may hold the full path as well as just the executable name w\ or w\o the extension. – Matteo Italia Oct 27 '10 at 09:30
  • 2
    argv[0] is always the name of the program I think. – Chubsdad Oct 27 '10 at 09:30
  • 3
    @Chubsdad: ereOn just pointed out when this might not be true. So no, it is not always the name of the program. – unwind Oct 27 '10 at 09:43
  • 3
    @Chubsdad: If you know write your own answer. If you only think then go look it up or wait for somebody that does know to answer. Currently you are wrong (and the foolish sheep who followed you with up-voting your comment). – Martin York Oct 27 '10 at 09:55
  • 3
    It's much worse than that. On Linux with bash, this parameter is user-faced : bash -c 'exec -a"The beautiful program name that is in argv[0]" ./executable' – BatchyX Oct 27 '10 at 10:09
6

No, it depends entirely on what the parent program puts in there.

The exec family of functions allow the executable name to be totally different to the argument passed in, and this is supported by the ISO C standard.

If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment.

So no, it's only the program name if the name is available. And the section before that states:

If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.

(my italics).

So, even their values are not dictated by the standard, it's up to the implementation entirely. This means that the program name can be empty if the host environment doesn't provide it, and anything else if the host environment does provide it.

However, implementation-defined has a specific meaning in the ISO standards - the implementation must document how it works. So even UNIX, which can put anything it likes into argv[0] with the exec family of calls, has to (and does) document it.

Similarly (thanks to Chubsdad), C++03 states:

"If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs) (17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "".

So, even there, argv[0] may not contain anything and, even if it does, "represents the name" is a very vague requirement. It doesn't have to be the full pathname of the executable or even contain the command used to invoke it


Another way to do it under Linux is with the proc filesystem. I think /proc/self/exe is a link to the executable file.

Wikipedia has an entry for the procfs filesystem with lots of goodies.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    The C++ standard (03) states - "If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs) (17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "". – Chubsdad Oct 27 '10 at 09:38
  • So, is the behavior possibly different for C and C++? – Chubsdad Oct 27 '10 at 09:40
  • 1
    I don't think so, @Chubsdad: that seems little different to the C standard. `argv[0]` can represent the program name or be empty. Notice also the weasel words "represent the name" - this in no way has to be the full path of the executable or even a partial match. Maybe I'm cynical but the string `"A delay program"` would be perfectly representative of `/bin/sleep` :-) – paxdiablo Oct 27 '10 at 09:42
  • @Chubsdad: I believe that's 100% equivalent to what pax quoted. –  Oct 27 '10 at 09:44
  • 'represents the name' is specifying the property of the NTMBS string. I think it means that the sequence of bytes would correspond to the program name. So 'sleep' or '/bin/sleep' probably is fine but not 'A cute little delay program' :) – Chubsdad Oct 27 '10 at 09:48
  • /proc/self/exe I have seen that it links to the executable, but how can I transform that to the string? – BЈовић Oct 27 '10 at 09:54
  • That's one interpretation :-) You're probably right but, unfortunately, it still doesn't get around thet `or ""` bit. I know there's a way to do it in Windows as well but I think the `/proc/self/exe` is probably safest for Linux. I'm not sure if that softlink stays valid if someone deletes the executable but I would suspect so, you just wouldn't be able to follow it, but you should still be able to `readlink` it. – paxdiablo Oct 27 '10 at 09:56
  • 1
    a softlink is allowed to point to a deleted file. In fact it's allowed to point to anything. They are plenty of those in /proc/*/fd/ that points to "[socket:1984]" or "[pipe:6116]" which doesn't exist at all in the filesystem. – BatchyX Oct 27 '10 at 10:12
3

You can determine the pid of your process using getpid() and then inspect the contents of /proc/[pid number] using standard I/O tools.

Eugene Smith
  • 9,126
  • 6
  • 36
  • 40
2

If you use GLib you can use the function g_get_prgname(). On Win32 it calls GetModuleFileNameW(), on everything else it appears to return NULL though.

Steve-o
  • 12,678
  • 2
  • 41
  • 60