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