initial checkin of new hdw-linux development cvs repository
[hdw-linux/hdw-linux.git] / packages / hackbard / cron / cron_3.0pl1-72.patch
1 --- cron-3.0pl1.orig/Makefile
2 +++ cron-3.0pl1/Makefile
3 @@ -55,30 +55,35 @@
4  INCLUDE                =       -I.
5  #INCLUDE       =
6  #<<need getopt()>>
7 -LIBS           =
8 +LIBS           = $(PAM_LIBS)
9  #<<optimize or debug?>>
10 -#OPTIM         =       -O
11 -OPTIM          =       -g
12 +OPTIM          =       -O2
13 +#OPTIM         =       -g
14  #<<ATT or BSD or POSIX?>>
15  # (ATT untested)
16  #COMPAT                =       -DATT
17  #(BSD is only needed if <sys/params.h> does not define it, as on ULTRIX)
18  #COMPAT                =       -DBSD
19  # (POSIX)
20 -#COMPAT                =       -DPOSIX
21 +COMPAT         =       -DPOSIX
22  #<<lint flags of choice?>>
23  LINTFLAGS      =       -hbxa $(INCLUDE) $(COMPAT) $(DEBUGGING)
24  #<<want to use a nonstandard CC?>>
25  #CC            =       vcc
26  #<<manifest defines>>
27 -DEFS           =
28 +# Allow override from command line
29 +DEBUG_DEFS = -DDEBUGGING=0   
30 +# The -DUSE_SIGCHLD is needed for the Alpha port
31 +DEFS = -DDEBIAN -DUSE_SIGCHLD $(DEBUG_DEFS) $(PAM_DEFS)
32  #(SGI IRIX systems need this)
33  #DEFS          =       -D_BSD_SIGNALS -Dconst=
34  #<<the name of the BSD-like install program>>
35  #INSTALL = installbsd
36  INSTALL = install
37  #<<any special load flags>>
38 -LDFLAGS                =
39 +# LDFLAGS              =       -s
40 +# Let install do the strip
41 +
42  #################################### end configurable stuff
43  
44  SHELL          =       /bin/sh
45 @@ -113,13 +118,14 @@
46                         $(CC) $(LDFLAGS) -o crontab $(CRONTAB_OBJ) $(LIBS)
47  
48  install                :       all
49 -                       $(INSTALL) -c -m  111 -o root -s cron    $(DESTSBIN)/
50 -                       $(INSTALL) -c -m 4111 -o root -s crontab $(DESTBIN)/
51 +                       $(INSTALL) -c -m  755 -o root -s cron    $(DESTSBIN)/
52 +                       $(INSTALL) -c -m 4755 -o root -s crontab $(DESTBIN)/
53                         sh putman.sh crontab.1 $(DESTMAN)
54                         sh putman.sh cron.8    $(DESTMAN)
55                         sh putman.sh crontab.5 $(DESTMAN)
56  
57 -clean          :;      rm -f *.o cron crontab a.out core tags *~ #*
58 +clean          :
59 +                       rm -f *.o cron crontab a.out core tags *~ #*
60  
61  kit            :       $(SHAR_SOURCE)
62                         makekit -m -s99k $(SHAR_SOURCE)
63 --- cron-3.0pl1.orig/README
64 +++ cron-3.0pl1/README
65 @@ -24,6 +24,12 @@
66  [V1.0 was May 6, 1987]
67  Paul Vixie
68  
69 +[Note from Debian cron maintainer: This is the original README from
70 +the the vixie-cron package. The location of many cron files has been
71 +changed in order to comply with Debian policy and common sense -- look
72 +in the cron(8), crontab(1) and crontab(5) man pages for more info, as
73 +well as the README.Debian file in this directory.]
74 +
75  This is a version of 'cron' that is known to run on BSD 4.[23] systems.  It
76  is functionally based on the SysV cron, which means that each user can have
77  their own crontab file (all crontab files are stored in a read-protected
78 --- cron-3.0pl1.orig/compat.c
79 +++ cron-3.0pl1/compat.c
80 @@ -53,7 +53,10 @@
81  {
82         char    *temp;
83  
84 -       temp = malloc(strlen(str) + 1);
85 +       if ((temp = malloc(strlen(str) + 1)) == NULL) {
86 +               errno = ENOMEM;
87 +               return NULL;
88 +       }
89         (void) strcpy(temp, str);
90         return temp;
91  }
92 @@ -73,7 +76,7 @@
93                 return sys_errlist[error];
94         }
95  
96 -       sprintf(buf, "Unknown error: %d", error);
97 +       snprintf(buf, 32, "Unknown error: %d", error);
98         return buf;
99  }
100  #endif
101 @@ -218,16 +221,18 @@
102         int overwrite;
103  {
104         char *tmp;
105 +       int tmp_size;
106  
107         if (overwrite && getenv(name))
108                 return -1;
109  
110 -       if (!(tmp = malloc(strlen(name) + strlen(value) + 2))) {
111 +       tmp_size = strlen(name) + strlen(value) + 2;
112 +       if (!(tmp = malloc(tmp_size))) {
113                 errno = ENOMEM;
114                 return -1;
115         }
116  
117 -       sprintf("%s=%s", name, value);
118 +       snprintf(tmp, tmp_size, "%s=%s", name, value);
119         return putenv(tmp);     /* intentionally orphan 'tmp' storage */
120  }
121  #endif
122 --- cron-3.0pl1.orig/compat.h
123 +++ cron-3.0pl1/compat.h
124 @@ -62,8 +62,8 @@
125  #endif
126  
127  #ifndef POSIX
128 -# if (BSD >= 199103) || defined(__linux) || defined(ultrix) || defined(AIX) ||\
129 -       defined(HPUX) || defined(CONVEX) || defined(IRIX)
130 +# if (BSD >= 199103) || defined(__linux__) || defined(__GNU__) || defined(ultrix) ||\
131 +        defined(AIX) ||\ defined(HPUX) || defined(CONVEX) || defined(IRIX)
132  #  define POSIX
133  # endif
134  #endif
135 @@ -76,17 +76,17 @@
136  
137  /*****************************************************************/
138  
139 -#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux)
140 +#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux__) && !defined(__GNU__)
141  # define NEED_VFORK
142  #endif
143  
144 -#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux) && \
145 -       !defined(IRIX) && !defined(NeXT) && !defined(HPUX)
146 +#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux__) && \
147 +       !defined(IRIX) && !defined(NeXT) && !defined(HPUX) && !defined(__GNU__)
148  # define NEED_STRCASECMP
149  #endif
150  
151 -#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux) &&\
152 -       !defined(IRIX) && !defined(UNICOS) && !defined(HPUX)
153 +#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux__) &&\
154 +       !defined(IRIX) && !defined(UNICOS) && !defined(HPUX) && !defined(__GNU__)
155  # define NEED_STRDUP
156  #endif
157  
158 @@ -102,7 +102,7 @@
159  # define NEED_SETSID
160  #endif
161  
162 -#if (defined(POSIX) && !defined(BSD)) && !defined(__linux)
163 +#if (defined(POSIX) && !defined(BSD)) && !defined(__linux__) && !defined(__GNU__)
164  # define NEED_GETDTABLESIZE
165  #endif
166  
167 @@ -110,11 +110,11 @@
168  # define HAVE_SAVED_UIDS
169  #endif
170  
171 -#if !defined(ATT) && !defined(__linux) && !defined(IRIX) && !defined(UNICOS)
172 +#if !defined(ATT) && !defined(__linux__) && !defined(__GNU__) && !defined(IRIX) && !defined(UNICOS)
173  # define USE_SIGCHLD
174  #endif
175  
176 -#if !defined(AIX) && !defined(UNICOS)
177 +#if !defined(AIX) && !defined(UNICOS) && !defined(DEBIAN)
178  # define SYS_TIME_H 1
179  #else
180  # define SYS_TIME_H 0
181 --- cron-3.0pl1.orig/config.h
182 +++ cron-3.0pl1/config.h
183 @@ -29,6 +29,7 @@
184   */
185  
186  #ifndef DEBUGGING
187 +#error DEBUGGING not defined
188  #define DEBUGGING 1    /* 1 or 0 -- do you want debugging code built in? */
189  #endif
190  
191 @@ -42,22 +43,26 @@
192                          */
193  
194  #define MAILCMD _PATH_SENDMAIL                                 /*-*/
195 -#define MAILARGS "%s -FCronDaemon -odi -oem -or0s %s"          /*-*/
196 -                       /* -Fx   = set full-name of sender
197 +#define MAILARGS "%s -i -FCronDaemon -odi -oem  %s"            /*-*/
198 +                       /* -i    = don't terminate on "." by itself
199 +                         * -Fx  = set full-name of sender
200                          * -odi  = Option Deliverymode Interactive
201                          * -oem  = Option Errors Mailedtosender
202 +                        * -t    = read recipient from header of message
203                          * -or0s = Option Readtimeout -- don't time out
204 +                        * XXX: sendmail doesn't allow -or0s when invoked
205 +                        * by joe user.  --okir
206                          */
207  
208 -/* #define MAILCMD "/bin/mail"                 /*-*/
209 -/* #define MAILARGS "%s -d  %s"                        /*-*/
210 +/* #define MAILCMD "/bin/mail"                 -*/
211 +/* #define MAILARGS "%s -d  %s"                        -*/
212                         /* -d = undocumented but common flag: deliver locally?
213                          */
214  
215 -/* #define MAILCMD "/usr/mmdf/bin/submit"      /*-*/
216 -/* #define MAILARGS "%s -mlrxto %s"            /*-*/
217 +/* #define MAILCMD "/usr/mmdf/bin/submit"      -*/
218 +/* #define MAILARGS "%s -mlrxto %s"            -*/
219  
220 -/* #define MAIL_DATE                           /*-*/
221 +/* #define MAIL_DATE                           -*/
222                         /* should we include an ersatz Date: header in
223                          * generated mail?  if you are using sendmail
224                          * for MAILCMD, it is better to let sendmail
225 @@ -68,7 +73,7 @@
226                          * defined but neither exists, should crontab(1) be
227                          * usable only by root?
228                          */
229 -/*#define ALLOW_ONLY_ROOT                      /*-*/
230 +/*#define ALLOW_ONLY_ROOT                      -*/
231  
232                         /* if you want to use syslog(3) instead of appending
233                          * to CRONDIR/LOG_FILE (/var/cron/log, e.g.), define
234 --- cron-3.0pl1.orig/cron.8
235 +++ cron-3.0pl1/cron.8
236 @@ -24,21 +24,35 @@
237  .SH SYNOPSIS
238  cron
239  .SH DESCRIPTION
240 -.I Cron
241 -should be started from /etc/rc or /etc/rc.local.  It will return immediately,
242 -so you don't need to start it with '&'.
243 +.I cron
244 +is started automatically from /etc/init.d on entering multi-user
245 +runlevels.
246  .PP
247 -.I Cron
248 -searches /var/cron/tabs for crontab files which are named after accounts in
249 -/etc/passwd; crontabs found are loaded into memory.
250 -.I Cron
251 -also searches for /etc/crontab which is in a different format (see
252 -.IR crontab(5)).
253 -.I Cron
254 -then wakes up every minute, examining all stored crontabs, checking each
255 -command to see if it should be run in the current minute.  When executing
256 -commands, any output is mailed to the owner of the crontab (or to the user
257 -named in the MAILTO environment variable in the crontab, if such exists).
258 +.I cron
259 +searches its spool area (/var/spool/cron/crontabs) for crontab
260 +files (which are named after accounts in
261 +/etc/passwd); crontabs found are loaded into memory.  Note that
262 +crontabs in this directory should not be accessed directly -
263 +the
264 +.I crontab
265 +command should be used to access and update them.
266 +
267 +.I cron
268 +also reads /etc/crontab, which is in a slightly different format (see
269 +.IR crontab(5)). 
270 +Additionally, cron reads the files in /etc/cron.d; see
271 +the
272 +.B DEBIAN SPECIFIC
273 +section below for more details.
274 +
275 +.I cron
276 +then wakes up every minute, examining all stored crontabs, checking
277 +each command to see if it should be run in the current minute.  When
278 +executing commands, any output is mailed to the owner of the crontab
279 +(or to the user named in the MAILTO environment variable in the
280 +crontab, if such exists).  The children copies of cron running these
281 +processes has its name coerced to uppercase, as will be seen in the
282 +syslog and ps output.
283  .PP
284  Additionally,
285  .I cron
286 @@ -51,9 +65,37 @@
287  changed.  Thus
288  .I cron
289  need not be restarted whenever a crontab file is modified.  Note that the
290 -.IR Crontab (1)
291 +.IR crontab (1)
292  command updates the modtime of the spool directory whenever it changes a
293  crontab.
294 +.PP
295 +Special considerations exist when the clock is changed by less than 3
296 +hours, for example at the beginning and end of daylight savings
297 +time. If the time has moved forwards, those jobs which would have
298 +run in the time that was skipped will be run soon after the change. 
299 +Conversely, if the time has moved backwards by less than 3 hours,
300 +those jobs that fall into the repeated time will not be re-run.
301 +.PP
302 +Only jobs that run at a particular time (not specified as
303 +@hourly, nor with '*' in the hour or minute specifier) are
304 +affected. Jobs which are specified with wildcards are run based on the
305 +new time immediately.
306 +.PP
307 +Clock changes of more than 3 hours are considered to be corrections to
308 +the clock, and the new time is used immediately.
309 +.SH DEBIAN SPECIFIC
310 +.I cron
311 +treats the files in /etc/cron.d as extensions to the /etc/crontab file (they
312 +follow the special format of that file, i.e. they include the 
313 +.I user
314 +field). The intended purpose of this feature is to allow packages that require
315 +finer control of their scheduling than the /etc/cron.{daily,weekly,monthly} 
316 +directories allow to add a crontab file to /etc/cron.d. Such files
317 +should be named after the package that supplies them. Files must
318 +conform to the same naming convention as used by run-parts(8): they
319 +must consist solely of upper- and lower-case letters, digits, underscores,
320 +and hyphens. Like /etc/crontab, the files in the /etc/cron.d directory are
321 +monitored for changes.
322  .SH "SEE ALSO"
323  crontab(1), crontab(5)
324  .SH AUTHOR
325 --- cron-3.0pl1.orig/cron.c
326 +++ cron-3.0pl1/cron.c
327 @@ -24,7 +24,7 @@
328  
329  
330  #include "cron.h"
331 -#include <sys/signal.h>
332 +#include <signal.h>
333  #if SYS_TIME_H
334  # include <sys/time.h>
335  #else
336 @@ -34,9 +34,9 @@
337  
338  static void    usage __P((void)),
339                 run_reboot_jobs __P((cron_db *)),
340 -               cron_tick __P((cron_db *)),
341 -               cron_sync __P((void)),
342 -               cron_sleep __P((void)),
343 +               find_jobs __P((time_min, cron_db *, int, int)),
344 +               set_time __P((void)),
345 +               cron_sleep __P((time_min)),
346  #ifdef USE_SIGCHLD
347                 sigchld_handler __P((int)),
348  #endif
349 @@ -46,7 +46,16 @@
350  
351  static void
352  usage() {
353 -       fprintf(stderr, "usage:  %s [-x debugflag[,...]]\n", ProgramName);
354 +#if DEBUGGING
355 +       char **dflags;
356 +
357 +       fprintf(stderr, "usage:  %s [-x [", ProgramName);
358 +       for(dflags = DebugFlagNames; *dflags; dflags++)
359 +               fprintf(stderr, "%s%s", *dflags, dflags[1] ? "," : "]");
360 +       fprintf(stderr, "]\n");
361 +#else
362 +       fprintf(stderr, "usage: %s\n", ProgramName);
363 +#endif
364         exit(ERROR_EXIT);
365  }
366  
367 @@ -100,6 +109,9 @@
368                         /* child process */
369                         log_it("CRON",getpid(),"STARTUP","fork ok");
370                         (void) setsid();
371 +                       freopen("/dev/null", "r", stdin);
372 +                       freopen("/dev/null", "w", stdout);
373 +                       freopen("/dev/null", "w", stderr);
374                         break;
375                 default:
376                         /* parent process should just die */
377 @@ -110,28 +122,136 @@
378         acquire_daemonlock(0);
379         database.head = NULL;
380         database.tail = NULL;
381 -       database.mtime = (time_t) 0;
382 +       database.sys_mtime = (time_t) 0;
383 +       database.user_mtime = (time_t) 0;
384 +#ifdef DEBIAN
385 +       database.sysd_mtime = (time_t) 0;
386 +#endif
387         load_database(&database);
388 +
389 +       set_time();
390         run_reboot_jobs(&database);
391 -       cron_sync();
392 +       timeRunning = virtualTime = clockTime;
393 +
394 +       /*
395 +        * too many clocks, not enough time (Al. Einstein)
396 +        * These clocks are in minutes since the epoch (time()/60).
397 +        * virtualTime: is the time it *would* be if we woke up
398 +        * promptly and nobody ever changed the clock. It is
399 +        * monotonically increasing... unless a timejump happens.
400 +        * At the top of the loop, all jobs for 'virtualTime' have run.
401 +        * timeRunning: is the time we last awakened.
402 +        * clockTime: is the time when set_time was last called.
403 +        */
404         while (TRUE) {
405 -# if DEBUGGING
406 -               if (!(DebugFlags & DTEST))
407 -# endif /*DEBUGGING*/
408 -                       cron_sleep();
409 +               time_min timeDiff;
410 +               int wakeupKind;
411  
412                 load_database(&database);
413  
414 -               /* do this iteration
415 +               /* ... wait for the time (in minutes) to change ... */
416 +               do {
417 +                       cron_sleep(timeRunning + 1);
418 +                       set_time();
419 +               } while (clockTime == timeRunning);
420 +               timeRunning = clockTime;
421 +
422 +               /*
423 +                * ... calculate how the current time differs from
424 +                * our virtual clock. Classify the change into one
425 +                * of 4 cases
426                  */
427 -               cron_tick(&database);
428 +               timeDiff = timeRunning - virtualTime;
429  
430 -               /* sleep 1 minute
431 -                */
432 -               TargetTime += 60;
433 +               /* shortcut for the most common case */
434 +               if (timeDiff == 1) {
435 +                       virtualTime = timeRunning;
436 +                       find_jobs(virtualTime, &database, TRUE, TRUE);
437 +               } else {
438 +                       wakeupKind = -1;
439 +                       if (timeDiff > -(3*MINUTE_COUNT))
440 +                               wakeupKind = 0;
441 +                       if (timeDiff > 0)
442 +                               wakeupKind = 1;
443 +                       if (timeDiff > 5)
444 +                               wakeupKind = 2;
445 +                       if (timeDiff > (3*MINUTE_COUNT))
446 +                               wakeupKind = 3;
447 +
448 +                       switch (wakeupKind) {
449 +                       case 1:
450 +                               /*
451 +                                * case 1: timeDiff is a small positive number
452 +                                * (wokeup late) run jobs for each virtual minute
453 +                                * until caught up.
454 +                                */
455 +                               Debug(DSCH, ("[%d], normal case %d minutes to go\n",
456 +                                   getpid(), timeRunning - virtualTime))
457 +                               do {
458 +                                       if (job_runqueue())
459 +                                               sleep(10);
460 +                                       virtualTime++;
461 +                                       find_jobs(virtualTime, &database, TRUE, TRUE);
462 +                               } while (virtualTime< timeRunning);
463 +                               break;
464 +
465 +                       case 2:
466 +                               /*
467 +                                * case 2: timeDiff is a medium-sized positive number,
468 +                                * for example because we went to DST run wildcard
469 +                                * jobs once, then run any fixed-time jobs that would
470 +                                * otherwise be skipped if we use up our minute
471 +                                * (possible, if there are a lot of jobs to run) go
472 +                                * around the loop again so that wildcard jobs have
473 +                                * a chance to run, and we do our housekeeping
474 +                                */
475 +                               Debug(DSCH, ("[%d], DST begins %d minutes to go\n",
476 +                                   getpid(), timeRunning - virtualTime))
477 +                               /* run wildcard jobs for current minute */
478 +                               find_jobs(timeRunning, &database, TRUE, FALSE);
479 +       
480 +                               /* run fixed-time jobs for each minute missed */ 
481 +                               do {
482 +                                       if (job_runqueue())
483 +                                               sleep(10);
484 +                                       virtualTime++;
485 +                                       find_jobs(virtualTime, &database, FALSE, TRUE);
486 +                                       set_time();
487 +                               } while (virtualTime< timeRunning &&
488 +                                   clockTime == timeRunning);
489 +                               break;
490 +       
491 +                       case 0:
492 +                               /*
493 +                                * case 3: timeDiff is a small or medium-sized
494 +                                * negative num, eg. because of DST ending just run
495 +                                * the wildcard jobs. The fixed-time jobs probably
496 +                                * have already run, and should not be repeated
497 +                                * virtual time does not change until we are caught up
498 +                                */
499 +                               Debug(DSCH, ("[%d], DST ends %d minutes to go\n",
500 +                                   getpid(), virtualTime - timeRunning))
501 +                               find_jobs(timeRunning, &database, TRUE, FALSE);
502 +                               break;
503 +                       default:
504 +                               /*
505 +                                * other: time has changed a *lot*,
506 +                                * jump virtual time, and run everything
507 +                                */
508 +                               Debug(DSCH, ("[%d], clock jumped\n", getpid()))
509 +                               virtualTime = timeRunning;
510 +                               find_jobs(timeRunning, &database, TRUE, TRUE);
511 +                       }
512 +               }
513 +               /* jobs to be run (if any) are loaded. clear the queue */
514 +               job_runqueue();
515         }
516  }
517  
518 +#ifdef DEBIAN
519 +#include <sys/stat.h>
520 +#include <fcntl.h>
521 +#endif
522  
523  static void
524  run_reboot_jobs(db)
525 @@ -139,7 +259,31 @@
526  {
527         register user           *u;
528         register entry          *e;
529 +    int rbfd;
530 +#ifdef DEBIAN
531 +#define REBOOT_FILE "/var/run/crond.reboot"
532 +       /* Run on actual reboot, rather than cron restart */
533 +       if (access(REBOOT_FILE, F_OK) == 0) {
534 +               /* File exists, return */
535 +               log_it("CRON", getpid(),"INFO",
536 +                      "Skipping @reboot jobs -- not system startup");
537 +               return;
538 +       }
539 +       /* Create the file */
540 +       if ((rbfd = creat(REBOOT_FILE, S_IRUSR&S_IWUSR)) < 0) {
541 +               /* Bad news, bail out */
542 +               log_it("CRON",getpid(),"DEATH","Can't create reboot check file");
543 +               exit(0);
544 +       } else {
545 +               close(rbfd);
546 +               log_it("CRON", getpid(),"INFO", "Running @reboot jobs");
547 +       }
548 +      
549  
550 +        Debug(DMISC, ("[%d], Debian running reboot jobs\n",getpid()));
551 +    
552 +#endif
553 +        Debug(DMISC, ("[%d], vixie running reboot jobs\n", getpid()));
554         for (u = db->head;  u != NULL;  u = u->next) {
555                 for (e = u->crontab;  e != NULL;  e = e->next) {
556                         if (e->flags & WHEN_REBOOT) {
557 @@ -152,10 +296,14 @@
558  
559  
560  static void
561 -cron_tick(db)
562 +find_jobs(vtime, db, doWild, doNonWild)
563 +       time_min vtime;
564         cron_db *db;
565 +       int doWild;
566 +       int doNonWild;
567  {
568 -       register struct tm      *tm = localtime(&TargetTime);
569 +       time_t   virtualSecond  = vtime * SECONDS_PER_MINUTE;
570 +       register struct tm      *tm = localtime(&virtualSecond);
571         register int            minute, hour, dom, month, dow;
572         register user           *u;
573         register entry          *e;
574 @@ -168,8 +316,9 @@
575         month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
576         dow = tm->tm_wday -FIRST_DOW;
577  
578 -       Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d)\n",
579 -               getpid(), minute, hour, dom, month, dow))
580 +       Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d) %s %s\n",
581 +               getpid(), minute, hour, dom, month, dow,
582 +               doWild?" ":"No wildcard",doNonWild?" ":"Wildcard only"))
583  
584         /* the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
585          * first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
586 @@ -180,73 +329,57 @@
587         for (u = db->head;  u != NULL;  u = u->next) {
588                 for (e = u->crontab;  e != NULL;  e = e->next) {
589                         Debug(DSCH|DEXT, ("user [%s:%d:%d:...] cmd=\"%s\"\n",
590 -                                         env_get("LOGNAME", e->envp),
591 -                                         e->uid, e->gid, e->cmd))
592 -                       if (bit_test(e->minute, minute)
593 -                        && bit_test(e->hour, hour)
594 -                        && bit_test(e->month, month)
595 -                        && ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
596 +                           env_get("LOGNAME", e->envp),
597 +                           e->uid, e->gid, e->cmd))
598 +                       if (bit_test(e->minute, minute) &&
599 +                           bit_test(e->hour, hour) &&
600 +                           bit_test(e->month, month) &&
601 +                           ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
602                               ? (bit_test(e->dow,dow) && bit_test(e->dom,dom))
603 -                             : (bit_test(e->dow,dow) || bit_test(e->dom,dom))
604 -                           )
605 -                          ) {
606 -                               job_add(e, u);
607 +                             : (bit_test(e->dow,dow) || bit_test(e->dom,dom)))) {
608 +                               if ((doNonWild && !(e->flags & (MIN_STAR|HR_STAR)))
609 +                                   || (doWild && (e->flags & (MIN_STAR|HR_STAR))))
610 +                                       job_add(e, u);
611                         }
612                 }
613         }
614  }
615  
616  
617 -/* the task here is to figure out how long it's going to be until :00 of the
618 - * following minute and initialize TargetTime to this value.  TargetTime
619 - * will subsequently slide 60 seconds at a time, with correction applied
620 - * implicitly in cron_sleep().  it would be nice to let cron execute in
621 - * the "current minute" before going to sleep, but by restarting cron you
622 - * could then get it to execute a given minute's jobs more than once.
623 - * instead we have the chance of missing a minute's jobs completely, but
624 - * that's something sysadmin's know to expect what with crashing computers..
625 +/*
626 + * set StartTime and clockTime to the current time.
627 + * these are used for computing what time it really is right now.
628 + * note that clockTime is a unix wallclock time converted to minutes
629   */
630  static void
631 -cron_sync() {
632 -       register struct tm      *tm;
633 -
634 -       TargetTime = time((time_t*)0);
635 -       tm = localtime(&TargetTime);
636 -       TargetTime += (60 - tm->tm_sec);
637 +set_time()
638 +{
639 +       StartTime = time((time_t *)0);
640 +       clockTime = StartTime / (unsigned long)SECONDS_PER_MINUTE;
641  }
642  
643 -
644 +/*
645 + * try to just hit the next minute
646 + */
647  static void
648 -cron_sleep() {
649 +cron_sleep(target)
650 +       time_min target;
651 +{
652         register int    seconds_to_wait;
653  
654 -       do {
655 -               seconds_to_wait = (int) (TargetTime - time((time_t*)0));
656 -               Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
657 -                       getpid(), TargetTime, seconds_to_wait))
658 -
659 -               /* if we intend to sleep, this means that it's finally
660 -                * time to empty the job queue (execute it).
661 -                *
662 -                * if we run any jobs, we'll probably screw up our timing,
663 -                * so go recompute.
664 -                *
665 -                * note that we depend here on the left-to-right nature
666 -                * of &&, and the short-circuiting.
667 -                */
668 -       } while (seconds_to_wait > 0 && job_runqueue());
669 +       seconds_to_wait = (int)(target*SECONDS_PER_MINUTE - time((time_t*)0)) + 1;
670 +       Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
671 +           getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait))
672  
673 -       while (seconds_to_wait > 0) {
674 -               Debug(DSCH, ("[%d] sleeping for %d seconds\n",
675 -                       getpid(), seconds_to_wait))
676 -               seconds_to_wait = (int) sleep((unsigned int) seconds_to_wait);
677 -       }
678 +       if (seconds_to_wait > 0 && seconds_to_wait< 65)
679 +               sleep((unsigned int) seconds_to_wait);
680  }
681  
682  
683  #ifdef USE_SIGCHLD
684  static void
685  sigchld_handler(x) {
686 +       int save_errno = errno;
687         WAIT_T          waiter;
688         PID_T           pid;
689  
690 @@ -260,10 +393,12 @@
691                 case -1:
692                         Debug(DPROC,
693                                 ("[%d] sigchld...no children\n", getpid()))
694 +                       errno = save_errno;
695                         return;
696                 case 0:
697                         Debug(DPROC,
698                                 ("[%d] sigchld...no dead kids\n", getpid()))
699 +                       errno = save_errno;
700                         return;
701                 default:
702                         Debug(DPROC,
703 @@ -271,6 +406,7 @@
704                                 getpid(), pid, WEXITSTATUS(waiter)))
705                 }
706         }
707 +       errno = save_errno;
708  }
709  #endif /*USE_SIGCHLD*/
710  
711 @@ -278,6 +414,10 @@
712  static void
713  sighup_handler(x) {
714         log_close();
715 +
716 +       /* we should use sigaction for proper signal blocking as this 
717 +          has a race, but... */
718 +       signal(SIGHUP, sighup_handler);
719  }
720  
721  
722 --- cron-3.0pl1.orig/cron.h
723 +++ cron-3.0pl1/cron.h
724 @@ -66,8 +66,8 @@
725  #define        OK_EXIT         0       /* exit() with this is considered 'normal' */
726  #define        MAX_FNAME       100     /* max length of internally generated fn */
727  #define        MAX_COMMAND     1000    /* max length of internally generated cmd */
728 -#define        MAX_ENVSTR      1000    /* max length of envvar=value\0 strings */
729 -#define        MAX_TEMPSTR     100     /* obvious */
730 +#define        MAX_TEMPSTR     1000    /* max length of envvar=value\0 strings */
731 +#define        MAX_ENVSTR      MAX_TEMPSTR     /* DO NOT change - buffer overruns otherwise */
732  #define        MAX_UNAME       20      /* max length of username, should be overkill */
733  #define        ROOT_UID        0       /* don't change this, it really must be root */
734  #define        ROOT_USER       "root"  /* ditto */
735 @@ -118,6 +118,10 @@
736                          LineNumber = ln; \
737                         }
738  
739 +typedef int time_min;
740 +
741 +#define SECONDS_PER_MINUTE 60
742 +
743  #define        FIRST_MINUTE    0
744  #define        LAST_MINUTE     59
745  #define        MINUTE_COUNT    (LAST_MINUTE - FIRST_MINUTE + 1)
746 @@ -160,6 +164,8 @@
747  #define        DOM_STAR        0x01
748  #define        DOW_STAR        0x02
749  #define        WHEN_REBOOT     0x04
750 +#define MIN_STAR       0x08
751 +#define HR_STAR                0x10
752  } entry;
753  
754                         /* the crontab database will be a list of the
755 @@ -178,7 +184,11 @@
756  
757  typedef        struct _cron_db {
758         user            *head, *tail;   /* links */
759 -       time_t          mtime;          /* last modtime on spooldir */
760 +       time_t          user_mtime;     /* last modtime on spooldir */
761 +       time_t          sys_mtime;      /* last modtime on system crontab */
762 +#ifdef DEBIAN
763 +       time_t          sysd_mtime;     /* last modtime on system crondir */
764 +#endif
765  } cron_db;
766  
767  
768 @@ -205,6 +215,7 @@
769                 get_char __P((FILE *)),
770                 get_string __P((char *, int, FILE *, char *)),
771                 swap_uids __P((void)),
772 +               swap_uids_back __P((void)),
773                 load_env __P((char *, FILE *)),
774                 cron_pclose __P((FILE *)),
775                 strcmp_until __P((char *, char *, int)),
776 @@ -225,7 +236,7 @@
777  entry          *load_entry __P((FILE *, void (*)(),
778                                  struct passwd *, char **));
779  
780 -FILE           *cron_popen __P((char *, char *));
781 +FILE           *cron_popen __P((char *, char *, entry *));
782  
783  
784                                 /* in the C tradition, we only create
785 @@ -254,7 +265,10 @@
786  
787  char   *ProgramName;
788  int    LineNumber;
789 -time_t TargetTime;
790 +time_t StartTime;
791 +time_min timeRunning;
792 +time_min virtualTime;
793 +time_min clockTime;
794  
795  # if DEBUGGING
796  int    DebugFlags;
797 @@ -269,7 +283,10 @@
798                 *DowNames[],
799                 *ProgramName;
800  extern int     LineNumber;
801 -extern time_t  TargetTime;
802 +extern time_t  StartTime;
803 +extern  time_min timeRunning;
804 +extern  time_min virtualTime;
805 +extern  time_min clockTime;
806  # if DEBUGGING
807  extern int     DebugFlags;
808  extern char    *DebugFlagNames[];
809 --- cron-3.0pl1.orig/crontab.1
810 +++ cron-3.0pl1/crontab.1
811 @@ -26,26 +26,27 @@
812  .br
813  crontab [ -u user ] { -l | -r | -e }
814  .SH DESCRIPTION
815 -.I Crontab
816 +.I crontab
817  is the program used to install, deinstall or list the tables
818  used to drive the
819  .IR cron (8)
820  daemon in Vixie Cron.  Each user can have their own crontab, and though
821 -these are files in /var, they are not intended to be edited directly.
822 +these are files in /var/spool/cron/crontabs,
823 +they are not intended to be edited directly.
824  .PP
825  If the
826 -.I allow
827 +.I /etc/cron.allow
828  file exists, then you must be listed therein in order to be allowed to use
829  this command.  If the
830 -.I allow
831 +.I /etc/cron.allow
832  file does not exist but the
833 -.I deny
834 +.I /etc/cron.deny
835  file does exist, then you must \fBnot\fR be listed in the
836 -.I deny
837 +.I /etc/cron.deny
838  file in order to use this command.  If neither of these files exists, then
839  depending on site-dependent configuration parameters, only the super user
840  will be allowed to use this command, or all users will be able to use this
841 -command.
842 +command. For standard Debian systems, all users may use this command.
843  .PP
844  If the
845  .I -u
846 @@ -58,7 +59,7 @@
847  can confuse
848  .I crontab
849  and that if you are running inside of
850 -.IR su (8)
851 +.IR su (8) 
852  you should always use the
853  .I -u
854  option for safety's sake.
855 @@ -68,7 +69,10 @@
856  .PP
857  The
858  .I -l
859 -option causes the current crontab to be displayed on standard output.
860 +option causes the current crontab to be displayed on standard output. See
861 +the note under 
862 +.B DEBIAN SPECIFIC
863 +below.
864  .PP
865  The
866  .I -r
867 @@ -77,14 +81,39 @@
868  The
869  .I -e
870  option is used to edit the current crontab using the editor specified by
871 -the \s-1VISUAL\s+1 or \s-1EDITOR\s+1 environment variables.  After you exit
872 +the \s-1VISUAL\s+1 or \s-1EDITOR\s+1 environment variables.
873 +The specified editor
874 +.B must
875 +edit the file in place;
876 +any editor that unlinks the file and recreates it cannot be used.
877 +After you exit
878  from the editor, the modified crontab will be installed automatically.
879 +.SH DEBIAN SPECIFIC
880 +The "out-of-the-box" behaviour for
881 +.I crontab -l
882 +is to display the three line "DO NOT EDIT THIS FILE" header 
883 +that is placed at the
884 +beginning of the crontab when it is installed. The problem is that
885 +it makes the sequence
886 +.PP
887 +crontab -l | crontab -
888 +.PP
889 +non-idempotent -- you keep adding copies of the header. This causes
890 +pain to scripts that use sed to edit a crontab. Therefore, the default
891 +behaviour of the 
892 +.B -l
893 +option has been changed to not output such header. You may obtain the
894 +original behaviour by setting the environment variable 
895 +.B CRONTAB_NOHEADER
896 +to 'N', which will cause the
897 +.I crontab -l
898 +command to emit the extraneous header.
899  .SH "SEE ALSO"
900  crontab(5), cron(8)
901  .SH FILES
902  .nf
903 -/var/cron/allow
904 -/var/cron/deny
905 +/etc/cron.allow
906 +/etc/cron.deny
907  .fi
908  .SH STANDARDS
909  The
910 @@ -92,9 +121,18 @@
911  command conforms to IEEE Std1003.2-1992 (``POSIX'').  This new command syntax
912  differs from previous versions of Vixie Cron, as well as from the classic
913  SVR3 syntax.
914 +
915  .SH DIAGNOSTICS
916  A fairly informative usage message appears if you run it with a bad command
917  line.
918 +
919 +.SH BUGS
920 +Although cron requires that each entry in a crontab end in a newline
921 +character, the neither the crontab command nor the cron daemon will
922 +detect this error. Instead, the crontab will appear load
923 +normally. However, the command will never run. The best choice is to
924 +ensure that your crontab has a blank line at the end.
925 +
926  .SH AUTHOR
927  .nf
928  Paul Vixie <paul@vix.com>
929 --- cron-3.0pl1.orig/crontab.5
930 +++ cron-3.0pl1/crontab.5
931 @@ -34,7 +34,7 @@
932  as part of a cron command.
933  .PP
934  Blank lines and leading spaces and tabs are ignored.  Lines whose first
935 -non-space character is a pound-sign (#) are comments, and are ignored.
936 +non-space character is a hash-sign (#) are comments, and are ignored.
937  Note that comments are not allowed on the same line as cron commands, since
938  they will be taken to be part of the command.  Similarly, comments are not
939  allowed on the same line as environment variable settings.
940 @@ -59,8 +59,9 @@
941  .IR cron (8)
942  daemon.
943  SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd 
944 -line of the crontab's owner.
945 -HOME and SHELL may be overridden by settings in the crontab; LOGNAME may not.
946 +line of the crontab's owner. PATH is set to "/usr/bin:/bin".
947 +HOME, SHELL, and PATH may be overridden by settings in the crontab;
948 +LOGNAME may not.
949  .PP
950  (Another note: the LOGNAME variable is sometimes called USER on BSD systems...
951  on these systems, USER will be set also.)
952 @@ -70,15 +71,19 @@
953  will look at MAILTO if it has any reason to send mail as a result of running
954  commands in ``this'' crontab.  If MAILTO is defined (and non-empty), mail is
955  sent to the user so named.  If MAILTO is defined but empty (MAILTO=""), no
956 -mail will be sent.  Otherwise mail is sent to the owner of the crontab.  This
957 -option is useful if you decide on /bin/mail instead of /usr/lib/sendmail as
958 -your mailer when you install cron -- /bin/mail doesn't do aliasing, and UUCP
959 -usually doesn't read its mail.
960 +mail will be sent.  Otherwise mail is sent to the owner of the crontab.
961  .PP
962  The format of a cron command is very much the V7 standard, with a number of
963  upward-compatible extensions.  Each line has five time and date fields,
964 -followed by a user name if this is the system crontab file,
965 -followed by a command.  Commands are executed by
966 +followed by a command, followed by a newline character ('\n').  
967 +The system crontab (/etc/crontab) uses the same format, except that
968 +the username for the command is specified after the time and
969 +date fields and before the command.
970 +Note that if the line does not have a trailing newline character, the
971 +entire line will be silently ignored by both crontab and cron; the command
972 +will never be executed.
973 +.PP
974 +Commands are executed by
975  .IR cron (8)
976  when the minute, hour, and month of year fields match the current time,
977  .I and
978 @@ -97,9 +102,9 @@
979  .br
980  hour   0-23
981  .br
982 -day of month   0-31
983 +day of month   1-31
984  .br
985 -month  0-12 (or names, see below)
986 +month  1-12 (or names, see below)
987  .br
988  day of week    0-7 (0 or 7 is Sun, or use names)
989  .br
990 @@ -146,6 +151,30 @@
991  ``30 4 1,15 * 5''
992  would cause a command to be run at 4:30 am on the 1st and 15th of each
993  month, plus every Friday.
994 +.PP
995 +Instead of the first five fields, one of eight special strings may appear:
996 +.IP
997 +.ta 1.5i
998 +string meaning
999 +.br
1000 +------ -------
1001 +.br
1002 +@reboot        Run once, at startup.
1003 +.br
1004 +@yearly        Run once a year, "0 0 1 1 *".
1005 +.br
1006 +@annually      (same as @yearly)
1007 +.br
1008 +@monthly       Run once a month, "0 0 1 * *".
1009 +.br
1010 +@weekly        Run once a week, "0 0 * * 0".
1011 +.br
1012 +@daily Run once a day, "0 0 * * *".
1013 +.br
1014 +@midnight      (same as @daily)
1015 +.br
1016 +@hourly        Run once an hour, "0 * * * *".
1017 +.br
1018  .SH EXAMPLE CRON FILE
1019  .nf
1020  
1021 @@ -163,6 +192,25 @@
1022  23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
1023  5 4 * * sun     echo "run at 5 after 4 every sunday"
1024  .fi
1025 +.SH EXAMPLE SYSTEM CRON FILE
1026 +This has the username field, as used by /etc/crontab.
1027 +.nf
1028 +# /etc/crontab: system-wide crontab
1029 +# Unlike any other crontab you don't have to run the `crontab'
1030 +# command to install the new version when you edit this file.
1031 +# This file also has a username field, that none of the other crontabs do.
1032 +
1033 +SHELL=/bin/sh
1034 +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
1035 +
1036 +# m h dom mon dow user command
1037 +42 6   * * *   root    run-parts --report /etc/cron.daily
1038 +47 6   * * 7   root    run-parts --report /etc/cron.weekly
1039 +52 6   1 * *   root    run-parts --report /etc/cron.monthly
1040 +#
1041 +# Removed invocation of anacron, as this is now handled by a 
1042 +# /etc/cron.d file
1043 +.fi
1044  .SH SEE ALSO
1045  cron(8), crontab(1)
1046  .SH EXTENSIONS
1047 @@ -183,6 +231,9 @@
1048  mailed to a person other than the crontab owner (SysV can't do this), or the
1049  feature can be turned off and no mail will be sent at all (SysV can't do this
1050  either).
1051 +.PP
1052 +All of the `@' commands that can appear in place of the first five fields
1053 +are extensions.
1054  .SH AUTHOR
1055  .nf
1056  Paul Vixie <paul@vix.com>
1057 --- cron-3.0pl1.orig/crontab.c
1058 +++ cron-3.0pl1/crontab.c
1059 @@ -31,6 +31,7 @@
1060  #include "cron.h"
1061  #include <errno.h>
1062  #include <fcntl.h>
1063 +#include <signal.h>
1064  #include <sys/file.h>
1065  #include <sys/stat.h>
1066  #ifdef USE_UTIMES
1067 @@ -55,9 +56,9 @@
1068  
1069  
1070  static PID_T           Pid;
1071 -static char            User[MAX_UNAME], RealUser[MAX_UNAME];
1072 +static char            *User, *RealUser;
1073  static char            Filename[MAX_FNAME];
1074 -static FILE            *NewCrontab;
1075 +static FILE            *NewCrontab = NULL;
1076  static int             CheckErrorCount;
1077  static enum opt_t      Option;
1078  static struct passwd   *pw;
1079 @@ -124,11 +125,23 @@
1080         case opt_replace:       if (replace_cmd() < 0)
1081                                         exitstatus = ERROR_EXIT;
1082                                 break;
1083 +                               /* The following was added to shut
1084 +                                -Wall up, but it will never be hit,
1085 +                                because the option parser will catch
1086 +                                it */
1087 +       case opt_unknown: usage("unknown option specified");
1088 +                         break;
1089         }
1090         exit(0);
1091         /*NOTREACHED*/
1092  }
1093         
1094 +#if DEBUGGING
1095 +char *getoptarg = "u:lerx:";
1096 +#else
1097 +char *getoptarg = "u:ler";
1098 +#endif
1099 +
1100  
1101  static void
1102  parse_args(argc, argv)
1103 @@ -136,6 +149,7 @@
1104         char    *argv[];
1105  {
1106         int             argch;
1107 +       struct stat     statbuf;
1108  
1109         if (!(pw = getpwuid(getuid()))) {
1110                 fprintf(stderr, "%s: your UID isn't in the passwd file.\n",
1111 @@ -143,30 +157,42 @@
1112                 fprintf(stderr, "bailing out.\n");
1113                 exit(ERROR_EXIT);
1114         }
1115 -       strcpy(User, pw->pw_name);
1116 -       strcpy(RealUser, User);
1117 +       if (((User=strdup(pw->pw_name)) == NULL) ||
1118 +           ((RealUser=strdup(pw->pw_name)) == NULL)) {
1119 +               fprintf(stderr, "Memory allocation error\n");
1120 +               exit(ERROR_EXIT);
1121 +       }
1122         Filename[0] = '\0';
1123         Option = opt_unknown;
1124 -       while (EOF != (argch = getopt(argc, argv, "u:lerx:"))) {
1125 +
1126 +       while (EOF != (argch = getopt(argc, argv, getoptarg))) {
1127                 switch (argch) {
1128 +#if DEBUGGING
1129                 case 'x':
1130                         if (!set_debug_flags(optarg))
1131                                 usage("bad debug option");
1132 +                       usage("unrecognized option");
1133                         break;
1134 +#endif
1135                 case 'u':
1136 -                       if (getuid() != ROOT_UID)
1137 +                       if (!(pw = getpwnam(optarg)))
1138 +                       {
1139 +                               fprintf(stderr, "%s:  user `%s' unknown\n",
1140 +                                       ProgramName, optarg);
1141 +                               exit(ERROR_EXIT);
1142 +                       }
1143 +                       if ((getuid() != ROOT_UID) &&
1144 +                           (getuid() != pw->pw_uid))
1145                         {
1146                                 fprintf(stderr,
1147                                         "must be privileged to use -u\n");
1148                                 exit(ERROR_EXIT);
1149                         }
1150 -                       if (!(pw = getpwnam(optarg)))
1151 -                       {
1152 -                               fprintf(stderr, "%s:  user `%s' unknown\n",
1153 -                                       ProgramName, optarg);
1154 +                       free(User);
1155 +                       if ((User=strdup(pw->pw_name)) == NULL) {
1156 +                               fprintf(stderr, "Memory allocation error\n");
1157                                 exit(ERROR_EXIT);
1158                         }
1159 -                       (void) strcpy(User, optarg);
1160                         break;
1161                 case 'l':
1162                         if (Option != opt_unknown)
1163 @@ -197,7 +223,9 @@
1164         } else {
1165                 if (argv[optind] != NULL) {
1166                         Option = opt_replace;
1167 -                       (void) strcpy (Filename, argv[optind]);
1168 +                       (void) strncpy (Filename, argv[optind], (sizeof Filename)-1);
1169 +                       Filename[(sizeof Filename)-1] = '\0';
1170 +
1171                 } else {
1172                         usage("file name must be specified for replace");
1173                 }
1174 @@ -227,7 +255,16 @@
1175                                 perror(Filename);
1176                                 exit(ERROR_EXIT);
1177                         }
1178 -                       if (swap_uids() < OK) {
1179 +                       /* Make sure we opened a normal file. */
1180 +                       if (fstat(fileno(NewCrontab), &statbuf) < 0) {
1181 +                               perror("fstat");
1182 +                               exit(ERROR_EXIT);
1183 +                       }
1184 +                       if (!S_ISREG(statbuf.st_mode)) {
1185 +                               fprintf(stderr, "%s: Not a regular file.\n", Filename);
1186 +                               exit(ERROR_EXIT);
1187 +                       }
1188 +                       if (swap_uids_back() < OK) {
1189                                 perror("swapping uids back");
1190                                 exit(ERROR_EXIT);
1191                         }
1192 @@ -244,9 +281,13 @@
1193         char    n[MAX_FNAME];
1194         FILE    *f;
1195         int     ch;
1196 +#ifdef DEBIAN
1197 +       int     x;
1198 +       char    *ctnh;
1199 +#endif
1200  
1201         log_it(RealUser, Pid, "LIST", User);
1202 -       (void) sprintf(n, CRON_TAB(User));
1203 +       (void) snprintf(n, MAX_FNAME, CRON_TAB(User));
1204         if (!(f = fopen(n, "r"))) {
1205                 if (errno == ENOENT)
1206                         fprintf(stderr, "no crontab for %s\n", User);
1207 @@ -258,6 +299,30 @@
1208         /* file is open. copy to stdout, close.
1209          */
1210         Set_LineNum(1)
1211 +#ifdef DEBIAN
1212 +         /* DEBIAN: Don't list header lines unless CRONTAB_NOHEADER is
1213 +            'N'. */
1214 +         /* ignore the top few comments since we probably put them there.
1215 +          */
1216 +         if (!(ctnh = getenv("CRONTAB_NOHEADER")) ||
1217 +             toupper(*ctnh) != 'N') 
1218 +           {
1219 +           for (x = 0;  x < NHEADER_LINES;  x++) {
1220 +             ch = get_char(f);
1221 +             if (EOF == ch)
1222 +               break;
1223 +             if ('#' != ch) {
1224 +               putchar(ch);
1225 +               break;
1226 +             }
1227 +             while (EOF != (ch = get_char(f)))
1228 +               if (ch == '\n')
1229 +                 break;
1230 +             if (EOF == ch)
1231 +               break;
1232 +           }
1233 +         }
1234 +#endif
1235         while (EOF != (ch = get_char(f)))
1236                 putchar(ch);
1237         fclose(f);
1238 @@ -269,7 +334,7 @@
1239         char    n[MAX_FNAME];
1240  
1241         log_it(RealUser, Pid, "DELETE", User);
1242 -       (void) sprintf(n, CRON_TAB(User));
1243 +       (void) snprintf(n, MAX_FNAME, CRON_TAB(User));
1244         if (unlink(n)) {
1245                 if (errno == ENOENT)
1246                         fprintf(stderr, "no crontab for %s\n", User);
1247 @@ -295,13 +360,14 @@
1248         char            n[MAX_FNAME], q[MAX_TEMPSTR], *editor;
1249         FILE            *f;
1250         int             ch, t, x;
1251 -       struct stat     statbuf;
1252 +       struct stat     statbuf, fsbuf;
1253         time_t          mtime;
1254         WAIT_T          waiter;
1255         PID_T           pid, xpid;
1256 +       mode_t          um;
1257  
1258         log_it(RealUser, Pid, "BEGIN EDIT", User);
1259 -       (void) sprintf(n, CRON_TAB(User));
1260 +       (void) snprintf(n, MAX_FNAME, CRON_TAB(User));
1261         if (!(f = fopen(n, "r"))) {
1262                 if (errno != ENOENT) {
1263                         perror(n);
1264 @@ -315,11 +381,26 @@
1265                 }
1266         }
1267  
1268 -       (void) sprintf(Filename, "/tmp/crontab.%d", Pid);
1269 -       if (-1 == (t = open(Filename, O_CREAT|O_EXCL|O_RDWR, 0600))) {
1270 +       um = umask(077);
1271 +#if 0
1272 +       /* The support for TMPDIR is temporarily removed, because of
1273 +          interactions with emacs */
1274 +       if (getenv("TMPDIR")) {
1275 +         strcpy(Filename, getenv("TMPDIR"));
1276 +       } else {
1277 +         strcpy(Filename,"/tmp");
1278 +       }
1279 +#else
1280 +         strcpy(Filename,"/tmp");
1281 +#endif
1282 +        
1283 +       (void) sprintf(Filename+strlen(Filename), "/crontab.XXXXXXXXXX");
1284 +       if ((t = mkstemp(Filename)) == -1) {
1285                 perror(Filename);
1286 +               (void) umask(um);
1287                 goto fatal;
1288         }
1289 +       (void) umask(um);
1290  #ifdef HAS_FCHOWN
1291         if (fchown(t, getuid(), getgid()) < 0) {
1292  #else
1293 @@ -362,6 +443,10 @@
1294                 perror(Filename);
1295                 exit(ERROR_EXIT);
1296         }
1297 +       if (fstat(t, &fsbuf) < 0) {
1298 +               perror("unable to fstat temp file");
1299 +               goto fatal;
1300 +       }
1301   again:
1302         rewind(NewCrontab);
1303         if (ferror(NewCrontab)) {
1304 @@ -374,6 +459,11 @@
1305                 perror("fstat");
1306                 goto fatal;
1307         }
1308 +       if (statbuf.st_dev != fsbuf.st_dev || statbuf.st_ino != fsbuf.st_ino) {
1309 +               fprintf(stderr, "temp file must be edited in place\n");
1310 +               exit(ERROR_EXIT);
1311 +       }
1312 +
1313         mtime = statbuf.st_mtime;
1314  
1315         if ((!(editor = getenv("VISUAL")))
1316 @@ -390,6 +480,10 @@
1317          * close and reopen the file around the edit.
1318          */
1319  
1320 +       /* Turn off signals. */
1321 +       (void)signal(SIGHUP, SIG_IGN);
1322 +       (void)signal(SIGINT, SIG_IGN);
1323 +       (void)signal(SIGQUIT, SIG_IGN);
1324         switch (pid = fork()) {
1325         case -1:
1326                 perror("fork");
1327 @@ -409,7 +503,7 @@
1328                                 ProgramName);
1329                         exit(ERROR_EXIT);
1330                 }
1331 -               sprintf(q, "%s %s", editor, Filename);
1332 +               snprintf(q, MAX_TEMPSTR, "%s %s", editor, Filename);
1333                 execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", q, NULL);
1334                 perror(editor);
1335                 exit(ERROR_EXIT);
1336 @@ -420,23 +514,37 @@
1337         }
1338  
1339         /* parent */
1340 -       xpid = wait(&waiter);
1341 -       if (xpid != pid) {
1342 -               fprintf(stderr, "%s: wrong PID (%d != %d) from \"%s\"\n",
1343 -                       ProgramName, xpid, pid, editor);
1344 -               goto fatal;
1345 -       }
1346 -       if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
1347 -               fprintf(stderr, "%s: \"%s\" exited with status %d\n",
1348 -                       ProgramName, editor, WEXITSTATUS(waiter));
1349 -               goto fatal;
1350 -       }
1351 -       if (WIFSIGNALED(waiter)) {
1352 -               fprintf(stderr,
1353 -                       "%s: \"%s\" killed; signal %d (%score dumped)\n",
1354 -                       ProgramName, editor, WTERMSIG(waiter),
1355 -                       WCOREDUMP(waiter) ?"" :"no ");
1356 -               goto fatal;
1357 +       while (1) {
1358 +               xpid = waitpid(pid, &waiter, WUNTRACED);
1359 +               if (xpid == -1) {
1360 +                       fprintf(stderr, "%s: waitpid() failed waiting for PID %d from \"%s\": %s\n",
1361 +                               ProgramName, pid, editor, strerror(errno));
1362 +               } else if (xpid != pid) {
1363 +                       fprintf(stderr, "%s: wrong PID (%d != %d) from \"%s\"\n",
1364 +                               ProgramName, xpid, pid, editor);
1365 +                       goto fatal;
1366 +               } else if (WIFSTOPPED(waiter)) {
1367 +                       /* raise(WSTOPSIG(waiter)); Not needed and breaks in job control shell*/
1368 +               } else if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
1369 +                       fprintf(stderr, "%s: \"%s\" exited with status %d\n",
1370 +                               ProgramName, editor, WEXITSTATUS(waiter));
1371 +                       goto fatal;
1372 +               } else if (WIFSIGNALED(waiter)) {
1373 +                       fprintf(stderr,
1374 +                               "%s: \"%s\" killed; signal %d (%score dumped)\n",
1375 +                               ProgramName, editor, WTERMSIG(waiter),
1376 +                               WCOREDUMP(waiter) ?"" :"no ");
1377 +                       goto fatal;
1378 +               } else
1379 +                       break;
1380 +       }
1381 +       (void)signal(SIGHUP, SIG_DFL);
1382 +       (void)signal(SIGINT, SIG_DFL);
1383 +       (void)signal(SIGQUIT, SIG_DFL);
1384 +       (void)signal(SIGTSTP, SIG_DFL);
1385 +       if (statbuf.st_dev != fsbuf.st_dev || statbuf.st_ino != fsbuf.st_ino) {
1386 +               fprintf(stderr, "temp file must be edited in place\n");
1387 +               exit(ERROR_EXIT);
1388         }
1389         if (fstat(t, &statbuf) < 0) {
1390                 perror("fstat");
1391 @@ -473,7 +581,8 @@
1392                         ProgramName, Filename);
1393                 goto done;
1394         default:
1395 -               fprintf(stderr, "%s: panic: bad switch() in replace_cmd()\n");
1396 +               fprintf(stderr, "%s: panic: bad switch() in replace_cmd()\n",
1397 +                   ProgramName);
1398                 goto fatal;
1399         }
1400   remove:
1401 @@ -481,7 +590,14 @@
1402   done:
1403         log_it(RealUser, Pid, "END EDIT", User);
1404  }
1405 -       
1406 +
1407 +static char tn[MAX_FNAME];
1408 +
1409 +static void sig_handler(int x)
1410 +{
1411 +       unlink(tn);
1412 +       exit(1);
1413 +}      
1414  
1415  /* returns     0       on success
1416   *             -1      on syntax error
1417 @@ -489,19 +605,51 @@
1418   */
1419  static int
1420  replace_cmd() {
1421 -       char    n[MAX_FNAME], envstr[MAX_ENVSTR], tn[MAX_FNAME];
1422 +       char    n[MAX_FNAME], envstr[MAX_ENVSTR];
1423         FILE    *tmp;
1424 -       int     ch, eof;
1425 +       int     ch, eof, fd;
1426         entry   *e;
1427         time_t  now = time(NULL);
1428         char    **envp = env_init();
1429 +       mode_t  um;
1430 +       int     saved_uid;
1431  
1432 -       (void) sprintf(n, "tmp.%d", Pid);
1433 -       (void) sprintf(tn, CRON_TAB(n));
1434 -       if (!(tmp = fopen(tn, "w+"))) {
1435 +       if (envp == NULL) {
1436 +               fprintf(stderr, "%s: Cannot allocate memory.\n", ProgramName);
1437 +               return (-2);
1438 +       }
1439 +
1440 +       /* Assume privilege.  This way we can only receive signals on our
1441 +          input - the ones listed below (or from root - root's problem, not
1442 +          ours). */
1443 +       saved_uid = getuid();
1444 +       if (setuid(geteuid()) < 0) {
1445 +               perror("setuid");
1446 +               return -2;
1447 +       }
1448 +
1449 +       /* Assumes Linux-style signal handlers (takes int, returns void) */
1450 +       /* Signal handlers, to ensure we do not leave temp files in the
1451 +          spool dir.  We don't remove these on exiting this function;
1452 +          but that's OK, we exit immediately afterwards anyway. */
1453 +       signal(SIGHUP, sig_handler);
1454 +       signal(SIGINT, sig_handler);
1455 +       signal(SIGQUIT, sig_handler);
1456 +       signal(SIGTSTP, SIG_IGN);
1457 +
1458 +       (void) snprintf(tn, MAX_FNAME, CRON_TAB("tmp.XXXXXX"));
1459 +       um = umask(077);
1460 +       fd = mkstemp(tn);
1461 +       if (!fd) {
1462 +               perror(tn);
1463 +               return(-2);
1464 +       }
1465 +       tmp = fdopen(fd, "w+");
1466 +       if (!tmp) {
1467                 perror(tn);
1468                 return (-2);
1469         }
1470 +       (void) umask(um);
1471  
1472         /* write a signature at the top of the file.
1473          *
1474 @@ -517,19 +665,18 @@
1475         Set_LineNum(1)
1476         while (EOF != (ch = get_char(NewCrontab)))
1477                 putc(ch, tmp);
1478 -       ftruncate(fileno(tmp), ftell(tmp));
1479 -       fflush(tmp);  rewind(tmp);
1480  
1481 -       if (ferror(tmp)) {
1482 +       if (ferror(tmp) || fflush(tmp) || fsync(fd)) {
1483                 fprintf(stderr, "%s: error while writing new crontab to %s\n",
1484                         ProgramName, tn);
1485 +               perror("Error");
1486                 fclose(tmp);  unlink(tn);
1487                 return (-2);
1488         }
1489  
1490         /* check the syntax of the file being installed.
1491          */
1492 -
1493 +       rewind(tmp);
1494         /* BUG: was reporting errors after the EOF if there were any errors
1495          * in the file proper -- kludged it by stopping after first error.
1496          *              vix 31mar87
1497 @@ -554,6 +701,9 @@
1498         if (CheckErrorCount != 0) {
1499                 fprintf(stderr, "errors in crontab file, can't install.\n");
1500                 fclose(tmp);  unlink(tn);
1501 +               /* Give up privilege, in case we loop. */
1502 +               if (setreuid(saved_uid, -1) < 0)
1503 +                       return (-2);
1504                 return (-1);
1505         }
1506  
1507 @@ -585,7 +735,7 @@
1508                 return (-2);
1509         }
1510  
1511 -       (void) sprintf(n, CRON_TAB(User));
1512 +       (void) snprintf(n, sizeof(n), CRON_TAB(User));
1513         if (rename(tn, n)) {
1514                 fprintf(stderr, "%s: error renaming %s to %s\n",
1515                         ProgramName, tn, n);
1516 @@ -596,6 +746,11 @@
1517         log_it(RealUser, Pid, "REPLACE", User);
1518  
1519         poke_daemon();
1520 +
1521 +       /* Give up privilege, just in case. */
1522 +       /* Don't need to check for error; nothing happens beyond here but a log entry,
1523 +          and the failure message is incorrect after the rename above. */
1524 +       setreuid(saved_uid, -1);
1525  
1526         return (0);
1527  }
1528 --- cron-3.0pl1.orig/database.c
1529 +++ cron-3.0pl1/database.c
1530 @@ -31,22 +31,43 @@
1531  
1532  #define TMAX(a,b) ((a)>(b)?(a):(b))
1533  
1534 +/* Try to get maximum path name -- this isn't really correct, but we're
1535 +going to be lazy */
1536 +
1537 +#ifndef PATH_MAX
1538 +
1539 +#ifdef MAXPATHLEN
1540 +#define PATH_MAX MAXPATHLEN 
1541 +#else
1542 +#define PATH_MAX 2048
1543 +#endif
1544 +
1545 +#endif /* ifndef PATH_MAX */
1546  
1547  static void            process_crontab __P((char *, char *, char *,
1548                                              struct stat *,
1549                                              cron_db *, cron_db *));
1550 -
1551 -
1552 +#ifdef DEBIAN
1553 +static int valid_name (char *filename);
1554 +static user *get_next_system_crontab __P((user *));
1555 +#endif
1556  void
1557  load_database(old_db)
1558         cron_db         *old_db;
1559  {
1560 -       DIR             *dir;
1561 +        DIR            *dir;
1562         struct stat     statbuf;
1563         struct stat     syscron_stat;
1564         DIR_T           *dp;
1565         cron_db         new_db;
1566         user            *u, *nu;
1567 +#ifdef DEBIAN
1568 +       struct stat     syscrond_stat;
1569 +       struct stat     syscrond_file_stat;
1570 +       
1571 +        char            syscrond_fname[PATH_MAX+1];
1572 +       int             syscrond_change = 0;
1573 +#endif
1574  
1575         Debug(DLOAD, ("[%d] load_database()\n", getpid()))
1576  
1577 @@ -64,6 +85,53 @@
1578         if (stat(SYSCRONTAB, &syscron_stat) < OK)
1579                 syscron_stat.st_mtime = 0;
1580  
1581 +#ifdef DEBIAN
1582 +       /* Check mod time of SYSCRONDIR. This won't tell us if a file
1583 +         * in it changed, but will capture deletions, which the individual
1584 +         * file check won't
1585 +        */
1586 +       if (stat(SYSCRONDIR, &syscrond_stat) < OK) {
1587 +               log_it("CRON", getpid(), "STAT FAILED", SYSCRONDIR);
1588 +               (void) exit(ERROR_EXIT);
1589 +       }
1590 +
1591 +       /* If SYSCRONDIR was modified, we know that something is changed and
1592 +        * there is no need for any further checks. If it wasn't, we should
1593 +        * pass through the old list of files in SYSCRONDIR and check their
1594 +        * mod time. Therefore a stopped hard drive won't be spun up, since
1595 +        * we avoid reading of SYSCRONDIR and don't change its access time.
1596 +        * This is especially important on laptops with APM.
1597 +        */
1598 +       if (old_db->sysd_mtime != syscrond_stat.st_mtime) {
1599 +               syscrond_change = 1;
1600 +       } else {
1601 +               /* Look through the individual files */
1602 +               user *systab;
1603 +
1604 +               Debug(DLOAD, ("[%d] system dir mtime unch, check files now.\n",
1605 +                             getpid()))
1606 +
1607 +               for (systab = old_db->head;
1608 +                    (systab = get_next_system_crontab (systab)) != NULL;
1609 +                    systab = systab->next) {
1610 +
1611 +                       sprintf(syscrond_fname, "%s/%s", SYSCRONDIR,
1612 +                                                        systab->name + 8);
1613 +
1614 +                       Debug(DLOAD, ("\t%s:", syscrond_fname))
1615 +
1616 +                       if (stat(syscrond_fname, &syscrond_file_stat) < OK)
1617 +                               syscrond_file_stat.st_mtime = 0;
1618 +
1619 +                       if (syscrond_file_stat.st_mtime != systab->mtime) {
1620 +                               syscrond_change = 1;
1621 +                        }
1622 +
1623 +                       Debug(DLOAD, (" [checked]\n"))
1624 +               }
1625 +       }
1626 +#endif /* DEBIAN */
1627 +
1628         /* if spooldir's mtime has not changed, we don't need to fiddle with
1629          * the database.
1630          *
1631 @@ -71,7 +139,14 @@
1632          * so is guaranteed to be different than the stat() mtime the first
1633          * time this function is called.
1634          */
1635 -       if (old_db->mtime == TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) {
1636 +#ifdef DEBIAN
1637 +       if ((old_db->user_mtime == statbuf.st_mtime) &&
1638 +           (old_db->sys_mtime == syscron_stat.st_mtime) &&
1639 +           (!syscrond_change)) {
1640 +#else
1641 +       if ((old_db->user_mtime == statbuf.st_mtime) &&
1642 +           (old_db->sys_mtime == syscron_stat.st_mtime)) {
1643 +#endif
1644                 Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n",
1645                               getpid()))
1646                 return;
1647 @@ -82,7 +157,11 @@
1648          * actually changed.  Whatever is left in the old database when
1649          * we're done is chaff -- crontabs that disappeared.
1650          */
1651 -       new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
1652 +       new_db.user_mtime = statbuf.st_mtime;
1653 +       new_db.sys_mtime = syscron_stat.st_mtime;
1654 +#ifdef DEBIAN
1655 +       new_db.sysd_mtime = syscrond_stat.st_mtime;
1656 +#endif
1657         new_db.head = new_db.tail = NULL;
1658  
1659         if (syscron_stat.st_mtime) {
1660 @@ -91,6 +170,46 @@
1661                                 &new_db, old_db);
1662         }
1663  
1664 +#ifdef DEBIAN
1665 +       /* Read all the package crontabs. */
1666 +       if (!(dir = opendir(SYSCRONDIR))) {
1667 +               log_it("CRON", getpid(), "OPENDIR FAILED", SYSCRONDIR);
1668 +               (void) exit(ERROR_EXIT);
1669 +       }
1670 +
1671 +       while (NULL != (dp = readdir(dir))) {
1672 +               char    fname[MAXNAMLEN+1],
1673 +                       tabname[PATH_MAX+1];
1674 +
1675 +
1676 +               /* avoid file names beginning with ".".  this is good
1677 +                * because we would otherwise waste two guaranteed calls
1678 +                * to stat() for . and .., and also because package names
1679 +                * starting with a period are just too nasty to consider.
1680 +                */
1681 +               if (dp->d_name[0] == '.')
1682 +                       continue;
1683 +
1684 +               /* skipfile names with letters outside the set
1685 +                * [A-Za-z0-9_-], like run-parts.
1686 +                */
1687 +               if (!valid_name(dp->d_name))
1688 +                 continue;
1689 +
1690 +               /* Generate the "fname" */
1691 +               (void) strcpy(fname,"*system*");
1692 +               (void) strcat(fname, dp->d_name);
1693 +               sprintf(tabname,"%s/%s", SYSCRONDIR, dp->d_name);
1694 +
1695 +               /* statbuf is used as working storage by process_crontab() --
1696 +                  current contents are irrelevant */
1697 +               process_crontab("root", fname, tabname,
1698 +                               &statbuf, &new_db, old_db);
1699 +
1700 +       }
1701 +       closedir(dir);
1702 +#endif
1703 +
1704         /* we used to keep this dir open all the time, for the sake of
1705          * efficiency.  however, we need to close it in every fork, and
1706          * we fork a lot more often than the mtime of the dir changes.
1707 @@ -102,7 +221,7 @@
1708  
1709         while (NULL != (dp = readdir(dir))) {
1710                 char    fname[MAXNAMLEN+1],
1711 -                       tabname[MAXNAMLEN+1];
1712 +                       tabname[PATH_MAX+1];
1713  
1714                 /* avoid file names beginning with ".".  this is good
1715                  * because we would otherwise waste two guaranteed calls
1716 @@ -113,7 +232,7 @@
1717                         continue;
1718  
1719                 (void) strcpy(fname, dp->d_name);
1720 -               sprintf(tabname, CRON_TAB(fname));
1721 +               snprintf(tabname, PATH_MAX+1, CRON_TAB(fname));
1722  
1723                 process_crontab(fname, fname, tabname,
1724                                 &statbuf, &new_db, old_db);
1725 @@ -203,10 +322,19 @@
1726         int             crontab_fd = OK - 1;
1727         user            *u;
1728  
1729 +#ifdef DEBIAN
1730 +       /* If the name begins with *system*, don't worry about password -
1731 +        it's part of the system crontab */
1732 +       if (strncmp(fname, "*system*", 8) && !(pw = getpwnam(uname))) {
1733 +#else
1734         if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
1735 +#endif
1736                 /* file doesn't have a user in passwd file.
1737                  */
1738 -               log_it(fname, getpid(), "ORPHAN", "no passwd entry");
1739 +               if (strncmp(fname, "tmp.", 4)) {
1740 +                       /* don't log these temporary files */
1741 +                       log_it(fname, getpid(), "ORPHAN", "no passwd entry");
1742 +               }
1743                 goto next_crontab;
1744         }
1745  
1746 @@ -259,3 +387,35 @@
1747                 close(crontab_fd);
1748         }
1749  }
1750 +
1751 +#ifdef DEBIAN
1752 +
1753 +/* True or false? Is this a valid filename (upper/lower alpha, digits,
1754 + * underscores, and hyphens only?)
1755 + */
1756 +#include <ctype.h>
1757 +/* Same function, better compliance with ISO C */
1758 +static int valid_name (char *filename)
1759 +{
1760 +  while (*filename) {
1761 +    if (!(isalnum(*filename) ||
1762 +         (*filename == '_') ||
1763 +         (*filename == '-')))
1764 +      return 0;
1765 +    ++filename;
1766 +  }
1767 +
1768 +  return 1;
1769 +}
1770 +
1771 +static user *
1772 +get_next_system_crontab (curtab)
1773 +       user    *curtab;
1774 +{
1775 +       for ( ; curtab != NULL; curtab = curtab->next)
1776 +               if (!strncmp(curtab->name, "*system*", 8) && curtab->name [8])
1777 +                       break;
1778 +       return curtab;
1779 +}
1780 +
1781 +#endif
1782 --- cron-3.0pl1.orig/do_command.c
1783 +++ cron-3.0pl1/do_command.c
1784 @@ -21,13 +21,26 @@
1785  
1786  
1787  #include "cron.h"
1788 -#include <sys/signal.h>
1789 +#include <signal.h>
1790 +#include <grp.h>
1791  #if defined(sequent)
1792  # include <sys/universe.h>
1793  #endif
1794  #if defined(SYSLOG)
1795  # include <syslog.h>
1796  #endif
1797 +#if defined(USE_PAM)
1798 +#include <security/pam_appl.h>
1799 +static pam_handle_t *pamh = NULL;
1800 +static const struct pam_conv conv = {
1801 +       NULL
1802 +};
1803 +#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
1804 +       fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
1805 +       syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
1806 +       pam_end(pamh, retcode); exit(1); \
1807 +   }
1808 +#endif
1809  
1810  
1811  static void            child_process __P((entry *, user *)),
1812 @@ -78,6 +91,10 @@
1813         char            *usernm, *mailto;
1814         int             children = 0;
1815  
1816 +#if defined(USE_PAM)
1817 +       int             retcode = 0;
1818 +#endif
1819 +
1820         Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd))
1821  
1822         /* mark ourselves as different to PS command watchers by upshifting
1823 @@ -95,13 +112,32 @@
1824         usernm = env_get("LOGNAME", e->envp);
1825         mailto = env_get("MAILTO", e->envp);
1826  
1827 +       /* Check for arguments */
1828 +       if (mailto) {
1829 +               const char      *end;
1830 +
1831 +               /* These chars have to match those cron_popen()
1832 +                * uses to split the command string */
1833 +               mailto += strspn(mailto, " \t\n");
1834 +               end = mailto + strcspn(mailto, " \t\n");
1835 +               if (*mailto == '-' || *end != '\0') {
1836 +                       printf("Bad Mailto karma.\n");
1837 +                       log_it("CRON",getpid(),"error","bad mailto");
1838 +                       mailto = NULL;
1839 +               }
1840 +       }
1841 +
1842  #ifdef USE_SIGCHLD
1843         /* our parent is watching for our death by catching SIGCHLD.  we
1844          * do not care to watch for our children's deaths this way -- we
1845          * use wait() explictly.  so we have to disable the signal (which
1846          * was inherited from the parent).
1847          */
1848 +#ifdef DEBIAN
1849 +       (void) signal(SIGCHLD, SIG_DFL);
1850 +#else
1851         (void) signal(SIGCHLD, SIG_IGN);
1852 +#endif
1853  #else
1854         /* on system-V systems, we are ignoring SIGCLD.  we have to stop
1855          * ignoring it now or the wait() in cron_pclose() won't work.
1856 @@ -122,13 +158,21 @@
1857          * command, and subsequent characters are the additional input to
1858          * the command.  Subsequent %'s will be transformed into newlines,
1859          * but that happens later.
1860 +        *
1861 +        * If there are escaped %'s, remove the escape character.
1862          */
1863         /*local*/{
1864                 register int escaped = FALSE;
1865                 register int ch;
1866 +               register char *p;
1867  
1868 -               for (input_data = e->cmd;  ch = *input_data;  input_data++) {
1869 +               for (input_data = p = e->cmd; (ch = *input_data);
1870 +                   input_data++, p++) {
1871 +                       if (p != input_data)
1872 +                               *p = ch;
1873                         if (escaped) {
1874 +                               if (ch == '%' || ch == '\\')
1875 +                                       *--p = ch;
1876                                 escaped = FALSE;
1877                                 continue;
1878                         }
1879 @@ -141,8 +185,21 @@
1880                                 break;
1881                         }
1882                 }
1883 +               *p = '\0';
1884         }
1885  
1886 +#if defined(USE_PAM)
1887 +       retcode = pam_start("cron", usernm, &conv, &pamh);
1888 +       PAM_FAIL_CHECK;
1889 +       retcode = pam_acct_mgmt(pamh, PAM_SILENT);
1890 +       PAM_FAIL_CHECK;
1891 +       retcode = pam_open_session(pamh, PAM_SILENT);
1892 +       PAM_FAIL_CHECK;
1893 +       retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT);
1894 +       PAM_FAIL_CHECK;
1895 +
1896 +#endif
1897 +
1898         /* fork again, this time so we can exec the user's command.
1899          */
1900         switch (vfork()) {
1901 @@ -168,9 +225,7 @@
1902  
1903                 /* that's the last thing we'll log.  close the log files.
1904                  */
1905 -#ifdef SYSLOG
1906 -               closelog();
1907 -#endif
1908 +               log_close();
1909  
1910                 /* get new pgrp, void tty, etc.
1911                  */
1912 @@ -188,9 +243,12 @@
1913                 /* grandchild process.  make std{in,out} be the ends of
1914                  * pipes opened by our daddy; make stderr go to stdout.
1915                  */
1916 -               close(STDIN);   dup2(stdin_pipe[READ_PIPE], STDIN);
1917 -               close(STDOUT);  dup2(stdout_pipe[WRITE_PIPE], STDOUT);
1918 -               close(STDERR);  dup2(STDOUT, STDERR);
1919 +               /* Closes are unnecessary -- let dup2() do it */
1920 +
1921 +                 /* close(STDIN) */; dup2(stdin_pipe[READ_PIPE], STDIN);
1922 +                 /* close(STDOUT) */;  dup2(stdout_pipe[WRITE_PIPE], STDOUT);
1923 +                 /* close(STDERR)*/; dup2(STDOUT, STDERR);
1924 +
1925  
1926                 /* close the pipes we just dup'ed.  The resources will remain.
1927                  */
1928 @@ -207,10 +265,16 @@
1929                  * we set uid, we've lost root privledges.
1930                  */
1931                 setgid(e->gid);
1932 -# if defined(BSD)
1933 +# if defined(BSD) || defined(POSIX)
1934                 initgroups(env_get("LOGNAME", e->envp), e->gid);
1935  # endif
1936 -               setuid(e->uid);         /* we aren't root after this... */
1937 +               if (setuid(e->uid) !=0) { /* we aren't root after this... */
1938 +                 char msg[256];
1939 +                 snprintf(msg, 256, "do_command:setuid(%lu) failed: %s",
1940 +                          (unsigned long) e->uid, strerror(errno)); 
1941 +                 log_it("CRON",getpid(),"error",msg);
1942 +                 exit(ERROR_EXIT);
1943 +               }       
1944                 chdir(env_get("HOME", e->envp));
1945  
1946                 /* exec the command.
1947 @@ -227,6 +291,13 @@
1948                                 _exit(OK_EXIT);
1949                         }
1950  # endif /*DEBUGGING*/
1951 +#if 0
1952 +                       {
1953 +                         struct sigaction oact;
1954 +                         sigaction(SIGCHLD, NULL, &oact);
1955 +                       }
1956 +                       fprintf(stdout,"error");
1957 +#endif
1958                         execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);
1959                         fprintf(stderr, "execl: couldn't exec `%s'\n", shell);
1960                         perror("execl");
1961 @@ -281,7 +352,7 @@
1962                  *      %  -> \n
1963                  *      \x -> \x        for all x != %
1964                  */
1965 -               while (ch = *input_data++) {
1966 +               while ((ch = *input_data++) != '\0') {
1967                         if (escaped) {
1968                                 if (ch != '%')
1969                                         putc('\\', out);
1970 @@ -366,9 +437,9 @@
1971                                 auto char       hostname[MAXHOSTNAMELEN];
1972  
1973                                 (void) gethostname(hostname, MAXHOSTNAMELEN);
1974 -                               (void) sprintf(mailcmd, MAILARGS,
1975 -                                              MAILCMD, mailto);
1976 -                               if (!(mail = cron_popen(mailcmd, "w"))) {
1977 +                               (void) snprintf(mailcmd, sizeof(mailcmd),
1978 +                                   MAILARGS, MAILCMD, mailto);
1979 +                               if (!(mail = cron_popen(mailcmd, "w", e))) {
1980                                         perror(MAILCMD);
1981                                         (void) _exit(ERROR_EXIT);
1982                                 }
1983 @@ -379,7 +450,7 @@
1984                                         e->cmd);
1985  # if defined(MAIL_DATE)
1986                                 fprintf(mail, "Date: %s\n",
1987 -                                       arpadate(&TargetTime));
1988 +                                       arpadate(&StartTime));
1989  # endif /* MAIL_DATE */
1990                                 for (env = e->envp;  *env;  env++)
1991                                         fprintf(mail, "X-Cron-Env: <%s>\n",
1992 @@ -425,7 +496,7 @@
1993                         if (mailto && status) {
1994                                 char buf[MAX_TEMPSTR];
1995  
1996 -                               sprintf(buf,
1997 +                               snprintf(buf, MAX_TEMPSTR,
1998                         "mailed %d byte%s of output but got status 0x%04x\n",
1999                                         bytes, (bytes==1)?"":"s",
2000                                         status);
2001 @@ -460,6 +531,11 @@
2002                         Debug(DPROC, (", dumped core"))
2003                 Debug(DPROC, ("\n"))
2004         }
2005 +#if defined(USE_PAM)
2006 +       pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
2007 +       retcode = pam_close_session(pamh, PAM_SILENT);
2008 +       pam_end(pamh, retcode);
2009 +#endif
2010  }
2011  
2012  
2013 --- cron-3.0pl1.orig/entry.c
2014 +++ cron-3.0pl1/entry.c
2015 @@ -91,6 +91,7 @@
2016         int     ch;
2017         char    cmd[MAX_COMMAND];
2018         char    envstr[MAX_ENVSTR];
2019 +       char    **tenvp;
2020  
2021         Debug(DPARS, ("load_entry()...about to eat comments\n"))
2022  
2023 @@ -139,8 +140,9 @@
2024                         bit_set(e->minute, 0);
2025                         bit_set(e->hour, 0);
2026                         bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
2027 +                       e->flags |= DOM_STAR;
2028                         bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
2029 -                       bit_set(e->dow, 0);
2030 +                       bit_nset(e->dow, 0,0);
2031                 } else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
2032                         bit_set(e->minute, 0);
2033                         bit_set(e->hour, 0);
2034 @@ -149,10 +151,11 @@
2035                         bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
2036                 } else if (!strcmp("hourly", cmd)) {
2037                         bit_set(e->minute, 0);
2038 -                       bit_set(e->hour, (LAST_HOUR-FIRST_HOUR+1));
2039 +                       bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
2040                         bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
2041                         bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
2042                         bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
2043 +                       e->flags |= HR_STAR;
2044                 } else {
2045                         ecode = e_timespec;
2046                         goto eof;
2047 @@ -160,6 +163,8 @@
2048         } else {
2049                 Debug(DPARS, ("load_entry()...about to parse numerics\n"))
2050  
2051 +               if (ch == '*')
2052 +                       e->flags |= MIN_STAR;
2053                 ch = get_list(e->minute, FIRST_MINUTE, LAST_MINUTE,
2054                               PPC_NULL, ch, file);
2055                 if (ch == EOF) {
2056 @@ -170,6 +175,8 @@
2057                 /* hours
2058                  */
2059  
2060 +               if (ch == '*')
2061 +                       e->flags |= HR_STAR;
2062                 ch = get_list(e->hour, FIRST_HOUR, LAST_HOUR,
2063                               PPC_NULL, ch, file);
2064                 if (ch == EOF) {
2065 @@ -218,6 +225,9 @@
2066                 bit_set(e->dow, 7);
2067         }
2068  
2069 +       /* If we used one of the @commands, we may be pointing at
2070 +       blanks, and if we don't skip over them, we'll miss the user/command */  
2071 +    Skip_Blanks(ch, file);
2072         /* ch is the first character of a command, or a username */
2073         unget_char(ch, file);
2074  
2075 @@ -239,6 +249,9 @@
2076                         goto eof;
2077                 }
2078                 Debug(DPARS, ("load_entry()...uid %d, gid %d\n",e->uid,e->gid))
2079 +       } else if (ch == '*') {
2080 +               ecode = e_cmd;
2081 +               goto eof;
2082         }
2083  
2084         e->uid = pw->pw_uid;
2085 @@ -247,24 +260,52 @@
2086         /* copy and fix up environment.  some variables are just defaults and
2087          * others are overrides.
2088          */
2089 -       e->envp = env_copy(envp);
2090 +       if ((e->envp = env_copy(envp)) == NULL) {
2091 +               ecode = e_none;
2092 +               goto eof;
2093 +       }
2094         if (!env_get("SHELL", e->envp)) {
2095 -               sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
2096 -               e->envp = env_set(e->envp, envstr);
2097 +               snprintf(envstr, MAX_ENVSTR, "SHELL=%s", _PATH_BSHELL);
2098 +               if ((tenvp = env_set(e->envp, envstr))) {
2099 +                       e->envp = tenvp;
2100 +               } else {
2101 +                       ecode = e_none;
2102 +                       goto eof;
2103 +               }
2104         }
2105         if (!env_get("HOME", e->envp)) {
2106 -               sprintf(envstr, "HOME=%s", pw->pw_dir);
2107 -               e->envp = env_set(e->envp, envstr);
2108 +               snprintf(envstr, MAX_ENVSTR, "HOME=%s", pw->pw_dir);
2109 +               if ((tenvp = env_set(e->envp, envstr))) {
2110 +                       e->envp = tenvp;
2111 +               } else {
2112 +                       ecode = e_none;
2113 +                       goto eof;
2114 +               }
2115         }
2116         if (!env_get("PATH", e->envp)) {
2117 -               sprintf(envstr, "PATH=%s", _PATH_DEFPATH);
2118 -               e->envp = env_set(e->envp, envstr);
2119 +               snprintf(envstr, MAX_ENVSTR, "PATH=%s", _PATH_DEFPATH);
2120 +               if ((tenvp = env_set(e->envp, envstr))) {
2121 +                       e->envp = tenvp;
2122 +               } else {
2123 +                       ecode = e_none;
2124 +                       goto eof;
2125 +               }
2126 +       }
2127 +       snprintf(envstr, MAX_ENVSTR, "%s=%s", "LOGNAME", pw->pw_name);
2128 +       if ((tenvp = env_set(e->envp, envstr))) {
2129 +               e->envp = tenvp;
2130 +       } else {
2131 +               ecode = e_none;
2132 +               goto eof;
2133         }
2134 -       sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
2135 -       e->envp = env_set(e->envp, envstr);
2136  #if defined(BSD)
2137 -       sprintf(envstr, "%s=%s", "USER", pw->pw_name);
2138 -       e->envp = env_set(e->envp, envstr);
2139 +       snprintf(envstr, MAX_ENVSTR, "%s=%s", "USER", pw->pw_name);
2140 +       if ((tenvp = env_set(e->envp, envstr))) {
2141 +               e->envp = tenvp;
2142 +       } else {
2143 +               ecode = e_none;
2144 +               goto eof;
2145 +       }
2146  #endif
2147  
2148         Debug(DPARS, ("load_entry()...about to parse command\n"))
2149 @@ -280,12 +321,16 @@
2150          */
2151         if (ch == EOF) {
2152                 ecode = e_cmd;
2153 +                log_it("CRON",getpid(),"DEBUG","detected early eof");
2154                 goto eof;
2155         }
2156  
2157         /* got the command in the 'cmd' string; save it in *e.
2158          */
2159 -       e->cmd = strdup(cmd);
2160 +       if ((e->cmd = strdup(cmd)) == NULL) {
2161 +               ecode = e_none;
2162 +               goto eof;
2163 +       }
2164  
2165         Debug(DPARS, ("load_entry()...returning successfully\n"))
2166  
2167 @@ -294,6 +339,10 @@
2168         return e;
2169  
2170   eof:
2171 +       if (e->envp)
2172 +               env_free(e->envp);
2173 +       if (e->cmd)
2174 +               free(e->cmd);
2175         free(e);
2176         if (ecode != e_none && error_func)
2177                 (*error_func)(ecodes[(int)ecode]);
2178 --- cron-3.0pl1.orig/env.c
2179 +++ cron-3.0pl1/env.c
2180 @@ -28,7 +28,8 @@
2181  {
2182         register char   **p = (char **) malloc(sizeof(char **));
2183  
2184 -       p[0] = NULL;
2185 +       if (p)
2186 +               p[0] = NULL;
2187         return (p);
2188  }
2189  
2190 @@ -55,8 +56,18 @@
2191         for (count = 0;  envp[count] != NULL;  count++)
2192                 ;
2193         p = (char **) malloc((count+1) * sizeof(char *));  /* 1 for the NULL */
2194 +       if (p == NULL) {
2195 +               errno = ENOMEM;
2196 +               return NULL;
2197 +       }
2198         for (i = 0;  i < count;  i++)
2199 -               p[i] = strdup(envp[i]);
2200 +               if ((p[i] = strdup(envp[i])) == NULL) {
2201 +                       while (--i >= 0)
2202 +                               (void) free(p[i]);
2203 +                       free(p);
2204 +                       errno = ENOMEM;
2205 +                       return NULL;
2206 +               }
2207         p[count] = NULL;
2208         return (p);
2209  }
2210 @@ -87,7 +98,11 @@
2211                  * save our new one there, and return the existing array.
2212                  */
2213                 free(envp[found]);
2214 -               envp[found] = strdup(envstr);
2215 +               if ((envp[found] = strdup(envstr)) == NULL) {
2216 +                       envp[found] = "";
2217 +                       errno = ENOMEM;
2218 +                       return NULL;
2219 +               }
2220                 return (envp);
2221         }
2222  
2223 @@ -98,8 +113,15 @@
2224          */
2225         p = (char **) realloc((void *) envp,
2226                               (unsigned) ((count+1) * sizeof(char **)));
2227 +       if (p == NULL)  {
2228 +               errno = ENOMEM;
2229 +               return NULL;
2230 +       }
2231         p[count] = p[count-1];
2232 -       p[count-1] = strdup(envstr);
2233 +       if ((p[count-1] = strdup(envstr)) == NULL) {
2234 +               errno = ENOMEM;
2235 +               return NULL;
2236 +       }
2237         return (p);
2238  }
2239  
2240 @@ -115,15 +137,17 @@
2241  {
2242         long    filepos;
2243         int     fileline;
2244 -       char    name[MAX_TEMPSTR], val[MAX_ENVSTR];
2245 +       char    name[MAX_ENVSTR], val[MAX_ENVSTR];
2246         int     fields;
2247  
2248         filepos = ftell(f);
2249         fileline = LineNumber;
2250         skip_comments(f);
2251 -       if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
2252 +       if (EOF == get_string(envstr, MAX_ENVSTR - 1, f, "\n"))
2253                 return (ERR);
2254  
2255 +    envstr[MAX_ENVSTR - 1] = '\0';
2256 +
2257         Debug(DPARS, ("load_env, read <%s>\n", envstr))
2258  
2259         name[0] = val[0] = '\0';
2260 @@ -154,6 +178,8 @@
2261                 }
2262         }
2263  
2264 +       if (strlen(name) + 1 + strlen(val) >= MAX_ENVSTR-1)
2265 +               return (FALSE);
2266         (void) sprintf(envstr, "%s=%s", name, val);
2267         Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr))
2268         return (TRUE);
2269 @@ -168,7 +194,7 @@
2270         register int    len = strlen(name);
2271         register char   *p, *q;
2272  
2273 -       while (p = *envp++) {
2274 +       while ((p = *envp++)) {
2275                 if (!(q = strchr(p, '=')))
2276                         continue;
2277                 if ((q - p) == len && !strncmp(p, name, len))
2278 --- cron-3.0pl1.orig/externs.h
2279 +++ cron-3.0pl1/externs.h
2280 @@ -20,6 +20,7 @@
2281  # include <unistd.h>
2282  # include <string.h>
2283  # include <dirent.h>
2284 +# include <errno.h>
2285  # define DIR_T struct dirent
2286  # define WAIT_T        int
2287  # define WAIT_IS_INT 1
2288 --- cron-3.0pl1.orig/job.c
2289 +++ cron-3.0pl1/job.c
2290 @@ -45,7 +45,8 @@
2291                 if (j->e == e && j->u == u) { return; }
2292  
2293         /* build a job queue element */
2294 -       j = (job*)malloc(sizeof(job));
2295 +       if ((j = (job*)malloc(sizeof(job))) == NULL)
2296 +               return;
2297         j->next = (job*) NULL;
2298         j->e = e;
2299         j->u = u;
2300 --- cron-3.0pl1.orig/misc.c
2301 +++ cron-3.0pl1/misc.c
2302 @@ -263,11 +263,11 @@
2303                 char    buf[MAX_TEMPSTR];
2304                 int     fd, otherpid;
2305  
2306 -               (void) sprintf(pidfile, PIDFILE, PIDDIR);
2307 +               (void) snprintf(pidfile, MAX_FNAME, PIDFILE, PIDDIR);
2308                 if ((-1 == (fd = open(pidfile, O_RDWR|O_CREAT, 0644)))
2309                     || (NULL == (fp = fdopen(fd, "r+")))
2310                     ) {
2311 -                       sprintf(buf, "can't open or create %s: %s",
2312 +                       snprintf(buf, MAX_TEMPSTR, "can't open or create %s: %s",
2313                                 pidfile, strerror(errno));
2314                         fprintf(stderr, "%s: %s\n", ProgramName, buf);
2315                         log_it("CRON", getpid(), "DEATH", buf);
2316 @@ -278,13 +278,14 @@
2317                         int save_errno = errno;
2318  
2319                         fscanf(fp, "%d", &otherpid);
2320 -                       sprintf(buf, "can't lock %s, otherpid may be %d: %s",
2321 +                       snprintf(buf, MAX_TEMPSTR, "can't lock %s, otherpid may be %d: %s",
2322                                 pidfile, otherpid, strerror(save_errno));
2323                         fprintf(stderr, "%s: %s\n", ProgramName, buf);
2324                         log_it("CRON", getpid(), "DEATH", buf);
2325                         exit(ERROR_EXIT);
2326                 }
2327 -
2328 +               snprintf(buf, MAX_TEMPSTR, "pidfile fd = %d", fd);
2329 +               log_it("CRON", getpid(), "INFO", buf);
2330                 (void) fcntl(fd, F_SETFD, 1);
2331         }
2332  
2333 @@ -296,6 +297,7 @@
2334         /* abandon fd and fp even though the file is open. we need to
2335          * keep it open and locked, but we don't need the handles elsewhere.
2336          */
2337 +       
2338  }
2339  
2340  /* get_char(file) : like getc() but increment LineNumber on newlines
2341 @@ -308,7 +310,7 @@
2342  
2343         ch = getc(file);
2344         if (ch == '\n')
2345 -               Set_LineNum(LineNumber + 1)
2346 +               Set_LineNum(LineNumber + 1);
2347         return ch;
2348  }
2349  
2350 @@ -322,7 +324,7 @@
2351  {
2352         ungetc(ch, file);
2353         if (ch == '\n')
2354 -               Set_LineNum(LineNumber - 1)
2355 +              Set_LineNum(LineNumber - 1);
2356  }
2357  
2358  
2359 @@ -461,25 +463,26 @@
2360         char    *event;
2361         char    *detail;
2362  {
2363 -       PID_T                   pid = xpid;
2364  #if defined(LOG_FILE)
2365 +       PID_T                   pid = xpid;
2366         char                    *msg;
2367         TIME_T                  now = time((TIME_T) 0);
2368         register struct tm      *t = localtime(&now);
2369 +       int                     msg_size;
2370  #endif /*LOG_FILE*/
2371  
2372 -#if defined(SYSLOG)
2373 -       static int              syslog_open = 0;
2374 -#endif
2375  
2376  #if defined(LOG_FILE)
2377         /* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
2378          */
2379 -       msg = malloc(strlen(username)
2380 -                    + strlen(event)
2381 -                    + strlen(detail)
2382 -                    + MAX_TEMPSTR);
2383 -
2384 +       msg_size = strlen(username) + strlen(event) + strlen(detail) + MAX_TEMPSTR;
2385 +       msg = malloc(msg_size);
2386 +       if (msg == NULL) {
2387 +           /* damn, out of mem and we did not test that before... */
2388 +           fprintf(stderr, "%s: Run OUT OF MEMORY while %s\n",
2389 +                   ProgramName, __FUNCTION__);
2390 +           return;
2391 +       }
2392         if (LogFD < OK) {
2393                 LogFD = open(LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0600);
2394                 if (LogFD < OK) {
2395 @@ -491,16 +494,16 @@
2396                 }
2397         }
2398  
2399 -       /* we have to sprintf() it because fprintf() doesn't always write
2400 +       /* we have to snprintf() it because fprintf() doesn't always write
2401          * everything out in one chunk and this has to be atomically appended
2402          * to the log file.
2403          */
2404 -       sprintf(msg, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
2405 +       snprintf(msg, msg_size, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
2406                 username,
2407                 t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, pid,
2408                 event, detail);
2409  
2410 -       /* we have to run strlen() because sprintf() returns (char*) on old BSD
2411 +       /* we have to run strlen() because snprintf() returns (char*) on old BSD
2412          */
2413         if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) {
2414                 if (LogFD >= OK)
2415 @@ -513,27 +516,30 @@
2416  #endif /*LOG_FILE*/
2417  
2418  #if defined(SYSLOG)
2419 -       if (!syslog_open) {
2420 -               /* we don't use LOG_PID since the pid passed to us by
2421 -                * our client may not be our own.  therefore we want to
2422 -                * print the pid ourselves.
2423 -                */
2424 -# ifdef LOG_DAEMON
2425 -               openlog(ProgramName, LOG_PID, LOG_CRON);
2426 +
2427 +
2428 +           /* we don't use LOG_PID since the pid passed to us by
2429 +            * our client may not be our own.  therefore we want to
2430 +            * print the pid ourselves.
2431 +            */
2432 +           /* SteveG says: That comment is not consistent with the
2433 +              code, and makes no sense -- I suspect it's a remnant
2434 +              of a cut-n-paster... */
2435 +# ifdef LOG_CRON
2436 +       openlog(ProgramName, LOG_PID, LOG_CRON);
2437  # else
2438 -               openlog(ProgramName, LOG_PID);
2439 +       openlog(ProgramName, LOG_PID);
2440  # endif
2441 -               syslog_open = TRUE;             /* assume openlog success */
2442 -       }
2443 -
2444 -       syslog(LOG_INFO, "(%s) %s (%s)\n", username, event, detail);
2445 +         
2446 +       syslog(LOG_INFO, "(%s) %s (%s)", username, event, detail);
2447  
2448 +       closelog();
2449  #endif /*SYSLOG*/
2450  
2451  #if DEBUGGING
2452         if (DebugFlags) {
2453                 fprintf(stderr, "log_it: (%s %d) %s (%s)\n",
2454 -                       username, pid, event, detail);
2455 +                       username, xpid, event, detail);
2456         }
2457  #endif
2458  }
2459 @@ -541,10 +547,15 @@
2460  
2461  void
2462  log_close() {
2463 +#if defined(LOG_FILE)
2464         if (LogFD != ERR) {
2465                 close(LogFD);
2466                 LogFD = ERR;
2467         }
2468 +#endif
2469 +#if defined(SYSLOG)
2470 +       closelog();
2471 +#endif
2472  }
2473  
2474  
2475 @@ -604,8 +615,10 @@
2476                         *dst++ = '^';
2477                         *dst++ = '?';
2478                 } else {                        /* parity character */
2479 -                       sprintf(dst, "\\%03o", ch);
2480 -                       dst += 4;
2481 +                   /* well, the following snprintf is paranoid, but that will
2482 +                    * keep grep happy */
2483 +                   snprintf(dst, 5, "\\%03o", ch);
2484 +                   dst += 4;
2485                 }
2486         }
2487         *dst = '\0';
2488 @@ -622,39 +635,50 @@
2489  {
2490         register char *dst = malloc(len*4 + 1);
2491  
2492 -       mkprint(dst, src, len);
2493 +       if (dst)
2494 +               mkprint(dst, src, len);
2495  
2496         return dst;
2497  }
2498  
2499  
2500  #ifdef MAIL_DATE
2501 -/* Sat, 27 Feb 93 11:44:51 CST
2502 - * 123456789012345678901234567
2503 +/* Sat, 27 Feb 1993 11:44:51 -0800 (CST)
2504 + * 1234567890123456789012345678901234567
2505   */
2506  char *
2507  arpadate(clock)
2508         time_t *clock;
2509  {
2510 -       time_t t = clock ?*clock :time(0L);
2511 +       static char ret[64];    /* zone name might be >3 chars */
2512 +       time_t t = clock ? *clock : time(NULL);
2513         struct tm *tm = localtime(&t);
2514 -       static char ret[30];    /* zone name might be >3 chars */
2515 -       
2516 -       (void) sprintf(ret, "%s, %2d %s %2d %02d:%02d:%02d %s",
2517 -                      DowNames[tm->tm_wday],
2518 -                      tm->tm_mday,
2519 -                      MonthNames[tm->tm_mon],
2520 -                      tm->tm_year,
2521 -                      tm->tm_hour,
2522 -                      tm->tm_min,
2523 -                      tm->tm_sec,
2524 -                      TZONE(*tm));
2525 +       char *qmark;
2526 +       size_t len;
2527 +       int hours = tm->tm_gmtoff / 3600;
2528 +       int minutes = (tm->tm_gmtoff - (hours * 3600)) / 60;
2529 +
2530 +       if (minutes < 0)
2531 +               minutes = -minutes;
2532 +
2533 +       /* Defensive coding (almost) never hurts... */
2534 +       len = strftime(ret, sizeof(ret), "%a, %e %b %Y %T ????? (%Z)", tm);
2535 +       if (len == 0) {
2536 +               ret[0] = '?';
2537 +               ret[1] = '\0';
2538 +               return ret;
2539 +       }
2540 +       qmark = strchr(ret, '?');
2541 +       if (qmark && len - (qmark - ret) >= 6) {
2542 +               snprintf(qmark, 6, "% .2d%.2d", hours, minutes);
2543 +               qmark[5] = ' ';
2544 +       }
2545         return ret;
2546  }
2547  #endif /*MAIL_DATE*/
2548  
2549  
2550 -#ifdef HAVE_SAVED_SUIDS
2551 +#ifdef HAVE_SAVED_UIDS
2552  static int save_euid;
2553  int swap_uids() { save_euid = geteuid(); return seteuid(getuid()); }
2554  int swap_uids_back() { return seteuid(save_euid); }
2555 --- cron-3.0pl1.orig/pathnames.h
2556 +++ cron-3.0pl1/pathnames.h
2557 @@ -19,7 +19,7 @@
2558   * $Id: cron_3.0pl1-72.patch,v 1.1 2004-07-21 08:58:06 hackbard Exp $
2559   */
2560  
2561 -#if (defined(BSD)) && (BSD >= 199103) || defined(__linux) || defined(AIX)
2562 +#if (defined(BSD)) && (BSD >= 199103) || defined(__linux__) || defined(AIX)
2563  # include <paths.h>
2564  #endif /*BSD*/
2565  
2566 @@ -28,7 +28,7 @@
2567                          * to; SPOOL_DIR, ALLOW_FILE, DENY_FILE, and LOG_FILE
2568                          * are all relative to this directory.
2569                          */
2570 -#define CRONDIR                "/var/cron"
2571 +#define CRONDIR                "/var/spool/cron"
2572  #endif
2573  
2574                         /* SPOOLDIR is where the crontabs live.
2575 @@ -39,7 +39,7 @@
2576                          * newer than they were last time around (or which
2577                          * didn't exist last time around...)
2578                          */
2579 -#define SPOOL_DIR      "tabs"
2580 +#define SPOOL_DIR      "crontabs"
2581  
2582                         /* undefining these turns off their features.  note
2583                          * that ALLOW_FILE and DENY_FILE must both be defined
2584 @@ -47,9 +47,14 @@
2585                          * LOG_FILE or SYSLOG is defined, we don't log.  If
2586                          * both are defined, we log both ways.
2587                          */
2588 +#ifdef DEBIAN
2589 +#define        ALLOW_FILE      "/etc/cron.allow"               /*-*/
2590 +#define DENY_FILE      "/etc/cron.deny"                /*-*/
2591 +#else
2592  #define        ALLOW_FILE      "allow"         /*-*/
2593  #define DENY_FILE      "deny"          /*-*/
2594 -#define LOG_FILE       "log"           /*-*/
2595 +#endif
2596 +/* #define LOG_FILE    "log"             -*/
2597  
2598                         /* where should the daemon stick its PID?
2599                          */
2600 @@ -58,15 +63,20 @@
2601  #else
2602  # define PIDDIR "/etc/"
2603  #endif
2604 -#define PIDFILE                "%scron.pid"
2605 +#define PIDFILE                "%scrond.pid"
2606  
2607                         /* 4.3BSD-style crontab */
2608  #define SYSCRONTAB     "/etc/crontab"
2609 -
2610 +#ifdef DEBIAN
2611 +                        /* where package specific crontabs live */ 
2612 +#define SYSCRONDIR      "/etc/cron.d"
2613 +#endif
2614                         /* what editor to use if no EDITOR or VISUAL
2615                          * environment variable specified.
2616                          */
2617 -#if defined(_PATH_VI)
2618 +#if defined(DEBIAN)
2619 +# define EDITOR "/usr/bin/editor"
2620 +#elif defined(_PATH_VI)
2621  # define EDITOR _PATH_VI
2622  #else
2623  # define EDITOR "/usr/ucb/vi"
2624 @@ -78,4 +88,8 @@
2625  
2626  #ifndef _PATH_DEFPATH
2627  # define _PATH_DEFPATH "/usr/bin:/bin"
2628 +#endif
2629 +
2630 +#ifndef _PATH_DEFPATH_ROOT
2631 +# define _PATH_DEFPATH_ROOT "/usr/sbin:/usr/bin:/sbin:/bin"
2632  #endif
2633 --- cron-3.0pl1.orig/popen.c
2634 +++ cron-3.0pl1/popen.c
2635 @@ -29,9 +29,14 @@
2636  #endif /* not lint */
2637  
2638  #include "cron.h"
2639 -#include <sys/signal.h>
2640 +#include <signal.h>
2641 +
2642 +#if defined(BSD) || defined(POSIX)
2643 +#  include <grp.h>
2644 +#endif
2645  
2646  
2647 +#define MAX_ARGS 100
2648  #define WANT_GLOBBING 0
2649  
2650  /*
2651 @@ -43,14 +48,15 @@
2652  static int fds;
2653  
2654  FILE *
2655 -cron_popen(program, type)
2656 +cron_popen(program, type, e)
2657         char *program, *type;
2658 +       entry *e;
2659  {
2660         register char *cp;
2661         FILE *iop;
2662         int argc, pdes[2];
2663         PID_T pid;
2664 -       char *argv[100];
2665 +       char *argv[MAX_ARGS + 1];
2666  #if WANT_GLOBBING
2667         char **pop, *vv[2];
2668         int gargc;
2669 @@ -58,7 +64,7 @@
2670         extern char **glob(), **copyblk();
2671  #endif
2672  
2673 -       if (*type != 'r' && *type != 'w' || type[1])
2674 +       if ((*type != 'r' && *type != 'w') || type[1])
2675                 return(NULL);
2676  
2677         if (!pids) {
2678 @@ -72,9 +78,10 @@
2679                 return(NULL);
2680  
2681         /* break up string into pieces */
2682 -       for (argc = 0, cp = program;; cp = NULL)
2683 +       for (argc = 0, cp = program; argc < MAX_ARGS; cp = NULL)
2684                 if (!(argv[argc++] = strtok(cp, " \t\n")))
2685                         break;
2686 +    argv[MAX_ARGS] = NULL;
2687  
2688  #if WANT_GLOBBING
2689         /* glob each piece */
2690 @@ -114,6 +121,20 @@
2691                         }
2692                         (void)close(pdes[1]);
2693                 }
2694 +               /* Lose root privilege */
2695 +               setgid(e->gid);
2696 +# if defined(BSD) || defined(POSIX)
2697 +               initgroups(env_get("LOGNAME", e->envp), e->gid);
2698 +# endif
2699 +               if (setuid(e->uid) !=0) {
2700 +                 char msg[256];
2701 +                 snprintf(msg, 256, "popen: setuid(%lu) failed: %s",
2702 +                          (unsigned long) e->uid, strerror(errno)); 
2703 +                 log_it("CRON",getpid(),"error",msg);
2704 +                 exit(ERROR_EXIT);
2705 +               }       
2706 +               chdir(env_get("HOME", e->envp));
2707 +
2708  #if WANT_GLOBBING
2709                 execvp(gargv[0], gargv);
2710  #else
2711 --- cron-3.0pl1.orig/user.c
2712 +++ cron-3.0pl1/user.c
2713 @@ -52,7 +52,7 @@
2714         user    *u;
2715         entry   *e;
2716         int     status;
2717 -       char    **envp;
2718 +       char    **envp, **tenvp;
2719  
2720         if (!(file = fdopen(crontab_fd, "r"))) {
2721                 perror("fdopen on crontab_fd in load_user");
2722 @@ -63,14 +63,25 @@
2723  
2724         /* file is open.  build user entry, then read the crontab file.
2725          */
2726 -       u = (user *) malloc(sizeof(user));
2727 -       u->name = strdup(name);
2728 +       if ((u = (user *) malloc(sizeof(user))) == NULL) {
2729 +               errno = ENOMEM;
2730 +               return NULL;
2731 +       }
2732 +       if ((u->name = strdup(name)) == NULL) {
2733 +               free(u);
2734 +               errno = ENOMEM;
2735 +               return NULL;
2736 +       }
2737         u->crontab = NULL;
2738  
2739         /* 
2740          * init environment.  this will be copied/augmented for each entry.
2741          */
2742 -       envp = env_init();
2743 +       if ((envp = env_init()) == NULL) {
2744 +               free(u->name);
2745 +               free(u);
2746 +               return NULL;
2747 +       }
2748  
2749         /*
2750          * load the crontab
2751 @@ -89,7 +100,13 @@
2752                         }
2753                         break;
2754                 case TRUE:
2755 -                       envp = env_set(envp, envstr);
2756 +                       if ((tenvp = env_set(envp, envstr))) {
2757 +                               envp = tenvp;
2758 +                       } else {
2759 +                               free_user(u);
2760 +                               u = NULL;
2761 +                               goto done;
2762 +                       }
2763                         break;
2764                 }
2765         }
2766 --- cron-3.0pl1.orig/debian/README.anacron
2767 +++ cron-3.0pl1/debian/README.anacron
2768 @@ -0,0 +1,14 @@
2769 +To ease coordination with anacron, the invocation of the run-parts for
2770 +the /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly directories
2771 +was changed to the form
2772 +
2773 +         test -e /usr/sbin/anacron || run-parts --report /etc/cron.daily
2774 +
2775 +What this means is that if anacron has been installed, it will
2776 +be responsible for running those scripts. This is the standard
2777 +configuration of anacron: if you simply install both cron and anacron,
2778 +things will work as expected.
2779 +
2780 +However, if you have modified your anacron configuration
2781 +(/etc/anacrontab), you may need to re-adjust it in order to accommodate
2782 +this change.
2783 --- cron-3.0pl1.orig/debian/README.debian
2784 +++ cron-3.0pl1/debian/README.debian
2785 @@ -0,0 +1,38 @@
2786 +cron for DEBIAN
2787 +----------------------
2788 +
2789 +This is the Debian GNU/Linux prepackaged version of Paul Vixie's cron
2790 +subsystem.
2791 +
2792 +This package was put together by Ian Jackson <iwj10@cus.cam.ac.uk>,
2793 +from the standard sources to 3.0pl1, as posted to comp.sources.unix.
2794 +Ian obtained them from
2795 +src.doc.ic.ac.uk:/usenet/comp.sources.unix/volume27/vixie-cron.
2796 +
2797 +The changes are essentially the configuration for Debian Linux in the
2798 +Makefile and pathnames.h, and the addition of support for the Debian
2799 +package maintenance scheme in the form of various files (now in the
2800 +debian directory).
2801 +
2802 +The `checksecurity' script installed in /usr/sbin in the binary distribution
2803 +(found in ./debian in the source) was (probably) written by Ian Jackson,
2804 +and has been modified by Steve Greenland.
2805 +
2806 +File locations that are different than that indicated in 
2807 +the cron distributions README:
2808 +
2809 +user crontabs: /var/spool/cron/crontabs/*
2810 +log file:      /var/log/cron.log
2811 +allow file:    /etc/cron.allow
2812 +deny file:     /etc/cron.deny
2813 +
2814 +Note that the location of the log file can be changed via syslog.conf.
2815 +
2816 +1998: Added reading of crontab fragments from /etc/cron.d to support
2817 +other Debian package cron requirements. Files follow /etc/crontab
2818 +format (i.e. with user field), must meet run-parts(8) naming
2819 +convention (alphanumeric, underscore, hyphen only).
2820 +
2821 +This package is now maintained by Steve Greenland
2822 +<stevegr@master.debian.org>.
2823 +
2824 --- cron-3.0pl1.orig/debian/changelog
2825 +++ cron-3.0pl1/debian/changelog
2826 @@ -0,0 +1,427 @@
2827 +cron (3.0pl1-72) unstable; urgency=low
2828 +
2829 +  * Add type usbdevfs to skipped "file systems" (this is /proc/bus/usb)
2830 +    (closes: #113186,#113187)
2831 +  * Removed 'xfs' from list of skipped file system types. Unfortunately,
2832 +    it appears to be used by both the arla network file system and the SGI
2833 +    XFS filesystem, and I must make the conservative choice. (closes: #113234)
2834 +  * Remove extra diff in checksecurity. (closes: 113950)
2835 +  * Add type none to skipped "file systems" (--bind mounts) (closes: #111395)
2836 +
2837 + -- Steve Greenland <stevegr@debian.org>  Mon,  1 Oct 2001 07:46:34 -0500
2838 +
2839 +cron (3.0pl1-71) unstable; urgency=medium
2840 +
2841 +  * Fixed nasty typo in checksecurity. (closes: #112156)
2842 +  * Note to release manager: either -71 should go into woody,
2843 +  or only -69.
2844 +
2845 + -- Steve Greenland <stevegr@debian.org>  Thu, 13 Sep 2001 16:39:25 -0500
2846 +
2847 +cron (3.0pl1-70) unstable; urgency=medium
2848 +
2849 +  * Catch full disk when writing new crontab. (closes: #110612)
2850 +  * Don't modify backup file modes if no change (to prevent misleading
2851 +    time mods). (closes: #104093)
2852 +  * Remove obsolete reference to /bin/mail in crontab.5.  (closes: #110962)
2853 +  * Add Marc Merlin's checksecurity patches with more configuration
2854 +    options. (closes: #89547, #63445)
2855 +  * Make all setuid.{today,yesterday,etc.} files group adm. (closes: #109520)
2856 +
2857 + -- Steve Greenland <stevegr@debian.org>  Fri,  7 Sep 2001 18:27:37 -0500
2858 +
2859 +cron (3.0pl1-69) unstable; urgency=low
2860 +
2861 +  * Don't run checksecurity on any partition mount nosuid or noexec.
2862 +  (closes:#98160)
2863 +  * Don't run on devpts, either.
2864 +  
2865 + -- Steve Greenland <stevegr@debian.org>  Sun, 20 May 2001 13:48:15 -0500
2866 +
2867 +cron (3.0pl1-68) unstable; urgency=low
2868 +
2869 +  * Finally tracked down the problem with @{reboot,hourly,etc.} commands
2870 +  in the root crontabs (/etc/crontab, /etc/cron.d/*) (closes:#62141, #84727)
2871 +  * Minor cosmetic cleanup in lost+found output, from Matthijs Melchior 
2872 +  (closes:#88861)
2873 +
2874 + -- Steve Greenland <stevegr@debian.org>  Sat, 19 May 2001 17:37:52 -0500
2875 +
2876 +cron (3.0pl1-67) unstable; urgency=high
2877 +
2878 +  * With crontab -e, don't give uid root on re-edit.
2879 +
2880 + -- Steve Greenland <stevegr@debian.org>  Sun,  6 May 2001 11:41:50 -0500
2881 +
2882 +cron (3.0pl1-66) unstable; urgency=low
2883 +
2884 +  * The "Julian Gilbey has been spending too much time proofreading"
2885 +  release. Remove hyphens in cron.init (closes:#91323)
2886 +  * change log_it() to open and close syslog every time, remove SIGPIPE
2887 +  catcher, etc., all in attempt to keep PAM happy.
2888 +  * Added original location to copyright file (closes:#88507)
2889 +  * Allocate username dynamically in crontab.c (closes:#89040,#62268)
2890 +  * Remove pam_limits.so from cron.pam file.
2891 +
2892 + -- Steve Greenland <stevegr@debian.org>  Tue, 27 Mar 2001 18:04:16 -0600
2893 +
2894 +cron (3.0pl1-65) unstable; urgency=high
2895 +
2896 +  * Close reboot file /var/run/crond.reboot after creating it, duh. Leaving
2897 +  it open allowed possible writes from cron jobs.
2898 +
2899 + -- Steve Greenland <stevegr@debian.org>  Mon, 26 Feb 2001 09:47:34 -0600
2900 +
2901 +cron (3.0pl1-64) unstable; urgency=high
2902 +  * The "President's Birthday" release.
2903 +  * Add checks for setuid() failures, to avoid running user jobs as root.
2904 +  (closes:#85609, #86775) 
2905 +  * Add portability flag -P to df (in /etc/cron.daily/standard) to 
2906 +  avoid problem with long device names. (closes:#86851)
2907 +  * Convert from suidmanager to dpkg --statoverride.
2908 +  * Remove unnecessary dependency on bsdutils (it's Essential)
2909 +  * Change compat.h to not cause inclusion of sys/time.h (instead of 
2910 +  time.h), due to recent change in glibc. Why it was doing this, I have
2911 +  no idea.
2912 +
2913 + -- Steve Greenland <stevegr@debian.org>  Wed, 21 Feb 2001 16:26:57 -0600
2914 +
2915 +cron (3.0pl1-63) unstable; urgency=medium
2916 +
2917 +  * Fix mistaken diagnostic in crontab ("Reached end of file 
2918 +  while reading environment").
2919 +  * Fix "Too many arguments to [" error in postinst. (closes:#79725)
2920 +
2921 + -- Steve Greenland <stevegr@debian.org>  Sun, 28 Jan 2001 12:00:55 -0600
2922 +
2923 +cron (3.0pl1-62) unstable; urgency=medium
2924 +
2925 +  * Change tracking of crontab directory mod times to deal with directories
2926 +  with mtimes in the future. Thanks to Florian Lohoff for tracking down
2927 +  the cause of this rare yet long-standing bug. 
2928 +  (closes:#51202, #57356, #64198, #77353)
2929 +  * Run @reboot jobs only on reboot instead of cron restart. 
2930 +  (closes:#74762, #77563)
2931 +  * Clarify which directory the lost+found files are in.
2932 +  * Protect against reading other people's crontabs via temp file symlink
2933 +  in crontab -e.
2934 +
2935 + -- Steve Greenland <stevegr@debian.org>  Sat, 27 Jan 2001 17:01:43 -0600
2936 +
2937 +cron (3.0pl1-61) unstable; urgency=high
2938 +
2939 +  * Fix usage message in cron.init.
2940 +  * Use pam only on non-Hurd. (closes:#75408)
2941 +  * Move dpkg status backups to /var/backups.
2942 +  * Apply security fix for temp file attack, thanks to Daniel Jacobowitz.
2943 +  * Made /etc/pam.d/cron a conffile.
2944 +
2945 + -- Steve Greenland <stevegr@debian.org>  Fri, 17 Nov 2000 16:06:03 -0600
2946 +
2947 +cron (3.0pl1-60) unstable; urgency=low
2948 +
2949 +  * Re-set log to LOG_CRON after PAM changes it to LOG_AUTH.(closes:#70028)
2950 +
2951 + -- Steve Greenland <stevegr@debian.org>  Thu, 31 Aug 2000 14:37:44 -0500
2952 +
2953 +cron (3.0pl1-59) unstable; urgency=low
2954 +
2955 +  * Fixed typo of @cmp in standard.daily (closes:#69921,#69937,#69956)
2956 +  * Add /etc/pam.d/cron, using standard Unix authorizations (closes:#69939)
2957 +
2958 + -- Steve Greenland <stevegr@debian.org>  Fri, 25 Aug 2000 14:02:47 -0500
2959 +
2960 +cron (3.0pl1-58) unstable; urgency=low
2961 +
2962 +  * Fix use of PATH_MAX/MAXPATHLEN in database.c and other HURD issues
2963 +    (closes:#64382) 
2964 +  * Look in all (ext2) lost+found directories, not just
2965 +    /lost+found (closes:#66629)
2966 +  * Cosmetic changes to daily/standard (closes:#65078)
2967 +  * Use diff -u0 in checksecurity to avoid useless context (closes:#60919)
2968 +  * Note uppercasing of child processes in cron.8 (closes:#62103)
2969 +  * Added Topi Mitterands PAM support patch - Thanks! (closes:#68366,#67586)
2970 +  * Fix segfault in crontab -l (closes:#53735)
2971 +  * Added Build-Depends.
2972 +  * Added support for DEB_BUILD_OPTIONS, changed default compile to '-02 -Wall'
2973 +  * Fixed various complaints generated by -Wall :-), except 'rcsid unused'
2974 +
2975 + -- Steve Greenland <stevegr@debian.org>  Wed, 23 Aug 2000 16:20:39 -0500
2976 +
2977 +cron (3.0pl1-57) frozen unstable; urgency=low
2978 +
2979 +  * Release Manager: 61296 is RC bug;
2980 +  * Change lockfile-progs "Depends" to "Suggests" (policy violation),
2981 +  only try to use lockfile-create in /etc/cron.daily/standard if it is
2982 +  installed (closes:#61296)
2983 +
2984 + -- Steve Greenland <stevegr@debian.org>  Wed, 29 Mar 2000 20:12:06 -0600
2985 +
2986 +cron (3.0pl1-56) frozen unstable; urgency=medium
2987 +
2988 +  * Release Manager: 59115 is RC bug.
2989 +  * set backup password files to root-only rw (closes:#59115)
2990 +  * Fixed missing ntfs in checksecurity.conf (closes:#56939)
2991 +
2992 + -- Steve Greenland <stevegr@debian.org>  Mon, 28 Feb 2000 19:16:20 -0600
2993 +
2994 +cron (3.0pl1-55) unstable; urgency=low
2995 +
2996 +  * Changed __linux feature checks to __linux__ (closes:#50240)
2997 +  * Added '-u' to diff in checksecurity (closes:#51679)
2998 +  * Moved checksecurity LOGDIR (formerly LOG) setting to config 
2999 +  file (closes:#49683)
3000 +  * Fixed removal of lockfile in cron.daily/standard.
3001 +
3002 + -- Steve Greenland <stevegr@debian.org>  Sat, 18 Dec 1999 18:53:29 -0600
3003 +
3004 +cron (3.0pl1-54) unstable; urgency=low
3005 +
3006 +  * Fixed spelling in checksecurity.8 (closes:#45281)
3007 +  * Only look in /lost+found if it exists (closes:#46389)
3008 +  * Only run @weekly jobs once a week (was looking at dom with OR
3009 +  rather than AND.) (closes:#49437)
3010 +  * Don't run more than one instance of /etc/cron.daily/standard (closes:#45487)
3011 +  * Removed extra generation of TSTP in crontab -e. (closes:#48542)
3012 +
3013 + -- Steve Greenland <stevegr@debian.org>  Sun,  7 Nov 1999 15:09:48 -0600
3014 +
3015 +cron (3.0pl1-53) unstable; urgency=medium
3016 +
3017 +  * Applied OpenBSD patches supplied Topi Miettinen. Big change is
3018 +  better handling of timekeeping (in particular, changes to/from daylight
3019 +  savings time) (closes:#8499).
3020 +  * Redirect stdin, stdout, and stderr to /dev/null.
3021 +  (closes:#37189, #23231, #30653).
3022 +  * Fixed bit_set()/bit_nset() confusion that caused @hourly to not work, so
3023 +  that functionality is now documented (closes:#43282).
3024 +  * Changed warrantee to warranty in debian/copyright (but it's still 
3025 +  misspelled in the source files) (closes:#40312)
3026 +  * Adjust checksecurity and cron_daily/standard to get consistent owner/perms
3027 +  on /var/log/setuid* files. (closes:#15295)
3028 +  * Add 'coda' to the list of nfs/afs like file systems in checksecurity.conf
3029 +  (closes:#29909)
3030 +  * Fix version comparison to use dpkg --compare-versions, which is what I
3031 +  should have done in the first place (closes:#42454)
3032 +  * Add 'xfs' to the list of nfs/afs like file systems in checksecurity.conf,
3033 +  as it appears that xfs==arla and arla==xfs. If there are other file systems
3034 +  that show up as 'xfs', please let me know (closes:#37523)
3035 +  * Don't rotate wtmp and btmp (closes:#42301).
3036 +
3037 + -- Steve Greenland <stevegr@debian.org>  Sat, 11 Sep 1999 18:42:37 -0500
3038 +
3039 +cron (3.0pl1-52) unstable; urgency=high
3040 +
3041 +  * Patch to fix "Reverse DoS": user could send arbitrary options to 
3042 +  sendmail via MAILTO variable. Fix by not allowing spaces or leading
3043 +  dashes in MAILTO, and run sendmail as user, not root.
3044 +
3045 + -- Steve Greenland <stevegr@debian.org>  Sun, 29 Aug 1999 21:50:28 -0500
3046 +
3047 +cron (3.0pl1-51) unstable; urgency=low
3048 +
3049 +  * Changed default of "crontab -l" to NOT list the extra header lines. May
3050 +  obtain original behaviour by setting "CRONTAB_NOHEADER=N".
3051 +  * Fixed comment in misc.c that accidentally cause the SIGPIPE handler to
3052 +  be reset more often than necessary.
3053 +  * Don't checksecurity on ntfs file systems (closes:#33079)
3054 +  * Added '-i' flag to sendmail command (closes:#36338)
3055 +  * Added check for files in /lost+found (closes:#29791)
3056 +  * Added preferential invocation of anacron for cron.{daily,weekly,monthly}
3057 +
3058 + -- Steve Greenland <stevegr@master.debian.org>  Thu, 27 May 1999 17:37:54 -0500
3059 +
3060 +cron (3.0pl1-50) frozen unstable; urgency=low
3061 +
3062 +  * Fixed rules file *again* so that crontab suidness doesn't get
3063 +    stepped on by debhelper under certain kernel versions.
3064 +
3065 + -- Steve Greenland <stevegr@debian.org>  Sat,  9 Jan 1999 14:17:09 -0600
3066 +
3067 +cron (3.0pl1-49) frozen unstable; urgency=low
3068 +
3069 +  * Check for /etc/shadow and /etc/gshadow separately (closes:Bug#30232)
3070 +
3071 + -- Steve Greenland <stevegr@master.debian.org>  Wed,  2 Dec 1998 21:30:00 -0600
3072 +
3073 +cron (3.0pl1-48) frozen unstable; urgency=low
3074 +
3075 +  * Fixed rules file so that crontab doesn't get suid bit removed by latest
3076 +  version of debhelper. (closes:Bug#29683)
3077 +
3078 + -- Steve Greenland <stevegr@master.debian.org>  Mon, 30 Nov 1998 21:10:00 -0600
3079 +
3080 +cron (3.0pl1-47) frozen unstable; urgency=high
3081 +
3082 +  * Removed close of {stdin,stdout,stderr}, as it appears that
3083 +  some cron users expect it.
3084 +
3085 + -- Steve Greenland <stevegr@master.debian.org>  Mon,  2 Nov 1998 09:25:44 -0600
3086 +
3087 +Cron (3.0pl1-46) frozen unstable; urgency=medium
3088 +
3089 +  * changed mention of /var/spool/crontabs to /var/spool/cron/crontabs, and
3090 +  added example /etc/crontab. (closes:Bug#28458,Bug#23101)
3091 +  * Incorporated buffer overflow patches. (closes:Bug#26705,Bug#26749) 
3092 +  * Added backup of /etc/shadow and /etc/gshadow in cron.daily/standard.
3093 +  (closes:Bug#25853)
3094 +  * Better daemonization (close stdin,stdout,stderr). (closes:Bug#23231)
3095 +  * Do cron.daily a little earlier, try to avoid overlap with cron.weekly.
3096 +  (closes:Bug#23023)
3097 +  * Added note in crontab.1 and crontab.5 about trailing newline requirement.
3098 +  (closes:Bug#16132)
3099 +
3100 + -- Steve Greenland <stevegr@master.debian.org>  Sun,  1 Nov 1998 19:10:45 -0600
3101 +
3102 +cron (3.0pl1-45) frozen unstable; urgency=high
3103 +
3104 +  * Updated README and README.Debian w.r.t. file locations.
3105 +  * Updated crontab.1 w.r.t. location of allow and deny files.
3106 +  * Fixed problem in postinst when new install (instead of upgrade) 
3107 +  (closes:Bug#21426)
3108 +  * Smarter algorithm for checking /etc/cron.d for changes, no longer
3109 +  spins up laptop disks every minute. Thanks to Alexander "Shurik" 
3110 +  Shumakovitch for the fix.
3111 +  * Re-did checksecurity to only report NFS/AFS insecure mounts
3112 +  instead of running find on them (suggestion from Gregory Stark).
3113 +
3114 + -- Steve Greenland <stevegr@master.debian.org>  Sun, 26 Apr 1998 13:41:51 -0500
3115 +
3116 +cron (3.0pl1-44) unstable; urgency=low
3117 +
3118 +  * Fixed standards version reference.
3119 +  * Fixed init script "comment", sigh. Let this be a warning to you: NEVER EVER
3120 +  change a file with doing a complete test, even if it is "just a comment".
3121 +  (closes:Bug#19466,Bug#19492,Bug#19479,Bug#19595,Bug#19725,Bug#19840,
3122 +  Bug#19845,Bug19852). Sheesh. 
3123 +
3124 + -- Steve Greenland <stevegr@master.debian.org>  Tue, 17 Mar 1998 21:55:03 -0600
3125 +
3126 +cron (3.0pl1-43) unstable; urgency=medium
3127 +
3128 +  * Removed support for TMPDIR. This is due to the problem it causes
3129 +    with emacs -- emacs does different things with it's backup files
3130 +    depending on whether or not the file is in /tmp. Emacs probably ought
3131 +    to use TMPDIR instead of /tmp in its check. I've opened a "wishlist"
3132 +    bug for crontab to support TMPDIR. 
3133 +    (closes: Bug#15985)
3134 +  * When USE_SIGCHLD is defined, before running user process, set handling 
3135 +    for SIGCHLD to SIG_DFL, not SIG_IGN. Despite documentation that the
3136 +    default for SIGCHLD is ignore, the behaviour is different.
3137 +    (closes:Bug#17564,Bug#9075,Bug#16436,Bug#17814)
3138 +  * Moved allow and deny files from /var/spool/cron to /etc/cron.{allow,deny}
3139 +    (closes:Bug#14970)
3140 +  * filenames in /etc/cron.d must comply with run-parts naming convention -
3141 +    alpha-numeric, underscore, or hyphen. This ensures that conffile
3142 +    remains (e.g. package.dpkg-dist) files don't get run.
3143 +  * removed cronanacron command from /etc/crontab and distribution -- 
3144 +    replaced by /etc/cron.d/anacron file (from anacron package, not cron).
3145 +  * Documented /etc/cron.d dir in manpage and readme.debian
3146 +  * modified checksecurity.conf to not check auto file systems. 
3147 +    (closes:Bug#8702)
3148 +  * crontab -u `whoami` now works. (closes:Bug#8702)
3149 +  * documented CRONTAB_NOHEADER in crontab.1
3150 +  * /etc/crontab now uses run-parts(8) --report switch. (closes:Bug#18273)
3151 +  * fixed initialization of oact in misc.c. (closes:Bug#17134)
3152 +  * converted to use debhelper rather than debmake.
3153 +  * changed date format in checksecurity so that we don't get false positives
3154 +    after six months. (closes:Bug#19025)
3155 +  * remove /etc/cron.{allow,deny} on purge
3156 +
3157 + -- Steve Greenland <stevegr@master.debian.org>  Mon,  9 Mar 1998 01:31:13 -0600
3158 +
3159 +cron (3.0pl1-42) unstable; urgency=low
3160 +
3161 +  * Don't output header on 'crontab -l' if CRONTAB_NOHEADER is 'Y' (Bug#15642)
3162 +  * Read files in /etc/cron.d in addition to /etc/crontab (Bug#16628, 
3163 +  Bug#16617)
3164 +
3165 + -- Steve Greenland <stevegr@master.debian.org>  Sun, 11 Jan 1998 18:32:26 -0600
3166 +
3167 +cron (3.0pl1-41) unstable; urgency=low
3168 +
3169 +  * Updated crontab to use /usr/bin/editor if EDITOR and VISUAL undefined.
3170 +  * Added support for TMPDIR from crontab (Bug#9309)
3171 +  * Compress /usr/doc/cron/changelog.Debian -- this time for sure! (Bug#15296)
3172 +
3173 + -- Steve Greenland <stevegr@master.debian.org>  Fri, 28 Nov 1997 13:47:03 -0600
3174 +
3175 +cron (3.0pl1-40) unstable; urgency=low
3176 +
3177 +  * Correct directory reference in standard.monthly to /var/log 
3178 +  (Bug#12315, Bug#13466)
3179 +  * Added -DUSE_SIGCHLD to defs, needed for alpha (Bug#12855,Bug#8611). 
3180 +  May also fix Bug#9075.
3181 +  * Changed check for suidmanager (Bug#9326)
3182 +  * Checksecurity no longer checks fat or vfat filesystems (Bug#8845, 
3183 +  Bug#13574)
3184 +  * Changed spaces in crontab to <TAB>, appearance only (Bug#13369)
3185 +  * Removed bashism from standard.daily and checksecurity (Bug#9908,
3186 +  Bug#9909)
3187 +  * Added CHECKSECURITY_DISABLE flag to checksecurity.conf.
3188 +  * Get the changelog names correct (Bug#14618)
3189 +  * Correct day-of-month and month ranges in crontab.5 (Bug#15073)
3190 +
3191 + -- Steve Greenland <stevegr@master.debian.org>  Sun, 23 Nov 1997 22:58:05 -0600
3192 +
3193 +cron (3.0pl1-39) unstable; urgency=low
3194 +
3195 +  * Added configuration variable to eliminate error messages from
3196 +    checksecurity's find command 
3197 +  * Better integration with anacron: suggest anacron, call anacron
3198 +    on a regular basis so that it can keeps it's status up-to-date. New
3199 +    file /usr/sbin/cronanacron.
3200 +  * Call savelog for /var/adm/btmp from /etc/cron.monthly/standard.
3201 +       
3202 + -- Steve Greenland <stevegr@master.debian.org>  Sun, 24 Aug 1997 18:52:55 -0500
3203 +
3204 +cron (3.0pl1-38) stable unstable; urgency=low
3205 +
3206 +  * When upgrading from -36 or -36.1, stop old cron daemon
3207 +  in preinst, because the prerm's in those versions doesn't.
3208 +  * Follow console message standard.
3209 +
3210 + -- Steve Greenland <stevegr@master.debian.org>  Sat, 18 Jan 1997 15:34:42 -0600
3211 +
3212 +cron (3.0pl1-37) stable unstable; urgency=medium
3213 +
3214 +  * Corrected postinst,prerm, and postrm scripts -- Installs and
3215 +  removes rc.d links, and re-starts cron after install.
3216 +  * More fixes from the BSD crew, sent to me by Marek Michalkiewicz: mostly
3217 +  checks for null pointers, but also a few Makefile fixes, and at least
3218 +  one potential buffer overrun (but I know of no exploits).
3219 +  * Left in suidmanager stuff, but corrected default permission to 4755,
3220 +  per Debian standards.
3221 +  * Added CHANGES file (as /usr/doc/cron/changelog.upstream.gz) to
3222 +  distribution. Added upstream README to distribution.
3223 +  * Moved files out of ./debian/extra into ./debian because dpkg-source
3224 +  cannot deal with createing directories. Hmmph.
3225 +  * Removed filereaper reference from standard.daily
3226 +
3227 + -- Steve Greenland <stevegr@master.debian.org>  Sun, 5 Jan 1997 18:23:14 -0600
3228 +
3229 +cron (3.0pl1-36.1) stable unstable; urgency=HIGH
3230 +
3231 +  * Mended `find' invocation in debian/rules.
3232 +  * Serious security hole (buffer overrun) fixed.
3233 +  * Silly suidmanager stuff added by debmake.  Pah. 
3234 +
3235 + -- Jon Rabone <jkr@master.debian.org>  Wed, 18 Dec 1996 21:38:33 +0000
3236 +
3237 +cron (3.0pl1-36) frozen unstable; urgency=low
3238 +
3239 +  * Removed DEBUG logging about SIGPIPE -- it's generated by every
3240 +  child once syslogd has been restarted.
3241 +
3242 + -- Steve Greenland <stevegr@master.debian.org>  Mon, 2 Dec 1996 01:41:16 -0600
3243 +
3244 +cron (3.0pl1-35) frozen unstable; urgency=low
3245 +
3246 +  * Converted to new source format
3247 +  * Added code in misc.c to catch SIGPIPE and re-open syslog. This
3248 +  is all in #if defined(DEBIAN), and should be removed when syslog(3)
3249 +  is fixed. Also added -DDEBIAN to build commands in Makefile.
3250 +
3251 + -- Steve Greenland <steveg@neuromancer.dmccorp.com>  Sun, 1 Dec 1996 16:21:52 -0600
3252 +
3253 +
3254 --- cron-3.0pl1.orig/debian/checksecurity
3255 +++ cron-3.0pl1/debian/checksecurity
3256 @@ -0,0 +1,87 @@
3257 +#!/bin/sh
3258 +# Security checks script - run daily out of the system crontab
3259 +
3260 +set -e
3261 +
3262 +PATH=/sbin:/bin:/usr/sbin:/usr/bin
3263 +
3264 +
3265 +umask 027
3266 +cd /
3267 +
3268 +. /etc/checksecurity.conf
3269 +
3270 +if [ "$CHECKSECURITY_DISABLE" = "TRUE" ] ; then
3271 +    exit
3272 +fi
3273 +
3274 +if [ -z "$CHECKSECURITY_GREPOUT" ]; then
3275 +    CHECKSECURITY_GREPOUT="$^"
3276 +fi
3277 +
3278 +TMPSETUID=${LOGDIR:=/var/log}/setuid.new.tmp
3279 +TMPDIFF=${LOGDIR:=/var/log}/setuid.diff.tmp
3280 +
3281 +#
3282 +# Check for NFS/AFS mounts that are not nosuid/nodev
3283 +#
3284 +if [ ! "$CHECKSECURITY_NONFSAFS" = "TRUE" ] ; then
3285 +   # temporarily disable error exit, as grep may give errors if no nfs/afs
3286 +   # are mounted.
3287 +   set +e
3288 +   nfssys=`mount | grep -E 'nfs|afs' | grep -vE '\(.*(nosuid|noexec).*nodev.*\)'`
3289 +   nfssyscnt=`echo $nfssys |grep "[a-z]"| wc -l`
3290 +   set -e
3291 +   if [ $nfssyscnt -gt 0 ] ; then
3292 +      echo "The following NFS or AFS filesystems are mounted insecurely:"
3293 +      echo ""
3294 +      echo $nfssys
3295 +      echo ""
3296 +      echo "If this is intentional and you have supreme confidence in the"
3297 +      echo "security of the server for these file systems, you may disable"
3298 +      echo "this message by editing the value of CHECKSECURITY_NONFSAFS in"
3299 +      echo "the file /etc/checksecurity.conf."
3300 +   fi
3301 +fi
3302 +
3303 +if [ "$CHECKSECURITY_NOFINDERRORS" = "TRUE" ] ; then
3304 +       exec 9>&2
3305 +       exec 2>/dev/null
3306 +fi
3307 +
3308 +
3309 +# This is the only way to pass '*' through a variable (NODEVDIRS)  -- Marc
3310 +set -o noglob
3311 +find `mount | grep -vE "$CHECKSECURITY_FILTER" | cut -d ' ' -f 3` \
3312 +    -xdev \(  $CHECKSECURITY_PATHFILTER \) -prune -o \
3313 +    \( -type f -perm +06000 -o \
3314 +    \( \( -type b -o -type c \) -a -not \( $CHECKSECURITY_DEVICEFILTER \) \) \) \
3315 +    -printf "%8i %5m %3n %-10u %-10g %9s %t %h/%f\n" | sort >$TMPSETUID
3316 +set +o noglob
3317 +
3318 +if [ "$CHECKSECURITY_NOFINDERRORS" = "TRUE" ] ; then
3319 +       exec 2>&9
3320 +fi
3321 +
3322 +cd $LOGDIR
3323 +
3324 +test -f setuid.today || touch setuid.today
3325 +
3326 +if cmp -s setuid.today $TMPSETUID >/dev/null
3327 +then
3328 +    :
3329 +else
3330 +       diff -u0 setuid.today $TMPSETUID >> $TMPDIFF || [ $? = 1 ]
3331 +       echo "`hostname` changes to setuid programs and devices:" 
3332 +       cat $TMPDIFF 
3333 +       
3334 +       if [ `cat $TMPDIFF | wc -l` -gt 0 -a ! -z "$CHECKSECURITY_EMAIL" ]; then
3335 +               /usr/bin/mail -s "Setuid changes for `hostname -f` on `date '+%D %T'`" $CHECKSECURITY_EMAIL < $TMPDIFF
3336 +       fi
3337 +       
3338 +       mv setuid.today setuid.yesterday
3339 +       mv $TMPSETUID setuid.today
3340 +        chown root.adm setuid.today
3341 +fi
3342 +rm -f $TMPDIFF
3343 +rm -f $TMPSETUID
3344 --- cron-3.0pl1.orig/debian/checksecurity.8
3345 +++ cron-3.0pl1/debian/checksecurity.8
3346 @@ -0,0 +1,145 @@
3347 +.\" -*- nroff -*-
3348 +.TH CHECKSECURITY 8 "2 February 1997" "Debian Linux"
3349 +.SH NAME
3350 +checksecurity \- check for changes to setuid programs
3351 +.SH SYNOPSIS
3352 +.B checksecurity
3353 +.SH DESCRIPTION
3354 +The
3355 +.B checksecurity
3356 +command scans the mounted files systems (subject to the filter defined
3357 +in /etc/checksecurity.conf) and compares the list of setuid programs to the
3358 +list created on the previous run. Any changes are printed to standard
3359 +output. Also, it generates a list of 
3360 +.I nfs
3361 +and 
3362 +.I afs
3363 +filesystems that are mounted insecurely (i.e. they are missing the 
3364 +.I nodev 
3365 +and either the
3366 +.I noexec
3367 +or
3368 +.I nosuid 
3369 +flags).
3370 +.PP
3371 +.B checksecurity
3372 +is run by 
3373 +.B cron
3374 +on a daily basis, and the output stored in /var/log/setuid.changes.
3375 +.SH CONFIGURATION
3376 +The
3377 +.B checksecurity.conf
3378 +file defines several configuration variables:
3379 +.BR CHECKSECURITY_FILTER ,
3380 +.BR CHECKSECURITY_NOFINDERRORS ,
3381 +.BR CHECKSECURITY_DISABLE ,
3382 +.BR CHECKSECURITY_NONFSAFS ,
3383 +.BR CHECKSECURITY_EMAIL ,
3384 +.BR CHECKSECURITY_DEVICEFILTER ,
3385 +.BR CHECKSECURITY_PATHFILTER , 
3386 +and
3387 +.BR LOGDIR .
3388 +Each is described below.
3389 +.PP
3390 +The 
3391 +.B CHECKSECURITY_FILTER
3392 +environment variable which is the argument of 'grep -vE' applied to
3393 +the output of the  
3394 +.B mount
3395 +command. In other words, the value of
3396 +.B CHECKSECURITY_FILTER
3397 +is a regular expression that removes matching lines from those
3398 +file systems that will be scanned. The default value removes
3399 +all file systems of type 
3400 +.I proc, msdos, iso9660, ncpfs, nfs, afs,
3401 +.I smbfs, auto, ntfs, coda
3402 +file systems, 
3403 +anything mounted on /dev/fd*, anything mounted
3404 +on /mnt or /amd, and anything mounted with option nosuid or noexec.
3405 +.PP
3406 +The
3407 +.B checksecurity.conf
3408 +file is sourced from 
3409 +.B checksecurity,
3410 +so you could do some fairly tricky things to define 
3411 +.BR CHECKSECURITY_FILTER .
3412 +.PP
3413 +The 
3414 +.B CHECKSECURITY_NOFINDERRORS 
3415 +environment variable, if set to the literal "TRUE", disables
3416 +find errors from checksecurity (actually, it re-routes them to 
3417 +.B /dev/null
3418 +).
3419 +.PP
3420 +The
3421 +.B CHECKSECURITY_DISABLE  
3422 +environment variable, if set to the literal "TRUE", disables
3423 +checksecurity entirely, as a sop to those who think it's safe to allow
3424 +random mounting of NFS and AFS disks without the nosuid or noexec flags.
3425 +.PP
3426 +The
3427 +.B CHECKSECURITY_NONFSAFS
3428 +environment variable, if set to the literal "TRUE", disables the message about 
3429 +.I nfs
3430 +and
3431 +.I afs
3432 +file systems that are mounted without the
3433 +.I nodev 
3434 +and either the
3435 +.I noexec
3436 +or
3437 +.I nosuid 
3438 +options.
3439 +.PP
3440 +If set, the 
3441 +.B CHECKSECURITY_EMAIL
3442 +variable defines who is sent a copy of the setuid.changes file.
3443 +.PP
3444 +The
3445 +.B CHECKSECURITY_DEVICEFILTER
3446 +variable specifies a 
3447 +.B find
3448 +clause for which matching block and character device files will not be
3449 +monitored for changing owners and permissions. For example, if you
3450 +didn't want to check for permission changes on tty device files
3451 +beneath /dev, you could set the following:
3452 +.PP
3453 +.RS
3454 +CHECKSECURITY_DEVICEFILTER='-path /dev/tty*'
3455 +.RE
3456 +.PP
3457 +Note that any added or modified suid programs under that path would
3458 +still be detected. If you want to specify multiple expressions,
3459 +separate them with '-o', but there is no need to surround the whole
3460 +clause with parentheses. To disable this filter, specify it as
3461 +'-false' (which is the default).
3462 +.PP
3463 +The
3464 +.B CHECKSECURITY_PATHFILTER
3465 +variable specifies a 
3466 +.B find
3467 +clause which will be pruned from the search path.
3468 +.B This means that the entire subtree will be completely skipped.
3469 +Thus, specifying  
3470 +.PP
3471 +.RS
3472 +CHECKSECURITY_PATHFILTER='-path /var/ftp'
3473 +.RE
3474 +.PP
3475 +then the entire /var/ftp tree will be skipped. To disable this filter,
3476 +specify it as '-false' (which is the default).
3477 +.PP
3478 +.B LOGDIR
3479 +sets the name of the directory which stores the files which track
3480 +the permission and ownership changes. By default, they are in 
3481 +.BR /var/log .
3482 +.SH FILES
3483 +.TP
3484 +.I /etc/checksecurity.conf
3485 +checksecurity configuration file
3486 +.TP
3487 +.I /var/log/setuid.today
3488 +setuid files from the most recent run
3489 +.TP
3490 +.I /var/log/setuid.yesterday
3491 +setuid files from the previous run
3492 --- cron-3.0pl1.orig/debian/checksecurity.conf
3493 +++ cron-3.0pl1/debian/checksecurity.conf
3494 @@ -0,0 +1,126 @@
3495 +#
3496 +# This is the checksecurity script configuration file
3497 +#
3498 +# These configuration variables mabye set:
3499 +# 
3500 +#     CHECKSECURITY_FILTER
3501 +#     CHECKSECURITY_NOFINDERRORS
3502 +#     CHECKSECURITY_DISABLE
3503 +#     CHECKSECURITY_NONFSAFS
3504 +#     CHECKSECURITY_EMAIL
3505 +#     CHECKSECURITY_DEVICEFILTER
3506 +#     CHECKSECURITY_PATHFILTER
3507 +#     LOGDIR
3508 +# 
3509 +# Each is described in it's own section below -- search for ####
3510 +# as a section divider.
3511 +#
3512 +####
3513 +#
3514 +# The CHECKSECURITY_FILTER variable is used as an argument to
3515 +# "grep -vE" to filter lines from the output of the "mount"
3516 +# command. 
3517 +#
3518 +# The default is not check the following file systems:
3519 +#
3520 +#   type proc
3521 +#   type msdos
3522 +#   type iso9660
3523 +#   type ncpfs
3524 +#   type smbfs
3525 +#   type nfs
3526 +#   type afs
3527 +#   type auto (They'll typically be picked up on the nfs branch)
3528 +#   type ntfs
3529 +#   type coda (similar to afs)
3530 +#   type usbdevfs
3531 +#   type none (--bind mounts)
3532 +#
3533 +#   floppies (i.e. /dev/fd<whatever>)
3534 +#   anything on /mnt or /amd
3535 +#
3536 +# Note that behaviour for nfs/afs has changed as of release -45. We
3537 +# no longer run find across nfs/afs disks; instead we simply report
3538 +# afs/nfs disks that are mounted insecurely (without -onosuid|noexec,nodev).
3539 +# You can disable this report by going setting the CHECKSECURITY_NONFSAFS 
3540 +# variable below.
3541 +#
3542 +# Use temp variables to build up CHECKSECURITY_FILTER, to make it
3543 +# a little more readable.
3544 +#
3545 +CS_NFSAFS='(nfs|afs|coda)'
3546 +# Uncomment the next line to get the old behaviour.
3547 +#CS_NFSAFS='(nfs|afs) \(.*(nosuid|noexec).*nodev.*\)'
3548 +#
3549 +CS_TYPES=' type (auto|proc|msdos|fat|vfat|iso9660|usbdevfs|ncpfs|smbfs|ntfs|devpts|none|'$CS_NFSAFS')'
3550 +#
3551 +CS_OPTS='\(.*(nosuid|noexec).*\)'
3552 +#
3553 +CS_DEVS='^/dev/fd'
3554 +#
3555 +CS_DIRS='on /mnt'
3556 +#
3557 +CHECKSECURITY_FILTER="$CS_TYPES|$CS_OPTS|$CS_DEVS|$CS_DIRS"
3558 +#
3559 +# Clear the temporary variables
3560 +#
3561 +unset CS_NFSAFS CS_TYPES CS_DIRS CS_OPTS
3562 +#
3563 +####
3564 +#
3565 +# The CHECKSECURITY_NOFINDERRORS, if set to "TRUE" (case sensitive),
3566 +# redirects any errors from the find command used in checksecurity
3567 +# to /dev/null.
3568 +#
3569 +CHECKSECURITY_NOFINDERRORS="FALSE"
3570 +####
3571 +#
3572 +# The CHECKSECURITY_DISABLE, if set to "TRUE" (case sensitive),
3573 +# disables the running of checksecurity
3574 +#
3575 +CHECKSECURITY_DISABLE="FALSE"
3576 +####
3577 +#
3578 +# The CHECKSECURITY_NONFSAFS, if set to "TRUE" (case sensitive),
3579 +# disables the message about insecurely mounted nfs/afs disks
3580 +#
3581 +CHECKSECURITY_NONFSAFS="FALSE"
3582 +####
3583 +#
3584 +# If the CHECKSECURITY_EMAIL is set, the report is mailed to the given
3585 +# address. Note that if you set this, it is *assumed* that you have
3586 +# /usr/bin/mail that accepts -s; the mailx package provides this; or
3587 +# you can install mutt and create a link, or some other
3588 +# alternative. No, I'm not going to fix it to write the appropriate
3589 +# headers and use sendmail (although I'd consider patch), nor am I
3590 +# going to add a {Depends|Recommends|Suggests} to the cron package.
3591 +# Do not submit bugs about this unless you include the above mentioned
3592 +# patch. You enabled this option -- you take responsibility.
3593 +#
3594 +#CHECKSECURITY_EMAIL="root"
3595 +####
3596 +#
3597 +# The CHECKSECURITY_DEVICEFILTER lets you tell find not to report
3598 +# devices in those directories (if you choose the daily Emails,
3599 +# devices like /dev/pts/?, /dev/tty?, or /dev/urandom will change
3600 +# often and clutter your mailbox) Note that these directories are
3601 +# still searched for suid executables.  Also not that *something* must
3602 +# be defined, which is why the default is "-false".
3603 +# Examples:
3604 +#CHECKSECURITY_DEVICEFILTER="-path /dev/*"
3605 +#CHECKSECURITY_DEVICEFILTER="-path /dev/* -o -path /home/ftp/dev/*"
3606 +CHECKSECURITY_DEVICEFILTER="-false"
3607 +####
3608 +# The CHECKSECURITY_PATHFILTER variable lets you set a pattern of
3609 +# pathnames that you don't want to check at all. You hopefully know
3610 +# what you're doing if you do this :-).
3611 +# Example:
3612 +# CHECKSECURITY_PATHFILTER="-path /dev/rd* -o -path /var/home/ftp*"
3613 +CHECKSECURITY_PATHFILTER="-false"
3614 +####
3615 +#
3616 +# Location of setuid file databases. Probably should
3617 +# be in /var/lib/cron, but I don't want to move them now. After
3618 +# the release, maybe.
3619 +#
3620 +LOGDIR=/var/log
3621 --- cron-3.0pl1.orig/debian/conffiles.nopam
3622 +++ cron-3.0pl1/debian/conffiles.nopam
3623 @@ -0,0 +1,5 @@
3624 +/etc/checksecurity.conf
3625 +/etc/crontab
3626 +/etc/init.d/cron
3627 +/etc/cron.daily/standard
3628 +/etc/cron.monthly/standard
3629 --- cron-3.0pl1.orig/debian/conffiles.pam
3630 +++ cron-3.0pl1/debian/conffiles.pam
3631 @@ -0,0 +1,6 @@
3632 +/etc/checksecurity.conf
3633 +/etc/crontab
3634 +/etc/init.d/cron
3635 +/etc/cron.daily/standard
3636 +/etc/cron.monthly/standard
3637 +/etc/pam.d/cron
3638 --- cron-3.0pl1.orig/debian/control
3639 +++ cron-3.0pl1/debian/control
3640 @@ -0,0 +1,35 @@
3641 +Source: cron
3642 +Section: admin
3643 +Priority: important
3644 +Maintainer: Steve Greenland <stevegr@debian.org>
3645 +Standards-Version: 3.5.2
3646 +Build-Depends: debhelper, libpam0g-dev
3647 +
3648 +Package: cron
3649 +Architecture: any
3650 +Depends: ${shlibs:Depends}, debianutils (>=1.7)
3651 +Recommends: exim | smail | sendmail | mail-transport-agent
3652 +Suggests: anacron (>=2.0-1), logrotate, lockfile-progs
3653 +Conflicts: suidmanager (<< 0.50)
3654 +Provides:
3655 +Description: management of regular background processing
3656 + cron is a background process (`daemon') that runs programs at regular
3657 + intervals (for example, every minute, day, week or month); which
3658 + processes are run and at what times are specified in the `crontab'.
3659 + .
3660 + Users may also install crontabs so that processes are run on
3661 + their behalf, though this feature can be disabled or restricted to
3662 + particular users.
3663 + .
3664 + Output from the commands is usually mailed to the system administrator
3665 + (or to the user in question); you should probably install a mail system
3666 + as well so that you can receive these messages.
3667 + .
3668 + This cron package is configured by default to do various standard
3669 + system maintenance tasks, such as ensuring that logfiles do not
3670 + grow endlessly and overflow the disk.
3671 + .
3672 + The lockfile-progs package is only a "Suggests" because of the poor
3673 + way that dselect handles "Recomments", but I do strongly suggest that
3674 + you install it; it prevents /etc/cron.daily/standard from running multiple
3675 + times if something gets jammed.
3676 --- cron-3.0pl1.orig/debian/copyright
3677 +++ cron-3.0pl1/debian/copyright
3678 @@ -0,0 +1,39 @@
3679 +Copyright 1988,1990,1993,1994 by Paul Vixie;
3680 +All rights reserved
3681 +
3682 +Distribute freely, except: don't remove my name from the source or
3683 +documentation (don't take credit for my work), mark your changes (don't
3684 +get me blamed for your possible bugs), don't alter or remove this
3685 +notice.  May be sold if buildable source is provided to buyer.  No
3686 +warranty of any kind, express or implied, is included with this
3687 +software; use at your own risk, responsibility for damages (if any) to
3688 +anyone resulting from the use of this software rests entirely with the
3689 +user.
3690 +
3691 +
3692 +The original source for this package may be obtained from 
3693 +ftp://ftp.vix.com/pub/vixie/cron-3.0.
3694 +
3695 +Modifications for Debian GNU/Linux Copyright 1994 Ian Jackson;
3696 +checksecurity script:
3697 +Copyright (C) 1994 Ian Jackson
3698 +Copyright (C) 1996, 1997, 1998, 1999, 2000 Steve Greenland
3699 +
3700 +The `checksecurity' script and its associated files (checksecurity.8
3701 +and checksecurity.conf) are free software; you can redistribute it
3702 +and/or modify it under the terms of the GNU General Public License as
3703 +published by the Free Software Foundation; either version 2, or (at
3704 +your option) any later version.
3705 +
3706 +This program is distributed in the hope that it will be useful, but
3707 +WITHOUT ANY WARRANTY; without even the implied warranty of
3708 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3709 +General Public License for more details.
3710 +
3711 +A copy of the GNU General Public License is available as
3712 +`/usr/share/common-licenses/GPL' in the 
3713 +Debian GNU/Linux distribution or on the World Wide Web
3714 +at `http://www.gnu.org/copyleft/gpl.html'. You can also obtain it by
3715 +writing to the Free Software Foundation, Inc., 59 Temple Place - Suite
3716 +330, Boston, MA 02111-1307, USA.
3717 +
3718 --- cron-3.0pl1.orig/debian/cron.init
3719 +++ cron-3.0pl1/debian/cron.init
3720 @@ -0,0 +1,28 @@
3721 +#!/bin/sh
3722 +# Start/stop the cron daemon.
3723 +
3724 +test -f /usr/sbin/cron || exit 0
3725 +
3726 +case "$1" in
3727 +start) echo -n "Starting periodic command scheduler: cron"
3728 +        start-stop-daemon --start --quiet --exec /usr/sbin/cron
3729 +        echo "." 
3730 +       ;;
3731 +stop)  echo -n "Stopping periodic command scheduler: cron"
3732 +        start-stop-daemon --stop --quiet --exec /usr/sbin/cron
3733 +        echo "."
3734 +        ;;
3735 +restart) echo -n "Restarting periodic command scheduler: cron"
3736 +        start-stop-daemon --stop --quiet --exec /usr/sbin/cron
3737 +        start-stop-daemon --start --quiet --exec /usr/sbin/cron
3738 +        echo "."
3739 +        ;;
3740 +reload|force-reload) echo -n "Reloading configuration files for periodic command scheduler: cron"
3741 +       # cron reloads automatically
3742 +        echo "."
3743 +        ;;
3744 +*)     echo "Usage: /etc/init.d/cron start|stop|restart|reload|force-reload"
3745 +        exit 1 
3746 +        ;;
3747 +esac
3748 +exit 0
3749 --- cron-3.0pl1.orig/debian/cron.pam
3750 +++ cron-3.0pl1/debian/cron.pam
3751 @@ -0,0 +1,9 @@
3752 +#
3753 +# The PAM configuration file for the cron daemon
3754 +#
3755 +
3756 +account    required   pam_unix.so
3757 +auth       required   pam_unix.so nullok
3758 +auth       required   pam_env.so
3759 +session    required   pam_unix.so
3760 +
3761 --- cron-3.0pl1.orig/debian/crontab.main
3762 +++ cron-3.0pl1/debian/crontab.main
3763 @@ -0,0 +1,15 @@
3764 +# /etc/crontab: system-wide crontab
3765 +# Unlike any other crontab you don't have to run the `crontab'
3766 +# command to install the new version when you edit this file.
3767 +# This file also has a username field, that none of the other crontabs do.
3768 +
3769 +SHELL=/bin/sh
3770 +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
3771 +
3772 +# m h dom mon dow user command
3773 +25 6   * * *   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.daily
3774 +47 6   * * 7   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.weekly
3775 +52 6   1 * *   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.monthly
3776 +#
3777 +
3778 +
3779 --- cron-3.0pl1.orig/debian/dirs
3780 +++ cron-3.0pl1/debian/dirs
3781 @@ -0,0 +1,12 @@
3782 +usr/bin
3783 +usr/sbin
3784 +usr/share/man/man1
3785 +usr/share/man/man5
3786 +usr/share/man/man8
3787 +etc/cron.daily
3788 +etc/cron.weekly
3789 +etc/cron.monthly
3790 +etc/cron.d
3791 +etc/init.d
3792 +etc/pam.d
3793 +var/spool/cron/crontabs
3794 --- cron-3.0pl1.orig/debian/postinst
3795 +++ cron-3.0pl1/debian/postinst
3796 @@ -0,0 +1,51 @@
3797 +#!/bin/sh
3798 +set -e
3799 +
3800 +update-rc.d cron defaults 89 11 >/dev/null
3801 +# Copy existing allow/deny files
3802 +crondir="/var/spool/cron"
3803 +pausemessage="F"
3804 +for fname in allow deny ; do
3805 +    if [ -f $crondir/$fname ] ; then
3806 +       if [ ! -f $/etc/cron.$fname ] ; then
3807 +           mv $crondir/$fname /etc/cron.$fname
3808 +           echo " "
3809 +           echo "Moving $crondir/$fname to /etc/cron.$fname to comply with Debian policy"
3810 +           pausemessage="T"
3811 +       else
3812 +           echo " "
3813 +           echo "Warning:"
3814 +           echo "Both $crondir/$fname and /etc/cron.$fname exist -- cron will"
3815 +           echo "use /etc/cron.$fname"
3816 +           pausemessage="T"
3817 +       fi
3818 +    fi
3819 +done
3820 +#
3821 +# Check for upgrades from very old versions
3822 +#
3823 +if [ "$1" = "configure" -a -n "$2" ] && dpkg --compare-versions "$2" lt "3.0pl1-43" ; then
3824 +    echo " "
3825 +    echo "The format of the setuid.today file (output from checksecurity) has"
3826 +    echo "changed. This means that the first run of checksecurity after the "
3827 +    echo "upgrade will produce a diff on every every file affected".
3828 +    pausemessage="T"
3829 +fi
3830 +
3831 +#
3832 +# Move dpkg status file backups, if necessary/possible.
3833 +#
3834 +( cd /var/lib/dpkg ;
3835 +for oldstat in status.yesterday.* ; do
3836 +    if [ -f $oldstat ] ; then
3837 +        newstat=`echo $oldstat | sed 's/yesterday\.//'`;
3838 +        newstat=/var/backups/dpkg.$newstat;            
3839 +        if [ ! -f $newstat ] ; then
3840 +            mv $oldstat $newstat ;
3841 +        fi
3842 +    fi                        
3843 +done)
3844 +
3845 +start-stop-daemon --start --quiet --oknodo --exec /usr/sbin/cron
3846 +
3847 +#DEBHELPER#
3848 --- cron-3.0pl1.orig/debian/postrm
3849 +++ cron-3.0pl1/debian/postrm
3850 @@ -0,0 +1,7 @@
3851 +#!/bin/sh
3852 +set -e
3853 +if [ $1 = purge ]; then 
3854 +    update-rc.d cron remove >/dev/null
3855 +    rm -f /etc/cron.allow /etc/cron.deny
3856 +fi
3857 +
3858 --- cron-3.0pl1.orig/debian/preinst
3859 +++ cron-3.0pl1/debian/preinst
3860 @@ -0,0 +1,8 @@
3861 +#! /bin/sh
3862 +#
3863 +# Needed because -36 and -36.1 included bad prerm scripts
3864 +#
3865 +if [ "$1" = "upgrade" -a \( "$2" = "3.0pl1-36" -o "$2" = "3.0pl1-36.1" \) ] ; then
3866 +   #kill the running cron
3867 +   start-stop-daemon --oknodo --quiet --stop --exec /usr/sbin/cron
3868 +fi
3869 --- cron-3.0pl1.orig/debian/prerm
3870 +++ cron-3.0pl1/debian/prerm
3871 @@ -0,0 +1,5 @@
3872 +#!/bin/sh
3873 +set -e
3874 +/etc/init.d/cron stop 
3875 +
3876 +#DEBHELPER#
3877 --- cron-3.0pl1.orig/debian/rules
3878 +++ cron-3.0pl1/debian/rules
3879 @@ -0,0 +1,106 @@
3880 +#!/usr/bin/make -f
3881 +# 
3882 +# Rules file for cron
3883 +#
3884 +
3885 +# Uncomment this to turn on verbose mode.
3886 +#export DH_VERBOSE=1
3887 +
3888 +DEB_OPTIM= -O2 -Wall
3889 +DEB_INSTALL = install
3890 +DEB_DEBUG_DEFS = -DDEBUGGING=0
3891 +
3892 +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
3893 +  DEB_OPTIM = -g -Wall 
3894 +  DEB_DEBUG_DEFS= -DDEBUGGING=1
3895 +endif
3896 +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
3897 +  DEB_INSTALL += -s
3898 +endif
3899 +
3900 +# Set system type (Linux, HURD, etc.)
3901 +DEB_HOST_GNU_SYSTEM = $(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM)
3902 +ifeq ($(DEB_HOST_GNU_SYSTEM), gnu)
3903 +  PAM_DEFS = 
3904 +  PAM_LIBS =
3905 +  CONFFILES = conffiles.nopam
3906 +else
3907 +  PAM_DEFS = -DUSE_PAM
3908 +  PAM_LIBS = -lpam
3909 +  CONFFILES = conffiles.pam
3910 +endif
3911 +
3912 +export PAM_DEFS
3913 +export PAM_LIBS
3914 +
3915 +build: build-stamp
3916 +build-stamp:
3917 +       dh_testdir
3918 +
3919 +       # Add here commands to compile the package.
3920 +       $(MAKE) OPTIM="$(DEB_OPTIM)" DEBUG_DEFS="$(DEB_DEBUG_DEFS)"
3921 +
3922 +       touch build-stamp
3923 +
3924 +clean:
3925 +       dh_testdir
3926 +       dh_testroot
3927 +       rm -f build-stamp
3928 +
3929 +       # Add here commands to clean up after the build process.
3930 +       -$(MAKE) clean
3931 +       rm -f debian/conffiles
3932 +       dh_clean
3933 +
3934 +# Build architecture-independent files here.
3935 +binary-indep: build
3936 +# We have nothing to do by default.
3937 +
3938 +# Build architecture-dependent files here.
3939 +binary-arch: build
3940 +#      dh_testversion
3941 +       dh_testdir
3942 +       dh_testroot
3943 +       dh_clean -k
3944 +       dh_installdirs
3945 +
3946 +       # Add here commands to install the files into debian/tmp
3947 +       $(MAKE) install DESTDIR=`pwd`/debian/tmp OPTIM="$(DEB_OPTIM)" INSTALL="$(DEB_INSTALL)" DEBUG_DEFS="$(DEB_DEBUG_DEFS)"
3948 +       install -m 755 debian/checksecurity debian/tmp/usr/sbin/.
3949 +       install -m 644 debian/checksecurity.conf debian/tmp/etc/.
3950 +
3951 +       cp -p debian/$(CONFFILES) debian/conffiles
3952 +       dh_installdocs FEATURES THANKS README debian/README.anacron
3953 +#      dh_installexamples
3954 +#      dh_installmenu
3955 +       dh_installpam
3956 +       dh_installinit --noscripts
3957 +       # Can't use dh_installcron because we don't have "normal" naming
3958 +       # convention
3959 +       install -m 644 debian/crontab.main debian/tmp/etc/crontab
3960 +       install -m 755 debian/standard.daily \
3961 +                       debian/tmp/etc/cron.daily/standard
3962 +       install -m 755 debian/standard.monthly \
3963 +                       debian/tmp/etc/cron.monthly/standard
3964 +       dh_installmanpages crontab.1 crontab.5 cron.8 bitstring.3
3965 +#      dh_undocumented
3966 +       dh_installchangelogs CHANGES
3967 +       dh_strip
3968 +       dh_compress
3969 +       dh_fixperms
3970 +       # dh_suidregister -- deliberately commented out, as it causes
3971 +       # /usr/bin/crontab to be shipped non-suid.
3972 +       # so does dh_fixperms when not run under fakeroot. sigh.
3973 +       chmod u+s debian/tmp/usr/bin/crontab
3974 +       dh_installdeb
3975 +       dh_shlibdeps
3976 +       dh_gencontrol
3977 +#      dh_makeshlibs
3978 +       dh_md5sums
3979 +       dh_builddeb
3980 +
3981 +source diff:                                                                  
3982 +       @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false
3983 +
3984 +binary: binary-indep binary-arch
3985 +.PHONY: build clean binary-indep binary-arch binary
3986 --- cron-3.0pl1.orig/debian/standard.daily
3987 +++ cron-3.0pl1/debian/standard.daily
3988 @@ -0,0 +1,103 @@
3989 +#!/bin/sh
3990 +# /etc/cron.daily/standard: standard daily maintenance script
3991 +# Written by Ian A. Murdock <imurdock@gnu.ai.mit.edu>
3992 +# Modified by Ian Jackson <ijackson@nyx.cs.du.edu>
3993 +# Modified by Steve Greenland <stevegr@debian.org>
3994 +
3995 +bak=/var/backups
3996 +LOCKFILE=/var/lock/cron.daily
3997 +umask 022
3998 +
3999 +#
4000 +# Avoid running more than one at a time -- could happen if the
4001 +# checksecurity script lands on a network drive.
4002 +#
4003 +
4004 +if [ -x /usr/bin/lockfile-create ] ; then
4005 +    lockfile-create $LOCKFILE
4006 +    if [ $? -ne 0 ] ; then
4007 +       cat <<EOF
4008 +
4009 +Unable to run /etc/cron.daily/standard because lockfile $LOCKFILE
4010 +acquisition failed. This probably means that the previous days
4011 +instance is still running. Please check and correct if necessary.
4012 +
4013 +EOF
4014 +       exit 1
4015 +    fi
4016 +
4017 +    # Keep lockfile fresh
4018 +    lockfile-touch $LOCKFILE &
4019 +    LOCKTOUCHPID="$!"
4020 +fi
4021 +
4022 +#
4023 +# Backup key system files
4024 +#
4025 +
4026 +if cd $bak ; then
4027 +       cmp -s passwd.bak /etc/passwd || (cp -p /etc/passwd passwd.bak &&
4028 +                                         chmod 600 passwd.bak)
4029 +       cmp -s group.bak /etc/group || (cp -p /etc/group group.bak &&
4030 +                                       chmod 600 passwd.bak)
4031 +        if [ -f /etc/shadow ] ; then
4032 +         cmp -s shadow.bak /etc/shadow || (cp -p /etc/shadow shadow.bak &&
4033 +                                            chmod 600 shadow.bak)
4034 +       fi
4035 +        if [ -f /etc/gshadow ] ; then
4036 +         cmp -s gshadow.bak /etc/gshadow || (cp -p /etc/gshadow gshadow.bak &&
4037 +                                             chmod 600 gshadow.bak)
4038 +       fi
4039 +fi
4040 +
4041 +if cd $bak ; then
4042 +    if ! cmp -s dpkg.status.0 /var/lib/dpkg/status ; then
4043 +           cp -p /var/lib/dpkg/status dpkg.status
4044 +           savelog -c 7 dpkg.status >/dev/null
4045 +    fi
4046 +fi
4047 +cd /var/log
4048 +umask 027
4049 +savelog -c 7 -m 640 -u root -g adm setuid.changes >/dev/null
4050 +checksecurity >setuid.changes
4051 +
4052 +#
4053 +# Check to see if any files are in lost+found directories and warn admin
4054 +#
4055 +# Get a list of the (potential) ext2 l+f directories
4056 +lflist=`df -P --type=ext2  |awk '$6 == "/" {$6 = ""} /\/dev\// {printf "%s/lost+found ", $6}'`
4057 +
4058 +# In each directory, look for files
4059 +for lfdir in $lflist ; do
4060 +    if [ -d "$lfdir" ] ; then
4061 +       more_lost_found=`ls -1  "$lfdir" | grep -v 'lost+found$' | sed 's/^/    /'`
4062 +       if [ -n "$more_lost_found" ] ; then
4063 +           lost_found="$lost_found
4064 +
4065 +$lfdir:
4066 +$more_lost_found"
4067 +           # NOTE: above weird line breaks in string are intentional!
4068 +        fi
4069 +    fi
4070 +done
4071 +
4072 +if [ -n "$lost_found" ]; then
4073 +    cat << EOF
4074 +Files were found in lost+found directories. This is probably
4075 +the result of a crash or bad shutdown, or possibly of a disk
4076 +problem. These files may contain important information. You
4077 +should examine them, and move them out of lost+found or delete
4078 +them if they are not important.
4079 +
4080 +The following files were found:
4081 +$lost_found
4082 +EOF
4083 +fi
4084 +
4085 +#
4086 +# Clean up lockfile
4087 +#
4088 +if [ -x /usr/bin/lockfile-create ] ; then
4089 +    kill $LOCKTOUCHPID
4090 +    lockfile-remove $LOCKFILE
4091 +fi
4092 --- cron-3.0pl1.orig/debian/standard.monthly
4093 +++ cron-3.0pl1/debian/standard.monthly
4094 @@ -0,0 +1,4 @@
4095 +#!/bin/sh
4096 +# /etc/cron.monthly/standard: standard monthly maintenance script
4097 +
4098 +# rotation of wtmp and btmp taken over by logrotate