]> diplodocus.org Git - nmh/blob - sbr/error.c
Alter mh-chart(7)'s NAME to be lowercase.
[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, e.g. longjmp(3), but it must not return to adios().
33 * If it does then it's a bug and adios() will abort(3) as callers do
34 * not expect execution to continue. */
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 abort();
45 }
46
47
48 /* admonish calls advertise() with a tail indicating the program
49 * continues. */
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 /* advertise prints fmt and ap to stderr after flushing stdout.
62 * If invo_name isn't NULL or empty, it precedes the output seperated by ": ".
63 * If what isn't NULL, errno as a string is appended.
64 * A non-empty what separates fmt from errno, surrounded by " " and ": ".
65 * BUG: No space separator before errno if what is "".
66 * If tail isn't NULL or empty then ", " and tail are appended
67 * before the finishing "\n".
68 * In summary: "invo_name: fmt what: errno, tail\n". */
69 void
70 advertise (const char *what, char *tail, const char *fmt, va_list ap)
71 {
72 int eindex = errno;
73 char buffer[NMH_BUFSIZ], errbuf[NMH_BUFSIZ], *err;
74 struct iovec iob[10], *iov;
75 size_t niov;
76
77 iov = iob;
78
79 #define APPEND_IOV(p, len) \
80 iov->iov_base = (p); \
81 iov->iov_len = (len); \
82 iov++
83
84 #define ADD_LITERAL(s) APPEND_IOV((s), LEN(s))
85 #define ADD_VAR(s) APPEND_IOV((s), strlen(s))
86
87 if (invo_name && *invo_name) {
88 ADD_VAR(invo_name);
89 ADD_LITERAL(": ");
90 }
91
92 vsnprintf (buffer, sizeof(buffer), fmt, ap);
93 ADD_VAR(buffer);
94 if (what) {
95 if (*what) {
96 ADD_LITERAL(" ");
97 ADD_VAR((void *)what);
98 ADD_LITERAL(": ");
99 }
100 err = strerror(eindex);
101 if (!err) {
102 /* this shouldn't happen, but we'll test for it just in case */
103 snprintf(errbuf, sizeof(errbuf), "Error %d", eindex);
104 err = errbuf;
105 }
106 ADD_VAR(err);
107 }
108 if (tail && *tail) {
109 ADD_LITERAL(", ");
110 ADD_VAR(tail);
111 }
112 ADD_LITERAL("\n");
113
114 #undef ADD_LITERAL
115 #undef ADD_VAR
116
117 niov = iov - iob;
118 assert(niov <= DIM(iob));
119
120 fflush (stdout);
121 fflush (stderr);
122 if (writev(fileno(stderr), iob, niov) == -1) {
123 snprintf(buffer, sizeof buffer, "%s: write stderr failed: %d\n",
124 invo_name && *invo_name ? invo_name : "nmh", errno);
125 if (write(2, buffer, strlen(buffer)) == -1) {
126 /* Ignore. if-statement needed to shut up compiler. */
127 }
128 }
129 }