Without access to argv[0], how do I get the program name?

对着背影说爱祢 提交于 2021-02-06 10:12:37

问题


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.


回答1:


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.)




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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




回答6:


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.



来源:https://stackoverflow.com/questions/4031672/without-access-to-argv0-how-do-i-get-the-program-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!