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