From 5add556a1cb64b49a664506aa76216d885b22c97 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 8 Jun 2012 20:49:32 +0930 Subject: [PATCH] err: actually implement replacement versions! This is where you see the genius of the originals: you can't implement them without horrible hacks to get the program name :( --- ccan/err/_info | 4 +++ ccan/err/err.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ ccan/err/err.h | 18 +++++++++++++ ccan/err/test/run.c | 22 +++++++++++++--- 4 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 ccan/err/err.c diff --git a/ccan/err/_info b/ccan/err/_info index 5a5752bb..97bc0f9e 100644 --- a/ccan/err/_info +++ b/ccan/err/_info @@ -8,11 +8,15 @@ * A few platforms don't provide err.h; for those, this provides replacements. * For most, it simple includes the system err.h. * + * Unfortunately, you have to call err_set_progname() to tell the replacements + * your program name, otherwise it prints "unknown program". + * * Example: * #include * * int main(int argc, char *argv[]) * { + * err_set_progname(argv[0]); * if (argc != 1) * errx(1, "Expect no arguments"); * exit(0); diff --git a/ccan/err/err.c b/ccan/err/err.c new file mode 100644 index 00000000..9e0e20c8 --- /dev/null +++ b/ccan/err/err.c @@ -0,0 +1,64 @@ +#include "err.h" + +#if !HAVE_ERR_H +#include +#include +#include +#include +#include + +static const char *progname = "unknown program"; + +void err_set_progname(const char *name) +{ + progname = name; +} + +void NORETURN err(int eval, const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); + exit(eval); +} + +void NORETURN errx(int eval, const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(eval); +} + +void warn(const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); +} + +void warnx(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} +#endif diff --git a/ccan/err/err.h b/ccan/err/err.h index da9ea0c5..58ad91c7 100644 --- a/ccan/err/err.h +++ b/ccan/err/err.h @@ -4,9 +4,27 @@ #if HAVE_ERR_H #include + +/* This is unnecessary with a real err.h. See below */ +#define err_set_progname(name) ((void)name) + #else #include +/** + * err_set_progname - set the program name + * @name: the name to use for err, errx, warn and warnx + * + * The BSD err.h calls know the program name, unfortunately there's no + * portable way for the CCAN replacements to do that on other systems. + * + * If you don't call this with argv[0], it will be "unknown program". + * + * Example: + * err_set_progname(argv[0]); + */ +void err_set_progname(const char *name); + /** * err - exit(eval) with message based on format and errno. * @eval: the exit code diff --git a/ccan/err/test/run.c b/ccan/err/test/run.c index c0407a93..242e93f8 100644 --- a/ccan/err/test/run.c +++ b/ccan/err/test/run.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -10,15 +10,25 @@ #define BUFFER_MAX 1024 -int main(void) +int main(int argc, char *argv[]) { int pfd[2]; + const char *base; - plan_tests(20); - fflush(stdout); + plan_tests(24); + + err_set_progname(argv[0]); + + /* In case it only prints out the basename of argv[0]. */ + base = strrchr(argv[0], '/'); + if (base) + base++; + else + base = argv[0]; /* Test err() in child */ pipe(pfd); + fflush(stdout); if (fork()) { char buffer[BUFFER_MAX+1]; unsigned int i; @@ -31,6 +41,7 @@ int main(void) buffer[i] = '\0'; ok1(strstr(buffer, "running err:")); ok1(strstr(buffer, strerror(ENOENT))); + ok1(strstr(buffer, base)); ok1(buffer[i-1] == '\n'); break; } @@ -61,6 +72,7 @@ int main(void) if (read(pfd[0], buffer + i, 1) == 0) { buffer[i] = '\0'; ok1(strstr(buffer, "running errx\n")); + ok1(strstr(buffer, base)); break; } } @@ -91,6 +103,7 @@ int main(void) buffer[i] = '\0'; ok1(strstr(buffer, "running warn:")); ok1(strstr(buffer, strerror(ENOENT))); + ok1(strstr(buffer, base)); ok1(buffer[i-1] == '\n'); break; } @@ -121,6 +134,7 @@ int main(void) if (read(pfd[0], buffer + i, 1) == 0) { buffer[i] = '\0'; ok1(strstr(buffer, "running warnx\n")); + ok1(strstr(buffer, base)); break; } } -- 2.39.2