]> diplodocus.org Git - nmh/blob - sbr/error.c
mhbuildsbr.c: Flip logic, moving goto to then-block; no need for else.
[nmh] / sbr / error.c
1 /* error.c -- main error handling routines
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h>
9
10 #include <sys/types.h>
11 #include <sys/uio.h>
12
13
14 /* inform calls advertise() with no what and no tail.
15 * Thus the simple "[invo_name: ]fmt\n" results. */
16 void inform(char *fmt, ...)
17 {
18 va_list ap;
19
20 va_start(ap, fmt);
21 advertise(NULL, NULL, fmt, ap);
22 va_end(ap);
23 }
24
25
26 /* advise calls advertise() with no tail to print fmt, and perhaps what,
27 * to stderr.
28 * Thus "[invo_name: ]fmt[[ what]: errno]\n" results. */
29 void
30 advise (const char *what, const char *fmt, ...)
31 {
32 va_list ap;
33
34 va_start(ap, fmt);
35 advertise (what, NULL, fmt, ap);
36 va_end(ap);
37 }
38
39
40 /* adios is the same as advise(), but then "ends" the program.
41 * It calls advertise() with no tail to print fmt, and perhaps what, to
42 * stderr, and exits the program with an error status.
43 * Thus "[invo_name: ]fmt[[ what]: errno]\n" results.
44 * The route to exit is via the done function pointer and may not be
45 * straightforward, e.g. longjmp(3), but it must not return to adios().
46 * If it does then it's a bug and adios() will abort(3) as callers do
47 * not expect execution to continue. */
48 void NORETURN
49 adios (const char *what, const char *fmt, ...)
50 {
51 va_list ap;
52
53 va_start(ap, fmt);
54 advertise (what, NULL, fmt, ap);
55 va_end(ap);
56 done (1);
57 abort();
58 }
59
60
61 /* admonish calls advertise() with a tail indicating the program
62 * continues.
63 * Thus "[invo_name: ]fmt[[ what]: errno], continuing...\n" results. */
64 void
65 admonish (char *what, char *fmt, ...)
66 {
67 va_list ap;
68
69 va_start(ap, fmt);
70 advertise (what, "continuing...", fmt, ap);
71 va_end(ap);
72 }
73
74
75 /* advertise prints fmt and ap to stderr after flushing stdout.
76 * If invo_name isn't NULL or empty then "invo_name: " precedes fmt.
77 * If what isn't NULL or empty then " what" is appended.
78 * If what isn't NULL then ": errno" is appended.
79 * If tail isn't NULL or empty then ", tail" is appended.
80 * A "\n" finishes the output to stderr.
81 * In summary: "[invo_name: ]fmt[[ what]: errno][, tail]\n". */
82 void
83 advertise (const char *what, char *tail, const char *fmt, va_list ap)
84 {
85 int eindex = errno;
86 char buffer[NMH_BUFSIZ], *err;
87 struct iovec iob[10], *iov;
88 size_t niov;
89
90 iov = iob;
91
92 #define APPEND_IOV(p, len) \
93 iov->iov_base = (p); \
94 iov->iov_len = (len); \
95 iov++
96
97 #define ADD_LITERAL(s) APPEND_IOV((s), LEN(s))
98 #define ADD_VAR(s) APPEND_IOV((s), strlen(s))
99
100 if (invo_name && *invo_name) {
101 ADD_VAR(invo_name);
102 ADD_LITERAL(": ");
103 }
104
105 vsnprintf (buffer, sizeof(buffer), fmt, ap);
106 ADD_VAR(buffer);
107 if (what) {
108 if (*what) {
109 ADD_LITERAL(" ");
110 ADD_VAR((void *)what);
111 }
112 ADD_LITERAL(": ");
113 err = strerror(eindex);
114 ADD_VAR(err);
115 }
116 if (tail && *tail) {
117 ADD_LITERAL(", ");
118 ADD_VAR(tail);
119 }
120 ADD_LITERAL("\n");
121
122 #undef ADD_LITERAL
123 #undef ADD_VAR
124
125 niov = iov - iob;
126 assert(niov <= DIM(iob));
127
128 fflush (stdout);
129 fflush (stderr);
130 if (writev(fileno(stderr), iob, niov) == -1) {
131 snprintf(buffer, sizeof buffer, "%s: write stderr failed: %d\n",
132 invo_name && *invo_name ? invo_name : "nmh", errno);
133 if (write(2, buffer, strlen(buffer)) == -1) {
134 /* Ignore. if-statement needed to shut up compiler. */
135 }
136 }
137 }