Initial revision
[mmh] / sbr / error.c
1
2 /*
3  * error.c -- main error handling routines
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9
10 #ifdef HAVE_WRITEV
11 # include <sys/types.h>
12 # include <sys/uio.h>
13 #endif
14
15 extern int errno;
16
17
18 /*
19  * print out error message
20  */
21 void
22 advise (char *what, char *fmt, ...)
23 {
24     va_list ap;
25
26     va_start(ap, fmt);
27     advertise (what, NULL, fmt, ap);
28     va_end(ap);
29 }
30
31
32 /*
33  * print out error message and exit
34  */
35 void
36 adios (char *what, char *fmt, ...)
37 {
38     va_list ap;
39
40     va_start(ap, fmt);
41     advertise (what, NULL, fmt, ap);
42     va_end(ap);
43     done (1);
44 }
45
46
47 /*
48  * admonish the user
49  */
50 void
51 admonish (char *what, char *fmt, ...)
52 {
53     va_list ap;
54
55     va_start(ap, fmt);
56     advertise (what, "continuing...", fmt, ap);
57     va_end(ap);
58 }
59
60
61 /*
62  * main routine for printing error messages.
63  *
64  * Use writev() if available, for slightly better performance.
65  * Why?  Well, there are a couple of reasons.  Primarily, it
66  * gives a smoother output...  More importantly though, it's a
67  * sexy syscall()...
68  */
69 void
70 advertise (char *what, char *tail, char *fmt, va_list ap)
71 {
72     int eindex = errno;
73
74 #ifdef HAVE_WRITEV
75     char buffer[BUFSIZ], err[BUFSIZ];
76     struct iovec iob[20], *iov;
77 #endif
78
79     fflush (stdout);
80
81 #ifdef HAVE_WRITEV
82     fflush (stderr);
83     iov = iob;
84
85     if (invo_name && *invo_name) {
86         iov->iov_len = strlen (iov->iov_base = invo_name);
87         iov++;
88         iov->iov_len = strlen (iov->iov_base = ": ");
89         iov++;
90     }
91     
92     vsnprintf (buffer, sizeof(buffer), fmt, ap);
93     iov->iov_len = strlen (iov->iov_base = buffer);
94     iov++;
95     if (what) {
96         if (*what) {
97             iov->iov_len = strlen (iov->iov_base = " ");
98             iov++;
99             iov->iov_len = strlen (iov->iov_base = what);
100             iov++;
101             iov->iov_len = strlen (iov->iov_base = ": ");
102             iov++;
103         }
104         if (!(iov->iov_base = strerror (eindex))) {
105             /* this shouldn't happen, but we'll test for it just in case */
106             snprintf (err, sizeof(err), "Error %d", eindex);
107             iov->iov_base = err;
108         }
109         iov->iov_len = strlen (iov->iov_base);
110         iov++;
111     }
112     if (tail && *tail) {
113         iov->iov_len = strlen (iov->iov_base = ", ");
114         iov++;
115         iov->iov_len = strlen (iov->iov_base = tail);
116         iov++;
117     }
118     iov->iov_len = strlen (iov->iov_base = "\n");
119     iov++;
120     writev (fileno (stderr), iob, iov - iob);
121 #else
122     if (invo_name && *invo_name)
123         fprintf (stderr, "%s: ", invo_name);
124     vfprintf (stderr, fmt, ap);
125
126     if (what) {
127         char *s;
128
129         if (*what)
130             fprintf (stderr, " %s: ", what);
131         if ((s = strerror(eindex)))
132             fprintf (stderr, "%s", s);
133         else
134             fprintf (stderr, "Error %d", eindex);
135     }
136     if (tail)
137         fprintf (stderr, ", %s", tail);
138     fputc ('\n', stderr);
139 #endif
140 }