Subject: Cron runs weekly jobs nightly (#423) Index: usr.sbin/cron/entry.c 2.11BSD Description: cron(8) runs weekly jobs (scheduled only for day 6) nightly. Repeat-By: 1. Have the following entry in /etc/crontab file (or omit the "user" field if the entry is placed in a user's crontab). Adjust the minute and hour field to be conveniently in the near future (and use a day other than 6 if running this test on a Saturday ;)): 0 9 * * * root echo "The first command" 2 9 * * 6 root echo "The second command" Note that you will receive two mail items a couple minutes apart because not only did the hourly job run but so did the weekly one! Fix: There were a total of 4 bugs found dating back to 1994 (these are not things I broke during the port to 2.11BSD). Fortunately only one of them was "fatal" and generated unexpected results. 1) The use of the bit_nclear() macro in entry.c had a bogus "+1" in it to deal with 0 origined numbers. BUT, the bit_nclear macro already had "+1" logic in it. The result was that one two many bits were cleared. On systems where the C compiler aligned 'int' structure members on a 4 byte boundary clearing an extra bit in a "pad byte" was harmless (still an error though). But on a 16 bit machine where the alignment requirement is only 2 bytes clearing an extra bit would (and in this case _did_) clear the first bit of the next structure member. In this case the "DOW_STAR" flag bit was being cleared which resulted in cron running the weekly job every day. 2) The definition of 'bit_alloc' was calling malloc(3) with two arguments. Luckily noone uses 'bit_alloc' but the error was fixed anyhow by using 'calloc' instead of 'malloc'. 3) The sigblock() return value in cron_pclose() was being assigned to an 'int'. This is incorrect since "sizeof int != sizeof long". A 'long' would have been better but since 'sigset_t' now exists it was used. 4) In crontab one of the 'swap_uids' calls should have been 'swap_uids_back'. On a system which has 'SAVED_UIDS' calling 'swap_uids' and 'swap_uids_back' are _NOT_ the same thing. Only on systems which use 'setreuid' (those which do not have SAVED_UIDS) are 'swap_uids' and 'swap_uids_back' a "toggle". To install this update cut where indicated saving to a file (/tmp/423) and then: kill the currently running cron process ps | grep cron kill _cron_pid_ patch -p0 < /tmp/423 cd /usr/src/usr.sbin/cron make clean make make install make clean cron As always this and previous updates to 2.11BSD are available via anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the directory /pub/2.11BSD. ----------------------------cut here--------------------- *** /usr/src/usr.sbin/cron/README.2BSD.old Fri Jun 18 19:53:04 1999 --- /usr/src/usr.sbin/cron/README.2BSD Mon Aug 9 21:32:02 1999 *************** *** 1,5 **** --- 1,19 ---- This is the 2.11BSD port of the 'Vixie cron-3.0 patch1'. + Updated 1999/8/9: Fix an off by one condition in entry.c that was + causing the 'dow' (day of week) bitmap to be overrun by one bit. + Properly ifdef'd some rcs/sccs id strings so that they do not get + compiled in (data space is at a premium on a 16 bit machine). Fix + a bug in bitstring.h (fortunately nothing uses the macro bit_alloc + at this time) that was using 'malloc' with two arguments. Do some + minor cosmetic cleanup (trailing and extra blank lines, etc). Fix + the sigmask handling in cron_pclose() - it was using 'int' as the + signal mask type instead of 'long' or more properly 'sigmask_t'. + In addition to fixing the sigmask type the code was revised to use + modern signal and wait calls. In crontab one of the 'swap_uids' + calls should have been 'swap_uids_back' in case "SAVED_UIDS" is + supported by the system. + The files Part01, Part02 and Patch01 were retrieved from ftp://ftp.vix.com/pub/vixie/cron-3.0/ *** /usr/src/usr.sbin/cron/bitstring.h.old Sat Jun 12 10:08:40 1999 --- /usr/src/usr.sbin/cron/bitstring.h Thu Aug 5 20:43:41 1999 *************** *** 17,23 **** * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * ! * @(#)bitstring.h 5.2 (Berkeley) 4/4/90 */ typedef unsigned char bitstr_t; --- 17,23 ---- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * ! * @(#)bitstring.h 5.2.1 (2.11BSD) 1999/8/5 */ typedef unsigned char bitstr_t; *************** *** 38,44 **** /* allocate a bitstring */ #define bit_alloc(nbits) \ ! (bitstr_t *)malloc(1, \ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t)) /* allocate a bitstring on the stack */ --- 38,44 ---- /* allocate a bitstring */ #define bit_alloc(nbits) \ ! (bitstr_t *)calloc(1, \ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t)) /* allocate a bitstring on the stack */ *** /usr/src/usr.sbin/cron/cron.c.old Tue Jun 15 21:11:15 1999 --- /usr/src/usr.sbin/cron/cron.c Thu Aug 5 20:48:36 1999 *************** *** 15,27 **** * Paul Vixie uunet!decwrl!vixie!paul */ ! #if !defined(lint) && !defined(LINT) ! static char rcsid[] = "$Id: cron.c,v 2.11 1994/01/15 20:43:43 vixie Exp $"; #endif - #define MAIN_PROGRAM - #include "cron.h" #include --- 15,25 ---- * Paul Vixie uunet!decwrl!vixie!paul */ ! #if !defined(lint) && defined(DOSCCS) ! static char sccsid[] = "@(#)cron.c 2.11.1 (2.11BSD) 1999/08/05"; #endif #define MAIN_PROGRAM #include "cron.h" #include *** /usr/src/usr.sbin/cron/crontab.c.old Tue Jun 15 21:11:42 1999 --- /usr/src/usr.sbin/cron/crontab.c Mon Aug 9 21:55:29 1999 *************** *** 15,23 **** * Paul Vixie uunet!decwrl!vixie!paul */ ! #if !defined(lint) && !defined(LINT) ! static char rcsid[] = "$Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $"; ! #endif /* crontab - install and manage per-user crontab files * vix 02may87 [RCS has the rest of the log] --- 15,21 ---- * Paul Vixie uunet!decwrl!vixie!paul */ ! static char sccsid[] = "@(#) crontab.c 2.13.1 (2.11BSD) 1999/8/9"; /* crontab - install and manage per-user crontab files * vix 02may87 [RCS has the rest of the log] *************** *** 24,33 **** * vix 26jan87 [original] */ - #define MAIN_PROGRAM - #include "cron.h" #include #include --- 22,29 ---- *************** *** 212,218 **** perror(Filename); exit(ERROR_EXIT); } ! if (swap_uids() < OK) { perror("swapping uids back"); exit(ERROR_EXIT); } --- 208,214 ---- perror(Filename); exit(ERROR_EXIT); } ! if (swap_uids_back() < OK) { perror("swapping uids back"); exit(ERROR_EXIT); } *************** *** 492,498 **** */ fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n"); fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now)); ! fprintf(tmp, "# (Cron version -- %s)\n", rcsid); /* copy the crontab to the tmp */ --- 488,494 ---- */ fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n"); fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now)); ! fprintf(tmp, "# (Cron version -- %s)\n", sccsid); /* copy the crontab to the tmp */ *** /usr/src/usr.sbin/cron/entry.c.old Tue Jun 15 21:11:55 1999 --- /usr/src/usr.sbin/cron/entry.c Thu Aug 5 20:51:31 1999 *************** *** 15,22 **** * Paul Vixie uunet!decwrl!vixie!paul */ ! #if !defined(lint) && !defined(LINT) ! static char rcsid[] = "$Id: entry.c,v 2.12 1994/01/17 03:20:37 vixie Exp $"; #endif /* vix 26jan87 [RCS'd; rest of log is in RCS file] --- 15,22 ---- * Paul Vixie uunet!decwrl!vixie!paul */ ! #if !defined(lint) && defined(DOSCCS) ! static char sccsid[] = "@(#)entry.c 2.12.2 (2.11BSD) 1999/08/05"; #endif /* vix 26jan87 [RCS'd; rest of log is in RCS file] *************** *** 25,34 **** * vix 30dec86 [written] */ - #include "cron.h" - typedef enum ecode { e_none, e_minute, e_hour, e_dom, e_month, e_dow, e_cmd, e_timespec, e_username --- 25,32 ---- *************** *** 322,330 **** /* list = range {"," range} */ ! /* clear the bit string, since the default is 'off'. */ ! bit_nclear(bits, 0, (high-low+1)); /* process all ranges */ --- 320,329 ---- /* list = range {"," range} */ ! /* clear the bit string, since the default is 'off'. DONT add an ! * extra bit here, that's done in the macro! */ ! bit_nclear(bits, 0, (high-low)); /* process all ranges */ *** /usr/src/usr.sbin/cron/popen.c.old Sat Jun 12 10:08:40 1999 --- /usr/src/usr.sbin/cron/popen.c Thu Aug 5 20:49:35 1999 *************** *** 23,37 **** * globbing stuff since we don't need it. also execvp instead of execv. */ ! #ifndef lint ! static char rcsid[] = "$Id: popen.c,v 1.5 1994/01/15 20:43:43 vixie Exp $"; ! static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89"; ! #endif /* not lint */ #include "cron.h" #include - #define WANT_GLOBBING 0 /* --- 23,36 ---- * globbing stuff since we don't need it. also execvp instead of execv. */ ! #if !defined(lint) && defined(DOSCCS) ! static char sccsid[] = "@(#)popen.c 5.7.2 (2.11BSD) 1999/08/05"; ! #endif #include "cron.h" + #include #include #define WANT_GLOBBING 0 /* *************** *** 146,154 **** FILE *iop; { register int fdes; ! int omask; WAIT_T stat_loc; ! PID_T pid; /* * pclose returns -1 if stream is not associated with a --- 145,153 ---- FILE *iop; { register int fdes; ! sigset_t omask, nmask; WAIT_T stat_loc; ! register PID_T pid; /* * pclose returns -1 if stream is not associated with a *************** *** 157,166 **** if (pids == 0 || pids[fdes = fileno(iop)] == 0) return(-1); (void)fclose(iop); ! omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); ! while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) ! ; ! (void)sigsetmask(omask); pids[fdes] = 0; return (pid == -1 ? -1 : WEXITSTATUS(stat_loc)); } --- 156,170 ---- if (pids == 0 || pids[fdes = fileno(iop)] == 0) return(-1); (void)fclose(iop); ! sigemptyset(&nmask); ! sigaddset(&nmask, SIGINT); ! sigaddset(&nmask, SIGQUIT); ! sigaddset(&nmask, SIGHUP); ! sigprocmask(SIG_BLOCK, &nmask, &omask); ! do { ! pid = waitpid(pids[fdes], &stat_loc, NULL); ! } while (pid == -1 && errno == EINTR); ! (void)sigprocmask(SIG_SETMASK, &omask, NULL); pids[fdes] = 0; return (pid == -1 ? -1 : WEXITSTATUS(stat_loc)); } *** /VERSION.old Tue Jul 20 20:14:15 1999 --- /VERSION Thu Aug 5 20:59:43 1999 *************** *** 1,5 **** ! Current Patch Level: 422 ! Date: July 20, 1999 2.11 BSD ============ --- 1,5 ---- ! Current Patch Level: 423 ! Date: August 5, 1999 2.11 BSD ============