GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/amd/amd/xutil.c Lines: 0 123 0.0 %
Date: 2017-11-07 Branches: 0 86 0.0 %

Line Branch Exec Source
1
/*
2
 * Copyright (c) 1990 Jan-Simon Pendry
3
 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4
 * Copyright (c) 1990, 1993
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software contributed to Berkeley by
8
 * Jan-Simon Pendry at Imperial College, London.
9
 *
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. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 *
34
 *	from: @(#)xutil.c	8.1 (Berkeley) 6/6/93
35
 *	$Id: xutil.c,v 1.19 2015/12/12 20:06:42 mmcc Exp $
36
 */
37
38
#include "am.h"
39
40
#include <sys/stat.h>
41
#include <stdarg.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <syslog.h>
45
#include <time.h>
46
#include <unistd.h>
47
48
FILE *logfp = stderr;		/* Log errors to stderr initially */
49
int syslogging;
50
int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS & ~XLOG_INFO;
51
int xlog_level_init = ~0;
52
53
/*
54
 * List of log options
55
 */
56
struct opt_tab xlog_opt[] = {
57
	{ "all", XLOG_ALL },		/* All messages */
58
#ifdef DEBUG
59
	{ "debug", XLOG_DEBUG },	/* Debug messages */
60
#endif /* DEBUG */
61
	{ "error", XLOG_ERROR },	/* Non-fatal system errors */
62
	{ "fatal", XLOG_FATAL },	/* Fatal errors */
63
	{ "info", XLOG_INFO },		/* Information */
64
	{ "map", XLOG_MAP },		/* Map errors */
65
	{ "stats", XLOG_STATS },	/* Additional statistical information */
66
	{ "user", XLOG_USER },		/* Non-fatal user errors */
67
	{ "warn", XLOG_WARNING },	/* Warnings */
68
	{ "warning", XLOG_WARNING },	/* Warnings */
69
	{ 0, 0 }
70
};
71
72
__dead void
73
xmallocfailure(void)
74
{
75
	plog(XLOG_FATAL, "Out of memory");
76
	going_down(1);
77
	abort();
78
}
79
80
void *
81
xmalloc(size_t len)
82
{
83
	void *p;
84
	int retries = 600;
85
86
	do {
87
		if ((p = malloc(len)) != NULL)
88
			return p;
89
90
		if (retries > 0) {
91
			plog(XLOG_ERROR, "Retrying memory allocation");
92
			sleep(1);
93
		}
94
	} while (--retries);
95
96
	xmallocfailure();
97
}
98
99
void *
100
xreallocarray(void *ptr, size_t nmemb, size_t size)
101
{
102
	ptr = reallocarray(ptr, nmemb, size);
103
104
	if (ptr == NULL)
105
		xmallocfailure();
106
	return (ptr);
107
}
108
109
110
/*
111
 * Take a log format string and expand occurrences of %m
112
 * with the current error code taken from errno.  Make sure
113
 * 'e' never gets longer than maxlen characters.
114
 */
115
static void
116
expand_error(const char *f, char *e, int maxlen)
117
{
118
	const char *p;
119
	char *q;
120
	int error = errno;
121
	int len = 0;
122
123
	for (p = f, q = e; (*q = *p) && len < maxlen; len++, q++, p++) {
124
		if (p[0] == '%' && p[1] == 'm') {
125
			char *errstr;
126
			errstr = strerror(error);
127
			if (errstr)
128
				strlcpy(q, errstr, maxlen - (q - e));
129
			else
130
				snprintf(q, maxlen - (q - e),
131
				    "Error %d", error);
132
			len += strlen(q) - 1;
133
			q += strlen(q) - 1;
134
			p++;
135
		}
136
	}
137
	e[maxlen-1] = '\0';		/* null terminate, to be sure */
138
}
139
140
/*
141
 * Output the time of day and hostname to the logfile
142
 */
