1*1511Sbill static char *sccsid ="@(#)dnd.c 4.1 (Berkeley) 10/18/80"; 2*1511Sbill /* 3*1511Sbill * batch queue manager. by Greg Chesson. Modified to be 4*1511Sbill * a daemon managing requests to a multiple autodialers, by 5*1511Sbill * Keith Sklower. 6*1511Sbill */ 7*1511Sbill #include <stdio.h> 8*1511Sbill #include <sgtty.h> 9*1511Sbill #include <sys/mx.h> 10*1511Sbill #include <pwd.h> 11*1511Sbill #define QSIZE 16 12*1511Sbill #define DSIZE 40 13*1511Sbill 14*1511Sbill int xd; 15*1511Sbill int dndebug = 1; /* we actually run debug = 1 */ 16*1511Sbill int nactive; /* number running */ 17*1511Sbill int max; /* max allowable */ 18*1511Sbill int jobnum; 19*1511Sbill char dialbuf[DSIZE]; 20*1511Sbill char *dp = dialbuf; 21*1511Sbill FILE *actfile; 22*1511Sbill struct mx_leaves { 23*1511Sbill char *name; 24*1511Sbill char rack,modem; 25*1511Sbill short chan; 26*1511Sbill int file; 27*1511Sbill } pdevs[] = {{"/dev/cua0",'4','0'}, /*{"/dev/cua1",'4','1'},*/ {0}}; 28*1511Sbill /* the second line here is commented out because, 29*1511Sbill our 1200 baud dialer is being repaired, and if one attempts 30*1511Sbill to dial with a modem that is not capable, the dialer gets 31*1511Sbill hung and must be pulled out of the machine */ 32*1511Sbill 33*1511Sbill struct actinfo { 34*1511Sbill short index; 35*1511Sbill short uid; 36*1511Sbill } runq[QSIZE], xx; 37*1511Sbill 38*1511Sbill #define INDEX(x) ((x&0xff00)>>4) 39*1511Sbill 40*1511Sbill main(argc, argv) 41*1511Sbill char **argv; 42*1511Sbill { 43*1511Sbill register cc; 44*1511Sbill char buf[512]; 45*1511Sbill 46*1511Sbill 47*1511Sbill setbuf(stdout, NULL); 48*1511Sbill umask(0); 49*1511Sbill /*if (argc<2) 50*1511Sbill quit("max jobs?"); 51*1511Sbill max = atoi(argv[1]);*/ max = 1; 52*1511Sbill if(fork()) 53*1511Sbill exit(0); 54*1511Sbill while(fork()) 55*1511Sbill wait(0); 56*1511Sbill strcpy(argv[0], "dnd-child"); 57*1511Sbill 58*1511Sbill xd = init(); 59*1511Sbill if (xd < 0) 60*1511Sbill quit("can't make node"); 61*1511Sbill 62*1511Sbill while( (cc=read(xd, buf, 512)) >= 0) { 63*1511Sbill unpack(buf, cc); 64*1511Sbill } 65*1511Sbill } 66*1511Sbill 67*1511Sbill short noioctl = M_IOANS; 68*1511Sbill control(x, cb, cc) 69*1511Sbill register char *cb; 70*1511Sbill { 71*1511Sbill register char *end; 72*1511Sbill register struct chan *cp; 73*1511Sbill int cmd, stat, ch; 74*1511Sbill int uid; 75*1511Sbill 76*1511Sbill end = cb + cc; 77*1511Sbill while (cb < end ) { 78*1511Sbill cmd = *cb++; 79*1511Sbill cb++; 80*1511Sbill switch(cmd&0xff) { 81*1511Sbill case M_WATCH: 82*1511Sbill uid = *((short *)cb); 83*1511Sbill cb += sizeof(short); 84*1511Sbill putq(x,uid); 85*1511Sbill startjob(); 86*1511Sbill break; 87*1511Sbill case M_CLOSE: 88*1511Sbill stopjob(x); 89*1511Sbill break; 90*1511Sbill case M_IOCTL: 91*1511Sbill wctl(x,(char *)&noioctl,sizeof(noioctl)); 92*1511Sbill cb += sizeof(struct sgttyb); 93*1511Sbill } 94*1511Sbill } 95*1511Sbill } 96*1511Sbill 97*1511Sbill 98*1511Sbill 99*1511Sbill 100*1511Sbill startjob() 101*1511Sbill { 102*1511Sbill register x, stat; 103*1511Sbill if (nactive >= max) 104*1511Sbill return; 105*1511Sbill 106*1511Sbill x = getq(); 107*1511Sbill if (x == 0) 108*1511Sbill return; 109*1511Sbill 110*1511Sbill stat = attach(x, xd); 111*1511Sbill if (stat == -1) 112*1511Sbill return; 113*1511Sbill nactive++; 114*1511Sbill printf("starting to dial on behalf of uid %d\n",xx.uid); 115*1511Sbill dp = dialbuf; 116*1511Sbill } 117*1511Sbill 118*1511Sbill stopjob(x) 119*1511Sbill { 120*1511Sbill detach(x, xd); 121*1511Sbill if (delq(x)) { 122*1511Sbill printf("channel %d aborted\n", INDEX(x)); 123*1511Sbill } else { 124*1511Sbill nactive--; 125*1511Sbill printf("channel %d finished\n", INDEX(x)); 126*1511Sbill } 127*1511Sbill startjob(); 128*1511Sbill } 129*1511Sbill 130*1511Sbill 131*1511Sbill /* 132*1511Sbill * make mpx node, open accounting file, and initialize queue. 133*1511Sbill */ 134*1511Sbill init() 135*1511Sbill { 136*1511Sbill register struct mx_leaves *lp; 137*1511Sbill register int t; 138*1511Sbill int xd; 139*1511Sbill 140*1511Sbill if(dndebug==0) 141*1511Sbill freopen(stdout,"/dev/null","w"); 142*1511Sbill if((actfile = fopen("/usr/adm/dnacct","a"))==NULL) 143*1511Sbill quit("Can't make accouting file"); 144*1511Sbill 145*1511Sbill for(t=QSIZE; --t>=0;) runq[t].uid = -1; 146*1511Sbill 147*1511Sbill xd = mpx("", 0666); 148*1511Sbill if(xd < 0) quit("Can't open master mpx node"); 149*1511Sbill 150*1511Sbill for(lp = pdevs; lp->name; lp++) { 151*1511Sbill t = mpx(lp->name, 0666); 152*1511Sbill if (t < 0) { 153*1511Sbill unlink(lp->name); 154*1511Sbill t = mpx(lp->name, 0666); 155*1511Sbill } 156*1511Sbill if(t < 0) quit("Can't make minor mpx node"); 157*1511Sbill lp->file = t; 158*1511Sbill if((t = join(t,xd)) == -1) quit("Can't attach to tree"); 159*1511Sbill else 160*1511Sbill printf("pseudo-device %s assigned channel %x\n",lp->name,t); 161*1511Sbill lp->chan = t; 162*1511Sbill } 163*1511Sbill return(xd); 164*1511Sbill } 165*1511Sbill 166*1511Sbill /* 167*1511Sbill * unpack an mpx buffer at 168*1511Sbill * bp of length cc. 169*1511Sbill */ 170*1511Sbill unpack(bp, cc) 171*1511Sbill register char *bp; 172*1511Sbill { 173*1511Sbill register char *end; 174*1511Sbill register struct rh *rp; 175*1511Sbill 176*1511Sbill end = bp + cc; 177*1511Sbill while (bp < end) { 178*1511Sbill rp = (struct rh *)bp; 179*1511Sbill bp += sizeof (struct rh); 180*1511Sbill 181*1511Sbill if (rp->count==0) { 182*1511Sbill control(rp->index, bp, rp->ccount); 183*1511Sbill } else 184*1511Sbill perform(rp,bp); 185*1511Sbill rp->count += rp->ccount; 186*1511Sbill if (rp->count & 1) 187*1511Sbill rp->count++; 188*1511Sbill bp += rp->count; 189*1511Sbill 190*1511Sbill } 191*1511Sbill } 192*1511Sbill /* transfer numbers to the unique dialer */ 193*1511Sbill perform(rp,data) 194*1511Sbill register struct rh *rp; 195*1511Sbill register char *data; 196*1511Sbill { 197*1511Sbill register char *lim; 198*1511Sbill long clock; char c; 199*1511Sbill char *mdata, *tmpt, *ctime(); 200*1511Sbill struct passwd *getpwuid(); 201*1511Sbill if(rp->index!=xx.index) 202*1511Sbill printf("phase error: Writing data from chan %x on behalf of chan %x\n",rp->index,xx.index); 203*1511Sbill lim = rp->count + data; 204*1511Sbill mdata = data; 205*1511Sbill while(mdata< lim && dp < dialbuf+DSIZE) { 206*1511Sbill *dp++ = *mdata; 207*1511Sbill if(*mdata=='<') { 208*1511Sbill *dp++ = 0; 209*1511Sbill time(&clock); tmpt = ctime(&clock); tmpt[20] = 0; 210*1511Sbill if((c = dialit(dialbuf))=='A') 211*1511Sbill fprintf(actfile, "%s dialed %s at %s\n", 212*1511Sbill getpwuid(xx.uid)->pw_name,dialbuf,tmpt); 213*1511Sbill else printf("Dialer returns %c\n",c); 214*1511Sbill fflush(actfile); 215*1511Sbill dp = dialbuf; 216*1511Sbill stopjob(rp->index); 217*1511Sbill return; 218*1511Sbill } 219*1511Sbill mdata++; 220*1511Sbill } 221*1511Sbill } 222*1511Sbill quit(msg) 223*1511Sbill char *msg; 224*1511Sbill { 225*1511Sbill printf("%s\n", msg); 226*1511Sbill exit(1); 227*1511Sbill } 228*1511Sbill 229*1511Sbill putq(x,uid) 230*1511Sbill { 231*1511Sbill register i; 232*1511Sbill 233*1511Sbill for(i=0; i<QSIZE; i++) 234*1511Sbill if (runq[i].uid == -1) { 235*1511Sbill runq[i].index = x; 236*1511Sbill runq[i].uid = uid; 237*1511Sbill return; 238*1511Sbill } 239*1511Sbill } 240*1511Sbill 241*1511Sbill getq() 242*1511Sbill { 243*1511Sbill register i, j, x; 244*1511Sbill 245*1511Sbill i = 0; 246*1511Sbill xx = runq[0]; 247*1511Sbill x = xx.index; 248*1511Sbill if(xx.uid==-1) x = 0; 249*1511Sbill while(runq[i].uid!=-1) { 250*1511Sbill j = i+1; 251*1511Sbill runq[i] = runq[j]; 252*1511Sbill i = j; 253*1511Sbill } 254*1511Sbill return(x); 255*1511Sbill } 256*1511Sbill 257*1511Sbill delq(x) 258*1511Sbill register x; 259*1511Sbill { 260*1511Sbill register i, j; 261*1511Sbill 262*1511Sbill for(i=0; i<QSIZE; i++) { 263*1511Sbill if (runq[i].index == -1) 264*1511Sbill return(0); 265*1511Sbill if (runq[i].index != x) 266*1511Sbill continue; 267*1511Sbill for(j=i+1; j<QSIZE;j++) { 268*1511Sbill runq[i] = runq[j]; 269*1511Sbill i = j; 270*1511Sbill } 271*1511Sbill runq[j].uid = -1; 272*1511Sbill return(x); 273*1511Sbill } 274*1511Sbill return(0); 275*1511Sbill } 276*1511Sbill wchan(chan,obuf,count) 277*1511Sbill register char *obuf; 278*1511Sbill { 279*1511Sbill struct wh msg; 280*1511Sbill 281*1511Sbill msg.index = chan; 282*1511Sbill msg.count = count; 283*1511Sbill msg.ccount = 0; 284*1511Sbill msg.data = obuf; 285*1511Sbill write(xd,&msg,sizeof msg); 286*1511Sbill } 287*1511Sbill wctl(chan,obuf,count) 288*1511Sbill register char *obuf; 289*1511Sbill { 290*1511Sbill struct wh msg; 291*1511Sbill 292*1511Sbill msg.index = chan; 293*1511Sbill msg.count = 0; 294*1511Sbill msg.ccount = count; 295*1511Sbill msg.data = obuf; 296*1511Sbill write(xd,&msg,sizeof msg); 297*1511Sbill } 298*1511Sbill 299*1511Sbill 300*1511Sbill char *DN = "/dev/ttya2"; 301*1511Sbill #define pc(x) (c = x, write(fd,&c,1)) 302*1511Sbill #define ABORT 01 303*1511Sbill #define SI 017 304*1511Sbill #define STX 02 305*1511Sbill #define ETX 03 306*1511Sbill #define unlike(a,b) (((a)^(b))&0xf) 307*1511Sbill static struct sgttyb cntrl; 308*1511Sbill dialit(string) 309*1511Sbill register char *string; 310*1511Sbill { 311*1511Sbill register int fd = open(DN,2); 312*1511Sbill char c, cc, *sanitize(); 313*1511Sbill register struct mx_leaves *lp = pdevs; 314*1511Sbill int test; 315*1511Sbill 316*1511Sbill if(fd<0) return('C'); 317*1511Sbill /*if(linebusy()) return('X');*/ 318*1511Sbill 319*1511Sbill gtty(fd,&cntrl); /* set raw, -echo, 2400 Baud */ 320*1511Sbill cntrl.sg_ispeed = cntrl.sg_ospeed = B2400; 321*1511Sbill cntrl.sg_flags = RAW | EVENP | ODDP; 322*1511Sbill stty(fd,&cntrl); 323*1511Sbill string = sanitize(string); 324*1511Sbill if(*string=='<' && string[1]==0) { 325*1511Sbill c = 'U'; 326*1511Sbill close(fd); 327*1511Sbill return(c); 328*1511Sbill } 329*1511Sbill while(test = unlike(lp->chan,xx.index)) 330*1511Sbill if(lp->name==0) { 331*1511Sbill printf("Unable to locate dialer, chan = %x\n",xx.index); 332*1511Sbill return('K'); 333*1511Sbill } else lp++; 334*1511Sbill pc(STX); pc(lp->rack); pc(lp->modem); 335*1511Sbill for(;*string && *string!='<'; string++) pc(*string); 336*1511Sbill /*for(;*string; string++) pc(*string);*/ 337*1511Sbill pc(SI); pc(ETX); 338*1511Sbill /*if(*string=='<') { 339*1511Sbill c = 'M'; 340*1511Sbill read(fd,&c,1); 341*1511Sbill if(c=='A'); 342*1511Sbill }*/ 343*1511Sbill if(read(fd,&c,1)!=1) c = 'M'; 344*1511Sbill if(c=='B'||c=='G') { 345*1511Sbill pc(ABORT); 346*1511Sbill read(fd,&cc,1); 347*1511Sbill } 348*1511Sbill out: 349*1511Sbill close(fd); 350*1511Sbill return(c); 351*1511Sbill } 352*1511Sbill char * 353*1511Sbill sanitize(string) 354*1511Sbill register char *string; 355*1511Sbill { 356*1511Sbill static char buf[512]; 357*1511Sbill register char *cp = buf; 358*1511Sbill for(;*string; string++) { 359*1511Sbill switch(*string) { 360*1511Sbill case '0': case '1': case '2': case '3': case '4': 361*1511Sbill case '5': case '6': case '7': case '8': case '9': case '<': 362*1511Sbill *cp++ = *string; 363*1511Sbill break; 364*1511Sbill case '_': 365*1511Sbill *cp++ = '='; 366*1511Sbill break; 367*1511Sbill } 368*1511Sbill } 369*1511Sbill *cp++ = 0; 370*1511Sbill return(buf); 371*1511Sbill } 372*1511Sbill /* Band-aid for hardware glitch - access forbidded to 373*1511Sbill dialer while line in use */ 374*1511Sbill char *DZ = "/dev/cul0"; 375*1511Sbill #include <setjmp.h> 376*1511Sbill #include <signal.h> 377*1511Sbill jmp_buf handy; 378*1511Sbill linebusy() { 379*1511Sbill void catchit(); int fd; 380*1511Sbill signal(SIGALRM,catchit); 381*1511Sbill alarm(2); 382*1511Sbill if(setjmp(handy)==0) { 383*1511Sbill fd = open(DZ,2); 384*1511Sbill /* if we are there the open did not hang, so 385*1511Sbill we problem got the line was busy */ 386*1511Sbill if(fd > 0) { 387*1511Sbill alarm(0); 388*1511Sbill printf("open succeeded did not hang\n"); 389*1511Sbill close(fd); 390*1511Sbill } 391*1511Sbill printf("Line in use\n"); 392*1511Sbill return(1); /* line busy */ 393*1511Sbill } else 394*1511Sbill /* came in on interrupt */ 395*1511Sbill return(0); /* line is free, we did hang waiting for Carrier */ 396*1511Sbill } 397*1511Sbill void 398*1511Sbill catchit(){ 399*1511Sbill longjmp(handy,1); 400*1511Sbill } 401