1*1623Sbill static char *sccsid ="@(#)dnd.c 4.2 (Berkeley) 10/27/80"; 21511Sbill /* 31511Sbill * batch queue manager. by Greg Chesson. Modified to be 41511Sbill * a daemon managing requests to a multiple autodialers, by 51511Sbill * Keith Sklower. 61511Sbill */ 71511Sbill #include <stdio.h> 81511Sbill #include <sgtty.h> 91511Sbill #include <sys/mx.h> 101511Sbill #include <pwd.h> 111511Sbill #define QSIZE 16 121511Sbill #define DSIZE 40 131511Sbill 141511Sbill int xd; 151511Sbill int dndebug = 1; /* we actually run debug = 1 */ 161511Sbill int nactive; /* number running */ 171511Sbill int max; /* max allowable */ 181511Sbill int jobnum; 191511Sbill char dialbuf[DSIZE]; 201511Sbill char *dp = dialbuf; 211511Sbill FILE *actfile; 221511Sbill struct mx_leaves { 231511Sbill char *name; 241511Sbill char rack,modem; 251511Sbill short chan; 261511Sbill int file; 271511Sbill } pdevs[] = {{"/dev/cua0",'4','0'}, /*{"/dev/cua1",'4','1'},*/ {0}}; 281511Sbill /* the second line here is commented out because, 291511Sbill our 1200 baud dialer is being repaired, and if one attempts 301511Sbill to dial with a modem that is not capable, the dialer gets 311511Sbill hung and must be pulled out of the machine */ 321511Sbill 331511Sbill struct actinfo { 341511Sbill short index; 351511Sbill short uid; 361511Sbill } runq[QSIZE], xx; 371511Sbill 381511Sbill #define INDEX(x) ((x&0xff00)>>4) 391511Sbill 401511Sbill main(argc, argv) 411511Sbill char **argv; 421511Sbill { 431511Sbill register cc; 441511Sbill char buf[512]; 451511Sbill 461511Sbill 471511Sbill setbuf(stdout, NULL); 481511Sbill umask(0); 491511Sbill /*if (argc<2) 501511Sbill quit("max jobs?"); 511511Sbill max = atoi(argv[1]);*/ max = 1; 521511Sbill if(fork()) 531511Sbill exit(0); 54*1623Sbill while(fork()) { 55*1623Sbill sleep(10); 561511Sbill wait(0); 57*1623Sbill } 581511Sbill strcpy(argv[0], "dnd-child"); 591511Sbill 601511Sbill xd = init(); 611511Sbill if (xd < 0) 621511Sbill quit("can't make node"); 631511Sbill 641511Sbill while( (cc=read(xd, buf, 512)) >= 0) { 651511Sbill unpack(buf, cc); 661511Sbill } 67*1623Sbill _exit(0); 681511Sbill } 691511Sbill 701511Sbill short noioctl = M_IOANS; 711511Sbill control(x, cb, cc) 721511Sbill register char *cb; 731511Sbill { 741511Sbill register char *end; 751511Sbill register struct chan *cp; 761511Sbill int cmd, stat, ch; 771511Sbill int uid; 781511Sbill 791511Sbill end = cb + cc; 801511Sbill while (cb < end ) { 811511Sbill cmd = *cb++; 821511Sbill cb++; 831511Sbill switch(cmd&0xff) { 841511Sbill case M_WATCH: 851511Sbill uid = *((short *)cb); 861511Sbill cb += sizeof(short); 871511Sbill putq(x,uid); 881511Sbill startjob(); 891511Sbill break; 901511Sbill case M_CLOSE: 911511Sbill stopjob(x); 921511Sbill break; 931511Sbill case M_IOCTL: 941511Sbill wctl(x,(char *)&noioctl,sizeof(noioctl)); 951511Sbill cb += sizeof(struct sgttyb); 961511Sbill } 971511Sbill } 981511Sbill } 991511Sbill 1001511Sbill 1011511Sbill 1021511Sbill 1031511Sbill startjob() 1041511Sbill { 1051511Sbill register x, stat; 1061511Sbill if (nactive >= max) 1071511Sbill return; 1081511Sbill 1091511Sbill x = getq(); 1101511Sbill if (x == 0) 1111511Sbill return; 1121511Sbill 1131511Sbill stat = attach(x, xd); 1141511Sbill if (stat == -1) 1151511Sbill return; 1161511Sbill nactive++; 1171511Sbill printf("starting to dial on behalf of uid %d\n",xx.uid); 1181511Sbill dp = dialbuf; 1191511Sbill } 1201511Sbill 1211511Sbill stopjob(x) 1221511Sbill { 1231511Sbill detach(x, xd); 1241511Sbill if (delq(x)) { 1251511Sbill printf("channel %d aborted\n", INDEX(x)); 1261511Sbill } else { 1271511Sbill nactive--; 1281511Sbill printf("channel %d finished\n", INDEX(x)); 1291511Sbill } 1301511Sbill startjob(); 1311511Sbill } 1321511Sbill 1331511Sbill 1341511Sbill /* 1351511Sbill * make mpx node, open accounting file, and initialize queue. 1361511Sbill */ 1371511Sbill init() 1381511Sbill { 1391511Sbill register struct mx_leaves *lp; 1401511Sbill register int t; 1411511Sbill int xd; 1421511Sbill 1431511Sbill if(dndebug==0) 1441511Sbill freopen(stdout,"/dev/null","w"); 1451511Sbill if((actfile = fopen("/usr/adm/dnacct","a"))==NULL) 1461511Sbill quit("Can't make accouting file"); 1471511Sbill 1481511Sbill for(t=QSIZE; --t>=0;) runq[t].uid = -1; 1491511Sbill 1501511Sbill xd = mpx("", 0666); 1511511Sbill if(xd < 0) quit("Can't open master mpx node"); 1521511Sbill 1531511Sbill for(lp = pdevs; lp->name; lp++) { 1541511Sbill t = mpx(lp->name, 0666); 1551511Sbill if (t < 0) { 1561511Sbill unlink(lp->name); 1571511Sbill t = mpx(lp->name, 0666); 1581511Sbill } 1591511Sbill if(t < 0) quit("Can't make minor mpx node"); 1601511Sbill lp->file = t; 1611511Sbill if((t = join(t,xd)) == -1) quit("Can't attach to tree"); 1621511Sbill else 1631511Sbill printf("pseudo-device %s assigned channel %x\n",lp->name,t); 1641511Sbill lp->chan = t; 1651511Sbill } 1661511Sbill return(xd); 1671511Sbill } 1681511Sbill 1691511Sbill /* 1701511Sbill * unpack an mpx buffer at 1711511Sbill * bp of length cc. 1721511Sbill */ 1731511Sbill unpack(bp, cc) 1741511Sbill register char *bp; 1751511Sbill { 1761511Sbill register char *end; 1771511Sbill register struct rh *rp; 1781511Sbill 1791511Sbill end = bp + cc; 1801511Sbill while (bp < end) { 1811511Sbill rp = (struct rh *)bp; 1821511Sbill bp += sizeof (struct rh); 1831511Sbill 1841511Sbill if (rp->count==0) { 1851511Sbill control(rp->index, bp, rp->ccount); 1861511Sbill } else 1871511Sbill perform(rp,bp); 1881511Sbill rp->count += rp->ccount; 1891511Sbill if (rp->count & 1) 1901511Sbill rp->count++; 1911511Sbill bp += rp->count; 1921511Sbill 1931511Sbill } 1941511Sbill } 1951511Sbill /* transfer numbers to the unique dialer */ 1961511Sbill perform(rp,data) 1971511Sbill register struct rh *rp; 1981511Sbill register char *data; 1991511Sbill { 2001511Sbill register char *lim; 2011511Sbill long clock; char c; 2021511Sbill char *mdata, *tmpt, *ctime(); 2031511Sbill struct passwd *getpwuid(); 2041511Sbill if(rp->index!=xx.index) 2051511Sbill printf("phase error: Writing data from chan %x on behalf of chan %x\n",rp->index,xx.index); 2061511Sbill lim = rp->count + data; 2071511Sbill mdata = data; 2081511Sbill while(mdata< lim && dp < dialbuf+DSIZE) { 2091511Sbill *dp++ = *mdata; 2101511Sbill if(*mdata=='<') { 2111511Sbill *dp++ = 0; 2121511Sbill time(&clock); tmpt = ctime(&clock); tmpt[20] = 0; 2131511Sbill if((c = dialit(dialbuf))=='A') 2141511Sbill fprintf(actfile, "%s dialed %s at %s\n", 2151511Sbill getpwuid(xx.uid)->pw_name,dialbuf,tmpt); 2161511Sbill else printf("Dialer returns %c\n",c); 2171511Sbill fflush(actfile); 2181511Sbill dp = dialbuf; 2191511Sbill stopjob(rp->index); 2201511Sbill return; 2211511Sbill } 2221511Sbill mdata++; 2231511Sbill } 2241511Sbill } 2251511Sbill quit(msg) 2261511Sbill char *msg; 2271511Sbill { 2281511Sbill printf("%s\n", msg); 2291511Sbill exit(1); 2301511Sbill } 2311511Sbill 2321511Sbill putq(x,uid) 2331511Sbill { 2341511Sbill register i; 2351511Sbill 2361511Sbill for(i=0; i<QSIZE; i++) 2371511Sbill if (runq[i].uid == -1) { 2381511Sbill runq[i].index = x; 2391511Sbill runq[i].uid = uid; 2401511Sbill return; 2411511Sbill } 2421511Sbill } 2431511Sbill 2441511Sbill getq() 2451511Sbill { 2461511Sbill register i, j, x; 2471511Sbill 2481511Sbill i = 0; 2491511Sbill xx = runq[0]; 2501511Sbill x = xx.index; 2511511Sbill if(xx.uid==-1) x = 0; 2521511Sbill while(runq[i].uid!=-1) { 2531511Sbill j = i+1; 2541511Sbill runq[i] = runq[j]; 2551511Sbill i = j; 2561511Sbill } 2571511Sbill return(x); 2581511Sbill } 2591511Sbill 2601511Sbill delq(x) 2611511Sbill register x; 2621511Sbill { 2631511Sbill register i, j; 2641511Sbill 2651511Sbill for(i=0; i<QSIZE; i++) { 2661511Sbill if (runq[i].index == -1) 2671511Sbill return(0); 2681511Sbill if (runq[i].index != x) 2691511Sbill continue; 2701511Sbill for(j=i+1; j<QSIZE;j++) { 2711511Sbill runq[i] = runq[j]; 2721511Sbill i = j; 2731511Sbill } 2741511Sbill runq[j].uid = -1; 2751511Sbill return(x); 2761511Sbill } 2771511Sbill return(0); 2781511Sbill } 2791511Sbill wchan(chan,obuf,count) 2801511Sbill register char *obuf; 2811511Sbill { 2821511Sbill struct wh msg; 2831511Sbill 2841511Sbill msg.index = chan; 2851511Sbill msg.count = count; 2861511Sbill msg.ccount = 0; 2871511Sbill msg.data = obuf; 2881511Sbill write(xd,&msg,sizeof msg); 2891511Sbill } 2901511Sbill wctl(chan,obuf,count) 2911511Sbill register char *obuf; 2921511Sbill { 2931511Sbill struct wh msg; 2941511Sbill 2951511Sbill msg.index = chan; 2961511Sbill msg.count = 0; 2971511Sbill msg.ccount = count; 2981511Sbill msg.data = obuf; 2991511Sbill write(xd,&msg,sizeof msg); 3001511Sbill } 3011511Sbill 3021511Sbill 3031511Sbill char *DN = "/dev/ttya2"; 3041511Sbill #define pc(x) (c = x, write(fd,&c,1)) 3051511Sbill #define ABORT 01 3061511Sbill #define SI 017 3071511Sbill #define STX 02 3081511Sbill #define ETX 03 3091511Sbill #define unlike(a,b) (((a)^(b))&0xf) 3101511Sbill static struct sgttyb cntrl; 3111511Sbill dialit(string) 3121511Sbill register char *string; 3131511Sbill { 3141511Sbill register int fd = open(DN,2); 3151511Sbill char c, cc, *sanitize(); 3161511Sbill register struct mx_leaves *lp = pdevs; 3171511Sbill int test; 3181511Sbill 3191511Sbill if(fd<0) return('C'); 3201511Sbill /*if(linebusy()) return('X');*/ 3211511Sbill 3221511Sbill gtty(fd,&cntrl); /* set raw, -echo, 2400 Baud */ 3231511Sbill cntrl.sg_ispeed = cntrl.sg_ospeed = B2400; 3241511Sbill cntrl.sg_flags = RAW | EVENP | ODDP; 3251511Sbill stty(fd,&cntrl); 3261511Sbill string = sanitize(string); 3271511Sbill if(*string=='<' && string[1]==0) { 3281511Sbill c = 'U'; 3291511Sbill close(fd); 3301511Sbill return(c); 3311511Sbill } 3321511Sbill while(test = unlike(lp->chan,xx.index)) 3331511Sbill if(lp->name==0) { 3341511Sbill printf("Unable to locate dialer, chan = %x\n",xx.index); 3351511Sbill return('K'); 3361511Sbill } else lp++; 3371511Sbill pc(STX); pc(lp->rack); pc(lp->modem); 3381511Sbill for(;*string && *string!='<'; string++) pc(*string); 3391511Sbill /*for(;*string; string++) pc(*string);*/ 3401511Sbill pc(SI); pc(ETX); 3411511Sbill /*if(*string=='<') { 3421511Sbill c = 'M'; 3431511Sbill read(fd,&c,1); 3441511Sbill if(c=='A'); 3451511Sbill }*/ 3461511Sbill if(read(fd,&c,1)!=1) c = 'M'; 3471511Sbill if(c=='B'||c=='G') { 3481511Sbill pc(ABORT); 3491511Sbill read(fd,&cc,1); 3501511Sbill } 3511511Sbill out: 3521511Sbill close(fd); 3531511Sbill return(c); 3541511Sbill } 3551511Sbill char * 3561511Sbill sanitize(string) 3571511Sbill register char *string; 3581511Sbill { 3591511Sbill static char buf[512]; 3601511Sbill register char *cp = buf; 3611511Sbill for(;*string; string++) { 3621511Sbill switch(*string) { 3631511Sbill case '0': case '1': case '2': case '3': case '4': 3641511Sbill case '5': case '6': case '7': case '8': case '9': case '<': 3651511Sbill *cp++ = *string; 3661511Sbill break; 3671511Sbill case '_': 3681511Sbill *cp++ = '='; 3691511Sbill break; 3701511Sbill } 3711511Sbill } 3721511Sbill *cp++ = 0; 3731511Sbill return(buf); 3741511Sbill } 3751511Sbill /* Band-aid for hardware glitch - access forbidded to 3761511Sbill dialer while line in use */ 3771511Sbill char *DZ = "/dev/cul0"; 3781511Sbill #include <setjmp.h> 3791511Sbill #include <signal.h> 3801511Sbill jmp_buf handy; 3811511Sbill linebusy() { 3821511Sbill void catchit(); int fd; 3831511Sbill signal(SIGALRM,catchit); 3841511Sbill alarm(2); 3851511Sbill if(setjmp(handy)==0) { 3861511Sbill fd = open(DZ,2); 3871511Sbill /* if we are there the open did not hang, so 3881511Sbill we problem got the line was busy */ 3891511Sbill if(fd > 0) { 3901511Sbill alarm(0); 3911511Sbill printf("open succeeded did not hang\n"); 3921511Sbill close(fd); 3931511Sbill } 3941511Sbill printf("Line in use\n"); 3951511Sbill return(1); /* line busy */ 3961511Sbill } else 3971511Sbill /* came in on interrupt */ 3981511Sbill return(0); /* line is free, we did hang waiting for Carrier */ 3991511Sbill } 4001511Sbill void 4011511Sbill catchit(){ 4021511Sbill longjmp(handy,1); 4031511Sbill } 404