All changes from 0.99.1 to 0.99.2 pre-release.

This commit is contained in:
dale_mellor 2003-07-20 15:52:35 +00:00
commit 2c6cfc753d
13 changed files with 399 additions and 331 deletions

View file

@ -1 +1,8 @@
Dale Mellor (dale_mellor@users.sourceforge.net)
wrote everything from scratch, with some reference to Paul Vixie's code,
with the exceptions noted below.
The section of the manual which describes in detail the syntax for Vixie-style
configuration files is copied verbatim from Paul Vixie's own distribution,
on the understanding that this is permitted under his copyright notice,
which is reproduced in its entirety in this section of the manual.

25
BUGS
View file

@ -1,15 +1,22 @@
-*-text-*-
* If two users modify their crontabs simultaneously, there will be contention
for /var/cron/update between themselves and with the main daemon.
-*-text-*-
* Daylight savings time shifts are not taken into account very well. If things
are critical, your best bet is to set your TZ environment variable to
`:Universal', and express all your configuration files in Universal
Coordinated Time (UTC).
* As often as not the cron daemon crashes (segfaults) when crontab sends it a
SIGHUP. For this reason, the current release does not install cron or
crontab.
_______________________________________________________________________________
Copyright (C) 2003 Dale Mellor
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
copyright notice and this permission notice are preserved,
thus giving the recipient permission to redistribute in turn.
Permission is granted to distribute modified versions
of this document, or of portions of it,
under the above conditions, provided also that they
carry prominent notices stating who last changed them.

View file

@ -1,8 +1,20 @@
2003-07-05 Dale Mellor <dale_mellor@users.sourceforge.net>
2003-07-20 Dale Mellor <dale_mellor@users.sourceforge.net>
* Second cut, now _really_ fully functional (100% Vixie
compatible), production quality code, still needs lots of testing
doing...
* Converted from SIGUP-/var/cron/update to select-/var/cron/socket
method of communication between crontab and cron.
* Added implicit job which checks every minute for updates to
/etc/crontab.
* Removed --enable-vixie configuration option - the Vixie programs
are built and installed by default now.
* Bumped version to 0.99.2.
* configure.ac, makefile.am: Disabled installation of cron,
crontab programs by default as they are broken.
2003-06-28 Dale Mellor <dale_mellor@users.sourceforge.net>
@ -10,3 +22,21 @@
testing...
* Version set at 0.99.1
________________________________________________________________________________
Copyright (C) 2003 Dale Mellor
Permission is granted to anyone to make or distribute verbatim
copies of this document as received, in any medium, provided that
the copyright notice and this permission notice are preserved,
thus giving the recipient permission to redistribute in turn.
Permission is granted to distribute modified versions of this
document, or of portions of it, under the above conditions,
provided also that they carry prominent notices stating who last
changed them.

15
NEWS
View file

@ -6,6 +6,17 @@ See the end for copying conditions.
Please send bug reports to dale_mellor@users.sourceforge.net.
Sunday, 20th July 2003
Released version 0.99.2. (Now fully functional). The CVS tag is
release_0-99-2 (no branch).
Sunday, 20th July 2003
It has been a long and painful journey, but we have at last worked out how
to work around all the faults in Guile (an implementation with no threads
and no UNIX signals!). The code is now really 100% Vixie compatible.
Saturday, 5th July 2003
Released version 0.99.1, with installation of cron and crontab disabled by
default (suspect problems with Guile internals are preventing these from
@ -20,9 +31,7 @@ Friday, 4th July 2003
----------------------------------------------------------------------
Copyright information:
____________________________________________________________________________
Copyright (C) 2003 Dale Mellor
Permission is granted to anyone to make or distribute verbatim copies

84
README
View file

@ -1,13 +1,13 @@
-*-text-*-
Copyright (C) 2003 Dale Mellor
See the end for copying conditions.
This is version 0.99.1 of the mcron program, designed and written by Dale
Mellor, which replaces and hugely enhances Vixie cron. It is functionally
complete, production quality code (did you expect less?), but has not received
much testing yet and contains known bugs. It has only been built on a GNU/Linux
system, and will most likely fail on others (but you never know...).
Mcron is supposed to be 100% Vixie compatible. However, in the current release
this is broken, and by default only 50% compatibility is installed.
This is version 0.99.2 of the mcron program (the second 1.0.0 release
candidate), designed and written by Dale Mellor, which replaces and hugely
enhances Vixie cron. It is functionally complete, production quality code (did
you expect less?), but has not received much testing yet. It has only been built
on a GNU/Linux system, and will most likely fail on others (but you never
know...).
----------------------------------------------------------------------
@ -15,41 +15,33 @@ IMPORTANT NOTICES
Read the BUGS file.
By default, the cron and crontab programs are not installed, and mcron will
happiliy coexist alongside any existing cron programs you have on your
system. The Vixie-style programs can be installed by specifying --enable-vixie
to the configure command, in which case you must take heed of the following
notes.
Do not (yet) install this software on a machine which relies for its functioning
on its current set of crontabs.
The package must be installed by root.
Do not (yet) install this software on a machine which relies for its
functioning on its current set of crontabs.
Before installing this package for the first time, it is necessary to terminate
any running cron daemons on your system. If your old cron is not Vixie or
accurately Vixie compatible (files in /var/cron/tabs*, /var/cron/allow,
/var/cron/deny, /etc/crontab, /var/run/cron.pid) then you will need to clear out
all old crontabs and make new ones afresh.
The package must be installed by root.
If your old cron is Vixie, or very similar, mcron should fall right into place
where your old cron was (the binaries cron and crontab will be replaced), and
you should be able to continue to use your existing crontabs without noticing
any changes. Bear in mind that if you use /etc/crontab, then changes to this
file will *not* take immediate effect (this is the 1% incompatibility between
mcron and Vixie cron); you may want to add a comment to this file with a note to
this effect. Alternatively, use the new mcron program, it's better!
Before installing this package for the first time, it is necessary to
terminate any running cron daemons on your system. If your old cron is not
accurately Vixie compatible (files in /var/cron/tabs*, /var/cron/allow,
/var/cron/deny, /etc/crontab, /var/run/cron.pid) then you will need to clear
out all old crontabs and make new ones afresh.
If your old cron is Vixie, or very similar, mcron should fall right into
place where your old cron was (the binaries cron and crontab will be
replaced), and you should be able to continue to use your existing crontabs
without noticing any changes. Bear in mind that if you use /etc/crontab,
then changes to this file will *not* take immediate effect (this is the 1%
incompatibility between mcron and Vixie cron); you may want to add a comment
to this file with a note to this effect. Alternatively, use the new mcron
program, it's better!
If you don't want to clobber your existing cron executables, you can specify
the --program-prefix option to configure with a prefix ending in a
non-alphabetic character, for example "m.", and then run the programs as
m.mcron, m.cron and m.crontab.
If you don't want to clobber your existing cron executables, you can specify the
--program-prefix option to configure with a prefix ending in a non-alphabetic
character, for example "m.", and then run the programs as m.mcron, m.cron and
m.crontab.
----------------------------------------------------------------------
See the file INSTALL for building and installation instructions.
See the file INSTALL for generic building and installation instructions.
After installation, read the info file for full instructions for use (type
`info mcron' at the command line).
@ -57,7 +49,25 @@ After installation, read the info file for full instructions for use (type
Known bugs are noted in the BUGS file, and features which might be implemented
sometime sooner or later are noted in the TODO file.
Please send all other bug reports by electronic mail to:
Please send all other bug reports either via Savannah at
https://savannah.nongnu.org/bugs/?func=addbug&group=mcron
or by electronic mail to:
dale_mellor@users.sourceforge.net
Mcron is free software. See the file COPYING for copying conditions.
The mcron development home page is at http://www.nongnu.org/mcron.
_______________________________________________________________________________
Copyright (C) 2003 Dale Mellor
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
copyright notice and this permission notice are preserved,
thus giving the recipient permission to redistribute in turn.
Permission is granted to distribute modified versions
of this document, or of portions of it,
under the above conditions, provided also that they
carry prominent notices stating who last changed them.

57
TODO
View file

@ -1,47 +1,66 @@
-*-text-*-
Copyright (C) 2003 Dale Mellor
See the end for copying conditions.
Maybe in the near future...
* Logging.
* Logging.
* Check POSIX compliance.
* Check POSIX compliance (should be okay if Vixie cron was okay).
* Work out how to give each user his own closure (or environment or module)
for his configuration files so that he can't mess the core or other
users' files up. Then allow scheme code in the system crontabs.
* Move the code into modules so that it can be incorporated directly into
other programs.
There are no plans to actually do the following any time soon...
* Develop at, batch modes of operation.
* Develop at and batch modes of operation.
* Make compatibilities with other crons (BSD, SYSV, Solaris, Dillon's, ...)
* Make compatibilities with other crons (BSD, SYSV, Solaris, Dillon's, ...)
* Port to BSD, other operating systems.
* Port to BSD, other operating systems.
* Full security audit for Vixie mode.
* Move internal functions into a namespace, or provide alternative
environments, such that configuration files cannot interfere with mcron
itself.
* Full security audit for Vixie mode.
Quite likely to happen if version 2.0 ever materializes...
* Split program into Vixie and mcron separates (should streamline mcron
code by a factor of three; removes need for security audit).
* Split program into Vixie and mcron separates (should streamline mcron code
by a factor of three; removes need for security audit).
* UNIX or TCP socket will allow interrogation and control of a running
* UNIX or TCP socket will allow interrogation and control of a running
daemon (should be more reliable, efficient and useful than using the
SIGHUP-/var/cron/update method). (I did already try this but, as with
processes, Guile's use of threads falls over.)
SIGHUP-/var/cron/update method).
May happen if version 2.0 ever materializes...
* Add anacron functionality (run missed jobs if the daemon is stopped, for
* Add anacron functionality (run missed jobs if the daemon is stopped, for
example if a personal computer does not run 24 hours a day).
* TCP socket to allow control via HTTP (web browser interface). Or maybe
* TCP socket to allow control via HTTP (web browser interface). Or maybe
just CGI personality.
* GTK+/Bononbo interface.
* GTK+/Bononbo/Gnome2 interface.
________________________________________________________________________________
Copyright (C) 2003 Dale Mellor
Permission is granted to anyone to make or distribute verbatim copies of this
document as received, in any medium, provided that the copyright notice and
this permission notice are preserved, thus giving the recipient permission to
redistribute in turn.
Permission is granted to distribute modified versions of this document, or of
portions of it, under the above conditions, provided also that they carry
prominent notices stating who last changed them.

View file

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT(mcron, 0.99.1, dale_mellor@users.sourceforge.net)
AC_INIT(mcron, 0.99.2, dale_mellor@users.sourceforge.net)
AM_INIT_AUTOMAKE
@ -21,25 +21,6 @@ fi
AC_SUBST(CONFIG_DEBUG)
AC_MSG_CHECKING([whether the (broken) Vixie programs are requested])
AC_ARG_ENABLE(vixie,
AC_HELP_STRING([--enable-vixie],
[enable installation of cron and crontab programs]),
CONFIG_ENABLE_VIXIE=$enableval,
CONFIG_ENABLE_VIXIE=no)
AC_MSG_RESULT($CONFIG_ENABLE_VIXIE)
AC_SUBST(CONFIG_ENABLE_VIXIE)
# We substitute the following commands into the makefile by configure, because
# automake is confused by the ifeq command.
IFEQ_VIXIE="ifeq (\$(CONFIG_ENABLE_VIXIE), yes)"
AC_SUBST(IFEQ_VIXIE)
ENDIF="endif"
AC_SUBST(ENDIF)
AC_PROG_CC
GUILE_PROGS
GUILE_FLAGS
@ -76,7 +57,9 @@ else
fi
SENDMAIL=$ac_cv_prog_SENDMAIL
# This is to support `make DESTDIR=...'
real_program_prefix=`echo $program_prefix | sed s/NONE//`
AC_SUBST(real_program_prefix)

View file

@ -30,15 +30,10 @@
(define (hit-server user-name)
(catch #t (lambda ()
(let ((server-pid (with-input-from-file "/var/run/cron.pid"
(lambda () (string->number (read-line))))))
(catch #t (lambda ()
(with-output-to-file "/var/cron/update" (lambda ()
(display user-name)(newline))))
(lambda (key . args)
(display "Cannot write to /var/cron/update.\n")
(primitive-exit 14)))
(kill server-pid SIGHUP)))
(let* ((socket (socket AF_UNIX SOCK_STREAM 0)))
(connect socket AF_UNIX "/var/cron/socket")
(display user-name socket)
(close socket)))
(lambda (key . args)
(display "Warning: a cron daemon is not running.\n"))))
@ -145,14 +140,13 @@
;; crontab, wake the cron daemon up, and remove the temporary file.
((option-ref options 'edit #f)
(let ((temp-file (string-append "/tmp/crontab." (number->string (getpid))))
(editor (cond ((getenv "VISUAL") (getenv "VISUAL"))
((getenv "EDITOR") (getenv "EDITOR"))
(else "vi"))))
(let ((temp-file (string-append "/tmp/crontab." (number->string (getpid)))))
(catch #t (lambda () (copy-file crontab-file temp-file))
(lambda (key . args) (with-output-to-file temp-file noop)))
(chown temp-file (getuid) (getgid))
(system (string-append editor " " temp-file))
(system (string-append (or (getenv "VISUAL") (getenv "EDITOR") "vi")
" "
temp-file))
(read-vixie-file temp-file)
(copy-file temp-file crontab-file)
(delete-file temp-file)

View file

@ -41,27 +41,21 @@ mcron.c : config.scm mcron.scm vixie.scm environment.scm email.scm crontab.scm \
@rm -f mcron.escaped.scm > /dev/null 2>&1
install-exec-local:
@IFEQ_VIXIE@
@if [ `id -u` -ne 0 ]; then \
echo "*** MUST BE ROOT TO INSTALL MCRON ***"; \
exit 1; \
fi
@ENDIF@
#full program prefix
fpp = $(DESTDIR)$(bindir)/@real_program_prefix@
install-exec-hook:
@IFEQ_VIXIE@
@rm -f $(fpp)cron$(EXEEXT) > /dev/null 2>&1
@$(INSTALL) --mode='u=rwx' mcron$(EXEEXT) $(fpp)cron$(EXEEXT)
@rm -f $(fpp)crontab$(EXEEXT) > /dev/null 2>&1
@$(INSTALL) --mode='u=rwxs,og=rx' mcron$(EXEEXT) $(fpp)crontab$(EXEEXT)
@ENDIF@
rm -f $(fpp)cron$(EXEEXT) > /dev/null 2>&1
$(INSTALL) --mode='u=rwx' mcron$(EXEEXT) $(fpp)cron$(EXEEXT)
rm -f $(fpp)crontab$(EXEEXT) > /dev/null 2>&1
$(INSTALL) --mode='u=rwxs,og=rx' mcron$(EXEEXT) $(fpp)crontab$(EXEEXT)
./mkinstalldirs -m 'u=rwx' /var/cron
./mkinstalldirs -m 'u=rwx,og=rx' /var/run
uninstall-hook:
@IFEQ_VIXIE@
@rm -f $(fpp){cron,crontab}$(EXEEXT)
@ENDIF@
rm -f $(fpp){cron,crontab}$(EXEEXT)

View file

@ -1,3 +1,4 @@
/* -*-c-*- */
/*
* Copyright (C) 2003 Dale Mellor
*
@ -69,16 +70,6 @@ void react_to_terminal_signal (int sig)
/* This is a function designed to be installed as a signal handler. It calls the
scheme procedure to do all the work (see mcron.scm for details). */
void react_to_hup_signal (int sig)
{
scm_eval_string (scm_take0str ("(process-hup)") );
}
/* This is a function designed to be callable from scheme, and sets up all the
signal handlers required by the cron personality. */
@ -90,10 +81,7 @@ SCM set_cron_signals ()
sigaction (SIGTERM, &sa, 0);
sigaction (SIGINT, &sa, 0);
sigaction (SIGQUIT, &sa, 0);
static struct sigaction hup; hup = sa;
hup.sa_handler = react_to_hup_signal;
sigaction (SIGHUP, &hup, 0);
sigaction (SIGHUP, &sa, 0);
return SCM_BOOL_T;
}

270
mcron.scm
View file

@ -85,6 +85,7 @@
(remove (single-char #\r) (value #f))))
(else `((schedule (single-char #\s) (value optional))
(daemon (single-char #\d) (value #f))
(noetc (single-char #\n) (value #f))
(stdin (single-char #\i) (value #t)
(predicate
,(lambda (value)
@ -142,7 +143,9 @@ reading all the information in the users' crontabs and in /etc/crontab.\n
-v, --version Display version\n
-h, --help Display this help message\n
-s, --schedule[=COUNT] Display the next COUNT jobs (default 8) that\n
will be run by cron")
will be run by cron\n
-n, --noetc Do not check /etc/crontab for updates (HIGHLY\n
RECOMMENDED).")
('crontab
(string-append " [-u user] file\n"
@ -168,52 +171,13 @@ Report bugs to " config-package-bugreport ".\n
;; running.
(define (delete-run-file)
(catch #t (lambda () (delete-file "/var/run/cron.pid"))
(lambda (key . args) #t))
(catch #t (lambda () (delete-file "/var/run/cron.pid")
(delete-file "/var/cron/socket"))
noop)
(quit))
;; Every time a SIGHUP is received from a crontab process, we read the
;; /var/cron/update file for a user name (he whose crontab has been modified)
;; and add it to this list (thus it may be regarded as a deferred update list).
(define hup-received-for '())
;; Two arbiters to control access to the above list. When an interrupt is
;; received, the list will only be modified if pending-lock is available. If it
;; is not, then the interrupt routine will lock interrupt-required and return
;; immediately to the system, which should at convenient times check this lock
;; and send a SIGHUP to the process to re-run the interrupt routine (obviously,
;; if the main program locks pending-lock (or leaves locked) and issues an
;; interrupt the interrupt routine will be a no-op).
(define pending-lock (make-arbiter "pending-lock"))
(define interrupt-required (make-arbiter "interrupt-required"))
;; This is called from the C front-end whenever a HUP signal is received. We
;; read the name of the user whose crontab has been modified, add his name to
;; the list of pending requests, and remove the update file as an
;; acknowledgement that we received the signal.
;;
;; ! We should put a warning in a log file if we receive a HUP and the update
;; file is not present.
(define (process-hup)
(if (try-arbiter pending-lock)
(begin
(with-input-from-file "/var/cron/update" (lambda ()
(set! hup-received-for (append hup-received-for (list (read-line))))))
(delete-file "/var/cron/update")
(release-arbiter pending-lock))
(try-arbiter interrupt-required)))
;; Setup the cron process, if appropriate. If there is already a
;; /var/run/cron.pid file, then we must assume a cron daemon is already running
;; and refuse to start another one.
@ -409,7 +373,7 @@ Report bugs to " config-package-bugreport ".\n
;; The list of all jobs known to the system. Each element of the list is
;;
;; (vector user next-time-function action environment next-time)
;; (vector user next-time-function action environment displayable next-time)
;;
;; where action may be a string (indicating a shell command) or a list
;; (indicating scheme code) or a procedure, and the environment is an alist of
@ -418,7 +382,8 @@ Report bugs to " config-package-bugreport ".\n
;; running of a cron process (i.e. all the others are set once and for all at
;; configuration time).
(define job-list '())
(define system-job-list '())
(define user-job-list '())
@ -428,8 +393,11 @@ Report bugs to " config-package-bugreport ".\n
(define (job:next-time-function job) (vector-ref job 1))
(define (job:action job) (vector-ref job 2))
(define (job:environment job) (vector-ref job 3))
(define (job:next-time job) (vector-ref job 4))
(define (job:set-next-time! job time) (vector-set! job 4 time))
(define (job:displayable job) (vector-ref job 4))
(define (job:next-time job) (vector-ref job 5))
(define (job:advance-time! job)
(set! current-action-time (job:next-time job))
(vector-set! job 5 ((job:next-time-function job) current-action-time)))
@ -480,7 +448,9 @@ Report bugs to " config-package-bugreport ".\n
;; important so that the entries in the system crontab /etc/crontab finish up at
;; the front of the list when we scan that file).
(define (job time-proc action)
(define configuration-source 'user)
(define (job time-proc action . displayable)
(let ((action (cond ((procedure? action) action)
((list? action) (lambda () (primitive-eval action)))
((string? action) (lambda () (system action)))
@ -498,14 +468,29 @@ Report bugs to " config-package-bugreport ".\n
(display "job: invalid first argument (next-time-function; should ")
(display "be function, string or list)")
(primitive-exit 3)))))
(set! job-list (cons (vector configuration-user
time-proc
action
(list-copy current-environment-mods)
(time-proc current-action-time))
job-list))))
(primitive-exit 3))))
(displayable
(cond ((not (null? displayable)) (car displayable))
((procedure? action) "Lambda function")
((string? action) action)
((list? action) (with-output-to-string
(lambda () (display action)))))))
(if (eq? configuration-source 'user)
(set! user-job-list (cons (vector configuration-user
time-proc
action
(list-copy current-environment-mods)
displayable
(time-proc current-action-time))
user-job-list))
(set! system-job-list (cons (vector configuration-user
time-proc
action
(list-copy current-environment-mods)
displayable
(time-proc current-action-time))
system-job-list)))))
;;----------------------------------------------------------------------
@ -578,7 +563,7 @@ Report bugs to " config-package-bugreport ".\n
;; Procedure to check that a user name is the the passwd database (it may happen
;; Procedure to check that a user name is in the passwd database (it may happen
;; that a user is removed after creating a crontab). If the user name is valid,
;; the full passwd entry for that user is returned to the caller.
@ -606,7 +591,7 @@ Report bugs to " config-package-bugreport ".\n
(catch #t (lambda ()
(let ((directory (opendir "/var/cron/tabs")))
(do ((file-name (readdir directory) (readdir directory)))
((eof-object? file-name) (closedir directory))
((eof-object? file-name))
(and-let* ((user (valid-user file-name)))
(set! configuration-user user)
(read-vixie-file (string-append "/var/cron/tabs/"
@ -617,13 +602,6 @@ Report bugs to " config-package-bugreport ".\n
;; The head of the jobs list will contain the jobs specified in /etc/crontab,
;; and this variable tells us how long that head is.
(define system-jobs 0)
;; Having defined all the necessary procedures for scanning various sets of
;; files, we perform the actual configuration of the program depending on the
;; personality we are running as. If it is mcron, we either scan the files
@ -639,10 +617,24 @@ Report bugs to " config-package-bugreport ".\n
(option-ref options '() '()))))
('cron (process-files-in-system-directory)
(let ((start-length (length job-list)))
(read-vixie-file "/etc/crontab" parse-system-vixie-line)
(set! system-jobs (- (length job-list) start-length)))))
(set! configuration-source 'system)
(read-vixie-file "/etc/crontab" parse-system-vixie-line)
(set! configuration-source 'user)))
(if (eq? command-type 'cron)
(if (not (option-ref options 'noetc #f))
(begin
(display
"WARNING: cron will check for updates to /etc/crontab EVERY MINUTE. If you do\n
not use this file, or you are prepared to manually restart cron whenever you\n
make a change, then it is HIGHLY RECOMMENDED that you use the --noetc\n
option.\n")
(set! configuration-user (getpw "root"))
(job '(- (next-minute-from (next-minute)) 6)
check-system-crontab
"/etc/crontab update checker."))))
;;----------------------------------------------------------------------
@ -670,27 +662,29 @@ Report bugs to " config-package-bugreport ".\n
;; recurse the list.
(define (find-next-jobs)
(let ((job-list (append system-job-list user-job-list)))
(if (null? job-list)
(if (eq? command-type 'mcron)
(begin (display "Nothing to do.\n")
(primitive-exit 5))
(cons #f '()))
(let ((next-time 2000000000)
(next-jobs-list '()))
(if (null? job-list)
(if (eq? command-type 'mcron)
(begin (display "Nothing to do.\n")
(primitive-exit 5))
(cons #f '()))
(let ((next-time (job:next-time (car job-list)))
(next-jobs-list (list (car job-list))))
(for-each
(lambda (job)
(let ((this-time (job:next-time job)))
(cond ((< this-time next-time)
(set! next-time this-time)
(set! next-jobs-list (list job)))
((eqv? this-time next-time)
(set! next-jobs-list (cons job next-jobs-list))))))
job-list)
(for-each
(lambda (job)
(let ((this-time (job:next-time job)))
(cond ((< this-time next-time)
(set! next-time this-time)
(set! next-jobs-list (list job)))
((eqv? this-time next-time)
(set! next-jobs-list (cons job next-jobs-list))))))
(cdr job-list))
(cons next-time next-jobs-list))))
(cons next-time next-jobs-list)))))
@ -715,8 +709,9 @@ Report bugs to " config-package-bugreport ".\n
(let* ((next-jobs (find-next-jobs))
(date-string (strftime "%c\n" (localtime (car next-jobs)))))
(for-each (lambda (job) (display date-string)
(write (job:action job))
(newline)(newline))
(display (job:displayable job))
(newline)(newline)
(job:advance-time! job))
(cdr next-jobs))))
(quit))
@ -748,9 +743,7 @@ Report bugs to " config-package-bugreport ".\n
(begin
(set! number-children (+ number-children 1))
(set! current-action-time (job:next-time job))
(job:set-next-time! job
((job:next-time-function job)
current-action-time)))))
(job:advance-time! job))))
jobs-list))
@ -770,6 +763,39 @@ Report bugs to " config-package-bugreport ".\n
(define fd-list '())
(if (eq? command-type 'cron)
(let ((socket (socket AF_UNIX SOCK_STREAM 0)))
(bind socket AF_UNIX "/var/cron/socket")
(listen socket 5)
(set! fd-list (list socket))))
(define (process-update-request)
(let* ((socket (car (accept (car fd-list))))
(user-name (read-line socket)))
(close socket)
(set! configuration-time (current-time))
(if (string=? user-name "/etc/crontab")
(begin
(set! system-job-list '())
(set! configuration-source 'system)
(read-vixie-file "/etc/crontab" parse-system-vixie-line)
(set! configuration-source 'user))
(let ((user (getpw user-name)))
(set! user-job-list
(remove (lambda (job) (eqv? (passwd:uid user)
(passwd:uid (job:user job))))
user-job-list))
(set! configuration-user user)
(read-vixie-file (string-append "/var/cron/tabs/" user-name))))))
;; Now the main loop. Take the current time. Loop over all job specifications,
;; get a list of the next ones to run (may be more than one). Set an alarm and
;; go to sleep. When we wake, run the jobs. Repeat ad infinitum.
@ -778,36 +804,6 @@ Report bugs to " config-package-bugreport ".\n
(let main-loop ()
(release-arbiter pending-lock)
;; Check for any pending updates to the configuration files (as notified by
;; crontab). If one is seen, remove all work from the job-list that belongs to
;; this user, set up the global variables current-action-time and
;; configuration-user appropriately, and then process the new configuration
;; file for the user.
(do () ((and (if (release-arbiter interrupt-required)
(begin (kill (getpid) SIGHUP) #f)
#t)
(null? hup-received-for)))
(try-arbiter pending-lock)
(let ((user (car hup-received-for)))
(set! hup-received-for (cdr hup-received-for))
(release-arbiter pending-lock)
(set! configuration-user (getpw user))
(let ((uid (passwd:uid configuration-user))
(old-job-list job-list))
(set! current-action-time (current-time))
(set! job-list
(append
(list-head old-job-list system-jobs)
(begin (set! job-list '())
(read-vixie-file (string-append "/var/cron/tabs/" user))
job-list)
(remove (lambda (job) (eqv? (passwd:uid (job:user job)) uid))
(list-tail old-job-list system-jobs)))))))
;; Compute the amount of time that we must sleep until the next job is due to
;; run.
@ -817,27 +813,13 @@ Report bugs to " config-package-bugreport ".\n
(sleep-time (if next-time (- next-time (current-time))
#f)))
;; If an update signal has just come in, or there are no current jobs and a
;; pause operation has been interrupted (presumably by a SIGHUP), or the
;; sleep operation has been interrupted (presumably by a SIGHUP), then undo
;; the latest time calculations and jump back to the top of the loop where
;; the pending updates will be dealt with.
;;
;; Otherwise, when we wake from our sleep, first try to collect as many
;; child zombies as possible from previous job runs, then run the current
;; set of jobs (on the next-jobs-list).
(if (and (null? hup-received-for)
;; ! If a signal occurs now, we won't see it
;; until the next signal.
(eqv? 0 (cond ((not sleep-time) (pause) 1)
((> sleep-time 0) (sleep sleep-time))
(else 0))))
(if (and (or (not sleep-time) (> sleep-time 0))
(not (null? (car (select fd-list '() '() sleep-time)))))
(process-update-request)
(run-jobs next-jobs-list)))
(do () ((or (<= number-children 0)
(eqv? (car (waitpid WAIT_ANY WNOHANG)) 0)))
(set! number-children (- number-children 1)))
(do () ((or (<= number-children 0)
(eqv? (car (waitpid WAIT_ANY WNOHANG)) 0)))
(set! number-children (- number-children 1)))
(main-loop))
(main-loop))

View file

@ -10,12 +10,6 @@
This file documents the @code{mcron} command for running jobs at
scheduled times.
IMPORTANT NOTICE:
IT IS VERY LIKELY THAT THE CRON AND CRONTAB PROGRAMS DESCRIBED IN THIS
MANUAL HAVE NOT BEEN INSTALLED IN YOUR SYSTEM (THEY ARE CURRENTLY
BROKEN). THUS, ONLY THE MCRON PERSONALITY IS CURRENTLY AVAILABLE FOR
USE.
Copyright (C) 2003 Dale Mellor
This is free software. See the source files for the terms of the
copyright.
@ -254,7 +248,7 @@ then run the command @code{mcron}.
Alternatively (full compatibility with Vixie cron), set your
environment variable @code{EDITOR} to your favorite editor, run
@code{crontab -e}, put the above line into the edit buffer, save and
exit. For this to work the @code{crond} daemon must be already running
exit. For this to work the @code{cron} daemon must be already running
on your system, by root.
@node Syntax, Invoking, Simple examples, Top
@ -272,8 +266,9 @@ on your system, by root.
@findex job
In Guile-formatted configuration files each command that needs
executing is introduced with the @code{job} function. This function
always takes exactly two arguments, the first a time specification,
and the second a command specification.
always takes two arguments, the first a time specification, and the
second a command specification. An optional third argument may contain
a string to display when this job is listed in a schedule.
@cindex time specification, procedure
@cindex procedure time specification
@ -521,23 +516,19 @@ there is a bug in the program. This section is also copied verbatim
from Paul Vixie's documentation for his cron program, and his
copyright notice is duly reproduced below.
@cindex /etc/crontab
@cindex system crontab
@cindex incompatibility
@cindex vixie incompatibility
There is one single exception to the above. @strong{Mcron does not
notice changes made to /etc/crontab}. If a change is made, then it is
necessary to kill the cron daemon and restart it for the change to
take effect.
There are three problems with this specification.
@cindex zero'th day of month
@cindex 0'th day of month
1. It is allowed to specify days of the month in the range 0-31. What
does it mean to specify day 0? Well, if I'm not mistaken mcron will
run the command on the last day of the previous month (but don't rely
on this). I don't know what Vixie cron would have done.
does it mean to specify day 0? Looking at the Vixie source code, it
seems that if this date appears as part of a list, it has no
effect. However, if it appears on its own, the effect is to say
``don't run on any particular day of the month, only take the week-day
specification into account.'' Mcron has been coded to mimic this
behaviour as a special case (unmodified mcron logic implies that this
date specification would cause jobs to run on the last day of the
previous month).
@cindex thirteenth month of year
@cindex 13th month of year
@ -901,21 +892,19 @@ standard output.
@cindex running crond
@cindex /var/cron/tabs
@cindex /var/run/cron.pid
If the program runs by the name of cron or crond, then it will read
all the files in /var/cron/tabs (which should only be readable by
root) and the file /etc/crontab, and then detaches itself from the
terminal to live forever as a daemon process. Additionally, it puts
its PID into /var/run/cron.pid, and listens for SIGHUPs, in which case
it will look for a file /var/cron/update which should contain a single
username, and the program will re-read that user's crontab. This is
for correct functioning with the crontab program.
If the program runs by the name of @code{cron} or @code{crond}, then
it will read all the files in @code{/var/cron/tabs} (which should only
be readable by root) and the file @code{/etc/crontab}, and then
detaches itself from the terminal to live forever as a daemon
process. Additionally, it creates a UNIX socket at
@code{/var/cron/socket}, and listens for messages sent to that socket
consisting of a user name whose crontabs have been changed. In this
case, the program will re-read that user's crontab. This is for
correct functioning with the crontab program.
@cindex /etc/crontab
@cindex incompatibility
@strong{NOTE} that it does not detect changes in /etc/crontab; if this file
is ever changed then it will be necessary to kill and then restart the
daemon. This is the one and only incompatibility with Vixie's cron
program.
Further, if the @code{--noetc} option was not used, a job is scheduled
to run every minute to check if /etc/crontab has been modified
recently. If so, this file will also be re-read.
The options which may be used with this program are as follows.
@ -939,6 +928,32 @@ information about the version and copyright for the current program.
This causes a short but complete usage message to be displayed on
standard output.
@item -s [count]
@itemx --schedule[=count]
@cindex printout of jobs schedule
@cindex schedule of jobs, listing
@cindex options, schedule
@cindex options, -s
@cindex -s option
@cindex --schedule option
With this option specified no commands are run. Instead, the program
computes the times the commands would be run and prints the
information to the screen, and then immediately exits.
The count, if supplied, indicates the number of commands to
display. The default value is 8.
@cindex -n option
@cindex --noetc option
@cindex options, -n
@cindex options, --noetc
@item -n
@itemx --noetc
This tells cron not to add a job to the system which wakes up every
minute to check for modifications to @code{/etc/crontab}. It is
recommended that this option be used (and further that the
@code{/etc/crontab} file be taken off the system altogether!)
@end table
@node Running crontab, Exit codes, Running cron or crond, Invoking

View file

@ -25,7 +25,8 @@
(use-modules (ice-9 regex) (ice-9 rdelim) (srfi srfi-13) (srfi srfi-14))
(use-modules (ice-9 regex) (ice-9 rdelim)
(srfi srfi-1) (srfi srfi-13) (srfi srfi-14))
@ -136,7 +137,7 @@
(define (interpolate-weekdays mday-list wday-list month year)
(let ((t (localtime 0)))
(set-tm:mday t 1)
(set-tm:mon t month)
(set-tm:mon t month)
(set-tm:year t year)
(let ((first-day (tm:wday (cdr (mktime t)))))
(apply append
@ -278,7 +279,9 @@
;; which references to a time-spec-list will be bound. It will be used by the
;; returned procedure [3] to compute the next time a function should run. Any
;; 7's in the weekday component of the list (the last one) are folded into 0's
;; (both values represent sunday) [2].
;; (both values represent sunday) [2]. Any 0's in the month-day component of the
;; list are removed (this allows a solitary zero to be used to indicate that
;; jobs should only run on certain days of the _week_) [2.1].
;;
;; The returned procedure itself:-
;;
@ -306,8 +309,8 @@
(list-ref tokens (vector-ref x 0))
(vector-ref x 1)
(vector-ref x 2))
(vector-ref x 3)
(vector-ref x 4)))
(vector-ref x 3)
(vector-ref x 4)))
;; token range-top+1 getter setter
`( #( 0 0 60 ,tm:min ,set-tm:min )
#( 1 0 24 ,tm:hour ,set-tm:hour )
@ -320,6 +323,12 @@
(map (lambda (time-spec)
(if (eqv? time-spec 7) 0 time-spec))
(vector-ref (car (last-pair time-spec-list)) 0))) ;; [2]
(vector-set! (caddr time-spec-list)
0
(remove (lambda (day) (eqv? day 0))
(vector-ref (caddr time-spec-list) 0))) ;; [2.1]
(lambda (current-time) ;; [3]
(let ((time (localtime current-time))) ;; [4]
@ -328,15 +337,17 @@
(time-spec:list (cadddr time-spec-list))))
(begin
(nudge-month! time (cdddr time-spec-list))
(set-tm:mday time 0)
(set-tm:hour time -1)
(set-tm:min time -1)))
(if (not (member (tm:mday time) ;; !!
(time-spec:list (caddr time-spec-list))))
(set-tm:mday time 0)))
(if (or (eqv? (tm:mday time) 0)
(not (member (tm:mday time)
(interpolate-weekdays
(time-spec:list (caddr time-spec-list))
(time-spec:list (caddr (cddr time-spec-list)))
(tm:mon time)
(tm:year time)))))
(begin
(nudge-day! time (cddr time-spec-list))
(set-tm:hour time -1)
(set-tm:min time -1)))
(set-tm:hour time -1)))
(if (not (member (tm:hour time)
(time-spec:list (cadr time-spec-list))))
(begin
@ -367,7 +378,8 @@
(if (not match) (begin (display "Bad job line in Vixie file.\n")
(primitive-exit 10)))
(job (match:substring match 1)
(lambda () (with-mail-out (match:substring match 3))))))
(lambda () (with-mail-out (match:substring match 3)))
(match:substring match 3))))
@ -379,13 +391,14 @@
"([[:alpha:]][[:alnum:]_]*)[[:space:]]+(.*)$")))
(define (parse-system-vixie-line line)
(let ((match (regexp-exec parse-user-vixie-line-regexp line)))
(let ((match (regexp-exec parse-system-vixie-line-regexp line)))
(if (not match) (begin (display "Bad job line in /etc/crontab.\n")
(primitive-exit 11)))
(set! configuration-user (passwd (match:substring match 3)))
(set! configuration-user (getpw (match:substring match 3)))
(job (match:substring match 1)
(lambda () (with-mail-out (match:substring match 4)
(passwd:name configuration-user))))))
(passwd:name configuration-user)))
(match:substring match 4))))
@ -416,10 +429,10 @@
((eof-object? line))
;; If the line ends with \, append the next line.
(while ((and (>= (string-length line) 1)
(char=? (string-ref line
(- (string-length line) 1))
#\\)))
(while (and (>= (string-length line) 1)
(char=? (string-ref line
(- (string-length line) 1))
#\\))
(let ((next-line (read-line port)))
(if (eof-object? next-line)
(set! next-line ""))
@ -449,3 +462,20 @@
(read-vixie-port port)
(read-vixie-port port (car parse-vixie-line)))
(close port)))))
;; A procedure which determines if the /etc/crontab file has been recently
;; modified, and, if so, signals the main routine to re-read the file. We run
;; under the with-mail-to command so that the process runs as a child,
;; preventing lockup. If cron is supposed to check for updates to /etc/crontab,
;; then this procedure will be called about 5 seconds before every minute.
(define (check-system-crontab)
(with-mail-out (lambda ()
(let ((mtime (stat:mtime (stat "/etc/crontab"))))
(if (> mtime (- (current-time) 60))
(let ((socket (socket AF_UNIX SOCK_STREAM 0)))
(connect socket AF_UNIX "/var/cron/socket")
(display "/etc/crontab" socket)
(close socket)))))))