>From 36a255e847e4a782bb31b4b84a64553caeb560a6 Mon Sep 17 00:00:00 2001 From: Mathieu Lirzin Date: Sun, 16 Aug 2015 10:33:37 +0200 Subject: [PATCH] main: Add (mcron main) module. Replace 'ed' hack to eval content of scm/mcron/main.scm in the C wrapper by executing the C code in the context of (mcron main). * scm/mcron/main.scm (mcron main): New module. (show-version, show-package-information, show-help, main): Remove extra newline characters in strings. * mcron.c.template: Rename to ... * mcron.c: ... this. (inner_main): Set current module to (mcron main). * makefile.ed: Delete file. * configure.ac: Remove check for 'ed' program. * makefile.am, .gitignore: Adjust accordingly. --- .gitignore | 1 - configure.ac | 4 -- makefile.am | 11 +---- makefile.ed | 34 --------------- mcron.c | 102 +++++++++++++++++++++++++++++++++++++++++++++ mcron.c.template | 120 ----------------------------------------------------- scm/mcron/main.scm | 108 ++++++++++++++++++++++------------------------- 7 files changed, 153 insertions(+), 227 deletions(-) delete mode 100644 makefile.ed create mode 100644 mcron.c delete mode 100644 mcron.c.template diff --git a/.gitignore b/.gitignore index 6aaa315..4505cc5 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ install-sh makefile makefile.in /mcron -mcron.c /mdate-sh *.o missing diff --git a/configure.ac b/configure.ac index a3b84e6..2149e9d 100644 --- a/configure.ac +++ b/configure.ac @@ -64,10 +64,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) diff --git a/makefile.am b/makefile.am index 1ee24bd..045107d 100644 --- a/makefile.am +++ b/makefile.am @@ -21,12 +21,9 @@ SUBDIRS = scm/mcron . -ED = @ED@ # !!!! Are these needed? CP = @CP@ -CLEANFILES = mcron.c - -EXTRA_DIST = makefile.ed mcron.c.template BUGS +EXTRA_DIST = BUGS info_TEXINFOS = doc/mcron.texi @@ -40,12 +37,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 - dist-hook: gen-ChangeLog gen_start_date = 2015-07-07 diff --git a/makefile.ed b/makefile.ed deleted file mode 100644 index 7047ec7..0000000 --- a/makefile.ed +++ /dev/null @@ -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 . -# -# -# -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 diff --git a/mcron.c b/mcron.c new file mode 100644 index 0000000..472f096 --- /dev/null +++ b/mcron.c @@ -0,0 +1,102 @@ +/* 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 . */ + +/* 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 +#include +#include + +/* 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 (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; +} diff --git a/mcron.c.template b/mcron.c.template deleted file mode 100644 index e9a755d..0000000 --- a/mcron.c.template +++ /dev/null @@ -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 . - */ - - -/* - 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 -#include -#include - - - -/* 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; -} diff --git a/scm/mcron/main.scm b/scm/mcron/main.scm index 6a75be4..c03ccfc 100644 --- a/scm/mcron/main.scm +++ b/scm/mcron/main.scm @@ -16,28 +16,22 @@ ;; You should have received a copy of the GNU General Public License along ;; with GNU mcron. If not, see . - - -;; 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. - -(use-modules (ice-9 getopt-long) - (ice-9 rdelim) - (ice-9 regex) - (mcron config) - (mcron core) - (mcron job-specifier) - (mcron vixie-specification) - (srfi srfi-2) - (srfi srfi-26)) +;;; 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-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 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)) (define* (command-name #:optional (command (car (command-line)))) "Extract the actual command name from COMMAND. This returns the last part @@ -112,18 +106,18 @@ and exit with its error code." (let* ((name config-package-name) (short-name (cadr (string-split name #\space))) (version config-package-version)) - (simple-format #t "~a (~a) ~a\n -Copyright (C) 2015 the ~a authors.\n -License GPLv3+: GNU GPL version 3 or later \n -This is free software: you are free to change and redistribute it.\n + (simple-format #t "~a (~a) ~a +Copyright (C) 2015 the ~a authors. +License GPLv3+: GNU GPL version 3 or later +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 short-name) (quit))) (define (show-package-information) "Display where to get help and send bug reports." - (simple-format #t "\nReport bugs to: ~a.\n -~a home page: <~a>\n + (simple-format #t "\nReport bugs to: ~a. +~a home page: <~a> General help using GNU software: \n" config-package-bugreport config-package-name @@ -135,34 +129,34 @@ General help using GNU software: \n" (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) - " [-u user] file\n - crontab [-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 + " [-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) @@ -379,10 +373,10 @@ comes in on the above socket." 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\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 + (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) @@ -423,5 +417,3 @@ option.\n") (run-job-loop fdes-list) (unless (null? fdes-list) (process-update-request fdes-list)))))) - -(main) -- 2.6.1