diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-02-18 19:48:37 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-02-18 19:48:37 +0000 |
commit | 9d12880bde356edc1caf95ce9c16eda5cd362a71 (patch) | |
tree | 76105126f0a9e8669fcf6a00b6332268446f91d1 /usr.sbin | |
parent | 401b427202f6878b62792414313a54831b405451 (diff) |
Update to ISC cron 4.0b1 + our patches. This is now under a BSD license.
I also fixed the signal handlers while I was at it.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/cron/compat.c | 238 | ||||
-rw-r--r-- | usr.sbin/cron/compat.h | 137 | ||||
-rw-r--r-- | usr.sbin/cron/config.h | 62 | ||||
-rw-r--r-- | usr.sbin/cron/cron.8 | 43 | ||||
-rw-r--r-- | usr.sbin/cron/cron.c | 296 | ||||
-rw-r--r-- | usr.sbin/cron/cron.h | 298 | ||||
-rw-r--r-- | usr.sbin/cron/crontab.1 | 28 | ||||
-rw-r--r-- | usr.sbin/cron/crontab.5 | 30 | ||||
-rw-r--r-- | usr.sbin/cron/crontab.c | 367 | ||||
-rw-r--r-- | usr.sbin/cron/database.c | 118 | ||||
-rw-r--r-- | usr.sbin/cron/do_command.c | 291 | ||||
-rw-r--r-- | usr.sbin/cron/entry.c | 156 | ||||
-rw-r--r-- | usr.sbin/cron/env.c | 104 | ||||
-rw-r--r-- | usr.sbin/cron/externs.h | 207 | ||||
-rw-r--r-- | usr.sbin/cron/funcs.h | 70 | ||||
-rw-r--r-- | usr.sbin/cron/globals.h | 77 | ||||
-rw-r--r-- | usr.sbin/cron/job.c | 54 | ||||
-rw-r--r-- | usr.sbin/cron/macros.h | 125 | ||||
-rw-r--r-- | usr.sbin/cron/misc.c | 218 | ||||
-rw-r--r-- | usr.sbin/cron/pathnames.h | 51 | ||||
-rw-r--r-- | usr.sbin/cron/popen.c | 56 | ||||
-rw-r--r-- | usr.sbin/cron/structs.h | 64 | ||||
-rw-r--r-- | usr.sbin/cron/user.c | 83 |
23 files changed, 1435 insertions, 1738 deletions
diff --git a/usr.sbin/cron/compat.c b/usr.sbin/cron/compat.c deleted file mode 100644 index 141f120cc7b..00000000000 --- a/usr.sbin/cron/compat.c +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright 1988,1990,1993,1994 by Paul Vixie - * All rights reserved - * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. - * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul - */ - -#if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: compat.c,v 1.3 2000/08/21 21:08:55 deraadt Exp $"; -#endif - -/* vix 30dec93 [broke this out of misc.c - see RCS log for history] - * vix 15jan87 [added TIOCNOTTY, thanks csg@pyramid] - */ - - -#include "cron.h" -#ifdef NEED_GETDTABLESIZE -# include <limits.h> -#endif -#if defined(NEED_SETSID) && defined(BSD) -# include <sys/ioctl.h> -#endif -#include <errno.h> - - -/* the code does not depend on any of vfork's - * side-effects; it just uses it as a quick - * fork-and-exec. - */ -#ifdef NEED_VFORK -PID_T -vfork() { - return (fork()); -} -#endif - - -#ifdef NEED_STRDUP -char * -strdup(str) - char *str; -{ - char *temp; - - if ((temp = malloc(strlen(str) + 1)) == NULL) { - errno = ENOMEM; - return NULL; - } - (void) strcpy(temp, str); - return temp; -} -#endif - - -#ifdef NEED_STRERROR -char * -strerror(error) - int error; -{ - extern char *sys_errlist[]; - extern int sys_nerr; - static char buf[32]; - - if ((error <= sys_nerr) && (error > 0)) { - return sys_errlist[error]; - } - - snprintf(buf, sizeof buf, "Unknown error: %d", error); - return buf; -} -#endif - - -#ifdef NEED_STRCASECMP -int -strcasecmp(left, right) - char *left; - char *right; -{ - while (*left && (MkLower(*left) == MkLower(*right))) { - left++; - right++; - } - return MkLower(*left) - MkLower(*right); -} -#endif - - -#ifdef NEED_SETSID -int -setsid() -{ - int newpgrp; -# if defined(BSD) - int fd; -# if defined(POSIX) - newpgrp = setpgid((pid_t)0, getpid()); -# else - newpgrp = setpgrp(0, getpid()); -# endif - if ((fd = open("/dev/tty", 2)) >= 0) - { - (void) ioctl(fd, TIOCNOTTY, (char*)0); - (void) close(fd); - } -# else /*BSD*/ - newpgrp = setpgrp(); - - (void) close(STDIN); (void) open("/dev/null", 0); - (void) close(STDOUT); (void) open("/dev/null", 1); - (void) close(STDERR); (void) open("/dev/null", 2); -# endif /*BSD*/ - return newpgrp; -} -#endif /*NEED_SETSID*/ - - -#ifdef NEED_GETDTABLESIZE -int -getdtablesize() { -#ifdef _SC_OPEN_MAX - return sysconf(_SC_OPEN_MAX); -#else - return _POSIX_OPEN_MAX; -#endif -} -#endif - - -#ifdef NEED_FLOCK -/* The following flock() emulation snarfed intact *) from the HP-UX - * "BSD to HP-UX porting tricks" maintained by - * system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson)) - * from the version "last updated: 11-Jan-1993" - * Snarfage done by Jarkko Hietaniemi <Jarkko.Hietaniemi@hut.fi> - * *) well, almost, had to K&R the function entry, HPUX "cc" - * does not grok ANSI function prototypes */ - -/* - * flock (fd, operation) - * - * This routine performs some file locking like the BSD 'flock' - * on the object described by the int file descriptor 'fd', - * which must already be open. - * - * The operations that are available are: - * - * LOCK_SH - get a shared lock. - * LOCK_EX - get an exclusive lock. - * LOCK_NB - don't block (must be ORed with LOCK_SH or LOCK_EX). - * LOCK_UN - release a lock. - * - * Return value: 0 if lock successful, -1 if failed. - * - * Note that whether the locks are enforced or advisory is - * controlled by the presence or absence of the SETGID bit on - * the executable. - * - * Note that there is no difference between shared and exclusive - * locks, since the 'lockf' system call in SYSV doesn't make any - * distinction. - * - * The file "<sys/file.h>" should be modified to contain the definitions - * of the available operations, which must be added manually (see below - * for the values). - */ - -/* this code has been reformatted by vixie */ - -int -flock(fd, operation) - int fd; - int operation; -{ - int i; - - switch (operation) { - case LOCK_SH: /* get a shared lock */ - case LOCK_EX: /* get an exclusive lock */ - i = lockf (fd, F_LOCK, 0); - break; - - case LOCK_SH|LOCK_NB: /* get a non-blocking shared lock */ - case LOCK_EX|LOCK_NB: /* get a non-blocking exclusive lock */ - i = lockf (fd, F_TLOCK, 0); - if (i == -1) - if ((errno == EAGAIN) || (errno == EACCES)) - errno = EWOULDBLOCK; - break; - - case LOCK_UN: /* unlock */ - i = lockf (fd, F_ULOCK, 0); - break; - - default: /* can't decipher operation */ - i = -1; - errno = EINVAL; - break; - } - - return (i); -} -#endif /*NEED_FLOCK*/ - - -#ifdef NEED_SETENV -int -setenv(name, value, overwrite) - char *name, *value; - int overwrite; -{ - char *tmp; - int len; - - if (overwrite && getenv(name)) - return -1; - - len = strlen(name) + strlen(value) + 2; - if (!(tmp = malloc(len))) { - errno = ENOMEM; - return -1; - } - - snprintf(tmp, len, "%s=%s", name, value); - return putenv(tmp); /* intentionally orphan 'tmp' storage */ -} -#endif diff --git a/usr.sbin/cron/compat.h b/usr.sbin/cron/compat.h deleted file mode 100644 index 552ee0ffb4b..00000000000 --- a/usr.sbin/cron/compat.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright 1993,1994 by Paul Vixie - * All rights reserved - * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. - * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul - */ - -/* - * $Id: compat.h,v 1.1 1995/10/18 08:47:30 deraadt Exp $ - */ - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# define const -# endif -#endif - -#if defined(UNIXPC) || defined(unixpc) -# define UNIXPC 1 -# define ATT 1 -#endif - -#if defined(hpux) || defined(_hpux) || defined(__hpux) -# define HPUX 1 -# define seteuid(e) setresuid(-1,e,-1) -# define setreuid(r,e) setresuid(r,e,-1) -#endif - -#if defined(_IBMR2) -# define AIX 1 -#endif - -#if defined(__convex__) -# define CONVEX 1 -#endif - -#if defined(sgi) || defined(_sgi) || defined(__sgi) -# define IRIX 1 -/* IRIX 4 hdrs are broken: one cannot #include both <stdio.h> - * and <stdlib.h> because they disagree on system(), perror(). - * Therefore we must zap the "const" keyword BEFORE including - * either of them. - */ -# define const -#endif - -#if defined(_UNICOS) -# define UNICOS 1 -#endif - -#ifndef POSIX -# if (BSD >= 199103) || defined(__linux) || defined(ultrix) || defined(AIX) ||\ - defined(HPUX) || defined(CONVEX) || defined(IRIX) -# define POSIX -# endif -#endif - -#ifndef BSD -# if defined(ultrix) -# define BSD 198902 -# endif -#endif - -/*****************************************************************/ - -#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux) -# define NEED_VFORK -#endif - -#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux) && \ - !defined(IRIX) && !defined(NeXT) && !defined(HPUX) -# define NEED_STRCASECMP -#endif - -#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux) &&\ - !defined(IRIX) && !defined(UNICOS) && !defined(HPUX) -# define NEED_STRDUP -#endif - -#if (!defined(BSD) || (BSD < 198911)) && !defined(POSIX) && !defined(NeXT) -# define NEED_STRERROR -#endif - -#if defined(HPUX) || defined(AIX) || defined(UNIXPC) -# define NEED_FLOCK -#endif - -#ifndef POSIX -# define NEED_SETSID -#endif - -#if (defined(POSIX) && !defined(BSD)) && !defined(__linux) -# define NEED_GETDTABLESIZE -#endif - -#if (BSD >= 199103) -# define HAVE_SAVED_UIDS -#endif - -#if !defined(ATT) && !defined(__linux) && !defined(IRIX) && !defined(UNICOS) -# define USE_SIGCHLD -#endif - -#if !defined(AIX) && !defined(UNICOS) -# define SYS_TIME_H 1 -#else -# define SYS_TIME_H 0 -#endif - -#if defined(BSD) && !defined(POSIX) -# define USE_UTIMES -#endif - -#if defined(AIX) || defined(HPUX) || defined(IRIX) -# define NEED_SETENV -#endif - -#if !defined(UNICOS) && !defined(UNIXPC) -# define HAS_FCHOWN -#endif - -#if !defined(UNICOS) && !defined(UNIXPC) -# define HAS_FCHMOD -#endif diff --git a/usr.sbin/cron/config.h b/usr.sbin/cron/config.h index 91120609b74..4f7d67f4ab7 100644 --- a/usr.sbin/cron/config.h +++ b/usr.sbin/cron/config.h @@ -1,29 +1,28 @@ +/* $OpenBSD: config.h,v 1.6 2001/02/18 19:48:31 millert Exp $ */ + /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ /* config.h - configurables for Vixie Cron - * - * $Id: config.h,v 1.5 2000/08/20 18:42:42 millert Exp $ */ -#if !defined(_PATH_SENDMAIL) -# define _PATH_SENDMAIL "/usr/lib/sendmail" -#endif /*SENDMAIL*/ - /* * these are site-dependent */ @@ -33,37 +32,35 @@ #endif /* - * choose one of these MAILCMD commands. I use + * choose one of these mailer commands. some use * /bin/mail for speed; it makes biff bark but doesn't - * do aliasing. /usr/lib/sendmail does aliasing but is + * do aliasing. sendmail does do aliasing but is * a hog for short messages. aliasing is not needed * if you make use of the MAILTO= feature in crontabs. * (hint: MAILTO= was added for this reason). */ -#define MAILCMD _PATH_SENDMAIL /*-*/ -#define MAILARGS "%s -FCronDaemon -odi -oem -oi -t" /*-*/ +#define MAILFMT "%s -FCronDaemon -odi -oem -or0s -t" /*-*/ /* -Fx = set full-name of sender * -odi = Option Deliverymode Interactive * -oem = Option Errors Mailedtosender - * -t = read recipient from header of message - * NOTE: since this runs as the user, not root you must - * not specify any args that will cause sendmail - * to drop its suidness (see op.me for a list). + * -or0s = Option Readtimeout -- don't time out + * -t = Get recipient from headers */ +#define MAILARG _PATH_SENDMAIL /*-*/ -/* #define MAILCMD "/bin/mail" -*/ -/* #define MAILARGS "%s -d %s" -*/ +/* #define MAILFMT "%s -d %s" -*/ /* -d = undocumented but common flag: deliver locally? */ +/* #define MAILARG "/bin/mail",mailto -*/ -/* #define MAILCMD "/usr/mmdf/bin/submit" -*/ -/* #define MAILARGS "%s -mlrxto %s" -*/ +/* #define MAILFMT "%s -mlrxto %s" -*/ +/* #define MAILARG "/usr/mmdf/bin/submit",mailto -*/ /* #define MAIL_DATE -*/ /* should we include an ersatz Date: header in * generated mail? if you are using sendmail - * for MAILCMD, it is better to let sendmail + * as the mailer, it is better to let sendmail * generate the Date: header. */ @@ -89,4 +86,7 @@ #define SYSLOG /*-*/ /* if your OS supports a BSD-style login.conf file */ -#define LOGIN_CAP /*-*/ +#define LOGIN_CAP /*-*/ + + /* if your OS supports BSD authentication */ +/*#define BSD_AUTH -*/ diff --git a/usr.sbin/cron/cron.8 b/usr.sbin/cron/cron.8 index 8cb0cbe7a0f..59845209488 100644 --- a/usr.sbin/cron/cron.8 +++ b/usr.sbin/cron/cron.8 @@ -1,21 +1,23 @@ -.\"/* Copyright 1988,1990,1993 by Paul Vixie +.\"/* Copyright 1988,1990,1993,1996 by Paul Vixie .\" * All rights reserved -.\" * -.\" * Distribute freely, except: don't remove my name from the source or -.\" * documentation (don't take credit for my work), mark your changes (don't -.\" * get me blamed for your possible bugs), don't alter or remove this -.\" * notice. May be sold if buildable source is provided to buyer. No -.\" * warrantee of any kind, express or implied, is included with this -.\" * software; use at your own risk, responsibility for damages (if any) to -.\" * anyone resulting from the use of this software rests entirely with the -.\" * user. -.\" * -.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and -.\" * I'll try to keep a version up to date. I can be reached as follows: -.\" * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul .\" */ .\" -.\" $Id: cron.8,v 1.8 2000/03/19 17:57:03 aaron Exp $ +.\" Copyright (c) 1997,2000 by Internet Software Consortium, Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" $OpenBSD: cron.8,v 1.9 2001/02/18 19:48:31 millert Exp $ .\" .Dd June 6, 1999 .Dt CRON 8 @@ -90,6 +92,17 @@ new time immediately. .Pp Clock changes of more than 3 hours are considered to be corrections to the clock, and the new time is used immediately. +.Sh SIGNALS +On receipt of a +.Tn SIGHUP , +the cron daemon will close and reopen its log file. +This is useful in scripts which rotate and age log files. +Naturally this is not relevant if cron was built to use +.Xr syslog 3 . +Sh BUGS +.Nm +will behave mysteriously if a system clock is reset backward by more than +59 seconds. Smaller steps, or steps forward, are handled correctly. .Sh SEE ALSO .Xr crontab 1 , .Xr crontab 5 diff --git a/usr.sbin/cron/cron.c b/usr.sbin/cron/cron.c index 59ab8b33b07..b9086c8c2c0 100644 --- a/usr.sbin/cron/cron.c +++ b/usr.sbin/cron/cron.c @@ -1,70 +1,65 @@ +/* $OpenBSD: cron.c,v 1.10 2001/02/18 19:48:31 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: cron.c,v 1.9 2001/01/19 17:53:12 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: cron.c,v 1.10 2001/02/18 19:48:31 millert Exp $"; #endif - #define MAIN_PROGRAM - #include "cron.h" -#include <sys/signal.h> -#if SYS_TIME_H -# include <sys/time.h> -#else -# include <time.h> -#endif - -static void usage __P((void)), - run_reboot_jobs __P((cron_db *)), +static void usage(void), + run_reboot_jobs(cron_db *), find_jobs __P((time_min, cron_db *, int, int)), set_time __P((void)), cron_sleep __P((time_min)), -#ifdef USE_SIGCHLD - sigchld_handler __P((int)), -#endif - sighup_handler __P((int)), - parse_args __P((int c, char *v[])); + sigchld_handler(int), + sighup_handler(int), + sigchld_reaper(void), + parse_args(int c, char *v[]); +static int got_sighup, got_sigchld; static void -usage() { - char **dflags; +usage(void) { + const char **dflags; fprintf(stderr, "usage: %s [-x [", ProgramName); - for(dflags = DebugFlagNames; *dflags; dflags++) + for (dflags = DebugFlagNames; *dflags; dflags++) fprintf(stderr, "%s%s", *dflags, dflags[1] ? "," : "]"); fprintf(stderr, "]\n"); exit(ERROR_EXIT); } - int -main(argc, argv) - int argc; - char *argv[]; -{ +main(int argc, char *argv[]) { cron_db database; + struct sigaction sact; ProgramName = argv[0]; + setlocale(LC_ALL, ""); + #if defined(BSD) setlinebuf(stdout); setlinebuf(stderr); @@ -72,30 +67,31 @@ main(argc, argv) parse_args(argc, argv); -#ifdef USE_SIGCHLD - (void) signal(SIGCHLD, sigchld_handler); -#else - (void) signal(SIGCLD, SIG_IGN); + bzero((char *)&sact, sizeof sact); + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; +#ifdef SA_RESTART + sact.sa_flags |= SA_RESTART; #endif - (void) signal(SIGHUP, sighup_handler); + sact.sa_handler = sigchld_handler; + (void) sigaction(SIGCHLD, &sact, NULL); + sact.sa_handler = sighup_handler; + (void) sigaction(SIGHUP, &sact, NULL); acquire_daemonlock(0); set_cron_uid(); set_cron_cwd(); -#if defined(POSIX) - if (setenv("PATH", _PATH_DEFPATH, 1) == -1) { + if (putenv("PATH="_PATH_DEFPATH) == -1) { log_it("CRON",getpid(),"DEATH","can't malloc"); exit(1); } -#endif /* if there are no debug flags turned on, fork as a daemon should. */ - if (DebugFlags) { #if DEBUGGING - (void) fprintf(stderr, "[%d] cron started\n", getpid()); + (void) fprintf(stderr, "[%ld] cron started\n", (long)getpid()); #endif } else { switch (fork()) { @@ -119,13 +115,12 @@ main(argc, argv) database.tail = NULL; database.mtime = (time_t) 0; load_database(&database); - set_time(); run_reboot_jobs(&database); timeRunning = virtualTime = clockTime; /* - * too many clocks, not enough time (Al. Einstein) + * Too many clocks, not enough time (Al. Einstein) * These clocks are in minutes since the epoch (time()/60). * virtualTime: is the time it *would* be if we woke up * promptly and nobody ever changed the clock. It is @@ -138,8 +133,16 @@ main(argc, argv) time_min timeDiff; int wakeupKind; - load_database(&database); + if (got_sighup) { + got_sighup = 0; + log_close(); + } + if (got_sigchld) { + got_sigchld = 0; + sigchld_reaper(); + } + load_database(&database); /* ... wait for the time (in minutes) to change ... */ do { cron_sleep(timeRunning + 1); @@ -148,9 +151,8 @@ main(argc, argv) timeRunning = clockTime; /* - * ... calculate how the current time differs from - * our virtual clock. Classify the change into one - * of 4 cases + * Calculate how the current time differs from our virtual + * clock. Classify the change into one of 4 cases. */ timeDiff = timeRunning - virtualTime; @@ -173,8 +175,8 @@ main(argc, argv) case 1: /* * case 1: timeDiff is a small positive number - * (wokeup late) run jobs for each virtual minute - * until caught up. + * (wokeup late) run jobs for each virtual + * minute until caught up. */ Debug(DSCH, ("[%d], normal case %d minutes to go\n", getpid(), timeRunning - virtualTime)) @@ -182,31 +184,35 @@ main(argc, argv) if (job_runqueue()) sleep(10); virtualTime++; - find_jobs(virtualTime, &database, TRUE, TRUE); + find_jobs(virtualTime, &database, + TRUE, TRUE); } while (virtualTime< timeRunning); break; case 2: /* - * case 2: timeDiff is a medium-sized positive number, - * for example because we went to DST run wildcard - * jobs once, then run any fixed-time jobs that would - * otherwise be skipped if we use up our minute - * (possible, if there are a lot of jobs to run) go - * around the loop again so that wildcard jobs have - * a chance to run, and we do our housekeeping + * case 2: timeDiff is a medium-sized positive + * number, for example because we went to DST + * run wildcard jobs once, then run any + * fixed-time jobs that would otherwise be + * skipped if we use up our minute (possible, + * if there are a lot of jobs to run) go + * around the loop again so that wildcard jobs + * have a chance to run, and we do our + * housekeeping. */ Debug(DSCH, ("[%d], DST begins %d minutes to go\n", getpid(), timeRunning - virtualTime)) /* run wildcard jobs for current minute */ find_jobs(timeRunning, &database, TRUE, FALSE); - /* run fixed-time jobs for each minute missed */ + /* run fixed-time jobs for each minute missed */ do { if (job_runqueue()) sleep(10); virtualTime++; - find_jobs(virtualTime, &database, FALSE, TRUE); + find_jobs(virtualTime, &database, + FALSE, TRUE); set_time(); } while (virtualTime< timeRunning && clockTime == timeRunning); @@ -215,10 +221,11 @@ main(argc, argv) case 0: /* * case 3: timeDiff is a small or medium-sized - * negative num, eg. because of DST ending just run - * the wildcard jobs. The fixed-time jobs probably - * have already run, and should not be repeated - * virtual time does not change until we are caught up + * negative num, eg. because of DST ending just + * run the wildcard jobs. The fixed-time jobs + * probably have already run, and should not be + * repeated. Virtual time does not change until + * we are caught up. */ Debug(DSCH, ("[%d], DST ends %d minutes to go\n", getpid(), virtualTime - timeRunning)) @@ -234,42 +241,33 @@ main(argc, argv) find_jobs(timeRunning, &database, TRUE, TRUE); } } - /* jobs to be run (if any) are loaded. clear the queue */ + + /* Jobs to be run (if any) are loaded; clear the queue. */ job_runqueue(); } } - static void -run_reboot_jobs(db) - cron_db *db; -{ - register user *u; - register entry *e; - - for (u = db->head; u != NULL; u = u->next) { - for (e = u->crontab; e != NULL; e = e->next) { - if (e->flags & WHEN_REBOOT) { +run_reboot_jobs(cron_db *db) { + user *u; + entry *e; + + for (u = db->head; u != NULL; u = u->next) { + for (e = u->crontab; e != NULL; e = e->next) { + if (e->flags & WHEN_REBOOT) job_add(e, u); - } } } (void) job_runqueue(); } - static void -find_jobs(vtime, db, doWild, doNonWild) - time_min vtime; - cron_db *db; - int doWild; - int doNonWild; -{ - time_t virtualSecond = vtime * SECONDS_PER_MINUTE; - register struct tm *tm = localtime(&virtualSecond); - register int minute, hour, dom, month, dow; - register user *u; - register entry *e; +find_jobs(time_min vtime, cron_db *db, int doWild, int doNonWild) { + time_t virtualSecond = vtime * SECONDS_PER_MINUTE; + struct tm *tm = localtime(&virtualSecond); + int minute, hour, dom, month, dow; + user *u; + entry *e; /* make 0-based values out of these so we can use them as indicies */ @@ -279,9 +277,9 @@ find_jobs(vtime, db, doWild, doNonWild) month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH; dow = tm->tm_wday -FIRST_DOW; - Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d) %s %s\n", - getpid(), minute, hour, dom, month, dow, - doWild?" ":"No wildcard",doNonWild?" ":"Wildcard only")) + Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n", + (long)getpid(), minute, hour, dom, month, dow, + doWild?" ":"No wildcard",doNonWild?" ":"Wildcard only")) /* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the * first and fifteenth AND every Sunday; '* * * * Sun' will run *only* @@ -289,108 +287,90 @@ find_jobs(vtime, db, doWild, doNonWild) * is why we keep 'e->dow_star' and 'e->dom_star'. yes, it's bizarre. * like many bizarre things, it's the standard. */ - for (u = db->head; u != NULL; u = u->next) { - for (e = u->crontab; e != NULL; e = e->next) { - Debug(DSCH|DEXT, ("user [%s:%d:%d:...] cmd=\"%s\"\n", - env_get("LOGNAME", e->envp), - e->uid, e->gid, e->cmd)) + for (u = db->head; u != NULL; u = u->next) { + for (e = u->crontab; e != NULL; e = e->next) { + Debug(DSCH|DEXT, ("user [%s:%ld:%ld:...] cmd=\"%s\"\n", + env_get("LOGNAME", e->envp), + (long)e->uid, (long)e->gid, e->cmd)) if (bit_test(e->minute, minute) && bit_test(e->hour, hour) && bit_test(e->month, month) && ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR)) ? (bit_test(e->dow,dow) && bit_test(e->dom,dom)) - : (bit_test(e->dow,dow) || bit_test(e->dom,dom)))) { - if ((doNonWild && !(e->flags & (MIN_STAR|HR_STAR))) - || (doWild && (e->flags & (MIN_STAR|HR_STAR)))) - job_add(e, u); - } + : (bit_test(e->dow,dow) || bit_test(e->dom,dom)) + ) + ) + job_add(e, u); } } } - /* - * set StartTime and clockTime to the current time. - * these are used for computing what time it really is right now. - * note that clockTime is a unix wallclock time converted to minutes + * Set StartTime and clockTime to the current time. + * These are used for computing what time it really is right now. + * Note that clockTime is a unix wallclock time converted to minutes. */ static void -set_time() -{ +set_time(void) { + StartTime = time((time_t *)0); clockTime = StartTime / (unsigned long)SECONDS_PER_MINUTE; } /* - * try to just hit the next minute + * Try to just hit the next minute. */ static void -cron_sleep(target) - time_min target; -{ - register int seconds_to_wait; +cron_sleep(time_min target) { + int seconds_to_wait; - seconds_to_wait = (int)(target*SECONDS_PER_MINUTE - time((time_t*)0)) + 1; - Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n", - getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait)) + seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - time(NULL)) + 1; + Debug(DSCH, ("[%ld] Target time=%ld, sec-to-wait=%d\n", + (long)getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait)) - if (seconds_to_wait > 0 && seconds_to_wait< 65) + if (seconds_to_wait > 0 && seconds_to_wait < 65) sleep((unsigned int) seconds_to_wait); } +static void +sighup_handler(int x) { + got_sighup = 1; +} + +static void +sigchld_handler(int x) { + got_sigchld = 1; +} -#ifdef USE_SIGCHLD static void -sigchld_handler(x) { - int save_errno = errno; - WAIT_T waiter; - PID_T pid; +sigchld_reaper() { + WAIT_T waiter; + PID_T pid; - for (;;) { -#ifdef POSIX + do { pid = waitpid(-1, &waiter, WNOHANG); -#else - pid = wait3(&waiter, WNOHANG, (struct rusage *)0); -#endif - /* XXX unsafe */ switch (pid) { case -1: Debug(DPROC, - ("[%d] sigchld...no children\n", getpid())) - errno = save_errno; - return; + ("[%ld] sigchld...no children\n", + (long)getpid())) + break; case 0: Debug(DPROC, - ("[%d] sigchld...no dead kids\n", getpid())) - errno = save_errno; - return; + ("[%ld] sigchld...no dead kids\n", + (long)getpid())) + break; default: Debug(DPROC, - ("[%d] sigchld...pid #%d died, stat=%d\n", - getpid(), pid, WEXITSTATUS(waiter))) + ("[%ld] sigchld...pid #%ld died, stat=%d\n", + (long)getpid(), (long)pid, WEXITSTATUS(waiter))) } - } - errno = save_errno; -} -#endif /*USE_SIGCHLD*/ - - -static void -sighup_handler(x) { - int save_errno = errno; - - /* XXX unsafe */ - log_close(); - errno = save_errno; + } while (pid > 0); } - static void -parse_args(argc, argv) - int argc; - char *argv[]; -{ - int argch; +parse_args(int argc, char *argv[]) { + int argch; while (-1 != (argch = getopt(argc, argv, "x:"))) { switch (argch) { diff --git a/usr.sbin/cron/cron.h b/usr.sbin/cron/cron.h index 144c33328e2..bc7b5659bf1 100644 --- a/usr.sbin/cron/cron.h +++ b/usr.sbin/cron/cron.h @@ -1,292 +1,36 @@ +/* $OpenBSD: cron.h,v 1.6 2001/02/18 19:48:31 millert Exp $ */ + /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ /* cron.h - header for vixie's cron * - * $Id: cron.h,v 1.5 2001/02/12 18:46:54 millert Exp $ - * * vix 14nov88 [rest of log is in RCS] * vix 14jan87 [0 or 7 can be sunday; thanks, mwm@berkeley] * vix 30dec86 [written] */ -/* reorder these #include's at your peril */ - -#include <sys/types.h> -#include <sys/param.h> -#include "compat.h" - -#include <stdio.h> -#include <ctype.h> -#include <bitstring.h> -#include <pwd.h> -#include <sys/wait.h> - -#include "pathnames.h" #include "config.h" #include "externs.h" - - /* these are really immutable, and are - * defined for symbolic convenience only - * TRUE, FALSE, and ERR must be distinct - * ERR must be < OK. - */ -#define TRUE 1 -#define FALSE 0 - /* system calls return this on success */ -#define OK 0 - /* or this on error */ -#define ERR (-1) - - /* turn this on to get '-x' code */ -#ifndef DEBUGGING -#define DEBUGGING FALSE -#endif - -#define READ_PIPE 0 /* which end of a pipe pair do you read? */ -#define WRITE_PIPE 1 /* or write to? */ -#define STDIN 0 /* what is stdin's file descriptor? */ -#define STDOUT 1 /* stdout's? */ -#define STDERR 2 /* stderr's? */ -#define ERROR_EXIT 1 /* exit() with this will scare the shell */ -#define OK_EXIT 0 /* exit() with this is considered 'normal' */ -#define MAX_FNAME 100 /* max length of internally generated fn */ -#define MAX_COMMAND 1000 /* max length of internally generated cmd */ -#define MAX_ENVSTR 1000 /* max length of envvar=value\0 strings */ -#define MAX_TEMPSTR 100 /* obvious */ -#define MAX_UNAME (_PW_NAME_LEN+1) /* max length of username */ -#define ROOT_UID 0 /* don't change this, it really must be root */ -#define ROOT_USER "root" /* ditto */ - - /* NOTE: these correspond to DebugFlagNames, - * defined below. - */ -#define DEXT 0x0001 /* extend flag for other debug masks */ -#define DSCH 0x0002 /* scheduling debug mask */ -#define DPROC 0x0004 /* process control debug mask */ -#define DPARS 0x0008 /* parsing debug mask */ -#define DLOAD 0x0010 /* database loading debug mask */ -#define DMISC 0x0020 /* misc debug mask */ -#define DTEST 0x0040 /* test mode: don't execute any commands */ -#define DBIT 0x0080 /* bit twiddling shown (long) */ - -#define CRON_TAB(u) "%s/%s", SPOOL_DIR, u -#define REG register -#define PPC_NULL ((char **)NULL) - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define Skip_Blanks(c, f) \ - while (c == '\t' || c == ' ') \ - c = get_char(f); - -#define Skip_Nonblanks(c, f) \ - while (c!='\t' && c!=' ' && c!='\n' && c != EOF) \ - c = get_char(f); - -#define Skip_Line(c, f) \ - do {c = get_char(f);} while (c != '\n' && c != EOF); - -#if DEBUGGING -# define Debug(mask, message) \ - if ( (DebugFlags & (mask) ) == (mask) ) \ - printf message; -#else /* !DEBUGGING */ -# define Debug(mask, message) \ - ; -#endif /* DEBUGGING */ - -#define MkLower(ch) (isupper(ch) ? tolower(ch) : ch) -#define MkUpper(ch) (islower(ch) ? toupper(ch) : ch) -#define Set_LineNum(ln) {Debug(DPARS|DEXT,("linenum=%d\n",ln)); \ - LineNumber = ln; \ - } - -typedef int time_min; - -#define SECONDS_PER_MINUTE 60 - -#define FIRST_MINUTE 0 -#define LAST_MINUTE 59 -#define MINUTE_COUNT (LAST_MINUTE - FIRST_MINUTE + 1) - -#define FIRST_HOUR 0 -#define LAST_HOUR 23 -#define HOUR_COUNT (LAST_HOUR - FIRST_HOUR + 1) - -#define FIRST_DOM 1 -#define LAST_DOM 31 -#define DOM_COUNT (LAST_DOM - FIRST_DOM + 1) - -#define FIRST_MONTH 1 -#define LAST_MONTH 12 -#define MONTH_COUNT (LAST_MONTH - FIRST_MONTH + 1) - -/* note on DOW: 0 and 7 are both Sunday, for compatibility reasons. */ -#define FIRST_DOW 0 -#define LAST_DOW 7 -#define DOW_COUNT (LAST_DOW - FIRST_DOW + 1) - - /* each user's crontab will be held as a list of - * the following structure. - * - * These are the cron commands. - */ - -typedef struct _entry { - struct _entry *next; - uid_t uid; - gid_t gid; - char **envp; - char *cmd; - bitstr_t bit_decl(minute, MINUTE_COUNT); - bitstr_t bit_decl(hour, HOUR_COUNT); - bitstr_t bit_decl(dom, DOM_COUNT); - bitstr_t bit_decl(month, MONTH_COUNT); - bitstr_t bit_decl(dow, DOW_COUNT); - int flags; -#define DOM_STAR 0x01 -#define DOW_STAR 0x02 -#define WHEN_REBOOT 0x04 -#define MIN_STAR 0x08 -#define HR_STAR 0x10 -} entry; - - /* the crontab database will be a list of the - * following structure, one element per user - * plus one for the system. - * - * These are the crontabs. - */ - -typedef struct _user { - struct _user *next, *prev; /* links */ - char *name; - time_t mtime; /* last modtime of crontab */ - entry *crontab; /* this person's crontab */ -} user; - -typedef struct _cron_db { - user *head, *tail; /* links */ - time_t mtime; /* last modtime on spooldir */ -} cron_db; - - -void set_cron_uid __P((void)), - set_cron_cwd __P((void)), - load_database __P((cron_db *)), - open_logfile __P((void)), - sigpipe_func __P((void)), - job_add __P((entry *, user *)), - do_command __P((entry *, user *)), - link_user __P((cron_db *, user *)), - unlink_user __P((cron_db *, user *)), - free_user __P((user *)), - env_free __P((char **)), - unget_char __P((int, FILE *)), - free_entry __P((entry *)), - acquire_daemonlock __P((int)), - skip_comments __P((FILE *)), - log_it __P((char *, int, char *, char *)), - log_close __P((void)); - -int job_runqueue __P((void)), - set_debug_flags __P((char *)), - get_char __P((FILE *)), - get_string __P((char *, int, FILE *, char *)), - swap_uids __P((void)), - swap_uids_back __P((void)), - load_env __P((char *, FILE *)), - cron_pclose __P((FILE *)), - strcmp_until __P((char *, char *, int)), - allowed __P((char *)), - strdtb __P((char *)); - -char *env_get __P((char *, char **)), - *arpadate __P((time_t *)), - *mkprints __P((unsigned char *, unsigned int)), - *first_word __P((char *, char *)), - **env_init __P((void)), - **env_copy __P((char **)), - **env_set __P((char **, char *)); - -user *load_user __P((int, struct passwd *, char *)), - *find_user __P((cron_db *, char *)); - -entry *load_entry __P((FILE *, void (*)(), - struct passwd *, char **)); - -FILE *cron_popen __P((char *, char *, entry *)); - - - /* in the C tradition, we only create - * variables for the main program, just - * extern them elsewhere. - */ - -#ifdef MAIN_PROGRAM -# if !defined(LINT) && !defined(lint) -char *copyright[] = { - "@(#) Copyright 1988,1989,1990,1993,1994 by Paul Vixie", - "@(#) All rights reserved" - }; -# endif - -char *MonthNames[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - NULL - }; - -char *DowNames[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", - NULL - }; - -char *ProgramName; -int LineNumber; -time_t StartTime; -time_min timeRunning; -time_min virtualTime; -time_min clockTime; - -# if DEBUGGING -int DebugFlags; -char *DebugFlagNames[] = { /* sync with #defines */ - "ext", "sch", "proc", "pars", "load", "misc", "test", "bit", - NULL /* NULL must be last element */ - }; -# else -#define DebugFlags 0 -# endif /* DEBUGGING */ -#else /*MAIN_PROGRAM*/ -extern char *copyright[], - *MonthNames[], - *DowNames[], - *ProgramName; -extern int LineNumber; -extern time_t StartTime; -extern time_min timeRunning; -extern time_min virtualTime; -extern time_min clockTime; -# if DEBUGGING -extern int DebugFlags; -extern char *DebugFlagNames[]; -# endif /* DEBUGGING */ -#endif /*MAIN_PROGRAM*/ +#include "pathnames.h" +#include "macros.h" +#include "structs.h" +#include "funcs.h" +#include "globals.h" diff --git a/usr.sbin/cron/crontab.1 b/usr.sbin/cron/crontab.1 index a838ac7e426..9ab9b5d1b4b 100644 --- a/usr.sbin/cron/crontab.1 +++ b/usr.sbin/cron/crontab.1 @@ -1,21 +1,21 @@ .\"/* Copyright 1988,1990,1993 by Paul Vixie .\" * All rights reserved -.\" * -.\" * Distribute freely, except: don't remove my name from the source or -.\" * documentation (don't take credit for my work), mark your changes (don't -.\" * get me blamed for your possible bugs), don't alter or remove this -.\" * notice. May be sold if buildable source is provided to buyer. No -.\" * warrantee of any kind, express or implied, is included with this -.\" * software; use at your own risk, responsibility for damages (if any) to -.\" * anyone resulting from the use of this software rests entirely with the -.\" * user. -.\" * -.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and -.\" * I'll try to keep a version up to date. I can be reached as follows: -.\" * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul .\" */ .\" -.\" $Id: crontab.1,v 1.7 2000/03/23 21:39:57 aaron Exp $ +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" $OpenBSD: crontab.1,v 1.8 2001/02/18 19:48:32 millert Exp $ .\" .Dd June 8, 1999 .Dt CRONTAB 1 diff --git a/usr.sbin/cron/crontab.5 b/usr.sbin/cron/crontab.5 index 94ddaf40bbe..27f7b05ff39 100644 --- a/usr.sbin/cron/crontab.5 +++ b/usr.sbin/cron/crontab.5 @@ -1,21 +1,21 @@ -.\" $NetBSD: crontab.5,v 1.5 1997/07/13 11:01:16 mouse Exp $ +.\"/* Copyright 1988,1990,1993,1994 by Paul Vixie .\" * All rights reserved -.\" * -.\" * Distribute freely, except: don't remove my name from the source or -.\" * documentation (don't take credit for my work), mark your changes (don't -.\" * get me blamed for your possible bugs), don't alter or remove this -.\" * notice. May be sold if buildable source is provided to buyer. No -.\" * warrantee of any kind, express or implied, is included with this -.\" * software; use at your own risk, responsibility for damages (if any) to -.\" * anyone resulting from the use of this software rests entirely with the -.\" * user. -.\" * -.\" * Send bug reports, bug fixes, enhancements, requests, flames, etc., and -.\" * I'll try to keep a version up to date. I can be reached as follows: -.\" * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul .\" */ .\" -.\" $Id: crontab.5,v 1.11 2000/04/15 11:53:29 aaron Exp $ +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" $OpenBSD: crontab.5,v 1.12 2001/02/18 19:48:32 millert Exp $ .\" .Dd June 8, 1999 .Dt CRONTAB 5 diff --git a/usr.sbin/cron/crontab.c b/usr.sbin/cron/crontab.c index 407cfa1eb6e..2846971c657 100644 --- a/usr.sbin/cron/crontab.c +++ b/usr.sbin/cron/crontab.c @@ -1,22 +1,27 @@ +/* $OpenBSD: crontab.c,v 1.19 2001/02/18 19:48:32 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: crontab.c,v 1.18 2000/08/21 21:08:55 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: crontab.c,v 1.19 2001/02/18 19:48:32 millert Exp $"; #endif /* crontab - install and manage per-user crontab files @@ -24,58 +29,39 @@ static char rcsid[] = "$Id: crontab.c,v 1.18 2000/08/21 21:08:55 deraadt Exp $"; * vix 26jan87 [original] */ - #define MAIN_PROGRAM - #include "cron.h" -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/file.h> -#include <sys/stat.h> -#ifdef USE_UTIMES -# include <sys/time.h> -#else -# include <time.h> -# include <utime.h> -#endif -#if defined(POSIX) -# include <locale.h> -#endif - #define NHEADER_LINES 3 - enum opt_t { opt_unknown, opt_list, opt_delete, opt_edit, opt_replace }; #if DEBUGGING static char *Options[] = { "???", "list", "delete", "edit", "replace" }; +static char *getoptargs = "u:lerx:"; +#else +static char *getoptargs = "u:ler"; #endif - static PID_T Pid; static char User[MAX_UNAME], RealUser[MAX_UNAME]; -static char Filename[MAX_FNAME], *TempFilename; +static char Filename[MAX_FNAME], TempFilename[MAX_FNAME]; static FILE *NewCrontab; static int CheckErrorCount; static enum opt_t Option; static struct passwd *pw; -static void list_cmd __P((void)), - delete_cmd __P((void)), - edit_cmd __P((void)), - poke_daemon __P((void)), - check_error __P((char *)), - parse_args __P((int c, char *v[])); -static int replace_cmd __P((void)); +static void list_cmd(void), + delete_cmd(void), + edit_cmd(void), + poke_daemon(void), + check_error(const char *), + parse_args(int c, char *v[]); +static int replace_cmd(void); static void clean_turds __P((int)); - static void -usage(msg) - char *msg; -{ +usage(const char *msg) { fprintf(stderr, "%s: usage error: %s\n", ProgramName, msg); fprintf(stderr, "usage:\t%s [-u user] file\n", ProgramName); fprintf(stderr, "\t%s [-u user] [ -e | -l | -r ]\n", ProgramName); @@ -86,20 +72,14 @@ usage(msg) exit(ERROR_EXIT); } - int -main(argc, argv) - int argc; - char *argv[]; -{ +main(int argc, char *argv[]) { int exitstatus; Pid = getpid(); ProgramName = argv[0]; -#if defined(POSIX) setlocale(LC_ALL, ""); -#endif #if defined(BSD) setlinebuf(stderr); @@ -117,32 +97,29 @@ main(argc, argv) } exitstatus = OK_EXIT; switch (Option) { - case opt_list: list_cmd(); - break; - case opt_delete: delete_cmd(); - break; - case opt_edit: edit_cmd(); - break; - case opt_replace: if (replace_cmd() < 0) - exitstatus = ERROR_EXIT; - break; + case opt_list: + list_cmd(); + break; + case opt_delete: + delete_cmd(); + break; + case opt_edit: + edit_cmd(); + break; + case opt_replace: + if (replace_cmd() < 0) + exitstatus = ERROR_EXIT; + break; + default: + abort(); } exit(0); /*NOTREACHED*/ } - -#if DEBUGGING -char *getoptarg = "u:lerx:"; -#else -char *getoptarg = "u:ler"; -#endif static void -parse_args(argc, argv) - int argc; - char *argv[]; -{ - int argch; +parse_args(int argc, char *argv[]) { + int argch; if (!(pw = getpwuid(getuid()))) { fprintf(stderr, "%s: your UID isn't in the passwd file.\n", @@ -150,36 +127,34 @@ parse_args(argc, argv) fprintf(stderr, "bailing out.\n"); exit(ERROR_EXIT); } - (void) strncpy(User, pw->pw_name, (sizeof User)-1); - User[(sizeof User)-1] = '\0'; + if (strlen(pw->pw_name) >= sizeof User) { + fprintf(stderr, "username too long\n"); + exit(ERROR_EXIT); + } + strcpy(User, pw->pw_name); strcpy(RealUser, User); Filename[0] = '\0'; Option = opt_unknown; - - while (-1 != (argch = getopt(argc, argv, getoptarg))) { + while (-1 != (argch = getopt(argc, argv, getoptargs))) { switch (argch) { -#if DEBUGGING case 'x': if (!set_debug_flags(optarg)) usage("bad debug option"); - usage("unrecognized option"); break; -#endif case 'u': - if (getuid() != ROOT_UID) - { + if (MY_UID(pw) != ROOT_UID) { fprintf(stderr, "must be privileged to use -u\n"); exit(ERROR_EXIT); } - if (!(pw = getpwnam(optarg))) - { + if (!(pw = getpwnam(optarg))) { fprintf(stderr, "%s: user `%s' unknown\n", ProgramName, optarg); exit(ERROR_EXIT); } - (void) strncpy(User, pw->pw_name, (sizeof User)-1); - User[(sizeof User)-1] = '\0'; + if (strlen(optarg) >= sizeof User) + usage("username too long"); + (void) strcpy(User, optarg); break; case 'l': if (Option != opt_unknown) @@ -204,18 +179,16 @@ parse_args(argc, argv) endpwent(); if (Option != opt_unknown) { - if (argv[optind] != NULL) { + if (argv[optind] != NULL) usage("no arguments permitted after this option"); - } } else { if (argv[optind] != NULL) { Option = opt_replace; - (void) strncpy (Filename, argv[optind], (sizeof Filename)-1); - Filename[(sizeof Filename)-1] = '\0'; - - } else { + if (strlen(argv[optind]) >= sizeof Filename) + usage("filename too long"); + (void) strcpy (Filename, argv[optind]); + } else usage("file name must be specified for replace"); - } } if (Option == opt_replace) { @@ -223,9 +196,9 @@ parse_args(argc, argv) * chdir(2) into /var/cron before we get around to * reading the file. */ - if (!strcmp(Filename, "-")) { + if (!strcmp(Filename, "-")) NewCrontab = stdin; - } else { + else { /* relinquish the setuid status of the binary during * the open, lest nonroot users read files they should * not be able to read. we can't use access() here @@ -255,13 +228,16 @@ parse_args(argc, argv) static void -list_cmd() { - char n[MAX_FNAME]; - FILE *f; - int ch; +list_cmd(void) { + char n[MAX_FNAME]; + FILE *f; + int ch; log_it(RealUser, Pid, "LIST", User); - (void) snprintf(n, sizeof n, CRON_TAB(User)); + if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { + fprintf(stderr, "path too long\n"); + exit(ERROR_EXIT); + } if (!(f = fopen(n, "r"))) { if (errno == ENOENT) fprintf(stderr, "no crontab for %s\n", User); @@ -278,14 +254,16 @@ list_cmd() { fclose(f); } - static void -delete_cmd() { - char n[MAX_FNAME]; +delete_cmd(void) { + char n[MAX_FNAME]; log_it(RealUser, Pid, "DELETE", User); - (void) snprintf(n, sizeof n, CRON_TAB(User)); - if (unlink(n)) { + if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { + fprintf(stderr, "path too long\n"); + exit(ERROR_EXIT); + } + if (unlink(n) != 0) { if (errno == ENOENT) fprintf(stderr, "no crontab for %s\n", User); else @@ -295,29 +273,28 @@ delete_cmd() { poke_daemon(); } - static void -check_error(msg) - char *msg; -{ +check_error(const char *msg) { CheckErrorCount++; fprintf(stderr, "\"%s\":%d: %s\n", Filename, LineNumber-1, msg); } - static void -edit_cmd() { - char n[MAX_FNAME], q[MAX_TEMPSTR], *editor; - FILE *f; - int ch, t, x; - struct stat statbuf; - time_t mtime; - off_t size; - WAIT_T waiter; - PID_T pid, xpid; +edit_cmd(void) { + char n[MAX_FNAME], q[MAX_TEMPSTR], *editor; + FILE *f; + int ch, t, x; + struct stat statbuf; + time_t mtime; + off_t size; + WAIT_T waiter; + PID_T pid, xpid; log_it(RealUser, Pid, "BEGIN EDIT", User); - (void) snprintf(n, sizeof n, CRON_TAB(User)); + if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { + fprintf(stderr, "path too long\n"); + exit(ERROR_EXIT); + } if (!(f = fopen(n, "r"))) { if (errno != ENOENT) { perror(n); @@ -336,19 +313,26 @@ edit_cmd() { (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); - (void) snprintf(Filename, sizeof Filename, "/tmp/crontab.XXXXXXXXXX"); - if ((t = mkstemp(Filename)) == -1) { + if (!glue_strings(Filename, sizeof Filename, _PATH_TMP, + "crontab.XXXXXXXXXX", '/')) { + fprintf(stderr, "path too long\n"); + goto fatal; + } + if (-1 == (t = mkstemp(Filename))) { perror(Filename); goto fatal; } #ifdef HAS_FCHOWN - if (fchown(t, getuid(), getgid()) < 0) { -#else - if (chown(Filename, getuid(), getgid()) < 0) { -#endif + if (fchown(t, MY_UID(pw), MY_GID(pw)) < 0) { perror("fchown"); goto fatal; } +#else + if (chown(Filename, MY_UID(pw), MY_GID(pw)) < 0) { + perror("chown"); + goto fatal; + } +#endif if (!(NewCrontab = fdopen(t, "r+"))) { perror("fdopen"); goto fatal; @@ -388,7 +372,8 @@ edit_cmd() { if (ferror(NewCrontab)) { fprintf(stderr, "%s: error while writing new crontab to %s\n", ProgramName, Filename); - fatal: unlink(Filename); + fatal: + unlink(Filename); exit(ERROR_EXIT); } if (fstat(t, &statbuf) < 0) { @@ -398,9 +383,8 @@ edit_cmd() { mtime = statbuf.st_mtime; size = statbuf.st_size; - if ((!(editor = getenv("VISUAL"))) - && (!(editor = getenv("EDITOR"))) - ) { + if (((editor = getenv("VISUAL")) == NULL || *editor == '\0') && + ((editor = getenv("EDITOR")) == NULL || *editor == '\0')) { editor = EDITOR; } @@ -418,20 +402,23 @@ edit_cmd() { goto fatal; case 0: /* child */ - if (setuid(getuid()) < 0) { + if (setgid(MY_GID(pw)) < 0) { + perror("setgid(getgid())"); + exit(ERROR_EXIT); + } + if (setuid(MY_UID(pw)) < 0) { perror("setuid(getuid())"); exit(ERROR_EXIT); } - if (chdir("/tmp") < 0) { - perror("chdir(\"/tmp\")"); + if (chdir(_PATH_TMP) < 0) { + perror(_PATH_TMP); exit(ERROR_EXIT); } - if (strlen(editor) + strlen(Filename) + 2 >= sizeof(q)) { - fprintf(stderr, "%s: editor or filename too long\n", - ProgramName); + if (!glue_strings(q, sizeof q, editor, Filename, ' ')) { + fprintf(stderr, "%s: editor command line too long\n", + ProgramName); exit(ERROR_EXIT); } - snprintf(q, sizeof q, "%s %s", editor, Filename); execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", q, NULL); perror(editor); exit(ERROR_EXIT); @@ -442,14 +429,14 @@ edit_cmd() { } /* parent */ - while (1) { + for (;;) { xpid = waitpid(pid, &waiter, WUNTRACED); if (xpid == -1) { - fprintf(stderr, "%s: waitpid() failed waiting for PID %d from \"%s\": %s\n", - ProgramName, pid, editor, strerror(errno)); + fprintf(stderr, "%s: waitpid() failed waiting for PID %ld from \"%s\": %s\n", + ProgramName, (long)pid, editor, strerror(errno)); } else if (xpid != pid) { - fprintf(stderr, "%s: wrong PID (%d != %d) from \"%s\"\n", - ProgramName, xpid, pid, editor); + fprintf(stderr, "%s: wrong PID (%ld != %ld) from \"%s\"\n", + ProgramName, (long)xpid, (long)pid, editor); goto fatal; } else if (WIFSTOPPED(waiter)) { raise(WSTOPSIG(waiter)); @@ -505,7 +492,7 @@ edit_cmd() { goto done; default: fprintf(stderr, "%s: panic: bad switch() in replace_cmd()\n", - ProgramName); + ProgramName); goto fatal; } remove: @@ -513,40 +500,40 @@ edit_cmd() { done: log_it(RealUser, Pid, "END EDIT", User); } - + /* returns 0 on success * -1 on syntax error * -2 on install error */ static int -replace_cmd() { - char n[MAX_FNAME], envstr[MAX_ENVSTR]; - FILE *tmp; - int ch, eof, fd; - int error = 0; - entry *e; - time_t now = time(NULL); - char **envp = env_init(); +replace_cmd(void) { + char n[MAX_FNAME], envstr[MAX_ENVSTR]; + FILE *tmp; + int ch, eof, fd; + int error = 0; + entry *e; + time_t now = time(NULL); + char **envp = env_init(); + struct stat sb; if (envp == NULL) { fprintf(stderr, "%s: Cannot allocate memory.\n", ProgramName); return (-2); } - - TempFilename = strdup(__CONCAT(SPOOL_DIR,"/tmp.XXXXXXXXXX")); - if (TempFilename == NULL) { - fprintf(stderr, "%s: Cannot allocate memory.\n", ProgramName); + if (!glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR, + "tmp.XXXXXXXXXX", '/')) { + TempFilename[0] = '\0'; + fprintf(stderr, "path too long\n"); return (-2); } if ((fd = mkstemp(TempFilename)) == -1 || !(tmp = fdopen(fd, "w+"))) { perror(TempFilename); if (fd != -1) { - fprintf(stderr, "%s: Cannot allocate memory.\n", - ProgramName); close(fd); unlink(TempFilename); } + TempFilename[0] = '\0'; return (-2); } @@ -568,7 +555,7 @@ replace_cmd() { Set_LineNum(1) while (EOF != (ch = get_char(NewCrontab))) putc(ch, tmp); - ftruncate(fileno(tmp), ftell(tmp)); + ftruncate(fileno(tmp), ftell(tmp)); /* XXX redundant with "w+"? */ fflush(tmp); rewind(tmp); if (ferror(tmp)) { @@ -610,29 +597,40 @@ replace_cmd() { goto done; } + if (fstat(fileno(tmp), &sb)) + sb.st_gid = -1; + #ifdef HAS_FCHOWN - if (fchown(fileno(tmp), ROOT_UID, -1) < OK) + if (fchown(fileno(tmp), ROOT_UID, sb.st_gid) < OK) { + perror("fchown"); + fclose(tmp); + error = -2; + goto done; + } #else - if (chown(TempFilename, ROOT_UID, -1) < OK) -#endif - { + if (chown(TempFilename, ROOT_UID, sb.st_gid) < OK) { perror("chown"); fclose(tmp); error = -2; goto done; } +#endif #ifdef HAS_FCHMOD - if (fchmod(fileno(tmp), 0600) < OK) + if (fchmod(fileno(tmp), 0600) < OK) { + perror("fchmod"); + fclose(tmp); + error = -2; + goto done; + } #else - if (chmod(TempFilename, 0600) < OK) -#endif - { - perror("chown"); + if (chmod(TempFilename, 0600) < OK) { + perror("chmod"); fclose(tmp); error = -2; goto done; } +#endif if (fclose(tmp) == EOF) { perror("fclose"); @@ -640,15 +638,19 @@ replace_cmd() { goto done; } - if (snprintf(n, sizeof n, CRON_TAB(User)) >= sizeof n || - rename(TempFilename, n)) { + if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { + fprintf(stderr, "path too long\n"); + error = -2; + goto done; + } + if (rename(TempFilename, n)) { fprintf(stderr, "%s: error renaming %s to %s\n", ProgramName, TempFilename, n); perror("rename"); error = -2; goto done; } - TempFilename = NULL; + TempFilename[0] = '\0'; log_it(RealUser, Pid, "REPLACE", User); poke_daemon(); @@ -657,45 +659,30 @@ done: (void) signal(SIGHUP, SIG_DFL); (void) signal(SIGINT, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); - if (TempFilename) { + if (TempFilename[0]) { (void) unlink(TempFilename); - free(TempFilename); + TempFilename[0] = '\0'; } return (error); } - static void poke_daemon() { -#ifdef USE_UTIMES - struct timeval tvs[2]; - struct timezone tz; - - (void) gettimeofday(&tvs[0], &tz); - tvs[1] = tvs[0]; - if (utimes(SPOOL_DIR, tvs) < OK) { - fprintf(stderr, "crontab: can't update mtime on spooldir\n"); - perror(SPOOL_DIR); - return; - } -#else if (utime(SPOOL_DIR, NULL) < OK) { fprintf(stderr, "crontab: can't update mtime on spooldir\n"); perror(SPOOL_DIR); return; } -#endif /*USE_UTIMES*/ } - static void -clean_turds(sig) - int sig; +clean_turds(signo) + int signo; { if (TempFilename[0]) (void) unlink(TempFilename); - if (sig) { - (void) signal(sig, SIG_DFL); - (void) kill(getpid(), sig); + if (signo) { + (void) signal(signo, SIG_DFL); + (void) raise(signo); } } diff --git a/usr.sbin/cron/database.c b/usr.sbin/cron/database.c index a60c16b4b9d..7fec60661c5 100644 --- a/usr.sbin/cron/database.c +++ b/usr.sbin/cron/database.c @@ -1,54 +1,49 @@ +/* $OpenBSD: database.c,v 1.5 2001/02/18 19:48:33 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: database.c,v 1.4 2000/08/21 21:08:56 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: database.c,v 1.5 2001/02/18 19:48:33 millert Exp $"; #endif /* vix 26jan87 [RCS has the log] */ - #include "cron.h" -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/file.h> - -#define TMAX(a,b) ((a)>(b)?(a):(b)) #define HASH(a,b) ((a)+(b)) -static void process_crontab __P((char *, char *, char *, - struct stat *, - cron_db *, cron_db *)); - +static void process_crontab(const char *, const char *, + const char *, struct stat *, + cron_db *, cron_db *); void -load_database(old_db) - cron_db *old_db; -{ - DIR *dir; - struct stat statbuf; - struct stat syscron_stat; - DIR_T *dp; - cron_db new_db; - user *u, *nu; +load_database(cron_db *old_db) { + struct stat statbuf, syscron_stat; + cron_db new_db; + DIR_T *dp; + DIR *dir; + user *u, *nu; - Debug(DLOAD, ("[%d] load_database()\n", getpid())) + Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid())) /* before we start loading any data, do a stat on SPOOL_DIR * so that if anything changes as of this moment (i.e., before we've @@ -72,8 +67,8 @@ load_database(old_db) * time this function is called. */ if (old_db->mtime == HASH(statbuf.st_mtime, syscron_stat.st_mtime)) { - Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n", - getpid())) + Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n", + (long)getpid())) return; } @@ -101,8 +96,7 @@ load_database(old_db) } while (NULL != (dp = readdir(dir))) { - char fname[MAXNAMLEN+1], - tabname[MAXPATHLEN]; + char fname[MAXNAMLEN+1], tabname[MAXNAMLEN]; /* avoid file names beginning with ".". this is good * because we would otherwise waste two guaranteed calls @@ -112,8 +106,13 @@ load_database(old_db) if (dp->d_name[0] == '.') continue; + if (strlen(dp->d_name) >= sizeof fname) + continue; /* XXX log? */ (void) strcpy(fname, dp->d_name); - snprintf(tabname, sizeof tabname, CRON_TAB(fname)); + + if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, + fname, '/')) + continue; /* XXX log? */ process_crontab(fname, fname, tabname, &statbuf, &new_db, old_db); @@ -142,12 +141,8 @@ load_database(old_db) Debug(DLOAD, ("load_database is done\n")) } - void -link_user(db, u) - cron_db *db; - user *u; -{ +link_user(cron_db *db, user *u) { if (db->head == NULL) db->head = u; if (db->tail) @@ -157,12 +152,8 @@ link_user(db, u) db->tail = u; } - void -unlink_user(db, u) - cron_db *db; - user *u; -{ +unlink_user(cron_db *db, user *u) { if (u->prev == NULL) db->head = u->next; else @@ -174,36 +165,25 @@ unlink_user(db, u) u->next->prev = u->prev; } - user * -find_user(db, name) - cron_db *db; - char *name; -{ - char *env_get(); - user *u; +find_user(cron_db *db, const char *name) { + user *u; for (u = db->head; u != NULL; u = u->next) - if (!strcmp(u->name, name)) + if (strcmp(u->name, name) == 0) break; - return u; + return (u); } - static void -process_crontab(uname, fname, tabname, statbuf, new_db, old_db) - char *uname; - char *fname; - char *tabname; - struct stat *statbuf; - cron_db *new_db; - cron_db *old_db; +process_crontab(const char *uname, const char *fname, const char *tabname, + struct stat *statbuf, cron_db *new_db, cron_db *old_db) { - struct passwd *pw = NULL; - int crontab_fd = OK - 1; - user *u; + struct passwd *pw = NULL; + int crontab_fd = OK - 1; + user *u; - if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) { + if (strcmp(fname, "*system*") != 0 && !(pw = getpwnam(uname))) { /* file doesn't have a user in passwd file. */ log_it(fname, getpid(), "ORPHAN", "no passwd entry"); @@ -253,7 +233,7 @@ process_crontab(uname, fname, tabname, statbuf, new_db, old_db) link_user(new_db, u); } -next_crontab: + next_crontab: if (crontab_fd >= OK) { Debug(DLOAD, (" [done]\n")) close(crontab_fd); diff --git a/usr.sbin/cron/do_command.c b/usr.sbin/cron/do_command.c index 2e3e008e22d..120aaacd905 100644 --- a/usr.sbin/cron/do_command.c +++ b/usr.sbin/cron/do_command.c @@ -1,48 +1,39 @@ +/* $OpenBSD: do_command.c,v 1.10 2001/02/18 19:48:33 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: do_command.c,v 1.9 2000/08/21 21:08:56 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: do_command.c,v 1.10 2001/02/18 19:48:33 millert Exp $"; #endif - #include "cron.h" -#include <sys/signal.h> -#if defined(sequent) -# include <sys/universe.h> -#endif -#if defined(SYSLOG) -# include <syslog.h> -#endif -#if defined(LOGIN_CAP) -# include <login_cap.h> -#endif - -static void child_process __P((entry *, user *)), - do_univ __P((user *)); +static void child_process(entry *, user *); +static int safe_p(const char *, const char *); void -do_command(e, u) - entry *e; - user *u; -{ - Debug(DPROC, ("[%d] do_command(%s, (%s,%d,%d))\n", - getpid(), e->cmd, u->name, e->uid, e->gid)) +do_command(entry *e, user *u) { + Debug(DPROC, ("[%ld] do_command(%s, (%s,%ld,%ld))\n", + (long)getpid(), e->cmd, u->name, + (long)e->uid, (long)e->gid)) /* fork to become asynchronous -- parent process is done immediately, * and continues to run the normal cron code, which means return to @@ -53,70 +44,55 @@ do_command(e, u) */ switch (fork()) { case -1: - log_it("CRON",getpid(),"error","can't fork"); + log_it("CRON", getpid(), "error", "can't fork"); break; case 0: /* child process */ acquire_daemonlock(1); child_process(e, u); - Debug(DPROC, ("[%d] child process done, exiting\n", getpid())) + Debug(DPROC, ("[%ld] child process done, exiting\n", + (long)getpid())) _exit(OK_EXIT); break; default: /* parent process */ break; } - Debug(DPROC, ("[%d] main process returning to work\n", getpid())) + Debug(DPROC, ("[%ld] main process returning to work\n",(long)getpid())) } - static void -child_process(e, u) - entry *e; - user *u; -{ - int stdin_pipe[2], stdout_pipe[2]; - char *input_data; - char *usernm, *mailto; - int children = 0; - -#ifdef __GNUC__ - (void) &input_data; /* Avoid vfork clobbering */ - (void) &mailto; - (void) &children; -#endif +child_process(entry *e, user *u) { + int stdin_pipe[2], stdout_pipe[2]; + char *usernm; + char * volatile input_data, * volatile mailto; + volatile int children = 0; - Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd)) + Debug(DPROC, ("[%ld] child_process('%s')\n", (long)getpid(), e->cmd)) +#ifdef CAPITALIZE_FOR_PS /* mark ourselves as different to PS command watchers by upshifting * our program name. This has no effect on some kernels. */ /*local*/{ - register char *pch; + char *pch; for (pch = ProgramName; *pch; pch++) *pch = MkUpper(*pch); } +#endif /* CAPITALIZE_FOR_PS */ /* discover some useful and important environment settings */ usernm = env_get("LOGNAME", e->envp); mailto = env_get("MAILTO", e->envp); -#ifdef USE_SIGCHLD /* our parent is watching for our death by catching SIGCHLD. we * do not care to watch for our children's deaths this way -- we - * use wait() explictly. so we have to disable the signal (which + * use wait() explictly. so we have to reset the signal (which * was inherited from the parent). */ (void) signal(SIGCHLD, SIG_DFL); -#else - /* on system-V systems, we are ignoring SIGCLD. we have to stop - * ignoring it now or the wait() in cron_pclose() won't work. - * because of this, we have to wait() for our children here, as well. - */ - (void) signal(SIGCLD, SIG_DFL); -#endif /*BSD*/ /* create some pipes to talk to our future child */ @@ -134,12 +110,13 @@ child_process(e, u) * If there are escaped %'s, remove the escape character. */ /*local*/{ - register int escaped = FALSE; - register int ch; - register char *p; + int escaped = FALSE; + int ch; + char *p; - for (input_data = p = e->cmd; (ch = *input_data); - input_data++, p++) { + for (input_data = p = e->cmd; + (ch = *input_data) != '\0'; + input_data++, p++) { if (p != input_data) *p = ch; if (escaped) { @@ -164,19 +141,19 @@ child_process(e, u) */ switch (vfork()) { case -1: - log_it("CRON",getpid(),"error","can't vfork"); + log_it("CRON", getpid(), "error", "can't vfork"); exit(ERROR_EXIT); /*NOTREACHED*/ case 0: - Debug(DPROC, ("[%d] grandchild process Vfork()'ed\n", - getpid())) + Debug(DPROC, ("[%ld] grandchild process Vfork()'ed\n", + (long)getpid())) /* write a log message. we've waited this long to do it * because it was not until now that we knew the PID that * the actual user command shell was going to get and the * PID is part of the log message. */ - /*local*/{ + if ((e->flags & DONT_LOG) == 0) { char *x = mkprints((u_char *)e->cmd, strlen(e->cmd)); log_it(usernm, getpid(), "CMD", x); @@ -214,16 +191,10 @@ child_process(e, u) close(stdin_pipe[READ_PIPE]); close(stdout_pipe[WRITE_PIPE]); - /* set our login universe. Do this in the grandchild - * so that the child can invoke /usr/lib/sendmail - * without surprises. - */ - do_univ(u); - /* set our directory, uid and gid. Set gid first, since once * we set uid, we've lost root privledges. */ -# ifdef LOGIN_CAP +#ifdef LOGIN_CAP { struct passwd *pwd; char *ep, *np; @@ -238,32 +209,38 @@ child_process(e, u) fprintf(stderr, "setusercontext failed for %d\n", e->uid); _exit(ERROR_EXIT); } +#ifdef BSD_AUTH + if (auth_approval(0, 0, pwd->pw_name, "cron") <= 0) { + fprintf(stderr, "approval failed for %d\n", e->uid); + _exit(ERROR_EXIT); + } +#endif /* BSD_AUTH */ /* If no PATH specified in crontab file but - * we just added on via login.conf, add it to + * we just added one via login.conf, add it to * the crontab environment. */ if (env_get("PATH", e->envp) == NULL && (ep = getenv("PATH"))) { np = malloc(strlen(ep) + 6); if (np) { - strcpy(np, "PATH="); - strcat(np, ep); - e->envp = env_set(e->envp, np); + strcpy(np, "PATH="); + strcat(np, ep); + e->envp = env_set(e->envp, np); } } + } - -# else +#else setgid(e->gid); -# if defined(BSD) initgroups(env_get("LOGNAME", e->envp), e->gid); -# endif setlogin(usernm); setuid(e->uid); /* we aren't root after this... */ -# endif + +#endif /* LOGIN_CAP */ chdir(env_get("HOME", e->envp)); - /* exec the command. + /* + * Exec the command. */ { char *shell = env_get("SHELL", e->envp); @@ -294,7 +271,7 @@ child_process(e, u) * the user's command. */ - Debug(DPROC, ("[%d] child continues, closing pipes\n", getpid())) + Debug(DPROC, ("[%ld] child continues, closing pipes\n",(long)getpid())) /* close the ends of the pipe that will only be referenced in the * grandchild process... @@ -314,12 +291,13 @@ child_process(e, u) */ if (*input_data && fork() == 0) { - register FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w"); - register int need_newline = FALSE; - register int escaped = FALSE; - register int ch; + FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w"); + int need_newline = FALSE; + int escaped = FALSE; + int ch; - Debug(DPROC, ("[%d] child2 sending data to grandchild\n", getpid())) + Debug(DPROC, ("[%ld] child2 sending data to grandchild\n", + (long)getpid())) /* close the pipe we don't use, since we inherited it and * are part of its reference count now. @@ -355,7 +333,8 @@ child_process(e, u) */ fclose(out); - Debug(DPROC, ("[%d] child2 done sending to grandchild\n", getpid())) + Debug(DPROC, ("[%ld] child2 done sending to grandchild\n", + (long)getpid())) exit(0); } @@ -373,28 +352,26 @@ child_process(e, u) * when the grandchild exits, we'll get EOF. */ - Debug(DPROC, ("[%d] child reading output from grandchild\n", getpid())) + Debug(DPROC, ("[%ld] child reading output from grandchild\n", + (long)getpid())) /*local*/{ - register FILE *in = fdopen(stdout_pipe[READ_PIPE], "r"); - register int ch = getc(in); + FILE *in = fdopen(stdout_pipe[READ_PIPE], "r"); + int ch = getc(in); if (ch != EOF) { - FILE *mail; - register int bytes = 1; - int status = 0; + FILE * volatile mail; + int bytes = 1; + int status = 0; -#ifdef __GNUC__ - (void) &mail; -#endif Debug(DPROC|DEXT, - ("[%d] got data (%x:%c) from grandchild\n", - getpid(), ch, ch)) + ("[%ld] got data (%x:%c) from grandchild\n", + (long)getpid(), ch, ch)) /* get name of recipient. this is MAILTO if set to a * valid local username; USER otherwise. */ - if (mailto) { + if (mailto && safe_p(usernm, mailto)) { /* MAILTO was present in the environment */ if (!*mailto) { @@ -414,15 +391,18 @@ child_process(e, u) */ if (mailto) { - register char **env; - auto char mailcmd[MAX_COMMAND]; - auto char hostname[MAXHOSTNAMELEN]; - - (void) gethostname(hostname, MAXHOSTNAMELEN); - (void) snprintf(mailcmd, sizeof(mailcmd), - MAILARGS, MAILCMD); + char **env; + char mailcmd[MAX_COMMAND]; + char hostname[MAXHOSTNAMELEN]; + + gethostname(hostname, MAXHOSTNAMELEN); + if (snprintf(mailcmd, sizeof mailcmd, MAILFMT, + MAILARG) >= sizeof mailcmd) { + fprintf(stderr, "mailcmd too long\n"); + (void) _exit(ERROR_EXIT); + } if (!(mail = cron_popen(mailcmd, "w", e))) { - perror(MAILCMD); + perror(mailcmd); (void) _exit(ERROR_EXIT); } fprintf(mail, "From: root (Cron Daemon)\n"); @@ -430,10 +410,10 @@ child_process(e, u) fprintf(mail, "Subject: Cron <%s@%s> %s\n", usernm, first_word(hostname, "."), e->cmd); -# if defined(MAIL_DATE) +#ifdef MAIL_DATE fprintf(mail, "Date: %s\n", arpadate(&StartTime)); -# endif /* MAIL_DATE */ +#endif /*MAIL_DATE*/ for (env = e->envp; *env; env++) fprintf(mail, "X-Cron-Env: <%s>\n", *env); @@ -441,7 +421,7 @@ child_process(e, u) /* this was the first char from the pipe */ - putc(ch, mail); + fputc(ch, mail); } /* we have to read the input pipe no matter whether @@ -452,7 +432,7 @@ child_process(e, u) while (EOF != (ch = getc(in))) { bytes++; if (mailto) - putc(ch, mail); + fputc(ch, mail); } /* only close pipe if we opened it -- i.e., we're @@ -460,8 +440,8 @@ child_process(e, u) */ if (mailto) { - Debug(DPROC, ("[%d] closing pipe to mail\n", - getpid())) + Debug(DPROC, ("[%ld] closing pipe to mail\n", + (long)getpid())) /* Note: the pclose will probably see * the termination of the grandchild * in addition to the mail process, since @@ -487,68 +467,47 @@ child_process(e, u) } /*if data from grandchild*/ - Debug(DPROC, ("[%d] got EOF from grandchild\n", getpid())) + Debug(DPROC, ("[%ld] got EOF from grandchild\n", + (long)getpid())) fclose(in); /* also closes stdout_pipe[READ_PIPE] */ } /* wait for children to die. */ - for (; children > 0; children--) - { - WAIT_T waiter; - PID_T pid; + for (; children > 0; children--) { + WAIT_T waiter; + PID_T pid; - Debug(DPROC, ("[%d] waiting for grandchild #%d to finish\n", - getpid(), children)) + Debug(DPROC, ("[%ld] waiting for grandchild #%d to finish\n", + (long)getpid(), children)) pid = wait(&waiter); if (pid < OK) { - Debug(DPROC, ("[%d] no more grandchildren--mail written?\n", - getpid())) + Debug(DPROC, + ("[%ld] no more grandchildren--mail written?\n", + (long)getpid())) break; } - Debug(DPROC, ("[%d] grandchild #%d finished, status=%04x", - getpid(), pid, WEXITSTATUS(waiter))) + Debug(DPROC, ("[%ld] grandchild #%ld finished, status=%04x", + (long)getpid(), (long)pid, WEXITSTATUS(waiter))) if (WIFSIGNALED(waiter) && WCOREDUMP(waiter)) Debug(DPROC, (", dumped core")) Debug(DPROC, ("\n")) } } - -static void -do_univ(u) - user *u; -{ -#if defined(sequent) -/* Dynix (Sequent) hack to put the user associated with - * the passed user structure into the ATT universe if - * necessary. We have to dig the gecos info out of - * the user's password entry to see if the magic - * "universe(att)" string is present. - */ - - struct passwd *p; - char *s; - int i; - - p = getpwuid(u->uid); - (void) endpwent(); - - if (p == NULL) - return; - - s = p->pw_gecos; - - for (i = 0; i < 4; i++) - { - if ((s = strchr(s, ',')) == NULL) - return; - s++; +static int +safe_p(const char *usernm, const char *s) { + static const char safe_delim[] = "@!:%-.,"; /* conservative! */ + const char *t; + int ch, first; + + for (t = s, first = 1; (ch = *t++) != '\0'; first = 0) { + if (isascii(ch) && isprint(ch) && + (isalnum(ch) || (!first && strchr(safe_delim, ch)))) + continue; + log_it(usernm, getpid(), "UNSAFE", s); + return (FALSE); } - if (strcmp(s, "universe(att)")) - return; - - (void) universe(U_ATT); -#endif + return (TRUE); } diff --git a/usr.sbin/cron/entry.c b/usr.sbin/cron/entry.c index 93a74d58e95..3b1906a84d5 100644 --- a/usr.sbin/cron/entry.c +++ b/usr.sbin/cron/entry.c @@ -1,22 +1,28 @@ -/* Copyright 1988,1990,1993,1994 by Paul Vixie +/* $OpenBSD: entry.c,v 1.8 2001/02/18 19:48:33 millert Exp $ */ +/* + * Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: entry.c,v 1.7 2000/08/21 21:08:56 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: entry.c,v 1.8 2001/02/18 19:48:33 millert Exp $"; #endif /* vix 26jan87 [RCS'd; rest of log is in RCS file] @@ -31,15 +37,10 @@ static char rcsid[] = "$Id: entry.c,v 1.7 2000/08/21 21:08:56 deraadt Exp $"; typedef enum ecode { e_none, e_minute, e_hour, e_dom, e_month, e_dow, - e_cmd, e_timespec, e_username + e_cmd, e_timespec, e_username, e_option } ecode_e; -static char get_list __P((bitstr_t *, int, int, char *[], int, FILE *)), - get_range __P((bitstr_t *, int, int, char *[], int, FILE *)), - get_number __P((int *, int, char *[], int, FILE *)); -static int set_element __P((bitstr_t *, int, int, int)); - -static char *ecodes[] = +static const char *ecodes[] = { "no error", "bad minute", @@ -50,8 +51,13 @@ static char *ecodes[] = "bad command", "bad time specifier", "bad username", + "bad option" }; +static char get_list(bitstr_t *, int, int, const char *[], int, FILE *), + get_range(bitstr_t *, int, int, const char *[], int, FILE *), + get_number(int *, int, const char *[], int, FILE *); +static int set_element(bitstr_t *, int, int, int); void free_entry(e) @@ -252,7 +258,8 @@ load_entry(file, error_func, pw, envp) ecode = e_username; goto eof; } - Debug(DPARS, ("load_entry()...uid %d, gid %d\n",e->uid,e->gid)) + Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n", + (long)e->uid, (long)e->gid)) } else if (ch == '*') { ecode = e_cmd; goto eof; @@ -269,55 +276,87 @@ load_entry(file, error_func, pw, envp) goto eof; } if (!env_get("SHELL", e->envp)) { - snprintf(envstr, sizeof envstr, "SHELL=%s", _PATH_BSHELL); - if ((tenvp = env_set(e->envp, envstr))) { - e->envp = tenvp; - } else { - ecode = e_none; - goto eof; - } + if (glue_strings(envstr, sizeof envstr, "SHELL", + _PATH_BSHELL, '=')) { + if ((tenvp = env_set(e->envp, envstr))) { + e->envp = tenvp; + } else { + ecode = e_none; + goto eof; + } + } else + log_it("CRON", getpid(), "error", "can't set SHELL"); } if (!env_get("HOME", e->envp)) { - snprintf(envstr, sizeof envstr, "HOME=%s", pw->pw_dir); + if (glue_strings(envstr, sizeof envstr, "HOME", + pw->pw_dir, '=')) { + if ((tenvp = env_set(e->envp, envstr))) { + e->envp = tenvp; + } else { + ecode = e_none; + goto eof; + } + } else + log_it("CRON", getpid(), "error", "can't set HOME"); + } +#ifdef LOGIN_CAP + if (!env_get("PATH", e->envp)) { + if (glue_strings(envstr, sizeof envstr, "PATH", + _PATH_DEFPATH, '=')) { + if ((tenvp = env_set(e->envp, envstr))) { + e->envp = tenvp; + } else { + ecode = e_none; + goto eof; + } + } else + log_it("CRON", getpid(), "error", "can't set PATH"); + } +#endif /* LOGIN_CAP */ + if (glue_strings(envstr, sizeof envstr, "LOGNAME", + pw->pw_name, '=')) { if ((tenvp = env_set(e->envp, envstr))) { e->envp = tenvp; } else { ecode = e_none; goto eof; } - } - if (!env_get("PATH", e->envp)) { - snprintf(envstr, sizeof envstr, "PATH=%s", _PATH_DEFPATH); + } else + log_it("CRON", getpid(), "error", "can't set LOGNAME"); +#if defined(BSD) + if (glue_strings(envstr, sizeof envstr, "USER", + pw->pw_name, '=')) { if ((tenvp = env_set(e->envp, envstr))) { e->envp = tenvp; } else { ecode = e_none; goto eof; } - } - snprintf(envstr, sizeof envstr, "%s=%s", "LOGNAME", pw->pw_name); - if ((tenvp = env_set(e->envp, envstr))) { - e->envp = tenvp; - } else { - ecode = e_none; - goto eof; - } -#if defined(BSD) - snprintf(envstr, sizeof envstr, "%s=%s", "USER", pw->pw_name); - if ((tenvp = env_set(e->envp, envstr))) { - e->envp = tenvp; - } else { - ecode = e_none; - goto eof; - } + } else + log_it("CRON", getpid(), "error", "can't set USER"); #endif Debug(DPARS, ("load_entry()...about to parse command\n")) + /* If the first character of the command is '-' it is a cron option. + */ + while ((ch = get_char(file)) == '-') { + switch (ch = get_char(file)) { + case 'q': + e->flags |= DONT_LOG; + Skip_Nonblanks(ch, file) + break; + default: + ecode = e_option; + goto eof; + } + Skip_Blanks(ch, file) + } + unget_char(ch, file); + /* Everything up to the next \n or EOF is part of the command... * too bad we don't know in advance how long it will be, since we * need to malloc a string for it... so, we limit it to MAX_COMMAND. - * XXX - should use realloc(). */ ch = get_string(cmd, MAX_COMMAND, file, "\n"); @@ -359,11 +398,11 @@ static char get_list(bits, low, high, names, ch, file) bitstr_t *bits; /* one bit per flag, default=FALSE */ int low, high; /* bounds, impl. offset for bitstr */ - char *names[]; /* NULL or *[] of names for these elements */ + const char *names[]; /* NULL or *[] of names for these elements */ int ch; /* current character being processed */ FILE *file; /* file being read */ { - register int done; + int done; /* we know that we point to a non-blank character here; * must do a Skip_Blanks before we exit, so that the @@ -406,15 +445,14 @@ static char get_range(bits, low, high, names, ch, file) bitstr_t *bits; /* one bit per flag, default=FALSE */ int low, high; /* bounds, impl. offset for bitstr */ - char *names[]; /* NULL or names of elements */ + const char *names[]; /* NULL or names of elements */ int ch; /* current character being processed */ FILE *file; /* file being read */ { /* range = number | number "-" number [ "/" number ] */ - register int i; - auto int num1, num2, num3; + int i, num1, num2, num3; Debug(DPARS|DEXT, ("get_range()...entering, exit won't show\n")) @@ -489,11 +527,11 @@ get_range(bits, low, high, names, ch, file) static char get_number(numptr, low, names, ch, file) - int *numptr; /* where does the result go? */ - int low; /* offset applied to result if symbolic enum used */ - char *names[]; /* symbolic names, if any, for enums */ - int ch; /* current character */ - FILE *file; /* source */ + int *numptr; /* where does the result go? */ + int low; /* offset applied to enum result */ + const char *names[]; /* symbolic names, if any, for enums */ + int ch; /* current character */ + FILE *file; /* source */ { char temp[MAX_TEMPSTR], *pc; int len, i, all_digits; diff --git a/usr.sbin/cron/env.c b/usr.sbin/cron/env.c index a9fc3252fab..69b59f419d8 100644 --- a/usr.sbin/cron/env.c +++ b/usr.sbin/cron/env.c @@ -1,22 +1,27 @@ +/* $OpenBSD: env.c,v 1.8 2001/02/18 19:48:34 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: env.c,v 1.7 2000/08/21 21:08:56 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: env.c,v 1.8 2001/02/18 19:48:34 millert Exp $"; #endif @@ -26,9 +31,9 @@ static char rcsid[] = "$Id: env.c,v 1.7 2000/08/21 21:08:56 deraadt Exp $"; char ** env_init() { - register char **p = (char **) malloc(sizeof(char **)); + char **p = (char **) malloc(sizeof(char **)); - if (p) + if (p != NULL) p[0] = NULL; return (p); } @@ -48,27 +53,26 @@ env_free(envp) char ** env_copy(envp) - register char **envp; + char **envp; { - register int count, i; - register char **p; + int count, i, save_errno; + char **p; for (count = 0; envp[count] != NULL; count++) ; p = (char **) malloc((count+1) * sizeof(char *)); /* 1 for the NULL */ - if (p == NULL) { - errno = ENOMEM; - return NULL; + if (p != NULL) { + for (i = 0; i < count; i++) + if ((p[i] = strdup(envp[i])) == NULL) { + save_errno = errno; + while (--i >= 0) + free(p[i]); + free(p); + errno = save_errno; + return (NULL); + } + p[count] = NULL; } - for (i = 0; i < count; i++) - if ((p[i] = strdup(envp[i])) == NULL) { - while (--i >= 0) - (void) free(p[i]); - free(p); - errno = ENOMEM; - return NULL; - } - p[count] = NULL; return (p); } @@ -78,8 +82,8 @@ env_set(envp, envstr) char **envp; char *envstr; { - register int count, found; - register char **p; + int count, found; + char **p, *cp; /* * count the number of elements, including the null pointer; @@ -100,8 +104,7 @@ env_set(envp, envstr) free(envp[found]); if ((envp[found] = strdup(envstr)) == NULL) { envp[found] = ""; - errno = ENOMEM; - return NULL; + return (NULL); } return (envp); } @@ -112,16 +115,14 @@ env_set(envp, envstr) * array. */ p = (char **) realloc((void *) envp, - (unsigned) ((count+1) * sizeof(char **))); - if (p == NULL) { - errno = ENOMEM; - return NULL; - } + (size_t) ((count+1) * sizeof(char **))); + if (p == NULL) + return (NULL); + cp = strdup(envstr); + if (cp == NULL) + return(NULL); p[count] = p[count-1]; - if ((p[count-1] = strdup(envstr)) == NULL) { - errno = ENOMEM; - return NULL; - } + p[count-1] = cp; return (p); } @@ -157,7 +158,8 @@ load_env(envstr, f) return (FALSE); } - /* 2 fields from scanf; looks like an env setting + /* + * 2 fields from scanf; looks like an env setting. */ /* @@ -176,8 +178,10 @@ load_env(envstr, f) } } - if (strlen(name) + 1 + strlen(val) >= MAX_ENVSTR-1) - return (FALSE); + /* + * This can't overflow because get_string() limited the size of the + * name and val fields. Still, it doesn't hurt... + */ (void) snprintf(envstr, MAX_ENVSTR, "%s=%s", name, val); Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr)) return (TRUE); @@ -186,13 +190,13 @@ load_env(envstr, f) char * env_get(name, envp) - register char *name; - register char **envp; + char *name; + char **envp; { - register int len = strlen(name); - register char *p, *q; + int len = strlen(name); + char *p, *q; - while ((p = *envp++) != NULL) { + while ((p = *envp++) != '\0') { if (!(q = strchr(p, '='))) continue; if ((q - p) == len && !strncmp(p, name, len)) diff --git a/usr.sbin/cron/externs.h b/usr.sbin/cron/externs.h index 5d104302279..11b3e7c6cec 100644 --- a/usr.sbin/cron/externs.h +++ b/usr.sbin/cron/externs.h @@ -1,68 +1,99 @@ +/* $OpenBSD: externs.h,v 1.3 2001/02/18 19:48:34 millert Exp $ */ + /* Copyright 1993,1994 by Paul Vixie * All rights reserved + */ +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ -#if defined(POSIX) || defined(ATT) -# include <stdlib.h> -# include <unistd.h> -# include <string.h> -# include <dirent.h> -# include <errno.h> -# define DIR_T struct dirent -# define WAIT_T int -# define WAIT_IS_INT 1 +/* reorder these #include's at your peril */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/stat.h> + +#include <bitstring.h> +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <locale.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> + +#if defined(SYSLOG) +# include <syslog.h> +#endif + +#if (defined(BSD)) && (BSD >= 199103) || defined(__linux) || defined(AIX) +# include <paths.h> +#endif /*BSD*/ + +#if !defined(_PATH_SENDMAIL) +# define _PATH_SENDMAIL "/usr/lib/sendmail" +#endif /*SENDMAIL*/ + +#if defined(LOGIN_CAP) +#include <login_cap.h> +#endif /*LOGIN_CAP*/ + +#if defined(BSD_AUTH) +#include <bsd_auth.h> +#endif /*BSD_AUTH*/ + +#define DIR_T struct dirent +#define WAIT_T int +#define SIG_T sig_t +#define TIME_T time_t +#define PID_T pid_t + +#ifndef TZNAME_ALREADY_DEFINED extern char *tzname[2]; -# define TZONE(tm) tzname[(tm).tm_isdst] #endif +#define TZONE(tm) tzname[(tm).tm_isdst] -#if defined(UNIXPC) -# undef WAIT_T -# undef WAIT_IS_INT -# define WAIT_T union wait +#if (BSD >= 198606) +# define HAVE_FCHOWN +# define HAVE_FCHMOD #endif -#if defined(POSIX) -# define SIG_T sig_t -# define TIME_T time_t -# define PID_T pid_t +#if (BSD >= 199103) +# define HAVE_SAVED_UIDS #endif -#if defined(ATT) -# define SIG_T void -# define TIME_T long -# define PID_T int -#endif +#define MY_UID(pw) getuid() +#define MY_GID(pw) getgid() -#if !defined(POSIX) && !defined(ATT) -/* classic BSD */ -extern time_t time(); -extern unsigned sleep(); -extern struct tm *localtime(); -extern struct passwd *getpwnam(); -extern int errno; -extern void perror(), exit(), free(); -extern char *getenv(), *strcpy(), *strchr(), *strtok(); -extern void *malloc(), *realloc(); -# define SIG_T void -# define TIME_T long -# define PID_T int -# define WAIT_T union wait -# define DIR_T struct direct -# include <sys/dir.h> -# define TZONE(tm) (tm).tm_zone +#if !defined(AIX) && !defined(UNICOS) +# define SYS_TIME_H 1 +#else +# define SYS_TIME_H 0 #endif /* getopt() isn't part of POSIX. some systems define it in <stdlib.h> anyway. @@ -71,8 +102,8 @@ extern void *malloc(), *realloc(); * in ways that we cannot predict or comprehend, yet do not define the adjunct * external variables needed for the interface. */ -#if (!defined(BSD) || (BSD < 198911)) && !defined(ATT) && !defined(UNICOS) -int getopt __P((int, char * const *, const char *)); +#if (!defined(BSD) || (BSD < 198911)) +int getopt(int, char * const *, const char *); #endif #if (!defined(BSD) || (BSD < 199103)) @@ -80,67 +111,21 @@ extern char *optarg; extern int optind, opterr, optopt; #endif -#if WAIT_IS_INT -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) (((x) >> 8) & 0xff) -# endif -# ifndef WTERMSIG -# define WTERMSIG(x) ((x) & 0x7f) -# endif -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x) & 0x80) -# endif -#else /*WAIT_IS_INT*/ -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) ((x).w_retcode) -# endif -# ifndef WTERMSIG -# define WTERMSIG(x) ((x).w_termsig) -# endif -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x).w_coredump) -# endif -#endif /*WAIT_IS_INT*/ - -#ifndef WIFSIGNALED -#define WIFSIGNALED(x) (WTERMSIG(x) != 0) -#endif -#ifndef WIFEXITED -#define WIFEXITED(x) (WTERMSIG(x) == 0) -#endif - -#ifdef NEED_STRCASECMP -extern int strcasecmp __P((char *, char *)); -#endif - -#ifdef NEED_STRDUP -extern char *strdup __P((char *)); -#endif - -#ifdef NEED_STRERROR -extern char *strerror __P((int)); -#endif +/* digital unix needs this but does not give us a way to identify it. + */ +extern int flock(int, int); -#ifdef NEED_FLOCK -extern int flock __P((int, int)); +/* not all systems who provice flock() provide these definitions. + */ +#ifndef LOCK_SH # define LOCK_SH 1 -# define LOCK_EX 2 -# define LOCK_NB 4 -# define LOCK_UN 8 -#endif - -#ifdef NEED_SETSID -extern int setsid __P((void)); #endif - -#ifdef NEED_GETDTABLESIZE -extern int getdtablesize __P((void)); +#ifndef LOCK_EX +# define LOCK_EX 2 #endif - -#ifdef NEED_SETENV -extern int setenv __P((char *, char *, int)); +#ifndef LOCK_NB +# define LOCK_NB 4 #endif - -#ifdef NEED_VFORK -extern PID_T vfork __P((void)); +#ifndef LOCK_UN +# define LOCK_UN 8 #endif diff --git a/usr.sbin/cron/funcs.h b/usr.sbin/cron/funcs.h new file mode 100644 index 00000000000..4e2e0289b89 --- /dev/null +++ b/usr.sbin/cron/funcs.h @@ -0,0 +1,70 @@ +/* $OpenBSD: funcs.h,v 1.1 2001/02/18 19:48:35 millert Exp $ */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Notes: + * This file has to be included by cron.h after data structure defs. + * We should reorg this into sections by module. + */ + +void set_cron_uid(void), + set_cron_cwd(void), + load_database(cron_db *), + open_logfile(void), + sigpipe_func(void), + job_add(entry *, user *), + do_command(entry *, user *), + link_user(cron_db *, user *), + unlink_user(cron_db *, user *), + free_user(user *), + env_free(char **), + unget_char(int, FILE *), + free_entry(entry *), + acquire_daemonlock(int), + skip_comments(FILE *), + log_it(const char *, int, const char *, const char *), + log_close(void); + +int job_runqueue(void), + set_debug_flags(char *), + get_char(FILE *), + get_string(char *, int, FILE *, char *), + swap_uids(void), + swap_uids_back __P((void)), + load_env(char *, FILE *), + cron_pclose(FILE *), + glue_strings(char *, int, char *, char *, int), + strcmp_until(const char *, const char *, int), + allowed(char *), + strdtb(char *); + +char *env_get(char *, char **), + *arpadate(time_t *), + *mkprints(unsigned char *, unsigned int), + *first_word(char *, char *), + **env_init(void), + **env_copy(char **), + **env_set(char **, char *); + +user *load_user(int, struct passwd *, const char *), + *find_user(cron_db *, const char *); + +entry *load_entry(FILE *, void (*)(), + struct passwd *, char **); + +FILE *cron_popen(char *, char *, entry *); diff --git a/usr.sbin/cron/globals.h b/usr.sbin/cron/globals.h new file mode 100644 index 00000000000..a6063785b1f --- /dev/null +++ b/usr.sbin/cron/globals.h @@ -0,0 +1,77 @@ +/* $OpenBSD: globals.h,v 1.1 2001/02/18 19:48:35 millert Exp $ */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef MAIN_PROGRAM +# define XTRN +# define INIT(x) = x +#else +# define XTRN extern +# define INIT(x) +#endif + +XTRN const char *copyright[] +#ifdef MAIN_PROGRAM + = { + "@(#) Copyright 1988,1989,1990,1993,1994 by Paul Vixie", + "@(#) Copyright 1997 by Internet Software Consortium, Inc.", + "@(#) All rights reserved", + NULL + } +#endif + ; + +XTRN const char *MonthNames[] +#ifdef MAIN_PROGRAM + = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun",\ + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",\ + NULL + } +#endif + ; + +XTRN const char *DowNames[] +#ifdef MAIN_PROGRAM + = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",\ + NULL + } +#endif + ; + +XTRN const char *ProgramName INIT("amnesia"); +XTRN int LineNumber INIT(0); +XTRN time_t StartTime INIT(0); +XTRN time_min timeRunning INIT(0); +XTRN time_min virtualTime INIT(0); +XTRN time_min clockTime INIT(0); + +#if DEBUGGING +XTRN int DebugFlags INIT(0); +XTRN const char *DebugFlagNames[] +#ifdef MAIN_PROGRAM + = { + "ext", "sch", "proc", "pars", "load", "misc", "test", "bit",\ + NULL + } +#endif + ; +#else +#define DebugFlags 0 +#endif /* DEBUGGING */ diff --git a/usr.sbin/cron/job.c b/usr.sbin/cron/job.c index 18e96b6e36b..c85c7270d53 100644 --- a/usr.sbin/cron/job.c +++ b/usr.sbin/cron/job.c @@ -1,22 +1,27 @@ +/* $OpenBSD: job.c,v 1.3 2001/02/18 19:48:35 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: job.c,v 1.2 1996/11/01 23:27:36 millert Exp $"; +static char rcsid[] = "$OpenBSD: job.c,v 1.3 2001/02/18 19:48:35 millert Exp $"; #endif @@ -35,14 +40,15 @@ static job *jhead = NULL, *jtail = NULL; void job_add(e, u) - register entry *e; - register user *u; + entry *e; + user *u; { - register job *j; + job *j; /* if already on queue, keep going */ - for (j=jhead; j; j=j->next) - if (j->e == e && j->u == u) { return; } + for (j = jhead; j != NULL; j = j->next) + if (j->e == e && j->u == u) + return; /* build a job queue element */ if ((j = (job*)malloc(sizeof(job))) == NULL) @@ -52,8 +58,10 @@ job_add(e, u) j->u = u; /* add it to the tail */ - if (!jhead) { jhead=j; } - else { jtail->next=j; } + if (jhead == NULL) + jhead = j; + else + jtail->next = j; jtail = j; } @@ -61,15 +69,15 @@ job_add(e, u) int job_runqueue() { - register job *j, *jn; - register int run = 0; + job *j, *jn; + int run = 0; - for (j=jhead; j; j=jn) { + for (j = jhead; j; j = jn) { do_command(j->e, j->u); jn = j->next; free(j); run++; } jhead = jtail = NULL; - return run; + return (run); } diff --git a/usr.sbin/cron/macros.h b/usr.sbin/cron/macros.h new file mode 100644 index 00000000000..8dfae8772f3 --- /dev/null +++ b/usr.sbin/cron/macros.h @@ -0,0 +1,125 @@ +/* $OpenBSD: macros.h,v 1.1 2001/02/18 19:48:35 millert Exp $ */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + /* these are really immutable, and are + * defined for symbolic convenience only + * TRUE, FALSE, and ERR must be distinct + * ERR must be < OK. + */ +#define TRUE 1 +#define FALSE 0 + /* system calls return this on success */ +#define OK 0 + /* or this on error */ +#define ERR (-1) + + /* turn this on to get '-x' code */ +#ifndef DEBUGGING +#define DEBUGGING FALSE +#endif + +#define INIT_PID 1 /* parent of orphans */ +#define READ_PIPE 0 /* which end of a pipe pair do you read? */ +#define WRITE_PIPE 1 /* or write to? */ +#define STDIN 0 /* what is stdin's file descriptor? */ +#define STDOUT 1 /* stdout's? */ +#define STDERR 2 /* stderr's? */ +#define ERROR_EXIT 1 /* exit() with this will scare the shell */ +#define OK_EXIT 0 /* exit() with this is considered 'normal' */ +#define MAX_FNAME 100 /* max length of internally generated fn */ +#define MAX_COMMAND 1000 /* max length of internally generated cmd */ +#define MAX_ENVSTR 1000 /* max length of envvar=value\0 strings */ +#define MAX_TEMPSTR 100 /* obvious */ +#define MAX_UNAME (_PW_NAME_LEN+1) /* max length of username, should be overkill */ +#define ROOT_UID 0 /* don't change this, it really must be root */ +#define ROOT_USER "root" /* ditto */ + + /* NOTE: these correspond to DebugFlagNames, + * defined below. + */ +#define DEXT 0x0001 /* extend flag for other debug masks */ +#define DSCH 0x0002 /* scheduling debug mask */ +#define DPROC 0x0004 /* process control debug mask */ +#define DPARS 0x0008 /* parsing debug mask */ +#define DLOAD 0x0010 /* database loading debug mask */ +#define DMISC 0x0020 /* misc debug mask */ +#define DTEST 0x0040 /* test mode: don't execute any commands */ +#define DBIT 0x0080 /* bit twiddling shown (long) */ + +#define CRON_TAB(u) "%s/%s", SPOOL_DIR, u +#define PPC_NULL ((const char **)NULL) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define Skip_Blanks(c, f) \ + while (c == '\t' || c == ' ') \ + c = get_char(f); + +#define Skip_Nonblanks(c, f) \ + while (c!='\t' && c!=' ' && c!='\n' && c != EOF) \ + c = get_char(f); + +#define Skip_Line(c, f) \ + do {c = get_char(f);} while (c != '\n' && c != EOF); + +#if DEBUGGING +# define Debug(mask, message) \ + if ( (DebugFlags & (mask) ) == (mask) ) \ + printf message; +#else /* !DEBUGGING */ +# define Debug(mask, message) \ + ; +#endif /* DEBUGGING */ + +#define MkLower(ch) (isupper(ch) ? tolower(ch) : ch) +#define MkUpper(ch) (islower(ch) ? toupper(ch) : ch) +#define Set_LineNum(ln) {Debug(DPARS|DEXT,("linenum=%d\n",ln)); \ + LineNumber = ln; \ + } + +#define SECONDS_PER_MINUTE 60 + +#define FIRST_MINUTE 0 +#define LAST_MINUTE 59 +#define MINUTE_COUNT (LAST_MINUTE - FIRST_MINUTE + 1) + +#define FIRST_HOUR 0 +#define LAST_HOUR 23 +#define HOUR_COUNT (LAST_HOUR - FIRST_HOUR + 1) + +#define FIRST_DOM 1 +#define LAST_DOM 31 +#define DOM_COUNT (LAST_DOM - FIRST_DOM + 1) + +#define FIRST_MONTH 1 +#define LAST_MONTH 12 +#define MONTH_COUNT (LAST_MONTH - FIRST_MONTH + 1) + +/* note on DOW: 0 and 7 are both Sunday, for compatibility reasons. */ +#define FIRST_DOW 0 +#define LAST_DOW 7 +#define DOW_COUNT (LAST_DOW - FIRST_DOW + 1) + + /* each user's crontab will be held as a list of + * the following structure. + * + * These are the cron commands. + */ diff --git a/usr.sbin/cron/misc.c b/usr.sbin/cron/misc.c index 53193779777..07ca1452e0c 100644 --- a/usr.sbin/cron/misc.c +++ b/usr.sbin/cron/misc.c @@ -1,22 +1,27 @@ +/* $OpenBSD: misc.c,v 1.8 2001/02/18 19:48:35 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: misc.c,v 1.7 2000/08/21 21:08:57 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: misc.c,v 1.8 2001/02/18 19:48:35 millert Exp $"; #endif /* vix 26jan87 [RCS has the rest of the log] @@ -33,29 +38,64 @@ static char rcsid[] = "$Id: misc.c,v 1.7 2000/08/21 21:08:57 deraadt Exp $"; #include <sys/file.h> #include <sys/stat.h> #include <errno.h> -#include <string.h> #include <fcntl.h> #if defined(SYSLOG) # include <syslog.h> #endif +#if defined(LOG_CRON) && defined(LOG_FILE) +# undef LOG_FILE +#endif + #if defined(LOG_DAEMON) && !defined(LOG_CRON) -#define LOG_CRON LOG_DAEMON +# define LOG_CRON LOG_DAEMON #endif static int LogFD = ERR; - +/* + * glue_strings is the overflow-safe equivalent of + * sprintf(buffer, "%s%c%s", a, separator, b); + * + * returns 1 on success, 0 on failure. 'buffer' MUST NOT be used if + * glue_strings fails. + */ int -strcmp_until(left, right, until) - char *left; - char *right; - int until; +glue_strings(buffer, buffer_size, a, b, separator) + char *buffer; + int buffer_size; + char *a; + char *b; + int separator; { - register int diff; + char *buf; + char *buf_end; + + if (buffer_size <= 0) + return (0); + buf_end = buffer + buffer_size; + buf = buffer; + + for ( /* nothing */; buf < buf_end && *a != '\0'; buf++, a++ ) + *buf = *a; + if (buf == buf_end) + return (0); + if (separator != '/' || buf == buffer || buf[-1] != '/') + *buf++ = separator; + if (buf == buf_end) + return (0); + for ( /* nothing */; buf < buf_end && *b != '\0'; buf++, b++ ) + *buf = *b; + if (buf == buf_end) + return (0); + *buf = '\0'; + return (1); +} +int +strcmp_until(const char *left, const char *right, int until) { while (*left && *left != until && *left == *right) { left++; right++; @@ -63,12 +103,9 @@ strcmp_until(left, right, until) if ((*left=='\0' || *left == until) && (*right=='\0' || *right == until)) { - diff = 0; - } else { - diff = *left - *right; + return (0); } - - return diff; + return (*left - *right); } @@ -99,7 +136,7 @@ strdtb(s) /* the difference between the position of the null character and * the position of the first character of the string is the length. */ - return x - s; + return (x - s); } @@ -116,7 +153,7 @@ set_debug_flags(flags) #if !DEBUGGING printf("this program was compiled without debugging enabled\n"); - return FALSE; + return (FALSE); #else /* DEBUGGING */ @@ -125,13 +162,13 @@ set_debug_flags(flags) DebugFlags = 0; while (*pc) { - char **test; - int mask; + const char **test; + int mask; /* try to find debug flag name in our list. */ for ( test = DebugFlagNames, mask = 1; - *test && strcmp_until(*test, pc, ','); + *test != NULL && strcmp_until(*test, pc, ','); test++, mask <<= 1 ) ; @@ -140,7 +177,7 @@ set_debug_flags(flags) fprintf(stderr, "unrecognized debug flag <%s> <%s>\n", flags, pc); - return FALSE; + return (FALSE); } DebugFlags |= mask; @@ -164,7 +201,7 @@ set_debug_flags(flags) fprintf(stderr, "\n"); } - return TRUE; + return (TRUE); #endif /* DEBUGGING */ } @@ -251,6 +288,9 @@ acquire_daemonlock(closeflag) int closeflag; { static FILE *fp = NULL; + char buf[3*MAX_FNAME]; + char pidfile[MAX_FNAME]; + int fd, otherpid; if (closeflag && fp) { fclose(fp); @@ -259,14 +299,15 @@ acquire_daemonlock(closeflag) } if (!fp) { - char pidfile[MAX_FNAME]; - char buf[MAX_TEMPSTR]; - int fd, otherpid; - - if (snprintf(pidfile, sizeof pidfile, PIDFILE, - PIDDIR) >= sizeof pidfile || - (fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 || - (fp = fdopen(fd, "r+")) == NULL) { + if (!glue_strings(pidfile, sizeof pidfile, PIDDIR, + PIDFILE, '/')) { + fprintf(stderr, "%s%s: path too long\n", + PIDDIR, PIDFILE); + log_it("CRON", getpid(), "DEATH", "path too long"); + exit(ERROR_EXIT); + } + if ((-1 == (fd = open(pidfile, O_RDWR|O_CREAT, 0644))) || + (NULL == (fp = fdopen(fd, "r+")))) { snprintf(buf, sizeof buf, "can't open or create %s: %s", pidfile, strerror(errno)); fprintf(stderr, "%s: %s\n", ProgramName, buf); @@ -279,8 +320,8 @@ acquire_daemonlock(closeflag) fscanf(fp, "%d", &otherpid); snprintf(buf, sizeof buf, - "can't lock %s, otherpid may be %d: %s", - pidfile, otherpid, strerror(save_errno)); + "can't lock %s, otherpid may be %d: %s", + pidfile, otherpid, strerror(save_errno)); fprintf(stderr, "%s: %s\n", ProgramName, buf); log_it("CRON", getpid(), "DEATH", buf); exit(ERROR_EXIT); @@ -290,7 +331,7 @@ acquire_daemonlock(closeflag) } rewind(fp); - fprintf(fp, "%d\n", getpid()); + fprintf(fp, "%ld\n", (long)getpid()); fflush(fp); (void) ftruncate(fileno(fp), ftell(fp)); @@ -310,7 +351,7 @@ get_char(file) ch = getc(file); if (ch == '\n') Set_LineNum(LineNumber + 1) - return ch; + return (ch); } @@ -352,7 +393,7 @@ get_string(string, size, file, terms) if (size > 0) *string = '\0'; - return ch; + return (ch); } @@ -412,9 +453,9 @@ in_file(string, file) if (line[0] != '\0') line[strlen(line)-1] = '\0'; if (0 == strcmp(line, string)) - return TRUE; + return (TRUE); } - return FALSE; + return (FALSE); } @@ -450,37 +491,38 @@ allowed(username) #if defined(ALLOW_ONLY_ROOT) return (strcmp(username, ROOT_USER) == 0); #else - return TRUE; + return (TRUE); #endif } void log_it(username, xpid, event, detail) - char *username; + const char *username; int xpid; - char *event; - char *detail; + const char *event; + const char *detail; { - PID_T pid = xpid; +#if defined(LOG_FILE) || DEBUGGING + PID_T pid = xpid; +#endif #if defined(LOG_FILE) - char *msg; - TIME_T now = time((TIME_T) 0); - register struct tm *t = localtime(&now); - int msglen; + char *msg; + size_t msglen; + TIME_T now = time((TIME_T) 0); + struct tm *t = localtime(&now); #endif /*LOG_FILE*/ #if defined(SYSLOG) - static int syslog_open = 0; + static int syslog_open = 0; #endif #if defined(LOG_FILE) /* we assume that MAX_TEMPSTR will hold the date, time, &punctuation. */ msglen = strlen(username) + strlen(event) + strlen(detail) + - MAX_TEMPSTR); - msg = malloc(msglen); - if (!msg) + MAX_TEMPSTR; + if ((msg = malloc(msglen)) == NULL) return; if (LogFD < OK) { @@ -499,10 +541,12 @@ log_it(username, xpid, event, detail) * to the log file. */ snprintf(msg, msglen, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n", - username, - t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, pid, - event, detail); + username, + t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, pid, + event, detail); + /* we have to run strlen() because sprintf() returns (char*) on old BSD + */ if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) { if (LogFD >= OK) perror(LOG_FILE); @@ -533,8 +577,8 @@ log_it(username, xpid, event, detail) #if DEBUGGING if (DebugFlags) { - fprintf(stderr, "log_it: (%s %d) %s (%s)\n", - username, pid, event, detail); + fprintf(stderr, "log_it: (%s %ld) %s (%s)\n", + username, (long)pid, event, detail); } #endif } @@ -555,12 +599,12 @@ log_close() { */ char * first_word(s, t) - register char *s; /* string we want the first word of */ - register char *t; /* terminators, implicitly including \0 */ + char *s; /* string we want the first word of */ + char *t; /* terminators, implicitly including \0 */ { static char retbuf[2][MAX_TEMPSTR + 1]; /* sure wish C had GC */ static int retsel = 0; - register char *rb, *rp; + char *rb, *rp; /* select a return buffer */ retsel = 1-retsel; @@ -579,7 +623,7 @@ first_word(s, t) /* finish the return-string and return it */ *rp = '\0'; - return rb; + return (rb); } @@ -588,13 +632,18 @@ first_word(s, t) */ void mkprint(dst, src, len) - register char *dst; - register unsigned char *src; - register int len; + char *dst; + unsigned char *src; + int len; { + /* + * XXX + * We know this routine can't overflow the dst buffer because mkprints() + * allocated enough space for the worst case. + */ while (len-- > 0) { - register unsigned char ch = *src++; + unsigned char ch = *src++; if (ch < ' ') { /* control character */ *dst++ = '^'; @@ -618,15 +667,15 @@ mkprint(dst, src, len) */ char * mkprints(src, len) - register unsigned char *src; - register unsigned int len; + unsigned char *src; + unsigned int len; { - register char *dst = malloc(len*4 + 1); + char *dst = malloc(len*4 + 1); if (dst) mkprint(dst, src, len); - return dst; + return (dst); } @@ -638,9 +687,9 @@ char * arpadate(clock) time_t *clock; { - static char ret[64]; /* zone name might be >3 chars */ time_t t = clock ? *clock : time(NULL); struct tm *tm = localtime(&t); + static char ret[64]; /* zone name might be >3 chars */ char *qmark; size_t len; int hours = tm->tm_gmtoff / 3600; @@ -654,23 +703,22 @@ arpadate(clock) if (len == 0) { ret[0] = '?'; ret[1] = '\0'; - return ret; + return (ret); } qmark = strchr(ret, '?'); if (qmark && len - (qmark - ret) >= 6) { snprintf(qmark, 6, "% .2d%.2d", hours, minutes); qmark[5] = ' '; } - return ret; + return (ret); } #endif /*MAIL_DATE*/ - #ifdef HAVE_SAVED_UIDS static uid_t save_euid; -int swap_uids() { save_euid = geteuid(); return seteuid(getuid()); } -int swap_uids_back() { return seteuid(save_euid); } +int swap_uids() { save_euid = geteuid(); return (seteuid(getuid())); } +int swap_uids_back() { return (seteuid(save_euid)); } #else /*HAVE_SAVED_UIDS*/ -int swap_uids() { return setreuid(geteuid(), getuid()); } -int swap_uids_back() { return swap_uids(); } +int swap_uids() { return (setreuid(geteuid(), getuid())); } +int swap_uids_back() { return (swap_uids()); } #endif /*HAVE_SAVED_UIDS*/ diff --git a/usr.sbin/cron/pathnames.h b/usr.sbin/cron/pathnames.h index bd46f47afb4..e01e0321843 100644 --- a/usr.sbin/cron/pathnames.h +++ b/usr.sbin/cron/pathnames.h @@ -1,28 +1,25 @@ +/* $OpenBSD: pathnames.h,v 1.3 2001/02/18 19:48:36 millert Exp $ */ + /* Copyright 1993,1994 by Paul Vixie * All rights reserved - * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. - * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul */ - /* - * $Id: pathnames.h,v 1.2 1998/03/30 06:59:46 deraadt Exp $ + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ -#if (defined(BSD)) && (BSD >= 199103) || defined(__linux) || defined(AIX) -# include <paths.h> -#endif /*BSD*/ - #ifndef CRONDIR /* CRONDIR is where crond(8) and crontab(1) both chdir * to; SPOOL_DIR, ALLOW_FILE, DENY_FILE, and LOG_FILE @@ -45,11 +42,13 @@ * that ALLOW_FILE and DENY_FILE must both be defined * in order to enable the allow/deny code. If neither * LOG_FILE or SYSLOG is defined, we don't log. If - * both are defined, we log both ways. + * both are defined, we log both ways. Note that if + * LOG_CRON is defined by <syslog.h>, LOG_FILE will not + * be used. */ -#define ALLOW_FILE "allow" /*-*/ -#define DENY_FILE "deny" /*-*/ -/* #define LOG_FILE "log" -*/ +#define ALLOW_FILE "allow" +#define DENY_FILE "deny" +#define LOG_FILE "log" /* where should the daemon stick its PID? */ @@ -58,7 +57,7 @@ #else # define PIDDIR "/etc/" #endif -#define PIDFILE "%scron.pid" +#define PIDFILE "cron.pid" /* 4.3BSD-style crontab */ #define SYSCRONTAB "/etc/crontab" @@ -79,3 +78,7 @@ #ifndef _PATH_DEFPATH # define _PATH_DEFPATH "/usr/bin:/bin" #endif + +#ifndef _PATH_TMP +# define _PATH_TMP "/tmp" +#endif diff --git a/usr.sbin/cron/popen.c b/usr.sbin/cron/popen.c index 15d7e50cbcd..e13db8842b4 100644 --- a/usr.sbin/cron/popen.c +++ b/usr.sbin/cron/popen.c @@ -1,3 +1,4 @@ +/* $OpenBSD: popen.c,v 1.8 2001/02/18 19:48:36 millert Exp $ */ /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. @@ -24,22 +25,14 @@ */ #ifndef lint -static char rcsid[] = "$Id: popen.c,v 1.7 2000/08/21 21:01:21 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: popen.c,v 1.8 2001/02/18 19:48:36 millert Exp $"; static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89"; #endif /* not lint */ #include "cron.h" -#include <signal.h> -#include <syslog.h> -#include <unistd.h> -#include <grp.h> - -#if defined(LOGIN_CAP) -# include <login_cap.h> -#endif - #define MAX_ARGS 100 +#define MAX_GARGS 1000 #define WANT_GLOBBING 0 /* @@ -52,37 +45,34 @@ static int fds; FILE * cron_popen(program, type, e) - char *program, *type; + char *program; + char *type; entry *e; { - register char *cp; - FILE *iop; + char *cp; + FILE * volatile iop; int argc, pdes[2]; PID_T pid; char *argv[MAX_ARGS + 1]; #if WANT_GLOBBING char **pop, *vv[2]; int gargc; - char *gargv[1000]; + char *gargv[MAX_GARGS]; extern char **glob(), **copyblk(); #endif -#ifdef __GNUC__ - (void) &iop; /* Avoid vfork clobbering */ -#endif - - if ((*type != 'r' && *type != 'w') || type[1]) - return(NULL); + if ((*type != 'r' && *type != 'w') || type[1] != '\0') + return (NULL); if (!pids) { - if ((fds = getdtablesize()) <= 0) - return(NULL); - if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T))))) - return(NULL); + if ((fds = sysconf(_SC_OPEN_MAX)) <= 0) + return (NULL); + if (!(pids = (PID_T *)malloc((size_t)(fds * sizeof(PID_T))))) + return (NULL); bzero((char *)pids, fds * sizeof(PID_T)); } if (pipe(pdes) < 0) - return(NULL); + return (NULL); /* break up string into pieces */ for (argc = 0, cp = program; argc < MAX_ARGS; cp = NULL) @@ -100,7 +90,7 @@ cron_popen(program, type, e) pop = copyblk(vv); } argv[argc] = (char *)pop; /* save to free later */ - while (*pop && gargc < 1000) + while (*pop && gargc < MAX_GARGS) gargv[gargc++] = *pop++; } gargv[gargc] = NULL; @@ -144,14 +134,14 @@ cron_popen(program, type, e) } #else if (setgid(e->gid) || - setgroups(0, NULL) || - initgroups(env_get("LOGNAME", e->envp), e->gid)) - _exit(1); + setgroups(0, NULL) || + initgroups(env_get("LOGNAME", e->envp), e->gid)) + _exit(1); setlogin(env_get("LOGNAME", e->envp)); if (setuid(e->uid)) _exit(1); chdir(env_get("HOME", e->envp)); -#endif +#endif /* LOGIN_CAP */ } #if WANT_GLOBBING execvp(gargv[0], gargv); @@ -177,14 +167,14 @@ pfree: free((char *)argv[argc]); } #endif - return(iop); + return (iop); } int cron_pclose(iop) FILE *iop; { - register int fdes; + int fdes; int omask; WAIT_T stat_loc; PID_T pid; @@ -194,7 +184,7 @@ cron_pclose(iop) * `popened' command, or, if already `pclosed'. */ if (pids == 0 || pids[fdes = fileno(iop)] == 0) - return(-1); + return (-1); (void)fclose(iop); omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) diff --git a/usr.sbin/cron/structs.h b/usr.sbin/cron/structs.h new file mode 100644 index 00000000000..7dd49ae87d7 --- /dev/null +++ b/usr.sbin/cron/structs.h @@ -0,0 +1,64 @@ +/* $OpenBSD: structs.h,v 1.1 2001/02/18 19:48:36 millert Exp $ */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +typedef int time_min; /* time in minutes */ + +typedef struct _entry { + struct _entry *next; + uid_t uid; + gid_t gid; + char **envp; + char *cmd; + bitstr_t bit_decl(minute, MINUTE_COUNT); + bitstr_t bit_decl(hour, HOUR_COUNT); + bitstr_t bit_decl(dom, DOM_COUNT); + bitstr_t bit_decl(month, MONTH_COUNT); + bitstr_t bit_decl(dow, DOW_COUNT); + int flags; +#define MIN_STAR 0x01 +#define HR_STAR 0x02 +#define DOM_STAR 0x04 +#define DOW_STAR 0x08 +#define WHEN_REBOOT 0x10 +#define DONT_LOG 0x20 +} entry; + + /* the crontab database will be a list of the + * following structure, one element per user + * plus one for the system. + * + * These are the crontabs. + */ + +typedef struct _user { + struct _user *next, *prev; /* links */ + char *name; + time_t mtime; /* last modtime of crontab */ + entry *crontab; /* this person's crontab */ +} user; + +typedef struct _cron_db { + user *head, *tail; /* links */ + time_t mtime; /* last modtime on spooldir */ +} cron_db; + /* in the C tradition, we only create + * variables for the main program, just + * extern them elsewhere. + */ + diff --git a/usr.sbin/cron/user.c b/usr.sbin/cron/user.c index a2ce35bfed2..7ef42d9271d 100644 --- a/usr.sbin/cron/user.c +++ b/usr.sbin/cron/user.c @@ -1,36 +1,37 @@ +/* $OpenBSD: user.c,v 1.3 2001/02/18 19:48:36 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved + */ + +/* + * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. * - * Distribute freely, except: don't remove my name from the source or - * documentation (don't take credit for my work), mark your changes (don't - * get me blamed for your possible bugs), don't alter or remove this - * notice. May be sold if buildable source is provided to buyer. No - * warrantee of any kind, express or implied, is included with this - * software; use at your own risk, responsibility for damages (if any) to - * anyone resulting from the use of this software rests entirely with the - * user. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * Send bug reports, bug fixes, enhancements, requests, flames, etc., and - * I'll try to keep a version up to date. I can be reached as follows: - * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$Id: user.c,v 1.2 1996/11/01 23:27:39 millert Exp $"; +static char rcsid[] = "$OpenBSD: user.c,v 1.3 2001/02/18 19:48:36 millert Exp $"; #endif /* vix 26jan87 [log is in RCS file] */ - #include "cron.h" - void -free_user(u) - user *u; -{ - entry *e, *ne; +free_user(user *u) { + entry *e, *ne; free(u->name); for (e = u->crontab; e != NULL; e = ne) { @@ -40,51 +41,45 @@ free_user(u) free(u); } - user * -load_user(crontab_fd, pw, name) - int crontab_fd; - struct passwd *pw; /* NULL implies syscrontab */ - char *name; -{ - char envstr[MAX_ENVSTR]; - FILE *file; - user *u; - entry *e; - int status; - char **envp, **tenvp; +load_user(int crontab_fd, struct passwd *pw, const char *name) { + char envstr[MAX_ENVSTR]; + FILE *file; + user *u; + entry *e; + int status, save_errno; + char **envp, **tenvp; if (!(file = fdopen(crontab_fd, "r"))) { perror("fdopen on crontab_fd in load_user"); - return NULL; + return (NULL); } Debug(DPARS, ("load_user()\n")) /* file is open. build user entry, then read the crontab file. */ - if ((u = (user *) malloc(sizeof(user))) == NULL) { - errno = ENOMEM; - return NULL; - } + if ((u = (user *) malloc(sizeof(user))) == NULL) + return (NULL); if ((u->name = strdup(name)) == NULL) { + save_errno = errno; free(u); - errno = ENOMEM; - return NULL; + errno = save_errno; + return (NULL); } u->crontab = NULL; - /* - * init environment. this will be copied/augmented for each entry. + /* init environment. this will be copied/augmented for each entry. */ if ((envp = env_init()) == NULL) { + save_errno = errno; free(u->name); free(u); - return NULL; + errno = save_errno; + return (NULL); } - /* - * load the crontab + /* load the crontab */ while ((status = load_env(envstr, file)) >= OK) { switch (status) { @@ -103,8 +98,10 @@ load_user(crontab_fd, pw, name) if ((tenvp = env_set(envp, envstr))) { envp = tenvp; } else { + save_errno = errno; free_user(u); u = NULL; + errno = save_errno; goto done; } break; @@ -115,5 +112,5 @@ load_user(crontab_fd, pw, name) env_free(envp); fclose(file); Debug(DPARS, ("...load_user() done\n")) - return u; + return (u); } |