From ca55b93a497bc53a2ff4520b14993db73023e652 Mon Sep 17 00:00:00 2001 From: Thibault Godouet Date: Mon, 24 Dec 2012 15:19:41 +0000 Subject: [PATCH] Applied indentation with 'make indent' --- Makefile.in | 4 +- allow.c | 64 +- allow.h | 2 +- bitstring.h | 26 +- cl.c | 11 +- cl.h | 54 +- conf.c | 1461 +++++++++++++------------- conf.h | 2 +- convert-fcrontab.c | 203 ++-- convert-fcrontab.h | 2 +- database.c | 1761 ++++++++++++++++--------------- database.h | 24 +- doc/en/changes.sgml | 9 + doc/en/todo.sgml | 8 +- dyncom.h | 2 +- env_list.c | 86 +- env_list.h | 23 +- exe_list.c | 29 +- exe_list.h | 20 +- exe_list_test.c | 138 ++- fcron.c | 694 +++++++------ fcron.h | 5 +- fcronconf.c | 137 +-- fcronconf.h | 2 +- fcrondyn.c | 665 ++++++------ fcrondyn.h | 2 +- fcronsighup.c | 271 ++--- fcronsighup.h | 2 +- fcrontab.c | 1185 ++++++++++----------- fcrontab.h | 2 +- fifo_list.c | 174 ++-- fifo_list.h | 40 +- fileconf.c | 2426 ++++++++++++++++++++++--------------------- fileconf.h | 2 +- getloadavg.c | 92 +- getloadavg.h | 2 +- global.h | 29 +- job.c | 838 +++++++-------- job.h | 9 +- lavg_list.c | 30 +- lavg_list.h | 20 +- log.c | 125 +-- log.h | 6 +- mem.c | 30 +- mem.h | 6 +- option.h | 3 +- pam.h | 2 +- read_string.c | 94 +- read_string.h | 4 +- save.c | 318 +++--- save.h | 60 +- socket.c | 1049 ++++++++++--------- socket.h | 2 +- subs.c | 141 +-- subs.h | 11 +- temp_file.c | 34 +- temp_file.h | 2 +- u_list.c | 184 ++-- u_list.h | 38 +- 59 files changed, 6498 insertions(+), 6167 deletions(-) diff --git a/Makefile.in b/Makefile.in index 5bc938c..4f7004f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -281,7 +281,9 @@ updatedoc: $(MAKE) -C doc doc indent: - indent -linux -i4 -nsob -sc -psl -nce *.c *.h + indent -linux -i4 --no-tabs --leave-optional-blank-lines \ + --start-left-side-of-comments --procnames-start-lines \ + --dont-cuddle-else *.c *.h configure: configure.in # update configure script, then Makefile and config.h, and finally diff --git a/allow.c b/allow.c index 430bf5f..7405bb0 100644 --- a/allow.c +++ b/allow.c @@ -38,31 +38,31 @@ in_file(char *str, char *file) FILE *f = NULL; char *start = NULL; - if ( (f = fopen(file, "r")) == NULL ) { - if (errno == ENOENT) - /* file does not exist */ - return -1; - else - die_e("could not open %s", file); + if ((f = fopen(file, "r")) == NULL) { + if (errno == ENOENT) + /* file does not exist */ + return -1; + else + die_e("could not open %s", file); } - while ( fgets(buf, sizeof(buf), f) != NULL ) { - - /* skip leading and trailing blanks, comments */ - start = buf; - Skip_blanks(start); - if ( *start == '#' || *start == '\0' ) - continue; - remove_blanks(start); - - if ( strcmp(str, start) == 0 ) { - fclose(f); - return 1; - } - if ( strcmp(start, "all") == 0 ) { - fclose(f); - return 2; - } + while (fgets(buf, sizeof(buf), f) != NULL) { + + /* skip leading and trailing blanks, comments */ + start = buf; + Skip_blanks(start); + if (*start == '#' || *start == '\0') + continue; + remove_blanks(start); + + if (strcmp(str, start) == 0) { + fclose(f); + return 1; + } + if (strcmp(start, "all") == 0) { + fclose(f); + return 2; + } } fclose(f); @@ -81,7 +81,7 @@ is_allowed(char *user) int deny = 0; /* check if user is in passwd file */ - if ( getpwnam(user) != NULL ) { + if (getpwnam(user) != NULL) { /* check if user is in fcron.allow and/or in fcron.deny files */ allow = in_file(user, fcronallow); @@ -93,20 +93,20 @@ is_allowed(char *user) * 1 if it is in file * and 2 if file contains "all" string */ - if ( allow == -1 && deny == -1 ) + if (allow == -1 && deny == -1) /* neither fcron.allow nor fcron.deny exist : * we consider that user is allowed */ - return 1; + return 1; - if ( allow == -1 && deny == 0 ) + if (allow == -1 && deny == 0) return 1; - - if ( deny == -1 && allow == 1 ) + + if (deny == -1 && allow == 1) return 1; - if ( allow == 1 && deny != 1 ) + if (allow == 1 && deny != 1) return 1; - if ( allow == 2 && deny <= 0 ) + if (allow == 2 && deny <= 0) return 1; } @@ -117,7 +117,7 @@ is_allowed(char *user) { int audit_fd = audit_open(); audit_log_user_message(audit_fd, AUDIT_USER_START, "fcron deny", - NULL, NULL, NULL, 0); + NULL, NULL, NULL, 0); close(audit_fd); } #endif diff --git a/allow.h b/allow.h index 3b85420..14a1945 100644 --- a/allow.h +++ b/allow.h @@ -28,4 +28,4 @@ /* functions prototypes */ extern int is_allowed(char *user); -#endif /* __ALLOW_H__ */ +#endif /* __ALLOW_H__ */ diff --git a/bitstring.h b/bitstring.h index e5e1aed..24007bc 100644 --- a/bitstring.h +++ b/bitstring.h @@ -20,46 +20,46 @@ * @(#)bitstring.h 5.2 (Berkeley) 4/4/90 */ -typedef unsigned char bitstr_t; +typedef unsigned char bitstr_t; /* internal macros */ - /* byte of the bitstring bit is in */ + /* byte of the bitstring bit is in */ /* in other words, _bit_byte(bitnum) is the index (starting from 0) of the byte * which contain the bit number 'bitnum' */ #define _bit_byte(bit) \ ((bit) >> 3) - /* mask for the bit within its byte */ + /* mask for the bit within its byte */ #define _bit_mask(bit) \ (1 << ((bit)&0x7)) /* external macros */ - /* bytes in a bitstring of nbits bits */ + /* bytes in a bitstring of nbits bits */ #define bitstr_size(nbits) \ ((((nbits) - 1) >> 3) + 1) - /* allocate a bitstring */ + /* allocate a bitstring */ #define bit_alloc(nbits) \ (bitstr_t *)malloc(1, \ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t)) - /* allocate a bitstring on the stack */ + /* allocate a bitstring on the stack */ #define bit_decl(name, nbits) \ (name)[bitstr_size(nbits)] - /* is bit N of bitstring name set? */ + /* is bit N of bitstring name set? */ #define bit_test(name, bit) \ ((name)[_bit_byte(bit)] & _bit_mask(bit)) - /* set bit N of bitstring name */ + /* set bit N of bitstring name */ #define bit_set(name, bit) \ (name)[_bit_byte(bit)] |= _bit_mask(bit) - /* clear bit N of bitstring name */ + /* clear bit N of bitstring name */ #define bit_clear(name, bit) \ (name)[_bit_byte(bit)] &= ~_bit_mask(bit) - /* clear bits start ... stop in bitstring */ + /* clear bits start ... stop in bitstring */ #define bit_nclear(name, start, stop) { \ register bitstr_t *_name = name; \ register int _start = start, _stop = stop; \ @@ -76,7 +76,7 @@ typedef unsigned char bitstr_t; } \ } - /* set bits start ... stop in bitstring */ + /* set bits start ... stop in bitstring */ #define bit_nset(name, start, stop) { \ register bitstr_t *_name = name; \ register int _start = start, _stop = stop; \ @@ -93,7 +93,7 @@ typedef unsigned char bitstr_t; } \ } - /* find first bit clear in name */ + /* find first bit clear in name */ #define bit_ffc(name, nbits, value) { \ register bitstr_t *_name = name; \ register int _byte, _nbits = nbits; \ @@ -108,7 +108,7 @@ typedef unsigned char bitstr_t; *(value) = _value; \ } - /* find first bit set in name */ + /* find first bit set in name */ #define bit_ffs(name, nbits, value) { \ register bitstr_t *_name = name; \ register int _byte, _nbits = nbits; \ diff --git a/cl.c b/cl.c index 2711bc0..c4e1f94 100644 --- a/cl.c +++ b/cl.c @@ -25,8 +25,8 @@ #include "cl.h" #include "mem.h" -cl_t* -dups_cl(cl_t *orig) +cl_t * +dups_cl(cl_t * orig) /* Duplicate a line, including the strings it points to. */ { cl_t *cl = NULL; @@ -48,7 +48,8 @@ dups_cl(cl_t *orig) cl->cl_runas = NULL; Set(cl->cl_runas, orig->cl_runas); - debug("%s: Set cl->cl_runas=%s", __func__, (cl->cl_runas == NULL) ? "null" : cl->cl_runas); + debug("%s: Set cl->cl_runas=%s", __func__, + (cl->cl_runas == NULL) ? "null" : cl->cl_runas); cl->cl_mailto = NULL; Set(cl->cl_mailto, orig->cl_mailto); @@ -60,7 +61,7 @@ dups_cl(cl_t *orig) } void -free_line(cl_t *cl) +free_line(cl_t * cl) /* free a line, including its fields */ { if (cl != NULL) { @@ -71,5 +72,3 @@ free_line(cl_t *cl) Free_safe(cl); } } - - diff --git a/cl.h b/cl.h index 8d6e373..3483bc7 100644 --- a/cl.h +++ b/cl.h @@ -30,37 +30,37 @@ * TYPES */ -#define OPTION_SIZE 4 /* number of bytes to hold the cl_option bit array */ +#define OPTION_SIZE 4 /* number of bytes to hold the cl_option bit array */ #define LAVG_SIZE 3 /* warning : do not change the order of the members of this structure * because some tests made are dependent to that order */ /* warning : if you change a field type, you may have to also make some changes * in the save/load binary fcrontab functions */ typedef struct cl_t { - struct cl_t *cl_next; - struct cf_t *cl_file; /* the file in which the line is */ - char *cl_shell; /* shell command */ - char *cl_runas; /* determine permissions of the job */ - char *cl_mailto; /* mail output to cl_mailto */ - char *cl_tz; /* time zone of the line */ - unsigned long cl_id; /* line's unique id number */ - time_t cl_until; /* timeout of the wait for a lavg value */ - time_t cl_first; /* initial delay preserved for volatile entries */ - time_t cl_nextexe; /* time and date of the next execution */ - long int cl_timefreq; /* Run every n seconds */ - unsigned short cl_remain; /* remaining until next execution */ - unsigned short cl_runfreq; /* Run once every n matches(=1 for %-lines)*/ - unsigned char cl_option[OPTION_SIZE]; /* line's option (see option.h) */ - unsigned char cl_lavg[LAVG_SIZE];/*load averages needed (1,5,15 mins) */ - unsigned char cl_numexe; /* entries in queues & running processes */ - char cl_nice; /* nice value to control priority */ - unsigned char cl_jitter; /* run randomly late up to jitter seconds */ + struct cl_t *cl_next; + struct cf_t *cl_file; /* the file in which the line is */ + char *cl_shell; /* shell command */ + char *cl_runas; /* determine permissions of the job */ + char *cl_mailto; /* mail output to cl_mailto */ + char *cl_tz; /* time zone of the line */ + unsigned long cl_id; /* line's unique id number */ + time_t cl_until; /* timeout of the wait for a lavg value */ + time_t cl_first; /* initial delay preserved for volatile entries */ + time_t cl_nextexe; /* time and date of the next execution */ + long int cl_timefreq; /* Run every n seconds */ + unsigned short cl_remain; /* remaining until next execution */ + unsigned short cl_runfreq; /* Run once every n matches(=1 for %-lines) */ + unsigned char cl_option[OPTION_SIZE]; /* line's option (see option.h) */ + unsigned char cl_lavg[LAVG_SIZE]; /*load averages needed (1,5,15 mins) */ + unsigned char cl_numexe; /* entries in queues & running processes */ + char cl_nice; /* nice value to control priority */ + unsigned char cl_jitter; /* run randomly late up to jitter seconds */ /* see bitstring(3) man page for more details */ - bitstr_t bit_decl(cl_mins, 60); /* 0-59 */ - bitstr_t bit_decl(cl_hrs, 24); /* 0-23 */ - bitstr_t bit_decl(cl_days, 32); /* 1-31 */ - bitstr_t bit_decl(cl_mons, 12); /* 0-11 */ - bitstr_t bit_decl(cl_dow, 8); /* 0-7, 0 and 7 are both Sunday */ + bitstr_t bit_decl(cl_mins, 60); /* 0-59 */ + bitstr_t bit_decl(cl_hrs, 24); /* 0-23 */ + bitstr_t bit_decl(cl_days, 32); /* 1-31 */ + bitstr_t bit_decl(cl_mons, 12); /* 0-11 */ + bitstr_t bit_decl(cl_dow, 8); /* 0-7, 0 and 7 are both Sunday */ } cl_t; @@ -69,7 +69,7 @@ typedef struct cl_t { */ /* duplicate a line, including strings it points to */ -cl_t* dups_cl(cl_t *orig); -void free_line(cl_t *cl); +cl_t *dups_cl(cl_t * orig); +void free_line(cl_t * cl); -#endif /* __CL_H__ */ +#endif /* __CL_H__ */ diff --git a/conf.c b/conf.c index e44b7c9..7085270 100644 --- a/conf.c +++ b/conf.c @@ -28,9 +28,9 @@ #include "conf.h" #include "database.h" -int read_file(const char *file_name, cf_t *cf, int is_system_startup); -int add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, - time_t t_save, int is_system_startup); +int read_file(const char *file_name, cf_t * cf, int is_system_startup); +int add_line_to_file(cl_t * cl, cf_t * cf, uid_t runas, char *runas_str, + time_t t_save, int is_system_startup); int read_strn(int fd, char **str, short int size); int read_type(int fd, short int *type, short int *size); void synchronize_file(char *file_name, int is_system_startup); @@ -53,17 +53,17 @@ reload_all(const char *dir_name) explain("Removing current configuration from memory"); f = file_base; - while ( f != NULL ) { - if ( f->cf_running > 0 ) - wait_all( &f->cf_running ); - save_file(f); - delete_file(f->cf_user); - - /* delete_file remove the f file from the list : - * next file to remove is now pointed by file_base. */ - f = file_base; + while (f != NULL) { + if (f->cf_running > 0) + wait_all(&f->cf_running); + save_file(f); + delete_file(f->cf_user); + + /* delete_file remove the f file from the list : + * next file to remove is now pointed by file_base. */ + f = file_base; } - + synchronize_dir(dir_name, 0); } @@ -79,123 +79,123 @@ synchronize_dir(const char *dir_name, int is_system_startup) list_t *rm_list = NULL; list_t *new_list = NULL; - list_t *file_list = NULL; + list_t *file_list = NULL; list_t *list_cur = NULL; DIR *dir; struct dirent *den; - if ( strcmp(dir_name, ".") == 0 ) - explain("updating configuration from %s", fcrontabs); + if (strcmp(dir_name, ".") == 0) + explain("updating configuration from %s", fcrontabs); else - explain("updating configuration from %s", dir_name); + explain("updating configuration from %s", dir_name); if ((dir = opendir("."))) { - while ((den = readdir(dir))) { - - if (strncmp(den->d_name, "rm.", 3) == 0) { - /* this is a file to remove from database */ - Alloc(list_cur, list_t); - list_cur->str = strdup2(den->d_name); - list_cur->next = rm_list; - rm_list = list_cur; - } else - - if (strncmp(den->d_name, "new.", 4) == 0) { - /* this is a file to append to database */ - Alloc(list_cur, list_t); - list_cur->str = strdup2(den->d_name); - list_cur->next = new_list; - new_list = list_cur; - } else - - if (strchr(den->d_name, '.') != NULL) - continue; - else - /* this is a normal file : if file_base is not null, - * so if a database has already been created, we - * ignore it */ - if ( file_base == NULL ) { - Alloc(list_cur, list_t); - list_cur->str = strdup2(den->d_name); - list_cur->next = file_list; - file_list = list_cur; - } - - } - closedir(dir); - } else - die("Unable to open current dir!"); - + while ((den = readdir(dir))) { + + if (strncmp(den->d_name, "rm.", 3) == 0) { + /* this is a file to remove from database */ + Alloc(list_cur, list_t); + list_cur->str = strdup2(den->d_name); + list_cur->next = rm_list; + rm_list = list_cur; + } + else if (strncmp(den->d_name, "new.", 4) == 0) { + /* this is a file to append to database */ + Alloc(list_cur, list_t); + list_cur->str = strdup2(den->d_name); + list_cur->next = new_list; + new_list = list_cur; + } + else if (strchr(den->d_name, '.') != NULL) + continue; + else + /* this is a normal file : if file_base is not null, + * so if a database has already been created, we + * ignore it */ + if (file_base == NULL) { + Alloc(list_cur, list_t); + list_cur->str = strdup2(den->d_name); + list_cur->next = file_list; + file_list = list_cur; + } + + } + closedir(dir); + } + else + die("Unable to open current dir!"); + /* proceed to adds or removes */ /* begin by removing files which are no longer wanted */ - for (list_cur = rm_list; list_cur; list_cur = list_cur->next ) { - explain("removing file %s", list_cur->str + 3); - delete_file(list_cur->str + 3); /* len("rm.") = 3 */ - if ( remove(list_cur->str + 3) != 0 && errno != ENOENT ) - error_e("Could not remove %s", list_cur->str + 3); - if ( remove(list_cur->str) != 0 && errno != ENOENT ) - error_e("Could not remove %s", list_cur->str); + for (list_cur = rm_list; list_cur; list_cur = list_cur->next) { + explain("removing file %s", list_cur->str + 3); + delete_file(list_cur->str + 3); /* len("rm.") = 3 */ + if (remove(list_cur->str + 3) != 0 && errno != ENOENT) + error_e("Could not remove %s", list_cur->str + 3); + if (remove(list_cur->str) != 0 && errno != ENOENT) + error_e("Could not remove %s", list_cur->str); } - + /* then add normal files, if any, to database */ - for (list_cur = file_list; list_cur; list_cur = list_cur->next ) { - errno = 0; - if ( getpwnam(list_cur->str) + for (list_cur = file_list; list_cur; list_cur = list_cur->next) { + errno = 0; + if (getpwnam(list_cur->str) #ifdef SYSFCRONTAB - || strcmp(list_cur->str, SYSFCRONTAB) == 0 + || strcmp(list_cur->str, SYSFCRONTAB) == 0 #endif - ) { - explain("adding file %s", list_cur->str); - synchronize_file(list_cur->str, is_system_startup); - } - else - error_e("ignoring file \"%s\" : not in passwd file.", list_cur->str); + ) { + explain("adding file %s", list_cur->str); + synchronize_file(list_cur->str, is_system_startup); + } + else + error_e("ignoring file \"%s\" : not in passwd file.", + list_cur->str); } /* finally add new files */ - for (list_cur = new_list; list_cur; list_cur = list_cur->next ) { - /* len("new.") = 4 : */ - errno = 0; - if ( getpwnam(list_cur->str + 4) + for (list_cur = new_list; list_cur; list_cur = list_cur->next) { + /* len("new.") = 4 : */ + errno = 0; + if (getpwnam(list_cur->str + 4) #ifdef SYSFCRONTAB - || strcmp(list_cur->str + 4, SYSFCRONTAB) == 0 + || strcmp(list_cur->str + 4, SYSFCRONTAB) == 0 #endif - ) { - explain("adding new file %s", list_cur->str + 4); - synchronize_file(list_cur->str, is_system_startup); - } - else - error_e("ignoring file %s : not in passwd file.", - (list_cur->str + 4)); + ) { + explain("adding new file %s", list_cur->str + 4); + synchronize_file(list_cur->str, is_system_startup); + } + else + error_e("ignoring file %s : not in passwd file.", + (list_cur->str + 4)); } /* free lists */ { - list_t *l = NULL; - list_t *next = NULL; - - next = rm_list; - while( (l = next) != NULL ) { - next = l->next; - Free_safe(l->str); - Free_safe(l); - } - - next = new_list; - while( (l = next) != NULL ) { - next = l->next; - Free_safe(l->str); - Free_safe(l); - } - - next = file_list; - while( (l = next) != NULL ) { - next = l->next; - Free_safe(l->str); - Free_safe(l); - } + list_t *l = NULL; + list_t *next = NULL; + + next = rm_list; + while ((l = next) != NULL) { + next = l->next; + Free_safe(l->str); + Free_safe(l); + } + + next = new_list; + while ((l = next) != NULL) { + next = l->next; + Free_safe(l->str); + Free_safe(l); + } + + next = file_list; + while ((l = next) != NULL) { + next = l->next; + Free_safe(l->str); + Free_safe(l); + } } @@ -209,170 +209,172 @@ synchronize_file(char *file_name, int is_system_startup) cf_t *cur_f = NULL; char *user = NULL; - if (strchr(file_name, '.') != NULL ) { - /* this is a new file : we have to check if there is an old - * version in database in order to keep a maximum of fields - * (cl_nextexe) to their current value */ - - cf_t *prev = NULL; - - /* set user name */ - /* we add 4 to file_name pointer because of the "new." - * string at the beginning of a new file */ - user = (file_name + 4); - - for (cur_f = file_base; cur_f; cur_f = cur_f->cf_next) { - if ( strcmp(user, cur_f->cf_user) == 0 ) - break; - prev = cur_f; - } - - if (cur_f != NULL) { - /* an old version of this file exist in database */ - - cf_t *old = NULL; - cl_t *old_l = NULL; - cl_t *new_l = NULL; - /* size used when comparing two line : - * it's the size of all time table (mins, days ...) */ - const size_t size=( bitstr_size(60) + bitstr_size(24) + - bitstr_size(32) + bitstr_size(12) + - bitstr_size(7) ); - - old = cur_f; - - /* load new file */ - Alloc(cur_f, cf_t); - if ( read_file(file_name, cur_f, is_system_startup) != 0 ) { - /* an error as occured */ - return; - } - - /* assign old pointer to the old file, and move it to the first - * place of the list : delete_file() only remove the first - * occurrence of the file which has the name given in argument */ - if (prev != NULL) { - prev->cf_next = old->cf_next; - old->cf_next = file_base; - file_base = old; - } - else - /* this is the first file in the list : no need to move it */ - ; - - /* compare each lines between the new and the old - * version of the file */ - for (new_l = cur_f->cf_line_base; new_l; new_l = new_l->cl_next) - for(old_l = old->cf_line_base; old_l; old_l = old_l->cl_next) { - - /* compare the shell command and the fields - from cl_mins down to cl_runfreq or the timefreq */ - if ( strcmp(new_l->cl_shell, old_l->cl_shell) == 0 && ( - ( is_freq(new_l->cl_option) && - new_l->cl_timefreq == old_l->cl_timefreq ) || - ( is_td(new_l->cl_option) && - memcmp( &(new_l->cl_mins), &(old_l->cl_mins), - size)==0 && - is_dayor(new_l->cl_option) == - is_dayor(old_l->cl_option) ) - ) ) { - - if ( new_l->cl_runfreq == old_l->cl_runfreq ) - new_l->cl_remain = old_l->cl_remain; - /* check if there is a change about the tz diff */ - if ( (new_l->cl_file->cf_tzdiff != - old_l->cl_file->cf_tzdiff) && - (old_l->cl_nextexe - old_l->cl_file->cf_tzdiff - + new_l->cl_file->cf_tzdiff > now) ) - new_l->cl_nextexe = old_l->cl_nextexe - - old_l->cl_file->cf_tzdiff - + new_l->cl_file->cf_tzdiff; - else - new_l->cl_nextexe = old_l->cl_nextexe; - - if (is_runonce(new_l->cl_option) && is_runonce(old_l->cl_option) + if (strchr(file_name, '.') != NULL) { + /* this is a new file : we have to check if there is an old + * version in database in order to keep a maximum of fields + * (cl_nextexe) to their current value */ + + cf_t *prev = NULL; + + /* set user name */ + /* we add 4 to file_name pointer because of the "new." + * string at the beginning of a new file */ + user = (file_name + 4); + + for (cur_f = file_base; cur_f; cur_f = cur_f->cf_next) { + if (strcmp(user, cur_f->cf_user) == 0) + break; + prev = cur_f; + } + + if (cur_f != NULL) { + /* an old version of this file exist in database */ + + cf_t *old = NULL; + cl_t *old_l = NULL; + cl_t *new_l = NULL; + /* size used when comparing two line : + * it's the size of all time table (mins, days ...) */ + const size_t size = (bitstr_size(60) + bitstr_size(24) + + bitstr_size(32) + bitstr_size(12) + + bitstr_size(7)); + + old = cur_f; + + /* load new file */ + Alloc(cur_f, cf_t); + if (read_file(file_name, cur_f, is_system_startup) != 0) { + /* an error as occured */ + return; + } + + /* assign old pointer to the old file, and move it to the first + * place of the list : delete_file() only remove the first + * occurrence of the file which has the name given in argument */ + if (prev != NULL) { + prev->cf_next = old->cf_next; + old->cf_next = file_base; + file_base = old; + } + else + /* this is the first file in the list : no need to move it */ + ; + + /* compare each lines between the new and the old + * version of the file */ + for (new_l = cur_f->cf_line_base; new_l; new_l = new_l->cl_next) + for (old_l = old->cf_line_base; old_l; old_l = old_l->cl_next) { + + /* compare the shell command and the fields + * from cl_mins down to cl_runfreq or the timefreq */ + if (strcmp(new_l->cl_shell, old_l->cl_shell) == 0 + && ((is_freq(new_l->cl_option) + && new_l->cl_timefreq == old_l->cl_timefreq) + || (is_td(new_l->cl_option) + && memcmp(&(new_l->cl_mins), &(old_l->cl_mins), + size) == 0 + && is_dayor(new_l->cl_option) == + is_dayor(old_l->cl_option)) + )) { + + if (new_l->cl_runfreq == old_l->cl_runfreq) + new_l->cl_remain = old_l->cl_remain; + /* check if there is a change about the tz diff */ + if ((new_l->cl_file->cf_tzdiff != + old_l->cl_file->cf_tzdiff) && + (old_l->cl_nextexe - old_l->cl_file->cf_tzdiff + + new_l->cl_file->cf_tzdiff > now)) + new_l->cl_nextexe = old_l->cl_nextexe + - old_l->cl_file->cf_tzdiff + + new_l->cl_file->cf_tzdiff; + else + new_l->cl_nextexe = old_l->cl_nextexe; + + if (is_runonce(new_l->cl_option) + && is_runonce(old_l->cl_option) && is_hasrun(old_l->cl_option)) { - explain(" from last conf: job '%s' with runonce set has " - "already run since last system startup: not " - "re-scheduling.", new_l->cl_shell); + explain + (" from last conf: job '%s' with runonce set has " + "already run since last system startup: not " + "re-scheduling.", new_l->cl_shell); set_hasrun(new_l->cl_option); /* job has already run: remove from the queue */ job_queue_remove(new_l); } else /* update the position in the queue */ - insert_nextexe(new_l); - - if (debug_opt && ! is_hasrun(new_l->cl_option)) { - struct tm *ftime; - ftime = localtime(&new_l->cl_nextexe); - debug(" from last conf: %s next exec %d/%d/%d" - " wday:%d %02d:%02d:%02d (system time)", - new_l->cl_shell, - (ftime->tm_mon + 1), ftime->tm_mday, - (ftime->tm_year + 1900), ftime->tm_wday, - ftime->tm_hour, ftime->tm_min, ftime->tm_sec); - } - - break; - - } - } - - /* remove old file from the list */ - delete_file(user); - - /* insert new file in the list */ - cur_f->cf_next = file_base; - file_base = cur_f; - - /* save final file */ - save_file(cur_f); - - /* delete new.user file */ - if ( remove(file_name) != 0 ) - error_e("could not remove %s", file_name); - - } - - else { - /* no old version exist in database : load this file - * as a normal file, but change its name */ - - Alloc(cur_f, cf_t); - - if ( read_file(file_name, cur_f, is_system_startup) != 0 ) { - /* an error as occured */ - return; - } - - /* insert the file in the list */ - cur_f->cf_next = file_base; - file_base = cur_f; - - /* save as a normal file */ - save_file(cur_f); - - /* delete new.user file */ - if ( remove(file_name) != 0 ) - error_e("could not remove %s", file_name); - } + insert_nextexe(new_l); + + if (debug_opt && !is_hasrun(new_l->cl_option)) { + struct tm *ftime; + ftime = localtime(&new_l->cl_nextexe); + debug(" from last conf: %s next exec %d/%d/%d" + " wday:%d %02d:%02d:%02d (system time)", + new_l->cl_shell, + (ftime->tm_mon + 1), ftime->tm_mday, + (ftime->tm_year + 1900), ftime->tm_wday, + ftime->tm_hour, ftime->tm_min, ftime->tm_sec); + } + + break; + + } + } + + /* remove old file from the list */ + delete_file(user); + + /* insert new file in the list */ + cur_f->cf_next = file_base; + file_base = cur_f; + + /* save final file */ + save_file(cur_f); + + /* delete new.user file */ + if (remove(file_name) != 0) + error_e("could not remove %s", file_name); + + } + + else { + /* no old version exist in database : load this file + * as a normal file, but change its name */ + + Alloc(cur_f, cf_t); + + if (read_file(file_name, cur_f, is_system_startup) != 0) { + /* an error as occured */ + return; + } + + /* insert the file in the list */ + cur_f->cf_next = file_base; + file_base = cur_f; + + /* save as a normal file */ + save_file(cur_f); + + /* delete new.user file */ + if (remove(file_name) != 0) + error_e("could not remove %s", file_name); + } } else { - /* this is a normal file */ - - Alloc(cur_f, cf_t); + /* this is a normal file */ + + Alloc(cur_f, cf_t); - if ( read_file(file_name, cur_f, is_system_startup) != 0 ) { - /* an error as occured */ - return; - } + if (read_file(file_name, cur_f, is_system_startup) != 0) { + /* an error as occured */ + return; + } - /* insert the file in the list */ - cur_f->cf_next = file_base; - file_base = cur_f; + /* insert the file in the list */ + cur_f->cf_next = file_base; + file_base = cur_f; } @@ -383,32 +385,32 @@ int read_strn(int fd, char **str, short int size) /* read a "size"-length string in a binary fcrontab file */ { - if ( (*str = calloc(size + 1, sizeof(char))) == NULL ) - goto err; - - if ( read(fd, *str, size) < size ) - goto err; + if ((*str = calloc(size + 1, sizeof(char))) == NULL) + goto err; + + if (read(fd, *str, size) < size) + goto err; (*str)[size] = '\0'; return OK; - err: + err: Free_safe(*str); return ERR; - + } int read_type(int fd, short int *type, short int *size) /* read the type and size of the next field in a binary fcrontab file */ { - if ( read(fd, type, sizeof(short int)) < sizeof(short int) ) - goto err; - if ( read(fd, size, sizeof(short int)) < sizeof(short int) ) - goto err; - + if (read(fd, type, sizeof(short int)) < sizeof(short int)) + goto err; + if (read(fd, size, sizeof(short int)) < sizeof(short int)) + goto err; + return OK; - err: + err: return ERR; } @@ -433,9 +435,9 @@ read_type(int fd, short int *type, short int *size) } int -read_file(const char *file_name, cf_t *cf, int is_system_startup) +read_file(const char *file_name, cf_t * cf, int is_system_startup) /* read a formated fcrontab. - return ERR on error, OK otherwise */ + * return ERR on error, OK otherwise */ { FILE *ff = NULL; cl_t *cl = NULL; @@ -447,7 +449,7 @@ read_file(const char *file_name, cf_t *cf, int is_system_startup) struct passwd *pass = NULL; short int type = 0, size = 0; int rc; - int has_read_cl_first = 0; /* have we read S_FIRST_T? */ + int has_read_cl_first = 0; /* have we read S_FIRST_T? */ #ifdef WITH_SELINUX int flask_enabled = is_selinux_enabled(); int retval; @@ -456,55 +458,54 @@ read_file(const char *file_name, cf_t *cf, int is_system_startup) #endif /* open file */ - if ( (ff = fopen(file_name, "r")) == NULL ) { - warn_e("Could not read %s (may have just been removed)", file_name); - goto err; + if ((ff = fopen(file_name, "r")) == NULL) { + warn_e("Could not read %s (may have just been removed)", file_name); + goto err; } /* check if this file is owned by root : otherwise, all runas fields * of this field should be set to the owner */ rc = fstat(fileno(ff), &file_stat); - if ( rc != 0 ) { - error_e("Could not stat %s", file_name); - goto err; + if (rc != 0) { + error_e("Could not stat %s", file_name); + goto err; } #ifdef WITH_SELINUX - if(flask_enabled && fgetfilecon(fileno(ff), &cf->cf_file_context) < 0 ) - { - error_e("Could not get context of %s", file_name); - goto err; + if (flask_enabled && fgetfilecon(fileno(ff), &cf->cf_file_context) < 0) { + error_e("Could not get context of %s", file_name); + goto err; } #endif - if ( strncmp(file_name,"new.", 4) == 0 ) { - if ( file_stat.st_uid == rootuid ) { - /* file is owned by root : no test needed : set runas to rootuid */ - runas = rootuid; - } - else { - /* this is a standard user's new fcrontab : set the runas field to - * the owner of the file */ - runas = file_stat.st_uid; - if ( (pass = getpwuid(file_stat.st_uid)) == NULL ) { - error_e("Could not getpwuid(%d)", file_stat.st_uid); - goto err; - } - runas_str = strdup2(pass->pw_name); - } - cf->cf_user = strdup2(file_name + 4); + if (strncmp(file_name, "new.", 4) == 0) { + if (file_stat.st_uid == rootuid) { + /* file is owned by root : no test needed : set runas to rootuid */ + runas = rootuid; + } + else { + /* this is a standard user's new fcrontab : set the runas field to + * the owner of the file */ + runas = file_stat.st_uid; + if ((pass = getpwuid(file_stat.st_uid)) == NULL) { + error_e("Could not getpwuid(%d)", file_stat.st_uid); + goto err; + } + runas_str = strdup2(pass->pw_name); + } + cf->cf_user = strdup2(file_name + 4); } else { - if(!cf->cf_user) - cf->cf_user = strdup2(file_name); - if ( file_stat.st_uid == rootuid ) { - /* file is owned by root : either this file has already been parsed - * at least once by fcron, or it is root's fcrontab */ - runas = rootuid; - } - else { - error("Non-new file %s owned by someone else than root",file_name); - goto err; - } + if (!cf->cf_user) + cf->cf_user = strdup2(file_name); + if (file_stat.st_uid == rootuid) { + /* file is owned by root : either this file has already been parsed + * at least once by fcron, or it is root's fcrontab */ + runas = rootuid; + } + else { + error("Non-new file %s owned by someone else than root", file_name); + goto err; + } } #ifdef WITH_SELINUX @@ -516,25 +517,24 @@ read_file(const char *file_name, cf_t *cf, int is_system_startup) * permission check for this purpose. */ #ifdef SYSFCRONTAB - if(!strcmp(cf->cf_user, SYSFCRONTAB)) - user_name = "system_u"; + if (!strcmp(cf->cf_user, SYSFCRONTAB)) + user_name = "system_u"; else -#endif /* def SYSFCRONTAB */ - user_name = cf->cf_user; - if(flask_enabled) - { - if(get_default_context(user_name, NULL, &cf->cf_user_context)) - error_e("NO CONTEXT for user \"%s\"", cf->cf_user_context); - retval = security_compute_av(cf->cf_user_context, cf->cf_file_context - , SECCLASS_FILE, FILE__ENTRYPOINT, &avd); - - if(retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) - { - syslog(LOG_ERR, "ENTRYPOINT FAILED for user \"%s\" " - "(CONTEXT %s) for file CONTEXT %s" - , cf->cf_user, cf->cf_user_context, cf->cf_file_context); - goto err; - } +#endif /* def SYSFCRONTAB */ + user_name = cf->cf_user; + if (flask_enabled) { + if (get_default_context(user_name, NULL, &cf->cf_user_context)) + error_e("NO CONTEXT for user \"%s\"", cf->cf_user_context); + retval = + security_compute_av(cf->cf_user_context, cf->cf_file_context, + SECCLASS_FILE, FILE__ENTRYPOINT, &avd); + + if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) { + syslog(LOG_ERR, "ENTRYPOINT FAILED for user \"%s\" " + "(CONTEXT %s) for file CONTEXT %s", cf->cf_user, + cf->cf_user_context, cf->cf_file_context); + goto err; + } } #endif @@ -544,237 +544,239 @@ read_file(const char *file_name, cf_t *cf, int is_system_startup) * a file which he won't understand the syntax, for example * a file using a depreciated format generated by an old fcrontab, * if the syntax has changed */ - if ( read_type(fileno(ff), &type, &size) != OK || type != S_HEADER_T || - read(fileno(ff), &bufi, size) < size || bufi != S_FILEVERSION ) { - error("File %s is not valid: ignored.", file_name); - error("This file may have been generated by an old version of fcron."); - error("In that case, you should try to use the converter given in the " - "source package, or install it again using fcrontab."); - goto err; - } - - if ( read_type(fileno(ff), &type, &size) != OK || type != S_USER_T ) { - error("Invalid binary fcrontab (no USER field)"); - goto err; + if (read_type(fileno(ff), &type, &size) != OK || type != S_HEADER_T || + read(fileno(ff), &bufi, size) < size || bufi != S_FILEVERSION) { + error("File %s is not valid: ignored.", file_name); + error("This file may have been generated by an old version of fcron."); + error("In that case, you should try to use the converter given in the " + "source package, or install it again using fcrontab."); + goto err; + } + + if (read_type(fileno(ff), &type, &size) != OK || type != S_USER_T) { + error("Invalid binary fcrontab (no USER field)"); + goto err; } /* get the owner's name */ /* we set cf->cf_user before for SE Linux, so we need to free it here */ Free_safe(cf->cf_user); - if ( read_strn(fileno(ff), &cf->cf_user, size) != OK ) { - error("Cannot read user's name : file ignored"); - goto err; + if (read_strn(fileno(ff), &cf->cf_user, size) != OK) { + error("Cannot read user's name : file ignored"); + goto err; + } + if (runas != rootuid) { + /* we use file owner's name for more security (see above) */ + /* free the value obtained by read_strn() (we need to read it anyway + * to set the file ptr to the next thing to read) */ + Free_safe(cf->cf_user); + cf->cf_user = runas_str; } - if ( runas != rootuid ) { - /* we use file owner's name for more security (see above) */ - /* free the value obtained by read_strn() (we need to read it anyway - * to set the file ptr to the next thing to read) */ - Free_safe(cf->cf_user); - cf->cf_user = runas_str; - } /* get the time & date of the saving */ /* a new file generated by fcrontab has t_save set to 0 */ - if ( read_type(fileno(ff), &type, &size) != OK || type != S_TIMEDATE_T - || read(fileno(ff), &t_save, size) < size ) { - error("could not get time and date of saving"); - goto err; + if (read_type(fileno(ff), &type, &size) != OK || type != S_TIMEDATE_T + || read(fileno(ff), &t_save, size) < size) { + error("could not get time and date of saving"); + goto err; } - - if ( cf->cf_env_list == NULL ) + + if (cf->cf_env_list == NULL) cf->cf_env_list = env_list_init(); Alloc(cl, cl_t); /* main loop : read env variables, and lines */ - while ( read_type(fileno(ff), &type, &size) == OK ) { - /* action is determined by the type of the field */ - switch ( type ) { + while (read_type(fileno(ff), &type, &size) == OK) { + /* action is determined by the type of the field */ + switch (type) { - case S_ENVVAR_T: - /* read a env variable and add it to the env var list */ + case S_ENVVAR_T: + /* read a env variable and add it to the env var list */ { char *envvar = NULL; /* Read_strn go to "err" on error */ Read_strn(envvar, size, "Error while reading env var"); - debug(" Env: \"%s\"", envvar ); + debug(" Env: \"%s\"", envvar); /* we do not allow USER or LOGNAME assignment. * this was already checked by fcrontab, but we check again * just in case... */ - if ( strcmp_until(envvar, "USER", '=') == 0 - || strcmp_until(envvar, "LOGNAME", '=') == 0 ) { - error("USER or LOGNAME assignement is not allowed: ignored."); + if (strcmp_until(envvar, "USER", '=') == 0 + || strcmp_until(envvar, "LOGNAME", '=') == 0) { + error + ("USER or LOGNAME assignement is not allowed: ignored."); } else { env_list_putenv(cf->cf_env_list, envvar, 1); } Free_safe(envvar); } - break; - - case S_TZDIFF_T: - /* time diff between local (real) and system hour */ - Read(bufi, size, "Error while reading tzdiff field"); - cf->cf_tzdiff = (signed char) bufi; - break; - - case S_TZ_T: - /* read the timezone (string) in which the line should run */ - Read_strn(cl->cl_tz, size, "Error while reading timezone field"); - break; - - case S_SHELL_T: - Read_strn(cl->cl_shell, size, "Error while reading shell field"); - break; - - case S_RUNAS_T: - Read_strn(cl->cl_runas, size, "Error while reading runas field"); - break; - - case S_MAILTO_T: - Read_strn(cl->cl_mailto, size, "Error while reading mailto field"); - break; - - case S_NEXTEXE_T: - Read(bufi, size, "Error while reading nextexe field"); - cl->cl_nextexe = (time_t) bufi; - break; - - case S_FIRST_T: - Read(bufi, size, "Error while reading first field"); - cl->cl_first = (time_t) bufi; + break; + + case S_TZDIFF_T: + /* time diff between local (real) and system hour */ + Read(bufi, size, "Error while reading tzdiff field"); + cf->cf_tzdiff = (signed char)bufi; + break; + + case S_TZ_T: + /* read the timezone (string) in which the line should run */ + Read_strn(cl->cl_tz, size, "Error while reading timezone field"); + break; + + case S_SHELL_T: + Read_strn(cl->cl_shell, size, "Error while reading shell field"); + break; + + case S_RUNAS_T: + Read_strn(cl->cl_runas, size, "Error while reading runas field"); + break; + + case S_MAILTO_T: + Read_strn(cl->cl_mailto, size, "Error while reading mailto field"); + break; + + case S_NEXTEXE_T: + Read(bufi, size, "Error while reading nextexe field"); + cl->cl_nextexe = (time_t) bufi; + break; + + case S_FIRST_T: + Read(bufi, size, "Error while reading first field"); + cl->cl_first = (time_t) bufi; has_read_cl_first = 1; - break; - - case S_OPTION_T: - if (size < OPTION_SIZE) - /* set the options not defined in the savefile to default */ - set_default_opt(cl->cl_option); - Read(cl->cl_option, size, "Error while reading option field"); - break; - - case S_NUMEXE_T: - Read(cl->cl_numexe, size, "Error while reading numexe field"); - break; - - case S_LAVG_T: - Read(cl->cl_lavg, size, "Error while reading lavg field"); - break; - - case S_UNTIL_T: - Read(bufi, size, "Error while reading until field"); - cl->cl_until = (time_t) bufi; - break; - - case S_NICE_T: - Read(cl->cl_nice, size, "Error while reading nice field"); - break; - - case S_RUNFREQ_T: - Read(bufi, size, "Error while reading runfreq field"); - cl->cl_runfreq = (unsigned short) bufi; - break; - - case S_REMAIN_T: - Read(bufi, size, "Error while reading remain field"); - cl->cl_remain = (unsigned short) bufi; - break; - - case S_TIMEFREQ_T: - Read(bufi, size, "Error while reading timefreq field"); - cl->cl_timefreq = (time_t) bufi; - break; - - case S_JITTER_T: - /* read the jitter (uchar) to use to set next execution time */ - Read(bufi, size, "Error while reading jitter field"); - cl->cl_jitter = (unsigned char) bufi; - break; - - case S_MINS_T: - Read(cl->cl_mins, size, "Error while reading mins field"); - break; - - case S_HRS_T: - Read(cl->cl_hrs, size, "Error while reading hrs field"); - break; - - case S_DAYS_T: - Read(cl->cl_days, size, "Error while reading days field"); - break; - - case S_MONS_T: - Read(cl->cl_mons, size, "Error while reading mons field"); - break; - - case S_DOW_T: - Read(cl->cl_dow, size, "Error while reading dow field"); - break; - - case S_ENDLINE_T: - if (is_freq(cl->cl_option) && ! has_read_cl_first) { + break; + + case S_OPTION_T: + if (size < OPTION_SIZE) + /* set the options not defined in the savefile to default */ + set_default_opt(cl->cl_option); + Read(cl->cl_option, size, "Error while reading option field"); + break; + + case S_NUMEXE_T: + Read(cl->cl_numexe, size, "Error while reading numexe field"); + break; + + case S_LAVG_T: + Read(cl->cl_lavg, size, "Error while reading lavg field"); + break; + + case S_UNTIL_T: + Read(bufi, size, "Error while reading until field"); + cl->cl_until = (time_t) bufi; + break; + + case S_NICE_T: + Read(cl->cl_nice, size, "Error while reading nice field"); + break; + + case S_RUNFREQ_T: + Read(bufi, size, "Error while reading runfreq field"); + cl->cl_runfreq = (unsigned short)bufi; + break; + + case S_REMAIN_T: + Read(bufi, size, "Error while reading remain field"); + cl->cl_remain = (unsigned short)bufi; + break; + + case S_TIMEFREQ_T: + Read(bufi, size, "Error while reading timefreq field"); + cl->cl_timefreq = (time_t) bufi; + break; + + case S_JITTER_T: + /* read the jitter (uchar) to use to set next execution time */ + Read(bufi, size, "Error while reading jitter field"); + cl->cl_jitter = (unsigned char)bufi; + break; + + case S_MINS_T: + Read(cl->cl_mins, size, "Error while reading mins field"); + break; + + case S_HRS_T: + Read(cl->cl_hrs, size, "Error while reading hrs field"); + break; + + case S_DAYS_T: + Read(cl->cl_days, size, "Error while reading days field"); + break; + + case S_MONS_T: + Read(cl->cl_mons, size, "Error while reading mons field"); + break; + + case S_DOW_T: + Read(cl->cl_dow, size, "Error while reading dow field"); + break; + + case S_ENDLINE_T: + if (is_freq(cl->cl_option) && !has_read_cl_first) { /* Up to fcron 3.0.X, cl_first/S_FIRST_T was not saved for all @-lines */ cl->cl_first = cl->cl_nextexe; } - if (add_line_to_file(cl, cf, runas, runas_str, t_save, is_system_startup) != 0) + if (add_line_to_file + (cl, cf, runas, runas_str, t_save, is_system_startup) != 0) free_line(cl); Alloc(cl, cl_t); - break; + break; - /* default case in "switch(type)" */ - default: - error("Error while loading %s : unknown field type %d (ignored)", - file_name, type); + /* default case in "switch(type)" */ + default: + error("Error while loading %s : unknown field type %d (ignored)", + file_name, type); free_line(cl); Alloc(cl, cl_t); - /* skip the data corresponding to the unknown field */ - { - /* we avoid using fseek(), as it seems not to work correctly - * on some systems when we use read() on the FILE stream */ - int i; - for (i = 0; i < size; i++) - if ( getc(ff) == EOF ) - goto err; - } - } + /* skip the data corresponding to the unknown field */ + { + /* we avoid using fseek(), as it seems not to work correctly + * on some systems when we use read() on the FILE stream */ + int i; + for (i = 0; i < size; i++) + if (getc(ff) == EOF) + goto err; + } + } } /* free last cl Alloc : unused */ Free_safe(cl); /* check for an error */ - if ( ferror(ff) != 0 ) - error("file %s is truncated : you should reinstall it with fcrontab", - file_name); + if (ferror(ff) != 0) + error("file %s is truncated : you should reinstall it with fcrontab", + file_name); fclose(ff); return OK; - err: - if ( ff != NULL) - fclose(ff); + err: + if (ff != NULL) + fclose(ff); - if ( cl != NULL && cl->cl_next == NULL ) { - /* line is not yet in the line list of the file : free it */ - Free_safe(cl->cl_shell); - Free_safe(cl->cl_runas); - Free_safe(cl->cl_mailto); - Free_safe(cl); + if (cl != NULL && cl->cl_next == NULL) { + /* line is not yet in the line list of the file : free it */ + Free_safe(cl->cl_shell); + Free_safe(cl->cl_runas); + Free_safe(cl->cl_mailto); + Free_safe(cl); } /* check if we have started to read the lines and env var */ - if ( cl != NULL ) { - /* insert the line in the file list in order to be able to free - * the memory using delete_file() */ - - cf->cf_next = file_base; - file_base = cf; - - delete_file(cf->cf_user); - + if (cl != NULL) { + /* insert the line in the file list in order to be able to free + * the memory using delete_file() */ + + cf->cf_next = file_base; + file_base = cf; + + delete_file(cf->cf_user); + } else { - Free_safe(cf->cf_user); + Free_safe(cf->cf_user); } return ERR; @@ -783,36 +785,37 @@ read_file(const char *file_name, cf_t *cf, int is_system_startup) int -add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, time_t t_save, int is_system_startup) +add_line_to_file(cl_t * cl, cf_t * cf, uid_t runas, char *runas_str, + time_t t_save, int is_system_startup) /* check if the line is valid, and if yes, add it to the file cf */ { time_t slept = now - t_save; - if ( cl->cl_shell == NULL || cl->cl_runas == NULL || - cl->cl_mailto == NULL ) { - error("Line is not valid (empty shell, runas or mailto field)" - " : ignored"); - return 1; + if (cl->cl_shell == NULL || cl->cl_runas == NULL || cl->cl_mailto == NULL) { + error("Line is not valid (empty shell, runas or mailto field)" + " : ignored"); + return 1; } /* set runas field if necessary (to improve security) */ if (runas != rootuid) { - if (strcmp(cl->cl_runas, runas_str) != 0) - warn("warning: runas(%s) is not owner (%s): overridden.", - cl->cl_runas, runas_str); - Set(cl->cl_runas, runas_str); + if (strcmp(cl->cl_runas, runas_str) != 0) + warn("warning: runas(%s) is not owner (%s): overridden.", + cl->cl_runas, runas_str); + Set(cl->cl_runas, runas_str); } - + /* we need that here because the user's name contained in the * struct cf_t may be required */ cl->cl_file = cf; /* check if the mailto field is valid */ - if ( cl->cl_mailto && (*(cl->cl_mailto) == '-' || - strcspn(cl->cl_mailto, " \t\n") != strlen(cl->cl_mailto) ) ) { - error("mailto field \'%s\' is not valid : set to owner %s.", cl->cl_mailto, - cl->cl_file->cf_user); - Set(cl->cl_mailto,cl->cl_file->cf_user); + if (cl->cl_mailto && (*(cl->cl_mailto) == '-' || + strcspn(cl->cl_mailto, + " \t\n") != strlen(cl->cl_mailto))) { + error("mailto field \'%s\' is not valid : set to owner %s.", + cl->cl_mailto, cl->cl_file->cf_user); + Set(cl->cl_mailto, cl->cl_file->cf_user); } /* job has been stopped during execution: insert it in lavg or serial queue @@ -820,24 +823,23 @@ add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, time_t t_save /* NOTE: runatreboot is prioritary over jobs that were still running * when fcron stops, because the former will get run quicker as they are not * put into the serial queue. runatreboot jobs will be handled later on. */ - if (cl->cl_numexe > 0 && ! is_runatreboot(cl->cl_option)) { - - cl->cl_numexe = 0; - if ( is_lavg(cl->cl_option) ) { - if ( ! is_strict(cl->cl_option) ) - add_lavg_job(cl, -1); - } - else if ( is_serial(cl->cl_option) - || is_serial_once(cl->cl_option) ) - add_serial_job(cl, -1); - else { - /* job has been stopped during execution : - * launch it again */ - warn("job %s did not finish : running it again.", - cl->cl_shell); - set_serial_once(cl->cl_option); - add_serial_job(cl, -1); - } + if (cl->cl_numexe > 0 && !is_runatreboot(cl->cl_option)) { + + cl->cl_numexe = 0; + if (is_lavg(cl->cl_option)) { + if (!is_strict(cl->cl_option)) + add_lavg_job(cl, -1); + } + else if (is_serial(cl->cl_option) + || is_serial_once(cl->cl_option)) + add_serial_job(cl, -1); + else { + /* job has been stopped during execution : + * launch it again */ + warn("job %s did not finish : running it again.", cl->cl_shell); + set_serial_once(cl->cl_option); + add_serial_job(cl, -1); + } } if (is_system_startup || is_volatile(cl->cl_option)) { @@ -850,16 +852,16 @@ add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, time_t t_save explain("job '%s' with runonce set has already run since last " "system startup: not re-scheduling.", cl->cl_shell); } - else if ( is_td(cl->cl_option) ) { - - /* set the time and date of the next execution */ - if ( is_system_startup && is_runatreboot(cl->cl_option) ) { + else if (is_td(cl->cl_option)) { + + /* set the time and date of the next execution */ + if (is_system_startup && is_runatreboot(cl->cl_option)) { - if ( is_notice_notrun(cl->cl_option) ) { + if (is_notice_notrun(cl->cl_option)) { - if ( cl->cl_runfreq == 1 ) { + if (cl->cl_runfreq == 1) { /* %-line */ - set_next_exe_notrun(cl, SYSDOWN_RUNATREBOOT); + set_next_exe_notrun(cl, SYSDOWN_RUNATREBOOT); } else { /* set next exe and mail user */ @@ -877,112 +879,113 @@ add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, time_t t_save insert_nextexe(cl); } - else if ( cl->cl_nextexe <= now ) { - if ( cl->cl_nextexe == 0 ) - /* the is a line from a new file */ - set_next_exe(cl, NO_GOTO, -1); - else if (cl->cl_runfreq == 1 && - is_notice_notrun(cl->cl_option)) - set_next_exe_notrun(cl, SYSDOWN); - else if ( is_bootrun(cl->cl_option) && t_save != 0 - && cl->cl_runfreq != 1) { - if ( cl->cl_remain > 0 && --cl->cl_remain > 0 ) { - debug(" cl_remain: %d", cl->cl_remain); - } - else { - /* run bootrun jobs */ - cl->cl_remain = cl->cl_runfreq; - debug(" boot-run %s", cl->cl_shell); - if ( ! is_lavg(cl->cl_option) ) { - set_serial_once(cl->cl_option); - add_serial_job(cl, -1); - } - else - add_lavg_job(cl, -1); - } - set_next_exe(cl, STD, -1); - } - else { - if ( is_notice_notrun(cl->cl_option) ) { + else if (cl->cl_nextexe <= now) { + if (cl->cl_nextexe == 0) + /* the is a line from a new file */ + set_next_exe(cl, NO_GOTO, -1); + else if (cl->cl_runfreq == 1 && is_notice_notrun(cl->cl_option)) + set_next_exe_notrun(cl, SYSDOWN); + else if (is_bootrun(cl->cl_option) && t_save != 0 + && cl->cl_runfreq != 1) { + if (cl->cl_remain > 0 && --cl->cl_remain > 0) { + debug(" cl_remain: %d", cl->cl_remain); + } + else { + /* run bootrun jobs */ + cl->cl_remain = cl->cl_runfreq; + debug(" boot-run %s", cl->cl_shell); + if (!is_lavg(cl->cl_option)) { + set_serial_once(cl->cl_option); + add_serial_job(cl, -1); + } + else + add_lavg_job(cl, -1); + } + set_next_exe(cl, STD, -1); + } + else { + if (is_notice_notrun(cl->cl_option)) { /* set next exe and mail user */ time_t since = cl->cl_nextexe; - set_next_exe(cl, NO_GOTO, -1); + set_next_exe(cl, NO_GOTO, -1); mail_notrun_time_t(cl, SYSDOWN, since); - } - else - set_next_exe(cl, NO_GOTO, -1); - } - } - else { - /* value of nextexe is valid : just insert line in queue */ - insert_nextexe(cl); + } + else + set_next_exe(cl, NO_GOTO, -1); + } + } + else { + /* value of nextexe is valid : just insert line in queue */ + insert_nextexe(cl); } - } else { /* is_td(cl->cl_option) */ - /* standard @-lines */ - if ( is_system_startup && is_runatreboot(cl->cl_option) ) { + } + else { /* is_td(cl->cl_option) */ + /* standard @-lines */ + if (is_system_startup && is_runatreboot(cl->cl_option)) { cl->cl_nextexe = now; } /* t_save == 0 means this is a new file, hence a new line */ - else if (t_save == 0 - || is_volatile(cl->cl_option) - || ( is_system_startup - && ( is_rebootreset(cl->cl_option) - || is_runonce(cl->cl_option) ) ) ) { - /* cl_first is always saved to disk for a volatile line */ - if ( cl->cl_first == LONG_MAX ) { + else if (t_save == 0 || is_volatile(cl->cl_option) + || (is_system_startup && (is_rebootreset(cl->cl_option) + || is_runonce(cl->cl_option)))) { + /* cl_first is always saved to disk for a volatile line */ + if (cl->cl_first == LONG_MAX) { cl->cl_nextexe = LONG_MAX; } else { cl->cl_nextexe = now + cl->cl_first; - if ( cl->cl_nextexe < now ) { + if (cl->cl_nextexe < now) { /* there was an integer overflow! */ - error("Error while setting next exe time for job %s: cl_nextexe" - " overflowed. now=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", - cl->cl_shell, now, cl->cl_timefreq, cl->cl_nextexe); - error("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); + error + ("Error while setting next exe time for job %s: cl_nextexe" + " overflowed. now=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", + cl->cl_shell, now, cl->cl_timefreq, cl->cl_nextexe); + error + ("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); cl->cl_nextexe = LONG_MAX; } } } else { - if ( cl->cl_nextexe != LONG_MAX ) { + if (cl->cl_nextexe != LONG_MAX) { cl->cl_nextexe += slept; - if ( cl->cl_nextexe < now ) { + if (cl->cl_nextexe < now) { /* there was an integer overflow! */ - error("Error while setting next exe time for job %s: cl_nextexe" - " overflowed. now=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", - cl->cl_shell, now, cl->cl_timefreq, cl->cl_nextexe); - error("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); + error + ("Error while setting next exe time for job %s: cl_nextexe" + " overflowed. now=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", + cl->cl_shell, now, cl->cl_timefreq, cl->cl_nextexe); + error + ("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); cl->cl_nextexe = LONG_MAX; } } } - - if ( cl->cl_timefreq < 10 ) { - error("Invalid timefreq for %s: set to 1 day", - cl->cl_shell); - cl->cl_timefreq = 3600*24; - } + + if (cl->cl_timefreq < 10) { + error("Invalid timefreq for %s: set to 1 day", cl->cl_shell); + cl->cl_timefreq = 3600 * 24; + } insert_nextexe(cl); - } - - if (debug_opt && ! (is_runonce(cl->cl_option) && is_hasrun(cl->cl_option)) ) { - struct tm *ftime; - ftime = localtime( &(cl->cl_nextexe) ); - debug(" cmd %s next exec %d/%d/%d wday:%d %02d:%02d:%02d" - " (system time)", - cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday, - (ftime->tm_year + 1900), ftime->tm_wday, - ftime->tm_hour, ftime->tm_min, ftime->tm_sec); - } + } + + if (debug_opt && !(is_runonce(cl->cl_option) && is_hasrun(cl->cl_option))) { + struct tm *ftime; + ftime = localtime(&(cl->cl_nextexe)); + debug(" cmd %s next exec %d/%d/%d wday:%d %02d:%02d:%02d" + " (system time)", + cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday, + (ftime->tm_year + 1900), ftime->tm_wday, + ftime->tm_hour, ftime->tm_min, ftime->tm_sec); + } /* add the current line to the list, and allocate a new line */ - if ( (cl->cl_id = next_id++) >= ULONG_MAX - 1) { + if ((cl->cl_id = next_id++) >= ULONG_MAX - 1) { warn("Line id reached %ld: cycling back to zero.", ULONG_MAX); - next_id = 0; + next_id = 0; } cl->cl_next = cf->cf_line_base; cf->cf_line_base = cl; @@ -1006,109 +1009,111 @@ delete_file(const char *user_name) lavg_t *l = NULL; file = file_base; - while ( file != NULL) { - if (strcmp(user_name, file->cf_user) != 0) { - prev_file = file; - file = file->cf_next; - continue; - } - - for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) - if ( e->e_line != NULL && - e->e_line->cl_file == file ) { - /* we set the e_line to NULL, as so we know in wait_chld() - * and wait_all() the corresponding file has been removed. - * Plus, we decrement serial_running and lavg_serial_running - * as we won't be able to do it at the end of the job */ - if ( ( is_serial(e->e_line->cl_option) || - is_serial_once(e->e_line->cl_option) ) && - ! is_lavg(e->e_line->cl_option) ) - serial_running--; - else if ( is_serial(e->e_line->cl_option) && - is_lavg(e->e_line->cl_option) ) - lavg_serial_running--; - e->e_line = NULL; - } - - /* free lavg queue entries */ - for (l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list)) - if ( l->l_line->cl_file == file ) { - debug("removing %s from lavg queue", l->l_line->cl_shell); - lavg_list_remove_cur(lavg_list); - } - - /* free serial queue entries */ - for ( i = 0; i < serial_array_size; i++) - if (serial_array[i] != NULL && serial_array[i]->cl_file == file ) { - if ( ! s_a ) { - s_a = alloc_safe(serial_array_size*sizeof(cl_t *), "serial queue"); + while (file != NULL) { + if (strcmp(user_name, file->cf_user) != 0) { + prev_file = file; + file = file->cf_next; + continue; + } + + for (e = exe_list_first(exe_list); e != NULL; + e = exe_list_next(exe_list)) + if (e->e_line != NULL && e->e_line->cl_file == file) { + /* we set the e_line to NULL, as so we know in wait_chld() + * and wait_all() the corresponding file has been removed. + * Plus, we decrement serial_running and lavg_serial_running + * as we won't be able to do it at the end of the job */ + if ((is_serial(e->e_line->cl_option) || + is_serial_once(e->e_line->cl_option)) && + !is_lavg(e->e_line->cl_option)) + serial_running--; + else if (is_serial(e->e_line->cl_option) && + is_lavg(e->e_line->cl_option)) + lavg_serial_running--; + e->e_line = NULL; + } + + /* free lavg queue entries */ + for (l = lavg_list_first(lavg_list); l != NULL; + l = lavg_list_next(lavg_list)) + if (l->l_line->cl_file == file) { + debug("removing %s from lavg queue", l->l_line->cl_shell); + lavg_list_remove_cur(lavg_list); + } + + /* free serial queue entries */ + for (i = 0; i < serial_array_size; i++) + if (serial_array[i] != NULL && serial_array[i]->cl_file == file) { + if (!s_a) { + s_a = + alloc_safe(serial_array_size * sizeof(cl_t *), + "serial queue"); } - debug("removing %s from serial queue", - serial_array[i]->cl_shell); - serial_num--; - serial_array[i]->cl_numexe--; - serial_array[i] = NULL; - } - /* remove from queue and move the rest of the jobs to get - * a queue in order without empty entries */ - if ( ! s_a ) - goto end_of_serial_recomputing; - - if ( (k = serial_array_index + serial_num) >= serial_array_size ) - k -= serial_array_size; - for ( i = k = 0; i < serial_array_size; i++) { - if ( serial_array_index + i < serial_array_size ) { - if ( (s_a[k] = serial_array[serial_array_index + i]) != NULL) - k++; - } - else - if( (s_a[k] = - serial_array[serial_array_index + i - serial_array_size]) - != NULL) - k++; - } - Free_safe(serial_array); - serial_array = s_a; - serial_array_index = 0; - - end_of_serial_recomputing: - - /* free lines */ - cur_line = file->cf_line_base; - while ( (line = cur_line) != NULL) { - cur_line = line->cl_next; - - /* remove from the main queue */ - prev_j = NULL; - for ( j = queue_base; j != NULL; j = j->j_next ) - if ( j->j_line == line ) { - if (prev_j != NULL) - prev_j->j_next = j->j_next; - else - queue_base = j->j_next; - Free_safe(j); - break; - } - else - prev_j = j; + debug("removing %s from serial queue", + serial_array[i]->cl_shell); + serial_num--; + serial_array[i]->cl_numexe--; + serial_array[i] = NULL; + } + /* remove from queue and move the rest of the jobs to get + * a queue in order without empty entries */ + if (!s_a) + goto end_of_serial_recomputing; + + if ((k = serial_array_index + serial_num) >= serial_array_size) + k -= serial_array_size; + for (i = k = 0; i < serial_array_size; i++) { + if (serial_array_index + i < serial_array_size) { + if ((s_a[k] = serial_array[serial_array_index + i]) != NULL) + k++; + } + else if ((s_a[k] = + serial_array[serial_array_index + i - serial_array_size]) + != NULL) + k++; + } + Free_safe(serial_array); + serial_array = s_a; + serial_array_index = 0; + + end_of_serial_recomputing: + + /* free lines */ + cur_line = file->cf_line_base; + while ((line = cur_line) != NULL) { + cur_line = line->cl_next; + + /* remove from the main queue */ + prev_j = NULL; + for (j = queue_base; j != NULL; j = j->j_next) + if (j->j_line == line) { + if (prev_j != NULL) + prev_j->j_next = j->j_next; + else + queue_base = j->j_next; + Free_safe(j); + break; + } + else + prev_j = j; /* free line itself */ free_line(line); - } - /* delete_file() MUST remove only the first occurrence : - * this is needed by synchronize_file() */ - break ; + } + /* delete_file() MUST remove only the first occurrence : + * this is needed by synchronize_file() */ + break; } if (file == NULL) - /* file not in the file list */ - return; - + /* file not in the file list */ + return; + /* remove file from file list */ if (prev_file == NULL) - file_base = file->cf_next; + file_base = file->cf_next; else - prev_file->cf_next = file->cf_next; + prev_file->cf_next = file->cf_next; /* free env variables */ env_list_destroy(file->cf_env_list); @@ -1121,7 +1126,7 @@ delete_file(const char *user_name) void -save_file(cf_t *arg_file) +save_file(cf_t * arg_file) /* Store the informations relatives to the executions * of tasks at a defined frequency of system's running time */ { @@ -1129,22 +1134,22 @@ save_file(cf_t *arg_file) cf_t *start_file = NULL; if (arg_file != NULL) - start_file = arg_file; + start_file = arg_file; else - start_file = file_base; - - + start_file = file_base; + + for (file = start_file; file; file = file->cf_next) { - debug("Saving %s...", file->cf_user); + debug("Saving %s...", file->cf_user); - /* save the file safely : save it to a temporary name, then rename() it */ - /* chown the file to root:root : this file should only be read and - * modified by fcron (not fcrontab) */ - save_file_safe(file, file->cf_user, "fcron", rootuid, rootgid, now); + /* save the file safely : save it to a temporary name, then rename() it */ + /* chown the file to root:root : this file should only be read and + * modified by fcron (not fcrontab) */ + save_file_safe(file, file->cf_user, "fcron", rootuid, rootgid, now); - if (arg_file != NULL) - /* we have to save only a single file */ - break ; + if (arg_file != NULL) + /* we have to save only a single file */ + break; } } diff --git a/conf.h b/conf.h index f4704a3..d19531e 100644 --- a/conf.h +++ b/conf.h @@ -31,4 +31,4 @@ extern void synchronize_dir(const char *dir_name, int is_system_startup); extern void delete_file(const char *user_name); extern void save_file(struct cf_t *file_name); -#endif /* __CONF_H__ */ +#endif /* __CONF_H__ */ diff --git a/convert-fcrontab.c b/convert-fcrontab.c index 8e9b148..0036c17 100644 --- a/convert-fcrontab.c +++ b/convert-fcrontab.c @@ -30,10 +30,10 @@ void info(void); void usage(void); void convert_file(char *file_name); -char *read_str(FILE *f, char *buf, int max); -void delete_file(cf_t *file); +char *read_str(FILE * f, char *buf, int max); +void delete_file(cf_t * file); -char *cdir = FCRONTABS; /* the dir where are stored users' fcrontabs */ +char *cdir = FCRONTABS; /* the dir where are stored users' fcrontabs */ /* needed by log part : */ char *prog_name = NULL; @@ -49,16 +49,15 @@ info(void) * version, license */ { fprintf(stderr, - "convert-fcrontab "VERSION_QUOTED "\n" - "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" - "This program is free software distributed WITHOUT ANY WARRANTY.\n" + "convert-fcrontab " VERSION_QUOTED "\n" + "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" + "This program is free software distributed WITHOUT ANY WARRANTY.\n" "See the GNU General Public License for more details.\n" - "\n" - "WARNING: this program is not supposed to be installed on the " - "system. It is only used at installation time to convert the " - "the binary fcrontabs in the old format (fcron < 1.1.0, which " - "was published in 2001) to the present one." - ); + "\n" + "WARNING: this program is not supposed to be installed on the " + "system. It is only used at installation time to convert the " + "the binary fcrontabs in the old format (fcron < 1.1.0, which " + "was published in 2001) to the present one."); exit(EXIT_OK); @@ -70,58 +69,57 @@ usage() /* print a help message about command line options and exit */ { fprintf(stderr, "\nconvert-fcrontab " VERSION_QUOTED "\n\n" - "convert-fcrontab -h\n" - "convert-fcrontab -V\n" - "convert-fcrontab user\n" - " Update the fcrontab of \"user\" to fit the new binary format.\n" - "\n" - "WARNING: this program is not supposed to be installed on the " - "system. It is only used at installation time to convert the " - "the binary fcrontabs in the old format (fcron < 1.1.0, which " - "was published in 2001) to the present one." - ); - + "convert-fcrontab -h\n" + "convert-fcrontab -V\n" + "convert-fcrontab user\n" + " Update the fcrontab of \"user\" to fit the new binary format.\n" + "\n" + "WARNING: this program is not supposed to be installed on the " + "system. It is only used at installation time to convert the " + "the binary fcrontabs in the old format (fcron < 1.1.0, which " + "was published in 2001) to the present one."); + exit(EXIT_ERR); } char * -read_str(FILE *f, char *buf, int max) +read_str(FILE * f, char *buf, int max) /* return a pointer to string read from file f * if it is non-zero length */ { int i; for (i = 0; i < max; i++) - if ( (buf[i] = fgetc(f)) == '\0') - break; - buf[max-1] = '\0'; + if ((buf[i] = fgetc(f)) == '\0') + break; + buf[max - 1] = '\0'; - if ( strlen(buf) == 0 ) - return NULL; + if (strlen(buf) == 0) + return NULL; else - return strdup2(buf); + return strdup2(buf); } void -delete_file(cf_t *file) +delete_file(cf_t * file) /* free a file if user_name is not null * otherwise free all files */ { cl_t *line = NULL; cl_t *cur_line = NULL; - + /* free lines */ cur_line = file->cf_line_base; - while ( (line = cur_line) != NULL) { - cur_line = line->cl_next; - Free_safe(line->cl_shell); - Free_safe(line->cl_mailto); - Free_safe(line->cl_runas); - Free_safe(line); + while ((line = cur_line) != NULL) { + cur_line = line->cl_next; + Free_safe(line->cl_shell); + Free_safe(line->cl_mailto); + Free_safe(line->cl_runas); + Free_safe(line); } /* free env variables */ @@ -151,59 +149,58 @@ convert_file(char *file_name) Alloc(file, cf_t); /* open file */ - if ( (f = fopen(file_name, "r")) == NULL ) - die_e("Could not read %s", file_name); + if ((f = fopen(file_name, "r")) == NULL) + die_e("Could not read %s", file_name); - if ( fstat(fileno(f), &file_stat) != 0 ) - die_e("Could not stat %s", file_name); + if (fstat(fileno(f), &file_stat) != 0) + die_e("Could not stat %s", file_name); bzero(buf, sizeof(buf)); - + if (fgets(buf, sizeof(buf), f) == NULL || - strncmp(buf, "fcrontab-017\n", - sizeof("fcrontab-017\n")) != 0) { - - error("File %s is not valid: ignored.", file_name); - error("Maybe this file has been generated by a too old version " - "of fcron ( <= 0.9.4), or is already in the new binary format."); - error("In this case, you should reinstall it using fcrontab" - " (but be aware that you may lose some data as the last " - "execution time and date as if you run a fcrontab -z -n)."); - exit(EXIT_ERR); - } + strncmp(buf, "fcrontab-017\n", sizeof("fcrontab-017\n")) != 0) { + + error("File %s is not valid: ignored.", file_name); + error("Maybe this file has been generated by a too old version " + "of fcron ( <= 0.9.4), or is already in the new binary format."); + error("In this case, you should reinstall it using fcrontab" + " (but be aware that you may lose some data as the last " + "execution time and date as if you run a fcrontab -z -n)."); + exit(EXIT_ERR); + } if ((file->cf_user = read_str(f, buf, sizeof(buf))) == NULL) - die_e("Cannot read user's name"); + die_e("Cannot read user's name"); - if ( fscanf(f, "%" ATTR_SIZE_TIMET "d", CAST_TIMET_PTR &t_save) != 1 ) - error("could not get time and date of saving"); + if (fscanf(f, "%" ATTR_SIZE_TIMET "d", CAST_TIMET_PTR & t_save) != 1) + error("could not get time and date of saving"); /* read env variables */ - while( (env = read_str(f, buf, sizeof(buf))) != NULL ) { + while ((env = read_str(f, buf, sizeof(buf))) != NULL) { env_list_putenv(file->cf_env_list, env, 1); Free_safe(env); } /* read lines */ Alloc(line, cl_t); - while ( fread(line, sizeof(cl_t), 1, f) == 1 ) { - - if ((line->cl_shell = read_str(f, buf, sizeof(buf))) == NULL) { - error("Line is not valid (empty shell command) : ignored"); - continue; - } - if ((line->cl_runas = read_str(f, buf, sizeof(buf))) == NULL) { - error("Line is not valid (empty runas field) : ignored"); - continue; - } - if ((line->cl_mailto = read_str(f, buf, sizeof(buf))) == NULL) { - error("Line is not valid (empty mailto field) : ignored"); - continue; - } - - line->cl_next = file->cf_line_base; - file->cf_line_base = line; - Alloc(line, cl_t); + while (fread(line, sizeof(cl_t), 1, f) == 1) { + + if ((line->cl_shell = read_str(f, buf, sizeof(buf))) == NULL) { + error("Line is not valid (empty shell command) : ignored"); + continue; + } + if ((line->cl_runas = read_str(f, buf, sizeof(buf))) == NULL) { + error("Line is not valid (empty runas field) : ignored"); + continue; + } + if ((line->cl_mailto = read_str(f, buf, sizeof(buf))) == NULL) { + error("Line is not valid (empty mailto field) : ignored"); + continue; + } + + line->cl_next = file->cf_line_base; + file->cf_line_base = line; + Alloc(line, cl_t); } @@ -214,14 +211,14 @@ convert_file(char *file_name) /* open a temp file in write mode and truncate it */ strcpy(buf, "tmp_"); strncat(buf, file_name, sizeof(buf) - sizeof("tmp_") - 1); - buf[sizeof(buf)-1]='\0'; + buf[sizeof(buf) - 1] = '\0'; /* everything's ok : we can override the src file safely */ - if ( rename(buf, file_name) != 0 ) - error_e("Could not rename %s to %s", buf, file_name); + if (rename(buf, file_name) != 0) + error_e("Could not rename %s to %s", buf, file_name); save_file_safe(file, file_name, "convert-fcrontab", file_stat.st_uid, - file_stat.st_gid, t_save); + file_stat.st_gid, t_save); delete_file(file); } @@ -237,46 +234,50 @@ main(int argc, char *argv[]) rootuid = get_user_uid_safe(ROOTNAME); rootgid = get_group_gid_safe(ROOTGROUP); - if ( strrchr(argv[0], '/') == NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0], '/') + 1; + if (strrchr(argv[0], '/') == NULL) + prog_name = argv[0]; + else + prog_name = strrchr(argv[0], '/') + 1; /* constants and variables defined by command line */ - while(1) { - c = getopt(argc, argv, "hV"); - if (c == EOF) break; - switch (c) { + while (1) { + c = getopt(argc, argv, "hV"); + if (c == EOF) + break; + switch (c) { - case 'V': - info(); break; + case 'V': + info(); + break; - case 'h': - usage(); break; + case 'h': + usage(); + break; - case ':': - fprintf(stderr, "(setopt) Missing parameter"); - usage(); + case ':': + fprintf(stderr, "(setopt) Missing parameter"); + usage(); - case '?': - usage(); + case '?': + usage(); - default: - fprintf(stderr, "(setopt) Warning: getopt returned %c", c); - } + default: + fprintf(stderr, "(setopt) Warning: getopt returned %c", c); + } } if (optind >= argc || argc != 2) - usage(); + usage(); user_to_update = strdup2(argv[optind]); if (chdir(cdir) != 0) - die_e("Could not change dir to " FCRONTABS); + die_e("Could not change dir to " FCRONTABS); convert_file(user_to_update); exit(EXIT_OK); } - diff --git a/convert-fcrontab.h b/convert-fcrontab.h index 6881057..e758fb2 100644 --- a/convert-fcrontab.h +++ b/convert-fcrontab.h @@ -33,4 +33,4 @@ extern uid_t rootuid; extern gid_t rootgid; -#endif /* __CONVERT_FCRONTAB_H__ */ +#endif /* __CONVERT_FCRONTAB_H__ */ diff --git a/database.c b/database.c index af8117f..4c8a37d 100644 --- a/database.c +++ b/database.c @@ -32,13 +32,13 @@ int is_leap_year(int year); int get_nb_mdays(int year, int mon); void set_wday(struct tm *date); time_t mktime_no_dst(struct tm *t); -void goto_beginning_next_period_periodical(cl_t *line, struct tm *ftime); -void move_time_to(int where, cl_t *line, struct tm *ftime); -#define BEGIN_NEXT_PERIOD 11 /* move_time_to()'s where possible value */ -#define END_OF_INTERVAL 12 /* move_time_to()'s where possible value */ +void goto_beginning_next_period_periodical(cl_t * line, struct tm *ftime); +void move_time_to(int where, cl_t * line, struct tm *ftime); +#define BEGIN_NEXT_PERIOD 11 /* move_time_to()'s where possible value */ +#define END_OF_INTERVAL 12 /* move_time_to()'s where possible value */ void run_serial_job(void); -void run_lavg_job(lavg_t *l); -void run_queue_job(cl_t *line); +void run_lavg_job(lavg_t * l); +void run_queue_job(cl_t * line); void test_jobs(void) @@ -50,49 +50,50 @@ test_jobs(void) debug("Looking for jobs to execute ..."); /* // */ - while ( (j=queue_base) && j->j_line->cl_nextexe <= now ) { + while ((j = queue_base) && j->j_line->cl_nextexe <= now) { - if ( j->j_line->cl_remain > 0 && --(j->j_line->cl_remain) > 0) { - debug(" cl_remain: %d", j->j_line->cl_remain); - } + if (j->j_line->cl_remain > 0 && --(j->j_line->cl_remain) > 0) { + debug(" cl_remain: %d", j->j_line->cl_remain); + } else { j->j_line->cl_remain = j->j_line->cl_runfreq; - if ( is_lavg(j->j_line->cl_option) ) + if (is_lavg(j->j_line->cl_option)) add_lavg_job(j->j_line, -1); - else if ( is_serial(j->j_line->cl_option) ) + else if (is_serial(j->j_line->cl_option)) add_serial_job(j->j_line, -1); else run_normal_job(j->j_line, -1); set_hasrun(j->j_line->cl_option); } - - if ( is_runonce(j->j_line->cl_option) && is_hasrun(j->j_line->cl_option) ) { - explain("Line %s has runonce set: not re-scheduling it.", j->j_line->cl_shell); + + if (is_runonce(j->j_line->cl_option) && is_hasrun(j->j_line->cl_option)) { + explain("Line %s has runonce set: not re-scheduling it.", + j->j_line->cl_shell); job_queue_remove(j->j_line); } - else { - set_next_exe(j->j_line, STD, -1); - } + else { + set_next_exe(j->j_line, STD, -1); + } } } int -switch_timezone(const char *orig_tz, const char* dest_tz) +switch_timezone(const char *orig_tz, const char *dest_tz) /* check if we have already switched to dest_tz timezone, otherwise do it */ /* If dest_tz is NULL, this function does nothing */ /* Returns 1 if this function has switched the timezone, 0 otherwise */ { char *current_tz = getenv("TZ"); - if ( dest_tz != NULL && - (current_tz == NULL || strcmp(dest_tz, current_tz) != 0)) { + if (dest_tz != NULL && + (current_tz == NULL || strcmp(dest_tz, current_tz) != 0)) { my_setenv_overwrite("TZ", dest_tz); - return 1; + return 1; } else return 0; @@ -103,7 +104,7 @@ switch_back_timezone(const char *orig_tz) /* if orig_tz is NULL, unsets TZ * otherwise, sets TZ to orig_tz */ { - if ( orig_tz == NULL) { + if (orig_tz == NULL) { my_unsetenv("TZ"); } else { @@ -134,34 +135,34 @@ mktime_no_dst(struct tm *t) ti1 = mktime(&t2); /* */ debug("after mktime() : %d:%d isdst:%d ti:%ld\n", - t2.tm_hour, t2.tm_min, t2.tm_isdst, ti1); + t2.tm_hour, t2.tm_min, t2.tm_isdst, ti1); /* */ /* check if there have been a dst change adjustment */ - if ( t->tm_isdst != t2.tm_isdst ) { - - time_t ti2; - struct tm t3; - - /* recompute the time_t field with the other isdst value - * it works well, unless in a special case, hence the test - * below */ - t3 = *t; - t3.tm_isdst = t2.tm_isdst; - ti2 = mktime(&t3); - /* */ - debug("after dst fix 1 : %d:%d isdst:%d ti:%ld\n", - t3.tm_hour, t3.tm_min, t3.tm_isdst, ti2); - /* */ - - /* if t1 is in the "gap" of a dst change (for instance, - * if t1 is 2:30 while at 2:00, it is 3:00 due to the dst change, - * ie. 2:30 is never reached), the ti2 may be incorrect : - * we check that it is correct before using it : */ - if ( t3.tm_hour == t->tm_hour || ti1 < ti2 ) { - t2 = t3; - ti1 = ti2; - } + if (t->tm_isdst != t2.tm_isdst) { + + time_t ti2; + struct tm t3; + + /* recompute the time_t field with the other isdst value + * it works well, unless in a special case, hence the test + * below */ + t3 = *t; + t3.tm_isdst = t2.tm_isdst; + ti2 = mktime(&t3); + /* */ + debug("after dst fix 1 : %d:%d isdst:%d ti:%ld\n", + t3.tm_hour, t3.tm_min, t3.tm_isdst, ti2); + /* */ + + /* if t1 is in the "gap" of a dst change (for instance, + * if t1 is 2:30 while at 2:00, it is 3:00 due to the dst change, + * ie. 2:30 is never reached), the ti2 may be incorrect : + * we check that it is correct before using it : */ + if (t3.tm_hour == t->tm_hour || ti1 < ti2) { + t2 = t3; + ti1 = ti2; + } } @@ -171,31 +172,31 @@ mktime_no_dst(struct tm *t) void -run_normal_job(cl_t *line, int info_fd) +run_normal_job(cl_t * line, int info_fd) /* run a job, and write "log" on info_fd if positive */ { - if (line->cl_numexe <= 0 || - (is_exe_sev(line->cl_option) && line->cl_numexe < UCHAR_MAX)) { - line->cl_numexe += 1; - run_queue_job(line); - send_msg_fd(info_fd, "Job %s started.", line->cl_shell); + if (line->cl_numexe <= 0 || + (is_exe_sev(line->cl_option) && line->cl_numexe < UCHAR_MAX)) { + line->cl_numexe += 1; + run_queue_job(line); + send_msg_fd(info_fd, "Job %s started.", line->cl_shell); } else { - warn_fd(info_fd, " process already running: %s's %s", - line->cl_file->cf_user, line->cl_shell); - } + warn_fd(info_fd, " process already running: %s's %s", + line->cl_file->cf_user, line->cl_shell); + } } void -run_lavg_job(lavg_t *l) +run_lavg_job(lavg_t * l) { run_queue_job(l->l_line); - if ( is_serial(l->l_line->cl_option) ) - lavg_serial_running++; + if (is_serial(l->l_line->cl_option)) + lavg_serial_running++; } @@ -209,22 +210,22 @@ run_serial_job(void) /* // */ debug("num: %d running:%d index:%d", serial_num, serial_running, - serial_array_index); - if ( serial_num != 0 ) { - run_queue_job(serial_array[serial_array_index]); - serial_array[serial_array_index] = NULL; - - serial_running++; - if ( ++serial_array_index >= serial_array_size ) - serial_array_index -= serial_array_size; - serial_num--; - + serial_array_index); + if (serial_num != 0) { + run_queue_job(serial_array[serial_array_index]); + serial_array[serial_array_index] = NULL; + + serial_running++; + if (++serial_array_index >= serial_array_size) + serial_array_index -= serial_array_size; + serial_num--; + } } - + void -run_queue_job(cl_t *line) +run_queue_job(cl_t * line) /* run a job */ { @@ -237,16 +238,16 @@ run_queue_job(cl_t *line) e.e_line = line; /* run the job */ - if ( run_job(&e) == OK ) { - /* append job to the list of executed job */ - exe_list_add(exe_list, &e); - line->cl_file->cf_running += 1; + if (run_job(&e) == OK) { + /* append job to the list of executed job */ + exe_list_add(exe_list, &e); + line->cl_file->cf_running += 1; } } job_t * -job_queue_remove(cl_t *line) +job_queue_remove(cl_t * line) /* remove a job from the queue list * returns a pointer to the previous entry, * or NULL if the line either wasn't in the queue or was the first entry */ @@ -258,8 +259,8 @@ job_queue_remove(cl_t *line) return NULL; /* find the job in the list */ - for (j = queue_base; j != NULL ; jprev = j, j = j->j_next) { - if ( j->j_line == line ) { + for (j = queue_base; j != NULL; jprev = j, j = j->j_next) { + if (j->j_line == line) { /* remove it from the list */ if (jprev != NULL) { jprev->j_next = j->j_next; @@ -278,7 +279,7 @@ job_queue_remove(cl_t *line) } void -insert_nextexe(cl_t *line) +insert_nextexe(cl_t * line) /* insert a job at the right position in the job queue */ { struct job_t *newjob = NULL; @@ -290,18 +291,18 @@ insert_nextexe(cl_t *line) newjob->j_next = NULL; if (queue_base == NULL) { - /* no job in queue */ - queue_base = newjob; + /* no job in queue */ + queue_base = newjob; return; } jprev = job_queue_remove(line); - j = (jprev)? jprev : queue_base; + j = (jprev) ? jprev : queue_base; /* check if we should start from queue_base or from jprev * (in some cases, e.g. fcrontab has just been edited, the line should * be moved *forward* in the queue) */ - if (jprev == NULL || line->cl_nextexe < jprev->j_line->cl_nextexe ) { + if (jprev == NULL || line->cl_nextexe < jprev->j_line->cl_nextexe) { j = queue_base; } @@ -322,68 +323,71 @@ insert_nextexe(cl_t *line) } void -add_serial_job(cl_t *line, int info_fd) +add_serial_job(cl_t * line, int info_fd) /* add the next queued job in serial queue */ { short int i; /* check if the line is already in the serial queue * (we consider serial jobs currently running as in the queue) */ - if ( (is_serial_sev(line->cl_option) && line->cl_numexe >= UCHAR_MAX) || - (! is_serial_sev(line->cl_option) && line->cl_numexe > 0) ) { - send_msg_fd_debug(info_fd, "already in serial queue %s", line->cl_shell); - return; + if ((is_serial_sev(line->cl_option) && line->cl_numexe >= UCHAR_MAX) || + (!is_serial_sev(line->cl_option) && line->cl_numexe > 0)) { + send_msg_fd_debug(info_fd, "already in serial queue %s", + line->cl_shell); + return; } send_msg_fd_debug(info_fd, "inserting in serial queue %s", line->cl_shell); - if ( serial_num >= serial_array_size ) { - if ( serial_num >= serial_queue_max ) { - error_fd(info_fd, "Could not add job : serial queue is full " - "(%d jobs). Consider using option serialonce, fcron's " - "option -m and/or -q : %s",serial_queue_max,line->cl_shell); - if ( is_notice_notrun(line->cl_option) ) - mail_notrun(line, QUEUE_FULL, NULL); - return; - } - else { - cl_t **ptr = NULL; - short int old_size = serial_array_size; - - debug("Resizing serial_array"); - serial_array_size = (serial_array_size + SERIAL_GROW_SIZE); - - ptr = alloc_safe(serial_array_size*sizeof(cl_t *), "serial_array"); - - /* copy lines in order to have the first line at the index 0 */ - memcpy(ptr + serial_array_index, serial_array, - (sizeof(cl_t*) * (old_size - serial_array_index)) ); - memcpy(ptr, serial_array + (old_size - serial_array_index), - (sizeof(cl_t*) * serial_array_index)); - serial_array_index = 0; - Free_safe(serial_array); - serial_array = ptr; - } + if (serial_num >= serial_array_size) { + if (serial_num >= serial_queue_max) { + error_fd(info_fd, "Could not add job : serial queue is full " + "(%d jobs). Consider using option serialonce, fcron's " + "option -m and/or -q : %s", serial_queue_max, + line->cl_shell); + if (is_notice_notrun(line->cl_option)) + mail_notrun(line, QUEUE_FULL, NULL); + return; + } + else { + cl_t **ptr = NULL; + short int old_size = serial_array_size; + + debug("Resizing serial_array"); + serial_array_size = (serial_array_size + SERIAL_GROW_SIZE); + + ptr = + alloc_safe(serial_array_size * sizeof(cl_t *), "serial_array"); + + /* copy lines in order to have the first line at the index 0 */ + memcpy(ptr + serial_array_index, serial_array, + (sizeof(cl_t *) * (old_size - serial_array_index))); + memcpy(ptr, serial_array + (old_size - serial_array_index), + (sizeof(cl_t *) * serial_array_index)); + serial_array_index = 0; + Free_safe(serial_array); + serial_array = ptr; + } } - if ( (i = serial_array_index + serial_num) >= serial_array_size ) - i -= serial_array_size; - + if ((i = serial_array_index + serial_num) >= serial_array_size) + i -= serial_array_size; + serial_array[i] = line; serial_num++; line->cl_numexe += 1; send_msg_fd_debug(info_fd, "serial num: %d size:%d index:%d curline:%d " - "running:%d (%s)", serial_num, serial_array_size, - serial_array_index, i, serial_running, line->cl_shell); + "running:%d (%s)", serial_num, serial_array_size, + serial_array_index, i, serial_running, line->cl_shell); } void -add_lavg_job(cl_t *line, int info_fd) +add_lavg_job(cl_t * line, int info_fd) /* add the next queued job in lavg queue */ /* WARNING : must be run before a set_next_exe() to get the strict option * working correctly */ @@ -392,69 +396,69 @@ add_lavg_job(cl_t *line, int info_fd) /* check if the line is already in the lavg queue * (we consider serial jobs currently running as in the queue) */ - if ( (is_lavg_sev(line->cl_option) && line->cl_numexe >= UCHAR_MAX) || - (! is_lavg_sev(line->cl_option) && line->cl_numexe > 0 ) ) { - send_msg_fd_debug(info_fd, "already in lavg queue %s", line->cl_shell); - return; + if ((is_lavg_sev(line->cl_option) && line->cl_numexe >= UCHAR_MAX) || + (!is_lavg_sev(line->cl_option) && line->cl_numexe > 0)) { + send_msg_fd_debug(info_fd, "already in lavg queue %s", line->cl_shell); + return; } /* // */ send_msg_fd_debug(info_fd, "inserting in lavg queue %s", line->cl_shell); /* // */ - + /* append job to the list of lavg job */ lavg_entry = lavg_list_add_line(lavg_list, line); - if ( lavg_entry == NULL ) { - error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)." - " Consider using options lavgonce, until, strict and/or " - "fcron's option -q.", lavg_list->max_entries, line->cl_shell); - if ( is_notice_notrun(line->cl_option) ) - mail_notrun(line, QUEUE_FULL, NULL); - return; + if (lavg_entry == NULL) { + error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)." + " Consider using options lavgonce, until, strict and/or " + "fcron's option -q.", lavg_list->max_entries, line->cl_shell); + if (is_notice_notrun(line->cl_option)) + mail_notrun(line, QUEUE_FULL, NULL); + return; } line->cl_numexe += 1; set_run_if_late(line->cl_option); - if ( is_strict(line->cl_option) && line->cl_runfreq == 1) { - struct tm *ft; - struct tm ftime; - time_t begin_of_cur_int, end_of_cur_int = 0; - int tz_changed = 0; - - /* Switch to another timezone if necessary. */ - /* If line should be scheduled in a different time zone - * (ie. cl_tz != NULL), - * switch to that timezone now, do the calculations, - * and switch back to the local timezone at the end - * of the function. */ - tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz); - - /* handle timezone differences */ - begin_of_cur_int = line->cl_nextexe - (line->cl_file->cf_tzdiff*3600); - - ft = localtime( &begin_of_cur_int ); - - /* localtime() function seems to return every time the same pointer : - it resets our previous changes, so we need to prevent it - ( localtime() is used in the debug() function) */ - memcpy(&ftime, ft, sizeof(struct tm)); - - move_time_to(END_OF_INTERVAL, line, &ftime); - - end_of_cur_int = mktime_no_dst(&ftime) + (line->cl_file->cf_tzdiff * 3600); - - if ((line->cl_until > 0) && (line->cl_until + now < end_of_cur_int)) - lavg_entry->l_until = line->cl_until + now; - else { - lavg_entry->l_until = end_of_cur_int; - clear_run_if_late(line->cl_option); - } - - if ( tz_changed > 0 ) - switch_back_timezone(orig_tz_envvar); + if (is_strict(line->cl_option) && line->cl_runfreq == 1) { + struct tm *ft; + struct tm ftime; + time_t begin_of_cur_int, end_of_cur_int = 0; + int tz_changed = 0; + + /* Switch to another timezone if necessary. */ + /* If line should be scheduled in a different time zone + * (ie. cl_tz != NULL), + * switch to that timezone now, do the calculations, + * and switch back to the local timezone at the end + * of the function. */ + tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz); + + /* handle timezone differences */ + begin_of_cur_int = line->cl_nextexe - (line->cl_file->cf_tzdiff * 3600); + + ft = localtime(&begin_of_cur_int); + + /* localtime() function seems to return every time the same pointer : + * it resets our previous changes, so we need to prevent it + * ( localtime() is used in the debug() function) */ + memcpy(&ftime, ft, sizeof(struct tm)); + + move_time_to(END_OF_INTERVAL, line, &ftime); + + end_of_cur_int = + mktime_no_dst(&ftime) + (line->cl_file->cf_tzdiff * 3600); + + if ((line->cl_until > 0) && (line->cl_until + now < end_of_cur_int)) + lavg_entry->l_until = line->cl_until + now; + else { + lavg_entry->l_until = end_of_cur_int; + clear_run_if_late(line->cl_option); + } + + if (tz_changed > 0) + switch_back_timezone(orig_tz_envvar); } else - lavg_entry->l_until = - (line->cl_until > 0) ? now + line->cl_until : 0; + lavg_entry->l_until = (line->cl_until > 0) ? now + line->cl_until : 0; } @@ -471,42 +475,43 @@ wait_chld(void) /* debug("wait_chld"); */ /* // */ - while ( (pid = wait3(NULL, WNOHANG, NULL)) > 0 ) { + while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) { - for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) { + for (e = exe_list_first(exe_list); e != NULL; + e = exe_list_next(exe_list)) { - if (pid == e->e_ctrl_pid) { - if ( e->e_line == NULL ) { - /* the corresponding file has been removed from memory */ - debug("job finished: pid %d", pid); - } - else { - - line = e->e_line; + if (pid == e->e_ctrl_pid) { + if (e->e_line == NULL) { + /* the corresponding file has been removed from memory */ + debug("job finished: pid %d", pid); + } + else { + + line = e->e_line; /* debug("job finished: %s", line->cl_shell); */ - line->cl_numexe -= 1; - line->cl_file->cf_running -= 1; - - if ( is_serial_once(line->cl_option) ) { - clear_serial_once(line->cl_option); - if ( --serial_running < serial_max_running ) - run_serial_job(); - } - else if ( is_serial(line->cl_option) - && ! is_lavg(line->cl_option) ) { - if (--serial_running < serial_max_running) - run_serial_job(); - } - else if ( is_lavg(line->cl_option) && - is_serial(line->cl_option) ) - lavg_serial_running--; - } - - exe_list_remove_cur(exe_list); - exe_list_end_iteration(exe_list); - break; - } - } + line->cl_numexe -= 1; + line->cl_file->cf_running -= 1; + + if (is_serial_once(line->cl_option)) { + clear_serial_once(line->cl_option); + if (--serial_running < serial_max_running) + run_serial_job(); + } + else if (is_serial(line->cl_option) + && !is_lavg(line->cl_option)) { + if (--serial_running < serial_max_running) + run_serial_job(); + } + else if (is_lavg(line->cl_option) + && is_serial(line->cl_option)) + lavg_serial_running--; + } + + exe_list_remove_cur(exe_list); + exe_list_end_iteration(exe_list); + break; + } + } } @@ -519,34 +524,35 @@ wait_all(int *counter) { int pid; exe_t *e = NULL; - + debug("Waiting for all jobs"); - - while ( (*counter > 0) && (pid = wait3(NULL, 0, NULL)) > 0 ) { - for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) { - if (pid == e->e_ctrl_pid) { - if ( e->e_line == NULL ) { - /* the corresponding file has been removed from memory */ - debug("job finished: pid %d", pid); - } - else { - - debug("job finished: %s", e->e_line->cl_shell); - e->e_line->cl_numexe -= 1; - e->e_line->cl_file->cf_running -= 1; - - if ( is_serial_once(e->e_line->cl_option) ) - clear_serial_once(e->e_line->cl_option); - - } - - exe_list_remove_cur(exe_list); - exe_list_end_iteration(exe_list); - break; - } - } - } - + + while ((*counter > 0) && (pid = wait3(NULL, 0, NULL)) > 0) { + for (e = exe_list_first(exe_list); e != NULL; + e = exe_list_next(exe_list)) { + if (pid == e->e_ctrl_pid) { + if (e->e_line == NULL) { + /* the corresponding file has been removed from memory */ + debug("job finished: pid %d", pid); + } + else { + + debug("job finished: %s", e->e_line->cl_shell); + e->e_line->cl_numexe -= 1; + e->e_line->cl_file->cf_running -= 1; + + if (is_serial_once(e->e_line->cl_option)) + clear_serial_once(e->e_line->cl_option); + + } + + exe_list_remove_cur(exe_list); + exe_list_end_iteration(exe_list); + break; + } + } + } + } @@ -554,8 +560,7 @@ int is_leap_year(int year) /* return 1 if it's a leap year otherwise return 0 */ { - return ( (year % 4 == 0) && - ( (year % 100 != 0) || (year % 400 == 0) ) ); + return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))); } @@ -564,21 +569,21 @@ int get_nb_mdays(int year, int mon) /* return the number of days in a given month of a given year */ { - if (mon == 1) { /* is February ? */ - if ( is_leap_year(year) ) - return 29; - else - return 28; + if (mon == 1) { /* is February ? */ + if (is_leap_year(year)) + return 29; + else + return 28; } else if (mon <= 6) - if (mon % 2 == 0) - return 31; - else - return 30; + if (mon % 2 == 0) + return 31; + else + return 30; else if (mon % 2 == 0) - return 30; - else - return 31; + return 30; + else + return 31; } @@ -593,29 +598,29 @@ set_wday(struct tm *date) int i; /* we add the number of days of each previous years */ - for (i = (date->tm_year - 1); i >= 100 ; i--) - nod += ( is_leap_year(i+1900) ) ? 366 : 365; + for (i = (date->tm_year - 1); i >= 100; i--) + nod += (is_leap_year(i + 1900)) ? 366 : 365; /* and month */ - for (i = (date->tm_mon - 1); i >= 0; i--) - nod += get_nb_mdays( (date->tm_year + 1900), i); + for (i = (date->tm_mon - 1); i >= 0; i--) + nod += get_nb_mdays((date->tm_year + 1900), i); /* then we add the number of days passed in the current month */ nod += (date->tm_mday - 1); /* (mday is set from 1 to 31) */ date->tm_wday = (nod % 7) + 6; - if ( date->tm_wday >= 7 ) - date->tm_wday -= 7; + if (date->tm_wday >= 7) + date->tm_wday -= 7; - debug(" dow of %d-%d-%d : %d", (date->tm_mon + 1), date->tm_mday, - ( date->tm_year + 1900 ), date->tm_wday); + debug(" dow of %d-%d-%d : %d", (date->tm_mon + 1), date->tm_mday, + (date->tm_year + 1900), date->tm_wday); -} +} void -goto_beginning_next_period_periodical(cl_t *line, struct tm *ftime) +goto_beginning_next_period_periodical(cl_t * line, struct tm *ftime) /* From ftime, search the first/nearest time and date of the line's next * period of execution. * @@ -632,10 +637,10 @@ goto_beginning_next_period_periodical(cl_t *line, struct tm *ftime) int max = 0; /* sanity check */ - if ( ! is_freq_periodically(line->cl_option) ) - die("goto_beginning_next_period() called with a non periodical line"); + if (!is_freq_periodically(line->cl_option)) + die("goto_beginning_next_period() called with a non periodical line"); + - /* number of days in ftime's month */ max = get_nb_mdays(ftime->tm_year, ftime->tm_mon); @@ -644,81 +649,88 @@ goto_beginning_next_period_periodical(cl_t *line, struct tm *ftime) if (is_freq_mid(line->cl_option)) { - if (is_freq_mins(line->cl_option)) - /* nothing to do : return */ - return; - else if (is_freq_hrs(line->cl_option)) { - if (ftime->tm_min >= 30) - ftime->tm_hour++; - ftime->tm_min = 30; - } else { - ftime->tm_min = 0; - if (is_freq_days(line->cl_option)) { - if (ftime->tm_hour >= 12) - ftime->tm_mday++; - ftime->tm_hour = 12; - } else { - ftime->tm_hour = 0; - if (is_freq_dow(line->cl_option)) { - int to_add = (ftime->tm_wday >= 4) ? 11-ftime->tm_wday: - 4 - ftime->tm_wday; - if (ftime->tm_mday + to_add > max) { - ftime->tm_mon++; - ftime->tm_mday = ftime->tm_mday + to_add - max; - } else - ftime->tm_mday += to_add; - } else { - if (is_freq_mons(line->cl_option)) { - if (ftime->tm_mday >= 15) - ftime->tm_mon++; - ftime->tm_mday = 15; - } - else { - /* weird : we have the bit freq_mid set, but - * none of freq_{mins|hour|days|dow|mons} is set : - * we do nothing but increase tm_min by 1 - * so as we don't return a time in the past */ - ftime->tm_min++; - warn("Line %s doesn't seem correct: consider " - "reinstalling the corresponding fcrontab"); - } - } - } - } - - } - - else { /* is_freq_mid(line->cl_option) */ - - if (is_freq_mins(line->cl_option)) - /* nothing to do */ - return; - else { - ftime->tm_min = 0; - if (is_freq_hrs(line->cl_option)) - ftime->tm_hour++; - else { - ftime->tm_hour = 0; - if (is_freq_days(line->cl_option)) - ftime->tm_mday++; - else { - if (is_freq_dow(line->cl_option)) { - int to_add=(ftime->tm_wday==0)?1: 8-ftime->tm_wday; - if (ftime->tm_mday + to_add > max) { - ftime->tm_mday = ftime->tm_mday + to_add - max; - ftime->tm_mon++; - } else - ftime->tm_mday += to_add; - } else { - ftime->tm_mday = 1; - if (is_freq_mons(line->cl_option)) - ftime->tm_mon++; - } - } - } - } - - } /* is_freq_mid(line->cl_option) */ + if (is_freq_mins(line->cl_option)) + /* nothing to do : return */ + return; + else if (is_freq_hrs(line->cl_option)) { + if (ftime->tm_min >= 30) + ftime->tm_hour++; + ftime->tm_min = 30; + } + else { + ftime->tm_min = 0; + if (is_freq_days(line->cl_option)) { + if (ftime->tm_hour >= 12) + ftime->tm_mday++; + ftime->tm_hour = 12; + } + else { + ftime->tm_hour = 0; + if (is_freq_dow(line->cl_option)) { + int to_add = (ftime->tm_wday >= 4) ? 11 - ftime->tm_wday : + 4 - ftime->tm_wday; + if (ftime->tm_mday + to_add > max) { + ftime->tm_mon++; + ftime->tm_mday = ftime->tm_mday + to_add - max; + } + else + ftime->tm_mday += to_add; + } + else { + if (is_freq_mons(line->cl_option)) { + if (ftime->tm_mday >= 15) + ftime->tm_mon++; + ftime->tm_mday = 15; + } + else { + /* weird : we have the bit freq_mid set, but + * none of freq_{mins|hour|days|dow|mons} is set : + * we do nothing but increase tm_min by 1 + * so as we don't return a time in the past */ + ftime->tm_min++; + warn("Line %s doesn't seem correct: consider " + "reinstalling the corresponding fcrontab"); + } + } + } + } + + } + + else { /* is_freq_mid(line->cl_option) */ + + if (is_freq_mins(line->cl_option)) + /* nothing to do */ + return; + else { + ftime->tm_min = 0; + if (is_freq_hrs(line->cl_option)) + ftime->tm_hour++; + else { + ftime->tm_hour = 0; + if (is_freq_days(line->cl_option)) + ftime->tm_mday++; + else { + if (is_freq_dow(line->cl_option)) { + int to_add = + (ftime->tm_wday == 0) ? 1 : 8 - ftime->tm_wday; + if (ftime->tm_mday + to_add > max) { + ftime->tm_mday = ftime->tm_mday + to_add - max; + ftime->tm_mon++; + } + else + ftime->tm_mday += to_add; + } + else { + ftime->tm_mday = 1; + if (is_freq_mons(line->cl_option)) + ftime->tm_mon++; + } + } + } + } + + } /* is_freq_mid(line->cl_option) */ /* we set tm_sec to 0 here and not before to ensure we will never return * a time in the past (case is_freq_mins(line->cl_option) @@ -729,37 +741,37 @@ goto_beginning_next_period_periodical(cl_t *line, struct tm *ftime) * (a value may exceed the max value of a field: fix it if necessary) */ if (ftime->tm_min >= 60) { - ftime->tm_min = 0; - ftime->tm_hour++; + ftime->tm_min = 0; + ftime->tm_hour++; } if (ftime->tm_hour >= 24) { - ftime->tm_hour = 0; - ftime->tm_mday++; + ftime->tm_hour = 0; + ftime->tm_mday++; } /* the month field may have changed */ max = get_nb_mdays((ftime->tm_year + 1900), ftime->tm_mon); if (ftime->tm_mday > max) { - ftime->tm_mday = 1; - ftime->tm_mon++; + ftime->tm_mday = 1; + ftime->tm_mon++; } if (ftime->tm_mon >= 12) { - ftime->tm_mon = 0; - ftime->tm_year++; + ftime->tm_mon = 0; + ftime->tm_year++; } if (debug_opt) - set_wday(ftime); + set_wday(ftime); debug(" %s beginning of next period %d/%d/%d wday:%d %02d:%02d " - "(tzdiff=%d, timezone=%s)", line->cl_shell, (ftime->tm_mon + 1), - ftime->tm_mday, (ftime->tm_year + 1900), ftime->tm_wday, - ftime->tm_hour, ftime->tm_min, line->cl_file->cf_tzdiff, - (line->cl_tz != NULL)? line->cl_tz : "localtime"); - + "(tzdiff=%d, timezone=%s)", line->cl_shell, (ftime->tm_mon + 1), + ftime->tm_mday, (ftime->tm_year + 1900), ftime->tm_wday, + ftime->tm_hour, ftime->tm_min, line->cl_file->cf_tzdiff, + (line->cl_tz != NULL) ? line->cl_tz : "localtime"); + } void -move_time_to(int where, cl_t *line, struct tm *ftime) +move_time_to(int where, cl_t * line, struct tm *ftime) /* IF WHERE == BEGIN_NEXT_PERIOD: from ftime, search the first/nearest time and date * of the line's next period of execution. * IF WHERE == END_OF_INTERVAL: search the last time and date @@ -778,168 +790,173 @@ move_time_to(int where, cl_t *line, struct tm *ftime) /* by default we set timet_next_period to now + 10 years, which will * always be later than the end of the interval of execution * so as to make the test timet_ftime < timet_next_period always true */ - time_t timet_next_period = now + 10 * 365 * 24 * 3600; + time_t timet_next_period = now + 10 * 365 * 24 * 3600; /* to prevent from infinite loop with unvalid lines : */ short int year_limit = MAXYEAR_SCHEDULE_TIME; /* Depending on the situation we may need to ignore some fields * while we walk through time */ char ignore_mins, ignore_hrs, ignore_days, ignore_mons, ignore_dow; - + /* sanity checks */ - if ( where != BEGIN_NEXT_PERIOD && where != END_OF_INTERVAL ) - die("move_time_to() called with invalid argument 'where': %d", (int)where); + if (where != BEGIN_NEXT_PERIOD && where != END_OF_INTERVAL) + die("move_time_to() called with invalid argument 'where': %d", + (int)where); - if ( where == BEGIN_NEXT_PERIOD && is_freq_periodically(line->cl_option) ) { - goto_beginning_next_period_periodical(line, ftime); - return; + if (where == BEGIN_NEXT_PERIOD && is_freq_periodically(line->cl_option)) { + goto_beginning_next_period_periodical(line, ftime); + return; } /* In all other cases, we will have to walk through time */ - if ( is_freq_periodically(line->cl_option) ) { + if (is_freq_periodically(line->cl_option)) { - /* In this case we want to make sure we won't go after the end - * of the period of execution, so we need to set next_period */ + /* In this case we want to make sure we won't go after the end + * of the period of execution, so we need to set next_period */ - memcpy(&tm_next_period, ftime, sizeof(tm_next_period)); - goto_beginning_next_period_periodical(line, &tm_next_period); - timet_next_period = mktime_no_dst(&tm_next_period); + memcpy(&tm_next_period, ftime, sizeof(tm_next_period)); + goto_beginning_next_period_periodical(line, &tm_next_period); + timet_next_period = mktime_no_dst(&tm_next_period); } timet_ftime = mktime_no_dst(ftime); - + if (where == BEGIN_NEXT_PERIOD) { - /* we have to ignore the fields containing single numbers */ - ignore_mins = (is_freq_mins(line->cl_option)) ? 1:0; - ignore_hrs = (is_freq_hrs(line->cl_option)) ? 1:0; - ignore_days = (is_freq_days(line->cl_option)) ? 1:0; - ignore_mons = (is_freq_mons(line->cl_option)) ? 1:0; - ignore_dow = (is_freq_dow(line->cl_option)) ? 1:0; + /* we have to ignore the fields containing single numbers */ + ignore_mins = (is_freq_mins(line->cl_option)) ? 1 : 0; + ignore_hrs = (is_freq_hrs(line->cl_option)) ? 1 : 0; + ignore_days = (is_freq_days(line->cl_option)) ? 1 : 0; + ignore_mons = (is_freq_mons(line->cl_option)) ? 1 : 0; + ignore_dow = (is_freq_dow(line->cl_option)) ? 1 : 0; } else { - /* we want to go to the end of the current interval: - * we don't ignore anything */ - ignore_mins = ignore_hrs = ignore_days = ignore_mons = ignore_dow = 0; + /* we want to go to the end of the current interval: + * we don't ignore anything */ + ignore_mins = ignore_hrs = ignore_days = ignore_mons = ignore_dow = 0; } /* */ debug(" ignore: %d %d %d %d %d", ignore_mins, ignore_hrs, - ignore_days, ignore_mons, ignore_dow); + ignore_days, ignore_mons, ignore_dow); /* */ /* while we are in an interval of execution and not in the next period */ - while ( (ignore_mins == 1 || bit_test(line->cl_mins, ftime->tm_min)) && - (ignore_hrs == 1 || bit_test(line->cl_hrs, ftime->tm_hour)) && - ( - (is_dayand(line->cl_option) && - (ignore_days==1||bit_test(line->cl_days,ftime->tm_mday)) && - (ignore_dow==1 || bit_test(line->cl_dow, ftime->tm_wday))) - || - (is_dayor(line->cl_option) && - (ignore_days==1||bit_test(line->cl_days, ftime->tm_mday) || - ignore_dow == 1 || bit_test(line->cl_dow,ftime->tm_wday))) - ) && - (ignore_mons == 1 || bit_test(line->cl_mons, ftime->tm_mon)) - && - (timet_ftime < timet_next_period) - ) { - - ftime->tm_sec = 0; - if (ignore_mins) ftime->tm_min = 60; - else { - do ftime->tm_min++ ; - while ( bit_test(line->cl_mins, ftime->tm_min) - && (ftime->tm_min < 60) ); - } - if (ftime->tm_min >= 60) { - ftime->tm_min = 0; - if (ignore_hrs && ignore_mins) ftime->tm_hour = 24; - else ftime->tm_hour++; - if (ftime->tm_hour >= 24) { - ftime->tm_hour = 0; - if (ignore_days && ignore_hrs && ignore_mins && ignore_dow) - ftime->tm_mday = 32; /* go to next month */ - else ftime->tm_mday++; - if (ftime->tm_mday > - get_nb_mdays((ftime->tm_year+1900),ftime->tm_mon)) { - ftime->tm_mday = 1; - if(ignore_mons && ignore_days && ignore_dow - && ignore_hrs && ignore_mins) - ftime->tm_mon = 12; - else ftime->tm_mon++; - if (ftime->tm_mon >= 12) { - ftime->tm_mon = 0; - ftime->tm_year++; - if (--year_limit <= 0) { - error("Can't found a non matching date for %s " - "in the next %d years. Maybe this line " - "is corrupted : consider reinstalling " - "the fcrontab", line->cl_shell, - MAXYEAR_SCHEDULE_TIME); - return; - } - } - } - set_wday(ftime); - } - } - - /* // */ - { - /* set temporarily debug_opt to false to avoid having too many - * messages in the logs */ - char debug_opt_previous = debug_opt; - debug_opt = 0; - - timet_ftime = mktime_no_dst(ftime); - - debug_opt = debug_opt_previous; - } - /* // */ - + while ((ignore_mins == 1 || bit_test(line->cl_mins, ftime->tm_min)) && + (ignore_hrs == 1 || bit_test(line->cl_hrs, ftime->tm_hour)) && + ((is_dayand(line->cl_option) && + (ignore_days == 1 || bit_test(line->cl_days, ftime->tm_mday)) && + (ignore_dow == 1 || bit_test(line->cl_dow, ftime->tm_wday))) + || + (is_dayor(line->cl_option) && + (ignore_days == 1 || bit_test(line->cl_days, ftime->tm_mday) || + ignore_dow == 1 || bit_test(line->cl_dow, ftime->tm_wday))) + ) && (ignore_mons == 1 || bit_test(line->cl_mons, ftime->tm_mon)) + && (timet_ftime < timet_next_period) + ) { + + ftime->tm_sec = 0; + if (ignore_mins) + ftime->tm_min = 60; + else { + do + ftime->tm_min++; + while (bit_test(line->cl_mins, ftime->tm_min) + && (ftime->tm_min < 60)); + } + if (ftime->tm_min >= 60) { + ftime->tm_min = 0; + if (ignore_hrs && ignore_mins) + ftime->tm_hour = 24; + else + ftime->tm_hour++; + if (ftime->tm_hour >= 24) { + ftime->tm_hour = 0; + if (ignore_days && ignore_hrs && ignore_mins && ignore_dow) + ftime->tm_mday = 32; /* go to next month */ + else + ftime->tm_mday++; + if (ftime->tm_mday > + get_nb_mdays((ftime->tm_year + 1900), ftime->tm_mon)) { + ftime->tm_mday = 1; + if (ignore_mons && ignore_days && ignore_dow + && ignore_hrs && ignore_mins) + ftime->tm_mon = 12; + else + ftime->tm_mon++; + if (ftime->tm_mon >= 12) { + ftime->tm_mon = 0; + ftime->tm_year++; + if (--year_limit <= 0) { + error("Can't found a non matching date for %s " + "in the next %d years. Maybe this line " + "is corrupted : consider reinstalling " + "the fcrontab", line->cl_shell, + MAXYEAR_SCHEDULE_TIME); + return; + } + } + } + set_wday(ftime); + } + } + + /* // */ + { + /* set temporarily debug_opt to false to avoid having too many + * messages in the logs */ + char debug_opt_previous = debug_opt; + debug_opt = 0; + + timet_ftime = mktime_no_dst(ftime); + + debug_opt = debug_opt_previous; + } + /* // */ + } if (timet_ftime > timet_next_period) { - /* the end of the interval if after the end of the period: - * we don't want to go in the next period, so we return - * the value of the end of the period. */ - memcpy(ftime, &tm_next_period, sizeof(tm_next_period)); + /* the end of the interval if after the end of the period: + * we don't want to go in the next period, so we return + * the value of the end of the period. */ + memcpy(ftime, &tm_next_period, sizeof(tm_next_period)); } if (where == END_OF_INTERVAL) { - /* we want the end of the current interval, not the beginning - * of the first non-matching interval : go back by one minute */ - if (--ftime->tm_min < 0) { - ftime->tm_min = 59; - if (--ftime->tm_hour < 0) { - ftime->tm_hour = 23; - if (--ftime->tm_mday < 1) { - if (--ftime->tm_mon < 0) { - ftime->tm_mon = 11; - ftime->tm_year--; - } - ftime->tm_mday = get_nb_mdays( (ftime->tm_year + 1900), - ftime->tm_mon); - } - } - } + /* we want the end of the current interval, not the beginning + * of the first non-matching interval : go back by one minute */ + if (--ftime->tm_min < 0) { + ftime->tm_min = 59; + if (--ftime->tm_hour < 0) { + ftime->tm_hour = 23; + if (--ftime->tm_mday < 1) { + if (--ftime->tm_mon < 0) { + ftime->tm_mon = 11; + ftime->tm_year--; + } + ftime->tm_mday = + get_nb_mdays((ftime->tm_year + 1900), ftime->tm_mon); + } + } + } } - + debug(" %s %s %d/%d/%d wday:%d %02d:%02d (tzdiff=%d, timezone=%s)", - line->cl_shell, - (where == END_OF_INTERVAL) ? "end of interval" : "begin of next period", - (ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900), - ftime->tm_wday, ftime->tm_hour, ftime->tm_min, - line->cl_file->cf_tzdiff, - (line->cl_tz != NULL)? line->cl_tz : "localtime"); + line->cl_shell, + (where == + END_OF_INTERVAL) ? "end of interval" : "begin of next period", + (ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900), + ftime->tm_wday, ftime->tm_hour, ftime->tm_min, + line->cl_file->cf_tzdiff, + (line->cl_tz != NULL) ? line->cl_tz : "localtime"); } -void -set_next_exe(cl_t *line, char option, int info_fd) +void +set_next_exe(cl_t * line, char option, int info_fd) /* set the cl_nextexe of a given cl_t and insert it in the queue */ { @@ -948,7 +965,7 @@ set_next_exe(cl_t *line, char option, int info_fd) struct tm ftime; int tz_changed = 0; - basetime = (option & FROM_CUR_NEXTEXE) ? line->cl_nextexe : now ; + basetime = (option & FROM_CUR_NEXTEXE) ? line->cl_nextexe : now; /* Switch to another timezone if necessary. */ /* If line should be scheduled in a different time zone @@ -958,282 +975,298 @@ set_next_exe(cl_t *line, char option, int info_fd) * of the function. */ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz); - if ( is_td(line->cl_option) ) { - - time_t nextexe = 0; - int i; - int max; - char has_changed = 0; - /* to prevent from invinite loop with unvalid lines : */ - short int year_limit = MAXYEAR_SCHEDULE_TIME; - /* timezone difference */ - time_t basetime_tz = basetime - (line->cl_file->cf_tzdiff * 3600); - - ft = localtime(&basetime_tz); - - /* localtime() function seem to return every time the same pointer : - it resets our previous changes, so we need to prevent it - ( localtime() is used in the debug() function) */ - memcpy(&ftime, ft, sizeof(struct tm)); - - /* creates a bug on DST change on some systems ?? */ - /* ftime.tm_isdst = -1; */ - - /* to prevent multiple execution of &-jobs in the same minute - * (but not if the user has explicitely asked to run jobs immediately) */ - if (first_sleep > 0 || option == STD || line->cl_runfreq != 1) { - ftime.tm_min += 1; - ftime.tm_sec = 0; - } - - if (line->cl_runfreq == 1 && option != NO_GOTO && option != NO_GOTO_LOG) - /* %-line: go to next period */ - move_time_to(BEGIN_NEXT_PERIOD, line, &ftime); - - setMonth: - for (i = ftime.tm_mon; (bit_test(line->cl_mons, i)==0) && (i<12); i++); - if (i >= 12) { - ftime.tm_year++; - if (--year_limit <= 0) { - error("Can't found a matching date for %s in the next %d" - " years. Maybe this line is corrupted : consider" - " reinstalling the fcrontab.", - line->cl_shell, MAXYEAR_SCHEDULE_TIME); - goto set_cl_nextexe; - } - if ( has_changed < 3) { - has_changed = 3; - ftime.tm_mon = 0; - ftime.tm_mday = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } else - ftime.tm_mon = 0; - goto setMonth; - } - if (ftime.tm_mon != i) { - ftime.tm_mon = i; - if ( has_changed < 2) { - has_changed = 2; - ftime.tm_mday = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } - } - - /* set the number of days in that month */ - max = get_nb_mdays( (ftime.tm_year + 1900), ftime.tm_mon); - - setDay: - if ( is_dayand(line->cl_option) ) { - for (i = ftime.tm_mday; - (bit_test(line->cl_days, i) == 0) && (i <= max); i++); - if (i > max) { - ftime.tm_mon++; - if ( has_changed < 2) { - has_changed = 2; - ftime.tm_mday = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } else - ftime.tm_mday = 1; - goto setMonth; - } - if ( ftime.tm_mday != i ) { - ftime.tm_mday = i; - if ( has_changed < 1) { - has_changed = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } - } - - set_wday(&ftime); - - /* check if the day of week is OK */ - if ( bit_test(line->cl_dow, ftime.tm_wday) == 0 ) { - ftime.tm_mday++; - ftime.tm_hour = 0; - ftime.tm_min = 0; - goto setDay; - } - } else { /* dayor */ - int j; - - set_wday(&ftime); - - j = ftime.tm_wday; - i = ftime.tm_mday; - while( (bit_test(line->cl_days, i) == 0) && - (bit_test(line->cl_dow, j) == 0) ) { - if (i > max) { - ftime.tm_mon++; - if ( has_changed < 2) { - has_changed = 2; - ftime.tm_mday = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } else - ftime.tm_mday = 1; - goto setMonth; - } - if (j >= 7) - j -= 7; - i++; - j++; - } - if ( ftime.tm_mday != i ) { - ftime.tm_mday = i; - if ( has_changed < 1) { - has_changed = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } - } - } - - setHour: - for (i=ftime.tm_hour; (bit_test(line->cl_hrs, i)==0) && (i<24); i++); - if (i >= 24) { - ftime.tm_mday++; - if ( has_changed < 1) { - has_changed = 1; - ftime.tm_hour = 0; - ftime.tm_min = 0; - } else - ftime.tm_hour = 0; - goto setDay; - } - if ( ftime.tm_hour != i ) { - ftime.tm_hour = i; - ftime.tm_min = 0; - } - - - for (i=ftime.tm_min; (bit_test(line->cl_mins, i)==0) && (i<60); i++); - if (i >= 60) { - ftime.tm_hour++; - ftime.tm_min = 0; - goto setHour; - } - ftime.tm_min = i; - - set_cl_nextexe: - /* set cl_nextexe (handle the timezone differences) */ - - /* NOTE : the output of mktime does not depend on the timezone, - * hence, nextexe is correct even if option timezone is used. */ - nextexe = mktime_no_dst(&ftime); - - if ( is_random(line->cl_option) ) { - /* run the job at a random time during its interval of execution */ - struct tm int_end; - time_t int_end_timet; - - debug(" cmd: %s begin int exec %d/%d/%d wday:%d %02d:%02d " - "(tzdiff=%d, timezone=%s)", line->cl_shell, (ftime.tm_mon + 1), - ftime.tm_mday, (ftime.tm_year + 1900), ftime.tm_wday, - ftime.tm_hour, ftime.tm_min, line->cl_file->cf_tzdiff, - (line->cl_tz != NULL)? line->cl_tz : "localtime"); - - memcpy(&int_end, &ftime, sizeof(int_end)); - move_time_to(END_OF_INTERVAL, line, &int_end); - int_end_timet = mktime_no_dst(&int_end); - - /* set a random time to add to the first allowed time of execution */ - nextexe += ( (i= int_end_timet - nextexe) > 0) ? - (time_t)(((float)i * (float)rand())/(float)RAND_MAX) : 0; - } - else if (is_td(line->cl_option) && line->cl_runfreq != 1 && line->cl_jitter > 0){ - /* &-lines only: - * run the command between nextexe and nextexe+jitter seconds, - * as a way not to have 100 jobs all starting exactly at - * the second 0 of the minute they should run */ - nextexe += (time_t)(((float)line->cl_jitter * (float)rand())/(float)RAND_MAX); - } - - line->cl_nextexe = nextexe + (line->cl_file->cf_tzdiff * 3600); - - if ( option != NO_GOTO ) { - if ( is_random(line->cl_option) ) { - ft = localtime(&nextexe); - memcpy(&ftime, ft, sizeof(ftime)); - } - send_msg_fd_debug(info_fd, " cmd: %s next exec %d/%d/%d wday:%d " - "%02d:%02d:%02d (tzdiff=%d, timezone=%s)", line->cl_shell, - (ftime.tm_mon + 1), ftime.tm_mday, - (ftime.tm_year + 1900), ftime.tm_wday, - ftime.tm_hour, ftime.tm_min, ftime.tm_sec, - line->cl_file->cf_tzdiff, - (line->cl_tz != NULL)? line->cl_tz : "system's"); - } - - /* - * sanity check : - * if the nextexe is set to the past because of a bug, - * the line will be executed again immediately, and it is most likely - * to be set again in the past next time. - * It would create a nasty infinite loop, a kind of "while(1) fork();" - * - * We add a test here to limit the consequences that would have - * an unknown bug in this function. - */ - if ( line->cl_nextexe <= now ) { - error("BUG ??? Fcron thinks the next exe time of %s is %ld, " - "hence before now (%ld). To avoid infinite loop, nextexe" - " will be set at now+5s.", line->cl_shell, line->cl_nextexe); - line->cl_nextexe = now + 5; - } + if (is_td(line->cl_option)) { + + time_t nextexe = 0; + int i; + int max; + char has_changed = 0; + /* to prevent from invinite loop with unvalid lines : */ + short int year_limit = MAXYEAR_SCHEDULE_TIME; + /* timezone difference */ + time_t basetime_tz = basetime - (line->cl_file->cf_tzdiff * 3600); + + ft = localtime(&basetime_tz); + + /* localtime() function seem to return every time the same pointer : + * it resets our previous changes, so we need to prevent it + * ( localtime() is used in the debug() function) */ + memcpy(&ftime, ft, sizeof(struct tm)); + + /* creates a bug on DST change on some systems ?? */ + /* ftime.tm_isdst = -1; */ + + /* to prevent multiple execution of &-jobs in the same minute + * (but not if the user has explicitely asked to run jobs immediately) */ + if (first_sleep > 0 || option == STD || line->cl_runfreq != 1) { + ftime.tm_min += 1; + ftime.tm_sec = 0; + } + + if (line->cl_runfreq == 1 && option != NO_GOTO && option != NO_GOTO_LOG) + /* %-line: go to next period */ + move_time_to(BEGIN_NEXT_PERIOD, line, &ftime); + + setMonth: + for (i = ftime.tm_mon; (bit_test(line->cl_mons, i) == 0) && (i < 12); + i++) ; + if (i >= 12) { + ftime.tm_year++; + if (--year_limit <= 0) { + error("Can't found a matching date for %s in the next %d" + " years. Maybe this line is corrupted : consider" + " reinstalling the fcrontab.", + line->cl_shell, MAXYEAR_SCHEDULE_TIME); + goto set_cl_nextexe; + } + if (has_changed < 3) { + has_changed = 3; + ftime.tm_mon = 0; + ftime.tm_mday = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + else + ftime.tm_mon = 0; + goto setMonth; + } + if (ftime.tm_mon != i) { + ftime.tm_mon = i; + if (has_changed < 2) { + has_changed = 2; + ftime.tm_mday = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + } + + /* set the number of days in that month */ + max = get_nb_mdays((ftime.tm_year + 1900), ftime.tm_mon); + + setDay: + if (is_dayand(line->cl_option)) { + for (i = ftime.tm_mday; + (bit_test(line->cl_days, i) == 0) && (i <= max); i++) ; + if (i > max) { + ftime.tm_mon++; + if (has_changed < 2) { + has_changed = 2; + ftime.tm_mday = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + else + ftime.tm_mday = 1; + goto setMonth; + } + if (ftime.tm_mday != i) { + ftime.tm_mday = i; + if (has_changed < 1) { + has_changed = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + } + + set_wday(&ftime); + + /* check if the day of week is OK */ + if (bit_test(line->cl_dow, ftime.tm_wday) == 0) { + ftime.tm_mday++; + ftime.tm_hour = 0; + ftime.tm_min = 0; + goto setDay; + } + } + else { /* dayor */ + int j; + + set_wday(&ftime); + + j = ftime.tm_wday; + i = ftime.tm_mday; + while ((bit_test(line->cl_days, i) == 0) && + (bit_test(line->cl_dow, j) == 0)) { + if (i > max) { + ftime.tm_mon++; + if (has_changed < 2) { + has_changed = 2; + ftime.tm_mday = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + else + ftime.tm_mday = 1; + goto setMonth; + } + if (j >= 7) + j -= 7; + i++; + j++; + } + if (ftime.tm_mday != i) { + ftime.tm_mday = i; + if (has_changed < 1) { + has_changed = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + } + } + + setHour: + for (i = ftime.tm_hour; (bit_test(line->cl_hrs, i) == 0) && (i < 24); + i++) ; + if (i >= 24) { + ftime.tm_mday++; + if (has_changed < 1) { + has_changed = 1; + ftime.tm_hour = 0; + ftime.tm_min = 0; + } + else + ftime.tm_hour = 0; + goto setDay; + } + if (ftime.tm_hour != i) { + ftime.tm_hour = i; + ftime.tm_min = 0; + } + + + for (i = ftime.tm_min; (bit_test(line->cl_mins, i) == 0) && (i < 60); + i++) ; + if (i >= 60) { + ftime.tm_hour++; + ftime.tm_min = 0; + goto setHour; + } + ftime.tm_min = i; + + set_cl_nextexe: + /* set cl_nextexe (handle the timezone differences) */ + + /* NOTE : the output of mktime does not depend on the timezone, + * hence, nextexe is correct even if option timezone is used. */ + nextexe = mktime_no_dst(&ftime); + + if (is_random(line->cl_option)) { + /* run the job at a random time during its interval of execution */ + struct tm int_end; + time_t int_end_timet; + + debug(" cmd: %s begin int exec %d/%d/%d wday:%d %02d:%02d " + "(tzdiff=%d, timezone=%s)", line->cl_shell, + (ftime.tm_mon + 1), ftime.tm_mday, (ftime.tm_year + 1900), + ftime.tm_wday, ftime.tm_hour, ftime.tm_min, + line->cl_file->cf_tzdiff, + (line->cl_tz != NULL) ? line->cl_tz : "localtime"); + + memcpy(&int_end, &ftime, sizeof(int_end)); + move_time_to(END_OF_INTERVAL, line, &int_end); + int_end_timet = mktime_no_dst(&int_end); + + /* set a random time to add to the first allowed time of execution */ + nextexe += ((i = int_end_timet - nextexe) > 0) ? + (time_t) (((float)i * (float)rand()) / (float)RAND_MAX) : 0; + } + else if (is_td(line->cl_option) && line->cl_runfreq != 1 + && line->cl_jitter > 0) { + /* &-lines only: + * run the command between nextexe and nextexe+jitter seconds, + * as a way not to have 100 jobs all starting exactly at + * the second 0 of the minute they should run */ + nextexe += + (time_t) (((float)line->cl_jitter * (float)rand()) / + (float)RAND_MAX); + } + + line->cl_nextexe = nextexe + (line->cl_file->cf_tzdiff * 3600); + + if (option != NO_GOTO) { + if (is_random(line->cl_option)) { + ft = localtime(&nextexe); + memcpy(&ftime, ft, sizeof(ftime)); + } + send_msg_fd_debug(info_fd, " cmd: %s next exec %d/%d/%d wday:%d " + "%02d:%02d:%02d (tzdiff=%d, timezone=%s)", + line->cl_shell, (ftime.tm_mon + 1), ftime.tm_mday, + (ftime.tm_year + 1900), ftime.tm_wday, + ftime.tm_hour, ftime.tm_min, ftime.tm_sec, + line->cl_file->cf_tzdiff, + (line->cl_tz != NULL) ? line->cl_tz : "system's"); + } + + /* + * sanity check : + * if the nextexe is set to the past because of a bug, + * the line will be executed again immediately, and it is most likely + * to be set again in the past next time. + * It would create a nasty infinite loop, a kind of "while(1) fork();" + * + * We add a test here to limit the consequences that would have + * an unknown bug in this function. + */ + if (line->cl_nextexe <= now) { + error("BUG ??? Fcron thinks the next exe time of %s is %ld, " + "hence before now (%ld). To avoid infinite loop, nextexe" + " will be set at now+5s.", line->cl_shell, line->cl_nextexe); + line->cl_nextexe = now + 5; + } } else { - /* this is a job based on system up time */ + /* this is a job based on system up time */ - if ( line->cl_timefreq == LONG_MAX ) { + if (line->cl_timefreq == LONG_MAX) { /* when timefreq is set to LONG_MAX, it means that next time nextexe * is updated we want it to be the furthest away possible so as the job * is never executed again (unless at the next reboot/fcron startup * if the line as the appropriate options set) */ /* NOTE: the options runonce/hasrun should be used to achieve this, * but we keep this here as an extra safety */ - debug("Setting cl_nextexe to LONG_MAX to prevent the line from running again."); + debug + ("Setting cl_nextexe to LONG_MAX to prevent the line from running again."); line->cl_nextexe = LONG_MAX; } else { line->cl_nextexe = basetime + line->cl_timefreq; - if ( line->cl_nextexe <= basetime ) { + if (line->cl_nextexe <= basetime) { /* there was an integer overflow! */ error("Error while setting next exe time for job %s: cl_nextexe" - " overflowed. basetime=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", - line->cl_shell, basetime, line->cl_timefreq, line->cl_nextexe); - error("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); + " overflowed. basetime=%lu, cl_timefreq=%lu, cl_nextexe=%lu.", + line->cl_shell, basetime, line->cl_timefreq, + line->cl_nextexe); + error + ("Setting cl_nextexe to LONG_MAX to prevent an infinite loop."); line->cl_nextexe = LONG_MAX; } } - ft = localtime( &(line->cl_nextexe) ); + ft = localtime(&(line->cl_nextexe)); - /* localtime() function seem to return every time the same pointer : - it resets our previous changes, so we need to prevent it - ( localtime() is used in the debug() function) */ - memcpy(&ftime, ft, sizeof(struct tm)); + /* localtime() function seem to return every time the same pointer : + * it resets our previous changes, so we need to prevent it + * ( localtime() is used in the debug() function) */ + memcpy(&ftime, ft, sizeof(struct tm)); - send_msg_fd_debug(info_fd, " cmd: %s next exec %d/%d/%d wday:%d " - "%02d:%02d:%02d (system time)", line->cl_shell, - (ftime.tm_mon + 1), ftime.tm_mday, (ftime.tm_year+1900), - ftime.tm_wday, ftime.tm_hour, ftime.tm_min, ftime.tm_sec); + send_msg_fd_debug(info_fd, " cmd: %s next exec %d/%d/%d wday:%d " + "%02d:%02d:%02d (system time)", line->cl_shell, + (ftime.tm_mon + 1), ftime.tm_mday, + (ftime.tm_year + 1900), ftime.tm_wday, ftime.tm_hour, + ftime.tm_min, ftime.tm_sec); } - + insert_nextexe(line); - if ( tz_changed > 0 ) - switch_back_timezone(orig_tz_envvar); + if (tz_changed > 0) + switch_back_timezone(orig_tz_envvar); } void -set_next_exe_notrun(cl_t *line, char context) +set_next_exe_notrun(cl_t * line, char context) /* set the time of the next execution and send a mail to tell user his job * has not run if necessary */ { @@ -1255,46 +1288,46 @@ set_next_exe_notrun(cl_t *line, char context) * and switch back to the local timezone at the end * of the function. */ tz_changed = switch_timezone(orig_tz_envvar, line->cl_tz); - + if (context == SYSDOWN || context == SYSDOWN_RUNATREBOOT) { - /* handle timezone differences */ - previous_period = line->cl_nextexe - (line->cl_file->cf_tzdiff * 3600); - set_next_exe_opt = NO_GOTO; + /* handle timezone differences */ + previous_period = line->cl_nextexe - (line->cl_file->cf_tzdiff * 3600); + set_next_exe_opt = NO_GOTO; } else { - previous_period = now - (line->cl_file->cf_tzdiff * 3600); - set_next_exe_opt = NO_GOTO_LOG; + previous_period = now - (line->cl_file->cf_tzdiff * 3600); + set_next_exe_opt = NO_GOTO_LOG; } ft = localtime(&previous_period); /* localtime() function seem to return every time the same pointer : - it resets our previous changes, so we need to prevent it - ( localtime() is used in the debug() function) */ + * it resets our previous changes, so we need to prevent it + * ( localtime() is used in the debug() function) */ memcpy(&ftime, ft, sizeof(ftime)); /* we also copy it to last_nextexe which will be used in mail_notrun */ memcpy(&last_nextexe, ft, sizeof(last_nextexe)); - + ftime.tm_sec = 0; move_time_to(BEGIN_NEXT_PERIOD, line, &ftime); next_period = mktime_no_dst(&ftime) + (line->cl_file->cf_tzdiff * 3600); - if ( context == SYSDOWN_RUNATREBOOT ) + if (context == SYSDOWN_RUNATREBOOT) line->cl_nextexe = now; else set_next_exe(line, set_next_exe_opt, -1); - if ( line->cl_nextexe >= next_period ) { - /* line has not run during one or more period(s) : send a mail */ - mail_notrun(line, context, &last_nextexe); + if (line->cl_nextexe >= next_period) { + /* line has not run during one or more period(s) : send a mail */ + mail_notrun(line, context, &last_nextexe); } - if ( tz_changed > 0 ) - switch_back_timezone(orig_tz_envvar); + if (tz_changed > 0) + switch_back_timezone(orig_tz_envvar); } void -mail_notrun_time_t(cl_t *line, char context, time_t since_time_t) +mail_notrun_time_t(cl_t * line, char context, time_t since_time_t) /* Same as mail_notrun() but with 'since' defined as a time_t instead of a struct tm */ { struct tm *since2 = NULL; @@ -1308,13 +1341,13 @@ mail_notrun_time_t(cl_t *line, char context, time_t since_time_t) mail_notrun(line, SYSDOWN, &since); - if ( tz_changed > 0 ) + if (tz_changed > 0) switch_back_timezone(orig_tz_envvar); } void -mail_notrun(cl_t *line, char context, struct tm *since) +mail_notrun(cl_t * line, char context, struct tm *since) /* send a mail to tell user a job has not run (and why) */ { int pid = 0; @@ -1322,25 +1355,25 @@ mail_notrun(cl_t *line, char context, struct tm *since) struct tm *time2 = NULL, time; char **sendmailenv = NULL; - switch ( pid = fork() ) { + switch (pid = fork()) { case -1: - error_e("Fork error : could not mail for not run %s", line->cl_shell); - return; + error_e("Fork error : could not mail for not run %s", line->cl_shell); + return; case 0: - /* child */ - break; + /* child */ + break; default: - /* parent */ + /* parent */ /* // */ - debug("Reporting by mail non execution of %s (pid %d)", - line->cl_shell, pid); + debug("Reporting by mail non execution of %s (pid %d)", + line->cl_shell, pid); /* // */ - /* create an entry in exe_list */ - /* set line to NULL as this is not a line ... */ - exe_list_add_line(exe_list, NULL); - return; + /* create an entry in exe_list */ + /* set line to NULL as this is not a line ... */ + exe_list_add_line(exe_list, NULL); + return; } /* If line should be scheduled in a different time zone @@ -1348,62 +1381,62 @@ mail_notrun(cl_t *line, char context, struct tm *since) * switch to that timezone now, before we do the calculations. */ /* No need to switch back as this function does NOT return. */ switch_timezone(orig_tz_envvar, line->cl_tz); - - if ( context == QUEUE_FULL ) - time2 = localtime(&now); + + if (context == QUEUE_FULL) + time2 = localtime(&now); else - time2 = localtime(&line->cl_nextexe); + time2 = localtime(&line->cl_nextexe); memcpy(&time, time2, sizeof(time)); /* create a temp file, and write in it the message to send */ mailf = create_mail(line, "Non-execution of fcron job", NULL, NULL, NULL); - switch ( context ) { + switch (context) { case SYSDOWN: - fprintf(mailf, "Line %s has not run since and including " - "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n" - "due to system's down state.\n", - line->cl_shell, (since->tm_mon + 1), since->tm_mday, - (since->tm_year + 1900), since->tm_wday, since->tm_hour, - since->tm_min, (line->cl_tz)? line->cl_tz : "system's"); - fprintf(mailf, "It will be next executed at %d/%d/%d wday:" - "%d %02d:%02d\n", (time.tm_mon + 1), time.tm_mday, - (time.tm_year+1900), time.tm_wday, time.tm_hour, time.tm_min); - break; + fprintf(mailf, "Line %s has not run since and including " + "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n" + "due to system's down state.\n", + line->cl_shell, (since->tm_mon + 1), since->tm_mday, + (since->tm_year + 1900), since->tm_wday, since->tm_hour, + since->tm_min, (line->cl_tz) ? line->cl_tz : "system's"); + fprintf(mailf, "It will be next executed at %d/%d/%d wday:" + "%d %02d:%02d\n", (time.tm_mon + 1), time.tm_mday, + (time.tm_year + 1900), time.tm_wday, time.tm_hour, time.tm_min); + break; case LAVG: - fprintf(mailf, "Line %s has not run since and including " - "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n", - line->cl_shell, (since->tm_mon + 1), since->tm_mday, - (since->tm_year + 1900), since->tm_wday, since->tm_hour, - since->tm_min, (line->cl_tz)? line->cl_tz : "system's"); - fprintf(mailf, "due to a too high system load average or " - "too many lavg-serial jobs.\n"); - fprintf(mailf, "It will be next executed at %d/%d/%d " - "wday:%d %02d:%02d (timezone=%s)\n", (time.tm_mon + 1), - time.tm_mday, (time.tm_year+1900), time.tm_wday, time.tm_hour, - time.tm_min, (line->cl_tz)? line->cl_tz : "system's"); - break; + fprintf(mailf, "Line %s has not run since and including " + "%d/%d/%d wday:%d %02d:%02d (timezone=%s)\n", + line->cl_shell, (since->tm_mon + 1), since->tm_mday, + (since->tm_year + 1900), since->tm_wday, since->tm_hour, + since->tm_min, (line->cl_tz) ? line->cl_tz : "system's"); + fprintf(mailf, "due to a too high system load average or " + "too many lavg-serial jobs.\n"); + fprintf(mailf, "It will be next executed at %d/%d/%d " + "wday:%d %02d:%02d (timezone=%s)\n", (time.tm_mon + 1), + time.tm_mday, (time.tm_year + 1900), time.tm_wday, time.tm_hour, + time.tm_min, (line->cl_tz) ? line->cl_tz : "system's"); + break; case QUEUE_FULL: - fprintf(mailf,"Line %s couldn't be added to lavg or serial queue which" - " is full ( %d/%d/%d wday:%d %02d:%02d (timezone=%s)).\n", - line->cl_shell, (time.tm_mon + 1), time.tm_mday, - (time.tm_year + 1900), time.tm_wday, time.tm_hour, time.tm_min, - (line->cl_tz)? line->cl_tz : "system's"); - fprintf(mailf, "Consider using options lavgonce, until, strict, " - "serialonce and/or fcron's option -m.\n"); - fprintf(mailf, "Note that job %s has not run.\n", line->cl_shell); - break; + fprintf(mailf, "Line %s couldn't be added to lavg or serial queue which" + " is full ( %d/%d/%d wday:%d %02d:%02d (timezone=%s)).\n", + line->cl_shell, (time.tm_mon + 1), time.tm_mday, + (time.tm_year + 1900), time.tm_wday, time.tm_hour, time.tm_min, + (line->cl_tz) ? line->cl_tz : "system's"); + fprintf(mailf, "Consider using options lavgonce, until, strict, " + "serialonce and/or fcron's option -m.\n"); + fprintf(mailf, "Note that job %s has not run.\n", line->cl_shell); + break; } - + /* become user (for security reasons) */ change_user_setup_env(line, &sendmailenv, NULL, NULL, NULL, NULL, NULL); /* then, send mail */ launch_mailer(line, mailf, sendmailenv); - + /* we should not come here : launch_mailer does not return */ die("mail_notrun : launch_mailer failed"); - + } time_t @@ -1415,9 +1448,10 @@ check_lavg(time_t lim) lavg_t *l = NULL; #ifdef NOLOADAVG - for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) { - run_lavg_job(l); - lavg_list_remove_cur(lavg_list); + for (l = lavg_list_first(lavg_list); l != NULL; + l = lavg_list_next(lavg_list)) { + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); } @@ -1426,86 +1460,86 @@ check_lavg(time_t lim) #else int i = 0; - double l_avg[3]= {0, 0, 0}; + double l_avg[3] = { 0, 0, 0 }; /* first, check if some lines must be executed because of until */ - for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) - if ( (l->l_line->cl_until > 0 || l->l_line->cl_runfreq == 1) - && l->l_until < now) { - if ( ! is_run_if_late(l->l_line->cl_option) ) { - if ( ! is_nolog(l->l_line->cl_option) ) - explain("Interval of execution exceeded : %s (not run)", - l->l_line->cl_shell); - - /* set time of the next execution and send a mail if needed */ - if ( is_td(l->l_line->cl_option) && - is_notice_notrun(l->l_line->cl_option) ) - set_next_exe_notrun(l->l_line, LAVG); - else - set_next_exe(l->l_line, NO_GOTO_LOG, -1); - - /* remove this job from the lavg queue */ - l->l_line->cl_numexe -= 1; - lavg_list_remove_cur(lavg_list); - } - else { - debug("until %s %d", l->l_line->cl_shell, - l->l_until); - run_lavg_job(l); - lavg_list_remove_cur(lavg_list); - } - } + for (l = lavg_list_first(lavg_list); l != NULL; + l = lavg_list_next(lavg_list)) + if ((l->l_line->cl_until > 0 || l->l_line->cl_runfreq == 1) + && l->l_until < now) { + if (!is_run_if_late(l->l_line->cl_option)) { + if (!is_nolog(l->l_line->cl_option)) + explain("Interval of execution exceeded : %s (not run)", + l->l_line->cl_shell); + + /* set time of the next execution and send a mail if needed */ + if (is_td(l->l_line->cl_option) && + is_notice_notrun(l->l_line->cl_option)) + set_next_exe_notrun(l->l_line, LAVG); + else + set_next_exe(l->l_line, NO_GOTO_LOG, -1); + + /* remove this job from the lavg queue */ + l->l_line->cl_numexe -= 1; + lavg_list_remove_cur(lavg_list); + } + else { + debug("until %s %d", l->l_line->cl_shell, l->l_until); + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); + } + } /* we do this set here as the nextexe of lavg line may change before */ tts = time_to_sleep(lim); - if ( lavg_list->num_entries == 0 ) - return tts; - - if ( (i = getloadavg(l_avg, 3)) != 3 ) - debug("got only %d lavg values", i); + if (lavg_list->num_entries == 0) + return tts; + + if ((i = getloadavg(l_avg, 3)) != 3) + debug("got only %d lavg values", i); debug("get_lavg: %lf, %lf, %lf", l_avg[0], l_avg[1], l_avg[2]); /* the 3 values stored in the fcron lines are the real value *= 10 */ l_avg[0] *= 10; l_avg[1] *= 10; l_avg[2] *= 10; - for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) { - /* check if the line should be executed */ - if ( lavg_serial_running >= serial_max_running && - is_serial(l->l_line->cl_option) ) { - continue; - } - if ( ( is_land(l->l_line->cl_option) - && ( l_avg[0] < l->l_line->cl_lavg[0] || l->l_line->cl_lavg[0] == 0 ) - && ( l_avg[1] < l->l_line->cl_lavg[1] || l->l_line->cl_lavg[1] == 0 ) - && ( l_avg[2] < l->l_line->cl_lavg[2] || l->l_line->cl_lavg[2] == 0 ) - ) - || - ( is_lor(l->l_line->cl_option) - && ( l_avg[0] < l->l_line->cl_lavg[0] - || l_avg[1] < l->l_line->cl_lavg[1] - || l_avg[2] < l->l_line->cl_lavg[2] ) - ) - ) { - debug("lavg %s %s %.0f:%d %.0f:%d %.0f:%d", - l->l_line->cl_shell, - (is_lor(l->l_line->cl_option)) ? "or" : "and", - l_avg[0], l->l_line->cl_lavg[0], - l_avg[1], l->l_line->cl_lavg[1], - l_avg[2], l->l_line->cl_lavg[2]); - run_lavg_job(l); - lavg_list_remove_cur(lavg_list); - - } + for (l = lavg_list_first(lavg_list); l != NULL; + l = lavg_list_next(lavg_list)) { + /* check if the line should be executed */ + if (lavg_serial_running >= serial_max_running && + is_serial(l->l_line->cl_option)) { + continue; + } + if ((is_land(l->l_line->cl_option) + && (l_avg[0] < l->l_line->cl_lavg[0] || l->l_line->cl_lavg[0] == 0) + && (l_avg[1] < l->l_line->cl_lavg[1] || l->l_line->cl_lavg[1] == 0) + && (l_avg[2] < l->l_line->cl_lavg[2] || l->l_line->cl_lavg[2] == 0) + ) + || (is_lor(l->l_line->cl_option) + && (l_avg[0] < l->l_line->cl_lavg[0] + || l_avg[1] < l->l_line->cl_lavg[1] + || l_avg[2] < l->l_line->cl_lavg[2]) + ) + ) { + debug("lavg %s %s %.0f:%d %.0f:%d %.0f:%d", + l->l_line->cl_shell, + (is_lor(l->l_line->cl_option)) ? "or" : "and", + l_avg[0], l->l_line->cl_lavg[0], + l_avg[1], l->l_line->cl_lavg[1], l_avg[2], + l->l_line->cl_lavg[2]); + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); + + } } - - if ( lavg_list->num_entries == 0 ) - return tts; + + if (lavg_list->num_entries == 0) + return tts; else - return (LAVG_SLEEP < tts) ? LAVG_SLEEP : tts; - -#endif /* def NOLOADAVG */ + return (LAVG_SLEEP < tts) ? LAVG_SLEEP : tts; + +#endif /* def NOLOADAVG */ } @@ -1519,17 +1553,16 @@ time_to_sleep(time_t lim) time_t ti = time(NULL); /* note : jobs in queue_base are sorted */ - if ( queue_base != NULL ) { - if ( queue_base->j_line->cl_nextexe < lim ) - tts = queue_base->j_line->cl_nextexe; + if (queue_base != NULL) { + if (queue_base->j_line->cl_nextexe < lim) + tts = queue_base->j_line->cl_nextexe; } - + tts = tts - ti; - if ( tts < 0) - tts = 0; + if (tts < 0) + tts = 0; /* debug("Time to sleep: %lds", tts); */ return tts; } - diff --git a/database.h b/database.h index fdbbc72..0c5f520 100644 --- a/database.h +++ b/database.h @@ -32,23 +32,23 @@ extern void wait_all(int *counter); extern time_t time_to_sleep(time_t lim); extern time_t check_lavg(time_t lim); extern void set_next_exe(struct cl_t *line, char option, int info_fd); -#define NO_GOTO 1 /* set_next_exe() : no goto_non_matching() */ -#define NO_GOTO_LOG 2 /* set_next_exe() : NO_GOTO but also log nextexe time */ -#define FROM_CUR_NEXTEXE 4 /* set_next_exe() : compute from nextexe, not now */ +#define NO_GOTO 1 /* set_next_exe() : no goto_non_matching() */ +#define NO_GOTO_LOG 2 /* set_next_exe() : NO_GOTO but also log nextexe time */ +#define FROM_CUR_NEXTEXE 4 /* set_next_exe() : compute from nextexe, not now */ extern void set_next_exe_notrun(struct cl_t *line, char context); -#define LAVG 1 /* set_next_exe_notrun() : context */ -#define SYSDOWN 2 /* set_next_exe_notrun() : context */ -#define QUEUE_FULL 3 /* set_next_exe_notrun() : context */ -#define SYSDOWN_RUNATREBOOT 4 /* set_next_exe_notrun() : context */ +#define LAVG 1 /* set_next_exe_notrun() : context */ +#define SYSDOWN 2 /* set_next_exe_notrun() : context */ +#define QUEUE_FULL 3 /* set_next_exe_notrun() : context */ +#define SYSDOWN_RUNATREBOOT 4 /* set_next_exe_notrun() : context */ extern void mail_notrun(struct cl_t *line, char context, struct tm *since); -extern void mail_notrun_time_t(cl_t *line, char context, time_t since_time_t); -extern job_t * job_queue_remove(cl_t *line); +extern void mail_notrun_time_t(cl_t * line, char context, time_t since_time_t); +extern job_t *job_queue_remove(cl_t * line); extern void insert_nextexe(struct cl_t *line); -extern void run_normal_job(cl_t *line, int fd); +extern void run_normal_job(cl_t * line, int fd); extern void add_serial_job(struct cl_t *line, int fd); extern void add_lavg_job(struct cl_t *line, int fd); extern void run_serial_job(void); -extern int switch_timezone(const char *orig_tz, const char* dest_tz); +extern int switch_timezone(const char *orig_tz, const char *dest_tz); extern void switch_back_timezone(const char *orig_tz); -#endif /* __DATABASE_H__ */ +#endif /* __DATABASE_H__ */ diff --git a/doc/en/changes.sgml b/doc/en/changes.sgml index bc342e8..fd34a60 100644 --- a/doc/en/changes.sgml +++ b/doc/en/changes.sgml @@ -12,6 +12,15 @@ A copy of the license is included in gfdl.sgml. Changes + + From version 3.0.6 to 3.1.1 + + fixed fcrontab edition of *ly lines (hourly, daily, etc) + + + tweaked 'make indent' options and applied + + From version 3.0.6 to 3.1.0 diff --git a/doc/en/todo.sgml b/doc/en/todo.sgml index 2826afb..a06146e 100644 --- a/doc/en/todo.sgml +++ b/doc/en/todo.sgml @@ -24,13 +24,7 @@ A copy of the license is included in gfdl.sgml. High priority - confirm 'make indent' options are good, and apply - - - change git config to fetch tags - - - Make DocBook in vim easier? (at least indentation) + diff --git a/dyncom.h b/dyncom.h index 9adc268..41c1ce7 100644 --- a/dyncom.h +++ b/dyncom.h @@ -78,4 +78,4 @@ #define CMD_SEND_SIGNAL 401 #define CMD_RENICE 402 -#endif /* __DYNCOM_H__ */ +#endif /* __DYNCOM_H__ */ diff --git a/env_list.c b/env_list.c index 5ebc5a2..edeac34 100644 --- a/env_list.c +++ b/env_list.c @@ -31,23 +31,24 @@ #include "fcron.h" #include "env_list.h" -env_list_t *env_list_init(void) +env_list_t * +env_list_init(void) { return (env_list_t *) u_list_init(sizeof(env_t), - ENVVAR_INITIAL_SIZE, ENVVAR_GROW_SIZE); + ENVVAR_INITIAL_SIZE, ENVVAR_GROW_SIZE); } env_list_t * -env_list_copy(env_list_t *list) +env_list_copy(env_list_t * list) { env_list_t *new_list = NULL; env_t *e = NULL; /* copy the list structure */ - new_list = (env_list_t *) u_list_copy( (u_list_t *) list); + new_list = (env_list_t *) u_list_copy((u_list_t *) list); /* for now the new list points to the same data strings - duplicate them */ - for ( e = env_list_first(new_list) ; e != NULL ; e = env_list_next(new_list) ) { + for (e = env_list_first(new_list); e != NULL; e = env_list_next(new_list)) { e->e_envvar = strdup2(e->e_envvar); } @@ -56,80 +57,82 @@ env_list_copy(env_list_t *list) } env_t * -env_list_setenv(env_list_t *list, char *name, char *value, int overwrite) +env_list_setenv(env_list_t * list, char *name, char *value, int overwrite) { env_t e = { NULL }; env_t *c = NULL; - size_t len = strlen(name)+1+strlen(value)+1; /* 1 for '=', 1 for '\0' */ + size_t len = strlen(name) + 1 + strlen(value) + 1; /* 1 for '=', 1 for '\0' */ /* sanity check */ - if ( name == NULL || name[0] == '\0' ) + if (name == NULL || name[0] == '\0') return NULL; /* check if a var 'name' already exists */ - for ( c = env_list_first(list) ; c != NULL ; c = env_list_next(list) ) { - if ( strcmp_until(name, c->e_envvar, '=') == 0 ) { + for (c = env_list_first(list); c != NULL; c = env_list_next(list)) { + if (strcmp_until(name, c->e_envvar, '=') == 0) { /* variable already set: overwrite the value if asked * and return that entry */ - if ( overwrite == 1 ) { - c->e_envvar = realloc_safe(c->e_envvar, len, "new env var value"); + if (overwrite == 1) { + c->e_envvar = + realloc_safe(c->e_envvar, len, "new env var value"); snprintf(c->e_envvar, len, "%s=%s", name, value); } env_list_end_iteration(list); return c; - } + } } /* if we're here we didn't find a var called 'name': add it */ e.e_envvar = alloc_safe(len, "new env var"); snprintf(e.e_envvar, len, "%s=%s", name, value); - return (env_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); + return (env_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) & e); } env_t * -env_list_putenv(env_list_t *list, char *envvar, int overwrite) +env_list_putenv(env_list_t * list, char *envvar, int overwrite) { env_t e = { NULL }; env_t *c = NULL; - size_t len = strlen(envvar) + 1; /* +1 for the terminating '\0' */ + size_t len = strlen(envvar) + 1; /* +1 for the terminating '\0' */ /* sanity check */ - if ( envvar == NULL || envvar[0] == '\0' ) + if (envvar == NULL || envvar[0] == '\0') return NULL; /* check if a var 'name' already exists */ - for ( c = env_list_first(list) ; c != NULL ; c = env_list_next(list) ) { - if ( strcmp_until(envvar, c->e_envvar, '=') == 0 ) { + for (c = env_list_first(list); c != NULL; c = env_list_next(list)) { + if (strcmp_until(envvar, c->e_envvar, '=') == 0) { /* variable already set: overwrite the value if asked * and return that entry */ - if ( overwrite == 1 ) { - c->e_envvar = realloc_safe(c->e_envvar, len, "new env var value"); - memcpy(c->e_envvar, envvar, len); /* includes the final '\0' */ + if (overwrite == 1) { + c->e_envvar = + realloc_safe(c->e_envvar, len, "new env var value"); + memcpy(c->e_envvar, envvar, len); /* includes the final '\0' */ } env_list_end_iteration(list); return c; - } + } } /* if we're here we didn't find a var called 'name': add it */ e.e_envvar = strdup2(envvar); - return (env_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); + return (env_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) & e); } char * -env_list_getenv(env_list_t *list, char *name) +env_list_getenv(env_list_t * list, char *name) { env_t *c = NULL; /* sanity check */ - if ( name == NULL || name[0] == '\0' ) + if (name == NULL || name[0] == '\0') return NULL; - for ( c = env_list_first(list) ; c != NULL ; c = env_list_next(list) ) { - if ( strcmp_until(name, c->e_envvar, '=') == 0 ) { + for (c = env_list_first(list); c != NULL; c = env_list_next(list)) { + if (strcmp_until(name, c->e_envvar, '=') == 0) { /* found the var: return the pointer to the value */ env_list_end_iteration(list); - return (c->e_envvar+strlen(name)+1); /* +1 for '=' */ + return (c->e_envvar + strlen(name) + 1); /* +1 for '=' */ } } @@ -138,25 +141,25 @@ env_list_getenv(env_list_t *list, char *name) } env_t * -env_list_first(env_list_t *list) +env_list_first(env_list_t * list) { return (env_t *) u_list_first((u_list_t *) list); } env_t * -env_list_next(env_list_t *list) +env_list_next(env_list_t * list) { return (env_t *) u_list_next((u_list_t *) list); } void -env_list_end_iteration(env_list_t *list) +env_list_end_iteration(env_list_t * list) { u_list_end_iteration((u_list_t *) list); } env_list_t * -env_list_destroy(env_list_t *list) +env_list_destroy(env_list_t * list) /* free() the memory allocated for list and returns NULL */ { env_t *c = NULL; @@ -164,7 +167,7 @@ env_list_destroy(env_list_t *list) /* make sure the iteration below won't fail in case one was already iterating */ env_list_end_iteration(list); /* free the data in the env_t entries */ - for ( c = env_list_first(list) ; c != NULL ; c = env_list_next(list) ) { + for (c = env_list_first(list); c != NULL; c = env_list_next(list)) { Free_safe(c->e_envvar); } /* free the actual list structure */ @@ -172,7 +175,7 @@ env_list_destroy(env_list_t *list) } char ** -env_list_export_envp(env_list_t *list) +env_list_export_envp(env_list_t * list) /* export list data as a char **envp structure to use as an argument of execle() */ { env_t *c = NULL; @@ -180,14 +183,16 @@ env_list_export_envp(env_list_t *list) char **envp = NULL; /* +1 for the end-of-list NULL */ - envp = alloc_safe((list->num_entries + 1)*sizeof(char *), "environment export"); + envp = + alloc_safe((list->num_entries + 1) * sizeof(char *), + "environment export"); - for ( c=env_list_first(list), i=0 ; c != NULL && i < list->num_entries ; - c=env_list_next(list), i++ ) { + for (c = env_list_first(list), i = 0; c != NULL && i < list->num_entries; + c = env_list_next(list), i++) { envp[i] = strdup2(c->e_envvar); } /* add a NULL as a end-of-list marker */ - envp[ (list->num_entries + 1 ) - 1] = NULL; + envp[(list->num_entries + 1) - 1] = NULL; return envp; } @@ -197,10 +202,9 @@ env_list_free_envp(char **envp) { char *p = NULL; - for ( p = envp[0] ; p != NULL ; p++ ) { + for (p = envp[0]; p != NULL; p++) { Free_safe(p); } Free_safe(envp); } - diff --git a/env_list.h b/env_list.h index fc4a8f0..d19b87b 100644 --- a/env_list.h +++ b/env_list.h @@ -41,22 +41,23 @@ typedef struct u_list_t env_list_t; /* functions prototypes */ extern env_list_t *env_list_init(void); -extern env_list_t *env_list_copy(env_list_t *list); +extern env_list_t *env_list_copy(env_list_t * list); /* WARNING: - These functions are NOT re-entrant. * i.e. there should always be a unique iteration loop based on * u_list_first()/u_list_next() running at any one time in the code * - setenv, putenv, getenv use an iteration internally * so they cannot be called when already iterating */ -extern env_t *env_list_setenv(env_list_t *list, char *name, char *value, int overwrite); -extern env_t *env_list_putenv(env_list_t *list, char *envvar, int overwrite); -extern char *env_list_getenv(env_list_t *list, char *name); -extern env_t *env_list_first(env_list_t *list); -extern env_t *env_list_next(env_list_t *list); -extern void env_list_end_iteration(env_list_t *list); -extern env_list_t *env_list_destroy(env_list_t *list); - -extern char **env_list_export_envp(env_list_t *list); +extern env_t *env_list_setenv(env_list_t * list, char *name, char *value, + int overwrite); +extern env_t *env_list_putenv(env_list_t * list, char *envvar, int overwrite); +extern char *env_list_getenv(env_list_t * list, char *name); +extern env_t *env_list_first(env_list_t * list); +extern env_t *env_list_next(env_list_t * list); +extern void env_list_end_iteration(env_list_t * list); +extern env_list_t *env_list_destroy(env_list_t * list); + +extern char **env_list_export_envp(env_list_t * list); extern void env_list_free_envp(char **envp); -#endif /* __ENV_LIST_H__ */ +#endif /* __ENV_LIST_H__ */ diff --git a/exe_list.c b/exe_list.c index e4b6dc1..1cc8f09 100644 --- a/exe_list.c +++ b/exe_list.c @@ -31,54 +31,55 @@ #include "fcron.h" #include "exe_list.h" -exe_list_t *exe_list_init(void) +exe_list_t * +exe_list_init(void) { - return (exe_list_t *) u_list_init(sizeof(exe_t), EXE_INITIAL_SIZE, EXE_GROW_SIZE); + return (exe_list_t *) u_list_init(sizeof(exe_t), EXE_INITIAL_SIZE, + EXE_GROW_SIZE); } exe_t * -exe_list_add_line(exe_list_t *list, struct cl_t *line) +exe_list_add_line(exe_list_t * list, struct cl_t *line) { - exe_t e = { NULL, 0, 0}; - e.e_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/ + exe_t e = { NULL, 0, 0 }; + e.e_line = line; /* ANSI C does not allow us to directly replace NULL by line above */ - return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); + return (exe_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) & e); } exe_t * -exe_list_add(exe_list_t *list, exe_t *e) +exe_list_add(exe_list_t * list, exe_t * e) { - return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) e); + return (exe_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) e); } exe_t * -exe_list_first(exe_list_t *list) +exe_list_first(exe_list_t * list) { return (exe_t *) u_list_first((u_list_t *) list); } exe_t * -exe_list_next(exe_list_t *list) +exe_list_next(exe_list_t * list) { return (exe_t *) u_list_next((u_list_t *) list); } void -exe_list_end_iteration(exe_list_t *list) +exe_list_end_iteration(exe_list_t * list) { u_list_end_iteration((u_list_t *) list); } void -exe_list_remove_cur(exe_list_t *list) +exe_list_remove_cur(exe_list_t * list) { u_list_remove_cur((u_list_t *) list); } exe_list_t * -exe_list_destroy(exe_list_t *list) +exe_list_destroy(exe_list_t * list) /* free() the memory allocated for list and returns NULL */ { return (exe_list_t *) u_list_destroy((u_list_t *) list); } - diff --git a/exe_list.h b/exe_list.h index 546d408..6aaeee7 100644 --- a/exe_list.h +++ b/exe_list.h @@ -35,23 +35,23 @@ /* Entry to describe one job being executed */ typedef struct exe_t { struct cl_t *e_line; - pid_t e_ctrl_pid; /* pid of the fcron process controling the job */ - pid_t e_job_pid; /* pid of the job itself */ + pid_t e_ctrl_pid; /* pid of the fcron process controling the job */ + pid_t e_job_pid; /* pid of the job itself */ } exe_t; typedef struct u_list_t exe_list_t; /* functions prototypes */ extern exe_list_t *exe_list_init(void); -extern exe_t *exe_list_add_line(exe_list_t *list, struct cl_t *line); -extern exe_t *exe_list_add(exe_list_t *list, exe_t *e); +extern exe_t *exe_list_add_line(exe_list_t * list, struct cl_t *line); +extern exe_t *exe_list_add(exe_list_t * list, exe_t * e); /* WARNING: there should always be a unique iteration loop based on * u_list_first()/u_list_next() running at any one time in the code */ -extern exe_t *exe_list_first(exe_list_t *list); -extern exe_t *exe_list_next(exe_list_t *list); -extern void exe_list_end_iteration(exe_list_t *list); -extern void exe_list_remove_cur(exe_list_t *list); -extern exe_list_t *exe_list_destroy(exe_list_t *list); +extern exe_t *exe_list_first(exe_list_t * list); +extern exe_t *exe_list_next(exe_list_t * list); +extern void exe_list_end_iteration(exe_list_t * list); +extern void exe_list_remove_cur(exe_list_t * list); +extern exe_list_t *exe_list_destroy(exe_list_t * list); -#endif /* __EXE_LIST_H__ */ +#endif /* __EXE_LIST_H__ */ diff --git a/exe_list_test.c b/exe_list_test.c index a1210f0..b2f656b 100644 --- a/exe_list_test.c +++ b/exe_list_test.c @@ -10,18 +10,25 @@ char foreground = 1; pid_t daemon_pid = 0; uid_t rootuid = 0; -void print_cur(exe_t *e) { - printf("Current entry's shell command: %s\n", e?e->e_line->cl_shell:"NULL"); +void +print_cur(exe_t * e) +{ + printf("Current entry's shell command: %s\n", + e ? e->e_line->cl_shell : "NULL"); } -void print_list(exe_list_t *list) { +void +print_list(exe_list_t * list) +{ exe_t *e = NULL; printf("Current list:\n"); - for ( e = exe_list_first(list) ; e != NULL ; e = exe_list_next(list) ) - printf(" Shell command: %s\n", e?e->e_line->cl_shell:"NULL"); + for (e = exe_list_first(list); e != NULL; e = exe_list_next(list)) + printf(" Shell command: %s\n", e ? e->e_line->cl_shell : "NULL"); } -int main(int argc, char *argv[]) { +int +main(int argc, char *argv[]) +{ exe_list_t *list = NULL; exe_t *e = NULL; cl_t l1, l2, l3, l4, l5, l6, l7; @@ -37,75 +44,114 @@ int main(int argc, char *argv[]) { list = exe_list_init(); /* trigger a resize of the list during an iteration */ - printf("Adding l1...\n"); exe_list_add_line(list, &l1); - printf("Adding l2...\n"); exe_list_add_line(list, &l2); - printf("Adding l3...\n"); exe_list_add_line(list, &l3); - e = exe_list_first(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - printf("Adding l4...\n"); exe_list_add_line(list, &l4); - printf("Adding l5...\n"); exe_list_add_line(list, &l5); - printf("Adding l6...\n"); exe_list_add_line(list, &l6); - printf("Adding l7...\n"); exe_list_add_line(list, &l7); - - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); + printf("Adding l1...\n"); + exe_list_add_line(list, &l1); + printf("Adding l2...\n"); + exe_list_add_line(list, &l2); + printf("Adding l3...\n"); + exe_list_add_line(list, &l3); + e = exe_list_first(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + printf("Adding l4...\n"); + exe_list_add_line(list, &l4); + printf("Adding l5...\n"); + exe_list_add_line(list, &l5); + printf("Adding l6...\n"); + exe_list_add_line(list, &l6); + printf("Adding l7...\n"); + exe_list_add_line(list, &l7); + + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); /* "standard" iteration: */ print_list(list); /* remove item at the beginning and middle of the list + add an item which is already in there */ printf("removing l1, l3, adding l2\n"); - e = exe_list_first(list); print_cur(e); - printf("Removing l1...\n"); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); /* this one will be the item replacing l1 */ - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - printf("Removing l3...\n"); exe_list_remove_cur(list); + e = exe_list_first(list); + print_cur(e); + printf("Removing l1...\n"); + exe_list_remove_cur(list); + e = exe_list_next(list); + print_cur(e); /* this one will be the item replacing l1 */ + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + printf("Removing l3...\n"); + exe_list_remove_cur(list); exe_list_end_iteration(list); - printf("Adding l2...\n"); exe_list_add_line(list, &l2); /* we suppose the list array won't be reallocated() */ + printf("Adding l2...\n"); + exe_list_add_line(list, &l2); /* we suppose the list array won't be reallocated() */ print_list(list); /* remove an item at the end of the list: */ printf("removing l5, l2\n"); - e = exe_list_first(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - printf("Removing l5...\n"); exe_list_remove_cur(list); + e = exe_list_first(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + printf("Removing l5...\n"); + exe_list_remove_cur(list); exe_list_end_iteration(list); - e = exe_list_first(list); print_cur(e); - e = exe_list_next(list); print_cur(e); - printf("Removing l2...\n");exe_list_remove_cur(list); + e = exe_list_first(list); + print_cur(e); + e = exe_list_next(list); + print_cur(e); + printf("Removing l2...\n"); + exe_list_remove_cur(list); exe_list_end_iteration(list); print_list(list); - printf("Adding l1...\n"); exe_list_add_line(list, &l1); + printf("Adding l1...\n"); + exe_list_add_line(list, &l1); print_list(list); printf("empty the list\n"); - e = exe_list_first(list); print_cur(e); + e = exe_list_first(list); + print_cur(e); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); + e = exe_list_next(list); + print_cur(e); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); + e = exe_list_next(list); + print_cur(e); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); + e = exe_list_next(list); + print_cur(e); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); + e = exe_list_next(list); + print_cur(e); exe_list_remove_cur(list); - e = exe_list_next(list); print_cur(e); + e = exe_list_next(list); + print_cur(e); print_list(list); - printf("Destroying the list...\n"); list = exe_list_destroy(list); + printf("Destroying the list...\n"); + list = exe_list_destroy(list); return 0; diff --git a/fcron.c b/fcron.c index 62edf3d..391d4c3 100644 --- a/fcron.c +++ b/fcron.c @@ -52,16 +52,16 @@ void create_spooldir(char *dir); /* command line options */ #ifdef FOREGROUND -char foreground = 1; /* set to 1 when we are on foreground, else 0 */ +char foreground = 1; /* set to 1 when we are on foreground, else 0 */ #else -char foreground = 0; /* set to 1 when we are on foreground, else 0 */ +char foreground = 0; /* set to 1 when we are on foreground, else 0 */ #endif time_t first_sleep = FIRST_SLEEP; time_t save_time = SAVE; -char once = 0; /* set to 1 if fcron shall return immediately after running - * all jobs that are due at the time when fcron is started */ -char dosyslog = 1; /* set to 1 when we log messages to syslog, else 0 */ +char once = 0; /* set to 1 if fcron shall return immediately after running + * all jobs that are due at the time when fcron is started */ +char dosyslog = 1; /* set to 1 when we log messages to syslog, else 0 */ /* Get the default locale character set for the mail * "Content-Type: ...; charset=" header */ @@ -72,7 +72,7 @@ char *tmp_path = ""; /* process identity */ pid_t daemon_pid; -mode_t saved_umask; /* default root umask */ +mode_t saved_umask; /* default root umask */ char *prog_name = NULL; char *orig_tz_envvar = NULL; @@ -83,33 +83,33 @@ uid_t rootuid = 0; gid_t rootgid = 0; /* have we got a signal ? */ -char sig_conf = 0; /* is 1 when we got a SIGHUP, 2 for a SIGUSR1 */ -char sig_chld = 0; /* is 1 when we got a SIGCHLD */ -char sig_debug = 0; /* is 1 when we got a SIGUSR2 */ +char sig_conf = 0; /* is 1 when we got a SIGHUP, 2 for a SIGUSR1 */ +char sig_chld = 0; /* is 1 when we got a SIGCHLD */ +char sig_debug = 0; /* is 1 when we got a SIGUSR2 */ /* jobs database */ struct cf_t *file_base; /* point to the first file of the list */ struct job_t *queue_base; /* ordered list of normal jobs to be run */ -unsigned long int next_id; /* id for next line to enter database */ +unsigned long int next_id; /* id for next line to enter database */ struct cl_t **serial_array; /* ordered list of job to be run one by one */ -short int serial_array_size; /* size of serial_array */ -short int serial_array_index; /* the index of the first job */ -short int serial_num; /* number of job being queued */ -short int serial_running; /* number of running serial jobs */ +short int serial_array_size; /* size of serial_array */ +short int serial_array_index; /* the index of the first job */ +short int serial_num; /* number of job being queued */ +short int serial_running; /* number of running serial jobs */ /* do not run more than this number of serial job simultaneously */ -short int serial_max_running = SERIAL_MAX_RUNNING; -short int serial_queue_max = SERIAL_QUEUE_MAX; +short int serial_max_running = SERIAL_MAX_RUNNING; +short int serial_queue_max = SERIAL_QUEUE_MAX; -lavg_list_t *lavg_list; /* jobs waiting for a given system load value */ +lavg_list_t *lavg_list; /* jobs waiting for a given system load value */ short int lavg_queue_max = LAVG_QUEUE_MAX; -short int lavg_serial_running;/* number of serialized lavg job being running */ +short int lavg_serial_running; /* number of serialized lavg job being running */ -exe_list_t *exe_list; /* jobs which are executed */ +exe_list_t *exe_list; /* jobs which are executed */ -time_t begin_sleep; /* the time at which sleep began */ -time_t now; /* the current time */ +time_t begin_sleep; /* the time at which sleep began */ +time_t now; /* the current time */ #ifdef HAVE_LIBPAM pam_handle_t *pamh = NULL; @@ -122,11 +122,10 @@ info(void) * version, license */ { fprintf(stderr, - "fcron " VERSION_QUOTED " - periodic command scheduler\n" - "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" - "This program is free software distributed WITHOUT ANY WARRANTY.\n" - "See the GNU General Public License for more details.\n" - ); + "fcron " VERSION_QUOTED " - periodic command scheduler\n" + "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" + "This program is free software distributed WITHOUT ANY WARRANTY.\n" + "See the GNU General Public License for more details.\n"); exit(EXIT_OK); @@ -138,26 +137,25 @@ usage(void) /* print a help message about command line options and exit */ { fprintf(stderr, "\nfcron " VERSION_QUOTED "\n\n" - "fcron [-d] [-f] [-b]\n" - "fcron -h\n" - " -s t --savetime t Save fcrontabs on disk every t sec.\n" - " -l t --firstsleep t Sets the initial delay before any job is executed" - ",\n default to %d seconds.\n" - " -m n --maxserial n Set to n the max number of running serial jobs.\n" - " -c f --configfile f Make fcron use config file f.\n" - " -n d --newspooldir d Create d as a new spool directory.\n" - " -f --foreground Stay in foreground.\n" - " -b --background Go to background.\n" - " -y --nosyslog Don't log to syslog at all.\n" - " -o --once Execute all jobs that need to be run, wait for " - "them,\n then return. Sets firstsleep to 0.\n" - " Especially useful with -f and -y.\n" - " -d --debug Set Debug mode.\n" - " -h --help Show this help message.\n" - " -V --version Display version & infos about fcron.\n", - FIRST_SLEEP - ); - + "fcron [-d] [-f] [-b]\n" + "fcron -h\n" + " -s t --savetime t Save fcrontabs on disk every t sec.\n" + " -l t --firstsleep t Sets the initial delay before any job is executed" + ",\n default to %d seconds.\n" + " -m n --maxserial n Set to n the max number of running serial jobs.\n" + " -c f --configfile f Make fcron use config file f.\n" + " -n d --newspooldir d Create d as a new spool directory.\n" + " -f --foreground Stay in foreground.\n" + " -b --background Go to background.\n" + " -y --nosyslog Don't log to syslog at all.\n" + " -o --once Execute all jobs that need to be run, wait for " + "them,\n then return. Sets firstsleep to 0.\n" + " Especially useful with -f and -y.\n" + " -d --debug Set Debug mode.\n" + " -h --help Show this help message.\n" + " -V --version Display version & infos about fcron.\n", + FIRST_SLEEP); + exit(EXIT_ERR); } @@ -172,23 +170,23 @@ print_schedule(void) explain("Printing schedule ..."); for (cf = file_base; cf; cf = cf->cf_next) { - explain(" File %s", cf->cf_user); - for (cl = cf->cf_line_base; cl; cl = cl->cl_next) { - ftime = localtime( &(cl->cl_nextexe) ); - explain(" cmd %s next exec %d/%d/%d wday:%d %02d:%02d" - " (system time)", - cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday, - (ftime->tm_year + 1900), ftime->tm_wday, - ftime->tm_hour, ftime->tm_min); - - } + explain(" File %s", cf->cf_user); + for (cl = cf->cf_line_base; cl; cl = cl->cl_next) { + ftime = localtime(&(cl->cl_nextexe)); + explain(" cmd %s next exec %d/%d/%d wday:%d %02d:%02d" + " (system time)", + cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday, + (ftime->tm_year + 1900), ftime->tm_wday, + ftime->tm_hour, ftime->tm_min); + + } } explain("... end of printing schedule."); } -void -xexit(int exit_value) +void +xexit(int exit_value) /* exit after having freed memory and removed lock file */ { cf_t *f = NULL; @@ -199,29 +197,29 @@ xexit(int exit_value) * job being executed because we might get a SIGKILL * if we don't exit quickly */ save_file(NULL); - + #ifdef FCRONDYN close_socket(); #endif f = file_base; - while ( f != NULL ) { - if ( f->cf_running > 0 ) { - /* */ - debug("waiting jobs for %s ...", f->cf_user); - /* */ - wait_all( &f->cf_running ); - save_file(f); - } - delete_file(f->cf_user); - - /* delete_file remove the f file from the list : - * next file to remove is now pointed by file_base. */ - f = file_base; + while (f != NULL) { + if (f->cf_running > 0) { + /* */ + debug("waiting jobs for %s ...", f->cf_user); + /* */ + wait_all(&f->cf_running); + save_file(f); + } + delete_file(f->cf_user); + + /* delete_file remove the f file from the list : + * next file to remove is now pointed by file_base. */ + f = file_base; } remove(pidfile); - + exe_list_destroy(exe_list); lavg_list_destroy(lavg_list); free_conf(); @@ -229,7 +227,7 @@ xexit(int exit_value) Free_safe(orig_tz_envvar); explain("Exiting with code %d", exit_value); - exit (exit_value); + exit(exit_value); } @@ -243,31 +241,32 @@ get_lock() FILE *daemon_lockfp = NULL; int fd; - if (((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 ) - || ((daemon_lockfp = fdopen(fd, "r+"))) == NULL) - die_e("can't open or create %s", pidfile); - + if (((fd = open(pidfile, O_RDWR | O_CREAT, 0644)) == -1) + || ((daemon_lockfp = fdopen(fd, "r+"))) == NULL) + die_e("can't open or create %s", pidfile); + #ifdef HAVE_FLOCK - if ( flock(fd, LOCK_EX|LOCK_NB) != 0 ) -#else /* HAVE_FLOCK */ - if ( lockf(fileno(daemon_lockfp), F_TLOCK, 0) != 0 ) -#endif /* ! HAVE_FLOCK */ - { - if ( fscanf(daemon_lockfp, "%d", &otherpid) >= 1 ) - die_e("can't lock %s, running daemon's pid may be %d", - pidfile, otherpid); - else - die_e("can't lock %s, and unable to read running" - " daemon's pid", pidfile); - } + if (flock(fd, LOCK_EX | LOCK_NB) != 0) +#else /* HAVE_FLOCK */ + if (lockf(fileno(daemon_lockfp), F_TLOCK, 0) != 0) +#endif /* ! HAVE_FLOCK */ + { + if (fscanf(daemon_lockfp, "%d", &otherpid) >= 1) + die_e("can't lock %s, running daemon's pid may be %d", pidfile, + otherpid); + else + die_e("can't lock %s, and unable to read running" + " daemon's pid", pidfile); + } fcntl(fd, F_SETFD, 1); rewind(daemon_lockfp); - fprintf(daemon_lockfp, "%d\n", (int) daemon_pid); + fprintf(daemon_lockfp, "%d\n", (int)daemon_pid); fflush(daemon_lockfp); - if ( ftruncate(fileno(daemon_lockfp), ftell(daemon_lockfp)) < 0 ) - error_e("Unable to ftruncate(fileno(daemon_lockfp), ftell(daemon_lockfp))"); + if (ftruncate(fileno(daemon_lockfp), ftell(daemon_lockfp)) < 0) + error_e + ("Unable to ftruncate(fileno(daemon_lockfp), ftell(daemon_lockfp))"); /* abandon fd and daemon_lockfp even though the file is open. we need to * keep it open and locked, but we don't need the handles elsewhere. @@ -306,113 +305,123 @@ parseopt(int argc, char *argv[]) int i; #ifdef HAVE_GETOPT_LONG - static struct option opt[] = - { - {"debug", 0, NULL, 'd'}, - {"foreground", 0, NULL, 'f'}, - {"background", 0, NULL, 'b'}, - {"nosyslog", 0, NULL, 'y'}, - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'V'}, - {"once", 0, NULL, 'o'}, - {"savetime", 1, NULL, 's'}, - {"firstsleep", 1, NULL, 'l'}, - {"maxserial", 1, NULL, 'm'}, - {"configfile", 1, NULL, 'c'}, - {"newspooldir", 1, NULL, 'n'}, - {"queuelen", 1, NULL, 'q'}, - {0,0,0,0} + static struct option opt[] = { + {"debug", 0, NULL, 'd'}, + {"foreground", 0, NULL, 'f'}, + {"background", 0, NULL, 'b'}, + {"nosyslog", 0, NULL, 'y'}, + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'V'}, + {"once", 0, NULL, 'o'}, + {"savetime", 1, NULL, 's'}, + {"firstsleep", 1, NULL, 'l'}, + {"maxserial", 1, NULL, 'm'}, + {"configfile", 1, NULL, 'c'}, + {"newspooldir", 1, NULL, 'n'}, + {"queuelen", 1, NULL, 'q'}, + {0, 0, 0, 0} }; -#endif /* HAVE_GETOPT_LONG */ +#endif /* HAVE_GETOPT_LONG */ extern char *optarg; extern int optind, opterr, optopt; /* constants and variables defined by command line */ - while(1) { + while (1) { #ifdef HAVE_GETOPT_LONG - c = getopt_long(argc, argv, "dfbyhVos:l:m:c:n:q:", opt, NULL); + c = getopt_long(argc, argv, "dfbyhVos:l:m:c:n:q:", opt, NULL); #else - c = getopt(argc, argv, "dfbyhVos:l:m:c:n:q:"); -#endif /* HAVE_GETOPT_LONG */ - if ( c == EOF ) break; - switch ( (char)c ) { - - case 'V': - info(); break; - - case 'h': - usage(); break; - - case 'd': - debug_opt = 1; break; - - case 'f': - foreground = 1; break; - - case 'b': - foreground = 0; break; - - case 'y': - dosyslog = 0; break; - - case 'o': - once = 1; first_sleep = 0; break; - - case 's': - if ( (save_time = strtol(optarg, NULL, 10)) < 60 || save_time >= LONG_MAX ) - die("Save time can only be set between 60 and %d.", LONG_MAX); - break; - - case 'l': - if ( (first_sleep = strtol(optarg, NULL, 10)) < 0 || first_sleep >= LONG_MAX) - die("First sleep can only be set between 0 and %d.", LONG_MAX); - break; - - case 'm': - if ( (serial_max_running = strtol(optarg, NULL, 10)) <= 0 - || serial_max_running >= SHRT_MAX ) - die("Max running can only be set between 1 and %d.",SHRT_MAX); - break; - - case 'c': - Set(fcronconf, optarg); - break; - - case 'n': - create_spooldir(optarg); - break; - - case 'q': - if ( (lavg_queue_max = serial_queue_max = strtol(optarg, NULL, 10)) < 5 - || serial_queue_max >= SHRT_MAX ) - die("Queue length can only be set between 5 and %d.", SHRT_MAX); - break; - - case ':': - error("(parseopt) Missing parameter"); - usage(); - - case '?': - usage(); - - default: - warn("(parseopt) Warning: getopt returned %c", c); - } + c = getopt(argc, argv, "dfbyhVos:l:m:c:n:q:"); +#endif /* HAVE_GETOPT_LONG */ + if (c == EOF) + break; + switch ((char)c) { + + case 'V': + info(); + break; + + case 'h': + usage(); + break; + + case 'd': + debug_opt = 1; + break; + + case 'f': + foreground = 1; + break; + + case 'b': + foreground = 0; + break; + + case 'y': + dosyslog = 0; + break; + + case 'o': + once = 1; + first_sleep = 0; + break; + + case 's': + if ((save_time = strtol(optarg, NULL, 10)) < 60 + || save_time >= LONG_MAX) + die("Save time can only be set between 60 and %d.", LONG_MAX); + break; + + case 'l': + if ((first_sleep = strtol(optarg, NULL, 10)) < 0 + || first_sleep >= LONG_MAX) + die("First sleep can only be set between 0 and %d.", LONG_MAX); + break; + + case 'm': + if ((serial_max_running = strtol(optarg, NULL, 10)) <= 0 + || serial_max_running >= SHRT_MAX) + die("Max running can only be set between 1 and %d.", SHRT_MAX); + break; + + case 'c': + Set(fcronconf, optarg); + break; + + case 'n': + create_spooldir(optarg); + break; + + case 'q': + if ((lavg_queue_max = serial_queue_max = + strtol(optarg, NULL, 10)) < 5 || serial_queue_max >= SHRT_MAX) + die("Queue length can only be set between 5 and %d.", SHRT_MAX); + break; + + case ':': + error("(parseopt) Missing parameter"); + usage(); + + case '?': + usage(); + + default: + warn("(parseopt) Warning: getopt returned %c", c); + } } if (optind < argc) { - for (i = optind; i<=argc; i++) - error("Unknown argument \"%s\"", argv[i]); - usage(); + for (i = optind; i <= argc; i++) + error("Unknown argument \"%s\"", argv[i]); + usage(); } return OK; } -void +void create_spooldir(char *dir) /* create a new spool dir for fcron : set correctly its mode and owner */ { @@ -421,30 +430,32 @@ create_spooldir(char *dir) uid_t useruid = get_user_uid_safe(USERNAME); gid_t usergid = get_group_gid_safe(GROUPNAME); - if ( mkdir(dir, 0) != 0 && errno != EEXIST ) - die_e("Cannot create dir %s", dir); + if (mkdir(dir, 0) != 0 && errno != EEXIST) + die_e("Cannot create dir %s", dir); - if ( (dir_fd = open(dir, 0)) < 0 ) - die_e("Cannot open dir %s", dir); + if ((dir_fd = open(dir, 0)) < 0) + die_e("Cannot open dir %s", dir); - if ( fstat(dir_fd, &st) != 0 ) { - close(dir_fd); - die_e("Cannot fstat %s", dir); + if (fstat(dir_fd, &st) != 0) { + close(dir_fd); + die_e("Cannot fstat %s", dir); } - if ( ! S_ISDIR(st.st_mode) ) { - close(dir_fd); - die("%s exists and is not a directory", dir); + if (!S_ISDIR(st.st_mode)) { + close(dir_fd); + die("%s exists and is not a directory", dir); } - if ( fchown(dir_fd, useruid, usergid) != 0 ) { - close(dir_fd); - die_e("Cannot fchown dir %s to %s:%s", dir, USERNAME, GROUPNAME); + if (fchown(dir_fd, useruid, usergid) != 0) { + close(dir_fd); + die_e("Cannot fchown dir %s to %s:%s", dir, USERNAME, GROUPNAME); } - if (fchmod(dir_fd, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP) != 0) { - close(dir_fd); - die_e("Cannot change dir %s's mode to 770", dir); + if (fchmod + (dir_fd, + S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP) != 0) { + close(dir_fd); + die_e("Cannot change dir %s's mode to 770", dir); } close(dir_fd); @@ -468,9 +479,9 @@ sighup_handler(int x) /* update configuration */ { /* we don't call the synchronize_dir() function directly, - because it may cause some problems if this signal - is not received during the sleep - */ + * because it may cause some problems if this signal + * is not received during the sleep + */ sig_conf = 1; } @@ -478,7 +489,7 @@ RETSIGTYPE sigchild_handler(int x) /* call wait_chld() to take care of finished jobs */ { - + sig_chld = 1; } @@ -489,9 +500,9 @@ sigusr1_handler(int x) /* reload all configurations */ { /* we don't call the synchronize_dir() function directly, - because it may cause some problems if this signal - is not received during the sleep - */ + * because it may cause some problems if this signal + * is not received during the sleep + */ sig_conf = 2; } @@ -518,13 +529,15 @@ main(int argc, char **argv) /* parse options */ - if ( strrchr(argv[0], '/') == NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0], '/') + 1; + if (strrchr(argv[0], '/') == NULL) + prog_name = argv[0]; + else + prog_name = strrchr(argv[0], '/') + 1; { - uid_t daemon_uid; - if ( (daemon_uid = getuid()) != rootuid ) - die("Fcron must be executed as root"); + uid_t daemon_uid; + if ((daemon_uid = getuid()) != rootuid) + die("Fcron must be executed as root"); } /* we have to set daemon_pid before the fork because it's @@ -542,73 +555,74 @@ main(int argc, char **argv) /* change directory */ if (chdir(fcrontabs) != 0) - die_e("Could not change dir to %s", fcrontabs); - + die_e("Could not change dir to %s", fcrontabs); + /* Get the default locale character set for the mail * "Content-Type: ...; charset=" header */ - setlocale(LC_ALL,""); /* set locale to system defaults or to - that specified by any LC_* env vars */ + setlocale(LC_ALL, ""); /* set locale to system defaults or to + * that specified by any LC_* env vars */ /* Except that "US-ASCII" is preferred to "ANSI_x3.4-1968" in MIME, * even though "ANSI_x3.4-1968" is the official charset name. */ - if ( (codeset = nl_langinfo(CODESET)) != 0L && - strcmp(codeset, "ANSI_x3.4-1968") != 0 ) + if ((codeset = nl_langinfo(CODESET)) != 0L && + strcmp(codeset, "ANSI_x3.4-1968") != 0) strncpy(default_mail_charset, codeset, sizeof(default_mail_charset)); else strcpy(default_mail_charset, "US-ASCII"); - if ( freopen("/dev/null", "r", stdin) == NULL ) + if (freopen("/dev/null", "r", stdin) == NULL) error_e("Could not open /dev/null as stdin"); if (foreground == 0) { - /* close stdout and stderr. - * close unused descriptors - * optional detach from controlling terminal */ - - int fd; - pid_t pid; - - switch ( pid = fork() ) { - case -1: - die_e("fork"); - break; - case 0: - /* child */ - break; - default: - /* parent */ + /* close stdout and stderr. + * close unused descriptors + * optional detach from controlling terminal */ + + int fd; + pid_t pid; + + switch (pid = fork()) { + case -1: + die_e("fork"); + break; + case 0: + /* child */ + break; + default: + /* parent */ /* printf("%s[%d] " VERSION_QUOTED " : started.\n", */ /* prog_name, pid); */ - exit(0); - } + exit(0); + } - daemon_pid = getpid(); + daemon_pid = getpid(); - if ((fd = open("/dev/tty", O_RDWR)) >= 0) { + if ((fd = open("/dev/tty", O_RDWR)) >= 0) { #ifndef _HPUX_SOURCE - ioctl(fd, TIOCNOTTY, 0); + ioctl(fd, TIOCNOTTY, 0); #endif - close(fd); - } - - if ( freopen("/dev/null", "w", stdout) == NULL ) + close(fd); + } + + if (freopen("/dev/null", "w", stdout) == NULL) error_e("Could not open /dev/null as stdout"); - if ( freopen("/dev/null", "w", stderr) == NULL ) + if (freopen("/dev/null", "w", stderr) == NULL) error_e("Could not open /dev/null as stderr"); - /* close most other open fds */ - xcloselog(); - for(fd = 3; fd < 250; fd++) (void) close(fd); + /* close most other open fds */ + xcloselog(); + for (fd = 3; fd < 250; fd++) + (void)close(fd); - /* finally, create a new session */ - if ( setsid() == -1 ) - error("Could not setsid()"); + /* finally, create a new session */ + if (setsid() == -1) + error("Could not setsid()"); } /* check if another fcron daemon is running, create pid file and lock it */ get_lock(); - + /* this program belongs to root : we set default permission mode * to 600 for security reasons, but we reset them to the saved * umask just before we run a job */ @@ -648,7 +662,8 @@ main(int argc, char **argv) serial_array_index = 0; serial_num = 0; serial_array_size = SERIAL_INITIAL_SIZE; - serial_array = alloc_safe(serial_array_size*sizeof(cl_t *), "serial_array"); + serial_array = + alloc_safe(serial_array_size * sizeof(cl_t *), "serial_array"); /* initialize lavg_array */ lavg_list = lavg_list_init(); @@ -665,22 +680,22 @@ main(int argc, char **argv) /* we use the hostname and tv_usec in order to get different seeds * on two different machines starting fcron at the same moment */ { - char hostname[50]; - int i; - unsigned int seed; + char hostname[50]; + int i; + unsigned int seed; #ifdef HAVE_GETTIMEOFDAY - struct timeval tv; /* we use usec field to get more precision */ - gettimeofday(&tv, NULL); - seed = ((unsigned int) tv.tv_usec) ^ ((unsigned int) tv.tv_sec); + struct timeval tv; /* we use usec field to get more precision */ + gettimeofday(&tv, NULL); + seed = ((unsigned int)tv.tv_usec) ^ ((unsigned int)tv.tv_sec); #else - seed = (unsigned int) time(NULL); + seed = (unsigned int)time(NULL); #endif - gethostname(hostname, sizeof(hostname)); + gethostname(hostname, sizeof(hostname)); - for ( i = 0; i < sizeof(hostname) - sizeof(seed); i += sizeof(seed) ) - seed ^= (unsigned int) *(hostname+i); + for (i = 0; i < sizeof(hostname) - sizeof(seed); i += sizeof(seed)) + seed ^= (unsigned int)*(hostname + i); - srand(seed); + srand(seed); } main_loop(); @@ -699,43 +714,43 @@ check_signal() * as it is not supported on some systems (HP-UX) and makes fcron crash */ if (sig_chld > 0) { - wait_chld(); - sig_chld = 0; + wait_chld(); + sig_chld = 0; #ifdef HAVE_SIGNAL - (void)signal(SIGCHLD, sigchild_handler); - siginterrupt(SIGCHLD, 0); + (void)signal(SIGCHLD, sigchild_handler); + siginterrupt(SIGCHLD, 0); #endif } if (sig_conf > 0) { - if (sig_conf == 1) { - /* update configuration */ - synchronize_dir(".", 0); - sig_conf = 0; + if (sig_conf == 1) { + /* update configuration */ + synchronize_dir(".", 0); + sig_conf = 0; #ifdef HAVE_SIGNAL - signal(SIGHUP, sighup_handler); - siginterrupt(SIGHUP, 0); + signal(SIGHUP, sighup_handler); + siginterrupt(SIGHUP, 0); #endif - } - else { - /* reload all configuration */ - reload_all("."); - sig_conf = 0; + } + else { + /* reload all configuration */ + reload_all("."); + sig_conf = 0; #ifdef HAVE_SIGNAL - signal(SIGUSR1, sigusr1_handler); - siginterrupt(SIGUSR1, 0); + signal(SIGUSR1, sigusr1_handler); + siginterrupt(SIGUSR1, 0); #endif - } + } } if (sig_debug > 0) { - print_schedule(); - debug_opt = (debug_opt > 0)? 0 : 1; - explain("debug_opt = %d", debug_opt); - sig_debug = 0; + print_schedule(); + debug_opt = (debug_opt > 0) ? 0 : 1; + explain("debug_opt = %d", debug_opt); + sig_debug = 0; #ifdef HAVE_SIGNAL - signal(SIGUSR2, sigusr2_handler); - siginterrupt(SIGUSR2, 0); + signal(SIGUSR2, sigusr2_handler); + siginterrupt(SIGUSR2, 0); #endif } @@ -746,11 +761,11 @@ main_loop() /* main loop - get the time to sleep until next job execution, * sleep, and then test all jobs and execute if needed. */ { - time_t save; /* time remaining until next save */ - time_t stime; /* time to sleep until next job - * execution */ + time_t save; /* time remaining until next save */ + time_t stime; /* time to sleep until next job + * execution */ #ifdef HAVE_GETTIMEOFDAY - struct timeval tv; /* we use usec field to get more precision */ + struct timeval tv; /* we use usec field to get more precision */ #endif #ifdef FCRONDYN int retcode = 0; @@ -765,73 +780,74 @@ main_loop() /* synchronize save with jobs execution */ save = now + save_time; - if ( serial_num > 0 || once ) - stime = first_sleep; - else if ( (stime = time_to_sleep(save)) < first_sleep ) - /* force first execution after first_sleep sec : execution of jobs - * during system boot time is not what we want */ - stime = first_sleep; + if (serial_num > 0 || once) + stime = first_sleep; + else if ((stime = time_to_sleep(save)) < first_sleep) + /* force first execution after first_sleep sec : execution of jobs + * during system boot time is not what we want */ + stime = first_sleep; debug("initial sleep time : %ld", stime); for (;;) { - + #ifdef HAVE_GETTIMEOFDAY #ifdef FCRONDYN - gettimeofday(&tv, NULL); - tv.tv_sec = (stime > 1) ? stime - 1 : 0; - /* we set tv_usec to slightly more than necessary so as - * we don't wake up too early, in which case we would - * have to sleep again for some time */ - tv.tv_usec = 1001000 - tv.tv_usec; - /* On some systems (BSD, etc), tv_usec cannot be greater than 999999 */ - if (tv.tv_usec > 999999) - tv.tv_usec = 999999; - /* note: read_set is set in socket.c */ - if((retcode = select(set_max_fd+1, &read_set, NULL, NULL, &tv)) < 0 && errno != EINTR) - die_e("select returned %d", errno); + gettimeofday(&tv, NULL); + tv.tv_sec = (stime > 1) ? stime - 1 : 0; + /* we set tv_usec to slightly more than necessary so as + * we don't wake up too early, in which case we would + * have to sleep again for some time */ + tv.tv_usec = 1001000 - tv.tv_usec; + /* On some systems (BSD, etc), tv_usec cannot be greater than 999999 */ + if (tv.tv_usec > 999999) + tv.tv_usec = 999999; + /* note: read_set is set in socket.c */ + if ((retcode = select(set_max_fd + 1, &read_set, NULL, NULL, &tv)) < 0 + && errno != EINTR) + die_e("select returned %d", errno); #else - if (stime > 1) - sleep(stime - 1); - gettimeofday(&tv, NULL); - /* we set tv_usec to slightly more than necessary to avoid - * infinite loop */ - usleep( 1001000 - tv.tv_usec ); -#endif /* FCRONDYN */ + if (stime > 1) + sleep(stime - 1); + gettimeofday(&tv, NULL); + /* we set tv_usec to slightly more than necessary to avoid + * infinite loop */ + usleep(1001000 - tv.tv_usec); +#endif /* FCRONDYN */ #else - sleep(stime); -#endif /* HAVE_GETTIMEOFDAY */ + sleep(stime); +#endif /* HAVE_GETTIMEOFDAY */ - now = time(NULL); + now = time(NULL); - check_signal(); + check_signal(); - debug("\n"); - test_jobs(); + debug("\n"); + test_jobs(); - while ( serial_num > 0 && serial_running < serial_max_running ) - run_serial_job(); + while (serial_num > 0 && serial_running < serial_max_running) + run_serial_job(); - if ( once ) { - explain("Running with option once : exiting ... "); - xexit(EXIT_OK); - } + if (once) { + explain("Running with option once : exiting ... "); + xexit(EXIT_OK); + } - if ( save <= now ) { - save = now + save_time; - /* save all files */ - save_file(NULL); - } + if (save <= now) { + save = now + save_time; + /* save all files */ + save_file(NULL); + } #ifdef FCRONDYN - /* check if there's a new connection, a new command to answer, etc ... */ - /* we do that *after* other checks, to avoid Denial Of Service attacks */ - check_socket(retcode); + /* check if there's a new connection, a new command to answer, etc ... */ + /* we do that *after* other checks, to avoid Denial Of Service attacks */ + check_socket(retcode); #endif - stime = check_lavg(save); - debug("next sleep time : %ld", stime); + stime = check_lavg(save); + debug("next sleep time : %ld", stime); - check_signal(); + check_signal(); } diff --git a/fcron.h b/fcron.h index e78fb94..7ad436e 100644 --- a/fcron.h +++ b/fcron.h @@ -83,7 +83,7 @@ extern short int serial_array_size; extern short int serial_array_index; extern short int serial_num; extern short int serial_running; -extern short int serial_max_running; +extern short int serial_max_running; extern short int serial_queue_max; extern short int lavg_queue_max; extern exe_list_t *exe_list; @@ -97,5 +97,4 @@ extern short int lavg_serial_running; /* fcron.c */ extern void xexit(int exit_value); -#endif /* __FCRON_H */ - +#endif /* __FCRON_H */ diff --git a/fcronconf.c b/fcronconf.c index cbfeb19..25479e9 100644 --- a/fcronconf.c +++ b/fcronconf.c @@ -50,7 +50,7 @@ init_conf(void) { /* set fcronconf if cmd line option -c has not been used */ if (fcronconf == NULL) - fcronconf = strdup2(ETC "/" FCRON_CONF); + fcronconf = strdup2(ETC "/" FCRON_CONF); fcrontabs = strdup2(FCRONTABS); pidfile = strdup2(PIDFILE); fifofile = strdup2(FIFOFILE); @@ -95,81 +95,100 @@ read_conf(void) gid_t fcrongid = -1; if (fcronconf != NULL) - /* fcronconf has been set by -c option : file must exist */ - err_on_enoent = 1; + /* 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; - } + 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; + } } /* get fcrongid */ gr = getgrnam(GROUPNAME); - if ( gr == NULL ) { - die_e("Unable to find %s in /etc/group", GROUPNAME); + if (gr == NULL) { + die_e("Unable to find %s in /etc/group", GROUPNAME); } fcrongid = gr->gr_gid; /* check if the file is secure : owner:root, group:fcron, * writable only by owner */ - if ( fstat(fileno(f), &st) != 0 - || st.st_uid != rootuid || st.st_gid != fcrongid - || st.st_mode & S_IWGRP || st.st_mode & S_IWOTH ) { - error("Conf file (%s) must be owned by root:" GROUPNAME - " and (no more than) 644 : ignored", fcronconf, GROUPNAME); - fclose(f); - return; + if (fstat(fileno(f), &st) != 0 + || st.st_uid != rootuid || st.st_gid != fcrongid + || st.st_mode & S_IWGRP || st.st_mode & S_IWOTH) { + error("Conf file (%s) must be owned by root:" GROUPNAME + " and (no more than) 644 : ignored", fcronconf, GROUPNAME); + 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 */ - - /* get the name of the var */ - if ( ( namesize = get_word(&ptr1) ) == 0 ) - /* name is zero-length */ - error("Zero-length var name at line %s : line ignored", buf); - - ptr2 = ptr1 + namesize; - - /* 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, "fcrontabs", namesize) == 0 ) { Set(fcrontabs, ptr2); } - else if ( strncmp(ptr1, "pidfile", namesize) == 0 ) { Set(pidfile, ptr2); } - else if ( strncmp(ptr1, "fifofile", namesize) == 0 ) { Set(fifofile , ptr2); } - else if ( strncmp(ptr1, "fcronallow", namesize) == 0 ) { Set(fcronallow , ptr2); } - else if ( strncmp(ptr1, "fcrondeny", namesize) == 0 ) { Set(fcrondeny , ptr2); } - else if ( strncmp(ptr1, "shell", namesize) == 0 ) { Set(shell , ptr2); } - else if ( strncmp(ptr1, "sendmail", namesize) == 0 ) { Set(sendmail , ptr2); } - else if ( strncmp(ptr1, "editor", namesize) == 0 ) { Set(editor , ptr2); } - else - error("Unknown var name at line %s : line ignored", buf); + 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 */ + + /* get the name of the var */ + if ((namesize = get_word(&ptr1)) == 0) + /* name is zero-length */ + error("Zero-length var name at line %s : line ignored", buf); + + ptr2 = ptr1 + namesize; + + /* 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, "fcrontabs", namesize) == 0) { + Set(fcrontabs, ptr2); + } + else if (strncmp(ptr1, "pidfile", namesize) == 0) { + Set(pidfile, ptr2); + } + else if (strncmp(ptr1, "fifofile", namesize) == 0) { + Set(fifofile, ptr2); + } + else if (strncmp(ptr1, "fcronallow", namesize) == 0) { + Set(fcronallow, ptr2); + } + else if (strncmp(ptr1, "fcrondeny", namesize) == 0) { + Set(fcrondeny, ptr2); + } + else if (strncmp(ptr1, "shell", namesize) == 0) { + Set(shell, ptr2); + } + else if (strncmp(ptr1, "sendmail", namesize) == 0) { + Set(sendmail, ptr2); + } + else if (strncmp(ptr1, "editor", namesize) == 0) { + Set(editor, ptr2); + } + else + error("Unknown var name at line %s : line ignored", buf); } if (debug_opt) { - debug(" fcronconf=%s", fcronconf); + debug(" fcronconf=%s", fcronconf); /* debug(" fcronallow=%s", fcronallow); */ /* debug(" fcrondeny=%s", fcrondeny); */ /* debug(" fcrontabs=%s", fcrontabs); */ @@ -183,5 +202,3 @@ read_conf(void) fclose(f); } - - diff --git a/fcronconf.h b/fcronconf.h index d211419..cfc36db 100644 --- a/fcronconf.h +++ b/fcronconf.h @@ -44,4 +44,4 @@ extern char *sendmail; extern void read_conf(void); extern void free_conf(void); -#endif /* __FCRONCONF_H__ */ +#endif /* __FCRONCONF_H__ */ diff --git a/fcrondyn.c b/fcrondyn.c index 84c3f33..f4e0ebc 100644 --- a/fcrondyn.c +++ b/fcrondyn.c @@ -75,14 +75,15 @@ gid_t user_gid = 0; struct cmd_list_ent cmd_list[NUM_CMD] = { /* name, desc, num opt, cmd code, cmd opts, cmd defaults */ {"ls", "List all jobs of user", 1, CMD_LIST_JOBS, - {USER}, {CUR_USER} }, + {USER}, {CUR_USER}}, {"ls_lavgq", "List jobs of user which are in lavg queue", 1, CMD_LIST_LAVGQ, {USER}, {CUR_USER}}, - {"ls_serialq", "List jobs of user which are in serial queue", 1, CMD_LIST_SERIALQ, + {"ls_serialq", "List jobs of user which are in serial queue", 1, + CMD_LIST_SERIALQ, {USER}, {CUR_USER}}, {"ls_exeq", "List running jobs of user", 1, CMD_LIST_EXEQ, {USER}, {CUR_USER}}, - {"detail", "Print details on job", 1, CMD_DETAILS, + {"detail", "Print details on job", 1, CMD_DETAILS, {JOBID}, {ARG_REQUIRED}}, /* {"reschedule", "Reschedule next execution of job", 2, CMD_RESCHEDULE, {TIME_AND_DATE, JOBID}, {ARG_REQUIRED, ARG_REQUIRED}}, */ @@ -103,11 +104,11 @@ info(void) * version, license */ { fprintf(stderr, - "fcrondyn " VERSION_QUOTED " - interact dynamically with daemon fcron\n" - "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" - "This program is free software distributed WITHOUT ANY WARRANTY.\n" - "See the GNU General Public License for more details.\n" - ); + "fcrondyn " VERSION_QUOTED + " - interact dynamically with daemon fcron\n" "Copyright " + COPYRIGHT_QUOTED " Thibault Godouet \n" + "This program is free software distributed WITHOUT ANY WARRANTY.\n" + "See the GNU General Public License for more details.\n"); exit(EXIT_OK); @@ -118,17 +119,15 @@ void usage(void) /* print a help message about command line options and exit */ { - fprintf(stderr, - "fcrondyn [-i]\n" - "fcrondyn -x 'command'\n" - "fcrondyn -h\n" - " -c f make fcrontab use config file f.\n" - " -d set up debug mode.\n" - " -h display this help message.\n" - " -V display version & infos about fcrondyn.\n" - "\n" - ); - + fprintf(stderr, + "fcrondyn [-i]\n" + "fcrondyn -x 'command'\n" + "fcrondyn -h\n" + " -c f make fcrontab use config file f.\n" + " -d set up debug mode.\n" + " -h display this help message.\n" + " -V display version & infos about fcrondyn.\n" "\n"); + exit(EXIT_ERR); } @@ -136,9 +135,10 @@ RETSIGTYPE sigpipe_handler(int x) /* handle broken pipes ... */ { - fprintf(stderr, "Broken pipe : fcron may have closed the connection\nThe connection " - "has been idle for more than %ds, or fcron may not be running anymore.\n", - MAX_IDLE_TIME); + fprintf(stderr, + "Broken pipe : fcron may have closed the connection\nThe connection " + "has been idle for more than %ds, or fcron may not be running anymore.\n", + MAX_IDLE_TIME); fprintf(stderr, "Exiting ...\n"); xexit(EXIT_ERR); @@ -177,175 +177,194 @@ parse_cmd(char *cmd_str, long int **cmd, int *cmd_len) bzero(buf, sizeof(buf)); *cmd_len = 0; - remove_blanks(cmd_str); /* at the end of the string */ - - if ( (word_size = get_word(&cmd_str)) == 0 ) { - fprintf(stderr, "Warning : Zero-length command name : line ignored.\n"); - return ZEROLEN_CMD; + remove_blanks(cmd_str); /* at the end of the string */ + + if ((word_size = get_word(&cmd_str)) == 0) { + fprintf(stderr, "Warning : Zero-length command name : line ignored.\n"); + return ZEROLEN_CMD; } - if (Strncmp(cmd_str, "q", word_size) == 0 || Strncmp(cmd_str, "quit", word_size) == 0 - || Strncmp(cmd_str, "exit", word_size) == 0) { - if ( debug_opt ) - fprintf(stderr, "quit command\n"); - return QUIT_CMD; + if (Strncmp(cmd_str, "q", word_size) == 0 + || Strncmp(cmd_str, "quit", word_size) == 0 + || Strncmp(cmd_str, "exit", word_size) == 0) { + if (debug_opt) + fprintf(stderr, "quit command\n"); + return QUIT_CMD; } - if( Strncmp(cmd_str, "h", word_size)==0 || Strncmp(cmd_str, "help", word_size)==0 ) { - if ( debug_opt ) - fprintf(stderr, "help command\n"); - return HELP_CMD; + if (Strncmp(cmd_str, "h", word_size) == 0 + || Strncmp(cmd_str, "help", word_size) == 0) { + if (debug_opt) + fprintf(stderr, "help command\n"); + return HELP_CMD; } for (i = 0; i < NUM_CMD; i++) { - if ( Strncmp(cmd_str, cmd_list[i].cmd_name, word_size) == 0 ) { - rank = i; - break; - } + if (Strncmp(cmd_str, cmd_list[i].cmd_name, word_size) == 0) { + rank = i; + break; + } } - if ( rank == (-1) ) { - fprintf(stderr, "Error : Unknown command.\n"); - return CMD_NOT_FOUND; + if (rank == (-1)) { + fprintf(stderr, "Error : Unknown command.\n"); + return CMD_NOT_FOUND; } Write_cmd(cmd_list[rank].cmd_code); - if ( debug_opt ) - fprintf(stderr, "command : %s\n", cmd_list[i].cmd_name); + if (debug_opt) + fprintf(stderr, "command : %s\n", cmd_list[i].cmd_name); cmd_str += word_size; - for (i = 0 ; i < cmd_list[rank].cmd_numopt; i++) { - - if ( (word_size = get_word(&cmd_str)) == 0 ) { - - if (cmd_list[rank].cmd_default[i] == ARG_REQUIRED) { - fprintf(stderr, "Error : arg required !\n"); - return INVALID_ARG; - } - - /* use default value : currently, works only with CUR_USER */ - if ( user_uid == rootuid ) { - /* default for root = all */ - int_buf = ALL; - Write_cmd( int_buf ); - if ( debug_opt ) - fprintf(stderr, " uid = ALL\n"); - } - else { - Write_cmd( user_uid ); - if ( debug_opt ) - fprintf(stderr, " uid = %d\n", (int)user_uid); - } - - } - - else { - - /* get value from line ... */ - switch (cmd_list[rank].cmd_opt[i]) { - - case USER: - int_buf = (long int) *(cmd_str + word_size); - *(cmd_str + word_size) = '\0'; + for (i = 0; i < cmd_list[rank].cmd_numopt; i++) { + + if ((word_size = get_word(&cmd_str)) == 0) { + + if (cmd_list[rank].cmd_default[i] == ARG_REQUIRED) { + fprintf(stderr, "Error : arg required !\n"); + return INVALID_ARG; + } + + /* use default value : currently, works only with CUR_USER */ + if (user_uid == rootuid) { + /* default for root = all */ + int_buf = ALL; + Write_cmd(int_buf); + if (debug_opt) + fprintf(stderr, " uid = ALL\n"); + } + else { + Write_cmd(user_uid); + if (debug_opt) + fprintf(stderr, " uid = %d\n", (int)user_uid); + } + + } + + else { + + /* get value from line ... */ + switch (cmd_list[rank].cmd_opt[i]) { + + case USER: + int_buf = (long int)*(cmd_str + word_size); + *(cmd_str + word_size) = '\0'; #ifdef SYSFCRONTAB - if ( strcmp(cmd_str, SYSFCRONTAB) == 0 ) { - Write_cmd(sysfcrontab_uid); - } - else { + if (strcmp(cmd_str, SYSFCRONTAB) == 0) { + Write_cmd(sysfcrontab_uid); + } + else { #endif - if ( ( pass = getpwnam(cmd_str) ) == NULL ) { - fprintf(stderr,"Error : '%s' isn't a valid username.\n",cmd_str); - return INVALID_ARG; - } - Write_cmd(pass->pw_uid); + if ((pass = getpwnam(cmd_str)) == NULL) { + fprintf(stderr, + "Error : '%s' isn't a valid username.\n", + cmd_str); + return INVALID_ARG; + } + Write_cmd(pass->pw_uid); #ifdef SYSFCRONTAB - } + } #endif - *(cmd_str + word_size) = (char) int_buf; - cmd_str += word_size; - if ( debug_opt ) - fprintf(stderr, " uid = %d\n", + *(cmd_str + word_size) = (char)int_buf; + cmd_str += word_size; + if (debug_opt) + fprintf(stderr, " uid = %d\n", #ifdef SYSFCRONTAB - (pass) ? (int)pass->pw_uid : (int)SYSFCRONTAB_UID + (pass) ? (int)pass->pw_uid : (int)SYSFCRONTAB_UID #else - (int)pass->pw_uid + (int)pass->pw_uid #endif - ); - break; - - case JOBID: - /* after strtol(), cmd_str will be updated (first non-number char) */ - if ( (int_buf = strtol(cmd_str, &cmd_str, 10)) < 0 || int_buf >= LONG_MAX - || (! isspace( (int) *cmd_str) && *cmd_str != '\0') ) { - fprintf(stderr, "Error : invalid jobid.\n"); - return INVALID_ARG; - } - Write_cmd(int_buf); - if ( debug_opt ) - fprintf(stderr, " jobid = %ld\n", int_buf); - break; - - case TIME_AND_DATE: - /* argghh !!! no standard function ! */ - break; - - case NICE_VALUE: - /* after strtol(), cmd_str will be updated (first non-number char) */ - if ( (int_buf = strtol(cmd_str, &cmd_str, 10)) > 20 - || (int_buf < 0 && getuid() != rootuid) || int_buf < -20 - || (! isspace( (int) *cmd_str) && *cmd_str != '\0') ) { - fprintf(stderr, "Error : invalid nice value.\n"); - return INVALID_ARG; - } - Write_cmd(int_buf); - if ( debug_opt ) - fprintf(stderr, " nicevalue = %ld\n", int_buf); - break; - - case SIGNAL: - if ( isalpha( (int) *cmd_str ) ) { - for (j = 0; j < word_size; j++) - *(cmd_str+j) = tolower ( *(cmd_str+j) ); - if ( Strncmp(cmd_str, "hup", word_size) == 0 ) int_buf = SIGHUP; - else if (Strncmp(cmd_str, "int", word_size) == 0) int_buf = SIGINT; - else if (Strncmp(cmd_str, "quit", word_size) == 0) int_buf = SIGQUIT; - else if (Strncmp(cmd_str, "kill", word_size) == 0) int_buf = SIGKILL; - else if (Strncmp(cmd_str, "alrm", word_size) == 0) int_buf = SIGALRM; - else if (Strncmp(cmd_str, "term", word_size) == 0) int_buf = SIGTERM; - else if (Strncmp(cmd_str, "usr1", word_size) == 0) int_buf = SIGUSR1; - else if (Strncmp(cmd_str, "usr2", word_size) == 0) int_buf = SIGUSR2; - else if (Strncmp(cmd_str, "cont", word_size) == 0) int_buf = SIGCONT; - else if (Strncmp(cmd_str, "stop", word_size) == 0) int_buf = SIGSTOP; - else if (Strncmp(cmd_str, "tstp", word_size) == 0) int_buf = SIGTSTP; - else { - fprintf(stderr, "Error : unknow signal (try integer value)\n"); - return INVALID_ARG; - } - cmd_str += word_size; - } - /* after strtol(), cmd_str will be updated (first non-number char) */ - else if((int_buf=strtol(cmd_str, &cmd_str, 10)) <= 0 || int_buf>=LONG_MAX - || (! isspace( (int) *cmd_str) && *cmd_str != '\0') ) { - fprintf(stderr, "Error : invalid signal value.\n"); - return INVALID_ARG; - } - Write_cmd(int_buf); - if ( debug_opt ) - fprintf(stderr, " signal = %ld\n", int_buf); - break; - - default: - fprintf(stderr, "Error : Unknown arg !"); - return INVALID_ARG; - } - } + ); + break; + + case JOBID: + /* after strtol(), cmd_str will be updated (first non-number char) */ + if ((int_buf = strtol(cmd_str, &cmd_str, 10)) < 0 + || int_buf >= LONG_MAX || (!isspace((int)*cmd_str) + && *cmd_str != '\0')) { + fprintf(stderr, "Error : invalid jobid.\n"); + return INVALID_ARG; + } + Write_cmd(int_buf); + if (debug_opt) + fprintf(stderr, " jobid = %ld\n", int_buf); + break; + + case TIME_AND_DATE: + /* argghh !!! no standard function ! */ + break; + + case NICE_VALUE: + /* after strtol(), cmd_str will be updated (first non-number char) */ + if ((int_buf = strtol(cmd_str, &cmd_str, 10)) > 20 + || (int_buf < 0 && getuid() != rootuid) || int_buf < -20 + || (!isspace((int)*cmd_str) && *cmd_str != '\0')) { + fprintf(stderr, "Error : invalid nice value.\n"); + return INVALID_ARG; + } + Write_cmd(int_buf); + if (debug_opt) + fprintf(stderr, " nicevalue = %ld\n", int_buf); + break; + + case SIGNAL: + if (isalpha((int)*cmd_str)) { + for (j = 0; j < word_size; j++) + *(cmd_str + j) = tolower(*(cmd_str + j)); + if (Strncmp(cmd_str, "hup", word_size) == 0) + int_buf = SIGHUP; + else if (Strncmp(cmd_str, "int", word_size) == 0) + int_buf = SIGINT; + else if (Strncmp(cmd_str, "quit", word_size) == 0) + int_buf = SIGQUIT; + else if (Strncmp(cmd_str, "kill", word_size) == 0) + int_buf = SIGKILL; + else if (Strncmp(cmd_str, "alrm", word_size) == 0) + int_buf = SIGALRM; + else if (Strncmp(cmd_str, "term", word_size) == 0) + int_buf = SIGTERM; + else if (Strncmp(cmd_str, "usr1", word_size) == 0) + int_buf = SIGUSR1; + else if (Strncmp(cmd_str, "usr2", word_size) == 0) + int_buf = SIGUSR2; + else if (Strncmp(cmd_str, "cont", word_size) == 0) + int_buf = SIGCONT; + else if (Strncmp(cmd_str, "stop", word_size) == 0) + int_buf = SIGSTOP; + else if (Strncmp(cmd_str, "tstp", word_size) == 0) + int_buf = SIGTSTP; + else { + fprintf(stderr, + "Error : unknow signal (try integer value)\n"); + return INVALID_ARG; + } + cmd_str += word_size; + } + /* after strtol(), cmd_str will be updated (first non-number char) */ + else if ((int_buf = strtol(cmd_str, &cmd_str, 10)) <= 0 + || int_buf >= LONG_MAX || (!isspace((int)*cmd_str) + && *cmd_str != '\0')) { + fprintf(stderr, "Error : invalid signal value.\n"); + return INVALID_ARG; + } + Write_cmd(int_buf); + if (debug_opt) + fprintf(stderr, " signal = %ld\n", int_buf); + break; + + default: + fprintf(stderr, "Error : Unknown arg !"); + return INVALID_ARG; + } + } } Skip_blanks(cmd_str); - if ( *cmd_str != '\0' ) - fprintf(stderr, "Warning : too much arguments : '%s' ignored.\n", cmd_str); + if (*cmd_str != '\0') + fprintf(stderr, "Warning : too much arguments : '%s' ignored.\n", + cmd_str); /* This is a valid command ... */ - *cmd = alloc_safe(*cmd_len*sizeof(long int), "command string"); + *cmd = alloc_safe(*cmd_len * sizeof(long int), "command string"); memcpy(*cmd, buf, *cmd_len * sizeof(long int)); return OK; @@ -358,12 +377,12 @@ authenticate_user_password(int fd) char *password = NULL; char buf[USER_NAME_LEN + 16]; int len = 0; - fd_set read_set; /* needed to use select to check if some data is waiting */ + fd_set read_set; /* needed to use select to check if some data is waiting */ struct timeval tv; snprintf(buf, sizeof(buf), "password for %s :", user_str); - if ( (password = read_string(CONV_ECHO_OFF, buf)) == NULL ) - return ERR; + if ((password = read_string(CONV_ECHO_OFF, buf)) == NULL) + return ERR; len = snprintf(buf, sizeof(buf), "%s", user_str) + 1; len += snprintf(buf + len, sizeof(buf) - len, "%s", password) + 1; @@ -371,20 +390,21 @@ authenticate_user_password(int fd) Overwrite(buf); Overwrite(password); Free_safe(password); - + tv.tv_sec = MAX_WAIT_TIME; tv.tv_usec = 0; FD_ZERO(&read_set); FD_SET(fd, &read_set); - if ( select(fd + 1, &read_set, NULL, NULL, &tv) <= 0 ) { - error_e("Couldn't get data from socket during %d seconds.", MAX_WAIT_TIME); - return ERR; + if (select(fd + 1, &read_set, NULL, NULL, &tv) <= 0) { + error_e("Couldn't get data from socket during %d seconds.", + MAX_WAIT_TIME); + return ERR; } - while ( recv(fd, buf, sizeof(buf), 0) < 0 && errno == EINTR ) - if ( errno == EINTR && debug_opt ) - fprintf(stderr, "Got EINTR ..."); - if ( strncmp(buf, "1", sizeof("1")) != 0 ) - return ERR; + while (recv(fd, buf, sizeof(buf), 0) < 0 && errno == EINTR) + if (errno == EINTR && debug_opt) + fprintf(stderr, "Got EINTR ..."); + if (strncmp(buf, "1", sizeof("1")) != 0) + return ERR; return OK; } @@ -399,35 +419,36 @@ connect_fcron(void) int len = 0; int sun_len = 0; - if ( (fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1 ) - die_e("could not create socket"); + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) + die_e("could not create socket"); addr.sun_family = AF_UNIX; len = strlen(fifofile); - if ( len > sizeof(addr.sun_path) - 1 ) - die("Error : fifo file path too long (max is %d)", sizeof(addr.sun_path) - 1); + if (len > sizeof(addr.sun_path) - 1) + die("Error : fifo file path too long (max is %d)", + sizeof(addr.sun_path) - 1); /* length(fifofile) < sizeof(add.sun_path), so strncpy will terminate * the string with at least one \0 (not necessarily required by the OS, * but still a good idea) */ strncpy(addr.sun_path, fifofile, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; + addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; sun_len = (addr.sun_path - (char *)&addr) + len; #if HAVE_SA_LEN addr.sun_len = sun_len; #endif - if ( connect(fd, (struct sockaddr *) &addr, sun_len) < 0 ) - die_e("Cannot connect() to fcron (check if fcron is running)"); + if (connect(fd, (struct sockaddr *)&addr, sun_len) < 0) + die_e("Cannot connect() to fcron (check if fcron is running)"); /* Nothing to do on the client side if we use SO_PASSCRED */ #ifndef SO_PASSCRED - if ( authenticate_user_password(fd) == ERR ) { + if (authenticate_user_password(fd) == ERR) { fprintf(stderr, "Invalid password or too many authentication failures" - " (try to connect later).\n(In the later case, fcron rejects all" - " new authentication during %d secs)\n", AUTH_WAIT); - die("Unable to authenticate user"); + " (try to connect later).\n(In the later case, fcron rejects all" + " new authentication during %d secs)\n", AUTH_WAIT); + die("Unable to authenticate user"); } -#endif /* SO_PASSCRED */ +#endif /* SO_PASSCRED */ return fd; @@ -443,61 +464,74 @@ talk_fcron(char *cmd_str, int fd) char buf[LINE_LEN]; size_t read_len = 0; char existing_connection = (fd < 0) ? 0 : 1; - fd_set read_set; /* needed to use select to check if some data is waiting */ + fd_set read_set; /* needed to use select to check if some data is waiting */ struct timeval tv; - switch ( parse_cmd(cmd_str, &cmd, &cmd_len) ) { + switch (parse_cmd(cmd_str, &cmd, &cmd_len)) { case OK: - break; + break; case HELP_CMD: - { - int i, j, len; - printf("Command recognized by fcrondyn :\n"); - printf("------------------------------\n"); - for (i = 0; i < NUM_CMD; i++) { - len = printf("%s ", cmd_list[i].cmd_name); - - /* print args : */ - for (j = 0; j < cmd_list[i].cmd_numopt; j++) { - if ( cmd_list[i].cmd_default[j] != ARG_REQUIRED ) - len += printf("["); - switch ( cmd_list[i].cmd_opt[j] ) { - case USER: len += printf("user"); break; - case JOBID: len += printf("jobid"); break; - case TIME_AND_DATE: len += printf("time"); break; - case NICE_VALUE: len += printf("niceval"); break; - case SIGNAL: len += printf("sig"); break; - case BOOLEAN: len += printf("bool"); break; - default: len += printf("unknown_arg!"); - } - if ( cmd_list[i].cmd_default[j] != ARG_REQUIRED ) - len += printf("]"); - len += printf(" "); - } - /* Align correctly the descriptions : */ - printf("%*s%s\n", 24 - len, "", cmd_list[i].cmd_desc); - } - printf("\n"); - printf("help\t\t\tDisplay this help message\n"); - printf("quit\t\t\tQuit fcrondyn\n"); - } - return HELP_CMD; + { + int i, j, len; + printf("Command recognized by fcrondyn :\n"); + printf("------------------------------\n"); + for (i = 0; i < NUM_CMD; i++) { + len = printf("%s ", cmd_list[i].cmd_name); + + /* print args : */ + for (j = 0; j < cmd_list[i].cmd_numopt; j++) { + if (cmd_list[i].cmd_default[j] != ARG_REQUIRED) + len += printf("["); + switch (cmd_list[i].cmd_opt[j]) { + case USER: + len += printf("user"); + break; + case JOBID: + len += printf("jobid"); + break; + case TIME_AND_DATE: + len += printf("time"); + break; + case NICE_VALUE: + len += printf("niceval"); + break; + case SIGNAL: + len += printf("sig"); + break; + case BOOLEAN: + len += printf("bool"); + break; + default: + len += printf("unknown_arg!"); + } + if (cmd_list[i].cmd_default[j] != ARG_REQUIRED) + len += printf("]"); + len += printf(" "); + } + /* Align correctly the descriptions : */ + printf("%*s%s\n", 24 - len, "", cmd_list[i].cmd_desc); + } + printf("\n"); + printf("help\t\t\tDisplay this help message\n"); + printf("quit\t\t\tQuit fcrondyn\n"); + } + return HELP_CMD; case QUIT_CMD: - return QUIT_CMD; + return QUIT_CMD; case CMD_NOT_FOUND: - return CMD_NOT_FOUND; + return CMD_NOT_FOUND; case INVALID_ARG: - return INVALID_ARG; + return INVALID_ARG; case ZEROLEN_CMD: - return ZEROLEN_CMD; + return ZEROLEN_CMD; default: - return ERR; + return ERR; } /* This is a valid command (so we'll have to free() it) ... */ - if ( ! existing_connection && (fd = connect_fcron()) == ERR ) - return ERR; + if (!existing_connection && (fd = connect_fcron()) == ERR) + return ERR; send(fd, cmd, cmd_len * sizeof(long int), 0); Free_safe(cmd); @@ -507,39 +541,42 @@ talk_fcron(char *cmd_str, int fd) tv.tv_usec = 0; FD_ZERO(&read_set); FD_SET(fd, &read_set); - if ( select(fd + 1, &read_set, NULL, NULL, &tv) <= 0 ) { - error_e("Couldn't get data from socket during %d seconds.", MAX_WAIT_TIME); - return ERR; + if (select(fd + 1, &read_set, NULL, NULL, &tv) <= 0) { + error_e("Couldn't get data from socket during %d seconds.", + MAX_WAIT_TIME); + return ERR; } - while ( (read_len = (size_t)recv(fd, buf, sizeof(buf), 0)) >= 0 || errno == EINTR ) { - if ( errno == EINTR && debug_opt) - fprintf(stderr, "got EINTR ...\n"); - else if ( read_len > sizeof(buf) ) { - /* weird ... no data yet ? */ - if ( debug_opt ) - fprintf(stderr, "no data yet ?"); - } - else if ( read_len <= 0 ) { - if ( debug_opt ) - fprintf(stderr, "read_len = %d\n", (int)read_len); - fprintf(stderr, "connection closed by fcron\n"); - shutdown(fd, SHUT_RDWR); - return ERR; - } - else { - if ( write(STDOUT_FILENO, buf, read_len) < 0 ) - error_e("unable to write() to STDOUT_FILENO"); - if ( read_len >= sizeof(END_STR) && - strncmp(&buf[read_len-sizeof(END_STR)], END_STR, sizeof(END_STR)) == 0) - break; - } + while ((read_len = (size_t) recv(fd, buf, sizeof(buf), 0)) >= 0 + || errno == EINTR) { + if (errno == EINTR && debug_opt) + fprintf(stderr, "got EINTR ...\n"); + else if (read_len > sizeof(buf)) { + /* weird ... no data yet ? */ + if (debug_opt) + fprintf(stderr, "no data yet ?"); + } + else if (read_len <= 0) { + if (debug_opt) + fprintf(stderr, "read_len = %d\n", (int)read_len); + fprintf(stderr, "connection closed by fcron\n"); + shutdown(fd, SHUT_RDWR); + return ERR; + } + else { + if (write(STDOUT_FILENO, buf, read_len) < 0) + error_e("unable to write() to STDOUT_FILENO"); + if (read_len >= sizeof(END_STR) && + strncmp(&buf[read_len - sizeof(END_STR)], END_STR, + sizeof(END_STR)) == 0) + break; + } } - if ( read_len < 0 ) - error_e("error in recv()"); + if (read_len < 0) + error_e("error in recv()"); - if ( ! existing_connection ) - close(fd); + if (!existing_connection) + close(fd); return OK; } @@ -554,14 +591,16 @@ interactive_mode(int fd) int return_code = 0; char buf[LINE_LEN]; - if ( ! existing_connection && (fd = connect_fcron()) == ERR ) - return ERR; + if (!existing_connection && (fd = connect_fcron()) == ERR) + return ERR; - while (fprintf(stderr, "fcrondyn> ") && fgets(buf, sizeof(buf), stdin) != NULL - && (return_code = talk_fcron(buf, fd)) != QUIT_CMD && return_code != ERR ) ; + while (fprintf(stderr, "fcrondyn> ") + && fgets(buf, sizeof(buf), stdin) != NULL + && (return_code = talk_fcron(buf, fd)) != QUIT_CMD + && return_code != ERR) ; - if ( ! existing_connection ) - close(fd); + if (!existing_connection) + close(fd); return OK; } @@ -578,49 +617,53 @@ parseopt(int argc, char *argv[]) /* constants and variables defined by command line */ - while(1) { - c = getopt(argc, argv, "hVdc:ix:"); - if (c == EOF) break; - switch (c) { + while (1) { + c = getopt(argc, argv, "hVdc:ix:"); + if (c == EOF) + break; + switch (c) { - case 'V': - info(); break; + case 'V': + info(); + break; - case 'h': - usage(); break; + case 'h': + usage(); + break; - case 'd': - debug_opt = 1; break; + case 'd': + debug_opt = 1; + break; - case 'c': - Set(fcronconf, optarg); - break; + case 'c': + Set(fcronconf, optarg); + break; - case 'i': - Free_safe(cmd_str); - break; + case 'i': + Free_safe(cmd_str); + break; - case 'x': - Set(cmd_str, optarg); - break; + case 'x': + Set(cmd_str, optarg); + break; - case ':': - fprintf(stderr, "(setopt) Missing parameter.\n"); - usage(); + case ':': + fprintf(stderr, "(setopt) Missing parameter.\n"); + usage(); - case '?': - usage(); + case '?': + usage(); - default: - fprintf(stderr, "(setopt) Warning: getopt returned %c.\n", c); - } + default: + fprintf(stderr, "(setopt) Warning: getopt returned %c.\n", c); + } } if (optind < argc) { - for (i = optind; i <= argc; i++) - fprintf(stderr, "Unknown argument \"%s\"", argv[i]); - usage(); + for (i = optind; i <= argc; i++) + fprintf(stderr, "Unknown argument \"%s\"", argv[i]); + usage(); } } @@ -635,13 +678,15 @@ main(int argc, char **argv) rootuid = get_user_uid_safe(ROOTNAME); rootgid = get_group_gid_safe(ROOTGROUP); - if ( strrchr(argv[0], '/') == NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0], '/') + 1; + if (strrchr(argv[0], '/') == NULL) + prog_name = argv[0]; + else + prog_name = strrchr(argv[0], '/') + 1; user_uid = getuid(); user_gid = getgid(); - if ( (pass = getpwuid(user_uid)) == NULL ) - die("user \"%s\" is not in passwd file. Aborting.", USERNAME); + if ((pass = getpwuid(user_uid)) == NULL) + die("user \"%s\" is not in passwd file. Aborting.", USERNAME); user_str = strdup2(pass->pw_name); /* drop suid rights that we don't need, but keep the sgid rights @@ -649,7 +694,7 @@ main(int argc, char **argv) #ifdef USE_SETE_ID seteuid_safe(user_uid); #endif - if ( setuid(user_uid) < 0 ) + if (setuid(user_uid) < 0) die_e("could not setuid() to %d", user_uid); /* interpret command line options */ @@ -658,27 +703,27 @@ main(int argc, char **argv) /* read fcron.conf and update global parameters */ read_conf(); - if ( ! is_allowed(user_str) ) { - die("User \"%s\" is not allowed to use %s. Aborting.", - user_str, prog_name); + if (!is_allowed(user_str)) { + die("User \"%s\" is not allowed to use %s. Aborting.", user_str, + prog_name); } /* we don't need anymore special rights : drop remaining ones */ #ifdef USE_SETE_ID setegid_safe(user_gid); #endif - if ( setgid(user_gid) < 0 ) + if (setgid(user_gid) < 0) die_e("could not setgid() to %d", user_gid); /* check for broken pipes ... */ signal(SIGPIPE, sigpipe_handler); - if ( cmd_str == NULL ) - return_code = interactive_mode(fd); + if (cmd_str == NULL) + return_code = interactive_mode(fd); else - return_code = talk_fcron(cmd_str, fd); + return_code = talk_fcron(cmd_str, fd); - xexit( (return_code == OK ) ? EXIT_OK : EXIT_ERR ); + xexit((return_code == OK) ? EXIT_OK : EXIT_ERR); /* never reached */ return EXIT_OK; diff --git a/fcrondyn.h b/fcrondyn.h index ca63136..30264bc 100644 --- a/fcrondyn.h +++ b/fcrondyn.h @@ -46,4 +46,4 @@ typedef struct cmd_list_ent { int cmd_default[MAX_NUM_OPT]; } cmd_list_ent; -#endif /* __FCRONDYN_H__ */ +#endif /* __FCRONDYN_H__ */ diff --git a/fcronsighup.c b/fcronsighup.c index 7c6f603..6449557 100644 --- a/fcronsighup.c +++ b/fcronsighup.c @@ -49,20 +49,16 @@ usage(void) /* print a help message about command line options and exit */ { fprintf(stderr, - "fcronsighup "VERSION_QUOTED" - make fcron update its fcrontabs\n" - "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" - "This program is free software distributed WITHOUT ANY WARRANTY.\n" - "See the GNU General Public License for more details.\n" - "\n" - ); - - fprintf(stderr, - "fcronsighup [fcronconf]\n" - " Signal fcron process using fcronconf configuration file\n" - " (or default configuration file " ETC "/" FCRON_CONF").\n" - "\n" - ); - + "fcronsighup " VERSION_QUOTED " - make fcron update its fcrontabs\n" + "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" + "This program is free software distributed WITHOUT ANY WARRANTY.\n" + "See the GNU General Public License for more details.\n" "\n"); + + fprintf(stderr, + "fcronsighup [fcronconf]\n" + " Signal fcron process using fcronconf configuration file\n" + " (or default configuration file " ETC "/" FCRON_CONF ").\n" "\n"); + exit(EXIT_ERR); } @@ -74,11 +70,11 @@ read_pid(void) { FILE *fp = NULL; pid_t pid = 0; - + if ((fp = fopen(pidfile, "r")) != NULL) { - if ( fscanf(fp, "%" ATTR_SIZE_PIDT "d", CAST_PIDT_PTR &pid) < 1 ) - error("Unable to read fcron daemon's pid (fscanf(fp,...))"); - fclose(fp); + if (fscanf(fp, "%" ATTR_SIZE_PIDT "d", CAST_PIDT_PTR & pid) < 1) + error("Unable to read fcron daemon's pid (fscanf(fp,...))"); + fclose(fp); } return pid; @@ -93,114 +89,116 @@ sig_daemon(void) { /* we don't need to make root wait */ if (uid != rootuid) { - time_t t = 0; - int sl = 0; - FILE *fp = NULL; - int fd = 0; - struct tm *tm = NULL; - char sigfile[PATH_LEN]; - char buf[PATH_LEN]; - - t = time(NULL); - tm = localtime(&t); - - if ( (sl = 60 - (t % 60) - 10) < 0 ) { - if ( (tm->tm_min = tm->tm_min + 2) >= 60 ) { - tm->tm_hour++; - tm->tm_min -= 60; - } - snprintf(buf, sizeof(buf), "%02dh%02d", tm->tm_hour, tm->tm_min); - sl = 60 - (t % 60) + 50; - } else { - if ( ++tm->tm_min >= 60 ) { - tm->tm_hour++; - tm->tm_min -= 60; - } - snprintf(buf, sizeof(buf), "%02dh%02d", tm->tm_hour, tm->tm_min); - } - fprintf(stderr, "Modifications will be taken into account" - " at %s.\n", buf); - - /* if fcrontabs is too long, snprintf will not be able to add "/fcrontab.sig" - * string at the end of sigfile */ - if ( strlen(fcrontabs) > (sizeof(sigfile) - sizeof("/fcrontab.sig")) ) - die("fcrontabs string too long (more than %d characters)", - (sizeof(sigfile) - sizeof("/fcrontab.sig"))); - snprintf(sigfile, sizeof(sigfile), "%s/fcrontab.sig", fcrontabs); - - switch ( fork() ) { - case -1: - remove(sigfile); - die_e("could not fork : daemon has not been signaled"); - break; - case 0: - /* child */ - break; - default: - /* parent */ - return; - } - - foreground = 0; - - /* try to create a lock file */ - /* // */ - debug("uid: %d, euid: %d, gid: %d, egid: %d", getuid(), geteuid(), getgid(), getegid()); - /* // */ - fd = open(sigfile, O_RDWR|O_CREAT, 0644); - if ( fd == -1 ) - die_e("can't open or create %s", sigfile); - fp = fdopen(fd, "r+"); - if ( fp == NULL ) - die_e("can't fdopen %s", sigfile); - - + time_t t = 0; + int sl = 0; + FILE *fp = NULL; + int fd = 0; + struct tm *tm = NULL; + char sigfile[PATH_LEN]; + char buf[PATH_LEN]; + + t = time(NULL); + tm = localtime(&t); + + if ((sl = 60 - (t % 60) - 10) < 0) { + if ((tm->tm_min = tm->tm_min + 2) >= 60) { + tm->tm_hour++; + tm->tm_min -= 60; + } + snprintf(buf, sizeof(buf), "%02dh%02d", tm->tm_hour, tm->tm_min); + sl = 60 - (t % 60) + 50; + } + else { + if (++tm->tm_min >= 60) { + tm->tm_hour++; + tm->tm_min -= 60; + } + snprintf(buf, sizeof(buf), "%02dh%02d", tm->tm_hour, tm->tm_min); + } + fprintf(stderr, "Modifications will be taken into account" + " at %s.\n", buf); + + /* if fcrontabs is too long, snprintf will not be able to add "/fcrontab.sig" + * string at the end of sigfile */ + if (strlen(fcrontabs) > (sizeof(sigfile) - sizeof("/fcrontab.sig"))) + die("fcrontabs string too long (more than %d characters)", + (sizeof(sigfile) - sizeof("/fcrontab.sig"))); + snprintf(sigfile, sizeof(sigfile), "%s/fcrontab.sig", fcrontabs); + + switch (fork()) { + case -1: + remove(sigfile); + die_e("could not fork : daemon has not been signaled"); + break; + case 0: + /* child */ + break; + default: + /* parent */ + return; + } + + foreground = 0; + + /* try to create a lock file */ + /* // */ + debug("uid: %d, euid: %d, gid: %d, egid: %d", getuid(), geteuid(), + getgid(), getegid()); + /* // */ + fd = open(sigfile, O_RDWR | O_CREAT, 0644); + if (fd == -1) + die_e("can't open or create %s", sigfile); + fp = fdopen(fd, "r+"); + if (fp == NULL) + die_e("can't fdopen %s", sigfile); + + #ifdef HAVE_FLOCK - if ( flock(fd, LOCK_EX|LOCK_NB) != 0 ) { - debug("fcrontab is already waiting for signalling the daemon :" - " exiting."); - return; - } -#else /* HAVE_FLOCK */ - if ( lockf(fd, F_TLOCK, 0) != 0 ) { - debug("fcrontab is already waiting for signalling the daemon :" - " exiting."); - return; - } -#endif /* ! HAVE_FLOCK */ - - sleep(sl); - - fclose(fp); - close(fd); - - if ( remove(sigfile) < 0 ) - error_e("Could not remove %s"); + if (flock(fd, LOCK_EX | LOCK_NB) != 0) { + debug("fcrontab is already waiting for signalling the daemon :" + " exiting."); + return; + } +#else /* HAVE_FLOCK */ + if (lockf(fd, F_TLOCK, 0) != 0) { + debug("fcrontab is already waiting for signalling the daemon :" + " exiting."); + return; + } +#endif /* ! HAVE_FLOCK */ + + sleep(sl); + + fclose(fp); + close(fd); + + if (remove(sigfile) < 0) + error_e("Could not remove %s"); } else - /* we are root */ - fprintf(stderr, "Modifications will be taken into account" - " right now.\n"); + /* we are root */ + fprintf(stderr, + "Modifications will be taken into account" " right now.\n"); - if ( (daemon_pid = read_pid()) == 0 ) - /* daemon is not running any longer : we exit */ - return ; + if ((daemon_pid = read_pid()) == 0) + /* daemon is not running any longer : we exit */ + return; foreground = 1; #ifdef USE_SETE_ID if (seteuid(rootuid) != 0) - error_e("seteuid(rootuid)"); -#endif /* USE_SETE_ID */ + error_e("seteuid(rootuid)"); +#endif /* USE_SETE_ID */ - if ( kill(daemon_pid, SIGHUP) != 0) - die_e("could not send SIGHUP to daemon (pid %d)", daemon_pid); + if (kill(daemon_pid, SIGHUP) != 0) + die_e("could not send SIGHUP to daemon (pid %d)", daemon_pid); #ifdef USE_SETE_ID /* get user's permissions */ - if (seteuid(fcrontab_uid) != 0) - die_e("Could not change euid to " USERNAME "[%d]", uid); -#endif /* USE_SETE_ID */ + if (seteuid(fcrontab_uid) != 0) + die_e("Could not change euid to " USERNAME "[%d]", uid); +#endif /* USE_SETE_ID */ } @@ -214,21 +212,23 @@ main(int argc, char **argv) rootuid = get_user_uid_safe(ROOTNAME); rootgid = get_group_gid_safe(ROOTGROUP); - if (strrchr(argv[0],'/')==NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0],'/')+1; + if (strrchr(argv[0], '/') == NULL) + prog_name = argv[0]; + else + prog_name = strrchr(argv[0], '/') + 1; fcrontab_uid = get_user_uid_safe(USERNAME); #ifdef USE_SETE_ID /* get user's permissions */ - if (seteuid(fcrontab_uid) != 0) - die_e("Could not change euid to " USERNAME "[%d]", uid); -#endif /* USE_SETE_ID */ + if (seteuid(fcrontab_uid) != 0) + die_e("Could not change euid to " USERNAME "[%d]", uid); +#endif /* USE_SETE_ID */ - if ( argc == 2 ) - fcronconf = argv[1]; - else if (argc > 2 ) - usage(); + if (argc == 2) + fcronconf = argv[1]; + else if (argc > 2) + usage(); /* read fcron.conf and update global parameters */ /* We deactivate output to console, because otherwise it may be used @@ -237,27 +237,28 @@ main(int argc, char **argv) foreground = 0; read_conf(); foreground = 1; - + uid = getuid(); /* check if user is allowed to use this program */ - if ( ! (pass = getpwuid(uid)) ) - die("user \"%s\" is not in passwd file. Aborting.", USERNAME); + if (!(pass = getpwuid(uid))) + die("user \"%s\" is not in passwd file. Aborting.", USERNAME); cur_user = strdup2(pass->pw_name); - if ( is_allowed(cur_user) ) { - /* check if daemon is running */ - if ( (daemon_pid = read_pid()) != 0 ) - sig_daemon(); - else - fprintf(stderr, "fcron is not running :\n modifications will" - " be taken into account at its next execution.\n"); + if (is_allowed(cur_user)) { + /* check if daemon is running */ + if ((daemon_pid = read_pid()) != 0) + sig_daemon(); + else + fprintf(stderr, "fcron is not running :\n modifications will" + " be taken into account at its next execution.\n"); } else - die("User \"%s\" is not allowed to use %s. Aborting.", - cur_user, prog_name); + die("User \"%s\" is not allowed to use %s. Aborting.", cur_user, + prog_name); - if (cur_user) free(cur_user); + if (cur_user) + free(cur_user); return EXIT_OK; } diff --git a/fcronsighup.h b/fcronsighup.h index ae4992f..2c65bf6 100644 --- a/fcronsighup.h +++ b/fcronsighup.h @@ -34,4 +34,4 @@ extern uid_t rootuid; extern gid_t rootgid; -#endif /* __FCRONSIGHUP_H__ */ +#endif /* __FCRONSIGHUP_H__ */ diff --git a/fcrontab.c b/fcrontab.c index bf84e1e..35fe3d6 100644 --- a/fcrontab.c +++ b/fcrontab.c @@ -66,16 +66,16 @@ int file_opt = 0; * in the configure script) */ char *user = NULL; char *runas = NULL; -uid_t useruid = 0; /* uid of the user */ -gid_t usergid = 0; /* gid of the user */ -uid_t asuid = 0; /* uid of the user whose fcrontab we are working on */ -gid_t asgid = 0; /* gid of the user whose fcrontab we are working on*/ -uid_t fcrontab_uid = 0; /* uid of the fcron user */ -gid_t fcrontab_gid = 0; /* gid of the fcron user */ -uid_t rootuid = 0; /* uid of root */ -gid_t rootgid = 0; /* gid of root */ +uid_t useruid = 0; /* uid of the user */ +gid_t usergid = 0; /* gid of the user */ +uid_t asuid = 0; /* uid of the user whose fcrontab we are working on */ +gid_t asgid = 0; /* gid of the user whose fcrontab we are working on */ +uid_t fcrontab_uid = 0; /* uid of the fcron user */ +gid_t fcrontab_gid = 0; /* gid of the fcron user */ +uid_t rootuid = 0; /* uid of root */ +gid_t rootgid = 0; /* gid of root */ -char need_sig = 0; /* do we need to signal fcron daemon */ +char need_sig = 0; /* do we need to signal fcron daemon */ char orig_dir[PATH_LEN]; cf_t *file_base = NULL; @@ -90,10 +90,10 @@ pid_t daemon_pid = 0; #ifdef HAVE_LIBPAM int conv_pam(int num_msg, const struct pam_message **msgm, - struct pam_response **response, void *appdata_ptr); + struct pam_response **response, void *appdata_ptr); pam_handle_t *pamh = NULL; const struct pam_conv apamconv = { conv_pam, NULL }; -#endif /* HAVE_LIBPAM */ +#endif /* HAVE_LIBPAM */ void info(void) @@ -101,11 +101,10 @@ info(void) * version, license */ { fprintf(stderr, - "fcrontab " VERSION_QUOTED " - user interface to daemon fcron\n" - "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" - "This program is free software distributed WITHOUT ANY WARRANTY.\n" - "See the GNU General Public License for more details.\n" - ); + "fcrontab " VERSION_QUOTED " - user interface to daemon fcron\n" + "Copyright " COPYRIGHT_QUOTED " Thibault Godouet \n" + "This program is free software distributed WITHOUT ANY WARRANTY.\n" + "See the GNU General Public License for more details.\n"); exit(EXIT_OK); @@ -116,23 +115,21 @@ void usage(void) /* print a help message about command line options and exit */ { - fprintf(stderr, - "fcrontab [-n] file [user|-u user]\n" - "fcrontab { -l | -r | -e | -z } [-n] [user|-u user]\n" - "fcrontab -h\n" - " -u user specify user name.\n" - " -l list user's current fcrontab.\n" - " -r remove user's current fcrontab.\n" - " -e edit user's current fcrontab.\n" - " -z reinstall user's fcrontab from source code.\n" - " -n ignore previous version of file.\n" - " -c f make fcrontab use config file f.\n" - " -d set up debug mode.\n" - " -h display this help message.\n" - " -V display version & infos about fcrontab.\n" - "\n" - ); - + fprintf(stderr, + "fcrontab [-n] file [user|-u user]\n" + "fcrontab { -l | -r | -e | -z } [-n] [user|-u user]\n" + "fcrontab -h\n" + " -u user specify user name.\n" + " -l list user's current fcrontab.\n" + " -r remove user's current fcrontab.\n" + " -e edit user's current fcrontab.\n" + " -z reinstall user's fcrontab from source code.\n" + " -n ignore previous version of file.\n" + " -c f make fcrontab use config file f.\n" + " -d set up debug mode.\n" + " -h display this help message.\n" + " -V display version & infos about fcrontab.\n" "\n"); + exit(EXIT_ERR); } @@ -147,33 +144,34 @@ xexit(int exit_val) * die_e() here, as die_e() would then call xexit() and we could * go into a loop! */ - if ( need_sig == 1 ) { - - /* fork and exec fcronsighup */ - switch ( pid = fork() ) { - case 0: - /* child */ + if (need_sig == 1) { + + /* fork and exec fcronsighup */ + switch (pid = fork()) { + case 0: + /* child */ if (getegid() != fcrontab_gid && setegid(fcrontab_gid) != 0) { - error_e("could not change egid to fcrontab_gid[%d]", fcrontab_gid); + error_e("could not change egid to fcrontab_gid[%d]", + fcrontab_gid); exit(ERR); } - execl(BINDIREX "/fcronsighup", BINDIREX "/fcronsighup", - fcronconf, NULL); + execl(BINDIREX "/fcronsighup", BINDIREX "/fcronsighup", fcronconf, + NULL); - error_e("Could not exec " BINDIREX " fcronsighup"); + error_e("Could not exec " BINDIREX " fcronsighup"); exit(ERR); - break; + break; - case -1: - error_e("Could not fork (fcron has not been signaled)"); + case -1: + error_e("Could not fork (fcron has not been signaled)"); exit(ERR); - break; + break; - default: - /* parent */ - waitpid(pid, NULL, 0); - break; - } + default: + /* parent */ + waitpid(pid, NULL, 0); + break; + } } #ifdef HAVE_LIBPAM @@ -200,67 +198,70 @@ copy_src(int from, char *dest) int nb; char *copy_buf[LINE_LEN]; - char tmp_filename_str[PATH_LEN+4]; + char tmp_filename_str[PATH_LEN + 4]; int dest_path_len, tmp_filename_index; char *tmp_suffix_str = ".tmp"; - int max_dest_len = sizeof(tmp_filename_str)- sizeof(tmp_suffix_str); + int max_dest_len = sizeof(tmp_filename_str) - sizeof(tmp_suffix_str); - if(from < 0) { + if (from < 0) { die("copy_src() called with an invalid 'from' argument"); } /* just in case the file was read in the past... */ lseek(from, 0, SEEK_SET); - /* the temp file must be in the same directory as the dest file */ + /* the temp file must be in the same directory as the dest file */ dest_path_len = strlen(dest); strncpy(tmp_filename_str, dest, max_dest_len); tmp_filename_index = (dest_path_len > max_dest_len) ? - max_dest_len : dest_path_len; + max_dest_len : dest_path_len; strcpy(&tmp_filename_str[tmp_filename_index], tmp_suffix_str); /* create it as fcrontab_uid (to avoid problem if user's uid changed) * except for root. Root requires filesystem uid root for security * reasons */ - to_fd = open_as_user(tmp_filename_str, (asuid==rootuid)?rootuid:fcrontab_uid, - fcrontab_gid, O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, S_IRUSR|S_IWUSR|S_IRGRP); - if ( to_fd < 0 ) { - error_e("could not open file %s", tmp_filename_str); - goto exiterr; + to_fd = + open_as_user(tmp_filename_str, + (asuid == rootuid) ? rootuid : fcrontab_uid, fcrontab_gid, + O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, + S_IRUSR | S_IWUSR | S_IRGRP); + if (to_fd < 0) { + error_e("could not open file %s", tmp_filename_str); + goto exiterr; } - if (asuid == rootuid ) { - if ( fchmod(to_fd, S_IWUSR | S_IRUSR) != 0 ) { - error_e("Could not fchmod %s to 600", tmp_filename_str); - goto exiterr; - } - if ( fchown(to_fd, rootuid, fcrontab_gid) != 0 ) { - error_e("Could not fchown %s to root", tmp_filename_str); - goto exiterr; - } + if (asuid == rootuid) { + if (fchmod(to_fd, S_IWUSR | S_IRUSR) != 0) { + error_e("Could not fchmod %s to 600", tmp_filename_str); + goto exiterr; + } + if (fchown(to_fd, rootuid, fcrontab_gid) != 0) { + error_e("Could not fchown %s to root", tmp_filename_str); + goto exiterr; + } } - while ( (nb = read(from, copy_buf, sizeof(copy_buf))) != -1 && nb != 0 ) - if ( write(to_fd, copy_buf, nb) != nb ) { - error_e("Error while copying file (no space left ?)." - " Aborting : old source file kept"); - goto exiterr; - } + while ((nb = read(from, copy_buf, sizeof(copy_buf))) != -1 && nb != 0) + if (write(to_fd, copy_buf, nb) != nb) { + error_e("Error while copying file (no space left ?)." + " Aborting : old source file kept"); + goto exiterr; + } close(to_fd); to_fd = -1; - if ( rename_as_user(tmp_filename_str, dest, useruid, fcrontab_gid) < 0 ) { - error_e("Unable to rename %s to %s : old source file kept", - tmp_filename_str, dest); - goto exiterr; + if (rename_as_user(tmp_filename_str, dest, useruid, fcrontab_gid) < 0) { + error_e("Unable to rename %s to %s : old source file kept", + tmp_filename_str, dest); + goto exiterr; } - + return OK; - exiterr: - if ( to_fd != -1 ) - close(to_fd); + exiterr: + if (to_fd != -1) + close(to_fd); return ERR; } @@ -273,15 +274,15 @@ remove_fcrontab(char rm_orig) int return_val = OK; int fd; - if ( rm_orig ) - explain("removing %s's fcrontab", user); + if (rm_orig) + explain("removing %s's fcrontab", user); /* remove source and formated file */ - if ( (rm_orig && remove_as_user(buf, fcrontab_uid, fcrontab_gid)) != 0 ) { - if ( errno == ENOENT ) - return_val = ENOENT; - else - error_e("could not remove %s", buf); + if ((rm_orig && remove_as_user(buf, fcrontab_uid, fcrontab_gid)) != 0) { + if (errno == ENOENT) + return_val = ENOENT; + else + error_e("could not remove %s", buf); } /* try to remove the temp file in case he has not @@ -292,16 +293,17 @@ remove_fcrontab(char rm_orig) /* finally create a file in order to tell the daemon * a file was removed, and launch a signal to daemon */ snprintf(buf, sizeof(buf), "rm.%s", user); - fd = open_as_user(buf, fcrontab_uid, fcrontab_gid, O_CREAT|O_TRUNC|O_EXCL, S_IRUSR|S_IWUSR); + fd = open_as_user(buf, fcrontab_uid, fcrontab_gid, + O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); - if ( fd == -1 ) { - if ( errno != EEXIST ) - error_e("Can't create file %s", buf); + if (fd == -1) { + if (errno != EEXIST) + error_e("Can't create file %s", buf); } - else if ( asuid == rootuid && fchown(fd, rootuid, fcrontab_gid) != 0 ) - error_e("Could not fchown %s to root", buf); + else if (asuid == rootuid && fchown(fd, rootuid, fcrontab_gid) != 0) + error_e("Could not fchown %s to root", buf); close(fd); - + need_sig = 1; return return_val; @@ -315,29 +317,29 @@ write_file(int fd) int return_val = OK; if (ignore_prev == 1) - /* if user wants to ignore previous version, we remove it * - * ( fcron daemon remove files no longer wanted before - * adding new ones ) */ - remove_fcrontab(0); + /* if user wants to ignore previous version, we remove it * + * ( fcron daemon remove files no longer wanted before + * adding new ones ) */ + remove_fcrontab(0); /* copy original file to fcrontabs dir */ snprintf(buf, sizeof(buf), "%s.orig", user); - if ( copy_src(fd, buf) == ERR ) { - return_val = ERR; + if (copy_src(fd, buf) == ERR) { + return_val = ERR; } else { - if ( file_base->cf_line_base == NULL ) { - /* no entries */ - explain("%s's fcrontab contains no entries : removed.", user); - remove_fcrontab(0); - } - else { - /* write the binary fcrontab on disk */ - snprintf(buf, sizeof(buf), "new.%s", user); - if ( save_file(buf) != OK ) - return_val = ERR; - } + if (file_base->cf_line_base == NULL) { + /* no entries */ + explain("%s's fcrontab contains no entries : removed.", user); + remove_fcrontab(0); + } + else { + /* write the binary fcrontab on disk */ + snprintf(buf, sizeof(buf), "new.%s", user); + if (save_file(buf) != OK) + return_val = ERR; + } } @@ -350,27 +352,27 @@ make_file(char *file, int fd) explain("installing file %s for user %s", file, user); /* read file and create a list in memory */ - switch ( read_file(file, fd) ) { + switch (read_file(file, fd)) { case 2: case OK: - if (write_file(fd) == ERR) - return ERR; - else - /* tell daemon to update the conf */ - need_sig = 1; + if (write_file(fd) == ERR) + return ERR; + else + /* tell daemon to update the conf */ + need_sig = 1; - /* free memory used to store the list */ - delete_file(user); + /* free memory used to store the list */ + delete_file(user); - break; + break; case ERR: - return ERR; + return ERR; } return OK; - + } @@ -384,22 +386,22 @@ list_file(char *file) explain("listing %s's fcrontab", user); fd = open_as_user(file, useruid, fcrontab_gid, O_RDONLY); - if ( fd < 0 ) { - if ( errno == ENOENT ) { - explain("user %s has no fcrontab.", user); - return ; - } - else - die_e("User %s could not read file \"%s\"", user, file); + if (fd < 0) { + if (errno == ENOENT) { + explain("user %s has no fcrontab.", user); + return; + } + else + die_e("User %s could not read file \"%s\"", user, file); } f = fdopen(fd, "r"); - if ( f == NULL ) { + if (f == NULL) { close(fd); die_e("User %s could not read file \"%s\"", user, file); } - while ( (c = getc(f)) != EOF ) + while ((c = getc(f)) != EOF) putchar(c); fclose(f); @@ -409,7 +411,7 @@ list_file(char *file) void edit_file(char *fcron_orig) /* copy file to a temp file, edit that file, and install it - if necessary */ + * if necessary */ { char *cureditor = NULL; char editorcmd[PATH_LEN]; @@ -424,214 +426,217 @@ edit_file(char *fcron_orig) char correction = 0; short return_val = EXIT_OK; - explain("fcrontab : editing %s's fcrontab", user); + explain("fcrontab : editing %s's fcrontab", user); + + if ((cureditor = getenv("VISUAL")) == NULL || strcmp(cureditor, "\0") == 0) + if ((cureditor = getenv("EDITOR")) == NULL + || strcmp(cureditor, "\0") == 0) + cureditor = 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 ) { - error_e("could not fdopen"); - goto exiterr; + if ((fi = fdopen(file, "w")) == NULL) { + error_e("could not fdopen"); + goto exiterr; } #ifndef USE_SETE_ID if (fchown(file, asuid, asgid) != 0) { - error_e("Could not fchown %s to asuid and asgid", tmp_str); - goto exiterr; + error_e("Could not fchown %s to asuid and asgid", tmp_str); + goto exiterr; } #endif /* copy user's fcrontab (if any) to a temp file */ origfd = open_as_user(fcron_orig, useruid, fcrontab_gid, O_RDONLY); - if ( origfd < 0 ) { - if ( errno != ENOENT ) { - error_e("could not open file %s", fcron_orig); - goto exiterr; - } - else - fprintf(stderr, "no fcrontab for %s - using an empty one\n", - user); + if (origfd < 0) { + if (errno != ENOENT) { + error_e("could not open file %s", fcron_orig); + goto exiterr; + } + else + fprintf(stderr, "no fcrontab for %s - using an empty one\n", user); } - else { + else { f = fdopen(origfd, "r"); - if ( f == NULL ) { - error_e("could not fdopen file %s", fcron_orig); - goto exiterr; + if (f == NULL) { + error_e("could not fdopen file %s", fcron_orig); + goto exiterr; + } + /* copy original file to temp file */ + while ((c = getc(f)) != EOF) { + if (putc(c, fi) == EOF) { + error_e("could not write to file %s", tmp_str); + goto exiterr; + } } - /* copy original file to temp file */ - while ( (c=getc(f)) != EOF ) { - if ( putc(c, fi) == EOF ) { - error_e("could not write to file %s", tmp_str); - goto exiterr; - } - } - fclose(f); - f = NULL; - - if ( ferror(fi) ) + fclose(f); + f = NULL; + + if (ferror(fi)) error_e("Error while writing new fcrontab to %s"); } /* Don't close fi, because we still need the file descriptor 'file' */ - if ( fflush(fi) != 0 ) + if (fflush(fi) != 0) die_e("Could not fflush(%s)", fi); fi = NULL; do { - if ( fstat(file, &st) == 0 ) - mtime = st.st_mtime; - else { - error_e("could not stat \"%s\"", tmp_str); - goto exiterr; - } + if (fstat(file, &st) == 0) + mtime = st.st_mtime; + else { + error_e("could not stat \"%s\"", tmp_str); + goto exiterr; + } #ifndef USE_SETE_ID - /* chown the file (back if correction) to asuid/asgid so as user can edit it */ - if ( fchown(file, asuid, asgid) != 0 || fchmod(file, S_IRUSR|S_IWUSR) != 0 ){ + /* chown the file (back if correction) to asuid/asgid so as user can edit it */ + if (fchown(file, asuid, asgid) != 0 + || fchmod(file, S_IRUSR | S_IWUSR) != 0) { fprintf(stderr, "Can't chown or chmod %s.\n", tmp_str); goto exiterr; } #endif - /* close the file before the user edits it */ + /* close the file before the user edits it */ close(file); - switch ( pid = fork() ) { - case 0: - /* child */ - if ( useruid != rootuid ) { - if (setgid(asgid) < 0) { - error_e("setgid(asgid)"); - goto exiterr; - } - if (setuid(asuid) < 0) { - error_e("setuid(asuid)"); - goto exiterr; - } - } - else { - /* Some programs, like perl, require gid=egid : */ - if ( setgid(getgid()) < 0 ) { - error_e("setgid(getgid())"); - goto exiterr; - } - } - snprintf(editorcmd, sizeof(editorcmd), "%s %s", cureditor, tmp_str); - if ( chdir(tmp_path) != 0 ) + switch (pid = fork()) { + case 0: + /* child */ + if (useruid != rootuid) { + if (setgid(asgid) < 0) { + error_e("setgid(asgid)"); + goto exiterr; + } + if (setuid(asuid) < 0) { + error_e("setuid(asuid)"); + goto exiterr; + } + } + else { + /* Some programs, like perl, require gid=egid : */ + if (setgid(getgid()) < 0) { + error_e("setgid(getgid())"); + goto exiterr; + } + } + snprintf(editorcmd, sizeof(editorcmd), "%s %s", cureditor, tmp_str); + if (chdir(tmp_path) != 0) error_e("Could not chdir to %s", tmp_path); - execlp(shell, shell, "-c", editorcmd, tmp_str, NULL); - error_e("Error while running \"%s\"", cureditor); - goto exiterr; - - case -1: - error_e("fork"); - goto exiterr; - - default: - /* parent */ - break ; - } - - /* only reached by parent */ - waitpid(pid, &status, 0); - if ( ! WIFEXITED(status) ) { - fprintf(stderr, "Editor exited abnormally:" - " fcrontab is unchanged.\n"); - goto exiterr; - } + execlp(shell, shell, "-c", editorcmd, tmp_str, NULL); + error_e("Error while running \"%s\"", cureditor); + goto exiterr; + + case -1: + error_e("fork"); + goto exiterr; + + default: + /* parent */ + break; + } + + /* only reached by parent */ + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) { + fprintf(stderr, + "Editor exited abnormally:" " fcrontab is unchanged.\n"); + goto exiterr; + } /* re-open the file that has just been edited */ file = open_as_user(tmp_str, useruid, usergid, O_RDONLY); - if ( file < 0 ) { + if (file < 0) { error_e("Could not open file %s", tmp_str); goto exiterr; } #ifndef USE_SETE_ID - /* chown the file back to rootuid/rootgid */ - if ( fchown(file, rootuid, rootgid) != 0 || fchmod(file, S_IRUSR|S_IWUSR) != 0 ){ + /* chown the file back to rootuid/rootgid */ + if (fchown(file, rootuid, rootgid) != 0 + || fchmod(file, S_IRUSR | S_IWUSR) != 0) { fprintf(stderr, "Can't chown or chmod %s.\n", tmp_str); goto exiterr; } #endif - - /* check if file has been modified */ - if ( fstat(file, &st) != 0 ) { - error_e("could not stat %s", tmp_str); - goto exiterr; - } - - else if ( st.st_mtime > mtime || correction == 1) { - - correction = 0; - - switch ( read_file(tmp_str, file) ) { - case ERR: - goto exiterr; - case 2: - fprintf(stderr, "\nFile contains some errors. " - "Ignore [i] or Correct [c] ? "); - while ( (c = getchar()) ) { + + /* check if file has been modified */ + if (fstat(file, &st) != 0) { + error_e("could not stat %s", tmp_str); + goto exiterr; + } + + else if (st.st_mtime > mtime || correction == 1) { + + correction = 0; + + switch (read_file(tmp_str, file)) { + case ERR: + goto exiterr; + case 2: + fprintf(stderr, "\nFile contains some errors. " + "Ignore [i] or Correct [c] ? "); + while ((c = getchar())) { /* consume the rest of the line, e.g. the newline char (\n) */ - while (c != '\n' && (getchar() != '\n') ); + while (c != '\n' && (getchar() != '\n')) ; if (c == 'i') { break; } - else if ( c == 'c' ) { + else if (c == 'c') { /* free memory used to store the list */ delete_file(user); correction = 1; break; } else { - fprintf(stderr, "Please press c to correct, " + fprintf(stderr, + "Please press c to correct, " "or i to ignore: "); } } - break; - default: - break; - } - - } - else { - fprintf(stderr, "Fcrontab is unchanged :" - " no need to install it.\n"); - goto end; - } - - } while ( correction == 1); - - if ( write_file(file) != OK ) - return_val = EXIT_ERR; + break; + default: + break; + } + + } + else { + fprintf(stderr, + "Fcrontab is unchanged :" " no need to install it.\n"); + goto end; + } + + } while (correction == 1); + + if (write_file(file) != OK) + return_val = EXIT_ERR; else - /* tell daemon to update the conf */ - need_sig = 1; - + /* tell daemon to update the conf */ + need_sig = 1; + /* free memory used to store the list */ delete_file(user); - - end: - if ( file != -1 && close(file) != 0 ) - error_e("could not close %s", tmp_str); - if ( remove_as_user(tmp_str, useruid, fcrontab_gid) != 0 ) - error_e("could not remove %s", tmp_str); + + end: + if (file != -1 && close(file) != 0) + error_e("could not close %s", tmp_str); + if (remove_as_user(tmp_str, useruid, fcrontab_gid) != 0) + error_e("could not remove %s", tmp_str); free(tmp_str); - xexit (return_val); + xexit(return_val); - exiterr: - if ( remove_as_user(tmp_str, useruid, fcrontab_gid) != 0 ) - error_e("could not remove %s", tmp_str); + exiterr: + if (remove_as_user(tmp_str, useruid, fcrontab_gid) != 0) + error_e("could not remove %s", tmp_str); free(tmp_str); - if ( f != NULL ) - fclose(f); - if ( fi != NULL ) - fclose(fi); - if ( file != -1 ) - close(file); - xexit (EXIT_ERR); + if (f != NULL) + fclose(f); + if (fi != NULL) + fclose(fi); + if (file != -1) + close(file); + xexit(EXIT_ERR); } @@ -645,31 +650,31 @@ install_stdin(void) char *tmp_str = NULL; int c; short return_val = EXIT_OK; - + tmp_fd = temp_file(&tmp_str); - - if( (tmp_file = fdopen(tmp_fd, "w")) == NULL ) - die_e("Could not fdopen file %s", tmp_str); - while ( (c = getc(stdin)) != EOF ) - putc(c, tmp_file); + if ((tmp_file = fdopen(tmp_fd, "w")) == NULL) + die_e("Could not fdopen file %s", tmp_str); + + while ((c = getc(stdin)) != EOF) + putc(c, tmp_file); /* // */ debug("Copied stdin to %s, about to parse file %s...", tmp_str, tmp_str); /* don't closes tmp_fd as it will be used for make_file(): */ - if ( fflush(tmp_file) != 0 ) + if (fflush(tmp_file) != 0) die_e("Could not fflush(%s)", tmp_file); - if ( make_file(tmp_str, tmp_fd) == ERR ) - goto exiterr; + if (make_file(tmp_str, tmp_fd) == ERR) + goto exiterr; else - goto exit; + goto exit; - exiterr: - return_val = EXIT_ERR; - exit: - if ( remove(tmp_str) != 0 ) - error_e("Could not remove %s", tmp_str); + exiterr: + return_val = EXIT_ERR; + exit: + if (remove(tmp_str) != 0) + error_e("Could not remove %s", tmp_str); free(tmp_str); return return_val; @@ -682,19 +687,20 @@ reinstall(char *fcron_orig) explain("reinstalling %s's fcrontab", user); - if ( (i = open_as_user(fcron_orig, useruid, fcrontab_gid, O_RDONLY)) < 0) { - if ( errno == ENOENT ) { - fprintf(stderr, "Could not reinstall: user %s has no fcrontab\n", - user); - } - else - fprintf(stderr, "Could not open \"%s\": %s\n", fcron_orig, - strerror(errno)); + if ((i = open_as_user(fcron_orig, useruid, fcrontab_gid, O_RDONLY)) < 0) { + if (errno == ENOENT) { + fprintf(stderr, "Could not reinstall: user %s has no fcrontab\n", + user); + } + else + fprintf(stderr, "Could not open \"%s\": %s\n", fcron_orig, + strerror(errno)); - xexit(EXIT_ERR); + xexit(EXIT_ERR); } - close(0); dup2(i, 0); + close(0); + dup2(i, 0); close(i); xexit(install_stdin()); @@ -704,98 +710,98 @@ reinstall(char *fcron_orig) #ifdef HAVE_LIBPAM int -conv_pam(int num_msg, const struct pam_message **msgm, struct pam_response **response, - void *appdata_ptr) +conv_pam(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) /* text based conversation for pam. */ { int count = 0; struct pam_response *reply; - if (num_msg <= 0 ) - return PAM_CONV_ERR; + if (num_msg <= 0) + return PAM_CONV_ERR; - reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response)); + reply = (struct pam_response *)calloc(num_msg, sizeof(struct pam_response)); if (reply == NULL) { - debug("no memory for responses"); - return PAM_CONV_ERR; + debug("no memory for responses"); + return PAM_CONV_ERR; } for (count = 0; count < num_msg; ++count) { - char *string = NULL; - - switch ( msgm[count]->msg_style ) { - case PAM_PROMPT_ECHO_OFF: - string = read_string(CONV_ECHO_OFF,msgm[count]->msg); - if (string == NULL) { - goto failed_conversation; - } - break; - case PAM_PROMPT_ECHO_ON: - string = read_string(CONV_ECHO_ON,msgm[count]->msg); - if (string == NULL) { - goto failed_conversation; - } - break; - case PAM_ERROR_MSG: - if (fprintf(stderr,"%s\n",msgm[count]->msg) < 0) { - goto failed_conversation; - } - break; - case PAM_TEXT_INFO: - if (fprintf(stdout,"%s\n",msgm[count]->msg) < 0) { - goto failed_conversation; - } - break; - default: - fprintf(stderr, "erroneous conversation (%d)\n" - ,msgm[count]->msg_style); - goto failed_conversation; - } - - if (string) { /* must add to reply array */ - /* add string to list of responses */ - - reply[count].resp_retcode = 0; - reply[count].resp = string; - string = NULL; - } + char *string = NULL; + + switch (msgm[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + string = read_string(CONV_ECHO_OFF, msgm[count]->msg); + if (string == NULL) { + goto failed_conversation; + } + break; + case PAM_PROMPT_ECHO_ON: + string = read_string(CONV_ECHO_ON, msgm[count]->msg); + if (string == NULL) { + goto failed_conversation; + } + break; + case PAM_ERROR_MSG: + if (fprintf(stderr, "%s\n", msgm[count]->msg) < 0) { + goto failed_conversation; + } + break; + case PAM_TEXT_INFO: + if (fprintf(stdout, "%s\n", msgm[count]->msg) < 0) { + goto failed_conversation; + } + break; + default: + fprintf(stderr, "erroneous conversation (%d)\n", + msgm[count]->msg_style); + goto failed_conversation; + } + + if (string) { /* must add to reply array */ + /* add string to list of responses */ + + reply[count].resp_retcode = 0; + reply[count].resp = string; + string = NULL; + } } /* New (0.59+) behavior is to always have a reply - this is - compatable with the X/Open (March 1997) spec. */ + * compatable with the X/Open (March 1997) spec. */ *response = reply; reply = NULL; return PAM_SUCCESS; -failed_conversation: + failed_conversation: if (reply) { - for (count=0; countmsg_style) { - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: - Overwrite(reply[count].resp); - free(reply[count].resp); - break; - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - /* should not actually be able to get here... */ - free(reply[count].resp); - } - reply[count].resp = NULL; - } - /* forget reply too */ - free(reply); - reply = NULL; + for (count = 0; count < num_msg; ++count) { + if (reply[count].resp == NULL) { + continue; + } + switch (msgm[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + case PAM_PROMPT_ECHO_OFF: + Overwrite(reply[count].resp); + free(reply[count].resp); + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + /* should not actually be able to get here... */ + free(reply[count].resp); + } + reply[count].resp = NULL; + } + /* forget reply too */ + free(reply); + reply = NULL; } return PAM_CONV_ERR; } -#endif /* HAVE_LIBPAM */ +#endif /* HAVE_LIBPAM */ void @@ -813,172 +819,175 @@ parseopt(int argc, char *argv[]) /* constants and variables defined by command line */ - while(1) { - c = getopt(argc, argv, "u:lrezdnhVc:"); - if (c == EOF) break; - switch (c) { - - case 'V': - info(); break; - - case 'h': - usage(); break; - - case 'u': - if (useruid != rootuid) { - fprintf(stderr, "must be privileged to use -u\n"); - xexit(EXIT_ERR); - } - user = strdup2(optarg) ; - break; - - case 'd': - debug_opt = 1; break; - - case 'l': - if (rm_opt || edit_opt || reinstall_opt) { - fprintf(stderr, "Only one of the options -l, -r, -e and -z" - "may be used simultaneously.\n"); - xexit(EXIT_ERR); - } - list_opt = 1; - rm_opt = edit_opt = reinstall_opt = 0; - break; - - case 'r': - if (list_opt || edit_opt || reinstall_opt) { - fprintf(stderr, "Only one of the options -l, -r, -e and -z" - "may be used simultaneously.\n"); - xexit(EXIT_ERR); - } - rm_opt = 1; - list_opt = edit_opt = reinstall_opt = 0; - break; - - case 'e': - if (list_opt || rm_opt || reinstall_opt) { - fprintf(stderr, "Only one of the options -l, -r, -e and -z" - "may be used simultaneously.\n"); - xexit(EXIT_ERR); - } - edit_opt = 1; - list_opt = rm_opt = reinstall_opt = 0; - break; - - case 'z': - if (list_opt || rm_opt || edit_opt) { - fprintf(stderr, "Only one of the options -l, -r, -e and -z" - "may be used simultaneously.\n"); - xexit(EXIT_ERR); - } - reinstall_opt = ignore_prev = 1; - list_opt = rm_opt = edit_opt = 0; - break; - - case 'n': - ignore_prev = 1; - break; - - case 'c': - if ( optarg[0] == '/' ) { - Set(fcronconf, optarg); - } - else { - char buf[PATH_LEN]; - snprintf(buf, sizeof(buf), "%s/%s", orig_dir, optarg); - Set(fcronconf, buf); - } - break; - - case ':': - fprintf(stderr, "(setopt) Missing parameter.\n"); - usage(); - - case '?': - usage(); - - default: - fprintf(stderr, "(setopt) Warning: getopt returned %c.\n", c); - } + while (1) { + c = getopt(argc, argv, "u:lrezdnhVc:"); + if (c == EOF) + break; + switch (c) { + + case 'V': + info(); + break; + + case 'h': + usage(); + break; + + case 'u': + if (useruid != rootuid) { + fprintf(stderr, "must be privileged to use -u\n"); + xexit(EXIT_ERR); + } + user = strdup2(optarg); + break; + + case 'd': + debug_opt = 1; + break; + + case 'l': + if (rm_opt || edit_opt || reinstall_opt) { + fprintf(stderr, "Only one of the options -l, -r, -e and -z" + "may be used simultaneously.\n"); + xexit(EXIT_ERR); + } + list_opt = 1; + rm_opt = edit_opt = reinstall_opt = 0; + break; + + case 'r': + if (list_opt || edit_opt || reinstall_opt) { + fprintf(stderr, "Only one of the options -l, -r, -e and -z" + "may be used simultaneously.\n"); + xexit(EXIT_ERR); + } + rm_opt = 1; + list_opt = edit_opt = reinstall_opt = 0; + break; + + case 'e': + if (list_opt || rm_opt || reinstall_opt) { + fprintf(stderr, "Only one of the options -l, -r, -e and -z" + "may be used simultaneously.\n"); + xexit(EXIT_ERR); + } + edit_opt = 1; + list_opt = rm_opt = reinstall_opt = 0; + break; + + case 'z': + if (list_opt || rm_opt || edit_opt) { + fprintf(stderr, "Only one of the options -l, -r, -e and -z" + "may be used simultaneously.\n"); + xexit(EXIT_ERR); + } + reinstall_opt = ignore_prev = 1; + list_opt = rm_opt = edit_opt = 0; + break; + + case 'n': + ignore_prev = 1; + break; + + case 'c': + if (optarg[0] == '/') { + Set(fcronconf, optarg); + } + else { + char buf[PATH_LEN]; + snprintf(buf, sizeof(buf), "%s/%s", orig_dir, optarg); + Set(fcronconf, buf); + } + break; + + case ':': + fprintf(stderr, "(setopt) Missing parameter.\n"); + usage(); + + case '?': + usage(); + + default: + fprintf(stderr, "(setopt) Warning: getopt returned %c.\n", c); + } } /* 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(); - else if (argc - optind == 2 ) { - if ( list_opt + rm_opt + edit_opt + reinstall_opt == 0 ) - file_opt = optind++; - else - usage(); - - if (useruid != rootuid) { - fprintf(stderr, "must be privileged to use -u\n"); - xexit(EXIT_ERR); - } - Set(user, argv[optind]); + usage(); + else if (argc - optind == 2) { + if (list_opt + rm_opt + edit_opt + reinstall_opt == 0) + file_opt = optind++; + else + usage(); + + if (useruid != rootuid) { + fprintf(stderr, "must be privileged to use -u\n"); + xexit(EXIT_ERR); + } + Set(user, argv[optind]); } else if (argc - optind == 1) { - if ( list_opt + rm_opt + edit_opt + reinstall_opt == 0 ) - file_opt = optind; - else { - if (useruid != rootuid) { - fprintf(stderr, "must be privileged to use [user|-u user]\n"); - xexit(EXIT_ERR); - } - Set(user, argv[optind]); - } + if (list_opt + rm_opt + edit_opt + reinstall_opt == 0) + file_opt = optind; + else { + if (useruid != rootuid) { + fprintf(stderr, "must be privileged to use [user|-u user]\n"); + xexit(EXIT_ERR); + } + Set(user, argv[optind]); + } } else if (list_opt + rm_opt + edit_opt + reinstall_opt != 1) - usage(); - - if ( user == NULL ) { - /* get user's name using getpwuid() */ - if ( ! (pass = getpwuid(useruid)) ) - die_e("user \"%s\" is not in passwd file. Aborting.", USERNAME); - /* we need to strdup2 the value given by getpwuid() because we free - * file->cf_user in delete_file */ - user = strdup2(pass->pw_name); - asuid = pass->pw_uid; - asgid = pass->pw_gid; + usage(); + + if (user == NULL) { + /* get user's name using getpwuid() */ + if (!(pass = getpwuid(useruid))) + die_e("user \"%s\" is not in passwd file. Aborting.", USERNAME); + /* we need to strdup2 the value given by getpwuid() because we free + * file->cf_user in delete_file */ + user = strdup2(pass->pw_name); + asuid = pass->pw_uid; + asgid = pass->pw_gid; } else { #ifdef SYSFCRONTAB - if ( strcmp(user, SYSFCRONTAB) == 0 ) { - is_sysfcrontab = 1; - asuid = rootuid; - asgid = rootgid; - } - else -#endif /* def SYSFCRONTAB */ - { - errno = 0; - if ( (pass = getpwnam(user)) ) { - asuid = pass->pw_uid; - asgid = pass->pw_gid; - } - else - die_e("user \"%s\" is not in passwd file. Aborting.", user); - } + if (strcmp(user, SYSFCRONTAB) == 0) { + is_sysfcrontab = 1; + asuid = rootuid; + asgid = rootgid; + } + else +#endif /* def SYSFCRONTAB */ + { + errno = 0; + if ((pass = getpwnam(user))) { + asuid = pass->pw_uid; + asgid = pass->pw_gid; + } + else + die_e("user \"%s\" is not in passwd file. Aborting.", user); + } } - if ( + if ( #ifdef SYSFCRONTAB - ! is_sysfcrontab && + !is_sysfcrontab && #endif - ! is_allowed(user) ) { - die("User \"%s\" is not allowed to use %s. Aborting.", - user, prog_name); + !is_allowed(user)) { + die("User \"%s\" is not allowed to use %s. Aborting.", user, prog_name); } #ifdef SYSFCRONTAB - if ( is_sysfcrontab ) - runas = ROOTNAME; + if (is_sysfcrontab) + runas = ROOTNAME; else #endif - runas = user; + runas = user; } @@ -988,8 +997,8 @@ main(int argc, char **argv) { #ifdef HAVE_LIBPAM - int retcode = 0; - const char * const * env; + int retcode = 0; + const char *const *env; #endif struct passwd *pass; @@ -999,9 +1008,11 @@ main(int argc, char **argv) memset(buf, 0, sizeof(buf)); memset(file, 0, sizeof(file)); - if (strrchr(argv[0],'/')==NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0],'/')+1; - + if (strrchr(argv[0], '/') == NULL) + prog_name = argv[0]; + else + prog_name = strrchr(argv[0], '/') + 1; + useruid = getuid(); usergid = getgid(); @@ -1012,15 +1023,15 @@ main(int argc, char **argv) #endif errno = 0; - if ( ! (pass = getpwnam(USERNAME)) ) - die_e("user \"%s\" is not in passwd file. Aborting.", USERNAME); + if (!(pass = getpwnam(USERNAME))) + die_e("user \"%s\" is not in passwd file. Aborting.", USERNAME); fcrontab_uid = pass->pw_uid; fcrontab_gid = pass->pw_gid; /* get current dir */ orig_dir[0] = '\0'; - if ( getcwd(orig_dir, sizeof(orig_dir)) == NULL ) - die_e("getcwd"); + if (getcwd(orig_dir, sizeof(orig_dir)) == NULL) + die_e("getcwd"); /* interpret command line options */ parseopt(argc, argv); @@ -1034,117 +1045,123 @@ main(int argc, char **argv) #ifdef HAVE_LIBPAM /* Open PAM session for the user and obtain any security - credentials we might need */ + * credentials we might need */ debug("username: %s, runas: %s", user, runas); retcode = pam_start("fcrontab", runas, &apamconv, &pamh); - if (retcode != PAM_SUCCESS) die_pame(pamh, retcode, "Could not start PAM"); - retcode = pam_authenticate(pamh, 0); /* is user really user? */ if (retcode != PAM_SUCCESS) - die_pame(pamh, retcode, "Could not authenticate user using PAM (%d)", retcode); - retcode = pam_acct_mgmt(pamh, 0); /* permitted access? */ + die_pame(pamh, retcode, "Could not start PAM"); + retcode = pam_authenticate(pamh, 0); /* is user really user? */ + if (retcode != PAM_SUCCESS) + die_pame(pamh, retcode, "Could not authenticate user using PAM (%d)", + retcode); + retcode = pam_acct_mgmt(pamh, 0); /* permitted access? */ if (retcode != PAM_SUCCESS) - die_pame(pamh, retcode, "Could not init PAM account management (%d)", retcode); + die_pame(pamh, retcode, "Could not init PAM account management (%d)", + retcode); retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); - if (retcode != PAM_SUCCESS) die_pame(pamh, retcode, "Could not set PAM credentials"); + if (retcode != PAM_SUCCESS) + die_pame(pamh, retcode, "Could not set PAM credentials"); retcode = pam_open_session(pamh, 0); - if (retcode != PAM_SUCCESS) die_pame(pamh, retcode, "Could not open PAM session"); + if (retcode != PAM_SUCCESS) + die_pame(pamh, retcode, "Could not open PAM session"); - env = (const char * const *) pam_getenvlist(pamh); + env = (const char *const *)pam_getenvlist(pamh); while (env && *env) { - if (putenv((char*) *env)) die_e("Could not copy PAM environment"); - env++; + if (putenv((char *)*env)) + die_e("Could not copy PAM environment"); + env++; } /* Close the log here, because PAM calls openlog(3) and - our log messages could go to the wrong facility */ + * our log messages could go to the wrong facility */ xcloselog(); -#endif /* USE_PAM */ +#endif /* USE_PAM */ #ifdef USE_SETE_ID seteuid_safe(fcrontab_uid); /* change directory */ if (chdir(fcrontabs) != 0) { - error_e("Could not chdir to %s", fcrontabs); - xexit (EXIT_ERR); + error_e("Could not chdir to %s", fcrontabs); + xexit(EXIT_ERR); } seteuid_safe(useruid); -#else /* USE_SETE_ID */ +#else /* USE_SETE_ID */ - if (setuid(rootuid) != 0 ) - die_e("Could not change uid to rootuid"); + if (setuid(rootuid) != 0) + die_e("Could not change uid to rootuid"); if (setgid(rootgid) != 0) - die_e("Could not change gid to rootgid"); + die_e("Could not change gid to rootgid"); /* change directory */ if (chdir(fcrontabs) != 0) { - error_e("Could not chdir to %s", fcrontabs); - xexit (EXIT_ERR); + error_e("Could not chdir to %s", fcrontabs); + xexit(EXIT_ERR); } -#endif /* USE_SETE_ID */ - +#endif /* USE_SETE_ID */ + /* this program is seteuid : we set default permission mode * to 640 for a normal user, 600 for root, for security reasons */ - if ( asuid == rootuid ) - umask(066); /* octal : '0' + number in octal notation */ + if (asuid == rootuid) + umask(066); /* octal : '0' + number in octal notation */ else - umask(026); + umask(026); snprintf(buf, sizeof(buf), "%s.orig", user); /* determine what action should be taken */ - if ( file_opt ) { + if (file_opt) { - if ( strcmp(argv[file_opt], "-") == 0 ) + if (strcmp(argv[file_opt], "-") == 0) - xexit(install_stdin()); + xexit(install_stdin()); - else { + else { int fd = -1; - if ( *argv[file_opt] != '/' ) - /* this is just the file name, not the path : complete it */ - snprintf(file, sizeof(file), "%s/%s", orig_dir, argv[file_opt]); - else { - strncpy(file, argv[file_opt], sizeof(file) - 1); - file[sizeof(file)-1] = '\0'; - } + if (*argv[file_opt] != '/') + /* this is just the file name, not the path : complete it */ + snprintf(file, sizeof(file), "%s/%s", orig_dir, argv[file_opt]); + else { + strncpy(file, argv[file_opt], sizeof(file) - 1); + file[sizeof(file) - 1] = '\0'; + } fd = open_as_user(file, useruid, usergid, O_RDONLY); if (fd < 0) die_e("Could not open file %s", file); - if (make_file(file, fd) == OK) - xexit(EXIT_OK); - else - xexit(EXIT_ERR); + if (make_file(file, fd) == OK) + xexit(EXIT_OK); + else + xexit(EXIT_ERR); - } + } - } + } /* remove user's entries */ - if ( rm_opt == 1 ) { - if ( remove_fcrontab(1) == ENOENT ) - fprintf(stderr, "no fcrontab for %s\n", user); - xexit (EXIT_OK); + if (rm_opt == 1) { + if (remove_fcrontab(1) == ENOENT) + fprintf(stderr, "no fcrontab for %s\n", user); + xexit(EXIT_OK); } /* list user's entries */ - if ( list_opt == 1 ) { - list_file(buf); - xexit(EXIT_OK); + if (list_opt == 1) { + list_file(buf); + xexit(EXIT_OK); } /* edit user's entries */ - if ( edit_opt == 1 ) { - edit_file(buf); - xexit(EXIT_OK); + if (edit_opt == 1) { + edit_file(buf); + xexit(EXIT_OK); } /* reinstall user's entries */ - if ( reinstall_opt == 1 ) { - reinstall(buf); - xexit(EXIT_OK); + if (reinstall_opt == 1) { + reinstall(buf); + xexit(EXIT_OK); } /* never reached */ diff --git a/fcrontab.h b/fcrontab.h index 08a9cdb..571337c 100644 --- a/fcrontab.h +++ b/fcrontab.h @@ -42,4 +42,4 @@ extern gid_t fcrontab_gid; extern uid_t rootuid; extern gid_t rootgid; -#endif /* __FCRONTAB_H__ */ +#endif /* __FCRONTAB_H__ */ diff --git a/fifo_list.c b/fifo_list.c index 5509e22..d8e9804 100644 --- a/fifo_list.c +++ b/fifo_list.c @@ -31,12 +31,12 @@ #include "fifo_list.h" /* private functions: */ -int fifo_list_resize_array(fifo_list_t *l); +int fifo_list_resize_array(fifo_list_t * l); #define Sizeof_fifo_list(list) ((list)->entry_size * (list)->array_size) -fifo_list_entry_t *fifo_list_last(fifo_list_t *l); +fifo_list_entry_t *fifo_list_last(fifo_list_t * l); fifo_list_t * -fifo_list_init(size_t entry_size, int init_size, int grow_size) +fifo_list_init(size_t entry_size, int init_size, int grow_size) /* Create a new fifo list * Returns the newly created unordered list * Enough memory to hold init_size entries will initially be allocated, @@ -46,9 +46,8 @@ fifo_list_init(size_t entry_size, int init_size, int grow_size) fifo_list_t *l = NULL; /* sanity check */ - if ( entry_size < 1 || init_size < 1 || grow_size < 1 ) - die("Invalid arguments for fifo_list_init(): entry_size=%d, init_size=%d, " - "grow_size=%d", entry_size, init_size, grow_size); + if (entry_size < 1 || init_size < 1 || grow_size < 1) + die("Invalid arguments for fifo_list_init(): entry_size=%d, init_size=%d, " "grow_size=%d", entry_size, init_size, grow_size); /* Allocate the list structure: */ l = alloc_safe(sizeof(struct fifo_list_t), "new fifo_list_t"); @@ -59,28 +58,30 @@ fifo_list_init(size_t entry_size, int init_size, int grow_size) l->entry_size = entry_size; l->grow_size = grow_size; l->first_entry = l->cur_entry = NULL; - l->entries_array = alloc_safe(init_size*entry_size, "new fifo_list_t array"); + l->entries_array = + alloc_safe(init_size * entry_size, "new fifo_list_t array"); return l; } fifo_list_entry_t * -fifo_list_last(fifo_list_t *l) +fifo_list_last(fifo_list_t * l) /* Returns the pointer of the last entry in the list, or NULL if l is empty */ { fifo_list_entry *e = NULL; - if ( l->num_entries <= 0 ) - return NULL; - - e = (fifo_list_entry_t *) - ( (char *)l->entries_array + l->entry_size * ( l->num_entries - 1 ) ); - if ( e >= (fifo_list_entry_t *) ( (char *)l->entries_array + Sizeof_fifo_list(l) ) ) - e -= Sizeof_fifo_list(l); + if (l->num_entries <= 0) + return NULL; + + e = (fifo_list_entry_t *) + ((char *)l->entries_array + l->entry_size * (l->num_entries - 1)); + if (e >= + (fifo_list_entry_t *) ((char *)l->entries_array + Sizeof_fifo_list(l))) + e -= Sizeof_fifo_list(l); } int -fifo_list_resize_array(fifo_list_t *l) +fifo_list_resize_array(fifo_list_t * l) /* Resize l's entries_array up to l->max_entries * Returns OK on success, ERR if the array is already at maximum size */ { @@ -89,53 +90,56 @@ fifo_list_resize_array(fifo_list_t *l) int old_size = l->array_size; /* sanity check */ - if ( l == NULL ) - die("Invalid argument for fifo_list_resize_array(): list=%d", l); - if ( l->max_entries > 0 && l->array_size >= l->max_entries ) { - debug("Resizing fifo_list_t failed because it is already at max size (size: %d)", - l->array_size); - return ERR; + if (l == NULL) + die("Invalid argument for fifo_list_resize_array(): list=%d", l); + if (l->max_entries > 0 && l->array_size >= l->max_entries) { + debug + ("Resizing fifo_list_t failed because it is already at max size (size: %d)", + l->array_size); + return ERR; } - if ( l->cur_entry != NULL ) - /* Compute cur_entry's offset so as we can set cur_entry to the right place - * after we have allocated a new chunk of memory for the entries_array */ - offset = (char *) l->cur_entry - (char *) l->entries_array; + if (l->cur_entry != NULL) + /* Compute cur_entry's offset so as we can set cur_entry to the right place + * after we have allocated a new chunk of memory for the entries_array */ + offset = (char *)l->cur_entry - (char *)l->entries_array; l->array_size = (l->array_size + l->grow_size); - if ( l->max_entries > 0 && l->array_size > l->max_entries ) - l->array_size = l->max_entries; + if (l->max_entries > 0 && l->array_size > l->max_entries) + l->array_size = l->max_entries; + + debug("Resizing fifo_list_t (old size: %d, new size: %d)...", old_size, + l->array_size); - debug("Resizing fifo_list_t (old size: %d, new size: %d)...", old_size, l->array_size); - - e = alloc_safe(l->array_size*l->entry_size, "larger fifo_list_t array"); + e = alloc_safe(l->array_size * l->entry_size, "larger fifo_list_t array"); memcpy(e, l->entries_array, (l->entry_size * old_size)); Free_safe(l->entries_array); - l->entries_array = e; + l->entries_array = e; - if ( l->cur_entry != NULL ) - l->cur_entry = (fifo_list_entry_t *) ( (char *) l->entries_array + offset ); + if (l->cur_entry != NULL) + l->cur_entry = + (fifo_list_entry_t *) ((char *)l->entries_array + offset); return OK; } -fifo_list_entry_t * -fifo_list_add(fifo_list_t *l, fifo_list_entry_t *e) +fifo_list_entry_t * +fifo_list_add(fifo_list_t * l, fifo_list_entry_t * e) /* Add one entry to the list * Returns a pointer to the added element, or NULL if list is already at max size */ { fifo_list_entry_t *new = NULL; /* sanity check */ - if ( l == NULL || e == NULL ) - die("Invalid arguments for fifo_list_add(): list=%d, entry=%d", l, e); + if (l == NULL || e == NULL) + die("Invalid arguments for fifo_list_add(): list=%d, entry=%d", l, e); /* Check there is some space left, or resize the array */ - if ( l->num_entries >= l->array_size ) { - /* no more space: attempt to grow (the following function dies on error: */ - if ( fifo_list_resize_array(l) != OK ) - return NULL; + if (l->num_entries >= l->array_size) { + /* no more space: attempt to grow (the following function dies on error: */ + if (fifo_list_resize_array(l) != OK) + return NULL; } l->num_entries++; @@ -145,59 +149,61 @@ fifo_list_add(fifo_list_t *l, fifo_list_entry_t *e) return new; } -fifo_list_entry_t * -fifo_list_first(fifo_list_t *l) +fifo_list_entry_t * +fifo_list_first(fifo_list_t * l) /* Return the first entry of the list (then fifo_list_next() can be used) */ { /* sanity check */ - if ( l == NULL ) - die("Invalid argument for fifo_list_first(): list=%d", l); - if ( l->cur_entry != NULL ) - die("fifo_list_first() called but there is already an iteration"); + if (l == NULL) + die("Invalid argument for fifo_list_first(): list=%d", l); + if (l->cur_entry != NULL) + die("fifo_list_first() called but there is already an iteration"); if (l->num_entries > 0) { - l->cur_entry = l->entries_array; + l->cur_entry = l->entries_array; } - + return l->cur_entry; } -fifo_list_entry_t * -fifo_list_next(fifo_list_t *l) +fifo_list_entry_t * +fifo_list_next(fifo_list_t * l) /* Return the entry after e */ { /* // WHAT IF I CALL _ADD() (+RESIZE?) OR _REMOVE() BETWEEN TWO _NEXT CALLS? */ /* sanity checks */ - if ( l == NULL ) - die("Invalid arguments for fifo_list_next(): list=%d", l); - if ( l->cur_entry == NULL ) - die("fifo_list_next() called outside an iteration: l->cur_entry=%d", l->cur_entry); - - if ( l->cur_removed > 0 ) { - l->cur_removed = 0; - /* the current entry has just been removed and replaced by another one: - * we can return the same pointer again. - * However if the removed entry was the last one then we reached the end - * of the list */ - if ( l->cur_entry > fifo_list_last(l) ) - l->cur_entry = NULL; + if (l == NULL) + die("Invalid arguments for fifo_list_next(): list=%d", l); + if (l->cur_entry == NULL) + die("fifo_list_next() called outside an iteration: l->cur_entry=%d", + l->cur_entry); + + if (l->cur_removed > 0) { + l->cur_removed = 0; + /* the current entry has just been removed and replaced by another one: + * we can return the same pointer again. + * However if the removed entry was the last one then we reached the end + * of the list */ + if (l->cur_entry > fifo_list_last(l)) + l->cur_entry = NULL; } else { - /* cur_entry *not* removed (standard behavior) */ - - if ( l->cur_entry < fifo_list_last(l) ) - l->cur_entry = (fifo_list_entry_t *) ( (char *) l->cur_entry + l->entry_size); - else - /* reached the end of the list */ - l->cur_entry = NULL; + /* cur_entry *not* removed (standard behavior) */ + + if (l->cur_entry < fifo_list_last(l)) + l->cur_entry = + (fifo_list_entry_t *) ((char *)l->cur_entry + l->entry_size); + else + /* reached the end of the list */ + l->cur_entry = NULL; } return l->cur_entry; } void -fifo_list_end_iteration(fifo_list_t *list) +fifo_list_end_iteration(fifo_list_t * list) /* Stop an iteration before _next() reached the end of the list by itself */ { list->cur_entry = NULL; @@ -206,21 +212,21 @@ fifo_list_end_iteration(fifo_list_t *list) void -fifo_list_remove_first(fifo_list_t *l) +fifo_list_remove_first(fifo_list_t * l) { /* // MANAGE L->NEXT_ENTRY (+ SPECIAL CASE FIRST/LAST ENTRY) */ fifo_list_entry_t *last = NULL; /* sanity checks */ - if ( l == NULL ) - die("Invalid arguments for fifo_list_remove(): list=%d", l); - if ( l->cur_entry == NULL ) - die("fifo_list_remove_cur() called outside of an iteration"); + if (l == NULL) + die("Invalid arguments for fifo_list_remove(): list=%d", l); + if (l->cur_entry == NULL) + die("fifo_list_remove_cur() called outside of an iteration"); last = fifo_list_last(l); - if ( l->cur_entry < last ) { - /* Override e with the last entry */ - memcpy(l->cur_entry, last, l->entry_size); + if (l->cur_entry < last) { + /* Override e with the last entry */ + memcpy(l->cur_entry, last, l->entry_size); } /* erase the last entry and update the number of entries */ memset(last, 0, l->entry_size); @@ -230,11 +236,11 @@ fifo_list_remove_first(fifo_list_t *l) } fifo_list_t * -fifo_list_destroy(fifo_list_t *list) +fifo_list_destroy(fifo_list_t * list) /* free() the memory allocated for list and returns NULL */ { - if ( list == NULL ) - die("Invalid argument for fifo_list_destroy(): list=%d", list); + if (list == NULL) + die("Invalid argument for fifo_list_destroy(): list=%d", list); Free_safe(list->entries_array); Free_safe(list); diff --git a/fifo_list.h b/fifo_list.h index 947f9e7..7e93745 100644 --- a/fifo_list.h +++ b/fifo_list.h @@ -38,26 +38,28 @@ typedef void fifo_list_entry_t; typedef struct fifo_list_t { /* PUBLIC: */ - int max_entries; /* max allowed element number (0: no limit) */ - int num_entries; /* READ ONLY: num of entries in the list now */ + int max_entries; /* max allowed element number (0: no limit) */ + int num_entries; /* READ ONLY: num of entries in the list now */ /* PRIVATE: DO NOT ACCESS DIRECTLY */ - int array_size; /* size of the array (in number of entries) */ - size_t entry_size; /* number of element currently in the array */ - int grow_size; /* grow array by grow_size entries at a time */ - u_list_entry_t *first_entry; /* Current entry in iteration */ - u_list_entry_t *cur_entry; /* Current entry in iteration - * (null if not in iteration, i.e. X_first() has - * not been called or we reached the list end */ - u_list_entry_t *entries_array; /* pointer to the actual array */ + int array_size; /* size of the array (in number of entries) */ + size_t entry_size; /* number of element currently in the array */ + int grow_size; /* grow array by grow_size entries at a time */ + u_list_entry_t *first_entry; /* Current entry in iteration */ + u_list_entry_t *cur_entry; /* Current entry in iteration + * (null if not in iteration, i.e. X_first() has + * not been called or we reached the list end */ + u_list_entry_t *entries_array; /* pointer to the actual array */ } fifo_list_t; /* functions prototypes */ -extern fifo_list_t *fifo_list_init(size_t entry_size, int init_size, int grow_size); -extern fifo_list_entry_t *fifo_list_add(fifo_list_t *list, fifo_list_entry_t *entry); -extern fifo_list_entry_t *fifo_list_first(fifo_list_t *list); -extern fifo_list_entry_t *fifo_list_next(fifo_list_t *list); -extern void fifo_list_end_iteration(fifo_list_t *list); -extern void fifo_list_remove_first(fifo_list_t *list); -extern fifo_list_t *fifo_list_destroy(fifo_list_t *list); - -#endif /* __FIFO_LIST_H__ */ +extern fifo_list_t *fifo_list_init(size_t entry_size, int init_size, + int grow_size); +extern fifo_list_entry_t *fifo_list_add(fifo_list_t * list, + fifo_list_entry_t * entry); +extern fifo_list_entry_t *fifo_list_first(fifo_list_t * list); +extern fifo_list_entry_t *fifo_list_next(fifo_list_t * list); +extern void fifo_list_end_iteration(fifo_list_t * list); +extern void fifo_list_remove_first(fifo_list_t * list); +extern fifo_list_t *fifo_list_destroy(fifo_list_t * list); + +#endif /* __FIFO_LIST_H__ */ diff --git a/fileconf.c b/fileconf.c index 795812a..7197fb0 100644 --- a/fileconf.c +++ b/fileconf.c @@ -27,24 +27,24 @@ #include "fileconf.h" char *get_string(char *ptr); -int get_line(char *str, size_t size, FILE *file); -void init_default_line(cl_t *cl, cf_t *cf); -char *get_time(char *ptr, time_t *time, int zero_allowed); +int get_line(char *str, size_t size, FILE * file); +void init_default_line(cl_t * cl, cf_t * cf); +char *get_time(char *ptr, time_t * time, int zero_allowed); char *get_num(char *ptr, int *num, int max, short int decimal, - const char **names); + const char **names); char *get_nice(char *ptr, int *nice); char *get_bool(char *ptr, int *i); -char *read_field(char *ptr, bitstr_t *ary, int max, const char **names); -void read_freq(char *ptr, cf_t *cf); -void read_arys(char *ptr, cf_t *cf); -void read_period(char *ptr, cf_t *cf); -int read_shortcut(char *ptr, cf_t *cf); -void read_env(char *ptr, cf_t *cf); -char *read_opt(char *ptr, cl_t *cl); -char *check_username(char *ptr, cf_t *cf, cl_t *cl); +char *read_field(char *ptr, bitstr_t * ary, int max, const char **names); +void read_freq(char *ptr, cf_t * cf); +void read_arys(char *ptr, cf_t * cf); +void read_period(char *ptr, cf_t * cf); +int read_shortcut(char *ptr, cf_t * cf); +void read_env(char *ptr, cf_t * cf); +char *read_opt(char *ptr, cl_t * cl); +char *check_username(char *ptr, cf_t * cf, cl_t * cl); char need_correction; -cl_t default_line; /* default options for a line */ +cl_t default_line; /* default options for a line */ char *file_name; int line; @@ -56,7 +56,7 @@ const char *dows_ary[] = { /* warning : all names must have the same length */ const char *mons_ary[] = { - "jan", "feb", "mar", "apr", "may", "jun", + "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", NULL }; @@ -74,23 +74,23 @@ get_string(char *ptr) int length = 0; char *rtn_string = NULL; - if ( *ptr == '\"' || *ptr == '\'' ) { - quote = *ptr; - ptr++; + if (*ptr == '\"' || *ptr == '\'') { + quote = *ptr; + ptr++; } length = remove_blanks(ptr); - if ( quote != 0 ) { - if ( *(ptr + length - 1) == quote ) - *(ptr + length - 1) = '\0'; - else { - /* mismatched quotes */ - need_correction = 1; - return NULL; - } + if (quote != 0) { + if (*(ptr + length - 1) == quote) + *(ptr + length - 1) = '\0'; + else { + /* mismatched quotes */ + need_correction = 1; + return NULL; + } } - + Set(rtn_string, ptr); return rtn_string; @@ -98,50 +98,49 @@ get_string(char *ptr) int -get_line(char *str, size_t size, FILE *file) +get_line(char *str, size_t size, FILE * file) /* similar to fgets, but increase line if necessary, * and continue over an "\" followed by an "\n" char */ { - size_t size_max = size - 1 ; - int i=0; + size_t size_max = size - 1; + int i = 0; int c; - while (i < size_max ) { - - switch ( c = getc(file) ) { - - case '\n': - /* check if the \n char is preceded by a "\" char : - * in this case, suppress the "\", don't copy the \n, - * and continue */ - if ( i > 0 && *(str + i - 1) == '\\') { - i--; - line++; - continue; - } - else { - *(str + i) = (char) '\0'; - return OK; - } + while (i < size_max) { + + switch (c = getc(file)) { + + case '\n': + /* check if the \n char is preceded by a "\" char : + * in this case, suppress the "\", don't copy the \n, + * and continue */ + if (i > 0 && *(str + i - 1) == '\\') { + i--; + line++; + continue; + } + else { + *(str + i) = (char)'\0'; + return OK; + } break; - - case EOF: - *(str + i) = (char) '\0'; - /* we couldn't return EOF ( equal to ERR by default ) - * nor ERR, which is used for another error */ - return GET_LINE_EOF; - default: - *(str + i) = (char) c; - i++; + case EOF: + *(str + i) = (char)'\0'; + /* we couldn't return EOF ( equal to ERR by default ) + * nor ERR, which is used for another error */ + return GET_LINE_EOF; - } + default: + *(str + i) = (char)c; + i++; + + } } /* line is too long : goto next line and return ERR */ - while ( ( (c = getc(file)) != EOF ) && ( c != '\n') ) - ; + while (((c = getc(file)) != EOF) && (c != '\n')) ; line++; need_correction = 1; return ERR; @@ -149,7 +148,7 @@ get_line(char *str, size_t size, FILE *file) } void -init_default_line(cl_t *cl, cf_t *cf) +init_default_line(cl_t * cl, cf_t * cf) /* clear all context/options from cl */ { bzero(cl, sizeof(cl_t)); @@ -170,10 +169,10 @@ read_file(char *filename, int fd) char buf[LINE_LEN]; int max_lines; int max_entries = MAXENTRIES; - int entries=0; + int entries = 0; char *ptr = NULL; int ret; - + bzero(buf, sizeof(buf)); need_correction = 0; line = 1; @@ -181,10 +180,10 @@ read_file(char *filename, int fd) /* open file */ - if ( (file = fdopen(fd, "r")) == NULL ) { - fprintf(stderr, "Could not open \"%s\": %s\n", file_name, - strerror(errno)); - return ERR; + if ((file = fdopen(fd, "r")) == NULL) { + fprintf(stderr, "Could not open \"%s\": %s\n", file_name, + strerror(errno)); + return ERR; } /* Rewind, just in case */ @@ -195,83 +194,85 @@ read_file(char *filename, int fd) Set(cf->cf_user, user); init_default_line(&default_line, cf); - if ( debug_opt ) - fprintf(stderr, "FILE %s\n", file_name); + if (debug_opt) + fprintf(stderr, "FILE %s\n", file_name); if (strcmp(runas, ROOTNAME) == 0) - max_entries = 65535; + max_entries = 65535; /* max_lines acts here as a security counter to avoid endless loop. */ max_lines = (max_entries * 10) + 10; - while ( entries < max_entries && line <= max_lines ) { + while (entries < max_entries && line <= max_lines) { - ret = get_line(buf, sizeof(buf), file); + ret = get_line(buf, sizeof(buf), file); - if ( ret == ERR ) { - fprintf(stderr, "%s:%d: Line is too long (more than %d): skipping line.\n", - file_name, line, (int)sizeof(buf)); - continue; - } + if (ret == ERR) { + fprintf(stderr, + "%s:%d: Line is too long (more than %d): skipping line.\n", + file_name, line, (int)sizeof(buf)); + continue; + } - ptr = buf; - Skip_blanks(ptr); + ptr = buf; + Skip_blanks(ptr); - if (debug_opt && *ptr != '#' && *ptr != '\0') - fprintf(stderr, " %s\n", buf); + if (debug_opt && *ptr != '#' && *ptr != '\0') + fprintf(stderr, " %s\n", buf); - switch(*ptr) { - case '#': - case '\0': - /* comments or empty line: skipping */ - break; - case '@': + switch (*ptr) { + case '#': + case '\0': + /* comments or empty line: skipping */ + break; + case '@': /* if it is not a shortcut line then read_shortcut() won't do anything. */ - if ( ! read_shortcut(ptr, cf)) + if (!read_shortcut(ptr, cf)) read_freq(ptr, cf); - entries++; - break; - case '&': - read_arys(ptr, cf); - entries++; - break; - case '%': - read_period(ptr, cf); - entries++; - break; - case '!': - ptr = read_opt(ptr, &default_line); - if ( ptr != NULL && *ptr != '\0' ) { - fprintf(stderr, "%s:%d: Syntax error: string \"%s\" ignored\n", - file_name, line, ptr); - need_correction = 1; - } - break; - default: - if ( isdigit( (int) *ptr) || *ptr == '*' ) { - read_arys(ptr, cf); - entries++; - } else - read_env(ptr, cf); - } - - line++; - - if ( ret != OK ) - /* in this case, ret == GET_LINE_EOF : - * no more lines, so we exit the loop */ - break; - + entries++; + break; + case '&': + read_arys(ptr, cf); + entries++; + break; + case '%': + read_period(ptr, cf); + entries++; + break; + case '!': + ptr = read_opt(ptr, &default_line); + if (ptr != NULL && *ptr != '\0') { + fprintf(stderr, "%s:%d: Syntax error: string \"%s\" ignored\n", + file_name, line, ptr); + need_correction = 1; + } + break; + default: + if (isdigit((int)*ptr) || *ptr == '*') { + read_arys(ptr, cf); + entries++; + } + else + read_env(ptr, cf); + } + + line++; + + if (ret != OK) + /* in this case, ret == GET_LINE_EOF : + * no more lines, so we exit the loop */ + break; + } if (entries == max_entries) { - error("%s:%d: maximum number of entries (%d) has been reached by %s", - file_name, line, user); - fprintf(stderr, "Anything after this line will be ignored\n"); + error("%s:%d: maximum number of entries (%d) has been reached by %s", + file_name, line, user); + fprintf(stderr, "Anything after this line will be ignored\n"); } else if (line == max_lines) - error("%s:%d: maximum number of lines (%d) has been reached by %s", - file_name, line, user); + error("%s:%d: maximum number of lines (%d) has been reached by %s", + file_name, line, user); cf->cf_next = file_base; file_base = cf; @@ -279,96 +280,96 @@ read_file(char *filename, int fd) /* don't close as underlying fd may still be used by calling function */ if (fflush(file) != 0) error_e("could not fflush() file_name"); - + Free_safe(default_line.cl_runas); Free_safe(default_line.cl_mailto); Free_safe(default_line.cl_tz); - if ( ! need_correction ) - return OK; + if (!need_correction) + return OK; else - return 2; + return 2; } void -read_env(char *ptr, cf_t *cf) +read_env(char *ptr, cf_t * cf) /* append env variable list. * (remove blanks) */ { char name[LINE_LEN]; - int j=0; + int j = 0; char *val = NULL; bzero(name, sizeof(name)); /* copy env variable's name */ - while ( (isalnum( (int) *ptr) || *ptr == '_') && *ptr != '=' - && ! isspace( (int) *ptr) && j < sizeof(name) ) { - name[j++] = *ptr; - ptr++; + while ((isalnum((int)*ptr) || *ptr == '_') && *ptr != '=' + && !isspace((int)*ptr) && j < sizeof(name)) { + name[j++] = *ptr; + ptr++; } name[j] = '\0'; - if ( name[0] == '\0' ) - goto error; + if (name[0] == '\0') + goto error; /* skip '=' and spaces around */ - while ( isspace( (int) *ptr) ) - ptr++; + while (isspace((int)*ptr)) + ptr++; /* if j == 0 name is a zero length string */ - if ( *ptr++ != '=' || j == 0 ) - goto error; + if (*ptr++ != '=' || j == 0) + goto error; - while ( isspace( (int) *ptr) ) - ptr++; + while (isspace((int)*ptr)) + ptr++; /* get value */ - if ( ( val = get_string(ptr)) == NULL ) { - fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", - file_name, line); - need_correction = 1; - return; + if ((val = get_string(ptr)) == NULL) { + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); + need_correction = 1; + return; } if (debug_opt) - fprintf(stderr, " Env : '%s=%s'\n", name, val); + fprintf(stderr, " Env : '%s=%s'\n", name, val); /* we ignore USER/LOGNAME's assignment */ - if ( strcmp(name, "USER") == 0 || strcmp(name, "LOGNAME") == 0 ) { - fprintf(stderr, "%s:%d: USER or LOGNAME assignement is not allowed: ignored.\n", - file_name, line); - return; + if (strcmp(name, "USER") == 0 || strcmp(name, "LOGNAME") == 0) { + fprintf(stderr, + "%s:%d: USER or LOGNAME assignement is not allowed: ignored.\n", + file_name, line); + return; } /* the MAILTO assignment is, in fact, an fcron option : * we don't store it in the same way. */ /* please note that we check if the mailto is valid in conf.c */ - if ( strcmp(name, "MAILTO") == 0 ) { - if ( strcmp(val, "\0") == 0 ) { - clear_mail(default_line.cl_option); - clear_mailzerolength(default_line.cl_option); - } - else { - Set(default_line.cl_mailto, val); - set_mail(default_line.cl_option); - } - + if (strcmp(name, "MAILTO") == 0) { + if (strcmp(val, "\0") == 0) { + clear_mail(default_line.cl_option); + clear_mailzerolength(default_line.cl_option); + } + else { + Set(default_line.cl_mailto, val); + set_mail(default_line.cl_option); + } + } else { env_list_setenv(cf->cf_env_list, name, val, 1); } - + Free_safe(val); return; - error: - fprintf(stderr, "%s:%d: Syntax error: skipping line.\n", - file_name, line); - need_correction = 1; - return; + error: + fprintf(stderr, "%s:%d: Syntax error: skipping line.\n", file_name, line); + need_correction = 1; + return; } @@ -379,23 +380,23 @@ get_nice(char *ptr, int *nice) { char negative = 0; - if ( *ptr == '-' ) { - negative = 1; - ptr++; + if (*ptr == '-') { + negative = 1; + ptr++; } - if ( (ptr = get_num(ptr, nice, 20, 0, NULL)) == NULL ) - return NULL; + if ((ptr = get_num(ptr, nice, 20, 0, NULL)) == NULL) + return NULL; - if ( negative == 1 ) { - if (getuid() != rootuid) { - fprintf(stderr, "must be privileged to use a negative argument " - "with nice: set to 0\n"); - need_correction = 1; - *nice = 0; - } + if (negative == 1) { + if (getuid() != rootuid) { + fprintf(stderr, "must be privileged to use a negative argument " + "with nice: set to 0\n"); + need_correction = 1; + *nice = 0; + } - *nice *= (-1); + *nice *= (-1); } return ptr; @@ -415,21 +416,20 @@ assign_option_string(char **var, char *value) Free_safe(*var); /* look for the end of the option value */ - while ( ptr != NULL && *ptr != ')' ) { + while (ptr != NULL && *ptr != ')') { ptr++; len++; } - if ( len <= 0 ) { + if (len <= 0) { return len; } - end = ptr-1; + end = ptr - 1; /* spaces and quotes are not allowed before or after the value */ - if ( isspace((int) *start) || isspace((int) *end) - || *start == '\'' || *start == '\"' - || *end == '\'' || *end == '\"' ) { + if (isspace((int)*start) || isspace((int)*end) + || *start == '\'' || *start == '\"' || *end == '\'' || *end == '\"') { return -1; } @@ -444,50 +444,50 @@ get_bool(char *ptr, int *i) /* get a bool value : either true (1) or false (0) * return NULL on error */ { - if ( *ptr == '1' ) - goto true; - else if ( *ptr == '0' ) - goto false; - else if ( strncmp(ptr, "true", 4) == 0 ) { - ptr += 3; - goto true; + if (*ptr == '1') + goto true; + else if (*ptr == '0') + goto false; + else if (strncmp(ptr, "true", 4) == 0) { + ptr += 3; + goto true; } - else if ( strncmp(ptr, "yes", 3) == 0 ) { - ptr += 2; - goto true; + else if (strncmp(ptr, "yes", 3) == 0) { + ptr += 2; + goto true; } - else if ( strncmp(ptr, "false", 5) == 0 ) { - ptr += 4; - goto false; + else if (strncmp(ptr, "false", 5) == 0) { + ptr += 4; + goto false; } - else if ( strncmp(ptr, "no", 2) == 0 ) { - ptr += 1; - goto false; + else if (strncmp(ptr, "no", 2) == 0) { + ptr += 1; + goto false; } else - return NULL; + return NULL; - true: + true: *i = 1; ptr++; return ptr; - false: + false: *i = 0; ptr++; return ptr; - + } char * -read_opt(char *ptr, cl_t *cl) +read_opt(char *ptr, cl_t * cl) /* read one or several options and fill in the field "option" */ { char opt_name[20]; int i; char in_brackets; - + #define Handle_err \ { \ fprintf(stderr, "%s:%d: Argument(s) for option \"%s\" not valid: " \ @@ -496,482 +496,491 @@ read_opt(char *ptr, cl_t *cl) return NULL; \ } - if ( *ptr == '!' ) - ptr++; - - do { - i = 0; - bzero(opt_name, sizeof(opt_name)); - - while ( isalnum( (int) *ptr) && i < sizeof(opt_name)) - opt_name[i++] = *ptr++; - - i = 1; - in_brackets = 0; - - if ( *ptr == '(' ) { - in_brackets = 1; - ptr++; - } - - /* spaces are not allowed -- make sure there is no leading space. */ - if ( isspace( (int) *ptr) ) { - Handle_err; - } - - /* global options for a file */ - - if ( strcmp(opt_name, "tzdiff") == 0 ) { - char negative = 0; - - if ( ! in_brackets ) - Handle_err; - if ( *ptr == '-' ) { - negative = 1; - ptr++; - } - if ( (ptr = get_num(ptr, &i, 24, 0, NULL)) == NULL ) - Handle_err; - if ( negative ) - cl->cl_file->cf_tzdiff = (- i); - else - cl->cl_file->cf_tzdiff = i; - - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" (-)%d\n", opt_name, i); - } - - /* options related to a line (or a set of lines) */ - - else if ( strcmp(opt_name, "timezone") == 0 ) { + if (*ptr == '!') + ptr++; + + do { + i = 0; + bzero(opt_name, sizeof(opt_name)); + + while (isalnum((int)*ptr) && i < sizeof(opt_name)) + opt_name[i++] = *ptr++; + + i = 1; + in_brackets = 0; + + if (*ptr == '(') { + in_brackets = 1; + ptr++; + } + + /* spaces are not allowed -- make sure there is no leading space. */ + if (isspace((int)*ptr)) { + Handle_err; + } + + /* global options for a file */ + + if (strcmp(opt_name, "tzdiff") == 0) { + char negative = 0; + + if (!in_brackets) + Handle_err; + if (*ptr == '-') { + negative = 1; + ptr++; + } + if ((ptr = get_num(ptr, &i, 24, 0, NULL)) == NULL) + Handle_err; + if (negative) + cl->cl_file->cf_tzdiff = (-i); + else + cl->cl_file->cf_tzdiff = i; + + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" (-)%d\n", opt_name, i); + } + + /* options related to a line (or a set of lines) */ + + else if (strcmp(opt_name, "timezone") == 0) { int len = -1; - if ( ! in_brackets ) { - Handle_err; + if (!in_brackets) { + Handle_err; } len = assign_option_string(&(cl->cl_tz), ptr); - if ( len < 0 ) { - Handle_err; + if (len < 0) { + Handle_err; } else { ptr += len; } if (debug_opt) { - fprintf(stderr, " Opt : \"%s\" \"%s\"\n", opt_name, cl->cl_tz); + fprintf(stderr, " Opt : \"%s\" \"%s\"\n", opt_name, cl->cl_tz); } - } - - - else if(strcmp(opt_name, "s") == 0 || strcmp(opt_name, "serial") == 0){ - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - clear_serial(cl->cl_option); - else - set_serial(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if (strcmp(opt_name, "serialonce") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - set_serial_sev(cl->cl_option); - else - clear_serial_sev(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if (strcmp(opt_name, "lavgonce") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - set_lavg_sev(cl->cl_option); - else - clear_lavg_sev(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if (strcmp(opt_name, "exesev") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - clear_exe_sev(cl->cl_option); - else - set_exe_sev(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if(strcmp(opt_name, "b")==0 || strcmp(opt_name, "bootrun")==0){ - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_bootrun(cl->cl_option); - else - set_bootrun(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if(strcmp(opt_name, "rebootreset")==0) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_rebootreset(cl->cl_option); - else - set_rebootreset(cl->cl_option); + } + + + else if (strcmp(opt_name, "s") == 0 || strcmp(opt_name, "serial") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_serial(cl->cl_option); + else + set_serial(cl->cl_option); if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "serialonce") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_serial_sev(cl->cl_option); + else + clear_serial_sev(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + else if (strcmp(opt_name, "lavgonce") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_lavg_sev(cl->cl_option); + else + clear_lavg_sev(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } - else if(strcmp(opt_name, "runatreboot")==0){ - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_runatreboot(cl->cl_option); - else + else if (strcmp(opt_name, "exesev") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_exe_sev(cl->cl_option); + else + set_exe_sev(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "b") == 0 || strcmp(opt_name, "bootrun") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_bootrun(cl->cl_option); + else + set_bootrun(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "rebootreset") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_rebootreset(cl->cl_option); + else + set_rebootreset(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + + else if (strcmp(opt_name, "runatreboot") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_runatreboot(cl->cl_option); + else set_runatreboot(cl->cl_option); if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } - else if(strcmp(opt_name, "runonce")==0){ - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_runonce(cl->cl_option); - else + else if (strcmp(opt_name, "runonce") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_runonce(cl->cl_option); + else set_runonce(cl->cl_option); if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } - else if( strcmp(opt_name, "reset")==0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 1 ) { + else if (strcmp(opt_name, "reset") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 1) { init_default_line(cl, cl->cl_file); - } - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - - else if(strcmp(opt_name, "f") == 0 || strcmp(opt_name, "first") == 0) { - if( ! in_brackets || (ptr=get_time(ptr, &(cl->cl_first), 1)) == NULL ) - Handle_err; - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %ld\n", opt_name, - (long int)cl->cl_first); - } - - else if(strcmp(opt_name, "r")==0 || strcmp(opt_name, "runfreq")==0) { - if ( cl->cl_runfreq == 1 ) { - fprintf(stderr, "cannot change runfreq value in a %%-line"); - Handle_err; - } - if ( !in_brackets || (ptr=get_num(ptr,&i,USHRT_MAX,0,NULL)) == NULL) - Handle_err; - if (i <= 1) { - fprintf(stderr, "runfreq must be 2 or more.\n"); - Handle_err; - } - cl->cl_runfreq = i; - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "strict") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - clear_strict(cl->cl_option); - else - set_strict(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "noticenotrun") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if (i == 0 ) - clear_notice_notrun(cl->cl_option); - else - set_notice_notrun(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "lavg") == 0 ) { - if (!in_brackets || (ptr=get_num(ptr,&i,UCHAR_MAX,1,NULL)) == NULL) - Handle_err; - cl->cl_lavg[0] = i; - if (debug_opt) - fprintf(stderr, " Opt : 'lavg1' %d\n", i); - if ( *ptr++ != ',' ) - Handle_err; - if (!in_brackets || (ptr=get_num(ptr,&i,UCHAR_MAX,1,NULL)) == NULL) - Handle_err; - cl->cl_lavg[1] = i; - if (debug_opt) - fprintf(stderr, " Opt : 'lavg5' %d\n", i); - if ( *ptr++ != ',' ) - Handle_err; - if(!in_brackets || (ptr=get_num(ptr,&i,UCHAR_MAX,1,NULL)) == NULL ) - Handle_err; - cl->cl_lavg[2] = i; - if (debug_opt) - fprintf(stderr, " Opt : 'lavg15' %d\n", i); - if ( cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2] ) - set_lavg(cl->cl_option); - else - clear_lavg(cl->cl_option); + } + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + + else if (strcmp(opt_name, "f") == 0 || strcmp(opt_name, "first") == 0) { + if (!in_brackets + || (ptr = get_time(ptr, &(cl->cl_first), 1)) == NULL) + Handle_err; + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %ld\n", opt_name, + (long int)cl->cl_first); + } + + else if (strcmp(opt_name, "r") == 0 || strcmp(opt_name, "runfreq") == 0) { + if (cl->cl_runfreq == 1) { + fprintf(stderr, "cannot change runfreq value in a %%-line"); + Handle_err; + } + if (!in_brackets + || (ptr = get_num(ptr, &i, USHRT_MAX, 0, NULL)) == NULL) + Handle_err; + if (i <= 1) { + fprintf(stderr, "runfreq must be 2 or more.\n"); + Handle_err; + } + cl->cl_runfreq = i; + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "strict") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_strict(cl->cl_option); + else + set_strict(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "noticenotrun") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_notice_notrun(cl->cl_option); + else + set_notice_notrun(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "lavg") == 0) { + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[0] = i; + if (debug_opt) + fprintf(stderr, " Opt : 'lavg1' %d\n", i); + if (*ptr++ != ',') + Handle_err; + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[1] = i; + if (debug_opt) + fprintf(stderr, " Opt : 'lavg5' %d\n", i); + if (*ptr++ != ',') + Handle_err; + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[2] = i; + if (debug_opt) + fprintf(stderr, " Opt : 'lavg15' %d\n", i); + if (cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2]) + set_lavg(cl->cl_option); + else + clear_lavg(cl->cl_option); #ifdef NOLOADAVG - warn("As fcron has been compiled with no procfs support,\n" - "you will not be able to use the lavg* options"); -#endif /* NOLOADAVG */ - } - - else if( strcmp(opt_name, "lavg1") == 0 ) { - if(!in_brackets ||(ptr=get_num(ptr, &i, UCHAR_MAX, 1, NULL))==NULL) - Handle_err; - cl->cl_lavg[0] = i; - if ( cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2] ) - set_lavg(cl->cl_option); - else - clear_lavg(cl->cl_option); + warn("As fcron has been compiled with no procfs support,\n" + "you will not be able to use the lavg* options"); +#endif /* NOLOADAVG */ + } + + else if (strcmp(opt_name, "lavg1") == 0) { + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[0] = i; + if (cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2]) + set_lavg(cl->cl_option); + else + clear_lavg(cl->cl_option); #if NOLOADAVG - warn("As fcron has been compiled with no procfs support,\n" - "you will not be able to use the lavg* options"); -#endif /* NOLOADAVG */ - if (debug_opt) - fprintf(stderr, " Opt : 'lavg1' %d\n", i); - } - - else if( strcmp(opt_name, "lavg5") == 0 ) { - if(!in_brackets ||(ptr=get_num(ptr, &i, UCHAR_MAX, 1, NULL))==NULL) - Handle_err; - cl->cl_lavg[1] = i; - if ( cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2] ) - set_lavg(cl->cl_option); - else - clear_lavg(cl->cl_option); + warn("As fcron has been compiled with no procfs support,\n" + "you will not be able to use the lavg* options"); +#endif /* NOLOADAVG */ + if (debug_opt) + fprintf(stderr, " Opt : 'lavg1' %d\n", i); + } + + else if (strcmp(opt_name, "lavg5") == 0) { + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[1] = i; + if (cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2]) + set_lavg(cl->cl_option); + else + clear_lavg(cl->cl_option); #ifdef NOLOADAVG - warn("As fcron has been compiled with no procfs support,\n" - "you will not be able to use the lavg* options"); -#endif /* NOLOADAVG = 0 */ - if (debug_opt) - fprintf(stderr, " Opt : 'lavg5' %d\n", i); - } - - else if( strcmp(opt_name, "lavg15") == 0 ) { - if(!in_brackets ||(ptr=get_num(ptr, &i, UCHAR_MAX, 1, NULL))==NULL) - Handle_err; - cl->cl_lavg[2] = i; - if ( cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2] ) - set_lavg(cl->cl_option); - else - clear_lavg(cl->cl_option); + warn("As fcron has been compiled with no procfs support,\n" + "you will not be able to use the lavg* options"); +#endif /* NOLOADAVG = 0 */ + if (debug_opt) + fprintf(stderr, " Opt : 'lavg5' %d\n", i); + } + + else if (strcmp(opt_name, "lavg15") == 0) { + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 1, NULL)) == NULL) + Handle_err; + cl->cl_lavg[2] = i; + if (cl->cl_lavg[0] || cl->cl_lavg[1] || cl->cl_lavg[2]) + set_lavg(cl->cl_option); + else + clear_lavg(cl->cl_option); #ifdef NOLOADAVG - warn("As fcron has been compiled with no procfs support,\n" - "you will not be able to use the lavg* options"); -#endif /* NOLOADAVG = 0 */ - if (debug_opt) - fprintf(stderr, " Opt : 'lavg15' %d\n", i); - } - - else if( strcmp(opt_name, "lavgand") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - set_lor(cl->cl_option); - else - set_land(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if( strcmp(opt_name, "lavgor") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - set_land(cl->cl_option); - else - set_lor(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if(strcmp(opt_name, "u") == 0 || strcmp(opt_name, "until") == 0) { - if( ! in_brackets || (ptr=get_time(ptr, &(cl->cl_until), 0)) == NULL ) - Handle_err; - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %ld\n", opt_name, - (long int)cl->cl_until); - } - - else if(strcmp(opt_name, "m")==0 || strcmp(opt_name, "mail")==0){ - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) { - clear_mail(cl->cl_option); - clear_mailzerolength(cl->cl_option); + warn("As fcron has been compiled with no procfs support,\n" + "you will not be able to use the lavg* options"); +#endif /* NOLOADAVG = 0 */ + if (debug_opt) + fprintf(stderr, " Opt : 'lavg15' %d\n", i); + } + + else if (strcmp(opt_name, "lavgand") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_lor(cl->cl_option); + else + set_land(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "lavgor") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_land(cl->cl_option); + else + set_lor(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "u") == 0 || strcmp(opt_name, "until") == 0) { + if (!in_brackets + || (ptr = get_time(ptr, &(cl->cl_until), 0)) == NULL) + Handle_err; + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %ld\n", opt_name, + (long int)cl->cl_until); + } + + else if (strcmp(opt_name, "m") == 0 || strcmp(opt_name, "mail") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) { + clear_mail(cl->cl_option); + clear_mailzerolength(cl->cl_option); } - else - set_mail(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if( strcmp(opt_name, "forcemail") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_mailzerolength(cl->cl_option); - else { - set_mailzerolength(cl->cl_option); - set_mail(cl->cl_option); + else + set_mail(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "forcemail") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_mailzerolength(cl->cl_option); + else { + set_mailzerolength(cl->cl_option); + set_mail(cl->cl_option); } - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } - else if( strcmp(opt_name, "mailto") == 0) { + else if (strcmp(opt_name, "mailto") == 0) { int len = -1; - if ( ! in_brackets ) { - Handle_err; + if (!in_brackets) { + Handle_err; } - /* please note that we check if the mailto is valid in conf.c */ + /* please note that we check if the mailto is valid in conf.c */ len = assign_option_string(&(cl->cl_mailto), ptr); - if ( len < 0 ) { - Handle_err; + if (len < 0) { + Handle_err; } - else if ( len == 0 ) { - clear_mail(cl->cl_option); - clear_mailzerolength(cl->cl_option); + else if (len == 0) { + clear_mail(cl->cl_option); + clear_mailzerolength(cl->cl_option); } else { ptr += len; set_mail(cl->cl_option); } - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" \"%s\"\n", opt_name, cl->cl_mailto); - } - - else if( strcmp(opt_name, "erroronlymail") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_erroronlymail(cl->cl_option); - else - set_erroronlymail(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if( strcmp(opt_name, "dayand") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - set_dayor(cl->cl_option); - else - set_dayand(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if( strcmp(opt_name, "dayor") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - set_dayand(cl->cl_option); - else - set_dayor(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "nolog") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_nolog(cl->cl_option); - else - set_nolog(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "volatile") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_volatile(cl->cl_option); - else - set_volatile(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if ( strcmp(opt_name, "stdout") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_stdout(cl->cl_option); - else - set_stdout(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if(strcmp(opt_name, "n") == 0 || strcmp(opt_name, "nice") == 0) { - if( ! in_brackets || (ptr = get_nice(ptr, &i)) == NULL ) - Handle_err; - cl->cl_nice = (char)i; - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" (-)%d\n", opt_name, i); - } - - else if(strcmp(opt_name, "runas") == 0) { + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" \"%s\"\n", opt_name, + cl->cl_mailto); + } + + else if (strcmp(opt_name, "erroronlymail") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_erroronlymail(cl->cl_option); + else + set_erroronlymail(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "dayand") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_dayor(cl->cl_option); + else + set_dayand(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "dayor") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + set_dayand(cl->cl_option); + else + set_dayor(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "nolog") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_nolog(cl->cl_option); + else + set_nolog(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "volatile") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_volatile(cl->cl_option); + else + set_volatile(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "stdout") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_stdout(cl->cl_option); + else + set_stdout(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "n") == 0 || strcmp(opt_name, "nice") == 0) { + if (!in_brackets || (ptr = get_nice(ptr, &i)) == NULL) + Handle_err; + cl->cl_nice = (char)i; + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" (-)%d\n", opt_name, i); + } + + else if (strcmp(opt_name, "runas") == 0) { int len = -1; char *runas = NULL; struct passwd *pas; - if ( ! in_brackets ) { - Handle_err; + if (!in_brackets) { + Handle_err; } len = assign_option_string(&runas, ptr); - if ( len < 0 ) { - Handle_err; + if (len < 0) { + Handle_err; } else { ptr += len; } - if (getuid() != rootuid) { - fprintf(stderr, "must be privileged to use option runas: " - "skipping option\n"); - need_correction = 1; + if (getuid() != rootuid) { + fprintf(stderr, "must be privileged to use option runas: " + "skipping option\n"); + need_correction = 1; } - else if ( len > USER_NAME_LEN ) { - fprintf(stderr, "runas: user name \"%s\" longer than %d" - "characters: skipping option\n", - runas, USER_NAME_LEN); - need_correction = 1; + else if (len > USER_NAME_LEN) { + fprintf(stderr, "runas: user name \"%s\" longer than %d" + "characters: skipping option\n", runas, USER_NAME_LEN); + need_correction = 1; } - else if ((pas = getpwnam(runas)) == NULL) { + else if ((pas = getpwnam(runas)) == NULL) { fprintf(stderr, "runas: \"%s\" is not in passwd file : " "ignored", runas); need_correction = 1; @@ -988,206 +997,207 @@ read_opt(char *ptr, cl_t *cl) /* all good */ if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %s ptr=%p\n", opt_name, cl->cl_runas, cl->cl_runas); - - } - - else if( strcmp(opt_name, "random") == 0 ) { - if ( in_brackets && (ptr = get_bool(ptr, &i)) == NULL ) - Handle_err; - if ( i == 0 ) - clear_random(cl->cl_option); - else - set_random(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - else if( strcmp(opt_name, "jitter") == 0 ) { - if(!in_brackets ||(ptr=get_num(ptr, &i, UCHAR_MAX, 0, NULL))==NULL) - Handle_err; - cl->cl_jitter = i; - if (debug_opt) - fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); - } - - /* handle %-line : we check if we are really in a %-line (which we do not do - * for other options), because writing "&hourly" in a fcrontab results in an - * error (hourly ignored) hard to find, and, in any case, annoying. */ - else if ( cl->cl_runfreq == 1 ) { - /* options to run once per interval : - * ignore every fields below the limit */ - if (strcmp(opt_name, "mins") == 0) { - /* nothing to do */ - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "hours") == 0) { - set_freq_mins(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "days") == 0) { - set_freq_mins(cl->cl_option); - set_freq_hrs(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "mons") == 0) { - set_freq_mins(cl->cl_option); - set_freq_hrs(cl->cl_option); - set_freq_days(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "dow") == 0) { - set_freq_mins(cl->cl_option); - set_freq_hrs(cl->cl_option); - set_freq_days(cl->cl_option); - set_freq_mons(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - - /* run once an element of the selected field - * (once an hour, once a day, etc) */ - else if (strcmp(opt_name, "hourly") == 0) { - set_freq_hrs(cl->cl_option); - set_freq_periodically(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "daily") == 0) { - set_freq_days(cl->cl_option); - set_freq_periodically(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "monthly") == 0) { - set_freq_mons(cl->cl_option); - set_freq_periodically(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "weekly") == 0) { - set_freq_dow(cl->cl_option); - set_freq_periodically(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - - /* run once an element of the selected field - * from middle to middle of that field - * (ie once from 12h to 12h the following day) */ - else if (strcmp(opt_name, "midhourly") == 0) { - set_freq_hrs(cl->cl_option); - set_freq_periodically(cl->cl_option); - set_freq_mid(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "middaily") == 0 - || strcmp(opt_name, "nightly") == 0) { - set_freq_days(cl->cl_option); - set_freq_periodically(cl->cl_option); - set_freq_mid(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "midmonthly") == 0) { - set_freq_mons(cl->cl_option); - set_freq_periodically(cl->cl_option); - set_freq_mid(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - else if (strcmp(opt_name, "midweekly") == 0) { - set_freq_dow(cl->cl_option); - set_freq_periodically(cl->cl_option); - set_freq_mid(cl->cl_option); - if (debug_opt) - fprintf(stderr, " Opt : \"%s\"\n", opt_name); - } - } - - else { - fprintf(stderr, "%s:%d: Option \"%s\" unknown: " - "skipping option.\n", file_name, line, opt_name); - need_correction = 1; - } - - if ( in_brackets ) { - if ( *ptr != ')' ) - { Handle_err } - else - ptr++; - } - - } while ( *ptr == ',' && ptr++); - + fprintf(stderr, " Opt : \"%s\" %s ptr=%p\n", opt_name, + cl->cl_runas, cl->cl_runas); + + } + + else if (strcmp(opt_name, "random") == 0) { + if (in_brackets && (ptr = get_bool(ptr, &i)) == NULL) + Handle_err; + if (i == 0) + clear_random(cl->cl_option); + else + set_random(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + else if (strcmp(opt_name, "jitter") == 0) { + if (!in_brackets + || (ptr = get_num(ptr, &i, UCHAR_MAX, 0, NULL)) == NULL) + Handle_err; + cl->cl_jitter = i; + if (debug_opt) + fprintf(stderr, " Opt : \"%s\" %d\n", opt_name, i); + } + + /* handle %-line : we check if we are really in a %-line (which we do not do + * for other options), because writing "&hourly" in a fcrontab results in an + * error (hourly ignored) hard to find, and, in any case, annoying. */ + else if (cl->cl_runfreq == 1) { + /* options to run once per interval : + * ignore every fields below the limit */ + if (strcmp(opt_name, "mins") == 0) { + /* nothing to do */ + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "hours") == 0) { + set_freq_mins(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "days") == 0) { + set_freq_mins(cl->cl_option); + set_freq_hrs(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "mons") == 0) { + set_freq_mins(cl->cl_option); + set_freq_hrs(cl->cl_option); + set_freq_days(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "dow") == 0) { + set_freq_mins(cl->cl_option); + set_freq_hrs(cl->cl_option); + set_freq_days(cl->cl_option); + set_freq_mons(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + + /* run once an element of the selected field + * (once an hour, once a day, etc) */ + else if (strcmp(opt_name, "hourly") == 0) { + set_freq_hrs(cl->cl_option); + set_freq_periodically(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "daily") == 0) { + set_freq_days(cl->cl_option); + set_freq_periodically(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "monthly") == 0) { + set_freq_mons(cl->cl_option); + set_freq_periodically(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "weekly") == 0) { + set_freq_dow(cl->cl_option); + set_freq_periodically(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + + /* run once an element of the selected field + * from middle to middle of that field + * (ie once from 12h to 12h the following day) */ + else if (strcmp(opt_name, "midhourly") == 0) { + set_freq_hrs(cl->cl_option); + set_freq_periodically(cl->cl_option); + set_freq_mid(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "middaily") == 0 + || strcmp(opt_name, "nightly") == 0) { + set_freq_days(cl->cl_option); + set_freq_periodically(cl->cl_option); + set_freq_mid(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "midmonthly") == 0) { + set_freq_mons(cl->cl_option); + set_freq_periodically(cl->cl_option); + set_freq_mid(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + else if (strcmp(opt_name, "midweekly") == 0) { + set_freq_dow(cl->cl_option); + set_freq_periodically(cl->cl_option); + set_freq_mid(cl->cl_option); + if (debug_opt) + fprintf(stderr, " Opt : \"%s\"\n", opt_name); + } + } + + else { + fprintf(stderr, "%s:%d: Option \"%s\" unknown: " + "skipping option.\n", file_name, line, opt_name); + need_correction = 1; + } + + if (in_brackets) { + if (*ptr != ')') { + Handle_err} + else + ptr++; + } + + } while (*ptr == ',' && ptr++); + Skip_blanks(ptr); return ptr; } char * -get_time(char *ptr, time_t *time, int zero_allowed) +get_time(char *ptr, time_t * time, int zero_allowed) /* convert time read in string in time_t format */ { time_t sum; - - *time = 0 ; - - while( (*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0') && - (*ptr != ')') ) { - - sum = 0; - - while ( isdigit( (int) *ptr) ) { - sum *= 10; - sum += *ptr - 48; - ptr++; - } - - /* interpret multipliers */ - switch (*ptr) { - case 'm': /* months */ - sum *= 4; - case 'w': /* weeks */ - sum *= 7; - case 'd': /* days */ - sum *= 24; - case 'h': /* hours */ - sum *= 3600; - case 's': /* seconds */ - ptr++; - break; - case ' ': - case '\t': - case ')': - sum *= 60; /* minutes */ - break; - default: - need_correction = 1; - return NULL; - } - - *time += sum; + + *time = 0; + + while ((*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0') && (*ptr != ')')) { + + sum = 0; + + while (isdigit((int)*ptr)) { + sum *= 10; + sum += *ptr - 48; + ptr++; + } + + /* interpret multipliers */ + switch (*ptr) { + case 'm': /* months */ + sum *= 4; + case 'w': /* weeks */ + sum *= 7; + case 'd': /* days */ + sum *= 24; + case 'h': /* hours */ + sum *= 3600; + case 's': /* seconds */ + ptr++; + break; + case ' ': + case '\t': + case ')': + sum *= 60; /* minutes */ + break; + default: + need_correction = 1; + return NULL; + } + + *time += sum; } Skip_blanks(ptr); - if (*time == 0 && ! zero_allowed) { - need_correction = 1; - return NULL; + if (*time == 0 && !zero_allowed) { + need_correction = 1; + return NULL; } else - return ptr; + return ptr; } char * -check_username(char *ptr, cf_t *cf, cl_t *cl) +check_username(char *ptr, cf_t * cf, cl_t * cl) /* check ptr to see if the first word is a username, returns new ptr */ { short int indx = 0; @@ -1197,24 +1207,27 @@ check_username(char *ptr, cf_t *cf, cl_t *cl) /* check to see if next word is a username */ /* we don't allow quotes, to be able to distinguish a user name from * a command line (where quotes are allowed) */ - while ( isalnum( (int) ptr[indx]) || ptr[indx] == '-' || ptr[indx] == '_' ) indx++; - if (indx >= USER_NAME_LEN) indx = USER_NAME_LEN - 1; + while (isalnum((int)ptr[indx]) || ptr[indx] == '-' || ptr[indx] == '_') + indx++; + if (indx >= USER_NAME_LEN) + indx = USER_NAME_LEN - 1; strncpy(username, ptr, indx); username[indx] = '\0'; if ((userpwent = getpwnam(username)) != NULL) { - /* found the user */ - ptr = ptr + indx; /* move ptr to the next word */ - Skip_blanks(ptr); - - if (getuid() != rootuid) { - fprintf(stderr, "must be privileged to run as another user : " - "ignoring\n"); - } else { - Set(cl->cl_runas, username); + /* found the user */ + ptr = ptr + indx; /* move ptr to the next word */ + Skip_blanks(ptr); + + if (getuid() != rootuid) { + fprintf(stderr, "must be privileged to run as another user : " + "ignoring\n"); + } + else { + Set(cl->cl_runas, username); if (debug_opt) - fprintf(stderr, " Opt : inline_runas %s\n", username); - } + fprintf(stderr, " Opt : inline_runas %s\n", username); + } } return ptr; @@ -1230,14 +1243,14 @@ read_word(char *ptr, char *buf, size_t buf_size) bzero(buf, buf_size); - while ( isalnum( (int) *ptr) && i < buf_size ) + while (isalnum((int)*ptr) && i < buf_size) buf[i++] = *ptr++; return ptr; } int -read_shortcut(char *ptr, cf_t *cf) +read_shortcut(char *ptr, cf_t * cf) /* try to read a shortcut entry, and if it is one then append a line to cf * Return 1 if that was a shortcut entry. If it wasn't, return 0 and make sure * ptr is back to its orig value. */ @@ -1255,9 +1268,9 @@ read_shortcut(char *ptr, cf_t *cf) /* time&date by default -- we'll switch to freq if @reboot */ set_td(cl->cl_option); - cl->cl_remain = cl->cl_runfreq; /* FIXME: necessary?? */ + cl->cl_remain = cl->cl_runfreq; /* FIXME: necessary?? */ - if ( strcmp(shortcut, "reboot") == 0 ) { + if (strcmp(shortcut, "reboot") == 0) { set_freq(cl->cl_option); set_runatreboot(cl->cl_option); set_runonce(cl->cl_option); @@ -1268,30 +1281,31 @@ read_shortcut(char *ptr, cf_t *cf) * we set timefreq to LONG_MAX just in case */ cl->cl_timefreq = LONG_MAX; - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @reboot\n"); } - else if ( strcmp(shortcut, "yearly") == 0 || strcmp(shortcut, "annually") == 0 ) { + else if (strcmp(shortcut, "yearly") == 0 + || strcmp(shortcut, "annually") == 0) { bit_set(cl->cl_mins, 0); bit_set(cl->cl_hrs, 0); bit_set(cl->cl_days, 1); bit_set(cl->cl_mons, 0); bit_nset(cl->cl_dow, 0, 7); - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @yearly\n"); } - else if ( strcmp(shortcut, "monthly") == 0 ) { + else if (strcmp(shortcut, "monthly") == 0) { bit_set(cl->cl_mins, 0); bit_set(cl->cl_hrs, 0); bit_set(cl->cl_days, 1); bit_nset(cl->cl_mons, 0, 11); bit_nset(cl->cl_dow, 0, 7); - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @monthly\n"); } - else if ( strcmp(shortcut, "weekly") == 0 ) { + else if (strcmp(shortcut, "weekly") == 0) { bit_set(cl->cl_mins, 0); bit_set(cl->cl_hrs, 0); bit_nset(cl->cl_days, 0, 31); @@ -1299,27 +1313,28 @@ read_shortcut(char *ptr, cf_t *cf) bit_set(cl->cl_dow, 0); bit_set(cl->cl_dow, 7); /* 0 and 7 are both sunday */ - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @weekly\n"); } - else if ( strcmp(shortcut, "daily") == 0 || strcmp(shortcut, "midnight") == 0 ) { + else if (strcmp(shortcut, "daily") == 0 + || strcmp(shortcut, "midnight") == 0) { bit_set(cl->cl_mins, 0); bit_set(cl->cl_hrs, 0); bit_nset(cl->cl_days, 0, 31); bit_nset(cl->cl_mons, 0, 11); bit_nset(cl->cl_dow, 0, 7); - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @daily\n"); } - else if ( strcmp(shortcut, "hourly") == 0 ) { + else if (strcmp(shortcut, "hourly") == 0) { bit_set(cl->cl_mins, 0); bit_nset(cl->cl_hrs, 0, 23); bit_nset(cl->cl_days, 0, 31); bit_nset(cl->cl_mons, 0, 11); bit_nset(cl->cl_dow, 0, 7); - if ( debug_opt ) + if (debug_opt) fprintf(stderr, " Shc : @hourly\n"); } else { @@ -1332,16 +1347,16 @@ read_shortcut(char *ptr, cf_t *cf) ptr = check_username(ptr, cf, cl); /* get cl_shell field ( remove trailing blanks ) */ - if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", - file_name, line); - goto exiterr; + if ((cl->cl_shell = get_string(ptr)) == NULL) { + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); + goto exiterr; } - if ( strcmp(cl->cl_shell, "\0") == 0 ) { - fprintf(stderr, "%s:%d: No shell command: skipping line.\n", - file_name, line); - Free_safe(cl->cl_shell); - goto exiterr; + if (strcmp(cl->cl_shell, "\0") == 0) { + fprintf(stderr, "%s:%d: No shell command: skipping line.\n", + file_name, line); + Free_safe(cl->cl_shell); + goto exiterr; } #ifndef USE_SENDMAIL @@ -1352,82 +1367,84 @@ read_shortcut(char *ptr, cf_t *cf) cl->cl_next = cf->cf_line_base; cf->cf_line_base = cl; - if ( debug_opt ) - fprintf(stderr, " Cmd \"%s\" (shortcut)\n", cl->cl_shell); + if (debug_opt) + fprintf(stderr, " Cmd \"%s\" (shortcut)\n", cl->cl_shell); return 1; - exiterr: + exiterr: Free_safe(cl); need_correction = 1; return 1; } void -read_freq(char *ptr, cf_t *cf) +read_freq(char *ptr, cf_t * cf) /* read a freq entry, and append a line to cf */ { cl_t *cl = NULL; - + cl = dups_cl(&default_line); - cl->cl_first = -1; /* 0 is a valid value, so we have to use -1 to detect unset */ + cl->cl_first = -1; /* 0 is a valid value, so we have to use -1 to detect unset */ /* skip the @ */ ptr++; /* get the time before first execution or the options */ - if ( isdigit( (int) *ptr) ) { - if ( (ptr = get_time(ptr, &(cl->cl_first), 1)) == NULL ) { - fprintf(stderr, "%s:%d: Error while reading first delay:" - " skipping line.\n", file_name, line); - goto exiterr; - } - - Skip_blanks(ptr); + if (isdigit((int)*ptr)) { + if ((ptr = get_time(ptr, &(cl->cl_first), 1)) == NULL) { + fprintf(stderr, "%s:%d: Error while reading first delay:" + " skipping line.\n", file_name, line); + goto exiterr; + } + + Skip_blanks(ptr); } - else if ( isalnum( (int) *ptr) ) { - if ( (ptr = read_opt(ptr, cl)) == NULL ) - goto exiterr; + else if (isalnum((int)*ptr)) { + if ((ptr = read_opt(ptr, cl)) == NULL) + goto exiterr; } else - Skip_blanks(ptr); + Skip_blanks(ptr); /* we set this here, because it may be unset by read_opt (reset option) */ cl->cl_runfreq = 0; set_freq(cl->cl_option); /* then cl_timefreq */ - if ( (ptr = get_time(ptr, (time_t *) &(cl->cl_timefreq), 0)) == NULL - || cl->cl_timefreq < 1 ) { - fprintf(stderr, "%s:%d: Error while reading frequency %s: skipping line.\n", - file_name, line, (cl->cl_timefreq < 10) ? "(lower than 10s) " : ""); - goto exiterr; + if ((ptr = get_time(ptr, (time_t *) & (cl->cl_timefreq), 0)) == NULL + || cl->cl_timefreq < 1) { + fprintf(stderr, + "%s:%d: Error while reading frequency %s: skipping line.\n", + file_name, line, + (cl->cl_timefreq < 10) ? "(lower than 10s) " : ""); + goto exiterr; } - - if ( cl->cl_timefreq == 0) { - fprintf(stderr, "%s:%d: no freq specified: skipping line.\n", - file_name, line); - goto exiterr; + + if (cl->cl_timefreq == 0) { + fprintf(stderr, "%s:%d: no freq specified: skipping line.\n", + file_name, line); + goto exiterr; } - if ( cl->cl_first == -1 ) - /* time before first execution was not specified explicitely */ - cl->cl_first = cl->cl_timefreq; + if (cl->cl_first == -1) + /* time before first execution was not specified explicitely */ + cl->cl_first = cl->cl_timefreq; /* check for inline runas */ ptr = check_username(ptr, cf, cl); - + /* get cl_shell field ( remove trailing blanks ) */ - if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", - file_name, line); - goto exiterr; - } - if ( strcmp(cl->cl_shell, "\0") == 0 ) { - fprintf(stderr, "%s:%d: No shell command: skipping line.\n", - file_name, line); - Free_safe(cl->cl_shell); - goto exiterr; + if ((cl->cl_shell = get_string(ptr)) == NULL) { + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); + goto exiterr; + } + if (strcmp(cl->cl_shell, "\0") == 0) { + fprintf(stderr, "%s:%d: No shell command: skipping line.\n", + file_name, line); + Free_safe(cl->cl_shell); + goto exiterr; } #ifndef USE_SENDMAIL @@ -1438,13 +1455,13 @@ read_freq(char *ptr, cf_t *cf) cl->cl_next = cf->cf_line_base; cf->cf_line_base = cl; - if ( debug_opt ) - fprintf(stderr, " Cmd \"%s\", timefreq %ld, first %ld\n", - cl->cl_shell, cl->cl_timefreq, (long int)cl->cl_first); - + if (debug_opt) + fprintf(stderr, " Cmd \"%s\", timefreq %ld, first %ld\n", + cl->cl_shell, cl->cl_timefreq, (long int)cl->cl_first); + return; - exiterr: + exiterr: free_line(cl); need_correction = 1; return; @@ -1464,7 +1481,7 @@ read_freq(char *ptr, cf_t *cf) void -read_arys(char *ptr, cf_t *cf) +read_arys(char *ptr, cf_t * cf) /* read a run freq number plus a normal fcron line */ { cl_t *cl = NULL; @@ -1473,27 +1490,28 @@ read_arys(char *ptr, cf_t *cf) cl = dups_cl(&default_line); /* set cl_remain if not specified */ - if ( *ptr == '&' ) { - ptr++; - if ( isdigit( (int) *ptr) ) { - if ( (ptr = get_num(ptr, &i, USHRT_MAX, 0, NULL)) == NULL ) { - fprintf(stderr, "%s:%d: Error while reading runfreq:" - " skipping line.\n", file_name, line); - goto exiterr; - } else { - if (i <= 1) { - fprintf(stderr, "%s:%d: runfreq must be 2 or more :" - " skipping line.\n", file_name, line); - goto exiterr; - } - cl->cl_runfreq = (unsigned short) i; - } - } - else if ( isalnum( (int) *ptr) ) - if ( (ptr = read_opt(ptr, cl)) == NULL ) { - goto exiterr; - } - Skip_blanks(ptr); + if (*ptr == '&') { + ptr++; + if (isdigit((int)*ptr)) { + if ((ptr = get_num(ptr, &i, USHRT_MAX, 0, NULL)) == NULL) { + fprintf(stderr, "%s:%d: Error while reading runfreq:" + " skipping line.\n", file_name, line); + goto exiterr; + } + else { + if (i <= 1) { + fprintf(stderr, "%s:%d: runfreq must be 2 or more :" + " skipping line.\n", file_name, line); + goto exiterr; + } + cl->cl_runfreq = (unsigned short)i; + } + } + else if (isalnum((int)*ptr)) + if ((ptr = read_opt(ptr, cl)) == NULL) { + goto exiterr; + } + Skip_blanks(ptr); } cl->cl_remain = cl->cl_runfreq; @@ -1502,7 +1520,7 @@ read_arys(char *ptr, cf_t *cf) set_td(cl->cl_option); if (debug_opt) - fprintf(stderr, " "); + fprintf(stderr, " "); /* get the fields (check for errors) */ R_field(ptr, cl->cl_mins, 59, NULL, "minutes"); @@ -1513,24 +1531,24 @@ read_arys(char *ptr, cf_t *cf) R_field(ptr, cl->cl_dow, 7, dows_ary, "days of week"); if (debug_opt) - /* if debug_opt is set, we print informations in read_field function, - * but no end line : we print it here */ - fprintf(stderr, " remain %d\n", cl->cl_remain); + /* if debug_opt is set, we print informations in read_field function, + * but no end line : we print it here */ + fprintf(stderr, " remain %d\n", cl->cl_remain); /* check for inline runas */ ptr = check_username(ptr, cf, cl); - + /* get the shell command (remove trailing blanks) */ - if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", - file_name, line); - goto exiterr; + if ((cl->cl_shell = get_string(ptr)) == NULL) { + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); + goto exiterr; } - if ( strcmp(cl->cl_shell, "\0") == 0 ) { - fprintf(stderr, "%s:%d: No shell command: skipping line.\n", - file_name, line); - Free_safe(cl->cl_shell); - goto exiterr; + if (strcmp(cl->cl_shell, "\0") == 0) { + fprintf(stderr, "%s:%d: No shell command: skipping line.\n", + file_name, line); + Free_safe(cl->cl_shell); + goto exiterr; } #ifndef USE_SENDMAIL @@ -1541,11 +1559,11 @@ read_arys(char *ptr, cf_t *cf) cl->cl_next = cf->cf_line_base; cf->cf_line_base = cl; - if ( debug_opt ) - fprintf(stderr, " Cmd \"%s\"\n", cl->cl_shell); + if (debug_opt) + fprintf(stderr, " Cmd \"%s\"\n", cl->cl_shell); return; - exiterr: + exiterr: need_correction = 1; free_line(cl); return; @@ -1553,7 +1571,7 @@ read_arys(char *ptr, cf_t *cf) } void -read_period(char *ptr, cf_t *cf) +read_period(char *ptr, cf_t * cf) /* read a line to run periodically (i.e. once a day, once a week, etc) */ { cl_t *cl = NULL; @@ -1569,8 +1587,8 @@ read_period(char *ptr, cf_t *cf) cl->cl_remain = cl->cl_runfreq = 1; /* set cl_remain if not specified */ - if ( (ptr = read_opt(ptr, cl)) == NULL ) { - goto exiterr; + if ((ptr = read_opt(ptr, cl)) == NULL) { + goto exiterr; } Skip_blanks(ptr); @@ -1578,96 +1596,116 @@ read_period(char *ptr, cf_t *cf) set_td(cl->cl_option); if (debug_opt) - fprintf(stderr, " "); - - if ( is_freq_periodically(cl->cl_option) ) { - if (is_freq_mins(cl->cl_option)) remain = 0; - else if (is_freq_hrs(cl->cl_option)) remain = 1; - else if (is_freq_days(cl->cl_option)) remain = 2; - else if (is_freq_mons(cl->cl_option)) remain = 3; - else if (is_freq_dow(cl->cl_option)) remain = 2; + fprintf(stderr, " "); + + if (is_freq_periodically(cl->cl_option)) { + if (is_freq_mins(cl->cl_option)) + remain = 0; + else if (is_freq_hrs(cl->cl_option)) + remain = 1; + else if (is_freq_days(cl->cl_option)) + remain = 2; + else if (is_freq_mons(cl->cl_option)) + remain = 3; + else if (is_freq_dow(cl->cl_option)) + remain = 2; } /* get the fields (check for errors) */ - if ( remain-- > 0) { R_field(ptr, cl->cl_mins, 59, NULL, "minutes") } - else bit_nset(cl->cl_mins, 0, 59); - if ( remain-- > 0) { R_field(ptr, cl->cl_hrs, 23, NULL, "hours") } - else bit_nset(cl->cl_hrs, 0, 23); - if ( remain-- > 0) { R_field(ptr, cl->cl_days, 31, NULL, "days") } - else bit_nset(cl->cl_days, 1, 32); + if (remain-- > 0) { + R_field(ptr, cl->cl_mins, 59, NULL, "minutes")} + else + bit_nset(cl->cl_mins, 0, 59); + if (remain-- > 0) { + R_field(ptr, cl->cl_hrs, 23, NULL, "hours")} + else + bit_nset(cl->cl_hrs, 0, 23); + if (remain-- > 0) { + R_field(ptr, cl->cl_days, 31, NULL, "days")} + else + bit_nset(cl->cl_days, 1, 32); /* month are defined by user from 1 to 12 : max is 12 */ - if ( remain-- > 0) { R_field(ptr, cl->cl_mons, 12, mons_ary, "months") } - else bit_nset(cl->cl_mons, 0, 11); - if ( remain-- > 0) { R_field(ptr, cl->cl_dow,7, dows_ary, "days of week") } - else bit_nset(cl->cl_dow, 0, 7); + if (remain-- > 0) { + R_field(ptr, cl->cl_mons, 12, mons_ary, "months")} + else + bit_nset(cl->cl_mons, 0, 11); + if (remain-- > 0) { + R_field(ptr, cl->cl_dow, 7, dows_ary, "days of week")} + else + bit_nset(cl->cl_dow, 0, 7); if (debug_opt) - /* if debug_opt is set, we print informations in read_field function, - * but no end line : we print it here */ - fprintf(stderr, " remain %d\n", cl->cl_remain); + /* if debug_opt is set, we print informations in read_field function, + * but no end line : we print it here */ + fprintf(stderr, " remain %d\n", cl->cl_remain); /* check for inline runas */ ptr = check_username(ptr, cf, cl); - + /* get the shell command (remove trailing blanks) */ - if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", - file_name, line); - goto exiterr; + if ((cl->cl_shell = get_string(ptr)) == NULL) { + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); + goto exiterr; + } + if (strcmp(cl->cl_shell, "\0") == 0) { + fprintf(stderr, "%s:%d: No shell command: skipping line.\n", + file_name, line); + Free_safe(cl->cl_shell); + goto exiterr; } - if ( strcmp(cl->cl_shell, "\0") == 0 ) { - fprintf(stderr, "%s:%d: No shell command: skipping line.\n", - file_name, line); - Free_safe(cl->cl_shell); - goto exiterr; - } - else if ( cl->cl_shell[0] == '*' || isdigit( (int) cl->cl_shell[0]) ) - fprintf(stderr, "%s:%d: Warning : shell command beginning by '%c'.\n", - file_name, line, cl->cl_shell[0]); + else if (cl->cl_shell[0] == '*' || isdigit((int)cl->cl_shell[0])) + fprintf(stderr, "%s:%d: Warning : shell command beginning by '%c'.\n", + file_name, line, cl->cl_shell[0]); /* check for non matching if option runfreq is set to 1 */ - if ( ! is_freq_periodically(cl->cl_option) ) { - const size_t s_mins=60, s_hrs=24; - const size_t s_days=32, s_mons=12; - const size_t s_dow=8; - int j = 0; - - if ( ! is_freq_mins(cl->cl_option) ) { - bit_ffc(cl->cl_mins, s_mins, &j); - if ( j != -1 && j < s_mins) goto ok; - } - if ( ! is_freq_hrs(cl->cl_option) ) { - bit_ffc(cl->cl_hrs, s_hrs, &j); - if ( j != -1 && j < s_hrs) goto ok; - } - if ( ! is_freq_days(cl->cl_option) ) { - bit_ffc(cl->cl_days, s_days, &j); - if ( j != -1 && j < s_days) { - if ( is_dayand(cl->cl_option) ) - goto ok; - else { - if ( ! is_freq_dow(cl->cl_option) ) { - bit_ffc(cl->cl_dow, s_dow, &j); - if ( j != -1 && j < s_dow) goto ok; - } - } - } - } - if ( ! is_freq_mons(cl->cl_option) ) { - bit_ffc(cl->cl_mons, s_mons, &j); - if ( j != -1 && j < s_mons ) goto ok; - } - if ( ! is_freq_dow(cl->cl_option) ) { - bit_ffc(cl->cl_dow, s_dow, &j); - if ( j != -1 && j < s_dow && is_dayand(cl->cl_option) ) goto ok; - } - - fprintf(stderr, "%s:%d: periodical line with no intervals: " - "skipping line.\n", file_name, line); - goto exiterr; + if (!is_freq_periodically(cl->cl_option)) { + const size_t s_mins = 60, s_hrs = 24; + const size_t s_days = 32, s_mons = 12; + const size_t s_dow = 8; + int j = 0; + + if (!is_freq_mins(cl->cl_option)) { + bit_ffc(cl->cl_mins, s_mins, &j); + if (j != -1 && j < s_mins) + goto ok; + } + if (!is_freq_hrs(cl->cl_option)) { + bit_ffc(cl->cl_hrs, s_hrs, &j); + if (j != -1 && j < s_hrs) + goto ok; + } + if (!is_freq_days(cl->cl_option)) { + bit_ffc(cl->cl_days, s_days, &j); + if (j != -1 && j < s_days) { + if (is_dayand(cl->cl_option)) + goto ok; + else { + if (!is_freq_dow(cl->cl_option)) { + bit_ffc(cl->cl_dow, s_dow, &j); + if (j != -1 && j < s_dow) + goto ok; + } + } + } + } + if (!is_freq_mons(cl->cl_option)) { + bit_ffc(cl->cl_mons, s_mons, &j); + if (j != -1 && j < s_mons) + goto ok; + } + if (!is_freq_dow(cl->cl_option)) { + bit_ffc(cl->cl_dow, s_dow, &j); + if (j != -1 && j < s_dow && is_dayand(cl->cl_option)) + goto ok; + } + + fprintf(stderr, "%s:%d: periodical line with no intervals: " + "skipping line.\n", file_name, line); + goto exiterr; } - ok: + ok: #ifndef USE_SENDMAIL clear_mail(cl->cl_option); clear_forcemail(cl->cl_option); @@ -1676,11 +1714,11 @@ read_period(char *ptr, cf_t *cf) cl->cl_next = cf->cf_line_base; cf->cf_line_base = cl; - if ( debug_opt ) - fprintf(stderr, " Cmd \"%s\"\n", cl->cl_shell); + if (debug_opt) + fprintf(stderr, " Cmd \"%s\"\n", cl->cl_shell); return; - exiterr: + exiterr: need_correction = 1; free_line(cl); return; @@ -1695,58 +1733,60 @@ get_num(char *ptr, int *num, int max, short int decimal, const char **names) int i = 0; *num = 0; - if ( isalpha( (int) *ptr) ) { + if (isalpha((int)*ptr)) { - if ( names == NULL ) { - need_correction = 1; - return NULL; - } - - /* set string to lower case */ - for ( i = 0; i < strlen(names[0]); i++ ) - *(ptr+i) = tolower( *(ptr+i) ); + if (names == NULL) { + need_correction = 1; + return NULL; + } - for (i = 0; names[i]; ++i) - if (strncmp(ptr, names[i], strlen(names[i])) == 0) { - *num = i; - ptr += strlen(names[i]); - return ptr; - break; - } + /* set string to lower case */ + for (i = 0; i < strlen(names[0]); i++) + *(ptr + i) = tolower(*(ptr + i)); - /* string is not in name list */ - need_correction = 1; - return NULL; + for (i = 0; names[i]; ++i) + if (strncmp(ptr, names[i], strlen(names[i])) == 0) { + *num = i; + ptr += strlen(names[i]); + return ptr; + break; + } - } else { + /* string is not in name list */ + need_correction = 1; + return NULL; - while ( isdigit( (int) *ptr) || *ptr == '.') { + } + else { - if ( *ptr == '.' && ptr++ && i++ > 0 ) - return NULL; - if ( i > 0 && --decimal < 0 ) { - /* the decimal number is exceeded : we round off, - * skip the other decimals and return */ - if ( *ptr >= '5' ) - *num += 1; - while ( isdigit( (int) *(++ptr)) ) ; - ptr--; - } else { - *num *= 10; - *num += *ptr - 48; - } + while (isdigit((int)*ptr) || *ptr == '.') { + + if (*ptr == '.' && ptr++ && i++ > 0) + return NULL; + if (i > 0 && --decimal < 0) { + /* the decimal number is exceeded : we round off, + * skip the other decimals and return */ + if (*ptr >= '5') + *num += 1; + while (isdigit((int)*(++ptr))) ; + ptr--; + } + else { + *num *= 10; + *num += *ptr - 48; + } - if (*num > max) { - need_correction = 1; - return NULL; - } + if (*num > max) { + need_correction = 1; + return NULL; + } - ptr++; + ptr++; - } + } - if ( decimal > 0 ) - *num *= 10 * decimal; + if (decimal > 0) + *num *= 10 * decimal; } @@ -1755,7 +1795,7 @@ get_num(char *ptr, int *num, int max, short int decimal, const char **names) char * -read_field(char *ptr, bitstr_t *ary, int max, const char **names) +read_field(char *ptr, bitstr_t * ary, int max, const char **names) /* read a field like "2,5-8,10-20/2,21-30~25" and fill ary */ { int start = 0; @@ -1764,129 +1804,132 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names) int rm = 0; int i = 0; - while ( (*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0') ) { - - start = stop = step = 0 ; - - /* there may be a "," */ - if ( *ptr == ',' ) - ptr++; - - if ( *ptr == '*' ) { - /* we have to fill everything (may be modified by a step ) */ - start = 0; - /* user set month from 1 to 12, but we manage it internally - * as a number from 0 to 11 */ - stop = ( max == 12 ) ? 11 : max; - ptr++; - } else { - - ptr = get_num(ptr, &start, max, 0, names); - if (ptr == NULL) - return NULL; - if (max == 12) + while ((*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0')) { + + start = stop = step = 0; + + /* there may be a "," */ + if (*ptr == ',') + ptr++; + + if (*ptr == '*') { + /* we have to fill everything (may be modified by a step ) */ + start = 0; + /* user set month from 1 to 12, but we manage it internally + * as a number from 0 to 11 */ + stop = (max == 12) ? 11 : max; + ptr++; + } + else { + + ptr = get_num(ptr, &start, max, 0, names); + if (ptr == NULL) + return NULL; + if (max == 12) /* this number is part of the month field. * user set it from 1 to 12, but we manage it internally * as a number from 0 to 11 : we remove 1 to start */ - start -= 1; - - if (*ptr == ',' || *ptr == ' ' || *ptr == '\t') { - /* this is a single number : set up array and continue */ - if (debug_opt) - fprintf(stderr, " %d", start); - bit_set(ary, start); - continue; - } - - /* check for a dash */ - else if ( *ptr == '-' ) { - ptr++; - ptr = get_num(ptr, &stop, max, 0, names); - if (ptr == NULL) + start -= 1; + + if (*ptr == ',' || *ptr == ' ' || *ptr == '\t') { + /* this is a single number : set up array and continue */ + if (debug_opt) + fprintf(stderr, " %d", start); + bit_set(ary, start); + continue; + } + + /* check for a dash */ + else if (*ptr == '-') { + ptr++; + ptr = get_num(ptr, &stop, max, 0, names); + if (ptr == NULL) /* we reached the end of the string to parse */ - return NULL; - if (max == 12) + return NULL; + if (max == 12) /* this number is part of the month field. * user set it from 1 to 12, but we manage it internally * as a number from 0 to 11 : we remove 1 to stop */ - stop -= 1; - } else { - /* syntax error */ - need_correction = 1; - return NULL; - } - } - - /* check for step size */ - if ( *ptr == '/' ) { - ptr++; - if ((ptr = get_num(ptr, &step, max, 0, names))==NULL || step == 0) - return NULL; - } else - /* step undefined : default is 0 */ - step = 1; - - /* fill array */ - if (debug_opt) - fprintf(stderr, " %d-%d/%d", start, stop, step); - - if (start < stop) - for (i = start; i <= stop; i += step) - bit_set(ary, i); - else { - short int field_max = ( max == 12 ) ? 11 : max; - /* this is a field like (for hours field) "22-3" : - * we should set from 22 to 3 (not from 3 to 22 or nothing :)) ) */ - for (i = start; i <= field_max; i += step) - bit_set(ary, i); - for (i -= (field_max + 1); i <= stop; i += step) - bit_set(ary, i); - } - - /* finally, remove unwanted values */ - while ( *ptr == '~' ) { - ptr++; - rm = 0; - if ( (ptr = get_num(ptr, &rm, max, 0, names)) == NULL ) - return NULL; - if (max == 12) + stop -= 1; + } + else { + /* syntax error */ + need_correction = 1; + return NULL; + } + } + + /* check for step size */ + if (*ptr == '/') { + ptr++; + if ((ptr = get_num(ptr, &step, max, 0, names)) == NULL || step == 0) + return NULL; + } + else + /* step undefined : default is 0 */ + step = 1; + + /* fill array */ + if (debug_opt) + fprintf(stderr, " %d-%d/%d", start, stop, step); + + if (start < stop) + for (i = start; i <= stop; i += step) + bit_set(ary, i); + else { + short int field_max = (max == 12) ? 11 : max; + /* this is a field like (for hours field) "22-3" : + * we should set from 22 to 3 (not from 3 to 22 or nothing :)) ) */ + for (i = start; i <= field_max; i += step) + bit_set(ary, i); + for (i -= (field_max + 1); i <= stop; i += step) + bit_set(ary, i); + } + + /* finally, remove unwanted values */ + while (*ptr == '~') { + ptr++; + rm = 0; + if ((ptr = get_num(ptr, &rm, max, 0, names)) == NULL) + return NULL; + if (max == 12) /* this number is part of the month field. * user set it from 1 to 12, but we manage it internally * as a number from 0 to 11 : we remove 1 to rm */ - rm -= 1; - - if (debug_opt) - fprintf(stderr, " ~%d", rm); - bit_clear(ary, rm); - - /* if we remove one value of Sunday, remove the other */ - if (max == 7 && rm == 0) { - bit_clear(ary, 7); - if (debug_opt) - fprintf(stderr, " ~%d", 7); - } - else if (max == 7 && rm == 7) { - bit_clear(ary, 0); - if (debug_opt) - fprintf(stderr, " ~%d", 0); - } - - } + rm -= 1; + + if (debug_opt) + fprintf(stderr, " ~%d", rm); + bit_clear(ary, rm); + + /* if we remove one value of Sunday, remove the other */ + if (max == 7 && rm == 0) { + bit_clear(ary, 7); + if (debug_opt) + fprintf(stderr, " ~%d", 7); + } + else if (max == 7 && rm == 7) { + bit_clear(ary, 0); + if (debug_opt) + fprintf(stderr, " ~%d", 0); + } + + } } /* Sunday is both 0 and 7 : if one is set, set the other */ - if ( max == 7 ) { - if ( bit_test(ary, 0) ) - bit_set(ary, 7); - else if ( bit_test(ary, 7) ) - bit_set(ary, 0); + if (max == 7) { + if (bit_test(ary, 0)) + bit_set(ary, 7); + else if (bit_test(ary, 7)) + bit_set(ary, 0); } Skip_blanks(ptr); if (debug_opt) - fprintf(stderr, " #"); + fprintf(stderr, " #"); return ptr; } @@ -1902,32 +1945,33 @@ delete_file(const char *user_name) cl_t *cur_line = NULL; file = file_base; - while ( file != NULL) { - if (strcmp(user_name, file->cf_user) == 0) { + while (file != NULL) { + if (strcmp(user_name, file->cf_user) == 0) { - /* free lines */ - cur_line = file->cf_line_base; - while ( (line = cur_line) != NULL) { - cur_line = line->cl_next; + /* free lines */ + cur_line = file->cf_line_base; + while ((line = cur_line) != NULL) { + cur_line = line->cl_next; free_line(line); - } - break ; + } + break; - } else { - prev_file = file; - file = file->cf_next; - } + } + else { + prev_file = file; + file = file->cf_next; + } } - + if (file == NULL) - /* file not in list */ - return; - + /* file not in list */ + return; + /* remove file from list */ if (prev_file == NULL) - file_base = file->cf_next; + file_base = file->cf_next; else - prev_file->cf_next = file->cf_next; + prev_file->cf_next = file->cf_next; /* free env variables */ env_list_destroy(file->cf_env_list); @@ -1946,21 +1990,23 @@ save_file(char *path) cf_t *file = NULL; if (debug_opt) - fprintf(stderr, "Saving ...\n"); - + fprintf(stderr, "Saving ...\n"); + for (file = file_base; file; file = file->cf_next) { - /* save_file() is run under user's rights. - * If fcrontab is run by root for a normal user, we must change the file's - * ownership to this user, in order to make fcron check the runas fields. - * (a malicious user could put a runas(root) and wait for the fcrontab to be - * installed by root) */ + /* save_file() is run under user's rights. + * If fcrontab is run by root for a normal user, we must change the file's + * ownership to this user, in order to make fcron check the runas fields. + * (a malicious user could put a runas(root) and wait for the fcrontab to be + * installed by root) */ #ifdef USE_SETE_ID - if ( save_file_safe(file, path, "fcrontab", asuid, fcrontab_gid, 0) == ERR ) - return ERR; + if (save_file_safe(file, path, "fcrontab", asuid, fcrontab_gid, 0) == + ERR) + return ERR; #else - if ( save_file_safe(file, path, "fcrontab", fcrontab_uid, fcrontab_gid, 0) == ERR ) - return ERR; + if (save_file_safe + (file, path, "fcrontab", fcrontab_uid, fcrontab_gid, 0) == ERR) + return ERR; #endif } diff --git a/fileconf.h b/fileconf.h index 4ef90f5..8eb04d2 100644 --- a/fileconf.h +++ b/fileconf.h @@ -30,4 +30,4 @@ extern int read_file(char *filename, int fd); extern void delete_file(const char *user_name); extern int save_file(char *path); -#endif /* __FILECONF_H__ */ +#endif /* __FILECONF_H__ */ diff --git a/getloadavg.c b/getloadavg.c index 7f6b6be..e5a8e33 100644 --- a/getloadavg.c +++ b/getloadavg.c @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _POSIX_SOURCE /* Don't redefine if already exists */ +#ifndef _POSIX_SOURCE /* Don't redefine if already exists */ #define _POSIX_SOURCE 1 #endif @@ -40,46 +40,46 @@ getloadavg(double *result, int n) * the number of load averages read, or <0 for error */ { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knm; - kstat_named_t knm_buf[20]; - int cnt; - int ret; - - if ( n != 3) { - return -1; - } + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *knm; + kstat_named_t knm_buf[20]; + int cnt; + int ret; + + if (n != 3) { + return -1; + } - ret = 0; - - kc = kstat_open(); - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_name, "system_misc") == 0) { - kstat_read(kc, ksp, &knm_buf); - for (cnt=0; cntks_ndata; cnt++) { - knm=&knm_buf[cnt]; - if (strcmp(knm->name,"avenrun_1min") == 0) { - result[0] = knm->value.ui32 / 256.0; - ret++; - } - else if (strcmp(knm->name,"avenrun_5min") == 0) { - result[1] = knm->value.ui32 / 256.0; - ret++; - } - else if (strcmp(knm->name,"avenrun_15min") == 0) { - result[2] = knm->value.ui32 / 256.0; - ret++; - } + ret = 0; + + kc = kstat_open(); + for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { + if (strcmp(ksp->ks_name, "system_misc") == 0) { + kstat_read(kc, ksp, &knm_buf); + for (cnt = 0; cnt < ksp->ks_ndata; cnt++) { + knm = &knm_buf[cnt]; + if (strcmp(knm->name, "avenrun_1min") == 0) { + result[0] = knm->value.ui32 / 256.0; + ret++; + } + else if (strcmp(knm->name, "avenrun_5min") == 0) { + result[1] = knm->value.ui32 / 256.0; + ret++; + } + else if (strcmp(knm->name, "avenrun_15min") == 0) { + result[2] = knm->value.ui32 / 256.0; + ret++; } } } - kstat_close(kc); + } + kstat_close(kc); - return ret; + return ret; } -#else /* def HAVE_KSTAT */ +#else /* def HAVE_KSTAT */ int getloadavg(double *result, int n) @@ -91,23 +91,23 @@ getloadavg(double *result, int n) int i; if (n > 3) - n = 3; + n = 3; if ((fp = fopen(PROC "/loadavg", "r")) == NULL) { - error_e("could not open '"PROC"/loadavg'" - " (make sure procfs is mounted)"); - i = -1; + error_e("could not open '" PROC "/loadavg'" + " (make sure procfs is mounted)"); + i = -1; } else { - for (i = 0; i < n; i++) { - if (fscanf(fp, "%lf", result) != 1) - goto end; - result++; - } + for (i = 0; i < n; i++) { + if (fscanf(fp, "%lf", result) != 1) + goto end; + result++; + } } - end: + end: fclose(fp); - return (i<0) ? i : i; + return (i < 0) ? i : i; } -#endif /* def HAVE_KSTAT */ +#endif /* def HAVE_KSTAT */ diff --git a/getloadavg.h b/getloadavg.h index 42afd27..434a4f1 100644 --- a/getloadavg.h +++ b/getloadavg.h @@ -28,4 +28,4 @@ /* functions prototypes */ int getloadavg(double *result, int n); -#endif /* __GETLOADAVG_H__ */ +#endif /* __GETLOADAVG_H__ */ diff --git a/global.h b/global.h index eced481..40be6ce 100644 --- a/global.h +++ b/global.h @@ -135,13 +135,13 @@ #include "pam.h" #endif -#include "bitstring.h" /* bit arrays */ -#include "option.h" /* manage fcrontab's options */ -#include "env_list.h" /* manage fcrontab's environment variable lists */ -#include "cl.h" /* Cron Line cl_t type and associated functions */ +#include "bitstring.h" /* bit arrays */ +#include "option.h" /* manage fcrontab's options */ +#include "env_list.h" /* manage fcrontab's environment variable lists */ +#include "cl.h" /* Cron Line cl_t type and associated functions */ /* you should not change this (nor need to do it) */ -#define ERR -1 +#define ERR -1 #define OK 0 /* options for local functions */ @@ -171,12 +171,12 @@ #define debug if(debug_opt) Debug typedef struct cf_t { - struct cf_t *cf_next; - struct cl_t *cf_line_base; - char *cf_user; /* user-name */ - env_list_t *cf_env_list; /* list of all parsed env var */ - int cf_running; /* number of jobs running */ - signed char cf_tzdiff; /* time diff between system and local hour */ + struct cf_t *cf_next; + struct cl_t *cf_line_base; + char *cf_user; /* user-name */ + env_list_t *cf_env_list; /* list of all parsed env var */ + int cf_running; /* number of jobs running */ + signed char cf_tzdiff; /* time diff between system and local hour */ #ifdef WITH_SELINUX security_context_t cf_user_context; security_context_t cf_file_context; @@ -185,8 +185,8 @@ typedef struct cf_t { typedef struct job_t { - struct cl_t *j_line; - struct job_t *j_next; + struct cl_t *j_line; + struct job_t *j_next; } job_t; @@ -234,5 +234,4 @@ typedef struct job_t { #include "subs.h" -#endif /* __GLOBAL_H__ */ - +#endif /* __GLOBAL_H__ */ diff --git a/job.c b/job.c index 30b834f..0e3b695 100644 --- a/job.c +++ b/job.c @@ -28,10 +28,12 @@ #include "temp_file.h" void sig_dfl(void); -void end_job(cl_t *line, int status, FILE *mailf, short mailpos, char **sendmailenv); -void end_mailer(cl_t *line, int status); +void end_job(cl_t * line, int status, FILE * mailf, short mailpos, + char **sendmailenv); +void end_mailer(cl_t * line, int status); #ifdef HAVE_LIBPAM -void die_mail_pame(cl_t *cl, int pamerrno, struct passwd *pas, char *str, env_list_t *env); +void die_mail_pame(cl_t * cl, int pamerrno, struct passwd *pas, char *str, + env_list_t * env); #endif #define PIPE_READ 0 #define PIPE_WRITE 1 @@ -42,7 +44,8 @@ void become_user(struct cl_t *cl, struct passwd *pas, char *home); #ifdef HAVE_LIBPAM void -die_mail_pame(cl_t *cl, int pamerrno, struct passwd *pas, char *str, env_list_t *env) +die_mail_pame(cl_t * cl, int pamerrno, struct passwd *pas, char *str, + env_list_t * env) /* log an error in syslog, mail user if necessary, and die */ { char buf[MAX_MSG]; @@ -51,26 +54,27 @@ die_mail_pame(cl_t *cl, int pamerrno, struct passwd *pas, char *str, env_list_t if (is_mail(cl->cl_option)) { char **envp = env_list_export_envp(env); - FILE *mailf = create_mail(cl, "Could not run fcron job", NULL, NULL, envp); + FILE *mailf = + create_mail(cl, "Could not run fcron job", NULL, NULL, envp); - /* print the error in both syslog and a file, in order to mail it to user */ - if (dup2(fileno(mailf), 1) != 1 || dup2(1, 2) != 2) - die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ + /* print the error in both syslog and a file, in order to mail it to user */ + if (dup2(fileno(mailf), 1) != 1 || dup2(1, 2) != 2) + die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ - foreground = 1; - error_pame(pamh, pamerrno, buf, cl->cl_shell); - error("Job '%s' has *not* run.", cl->cl_shell); - foreground = 0; + foreground = 1; + error_pame(pamh, pamerrno, buf, cl->cl_shell); + error("Job '%s' has *not* run.", cl->cl_shell); + foreground = 0; - pam_end(pamh, pamerrno); + pam_end(pamh, pamerrno); become_user(cl, pas, "/"); - launch_mailer(cl, mailf, envp); - /* launch_mailer() does not return : we never get here */ + launch_mailer(cl, mailf, envp); + /* launch_mailer() does not return : we never get here */ } else - die_pame(pamh, pamerrno, buf, cl->cl_shell); + die_pame(pamh, pamerrno, buf, cl->cl_shell); } #endif @@ -84,7 +88,7 @@ become_user(struct cl_t *cl, struct passwd *pas, char *home) if (pas == NULL) die("become_user() called with a NULL struct passwd"); - /* Change running state to the user in question */ + /* Change running state to the user in question */ if (initgroups(pas->pw_name, pas->pw_gid) < 0) die_e("initgroups failed: %s", pas->pw_name); @@ -93,11 +97,12 @@ become_user(struct cl_t *cl, struct passwd *pas, char *home) if (setuid(pas->pw_uid) < 0) die("setuid failed: %s %d", pas->pw_name, pas->pw_uid); -#endif /* not RUN_NON_PRIVILEGED */ +#endif /* not RUN_NON_PRIVILEGED */ /* make sure HOME is defined and change dir to it */ if (chdir(home) != 0) { - error_e("Could not chdir to HOME dir '%s'. Trying to chdir to '/'.", home); + error_e("Could not chdir to HOME dir '%s'. Trying to chdir to '/'.", + home); if (chdir("/") < 0) die_e("Could not chdir to HOME dir /"); } @@ -113,14 +118,13 @@ setup_user_and_env(struct cl_t *cl, struct passwd *pas, /* (*curshell) and (*curhome) will be allocated and should thus be freed * if curshell and curhome are not NULL. */ /* Return the the two env var sets, the shell to use to execle() commands and the home dir */ - { env_list_t *env_list = env_list_init(); env_t *e = NULL; char *path = NULL; char *myshell = NULL; #ifdef HAVE_LIBPAM - int retcode = 0; + int retcode = 0; char **env; #endif @@ -133,13 +137,14 @@ setup_user_and_env(struct cl_t *cl, struct passwd *pas, /* inherit fcron's PATH for sendmail. We will later change it to DEFAULT_JOB_PATH * or a user defined PATH for the job itself */ path = getenv("PATH"); - env_list_setenv(env_list, "PATH", ( path != NULL ) ? path : DEFAULT_JOB_PATH, 1); + env_list_setenv(env_list, "PATH", (path != NULL) ? path : DEFAULT_JOB_PATH, + 1); if (cl->cl_tz != NULL) env_list_setenv(env_list, "TZ", cl->cl_tz, 1); /* To ensure compatibility with Vixie cron, we don't use the shell defined * in /etc/passwd by default, but the default value from fcron.conf instead: */ - if ( shell != NULL && shell[0] != '\0' ) + if (shell != NULL && shell[0] != '\0') /* default: use value from fcron.conf */ env_list_setenv(env_list, "SHELL", shell, 1); else @@ -148,35 +153,38 @@ setup_user_and_env(struct cl_t *cl, struct passwd *pas, #if ( ! defined(RUN_NON_PRIVILEGED)) && defined(HAVE_LIBPAM) /* Open PAM session for the user and obtain any security - credentials we might need */ + * credentials we might need */ retcode = pam_start("fcron", pas->pw_name, &apamconv, &pamh); - if (retcode != PAM_SUCCESS) die_pame(pamh, retcode, "Could not start PAM for %s", - cl->cl_shell); + if (retcode != PAM_SUCCESS) + die_pame(pamh, retcode, "Could not start PAM for %s", cl->cl_shell); /* Some system seem to need that pam_authenticate() call. * Anyway, we have no way to authentificate the user : * we must set auth to pam_permit. */ retcode = pam_authenticate(pamh, PAM_SILENT); - if (retcode != PAM_SUCCESS) die_mail_pame(cl, retcode, pas, - "Could not authenticate PAM user", env_list); - retcode = pam_acct_mgmt(pamh, PAM_SILENT); /* permitted access? */ - if (retcode != PAM_SUCCESS) die_mail_pame(cl, retcode, pas, - "Could not init PAM account management", env_list); + if (retcode != PAM_SUCCESS) + die_mail_pame(cl, retcode, pas, + "Could not authenticate PAM user", env_list); + retcode = pam_acct_mgmt(pamh, PAM_SILENT); /* permitted access? */ + if (retcode != PAM_SUCCESS) + die_mail_pame(cl, retcode, pas, + "Could not init PAM account management", env_list); retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); - if (retcode != PAM_SUCCESS) die_mail_pame(cl, retcode, pas, - "Could not set PAM credentials", env_list); + if (retcode != PAM_SUCCESS) + die_mail_pame(cl, retcode, pas, "Could not set PAM credentials", + env_list); retcode = pam_open_session(pamh, PAM_SILENT); - if (retcode != PAM_SUCCESS) die_mail_pame(cl, retcode, pas, - "Could not open PAM session", env_list); + if (retcode != PAM_SUCCESS) + die_mail_pame(cl, retcode, pas, "Could not open PAM session", env_list); for (env = pam_getenvlist(pamh); env && *env; env++) { env_list_putenv(env_list, *env, 1); } /* Close the log here, because PAM calls openlog(3) and - our log messages could go to the wrong facility */ + * our log messages could go to the wrong facility */ xcloselog(); -#endif /* ( ! defined(RUN_NON_PRIVILEGED)) && defined(HAVE_LIBPAM) */ +#endif /* ( ! defined(RUN_NON_PRIVILEGED)) && defined(HAVE_LIBPAM) */ /* export the environment for sendmail before we apply user customization */ if (sendmailenv != NULL) @@ -189,45 +197,46 @@ setup_user_and_env(struct cl_t *cl, struct passwd *pas, /* Make sure we don't keep fcron daemon's PATH (which we used for sendmail) */ env_list_setenv(env_list, "PATH", DEFAULT_JOB_PATH, 1); - for ( e = env_list_first(cl->cl_file->cf_env_list); e != NULL; - e = env_list_next(cl->cl_file->cf_env_list) ) { + for (e = env_list_first(cl->cl_file->cf_env_list); e != NULL; + e = env_list_next(cl->cl_file->cf_env_list)) { env_list_putenv(env_list, e->e_envvar, 1); } /* make sure HOME is defined */ env_list_putenv(env_list, "HOME=/", 0); /* don't overwrite if already defined */ - if ( curhome != NULL ) { + if (curhome != NULL) { (*curhome) = strdup2(env_list_getenv(env_list, "HOME")); } /* check that SHELL is valid */ myshell = env_list_getenv(env_list, "SHELL"); - if ( myshell == NULL || myshell[0] == '\0' ) { + if (myshell == NULL || myshell[0] == '\0') { myshell = shell; } - else if ( access(myshell, X_OK) != 0 ) { + else if (access(myshell, X_OK) != 0) { if (errno == ENOENT) error("shell \"%s\" : no file or directory. SHELL set to %s", - myshell, shell); + myshell, shell); else - error_e("shell \"%s\" not valid : SHELL set to %s", - myshell, shell); + error_e("shell \"%s\" not valid : SHELL set to %s", myshell, + shell); myshell = shell; } env_list_setenv(env_list, "SHELL", myshell, 1); - if ( curshell != NULL ) + if (curshell != NULL) *curshell = strdup2(myshell); *jobenv = env_list_export_envp(env_list); } - if ( content_type != NULL ) { + if (content_type != NULL) { (*content_type) = strdup2(env_list_getenv(env_list, "CONTENT_TYPE")); } - if ( encoding != NULL ) { - (*encoding) = strdup2(env_list_getenv(env_list, "CONTENT_TRANSFER_ENCODING")); + if (encoding != NULL) { + (*encoding) = + strdup2(env_list_getenv(env_list, "CONTENT_TRANSFER_ENCODING")); } env_list_destroy(env_list); @@ -236,8 +245,8 @@ setup_user_and_env(struct cl_t *cl, struct passwd *pas, void change_user_setup_env(struct cl_t *cl, - char ***sendmailenv, char ***jobenv, char **curshell, - char **curhome, char **content_type, char **encoding) + char ***sendmailenv, char ***jobenv, char **curshell, + char **curhome, char **content_type, char **encoding) /* call setup_user_and_env() and become_user(). * As a result, *curshell and *curhome will be allocated and should thus be freed * if curshell and curhome are not NULL. */ @@ -246,7 +255,7 @@ change_user_setup_env(struct cl_t *cl, errno = 0; pas = getpwnam(cl->cl_runas); - if ( pas == NULL ) + if (pas == NULL) die_e("failed to get passwd fields for user \"%s\"", cl->cl_runas); setup_user_and_env(cl, pas, sendmailenv, jobenv, curshell, curhome, @@ -259,17 +268,17 @@ void sig_dfl(void) /* set signals handling to its default */ { - signal(SIGTERM, SIG_DFL); - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGUSR1, SIG_DFL); - signal(SIGUSR2, SIG_DFL); - signal(SIGPIPE, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGUSR1, SIG_DFL); + signal(SIGUSR2, SIG_DFL); + signal(SIGPIPE, SIG_DFL); } FILE * -create_mail(cl_t *line, char *subject, char *content_type, char *encoding, +create_mail(cl_t * line, char *subject, char *content_type, char *encoding, char **env) /* create a temp file and write in it a mail header */ { @@ -281,37 +290,38 @@ create_mail(cl_t *line, char *subject, char *content_type, char *encoding, char add_hostname = 0; int i = 0; - if ( mailf == NULL ) - die_e("Could not fdopen() mailfd"); + if (mailf == NULL) + die_e("Could not fdopen() mailfd"); #ifdef HAVE_GETHOSTNAME if (gethostname(hostname, sizeof(hostname)) != 0) { - error_e("Could not get hostname"); - hostname[0] = '\0'; + error_e("Could not get hostname"); + hostname[0] = '\0'; } else { - /* it is unspecified whether a truncated hostname is NUL-terminated */ - hostname[USER_NAME_LEN-1] = '\0'; + /* it is unspecified whether a truncated hostname is NUL-terminated */ + hostname[USER_NAME_LEN - 1] = '\0'; - /* check if mailto is a complete mail address */ - add_hostname = ( strchr(line->cl_mailto, '@') == NULL ) ? 1 : 0; + /* check if mailto is a complete mail address */ + add_hostname = (strchr(line->cl_mailto, '@') == NULL) ? 1 : 0; } -#else /* HAVE_GETHOSTNAME */ +#else /* HAVE_GETHOSTNAME */ hostname[0] = '\0'; -#endif /* HAVE_GETHOSTNAME */ +#endif /* HAVE_GETHOSTNAME */ /* write mail header */ - if ( add_hostname ) + if (add_hostname) fprintf(mailf, "To: %s@%s\n", line->cl_mailto, hostname); else fprintf(mailf, "To: %s\n", line->cl_mailto); if (subject) - fprintf(mailf, "Subject: fcron <%s@%s> %s: %s\n", line->cl_file->cf_user, - ( hostname[0] != '\0')? hostname:"?" , subject, line->cl_shell); + fprintf(mailf, "Subject: fcron <%s@%s> %s: %s\n", + line->cl_file->cf_user, (hostname[0] != '\0') ? hostname : "?", + subject, line->cl_shell); else - fprintf(mailf, "Subject: fcron <%s@%s> %s\n", line->cl_file->cf_user, - ( hostname[0] != '\0')? hostname:"?" , line->cl_shell); + fprintf(mailf, "Subject: fcron <%s@%s> %s\n", line->cl_file->cf_user, + (hostname[0] != '\0') ? hostname : "?", line->cl_shell); if (content_type == NULL) { fprintf(mailf, "Content-Type: text/plain; charset=%s\n", @@ -323,7 +333,7 @@ create_mail(cl_t *line, char *subject, char *content_type, char *encoding, /* Remove new-lines or users could specify arbitrary mail headers! * (fcrontab should already prevent that, but better safe than sorry) */ - for (c=content_type; *c != '\0'; c++) { + for (c = content_type; *c != '\0'; c++) { if (*c == '\n') *c = ' '; } @@ -335,7 +345,7 @@ create_mail(cl_t *line, char *subject, char *content_type, char *encoding, /* Remove new-lines or users could specify arbitrary mail headers! * (fcrontab should already prevent that, but better safe than sorry) */ - for (c=encoding; *c != '\0'; c++) { + for (c = encoding; *c != '\0'; c++) { if (*c == '\n') *c = ' '; } @@ -353,8 +363,8 @@ create_mail(cl_t *line, char *subject, char *content_type, char *encoding, /* See environ(7) and execle(3) to get documentation on environ: * it is an array of NULL-terminated strings, whose last entry is NULL */ - if ( env != NULL ) { - for ( i = 0 ; env[i] != NULL ; i++ ) { + if (env != NULL) { + for (i = 0; env[i] != NULL; i++) { fprintf(mailf, "X-Cron-Env: <%s>\n", env[i]); } } @@ -377,43 +387,45 @@ read_write_pipe(int fd, void *buf, size_t size, int action) int size_processed = 0; int ret; int num_retry = 0; - - while ( size_processed < size ) { - errno = 0; - if ( action == PIPE_READ ) - ret = read(fd, (char *)buf + size_processed, size); - else if ( action == PIPE_WRITE ) - ret = write(fd, (char *)buf + size_processed, size); - else { - error("Invalid action parameter for function read_write_pipe():" - " %d", action); - return ERR; - } - if ( ret > 0 ) - /* some data read correctly -- we still may need - * one or several calls of read() to read the rest */ - size_processed += ret; - else if ( ret < 0 && errno == EINTR ) - /* interrupted by a signal : let's try again */ - continue; - else { - /* error */ - - if ( ret == 0 ) { - /* is it really an error when writing ? should we continue - * in this case ? */ - if ( num_retry < 3 ) { - num_retry++; - error_e("read_write_pipe(): read/write returned 0: retrying... (size: %d, size_processed: %d, num_retry: %d)", size, size_processed, num_retry); - sleep(1); - continue; - } - else - return ERR; - } - else - return errno; - } + + while (size_processed < size) { + errno = 0; + if (action == PIPE_READ) + ret = read(fd, (char *)buf + size_processed, size); + else if (action == PIPE_WRITE) + ret = write(fd, (char *)buf + size_processed, size); + else { + error("Invalid action parameter for function read_write_pipe():" + " %d", action); + return ERR; + } + if (ret > 0) + /* some data read correctly -- we still may need + * one or several calls of read() to read the rest */ + size_processed += ret; + else if (ret < 0 && errno == EINTR) + /* interrupted by a signal : let's try again */ + continue; + else { + /* error */ + + if (ret == 0) { + /* is it really an error when writing ? should we continue + * in this case ? */ + if (num_retry < 3) { + num_retry++; + error_e + ("read_write_pipe(): read/write returned 0: retrying... (size: %d, size_processed: %d, num_retry: %d)", + size, size_processed, num_retry); + sleep(1); + continue; + } + else + return ERR; + } + else + return errno; + } } return OK; @@ -440,57 +452,57 @@ write_pipe(int fd, void *buf, size_t size) } void -run_job_grand_child_setup_stderr_stdout(cl_t *line, int *pipe_fd) +run_job_grand_child_setup_stderr_stdout(cl_t * line, int *pipe_fd) /* setup stderr and stdout correctly so as the mail containing * the output of the job can be send at the end of the job. * Close the pipe (both ways). */ { - if (is_mail(line->cl_option) ) { - /* we can't dup2 directly to mailfd, since a "cmd > /dev/stderr" in - * a script would erase all previously collected message */ - if ( dup2( pipe_fd[1], 1) != 1 || dup2(1, 2) != 2 ) - die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ - /* we close the pipe_fd[]s : the resources remain, and the pipe will - * be effectively close when the job stops */ - if ( close(pipe_fd[0]) < 0 ) - error_e("setup_stderr_stdout: could not close(pipe_fd[0])"); - if ( close(pipe_fd[1]) < 0 ) - error_e("setup_stderr_stdout: could not close(pipe_fd[1])"); - /* Standard buffering results in unwanted behavior (some messages, - at least error from fcron process itself, are lost) */ + if (is_mail(line->cl_option)) { + /* we can't dup2 directly to mailfd, since a "cmd > /dev/stderr" in + * a script would erase all previously collected message */ + if (dup2(pipe_fd[1], 1) != 1 || dup2(1, 2) != 2) + die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ + /* we close the pipe_fd[]s : the resources remain, and the pipe will + * be effectively close when the job stops */ + if (close(pipe_fd[0]) < 0) + error_e("setup_stderr_stdout: could not close(pipe_fd[0])"); + if (close(pipe_fd[1]) < 0) + error_e("setup_stderr_stdout: could not close(pipe_fd[1])"); + /* Standard buffering results in unwanted behavior (some messages, + * at least error from fcron process itself, are lost) */ #ifdef HAVE_SETLINEBUF - setlinebuf(stdout); - setlinebuf(stderr); + setlinebuf(stdout); + setlinebuf(stderr); #else - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); #endif } - else if ( foreground ) { - if ( freopen("/dev/null", "w", stdout) == NULL ) + else if (foreground) { + if (freopen("/dev/null", "w", stdout) == NULL) error_e("could not freopen /dev/null as stdout"); - if ( freopen("/dev/null", "w", stderr) == NULL ) + if (freopen("/dev/null", "w", stderr) == NULL) error_e("could not freopen /dev/null as stderr"); } - + } void -run_job_grand_child_setup_nice(cl_t *line) +run_job_grand_child_setup_nice(cl_t * line) /* set the nice value for the job */ { - if ( line->cl_nice != 0 ) { - errno = 0; /* so that it works with any libc and kernel */ - if ( nice(line->cl_nice) == -1 && errno != 0 ) - error_e("could not set nice value"); + if (line->cl_nice != 0) { + errno = 0; /* so that it works with any libc and kernel */ + if (nice(line->cl_nice) == -1 && errno != 0) + error_e("could not set nice value"); } } -int +int run_job(struct exe_t *exeent) /* fork(), redirect outputs to a temp file, and execl() the task. - * Return ERR if it could not fork() the first time, OK otherwise. */ + * Return ERR if it could not fork() the first time, OK otherwise. */ { pid_t pid; @@ -499,255 +511,262 @@ run_job(struct exe_t *exeent) int ret = 0; /* prepare the job execution */ - if ( pipe(pipe_pid_fd) != 0 ) { - error_e("pipe(pipe_pid_fd) : setting job_pid to -1"); - exeent->e_job_pid = -1; - pipe_pid_fd[0] = pipe_pid_fd[1] = -1; + if (pipe(pipe_pid_fd) != 0) { + error_e("pipe(pipe_pid_fd) : setting job_pid to -1"); + exeent->e_job_pid = -1; + pipe_pid_fd[0] = pipe_pid_fd[1] = -1; } #ifdef CHECKRUNJOB - debug("run_job(): first pipe created successfully : about to do first fork()"); -#endif /* CHECKRUNJOB */ + debug + ("run_job(): first pipe created successfully : about to do first fork()"); +#endif /* CHECKRUNJOB */ - switch ( pid = fork() ) { + switch (pid = fork()) { case -1: - error_e("Fork error : could not exec \"%s\"", line->cl_shell); - return ERR; - break; + error_e("Fork error : could not exec \"%s\"", line->cl_shell); + return ERR; + break; case 0: - /* child */ - { - struct passwd *pas = NULL; - char **jobenv = NULL; - char **sendmailenv = NULL; - char *curshell = NULL; - char *curhome = NULL; - char *content_type = NULL; - char *encoding = NULL; - FILE *mailf = NULL; - int status = 0; - int to_stdout = foreground && is_stdout(line->cl_option); - int pipe_fd[2]; - short int mailpos = 0; /* 'empty mail file' size */ + /* child */ + { + struct passwd *pas = NULL; + char **jobenv = NULL; + char **sendmailenv = NULL; + char *curshell = NULL; + char *curhome = NULL; + char *content_type = NULL; + char *encoding = NULL; + FILE *mailf = NULL; + int status = 0; + int to_stdout = foreground && is_stdout(line->cl_option); + int pipe_fd[2]; + short int mailpos = 0; /* 'empty mail file' size */ #ifdef WITH_SELINUX - int flask_enabled = is_selinux_enabled(); + int flask_enabled = is_selinux_enabled(); #endif - /* // */ - debug("run_job(): child: %s, output to %s, %s, %s\n", - is_mail(line->cl_option) ? "mail" : "no mail", - to_stdout ? "stdout" : "file", - foreground ? "running in foreground" : "running in background", - is_stdout(line->cl_option) ? "stdout" : "normal" ); - /* // */ - - errno = 0; - pas = getpwnam(line->cl_runas); - if ( pas == NULL ) - die_e("failed to get passwd fields for user \"%s\"", line->cl_runas); - - setup_user_and_env(line, pas, &sendmailenv, &jobenv, &curshell, - &curhome, &content_type, &encoding); - - /* close unneeded READ fd */ - if ( close(pipe_pid_fd[0]) < 0 ) - error_e("child: could not close(pipe_pid_fd[0])"); + /* // */ + debug("run_job(): child: %s, output to %s, %s, %s\n", + is_mail(line->cl_option) ? "mail" : "no mail", + to_stdout ? "stdout" : "file", + foreground ? "running in foreground" : + "running in background", + is_stdout(line->cl_option) ? "stdout" : "normal"); + /* // */ - pipe_fd[0] = pipe_fd[1] = -1; - if ( ! to_stdout && is_mail(line->cl_option) ) { - /* we create the temp file (if needed) before change_user(), - * as temp_file() needs root privileges */ - /* if we run in foreground, stdout and stderr point to the console. - * Otherwise, stdout and stderr point to /dev/null . */ - mailf = create_mail(line, NULL, content_type, encoding, jobenv); - mailpos = ftell(mailf); - if (pipe(pipe_fd) != 0) - die_e("could not pipe() (job not executed)"); - } + errno = 0; + pas = getpwnam(line->cl_runas); + if (pas == NULL) + die_e("failed to get passwd fields for user \"%s\"", + line->cl_runas); + + setup_user_and_env(line, pas, &sendmailenv, &jobenv, &curshell, + &curhome, &content_type, &encoding); + + /* close unneeded READ fd */ + if (close(pipe_pid_fd[0]) < 0) + error_e("child: could not close(pipe_pid_fd[0])"); + + pipe_fd[0] = pipe_fd[1] = -1; + if (!to_stdout && is_mail(line->cl_option)) { + /* we create the temp file (if needed) before change_user(), + * as temp_file() needs root privileges */ + /* if we run in foreground, stdout and stderr point to the console. + * Otherwise, stdout and stderr point to /dev/null . */ + mailf = create_mail(line, NULL, content_type, encoding, jobenv); + mailpos = ftell(mailf); + if (pipe(pipe_fd) != 0) + die_e("could not pipe() (job not executed)"); + } - become_user(line, pas, curhome); - Free_safe(curhome); + become_user(line, pas, curhome); + Free_safe(curhome); - /* restore umask to default */ - umask (saved_umask); + /* restore umask to default */ + umask(saved_umask); - sig_dfl(); + sig_dfl(); #ifdef CHECKRUNJOB - debug("run_job(): child: change_user() done -- about to do 2nd fork()"); -#endif /* CHECKRUNJOB */ - - /* now, run the job */ - switch ( pid = fork() ) { - case -1: - error_e("Fork error : could not exec \"%s\"", line->cl_shell); - if ( write(pipe_pid_fd[1], &pid, sizeof(pid)) < 0 ) - error_e("could not write child pid to pipe_pid_fd[1]"); - if ( pipe_fd[0] != -1 && close(pipe_fd[0]) < 0 ) - error_e("child: could not close(pipe_fd[0])"); - if ( pipe_fd[1] != -1 && close(pipe_fd[1]) < 0 ) - error_e("child: could not close(pipe_fd[1])"); - if ( close(pipe_pid_fd[1]) < 0 ) - error_e("child: could not close(pipe_pid_fd[1])"); - exit(EXIT_ERR); - break; - - case 0: - /* grand child (child of the 2nd fork) */ - - /* the grand child does not use this pipe: close remaining fd */ - if ( close(pipe_pid_fd[1]) < 0 ) - error_e("grand child: could not close(pipe_pid_fd[1])"); - - if ( ! to_stdout ) - /* note : the following closes the pipe */ - run_job_grand_child_setup_stderr_stdout(line, pipe_fd); - - foreground = 1; - /* now, errors will be mailed to the user (or to /dev/null) */ - - run_job_grand_child_setup_nice(line); - - xcloselog(); + debug + ("run_job(): child: change_user() done -- about to do 2nd fork()"); +#endif /* CHECKRUNJOB */ + + /* now, run the job */ + switch (pid = fork()) { + case -1: + error_e("Fork error : could not exec \"%s\"", line->cl_shell); + if (write(pipe_pid_fd[1], &pid, sizeof(pid)) < 0) + error_e("could not write child pid to pipe_pid_fd[1]"); + if (pipe_fd[0] != -1 && close(pipe_fd[0]) < 0) + error_e("child: could not close(pipe_fd[0])"); + if (pipe_fd[1] != -1 && close(pipe_fd[1]) < 0) + error_e("child: could not close(pipe_fd[1])"); + if (close(pipe_pid_fd[1]) < 0) + error_e("child: could not close(pipe_pid_fd[1])"); + exit(EXIT_ERR); + break; + + case 0: + /* grand child (child of the 2nd fork) */ + + /* the grand child does not use this pipe: close remaining fd */ + if (close(pipe_pid_fd[1]) < 0) + error_e("grand child: could not close(pipe_pid_fd[1])"); + + if (!to_stdout) + /* note : the following closes the pipe */ + run_job_grand_child_setup_stderr_stdout(line, pipe_fd); + + foreground = 1; + /* now, errors will be mailed to the user (or to /dev/null) */ + + run_job_grand_child_setup_nice(line); + + xcloselog(); #if defined(CHECKJOBS) || defined(CHECKRUNJOB) - /* this will force to mail a message containing at least the exact - * and complete command executed for each execution of all jobs */ - debug("run_job(): grand-child: Executing \"%s -c %s\"", curshell, line->cl_shell); -#endif /* CHECKJOBS OR CHECKRUNJOB */ + /* this will force to mail a message containing at least the exact + * and complete command executed for each execution of all jobs */ + debug("run_job(): grand-child: Executing \"%s -c %s\"", + curshell, line->cl_shell); +#endif /* CHECKJOBS OR CHECKRUNJOB */ #ifdef WITH_SELINUX - if(flask_enabled && setexeccon(line->cl_file->cf_user_context) < 0) - die_e("Can't set execute context '%s' for user '%s'.", - line->cl_file->cf_user_context, line->cl_runas); + if (flask_enabled + && setexeccon(line->cl_file->cf_user_context) < 0) + die_e("Can't set execute context '%s' for user '%s'.", + line->cl_file->cf_user_context, line->cl_runas); #else - if (setsid() == -1) { - die_e("setsid(): errno %d", errno); - } + if (setsid() == -1) { + die_e("setsid(): errno %d", errno); + } #endif - execle(curshell, curshell, "-c", line->cl_shell, NULL, jobenv); - /* execle returns only on error */ - die_e("Couldn't exec shell '%s'",curshell); + execle(curshell, curshell, "-c", line->cl_shell, NULL, jobenv); + /* execle returns only on error */ + die_e("Couldn't exec shell '%s'", curshell); - /* execution never gets here */ + /* execution never gets here */ - default: - /* child (parent of the 2nd fork) */ + default: + /* child (parent of the 2nd fork) */ - /* close unneeded WRITE pipe and READ pipe */ - if ( pipe_fd[1] != -1 && close(pipe_fd[1]) < 0 ) - error_e("child: could not close(pipe_fd[1])"); + /* close unneeded WRITE pipe and READ pipe */ + if (pipe_fd[1] != -1 && close(pipe_fd[1]) < 0) + error_e("child: could not close(pipe_fd[1])"); #ifdef CHECKRUNJOB - debug("run_job(): child: pipe_fd[1] and pipe_pid_fd[0] closed" - " -- about to write grand-child pid to pipe"); -#endif /* CHECKRUNJOB */ - - /* give the pid of the child to the parent (main) fcron process */ - ret = write_pipe(pipe_pid_fd[1], &pid, sizeof(pid)); - if ( ret != OK ) { - if ( ret == ERR ) - error("run_job(): child: Could not write job pid to pipe"); - else { - errno = ret; - error_e("run_job(): child: Could not write job pid to pipe"); + debug("run_job(): child: pipe_fd[1] and pipe_pid_fd[0] closed" + " -- about to write grand-child pid to pipe"); +#endif /* CHECKRUNJOB */ + + /* give the pid of the child to the parent (main) fcron process */ + ret = write_pipe(pipe_pid_fd[1], &pid, sizeof(pid)); + if (ret != OK) { + if (ret == ERR) + error + ("run_job(): child: Could not write job pid to pipe"); + else { + errno = ret; + error_e + ("run_job(): child: Could not write job pid to pipe"); + } } - } #ifdef CHECKRUNJOB - debug("run_job(): child: grand-child pid written to pipe"); -#endif /* CHECKRUNJOB */ - - if ( ! is_nolog(line->cl_option) ) - explain("Job %s started for user %s (pid %d)", line->cl_shell, - line->cl_file->cf_user, pid); - - if ( ! to_stdout && is_mail(line->cl_option ) ) { - /* user wants a mail : we use the pipe */ - char mailbuf[TERM_LEN]; - FILE *pipef = fdopen(pipe_fd[0], "r"); - - if ( pipef == NULL ) - die_e("Could not fdopen() pipe_fd[0]"); - - mailbuf[sizeof(mailbuf)-1] = '\0'; - while ( fgets(mailbuf, sizeof(mailbuf), pipef) != NULL ) - if ( fputs(mailbuf, mailf) < 0 ) - warn("fputs() failed to write to mail file for job %s (pid %d)", - line->cl_shell, pid); - /* (closes also pipe_fd[0]): */ - if ( fclose(pipef) != 0 ) - error_e("child: Could not fclose(pipef)"); - } + debug("run_job(): child: grand-child pid written to pipe"); +#endif /* CHECKRUNJOB */ + + if (!is_nolog(line->cl_option)) + explain("Job %s started for user %s (pid %d)", + line->cl_shell, line->cl_file->cf_user, pid); + + if (!to_stdout && is_mail(line->cl_option)) { + /* user wants a mail : we use the pipe */ + char mailbuf[TERM_LEN]; + FILE *pipef = fdopen(pipe_fd[0], "r"); + + if (pipef == NULL) + die_e("Could not fdopen() pipe_fd[0]"); + + mailbuf[sizeof(mailbuf) - 1] = '\0'; + while (fgets(mailbuf, sizeof(mailbuf), pipef) != NULL) + if (fputs(mailbuf, mailf) < 0) + warn("fputs() failed to write to mail file for job %s (pid %d)", line->cl_shell, pid); + /* (closes also pipe_fd[0]): */ + if (fclose(pipef) != 0) + error_e("child: Could not fclose(pipef)"); + } - /* FIXME : FOLLOWING HACK USELESS ? */ - /* FIXME : HACK - * this is a try to fix the bug on sorcerer linux (no jobs - * exectued at all, and - * "Could not read job pid : setting it to -1: No child processes" - * error messages) */ - /* use a select() or similar to know when parent has read - * the pid (with a timeout !) */ - /* // */ - sleep(2); - /* // */ + /* FIXME : FOLLOWING HACK USELESS ? */ + /* FIXME : HACK + * this is a try to fix the bug on sorcerer linux (no jobs + * exectued at all, and + * "Could not read job pid : setting it to -1: No child processes" + * error messages) */ + /* use a select() or similar to know when parent has read + * the pid (with a timeout !) */ + /* // */ + sleep(2); + /* // */ #ifdef CHECKRUNJOB - debug("run_job(): child: closing pipe with parent"); -#endif /* CHECKRUNJOB */ - if ( close(pipe_pid_fd[1]) < 0 ) - error_e("child: could not close(pipe_pid_fd[1])"); - - /* we use a while because of a possible interruption by a signal */ - while ( (pid = wait3(&status, 0, NULL)) > 0) - { + debug("run_job(): child: closing pipe with parent"); +#endif /* CHECKRUNJOB */ + if (close(pipe_pid_fd[1]) < 0) + error_e("child: could not close(pipe_pid_fd[1])"); + + /* we use a while because of a possible interruption by a signal */ + while ((pid = wait3(&status, 0, NULL)) > 0) { #ifdef CHECKRUNJOB - debug("run_job(): child: ending job pid %d", pid); -#endif /* CHECKRUNJOB */ - end_job(line, status, mailf, mailpos, sendmailenv); - } + debug("run_job(): child: ending job pid %d", pid); +#endif /* CHECKRUNJOB */ + end_job(line, status, mailf, mailpos, sendmailenv); + } - /* execution never gets here */ + /* execution never gets here */ - } + } - /* execution should never gets here, but if it happened we exit with an error */ - exit(EXIT_ERR); - } + /* execution should never gets here, but if it happened we exit with an error */ + exit(EXIT_ERR); + } default: - /* parent */ + /* parent */ - /* close unneeded WRITE fd */ - if ( close(pipe_pid_fd[1]) < 0 ) - error_e("parent: could not close(pipe_pid_fd[1])"); + /* close unneeded WRITE fd */ + if (close(pipe_pid_fd[1]) < 0) + error_e("parent: could not close(pipe_pid_fd[1])"); - exeent->e_ctrl_pid = pid; + exeent->e_ctrl_pid = pid; #ifdef CHECKRUNJOB - debug("run_job(): about to read grand-child pid..."); -#endif /* CHECKRUNJOB */ - - /* read the pid of the job */ - ret = read_pipe(pipe_pid_fd[0], &(exeent->e_job_pid), sizeof(pid_t)); - if ( ret != OK ) { - if ( ret == ERR ) - error("Could not read job pid because of closed pipe:" - " setting it to -1"); - else { - errno = ret; - error_e("Could not read job pid : setting it to -1"); - } - - exeent->e_job_pid = -1; - break; - } - if ( close(pipe_pid_fd[0]) < 0 ) - error_e("parent: could not close(pipe_pid_fd[0])"); + debug("run_job(): about to read grand-child pid..."); +#endif /* CHECKRUNJOB */ + + /* read the pid of the job */ + ret = read_pipe(pipe_pid_fd[0], &(exeent->e_job_pid), sizeof(pid_t)); + if (ret != OK) { + if (ret == ERR) + error("Could not read job pid because of closed pipe:" + " setting it to -1"); + else { + errno = ret; + error_e("Could not read job pid : setting it to -1"); + } + + exeent->e_job_pid = -1; + break; + } + if (close(pipe_pid_fd[0]) < 0) + error_e("parent: could not close(pipe_pid_fd[0])"); #ifdef CHECKRUNJOB - debug("run_job(): finished reading pid of the job -- end of run_job()."); -#endif /* CHECKRUNJOB */ + debug + ("run_job(): finished reading pid of the job -- end of run_job()."); +#endif /* CHECKRUNJOB */ } @@ -755,62 +774,62 @@ run_job(struct exe_t *exeent) } -void -end_job(cl_t *line, int status, FILE *mailf, short mailpos, char **sendmailenv) +void +end_job(cl_t * line, int status, FILE * mailf, short mailpos, + char **sendmailenv) /* if task have made some output, mail it to user */ { char mail_output; char *m; - if ( mailf != NULL - && ( - is_mailzerolength(line->cl_option) - || - ( - is_mail(line->cl_option) - && ( - /* job wrote some output and we wan't it in any case: */ - ( (fseek(mailf, 0, SEEK_END) == 0 && ftell(mailf) > mailpos) - && ! is_erroronlymail(line->cl_option) ) - || - /* or we want an email only if the job returned an error: */ - ! (WIFEXITED(status) && WEXITSTATUS(status) == 0) - ) - ) - ) - ) - /* an output exit : we will mail it */ - mail_output = 1; + if (mailf != NULL && (is_mailzerolength(line->cl_option) + || (is_mail(line->cl_option) + && ( + /* job wrote some output and we wan't it in any case: */ + ((fseek(mailf, 0, SEEK_END) == 0 + && ftell(mailf) > mailpos) + && !is_erroronlymail(line->cl_option)) + || + /* or we want an email only if the job returned an error: */ + !(WIFEXITED(status) + && WEXITSTATUS(status) == 0) + ) + ) + ) + ) + /* an output exit : we will mail it */ + mail_output = 1; else - /* no output */ - mail_output = 0; + /* no output */ + mail_output = 0; m = (mail_output == 1) ? " (mailing output)" : ""; if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - if ( ! is_nolog(line->cl_option) ) - explain("Job %s completed%s", line->cl_shell, m); + if (!is_nolog(line->cl_option)) + explain("Job %s completed%s", line->cl_shell, m); } else if (WIFEXITED(status)) { - warn("Job %s terminated (exit status: %d)%s", - line->cl_shell, WEXITSTATUS(status), m); - /* there was an error : in order to inform the user by mail, we need - * to add some data to mailf */ - if ( mailf != NULL ) - fprintf(mailf, "Job %s terminated (exit status: %d)%s", - line->cl_shell, WEXITSTATUS(status), m); + warn("Job %s terminated (exit status: %d)%s", + line->cl_shell, WEXITSTATUS(status), m); + /* there was an error : in order to inform the user by mail, we need + * to add some data to mailf */ + if (mailf != NULL) + fprintf(mailf, "Job %s terminated (exit status: %d)%s", + line->cl_shell, WEXITSTATUS(status), m); } else if (WIFSIGNALED(status)) { - error("Job %s terminated due to signal %d%s", - line->cl_shell, WTERMSIG(status), m); - if ( mailf != NULL ) - fprintf(mailf, "Job %s terminated due to signal %d%s", - line->cl_shell, WTERMSIG(status), m); + error("Job %s terminated due to signal %d%s", + line->cl_shell, WTERMSIG(status), m); + if (mailf != NULL) + fprintf(mailf, "Job %s terminated due to signal %d%s", + line->cl_shell, WTERMSIG(status), m); } - else { /* is this possible? */ - error("Job %s terminated abnormally %s", line->cl_shell, m); - if ( mailf != NULL ) - fprintf(mailf, "Job %s terminated abnormally %s", line->cl_shell, m); + else { /* is this possible? */ + error("Job %s terminated abnormally %s", line->cl_shell, m); + if (mailf != NULL) + fprintf(mailf, "Job %s terminated abnormally %s", line->cl_shell, + m); } #ifdef HAVE_LIBPAM @@ -822,28 +841,28 @@ end_job(cl_t *line, int status, FILE *mailf, short mailpos, char **sendmailenv) * It should be ok like that, otherwise contact me ... -tg */ /* Aiee! we may need to be root to do this properly under Linux. Let's - hope we're more l33t than PAM and try it as non-root. If someone - complains, I'll fix this :P -hmh */ + * hope we're more l33t than PAM and try it as non-root. If someone + * complains, I'll fix this :P -hmh */ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); pam_end(pamh, pam_close_session(pamh, PAM_SILENT)); #endif if (mail_output == 1) { - launch_mailer(line, mailf, sendmailenv); - /* never reached */ - die_e("Internal error: launch_mailer returned"); + launch_mailer(line, mailf, sendmailenv); + /* never reached */ + die_e("Internal error: launch_mailer returned"); } /* if mail is sent, execution doesn't get here : close /dev/null */ - if ( mailf != NULL && fclose(mailf) != 0 ) - die_e("Can't close file mailf"); + if (mailf != NULL && fclose(mailf) != 0) + die_e("Can't close file mailf"); exit(0); } void -launch_mailer(cl_t *line, FILE *mailf, char **sendmailenv) +launch_mailer(cl_t * line, FILE * mailf, char **sendmailenv) /* mail the output of a job to user */ { #ifdef USE_SENDMAIL @@ -856,24 +875,27 @@ launch_mailer(cl_t *line, FILE *mailf, char **sendmailenv) * For those users, lseek() works, so I have decided to use both, * as I am not sure that lseek(fileno(...)...) will work as expected * on non linux systems. */ - if ( fseek(mailf, 0, SEEK_SET ) != 0) die_e("Can't fseek()"); - if ( lseek(fileno(mailf), 0, SEEK_SET ) != 0) die_e("Can't lseek()"); - if ( dup2(fileno(mailf), 0) != 0 ) die_e("Can't dup2(fileno(mailf))"); + if (fseek(mailf, 0, SEEK_SET) != 0) + die_e("Can't fseek()"); + if (lseek(fileno(mailf), 0, SEEK_SET) != 0) + die_e("Can't lseek()"); + if (dup2(fileno(mailf), 0) != 0) + die_e("Can't dup2(fileno(mailf))"); xcloselog(); - if ( chdir("/") < 0 ) - die_e("Could not chdir to /"); + if (chdir("/") < 0) + die_e("Could not chdir to /"); /* run sendmail with mail file as standard input */ /* // */ - debug("execle(%s, %s, %s, %s, NULL, sendmailenv)", sendmail, sendmail, SENDMAIL_ARGS, line->cl_mailto); + debug("execle(%s, %s, %s, %s, NULL, sendmailenv)", sendmail, sendmail, + SENDMAIL_ARGS, line->cl_mailto); /* // */ - execle(sendmail, sendmail, SENDMAIL_ARGS, line->cl_mailto, NULL, sendmailenv); + execle(sendmail, sendmail, SENDMAIL_ARGS, line->cl_mailto, NULL, + sendmailenv); die_e("Couldn't exec '%s'", sendmail); -#else /* defined(USE_SENDMAIL) */ +#else /* defined(USE_SENDMAIL) */ exit(EXIT_OK); #endif } - - diff --git a/job.h b/job.h index 82658d4..9d4c3b7 100644 --- a/job.h +++ b/job.h @@ -27,11 +27,12 @@ /* functions prototypes */ extern void change_user_setup_env(struct cl_t *cl, char ***sendmailenv, - char ***jobenv, char **curshell, char **curhome, - char **content_type, char **encoding); + char ***jobenv, char **curshell, + char **curhome, char **content_type, + char **encoding); extern int run_job(struct exe_t *exeent); extern FILE *create_mail(struct cl_t *line, char *subject, char *content_type, char *encoding, char **env); -extern void launch_mailer(struct cl_t *line, FILE *mailf, char **env); +extern void launch_mailer(struct cl_t *line, FILE * mailf, char **env); -#endif /* __JOB_H__ */ +#endif /* __JOB_H__ */ diff --git a/lavg_list.c b/lavg_list.c index bf31e6e..802a7af 100644 --- a/lavg_list.c +++ b/lavg_list.c @@ -31,55 +31,57 @@ #include "fcron.h" #include "lavg_list.h" -lavg_list_t *lavg_list_init(void) +lavg_list_t * +lavg_list_init(void) { - lavg_list_t *l = (lavg_list_t *)u_list_init(sizeof(lavg_t), LAVG_INITIAL_SIZE, LAVG_GROW_SIZE); + lavg_list_t *l = + (lavg_list_t *) u_list_init(sizeof(lavg_t), LAVG_INITIAL_SIZE, + LAVG_GROW_SIZE); l->max_entries = LAVG_QUEUE_MAX; return l; } lavg_t * -lavg_list_add_line(lavg_list_t *list, struct cl_t *line) +lavg_list_add_line(lavg_list_t * list, struct cl_t * line) { - lavg_t e = { NULL, 0}; - e.l_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/ + lavg_t e = { NULL, 0 }; + e.l_line = line; /* ANSI C does not allow us to directly replace NULL by line above */ - return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); + return (lavg_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) & e); } lavg_t * -lavg_list_add(lavg_list_t *list, lavg_t *entry) +lavg_list_add(lavg_list_t * list, lavg_t * entry) { - return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) entry); + return (lavg_t *) u_list_add((u_list_t *) list, (u_list_entry_t *) entry); } lavg_t * -lavg_list_first(lavg_list_t *list) +lavg_list_first(lavg_list_t * list) { return (lavg_t *) u_list_first((u_list_t *) list); } lavg_t * -lavg_list_next(lavg_list_t *list) +lavg_list_next(lavg_list_t * list) { return (lavg_t *) u_list_next((u_list_t *) list); } void -lavg_list_end_iteration(lavg_list_t *list) +lavg_list_end_iteration(lavg_list_t * list) { u_list_end_iteration((u_list_t *) list); } void -lavg_list_remove_cur(lavg_list_t *list) +lavg_list_remove_cur(lavg_list_t * list) { u_list_remove_cur((u_list_t *) list); } lavg_list_t * -lavg_list_destroy(lavg_list_t *list) +lavg_list_destroy(lavg_list_t * list) { return (lavg_list_t *) u_list_destroy((u_list_t *) list); } - diff --git a/lavg_list.h b/lavg_list.h index ffb133f..9748ed0 100644 --- a/lavg_list.h +++ b/lavg_list.h @@ -34,23 +34,23 @@ /* Entry to describe one job waiting for an appropriate load average to be executed */ typedef struct lavg_t { - struct cl_t *l_line; - time_t l_until; /* the timeout of the wait for load averages */ + struct cl_t *l_line; + time_t l_until; /* the timeout of the wait for load averages */ } lavg_t; typedef struct u_list_t lavg_list_t; /* functions prototypes */ extern lavg_list_t *lavg_list_init(void); -extern lavg_t *lavg_list_add_line(lavg_list_t *list, struct cl_t *line); -extern lavg_t *lavg_list_add(lavg_list_t *list, lavg_t *entry); +extern lavg_t *lavg_list_add_line(lavg_list_t * list, struct cl_t *line); +extern lavg_t *lavg_list_add(lavg_list_t * list, lavg_t * entry); /* WARNING: there should always be a unique iteration loop based on * u_list_first()/u_list_next() running at any one time in the code */ -extern lavg_t *lavg_list_first(lavg_list_t *list); -extern lavg_t *lavg_list_next(lavg_list_t *list); -extern void lavg_list_end_iteration(lavg_list_t *list); -extern void lavg_list_remove_cur(lavg_list_t *list); -extern lavg_list_t *lavg_list_destroy(lavg_list_t *list); +extern lavg_t *lavg_list_first(lavg_list_t * list); +extern lavg_t *lavg_list_next(lavg_list_t * list); +extern void lavg_list_end_iteration(lavg_list_t * list); +extern void lavg_list_remove_cur(lavg_list_t * list); +extern lavg_list_t *lavg_list_destroy(lavg_list_t * list); -#endif /* __LAVG_LIST_H__ */ +#endif /* __LAVG_LIST_H__ */ diff --git a/log.c b/log.c index d5a8d2e..46d8b50 100644 --- a/log.c +++ b/log.c @@ -34,22 +34,22 @@ #include #ifdef DEBUG -char debug_opt = 1; /* set to 1 if we are in debug mode */ +char debug_opt = 1; /* set to 1 if we are in debug mode */ #else -char debug_opt = 0; /* set to 1 if we are in debug mode */ +char debug_opt = 0; /* set to 1 if we are in debug mode */ #endif static void xopenlog(void); -char* make_msg(const char *append, char *fmt, va_list args); +char *make_msg(const char *append, char *fmt, va_list args); void log_syslog_str(int priority, char *msg); void log_console_str(char *msg); void log_fd_str(int fd, char *msg); static void log_syslog(int priority, int fd, char *fmt, va_list args); static void log_e(int priority, char *fmt, va_list args); #ifdef HAVE_LIBPAM -static void log_pame(int priority, pam_handle_t *pamh, int pamerrno, - char *fmt, va_list args); +static void log_pame(int priority, pam_handle_t * pamh, int pamerrno, + char *fmt, va_list args); #endif static char truncated[] = " (truncated)"; @@ -60,8 +60,8 @@ static void xopenlog(void) { if (!log_open) { - openlog(prog_name, LOG_PID, SYSLOG_FACILITY); - log_open=1; + openlog(prog_name, LOG_PID, SYSLOG_FACILITY); + log_open = 1; } } @@ -69,7 +69,8 @@ xopenlog(void) void xcloselog() { - if (log_open) closelog(); + if (log_open) + closelog(); log_open = 0; } @@ -81,19 +82,19 @@ make_msg(const char *append, char *fmt, va_list args) int len; char *msg = NULL; - if ( (msg = calloc(1, MAX_MSG + 1)) == NULL ) - return NULL; + if ((msg = calloc(1, MAX_MSG + 1)) == NULL) + return NULL; /* There's some confusion in the documentation about what vsnprintf * returns when the buffer overflows. Hmmm... */ len = vsnprintf(msg, MAX_MSG + 1, fmt, args); - if ( append != NULL ) { - size_t size_to_cat = ( (MAX_MSG-len) > 0) ? (MAX_MSG-len) : 0; - strncat(msg, ": ", size_to_cat); - strncat(msg, append, size_to_cat); - len += 2 + strlen(append); + if (append != NULL) { + size_t size_to_cat = ((MAX_MSG - len) > 0) ? (MAX_MSG - len) : 0; + strncat(msg, ": ", size_to_cat); + strncat(msg, append, size_to_cat); + len += 2 + strlen(append); } if (len >= MAX_MSG) - strcpy(msg + (MAX_MSG - 1) - sizeof(truncated), truncated); + strcpy(msg + (MAX_MSG - 1) - sizeof(truncated), truncated); return msg; } @@ -104,8 +105,8 @@ void log_syslog_str(int priority, char *msg) { if (dosyslog) { - xopenlog(); - syslog(priority, "%s", msg); + xopenlog(); + syslog(priority, "%s", msg); } } @@ -115,14 +116,14 @@ void log_console_str(char *msg) { if (foreground == 1) { - time_t t = time(NULL); - struct tm *ft; - char date[30]; + time_t t = time(NULL); + struct tm *ft; + char date[30]; - ft = localtime(&t); - date[0] = '\0'; - strftime(date, sizeof(date), "%H:%M:%S", ft); - fprintf(stderr, "%s %s\n", date, msg); + ft = localtime(&t); + date[0] = '\0'; + strftime(date, sizeof(date), "%H:%M:%S", ft); + fprintf(stderr, "%s %s\n", date, msg); } } @@ -131,9 +132,9 @@ log_console_str(char *msg) void log_fd_str(int fd, char *msg) { - if ( fd >= 0 ) { - send(fd, msg, strlen(msg), 0); - send(fd, "\n", strlen("\n"), 0); + if (fd >= 0) { + send(fd, msg, strlen(msg), 0); + send(fd, "\n", strlen("\n"), 0); } } @@ -145,8 +146,8 @@ log_syslog(int priority, int fd, char *fmt, va_list args) { char *msg; - if ( (msg = make_msg(NULL, fmt, args)) == NULL) - return; + if ((msg = make_msg(NULL, fmt, args)) == NULL) + return; log_syslog_str(priority, msg); log_console_str(msg); @@ -163,10 +164,10 @@ log_e(int priority, char *fmt, va_list args) int saved_errno; char *msg; - saved_errno=errno; + saved_errno = errno; - if ( (msg = make_msg(strerror(saved_errno), fmt, args)) == NULL ) - return ; + if ((msg = make_msg(strerror(saved_errno), fmt, args)) == NULL) + return; log_syslog_str(priority, msg); log_console_str(msg); @@ -179,12 +180,13 @@ log_e(int priority, char *fmt, va_list args) /* Same as log_syslog(), but also appends an error description corresponding * to the pam_error. */ static void -log_pame(int priority, pam_handle_t *pamh, int pamerrno, char *fmt, va_list args) +log_pame(int priority, pam_handle_t * pamh, int pamerrno, char *fmt, + va_list args) { char *msg; - if ( (msg = make_msg(pam_strerror(pamh, pamerrno), fmt, args)) == NULL ) - return ; + if ((msg = make_msg(pam_strerror(pamh, pamerrno), fmt, args)) == NULL) + return; log_syslog_str(priority, msg); log_console_str(msg); @@ -304,11 +306,11 @@ error_e(char *fmt, ...) #ifdef HAVE_LIBPAM /* Log a "complain" level message, with a PAM error description */ void -error_pame(pam_handle_t *pamh, int pamerrno, char *fmt, ...) +error_pame(pam_handle_t * pamh, int pamerrno, char *fmt, ...) { va_list args; - xcloselog(); /* PAM is likely to have used openlog() */ + xcloselog(); /* PAM is likely to have used openlog() */ va_start(args, fmt); log_pame(COMPLAIN_LEVEL, pamh, pamerrno, fmt, args); @@ -330,53 +332,54 @@ die(char *fmt, ...) } else { error("fcron child aborted: this does not affect the main fcron daemon," - " but this may prevent a job from being run or an email from being sent."); + " but this may prevent a job from being run or an email from being sent."); } exit(EXIT_ERR); -} +} /* Log a "complain" level message, with an error description, and exit */ void die_e(char *fmt, ...) { - va_list args; - int err_no = 0; + va_list args; + int err_no = 0; - err_no = errno; + err_no = errno; - va_start(args, fmt); - log_e(COMPLAIN_LEVEL, fmt, args); - va_end(args); - if (getpid() == daemon_pid) { + va_start(args, fmt); + log_e(COMPLAIN_LEVEL, fmt, args); + va_end(args); + if (getpid() == daemon_pid) { error("Aborted"); } else { error("fcron child aborted: this does not affect the main fcron daemon," - " but this may prevent a job from being run or an email from being sent."); + " but this may prevent a job from being run or an email from being sent."); } - exit(err_no); + exit(err_no); -} +} #ifdef HAVE_LIBPAM /* Log a "complain" level message, with a PAM error description, and exit */ void -die_pame(pam_handle_t *pamh, int pamerrno, char *fmt, ...) +die_pame(pam_handle_t * pamh, int pamerrno, char *fmt, ...) { va_list args; - xcloselog(); /* PAM is likely to have used openlog() */ + xcloselog(); /* PAM is likely to have used openlog() */ va_start(args, fmt); log_pame(COMPLAIN_LEVEL, pamh, pamerrno, fmt, args); va_end(args); - pam_end(pamh, pamerrno); - if (getpid() == daemon_pid) error("Aborted"); + pam_end(pamh, pamerrno); + if (getpid() == daemon_pid) + error("Aborted"); exit(EXIT_ERR); @@ -404,11 +407,11 @@ send_msg_fd_debug(int fd, char *fmt, ...) va_start(args, fmt); - if ( (msg = make_msg(NULL, fmt, args)) == NULL) - return; + if ((msg = make_msg(NULL, fmt, args)) == NULL) + return; - if ( debug_opt ) - log_syslog_str(DEBUG_LEVEL, msg); + if (debug_opt) + log_syslog_str(DEBUG_LEVEL, msg); log_fd_str(fd, msg); @@ -427,8 +430,8 @@ send_msg_fd(int fd, char *fmt, ...) va_start(args, fmt); - if ( (msg = make_msg(NULL, fmt, args)) == NULL) - return; + if ((msg = make_msg(NULL, fmt, args)) == NULL) + return; log_fd_str(fd, msg); @@ -436,5 +439,3 @@ send_msg_fd(int fd, char *fmt, ...) va_end(args); } - - diff --git a/log.h b/log.h index 5bf643a..0ec33d9 100644 --- a/log.h +++ b/log.h @@ -41,11 +41,11 @@ extern void error_e(char *fmt, ...); extern void die(char *fmt, ...); extern void die_e(char *fmt, ...); #ifdef HAVE_LIBPAM -extern void error_pame(pam_handle_t *pamh, int pamerrno, char *fmt, ...); -extern void die_pame(pam_handle_t *pamh, int pamerrno, char *fmt, ...); +extern void error_pame(pam_handle_t * pamh, int pamerrno, char *fmt, ...); +extern void die_pame(pam_handle_t * pamh, int pamerrno, char *fmt, ...); #endif extern void Debug(char *fmt, ...); extern void send_msg_fd_debug(int fd, char *fmt, ...); extern void send_msg_fd(int fd, char *fmt, ...); -#endif /* __LOG_H__ */ +#endif /* __LOG_H__ */ diff --git a/mem.c b/mem.c index db11080..2b9814e 100644 --- a/mem.c +++ b/mem.c @@ -29,15 +29,15 @@ strdup2(const char *str) { char *ptr; - if ( str == NULL ) + if (str == NULL) return NULL; ptr = strdup(str); - if ( ! ptr) + if (!ptr) die_e("Could not strdup()"); - return(ptr); + return (ptr); } char * @@ -45,43 +45,43 @@ strndup2(const char *str, size_t n) { char *ptr; - if ( str == NULL ) - return NULL; + if (str == NULL) + return NULL; ptr = strndup(str, n); - if ( ! ptr) + if (!ptr) die_e("Could not strdup()"); - return(ptr); + return (ptr); } void * -alloc_safe(size_t len, const char * desc) +alloc_safe(size_t len, const char *desc) /* allocate len-bytes of memory, and return the pointer. * Die with a log message if there is any error */ { void *ptr = NULL; ptr = calloc(1, len); - if ( ptr == NULL ) { - die_e("Could not allocate %d bytes of memory%s%s", len, (desc)? "for " : "", desc); + if (ptr == NULL) { + die_e("Could not allocate %d bytes of memory%s%s", len, + (desc) ? "for " : "", desc); } return ptr; } void * -realloc_safe(void *cur, size_t len, const char * desc) +realloc_safe(void *cur, size_t len, const char *desc) /* allocate len-bytes of memory, and return the pointer. * Die with a log message if there is any error */ { void *new = NULL; new = realloc(cur, len); - if ( new == NULL ) { - die_e("Could not reallocate %d bytes of memory%s%s", len, (desc)? "for " : "", desc); + if (new == NULL) { + die_e("Could not reallocate %d bytes of memory%s%s", len, + (desc) ? "for " : "", desc); } return new; } - - diff --git a/mem.h b/mem.h index d8b33fc..27b9809 100644 --- a/mem.h +++ b/mem.h @@ -55,7 +55,7 @@ /* functions prototypes */ extern char *strdup2(const char *); extern char *strndup2(const char *, size_t n); -extern void *alloc_safe(size_t len, const char * desc); -extern void *realloc_safe(void *ptr, size_t len, const char * desc); +extern void *alloc_safe(size_t len, const char *desc); +extern void *realloc_safe(void *ptr, size_t len, const char *desc); -#endif /* __MEM_H__ */ +#endif /* __MEM_H__ */ diff --git a/option.h b/option.h index 258ab5c..966538c 100644 --- a/option.h +++ b/option.h @@ -510,5 +510,4 @@ #define clear_hasrun(opt) \ (_bit_clear(opt, 30)) -#endif /* __OPTIONH__ */ - +#endif /* __OPTIONH__ */ diff --git a/pam.h b/pam.h index 2a18880..a53c37b 100644 --- a/pam.h +++ b/pam.h @@ -35,4 +35,4 @@ extern pam_handle_t *pamh; extern const struct pam_conv apamconv; -#endif /* __PAM_H__ */ +#endif /* __PAM_H__ */ diff --git a/read_string.c b/read_string.c index 3ba92f5..d6d1e76 100644 --- a/read_string.c +++ b/read_string.c @@ -39,68 +39,70 @@ extern char debug_opt; #define PAM_MAX_MSG_SIZE LINE_LEN #endif -char *read_string(int echo, const char *prompt) +char * +read_string(int echo, const char *prompt) /* read a line of input string, giving prompt when appropriate */ { struct termios term_before, term_tmp; char line[PAM_MAX_MSG_SIZE]; - int nc, have_term=0; + int nc, have_term = 0; - debug("called with echo='%s', prompt='%s'.", echo ? "ON":"OFF" , prompt); + debug("called with echo='%s', prompt='%s'.", echo ? "ON" : "OFF", prompt); - if (isatty(STDIN_FILENO)) { /* terminal state */ + if (isatty(STDIN_FILENO)) { /* terminal state */ - /* is a terminal so record settings and flush it */ - if ( tcgetattr(STDIN_FILENO, &term_before) != 0 ) { - debug("error: failed to get terminal settings"); - return NULL; - } - memcpy(&term_tmp, &term_before, sizeof(term_tmp)); - if (!echo) - term_tmp.c_lflag &= ~(ECHO); - have_term = 1; + /* is a terminal so record settings and flush it */ + if (tcgetattr(STDIN_FILENO, &term_before) != 0) { + debug("error: failed to get terminal settings"); + return NULL; + } + memcpy(&term_tmp, &term_before, sizeof(term_tmp)); + if (!echo) + term_tmp.c_lflag &= ~(ECHO); + have_term = 1; - } + } else if (!echo) - debug("warning: cannot turn echo off"); + debug("warning: cannot turn echo off"); /* reading the line */ while (1) { - fprintf(stderr, "%s", prompt); - /* this may, or may not set echo off -- drop pending input */ - if (have_term) - (void) tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_tmp); - - nc = read(STDIN_FILENO, line, sizeof(line)-1); - if (have_term) { - (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &term_before); - if (!echo) /* do we need a newline? */ - fprintf(stderr,"\n"); - } - if (nc > 0) { /* we got some user input */ - char *input; - - if (nc > 0 && line[nc-1] == '\n') { /* terminate */ - line[--nc] = '\0'; - } else { - line[nc] = '\0'; - } - input = strdup2(line); - Overwrite(line); - - return input; /* return malloc()ed string */ - } else if (nc == 0) { /* Ctrl-D */ - debug("user did not want to type anything"); - fprintf(stderr, "\n"); - break; - } + fprintf(stderr, "%s", prompt); + /* this may, or may not set echo off -- drop pending input */ + if (have_term) + (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_tmp); + + nc = read(STDIN_FILENO, line, sizeof(line) - 1); + if (have_term) { + (void)tcsetattr(STDIN_FILENO, TCSADRAIN, &term_before); + if (!echo) /* do we need a newline? */ + fprintf(stderr, "\n"); + } + if (nc > 0) { /* we got some user input */ + char *input; + + if (nc > 0 && line[nc - 1] == '\n') { /* terminate */ + line[--nc] = '\0'; + } + else { + line[nc] = '\0'; + } + input = strdup2(line); + Overwrite(line); + + return input; /* return malloc()ed string */ + } + else if (nc == 0) { /* Ctrl-D */ + debug("user did not want to type anything"); + fprintf(stderr, "\n"); + break; + } } if (have_term) - (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &term_before); + (void)tcsetattr(STDIN_FILENO, TCSADRAIN, &term_before); - memset(line, 0, PAM_MAX_MSG_SIZE); /* clean up */ + memset(line, 0, PAM_MAX_MSG_SIZE); /* clean up */ return NULL; } - diff --git a/read_string.h b/read_string.h index 2470fc5..3528b7e 100644 --- a/read_string.h +++ b/read_string.h @@ -27,9 +27,9 @@ #include "global.h" -#define CONV_ECHO_ON 1 /* types of echo state */ +#define CONV_ECHO_ON 1 /* types of echo state */ #define CONV_ECHO_OFF 0 extern char *read_string(int echo, const char *prompt); -#endif /* __READ_STRING_H__ */ +#endif /* __READ_STRING_H__ */ diff --git a/save.c b/save.c index 6408f16..5ce201f 100644 --- a/save.c +++ b/save.c @@ -30,11 +30,12 @@ extern char debug_opt; int write_buf_to_disk(int fd, char *write_buf, int *buf_used); int save_type(int fd, short int type, char *write_buf, int *buf_used); int save_str(int fd, short int type, char *str, char *write_buf, int *buf_used); -int save_strn(int fd, short int type, char *str, short int size, char *write_buf, - int *buf_used); -int save_lint(int fd, short int type, long int value, char *write_buf, int *buf_used); -int save_one_file(cf_t *file, char *filename, uid_t own_uid, gid_t own_gid, - time_t save_date); +int save_strn(int fd, short int type, char *str, short int size, + char *write_buf, int *buf_used); +int save_lint(int fd, short int type, long int value, char *write_buf, + int *buf_used); +int save_one_file(cf_t * file, char *filename, uid_t own_uid, gid_t own_gid, + time_t save_date); int @@ -44,13 +45,13 @@ save_type(int fd, short int type, char *write_buf, int *buf_used) short int size = 0; int write_len = sizeof(type) + sizeof(size); - if ( write_len > WRITE_BUF_LEN - *buf_used ) - if ( write_buf_to_disk(fd, write_buf, buf_used) == ERR ) - return ERR; + if (write_len > WRITE_BUF_LEN - *buf_used) + if (write_buf_to_disk(fd, write_buf, buf_used) == ERR) + return ERR; - memcpy((write_buf+*buf_used), &type, sizeof(type)); + memcpy((write_buf + *buf_used), &type, sizeof(type)); *buf_used += sizeof(type); - memcpy((write_buf+*buf_used), &size, sizeof(size)); + memcpy((write_buf + *buf_used), &size, sizeof(size)); *buf_used += sizeof(size); return OK; @@ -64,15 +65,15 @@ save_str(int fd, short int type, char *str, char *write_buf, int *buf_used) short int size = strlen(str); int write_len = sizeof(type) + sizeof(size) + size; - if ( write_len > WRITE_BUF_LEN - *buf_used ) - if ( write_buf_to_disk(fd, write_buf, buf_used) == ERR ) - return ERR; + if (write_len > WRITE_BUF_LEN - *buf_used) + if (write_buf_to_disk(fd, write_buf, buf_used) == ERR) + return ERR; - memcpy((write_buf+*buf_used), &type, sizeof(type)); + memcpy((write_buf + *buf_used), &type, sizeof(type)); *buf_used += sizeof(type); - memcpy((write_buf+*buf_used), &size, sizeof(size)); + memcpy((write_buf + *buf_used), &size, sizeof(size)); *buf_used += sizeof(size); - memcpy((write_buf+*buf_used), str, size); + memcpy((write_buf + *buf_used), str, size); *buf_used += size; return OK; @@ -80,41 +81,42 @@ save_str(int fd, short int type, char *str, char *write_buf, int *buf_used) int save_strn(int fd, short int type, char *str, short int size, char *write_buf, - int *buf_used) + int *buf_used) /* save a "size"-length string of type "type" in a binary fcrontab file */ { int write_len = sizeof(type) + sizeof(size) + size; - if ( write_len > WRITE_BUF_LEN - *buf_used ) - if ( write_buf_to_disk(fd, write_buf, buf_used) == ERR ) - return ERR; + if (write_len > WRITE_BUF_LEN - *buf_used) + if (write_buf_to_disk(fd, write_buf, buf_used) == ERR) + return ERR; - memcpy((write_buf+*buf_used), &type, sizeof(type)); + memcpy((write_buf + *buf_used), &type, sizeof(type)); *buf_used += sizeof(type); - memcpy((write_buf+*buf_used), &size, sizeof(size)); + memcpy((write_buf + *buf_used), &size, sizeof(size)); *buf_used += sizeof(size); - memcpy((write_buf+*buf_used), str, size); + memcpy((write_buf + *buf_used), str, size); *buf_used += size; return OK; } int -save_lint(int fd, short int type, long int value, char *write_buf, int *buf_used) +save_lint(int fd, short int type, long int value, char *write_buf, + int *buf_used) /* save an integer of type "type" in a binary fcrontab file */ { short int size = sizeof(value); int write_len = sizeof(type) + sizeof(size) + size; - if ( write_len > WRITE_BUF_LEN - *buf_used ) - if ( write_buf_to_disk(fd, write_buf, buf_used) == ERR ) - return ERR; + if (write_len > WRITE_BUF_LEN - *buf_used) + if (write_buf_to_disk(fd, write_buf, buf_used) == ERR) + return ERR; - memcpy((write_buf+*buf_used), &type, sizeof(type)); + memcpy((write_buf + *buf_used), &type, sizeof(type)); *buf_used += sizeof(type); - memcpy((write_buf+*buf_used), &size, sizeof(size)); + memcpy((write_buf + *buf_used), &size, sizeof(size)); *buf_used += sizeof(size); - memcpy((write_buf+*buf_used), &value, size); + memcpy((write_buf + *buf_used), &value, size); *buf_used += size; return OK; @@ -125,37 +127,38 @@ int write_buf_to_disk(int fd, char *write_buf, int *buf_used) /* write the buffer to disk */ { - ssize_t to_write = *buf_used; + ssize_t to_write = *buf_used; ssize_t written = 0; ssize_t return_val; int num_retries = 0; - while ( written < to_write ) { - if ( num_retries++ > (int)(to_write / 2) ) { - error("too many retries (%d) to write buf to disk : giving up.",num_retries); - return ERR; - } - return_val = write(fd, (write_buf+written), to_write - written); - if ( return_val == -1 ) { - error_e("could not write() buf to disk"); - return ERR; - } - written += return_val; + while (written < to_write) { + if (num_retries++ > (int)(to_write / 2)) { + error("too many retries (%d) to write buf to disk : giving up.", + num_retries); + return ERR; + } + return_val = write(fd, (write_buf + written), to_write - written); + if (return_val == -1) { + error_e("could not write() buf to disk"); + return ERR; + } + written += return_val; } /* */ - debug("write_buf_to_disk() : written %d/%d, %d (re)try(ies)", written, to_write, - num_retries); + debug("write_buf_to_disk() : written %d/%d, %d (re)try(ies)", written, + to_write, num_retries); /* */ - if ( written == to_write ) { - *buf_used = 0; - return OK; + if (written == to_write) { + *buf_used = 0; + return OK; } else { - error("write_buf_to_disk() : written %d bytes for %d requested.", - written, to_write); - return ERR; + error("write_buf_to_disk() : written %d bytes for %d requested.", + written, to_write); + return ERR; } } @@ -223,74 +226,84 @@ write_file_to_disk(int fd, struct cf_t *file, time_t time_date) Save_lint(fd, S_TIMEDATE_T, time_date, write_buf, &write_buf_used); /* Save the time diff between local (real) and system hour (if any) */ - if ( file->cf_tzdiff != 0 ) - Save_lint(fd, S_TZDIFF_T, file->cf_tzdiff, write_buf, &write_buf_used); + if (file->cf_tzdiff != 0) + Save_lint(fd, S_TZDIFF_T, file->cf_tzdiff, write_buf, &write_buf_used); /* env variables, */ for (env = env_list_first(file->cf_env_list); - env != NULL; - env = env_list_next(file->cf_env_list)) { + env != NULL; env = env_list_next(file->cf_env_list)) { Save_str(fd, S_ENVVAR_T, env->e_envvar, write_buf, &write_buf_used); } - + /* then, lines. */ for (line = file->cf_line_base; line; line = line->cl_next) { - /* this ones are saved for every lines */ - Save_str(fd, S_SHELL_T, line->cl_shell, write_buf, &write_buf_used); - Save_str(fd, S_RUNAS_T, line->cl_runas, write_buf, &write_buf_used); - Save_str(fd, S_MAILTO_T, line->cl_mailto, write_buf, &write_buf_used); - Save_strn(fd, S_OPTION_T, (char *)line->cl_option, OPTION_SIZE, - write_buf, &write_buf_used); - Save_lint(fd, S_NEXTEXE_T, line->cl_nextexe, write_buf, &write_buf_used); - - /* the following are saved only if needed */ - if ( line->cl_numexe ) - Save_strn(fd, S_NUMEXE_T, (char *)&line->cl_numexe, 1, write_buf, &write_buf_used); - if ( is_lavg(line->cl_option) ) - Save_strn(fd, S_LAVG_T, (char *)line->cl_lavg, LAVG_SIZE, - write_buf, &write_buf_used); - if ( line->cl_until > 0 ) - Save_lint(fd, S_UNTIL_T, line->cl_until, write_buf, &write_buf_used); - if ( line->cl_nice != 0 ) - Save_strn(fd, S_NICE_T, &line->cl_nice, 1, write_buf, &write_buf_used); - if ( line->cl_runfreq > 0 ) { - Save_lint(fd, S_RUNFREQ_T, line->cl_runfreq, write_buf, &write_buf_used); - Save_lint(fd, S_REMAIN_T, line->cl_remain, write_buf, &write_buf_used); - } - if ( line->cl_tz != NULL ) { - Save_str(fd, S_TZ_T, line->cl_tz, write_buf, &write_buf_used); - } - if ( line->cl_jitter > 0 ) { - Save_lint(fd, S_JITTER_T, line->cl_jitter, write_buf, &write_buf_used); - } - - if ( is_freq(line->cl_option) ) { - /* save the frequency to run the line */ - Save_lint(fd, S_FIRST_T, line->cl_first, write_buf, &write_buf_used); - Save_lint(fd, S_TIMEFREQ_T, line->cl_timefreq, write_buf, &write_buf_used); - } - else { - /* save the time and date bit fields */ - Save_strn(fd, S_MINS_T, (char *)line->cl_mins, bitstr_size(60), - write_buf, &write_buf_used); - Save_strn(fd, S_HRS_T, (char *)line->cl_hrs, bitstr_size(24), - write_buf, &write_buf_used); - Save_strn(fd, S_DAYS_T, (char *)line->cl_days, bitstr_size(32), - write_buf, &write_buf_used); - Save_strn(fd, S_MONS_T, (char *)line->cl_mons, bitstr_size(12), - write_buf, &write_buf_used); - Save_strn(fd, S_DOW_T, (char *)line->cl_dow, bitstr_size(8), - write_buf, &write_buf_used); - } - - /* This field *must* be the last of each line */ - Save_type(fd, S_ENDLINE_T, write_buf, &write_buf_used); + /* this ones are saved for every lines */ + Save_str(fd, S_SHELL_T, line->cl_shell, write_buf, &write_buf_used); + Save_str(fd, S_RUNAS_T, line->cl_runas, write_buf, &write_buf_used); + Save_str(fd, S_MAILTO_T, line->cl_mailto, write_buf, &write_buf_used); + Save_strn(fd, S_OPTION_T, (char *)line->cl_option, OPTION_SIZE, + write_buf, &write_buf_used); + Save_lint(fd, S_NEXTEXE_T, line->cl_nextexe, write_buf, + &write_buf_used); + + /* the following are saved only if needed */ + if (line->cl_numexe) + Save_strn(fd, S_NUMEXE_T, (char *)&line->cl_numexe, 1, write_buf, + &write_buf_used); + if (is_lavg(line->cl_option)) + Save_strn(fd, S_LAVG_T, (char *)line->cl_lavg, LAVG_SIZE, + write_buf, &write_buf_used); + if (line->cl_until > 0) + Save_lint(fd, S_UNTIL_T, line->cl_until, write_buf, + &write_buf_used); + if (line->cl_nice != 0) + Save_strn(fd, S_NICE_T, &line->cl_nice, 1, write_buf, + &write_buf_used); + if (line->cl_runfreq > 0) { + Save_lint(fd, S_RUNFREQ_T, line->cl_runfreq, write_buf, + &write_buf_used); + Save_lint(fd, S_REMAIN_T, line->cl_remain, write_buf, + &write_buf_used); + } + if (line->cl_tz != NULL) { + Save_str(fd, S_TZ_T, line->cl_tz, write_buf, &write_buf_used); + } + if (line->cl_jitter > 0) { + Save_lint(fd, S_JITTER_T, line->cl_jitter, write_buf, + &write_buf_used); + } + + if (is_freq(line->cl_option)) { + /* save the frequency to run the line */ + Save_lint(fd, S_FIRST_T, line->cl_first, write_buf, + &write_buf_used); + Save_lint(fd, S_TIMEFREQ_T, line->cl_timefreq, write_buf, + &write_buf_used); + } + else { + /* save the time and date bit fields */ + Save_strn(fd, S_MINS_T, (char *)line->cl_mins, bitstr_size(60), + write_buf, &write_buf_used); + Save_strn(fd, S_HRS_T, (char *)line->cl_hrs, bitstr_size(24), + write_buf, &write_buf_used); + Save_strn(fd, S_DAYS_T, (char *)line->cl_days, bitstr_size(32), + write_buf, &write_buf_used); + Save_strn(fd, S_MONS_T, (char *)line->cl_mons, bitstr_size(12), + write_buf, &write_buf_used); + Save_strn(fd, S_DOW_T, (char *)line->cl_dow, bitstr_size(8), + write_buf, &write_buf_used); + } + + /* This field *must* be the last of each line */ + Save_type(fd, S_ENDLINE_T, write_buf, &write_buf_used); } - if ( write_buf_to_disk(fd, write_buf, &write_buf_used) == ERR ) { - error("Could not write final buffer content to disk: file %s has not been saved.", file->cf_user); - return ERR; + if (write_buf_to_disk(fd, write_buf, &write_buf_used) == ERR) { + error + ("Could not write final buffer content to disk: file %s has not been saved.", + file->cf_user); + return ERR; } return OK; @@ -298,83 +311,88 @@ write_file_to_disk(int fd, struct cf_t *file, time_t time_date) int -save_one_file(cf_t *file, char *filename, uid_t own_uid, gid_t own_gid, time_t save_date) +save_one_file(cf_t * file, char *filename, uid_t own_uid, gid_t own_gid, + time_t save_date) /* save a given file to disk */ { int fd; /* open file */ #ifdef WITH_SELINUX - if ( is_selinux_enabled() && setfscreatecon(file->cf_file_context) ) - { - error_e("Could not set create context for file %s", filename); - return ERR; + if (is_selinux_enabled() && setfscreatecon(file->cf_file_context)) { + error_e("Could not set create context for file %s", filename); + return ERR; } #endif - fd = open_as_user(filename, own_uid, own_gid, O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, S_IRUSR|S_IWUSR); + fd = open_as_user(filename, own_uid, own_gid, + O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR); #ifdef WITH_SELINUX - if ( is_selinux_enabled() ) - setfscreatecon(NULL); + if (is_selinux_enabled()) + setfscreatecon(NULL); #endif - if ( fd == -1 ) { - error_e("Could not open %s", filename); - return ERR; + if (fd == -1) { + error_e("Could not open %s", filename); + return ERR; } if (fchown(fd, own_uid, own_gid) != 0) { - error_e("Could not fchown %s to uid:%d gid:%d", filename, own_uid, own_gid); - if ( close(fd) < 0 ) - error_e("save_one_file(%s): could not close(fd)", filename); - remove_as_user(filename, own_uid, own_gid); - return ERR; + error_e("Could not fchown %s to uid:%d gid:%d", filename, own_uid, + own_gid); + if (close(fd) < 0) + error_e("save_one_file(%s): could not close(fd)", filename); + remove_as_user(filename, own_uid, own_gid); + return ERR; } /* save file : */ - if ( write_file_to_disk(fd, file, save_date) == ERR ) { - if ( close(fd) < 0 ) - error_e("save_one_file(%s): could not close(fd)", filename); - remove_as_user(filename, own_uid, own_gid); - return ERR; + if (write_file_to_disk(fd, file, save_date) == ERR) { + if (close(fd) < 0) + error_e("save_one_file(%s): could not close(fd)", filename); + remove_as_user(filename, own_uid, own_gid); + return ERR; } - if ( close(fd) < 0 ) - error_e("save_one_file(%s): could not close(fd)", filename); + if (close(fd) < 0) + error_e("save_one_file(%s): could not close(fd)", filename); return OK; } int -save_file_safe(cf_t *file, char *final_path, char *prog_name, uid_t own_uid, - gid_t own_gid, time_t save_date) +save_file_safe(cf_t * file, char *final_path, char *prog_name, uid_t own_uid, + gid_t own_gid, time_t save_date) /* save a file to a temp path, and then rename it (safely) to avoid loss of data * if a system crash, hardware failure, etc happens. */ { - char temp_path[PATH_LEN+4]; + char temp_path[PATH_LEN + 4]; int final_path_len, temp_path_index; char *tmp_str = ".tmp"; final_path_len = strlen(final_path); - strncpy(temp_path, final_path, sizeof(temp_path)-sizeof(tmp_str)); - temp_path_index = ( final_path_len > sizeof(temp_path)-sizeof(tmp_str) ) ? - sizeof(temp_path)-sizeof(tmp_str) : final_path_len; + strncpy(temp_path, final_path, sizeof(temp_path) - sizeof(tmp_str)); + temp_path_index = (final_path_len > sizeof(temp_path) - sizeof(tmp_str)) ? + sizeof(temp_path) - sizeof(tmp_str) : final_path_len; strcpy(&temp_path[temp_path_index], tmp_str); - if ( save_one_file(file, temp_path, own_uid, own_gid, save_date) == OK ) { - if ( rename_as_user(temp_path, final_path, own_uid, own_gid) != 0 ) { - error_e("Cannot rename %s to %s", temp_path, final_path); - error("%s will try to save the name to its definitive filename " - "directly.", prog_name); - error("If there is an error, root may consider to replace %s (which is " - "a valid copy) by %s manually.", final_path, temp_path); - if ( save_one_file(file, final_path, own_uid, own_gid, save_date) == ERR ) - return ERR; - } + if (save_one_file(file, temp_path, own_uid, own_gid, save_date) == OK) { + if (rename_as_user(temp_path, final_path, own_uid, own_gid) != 0) { + error_e("Cannot rename %s to %s", temp_path, final_path); + error("%s will try to save the name to its definitive filename " + "directly.", prog_name); + error + ("If there is an error, root may consider to replace %s (which is " + "a valid copy) by %s manually.", final_path, temp_path); + if (save_one_file(file, final_path, own_uid, own_gid, save_date) == + ERR) + return ERR; + } } else { - error("Since %s has not been able to save %s's file, it will keep " - "the previous version (if any) of %s.", prog_name, final_path, final_path); - return ERR; + error("Since %s has not been able to save %s's file, it will keep " + "the previous version (if any) of %s.", prog_name, final_path, + final_path); + return ERR; } return OK; diff --git a/save.h b/save.h index a842591..638b408 100644 --- a/save.h +++ b/save.h @@ -27,8 +27,8 @@ /* functions defined by save.c */ extern int write_file_to_disk(int fd, struct cf_t *file, time_t time_date); -extern int save_file_safe(cf_t *file, char *final_path, char *prog_name, uid_t own_uid, - gid_t own_gid, time_t save_date); +extern int save_file_safe(cf_t * file, char *final_path, char *prog_name, + uid_t own_uid, gid_t own_gid, time_t save_date); /* here is the format fcron(tab) uses to save the fcrontabs : @@ -41,7 +41,7 @@ extern int save_file_safe(cf_t *file, char *final_path, char *prog_name, uid_t o /* kept for backward compatibility : we now have an extended * save format with no use of such a fileversion (unless to know that * the save file is in extended format, not an old one) */ -#define S_FILEVERSION 100 /* syntax's version of fcrontabs */ +#define S_FILEVERSION 100 /* syntax's version of fcrontabs */ /* type constants : DO NOT REMOVE ANY of them : they are used for backward @@ -51,35 +51,35 @@ extern int save_file_safe(cf_t *file, char *final_path, char *prog_name, uid_t o /* type is an unsigned short int */ /* header file types */ -#define S_HEADER_T 1 /* file version */ -#define S_USER_T 2 /* name of the fcrontab's owner */ -#define S_TIMEDATE_T 3 /* time and date of saving */ -#define S_TZDIFF_T 4 /* time diff between the local and system hour */ +#define S_HEADER_T 1 /* file version */ +#define S_USER_T 2 /* name of the fcrontab's owner */ +#define S_TIMEDATE_T 3 /* time and date of saving */ +#define S_TZDIFF_T 4 /* time diff between the local and system hour */ /* env var */ -#define S_ENVVAR_T 1000 /* an environment variable */ +#define S_ENVVAR_T 1000 /* an environment variable */ /* line field types */ -#define S_ENDLINE_T 2000 /* we need to know where a new line begin */ -#define S_SHELL_T 2001 /* shell command of the line */ -#define S_NUMEXE_T 2002 /* num of entries in queues & running processes */ -#define S_LAVG_T 2003 /* load averages needed (1, 5, 15 mins) */ -#define S_UNTIL_T 2004 /* timeout of the wait for a lavg value */ -#define S_NICE_T 2005 /* nice value to control priority */ -#define S_RUNAS_T 2006 /* determine permissions of the job */ -#define S_MAILTO_T 2007 /* mail output to cl_mailto */ -#define S_NEXTEXE_T 2008 /* time and date of the next execution */ -#define S_REMAIN_T 2009 /* remaining until next execution */ -#define S_TIMEFREQ_T 2010 /* Run every n seconds */ -#define S_RUNFREQ_T 2011 /* Run once every n matches */ -#define S_MINS_T 2012 /* mins boolean array */ -#define S_HRS_T 2013 /* hrs boolean array */ -#define S_DAYS_T 2014 /* days boolean array */ -#define S_MONS_T 2015 /* mons boolean array */ -#define S_DOW_T 2016 /* dow boolean array */ -#define S_OPTION_T 2017 /* options for that line (see option.h) */ -#define S_FIRST_T 2018 /* wait time before first execution */ -#define S_TZ_T 2019 /* time zone of the line */ -#define S_JITTER_T 2020 /* jitter of the line */ +#define S_ENDLINE_T 2000 /* we need to know where a new line begin */ +#define S_SHELL_T 2001 /* shell command of the line */ +#define S_NUMEXE_T 2002 /* num of entries in queues & running processes */ +#define S_LAVG_T 2003 /* load averages needed (1, 5, 15 mins) */ +#define S_UNTIL_T 2004 /* timeout of the wait for a lavg value */ +#define S_NICE_T 2005 /* nice value to control priority */ +#define S_RUNAS_T 2006 /* determine permissions of the job */ +#define S_MAILTO_T 2007 /* mail output to cl_mailto */ +#define S_NEXTEXE_T 2008 /* time and date of the next execution */ +#define S_REMAIN_T 2009 /* remaining until next execution */ +#define S_TIMEFREQ_T 2010 /* Run every n seconds */ +#define S_RUNFREQ_T 2011 /* Run once every n matches */ +#define S_MINS_T 2012 /* mins boolean array */ +#define S_HRS_T 2013 /* hrs boolean array */ +#define S_DAYS_T 2014 /* days boolean array */ +#define S_MONS_T 2015 /* mons boolean array */ +#define S_DOW_T 2016 /* dow boolean array */ +#define S_OPTION_T 2017 /* options for that line (see option.h) */ +#define S_FIRST_T 2018 /* wait time before first execution */ +#define S_TZ_T 2019 /* time zone of the line */ +#define S_JITTER_T 2020 /* jitter of the line */ -#endif /* __SAVE_H__ */ +#endif /* __SAVE_H__ */ diff --git a/socket.c b/socket.c index 494da26..3fdb68d 100644 --- a/socket.c +++ b/socket.c @@ -32,47 +32,53 @@ #include "fcronconf.h" -void remove_connection(struct fcrondyn_cl **client, struct fcrondyn_cl *prev_client); +void remove_connection(struct fcrondyn_cl **client, + struct fcrondyn_cl *prev_client); void exe_cmd(struct fcrondyn_cl *client); -#ifdef SO_PEERCRED /* linux */ +#ifdef SO_PEERCRED /* linux */ void auth_client_so_peercred(struct fcrondyn_cl *client); -#elif defined(HAVE_GETPEERUCRED) || defined(HAVE_GETPEEREID) /* resp. solaris 10 and Free/OpenBSD) */ +#elif defined(HAVE_GETPEERUCRED) || defined(HAVE_GETPEEREID) /* resp. solaris 10 and Free/OpenBSD) */ void auth_client_getpeer(struct fcrondyn_cl *client); #endif void auth_client_password(struct fcrondyn_cl *client); void cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root); void print_fields(int fd, unsigned char *details); -void print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, int index, - time_t until); -void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root); -void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e, - int is_root); -void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e); +void print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, + int index, time_t until); +void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, + int is_root); +void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t * e, + int is_root); +void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, + exe_t * e); void cmd_run(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root); -void add_to_select_set(int fd, fd_set *set, int *max_fd); -void remove_from_select_set(int fd, fd_set *set, int *max_fd); - -fcrondyn_cl *fcrondyn_cl_base; /* list of connected fcrondyn clients */ -int fcrondyn_cl_num = 0; /* number of fcrondyn clients currently connected */ -fd_set read_set; /* client fds list : cmd waiting ? */ -fd_set master_set; /* master set : needed since select() modify read_set */ -int set_max_fd = 0; /* needed by select() */ -int listen_fd = -1; /* fd which catches incoming connection */ -int auth_fail = 0; /* number of auth failure */ -time_t auth_nofail_since = 0; /* we refuse auth since x due to too many failures */ +void add_to_select_set(int fd, fd_set * set, int *max_fd); +void remove_from_select_set(int fd, fd_set * set, int *max_fd); + +fcrondyn_cl *fcrondyn_cl_base; /* list of connected fcrondyn clients */ +int fcrondyn_cl_num = 0; /* number of fcrondyn clients currently connected */ +fd_set read_set; /* client fds list : cmd waiting ? */ +fd_set master_set; /* master set : needed since select() modify read_set */ +int set_max_fd = 0; /* needed by select() */ +int listen_fd = -1; /* fd which catches incoming connection */ +int auth_fail = 0; /* number of auth failure */ +time_t auth_nofail_since = 0; /* we refuse auth since x due to too many failures */ /* some error messages ... */ char err_no_err_str[] = "Command successfully completed.\n"; -char err_unknown_str[] = "Fcron has encountered an error : command not completed.\n"; +char err_unknown_str[] = + "Fcron has encountered an error : command not completed.\n"; char err_cmd_unknown_str[] = "Unknown command.\n"; char err_job_nfound_str[] = "No corresponding job found.\n"; -char err_rjob_nfound_str[] = "No corresponding running job found.\n (The job may have " -"just finished its execution.)\n"; +char err_rjob_nfound_str[] = + "No corresponding running job found.\n (The job may have " + "just finished its execution.)\n"; char err_invalid_user_str[] = "Invalid user : unable to find a passwd entry.\n"; char err_invalid_args_str[] = "Invalid arguments.\n"; char err_job_nallowed_str[] = "You are not allowed to see/change this line.\n"; char err_all_nallowed_str[] = "You are not allowed to list all jobs.\n"; -char err_others_nallowed_str[] = "You are not allowed to list other users' jobs.\n"; +char err_others_nallowed_str[] = + "You are not allowed to list other users' jobs.\n"; /* Send an error message to fcrondyn */ #define Send_err_msg(FD, MSG) \ @@ -103,32 +109,33 @@ char err_others_nallowed_str[] = "You are not allowed to list other users' jobs. void -add_to_select_set(int fd, fd_set *set, int *max_fd) +add_to_select_set(int fd, fd_set * set, int *max_fd) /* add fd to set, and update max_fd if necessary (for select()) */ { FD_SET(fd, set); - if ( fd > *max_fd ) - *max_fd = fd; + if (fd > *max_fd) + *max_fd = fd; } void -remove_from_select_set(int fd, fd_set *set, int *max_fd) +remove_from_select_set(int fd, fd_set * set, int *max_fd) /* remove fd to set, and update max_fd if necessary (for select()) */ { FD_CLR(fd, set); - if ( fd == *max_fd ) { - /* find the biggest fd in order to update max_fd */ - struct fcrondyn_cl *client; - int tmp_max_fd = listen_fd; - - for ( client = fcrondyn_cl_base; client != NULL; client = client->fcl_next) { - if ( client->fcl_sock_fd > tmp_max_fd ) - tmp_max_fd = client->fcl_sock_fd; - } - - /* update max_fd */ - *max_fd = tmp_max_fd; + if (fd == *max_fd) { + /* find the biggest fd in order to update max_fd */ + struct fcrondyn_cl *client; + int tmp_max_fd = listen_fd; + + for (client = fcrondyn_cl_base; client != NULL; + client = client->fcl_next) { + if (client->fcl_sock_fd > tmp_max_fd) + tmp_max_fd = client->fcl_sock_fd; + } + + /* update max_fd */ + *max_fd = tmp_max_fd; } } @@ -145,58 +152,64 @@ init_socket(void) FD_ZERO(&read_set); FD_ZERO(&master_set); - if ( (listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1 ) { - error_e("Could not create socket : fcrondyn won't work"); - return; + if ((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { + error_e("Could not create socket : fcrondyn won't work"); + return; } addr.sun_family = AF_UNIX; len = strlen(fifofile); - if ( len > sizeof(addr.sun_path) - 1 ) { - error("Error : fifo file path too long (max is %d)", sizeof(addr.sun_path) - 1); - goto err; + if (len > sizeof(addr.sun_path) - 1) { + error("Error : fifo file path too long (max is %d)", + sizeof(addr.sun_path) - 1); + goto err; } strncpy(addr.sun_path, fifofile, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path) -1 ] = '\0'; + addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; sun_len = (addr.sun_path - (char *)&addr) + len; #if HAVE_SA_LEN addr.sun_len = sun_len; #endif unlink(fifofile); - if (bind(listen_fd, (struct sockaddr*) &addr, sun_len) != 0){ - error_e("Cannot bind socket to '%s'", fifofile); - goto err; + if (bind(listen_fd, (struct sockaddr *)&addr, sun_len) != 0) { + error_e("Cannot bind socket to '%s'", fifofile); + goto err; } - if ( listen(listen_fd, MAX_CONNECTION) != 0 ) { - error_e("Cannot set socket in listen mode"); - goto err; + if (listen(listen_fd, MAX_CONNECTION) != 0) { + error_e("Cannot set socket in listen mode"); + goto err; } /* */ /* The exec bit is not necessary and ignored on all systems but AIX, where it is * needed to allow fcrondyn to open the file */ - if ( chmod(fifofile, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH) != 0 ) - error_e("Cannot chmod() socket file"); + if (chmod + (fifofile, + S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | + S_IWOTH | S_IXOTH) != 0) + error_e("Cannot chmod() socket file"); /* */ - + fcntl(listen_fd, F_SETFD, 1); /* set listen_fd to O_NONBLOCK : we do not want fcron to be stopped on error, etc */ - if ( fcntl(listen_fd, F_SETFL, fcntl(listen_fd, F_GETFL) | O_NONBLOCK) == -1 ) { - error_e("Could not set listen_fd attribute O_NONBLOCK : no fcrondyn support"); - goto err; + if (fcntl(listen_fd, F_SETFL, fcntl(listen_fd, F_GETFL) | O_NONBLOCK) == -1) { + error_e + ("Could not set listen_fd attribute O_NONBLOCK : no fcrondyn support"); + goto err; } /* no error */ add_to_select_set(listen_fd, &master_set, &set_max_fd); - + /* copy master in read_fs, because read_fs will be modified by select() */ read_set = master_set; - debug("Socket initialized : listen_fd : %d set_max_fd : %d ", listen_fd, set_max_fd); + debug("Socket initialized : listen_fd : %d set_max_fd : %d ", listen_fd, + set_max_fd); return; - err: + err: close_socket(); } @@ -220,8 +233,8 @@ auth_client_getpeer(struct fcrondyn_cl *client) #elif defined(HAVE_GETPEEREID) uid_t euid = -1; gid_t egid = -1; -#endif - +#endif + #ifdef GETPEERUCRED if (getpeerucred(client->fcl_sock_fd, &ucred) < 0) { error_e("Could not get client credentials using getpeerucred()"); @@ -233,22 +246,23 @@ auth_client_getpeer(struct fcrondyn_cl *client) return; } #else -# error "No authentication method in auth_client_getpeer()!" -#endif +#error "No authentication method in auth_client_getpeer()!" +#endif p_entry = getpwuid(cred.uid); - if ( p_entry == NULL ) { + if (p_entry == NULL) { error_e("Could not find password entry for uid %d", cred.uid); - return; + return; } /* Successfully identified user: */ client->fcl_user = strdup2(p_entry->pw_name); - explain("Client's pid=%d, uid=%d, gid=%d username=%s\n", cred.pid, cred.uid, cred.gid, client->fcl_user); + explain("Client's pid=%d, uid=%d, gid=%d username=%s\n", cred.pid, cred.uid, + cred.gid, client->fcl_user); } -#endif /* HAVE_GETPEERUCRED || HAVE_GETPEEREID */ +#endif /* HAVE_GETPEERUCRED || HAVE_GETPEEREID */ @@ -270,31 +284,35 @@ auth_client_so_peercred(struct fcrondyn_cl *client) uid_t uid; gid_t gid; }; -#endif /* struct ucred not defined */ +#endif /* struct ucred not defined */ struct ucred cred; socklen_t cred_size = sizeof(cred); struct passwd *p_entry = NULL; - - setsockopt(client->fcl_sock_fd, SOL_SOCKET, SO_PASSCRED, &true, sizeof(true)); - if ( getsockopt(client->fcl_sock_fd, SOL_SOCKET, SO_PEERCRED, - &cred, &cred_size) != 0) { - error_e("Could not get client credentials using getsockopt(SO_PEERCRED)"); - return; + + setsockopt(client->fcl_sock_fd, SOL_SOCKET, SO_PASSCRED, &true, + sizeof(true)); + if (getsockopt + (client->fcl_sock_fd, SOL_SOCKET, SO_PEERCRED, &cred, + &cred_size) != 0) { + error_e + ("Could not get client credentials using getsockopt(SO_PEERCRED)"); + return; } p_entry = getpwuid(cred.uid); - if ( p_entry == NULL ) { + if (p_entry == NULL) { error_e("Could not find password entry for uid %d", cred.uid); - return; + return; } /* Successfully identified user: */ client->fcl_user = strdup2(p_entry->pw_name); - explain("Client's pid=%d, uid=%d, gid=%d username=%s\n", cred.pid, cred.uid, cred.gid, client->fcl_user); + explain("Client's pid=%d, uid=%d, gid=%d username=%s\n", cred.pid, cred.uid, + cred.gid, client->fcl_user); } -#endif /* SO_PEERCRED */ +#endif /* SO_PEERCRED */ void auth_client_password(struct fcrondyn_cl *client) @@ -306,19 +324,19 @@ auth_client_password(struct fcrondyn_cl *client) #ifdef HAVE_GETSPNAM struct spwd *pass_sp = NULL; - if ( (pass_sp = getspnam((char *) client->fcl_cmd )) == NULL ) { - error_e("could not getspnam %s", (char *) client->fcl_cmd); - send(client->fcl_sock_fd, "0", sizeof("0"), 0); - return; + if ((pass_sp = getspnam((char *)client->fcl_cmd)) == NULL) { + error_e("could not getspnam %s", (char *)client->fcl_cmd); + send(client->fcl_sock_fd, "0", sizeof("0"), 0); + return; } pass_sys = pass_sp->sp_pwdp; #else struct passwd *pass = NULL; errno = 0; - if ( (pass = getpwnam((char *) client->fcl_cmd )) == NULL ) { - error_e("could not getpwnam %s", (char *) client->fcl_cmd); - send(client->fcl_sock_fd, "0", sizeof("0"), 0); - return; + if ((pass = getpwnam((char *)client->fcl_cmd)) == NULL) { + error_e("could not getpwnam %s", (char *)client->fcl_cmd); + send(client->fcl_sock_fd, "0", sizeof("0"), 0); + return; } pass_sys = pass->pw_passwd; #endif @@ -329,37 +347,37 @@ auth_client_password(struct fcrondyn_cl *client) /* we need to limit auth failures : otherwise fcron may be used to "read" * shadow password !!! (or to crack it using a test-all-possible-password attack) */ - if (auth_fail > 0 && auth_nofail_since + AUTH_WAIT <= now ) - /* no auth time exceeded : set counter to 0 */ - auth_fail = 0; + if (auth_fail > 0 && auth_nofail_since + AUTH_WAIT <= now) + /* no auth time exceeded : set counter to 0 */ + auth_fail = 0; if (auth_fail >= MAX_AUTH_FAIL) { - error("Too many authentication failures : try to connect later."); - send(client->fcl_sock_fd, "0", sizeof("0"), 0); - auth_fail = auth_nofail_since = 0; - return; + error("Too many authentication failures : try to connect later."); + send(client->fcl_sock_fd, "0", sizeof("0"), 0); + auth_fail = auth_nofail_since = 0; + return; } /* the password is stored after the user name */ - pass_str = &( (char *)client->fcl_cmd ) [ strlen( (char*)client->fcl_cmd ) + 1 ]; - if ( (pass_cry = crypt(pass_str, pass_sys)) == NULL ) { - error_e("could not crypt()"); - send(client->fcl_sock_fd, "0", sizeof("0"), 0); - Overwrite(pass_str); - return; + pass_str = &((char *)client->fcl_cmd)[strlen((char *)client->fcl_cmd) + 1]; + if ((pass_cry = crypt(pass_str, pass_sys)) == NULL) { + error_e("could not crypt()"); + send(client->fcl_sock_fd, "0", sizeof("0"), 0); + Overwrite(pass_str); + return; } /* debug("pass_sp->sp_pwdp : %s", pass_sp->sp_pwdp); */ /* debug("pass_cry : %s", pass_cry); */ if (strcmp(pass_cry, pass_sys) == 0) { - client->fcl_user = strdup2( (char *) client->fcl_cmd ); - send(client->fcl_sock_fd, "1", sizeof("1"), 0); + client->fcl_user = strdup2((char *)client->fcl_cmd); + send(client->fcl_sock_fd, "1", sizeof("1"), 0); } else { - auth_fail++; - auth_nofail_since = now; - error("Invalid passwd for %s from socket %d", - (char *) client->fcl_cmd, client->fcl_sock_fd); - send(client->fcl_sock_fd, "0", sizeof("0"), 0); + auth_fail++; + auth_nofail_since = now; + error("Invalid passwd for %s from socket %d", + (char *)client->fcl_cmd, client->fcl_sock_fd); + send(client->fcl_sock_fd, "0", sizeof("0"), 0); } Overwrite(pass_str); @@ -405,17 +423,17 @@ print_fields(int fd, unsigned char *details) Add_field(field_cmd); Add_field(field_endline); - fields[TERM_LEN-1] = '\0'; + fields[TERM_LEN - 1] = '\0'; - if ( send(fd, fields, (len < sizeof(fields)) ? len : sizeof(fields), 0) < 0 ) - error_e("error in send()"); + if (send(fd, fields, (len < sizeof(fields)) ? len : sizeof(fields), 0) < 0) + error_e("error in send()"); } void -print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, int index, - time_t until) +print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, + int index, time_t until) /* print some basic fields of a line, and some more if details == 1 */ { char buf[TERM_LEN]; @@ -424,55 +442,61 @@ print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, int in len = snprintf(buf, sizeof(buf), "%-5ld", line->cl_id); - if ( bit_test(details, FIELD_USER) ) - len += snprintf(buf+len, sizeof(buf)-len, " %-6s", line->cl_file->cf_user); - if ( bit_test(details, FIELD_PID) ) - len += snprintf(buf+len, sizeof(buf)-len, " %-7d", (int)pid); - if ( bit_test(details, FIELD_INDEX) ) - len += snprintf(buf+len, sizeof(buf)-len, " %-5d", index); - if ( bit_test(details, FIELD_RQ) ) - len += snprintf(buf+len, sizeof(buf)-len, " %-4d", line->cl_numexe); - if ( bit_test(details, FIELD_OPTIONS) ) { - char opt[9]; - int i = 0; - opt[0] = '\0'; - if ( is_lavg(line->cl_option) ) - i += snprintf(opt+i, sizeof(opt)-i, "L%.*s", - (is_lavg_sev(line->cl_option)) ? 0:1, "O"); - if ( is_serial(line->cl_option) ) - i += snprintf(opt+i, sizeof(opt)-i, "%.*sS%.*s", i, ",", - (is_serial_sev(line->cl_option)) ? 0:1, "O"); - if ( is_exe_sev(line->cl_option) ) - i += snprintf(opt+i, sizeof(opt)-i, "%.*sES", i, ","); - - len += snprintf(buf+len, sizeof(buf)-len, " %-9s", opt); - } - if ( bit_test(details, FIELD_LAVG) ) { - len += snprintf(buf+len, sizeof(buf)-len, " %.1f,%.1f,%.1f", - ((double)((line->cl_lavg)[0]))/10, - ((double)((line->cl_lavg)[1]))/10, - ((double)((line->cl_lavg)[2]))/10); - if ( until > 0 ) { - ftime = localtime( &until ); - len += snprintf(buf+len, sizeof(buf)-len, " %02d/%02d/%d %02d:%02d %s", - (ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900), - ftime->tm_hour, ftime->tm_min, - (is_strict(line->cl_option)) ? "Y":"N"); - } - else - len += snprintf(buf+len, sizeof(buf)-len, " %18s", " (no until set) "); - } - if ( bit_test(details, FIELD_SCHEDULE) ) { - ftime = localtime( &(line->cl_nextexe) ); - len += snprintf(buf+len, sizeof(buf)-len, " %02d/%02d/%d %02d:%02d", - (ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900), - ftime->tm_hour, ftime->tm_min ); - } - len += snprintf(buf+len, sizeof(buf)-len, " %s\n", line->cl_shell); - - if ( send(fd, buf, (len < sizeof(buf)) ? len : sizeof(buf), 0) < 0 ) - error_e("error in send()"); - + if (bit_test(details, FIELD_USER)) + len += + snprintf(buf + len, sizeof(buf) - len, " %-6s", + line->cl_file->cf_user); + if (bit_test(details, FIELD_PID)) + len += snprintf(buf + len, sizeof(buf) - len, " %-7d", (int)pid); + if (bit_test(details, FIELD_INDEX)) + len += snprintf(buf + len, sizeof(buf) - len, " %-5d", index); + if (bit_test(details, FIELD_RQ)) + len += snprintf(buf + len, sizeof(buf) - len, " %-4d", line->cl_numexe); + if (bit_test(details, FIELD_OPTIONS)) { + char opt[9]; + int i = 0; + opt[0] = '\0'; + if (is_lavg(line->cl_option)) + i += snprintf(opt + i, sizeof(opt) - i, "L%.*s", + (is_lavg_sev(line->cl_option)) ? 0 : 1, "O"); + if (is_serial(line->cl_option)) + i += snprintf(opt + i, sizeof(opt) - i, "%.*sS%.*s", i, ",", + (is_serial_sev(line->cl_option)) ? 0 : 1, "O"); + if (is_exe_sev(line->cl_option)) + i += snprintf(opt + i, sizeof(opt) - i, "%.*sES", i, ","); + + len += snprintf(buf + len, sizeof(buf) - len, " %-9s", opt); + } + if (bit_test(details, FIELD_LAVG)) { + len += snprintf(buf + len, sizeof(buf) - len, " %.1f,%.1f,%.1f", + ((double)((line->cl_lavg)[0])) / 10, + ((double)((line->cl_lavg)[1])) / 10, + ((double)((line->cl_lavg)[2])) / 10); + if (until > 0) { + ftime = localtime(&until); + len += + snprintf(buf + len, sizeof(buf) - len, + " %02d/%02d/%d %02d:%02d %s", (ftime->tm_mon + 1), + ftime->tm_mday, (ftime->tm_year + 1900), + ftime->tm_hour, ftime->tm_min, + (is_strict(line->cl_option)) ? "Y" : "N"); + } + else + len += + snprintf(buf + len, sizeof(buf) - len, " %18s", + " (no until set) "); + } + if (bit_test(details, FIELD_SCHEDULE)) { + ftime = localtime(&(line->cl_nextexe)); + len += snprintf(buf + len, sizeof(buf) - len, " %02d/%02d/%d %02d:%02d", + (ftime->tm_mon + 1), ftime->tm_mday, + (ftime->tm_year + 1900), ftime->tm_hour, ftime->tm_min); + } + len += snprintf(buf + len, sizeof(buf) - len, " %s\n", line->cl_shell); + + if (send(fd, buf, (len < sizeof(buf)) ? len : sizeof(buf), 0) < 0) + error_e("error in send()"); + } @@ -497,138 +521,140 @@ cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) lavg_t *l = NULL; for (i = 0; i < FIELD_NUM_SIZE; i++) - fields[i] = 0; - - switch ( cmd[0] ) { + fields[i] = 0; + + switch (cmd[0]) { case CMD_DETAILS: - bit_set(fields, FIELD_SCHEDULE); - bit_set(fields, FIELD_RQ); - bit_set(fields, FIELD_USER); - bit_set(fields, FIELD_OPTIONS); - print_fields(fd, fields); - for ( j = queue_base; j != NULL; j = j->j_next ) { - if ( cmd[1] == j->j_line->cl_id ) { - if (strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 - || is_root ) - print_line(fd, j->j_line, fields, 0, 0, 0); - else - Send_err_msg(fd, err_job_nfound_str); - found = 1; - break; - } - } - break; + bit_set(fields, FIELD_SCHEDULE); + bit_set(fields, FIELD_RQ); + bit_set(fields, FIELD_USER); + bit_set(fields, FIELD_OPTIONS); + print_fields(fd, fields); + for (j = queue_base; j != NULL; j = j->j_next) { + if (cmd[1] == j->j_line->cl_id) { + if (strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 + || is_root) + print_line(fd, j->j_line, fields, 0, 0, 0); + else + Send_err_msg(fd, err_job_nfound_str); + found = 1; + break; + } + } + break; case CMD_LIST_JOBS: case CMD_LIST_LAVGQ: case CMD_LIST_SERIALQ: case CMD_LIST_EXEQ: - if ( cmd[0] == CMD_LIST_LAVGQ ) { - double lavg[3] = {0, 0, 0}; - char lavg_str[TERM_LEN]; - getloadavg(lavg, 3); - i = snprintf(lavg_str, sizeof(lavg_str), "Current load average : " - "%.1f, %.1f, %.1f\n", lavg[0], lavg[1], lavg[2]); - send(fd, lavg_str, i, 0); - - bit_set(fields, FIELD_LAVG); - } - else - bit_set(fields, FIELD_SCHEDULE); - - if ( cmd[0] == CMD_LIST_SERIALQ ) - bit_set(fields, FIELD_INDEX); - - if ( cmd[0] == CMD_LIST_EXEQ ) - bit_set(fields, FIELD_PID); - - if ( all && ! is_root) { - warn("User %s tried to list *all* jobs.", client->fcl_user); - Send_err_msg_end(fd, err_all_nallowed_str); - return; - } - if ( all ) - bit_set(fields, FIELD_USER); - print_fields(fd, fields); - - if (! all) { - struct passwd *pass; - + if (cmd[0] == CMD_LIST_LAVGQ) { + double lavg[3] = { 0, 0, 0 }; + char lavg_str[TERM_LEN]; + getloadavg(lavg, 3); + i = snprintf(lavg_str, sizeof(lavg_str), "Current load average : " + "%.1f, %.1f, %.1f\n", lavg[0], lavg[1], lavg[2]); + send(fd, lavg_str, i, 0); + + bit_set(fields, FIELD_LAVG); + } + else + bit_set(fields, FIELD_SCHEDULE); + + if (cmd[0] == CMD_LIST_SERIALQ) + bit_set(fields, FIELD_INDEX); + + if (cmd[0] == CMD_LIST_EXEQ) + bit_set(fields, FIELD_PID); + + if (all && !is_root) { + warn("User %s tried to list *all* jobs.", client->fcl_user); + Send_err_msg_end(fd, err_all_nallowed_str); + return; + } + if (all) + bit_set(fields, FIELD_USER); + print_fields(fd, fields); + + if (!all) { + struct passwd *pass; + #ifdef SYSFCRONTAB - if ( cmd[1] == SYSFCRONTAB_UID ) - user = SYSFCRONTAB; - else { + if (cmd[1] == SYSFCRONTAB_UID) + user = SYSFCRONTAB; + else { #endif - if ( (pass = getpwuid( (uid_t) cmd[1] )) == NULL ) { - warn_e("Unable to find passwd entry for %ld", cmd[1]); - Send_err_msg_end(fd, err_invalid_user_str); - return; - } - if ( ! is_root && strcmp(pass->pw_name, client->fcl_user) != 0 ) { - warn_e("%s is not allowed to see %s's jobs. %ld", client->fcl_user, - pass->pw_name); - Send_err_msg_end(fd, err_others_nallowed_str); - return; - } - user = pass->pw_name; + if ((pass = getpwuid((uid_t) cmd[1])) == NULL) { + warn_e("Unable to find passwd entry for %ld", cmd[1]); + Send_err_msg_end(fd, err_invalid_user_str); + return; + } + if (!is_root && strcmp(pass->pw_name, client->fcl_user) != 0) { + warn_e("%s is not allowed to see %s's jobs. %ld", + client->fcl_user, pass->pw_name); + Send_err_msg_end(fd, err_others_nallowed_str); + return; + } + user = pass->pw_name; #ifdef SYSFCRONTAB - } + } #endif - } - - /* list all jobs one by one and find the corresponding ones */ - switch ( cmd[0] ) { - case CMD_LIST_JOBS: - for ( j = queue_base; j != NULL; j = j->j_next ) - Test_line(j->j_line, 0, 0, 0); - break; - - case CMD_LIST_EXEQ: - for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) { - if ( e->e_line == NULL ) { - if ( is_root ) { - send_msg_fd(fd, "job no more in an fcrontab: pid %d", - e->e_job_pid); - found = 1; - } - } - else { - Test_line(e->e_line, e->e_job_pid, 0, 0); + } + + /* list all jobs one by one and find the corresponding ones */ + switch (cmd[0]) { + case CMD_LIST_JOBS: + for (j = queue_base; j != NULL; j = j->j_next) + Test_line(j->j_line, 0, 0, 0); + break; + + case CMD_LIST_EXEQ: + for (e = exe_list_first(exe_list); e != NULL; + e = exe_list_next(exe_list)) { + if (e->e_line == NULL) { + if (is_root) { + send_msg_fd(fd, "job no more in an fcrontab: pid %d", + e->e_job_pid); + found = 1; + } + } + else { + Test_line(e->e_line, e->e_job_pid, 0, 0); } - } - break; - - case CMD_LIST_LAVGQ: - for (l=lavg_list_first(lavg_list); l!=NULL; l=lavg_list_next(lavg_list)) - Test_line(l->l_line, 0, 0, l->l_until); - break; - - case CMD_LIST_SERIALQ: - { - int j; - i = serial_array_index; - for ( j = 0; j < serial_num; j++ ) { - Test_line(serial_array[i], 0, j, 0); - if ( ++i >= serial_array_size ) - i -= serial_array_size; - } - break; - } - - } - - break; - } - - if ( ! found ) - Send_err_msg(fd, err_job_nfound_str); + } + break; + + case CMD_LIST_LAVGQ: + for (l = lavg_list_first(lavg_list); l != NULL; + l = lavg_list_next(lavg_list)) + Test_line(l->l_line, 0, 0, l->l_until); + break; + + case CMD_LIST_SERIALQ: + { + int j; + i = serial_array_index; + for (j = 0; j < serial_num; j++) { + Test_line(serial_array[i], 0, j, 0); + if (++i >= serial_array_size) + i -= serial_array_size; + } + break; + } + + } + + break; + } + + if (!found) + Send_err_msg(fd, err_job_nfound_str); /* to tell fcrondyn there's no more data to wait */ Tell_no_more_data(fd); - + } -void +void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) /* common code to all cmds working on jobs in the exeq */ { @@ -638,125 +664,124 @@ cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) /* find the corresponding job */ for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) { - if ( e->e_line != NULL - && cmd[2] == e->e_line->cl_id ) { - - found = 1; - - /* check if the request is valid */ - if ( ! is_root && - strcmp(client->fcl_user, e->e_line->cl_file->cf_user) != 0 ) { - - if ( cmd[0] == CMD_RENICE ) - err_str = "%s tried to renice to %ld job id %ld for %s : " - "not allowed."; - else if (cmd[0] == CMD_SEND_SIGNAL) - err_str = "%s tried to send signal %ld to id %ld for %s : " - "not allowed."; - else - err_str = "cannot run unknown cmd with arg %ld on job id " - "%ld for %s : not allowed."; - - warn(err_str, client->fcl_user, cmd[1], cmd[2], - client->fcl_user); - Send_err_msg_end(fd, err_job_nfound_str); - } - else { - /* request is valid : do it */ - - if ( cmd[0] == CMD_SEND_SIGNAL ) - cmd_send_signal(client, cmd, fd, e); - else if ( cmd[0] == CMD_RENICE ) - cmd_renice(client, cmd, fd, e, is_root); - else { - Send_err_msg_end(fd, err_cmd_unknown_str); - exe_list_end_iteration(exe_list); - return; - } - } - } - } - - if ( ! found ) { - - if ( cmd[0] == CMD_RENICE ) - err_str = "cannot renice job id %ld for %s : no corresponding " - "running job."; - else if (cmd[0] == CMD_SEND_SIGNAL) - err_str = "cannot send signal to job id %ld for %s :" - " no corresponding running job."; - else - err_str = "cannot run unknown cmd on job id %ld for %s :" - " no corresponding running job."; - - warn(err_str, cmd[2], client->fcl_user); - Send_err_msg_end(fd, err_rjob_nfound_str); + if (e->e_line != NULL && cmd[2] == e->e_line->cl_id) { + + found = 1; + + /* check if the request is valid */ + if (!is_root && + strcmp(client->fcl_user, e->e_line->cl_file->cf_user) != 0) { + + if (cmd[0] == CMD_RENICE) + err_str = "%s tried to renice to %ld job id %ld for %s : " + "not allowed."; + else if (cmd[0] == CMD_SEND_SIGNAL) + err_str = "%s tried to send signal %ld to id %ld for %s : " + "not allowed."; + else + err_str = "cannot run unknown cmd with arg %ld on job id " + "%ld for %s : not allowed."; + + warn(err_str, client->fcl_user, cmd[1], cmd[2], + client->fcl_user); + Send_err_msg_end(fd, err_job_nfound_str); + } + else { + /* request is valid : do it */ + + if (cmd[0] == CMD_SEND_SIGNAL) + cmd_send_signal(client, cmd, fd, e); + else if (cmd[0] == CMD_RENICE) + cmd_renice(client, cmd, fd, e, is_root); + else { + Send_err_msg_end(fd, err_cmd_unknown_str); + exe_list_end_iteration(exe_list); + return; + } + } + } + } + + if (!found) { + + if (cmd[0] == CMD_RENICE) + err_str = "cannot renice job id %ld for %s : no corresponding " + "running job."; + else if (cmd[0] == CMD_SEND_SIGNAL) + err_str = "cannot send signal to job id %ld for %s :" + " no corresponding running job."; + else + err_str = "cannot run unknown cmd on job id %ld for %s :" + " no corresponding running job."; + + warn(err_str, cmd[2], client->fcl_user); + Send_err_msg_end(fd, err_rjob_nfound_str); } else { - Tell_no_more_data(fd); + Tell_no_more_data(fd); } - + } -void -cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e, int is_root) +void +cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t * e, + int is_root) /* change nice value of a running job */ { #ifdef HAVE_SETPRIORITY /* check if arguments are valid */ - if ( e->e_job_pid <= 0 || ((int)cmd[1] < 0 && ! is_root) - || (int)cmd[1] > 20 || (int)cmd[1] < -20 ) { - warn("renice: invalid args : pid: %d nice_value: %d user: %s.", - e->e_job_pid, (int)cmd[1], client->fcl_user); - Send_err_msg_end(fd, err_invalid_args_str); - return; + if (e->e_job_pid <= 0 || ((int)cmd[1] < 0 && !is_root) + || (int)cmd[1] > 20 || (int)cmd[1] < -20) { + warn("renice: invalid args : pid: %d nice_value: %d user: %s.", + e->e_job_pid, (int)cmd[1], client->fcl_user); + Send_err_msg_end(fd, err_invalid_args_str); + return; } /* ok, now setpriority() the job */ - if ( setpriority(PRIO_PROCESS, e->e_job_pid, (int)cmd[1]) != 0) { - error_e("could not setpriority(PRIO_PROCESS, %d, %d)", - e->e_job_pid, (int)cmd[1]); - Send_err_msg_end(fd, err_unknown_str); - return; + if (setpriority(PRIO_PROCESS, e->e_job_pid, (int)cmd[1]) != 0) { + error_e("could not setpriority(PRIO_PROCESS, %d, %d)", + e->e_job_pid, (int)cmd[1]); + Send_err_msg_end(fd, err_unknown_str); + return; } else { - send_msg_fd(fd, "Command successfully completed on process %d.", - e->e_job_pid); - return; + send_msg_fd(fd, "Command successfully completed on process %d.", + e->e_job_pid); + return; } -#else /* HAVE_SETPRIORITY */ - warn("System has no setpriority() : cannot renice. pid: %d nice_value: %d user: %s.", - e->e_job_pid, (int)cmd[1], client->fcl_user); - Send_err_msg_end(fd, err_cmd_unknown_str); +#else /* HAVE_SETPRIORITY */ + warn("System has no setpriority() : cannot renice. pid: %d nice_value: %d user: %s.", e->e_job_pid, (int)cmd[1], client->fcl_user); + Send_err_msg_end(fd, err_cmd_unknown_str); -#endif /* HAVE_SETPRIORITY */ +#endif /* HAVE_SETPRIORITY */ } void -cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e) +cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t * e) /* send a signal to a running job */ { - if ( e->e_job_pid <= 0 || (int)cmd[1] <= 0 ) { - warn("send_signal: invalid args : pid: %d signal: %d user: %s", - e->e_job_pid, (int)cmd[1], client->fcl_user); - Send_err_msg_end(fd, err_invalid_args_str); - return; + if (e->e_job_pid <= 0 || (int)cmd[1] <= 0) { + warn("send_signal: invalid args : pid: %d signal: %d user: %s", + e->e_job_pid, (int)cmd[1], client->fcl_user); + Send_err_msg_end(fd, err_invalid_args_str); + return; } /* ok, now kill() the job */ - if ( kill(e->e_job_pid, (int)cmd[1]) != 0) { - error_e("could not kill(%d, %d)", e->e_job_pid, (int)cmd[1]); - Send_err_msg_end(fd, err_unknown_str); - return; + if (kill(e->e_job_pid, (int)cmd[1]) != 0) { + error_e("could not kill(%d, %d)", e->e_job_pid, (int)cmd[1]); + Send_err_msg_end(fd, err_unknown_str); + return; } else { - send_msg_fd(fd, "Command successfully completed on process %d.", - e->e_job_pid); - return; + send_msg_fd(fd, "Command successfully completed on process %d.", + e->e_job_pid); + return; } } @@ -768,29 +793,29 @@ cmd_run(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) struct job_t *j = NULL; - for ( j = queue_base; j != NULL; j = j->j_next ) { - if ( cmd[1] == j->j_line->cl_id ) { - if (strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 - || is_root ) { + for (j = queue_base; j != NULL; j = j->j_next) { + if (cmd[1] == j->j_line->cl_id) { + if (strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 + || is_root) { - if ( is_lavg(j->j_line->cl_option) ) - add_lavg_job(j->j_line, fd); - else if ( is_serial(j->j_line->cl_option) ) - add_serial_job(j->j_line, fd); - else - run_normal_job(j->j_line, fd); + if (is_lavg(j->j_line->cl_option)) + add_lavg_job(j->j_line, fd); + else if (is_serial(j->j_line->cl_option)) + add_serial_job(j->j_line, fd); + else + run_normal_job(j->j_line, fd); - if ( cmd[0] == CMD_RUNNOW ) - set_next_exe(j->j_line, FROM_CUR_NEXTEXE, fd); + if (cmd[0] == CMD_RUNNOW) + set_next_exe(j->j_line, FROM_CUR_NEXTEXE, fd); - Tell_no_more_data(fd); + Tell_no_more_data(fd); - return; + return; - } - } + } + } } - + /* we don't come here if a job has been found */ Send_err_msg_end(fd, err_job_nfound_str); @@ -813,33 +838,33 @@ exe_cmd(struct fcrondyn_cl *client) /* */ debug("exe_cmd [0,1,2] : %d %d %d", cmd[0], cmd[1], cmd[2]); /* */ - - switch ( cmd[0] ) { + + switch (cmd[0]) { case CMD_SEND_SIGNAL: case CMD_RENICE: - cmd_on_exeq(client, cmd, fd, is_root); - break; + cmd_on_exeq(client, cmd, fd, is_root); + break; case CMD_DETAILS: case CMD_LIST_JOBS: case CMD_LIST_LAVGQ: case CMD_LIST_SERIALQ: case CMD_LIST_EXEQ: - cmd_ls(client, cmd, fd, is_root); - break; + cmd_ls(client, cmd, fd, is_root); + break; case CMD_RUN: case CMD_RUNNOW: - cmd_run(client, cmd, fd, is_root); - break; + cmd_run(client, cmd, fd, is_root); + break; default: - Send_err_msg_end(fd, err_cmd_unknown_str); + Send_err_msg_end(fd, err_cmd_unknown_str); } } -void +void remove_connection(struct fcrondyn_cl **client, struct fcrondyn_cl *prev_client) /* close the connection, remove it from the list and make client points to the next entry */ @@ -848,17 +873,17 @@ and make client points to the next entry */ close((*client)->fcl_sock_fd); remove_from_select_set((*client)->fcl_sock_fd, &master_set, &set_max_fd); debug("connection closed : fd : %d", (*client)->fcl_sock_fd); - if (prev_client == NULL ) { - fcrondyn_cl_base = (*client)->fcl_next; - Free_safe((*client)->fcl_user); - Free_safe(*client); - *client = fcrondyn_cl_base; + if (prev_client == NULL) { + fcrondyn_cl_base = (*client)->fcl_next; + Free_safe((*client)->fcl_user); + Free_safe(*client); + *client = fcrondyn_cl_base; } else { - prev_client->fcl_next = (*client)->fcl_next; - Free_safe((*client)->fcl_user); - Free_safe(*client); - *client = prev_client->fcl_next; + prev_client->fcl_next = (*client)->fcl_next; + Free_safe((*client)->fcl_user); + Free_safe(*client); + *client = prev_client->fcl_next; } fcrondyn_cl_num -= 1; } @@ -874,105 +899,111 @@ check_socket(int num) int read_len = 0; struct fcrondyn_cl *client = NULL, *prev_client = NULL; - if ( num <= 0 ) - /* no socket to check : go directly to the end of that function */ - goto final_settings; + if (num <= 0) + /* no socket to check : go directly to the end of that function */ + goto final_settings; debug("Checking socket ..."); - if ( FD_ISSET(listen_fd, &read_set) ) { - debug("got new connection ..."); - fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_len); - if ( fd == -1 ) { - error_e("could not accept new connection : isset(listen_fd = %d) = %d", - listen_fd, FD_ISSET(listen_fd, &read_set)); - } - else { - fcntl(fd, F_SETFD, 1); - /* set fd to O_NONBLOCK : we do not want fcron to be stopped on error, etc */ - if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { - error_e("Could not set fd attribute O_NONBLOCK : connection rejected."); - shutdown(fd, SHUT_RDWR); - close(fd); - } - else { - Alloc(client, fcrondyn_cl); - client->fcl_sock_fd = fd; - /* means : not authenticated yet : */ - client->fcl_user = NULL; - client->fcl_cmd = NULL; - - /* include new entry in client list */ - client->fcl_next = fcrondyn_cl_base; - fcrondyn_cl_base = client; - client->fcl_idle_since = now; - /* to avoid trying to read from it in this call */ - avoid_fd = fd; - - add_to_select_set(fd, &master_set, &set_max_fd); - fcrondyn_cl_num += 1; - - debug("Added connection fd : %d - %d connections", fd, fcrondyn_cl_num); + if (FD_ISSET(listen_fd, &read_set)) { + debug("got new connection ..."); + fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_len); + if (fd == -1) { + error_e + ("could not accept new connection : isset(listen_fd = %d) = %d", + listen_fd, FD_ISSET(listen_fd, &read_set)); + } + else { + fcntl(fd, F_SETFD, 1); + /* set fd to O_NONBLOCK : we do not want fcron to be stopped on error, etc */ + if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { + error_e + ("Could not set fd attribute O_NONBLOCK : connection rejected."); + shutdown(fd, SHUT_RDWR); + close(fd); + } + else { + Alloc(client, fcrondyn_cl); + client->fcl_sock_fd = fd; + /* means : not authenticated yet : */ + client->fcl_user = NULL; + client->fcl_cmd = NULL; + + /* include new entry in client list */ + client->fcl_next = fcrondyn_cl_base; + fcrondyn_cl_base = client; + client->fcl_idle_since = now; + /* to avoid trying to read from it in this call */ + avoid_fd = fd; + + add_to_select_set(fd, &master_set, &set_max_fd); + fcrondyn_cl_num += 1; + + debug("Added connection fd : %d - %d connections", fd, + fcrondyn_cl_num); #ifdef SO_PEERCRED - auth_client_so_peercred(client); + auth_client_so_peercred(client); #elif defined(HAVE_GETPEERUCRED) || defined(HAVE_GETPEEREID) - auth_client_getpeer(client); -#endif /* SO_PEERCRED */ - } - } + auth_client_getpeer(client); +#endif /* SO_PEERCRED */ + } + } } client = fcrondyn_cl_base; - while ( client != NULL ) { - if (! FD_ISSET(client->fcl_sock_fd, &read_set) || client->fcl_sock_fd==avoid_fd){ - /* check if the connection has not been idle for too long ... */ - if (client->fcl_user==NULL && now - client->fcl_idle_since > MAX_AUTH_TIME ){ - warn("Connection with no auth for more than %ds : closing it.", - MAX_AUTH_TIME); - remove_connection(&client, prev_client); - } - else if ( now - client->fcl_idle_since > MAX_IDLE_TIME ) { - warn("Connection of %s is idle for more than %ds : closing it.", - client->fcl_user, MAX_IDLE_TIME); - remove_connection(&client, prev_client); - } - else { - /* nothing to do on this one ... check the next one */ - prev_client = client; - client = client->fcl_next; - } - continue; - } - - if ( (read_len = recv(client->fcl_sock_fd, buf_int, sizeof(buf_int), 0)) <= 0 ) { - if (read_len == 0) { - /* connection closed by client */ - remove_connection(&client, prev_client); - } - else { - error_e("error recv() from sock fd %d", client->fcl_sock_fd); - prev_client = client; - client = client->fcl_next; - } - } - else { - client->fcl_cmd_len = read_len; - client->fcl_cmd = buf_int; - if ( client->fcl_user == NULL ) - /* not authenticated yet */ - auth_client_password(client); - else { - /* we've just read a command ... */ - client->fcl_idle_since = now; - exe_cmd(client); - } - prev_client = client; - client = client->fcl_next; - } - } - - final_settings: + while (client != NULL) { + if (!FD_ISSET(client->fcl_sock_fd, &read_set) + || client->fcl_sock_fd == avoid_fd) { + /* check if the connection has not been idle for too long ... */ + if (client->fcl_user == NULL + && now - client->fcl_idle_since > MAX_AUTH_TIME) { + warn("Connection with no auth for more than %ds : closing it.", + MAX_AUTH_TIME); + remove_connection(&client, prev_client); + } + else if (now - client->fcl_idle_since > MAX_IDLE_TIME) { + warn("Connection of %s is idle for more than %ds : closing it.", + client->fcl_user, MAX_IDLE_TIME); + remove_connection(&client, prev_client); + } + else { + /* nothing to do on this one ... check the next one */ + prev_client = client; + client = client->fcl_next; + } + continue; + } + + if ((read_len = + recv(client->fcl_sock_fd, buf_int, sizeof(buf_int), 0)) <= 0) { + if (read_len == 0) { + /* connection closed by client */ + remove_connection(&client, prev_client); + } + else { + error_e("error recv() from sock fd %d", client->fcl_sock_fd); + prev_client = client; + client = client->fcl_next; + } + } + else { + client->fcl_cmd_len = read_len; + client->fcl_cmd = buf_int; + if (client->fcl_user == NULL) + /* not authenticated yet */ + auth_client_password(client); + else { + /* we've just read a command ... */ + client->fcl_idle_since = now; + exe_cmd(client); + } + prev_client = client; + client = client->fcl_next; + } + } + + final_settings: /* copy master_set in read_set, because read_set is modified by select() */ read_set = master_set; } @@ -984,20 +1015,20 @@ close_socket(void) { struct fcrondyn_cl *client, *client_buf = NULL; - if ( listen_fd ) { - shutdown(listen_fd, SHUT_RDWR); - close(listen_fd); - unlink(fifofile); - - client = fcrondyn_cl_base; - while ( client != NULL ) { - shutdown(client->fcl_sock_fd, SHUT_RDWR); - close(client->fcl_sock_fd); - - client_buf = client->fcl_next; - Free_safe(client); - fcrondyn_cl_num -= 1; - client = client_buf; - } + if (listen_fd) { + shutdown(listen_fd, SHUT_RDWR); + close(listen_fd); + unlink(fifofile); + + client = fcrondyn_cl_base; + while (client != NULL) { + shutdown(client->fcl_sock_fd, SHUT_RDWR); + close(client->fcl_sock_fd); + + client_buf = client->fcl_next; + Free_safe(client); + fcrondyn_cl_num -= 1; + client = client_buf; + } } } diff --git a/socket.h b/socket.h index fcf5f03..504d895 100644 --- a/socket.h +++ b/socket.h @@ -55,4 +55,4 @@ typedef struct fcrondyn_cl { } fcrondyn_cl; -#endif /* __SOCKET_H__ */ +#endif /* __SOCKET_H__ */ diff --git a/subs.c b/subs.c index 25ce697..9936ce6 100644 --- a/subs.c +++ b/subs.c @@ -33,11 +33,11 @@ get_user_uid_safe(char *username) errno = 0; pass = getpwnam(username); - if ( pass == NULL ) { - die_e("Unable to get the uid of user %s (is user in passwd file?)", - username); + if (pass == NULL) { + die_e("Unable to get the uid of user %s (is user in passwd file?)", + username); } - + return pass->pw_uid; } @@ -50,10 +50,10 @@ get_group_gid_safe(char *groupname) errno = 0; grp = getgrnam(groupname); - if ( grp == NULL ) { - die_e("Unable to get the gid of group %s", groupname); + if (grp == NULL) { + die_e("Unable to get the gid of group %s", groupname); } - + return grp->gr_gid; } @@ -84,7 +84,7 @@ setegid_safe(gid_t egid) die_e("could not change egid to %d", egid); } -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ #ifdef USE_SETE_ID int @@ -102,7 +102,9 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) if (flags & O_CREAT) { va_start(ap, flags); - mode = (sizeof(mode_t) < sizeof(int)) ? va_arg(ap, int) : va_arg(ap, mode_t); + mode = + (sizeof(mode_t) < sizeof(int)) ? va_arg(ap, int) : va_arg(ap, + mode_t); va_end(ap); } @@ -120,18 +122,18 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) setegid_safe(orig_egid); /* if open() didn't fail make sure we opened a 'normal' file */ - if ( fd >= 0 ) { + if (fd >= 0) { - if ( fstat(fd, &s) < 0 ) { + if (fstat(fd, &s) < 0) { error_e("open_as_user(): could not fstat %s", pathname); - if ( close(fd) < 0 ) + if (close(fd) < 0) error_e("open_as_user: could not close() %s", pathname); fd = -1; } - if ( ! S_ISREG(s.st_mode) || s.st_nlink != 1 ) { + if (!S_ISREG(s.st_mode) || s.st_nlink != 1) { error_e("open_as_user(): file %s is not a regular file", pathname); - if ( close(fd) < 0 ) + if (close(fd) < 0) error_e("open_as_user: could not close() %s", pathname); errno = 0; fd = -1; @@ -143,7 +145,7 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) } -#else /* def USE_SETE_ID */ +#else /* def USE_SETE_ID */ int open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) @@ -160,7 +162,9 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) if (flags & O_CREAT) { va_start(ap, flags); - mode = (sizeof(mode_t) < sizeof(int)) ? va_arg(ap, int) : va_arg(ap, mode_t); + mode = + (sizeof(mode_t) < sizeof(int)) ? va_arg(ap, int) : va_arg(ap, + mode_t); va_end(ap); } @@ -169,18 +173,18 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) * There will always be a risk of race-condition between the test * and the open but that's the best we can realistically do * without seteuid()... */ - if ( stat(pathname, &s) == 0 ) { - if ( ! ( s.st_mode & S_IROTH - || ( s.st_uid == openuid && s.st_mode & S_IRUSR ) - || ( s.st_gid == opengid && s.st_mode & S_IRGRP ) ) ) { + if (stat(pathname, &s) == 0) { + if (! + (s.st_mode & S_IROTH || (s.st_uid == openuid && s.st_mode & S_IRUSR) + || (s.st_gid == opengid && s.st_mode & S_IRGRP))) { error("open_as_user(): file %s does not pass the security test: " - "uid=%d gid=%d mode=%lo openuid=%d opengid=%d", - pathname, s.st_uid, s.st_gid, s.st_mode, openuid, opengid); + "uid=%d gid=%d mode=%lo openuid=%d opengid=%d", + pathname, s.st_uid, s.st_gid, s.st_mode, openuid, opengid); errno = EACCES; return -1; } } - else if ( errno == ENOENT ) { + else if (errno == ENOENT) { /* the file doesn't exist so no risk to truncate the wrong file! */ ; } @@ -195,16 +199,16 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) else fd = open(pathname, flags); - if ( fd < 0 ) + if (fd < 0) /* we couldn't open the file */ return fd; /* if open() didn't fail make sure we opened a 'normal' file */ - if ( fstat(fd, &s) < 0 ) { + if (fstat(fd, &s) < 0) { error_e("open_as_user(): could not fstat %s", pathname); goto err; } - if ( ! S_ISREG(s.st_mode) || s.st_nlink != 1 ) { + if (!S_ISREG(s.st_mode) || s.st_nlink != 1) { error_e("open_as_user(): file %s is not a regular file", pathname); goto err; } @@ -213,12 +217,11 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) * is allowed to read that file * We do that again as a malicious user could have replaced the file * by another one (e.g. a link) between the stat() and the open() earlier */ - if ( ! ( s.st_mode & S_IROTH - || ( s.st_uid == openuid && s.st_mode & S_IRUSR ) - || ( s.st_gid == opengid && s.st_mode & S_IRGRP ) ) ) { + if (!(s.st_mode & S_IROTH || (s.st_uid == openuid && s.st_mode & S_IRUSR) + || (s.st_gid == opengid && s.st_mode & S_IRGRP))) { error("open_as_user(): file %s does not pass the security test: " - "uid=%d gid=%d mode=%lo openuid=%d opengid=%d", - pathname, s.st_uid, s.st_gid, s.st_mode, openuid, opengid); + "uid=%d gid=%d mode=%lo openuid=%d opengid=%d", + pathname, s.st_uid, s.st_gid, s.st_mode, openuid, opengid); errno = EACCES; goto err; } @@ -229,9 +232,10 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) * then we will end up changing the ownership even if the seteuid() * version of that function wouldn't have. That shouldn't break * anything though. */ - if ( (flags & O_CREAT) && fchown(fd, openuid, opengid) != 0) { - error_e("Could not fchown %s to uid:%d gid:%d", pathname, openuid, opengid); - if ( close(fd) < 0 ) + if ((flags & O_CREAT) && fchown(fd, openuid, opengid) != 0) { + error_e("Could not fchown %s to uid:%d gid:%d", pathname, openuid, + opengid); + if (close(fd) < 0) error_e("open_as_user: could not close() %s", pathname); return -1; } @@ -239,13 +243,13 @@ open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...) /* everything went ok: return the file descriptor */ return fd; -err: - if ( fd >= 0 && close(fd) < 0 ) + err: + if (fd >= 0 && close(fd) < 0) error_e("open_as_user: could not close() %s", pathname); return -1; } -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ int remove_as_user(const char *pathname, uid_t removeuid, gid_t removegid) @@ -258,20 +262,21 @@ remove_as_user(const char *pathname, uid_t removeuid, gid_t removegid) seteuid_safe(removeuid); setegid_safe(removegid); -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ rval = remove(pathname); #ifdef USE_SETE_ID seteuid_safe(orig_euid); setegid_safe(orig_egid); -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ return rval; } int -rename_as_user(const char *oldpath, const char *newpath, uid_t renameuid, gid_t renamegid) +rename_as_user(const char *oldpath, const char *newpath, uid_t renameuid, + gid_t renamegid) /* Become user and call rename(), then revert back to who we were */ { int rval = -1; @@ -281,14 +286,14 @@ rename_as_user(const char *oldpath, const char *newpath, uid_t renameuid, gid_t seteuid_safe(renameuid); setegid_safe(renamegid); -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ rval = rename(oldpath, newpath); #ifdef USE_SETE_ID seteuid_safe(orig_euid); setegid_safe(orig_egid); -#endif /* def USE_SETE_ID */ +#endif /* def USE_SETE_ID */ return rval; @@ -303,23 +308,25 @@ remove_blanks(char *str) /* scan forward to the null */ while (*c) - c++; + c++; /* scan backward to the first character that is not a space */ - do {c--;} - while (c >= str && isspace( (int) *c)); + do { + c--; + } + while (c >= str && isspace((int)*c)); /* if last char is a '\n', we remove it */ - if ( *c == '\n' ) - *c = '\0'; + if (*c == '\n') + *c = '\0'; else - /* one character beyond where we stopped above is where the null - * goes. */ - *++c = '\0'; + /* one character beyond where we stopped above is where the null + * goes. */ + *++c = '\0'; /* return the new length */ - return ( c - str ); - + return (c - str); + } int @@ -328,7 +335,6 @@ strcmp_until(const char *left, const char *right, char until) /* Copyright 1988,1990,1993,1994 by Paul Vixie */ /* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. */ - { while (*left != '\0' && *left != until && *left == *right) { left++; @@ -336,7 +342,7 @@ strcmp_until(const char *left, const char *right, char until) } if ((*left == '\0' || *left == until) - && (*right == '\0' || *right == until)) { + && (*right == '\0' || *right == until)) { return (0); } return (*left - *right); @@ -351,10 +357,10 @@ get_word(char **str) Skip_blanks(*str); ptr = *str; - while ( (isalnum( (int) *ptr) || *ptr == '_' || *ptr == '-') - && *ptr != '=' && ! isspace( (int) *ptr) ) - ptr++; - + while ((isalnum((int)*ptr) || *ptr == '_' || *ptr == '-') + && *ptr != '=' && !isspace((int)*ptr)) + ptr++; + return (ptr - *str); } @@ -365,13 +371,13 @@ my_unsetenv(const char *name) { #ifdef HAVE_UNSETENV - if ( unsetenv(name) < 0 ) + if (unsetenv(name) < 0) error_e("could not flush env var %s with unsetenv()", name); #else char buf[PATH_LEN]; snprintf(buf, sizeof(buf) - 1, "%s=", name); - buf[sizeof(buf)-1] = '\0'; - if ( putenv(buf) < 0 ) + buf[sizeof(buf) - 1] = '\0'; + if (putenv(buf) < 0) error_e("could not flush env var %s with putenv()", name); #endif @@ -382,7 +388,6 @@ my_setenv_overwrite(const char *name, const char *value) /* call setenv(x, x, 1) if available, otherwise call putenv() with the appropriate * constructed string. * Check for errors and log them. */ - { #ifdef HAVE_SETENV @@ -390,7 +395,7 @@ my_setenv_overwrite(const char *name, const char *value) /* // */ debug("Calling setenv(%s, %s, 1)", name, value); /* // */ - if ( setenv(name, value, 1) != 0 ) + if (setenv(name, value, 1) != 0) error_e("setenv(%s, %s, 1) failed", name, value); #else @@ -398,18 +403,16 @@ my_setenv_overwrite(const char *name, const char *value) snprintf(buf, sizeof(buf) - 1, "%s=%s", name, value) - /* The final \0 may not have been copied because of lack of space: - * add it to make sure */ - buf[sizeof(buf)-1]='\0'; + /* The final \0 may not have been copied because of lack of space: + * add it to make sure */ + buf[sizeof(buf) - 1] = '\0'; /* // */ debug("Calling putenv(%s)", buf); /* // */ - if ( putenv(buf) != 0 ) + if (putenv(buf) != 0) error_e("putenv(%s) failed", buf); #endif } - - diff --git a/subs.h b/subs.h index 606a4bf..3d53661 100644 --- a/subs.h +++ b/subs.h @@ -31,9 +31,12 @@ extern uid_t get_user_uid_safe(char *username); extern gid_t get_group_gid_safe(char *groupname); extern void seteuid_safe(uid_t euid); extern void setegid_safe(uid_t egid); -extern int remove_as_user(const char *pathname, uid_t removeuid, gid_t removegid); -extern int open_as_user(const char *pathname, uid_t openuid, gid_t opengid, int flags, ...); -extern int rename_as_user(const char *oldpath, const char *newpath, uid_t renameuid, gid_t renamegid); +extern int remove_as_user(const char *pathname, uid_t removeuid, + gid_t removegid); +extern int open_as_user(const char *pathname, uid_t openuid, gid_t opengid, + int flags, ...); +extern int rename_as_user(const char *oldpath, const char *newpath, + uid_t renameuid, gid_t renamegid); extern int remove_blanks(char *str); extern int strcmp_until(const char *left, const char *right, char until); @@ -41,4 +44,4 @@ extern int get_word(char **str); extern void my_unsetenv(const char *name); extern void my_setenv_overwrite(const char *name, const char *value); -#endif /* __SUBS_H__ */ +#endif /* __SUBS_H__ */ diff --git a/temp_file.c b/temp_file.c index 6994e72..3ff6a3c 100644 --- a/temp_file.c +++ b/temp_file.c @@ -40,12 +40,12 @@ temp_file(char **name) #ifdef HAVE_MKSTEMP char name_local[PATH_LEN] = ""; snprintf(name_local, sizeof(name_local), "%sfcr-XXXXXX", tmp_path); - if ( (fd = mkstemp(name_local)) == -1 ) - die_e("Can't find a unique temporary filename"); + if ((fd = mkstemp(name_local)) == -1) + die_e("Can't find a unique temporary filename"); /* we must set the file mode to 600 (some versions of mkstemp may set it * incorrectly) */ - if ( fchmod(fd, S_IWUSR | S_IRUSR) != 0 ) - die_e("Can't fchmod temp file"); + if (fchmod(fd, S_IWUSR | S_IRUSR) != 0) + die_e("Can't fchmod temp file"); #else const int max_retries = 50; char *name_local = NULL; @@ -53,28 +53,28 @@ temp_file(char **name) i = 0; do { - i++; - Set(name_local, tempnam(NULL, NULL)); - if ( name_local == NULL ) - die("Can't find a unique temporary filename"); - fd = open(name_local, O_RDWR|O_CREAT|O_EXCL|O_APPEND, S_IRUSR|S_IWUSR); - /* I'm not sure we actually need to be so persistent here */ + i++; + Set(name_local, tempnam(NULL, NULL)); + if (name_local == NULL) + die("Can't find a unique temporary filename"); + fd = open(name_local, O_RDWR | O_CREAT | O_EXCL | O_APPEND, + S_IRUSR | S_IWUSR); + /* I'm not sure we actually need to be so persistent here */ } while (fd == -1 && errno == EEXIST && i < max_retries); if (fd == -1) - die_e("Can't open temporary file"); + die_e("Can't open temporary file"); #endif - if ( name == NULL && unlink(name_local) != 0 ) - die_e("Can't unlink temporary file %s", name_local); + if (name == NULL && unlink(name_local) != 0) + die_e("Can't unlink temporary file %s", name_local); + + fcntl(fd, F_SETFD, 1); /* set close-on-exec flag */ - fcntl(fd, F_SETFD, 1); /* set close-on-exec flag */ - /* give the name of the temp file if necessary */ if (name != NULL) - *name = strdup2(name_local); + *name = strdup2(name_local); #ifndef HAVE_MKSTEMP free(name_local); #endif return fd; } - diff --git a/temp_file.h b/temp_file.h index 3ab12ee..dd587cd 100644 --- a/temp_file.h +++ b/temp_file.h @@ -28,4 +28,4 @@ /* functions prototypes */ extern int temp_file(char **name); -#endif /* __TEMP_FILE_H__ */ +#endif /* __TEMP_FILE_H__ */ diff --git a/u_list.c b/u_list.c index 2153657..bc70d6e 100644 --- a/u_list.c +++ b/u_list.c @@ -32,11 +32,11 @@ #include "u_list.h" /* private functions: */ -int u_list_resize_array(u_list_t *l); -u_list_entry_t *u_list_last(u_list_t *l); +int u_list_resize_array(u_list_t * l); +u_list_entry_t *u_list_last(u_list_t * l); u_list_t * -u_list_init(size_t entry_size, int init_size, int grow_size) +u_list_init(size_t entry_size, int init_size, int grow_size) /* Create a new unordered list * Returns the newly created unorderd list * Enough memory to hold init_size entries will initially be allocated, @@ -46,9 +46,9 @@ u_list_init(size_t entry_size, int init_size, int grow_size) u_list_t *l = NULL; /* sanity check */ - if ( entry_size < 1 || init_size < 1 || grow_size < 1 ) + if (entry_size < 1 || init_size < 1 || grow_size < 1) die("Invalid arguments for u_list_init(): entry_size=%d, init_size=%d, " - "grow_size=%d", entry_size, init_size, grow_size); + "grow_size=%d", entry_size, init_size, grow_size); /* Allocate the list structure: */ l = alloc_safe(sizeof(struct u_list_t), "new u_list_t"); @@ -59,17 +59,17 @@ u_list_init(size_t entry_size, int init_size, int grow_size) l->grow_size = grow_size; l->cur_entry = NULL; l->cur_removed = 0; - l->entries_array = alloc_safe(init_size*entry_size, "new u_list_t array"); + l->entries_array = alloc_safe(init_size * entry_size, "new u_list_t array"); return l; } u_list_t * -u_list_copy(u_list_t *list) +u_list_copy(u_list_t * list) { u_list_t *new_list = NULL; - if ( list == NULL ) + if (list == NULL) return NULL; new_list = alloc_safe(sizeof(struct u_list_t), "u_list_t copy"); @@ -77,8 +77,8 @@ u_list_copy(u_list_t *list) new_list->cur_entry = NULL; - new_list->entries_array = alloc_safe(list->array_size*list->entry_size, - "u_list_t copy (array)"); + new_list->entries_array = alloc_safe(list->array_size * list->entry_size, + "u_list_t copy (array)"); memcpy(new_list->entries_array, list->entries_array, (list->array_size * list->entry_size)); @@ -87,7 +87,7 @@ u_list_copy(u_list_t *list) int -u_list_resize_array(u_list_t *l) +u_list_resize_array(u_list_t * l) /* Resize l's entries_array up to l->max_entries * Returns OK on success, ERR if the array is already at maximum size */ { @@ -95,63 +95,67 @@ u_list_resize_array(u_list_t *l) int old_size = l->array_size; /* sanity check */ - if ( l == NULL ) - die("Invalid argument for u_list_resize_array(): list=%d", l); - if ( l->max_entries > 0 && l->array_size >= l->max_entries ) { - debug("Resizing u_list_t failed because it is already at max size (size: %d)", - l->array_size); - return ERR; + if (l == NULL) + die("Invalid argument for u_list_resize_array(): list=%d", l); + if (l->max_entries > 0 && l->array_size >= l->max_entries) { + debug + ("Resizing u_list_t failed because it is already at max size (size: %d)", + l->array_size); + return ERR; } - if ( l->cur_entry != NULL ) - /* Compute cur_entry's offset so as we can set cur_entry to the right place - * after we have allocated a new chunk of memory for the entries_array */ - offset = (char *) l->cur_entry - (char *) l->entries_array; + if (l->cur_entry != NULL) + /* Compute cur_entry's offset so as we can set cur_entry to the right place + * after we have allocated a new chunk of memory for the entries_array */ + offset = (char *)l->cur_entry - (char *)l->entries_array; l->array_size = (l->array_size + l->grow_size); - if ( l->max_entries > 0 && l->array_size > l->max_entries ) - l->array_size = l->max_entries; + if (l->max_entries > 0 && l->array_size > l->max_entries) + l->array_size = l->max_entries; - debug("Resizing u_list_t (old size: %d, new size: %d)...", old_size, l->array_size); - - l->entries_array = realloc_safe(l->entries_array, (l->array_size * l->entry_size), "larger u_list_t array"); + debug("Resizing u_list_t (old size: %d, new size: %d)...", old_size, + l->array_size); + + l->entries_array = + realloc_safe(l->entries_array, (l->array_size * l->entry_size), + "larger u_list_t array"); /* allocate newly allocated memory */ - memset((char *) l->entries_array+(old_size * l->entry_size), '\0', - (l->array_size-old_size)*l->entry_size); + memset((char *)l->entries_array + (old_size * l->entry_size), '\0', + (l->array_size - old_size) * l->entry_size); - if ( l->cur_entry != NULL ) - l->cur_entry = (u_list_entry_t *) ( (char *) l->entries_array + offset ); + if (l->cur_entry != NULL) + l->cur_entry = (u_list_entry_t *) ((char *)l->entries_array + offset); return OK; } u_list_entry_t * -u_list_last(u_list_t *l) +u_list_last(u_list_t * l) /* Returns the pointer of the last entry in the list, or NULL if l is empty */ { - if ( l->num_entries <= 0 ) - return NULL; + if (l->num_entries <= 0) + return NULL; else - return (u_list_entry_t *) - ( (char *)l->entries_array + l->entry_size * ( l->num_entries - 1 ) ); + return (u_list_entry_t *) + ((char *)l->entries_array + l->entry_size * (l->num_entries - 1)); } -u_list_entry_t * -u_list_add(u_list_t *l, u_list_entry_t *e) +u_list_entry_t * +u_list_add(u_list_t * l, u_list_entry_t * e) /* Add one entry to the list * Returns a pointer to the added element, or NULL if list is already at max size */ { u_list_entry_t *new = NULL; /* sanity check */ - if ( l == NULL || e == NULL ) - die("Invalid arguments for u_list_add(): list=%d, entry=%d", l, e); + if (l == NULL || e == NULL) + die("Invalid arguments for u_list_add(): list=%d, entry=%d", l, e); /* Check there is some space left, or resize the array */ - if ( l->num_entries >= l->array_size ) { - /* no more space: attempt to grow (the following function dies on error: */ - if ( u_list_resize_array(l) != OK ) - return NULL; + if (l->num_entries >= l->array_size) { + /* no more space: attempt to grow (the following function dies on error: */ + if (u_list_resize_array(l) != OK) + return NULL; } l->num_entries++; @@ -162,66 +166,68 @@ u_list_add(u_list_t *l, u_list_entry_t *e) } int -u_list_is_iterating(u_list_t *l) +u_list_is_iterating(u_list_t * l) { /* sanity check */ - if ( l == NULL ) - die("Invalid argument for u_list_iterating(): list=%d", l); + if (l == NULL) + die("Invalid argument for u_list_iterating(): list=%d", l); - return ( l->cur_entry != NULL ); + return (l->cur_entry != NULL); } -u_list_entry_t * -u_list_first(u_list_t *l) +u_list_entry_t * +u_list_first(u_list_t * l) /* Return the first entry of the list (then u_list_next() can be used) */ { /* sanity check */ - if ( l == NULL ) - die("Invalid argument for u_list_first(): list=%d", l); - if ( l->cur_entry != NULL ) - die("u_list_first() called but there is already an iteration"); + if (l == NULL) + die("Invalid argument for u_list_first(): list=%d", l); + if (l->cur_entry != NULL) + die("u_list_first() called but there is already an iteration"); if (l->num_entries > 0) { - l->cur_entry = l->entries_array; + l->cur_entry = l->entries_array; } - + return l->cur_entry; } -u_list_entry_t * -u_list_next(u_list_t *l) +u_list_entry_t * +u_list_next(u_list_t * l) /* Return the entry after e */ { /* sanity checks */ - if ( l == NULL ) - die("Invalid arguments for u_list_next(): list=%d", l); - if ( l->cur_entry == NULL ) - die("u_list_next() called outside an iteration: l->cur_entry=%d", l->cur_entry); - - if ( l->cur_removed > 0 ) { - l->cur_removed = 0; - /* the current entry has just been removed and replaced by another one: - * we can return the same pointer again. - * However if the removed entry was the last one then we reached the end - * of the list */ - if ( l->cur_entry > u_list_last(l) ) - l->cur_entry = NULL; + if (l == NULL) + die("Invalid arguments for u_list_next(): list=%d", l); + if (l->cur_entry == NULL) + die("u_list_next() called outside an iteration: l->cur_entry=%d", + l->cur_entry); + + if (l->cur_removed > 0) { + l->cur_removed = 0; + /* the current entry has just been removed and replaced by another one: + * we can return the same pointer again. + * However if the removed entry was the last one then we reached the end + * of the list */ + if (l->cur_entry > u_list_last(l)) + l->cur_entry = NULL; } else { - /* cur_entry *not* removed (standard behavior) */ - - if ( l->cur_entry < u_list_last(l) ) - l->cur_entry = (u_list_entry_t *) ( (char *) l->cur_entry + l->entry_size); - else - /* reached the end of the list */ - l->cur_entry = NULL; + /* cur_entry *not* removed (standard behavior) */ + + if (l->cur_entry < u_list_last(l)) + l->cur_entry = + (u_list_entry_t *) ((char *)l->cur_entry + l->entry_size); + else + /* reached the end of the list */ + l->cur_entry = NULL; } return l->cur_entry; } void -u_list_end_iteration(u_list_t *list) +u_list_end_iteration(u_list_t * list) /* Stop an iteration before _next() reached the end of the list by itself */ { list->cur_entry = NULL; @@ -230,20 +236,20 @@ u_list_end_iteration(u_list_t *list) void -u_list_remove_cur(u_list_t *l) +u_list_remove_cur(u_list_t * l) { u_list_entry_t *last = NULL; /* sanity checks */ - if ( l == NULL ) - die("Invalid arguments for u_list_remove(): list=%d", l); - if ( l->cur_entry == NULL ) - die("u_list_remove_cur() called outside of an iteration"); + if (l == NULL) + die("Invalid arguments for u_list_remove(): list=%d", l); + if (l->cur_entry == NULL) + die("u_list_remove_cur() called outside of an iteration"); last = u_list_last(l); - if ( l->cur_entry < last ) { - /* Override e with the last entry */ - memcpy(l->cur_entry, last, l->entry_size); + if (l->cur_entry < last) { + /* Override e with the last entry */ + memcpy(l->cur_entry, last, l->entry_size); } /* erase the last entry and update the number of entries */ memset(last, 0, l->entry_size); @@ -253,11 +259,11 @@ u_list_remove_cur(u_list_t *l) } u_list_t * -u_list_destroy(u_list_t *list) +u_list_destroy(u_list_t * list) /* free() the memory allocated for list and returns NULL */ { - if ( list == NULL ) - die("Invalid argument for u_list_destroy(): list=%d", list); + if (list == NULL) + die("Invalid argument for u_list_destroy(): list=%d", list); Free_safe(list->entries_array); Free_safe(list); diff --git a/u_list.h b/u_list.h index 2d326d2..80ffe5b 100644 --- a/u_list.h +++ b/u_list.h @@ -38,33 +38,33 @@ typedef void u_list_entry_t; typedef struct u_list_t { /* PUBLIC: */ - int max_entries; /* max allowed element number (0: no limit) */ - int num_entries; /* READ ONLY: num of entries in the list now */ + int max_entries; /* max allowed element number (0: no limit) */ + int num_entries; /* READ ONLY: num of entries in the list now */ /* PRIVATE: DO NOT ACCESS DIRECTLY */ - int array_size; /* size of the array (in number of entries) */ - size_t entry_size; /* number of element currently in the array */ - int grow_size; /* grow array by grow_size entries at a time */ - u_list_entry_t *cur_entry; /* Current entry in iteration - * (null if not in iteration, i.e. X_first() has - * not been called or we reached the list end */ - char cur_removed; /* >0 if cur_entry has just been removed */ - u_list_entry_t *entries_array; /* pointer to the actual array */ + int array_size; /* size of the array (in number of entries) */ + size_t entry_size; /* number of element currently in the array */ + int grow_size; /* grow array by grow_size entries at a time */ + u_list_entry_t *cur_entry; /* Current entry in iteration + * (null if not in iteration, i.e. X_first() has + * not been called or we reached the list end */ + char cur_removed; /* >0 if cur_entry has just been removed */ + u_list_entry_t *entries_array; /* pointer to the actual array */ } u_list_t; /* functions prototypes */ extern u_list_t *u_list_init(size_t entry_size, int init_size, int grow_size); -extern u_list_t *u_list_copy(u_list_t *list); -extern u_list_entry_t *u_list_add(u_list_t *list, u_list_entry_t *entry); +extern u_list_t *u_list_copy(u_list_t * list); +extern u_list_entry_t *u_list_add(u_list_t * list, u_list_entry_t * entry); /* WARNING: - the iteration functions are not re-entrant, * i.e. there should always be a unique iteration loop based on * u_list_first()/u_list_next() running at any one time in the code * - the u_list_entry_t* returned by _first() and _next() should not * be used anymore after a _add() or a _remove_cur() */ -extern int u_list_is_iterating(u_list_t *list); -extern u_list_entry_t *u_list_first(u_list_t *list); -extern u_list_entry_t *u_list_next(u_list_t *list); -extern void u_list_end_iteration(u_list_t *list); -extern void u_list_remove_cur(u_list_t *list); -extern u_list_t *u_list_destroy(u_list_t *list); +extern int u_list_is_iterating(u_list_t * list); +extern u_list_entry_t *u_list_first(u_list_t * list); +extern u_list_entry_t *u_list_next(u_list_t * list); +extern void u_list_end_iteration(u_list_t * list); +extern void u_list_remove_cur(u_list_t * list); +extern u_list_t *u_list_destroy(u_list_t * list); -#endif /* __U_LIST_H__ */ +#endif /* __U_LIST_H__ */ -- 2.47.3