static char *sccsid ="@(#)dnd.c 4.4 (Berkeley) 1/20/81"; /* * batch queue manager. by Greg Chesson. Modified to be * a daemon managing requests to a multiple autodialers, by * Keith Sklower. */ #include #include #include #include #define QSIZE 16 #define DSIZE 40 int xd; int dndebug = 1; /* we actually run debug = 1 */ int nactive; /* number running */ int max; /* max allowable */ int jobnum; char dialbuf[DSIZE]; char *dp = dialbuf; FILE *actfile; struct mx_leaves { char *name; char rack,modem; short chan; int file; } pdevs[] = {{"/dev/cua0",'4','8'}, /*{"/dev/cua1",'4','1'},*/ {0}}; /* the second line here is commented out because, our 1200 baud dialer is being repaired, and if one attempts to dial with a modem that is not capable, the dialer gets hung and must be pulled out of the machine */ struct actinfo { short index; short uid; } runq[QSIZE], xx; #define INDEX(x) ((x&0xff00)>>4) main(argc, argv) char **argv; { register cc; char buf[512]; setbuf(stdout, NULL); umask(0); /*if (argc<2) quit("max jobs?"); max = atoi(argv[1]);*/ max = 1; if(fork()) exit(0); while(fork()) { sleep(10); wait(0); } strcpy(argv[0], "dnd-child"); xd = init(); if (xd < 0) quit("can't make node"); while( (cc=read(xd, buf, 512)) >= 0) { unpack(buf, cc); } _exit(0); } short noioctl = M_IOANS; control(x, cb, cc) register char *cb; { register char *end; register struct chan *cp; int cmd, stat, ch; int uid; end = cb + cc; while (cb < end ) { cmd = *cb++; cb++; switch(cmd&0xff) { case M_WATCH: uid = *((short *)cb); cb += sizeof(short); putq(x,uid); startjob(); break; case M_CLOSE: stopjob(x); break; case M_IOCTL: wctl(x,(char *)&noioctl,sizeof(noioctl)); cb += sizeof(struct sgttyb); } } } startjob() { register x, stat; if (nactive >= max) return; x = getq(); if (x == 0) return; stat = attach(x, xd); if (stat == -1) return; nactive++; printf("starting to dial on behalf of uid %d\n",xx.uid); dp = dialbuf; } stopjob(x) { detach(x, xd); if (delq(x)) { printf("channel %d aborted\n", INDEX(x)); } else { nactive--; printf("channel %d finished\n", INDEX(x)); } startjob(); } /* * make mpx node, open accounting file, and initialize queue. */ init() { register struct mx_leaves *lp; register int t; int xd; if(dndebug==0) freopen(stdout,"/dev/null","w"); if((actfile = fopen("/usr/adm/dnacct","a"))==NULL) quit("Can't make accouting file"); for(t=QSIZE; --t>=0;) runq[t].uid = -1; xd = mpx("", 0666); if(xd < 0) quit("Can't open master mpx node"); for(lp = pdevs; lp->name; lp++) { t = mpx(lp->name, 0666); if (t < 0) { unlink(lp->name); t = mpx(lp->name, 0666); } if(t < 0) quit("Can't make minor mpx node"); lp->file = t; if((t = join(t,xd)) == -1) quit("Can't attach to tree"); else printf("pseudo-device %s assigned channel %x\n",lp->name,t); lp->chan = t; } return(xd); } /* * unpack an mpx buffer at * bp of length cc. */ unpack(bp, cc) register char *bp; { register char *end; register struct rh *rp; end = bp + cc; while (bp < end) { rp = (struct rh *)bp; bp += sizeof (struct rh); if (rp->count==0) { control(rp->index, bp, rp->ccount); } else perform(rp,bp); rp->count += rp->ccount; if (rp->count & 1) rp->count++; bp += rp->count; } } /* transfer numbers to the unique dialer */ perform(rp,data) register struct rh *rp; register char *data; { register char *lim; long clock; char c; char *mdata, *tmpt, *ctime(); struct passwd *getpwuid(); if(rp->index!=xx.index) printf("phase error: Writing data from chan %x on behalf of chan %x\n",rp->index,xx.index); lim = rp->count + data; mdata = data; while(mdata< lim && dp < dialbuf+DSIZE) { *dp++ = *mdata; if(*mdata=='<') { *dp++ = 0; time(&clock); tmpt = ctime(&clock); tmpt[20] = 0; if((c = dialit(dialbuf))=='A') fprintf(actfile, "%s dialed %s at %s\n", getpwuid(xx.uid)->pw_name,dialbuf,tmpt); else printf("Dialer returns %c\n",c); fflush(actfile); dp = dialbuf; stopjob(rp->index); return; } mdata++; } } quit(msg) char *msg; { printf("%s\n", msg); exit(1); } putq(x,uid) { register i; for(i=0; ichan,xx.index)) if(lp->name==0) { printf("Unable to locate dialer, chan = %x\n",xx.index); return('K'); } else lp++; pc(STX); pc(lp->rack); pc(lp->modem); for(;*string && *string!='<'; string++) pc(*string); /*for(;*string; string++) pc(*string);*/ pc(SI); pc(ETX); /*if(*string=='<') { c = 'M'; read(fd,&c,1); if(c=='A'); }*/ if(read(fd,&c,1)!=1) c = 'M'; if(c=='B'||c=='G') { pc(ABORT); read(fd,&cc,1); } out: close(fd); return(c); } char * sanitize(string) register char *string; { static char buf[512]; register char *cp = buf; for(;*string; string++) { switch(*string) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '<': *cp++ = *string; break; case '_': *cp++ = '='; break; } } *cp++ = 0; return(buf); } /* Band-aid for hardware glitch - access forbidded to dialer while line in use */ char *DZ = "/dev/cul0"; #include #include jmp_buf handy; linebusy() { void catchit(); int fd; signal(SIGALRM,catchit); alarm(2); if(setjmp(handy)==0) { fd = open(DZ,2); /* if we are there the open did not hang, so we problem got the line was busy */ if(fd > 0) { alarm(0); printf("open succeeded did not hang\n"); close(fd); } printf("Line in use\n"); return(1); /* line busy */ } else /* came in on interrupt */ return(0); /* line is free, we did hang waiting for Carrier */ } void catchit(){ longjmp(handy,1); }