int main(int argc, char *argv[]) { char *fn, *p; char cmd[1024]; FILE *fd; strbuffer_t *inbuf = newstrbuffer(0); void *listhead = NULL; int done, linenum; fn = strdup(argv[1]); strcpy(cmd, "!"); done = 0; while (!done) { if (*cmd == '!') { fd = stackfopen(fn, "r", &listhead); linenum = 1; if (!fd) { errprintf("Cannot open file %s\n", fn); continue; } while (stackfgets(inbuf, NULL)) { linenum++; printf("%s", STRBUF(inbuf)); } stackfclose(fd); } else if (*cmd == '?') { filelist_t *walk = (filelist_t *)listhead; while (walk) { printf("%s %lu\n", walk->filename, (unsigned long)walk->fsize); walk = walk->next; } if (stackfmodified(listhead)) printf("File(s) have been modified\n"); else printf("No changes\n"); } else if (*cmd == '.') { done = 1; continue; } else { xfree(fn); fn = strdup(cmd); stackfclist(&listhead); strcpy(cmd, "!"); continue; } printf("\nCmd: "); fflush(stdout); fgets(cmd, sizeof(cmd), stdin); p = strchr(cmd, '\n'); if (p) *p = '\0'; } xfree(fn); stackfclist(&listhead); return 0; }
static int prepare_fromfile(char *hostsfn, char *extrainclude) { static void *hostfiles = NULL; FILE *hosts; strbuffer_t *inbuf; /* First check if there were no modifications at all */ if (hostfiles) { if (!stackfmodified(hostfiles)){ return 1; } else { stackfclist(&hostfiles); hostfiles = NULL; } } if (!contentbuffer) contentbuffer = newstrbuffer(0); clearstrbuffer(contentbuffer); hosts = stackfopen(hostsfn, "r", &hostfiles); if (hosts == NULL) return -1; inbuf = newstrbuffer(0); while (stackfgets(inbuf, extrainclude)) { sanitize_input(inbuf, 0, 0); addtostrbuffer(contentbuffer, inbuf); addtobuffer(contentbuffer, "\n"); } stackfclose(hosts); freestrbuffer(inbuf); return 0; }
void readconfig(char *cfgfn, int verbose) { static void *cfgfiles = NULL; FILE *cfgfd; strbuffer_t *inbuf; struct req_t *reqitem = NULL; int tasksleep = atoi(xgetenv("TASKSLEEP")); mibdef_t *mib; /* Check if config was modified */ if (cfgfiles) { if (!stackfmodified(cfgfiles)) { dbgprintf("No files changed, skipping reload\n"); return; } else { stackfclist(&cfgfiles); cfgfiles = NULL; } } cfgfd = stackfopen(cfgfn, "r", &cfgfiles); if (cfgfd == NULL) { errprintf("Cannot open configuration files %s\n", cfgfn); return; } inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { char *bot, *p, *mibidx; char savech; sanitize_input(inbuf, 0, 0); bot = STRBUF(inbuf) + strspn(STRBUF(inbuf), " \t"); if ((*bot == '\0') || (*bot == '#')) continue; if (*bot == '[') { char *intvl = strchr(bot, '/'); /* * See if we're running a non-standard interval. * If yes, then process only the records that match * this TASKSLEEP setting. */ if (tasksleep != 300) { /* Non-default interval. Skip the host if it HASN'T got an interval setting */ if (!intvl) continue; /* Also skip the hosts that have an interval different from the current */ *intvl = '\0'; /* Clip the interval from the hostname */ if (atoi(intvl+1) != tasksleep) continue; } else { /* Default interval. Skip the host if it HAS an interval setting */ if (intvl) continue; } reqitem = (req_t *)calloc(1, sizeof(req_t)); p = strchr(bot, ']'); if (p) *p = '\0'; reqitem->hostname = strdup(bot + 1); if (p) *p = ']'; reqitem->hostip[0] = reqitem->hostname; reqitem->version = SNMP_VERSION_1; reqitem->authmethod = SNMP_V3AUTH_MD5; reqitem->next = reqhead; reqhead = reqitem; continue; } /* If we have nowhere to put the data, then skip further processing */ if (!reqitem) continue; if (strncmp(bot, "ip=", 3) == 0) { char *nextip = strtok(strdup(bot+3), ","); int i = 0; do { reqitem->hostip[i++] = nextip; nextip = strtok(NULL, ","); } while (nextip); continue; } if (strncmp(bot, "version=", 8) == 0) { switch (*(bot+8)) { case '1': reqitem->version = SNMP_VERSION_1; break; case '2': reqitem->version = SNMP_VERSION_2c; break; case '3': reqitem->version = SNMP_VERSION_3; break; } continue; } if (strncmp(bot, "community=", 10) == 0) { reqitem->community = strdup(bot+10); continue; } if (strncmp(bot, "username="******"passphrase=", 10) == 0) { reqitem->passphrase = strdup(bot+10); continue; } if (strncmp(bot, "authmethod=", 10) == 0) { if (strcasecmp(bot+10, "md5") == 0) reqitem->authmethod = SNMP_V3AUTH_MD5; else if (strcasecmp(bot+10, "sha1") == 0) reqitem->authmethod = SNMP_V3AUTH_SHA1; else errprintf("Unknown SNMPv3 authentication method '%s'\n", bot+10); continue; } /* Custom mibs */ p = bot + strcspn(bot, "= \t\r\n"); savech = *p; *p = '\0'; mib = find_mib(bot); *p = savech; p += strspn(p, "= \t"); mibidx = p; if (mib) { int i; mibidx_t *iwalk = NULL; char *oid, *oidbuf; char *devname; oidset_t *swalk; setupmib(mib, verbose); if (mib->loadstatus != MIB_STATUS_LOADED) continue; /* Cannot use this MIB */ /* See if this is an entry where we must determine the index ourselves */ if (*mibidx) { for (iwalk = mib->idxlist; (iwalk && (*mibidx != iwalk->marker)); iwalk = iwalk->next) ; } if ((*mibidx == '*') && !iwalk) { errprintf("Cannot do wildcard matching without an index (host %s, mib %s)\n", reqitem->hostname, mib->mibname); continue; } if (!iwalk) { /* No key lookup */ swalk = mib->oidlisthead; while (swalk) { reqitem->setnumber++; for (i=0; (i <= swalk->oidcount); i++) { if (*mibidx) { oid = oidbuf = (char *)malloc(strlen(swalk->oids[i].oid) + strlen(mibidx) + 2); sprintf(oidbuf, "%s.%s", swalk->oids[i].oid, mibidx); devname = mibidx; } else { oid = swalk->oids[i].oid; oidbuf = NULL; devname = "-"; } make_oitem(mib, devname, &swalk->oids[i], oid, reqitem); if (oidbuf) xfree(oidbuf); } swalk = swalk->next; } reqitem->next_oid = reqitem->oidhead; } else { /* Add a key-record so we can try to locate the index */ keyrecord_t *newitem = (keyrecord_t *)calloc(1, sizeof(keyrecord_t)); char endmarks[6]; mibidx++; /* Skip the key-marker */ sprintf(endmarks, "%s%c", ")]}>", iwalk->marker); p = mibidx + strcspn(mibidx, endmarks); *p = '\0'; newitem->key = strdup(mibidx); newitem->indexmethod = iwalk; newitem->mib = mib; newitem->next = reqitem->keyrecords; reqitem->currentkey = reqitem->keyrecords = newitem; } continue; } else { errprintf("Unknown MIB (not in snmpmibs.cfg): '%s'\n", bot); } } stackfclose(cfgfd); freestrbuffer(inbuf); }
void load_config(char *conffn) { static void *configfiles = NULL; tasklist_t *twalk, *curtask = NULL; FILE *fd; strbuffer_t *inbuf; char *p; char myhostname[256]; /* First check if there were no modifications at all */ if (configfiles) { if (!stackfmodified(configfiles) && (!forcereload)) { dbgprintf("No files modified, skipping reload of %s\n", conffn); return; } else { stackfclist(&configfiles); configfiles = NULL; } } errprintf("Loading tasklist configuration from %s\n", conffn); if (gethostname(myhostname, sizeof(myhostname)) != 0) { errprintf("Cannot get the local hostname, using 'localhost' (error: %s)\n", strerror(errno)); strcpy(myhostname, "localhost"); } /* The cfload flag: -1=delete task, 0=old task unchanged, 1=new/changed task */ for (twalk = taskhead; (twalk); twalk = twalk->next) { twalk->cfload = -1; twalk->group = NULL; /* Create a copy, but retain the settings and pointers are the same */ twalk->copy = xmalloc(sizeof(tasklist_t)); memcpy(twalk->copy,twalk,sizeof(tasklist_t)); /* These should get cleared */ twalk->copy->next = NULL; twalk->copy->copy = NULL; /* And clean the values of all others, so that we really can detect a difference */ twalk->disabled = 0; twalk->cmd = NULL; twalk->interval = 0; twalk->maxruntime = 0; twalk->group = NULL; twalk->logfile = NULL; twalk->envfile = NULL; twalk->envarea = NULL; twalk->onhostptn = NULL; twalk->cronstr = NULL; twalk->crondate = NULL; twalk->depends = NULL; } fd = stackfopen(conffn, "r", &configfiles); if (fd == NULL) { errprintf("Cannot open configuration file %s: %s\n", conffn, strerror(errno)); return; } inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue; p = STRBUF(inbuf); if (*p == '[') { /* New task */ char *endp; /* get name */ p++; endp = strchr(p, ']'); if (endp == NULL) continue; *endp = '\0'; /* try to find the task */ for (twalk = taskhead; (twalk && (strcmp(twalk->key, p))); twalk = twalk->next); if (twalk) { curtask=twalk; } else { /* New task, just create it */ curtask = (tasklist_t *)calloc(1, sizeof(tasklist_t)); curtask->key = strdup(p); /* add it to the list */ if (taskhead == NULL) taskhead = curtask; else tasktail->next = curtask; tasktail = curtask; } /* mark task as configured */ curtask->cfload = 0; } else if (curtask && (strncasecmp(p, "CMD ", 4) == 0)) { p += 3; p += strspn(p, " \t"); /* Handle + - options as well */ if (*p == '+') { /* append to command */ if (curtask->cmd) { int l1 = strlen(curtask->cmd); int l2 = strlen(p); char *newcmd = xcalloc(1, l1+l2+1); strncpy(newcmd,curtask->cmd,l1); strncpy(newcmd+l1,p,l2); newcmd[l1]=' '; /* this also overwrites the + */ /* free and assign new */ xfreeassign(curtask->cmd,newcmd); } } else if (*p == '-') { /* remove from command */ if (curtask->cmd) { int l = strlen(p)-1; if (l > 0) { char *found; while((found = strstr(curtask->cmd,p+1)) != NULL) { /* doing a copy - can not use strcpy as we are overlapping */ char *s = found + l; while (*s) { *found=*s; found++; s++; } *found=0; } } else { errprintf("Configuration error, empty command removal (CMD -) for task %s\n", curtask->key); } } } else { xfreedup(curtask->cmd,p); } } else if (strncasecmp(p, "GROUP ", 6) == 0) { /* Note: GROUP can be used by itself to define a group, or inside a task definition */ char *groupname; int maxuse; grouplist_t *gwalk; p += 6; p += strspn(p, " \t"); groupname = p; p += strcspn(p, " \t"); if (isdigit((int) *p)) maxuse = atoi(p); else maxuse = 1; /* Find or create the grouplist entry */ for (gwalk = grouphead; (gwalk && (strcmp(gwalk->groupname, groupname))); gwalk = gwalk->next); if (gwalk == NULL) { gwalk = (grouplist_t *)malloc(sizeof(grouplist_t)); gwalk->groupname = strdup(groupname); gwalk->maxuse = maxuse; gwalk->currentuse = 0; gwalk->next = grouphead; grouphead = gwalk; } if (curtask) curtask->group = gwalk; } else if (curtask && (strncasecmp(p, "INTERVAL ", 9) == 0)) { char *tspec; p += 9; curtask->interval = atoi(p); tspec = p + strspn(p, "0123456789"); switch (*tspec) { case 'm': curtask->interval *= 60; break; /* Minutes */ case 'h': curtask->interval *= 3600; break; /* Hours */ case 'd': curtask->interval *= 86400; break; /* Days */ } } else if (curtask && (strncasecmp(p, "CRONDATE ", 9) == 0)) { p+= 9; xfreedup(curtask->cronstr,p); if (curtask->crondate) crondatefree(curtask->crondate); curtask->crondate = parse_cron_time(curtask->cronstr); if (!curtask->crondate) { errprintf("Can't parse cron date: %s->%s\n", curtask->key, curtask->cronstr); curtask->disabled = 1; } curtask->interval = -1; /* disable interval */ } else if (curtask && (strncasecmp(p, "MAXTIME ", 8) == 0)) { char *tspec; p += 8; curtask->maxruntime = atoi(p); tspec = p + strspn(p, "0123456789"); switch (*tspec) { case 'm': curtask->maxruntime *= 60; break; /* Minutes */ case 'h': curtask->maxruntime *= 3600; break; /* Hours */ case 'd': curtask->maxruntime *= 86400; break; /* Days */ } } else if (curtask && (strncasecmp(p, "LOGFILE ", 8) == 0)) { p += 7; p += strspn(p, " \t"); xfreedup(curtask->logfile,p); } else if (curtask && (strncasecmp(p, "NEEDS ", 6) == 0)) { p += 6; p += strspn(p, " \t"); for (twalk = taskhead; (twalk && strcmp(twalk->key, p)); twalk = twalk->next); if (twalk) { curtask->depends = twalk; } else { errprintf("Configuration error, unknown dependency %s->%s\n", curtask->key, p); } } else if (curtask && (strncasecmp(p, "ENVFILE ", 8) == 0)) { p += 7; p += strspn(p, " \t"); xfreedup(curtask->envfile,p); } else if (curtask && (strncasecmp(p, "ENVAREA ", 8) == 0)) { p += 7; p += strspn(p, " \t"); xfreedup(curtask->envarea,p); } else if (curtask && (strcasecmp(p, "DISABLED") == 0)) { curtask->disabled = 1; } else if (curtask && (strcasecmp(p, "ENABLED") == 0)) { curtask->disabled = 0; } else if (curtask && (strncasecmp(p, "ONHOST ", 7) == 0)) { regex_t cpattern; int status; p += 7; p += strspn(p, " \t"); xfreedup(curtask->onhostptn,p); /* Match the hostname against the pattern; if it doesnt match then disable the task */ status = regcomp(&cpattern, curtask->onhostptn, REG_EXTENDED|REG_ICASE|REG_NOSUB); if (status == 0) { status = regexec(&cpattern, myhostname, 0, NULL, 0); if (status == REG_NOMATCH) curtask->disabled = 1; } else { errprintf("ONHOST pattern '%s' is invalid\n", p); } } } stackfclose(fd); freestrbuffer(inbuf); /* Running tasks that have been deleted or changed are killed off now. */ for (twalk = taskhead; (twalk); twalk = twalk->next) { /* compare the current settings with the copy - if we have one */ if (twalk->cfload == 0) { if (twalk->copy) { /* compare the current version with the new version and decide if we have changed */ int changed=0; int reload=0; /* first the nummeric ones */ if (twalk->disabled!=twalk->copy->disabled) { changed++; } if (twalk->interval!=twalk->copy->interval) { changed++; } if (twalk->maxruntime!=twalk->copy->maxruntime) { changed++; } if (twalk->group!=twalk->copy->group) { changed++; reload++;} /* then the string versions */ #define twalkstrcmp(k,doreload) { \ if (twalk->k!=twalk->copy->k) { \ if (twalk->copy->k) { \ if (twalk->k) { \ if (strcmp(twalk->k,twalk->copy->k)) { \ changed++;reload+=doreload; \ } \ } else { \ changed++;reload+=doreload; \ } \ /* we can always delete the copy*/ \ xfree(twalk->copy->k); \ twalk->copy->k=NULL; \ } else { \ changed++;reload+=doreload; \ } \ } \ } twalkstrcmp(cmd,1); twalkstrcmp(logfile,1); twalkstrcmp(envfile,1); twalkstrcmp(envarea,1); twalkstrcmp(onhostptn,0); twalkstrcmp(cronstr,0); if ((twalk->copy->cronstr == NULL) && twalk->copy->crondate) { crondatefree(twalk->copy->crondate); twalk->copy->crondate = NULL; } /* we can release the copy now - not using xfree, as this releases it from the list making a mess...*/ xfreenull(twalk->copy); /* now make the decision for reloading - if we have changed, then we may assign cfload, - otherwise the entry does not exist any longer */ if (reload) { reload=1;} if (changed) { twalk->cfload=reload; } } else { /* new object, so we need to do this */ twalk->cfload=1; } } /* and based on this decide what to do */ switch (twalk->cfload) { case -1: /* Kill the task, if active */ if (twalk->pid) { dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid); twalk->beingkilled = 1; kill(twalk->pid, SIGTERM); } /* And prepare to free this tasklist entry */ xfreenull(twalk->key); xfreenull(twalk->cmd); xfreenull(twalk->logfile); xfreenull(twalk->envfile); xfreenull(twalk->envarea); xfreenull(twalk->onhostptn); xfreenull(twalk->cronstr); if (twalk->crondate) crondatefree(twalk->crondate); break; case 0: /* Do nothing */ break; case 1: /* Bounce the task, if it is active */ if (twalk->pid) { dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid); twalk->beingkilled = 1; kill(twalk->pid, SIGTERM); } break; } } /* First clean out dead tasks at the start of the list */ while (taskhead && (taskhead->cfload == -1)) { tasklist_t *tmp; tmp = taskhead; taskhead = taskhead->next; xfree(tmp); } /* Then unlink and free those inside the list */ twalk = taskhead; while (twalk && twalk->next) { tasklist_t *tmp; if (twalk->next->cfload == -1) { tmp = twalk->next; twalk->next = tmp->next; xfree(tmp); } else twalk = twalk->next; } if (taskhead == NULL) tasktail = NULL; else { tasktail = taskhead; while (tasktail->next) tasktail = tasktail->next; } /* Make sure group usage counts are correct (groups can change) */ for (twalk = taskhead; (twalk); twalk = twalk->next) { if (twalk->group) twalk->group->currentuse = 0; } for (twalk = taskhead; (twalk); twalk = twalk->next) { if (twalk->group && twalk->pid) twalk->group->currentuse++; } }
int load_holidays(int year) { static void *configholidays = NULL; char fn[PATH_MAX]; FILE *fd; strbuffer_t *inbuf; holiday_t newholiday; xtreePos_t handle, commonhandle; char *setname = NULL; holidayset_t *commonhols; MEMDEFINE(fn); if (year == 0) { time_t tnow; struct tm *now; tnow = getcurrenttime(NULL); now = localtime(&tnow); year = now->tm_year; } else if (year > 1000) { year -= 1900; } sprintf(fn, "%s/etc/holidays.cfg", xgetenv("XYMONHOME")); /* First check if there were no modifications at all */ if (configholidays) { /* if the new year begins, the holidays have to be recalculated */ if (!stackfmodified(configholidays) && (year == current_year)){ dbgprintf("No files modified, skipping reload of %s\n", fn); MEMUNDEFINE(fn); return 0; } else { stackfclist(&configholidays); configholidays = NULL; } } reset_holidays(); fd = stackfopen(fn, "r", &configholidays); if (!fd) { errprintf("Cannot open configuration file %s\n", fn); MEMUNDEFINE(fn); return 0; } memset(&newholiday,0,sizeof(holiday_t)); inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { char *p, *delim, *arg1, *arg2; sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue; p = STRBUF(inbuf); if (strncasecmp(p, "HOLIDAYLIKEWEEKDAY=", 19) == 0) { p+=19; holidays_like_weekday = atoi(p); if (holidays_like_weekday < -1 || holidays_like_weekday > 6) { holidays_like_weekday = -1; errprintf("Invalid HOLIDAYLIKEWEEKDAY in %s\n", fn); } continue; } if (*p == '[') { /* New set of holidays */ if (setname) xfree(setname); delim = strchr(p, ']'); if (delim) *delim = '\0'; setname = strdup(p+1); continue; } delim = strchr(p, ':'); if (delim) { memset(&newholiday,0,sizeof(holiday_t)); if (delim == p) { newholiday.desc = "untitled"; } else { *delim = '\0'; newholiday.desc = p; p=delim+1; } } arg1 = strtok(p, "="); while (arg1) { arg2=strtok(NULL," ,;\t\n\r"); if (!arg2) break; if (strncasecmp(arg1, "TYPE", 4) == 0) { if (strncasecmp(arg2, "STATIC", 6) == 0) newholiday.holtype = HOL_ABSOLUTE; else if (strncasecmp(arg2, "EASTER", 6) == 0) newholiday.holtype = HOL_EASTER; else if (strncasecmp(arg2, "4ADVENT", 7) == 0) newholiday.holtype = HOL_ADVENT; else if (strncasecmp(arg2, "MON", 3) == 0) newholiday.holtype = HOL_MON; else if (strncasecmp(arg2, "TUE", 3) == 0) newholiday.holtype = HOL_TUE; else if (strncasecmp(arg2, "WED", 3) == 0) newholiday.holtype = HOL_WED; else if (strncasecmp(arg2, "THU", 3) == 0) newholiday.holtype = HOL_THU; else if (strncasecmp(arg2, "FRI", 3) == 0) newholiday.holtype = HOL_FRI; else if (strncasecmp(arg2, "SAT", 3) == 0) newholiday.holtype = HOL_SAT; else if (strncasecmp(arg2, "SUN", 3) == 0) newholiday.holtype = HOL_SUN; else if (strncasecmp(arg2, "+MON", 4) == 0) newholiday.holtype = HOL_MON_AFTER; else if (strncasecmp(arg2, "+TUE", 4) == 0) newholiday.holtype = HOL_TUE_AFTER; else if (strncasecmp(arg2, "+WED", 4) == 0) newholiday.holtype = HOL_WED_AFTER; else if (strncasecmp(arg2, "+THU", 4) == 0) newholiday.holtype = HOL_THU_AFTER; else if (strncasecmp(arg2, "+FRI", 4) == 0) newholiday.holtype = HOL_FRI_AFTER; else if (strncasecmp(arg2, "+SAT", 4) == 0) newholiday.holtype = HOL_SAT_AFTER; else if (strncasecmp(arg2, "+SUN", 4) == 0) newholiday.holtype = HOL_SUN_AFTER; } else if (strncasecmp(arg1, "MONTH", 5) == 0) { newholiday.month=atoi(arg2); } else if (strncasecmp(arg1, "DAY", 3) == 0) { newholiday.day=atoi(arg2); } else if (strncasecmp(arg1, "OFFSET", 6) == 0) { newholiday.day=atoi(arg2); } else if (strncasecmp(arg1, "YEAR", 4) == 0) { newholiday.year=atoi(arg2); if (newholiday.year > 1000) { newholiday.year -= 1900; } } arg1 = strtok(NULL,"="); } add_holiday((setname ? setname : ""), year, &newholiday); } stackfclose(fd); freestrbuffer(inbuf); commonhandle = xtreeFind(holidays, ""); commonhols = (commonhandle != xtreeEnd(holidays)) ? (holidayset_t *)xtreeData(holidays, commonhandle) : NULL; for (handle = xtreeFirst(holidays); (handle != xtreeEnd(holidays)); handle = xtreeNext(holidays, handle)) { holidayset_t *oneset = (holidayset_t *)xtreeData(holidays, handle); if (commonhols && (oneset != commonhols)) { /* Add the common holidays to this set */ holiday_t *walk; for (walk = commonhols->head; (walk); walk = walk->next) add_holiday(oneset->key, year, walk); } oneset->head = msort(oneset->head, record_compare, record_getnext, record_setnext); } MEMUNDEFINE(fn); current_year = year; return 0; }
void load_config(char *conffn) { static void *configfiles = NULL; tasklist_t *twalk, *curtask = NULL; FILE *fd; strbuffer_t *inbuf; char *p; char myhostname[256]; /* First check if there were no modifications at all */ if (configfiles) { if (!stackfmodified(configfiles)){ dbgprintf("No files modified, skipping reload of %s\n", conffn); return; } else { stackfclist(&configfiles); configfiles = NULL; } } errprintf("Loading tasklist configuration from %s\n", conffn); if (gethostname(myhostname, sizeof(myhostname)) != 0) { errprintf("Cannot get the local hostname, using 'localhost' (error: %s)\n", strerror(errno)); strcpy(myhostname, "localhost"); } /* The cfload flag: -1=delete task, 0=old task unchanged, 1=new/changed task */ for (twalk = taskhead; (twalk); twalk = twalk->next) { twalk->cfload = -1; twalk->group = NULL; } fd = stackfopen(conffn, "r", &configfiles); if (fd == NULL) { errprintf("Cannot open configuration file %s: %s\n", conffn, strerror(errno)); return; } inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue; p = STRBUF(inbuf); if (*p == '[') { /* New task */ char *endp; if (curtask) { update_task(curtask); curtask = NULL; } p++; endp = strchr(p, ']'); if (endp == NULL) continue; *endp = '\0'; curtask = (tasklist_t *)calloc(1, sizeof(tasklist_t)); curtask->key = strdup(p); } else if (curtask && (strncasecmp(p, "CMD ", 4) == 0)) { p += 3; p += strspn(p, " \t"); curtask->cmd = strdup(p); } else if (strncasecmp(p, "GROUP ", 6) == 0) { /* Note: GROUP can be used by itself to define a group, or inside a task definition */ char *groupname; int maxuse; grouplist_t *gwalk; p += 6; p += strspn(p, " \t"); groupname = p; p += strcspn(p, " \t"); if (isdigit((int) *p)) maxuse = atoi(p); else maxuse = 1; /* Find or create the grouplist entry */ for (gwalk = grouphead; (gwalk && (strcmp(gwalk->groupname, groupname))); gwalk = gwalk->next); if (gwalk == NULL) { gwalk = (grouplist_t *)malloc(sizeof(grouplist_t)); gwalk->groupname = strdup(groupname); gwalk->maxuse = maxuse; gwalk->currentuse = 0; gwalk->next = grouphead; grouphead = gwalk; } if (curtask) curtask->group = gwalk; } else if (curtask && (strncasecmp(p, "INTERVAL ", 9) == 0)) { char *tspec; p += 9; curtask->interval = atoi(p); tspec = p + strspn(p, "0123456789"); switch (*tspec) { case 'm': curtask->interval *= 60; break; /* Minutes */ case 'h': curtask->interval *= 3600; break; /* Hours */ case 'd': curtask->interval *= 86400; break; /* Days */ } } else if (curtask && (strncasecmp(p, "CRONDATE ", 9) == 0)) { p+= 9; curtask->cronstr = strdup(p); curtask->crondate = parse_cron_time(curtask->cronstr); if (!curtask->crondate) { errprintf("Can't parse cron date: %s->%s", curtask->key, curtask->cronstr); curtask->disabled = 1; } curtask->interval = -1; /* disable interval */ } else if (curtask && (strncasecmp(p, "MAXTIME ", 8) == 0)) { char *tspec; p += 8; curtask->maxruntime = atoi(p); tspec = p + strspn(p, "0123456789"); switch (*tspec) { case 'm': curtask->maxruntime *= 60; break; /* Minutes */ case 'h': curtask->maxruntime *= 3600; break; /* Hours */ case 'd': curtask->maxruntime *= 86400; break; /* Days */ } } else if (curtask && (strncasecmp(p, "LOGFILE ", 8) == 0)) { p += 7; p += strspn(p, " \t"); curtask->logfile = strdup(p); } else if (curtask && (strncasecmp(p, "NEEDS ", 6) == 0)) { p += 6; p += strspn(p, " \t"); for (twalk = taskhead; (twalk && strcmp(twalk->key, p)); twalk = twalk->next); if (twalk) { curtask->depends = twalk; } else { errprintf("Configuration error, unknown dependency %s->%s", curtask->key, p); } } else if (curtask && (strncasecmp(p, "ENVFILE ", 8) == 0)) { p += 7; p += strspn(p, " \t"); curtask->envfile = strdup(p); } else if (curtask && (strncasecmp(p, "ENVAREA ", 8) == 0)) { p += 7; p += strspn(p, " \t"); curtask->envarea = strdup(p); } else if (curtask && (strcasecmp(p, "DISABLED") == 0)) { curtask->disabled = 1; } else if (curtask && (strncasecmp(p, "ONHOST ", 7) == 0)) { regex_t cpattern; int status; p += 7; p += strspn(p, " \t"); curtask->onhostptn = strdup(p); /* Match the hostname against the pattern; if it doesnt match then disable the task */ status = regcomp(&cpattern, curtask->onhostptn, REG_EXTENDED|REG_ICASE|REG_NOSUB); if (status == 0) { status = regexec(&cpattern, myhostname, 0, NULL, 0); if (status == REG_NOMATCH) curtask->disabled = 1; } else { errprintf("ONHOST pattern '%s' is invalid\n", p); } } } if (curtask) update_task(curtask); stackfclose(fd); freestrbuffer(inbuf); /* Running tasks that have been deleted or changed are killed off now. */ for (twalk = taskhead; (twalk); twalk = twalk->next) { switch (twalk->cfload) { case -1: /* Kill the task, if active */ if (twalk->pid) { dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid); twalk->beingkilled = 1; kill(twalk->pid, SIGTERM); } /* And prepare to free this tasklist entry */ xfree(twalk->key); xfree(twalk->cmd); if (twalk->logfile) xfree(twalk->logfile); if (twalk->envfile) xfree(twalk->envfile); if (twalk->envarea) xfree(twalk->envarea); if (twalk->onhostptn) xfree(twalk->onhostptn); if (twalk->cronstr) xfree(twalk->cronstr); if (twalk->crondate) crondatefree(twalk->crondate); break; case 0: /* Do nothing */ break; case 1: /* Bounce the task, if it is active */ if (twalk->pid) { dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid); twalk->beingkilled = 1; kill(twalk->pid, SIGTERM); } break; } } /* First clean out dead tasks at the start of the list */ while (taskhead && (taskhead->cfload == -1)) { tasklist_t *tmp; tmp = taskhead; taskhead = taskhead->next; xfree(tmp); } /* Then unlink and free those inside the list */ twalk = taskhead; while (twalk && twalk->next) { tasklist_t *tmp; if (twalk->next->cfload == -1) { tmp = twalk->next; twalk->next = tmp->next; xfree(tmp); } else twalk = twalk->next; } if (taskhead == NULL) tasktail = NULL; else { tasktail = taskhead; while (tasktail->next) tasktail = tasktail->next; } /* Make sure group usage counts are correct (groups can change) */ for (twalk = taskhead; (twalk); twalk = twalk->next) { if (twalk->group) twalk->group->currentuse = 0; } for (twalk = taskhead; (twalk); twalk = twalk->next) { if (twalk->group && twalk->pid) twalk->group->currentuse++; } }
int load_nkconfig(char *fn) { static void *configfiles = NULL; static int firsttime = 1; FILE *fd; strbuffer_t *inbuf; /* Setup the default configuration filename */ if (!fn) { if (!defaultfn) { char *bbhome = xgetenv("BBHOME"); defaultfn = (char *)malloc(strlen(bbhome) + strlen(DEFAULTCONFIG) + 2); sprintf(defaultfn, "%s/%s", bbhome, DEFAULTCONFIG); } fn = defaultfn; } if (configfn) xfree(configfn); configfn = strdup(fn); /* First check if there were no modifications at all */ if (configfiles) { if (!stackfmodified(configfiles)){ dbgprintf("No files modified, skipping reload of %s\n", fn); return 0; } else { stackfclist(&configfiles); configfiles = NULL; } } if (!firsttime) { /* Clean up existing datatree */ RbtHandle handle; void *k1, *k2; for (handle = rbtBegin(rbconf); (handle != rbtEnd(rbconf)); handle = rbtNext(rbconf, handle)) { rbtKeyValue(rbconf, handle, &k1, &k2); flushrec(k1, k2); } rbtDelete(rbconf); } firsttime = 0; rbconf = rbtNew(name_compare); fd = stackfopen(fn, "r", &configfiles); if (fd == NULL) return 1; inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { /* Full record : Host service START END TIMESPEC TTPrio TTGroup TTExtra */ /* Clone record: Host =HOST */ char *ehost, *eservice, *estart, *eend, *etime, *ttgroup, *ttextra, *updinfo; int ttprio = 0; nkconf_t *newitem; RbtStatus status; int idx = 0; ehost = gettok(STRBUF(inbuf), "|\n"); if (!ehost) continue; eservice = gettok(NULL, "|\n"); if (!eservice) continue; if (*eservice == '=') { char *key = (char *)malloc(strlen(ehost) + 2); char *pointsto = strdup(eservice+1); sprintf(key, "%s=", ehost); status = rbtInsert(rbconf, key, pointsto); } else { estart = gettok(NULL, "|\n"); if (!estart) continue; eend = gettok(NULL, "|\n"); if (!eend) continue; etime = gettok(NULL, "|\n"); if (!etime) continue; ttprio = atoi(gettok(NULL, "|\n")); if (ttprio == 0) continue; ttgroup = gettok(NULL, "|\n"); ttextra = gettok(NULL, "|\n"); updinfo = gettok(NULL, "|\n"); newitem = (nkconf_t *)malloc(sizeof(nkconf_t)); newitem->key = (char *)malloc(strlen(ehost) + strlen(eservice) + 15); sprintf(newitem->key, "%s|%s", ehost, eservice); newitem->starttime= ((estart && *estart) ? atoi(estart) : 0); newitem->endtime = ((eend && *eend) ? atoi(eend) : 0); newitem->nktime = ((etime && *etime) ? strdup(etime) : NULL); newitem->priority = ttprio; newitem->ttgroup = strdup(ttgroup); newitem->ttextra = strdup(ttextra); newitem->updinfo = strdup(updinfo); status = rbtInsert(rbconf, newitem->key, newitem); while (status == RBT_STATUS_DUPLICATE_KEY) { idx++; sprintf(newitem->key, "%s|%s|%d", ehost, eservice, idx); status = rbtInsert(rbconf, newitem->key, newitem); } } } stackfclose(fd); freestrbuffer(inbuf); if (debug) { RbtHandle handle; handle = rbtBegin(rbconf); while (handle != rbtEnd(rbconf)) { void *k1, *k2; rbtKeyValue(rbconf, handle, &k1, &k2); printf("%s\n", (char *)k1); handle = rbtNext(rbconf, handle); } } return 0; }
int load_hostnames(char *bbhostsfn, char *extrainclude, int fqdn) { /* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */ static void *bbhfiles = NULL; FILE *bbhosts; int ip1, ip2, ip3, ip4, groupid, pageidx; char hostname[4096]; strbuffer_t *inbuf; pagelist_t *curtoppage, *curpage, *pgtail; namelist_t *nametail = NULL; RbtHandle htree; /* First check if there were no modifications at all */ if (bbhfiles) { if (!stackfmodified(bbhfiles)){ dbgprintf("No files modified, skipping reload of %s\n", bbhostsfn); return 1; } else { stackfclist(&bbhfiles); bbhfiles = NULL; } } MEMDEFINE(hostname); MEMDEFINE(l); configloaded = 1; initialize_hostlist(); curpage = curtoppage = pgtail = pghead; pageidx = groupid = 0; bbhosts = stackfopen(bbhostsfn, "r", &bbhfiles); if (bbhosts == NULL) return -1; inbuf = newstrbuffer(0); htree = rbtNew(name_compare); while (stackfgets(inbuf, extrainclude)) { sanitize_input(inbuf, 0, 0); if (strncmp(STRBUF(inbuf), "page", 4) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (get_page_name_title(STRBUF(inbuf), "page", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = strdup(name); newp->pagetitle = (title ? strdup(title) : NULL); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = curtoppage = newp; } } else if (strncmp(STRBUF(inbuf), "subpage", 7) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (get_page_name_title(STRBUF(inbuf), "subpage", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(curtoppage->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", curtoppage->pagepath, name); newp->pagetitle = malloc(strlen(curtoppage->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", curtoppage->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(STRBUF(inbuf), "subparent", 9) == 0) { pagelist_t *newp, *parent; char *pname, *name, *title; pageidx = groupid = 0; parent = NULL; if (get_page_name_title(STRBUF(inbuf), "subparent", &pname, &title) == 0) { for (parent = pghead; (parent && !pagematch(parent, pname)); parent = parent->next); } if (parent && (get_page_name_title(title, "", &name, &title) == 0)) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(parent->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", parent->pagepath, name); newp->pagetitle = malloc(strlen(parent->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", parent->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(STRBUF(inbuf), "group", 5) == 0) { groupid++; } else if (sscanf(STRBUF(inbuf), "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) { char *startoftags, *tag, *delim; int elemidx, elemsize; char clientname[4096]; char downtime[4096]; char groupidstr[10]; RbtIterator handle; namelist_t *newitem = calloc(1, sizeof(namelist_t)); namelist_t *iwalk, *iprev; MEMDEFINE(clientname); MEMDEFINE(downtime); /* Hostname beginning with '@' are "no-display" hosts. But we still want them. */ if (*hostname == '@') memmove(hostname, hostname+1, strlen(hostname)); if (!fqdn) { /* Strip any domain from the hostname */ char *p = strchr(hostname, '.'); if (p) *p = '\0'; } sprintf(newitem->ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); sprintf(groupidstr, "%d", groupid); newitem->groupid = strdup(groupidstr); newitem->pageindex = pageidx++; newitem->bbhostname = strdup(hostname); if (ip1 || ip2 || ip3 || ip4) newitem->preference = 1; else newitem->preference = 0; newitem->logname = strdup(newitem->bbhostname); { char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } } newitem->page = curpage; newitem->defaulthost = defaulthost; clientname[0] = downtime[0] = '\0'; startoftags = strchr(STRBUF(inbuf), '#'); if (startoftags == NULL) startoftags = ""; else startoftags++; startoftags += strspn(startoftags, " \t\r\n"); newitem->allelems = strdup(startoftags); elemsize = 5; newitem->elems = (char **)malloc((elemsize+1)*sizeof(char *)); tag = newitem->allelems; elemidx = 0; while (tag && *tag) { if (elemidx == elemsize) { elemsize += 5; newitem->elems = (char **)realloc(newitem->elems, (elemsize+1)*sizeof(char *)); } newitem->elems[elemidx] = tag; /* Skip until we hit a whitespace or a quote */ tag += strcspn(tag, " \t\r\n\""); if (*tag == '"') { delim = tag; /* Hit a quote - skip until the next matching quote */ tag = strchr(tag+1, '"'); if (tag != NULL) { /* Found end-quote, NULL the item here and move on */ *tag = '\0'; tag++; } /* Now move quoted data one byte down (including the NUL) to kill quotechar */ memmove(delim, delim+1, strlen(delim)); } else if (*tag) { /* Normal end of item, NULL it and move on */ *tag = '\0'; tag++; } else { /* End of line - no more to do. */ tag = NULL; } /* * If we find a "noconn", drop preference value to 0. * If we find a "prefer", up reference value to 2. */ if ((newitem->preference == 1) && (strcmp(newitem->elems[elemidx], "noconn") == 0)) newitem->preference = 0; else if (strcmp(newitem->elems[elemidx], "prefer") == 0) newitem->preference = 2; /* Skip whitespace until start of next tag */ if (tag) tag += strspn(tag, " \t\r\n"); elemidx++; } newitem->elems[elemidx] = NULL; /* See if this host is defined before */ handle = rbtFind(htree, newitem->bbhostname); if (strcasecmp(newitem->bbhostname, ".default.") == 0) { /* The pseudo DEFAULT host */ newitem->next = NULL; defaulthost = newitem; } else if (handle == rbtEnd(htree)) { /* New item, so add to end of list */ newitem->next = NULL; if (namehead == NULL) namehead = nametail = newitem; else { nametail->next = newitem; nametail = newitem; } rbtInsert(htree, newitem->bbhostname, newitem); } else { /* Find the existing record - compare the record pointer instead of the name */ namelist_t *existingrec = (namelist_t *)gettreeitem(htree, handle); for (iwalk = namehead, iprev = NULL; ((iwalk != existingrec) && iwalk); iprev = iwalk, iwalk = iwalk->next) ; if (newitem->preference <= iwalk->preference) { /* Add after the existing (more preferred) entry */ newitem->next = iwalk->next; iwalk->next = newitem; } else { /* New item has higher preference, so add before the iwalk item (i.e. after iprev) */ if (iprev == NULL) { newitem->next = namehead; namehead = newitem; } else { newitem->next = iprev->next; iprev->next = newitem; } } } newitem->clientname = bbh_find_item(newitem, BBH_CLIENTALIAS); if (newitem->clientname == NULL) newitem->clientname = newitem->bbhostname; newitem->downtime = bbh_find_item(newitem, BBH_DOWNTIME); MEMUNDEFINE(clientname); MEMUNDEFINE(downtime); } } stackfclose(bbhosts); freestrbuffer(inbuf); rbtDelete(htree); MEMUNDEFINE(hostname); MEMUNDEFINE(l); build_hosttree(); return 0; }
void load_clientconfig(void) { static char *configfn = NULL; static void *clientconflist = NULL; FILE *fd; strbuffer_t *buf; char *sectstart; if (!configfn) { configfn = (char *)malloc(strlen(xgetenv("XYMONHOME"))+ strlen("/etc/client-local.cfg") + 1); sprintf(configfn, "%s/etc/client-local.cfg", xgetenv("XYMONHOME")); } /* First check if there were no modifications at all */ if (clientconflist) { if (!stackfmodified(clientconflist)){ dbgprintf("No files modified, skipping reload of %s\n", configfn); return; } else { stackfclist(&clientconflist); clientconflist = NULL; } } if (!clientconfigs) { clientconfigs = newstrbuffer(0); } else { xtreeDestroy(rbconfigs); clearstrbuffer(clientconfigs); } rbconfigs = xtreeNew(strcasecmp); addtobuffer(clientconfigs, "\n"); buf = newstrbuffer(0); fd = stackfopen(configfn, "r", &clientconflist); if (!fd) return; while (stackfgets(buf, NULL)) addtostrbuffer(clientconfigs, buf); stackfclose(fd); sectstart = strstr(STRBUF(clientconfigs), "\n["); while (sectstart) { char *key, *nextsect; sectstart += 2; key = sectstart; sectstart += strcspn(sectstart, "]\n"); if (*sectstart == ']') { *sectstart = '\0'; sectstart++; sectstart += strcspn(sectstart, "\n"); } nextsect = strstr(sectstart, "\n["); if (nextsect) *(nextsect+1) = '\0'; xtreeAdd(rbconfigs, key, sectstart+1); sectstart = nextsect; } freestrbuffer(buf); }
int load_alertconfig(char *configfn, int defcolors, int defaultinterval) { /* (Re)load the configuration file without leaking memory */ static void *configfiles = NULL; char fn[PATH_MAX]; FILE *fd; strbuffer_t *inbuf; char *p; rule_t *currule = NULL; recip_t *currcp = NULL, *rcptail = NULL; MEMDEFINE(fn); if (configfn) strcpy(fn, configfn); else sprintf(fn, "%s/etc/alerts.cfg", xgetenv("XYMONHOME")); /* First check if there were no modifications at all */ if (configfiles) { if (!stackfmodified(configfiles)){ dbgprintf("No files modified, skipping reload of %s\n", fn); MEMUNDEFINE(fn); return 0; } else { stackfclist(&configfiles); configfiles = NULL; } } fd = stackfopen(fn, "r", &configfiles); if (!fd) { errprintf("Cannot open configuration file %s: %s\n", fn, strerror(errno)); MEMUNDEFINE(fn); return 0; } /* First, clean out the old rule set */ while (rulehead) { rule_t *trule; if (rulehead->criteria) { free_criteria(rulehead->criteria); xfree(rulehead->criteria); } while (rulehead->recipients) { recip_t *trecip = rulehead->recipients; if (trecip->criteria) { recip_t *rwalk; /* Clear out the duplicate criteria that may exist, to avoid double-free'ing them */ for (rwalk = trecip->next; (rwalk); rwalk = rwalk->next) { if (rwalk->criteria == trecip->criteria) rwalk->criteria = NULL; } free_criteria(trecip->criteria); xfree(trecip->criteria); } if (trecip->recipient) xfree(trecip->recipient); if (trecip->scriptname) xfree(trecip->scriptname); rulehead->recipients = rulehead->recipients->next; xfree(trecip); } trule = rulehead; rulehead = rulehead->next; xfree(trule); } while (tokhead) { token_t *ttok; if (tokhead->name) xfree(tokhead->name); if (tokhead->value) xfree(tokhead->value); ttok = tokhead; tokhead = tokhead->next; xfree(ttok); } defaultcolors = defcolors; MEMDEFINE(cfline); cfid = 0; inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { int firsttoken = 1; int mailcmdactive = 0, scriptcmdactive = 0; recip_t *curlinerecips = NULL; cfid++; sanitize_input(inbuf, 1, 0); /* Skip empty lines */ if (STRBUFLEN(inbuf) == 0) continue; if ((*STRBUF(inbuf) == '$') && strchr(STRBUF(inbuf), '=')) { /* Define a macro */ token_t *newtok = (token_t *) malloc(sizeof(token_t)); char *delim; delim = strchr(STRBUF(inbuf), '='); *delim = '\0'; newtok->name = strdup(STRBUF(inbuf)+1); /* Skip the '$' */ newtok->value = strdup(preprocess(delim+1)); newtok->next = tokhead; tokhead = newtok; continue; } strncpy(cfline, STRBUF(inbuf), (sizeof(cfline)-1)); cfline[sizeof(cfline)-1] = '\0'; /* Expand macros inside the line before parsing */ p = strtok(preprocess(STRBUF(inbuf)), " \t"); while (p) { if ((strncasecmp(p, "PAGE=", 5) == 0) || (strncasecmp(p, "PAGES=", 6) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->pagespec = strdup(val); if (*(crit->pagespec) == '%') crit->pagespecre = compileregex(crit->pagespec+1); firsttoken = 0; } else if ((strncasecmp(p, "EXPAGE=", 7) == 0) || (strncasecmp(p, "EXPAGES=", 8) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->expagespec = strdup(val); if (*(crit->expagespec) == '%') crit->expagespecre = compileregex(crit->expagespec+1); firsttoken = 0; } else if ((strncasecmp(p, "DISPLAYGROUP=", 13) == 0) || (strncasecmp(p, "DISPLAYGROUPS=", 14) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->dgspec = strdup(val); if (*(crit->dgspec) == '%') crit->dgspecre = compileregex(crit->dgspec+1); firsttoken = 0; } else if ((strncasecmp(p, "EXDISPLAYGROUP=", 15) == 0) || (strncasecmp(p, "EXDISPLAYGROUPS=", 16) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->exdgspec = strdup(val); if (*(crit->exdgspec) == '%') crit->exdgspecre = compileregex(crit->exdgspec+1); firsttoken = 0; } else if ((strncasecmp(p, "HOST=", 5) == 0) || (strncasecmp(p, "HOSTS=", 6) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->hostspec = strdup(val); if (*(crit->hostspec) == '%') crit->hostspecre = compileregex(crit->hostspec+1); firsttoken = 0; } else if ((strncasecmp(p, "EXHOST=", 7) == 0) || (strncasecmp(p, "EXHOSTS=", 8) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->exhostspec = strdup(val); if (*(crit->exhostspec) == '%') crit->exhostspecre = compileregex(crit->exhostspec+1); firsttoken = 0; } else if ((strncasecmp(p, "SERVICE=", 8) == 0) || (strncasecmp(p, "SERVICES=", 9) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->svcspec = strdup(val); if (*(crit->svcspec) == '%') crit->svcspecre = compileregex(crit->svcspec+1); firsttoken = 0; } else if ((strncasecmp(p, "EXSERVICE=", 10) == 0) || (strncasecmp(p, "EXSERVICES=", 11) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->exsvcspec = strdup(val); if (*(crit->exsvcspec) == '%') crit->exsvcspecre = compileregex(crit->exsvcspec+1); firsttoken = 0; } else if (strncasecmp(p, "CLASS=", 6) == 0) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->classspec = strdup(val); if (*(crit->classspec) == '%') crit->classspecre = compileregex(crit->classspec+1); firsttoken = 0; } else if (strncasecmp(p, "EXCLASS=", 8) == 0) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->exclassspec = strdup(val); if (*(crit->exclassspec) == '%') crit->exclassspecre = compileregex(crit->exclassspec+1); firsttoken = 0; } else if (strncasecmp(p, "GROUP=", 6) == 0) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->groupspec = strdup(val); if (*(crit->groupspec) == '%') crit->groupspecre = compileregex(crit->groupspec+1); firsttoken = 0; } else if (strncasecmp(p, "EXGROUP=", 8) == 0) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->exgroupspec = strdup(val); if (*(crit->exgroupspec) == '%') crit->exgroupspecre = compileregex(crit->exgroupspec+1); firsttoken = 0; } else if ((strncasecmp(p, "COLOR=", 6) == 0) || (strncasecmp(p, "COLORS=", 7) == 0)) { criteria_t *crit; char *c1, *c2; int cval, reverse = 0; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); /* Put a value in crit->colors so we know there is an explicit color setting */ crit->colors = (1 << 30); c1 = strchr(p, '=')+1; /* * If the first colorspec is "!color", then apply the default colors and * subtract colors from that. */ if (*c1 == '!') crit->colors |= defaultcolors; do { c2 = strchr(c1, ','); if (c2) *c2 = '\0'; if (*c1 == '!') { reverse=1; c1++; } cval = (1 << parse_color(c1)); if (reverse) crit->colors &= (~cval); else crit->colors |= cval; if (c2) c1 = (c2+1); else c1 = NULL; } while (c1); firsttoken = 0; } else if ((strncasecmp(p, "TIME=", 5) == 0) || (strncasecmp(p, "TIMES=", 6) == 0)) { char *val; criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } val = strchr(p, '=')+1; crit = setup_criteria(&currule, &currcp); crit->timespec = strdup(val); firsttoken = 0; } else if (strncasecmp(p, "DURATION", 8) == 0) { criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); if (*(p+8) == '>') crit->minduration = 60*durationvalue(p+9); else if (*(p+8) == '<') crit->maxduration = 60*durationvalue(p+9); else errprintf("Ignoring invalid DURATION at line %d: %s\n",cfid, p); firsttoken = 0; } else if (strncasecmp(p, "RECOVERED", 9) == 0) { criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); crit->sendrecovered = SR_WANTED; firsttoken = 0; } else if (strncasecmp(p, "NORECOVERED", 11) == 0) { criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); crit->sendrecovered = SR_NOTWANTED; firsttoken = 0; } else if (strncasecmp(p, "NOTICE", 6) == 0) { criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); crit->sendnotice = SR_WANTED; firsttoken = 0; } else if (strncasecmp(p, "NONOTICE", 8) == 0) { criteria_t *crit; if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; } crit = setup_criteria(&currule, &currcp); crit->sendnotice = SR_NOTWANTED; firsttoken = 0; } else if ((pstate == P_RECIP) && (strncasecmp(p, "FORMAT=", 7) == 0)) { if (!currcp) errprintf("FORMAT used without a recipient (line %d), ignored\n", cfid); else if (strcasecmp(p+7, "TEXT") == 0) currcp->format = ALERTFORM_TEXT; else if (strcasecmp(p+7, "PLAIN") == 0) currcp->format = ALERTFORM_PLAIN; else if (strcasecmp(p+7, "SMS") == 0) currcp->format = ALERTFORM_SMS; else if (strcasecmp(p+7, "PAGER") == 0) currcp->format = ALERTFORM_PAGER; else if (strcasecmp(p+7, "SCRIPT") == 0) currcp->format = ALERTFORM_SCRIPT; else errprintf("Unknown FORMAT setting '%s' ignored\n", p); firsttoken = 0; } else if ((pstate == P_RECIP) && (strncasecmp(p, "REPEAT=", 7) == 0)) { if (!currcp) errprintf("REPEAT used without a recipient (line %d), ignored\n", cfid); else currcp->interval = 60*durationvalue(p+7); firsttoken = 0; } else if ((pstate == P_RECIP) && (strcasecmp(p, "STOP") == 0)) { if (!currcp) errprintf("STOP used without a recipient (line %d), ignored\n", cfid); else currcp->stoprule = 1; firsttoken = 0; } else if ((pstate == P_RECIP) && (strcasecmp(p, "UNMATCHED") == 0)) { if (!currcp) errprintf("UNMATCHED used without a recipient (line %d), ignored\n", cfid); else currcp->unmatchedonly = 1; firsttoken = 0; } else if ((pstate == P_RECIP) && (strncasecmp(p, "NOALERT", 7) == 0)) { if (!currcp) errprintf("NOALERT used without a recipient (line %d), ignored\n", cfid); else currcp->noalerts = 1; firsttoken = 0; } else if (currule && ((strncasecmp(p, "MAIL", 4) == 0) || mailcmdactive) ) { recip_t *newrcp; mailcmdactive = 1; newrcp = (recip_t *)calloc(1, sizeof(recip_t)); newrcp->cfid = cfid; newrcp->method = M_MAIL; newrcp->format = ALERTFORM_TEXT; if (strncasecmp(p, "MAIL=", 5) == 0) { p += 5; } else if (strcasecmp(p, "MAIL") == 0) { p = strtok(NULL, " \t"); } else { /* Second recipient on a rule - do nothing */ } if (p) { newrcp->recipient = strdup(p); newrcp->interval = defaultinterval; currcp = newrcp; if (curlinerecips == NULL) curlinerecips = newrcp; pstate = P_RECIP; if (currule->recipients == NULL) currule->recipients = rcptail = newrcp; else { rcptail->next = newrcp; rcptail = newrcp; } } else { errprintf("Ignoring MAIL with no recipient at line %d\n", cfid); xfree(newrcp); } firsttoken = 0; } else if (currule && ((strncasecmp(p, "SCRIPT", 6) == 0) || scriptcmdactive)) { recip_t *newrcp; scriptcmdactive = 1; newrcp = (recip_t *)calloc(1, sizeof(recip_t)); newrcp->cfid = cfid; newrcp->method = M_SCRIPT; newrcp->format = ALERTFORM_SCRIPT; if (strncasecmp(p, "SCRIPT=", 7) == 0) { p += 7; newrcp->scriptname = strdup(p); p = strtok(NULL, " \t"); } else if (strcasecmp(p, "SCRIPT") == 0) { p = strtok(NULL, " \t"); if (p) { newrcp->scriptname = strdup(p); p = strtok(NULL, " \t"); } else { errprintf("Invalid SCRIPT command at line %d\n", cfid); } } else { /* A second recipient for the same script as the previous one */ newrcp->scriptname = strdup(currcp->scriptname); } if (p) { newrcp->recipient = strdup(p); newrcp->interval = defaultinterval; currcp = newrcp; if (curlinerecips == NULL) curlinerecips = newrcp; pstate = P_RECIP; if (currule->recipients == NULL) currule->recipients = rcptail = newrcp; else { rcptail->next = newrcp; rcptail = newrcp; } } else { errprintf("Ignoring SCRIPT with no recipient at line %d\n", cfid); if (newrcp->scriptname) xfree(newrcp->scriptname); xfree(newrcp); } firsttoken = 0; } else if (currule && (strncasecmp(p, "IGNORE", 6) == 0)) { recip_t *newrcp; newrcp = (recip_t *)calloc(1, sizeof(recip_t)); newrcp->cfid = cfid; newrcp->method = M_IGNORE; newrcp->format = ALERTFORM_NONE; newrcp->interval = defaultinterval; newrcp->stoprule = 1; currcp = newrcp; if (curlinerecips == NULL) curlinerecips = newrcp; pstate = P_RECIP; if (currule->recipients == NULL) currule->recipients = rcptail = newrcp; else { rcptail->next = newrcp; rcptail = newrcp; } firsttoken = 0; } else { errprintf("Ignored unknown/unexpected token '%s' at line %d\n", p, cfid); } if (p) p = strtok(NULL, " \t"); } if (curlinerecips && currcp && (curlinerecips != currcp)) { /* We have multiple recipients on one line. Make sure criteria etc. get copied */ recip_t *rwalk; /* All criteria etc. have been set on the last recipient (currcp) */ for (rwalk = curlinerecips; (rwalk != currcp); rwalk = rwalk->next) { rwalk->format = currcp->format; rwalk->interval = currcp->interval; rwalk->criteria = currcp->criteria; rwalk->noalerts = currcp->noalerts; } } } flush_rule(currule); stackfclose(fd); freestrbuffer(inbuf); MEMUNDEFINE(cfline); MEMUNDEFINE(fn); return 1; }