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 | ||||
| INSTALL | ||||
| aclocal.m4 | ||||
| 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 | ||||
| config.cache | ||||
| config.log | ||||
| config.scm | ||||
| config.status | ||||
|  | @ -20,8 +31,6 @@ install-sh | |||
| makefile | ||||
| makefile.in | ||||
| /mcron | ||||
| mcron.c | ||||
| /mdate-sh | ||||
| *.o | ||||
| missing | ||||
| texinfo.tex | ||||
|  |  | |||
							
								
								
									
										5
									
								
								AUTHORS
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								AUTHORS
									
										
									
									
									
								
							|  | @ -1,6 +1,6 @@ | |||
| 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, | ||||
|   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, | ||||
|     on the understanding that this is permitted under his copyright notice, | ||||
|     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. | ||||
|  |  | |||
							
								
								
									
										13
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								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> | ||||
| 
 | ||||
| 	* configure.ac: Fix package name and bug reports email address. | ||||
|  |  | |||
							
								
								
									
										9
									
								
								TODO
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								TODO
									
										
									
									
									
								
							|  | @ -1,5 +1,6 @@ | |||
| GNU mcron --- TODO                                  -*-text-*- | ||||
| 
 | ||||
|   Copyright (C) 2015  Mathieu Lirzin | ||||
|   Copyright (C) 2003, 2005, 2006, 2014  Dale Mellor | ||||
| 
 | ||||
|   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 | ||||
|        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... | ||||
|  |  | |||
							
								
								
									
										25
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								configure.ac
									
										
									
									
									
								
							|  | @ -2,8 +2,7 @@ | |||
| # Process this file with autoconf to produce a configure script. | ||||
| 
 | ||||
|    | ||||
| #    Copyright (C) 2003, 2005, 2012, 2014  Dale Mellor | ||||
| #    Copyright (C) 2015  Mathieu Lirzin | ||||
| #    Copyright (C) 2003, 2005, 2012, 2014, 2015  Dale Mellor | ||||
| #    | ||||
| #    This file is part of GNU mcron. | ||||
| #  | ||||
|  | @ -24,8 +23,13 @@ | |||
| AC_PREREQ(2.61) | ||||
| AC_INIT([GNU Mcron], [1.0.8], [bug-mcron@gnu.org]) | ||||
| 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_ARG_ENABLE(debug, | ||||
|  | @ -45,12 +49,19 @@ AC_SUBST(CONFIG_DEBUG) | |||
| # We have no interest (hence a no-op), but Debian wants this. | ||||
| AC_ARG_ENABLE(maintainer-mode) | ||||
| 
 | ||||
| 
 | ||||
| AC_CANONICAL_HOST | ||||
| AC_PROG_AWK | ||||
| AC_PROG_EGREP | ||||
| 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. | ||||
|    | ||||
|  | @ -64,10 +75,6 @@ AC_CHECK_PROGS(HEAD, head) | |||
| if test "x$ac_cv_prog_HEAD" = "x"; then | ||||
|    AC_MSG_ERROR(head not found) | ||||
| 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) | ||||
| if test "x$ac_cv_prog_WHICH" = "x"; then | ||||
|     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. | ||||
| * Invoking::                    What happens when you run the mcron command. | ||||
| * Guile modules::               Incorporating mcron into another Guile program. | ||||
| * GNU Free Documentation License::  The license of this manual. | ||||
| * Index::                       The complete index. | ||||
| 
 | ||||
| @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 | ||||
| @code{read-vixie-file}. | ||||
| 
 | ||||
| @node GNU Free Documentation License | ||||
| @appendix GNU Free Documentation License | ||||
| 
 | ||||
| @include fdl.texi | ||||
| 
 | ||||
| @node Index,  , Guile modules, Top | ||||
| @unnumbered Index | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										31
									
								
								makefile.am
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								makefile.am
									
										
									
									
									
								
							|  | @ -1,6 +1,5 @@ | |||
| ## Makefile for the toplevel directory of mcron. | ||||
| ## Copyright (C) 2003 Dale Mellor | ||||
| ## Copyright (C) 2015 Mathieu Lirzin | ||||
| ## Copyright (C) 2003, 2015 Dale Mellor | ||||
| ## | ||||
| #    This file is part of GNU mcron. | ||||
| #  | ||||
|  | @ -17,20 +16,13 @@ | |||
| #    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 | ||||
| ## Process this file with automake to produce makefile.in | ||||
| 
 | ||||
| SUBDIRS = scm/mcron . | ||||
| 
 | ||||
| ED = @ED@   # !!!! Are these needed? | ||||
| CP = @CP@ | ||||
| 
 | ||||
| MAINTAINERCLEANFILES = configure makefile makefile.in config.guess config.sub \ | ||||
|                        install-sh missing texinfo.tex INSTALL \ | ||||
|                        aclocal.m4 compile depcomp doc/mcron.1 | ||||
| 
 | ||||
| CLEANFILES = mcron.c | ||||
| 
 | ||||
| EXTRA_DIST = makefile.ed mcron.c.template BUGS | ||||
| EXTRA_DIST = BUGS | ||||
| 
 | ||||
| info_TEXINFOS = doc/mcron.texi | ||||
| 
 | ||||
|  | @ -44,13 +36,6 @@ mcron_LDADD = @GUILE_LIBS@ | |||
| # in turn so that we can do mcron --help during the build process. | ||||
| 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. | ||||
| 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 | ||||
| # elemental man page.  Will only work once the mcron program is installed. | ||||
| $(dist_man_MANS): mcron.c | ||||
| # elemental man page. | ||||
| doc/mcron.1 : mcron | ||||
| 	$(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: | ||||
| 	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-*- | ||||
| 
 | ||||
| ;;   Copyright (C) 2015 Mathieu Lirzin | ||||
| ;;   Copyright (C) 2003 Dale Mellor | ||||
| ;;  | ||||
| ;;   This file is part of GNU mcron. | ||||
|  | @ -23,8 +24,11 @@ | |||
| (define-module (mcron config)) | ||||
| 
 | ||||
| (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-bugreport "@PACKAGE_BUGREPORT@") | ||||
| (define-public config-package-url "@PACKAGE_URL@") | ||||
| (define-public config-sendmail "@SENDMAIL@") | ||||
| 
 | ||||
| (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 | ||||
|  ;; used to put out, for total compatibility. | ||||
| 
 | ||||
|  (else | ||||
|   (mcron-error 15 "usage error: file name must be specified for replace."))) | ||||
|  (else (mcron-error 15 | ||||
|          "usage error: file name must be specified for replace."))) | ||||
| 
 | ||||
| 
 | ||||
| )) ;; 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. | ||||
| ;; | ||||
|  | @ -31,6 +31,7 @@ | |||
| 
 | ||||
| 
 | ||||
| (define-module (mcron environment) | ||||
|   #:use-module (srfi srfi-26) | ||||
|   #:export (modify-environment | ||||
|             clear-environment-mods | ||||
|             append-environment-mods | ||||
|  | @ -38,37 +39,6 @@ | |||
|              | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; 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 | ||||
| ;; variables here. | ||||
| 
 | ||||
|  | @ -103,3 +73,24 @@ | |||
|   (set! current-environment-mods (append current-environment-mods | ||||
|                                          (list (cons name value)))) | ||||
|   #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 | ||||
|             job | ||||
|             find-best-next) | ||||
|   #:use-module (mcron core) | ||||
|   #:use-module (mcron mcron-core) | ||||
|   #:use-module (mcron environment) | ||||
|   #:use-module (mcron vixie-time) | ||||
|   #:re-export (append-environment-mods)) | ||||
|  | @ -203,11 +203,16 @@ | |||
| (define configuration-user (getpw (getuid))) | ||||
| (define configuration-time (current-time)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| (define (set-configuration-user user) | ||||
|   (set! configuration-user (if (or (string? user) | ||||
|                                    (integer? user)) | ||||
|                                (getpw user) | ||||
|                                user))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| (define (set-configuration-time time) (set! configuration-time time)) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -233,8 +238,7 @@ | |||
|                       ((list? action) (lambda () (primitive-eval action))) | ||||
|                       ((string? action) (lambda () (system action))) | ||||
|                       (else  | ||||
|            (throw 'mcron-error  | ||||
|                   2 | ||||
|            (throw 'mcron-error 2 | ||||
|                   "job: invalid second argument (action; should be lambda " | ||||
|                   "function, string or list)")))) | ||||
| 
 | ||||
|  | @ -244,10 +248,9 @@ | |||
|                ((list? time-proc)      (lambda (current-time) | ||||
|                                          (primitive-eval time-proc))) | ||||
|                (else | ||||
|           (throw 'mcron-error  | ||||
|                  3        | ||||
|                  "job: invalid first argument (next-time-function; should ") | ||||
|                  "be function, string or list)"))) | ||||
|                 (throw 'mcron-error 3 | ||||
|                        "job: invalid first argument (next-time-function; " | ||||
|                        "should be function, string or list)")))) | ||||
|         (displayable | ||||
|          (cond ((not (null? displayable)) (car displayable)) | ||||
|                ((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. | ||||
| ;; | ||||
|  | @ -16,34 +16,24 @@ | |||
| ;;   with GNU mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; This is the 'main' routine for the whole system; the top of this file is the | ||||
| ;; global entry point (after the minimal C wrapper, mcron.c.template); to all | ||||
| ;; intents and purposes the program is pure Guile and starts here. | ||||
| ;; | ||||
| ;; This file is built into mcron.c.template by the makefile, which stringifies | ||||
| ;; the whole lot, and escapes quotation marks and escape characters | ||||
| ;; accordingly. Bear this in mind when considering literal multi-line strings. | ||||
| ;; | ||||
| ;; (l0ad "crontab.scm") (sic) is inlined by the makefile. All other | ||||
| ;; functionality comes through modules in .../share/guile/site/mcron/*.scm. | ||||
| (define-module (mcron main) | ||||
|   #:use-module (ice-9 getopt-long) | ||||
|   #:use-module (ice-9 rdelim) | ||||
|   #:use-module (ice-9 regex) | ||||
|   #:use-module (mcron config) | ||||
|   #:use-module (mcron mcron-core) | ||||
|   #:use-module (mcron job-specifier) | ||||
|   #:use-module (mcron vixie-specification) | ||||
|   #:use-module (srfi srfi-2) | ||||
|   #:use-module (srfi srfi-26) | ||||
|   #:export (delete-run-file | ||||
|             main)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Pull in some constants set by the builder (via autoconf) at configuration | ||||
| ;; time. Turn debugging on if indicated. | ||||
| 
 | ||||
| (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)) | ||||
| ;; Extract the actual command name from \a command.  This returns the last | ||||
| ;; part of \a command without any non-alphabetic characters.  For example | ||||
| ;; "in.cron" and "./mcron" will return respectively "cron" and "mcron". | ||||
| 
 | ||||
| (define command-name (match:substring (regexp-exec (make-regexp "[[:alpha:]]*$") | ||||
|                                                    (car (command-line))))) | ||||
|  | @ -51,49 +41,49 @@ | |||
| 
 | ||||
| 
 | ||||
| ;; 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 | ||||
| ;; exit to the system with this code. | ||||
| ;; the parts of \a rest), and if the \a exit-code error is fatal (present and | ||||
| ;; non-zero) then exit to the system with \a exit-code. | ||||
| 
 | ||||
| (define (mcron-error exit-code . rest) | ||||
|   (with-output-to-port (current-error-port) | ||||
|     (lambda () | ||||
|       (for-each display (append (list command-name ": ") rest)) | ||||
|       (for-each display | ||||
|                 (cons* command-name ": " rest)) | ||||
|       (newline))) | ||||
|   (if (and exit-code (not (eq? exit-code 0))) | ||||
|   (when (and 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. | ||||
| 
 | ||||
| (defmacro catch-mcron-error (. body) | ||||
|   `(catch 'mcron-error | ||||
|           (lambda () | ||||
|             ,@body) | ||||
| (define-syntax-rule (catch-mcron-error exp ...) | ||||
|   (catch 'mcron-error | ||||
|     (lambda () exp ...) | ||||
|     (lambda (key 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 | ||||
| ;; perform the string comparisons once and for all here. | ||||
| ;; One of the symbols \c mcron, \c crond or \c crontab according to the means | ||||
| ;; of our invocation. | ||||
| 
 | ||||
| (define command-type (cond ((string=? command-name "mcron") 'mcron) | ||||
|                            ((or (string=? command-name "cron") | ||||
|                                 (string=? command-name "crond")) 'cron) | ||||
|                            ((string=? command-name "crontab") 'crontab) | ||||
|                            (else | ||||
|                             (mcron-error 12 "The command name is invalid.")))) | ||||
| (define command-type | ||||
|   (let ((command=? (cute string=? command-name <>))) | ||||
|     (cond ((command=? "mcron") 'mcron) | ||||
|           ((or (command=? "cron") (command=? "crond")) 'cron) | ||||
|           ((command=? "crontab") 'crontab) | ||||
|           (else (mcron-error 12 "The command name is invalid."))))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; There are a different set of options for the crontab personality compared to | ||||
| ;; all the others, with the --help and --version options common to all the | ||||
| ;; There are a different set of options for the crontab personality compared | ||||
| ;; to all the others, with the --help and --version options common to all the | ||||
| ;; personalities. | ||||
| 
 | ||||
| (use-modules (ice-9 getopt-long)) | ||||
| 
 | ||||
| (define options | ||||
|   (catch | ||||
|    'misc-error | ||||
|  | @ -120,79 +110,86 @@ | |||
|                    '((version  (single-char #\v) (value #f)) | ||||
|                      (help     (single-char #\h) (value #f)))))) | ||||
|    (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 | ||||
| ")) | ||||
| 
 | ||||
| ;; Display version information for \a command and quit. | ||||
| 
 | ||||
| (define* (show-version #:optional (command command-name)) | ||||
|   (let* ((name       config-package-name) | ||||
|          (short-name (cadr (string-split name #\space))) | ||||
|          (version    config-package-version)) | ||||
|     (simple-format #t "~a (~a) ~a | ||||
| Copyright (C) 2015 Free Software Foundation, Inc. | ||||
| 
 | ||||
| License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | ||||
| This is free software: you are free to change and redistribute it. | ||||
| There is NO WARRANTY, to the extent permitted by law.\n" | ||||
| 		   command name version) | ||||
|     (quit))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Likewise if the user requested the help text. | ||||
| ;; Display where to get help and send bug reports. | ||||
| 
 | ||||
| (if (option-ref options 'help #f) | ||||
|     (begin | ||||
|       (display (string-append " | ||||
| Usage: " (car (command-line)) | ||||
| (define (show-package-information) | ||||
|   (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]\n | ||||
| Run an mcron process according to the specifications in the FILES (`-' for\n | ||||
| standard input), or use all the files in ~/.config/cron (or the \n | ||||
| deprecated ~/.cron) with .guile or .vixie extensions.\n | ||||
| \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 | ||||
|   -d, --daemon              Immediately detach the program from the terminal\n | ||||
|                               and run as a daemon process\n | ||||
|   -i, --stdin=(guile|vixie) Format of data passed as standard input or\n | ||||
|       " [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)") | ||||
| 
 | ||||
|      ((cron) | ||||
| " [OPTIONS]\n | ||||
| Unless an option is specified, run a cron daemon as a detached process, \n | ||||
| reading all the information in the users' crontabs and in /etc/crontab.\n | ||||
| \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 | ||||
|       " [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. | ||||
| 
 | ||||
|   -v, --version             Display version | ||||
|   -h, --help                Display this help message | ||||
|   -sN, --schedule[=]N       Display the next N jobs that will be run by cron | ||||
|   -n, --noetc               Do not check /etc/crontab for updates (HIGHLY | ||||
|                               RECOMMENDED).") | ||||
|    | ||||
|      ((crontab) | ||||
|            (string-append " [-u user] file\n" | ||||
|            "       " (car (command-line)) " [-u user] { -e | -l | -r }\n" | ||||
|            "               (default operation is replace, per 1003.2)\n" | ||||
|            "       -e      (edit user's crontab)\n" | ||||
|            "       -l      (list user's crontab)\n" | ||||
|            "       -r      (delete user's crontab)\n")) | ||||
| 
 | ||||
|   (else "rubbish")) | ||||
| 
 | ||||
| "\n\n | ||||
| Report bugs to " config-package-bugreport ".\n | ||||
| ")) | ||||
|       (quit))) | ||||
|       " [-u user] file | ||||
|        crontab [-u user] { -e | -l | -r } | ||||
|                (default operation is replace, per 1003.2) | ||||
|        -e      (edit user's crontab) | ||||
|        -l      (list user's crontab) | ||||
|        -r      (delete user's crontab)") | ||||
|      (else "\nrubbish"))) | ||||
|   (newline) | ||||
|   (show-package-information) | ||||
|   (quit)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; This is called from the C front-end whenever a terminal signal is | ||||
| ;; received. We remove the /var/run/cron.pid file so that crontab and other | ||||
| ;; invocations of cron don't get the wrong idea that a daemon is currently | ||||
| ;; running. | ||||
| ;; Remove the /var/run/cron.pid file so that crontab and other invocations of | ||||
| ;; cron don't get the wrong idea that a daemon is currently running.  This | ||||
| ;; procedure is called from the C front-end whenever a terminal signal is | ||||
| ;; received. | ||||
| 
 | ||||
| (define (delete-run-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 | ||||
| ;; /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. | ||||
| ;; Return standard input as a string. | ||||
| 
 | ||||
| (define (stdin->string) | ||||
|   (with-output-to-string (lambda () (do ((in (read-char) (read-char))) | ||||
|  | @ -251,216 +208,114 @@ Report bugs to " config-package-bugreport ".\n | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Now we have the procedures in place for dealing with the contents of | ||||
| ;; 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. | ||||
| ;; Return a thunk which process each file in \a directory with \a proc.  The | ||||
| ;; \a directory must be a directory name.  The \a proc argument must be a | ||||
| ;; procedure that takes one file name argument. | ||||
| 
 | ||||
| (if (eq? command-type 'crontab) | ||||
|     (begin | ||||
|       (load "crontab.scm") | ||||
|       (quit))) | ||||
| (define (proc-in-directory directory proc) | ||||
|   (let ((dir (opendir directory))) | ||||
|     (do ((file-name (readdir dir) (readdir dir))) | ||||
|         ((eof-object? file-name) (closedir dir)) | ||||
|       (proc file-name)))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Code contributed by Sergey Poznyakoff.  Determine if the given file is a | ||||
| ;; regular file or not. | ||||
| ;; Process \a file-name according its extension.  When \a guile-syntax? is \c | ||||
| ;; 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) | ||||
|   (catch 'system-error | ||||
| 	 (lambda () | ||||
| 	   (eq? (stat:type (stat file)) 'regular)) | ||||
| 	 (lambda (key call fmt args . rest) | ||||
| 	   (mcron-error 0 (apply format (append (list #f fmt) args))) | ||||
| 	   #f))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Procedure which processes any configuration file according to the | ||||
| ;; extension. If a file is not recognized, it is silently ignored (this deals | ||||
| ;; 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 "-") | ||||
| (define process-user-file | ||||
|   (let ((guile-regexp (make-regexp "\\.gui(le)?$")) | ||||
|         (vixie-regexp (make-regexp "\\.vix(ie)?$"))) | ||||
|     (lambda* (file-path #:optional 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)))) | ||||
|             ((regexp-exec vixie-regexp file-path) | ||||
|              (read-vixie-file file-path)) | ||||
|             ((or assume-guile | ||||
|                  (regexp-exec guile-regexp file-path)) | ||||
|              (load 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). | ||||
| ;; Process files in $XDG_CONFIG_HOME/cron and/or ~/.cron directories (if | ||||
| ;; $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead). | ||||
| 
 | ||||
| (define (process-files-in-user-directory) | ||||
|   (let ((errors 0) | ||||
|         (home-directory (passwd:dir (getpw (getuid))))) | ||||
|     (map (lambda (config-directory) | ||||
|     (map (lambda (dir) | ||||
|            (catch #t | ||||
|                   (lambda () | ||||
|                    (let ((directory (opendir config-directory))) | ||||
|                      (do ((file-name (readdir directory) (readdir directory))) | ||||
|                          ((eof-object? file-name) (closedir directory)) | ||||
|                        (process-user-file (string-append config-directory | ||||
|                                                          "/" | ||||
|                                                          file-name))))) | ||||
|                     (proc-in-directory | ||||
|                      dir | ||||
|                      (lambda (file-name) | ||||
|                        (process-user-file (string-append dir "/" file-name))))) | ||||
|                   (lambda (key . args) | ||||
|                     (set! errors (1+ errors))))) | ||||
|          (list (string-append home-directory "/.cron") | ||||
|                (string-append (or (getenv "XDG_CONFIG_HOME") | ||||
|                                   (string-append home-directory "/.config")) | ||||
|                               "/cron"))) | ||||
|     (if (eq? 2 errors) | ||||
|     (when (eq? 2 errors) | ||||
|       (mcron-error 13 | ||||
|                      "Cannot read files in your ~/.config/cron (or ~/.cron) " | ||||
|                      "directory.")))) | ||||
|         "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 | ||||
| ;; that a user is removed after creating a crontab). If the user name is valid, | ||||
| ;; the full passwd entry for that user is returned to the caller. | ||||
| 
 | ||||
| (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*. | ||||
| ;; Process all the files in the crontab directory.  When the job procedure is | ||||
| ;; run on behalf of the configuration files, the jobs are registered on the | ||||
| ;; 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 (process-files-in-system-directory) | ||||
|   (catch #t | ||||
|     (lambda () | ||||
|            (let ((directory (opendir config-spool-dir))) | ||||
|              (do ((file-name (readdir directory) (readdir directory))) | ||||
|                  ((eof-object? file-name)) | ||||
|                (and-let* ((user (valid-user file-name))) | ||||
|                          (set-configuration-user user)         ;; / ?? !!!! | ||||
|       (proc-in-directory | ||||
|          config-spool-dir | ||||
|          (lambda (user-name) | ||||
|            (and-let* ((user (false-if-exception (getpwnam user-name)))) | ||||
|                      (set-configuration-user user) | ||||
|                      (catch-mcron-error | ||||
|                           (read-vixie-file (string-append config-spool-dir | ||||
|                                                           "/" | ||||
|                                                           file-name))))))) | ||||
|                        (read-vixie-file | ||||
|                           (string-append config-spool-dir "/" user-name))))))) | ||||
|     (lambda (key . args) | ||||
|            (mcron-error | ||||
|             4 | ||||
|       (mcron-error 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)))))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; If we are running as cron or crond, we establish a socket to listen for | ||||
| ;; updates from a crontab program. This is put into fd-list so that we can | ||||
| ;; inform the main wait-run-wait execution loop to listen for incoming messages | ||||
| ;; on this socket. | ||||
| 
 | ||||
| (define fd-list '()) | ||||
| 
 | ||||
| (define (cron-file-descriptors) | ||||
|   (if (eq? command-type 'cron) | ||||
|       (catch #t | ||||
|              (lambda () | ||||
|                (let ((socket (socket AF_UNIX SOCK_STREAM 0))) | ||||
|                  (bind socket AF_UNIX config-socket-file) | ||||
|                  (listen socket 5) | ||||
|                (set! fd-list (list socket)))) | ||||
|                  (list socket))) | ||||
|              (lambda (key . args) | ||||
|                (delete-file config-pid-file) | ||||
|                (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 | ||||
| ;; user's updated file. In the special case we drop all the system jobs and | ||||
| ;; re-read the /etc/crontab file. | ||||
| ;; user's updated file.  In the special case drop all the system jobs and | ||||
| ;; 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)))) | ||||
|          (user-name (read-line socket))) | ||||
|     (close socket) | ||||
|  | @ -475,29 +330,123 @@ option.\n") | |||
|          (let ((user (getpw user-name))) | ||||
|            (remove-user-jobs 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. | ||||
| 
 | ||||
| (define (main . args) | ||||
|   ;; Added by Sergey Poznyakoff.  This no-op will collect zombie child processes | ||||
|   ;; 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)) | ||||
|    | ||||
| ;; Unfortunately it seems to interact badly with the select system call, | ||||
| ;; wreaking havoc... | ||||
|   ;; 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)) | ||||
| 
 | ||||
| ;; (sigaction SIGCHLD (lambda (sig) noop) SA_RESTART) | ||||
|   ;; Now we have the procedures in place for dealing with the contents of | ||||
|   ;; 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)) | ||||
| 
 | ||||
|   ;; 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)) | ||||
| 
 | ||||
| ;; 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. | ||||
|   ;; 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. | ||||
|   (when (option-ref options 'daemon (eq? command-type 'cron)) | ||||
|     (unless (eqv? (primitive-fork) 0) | ||||
|             (quit)) | ||||
|     (setsid) | ||||
|     (when (eq? command-type 'cron) | ||||
|           (with-output-to-file config-pid-file | ||||
|             (lambda () (display (getpid)) (newline))))) | ||||
|    | ||||
|   ;; 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) | ||||
|         (if (not (null? fd-list)) | ||||
|             (process-update-request)))) | ||||
|        (unless (null? fd-list) | ||||
|          (process-update-request fd-list)))))) | ||||
|  |  | |||
|  | @ -1,15 +1,60 @@ | |||
| EXTRA_DIST = main.scm mcron-core.scm vixie-specification.scm \ | ||||
|              crontab.scm environment.scm job-specifier.scm redirect.scm \ | ||||
| ## Makefile for the scm/mcron directory of mcron. | ||||
| 
 | ||||
| #  Copyright (C) 2015 Mathieu Lirzin | ||||
| # | ||||
| #  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. | ||||
| 
 | ||||
| 
 | ||||
| MODULES = environment.scm			\ | ||||
|           job-specifier.scm			\ | ||||
|           main.scm					\ | ||||
|           mcron-core.scm			\ | ||||
|           redirect.scm				\ | ||||
|           vixie-specification.scm	\ | ||||
|           vixie-time.scm | ||||
| 
 | ||||
| pkgdata_DATA = core.scm environment.scm job-specifier.scm redirect.scm \ | ||||
|                vixie-time.scm vixie-specification.scm config.scm | ||||
| GOBJECTS = $(MODULES:%.scm=%.go) config.go | ||||
| 
 | ||||
| nobase_dist_guilemodule_DATA = $(MODULES) crontab.scm | ||||
| nobase_nodist_guilemodule_DATA = $(GOBJECTS) config.scm | ||||
| 
 | ||||
| # If you're wondering, the configure script keeps deleting all files with a name | ||||
| # like core.*, so we have to keep re-making it (I lost a good day's work because | ||||
| # of this). | ||||
| CLEANFILES = $(GOBJECTS) | ||||
| 
 | ||||
| core.scm : mcron-core.scm | ||||
| 	$(CP) mcron-core.scm core.scm | ||||
| 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. | ||||
| ;; | ||||
|  | @ -17,8 +17,9 @@ | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| (define-module (mcron core) | ||||
| (define-module (mcron mcron-core) | ||||
|   #:use-module (mcron environment) | ||||
|   #:use-module (srfi srfi-9) | ||||
|   #:export     (add-job | ||||
|                 remove-user-jobs | ||||
|                 get-schedule | ||||
|  | @ -38,7 +39,7 @@ | |||
| 
 | ||||
| ;; 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 | ||||
| ;; 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-user-job-list) (set! configuration-source 'user)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ;; Convenience functions for getting and setting the elements of a job object. | ||||
| 
 | ||||
| (define (job:user job)                (vector-ref job 0)) | ||||
| (define (job:next-time-function job)  (vector-ref job 1)) | ||||
| (define (job:action job)              (vector-ref job 2)) | ||||
| (define (job:environment job)         (vector-ref job 3)) | ||||
| (define (job:displayable job)         (vector-ref job 4)) | ||||
| (define (job:next-time job)           (vector-ref job 5)) | ||||
| 
 | ||||
| 
 | ||||
| ;; A cron job. | ||||
| (define-record-type <job> | ||||
|   (make-job user time-proc action environment displayable next-time) | ||||
|   job? | ||||
|   (user        job:user)                ;string : user passwd entry | ||||
|   (time-proc   job:next-time-function)  ;proc   : with one 'time' parameter | ||||
|   (action      job:action)              ;thunk  : user's code | ||||
|   (environment job:environment)         ;alist  : environment variables | ||||
|   (displayable job:displayable)         ;string : visible in schedule | ||||
|   (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. | ||||
| 
 | ||||
|  | @ -97,7 +97,7 @@ | |||
| 
 | ||||
| (define (add-job time-proc action displayable configuration-time | ||||
|                  configuration-user) | ||||
|   (let ((entry (vector configuration-user | ||||
|   (let ((entry (make-job configuration-user | ||||
|                          time-proc | ||||
|                          action | ||||
|                          (get-current-environment-mods-copy) | ||||
|  | @ -165,16 +165,15 @@ | |||
|     (lambda () | ||||
|       (do ((count count (- count 1))) | ||||
|           ((eqv? count 0)) | ||||
|         (and-let* ((next-jobs (find-next-jobs)) | ||||
|         (and-let* | ||||
|          ((next-jobs (find-next-jobs)) | ||||
|           (time (car next-jobs)) | ||||
|           (date-string (strftime "%c %z\n" (localtime time)))) | ||||
|          (for-each (lambda (job) | ||||
|                      (display date-string) | ||||
|                      (display (job:displayable job)) | ||||
|                      (newline)(newline) | ||||
|                       (vector-set! job | ||||
|                                    5 | ||||
|                                    ((job:next-time-function job) | ||||
|                      (job:next-time-set! job ((job:next-time-function job) | ||||
|                                               (job:next-time job)))) | ||||
|                    (cdr next-jobs))))))) | ||||
| 
 | ||||
|  | @ -195,7 +194,8 @@ | |||
| ;; to run. | ||||
| 
 | ||||
| (define (run-jobs jobs-list) | ||||
|   (for-each (lambda (job) | ||||
|   (for-each | ||||
|    (lambda (job) | ||||
|      (if (eqv? (primitive-fork) 0) | ||||
|          (begin | ||||
|            (setgid (passwd:gid (job:user job))) | ||||
|  | @ -206,9 +206,7 @@ | |||
|            (primitive-exit 0)) | ||||
|          (begin | ||||
|            (set! number-children (+ number-children 1)) | ||||
|                     (vector-set! job | ||||
|                                  5 | ||||
|                                  ((job:next-time-function job) | ||||
|            (job:next-time-set! job ((job:next-time-function job) | ||||
|                                     (current-time)))))) | ||||
|    jobs-list)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ | |||
| 
 | ||||
| (define-module (mcron redirect) | ||||
|   #:export (with-mail-out) | ||||
|   #:use-module (ice-9 regex) | ||||
|   #:use-module ((mcron config) :select (config-sendmail)) | ||||
|   #:use-module (mcron vixie-time)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
|             read-vixie-file | ||||
|             check-system-crontab) | ||||
|   #: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 redirect) | ||||
|   #:use-module (mcron vixie-time)) | ||||
|  | @ -162,9 +162,7 @@ | |||
|                          (parse-vixie-environment line) | ||||
|                          (parse-vixie-line line))) | ||||
|                    (lambda (key exit-code . msg) | ||||
|                      (throw | ||||
|                       'mcron-error | ||||
|                       exit-code | ||||
|                      (throw 'mcron-error exit-code | ||||
|                             (apply string-append | ||||
|                                    (number->string report-line) | ||||
|                                    ": " | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dale Mellor
				Dale Mellor