143
static void
144
show_time_host_and_name(int lvl)
145
{
146
	static time_t last_t = 0;
147
	static char *last_ctime = 0;
148
	time_t t = clocktime();
149
	char *sev;
150
151
#if defined(DEBUG) && defined(PARANOID)
152
extern char **gargv;
153
#endif /* defined(DEBUG) && defined(PARANOID) */
154
155
	if (t != last_t) {
156
		last_ctime = ctime(&t);
157
		last_t = t;
158
	}
159
160
	switch (lvl) {
161
	case XLOG_FATAL:	sev = "fatal:"; break;
162
	case XLOG_ERROR:	sev = "error:"; break;
163
	case XLOG_USER:		sev = "user: "; break;
164
	case XLOG_WARNING:	sev = "warn: "; break;
165
	case XLOG_INFO:		sev = "info: "; break;
166
	case XLOG_DEBUG:	sev = "debug:"; break;
167
	case XLOG_MAP:		sev = "map:  "; break;
168
	case XLOG_STATS:	sev = "stats:"; break;
169
	default:		sev = "hmm:  "; break;
170
	}
171
	fprintf(logfp, "%15.15s %s %s[%ld]/%s ",
172
		last_ctime+4, hostname,
173
#if defined(DEBUG) && defined(PARANOID)
174
		gargv[0],
175
#else
176
		__progname,
177
#endif /* defined(DEBUG) && defined(PARANOID) */
178
		(long)mypid,
179
		sev);
180
}
181
182
void
183
plog(int lvl, const char *fmt, ...)
184
{
185
	char efmt[1024];
186
	va_list ap;
187
188
	if (!(xlog_level & lvl))
189
		return;
190
191
192
	if (syslogging) {
193
		switch(lvl) {	/* from mike <mcooper@usc.edu> */
194
		case XLOG_FATAL:	lvl = LOG_CRIT; break;
195
		case XLOG_ERROR:	lvl = LOG_ERR; break;
196
		case XLOG_USER:		lvl = LOG_WARNING; break;
197
		case XLOG_WARNING:	lvl = LOG_WARNING; break;
198
		case XLOG_INFO:		lvl = LOG_INFO; break;
199
		case XLOG_DEBUG:	lvl = LOG_DEBUG; break;
200
		case XLOG_MAP:		lvl = LOG_DEBUG; break;
201
		case XLOG_STATS:	lvl = LOG_INFO; break;
202
		default:		lvl = LOG_ERR; break;
203
		}
204
		va_start(ap, fmt);
205
		vsyslog(lvl, fmt, ap);
206
		va_end(ap);
207
		return;
208
	}
209
210
	expand_error(fmt, efmt, sizeof(efmt));
211
212
	/*
213
	 * Mimic syslog header
214
	 */
215
	show_time_host_and_name(lvl);
216
	va_start(ap, fmt);
217
	vfprintf(logfp, efmt, ap);
218
	va_end(ap);
219
	fputc('\n', logfp);
220
	fflush(logfp);
221
}
222
223
void
224
show_opts(int ch, struct opt_tab *opts)
225
{
226
	/*
227
	 * Display current debug options
228
	 */
229
	int i;
230
	int s = '{';
231
232
	fprintf(stderr, "\t[-%c {no}", ch);
233
	for (i = 0; opts[i].opt; i++) {
234
		fprintf(stderr, "%c%s", s, opts[i].opt);
235
		s = ',';
236
	}
237
	fputs("}]\n", stderr);
238
}
239
240
int
241
cmdoption(char *s, struct opt_tab *optb, int *flags)
242
{
243
	char *p = s;
244
	int errs = 0;
245
246
	while (p && *p) {
247
		int neg;
248
		char *opt;
249
		struct opt_tab *dp, *dpn = 0;
250
251
		s = p;
252
		p = strchr(p, ',');
253
		if (p)
254
			*p = '\0';
255
256
		if (s[0] == 'n' && s[1] == 'o') {
257
			opt = s + 2;
258
			neg = 1;
259
		} else {
260
			opt = s;
261
			neg = 0;
262
		}
263
264
		/*
265
		 * Scan the array of debug options to find the
266
		 * corresponding flag value.  If it is found
267
		 * then set (or clear) the flag (depending on
268
		 * whether the option was prefixed with "no").
269
		 */
270
		for (dp = optb; dp->opt; dp++) {
271
			if (strcmp(opt, dp->opt) == 0)
272
				break;
273
			if (opt != s && !dpn && strcmp(s, dp->opt) == 0)
274
				dpn = dp;
275
		}
276
277
		if (dp->opt || dpn) {
278
			if (!dp->opt) {
279
				dp = dpn;
280
				neg = !neg;
281
			}
282
			if (neg)
283
				*flags &= ~dp->flag;
284
			else
285
				*flags |= dp->flag;
286
		} else {
287
			/*
288
			 * This will log to stderr when parsing the command line
289
			 * since any -l option will not yet have taken effect.
290
			 */
291
			plog(XLOG_USER, "option \"%s\" not recognised", s);
292
			errs++;
293
		}
294
		/*
295
		 * Put the comma back
296
		 */
297
		if (p)
298
			*p++ = ',';
299
	}
300
301
	return errs;
302
}
303
304
/*
305
 * Switch on/off logging options
306
 */
