From 22732b9850ed1f00b7bfd1b7ac88705be4ab7c54 Mon Sep 17 00:00:00 2001 From: thib Date: Fri, 22 Jun 2001 21:06:05 +0000 Subject: [PATCH] added fcron.conf support --- allow.c | 6 +-- conf.c | 4 +- config.h.in | 46 +++++++++--------- fcron.c | 36 ++++++++------ fcrontab.c | 50 ++++++++++++-------- job.c | 31 ++++++------ subs.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++- subs.h | 17 ++++++- 8 files changed, 244 insertions(+), 80 deletions(-) diff --git a/allow.c b/allow.c index edea906..d13c3a2 100644 --- a/allow.c +++ b/allow.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: allow.c,v 1.8 2001-06-12 06:40:54 thib Exp $ */ + /* $Id: allow.c,v 1.9 2001-06-22 21:10:30 thib Exp $ */ #include "fcrontab.h" #include "allow.h" @@ -84,8 +84,8 @@ is_allowed(char *user) return 0; /* check if user is in fcron.allow and/or in fcron.deny files */ - allow = in_file(user, ETC "/" FCRON_ALLOW); - deny = in_file(user, ETC "/" FCRON_DENY); + allow = in_file(user, fcronallow); + deny = in_file(user, fcrondeny); if ( allow == -1 && deny == -1 ) /* neither fcron.allow nor fcron.deny exist : diff --git a/conf.c b/conf.c index c9c7fa6..0ca2ab8 100644 --- a/conf.c +++ b/conf.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: conf.c,v 1.45 2001-05-28 18:48:54 thib Exp $ */ + /* $Id: conf.c,v 1.46 2001-06-22 21:09:00 thib Exp $ */ #include "fcron.h" #include "conf.h" @@ -82,7 +82,7 @@ synchronize_dir(const char *dir_name) struct dirent *den; if ( strcmp(dir_name, ".") == 0 ) - explain("updating configuration from " FCRONTABS ); + explain("updating configuration from %s", fcrontabs); else explain("updating configuration from %s", dir_name); diff --git a/config.h.in b/config.h.in index 2977d6f..8c535fc 100644 --- a/config.h.in +++ b/config.h.in @@ -21,7 +21,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: config.h.in,v 1.31 2001-06-05 10:18:16 thib Exp $ */ + /* $Id: config.h.in,v 1.32 2001-06-22 21:09:30 thib Exp $ */ /* *********************************************************** */ @@ -33,14 +33,34 @@ /* beginning of configurable stuff ********************************** */ -/* fcron allow and deny file are located in directory ETC (see below) */ +/* fcron allow, deny and conf files are located in directory ETC (see below) */ #define FCRON_ALLOW "fcron.allow" - #define FCRON_DENY "fcron.deny" +#define FCRON_CONF "fcron.conf" #define SENDMAIL_ARGS "-Ffcron", "-odi" /* args of mail command */ +/* *** time *** */ +#define FIRST_SLEEP 20 /* fcron sleep at least this time after startup + * before executing a job, to avoid to run jobs + * during system boot */ + +#define LAVG_SLEEP 30 /* the time we sleep when some jobs are in lavg queue */ + +#define SAVE 1800 /* save every n seconds */ + +/* *** behavior *** */ +#define SERIAL_ONCE 0 /* can a job be several times in the serial queue at + * the same moment ? */ + +#define LAVG_ONCE 1 /* can a job be several times in the lavg queue at + * the same moment ? */ + +#define MAXYEAR_SCHEDULE_TIME 10 /* a job can't be scheduled further than + * now + MAXYEAR_SCHEDULE years. This is used + * to prevent infinite loop on corrupted lines */ + /* *** memory *** */ #define EXE_INITIAL_SIZE 6 /* initial number of possible running job * if more jobs have to be run simultaneously, @@ -84,26 +104,6 @@ #define MAX_MSG 150 /* max length of a log message */ -/* *** time *** */ -#define FIRST_SLEEP 20 /* fcron sleep at least this time after startup - * before executing a job, to avoid to run jobs - * during system boot */ - -#define LAVG_SLEEP 30 /* the time we sleep when some jobs are in lavg queue */ - -#define SAVE 1800 /* save every n seconds */ - -/* *** behavior *** */ -#define SERIAL_ONCE 0 /* can a job be several times in the serial queue at - * the same moment ? */ - -#define LAVG_ONCE 1 /* can a job be several times in the lavg queue at - * the same moment ? */ - -#define MAXYEAR_SCHEDULE_TIME 10 /* a job can't be scheduled further than - * now + MAXYEAR_SCHEDULE years. This is used - * to prevent infinite loop on corrupted lines */ - /* *** system dependent *** */ #define EXIT_ERR 1 /* code returned by fcron/fcrontab on error */ #define EXIT_OK 0 /* code returned on normal exit */ diff --git a/fcron.c b/fcron.c index 5f9d7be..e8b4889 100644 --- a/fcron.c +++ b/fcron.c @@ -21,11 +21,11 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fcron.c,v 1.48 2001-06-05 10:17:56 thib Exp $ */ + /* $Id: fcron.c,v 1.49 2001-06-22 21:08:03 thib Exp $ */ #include "fcron.h" -char rcs_info[] = "$Id: fcron.c,v 1.48 2001-06-05 10:17:56 thib Exp $"; +char rcs_info[] = "$Id: fcron.c,v 1.49 2001-06-22 21:08:03 thib Exp $"; void main_loop(void); void check_signal(void); @@ -158,7 +158,7 @@ xexit(int exit_value) f = file_base; } - remove(PIDFILE); + remove(pidfile); explain("Exiting with code %d", exit_value); exit (exit_value); @@ -179,17 +179,17 @@ get_lock() if ( ! daemon_lockfp ) { int fd; - if (((fd = open(PIDFILE, O_RDWR|O_CREAT, 0644)) == -1 ) + if (((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 ) || ((daemon_lockfp = fdopen(fd, "r+"))) == NULL) - die_e("can't open or create " PIDFILE); + die_e("can't open or create %s", pidfile); #ifdef HAVE_FLOCK /* flock() seems to keep the lock over a fork() (contrary to lockf() ): * we only need to lock the file once */ if ( flock(fd, LOCK_EX|LOCK_NB) != 0 ) { fscanf(daemon_lockfp, "%d", &otherpid); - die("can't lock " PIDFILE ", running daemon's pid may be %d", - otherpid); + die("can't lock %s, running daemon's pid may be %d", + pidfile, otherpid); } #endif /* HAVE_FLOCK */ @@ -200,8 +200,8 @@ get_lock() #ifndef HAVE_FLOCK if ( lockf(fileno(daemon_lockfp), F_TLOCK, 0) != 0 ) { fscanf(daemon_lockfp, "%d", &otherpid); - die("can't lock " PIDFILE ", running daemon's pid may be %d", - otherpid); + die("can't lock %s, running daemon's pid may be %d", + pidfile, otherpid); } #endif /* ! HAVE_FLOCK */ @@ -238,6 +238,7 @@ parseopt(int argc, char *argv[]) {"version", 0, NULL, 'V'}, {"savetime", 1, NULL, 's'}, {"maxserial", 1, NULL, 'm'}, + {"configfile", 1, NULL, 'c'}, {0,0,0,0} }; #endif /* HAVE_GETOPT_H */ @@ -249,9 +250,9 @@ parseopt(int argc, char *argv[]) while(1) { #ifdef HAVE_GETOPT_H - c = getopt_long(argc, argv, "dfbhVs:m:", opt, NULL); + c = getopt_long(argc, argv, "dfbhVs:m:c:", opt, NULL); #else - c = getopt(argc, argv, "dfbhVs:m:"); + c = getopt(argc, argv, "dfbhVs:m:c:"); #endif /* HAVE_GETOPT_H */ if (c == EOF) break; switch (c) { @@ -283,6 +284,10 @@ parseopt(int argc, char *argv[]) die("Max running can only be set between 1 and %d.",SHRT_MAX); break; + case 'c': + Set(fcronconf, optarg); + break; + case ':': error("(parseopt) Missing parameter"); usage(); @@ -358,7 +363,7 @@ int main(int argc, char **argv) { - /* we set it to 022 in order to get a PIDFILE readable by fcrontab + /* we set it to 022 in order to get a pidfile readable by fcrontab * (will be set to 066 later) */ saved_umask = umask(022); @@ -379,10 +384,13 @@ main(int argc, char **argv) parseopt(argc, argv); + /* read fcron.conf and update global parameters */ + read_conf(); + /* change directory */ - if (chdir(FCRONTABS) != 0) - die_e("Could not change dir to " FCRONTABS); + if (chdir(fcrontabs) != 0) + die_e("Could not change dir to %s", fcrontabs); if (foreground == 0) { diff --git a/fcrontab.c b/fcrontab.c index c99fc32..df72dd9 100644 --- a/fcrontab.c +++ b/fcrontab.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fcrontab.c,v 1.38 2001-06-03 10:54:22 thib Exp $ */ + /* $Id: fcrontab.c,v 1.39 2001-06-22 21:06:37 thib Exp $ */ /* * The goal of this program is simple : giving a user interface to fcron @@ -42,7 +42,7 @@ #include "fcrontab.h" -char rcs_info[] = "$Id: fcrontab.c,v 1.38 2001-06-03 10:54:22 thib Exp $"; +char rcs_info[] = "$Id: fcrontab.c,v 1.39 2001-06-22 21:06:37 thib Exp $"; void info(void); void usage(void); @@ -135,7 +135,7 @@ read_pid(void) FILE *fp = NULL; pid_t pid = 0; - if ((fp = fopen(PIDFILE, "r")) != NULL) { + if ((fp = fopen(pidfile, "r")) != NULL) { fscanf(fp, "%d", (int *) &pid); fclose(fp); } @@ -157,7 +157,7 @@ sig_daemon(void) FILE *fp = NULL; int fd = 0; struct tm *tm = NULL; - + char sigfile[PATH_LEN]; t = time(NULL); tm = localtime(&t); @@ -179,6 +179,7 @@ sig_daemon(void) fprintf(stderr, "Modifications will be taken into account" " at %s.\n", buf); + snprintf(sigfile, sizeof(sigfile), "%s/fcrontab.sig", fcrontabs); #if defined(HAVE_SETREGID) && defined(HAVE_SETREUID) if (seteuid(fcrontab_uid) != 0) @@ -187,7 +188,7 @@ sig_daemon(void) switch ( fork() ) { case -1: - remove(FCRONTABS "/fcrontab.sig"); + remove(sigfile); die_e("could not fork : daemon has not been signaled"); break; case 0: @@ -201,9 +202,9 @@ sig_daemon(void) foreground = 0; /* try to create a lock file */ - if ((fd = open(FCRONTABS "/fcrontab.sig", O_RDWR|O_CREAT, 0644)) == -1 + if ((fd = open(sigfile, O_RDWR|O_CREAT, 0644)) == -1 || ((fp = fdopen(fd, "r+")) == NULL) ) - die_e("can't open or create " FCRONTABS "/fcrontab.sig"); + die_e("can't open or create %s", sigfile); #ifdef HAVE_FLOCK if ( flock(fd, LOCK_EX|LOCK_NB) != 0 ) { @@ -224,7 +225,7 @@ sig_daemon(void) fclose(fp); close(fd); - remove(FCRONTABS "/fcrontab.sig"); + remove(sigfile); } else fprintf(stderr, "Modifications will be taken into account" @@ -378,7 +379,7 @@ write_file(char *file) return_val = ERR; } - /* copy original file to FCRONTABS dir */ + /* copy original file to fcrontabs dir */ snprintf(buf, sizeof(buf), "%s.orig", user); if ( copy(file, buf) == ERR ) return_val = ERR; @@ -448,7 +449,7 @@ edit_file(char *buf) /* copy file to a temp file, edit that file, and install it if necessary */ { - char *editor = NULL; + char *cureditor = NULL; pid_t pid; int status; struct stat st; @@ -460,11 +461,11 @@ edit_file(char *buf) char correction = 0; short return_val = EXIT_OK; - explain("fcrontabs : editing %s's fcrontab", user); + explain("fcrontab : editing %s's fcrontab", user); - if ( (editor = getenv("VISUAL")) == NULL || strcmp(editor, "\0") == 0 ) - if( (editor = getenv("EDITOR")) == NULL || strcmp(editor, "\0") == 0 ) - editor = EDITOR; + if ((cureditor=getenv("VISUAL")) == NULL || strcmp(cureditor, "\0") == 0 ) + if((cureditor=getenv("EDITOR"))==NULL || strcmp(cureditor, "\0") == 0 ) + cureditor = editor; file = temp_file(&tmp_str); if ( (fi = fdopen(file, "w")) == NULL ) { @@ -530,8 +531,8 @@ edit_file(char *buf) goto exiterr; } #endif - execlp(editor, editor, tmp_str, NULL); - error_e("Error while running \"%s\"", editor); + execlp(cureditor, cureditor, tmp_str, NULL); + error_e("Error while running \"%s\"", cureditor); goto exiterr; case -1: @@ -720,7 +721,7 @@ parseopt(int argc, char *argv[]) /* constants and variables defined by command line */ while(1) { - c = getopt(argc, argv, "u:lrezdnhV"); + c = getopt(argc, argv, "u:lrezdnhVc:"); if (c == EOF) break; switch (c) { @@ -793,6 +794,10 @@ parseopt(int argc, char *argv[]) ignore_prev = 1; break; + case 'c': + Set(fcronconf, optarg); + break; + case ':': fprintf(stderr, "(setopt) Missing parameter"); usage(); @@ -805,6 +810,9 @@ parseopt(int argc, char *argv[]) } } + /* read fcron.conf and update global parameters */ + read_conf(); + /* read the file name and/or user and check validity of the arguments */ if (argc - optind > 2) usage(); @@ -891,8 +899,8 @@ main(int argc, char **argv) if (seteuid(fcrontab_uid) != 0) die_e("Could not change uid to fcrontab_uid[%d]",fcrontab_uid); /* change directory */ - if (chdir(FCRONTABS) != 0) { - error_e("Could not chdir to " FCRONTABS ); + if (chdir(fcrontabs) != 0) { + error_e("Could not chdir to %s", fcrontabs); xexit (EXIT_ERR); } /* get user's permissions */ @@ -907,8 +915,8 @@ main(int argc, char **argv) if (setgid(0) != 0) die_e("Could not change gid to 0"); /* change directory */ - if (chdir(FCRONTABS) != 0) { - error_e("Could not chdir to " FCRONTABS ); + if (chdir(fcrontabs) != 0) { + error_e("Could not chdir to %s", fcrontabs); xexit (EXIT_ERR); } #endif diff --git a/job.c b/job.c index cf5327e..52656ee 100644 --- a/job.c +++ b/job.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: job.c,v 1.38 2001-05-15 00:37:54 thib Exp $ */ + /* $Id: job.c,v 1.39 2001-06-22 21:06:05 thib Exp $ */ #include "fcron.h" #include "job.h" @@ -157,7 +157,7 @@ run_job(struct exe *exeent) case 0: /* child */ { - char *shell; + char *curshell; char *home; env_t *env; int mailfd = 0; @@ -205,15 +205,16 @@ run_job(struct exe *exeent) die_e("Could not chdir to HOME dir /"); } - if ( (shell = getenv("SHELL")) == NULL ) - shell = SHELL; - else if ( access(shell, X_OK) != 0 ) { + if ( (curshell = getenv("SHELL")) == NULL ) + curshell = shell; + else if ( access(curshell, X_OK) != 0 ) { if (errno == ENOENT) - error("shell \"%s\" : no file or directory. SHELL set to " - SHELL, shell); + error("shell \"%s\" : no file or directory. SHELL set to %s", + curshell, shell); else - error_e("shell \"%s\" not valid : SHELL set to " SHELL, shell); - shell = SHELL; + error_e("shell \"%s\" not valid : SHELL set to %s", + curshell, shell); + curshell = shell; } @@ -229,14 +230,14 @@ run_job(struct exe *exeent) #ifdef CHECKJOBS /* this will force to mail a message containing at least the exact * and complete command executed for each execution of all jobs */ - debug("Execing \"%s -c %s\"", shell, line->cl_shell); + debug("Execing \"%s -c %s\"", curshell, line->cl_shell); #endif /* CHECKJOBS */ - execl(shell, shell, "-c", line->cl_shell, NULL); + execl(curshell, curshell, "-c", line->cl_shell, NULL); /* execl returns only on error */ - error_e("Can't find \"%s\". Trying a execlp(\"sh\", ...)", shell); + error_e("Can't find \"%s\". Trying a execlp(\"sh\",...)",curshell); execlp("sh", "sh", "-c", line->cl_shell, NULL); - die_e("execl() \"%s -c %s\" error", shell, line->cl_shell); + die_e("execl() \"%s -c %s\" error", curshell, line->cl_shell); /* execution never gets here */ @@ -321,8 +322,8 @@ launch_mailer(CL *line, int mailfd) xcloselog(); /* run sendmail with mail file as standard input */ - execl(SENDMAIL, SENDMAIL, SENDMAIL_ARGS, line->cl_mailto, NULL); - error_e("Can't find \""SENDMAIL"\". Trying a execlp(\"sendmail\")"); + execl(sendmail, sendmail, SENDMAIL_ARGS, line->cl_mailto, NULL); + error_e("Can't find \"%s\". Trying a execlp(\"sendmail\")", sendmail); execlp("sendmail", "sendmail", SENDMAIL_ARGS, line->cl_mailto, NULL); die_e("Can't exec " SENDMAIL); #else /* defined(SENDMAIL) */ diff --git a/subs.c b/subs.c index 55a8a82..f70e6b5 100644 --- a/subs.c +++ b/subs.c @@ -22,12 +22,25 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: subs.c,v 1.9 2001-06-12 06:40:33 thib Exp $ */ + /* $Id: subs.c,v 1.10 2001-06-22 21:10:18 thib Exp $ */ #include "global.h" #include "subs.h" +void init_conf(void); + extern char *tmp_path; +extern char debug_opt; + +/* fcron.conf parameters */ +char *fcronconf = NULL; +char *fcronallow = NULL; +char *fcrondeny = NULL; +char *fcrontabs = NULL; +char *pidfile = NULL; +char *editor = NULL; +char *shell = NULL; +char *sendmail = NULL; int remove_blanks(char *str) @@ -120,6 +133,125 @@ temp_file(char **name) } +void +init_conf(void) +/* initialises config with compiled in constants */ +{ + /* set fcronconf if cmd line option -c has not been used */ + if (fcronconf == NULL) + fcronconf = strdup2(ETC "/" FCRON_CONF); + fcronallow = strdup2(ETC "/" FCRON_ALLOW); + fcrondeny = strdup2(ETC "/" FCRON_DENY); + fcrontabs = strdup2(FCRONTABS); + pidfile = strdup2(PIDFILE); + editor = strdup2(EDITOR); + shell = strdup2(SHELL); + sendmail = strdup2(SENDMAIL); +} + + +void +read_conf(void) +/* reads in a config file and updates the necessary global variables */ +{ + FILE *f = NULL; + struct stat st; + char buf[LINE_LEN]; + char *ptr1 = NULL, *ptr2 = NULL; + short namesize = 0; + char err_on_enoent = 0; + + if (fcronconf != NULL) + /* fcronconf has been set by -c option : file must exist */ + err_on_enoent = 1; + + init_conf(); + + if ( (f = fopen(fcronconf, "r")) == NULL ) { + if ( errno == ENOENT ) { + if ( err_on_enoent ) + die_e("Could not read %s", fcronconf); + else + /* file does not exist, it is not an error */ + return; + } + else { + error_e("Could not read %s : config file ignored", fcronconf); + return; + } + } + + /* check if the file is secure : owned and writable only by root */ + if ( fstat(fileno(f), &st) != 0 || st.st_uid != 0 + || st.st_mode & S_IWGRP || st.st_mode & S_IWOTH ) { + error("Conf file (%s) must be owned by root and (no more than) 644 : " + "ignored", fcronconf); + fclose(f); + return; + } + + while ( (ptr1 = fgets(buf, sizeof(buf), f)) != NULL ) { + + Skip_blanks(ptr1); /* at the beginning of the line */ + + /* ignore comments and blank lines */ + if ( *ptr1 == '#' || *ptr1 == '\n' || *ptr1 == '\0') + continue; + + remove_blanks(ptr1); /* at the end of the line */ + + ptr2 = ptr1; + + /* get the name of the var */ + while ( (isalnum( (int) *ptr2) || *ptr2 == '_') + && *ptr2 != '=' && ! isspace( (int) *ptr2) ) + ptr2++; + + if ( (namesize = ptr2 - ptr1) == 0 ) + /* name is zero-length */ + error("Zero-length var name at line %s : line ignored", buf); + + /* skip the blanks and the "=" and go to the value */ + while ( isspace( (int) *ptr2 ) ) ptr2++; + if ( *ptr2 == '=' ) ptr2++; + while ( isspace( (int) *ptr2 ) ) ptr2++; + + /* find which var the line refers to and update it */ + if ( strncmp(ptr1, "fcronallow", 10) == 0 ) + fcronallow = strdup2(ptr2); + else if ( strncmp(ptr1, "fcrondeny", 9) == 0 ) + fcrondeny = strdup2(ptr2); + else if ( strncmp(ptr1, "fcrontabs", 9) == 0 ) + fcrontabs = strdup2(ptr2); + else if ( strncmp(ptr1, "pidfile", 7) == 0 ) + pidfile = strdup2(ptr2); + else if ( strncmp(ptr1, "editor", 6) == 0 ) + editor = strdup2(ptr2); + else if ( strncmp(ptr1, "shell", 5) == 0 ) + shell = strdup2(ptr2); + else if ( strncmp(ptr1, "sendmail", 8) == 0 ) + sendmail = strdup2(ptr2); + else + error("Unknown var name at line %s : line ignored", buf); + + } + + if (debug_opt) { + debug("fcronconf=%s", fcronconf); + debug("fcronallow=%s", fcronallow); + debug("fcrondeny=%s", fcrondeny); + debug("fcrontabs=%s", fcrontabs); + debug("pidfile=%s", pidfile); + debug("editor=%s", editor); + debug("shell=%s", shell); + debug("sendmail=%s", sendmail); + } + + fclose(f); + +} + + int save_type(FILE *f, short int type) /* save a single type (with no data attached) in a binary fcrontab file */ diff --git a/subs.h b/subs.h index bfde3e5..f31e7c7 100644 --- a/subs.h +++ b/subs.h @@ -21,15 +21,30 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: subs.h,v 1.2 2001-05-15 00:51:17 thib Exp $ */ + /* $Id: subs.h,v 1.3 2001-06-22 21:10:27 thib Exp $ */ #ifndef __SUBS_H__ #define __SUBS_H__ + +/* global variables */ + +/* fcron.conf parameters */ +extern char *fcronconf; +extern char *fcronallow; +extern char *fcrondeny; +extern char *fcrontabs; +extern char *pidfile; +extern char *editor; +extern char *shell; +extern char *sendmail; +/* end of global variables */ + /* functions prototypes */ extern int remove_blanks(char *str); extern char *strdup2(const char *); extern int temp_file(char **name); +extern void read_conf(void); extern int save_type(FILE *f, short int type); extern int save_str(FILE *f, short int type, char *str); extern int save_strn(FILE *f, short int type, char *str, short int size); -- 2.40.0