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