|
|
1.1 root 1: static char *sccsid ="@(#)dnd.c 4.3 (Berkeley) 11/4/80";
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','0'}, {"/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: for(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<QSIZE;j++) {
271: runq[i] = runq[j];
272: i = j;
273: }
274: runq[j].uid = -1;
275: return(x);
276: }
277: return(0);
278: }
279: wchan(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.