-
-/*
- * error.c -- main error handling routines
+/* error.c -- main error handling routines
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
#include <sys/uio.h>
+/* inform calls advertise() with no what and no tail.
+ * Thus the simple "[invo_name: ]fmt\n" results. */
+void inform(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ advertise(NULL, NULL, fmt, ap);
+ va_end(ap);
+}
+
+
/* advise calls advertise() with no tail to print fmt, and perhaps what,
- * to stderr. */
+ * to stderr.
+ * Thus "[invo_name: ]fmt[[ what]: errno]\n" results. */
void
advise (const char *what, const char *fmt, ...)
{
}
-/* adios calls advertise() with no tail to print fmt, and perhaps what,
- * to stderr, and "ends" the program with an error exit status. The
- * route to exit is via the done function pointer and may not be
- * straightforward.
- * FIXME: Document if this function can ever return. If not, perhaps an
- * abort(3) at the end of the routine would make that more clear. */
+/* adios is the same as advise(), but then "ends" the program.
+ * It calls advertise() with no tail to print fmt, and perhaps what, to
+ * stderr, and exits the program with an error status.
+ * Thus "[invo_name: ]fmt[[ what]: errno]\n" results.
+ * The route to exit is via the done function pointer and may not be
+ * straightforward, e.g. longjmp(3), but it must not return to adios().
+ * If it does then it's a bug and adios() will abort(3) as callers do
+ * not expect execution to continue. */
void
adios (const char *what, const char *fmt, ...)
{
advertise (what, NULL, fmt, ap);
va_end(ap);
done (1);
+ abort();
}
/* admonish calls advertise() with a tail indicating the program
- * continues. */
+ * continues.
+ * Thus "[invo_name: ]fmt[[ what]: errno], continuing...\n" results. */
void
admonish (char *what, char *fmt, ...)
{
/* advertise prints fmt and ap to stderr after flushing stdout.
- * If invo_name isn't NULL or empty, it precedes the output seperated by ": ".
- * If what isn't NULL, errno as a string is appended.
- * A non-empty what separates fmt from errno, surrounded by " " and ": ".
- * BUG: No space separator before errno if what is "".
- * If tail isn't NULL or empty then ", " and tail are appended
- * before the finishing "\n".
- * In summary: "invo_name: fmt what: errno, tail\n". */
+ * If invo_name isn't NULL or empty then "invo_name: " precedes fmt.
+ * If what isn't NULL or empty then " what" is appended.
+ * If what isn't NULL then ": errno" is appended.
+ * If tail isn't NULL or empty then ", tail" is appended.
+ * A "\n" finishes the output to stderr.
+ * In summary: "[invo_name: ]fmt[[ what]: errno][, tail]\n". */
void
advertise (const char *what, char *tail, const char *fmt, va_list ap)
{
int eindex = errno;
- char buffer[BUFSIZ], errbuf[BUFSIZ], *err;
- struct iovec iob[20], *iov;
+ char buffer[NMH_BUFSIZ], *err;
+ struct iovec iob[10], *iov;
+ size_t niov;
iov = iob;
if (*what) {
ADD_LITERAL(" ");
ADD_VAR((void *)what);
- ADD_LITERAL(": ");
}
+ ADD_LITERAL(": ");
err = strerror(eindex);
- if (!err) {
- /* this shouldn't happen, but we'll test for it just in case */
- snprintf(errbuf, sizeof(errbuf), "Error %d", eindex);
- err = errbuf;
- }
ADD_VAR(err);
}
if (tail && *tail) {
#undef ADD_LITERAL
#undef ADD_VAR
+ niov = iov - iob;
+ assert(niov <= DIM(iob));
+
fflush (stdout);
fflush (stderr);
- if (writev (fileno (stderr), iob, iov - iob) < 0) {
+ if (writev(fileno(stderr), iob, niov) == -1) {
snprintf(buffer, sizeof buffer, "%s: write stderr failed: %d\n",
invo_name && *invo_name ? invo_name : "nmh", errno);
if (write(2, buffer, strlen(buffer)) == -1) {