307
int
308
switch_option(char *opt)
309
{
310
	int xl = xlog_level;
311
	int rc = cmdoption(opt, xlog_opt, &xl);
312
	if (rc) {
313
		rc = EINVAL;
314
	} else {
315
		/*
316
		 * Keep track of initial log level, and
317
		 * don't allow options to be turned off.
318
		 */
319
		if (xlog_level_init == ~0)
320
			xlog_level_init = xl;
321
		else
322
			xl |= xlog_level_init;
323
		xlog_level = xl;
324
	}
325
	return rc;
326
}
327
328
/*
329
 * Change current logfile
330
 */
331
int
332
switch_to_logfile(char *logfile)
333
{
334
	FILE *new_logfp = stderr;
335
336
	if (logfile) {
337
		syslogging = 0;
338
		if (strcmp(logfile, "/dev/stderr") == 0)
339
			new_logfp = stderr;
340
		else if (strcmp(logfile, "syslog") == 0) {
341
			syslogging = 1;
342
			new_logfp = stderr;
343
#if defined(LOG_CONS) && defined(LOG_NOWAIT)
344
			openlog(__progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
345
				LOG_DAEMON);
346
#else
347
			/* 4.2 compat mode - XXX */
348
			openlog(__progname, LOG_PID);
349
#endif /* LOG_CONS && LOG_NOWAIT */
350
		} else {
351
			(void) umask(orig_umask);
352
			new_logfp = fopen(logfile, "a");
353
			umask(0);
354
		}
355
	}
356
357
	/*
358
	 * If we couldn't open a new file, then continue using the old.
359
	 */
360
	if (!new_logfp && logfile) {
361
		plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
362
		return 1;
363
	}
364
	/*
365
	 * Close the previous file
366
	 */
367
	if (logfp && logfp != stderr)
368
		(void) fclose(logfp);
369
	logfp = new_logfp;
370
	return 0;
371
}
372
373
time_t clock_valid = 0;
374
time_t xclock_valid = 0;
375
#ifndef clocktime
376
time_t
377
clocktime(void)
378
{
379
	time_t now = time(&clock_valid);
380
	if (xclock_valid > now) {
381
		/*
382
		 * Someone set the clock back!
383
		 */
384
		plog(XLOG_WARNING, "system clock reset");
385
		reschedule_timeouts(now, xclock_valid);
386
	}
387
	return xclock_valid = now;
388
}
389
#endif /* clocktime */