|
|
1.1 root 1: /*
2: * DCON
3: * Connect terminal to Datakit network
4: * Operation is line-at-a-time with remote echo.
5: */
6: #include <stdio.h>
7: #include <sys/param.h>
8: #include <sys/types.h>
9: #include <sgtty.h>
10: #include <signal.h>
11: #include <dk.h>
12: #include <errno.h>
13:
14: #define CEOT 04
15: #define NULL 0
16:
17:
18: struct sgttyb locvec, savloc;
19: struct tchars savechars;
20: struct ltchars lsavechars;
21: struct ltchars nlchars = { -1, -1, -1, -1, -1, -1 };
22:
23: int rem; /* remote descriptor */
24: int rembit; /* 1<<rem; for select */
25: extern int dkp_ld, dt_ld, pk_ld, mesg_ld;
26: int which_ld;
27: char serv[32]; /* .login, .dcon, etc. */
28: int autologin;
29: int noflush;
30: fd_set rdfd_set;
31: #define NSELFD (rem+1)
32: #define LINSIZ 128
33: char *space = " \r\t\n";
34: int neofs = 0; /* die when greater than N */
35:
36: int sigint();
37: extern dt_ld; /* TDK protocol line discipline */
38: extern int dkverbose ;
39: char *mytty;
40: extern char *strtok();
41: extern char *strchr();
42: extern char *strcpy();
43: extern char *strcat();
44: extern char *malloc();
45: extern FILE *scriptopen();
46: SIG_TYP savint, savquit;
47:
48: intcatch(){ /* catch interrupts, turn them into rubouts */
49: signal(SIGINT, intcatch);
50: ioctl(rem, TIOCFLUSH, 0);
51: write(rem, &savechars.t_intrc, 1);
52: ioctl(rem, TIOCFLUSH, 0);
53: ioctl(0, TIOCFLUSH, 0);
54: rdfd_set.fds_bits[0] = 0;
55: }
56:
57: quitcatch(){ /* catch quits, turn them into FS's */
58: ioctl(0, TIOCFLUSH, 0);
59: signal(SIGQUIT, quitcatch);
60: write(rem, &savechars.t_quitc, 1);
61: }
62:
63: main(argc,argv)
64: char **argv;
65: {
66: int i, traffic;
67: char dialstr[64] ;
68: int scriptlogin;
69: FILE *script;
70: extern char *getenv();
71: extern char *ttyname();
72:
73: ioctl(0, TIOCGETC, &savechars);
74: ioctl(0, TIOCGLTC, &lsavechars);
75: ioctl(0, TIOCGETP, &savloc);
76: locvec = savloc;
77: which_ld = dkp_ld;
78: strcpy(serv, ".dcon");
79: if(strcmp(argv[0], "tdcon") == 0 || getenv("TDCON") != NULL){
80: strcpy(serv, ".tdcon");
81: which_ld = dkp_ld;
82: if(strcmp(argv[1], "-x") == 0){
83: argv[1][1] = 't';
84: }
85: }
86: traffic = 0;
87: autologin = 1;
88: scriptlogin = 0;
89: for(i=1; i<argc && argv[i][0]=='-'; i++) {
90: switch(argv[i][1]) {
91: case 'f':
92: noflush++;
93: continue;
94: case 's':
95: scriptlogin = 1;
96: case 'l':
97: serv[0] = '\0';
98: autologin = 0;
99: which_ld = dt_ld;
100: continue;
101: case 'x': /* deprecated */
102: strcpy(serv, ".dcon");
103: which_ld = dkp_ld;
104: autologin = 1;
105: break;
106: case 't':
107: which_ld = dkp_ld;
108: strcpy(serv, ".tdcon");
109: break;
110: case 'd':
111: case 'b':
112: which_ld = dkp_ld;
113: break;
114: case 'c':
115: which_ld = dt_ld;
116: break;
117: case 'p':
118: case 'g':
119: which_ld = pk_ld;
120: break;
121: case 'v':
122: dkverbose++ ;
123: continue ;
124: default:
125: goto Usage;
126: }
127: }
128: if (i>=argc){
129: Usage:
130: /* don't use quit() because ioctl's aren't set up */
131: printf("usage: dcon [-lvs] hostname\n");
132: exit(1) ;
133: }
134: savint = signal(SIGINT, intcatch);
135: savquit = signal(SIGQUIT, quitcatch);
136: /*
137: * request circuit to host.
138: */
139: strcpy(dialstr, argv[i]) ;
140: if(index(dialstr, '.')){
141: serv[0] = '\0';
142: }
143: if(scriptlogin) {
144: script = scriptopen(dialstr);
145: if(script == NULL)
146: quit("bad script");
147: }
148: strcat(dialstr, serv);
149: rem = tdkdial(dialstr, traffic);
150: if (rem < 0) {
151: char msg[64];
152: extern char *dkerror;
153: sprintf(msg, "%s; call failed", dkerror);
154: quit(msg);
155: }
156: if(dkverbose) printf("cut through\n");
157: rembit = 1<<rem;
158: /*
159: * turn on line discipline according to protocol.
160: */
161: if(dkverbose) printf("pushing %d...\n", which_ld);
162: if(dkproto(rem, which_ld) < 0)
163: quit("can't turn on datakit protocol");
164: if (autologin){
165: if (tdklogin(rem) < 0)
166: quit("can't log in") ;
167: if(dkverbose) printf("logged in\n");
168: } else if(scriptlogin) {
169: if (dkscript(rem,script) < 0)
170: quit("can't log in") ;
171: if(dkverbose) fprintf(stderr,"logged in\n");
172: }
173: if(strcmp(serv, ".tdcon") == 0){
174: dotdcon(rem);
175: if(dkverbose) printf("set terminal\n");
176: }
177: locvec.sg_flags &= ~(CRMOD|ECHO|XTABS);
178: locvec.sg_flags |= CBREAK;
179: ioctl(0, TIOCSETP, &locvec);
180: ioctl(0, TIOCSLTC, &nlchars);
181:
182:
183: /*
184: * main loop.
185: */
186: ioctl(rem, DIOCSTREAM, (char *)0);
187: do; while(scan() != -1);
188: quit("select failed");
189: /*NOTREACHED*/
190: }
191: scan()
192: {
193: extern errno;
194: Loop:
195: rdfd_set.fds_bits[0] = 1|(1<<rem);
196: if(select(NSELFD, &rdfd_set, (fd_set *)0, 2000) == -1)
197: if(errno == EINTR)
198: goto Loop;
199: else
200: return -1;
201: if(rdfd_set.fds_bits[0] == 0) /* timeout */
202: goto Loop;
203: if(rdfd_set.fds_bits[0] & 1)
204: keyboard();
205: if(rdfd_set.fds_bits[0] & rembit)
206: remote();
207: return 0;
208: }
209:
210: quit(s)
211: char *s;
212: {
213: printf("dcon: %s\n", s);
214: ioctl(0, TIOCSETP, &savloc);
215: ioctl(0, TIOCSLTC, &lsavechars);
216: signal(SIGINT, SIG_DFL);
217: if (noflush==0) {
218: ioctl(rem, TIOCFLUSH, 0);
219: savloc.sg_ispeed = savloc.sg_ospeed = 0; /* hangup */
220: ioctl(rem, TIOCSETP, &savloc);
221: }
222: close(rem);
223: exit(strcmp(s, "eof"));
224: }
225:
226: /*
227: * Scan data from keyboard, looking for escape lines.
228: */
229: keyboard()
230: {
231: register c;
232: register cc;
233: register char *bp;
234: register char *be, *obp;
235: char buf[1024];
236: static char line[128];
237: static char *linep = &line[0];
238: static col = 0;
239: long time();
240: static long timev[2];
241:
242: cc = read(0, buf, sizeof buf);
243: if(cc <0){
244: if(errno == EINTR)
245: return;
246: }
247: if(cc <= 0)
248: quit("read error on file descriptor 0");
249: be = buf+cc;
250: bp = obp = buf;
251: while(bp < be) {
252: c = *bp++;
253: if (col==0 && c=='~') {
254: *linep++ = c;
255: col = 1;
256: locvec.sg_flags |= savloc.sg_flags&(CRMOD|ECHO);
257: ioctl(0, TIOCSETP, &locvec);
258: write(1, linep-1, 1);
259: continue;
260: }
261: col++;
262: if (c=='\r')
263: c = '\n';
264: if (linep>line) {
265: *linep++ = c;
266: if (c==savloc.sg_kill)
267: write(1, "\n", 1);
268: if (c==savloc.sg_erase)
269: linep -= 2;
270: if (c==savloc.sg_kill || linep<=line) {
271: linep = line;
272: locvec.sg_flags &= ~(CRMOD|ECHO);
273: ioctl(0, TIOCSETP, &locvec);
274: col = 0;
275: obp = bp;
276: }
277: }
278: if (c=='\n') {
279: col = 0;
280: if (linep > line) {
281: *linep = '\0';
282: if (escape(line+1, linep))
283: write(rem, line+1, linep-line-1);
284: obp = bp;
285: linep = line;
286: locvec.sg_flags &= ~(CRMOD|ECHO);
287: ioctl(0, TIOCSETP, &locvec);
288: }
289: }
290: }
291: if (bp>obp && linep==line)
292: write(rem, obp, bp-obp);
293: }
294:
295: /*
296: * Send data from remote machine to standard output (trivial)
297: */
298: remote(){
299: char buf[1024];
300: register n;
301:
302: n = read(rem, buf, sizeof buf);
303: if(n < 0 && errno == EINTR)
304: return;
305: if(n <= 0){
306: if(dkverbose) printf("EOF %d\r\n", neofs);
307: if(neofs++ > 4){
308: quit("Eof\r");
309: }
310: return;
311: }
312: neofs = 0;
313: write(1, buf, n);
314: }
315:
316: escape(line, end)
317: register char *line;
318: {
319: int cc;
320:
321: switch(*line++) {
322: case '!':
323: cunix(line);
324: return(0);
325:
326: case '.':
327: case CEOT:
328: quit("eof");
329:
330: case 'b':
331: ioctl(rem, TIOCSBRK, 0);
332: return(0);
333: default:
334: return(1);
335: }
336: }
337:
338: cunix(prog)
339: char *prog;
340: {
341: register int upid;
342: int retcode;
343:
344: if ((upid = fork()) == 0) {
345: signal(SIGINT, savint);
346: signal(SIGQUIT, savquit);
347: ioctl(0, TIOCSETN, &savloc);
348: ioctl(0, TIOCSLTC, &lsavechars);
349: if (*prog == '\n')
350: execl("/bin/sh", "sh", "-i", 0);
351: else
352: execl("/bin/sh","sh","-c",prog,0);
353: exit(0100);
354: }
355: if (upid < 0) {
356: printf("can't fork\n");
357: } else {
358: while((wait(&retcode) !=upid))
359: ;
360: }
361: signal(SIGINT, intcatch);
362: signal(SIGQUIT, quitcatch);
363: ioctl(0, TIOCSETN, &locvec);
364: ioctl(0, TIOCSLTC, &nlchars);
365: printf("!!\n");
366: }
367:
368: int tfd;
369:
370: dotdcon(fd)
371: {
372: char *p, *getenv();
373: char buf[3000];
374: char c;
375:
376: tfd = fd;
377: if((p = getenv("TERM")) != NULL && strlen(p) < (sizeof(buf) - 20)){
378: sprintf(buf, "TERM=%s", p);
379: tsend("env", buf);
380: }
381:
382: qsend("erase", savloc.sg_erase, '\b');
383: qsend("kill", savloc.sg_kill, '@');
384: qsend("intrc", savechars.t_intrc, '\177');
385: qsend("quitc", savechars.t_quitc, '\034');
386: qsend("startc", savechars.t_startc, 'q' & 037);
387: qsend("stopc", savechars.t_stopc, 's' & 037);
388: qsend("eofc", savechars.t_eofc, '\004');
389: qsend("brkc", savechars.t_brkc, '\377');
390:
391: if(savloc.sg_flags & XTABS) tsend("XTABS", "yes");
392: if((savloc.sg_flags & CRMOD) == 0) tsend("CRMOD", "no");
393: if((savloc.sg_flags & ECHO) == 0) tsend("ECHO", "no");
394: if(savloc.sg_flags & CBREAK) tsend("CBREAK", "yes");
395: if(savloc.sg_flags & LCASE) tsend("LCASE", "yes");
396:
397: tsend("env", "TDCON=YES");
398:
399: if((p = getenv("TDKBAG")) && strlen(p) < (sizeof(buf) - 20)){
400: sprintf(buf, "TDKBAG=%s", p);
401: tsend("env", buf);
402: }
403: /* TERMCAP is last because it might have messed up characters */
404: if((p = getenv("TERMCAP")) != NULL){
405: if(strlen(p) < (sizeof(buf) - 20)){
406: sprintf(buf, "TERMCAP=%s", p);
407: tsend("env", buf);
408: }
409: }
410:
411: write(fd, "\n", 1);
412: }
413:
414: tsend(a, b)
415: char *a, *b;
416: {
417: char *p;
418:
419: p = (char *) malloc(strlen(a) + strlen(b) + 10);
420: if(p == NULL) return;
421: sprintf(p, "%s=%s\n", a, b);
422: write(tfd, p, strlen(p));
423: if(dkverbose > 1) write(1, p, strlen(p));
424: free(p);
425: }
426:
427: ctsend(s, c)
428: char *s;
429: char c;
430: {
431: char buf[50];
432:
433: sprintf(buf, "%o", (int) c);
434: tsend(s, buf);
435: }
436:
437: qsend(s, c, wc)
438: char *s;
439: char c, wc;
440: {
441: if(c != wc)
442: ctsend(s, c);
443: }
444:
445: dkscript(rem,f)
446: FILE *f;
447: {
448: char sline[LINSIZ];
449: while(fgets(sline,100,f)) {
450: if(rget(rem,strtok(sline,space)) < 0)
451: return(-1);
452: if(fgets(sline,100,f)==0)
453: return(-1);
454: if(dkverbose) fprintf(stderr,"sending %s",sline);
455: write(rem,sline,strlen(sline));
456: }
457: return(1);
458: }
459:
460: rget(rem,s)
461: char *s;
462: {
463: int i;
464: char buf[LINSIZ];
465: int brkchr = s[strlen(s)-1];
466: for(;;) {
467: for(i=0; ; i++) {
468: if(i>=LINSIZ-2) {
469: buf[i] = 0;
470: strcpy(buf,&buf[LINSIZ/2]);
471: i = strlen(buf);
472: }
473: if(read(rem,&buf[i],1) <= 0)
474: return(-1);
475: buf[i] &= 0177;
476: if(buf[i] == brkchr)
477: break;
478: }
479: buf[i+1] = 0;
480: while(i>=0 && buf[i] && !strchr(space,buf[i]))
481: i--;
482: i++;
483: if(dkverbose) fprintf(stderr,"check '%s' vs '%s'\n",s,&buf[i]);
484: if(strcmp(s,&buf[i]) == 0)
485: return(1);
486: }
487: /*NOTREACHED*/
488: }
489:
490: FILE *
491: scriptopen(s)
492: char *s;
493: {
494: FILE *script = fopen(s, "r");
495: if(script == NULL)
496: return(NULL);
497: if(fgets(s,LINSIZ,script) == NULL)
498: return(NULL);
499: if(dkverbose) fprintf(stderr,"calling %s\n",s);
500: strtok(s,"\n");
501: return script;
502: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.