xref: /csrg-svn/usr.bin/tip/cmds.c (revision 13137)
1*13137Sralph /*	cmds.c	4.11	83/06/15	*/
23688Sroot #include "tip.h"
33688Sroot /*
43688Sroot  * tip
53688Sroot  *
63688Sroot  * miscellaneous commands
73688Sroot  */
83688Sroot 
9*13137Sralph static char *sccsid = "@(#)cmds.c	4.11 06/15/83";
10*13137Sralph 
113688Sroot int	quant[] = { 60, 60, 24 };
123688Sroot 
133688Sroot char	null = '\0';
143688Sroot char	*sep[] = { "second", "minute", "hour" };
153688Sroot static char *argv[10];		/* argument vector for take and put */
163688Sroot 
173688Sroot int	timeout();		/* timeout function called on alarm */
183688Sroot int	stopsnd();		/* SIGINT handler during file transfers */
193688Sroot int	intprompt();		/* used in handling SIG_INT during prompt */
203688Sroot int	intcopy();		/* interrupt routine for file transfers */
213688Sroot 
223688Sroot /*
233688Sroot  * FTP - remote ==> local
243688Sroot  *  get a file from the remote host
253688Sroot  */
263688Sroot getfl(c)
273688Sroot 	char c;
283688Sroot {
293688Sroot 	char buf[256];
30*13137Sralph 	char *copynamex;
31*13137Sralph 	char *expand();
323688Sroot 
333688Sroot 	putchar(c);
343688Sroot 	/*
353688Sroot 	 * get the UNIX receiving file's name
363688Sroot 	 */
373688Sroot 	if (prompt("Local file name? ", copyname))
383688Sroot 		return;
39*13137Sralph 	copynamex = expand(copyname);
40*13137Sralph 	if ((sfd = creat(copynamex, 0666)) < 0) {
413688Sroot 		printf("\r\n%s: cannot creat\r\n", copyname);
423688Sroot 		return;
433688Sroot 	}
443688Sroot 
453688Sroot 	/*
463688Sroot 	 * collect parameters
473688Sroot 	 */
483688Sroot 	if (prompt("List command for remote system? ", buf)) {
493688Sroot 		unlink(copyname);
503688Sroot 		return;
513688Sroot 	}
523688Sroot 	transfer(buf, sfd, value(EOFREAD));
533688Sroot }
543688Sroot 
553688Sroot /*
563688Sroot  * Cu-like take command
573688Sroot  */
583688Sroot cu_take(cc)
593688Sroot 	char cc;
603688Sroot {
613688Sroot 	int fd, argc;
623688Sroot 	char line[BUFSIZ];
63*13137Sralph 	char *expand();
64*13137Sralph 	char *copynamex;
653688Sroot 
663688Sroot 	if (prompt("[take] ", copyname))
673688Sroot 		return;
683688Sroot 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
693688Sroot 		printf("usage: <take> from [to]\r\n");
703688Sroot 		return;
713688Sroot 	}
723688Sroot 	if (argc == 1)
733688Sroot 		argv[1] = argv[0];
74*13137Sralph 	copynamex = expand(argv[1]);
75*13137Sralph 	if ((fd = creat(copynamex, 0666)) < 0) {
763688Sroot 		printf("\r\n%s: cannot create\r\n", argv[1]);
773688Sroot 		return;
783688Sroot 	}
79*13137Sralph 	sprintf(line, "cat %s;echo \01", argv[0]);
803688Sroot 	transfer(line, fd, "\01");
813688Sroot }
823688Sroot 
833688Sroot /*
843688Sroot  * Bulk transfer routine --
853688Sroot  *  used by getfl(), cu_take(), and pipefile()
863688Sroot  */
873688Sroot transfer(buf, fd, eofchars)
883688Sroot 	char *buf, *eofchars;
893688Sroot {
903688Sroot 	register int ct;
913688Sroot 	char c, buffer[BUFSIZ];
923688Sroot 	register char *p = buffer;
933688Sroot 	register int cnt, eof;
943688Sroot 	time_t start;
953688Sroot 
96*13137Sralph 	pwrite(FD, buf, size(buf));
973688Sroot 	quit = 0;
983688Sroot 	signal(SIGINT, intcopy);
993688Sroot 	kill(pid, SIGIOT);
1003688Sroot 	read(repdes[0], (char *)&ccc, 1);  /* Wait until read process stops */
1013688Sroot 
1023688Sroot 	/*
1033688Sroot 	 * finish command
1043688Sroot 	 */
105*13137Sralph 	pwrite(FD, "\r", 1);
1063688Sroot 	do
1073688Sroot 		read(FD, &c, 1);
1083688Sroot 	while ((c&0177) != '\n');
1093688Sroot 	ioctl(0, TIOCSETC, &defchars);
1103688Sroot 
1113688Sroot 	start = time(0);
1123688Sroot 	for (ct = 0; !quit;) {
1133688Sroot 		eof = read(FD, &c, 1) <= 0;
1143688Sroot 		c &= 0177;
1153688Sroot 		if (quit)
1163688Sroot 			continue;
1173688Sroot 		if (eof || any(c, eofchars))
1183688Sroot 			break;
1193688Sroot 		if (c == 0)
1203688Sroot 			continue;	/* ignore nulls */
1213688Sroot 		if (c == '\r')
1223688Sroot 			continue;
1233688Sroot 		*p++ = c;
1243688Sroot 
1253688Sroot 		if (c == '\n' && boolean(value(VERBOSE)))
1263688Sroot 			printf("\r%d", ++ct);
1273688Sroot 		if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
1283688Sroot 			if (write(fd, buffer, cnt) != cnt) {
1293688Sroot 				printf("\r\nwrite error\r\n");
1303688Sroot 				quit = 1;
1313688Sroot 			}
1323688Sroot 			p = buffer;
1333688Sroot 		}
1343688Sroot 	}
1353688Sroot 	if (cnt = (p-buffer))
1363688Sroot 		if (write(fd, buffer, cnt) != cnt)
1373688Sroot 			printf("\r\nwrite error\r\n");
1383688Sroot 
1393688Sroot 	if (boolean(value(VERBOSE)))
1403688Sroot 		prtime(" lines transferred in ", time(0)-start);
1413688Sroot 	ioctl(0, TIOCSETC, &tchars);
1423688Sroot 	write(fildes[1], (char *)&ccc, 1);
1433688Sroot 	signal(SIGINT, SIG_DFL);
1443688Sroot 	close(fd);
1453688Sroot }
1463688Sroot 
1473688Sroot /*
1483688Sroot  * FTP - remote ==> local process
1493688Sroot  *   send remote input to local process via pipe
1503688Sroot  */
1513688Sroot pipefile()
1523688Sroot {
1533688Sroot 	int cpid, pdes[2];
1543688Sroot 	char buf[256];
1553688Sroot 	int status, p;
1563688Sroot 	extern int errno;
1573688Sroot 
1583688Sroot 	if (prompt("Local command? ", buf))
1593688Sroot 		return;
1603688Sroot 
1613688Sroot 	if (pipe(pdes)) {
1623688Sroot 		printf("can't establish pipe\r\n");
1633688Sroot 		return;
1643688Sroot 	}
1653688Sroot 
1663688Sroot 	if ((cpid = fork()) < 0) {
1673688Sroot 		printf("can't fork!\r\n");
1683688Sroot 		return;
1693688Sroot 	} else if (cpid) {
1703688Sroot 		if (prompt("List command for remote system? ", buf)) {
1713688Sroot 			close(pdes[0]), close(pdes[1]);
1723688Sroot 			kill (cpid, SIGKILL);
1733688Sroot 		} else {
1743688Sroot 			close(pdes[0]);
1753688Sroot 			signal(SIGPIPE, intcopy);
1763688Sroot 			transfer(buf, pdes[1], value(EOFREAD));
1773688Sroot 			signal(SIGPIPE, SIG_DFL);
1783688Sroot 			while ((p = wait(&status)) > 0 && p != cpid)
1793688Sroot 				;
1803688Sroot 		}
1813688Sroot 	} else {
1823688Sroot 		register int f;
1833688Sroot 
1843688Sroot 		dup2(pdes[0], 0);
1853688Sroot 		close(pdes[0]);
1863688Sroot 		for (f = 3; f < 20; f++)
1873688Sroot 			close(f);
1883688Sroot 		execute(buf);
1893688Sroot 		printf("can't execl!\r\n");
1903688Sroot 		exit(0);
1913688Sroot 	}
1923688Sroot }
1933688Sroot 
1943688Sroot /*
1953688Sroot  * Interrupt service routine for FTP
1963688Sroot  */
1973688Sroot stopsnd()
1983688Sroot {
1993688Sroot 	stop = 1;
2003688Sroot 	signal(SIGINT, SIG_IGN);
2013688Sroot }
2023688Sroot 
2033688Sroot /*
2043688Sroot  * FTP - local ==> remote
2053688Sroot  *  send local file to remote host
2063688Sroot  *  terminate transmission with pseudo EOF sequence
2073688Sroot  */
2083688Sroot sendfile(cc)
2093688Sroot 	char cc;
2103688Sroot {
2113688Sroot 	FILE *fd;
212*13137Sralph 	char *fnamex;
213*13137Sralph 	char *expand();
2143688Sroot 
2153688Sroot 	putchar(cc);
2163688Sroot 	/*
2173688Sroot 	 * get file name
2183688Sroot 	 */
2193688Sroot 	if (prompt("Local file name? ", fname))
2203688Sroot 		return;
2213688Sroot 
2223688Sroot 	/*
2233688Sroot 	 * look up file
2243688Sroot 	 */
225*13137Sralph 	fnamex = expand(fname);
226*13137Sralph 	if ((fd = fopen(fnamex, "r")) == NULL) {
2273688Sroot 		printf("%s: cannot open\r\n", fname);
2283688Sroot 		return;
2293688Sroot 	}
2303688Sroot 	transmit(fd, value(EOFWRITE), NULL);
2313843Ssam 	if (!boolean(value(ECHOCHECK))) {
2323843Ssam 		struct sgttyb buf;
2333843Ssam 
2343843Ssam 		ioctl(FD, TIOCGETP, &buf);	/* this does a */
2353843Ssam 		ioctl(FD, TIOCSETP, &buf);	/*   wflushtty */
2363843Ssam 	}
2373688Sroot }
2383688Sroot 
2393688Sroot /*
2403688Sroot  * Bulk transfer routine to remote host --
2413688Sroot  *   used by sendfile() and cu_put()
2423688Sroot  */
2433688Sroot transmit(fd, eofchars, command)
2443688Sroot 	FILE *fd;
2453688Sroot 	char *eofchars, *command;
2463688Sroot {
247*13137Sralph 	char *pc, lastc;
2483688Sroot 	int c, ccount, lcount;
2493688Sroot 	time_t start_t, stop_t;
2503688Sroot 
2513688Sroot 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
2523688Sroot 	signal(SIGINT, stopsnd);
2533688Sroot 	stop = 0;
2543688Sroot 	ioctl(0, TIOCSETC, &defchars);
2553688Sroot 	read(repdes[0], (char *)&ccc, 1);
2563688Sroot 	if (command != NULL) {
2573688Sroot 		for (pc = command; *pc; pc++)
2583688Sroot 			send(*pc);
2593843Ssam 		if (boolean(value(ECHOCHECK)))
2603843Ssam 			read(FD, (char *)&c, 1);	/* trailing \n */
2613843Ssam 		else {
2623843Ssam 			struct sgttyb buf;
2633843Ssam 
2643843Ssam 			ioctl(FD, TIOCGETP, &buf);	/* this does a */
2653843Ssam 			ioctl(FD, TIOCSETP, &buf);	/*   wflushtty */
2663843Ssam 			sleep(5); /* wait for remote stty to take effect */
2673843Ssam 		}
2683688Sroot 	}
2693688Sroot 	lcount = 0;
2703688Sroot 	lastc = '\0';
2713688Sroot 	start_t = time(0);
2725133Ssam 	while (1) {
2733688Sroot 		ccount = 0;
2743688Sroot 		do {
2753688Sroot 			c = getc(fd);
2763688Sroot 			if (stop)
2773688Sroot 				goto out;
2783688Sroot 			if (c == EOF)
2793688Sroot 				goto out;
280*13137Sralph 			if (c == 0177 && !boolean(value(RAWFTP)))
2813688Sroot 				continue;
2823688Sroot 			lastc = c;
2833688Sroot 			if (c < 040) {
284*13137Sralph 				if (c == '\n') {
285*13137Sralph 					if (!boolean(value(RAWFTP)))
286*13137Sralph 						c = '\r';
287*13137Sralph 				}
2883688Sroot 				else if (c == '\t') {
289*13137Sralph 					if (!boolean(value(RAWFTP))) {
290*13137Sralph 						if (boolean(value(TABEXPAND))) {
2913688Sroot 							send(' ');
292*13137Sralph 							while ((++ccount % 8) != 0)
293*13137Sralph 								send(' ');
294*13137Sralph 							continue;
295*13137Sralph 						}
296*13137Sralph 					}
297*13137Sralph 				} else
298*13137Sralph 					if (!boolean(value(RAWFTP)))
2993688Sroot 						continue;
3003688Sroot 			}
3013688Sroot 			send(c);
302*13137Sralph 		} while (c != '\r' && !boolean(value(RAWFTP)));
3033688Sroot 		if (boolean(value(VERBOSE)))
3043688Sroot 			printf("\r%d", ++lcount);
3053843Ssam 		if (boolean(value(ECHOCHECK))) {
306*13137Sralph 			alarm(value(ETIMEOUT));
3073843Ssam 			timedout = 0;
3083843Ssam 			do {	/* wait for prompt */
309*13137Sralph 				read(FD, (char *)&c, 1);
3103843Ssam 				if (timedout || stop) {
3113843Ssam 					if (timedout)
3123843Ssam 						printf("\r\ntimed out at eol\r\n");
3133843Ssam 					alarm(0);
3143843Ssam 					goto out;
3153843Ssam 				}
316*13137Sralph 			} while ((c&0177) != character(value(PROMPT)));
3173843Ssam 			alarm(0);
3183843Ssam 		}
3193688Sroot 	}
3203688Sroot out:
321*13137Sralph 	if (lastc != '\n' && !boolean(value(RAWFTP)))
3223688Sroot 		send('\r');
3233688Sroot 	for (pc = eofchars; *pc; pc++)
3243688Sroot 		send(*pc);
3253688Sroot 	stop_t = time(0);
3263688Sroot 	fclose(fd);
3273688Sroot 	signal(SIGINT, SIG_DFL);
3283688Sroot 	if (boolean(value(VERBOSE)))
329*13137Sralph 		if (boolean(value(RAWFTP)))
330*13137Sralph 			prtime(" chars transferred in ", stop_t-start_t);
331*13137Sralph 		else
332*13137Sralph 			prtime(" lines transferred in ", stop_t-start_t);
3333688Sroot 	write(fildes[1], (char *)&ccc, 1);
3343688Sroot 	ioctl(0, TIOCSETC, &tchars);
3353688Sroot }
3363688Sroot 
3373688Sroot /*
3383688Sroot  * Cu-like put command
3393688Sroot  */
3403688Sroot cu_put(cc)
3413688Sroot 	char cc;
3423688Sroot {
3433688Sroot 	FILE *fd;
3443688Sroot 	char line[BUFSIZ];
3453688Sroot 	int argc;
346*13137Sralph 	char *expand();
347*13137Sralph 	char *copynamex;
3483688Sroot 
3493688Sroot 	if (prompt("[put] ", copyname))
3503688Sroot 		return;
3513688Sroot 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
3523688Sroot 		printf("usage: <put> from [to]\r\n");
3533688Sroot 		return;
3543688Sroot 	}
3553688Sroot 	if (argc == 1)
3563688Sroot 		argv[1] = argv[0];
357*13137Sralph 	copynamex = expand(argv[0]);
358*13137Sralph 	if ((fd = fopen(copynamex, "r")) == NULL) {
359*13137Sralph 		printf("%s: cannot open\r\n", copynamex);
3603688Sroot 		return;
3613688Sroot 	}
3623843Ssam 	if (boolean(value(ECHOCHECK)))
363*13137Sralph 		sprintf(line, "cat>%s\r", argv[1]);
3643843Ssam 	else
365*13137Sralph 		sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]);
3663688Sroot 	transmit(fd, "\04", line);
3673688Sroot }
3683688Sroot 
3693688Sroot /*
3703688Sroot  * FTP - send single character
3713688Sroot  *  wait for echo & handle timeout
3723688Sroot  */
3733688Sroot send(c)
3743688Sroot 	char c;
3753688Sroot {
3767588Sshannon 	char cc;
3773688Sroot 	int retry = 0;
3783688Sroot 
3793688Sroot 	cc = c;
380*13137Sralph 	pwrite(FD, &cc, 1);
381*13137Sralph #ifdef notdef
382*13137Sralph 	if (number(value(CDELAY)) > 0 && c != '\r')
383*13137Sralph 		nap(number(value(CDELAY)));
384*13137Sralph #endif
385*13137Sralph 	if (!boolean(value(ECHOCHECK))) {
386*13137Sralph #ifdef notdef
387*13137Sralph 		if (number(value(LDELAY)) > 0 && c == '\r')
388*13137Sralph 			nap(number(value(LDELAY)));
389*13137Sralph #endif
3903843Ssam 		return;
391*13137Sralph 	}
3923688Sroot tryagain:
3933688Sroot 	timedout = 0;
394*13137Sralph 	alarm(value(ETIMEOUT));
395*13137Sralph 	read(FD, &cc, 1);
3963688Sroot 	alarm(0);
3973688Sroot 	if (timedout) {
3983688Sroot 		printf("\r\ntimeout error (%s)\r\n", ctrl(c));
3993688Sroot 		if (retry++ > 3)
4003688Sroot 			return;
401*13137Sralph 		pwrite(FD, &null, 1); /* poke it */
4023688Sroot 		goto tryagain;
4033688Sroot 	}
4043688Sroot }
4053688Sroot 
4063688Sroot timeout()
4073688Sroot {
4083688Sroot 	signal(SIGALRM, timeout);
4093688Sroot 	timedout = 1;
4103688Sroot }
4113688Sroot 
4123688Sroot #ifdef CONNECT
4133688Sroot /*
4143688Sroot  * Fork a program with:
4153688Sroot  *  0 <-> local tty in
4163688Sroot  *  1 <-> local tty out
4173688Sroot  *  2 <-> local tty out
4183688Sroot  *  3 <-> remote tty in
4193688Sroot  *  4 <-> remote tty out
4203688Sroot  */
4213688Sroot consh(c)
4223688Sroot {
4233688Sroot 	char buf[256];
4243688Sroot 	int cpid, status, p;
4253688Sroot 	time_t start;
4263688Sroot 
4273688Sroot 	putchar(c);
4283688Sroot 	if (prompt("Local command? ", buf))
4293688Sroot 		return;
4303688Sroot 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
4313688Sroot 	signal(SIGINT, SIG_IGN);
4323688Sroot 	signal(SIGQUIT, SIG_IGN);
4333688Sroot 	ioctl(0, TIOCSETC, &defchars);
4343688Sroot 	read(repdes[0], (char *)&ccc, 1);
4353688Sroot 	/*
4363688Sroot 	 * Set up file descriptors in the child and
4373688Sroot 	 *  let it go...
4383688Sroot 	 */
4393688Sroot 	if ((cpid = fork()) < 0)
4403688Sroot 		printf("can't fork!\r\n");
4413688Sroot 	else if (cpid) {
4423688Sroot 		start = time(0);
4433688Sroot 		while ((p = wait(&status)) > 0 && p != cpid)
4443688Sroot 			;
4453688Sroot 	} else {
4463688Sroot 		register int i;
4473688Sroot 
4483688Sroot 		dup2(FD, 3);
4493688Sroot 		dup2(3, 4);
4503688Sroot 		for (i = 5; i < 20; i++)
4513688Sroot 			close(i);
4523688Sroot 		signal(SIGINT, SIG_DFL);
4533688Sroot 		signal(SIGQUIT, SIG_DFL);
4543688Sroot 		execute(buf);
4553688Sroot 		printf("can't find `%s'\r\n", buf);
4563688Sroot 		exit(0);
4573688Sroot 	}
4583688Sroot 	if (boolean(value(VERBOSE)))
4593688Sroot 		prtime("away for ", time(0)-start);
4603688Sroot 	write(fildes[1], (char *)&ccc, 1);
4613688Sroot 	ioctl(0, TIOCSETC, &tchars);
4623688Sroot 	signal(SIGINT, SIG_DFL);
4633688Sroot 	signal(SIGQUIT, SIG_DFL);
4643688Sroot }
4653688Sroot #endif
4663688Sroot 
4673688Sroot /*
468*13137Sralph  * Execute command under local shell
469*13137Sralph  */
470*13137Sralph lcmd()
471*13137Sralph {
472*13137Sralph 	int shpid, status;
473*13137Sralph 	extern char **environ;
474*13137Sralph 	char *cp;
475*13137Sralph 	char	cmdline[255];
476*13137Sralph 	register char *cmdp = cmdline;
477*13137Sralph 
478*13137Sralph 	if (prompt("!", cmdline))
479*13137Sralph 		if (stoprompt)
480*13137Sralph 			return;
481*13137Sralph 	signal(SIGINT, SIG_IGN);
482*13137Sralph 	signal(SIGQUIT, SIG_IGN);
483*13137Sralph 	unraw();
484*13137Sralph 	if (shpid = fork()) {
485*13137Sralph 		while (shpid != wait(&status));
486*13137Sralph 		raw();
487*13137Sralph 		printf("\r\n!\r\n");
488*13137Sralph 		signal(SIGINT, SIG_DFL);
489*13137Sralph 		signal(SIGQUIT, SIG_DFL);
490*13137Sralph 		return;
491*13137Sralph 	} else {
492*13137Sralph 		signal(SIGQUIT, SIG_DFL);
493*13137Sralph 		signal(SIGINT, SIG_DFL);
494*13137Sralph 		if ((cp = rindex(value(SHELL), '/')) == NULL)
495*13137Sralph 			cp = value(SHELL);
496*13137Sralph 		else
497*13137Sralph 			cp++;
498*13137Sralph 		execl(value(SHELL), cp, "-c", cmdline, 0);
499*13137Sralph 		printf("\r\ncan't execl!\r\n");
500*13137Sralph 		exit(1);
501*13137Sralph 	}
502*13137Sralph }
503*13137Sralph 
504*13137Sralph /*
5053688Sroot  * Escape to local shell
5063688Sroot  */
5073688Sroot shell()
5083688Sroot {
5093688Sroot 	int shpid, status;
5103688Sroot 	extern char **environ;
5113688Sroot 	char *cp;
5123688Sroot 
5133688Sroot 	printf("[sh]\r\n");
5143688Sroot 	signal(SIGINT, SIG_IGN);
5153688Sroot 	signal(SIGQUIT, SIG_IGN);
5163688Sroot 	unraw();
5173688Sroot 	if (shpid = fork()) {
5183688Sroot 		while (shpid != wait(&status));
5193688Sroot 		raw();
5203688Sroot 		printf("\r\n!\r\n");
5213688Sroot 		signal(SIGINT, SIG_DFL);
5223688Sroot 		signal(SIGQUIT, SIG_DFL);
5233688Sroot 		return;
5243688Sroot 	} else {
5253688Sroot 		signal(SIGQUIT, SIG_DFL);
5263688Sroot 		signal(SIGINT, SIG_DFL);
5273688Sroot 		if ((cp = rindex(value(SHELL), '/')) == NULL)
5283688Sroot 			cp = value(SHELL);
5293688Sroot 		else
5303688Sroot 			cp++;
5313688Sroot 		execl(value(SHELL), cp, 0);
5323688Sroot 		printf("\r\ncan't execl!\r\n");
5333688Sroot 		exit(1);
5343688Sroot 	}
5353688Sroot }
5363688Sroot 
5373688Sroot /*
5383688Sroot  * TIPIN portion of scripting
5393688Sroot  *   initiate the conversation with TIPOUT
5403688Sroot  */
5413688Sroot setscript()
5423688Sroot {
5433688Sroot 	char c;
5443688Sroot 	/*
5453688Sroot 	 * enable TIPOUT side for dialogue
5463688Sroot 	 */
5473688Sroot 	kill(pid, SIGEMT);
5483688Sroot 	if (boolean(value(SCRIPT)))
5493688Sroot 		write(fildes[1], value(RECORD), size(value(RECORD)));
5503688Sroot 	write(fildes[1], "\n", 1);
5513688Sroot 	/*
5523688Sroot 	 * wait for TIPOUT to finish
5533688Sroot 	 */
5543688Sroot 	read(repdes[0], &c, 1);
5553688Sroot 	if (c == 'n')
5563688Sroot 		printf("can't create %s\r\n", value(RECORD));
5573688Sroot }
5583688Sroot 
5593688Sroot /*
5603688Sroot  * Change current working directory of
5613688Sroot  *   local portion of tip
5623688Sroot  */
5633688Sroot chdirectory()
5643688Sroot {
5653688Sroot 	char	dirname[80];
5663688Sroot 	register char *cp = dirname;
5673688Sroot 
5683688Sroot 	if (prompt("[cd] ", dirname))
5693688Sroot 		if (stoprompt)
5703688Sroot 			return;
5713688Sroot 		else
5723688Sroot 			cp = value(HOME);
5733688Sroot 	if (chdir(cp) < 0)
5743688Sroot 		printf("%s: bad directory\r\n", cp);
5753688Sroot 	printf("!\r\n");
5763688Sroot }
5773688Sroot 
5783688Sroot finish()
5793688Sroot {
580*13137Sralph 	char *dismsg;
581*13137Sralph 
582*13137Sralph 	if ((dismsg = value(DISCONNECT)) != NOSTR) {
583*13137Sralph 		write(FD,dismsg,strlen(dismsg));
584*13137Sralph 		sleep(5);
585*13137Sralph 	}
5863688Sroot 	kill(pid, SIGTERM);
5873688Sroot 	disconnect();
5883688Sroot 	printf("\r\n[EOT]\r\n");
5893688Sroot 	delock(uucplock);
5903688Sroot 	unraw();
5913688Sroot 	exit(0);
5923688Sroot }
5933688Sroot 
5943688Sroot intcopy()
5953688Sroot {
5963688Sroot 	raw();
5973688Sroot 	quit = 1;
5983688Sroot }
5993688Sroot 
6003688Sroot execute(s)
6013688Sroot 	char *s;
6023688Sroot {
6033688Sroot 	register char *cp;
6043688Sroot 
6053688Sroot 	if ((cp = rindex(value(SHELL), '/')) == NULL)
6063688Sroot 		cp = value(SHELL);
6073688Sroot 	else
6083688Sroot 		cp++;
6093688Sroot 	execl(value(SHELL), cp, "-c", s, 0);
6103688Sroot }
6113688Sroot 
6123688Sroot args(buf, a)
6133688Sroot 	char *buf, *a[];
6143688Sroot {
6153688Sroot 	register char *p = buf, *start;
6163688Sroot 	register char **parg = a;
6173688Sroot 	register int n = 0;
6183688Sroot 
6193688Sroot 	do {
6203688Sroot 		while (*p && (*p == ' ' || *p == '\t'))
6213688Sroot 			p++;
6223688Sroot 		start = p;
6233688Sroot 		if (*p)
6243688Sroot 			*parg = p;
6253688Sroot 		while (*p && (*p != ' ' && *p != '\t'))
6263688Sroot 			p++;
6273688Sroot 		if (p != start)
6283688Sroot 			parg++, n++;
6293688Sroot 		if (*p)
6303688Sroot 			*p++ = '\0';
6313688Sroot 	} while (*p);
6323688Sroot 
6333688Sroot 	return(n);
6343688Sroot }
6353688Sroot 
6363688Sroot prtime(s, a)
6373688Sroot 	char *s;
6383688Sroot 	time_t a;
6393688Sroot {
6403688Sroot 	register i;
6413688Sroot 	int nums[3];
6423688Sroot 
6433688Sroot 	for (i = 0; i < 3; i++) {
6443688Sroot 		nums[i] = (int)(a % quant[i]);
6453688Sroot 		a /= quant[i];
6463688Sroot 	}
6473688Sroot 	printf("%s", s);
6483688Sroot 	while (--i >= 0)
6493688Sroot 		if (nums[i])
6503688Sroot 			printf("%d %s%c ", nums[i], sep[i],
6513688Sroot 				nums[i] == 1 ? '\0' : 's');
6523688Sroot 	printf("\r\n!\r\n");
6533688Sroot }
6543688Sroot 
6553688Sroot variable()
6563688Sroot {
6573688Sroot 	char	buf[256];
6583688Sroot 
6593688Sroot 	if (prompt("[set] ", buf))
6603688Sroot 		return;
6613688Sroot 	vlex(buf);
6623688Sroot 	if (vtable[BEAUTIFY].v_access&CHANGED) {
6633688Sroot 		vtable[BEAUTIFY].v_access &= ~CHANGED;
6645333Sshannon 		kill(pid, SIGSYS);
6653688Sroot 	}
6663688Sroot 	if (vtable[SCRIPT].v_access&CHANGED) {
6673688Sroot 		vtable[SCRIPT].v_access &= ~CHANGED;
6683688Sroot 		setscript();
6693865Ssam 		/*
6703865Ssam 		 * So that "set record=blah script" doesn't
6713865Ssam 		 *  cause two transactions to occur.
6723865Ssam 		 */
6733865Ssam 		if (vtable[RECORD].v_access&CHANGED)
6743865Ssam 			vtable[RECORD].v_access &= ~CHANGED;
6753688Sroot 	}
6763688Sroot 	if (vtable[RECORD].v_access&CHANGED) {
6773688Sroot 		vtable[RECORD].v_access &= ~CHANGED;
6783688Sroot 		if (boolean(value(SCRIPT)))
6793688Sroot 			setscript();
6803688Sroot 	}
681*13137Sralph 	if (vtable[TAND].v_access&CHANGED) {
682*13137Sralph 		vtable[TAND].v_access &= ~CHANGED;
683*13137Sralph 		if (boolean(value(TAND)))
684*13137Sralph 			tandem("on");
685*13137Sralph 		else
686*13137Sralph 			tandem("off");
687*13137Sralph 	}
688*13137Sralph  	if (vtable[LECHO].v_access&CHANGED) {
689*13137Sralph  		vtable[LECHO].v_access &= ~CHANGED;
690*13137Sralph  		HD = boolean(value(LECHO));
691*13137Sralph  	}
692*13137Sralph 	if (vtable[PARITY].v_access&CHANGED) {
693*13137Sralph 		vtable[PARITY].v_access &= ~CHANGED;
694*13137Sralph 		setparity();
695*13137Sralph 	}
6963688Sroot }
6973822Ssam 
6983822Ssam /*
699*13137Sralph  * turn tandem mode on or off for remote tty
700*13137Sralph  */
701*13137Sralph 
702*13137Sralph tandem(option)
703*13137Sralph char *option;
704*13137Sralph {
705*13137Sralph 	struct sgttyb rmtty;
706*13137Sralph 
707*13137Sralph 	ioctl(FD, TIOCGETP, &rmtty);
708*13137Sralph 	if (strcmp(option,"on") == 0) {
709*13137Sralph 		rmtty.sg_flags |= TANDEM;
710*13137Sralph 		arg.sg_flags |= TANDEM;
711*13137Sralph 	}
712*13137Sralph 	else {
713*13137Sralph 		rmtty.sg_flags &= ~TANDEM;
714*13137Sralph 		arg.sg_flags &= ~TANDEM;
715*13137Sralph 	}
716*13137Sralph 	ioctl(FD, TIOCSETP, &rmtty);
717*13137Sralph 	ioctl(0,  TIOCSETP, &arg);
718*13137Sralph }
719*13137Sralph 
720*13137Sralph /*
7213822Ssam  * Send a break.
7223822Ssam  * If we can't do it directly (as on VMUNIX), then simulate it.
7233822Ssam  */
7243822Ssam genbrk()
7253822Ssam {
726*13137Sralph #ifdef VMUNIX
7273822Ssam 	ioctl(FD, TIOCSBRK, NULL);
7283822Ssam 	sleep(1);
7293822Ssam 	ioctl(FD, TIOCCBRK, NULL);
7303822Ssam #else
7313822Ssam 	struct sgttyb ttbuf;
7323822Ssam 	int sospeed;
7333822Ssam 
7343822Ssam 	ioctl(FD, TIOCGETP, &ttbuf);
7353822Ssam 	sospeed = ttbuf.sg_ospeed;
7363822Ssam 	ttbuf.sg_ospeed = B150;
7373822Ssam 	ioctl(FD, TIOCSETP, &ttbuf);
738*13137Sralph 	pwrite(FD, "\0\0\0\0\0\0\0\0\0\0", 10);
7393822Ssam 	ttbuf.sg_ospeed = sospeed;
7403822Ssam 	ioctl(FD, TIOCSETP, &ttbuf);
741*13137Sralph 	pwrite(FD, "@", 1);
7423822Ssam #endif
7433822Ssam }
7445133Ssam 
7455133Ssam #ifdef SIGTSTP
7465133Ssam /*
7475133Ssam  * Suspend tip
7485133Ssam  */
7495133Ssam suspend()
7505133Ssam {
7515133Ssam 	unraw();
7525133Ssam 	kill(0, SIGTSTP);
7535133Ssam 	raw();
7545133Ssam }
7555133Ssam #endif
756*13137Sralph 
757*13137Sralph /*
758*13137Sralph  *	expand a file name if it includes shell meta characters
759*13137Sralph  */
760*13137Sralph 
761*13137Sralph char *
762*13137Sralph expand(name)
763*13137Sralph 	char name[];
764*13137Sralph {
765*13137Sralph 	static char xname[BUFSIZ];
766*13137Sralph 	char cmdbuf[BUFSIZ];
767*13137Sralph 	register int pid, l, rc;
768*13137Sralph 	register char *cp, *Shell;
769*13137Sralph 	int s, pivec[2], (*sigint)();
770*13137Sralph 
771*13137Sralph 	if (!anyof(name, "~{[*?$`'\"\\"))
772*13137Sralph 		return(name);
773*13137Sralph 	/* sigint = signal(SIGINT, SIG_IGN); */
774*13137Sralph 	if (pipe(pivec) < 0) {
775*13137Sralph 		perror("pipe");
776*13137Sralph 		/* signal(SIGINT, sigint) */
777*13137Sralph 		return(name);
778*13137Sralph 	}
779*13137Sralph 	sprintf(cmdbuf, "echo %s", name);
780*13137Sralph 	if ((pid = vfork()) == 0) {
781*13137Sralph 		Shell = value(SHELL);
782*13137Sralph 		if (Shell == NOSTR)
783*13137Sralph 			Shell = "/bin/sh";
784*13137Sralph 		close(pivec[0]);
785*13137Sralph 		close(1);
786*13137Sralph 		dup(pivec[1]);
787*13137Sralph 		close(pivec[1]);
788*13137Sralph 		close(2);
789*13137Sralph 		execl(Shell, Shell, "-c", cmdbuf, 0);
790*13137Sralph 		_exit(1);
791*13137Sralph 	}
792*13137Sralph 	if (pid == -1) {
793*13137Sralph 		perror("fork");
794*13137Sralph 		close(pivec[0]);
795*13137Sralph 		close(pivec[1]);
796*13137Sralph 		return(NOSTR);
797*13137Sralph 	}
798*13137Sralph 	close(pivec[1]);
799*13137Sralph 	l = read(pivec[0], xname, BUFSIZ);
800*13137Sralph 	close(pivec[0]);
801*13137Sralph 	while (wait(&s) != pid);
802*13137Sralph 		;
803*13137Sralph 	s &= 0377;
804*13137Sralph 	if (s != 0 && s != SIGPIPE) {
805*13137Sralph 		fprintf(stderr, "\"Echo\" failed\n");
806*13137Sralph 		return(NOSTR);
807*13137Sralph 	}
808*13137Sralph 	if (l < 0) {
809*13137Sralph 		perror("read");
810*13137Sralph 		return(NOSTR);
811*13137Sralph 	}
812*13137Sralph 	if (l == 0) {
813*13137Sralph 		fprintf(stderr, "\"%s\": No match\n", name);
814*13137Sralph 		return(NOSTR);
815*13137Sralph 	}
816*13137Sralph 	if (l == BUFSIZ) {
817*13137Sralph 		fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
818*13137Sralph 		return(NOSTR);
819*13137Sralph 	}
820*13137Sralph 	xname[l] = 0;
821*13137Sralph 	for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
822*13137Sralph 		;
823*13137Sralph 	*++cp = '\0';
824*13137Sralph 	return(xname);
825*13137Sralph }
826*13137Sralph 
827*13137Sralph /*
828*13137Sralph  * Are any of the characters in the two strings the same?
829*13137Sralph  */
830*13137Sralph 
831*13137Sralph anyof(s1, s2)
832*13137Sralph 	register char *s1, *s2;
833*13137Sralph {
834*13137Sralph 	register int c;
835*13137Sralph 
836*13137Sralph 	while (c = *s1++)
837*13137Sralph 		if (any(c, s2))
838*13137Sralph 			return(1);
839*13137Sralph 	return(0);
840*13137Sralph }
841