BSD progname (getprogname, setprogname): Difference between revisions
(Create page) |
(Add example code) |
||
Line 10: | Line 10: | ||
<code>setprogname</code> has functionality for setting <code>__progname</code>, including using <code>strrchr</code> to get the location of the last occurrence of <code>/</code>. This is to normalize a program run from <code>./blah/bin/hello</code> to just <code>hello</code>, which is actually useful added value that isn't mentioned in the man page. However, unless the source file is modified, this functionality is never used, since a constant defined in the file makes the function a no-op.<ref>http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/setprogname.c?rev=1.3&content-type=text/x-cvsweb-markup&only_with_tag=MAIN</ref>. <code>__progname</code> gets set in <code>crt0</code> using the same rule that the <code>setprogname</code> would have followed, but with a manual search, and with an extra rule that sets <code>__progname</code> to an empty string (pointer to <code>\0</code>) instead of <code>NULL</code> if the program name really is <code>NULL</code>, making the point in the man page about <code>getprogname</code> possibly returning <code>NULL</code> moot.<ref>http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/csu/common/crt0-common.c?rev=1.27&content-type=text/x-cvsweb-markup&only_with_tag=MAIN</ref> |
<code>setprogname</code> has functionality for setting <code>__progname</code>, including using <code>strrchr</code> to get the location of the last occurrence of <code>/</code>. This is to normalize a program run from <code>./blah/bin/hello</code> to just <code>hello</code>, which is actually useful added value that isn't mentioned in the man page. However, unless the source file is modified, this functionality is never used, since a constant defined in the file makes the function a no-op.<ref>http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/setprogname.c?rev=1.3&content-type=text/x-cvsweb-markup&only_with_tag=MAIN</ref>. <code>__progname</code> gets set in <code>crt0</code> using the same rule that the <code>setprogname</code> would have followed, but with a manual search, and with an extra rule that sets <code>__progname</code> to an empty string (pointer to <code>\0</code>) instead of <code>NULL</code> if the program name really is <code>NULL</code>, making the point in the man page about <code>getprogname</code> possibly returning <code>NULL</code> moot.<ref>http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/csu/common/crt0-common.c?rev=1.27&content-type=text/x-cvsweb-markup&only_with_tag=MAIN</ref> |
||
== Quick test == |
|||
Compile this and run it from different paths. |
|||
<syntaxhighlight lang="c"> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("progname is %s\n", getprogname()); |
|||
printf("argv[0] is %s\n", argv[0]); |
|||
return EXIT_SUCCESS; |
|||
} |
|||
</syntaxhighlight> |
|||
== References == |
== References == |
Revision as of 04:39, 23 June 2023
The BSD __progname interface, composed of (getprogname and setprogname), stood out to me while reading the NetBSD source code. Why have functions for argv[0]
? It turns out it does a little more.
Initial thoughts
The man page says the functions appeared in NetBSD 1.6 and seems to suggest that they store argv[0]
verbatim, even if it is NULL
, and that setprogname
is useless because crt0
calls it during C runtime initialization and because the program name is a write-once value.[1] The functions then found their way into FreeBSD 4.4.[2]. Unlike NetBSD and FreeBSD, OpenBSD states that the functions originated as a wrapper for the 4.4BSD __progname
interface, first appearing in OpenBSD 5.4.[3]
How NetBSD does it
getprogname
simply returns __progname
.[4]
setprogname
has functionality for setting __progname
, including using strrchr
to get the location of the last occurrence of /
. This is to normalize a program run from ./blah/bin/hello
to just hello
, which is actually useful added value that isn't mentioned in the man page. However, unless the source file is modified, this functionality is never used, since a constant defined in the file makes the function a no-op.[5]. __progname
gets set in crt0
using the same rule that the setprogname
would have followed, but with a manual search, and with an extra rule that sets __progname
to an empty string (pointer to \0
) instead of NULL
if the program name really is NULL
, making the point in the man page about getprogname
possibly returning NULL
moot.[6]
Quick test
Compile this and run it from different paths.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("progname is %s\n", getprogname());
printf("argv[0] is %s\n", argv[0]);
return EXIT_SUCCESS;
}
References
- ↑ https://man.netbsd.org/NetBSD-9.3-STABLE/getprogname.3
- ↑ https://man.freebsd.org/cgi/man.cgi?query=getprogname&apropos=0&sektion=3&manpath=FreeBSD+13.2-RELEASE+and+Ports&arch=default&format=html
- ↑ https://man.openbsd.org/OpenBSD-7.3/getprogname.3
- ↑ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/getprogname.c?rev=1.5&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
- ↑ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/setprogname.c?rev=1.3&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
- ↑ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/csu/common/crt0-common.c?rev=1.27&content-type=text/x-cvsweb-markup&only_with_tag=MAIN