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); +}