xref: /csrg-svn/usr.bin/tip/tip.c (revision 13139)
1*13139Sralph /*	tip.c	4.14	83/06/15	*/
25136Ssam 
33696Sroot /*
45136Ssam  * tip - UNIX link to other systems
53696Sroot  *  tip [-v] [-speed] system-name
65136Ssam  * or
75136Ssam  *  cu phone-number [-s speed] [-l line] [-a acu]
83696Sroot  */
93696Sroot #include "tip.h"
103696Sroot 
11*13139Sralph static char *sccsid = "@(#)tip.c	4.14 06/15/83";
12*13139Sralph 
133696Sroot /*
143696Sroot  * Baud rate mapping table
153696Sroot  */
163696Sroot int bauds[] = {
173696Sroot 	0, 50, 75, 110, 134, 150, 200, 300, 600,
183696Sroot 	1200, 1800, 2400, 4800, 9600, 19200, -1
193696Sroot };
203696Sroot 
214004Ssam #ifdef VMUNIX
224004Ssam int	disc = OTTYDISC;		/* tip normally runs this way */
234004Ssam #endif
244004Ssam 
253696Sroot int	intprompt();
263696Sroot int	timeout();
275136Ssam int	cleanup();
285257Sshannon char	*sname();
295257Sshannon extern char *sprintf();
303696Sroot 
313696Sroot main(argc, argv)
324962Ssam 	char *argv[];
333696Sroot {
343696Sroot 	char *system = NOSTR;
353696Sroot 	register int i;
365257Sshannon 	register char *p;
375257Sshannon 	char sbuf[12];
383696Sroot 
395257Sshannon 	if (equal(sname(argv[0]), "cu")) {
405136Ssam 		cumain(argc, argv);
415136Ssam 		cumode = 1;
425136Ssam 		goto cucommon;
435136Ssam 	}
445136Ssam 
453696Sroot 	if (argc > 4) {
463696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
473696Sroot 		exit(1);
483696Sroot 	}
493696Sroot 	if (!isatty(0)) {
503696Sroot 		fprintf(stderr, "tip: must be interactive\n");
513696Sroot 		exit(1);
523696Sroot 	}
535257Sshannon 
545257Sshannon 	for (; argc > 1; argv++, argc--) {
555257Sshannon 		if (argv[1][0] != '-')
565257Sshannon 			system = argv[1];
575257Sshannon 		else switch (argv[1][1]) {
585257Sshannon 
595257Sshannon 		case 'v':
605257Sshannon 			vflag++;
615257Sshannon 			break;
625257Sshannon 
635257Sshannon 		case '0': case '1': case '2': case '3': case '4':
645257Sshannon 		case '5': case '6': case '7': case '8': case '9':
655257Sshannon 			BR = atoi(&argv[1][1]);
665257Sshannon 			break;
675257Sshannon 
685257Sshannon 		default:
695257Sshannon 			fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
705257Sshannon 			break;
715257Sshannon 		}
725257Sshannon 	}
735257Sshannon 
747593Sshannon 	if (system == NOSTR)
757593Sshannon 		goto notnumber;
765257Sshannon 	for (p = system; *p; p++)
775257Sshannon 		if (isalpha(*p))
785257Sshannon 			goto notnumber;
795257Sshannon 	PN = system;		/* system name is really a phone number */
805257Sshannon 	system = sprintf(sbuf, "tip%d", BR);
815257Sshannon 
825257Sshannon notnumber:
833696Sroot 	signal(SIGINT, cleanup);
843696Sroot 	signal(SIGQUIT, cleanup);
853696Sroot 	signal(SIGHUP, cleanup);
863696Sroot 	signal(SIGTERM, cleanup);
873898Ssam 
883696Sroot 	if ((i = hunt(system)) == 0) {
893696Sroot 		printf("all ports busy\n");
903696Sroot 		exit(3);
913696Sroot 	}
923696Sroot 	if (i == -1) {
933696Sroot 		printf("link down\n");
944232Ssam 		delock(uucplock);
953696Sroot 		exit(3);
963696Sroot 	}
973719Ssam 	setbuf(stdout, NULL);
983696Sroot 	loginit();
993696Sroot 	/*
1003696Sroot 	 * Now that we have the logfile and the ACU open
1013696Sroot 	 *  return to the real uid and gid.  These things will
1023696Sroot 	 *  be closed on exit.  Note that we can't run as root,
1033696Sroot 	 *  because locking mechanism on the tty and the accounting
1043696Sroot 	 *  will be bypassed.
1053696Sroot 	 */
106*13139Sralph 	setgid(getgid());
1073696Sroot 	setuid(getuid());
1085257Sshannon 
1093696Sroot 	/*
1103696Sroot 	 * Kludge, their's no easy way to get the initialization
1113696Sroot 	 *   in the right order, so force it here
1123696Sroot 	 */
1133696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
1143696Sroot 		PH = "/etc/phones";
1153696Sroot 	vinit();				/* init variables */
116*13139Sralph 	setparity();				/* set the parity table */
1174004Ssam 	if ((i = speed(number(value(BAUDRATE)))) == NULL) {
1183696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
1193696Sroot 		delock(uucplock);
1203696Sroot 		exit(3);
1213696Sroot 	}
1223898Ssam 
1234004Ssam 	/*
1244004Ssam 	 * Hardwired connections require the
1254004Ssam 	 *  line speed set before they make any transmissions
1264004Ssam 	 *  (this is particularly true of things like a DF03-AC)
1274004Ssam 	 */
1284004Ssam 	if (HW)
1294004Ssam 		ttysetup(i);
1303898Ssam 	if (p = connect()) {
1313898Ssam 		printf("\07%s\n[EOT]\n", p);
1323898Ssam 		delock(uucplock);
1333898Ssam 		exit(1);
1343898Ssam 	}
1354004Ssam 	if (!HW)
1364004Ssam 		ttysetup(i);
1375136Ssam cucommon:
1383696Sroot 	/*
1395136Ssam 	 * From here down the code is shared with
1405136Ssam 	 * the "cu" version of tip.
1413696Sroot 	 */
1424004Ssam 	ioctl(0, TIOCGETP, (char *)&defarg);
1434004Ssam 	ioctl(0, TIOCGETC, (char *)&defchars);
14412478Sroot 	ioctl(0, TIOCGLTC, (char *)&deflchars);
1454013Ssam #ifdef VMUNIX
1464004Ssam 	ioctl(0, TIOCGETD, (char *)&odisc);
1474013Ssam #endif
1483696Sroot 	arg = defarg;
1493696Sroot 	arg.sg_flags = ANYP | CBREAK;
1503696Sroot 	tchars = defchars;
1513696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
15212478Sroot 	ltchars = deflchars;
15312478Sroot 	ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
15412478Sroot 		= ltchars.t_lnextc = -1;
1553696Sroot 	raw();
1564004Ssam 
1573696Sroot 	pipe(fildes); pipe(repdes);
1583696Sroot 	signal(SIGALRM, timeout);
1593898Ssam 
1603898Ssam 	/*
1613898Ssam 	 * Everything's set up now:
1623898Ssam 	 *	connection established (hardwired or diaulup)
1633898Ssam 	 *	line conditioned (baud rate, mode, etc.)
1643898Ssam 	 *	internal data structures (variables)
1653898Ssam 	 * so, fork one process for local side and one for remote.
1663898Ssam 	 */
1675136Ssam 	printf(cumode ? "Connected\r\n" : "\07connected\r\n");
1683696Sroot 	if (pid = fork())
1693696Sroot 		tipin();
1703696Sroot 	else
1713696Sroot 		tipout();
1723696Sroot 	/*NOTREACHED*/
1733696Sroot }
1743696Sroot 
1753696Sroot cleanup()
1763696Sroot {
1773696Sroot 	delock(uucplock);
1783898Ssam #ifdef VMUNIX
1793898Ssam 	if (odisc)
1803898Ssam 		ioctl(0, TIOCSETD, (char *)&odisc);
1813898Ssam #endif
1823696Sroot 	exit(0);
1833696Sroot }
1843696Sroot 
1853696Sroot /*
1863696Sroot  * put the controlling keyboard into raw mode
1873696Sroot  */
1883696Sroot raw()
1893696Sroot {
1903696Sroot 	ioctl(0, TIOCSETP, &arg);
1913696Sroot 	ioctl(0, TIOCSETC, &tchars);
19212478Sroot 	ioctl(0, TIOCSLTC, &ltchars);
1934004Ssam #ifdef VMUNIX
1944004Ssam 	ioctl(0, TIOCSETD, (char *)&disc);
1954004Ssam #endif
1963696Sroot }
1973696Sroot 
1983696Sroot 
1993696Sroot /*
2003696Sroot  * return keyboard to normal mode
2013696Sroot  */
2023696Sroot unraw()
2033696Sroot {
2044004Ssam #ifdef VMUNIX
2054004Ssam 	ioctl(0, TIOCSETD, (char *)&odisc);
2064004Ssam #endif
2074004Ssam 	ioctl(0, TIOCSETP, (char *)&defarg);
2084004Ssam 	ioctl(0, TIOCSETC, (char *)&defchars);
20912478Sroot 	ioctl(0, TIOCSLTC, (char *)&deflchars);
2103696Sroot }
2113696Sroot 
2123696Sroot /*
2133696Sroot  * Print string ``s'', then read a string
2143696Sroot  *  in from the terminal.  Handles signals & allows use of
2153696Sroot  *  normal erase and kill characters.
2163696Sroot  */
2173696Sroot prompt(s, p)
2183696Sroot 	char *s;
2193696Sroot 	register char *p;
2203696Sroot {
2213696Sroot 	register char *b = p;
2223696Sroot 
2233696Sroot 	stoprompt = 0;
2243696Sroot 	signal(SIGINT, intprompt);
2253696Sroot 	signal(SIGQUIT, SIG_IGN);
2263696Sroot 	unraw();
2273696Sroot 	printf("%s", s);
2283696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
2293696Sroot 		if (stoprompt)
2303696Sroot 			goto pbreak;
2313696Sroot 		p++;
2323696Sroot 	}
2333696Sroot 	*p = '\0';
2343696Sroot pbreak:
2353696Sroot 	raw();
2363696Sroot 	signal(SIGINT, SIG_DFL);
2373696Sroot 	signal(SIGQUIT,SIG_DFL);
2383696Sroot 	return(stoprompt || p == b);
2393696Sroot }
2403696Sroot 
2413696Sroot /*
2423696Sroot  * Interrupt service routine during prompting
2433696Sroot  */
2443696Sroot intprompt()
2453696Sroot {
2463696Sroot 	signal(SIGINT, SIG_IGN);
2473696Sroot 	stoprompt = 1;
2483696Sroot 	printf("\r\n");
2493696Sroot }
2503696Sroot 
2513696Sroot /*
2523696Sroot  * ****TIPIN   TIPIN****
2533696Sroot  */
2543696Sroot tipin()
2553696Sroot {
2563696Sroot 	char gch, bol = 1;
2573696Sroot 
2583796Ssam 	/*
2593796Ssam 	 * Kinda klugey here...
2603796Ssam 	 *   check for scripting being turned on from the .tiprc file,
2613796Ssam 	 *   but be careful about just using setscript(), as we may
2623796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
2633796Ssam 	 *   it; so wait a second, then setscript()
2643796Ssam 	 */
2653796Ssam 	if (boolean(value(SCRIPT))) {
2663796Ssam 		sleep(1);
2673796Ssam 		setscript();
2683796Ssam 	}
2693796Ssam 
2703696Sroot 	while (1) {
2713696Sroot 		gch = getchar()&0177;
2723696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2733696Sroot 			if (!(gch = escape()))
2743696Sroot 				continue;
2755136Ssam 		} else if (!cumode && gch == character(value(RAISECHAR))) {
2763696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2773696Sroot 			continue;
2783696Sroot 		} else if (gch == '\r') {
2793696Sroot 			bol = 1;
280*13139Sralph 			pwrite(FD, &gch, 1);
281*13139Sralph 			if (boolean(value(HALFDUPLEX)))
282*13139Sralph 				printf("\r\n");
2833696Sroot 			continue;
2845136Ssam 		} else if (!cumode && gch == character(value(FORCE)))
2853696Sroot 			gch = getchar()&0177;
2863696Sroot 		bol = any(gch, value(EOL));
2873696Sroot 		if (boolean(value(RAISE)) && islower(gch))
288*13139Sralph 			gch = toupper(gch);
289*13139Sralph 		pwrite(FD, &gch, 1);
290*13139Sralph 		if (boolean(value(HALFDUPLEX)))
291*13139Sralph 			printf("%c", gch);
2923696Sroot 	}
2933696Sroot }
2943696Sroot 
2953696Sroot /*
2963696Sroot  * Escape handler --
2973696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
2983696Sroot  */
2993696Sroot escape()
3003696Sroot {
3013696Sroot 	register char gch;
3023696Sroot 	register esctable_t *p;
3033696Sroot 	char c = character(value(ESCAPE));
3043696Sroot 	extern esctable_t etable[];
3053696Sroot 
3063696Sroot 	gch = (getchar()&0177);
3073696Sroot 	for (p = etable; p->e_char; p++)
3083696Sroot 		if (p->e_char == gch) {
3093696Sroot 			if ((p->e_flags&PRIV) && getuid())
3103696Sroot 				continue;
3113696Sroot 			printf("%s", ctrl(c));
3123696Sroot 			(*p->e_func)(gch);
3133696Sroot 			return(0);
3143696Sroot 		}
3154146Ssam 	/* ESCAPE ESCAPE forces ESCAPE */
3164146Ssam 	if (c != gch)
317*13139Sralph 		pwrite(FD, &c, 1);
3183696Sroot 	return(gch);
3193696Sroot }
3203696Sroot 
3213696Sroot speed(n)
3223696Sroot {
3233696Sroot 	register int *p;
3243696Sroot 
3253696Sroot 	for (p = bauds; *p != -1;  p++)
3263696Sroot 		if (*p == n)
3273696Sroot 			return(p-bauds);
3283696Sroot 	return(NULL);
3293696Sroot }
3303696Sroot 
3313696Sroot any(c, p)
3323696Sroot 	register char c, *p;
3333696Sroot {
3347593Sshannon 	if (p)
3353696Sroot 	while (*p)
3363696Sroot 		if (*p++ == c)
3373696Sroot 			return(1);
3383696Sroot 	return(0);
3393696Sroot }
3403696Sroot 
3413696Sroot size(s)
3423696Sroot 	register char	*s;
3433696Sroot {
3443696Sroot 	register int	i = 0;
3453696Sroot 
3463696Sroot 	while (*s++) i++;
3473696Sroot 	return(i);
3483696Sroot }
3493696Sroot 
3503696Sroot char *
3513696Sroot interp(s)
3523696Sroot 	register char *s;
3533696Sroot {
3543696Sroot 	static char buf[256];
3553696Sroot 	register char *p = buf, c, *q;
3563696Sroot 
3573696Sroot 	while (c = *s++) {
3583696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3593696Sroot 			if (*q++ == c) {
3603696Sroot 				*p++ = '\\'; *p++ = *q;
3613696Sroot 				goto next;
3623696Sroot 			}
3633696Sroot 		if (c < 040) {
3643696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3653696Sroot 		} else if (c == 0177) {
3663696Sroot 			*p++ = '^'; *p++ = '?';
3673696Sroot 		} else
3683696Sroot 			*p++ = c;
3693696Sroot 	next:
3703696Sroot 		;
3713696Sroot 	}
3723696Sroot 	*p = '\0';
3733696Sroot 	return(buf);
3743696Sroot }
3753696Sroot 
3763696Sroot char *
3773696Sroot ctrl(c)
3783696Sroot 	char c;
3793696Sroot {
3803696Sroot 	static char s[3];
3813696Sroot 
3823696Sroot 	if (c < 040 || c == 0177) {
3833696Sroot 		s[0] = '^';
3843696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3853696Sroot 		s[2] = '\0';
3863696Sroot 	} else {
3873696Sroot 		s[0] = c;
3883696Sroot 		s[1] = '\0';
3893696Sroot 	}
3903696Sroot 	return(s);
3913696Sroot }
3923696Sroot 
3933696Sroot /*
3943696Sroot  * Help command
3953696Sroot  */
3963696Sroot help(c)
3973696Sroot 	char c;
3983696Sroot {
3993696Sroot 	register esctable_t *p;
4003696Sroot 	extern esctable_t etable[];
4013696Sroot 
4023696Sroot 	printf("%c\r\n", c);
4033696Sroot 	for (p = etable; p->e_char; p++) {
4043696Sroot 		if ((p->e_flags&PRIV) && getuid())
4053696Sroot 			continue;
4063696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
4073696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
4083696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
4093696Sroot 	}
4103696Sroot }
4114004Ssam 
4124004Ssam /*
4134004Ssam  * Set up the "remote" tty's state
4144004Ssam  */
4154004Ssam ttysetup(speed)
4164004Ssam {
4174004Ssam #ifdef VMUNIX
4184004Ssam 	unsigned bits = LDECCTQ;
4194004Ssam #endif
4204004Ssam 
4214004Ssam 	arg.sg_ispeed = arg.sg_ospeed = speed;
422*13139Sralph 	if (boolean(value(TAND)))
423*13139Sralph 		arg.sg_flags = TANDEM|RAW;
424*13139Sralph 	else
425*13139Sralph 		arg.sg_flags = RAW;
4264004Ssam 	ioctl(FD, TIOCSETP, (char *)&arg);
4274004Ssam #ifdef VMUNIX
4284004Ssam 	ioctl(FD, TIOCLBIS, (char *)&bits);
4294004Ssam #endif
4304004Ssam }
4315257Sshannon 
4325257Sshannon /*
4335257Sshannon  * Return "simple" name from a file name,
4345257Sshannon  * strip leading directories.
4355257Sshannon  */
4365257Sshannon char *
4375257Sshannon sname(s)
4385257Sshannon 	register char *s;
4395257Sshannon {
4405257Sshannon 	register char *p = s;
4415257Sshannon 
4425257Sshannon 	while (*s)
4435257Sshannon 		if (*s++ == '/')
4445257Sshannon 			p = s;
4455257Sshannon 	return (p);
4465257Sshannon }
447*13139Sralph 
448*13139Sralph extern char chartab[];
449*13139Sralph static char partab[0200];
450*13139Sralph 
451*13139Sralph /*
452*13139Sralph  * do a write to the remote machine with the correct parity
453*13139Sralph  * we are doing 8 bit wide output, so we just generate a character
454*13139Sralph  * with the right parity and output it.
455*13139Sralph  */
456*13139Sralph pwrite(fd, buf, n)
457*13139Sralph 	int fd;
458*13139Sralph 	char *buf;
459*13139Sralph 	register int n;
460*13139Sralph {
461*13139Sralph 	register int i;
462*13139Sralph 	register char *bp = buf;
463*13139Sralph 
464*13139Sralph 	for (i = 0, bp = buf; i < n; i++, bp++) {
465*13139Sralph 		*bp = partab[(*bp) & 0177];
466*13139Sralph 	}
467*13139Sralph 	write(fd, buf, n);
468*13139Sralph }
469*13139Sralph 
470*13139Sralph /*
471*13139Sralph  * build a parity table with the right high-order bit
472*13139Sralph  * copy an even-parity table and doctor it
473*13139Sralph  */
474*13139Sralph setparity()
475*13139Sralph {
476*13139Sralph 	int i;
477*13139Sralph 	char *parity;
478*13139Sralph 
479*13139Sralph 	if (value(PARITY) == NOSTR)
480*13139Sralph 		value(PARITY) = "even";
481*13139Sralph 
482*13139Sralph 	parity = value(PARITY);
483*13139Sralph 
484*13139Sralph 	for (i = 0; i < 0200; i++)
485*13139Sralph 		partab[i] = chartab[i];
486*13139Sralph 
487*13139Sralph 	if (equal(parity, "odd")) {
488*13139Sralph 		for (i = 0; i < 0200; i++)
489*13139Sralph 			partab[i] ^= 0200;	/* reverse bit 7 */
490*13139Sralph 	}
491*13139Sralph 	else if (equal(parity, "none") || equal(parity, "zero")) {
492*13139Sralph 		for (i = 0; i < 0200; i++)
493*13139Sralph 			partab[i] &= ~0200;	/* turn off bit 7 */
494*13139Sralph 	}
495*13139Sralph 	else if (equal(parity, "one")) {
496*13139Sralph 		for (i = 0; i < 0200; i++)
497*13139Sralph 			partab[i] |= 0200;	/* turn on bit 7 */
498*13139Sralph 	}
499*13139Sralph 	else if (equal(parity, "even")) {
500*13139Sralph 		/* table is already even parity */
501*13139Sralph 	}
502*13139Sralph 	else {
503*13139Sralph 		fprintf(stderr, "parity value %s unknown\n", PA);
504*13139Sralph 		fflush(stderr);
505*13139Sralph 	}
506*13139Sralph }
507