|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)tip.c 4.16 (Berkeley) 6/28/83";
3: #endif
4:
5: /*
6: * tip - UNIX link to other systems
7: * tip [-v] [-speed] system-name
8: * or
9: * cu phone-number [-s speed] [-l line] [-a acu]
10: */
11: #include "tip.h"
12:
13: /*
14: * Baud rate mapping table
15: */
16: int bauds[] = {
17: 0, 50, 75, 110, 134, 150, 200, 300, 600,
18: 1200, 1800, 2400, 4800, 9600, 19200, -1
19: };
20:
21: int disc = OTTYDISC; /* tip normally runs this way */
22: int intprompt();
23: int timeout();
24: int cleanup();
25: char *sname();
26: extern char *sprintf();
27:
28: main(argc, argv)
29: char *argv[];
30: {
31: char *system = NOSTR;
32: register int i;
33: register char *p;
34: char sbuf[12];
35:
36: if (equal(sname(argv[0]), "cu")) {
37: cumain(argc, argv);
38: cumode = 1;
39: goto cucommon;
40: }
41:
42: if (argc > 4) {
43: fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
44: exit(1);
45: }
46: if (!isatty(0)) {
47: fprintf(stderr, "tip: must be interactive\n");
48: exit(1);
49: }
50:
51: for (; argc > 1; argv++, argc--) {
52: if (argv[1][0] != '-')
53: system = argv[1];
54: else switch (argv[1][1]) {
55:
56: case 'v':
57: vflag++;
58: break;
59:
60: case '0': case '1': case '2': case '3': case '4':
61: case '5': case '6': case '7': case '8': case '9':
62: BR = atoi(&argv[1][1]);
63: break;
64:
65: default:
66: fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
67: break;
68: }
69: }
70:
71: if (system == NOSTR)
72: goto notnumber;
73: for (p = system; *p; p++)
74: if (isalpha(*p))
75: goto notnumber;
76: PN = system; /* system name is really a phone number */
77: system = sprintf(sbuf, "tip%d", BR);
78:
79: notnumber:
80: signal(SIGINT, cleanup);
81: signal(SIGQUIT, cleanup);
82: signal(SIGHUP, cleanup);
83: signal(SIGTERM, cleanup);
84:
85: if ((i = hunt(system)) == 0) {
86: printf("all ports busy\n");
87: exit(3);
88: }
89: if (i == -1) {
90: printf("link down\n");
91: delock(uucplock);
92: exit(3);
93: }
94: setbuf(stdout, NULL);
95: loginit();
96: /*
97: * Now that we have the logfile and the ACU open
98: * return to the real uid and gid. These things will
99: * be closed on exit. Note that we can't run as root,
100: * because locking mechanism on the tty and the accounting
101: * will be bypassed.
102: */
103: setgid(getgid());
104: setuid(getuid());
105:
106: /*
107: * Kludge, their's no easy way to get the initialization
108: * in the right order, so force it here
109: */
110: if ((PH = getenv("PHONES")) == NOSTR)
111: PH = "/etc/phones";
112: vinit(); /* init variables */
113: setparity("even"); /* set the parity table */
114: if ((i = speed(number(value(BAUDRATE)))) == NULL) {
115: printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
116: delock(uucplock);
117: exit(3);
118: }
119:
120: /*
121: * Hardwired connections require the
122: * line speed set before they make any transmissions
123: * (this is particularly true of things like a DF03-AC)
124: */
125: if (HW)
126: ttysetup(i);
127: if (p = connect()) {
128: printf("\07%s\n[EOT]\n", p);
129: delock(uucplock);
130: exit(1);
131: }
132: if (!HW)
133: ttysetup(i);
134: cucommon:
135: /*
136: * From here down the code is shared with
137: * the "cu" version of tip.
138: */
139: ioctl(0, TIOCGETP, (char *)&defarg);
140: ioctl(0, TIOCGETC, (char *)&defchars);
141: ioctl(0, TIOCGLTC, (char *)&deflchars);
142: ioctl(0, TIOCGETD, (char *)&odisc);
143: arg = defarg;
144: arg.sg_flags = ANYP | CBREAK;
145: tchars = defchars;
146: tchars.t_intrc = tchars.t_quitc = -1;
147: ltchars = deflchars;
148: ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
149: = ltchars.t_lnextc = -1;
150: raw();
151:
152: pipe(fildes); pipe(repdes);
153: signal(SIGALRM, timeout);
154:
155: /*
156: * Everything's set up now:
157: * connection established (hardwired or diaulup)
158: * line conditioned (baud rate, mode, etc.)
159: * internal data structures (variables)
160: * so, fork one process for local side and one for remote.
161: */
162: printf(cumode ? "Connected\r\n" : "\07connected\r\n");
163: if (pid = fork())
164: tipin();
165: else
166: tipout();
167: /*NOTREACHED*/
168: }
169:
170: cleanup()
171: {
172:
173: delock(uucplock);
174: if (odisc)
175: ioctl(0, TIOCSETD, (char *)&odisc);
176: exit(0);
177: }
178:
179: /*
180: * put the controlling keyboard into raw mode
181: */
182: raw()
183: {
184:
185: ioctl(0, TIOCSETP, &arg);
186: ioctl(0, TIOCSETC, &tchars);
187: ioctl(0, TIOCSLTC, <chars);
188: ioctl(0, TIOCSETD, (char *)&disc);
189: }
190:
191:
192: /*
193: * return keyboard to normal mode
194: */
195: unraw()
196: {
197:
198: ioctl(0, TIOCSETD, (char *)&odisc);
199: ioctl(0, TIOCSETP, (char *)&defarg);
200: ioctl(0, TIOCSETC, (char *)&defchars);
201: ioctl(0, TIOCSLTC, (char *)&deflchars);
202: }
203:
204: static jmp_buf promptbuf;
205:
206: /*
207: * Print string ``s'', then read a string
208: * in from the terminal. Handles signals & allows use of
209: * normal erase and kill characters.
210: */
211: prompt(s, p)
212: char *s;
213: register char *p;
214: {
215: register char *b = p;
216: int (*oint)(), (*oquit)();
217:
218: stoprompt = 0;
219: oint = signal(SIGINT, intprompt);
220: oint = signal(SIGQUIT, SIG_IGN);
221: unraw();
222: printf("%s", s);
223: if (setjmp(promptbuf) == 0)
224: while ((*p = getchar()) != EOF && *p != '\n')
225: p++;
226: *p = '\0';
227:
228: raw();
229: signal(SIGINT, oint);
230: signal(SIGQUIT, oint);
231: return (stoprompt || p == b);
232: }
233:
234: /*
235: * Interrupt service routine during prompting
236: */
237: intprompt()
238: {
239:
240: signal(SIGINT, SIG_IGN);
241: stoprompt = 1;
242: printf("\r\n");
243: longjmp(promptbuf, 1);
244: }
245:
246: /*
247: * ****TIPIN TIPIN****
248: */
249: tipin()
250: {
251: char gch, bol = 1;
252:
253: /*
254: * Kinda klugey here...
255: * check for scripting being turned on from the .tiprc file,
256: * but be careful about just using setscript(), as we may
257: * send a SIGEMT before tipout has a chance to set up catching
258: * it; so wait a second, then setscript()
259: */
260: if (boolean(value(SCRIPT))) {
261: sleep(1);
262: setscript();
263: }
264:
265: while (1) {
266: gch = getchar()&0177;
267: if ((gch == character(value(ESCAPE))) && bol) {
268: if (!(gch = escape()))
269: continue;
270: } else if (!cumode && gch == character(value(RAISECHAR))) {
271: boolean(value(RAISE)) = !boolean(value(RAISE));
272: continue;
273: } else if (gch == '\r') {
274: bol = 1;
275: pwrite(FD, &gch, 1);
276: if (boolean(value(HALFDUPLEX)))
277: printf("\r\n");
278: continue;
279: } else if (!cumode && gch == character(value(FORCE)))
280: gch = getchar()&0177;
281: bol = any(gch, value(EOL));
282: if (boolean(value(RAISE)) && islower(gch))
283: gch = toupper(gch);
284: pwrite(FD, &gch, 1);
285: if (boolean(value(HALFDUPLEX)))
286: printf("%c", gch);
287: }
288: }
289:
290: /*
291: * Escape handler --
292: * called on recognition of ``escapec'' at the beginning of a line
293: */
294: escape()
295: {
296: register char gch;
297: register esctable_t *p;
298: char c = character(value(ESCAPE));
299: extern esctable_t etable[];
300:
301: gch = (getchar()&0177);
302: for (p = etable; p->e_char; p++)
303: if (p->e_char == gch) {
304: if ((p->e_flags&PRIV) && getuid())
305: continue;
306: printf("%s", ctrl(c));
307: (*p->e_func)(gch);
308: return (0);
309: }
310: /* ESCAPE ESCAPE forces ESCAPE */
311: if (c != gch)
312: pwrite(FD, &c, 1);
313: return (gch);
314: }
315:
316: speed(n)
317: int n;
318: {
319: register int *p;
320:
321: for (p = bauds; *p != -1; p++)
322: if (*p == n)
323: return (p - bauds);
324: return (NULL);
325: }
326:
327: any(c, p)
328: register char c, *p;
329: {
330: while (p && *p)
331: if (*p++ == c)
332: return (1);
333: return (0);
334: }
335:
336: size(s)
337: register char *s;
338: {
339: register int i = 0;
340:
341: while (s && *s++)
342: i++;
343: return (i);
344: }
345:
346: char *
347: interp(s)
348: register char *s;
349: {
350: static char buf[256];
351: register char *p = buf, c, *q;
352:
353: while (c = *s++) {
354: for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
355: if (*q++ == c) {
356: *p++ = '\\'; *p++ = *q;
357: goto next;
358: }
359: if (c < 040) {
360: *p++ = '^'; *p++ = c + 'A'-1;
361: } else if (c == 0177) {
362: *p++ = '^'; *p++ = '?';
363: } else
364: *p++ = c;
365: next:
366: ;
367: }
368: *p = '\0';
369: return (buf);
370: }
371:
372: char *
373: ctrl(c)
374: char c;
375: {
376: static char s[3];
377:
378: if (c < 040 || c == 0177) {
379: s[0] = '^';
380: s[1] = c == 0177 ? '?' : c+'A'-1;
381: s[2] = '\0';
382: } else {
383: s[0] = c;
384: s[1] = '\0';
385: }
386: return (s);
387: }
388:
389: /*
390: * Help command
391: */
392: help(c)
393: char c;
394: {
395: register esctable_t *p;
396: extern esctable_t etable[];
397:
398: printf("%c\r\n", c);
399: for (p = etable; p->e_char; p++) {
400: if ((p->e_flags&PRIV) && getuid())
401: continue;
402: printf("%2s", ctrl(character(value(ESCAPE))));
403: printf("%-2s %c %s\r\n", ctrl(p->e_char),
404: p->e_flags&EXP ? '*': ' ', p->e_help);
405: }
406: }
407:
408: /*
409: * Set up the "remote" tty's state
410: */
411: ttysetup(speed)
412: int speed;
413: {
414: unsigned bits = LDECCTQ;
415:
416: arg.sg_ispeed = arg.sg_ospeed = speed;
417: arg.sg_flags = RAW;
418: if (boolean(value(TAND)))
419: arg.sg_flags |= TANDEM;
420: ioctl(FD, TIOCSETP, (char *)&arg);
421: ioctl(FD, TIOCLBIS, (char *)&bits);
422: }
423:
424: /*
425: * Return "simple" name from a file name,
426: * strip leading directories.
427: */
428: char *
429: sname(s)
430: register char *s;
431: {
432: register char *p = s;
433:
434: while (*s)
435: if (*s++ == '/')
436: p = s;
437: return (p);
438: }
439:
440: static char partab[0200];
441:
442: /*
443: * Do a write to the remote machine with the correct parity.
444: * We are doing 8 bit wide output, so we just generate a character
445: * with the right parity and output it.
446: */
447: pwrite(fd, buf, n)
448: int fd;
449: char *buf;
450: register int n;
451: {
452: register int i;
453: register char *bp;
454:
455: bp = buf;
456: for (i = 0; i < n; i++) {
457: *bp = partab[(*bp) & 0177];
458: bp++;
459: }
460: write(fd, buf, n);
461: }
462:
463: /*
464: * Build a parity table with appropriate high-order bit.
465: */
466: setparity(defparity)
467: char *defparity;
468: {
469: register int i;
470: char *parity;
471: extern char evenpartab[];
472:
473: if (value(PARITY) == NOSTR)
474: value(PARITY) = defparity;
475: parity = value(PARITY);
476: for (i = 0; i < 0200; i++)
477: partab[i] = evenpartab[i];
478: if (equal(parity, "even"))
479: return;
480: if (equal(parity, "odd")) {
481: for (i = 0; i < 0200; i++)
482: partab[i] ^= 0200; /* reverse bit 7 */
483: return;
484: }
485: if (equal(parity, "none") || equal(parity, "zero")) {
486: for (i = 0; i < 0200; i++)
487: partab[i] &= ~0200; /* turn off bit 7 */
488: return;
489: }
490: if (equal(parity, "one")) {
491: for (i = 0; i < 0200; i++)
492: partab[i] |= 0200; /* turn on bit 7 */
493: return;
494: }
495: fprintf(stderr, "%s: unknown parity value\n", PA);
496: fflush(stderr);
497: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.