xref: /csrg-svn/usr.bin/tip/tip.c (revision 3898)
1*3898Ssam /*	tip.c	4.4	81/06/16	*/
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
46*3898Ssam  *
47*3898Ssam  * sjl			6-16-81
48*3898Ssam  * 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 
613696Sroot int	intprompt();
623696Sroot int	timeout();
633696Sroot static int cleanup();
643696Sroot 
653696Sroot main(argc, argv)
663696Sroot char *argv[];
673696Sroot {
683696Sroot 	char *system = NOSTR;
693696Sroot 	register int i;
703696Sroot #ifdef VMUNIX
713696Sroot 	int disc;
723696Sroot #endif
733696Sroot 	char *p;
743696Sroot 
753696Sroot 	if (argc > 4) {
763696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
773696Sroot 		exit(1);
783696Sroot 	}
793696Sroot 	if (!isatty(0)) {
803696Sroot 		fprintf(stderr, "tip: must be interactive\n");
813696Sroot 		exit(1);
823696Sroot 	}
833696Sroot 	if (argc > 1 && argv[argc-1][0] != '-')
843696Sroot 		system = argv[argc-1];		/* always last item */
853696Sroot 	signal(SIGINT, cleanup);
863696Sroot 	signal(SIGQUIT, cleanup);
873696Sroot 	signal(SIGHUP, cleanup);
883696Sroot 	signal(SIGTERM, cleanup);
89*3898Ssam 
903696Sroot 	if ((i = hunt(system)) == 0) {
913696Sroot 		printf("all ports busy\n");
923696Sroot 		exit(3);
933696Sroot 	}
943696Sroot 	if (i == -1) {
953696Sroot 		printf("link down\n");
963696Sroot 		exit(3);
973696Sroot 	}
983719Ssam 	setbuf(stdout, NULL);
993696Sroot 	loginit();
1003696Sroot 	/*
1013696Sroot 	 * Now that we have the logfile and the ACU open
1023696Sroot 	 *  return to the real uid and gid.  These things will
1033696Sroot 	 *  be closed on exit.  Note that we can't run as root,
1043696Sroot 	 *  because locking mechanism on the tty and the accounting
1053696Sroot 	 *  will be bypassed.
1063696Sroot 	 */
1073696Sroot 	setuid(getuid());
1083696Sroot 	setgid(getgid());
1093696Sroot 	for (i = 1; i < argc-1; i++)
1103696Sroot 		if (equal(argv[i], "-v"))
1113696Sroot 			vflag++;
1123696Sroot 	/*
1133696Sroot 	 * Kludge, their's no easy way to get the initialization
1143696Sroot 	 *   in the right order, so force it here
1153696Sroot 	 */
1163696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
1173696Sroot 		PH = "/etc/phones";
1183696Sroot 	vinit();				/* init variables */
1193696Sroot 	for (i = 1; i < argc-1; i++)
1203696Sroot 		if (argv[i][0] == '-' && argv[i][1] != 'v') {
1213696Sroot 			if (isnum(argv[i][1]))
1223696Sroot 				number(value(BAUDRATE)) = atoi(&argv[i][1]);
1233696Sroot 			else
1243696Sroot 				printf("%s: unknown option\n", argv[i]);
1253696Sroot 		}
1263696Sroot 	if ((arg.sg_ispeed = speed(number(value(BAUDRATE)))) == NULL) {
1273696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
1283696Sroot 		delock(uucplock);
1293696Sroot 		exit(3);
1303696Sroot 	}
131*3898Ssam 
132*3898Ssam 	if (p = connect()) {
133*3898Ssam 		printf("\07%s\n[EOT]\n", p);
134*3898Ssam 		delock(uucplock);
135*3898Ssam 		exit(1);
136*3898Ssam 	}
1373696Sroot 	arg.sg_ospeed = arg.sg_ispeed;
1383696Sroot 	/*
1393696Sroot 	 * NOTE that remote side runs in TANDEM mode,
1403696Sroot 	 *  if the host doesn't honor X-ON/X-OFF with default
1413696Sroot 	 *  start/stop chars, the remote description must be
1423696Sroot 	 *  extended and tchars will have to be set up here.
1433696Sroot 	 * If the host doesn't honor TANDEM mode, then watch
1443696Sroot 	 *  out, as you'll get garbage.
1453696Sroot 	 */
1463696Sroot 	arg.sg_flags = RAW | TANDEM;
1473696Sroot 	ioctl(FD, TIOCSETP, &arg);
1483696Sroot 
1493696Sroot 	ioctl(0, TIOCGETP, &defarg);	/* store initial status */
1503696Sroot 	ioctl(0, TIOCGETC, &defchars);
1513696Sroot 	arg = defarg;
1523696Sroot 	arg.sg_flags = ANYP | CBREAK;
1533696Sroot 	tchars = defchars;
1543696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
1553696Sroot 	raw();
1563696Sroot #ifdef VMUNIX
1573696Sroot 	ioctl(0, TIOCGETD, (char *)&odisc);
1583696Sroot 	disc = OTTYDISC;
1593696Sroot 	ioctl(0, TIOCSETD, (char *)&disc);
1603696Sroot #endif
1613696Sroot 	pipe(fildes); pipe(repdes);
1623696Sroot 	signal(SIGALRM, timeout);
163*3898Ssam 
164*3898Ssam 	/*
165*3898Ssam 	 * Everything's set up now:
166*3898Ssam 	 *	connection established (hardwired or diaulup)
167*3898Ssam 	 *	line conditioned (baud rate, mode, etc.)
168*3898Ssam 	 *	internal data structures (variables)
169*3898Ssam 	 * so, fork one process for local side and one for remote.
170*3898Ssam 	 */
171*3898Ssam 	write(1, "\07connected\r\n", 12);
1723696Sroot 	if (pid = fork())
1733696Sroot 		tipin();
1743696Sroot 	else
1753696Sroot 		tipout();
1763696Sroot 	/*NOTREACHED*/
1773696Sroot }
1783696Sroot 
1793696Sroot static
1803696Sroot cleanup()
1813696Sroot {
1823696Sroot 	delock(uucplock);
183*3898Ssam #ifdef VMUNIX
184*3898Ssam 	if (odisc)
185*3898Ssam 		ioctl(0, TIOCSETD, (char *)&odisc);
186*3898Ssam #endif
1873696Sroot 	exit(0);
1883696Sroot }
1893696Sroot 
1903696Sroot /*
1913696Sroot  * put the controlling keyboard into raw mode
1923696Sroot  */
1933696Sroot raw()
1943696Sroot {
1953696Sroot 	ioctl(0, TIOCSETP, &arg);
1963696Sroot 	ioctl(0, TIOCSETC, &tchars);
1973696Sroot }
1983696Sroot 
1993696Sroot 
2003696Sroot /*
2013696Sroot  * return keyboard to normal mode
2023696Sroot  */
2033696Sroot unraw()
2043696Sroot {
2053696Sroot 	ioctl(0, TIOCSETP, &defarg);
2063696Sroot 	ioctl(0, TIOCSETC, &defchars);
2073696Sroot }
2083696Sroot 
2093696Sroot /*
2103696Sroot  * Print string ``s'', then read a string
2113696Sroot  *  in from the terminal.  Handles signals & allows use of
2123696Sroot  *  normal erase and kill characters.
2133696Sroot  */
2143696Sroot prompt(s, p)
2153696Sroot 	char *s;
2163696Sroot 	register char *p;
2173696Sroot {
2183696Sroot 	register char *b = p;
2193696Sroot 
2203696Sroot 	stoprompt = 0;
2213696Sroot 	signal(SIGINT, intprompt);
2223696Sroot 	signal(SIGQUIT, SIG_IGN);
2233696Sroot 	unraw();
2243696Sroot 	printf("%s", s);
2253696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
2263696Sroot 		if (stoprompt)
2273696Sroot 			goto pbreak;
2283696Sroot 		p++;
2293696Sroot 	}
2303696Sroot 	*p = '\0';
2313696Sroot pbreak:
2323696Sroot 	raw();
2333696Sroot 	signal(SIGINT, SIG_DFL);
2343696Sroot 	signal(SIGQUIT,SIG_DFL);
2353696Sroot 	return(stoprompt || p == b);
2363696Sroot }
2373696Sroot 
2383696Sroot /*
2393696Sroot  * Interrupt service routine during prompting
2403696Sroot  */
2413696Sroot intprompt()
2423696Sroot {
2433696Sroot 	signal(SIGINT, SIG_IGN);
2443696Sroot 	stoprompt = 1;
2453696Sroot 	printf("\r\n");
2463696Sroot }
2473696Sroot 
2483696Sroot /*
2493696Sroot  * ****TIPIN   TIPIN****
2503696Sroot  */
2513696Sroot tipin()
2523696Sroot {
2533696Sroot 	char gch, bol = 1;
2543696Sroot 
2553796Ssam 	/*
2563796Ssam 	 * Kinda klugey here...
2573796Ssam 	 *   check for scripting being turned on from the .tiprc file,
2583796Ssam 	 *   but be careful about just using setscript(), as we may
2593796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
2603796Ssam 	 *   it; so wait a second, then setscript()
2613796Ssam 	 */
2623796Ssam 	if (boolean(value(SCRIPT))) {
2633796Ssam 		sleep(1);
2643796Ssam 		setscript();
2653796Ssam 	}
2663796Ssam 
2673696Sroot 	while (1) {
2683696Sroot 		gch = getchar()&0177;
2693696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2703696Sroot 			if (!(gch = escape()))
2713696Sroot 				continue;
2723696Sroot 		} else if (gch == character(value(RAISECHAR))) {
2733696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2743696Sroot 			printf("%s", ctrl(character(value(RAISECHAR))));
2753696Sroot 			continue;
2763696Sroot 		} else if (gch == '\r') {
2773696Sroot 			bol = 1;
2783696Sroot 			write(FD, &gch, 1);
2793696Sroot 			continue;
2803696Sroot 		} else if (gch == character(value(FORCE))) {
2813696Sroot 			printf("%s", ctrl(character(value(FORCE))));
2823696Sroot 			gch = getchar()&0177;
2833696Sroot 		}
2843696Sroot 		bol = any(gch, value(EOL));
2853696Sroot 		if (boolean(value(RAISE)) && islower(gch))
2863696Sroot 			toupper(gch);
2873696Sroot 		write(FD, &gch, 1);
2883696Sroot 	}
2893696Sroot }
2903696Sroot 
2913696Sroot /*
2923696Sroot  * Escape handler --
2933696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
2943696Sroot  */
2953696Sroot escape()
2963696Sroot {
2973696Sroot 	register char gch;
2983696Sroot 	register esctable_t *p;
2993696Sroot 	char c = character(value(ESCAPE));
3003696Sroot 	extern esctable_t etable[];
3013696Sroot 
3023696Sroot 	gch = (getchar()&0177);
3033696Sroot 	for (p = etable; p->e_char; p++)
3043696Sroot 		if (p->e_char == gch) {
3053696Sroot 			if ((p->e_flags&PRIV) && getuid())
3063696Sroot 				continue;
3073696Sroot 			printf("%s", ctrl(c));
3083696Sroot 			(*p->e_func)(gch);
3093696Sroot 			return(0);
3103696Sroot 		}
3113696Sroot 
3123696Sroot 	write(FD, &c, 1);
3133696Sroot 	return(gch);
3143696Sroot }
3153696Sroot 
3163696Sroot speed(n)
3173696Sroot {
3183696Sroot 	register int *p;
3193696Sroot 
3203696Sroot 	for (p = bauds; *p != -1;  p++)
3213696Sroot 		if (*p == n)
3223696Sroot 			return(p-bauds);
3233696Sroot 	return(NULL);
3243696Sroot }
3253696Sroot 
3263696Sroot any(c, p)
3273696Sroot 	register char c, *p;
3283696Sroot {
3293696Sroot 	while (*p)
3303696Sroot 		if (*p++ == c)
3313696Sroot 			return(1);
3323696Sroot 	return(0);
3333696Sroot }
3343696Sroot 
3353696Sroot size(s)
3363696Sroot 	register char	*s;
3373696Sroot {
3383696Sroot 	register int	i = 0;
3393696Sroot 
3403696Sroot 	while (*s++) i++;
3413696Sroot 	return(i);
3423696Sroot }
3433696Sroot 
3443696Sroot char *
3453696Sroot interp(s)
3463696Sroot 	register char *s;
3473696Sroot {
3483696Sroot 	static char buf[256];
3493696Sroot 	register char *p = buf, c, *q;
3503696Sroot 
3513696Sroot 	while (c = *s++) {
3523696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3533696Sroot 			if (*q++ == c) {
3543696Sroot 				*p++ = '\\'; *p++ = *q;
3553696Sroot 				goto next;
3563696Sroot 			}
3573696Sroot 		if (c < 040) {
3583696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3593696Sroot 		} else if (c == 0177) {
3603696Sroot 			*p++ = '^'; *p++ = '?';
3613696Sroot 		} else
3623696Sroot 			*p++ = c;
3633696Sroot 	next:
3643696Sroot 		;
3653696Sroot 	}
3663696Sroot 	*p = '\0';
3673696Sroot 	return(buf);
3683696Sroot }
3693696Sroot 
3703696Sroot char *
3713696Sroot ctrl(c)
3723696Sroot 	char c;
3733696Sroot {
3743696Sroot 	static char s[3];
3753696Sroot 
3763696Sroot 	if (c < 040 || c == 0177) {
3773696Sroot 		s[0] = '^';
3783696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3793696Sroot 		s[2] = '\0';
3803696Sroot 	} else {
3813696Sroot 		s[0] = c;
3823696Sroot 		s[1] = '\0';
3833696Sroot 	}
3843696Sroot 	return(s);
3853696Sroot }
3863696Sroot 
3873696Sroot /*
3883696Sroot  * Help command
3893696Sroot  */
3903696Sroot help(c)
3913696Sroot 	char c;
3923696Sroot {
3933696Sroot 	register esctable_t *p;
3943696Sroot 	extern esctable_t etable[];
3953696Sroot 
3963696Sroot 	printf("%c\r\n", c);
3973696Sroot 	for (p = etable; p->e_char; p++) {
3983696Sroot 		if ((p->e_flags&PRIV) && getuid())
3993696Sroot 			continue;
4003696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
4013696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
4023696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
4033696Sroot 	}
4043696Sroot }
405