500 lines
12 KiB
C
500 lines
12 KiB
C
/*
|
|
* 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 <Art> <Partner> <Key> <Karte> <Mod> <Parameter...> */
|
|
{
|
|
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 <Art> <Partner> <Key> <Mod,#> <Modus> <Module...> */
|
|
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 <Art> <Partner> <Key> <Mod> <Modus> <Module...> */
|
|
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 <Art> <Partner> <Key> <Karte> <Mod> <Nr> */
|
|
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 <Key> <String> */
|
|
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 <Key> <Karte> <Nummer> <Protokolle> */
|
|
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 <Karte> <Nummernpräfixe-Dialout> <Nummernpräfixe-Dialin> */
|
|
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);
|
|
}
|
|
|
|
|