I wrote: |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.
Heaven! I'd be willing in adjusting this to OpenBSD style shall there be any interest in the below! Thanks and ciao, Date: Thu, 16 Jan 2014 16:56:11 +0100 From: Steffen (Daode) Nurpmeso <sdao...@gmail.com> To: bugs@openbsd.org Cc: Theo de Raadt <dera...@cvs.openbsd.org>, Philip Guenther <pguent...@proofpoint.com>, Ted Unangst <t...@tedunangst.com> Subject: Re: err.h / err(3): add missing errc(3)/verrc(3)/warnc(3)/vwarnc(3) family Message-ID: <20140116155611.7wqkXKtuCH64XbxL/MJ/Vpm6@dietcurd.local> References: <201401141627.s0egrffq028...@cvs.openbsd.org> <alpine.BSO.2.11.1401140916520.30037@morgaine.local> In-Reply-To: <alpine.BSO.2.11.1401140916520.30037@morgaine.local> User-Agent: s-nail v14.5.1-92-g05ec88f MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Status: RO 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); +}