]> git.ipfire.org Git - thirdparty/fcron.git/commitdiff
new save system : the binary format has changed, so it is no more necessary to reinst...
authorThibault Godouet <yo8192@users.noreply.github.com>
Sat, 21 Apr 2001 08:46:55 +0000 (08:46 +0000)
committerThibault Godouet <yo8192@users.noreply.github.com>
Sat, 21 Apr 2001 08:46:55 +0000 (08:46 +0000)
conf.c
fcron.h
fileconf.c

diff --git a/conf.c b/conf.c
index 2d9aa2864d09677365ac42092d436ae9c9b27647..d0652ae010264d491b7456f6d8ff03a69be14165 100644 (file)
--- a/conf.c
+++ b/conf.c
  *  `LICENSE' that comes with the fcron source distribution.
  */
 
- /* $Id: conf.c,v 1.40 2001-02-27 20:50:03 thib Exp $ */
+ /* $Id: conf.c,v 1.41 2001-04-21 08:48:14 thib Exp $ */
 
 #include "fcron.h"
 
 int read_file(const char *file_name, CF *cf);
-char *read_str(FILE *f, char *buf, int max);
+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);
 
 
@@ -229,7 +230,6 @@ synchronize_file(char *file_name)
            Alloc(cur_f, CF);
            if ( read_file(file_name, cur_f) != 0 ) {
                /* an error as occured */
-               free(cur_f);
                return;
            }
 
@@ -306,7 +306,6 @@ synchronize_file(char *file_name)
 
            if ( read_file(file_name, cur_f) != 0 ) {
                /* an error as occured */
-               free(cur_f);
                return;
            }
 
@@ -331,7 +330,6 @@ synchronize_file(char *file_name)
 
        if ( read_file(file_name, cur_f) != 0 ) {
            /* an error as occured */
-           free(cur_f);
            return;
        }
 
@@ -344,53 +342,71 @@ synchronize_file(char *file_name)
 }
 
 
-char *
-read_str(FILE *f, char *buf, int max)
-    /* return a pointer to string read from file f
-     * if it is non-zero length */
+int
+read_strn(int fd, char **str, short int size)
+/* read a "size"-length string in a binary fcrontab file */
 {
-    int i;
+    if ( (*str = calloc(size + 1, sizeof(char))) == NULL )
+       goto err;
+    
+    if ( read(fd, *str, size) < size )
+       goto err;
+    (*str)[size] = '\0';
+    return OK;
+
+  err:
+    if (*str)
+       free(*str);
+    *str = NULL;
+    return ERR;
+    
+}
 
-    for (i = 0; i < max; i++)
-       if ( (buf[i] = fgetc(f)) == '\0')
-           break;
-    buf[max-1] = '\0';
+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;
+    
+    return OK;
 
-    if ( strlen(buf) == 0 )
-       return NULL;
-    else
-       return strdup2(buf);
+  err:
+    return ERR;
 
 }
 
-
 int
 read_file(const char *file_name, CF *cf)
     /* read a formated fcrontab.
-       return 1 on error, 0 otherwise */
+       return ERR on error, OK otherwise */
 {
     FILE *ff = NULL;
     CL *cl = NULL;
     env_t *env = NULL;
     char buf[LINE_LEN];
+    long int bufi = 0;
     time_t t_save = 0;
     time_t slept = 0;
     uid_t runas = 0;
     char *runas_str = NULL;
     struct stat file_stat;
     struct passwd *pass = NULL;
+    short int type = 0, size = 0;
 
     /* open file */
     if ( (ff = fopen(file_name, "r")) == NULL ) {
        error_e("Could not read %s", file_name);
-       return 1;
+       goto err;
     }
 
     /* check if this file is owned by root : otherwise, all runas fields
      * of this field should be set to the owner */
     if ( fstat(fileno(ff), &file_stat) != 0 ) {
        error_e("Could not stat %s", file_name);
-       return 1;
+       goto err;
     }
 
     if ( strncmp(file_name,"new.", 4) == 0 ) {
@@ -403,7 +419,7 @@ read_file(const char *file_name, CF *cf)
            runas = file_stat.st_uid;
            if ( (pass = getpwuid(file_stat.st_uid)) == NULL ) {
                error_e("Could not getpwuid(%d)", file_stat.st_uid);
-               return 1;
+               goto err;
            }
            /* set cf_user field */
            runas_str = cf->cf_user = strdup2(pass->pw_name);
@@ -416,7 +432,7 @@ read_file(const char *file_name, CF *cf)
            runas = 0;
        else {
            error("Non-new file %s owned by someone else than root",file_name);
-           return 1;
+           goto err;
        }
     }
 
@@ -427,177 +443,358 @@ read_file(const char *file_name, CF *cf)
      * a file which he won't understand the syntax, for exemple
      * a file using a depreciated format generated by an old fcrontab,
      * if the syntax has changed */
-    if (fgets(buf, sizeof(buf), ff) == NULL ||
-       strncmp(buf, "fcrontab-"FILEVERSION"\n",
-               sizeof("fcrontab-"FILEVERSION"\n")) != 0) {
-
+    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("Maybe this file has been generated by an old version"
-             " of fcron. In this case, you should install it again"
-             " using fcrontab.");
-       return 1;
+       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 ( runas == 0 ) {
        /* get the owner's name */
-       if ((cf->cf_user = read_str(ff, buf, sizeof(buf))) == NULL) {
+       if ( read_strn(fileno(ff), &cf->cf_user, size) != OK ) {
            error("Cannot read user's name : file ignored");
-           return 1;
+           goto err;
        }
     } 
     else 
-       /* read the user name but ignore it */
-       read_str(ff, buf, sizeof(buf));
+       /* ignore the owner's name */
+       if ( fseek(ff, size, SEEK_CUR) < 0 ) {
+           error_e("Could not fseek file %s", file_name);
+           goto err;
+       }
 
     /* get the time & date of the saving */
     /* a new file generated by fcrontab has t_save set to 0 */
-    if ( fscanf(ff, "%ld", &t_save) != 1 )
+    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;
+    }
        
     slept = now - t_save;
 
 
-    /* read env variables */
-    Alloc(env, env_t);
-    while( (env->e_val = read_str(ff, buf, sizeof(buf))) != NULL ) {
-       debug("  Env: \"%s\"", env->e_val );
-       
-       env->e_next = cf->cf_env_base;
-       cf->cf_env_base = env;
-       Alloc(env, env_t);
-    }
-    /* free last alloc : unused */
-    free(env);
-       
-    /* read lines */
     Alloc(cl, CL);
-    while ( fread(cl, sizeof(CL), 1, ff) == 1 ) {
+    /* 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 ) {
+
+       case S_ENVVAR_T:
+           /* read a env variable and add it to the env var list */
+           Alloc(env, env_t);
+           if ( read_strn(fileno(ff), &env->e_val, size) == OK ) {
+               debug("  Env: \"%s\"", env->e_val );
+               env->e_next = cf->cf_env_base;
+               cf->cf_env_base = env;      
+           }
+           else {
+               error_e("Error while reading env var");
+               goto err;
+           }
+           break;
 
-       if ((cl->cl_shell = read_str(ff, buf, sizeof(buf))) == NULL) {
-           error("Line is not valid (empty shell command) : ignored");
-           continue;
-       }
-       if ((cl->cl_runas = read_str(ff, buf, sizeof(buf))) == NULL) {
-           error("Line is not valid (empty runas field) : ignored");
-           continue;
-       }
-       if ((cl->cl_mailto = read_str(ff, buf, sizeof(buf))) == NULL) {
-           error("Line is not valid (empty mailto field) : ignored");
-           continue;
-       }
+       case S_SHELL_T:
+           if ( read_strn(fileno(ff), &cl->cl_shell, size) != OK ) {
+               error_e("Error while reading shell field");
+               goto err;
+           }
+           break;
 
-       /* set runas field if necessary (to improve security) */
-       if (runas > 0) {
-           if (strcmp(cl->cl_runas, runas_str) != 0)
-               warn("warning: runas(%s) is not owner (%s): overridden.",
-                    cl->cl_runas, runas_str);
-           free(cl->cl_runas);
-           cl->cl_runas = strdup2(runas_str);
-       }
+       case S_RUNAS_T:
+           if ( read_strn(fileno(ff), &cl->cl_runas, size) != OK ) {
+               error_e("Error while reading runas field");
+               goto err;
+           }
+           break;
+
+       case S_MAILTO_T:
+           if ( read_strn(fileno(ff), &cl->cl_mailto, size) != OK ) {
+               error_e("Error while reading mailto field");
+               goto err;
+           }
+           break;
+
+       case S_NEXTEXE_T:
+           if ( read(fileno(ff), &bufi, size) < size ) {
+               error_e("Error while reading nextexe field");
+               goto err;
+           }
+           cl->cl_nextexe = (time_t) bufi;
+           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);
+           if ( read(fileno(ff), &(cl->cl_option), size) < size ) {
+               error_e("Error while reading option field");
+               goto err;
+           }
+           break;
+
+       case S_NUMEXE_T:
+           if ( read(fileno(ff), &(cl->cl_numexe), size) < size ) {
+               error_e("Error while reading numexe field");
+               goto err;
+           }
+           break;
+
+       case S_LAVG_T:
+           if ( read(fileno(ff), &(cl->cl_lavg), size) < size ) {
+               error_e("Error while reading lavg field");
+               goto err;
+           }
+           break;
+
+       case S_UNTIL_T:
+           if ( read(fileno(ff), &bufi, size) < size ) {
+               error_e("Error while reading until field");
+               goto err;
+           }
+           cl->cl_until = (time_t) bufi;
+           break;
 
-       /* we need that here because the user's name (contained in the
-        * struct CF may be required */
-       cl->cl_file = cf;
-
-       /* check if the task has not been stopped during execution and insert
-        * in lavg or serial queues the jobs which was in one at fcron's stops
-        */
-       if (cl->cl_numexe > 0) {
-           cl->cl_numexe = 0;
-           if ( ! is_strict(cl->cl_option) ) {
-               if ( is_lavg(cl->cl_option) )
-                   add_lavg_job(cl);
-               else if ( is_serial(cl->cl_option) 
-                         || is_serial_once(cl->cl_option) )
-                   add_serial_job(cl);
-               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);
+       case S_NICE_T:
+           if ( read(fileno(ff), &(cl->cl_nice), size) < size ) {
+               error_e("Error while reading nice field");
+               goto err;
+           }
+           break;
+
+       case S_RUNFREQ_T:
+           if ( read(fileno(ff), &bufi, size) < size ) {
+               error_e("Error while reading runfreq field");
+               goto err;
+           }
+           cl->cl_runfreq = (unsigned short) bufi;
+           break;
+
+       case S_REMAIN_T:
+           if ( read(fileno(ff), &bufi, size) < size ) {
+               error_e("Error while reading remain field");
+               goto err;
+           }
+           cl->cl_remain = (unsigned short) bufi;
+           break;
+
+       case S_TIMEFREQ_T:
+           if ( read(fileno(ff), &bufi, size) < size ) {
+               error_e("Error while reading timefreq field");
+               goto err;
+           }
+           cl->cl_timefreq = (time_t) bufi;
+           break;
+
+       case S_MINS_T:
+           if ( read(fileno(ff), &(cl->cl_mins), size) < size ) {
+               error_e("Error while reading mins field");
+               goto err;
+           }
+           break;
+
+       case S_HRS_T:
+           if ( read(fileno(ff), &(cl->cl_hrs), size) < size ) {
+               error_e("Error while reading hrs field");
+               goto err;
+           }
+           break;
+
+       case S_DAYS_T:
+           if ( read(fileno(ff), &(cl->cl_days), size) < size ) {
+               error_e("Error while reading days field");
+               goto err;
+           }
+           break;
+
+       case S_MONS_T:
+           if ( read(fileno(ff), &(cl->cl_mons), size) < size ) {
+               error_e("Error while reading mons field");
+               goto err;
+           }
+           break;
+
+       case S_DOW_T:
+           if ( read(fileno(ff), &(cl->cl_dow), size) < size ) {
+               error_e("Error while reading dow field");
+               goto err;
+           }
+           break;
+
+       case S_ENDLINE_T:
+           /* make checks on the current line to make sure it is usable */
+           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");
+               bzero(cl, sizeof(cl));
+               continue;
+           }
+
+           /* set runas field if necessary (to improve security) */
+           if (runas > 0) {
+               if (strcmp(cl->cl_runas, runas_str) != 0)
+                   warn("warning: runas(%s) is not owner (%s): overridden.",
+                        cl->cl_runas, runas_str);
+               free(cl->cl_runas);
+               cl->cl_runas = strdup2(runas_str);
+           }
+           
+           /* we need that here because the user's name (contained in the
+            * struct CF may be required */
+           cl->cl_file = cf;
+
+
+           /* check if the job hasn't been stopped during execution and insert
+            * it in lavg or serial queue if it was in one at fcron's stops  */
+           if (cl->cl_numexe > 0) {
+               cl->cl_numexe = 0;
+               if ( ! is_strict(cl->cl_option) ) {
+                   if ( is_lavg(cl->cl_option) )
+                       add_lavg_job(cl);
+                   else if ( is_serial(cl->cl_option) 
+                             || is_serial_once(cl->cl_option) )
+                       add_serial_job(cl);
+                   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);
+                   }
                }
            }
-       }
 
-       if ( is_td(cl->cl_option) ) {
+           if ( is_td(cl->cl_option) ) {
     
-           /* set the time and date of the next execution  */
-           if ( cl->cl_nextexe <= now ) {
-               if ( cl->cl_nextexe == 0 )
-                   /* the is a line from a new file */
-                   set_next_exe(cl, NO_GOTO);              
-               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);
+               /* set the time and date of the next execution  */
+               if ( cl->cl_nextexe <= now ) {
+                   if ( cl->cl_nextexe == 0 )
+                       /* the is a line from a new file */
+                       set_next_exe(cl, NO_GOTO);                  
+                   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);
+                           }
+                           else
+                               add_lavg_job(cl);                           
+                       }
+                       set_next_exe(cl, STD);
                    }
                    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);
-                       }
+                       if ( is_notice_notrun(cl->cl_option) ) {
+                           /* set next exe and mail user */
+                           struct tm *since2 = localtime(&cl->cl_nextexe);
+                           struct tm since;
+                           memcpy(&since, since2, sizeof(since));
+                           set_next_exe(cl, NO_GOTO);
+                           mail_notrun(cl, SYSDOWN, &since);
+                       } 
                        else
-                           add_lavg_job(cl);                       
+                           set_next_exe(cl, NO_GOTO);
                    }
-                   set_next_exe(cl, STD);
                }
-               else {
-                   if ( is_notice_notrun(cl->cl_option) ) {
-                       /* set next exe and mail user */
-                       struct tm *since2 = localtime(&cl->cl_nextexe), since;
-                       memcpy(&since, since2, sizeof(since));
-                       set_next_exe(cl, NO_GOTO);
-                       mail_notrun(cl, SYSDOWN, &since);
-                   } 
-                   else
-                       set_next_exe(cl, NO_GOTO);
+               else
+                   /* value of nextexe is valid : just insert line in queue */
+                   insert_nextexe(cl);
+           } else {  /* is_td(cl->cl_option) */
+               /* standard @-lines */
+               if ( cl->cl_timefreq < 60 ) {
+                   error("Invalid timefreq for %s: set to 1 day",
+                         cl->cl_shell);
+                   cl->cl_timefreq = 3600*24;
                }
-           }
-           else
-               /* value of nextexe is valid : just insert line in queue */
+               cl->cl_nextexe += slept;
                insert_nextexe(cl);
-       } else {  /* is_td(cl->cl_option) */
-           /* standard @-lines */
-           if ( cl->cl_timefreq < 60 ) {
-               error("Invalid timefreq for %s: set to 1 day", cl->cl_shell);
-               cl->cl_timefreq = 3600*24;
-           }
-           cl->cl_nextexe += slept;
-           insert_nextexe(cl);
-       }           
-
-       if (debug_opt) {
-           struct tm *ftime;
-           ftime = localtime( &(cl->cl_nextexe) );
-           debug("  cmd %s next exec %d/%d/%d wday:%d %02d:%02d",
-                 cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday,
-                 (ftime->tm_year + 1900), ftime->tm_wday,
-                 ftime->tm_hour, ftime->tm_min); 
-       } 
-       
+           }       
+
+           if (debug_opt) {
+               struct tm *ftime;
+               ftime = localtime( &(cl->cl_nextexe) );
+               debug("  cmd %s next exec %d/%d/%d wday:%d %02d:%02d",
+                     cl->cl_shell, (ftime->tm_mon + 1), ftime->tm_mday,
+                     (ftime->tm_year + 1900), ftime->tm_wday,
+                     ftime->tm_hour, ftime->tm_min); 
+           } 
 
-       cl->cl_next = cf->cf_line_base;
-       cf->cf_line_base = cl;
-       Alloc(cl, CL);
+           /* add the current line to the list, and allocate a new line */
+           cl->cl_next = cf->cf_line_base;
+           cf->cf_line_base = cl;
+           Alloc(cl, CL);
+           break;
+           /* end of "case S_ENDLINE_T" in "switch(type)" */
+
+           /* default case in "switch(type)" */
+       default:
+           error("Error while loading %s : unknown field type %d (ignored)",
+                 file_name, type);
+           /* skip the data corresponding to the unknown field */
+           if ( fseek(ff, size, SEEK_CUR) < 0 ) {
+               error_e("Could not fseek file %s", file_name);
+               goto err;
+           }
+       }
     }
+
+    /* free last cl Alloc : unused */
+    free(cl);
+
     /* check for an error */
     if ( ferror(ff) != 0 )
        error("file %s is truncated : you should reinstall it with fcrontab",
              file_name);
 
-    /* free last calloc : unused */
-    free(cl);
-    
     fclose(ff);
 
-    return 0;
+    return OK;
+
+  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 */
+       if ( cl->cl_shell ) free(cl->cl_shell);
+       if ( cl->cl_runas) free(cl->cl_runas);
+       if ( cl->cl_mailto) free(cl->cl_mailto);
+       free(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);
+       
+    }
+    else if (cf->cf_user != NULL)
+       free(cf->cf_user);
+
+    return ERR;
 
 }
 
@@ -750,30 +947,73 @@ delete_file(const char *user_name)
 }
 
 
+/* save_file() error management */
+#define Save_type(file, type) \
+        { \
+          if ( save_type(file, type) != OK ) { \
+            error_e("Could not write type : file has not been saved."); \
+            fclose(file); \
+            remove(cf->cf_user); \
+            goto next_file; \
+         } \
+        }
+
+#define Save_str(file, type, str) \
+        { \
+          if ( save_str(file, type, str) != OK ) { \
+            error_e("Could not write str : file has not been saved."); \
+            fclose(file); \
+            remove(cf->cf_user); \
+            goto next_file; \
+         } \
+        }
+
+#define Save_strn(file, type, str, size) \
+        { \
+          if ( save_strn(file, type, str, size) != OK ) { \
+            error_e("Could not write strn : file has not been saved."); \
+            fclose(file); \
+            remove(cf->cf_user); \
+            goto next_file; \
+         } \
+        }
+
+#define Save_lint(file, type, value) \
+        { \
+          if ( save_lint(file, type, value) != OK ) { \
+            error_e("Could not write lint : file has not been saved."); \
+            fclose(file); \
+            remove(cf->cf_user); \
+            goto next_file; \
+         } \
+        }
+
 void
-save_file(CF *file)
+save_file(CF *arg_file)
     /* Store the informations relatives to the executions
      * of tasks at a defined frequency of system's running time */
 {
-    CF *cf = NULL;
-    CL *cl = NULL;
+    CF *file = NULL;
+    CL *line = NULL;
     FILE *f = NULL;
-    CF *start = NULL;
+    CF *start_file = NULL;
     env_t *env = NULL;
 
-    if (file != NULL)
-       start = file;
+    if (arg_file != NULL)
+       start_file = arg_file;
     else
-       start = file_base;
+       start_file = file_base;
        
     
-    for (cf = start; cf; cf = cf->cf_next) {
+    for (file = start_file; file; file = file->cf_next) {
 
-       debug("Saving %s...", cf->cf_user);
+       debug("Saving %s...", file->cf_user);
 
-       /* open file for writing */
-       if ( (f = fopen(cf->cf_user, "w")) == NULL )
-           error_e("save");
+       /* open file */
+       if ( (f = fopen(file->cf_user, "w")) == NULL ) {
+           error_e("Could not open %s", file->cf_user);
+           goto next_file;
+       }
 
        /* chown the file to root:root : this file should only be read and
         * modified by fcron (not fcrontab) */
@@ -782,39 +1022,72 @@ save_file(CF *file)
 
        /* save file : */
 
-       /* put version of frontab file: it permit to daemon not to load
+       /* put program's version : it permit to daemon not to load
         * a file which he won't understand the syntax, for exemple
         * a file using a depreciated format generated by an old fcrontab,
         * if the syntax has changed */
-       fprintf(f, "fcrontab-" FILEVERSION "\n");
+       /* an binary fcrontab *must* start by such a header */
+       save_lint(f, S_HEADER_T, S_FILEVERSION );
 
-       /* put the user's name : it is used to check his uid has not changed */
-       fprintf(f, "%s%c", cf->cf_user, '\0');
+       /* put the user's name : needed to check if his uid has not changed */
+       /* S_USER_T *must* be the 2nd field of a binary fcrontab */
+       save_str(f, S_USER_T, file->cf_user);
 
        /* put the time & date of saving : this is use for calcutating 
-        * the system down time */
-       fprintf(f, "%ld", now);
+        * the system down time. As it is a new file, we set it to 0 */
+       /* S_USER_T *must* be the 3rd field of a binary fcrontab */
+       save_lint(f, S_TIMEDATE_T, 0);
 
        /*   env variables, */
-       for (env = cf->cf_env_base; env; env = env->e_next)
-           fprintf(f, "%s%c", env->e_val, '\0');
+       for (env = file->cf_env_base; env; env = env->e_next)
+           save_str(f, S_ENVVAR_T, env->e_val);
        
-       fprintf(f, "%c", '\0');
-
-       /* finally, lines. */
-       for (cl = cf->cf_line_base; cl; cl = cl->cl_next) {
-           if ( fwrite(cl, sizeof(CL), 1, f) != 1 )
-               error_e("save");
-           fprintf(f, "%s%c", cl->cl_shell, '\0');
-           fprintf(f, "%s%c", cl->cl_runas, '\0');
-           fprintf(f, "%s%c", cl->cl_mailto, '\0');
+       /*   then, lines. */
+       for (line = file->cf_line_base; line; line = line->cl_next) {
+
+           /* this ones are saved for every lines */
+           save_str(f, S_SHELL_T, line->cl_shell);
+           save_str(f, S_RUNAS_T, line->cl_runas);
+           save_str(f, S_MAILTO_T, line->cl_mailto);
+           save_lint(f, S_NEXTEXE_T, line->cl_nextexe);
+           save_strn(f, S_OPTION_T, line->cl_option, OPTION_SIZE);
+
+           /* the following are saved only if needed */
+           if ( line->cl_numexe )
+               save_strn(f, S_NUMEXE_T, &line->cl_numexe, 1);
+           if ( is_lavg(line->cl_option) )
+               save_strn(f, S_LAVG_T, line->cl_lavg, LAVG_SIZE);
+           if ( line->cl_until > 0 )
+               save_lint(f, S_UNTIL_T, line->cl_until);
+           if ( line->cl_nice != 0 )
+               save_strn(f, S_NICE_T, &line->cl_nice, 1);
+           if ( line->cl_runfreq > 0 ) {
+               save_lint(f, S_RUNFREQ_T, line->cl_runfreq);
+               save_lint(f, S_REMAIN_T, line->cl_remain);
+           }
+                    
+           if ( is_freq(line->cl_option) )
+               /* save the frequency to run the line */
+               save_lint(f, S_TIMEFREQ_T, line->cl_timefreq);
+           else {
+               /* save the time and date bit fields */
+               save_strn(f, S_MINS_T, line->cl_mins, bitstr_size(60));
+               save_strn(f, S_HRS_T, line->cl_hrs, bitstr_size(24));
+               save_strn(f, S_DAYS_T, line->cl_days, bitstr_size(32));
+               save_strn(f, S_MONS_T, line->cl_mons, bitstr_size(12));
+               save_strn(f, S_DOW_T, line->cl_dow, bitstr_size(8));
+           }
+
+           /* This field *must* be the last of each line */
+           save_type(f, S_ENDLINE_T);
        }
-    
+
        fclose(f);
 
-       if (file != NULL)
+       if (arg_file != NULL)
            /* we have to save only a single file */
            break ;
 
+      next_file:
     }
 }
diff --git a/fcron.h b/fcron.h
index c1573428759304c0aaade03f064f65bc52b9705c..83a25b7b82ec3101a3fdf9b9a01c5fbb141f7e0b 100644 (file)
--- a/fcron.h
+++ b/fcron.h
@@ -21,7 +21,7 @@
  *  `LICENSE' that comes with the fcron source distribution.
  */
 
