]> diplodocus.org Git - nmh/blob - sbr/error.c
5dc84e87a438ca15b8570fa64fb6a3d4ff208605
[nmh] / sbr / error.c
1
2 /*
3 * error.c -- main error handling routines
4 *
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
8 */
9
10 #include <h/mh.h>
11
12 #include <sys/types.h>
13 #include <sys/uio.h>
14
15
16 /* advise calls advertise() with no tail to print fmt, and perhaps what,
17 * to stderr. */
18 void
19 advise (const char *what, const char *fmt, ...)
20 {
21 va_list ap;
22
23 va_start(ap, fmt);
24 advertise (what, NULL, fmt, ap);
25 va_end(ap);
26 }
27
28
29 /* adios calls advertise() with no tail to print fmt, and perhaps what,
30 * to stderr, and "ends" the program with an error exit status. The
31 * route to exit is via the done function pointer and may not be
32 * straightforward.
33 * FIXME: Document if this function can ever return. If not, perhaps an
34 * abort(3) at the end of the routine would make that more clear. */
35 void
36 adios (const char *what, const 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 /* admonish calls advertise() with a tail indicating the program
48 * continues. */
49 void
50 admonish (char *what, char *fmt, ...)
51 {
52 va_list ap;
53
54 va_start(ap, fmt);
55 advertise (what, "continuing...", fmt, ap);
56 va_end(ap);
57 }
58
59
60 /* advertise prints fmt and ap to stderr after flushing stdout.
61 * If invo_name isn't NULL or empty, it precedes the output seperated by ": ".
62 * If what isn't NULL, errno as a string is appended.
63 * A non-empty what separates fmt from errno, surrounded by " " and ": ".
64 * BUG: No space separator before errno if what is "".
65 * If tail isn't NULL or empty then ", " and tail are appended
66 * before the finishing "\n".
67 * In summary: "invo_name: fmt what: errno, tail\n". */
68 void
69 advertise (const char *what, char *tail, const char *fmt, va_list ap)
70 {
71 int eindex = errno;
72 char buffer[BUFSIZ], errbuf[BUFSIZ], *err;
73 struct iovec iob[20], *iov;
74
75 iov = iob;
76
77 #define APPEND_IOV(p, len) \
78 iov->iov_base = (p); \
79 iov->iov_len = (len); \
80 iov++
81
82 #define ADD_LITERAL(s) APPEND_IOV((s), LEN(s))
83 #define ADD_VAR(s) APPEND_IOV((s), strlen(s))
84
85 if (invo_name && *invo_name) {
86 ADD_VAR(invo_name);
87 ADD_LITERAL(": ");
88 }
89
90 vsnprintf (buffer, sizeof(buffer), fmt, ap);
91 ADD_VAR(buffer);
92 if (what) {
93 if (*what) {
94 ADD_LITERAL(" ");
95 ADD_VAR((void *)what);
96 ADD_LITERAL(": ");
97 }
98 err = strerror(eindex);
99 if (!err) {
100 /* this shouldn't happen, but we'll test for it just in case */
101 snprintf(errbuf, sizeof(errbuf), "Error %d", eindex);
102 err = errbuf;
103 }
104 ADD_VAR(err);
105 }
106 if (tail && *tail) {
107 ADD_LITERAL(", ");
108 ADD_VAR(tail);
109 }
110 ADD_LITERAL("\n");
111
112 #undef ADD_LITERAL
113 #undef ADD_VAR
114
115 fflush (stdout);
116 fflush (stderr);
117 if (writev (fileno (stderr), iob, iov - iob) < 0) {
118 snprintf(buffer, sizeof buffer, "%s: write stderr failed: %d\n",
119 invo_name && *invo_name ? invo_name : "nmh", errno);
120 if (write(2, buffer, strlen(buffer)) == -1) {
121 /* Ignore. if-statement needed to shut up compiler. */
122 }
123 }
124 }