xref: /original-bsd/usr.bin/tip/cmds.c (revision e59fb703)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)cmds.c	5.16 (Berkeley) 07/31/91";
10 #endif /* not lint */
11 
12 #include "tip.h"
13 #include "pathnames.h"
14 
15 /*
16  * tip
17  *
18  * miscellaneous commands
19  */
20 
21 int	quant[] = { 60, 60, 24 };
22 
23 char	null = '\0';
24 char	*sep[] = { "second", "minute", "hour" };
25 static char *argv[10];		/* argument vector for take and put */
26 
27 void	timeout();		/* timeout function called on alarm */
28 void	stopsnd();		/* SIGINT handler during file transfers */
29 void	intcopy();		/* interrupt routine for file transfers */
30 
31 /*
32  * FTP - remote ==> local
33  *  get a file from the remote host
34  */
35 getfl(c)
36 	char c;
37 {
38 	char buf[256], *cp, *expand();
39 
40 	putchar(c);
41 	/*
42 	 * get the UNIX receiving file's name
43 	 */
44 	if (prompt("Local file name? ", copyname))
45 		return;
46 	cp = expand(copyname);
47 	if ((sfd = creat(cp, 0666)) < 0) {
48 		printf("\r\n%s: cannot creat\r\n", copyname);
49 		return;
50 	}
51 
52 	/*
53 	 * collect parameters
54 	 */
55 	if (prompt("List command for remote system? ", buf)) {
56 		unlink(copyname);
57 		return;
58 	}
59 	transfer(buf, sfd, value(EOFREAD));
60 }
61 
62 /*
63  * Cu-like take command
64  */
65 cu_take(cc)
66 	char cc;
67 {
68 	int fd, argc;
69 	char line[BUFSIZ], *expand(), *cp;
70 
71 	if (prompt("[take] ", copyname))
72 		return;
73 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
74 		printf("usage: <take> from [to]\r\n");
75 		return;
76 	}
77 	if (argc == 1)
78 		argv[1] = argv[0];
79 	cp = expand(argv[1]);
80 	if ((fd = creat(cp, 0666)) < 0) {
81 		printf("\r\n%s: cannot create\r\n", argv[1]);
82 		return;
83 	}
84 	sprintf(line, "cat %s;echo \01", argv[0]);
85 	transfer(line, fd, "\01");
86 }
87 
88 static	jmp_buf intbuf;
89 /*
90  * Bulk transfer routine --
91  *  used by getfl(), cu_take(), and pipefile()
92  */
93 transfer(buf, fd, eofchars)
94 	char *buf, *eofchars;
95 {
96 	register int ct;
97 	char c, buffer[BUFSIZ];
98 	register char *p = buffer;
99 	register int cnt, eof;
100 	time_t start;
101 	sig_t f;
102 	char r;
103 
104 	pwrite(FD, buf, size(buf));
105 	quit = 0;
106 	kill(pid, SIGIOT);
107 	read(repdes[0], (char *)&ccc, 1);  /* Wait until read process stops */
108 
109 	/*
110 	 * finish command
111 	 */
112 	r = '\r';
113 	pwrite(FD, &r, 1);
114 	do
115 		read(FD, &c, 1);
116 	while ((c&0177) != '\n');
117 	ioctl(0, TIOCSETC, &defchars);
118 
119 	(void) setjmp(intbuf);
120 	f = signal(SIGINT, intcopy);
121 	start = time(0);
122 	for (ct = 0; !quit;) {
123 		eof = read(FD, &c, 1) <= 0;
124 		c &= 0177;
125 		if (quit)
126 			continue;
127 		if (eof || any(c, eofchars))
128 			break;
129 		if (c == 0)
130 			continue;	/* ignore nulls */
131 		if (c == '\r')
132 			continue;
133 		*p++ = c;
134 
135 		if (c == '\n' && boolean(value(VERBOSE)))
136 			printf("\r%d", ++ct);
137 		if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
138 			if (write(fd, buffer, cnt) != cnt) {
139 				printf("\r\nwrite error\r\n");
140 				quit = 1;
141 			}
142 			p = buffer;
143 		}
144 	}
145 	if (cnt = (p-buffer))
146 		if (write(fd, buffer, cnt) != cnt)
147 			printf("\r\nwrite error\r\n");
148 
149 	if (boolean(value(VERBOSE)))
150 		prtime(" lines transferred in ", time(0)-start);
151 	ioctl(0, TIOCSETC, &tchars);
152 	write(fildes[1], (char *)&ccc, 1);
153 	signal(SIGINT, f);
154 	close(fd);
155 }
156 
157 /*
158  * FTP - remote ==> local process
159  *   send remote input to local process via pipe
160  */
161 pipefile()
162 {
163 	int cpid, pdes[2];
164 	char buf[256];
165 	int status, p;
166 	extern int errno;
167 
168 	if (prompt("Local command? ", buf))
169 		return;
170 
171 	if (pipe(pdes)) {
172 		printf("can't establish pipe\r\n");
173 		return;
174 	}
175 
176 	if ((cpid = fork()) < 0) {
177 		printf("can't fork!\r\n");
178 		return;
179 	} else if (cpid) {
180 		if (prompt("List command for remote system? ", buf)) {
181 			close(pdes[0]), close(pdes[1]);
182 			kill (cpid, SIGKILL);
183 		} else {
184 			close(pdes[0]);
185 			signal(SIGPIPE, intcopy);
186 			transfer(buf, pdes[1], value(EOFREAD));
187 			signal(SIGPIPE, SIG_DFL);
188 			while ((p = wait(&status)) > 0 && p != cpid)
189 				;
190 		}
191 	} else {
192 		register int f;
193 
194 		dup2(pdes[0], 0);
195 		close(pdes[0]);
196 		for (f = 3; f < 20; f++)
197 			close(f);
198 		execute(buf);
199 		printf("can't execl!\r\n");
200 		exit(0);
201 	}
202 }
203 
204 /*
205  * Interrupt service routine for FTP
206  */
207 void
208 stopsnd()
209 {
210 
211 	stop = 1;
212 	signal(SIGINT, SIG_IGN);
213 }
214 
215 /*
216  * FTP - local ==> remote
217  *  send local file to remote host
218  *  terminate transmission with pseudo EOF sequence
219  */
220 sendfile(cc)
221 	char cc;
222 {
223 	FILE *fd;
224 	char *fnamex;
225 	char *expand();
226 
227 	putchar(cc);
228 	/*
229 	 * get file name
230 	 */
231 	if (prompt("Local file name? ", fname))
232 		return;
233 
234 	/*
235 	 * look up file
236 	 */
237 	fnamex = expand(fname);
238 	if ((fd = fopen(fnamex, "r")) == NULL) {
239 		printf("%s: cannot open\r\n", fname);
240 		return;
241 	}
242 	transmit(fd, value(EOFWRITE), NULL);
243 	if (!boolean(value(ECHOCHECK))) {
244 		struct sgttyb buf;
245 
246 		ioctl(FD, TIOCGETP, &buf);	/* this does a */
247 		ioctl(FD, TIOCSETP, &buf);	/*   wflushtty */
248 	}
249 }
250 
251 /*
252  * Bulk transfer routine to remote host --
253  *   used by sendfile() and cu_put()
254  */
255 transmit(fd, eofchars, command)
256 	FILE *fd;
257 	char *eofchars, *command;
258 {
259 	char *pc, lastc;
260 	int c, ccount, lcount;
261 	time_t start_t, stop_t;
262 	sig_t f;
263 
264 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
265 	stop = 0;
266 	f = signal(SIGINT, stopsnd);
267 	ioctl(0, TIOCSETC, &defchars);
268 	read(repdes[0], (char *)&ccc, 1);
269 	if (command != NULL) {
270 		for (pc = command; *pc; pc++)
271 			send(*pc);
272 		if (boolean(value(ECHOCHECK)))
273 			read(FD, (char *)&c, 1);	/* trailing \n */
274 		else {
275 			struct sgttyb buf;
276 
277 			ioctl(FD, TIOCGETP, &buf);	/* this does a */
278 			ioctl(FD, TIOCSETP, &buf);	/*   wflushtty */
279 			sleep(5); /* wait for remote stty to take effect */
280 		}
281 	}
282 	lcount = 0;
283 	lastc = '\0';
284 	start_t = time(0);
285 	while (1) {
286 		ccount = 0;
287 		do {
288 			c = getc(fd);
289 			if (stop)
290 				goto out;
291 			if (c == EOF)
292 				goto out;
293 			if (c == 0177 && !boolean(value(RAWFTP)))
294 				continue;
295 			lastc = c;
296 			if (c < 040) {
297 				if (c == '\n') {
298 					if (!boolean(value(RAWFTP)))
299 						c = '\r';
300 				}
301 				else if (c == '\t') {
302 					if (!boolean(value(RAWFTP))) {
303 						if (boolean(value(TABEXPAND))) {
304 							send(' ');
305 							while ((++ccount % 8) != 0)
306 								send(' ');
307 							continue;
308 						}
309 					}
310 				} else
311 					if (!boolean(value(RAWFTP)))
312 						continue;
313 			}
314 			send(c);
315 		} while (c != '\r' && !boolean(value(RAWFTP)));
316 		if (boolean(value(VERBOSE)))
317 			printf("\r%d", ++lcount);
318 		if (boolean(value(ECHOCHECK))) {
319 			timedout = 0;
320 			alarm((int)value(ETIMEOUT));
321 			do {	/* wait for prompt */
322 				read(FD, (char *)&c, 1);
323 				if (timedout || stop) {
324 					if (timedout)
325 						printf("\r\ntimed out at eol\r\n");
326 					alarm(0);
327 					goto out;
328 				}
329 			} while ((c&0177) != character(value(PROMPT)));
330 			alarm(0);
331 		}
332 	}
333 out:
334 	if (lastc != '\n' && !boolean(value(RAWFTP)))
335 		send('\r');
336 	for (pc = eofchars; *pc; pc++)
337 		send(*pc);
338 	stop_t = time(0);
339 	fclose(fd);
340 	signal(SIGINT, f);
341 	if (boolean(value(VERBOSE)))
342 		if (boolean(value(RAWFTP)))
343 			prtime(" chars transferred in ", stop_t-start_t);
344 		else
345 			prtime(" lines transferred in ", stop_t-start_t);
346 	write(fildes[1], (char *)&ccc, 1);
347 	ioctl(0, TIOCSETC, &tchars);
348 }
349 
350 /*
351  * Cu-like put command
352  */
353 cu_put(cc)
354 	char cc;
355 {
356 	FILE *fd;
357 	char line[BUFSIZ];
358 	int argc;
359 	char *expand();
360 	char *copynamex;
361 
362 	if (prompt("[put] ", copyname))
363 		return;
364 	if ((argc = args(copyname, argv)) < 1 || argc > 2) {
365 		printf("usage: <put> from [to]\r\n");
366 		return;
367 	}
368 	if (argc == 1)
369 		argv[1] = argv[0];
370 	copynamex = expand(argv[0]);
371 	if ((fd = fopen(copynamex, "r")) == NULL) {
372 		printf("%s: cannot open\r\n", copynamex);
373 		return;
374 	}
375 	if (boolean(value(ECHOCHECK)))
376 		sprintf(line, "cat>%s\r", argv[1]);
377 	else
378 		sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]);
379 	transmit(fd, "\04", line);
380 }
381 
382 /*
383  * FTP - send single character
384  *  wait for echo & handle timeout
385  */
386 send(c)
387 	char c;
388 {
389 	char cc;
390 	int retry = 0;
391 
392 	cc = c;
393 	pwrite(FD, &cc, 1);
394 #ifdef notdef
395 	if (number(value(CDELAY)) > 0 && c != '\r')
396 		nap(number(value(CDELAY)));
397 #endif
398 	if (!boolean(value(ECHOCHECK))) {
399 #ifdef notdef
400 		if (number(value(LDELAY)) > 0 && c == '\r')
401 			nap(number(value(LDELAY)));
402 #endif
403 		return;
404 	}
405 tryagain:
406 	timedout = 0;
407 	alarm((int)value(ETIMEOUT));
408 	read(FD, &cc, 1);
409 	alarm(0);
410 	if (timedout) {
411 		printf("\r\ntimeout error (%s)\r\n", ctrl(c));
412 		if (retry++ > 3)
413 			return;
414 		pwrite(FD, &null, 1); /* poke it */
415 		goto tryagain;
416 	}
417 }
418 
419 void
420 timeout()
421 {
422 	signal(SIGALRM, timeout);
423 	timedout = 1;
424 }
425 
426 /*
427  * Stolen from consh() -- puts a remote file on the output of a local command.
428  *	Identical to consh() except for where stdout goes.
429  */
430 pipeout(c)
431 {
432 	char buf[256];
433 	int cpid, status, p;
434 	time_t start;
435 
436 	putchar(c);
437 	if (prompt("Local command? ", buf))
438 		return;
439 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
440 	signal(SIGINT, SIG_IGN);
441 	signal(SIGQUIT, SIG_IGN);
442 	ioctl(0, TIOCSETC, &defchars);
443 	read(repdes[0], (char *)&ccc, 1);
444 	/*
445 	 * Set up file descriptors in the child and
446 	 *  let it go...
447 	 */
448 	if ((cpid = fork()) < 0)
449 		printf("can't fork!\r\n");
450 	else if (cpid) {
451 		start = time(0);
452 		while ((p = wait(&status)) > 0 && p != cpid)
453 			;
454 	} else {
455 		register int i;
456 
457 		dup2(FD, 1);
458 		for (i = 3; i < 20; i++)
459 			close(i);
460 		signal(SIGINT, SIG_DFL);
461 		signal(SIGQUIT, SIG_DFL);
462 		execute(buf);
463 		printf("can't find `%s'\r\n", buf);
464 		exit(0);
465 	}
466 	if (boolean(value(VERBOSE)))
467 		prtime("away for ", time(0)-start);
468 	write(fildes[1], (char *)&ccc, 1);
469 	ioctl(0, TIOCSETC, &tchars);
470 	signal(SIGINT, SIG_DFL);
471 	signal(SIGQUIT, SIG_DFL);
472 }
473 
474 #ifdef CONNECT
475 /*
476  * Fork a program with:
477  *  0 <-> local tty in
478  *  1 <-> local tty out
479  *  2 <-> local tty out
480  *  3 <-> remote tty in
481  *  4 <-> remote tty out
482  */
483 consh(c)
484 {
485 	char buf[256];
486 	int cpid, status, p;
487 	time_t start;
488 
489 	putchar(c);
490 	if (prompt("Local command? ", buf))
491 		return;
492 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
493 	signal(SIGINT, SIG_IGN);
494 	signal(SIGQUIT, SIG_IGN);
495 	ioctl(0, TIOCSETC, &defchars);
496 	read(repdes[0], (char *)&ccc, 1);
497 	/*
498 	 * Set up file descriptors in the child and
499 	 *  let it go...
500 	 */
501 	if ((cpid = fork()) < 0)
502 		printf("can't fork!\r\n");
503 	else if (cpid) {
504 		start = time(0);
505 		while ((p = wait(&status)) > 0 && p != cpid)
506 			;
507 	} else {
508 		register int i;
509 
510 		dup2(FD, 3);
511 		dup2(3, 4);
512 		for (i = 5; i < 20; i++)
513 			close(i);
514 		signal(SIGINT, SIG_DFL);
515 		signal(SIGQUIT, SIG_DFL);
516 		execute(buf);
517 		printf("can't find `%s'\r\n", buf);
518 		exit(0);
519 	}
520 	if (boolean(value(VERBOSE)))
521 		prtime("away for ", time(0)-start);
522 	write(fildes[1], (char *)&ccc, 1);
523 	ioctl(0, TIOCSETC, &tchars);
524 	signal(SIGINT, SIG_DFL);
525 	signal(SIGQUIT, SIG_DFL);
526 }
527 #endif
528 
529 /*
530  * Escape to local shell
531  */
532 shell()
533 {
534 	int shpid, status;
535 	extern char **environ;
536 	char *cp;
537 
538 	printf("[sh]\r\n");
539 	signal(SIGINT, SIG_IGN);
540 	signal(SIGQUIT, SIG_IGN);
541 	unraw();
542 	if (shpid = fork()) {
543 		while (shpid != wait(&status));
544 		raw();
545 		printf("\r\n!\r\n");
546 		signal(SIGINT, SIG_DFL);
547 		signal(SIGQUIT, SIG_DFL);
548 		return;
549 	} else {
550 		signal(SIGQUIT, SIG_DFL);
551 		signal(SIGINT, SIG_DFL);
552 		if ((cp = rindex(value(SHELL), '/')) == NULL)
553 			cp = value(SHELL);
554 		else
555 			cp++;
556 		shell_uid();
557 		execl(value(SHELL), cp, 0);
558 		printf("\r\ncan't execl!\r\n");
559 		exit(1);
560 	}
561 }
562 
563 /*
564  * TIPIN portion of scripting
565  *   initiate the conversation with TIPOUT
566  */
567 setscript()
568 {
569 	char c;
570 	/*
571 	 * enable TIPOUT side for dialogue
572 	 */
573 	kill(pid, SIGEMT);
574 	if (boolean(value(SCRIPT)))
575 		write(fildes[1], value(RECORD), size(value(RECORD)));
576 	write(fildes[1], "\n", 1);
577 	/*
578 	 * wait for TIPOUT to finish
579 	 */
580 	read(repdes[0], &c, 1);
581 	if (c == 'n')
582 		printf("can't create %s\r\n", value(RECORD));
583 }
584 
585 /*
586  * Change current working directory of
587  *   local portion of tip
588  */
589 chdirectory()
590 {
591 	char dirname[80];
592 	register char *cp = dirname;
593 
594 	if (prompt("[cd] ", dirname)) {
595 		if (stoprompt)
596 			return;
597 		cp = value(HOME);
598 	}
599 	if (chdir(cp) < 0)
600 		printf("%s: bad directory\r\n", cp);
601 	printf("!\r\n");
602 }
603 
604 tipabort(msg)
605 	char *msg;
606 {
607 
608 	kill(pid, SIGTERM);
609 	disconnect(msg);
610 	if (msg != NOSTR)
611 		printf("\r\n%s", msg);
612 	printf("\r\n[EOT]\r\n");
613 	daemon_uid();
614 	(void)uu_unlock(uucplock);
615 	unraw();
616 	exit(0);
617 }
618 
619 finish()
620 {
621 	char *dismsg;
622 
623 	if ((dismsg = value(DISCONNECT)) != NOSTR) {
624 		write(FD, dismsg, strlen(dismsg));
625 		sleep(5);
626 	}
627 	tipabort(NOSTR);
628 }
629 
630 void
631 intcopy()
632 {
633 	raw();
634 	quit = 1;
635 	longjmp(intbuf, 1);
636 }
637 
638 execute(s)
639 	char *s;
640 {
641 	register char *cp;
642 
643 	if ((cp = rindex(value(SHELL), '/')) == NULL)
644 		cp = value(SHELL);
645 	else
646 		cp++;
647 	shell_uid();
648 	execl(value(SHELL), cp, "-c", s, 0);
649 }
650 
651 args(buf, a)
652 	char *buf, *a[];
653 {
654 	register char *p = buf, *start;
655 	register char **parg = a;
656 	register int n = 0;
657 
658 	do {
659 		while (*p && (*p == ' ' || *p == '\t'))
660 			p++;
661 		start = p;
662 		if (*p)
663 			*parg = p;
664 		while (*p && (*p != ' ' && *p != '\t'))
665 			p++;
666 		if (p != start)
667 			parg++, n++;
668 		if (*p)
669 			*p++ = '\0';
670 	} while (*p);
671 
672 	return(n);
673 }
674 
675 prtime(s, a)
676 	char *s;
677 	time_t a;
678 {
679 	register i;
680 	int nums[3];
681 
682 	for (i = 0; i < 3; i++) {
683 		nums[i] = (int)(a % quant[i]);
684 		a /= quant[i];
685 	}
686 	printf("%s", s);
687 	while (--i >= 0)
688 		if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
689 			printf("%d %s%c ", nums[i], sep[i],
690 				nums[i] == 1 ? '\0' : 's');
691 	printf("\r\n!\r\n");
692 }
693 
694 variable()
695 {
696 	char	buf[256];
697 
698 	if (prompt("[set] ", buf))
699 		return;
700 	vlex(buf);
701 	if (vtable[BEAUTIFY].v_access&CHANGED) {
702 		vtable[BEAUTIFY].v_access &= ~CHANGED;
703 		kill(pid, SIGSYS);
704 	}
705 	if (vtable[SCRIPT].v_access&CHANGED) {
706 		vtable[SCRIPT].v_access &= ~CHANGED;
707 		setscript();
708 		/*
709 		 * So that "set record=blah script" doesn't
710 		 *  cause two transactions to occur.
711 		 */
712 		if (vtable[RECORD].v_access&CHANGED)
713 			vtable[RECORD].v_access &= ~CHANGED;
714 	}
715 	if (vtable[RECORD].v_access&CHANGED) {
716 		vtable[RECORD].v_access &= ~CHANGED;
717 		if (boolean(value(SCRIPT)))
718 			setscript();
719 	}
720 	if (vtable[TAND].v_access&CHANGED) {
721 		vtable[TAND].v_access &= ~CHANGED;
722 		if (boolean(value(TAND)))
723 			tandem("on");
724 		else
725 			tandem("off");
726 	}
727  	if (vtable[LECHO].v_access&CHANGED) {
728  		vtable[LECHO].v_access &= ~CHANGED;
729  		HD = boolean(value(LECHO));
730  	}
731 	if (vtable[PARITY].v_access&CHANGED) {
732 		vtable[PARITY].v_access &= ~CHANGED;
733 		setparity();
734 	}
735 }
736 
737 /*
738  * Turn tandem mode on or off for remote tty.
739  */
740 tandem(option)
741 	char *option;
742 {
743 	struct sgttyb rmtty;
744 
745 	ioctl(FD, TIOCGETP, &rmtty);
746 	if (strcmp(option,"on") == 0) {
747 		rmtty.sg_flags |= TANDEM;
748 		arg.sg_flags |= TANDEM;
749 	} else {
750 		rmtty.sg_flags &= ~TANDEM;
751 		arg.sg_flags &= ~TANDEM;
752 	}
753 	ioctl(FD, TIOCSETP, &rmtty);
754 	ioctl(0,  TIOCSETP, &arg);
755 }
756 
757 /*
758  * Send a break.
759  */
760 genbrk()
761 {
762 
763 	ioctl(FD, TIOCSBRK, NULL);
764 	sleep(1);
765 	ioctl(FD, TIOCCBRK, NULL);
766 }
767 
768 /*
769  * Suspend tip
770  */
771 suspend(c)
772 	char c;
773 {
774 
775 	unraw();
776 	kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
777 	raw();
778 }
779 
780 /*
781  *	expand a file name if it includes shell meta characters
782  */
783 
784 char *
785 expand(name)
786 	char name[];
787 {
788 	static char xname[BUFSIZ];
789 	char cmdbuf[BUFSIZ];
790 	register int pid, l, rc;
791 	register char *cp, *Shell;
792 	int s, pivec[2], (*sigint)();
793 
794 	if (!anyof(name, "~{[*?$`'\"\\"))
795 		return(name);
796 	/* sigint = signal(SIGINT, SIG_IGN); */
797 	if (pipe(pivec) < 0) {
798 		perror("pipe");
799 		/* signal(SIGINT, sigint) */
800 		return(name);
801 	}
802 	sprintf(cmdbuf, "echo %s", name);
803 	if ((pid = vfork()) == 0) {
804 		Shell = value(SHELL);
805 		if (Shell == NOSTR)
806 			Shell = _PATH_BSHELL;
807 		close(pivec[0]);
808 		close(1);
809 		dup(pivec[1]);
810 		close(pivec[1]);
811 		close(2);
812 		shell_uid();
813 		execl(Shell, Shell, "-c", cmdbuf, 0);
814 		_exit(1);
815 	}
816 	if (pid == -1) {
817 		perror("fork");
818 		close(pivec[0]);
819 		close(pivec[1]);
820 		return(NOSTR);
821 	}
822 	close(pivec[1]);
823 	l = read(pivec[0], xname, BUFSIZ);
824 	close(pivec[0]);
825 	while (wait(&s) != pid);
826 		;
827 	s &= 0377;
828 	if (s != 0 && s != SIGPIPE) {
829 		fprintf(stderr, "\"Echo\" failed\n");
830 		return(NOSTR);
831 	}
832 	if (l < 0) {
833 		perror("read");
834 		return(NOSTR);
835 	}
836 	if (l == 0) {
837 		fprintf(stderr, "\"%s\": No match\n", name);
838 		return(NOSTR);
839 	}
840 	if (l == BUFSIZ) {
841 		fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
842 		return(NOSTR);
843 	}
844 	xname[l] = 0;
845 	for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
846 		;
847 	*++cp = '\0';
848 	return(xname);
849 }
850 
851 /*
852  * Are any of the characters in the two strings the same?
853  */
854 
855 anyof(s1, s2)
856 	register char *s1, *s2;
857 {
858 	register int c;
859 
860 	while (c = *s1++)
861 		if (any(c, s2))
862 			return(1);
863 	return(0);
864 }
865