From: Thibault Godouet Date: Thu, 15 Jun 2000 20:17:06 +0000 (+0000) Subject: bug fixes + ask user for corrections X-Git-Tag: ver2_9_4~700 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=810d63caa155e1863f332b52075ef8fa57711f94;p=thirdparty%2Ffcron.git bug fixes + ask user for corrections --- diff --git a/fcrontab.c b/fcrontab.c index 877f853..6ee65be 100644 --- a/fcrontab.c +++ b/fcrontab.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fcrontab.c,v 1.5 2000-06-11 20:30:37 thib Exp $ */ + /* $Id: fcrontab.c,v 1.6 2000-06-15 20:17:06 thib Exp $ */ /* * The goal of this program is simple : giving a user interface to fcron @@ -42,7 +42,7 @@ #include "fcrontab.h" -char rcs_info[] = "$Id: fcrontab.c,v 1.5 2000-06-11 20:30:37 thib Exp $"; +char rcs_info[] = "$Id: fcrontab.c,v 1.6 2000-06-15 20:17:06 thib Exp $"; void info(void); void usage(void); @@ -284,15 +284,11 @@ remove_fcrontab(char rm_orig) } + void -make_file(char *file, char *user) +write_file(char *file) { - explain("installing file '%s' for user %s", file, user); - - /* read file and create a list in memory */ - if ( read_file(file, user) != ERR ) { - if ( file_base->cf_line_base == NULL ) { /* no entries */ explain("%s's fcrontab contains no entries", user); @@ -315,14 +311,33 @@ make_file(char *file, char *user) } +} + +int +make_file(char *file) +{ + + explain("installing file '%s' for user %s", file, user); + + /* read file and create a list in memory */ + switch ( read_file(file, user) ) { + case 2: + case OK: + + write_file(file); + /* free memory used to store the list */ delete_file(user); /* tell daemon to update the conf */ need_sig = 1; + break; - } else - xexit(EXIT_ERR); + case ERR: + return ERR; + } + + return OK; } @@ -368,6 +383,7 @@ edit_file(char *buf) FILE *f, *fi; int file = 0; char c; + char correction = 0; explain("fcrontabs : editing %s's fcrontab", user); @@ -403,51 +419,89 @@ edit_file(char *buf) fclose(fi); close(file); - if ( stat(tmp, &st) == 0 ) - mtime = st.st_mtime; - else - die_e("could not stat '%s'", buf); + do { + + if ( stat(tmp, &st) == 0 ) + mtime = st.st_mtime; + else + die_e("could not stat '%s'", buf); - switch ( pid = fork() ) { - case 0: - /* child */ - if (setuid(getuid()) < 0) { - perror("setuid(getuid())"); + switch ( pid = fork() ) { + case 0: + /* child */ + if (setuid(getuid()) < 0) { + perror("setuid(getuid())"); + xexit(EXIT_ERR); + } + execlp(editor, editor, tmp, NULL); + perror(editor); xexit(EXIT_ERR); - } - execlp(editor, editor, tmp, NULL); - perror(editor); - xexit(EXIT_ERR); - case -1: - perror("fork"); - xexit(EXIT_ERR); + case -1: + perror("fork"); + xexit(EXIT_ERR); - default: - /* parent */ - break ; - } + default: + /* parent */ + break ; + } - /* only reached by parent */ - wait4(pid, &status, 0, NULL); - if ( ! WIFEXITED(status) ) { - fprintf(stderr, "Editor exited abnormally:" - " fcrontab is unchanged.\n"); - xexit(EXIT_ERR); - } + /* only reached by parent */ + wait4(pid, &status, 0, NULL); + if ( ! WIFEXITED(status) ) { + fprintf(stderr, "Editor exited abnormally:" + " fcrontab is unchanged.\n"); + xexit(EXIT_ERR); + } - /* check if file has been modified */ - if ( stat(tmp, &st) != 0 ) - die_e("could not stat %s", tmp); + /* check if file has been modified */ + if ( stat(tmp, &st) != 0 ) + die_e("could not stat %s", tmp); - else if ( st.st_mtime > mtime ) - make_file(tmp, user); + else if ( st.st_mtime > mtime || correction == 1) { + + correction = 0; + + switch ( read_file(tmp, user) ) { + case ERR: + if ( remove(tmp) != 0 ) + error("could not remove %s", tmp); + xexit (EXIT_ERR); + case 2: + fprintf(stderr, "\nFile contains some errors. " + "Ignore [i] or Correct [c] ? "); + /* the 2nd getchar() is for the newline char (\n) */ + while ( (c = getchar()) && getchar() && c != 'i' && c != 'c' ) + fprintf(stderr, "Please press c to correct, " + "or i to ignore: "); + if ( c == 'c' ) { + /* free memory used to store the list */ + delete_file(user); + correction = 1; + } + break; + default: + break; + } + + } + else { + fprintf(stderr, "Fcrontab is unchanged :" + " no need to install it.\n"); + xexit(EXIT_OK); + } - else - fprintf(stderr, "Fcrontab is unchanged :" - " no need to install it.\n"); + } while ( correction == 1); + write_file(tmp); + + /* free memory used to store the list */ + delete_file(user); + + /* tell daemon to update the conf */ + need_sig = 1; + if ( remove(tmp) != 0 ) error("could not remove %s", tmp); @@ -603,11 +657,14 @@ main(int argc, char **argv) if ( chown(tmp, getuid(), getgid()) != 0 ) die_e("could not chown %s", tmp); - make_file(tmp, user); - - remove(tmp); - - xexit ( EXIT_OK ); + if ( make_file(tmp) == ERR ) { + remove(tmp); + xexit ( EXIT_ERR ); + } + else { + remove(tmp); + xexit ( EXIT_OK ); + } } @@ -619,9 +676,10 @@ main(int argc, char **argv) else strncpy(file, argv[file_opt], sizeof(file)); - make_file(file, user); - - xexit ( EXIT_OK ); + if (make_file(file) == OK) + xexit ( EXIT_OK ); + else + xexit ( EXIT_ERR ); } @@ -639,7 +697,6 @@ main(int argc, char **argv) } - /* list user's entries */ if ( list_opt == 1 ) { @@ -650,7 +707,6 @@ main(int argc, char **argv) } - /* edit user's entries */ if ( edit_opt == 1 ) { diff --git a/fileconf.c b/fileconf.c index d384e7b..500c56c 100644 --- a/fileconf.c +++ b/fileconf.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fileconf.c,v 1.4 2000-06-10 22:16:44 thib Exp $ */ + /* $Id: fileconf.c,v 1.5 2000-06-15 20:17:46 thib Exp $ */ #include "fcrontab.h" @@ -33,10 +33,12 @@ void read_freq(char *ptr, CF *cf, int line, char *file_name); void read_arys(char *ptr, CF *cf, int line, char *file_name); char *read_field(char *ptr, bitstr_t *ary, int max, const char **names, int line, char *file_name); -void read_env(char *ptr, CF *cf, int line); +void read_env(char *ptr, CF *cf, int line, char *file_name); char *get_string(char *ptr); +char need_correction; + /* warning : all names must have the same length */ const char *dows_ary[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat", @@ -70,9 +72,11 @@ get_string(char *ptr) if ( quote != 0 ) { if ( *(ptr + length - 1) == quote ) *(ptr + length - 1) = '\0'; - else + else { /* mismatched quotes */ + need_correction = 1; return NULL; + } } @@ -125,6 +129,7 @@ get_line(char *str, size_t size, FILE *file, int *line) while ((*str = getc(file)) != '\n' && *str != EOF ) ; (*line)++; + need_correction = 1; return ERR; } @@ -144,6 +149,7 @@ read_file(char *file_name, char *user) int ret; bzero(buf, sizeof(buf)); + need_correction = 0; /* open file */ @@ -172,8 +178,8 @@ read_file(char *file_name, char *user) if ( (ret = get_line(buf, sizeof(buf), file, &line)) == OK) ; else if ( ret == ERR ) { - fprintf(stderr, "Line %d of %s is too long (more than %d):" - " skipping line.\n",line, file_name, sizeof(buf)); + fprintf(stderr, "%s:%d: Line is too long (more than %d):" + " skipping line.\n", file_name, line, sizeof(buf)); continue; } else /* EOF : no more lines */ @@ -207,7 +213,7 @@ read_file(char *file_name, char *user) read_arys(ptr, cf, line, file_name); entries++; } else - read_env(ptr, cf, line); + read_env(ptr, cf, line, file_name); } line++; @@ -220,12 +226,15 @@ read_file(char *file_name, char *user) fclose(file); - return OK; + if ( ! need_correction ) + return OK; + else + return 2; } void -read_env(char *ptr, CF *cf, int line) +read_env(char *ptr, CF *cf, int line, char *file_name) /* append env variable list. * (remove blanks) */ { @@ -243,14 +252,21 @@ read_env(char *ptr, CF *cf, int line) } name[j] = '\0'; + if ( name == '\0' ) + goto error; + /* skip '=' and spaces around */ - while ( isspace(*ptr) || *ptr == '=' ) + while ( isspace(*ptr) ) ptr++; + /* if j == 0 name is a zero length string */ + if ( *ptr++ != '=' || j == 0 ) + goto error; + /* get value */ if ( ( val = get_string(ptr)) == NULL ) { - fprintf(stderr, "Error at line %d (mismatched" - " quotes): skipping line.\n", line); + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); return; } @@ -258,8 +274,11 @@ read_env(char *ptr, CF *cf, int line) fprintf(stderr, " Env : '%s=%s'\n", name, val); /* we ignore USER's assignment */ - if ( strcmp(name, "USER") == 0 ) + if ( strcmp(name, "USER") == 0 ) { + fprintf(stderr, "%s:%d: USER 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. */ @@ -278,6 +297,11 @@ read_env(char *ptr, CF *cf, int line) return; + error: + fprintf(stderr, "%s:%d: Syntax error: skipping line.\n", + file_name, line); + return; + } @@ -306,10 +330,14 @@ get_time(char *ptr, time_t *time, int line, char *file_name ) case 'd': /* days */ sum *= 24; case 'h': /* hours */ - sum *= 60; + sum *= 3600; ptr++; + break; default: /* minutes */ - sum *= 60; + if ( (*ptr != ' ') && (*ptr != '\t') ) { + need_correction = 1; + return NULL; + } } @@ -333,15 +361,25 @@ read_freq(char *ptr, CF *cf, int line, char *file_name) ptr++; /* get the time before first execution */ - ptr = get_time(ptr, &(cl->cl_nextexe), line, file_name); + if ( (ptr = get_time(ptr, &(cl->cl_nextexe), line, file_name)) == NULL ) { + fprintf(stderr, "%s:%d: Error while reading first delay:" + " skipping line.\n", file_name, line); + return; + } Skip_blanks(ptr); /* then cl_timefreq */ - ptr = get_time(ptr, &(cl->cl_timefreq), line, file_name); + if ( (ptr = get_time(ptr, &(cl->cl_timefreq), line, file_name)) == NULL) { + fprintf(stderr, "%s:%d: Error while reading frequency:" + " skipping line.\n", file_name, line); + return; + } + if ( cl->cl_timefreq == 0) { - fprintf(stderr, "Error at line %d of file %s (no freq" - " specified): skipping line.\n", line, file_name); + fprintf(stderr, "%s:%d: no freq specified: skipping line.\n", + file_name, line); + need_correction = 1; free(cl); return; } @@ -354,8 +392,8 @@ read_freq(char *ptr, CF *cf, int line, char *file_name) /* get cl_shell field ( remove trailing blanks ) */ if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "Error at line %d of file %s (mismatched" - " quotes): skipping line.\n", line, file_name); + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); free(cl); return; } @@ -375,8 +413,8 @@ read_freq(char *ptr, CF *cf, int line, char *file_name) if((ptr = read_field(ptr, ary, max, aryconst, line, file_name)) == NULL) { \ if (debug_opt) \ fprintf(stderr, "\n"); \ - fprintf(stderr, "Error while reading " descrp " field line %d" \ - " of file %s: ignoring line.\n", line, file_name); \ + fprintf(stderr, "%s:%d: Error while reading " descrp " field: " \ + "skipping line.\n", file_name, line); \ free(cl); \ return; \ } @@ -426,8 +464,8 @@ read_arys(char *ptr, CF *cf, int line, char *file_name) /* get the shell command (remove trailing blanks) */ if ( (cl->cl_shell = get_string(ptr)) == NULL ) { - fprintf(stderr, "Error at line %d of file %s (mismatched" - " quotes): skipping line.\n", line, file_name); + fprintf(stderr, "%s:%d: Mismatched quotes: skipping line.\n", + file_name, line); free(cl); return; } @@ -451,8 +489,10 @@ read_num(char *ptr, int *num, int max, const char **names) if ( isalpha(*ptr) ) { int i; - if ( names == NULL ) + if ( names == NULL ) { + need_correction = 1; return NULL; + } /* set string to lower case */ for ( i = 0; i < strlen(names[0]); i++ ) @@ -467,6 +507,7 @@ read_num(char *ptr, int *num, int max, const char **names) } /* string is not in name list */ + need_correction = 1; return NULL; } else { @@ -479,8 +520,10 @@ read_num(char *ptr, int *num, int max, const char **names) *num *= 10; *num += *ptr - 48; - if (*num >= max) + if (*num >= max) { + need_correction = 1; return NULL; + } ptr++; @@ -540,10 +583,11 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names, ptr++; if ( (ptr = read_num(ptr, &stop, max, names)) == NULL ) return NULL; - } else + } else { /* syntax error */ + need_correction = 1; return NULL; - + } } /* check for step size */