[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
determining the program_invocation_name
From: |
Bruno Haible |
Subject: |
determining the program_invocation_name |
Date: |
Fri, 24 Dec 2010 22:41:40 +0100 |
User-agent: |
KMail/1.9.9 |
Hi,
How can some library code determine the name of the running program,
for error message and display purposes, if the program's main() function
has not stored argv[0] in a particular place?
Let's be clear about two things:
1) This question is mostly irrelevant for libposix, because library
functions in libposix should not call exit() and should not print
error messages. The only ways out that a library function has is
to call abort() if there was a programming error, and to return
an error code or error message that the caller can then handle.
2) Even if we find an answer to this question, it does not magically
resolve all problems with the 'error' module, because the question
remains where the 'program_name' variable shall be allocated,
and it is a portability problem for MacOS X, AIX, Solaris, Cygwin [1].
There was this thread [2] in 2006 where we found out that we needed some
new API [3] because we did not want to implement the BSD functions with
different semantics.
Recently, Bastien Roucariès respawned the topic in two threads [4][5],
by proposing to fetch the program invocation name (= argv[0] or a
variant of it) through the API that 'ps' and 'top' typically use.
Find attached a collection of the platform dependent code snippets.
I added code for Cygwin, mingw (from progreloc.c), and OSF/1, and
tested it on the various platforms.
The results of this investigation are:
1) There are six different notions of "program name".
- get_program_invocation_short_name ()
This is what glibc calls 'program_invocation_short_name' and
BSD calls 'getprogname ()'. It's the basename of the argv[0].
- get_program_invocation_short_name_truncated ()
This is like get_program_invocation_short_name (), except it
is truncated to a certain number of bytes (14, 16, or 32).
- get_program_invocation_name ()
This is what glibc calls 'program_invocation_name'. It's the
argv[0] before the search in $PATH was performed.
- get_program_absolute_name ()
This is like get_program_invocation_name(), except that it
makes the result absolute by stuffing in the current directory
if needed.
- get_resolved_program_invocation_name ()
This is like get_program_invocation_name(), except that it
resolves symbolic links and removes trivial filename components.
- get_program_canonicalized_name ()
This is like a combination of get_program_absolute_name() and
get_resolved_program_invocation_name(): It resolves symbolic
links, removes trivial filename components, and stuffs in the
current directory.
2) Each of the functions may fail, i.e. return NULL.
3) It's highly platform dependent. Here's the matrix of available functions:
A = get_program_invocation_short_name ()
A x = get_program_invocation_short_name_truncated ()
B = get_program_invocation_name ()
C = get_program_absolute_name ()
D = get_resolved_program_invocation_name ()
E = get_program_canonicalized_name ()
| A | B | C | D | E |
---------------+---+---+---+---+---+
glibc/Linux | X | X | | | X |
glibc/other | X | X | | | |
uClibc/Linux | | | | | X |
MacOS X | X | | X | | |
FreeBSD | X | | | | |
NetBSD | X | | | | |
OpenBSD | X | | | | |
AIX | x | X | | | |
HP-UX | x | | | | |
IRIX | x | | | | |
OSF/1 | x | | | | |
Solaris | X | | | X | |
Cygwin | X | | | | X |
mingw | | | | | X |
Interix | | | | | |
---------------+---+---+---+---+---+
Given B, you can determine C, D, E, by assuming the current directory
and $PATH have not changed since the program was launched.
But given A only, one cannot determine B, C, D, E. And unfortunately,
on many Unix platforms, A is the only thing you can get.
What can we reasonably do with this?
(a) We could create a new module that exports functions
/* Returns the base name of argv[0], if known. */
const char *get_program_invocation_short_name ();
/* Returns the truncated base name of argv[0], if known. */
const char *get_program_invocation_short_name_truncated ();
size_t get_program_invocation_short_name_truncation_length ();
/* Return argv[0], without resolving symlinks or current directory
if possible. */
const char *get_program_invocation_name ();
/* Return argv[0] as a canonical filename. Assumes that the current
directory and $PATH have not changed since the program was launched. */
const char *get_program_canonicalized_name ();
Of course these functions would cache their respective result once it has
been determined.
And of course there are platforms, like Interix, NonStop Kernel, or Haiku,
where all functions will return NULL.
(b) We can observe that these proposed functions would still have
portability pitfalls:
- truncation of the short name,
- differences regarding relative filenames and symlinks,
- differences regarding the ".exe" suffix on Windows.
Decide that it is better to have no gnulib API at all than an API that
has portability problems.
What do you think?
Bruno
[1] http://lists.gnu.org/archive/html/bug-recutils/2010-12/msg00010.html
[2] http://lists.gnu.org/archive/html/bug-gnulib/2006-01/msg00005.html
[3] http://lists.gnu.org/archive/html/bug-gnulib/2006-01/msg00122.html
[4] http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00088.html
[5] http://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00064.html
get-program-name.c
Description: Text Data
- determining the program_invocation_name,
Bruno Haible <=