* `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);
Alloc(cur_f, CF);
if ( read_file(file_name, cur_f) != 0 ) {
/* an error as occured */
- free(cur_f);
return;
}
if ( read_file(file_name, cur_f) != 0 ) {
/* an error as occured */
- free(cur_f);
return;
}
if ( read_file(file_name, cur_f) != 0 ) {
/* an error as occured */
- free(cur_f);
return;
}
}
-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 ) {
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);
runas = 0;
else {
error("Non-new file %s owned by someone else than root",file_name);
- return 1;
+ goto err;
}
}
* 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;
}
}
+/* 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) */
/* 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:
}
}
* `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"
/* 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 ) {
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);
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);
}
-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 */
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 : */
* 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;
}
-