xref: /original-bsd/usr.sbin/amd/amd/xutil.c (revision 4092c5cc)
130e13732Spendry /*
230e13732Spendry  * Copyright (c) 1990 Jan-Simon Pendry
330e13732Spendry  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4*4092c5ccSbostic  * Copyright (c) 1990, 1993
5*4092c5ccSbostic  *	The Regents of the University of California.  All rights reserved.
630e13732Spendry  *
730e13732Spendry  * This code is derived from software contributed to Berkeley by
830e13732Spendry  * Jan-Simon Pendry at Imperial College, London.
930e13732Spendry  *
108a89c22cSpendry  * %sccs.include.redist.c%
1130e13732Spendry  *
12*4092c5ccSbostic  *	@(#)xutil.c	8.1 (Berkeley) 06/06/93
13c626267eSpendry  *
1410042f30Spendry  * $Id: xutil.c,v 5.2.2.3 1992/03/07 10:36:09 jsp Exp $
15c626267eSpendry  *
1630e13732Spendry  */
1730e13732Spendry 
1830e13732Spendry #include "config.h"
1930e13732Spendry #ifdef HAS_SYSLOG
2030e13732Spendry #include <syslog.h>
2130e13732Spendry #endif /* HAS_SYSLOG */
2218436490Spendry #ifdef HAS_STRERROR
2318436490Spendry #include <string.h>
2418436490Spendry #endif
2530e13732Spendry 
2630e13732Spendry FILE *logfp = stderr;		/* Log errors to stderr initially */
2730e13732Spendry #ifdef HAS_SYSLOG
2830e13732Spendry int syslogging;
2930e13732Spendry #endif /* HAS_SYSLOG */
3030e13732Spendry int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
3130e13732Spendry int xlog_level_init = ~0;
3230e13732Spendry 
3330e13732Spendry /*
3430e13732Spendry  * List of log options
3530e13732Spendry  */
3630e13732Spendry struct opt_tab xlog_opt[] = {
3730e13732Spendry 	{ "all", XLOG_ALL },		/* All messages */
3830e13732Spendry #ifdef DEBUG
3930e13732Spendry 	{ "debug", XLOG_DEBUG },	/* Debug messages */
4030e13732Spendry #endif /* DEBUG */
4130e13732Spendry 	{ "error", XLOG_ERROR },	/* Non-fatal system errors */
4230e13732Spendry 	{ "fatal", XLOG_FATAL },	/* Fatal errors */
4330e13732Spendry 	{ "info", XLOG_INFO },		/* Information */
4430e13732Spendry 	{ "map", XLOG_MAP },		/* Map errors */
4530e13732Spendry 	{ "stats", XLOG_STATS },	/* Additional statistical information */
4630e13732Spendry 	{ "user", XLOG_USER },		/* Non-fatal user errors */
4730e13732Spendry 	{ "warn", XLOG_WARNING },	/* Warnings */
4830e13732Spendry 	{ "warning", XLOG_WARNING },	/* Warnings */
4930e13732Spendry 	{ 0, 0 }
5030e13732Spendry };
5130e13732Spendry 
xmalloc(len)5230e13732Spendry voidp xmalloc(len)
5330e13732Spendry int len;
5430e13732Spendry {
5530e13732Spendry 	voidp p;
5630e13732Spendry 	int retries = 600;
5730e13732Spendry 
5810042f30Spendry 	/*
5910042f30Spendry 	 * Avoid malloc's which return NULL for malloc(0)
6010042f30Spendry 	 */
6110042f30Spendry 	if (len == 0)
6210042f30Spendry 		len = 1;
6310042f30Spendry 
6430e13732Spendry 	do {
6530e13732Spendry 		p = (voidp) malloc((unsigned) len);
6630e13732Spendry 		if (p) {
6730e13732Spendry #if defined(DEBUG) && defined(DEBUG_MEM)
6830e13732Spendry 			Debug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
6930e13732Spendry #endif /* defined(DEBUG) && defined(DEBUG_MEM) */
7030e13732Spendry 			return p;
7130e13732Spendry 		}
7230e13732Spendry 		if (retries > 0) {
7330e13732Spendry 			plog(XLOG_ERROR, "Retrying memory allocation");
7430e13732Spendry 			sleep(1);
7530e13732Spendry 		}
7630e13732Spendry 	} while (--retries);
7730e13732Spendry 
7830e13732Spendry 	plog(XLOG_FATAL, "Out of memory");
7930e13732Spendry 	going_down(1);
8030e13732Spendry 
8130e13732Spendry 	abort();
8230e13732Spendry 
8330e13732Spendry 	return 0;
8430e13732Spendry }
8530e13732Spendry 
xrealloc(ptr,len)8630e13732Spendry voidp xrealloc(ptr, len)
8730e13732Spendry voidp ptr;
8830e13732Spendry int len;
8930e13732Spendry {
9030e13732Spendry #if defined(DEBUG) && defined(DEBUG_MEM)
9130e13732Spendry 	Debug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
9230e13732Spendry #endif /* defined(DEBUG) && defined(DEBUG_MEM) */
9330e13732Spendry 
9410042f30Spendry 	if (len == 0)
9510042f30Spendry 		len = 1;
9610042f30Spendry 
9730e13732Spendry 	if (ptr)
9830e13732Spendry 		ptr = (voidp) realloc(ptr, (unsigned) len);
9930e13732Spendry 	else
10030e13732Spendry 		ptr = (voidp) xmalloc((unsigned) len);
10130e13732Spendry 
10230e13732Spendry 	if (!ptr) {
10330e13732Spendry 		plog(XLOG_FATAL, "Out of memory in realloc");
10430e13732Spendry 		going_down(1);
10530e13732Spendry 		abort();
10630e13732Spendry 	}
10730e13732Spendry 	return ptr;
10830e13732Spendry }
10930e13732Spendry 
11030e13732Spendry #if defined(DEBUG) && defined(DEBUG_MEM)
xfree(f,l,p)11130e13732Spendry xfree(f, l, p)
11230e13732Spendry char *f;
11330e13732Spendry int l;
11430e13732Spendry voidp p;
11530e13732Spendry {
11630e13732Spendry 	Debug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
11730e13732Spendry #undef free
11830e13732Spendry 	free(p);
11930e13732Spendry }
12030e13732Spendry #endif /* defined(DEBUG) && defined(DEBUG_MEM) */
12130e13732Spendry #ifdef DEBUG_MEM
12230e13732Spendry static int mem_bytes;
12330e13732Spendry static int orig_mem_bytes;
checkup_mem(P_void)12430e13732Spendry static void checkup_mem(P_void)
12530e13732Spendry {
12630e13732Spendry extern struct mallinfo __mallinfo;
12730e13732Spendry 	if (mem_bytes != __mallinfo.uordbytes) {
12830e13732Spendry 		if (orig_mem_bytes == 0)
12930e13732Spendry 			mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
13030e13732Spendry 		else {
13130e13732Spendry 			fprintf(logfp, "%s[%d]: ", progname, mypid);
13230e13732Spendry 			if (mem_bytes < __mallinfo.uordbytes) {
13330e13732Spendry 				fprintf(logfp, "ALLOC: %d bytes",
13430e13732Spendry 					__mallinfo.uordbytes - mem_bytes);
13530e13732Spendry 			} else {
13630e13732Spendry 				fprintf(logfp, "FREE: %d bytes",
13730e13732Spendry 					mem_bytes - __mallinfo.uordbytes);
13830e13732Spendry 			}
13930e13732Spendry 			mem_bytes = __mallinfo.uordbytes;
14030e13732Spendry 			fprintf(logfp, ", making %d missing\n",
14130e13732Spendry 				mem_bytes - orig_mem_bytes);
14230e13732Spendry 		}
14330e13732Spendry 	}
14430e13732Spendry 	malloc_verify();
14530e13732Spendry }
14630e13732Spendry #endif /* DEBUG_MEM */
14730e13732Spendry 
14830e13732Spendry /*
14930e13732Spendry  * Take a log format string and expand occurences of %m
15030e13732Spendry  * with the current error code take from errno.
15130e13732Spendry  */
15230e13732Spendry INLINE
expand_error(f,e)15330e13732Spendry static void expand_error(f, e)
15430e13732Spendry char *f;
15530e13732Spendry char *e;
15630e13732Spendry {
15718436490Spendry #ifndef HAS_STRERROR
15830e13732Spendry 	extern int sys_nerr;
15930e13732Spendry 	extern char *sys_errlist[];
16018436490Spendry #endif
16130e13732Spendry 	char *p;
16230e13732Spendry 	int error = errno;
16330e13732Spendry 
16430e13732Spendry 	for (p = f; *e = *p; e++, p++) {
16530e13732Spendry 		if (p[0] == '%' && p[1] == 'm') {
16630e13732Spendry 			char *errstr;
16718436490Spendry #ifdef HAS_STRERROR
16818436490Spendry 			errstr = strerror(error);
16918436490Spendry #else
17030e13732Spendry 			if (error < 0 || error >= sys_nerr)
17130e13732Spendry 				errstr = 0;
17230e13732Spendry 			else
17330e13732Spendry 				errstr = sys_errlist[error];
17418436490Spendry #endif
17530e13732Spendry 			if (errstr)
17630e13732Spendry 				strcpy(e, errstr);
17730e13732Spendry 			else
17830e13732Spendry 				sprintf(e, "Error %d", error);
17930e13732Spendry 			e += strlen(e) - 1;
18030e13732Spendry 			p++;
18130e13732Spendry 		}
18230e13732Spendry 	}
18330e13732Spendry }
18430e13732Spendry 
18530e13732Spendry /*
18630e13732Spendry  * Output the time of day and hostname to the logfile
18730e13732Spendry  */
show_time_host_and_name(lvl)18830e13732Spendry static void show_time_host_and_name(lvl)
18930e13732Spendry int lvl;
19030e13732Spendry {
19130e13732Spendry static time_t last_t = 0;
19230e13732Spendry static char *last_ctime = 0;
19330e13732Spendry 	time_t t = clocktime();
19430e13732Spendry 	char *sev;
19530e13732Spendry 	extern char *ctime();
19630e13732Spendry 
19730e13732Spendry #if defined(DEBUG) && defined(PARANOID)
19830e13732Spendry extern char **gargv;
19930e13732Spendry #endif /* defined(DEBUG) && defined(PARANOID) */
20030e13732Spendry 
20130e13732Spendry 	if (t != last_t) {
20230e13732Spendry 		last_ctime = ctime(&t);
20330e13732Spendry 		last_t = t;
20430e13732Spendry 	}
20530e13732Spendry 
20630e13732Spendry 	switch (lvl) {
20730e13732Spendry 	case XLOG_FATAL:	sev = "fatal:"; break;
20830e13732Spendry 	case XLOG_ERROR: 	sev = "error:"; break;
20930e13732Spendry 	case XLOG_USER:		sev = "user: "; break;
21030e13732Spendry 	case XLOG_WARNING:	sev = "warn: "; break;
21130e13732Spendry 	case XLOG_INFO:		sev = "info: "; break;
21230e13732Spendry 	case XLOG_DEBUG:	sev = "debug:"; break;
21330e13732Spendry 	case XLOG_MAP:		sev = "map:  "; break;
21430e13732Spendry 	case XLOG_STATS:	sev = "stats:"; break;
21530e13732Spendry 	default:		sev = "hmm:  "; break;
21630e13732Spendry 	}
21730e13732Spendry 	fprintf(logfp, "%15.15s %s %s[%d]/%s ",
21830e13732Spendry 		last_ctime+4, hostname,
21930e13732Spendry #if defined(DEBUG) && defined(PARANOID)
22030e13732Spendry 		gargv[0],
22130e13732Spendry #else
22230e13732Spendry 		progname,
22330e13732Spendry #endif /* defined(DEBUG) && defined(PARANOID) */
22430e13732Spendry 		mypid,
22530e13732Spendry 		sev);
22630e13732Spendry }
22730e13732Spendry 
22830e13732Spendry #ifdef DEBUG
22930e13732Spendry /*VARARGS1*/
dplog(fmt,j,s,_,p,e,n,d,r,y)23030e13732Spendry void dplog(fmt, j,s,_,p,e,n,d,r,y)
23130e13732Spendry char *fmt;
23230e13732Spendry char *j, *s, *_, *p, *e, *n, *d, *r, *y;
23330e13732Spendry {
23430e13732Spendry 	plog(XLOG_DEBUG, fmt, j,s,_,p,e,n,d,r,y);
23530e13732Spendry }
23630e13732Spendry 
23730e13732Spendry #endif /* DEBUG */
23830e13732Spendry /*VARARGS1*/
plog(lvl,fmt,j,s,_,p,e,n,d,r,y)23930e13732Spendry void plog(lvl, fmt, j,s,_,p,e,n,d,r,y)
24030e13732Spendry int lvl;
24130e13732Spendry char *fmt;
24230e13732Spendry char *j, *s, *_, *p, *e, *n, *d, *r, *y;
24330e13732Spendry {
24430e13732Spendry 	char msg[1024];
24530e13732Spendry 	char efmt[1024];
24630e13732Spendry 	char *ptr = msg;
24730e13732Spendry 
24830e13732Spendry 	if (!(xlog_level & lvl))
24930e13732Spendry 		return;
25030e13732Spendry 
25130e13732Spendry #ifdef DEBUG_MEM
25230e13732Spendry 	checkup_mem();
25330e13732Spendry #endif /* DEBUG_MEM */
25430e13732Spendry 
25530e13732Spendry 	expand_error(fmt, efmt);
25630e13732Spendry 	sprintf(ptr, efmt, j,s,_,p,e,n,d,r,y);
25730e13732Spendry 	ptr += strlen(ptr);
25830e13732Spendry 	if (ptr[-1] == '\n')
25930e13732Spendry 		*--ptr  = '\0';
26030e13732Spendry #ifdef HAS_SYSLOG
26130e13732Spendry 	if (syslogging) {
26230e13732Spendry 		switch(lvl) {	/* from mike <mcooper@usc.edu> */
26330e13732Spendry 		case XLOG_FATAL:	lvl = LOG_CRIT; break;
26430e13732Spendry 		case XLOG_ERROR: 	lvl = LOG_ERR; break;
26530e13732Spendry 		case XLOG_USER:		lvl = LOG_WARNING; break;
26630e13732Spendry 		case XLOG_WARNING:	lvl = LOG_WARNING; break;
26730e13732Spendry 		case XLOG_INFO:		lvl = LOG_INFO; break;
26830e13732Spendry 		case XLOG_DEBUG:	lvl = LOG_DEBUG; break;
26930e13732Spendry 		case XLOG_MAP:		lvl = LOG_DEBUG; break;
27030e13732Spendry 		case XLOG_STATS:	lvl = LOG_INFO; break;
27130e13732Spendry 		default:		lvl = LOG_ERR; break;
27230e13732Spendry 		}
27330e13732Spendry 		syslog(lvl, "%s", msg);
27430e13732Spendry 		return;
27530e13732Spendry 	}
27630e13732Spendry #endif /* HAS_SYSLOG */
27730e13732Spendry 
27830e13732Spendry 	*ptr++ = '\n';
27930e13732Spendry 	*ptr = '\0';
28030e13732Spendry 
28130e13732Spendry 	/*
28230e13732Spendry 	 * Mimic syslog header
28330e13732Spendry 	 */
28430e13732Spendry 	show_time_host_and_name(lvl);
28530e13732Spendry 	fwrite(msg, ptr - msg, 1, logfp);
28630e13732Spendry 	fflush(logfp);
28730e13732Spendry }
28830e13732Spendry 
28930e13732Spendry void show_opts P((int ch, struct opt_tab *opts));
show_opts(ch,opts)29030e13732Spendry void show_opts(ch, opts)
29130e13732Spendry int ch;
29230e13732Spendry struct opt_tab *opts;
29330e13732Spendry {
29430e13732Spendry 	/*
29530e13732Spendry 	 * Display current debug options
29630e13732Spendry 	 */
29730e13732Spendry 	int i;
29830e13732Spendry 	int s = '{';
29930e13732Spendry 	fprintf(stderr, "\t[-%c {no}", ch);
30030e13732Spendry 	for (i = 0; opts[i].opt; i++) {
30130e13732Spendry 		fprintf(stderr, "%c%s", s, opts[i].opt);
30230e13732Spendry 		s = ',';
30330e13732Spendry 	}
30430e13732Spendry 	fputs("}]\n", stderr);
30530e13732Spendry }
30630e13732Spendry 
30730e13732Spendry int cmdoption P((char *s, struct opt_tab *optb, int *flags));
cmdoption(s,optb,flags)30830e13732Spendry int cmdoption(s, optb, flags)
30930e13732Spendry char *s;
31030e13732Spendry struct opt_tab *optb;
31130e13732Spendry int *flags;
31230e13732Spendry {
31330e13732Spendry 	char *p = s;
31430e13732Spendry 	int errs = 0;
31530e13732Spendry 
31630e13732Spendry 	while (p && *p) {
31730e13732Spendry 		int neg;
31830e13732Spendry 		char *opt;
31930e13732Spendry 		struct opt_tab *dp, *dpn = 0;
32030e13732Spendry 
32130e13732Spendry 		s = p;
32230e13732Spendry 		p = strchr(p, ',');
32330e13732Spendry 		if (p)
32430e13732Spendry 			*p = '\0';
32530e13732Spendry 
32630e13732Spendry 		if (s[0] == 'n' && s[1] == 'o') {
32730e13732Spendry 			opt = s + 2;
32830e13732Spendry 			neg = 1;
32930e13732Spendry 		} else {
33030e13732Spendry 			opt = s;
33130e13732Spendry 			neg = 0;
33230e13732Spendry 		}
33330e13732Spendry 
33430e13732Spendry 		/*
33530e13732Spendry 		 * Scan the array of debug options to find the
33630e13732Spendry 		 * corresponding flag value.  If it is found
33730e13732Spendry 		 * then set (or clear) the flag (depending on
33830e13732Spendry 		 * whether the option was prefixed with "no").
33930e13732Spendry 		 */
34030e13732Spendry 		for (dp = optb; dp->opt; dp++) {
34130e13732Spendry 			if (strcmp(opt, dp->opt) == 0)
34230e13732Spendry 				break;
34330e13732Spendry 			if (opt != s && !dpn && strcmp(s, dp->opt) == 0)
34430e13732Spendry 				dpn = dp;
34530e13732Spendry 		}
34630e13732Spendry 
34730e13732Spendry 		if (dp->opt || dpn) {
34830e13732Spendry 			if (!dp->opt) {
34930e13732Spendry 				dp = dpn;
35030e13732Spendry 				neg = !neg;
35130e13732Spendry 			}
35230e13732Spendry 			if (neg)
35330e13732Spendry 				*flags &= ~dp->flag;
35430e13732Spendry 			else
35530e13732Spendry 				*flags |= dp->flag;
35630e13732Spendry 		} else {
35730e13732Spendry 			/*
35830e13732Spendry 			 * This will log to stderr when parsing the command line
35930e13732Spendry 			 * since any -l option will not yet have taken effect.
36030e13732Spendry 			 */
36130e13732Spendry 			plog(XLOG_USER, "option \"%s\" not recognised", s);
36230e13732Spendry 			errs++;
36330e13732Spendry 		}
36430e13732Spendry 		/*
36530e13732Spendry 		 * Put the comma back
36630e13732Spendry 		 */
36730e13732Spendry 		if (p)
36830e13732Spendry 			*p++ = ',';
36930e13732Spendry 	}
37030e13732Spendry 
37130e13732Spendry 	return errs;
37230e13732Spendry }
37330e13732Spendry 
37430e13732Spendry /*
37530e13732Spendry  * Switch on/off logging options
37630e13732Spendry  */
switch_option(opt)37730e13732Spendry int switch_option(opt)
37830e13732Spendry char *opt;
37930e13732Spendry {
38030e13732Spendry 	int xl = xlog_level;
38130e13732Spendry 	int rc = cmdoption(opt, xlog_opt, &xl);
38230e13732Spendry 	if (rc) {
38330e13732Spendry 		rc = EINVAL;
38430e13732Spendry 	} else {
38530e13732Spendry 		/*
38630e13732Spendry 		 * Keep track of initial log level, and
38730e13732Spendry 		 * don't allow options to be turned off.
38830e13732Spendry 		 */
38930e13732Spendry 		if (xlog_level_init == ~0)
39030e13732Spendry 			xlog_level_init = xl;
39130e13732Spendry 		else
39230e13732Spendry 			xl |= xlog_level_init;
39330e13732Spendry 		xlog_level = xl;
39430e13732Spendry 	}
39530e13732Spendry 	return rc;
39630e13732Spendry }
39730e13732Spendry 
39830e13732Spendry /*
39930e13732Spendry  * Change current logfile
40030e13732Spendry  */
40130e13732Spendry int switch_to_logfile P((char *logfile));
switch_to_logfile(logfile)40230e13732Spendry int switch_to_logfile(logfile)
40330e13732Spendry char *logfile;
40430e13732Spendry {
40530e13732Spendry 	FILE *new_logfp = stderr;
40630e13732Spendry 
40730e13732Spendry 	if (logfile) {
40830e13732Spendry #ifdef HAS_SYSLOG
40930e13732Spendry 		syslogging = 0;
41030e13732Spendry #endif /* HAS_SYSLOG */
41130e13732Spendry 		if (strcmp(logfile, "/dev/stderr") == 0)
41230e13732Spendry 			new_logfp = stderr;
41330e13732Spendry 		else if (strcmp(logfile, "syslog") == 0) {
41430e13732Spendry #ifdef HAS_SYSLOG
41530e13732Spendry 			syslogging = 1;
41630e13732Spendry 			new_logfp = stderr;
41730e13732Spendry #if defined(LOG_CONS) && defined(LOG_NOWAIT)
41830e13732Spendry 			openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
41930e13732Spendry 				LOG_DAEMON);
42030e13732Spendry #else
42130e13732Spendry 			/* 4.2 compat mode - XXX */
42230e13732Spendry 			openlog(progname, LOG_PID);
42330e13732Spendry #endif /* LOG_CONS && LOG_NOWAIT */
42430e13732Spendry #else
42530e13732Spendry 			plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
42630e13732Spendry #endif /* HAS_SYSLOG */
42730e13732Spendry 		} else {
42830e13732Spendry 			(void) umask(orig_umask);
42930e13732Spendry 			new_logfp = fopen(logfile, "a");
43030e13732Spendry 			umask(0);
43130e13732Spendry 		}
43230e13732Spendry 	}
43330e13732Spendry 
43430e13732Spendry 	/*
43530e13732Spendry 	 * If we couldn't open a new file, then continue using the old.
43630e13732Spendry 	 */
43730e13732Spendry 	if (!new_logfp && logfile) {
43830e13732Spendry 		plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
43930e13732Spendry 		return 1;
44030e13732Spendry 	}
44130e13732Spendry 	/*
44230e13732Spendry 	 * Close the previous file
44330e13732Spendry 	 */
44430e13732Spendry 	if (logfp && logfp != stderr)
44530e13732Spendry 		(void) fclose(logfp);
44630e13732Spendry 	logfp = new_logfp;
44730e13732Spendry 	return 0;
44830e13732Spendry }
44930e13732Spendry 
45030e13732Spendry time_t clock_valid = 0;
45130e13732Spendry time_t xclock_valid = 0;
45230e13732Spendry #ifndef clocktime
clocktime(P_void)45330e13732Spendry time_t clocktime(P_void)
45430e13732Spendry {
45530e13732Spendry 	time_t now = time(&clock_valid);
45630e13732Spendry 	if (xclock_valid > now) {
45730e13732Spendry 		/*
45830e13732Spendry 		 * Someone set the clock back!
45930e13732Spendry 		 */
46030e13732Spendry 		plog(XLOG_WARNING, "system clock reset");
46130e13732Spendry 		reschedule_timeouts(now, xclock_valid);
46230e13732Spendry 	}
46330e13732Spendry 	return xclock_valid = now;
46430e13732Spendry }
46530e13732Spendry #endif /* clocktime */
466