I'll append a version that i deem to be better, since it ensures
the message is written as a unity even in multithreaded+ programs.
It's not in OpenBSD style, though.
Yep, it seems there is a possibility to improve the codebase even
more, not only under the visual surface.
Ciao from horsy horse,

--steffen

--- /dev/null   2014-01-16 12:45:53.000000000 +0100
+++ err.h       2014-01-16 12:14:10.000000000 +0100
@@ -0,0 +1,39 @@
+
+#ifndef        _ERR_H
+#define        _ERR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#ifndef _Noreturn
+# define __ERR_H_DEFINED_NORETURN
+# define _Noreturn
+#endif
+
+/* Program exit and warning calls */
+_Noreturn void err(int, const char *, ...);
+_Noreturn void verr(int, const char *, va_list);
+_Noreturn void errc(int, int, const char *, ...);
+_Noreturn void verrc(int, int, const char *, va_list);
+_Noreturn void errx(int, const char *, ...);
+_Noreturn void verrx(int, const char *, va_list);
+
+void           warn(const char *, ...);
+void           vwarn(const char *, va_list);
+void           warnc(int, const char *, ...);
+void           vwarnc(int, const char *, va_list);
+void           warnx(const char *, ...);
+void           vwarnx(const char *, va_list);
+
+#ifdef __ERR_H_DEFINED_NORETURN
+# undef _Noreturn
+# undef __ERR_H_DEFINED_NORETURN
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ERR_H */
--- /dev/null   2014-01-16 12:45:57.000000000 +0100
+++ err.c       2014-01-16 12:44:52.000000000 +0100
@@ -0,0 +1,174 @@
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+/* Thread-safe locked with multiple I/Os, or a single output?
+ * Is used as the stack buffer size if defined */
+/*#define __PREPARE_STACK_BUFFER       1024*/
+
+/* Get the program name as a const char* */
+#define __PROGRAM_NAME()       getprogname()
+
+/* The shared workhorse */
+static void    _errwarn(FILE *fp, int doerr, int code, const char *fmt,
+                       va_list args);
+
+static void
+_errwarn(FILE *fp, int doerr, int code, const char *fmt, va_list args)
+{
+#ifdef __PREPARE_STACK_BUFFER
+       char buffer[__PREPARE_STACK_BUFFER];
+       size_t len;
+       int i;
+
+       i = snprintf(buffer, sizeof buffer, "%s: ", __PROGRAM_NAME());
+       if (i < 0)
+               goto jleave;
+       len = i;
+       if (len >= sizeof buffer)
+               goto jprint;
+
+       if (fmt != NULL) {
+               i = vsnprintf(buffer + len, sizeof(buffer) - len, fmt, args);
+               if (i < 0)
+                       goto jleave;
+               len += i;
+               if (len >= sizeof buffer)
+                       goto jprint;
+       }
+
+       if (doerr) {
+               i = snprintf(buffer + len, sizeof(buffer) - len, ": %s",
+                       strerror(code));
+               if (i < 0)
+                       goto jleave;
+               len += i;
+       }
+jprint:
+       if (len >= sizeof(buffer) - 1)
+               len = sizeof(buffer) - 2;
+       buffer[len++] = '\n';
+       buffer[len] = '\0';
+       fputs(buffer, fp);
+       fflush(fp);
+jleave:
+       ;
+
+#else /* __PREPARE_STACK_BUFFER */
+       flockfile(fp);
+       fprintf(fp, "%s: ", __PROGRAM_NAME());
+       if (fmt != NULL)
+               vfprintf(fp, fmt, args);
+       if (doerr)
+               fprintf(fp, ": %s", strerror(code));
+       fputc('\n', fp);
+       fflush(fp);
+       funlockfile(fp);
+#endif
+}
+
+void
+err(int status, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 1, errno, fmt, args);
+       va_end(args);
+       exit(status);
+}
+
+void
+verr(int status, const char *fmt, va_list args)
+{
+       _errwarn(stderr, 1, errno, fmt, args);
+       exit(status);
+}
+
+void
+errc(int status, int code, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 1, code, fmt, args);
+       va_end(args);
+       exit(status);
+}
+
+void
+verrc(int status, int code, const char *fmt, va_list args)
+{
+       _errwarn(stderr, 1, code, fmt, args);
+       exit(status);
+}
+
+void
+errx(int status, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 0, 0, fmt, args);
+       va_end(args);
+       exit(status);
+}
+
+void
+verrx(int status, const char *fmt, va_list args)
+{
+       _errwarn(stderr, 0, 0, fmt, args);
+       exit(status);
+}
+
+void
+warn(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 1, errno, fmt, args);
+       va_end(args);
+}
+
+void
+vwarn(const char *fmt, va_list args)
+{
+       _errwarn(stderr, 1, errno, fmt, args);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 1, code, fmt, args);
+       va_end(args);
+}
+
+void
+vwarnc(int code, const char *fmt, va_list args)
+{
+       _errwarn(stderr, 1, code, fmt, args);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _errwarn(stderr, 0, 0, fmt, args);
+       va_end(args);
+}
+
+void
+vwarnx(const char *fmt, va_list args)
+{
+       _errwarn(stderr, 0, 0, fmt, args);
+}

Reply via email to