- /* $Id: fcron.h,v 1.18 2001-01-30 17:41:57 thib Exp $ */
+ /* $Id: fcron.h,v 1.19 2001-04-21 08:46:55 thib Exp $ */
 
 #ifndef __FCRONH__
 #define __FCRONH__
@@ -60,6 +60,7 @@ extern char debug_opt;
 extern char foreground;
 extern char *cdir;
 extern pid_t daemon_pid;
+extern mode_t saved_umask;
 extern char *prog_name;
 extern char sig_hup;
 extern CF *file_base;
@@ -102,6 +103,10 @@ extern void Debug(char *fmt, ...);
 /* subs.c */
 extern int remove_blanks(char *str);
 extern char *strdup2(const char *);
+extern int save_type(FILE *f, short int type);
+extern int save_str(FILE *f, short int type, char *str);
+extern int save_strn(FILE *f, short int type, char *str, short int size);
+extern int save_lint(FILE *f, short int type, long int value);
 /* end of subs.c */
 
 /* database.c */
index 229218a4c77d8c7728d3208281d2410bf5284d30..75b37232d8ced743f7a7b34483f96403b46c3749 100644 (file)
@@ -22,7 +22,7 @@
  *  `LICENSE' that comes with the fcron source distribution.
  */
 
- /* $Id: fileconf.c,v 1.42 2001-03-10 13:10:23 thib Exp $ */
+ /* $Id: fileconf.c,v 1.43 2001-04-21 08:47:07 thib Exp $ */
 
 #include "fcrontab.h"
 
@@ -167,7 +167,6 @@ read_file(char *filename, char *user)
     /* open file */
 
     /* check if user is allowed to read file */
-    /* create a temp file with user's permissions */
     if ( access(file_name, R_OK) != 0 )
        die_e("User %s can't read file \"%s\"", user, file_name);
     else if ( (file = fopen(file_name, "r")) == NULL ) {
@@ -181,6 +180,7 @@ read_file(char *filename, char *user)
     default_line.cl_file = cf;
     default_line.cl_runas = strdup2(user);
     default_line.cl_mailto = strdup2(user);
+    set_default_opt(default_line.cl_option);
 
     if ( debug_opt )
        fprintf(stderr, "FILE %s\n", file_name);
@@ -532,6 +532,7 @@ read_opt(char *ptr, CL *cl)
                cl->cl_runas = strdup2(user);
                free(cl->cl_mailto);
                cl->cl_mailto = strdup2(user);
+               set_default_opt(cl->cl_option);
            }
            if (debug_opt)
                fprintf(stderr, "  Opt : \"%s\"\n", opt_name);
@@ -1540,7 +1541,48 @@ delete_file(const char *user_name)
 }
 
 
-void
+/* save_file() error management */
+#define Save_type(file, type) \
+        { \
+          if ( save_type(file, type) != OK ) { \
+            error_e("Could not write type : file has not been installed."); \
+            fclose(file); \
+            remove(path); \
+            return ERR; \
+         } \
+        }
+
+#define Save_str(file, type, str) \
+        { \
+          if ( save_str(file, type, str) != OK ) { \
+            error_e("Could not write str : file has not been installed."); \
+            fclose(file); \
+            remove(path); \
+            return ERR; \
+         } \
+        }
+
+#define Save_strn(file, type, str, size) \
+        { \
+          if ( save_strn(file, type, str, size) != OK ) { \
+            error_e("Could not write strn : file has not been installed."); \
+            fclose(file); \
+            remove(path); \
+            return ERR; \
+         } \
+        }
+
+#define Save_lint(file, type, value) \
+        { \
+          if ( save_lint(file, type, value) != OK ) { \
+            error_e("Could not write lint : file has not been installed."); \
+            fclose(file); \
+            remove(path); \
+            return ERR; \
+         } \
+        }
+
+int
 save_file(char *path)
     /* Store the informations relatives to the executions
      * of tasks at a defined frequency of system's running time */
@@ -1556,8 +1598,10 @@ save_file(char *path)
     for (file = file_base; file; file = file->cf_next) {
 
        /* open file */
-       if ( (f = fopen(path, "w")) == NULL )
-           die_e("File has not be saved");
+       if ( (f = fopen(path, "w")) == NULL ) {
+           error_e("Could not open %s : file has not be installed.", path);
+           return ERR;
+       }
 
        /* save file : */
 
@@ -1565,32 +1609,67 @@ save_file(char *path)
         * a file which he won't understand the syntax, for exemple
         * a file using a depreciated format generated by an old fcrontab,
         * if the syntax has changed */
-       fprintf(f, "fcrontab-" FILEVERSION "\n");
+       /* an binary fcrontab *must* start by such a header */
+       Save_lint(f, S_HEADER_T, S_FILEVERSION );
 
-       /* put the user's name : it is used to check his uid has not changed */
-       fprintf(f, "%s%c", user, '\0');
+       /* put the user's name : needed to check if his uid has not changed */
+       /* S_USER_T *must* be the 2nd field of a binary fcrontab */
+       Save_str(f, S_USER_T, user);
 
        /* put the time & date of saving : this is use for calcutating 
         * the system down time. As it is a new file, we set it to 0 */
-       fprintf(f, "%d", 0);
+       /* S_USER_T *must* be the 3rd field of a binary fcrontab */
+       Save_lint(f, S_TIMEDATE_T, 0);
 
        /*   env variables, */
        for (env = file->cf_env_base; env; env = env->e_next)
-           fprintf(f, "%s%c", env->e_val, '\0');
+           Save_str(f, S_ENVVAR_T, env->e_val);
        
-       fprintf(f, "%c", '\0');
-
        /*   then, lines. */
        for (line = file->cf_line_base; line; line = line->cl_next) {
-           if ( fwrite(line, sizeof(CL), 1, f) != 1 )
-               perror("save");
-           fprintf(f, "%s%c", line->cl_shell, '\0');
-           fprintf(f, "%s%c", line->cl_runas, '\0');
-           fprintf(f, "%s%c", line->cl_mailto, '\0');
+
+           /* this ones are saved for every lines */
+           Save_str(f, S_SHELL_T, line->cl_shell);
+           Save_str(f, S_RUNAS_T, line->cl_runas);
+           Save_str(f, S_MAILTO_T, line->cl_mailto);
+           Save_strn(f, S_OPTION_T, line->cl_option, OPTION_SIZE);
+
+           /* the following are saved only if needed */
+           if ( line->cl_numexe )
+               Save_strn(f, S_NUMEXE_T, &line->cl_numexe, 1);
+           if ( is_lavg(line->cl_option) )
+               Save_strn(f, S_LAVG_T, line->cl_lavg, LAVG_SIZE);
+           if ( line->cl_until > 0 )
+               Save_lint(f, S_UNTIL_T, line->cl_until);
+           if ( line->cl_nice != 0 )
+               Save_strn(f, S_NICE_T, &line->cl_nice, 1);
+           if ( line->cl_runfreq > 0 ) {
+               Save_lint(f, S_RUNFREQ_T, line->cl_runfreq);
+               Save_lint(f, S_REMAIN_T, line->cl_remain);
+           }
+                    
+           if ( is_freq(line->cl_option) ) {
+               /* save the frequency and the first wait time */
+               Save_lint(f, S_NEXTEXE_T, line->cl_nextexe);
+               Save_lint(f, S_TIMEFREQ_T, line->cl_timefreq);
+           }
+           else {
+               /* save the time and date bit fields */
+               Save_strn(f, S_MINS_T, line->cl_mins, bitstr_size(60));
+               Save_strn(f, S_HRS_T, line->cl_hrs, bitstr_size(24));
+               Save_strn(f, S_DAYS_T, line->cl_days, bitstr_size(32));
+               Save_strn(f, S_MONS_T, line->cl_mons, bitstr_size(12));
+               Save_strn(f, S_DOW_T, line->cl_dow, bitstr_size(8));
+           }
+
+           /* This field *must* be the last of each line */
+           {
+               Save_type(f, S_ENDLINE_T);
+           }
        }
 
        fclose(f);
 
     }
+    return OK;
 }
-