/** BEGIN COPYRIGHT BLOCK * This Program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License. * * This Program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA. * * In addition, as a special exception, Red Hat, Inc. gives You the additional * right to link the code of this Program with code not covered under the GNU * General Public License ("Non-GPL Code") and to distribute linked combinations * including the two, subject to the limitations in this paragraph. Non-GPL Code * permitted under this exception must only link to the code of this Program * through those well defined interfaces identified in the file named EXCEPTION * found in the source code files (the "Approved Interfaces"). The files of * Non-GPL Code may instantiate templates or use macros or inline functions from * the Approved Interfaces without causing the resulting work to be covered by * the GNU General Public License. Only Red Hat, Inc. may make changes or * additions to the list of Approved Interfaces. You must obey the GNU General * Public License in all respects for all of the Program code and other code used * in conjunction with the Program except the Non-GPL Code covered by this * exception. If you modify this file, you may extend this exception to your * version of the file, but you are not obligated to do so. If you do not wish to * provide this exception without modification, you must delete this exception * statement from your version and license this file solely under the GPL without * exception. * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include "cron_conf.h" #define NSAPI_PUBLIC #ifndef BUF_SIZE #define BUF_SIZE 4096 #endif #ifndef S_BUF_SIZE #define S_BUF_SIZE 1024 #endif #ifdef XP_WIN32 #pragma warning (disable: 4005) // macro redifinition // #define MALLOC(size) malloc(size) #define REALLOC(x, size) realloc(x, size) #define FREE(x) free((void*) x) #define STRDUP(x) strdup(x) #define strcasecmp(x, y) stricmp(x, y) #pragma warning (default: 4005) // macro redifinition // #endif static char *admroot; static char *nsroot; #define DAILY "Sun Mon Tue Wed Thu Fri Sat" static cron_conf_list *cclist = NULL; static cron_conf_list *cctail = NULL; static char *conffile = NULL; #ifndef CRON_CONF_STAND_ALONE static void set_roots() { char *ar = ADMCONFDIR; if(ar) admroot = STRDUP(ar); } #endif /* General note: strtok() is not MT safe on Unix , but it is okay to call here because this file is NT only and strtok() is MT safe on NT */ static char *nocr(char *buf) { if (buf) { if(buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0'; } return buf; } static int debug(char *fmt, ...) { va_list args; char buf[BUF_SIZE]; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); fprintf(stdout, "<> %s <>\n", buf); fflush(stdout); return 1; } static char *get_conf_file() { static char conffile [S_BUF_SIZE]; char nsconfile[S_BUF_SIZE]; char buf [BUF_SIZE]; char *r, *p; FILE *fp; int flag = 0; if (admroot) sprintf(nsconfile, "%s/ns-cron.conf", admroot); else sprintf(nsconfile, "%s/admin-serv/config/ns-cron.conf", nsroot); if (!(fp = fopen(nsconfile, "r"))) return NULL; while(fgets(buf, sizeof(buf), fp)) { r = strtok(buf, " \t\n"); if (!r) /* bad line, ignore */ continue; p = strtok(NULL, " \t\n"); if (!p) /* bad line, ignore */ continue; if (!strcasecmp(r, "ConfFile")) { /* if filename without path is specified, default to admin svr dir */ if((strchr(p, '\\') == NULL) && (strchr(p, '/') == NULL)) sprintf(conffile, "%s/%s", admroot, p); else sprintf(conffile, "%s", p); flag++; break; } } fclose(fp); if (!flag) return NULL; return conffile; } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif cron_conf_obj *cron_conf_create_obj(char *name, char *command, char *dir, char *user, char *start_time, char *days) { cron_conf_obj *object; char *d = NULL; object = (cron_conf_obj*)MALLOC(sizeof(cron_conf_obj)); object->name = (name) ? STRDUP(name) : NULL; object->command = (command) ? STRDUP(command) : NULL; object->dir = (dir) ? STRDUP(dir) : NULL; object->user = (user) ? STRDUP(user) : NULL; object->start_time = (start_time) ? STRDUP(start_time) : NULL; #if 1 if (days) { if (!(strcasecmp(days, "Daily"))) d = STRDUP(DAILY); else d = STRDUP(days); } #else d = STRDUP("Wed Thu"); #endif object->days = d; return object; } static void cron_conf_free_listobj(cron_conf_list *lobj) { cron_conf_obj *obj = lobj->obj; if (obj) { if(obj->name) FREE(obj->name); if(obj->command) FREE(obj->command); if(obj->dir) FREE(obj->dir); if(obj->user) FREE(obj->user); if(obj->start_time) FREE(obj->start_time); if(obj->days) FREE(obj->days); FREE(obj); } FREE(lobj); } static cron_conf_obj *get_object(FILE *fp) { cron_conf_obj *object; char name [S_BUF_SIZE]; char command [S_BUF_SIZE]; char dir [S_BUF_SIZE]; char user [S_BUF_SIZE]; char start_time[S_BUF_SIZE]; char days [S_BUF_SIZE]; char buf [BUF_SIZE]; char *p, *q; int flag = 0; int hascom, hasdir, hasuser, hastime, hasdays; p = fgets(buf, sizeof(buf), fp); if (!p) return NULL; /* else debug("Read line '%s'", nocr(buf)); */ if (strncmp(buf, "\n\t "); if (!p) return NULL; p = strtok(NULL, "<=>\n\t "); if (!p) return NULL; p = strtok(NULL, "<=>\n\t "); if (!p) return NULL; sprintf(name, "%s", p); /* debug("Setting name to '%s'", name); */ while(fgets(buf, sizeof(buf), fp)) { /* debug("Read line '%s'", nocr(buf)); */ p = strtok(buf, " \t\n"); if (!p) continue; if (!strcasecmp(p, "")) { flag++; break; } if(!strcasecmp(p, "Command")) { q = strtok(NULL, "\n"); if (q) q = strchr(q, '\"'); if (q) q++; if (q) { if (!hascom) { /* get rid of quotes */ p = strrchr(q, '\"'); if (p) *p = '\0'; if (q) { PR_snprintf(command, S_BUF_SIZE, "%s", q); /* debug("Setting command to '%s'", command); */ hascom++; } } else /* already has a command */ ; /* ignore */ } continue; } if(!strcasecmp(p, "Dir")) { q = strtok(NULL, "\n"); if (q) q = strchr(q, '\"'); if (q) q++; if (q) { if (!hasdir) { /* get rid of quotes */ p = strrchr(q, '\"'); if (p) *p = '\0'; if (q) { PR_snprintf(dir, S_BUF_SIZE, "%s", q); /* debug("Setting dir to '%s'", dir); */ hasdir++; } } else /* already has a dir */ ; /* ignore */ } continue; } else if(!strcasecmp(p, "User")) { q = strtok(NULL, " \t\n"); if (q) { if (!hasuser) { PR_snprintf(user, S_BUF_SIZE, "%s", q); /* debug("Setting user to '%s'", user); */ hasuser++; } else /* already has a user */ ; /* ignore */ } continue; } else if(!strcasecmp(p, "Time")) { q = strtok(NULL, "\n"); if (q) { if (!hastime) { PR_snprintf(start_time, S_BUF_SIZE, "%s", q); /* debug("Setting time to '%s'", start_time); */ hastime++; } else /* already has a time */ ; /* ignore */ } continue; } else if(!strcasecmp(p, "Days")) { q = strtok(NULL, "\n"); if (q) { if (!hasdays) { PR_snprintf(days, S_BUF_SIZE, "%s", q); /* debug("Setting days to '%s'", days); */ hasdays++; } else /* already has days */ ; /* ignore */ } continue; } else { /* gibberish... ignore... will be fixed when file is rewritten */ continue; } } object = cron_conf_create_obj(name, (hascom) ? command : NULL, (hasdir) ? dir : NULL, (hasuser) ? user : NULL, (hastime) ? start_time : NULL, (hasdays) ? days : NULL); return object; } static void cron_conf_write_stream(FILE *fp) { cron_conf_obj *obj; cron_conf_list *lobj; for(lobj = cclist; lobj; lobj = lobj->next) { obj = lobj->obj; fprintf(fp, "\n", (obj->name) ? obj->name : "?"); fprintf(fp, " Command \"%s\"\n", (obj->command) ? obj->command : "?"); if (obj->dir) fprintf(fp, " Dir \"%s\"\n", obj->dir); if (obj->user) fprintf(fp, " User %s\n", obj->user); fprintf(fp, " Time %s\n", (obj->start_time) ? obj->start_time : "?"); fprintf(fp, " Days %s\n", (obj->days) ? obj->days : "?"); fprintf(fp, "\n"); } } static void cron_conf_delete(char *name, cron_conf_obj *cco) { cron_conf_list *lobj = NULL; cron_conf_list *pobj = NULL; if (!cclist) return; if (!strcmp(cclist->name, name)) { lobj = cclist; cclist = cclist->next; if (cctail == lobj) cctail = cclist; cron_conf_free_listobj(lobj); } else { pobj = cclist; for(lobj = cclist->next; lobj; lobj = lobj->next) { if(!strcmp(lobj->name, name)) { if (lobj == cctail) cctail = pobj; pobj->next = lobj->next; cron_conf_free_listobj(lobj); break; } pobj = lobj; } } return; } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif int cron_conf_read() { FILE *fp; cron_conf_obj *obj; cron_conf_list *lobj; #ifndef CRON_CONF_STAND_ALONE set_roots(); #endif if (!(conffile = get_conf_file())) { /* debug("Conffile is null"); */ return 0; } /* else debug("Conffile: '%s'", conffile); */ if (!(fp = fopen(conffile, "r"))) { /* debug("Couldn't open conffile"); */ return 0; } while((obj = get_object(fp))) { lobj = (cron_conf_list*)MALLOC(sizeof(struct cron_conf_list)); lobj->name = obj->name; lobj->obj = obj; lobj->next = NULL; /* debug("Created a list object named '%s'", lobj->name); */ if(cclist == NULL) /* first object */ { cclist = cctail = lobj; } else { cctail->next = lobj; cctail = lobj; } /* debug("List now, head: '%s', tail: '%s'", cclist->name, cctail->name); */ } fclose(fp); return 1; } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif cron_conf_obj *cron_conf_get(char *name) { cron_conf_obj *obj = NULL; cron_conf_list *lobj = NULL; /* find object */ for(lobj = cclist; lobj; lobj = lobj->next) { if(!strcmp(lobj->name, name)) { obj = lobj->obj; break; } } #if 0 if (obj) { debug("Found object %s", obj->name); debug("obj->command = %s", (obj->command) ? obj->command : "NULL"); debug("obj->dir = %s", (obj->dir) ? obj->dir : "NULL"); debug("obj->user = %s", (obj->user) ? obj->user : "NULL"); debug("obj->start_time = %s", (obj->start_time) ? obj->start_time : "NULL"); debug("obj->days = %s", (obj->days) ? obj->days : "NULL"); } #endif return obj; } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif cron_conf_list *cron_conf_get_list() { return cclist; } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif cron_conf_obj *cron_conf_set(char *name, cron_conf_obj *cco) { cron_conf_obj *obj = NULL; cron_conf_list *lobj = NULL; if (!name) return NULL; if (!cco) { cron_conf_delete(name, cco); return NULL; } else /* cco exists */ { /* find object */ obj = cron_conf_get(name); if (obj) /* found it */ { if (cco->command) { FREE(obj->command); obj->command = cco->command; } if (cco->dir) { FREE(obj->dir); obj->dir = cco->dir; } if (cco->user) { FREE(obj->user); obj->user = cco->user; } if (cco->start_time) { FREE(obj->start_time); obj->start_time = cco->start_time; } if (cco->days) { FREE(obj->days); obj->days = cco->days; } FREE(cco); } else /* couldn't find it */ { obj = cco; lobj = (cron_conf_list*)MALLOC(sizeof(cron_conf_list)); lobj->name = obj->name; lobj->obj = obj; lobj->next = NULL; if(cclist == NULL) /* first object */ { cclist = cctail = lobj; } else { cctail->next = lobj; cctail = lobj; } } } return obj; } void cron_conf_write() { FILE *fp; if (!conffile) conffile = get_conf_file(); if(!(fp = fopen(conffile, "w"))) return; cron_conf_write_stream(fp); fclose(fp); } #ifndef CRON_CONF_STAND_ALONE NSAPI_PUBLIC #endif void cron_conf_free() { cron_conf_list *lobj = NULL; /* find object */ while(cclist) { lobj = cclist; cclist = cclist->next; cron_conf_free_listobj(lobj); } cclist = cctail = NULL; }