xref: /netbsd-src/usr.bin/tip/cmds.c (revision 6afb7d51900da19077985c98d14586fdc1259b2a)
1*6afb7d51Smlelstv /*	$NetBSD: cmds.c,v 1.37 2014/07/12 05:28:07 mlelstv Exp $	*/
239801cccSjtc 
361f28255Scgd /*
439801cccSjtc  * Copyright (c) 1983, 1993
539801cccSjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32e37283e1Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3439801cccSjtc #if 0
3539801cccSjtc static char sccsid[] = "@(#)cmds.c	8.1 (Berkeley) 6/6/93";
3639801cccSjtc #endif
37*6afb7d51Smlelstv __RCSID("$NetBSD: cmds.c,v 1.37 2014/07/12 05:28:07 mlelstv Exp $");
3861f28255Scgd #endif /* not lint */
3961f28255Scgd 
4061f28255Scgd #include "tip.h"
4161f28255Scgd #include "pathnames.h"
4261f28255Scgd 
4361f28255Scgd /*
4461f28255Scgd  * tip
4561f28255Scgd  *
4661f28255Scgd  * miscellaneous commands
4761f28255Scgd  */
4861f28255Scgd 
4961f28255Scgd int	quant[] = { 60, 60, 24 };
5061f28255Scgd 
5161f28255Scgd char	null = '\0';
524f6045fcSchristos const char	*sep[] = { "second", "minute", "hour" };
5361f28255Scgd static	char *argv[10];		/* argument vector for take and put */
5461f28255Scgd 
5558c2151fSperry int	args(char *, char **);
5658c2151fSperry int	anyof(char *, const char *);
5758c2151fSperry void	execute(char *);
58f20d1d23Sjoerg __dead static void	intcopy(int);
5958c2151fSperry void	prtime(const char *, time_t);
6058c2151fSperry void	stopsnd(int);
6158c2151fSperry void	transfer(char *, int, const char *);
6258c2151fSperry void	transmit(FILE *, const char *, char *);
6361f28255Scgd 
6461f28255Scgd /*
6561f28255Scgd  * FTP - remote ==> local
6661f28255Scgd  *  get a file from the remote host
6761f28255Scgd  */
68e37283e1Slukem void
getfl(char c)6958c2151fSperry getfl(char c)
7061f28255Scgd {
71e37283e1Slukem 	char buf[256], *cp;
7261f28255Scgd 
73ffe34450Schristos 	(void)putchar(c);
7461f28255Scgd 	/*
7561f28255Scgd 	 * get the UNIX receiving file's name
7661f28255Scgd 	 */
77923d7551Smrg 	if (prompt("Local file name? ", copyname, sizeof copyname))
7861f28255Scgd 		return;
7961f28255Scgd 	cp = expand(copyname);
809d002ba5Suebayasi 	if ((sfd = open(cp, O_RDWR|O_CREAT, 0666)) < 0) {
81ffe34450Schristos 		(void)printf("\r\n%s: cannot create\r\n", copyname);
8261f28255Scgd 		return;
8361f28255Scgd 	}
8461f28255Scgd 
8561f28255Scgd 	/*
8661f28255Scgd 	 * collect parameters
8761f28255Scgd 	 */
88923d7551Smrg 	if (prompt("List command for remote system? ", buf,
89923d7551Smrg 	    sizeof buf)) {
90ffe34450Schristos 		(void)unlink(copyname);
9161f28255Scgd 		return;
9261f28255Scgd 	}
9361f28255Scgd 	transfer(buf, sfd, value(EOFREAD));
9461f28255Scgd }
9561f28255Scgd 
9661f28255Scgd /*
9761f28255Scgd  * Cu-like take command
9861f28255Scgd  */
9929dc02e5Sperry /* ARGSUSED */
100e37283e1Slukem void
cu_take(char dummy __unused)101ffe34450Schristos cu_take(char dummy __unused)
10261f28255Scgd {
10361f28255Scgd 	int fd, argc;
104e37283e1Slukem 	char line[BUFSIZ], *cp;
10561f28255Scgd 
106923d7551Smrg 	if (prompt("[take] ", copyname, sizeof copyname))
10761f28255Scgd 		return;
10861f28255Scgd 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
109ffe34450Schristos 		(void)printf("usage: <take> from [to]\r\n");
11061f28255Scgd 		return;
11161f28255Scgd 	}
11261f28255Scgd 	if (argc == 1)
11361f28255Scgd 		argv[1] = argv[0];
11461f28255Scgd 	cp = expand(argv[1]);
1159d002ba5Suebayasi 	if ((fd = open(cp, O_RDWR|O_CREAT, 0666)) < 0) {
116ffe34450Schristos 		(void)printf("\r\n%s: cannot create\r\n", argv[1]);
11761f28255Scgd 		return;
11861f28255Scgd 	}
11953fddda6Smrg 	(void)snprintf(line, sizeof line, "cat %s;echo \01", argv[0]);
12061f28255Scgd 	transfer(line, fd, "\01");
12161f28255Scgd }
12261f28255Scgd 
12361f28255Scgd static	jmp_buf intbuf;
12461f28255Scgd /*
12561f28255Scgd  * Bulk transfer routine --
12661f28255Scgd  *  used by getfl(), cu_take(), and pipefile()
12761f28255Scgd  */
128e37283e1Slukem void
transfer(char * buf,int fd,const char * eofchars)12958c2151fSperry transfer(char *buf, int fd, const char *eofchars)
13061f28255Scgd {
131e37283e1Slukem 	int ct;
13261f28255Scgd 	char c, buffer[BUFSIZ];
133239d1ed1Schristos 	char * volatile p;
134e37283e1Slukem 	int cnt, eof;
13561f28255Scgd 	time_t start;
13661f28255Scgd 	sig_t f;
13739801cccSjtc 	char r;
13861f28255Scgd 
139239d1ed1Schristos 	p = buffer;
140d48673ceSthorpej 	xpwrite(FD, buf, strlen(buf));
14161f28255Scgd 	quit = 0;
142ffe34450Schristos 	(void)write(attndes[1], "W", 1);	/* Put TIPOUT into a wait state */
143ffe34450Schristos 	(void)read(repdes[0], (char *)&ccc, 1);  /* Wait until read process stops */
14461f28255Scgd 
14561f28255Scgd 	/*
14661f28255Scgd 	 * finish command
14761f28255Scgd 	 */
14839801cccSjtc 	r = '\r';
149d48673ceSthorpej 	xpwrite(FD, &r, 1);
15061f28255Scgd 	do
151ffe34450Schristos 		(void)read(FD, &c, 1);
152258108ceSpk 	while ((c&STRIP_PAR) != '\n');
153ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &defchars);
15461f28255Scgd 
15561f28255Scgd 	(void) setjmp(intbuf);
15661f28255Scgd 	f = signal(SIGINT, intcopy);
15761f28255Scgd 	start = time(0);
15861f28255Scgd 	for (ct = 0; !quit;) {
15961f28255Scgd 		eof = read(FD, &c, 1) <= 0;
160258108ceSpk 		c &= STRIP_PAR;
16161f28255Scgd 		if (quit)
16261f28255Scgd 			continue;
16361f28255Scgd 		if (eof || any(c, eofchars))
16461f28255Scgd 			break;
16561f28255Scgd 		if (c == 0)
16661f28255Scgd 			continue;	/* ignore nulls */
16761f28255Scgd 		if (c == '\r')
16861f28255Scgd 			continue;
16961f28255Scgd 		*p++ = c;
17061f28255Scgd 
17161f28255Scgd 		if (c == '\n' && boolean(value(VERBOSE)))
172ffe34450Schristos 			(void)printf("\r%d", ++ct);
17361f28255Scgd 		if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
174c4341bc3Schristos 			if (write(fd, buffer, (size_t)cnt) != cnt) {
175ffe34450Schristos 				(void)printf("\r\nwrite error\r\n");
17661f28255Scgd 				quit = 1;
17761f28255Scgd 			}
17861f28255Scgd 			p = buffer;
17961f28255Scgd 		}
18061f28255Scgd 	}
181e37283e1Slukem 	if ((cnt = (p-buffer)) != 0)
182c4341bc3Schristos 		if (write(fd, buffer, (size_t)cnt) != cnt)
183ffe34450Schristos 			(void)printf("\r\nwrite error\r\n");
18461f28255Scgd 
18561f28255Scgd 	if (boolean(value(VERBOSE)))
18661f28255Scgd 		prtime(" lines transferred in ", time(0)-start);
187c4341bc3Schristos 	(void)tcsetattr(0, TCSAFLUSH, &term);
188c4341bc3Schristos 	(void)write(fildes[1], (char *)&ccc, 1);
189c4341bc3Schristos 	(void)signal(SIGINT, f);
190c4341bc3Schristos 	(void)close(fd);
19161f28255Scgd }
19261f28255Scgd 
19361f28255Scgd /*
19461f28255Scgd  * FTP - remote ==> local process
19561f28255Scgd  *   send remote input to local process via pipe
19661f28255Scgd  */
19729dc02e5Sperry /* ARGSUSED */
198e37283e1Slukem void
pipefile(char dummy __unused)199ffe34450Schristos pipefile(char dummy __unused)
20061f28255Scgd {
20161f28255Scgd 	int cpid, pdes[2];
20261f28255Scgd 	char buf[256];
20361f28255Scgd 	int status, p;
20461f28255Scgd 
205923d7551Smrg 	if (prompt("Local command? ", buf, sizeof buf))
20661f28255Scgd 		return;
20761f28255Scgd 
20861f28255Scgd 	if (pipe(pdes)) {
209ffe34450Schristos 		(void)printf("can't establish pipe\r\n");
21061f28255Scgd 		return;
21161f28255Scgd 	}
21261f28255Scgd 
21361f28255Scgd 	if ((cpid = fork()) < 0) {
214ffe34450Schristos 		(void)printf("can't fork!\r\n");
21561f28255Scgd 		return;
21661f28255Scgd 	} else if (cpid) {
217923d7551Smrg 		if (prompt("List command for remote system? ", buf,
218923d7551Smrg 		    sizeof buf)) {
219ffe34450Schristos 			(void)close(pdes[0]);
220ffe34450Schristos 			(void)close(pdes[1]);
221ffe34450Schristos 			(void)kill(cpid, SIGKILL);
22261f28255Scgd 		} else {
223ffe34450Schristos 			(void)close(pdes[0]);
224ffe34450Schristos 			(void)signal(SIGPIPE, intcopy);
22561f28255Scgd 			transfer(buf, pdes[1], value(EOFREAD));
226ffe34450Schristos 			(void)signal(SIGPIPE, SIG_DFL);
22761f28255Scgd 			while ((p = wait(&status)) > 0 && p != cpid)
22861f28255Scgd 				;
22961f28255Scgd 		}
23061f28255Scgd 	} else {
231ffe34450Schristos 		(void)dup2(pdes[0], 0);
232ffe34450Schristos 		(void)close(pdes[0]);
233ffe34450Schristos 		(void)closefrom(3);
23461f28255Scgd 		execute(buf);
235ffe34450Schristos 		(void)printf("can't execl!\r\n");
23661f28255Scgd 		exit(0);
23761f28255Scgd 	}
23861f28255Scgd }
23961f28255Scgd 
24061f28255Scgd /*
24161f28255Scgd  * Interrupt service routine for FTP
24261f28255Scgd  */
24329dc02e5Sperry /* ARGSUSED */
24461f28255Scgd void
stopsnd(int dummy __unused)245ffe34450Schristos stopsnd(int dummy __unused)
24661f28255Scgd {
24761f28255Scgd 
24861f28255Scgd 	stop = 1;
249ffe34450Schristos 	(void)signal(SIGINT, SIG_IGN);
25061f28255Scgd }
25161f28255Scgd 
25261f28255Scgd /*
25361f28255Scgd  * FTP - local ==> remote
25461f28255Scgd  *  send local file to remote host
25561f28255Scgd  *  terminate transmission with pseudo EOF sequence
25661f28255Scgd  */
257e37283e1Slukem void
sendfile(char cc)25858c2151fSperry sendfile(char cc)
25961f28255Scgd {
26061f28255Scgd 	FILE *fd;
26161f28255Scgd 	char *fnamex;
26261f28255Scgd 
263ffe34450Schristos 	(void)putchar(cc);
26461f28255Scgd 	/*
26561f28255Scgd 	 * get file name
26661f28255Scgd 	 */
267923d7551Smrg 	if (prompt("Local file name? ", fname, sizeof fname))
26861f28255Scgd 		return;
26961f28255Scgd 
27061f28255Scgd 	/*
27161f28255Scgd 	 * look up file
27261f28255Scgd 	 */
27361f28255Scgd 	fnamex = expand(fname);
27461f28255Scgd 	if ((fd = fopen(fnamex, "r")) == NULL) {
275ffe34450Schristos 		(void)printf("%s: cannot open\r\n", fname);
27661f28255Scgd 		return;
27761f28255Scgd 	}
27861f28255Scgd 	transmit(fd, value(EOFWRITE), NULL);
279258108ceSpk 	if (!boolean(value(ECHOCHECK)))
280ffe34450Schristos 		(void)tcdrain(FD);
28161f28255Scgd }
28261f28255Scgd 
28361f28255Scgd /*
28461f28255Scgd  * Bulk transfer routine to remote host --
28561f28255Scgd  *   used by sendfile() and cu_put()
28661f28255Scgd  */
287e37283e1Slukem void
transmit(FILE * fd,const char * eofchars,char * command)28858c2151fSperry transmit(FILE *fd, const char *eofchars, char *command)
28961f28255Scgd {
2904f6045fcSchristos 	const char *pc;
2914f6045fcSchristos 	char lastc;
292c4341bc3Schristos 	int c;
293c4341bc3Schristos 	int ccount, lcount;
29461f28255Scgd 	time_t start_t, stop_t;
29561f28255Scgd 	sig_t f;
29661f28255Scgd 
297ffe34450Schristos 	(void)write(attndes[1], "W", 1);	/* put TIPOUT into a wait state */
29861f28255Scgd 	stop = 0;
29961f28255Scgd 	f = signal(SIGINT, stopsnd);
300ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &defchars);
301ffe34450Schristos 	(void)read(repdes[0], (char *)&ccc, 1);
30261f28255Scgd 	if (command != NULL) {
30361f28255Scgd 		for (pc = command; *pc; pc++)
304c4341bc3Schristos 			sendchar(*pc);
30561f28255Scgd 		if (boolean(value(ECHOCHECK)))
306c4341bc3Schristos 			(void)read(FD, &c, (size_t)1);	/* trailing \n */
30761f28255Scgd 		else {
308ffe34450Schristos 			(void)tcdrain(FD);
309ffe34450Schristos 			(void)sleep(5); /* wait for remote stty to take effect */
31061f28255Scgd 		}
31161f28255Scgd 	}
31261f28255Scgd 	lcount = 0;
31361f28255Scgd 	lastc = '\0';
31461f28255Scgd 	start_t = time(0);
31529dc02e5Sperry 	/* CONSTCOND */
31661f28255Scgd 	while (1) {
31761f28255Scgd 		ccount = 0;
31861f28255Scgd 		do {
31961f28255Scgd 			c = getc(fd);
32061f28255Scgd 			if (stop)
32161f28255Scgd 				goto out;
32261f28255Scgd 			if (c == EOF)
32361f28255Scgd 				goto out;
32461f28255Scgd 			if (c == 0177 && !boolean(value(RAWFTP)))
32561f28255Scgd 				continue;
32661f28255Scgd 			lastc = c;
32761f28255Scgd 			if (c < 040) {
32861f28255Scgd 				if (c == '\n') {
32961f28255Scgd 					if (!boolean(value(RAWFTP)))
33061f28255Scgd 						c = '\r';
33161f28255Scgd 				}
33261f28255Scgd 				else if (c == '\t') {
33361f28255Scgd 					if (!boolean(value(RAWFTP))) {
33461f28255Scgd 						if (boolean(value(TABEXPAND))) {
335c4341bc3Schristos 							sendchar(' ');
33661f28255Scgd 							while ((++ccount % 8) != 0)
337c4341bc3Schristos 								sendchar(' ');
33861f28255Scgd 							continue;
33961f28255Scgd 						}
34061f28255Scgd 					}
34161f28255Scgd 				} else
34261f28255Scgd 					if (!boolean(value(RAWFTP)))
34361f28255Scgd 						continue;
34461f28255Scgd 			}
345c4341bc3Schristos 			sendchar(c);
34661f28255Scgd 		} while (c != '\r' && !boolean(value(RAWFTP)));
34761f28255Scgd 		if (boolean(value(VERBOSE)))
348ffe34450Schristos 			(void)printf("\r%d", ++lcount);
34961f28255Scgd 		if (boolean(value(ECHOCHECK))) {
35061f28255Scgd 			timedout = 0;
351ffe34450Schristos 			(void)alarm((unsigned int)number(value(ETIMEOUT)));
35261f28255Scgd 			do {	/* wait for prompt */
353ffe34450Schristos 				(void)read(FD, &c, (size_t)1);
35461f28255Scgd 				if (timedout || stop) {
35561f28255Scgd 					if (timedout)
356ffe34450Schristos 						(void)printf(
357e37283e1Slukem 						    "\r\ntimed out at eol\r\n");
358ffe34450Schristos 					(void)alarm(0);
35961f28255Scgd 					goto out;
36061f28255Scgd 				}
361258108ceSpk 			} while ((c&STRIP_PAR) != character(value(PROMPT)));
362ffe34450Schristos 			(void)alarm(0);
36361f28255Scgd 		}
36461f28255Scgd 	}
36561f28255Scgd out:
36661f28255Scgd 	if (lastc != '\n' && !boolean(value(RAWFTP)))
367c4341bc3Schristos 		sendchar('\r');
3680b470f4fSjtc 	if (eofchars) {
36961f28255Scgd 		for (pc = eofchars; *pc; pc++)
370c4341bc3Schristos 			sendchar(*pc);
3710b470f4fSjtc 	}
37261f28255Scgd 	stop_t = time(0);
373ffe34450Schristos 	(void)fclose(fd);
374ffe34450Schristos 	(void)signal(SIGINT, f);
375f670fa10Sross 	if (boolean(value(VERBOSE))) {
37661f28255Scgd 		if (boolean(value(RAWFTP)))
37761f28255Scgd 			prtime(" chars transferred in ", stop_t-start_t);
37861f28255Scgd 		else
37961f28255Scgd 			prtime(" lines transferred in ", stop_t-start_t);
380f670fa10Sross 	}
381ffe34450Schristos 	(void)write(fildes[1], (char *)&ccc, 1);
382ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &term);
38361f28255Scgd }
38461f28255Scgd 
38561f28255Scgd /*
38661f28255Scgd  * Cu-like put command
38761f28255Scgd  */
38829dc02e5Sperry /* ARGSUSED */
389e37283e1Slukem void
cu_put(char dummy __unused)390ffe34450Schristos cu_put(char dummy __unused)
39161f28255Scgd {
39261f28255Scgd 	FILE *fd;
39361f28255Scgd 	char line[BUFSIZ];
39461f28255Scgd 	int argc;
39561f28255Scgd 	char *copynamex;
39661f28255Scgd 
397923d7551Smrg 	if (prompt("[put] ", copyname, sizeof copyname))
39861f28255Scgd 		return;
39961f28255Scgd 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
400ffe34450Schristos 		(void)printf("usage: <put> from [to]\r\n");
40161f28255Scgd 		return;
40261f28255Scgd 	}
40361f28255Scgd 	if (argc == 1)
40461f28255Scgd 		argv[1] = argv[0];
40561f28255Scgd 	copynamex = expand(argv[0]);
40661f28255Scgd 	if ((fd = fopen(copynamex, "r")) == NULL) {
407ffe34450Schristos 		(void)printf("%s: cannot open\r\n", copynamex);
40861f28255Scgd 		return;
40961f28255Scgd 	}
41061f28255Scgd 	if (boolean(value(ECHOCHECK)))
41153fddda6Smrg 		(void)snprintf(line, sizeof line, "cat>%s\r", argv[1]);
41261f28255Scgd 	else
41353fddda6Smrg 		(void)snprintf(line, sizeof line, "stty -echo;cat>%s;stty echo\r", argv[1]);
41461f28255Scgd 	transmit(fd, "\04", line);
41561f28255Scgd }
41661f28255Scgd 
41761f28255Scgd /*
41861f28255Scgd  * FTP - send single character
41961f28255Scgd  *  wait for echo & handle timeout
42061f28255Scgd  */
421e37283e1Slukem void
sendchar(char c)422c4341bc3Schristos sendchar(char c)
42361f28255Scgd {
42461f28255Scgd 	char cc;
42561f28255Scgd 	int retry = 0;
42661f28255Scgd 
42761f28255Scgd 	cc = c;
428d48673ceSthorpej 	xpwrite(FD, &cc, 1);
42961f28255Scgd #ifdef notdef
43061f28255Scgd 	if (number(value(CDELAY)) > 0 && c != '\r')
43161f28255Scgd 		nap(number(value(CDELAY)));
43261f28255Scgd #endif
43361f28255Scgd 	if (!boolean(value(ECHOCHECK))) {
43461f28255Scgd #ifdef notdef
43561f28255Scgd 		if (number(value(LDELAY)) > 0 && c == '\r')
43661f28255Scgd 			nap(number(value(LDELAY)));
43761f28255Scgd #endif
43861f28255Scgd 		return;
43961f28255Scgd 	}
44061f28255Scgd tryagain:
44161f28255Scgd 	timedout = 0;
442ffe34450Schristos 	(void)alarm((unsigned int)number(value(ETIMEOUT)));
443ffe34450Schristos 	(void)read(FD, &cc, 1);
444ffe34450Schristos 	(void)alarm(0);
44561f28255Scgd 	if (timedout) {
446ffe34450Schristos 		(void)printf("\r\ntimeout error (%s)\r\n", ctrl(c));
44761f28255Scgd 		if (retry++ > 3)
44861f28255Scgd 			return;
449d48673ceSthorpej 		xpwrite(FD, &null, 1); /* poke it */
45061f28255Scgd 		goto tryagain;
45161f28255Scgd 	}
45261f28255Scgd }
45361f28255Scgd 
45429dc02e5Sperry /* ARGSUSED */
45561f28255Scgd void
alrmtimeout(int dummy __unused)456ffe34450Schristos alrmtimeout(int dummy __unused)
45761f28255Scgd {
458923d7551Smrg 
459ffe34450Schristos 	(void)signal(SIGALRM, alrmtimeout);
46061f28255Scgd 	timedout = 1;
46161f28255Scgd }
46261f28255Scgd 
46361f28255Scgd /*
46461f28255Scgd  * Stolen from consh() -- puts a remote file on the output of a local command.
46561f28255Scgd  *	Identical to consh() except for where stdout goes.
46661f28255Scgd  */
467e37283e1Slukem void
pipeout(char c)46858c2151fSperry pipeout(char c)
46961f28255Scgd {
47061f28255Scgd 	char buf[256];
47161f28255Scgd 	int cpid, status, p;
472e37283e1Slukem 	time_t start = 0;
47361f28255Scgd 
474ffe34450Schristos 	(void)putchar(c);
475923d7551Smrg 	if (prompt("Local command? ", buf, sizeof buf))
47661f28255Scgd 		return;
477ffe34450Schristos 	(void)write(attndes[1], "W", 1);	/* put TIPOUT into a wait state */
478ffe34450Schristos 	(void)signal(SIGINT, SIG_IGN);
479ffe34450Schristos 	(void)signal(SIGQUIT, SIG_IGN);
480ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &defchars);
481ffe34450Schristos 	(void)read(repdes[0], (char *)&ccc, 1);
48261f28255Scgd 	/*
48361f28255Scgd 	 * Set up file descriptors in the child and
48461f28255Scgd 	 *  let it go...
48561f28255Scgd 	 */
48661f28255Scgd 	if ((cpid = fork()) < 0)
487ffe34450Schristos 		(void)printf("can't fork!\r\n");
48861f28255Scgd 	else if (cpid) {
48961f28255Scgd 		start = time(0);
49061f28255Scgd 		while ((p = wait(&status)) > 0 && p != cpid)
49161f28255Scgd 			;
49261f28255Scgd 	} else {
493ffe34450Schristos 		(void)dup2(FD, 1);
494ffe34450Schristos 		(void)closefrom(3);
495ffe34450Schristos 		(void)signal(SIGINT, SIG_DFL);
496ffe34450Schristos 		(void)signal(SIGQUIT, SIG_DFL);
49761f28255Scgd 		execute(buf);
498ffe34450Schristos 		(void)printf("can't find `%s'\r\n", buf);
49961f28255Scgd 		exit(0);
50061f28255Scgd 	}
50161f28255Scgd 	if (boolean(value(VERBOSE)))
50261f28255Scgd 		prtime("away for ", time(0)-start);
503ffe34450Schristos 	(void)write(fildes[1], (char *)&ccc, 1);
504ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &term);
505ffe34450Schristos 	(void)signal(SIGINT, SIG_DFL);
506ffe34450Schristos 	(void)signal(SIGQUIT, SIG_DFL);
50761f28255Scgd }
50861f28255Scgd 
50961f28255Scgd /*
51061f28255Scgd  * Fork a program with:
51161f28255Scgd  *  0 <-> remote tty in
51261f28255Scgd  *  1 <-> remote tty out
51361f28255Scgd  *  2 <-> local tty out
51461f28255Scgd  */
515e37283e1Slukem void
consh(char c)51658c2151fSperry consh(char c)
51761f28255Scgd {
51861f28255Scgd 	char buf[256];
51961f28255Scgd 	int cpid, status, p;
520e37283e1Slukem 	time_t start = 0;
52161f28255Scgd 
522ffe34450Schristos 	(void)putchar(c);
523923d7551Smrg 	if (prompt("Local command? ", buf, sizeof buf))
52461f28255Scgd 		return;
525ffe34450Schristos 	(void)write(attndes[1], "W", 1);	/* put TIPOUT into a wait state */
526ffe34450Schristos 	(void)signal(SIGINT, SIG_IGN);
527ffe34450Schristos 	(void)signal(SIGQUIT, SIG_IGN);
528ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &defchars);
529ffe34450Schristos 	(void)read(repdes[0], (char *)&ccc, 1);
53061f28255Scgd 	/*
53161f28255Scgd 	 * Set up file descriptors in the child and
53261f28255Scgd 	 *  let it go...
53361f28255Scgd 	 */
53461f28255Scgd 	if ((cpid = fork()) < 0)
535ffe34450Schristos 		(void)printf("can't fork!\r\n");
53661f28255Scgd 	else if (cpid) {
53761f28255Scgd 		start = time(0);
53861f28255Scgd 		while ((p = wait(&status)) > 0 && p != cpid)
53961f28255Scgd 			;
54061f28255Scgd 	} else {
541ffe34450Schristos 		(void)dup2(FD, 0);
542ffe34450Schristos 		(void)dup2(FD, 1);
543ffe34450Schristos 		(void)closefrom(3);
544ffe34450Schristos 		(void)signal(SIGINT, SIG_DFL);
545ffe34450Schristos 		(void)signal(SIGQUIT, SIG_DFL);
54661f28255Scgd 		execute(buf);
547ffe34450Schristos 		(void)printf("can't find `%s'\r\n", buf);
54861f28255Scgd 		exit(0);
54961f28255Scgd 	}
55061f28255Scgd 	if (boolean(value(VERBOSE)))
55161f28255Scgd 		prtime("away for ", time(0)-start);
552ffe34450Schristos 	(void)write(fildes[1], (char *)&ccc, 1);
553ffe34450Schristos 	(void)tcsetattr(0, TCSAFLUSH, &term);
554ffe34450Schristos 	(void)signal(SIGINT, SIG_DFL);
555ffe34450Schristos 	(void)signal(SIGQUIT, SIG_DFL);
55661f28255Scgd }
55761f28255Scgd 
55861f28255Scgd /*
55961f28255Scgd  * Escape to local shell
56061f28255Scgd  */
56129dc02e5Sperry /* ARGSUSED */
562e37283e1Slukem void
shell(char dummy __unused)563ffe34450Schristos shell(char dummy __unused)
56461f28255Scgd {
56561f28255Scgd 	int shpid, status;
5664f6045fcSchristos 	const char *cp;
56761f28255Scgd 
568ffe34450Schristos 	(void)printf("[sh]\r\n");
569ffe34450Schristos 	(void)signal(SIGINT, SIG_IGN);
570ffe34450Schristos 	(void)signal(SIGQUIT, SIG_IGN);
57161f28255Scgd 	unraw();
572e37283e1Slukem 	switch (shpid = fork()) {
573e37283e1Slukem 	default:
57461f28255Scgd 		while (shpid != wait(&status));
57561f28255Scgd 		raw();
576ffe34450Schristos 		(void)printf("\r\n!\r\n");
577ffe34450Schristos 		(void)signal(SIGINT, SIG_DFL);
578ffe34450Schristos 		(void)signal(SIGQUIT, SIG_DFL);
579e37283e1Slukem 		break;
580e37283e1Slukem 	case 0:
581ffe34450Schristos 		(void)signal(SIGQUIT, SIG_DFL);
582ffe34450Schristos 		(void)signal(SIGINT, SIG_DFL);
583e37283e1Slukem 		if ((cp = strrchr(value(SHELL), '/')) == NULL)
58461f28255Scgd 			cp = value(SHELL);
58561f28255Scgd 		else
58661f28255Scgd 			cp++;
587ffe34450Schristos 		(void)execl(value(SHELL), cp, NULL);
588ffe34450Schristos 		(void)fprintf(stderr, "\r\n");
589e37283e1Slukem 		err(1, "can't execl");
590e37283e1Slukem 		/* NOTREACHED */
591e37283e1Slukem 	case -1:
592ffe34450Schristos 		(void)fprintf(stderr, "\r\n");
593e37283e1Slukem 		err(1, "can't fork");
594e37283e1Slukem 		/* NOTREACHED */
59561f28255Scgd 	}
59661f28255Scgd }
59761f28255Scgd 
59861f28255Scgd /*
59961f28255Scgd  * TIPIN portion of scripting
60061f28255Scgd  *   initiate the conversation with TIPOUT
60161f28255Scgd  */
602e37283e1Slukem void
setscript(void)60358c2151fSperry setscript(void)
60461f28255Scgd {
60561f28255Scgd 	char c;
60661f28255Scgd 	/*
60761f28255Scgd 	 * enable TIPOUT side for dialogue
60861f28255Scgd 	 */
609ffe34450Schristos 	(void)write(attndes[1], "S", 1);
6106b9d2f6aSlukem 	if (boolean(value(SCRIPT)) && strlen(value(RECORD)))
611ffe34450Schristos 		(void)write(fildes[1], value(RECORD), strlen(value(RECORD)));
612ffe34450Schristos 	(void)write(fildes[1], "\n", 1);
61361f28255Scgd 	/*
61461f28255Scgd 	 * wait for TIPOUT to finish
61561f28255Scgd 	 */
616ffe34450Schristos 	(void)read(repdes[0], &c, 1);
61761f28255Scgd 	if (c == 'n')
618ffe34450Schristos 		(void)printf("can't create %s\r\n", (char *)value(RECORD));
61961f28255Scgd }
62061f28255Scgd 
62161f28255Scgd /*
62261f28255Scgd  * Change current working directory of
62361f28255Scgd  *   local portion of tip
62461f28255Scgd  */
62529dc02e5Sperry /* ARGSUSED */
626e37283e1Slukem void
chdirectory(char dummy __unused)627ffe34450Schristos chdirectory(char dummy __unused)
62861f28255Scgd {
6294f6045fcSchristos 	char dirnam[80];
6304f6045fcSchristos 	const char *cp = dirnam;
63161f28255Scgd 
6324f6045fcSchristos 	if (prompt("[cd] ", dirnam, sizeof dirnam)) {
63361f28255Scgd 		if (stoprompt)
63461f28255Scgd 			return;
63561f28255Scgd 		cp = value(HOME);
63661f28255Scgd 	}
63761f28255Scgd 	if (chdir(cp) < 0)
638ffe34450Schristos 		(void)printf("%s: bad directory\r\n", cp);
639ffe34450Schristos 	(void)printf("!\r\n");
64061f28255Scgd }
64161f28255Scgd 
642e37283e1Slukem void
tipabort(const char * msg)64358c2151fSperry tipabort(const char *msg)
64461f28255Scgd {
64561f28255Scgd 
646ffe34450Schristos 	(void)kill(pid, SIGTERM);
64761f28255Scgd 	disconnect(msg);
648e37283e1Slukem 	if (msg != NULL)
649ffe34450Schristos 		(void)printf("\r\n%s", msg);
650ffe34450Schristos 	(void)printf("\r\n[EOT]\r\n");
65161f28255Scgd 	unraw();
65261f28255Scgd 	exit(0);
65361f28255Scgd }
65461f28255Scgd 
65529dc02e5Sperry /* ARGSUSED */
656e37283e1Slukem void
finish(char dummy __unused)657ffe34450Schristos finish(char dummy __unused)
65861f28255Scgd {
6594f6045fcSchristos 	const char *dismsg;
66061f28255Scgd 
6616b9d2f6aSlukem 	dismsg = value(DISCONNECT);
6626b9d2f6aSlukem 	if (dismsg != NULL && dismsg[0] != '\0') {
663ffe34450Schristos 		(void)write(FD, dismsg, strlen(dismsg));
664ffe34450Schristos 		(void)sleep(5);
66561f28255Scgd 	}
666e37283e1Slukem 	tipabort(NULL);
66761f28255Scgd }
66861f28255Scgd 
66929dc02e5Sperry /* ARGSUSED */
67061f28255Scgd void
intcopy(int dummy __unused)671ffe34450Schristos intcopy(int dummy __unused)
67261f28255Scgd {
673923d7551Smrg 
67461f28255Scgd 	raw();
67561f28255Scgd 	quit = 1;
67661f28255Scgd 	longjmp(intbuf, 1);
67761f28255Scgd }
67861f28255Scgd 
679e37283e1Slukem void
execute(char * s)68058c2151fSperry execute(char *s)
68161f28255Scgd {
6824f6045fcSchristos 	const char *cp;
68361f28255Scgd 
684e37283e1Slukem 	if ((cp = strrchr(value(SHELL), '/')) == NULL)
68561f28255Scgd 		cp = value(SHELL);
68661f28255Scgd 	else
68761f28255Scgd 		cp++;
688ffe34450Schristos 	(void)execl(value(SHELL), cp, "-c", s, NULL);
68961f28255Scgd }
69061f28255Scgd 
691e37283e1Slukem int
args(char * buf,char * a[])69258c2151fSperry args(char *buf, char *a[])
69361f28255Scgd {
694e37283e1Slukem 	char *p = buf, *start;
695e37283e1Slukem 	char **parg = a;
696e37283e1Slukem 	int n = 0;
69761f28255Scgd 
69861f28255Scgd 	do {
69961f28255Scgd 		while (*p && (*p == ' ' || *p == '\t'))
70061f28255Scgd 			p++;
70161f28255Scgd 		start = p;
70261f28255Scgd 		if (*p)
70361f28255Scgd 			*parg = p;
70461f28255Scgd 		while (*p && (*p != ' ' && *p != '\t'))
70561f28255Scgd 			p++;
70661f28255Scgd 		if (p != start)
70761f28255Scgd 			parg++, n++;
70861f28255Scgd 		if (*p)
70961f28255Scgd 			*p++ = '\0';
71061f28255Scgd 	} while (*p);
71161f28255Scgd 
71261f28255Scgd 	return(n);
71361f28255Scgd }
71461f28255Scgd 
715e37283e1Slukem void
prtime(const char * s,time_t a)71658c2151fSperry prtime(const char *s, time_t a)
71761f28255Scgd {
718e37283e1Slukem 	int i;
71961f28255Scgd 	int nums[3];
72061f28255Scgd 
72161f28255Scgd 	for (i = 0; i < 3; i++) {
72261f28255Scgd 		nums[i] = (int)(a % quant[i]);
72361f28255Scgd 		a /= quant[i];
72461f28255Scgd 	}
725ffe34450Schristos 	(void)printf("%s", s);
72661f28255Scgd 	while (--i >= 0)
727e37283e1Slukem 		if (nums[i] || (i == 0 && nums[1] == 0 && nums[2] == 0))
728ffe34450Schristos 			(void)printf("%d %s%c ", nums[i], sep[i],
72961f28255Scgd 				nums[i] == 1 ? '\0' : 's');
730ffe34450Schristos 	(void)printf("\r\n!\r\n");
73161f28255Scgd }
73261f28255Scgd 
73329dc02e5Sperry /* ARGSUSED */
734e37283e1Slukem void
variable(char dummy __unused)735ffe34450Schristos variable(char dummy __unused)
73661f28255Scgd {
73761f28255Scgd 	char	buf[256];
73861f28255Scgd 
739923d7551Smrg 	if (prompt("[set] ", buf, sizeof buf))
74061f28255Scgd 		return;
74161f28255Scgd 	vlex(buf);
74261f28255Scgd 	if (vtable[BEAUTIFY].v_access&CHANGED) {
74361f28255Scgd 		vtable[BEAUTIFY].v_access &= ~CHANGED;
744ffe34450Schristos 		(void)write(attndes[1], "B", 1);	/* Tell TIPOUT to toggle */
74561f28255Scgd 	}
74661f28255Scgd 	if (vtable[SCRIPT].v_access&CHANGED) {
74761f28255Scgd 		vtable[SCRIPT].v_access &= ~CHANGED;
74861f28255Scgd 		setscript();
74961f28255Scgd 		/*
75061f28255Scgd 		 * So that "set record=blah script" doesn't
75161f28255Scgd 		 *  cause two transactions to occur.
75261f28255Scgd 		 */
75361f28255Scgd 		if (vtable[RECORD].v_access&CHANGED)
75461f28255Scgd 			vtable[RECORD].v_access &= ~CHANGED;
75561f28255Scgd 	}
75661f28255Scgd 	if (vtable[RECORD].v_access&CHANGED) {
75761f28255Scgd 		vtable[RECORD].v_access &= ~CHANGED;
75861f28255Scgd 		if (boolean(value(SCRIPT)))
75961f28255Scgd 			setscript();
76061f28255Scgd 	}
76161f28255Scgd 	if (vtable[TAND].v_access&CHANGED) {
76261f28255Scgd 		vtable[TAND].v_access &= ~CHANGED;
76361f28255Scgd 		if (boolean(value(TAND)))
76461f28255Scgd 			tandem("on");
76561f28255Scgd 		else
76661f28255Scgd 			tandem("off");
76761f28255Scgd 	}
76861f28255Scgd  	if (vtable[LECHO].v_access&CHANGED) {
76961f28255Scgd  		vtable[LECHO].v_access &= ~CHANGED;
77061f28255Scgd  		HD = boolean(value(LECHO));
77161f28255Scgd  	}
77261f28255Scgd 	if (vtable[PARITY].v_access&CHANGED) {
77361f28255Scgd 		vtable[PARITY].v_access &= ~CHANGED;
774e37283e1Slukem 		setparity(NULL);	/* XXX what is the correct arg? */
77561f28255Scgd 	}
77601ef0244Syamt 	if (vtable[HARDWAREFLOW].v_access&CHANGED) {
77701ef0244Syamt 		vtable[HARDWAREFLOW].v_access &= ~CHANGED;
77801ef0244Syamt 		if (boolean(value(HARDWAREFLOW)))
77901ef0244Syamt 			hardwareflow("on");
78001ef0244Syamt 		else
78101ef0244Syamt 			hardwareflow("off");
78201ef0244Syamt 	}
78361f28255Scgd }
78461f28255Scgd 
78561f28255Scgd /*
78661f28255Scgd  * Turn tandem mode on or off for remote tty.
78761f28255Scgd  */
788e37283e1Slukem void
tandem(const char * option)78958c2151fSperry tandem(const char *option)
79061f28255Scgd {
791258108ceSpk 	struct termios	rmtty;
79261f28255Scgd 
793ffe34450Schristos 	(void)tcgetattr(FD, &rmtty);
79461f28255Scgd 	if (strcmp(option, "on") == 0) {
795*6afb7d51Smlelstv 		rmtty.c_iflag |= IXON|IXOFF;
796*6afb7d51Smlelstv 		term.c_iflag |= IXON|IXOFF;
79761f28255Scgd 	} else {
798*6afb7d51Smlelstv 		rmtty.c_iflag &= ~(IXON|IXOFF);
799*6afb7d51Smlelstv 		term.c_iflag &= ~(IXON|IXOFF);
80061f28255Scgd 	}
801ffe34450Schristos 	(void)tcsetattr(FD, TCSADRAIN, &rmtty);
802ffe34450Schristos 	(void)tcsetattr(0, TCSADRAIN, &term);
80361f28255Scgd }
80461f28255Scgd 
80561f28255Scgd /*
80601ef0244Syamt  * Turn hardware flow control on or off for remote tty.
80701ef0244Syamt  */
80801ef0244Syamt void
hardwareflow(const char * option)80958c2151fSperry hardwareflow(const char *option)
81001ef0244Syamt {
81101ef0244Syamt 	struct termios	rmtty;
81201ef0244Syamt 
813ffe34450Schristos 	(void)tcgetattr(FD, &rmtty);
81401ef0244Syamt 	if (strcmp(option, "on") == 0)
815da6a898cStls 		rmtty.c_cflag |= CRTSCTS;
81601ef0244Syamt 	else
817da6a898cStls 		rmtty.c_cflag &= ~CRTSCTS;
818ffe34450Schristos 	(void)tcsetattr(FD, TCSADRAIN, &rmtty);
81901ef0244Syamt }
82001ef0244Syamt 
82101ef0244Syamt /*
82261f28255Scgd  * Send a break.
82361f28255Scgd  */
82429dc02e5Sperry /* ARGSUSED */
825e37283e1Slukem void
genbrk(char dummy __unused)826ffe34450Schristos genbrk(char dummy __unused)
82761f28255Scgd {
82861f28255Scgd 
829ffe34450Schristos 	(void)ioctl(FD, TIOCSBRK, NULL);
830ffe34450Schristos 	(void)sleep(1);
831ffe34450Schristos 	(void)ioctl(FD, TIOCCBRK, NULL);
83261f28255Scgd }
83361f28255Scgd 
83461f28255Scgd /*
83561f28255Scgd  * Suspend tip
83661f28255Scgd  */
837e37283e1Slukem void
suspend(char c)83858c2151fSperry suspend(char c)
83961f28255Scgd {
84061f28255Scgd 
84161f28255Scgd 	unraw();
842ffe34450Schristos 	(void)kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
84361f28255Scgd 	raw();
84461f28255Scgd }
84561f28255Scgd 
84661f28255Scgd /*
84761f28255Scgd  *	expand a file name if it includes shell meta characters
84861f28255Scgd  */
84961f28255Scgd 
85061f28255Scgd char *
expand(char aname[])851528614c1Schristos expand(char aname[])
85261f28255Scgd {
85361f28255Scgd 	static char xname[BUFSIZ];
854239d1ed1Schristos 	char * volatile name;
85561f28255Scgd 	char cmdbuf[BUFSIZ];
8564f6045fcSchristos 	int mypid, l;
8574f6045fcSchristos 	char *cp;
8584f6045fcSchristos 	const char *Shell;
859e37283e1Slukem 	int s, pivec[2];
86061f28255Scgd 
861239d1ed1Schristos 	name = aname;
86261f28255Scgd 	if (!anyof(name, "~{[*?$`'\"\\"))
86361f28255Scgd 		return(name);
86461f28255Scgd 	if (pipe(pivec) < 0) {
865b8dc57b8Stls 		warn("pipe");
86661f28255Scgd 		return(name);
86761f28255Scgd 	}
86853fddda6Smrg 	(void)snprintf(cmdbuf, sizeof cmdbuf, "echo %s", name);
8694f6045fcSchristos 	if ((mypid = vfork()) == 0) {
87061f28255Scgd 		Shell = value(SHELL);
871e37283e1Slukem 		if (Shell == NULL)
87261f28255Scgd 			Shell = _PATH_BSHELL;
873ffe34450Schristos 		(void)close(pivec[0]);
874ffe34450Schristos 		(void)close(1);
875ffe34450Schristos 		(void)dup(pivec[1]);
876ffe34450Schristos 		(void)close(pivec[1]);
877ffe34450Schristos 		(void)close(2);
878ffe34450Schristos 		(void)execl(Shell, Shell, "-c", cmdbuf, NULL);
87961f28255Scgd 		_exit(1);
88061f28255Scgd 	}
8814f6045fcSchristos 	if (mypid == -1) {
882b8dc57b8Stls 		warn("fork");
883ffe34450Schristos 		(void)close(pivec[0]);
884ffe34450Schristos 		(void)close(pivec[1]);
885e37283e1Slukem 		return(NULL);
88661f28255Scgd 	}
887ffe34450Schristos 	(void)close(pivec[1]);
88861f28255Scgd 	l = read(pivec[0], xname, BUFSIZ);
889ffe34450Schristos 	(void)close(pivec[0]);
890a625573bSjoerg 	while (wait(&s) != mypid)
8917a5b80beSjoerg 		continue;
89261f28255Scgd 	s &= 0377;
89361f28255Scgd 	if (s != 0 && s != SIGPIPE) {
894ffe34450Schristos 		(void)fprintf(stderr, "\"Echo\" failed\n");
895e37283e1Slukem 		return(NULL);
89661f28255Scgd 	}
89761f28255Scgd 	if (l < 0) {
898b8dc57b8Stls 		warn("read");
899e37283e1Slukem 		return(NULL);
90061f28255Scgd 	}
90161f28255Scgd 	if (l == 0) {
902ffe34450Schristos 		(void)fprintf(stderr, "\"%s\": No match\n", name);
903e37283e1Slukem 		return(NULL);
90461f28255Scgd 	}
90561f28255Scgd 	if (l == BUFSIZ) {
906ffe34450Schristos 		(void)fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
907e37283e1Slukem 		return(NULL);
90861f28255Scgd 	}
90961f28255Scgd 	xname[l] = 0;
91061f28255Scgd 	for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
91161f28255Scgd 		;
91261f28255Scgd 	*++cp = '\0';
91361f28255Scgd 	return(xname);
91461f28255Scgd }
91561f28255Scgd 
91661f28255Scgd /*
91761f28255Scgd  * Are any of the characters in the two strings the same?
91861f28255Scgd  */
91961f28255Scgd 
920e37283e1Slukem int
anyof(char * s1,const char * s2)92158c2151fSperry anyof(char *s1, const char *s2)
92261f28255Scgd {
923e37283e1Slukem 	int c;
92461f28255Scgd 
925c4341bc3Schristos 	while ((c = *s1++) != '\0')
92661f28255Scgd 		if (any(c, s2))
92761f28255Scgd 			return(1);
92861f28255Scgd 	return(0);
92961f28255Scgd }
930