xref: /csrg-svn/old/dnd/dnd.c (revision 1623)
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