/* * This file is part of the ISDN master program. * * Copyright (C) 1995 Matthias Urlichs. * See the file COPYING for license details. */ #include "master.h" static int seqnum; /* Read a line, handle empty lines and continuations. */ struct _cf * read_line (FILE * ffile, int *theLine) { char line[MAXLINE]; char *sofar = line; struct _cf *out; int remain = MAXLINE; int now; do { now = 0; while (remain > 3 && !feof (ffile) && fgets (sofar, remain - 1, ffile) != NULL) { now = strlen (sofar); if (now == 0) break; if (sofar[now - 1] != '\n') return NULL; (*theLine)++; if (sofar[now - 2] == '\\') { sofar += now - 2; remain -= now - 2; } else { sofar += now - 1; *sofar = '\0'; break; } } if (*line == '#' || *line == '\n') { sofar = line; *line = '\0'; remain = MAXLINE; } } while (sofar == line && now > 0); if (sofar == line || remain <= 3 || now == 0) return NULL; *sofar = '\0'; out = (struct _cf *)gxmalloc (sizeof (struct _cf) + (now = sofar - line + 1)); bcopy (line, (char *) (out + 1), now); bzero ((char *) out, sizeof (struct _cf)); return out; } /* Append a config entry to a list of config entries. */ static void app (cf * where, cf who) { char *x = (char *) who + 1; while (*x != '\0' && !isspace (*x)) { x++; } #if 1 while (*where != NULL) where = &((*where)->next); *where = who; who->next = NULL; #else who->next = *where; *where = who; #endif } /* Skip spaces */ static int skipsp (char **li) { char *x = *li; while (*x != ' ' && *x != '\t' && *x != '\0') x++; if (*x == '\0') return 1; *x++ = '\0'; while (*x == ' ' || *x == '\t') x++; *li = x; return 0; } #ifdef unused static void skipword (char **li) { char *x = *li; while (*x != ' ' && *x != '\t' && *x != '\0') x++; *li = x; } #endif void do_subclass(cf c) { char *info; if((info = strchr(c->card,'/')) != NULL) { char neg; int x = 0; *info++ = '\0'; neg = (*info == '-'); c->mask = neg ? ~0 : 0; while(*info != 0) { if(*info >= '0' && *info <= '9') { x = x * 10 + *info - '0'; } else if(x != 0) { if(neg) c->mask |= 1<<(x-1); else c->mask &=~ (1<<(x-1)); x = 0; } info++; } } else c->mask = ~0; } /* Read a config file */ void read_file (FILE * ffile, char *errf) { cf c; int errl = 0; syslog (LOG_INFO, "Reading %s", errf); while ((c = read_line (ffile, &errl)) != NULL) { char *li = (char *) (c + 1); switch (CHAR2 (li[0], li[1])) { case CHAR2 ('M', 'O'): continue; case CHAR2 ('P', ' '): case CHAR2 ('P', '_'): case CHAR2 ('P', '\t'): /* P */ { char *pri; if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) c->args = ""; else c->args = li; if((pri = strchr(c->type,',')) != NULL) c->num = atoi(pri); if((pri = strchr(c->type,'.')) != NULL) c->num2 = atoi(pri); do_subclass(c); chkone(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->args = str_enter(c->args); app (&cf_P, c); } continue; case CHAR2 ('M', 'L'): /* ML */ if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) break; c->args = li; { char *sp = strchr(c->type,','); if(sp != NULL) { *sp++=0; if ((c->num = atoi (sp)) == 0 && sp[0] != '0') break; } } do_subclass(c); chkone(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->args = str_enter(c->args); app (&cf_ML, c); continue; case CHAR2 ('M', 'P'): /* ML */ if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) break; c->arg = li; if (skipsp (&li)) break; c->args = li; chkone(c); do_subclass(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->arg = str_enter(c->arg); c->args = str_enter(c->args); app (&cf_MP, c); continue; case CHAR2 ('D', ' '): case CHAR2 ('D', '_'): case CHAR2 ('D', '\t'): { char *pri; /* D */ if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->type = li; if (!skipsp (&li)) { c->arg = li; if(!skipsp(&li)) break; } if((pri = strchr(c->type,',')) != NULL) c->num = atoi(pri); chkone(c); do_subclass(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->arg = str_enter(c->arg); app (&cf_D, c); } continue; case CHAR2 ('T', 'M'): /* TM */ if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->arg = li; if (!skipsp (&li)) break; while(isspace(c->arg[strlen(c->arg)-1])) c->arg[strlen(c->arg)-1] = '\0'; if (isintime(c->arg) < 0) break; chkone(c); c->cclass = str_enter(c->cclass); c->arg = str_enter(c->arg); app (&cf_TM, c); continue; case CHAR2 ('D', 'L'): /* DL */ if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->arg = li; if (skipsp (&li)) c->args = ""; else { c->args = li; while(isspace(c->args[strlen(c->args)-1])) c->args[strlen(c->args)-1] = '\0'; } chkone(c); do_subclass(c); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->arg = str_enter(c->arg); c->args = str_enter(c->args); app (&cf_DL, c); continue; case CHAR2 ('D', 'P'): /* DP */ if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->arg = li; if (skipsp (&li)) c->args = c->arg; else { c->args = li; while(isspace(c->args[strlen(c->args)-1])) c->args[strlen(c->args)-1] = '\0'; } if(c->args[0] == '\0') c->args = c->arg; chkone(c); do_subclass(c); c->card = str_enter(c->card); c->arg = str_enter(c->arg); c->args = str_enter(c->args); app (&cf_DP, c); continue; case CHAR2 ('R', ' '): case CHAR2 ('R', '_'): case CHAR2 ('R', '\t'): { char *username; struct passwd *pw; if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; username = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) break; c->args = li; if ((pw = getpwnam (username)) == NULL) break; chkone(c); do_subclass(c); c->num = pw->pw_uid; c->num2 = pw->pw_gid; c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->args = str_enter(c->args); app (&cf_R, c); } continue; case CHAR2 ('R', 'P'): { char *username; struct passwd *pw; if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; username = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) break; c->args = li; if ((pw = getpwnam (username)) == NULL) break; chkone(c); do_subclass(c); c->num = pw->pw_uid; c->num2 = pw->pw_gid; c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->type = str_enter(c->type); c->args = str_enter(c->args); app (&cf_RP, c); } continue; case CHAR2 ('L', 'F'): if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; if ((c->num = atoi (li)) == 0 && li[0] != '0') break; if (skipsp (&li)) break; if ((c->num2 = atoi (li)) == 0 && li[0] != '0') break; if (skipsp (&li)) break; c->arg = li; if(!skipsp (&li)) break; chkone(c); do_subclass(c); c->card = str_enter(c->card); c->arg = str_enter(c->arg); app (&cf_LF, c); continue; case CHAR2 ('C', 'L'): if (skipsp (&li)) break; c->protocol = li; if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; if ((c->num = atoi (li)) == 0 && li[0] != '0') break;; if (!skipsp (&li)) c->args = li; chkone(c); do_subclass(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->args = str_enter(c->args); app (&cf_CL, c); continue; } syslog (LOG_ERR, "Bad line %s:%d: %s", errf, errl, (char *) (c + 1)); gfree (c); } return; } char **fileargs; /* Read all the files. */ void read_args (void *nix) { int nexttime; #ifdef NEW_TIMEOUT static long classtimer; #endif char **arg; struct conninfo *conn; conngrab cg; cf cft; #define CFREE(what) do { while(what != NULL) { cf cf2 = what->next;gfree(what);what = cf2; } } while(0) CFREE (cf_P); CFREE (cf_ML); CFREE (cf_MP); CFREE (cf_D); CFREE (cf_DL); CFREE (cf_TM); CFREE (cf_DP); CFREE (cf_R); CFREE (cf_LF); CFREE (cf_RP); CFREE (cf_C); CFREE (cf_CL); seqnum = 0; for(conn=isdn4_conn; conn != NULL; conn = conn->next) { if((cg = conn->cg) == NULL) continue; cg->dl = NULL; cg->dp = NULL; cg->ml = NULL; cg->r_ = NULL; } for (arg = fileargs; *arg != NULL; arg++) { FILE *f = fopen (*arg, "r"); if (f == NULL) xquit ("Open", *arg); read_file (f, *arg); fclose (f); } if(theclass != NULL) { #ifdef NEW_TIMEOUT untimeout(classtimer); #else untimeout(read_args_run,NULL); #endif } theclass = ""; nexttime = 32767/HZ; for(cft = cf_TM; cft != NULL; cft = cft->next) { int newnexttime; if((newnexttime = isintime(cft->arg)) > 0) { char tmstr[100], *tmptr, elm; if((newnexttime > 0) && (newnexttime < nexttime)) nexttime = newnexttime; strcpy(tmstr,cft->cclass); tmptr = tmstr + strlen(tmstr); while((elm = *theclass++) != '\0') { if(strchr(cft->cclass,elm) == NULL) { *tmptr++ = elm; *tmptr = '\0'; } } theclass = str_enter(tmstr); } } if(*theclass == '\0') theclass = "*"; if((nexttime == 0) || (nexttime > 32767/HZ)) nexttime = 32767/HZ; #ifdef NEW_TIMEOUT classtimer = #endif timeout(read_args_run,NULL,nexttime * HZ); conn = gcxmalloc(sizeof(*conn)); if(conn != NULL) { char causeInfo[100]; bzero(conn,sizeof(*conn)); conn->seqnum = ++connseq; sprintf(causeInfo,"config read, next %d", nexttime/60); conn->causeInfo = str_enter(causeInfo); conn->cause = ID_priv_Print; conn->classname = theclass; conn->next = isdn4_conn; isdn4_conn = conn; dropconn(conn); } do_run_now++; run_now(NULL); } /* Read all the files and kick off the programs. */ void read_args_run(void *nix) { read_args(NULL); do_run_now++; run_now(NULL); }