infra: Clean up project setup
[jog] / err.c
CommitLineData
2ec1e693 1/* -*-c-*-
2 *
e9060e7e 3 * $Id: err.c,v 1.2 2002/02/02 19:16:46 mdw Exp $
2ec1e693 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
2ec1e693 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
e9060e7e 45#include "auerr.h"
2ec1e693 46#include "err.h"
47
48/*----- Static variables --------------------------------------------------*/
49
50static FILE *logfp = 0;
51static 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
68void 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);
e9060e7e 73 auerr_abort(reason, err);
2ec1e693 74 abort();
75}
76
77void 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
96static 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
109void 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
136void 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;
e9060e7e 146 auerr(ctx, reason, err);
2ec1e693 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
166void 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
184void err_logv(const char *msg, va_list *ap)
185{
186 err_reportv(0, 0, 0, msg, ap);
187}
188
189void 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 -------------------------------------------------*/