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