|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/stream.h>
3: #include <sys/stat.h>
4: #include <sys/ttyio.h>
5: #include <sys/filio.h>
6: #include <sys/dkio.h>
7: #include <stdio.h>
8: #include <errno.h>
9: #include <signal.h>
10: #include <ipc.h>
11: #include <libc.h>
12: #include <utsname.h>
13:
14: /*
15: * program to connect to
16: * another cpu on Datakit w/ transparent ioctls
17: */
18:
19: int rem=-1; /* remote file descriptor */
20: extern int mesg_ld;
21: struct sgttyb sgbuf;
22: struct tchars tcbuf;
23: int ttyrem=0; /* true if tty ld is remote */
24: char *ttyn;
25: int perms;
26:
27: struct sigmsg {
28: struct mesg m;
29: char sig[1];
30: };
31:
32: struct buffer {
33: int rfd,wfd;
34: int rmesgld;
35: int wmesgld;
36: char *rptr;
37: char *wptr;
38: char data[4096+MSGHLEN];
39: };
40: static struct buffer ttyb;
41: static struct buffer netb;
42:
43: struct mesg *getmsg();
44: int fillbuf();
45:
46: #define msglen(mp) ((mp)->losize + ((mp)->hisize<<8))
47:
48: int lfd;
49: char *av0;
50: int notdef;
51: int (*quitsig)();
52: int debug;
53:
54: usage()
55: {
56: fprintf(stderr, "usage: %s [-l] host\n", av0);
57: exit(1);
58: }
59:
60: main(argc, argv)
61: char **argv;
62: {
63: char *host;
64: struct stat sb;
65: int all, ld, nold;
66: extern int hupcatch();
67: char *ttyname();
68:
69: nold = 0;
70: av0 = strrchr(argv[0], '/');
71: av0 = av0==NULL ? argv[0] : av0+1;
72: while(argc>1 && argv[1][0]=='-'){
73: char *cp;
74: for(cp=&argv[1][1]; *cp; cp++)
75: switch (*cp) {
76: case 'l':
77: av0 = "con -l";
78: break;
79: case 'd':
80: debug = 1;
81: close(2);
82: creat("/tmp/con.debug", 0666);
83: break;
84: case 'n':
85: nold = 1;
86: break;
87: default:
88: usage();
89: }
90: argv++;
91: argc--;
92: }
93: host=argv[1];
94: if(strcmp(host, "helix")==0
95: || strcmp(host, "spindle")==0
96: || strcmp(host, "hobocpu")==0
97: || strcmp(host, "fornax")==0)
98: av0 = "dcon";
99: /*
100: if (host==NULL)
101: usage();
102: */
103: ioctl(0, TIOCGETP, &sgbuf);
104: ioctl(0, TIOCGETC, &tcbuf);
105: quitsig = signal(SIGQUIT, hupcatch);
106:
107: all = strcmp(av0, "con")==0;
108: if (strcmp(av0, "nogin")==0)
109: rem = trynogin(host);
110: if (all || strcmp(av0, "ndcon")==0)
111: rem = trymesg(host);
112: if (rem<0 && (all || strcmp(av0, "dcon")==0))
113: rem = trynomesg(host);
114: /*
115: if (rem<0 && (all || strcmp(av0, "9con")==0))
116: rem = try9con(host);
117: */
118: if (rem<0 && (all || strcmp(av0, "rogin")==0 || strcmp(av0, "rlogin")==0))
119: rem = tryrogin(host);
120: if (rem<0 && (all || strcmp(av0, "con -l")==0))
121: rem = trysimple(host);
122: if (rem<0) {
123: fprintf(stderr, "%s: %s connecting to %s\n", av0, errstr, host);
124: exit(1);
125: }
126:
127: /*
128: * we really have to avoid leaving mesg_ld's pushed
129: */
130: signal(SIGHUP, hupcatch);
131: signal(SIGPIPE, hupcatch);
132: if ((ttyn = ttyname(0)) != NULL
133: && stat(ttyn, &sb) >= 0) {
134: perms = sb.st_mode & ~S_IFMT;
135: chmod(ttyn, 0);
136: }
137:
138: /*
139: * push mesg_ld onto stdin and stdout if possible
140: */
141: ttyb.rmesgld = ttyb.wmesgld = netb.rmesgld = netb.wmesgld = 0;
142: if (!nold){
143: /* race ahead possible */
144: ioctl(0, TIOCFLUSH, (char *)0);
145: if(ioctl(0, FIOPUSHLD, &mesg_ld)>=0)
146: ttyb.rmesgld=1;
147: if(ioctl(1, FIOLOOKLD, &ld)>=0
148: && (ld==mesg_ld || ioctl(1, FIOPUSHLD, &mesg_ld)>=0))
149: ttyb.wmesgld=1;
150: }
151:
152: /*
153: * see if remote side accepts mesg_ld packets
154: */
155: netb.rmesgld = netb.wmesgld = ttyrem==0;
156: if(debug)
157: fprintf(stderr, "connected\n");
158: go(rem);
159: finish(0);
160: /* NOTREACHED */
161: }
162:
163: /* try to set up a message line discipline connection */
164: trymesg(host)
165: char *host;
166: {
167: int fd;
168:
169: fd = ipcopen(ipcpath(host, "dk", "mesgdcon"), "light hup");
170: if (fd<0)
171: return fd;
172: if (ipclogin(fd)<0) {
173: fprintf(stderr, "%s: can't log in\n", av0);
174: exit(1);
175: }
176: return fd;
177: }
178:
179: /* try to set up a no line discipline connection */
180: trynomesg(host)
181: char *host;
182: {
183: int fd;
184:
185: fd = ipcopen(ipcpath(host, "dk", "dcon"), "light hup");
186: if (fd<0)
187: return fd;
188: if (ipclogin(fd)<0) {
189: fprintf(stderr, "%s: can't log in\n", av0);
190: exit(1);
191: }
192: remtty(fd);
193: return fd;
194: }
195:
196: /*
197: * try to set up an dcon-like connection with local echo
198: */
199: try9con(host)
200: char *host;
201: {
202: int fd;
203: char service[256];
204:
205: sprintf(service, "nonet!%s", host);
206: fd = ipcopen(ipcpath("r70", "dk", service), "light hup bsdauth");
207: if (fd<0)
208: return fd;
209: ttyrem = 1;
210: return fd;
211: }
212:
213: /*
214: * try to set up an rlogin-like connection with local echo
215: *
216: * the authentication string is passwd by ipcopen because of the bsdauth
217: * parameter. The ipcrogin passes the terminal type and gets the authentication
218: * reply.
219: */
220: trynogin(host)
221: char *host;
222: {
223: int fd;
224: char *term;
225:
226: fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth");
227: if (fd<0)
228: return fd;
229: term = getenv("TERM");
230: ipcrogin(fd, term?term:"");
231: ttyrem = 1;
232: return fd;
233: }
234:
235: /*
236: * try to set up a rlogin-like connection with remote echo
237: */
238: tryrogin(host)
239: char *host;
240: {
241: int fd;
242: char *term;
243:
244: fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth");
245: if (fd<0)
246: return fd;
247: term = getenv("TERM");
248: ipcrogin(fd, term?term:"");
249: remtty(fd);
250: return fd;
251: }
252:
253: /* try to set up a non-authenticated connection */
254: trysimple(host)
255: char *host;
256: {
257: int fd;
258:
259: fd = ipcopen(ipcpath(host, "dk", ""), "light hup 1200");
260: if (fd<0)
261: return fd;
262: remtty(fd);
263: return fd;
264: }
265:
266: /* set up for tty control to be remote */
267: remtty(fd)
268: {
269: struct sgttyb sg;
270: struct tchars tc;
271:
272: sg = sgbuf;
273: sg.sg_flags &= ~(CRMOD|ECHO|XTABS);
274: sg.sg_flags |= CBREAK;
275: ioctl(0, TIOCSETP, &sg);
276: tc.t_quitc = tcbuf.t_quitc;
277: tc.t_intrc = tc.t_startc = tc.t_stopc = tc.t_eofc = tc.t_brkc = -1;
278: ioctl(0, TIOCSETC, &tc);
279: ttyrem = 1;
280: /*
281: * HACK!!!! to make select work when connected to a
282: * delimited stream --- turn off delimiters.
283: */
284: ioctl(fd, DIOCSTREAM, 0);
285: }
286:
287:
288: go(fd)
289: {
290: int rbits, wbits;
291: struct mesg *mp;
292: int dgenerated=0;
293: int lasttype=0;
294:
295: wbits = 0;
296: ttyb.rptr = ttyb.wptr = ttyb.data;
297: ttyb.rfd = 0;
298: ttyb.wfd = 1;
299: netb.rptr = netb.wptr = netb.data;
300: netb.rfd = fd;
301: netb.wfd = fd;
302: while(1){
303: rbits = 1 | (1<<fd);
304: if(select(20, (fd_set*)&rbits, (fd_set*)&wbits, 20000) < 0){
305: if(errno != EINTR)
306: return;
307: continue;
308: }
309: if(rbits & 1)
310: if (fillbuf(&ttyb)<0)
311: return;
312: if(rbits & (1<<fd))
313: if (fillbuf(&netb)<0)
314: return;
315: while(mp = getmsg(&ttyb)) {
316: if (mp->type==M_DELIM) {
317: if (ttyrem && lasttype==M_DELIM) {
318: sendmsg(&netb, M_DATA, &tcbuf.t_eofc, 1);
319: continue;
320: }
321: }
322: lasttype = mp->type;
323: if (mp->type==M_SIGNAL)
324: switch(((struct sigmsg *)mp)->sig[0]) {
325: case SIGQUIT:
326: dolocal(mp);
327: continue;
328: case SIGINT:
329: if(!ttyrem)
330: break;
331: sendmsg(&netb, M_DATA, &tcbuf.t_intrc, 1);
332: continue;
333: }
334: mp->magic = MSGMAGIC; /* temp safety */
335: if(writemsg(&netb, mp)<0)
336: return;
337: if(!ttyrem && mp->type == M_FLUSH) {
338: remflush();
339: rbits = 0;
340: }
341: }
342: while(mp = getmsg(&netb)){
343: if(mp->type == M_HANGUP)
344: return;
345: if(mp->type == M_IOCTL){
346: doioctl(mp);
347: } else if(dgenerated && mp->type==M_DELIM){
348: dgenerated = 0;
349: } else {
350: if(writemsg(&ttyb, mp)<0)
351: return;
352: if(mp->type==M_DATA) {
353: sendmsg(&ttyb, M_DELIM, (char *)mp, 0);
354: dgenerated = 1;
355: }
356: }
357: }
358: }
359: }
360:
361: /* read in at least a complete message */
362: fillbuf(bp)
363: register struct buffer *bp;
364: {
365: register int n;
366: struct mesg *mp;
367: static int neofs;
368:
369: if(!bp->rmesgld) {
370: bp->rptr = bp->data;
371: bp->wptr = bp->data+MSGHLEN;
372: mp = (struct mesg *)bp->rptr;
373: } else {
374: /* compact */
375: n = bp->wptr-bp->rptr;
376: if (n > 0 && bp->rptr!=bp->data)
377: memcpy(bp->data, bp->rptr, n);
378: bp->rptr = bp->data;
379: bp->wptr = bp->rptr + n;
380: }
381:
382: /* try reading */
383: n = bp->data+sizeof(bp->data) - bp->wptr;
384: if (n > 0) {
385: if(debug)
386: fprintf(stderr, "read(%d)\n", bp->rfd);
387: n = read(bp->rfd, bp->wptr, n);
388: if(debug){
389: char *cp;
390: fprintf(stderr, "read(%d) returns %d\n", bp->rfd, n);
391: for(cp = bp->wptr; cp < bp->wptr+n; cp++)
392: fprintf(stderr, "<%o>\n", *cp);
393: }
394: if(n<=0){
395: if(n<0 || ++neofs>4)
396: return -1;
397: if(!bp->rmesgld)
398: bp->wptr-=MSGHLEN;
399: }
400: bp->wptr += n;
401: } else
402: neofs = 0;
403:
404: if(!bp->rmesgld) {
405: mp->type = M_DATA;
406: mp->magic = MSGMAGIC;
407: setmsgl(mp, n);
408: }
409: return 0;
410: }
411:
412: /* get the next (buffered) message */
413: struct mesg *
414: getmsg(bp)
415: struct buffer *bp;
416: {
417: struct mesg *mp = (struct mesg *)bp->rptr;
418: int n = bp->wptr - bp->rptr;
419:
420: if (n<MSGHLEN || n<MSGHLEN+msglen(mp)) {
421: if (msglen(mp)+MSGHLEN > sizeof(bp->data))
422: bp->rptr = bp->wptr = bp->data;
423: return NULL;
424: }
425: bp->rptr += MSGHLEN + msglen(mp);
426: mp->magic = MSGMAGIC;
427: return mp;
428: }
429:
430: int
431: writemsg(bp, mp)
432: struct buffer *bp;
433: struct mesg *mp;
434: {
435: int len,n;
436: char *cp;
437:
438: if(bp->wmesgld) {
439: len = MSGHLEN + msglen(mp);
440: cp = (char *)mp;
441: } else if(mp->type==M_DATA){
442: len = msglen(mp);
443: cp = ((char *)mp)+MSGHLEN;
444: } else
445: return 0;
446: if(debug)
447: fprintf(stderr, "write(%d)\n", bp->wfd);
448: n=write(bp->wfd, cp, len);
449: if(debug)
450: fprintf(stderr, "write(%d) returns %d\n", bp->wfd, n);
451: if(n!=len)
452: return -1;
453: return 0;
454: }
455:
456: doioctl(mp)
457: struct mesg *mp;
458: {
459: struct iofoo{
460: int cmd;
461: union{
462: int i;
463: char errno;
464: struct insld insld;
465: } u;
466: } *iop;
467: int cmd, ld;
468: int n;
469:
470: iop = (struct iofoo *)(((char*)mp) + MSGHLEN);
471: cmd = iop->cmd;
472: n = msglen(mp);
473: n -= sizeof(iop->cmd);
474: switch(cmd){
475: case FIOLOOKLD:
476: if(n > 0)
477: ld = iop->u.i;
478: else
479: ld = 0;
480: ld++;
481: if(ioctl(1, FIOLOOKLD, &ld) < 0)
482: goto bad;
483: iop->cmd = ld;
484: n = sizeof(iop->cmd);
485: break;
486:
487: case FIOPOPLD:
488: if(n > 0)
489: ld = iop->u.i;
490: else
491: ld = 0;
492: ld++;
493: if(ioctl(1, FIOPOPLD, &ld) < 0)
494: goto bad;
495: n = 0;
496: break;
497:
498: case FIOPUSHLD:
499: iop->u.insld.level = 0;
500: /* fall through... */
501: case FIOINSLD:
502: iop->u.insld.level++;
503: if(ioctl(1, FIOINSLD, &(iop->u.insld)) < 0)
504: goto bad;
505: n = 0;
506: break;
507:
508: default:
509: mp->magic = MSGMAGIC; /* safety */
510: writemsg(&ttyb, mp);
511: return;
512: }
513: /* locally successful */
514: mp->type = M_IOCACK;
515: mp->magic = MSGMAGIC;
516: setmsgl(mp, n);
517: writemsg(&netb, mp);
518: return;
519: bad:
520: mp->type = M_IOCNAK;
521: mp->magic = MSGMAGIC;
522: setmsgl(mp, sizeof(struct iofoo));
523: iop->u.errno = errno;
524: writemsg(&netb, mp);
525: }
526:
527: remflush()
528: {
529: char buf[5000];
530: struct mesg *mp;
531:
532: mp = (struct mesg *) buf;
533: mp->type = M_IOCTL;
534: setmsgl(mp, sizeof(int));
535: mp->magic = MSGMAGIC;
536: writemsg(&netb, (struct mesg *)buf);
537:
538: while(read(rem, buf, sizeof(buf)) > 0){
539: if(mp->type == M_HANGUP){
540: close(rem);
541: return;
542: }
543: if(mp->type == M_IOCNAK || mp->type == M_IOCACK)
544: return;
545: }
546: }
547:
548: setmsgl(mp, n)
549: register struct mesg *mp;
550: int n;
551: {
552: mp->losize = n;
553: mp->hisize = n >> 8;
554: }
555:
556: hupcatch()
557: {
558: finish(0);
559: }
560:
561: finish(sts)
562: {
563: struct mesg m;
564:
565: if(ioctl(0, FIOLOOKLD, 0) == mesg_ld) {
566: ioctl(0, FIOPOPLD, 0);
567: ioctl(0, TIOCFLUSH, (char *)0);
568: }
569: if(ioctl(1, FIOLOOKLD, 0) == mesg_ld)
570: ioctl(1, FIOPOPLD, 0);
571: if (ttyn)
572: chmod(ttyn, perms);
573: ioctl(0, TIOCSETP, &sgbuf);
574: ioctl(0, TIOCSETC, &tcbuf);
575: signal(SIGQUIT, quitsig);
576: if(sts==0)
577: write(2, "Eof\n", 4);
578: exit(sts);
579: }
580:
581: dolocal(mp)
582: register struct mesg *mp;
583: {
584: char lbuf[128+1];
585: register char *lp;
586: struct sgttyb nsgbuf;
587: struct tchars ntcbuf;
588: int done;
589: static char prompt[32];
590: struct utsname uts;
591:
592:
593: ioctl(0, FIOPOPLD, (char *)0);
594: signal(SIGQUIT, quitsig);
595: ioctl(0, TIOCFLUSH, (char *)0);
596: ioctl(0, TIOCGETP, &nsgbuf);
597: ioctl(0, TIOCSETP, &sgbuf);
598: ioctl(0, TIOCGETC, &ntcbuf);
599: ioctl(0, TIOCSETC, &tcbuf);
600: if(prompt[0]==0){
601: uname(&uts);
602: strncpy(prompt, uts.nodename, sizeof(uts.nodename));
603: prompt[sizeof(uts.nodename)] = 0;
604: strcat(prompt, ">> ");
605: }
606: if (ttyn)
607: chmod(ttyn, perms);
608: for (done=0;!done;) {
609: lp = lbuf;
610: printf(prompt);
611: fflush(stdout);
612: while (lp < &lbuf[128] && read(0, lp, 1)>0 && *lp!='\n')
613: lp++;
614: *lp = '\0';
615: switch(*lbuf) {
616: case 'b':
617: if (ttyrem)
618: ioctl(netb.wfd, TIOCSBRK, 0);
619: else
620: sendmsg(&netb, M_BREAK, (char *)NULL, 0);
621: mp->type = 0;
622: done = 1;
623: break;
624: case 'i':
625: if (ttyrem) {
626: sendmsg(&netb, M_DATA, &tcbuf.t_quitc, 1);
627: mp->type = 0;
628: }
629: done = 1;
630: break;
631: case 'q':
632: case 'x':
633: case '.':
634: finish(1);
635: case '!':
636: system(lbuf+1);
637: printf("!!\n");
638: fflush(stdout);
639: mp->type = 0;
640: done = 1;
641: break;
642: case '\0':
643: mp->type = 0;
644: done = 1;
645: break;
646: default:
647: printf("[qx.] to exit, i for quit signal, b for break, !cmd for shell\n");
648: fflush(stdout);
649: }
650: }
651: ioctl(0, TIOCSETP, &nsgbuf);
652: ioctl(0, TIOCSETC, &ntcbuf);
653: signal(SIGQUIT, hupcatch);
654: ioctl(0, FIOPUSHLD, &mesg_ld);
655: if (ttyn)
656: chmod(ttyn, 0);
657: if (mp->type) {
658: mp->magic = MSGMAGIC; /* safety */
659: writemsg(&netb, mp);
660: }
661: }
662:
663: sendmsg(bp, type, cp, len)
664: struct buffer *bp;
665: int type, len;
666: char *cp;
667: {
668: struct amesg {
669: struct mesg m;
670: char body[128];
671: } am;
672:
673: am.m.magic = MSGMAGIC;
674: am.m.type = type;
675: setmsgl(&am.m, len);
676: if (cp!=NULL && len>0)
677: memcpy(am.body, cp, len);
678: writemsg(bp, (struct mesg *)&am);
679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.