xref: /csrg-svn/usr.bin/tip/tip.c (revision 5136)
1*5136Ssam /*	tip.c	4.10	81/11/29	*/
2*5136Ssam 
33696Sroot /*
4*5136Ssam  * tip - UNIX link to other systems
53696Sroot  *  tip [-v] [-speed] system-name
6*5136Ssam  * or
7*5136Ssam  *  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();
25*5136Ssam int	cleanup();
263696Sroot 
273696Sroot main(argc, argv)
284962Ssam 	char *argv[];
293696Sroot {
303696Sroot 	char *system = NOSTR;
313696Sroot 	register int i;
323696Sroot 	char *p;
333696Sroot 
34*5136Ssam 	if (strcmp(argv[0], "tip")) {
35*5136Ssam 		cumain(argc, argv);
36*5136Ssam 		cumode = 1;
37*5136Ssam 		goto cucommon;
38*5136Ssam 	}
39*5136Ssam 
403696Sroot 	if (argc > 4) {
413696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
423696Sroot 		exit(1);
433696Sroot 	}
443696Sroot 	if (!isatty(0)) {
453696Sroot 		fprintf(stderr, "tip: must be interactive\n");
463696Sroot 		exit(1);
473696Sroot 	}
483696Sroot 	if (argc > 1 && argv[argc-1][0] != '-')
493696Sroot 		system = argv[argc-1];		/* always last item */
503696Sroot 	signal(SIGINT, cleanup);
513696Sroot 	signal(SIGQUIT, cleanup);
523696Sroot 	signal(SIGHUP, cleanup);
533696Sroot 	signal(SIGTERM, cleanup);
543898Ssam 
553696Sroot 	if ((i = hunt(system)) == 0) {
563696Sroot 		printf("all ports busy\n");
573696Sroot 		exit(3);
583696Sroot 	}
593696Sroot 	if (i == -1) {
603696Sroot 		printf("link down\n");
614232Ssam 		delock(uucplock);
623696Sroot 		exit(3);
633696Sroot 	}
643719Ssam 	setbuf(stdout, NULL);
653696Sroot 	loginit();
663696Sroot 	/*
673696Sroot 	 * Now that we have the logfile and the ACU open
683696Sroot 	 *  return to the real uid and gid.  These things will
693696Sroot 	 *  be closed on exit.  Note that we can't run as root,
703696Sroot 	 *  because locking mechanism on the tty and the accounting
713696Sroot 	 *  will be bypassed.
723696Sroot 	 */
733696Sroot 	setuid(getuid());
743696Sroot 	setgid(getgid());
753696Sroot 	for (i = 1; i < argc-1; i++)
763696Sroot 		if (equal(argv[i], "-v"))
773696Sroot 			vflag++;
783696Sroot 	/*
793696Sroot 	 * Kludge, their's no easy way to get the initialization
803696Sroot 	 *   in the right order, so force it here
813696Sroot 	 */
823696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
833696Sroot 		PH = "/etc/phones";
843696Sroot 	vinit();				/* init variables */
853696Sroot 	for (i = 1; i < argc-1; i++)
863696Sroot 		if (argv[i][0] == '-' && argv[i][1] != 'v') {
873696Sroot 			if (isnum(argv[i][1]))
883696Sroot 				number(value(BAUDRATE)) = atoi(&argv[i][1]);
893696Sroot 			else
903696Sroot 				printf("%s: unknown option\n", argv[i]);
913696Sroot 		}
924004Ssam 	if ((i = speed(number(value(BAUDRATE)))) == NULL) {
933696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
943696Sroot 		delock(uucplock);
953696Sroot 		exit(3);
963696Sroot 	}
973898Ssam 
984004Ssam 	/*
994004Ssam 	 * Hardwired connections require the
1004004Ssam 	 *  line speed set before they make any transmissions
1014004Ssam 	 *  (this is particularly true of things like a DF03-AC)
1024004Ssam 	 */
1034004Ssam 	if (HW)
1044004Ssam 		ttysetup(i);
1053898Ssam 	if (p = connect()) {
1063898Ssam 		printf("\07%s\n[EOT]\n", p);
1073898Ssam 		delock(uucplock);
1083898Ssam 		exit(1);
1093898Ssam 	}
1104004Ssam 	if (!HW)
1114004Ssam 		ttysetup(i);
112*5136Ssam cucommon:
1133696Sroot 	/*
114*5136Ssam 	 * From here down the code is shared with
115*5136Ssam 	 * the "cu" version of tip.
1163696Sroot 	 */
1174004Ssam 	ioctl(0, TIOCGETP, (char *)&defarg);
1184004Ssam 	ioctl(0, TIOCGETC, (char *)&defchars);
1194013Ssam #ifdef VMUNIX
1204004Ssam 	ioctl(0, TIOCGETD, (char *)&odisc);
1214013Ssam #endif
1223696Sroot 	arg = defarg;
1233696Sroot 	arg.sg_flags = ANYP | CBREAK;
1243696Sroot 	tchars = defchars;
1253696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
1263696Sroot 	raw();
1274004Ssam 
1283696Sroot 	pipe(fildes); pipe(repdes);
1293696Sroot 	signal(SIGALRM, timeout);
1303898Ssam 
1313898Ssam 	/*
1323898Ssam 	 * Everything's set up now:
1333898Ssam 	 *	connection established (hardwired or diaulup)
1343898Ssam 	 *	line conditioned (baud rate, mode, etc.)
1353898Ssam 	 *	internal data structures (variables)
1363898Ssam 	 * so, fork one process for local side and one for remote.
1373898Ssam 	 */
138*5136Ssam 	printf(cumode ? "Connected\r\n" : "\07connected\r\n");
1393696Sroot 	if (pid = fork())
1403696Sroot 		tipin();
1413696Sroot 	else
1423696Sroot 		tipout();
1433696Sroot 	/*NOTREACHED*/
1443696Sroot }
1453696Sroot 
1463696Sroot cleanup()
1473696Sroot {
1483696Sroot 	delock(uucplock);
1493898Ssam #ifdef VMUNIX
1503898Ssam 	if (odisc)
1513898Ssam 		ioctl(0, TIOCSETD, (char *)&odisc);
1523898Ssam #endif
1533696Sroot 	exit(0);
1543696Sroot }
1553696Sroot 
1563696Sroot /*
1573696Sroot  * put the controlling keyboard into raw mode
1583696Sroot  */
1593696Sroot raw()
1603696Sroot {
1613696Sroot 	ioctl(0, TIOCSETP, &arg);
1623696Sroot 	ioctl(0, TIOCSETC, &tchars);
1634004Ssam #ifdef VMUNIX
1644004Ssam 	ioctl(0, TIOCSETD, (char *)&disc);
1654004Ssam #endif
1663696Sroot }
1673696Sroot 
1683696Sroot 
1693696Sroot /*
1703696Sroot  * return keyboard to normal mode
1713696Sroot  */
1723696Sroot unraw()
1733696Sroot {
1744004Ssam #ifdef VMUNIX
1754004Ssam 	ioctl(0, TIOCSETD, (char *)&odisc);
1764004Ssam #endif
1774004Ssam 	ioctl(0, TIOCSETP, (char *)&defarg);
1784004Ssam 	ioctl(0, TIOCSETC, (char *)&defchars);
1793696Sroot }
1803696Sroot 
1813696Sroot /*
1823696Sroot  * Print string ``s'', then read a string
1833696Sroot  *  in from the terminal.  Handles signals & allows use of
1843696Sroot  *  normal erase and kill characters.
1853696Sroot  */
1863696Sroot prompt(s, p)
1873696Sroot 	char *s;
1883696Sroot 	register char *p;
1893696Sroot {
1903696Sroot 	register char *b = p;
1913696Sroot 
1923696Sroot 	stoprompt = 0;
1933696Sroot 	signal(SIGINT, intprompt);
1943696Sroot 	signal(SIGQUIT, SIG_IGN);
1953696Sroot 	unraw();
1963696Sroot 	printf("%s", s);
1973696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
1983696Sroot 		if (stoprompt)
1993696Sroot 			goto pbreak;
2003696Sroot 		p++;
2013696Sroot 	}
2023696Sroot 	*p = '\0';
2033696Sroot pbreak:
2043696Sroot 	raw();
2053696Sroot 	signal(SIGINT, SIG_DFL);
2063696Sroot 	signal(SIGQUIT,SIG_DFL);
2073696Sroot 	return(stoprompt || p == b);
2083696Sroot }
2093696Sroot 
2103696Sroot /*
2113696Sroot  * Interrupt service routine during prompting
2123696Sroot  */
2133696Sroot intprompt()
2143696Sroot {
2153696Sroot 	signal(SIGINT, SIG_IGN);
2163696Sroot 	stoprompt = 1;
2173696Sroot 	printf("\r\n");
2183696Sroot }
2193696Sroot 
2203696Sroot /*
2213696Sroot  * ****TIPIN   TIPIN****
2223696Sroot  */
2233696Sroot tipin()
2243696Sroot {
2253696Sroot 	char gch, bol = 1;
2263696Sroot 
2273796Ssam 	/*
2283796Ssam 	 * Kinda klugey here...
2293796Ssam 	 *   check for scripting being turned on from the .tiprc file,
2303796Ssam 	 *   but be careful about just using setscript(), as we may
2313796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
2323796Ssam 	 *   it; so wait a second, then setscript()
2333796Ssam 	 */
2343796Ssam 	if (boolean(value(SCRIPT))) {
2353796Ssam 		sleep(1);
2363796Ssam 		setscript();
2373796Ssam 	}
2383796Ssam 
2393696Sroot 	while (1) {
2403696Sroot 		gch = getchar()&0177;
2413696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2423696Sroot 			if (!(gch = escape()))
2433696Sroot 				continue;
244*5136Ssam 		} else if (!cumode && gch == character(value(RAISECHAR))) {
2453696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2463696Sroot 			continue;
2473696Sroot 		} else if (gch == '\r') {
2483696Sroot 			bol = 1;
2493696Sroot 			write(FD, &gch, 1);
2503696Sroot 			continue;
251*5136Ssam 		} else if (!cumode && gch == character(value(FORCE)))
2523696Sroot 			gch = getchar()&0177;
2533696Sroot 		bol = any(gch, value(EOL));
2543696Sroot 		if (boolean(value(RAISE)) && islower(gch))
2553696Sroot 			toupper(gch);
2563696Sroot 		write(FD, &gch, 1);
2573696Sroot 	}
2583696Sroot }
2593696Sroot 
2603696Sroot /*
2613696Sroot  * Escape handler --
2623696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
2633696Sroot  */
2643696Sroot escape()
2653696Sroot {
2663696Sroot 	register char gch;
2673696Sroot 	register esctable_t *p;
2683696Sroot 	char c = character(value(ESCAPE));
2693696Sroot 	extern esctable_t etable[];
2703696Sroot 
2713696Sroot 	gch = (getchar()&0177);
2723696Sroot 	for (p = etable; p->e_char; p++)
2733696Sroot 		if (p->e_char == gch) {
2743696Sroot 			if ((p->e_flags&PRIV) && getuid())
2753696Sroot 				continue;
2763696Sroot 			printf("%s", ctrl(c));
2773696Sroot 			(*p->e_func)(gch);
2783696Sroot 			return(0);
2793696Sroot 		}
2804146Ssam 	/* ESCAPE ESCAPE forces ESCAPE */
2814146Ssam 	if (c != gch)
2824146Ssam 		write(FD, &c, 1);
2833696Sroot 	return(gch);
2843696Sroot }
2853696Sroot 
2863696Sroot speed(n)
2873696Sroot {
2883696Sroot 	register int *p;
2893696Sroot 
2903696Sroot 	for (p = bauds; *p != -1;  p++)
2913696Sroot 		if (*p == n)
2923696Sroot 			return(p-bauds);
2933696Sroot 	return(NULL);
2943696Sroot }
2953696Sroot 
2963696Sroot any(c, p)
2973696Sroot 	register char c, *p;
2983696Sroot {
2993696Sroot 	while (*p)
3003696Sroot 		if (*p++ == c)
3013696Sroot 			return(1);
3023696Sroot 	return(0);
3033696Sroot }
3043696Sroot 
3053696Sroot size(s)
3063696Sroot 	register char	*s;
3073696Sroot {
3083696Sroot 	register int	i = 0;
3093696Sroot 
3103696Sroot 	while (*s++) i++;
3113696Sroot 	return(i);
3123696Sroot }
3133696Sroot 
3143696Sroot char *
3153696Sroot interp(s)
3163696Sroot 	register char *s;
3173696Sroot {
3183696Sroot 	static char buf[256];
3193696Sroot 	register char *p = buf, c, *q;
3203696Sroot 
3213696Sroot 	while (c = *s++) {
3223696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3233696Sroot 			if (*q++ == c) {
3243696Sroot 				*p++ = '\\'; *p++ = *q;
3253696Sroot 				goto next;
3263696Sroot 			}
3273696Sroot 		if (c < 040) {
3283696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3293696Sroot 		} else if (c == 0177) {
3303696Sroot 			*p++ = '^'; *p++ = '?';
3313696Sroot 		} else
3323696Sroot 			*p++ = c;
3333696Sroot 	next:
3343696Sroot 		;
3353696Sroot 	}
3363696Sroot 	*p = '\0';
3373696Sroot 	return(buf);
3383696Sroot }
3393696Sroot 
3403696Sroot char *
3413696Sroot ctrl(c)
3423696Sroot 	char c;
3433696Sroot {
3443696Sroot 	static char s[3];
3453696Sroot 
3463696Sroot 	if (c < 040 || c == 0177) {
3473696Sroot 		s[0] = '^';
3483696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3493696Sroot 		s[2] = '\0';
3503696Sroot 	} else {
3513696Sroot 		s[0] = c;
3523696Sroot 		s[1] = '\0';
3533696Sroot 	}
3543696Sroot 	return(s);
3553696Sroot }
3563696Sroot 
3573696Sroot /*
3583696Sroot  * Help command
3593696Sroot  */
3603696Sroot help(c)
3613696Sroot 	char c;
3623696Sroot {
3633696Sroot 	register esctable_t *p;
3643696Sroot 	extern esctable_t etable[];
3653696Sroot 
3663696Sroot 	printf("%c\r\n", c);
3673696Sroot 	for (p = etable; p->e_char; p++) {
3683696Sroot 		if ((p->e_flags&PRIV) && getuid())
3693696Sroot 			continue;
3703696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
3713696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
3723696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
3733696Sroot 	}
3743696Sroot }
3754004Ssam 
3764004Ssam /*
3774004Ssam  * Set up the "remote" tty's state
3784004Ssam  */
3794004Ssam ttysetup(speed)
3804004Ssam {
3814004Ssam #ifdef VMUNIX
3824004Ssam 	unsigned bits = LDECCTQ;
3834004Ssam #endif
3844004Ssam 
3854004Ssam 	arg.sg_ispeed = arg.sg_ospeed = speed;
3864004Ssam 	arg.sg_flags = TANDEM|RAW;
3874004Ssam 	ioctl(FD, TIOCSETP, (char *)&arg);
3884004Ssam #ifdef VMUNIX
3894004Ssam 	ioctl(FD, TIOCLBIS, (char *)&bits);
3904004Ssam #endif
3914004Ssam }
392