xref: /freebsd/usr.sbin/cron/lib/misc.c (revision 8a7b61203704d362cfbc66c00619f51b24106b55)
184f33deaSJordan K. Hubbard /* Copyright 1988,1990,1993,1994 by Paul Vixie
284f33deaSJordan K. Hubbard  * All rights reserved
3*fe590ffeSEric van Gyzen  */
4*fe590ffeSEric van Gyzen 
5*fe590ffeSEric van Gyzen /*
6*fe590ffeSEric van Gyzen  * Copyright (c) 1997 by Internet Software Consortium
784f33deaSJordan K. Hubbard  *
8*fe590ffeSEric van Gyzen  * Permission to use, copy, modify, and distribute this software for any
9*fe590ffeSEric van Gyzen  * purpose with or without fee is hereby granted, provided that the above
10*fe590ffeSEric van Gyzen  * copyright notice and this permission notice appear in all copies.
1184f33deaSJordan K. Hubbard  *
12*fe590ffeSEric van Gyzen  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
13*fe590ffeSEric van Gyzen  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
14*fe590ffeSEric van Gyzen  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15*fe590ffeSEric van Gyzen  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16*fe590ffeSEric van Gyzen  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17*fe590ffeSEric van Gyzen  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18*fe590ffeSEric van Gyzen  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19*fe590ffeSEric van Gyzen  * SOFTWARE.
2084f33deaSJordan K. Hubbard  */
2184f33deaSJordan K. Hubbard 
2284f33deaSJordan K. Hubbard 
2384f33deaSJordan K. Hubbard /* vix 26jan87 [RCS has the rest of the log]
2484f33deaSJordan K. Hubbard  * vix 30dec86 [written]
2584f33deaSJordan K. Hubbard  */
2684f33deaSJordan K. Hubbard 
2784f33deaSJordan K. Hubbard 
2884f33deaSJordan K. Hubbard #include "cron.h"
2984f33deaSJordan K. Hubbard #if SYS_TIME_H
3084f33deaSJordan K. Hubbard # include <sys/time.h>
3184f33deaSJordan K. Hubbard #else
3284f33deaSJordan K. Hubbard # include <time.h>
3384f33deaSJordan K. Hubbard #endif
3484f33deaSJordan K. Hubbard #include <sys/file.h>
3584f33deaSJordan K. Hubbard #include <sys/stat.h>
3684f33deaSJordan K. Hubbard #include <errno.h>
3784f33deaSJordan K. Hubbard #include <string.h>
3884f33deaSJordan K. Hubbard #include <fcntl.h>
3984f33deaSJordan K. Hubbard #if defined(SYSLOG)
4084f33deaSJordan K. Hubbard # include <syslog.h>
4184f33deaSJordan K. Hubbard #endif
4284f33deaSJordan K. Hubbard 
4384f33deaSJordan K. Hubbard 
44*fe590ffeSEric van Gyzen #if defined(LOG_CRON) && defined(LOG_FILE)
45*fe590ffeSEric van Gyzen # undef LOG_FILE
46*fe590ffeSEric van Gyzen #endif
47*fe590ffeSEric van Gyzen 
4884f33deaSJordan K. Hubbard #if defined(LOG_DAEMON) && !defined(LOG_CRON)
4984f33deaSJordan K. Hubbard # define LOG_CRON LOG_DAEMON
5084f33deaSJordan K. Hubbard #endif
5184f33deaSJordan K. Hubbard 
5284f33deaSJordan K. Hubbard 
5384f33deaSJordan K. Hubbard static int		LogFD = ERR;
5484f33deaSJordan K. Hubbard 
5584f33deaSJordan K. Hubbard 
5684f33deaSJordan K. Hubbard int
strcmp_until(const char * left,const char * right,int until)57*fe590ffeSEric van Gyzen strcmp_until(const char *left, const char *right, int until)
5884f33deaSJordan K. Hubbard {
5984f33deaSJordan K. Hubbard 	while (*left && *left != until && *left == *right) {
6084f33deaSJordan K. Hubbard 		left++;
6184f33deaSJordan K. Hubbard 		right++;
6284f33deaSJordan K. Hubbard 	}
6384f33deaSJordan K. Hubbard 
6484f33deaSJordan K. Hubbard 	if ((*left=='\0' || *left == until) &&
6584f33deaSJordan K. Hubbard 	    (*right=='\0' || *right == until)) {
66*fe590ffeSEric van Gyzen 		return (0);
6784f33deaSJordan K. Hubbard 	}
68*fe590ffeSEric van Gyzen 	return (*left - *right);
6984f33deaSJordan K. Hubbard }
7084f33deaSJordan K. Hubbard 
7184f33deaSJordan K. Hubbard 
7284f33deaSJordan K. Hubbard /* strdtb(s) - delete trailing blanks in string 's' and return new length
7384f33deaSJordan K. Hubbard  */
7484f33deaSJordan K. Hubbard int
strdtb(char * s)75e93f27e3SJohn Baldwin strdtb(char *s)
7684f33deaSJordan K. Hubbard {
7784f33deaSJordan K. Hubbard 	char	*x = s;
7884f33deaSJordan K. Hubbard 
7984f33deaSJordan K. Hubbard 	/* scan forward to the null
8084f33deaSJordan K. Hubbard 	 */
8184f33deaSJordan K. Hubbard 	while (*x)
8284f33deaSJordan K. Hubbard 		x++;
8384f33deaSJordan K. Hubbard 
8484f33deaSJordan K. Hubbard 	/* scan backward to either the first character before the string,
8584f33deaSJordan K. Hubbard 	 * or the last non-blank in the string, whichever comes first.
8684f33deaSJordan K. Hubbard 	 */
8784f33deaSJordan K. Hubbard 	do	{x--;}
8884f33deaSJordan K. Hubbard 	while (x >= s && isspace(*x));
8984f33deaSJordan K. Hubbard 
9084f33deaSJordan K. Hubbard 	/* one character beyond where we stopped above is where the null
9184f33deaSJordan K. Hubbard 	 * goes.
9284f33deaSJordan K. Hubbard 	 */
9384f33deaSJordan K. Hubbard 	*++x = '\0';
9484f33deaSJordan K. Hubbard 
9584f33deaSJordan K. Hubbard 	/* the difference between the position of the null character and
9684f33deaSJordan K. Hubbard 	 * the position of the first character of the string is the length.
9784f33deaSJordan K. Hubbard 	 */
9884f33deaSJordan K. Hubbard 	return x - s;
9984f33deaSJordan K. Hubbard }
10084f33deaSJordan K. Hubbard 
10184f33deaSJordan K. Hubbard 
10284f33deaSJordan K. Hubbard int
set_debug_flags(char * flags)103e93f27e3SJohn Baldwin set_debug_flags(char *flags)
10484f33deaSJordan K. Hubbard {
10584f33deaSJordan K. Hubbard 	/* debug flags are of the form    flag[,flag ...]
10684f33deaSJordan K. Hubbard 	 *
10784f33deaSJordan K. Hubbard 	 * if an error occurs, print a message to stdout and return FALSE.
10884f33deaSJordan K. Hubbard 	 * otherwise return TRUE after setting ERROR_FLAGS.
10984f33deaSJordan K. Hubbard 	 */
11084f33deaSJordan K. Hubbard 
11184f33deaSJordan K. Hubbard #if !DEBUGGING
11284f33deaSJordan K. Hubbard 
11384f33deaSJordan K. Hubbard 	printf("this program was compiled without debugging enabled\n");
11484f33deaSJordan K. Hubbard 	return FALSE;
11584f33deaSJordan K. Hubbard 
11684f33deaSJordan K. Hubbard #else /* DEBUGGING */
11784f33deaSJordan K. Hubbard 
11884f33deaSJordan K. Hubbard 	char	*pc = flags;
11984f33deaSJordan K. Hubbard 
12084f33deaSJordan K. Hubbard 	DebugFlags = 0;
12184f33deaSJordan K. Hubbard 
12284f33deaSJordan K. Hubbard 	while (*pc) {
123*fe590ffeSEric van Gyzen 		const char	**test;
12484f33deaSJordan K. Hubbard 		int		mask;
12584f33deaSJordan K. Hubbard 
12684f33deaSJordan K. Hubbard 		/* try to find debug flag name in our list.
12784f33deaSJordan K. Hubbard 		 */
12884f33deaSJordan K. Hubbard 		for (	test = DebugFlagNames, mask = 1;
129*fe590ffeSEric van Gyzen 			*test != NULL && strcmp_until(*test, pc, ',');
13084f33deaSJordan K. Hubbard 			test++, mask <<= 1
13184f33deaSJordan K. Hubbard 		    )
13284f33deaSJordan K. Hubbard 			;
13384f33deaSJordan K. Hubbard 
13484f33deaSJordan K. Hubbard 		if (!*test) {
13584f33deaSJordan K. Hubbard 			fprintf(stderr,
13684f33deaSJordan K. Hubbard 				"unrecognized debug flag <%s> <%s>\n",
13784f33deaSJordan K. Hubbard 				flags, pc);
13884f33deaSJordan K. Hubbard 			return FALSE;
13984f33deaSJordan K. Hubbard 		}
14084f33deaSJordan K. Hubbard 
14184f33deaSJordan K. Hubbard 		DebugFlags |= mask;
14284f33deaSJordan K. Hubbard 
14384f33deaSJordan K. Hubbard 		/* skip to the next flag
14484f33deaSJordan K. Hubbard 		 */
14584f33deaSJordan K. Hubbard 		while (*pc && *pc != ',')
14684f33deaSJordan K. Hubbard 			pc++;
14784f33deaSJordan K. Hubbard 		if (*pc == ',')
14884f33deaSJordan K. Hubbard 			pc++;
14984f33deaSJordan K. Hubbard 	}
15084f33deaSJordan K. Hubbard 
15184f33deaSJordan K. Hubbard 	if (DebugFlags) {
15284f33deaSJordan K. Hubbard 		int	flag;
15384f33deaSJordan K. Hubbard 
15484f33deaSJordan K. Hubbard 		fprintf(stderr, "debug flags enabled:");
15584f33deaSJordan K. Hubbard 
15684f33deaSJordan K. Hubbard 		for (flag = 0;  DebugFlagNames[flag];  flag++)
15784f33deaSJordan K. Hubbard 			if (DebugFlags & (1 << flag))
15884f33deaSJordan K. Hubbard 				fprintf(stderr, " %s", DebugFlagNames[flag]);
15984f33deaSJordan K. Hubbard 		fprintf(stderr, "\n");
16084f33deaSJordan K. Hubbard 	}
16184f33deaSJordan K. Hubbard 
16284f33deaSJordan K. Hubbard 	return TRUE;
16384f33deaSJordan K. Hubbard 
16484f33deaSJordan K. Hubbard #endif /* DEBUGGING */
16584f33deaSJordan K. Hubbard }
16684f33deaSJordan K. Hubbard 
16784f33deaSJordan K. Hubbard 
16884f33deaSJordan K. Hubbard void
set_cron_uid(void)169e93f27e3SJohn Baldwin set_cron_uid(void)
17084f33deaSJordan K. Hubbard {
17184f33deaSJordan K. Hubbard #if defined(BSD) || defined(POSIX)
172401e6468SPhilippe Charnier 	if (seteuid(ROOT_UID) < OK)
173401e6468SPhilippe Charnier 		err(ERROR_EXIT, "seteuid");
17484f33deaSJordan K. Hubbard #else
175401e6468SPhilippe Charnier 	if (setuid(ROOT_UID) < OK)
176401e6468SPhilippe Charnier 		err(ERROR_EXIT, "setuid");
17784f33deaSJordan K. Hubbard #endif
17884f33deaSJordan K. Hubbard }
17984f33deaSJordan K. Hubbard 
18084f33deaSJordan K. Hubbard 
18184f33deaSJordan K. Hubbard void
set_cron_cwd(void)182e93f27e3SJohn Baldwin set_cron_cwd(void)
18384f33deaSJordan K. Hubbard {
18484f33deaSJordan K. Hubbard 	struct stat	sb;
18584f33deaSJordan K. Hubbard 
18684f33deaSJordan K. Hubbard 	/* first check for CRONDIR ("/var/cron" or some such)
18784f33deaSJordan K. Hubbard 	 */
18884f33deaSJordan K. Hubbard 	if (stat(CRONDIR, &sb) < OK && errno == ENOENT) {
189401e6468SPhilippe Charnier 		warn("%s", CRONDIR);
19084f33deaSJordan K. Hubbard 		if (OK == mkdir(CRONDIR, 0700)) {
191401e6468SPhilippe Charnier 			warnx("%s: created", CRONDIR);
19284f33deaSJordan K. Hubbard 			stat(CRONDIR, &sb);
19384f33deaSJordan K. Hubbard 		} else {
194401e6468SPhilippe Charnier 			err(ERROR_EXIT, "%s: mkdir", CRONDIR);
19584f33deaSJordan K. Hubbard 		}
19684f33deaSJordan K. Hubbard 	}
197401e6468SPhilippe Charnier 	if (!(sb.st_mode & S_IFDIR))
198401e6468SPhilippe Charnier 		err(ERROR_EXIT, "'%s' is not a directory, bailing out", CRONDIR);
199401e6468SPhilippe Charnier 	if (chdir(CRONDIR) < OK)
200401e6468SPhilippe Charnier 		err(ERROR_EXIT, "cannot chdir(%s), bailing out", CRONDIR);
20184f33deaSJordan K. Hubbard 
20284f33deaSJordan K. Hubbard 	/* CRONDIR okay (now==CWD), now look at SPOOL_DIR ("tabs" or some such)
20384f33deaSJordan K. Hubbard 	 */
20484f33deaSJordan K. Hubbard 	if (stat(SPOOL_DIR, &sb) < OK && errno == ENOENT) {
205401e6468SPhilippe Charnier 		warn("%s", SPOOL_DIR);
20684f33deaSJordan K. Hubbard 		if (OK == mkdir(SPOOL_DIR, 0700)) {
207401e6468SPhilippe Charnier 			warnx("%s: created", SPOOL_DIR);
20884f33deaSJordan K. Hubbard 			stat(SPOOL_DIR, &sb);
20984f33deaSJordan K. Hubbard 		} else {
210401e6468SPhilippe Charnier 			err(ERROR_EXIT, "%s: mkdir", SPOOL_DIR);
21184f33deaSJordan K. Hubbard 		}
21284f33deaSJordan K. Hubbard 	}
213401e6468SPhilippe Charnier 	if (!(sb.st_mode & S_IFDIR))
214401e6468SPhilippe Charnier 		err(ERROR_EXIT, "'%s' is not a directory, bailing out", SPOOL_DIR);
21584f33deaSJordan K. Hubbard }
21684f33deaSJordan K. Hubbard 
21784f33deaSJordan K. Hubbard 
21884f33deaSJordan K. Hubbard /* get_char(file) : like getc() but increment LineNumber on newlines
21984f33deaSJordan K. Hubbard  */
22084f33deaSJordan K. Hubbard int
get_char(FILE * file)221e93f27e3SJohn Baldwin get_char(FILE *file)
22284f33deaSJordan K. Hubbard {
22384f33deaSJordan K. Hubbard 	int	ch;
22484f33deaSJordan K. Hubbard 
22584f33deaSJordan K. Hubbard 	ch = getc(file);
22684f33deaSJordan K. Hubbard 	if (ch == '\n')
22784f33deaSJordan K. Hubbard 		Set_LineNum(LineNumber + 1)
22884f33deaSJordan K. Hubbard 	return ch;
22984f33deaSJordan K. Hubbard }
23084f33deaSJordan K. Hubbard 
23184f33deaSJordan K. Hubbard 
23284f33deaSJordan K. Hubbard /* unget_char(ch, file) : like ungetc but do LineNumber processing
23384f33deaSJordan K. Hubbard  */
23484f33deaSJordan K. Hubbard void
unget_char(int ch,FILE * file)235e93f27e3SJohn Baldwin unget_char(int ch, FILE *file)
23684f33deaSJordan K. Hubbard {
23784f33deaSJordan K. Hubbard 	ungetc(ch, file);
23884f33deaSJordan K. Hubbard 	if (ch == '\n')
23984f33deaSJordan K. Hubbard 		Set_LineNum(LineNumber - 1)
24084f33deaSJordan K. Hubbard }
24184f33deaSJordan K. Hubbard 
24284f33deaSJordan K. Hubbard 
24384f33deaSJordan K. Hubbard /* get_string(str, max, file, termstr) : like fgets() but
24484f33deaSJordan K. Hubbard  *		(1) has terminator string which should include \n
24584f33deaSJordan K. Hubbard  *		(2) will always leave room for the null
24684f33deaSJordan K. Hubbard  *		(3) uses get_char() so LineNumber will be accurate
24784f33deaSJordan K. Hubbard  *		(4) returns EOF or terminating character, whichever
24884f33deaSJordan K. Hubbard  */
24984f33deaSJordan K. Hubbard int
get_string(char * string,int size,FILE * file,char * terms)250e93f27e3SJohn Baldwin get_string(char *string, int size, FILE *file, char *terms)
25184f33deaSJordan K. Hubbard {
25284f33deaSJordan K. Hubbard 	int	ch;
25384f33deaSJordan K. Hubbard 
25484f33deaSJordan K. Hubbard 	while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
25584f33deaSJordan K. Hubbard 		if (size > 1) {
25684f33deaSJordan K. Hubbard 			*string++ = (char) ch;
25784f33deaSJordan K. Hubbard 			size--;
25884f33deaSJordan K. Hubbard 		}
25984f33deaSJordan K. Hubbard 	}
26084f33deaSJordan K. Hubbard 
26184f33deaSJordan K. Hubbard 	if (size > 0)
26284f33deaSJordan K. Hubbard 		*string = '\0';
26384f33deaSJordan K. Hubbard 
26484f33deaSJordan K. Hubbard 	return ch;
26584f33deaSJordan K. Hubbard }
26684f33deaSJordan K. Hubbard 
26784f33deaSJordan K. Hubbard 
26884f33deaSJordan K. Hubbard /* skip_comments(file) : read past comment (if any)
26984f33deaSJordan K. Hubbard  */
27084f33deaSJordan K. Hubbard void
skip_comments(FILE * file)271e93f27e3SJohn Baldwin skip_comments(FILE *file)
27284f33deaSJordan K. Hubbard {
27384f33deaSJordan K. Hubbard 	int	ch;
27484f33deaSJordan K. Hubbard 
27584f33deaSJordan K. Hubbard 	while (EOF != (ch = get_char(file))) {
27684f33deaSJordan K. Hubbard 		/* ch is now the first character of a line.
27784f33deaSJordan K. Hubbard 		 */
27884f33deaSJordan K. Hubbard 
27984f33deaSJordan K. Hubbard 		while (ch == ' ' || ch == '\t')
28084f33deaSJordan K. Hubbard 			ch = get_char(file);
28184f33deaSJordan K. Hubbard 
28284f33deaSJordan K. Hubbard 		if (ch == EOF)
28384f33deaSJordan K. Hubbard 			break;
28484f33deaSJordan K. Hubbard 
28584f33deaSJordan K. Hubbard 		/* ch is now the first non-blank character of a line.
28684f33deaSJordan K. Hubbard 		 */
28784f33deaSJordan K. Hubbard 
28884f33deaSJordan K. Hubbard 		if (ch != '\n' && ch != '#')
28984f33deaSJordan K. Hubbard 			break;
29084f33deaSJordan K. Hubbard 
29184f33deaSJordan K. Hubbard 		/* ch must be a newline or comment as first non-blank
29284f33deaSJordan K. Hubbard 		 * character on a line.
29384f33deaSJordan K. Hubbard 		 */
29484f33deaSJordan K. Hubbard 
29584f33deaSJordan K. Hubbard 		while (ch != '\n' && ch != EOF)
29684f33deaSJordan K. Hubbard 			ch = get_char(file);
29784f33deaSJordan K. Hubbard 
29884f33deaSJordan K. Hubbard 		/* ch is now the newline of a line which we're going to
29984f33deaSJordan K. Hubbard 		 * ignore.
30084f33deaSJordan K. Hubbard 		 */
30184f33deaSJordan K. Hubbard 	}
30284f33deaSJordan K. Hubbard 	if (ch != EOF)
30384f33deaSJordan K. Hubbard 		unget_char(ch, file);
30484f33deaSJordan K. Hubbard }
30584f33deaSJordan K. Hubbard 
30684f33deaSJordan K. Hubbard 
30784f33deaSJordan K. Hubbard /* int in_file(char *string, FILE *file)
30884f33deaSJordan K. Hubbard  *	return TRUE if one of the lines in file matches string exactly,
30984f33deaSJordan K. Hubbard  *	FALSE otherwise.
31084f33deaSJordan K. Hubbard  */
31184f33deaSJordan K. Hubbard static int
in_file(char * string,FILE * file)31266d48cdaSMatteo Riondato in_file(char *string, FILE *file)
31384f33deaSJordan K. Hubbard {
31484f33deaSJordan K. Hubbard 	char line[MAX_TEMPSTR];
31584f33deaSJordan K. Hubbard 
31684f33deaSJordan K. Hubbard 	rewind(file);
31784f33deaSJordan K. Hubbard 	while (fgets(line, MAX_TEMPSTR, file)) {
31884f33deaSJordan K. Hubbard 		if (line[0] != '\0')
319879e98b6SDavid Malone 			if (line[strlen(line)-1] == '\n')
32084f33deaSJordan K. Hubbard 				line[strlen(line)-1] = '\0';
32184f33deaSJordan K. Hubbard 		if (0 == strcmp(line, string))
32284f33deaSJordan K. Hubbard 			return TRUE;
32384f33deaSJordan K. Hubbard 	}
32484f33deaSJordan K. Hubbard 	return FALSE;
32584f33deaSJordan K. Hubbard }
32684f33deaSJordan K. Hubbard 
32784f33deaSJordan K. Hubbard 
32884f33deaSJordan K. Hubbard /* int allowed(char *username)
32984f33deaSJordan K. Hubbard  *	returns TRUE if (ALLOW_FILE exists and user is listed)
33084f33deaSJordan K. Hubbard  *	or (DENY_FILE exists and user is NOT listed)
33184f33deaSJordan K. Hubbard  *	or (neither file exists but user=="root" so it's okay)
33284f33deaSJordan K. Hubbard  */
33384f33deaSJordan K. Hubbard int
allowed(char * username)334e93f27e3SJohn Baldwin allowed(char *username)
33584f33deaSJordan K. Hubbard {
336526b145cSTim J. Robbins 	FILE	*allow, *deny;
337526b145cSTim J. Robbins 	int	isallowed;
33884f33deaSJordan K. Hubbard 
339526b145cSTim J. Robbins 	isallowed = FALSE;
340526b145cSTim J. Robbins 
34193931378SStefan Farfeleder 	deny = NULL;
34284f33deaSJordan K. Hubbard #if defined(ALLOW_FILE) && defined(DENY_FILE)
343526b145cSTim J. Robbins 	if ((allow = fopen(ALLOW_FILE, "r")) == NULL && errno != ENOENT)
344526b145cSTim J. Robbins 		goto out;
345526b145cSTim J. Robbins 	if ((deny = fopen(DENY_FILE, "r")) == NULL && errno != ENOENT)
346526b145cSTim J. Robbins 		goto out;
34784f33deaSJordan K. Hubbard 	Debug(DMISC, ("allow/deny enabled, %d/%d\n", !!allow, !!deny))
34884f33deaSJordan K. Hubbard #else
34984f33deaSJordan K. Hubbard 	allow = NULL;
35084f33deaSJordan K. Hubbard #endif
35184f33deaSJordan K. Hubbard 
35284f33deaSJordan K. Hubbard 	if (allow)
353526b145cSTim J. Robbins 		isallowed = in_file(username, allow);
354526b145cSTim J. Robbins 	else if (deny)
355526b145cSTim J. Robbins 		isallowed = !in_file(username, deny);
356526b145cSTim J. Robbins 	else {
35784f33deaSJordan K. Hubbard #if defined(ALLOW_ONLY_ROOT)
358526b145cSTim J. Robbins 		isallowed = (strcmp(username, ROOT_USER) == 0);
35984f33deaSJordan K. Hubbard #else
360526b145cSTim J. Robbins 		isallowed = TRUE;
36184f33deaSJordan K. Hubbard #endif
36284f33deaSJordan K. Hubbard 	}
363526b145cSTim J. Robbins out:	if (allow)
364526b145cSTim J. Robbins 		fclose(allow);
365526b145cSTim J. Robbins 	if (deny)
366526b145cSTim J. Robbins 		fclose(deny);
367526b145cSTim J. Robbins 	return (isallowed);
368526b145cSTim J. Robbins }
36984f33deaSJordan K. Hubbard 
37084f33deaSJordan K. Hubbard 
37184f33deaSJordan K. Hubbard void
log_it(const char * username,int xpid,const char * event,const char * detail)372*fe590ffeSEric van Gyzen log_it(const char *username, int xpid, const char *event, const char *detail)
37384f33deaSJordan K. Hubbard {
37424e4c29cSSergey Kandaurov #if defined(LOG_FILE) || DEBUGGING
37584f33deaSJordan K. Hubbard 	PID_T		pid = xpid;
37624e4c29cSSergey Kandaurov #endif
37784f33deaSJordan K. Hubbard #if defined(LOG_FILE)
37884f33deaSJordan K. Hubbard 	char		*msg;
37984f33deaSJordan K. Hubbard 	TIME_T		now = time((TIME_T) 0);
380*fe590ffeSEric van Gyzen 	struct tm	*t = localtime(&now);
38184f33deaSJordan K. Hubbard #endif /*LOG_FILE*/
38284f33deaSJordan K. Hubbard 
38384f33deaSJordan K. Hubbard #if defined(SYSLOG)
38484f33deaSJordan K. Hubbard 	static int	syslog_open = 0;
38584f33deaSJordan K. Hubbard #endif
38684f33deaSJordan K. Hubbard 
38784f33deaSJordan K. Hubbard #if defined(LOG_FILE)
38884f33deaSJordan K. Hubbard 	/* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
38984f33deaSJordan K. Hubbard 	 */
39084f33deaSJordan K. Hubbard 	msg = malloc(strlen(username)
39184f33deaSJordan K. Hubbard 		     + strlen(event)
39284f33deaSJordan K. Hubbard 		     + strlen(detail)
39384f33deaSJordan K. Hubbard 		     + MAX_TEMPSTR);
39484f33deaSJordan K. Hubbard 
3955c7cba96SGuy Helmer 	if (msg == NULL)
3965c7cba96SGuy Helmer 		warnx("failed to allocate memory for log message");
3975c7cba96SGuy Helmer 	else {
39884f33deaSJordan K. Hubbard 		if (LogFD < OK) {
39984f33deaSJordan K. Hubbard 			LogFD = open(LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0600);
40084f33deaSJordan K. Hubbard 			if (LogFD < OK) {
401401e6468SPhilippe Charnier 				warn("can't open log file %s", LOG_FILE);
40284f33deaSJordan K. Hubbard 			} else {
40384f33deaSJordan K. Hubbard 				(void) fcntl(LogFD, F_SETFD, 1);
40484f33deaSJordan K. Hubbard 			}
40584f33deaSJordan K. Hubbard 		}
40684f33deaSJordan K. Hubbard 
4075c7cba96SGuy Helmer 		/* we have to sprintf() it because fprintf() doesn't always
4085c7cba96SGuy Helmer 		 * write everything out in one chunk and this has to be
4095c7cba96SGuy Helmer 		 * atomically appended to the log file.
41084f33deaSJordan K. Hubbard 		 */
41184f33deaSJordan K. Hubbard 		sprintf(msg, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
41284f33deaSJordan K. Hubbard 			username,
4135c7cba96SGuy Helmer 			t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min,
4145c7cba96SGuy Helmer 			t->tm_sec, pid, event, detail);
41584f33deaSJordan K. Hubbard 
4165c7cba96SGuy Helmer 		/* we have to run strlen() because sprintf() returns (char*)
4175c7cba96SGuy Helmer 		 * on old BSD.
41884f33deaSJordan K. Hubbard 		 */
41984f33deaSJordan K. Hubbard 		if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) {
42084f33deaSJordan K. Hubbard 			if (LogFD >= OK)
421401e6468SPhilippe Charnier 				warn("%s", LOG_FILE);
422401e6468SPhilippe Charnier 			warnx("can't write to log file");
42384f33deaSJordan K. Hubbard 			write(STDERR, msg, strlen(msg));
42484f33deaSJordan K. Hubbard 		}
42584f33deaSJordan K. Hubbard 
42684f33deaSJordan K. Hubbard 		free(msg);
4275c7cba96SGuy Helmer 	}
42884f33deaSJordan K. Hubbard #endif /*LOG_FILE*/
42984f33deaSJordan K. Hubbard 
43084f33deaSJordan K. Hubbard #if defined(SYSLOG)
43184f33deaSJordan K. Hubbard 	if (!syslog_open) {
43284f33deaSJordan K. Hubbard 		/* we don't use LOG_PID since the pid passed to us by
43384f33deaSJordan K. Hubbard 		 * our client may not be our own.  therefore we want to
43484f33deaSJordan K. Hubbard 		 * print the pid ourselves.
43584f33deaSJordan K. Hubbard 		 */
43684f33deaSJordan K. Hubbard # ifdef LOG_DAEMON
43784f33deaSJordan K. Hubbard 		openlog(ProgramName, LOG_PID, LOG_CRON);
43884f33deaSJordan K. Hubbard # else
43984f33deaSJordan K. Hubbard 		openlog(ProgramName, LOG_PID);
44084f33deaSJordan K. Hubbard # endif
44184f33deaSJordan K. Hubbard 		syslog_open = TRUE;		/* assume openlog success */
44284f33deaSJordan K. Hubbard 	}
44384f33deaSJordan K. Hubbard 
44484f33deaSJordan K. Hubbard 	syslog(LOG_INFO, "(%s) %s (%s)\n", username, event, detail);
44584f33deaSJordan K. Hubbard 
44684f33deaSJordan K. Hubbard #endif /*SYSLOG*/
44784f33deaSJordan K. Hubbard 
44884f33deaSJordan K. Hubbard #if DEBUGGING
44984f33deaSJordan K. Hubbard 	if (DebugFlags) {
45084f33deaSJordan K. Hubbard 		fprintf(stderr, "log_it: (%s %d) %s (%s)\n",
45184f33deaSJordan K. Hubbard 			username, pid, event, detail);
45284f33deaSJordan K. Hubbard 	}
45384f33deaSJordan K. Hubbard #endif
45484f33deaSJordan K. Hubbard }
45584f33deaSJordan K. Hubbard 
45684f33deaSJordan K. Hubbard 
45784f33deaSJordan K. Hubbard void
log_close(void)458e93f27e3SJohn Baldwin log_close(void)
459e93f27e3SJohn Baldwin {
46084f33deaSJordan K. Hubbard 	if (LogFD != ERR) {
46184f33deaSJordan K. Hubbard 		close(LogFD);
46284f33deaSJordan K. Hubbard 		LogFD = ERR;
46384f33deaSJordan K. Hubbard 	}
46484f33deaSJordan K. Hubbard }
46584f33deaSJordan K. Hubbard 
46684f33deaSJordan K. Hubbard 
46784f33deaSJordan K. Hubbard /* two warnings:
46884f33deaSJordan K. Hubbard  *	(1) this routine is fairly slow
46984f33deaSJordan K. Hubbard  *	(2) it returns a pointer to static storage
470*fe590ffeSEric van Gyzen  * parameters:
471*fe590ffeSEric van Gyzen  *	s: string we want the first word of
472*fe590ffeSEric van Gyzen  *	t: terminators, implicitly including \0
47384f33deaSJordan K. Hubbard  */
47484f33deaSJordan K. Hubbard char *
first_word(char * s,char * t)475e93f27e3SJohn Baldwin first_word(char *s, char *t)
47684f33deaSJordan K. Hubbard {
47784f33deaSJordan K. Hubbard 	static char retbuf[2][MAX_TEMPSTR + 1];	/* sure wish C had GC */
47884f33deaSJordan K. Hubbard 	static int retsel = 0;
479*fe590ffeSEric van Gyzen 	char *rb, *rp;
48084f33deaSJordan K. Hubbard 
48184f33deaSJordan K. Hubbard 	/* select a return buffer */
48284f33deaSJordan K. Hubbard 	retsel = 1-retsel;
48384f33deaSJordan K. Hubbard 	rb = &retbuf[retsel][0];
48484f33deaSJordan K. Hubbard 	rp = rb;
48584f33deaSJordan K. Hubbard 
48684f33deaSJordan K. Hubbard 	/* skip any leading terminators */
48784f33deaSJordan K. Hubbard 	while (*s && (NULL != strchr(t, *s))) {
48884f33deaSJordan K. Hubbard 		s++;
48984f33deaSJordan K. Hubbard 	}
49084f33deaSJordan K. Hubbard 
49184f33deaSJordan K. Hubbard 	/* copy until next terminator or full buffer */
49284f33deaSJordan K. Hubbard 	while (*s && (NULL == strchr(t, *s)) && (rp < &rb[MAX_TEMPSTR])) {
49384f33deaSJordan K. Hubbard 		*rp++ = *s++;
49484f33deaSJordan K. Hubbard 	}
49584f33deaSJordan K. Hubbard 
49684f33deaSJordan K. Hubbard 	/* finish the return-string and return it */
49784f33deaSJordan K. Hubbard 	*rp = '\0';
49884f33deaSJordan K. Hubbard 	return rb;
49984f33deaSJordan K. Hubbard }
50084f33deaSJordan K. Hubbard 
50184f33deaSJordan K. Hubbard 
50284f33deaSJordan K. Hubbard /* warning:
50384f33deaSJordan K. Hubbard  *	heavily ascii-dependent.
50484f33deaSJordan K. Hubbard  */
505c082b52cSMatteo Riondato static void
mkprint(char * dst,unsigned char * src,int len)506*fe590ffeSEric van Gyzen mkprint(char *dst, unsigned char *src, int len)
50784f33deaSJordan K. Hubbard {
508*fe590ffeSEric van Gyzen 	/*
509*fe590ffeSEric van Gyzen 	 * XXX
510*fe590ffeSEric van Gyzen 	 * We know this routine can't overflow the dst buffer because mkprints()
511*fe590ffeSEric van Gyzen 	 * allocated enough space for the worst case.
512*fe590ffeSEric van Gyzen 	 */
51384f33deaSJordan K. Hubbard 	while (len-- > 0)
51484f33deaSJordan K. Hubbard 	{
515*fe590ffeSEric van Gyzen 		unsigned char ch = *src++;
51684f33deaSJordan K. Hubbard 
51784f33deaSJordan K. Hubbard 		if (ch < ' ') {			/* control character */
51884f33deaSJordan K. Hubbard 			*dst++ = '^';
51984f33deaSJordan K. Hubbard 			*dst++ = ch + '@';
52084f33deaSJordan K. Hubbard 		} else if (ch < 0177) {		/* printable */
52184f33deaSJordan K. Hubbard 			*dst++ = ch;
52284f33deaSJordan K. Hubbard 		} else if (ch == 0177) {	/* delete/rubout */
52384f33deaSJordan K. Hubbard 			*dst++ = '^';
52484f33deaSJordan K. Hubbard 			*dst++ = '?';
52584f33deaSJordan K. Hubbard 		} else {			/* parity character */
52684f33deaSJordan K. Hubbard 			sprintf(dst, "\\%03o", ch);
52784f33deaSJordan K. Hubbard 			dst += 4;
52884f33deaSJordan K. Hubbard 		}
52984f33deaSJordan K. Hubbard 	}
53084f33deaSJordan K. Hubbard 	*dst = '\0';
53184f33deaSJordan K. Hubbard }
53284f33deaSJordan K. Hubbard 
53384f33deaSJordan K. Hubbard 
53484f33deaSJordan K. Hubbard /* warning:
53584f33deaSJordan K. Hubbard  *	returns a pointer to malloc'd storage, you must call free yourself.
53684f33deaSJordan K. Hubbard  */
53784f33deaSJordan K. Hubbard char *
mkprints(unsigned char * src,unsigned int len)538e93f27e3SJohn Baldwin mkprints(unsigned char *src, unsigned int len)
53984f33deaSJordan K. Hubbard {
540*fe590ffeSEric van Gyzen 	char *dst = malloc(len*4 + 1);
54184f33deaSJordan K. Hubbard 
5425c7cba96SGuy Helmer 	if (dst != NULL)
54384f33deaSJordan K. Hubbard 		mkprint(dst, src, len);
54484f33deaSJordan K. Hubbard 
54584f33deaSJordan K. Hubbard 	return dst;
54684f33deaSJordan K. Hubbard }
54784f33deaSJordan K. Hubbard 
54884f33deaSJordan K. Hubbard 
54984f33deaSJordan K. Hubbard #ifdef MAIL_DATE
55084f33deaSJordan K. Hubbard /* Sat, 27 Feb 93 11:44:51 CST
55184f33deaSJordan K. Hubbard  * 123456789012345678901234567
55284f33deaSJordan K. Hubbard  */
55384f33deaSJordan K. Hubbard char *
arpadate(time_t * clock)554e93f27e3SJohn Baldwin arpadate(time_t *clock)
55584f33deaSJordan K. Hubbard {
55684f33deaSJordan K. Hubbard 	time_t t = clock ?*clock :time(0L);
55784f33deaSJordan K. Hubbard 	struct tm *tm = localtime(&t);
558*fe590ffeSEric van Gyzen 	static char ret[60];	/* zone name might be >3 chars */
55984f33deaSJordan K. Hubbard 
560b9a1702cSDaniel O'Callaghan 	if (tm->tm_year >= 100)
561b9a1702cSDaniel O'Callaghan 		tm->tm_year += 1900;
562b9a1702cSDaniel O'Callaghan 
563b9a1702cSDaniel O'Callaghan 	(void) snprintf(ret, sizeof(ret), "%s, %2d %s %d %02d:%02d:%02d %s",
56484f33deaSJordan K. Hubbard 		       DowNames[tm->tm_wday],
56584f33deaSJordan K. Hubbard 		       tm->tm_mday,
56684f33deaSJordan K. Hubbard 		       MonthNames[tm->tm_mon],
56784f33deaSJordan K. Hubbard 		       tm->tm_year,
56884f33deaSJordan K. Hubbard 		       tm->tm_hour,
56984f33deaSJordan K. Hubbard 		       tm->tm_min,
57084f33deaSJordan K. Hubbard 		       tm->tm_sec,
57184f33deaSJordan K. Hubbard 		       TZONE(*tm));
57284f33deaSJordan K. Hubbard 	return ret;
57384f33deaSJordan K. Hubbard }
57484f33deaSJordan K. Hubbard #endif /*MAIL_DATE*/
57584f33deaSJordan K. Hubbard 
57684f33deaSJordan K. Hubbard 
577aa4f20e4SAndrey A. Chernov #ifdef HAVE_SAVED_UIDS
57884f33deaSJordan K. Hubbard static int save_euid;
swap_uids(void)579e93f27e3SJohn Baldwin int swap_uids(void) { save_euid = geteuid(); return seteuid(getuid()); }
swap_uids_back(void)580e93f27e3SJohn Baldwin int swap_uids_back(void) { return seteuid(save_euid); }
58184f33deaSJordan K. Hubbard #else /*HAVE_SAVED_UIDS*/
swap_uids(void)582e93f27e3SJohn Baldwin int swap_uids(void) { return setreuid(geteuid(), getuid()); }
swap_uids_back(void)583e93f27e3SJohn Baldwin int swap_uids_back(void) { return swap_uids(); }
58484f33deaSJordan K. Hubbard #endif /*HAVE_SAVED_UIDS*/
585