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