xref: /csrg-svn/usr.bin/tip/tip.c (revision 7593)
1*7593Sshannon /*	tip.c	4.12	82/07/29	*/
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 
113696Sroot /*
123696Sroot  * Baud rate mapping table
133696Sroot  */
143696Sroot int bauds[] = {
153696Sroot 	0, 50, 75, 110, 134, 150, 200, 300, 600,
163696Sroot 	1200, 1800, 2400, 4800, 9600, 19200, -1
173696Sroot };
183696Sroot 
194004Ssam #ifdef VMUNIX
204004Ssam int	disc = OTTYDISC;		/* tip normally runs this way */
214004Ssam #endif
224004Ssam 
233696Sroot int	intprompt();
243696Sroot int	timeout();
255136Ssam int	cleanup();
265257Sshannon char	*sname();
275257Sshannon extern char *sprintf();
283696Sroot 
293696Sroot main(argc, argv)
304962Ssam 	char *argv[];
313696Sroot {
323696Sroot 	char *system = NOSTR;
333696Sroot 	register int i;
345257Sshannon 	register char *p;
355257Sshannon 	char sbuf[12];
363696Sroot 
375257Sshannon 	if (equal(sname(argv[0]), "cu")) {
385136Ssam 		cumain(argc, argv);
395136Ssam 		cumode = 1;
405136Ssam 		goto cucommon;
415136Ssam 	}
425136Ssam 
433696Sroot 	if (argc > 4) {
443696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
453696Sroot 		exit(1);
463696Sroot 	}
473696Sroot 	if (!isatty(0)) {
483696Sroot 		fprintf(stderr, "tip: must be interactive\n");
493696Sroot 		exit(1);
503696Sroot 	}
515257Sshannon 
525257Sshannon 	for (; argc > 1; argv++, argc--) {
535257Sshannon 		if (argv[1][0] != '-')
545257Sshannon 			system = argv[1];
555257Sshannon 		else switch (argv[1][1]) {
565257Sshannon 
575257Sshannon 		case 'v':
585257Sshannon 			vflag++;
595257Sshannon 			break;
605257Sshannon 
615257Sshannon 		case '0': case '1': case '2': case '3': case '4':
625257Sshannon 		case '5': case '6': case '7': case '8': case '9':
635257Sshannon 			BR = atoi(&argv[1][1]);
645257Sshannon 			break;
655257Sshannon 
665257Sshannon 		default:
675257Sshannon 			fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
685257Sshannon 			break;
695257Sshannon 		}
705257Sshannon 	}
715257Sshannon 
72*7593Sshannon 	if (system == NOSTR)
73*7593Sshannon 		goto notnumber;
745257Sshannon 	for (p = system; *p; p++)
755257Sshannon 		if (isalpha(*p))
765257Sshannon 			goto notnumber;
775257Sshannon 	PN = system;		/* system name is really a phone number */
785257Sshannon 	system = sprintf(sbuf, "tip%d", BR);
795257Sshannon 
805257Sshannon notnumber:
813696Sroot 	signal(SIGINT, cleanup);
823696Sroot 	signal(SIGQUIT, cleanup);
833696Sroot 	signal(SIGHUP, cleanup);
843696Sroot 	signal(SIGTERM, cleanup);
853898Ssam 
863696Sroot 	if ((i = hunt(system)) == 0) {
873696Sroot 		printf("all ports busy\n");
883696Sroot 		exit(3);
893696Sroot 	}
903696Sroot 	if (i == -1) {
913696Sroot 		printf("link down\n");
924232Ssam 		delock(uucplock);
933696Sroot 		exit(3);
943696Sroot 	}
953719Ssam 	setbuf(stdout, NULL);
963696Sroot 	loginit();
973696Sroot 	/*
983696Sroot 	 * Now that we have the logfile and the ACU open
993696Sroot 	 *  return to the real uid and gid.  These things will
1003696Sroot 	 *  be closed on exit.  Note that we can't run as root,
1013696Sroot 	 *  because locking mechanism on the tty and the accounting
1023696Sroot 	 *  will be bypassed.
1033696Sroot 	 */
1043696Sroot 	setuid(getuid());
1053696Sroot 	setgid(getgid());
1065257Sshannon 
1073696Sroot 	/*
1083696Sroot 	 * Kludge, their's no easy way to get the initialization
1093696Sroot 	 *   in the right order, so force it here
1103696Sroot 	 */
1113696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
1123696Sroot 		PH = "/etc/phones";
1133696Sroot 	vinit();				/* init variables */
1144004Ssam 	if ((i = speed(number(value(BAUDRATE)))) == NULL) {
1153696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
1163696Sroot 		delock(uucplock);
1173696Sroot 		exit(3);
1183696Sroot 	}
1193898Ssam 
1204004Ssam 	/*
1214004Ssam 	 * Hardwired connections require the
1224004Ssam 	 *  line speed set before they make any transmissions
1234004Ssam 	 *  (this is particularly true of things like a DF03-AC)
1244004Ssam 	 */
1254004Ssam 	if (HW)
1264004Ssam 		ttysetup(i);
1273898Ssam 	if (p = connect()) {
1283898Ssam 		printf("\07%s\n[EOT]\n", p);
1293898Ssam 		delock(uucplock);
1303898Ssam 		exit(1);
1313898Ssam 	}
1324004Ssam 	if (!HW)
1334004Ssam 		ttysetup(i);
1345136Ssam cucommon:
1353696Sroot 	/*
1365136Ssam 	 * From here down the code is shared with
1375136Ssam 	 * the "cu" version of tip.
1383696Sroot 	 */
1394004Ssam 	ioctl(0, TIOCGETP, (char *)&defarg);
1404004Ssam 	ioctl(0, TIOCGETC, (char *)&defchars);
1414013Ssam #ifdef VMUNIX
1424004Ssam 	ioctl(0, TIOCGETD, (char *)&odisc);
1434013Ssam #endif
1443696Sroot 	arg = defarg;
1453696Sroot 	arg.sg_flags = ANYP | CBREAK;
1463696Sroot 	tchars = defchars;
1473696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
1483696Sroot 	raw();
1494004Ssam 
1503696Sroot 	pipe(fildes); pipe(repdes);
1513696Sroot 	signal(SIGALRM, timeout);
1523898Ssam 
1533898Ssam 	/*
1543898Ssam 	 * Everything's set up now:
1553898Ssam 	 *	connection established (hardwired or diaulup)
1563898Ssam 	 *	line conditioned (baud rate, mode, etc.)
1573898Ssam 	 *	internal data structures (variables)
1583898Ssam 	 * so, fork one process for local side and one for remote.
1593898Ssam 	 */
1605136Ssam 	printf(cumode ? "Connected\r\n" : "\07connected\r\n");
1613696Sroot 	if (pid = fork())
1623696Sroot 		tipin();
1633696Sroot 	else
1643696Sroot 		tipout();
1653696Sroot 	/*NOTREACHED*/
1663696Sroot }
1673696Sroot 
1683696Sroot cleanup()
1693696Sroot {
1703696Sroot 	delock(uucplock);
1713898Ssam #ifdef VMUNIX
1723898Ssam 	if (odisc)
1733898Ssam 		ioctl(0, TIOCSETD, (char *)&odisc);
1743898Ssam #endif
1753696Sroot 	exit(0);
1763696Sroot }
1773696Sroot 
1783696Sroot /*
1793696Sroot  * put the controlling keyboard into raw mode
1803696Sroot  */
1813696Sroot raw()
1823696Sroot {
1833696Sroot 	ioctl(0, TIOCSETP, &arg);
1843696Sroot 	ioctl(0, TIOCSETC, &tchars);
1854004Ssam #ifdef VMUNIX
1864004Ssam 	ioctl(0, TIOCSETD, (char *)&disc);
1874004Ssam #endif
1883696Sroot }
1893696Sroot 
1903696Sroot 
1913696Sroot /*
1923696Sroot  * return keyboard to normal mode
1933696Sroot  */
1943696Sroot unraw()
1953696Sroot {
1964004Ssam #ifdef VMUNIX
1974004Ssam 	ioctl(0, TIOCSETD, (char *)&odisc);
1984004Ssam #endif
1994004Ssam 	ioctl(0, TIOCSETP, (char *)&defarg);
2004004Ssam 	ioctl(0, TIOCSETC, (char *)&defchars);
2013696Sroot }
2023696Sroot 
2033696Sroot /*
2043696Sroot  * Print string ``s'', then read a string
2053696Sroot  *  in from the terminal.  Handles signals & allows use of
2063696Sroot  *  normal erase and kill characters.
2073696Sroot  */
2083696Sroot prompt(s, p)
2093696Sroot 	char *s;
2103696Sroot 	register char *p;
2113696Sroot {
2123696Sroot 	register char *b = p;
2133696Sroot 
2143696Sroot 	stoprompt = 0;
2153696Sroot 	signal(SIGINT, intprompt);
2163696Sroot 	signal(SIGQUIT, SIG_IGN);
2173696Sroot 	unraw();
2183696Sroot 	printf("%s", s);
2193696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
2203696Sroot 		if (stoprompt)
2213696Sroot 			goto pbreak;
2223696Sroot 		p++;
2233696Sroot 	}
2243696Sroot 	*p = '\0';
2253696Sroot pbreak:
2263696Sroot 	raw();
2273696Sroot 	signal(SIGINT, SIG_DFL);
2283696Sroot 	signal(SIGQUIT,SIG_DFL);
2293696Sroot 	return(stoprompt || p == b);
2303696Sroot }
2313696Sroot 
2323696Sroot /*
2333696Sroot  * Interrupt service routine during prompting
2343696Sroot  */
2353696Sroot intprompt()
2363696Sroot {
2373696Sroot 	signal(SIGINT, SIG_IGN);
2383696Sroot 	stoprompt = 1;
2393696Sroot 	printf("\r\n");
2403696Sroot }
2413696Sroot 
2423696Sroot /*
2433696Sroot  * ****TIPIN   TIPIN****
2443696Sroot  */
2453696Sroot tipin()
2463696Sroot {
2473696Sroot 	char gch, bol = 1;
2483696Sroot 
2493796Ssam 	/*
2503796Ssam 	 * Kinda klugey here...
2513796Ssam 	 *   check for scripting being turned on from the .tiprc file,
2523796Ssam 	 *   but be careful about just using setscript(), as we may
2533796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
2543796Ssam 	 *   it; so wait a second, then setscript()
2553796Ssam 	 */
2563796Ssam 	if (boolean(value(SCRIPT))) {
2573796Ssam 		sleep(1);
2583796Ssam 		setscript();
2593796Ssam 	}
2603796Ssam 
2613696Sroot 	while (1) {
2623696Sroot 		gch = getchar()&0177;
2633696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2643696Sroot 			if (!(gch = escape()))
2653696Sroot 				continue;
2665136Ssam 		} else if (!cumode && gch == character(value(RAISECHAR))) {
2673696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2683696Sroot 			continue;
2693696Sroot 		} else if (gch == '\r') {
2703696Sroot 			bol = 1;
2713696Sroot 			write(FD, &gch, 1);
2723696Sroot 			continue;
2735136Ssam 		} else if (!cumode && gch == character(value(FORCE)))
2743696Sroot 			gch = getchar()&0177;
2753696Sroot 		bol = any(gch, value(EOL));
2763696Sroot 		if (boolean(value(RAISE)) && islower(gch))
2773696Sroot 			toupper(gch);
2783696Sroot 		write(FD, &gch, 1);
2793696Sroot 	}
2803696Sroot }
2813696Sroot 
2823696Sroot /*
2833696Sroot  * Escape handler --
2843696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
2853696Sroot  */
2863696Sroot escape()
2873696Sroot {
2883696Sroot 	register char gch;
2893696Sroot 	register esctable_t *p;
2903696Sroot 	char c = character(value(ESCAPE));
2913696Sroot 	extern esctable_t etable[];
2923696Sroot 
2933696Sroot 	gch = (getchar()&0177);
2943696Sroot 	for (p = etable; p->e_char; p++)
2953696Sroot 		if (p->e_char == gch) {
2963696Sroot 			if ((p->e_flags&PRIV) && getuid())
2973696Sroot 				continue;
2983696Sroot 			printf("%s", ctrl(c));
2993696Sroot 			(*p->e_func)(gch);
3003696Sroot 			return(0);
3013696Sroot 		}
3024146Ssam 	/* ESCAPE ESCAPE forces ESCAPE */
3034146Ssam 	if (c != gch)
3044146Ssam 		write(FD, &c, 1);
3053696Sroot 	return(gch);
3063696Sroot }
3073696Sroot 
3083696Sroot speed(n)
3093696Sroot {
3103696Sroot 	register int *p;
3113696Sroot 
3123696Sroot 	for (p = bauds; *p != -1;  p++)
3133696Sroot 		if (*p == n)
3143696Sroot 			return(p-bauds);
3153696Sroot 	return(NULL);
3163696Sroot }
3173696Sroot 
3183696Sroot any(c, p)
3193696Sroot 	register char c, *p;
3203696Sroot {
321*7593Sshannon 	if (p)
3223696Sroot 	while (*p)
3233696Sroot 		if (*p++ == c)
3243696Sroot 			return(1);
3253696Sroot 	return(0);
3263696Sroot }
3273696Sroot 
3283696Sroot size(s)
3293696Sroot 	register char	*s;
3303696Sroot {
3313696Sroot 	register int	i = 0;
3323696Sroot 
3333696Sroot 	while (*s++) i++;
3343696Sroot 	return(i);
3353696Sroot }
3363696Sroot 
3373696Sroot char *
3383696Sroot interp(s)
3393696Sroot 	register char *s;
3403696Sroot {
3413696Sroot 	static char buf[256];
3423696Sroot 	register char *p = buf, c, *q;
3433696Sroot 
3443696Sroot 	while (c = *s++) {
3453696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3463696Sroot 			if (*q++ == c) {
3473696Sroot 				*p++ = '\\'; *p++ = *q;
3483696Sroot 				goto next;
3493696Sroot 			}
3503696Sroot 		if (c < 040) {
3513696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3523696Sroot 		} else if (c == 0177) {
3533696Sroot 			*p++ = '^'; *p++ = '?';
3543696Sroot 		} else
3553696Sroot 			*p++ = c;
3563696Sroot 	next:
3573696Sroot 		;
3583696Sroot 	}
3593696Sroot 	*p = '\0';
3603696Sroot 	return(buf);
3613696Sroot }
3623696Sroot 
3633696Sroot char *
3643696Sroot ctrl(c)
3653696Sroot 	char c;
3663696Sroot {
3673696Sroot 	static char s[3];
3683696Sroot 
3693696Sroot 	if (c < 040 || c == 0177) {
3703696Sroot 		s[0] = '^';
3713696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3723696Sroot 		s[2] = '\0';
3733696Sroot 	} else {
3743696Sroot 		s[0] = c;
3753696Sroot 		s[1] = '\0';
3763696Sroot 	}
3773696Sroot 	return(s);
3783696Sroot }
3793696Sroot 
3803696Sroot /*
3813696Sroot  * Help command
3823696Sroot  */
3833696Sroot help(c)
3843696Sroot 	char c;
3853696Sroot {
3863696Sroot 	register esctable_t *p;
3873696Sroot 	extern esctable_t etable[];
3883696Sroot 
3893696Sroot 	printf("%c\r\n", c);
3903696Sroot 	for (p = etable; p->e_char; p++) {
3913696Sroot 		if ((p->e_flags&PRIV) && getuid())
3923696Sroot 			continue;
3933696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
3943696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
3953696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
3963696Sroot 	}
3973696Sroot }
3984004Ssam 
3994004Ssam /*
4004004Ssam  * Set up the "remote" tty's state
4014004Ssam  */
4024004Ssam ttysetup(speed)
4034004Ssam {
4044004Ssam #ifdef VMUNIX
4054004Ssam 	unsigned bits = LDECCTQ;
4064004Ssam #endif
4074004Ssam 
4084004Ssam 	arg.sg_ispeed = arg.sg_ospeed = speed;
4094004Ssam 	arg.sg_flags = TANDEM|RAW;
4104004Ssam 	ioctl(FD, TIOCSETP, (char *)&arg);
4114004Ssam #ifdef VMUNIX
4124004Ssam 	ioctl(FD, TIOCLBIS, (char *)&bits);
4134004Ssam #endif
4144004Ssam }
4155257Sshannon 
4165257Sshannon /*
4175257Sshannon  * Return "simple" name from a file name,
4185257Sshannon  * strip leading directories.
4195257Sshannon  */
4205257Sshannon char *
4215257Sshannon sname(s)
4225257Sshannon 	register char *s;
4235257Sshannon {
4245257Sshannon 	register char *p = s;
4255257Sshannon 
4265257Sshannon 	while (*s)
4275257Sshannon 		if (*s++ == '/')
4285257Sshannon 			p = s;
4295257Sshannon 	return (p);
4305257Sshannon }
431