xref: /csrg-svn/usr.bin/tip/tip.c (revision 4962)
1*4962Ssam /*	tip.c	4.9	81/11/20	*/
23696Sroot /*
33696Sroot  * tip - Unix link to other systems
43696Sroot  *  tip [-v] [-speed] system-name
53696Sroot  *
63696Sroot  * Uses remote file for system descriptions.
73696Sroot  * Current commands (escapes):
83696Sroot  *
93696Sroot  *	~!	fork a shell on the local machine
103696Sroot  *	~c	change working directory on local machine
113696Sroot  *	~^D	exit tip
123696Sroot  *	~<	fetch file from remote system
133696Sroot  *	~>	send file to remote system
143696Sroot  *	~t	take a file from a remote UNIX (uses cat & echo)
153696Sroot  *	~p	send a file to a remote UNIX (uses cat)
163696Sroot  *	~|	fetch file from remote system and pipe it to
173696Sroot  *		 a local process
183696Sroot  *	~%	fork and wait for a program which inherits file
193696Sroot  *		 descriptors 3 & 4 attached to the remote machine
203696Sroot  *		 (optional by CONNECT define)
213696Sroot  *	~s	set or show variable
223696Sroot  *	~?	give a help summary
233696Sroot  *
243696Sroot  * Samuel J. Leffler	1-18-81
253696Sroot  *
263696Sroot  * sjl			2-11-81
273696Sroot  * add auto-dial stuff for the BIZCOMP
283696Sroot  *
293696Sroot  * sjl			2-14-81
303696Sroot  * cleaned up auto-dialer stuff and added variables
313696Sroot  *
323696Sroot  * sjl			2-19-81
333696Sroot  * handle quit and interrupt during calls
343696Sroot  *
353696Sroot  * sjl			3-8-81
363696Sroot  * made to pass lint
373696Sroot  *
383696Sroot  * sjl			4-11-81
393696Sroot  * mods to handle both FIOCAPACITY and FIONREAD in biz.c
403696Sroot  *
413696Sroot  * sjl			4-17-81
423696Sroot  * added take and put, made piping stuff work
433696Sroot  * honor uucp locks
443696Sroot  * rewrite remote file stuff for DN-11 like acu's and just to clean
453696Sroot  *   it up
463898Ssam  *
473898Ssam  * sjl			6-16-81
483898Ssam  * real working setup for DN-11's
493696Sroot  */
503696Sroot 
513696Sroot #include "tip.h"
523696Sroot 
533696Sroot /*
543696Sroot  * Baud rate mapping table
553696Sroot  */
563696Sroot int bauds[] = {
573696Sroot 	0, 50, 75, 110, 134, 150, 200, 300, 600,
583696Sroot 	1200, 1800, 2400, 4800, 9600, 19200, -1
593696Sroot };
603696Sroot 
614004Ssam #ifdef VMUNIX
624004Ssam int	disc = OTTYDISC;		/* tip normally runs this way */
634004Ssam #endif
644004Ssam 
653696Sroot int	intprompt();
663696Sroot int	timeout();
673696Sroot static int cleanup();
683696Sroot 
693696Sroot main(argc, argv)
70*4962Ssam 	char *argv[];
713696Sroot {
723696Sroot 	char *system = NOSTR;
733696Sroot 	register int i;
743696Sroot 	char *p;
753696Sroot 
763696Sroot 	if (argc > 4) {
773696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
783696Sroot 		exit(1);
793696Sroot 	}
803696Sroot 	if (!isatty(0)) {
813696Sroot 		fprintf(stderr, "tip: must be interactive\n");
823696Sroot 		exit(1);
833696Sroot 	}
843696Sroot 	if (argc > 1 && argv[argc-1][0] != '-')
853696Sroot 		system = argv[argc-1];		/* always last item */
863696Sroot 	signal(SIGINT, cleanup);
873696Sroot 	signal(SIGQUIT, cleanup);
883696Sroot 	signal(SIGHUP, cleanup);
893696Sroot 	signal(SIGTERM, cleanup);
903898Ssam 
913696Sroot 	if ((i = hunt(system)) == 0) {
923696Sroot 		printf("all ports busy\n");
933696Sroot 		exit(3);
943696Sroot 	}
953696Sroot 	if (i == -1) {
963696Sroot 		printf("link down\n");
974232Ssam 		delock(uucplock);
983696Sroot 		exit(3);
993696Sroot 	}
1003719Ssam 	setbuf(stdout, NULL);
1013696Sroot 	loginit();
1023696Sroot 	/*
1033696Sroot 	 * Now that we have the logfile and the ACU open
1043696Sroot 	 *  return to the real uid and gid.  These things will
1053696Sroot 	 *  be closed on exit.  Note that we can't run as root,
1063696Sroot 	 *  because locking mechanism on the tty and the accounting
1073696Sroot 	 *  will be bypassed.
1083696Sroot 	 */
1093696Sroot 	setuid(getuid());
1103696Sroot 	setgid(getgid());
1113696Sroot 	for (i = 1; i < argc-1; i++)
1123696Sroot 		if (equal(argv[i], "-v"))
1133696Sroot 			vflag++;
1143696Sroot 	/*
1153696Sroot 	 * Kludge, their's no easy way to get the initialization
1163696Sroot 	 *   in the right order, so force it here
1173696Sroot 	 */
1183696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
1193696Sroot 		PH = "/etc/phones";
1203696Sroot 	vinit();				/* init variables */
1213696Sroot 	for (i = 1; i < argc-1; i++)
1223696Sroot 		if (argv[i][0] == '-' && argv[i][1] != 'v') {
1233696Sroot 			if (isnum(argv[i][1]))
1243696Sroot 				number(value(BAUDRATE)) = atoi(&argv[i][1]);
1253696Sroot 			else
1263696Sroot 				printf("%s: unknown option\n", argv[i]);
1273696Sroot 		}
1284004Ssam 	if ((i = speed(number(value(BAUDRATE)))) == NULL) {
1293696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
1303696Sroot 		delock(uucplock);
1313696Sroot 		exit(3);
1323696Sroot 	}
1333898Ssam 
1344004Ssam 	/*
1354004Ssam 	 * Hardwired connections require the
1364004Ssam 	 *  line speed set before they make any transmissions
1374004Ssam 	 *  (this is particularly true of things like a DF03-AC)
1384004Ssam 	 */
1394004Ssam 	if (HW)
1404004Ssam 		ttysetup(i);
1413898Ssam 	if (p = connect()) {
1423898Ssam 		printf("\07%s\n[EOT]\n", p);
1433898Ssam 		delock(uucplock);
1443898Ssam 		exit(1);
1453898Ssam 	}
1464004Ssam 	if (!HW)
1474004Ssam 		ttysetup(i);
1484004Ssam 
1493696Sroot 	/*
1504004Ssam 	 * Set up local tty state
1513696Sroot 	 */
1524004Ssam 	ioctl(0, TIOCGETP, (char *)&defarg);
1534004Ssam 	ioctl(0, TIOCGETC, (char *)&defchars);
1544013Ssam #ifdef VMUNIX
1554004Ssam 	ioctl(0, TIOCGETD, (char *)&odisc);
1564013Ssam #endif
1573696Sroot 	arg = defarg;
1583696Sroot 	arg.sg_flags = ANYP | CBREAK;
1593696Sroot 	tchars = defchars;
1603696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
1613696Sroot 	raw();
1624004Ssam 
1633696Sroot 	pipe(fildes); pipe(repdes);
1643696Sroot 	signal(SIGALRM, timeout);
1653898Ssam 
1663898Ssam 	/*
1673898Ssam 	 * Everything's set up now:
1683898Ssam 	 *	connection established (hardwired or diaulup)
1693898Ssam 	 *	line conditioned (baud rate, mode, etc.)
1703898Ssam 	 *	internal data structures (variables)
1713898Ssam 	 * so, fork one process for local side and one for remote.
1723898Ssam 	 */
1733898Ssam 	write(1, "\07connected\r\n", 12);
1743696Sroot 	if (pid = fork())
1753696Sroot 		tipin();
1763696Sroot 	else
1773696Sroot 		tipout();
1783696Sroot 	/*NOTREACHED*/
1793696Sroot }
1803696Sroot 
1813696Sroot static
1823696Sroot cleanup()
1833696Sroot {
1843696Sroot 	delock(uucplock);
1853898Ssam #ifdef VMUNIX
1863898Ssam 	if (odisc)
1873898Ssam 		ioctl(0, TIOCSETD, (char *)&odisc);
1883898Ssam #endif
1893696Sroot 	exit(0);
1903696Sroot }
1913696Sroot 
1923696Sroot /*
1933696Sroot  * put the controlling keyboard into raw mode
1943696Sroot  */
1953696Sroot raw()
1963696Sroot {
1973696Sroot 	ioctl(0, TIOCSETP, &arg);
1983696Sroot 	ioctl(0, TIOCSETC, &tchars);
1994004Ssam #ifdef VMUNIX
2004004Ssam 	ioctl(0, TIOCSETD, (char *)&disc);
2014004Ssam #endif
2023696Sroot }
2033696Sroot 
2043696Sroot 
2053696Sroot /*
2063696Sroot  * return keyboard to normal mode
2073696Sroot  */
2083696Sroot unraw()
2093696Sroot {
2104004Ssam #ifdef VMUNIX
2114004Ssam 	ioctl(0, TIOCSETD, (char *)&odisc);
2124004Ssam #endif
2134004Ssam 	ioctl(0, TIOCSETP, (char *)&defarg);
2144004Ssam 	ioctl(0, TIOCSETC, (char *)&defchars);
2153696Sroot }
2163696Sroot 
2173696Sroot /*
2183696Sroot  * Print string ``s'', then read a string
2193696Sroot  *  in from the terminal.  Handles signals & allows use of
2203696Sroot  *  normal erase and kill characters.
2213696Sroot  */
2223696Sroot prompt(s, p)
2233696Sroot 	char *s;
2243696Sroot 	register char *p;
2253696Sroot {
2263696Sroot 	register char *b = p;
2273696Sroot 
2283696Sroot 	stoprompt = 0;
2293696Sroot 	signal(SIGINT, intprompt);
2303696Sroot 	signal(SIGQUIT, SIG_IGN);
2313696Sroot 	unraw();
2323696Sroot 	printf("%s", s);
2333696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
2343696Sroot 		if (stoprompt)
2353696Sroot 			goto pbreak;
2363696Sroot 		p++;
2373696Sroot 	}
2383696Sroot 	*p = '\0';
2393696Sroot pbreak:
2403696Sroot 	raw();
2413696Sroot 	signal(SIGINT, SIG_DFL);
2423696Sroot 	signal(SIGQUIT,SIG_DFL);
2433696Sroot 	return(stoprompt || p == b);
2443696Sroot }
2453696Sroot 
2463696Sroot /*
2473696Sroot  * Interrupt service routine during prompting
2483696Sroot  */
2493696Sroot intprompt()
2503696Sroot {
2513696Sroot 	signal(SIGINT, SIG_IGN);
2523696Sroot 	stoprompt = 1;
2533696Sroot 	printf("\r\n");
2543696Sroot }
2553696Sroot 
2563696Sroot /*
2573696Sroot  * ****TIPIN   TIPIN****
2583696Sroot  */
2593696Sroot tipin()
2603696Sroot {
2613696Sroot 	char gch, bol = 1;
2623696Sroot 
2633796Ssam 	/*
2643796Ssam 	 * Kinda klugey here...
2653796Ssam 	 *   check for scripting being turned on from the .tiprc file,
2663796Ssam 	 *   but be careful about just using setscript(), as we may
2673796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
2683796Ssam 	 *   it; so wait a second, then setscript()
2693796Ssam 	 */
2703796Ssam 	if (boolean(value(SCRIPT))) {
2713796Ssam 		sleep(1);
2723796Ssam 		setscript();
2733796Ssam 	}
2743796Ssam 
2753696Sroot 	while (1) {
2763696Sroot 		gch = getchar()&0177;
2773696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2783696Sroot 			if (!(gch = escape()))
2793696Sroot 				continue;
2803696Sroot 		} else if (gch == character(value(RAISECHAR))) {
2813696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2823696Sroot 			printf("%s", ctrl(character(value(RAISECHAR))));
2833696Sroot 			continue;
2843696Sroot 		} else if (gch == '\r') {
2853696Sroot 			bol = 1;
2863696Sroot 			write(FD, &gch, 1);
2873696Sroot 			continue;
2883696Sroot 		} else if (gch == character(value(FORCE))) {
2893696Sroot 			printf("%s", ctrl(character(value(FORCE))));
2903696Sroot 			gch = getchar()&0177;
2913696Sroot 		}
2923696Sroot 		bol = any(gch, value(EOL));
2933696Sroot 		if (boolean(value(RAISE)) && islower(gch))
2943696Sroot 			toupper(gch);
2953696Sroot 		write(FD, &gch, 1);
2963696Sroot 	}
2973696Sroot }
2983696Sroot 
2993696Sroot /*
3003696Sroot  * Escape handler --
3013696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
3023696Sroot  */
3033696Sroot escape()
3043696Sroot {
3053696Sroot 	register char gch;
3063696Sroot 	register esctable_t *p;
3073696Sroot 	char c = character(value(ESCAPE));
3083696Sroot 	extern esctable_t etable[];
3093696Sroot 
3103696Sroot 	gch = (getchar()&0177);
3113696Sroot 	for (p = etable; p->e_char; p++)
3123696Sroot 		if (p->e_char == gch) {
3133696Sroot 			if ((p->e_flags&PRIV) && getuid())
3143696Sroot 				continue;
3153696Sroot 			printf("%s", ctrl(c));
3163696Sroot 			(*p->e_func)(gch);
3173696Sroot 			return(0);
3183696Sroot 		}
3194146Ssam 	/* ESCAPE ESCAPE forces ESCAPE */
3204146Ssam 	if (c != gch)
3214146Ssam 		write(FD, &c, 1);
3223696Sroot 	return(gch);
3233696Sroot }
3243696Sroot 
3253696Sroot speed(n)
3263696Sroot {
3273696Sroot 	register int *p;
3283696Sroot 
3293696Sroot 	for (p = bauds; *p != -1;  p++)
3303696Sroot 		if (*p == n)
3313696Sroot 			return(p-bauds);
3323696Sroot 	return(NULL);
3333696Sroot }
3343696Sroot 
3353696Sroot any(c, p)
3363696Sroot 	register char c, *p;
3373696Sroot {
3383696Sroot 	while (*p)
3393696Sroot 		if (*p++ == c)
3403696Sroot 			return(1);
3413696Sroot 	return(0);
3423696Sroot }
3433696Sroot 
3443696Sroot size(s)
3453696Sroot 	register char	*s;
3463696Sroot {
3473696Sroot 	register int	i = 0;
3483696Sroot 
3493696Sroot 	while (*s++) i++;
3503696Sroot 	return(i);
3513696Sroot }
3523696Sroot 
3533696Sroot char *
3543696Sroot interp(s)
3553696Sroot 	register char *s;
3563696Sroot {
3573696Sroot 	static char buf[256];
3583696Sroot 	register char *p = buf, c, *q;
3593696Sroot 
3603696Sroot 	while (c = *s++) {
3613696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3623696Sroot 			if (*q++ == c) {
3633696Sroot 				*p++ = '\\'; *p++ = *q;
3643696Sroot 				goto next;
3653696Sroot 			}
3663696Sroot 		if (c < 040) {
3673696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3683696Sroot 		} else if (c == 0177) {
3693696Sroot 			*p++ = '^'; *p++ = '?';
3703696Sroot 		} else
3713696Sroot 			*p++ = c;
3723696Sroot 	next:
3733696Sroot 		;
3743696Sroot 	}
3753696Sroot 	*p = '\0';
3763696Sroot 	return(buf);
3773696Sroot }
3783696Sroot 
3793696Sroot char *
3803696Sroot ctrl(c)
3813696Sroot 	char c;
3823696Sroot {
3833696Sroot 	static char s[3];
3843696Sroot 
3853696Sroot 	if (c < 040 || c == 0177) {
3863696Sroot 		s[0] = '^';
3873696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3883696Sroot 		s[2] = '\0';
3893696Sroot 	} else {
3903696Sroot 		s[0] = c;
3913696Sroot 		s[1] = '\0';
3923696Sroot 	}
3933696Sroot 	return(s);
3943696Sroot }
3953696Sroot 
3963696Sroot /*
3973696Sroot  * Help command
3983696Sroot  */
3993696Sroot help(c)
4003696Sroot 	char c;
4013696Sroot {
4023696Sroot 	register esctable_t *p;
4033696Sroot 	extern esctable_t etable[];
4043696Sroot 
4053696Sroot 	printf("%c\r\n", c);
4063696Sroot 	for (p = etable; p->e_char; p++) {
4073696Sroot 		if ((p->e_flags&PRIV) && getuid())
4083696Sroot 			continue;
4093696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
4103696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
4113696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
4123696Sroot 	}
4133696Sroot }
4144004Ssam 
4154004Ssam /*
4164004Ssam  * Set up the "remote" tty's state
4174004Ssam  */
4184004Ssam static
4194004Ssam ttysetup(speed)
4204004Ssam {
4214004Ssam #ifdef VMUNIX
4224004Ssam 	unsigned bits = LDECCTQ;
4234004Ssam #endif
4244004Ssam 
4254004Ssam 	arg.sg_ispeed = arg.sg_ospeed = speed;
4264004Ssam 	arg.sg_flags = TANDEM|RAW;
4274004Ssam 	ioctl(FD, TIOCSETP, (char *)&arg);
4284004Ssam #ifdef VMUNIX
4294004Ssam 	ioctl(FD, TIOCLBIS, (char *)&bits);
4304004Ssam #endif
4314004Ssam }
432