BSD 4_3_Net_2 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
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
af359dea
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.
25 *
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 5.3 (Berkeley) 5/12/91
39 *
40 * $Id: xutil.c,v 5.2.1.5 91/05/07 22:18:43 jsp Alpha $
903b00b4 41 *
903b00b4
JSP
42 */
43
44#include "config.h"
45#ifdef HAS_SYSLOG
46#include <syslog.h>
47#endif /* HAS_SYSLOG */
48
49FILE *logfp = stderr; /* Log errors to stderr initially */
50#ifdef HAS_SYSLOG
51int syslogging;
52#endif /* HAS_SYSLOG */
53int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
54int xlog_level_init = ~0;
55
56/*
57 * List of log options
58 */
59struct opt_tab xlog_opt[] = {
60 { "all", XLOG_ALL }, /* All messages */
61#ifdef DEBUG
62 { "debug", XLOG_DEBUG }, /* Debug messages */
63#endif /* DEBUG */
64 { "error", XLOG_ERROR }, /* Non-fatal system errors */
65 { "fatal", XLOG_FATAL }, /* Fatal errors */
66 { "info", XLOG_INFO }, /* Information */
67 { "map", XLOG_MAP }, /* Map errors */
68 { "stats", XLOG_STATS }, /* Additional statistical information */
69 { "user", XLOG_USER }, /* Non-fatal user errors */
70 { "warn", XLOG_WARNING }, /* Warnings */
71 { "warning", XLOG_WARNING }, /* Warnings */
72 { 0, 0 }
73};
74
75voidp xmalloc(len)
76int len;
77{
78 voidp p;
79 int retries = 600;
80
81 do {
82 p = (voidp) malloc((unsigned) len);
83 if (p) {
84#if defined(DEBUG) && defined(DEBUG_MEM)
85 Debug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
86#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
87 return p;
88 }
89 if (retries > 0) {
90 plog(XLOG_ERROR, "Retrying memory allocation");
91 sleep(1);
92 }
93 } while (--retries);
94
95 plog(XLOG_FATAL, "Out of memory");
96 going_down(1);
97
98 abort();
99
100 return 0;
101}
102
103voidp xrealloc(ptr, len)
104voidp ptr;
105int len;
106{
107#if defined(DEBUG) && defined(DEBUG_MEM)
108 Debug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
109#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
110
111 if (ptr)
112 ptr = (voidp) realloc(ptr, (unsigned) len);
113 else
114 ptr = (voidp) xmalloc((unsigned) len);
115
116 if (!ptr) {
117 plog(XLOG_FATAL, "Out of memory in realloc");
118 going_down(1);
119 abort();
120 }
121 return ptr;
122}
123
124#if defined(DEBUG) && defined(DEBUG_MEM)
125xfree(f, l, p)
126char *f;
127int l;
128voidp p;
129{
130 Debug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
131#undef free
132 free(p);
133}
134#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
135#ifdef DEBUG_MEM
136static int mem_bytes;
137static int orig_mem_bytes;
138static void checkup_mem(P_void)
139{
140extern struct mallinfo __mallinfo;
141 if (mem_bytes != __mallinfo.uordbytes) {
142 if (orig_mem_bytes == 0)
143 mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
144 else {
145 fprintf(logfp, "%s[%d]: ", progname, mypid);
146 if (mem_bytes < __mallinfo.uordbytes) {
147 fprintf(logfp, "ALLOC: %d bytes",
148 __mallinfo.uordbytes - mem_bytes);
149 } else {
150 fprintf(logfp, "FREE: %d bytes",
151 mem_bytes - __mallinfo.uordbytes);
152 }
153 mem_bytes = __mallinfo.uordbytes;
154 fprintf(logfp, ", making %d missing\n",
155 mem_bytes - orig_mem_bytes);
156 }
157 }
158 malloc_verify();
159}
160#endif /* DEBUG_MEM */
161
162/*
163 * Take a log format string and expand occurences of %m
164 * with the current error code take from errno.
165 */
166INLINE
167static void expand_error(f, e)
168char *f;
169char *e;
170{
171 extern int sys_nerr;
172 extern char *sys_errlist[];
173 char *p;
174 int error = errno;
175
176 for (p = f; *e = *p; e++, p++) {
177 if (p[0] == '%' && p[1] == 'm') {
178 char *errstr;
179 if (error < 0 || error >= sys_nerr)
180 errstr = 0;
181 else
182 errstr = sys_errlist[error];
183 if (errstr)
184 strcpy(e, errstr);
185 else
186 sprintf(e, "Error %d", error);
187 e += strlen(e) - 1;
188 p++;
189 }
190 }
191}
192
193/*
194 * Output the time of day and hostname to the logfile
195 */
196static void show_time_host_and_name(lvl)
197int lvl;
198{
199static time_t last_t = 0;
200static char *last_ctime = 0;
201 time_t t = clocktime();
202 char *sev;
203 extern char *ctime();
204
205#if defined(DEBUG) && defined(PARANOID)
206extern char **gargv;
207#endif /* defined(DEBUG) && defined(PARANOID) */
208
209 if (t != last_t) {
210 last_ctime = ctime(&t);
211 last_t = t;
212 }
213
214 switch (lvl) {
215 case XLOG_FATAL: sev = "fatal:"; break;
216 case XLOG_ERROR: sev = "error:"; break;
217 case XLOG_USER: sev = "user: "; break;
218 case XLOG_WARNING: sev = "warn: "; break;
219 case XLOG_INFO: sev = "info: "; break;
220 case XLOG_DEBUG: sev = "debug:"; break;
221 case XLOG_MAP: sev = "map: "; break;
222 case XLOG_STATS: sev = "stats:"; break;
223 default: sev = "hmm: "; break;
224 }
225 fprintf(logfp, "%15.15s %s %s[%d]/%s ",
226 last_ctime+4, hostname,
227#if defined(DEBUG) && defined(PARANOID)
228 gargv[0],
229#else
230 progname,
231#endif /* defined(DEBUG) && defined(PARANOID) */
232 mypid,
233 sev);
234}
235
236#ifdef DEBUG
237/*VARARGS1*/
238void dplog(fmt, j,s,_,p,e,n,d,r,y)
239char *fmt;
240char *j, *s, *_, *p, *e, *n, *d, *r, *y;
241{
242 plog(XLOG_DEBUG, fmt, j,s,_,p,e,n,d,r,y);
243}
244
245#endif /* DEBUG */
246/*VARARGS1*/
247void plog(lvl, fmt, j,s,_,p,e,n,d,r,y)
248int lvl;
249char *fmt;
250char *j, *s, *_, *p, *e, *n, *d, *r, *y;
251{
252 char msg[1024];
253 char efmt[1024];
254 char *ptr = msg;
255
256 if (!(xlog_level & lvl))
257 return;
258
259#ifdef DEBUG_MEM
260 checkup_mem();
261#endif /* DEBUG_MEM */
262
263 expand_error(fmt, efmt);
264 sprintf(ptr, efmt, j,s,_,p,e,n,d,r,y);
265 ptr += strlen(ptr);
266 if (ptr[-1] == '\n')
267 *--ptr = '\0';
268#ifdef HAS_SYSLOG
269 if (syslogging) {
270 switch(lvl) { /* from mike <mcooper@usc.edu> */
271 case XLOG_FATAL: lvl = LOG_CRIT; break;
272 case XLOG_ERROR: lvl = LOG_ERR; break;
273 case XLOG_USER: lvl = LOG_WARNING; break;
274 case XLOG_WARNING: lvl = LOG_WARNING; break;
275 case XLOG_INFO: lvl = LOG_INFO; break;
276 case XLOG_DEBUG: lvl = LOG_DEBUG; break;
277 case XLOG_MAP: lvl = LOG_DEBUG; break;
278 case XLOG_STATS: lvl = LOG_INFO; break;
279 default: lvl = LOG_ERR; break;
280 }
281 syslog(lvl, "%s", msg);
282 return;
283 }
284#endif /* HAS_SYSLOG */
285
286 *ptr++ = '\n';
287 *ptr = '\0';
288
289 /*
290 * Mimic syslog header
291 */
292 show_time_host_and_name(lvl);
293 fwrite(msg, ptr - msg, 1, logfp);
294 fflush(logfp);
295}
296
297void show_opts P((int ch, struct opt_tab *opts));
298void show_opts(ch, opts)
299int ch;
300struct opt_tab *opts;
301{
302 /*
303 * Display current debug options
304 */
305 int i;
306 int s = '{';
307 fprintf(stderr, "\t[-%c {no}", ch);
308 for (i = 0; opts[i].opt; i++) {
309 fprintf(stderr, "%c%s", s, opts[i].opt);
310 s = ',';
311 }
312 fputs("}]\n", stderr);
313}
314
315int cmdoption P((char *s, struct opt_tab *optb, int *flags));
316int cmdoption(s, optb, flags)
317char *s;
318struct opt_tab *optb;
319int *flags;
320{
321 char *p = s;
322 int errs = 0;
323
324 while (p && *p) {
325 int neg;
326 char *opt;
327 struct opt_tab *dp, *dpn = 0;
328
329 s = p;
330 p = strchr(p, ',');
331 if (p)
332 *p = '\0';
333
334 if (s[0] == 'n' && s[1] == 'o') {
335 opt = s + 2;
336 neg = 1;
337 } else {
338 opt = s;
339 neg = 0;
340 }
341
342 /*
343 * Scan the array of debug options to find the
344 * corresponding flag value. If it is found
345 * then set (or clear) the flag (depending on
346 * whether the option was prefixed with "no").
347 */
348 for (dp = optb; dp->opt; dp++) {
349 if (strcmp(opt, dp->opt) == 0)
350 break;
351 if (opt != s && !dpn && strcmp(s, dp->opt) == 0)
352 dpn = dp;
353 }
354
355 if (dp->opt || dpn) {
356 if (!dp->opt) {
357 dp = dpn;
358 neg = !neg;
359 }
360 if (neg)
361 *flags &= ~dp->flag;
362 else
363 *flags |= dp->flag;
364 } else {
365 /*
366 * This will log to stderr when parsing the command line
367 * since any -l option will not yet have taken effect.
368 */
369 plog(XLOG_USER, "option \"%s\" not recognised", s);
370 errs++;
371 }
372 /*
373 * Put the comma back
374 */
375 if (p)
376 *p++ = ',';
377 }
378
379 return errs;
380}
381
382/*
383 * Switch on/off logging options
384 */
385int switch_option(opt)
386char *opt;
387{
388 int xl = xlog_level;
389 int rc = cmdoption(opt, xlog_opt, &xl);
390 if (rc) {
391 rc = EINVAL;
392 } else {
393 /*
394 * Keep track of initial log level, and
395 * don't allow options to be turned off.
396 */
397 if (xlog_level_init == ~0)
398 xlog_level_init = xl;
399 else
400 xl |= xlog_level_init;
401 xlog_level = xl;
402 }
403 return rc;
404}
405
406/*
407 * Change current logfile
408 */
409int switch_to_logfile P((char *logfile));
410int switch_to_logfile(logfile)
411char *logfile;
412{
413 FILE *new_logfp = stderr;
414
415 if (logfile) {
416#ifdef HAS_SYSLOG
417 syslogging = 0;
418#endif /* HAS_SYSLOG */
419 if (strcmp(logfile, "/dev/stderr") == 0)
420 new_logfp = stderr;
421 else if (strcmp(logfile, "syslog") == 0) {
422#ifdef HAS_SYSLOG
423 syslogging = 1;
424 new_logfp = stderr;
425#if defined(LOG_CONS) && defined(LOG_NOWAIT)
426 openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
427 LOG_DAEMON);
428#else
429 /* 4.2 compat mode - XXX */
430 openlog(progname, LOG_PID);
431#endif /* LOG_CONS && LOG_NOWAIT */
432#else
433 plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
434#endif /* HAS_SYSLOG */
435 } else {
436 (void) umask(orig_umask);
437 new_logfp = fopen(logfile, "a");
438 umask(0);
439 }
440 }
441
442 /*
443 * If we couldn't open a new file, then continue using the old.
444 */
445 if (!new_logfp && logfile) {
446 plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
447 return 1;
448 }
449 /*
450 * Close the previous file
451 */
452 if (logfp && logfp != stderr)
453 (void) fclose(logfp);
454 logfp = new_logfp;
455 return 0;
456}
457
458time_t clock_valid = 0;
459time_t xclock_valid = 0;
460#ifndef clocktime
461time_t clocktime(P_void)
462{
463 time_t now = time(&clock_valid);
464 if (xclock_valid > now) {
465 /*
466 * Someone set the clock back!
467 */
468 plog(XLOG_WARNING, "system clock reset");
469 reschedule_timeouts(now, xclock_valid);
470 }
471 return xclock_valid = now;
472}
473#endif /* clocktime */