xref: /original-bsd/usr.bin/tip/cmds.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)cmds.c	8.1 (Berkeley) 06/06/93";
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 <-> remote tty in
478  *  1 <-> remote tty out
479  *  2 <-> local tty out
480  */
481 consh(c)
482 {
483 	char buf[256];
484 	int cpid, status, p;
485 	time_t start;
486 
487 	putchar(c);
488 	if (prompt("Local command? ", buf))
489 		return;
490 	kill(pid, SIGIOT);	/* put TIPOUT into a wait state */
491 	signal(SIGINT, SIG_IGN);
492 	signal(SIGQUIT, SIG_IGN);
493 	ioctl(0, TIOCSETC, &defchars);
494 	read(repdes[0], (char *)&ccc, 1);
495 	/*
496 	 * Set up file descriptors in the child and
497 	 *  let it go...
498 	 */
499 	if ((cpid = fork()) < 0)
500 		printf("can't fork!\r\n");
501 	else if (cpid) {
502 		start = time(0);
503 		while ((p = wait(&status)) > 0 && p != cpid)
504 			;
505 	} else {
506 		register int i;
507 
508 		dup2(FD, 0);
509 		dup2(3, 1);
510 		for (i = 3; i < 20; i++)
511 			close(i);
512 		signal(SIGINT, SIG_DFL);
513 		signal(SIGQUIT, SIG_DFL);
514 		execute(buf);
515 		printf("can't find `%s'\r\n", buf);
516 		exit(0);
517 	}
518 	if (boolean(value(VERBOSE)))
519 		prtime("away for ", time(0)-start);
520 	write(fildes[1], (char *)&ccc, 1);
521 	ioctl(0, TIOCSETC, &tchars);
522 	signal(SIGINT, SIG_DFL);
523 	signal(SIGQUIT, SIG_DFL);
524 }
525 #endif
526 
527 /*
528  * Escape to local shell
529  */
530 shell()
531 {
532 	int shpid, status;
533 	extern char **environ;
534 	char *cp;
535 
536 	printf("[sh]\r\n");
537 	signal(SIGINT, SIG_IGN);
538 	signal(SIGQUIT, SIG_IGN);
539 	unraw();
540 	if (shpid = fork()) {
541 		while (shpid != wait(&status));
542 		raw();
543 		printf("\r\n!\r\n");
544 		signal(SIGINT, SIG_DFL);
545 		signal(SIGQUIT, SIG_DFL);
546 		return;
547 	} else {
548 		signal(SIGQUIT, SIG_DFL);
549 		signal(SIGINT, SIG_DFL);
550 		if ((cp = rindex(value(SHELL), '/')) == NULL)
551 			cp = value(SHELL);
552 		else
553 			cp++;
554 		shell_uid();
555 		execl(value(SHELL), cp, 0);
556 		printf("\r\ncan't execl!\r\n");
557 		exit(1);
558 	}
559 }
560 
561 /*
562  * TIPIN portion of scripting
563  *   initiate the conversation with TIPOUT
564  */
565 setscript()
566 {
567 	char c;
568 	/*
569 	 * enable TIPOUT side for dialogue
570 	 */
571 	kill(pid, SIGEMT);
572 	if (boolean(value(SCRIPT)))
573 		write(fildes[1], value(RECORD), size(value(RECORD)));
574 	write(fildes[1], "\n", 1);
575 	/*
576 	 * wait for TIPOUT to finish
577 	 */
578 	read(repdes[0], &c, 1);
579 	if (c == 'n')
580 		printf("can't create %s\r\n", value(RECORD));
581 }
582 
583 /*
584  * Change current working directory of
585  *   local portion of tip
586  */
587 chdirectory()
588 {
589 	char dirname[80];
590 	register char *cp = dirname;
591 
592 	if (prompt("[cd] ", dirname)) {
593 		if (stoprompt)
594 			return;
595 		cp = value(HOME);
596 	}
597 	if (chdir(cp) < 0)
598 		printf("%s: bad directory\r\n", cp);
599 	printf("!\r\n");
600 }
601 
602 tipabort(msg)
603 	char *msg;
604 {
605 
606 	kill(pid, SIGTERM);
607 	disconnect(msg);
608 	if (msg != NOSTR)
609 		printf("\r\n%s", msg);
610 	printf("\r\n[EOT]\r\n");
611 	daemon_uid();
612 	(void)uu_unlock(uucplock);
613 	unraw();
614 	exit(0);
615 }
616 
617 finish()
618 {
619 	char *dismsg;
620 
621 	if ((dismsg = value(DISCONNECT)) != NOSTR) {
622 		write(FD, dismsg, strlen(dismsg));
623 		sleep(5);
624 	}
625 	tipabort(NOSTR);
626 }
627 
628 void
629 intcopy()
630 {
631 	raw();
632 	quit = 1;
633 	longjmp(intbuf, 1);
634 }
635 
636 execute(s)
637 	char *s;
638 {
639 	register char *cp;
640 
641 	if ((cp = rindex(value(SHELL), '/')) == NULL)
642 		cp = value(SHELL);
643 	else
644 		cp++;
645 	shell_uid();
646 	execl(value(SHELL), cp, "-c", s, 0);
647 }
648 
649 args(buf, a)
650 	char *buf, *a[];
651 {
652 	register char *p = buf, *start;
653 	register char **parg = a;
654 	register int n = 0;
655 
656 	do {
657 		while (*p && (*p == ' ' || *p == '\t'))
658 			p++;
659 		start = p;
660 		if (*p)
661 			*parg = p;
662 		while (*p && (*p != ' ' && *p != '\t'))
663 			p++;
664 		if (p != start)
665 			parg++, n++;
666 		if (*p)
667 			*p++ = '\0';
668 	} while (*p);
669 
670 	return(n);
671 }
672 
673 prtime(s, a)
674 	char *s;
675 	time_t a;
676 {
677 	register i;
678 	int nums[3];
679 
680 	for (i = 0; i < 3; i++) {
681 		nums[i] = (int)(a % quant[i]);
682 		a /= quant[i];
683 	}
684 	printf("%s", s);
685 	while (--i >= 0)
686 		if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
687 			printf("%d %s%c ", nums[i], sep[i],
688 				nums[i] == 1 ? '\0' : 's');
689 	printf("\r\n!\r\n");
690 }
691 
692 variable()
693 {
694 	char	buf[256];
695 
696 	if (prompt("[set] ", buf))
697 		return;
698 	vlex(buf);
699 	if (vtable[BEAUTIFY].v_access&CHANGED) {
700 		vtable[BEAUTIFY].v_access &= ~CHANGED;
701 		kill(pid, SIGSYS);
702 	}
703 	if (vtable[SCRIPT].v_access&CHANGED) {
704 		vtable[SCRIPT].v_access &= ~CHANGED;
705 		setscript();
706 		/*
707 		 * So that "set record=blah script" doesn't
708 		 *  cause two transactions to occur.
709 		 */
710 		if (vtable[RECORD].v_access&CHANGED)
711 			vtable[RECORD].v_access &= ~CHANGED;
712 	}
713 	if (vtable[RECORD].v_access&CHANGED) {
714 		vtable[RECORD].v_access &= ~CHANGED;
715 		if (boolean(value(SCRIPT)))
716 			setscript();
717 	}
718 	if (vtable[TAND].v_access&CHANGED) {
719 		vtable[TAND].v_access &= ~CHANGED;
720 		if (boolean(value(TAND)))
721 			tandem("on");
722 		else
723 			tandem("off");
724 	}
725  	if (vtable[LECHO].v_access&CHANGED) {
726  		vtable[LECHO].v_access &= ~CHANGED;
727  		HD = boolean(value(LECHO));
728  	}
729 	if (vtable[PARITY].v_access&CHANGED) {
730 		vtable[PARITY].v_access &= ~CHANGED;
731 		setparity();
732 	}
733 }
734 
735 /*
736  * Turn tandem mode on or off for remote tty.
737  */
738 tandem(option)
739 	char *option;
740 {
741 	struct sgttyb rmtty;
742 
743 	ioctl(FD, TIOCGETP, &rmtty);
744 	if (strcmp(option,"on") == 0) {
745 		rmtty.sg_flags |= TANDEM;
746 		arg.sg_flags |= TANDEM;
747 	} else {
748 		rmtty.sg_flags &= ~TANDEM;
749 		arg.sg_flags &= ~TANDEM;
750 	}
751 	ioctl(FD, TIOCSETP, &rmtty);
752 	ioctl(0,  TIOCSETP, &arg);
753 }
754 
755 /*
756  * Send a break.
757  */
758 genbrk()
759 {
760 
761 	ioctl(FD, TIOCSBRK, NULL);
762 	sleep(1);
763 	ioctl(FD, TIOCCBRK, NULL);
764 }
765 
766 /*
767  * Suspend tip
768  */
769 suspend(c)
770 	char c;
771 {
772 
773 	unraw();
774 	kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
775 	raw();
776 }
777 
778 /*
779  *	expand a file name if it includes shell meta characters
780  */
781 
782 char *
783 expand(name)
784 	char name[];
785 {
786 	static char xname[BUFSIZ];
787 	char cmdbuf[BUFSIZ];
788 	register int pid, l, rc;
789 	register char *cp, *Shell;
790 	int s, pivec[2], (*sigint)();
791 
792 	if (!anyof(name, "~{[*?$`'\"\\"))
793 		return(name);
794 	/* sigint = signal(SIGINT, SIG_IGN); */
795 	if (pipe(pivec) < 0) {
796 		perror("pipe");
797 		/* signal(SIGINT, sigint) */
798 		return(name);
799 	}
800 	sprintf(cmdbuf, "echo %s", name);
801 	if ((pid = vfork()) == 0) {
802 		Shell = value(SHELL);
803 		if (Shell == NOSTR)
804 			Shell = _PATH_BSHELL;
805 		close(pivec[0]);
806 		close(1);
807 		dup(pivec[1]);
808 		close(pivec[1]);
809 		close(2);
810 		shell_uid();
811 		execl(Shell, Shell, "-c", cmdbuf, 0);
812 		_exit(1);
813 	}
814 	if (pid == -1) {
815 		perror("fork");
816 		close(pivec[0]);
817 		close(pivec[1]);
818 		return(NOSTR);
819 	}
820 	close(pivec[1]);
821 	l = read(pivec[0], xname, BUFSIZ);
822 	close(pivec[0]);
823 	while (wait(&s) != pid);
824 		;
825 	s &= 0377;
826 	if (s != 0 && s != SIGPIPE) {
827 		fprintf(stderr, "\"Echo\" failed\n");
828 		return(NOSTR);
829 	}
830 	if (l < 0) {
831 		perror("read");
832 		return(NOSTR);
833 	}
834 	if (l == 0) {
835 		fprintf(stderr, "\"%s\": No match\n", name);
836 		return(NOSTR);
837 	}
838 	if (l == BUFSIZ) {
839 		fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
840 		return(NOSTR);
841 	}
842 	xname[l] = 0;
843 	for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
844 		;
845 	*++cp = '\0';
846 	return(xname);
847 }
848 
849 /*
850  * Are any of the characters in the two strings the same?
851  */
852 
853 anyof(s1, s2)
854 	register char *s1, *s2;
855 {
856 	register int c;
857 
858 	while (c = *s1++)
859 		if (any(c, s2))
860 			return(1);
861 	return(0);
862 }
863