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