/* * Copyright (c) 1987, 1989 University of Maryland * Department of Computer Science. All rights reserved. * Permission to copy for any purpose is hereby granted * so long as this copyright notice remains intact. */ #ifndef lint static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/error.c,v 2.8 89/08/22 21:49:12 chris Exp $"; #endif /* * Print an error message with an optional system error number, and * optionally quit. * * THIS CODE IS SYSTEM DEPENDENT UNLESS varargs WORKS WITH vprintf * OR _doprnt. It should work properly under System V using vprintf. * (If you have vprintf, define HAVE_VPRINTF in ../h/types.h.) */ #include "types.h" /* for HAVE_VPRINTF */ #include "error.h" #include #include #if defined(lint) && !defined(LINT_ANYWAY) /* ARGSUSED */ void SetErrorTrap(fn) void (*fn)(); {;} /* VARARGS3 ARGSUSED */ void error(quit, e, fmt) int quit, e; char *fmt; {;} /* VARARGS1 ARGSUSED */ void panic(fmt) char *fmt; { exit(1); /* NOTREACHED */ } #else lint extern char *ProgName; /* program name from argv[0] */ extern int errno; /* Unix system-call error */ extern char *sys_errlist[]; /* table of error number => string */ extern int sys_nerr; /* size of table */ static FILE *trap_file; /* error diversion file, if any */ static void (*trap_fn)(); /* trap function */ static char *trap_buf; /* buffer for trapped error strings */ static int trap_size; /* size of trap_buf */ extern char *malloc(), *realloc(); /* * Enable error trapping: register the function fn as the trapper. * If fn is NULL, stop trapping. */ void SetErrorTrap(fn) void (*fn)(); { int tempfd; char fname[BUFSIZ]; /* shut down any existing error trap */ if (trap_file) { (void) fclose(trap_file); trap_file = NULL; } if ((trap_fn = fn) == NULL) return; /* begin trapping */ if ((tempfd = MakeRWTempFile(fname)) < 0) error(1, -1, "cannot create temporary file %s", fname); if (trap_size == 0) { trap_buf = malloc((unsigned)(trap_size = 1000)); if (trap_buf == 0) error(1, -1, "cannot get space for error buffer"); } if ((trap_file = fdopen(tempfd, "r+")) == NULL) error(1, -1, "cannot get stdio file for error trap"); } /* * Read a trapped error into trap_buf. * Return a pointer to the (NUL-terminated) text. * If something goes wrong, return something else printable. */ static char * readback() { int nbytes = ftell(trap_file) + 1; if (nbytes > trap_size) { if (trap_buf == NULL) trap_buf = malloc((unsigned)nbytes); else trap_buf = realloc(trap_buf, (unsigned)nbytes); if (trap_buf == NULL) { trap_size = 0; return ("Ouch! Lost error text: out of memory?"); } } rewind(trap_file); /* now can read */ nbytes = fread(trap_buf, 1, nbytes, trap_file); if (nbytes < 0) return ("Ouch! Trouble reading error text!"); trap_buf[nbytes] = 0; return (trap_buf); } /* * Print an error message to the error output (either stderr, or * if trapping errors, to the error trap file). We precede this * with the program's name and an optional string (a0), then use * the format and variable argument list, then append an optional * Unix error string. Finally, if errors are being trapped, we * pass the error text and the quit flag to the trap function. * * In the interest of `look and feel', if errors are being trapped, * the program name is omitted. */ static void verror(quit, a0, fmt, l, e) char *a0, *fmt; va_list l; int e; { register FILE *fp = trap_file; /* print to the trap file, if any, else stderr */ if ((fp = trap_file) != NULL) rewind(fp); /* now can write */ else { fp = stderr; (void) fflush(fp); } if (trap_file == NULL) (void) fprintf(fp, "%s: ", ProgName); if (a0) (void) fprintf(fp, "%s", a0); #ifdef HAVE_VPRINTF (void) vfprintf(fp, fmt, l); #else (void) _doprnt(fmt, l, fp); #endif if (e) { if (e < sys_nerr) (void) fprintf(fp, ": %s", sys_errlist[e]); else (void) fprintf(fp, ": Unknown error code %d", e); } (void) putc('\n', fp); (void) fflush(fp); if (trap_file != NULL) (*trap_fn)(quit, readback()); if (quit) exit(quit); } /* * Print an error message and optionally quit. */ void error(va_alist) va_dcl { va_list l; int quit, e; char *fmt; va_start(l); quit = va_arg(l, int); if ((e = va_arg(l, int)) < 0) e = errno; fmt = va_arg(l, char *); verror(quit, (char *)NULL, fmt, l, e); va_end(l); } /* * Panic (print to stderr and abort). */ void panic(va_alist) va_dcl { va_list l; char *fmt; SetErrorTrap((void (*)())NULL); /* shut down any trap */ va_start(l); fmt = va_arg(l, char *); verror(0, "panic: ", fmt, l, 0); va_end(l); abort(); } #endif /* lint */