Subject: bin/36539: a mass of fixes for cron(8)
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Greg A. Woods <woods@planix.com>
List: netbsd-bugs
Date: 06/23/2007 20:35:00
>Number: 36539
>Category: bin
>Synopsis: a mass of fixes for cron(8)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jun 23 20:35:00 +0000 2007
>Originator: Greg A. Woods
>Release: netbsd-4 2007/06/22
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:
System: NetBSD
>Description:
the changes here should be mostly self-explanitory
>How-To-Repeat:
be appalled at the state of the cron code and docs and it's poor
logging ability, etc.
>Fix:
cvs diff: Diffing usr.sbin/cron
Index: usr.sbin/cron/Makefile
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/Makefile,v
retrieving revision 1.12
diff -u -r1.12 Makefile
--- usr.sbin/cron/Makefile 11 May 2006 23:16:30 -0000 1.12
+++ usr.sbin/cron/Makefile 28 May 2007 20:22:48 -0000
@@ -4,8 +4,9 @@
SRCS= cron.c database.c do_command.c entry.c env.c job.c \
misc.c popen.c user.c
CPPFLAGS+=-I${.CURDIR} -DLOGIN_CAP
+CPPFLAGS+=-DDEBUGGING
LDADD+=-lutil
-MAN= cron.8
+MAN= cron.8 crontab.5 crontab.1
WARNS= 3
Index: usr.sbin/cron/README.woods
===================================================================
RCS file: usr.sbin/cron/README.woods
diff -N usr.sbin/cron/README.woods
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ usr.sbin/cron/README.woods 28 May 2007 20:22:18 -0000
@@ -0,0 +1,7 @@
+Keep cron up-to-date
+
+ cd /usr/src-current/usr.sbin/cron
+ cvs -q update
+
+ find . -type f ! -name '.#*' -print -o -name CVS -prune | pax -rw /usr/src/usr.sbin/cron
+ find . -type f ! -name '.#*' -print -o -name CVS -prune | pax -rw /usr/src-4/usr.sbin/cron
Index: usr.sbin/cron/config.h
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/config.h,v
retrieving revision 1.6
diff -u -r1.6 config.h
--- usr.sbin/cron/config.h 9 Apr 1999 02:47:03 -0000 1.6
+++ usr.sbin/cron/config.h 28 May 2007 20:22:49 -0000
@@ -44,11 +44,10 @@
*/
#define MAILCMD _PATH_SENDMAIL /*-*/
-#define MAILARGS "%s -FCronDaemon -odi -oem -oi -or0s -t" /*-*/
+#define MAILARGS "%s -FCronDaemon -odi -oem -oi -t" /*-*/
/* -Fx = set full-name of sender
* -odi = Option Deliverymode Interactive
* -oem = Option Errors Mailedtosender
- * -or0s = Option Readtimeout -- don't time out
* -t = read recipient from header of message
*/
Index: usr.sbin/cron/cron.8
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/cron.8,v
retrieving revision 1.7
diff -u -r1.7 cron.8
--- usr.sbin/cron/cron.8 20 Mar 2004 18:54:33 -0000 1.7
+++ usr.sbin/cron/cron.8 28 May 2007 20:22:49 -0000
@@ -27,12 +27,15 @@
.Nd daemon to execute scheduled commands (Vixie Cron)
.Sh SYNOPSIS
.Nm
+.Op Fl f Ar system-crontab
.Op Fl x Ar debugflags
.Sh DESCRIPTION
.Nm
-is normally started during system boot by
+is normally started during system boot by the
.Xr rc.d 8
-framework, if cron is switched on in
+framework, if
+.Dv cron
+is switched on in
.Xr rc.conf 5 .
.Pp
.Nm
@@ -40,11 +43,12 @@
.Pa /var/cron/tabs
for crontab files which are named after accounts in
.Pa /etc/passwd .
-Crontabs found are loaded into memory.
+All crontab files which are found are loaded into memory.
.Nm
-also searches for
-.Pa /etc/crontab
-which is in a different format (see
+also searches for the system crontab, normally named
+.Pa /etc/crontab ,
+which has in a slightly different format with a username field before
+the command (see
.Xr crontab 5 ) .
.Nm
then wakes up every minute, examining all stored crontabs, checking each
@@ -56,20 +60,24 @@
.Pp
Additionally,
.Nm
-checks each minute to see if its spool directory's modtime (or the modtime
-on
+checks each minute to see if its spool directory's last-modified time
+(and the last modified time on the system crontab file,
.Pa /etc/crontab )
-has changed, and if it has,
+has changed, and if so,
.Nm
-will then examine the modtime on all crontabs and reload those which have
-changed.
+will then examine the last-modified time on all crontabs and reload all
+those which have changed.
Thus
.Nm
need not be restarted whenever a crontab file is modified.
Note that the
.Xr crontab 1
-command updates the modtime of the spool directory whenever it changes a
-crontab.
+command updates the last-modified time of the spool directory whenever
+it changes a crontab file.
+.Pp
+The parameter to the
+.Fl f
+flag changes the default system crontab filename.
.Pp
The
.Fl x
@@ -80,7 +88,9 @@
.Nm
writes some additional debugging information to system log during
its work.
+.Pp
Available debugging flags are:
+.Pp
.Bl -tag -width proc -compact
.It Ar sch
scheduling
@@ -103,9 +113,9 @@
.Bl -tag -width /var/cron/tabs -compact
.It Pa /var/cron/tabs
.Nm
-spool directory
+spool directory for per-user crontab files
.It Pa /etc/crontab
-system crontab
+default system crontab filename
.El
.Sh SEE ALSO
.Xr crontab 1 ,
Index: usr.sbin/cron/cron.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/cron.c,v
retrieving revision 1.13
diff -u -r1.13 cron.c
--- usr.sbin/cron/cron.c 18 Dec 2006 20:11:10 -0000 1.13
+++ usr.sbin/cron/cron.c 28 May 2007 20:22:49 -0000
@@ -27,7 +27,7 @@
#endif
-#define MAIN_PROGRAM
+#define MAIN_PROGRAM "[CRON]"
#include "cron.h"
@@ -37,6 +37,9 @@
#else
# include <time.h>
#endif
+#if defined(SYSLOG)
+# include <syslog.h>
+#endif
static void usage(void),
@@ -48,11 +51,25 @@
sigchld_handler(int),
#endif
sighup_handler(int),
+ shutdown_handler __P((int)),
parse_args(int c, char *v[]);
+static int set_syscron_name __P((const char *));
static void
usage(void) {
+#if DEBUGGING
+ int df;
+ fprintf(stderr, "usage: %s [-x debugflag[,...]] [-f system_crontab]\n- debugflags are: ", getprogname());
+ for (df = 0; DebugFlagNames[df]; df++) {
+ if (df)
+ fputs(", ", stderr);
+ fprintf(stderr, "%s", DebugFlagNames[df]);
+ }
+ fputs("\n", stderr);
+#else
+ fprintf(stderr, "usage: %s [-f system_crontab]\n", getprogname());
+#endif
fprintf(stderr, "usage: %s [-x debugflag[,...]]\n", getprogname());
exit(ERROR_EXIT);
}
@@ -78,6 +95,8 @@
(void) signal(SIGCLD, SIG_IGN);
#endif
(void) signal(SIGHUP, sighup_handler);
+ (void) signal(SIGINT, shutdown_handler);
+ (void) signal(SIGTERM, shutdown_handler);
acquire_daemonlock(0);
set_cron_uid();
@@ -97,12 +116,14 @@
(void) fprintf(stderr, "[%d] cron started\n", getpid());
} else {
if (daemon(1, 0)) {
- log_it("CRON",getpid(),"DEATH","can't fork");
+ log_it(LOG_ERR, "CRON", getpid(), "DEATH", "can't daemonize");
exit(1);
}
}
-
+ /* re-acquire the pidfile after daemon() */
acquire_daemonlock(0);
+ log_it(LOG_DEBUG, "CRON", getpid(), "START", "initial startup");
+
database.head = NULL;
database.tail = NULL;
database.mtime = (time_t) 0;
@@ -233,6 +254,19 @@
cron_sleep(void) {
int seconds_to_wait;
+ /* From FreeBSD PR#5572 by Matt Dillon <dillon@best.net>:
+ * Look for time step and don't run all the friggin cron jobs in
+ * between if a major backwards step occurs. Otherwise, a major
+ * time step (e.g. if the time gets messed up on the machine) may
+ * cause thousands of cron jobs to be run, especially if you have a lot
+ * of users.
+ */
+
+ seconds_to_wait = (int) (TargetTime - time((time_t*)0));
+
+ if (seconds_to_wait < -600 || seconds_to_wait > 600) {
+ cron_sync();
+ }
do {
seconds_to_wait = (int) (TargetTime - time((time_t*)0));
Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
@@ -292,23 +326,58 @@
static void
sighup_handler(int x __unused)
{
+ log_it(LOG_INFO, "CRON", getpid(), "LOGROTATE", "received SIGHUP, close and re-open log");
log_close();
}
static void
+shutdown_handler(int x)
+{
+ log_it(LOG_INFO, "CRON", getpid(), "SHUTDOWN", "received shutdown signal");
+ log_close();
+
+ exit(0);
+}
+
+
+static int
+set_syscron_name(const char *newname)
+{
+ static int was_set = 0;
+
+ if (was_set)
+ return 0;
+ was_set = 1;
+ syscron_name = newname;
+ return was_set;
+}
+
+static void
parse_args(int argc, char **argv)
{
int argch;
- while (-1 != (argch = getopt(argc, argv, "x:"))) {
+#if DEBUGGING
+# define GETOPT_OPTIONS "f:x:"
+#else
+# define GETOPT_OPTIONS "f:"
+#endif
+
+ while (-1 != (argch = getopt(argc, argv, GETOPT_OPTIONS))) {
switch (argch) {
default:
usage();
+ case 'f':
+ if (!set_syscron_name((const char *) optarg))
+ usage();
+ break;
+#if DEBUGGING
case 'x':
if (!set_debug_flags(optarg))
usage();
break;
}
+#endif
}
}
Index: usr.sbin/cron/cron.h
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/cron.h,v
retrieving revision 1.4
diff -u -r1.4 cron.h
--- usr.sbin/cron/cron.h 16 Mar 2005 02:53:55 -0000 1.4
+++ usr.sbin/cron/cron.h 28 May 2007 20:22:49 -0000
@@ -119,6 +119,9 @@
#define Set_LineNum(ln) {Debug(DPARS|DEXT,("linenum=%d\n",ln)); \
LineNumber = ln; \
}
+#define Set_FileName(fn) {Debug(DPARS|DEXT,("filename=%s\n",fn?fn:"<NONE>")); \
+ FileName = fn; \
+ }
#define FIRST_MINUTE 0
#define LAST_MINUTE 59
@@ -199,7 +202,7 @@
free_entry(entry *),
acquire_daemonlock(int),
skip_comments(FILE *),
- log_it(const char *, int, const char *, const char *),
+ log_it(int, const char *, int, const char *, const char *),
log_close(void);
int job_runqueue(void),
@@ -254,7 +257,10 @@
NULL
};
-char *ProgramName;
+const char *syscron_name = SYSCRONTAB;
+
+char *FileName = NULL;
+
int LineNumber;
time_t TargetTime;
@@ -269,7 +275,9 @@
extern char *copyright[],
*MonthNames[],
*DowNames[],
- *ProgramName;
+ *ProgramName,
+ *syscron_name;
+extern char *FileName;
extern int LineNumber;
extern time_t TargetTime;
# if DEBUGGING
Index: usr.sbin/cron/crontab.1
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/crontab.1,v
retrieving revision 1.7
diff -u -r1.7 crontab.1
--- usr.sbin/cron/crontab.1 8 Feb 2002 01:38:47 -0000 1.7
+++ usr.sbin/cron/crontab.1 28 May 2007 20:22:49 -0000
@@ -1,3 +1,4 @@
+.\" -*-nroff-*-
.\" $NetBSD: crontab.1,v 1.7 2002/02/08 01:38:47 ross Exp $
.\"
.\"/* Copyright 1988,1990,1993 by Paul Vixie
@@ -60,7 +61,7 @@
option is given, it specifies the name of the user whose crontab is to be
tweaked. If this option is not given,
.I crontab
-examines "your" crontab, i.e., the crontab of the person executing the
+examines ``your'' crontab, i.e., the crontab of the person executing the
command. Note that
.IR su (1)
can confuse
Index: usr.sbin/cron/crontab.5
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/crontab.5,v
retrieving revision 1.11
diff -u -r1.11 crontab.5
--- usr.sbin/cron/crontab.5 2 Sep 2004 11:41:27 -0000 1.11
+++ usr.sbin/cron/crontab.5 28 May 2007 20:22:49 -0000
@@ -1,3 +1,4 @@
+.\" -*-nroff-*-
.\" $NetBSD: crontab.5,v 1.11 2004/09/02 11:41:27 jmmv Exp $
.\"
.\"/* Copyright 1988,1990,1993,1994 by Paul Vixie
@@ -19,7 +20,7 @@
.\"
.\" Id: crontab.5,v 2.4 1994/01/15 20:43:43 vixie Exp
.\"
-.TH CRONTAB 5 "24 January 1994"
+.TH CRONTAB 5 "16 May 2003"
.UC 4
.SH NAME
crontab \- tables for driving cron
@@ -28,12 +29,12 @@
.I crontab
file contains instructions to the
.IR cron (8)
-daemon of the general form: ``run this command at this time on this date''.
+daemon of the general form: ``run this command at this time on this date''.
Each user has their own crontab, and commands in any given crontab will be
executed as the user who owns the crontab. Uucp and News will usually have
their own crontabs, eliminating the need for explicitly running
.IR su (1)
-as part of a cron command.
+as part of a cron command on non-BSD systems.
.PP
Blank lines and leading spaces and tabs are ignored. Lines whose first
non-space character is a pound-sign (#) are comments, and are ignored.
@@ -67,8 +68,8 @@
line of the crontab's owner.
HOME and SHELL may be overridden by settings in the crontab; LOGNAME may not.
.PP
-(Another note: the LOGNAME variable is sometimes called USER on BSD systems...
-on these systems, USER will be set also.)
+(Another note: the LOGNAME variable is sometimes called USER on BSD
+systems and on these systems, USER will be set also.)
.PP
In addition to LOGNAME, HOME, and SHELL,
.IR cron (8)
@@ -90,16 +91,16 @@
.PP
The CRON_WITHIN variable should indicate the number of seconds
within a job's scheduled time that it should still be run. On a
-heavily loaded system, or on a system that has just been "woken
-up", jobs will sometimes start later than originally intended, and
+heavily loaded system, or on a system that has just been ``woken
+up'', jobs will sometimes start later than originally intended, and
by skipping non-critical jobs because of delays, system load can
be lightened. If CRON_WITHIN is defined but empty (CRON_WITHIN="") or
set to some non-positive value (0, a negative number, or a non-numeric
string), it is treated as if it was unset.
.PP
-The format of a cron command is very much the V7 standard, with a number of
-upward-compatible extensions. Each line has five time and date fields,
-followed by a user name if this is the system crontab file,
+The format of a crontab entry is very much the V7 standard, with a
+number of upward-compatible extensions. Each line has five time and
+date fields, followed by a user name if this is the system crontab file,
followed by a command. Commands are executed by
.IR cron (8)
when the minute, hour, and month of year fields match the current time,
@@ -136,7 +137,7 @@
and 11.
.PP
Lists are allowed. A list is a set of numbers (or ranges)
-separated by commas. Examples: ``1,2,5,9'', ``0-4,8-12''.
+separated by commas. Examples: ``1,2,5,9'', ``0-4,8-12''.
.PP
Step values can be used in conjunction with ranges. Following
a range with ``/\*[Lt]number\*[Gt]'' specifies skips of the number's value
@@ -151,17 +152,21 @@
day or month (case doesn't matter). Ranges or
lists of names are not allowed.
.PP
-The ``sixth'' field (the rest of the line) specifies the command to be
-run.
-The entire command portion of the line, up to a newline or %
-character, will be executed by /bin/sh or by the shell
-specified in the SHELL variable of the cronfile.
-Percent-signs (%) in the command, unless escaped with backslash
-(\\), will be changed into newline characters, and all data
-after the first % will be sent to the command as standard
-input.
+On BSD systems the system crontab file (/etc/crontab) has a ``username''
+field after the time and date fields. The user name given in this field
+tells
+.I cron
+what user to execute the command as.
+.PP
+The ``last'' field (the rest of the line) specifies the command to be
+run. The entire command portion of the line, up to a newline or %
+character, will be executed by /bin/sh or by the shell specified in the
+SHELL variable of the cronfile. Percent-signs (%) in the command,
+unless escaped with backslash (\\), will be changed into newline
+characters, and all data after the first % will be sent to the command
+as standard input.
.PP
-Note: The day of a command's execution can be specified by two
+Note: The day of a command's execution can be specified by two
fields \(em day of month, and day of week. If both fields are
restricted (ie, aren't *), the command will be run when
.I either
@@ -179,7 +184,7 @@
.br
------ -------
.br
-@reboot Run once, at startup.
+@reboot Run once, at startup. (Caution, not just at system reboot)
.br
@yearly Run once a year, "0 0 1 1 *".
.br
@@ -195,24 +200,33 @@
.br
@hourly Run once an hour, "0 * * * *".
.br
-.SH EXAMPLE CRON FILE
+.ta 0
+.SH "EXAMPLE CRON FILE"
+.ta 2.25i
.nf
-
+#
# use /bin/sh to run commands, no matter what /etc/passwd says
SHELL=/bin/sh
# mail any output to `paul', no matter whose crontab this is
MAILTO=paul
#
+#mm hh mday mon wday command
+#
# run five minutes after midnight, every day
-5 0 * * * $HOME/bin/daily.job \*[Gt]\*[Gt] $HOME/tmp/out 2\*[Gt]\*[Am]1
+5 0 * * * $HOME/bin/daily.job \*[Gt]\*[Gt] $HOME/tmp/out 2\*[Gt]\*[Am]1
+#
# run at 2:15pm on the first of every month -- output mailed to paul
-15 14 1 * * $HOME/bin/monthly
-# run at 10 pm on weekdays, annoy Joe
-0 22 * * 1-5 mail -s "It's 10pm" joe%Joe,%%Where are your kids?%
+15 14 1 * * $HOME/bin/monthly
+#
+# run at 10 pm on weekdays, annoy Joe (note message body fed to command)
+0 22 * * 1-5 mail -s "It's 10pm" joe%Joe,%%Where are your kids?%
+#
23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
-5 4 * * sun echo "run at 5 after 4 every sunday"
+#
+5 4 * * sun echo "run at 5 after 4 every sunday"
+.ta 0
.fi
-.SH SEE ALSO
+.SH "SEE ALSO"
cron(8), crontab(1)
.SH EXTENSIONS
When specifying day of week, both day 0 and day 7 will be considered Sunday.
@@ -228,6 +242,9 @@
Environment variables can be set in the crontab. In BSD or ATT, the
environment handed to child processes is basically the one from /etc/rc.
.PP
+Command input is allowed with '%' as newline in the crontab entry (SysV
+can't do this).
+.PP
Command output is mailed to the crontab owner (BSD can't do this), can be
mailed to a person other than the crontab owner (SysV can't do this), or the
feature can be turned off and no mail will be sent at all (SysV can't do this
Index: usr.sbin/cron/crontab.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/crontab.c,v
retrieving revision 1.30
diff -u -r1.30 crontab.c
--- usr.sbin/cron/crontab.c 24 May 2006 21:43:43 -0000 1.30
+++ usr.sbin/cron/crontab.c 28 May 2007 20:22:49 -0000
@@ -35,7 +35,7 @@
#define MAXCRONTABSIZE (1024*256) /* max crontab size == 256 KB */
-#define MAIN_PROGRAM
+#define MAIN_PROGRAM "CRONTAB"
#include "cron.h"
@@ -54,6 +54,9 @@
#endif
#include <time.h>
#include <signal.h>
+#if defined(SYSLOG)
+# include <syslog.h>
+#endif
#define NHEADER_LINES 3
@@ -121,7 +124,7 @@
"You (%s) are not allowed to use this program (%s)\n",
User, getprogname());
fprintf(stderr, "See crontab(1) for more information\n");
- log_it(RealUser, Pid, "AUTH", "crontab command not allowed");
+ log_it(LOG_NOTICE, RealUser, Pid, "AUTH", "crontab command not allowed");
exit(ERROR_EXIT);
}
exitstatus = OK_EXIT;
@@ -280,7 +283,7 @@
FILE *f;
int ch;
- log_it(RealUser, Pid, "LIST", User);
+ log_it(LOG_INFO, RealUser, Pid, "LIST", User);
(void) snprintf(n, sizeof(n), CRON_TAB(User));
if (!(f = fopen(n, "r"))) {
if (errno == ENOENT)
@@ -304,7 +307,7 @@
delete_cmd(void) {
char n[MAX_FNAME];
- log_it(RealUser, Pid, "DELETE", User);
+ log_it(LOG_INFO, RealUser, Pid, "DELETE", User);
(void) snprintf(n, sizeof(n), CRON_TAB(User));
if (unlink(n)) {
if (errno == ENOENT)
@@ -338,7 +341,7 @@
sig_t oint, oabrt;
char *edit;
- log_it(RealUser, Pid, "BEGIN EDIT", User);
+ log_it(LOG_DEBUG, RealUser, Pid, "BEGIN EDIT", User);
(void) snprintf(n, sizeof(n), CRON_TAB(User));
if (!(f = fopen(n, "r"))) {
if (errno != ENOENT) {
@@ -439,6 +442,7 @@
/*NOTREACHED*/
default:
/* parent */
+ /* XXX ignore signals until child returns XXX */
break;
}
/* parent */
@@ -500,7 +504,7 @@
remove:
unlink(Filename);
done:
- log_it(RealUser, Pid, "END EDIT", User);
+ log_it(LOG_INFO, RealUser, Pid, "END EDIT", User);
}
@@ -661,7 +665,7 @@
warn("error renaming %s to %s", tn, n);
goto out;
}
- log_it(RealUser, Pid, "REPLACE", User);
+ log_it(LOG_INFO, RealUser, Pid, "REPLACE", User);
poke_daemon();
free(envp);
Index: usr.sbin/cron/database.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/database.c,v
retrieving revision 1.7
diff -u -r1.7 database.c
--- usr.sbin/cron/database.c 16 Mar 2005 02:53:55 -0000 1.7
+++ usr.sbin/cron/database.c 28 May 2007 20:22:49 -0000
@@ -34,13 +34,16 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/file.h>
+#if defined(SYSLOG)
+# include <syslog.h>
+#endif
#define TMAX(a,b) ((a)>(b)?(a):(b))
static void process_crontab(const char *, const char *,
- const char *, struct stat *,
+ char *, struct stat *,
cron_db *, cron_db *);
@@ -61,13 +64,13 @@
* cached any of the database), we'll see the changes next time.
*/
if (stat(SPOOL_DIR, &statbuf) < OK) {
- log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
+ log_it(LOG_ERR, "CRON", getpid(), "STAT FAILED", SPOOL_DIR);
(void) exit(ERROR_EXIT);
}
/* track system crontab file
*/
- if (stat(SYSCRONTAB, &syscron_stat) < OK)
+ if (stat(syscron_name, &syscron_stat) < OK)
syscron_stat.st_mtime = 0;
/* if spooldir's mtime has not changed, we don't need to fiddle with
@@ -92,8 +95,7 @@
new_db.head = new_db.tail = NULL;
if (syscron_stat.st_mtime) {
- process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
- &new_db, old_db);
+ process_crontab("root", (char *) NULL, syscron_name, &syscron_stat, &new_db, old_db);
}
/* we used to keep this dir open all the time, for the sake of
@@ -101,7 +103,7 @@
* we fork a lot more often than the mtime of the dir changes.
*/
if (!(dir = opendir(SPOOL_DIR))) {
- log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
+ log_it(LOG_ERR, "CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
(void) exit(ERROR_EXIT);
}
@@ -189,7 +191,7 @@
static void
-process_crontab(const char *uname, const char *fname, const char *tabname,
+process_crontab(const char *uname, const char *fname, char *tabname,
struct stat *statbuf, cron_db *new_db, cron_db *old_db)
{
struct passwd *pw = NULL;
@@ -203,19 +205,20 @@
} else if ((pw = getpwnam(uname)) == NULL) {
/* file doesn't have a user in passwd file.
*/
- log_it(fname, getpid(), "ORPHAN", "no passwd entry");
+ log_it(LOG_WARNING, fname, getpid(), "ORPHAN", "no passwd entry");
goto next_crontab;
}
+ Set_FileName(tabname)
if ((crontab_fd = open(tabname, O_RDONLY, 0)) < OK) {
/* crontab not accessible?
*/
- log_it(fname, getpid(), "CAN'T OPEN", tabname);
+ log_it(LOG_WARNING, fname, getpid(), "CAN'T OPEN", tabname);
goto next_crontab;
}
if (fstat(crontab_fd, statbuf) < OK) {
- log_it(fname, getpid(), "FSTAT FAILED", tabname);
+ log_it(LOG_WARNING, fname, getpid(), "FSTAT FAILED", tabname);
goto next_crontab;
}
@@ -242,7 +245,7 @@
Debug(DLOAD, (" [delete old data]"))
unlink_user(old_db, u);
free_user(u);
- log_it(fname, getpid(), "RELOAD", tabname);
+ log_it(LOG_INFO, fname, getpid(), "RELOAD", tabname);
}
u = load_user(crontab_fd, pw, fname);
if (u != NULL) {
@@ -254,5 +257,6 @@
if (crontab_fd >= OK) {
Debug(DLOAD, (" [done]\n"))
close(crontab_fd);
+ Set_FileName((char *) NULL)
}
}
Index: usr.sbin/cron/do_command.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/do_command.c,v
retrieving revision 1.25
diff -u -r1.25 do_command.c
--- usr.sbin/cron/do_command.c 18 Dec 2006 20:11:10 -0000 1.25
+++ usr.sbin/cron/do_command.c 28 May 2007 20:22:49 -0000
@@ -61,7 +61,7 @@
*/
switch (fork()) {
case -1:
- log_it("CRON",getpid(),"error","can't fork");
+ log_it(LOG_ERR, "CRON", getpid(), "error", "can't fork");
break;
case 0:
/* child process */
@@ -164,7 +164,7 @@
*/
switch (vfork()) {
case -1:
- log_it("CRON",getpid(),"error","can't vfork");
+ log_it(LOG_ERR, "CRON", getpid(), "error", "can't vfork");
exit(ERROR_EXIT);
/*NOTREACHED*/
case 0:
@@ -179,7 +179,7 @@
/*local*/{
char *x = mkprints((u_char *)e->cmd, strlen(e->cmd));
- log_it(usernm, getpid(), "CMD START", x);
+ log_it(LOG_INFO, usernm, getpid(), "CMD START", x);
free(x);
}
@@ -480,7 +480,7 @@
"mailed %d byte%s of output but got status 0x%04x\n",
bytes, (bytes==1)?"":"s",
status);
- log_it(usernm, getpid(), "MAIL", buf);
+ log_it(LOG_INFO, usernm, getpid(), "MAIL", buf);
}
} /*if data from grandchild*/
@@ -516,7 +516,7 @@
/*local*/{
char *x = mkprints((u_char *)e->cmd, strlen(e->cmd));
- log_it(usernm, getpid(), "CMD FINISH", x);
+ log_it(LOG_INFO, usernm, getpid(), "CMD FINISH", x);
free(x);
}
}
Index: usr.sbin/cron/entry.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/entry.c,v
retrieving revision 1.8
diff -u -r1.8 entry.c
--- usr.sbin/cron/entry.c 16 Mar 2005 02:53:55 -0000 1.8
+++ usr.sbin/cron/entry.c 28 May 2007 20:22:49 -0000
@@ -85,8 +85,10 @@
* syntax:
* user crontab:
* minutes hours doms months dows cmd\n
- * system crontab (/etc/crontab):
+ * BSD system crontab (/etc/crontab):
* minutes hours doms months dows USERNAME cmd\n
+ * UNIX system crontab (/etc/crontab):
+ * minutes hours doms months dows cmd\n
*/
ecode_e ecode = e_none;
@@ -229,6 +231,11 @@
/* ch is the first character of a command, or a username */
unget_char(ch, file);
+#if defined(BSD)
+ /*
+ * BSD /etc/crontab (the system crontab) has an extra field, the
+ * username, before the command.
+ */
if (!pw) {
char *username = cmd; /* temp buffer */
@@ -244,10 +251,12 @@
pw = getpwnam(username);
if (pw == NULL) {
ecode = e_username;
+ Debug(DPARS, ("load_entry()...invalid username\n"))
goto eof;
}
Debug(DPARS, ("load_entry()...uid %d, gid %d\n",e->uid,e->gid))
}
+#endif
e->uid = pw->pw_uid;
e->gid = pw->pw_gid;
Index: usr.sbin/cron/env.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/env.c,v
retrieving revision 1.15
diff -u -r1.15 env.c
--- usr.sbin/cron/env.c 7 Jun 2005 13:43:52 -0000 1.15
+++ usr.sbin/cron/env.c 28 May 2007 20:22:49 -0000
@@ -107,8 +107,12 @@
}
-/* return ERR = end of file
- * FALSE = not an env setting (file was repositioned)
+/*
+ * Load an environment variable from 'f'.
+ *
+ * return ERR = end of file
+ * FALSE = not an env setting
+ * NOTE: file is repositioned to where we started from.
* TRUE = was an env setting
*/
int
@@ -116,8 +120,10 @@
{
long filepos;
int fileline, len;
- char *name, *name_end, *val, *equal;
- char *s;
+ char *name = NULL;
+ char *name_end = NULL;
+ char *val, *equal;
+ char *s = NULL;
s = name = name_end = NULL; /* XXXGCC -Wuninitialized [sparc64] */
Index: usr.sbin/cron/job.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/job.c,v
retrieving revision 1.6
diff -u -r1.6 job.c
--- usr.sbin/cron/job.c 16 Mar 2005 02:53:55 -0000 1.6
+++ usr.sbin/cron/job.c 28 May 2007 20:22:49 -0000
@@ -32,9 +32,10 @@
#endif
#endif
-
#include "cron.h"
-
+#if defined(SYSLOG)
+# include <syslog.h>
+#endif
typedef struct _job {
struct _job *next;
@@ -90,7 +91,7 @@
strlen(j->e->cmd));
char *usernm = env_get("LOGNAME", j->e->envp);
- log_it(usernm, getpid(), "CMD (skipped)", x);
+ log_it(LOG_INFO, usernm, getpid(), "CMD (skipped)", x);
free(x);
}
jn = j->next;
Index: usr.sbin/cron/misc.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/misc.c,v
retrieving revision 1.13
diff -u -r1.13 misc.c
--- usr.sbin/cron/misc.c 21 May 2006 19:26:43 -0000 1.13
+++ usr.sbin/cron/misc.c 28 May 2007 20:22:49 -0000
@@ -272,7 +272,7 @@
"can't open or create %s: %s",
pidfile, strerror(errno));
warnx(buf);
- log_it("CRON", getpid(), "DEATH", buf);
+ log_it(LOG_ERR, "CRON", getpid(), "DEATH", buf);
exit(ERROR_EXIT);
}
@@ -284,7 +284,7 @@
"can't lock %s, otherpid may be %d: %s",
pidfile, otherpid, strerror(save_errno));
warnx(buf);
- log_it("CRON", getpid(), "DEATH", buf);
+ log_it(LOG_ERR, "CRON", getpid(), "DEATH", buf);
exit(ERROR_EXIT);
}
@@ -451,18 +451,18 @@
void
-log_it(const char *username, int xpid, const char *event, const char *detail)
+log_it(int priority, const char *username, int xpid, const char *event, const char *detail)
{
- PID_T pid = xpid;
+ PID_T pid = xpid;
#if defined(LOG_FILE)
- char *msg;
- size_t msglen;
- TIME_T now = time((TIME_T) 0);
+ 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)
@@ -503,10 +503,6 @@
#if defined(SYSLOG)
if (!syslog_open) {
- /* we don't use LOG_PID since the pid passed to us by
- * our client may not be our own. therefore we want to
- * print the pid ourselves.
- */
# ifdef LOG_DAEMON
openlog(getprogname(), LOG_PID, LOG_CRON);
# else
@@ -515,21 +511,25 @@
syslog_open = TRUE; /* assume openlog success */
}
- syslog(LOG_INFO, "(%s) %s (%s)\n", username, event, detail);
+ if (getpid() != pid) /* getpid() is fast enough */
+ syslog(priority, "(%s)[%d] %s (%s)\n", username, pid, event, detail);
+ else
+ syslog(priority, "(%s) %s (%s)\n", username, event, detail);
#endif /*SYSLOG*/
#if DEBUGGING
if (DebugFlags) {
- fprintf(stderr, "log_it: (%s %d) %s (%s)\n",
- username, pid, event, detail);
+ fprintf(stderr, "log_it: (%d, %s, %d) %s (%s)\n",
+ priority, username, pid, event, detail);
}
#endif
}
void
-log_close(void) {
+log_close(void)
+{
if (LogFD != ERR) {
close(LogFD);
LogFD = ERR;
Index: usr.sbin/cron/user.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.sbin/cron/user.c,v
retrieving revision 1.4
diff -u -r1.4 user.c
--- usr.sbin/cron/user.c 16 Mar 2005 02:53:55 -0000 1.4
+++ usr.sbin/cron/user.c 28 May 2007 20:22:49 -0000
@@ -31,6 +31,13 @@
#include "cron.h"
+#include <errno.h>
+#if defined(SYSLOG)
+# include <syslog.h>
+#endif
+
+
+static void load_user_error(const char *);
void
@@ -59,7 +66,7 @@
char **envp;
if (!(file = fdopen(crontab_fd, "r"))) {
- perror("fdopen on crontab_fd in load_user");
+ log_it(LOG_WARNING, "CRON", getpid(), "fdopen on crontab_fd in load_user", strerror(errno));
return NULL;
}
@@ -86,7 +93,7 @@
u = NULL;
goto done;
case FALSE:
- e = load_entry(file, NULL, pw, envp);
+ e = load_entry(file, load_user_error, pw, envp);
if (e) {
e->next = u->crontab;
u->crontab = e;
@@ -104,3 +111,19 @@
Debug(DPARS, ("...load_user() done\n"))
return u;
}
+
+
+static void
+load_user_error(const char *msg)
+{
+ char *pmsg;
+
+ if (-1 == asprintf(&pmsg, "error in crontab %s at line %d", FileName, LineNumber)) {
+ Debug(DLOAD, ("... out of memory formatting error message: %s!\n",
+ strerror(errno)))
+ log_it(LOG_ERR, "CRON", getpid(), "OUT OF MEMORY", msg);
+ } else
+ log_it(LOG_INFO, "CRON", getpid(), pmsg, msg);
+ if (pmsg)
+ free(pmsg);
+}
>Unformatted: