merge from dm-v1.2.0 part 1
This commit is contained in:
		
				commit
				
					
						6360e88416
					
				
			
		
					 21 changed files with 355 additions and 522 deletions
				
			
		
							
								
								
									
										76
									
								
								Makefile.am
									
										
									
									
									
								
							
							
						
						
									
										76
									
								
								Makefile.am
									
										
									
									
									
								
							|  | @ -21,40 +21,18 @@ | ||||||
| ## Programs.  ## | ## Programs.  ## | ||||||
| ## ---------- ## | ## ---------- ## | ||||||
| 
 | 
 | ||||||
| bin_PROGRAMS = bin/mcron | bin_SCRIPTS = bin/mcron | ||||||
|  | noinst_SCRIPTS =  | ||||||
| 
 | 
 | ||||||
| if MULTI_USER | if MULTI_USER | ||||||
| bin_PROGRAMS += bin/crontab | bin_SCRIPTS += bin/crontab | ||||||
| sbin_PROGRAMS = bin/cron | sbin_SCRIPTS = bin/cron | ||||||
| else | else | ||||||
| noinst_PROGRAMS = bin/cron bin/crontab | noinst_SCRIPTS += bin/cron bin/crontab | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| AM_CPPFLAGS = \ |  | ||||||
|   -DPACKAGE_LOAD_PATH=\"$(guilesitedir)\" \ |  | ||||||
|   -DPACKAGE_LOAD_COMPILED_PATH=\"$(guilesitegodir)\" \ |  | ||||||
|   -D_GNU_SOURCE |  | ||||||
| 
 |  | ||||||
| AM_CFLAGS = @GUILE_CFLAGS@ |  | ||||||
| LDADD = @GUILE_LIBS@ src/libmcron.a |  | ||||||
| 
 |  | ||||||
| bin_mcron_SOURCES = src/mcron.c |  | ||||||
| bin_mcron_DEPENDENCIES = $(compiled_modules) $(noinst_LIBRARIES) |  | ||||||
| 
 |  | ||||||
| bin_cron_SOURCES = src/cron.c |  | ||||||
| bin_cron_DEPENDENCIES = $(compiled_modules) $(noinst_LIBRARIES) |  | ||||||
| 
 |  | ||||||
| bin_crontab_SOURCES = src/crontab.c |  | ||||||
| bin_crontab_DEPENDENCIES = $(compiled_modules) $(noinst_LIBRARIES) |  | ||||||
| 
 |  | ||||||
| # wrapper to be used in the build environment and for running tests. | # wrapper to be used in the build environment and for running tests. | ||||||
| noinst_SCRIPTS = pre-inst-env | noinst_SCRIPTS += pre-inst-env | ||||||
| 
 |  | ||||||
| # local library. |  | ||||||
| noinst_LIBRARIES = src/libmcron.a |  | ||||||
| src_libmcron_a_SOURCES = \ |  | ||||||
|   src/utils.c \ |  | ||||||
|   src/utils.h |  | ||||||
| 
 | 
 | ||||||
| ## --------------- ## | ## --------------- ## | ||||||
| ## Guile modules.  ## | ## Guile modules.  ## | ||||||
|  | @ -97,7 +75,7 @@ compiled_modules = \ | ||||||
|   $(pkgmodulego_DATA) \ |   $(pkgmodulego_DATA) \ | ||||||
|   $(pkgscriptgo_DATA) |   $(pkgscriptgo_DATA) | ||||||
| 
 | 
 | ||||||
| CLEANFILES = $(compiled_modules) | CLEANFILES = $(compiled_modules) bin/crontab bin/cron bin/mcron | ||||||
| DISTCLEANFILES = src/mcron/config.scm | DISTCLEANFILES = src/mcron/config.scm | ||||||
| 
 | 
 | ||||||
| # Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling.  Otherwise, if | # Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling.  Otherwise, if | ||||||
|  | @ -120,6 +98,24 @@ DISTCLEANFILES = src/mcron/config.scm | ||||||
| 	  --warn=format --warn=unbound-variable --warn=arity-mismatch \ | 	  --warn=format --warn=unbound-variable --warn=arity-mismatch \ | ||||||
| 	  --target="$(host)" --output="$@" "$<" $(devnull_verbose) | 	  --target="$(host)" --output="$@" "$<" $(devnull_verbose) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | bin/% : src/%.in Makefile | ||||||
|  | 	-@sed	-e 's,%PREFIX%,${prefix},g'				\ | ||||||
|  | 		-e 's,%modsrcdir%,${guilesitedir},g'			\ | ||||||
|  | 		-e 's,%modbuilddir%,${guilesitegodir},g'		\ | ||||||
|  | 		-e 's,%localstatedir%,${localstatedir},g'		\ | ||||||
|  | 		-e 's,%pkglibdir%,${pkglibdir},g'			\ | ||||||
|  | 		-e 's,%sysconfdir%,${sysconfdir},g'			\ | ||||||
|  | 		-e 's,%localedir%,${localedir},g'			\ | ||||||
|  | 		-e 's,%VERSION%,@VERSION@,g'				\ | ||||||
|  | 		-e 's,%PACKAGE_BUGREPORT%,@PACKAGE_BUGREPORT@,g'	\ | ||||||
|  | 		-e 's,%PACKAGE_NAME%,@PACKAGE_NAME@,g'			\ | ||||||
|  | 		-e 's,%PACKAGE_URL%,@PACKAGE_URL@,g'			\ | ||||||
|  | 		-e 's,%GUILE%,$(GUILE),g'				\ | ||||||
|  | 	   $< > $@; | ||||||
|  | 	-@chmod a+x $@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ## ------------ ## | ## ------------ ## | ||||||
| ## Test suite.  ## | ## Test suite.  ## | ||||||
| ## ------------ ## | ## ------------ ## | ||||||
|  | @ -136,6 +132,7 @@ SCM_LOG_DRIVER = \ | ||||||
| TESTS = \ | TESTS = \ | ||||||
|   tests/basic.sh \ |   tests/basic.sh \ | ||||||
|   tests/schedule.sh \ |   tests/schedule.sh \ | ||||||
|  |   tests/schedule-2.sh \ | ||||||
|   tests/base.scm \ |   tests/base.scm \ | ||||||
|   tests/environment.scm \ |   tests/environment.scm \ | ||||||
|   tests/job-specifier.scm \ |   tests/job-specifier.scm \ | ||||||
|  | @ -160,25 +157,28 @@ EXTRA_DIST = \ | ||||||
| # Sed command for Transforming program names. | # Sed command for Transforming program names. | ||||||
| transform_exe = s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/ | transform_exe = s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/ | ||||||
| 
 | 
 | ||||||
| if MULTI_USER |  | ||||||
| install-exec-hook: | install-exec-hook: | ||||||
| 	tcrontab=`echo crontab$(EXEEXT) | sed '$(transform_exe)'`; \ | if MULTI_USER | ||||||
|  | 	tcrontab=`echo crontab | sed '$(transform_exe)'`; \ | ||||||
| 	chmod u+s $(DESTDIR)$(bindir)/$${tcrontab} | 	chmod u+s $(DESTDIR)$(bindir)/$${tcrontab} | ||||||
|  | 	tcron=`echo cron | sed '$(transform_exe)'`; \ | ||||||
|  | 	chmod u+s $(DESTDIR)$(sbindir)/$${tcron} | ||||||
| endif | endif | ||||||
|  | 	tmcron=`echo mcron | sed '$(transform_exe)'`; | ||||||
| 
 | 
 | ||||||
| installcheck-local: | installcheck-local: | ||||||
| ## Check that only expected programs are installed and configured | ## Check that only expected programs are installed and configured | ||||||
| 	tmcron=`echo mcron$(EXEEXT) | sed '$(transform_exe)'`; \ | 	tmcron=`echo mcron | sed '$(transform_exe)'`; \ | ||||||
| 	test -e $(DESTDIR)$(bindir)/$${tmcron} | 	test -e $(DESTDIR)$(bindir)/$${tmcron} | ||||||
| if MULTI_USER | if MULTI_USER | ||||||
| 	tcrontab=`echo crontab$(EXEEXT) | sed '$(transform_exe)'`; \ | 	tcrontab=`echo crontab | sed '$(transform_exe)'`; \ | ||||||
| 	test -u $(DESTDIR)$(bindir)/$${tcrontab} | 	test -u $(DESTDIR)$(bindir)/$${tcrontab} | ||||||
| 	tcron=`echo cron$(EXEEXT) | sed '$(transform_exe)'`; \ | 	tcron=`echo cron | sed '$(transform_exe)'`; \ | ||||||
| 	test -e $(DESTDIR)$(sbindir)/$${tcron} | 	test -e $(DESTDIR)$(sbindir)/$${tcron} | ||||||
| else !MULTI_USER | else !MULTI_USER | ||||||
| 	tcrontab=`echo crontab$(EXEEXT) | sed '$(transform_exe)'`; \ | 	tcrontab=`echo crontab | sed '$(transform_exe)'`; \ | ||||||
| 	test ! -u $(DESTDIR)$(bindir)/$${tcrontab} | 	test ! -u $(DESTDIR)$(bindir)/$${tcrontab} | ||||||
| 	tcron=`echo cron$(EXEEXT) | sed '$(transform_exe)'`; \ | 	tcron=`echo cron | sed '$(transform_exe)'`; \ | ||||||
| 	test ! -f $(DESTDIR)$(sbindir)/$${tcron} | 	test ! -f $(DESTDIR)$(sbindir)/$${tcron} | ||||||
| endif !MULTI_USER | endif !MULTI_USER | ||||||
| 
 | 
 | ||||||
|  | @ -219,10 +219,10 @@ gen_man = \ | ||||||
|   esac |   esac | ||||||
| 
 | 
 | ||||||
| $(srcdir)/doc/mcron.1: src/mcron/scripts/mcron.scm bin/mcron | $(srcdir)/doc/mcron.1: src/mcron/scripts/mcron.scm bin/mcron | ||||||
| 	-@prog="mcron"; man_section=1; $(gen_man) | 	-@prog="bin/mcron"; man_section=1; $(gen_man) | ||||||
| 
 | 
 | ||||||
| $(srcdir)/doc/crontab.1: src/mcron/scripts/crontab.scm bin/crontab | $(srcdir)/doc/crontab.1: src/mcron/scripts/crontab.scm bin/crontab | ||||||
| 	-@prog="crontab"; man_section=1; $(gen_man) | 	-@prog="bin/crontab"; man_section=1;	 $(gen_man) | ||||||
| 
 | 
 | ||||||
| $(srcdir)/doc/cron.8: src/mcron/scripts/cron.scm bin/cron | $(srcdir)/doc/cron.8: src/mcron/scripts/cron.scm bin/cron | ||||||
| 	-@prog="cron"; man_section=8; $(gen_man) | 	-@prog="cron"; man_section=8; $(gen_man) | ||||||
|  |  | ||||||
|  | @ -32,16 +32,16 @@ | ||||||
|                 '(".git" "autom4te" "Makefile.in" ".go" ".log" |                 '(".git" "autom4te" "Makefile.in" ".go" ".log" | ||||||
|                   "stamp-vti" ".dirstamp")) |                   "stamp-vti" ".dirstamp")) | ||||||
|            (any (λ (str) (string-suffix? str file)) |            (any (λ (str) (string-suffix? str file)) | ||||||
|                 '("trs""configure" "Makefile" "config.status" "pre-inst-env" |                 '("trs" "configure" "Makefile" "config.status" "pre-inst-env" | ||||||
|                   "aclocal.m4" "bin/cron" "bin/mcron" "bin/crontab" "config.cache" |                   "aclocal.m4" "bin/cron" "bin/mcron" "bin/crontab" | ||||||
|                   "guix.scm"))))) |                   "config.cache" "guix.scm"))))) | ||||||
| 
 | 
 | ||||||
| (define %srcdir | (define %srcdir | ||||||
|   (or (current-source-directory) ".")) |   (or (current-source-directory) ".")) | ||||||
| 
 | 
 | ||||||
| (package | (package | ||||||
|   (inherit (specification->package "mcron")) |   (inherit (specification->package "mcron")) | ||||||
|   (version "1.1.4") |   (version "1.1.4+") | ||||||
|   (source (local-file (dirname %srcdir) #:recursive? #t |   (source (local-file (dirname %srcdir) #:recursive? #t | ||||||
|                       #:select? keep-mcron-file?)) |                       #:select? keep-mcron-file?)) | ||||||
|   (inputs |   (inputs | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								configure.ac
									
										
									
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| ## Process this file with autoconf to produce a configure script. | ## Process this file with autoconf to produce a configure script. | ||||||
| # Copyright © 2003, 2005, 2012, 2014 Dale Mellor | # | ||||||
| # <dale_mellor@users.sourceforge.net> | # Copyright © 2003, 2005, 2012, 2014 Dale Mellor <mcron-lsfnyl@rdmp.org> | ||||||
| # Copyright © 2015, 2016, 2017, 2018 Mathieu Lirzin <mthl@gnu.org> | # Copyright © 2015, 2016, 2017, 2018 Mathieu Lirzin <mthl@gnu.org> | ||||||
| # Copyright © 2018 宋文武 <iyzsong@member.fsf.org> | # Copyright © 2018 宋文武 <iyzsong@member.fsf.org> | ||||||
| # | # | ||||||
|  | @ -20,19 +20,18 @@ | ||||||
| # along with GNU Mcron.  If not, see <http://www.gnu.org/licenses/>. | # along with GNU Mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| AC_PREREQ(2.61) | AC_PREREQ(2.61) | ||||||
| AC_INIT([GNU Mcron], [1.1.4], [bug-mcron@gnu.org]) | AC_INIT([GNU Mcron], [1.1.4+], [bug-mcron@gnu.org]) | ||||||
| AC_CONFIG_SRCDIR([src/mcron.c]) | AC_CONFIG_SRCDIR([src/mcron/scripts/mcron.scm]) | ||||||
| AC_CONFIG_AUX_DIR([build-aux]) | AC_CONFIG_AUX_DIR([build-aux]) | ||||||
| AC_REQUIRE_AUX_FILE([test-driver.scm]) | AC_REQUIRE_AUX_FILE([test-driver.scm]) | ||||||
| AM_INIT_AUTOMAKE([subdir-objects -Wall -Wno-override std-options]) | 
 | ||||||
| AM_SILENT_RULES([yes])		# enables silent rules by default | dnl We're fine with GNU make constructs, hence '-Wno-portability'. | ||||||
|  | AM_INIT_AUTOMAKE([1.11 gnu silent-rules subdir-objects color-tests | ||||||
|  |                   -Wall -Wno-override -Wno-portability std-options]) | ||||||
|  | 
 | ||||||
|  | AM_SILENT_RULES([yes])		# Enables silent rules by default. | ||||||
| 
 | 
 | ||||||
| AC_CANONICAL_HOST | AC_CANONICAL_HOST | ||||||
| AC_PROG_AWK |  | ||||||
| AC_PROG_EGREP |  | ||||||
| AM_PROG_CC_C_O |  | ||||||
| AC_PROG_RANLIB |  | ||||||
| AM_PROG_AR |  | ||||||
| 
 | 
 | ||||||
| # Check for Guile development files. | # Check for Guile development files. | ||||||
| GUILE_PKG([3.0 2.2 2.0]) | GUILE_PKG([3.0 2.2 2.0]) | ||||||
|  | @ -41,12 +40,6 @@ GUILE_PKG([3.0 2.2 2.0]) | ||||||
| # 'config.rpath' script. | # 'config.rpath' script. | ||||||
| PKG_CHECK_MODULES(GUILE, [guile-$GUILE_EFFECTIVE_VERSION]) | PKG_CHECK_MODULES(GUILE, [guile-$GUILE_EFFECTIVE_VERSION]) | ||||||
| 
 | 
 | ||||||
| # Check for 'argp' program arguments parser. |  | ||||||
| AC_CHECK_FUNC(argp_parse, [], AC_MSG_ERROR([argp not found])) |  | ||||||
| 
 |  | ||||||
| # Check for non-POSIX string formatting function. |  | ||||||
| AC_CHECK_FUNC(asprintf, [], AC_MSG_ERROR([asprintf not found])) |  | ||||||
| 
 |  | ||||||
| # Checks for programs. | # Checks for programs. | ||||||
| 
 | 
 | ||||||
| GUILE_PROGS | GUILE_PROGS | ||||||
|  |  | ||||||
|  | @ -158,10 +158,10 @@ example, take the system load into consideration. | ||||||
| Turns out to be easy to provide complete backwards compatibility with | Turns out to be easy to provide complete backwards compatibility with | ||||||
| Vixie cron. | Vixie cron. | ||||||
| @item | @item | ||||||
| Each user looks after his own files in his own directory.  He can use | Each user looks after their own files in their own directory.  They can use | ||||||
| more than one to break up complicated cron specifications. | more than one to break up complicated cron specifications. | ||||||
| @item | @item | ||||||
| Each user can run his own daemon.  This removes the need for suid | Each user can run their own daemon.  This removes the need for suid | ||||||
| programs to manipulate the crontabs, and eliminates many security | programs to manipulate the crontabs, and eliminates many security | ||||||
| concerns that surround all existing cron programs. | concerns that surround all existing cron programs. | ||||||
| @item | @item | ||||||
|  | @ -516,7 +516,7 @@ second-to-last day of every month. | ||||||
| @emph{NOTE} that this section is definitive.  If there is a difference in | @emph{NOTE} that this section is definitive.  If there is a difference in | ||||||
| behaviour between the mcron program and this part of the manual, then | behaviour between the mcron program and this part of the manual, then | ||||||
| there is a bug in the program.  This section is also copied verbatim | there is a bug in the program.  This section is also copied verbatim | ||||||
| from Paul Vixie's documentation for his cron program, and his | from Paul Vixie's documentation for their cron program, and their | ||||||
| copyright notice is duly reproduced below. | copyright notice is duly reproduced below. | ||||||
| 
 | 
 | ||||||
| There are three problems with this specification. | There are three problems with this specification. | ||||||
|  | @ -815,7 +815,7 @@ place in the part which implements the mcron personality. | ||||||
| @cindex mcron arguments | @cindex mcron arguments | ||||||
| @cindex command line, mcron | @cindex command line, mcron | ||||||
| @cindex mcron command line | @cindex mcron command line | ||||||
| Mcron should be run by the user who wants to schedule his jobs.  It | Mcron should be run by the user who wants to schedule their jobs.  It | ||||||
| may be made a background job using the facilities of the shell.  The | may be made a background job using the facilities of the shell.  The | ||||||
| basic command is @code{mcron [OPTION ...] [file ...]}  which has the | basic command is @code{mcron [OPTION ...] [file ...]}  which has the | ||||||
| effect of reading all the configuration files specified (subject to | effect of reading all the configuration files specified (subject to | ||||||
|  | @ -1026,7 +1026,7 @@ Delete the user's crontab file, and exit. | ||||||
| @item -e | @item -e | ||||||
| @item --edit | @item --edit | ||||||
| Using the editor specified in the user's VISUAL or EDITOR environment | Using the editor specified in the user's VISUAL or EDITOR environment | ||||||
| variables, allow the user to edit his crontab.  Once the user exits the | variables, allow the user to edit their crontab.  Once the user exits the | ||||||
| editor, the crontab is checked for parseability, and if it is okay | editor, the crontab is checked for parseability, and if it is okay | ||||||
| then it is installed as the user's new crontab and the daemon is | then it is installed as the user's new crontab and the daemon is | ||||||
| notified that a change has taken place, so that the new file will | notified that a change has taken place, so that the new file will | ||||||
|  | @ -1231,7 +1231,7 @@ the mcron base. | ||||||
| 
 | 
 | ||||||
| @deffn{Scheme procedure} remove-user-jobs user @ | @deffn{Scheme procedure} remove-user-jobs user @ | ||||||
|   [#:schedule @var{%global-schedule}] |   [#:schedule @var{%global-schedule}] | ||||||
| The argument @var{user} should be a string naming a user (his | The argument @var{user} should be a string naming a user (their | ||||||
| login name), or an integer UID, or an object representing the user's passwd | login name), or an integer UID, or an object representing the user's passwd | ||||||
| entry.  All jobs on the current job list that are scheduled to be run | entry.  All jobs on the current job list that are scheduled to be run | ||||||
| under this personality are removed from the job list. | under this personality are removed from the job list. | ||||||
|  |  | ||||||
							
								
								
									
										80
									
								
								src/cron.c
									
										
									
									
									
								
							
							
						
						
									
										80
									
								
								src/cron.c
									
										
									
									
									
								
							|  | @ -1,80 +0,0 @@ | ||||||
| /* cron.c -- run jobs at scheduled times
 |  | ||||||
|    Copyright © 2003, 2014 Dale Mellor <dale_mellor@users.sourceforge.net> |  | ||||||
|    Copyright © 2015, 2016, 2017 Mathieu Lirzin <mthl@gnu.org> |  | ||||||
| 
 |  | ||||||
|    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/>.  */
 |  | ||||||
| 
 |  | ||||||
| #include "utils.h" |  | ||||||
| #include <signal.h> |  | ||||||
| #include <string.h> |  | ||||||
| 
 |  | ||||||
| /* Forward declarations.  */ |  | ||||||
| static void inner_main (void *closure, int argc, char *argv[]); |  | ||||||
| static void react_to_terminal_signal (int sig); |  | ||||||
| static SCM set_cron_signals (void); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| main (int argc, char *argv[]) |  | ||||||
| { |  | ||||||
|   /* Set Guile load paths to ensure that Mcron modules will be found after
 |  | ||||||
|      installation.  In a build environment let the 'pre-inst-env' script set |  | ||||||
|      the correct paths.  */ |  | ||||||
|   if (getenv ("MCRON_UNINSTALLED") == NULL) |  | ||||||
|     { |  | ||||||
|       wrap_env_path ("GUILE_LOAD_PATH", PACKAGE_LOAD_PATH); |  | ||||||
|       wrap_env_path ("GUILE_LOAD_COMPILED_PATH", PACKAGE_LOAD_COMPILED_PATH); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   scm_boot_guile (argc, argv, inner_main, NULL); |  | ||||||
| 
 |  | ||||||
|   return EXIT_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* 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 scripts cron")); |  | ||||||
|   scm_c_define_gsubr ("c-set-cron-signals", 0, 0, 0, set_cron_signals); |  | ||||||
|   scm_call_0 (scm_variable_ref (scm_c_lookup ("main"))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Set up all the signal handlers.  This is necessary to perform the signal
 |  | ||||||
|    processing in C because the sigaction function won't work when called from |  | ||||||
|    Guile.  */ |  | ||||||
| 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; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Handle signal SIG and exit.  All signals that cron handles will produce the
 |  | ||||||
|    same behavior so we don't need to use SIG in the implementation.  */ |  | ||||||
| static void |  | ||||||
| react_to_terminal_signal (int sig) |  | ||||||
| { |  | ||||||
|   scm_c_eval_string ("(delete-run-file)"); |  | ||||||
|   exit (EXIT_FAILURE); |  | ||||||
| } |  | ||||||
							
								
								
									
										8
									
								
								src/cron.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/cron.in
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | #!%GUILE% --no-auto-compile | ||||||
|  | -*- scheme -*- | ||||||
|  | !# | ||||||
|  | 
 | ||||||
|  | (set! %load-path (cons "%modsrcdir%" %load-path)) | ||||||
|  | (set! %load-compiled-path (cons "%modbuilddir%" %load-compiled-path)) | ||||||
|  | (use-modules  (mcron scripts cron)) | ||||||
|  | (main) | ||||||
|  | @ -1,48 +0,0 @@ | ||||||
| /* crontab.c -- edit users' crontab files
 |  | ||||||
|    Copyright © 2003, 2014 Dale Mellor <dale_mellor@users.sourceforge.net> |  | ||||||
|    Copyright © 2015, 2016, 2017 Mathieu Lirzin <mthl@gnu.org> |  | ||||||
| 
 |  | ||||||
|    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/>.  */
 |  | ||||||
| 
 |  | ||||||
| #include "utils.h" |  | ||||||
| 
 |  | ||||||
| /* Forward declarations.  */ |  | ||||||
| static void inner_main (void *closure, int argc, char *argv[]); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| main (int argc, char *argv[]) |  | ||||||
| { |  | ||||||
|   /* Set Guile load paths to ensure that Mcron modules will be found after
 |  | ||||||
|      installation.  In a build environment let the 'pre-inst-env' script set |  | ||||||
|      the correct paths.  */ |  | ||||||
|   if (getenv ("MCRON_UNINSTALLED") == NULL) |  | ||||||
|     { |  | ||||||
|       wrap_env_path ("GUILE_LOAD_PATH", PACKAGE_LOAD_PATH); |  | ||||||
|       wrap_env_path ("GUILE_LOAD_COMPILED_PATH", PACKAGE_LOAD_COMPILED_PATH); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   scm_boot_guile (argc, argv, inner_main, NULL); |  | ||||||
| 
 |  | ||||||
|   return EXIT_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* 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 scripts crontab")); |  | ||||||
|   scm_call_0 (scm_variable_ref (scm_c_lookup ("main"))); |  | ||||||
| } |  | ||||||
							
								
								
									
										7
									
								
								src/crontab.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/crontab.in
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | #!%GUILE% --no-auto-compile | ||||||
|  | -*- scheme -*- | ||||||
|  | !# | ||||||
|  | 
 | ||||||
|  | (set! %load-path (cons "%modsrcdir%" %load-path)) | ||||||
|  | (set! %load-compiled-path (cons "%modbuilddir%" %load-compiled-path)) | ||||||
|  | ((@ (mcron scripts crontab) main)) | ||||||
							
								
								
									
										126
									
								
								src/mcron.c
									
										
									
									
									
								
							
							
						
						
									
										126
									
								
								src/mcron.c
									
										
									
									
									
								
							|  | @ -1,126 +0,0 @@ | ||||||
| /* mcron.c -- run jobs at scheduled times
 |  | ||||||
|    Copyright © 2003, 2014 Dale Mellor <dale_mellor@users.sourceforge.net> |  | ||||||
|    Copyright © 2015, 2016, 2017 Mathieu Lirzin <mthl@gnu.org> |  | ||||||
| 
 |  | ||||||
|    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/>.  */
 |  | ||||||
| 
 |  | ||||||
| #include "utils.h" |  | ||||||
| #include <argp.h> |  | ||||||
| #include <string.h> |  | ||||||
| 
 |  | ||||||
| /* Forward declarations.  */ |  | ||||||
| static void inner_main (void *closure, int argc, char *argv[]); |  | ||||||
| static SCM parse_args (int argc, char *argv[]); |  | ||||||
| static error_t parse_opt (int key, char *arg, struct argp_state *state); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| main (int argc, char *argv[]) |  | ||||||
| { |  | ||||||
|   /* Set Guile load paths to ensure that Mcron modules will be found after
 |  | ||||||
|      installation.  In a build environment let the 'pre-inst-env' script set |  | ||||||
|      the correct paths.  */ |  | ||||||
|   if (getenv ("MCRON_UNINSTALLED") == NULL) |  | ||||||
|     { |  | ||||||
|       wrap_env_path ("GUILE_LOAD_PATH", PACKAGE_LOAD_PATH); |  | ||||||
|       wrap_env_path ("GUILE_LOAD_COMPILED_PATH", PACKAGE_LOAD_COMPILED_PATH); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   scm_boot_guile (argc, argv, inner_main, NULL); |  | ||||||
| 
 |  | ||||||
|   return EXIT_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Launch the Mcron Guile main program.  */ |  | ||||||
| static void |  | ||||||
| inner_main (void *closure, int argc, char *argv[]) |  | ||||||
| { |  | ||||||
|   SCM config = parse_args (argc, argv); |  | ||||||
|   scm_set_current_module (scm_c_resolve_module ("mcron scripts mcron")); |  | ||||||
|   scm_call_1 (scm_variable_ref (scm_c_lookup ("main")), config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Handle command line arguments.  */ |  | ||||||
| static SCM |  | ||||||
| parse_args (int argc, char *argv[]) |  | ||||||
| { |  | ||||||
|   static struct argp_option options[] = { |  | ||||||
|     {"schedule", 's', "N", 0, |  | ||||||
|      "Display the next N jobs that will be run"}, |  | ||||||
|     {"daemon", 'd', 0, 0, |  | ||||||
|      "Run as a daemon process"}, |  | ||||||
|     {"stdin", 'i', "FORMAT", 0, |  | ||||||
|      "Format of data passed as standard input or file arguments (default guile)"}, |  | ||||||
|     {0, 0, 0, 0, 0} |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   static struct argp argp = { |  | ||||||
|     .options = options, |  | ||||||
|     .parser = parse_opt, |  | ||||||
|     .args_doc = "[FILE...]", |  | ||||||
|     .doc = "Run an mcron process according to the specifications in the " |  | ||||||
|     "FILE... (`-' for standard input), or use all the files in " |  | ||||||
|     "~/.config/cron (or the deprecated ~/.cron) with .guile or " |  | ||||||
|     ".vixie extensions." |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   SCM config = SCM_EOL; |  | ||||||
|   argp_program_version = PACKAGE_STRING; |  | ||||||
|   argp_program_bug_address = PACKAGE_BUGREPORT; |  | ||||||
|   argp_parse (&argp, argc, argv, 0, NULL, &config); |  | ||||||
| 
 |  | ||||||
|   return config; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static error_t |  | ||||||
| parse_opt (int key, char *arg, struct argp_state *state) |  | ||||||
| { |  | ||||||
|   SCM *config = state->input; |  | ||||||
| 
 |  | ||||||
|   switch (key) |  | ||||||
|     { |  | ||||||
|     case 's': |  | ||||||
|       assq_symbol_set_x (config, "schedule", |  | ||||||
|                          scm_from_int (atoi (arg))); |  | ||||||
|       break; |  | ||||||
|     case 'd': |  | ||||||
|       assq_symbol_set_x (config, "daemon", SCM_BOOL_T); |  | ||||||
|       break; |  | ||||||
|     case 'i': |  | ||||||
|       if (strncmp (arg, "vixie", 6) == 0) |  | ||||||
|         assq_symbol_set_x (config, "vixie", SCM_BOOL_T); |  | ||||||
|       break; |  | ||||||
|     case ARGP_KEY_NO_ARGS: |  | ||||||
|       assq_symbol_set_x (config, "files", SCM_EOL); |  | ||||||
|       break; |  | ||||||
|     case ARGP_KEY_ARGS: |  | ||||||
|       { |  | ||||||
|         SCM lst = SCM_EOL; |  | ||||||
|         int filec = state->argc - state->next; |  | ||||||
|         char **filev = state->argv + state->next; |  | ||||||
| 	int i; |  | ||||||
| 
 |  | ||||||
|         for (i = filec - 1; i >= 0; i--) |  | ||||||
|           lst = scm_cons (scm_from_locale_string (filev[i]), lst); |  | ||||||
| 
 |  | ||||||
|         assq_symbol_set_x (config, "files", lst); |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     case ARGP_KEY_ARG: |  | ||||||
|     default: |  | ||||||
|       return ARGP_ERR_UNKNOWN; |  | ||||||
|     } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
							
								
								
									
										8
									
								
								src/mcron.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/mcron.in
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | #!%GUILE% --no-auto-compile | ||||||
|  | -*- scheme -*- | ||||||
|  | !# | ||||||
|  | 
 | ||||||
|  | (set! %load-path (cons "%modsrcdir%" %load-path)) | ||||||
|  | (set! %load-compiled-path (cons "%modbuilddir%" %load-compiled-path)) | ||||||
|  | (use-modules  (mcron scripts mcron)) | ||||||
|  | (main) | ||||||
|  | @ -139,7 +139,7 @@ entries that are to run at this time.  When SCHEDULE is empty next time is | ||||||
| (define* (display-schedule count #:optional (port (current-output-port)) | (define* (display-schedule count #:optional (port (current-output-port)) | ||||||
|                            #:key (schedule %global-schedule)) |                            #:key (schedule %global-schedule)) | ||||||
|   "Display on PORT a textual list of the next COUNT jobs to run.  This |   "Display on PORT a textual list of the next COUNT jobs to run.  This | ||||||
| simulates the run of the job loop to display the resquested information. | simulates the run of the job loop to display the requested information. | ||||||
| Since calling this procedure has the effect of mutating the job timings, the | Since calling this procedure has the effect of mutating the job timings, the | ||||||
| program must exit after.  Otherwise the internal data state will be left | program must exit after.  Otherwise the internal data state will be left | ||||||
| unusable." | unusable." | ||||||
|  |  | ||||||
|  | @ -202,14 +202,14 @@ go into the list.  For example, (range 1 6 2) returns '(1 3 5)." | ||||||
| ;; The job function, available to configuration files for adding a job rule to | ;; The job function, available to configuration files for adding a job rule to | ||||||
| ;; the system. | ;; the system. | ||||||
| ;; | ;; | ||||||
| ;; Here we must 'normalize' the next-time-function so that it is always a lambda | ;; Here we must 'normalize' the next-time-function so that it is always a | ||||||
| ;; function which takes one argument (the last time the job ran) and returns a | ;; lambda function which takes one argument (the last time the job ran) and | ||||||
| ;; single value (the next time the job should run). If the input value is a | ;; returns a single value (the next time the job should run). If the input | ||||||
| ;; string this is parsed as a Vixie-style time specification, and if it is a | ;; value is a string this is parsed as a Vixie-style time specification, and | ||||||
| ;; list then we arrange to eval it (but note that such lists are expected to | ;; if it is a list then we arrange to eval it (but note that such lists are | ||||||
| ;; ignore the function parameter - the last run time is always read from the | ;; expected to ignore the function parameter - the last run time is always | ||||||
| ;; %CURRENT-ACTION-TIME parameter object). A similar normalization is applied to | ;; read from the %CURRENT-ACTION-TIME parameter object). A similar | ||||||
| ;; the action. | ;; normalization is applied to the action. | ||||||
| ;; | ;; | ||||||
| ;; Here we also compute the first time that the job is supposed to run, by | ;; Here we also compute the first time that the job is supposed to run, by | ||||||
| ;; finding the next legitimate time from the current configuration time (set | ;; finding the next legitimate time from the current configuration time (set | ||||||
|  | @ -229,7 +229,8 @@ go into the list.  For example, (range 1 6 2) returns '(1 3 5)." | ||||||
|          (cond ((procedure? time-proc) time-proc) |          (cond ((procedure? time-proc) time-proc) | ||||||
|                ((string? time-proc)    (parse-vixie-time time-proc)) |                ((string? time-proc)    (parse-vixie-time time-proc)) | ||||||
|                ((list? time-proc)      (lambda (current-time) |                ((list? time-proc)      (lambda (current-time) | ||||||
|                                          (primitive-eval time-proc))) |                                          (eval time-proc | ||||||
|  |                                (resolve-module '(mcron job-specifier))))) | ||||||
|                (else |                (else | ||||||
|                 (throw 'mcron-error 3 |                 (throw 'mcron-error 3 | ||||||
|                        "job: invalid first argument (next-time-function; " |                        "job: invalid first argument (next-time-function; " | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
| ;;; You should have received a copy of the GNU General Public License | ;;; You should have received a copy of the GNU General Public License | ||||||
| ;;; along with GNU Mcron.  If not, see <http://www.gnu.org/licenses/>. | ;;; along with GNU Mcron.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| (define-module (mcron scripts cron) | (define-module (mcron scripts cron) | ||||||
|   #:use-module (ice-9 getopt-long) |   #:use-module (ice-9 getopt-long) | ||||||
|   #:use-module (ice-9 ftw) |   #:use-module (ice-9 ftw) | ||||||
|  | @ -28,6 +29,8 @@ | ||||||
|   #:use-module (srfi srfi-2) |   #:use-module (srfi srfi-2) | ||||||
|   #:export (main)) |   #:export (main)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (show-help) | (define (show-help) | ||||||
|   (display "Usage: cron [OPTIONS] |   (display "Usage: cron [OPTIONS] | ||||||
| Unless an option is specified, run a cron daemon as a detached process, | Unless an option is specified, run a cron daemon as a detached process, | ||||||
|  | @ -41,13 +44,16 @@ reading all the information in the users' crontabs and in /etc/crontab. | ||||||
|   (newline) |   (newline) | ||||||
|   (show-package-information)) |   (show-package-information)) | ||||||
| 
 | 
 | ||||||
| (define %options | 
 | ||||||
|   `((schedule (single-char #\s) (value #t) | 
 | ||||||
|               (predicate ,(λ (str) (string->number str)))) | (define  %options  `((schedule (single-char #\s) (value #t) | ||||||
|  |                                (predicate ,string->number)) | ||||||
|                      (noetc    (single-char #\n) (value #f)) |                      (noetc    (single-char #\n) (value #f)) | ||||||
|                      (version  (single-char #\v) (value #f)) |                      (version  (single-char #\v) (value #f)) | ||||||
|                      (help     (single-char #\h) (value #f)))) |                      (help     (single-char #\h) (value #f)))) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (delete-run-file) | (define (delete-run-file) | ||||||
|   "Remove the /var/run/cron.pid file so that crontab and other invocations of |   "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 | cron don't get the wrong idea that a daemon is currently running.  This | ||||||
|  | @ -60,6 +66,8 @@ received." | ||||||
|     noop) |     noop) | ||||||
|   (quit)) |   (quit)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (cron-file-descriptors) | (define (cron-file-descriptors) | ||||||
|   "Establish a socket to listen for updates from a crontab program, and return |   "Establish a socket to listen for updates from a crontab program, and return | ||||||
| a list containing the file descriptors correponding to the files read by | a list containing the file descriptors correponding to the files read by | ||||||
|  | @ -74,6 +82,8 @@ crontab.  This requires that command-type is 'cron." | ||||||
|       (delete-file config-pid-file) |       (delete-file config-pid-file) | ||||||
|       (mcron-error 1 "Cannot bind to UNIX socket " config-socket-file)))) |       (mcron-error 1 "Cannot bind to UNIX socket " config-socket-file)))) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (process-files-in-system-directory) | (define (process-files-in-system-directory) | ||||||
|   "Process all the files in the crontab directory.  When the job procedure is |   "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 | run on behalf of the configuration files, the jobs are registered on the | ||||||
|  | @ -103,9 +113,6 @@ operation.  The permissions on the /var/cron/tabs directory enforce this." | ||||||
|     (with-output-to-file config-pid-file noop)) |     (with-output-to-file config-pid-file noop)) | ||||||
|   ;; Clear MAILTO so that outputs are sent to the various users. |   ;; Clear MAILTO so that outputs are sent to the various users. | ||||||
|   (setenv "MAILTO" #f) |   (setenv "MAILTO" #f) | ||||||
|   ;; XXX: 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) |  | ||||||
|   ;; Having defined all the necessary procedures for scanning various sets of |   ;; Having defined all the necessary procedures for scanning various sets of | ||||||
|   ;; files, we perform the actual configuration of the program depending on |   ;; 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 |   ;; the personality we are running as. If it is mcron, we either scan the | ||||||
|  | @ -138,8 +145,7 @@ option.\n") | ||||||
|   (let ((opts (getopt-long args %options))) |   (let ((opts (getopt-long args %options))) | ||||||
|     (when config-debug |     (when config-debug | ||||||
|       (debug-enable 'backtrace)) |       (debug-enable 'backtrace)) | ||||||
|     (cond |     (cond  ((option-ref opts 'help #f) | ||||||
|      ((option-ref opts 'help #f) |  | ||||||
|                (show-help) |                (show-help) | ||||||
|                (exit 0)) |                (exit 0)) | ||||||
|            ((option-ref opts 'version #f) |            ((option-ref opts 'version #f) | ||||||
|  | @ -157,17 +163,30 @@ option.\n") | ||||||
|            (else |            (else | ||||||
|                (%process-files (option-ref opts 'schedule #f) |                (%process-files (option-ref opts 'schedule #f) | ||||||
|                                (option-ref opts 'noetc #f)) |                                (option-ref opts 'noetc #f)) | ||||||
|       (cond ((option-ref opts 'schedule #f) ;display jobs schedule |                (cond ((option-ref opts 'schedule #f) | ||||||
|                       => (λ (count) |                       => (λ (count) | ||||||
|                            (display-schedule (max 1 (string->number count))) |                            (display-schedule (max 1 (string->number count))) | ||||||
|                   (exit 0))) |                            (exit 0))))))) | ||||||
|             (else (case (primitive-fork) ;run the daemon | 
 | ||||||
|                     ((0) |   ;; Daemonize ourself. | ||||||
|  |   (unless  (eq? 0 (primitive-fork))  (exit 0)) | ||||||
|   (setsid) |   (setsid) | ||||||
|                      ;; we can now write the PID file. | 
 | ||||||
|  |   ;; Set up process signal handlers, as signals are the only way to terminate | ||||||
|  |   ;; the daemon and we MUST be graceful in defeat. | ||||||
|  |   (for-each   (λ (x)  (sigaction  x | ||||||
|  |                           (λ (sig)  (catch #t | ||||||
|  |                                            (λ () | ||||||
|  |                                              (delete-file config-pid-file) | ||||||
|  |                                              (delete-file config-socket-file)) | ||||||
|  |                                            noop) | ||||||
|  |                              (exit EXIT_FAILURE)))) | ||||||
|  |                 '(SIGTERM SIGINT SIGQUIT SIGHUP)) | ||||||
|  | 
 | ||||||
|  |   ;; We can now write the PID file. | ||||||
|   (with-output-to-file  config-pid-file |   (with-output-to-file  config-pid-file | ||||||
|                        (λ () (display (getpid)) (newline)))) |                         (λ () (display (getpid)) (newline))) | ||||||
|                     (else (exit 0))))) | 
 | ||||||
|   ;; Forever execute the 'run-job-loop', and when it drops out (can |   ;; Forever execute the 'run-job-loop', and when it drops out (can | ||||||
|   ;; only be because a message has come in on the socket) we |   ;; only be because a message has come in on the socket) we | ||||||
|   ;; process the socket request before restarting the loop again. |   ;; process the socket request before restarting the loop again. | ||||||
|  | @ -175,5 +194,4 @@ option.\n") | ||||||
|    (let ((fdes-list (cron-file-descriptors))) |    (let ((fdes-list (cron-file-descriptors))) | ||||||
|      (while #t |      (while #t | ||||||
|        (run-job-loop fdes-list) |        (run-job-loop fdes-list) | ||||||
|            (unless (null? fdes-list) |        (unless (null? fdes-list) (process-update-request fdes-list)))))) | ||||||
|              (process-update-request fdes-list))))))))) |  | ||||||
|  |  | ||||||
|  | @ -25,13 +25,13 @@ | ||||||
|   #:use-module (mcron vixie-specification) |   #:use-module (mcron vixie-specification) | ||||||
|   #:export (main)) |   #:export (main)) | ||||||
| 
 | 
 | ||||||
| (define* (show-help) | (define (show-help) | ||||||
|   (display "Usage: crontab [-u user] file |   (display "Usage: crontab [-u user] file | ||||||
|        crontab [-u user] { -e | -l | -r } |        crontab [-u user] { -e | -l | -r } | ||||||
|                (default operation is replace, per 1003.2) |                (default operation is replace, per 1003.2) | ||||||
|        -e      (edit user's crontab) |        -e      (edit user's crontab) | ||||||
|        -l      (list user's crontab) |        -l      (list user's crontab) | ||||||
|        -r      (delete user's crontab") |        -r      (delete user's crontab)") | ||||||
|   (newline) |   (newline) | ||||||
|   (show-package-information)) |   (show-package-information)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,13 +19,40 @@ | ||||||
| 
 | 
 | ||||||
| (define-module (mcron scripts mcron) | (define-module (mcron scripts mcron) | ||||||
|   #:use-module (ice-9 ftw) |   #:use-module (ice-9 ftw) | ||||||
|  |   #:use-module (ice-9 getopt-long) | ||||||
|  |   #:use-module (ice-9 local-eval) | ||||||
|  |   #:use-module (ice-9 rdelim) | ||||||
|   #:use-module (mcron base) |   #:use-module (mcron base) | ||||||
|   #:use-module (mcron config) |   #:use-module (mcron config) | ||||||
|   #:use-module (mcron job-specifier)    ;for user/system files |   #:use-module (mcron job-specifier)    ; For user/system files. | ||||||
|   #:use-module (mcron utils) |   #:use-module (mcron utils) | ||||||
|   #:use-module (mcron vixie-specification) |   #:use-module (mcron vixie-specification) | ||||||
|   #:export (main)) |   #:export (main)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | (define (show-help) | ||||||
|  |   (display "Usage: mcron [OPTION...] [FILE...] | ||||||
|  | Run an mcron process according to the specifications in the FILE... (`-' for | ||||||
|  | standard input), or use all the files in ~/.config/cron (or the deprecated | ||||||
|  | ~/.cron) with .guile or .vixie extensions. | ||||||
|  | 
 | ||||||
|  |   -d, --daemon               Run as a daemon process | ||||||
|  |   -i, --stdin=(guile|vixie)  Format of data passed as standard input or file | ||||||
|  |                              arguments (default guile) | ||||||
|  |   -s, --schedule[=N]         Display the next N (or 8) jobs that will be run | ||||||
|  |   -?, --help                 Give this help list | ||||||
|  |   -V, --version              Print program version | ||||||
|  | 
 | ||||||
|  | Mandatory or optional arguments to long options are also mandatory or optional | ||||||
|  | for any corresponding short options. | ||||||
|  | 
 | ||||||
|  | Report bugs to bug-mcron@gnu.org. | ||||||
|  | 
 | ||||||
|  | ")) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define process-user-file | (define process-user-file | ||||||
|   (let ((guile-regexp (make-regexp "\\.gui(le)?$")) |   (let ((guile-regexp (make-regexp "\\.gui(le)?$")) | ||||||
|         (vixie-regexp (make-regexp "\\.vix(ie)?$"))) |         (vixie-regexp (make-regexp "\\.vix(ie)?$"))) | ||||||
|  | @ -36,12 +63,16 @@ silently ignored." | ||||||
|       (cond ((string=? "-" file-name) |       (cond ((string=? "-" file-name) | ||||||
|                   (if (string=? input "vixie") |                   (if (string=? input "vixie") | ||||||
|                       (read-vixie-port (current-input-port)) |                       (read-vixie-port (current-input-port)) | ||||||
|                  (eval-string (read-string)))) |                       (eval-string (read-string) | ||||||
|  |                                    (resolve-module '(mcron job-specifier))))) | ||||||
|             ((or guile-syntax? (regexp-exec guile-regexp file-name)) |             ((or guile-syntax? (regexp-exec guile-regexp file-name)) | ||||||
|              (load file-name)) |                   (eval-string (read-delimited "" (open-input-file file-name)) | ||||||
|  |                                (resolve-module '(mcron job-specifier)))) | ||||||
|             ((regexp-exec vixie-regexp file-name) |             ((regexp-exec vixie-regexp file-name) | ||||||
|                   (read-vixie-file file-name)))))) |                   (read-vixie-file file-name)))))) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (process-files-in-user-directory input-type) | (define (process-files-in-user-directory input-type) | ||||||
|   "Process files in $XDG_CONFIG_HOME/cron and/or ~/.cron directories (if |   "Process files in $XDG_CONFIG_HOME/cron and/or ~/.cron directories (if | ||||||
| $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead)." | $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead)." | ||||||
|  | @ -64,6 +95,8 @@ $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead)." | ||||||
|       (mcron-error 13 |       (mcron-error 13 | ||||||
|         "Cannot read files in your ~/.config/cron (or ~/.cron) directory.")))) |         "Cannot read files in your ~/.config/cron (or ~/.cron) directory.")))) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| (define (%process-files files input-type) | (define (%process-files files input-type) | ||||||
|   (if (null? files) |   (if (null? files) | ||||||
|       (process-files-in-user-directory input-type) |       (process-files-in-user-directory input-type) | ||||||
|  | @ -74,25 +107,42 @@ $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead)." | ||||||
| ;;; Entry point. | ;;; Entry point. | ||||||
| ;;; | ;;; | ||||||
| 
 | 
 | ||||||
| (define* (main #:optional (opts '())) | (define (main) | ||||||
|  | 
 | ||||||
|  |   (let ((options | ||||||
|  |             (getopt-long | ||||||
|  |                 (command-line) | ||||||
|  |                 `((daemon   (single-char #\d) (value #f)) | ||||||
|  |                   (stdin    (single-char #\i) (value #t) | ||||||
|  |                             (predicate ,(λ (in) (or (string=? in "guile") | ||||||
|  |                                                     (string=? in "vixie"))))) | ||||||
|  |                   (schedule (single-char #\s) (value optional) | ||||||
|  |                             (predicate ,string->number)) | ||||||
|  |                   (help     (single-char #\?)) | ||||||
|  |                   (version  (single-char #\V)))))) | ||||||
|  | 
 | ||||||
|  |     (cond ((option-ref options 'help #f)      (show-help)             (exit 0)) | ||||||
|  |           ((option-ref options 'version #f)   (show-version "mcron")  (exit 0))) | ||||||
|  |    | ||||||
|     (when config-debug |     (when config-debug | ||||||
|       (debug-enable 'backtrace)) |       (debug-enable 'backtrace)) | ||||||
| 
 | 
 | ||||||
|   (%process-files (or (assq-ref opts 'files) '()) |     (%process-files (option-ref options '() '()) | ||||||
|                   (if (assq-ref opts 'vixie) "vixie" "guile")) |                     (option-ref options 'stdin "guile")) | ||||||
| 
 | 
 | ||||||
|   (cond ((assq-ref opts 'schedule) ;display jobs schedule |     (cond ((option-ref options 'schedule #f) | ||||||
|                => (λ (count) |                => (λ (count) | ||||||
|               (display-schedule (max 1 count)) |                      (let ((c (if (string? count) (string->number count) 8))) | ||||||
|  |                        (display-schedule  (if (exact-integer? c) (max 1 c) 8))) | ||||||
|                      (exit 0))) |                      (exit 0))) | ||||||
|         ((assq-ref opts 'daemon) ;run mcron as a daemon |           ((option-ref options 'daemon #f) | ||||||
|                (case (primitive-fork) |                (case (primitive-fork) | ||||||
|                      ((0)  (setsid)) |                      ((0)  (setsid)) | ||||||
|                      (else (exit 0))))) |                      (else (exit 0))))) | ||||||
| 
 | 
 | ||||||
|   ;; Forever execute the 'run-job-loop', and when it drops out (can |     ;; Forever execute the 'run-job-loop', and when it drops out (can only be | ||||||
|   ;; only be because a message has come in on the socket) we process |     ;; because a message has come in on the socket) we process the socket | ||||||
|   ;; the socket request before restarting the loop again. |     ;; request before restarting the loop again. | ||||||
|     (catch-mcron-error |     (catch-mcron-error | ||||||
|      (let ((fdes-list '())) |      (let ((fdes-list '())) | ||||||
|        (while #t |        (while #t | ||||||
|  | @ -100,4 +150,4 @@ $XDG_CONFIG_HOME is not defined uses ~/.config/cron instead)." | ||||||
|          ;; we can also drop out of run-job-loop because of a SIGCHLD, |          ;; we can also drop out of run-job-loop because of a SIGCHLD, | ||||||
|          ;; so must test FDES-LIST. |          ;; so must test FDES-LIST. | ||||||
|          (unless (null? fdes-list) |          (unless (null? fdes-list) | ||||||
|          (process-update-request fdes-list)))))) |            (process-update-request fdes-list))))))) | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								src/utils.c
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/utils.c
									
										
									
									
									
								
							|  | @ -1,48 +0,0 @@ | ||||||
| /* utils.c -- Utility functions.
 |  | ||||||
|    Copyright © 2017 Mathieu Lirzin <mthl@gnu.org> |  | ||||||
| 
 |  | ||||||
|    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/>.  */
 |  | ||||||
| 
 |  | ||||||
| #include "utils.h" |  | ||||||
| #include <stdbool.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| wrap_env_path (const char *envar, const char *dir) |  | ||||||
| { |  | ||||||
|   const char *path = getenv (envar); |  | ||||||
|   if (path == NULL) |  | ||||||
|     setenv (envar, dir, true); |  | ||||||
|   else |  | ||||||
|     { |  | ||||||
|       char *new_path; |  | ||||||
|       int ret = asprintf (&new_path, "%s:%s", dir, path); |  | ||||||
|       if (ret >= 0) |  | ||||||
|         setenv (envar, new_path, true); |  | ||||||
|       else |  | ||||||
|         { |  | ||||||
|           perror (envar); |  | ||||||
|           exit (EXIT_FAILURE); |  | ||||||
|         } |  | ||||||
|       free (new_path); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| assq_symbol_set_x (SCM *alst, const char *symbol, SCM val) |  | ||||||
| { |  | ||||||
|   *alst = scm_assq_set_x (*alst, scm_from_utf8_symbol (symbol), val); |  | ||||||
| } |  | ||||||
							
								
								
									
										33
									
								
								src/utils.h
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								src/utils.h
									
										
									
									
									
								
							|  | @ -1,33 +0,0 @@ | ||||||
| /* utils.h -- Utility functions.
 |  | ||||||
|    Copyright © 2017 Mathieu Lirzin <mthl@gnu.org> |  | ||||||
| 
 |  | ||||||
|    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/>.  */
 |  | ||||||
| 
 |  | ||||||
| #ifndef MCRON_UTILS_H |  | ||||||
| #define MCRON_UTILS_H |  | ||||||
| 
 |  | ||||||
| #include <libguile.h> |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|    Append DIR in front of ENVAR environment variable value.  If ENVAR is not |  | ||||||
|    defined, then define it with DIR.  Bail out if something went wrong.  */ |  | ||||||
| extern void wrap_env_path (const char *envar, const char *dir); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|    In the association list pointed by ALST, set SYMBOL to VAL.  */ |  | ||||||
| extern void assq_symbol_set_x (SCM *alst, const char *symbol, SCM val); |  | ||||||
| 
 |  | ||||||
| #endif /* MCRON_UTILS_H */ |  | ||||||
|  | @ -27,6 +27,9 @@ cat > cron/foo.guile <<EOF | ||||||
| (job '(next-second) '(display "foo\n")) | (job '(next-second) '(display "foo\n")) | ||||||
| EOF | EOF | ||||||
| 
 | 
 | ||||||
|  | mcron --schedule=1 cron/foo.guile > "output$$" | ||||||
|  | grep -e "foo" "output$$" || fail_ "'foo.guile' job is not scheduled" | ||||||
|  | 
 | ||||||
| mcron --schedule=1 > "output$$" | mcron --schedule=1 > "output$$" | ||||||
| grep -e "foo" "output$$" || fail_ "'foo.guile' job is not scheduled" | grep -e "foo" "output$$" || fail_ "'foo.guile' job is not scheduled" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,36 +56,32 @@ | ||||||
| 
 | 
 | ||||||
| ;;; TODO: Find more meaningful date examples. | ;;; TODO: Find more meaningful date examples. | ||||||
| 
 | 
 | ||||||
|  | (setenv "TZ" ":UTC") | ||||||
|  | 
 | ||||||
| (test-equal "next-year" | (test-equal "next-year" | ||||||
|   (list 59989762800 1546293600) |   (list 1893456000 1546300800) | ||||||
|   (list (next-year '(1971)) |   (list (next-year '(130))   ;; This is the year 2030. | ||||||
|         (next-year-from 1522095469))) |         (next-year-from 1522095469))) | ||||||
| 
 | 
 | ||||||
| (test-equal "next-month" | (test-equal "next-month" | ||||||
|   (list 28854000 5094000) |   5097600 | ||||||
|   (list (next-month '(11)) |   (next-month-from 101 '(0 2 4))) | ||||||
|         (next-month-from 101 '(0 2 4)))) |  | ||||||
| 
 | 
 | ||||||
| (test-equal "next-day" | (test-equal "next-day" | ||||||
|   (list 2588400 342000) |   345600 | ||||||
|   (list (next-day '(31)) |   (next-day-from 4337 '(0 5 10))) | ||||||
|         (next-day-from 4337 '(0 5 10)))) |  | ||||||
| 
 | 
 | ||||||
| (test-equal "next-hour" | (test-equal "next-hour" | ||||||
|   '(3600 82800 3600) |   3600 | ||||||
|   (list (next-hour) |   (next-hour-from 3 '(0 1 2 3 4))) | ||||||
|         (next-hour '(0)) |  | ||||||
|         (next-hour-from 3 '(0 1 2 3 4)))) |  | ||||||
| 
 | 
 | ||||||
| (test-equal "next-minute" | (test-equal "next-minute" | ||||||
|   '(240 60) |   60 | ||||||
|   (list (next-minute '(4 9)) |   (next-minute-from 8)) | ||||||
|         (next-minute-from 8))) |  | ||||||
| 
 | 
 | ||||||
| (test-equal "next-second" | (test-equal "next-second" | ||||||
|   '(52 15) |   15 | ||||||
|   (list (next-second '(52 55)) |   (next-second-from 14)) | ||||||
|         (next-second-from 14))) |  | ||||||
| 
 | 
 | ||||||
| ;;; | ;;; | ||||||
| ;;; Check 'configuration-user' manipulation | ;;; Check 'configuration-user' manipulation | ||||||
|  |  | ||||||
							
								
								
									
										81
									
								
								tests/schedule-2.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								tests/schedule-2.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | ||||||
|  | # schedule-2.sh -- Check mcron schedule output | ||||||
|  | # Copyright © 2020  Dale Mellor <mcron-lsfnyl@rdmp.org> | ||||||
|  | # | ||||||
|  | # 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/>. | ||||||
|  | 
 | ||||||
|  | source "${srcdir}/tests/init.sh" | ||||||
|  | 
 | ||||||
|  | # Use UTC and SOURCE_DATE_EPOCH to get reproducible result. | ||||||
|  | 
 | ||||||
|  | SOURCE_DATE_EPOCH=1 | ||||||
|  | export SOURCE_DATE_EPOCH | ||||||
|  | 
 | ||||||
|  | TZ=UTC0 | ||||||
|  | export TZ | ||||||
|  | 
 | ||||||
|  | # Use current working directory to store mcron files | ||||||
|  | XDG_CONFIG_HOME=`pwd` | ||||||
|  | export XDG_CONFIG_HOME | ||||||
|  | 
 | ||||||
|  | LC_ALL=C | ||||||
|  | export LC_ALL | ||||||
|  | 
 | ||||||
|  | mkdir cron | ||||||
|  | cat > cron/foo.guile <<EOF | ||||||
|  | (job '(next-second) '(display "foo\n")) | ||||||
|  | EOF | ||||||
|  | 
 | ||||||
|  | cat > expected <<EOF | ||||||
|  | Thu Jan  1 00:00:01 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:02 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:03 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:04 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:05 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:06 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:07 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | Thu Jan  1 00:00:08 1970 +0000 | ||||||
|  | (display foo | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | EOF | ||||||
|  | 
 | ||||||
|  | mcron -s cron/foo.guile > output | ||||||
|  | diff expected output \ | ||||||
|  |     || skip_ 'The -s option is not fully functional;  | ||||||
|  | this will be fixed with a future version of GNU Guile.' | ||||||
|  | 
 | ||||||
|  | Exit 0 | ||||||
|  | @ -26,6 +26,9 @@ export SOURCE_DATE_EPOCH | ||||||
| TZ=UTC0 | TZ=UTC0 | ||||||
| export TZ | export TZ | ||||||
| 
 | 
 | ||||||
|  | LC_ALL=C | ||||||
|  | export LC_ALL | ||||||
|  | 
 | ||||||
| # Use current working directory to store mcron files | # Use current working directory to store mcron files | ||||||
| XDG_CONFIG_HOME=`pwd` | XDG_CONFIG_HOME=`pwd` | ||||||
| export XDG_CONFIG_HOME | export XDG_CONFIG_HOME | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 atsb
				atsb