On Tue, Feb 28, 2023 at 1:13 AM Benjamin Li <benl@xxxxxxxxxxxx> wrote: > > Platforms like Bionic libc don't have program_invocation_[short_]name, > which is a GNU extension. It does have getprogname(), a BSD extension, > but rather than supporting multiple extensions let's just introduce > our own local helpers. > > We derive the short name ourselves rather than calling basename(), > as the POSIX version takes char *, not const char *, and is thus > not guaranteed to avoid modifying its input. (The GNU version does > take const char * but we are avoiding extensions here.) > > Signed-off-by: Benjamin Li <benl@xxxxxxxxxxxx> > --- > tools/gpiodetect.c | 5 +++-- > tools/gpioget.c | 5 +++-- > tools/gpioinfo.c | 5 +++-- > tools/gpiomon.c | 5 +++-- > tools/gpionotify.c | 5 +++-- > tools/gpioset.c | 5 +++-- > tools/tools-common.c | 34 ++++++++++++++++++++++++++-------- > tools/tools-common.h | 4 +++- > 8 files changed, 47 insertions(+), 21 deletions(-) > > diff --git a/tools/gpiodetect.c b/tools/gpiodetect.c > index f0211da..eb8d273 100644 > --- a/tools/gpiodetect.c > +++ b/tools/gpiodetect.c > @@ -12,7 +12,7 @@ > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] [chip]...\n", get_progname()); > + printf("Usage: %s [OPTIONS] [chip]...\n", get_prog_short_name()); > printf("\n"); > printf("List GPIO chips, print their labels and number of GPIO lines.\n"); > printf("\n"); > @@ -51,7 +51,7 @@ static int parse_config(int argc, char **argv) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); This changes the semantics though - previously it would have returned the long name. I think it's better for the help output to return the full path. It's also consistent with what most command-line program seem to do. Same elsewhere. Bart > default: > abort(); > } > @@ -89,6 +89,7 @@ int main(int argc, char **argv) > int num_chips, i, ret = EXIT_SUCCESS; > char **paths, *path; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv); > argc -= i; > argv += i; > diff --git a/tools/gpioget.c b/tools/gpioget.c > index 08c17e6..c8238cf 100644 > --- a/tools/gpioget.c > +++ b/tools/gpioget.c > @@ -26,7 +26,7 @@ struct config { > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] <line>...\n", get_progname()); > + printf("Usage: %s [OPTIONS] <line>...\n", get_prog_short_name()); > printf("\n"); > printf("Read values of GPIO lines.\n"); > printf("\n"); > @@ -120,7 +120,7 @@ static int parse_config(int argc, char **argv, struct config *cfg) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); > case 0: > break; > default: > @@ -146,6 +146,7 @@ int main(int argc, char **argv) > struct config cfg; > const char *fmt; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv, &cfg); > argc -= i; > argv += i; > diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c > index 1ec7f63..ce2df63 100644 > --- a/tools/gpioinfo.c > +++ b/tools/gpioinfo.c > @@ -20,7 +20,7 @@ struct config { > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] [line]...\n", get_progname()); > + printf("Usage: %s [OPTIONS] [line]...\n", get_prog_short_name()); > printf("\n"); > printf("Print information about GPIO lines.\n"); > printf("\n"); > @@ -83,7 +83,7 @@ static int parse_config(int argc, char **argv, struct config *cfg) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); > case 0: > break; > default: > @@ -228,6 +228,7 @@ int main(int argc, char **argv) > struct config cfg; > char **paths; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv, &cfg); > argc -= i; > argv += i; > diff --git a/tools/gpiomon.c b/tools/gpiomon.c > index 93ff463..893b966 100644 > --- a/tools/gpiomon.c > +++ b/tools/gpiomon.c > @@ -34,7 +34,7 @@ struct config { > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] <line>...\n", get_progname()); > + printf("Usage: %s [OPTIONS] <line>...\n", get_prog_short_name()); > printf("\n"); > printf("Wait for events on GPIO lines and print them to standard output.\n"); > printf("\n"); > @@ -195,7 +195,7 @@ static int parse_config(int argc, char **argv, struct config *cfg) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); > case 0: > break; > default: > @@ -360,6 +360,7 @@ int main(int argc, char **argv) > struct config cfg; > int ret, i, j; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv, &cfg); > argc -= i; > argv += i; > diff --git a/tools/gpionotify.c b/tools/gpionotify.c > index a0976f7..e19d88c 100644 > --- a/tools/gpionotify.c > +++ b/tools/gpionotify.c > @@ -27,7 +27,7 @@ struct config { > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] <line>...\n", get_progname()); > + printf("Usage: %s [OPTIONS] <line>...\n", get_prog_short_name()); > printf("\n"); > printf("Wait for changes to info on GPIO lines and print them to standard output.\n"); > printf("\n"); > @@ -144,7 +144,7 @@ static int parse_config(int argc, char **argv, struct config *cfg) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); > case 0: > break; > default: > @@ -370,6 +370,7 @@ int main(int argc, char **argv) > struct pollfd *pollfds; > struct config cfg; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv, &cfg); > argc -= optind; > argv += optind; > diff --git a/tools/gpioset.c b/tools/gpioset.c > index a7084a3..cc9106c 100644 > --- a/tools/gpioset.c > +++ b/tools/gpioset.c > @@ -36,7 +36,7 @@ struct config { > > static void print_help(void) > { > - printf("Usage: %s [OPTIONS] <line=value>...\n", get_progname()); > + printf("Usage: %s [OPTIONS] <line=value>...\n", get_prog_short_name()); > printf("\n"); > printf("Set values of GPIO lines.\n"); > printf("\n"); > @@ -212,7 +212,7 @@ static int parse_config(int argc, char **argv, struct config *cfg) > print_version(); > exit(EXIT_SUCCESS); > case '?': > - die("try %s --help", get_progname()); > + die("try %s --help", get_prog_short_name()); > case 0: > break; > default: > @@ -876,6 +876,7 @@ int main(int argc, char **argv) > struct config cfg; > char **lines; > > + set_prog_name(argv[0]); > i = parse_config(argc, argv, &cfg); > argc -= i; > argv += i; > diff --git a/tools/tools-common.c b/tools/tools-common.c > index a0080fc..e5f6fc1 100644 > --- a/tools/tools-common.c > +++ b/tools/tools-common.c > @@ -19,9 +19,28 @@ > > #include "tools-common.h" > > -const char *get_progname(void) > +static const char *prog_name = NULL; > +static const char *prog_short_name = NULL; > + > +void set_prog_name(const char *name) > +{ > + prog_name = name; > + prog_short_name = name; > + while (*name) { > + if (*name++ == '/') { > + prog_short_name = name; > + } > + } > +} > + > +const char *get_prog_name(void) > +{ > + return prog_name; > +} > + > +const char *get_prog_short_name(void) > { > - return program_invocation_name; > + return prog_short_name; > } > > void print_error(const char *fmt, ...) > @@ -29,7 +48,7 @@ void print_error(const char *fmt, ...) > va_list va; > > va_start(va, fmt); > - fprintf(stderr, "%s: ", program_invocation_name); > + fprintf(stderr, "%s: ", get_prog_name()); > vfprintf(stderr, fmt, va); > fprintf(stderr, "\n"); > va_end(va); > @@ -40,7 +59,7 @@ void print_perror(const char *fmt, ...) > va_list va; > > va_start(va, fmt); > - fprintf(stderr, "%s: ", program_invocation_name); > + fprintf(stderr, "%s: ", get_prog_name()); > vfprintf(stderr, fmt, va); > fprintf(stderr, ": %s\n", strerror(errno)); > va_end(va); > @@ -51,7 +70,7 @@ void die(const char *fmt, ...) > va_list va; > > va_start(va, fmt); > - fprintf(stderr, "%s: ", program_invocation_name); > + fprintf(stderr, "%s: ", get_prog_name()); > vfprintf(stderr, fmt, va); > fprintf(stderr, "\n"); > va_end(va); > @@ -64,7 +83,7 @@ void die_perror(const char *fmt, ...) > va_list va; > > va_start(va, fmt); > - fprintf(stderr, "%s: ", program_invocation_name); > + fprintf(stderr, "%s: ", get_prog_name()); > vfprintf(stderr, fmt, va); > fprintf(stderr, ": %s\n", strerror(errno)); > va_end(va); > @@ -74,8 +93,7 @@ void die_perror(const char *fmt, ...) > > void print_version(void) > { > - printf("%s (libgpiod) v%s\n", > - program_invocation_short_name, gpiod_api_version()); > + printf("%s (libgpiod) v%s\n", get_prog_short_name(), gpiod_api_version()); > printf("Copyright (C) 2017-2023 Bartosz Golaszewski\n"); > printf("License: GPL-2.0-or-later\n"); > printf("This is free software: you are free to change and redistribute it.\n"); > diff --git a/tools/tools-common.h b/tools/tools-common.h > index 434e5ba..c82317a 100644 > --- a/tools/tools-common.h > +++ b/tools/tools-common.h > @@ -78,7 +78,9 @@ struct line_resolver { > struct resolved_line lines[]; > }; > > -const char *get_progname(void); > +void set_prog_name(const char *name); > +const char *get_prog_name(void); > +const char *get_prog_short_name(void); > void print_error(const char *fmt, ...) PRINTF(1, 2); > void print_perror(const char *fmt, ...) PRINTF(1, 2); > void die(const char *fmt, ...) NORETURN PRINTF(1, 2); > -- > 2.25.1 >