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