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