xref: /csrg-svn/usr.bin/tip/tip.c (revision 3796)
1*3796Ssam /*	tip.c	4.3	81/05/18	*/
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
463696Sroot  */
473696Sroot 
483696Sroot #include "tip.h"
493696Sroot 
503696Sroot /*
513696Sroot  * Baud rate mapping table
523696Sroot  */
533696Sroot int bauds[] = {
543696Sroot 	0, 50, 75, 110, 134, 150, 200, 300, 600,
553696Sroot 	1200, 1800, 2400, 4800, 9600, 19200, -1
563696Sroot };
573696Sroot 
583696Sroot int	intprompt();
593696Sroot int	timeout();
603696Sroot static int cleanup();
613696Sroot 
623696Sroot main(argc, argv)
633696Sroot char *argv[];
643696Sroot {
653696Sroot 	char *system = NOSTR;
663696Sroot 	register int i;
673696Sroot #ifdef VMUNIX
683696Sroot 	int disc;
693696Sroot #endif
703696Sroot 	char *p;
713696Sroot 
723696Sroot 	if (argc > 4) {
733696Sroot 		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
743696Sroot 		exit(1);
753696Sroot 	}
763696Sroot 	if (!isatty(0)) {
773696Sroot 		fprintf(stderr, "tip: must be interactive\n");
783696Sroot 		exit(1);
793696Sroot 	}
803696Sroot 	if (argc > 1 && argv[argc-1][0] != '-')
813696Sroot 		system = argv[argc-1];		/* always last item */
823696Sroot 	signal(SIGINT, cleanup);
833696Sroot 	signal(SIGQUIT, cleanup);
843696Sroot 	signal(SIGHUP, cleanup);
853696Sroot 	signal(SIGTERM, cleanup);
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");
923696Sroot 		exit(3);
933696Sroot 	}
943719Ssam 	setbuf(stdout, NULL);
953696Sroot 	loginit();
963696Sroot 	/*
973696Sroot 	 * Now that we have the logfile and the ACU open
983696Sroot 	 *  return to the real uid and gid.  These things will
993696Sroot 	 *  be closed on exit.  Note that we can't run as root,
1003696Sroot 	 *  because locking mechanism on the tty and the accounting
1013696Sroot 	 *  will be bypassed.
1023696Sroot 	 */
1033696Sroot 	setuid(getuid());
1043696Sroot 	setgid(getgid());
1053696Sroot 	for (i = 1; i < argc-1; i++)
1063696Sroot 		if (equal(argv[i], "-v"))
1073696Sroot 			vflag++;
1083696Sroot 	/*
1093696Sroot 	 * Kludge, their's no easy way to get the initialization
1103696Sroot 	 *   in the right order, so force it here
1113696Sroot 	 */
1123696Sroot 	if ((PH = getenv("PHONES")) == NOSTR)
1133696Sroot 		PH = "/etc/phones";
1143696Sroot 	vinit();				/* init variables */
1153696Sroot 	for (i = 1; i < argc-1; i++)
1163696Sroot 		if (argv[i][0] == '-' && argv[i][1] != 'v') {
1173696Sroot 			if (isnum(argv[i][1]))
1183696Sroot 				number(value(BAUDRATE)) = atoi(&argv[i][1]);
1193696Sroot 			else
1203696Sroot 				printf("%s: unknown option\n", argv[i]);
1213696Sroot 		}
1223696Sroot 	if ((arg.sg_ispeed = speed(number(value(BAUDRATE)))) == NULL) {
1233696Sroot 		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
1243696Sroot 		delock(uucplock);
1253696Sroot 		exit(3);
1263696Sroot 	}
1273696Sroot 	arg.sg_ospeed = arg.sg_ispeed;
1283696Sroot 	/*
1293696Sroot 	 * NOTE that remote side runs in TANDEM mode,
1303696Sroot 	 *  if the host doesn't honor X-ON/X-OFF with default
1313696Sroot 	 *  start/stop chars, the remote description must be
1323696Sroot 	 *  extended and tchars will have to be set up here.
1333696Sroot 	 * If the host doesn't honor TANDEM mode, then watch
1343696Sroot 	 *  out, as you'll get garbage.
1353696Sroot 	 */
1363696Sroot 	arg.sg_flags = RAW | TANDEM;
1373696Sroot 	ioctl(FD, TIOCSETP, &arg);
1383696Sroot 
1393696Sroot 	ioctl(0, TIOCGETP, &defarg);	/* store initial status */
1403696Sroot 	ioctl(0, TIOCGETC, &defchars);
1413696Sroot 	arg = defarg;
1423696Sroot 	arg.sg_flags = ANYP | CBREAK;
1433696Sroot 	tchars = defchars;
1443696Sroot 	tchars.t_intrc = tchars.t_quitc = -1;
1453696Sroot 
1463696Sroot 	if (p = connect()) {
1473696Sroot 		printf("\07%s\n[EOT]\n", p);
1483696Sroot 		delock(uucplock);
1493696Sroot 		exit(1);
1503696Sroot 	}
1513696Sroot 	write(1, "\07connected\n", 11);
1523696Sroot 	raw();
1533696Sroot #ifdef VMUNIX
1543696Sroot 	ioctl(0, TIOCGETD, (char *)&odisc);
1553696Sroot 	disc = OTTYDISC;
1563696Sroot 	ioctl(0, TIOCSETD, (char *)&disc);
1573696Sroot #endif
1583696Sroot 	pipe(fildes); pipe(repdes);
1593696Sroot 	signal(SIGALRM, timeout);
1603696Sroot 	if (pid = fork())
1613696Sroot 		tipin();
1623696Sroot 	else
1633696Sroot 		tipout();
1643696Sroot 	/*NOTREACHED*/
1653696Sroot }
1663696Sroot 
1673696Sroot static
1683696Sroot cleanup()
1693696Sroot {
1703696Sroot 	delock(uucplock);
1713696Sroot 	exit(0);
1723696Sroot }
1733696Sroot 
1743696Sroot /*
1753696Sroot  * put the controlling keyboard into raw mode
1763696Sroot  */
1773696Sroot raw()
1783696Sroot {
1793696Sroot 	ioctl(0, TIOCSETP, &arg);
1803696Sroot 	ioctl(0, TIOCSETC, &tchars);
1813696Sroot }
1823696Sroot 
1833696Sroot 
1843696Sroot /*
1853696Sroot  * return keyboard to normal mode
1863696Sroot  */
1873696Sroot unraw()
1883696Sroot {
1893696Sroot 	ioctl(0, TIOCSETP, &defarg);
1903696Sroot 	ioctl(0, TIOCSETC, &defchars);
1913696Sroot }
1923696Sroot 
1933696Sroot /*
1943696Sroot  * Print string ``s'', then read a string
1953696Sroot  *  in from the terminal.  Handles signals & allows use of
1963696Sroot  *  normal erase and kill characters.
1973696Sroot  */
1983696Sroot prompt(s, p)
1993696Sroot 	char *s;
2003696Sroot 	register char *p;
2013696Sroot {
2023696Sroot 	register char *b = p;
2033696Sroot 
2043696Sroot 	stoprompt = 0;
2053696Sroot 	signal(SIGINT, intprompt);
2063696Sroot 	signal(SIGQUIT, SIG_IGN);
2073696Sroot 	unraw();
2083696Sroot 	printf("%s", s);
2093696Sroot 	while ((*p = getchar()) != EOF && *p != '\n') {
2103696Sroot 		if (stoprompt)
2113696Sroot 			goto pbreak;
2123696Sroot 		p++;
2133696Sroot 	}
2143696Sroot 	*p = '\0';
2153696Sroot pbreak:
2163696Sroot 	raw();
2173696Sroot 	signal(SIGINT, SIG_DFL);
2183696Sroot 	signal(SIGQUIT,SIG_DFL);
2193696Sroot 	return(stoprompt || p == b);
2203696Sroot }
2213696Sroot 
2223696Sroot /*
2233696Sroot  * Interrupt service routine during prompting
2243696Sroot  */
2253696Sroot intprompt()
2263696Sroot {
2273696Sroot 	signal(SIGINT, SIG_IGN);
2283696Sroot 	stoprompt = 1;
2293696Sroot 	printf("\r\n");
2303696Sroot }
2313696Sroot 
2323696Sroot /*
2333696Sroot  * ****TIPIN   TIPIN****
2343696Sroot  */
2353696Sroot tipin()
2363696Sroot {
2373696Sroot 	char gch, bol = 1;
2383696Sroot 
239*3796Ssam 	/*
240*3796Ssam 	 * Kinda klugey here...
241*3796Ssam 	 *   check for scripting being turned on from the .tiprc file,
242*3796Ssam 	 *   but be careful about just using setscript(), as we may
243*3796Ssam 	 *   send a SIGEMT before tipout has a chance to set up catching
244*3796Ssam 	 *   it; so wait a second, then setscript()
245*3796Ssam 	 */
246*3796Ssam 	if (boolean(value(SCRIPT))) {
247*3796Ssam 		sleep(1);
248*3796Ssam 		setscript();
249*3796Ssam 	}
250*3796Ssam 
2513696Sroot 	while (1) {
2523696Sroot 		gch = getchar()&0177;
2533696Sroot 		if ((gch == character(value(ESCAPE))) && bol) {
2543696Sroot 			if (!(gch = escape()))
2553696Sroot 				continue;
2563696Sroot 		} else if (gch == character(value(RAISECHAR))) {
2573696Sroot 			boolean(value(RAISE)) = !boolean(value(RAISE));
2583696Sroot 			printf("%s", ctrl(character(value(RAISECHAR))));
2593696Sroot 			continue;
2603696Sroot 		} else if (gch == '\r') {
2613696Sroot 			bol = 1;
2623696Sroot 			write(FD, &gch, 1);
2633696Sroot 			continue;
2643696Sroot 		} else if (gch == character(value(FORCE))) {
2653696Sroot 			printf("%s", ctrl(character(value(FORCE))));
2663696Sroot 			gch = getchar()&0177;
2673696Sroot 		}
2683696Sroot 		bol = any(gch, value(EOL));
2693696Sroot 		if (boolean(value(RAISE)) && islower(gch))
2703696Sroot 			toupper(gch);
2713696Sroot 		write(FD, &gch, 1);
2723696Sroot 	}
2733696Sroot }
2743696Sroot 
2753696Sroot /*
2763696Sroot  * Escape handler --
2773696Sroot  *  called on recognition of ``escapec'' at the beginning of a line
2783696Sroot  */
2793696Sroot escape()
2803696Sroot {
2813696Sroot 	register char gch;
2823696Sroot 	register esctable_t *p;
2833696Sroot 	char c = character(value(ESCAPE));
2843696Sroot 	extern esctable_t etable[];
2853696Sroot 
2863696Sroot 	gch = (getchar()&0177);
2873696Sroot 	for (p = etable; p->e_char; p++)
2883696Sroot 		if (p->e_char == gch) {
2893696Sroot 			if ((p->e_flags&PRIV) && getuid())
2903696Sroot 				continue;
2913696Sroot 			printf("%s", ctrl(c));
2923696Sroot 			(*p->e_func)(gch);
2933696Sroot 			return(0);
2943696Sroot 		}
2953696Sroot 
2963696Sroot 	write(FD, &c, 1);
2973696Sroot 	return(gch);
2983696Sroot }
2993696Sroot 
3003696Sroot speed(n)
3013696Sroot {
3023696Sroot 	register int *p;
3033696Sroot 
3043696Sroot 	for (p = bauds; *p != -1;  p++)
3053696Sroot 		if (*p == n)
3063696Sroot 			return(p-bauds);
3073696Sroot 	return(NULL);
3083696Sroot }
3093696Sroot 
3103696Sroot any(c, p)
3113696Sroot 	register char c, *p;
3123696Sroot {
3133696Sroot 	while (*p)
3143696Sroot 		if (*p++ == c)
3153696Sroot 			return(1);
3163696Sroot 	return(0);
3173696Sroot }
3183696Sroot 
3193696Sroot size(s)
3203696Sroot 	register char	*s;
3213696Sroot {
3223696Sroot 	register int	i = 0;
3233696Sroot 
3243696Sroot 	while (*s++) i++;
3253696Sroot 	return(i);
3263696Sroot }
3273696Sroot 
3283696Sroot char *
3293696Sroot interp(s)
3303696Sroot 	register char *s;
3313696Sroot {
3323696Sroot 	static char buf[256];
3333696Sroot 	register char *p = buf, c, *q;
3343696Sroot 
3353696Sroot 	while (c = *s++) {
3363696Sroot 		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
3373696Sroot 			if (*q++ == c) {
3383696Sroot 				*p++ = '\\'; *p++ = *q;
3393696Sroot 				goto next;
3403696Sroot 			}
3413696Sroot 		if (c < 040) {
3423696Sroot 			*p++ = '^'; *p++ = c + 'A'-1;
3433696Sroot 		} else if (c == 0177) {
3443696Sroot 			*p++ = '^'; *p++ = '?';
3453696Sroot 		} else
3463696Sroot 			*p++ = c;
3473696Sroot 	next:
3483696Sroot 		;
3493696Sroot 	}
3503696Sroot 	*p = '\0';
3513696Sroot 	return(buf);
3523696Sroot }
3533696Sroot 
3543696Sroot char *
3553696Sroot ctrl(c)
3563696Sroot 	char c;
3573696Sroot {
3583696Sroot 	static char s[3];
3593696Sroot 
3603696Sroot 	if (c < 040 || c == 0177) {
3613696Sroot 		s[0] = '^';
3623696Sroot 		s[1] = c == 0177 ? '?' : c+'A'-1;
3633696Sroot 		s[2] = '\0';
3643696Sroot 	} else {
3653696Sroot 		s[0] = c;
3663696Sroot 		s[1] = '\0';
3673696Sroot 	}
3683696Sroot 	return(s);
3693696Sroot }
3703696Sroot 
3713696Sroot /*
3723696Sroot  * Help command
3733696Sroot  */
3743696Sroot help(c)
3753696Sroot 	char c;
3763696Sroot {
3773696Sroot 	register esctable_t *p;
3783696Sroot 	extern esctable_t etable[];
3793696Sroot 
3803696Sroot 	printf("%c\r\n", c);
3813696Sroot 	for (p = etable; p->e_char; p++) {
3823696Sroot 		if ((p->e_flags&PRIV) && getuid())
3833696Sroot 			continue;
3843696Sroot 		printf("%2s", ctrl(character(value(ESCAPE))));
3853696Sroot 		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
3863696Sroot 			p->e_flags&EXP ? '*': ' ', p->e_help);
3873696Sroot 	}
3883696Sroot }
389