|
|
1.1 root 1: #if TRACING | PSTATISTICS
2: #include <stdio.h>
3: #endif
4:
5: #include <sys/param.h>
6: #include <sys/types.h>
7: #include <sys/stream.h>
8: #include <sys/ttyio.h>
9: #include <sys/filio.h>
10: #include <signal.h>
11: #include <errno.h>
12: #include <jioctl.h>
13: #include <tty.h>
14:
15: #include "msgs.h"
16: #include "pconfig.h"
17: #include "proto.h"
18: #include "packets.h"
19: #include "pstats.h"
20:
21: /*
22: * One layer structure per file-descriptor
23: */
24: struct layer {
25: char chan; /* jerq protocol channel */
26: char busy;
27: char dx, dy; /* Window size in characters */
28: short bitsx, bitsy; /* Window size in bits */
29: int more;
30: struct ttychars ttychars;
31: char ptfile[14]; /* file name of slave */
32: char bchan; /* holding area for blocked data */
33: char bcount;
34: char bbuf[MAXPKTDSIZE];
35: };
36:
37: #define NLAYERS 16 /* Same as in jerq itself */
38: #define NSELFD 20 /* Maximum file descriptors for 'select' */
39: #define SELTIMO (1000*3) /* 'select' timeout in millisecs */
40: #define CDSIZE (sizeof(struct sgttyb)-1)
41:
42: char *jerqprog;
43: char *jerqstart;
44: char umesgf[]= "/dev/pt/pt109";
45: char *progname;
46: char *shell;
47: int quitflag;
48: fd_set rdfd;
49: int enabled=1;
50: int blocked=0;
51: struct layer layer[NSELFD];
52: char buf[MAXPKTDSIZE+MSGHLEN];
53: struct sgttyb sttymodes;
54: struct sgttyb sttysave;
55: struct ttydevb devmodes;
56: struct ttydevb devsave;
57: struct tchars tcharssave;
58: struct ttychars ttychars;
59: struct ttychars zerochars;
60: short booted;
61: extern int receive();
62: extern int creceive();
63: void dosig();
64: int twrite();
65: void wrmesgb();
66: extern char *sys_errlist[];
67: extern char *getenv();
68: extern char *itoa();
69: extern char *strcpy();
70: extern char *strcat();
71: extern int tty_ld;
72: extern int mesg_ld;
73: extern int errno;
74: extern int sys_nerr;
75: extern int strlen();
76: extern int write();
77:
78: struct{
79: short speed;
80: short bytes;
81: } speeds[] = {
82: EXTA, 1920,
83: B9600, 960,
84: B4800, 480,
85: B1200, 120,
86: B300, 30,
87: 0, 960, /* default */
88: };
89: #define NSPEEDS ((sizeof speeds)/(sizeof speeds[0]))
90: #define max(A,B) (((A)>(B))?(A):(B))
91:
92: struct Pchannel pconvs[NLAYERS];
93: struct Pconfig pconfig = {
94: # ifndef TRACING
95: write,
96: # else
97: twrite,
98: # endif
99: receive,
100: (void(*)())creceive,
101: };
102:
103: #ifdef TRACING
104: int twrite();
105: FILE *tracefd;
106: void trace();
107: void tread();
108: #define ifdeftracing(a) a
109: #else
110: #define trace(a, b)
111: #define tread(a, b)
112: #define ifdeftracing(a)
113: #endif
114:
115: #if TRACING==1 || PDEBUG==1
116: char tracefile[]="traces";
117: #define _exit exit
118: #endif
119:
120: main(argc, argv)
121: char *argv[];
122: {
123: register int n;
124: char cmdline[64];
125: progname=argv[0];
126: for(n=1; n<argc; n++) {
127: if(strcmp(argv[n], "-L")==0)
128: jerqstart=argv[++n];
129: else if(strcmp(argv[n], "-l")==0){
130: register fd; char jfd[32];
131: fd = creat(mktemp(strcpy(jfd, "/tmp/.muxXXXXXX")), 0744);
132: ++n, write(fd, argv[n], strlen(argv[n]));
133: close(fd);
134: strcpy(cmdline, jfd);
135: strcat(strcat(strcat(cmdline, "; rm "), jfd), "; exit");
136: jerqstart = cmdline;
137: }else{
138: n=argc+1; break;
139: }
140: }
141: if(n!=argc)
142: return service(argc-1, argv+1);
143: if((jerqprog=getenv("MUXTERM")) == 0)
144: jerqprog="/usr/jerq/lib/muxterm";
145: if((shell=getenv("SHELL")) == 0)
146: shell="sh";
147: ioctl(0, TIOCGETP, &sttymodes);
148: sttysave=sttymodes;
149: if(ioctl(0, TIOCGDEV, &devmodes)>=0) /* band-aid for old systems */
150: devsave=devmodes;
151: else {
152: devsave.ispeed=devmodes.ispeed=sttymodes.sg_ispeed;
153: devsave.ospeed=devmodes.ospeed=sttymodes.sg_ospeed;
154: }
155: ioctl(0, TIOCGETC, &tcharssave);
156: setmodes(&ttychars, &sttymodes);
157: settchars(&ttychars, &tcharssave);
158: sttymodes.sg_flags|=RAW;
159: sttymodes.sg_flags&=~ECHO;
160: ioctl(0, TIOCSETP, &sttymodes);
161: devmodes.flags|=F8BIT;
162: ioctl(0, TIOCSDEV, &devmodes);
163: signal(SIGPIPE, (int (*)())1);
164: #ifdef TRACING
165: tracefd=fopen(tracefile, "w");
166: #ifdef PDEBUG
167: ptracefd = tracefd;
168: #endif
169: #endif
170: #if TRACING!=1 && PDEBUG==1
171: ptracefd=fopen(tracefile, "w");
172: #endif
173: if(boot(jerqprog))
174: quit("can't boot terminal program");
175: booted++;
176: ioctl(0, TIOCEXCL, 0);
177: trace(0, 0);
178: trace("start\n", 0);
179: for(n=0; n<NSPEEDS; n++)
180: if(speeds[n].speed<=devmodes.ospeed)
181: break;
182: n=speeds[n].bytes;
183: Pxtimeout=max((((NLAYERS-2)*sizeof(struct Packet)*NPCBUFS+n-1)/n), 3);
184: Prtimeout=max(((sizeof(struct Packet)+n-1)/n), 2);
185: Pscanrate=1;
186: trace("speed = %d", n);
187: trace(" xtimo = %d", Pxtimeout);
188: trace(" rtimo = %d\n", Prtimeout);
189: Pxfdesc=1;
190: if(pinit(NLAYERS)==-1)
191: quit("bad protocol initialization");
192: buf[0]=JTIMO;
193: buf[1]=Prtimeout;
194: buf[2]=Pxtimeout;
195: if (jerqstart && (n = strlen(jerqstart)) <= MAXPKTDSIZE-3) {
196: strncpy(&buf[3], jerqstart, n);
197: n += 3;
198: } else
199: n = 3;
200: (void)psend(0, buf, n);
201: while(scan()!=-1){
202: if(quitflag)
203: quit(NULL);
204: ifdeftracing(fflush(tracefd));
205: }
206: trace("errno = %d\n", errno);
207: quit("select");
208: }
209: scan()
210: {
211: register fd, bit, n, ret=0;
212:
213: trace(0, 0);
214: trace("enabled %o\n", enabled);
215: if(blocked){ /* try to clear blocked channels */
216: for(fd=0, bit=1; fd<NSELFD; fd++, bit<<=1)
217: if((bit&blocked) &&
218: psend(layer[fd].bchan, layer[fd].bbuf, layer[fd].bcount)!=-1){
219: blocked&=~bit;
220: return 0;
221: }
222: }
223: rdfd.fds_bits[0]=enabled&~blocked;
224: while(select(NSELFD, &rdfd, (fd_set *)0, SELTIMO)==-1){
225: if(errno!=EINTR)
226: return -1;
227: ret++;
228: }
229: trace(0, 0);
230: trace("selected %o\n", rdfd.fds_bits[0]);
231: if(rdfd.fds_bits[0]==0) {
232: if(Ptflag)
233: ptimeout(SIGALRM);
234: }else for(fd=0, bit=1; fd<NSELFD; fd++, bit<<=1)
235: if(bit&rdfd.fds_bits[0]){
236: while((n=read(fd, buf, sizeof buf))==-1)
237: if(errno!=EINTR)
238: return -1;
239: else{
240: trace("read error, errno=%d\n", errno);
241: return 0;
242: }
243: ifdeftracing(if(n==0) trace("0 byte read", 0));
244: if(fd==0){
245: if(n==0)
246: quit("EOF on jerq");
247: tread(buf, n);
248: precv(buf, n);
249: } else if(unpack(fd, buf, n))
250: enabled&=~bit;
251: }
252: return ret; /* used in quit */
253: }
254: psend_hold(chan, bufp, count, fd)
255: int chan;
256: register char *bufp;
257: int count;
258: register fd;
259: {
260: int ret;
261: register i;
262: if((ret=psend(chan, bufp, count))==-1){
263: trace("psend hold on fd %d\n", fd);
264: layer[fd].bchan=chan;
265: layer[fd].bcount=count;
266: for(i=0; i<count; i++)
267: layer[fd].bbuf[i]=bufp[i];
268: blocked|=1<<fd;
269: }
270: return ret;
271: }
272: quit(s)
273: register char *s;
274: {
275: register l, i;
276:
277: ifdeftracing(trace("\nmux: %s\n", s); trace(0, 0); fflush(tracefd));
278: if(booted){
279: for(i=0; i<NSELFD; i++)
280: if(layer[i].busy)
281: (void)close(i);
282: layer[0].chan=0;
283: sendioctl(0, JTERM); /* kill demux ==> boot terminal */
284: for(i=Pxtimeout+1; Ptflag && i>0;){
285: enabled=1;
286: if((l=scan())==-1)
287: break;
288: i-=l;
289: }
290: alarm(0);
291: }
292: ioctl(0, TIOCSDEV, &devsave);
293: ioctl(0, TIOCSETP, &sttysave);
294: ioctl(0, TIOCNXCL, 0);
295: sleep(2);
296: if (s) {
297: write(2, progname, strlen(progname));
298: write(2, ": ", 2);
299: write(2, s, strlen(s));
300: write(2, "\n", 1);
301: }
302: #ifdef PSTATISTICS
303: for(i=0, l=0; i<PS_NSTATS; i++)
304: if (pstats[i].count) {
305: if(l++==0)
306: fprintf(stderr, "\nPacket protocol statistics:\n");
307: fprintf(stderr, "%6ld %s\n"
308: ,pstats[i].count
309: #ifdef PSTATSDESC
310: ,pstats[i].descp
311: #else
312: ,""
313: #endif
314: );
315: trace("%6ld ", pstats[i].count);
316: trace("%s\n", pstats[i].descp);
317: }
318: fflush(stderr);
319: #endif
320: #if TRACING == 1 || PDEBUG == 1
321: fprintf(stderr, "\nThere are traces in '%s'\n", tracefile);
322: #endif
323: ifdeftracing(fflush(tracefd); abort());
324: #ifdef MONITOR
325: monitor(0);
326: #endif
327: _exit(0);
328: }
329: /*
330: * Unpack a message buffer bp of length n.
331: */
332: unpack(fd, bp, n)
333: register int fd;
334: char *bp;
335: int n;
336: {
337: register struct mesg *mp;
338: struct ttychars tempchars;
339: static char cdbuf[256];
340: char *s;
341: register int size;
342: mp = (struct mesg *)bp;
343: size = mp->losize + (mp->hisize<<8);
344: trace("unpack fd %d", fd);
345: trace(" size %d", n);
346: trace(" count %d\n", size);
347: if(n<=0)
348: mp->type=M_HANGUP;
349: else if(layer[fd].more>0){
350: layer[fd].more-=n;
351: return sendchars(fd, bp, n);
352: }
353: switch (mp->type) {
354: case M_HANGUP:
355: trace("shell died\n", 0);
356: wait((int *)0);
357: if(layer[fd].busy){
358: sendioctl(fd, JDELETE);
359: /*(void)psend(layer[fd].chan, "Shell died.\n", 12);*/
360: }
361: layer[fd].busy = 0;
362: close(fd);
363: enabled &= ~(1<<fd);
364: return 1;
365: case M_DELAY:
366: default:
367: trace("ignore type 0%o\n", mp->type);
368: return 0;
369: case M_DELIM:
370: case M_DATA:
371: if(size==0){
372: trace("size 0 %s ignored\n", mp->type==M_DELIM? "delim" : "data");
373: return 0;
374: }
375: break;
376: case M_IOCTL:
377: mp->type = M_IOCACK;
378: switch (*(int *)(bp+MSGHLEN)) {
379: case TIOCSETP:
380: case TIOCSETN:
381: tempchars=layer[fd].ttychars;
382: setmodes(&tempchars, (struct sgttyb *)(bp+MSGHLEN+sizeof(int)));
383: ttyset(fd, &tempchars);
384: size = 0;
385: break;
386: case TIOCGETP:
387: tempchars=layer[fd].ttychars;
388: getmodes(&tempchars, (struct sgttyb *)(bp+MSGHLEN+sizeof(int)));
389: size=sizeof(struct sgttyb)+sizeof(int);
390: ttyset(fd, &tempchars);
391: break;
392: case TIOCSETC:
393: tempchars=layer[fd].ttychars;
394: settchars(&tempchars, (struct tchars *)(bp+MSGHLEN+sizeof(int)));
395: ttyset(fd, &tempchars);
396: size=0;
397: break;
398: case TIOCGETC:
399: gettchars(&layer[fd].ttychars, (struct tchars *)(bp+MSGHLEN+sizeof(int)));
400: size=sizeof (struct tchars) + sizeof (int);
401: break;
402: case TIOCSDEV:
403: size=0;
404: break;
405: case TIOCGDEV:
406: size=sizeof(devsave)+sizeof(int);
407: *(struct ttydevb *)(bp+MSGHLEN+sizeof(int))=devsave;
408: break;
409: case JMUX:
410: size=0;
411: break;
412: case JWINSIZE:
413: *((int *)(bp+MSGHLEN))=JWINSIZE; /* answering JWINSIZE ioctl */
414: #define BP ((struct winsize *)(bp+MSGHLEN+sizeof(int)))
415: BP->bytesx=layer[fd].dx;
416: BP->bytesy=layer[fd].dy;
417: BP->bitsx=layer[fd].bitsx;
418: BP->bitsy=layer[fd].bitsy;
419: size=sizeof(struct winsize)+sizeof(int);
420: break;
421: case JTERM:
422: case JBOOT:
423: case JZOMBOOT:
424: sendioctl(fd, *(int *)(bp+MSGHLEN));
425: size=0;
426: break;
427: case JEXIT:
428: sendioctl(fd, *(int *)(bp+MSGHLEN));
429: size=0;
430: break;
431: case JCHDIR:
432: s=bp+MSGHLEN+sizeof(int);
433: if(*s==0){
434: if(chdir(cdbuf)!=0)
435: mp->type = M_IOCNAK;
436: cdbuf[0]=0;
437: }else
438: strcat(cdbuf, s);
439: size = 0;
440: break;
441: default:
442: mp->type = M_IOCNAK;
443: size = 0;
444: }
445: mp->magic = MSGMAGIC; /* safety net */
446: mp->losize = size;
447: mp->hisize = size>>8;
448: write(fd, bp, MSGHLEN+size);
449: trace("unpack ioctl type '%c'", *(int *)(bp+MSGHLEN)>>8);
450: trace(" %d\n", *(int *)(bp+MSGHLEN)&0xff);
451: return 0;
452: }
453: if(size>MAXPKTDSIZE){
454: layer[fd].more=size-MAXPKTDSIZE;
455: size=MAXPKTDSIZE;
456: }
457: return sendchars(fd, bp+MSGHLEN, size);
458: }
459: getmodes(tp, bp)
460: register struct ttychars *tp;
461: register struct sgttyb *bp;
462: {
463: bp->sg_ispeed=sttysave.sg_ispeed;
464: bp->sg_ospeed=sttysave.sg_ospeed;
465: bp->sg_flags=(tp->flags1<<8)|(tp->flags0&0xFF);
466: bp->sg_erase=tp->erase;
467: bp->sg_kill=tp->kill;
468: }
469: setmodes(tp, bp)
470: register struct ttychars *tp;
471: register struct sgttyb *bp;
472: {
473: tp->flags0=bp->sg_flags;
474: tp->flags1=bp->sg_flags>>8;
475: tp->erase=bp->sg_erase;
476: tp->kill=bp->sg_kill;
477: }
478: gettchars(tp, bp)
479: register struct ttychars *tp;
480: register struct tchars *bp;
481: {
482: bp->t_intrc=tp->intrc;
483: bp->t_quitc=tp->quitc;
484: bp->t_startc=tp->startc;
485: bp->t_stopc=tp->stopc;
486: bp->t_eofc=tp->eofc;
487: bp->t_brkc=tp->brkc;
488: }
489: settchars(tp, bp)
490: register struct ttychars *tp;
491: register struct tchars *bp;
492: {
493: tp->intrc=bp->t_intrc;
494: tp->quitc=bp->t_quitc;
495: tp->startc=bp->t_startc;
496: tp->stopc=bp->t_stopc;
497: tp->eofc=bp->t_eofc;
498: tp->brkc=bp->t_brkc;
499: }
500: ttyset(fd, tp)
501: struct ttychars *tp;
502: {
503: register char *p, *q;
504: register i;
505: static struct ttycmesg m={JTTYC};
506: for(i=0, p=(char *)tp, q=(char *)&layer[fd].ttychars; *p++==*q++; i++)
507: if(i>=sizeof(struct ttychars))
508: return; /* no need to send; they're identical */
509: m.chan=layer[fd].chan;
510: layer[fd].ttychars = *tp;
511: m.ttychars = *tp;
512: (void)psend_hold(0, (char *)&m, sizeof m, fd);
513: }
514: sendioctl(fd, cmd)
515: {
516: char ioctlvec[2];
517: ioctlvec[0]=cmd;
518: ioctlvec[1]=layer[fd].chan;
519: if(psend_hold(0, ioctlvec, sizeof ioctlvec, fd)!=-1)
520: unblock(fd);
521: }
522: int
523: sendchars(fd, s, cc)
524: char *s;
525: int cc;
526: {
527: register int l=layer[fd].chan;
528: register int n;
529:
530: # ifdef TRACING
531: char buf[256];
532: trace("write %d chars ", cc);
533: trace("to layer %d\n", l);
534: strncpy(buf, s, cc);
535: buf[cc]=0;
536: trace("<%s>\n", buf);
537: # endif
538: if(fd!=0 && layer[fd].busy==0)
539: return 0; /* layer was deleted, but there's still data */
540: if(cc>0)
541: do{
542: if((n=cc)>MAXPKTDSIZE)
543: n=MAXPKTDSIZE;
544: if(psend(l, s, n)==-1){
545: trace("layer %d blocked\n", l);
546: return fd; /* BUG */
547: }
548: }while(s+=n, (cc-=n)>0);
549: unblock(fd);
550: return 0;
551: }
552: unblock(fd)
553: int fd;
554: {
555: register Pch_p pcp= &pconvs[layer[fd].chan];
556:
557: trace("unblock for layer %d", layer[fd].chan);
558: trace(" freepkts=%d\n", pcp->freepkts);
559: if(fd==0)
560: return;
561: if(pcp->freepkts>=1)
562: enabled|=1<<fd;
563: else
564: enabled&=~(1<<fd);
565: }
566: void
567: lerror(l, s, t)
568: int l;
569: char *s, t;
570: {
571: char ebuf[128];
572: int busy;
573: strcpy(ebuf, s);
574: if(errno){
575: strcat(ebuf, ": ");
576: if(errno < sys_nerr)
577: strcat(ebuf, sys_errlist[errno]);
578: else{
579: strcat(ebuf, "error ");
580: strcat(ebuf, itoa(errno));
581: }
582: errno=0;
583: }
584: strcat(ebuf, "\n");
585: trace("lerror type %d", t);
586: trace(" for layer %d", l);
587: trace(" %s\n", ebuf);
588: layer[0].chan=l;
589: sendchars(0, ebuf, strlen(ebuf));
590: }
591: int
592: creceive(l, s, n)
593: char *s;
594: {
595: if(s[0]!=C_UNBLK || n!=1)
596: quit("bad control type");
597: (void)receive(l, s, n);
598: }
599: int
600: receive(l, s, cc)
601: int l;
602: register char *s;
603: register int cc;
604: {
605: register int i;
606: struct mesg hupmsg;
607: if((i=ltofd(l))==-1)
608: switch(*s){
609: case C_NEW:
610: case C_EXIT:
611: break;
612: default:
613: errno = 0;
614: lerror(l, "inactive layer", *s);
615: case C_UNBLK:
616: return 0;
617: }
618: while(cc--){
619: trace("receive C type %d", *s);
620: trace(" for layer %d", l);
621: trace(" fd %d\n", i);
622: switch(*s++){
623: case C_SENDCHAR: /* send layer char */
624: wrmesgb(i, s++, 1);
625: delim(i);
626: cc--;
627: break;
628: case C_DELIM: /* send delimiter */
629: delim(i);
630: break;
631: case C_NEW: /* make layer */
632: if((i=doshell())==-1){
633: lerror(l, umesgf, C_NEW);
634: trace("can't open %s\n", umesgf);
635: cc-=6;
636: break;
637: }
638: layer[i].busy=1;
639: layer[i].chan=l;
640: ttyset(i, &ttychars);
641: trace("new fd %d ", i);
642: trace("layer %d ", l);
643: enabled |= (1<<i);
644: case C_RESHAPE:
645: layer[i].dx= *s++;
646: trace("x wid %d ", layer[i].dx);
647: layer[i].dy= *s++;
648: trace("y wid %d\n", layer[i].dy);
649: layer[i].bitsx=(unsigned char)*s++;
650: layer[i].bitsx|=(*s++)<<8;
651: layer[i].bitsy=(unsigned char)*s++;
652: layer[i].bitsy|=(*s++)<<8;
653: cc-=6;
654: break;
655: case C_UNBLK: /* unblock layer */
656: unblock(i);
657: break;
658: case C_PUSHLD: /* push ld onto stream */
659: pushld(i);
660: break;
661: case C_POPLD: /* pop ld from stream */
662: popld(i);
663: break;
664: case C_DELETE: /* delete layer */
665: hupmsg.losize=0;
666: hupmsg.hisize=0;
667: hupmsg.magic=MSGMAGIC;
668: hupmsg.type=M_HANGUP;
669: write(i, (char *)&hupmsg, MSGHLEN);
670: layer[i].busy=0;
671: pconvs[layer[i].chan].freepkts=1; /* hack */
672: unblock(i);
673: layer[i].ttychars=zerochars;
674: break;
675: case C_EXIT: /* exit */
676: quitflag++;
677: return 0;
678: case C_SENDNCHARS: /* send cc characters */
679: wrmesgb(i, s, cc);
680: return 0;
681: case C_KILL: /* send layer signal */
682: dosig(i, *s++);
683: cc--;
684: break;
685: default:
686: quit("unknown state incase 0");
687: }
688: ifdeftracing(if(cc<0) quit("bad count in receive"));
689: }
690: return 0;
691: }
692: int
693: ltofd(l)
694: {
695: register i;
696: if(l==0)
697: return 0;
698: for(i=1; i<NSELFD; i++)
699: if(layer[i].busy && layer[i].chan==l)
700: return i;
701: trace("unknown layer %d\n", l);
702: return -1;
703: }
704: void
705: dosig(fd, sig) /* Interrupt shell */
706: {
707: char sigbuf[MSGHLEN+1];
708: register struct mesg *mp;
709:
710: mp = (struct mesg *)sigbuf;
711: mp->type=M_SIGNAL;
712: mp->magic=MSGMAGIC;
713: mp->losize=sizeof(char);
714: mp->hisize=0;
715: sigbuf[MSGHLEN]=sig;
716: write(fd, sigbuf, MSGHLEN+1);
717: mp->type=M_FLUSH;
718: mp->magic=MSGMAGIC;
719: mp->losize=0;
720: mp->hisize=0;
721: write(fd, sigbuf, MSGHLEN);
722: }
723: void
724: wrmesgb(fd, cp, n)
725: register char *cp;
726: int n;
727: {
728: char wrbuf[MAXPKTDSIZE+MSGHLEN];
729: register char *bp;
730: register struct mesg *mp;
731: register int i;
732:
733: ifdeftracing(fprintf(tracefd, "mesg to fd %d: <%.*s>\n", fd, n, cp));
734: mp = (struct mesg *)wrbuf;
735: mp->type=M_DATA;
736: mp->magic=MSGMAGIC;
737: mp->losize=n;
738: mp->hisize=n>>8;
739: bp=wrbuf+MSGHLEN;
740: i=n;
741: while(i--)
742: *bp++= *cp++;
743: write(fd, wrbuf, MSGHLEN+n);
744: }
745: delim(fd)
746: {
747: struct mesg delbuf;
748:
749: ifdeftracing(fprintf(tracefd, "delim fd %d\n", fd));
750: delbuf.type=M_DELIM;
751: delbuf.magic=MSGMAGIC;
752: delbuf.losize=0;
753: delbuf.hisize=0;
754: write(fd, (char *)&delbuf, MSGHLEN);
755: }
756: popld(fd)
757: {
758: register f, i;
759: struct ttychars tempchars;
760: struct sgttyb tb;
761: struct tchars tc;
762: errno=0;
763: if((f=open(layer[fd].ptfile, 2))>0){
764: if((i=ioctl(f, FIOLOOKLD, 0))==tty_ld) {
765: i=0;
766: if(ioctl(f, TIOCGETP, &tb)<0
767: || ioctl(f, TIOCGETC, &tc)<0)
768: i=1; /* hack for old systems */
769: ioctl(f, FIOPOPLD, (struct sgttyb *)0);
770: if(i==0){
771: setmodes(&tempchars, &tb);
772: settchars(&tempchars, &tc);
773: ttyset(fd, &tempchars);
774: }
775: }
776: else if(i>=0)
777: lerror(layer[fd].chan, "mux warning: unknown line discipline", 0);
778: }
779: close(f);
780: trace("popld file %s\n", layer[fd].ptfile);
781: trace("popld file descriptor %d\n", f);
782: }
783: pushld(fd)
784: {
785: register f, i;
786: int tty;
787: struct tchars tc;
788: struct sgttyb tb;
789: if((f=open(layer[fd].ptfile, 2))>0){
790: if((i=ioctl(f, FIOLOOKLD, 0))==-1){
791: ioctl(f, FIOPUSHLD, (struct sgttyb *)&tty_ld);
792: getmodes(&layer[fd].ttychars, &tb);
793: gettchars(&layer[fd].ttychars, &tc);
794: ioctl(f, TIOCSETP, &tb);
795: ioctl(f, TIOCSETC, &tc);
796: }else
797: ; /* can't warn; program could be e.g. jim! */
798: }
799: trace("pushld errno file %d\n", errno);
800: close(f);
801: trace("pushld file descriptor file %s\n", layer[fd].ptfile);
802: }
803: int
804: doshell()
805: {
806: register fd, slave;
807: trace("do shell\n", 0);
808: if((fd=ptopen(umesgf))<0){
809: trace("can't open %s\n", umesgf);
810: return -1;
811: }
812: if((slave=open(umesgf, 2))==-1){
813: trace("can't open %s\n", umesgf);
814: close(fd);
815: return -1;
816: }
817: trace("opened %s\n", umesgf);
818: strcpy(layer[fd].ptfile, umesgf);
819: if(ioctl(fd, FIOPUSHLD, &mesg_ld) == -1){
820: trace("FIOPUSHLD fails, errno=%d\n", errno);
821: close(fd);
822: return -1;
823: }
824: switch(fork()){
825: case 0:
826: /* close every file descriptor in sight, and then some */
827: for(fd=0; fd<5+NLAYERS; fd++)
828: if(fd!=slave)
829: close(fd);
830: dup(slave); dup(slave); dup(slave); dup(slave);
831: close(slave);
832: ioctl(0, TIOCSPGRP, 0);
833: signal(SIGPIPE, (int (*)())0);
834: execlp(shell, shell, 0);
835: perror(shell);
836: exit(1);
837: break;
838: case -1:
839: close(fd);
840: return -1;
841: }
842: trace("doshell succeeds\n", 0);
843: close(slave);
844: return fd;
845: }
846: int
847: boot(s)
848: char *s;
849: {
850: if(system("/usr/jerq/bin/32ld", "32ld", s))
851: return 1;
852: sleep(2);
853: return 0;
854: }
855: int
856: system(s, t, u)
857: char *s, *t, *u;
858: {
859: int status, pid, l;
860:
861: if ((pid=fork())==0){
862: execl(s, t, u, 0);
863: _exit(127);
864: }
865: while ((l = wait(&status)) != pid && l != -1)
866: ;
867: if (l == -1)
868: status = -1;
869: return(status);
870: }
871: char *
872: itoa(i)
873: register int i;
874: {
875: static char str[11];
876: register char * sp = &str[sizeof str];
877:
878: *--sp = '\0';
879: if(i>0){
880: do
881: *--sp=i%10+'0';
882: while((i/=10)>0);
883: }else
884: *--sp='0';
885: return sp;
886: }
887: service(argc, argv)
888: char *argv[];
889: {
890: if(strcmp(argv[0], "cd")==0){
891: char *where=argv[1];
892: char buf[CDSIZE+1];
893: buf[CDSIZE]=0;
894: if(where==0 && (where=getenv("HOME"))==0){
895: write(2, "cd: no HOME set\n", 16);
896: return 1;
897: }
898: while(*where){
899: strncpy(buf, where, CDSIZE);
900: ioctl(0, JCHDIR, buf);
901: where+=strlen(buf);
902: }
903: if(ioctl(0, JCHDIR, where)!=0){
904: write(2, "cd: bad directory\n", 18);
905: return 1;
906: }
907: return 0;
908: }
909: if(strcmp(argv[0], "exit")==0)
910: return ioctl(0, JEXIT, 0);
911: write(2, "mux: no such command ", 21);
912: write(2, argv[0], strlen(argv[0]));
913: write(2, "\n", 1);
914: return 1;
915: }
916: #ifdef TRACING
917: /*VARARGS1*/
918: void
919: trace(s, a)
920: char *s, *a;
921: {
922: long t;
923: extern long time();
924: extern char *ctime();
925:
926: if(s)
927: fprintf(tracefd, s, a);
928: else{
929: (void)time(&t);
930: fprintf(tracefd, "%.9s", ctime(&t)+11);
931: }
932: }
933: int
934: twrite(fd, s, n)
935: unsigned char * s;
936: {
937: register i;
938: fprintf(tracefd, "to jerq: ");
939: for(i=0; i<n; i++)
940: fprintf(tracefd, "<%o>", s[i]);
941: fprintf(tracefd, "\n");
942: return write(fd, s, n);
943: }
944: void
945: tread(s, n)
946: unsigned char * s;
947: {
948: register i;
949: fprintf(tracefd, "from jerq: ");
950: for(i=0; i<n; i++)
951: fprintf(tracefd, "<%o>", s[i]);
952: fprintf(tracefd, "\n");
953: }
954: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.