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