Taken on board suggestions of Mathieu Lirzin as per e-mails to the bug-mcron@gnu.org mailing list around September 2015.
This commit is contained in:
		
					parent
					
						
							
								024027ae2d
							
						
					
				
			
			
				commit
				
					
						c0a6eb14c2
					
				
			
		
					 20 changed files with 1155 additions and 664 deletions
				
			
		
							
								
								
									
										13
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,9 +1,20 @@ | ||||||
| *~ | *~ | ||||||
|  | *.o | ||||||
|  | *.go | ||||||
| .deps | .deps | ||||||
| INSTALL | INSTALL | ||||||
| aclocal.m4 | aclocal.m4 | ||||||
| autom4te.cache | autom4te.cache | ||||||
|  | /build-aux/compile | ||||||
|  | /build-aux/config.guess | ||||||
|  | /build-aux/config.sub | ||||||
|  | /build-aux/depcomp | ||||||
|  | /build-aux/install-sh | ||||||
|  | /build-aux/mdate-sh | ||||||
|  | /build-aux/missing | ||||||
|  | /build-aux/texinfo.tex | ||||||
| compile | compile | ||||||
|  | config.cache | ||||||
| config.log | config.log | ||||||
| config.scm | config.scm | ||||||
| config.status | config.status | ||||||
|  | @ -20,8 +31,6 @@ install-sh | ||||||
| makefile | makefile | ||||||
| makefile.in | makefile.in | ||||||
| /mcron | /mcron | ||||||
| mcron.c |  | ||||||
| /mdate-sh | /mdate-sh | ||||||
| *.o |  | ||||||
| missing | missing | ||||||
| texinfo.tex | texinfo.tex | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								AUTHORS
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								AUTHORS
									
										
									
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| Authors of GNU mcron. | Authors of GNU mcron. | ||||||
| 
 | 
 | ||||||
|   Copyright (C) 2003, 2005, 2006  Dale Mellor |   Copyright (C) 2003, 2005, 2006, 2015  Dale Mellor | ||||||
| 
 | 
 | ||||||
|   Copying and distribution of this file, with or without modification, |   Copying and distribution of this file, with or without modification, | ||||||
|   are permitted in any medium without royalty provided the copyright |   are permitted in any medium without royalty provided the copyright | ||||||
|  | @ -16,3 +16,6 @@ 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, |     configuration files is copied verbatim from Paul Vixie's own distribution, | ||||||
|     on the understanding that this is permitted under his copyright notice, |     on the understanding that this is permitted under his copyright notice, | ||||||
|     which is reproduced in its entirety in this section of the manual. |     which is reproduced in its entirety in this section of the manual. | ||||||
|  | 
 | ||||||
|  | Further contributions have been received from Sergey Poznyakoff and Mathieu | ||||||
|  |     Lirzin, and incorporated where appropriate. | ||||||
|  |  | ||||||
							
								
								
									
										41
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,3 +1,16 @@ | ||||||
|  | 2015-10-22  Dale Mellor  <dale@rdmp.org> | ||||||
|  | 
 | ||||||
|  | 	Taken on board suggestions of Mathieu Lirzin.  This is mostly | ||||||
|  | 	cosmetic code re-arranging and refresh for newer features of | ||||||
|  | 	guile, but also: | ||||||
|  | 
 | ||||||
|  | 	* Eliminate the hacked embedding of the main scheme unit into the | ||||||
|  | 	C source code. | ||||||
|  | 
 | ||||||
|  | 	* Compile all the guile modules before installation. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
| 2015-07-01  Mathieu Lirzin  <mthl@openmailbox.org> | 2015-07-01  Mathieu Lirzin  <mthl@openmailbox.org> | ||||||
| 
 | 
 | ||||||
| 	* configure.ac: Fix package name and bug reports email address. | 	* configure.ac: Fix package name and bug reports email address. | ||||||
|  | @ -10,7 +23,7 @@ | ||||||
| 	* .gitignore: Ignore 'mcron' only in the top-level directory. | 	* .gitignore: Ignore 'mcron' only in the top-level directory. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2014-05-25  Dale Mellor <dale_mellor@users.sourceforge.net> | 2014-05-25  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* Juggled build infrastructure so that we can make the minimal man | 	* Juggled build infrastructure so that we can make the minimal man | ||||||
| 	page in the proper autotools way. | 	page in the proper autotools way. | ||||||
|  | @ -18,14 +31,14 @@ | ||||||
| 	* configure.ac: version to 1.0.8. | 	* configure.ac: version to 1.0.8. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2014-04-28  Dale Mellor <dale_mellor@users.sourceforge.net> | 2014-04-28  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* We now run against, and require, guile-2.0. | 	* We now run against, and require, guile-2.0. | ||||||
| 
 | 
 | ||||||
| 	* configure.ac: version to 1.0.7. | 	* configure.ac: version to 1.0.7. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2012-02-04  Dale Mellor <dale_mellor@users.sourceforge.net> | 2012-02-04  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* main.scm: added search for initial files in | 	* main.scm: added search for initial files in | ||||||
| 	$XDG_CONFIG_HOME/cron directory, defaulting to ~/.config/cron if | 	$XDG_CONFIG_HOME/cron directory, defaulting to ~/.config/cron if | ||||||
|  | @ -34,7 +47,7 @@ | ||||||
| 	standards). | 	standards). | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2010-06-13  Dale Mellor <dale_mellor@users.sourceforge.net> | 2010-06-13  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* configure.ac: added --enable-no-vixie-clobber argument to | 	* configure.ac: added --enable-no-vixie-clobber argument to | ||||||
| 	configure so that the root user can avoid overwriting a legacy | 	configure so that the root user can avoid overwriting a legacy | ||||||
|  | @ -47,7 +60,7 @@ | ||||||
| 	former is not supplied with the latest automake (1.11). | 	former is not supplied with the latest automake (1.11). | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2008-02-21  Dale Mellor <dale_mellor@users.sourceforge.net> | 2008-02-21  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* ALL FILES: Replaced version 2 GPL notices with version 3 ones. | 	* ALL FILES: Replaced version 2 GPL notices with version 3 ones. | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +71,7 @@ | ||||||
| 	* configure.ac: Bumped version to 1.0.4. | 	* configure.ac: Bumped version to 1.0.4. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2008-01-25  Dale Mellor <dale_mellor@users.sourceforge.net> | 2008-01-25  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* main.scm (command-type): Files which are listed on the command | 	* main.scm (command-type): Files which are listed on the command | ||||||
| 	line are assumed to be guile configurations if they do not end in | 	line are assumed to be guile configurations if they do not end in | ||||||
|  | @ -76,7 +89,7 @@ | ||||||
| 	* Version is currently at 1.0.3. | 	* Version is currently at 1.0.3. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2005-09-02  Dale Mellor <dale_mellor@users.sourceforge.net> | 2005-09-02  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* makefile.am, mcron.c.template (main): Modified install-exec-hook | 	* makefile.am, mcron.c.template (main): Modified install-exec-hook | ||||||
| 	so that a proper installation of a Vixie-compatible cron only | 	so that a proper installation of a Vixie-compatible cron only | ||||||
|  | @ -93,7 +106,7 @@ | ||||||
| 	* Bumped version to 1.0.2. | 	* Bumped version to 1.0.2. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2004-05-15  Dale Mellor <dale_mellor@users.sourceforge.net> | 2004-05-15  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* Modified all auxiliary files to reflect that the package is now | 	* Modified all auxiliary files to reflect that the package is now | ||||||
| 	properly homed at www.gnu.org. | 	properly homed at www.gnu.org. | ||||||
|  | @ -101,7 +114,7 @@ | ||||||
| 	* Bumped version to 1.0.1. | 	* Bumped version to 1.0.1. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-12-11  Dale Mellor <dale_mellor@users.sourceforge.net> | 2003-12-11  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* Modified all auxiliary files to reflect that we are now a GNU | 	* Modified all auxiliary files to reflect that we are now a GNU | ||||||
| 	package. | 	package. | ||||||
|  | @ -109,7 +122,7 @@ | ||||||
| 	* Bumped version to 1.0.0. | 	* Bumped version to 1.0.0. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-12-07  Dale Mellor <dale_mellor@users.sourceforge.net> | 2003-12-07  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* configure.ac: Added switches for files and directories used by | 	* configure.ac: Added switches for files and directories used by | ||||||
| 	mcron: --spool-dir, --socket-file, --allow-file, --deny-file, | 	mcron: --spool-dir, --socket-file, --allow-file, --deny-file, | ||||||
|  | @ -118,14 +131,14 @@ | ||||||
| 	manual). | 	manual). | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-12-05  Dale Mellor <dale_mellor@users.sourceforge.net> | 2003-12-05  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* configure.ac: Added test for guile version >= 1.6.4. | 	* configure.ac: Added test for guile version >= 1.6.4. | ||||||
| 
 | 
 | ||||||
| 	* bumped version to 0.99.4. | 	* bumped version to 0.99.4. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-08-03  Dale Mellor <dale_mellor@users.sourceforge.net> | 2003-08-03  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
|         * Third cut, fully functional, modular, production quality, still |         * Third cut, fully functional, modular, production quality, still | ||||||
| 	needs testing... | 	needs testing... | ||||||
|  | @ -136,7 +149,7 @@ | ||||||
| 	* Bumped version to 0.99.3. | 	* Bumped version to 0.99.3. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-07-20  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 |         * Second cut, now _really_ fully functional (100% Vixie | ||||||
| 	compatible), production quality code, still needs lots of testing | 	compatible), production quality code, still needs lots of testing | ||||||
|  | @ -154,7 +167,7 @@ | ||||||
| 	* Bumped version to 0.99.2. | 	* Bumped version to 0.99.2. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 2003-06-28  Dale Mellor <dale_mellor@users.sourceforge.net> | 2003-06-28  Dale Mellor  <dale_mellor@users.sourceforge.net> | ||||||
| 
 | 
 | ||||||
| 	* First cut, fully functional, production quality code, just needs | 	* First cut, fully functional, production quality code, just needs | ||||||
| 	testing... | 	testing... | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								TODO
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								TODO
									
										
									
									
									
								
							|  | @ -1,5 +1,6 @@ | ||||||
| GNU mcron --- TODO                                  -*-text-*- | GNU mcron --- TODO                                  -*-text-*- | ||||||
| 
 | 
 | ||||||
|  |   Copyright (C) 2015  Mathieu Lirzin | ||||||
|   Copyright (C) 2003, 2005, 2006, 2014  Dale Mellor |   Copyright (C) 2003, 2005, 2006, 2014  Dale Mellor | ||||||
| 
 | 
 | ||||||
|   Copying and distribution of this file, with or without modification, |   Copying and distribution of this file, with or without modification, | ||||||
|  | @ -19,6 +20,14 @@ Maybe in the near future... | ||||||
|        core or other users' files up. Then allow scheme code in the system |        core or other users' files up. Then allow scheme code in the system | ||||||
|        crontabs. |        crontabs. | ||||||
|                |                | ||||||
|  |     * Make mcron behavior not depend on the name used to invoke it, to conform | ||||||
|  |       to GNU standards. | ||||||
|  | 
 | ||||||
|  |     * Provide a test suite using SRFI-64 API. | ||||||
|  |       <http://srfi.schemers.org/srfi-64/srfi-64.html>. | ||||||
|  | 
 | ||||||
|  |     * Internationalize Mcron using GNU Gettext and ask the Translation | ||||||
|  |       Project to handle the localization. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| There are no plans to actually do the following any time soon... | There are no plans to actually do the following any time soon... | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								configure.ac
									
										
									
									
									
								
							|  | @ -2,8 +2,7 @@ | ||||||
| # Process this file with autoconf to produce a configure script. | # Process this file with autoconf to produce a configure script. | ||||||
| 
 | 
 | ||||||
|    |    | ||||||
| #    Copyright (C) 2003, 2005, 2012, 2014  Dale Mellor | #    Copyright (C) 2003, 2005, 2012, 2014, 2015  Dale Mellor | ||||||
| #    Copyright (C) 2015  Mathieu Lirzin |  | ||||||
| #    | #    | ||||||
| #    This file is part of GNU mcron. | #    This file is part of GNU mcron. | ||||||
| #  | #  | ||||||
|  | @ -24,8 +23,13 @@ | ||||||
| AC_PREREQ(2.61) | AC_PREREQ(2.61) | ||||||
| AC_INIT([GNU Mcron], [1.0.8], [bug-mcron@gnu.org]) | AC_INIT([GNU Mcron], [1.0.8], [bug-mcron@gnu.org]) | ||||||
| AC_CONFIG_AUX_DIR([build-aux]) | AC_CONFIG_AUX_DIR([build-aux]) | ||||||
| AM_INIT_AUTOMAKE | AM_INIT_AUTOMAKE([silent-rules]) | ||||||
| 
 | 
 | ||||||
|  | # Enable silent rules by default. | ||||||
|  | AM_SILENT_RULES([yes]) | ||||||
|  | 
 | ||||||
|  | guilemoduledir="${datarootdir}/guile/site/2.0" | ||||||
|  | AC_SUBST([guilemoduledir]) | ||||||
| 
 | 
 | ||||||
