chiark / gitweb /
infra: Clean up project setup
[jog] / err.c
1 /* -*-c-*-
2  *
3  * $Id: err.c,v 1.2 2002/02/02 19:16:46 mdw Exp $
4  *
5  * Error reporting
6  *
7  * (c) 2001 Mark Wooding
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Jog: Programming for a jogging machine.
13  *
14  * Jog is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * Jog is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with Jog; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Header files ------------------------------------------------------*/
30
31 #ifdef HAVE_CONFIG_H
32 #  include "config.h"
33 #endif
34
35 #include <errno.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41
42 #include <mLib/exc.h>
43 #include <mLib/quis.h>
44
45 #include "auerr.h"
46 #include "err.h"
47
48 /*----- Static variables --------------------------------------------------*/
49
50 static FILE *logfp = 0;
51 static unsigned flags = 0;
52
53 #define f_thread 1u
54
55 /*----- Main code ---------------------------------------------------------*/
56
57 /* --- @err_abort@ --- *
58  *
59  * Arguments:   @int reason@ = abort reason code
60  *              @unsigned long err@ = abort error code
61  *              @const char *msg@ = error message
62  *
63  * Returns:     Doesn't.
64  *
65  * Use:         Reports a fatal error.
66  */
67
68 void err_abortv(int reason, unsigned long err, const char *msg, va_list *ap)
69 {
70   fprintf(stderr, "%s: fatal error (code %d-%lu): ", QUIS, reason, err);
71   vfprintf(stderr, msg, *ap);
72   putc('\n', stderr);
73   auerr_abort(reason, err);
74   abort();
75 }
76
77 void err_abort(int reason, unsigned long err, const char *msg, ...)
78 {
79   va_list ap;
80
81   va_start(ap, msg);
82   err_abortv(reason, err, msg, &ap);
83   va_end(ap);
84 }
85
86 /* --- @err_init@ --- *
87  *
88  * Arguments:   ---
89  *
90  * Returns:     ---
91  *
92  * Use:         Attempts to initialize the logging system.  It is a
93  *              catastrophic failure if logging can't start up.
94  */
95
96 static void err_exc(exc_extype ex, exc_exval v)
97 {
98   switch (ex) {
99     case EXC_NOMEM:
100       err_report(ERR_EXC, 0, ex, "out of memory");
101       break;
102     default:
103       err_report(ERR_EXC, 0, ex, "uncaught mLib exception");
104       break;
105   }
106   exit(EXIT_FAILURE);
107 }
108
109 void err_init(void)
110 {
111   const char *lf;
112
113   lf = getenv("JOG_LOGFILE");
114   if (!lf)
115     logfp = stderr;
116   else if ((logfp = fopen(lf, "w")) == 0) {
117     err_abort(ERRABORT_LOGOPEN, errno,
118               "couldn't open logfile `%s': %s", lf, strerror(errno));
119   }
120   exc_uncaught(err_exc);
121 }
122
123 /* --- @err_report@ --- *
124  *
125  * Arguments:   @int ctx@ = context code
126  *              @int reason@ = reason code
127  *              @unsigned long err@ = system error code
128  *              @const char *msg@ = textual message to log
129  *
130  * Returns:     ---
131  *
132  * Use:         Reports an error.  Doesn't abort anything unless something
133  *              really serious happens.
134  */
135
136 void err_reportv(int ctx, int reason, unsigned long err,
137                  const char *msg, va_list *ap)
138 {
139   char buf[256];
140   time_t t;
141   struct tm *tm;
142
143   if (ctx && !(flags & f_thread)) {
144     unsigned f = flags;
145     flags |= f_thread;
146     auerr(ctx, reason, err);
147     flags = f;
148   }
149   t = time(0);
150   tm = localtime(&t);
151   strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
152   if (fputs(buf, logfp) == EOF ||
153       fprintf(stderr, " %s: ", QUIS) == EOF ||
154       vfprintf(logfp, msg, *ap) == EOF ||
155       (ctx && (fprintf(logfp, " (error %d", ctx) == EOF ||
156                (reason && fprintf(logfp, "-%d", reason) == EOF) ||
157                (err && fprintf(logfp, ":%lu", err) == EOF) ||
158                putc(')', logfp) == EOF)) ||
159       putc('\n', logfp) == EOF ||
160       fflush(logfp) == EOF) {
161     err_abort(ERRABORT_LOGWRITE, errno,
162               "error writing logfile: %s", strerror(errno));
163   }
164 }
165
166 void err_report(int ctx, int reason, unsigned long err, const char *msg, ...)
167 {
168   va_list ap;
169
170   va_start(ap, msg);
171   err_reportv(ctx, reason, err, msg, &ap);
172   va_end(ap);
173 }
174
175 /* --- @err_log@ --- *
176  *
177  * Arguments:    @const char *msg@ = textual message to log
178  *
179  * Returns:     ---
180  *
181  * Use:         Logs a message.
182  */
183
184 void err_logv(const char *msg, va_list *ap)
185 {
186   err_reportv(0, 0, 0, msg, ap);
187 }
188
189 void err_log(const char *msg, ...)
190 {
191   va_list ap;
192
193   va_start(ap, msg);
194   err_reportv(0, 0, 0, msg, &ap);
195   va_end(ap);
196 }
197
198 /*----- That's all, folks -------------------------------------------------*/