--- err.c.orig 2006-12-15 11:18:17.000000000 -0800 +++ err.c 2006-12-15 11:46:52.000000000 -0800 @@ -44,12 +44,85 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <vis.h> #include "un-namespace.h" #include "libc_private.h" -static FILE *err_file; /* file to use for error output */ -static void (*err_exit)(int); +#ifdef BUILDING_VARIANT + +__private_extern__ FILE *_e_err_file; /* file to use for error output */ +__private_extern__ void (*_e_err_exit)(int); +__private_extern__ void _e_visprintf(FILE * __restrict, const char * __restrict, va_list); + +#else /* !BUILDING_VARIANT */ + +__private_extern__ FILE *_e_err_file = NULL; /* file to use for error output */ +__private_extern__ void (*_e_err_exit)(int) = NULL; + +/* + * zero means pass as is + * 255 means use \nnn (octal) + * otherwise use \x (x is value) + * (NUL isn't used) + */ +static unsigned char escape[256] = { + /* NUL SOH STX ETX EOT ENQ ACK BEL */ + 0 , 255, 255, 255, 255, 255, 255, 'a', + /* BS HT NL VT NP CR SO SI */ + 'b', 't', 'n', 'v', 'f', 'r', 255, 255, + /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + 255, 255, 255, 255, 255, 255, 255, 255, + /* CAN EM SUB ESC FS GS RS US */ + 255, 255, 255, 255, 255, 255, 255, 255, + /* the rest are zero */ +}; + +/* + * Make characters visible. If we can't allocate enough + * memory, we fall back on vfprintf(). + */ +__private_extern__ void +_e_visprintf(FILE * __restrict stream, const char * __restrict format, va_list ap) +{ + int failed = 0; + char *str, *visstr; + va_list backup; + + va_copy(backup, ap); + vasprintf(&str, format, ap); + if (str != NULL) { + if ((visstr = malloc(4 * strlen(str) + 1)) != NULL) { + unsigned char *fp = (unsigned char *)str; + unsigned char *tp = (unsigned char *)visstr; + while(*fp) { + switch(escape[*fp]) { + case 0: + *tp++ = *fp; + break; + case 255: + sprintf(tp, "\\%03o", *fp); + tp += 4; + break; + default: + *tp++ = '\\'; + *tp++ = escape[*fp]; + break; + } + fp++; + } + *tp = 0; + fputs(visstr, stream); + free(visstr); + } else + failed = 1; + free(str); + } else + failed = 1; + if (failed) + vfprintf(stream, format, backup); + va_end(backup); +} /* * This is declared to take a `void *' so that the caller is not required @@ -60,16 +133,17 @@ err_set_file(void *fp) { if (fp) - err_file = fp; + _e_err_file = fp; else - err_file = stderr; + _e_err_file = stderr; } void err_set_exit(void (*ef)(int)) { - err_exit = ef; + _e_err_exit = ef; } +#endif /* !BUILDING_VARIANT */ __weak_reference(_err, err); @@ -107,16 +181,16 @@ const char *fmt; va_list ap; { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, ": "); } - fprintf(err_file, "%s\n", strerror(code)); - if (err_exit) - err_exit(eval); + fprintf(_e_err_file, "%s\n", strerror(code)); + if (_e_err_exit) + _e_err_exit(eval); exit(eval); } @@ -135,14 +209,14 @@ const char *fmt; va_list ap; { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) - vfprintf(err_file, fmt, ap); - fprintf(err_file, "\n"); - if (err_exit) - err_exit(eval); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, "\n"); + if (_e_err_exit) + _e_err_exit(eval); exit(eval); } @@ -180,14 +254,14 @@ const char *fmt; va_list ap; { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, ": "); } - fprintf(err_file, "%s\n", strerror(code)); + fprintf(_e_err_file, "%s\n", strerror(code)); } void @@ -204,10 +278,10 @@ const char *fmt; va_list ap; { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) - vfprintf(err_file, fmt, ap); - fprintf(err_file, "\n"); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, "\n"); }