| AC_MSG_CHECKING([whether debugging is requested]) | AC_MSG_CHECKING([whether debugging is requested]) | ||||||
| AC_ARG_ENABLE(debug, | AC_ARG_ENABLE(debug, | ||||||
|  | @ -45,12 +49,19 @@ AC_SUBST(CONFIG_DEBUG) | ||||||
| # We have no interest (hence a no-op), but Debian wants this. | # We have no interest (hence a no-op), but Debian wants this. | ||||||
| AC_ARG_ENABLE(maintainer-mode) | AC_ARG_ENABLE(maintainer-mode) | ||||||
| 
 | 
 | ||||||
| 
 | AC_CANONICAL_HOST | ||||||
| AC_PROG_AWK | AC_PROG_AWK | ||||||
| AC_PROG_EGREP | AC_PROG_EGREP | ||||||
| AM_PROG_CC_C_O | AM_PROG_CC_C_O | ||||||
| 
 | 
 | ||||||
| PKG_CHECK_MODULES(GUILE, guile-2.0) | PKG_CHECK_MODULES([GUILE], [guile-2.0 >= 2.0.7]) | ||||||
|  | AC_PATH_PROG([GUILE], [guile]) | ||||||
|  | 
 | ||||||
|  | # search guild | ||||||
|  | AC_PATH_PROG([GUILD], [guild]) | ||||||
|  | if test "x$GUILD" = "x"; then | ||||||
|  |    AC_MSG_ERROR(['guild' binary not found; please check your guile-2.x installation.]) | ||||||
|  | fi | ||||||
| 
 | 
 | ||||||
| # Checks for programs. | # Checks for programs. | ||||||
|    |    | ||||||
|  | @ -64,10 +75,6 @@ AC_CHECK_PROGS(HEAD, head) | ||||||
| if test "x$ac_cv_prog_HEAD" = "x"; then | if test "x$ac_cv_prog_HEAD" = "x"; then | ||||||
|    AC_MSG_ERROR(head not found) |    AC_MSG_ERROR(head not found) | ||||||
| fi | fi | ||||||
| AC_CHECK_PROGS(ED, ed) |  | ||||||
| if test "x$ac_cv_prog_ED" = "x"; then |  | ||||||
|    AC_MSG_ERROR(ed not found) |  | ||||||
| fi |  | ||||||
| AC_CHECK_PROGS(WHICH, which) | AC_CHECK_PROGS(WHICH, which) | ||||||
| if test "x$ac_cv_prog_WHICH" = "x"; then | if test "x$ac_cv_prog_WHICH" = "x"; then | ||||||
|     AC_MSG_ERROR(which not found) |     AC_MSG_ERROR(which not found) | ||||||
|  |  | ||||||
							
								
								
									
										505
									
								
								doc/fdl.texi
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								doc/fdl.texi
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,505 @@ | ||||||
|  | @c The GNU Free Documentation License. | ||||||
|  | @center Version 1.3, 3 November 2008 | ||||||
|  | 
 | ||||||
|  | @c This file is intended to be included within another document, | ||||||
|  | @c hence no sectioning command or @node. | ||||||
|  | 
 | ||||||
|  | @display | ||||||
|  | Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. | ||||||
|  | @uref{http://fsf.org/} | ||||||
|  | 
 | ||||||
|  | Everyone is permitted to copy and distribute verbatim copies | ||||||
|  | of this license document, but changing it is not allowed. | ||||||
|  | @end display | ||||||
|  | 
 | ||||||
|  | @enumerate 0 | ||||||
|  | @item | ||||||
|  | PREAMBLE | ||||||
|  | 
 | ||||||
|  | The purpose of this License is to make a manual, textbook, or other | ||||||
|  | functional and useful document @dfn{free} in the sense of freedom: to | ||||||
|  | assure everyone the effective freedom to copy and redistribute it, | ||||||
|  | with or without modifying it, either commercially or noncommercially. | ||||||
|  | Secondarily, this License preserves for the author and publisher a way | ||||||
|  | to get credit for their work, while not being considered responsible | ||||||
|  | for modifications made by others. | ||||||
|  | 
 | ||||||
|  | This License is a kind of ``copyleft'', which means that derivative | ||||||
|  | works of the document must themselves be free in the same sense.  It | ||||||
|  | complements the GNU General Public License, which is a copyleft | ||||||
|  | license designed for free software. | ||||||
|  | 
 | ||||||
|  | We have designed this License in order to use it for manuals for free | ||||||
|  | software, because free software needs free documentation: a free | ||||||
|  | program should come with manuals providing the same freedoms that the | ||||||
|  | software does.  But this License is not limited to software manuals; | ||||||
|  | it can be used for any textual work, regardless of subject matter or | ||||||
|  | whether it is published as a printed book.  We recommend this License | ||||||
|  | principally for works whose purpose is instruction or reference. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | APPLICABILITY AND DEFINITIONS | ||||||
|  | 
 | ||||||
|  | This License applies to any manual or other work, in any medium, that | ||||||
|  | contains a notice placed by the copyright holder saying it can be | ||||||
|  | distributed under the terms of this License.  Such a notice grants a | ||||||
|  | world-wide, royalty-free license, unlimited in duration, to use that | ||||||
|  | work under the conditions stated herein.  The ``Document'', below, | ||||||
|  | refers to any such manual or work.  Any member of the public is a | ||||||
|  | licensee, and is addressed as ``you''.  You accept the license if you | ||||||
|  | copy, modify or distribute the work in a way requiring permission | ||||||
|  | under copyright law. | ||||||
|  | 
 | ||||||
|  | A ``Modified Version'' of the Document means any work containing the | ||||||
|  | Document or a portion of it, either copied verbatim, or with | ||||||
|  | modifications and/or translated into another language. | ||||||
|  | 
 | ||||||
|  | A ``Secondary Section'' is a named appendix or a front-matter section | ||||||
|  | of the Document that deals exclusively with the relationship of the | ||||||
|  | publishers or authors of the Document to the Document's overall | ||||||
|  | subject (or to related matters) and contains nothing that could fall | ||||||
|  | directly within that overall subject.  (Thus, if the Document is in | ||||||
|  | part a textbook of mathematics, a Secondary Section may not explain | ||||||
|  | any mathematics.)  The relationship could be a matter of historical | ||||||
|  | connection with the subject or with related matters, or of legal, | ||||||
|  | commercial, philosophical, ethical or political position regarding | ||||||
|  | them. | ||||||
|  | 
 | ||||||
|  | The ``Invariant Sections'' are certain Secondary Sections whose titles | ||||||
|  | are designated, as being those of Invariant Sections, in the notice | ||||||
|  | that says that the Document is released under this License.  If a | ||||||
|  | section does not fit the above definition of Secondary then it is not | ||||||
|  | allowed to be designated as Invariant.  The Document may contain zero | ||||||
|  | Invariant Sections.  If the Document does not identify any Invariant | ||||||
|  | Sections then there are none. | ||||||
|  | 
 | ||||||
|  | The ``Cover Texts'' are certain short passages of text that are listed, | ||||||
|  | as Front-Cover Texts or Back-Cover Texts, in the notice that says that | ||||||
|  | the Document is released under this License.  A Front-Cover Text may | ||||||
|  | be at most 5 words, and a Back-Cover Text may be at most 25 words. | ||||||
|  | 
 | ||||||
|  | A ``Transparent'' copy of the Document means a machine-readable copy, | ||||||
|  | represented in a format whose specification is available to the | ||||||
|  | general public, that is suitable for revising the document | ||||||
|  | straightforwardly with generic text editors or (for images composed of | ||||||
|  | pixels) generic paint programs or (for drawings) some widely available | ||||||
|  | drawing editor, and that is suitable for input to text formatters or | ||||||
|  | for automatic translation to a variety of formats suitable for input | ||||||
|  | to text formatters.  A copy made in an otherwise Transparent file | ||||||
|  | format whose markup, or absence of markup, has been arranged to thwart | ||||||
|  | or discourage subsequent modification by readers is not Transparent. | ||||||
|  | An image format is not Transparent if used for any substantial amount | ||||||
|  | of text.  A copy that is not ``Transparent'' is called ``Opaque''. | ||||||
|  | 
 | ||||||
|  | Examples of suitable formats for Transparent copies include plain | ||||||
|  | ASCII without markup, Texinfo input format, La@TeX{} input | ||||||
|  | format, SGML or XML using a publicly available | ||||||
|  | DTD, and standard-conforming simple HTML, | ||||||
|  | PostScript or PDF designed for human modification.  Examples | ||||||
|  | of transparent image formats include PNG, XCF and | ||||||
|  | JPG@.  Opaque formats include proprietary formats that can be | ||||||
|  | read and edited only by proprietary word processors, SGML or | ||||||
|  | XML for which the DTD and/or processing tools are | ||||||
|  | not generally available, and the machine-generated HTML, | ||||||
|  | PostScript or PDF produced by some word processors for | ||||||
|  | output purposes only. | ||||||
|  | 
 | ||||||
|  | The ``Title Page'' means, for a printed book, the title page itself, | ||||||
|  | plus such following pages as are needed to hold, legibly, the material | ||||||
|  | this License requires to appear in the title page.  For works in | ||||||
|  | formats which do not have any title page as such, ``Title Page'' means | ||||||
|  | the text near the most prominent appearance of the work's title, | ||||||
|  | preceding the beginning of the body of the text. | ||||||
|  | 
 | ||||||
|  | The ``publisher'' means any person or entity that distributes copies | ||||||
|  | of the Document to the public. | ||||||
|  | 
 | ||||||
|  | A section ``Entitled XYZ'' means a named subunit of the Document whose | ||||||
|  | title either is precisely XYZ or contains XYZ in parentheses following | ||||||
|  | text that translates XYZ in another language.  (Here XYZ stands for a | ||||||
|  | specific section name mentioned below, such as ``Acknowledgements'', | ||||||
|  | ``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title'' | ||||||
|  | of such a section when you modify the Document means that it remains a | ||||||
|  | section ``Entitled XYZ'' according to this definition. | ||||||
|  | 
 | ||||||
|  | The Document may include Warranty Disclaimers next to the notice which | ||||||
|  | states that this License applies to the Document.  These Warranty | ||||||
|  | Disclaimers are considered to be included by reference in this | ||||||
|  | License, but only as regards disclaiming warranties: any other | ||||||
|  | implication that these Warranty Disclaimers may have is void and has | ||||||
|  | no effect on the meaning of this License. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | VERBATIM COPYING | ||||||
|  | 
 | ||||||
|  | You may copy and distribute the Document in any medium, either | ||||||
|  | commercially or noncommercially, provided that this License, the | ||||||
|  | copyright notices, and the license notice saying this License applies | ||||||
|  | to the Document are reproduced in all copies, and that you add no other | ||||||
|  | conditions whatsoever to those of this License.  You may not use | ||||||
|  | technical measures to obstruct or control the reading or further | ||||||
|  | copying of the copies you make or distribute.  However, you may accept | ||||||
|  | compensation in exchange for copies.  If you distribute a large enough | ||||||
|  | number of copies you must also follow the conditions in section 3. | ||||||
|  | 
 | ||||||
|  | You may also lend copies, under the same conditions stated above, and | ||||||
|  | you may publicly display copies. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | COPYING IN QUANTITY | ||||||
|  | 
 | ||||||
|  | If you publish printed copies (or copies in media that commonly have | ||||||
|  | printed covers) of the Document, numbering more than 100, and the | ||||||
|  | Document's license notice requires Cover Texts, you must enclose the | ||||||
|  | copies in covers that carry, clearly and legibly, all these Cover | ||||||
|  | Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on | ||||||
|  | the back cover.  Both covers must also clearly and legibly identify | ||||||
|  | you as the publisher of these copies.  The front cover must present | ||||||
|  | the full title with all words of the title equally prominent and | ||||||
|  | visible.  You may add other material on the covers in addition. | ||||||
|  | Copying with changes limited to the covers, as long as they preserve | ||||||
|  | the title of the Document and satisfy these conditions, can be treated | ||||||
|  | as verbatim copying in other respects. | ||||||
|  | 
 | ||||||
|  | If the required texts for either cover are too voluminous to fit | ||||||
|  | legibly, you should put the first ones listed (as many as fit | ||||||
|  | reasonably) on the actual cover, and continue the rest onto adjacent | ||||||
|  | pages. | ||||||
|  | 
 | ||||||
|  | If you publish or distribute Opaque copies of the Document numbering | ||||||
|  | more than 100, you must either include a machine-readable Transparent | ||||||
|  | copy along with each Opaque copy, or state in or with each Opaque copy | ||||||
|  | a computer-network location from which the general network-using | ||||||
|  | public has access to download using public-standard network protocols | ||||||
|  | a complete Transparent copy of the Document, free of added material. | ||||||
|  | If you use the latter option, you must take reasonably prudent steps, | ||||||
|  | when you begin distribution of Opaque copies in quantity, to ensure | ||||||
|  | that this Transparent copy will remain thus accessible at the stated | ||||||
|  | location until at least one year after the last time you distribute an | ||||||
|  | Opaque copy (directly or through your agents or retailers) of that | ||||||
|  | edition to the public. | ||||||
|  | 
 | ||||||
|  | It is requested, but not required, that you contact the authors of the | ||||||
|  | Document well before redistributing any large number of copies, to give | ||||||
|  | them a chance to provide you with an updated version of the Document. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | MODIFICATIONS | ||||||
|  | 
 | ||||||
|  | You may copy and distribute a Modified Version of the Document under | ||||||
|  | the conditions of sections 2 and 3 above, provided that you release | ||||||
|  | the Modified Version under precisely this License, with the Modified | ||||||
|  | Version filling the role of the Document, thus licensing distribution | ||||||
|  | and modification of the Modified Version to whoever possesses a copy | ||||||
|  | of it.  In addition, you must do these things in the Modified Version: | ||||||
|  | 
 | ||||||
|  | @enumerate A | ||||||
|  | @item | ||||||
|  | Use in the Title Page (and on the covers, if any) a title distinct | ||||||
|  | from that of the Document, and from those of previous versions | ||||||
|  | (which should, if there were any, be listed in the History section | ||||||
|  | of the Document).  You may use the same title as a previous version | ||||||
|  | if the original publisher of that version gives permission. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | List on the Title Page, as authors, one or more persons or entities | ||||||
|  | responsible for authorship of the modifications in the Modified | ||||||
|  | Version, together with at least five of the principal authors of the | ||||||
|  | Document (all of its principal authors, if it has fewer than five), | ||||||
|  | unless they release you from this requirement. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | State on the Title page the name of the publisher of the | ||||||
|  | Modified Version, as the publisher. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve all the copyright notices of the Document. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Add an appropriate copyright notice for your modifications | ||||||
|  | adjacent to the other copyright notices. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Include, immediately after the copyright notices, a license notice | ||||||
|  | giving the public permission to use the Modified Version under the | ||||||
|  | terms of this License, in the form shown in the Addendum below. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve in that license notice the full lists of Invariant Sections | ||||||
|  | and required Cover Texts given in the Document's license notice. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Include an unaltered copy of this License. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve the section Entitled ``History'', Preserve its Title, and add | ||||||
|  | to it an item stating at least the title, year, new authors, and | ||||||
|  | publisher of the Modified Version as given on the Title Page.  If | ||||||
|  | there is no section Entitled ``History'' in the Document, create one | ||||||
|  | stating the title, year, authors, and publisher of the Document as | ||||||
|  | given on its Title Page, then add an item describing the Modified | ||||||
|  | Version as stated in the previous sentence. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve the network location, if any, given in the Document for | ||||||
|  | public access to a Transparent copy of the Document, and likewise | ||||||
|  | the network locations given in the Document for previous versions | ||||||
|  | it was based on.  These may be placed in the ``History'' section. | ||||||
|  | You may omit a network location for a work that was published at | ||||||
|  | least four years before the Document itself, or if the original | ||||||
|  | publisher of the version it refers to gives permission. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve | ||||||
|  | the Title of the section, and preserve in the section all the | ||||||
|  | substance and tone of each of the contributor acknowledgements and/or | ||||||
|  | dedications given therein. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve all the Invariant Sections of the Document, | ||||||
|  | unaltered in their text and in their titles.  Section numbers | ||||||
|  | or the equivalent are not considered part of the section titles. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Delete any section Entitled ``Endorsements''.  Such a section | ||||||
|  | may not be included in the Modified Version. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Do not retitle any existing section to be Entitled ``Endorsements'' or | ||||||
|  | to conflict in title with any Invariant Section. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | Preserve any Warranty Disclaimers. | ||||||
|  | @end enumerate | ||||||
|  | 
 | ||||||
|  | If the Modified Version includes new front-matter sections or | ||||||
|  | appendices that qualify as Secondary Sections and contain no material | ||||||
|  | copied from the Document, you may at your option designate some or all | ||||||
|  | of these sections as invariant.  To do this, add their titles to the | ||||||
|  | list of Invariant Sections in the Modified Version's license notice. | ||||||
|  | These titles must be distinct from any other section titles. | ||||||
|  | 
 | ||||||
|  | You may add a section Entitled ``Endorsements'', provided it contains | ||||||
|  | nothing but endorsements of your Modified Version by various | ||||||
|  | parties---for example, statements of peer review or that the text has | ||||||
|  | been approved by an organization as the authoritative definition of a | ||||||
|  | standard. | ||||||
|  | 
 | ||||||
|  | You may add a passage of up to five words as a Front-Cover Text, and a | ||||||
|  | passage of up to 25 words as a Back-Cover Text, to the end of the list | ||||||
|  | of Cover Texts in the Modified Version.  Only one passage of | ||||||
|  | Front-Cover Text and one of Back-Cover Text may be added by (or | ||||||
|  | through arrangements made by) any one entity.  If the Document already | ||||||
|  | includes a cover text for the same cover, previously added by you or | ||||||
|  | by arrangement made by the same entity you are acting on behalf of, | ||||||
|  | you may not add another; but you may replace the old one, on explicit | ||||||
|  | permission from the previous publisher that added the old one. | ||||||
|  | 
 | ||||||
|  | The author(s) and publisher(s) of the Document do not by this License | ||||||
|  | give permission to use their names for publicity for or to assert or | ||||||
|  | imply endorsement of any Modified Version. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | COMBINING DOCUMENTS | ||||||
|  | 
 | ||||||
|  | You may combine the Document with other documents released under this | ||||||
|  | License, under the terms defined in section 4 above for modified | ||||||
|  | versions, provided that you include in the combination all of the | ||||||
|  | Invariant Sections of all of the original documents, unmodified, and | ||||||
|  | list them all as Invariant Sections of your combined work in its | ||||||
|  | license notice, and that you preserve all their Warranty Disclaimers. | ||||||
|  | 
 | ||||||
|  | The combined work need only contain one copy of this License, and | ||||||
|  | multiple identical Invariant Sections may be replaced with a single | ||||||
|  | copy.  If there are multiple Invariant Sections with the same name but | ||||||
|  | different contents, make the title of each such section unique by | ||||||
|  | adding at the end of it, in parentheses, the name of the original | ||||||
|  | author or publisher of that section if known, or else a unique number. | ||||||
|  | Make the same adjustment to the section titles in the list of | ||||||
|  | Invariant Sections in the license notice of the combined work. | ||||||
|  | 
 | ||||||
|  | In the combination, you must combine any sections Entitled ``History'' | ||||||
|  | in the various original documents, forming one section Entitled | ||||||
|  | ``History''; likewise combine any sections Entitled ``Acknowledgements'', | ||||||
|  | and any sections Entitled ``Dedications''.  You must delete all | ||||||
|  | sections Entitled ``Endorsements.'' | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | COLLECTIONS OF DOCUMENTS | ||||||
|  | 
 | ||||||
|  | You may make a collection consisting of the Document and other documents | ||||||
|  | released under this License, and replace the individual copies of this | ||||||
|  | License in the various documents with a single copy that is included in | ||||||
|  | the collection, provided that you follow the rules of this License for | ||||||
|  | verbatim copying of each of the documents in all other respects. | ||||||
|  | 
 | ||||||
|  | You may extract a single document from such a collection, and distribute | ||||||
|  | it individually under this License, provided you insert a copy of this | ||||||
|  | License into the extracted document, and follow this License in all | ||||||
|  | other respects regarding verbatim copying of that document. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | AGGREGATION WITH INDEPENDENT WORKS | ||||||
|  | 
 | ||||||
|  | A compilation of the Document or its derivatives with other separate | ||||||
|  | and independent documents or works, in or on a volume of a storage or | ||||||
|  | distribution medium, is called an ``aggregate'' if the copyright | ||||||
|  | resulting from the compilation is not used to limit the legal rights | ||||||
|  | of the compilation's users beyond what the individual works permit. | ||||||
|  | When the Document is included in an aggregate, this License does not | ||||||
|  | apply to the other works in the aggregate which are not themselves | ||||||
|  | derivative works of the Document. | ||||||
|  | 
 | ||||||
|  | If the Cover Text requirement of section 3 is applicable to these | ||||||
|  | copies of the Document, then if the Document is less than one half of | ||||||
|  | the entire aggregate, the Document's Cover Texts may be placed on | ||||||
|  | covers that bracket the Document within the aggregate, or the | ||||||
|  | electronic equivalent of covers if the Document is in electronic form. | ||||||
|  | Otherwise they must appear on printed covers that bracket the whole | ||||||
|  | aggregate. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | TRANSLATION | ||||||
|  | 
 | ||||||
|  | Translation is considered a kind of modification, so you may | ||||||
|  | distribute translations of the Document under the terms of section 4. | ||||||
|  | Replacing Invariant Sections with translations requires special | ||||||
|  | permission from their copyright holders, but you may include | ||||||
|  | translations of some or all Invariant Sections in addition to the | ||||||
|  | original versions of these Invariant Sections.  You may include a | ||||||
|  | translation of this License, and all the license notices in the | ||||||
|  | Document, and any Warranty Disclaimers, provided that you also include | ||||||
|  | the original English version of this License and the original versions | ||||||
|  | of those notices and disclaimers.  In case of a disagreement between | ||||||
|  | the translation and the original version of this License or a notice | ||||||
|  | or disclaimer, the original version will prevail. | ||||||
|  | 
 | ||||||
|  | If a section in the Document is Entitled ``Acknowledgements'', | ||||||
|  | ``Dedications'', or ``History'', the requirement (section 4) to Preserve | ||||||
|  | its Title (section 1) will typically require changing the actual | ||||||
|  | title. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | TERMINATION | ||||||
|  | 
 | ||||||
|  | You may not copy, modify, sublicense, or distribute the Document | ||||||
|  | except as expressly provided under this License.  Any attempt | ||||||
|  | otherwise to copy, modify, sublicense, or distribute it is void, and | ||||||
|  | will automatically terminate your rights under this License. | ||||||
|  | 
 | ||||||
|  | However, if you cease all violation of this License, then your license | ||||||
|  | from a particular copyright holder is reinstated (a) provisionally, | ||||||
|  | unless and until the copyright holder explicitly and finally | ||||||
|  | terminates your license, and (b) permanently, if the copyright holder | ||||||
|  | fails to notify you of the violation by some reasonable means prior to | ||||||
|  | 60 days after the cessation. | ||||||
|  | 
 | ||||||
|  | Moreover, your license from a particular copyright holder is | ||||||
|  | reinstated permanently if the copyright holder notifies you of the | ||||||
|  | violation by some reasonable means, this is the first time you have | ||||||
|  | received notice of violation of this License (for any work) from that | ||||||
|  | copyright holder, and you cure the violation prior to 30 days after | ||||||
|  | your receipt of the notice. | ||||||
|  | 
 | ||||||
|  | Termination of your rights under this section does not terminate the | ||||||
|  | licenses of parties who have received copies or rights from you under | ||||||
|  | this License.  If your rights have been terminated and not permanently | ||||||
|  | reinstated, receipt of a copy of some or all of the same material does | ||||||
|  | not give you any rights to use it. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | FUTURE REVISIONS OF THIS LICENSE | ||||||
|  | 
 | ||||||
|  | The Free Software Foundation may publish new, revised versions | ||||||
|  | of the GNU Free Documentation License from time to time.  Such new | ||||||
|  | versions will be similar in spirit to the present version, but may | ||||||
|  | differ in detail to address new problems or concerns.  See | ||||||
|  | @uref{http://www.gnu.org/copyleft/}. | ||||||
|  | 
 | ||||||
|  | Each version of the License is given a distinguishing version number. | ||||||
|  | If the Document specifies that a particular numbered version of this | ||||||
|  | License ``or any later version'' applies to it, you have the option of | ||||||
|  | following the terms and conditions either of that specified version or | ||||||
|  | of any later version that has been published (not as a draft) by the | ||||||
|  | Free Software Foundation.  If the Document does not specify a version | ||||||
|  | number of this License, you may choose any version ever published (not | ||||||
|  | as a draft) by the Free Software Foundation.  If the Document | ||||||
|  | specifies that a proxy can decide which future versions of this | ||||||
|  | License can be used, that proxy's public statement of acceptance of a | ||||||
|  | version permanently authorizes you to choose that version for the | ||||||
|  | Document. | ||||||
|  | 
 | ||||||
|  | @item | ||||||
|  | RELICENSING | ||||||
|  | 
 | ||||||
|  | ``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any | ||||||
|  | World Wide Web server that publishes copyrightable works and also | ||||||
|  | provides prominent facilities for anybody to edit those works.  A | ||||||
|  | public wiki that anybody can edit is an example of such a server.  A | ||||||
|  | ``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the | ||||||
|  | site means any set of copyrightable works thus published on the MMC | ||||||
|  | site. | ||||||
|  | 
 | ||||||
|  | ``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 | ||||||
|  | license published by Creative Commons Corporation, a not-for-profit | ||||||
|  | corporation with a principal place of business in San Francisco, | ||||||
|  | California, as well as future copyleft versions of that license | ||||||
|  | published by that same organization. | ||||||
|  | 
 | ||||||
|  | ``Incorporate'' means to publish or republish a Document, in whole or | ||||||
|  | in part, as part of another Document. | ||||||
|  | 
 | ||||||
|  | An MMC is ``eligible for relicensing'' if it is licensed under this | ||||||
|  | License, and if all works that were first published under this License | ||||||
|  | somewhere other than this MMC, and subsequently incorporated in whole | ||||||
|  | or in part into the MMC, (1) had no cover texts or invariant sections, | ||||||
|  | and (2) were thus incorporated prior to November 1, 2008. | ||||||
|  | 
 | ||||||
|  | The operator of an MMC Site may republish an MMC contained in the site | ||||||
|  | under CC-BY-SA on the same site at any time before August 1, 2009, | ||||||
|  | provided the MMC is eligible for relicensing. | ||||||
|  | 
 | ||||||
|  | @end enumerate | ||||||
|  | 
 | ||||||
|  | @page | ||||||
|  | @heading ADDENDUM: How to use this License for your documents | ||||||
|  | 
 | ||||||
|  | To use this License in a document you have written, include a copy of | ||||||
|  | the License in the document and put the following copyright and | ||||||
|  | license notices just after the title page: | ||||||
|  | 
 | ||||||
|  | @smallexample | ||||||
|  | @group | ||||||
|  |   Copyright (C)  @var{year}  @var{your name}. | ||||||
|  |   Permission is granted to copy, distribute and/or modify this document | ||||||
|  |   under the terms of the GNU Free Documentation License, Version 1.3 | ||||||
|  |   or any later version published by the Free Software Foundation; | ||||||
|  |   with no Invariant Sections, no Front-Cover Texts, and no Back-Cover | ||||||
|  |   Texts.  A copy of the license is included in the section entitled ``GNU | ||||||
|  |   Free Documentation License''. | ||||||
|  | @end group | ||||||
|  | @end smallexample | ||||||
|  | 
 | ||||||
|  | If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, | ||||||
|  | replace the ``with@dots{}Texts.''@: line with this: | ||||||
|  | 
 | ||||||
|  | @smallexample | ||||||
|  | @group | ||||||
|  |     with the Invariant Sections being @var{list their titles}, with | ||||||
|  |     the Front-Cover Texts being @var{list}, and with the Back-Cover Texts | ||||||
|  |     being @var{list}. | ||||||
|  | @end group | ||||||
|  | @end smallexample | ||||||
|  | 
 | ||||||
|  | If you have Invariant Sections without Cover Texts, or some other | ||||||
|  | combination of the three, merge those two alternatives to suit the | ||||||
|  | situation. | ||||||
|  | 
 | ||||||
|  | If your document contains nontrivial examples of program code, we | ||||||
|  | recommend releasing these examples in parallel under your choice of | ||||||
|  | free software license, such as the GNU General Public License, | ||||||
|  | to permit their use in free software. | ||||||
|  | 
 | ||||||
|  | @c Local Variables: | ||||||
|  | @c ispell-local-pdict: "ispell-dict" | ||||||
|  | @c End: | ||||||
|  | @ -63,6 +63,7 @@ running jobs at scheduled times. | ||||||
| * Syntax::                      All the possibilities for configuring cron jobs. | * Syntax::                      All the possibilities for configuring cron jobs. | ||||||
| * Invoking::                    What happens when you run the mcron command. | * Invoking::                    What happens when you run the mcron command. | ||||||
| * Guile modules::               Incorporating mcron into another Guile program. | * Guile modules::               Incorporating mcron into another Guile program. | ||||||
|  | * GNU Free Documentation License::  The license of this manual. | ||||||
| * Index::                       The complete index. | * Index::                       The complete index. | ||||||
| 
 | 
 | ||||||
| @detailmenu | @detailmenu | ||||||
|  | @ -1329,6 +1330,11 @@ Once this module has been declared in a program, a crontab file can be | ||||||
| used to augment the current job list with a call to | used to augment the current job list with a call to | ||||||
| @code{read-vixie-file}. | @code{read-vixie-file}. | ||||||
| 
 | 
 | ||||||
|  | @node GNU Free Documentation License | ||||||
|  | @appendix GNU Free Documentation License | ||||||
|  | 
 | ||||||
|  | @include fdl.texi | ||||||
|  | 
 | ||||||
| @node Index,  , Guile modules, Top | @node Index,  , Guile modules, Top | ||||||
| @unnumbered Index | @unnumbered Index | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								makefile.am
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								makefile.am
									
										
									
									
									
								
							|  | @ -1,6 +1,5 @@ | ||||||
| ## Makefile for the toplevel directory of mcron. | ## Makefile for the toplevel directory of mcron. | ||||||
| ## Copyright (C) 2003 Dale Mellor | ## Copyright (C) 2003, 2015 Dale Mellor | ||||||
| ## Copyright (C) 2015 Mathieu Lirzin |  | ||||||
| ## | ## | ||||||
| #    This file is part of GNU mcron. | #    This file is part of GNU mcron. | ||||||
| #  | #  | ||||||
|  | @ -17,20 +16,13 @@ | ||||||
| #    You should have received a copy of the GNU General Public License along | #    You should have received a copy of the GNU General Public License along | ||||||
| #    with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | #    with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| ## Process this file with automake to produce Makefile.in | ## Process this file with automake to produce makefile.in | ||||||
| 
 | 
 | ||||||
| SUBDIRS = scm/mcron . | SUBDIRS = scm/mcron . | ||||||
| 
 | 
 | ||||||
| ED = @ED@   # !!!! Are these needed? |  | ||||||
| CP = @CP@ | CP = @CP@ | ||||||
| 
 | 
 | ||||||
| MAINTAINERCLEANFILES = configure makefile makefile.in config.guess config.sub \ | EXTRA_DIST = BUGS | ||||||
|                        install-sh missing texinfo.tex INSTALL \ |  | ||||||
|                        aclocal.m4 compile depcomp doc/mcron.1 |  | ||||||
| 
 |  | ||||||
| CLEANFILES = mcron.c |  | ||||||
| 
 |  | ||||||
| EXTRA_DIST = makefile.ed mcron.c.template BUGS |  | ||||||
| 
 | 
 | ||||||
| info_TEXINFOS = doc/mcron.texi | info_TEXINFOS = doc/mcron.texi | ||||||
| 
 | 
 | ||||||
|  | @ -42,14 +34,7 @@ mcron_LDADD = @GUILE_LIBS@ | ||||||
| 
 | 
 | ||||||
| # The second option is so that we can execute the binary in the local directory, | # The second option is so that we can execute the binary in the local directory, | ||||||
| # in turn so that we can do mcron --help during the build process. | # in turn so that we can do mcron --help during the build process. | ||||||
| mcron_CFLAGS  = @GUILE_CFLAGS@ -DGUILE_LOAD_PATH=\"$(datadir):./scm:...\" | mcron_CFLAGS = @GUILE_CFLAGS@ -DGUILE_LOAD_PATH=\"$(datadir):./scm:...\" | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| mcron.c : scm/mcron/main.scm scm/mcron/crontab.scm makefile.ed mcron.c.template |  | ||||||
| 	@echo 'Building mcron.c...' |  | ||||||
| 	@$(ED) < makefile.ed > /dev/null 2>&1 |  | ||||||
| 	@rm -f mcron.escaped.scm > /dev/null 2>&1 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| # Full program prefix. | # Full program prefix. | ||||||
| fpp = $(DESTDIR)$(bindir)/@real_program_prefix@ | fpp = $(DESTDIR)$(bindir)/@real_program_prefix@ | ||||||
|  | @ -79,11 +64,15 @@ uninstall-hook: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Not part of formal package building, but a rule for manual use to get the | # Not part of formal package building, but a rule for manual use to get the | ||||||
| # elemental man page.  Will only work once the mcron program is installed. | # elemental man page. | ||||||
| $(dist_man_MANS): mcron.c | doc/mcron.1 : mcron | ||||||
| 	$(HELP2MAN) -n 'a program to run tasks at regular (or not) intervals' \ | 	$(HELP2MAN) -n 'a program to run tasks at regular (or not) intervals' \ | ||||||
| 	    ./mcron > $@ | 	    ./mcron > doc/mcron.1 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | MAINTAINERCLEANFILES = configure makefile makefile.in config.guess config.sub \ | ||||||
|  |                        install-sh missing texinfo.tex INSTALL \ | ||||||
|  |                        aclocal.m4 compile depcomp doc/mcron.1 | ||||||
|  | 
 | ||||||
| maintainer-clean-local: | maintainer-clean-local: | ||||||
| 	rm -r build-aux | 	rm -r build-aux | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								makefile.ed
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								makefile.ed
									
										
									
									
									
								
							|  | @ -1,34 +0,0 @@ | ||||||
| #   Copyright (C) 2003 Dale Mellor |  | ||||||
| #  |  | ||||||
| #    This file is part of GNU mcron. |  | ||||||
| #  |  | ||||||
| #    GNU mcron is free software: you can redistribute it and/or modify it under |  | ||||||
| #    the terms of the GNU General Public License as published by the Free |  | ||||||
| #    Software Foundation, either version 3 of the License, or (at your option) |  | ||||||
| #    any later version. |  | ||||||
| #  |  | ||||||
| #    GNU mcron is distributed in the hope that it will be useful, but WITHOUT |  | ||||||
| #    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |  | ||||||
| #    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for |  | ||||||
| #    more details. |  | ||||||
| #  |  | ||||||
| #    You should have received a copy of the GNU General Public License along |  | ||||||
| #    with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. |  | ||||||
| # |  | ||||||
| # |  | ||||||
| # |  | ||||||
| e scm/mcron/main.scm |  | ||||||
| /\(load "crontab.scm"\)/d |  | ||||||
| -1r scm/mcron/crontab.scm |  | ||||||
| %s/\\/\\\\/g |  | ||||||
| %s/"/\\"/g |  | ||||||
| %s/ *;;.*$/ /g |  | ||||||
| g/^ *$/d |  | ||||||
| %s/^/\"/ |  | ||||||
| %s/$/\"/ |  | ||||||
| w mcron.escaped.scm |  | ||||||
| e mcron.c.template |  | ||||||
| /GUILE_PROGRAM_GOES_HERE/d |  | ||||||
| -1r mcron.escaped.scm |  | ||||||
| w mcron.c |  | ||||||
| q |  | ||||||
							
								
								
									
										115
									
								
								mcron.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								mcron.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | ||||||
|  | /* mcron.c -- Run the mcron program.
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2015 Mathieu Lirzin | ||||||
|  |  * Copyright (C) 2003, 2014 Dale Mellor | ||||||
|  |  * | ||||||
|  |  * This file is part of GNU Mcron. | ||||||
|  |  * | ||||||
|  |  * GNU Mcron is free software: you can redistribute it and/or modify it under | ||||||
|  |  * the terms of the GNU General Public License as published by the Free | ||||||
|  |  * Software Foundation, either version 3 of the License, or (at your option) | ||||||
|  |  * any later version. | ||||||
|  |  * | ||||||
|  |  * GNU Mcron is distributed in the hope that it will be useful, but WITHOUT | ||||||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||||
|  |  * more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along | ||||||
|  |  * with GNU Mcron.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * This C code represents the thinnest possible wrapper around the Guile code | ||||||
|  |  * which constitutes all the functionality of the mcron program.  There are | ||||||
|  |  * two plus one reasons why we need to do this, and one very unfortunate | ||||||
|  |  * consequence. | ||||||
|  |  * | ||||||
|  |  *   Firstly, SUID does not work on an executable script.  In the end, it is | ||||||
|  |  *   the execution of the translator, in our case guile, which determines the | ||||||
|  |  *   effective user, and it is not wise to make the system guile installation | ||||||
|  |  *   SUID root! | ||||||
|  |  * | ||||||
|  |  *   Secondly, executable scripts show up in ugly ways in listings of the | ||||||
|  |  *   system process table.  Guile in particular, with its multi-line ``#! ...\ | ||||||
|  |  *   \n -s ...!#'' idiosyncracies shows up in process listings in a way that | ||||||
|  |  *   is difficult to determine what program is actually running. | ||||||
|  |  * | ||||||
|  |  *   A third reason for the C wrapper which might be mentioned is that a | ||||||
|  |  *   security-conscious system administrator can choose to only install a | ||||||
|  |  *   binary, thus removing the possibility of a user studying a guile script | ||||||
|  |  *   and working out ways of hacking it to his own ends, or worse still | ||||||
|  |  *   finding a way to modify it to his own ends. | ||||||
|  |  * | ||||||
|  |  *   Unfortunately, running the guile script from inside a C program means | ||||||
|  |  *   that the sigaction function does not work.  Instead, it is necessary to | ||||||
|  |  *   perform the signal processing in C. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include <libguile.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Handle the signal and exit.  All signals that mcron handles will produce
 | ||||||
|  |  * the same behavior so we don't need to use the signal value in the | ||||||
|  |  * implementation.  */ | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | react_to_terminal_signal (int signal) | ||||||
|  | { | ||||||
|  |   scm_c_eval_string ("(delete-run-file)"); | ||||||
|  |   exit (1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Set up all the signal handlers as required by the cron personality.  This
 | ||||||
|  |  * is necessary to perform the signal processing in C because the sigaction | ||||||
|  |  * function won't work when called from Guile; this function is called from | ||||||
|  |  * the Guile universe. */ | ||||||
|  | 
 | ||||||
|  | static SCM | ||||||
|  | set_cron_signals () | ||||||
|  | { | ||||||
|  |   static struct sigaction sa; | ||||||
|  | 
 | ||||||
|  |   memset (&sa, 0, sizeof (sa)); | ||||||
|  |   sa.sa_handler = react_to_terminal_signal; | ||||||
|  |   sigaction (SIGTERM, &sa, 0); | ||||||
|  |   sigaction (SIGINT,  &sa, 0); | ||||||
|  |   sigaction (SIGQUIT, &sa, 0); | ||||||
|  |   sigaction (SIGHUP,  &sa, 0); | ||||||
|  | 
 | ||||||
|  |   return SCM_BOOL_T; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Launch the Mcron Guile main program. */ | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | inner_main (void *closure, int argc, char **argv) | ||||||
|  | { | ||||||
|  |   scm_set_current_module (scm_c_resolve_module ("mcron main")); | ||||||
|  |   scm_c_define_gsubr ("c-set-cron-signals", 0, 0, 0, set_cron_signals); | ||||||
|  |   scm_c_eval_string ("(main)"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* The real main function.  Does nothing but start up the guile subsystem. */ | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main (int argc, char **argv) | ||||||
|  | { | ||||||
|  |   setenv ("GUILE_LOAD_PATH", GUILE_LOAD_PATH, 1); | ||||||
|  |   scm_boot_guile (argc, argv, inner_main, 0); | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
							
								
								
									
										120
									
								
								mcron.c.template
									
										
									
									
									
								
							
							
						
						
									
										120
									
								
								mcron.c.template
									
										
									
									
									
								
							|  | @ -1,120 +0,0 @@ | ||||||
| /*                                                   -*-c-*- */ |  | ||||||
| /* |  | ||||||
|  *   Copyright (C) 2003, 2014 Dale Mellor |  | ||||||
|  *  |  | ||||||
|  *   This file is part of GNU mcron. |  | ||||||
|  * |  | ||||||
|  *   GNU mcron is free software: you can redistribute it and/or modify it under |  | ||||||
|  *   the terms of the GNU General Public License as published by the Free |  | ||||||
|  *   Software Foundation, either version 3 of the License, or (at your option) |  | ||||||
|  *   any later version. |  | ||||||
|  * |  | ||||||
|  *   GNU mcron is distributed in the hope that it will be useful, but WITHOUT |  | ||||||
|  *   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |  | ||||||
|  *   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for |  | ||||||
|  *   more details. |  | ||||||
|  * |  | ||||||
|  *   You should have received a copy of the GNU General Public License along |  | ||||||
|  *   with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|     This C code represents the thinnest possible wrapper around the Guile code |  | ||||||
|     which constitutes all the functionality of the mcron program. There are two |  | ||||||
|     plus one reasons why we need to do this, and one very unfortunate |  | ||||||
|     consequence. |  | ||||||
| 
 |  | ||||||
|         Firstly, SUID does not work on an executable script. In the end, it is |  | ||||||
|         the execution of the translator, in our case guile, which determines the |  | ||||||
|         effective user, and it is not wise to make the system guile installation |  | ||||||
|         SUID root! |  | ||||||
| 
 |  | ||||||
|         Secondly, executable scripts show up in ugly ways in listings of the |  | ||||||
|         system process table. Guile in particular, with its multi-line |  | ||||||
|         #! ...\ \n -s ...!# |  | ||||||
|         idiosyncracies shows up in process listings in a way that is difficult |  | ||||||
|         to determine what program is actually running. |  | ||||||
| 
 |  | ||||||
|         A third reason for the C wrapper which might be mentioned is that a |  | ||||||
|         security-conscious system administrator can choose to only install a |  | ||||||
|         binary, thus removing the possibility of a user studying a guile script |  | ||||||
|         and working out ways of hacking it to his own ends, or worse still |  | ||||||
|         finding a way to modify it to his own ends. |  | ||||||
| 
 |  | ||||||
|         Unfortunately, running the guile script from inside a C program means |  | ||||||
|         that the sigaction function does not work. Instead, it is necessary to |  | ||||||
|         perform the signal processing in C. |  | ||||||
| 
 |  | ||||||
|     The guile code itself is substituted for the GU1LE_PROGRAM_GOES_HERE (sic) |  | ||||||
|     token by the makefile, which processes the scheme to make it look like one |  | ||||||
|     big string. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include <string.h> |  | ||||||
| #include <signal.h> |  | ||||||
| #include <libguile.h> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* This is a function designed to be installed as a signal handler, for signals |  | ||||||
|    which are supposed to initiate shutdown of this program. It calls the scheme |  | ||||||
|    procedure (see mcron.scm for details) to do all the work, and then exits. */ |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| react_to_terminal_signal (int sig) |  | ||||||
| { |  | ||||||
|   scm_c_eval_string ("(delete-run-file)"); |  | ||||||
|   exit (1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* This is a function designed to be callable from scheme, and sets up all the |  | ||||||
|    signal handlers required by the cron personality.  */ |  | ||||||
| 
 |  | ||||||
| SCM |  | ||||||
| set_cron_signals () |  | ||||||
| { |  | ||||||
|   static struct sigaction sa; |  | ||||||
|   memset (&sa, 0, sizeof (sa)); |  | ||||||
|   sa.sa_handler = react_to_terminal_signal; |  | ||||||
|   sigaction (SIGTERM, &sa, 0); |  | ||||||
|   sigaction (SIGINT,  &sa, 0); |  | ||||||
|   sigaction (SIGQUIT, &sa, 0); |  | ||||||
|   sigaction (SIGHUP,  &sa, 0); |  | ||||||
|    |  | ||||||
|   return SCM_BOOL_T; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* The effective main function (i.e. the one that actually does some work). We |  | ||||||
|    register the function above with the guile system, and then execute the mcron |  | ||||||
|    guile program. */ |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| inner_main () |  | ||||||
| { |  | ||||||
|   scm_c_define_gsubr ("c-set-cron-signals", 0, 0, 0, set_cron_signals); |  | ||||||
|      |  | ||||||
|   scm_c_eval_string ( |  | ||||||
|                      GUILE_PROGRAM_GOES_HERE |  | ||||||
|                      ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* The real main function. Does nothing but start up the guile subsystem. */ |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| main (int argc, char **argv) |  | ||||||
| { |  | ||||||
|   setenv ("GUILE_LOAD_PATH", GUILE_LOAD_PATH, 1); |  | ||||||
|    |  | ||||||
|   scm_boot_guile (argc, argv, inner_main, 0); |  | ||||||
|    |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| ;; -*-scheme-*- | ;; -*-scheme-*- | ||||||
| 
 | 
 | ||||||
|  | ;;   Copyright (C) 2015 Mathieu Lirzin | ||||||
| ;;   Copyright (C) 2003 Dale Mellor | ;;   Copyright (C) 2003 Dale Mellor | ||||||
| ;;  | ;;  | ||||||
| ;;   This file is part of GNU mcron. | ;;   This file is part of GNU mcron. | ||||||
|  | @ -23,8 +24,11 @@ | ||||||
| (define-module (mcron config)) | (define-module (mcron config)) | ||||||
| 
 | 
 | ||||||
| (define-public config-debug @CONFIG_DEBUG@) | (define-public config-debug @CONFIG_DEBUG@) | ||||||
|  | (define-public config-package-name "@PACKAGE_NAME@") | ||||||
|  | (define-public config-package-version "@PACKAGE_VERSION@") | ||||||
| (define-public config-package-string "@PACKAGE_STRING@") | (define-public config-package-string "@PACKAGE_STRING@") | ||||||
| (define-public config-package-bugreport "@PACKAGE_BUGREPORT@") | (define-public config-package-bugreport "@PACKAGE_BUGREPORT@") | ||||||
|  | (define-public config-package-url "@PACKAGE_URL@") | ||||||
| (define-public config-sendmail "@SENDMAIL@") | (define-public config-sendmail "@SENDMAIL@") | ||||||
| 
 | 
 | ||||||
| (define-public config-spool-dir "@CONFIG_SPOOL_DIR@") | (define-public config-spool-dir "@CONFIG_SPOOL_DIR@") | ||||||
|  |  | ||||||
|  | @ -221,8 +221,8 @@ | ||||||
|  ;; The user is being silly. The message here is identical to the one Vixie cron |  ;; The user is being silly. The message here is identical to the one Vixie cron | ||||||
|  ;; used to put out, for total compatibility. |  ;; used to put out, for total compatibility. | ||||||
| 
 | 
 | ||||||
|  (else |  (else (mcron-error 15 | ||||||
|   (mcron-error 15 "usage error: file name must be specified for replace."))) |          "usage error: file name must be specified for replace."))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| )) ;; End of file-level let-scopes. | )) ;; End of file-level let-scopes. | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| ;;   Copyright (C) 2003 Dale Mellor | ;;   Copyright (C) 2003, 2015 Dale Mellor | ||||||
| ;;  | ;;  | ||||||
| ;;   This file is part of GNU mcron. | ;;   This file is part of GNU mcron. | ||||||
| ;; | ;; | ||||||
|  | @ -31,42 +31,12 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (define-module (mcron environment) | (define-module (mcron environment) | ||||||
|  |   #:use-module (srfi srfi-26) | ||||||
|   #:export (modify-environment |   #:export (modify-environment | ||||||
|             clear-environment-mods |             clear-environment-mods | ||||||
|             append-environment-mods |             append-environment-mods | ||||||
|             get-current-environment-mods-copy)) |             get-current-environment-mods-copy)) | ||||||
|              |              | ||||||
|              |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; The env-alist is an association list of variable names and values. Variables |  | ||||||
| ;; later in the list will take precedence over variables before. We return a |  | ||||||
| ;; fixed-up version in which some variables are given specific default values |  | ||||||
| ;; (which the user can override), and two variables which the user is not |  | ||||||
| ;; allowed to control are added at the end of the list. |  | ||||||
| 
 |  | ||||||
| (define (impose-default-environment env-alist passwd-entry) |  | ||||||
|   (append `(("HOME"    . ,(passwd:dir passwd-entry)) |  | ||||||
|             ("CWD"     . ,(passwd:dir passwd-entry)) |  | ||||||
|             ("SHELL"   . ,(passwd:shell passwd-entry)) |  | ||||||
|             ("TERM"    . #f) |  | ||||||
|             ("TERMCAP" . #f)) |  | ||||||
|           env-alist |  | ||||||
|           `(("LOGNAME" . ,(passwd:name passwd-entry)) |  | ||||||
|             ("USER"    . ,(passwd:name passwd-entry))))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; Modify the UNIX environment for the current process according to the given |  | ||||||
| ;; association list of variables, with the default variable values imposed. |  | ||||||
| 
 |  | ||||||
| (define (modify-environment env-alist passwd-entry) |  | ||||||
|   (for-each (lambda (variable) |  | ||||||
|               (setenv (car variable) (cdr variable))) |  | ||||||
|             (impose-default-environment env-alist passwd-entry))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; As we parse configuration files, we build up an alist of environment | ;; As we parse configuration files, we build up an alist of environment | ||||||
|  | @ -103,3 +73,24 @@ | ||||||
|   (set! current-environment-mods (append current-environment-mods |   (set! current-environment-mods (append current-environment-mods | ||||||
|                                          (list (cons name value)))) |                                          (list (cons name value)))) | ||||||
|   #t) |   #t) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ;; Modify the UNIX environment for the current process according to the given | ||||||
|  | ;; association list of variables, with the default variable values imposed. | ||||||
|  | 
 | ||||||
|  | (define (modify-environment env-alist passwd-entry) | ||||||
|  |   (for-each (lambda (a) (setenv (car a) (cdr a))) | ||||||
|  |             (let ((home-dir  (passwd:dir passwd-entry)) | ||||||
|  |                   (user-name (passwd:name passwd-entry))) | ||||||
|  |               (append | ||||||
|  |                ;; Default environment variables which can be overidden by ENV. | ||||||
|  |                `(("HOME"    . ,home-dir) | ||||||
|  |                  ("CWD"     . ,home-dir) | ||||||
|  |                  ("SHELL"   . ,(passwd:shell passwd-entry)) | ||||||
|  |                  ("TERM"    . #f) | ||||||
|  |                  ("TERMCAP" . #f)) | ||||||
|  |                env-alist | ||||||
|  |                ;; Environment variables with imposed values. | ||||||
|  |                `(("LOGNAME" . ,user-name) | ||||||
|  |                  ("USER"    . ,user-name)))))) | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ | ||||||
|             set-configuration-time |             set-configuration-time | ||||||
|             job |             job | ||||||
|             find-best-next) |             find-best-next) | ||||||
|   #:use-module (mcron core) |   #:use-module (mcron mcron-core) | ||||||
|   #:use-module (mcron environment) |   #:use-module (mcron environment) | ||||||
|   #:use-module (mcron vixie-time) |   #:use-module (mcron vixie-time) | ||||||
|   #:re-export (append-environment-mods)) |   #:re-export (append-environment-mods)) | ||||||
|  | @ -203,11 +203,16 @@ | ||||||
| (define configuration-user (getpw (getuid))) | (define configuration-user (getpw (getuid))) | ||||||
| (define configuration-time (current-time)) | (define configuration-time (current-time)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (set-configuration-user user) | (define (set-configuration-user user) | ||||||
|   (set! configuration-user (if (or (string? user) |   (set! configuration-user (if (or (string? user) | ||||||
|                                    (integer? user)) |                                    (integer? user)) | ||||||
|                                (getpw user) |                                (getpw user) | ||||||
|                                user))) |                                user))) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (set-configuration-time time) (set! configuration-time time)) | (define (set-configuration-time time) (set! configuration-time time)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -233,10 +238,9 @@ | ||||||
|                       ((list? action) (lambda () (primitive-eval action))) |                       ((list? action) (lambda () (primitive-eval action))) | ||||||
|                       ((string? action) (lambda () (system action))) |                       ((string? action) (lambda () (system action))) | ||||||
|                       (else  |                       (else  | ||||||
|            (throw 'mcron-error  |            (throw 'mcron-error 2 | ||||||
|                   2 |                   "job: invalid second argument (action; should be lambda " | ||||||
|                   "job: invalid second argument (action; should be lambda" |                   "function, string or list)")))) | ||||||
|                   " function, string or list)")))) |  | ||||||
| 
 | 
 | ||||||
|         (time-proc |         (time-proc | ||||||
|          (cond ((procedure? time-proc) time-proc) |          (cond ((procedure? time-proc) time-proc) | ||||||
|  | @ -244,10 +248,9 @@ | ||||||
|                ((list? time-proc)      (lambda (current-time) |                ((list? time-proc)      (lambda (current-time) | ||||||
|                                          (primitive-eval time-proc))) |                                          (primitive-eval time-proc))) | ||||||
|                (else |                (else | ||||||
|           (throw 'mcron-error  |                 (throw 'mcron-error 3 | ||||||
|                  3        |                        "job: invalid first argument (next-time-function; " | ||||||
|                  "job: invalid first argument (next-time-function; should ") |                        "should be function, string or list)")))) | ||||||
|                  "be function, string or list)"))) |  | ||||||
|         (displayable |         (displayable | ||||||
|          (cond ((not (null? displayable)) (car displayable)) |          (cond ((not (null? displayable)) (car displayable)) | ||||||
|                ((procedure? action) "Lambda function") |                ((procedure? action) "Lambda function") | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| ;;   Copyright (C) 2003, 2012 Dale Mellor | ;;   Copyright (C) 2003, 2012, 2015 Dale Mellor | ||||||
| ;;  | ;;  | ||||||
| ;;   This file is part of GNU mcron. | ;;   This file is part of GNU mcron. | ||||||
| ;; | ;; | ||||||
|  | @ -16,34 +16,24 @@ | ||||||
| ;;   with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | ;;   with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | (define-module (mcron main) | ||||||
| ;; This is the 'main' routine for the whole system; the top of this file is the |   #:use-module (ice-9 getopt-long) | ||||||
| ;; global entry point (after the minimal C wrapper, mcron.c.template); to all |   #:use-module (ice-9 rdelim) | ||||||
| ;; intents and purposes the program is pure Guile and starts here. |   #:use-module (ice-9 regex) | ||||||
| ;; |   #:use-module (mcron config) | ||||||
| ;; This file is built into mcron.c.template by the makefile, which stringifies |   #:use-module (mcron mcron-core) | ||||||
| ;; the whole lot, and escapes quotation marks and escape characters |   #:use-module (mcron job-specifier) | ||||||
| ;; accordingly. Bear this in mind when considering literal multi-line strings. |   #:use-module (mcron vixie-specification) | ||||||
| ;; |   #:use-module (srfi srfi-2) | ||||||
| ;; (l0ad "crontab.scm") (sic) is inlined by the makefile. All other |   #:use-module (srfi srfi-26) | ||||||
| ;; functionality comes through modules in .../share/guile/site/mcron/*.scm. |   #:export (delete-run-file | ||||||
|  |             main)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Pull in some constants set by the builder (via autoconf) at configuration | ;; Extract the actual command name from \a command.  This returns the last | ||||||
| ;; time. Turn debugging on if indicated. | ;; part of \a command without any non-alphabetic characters.  For example | ||||||
| 
 | ;; "in.cron" and "./mcron" will return respectively "cron" and "mcron". | ||||||
| (use-modules (mcron config)) |  | ||||||
| (if config-debug (begin (debug-enable 'debug) |  | ||||||
|                         (debug-enable 'backtrace))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; To determine the name of the program, scan the first item of the command line |  | ||||||
| ;; backwards for the first non-alphabetic character. This allows names like |  | ||||||
| ;; in.cron to be accepted as an invocation of the cron command. |  | ||||||
| 
 |  | ||||||
| (use-modules (ice-9 regex) (ice-9 rdelim)) |  | ||||||
| 
 | 
 | ||||||
| (define command-name (match:substring (regexp-exec (make-regexp "[[:alpha:]]*$") | (define command-name (match:substring (regexp-exec (make-regexp "[[:alpha:]]*$") | ||||||
|                                                    (car (command-line))))) |                                                    (car (command-line))))) | ||||||
|  | @ -51,49 +41,49 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Code contributed by Sergey Poznyakoff.  Print an error message (made up from | ;; Code contributed by Sergey Poznyakoff.  Print an error message (made up from | ||||||
| ;; the parts of rest), and if the error is fatal (present and non-zero) then | ;; the parts of \a rest), and if the \a exit-code error is fatal (present and | ||||||
| ;; exit to the system with this code. | ;; non-zero) then exit to the system with \a exit-code. | ||||||
| 
 | 
 | ||||||
| (define (mcron-error exit-code . rest) | (define (mcron-error exit-code . rest) | ||||||
|   (with-output-to-port (current-error-port) |   (with-output-to-port (current-error-port) | ||||||
|     (lambda () |     (lambda () | ||||||
|       (for-each display (append (list command-name ": ") rest)) |       (for-each display | ||||||
|  |                 (cons* command-name ": " rest)) | ||||||
|       (newline))) |       (newline))) | ||||||
|   (if (and exit-code (not (eq? exit-code 0))) |   (when (and exit-code | ||||||
|       (primitive-exit exit-code))) |              (not (eq? exit-code 0))) | ||||||
|  |     (primitive-exit exit-code))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Code contributed by Sergey Poznyakoff.  Execute body. If an 'mcron-error | ;; Code contributed by Sergey Poznyakoff and improved upon by Mathieu Lirzin | ||||||
|  | ;; with newer guile features.  Execute the expressions.  If an 'mcron-error | ||||||
| ;; exception occurs, print its diagnostics and exit with its error code. | ;; exception occurs, print its diagnostics and exit with its error code. | ||||||
| 
 | 
 | ||||||
| (defmacro catch-mcron-error (. body) | (define-syntax-rule (catch-mcron-error exp ...) | ||||||
|   `(catch 'mcron-error |   (catch 'mcron-error | ||||||
|           (lambda () |     (lambda () exp ...) | ||||||
|             ,@body) |     (lambda (key exit-code . msg) | ||||||
|           (lambda (key exit-code . msg) |       (apply mcron-error exit-code msg)))) | ||||||
|             (apply mcron-error exit-code msg)))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; We will be doing a lot of testing of the command name, so it makes sense to | ;; One of the symbols \c mcron, \c crond or \c crontab according to the means | ||||||
| ;; perform the string comparisons once and for all here. | ;; of our invocation. | ||||||
| 
 | 
 | ||||||
| (define command-type (cond ((string=? command-name "mcron") 'mcron) | (define command-type | ||||||
|                            ((or (string=? command-name "cron") |   (let ((command=? (cute string=? command-name <>))) | ||||||
|                                 (string=? command-name "crond")) 'cron) |     (cond ((command=? "mcron") 'mcron) | ||||||
|                            ((string=? command-name "crontab") 'crontab) |           ((or (command=? "cron") (command=? "crond")) 'cron) | ||||||
|                            (else |           ((command=? "crontab") 'crontab) | ||||||
|                             (mcron-error 12 "The command name is invalid.")))) |           (else (mcron-error 12 "The command name is invalid."))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; There are a different set of options for the crontab personality compared to | ;; There are a different set of options for the crontab personality compared | ||||||
| ;; all the others, with the --help and --version options common to all the | ;; to all the others, with the --help and --version options common to all the | ||||||
| ;; personalities. | ;; personalities. | ||||||
| 
 | 
 | ||||||
| (use-modules (ice-9 getopt-long)) |  | ||||||
| 
 |  | ||||||
| (define options | (define options | ||||||
|   (catch |   (catch | ||||||
|    'misc-error |    'misc-error | ||||||
|  | @ -120,79 +110,86 @@ | ||||||
|                    '((version  (single-char #\v) (value #f)) |                    '((version  (single-char #\v) (value #f)) | ||||||
|                      (help     (single-char #\h) (value #f)))))) |                      (help     (single-char #\h) (value #f)))))) | ||||||
|    (lambda (key func fmt args . rest) |    (lambda (key func fmt args . rest) | ||||||
|      (mcron-error 1 (apply format (append (list #f fmt) args)))))) |      (mcron-error 1 (apply format (cons* #f fmt args)))))) | ||||||
| 
 |  | ||||||
| ;; If the user asked for the version of this program, give it to him and get |  | ||||||
| ;; out. |  | ||||||
| 
 |  | ||||||
| (if (option-ref options 'version #f) |  | ||||||
|     (begin |  | ||||||
|       (display (string-append "\n |  | ||||||
| " command-name "  (" config-package-string ")\n |  | ||||||
| Written by Dale Mellor\n |  | ||||||
| \n |  | ||||||
| Copyright (C) 2003, 2006, 2014  Dale Mellor\n |  | ||||||
| This is free software; see the source for copying conditions.  There is NO\n |  | ||||||
| warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n |  | ||||||
| ")) |  | ||||||
|       (quit))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Likewise if the user requested the help text. | ;; Display version information for \a command and quit. | ||||||
| 
 | 
 | ||||||
| (if (option-ref options 'help #f) | (define* (show-version #:optional (command command-name)) | ||||||
|     (begin |   (let* ((name       config-package-name) | ||||||
|       (display (string-append " |          (short-name (cadr (string-split name #\space))) | ||||||
| Usage: " (car (command-line)) |          (version    config-package-version)) | ||||||
| (case command-type |     (simple-format #t "~a (~a) ~a | ||||||
|  | Copyright (C) 2015 Free Software Foundation, Inc. | ||||||
| 
 | 
 | ||||||
|   ((mcron) | License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | ||||||
| " [OPTIONS] [FILES]\n | This is free software: you are free to change and redistribute it. | ||||||
| Run an mcron process according to the specifications in the FILES (`-' for\n | There is NO WARRANTY, to the extent permitted by law.\n" | ||||||
| standard input), or use all the files in ~/.config/cron (or the \n | 		   command name version) | ||||||
| deprecated ~/.cron) with .guile or .vixie extensions.\n |     (quit))) | ||||||
| \n | 
 | ||||||
|   -v, --version             Display version\n | 
 | ||||||
|   -h, --help                Display this help message\n | 
 | ||||||
|   -sN, --schedule[=]N       Display the next N jobs that will be run by mcron\n | ;; Display where to get help and send bug reports. | ||||||
|   -d, --daemon              Immediately detach the program from the terminal\n | 
 | ||||||
|                               and run as a daemon process\n | (define (show-package-information) | ||||||
|   -i, --stdin=(guile|vixie) Format of data passed as standard input or\n |   (simple-format #t "\nReport bugs to: ~a. | ||||||
|  | ~a home page: <~a> | ||||||
|  | General help using GNU software: <http://www.gnu.org/gethelp/>\n" | ||||||
|  | 		 config-package-bugreport | ||||||
|  | 		 config-package-name | ||||||
|  | 		 config-package-url)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ;; Display usage information and quit. | ||||||
|  | 
 | ||||||
|  | (define (show-help) | ||||||
|  |   (simple-format #t "Usage: ~a" command-name) | ||||||
|  |   (display | ||||||
|  |    (case command-type | ||||||
|  |      ((mcron) | ||||||
|  |       " [OPTIONS] [FILES] | ||||||
|  | Run an mcron process according to the specifications in the FILES (`-' for | ||||||
|  | standard input), or use all the files in ~/.config/cron (or the | ||||||
|  | deprecated ~/.cron) with .guile or .vixie extensions. | ||||||
|  | 
 | ||||||
|  |   -v, --version             Display version | ||||||
|  |   -h, --help                Display this help message | ||||||
|  |   -sN, --schedule[=]N       Display the next N jobs that will be run by mcron | ||||||
|  |   -d, --daemon              Immediately detach the program from the terminal | ||||||
|  |                               and run as a daemon process | ||||||
|  |   -i, --stdin=(guile|vixie) Format of data passed as standard input or | ||||||
|                               file arguments (default guile)") |                               file arguments (default guile)") | ||||||
|  |      ((cron) | ||||||
|  |       " [OPTIONS] | ||||||
|  | Unless an option is specified, run a cron daemon as a detached process, | ||||||
|  | reading all the information in the users' crontabs and in /etc/crontab. | ||||||
| 
 | 
 | ||||||
|   ((cron) |   -v, --version             Display version | ||||||
| " [OPTIONS]\n |   -h, --help                Display this help message | ||||||
| Unless an option is specified, run a cron daemon as a detached process, \n |   -sN, --schedule[=]N       Display the next N jobs that will be run by cron | ||||||
| reading all the information in the users' crontabs and in /etc/crontab.\n |   -n, --noetc               Do not check /etc/crontab for updates (HIGHLY | ||||||
| \n |  | ||||||
|   -v, --version             Display version\n |  | ||||||
|   -h, --help                Display this help message\n |  | ||||||
|   -sN, --schedule[=]N       Display the next N jobs that will be run by cron\n |  | ||||||
|   -n, --noetc               Do not check /etc/crontab for updates (HIGHLY\n |  | ||||||
|                               RECOMMENDED).") |                               RECOMMENDED).") | ||||||
|    |      ((crontab) | ||||||
|   ((crontab) |       " [-u user] file | ||||||
|            (string-append " [-u user] file\n" |        crontab [-u user] { -e | -l | -r } | ||||||
|            "       " (car (command-line)) " [-u user] { -e | -l | -r }\n" |                (default operation is replace, per 1003.2) | ||||||
|            "               (default operation is replace, per 1003.2)\n" |        -e      (edit user's crontab) | ||||||
|            "       -e      (edit user's crontab)\n" |        -l      (list user's crontab) | ||||||
|            "       -l      (list user's crontab)\n" |        -r      (delete user's crontab)") | ||||||
|            "       -r      (delete user's crontab)\n")) |      (else "\nrubbish"))) | ||||||
| 
 |   (newline) | ||||||
|   (else "rubbish")) |   (show-package-information) | ||||||
| 
 |   (quit)) | ||||||
| "\n\n |  | ||||||
| Report bugs to " config-package-bugreport ".\n |  | ||||||
| ")) |  | ||||||
|       (quit))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; This is called from the C front-end whenever a terminal signal is | ;; Remove the /var/run/cron.pid file so that crontab and other invocations of | ||||||
| ;; received. We remove the /var/run/cron.pid file so that crontab and other | ;; cron don't get the wrong idea that a daemon is currently running.  This | ||||||
| ;; invocations of cron don't get the wrong idea that a daemon is currently | ;; procedure is called from the C front-end whenever a terminal signal is | ||||||
| ;; running. | ;; received. | ||||||
| 
 | 
 | ||||||
| (define (delete-run-file) | (define (delete-run-file) | ||||||
|   (catch #t (lambda () (delete-file config-pid-file) |   (catch #t (lambda () (delete-file config-pid-file) | ||||||
|  | @ -202,47 +199,7 @@ Report bugs to " config-package-bugreport ".\n | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Setup the cron process, if appropriate. If there is already a | ;; Return standard input as a string. | ||||||
| ;; /var/run/cron.pid file, then we must assume a cron daemon is already running |  | ||||||
| ;; and refuse to start another one. |  | ||||||
| ;; |  | ||||||
| ;; Otherwise, clear the MAILTO environment variable so that output from cron |  | ||||||
| ;; jobs is sent to the various users (this may still be overridden in the |  | ||||||
| ;; configuration files), and call the function in the C wrapper to set up |  | ||||||
| ;; terminal signal responses to vector to the procedure above. The PID file will |  | ||||||
| ;; be filled in properly later when we have forked our daemon process (but not |  | ||||||
| ;; done if we are only viewing the schedules). |  | ||||||
| 
 |  | ||||||
| (if (eq? command-type 'cron) |  | ||||||
|     (begin |  | ||||||
|       (if (not (eqv? (getuid) 0)) |  | ||||||
|           (mcron-error 16 |  | ||||||
|                        "This program must be run by the root user (and should " |  | ||||||
|                        "have been installed as such).")) |  | ||||||
|       (if (access? config-pid-file F_OK) |  | ||||||
|           (mcron-error 1 |  | ||||||
| 		       "A cron daemon is already running.\n" |  | ||||||
| 		       "  (If you are sure this is not true, remove the file\n" |  | ||||||
| 		       "   " |  | ||||||
| 		       config-pid-file |  | ||||||
| 		       ".)")) |  | ||||||
|       (if (not (option-ref options 'schedule #f)) |  | ||||||
|           (with-output-to-file config-pid-file noop)) |  | ||||||
|       (setenv "MAILTO" #f) |  | ||||||
|       (c-set-cron-signals))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; Define the functions available to the configuration files. While we're here, |  | ||||||
| ;; we'll get the core loaded as well. |  | ||||||
| 
 |  | ||||||
| (use-modules (mcron core) |  | ||||||
|              (mcron job-specifier) |  | ||||||
|              (mcron vixie-specification)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; Procedure to slurp the standard input into a string. |  | ||||||
| 
 | 
 | ||||||
| (define (stdin->string) | (define (stdin->string) | ||||||
|   (with-output-to-string (lambda () (do ((in (read-char) (read-char))) |   (with-output-to-string (lambda () (do ((in (read-char) (read-char))) | ||||||
|  | @ -251,183 +208,83 @@ Report bugs to " config-package-bugreport ".\n | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Now we have the procedures in place for dealing with the contents of | ;; Return a thunk which process each file in \a directory with \a proc.  The | ||||||
| ;; configuration files, the crontab personality is able to validate such | ;; \a directory must be a directory name.  The \a proc argument must be a | ||||||
| ;; files. If the user requested the crontab personality, we load and run the | ;; procedure that takes one file name argument. | ||||||
| ;; code here and then get out. |  | ||||||
| 
 | 
 | ||||||
| (if (eq? command-type 'crontab) | (define (proc-in-directory directory proc) | ||||||
|     (begin |   (let ((dir (opendir directory))) | ||||||
|       (load "crontab.scm") |     (do ((file-name (readdir dir) (readdir dir))) | ||||||
|       (quit))) |         ((eof-object? file-name) (closedir dir)) | ||||||
|  |       (proc file-name)))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Code contributed by Sergey Poznyakoff.  Determine if the given file is a | ;; Process \a file-name according its extension.  When \a guile-syntax? is \c | ||||||
| ;; regular file or not. | ;; TRUE, force guile syntax usage.  If \a file-name format is not recognized, | ||||||
|  | ;; it is silently ignored (this deals properly with most editors' backup | ||||||
|  | ;; files, for instance). | ||||||
| 
 | 
 | ||||||
| (define (regular-file? file) | (define process-user-file | ||||||
|   (catch 'system-error |   (let ((guile-regexp (make-regexp "\\.gui(le)?$")) | ||||||
| 	 (lambda () |         (vixie-regexp (make-regexp "\\.vix(ie)?$"))) | ||||||
| 	   (eq? (stat:type (stat file)) 'regular)) |     (lambda* (file-path #:optional assume-guile) | ||||||
| 	 (lambda (key call fmt args . rest) |       (cond ((string=? "-" file-path) | ||||||
| 	   (mcron-error 0 (apply format (append (list #f fmt) args))) |              (if (string=? (option-ref options 'stdin "guile") "vixie") | ||||||
| 	   #f))) |                  (read-vixie-port (current-input-port)) | ||||||
|  |                  (eval-string (stdin->string)))) | ||||||
|  |             ((regexp-exec vixie-regexp file-path) | ||||||
|  |              (read-vixie-file file-path)) | ||||||
|  |             ((or assume-guile | ||||||
|  |                  (regexp-exec guile-regexp file-path)) | ||||||
|  |              (load file-path)))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Procedure which processes any configuration file according to the | ;; Process files in $XDG_CONFIG_HOME/cron and/or ~/.cron directories (if | ||||||
| ;; extension. If a file is not recognized, it is silently ignored (this deals | ;; $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead). | ||||||
| ;; properly with most editors' backup files, for instance). |  | ||||||
| 
 |  | ||||||
| (define guile-file-regexp (make-regexp "\\.gui(le)?$")) |  | ||||||
| (define vixie-file-regexp (make-regexp "\\.vix(ie)?$")) |  | ||||||
| 
 |  | ||||||
| (define (process-user-file file-path . assume-guile) |  | ||||||
|   (cond ((string=? file-path "-") |  | ||||||
|                (if (string=? (option-ref options 'stdin "guile") "vixie") |  | ||||||
|                    (read-vixie-port (current-input-port)) |  | ||||||
|                    (eval-string (stdin->string)))) |  | ||||||
|         ((or (not (null? assume-guile)) |  | ||||||
|              (regexp-exec guile-file-regexp file-path)) |  | ||||||
|          (load file-path)) |  | ||||||
|         ((regexp-exec vixie-file-regexp file-path) |  | ||||||
|          (read-vixie-file file-path)))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; Procedure to run through all the files in a user's ~/.cron and/or |  | ||||||
| ;; $XDG_CONFIG_HOME/cron or ~/.config/cron directories (only happens under the |  | ||||||
| ;; mcron personality). |  | ||||||
| 
 | 
 | ||||||
| (define (process-files-in-user-directory) | (define (process-files-in-user-directory) | ||||||
|   (let ((errors 0) |   (let ((errors 0) | ||||||
|         (home-directory (passwd:dir (getpw (getuid))))) |         (home-directory (passwd:dir (getpw (getuid))))) | ||||||
|     (map (lambda (config-directory) |     (map (lambda (dir) | ||||||
|           (catch #t |            (catch #t | ||||||
|                  (lambda () |                   (lambda () | ||||||
|                    (let ((directory (opendir config-directory))) |                     (proc-in-directory | ||||||
|                      (do ((file-name (readdir directory) (readdir directory))) |                      dir | ||||||
|                          ((eof-object? file-name) (closedir directory)) |                      (lambda (file-name) | ||||||
|                        (process-user-file (string-append config-directory |                        (process-user-file (string-append dir "/" file-name))))) | ||||||
|                                                          "/" |                   (lambda (key . args) | ||||||
|                                                          file-name))))) |                     (set! errors (1+ errors))))) | ||||||
|                  (lambda (key . args) |          (list (string-append home-directory "/.cron") | ||||||
|                    (set! errors (1+ errors))))) |                (string-append (or (getenv "XDG_CONFIG_HOME") | ||||||
|           (list (string-append home-directory "/.cron") |                                   (string-append home-directory "/.config")) | ||||||
|                 (string-append (or (getenv "XDG_CONFIG_HOME") |                               "/cron"))) | ||||||
|                                    (string-append home-directory "/.config")) |     (when (eq? 2 errors) | ||||||
|                                "/cron"))) |       (mcron-error 13 | ||||||
|     (if (eq? 2 errors) |         "Cannot read files in your ~/.config/cron (or ~/.cron) directory.")))) | ||||||
|         (mcron-error 13 |  | ||||||
|                      "Cannot read files in your ~/.config/cron (or ~/.cron) " |  | ||||||
|                      "directory.")))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; Procedure to check that a user name is in the passwd database (it may happen | ;; Process all the files in the crontab directory.  When the job procedure is | ||||||
| ;; that a user is removed after creating a crontab). If the user name is valid, | ;; run on behalf of the configuration files, the jobs are registered on the | ||||||
| ;; the full passwd entry for that user is returned to the caller. | ;; system with the appropriate user.  Only root should be able to perform this | ||||||
| 
 | ;; operation.  The permissions on the /var/cron/tabs directory enforce this. | ||||||
| (define (valid-user user-name) |  | ||||||
|   (setpwent) |  | ||||||
|   (do ((entry (getpw) (getpw))) |  | ||||||
|       ((or (not entry) |  | ||||||
|            (string=? (passwd:name entry) user-name)) |  | ||||||
|        (endpwent) |  | ||||||
|        entry))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; Procedure to process all the files in the crontab directory, making sure that |  | ||||||
| ;; each file is for a legitimate user and setting the configuration-user to that |  | ||||||
| ;; user. In this way, when the job procedure is run on behalf of the |  | ||||||
| ;; configuration files, the jobs are registered with the system with the |  | ||||||
| ;; appropriate user. Note that only the root user should be able to perform this |  | ||||||
| ;; operation, but we leave it to the permissions on the /var/cron/tabs directory |  | ||||||
| ;; to enforce this. |  | ||||||
| 
 |  | ||||||
| (use-modules (srfi srfi-2))  ;; For and-let*. |  | ||||||
| 
 | 
 | ||||||
| (define (process-files-in-system-directory) | (define (process-files-in-system-directory) | ||||||
|   (catch #t |   (catch #t | ||||||
|          (lambda () |     (lambda () | ||||||
|            (let ((directory (opendir config-spool-dir))) |       (proc-in-directory | ||||||
|              (do ((file-name (readdir directory) (readdir directory))) |          config-spool-dir | ||||||
|                  ((eof-object? file-name)) |          (lambda (user-name) | ||||||
|                (and-let* ((user (valid-user file-name))) |            (and-let* ((user (false-if-exception (getpwnam user-name)))) | ||||||
|                          (set-configuration-user user)         ;; / ?? !!!! |                      (set-configuration-user user) | ||||||
|                          (catch-mcron-error |                      (catch-mcron-error | ||||||
|                           (read-vixie-file (string-append config-spool-dir |                        (read-vixie-file | ||||||
|                                                           "/" |                           (string-append config-spool-dir "/" user-name))))))) | ||||||
|                                                           file-name))))))) |     (lambda (key . args) | ||||||
|          (lambda (key . args) |       (mcron-error 4 | ||||||
|            (mcron-error |          "You do not have permission to access the system crontabs.")))) | ||||||
|             4 |  | ||||||
|             "You do not have permission to access the system crontabs.")))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; 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 |  | ||||||
| ;; passed on the command line, or else all the ones in the user's .config/cron |  | ||||||
| ;; (or .cron) directory. If we are running under the cron personality, we read |  | ||||||
| ;; the /var/cron/tabs directory and also the /etc/crontab file. |  | ||||||
| 
 |  | ||||||
| (case command-type |  | ||||||
|   ((mcron) (if (null? (option-ref options '() '())) |  | ||||||
|                 (process-files-in-user-directory) |  | ||||||
|                 (for-each (lambda (file-path) |  | ||||||
|                             (process-user-file file-path #t)) |  | ||||||
|                           (option-ref options '() '())))) |  | ||||||
|    |  | ||||||
|   ((cron) (process-files-in-system-directory) |  | ||||||
|    (use-system-job-list) |  | ||||||
|    (catch-mcron-error |  | ||||||
|     (read-vixie-file "/etc/crontab" parse-system-vixie-line)) |  | ||||||
|    (use-user-job-list) |  | ||||||
|    (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 "root") |  | ||||||
|          (job '(- (next-minute-from (next-minute)) 6) |  | ||||||
|               check-system-crontab |  | ||||||
|               "/etc/crontab update checker."))))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; If the user has requested a schedule of jobs that will run, we provide the |  | ||||||
| ;; information here and then get out. |  | ||||||
| ;; |  | ||||||
| ;; Start by determining the number of time points in the future that output is |  | ||||||
| ;; required for. This may be provided on the command line as a parameter to the |  | ||||||
| ;; --schedule option, or else we assume a default of 8. Finally, ensure that the |  | ||||||
| ;; count is some positive integer. |  | ||||||
| 
 |  | ||||||
| (and-let* ((count (option-ref options 'schedule #f))) |  | ||||||
|           (set! count (string->number count)) |  | ||||||
|           (display (get-schedule (if (<= count 0) 1 count))) |  | ||||||
|           (quit)) |  | ||||||
|      |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ;; If we are supposed to run as a daemon process (either a --daemon option has |  | ||||||
| ;; been explicitly used, or we are running as cron or crond), detach from the |  | ||||||
| ;; terminal now. If we are running as cron, we can now write the PID file. |  | ||||||
| 
 |  | ||||||
| (if (option-ref options 'daemon (eq? command-type 'cron)) |  | ||||||
|     (begin |  | ||||||
|       (if (not (eqv? (primitive-fork) 0)) |  | ||||||
|           (quit)) |  | ||||||
|       (setsid) |  | ||||||
|       (if (eq? command-type 'cron) |  | ||||||
|           (with-output-to-file config-pid-file |  | ||||||
|             (lambda () (display (getpid)) (newline)))))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -436,32 +293,30 @@ option.\n") | ||||||
| ;; inform the main wait-run-wait execution loop to listen for incoming messages | ;; inform the main wait-run-wait execution loop to listen for incoming messages | ||||||
| ;; on this socket. | ;; on this socket. | ||||||
| 
 | 
 | ||||||
| (define fd-list '()) | (define (cron-file-descriptors) | ||||||
| 
 |   (if (eq? command-type 'cron) | ||||||
| (if (eq? command-type 'cron) |       (catch #t | ||||||
|     (catch #t |              (lambda () | ||||||
|            (lambda () |                (let ((socket (socket AF_UNIX SOCK_STREAM 0))) | ||||||
|              (let ((socket (socket AF_UNIX SOCK_STREAM 0))) |                  (bind socket AF_UNIX config-socket-file) | ||||||
|                (bind socket AF_UNIX config-socket-file) |                  (listen socket 5) | ||||||
|                (listen socket 5) |                  (list socket))) | ||||||
|                (set! fd-list (list socket)))) |              (lambda (key . args) | ||||||
|            (lambda (key . args) |                (delete-file config-pid-file) | ||||||
|              (delete-file config-pid-file) |                (mcron-error 1  | ||||||
|              (mcron-error 1 |                  "Cannot bind to UNIX socket " config-socket-file))) | ||||||
|                           "Cannot bind to UNIX socket " |       '())) | ||||||
|                           config-socket-file)))) |  | ||||||
| 		      |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ;; This function is called whenever a message comes in on the above socket. We | ;; Read a user name from the socket, dealing with the /etc/crontab special | ||||||
| ;; read a user name from the socket, dealing with the "/etc/crontab" special |  | ||||||
| ;; case, remove all the user's jobs from the job list, and then re-read the | ;; case, remove all the user's jobs from the job list, and then re-read the | ||||||
| ;; user's updated file. In the special case we drop all the system jobs and | ;; user's updated file.  In the special case drop all the system jobs and | ||||||
| ;; re-read the /etc/crontab file. | ;; re-read the /etc/crontab file.  This function should be called whenever a | ||||||
|  | ;; message comes in on the above socket. | ||||||
| 
 | 
 | ||||||
| (define (process-update-request) | (define (process-update-request fd-list) | ||||||
|   (let* ((socket (car (accept (car fd-list)))) |   (let* ((socket    (car (accept (car fd-list)))) | ||||||
|          (user-name (read-line socket))) |          (user-name (read-line socket))) | ||||||
|     (close socket) |     (close socket) | ||||||
|     (set-configuration-time (current-time)) |     (set-configuration-time (current-time)) | ||||||
|  | @ -475,29 +330,123 @@ option.\n") | ||||||
|          (let ((user (getpw user-name))) |          (let ((user (getpw user-name))) | ||||||
|            (remove-user-jobs user) |            (remove-user-jobs user) | ||||||
|            (set-configuration-user user) |            (set-configuration-user user) | ||||||
|            (read-vixie-file (string-append config-spool-dir "/" user-name))))))) |            (read-vixie-file  | ||||||
|  |                          (string-append config-spool-dir "/" user-name))))))) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ;; Entry point. | ||||||
|  | ;; | ||||||
|  | ;; This is the 'main' routine for the whole system; this module is the global | ||||||
|  | ;; entry point (after the minimal C wrapper); to all intents and purposes the | ||||||
|  | ;; program is pure Guile and starts here. | ||||||
| 
 | 
 | ||||||
| ;; Added by Sergey Poznyakoff.  This no-op will collect zombie child processes | (define (main . args) | ||||||
| ;; as soon as they die.  This is a big improvement as previously they stayed |   ;; Added by Sergey Poznyakoff.  This no-op will collect zombie child processes | ||||||
| ;; around the system until the next time mcron wakes to fire a new job off. |   ;; as soon as they die.  This is a big improvement as previously they stayed | ||||||
|  |   ;; around the system until the next time mcron wakes to fire a new job off. | ||||||
|  |   (when config-debug | ||||||
|  |         (debug-enable 'backtrace)) | ||||||
|  |   (when (option-ref options 'version #f) | ||||||
|  |         (show-version)) | ||||||
|  |   (when (option-ref options 'help #f) | ||||||
|  |         (show-help)) | ||||||
|  |    | ||||||
|  |   ;; 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. | ||||||
|  |   ;; | ||||||
|  |   ;; Otherwise, clear the MAILTO environment variable so that output from cron | ||||||
|  |   ;; jobs is sent to the various users (this may still be overridden in the | ||||||
|  |   ;; configuration files), and call the function in the C wrapper to set up | ||||||
|  |   ;; terminal signal responses to vector to the procedure above. The PID file | ||||||
|  |   ;; will be filled in properly later when we have forked our daemon process | ||||||
|  |   ;; (but not done if we are only viewing the schedules). | ||||||
|  |   (when (eq? command-type 'cron) | ||||||
|  |     (unless (eqv? (getuid) 0) | ||||||
|  |       (mcron-error 16 | ||||||
|  |         "This program must be run by the root user (and should have been " | ||||||
|  |         "installed as such).")) | ||||||
|  |     (when (access? config-pid-file F_OK) | ||||||
|  |       (mcron-error 1 | ||||||
|  |         "A cron daemon is already running.\n  (If you are sure this is not" | ||||||
|  |         " true, remove the file\n   " config-pid-file ".)")) | ||||||
|  |     (unless (option-ref options 'schedule #f) | ||||||
|  |       (with-output-to-file config-pid-file noop)) | ||||||
|  |     (setenv "MAILTO" #f) | ||||||
|  |     ;; Mathieu Lirzin: At compile time, this yields a "possibly unbound | ||||||
|  |     ;; variable" warning, but this is OK since it is bound in the C wrapper. | ||||||
|  |     (c-set-cron-signals)) | ||||||
| 
 | 
 | ||||||
| ;; Unfortunately it seems to interact badly with the select system call, |   ;; Now we have the procedures in place for dealing with the contents of | ||||||
| ;; wreaking havoc... |   ;; configuration files, the crontab personality is able to validate such | ||||||
|  |   ;; files. If the user requested the crontab personality, we load and run the | ||||||
|  |   ;; code here and then get out. | ||||||
|  |   (when (eq? command-type 'crontab) | ||||||
|  |     (load "crontab.scm") | ||||||
|  |     (quit)) | ||||||
| 
 | 
 | ||||||
| ;; (sigaction SIGCHLD (lambda (sig) noop) SA_RESTART) |   ;; 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 passed on the command line, or else all the ones in the user's | ||||||
|  |   ;; .config/cron (or .cron) directory. If we are running under the cron | ||||||
|  |   ;; personality, we read the /var/cron/tabs directory and also the | ||||||
|  |   ;; /etc/crontab file. | ||||||
|  |   (case command-type | ||||||
|  |     ((mcron) | ||||||
|  |      (if (null? (option-ref options '() '())) | ||||||
|  |          (process-files-in-user-directory) | ||||||
|  |          (for-each (lambda (file-path) (process-user-file file-path  | ||||||
|  |                                                           'guile-syntax)) | ||||||
|  |                    (option-ref options '() '())))) | ||||||
|  |     ((cron) | ||||||
|  |      (process-files-in-system-directory) | ||||||
|  |      (use-system-job-list) | ||||||
|  |      (catch-mcron-error (read-vixie-file "/etc/crontab" | ||||||
|  |                                          parse-system-vixie-line)) | ||||||
|  |      (use-user-job-list) | ||||||
|  |      (unless (option-ref options 'noetc #f) | ||||||
|  |        (display "\ | ||||||
|  | WARNING: cron will check for updates to /etc/crontab EVERY MINUTE. If you do | ||||||
|  | not use this file, or you are prepared to manually restart cron whenever you | ||||||
|  | make a change, then it is HIGHLY RECOMMENDED that you use the --noetc | ||||||
|  | option.\n") | ||||||
|  |        (set-configuration-user "root") | ||||||
|  |        (job '(- (next-minute-from (next-minute)) 6) | ||||||
|  |             check-system-crontab | ||||||
|  |             "/etc/crontab update checker.")))) | ||||||
| 
 | 
 | ||||||
|  |   ;; If the user has requested a schedule of jobs that will run, we provide | ||||||
|  |   ;; the information here and then get out.  Start by determining the number | ||||||
|  |   ;; of time points in the future that output is required for. This may be | ||||||
|  |   ;; provided on the command line as a parameter to the --schedule option, or | ||||||
|  |   ;; else we assume a default of 8. Finally, ensure that the count is some | ||||||
|  |   ;; positive integer. | ||||||
|  |   (and-let* ((count (option-ref options 'schedule #f))) | ||||||
|  |             (set! count (string->number count)) | ||||||
|  |             (display (get-schedule (max 1 count))) | ||||||
|  |             (quit)) | ||||||
| 
 | 
 | ||||||
| 
 |   ;; If we are supposed to run as a daemon process (either a --daemon option | ||||||
| ;; Now the main loop. Forever execute the run-job-loop procedure in the mcron |   ;; has been explicitly used, or we are running as cron or crond), detach | ||||||
| ;; core, and when it drops out (can only be because a message has come in on the |   ;; from the terminal now. If we are running as cron, we can now write the | ||||||
| ;; socket) we process the socket request before restarting the loop again. |   ;; PID file. | ||||||
| ;; Sergey Poznyakoff: we can also drop out of run-job-loop because of a SIGCHLD, |   (when (option-ref options 'daemon (eq? command-type 'cron)) | ||||||
| ;; so must test fd-list. |     (unless (eqv? (primitive-fork) 0) | ||||||
| 
 |             (quit)) | ||||||
| (catch-mcron-error |     (setsid) | ||||||
|  (while #t |     (when (eq? command-type 'cron) | ||||||
|         (run-job-loop fd-list) |           (with-output-to-file config-pid-file | ||||||
|         (if (not (null? fd-list)) |             (lambda () (display (getpid)) (newline))))) | ||||||
|             (process-update-request)))) |    | ||||||
|  |   ;; Now the main loop.  Forever execute the run-job-loop procedure in the | ||||||
|  |   ;; mcron core, and when it drops out (can only be because a message has come | ||||||
|  |   ;; in on the socket) we process the socket request before restarting the | ||||||
|  |   ;; loop again.  Sergey Poznyakoff: we can also drop out of run-job-loop | ||||||
|  |   ;; because of a SIGCHLD, so must test fd-list. | ||||||
|  |   (catch-mcron-error | ||||||
|  |    (let ((fd-list (cron-file-descriptors))) | ||||||
|  |      (while #t | ||||||
|  |        (run-job-loop fd-list) | ||||||
|  |        (unless (null? fd-list) | ||||||
|  |          (process-update-request fd-list)))))) | ||||||
|  |  | ||||||
|  | @ -1,15 +1,60 @@ | ||||||
| EXTRA_DIST = main.scm mcron-core.scm vixie-specification.scm \ | ## Makefile for the scm/mcron directory of mcron. | ||||||
|              crontab.scm environment.scm job-specifier.scm redirect.scm \ |  | ||||||
|              vixie-time.scm |  | ||||||
| 
 | 
 | ||||||
| pkgdata_DATA = core.scm environment.scm job-specifier.scm redirect.scm \ | #  Copyright (C) 2015 Mathieu Lirzin | ||||||
|                vixie-time.scm vixie-specification.scm config.scm | # | ||||||
|  | #  This file is part of GNU mcron. | ||||||
|  | #  | ||||||
|  | #  GNU mcron is free software: you can redistribute it and/or modify it under | ||||||
|  | #  the terms of the GNU General Public License as published by the Free Software | ||||||
|  | #  Foundation, either version 3 of the License, or (at your option) any later | ||||||
|  | #  version. | ||||||
|  | #  | ||||||
|  | #  GNU mcron is distributed in the hope that it will be useful, but WITHOUT ANY | ||||||
|  | #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||||||
|  | #  A PARTICULAR PURPOSE.  See the GNU General Public License for more details. | ||||||
|  | #  | ||||||
|  | #  You should have received a copy of the GNU General Public License along with | ||||||
|  | #  GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | ## Process this file with automake to produce makefile.in. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # If you're wondering, the configure script keeps deleting all files with a name | MODULES = environment.scm			\ | ||||||
| # like core.*, so we have to keep re-making it (I lost a good day's work because |           job-specifier.scm			\ | ||||||
| # of this). |           main.scm					\ | ||||||
|  |           mcron-core.scm			\ | ||||||
|  |           redirect.scm				\ | ||||||
|  |           vixie-specification.scm	\ | ||||||
|  |           vixie-time.scm | ||||||
| 
 | 
 | ||||||
| core.scm : mcron-core.scm | GOBJECTS = $(MODULES:%.scm=%.go) config.go | ||||||
| 	$(CP) mcron-core.scm core.scm |  | ||||||
| 
 | 
 | ||||||
|  | nobase_dist_guilemodule_DATA = $(MODULES) crontab.scm | ||||||
|  | nobase_nodist_guilemodule_DATA = $(GOBJECTS) config.scm | ||||||
|  | 
 | ||||||
|  | CLEANFILES = $(GOBJECTS) | ||||||
|  | 
 | ||||||
|  | AM_V_GUILEC = $(AM_V_GUILEC_$(V)) | ||||||
|  | AM_V_GUILEC_ = $(AM_V_GUILEC_$(AM_DEFAULT_VERBOSITY)) | ||||||
|  | AM_V_GUILEC_0 = @echo "  GUILEC" $@; | ||||||
|  | 
 | ||||||
|  | # Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling.  Otherwise, if | ||||||
|  | # $GUILE_LOAD_COMPILED_PATH contains $(moduledir), we may find .go files in | ||||||
|  | # there that are newer than the local .scm files (for instance because the | ||||||
|  | # user ran 'make install' recently).  When that happens, we end up loading | ||||||
|  | # those previously-installed .go files, which may be stale, thereby breaking | ||||||
|  | # the whole thing. | ||||||
|  | # | ||||||
|  | # XXX: Use the C locale for when Guile lacks | ||||||
|  | # <http://git.sv.gnu.org/cgit/guile.git/commit/?h=stable-2.0&id=e2c6bf3866d1186c60bacfbd4fe5037087ee5e3f>. | ||||||
|  | .scm.go: | ||||||
|  | 	$(AM_V_GUILEC)$(MKDIR_P) `dirname "$@"` ;			\ | ||||||
|  | 	unset GUILE_LOAD_COMPILED_PATH ;					\ | ||||||
|  | 	LC_ALL=C											\ | ||||||
|  | 	$(GUILD) compile									\ | ||||||
|  | 	  -L "$(top_builddir)/scm" -L "$(top_srcdir)/scm"	\ | ||||||
|  | 	  -Wformat -Wunbound-variable -Warity-mismatch		\ | ||||||
|  | 	  --target="$(host)"								\ | ||||||
|  | 	  -o "$@" "$<" | ||||||
|  | 
 | ||||||
|  | SUFFIXES = .go | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| ;;   Copyright (C) 2003 Dale Mellor | ;;   Copyright (C) 2003, 2015 Dale Mellor | ||||||
| ;;  | ;;  | ||||||
| ;;   This file is part of GNU mcron. | ;;   This file is part of GNU mcron. | ||||||
| ;; | ;; | ||||||
|  | @ -17,8 +17,9 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| (define-module (mcron core) | (define-module (mcron mcron-core) | ||||||
|   #:use-module (mcron environment) |   #:use-module (mcron environment) | ||||||
|  |   #:use-module (srfi srfi-9) | ||||||
|   #:export     (add-job |   #:export     (add-job | ||||||
|                 remove-user-jobs |                 remove-user-jobs | ||||||
|                 get-schedule |                 get-schedule | ||||||
|  | @ -38,7 +39,7 @@ | ||||||
| 
 | 
 | ||||||
| ;; The list of all jobs known to the system. Each element of the list is | ;; The list of all jobs known to the system. Each element of the list is | ||||||
| ;; | ;; | ||||||
| ;;  (vector user next-time-function action environment displayable next-time) | ;;  (make-job user next-time-function action environment displayable next-time) | ||||||
| ;; | ;; | ||||||
| ;; where action must be a procedure, and the environment is an alist of | ;; where action must be a procedure, and the environment is an alist of | ||||||
| ;; modifications that need making to the UNIX environment before the action is | ;; modifications that need making to the UNIX environment before the action is | ||||||
|  | @ -60,18 +61,17 @@ | ||||||
| (define (use-system-job-list) (set! configuration-source 'system)) | (define (use-system-job-list) (set! configuration-source 'system)) | ||||||
| (define (use-user-job-list) (set! configuration-source 'user)) | (define (use-user-job-list) (set! configuration-source 'user)) | ||||||
| 
 | 
 | ||||||
| 
 | ;; A cron job. | ||||||
| 
 | (define-record-type <job> | ||||||
| ;; Convenience functions for getting and setting the elements of a job object. |   (make-job user time-proc action environment displayable next-time) | ||||||
| 
 |   job? | ||||||
| (define (job:user job)                (vector-ref job 0)) |   (user        job:user)                ;string : user passwd entry | ||||||
| (define (job:next-time-function job)  (vector-ref job 1)) |   (time-proc   job:next-time-function)  ;proc   : with one 'time' parameter | ||||||
| (define (job:action job)              (vector-ref job 2)) |   (action      job:action)              ;thunk  : user's code | ||||||
| (define (job:environment job)         (vector-ref job 3)) |   (environment job:environment)         ;alist  : environment variables | ||||||
| (define (job:displayable job)         (vector-ref job 4)) |   (displayable job:displayable)         ;string : visible in schedule | ||||||
| (define (job:next-time job)           (vector-ref job 5)) |   (next-time   job:next-time            ;number : time in UNIX format | ||||||
| 
 |                job:next-time-set!)) | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| ;; Remove jobs from the user-job-list belonging to this user. | ;; Remove jobs from the user-job-list belonging to this user. | ||||||
| 
 | 
 | ||||||
|  | @ -97,12 +97,12 @@ | ||||||
| 
 | 
 | ||||||
| (define (add-job time-proc action displayable configuration-time | (define (add-job time-proc action displayable configuration-time | ||||||
|                  configuration-user) |                  configuration-user) | ||||||
|   (let ((entry (vector configuration-user |   (let ((entry (make-job configuration-user | ||||||
|                        time-proc |                          time-proc | ||||||
|                        action |                          action | ||||||
|                        (get-current-environment-mods-copy) |                          (get-current-environment-mods-copy) | ||||||
|                        displayable |                          displayable | ||||||
|                        (time-proc configuration-time)))) |                          (time-proc configuration-time)))) | ||||||
|     (if (eq? configuration-source 'user) |     (if (eq? configuration-source 'user) | ||||||
|       (set! user-job-list (cons entry user-job-list)) |       (set! user-job-list (cons entry user-job-list)) | ||||||
|       (set! system-job-list (cons entry system-job-list))))) |       (set! system-job-list (cons entry system-job-list))))) | ||||||
|  | @ -165,18 +165,17 @@ | ||||||
|     (lambda () |     (lambda () | ||||||
|       (do ((count count (- count 1))) |       (do ((count count (- count 1))) | ||||||
|           ((eqv? count 0)) |           ((eqv? count 0)) | ||||||
|         (and-let* ((next-jobs (find-next-jobs)) |         (and-let* | ||||||
|                    (time (car next-jobs)) |          ((next-jobs (find-next-jobs)) | ||||||
|                    (date-string (strftime "%c %z\n" (localtime time)))) |           (time (car next-jobs)) | ||||||
|           (for-each (lambda (job) |           (date-string (strftime "%c %z\n" (localtime time)))) | ||||||
|                       (display date-string) |          (for-each (lambda (job) | ||||||
|                       (display (job:displayable job)) |                      (display date-string) | ||||||
|                       (newline)(newline) |                      (display (job:displayable job)) | ||||||
|                       (vector-set! job |                      (newline)(newline) | ||||||
|                                    5 |                      (job:next-time-set! job ((job:next-time-function job) | ||||||
|                                    ((job:next-time-function job) |                                               (job:next-time job)))) | ||||||
|                                                           (job:next-time job)))) |                    (cdr next-jobs))))))) | ||||||
|                     (cdr next-jobs))))))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -195,22 +194,21 @@ | ||||||
| ;; to run. | ;; to run. | ||||||
| 
 | 
 | ||||||
| (define (run-jobs jobs-list) | (define (run-jobs jobs-list) | ||||||
|   (for-each (lambda (job) |   (for-each | ||||||
|               (if (eqv? (primitive-fork) 0) |    (lambda (job) | ||||||
|                   (begin |      (if (eqv? (primitive-fork) 0) | ||||||
|                     (setgid (passwd:gid (job:user job))) |          (begin | ||||||
|                     (setuid (passwd:uid (job:user job))) |            (setgid (passwd:gid (job:user job))) | ||||||
|                     (chdir (passwd:dir (job:user job))) |            (setuid (passwd:uid (job:user job))) | ||||||
|                     (modify-environment (job:environment job) (job:user job)) |            (chdir (passwd:dir (job:user job))) | ||||||
|                     ((job:action job)) |            (modify-environment (job:environment job) (job:user job)) | ||||||
|                     (primitive-exit 0)) |            ((job:action job)) | ||||||
|                   (begin |            (primitive-exit 0)) | ||||||
|                     (set! number-children (+ number-children 1)) |          (begin | ||||||
|                     (vector-set! job |            (set! number-children (+ number-children 1)) | ||||||
|                                  5 |            (job:next-time-set! job ((job:next-time-function job) | ||||||
|                                  ((job:next-time-function job) |                                     (current-time)))))) | ||||||
|                                                             (current-time)))))) |    jobs-list)) | ||||||
|             jobs-list)) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ | ||||||
| 
 | 
 | ||||||
| (define-module (mcron redirect) | (define-module (mcron redirect) | ||||||
|   #:export (with-mail-out) |   #:export (with-mail-out) | ||||||
|  |   #:use-module (ice-9 regex) | ||||||
|   #:use-module ((mcron config) :select (config-sendmail)) |   #:use-module ((mcron config) :select (config-sendmail)) | ||||||
|   #:use-module (mcron vixie-time)) |   #:use-module (mcron vixie-time)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ | ||||||
|             read-vixie-file |             read-vixie-file | ||||||
|             check-system-crontab) |             check-system-crontab) | ||||||
|   #:use-module ((mcron config) :select (config-socket-file)) |   #:use-module ((mcron config) :select (config-socket-file)) | ||||||
|   #:use-module (mcron core) |   #:use-module (mcron mcron-core) | ||||||
|   #:use-module (mcron job-specifier) |   #:use-module (mcron job-specifier) | ||||||
|   #:use-module (mcron redirect) |   #:use-module (mcron redirect) | ||||||
|   #:use-module (mcron vixie-time)) |   #:use-module (mcron vixie-time)) | ||||||
|  | @ -162,13 +162,11 @@ | ||||||
|                          (parse-vixie-environment line) |                          (parse-vixie-environment line) | ||||||
|                          (parse-vixie-line line))) |                          (parse-vixie-line line))) | ||||||
|                    (lambda (key exit-code . msg) |                    (lambda (key exit-code . msg) | ||||||
|                      (throw |                      (throw 'mcron-error exit-code | ||||||
|                       'mcron-error |                             (apply string-append | ||||||
|                       exit-code |                                    (number->string report-line) | ||||||
|                       (apply string-append |                                    ": " | ||||||
|                              (number->string report-line) |                                    msg))))))))) | ||||||
|                              ": " |  | ||||||
|                              msg))))))))) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dale Mellor
				Dale Mellor