/* * * ISDN master program. * * Copyright (c) 1993-1995 Matthias Urlichs . */ #define MASTER_MAIN #include "master.h" #include #if __GNU_LIBRARY__ - 0 == 6 /* NOCH notwendig, fehlt in glibc */ #include _syscall1(int,mlockall,int,what); #endif int main (int argc, char *argv[]) { extern char *optarg; extern int optind; char *devnam = "/dev/isdnmon"; int pushlog = 0; int debug = 0; int x; mlockall(MCL_CURRENT | MCL_FUTURE); MALLOC_INIT(); #ifdef DO_DEBUG_MALLOC mcheck(NULL); mmtrace(); #endif { struct passwd *pw; if ((pw = getpwnam (ROOTUSER)) != NULL) { rootuser = pw->pw_uid; /* rootgroup = pw->pw_gid; */ } } chkall(); setlinebuf(stdout); setlinebuf(stderr); /* no(t much) buffering */ progname = strrchr (*argv, '/'); /* basename */ if (progname == NULL) progname = *argv; else progname++; while ((x = getopt (argc, argv, "iIf:dlLwWqQmM"))!= EOF) { switch (x) { /* * Logging. Small letters are usermode, capitals log in the kernel. * 'l' is raw data, 'w' is interpreted data, 'q' is queue info. */ case 'm': log_34 |= 1; break; case 'M': log_34 |= 2; break; case 'l': pushlog |= 1; break; case 'L': pushlog |= 2; break; case 'w': pushlog |= 4; break; case 'W': pushlog |= 8; break; case 'q': pushlog |= 16; break; case 'Q': pushlog |= 32; break; case 'd': /* do not fork */ debug = 1; break; case 'I': /* for testing */ igstdin = 0; break; case 'i': igstdin = 1; break; case 'f': /* alternate device to open */ if (getuid ()!= 0) goto usage; devnam = optarg; break; default: usage: fprintf (stderr, "Usage: %s -iIdlLwWqQmM -f masterfile cf-datei...\n", progname); fprintf (stderr, " (READ THE DOCUMENTATION if you want to know what the options mean.)\n"); exit (1); } } if(argv[optind] == NULL) goto usage; openlog (progname, debug ? LOG_PERROR : 0, LOG_LOCAL7); /* Remember all files to scan */ fileargs = &argv[optind]; read_args (NULL); /* This also schedules starting all configured programs */ seteuid (getuid ()); if (!debug) { /* Disassociate */ switch (fork ()){ case -1: xquit ("fork", NULL); case 0: break; default: exit (0); } #ifdef TIOCNOTTY { int a = open ("/dev/tty", O_RDWR); if (a >= 0) { (void) ioctl (a, TIOCNOTTY, NULL); close (a); } } #endif { int i; for (i=getdtablesize()-1;i>=0;i--) (void) close(i); } open("/dev/null",O_RDWR); dup(0); dup(0); #ifdef HAVE_SETPGRP_2 setpgrp (0, getpid ()); #endif #ifdef HAVE_SETPGRP_0 setpgrp(); #endif } { /* Switch stdout and stderr */ int fd = dup(1); dup2(2,1); dup2(fd,2); close(fd); } /* Two lockdev() calls. The first may clear a stale lock. */ if((lockdev(0,0) < 0) && (sleep(2),lockdev(0,0) < 0)) { syslog(LOG_ERR,"Unable to lock the master device: %m"); _exit(1); } #ifdef linux { /* (Re)Create all our device files */ FILE * fd; if((fd = fopen("/proc/devices","r")) == NULL) syslog(LOG_ERR,"Reading device numbers: %m"); else { char xx[80]; int len; while(fgets(xx,sizeof(xx)-1,fd) != NULL) { char *x = xx; len = strlen(xx); if(len>0 && xx[len-1]=='\n') xx[len-1]='\0'; while(*x != '\0' && isspace(*x)) x++; if(isdigit(*x)) { int devnum = atoi(x); while(*x != '\0' && isdigit(*x)) x++; while(*x != '\0' && isspace(*x)) x++; if(strcmp(x,"tisdn") == 0) isdnterm = devnum; else if(strcmp(x,"isdn") == 0) isdnstd = devnum; } } fclose(fd); if(isdnstd == 0) syslog(LOG_CRIT, "No ISDN driver found!"); else { int i; system("rm -rf /dev/isdn /dev/isdnmon"); mkdir("/dev/isdn",0755); mknod ("/dev/isdnmon", S_IFCHR | S_IRUSR | S_IWUSR, makedev(isdnstd,0)); for(i=1;i 3 if (ioctl (fd_mon, I_PUSH, "isdn_3") < 0) xquit ("ISDN_3 module"); #endif { /* Associate the kernel stream with the user stream */ typedef int (*F) (); extern void isdn3_init (void); extern void isdn_init (void); extern qf_put strrput; extern qf_srv strwsrv; extern struct streamtab strloginfo, loghinfo; #if LEVEL < 4 extern struct streamtab isdn3_info; #endif extern struct qinit stwhdata, stwldata; extern struct module_info strhm_info; static struct qinit xhr = {strrput, do_h, NULL, NULL, NULL, &strhm_info, NULL}; static struct qinit xlr = {strrput, do_l, NULL, NULL, NULL, &strhm_info, NULL}; #if LEVEL < 4 isdn3_init (); #endif setq (&xs_mon->rh, &xhr, &stwhdata); setq (&xs_mon->wl, &stwldata, &xlr); #if LEVEL < 4 register_strmod (&isdn3_info); #endif register_strmod (&strloginfo); register_strmod (&loghinfo); #if LEVEL < 4 /* push user-mode streams modules */ if (pushlog & 1) strioctl (xs_mon, I_PUSH, (long) "strlog"); if (pushlog & 4) strioctl (xs_mon, I_PUSH, (long) "logh"); if (pushlog & 16) strioctl (xs_mon, I_PUSH, (long) "qinfo"); strioctl (xs_mon, I_PUSH, (long) "isdn_3"); #endif } if(0)callout_async (); /* We prefer to do everything synchronously */ timeout (log_idle, NULL, 5 * HZ); /* Tell everybody that we're still alive */ timeout (queue_idle, NULL, HZ/3); /* process the user-mode streams */ syspoll (); /* Now go and do some work */ /* Shut down. Ungracefully. Graceful shutdown of active cards TODO. */ strclose (xs_mon, 0); unlockdev(0); return 0; /* -> exit(0) */ }