277 lines
5.3 KiB
C
277 lines
5.3 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"
|
|
|
|
/* Too many strings to keep track of, no time for garbage collection. */
|
|
/* Enter them in a binary tree... */
|
|
/* str_enter MUST NOT be called while any string in the tree is temporarily
|
|
modified. No string in the tree may be permanently modified in ANY way. */
|
|
char *str_enter(char *master)
|
|
{
|
|
struct string **str = &stringdb;
|
|
struct string *st = *str;
|
|
|
|
if(master == NULL)
|
|
return NULL;
|
|
while(st != NULL) {
|
|
int sc;
|
|
if(st->data == master)
|
|
return master;
|
|
sc = strcmp(master,st->data);
|
|
if(sc == 0)
|
|
return st->data;
|
|
else if(sc < 0)
|
|
str = &st->left;
|
|
else
|
|
str = &st->right;
|
|
st = *str;
|
|
}
|
|
st = malloc(sizeof(struct string)+strlen(master));
|
|
if(st == NULL)
|
|
return NULL;
|
|
|
|
strcpy(st->data,master);
|
|
st->left = st->right = NULL;
|
|
*str = st;
|
|
chkone(st);
|
|
return st->data;
|
|
}
|
|
|
|
/* Simpleminded, bidirectional wildmat().
|
|
If both strings are patterns, this doesn't work. Unfortunately, pattern
|
|
joining is obviously NP-complete, and I don't know any algorithms to do it
|
|
anyway. */
|
|
char *wildmatch(char *a, char *b)
|
|
{
|
|
if(a == NULL)
|
|
return b;
|
|
else if(b == NULL)
|
|
return a;
|
|
else if(wildmat(a,b))
|
|
return a;
|
|
else if(wildmat(b,a))
|
|
return b;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/* Given a string aaa+bbb, return aaa. */
|
|
char *
|
|
strippat(char *a)
|
|
{
|
|
char aa[30];
|
|
char *aplus = strchr(a,'+');
|
|
|
|
if(aplus == NULL)
|
|
return a;
|
|
*aplus = '\0';
|
|
strcpy(aa,a);
|
|
*aplus = '+';
|
|
return str_enter(aa);
|
|
}
|
|
|
|
/* Given strings +aaa+bbb and +ccc+aaa, return +aaa+bbb+ccc. */
|
|
static char *
|
|
pluscat(char *a, char *b)
|
|
{
|
|
if(a == NULL)
|
|
return b;
|
|
if(b == NULL)
|
|
return a;
|
|
if(*a != '+')
|
|
return b;
|
|
if(*b != '+')
|
|
return a;
|
|
{
|
|
char classpat[50];
|
|
char *classind = classpat;
|
|
strcpy(classpat,a);
|
|
while(*classind) {
|
|
if(*classind == '+')
|
|
*classind = '\0';
|
|
classind++;
|
|
}
|
|
{
|
|
char *bnext = b;
|
|
do {
|
|
b = bnext + 1;
|
|
bnext = strchr(b,'+');
|
|
if(bnext != NULL) *bnext = '\0';
|
|
for(a = classpat+1; a < classind; a += strlen(a)+1)
|
|
if(strcmp(a,b) == 0)
|
|
break;
|
|
if(a >= classind) {
|
|
strcpy(classind+1,b);
|
|
classind += strlen(b)+1;
|
|
}
|
|
if(bnext != NULL) *bnext = '+';
|
|
} while(bnext != NULL);
|
|
for(a = classpat; a < classind; a += strlen(a))
|
|
*a++ = '+';
|
|
*a = '\0';
|
|
return str_enter(classpat);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ulong_t
|
|
maskmatch(ulong_t a, ulong_t b)
|
|
{
|
|
return a & b;
|
|
}
|
|
|
|
/* "abc" "bcd" -> "bc" */
|
|
/* "abc+bc" "bcd+b" -> "bc+bc+b" */
|
|
/* "abc+bc" "bcd+d" -> NULL */
|
|
/* It is of course possible to optimize all of this, but it's not worth the
|
|
work. */
|
|
char *
|
|
classmatch(char *a, char *b)
|
|
{
|
|
if(a == NULL)
|
|
return NULL;
|
|
if(b == NULL)
|
|
return NULL;
|
|
if(*b == '*' || *b == '\0')
|
|
return a;
|
|
if(*a == '*' || *a == '\0')
|
|
return b;
|
|
if(*a == '+' || *b == '+') {
|
|
if(*a == '+' && *b == '+') {
|
|
char classpat[50];
|
|
if(strcmp(a,b) == 0)
|
|
return a;
|
|
strcpy(classpat,a);
|
|
strcat(classpat,b);
|
|
return str_enter(classpat);
|
|
} else {
|
|
char *aorig,*bplus;
|
|
if(*a != '+') {
|
|
char *tmp = a; a = b; b = tmp;
|
|
}
|
|
if((bplus=strchr(b,'+')) != NULL) *bplus='\0';
|
|
aorig = a;
|
|
if(strlen(a) == 2) { /* Obvious optimization */
|
|
a = classmatch(b,a+1);
|
|
if(bplus != NULL) *bplus = '+';
|
|
return a;
|
|
}
|
|
do {
|
|
while(*++a != '\0' && *a != '+') {
|
|
if(strchr(b,*a) != NULL)
|
|
break;
|
|
}
|
|
if(*a == '\0' || *a == '+') {
|
|
if(bplus != NULL) *bplus='+';
|
|
return NULL;
|
|
}
|
|
} while((a = strchr(a,'+')) != NULL);
|
|
{
|
|
char classpat[50];
|
|
strcpy(classpat,b);
|
|
if(bplus != NULL)
|
|
*bplus='+';
|
|
strcat(classpat,pluscat(aorig,bplus));
|
|
return str_enter(classpat);
|
|
}
|
|
}
|
|
} else {
|
|
char classpat[30];
|
|
char *classind = classpat;
|
|
char *aplus, *bplus;
|
|
if((aplus=strchr(a,'+')) != NULL) *aplus='\0';
|
|
if((bplus=strchr(b,'+')) != NULL) *bplus='\0';
|
|
while(*a != 0) {
|
|
if(strchr(b,*a) != NULL)
|
|
*classind++ = *a;
|
|
a++;
|
|
}
|
|
if(aplus != NULL) *aplus='+';
|
|
if(bplus != NULL) *bplus='+';
|
|
if(classpat == classind)
|
|
return NULL;
|
|
*classind = 0;
|
|
/* If the class is one character long, there's not much point
|
|
in carrying around all the baggage. */
|
|
if((classind > classpat+1) && (aplus != NULL || bplus != NULL))
|
|
return classmatch(str_enter(classpat),pluscat(aplus,bplus));
|
|
else
|
|
return str_enter(classpat);
|
|
}
|
|
}
|
|
|
|
/* Put something into the environment. */
|
|
|
|
void
|
|
putenv2 (const char *key, const char *val)
|
|
{
|
|
char *xx = (char *)malloc (strlen (key) + strlen (val) + 2);
|
|
|
|
if (xx != NULL) {
|
|
sprintf (xx, "%s=%s", key, val);
|
|
putenv (xx);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Xbreak(void) { }
|
|
|
|
void
|
|
xquit (const char *s, const char *t)
|
|
{
|
|
if (s != NULL)
|
|
syslog (LOG_WARNING, "%s %s: %m", s, t ? t : "");
|
|
abort();
|
|
}
|
|
|
|
void panic(const char *x, ...)
|
|
{
|
|
*((char *)0xdeadbeef) = 0; /* Crash */
|
|
}
|
|
|
|
|
|
void
|
|
dropdead(void)
|
|
{
|
|
if(zzconn != NULL && zzconn->cg != NULL)
|
|
syslog(LOG_ERR, "Startup of %s:%s cancelled --
|
|
timeout",zzconn->cg->site,zzconn->cg->protocol);
|
|
else
|
|
syslog(LOG_ERR, "Startup cancelled because of a timeout!");
|
|
exit(9);
|
|
}
|
|
|
|
void
|
|
log_idle (void *xxx)
|
|
{
|
|
syslog (LOG_DEBUG, "ISDN is still alive.");
|
|
timeout (log_idle, NULL, 10 * 60 * HZ);
|
|
}
|
|
|
|
void
|
|
queue_idle (void *xxx)
|
|
{
|
|
runqueues (); runqueues();
|
|
timeout (queue_idle, NULL, HZ/2);
|
|
}
|
|
|
|
void
|
|
alarmsig(void)
|
|
{
|
|
printf("Dead");
|
|
}
|
|
|
|
void
|
|
do_quitnow(void *nix)
|
|
{
|
|
quitnow = 1;
|
|
kill_progs(NULL);
|
|
}
|