Browse Source

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 :(
Rusty Russell 13 years ago
parent
commit
5add556a1c
4 changed files with 104 additions and 4 deletions
  1. 4 0
      ccan/err/_info
  2. 64 0
      ccan/err/err.c
  3. 18 0
      ccan/err/err.h
  4. 18 4
      ccan/err/test/run.c

+ 4 - 0
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 <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);

+ 64 - 0
ccan/err/err.c

@@ -0,0 +1,64 @@
+#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

+ 18 - 0
ccan/err/err.h

@@ -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

+ 18 - 4
ccan/err/test/run.c

@@ -1,4 +1,4 @@
-#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;
 			}
 		}