BSD 4_4 release
[unix-history] / usr / src / usr.sbin / amd / amd / xutil.c
CommitLineData
903b00b4 1/*
903b00b4
JSP
2 * Copyright (c) 1990 Jan-Simon Pendry
3 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
ad787160
C
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
903b00b4
JSP
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
ad787160
C
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
903b00b4 25 *
ad787160
C
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)xutil.c 8.1 (Berkeley) 6/6/93
8d2991d5 39 *
00737562 40 * $Id: xutil.c,v 5.2.2.3 1992/03/07 10:36:09 jsp Exp $
8d2991d5 41 *
903b00b4
JSP
42 */
43
44#include "config.h"
45#ifdef HAS_SYSLOG
46#include <syslog.h>
47#endif /* HAS_SYSLOG */
fbc0c551
JSP
48#ifdef HAS_STRERROR
49#include <string.h>
50#endif
903b00b4
JSP
51
52FILE *logfp = stderr; /* Log errors to stderr initially */
53#ifdef HAS_SYSLOG
54int syslogging;
55#endif /* HAS_SYSLOG */
56int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
57int xlog_level_init = ~0;
58
59/*
60 * List of log options
61 */
62struct opt_tab xlog_opt[] = {
63 { "all", XLOG_ALL }, /* All messages */
64#ifdef DEBUG
65 { "debug", XLOG_DEBUG }, /* Debug messages */
66#endif /* DEBUG */
67 { "error", XLOG_ERROR }, /* Non-fatal system errors */
68 { "fatal", XLOG_FATAL }, /* Fatal errors */
69 { "info", XLOG_INFO }, /* Information */
70 { "map", XLOG_MAP }, /* Map errors */
71 { "stats", XLOG_STATS }, /* Additional statistical information */
72 { "user", XLOG_USER }, /* Non-fatal user errors */
73 { "warn", XLOG_WARNING }, /* Warnings */
74 { "warning", XLOG_WARNING }, /* Warnings */
75 { 0, 0 }
76};
77
78voidp xmalloc(len)
79int len;
80{
81 voidp p;
82 int retries = 600;
83
00737562
JSP
84 /*
85 * Avoid malloc's which return NULL for malloc(0)
86 */
87 if (len == 0)
88 len = 1;
89
903b00b4
JSP
90 do {
91 p = (voidp) malloc((unsigned) len);
92 if (p) {
93#if defined(DEBUG) && defined(DEBUG_MEM)
94 Debug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
95#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
96 return p;
97 }
98 if (retries > 0) {
99 plog(XLOG_ERROR, "Retrying memory allocation");
100 sleep(1);
101 }
102 } while (--retries);
103
104 plog(XLOG_FATAL, "Out of memory");
105 going_down(1);
106
107 abort();
108
109 return 0;
110}
111
112voidp xrealloc(ptr, len)
113voidp ptr;
114int len;
115{
116#if defined(DEBUG) && defined(DEBUG_MEM)
117 Debug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
118#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
119
00737562
JSP
120 if (len == 0)
121 len = 1;
122
903b00b4
JSP
123 if (ptr)
124 ptr = (voidp) realloc(ptr, (unsigned) len);
125 else
126 ptr = (voidp) xmalloc((unsigned) len);
127
128 if (!ptr) {
129 plog(XLOG_FATAL, "Out of memory in realloc");
130 going_down(1);
131 abort();
132 }
133 return ptr;
134}
135
136#if defined(DEBUG) && defined(DEBUG_MEM)
137xfree(f, l, p)
138char *f;
139int l;
140voidp p;
141{
142 Debug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
143#undef free
144 free(p);
145}
146#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
147#ifdef DEBUG_MEM
148static int mem_bytes;
149static int orig_mem_bytes;
150static void checkup_mem(P_void)
151{
152extern struct mallinfo __mallinfo;
153 if (mem_bytes != __mallinfo.uordbytes) {
154 if (orig_mem_bytes == 0)
155 mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
156 else {
157 fprintf(logfp, "%s[%d]: ", progname, mypid);
158 if (mem_bytes < __mallinfo.uordbytes) {
159 fprintf(logfp, "ALLOC: %d bytes",
160 __mallinfo.uordbytes - mem_bytes);
161 } else {
162 fprintf(logfp, "FREE: %d bytes",
163 mem_bytes - __mallinfo.uordbytes);
164 }
165 mem_bytes = __mallinfo.uordbytes;
166 fprintf(logfp, ", making %d missing\n",
167 mem_bytes - orig_mem_bytes);
168 }
169 }
170 malloc_verify();
171}
172#endif /* DEBUG_MEM */
173
174/*
175 * Take a log format string and expand occurences of %m
176 * with the current error code take from errno.
177 */
178INLINE
179static void expand_error(f, e)
180char *f;
181char *e;
182{
fbc0c551 183#ifndef HAS_STRERROR
903b00b4
JSP
184 extern int sys_nerr;
185 extern char *sys_errlist[];
fbc0c551 186#endif
903b00b4
JSP
187 char *p;
188 int error = errno;
189
190 for (p = f; *e = *p; e++, p++) {
191 if (p[0] == '%' && p[1] == 'm') {
192 char *errstr;
fbc0c551
JSP
193#ifdef HAS_STRERROR
194 errstr = strerror(error);
195#else
903b00b4
JSP
196 if (error < 0 || error >= sys_nerr)
197 errstr = 0;
198 else
199 errstr = sys_errlist[error];
fbc0c551 200#endif
903b00b4
JSP
201 if (errstr)
202 strcpy(e, errstr);
203 else
204 sprintf(e, "Error %d", error);
205 e += strlen(e) - 1;
206 p++;
207 }
208 }
209}
210
211/*
212 * Output the time of day and hostname to the logfile
213 */
214static void show_time_host_and_name(lvl)
215int lvl;
216{
217static time_t last_t = 0;
218static char *last_ctime = 0;
219 time_t t = clocktime();
220 char *sev;
221 extern char *ctime();
222
223#if defined(DEBUG) && defined(PARANOID)
224extern char **gargv;
225#endif /* defined(DEBUG) && defined(PARANOID) */
226
227 if (t != last_t) {
228 last_ctime = ctime(&t);
229 last_t = t;
230 }
231
232 switch (lvl) {
233 case XLOG_FATAL: sev = "fatal:"; break;
234 case XLOG_ERROR: sev = "error:"; break;
235 case XLOG_USER: sev = "user: "; break;
236 case XLOG_WARNING: sev = "warn: "; break;
237 case XLOG_INFO: sev = "info: "; break;
238 case XLOG_DEBUG: sev = "debug:"; break;
239 case XLOG_MAP: sev = "map: "; break;
240 case XLOG_STATS: sev = "stats:"; break;
241 default: sev = "hmm: "; break;
242 }
243 fprintf(logfp, "%15.15s %s %s[%d]/%s ",
244 last_ctime+4, hostname,
245#if defined(DEBUG) && defined(PARANOID)
246 gargv[0],
247#else
248 progname,
249#endif /* defined(DEBUG) && defined(PARANOID) */
250 mypid,
251 sev);
252}
253
254#ifdef DEBUG
255/*VARARGS1*/
256void dplog(fmt, j,s,_,p,e,n,d,r,y)
257char *fmt;
258char *j, *s, *_, *p, *e, *n, *d, *r, *y;
259{
260 plog(XLOG_DEBUG, fmt, j,s,_,p,e,n,d,r,y);
261}
262
263#endif /* DEBUG */
264/*VARARGS1*/
265void plog(lvl, fmt, j,s,_,p,e,n,d,r,y)
266int lvl;
267char *fmt;
268char *j, *s, *_, *p, *e, *n, *d, *r, *y;
269{
270 char msg[1024];
271 char efmt[1024];
272 char *ptr = msg;
273
274 if (!(xlog_level & lvl))
275 return;
276
277#ifdef DEBUG_MEM
278 checkup_mem();
279#endif /* DEBUG_MEM */
280
281 expand_error(fmt, efmt);
282 sprintf(ptr, efmt, j,s,_,p,e,n,d,r,y);
283 ptr += strlen(ptr);
284 if (ptr[-1] == '\n')
285 *--ptr = '\0';
286#ifdef HAS_SYSLOG
287 if (syslogging) {
288 switch(lvl) { /* from mike <mcooper@usc.edu> */
289 case XLOG_FATAL: lvl = LOG_CRIT; break;
290 case XLOG_ERROR: lvl = LOG_ERR; break;
291 case XLOG_USER: lvl = LOG_WARNING; break;
292 case XLOG_WARNING: lvl = LOG_WARNING; break;
293 case XLOG_INFO: lvl = LOG_INFO; break;
294 case XLOG_DEBUG: lvl = LOG_DEBUG; break;
295 case XLOG_MAP: lvl = LOG_DEBUG; break;
296 case XLOG_STATS: lvl = LOG_INFO; break;
297 default: lvl = LOG_ERR; break;
298 }
299 syslog(lvl, "%s", msg);
300 return;
301 }
302#endif /* HAS_SYSLOG */
303
304 *ptr++ = '\n';
305 *ptr = '\0';
306
307 /*
308 * Mimic syslog header
309 */
310 show_time_host_and_name(lvl);
311 fwrite(msg, ptr - msg, 1, logfp);
312 fflush(logfp);
313}
314
315void show_opts P((int ch, struct opt_tab *opts));
316void show_opts(ch, opts)
317int ch;
318struct opt_tab *opts;
319{
320 /*
321 * Display current debug options
322 */
323 int i;
324 int s = '{';
325 fprintf(stderr, "\t[-%c {no}", ch);
326 for (i = 0; opts[i].opt; i++) {
327 fprintf(stderr, "%c%s", s, opts[i].opt);
328 s = ',';
329 }
330 fputs("}]\n", stderr);
331}
332
333int cmdoption P((char *s, struct opt_tab *optb, int *flags));
334int cmdoption(s, optb, flags)
335char *s;
336struct opt_tab *optb;
337int *flags;
338{
339 char *p = s;
340 int errs = 0;
341
342 while (p && *p) {
343 int neg;
344 char *opt;
345 struct opt_tab *dp, *dpn = 0;
346
347 s = p;
348 p = strchr(p, ',');
349 if (p)
350 *p = '\0';
351
352 if (s[0] == 'n' && s[1] == 'o') {
353 opt = s + 2;
354 neg = 1;
355 } else {
356 opt = s;
357 neg = 0;
358 }
359
360 /*
361 * Scan the array of debug options to find the
362 * corresponding flag value. If it is found
363 * then set (or clear) the flag (depending on
364 * whether the option was prefixed with "no").
365 */
366 for (dp = optb; dp->opt; dp++) {
367 if (strcmp(opt, dp->opt) == 0)
368 break;
369 if (opt != s && !dpn && strcmp(s, dp->opt) == 0)
370 dpn = dp;
371 }
372
373 if (dp->opt || dpn) {
374 if (!dp->opt) {
375 dp = dpn;
376 neg = !neg;
377 }
378 if (neg)
379 *flags &= ~dp->flag;
380 else
381 *flags |= dp->flag;
382 } else {
383 /*
384 * This will log to stderr when parsing the command line
385 * since any -l option will not yet have taken effect.
386 */
387 plog(XLOG_USER, "option \"%s\" not recognised", s);
388 errs++;
389 }
390 /*
391 * Put the comma back
392 */
393 if (p)
394 *p++ = ',';
395 }
396
397 return errs;
398}
399
400/*
401 * Switch on/off logging options
402 */
403int switch_option(opt)
404char *opt;
405{
406 int xl = xlog_level;
407 int rc = cmdoption(opt, xlog_opt, &xl);
408 if (rc) {
409 rc = EINVAL;
410 } else {
411 /*
412 * Keep track of initial log level, and
413 * don't allow options to be turned off.
414 */
415 if (xlog_level_init == ~0)
416 xlog_level_init = xl;
417 else
418 xl |= xlog_level_init;
419 xlog_level = xl;
420 }
421 return rc;
422}
423
424/*
425 * Change current logfile
426 */
427int switch_to_logfile P((char *logfile));
428int switch_to_logfile(logfile)
429char *logfile;
430{
431 FILE *new_logfp = stderr;
432
433 if (logfile) {
434#ifdef HAS_SYSLOG
435 syslogging = 0;
436#endif /* HAS_SYSLOG */
437 if (strcmp(logfile, "/dev/stderr") == 0)
438 new_logfp = stderr;
439 else if (strcmp(logfile, "syslog") == 0) {
440#ifdef HAS_SYSLOG
441 syslogging = 1;
442 new_logfp = stderr;
443#if defined(LOG_CONS) && defined(LOG_NOWAIT)
444 openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
445 LOG_DAEMON);
446#else
447 /* 4.2 compat mode - XXX */
448 openlog(progname, LOG_PID);
449#endif /* LOG_CONS && LOG_NOWAIT */
450#else
451 plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
452#endif /* HAS_SYSLOG */
453 } else {
454 (void) umask(orig_umask);
455 new_logfp = fopen(logfile, "a");
456 umask(0);
457 }
458 }
459
460 /*
461 * If we couldn't open a new file, then continue using the old.
462 */
463 if (!new_logfp && logfile) {
464 plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
465 return 1;
466 }
467 /*
468 * Close the previous file
469 */
470 if (logfp && logfp != stderr)
471 (void) fclose(logfp);
472 logfp = new_logfp;
473 return 0;
474}
475
476time_t clock_valid = 0;
477time_t xclock_valid = 0;
478#ifndef clocktime
479time_t clocktime(P_void)
480{
481 time_t now = time(&clock_valid);
482 if (xclock_valid > now) {
483 /*
484 * Someone set the clock back!
485 */
486 plog(XLOG_WARNING, "system clock reset");
487 reschedule_timeouts(now, xclock_valid);
488 }
489 return xclock_valid = now;
490}
491#endif /* clocktime */