Commit 5add556a authored by Rusty Russell's avatar Rusty Russell

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 :(
parent 9f5e1ef7
......@@ -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 <ccan/err/err.h>
*
* int main(int argc, char *argv[])
* {
* err_set_progname(argv[0]);
* if (argc != 1)
* errx(1, "Expect no arguments");
* exit(0);
......
#include "err.h"
#if !HAVE_ERR_H
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
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
......@@ -4,9 +4,27 @@
#if HAVE_ERR_H
#include <err.h>
/* This is unnecessary with a real err.h. See below */
#define err_set_progname(name) ((void)name)
#else
#include <ccan/compiler/compiler.h>
/**
* 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
......
#include <ccan/err/err.h>
#include <ccan/err/err.c>
#include <ccan/tap/tap.h>
#include <unistd.h>
#include <string.h>
......@@ -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;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment