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