From: thib <thib>
Date: Sun, 18 Jun 2000 13:12:56 +0000 (+0000)
Subject: support of options
X-Git-Tag: ver1564~616
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43f3e1ed0d568f99ee0aef60a7d0ec55b38d923c;p=fcron

support of options
---

diff --git a/fileconf.c b/fileconf.c
index 500c56c..02de55d 100644
--- a/fileconf.c
+++ b/fileconf.c
@@ -22,22 +22,26 @@
  *  `LICENSE' that comes with the fcron source distribution.
  */
 
- /* $Id: fileconf.c,v 1.5 2000-06-15 20:17:46 thib Exp $ */
+ /* $Id: fileconf.c,v 1.6 2000-06-18 13:12:56 thib Exp $ */
 
 #include "fcrontab.h"
 
-int get_line(char *str, size_t size, FILE *file, int *line);
-char *get_time(char *ptr, time_t *time, int line, char *file_name);
-char *read_num(char *ptr, int *num, int max, const char **names);
-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, char *file_name);
 char *get_string(char *ptr);
+int get_line(char *str, size_t size, FILE *file);
+char *get_time(char *ptr, time_t *time);
+char *get_num(char *ptr, int *num, int max, const char **names);
+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 *cf);
+void read_arys(char *ptr, CF *cf);
+void read_env(char *ptr, CF *cf);
+char *read_opt(char *ptr, CL *cl);
 
 
 char need_correction;
+CL default_line;    /* default options for a line */
+char *file_name;
+int line;
 
 /* warning : all names must have the same length */
 const char *dows_ary[] = {
@@ -86,7 +90,7 @@ get_string(char *ptr)
 
 
 int
-get_line(char *str, size_t size, FILE *file, int *line)
+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 */
 {
@@ -101,9 +105,9 @@ get_line(char *str, size_t size, FILE *file, int *line)
 	    /* check if the \n char is preceded by a "\" char : 
 	     *  in this case, suppress the "\", don't copy the \n,
 	     *  and continue */
-	    if ( *(str + i - 1) == '\\') {
+	    if ( i > 0 && *(str + i - 1) == '\\') {
 		i--;
-		(*line)++;
+		line++;
 		continue;
 	    }
 	    else {
@@ -128,28 +132,30 @@ get_line(char *str, size_t size, FILE *file, int *line)
     /* line is too long : goto next line and return ERR */
     while ((*str = getc(file)) != '\n' && *str != EOF )
 	;
-    (*line)++;
+    line++;
     need_correction = 1;
     return ERR;
 
 }
 
 int
-read_file(char *file_name, char *user)
+read_file(char *filename, char *user)
     /* read file "name" and append CF list */
 {
     CF *cf = NULL;
     FILE *file = NULL;
     char buf[LINE_LEN];
     int max_lines;
-    int line = 1;
-    int max_entries = MAXLINES;
+    int max_entries = MAXENTRIES;
     int entries=0;
     char *ptr = NULL;
     int ret;
     
     bzero(buf, sizeof(buf));
+    bzero(&default_line, sizeof(CL));
     need_correction = 0;
+    line = 1;
+    file_name = filename;
 
     /* open file */
 
@@ -163,6 +169,7 @@ read_file(char *file_name, char *user)
     }
 
     Alloc(cf, CF);
+    default_line.cl_file = cf;
 
     if ( debug_opt )
 	fprintf(stderr, "FILE %s\n", file_name);
@@ -171,11 +178,11 @@ read_file(char *file_name, char *user)
 	max_entries = 65535;
 
     /* max_lines acts here as a security counter to avoid endless loop. */
-    max_lines = max_entries * 10;
+    max_lines = (max_entries * 10) + 10;
 
     while ( entries <= max_entries && line <= max_lines ) {
 
-	if ( (ret = get_line(buf, sizeof(buf), file, &line)) == OK)
+	if ( (ret = get_line(buf, sizeof(buf), file)) == OK)
 	    ;
 	else if ( ret == ERR ) {
 	    fprintf(stderr, "%s:%d: Line is too long (more than %d):"
@@ -188,6 +195,9 @@ read_file(char *file_name, char *user)
 	ptr = buf;
 	Skip_blanks(ptr);
 
+	if (debug_opt && *ptr != '#' && *ptr != '\0')
+	    fprintf(stderr, "      %s\n", buf);
+
 	switch(*ptr) {
 	case '#':
 	case '\0':
@@ -195,31 +205,42 @@ read_file(char *file_name, char *user)
 	    line++;
 	    continue;
 	case '@':
-	    if (debug_opt)
-		fprintf(stderr, "      %s\n", buf);
-	    read_freq(ptr, cf, line, file_name);
+	    read_freq(ptr, cf);
 	    entries++;
 	    break;
 	case '&':
-	    if (debug_opt)
-		fprintf(stderr, "      %s\n", buf);
-	    read_arys(ptr, cf, line, file_name);
+	    read_arys(ptr, cf);
 	    entries++;
 	    break;
+	case '!':
+	    ptr = read_opt(ptr, &default_line);
+	    if ( *ptr != '\0' ) {
+		fprintf(stderr, "%s:%d: Syntax error: string '%s' ignored\n",
+			file_name, line, ptr);
+		need_correction = 1;
+	    }
+	    break;
 	default:
 	    if ( isdigit(*ptr) || *ptr == '*' ) {
-		if (debug_opt)
-		    fprintf(stderr, "      %s\n", buf);
-		read_arys(ptr, cf, line, file_name);
+		read_arys(ptr, cf);
 		entries++;
 	    } else
-		read_env(ptr, cf, line, file_name);
+		read_env(ptr, cf);
 	}
 
 	line++;	
 
     }
 
+    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");
+    }
+    else if (line == max_lines)
+	error("%s:%d: maximum number of lines (%d) has been reached by %s",
+	      file_name, line, user);
+
     cf->cf_user = user;
     cf->cf_next = file_base;
     file_base = cf;
@@ -234,7 +255,7 @@ read_file(char *file_name, char *user)
 }
 
 void
-read_env(char *ptr, CF *cf, int line, char *file_name)
+read_env(char *ptr, CF *cf)
     /* append env variable list.
      * (remove blanks) */
 {
@@ -246,7 +267,7 @@ read_env(char *ptr, CF *cf, int line, char *file_name)
     bzero(name, sizeof(name));
 
     /* copy env variable's name */
-    while ( isalnum(*ptr) && *ptr != '=' && j < sizeof(name)) {
+    while (isalnum(*ptr) && *ptr != '=' && !isspace(*ptr) && j < sizeof(name)){
 	name[j++] = *ptr;
 	ptr++;
     }
@@ -263,6 +284,9 @@ read_env(char *ptr, CF *cf, int line, char *file_name)
     if ( *ptr++ != '=' || j == 0 )
 	goto error;
 
+    while ( isspace(*ptr) )
+	ptr++;
+
     /* get value */
     if ( ( val = get_string(ptr)) == NULL ) {
 	fprintf(stderr, "%s:%d: Mismatched  quotes: skipping line.\n",
@@ -282,9 +306,11 @@ read_env(char *ptr, CF *cf, int line, char *file_name)
 
     /* the MAILTO assignment is, in fact, an fcron option :
      *  we don't store it in the same way. */
-    if ( strcmp(name, "MAILTO") == 0 )
+    if ( strcmp(name, "MAILTO") == 0 ) {
+	if ( cf->cf_mailto != NULL )
+	    free(cf->cf_mailto);
 	cf->cf_mailto = val;
-    
+    }
     else {
 
 	Alloc(env, env_t);	
@@ -304,14 +330,157 @@ read_env(char *ptr, CF *cf, int line, char *file_name)
 
 }
 
+char *
+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;
+    }
+    else if ( strncmp(ptr, "false", 5) == 0 ) {
+	ptr += 4;
+	goto false;
+    }
+    else
+	return NULL;
+
+  true:
+    *i = 1;
+    ptr++;
+    return ptr;
+
+  false:
+    *i = 0;
+    ptr++;
+    return ptr;
+    
+}
+
+
+char *
+read_opt(char *ptr, CL *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 for option '%s' is not valid: " \
+		"skipping line.\n", file_name, line, opt_name); \
+        need_correction = 1; \
+        return NULL; \
+    }
+
+    if ( *ptr == '!' )
+	ptr++;
+
+    do { 
+	i = 0;
+	bzero(opt_name, sizeof(opt_name));
+
+	while ( isalnum(*ptr) )
+	    opt_name[i++] = *ptr++;
+    
+	i = 1;
+	in_brackets = 0;
+
+	if ( *ptr == '(' ) {
+	    in_brackets = 1;
+	    ptr++;
+	}
+
+	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, "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, "reset")==0 ) {
+	    if ( in_brackets && ((ptr = get_bool(ptr, &i)) == NULL || i == 0) )
+		Handle_err;
+	    bzero(cl, sizeof(cl));
+ 	    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_nextexe)))==NULL)
+		Handle_err;
+ 	    if (debug_opt)
+		fprintf(stderr, "  Opt : '%s' %ld\n",opt_name,cl->cl_nextexe);
+	}
+	else if(strcmp(opt_name, "r")==0 || strcmp(opt_name, "runfreq")==0) {
+	    if( ! in_brackets || (ptr=get_num(ptr, &i, 65534, NULL)) == NULL )
+		Handle_err;
+	    cl->cl_remain = i;
+ 	    if (debug_opt)
+		fprintf(stderr, "  Opt : '%s' %d\n", opt_name, i);
+	}
+	else if(strcmp(opt_name, "m")==0 || strcmp(opt_name, "mailto")==0) {
+	    char buf[50];
+	    bzero(buf, sizeof(buf));
+
+	    if( ! in_brackets )
+		Handle_err;
+
+	    i = 0;
+	    while ( isalnum(*ptr) )
+		buf[i++] = *ptr++;
+	    if ( cl->cl_file->cf_mailto != NULL )
+		free(cl->cl_file->cf_mailto);
+	    cl->cl_file->cf_mailto = strdup2(buf);
+ 	    if (debug_opt)
+		fprintf(stderr, "  Opt : '%s' '%s'\n", opt_name, buf);
+	}
+	else
+	    fprintf(stderr, "%s:%d: Option '%s' unknown: "
+		    "skipping option.\n", file_name, line, opt_name);  
+	
+	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 line, char *file_name )
+get_time(char *ptr, time_t *time)
     /* convert time read in string in time_t format */
 {
     time_t sum;
     
-    while( (*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0') ) { 
+    *time = 0 ;
+
+    while( (*ptr != ' ') && (*ptr != '\t') && (*ptr != '\0') &&
+	   (*ptr != ')') ) { 
 
 	sum = 0;
 
@@ -333,12 +502,14 @@ get_time(char *ptr, time_t *time, int line, char *file_name )
 	    sum *= 3600;
 	    ptr++;
 	    break;
-	default:                /* minutes */
-	    if ( (*ptr != ' ') && (*ptr != '\t') ) {
-		need_correction = 1;
-		return NULL;
-	    }
-	    
+	case ' ':
+	case '\t':
+	case ')':
+	    sum *= 60;          /* minutes */
+	    break;
+	default:
+	    need_correction = 1;
+	    return NULL;
 	}
 
 	*time += sum;
@@ -346,31 +517,47 @@ get_time(char *ptr, time_t *time, int line, char *file_name )
     }
 
     Skip_blanks(ptr);
-    return ptr;
+    if (*time == 0) {
+	need_correction = 1;
+	return NULL;
+    }
+    else
+	return ptr;
 }
 
 
 
 void
-read_freq(char *ptr, CF *cf, int line, char *file_name)
+read_freq(char *ptr, CF *cf)
     /* read a freq entry, and append a line to cf */
 {
-    CL *cl=NULL;
+    CL *cl = NULL;
     
     Alloc(cl, CL);
+    memcpy(cl, &default_line, sizeof(CL));
 
+    /* skip the @ */
     ptr++;
-    /* get the time before first execution */
-    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);
+    /* get the time before first execution or the options */
+    if ( isdigit(*ptr) ) {
+	if ( (ptr = get_time(ptr, &(cl->cl_nextexe))) == NULL ) {
+	    fprintf(stderr, "%s:%d: Error while reading first delay:"
+		    " skipping line.\n", file_name, line);
+	    return;
+	}
+	
+	Skip_blanks(ptr);
+    }
+    else if ( isalnum(*ptr) ) {
+	if ( (ptr = read_opt(ptr, cl)) == NULL )
+	    return;
+    }
+    else
+	Skip_blanks(ptr);
 
     /* then cl_timefreq */
-    if ( (ptr = get_time(ptr, &(cl->cl_timefreq), line, file_name)) == NULL) {
+    if ( (ptr = get_time(ptr, &(cl->cl_timefreq))) == NULL) {
 	fprintf(stderr, "%s:%d: Error while reading frequency:"
 		" skipping line.\n", file_name, line);
 	return;
@@ -410,7 +597,7 @@ read_freq(char *ptr, CF *cf, int line, char *file_name)
 
 
 #define R_field(ptr, ary, max, aryconst, descrp) \
-  if((ptr = read_field(ptr, ary, max, aryconst, line, file_name)) == NULL) { \
+  if((ptr = read_field(ptr, ary, max, aryconst)) == NULL) { \
       if (debug_opt) \
           fprintf(stderr, "\n"); \
       fprintf(stderr, "%s:%d: Error while reading " descrp " field: " \
@@ -420,32 +607,40 @@ read_freq(char *ptr, CF *cf, int line, char *file_name)
   }
 
 void
-read_arys(char *ptr, CF *cf, int line, char *file_name)
+read_arys(char *ptr, CF *cf)
     /* read a run freq number plus a normal fcron line */
 {
     CL *cl = NULL;
+    int i;
 
     Alloc(cl, CL);
+    memcpy(cl, &default_line, sizeof(CL));
 
 
     /* set cl_remain if not specified or 
      * if set to 1 to skip unnecessary tests */
     if ( *ptr != '&' )
 	/* cl_remain not specified : set it to 0 */
-	cl->cl_remain = 0;
+	i = 0;
     else {
 	ptr++;
-	/* get remain number */
-	while ( isdigit(*ptr) ) {	    
-	    cl->cl_remain *= 10;
-	    cl->cl_remain += *ptr - 48;
-	    ptr++;
+	if ( isdigit(*ptr) ) {
+	    if ( (ptr = get_num(ptr, &i, 65534, NULL)) == NULL ) {
+		fprintf(stderr, "%s:%d: Error while reading runfreq:"
+			" skipping line.\n", file_name, line);
+		free(cl);
+		return;
+	    }
 	}
+	else if ( isalnum(*ptr) )
+	    if ( (ptr = read_opt(ptr, cl)) == NULL )
+		return;
 
 	Skip_blanks(ptr);
+
     }
 
-    cl->cl_runfreq = cl->cl_remain;
+    cl->cl_runfreq = cl->cl_remain = i;
 
     if (debug_opt)
 	fprintf(stderr, "     ");
@@ -480,7 +675,7 @@ read_arys(char *ptr, CF *cf, int line, char *file_name)
 }
 
 char *
-read_num(char *ptr, int *num, int max, const char **names)
+get_num(char *ptr, int *num, int max, const char **names)
     /* read a string's number and return it under int format.
      *  Also check if that number is less than max */
 {
@@ -542,8 +737,7 @@ read_num(char *ptr, int *num, int max, const char **names)
 
 
 char *
-read_field(char *ptr, bitstr_t *ary, int max, const char **names,
-	   int line, char *file_name)
+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;
@@ -567,7 +761,7 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names,
 	    ptr++;
 	} else {
 
-	    if ( (ptr = read_num(ptr, &start, max, names)) == NULL )
+	    if ( (ptr = get_num(ptr, &start, max, names)) == NULL )
 		return NULL;
 
 	    if (*ptr == ',' || *ptr == ' ' || *ptr == '\t') {
@@ -581,7 +775,7 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names,
 	    /* check for a dash */
 	    else if ( *ptr == '-' ) {
 		ptr++;
-		if ( (ptr = read_num(ptr, &stop, max, names)) == NULL )
+		if ( (ptr = get_num(ptr, &stop, max, names)) == NULL )
 		    return NULL;
 	    } else {
 		/* syntax error */
@@ -593,7 +787,7 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names,
 	/* check for step size */
 	if ( *ptr == '/' ) {
 	    ptr++;
-	    if ((ptr = read_num(ptr, &step, max, names)) == NULL || step == 0)
+	    if ((ptr = get_num(ptr, &step, max, names)) == NULL || step == 0)
 		return NULL;
 	} else
 	    /* step undefined : default is 0 */
@@ -610,7 +804,7 @@ read_field(char *ptr, bitstr_t *ary, int max, const char **names,
 	while ( *ptr == '~' ) {
 	    ptr++;
 	    rm = 0;
-	    if ( (ptr = read_num(ptr, &rm, max, names)) == NULL )
+	    if ( (ptr = get_num(ptr, &rm, max, names)) == NULL )
 		return NULL;
 
 	    if (debug_opt)