1*2211Swnj static char *sccsid ="@(#)dnd.c 4.4 (Berkeley) 01/20/81";
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;
27*2211Swnj } pdevs[] = {{"/dev/cua0",'4','8'}, /*{"/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
main(argc,argv)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);
541623Sbill while(fork()) {
551623Sbill sleep(10);
561511Sbill wait(0);
571623Sbill }
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 }
671623Sbill _exit(0);
681511Sbill }
691511Sbill
701511Sbill short noioctl = M_IOANS;
control(x,cb,cc)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
startjob()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
stopjob(x)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 */
init()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 */
unpack(bp,cc)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 */
perform(rp,data)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 }
quit(msg)2251511Sbill quit(msg)
2261511Sbill char *msg;
2271511Sbill {
2281511Sbill printf("%s\n", msg);
2291511Sbill exit(1);
2301511Sbill }
2311511Sbill
putq(x,uid)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
getq()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
delq(x)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 }
wchan(chan,obuf,count)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 }
wctl(chan,obuf,count)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;
dialit(string)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 *
sanitize(string)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;
linebusy()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
catchit()4011511Sbill catchit(){
4021511Sbill longjmp(handy,1);
4031511Sbill }
404