chiark / gitweb /
Initial revision
[jog] / err.c
1 /* -*-c-*-
2  *
3  * $Id: err.c,v 1.1 2002/01/25 19:34:45 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 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: err.c,v $
32  * Revision 1.1  2002/01/25 19:34:45  mdw
33  * Initial revision
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include <errno.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
49
50 #include <mLib/exc.h>
51 #include <mLib/quis.h>
52
53 /* #include "au.h" */
54 #include "err.h"
55
56 /*----- Static variables --------------------------------------------------*/
57
58 static FILE *logfp = 0;
59 static unsigned flags = 0;
60
61 #define f_thread 1u
62
63 /*----- Main code ---------------------------------------------------------*/
64
65 /* --- @err_abort@ --- *
66  *
67  * Arguments:   @int reason@ = abort reason code
68  *              @unsigned long err@ = abort error code
69  *              @const char *msg@ = error message
70  *
71  * Returns:     Doesn't.
72  *
73  * Use:         Reports a fatal error.
74  */
75
76 void err_abortv(int reason, unsigned long err, const char *msg, va_list *ap)
77 {
78   fprintf(stderr, "%s: fatal error (code %d-%lu): ", QUIS, reason, err);
79   vfprintf(stderr, msg, *ap);
80   putc('\n', stderr);
81   /* au_abort(reason, err); */
82   abort();
83 }
84
85 void err_abort(int reason, unsigned long err, const char *msg, ...)
86 {
87   va_list ap;
88
89   va_start(ap, msg);
90   err_abortv(reason, err, msg, &ap);
91   va_end(ap);
92 }
93
94 /* --- @err_init@ --- *
95  *
96  * Arguments:   ---
97  *
98  * Returns:     ---
99  *
100  * Use:         Attempts to initialize the logging system.  It is a
101  *              catastrophic failure if logging can't start up.
102  */
103
104 static void err_exc(exc_extype ex, exc_exval v)
105 {
106   switch (ex) {
107     case EXC_NOMEM:
108       err_report(ERR_EXC, 0, ex, "out of memory");
109       break;
110     default:
111       err_report(ERR_EXC, 0, ex, "uncaught mLib exception");
112       break;
113   }
114   exit(EXIT_FAILURE);
115 }
116
117 void err_init(void)
118 {
119   const char *lf;
120
121   lf = getenv("JOG_LOGFILE");
122   if (!lf)
123     logfp = stderr;
124   else if ((logfp = fopen(lf, "w")) == 0) {
125     err_abort(ERRABORT_LOGOPEN, errno,
126               "couldn't open logfile `%s': %s", lf, strerror(errno));
127   }
128   exc_uncaught(err_exc);
129 }
130
131 /* --- @err_report@ --- *
132  *
133  * Arguments:   @int ctx@ = context code
134  *              @int reason@ = reason code
135  *              @unsigned long err@ = system error code
136  *              @const char *msg@ = textual message to log
137  *
138  * Returns:     ---
139  *
140  * Use:         Reports an error.  Doesn't abort anything unless something
141  *              really serious happens.
142  */
143
144 void err_reportv(int ctx, int reason, unsigned long err,
145                  const char *msg, va_list *ap)
146 {
147   char buf[256];
148   time_t t;
149   struct tm *tm;
150
151   if (ctx && !(flags & f_thread)) {
152     unsigned f = flags;
153     flags |= f_thread;
154 /*     au_misc(AU_ERROR, ctx, reason, err); */
155     flags = f;
156   }
157   t = time(0);
158   tm = localtime(&t);
159   strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
160   if (fputs(buf, logfp) == EOF ||
161       fprintf(stderr, " %s: ", QUIS) == EOF ||
162       vfprintf(logfp, msg, *ap) == EOF ||
163       (ctx && (fprintf(logfp, " (error %d", ctx) == EOF ||
164                (reason && fprintf(logfp, "-%d", reason) == EOF) ||
165                (err && fprintf(logfp, ":%lu", err) == EOF) ||
166                putc(')', logfp) == EOF)) ||
167       putc('\n', logfp) == EOF ||
168       fflush(logfp) == EOF) {
169     err_abort(ERRABORT_LOGWRITE, errno,
170               "error writing logfile: %s", strerror(errno));
171   }
172 }
173
174 void err_report(int ctx, int reason, unsigned long err, const char *msg, ...)
175 {
176   va_list ap;
177
178   va_start(ap, msg);
179   err_reportv(ctx, reason, err, msg, &ap);
180   va_end(ap);
181 }
182
183 /* --- @err_log@ --- *
184  *
185  * Arguments:    @const char *msg@ = textual message to log
186  *
187  * Returns:     ---
188  *
189  * Use:         Logs a message.
190  */
191
192 void err_logv(const char *msg, va_list *ap)
193 {
194   err_reportv(0, 0, 0, msg, ap);
195 }
196
197 void err_log(const char *msg, ...)
198 {
199   va_list ap;
200
201   va_start(ap, msg);
202   err_reportv(0, 0, 0, msg, &ap);
203   va_end(ap);
204 }
205
206 /*----- That's all, folks -------------------------------------------------*/