1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* 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 <stdio.h>
#include <stdarg.h>
#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(int quit, int e, char *fmt, ...)
{
va_list l;
va_start(l,fmt);
if (e < 0)
e = errno;
verror(quit, (char *)NULL, fmt, l, e);
va_end(l);
}
/*
* Panic (print to stderr and abort).
*/
void
panic(char *fmt, ...)
{
va_list l;
SetErrorTrap((void (*)())NULL); /* shut down any trap */
va_start(l,fmt);
verror(0, "panic: ", fmt, l, 0);
va_end(l);
abort();
}
#endif /* lint */
|