usched: Allow process to change self cpu affinity
[dragonfly.git] / usr.bin / tip / cmds.c
blob672ec702c4ddcad5fbd33447010031093dcb2334
1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#)cmds.c 8.1 (Berkeley) 6/6/93
30 * $FreeBSD: src/usr.bin/tip/tip/cmds.c,v 1.11.2.2 2000/07/01 12:24:23 ps Exp $
33 #include "tip.h"
34 #include "pathnames.h"
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <err.h>
39 #include <libutil.h>
40 #include <stdio.h>
41 #include <unistd.h>
44 * tip
46 * miscellaneous commands
49 int quant[] = { 60, 60, 24 };
51 char null = '\0';
52 char *sep[] = { "second", "minute", "hour" };
53 static char *argv[10]; /* argument vector for take and put */
55 static void stopsnd(int); /* SIGINT handler during file transfers */
56 static void intcopy(int); /* interrupt routine for file transfers */
58 static int anyof(char *, char *);
59 static void tandem(char *);
60 static void prtime(char *, time_t);
61 static int args(char *, char **, int);
62 static void execute(char *);
63 static void send(char);
64 static void transmit(FILE *, char *, char *);
65 static void transfer(char *, int, char *);
66 static void xfer(char *, int, char *);
68 static void
69 usedefchars(void)
71 int cnt;
72 struct termios ttermios;
73 ttermios = ctermios;
74 for (cnt = 0; cnt < NCCS; cnt++)
75 ttermios.c_cc [cnt] = otermios.c_cc [cnt];
76 tcsetattr (0, TCSANOW, &ttermios);
79 static void
80 usetchars(void)
82 tcsetattr (0, TCSANOW, &ctermios);
85 static void
86 flush_remote(void)
88 int cmd = 0;
89 ioctl (FD, TIOCFLUSH, &cmd);
93 * FTP - remote ==> local
94 * get a file from the remote host
96 void
97 getfl(int c)
99 char buf[256], *cp;
101 putchar(c);
103 * get the UNIX receiving file's name
105 if (prompt("Local file name? ", copyname, sizeof(copyname)))
106 return;
107 cp = expand(copyname);
108 if ((sfd = creat(cp, 0666)) < 0) {
109 printf("\r\n%s: cannot creat\r\n", copyname);
110 return;
114 * collect parameters
116 if (prompt("List command for remote system? ", buf, sizeof(buf))) {
117 unlink(copyname);
118 return;
120 transfer(buf, sfd, value(EOFREAD));
124 * Cu-like take command
126 void
127 cu_take(int c)
129 int fd, argc;
130 char line[BUFSIZ], *cp;
132 if (prompt("[take] ", copyname, sizeof(copyname)))
133 return;
134 if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || argc > 2) {
135 printf("usage: <take> from [to]\r\n");
136 return;
138 if (argc == 1)
139 argv[1] = argv[0];
140 cp = expand(argv[1]);
141 if ((fd = creat(cp, 0666)) < 0) {
142 printf("\r\n%s: cannot create\r\n", argv[1]);
143 return;
145 (void)snprintf(line, sizeof(line), "cat %s ; echo \"\" ; echo ___tip_end_of_file_marker___", argv[0]);
146 xfer(line, fd, "\n___tip_end_of_file_marker___\n");
149 static jmp_buf intbuf;
151 static void
152 xfer(char *buf, int fd, char *eofchars)
154 int ct;
155 char c, *match;
156 int cnt, eof, v;
157 time_t start;
158 sig_t f;
159 char r;
160 FILE *ff;
162 v = boolean(value(VERBOSE));
164 if ((ff = fdopen (fd, "w")) == NULL) {
165 warn("file open");
166 return;
168 if ((cnt = number(value(FRAMESIZE))) != BUFSIZ)
169 if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) {
170 warn("file allocation");
171 (void)fclose(ff);
172 return;
175 xpwrite(FD, buf, size(buf));
176 quit = 0;
177 kill(pid, SIGIOT);
178 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
181 * finish command
183 r = '\r';
184 xpwrite(FD, &r, 1);
186 read(FD, &c, 1);
187 while ((c&0177) != '\n');
189 usedefchars ();
191 (void) setjmp(intbuf);
192 f = signal(SIGINT, intcopy);
193 start = time(0);
194 match = eofchars;
195 for (ct = 0; !quit;) {
196 eof = read(FD, &c, 1) <= 0;
197 c &= 0177;
198 if (quit)
199 continue;
200 if (eof)
201 break;
202 if (c == 0)
203 continue; /* ignore nulls */
204 if (c == '\r')
205 continue;
206 if (c != *match && match > eofchars) {
207 char *p = eofchars;
208 while (p < match) {
209 if (*p == '\n'&& v)
210 (void)printf("\r%d", ++ct);
211 fputc(*p++, ff);
213 match = eofchars;
215 if (c == *match) {
216 if (*++match == '\0')
217 break;
218 } else {
219 if (c == '\n' && v)
220 (void)printf("\r%d", ++ct);
221 fputc(c, ff);
224 if (v)
225 prtime(" lines transferred in ", time(0)-start);
226 usetchars ();
227 write(fildes[1], (char *)&ccc, 1);
228 signal(SIGINT, f);
229 (void)fclose(ff);
233 * Bulk transfer routine --
234 * used by getfl(), cu_take(), and pipefile()
236 static void
237 transfer(char *buf, int fd, char *eofchars)
239 int ct;
240 char c;
241 int cnt, eof, v;
242 time_t start;
243 sig_t f;
244 char r;
245 FILE *ff;
247 v = boolean(value(VERBOSE));
249 if ((ff = fdopen (fd, "w")) == NULL) {
250 warn("file open");
251 return;
253 if ((cnt = number(value(FRAMESIZE))) != BUFSIZ)
254 if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) {
255 warn("file allocation");
256 (void)fclose(ff);
257 return;
260 xpwrite(FD, buf, size(buf));
261 quit = 0;
262 kill(pid, SIGIOT);
263 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
266 * finish command
268 r = '\r';
269 xpwrite(FD, &r, 1);
271 read(FD, &c, 1);
272 while ((c&0177) != '\n');
273 usedefchars ();
274 (void) setjmp(intbuf);
275 f = signal(SIGINT, intcopy);
276 start = time(0);
277 for (ct = 0; !quit;) {
278 eof = read(FD, &c, 1) <= 0;
279 c &= 0177;
280 if (quit)
281 continue;
282 if (eof || any(c, eofchars))
283 break;
284 if (c == 0)
285 continue; /* ignore nulls */
286 if (c == '\r')
287 continue;
288 if (c == '\n' && v)
289 printf("\r%d", ++ct);
290 fputc(c, ff);
292 if (v)
293 prtime(" lines transferred in ", time(0)-start);
294 usetchars ();
295 write(fildes[1], (char *)&ccc, 1);
296 signal(SIGINT, f);
297 (void)fclose(ff);
301 * FTP - remote ==> local process
302 * send remote input to local process via pipe
304 void
305 pipefile(int c)
307 int cpid, pdes[2];
308 char buf[256];
309 int status, p;
311 if (prompt("Local command? ", buf, sizeof(buf)))
312 return;
314 if (pipe(pdes)) {
315 printf("can't establish pipe\r\n");
316 return;
319 if ((cpid = fork()) < 0) {
320 printf("can't fork!\r\n");
321 return;
322 } else if (cpid) {
323 if (prompt("List command for remote system? ", buf, sizeof(buf))) {
324 close(pdes[0]), close(pdes[1]);
325 kill (cpid, SIGKILL);
326 } else {
327 close(pdes[0]);
328 signal(SIGPIPE, intcopy);
329 transfer(buf, pdes[1], value(EOFREAD));
330 signal(SIGPIPE, SIG_DFL);
331 while ((p = wait(&status)) > 0 && p != cpid)
334 } else {
335 int f;
337 dup2(pdes[0], 0);
338 close(pdes[0]);
339 for (f = 3; f < 20; f++)
340 close(f);
341 execute(buf);
342 printf("can't execl!\r\n");
343 exit(0);
348 * Interrupt service routine for FTP
350 void
351 stopsnd(int __dummy)
354 stop = 1;
355 signal(SIGINT, SIG_IGN);
359 * FTP - local ==> remote
360 * send local file to remote host
361 * terminate transmission with pseudo EOF sequence
363 void
364 sendfile(int c)
366 FILE *fd;
367 char *fnamex;
369 putchar(c);
371 * get file name
373 if (prompt("Local file name? ", fname, sizeof(fname)))
374 return;
377 * look up file
379 fnamex = expand(fname);
380 if ((fd = fopen(fnamex, "r")) == NULL) {
381 printf("%s: cannot open\r\n", fname);
382 return;
384 transmit(fd, value(EOFWRITE), NULL);
385 if (!boolean(value(ECHOCHECK))) {
386 flush_remote ();
391 * Bulk transfer routine to remote host --
392 * used by sendfile() and cu_put()
394 static void
395 transmit(FILE *fd, char *eofchars, char *command)
397 char *pc, lastc;
398 int c, ccount, lcount;
399 time_t start_t, stop_t;
400 sig_t f;
402 kill(pid, SIGIOT); /* put TIPOUT into a wait state */
403 stop = 0;
404 f = signal(SIGINT, stopsnd);
405 usedefchars ();
406 read(repdes[0], (char *)&ccc, 1);
407 if (command != NULL) {
408 for (pc = command; *pc; pc++)
409 send(*pc);
410 if (boolean(value(ECHOCHECK)))
411 read(FD, (char *)&c, 1); /* trailing \n */
412 else {
413 flush_remote ();
414 sleep(5); /* wait for remote stty to take effect */
417 lcount = 0;
418 lastc = '\0';
419 start_t = time(0);
420 while (1) {
421 ccount = 0;
422 do {
423 c = getc(fd);
424 if (stop)
425 goto out;
426 if (c == EOF)
427 goto out;
428 if (c == 0177 && !boolean(value(RAWFTP)))
429 continue;
430 lastc = c;
431 if (c < 040) {
432 if (c == '\n') {
433 if (!boolean(value(RAWFTP)))
434 c = '\r';
436 else if (c == '\t') {
437 if (!boolean(value(RAWFTP))) {
438 if (boolean(value(TABEXPAND))) {
439 send(' ');
440 while ((++ccount % 8) != 0)
441 send(' ');
442 continue;
445 } else
446 if (!boolean(value(RAWFTP)))
447 continue;
449 send(c);
450 } while (c != '\r' && !boolean(value(RAWFTP)));
451 if (boolean(value(VERBOSE)))
452 printf("\r%d", ++lcount);
453 if (boolean(value(ECHOCHECK))) {
454 timedout = 0;
455 alarm(number(value(ETIMEOUT)));
456 do { /* wait for prompt */
457 read(FD, (char *)&c, 1);
458 if (timedout || stop) {
459 if (timedout)
460 printf("\r\ntimed out at eol\r\n");
461 alarm(0);
462 goto out;
464 } while ((c&0177) != character(value(PROMPT)));
465 alarm(0);
468 out:
469 if (lastc != '\n' && !boolean(value(RAWFTP)))
470 send('\r');
471 for (pc = eofchars; pc && *pc; pc++)
472 send(*pc);
473 stop_t = time(0);
474 fclose(fd);
475 signal(SIGINT, f);
476 if (boolean(value(VERBOSE))) {
477 if (boolean(value(RAWFTP)))
478 prtime(" chars transferred in ", stop_t-start_t);
479 else
480 prtime(" lines transferred in ", stop_t-start_t);
482 write(fildes[1], (char *)&ccc, 1);
483 usetchars ();
487 * Cu-like put command
489 void
490 cu_put(int c)
492 FILE *fd;
493 char line[BUFSIZ];
494 int argc;
495 char *copynamex;
497 if (prompt("[put] ", copyname, sizeof(copyname)))
498 return;
499 if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || argc > 2) {
500 printf("usage: <put> from [to]\r\n");
501 return;
503 if (argc == 1)
504 argv[1] = argv[0];
505 copynamex = expand(argv[0]);
506 if ((fd = fopen(copynamex, "r")) == NULL) {
507 printf("%s: cannot open\r\n", copynamex);
508 return;
510 if (boolean(value(ECHOCHECK)))
511 snprintf(line, sizeof(line), "cat>%s\r", argv[1]);
512 else
513 snprintf(line, sizeof(line), "stty -echo;cat>%s;stty echo\r", argv[1]);
514 transmit(fd, "\04", line);
518 static int
519 nap(int msec)
521 if (usleep(msec*1000) != 0) {
522 fprintf ( stderr, "warning: ldelay or cdelay interrupted, "
523 "delay time cut short: %s\n",
524 strerror(errno) );
527 return 0;
532 * FTP - send single character
533 * wait for echo & handle timeout
535 static void
536 send(char c)
538 char cc;
539 int retry = 0;
541 cc = c;
542 xpwrite(FD, &cc, 1);
543 if (number(value(CDELAY)) > 0 && c != '\r')
544 nap(number(value(CDELAY)));
545 if (!boolean(value(ECHOCHECK))) {
546 if (number(value(LDELAY)) > 0 && c == '\r')
547 nap(number(value(LDELAY)));
548 return;
550 tryagain:
551 timedout = 0;
552 alarm(number(value(ETIMEOUT)));
553 read(FD, &cc, 1);
554 alarm(0);
555 if (timedout) {
556 printf("\r\ntimeout error (%s)\r\n", ctrl(c));
557 if (retry++ > 3)
558 return;
559 xpwrite(FD, &null, 1); /* poke it */
560 goto tryagain;
564 void
565 timeoutfunc(int __dummy)
567 signal(SIGALRM, timeoutfunc);
568 timedout = 1;
572 * Stolen from consh() -- puts a remote file on the output of a local command.
573 * Identical to consh() except for where stdout goes.
575 void
576 pipeout(int c)
578 char buf[256];
579 int cpid, status, p;
580 time_t start;
582 putchar(c);
583 if (prompt("Local command? ", buf, sizeof(buf)))
584 return;
585 kill(pid, SIGIOT); /* put TIPOUT into a wait state */
586 signal(SIGINT, SIG_IGN);
587 signal(SIGQUIT, SIG_IGN);
588 usedefchars ();
589 read(repdes[0], (char *)&ccc, 1);
591 * Set up file descriptors in the child and
592 * let it go...
594 if ((cpid = fork()) < 0)
595 printf("can't fork!\r\n");
596 else if (cpid) {
597 start = time(0);
598 while ((p = wait(&status)) > 0 && p != cpid)
600 } else {
601 int i;
603 dup2(FD, 1);
604 for (i = 3; i < 20; i++)
605 close(i);
606 signal(SIGINT, SIG_DFL);
607 signal(SIGQUIT, SIG_DFL);
608 execute(buf);
609 printf("can't find `%s'\r\n", buf);
610 exit(0);
612 if (boolean(value(VERBOSE)))
613 prtime("away for ", time(0)-start);
614 write(fildes[1], (char *)&ccc, 1);
615 usetchars ();
616 signal(SIGINT, SIG_DFL);
617 signal(SIGQUIT, SIG_DFL);
621 tiplink (char *cmd, unsigned int flags)
623 int cpid, status, p;
624 time_t start;
626 if (flags & TL_SIGNAL_TIPOUT) {
627 kill(pid, SIGIOT); /* put TIPOUT into a wait state */
628 signal(SIGINT, SIG_IGN);
629 signal(SIGQUIT, SIG_IGN);
630 usedefchars ();
631 read(repdes[0], (char *)&ccc, 1);
635 * Set up file descriptors in the child and
636 * let it go...
638 if ((cpid = fork()) < 0)
639 printf("can't fork!\r\n");
640 else if (cpid) {
641 start = time(0);
642 while ((p = wait(&status)) > 0 && p != cpid)
644 } else {
645 int fd;
647 dup2(FD, 0);
648 dup2(3, 1);
649 for (fd = 3; fd < 20; fd++)
650 close (fd);
651 signal(SIGINT, SIG_DFL);
652 signal(SIGQUIT, SIG_DFL);
653 execute (cmd);
654 printf("can't find `%s'\r\n", cmd);
655 exit(0);
658 if (flags & TL_VERBOSE && boolean(value(VERBOSE)))
659 prtime("away for ", time(0)-start);
661 if (flags & TL_SIGNAL_TIPOUT) {
662 write(fildes[1], (char *)&ccc, 1);
663 usetchars ();
664 signal(SIGINT, SIG_DFL);
665 signal(SIGQUIT, SIG_DFL);
668 return 0;
672 * Fork a program with:
673 * 0 <-> remote tty in
674 * 1 <-> remote tty out
675 * 2 <-> local tty out
677 void
678 consh(int c)
680 char buf[256];
681 putchar(c);
682 if (prompt("Local command? ", buf, sizeof(buf)))
683 return;
684 tiplink (buf, TL_SIGNAL_TIPOUT | TL_VERBOSE);
688 * Escape to local shell
690 void
691 shell(int c)
693 int shpid, status;
694 char *cp;
696 printf("[sh]\r\n");
697 signal(SIGINT, SIG_IGN);
698 signal(SIGQUIT, SIG_IGN);
699 unraw();
700 if ((shpid = fork())) {
701 while (shpid != wait(&status));
702 raw();
703 printf("\r\n!\r\n");
704 signal(SIGINT, SIG_DFL);
705 signal(SIGQUIT, SIG_DFL);
706 return;
707 } else {
708 signal(SIGQUIT, SIG_DFL);
709 signal(SIGINT, SIG_DFL);
710 if ((cp = rindex(value(SHELL), '/')) == NULL)
711 cp = value(SHELL);
712 else
713 cp++;
714 shell_uid();
715 execl(value(SHELL), cp, NULL);
716 printf("\r\ncan't execl!\r\n");
717 exit(1);
722 * TIPIN portion of scripting
723 * initiate the conversation with TIPOUT
725 void
726 setscript(void)
728 char c;
730 * enable TIPOUT side for dialogue
732 kill(pid, SIGEMT);
733 if (boolean(value(SCRIPT)))
734 write(fildes[1], value(RECORD), size(value(RECORD)));
735 write(fildes[1], "\n", 1);
737 * wait for TIPOUT to finish
739 read(repdes[0], &c, 1);
740 if (c == 'n')
741 printf("can't create %s\r\n", value(RECORD));
745 * Change current working directory of
746 * local portion of tip
748 void
749 chdirectory(int c)
751 char dirname[PATH_MAX];
752 char *cp = dirname;
754 if (prompt("[cd] ", dirname, sizeof(dirname))) {
755 if (stoprompt)
756 return;
757 cp = value(HOME);
759 if (chdir(cp) < 0)
760 printf("%s: bad directory\r\n", cp);
761 printf("!\r\n");
764 void
765 tipabort(char *msg)
768 kill(pid, SIGTERM);
769 disconnect(msg);
770 if (msg != NULL)
771 printf("\r\n%s", msg);
772 printf("\r\n[EOT]\r\n");
773 daemon_uid();
774 (void)uu_unlock(uucplock);
775 unraw();
776 exit(0);
779 void
780 finish(int c)
782 char *abortmsg = NULL, *dismsg;
784 if (LO != NULL && tiplink (LO, TL_SIGNAL_TIPOUT) != 0) {
785 abortmsg = "logout failed";
788 if ((dismsg = value(DISCONNECT)) != NULL) {
789 write(FD, dismsg, strlen(dismsg));
790 sleep (2);
792 tipabort(abortmsg);
795 void
796 intcopy(int signo)
798 raw();
799 quit = 1;
800 longjmp(intbuf, 1);
803 static void
804 execute(char *s)
806 char *cp;
808 if ((cp = rindex(value(SHELL), '/')) == NULL)
809 cp = value(SHELL);
810 else
811 cp++;
812 shell_uid();
813 execl(value(SHELL), cp, "-c", s, NULL);
816 static int
817 args(char *buf, char **a, int num)
819 char *p = buf, *start;
820 char **parg = a;
821 int n = 0;
823 while (*p && n < num) {
824 while (*p && (*p == ' ' || *p == '\t'))
825 p++;
826 start = p;
827 if (*p)
828 *parg = p;
829 while (*p && (*p != ' ' && *p != '\t'))
830 p++;
831 if (p != start)
832 parg++, n++;
833 if (*p)
834 *p++ = '\0';
836 return(n);
839 static void
840 prtime(char *s, time_t a)
842 int i;
843 int nums[3];
845 for (i = 0; i < 3; i++) {
846 nums[i] = (int)(a % quant[i]);
847 a /= quant[i];
849 printf("%s", s);
850 while (--i >= 0)
851 if (nums[i] || (i == 0 && nums[1] == 0 && nums[2] == 0))
852 printf("%d %s%c ", nums[i], sep[i],
853 nums[i] == 1 ? '\0' : 's');
854 printf("\r\n!\r\n");
857 void
858 variable(int c)
860 char buf[256];
862 if (prompt("[set] ", buf, sizeof(buf)))
863 return;
864 vlex(buf);
865 if (vtable[BEAUTIFY].v_access&CHANGED) {
866 vtable[BEAUTIFY].v_access &= ~CHANGED;
867 kill(pid, SIGSYS);
869 if (vtable[SCRIPT].v_access&CHANGED) {
870 vtable[SCRIPT].v_access &= ~CHANGED;
871 setscript();
873 * So that "set record=blah script" doesn't
874 * cause two transactions to occur.
876 if (vtable[RECORD].v_access&CHANGED)
877 vtable[RECORD].v_access &= ~CHANGED;
879 if (vtable[RECORD].v_access&CHANGED) {
880 vtable[RECORD].v_access &= ~CHANGED;
881 if (boolean(value(SCRIPT)))
882 setscript();
884 if (vtable[TAND].v_access&CHANGED) {
885 vtable[TAND].v_access &= ~CHANGED;
886 if (boolean(value(TAND)))
887 tandem("on");
888 else
889 tandem("off");
891 if (vtable[LECHO].v_access&CHANGED) {
892 vtable[LECHO].v_access &= ~CHANGED;
893 HD = boolean(value(LECHO));
895 if (vtable[PARITY].v_access&CHANGED) {
896 vtable[PARITY].v_access &= ~CHANGED;
897 setparity(value(PARITY));
902 * Turn tandem mode on or off for remote tty.
904 static void
905 tandem(char *option)
907 struct termios ttermios;
908 tcgetattr (FD, &ttermios);
909 if (strcmp(option,"on") == 0) {
910 ttermios.c_iflag |= IXOFF;
911 ctermios.c_iflag |= IXOFF;
913 else {
914 ttermios.c_iflag &= ~IXOFF;
915 ctermios.c_iflag &= ~IXOFF;
917 tcsetattr (FD, TCSANOW, &ttermios);
918 tcsetattr (0, TCSANOW, &ctermios);
922 * Send a break.
924 void
925 genbrk(int c)
928 ioctl(FD, TIOCSBRK, NULL);
929 sleep(1);
930 ioctl(FD, TIOCCBRK, NULL);
934 * Suspend tip
936 void
937 suspend(int c)
940 unraw();
941 kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
942 raw();
946 * expand a file name if it includes shell meta characters
949 char *
950 expand(char *name)
952 static char xname[BUFSIZ];
953 char cmdbuf[BUFSIZ];
954 int pid, l;
955 char *cp, *Shell;
956 int s, pivec[2] /*, (*sigint)()*/;
958 if (!anyof(name, "~{[*?$`'\"\\"))
959 return(name);
960 /* sigint = signal(SIGINT, SIG_IGN); */
961 if (pipe(pivec) < 0) {
962 warn("pipe");
963 /* signal(SIGINT, sigint) */
964 return(name);
966 snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
967 if ((pid = vfork()) == 0) {
968 Shell = value(SHELL);
969 if (Shell == NULL)
970 Shell = _PATH_BSHELL;
971 close(pivec[0]);
972 close(1);
973 dup(pivec[1]);
974 close(pivec[1]);
975 close(2);
976 shell_uid();
977 execl(Shell, Shell, "-c", cmdbuf, NULL);
978 _exit(1);
980 if (pid == -1) {
981 warn("fork");
982 close(pivec[0]);
983 close(pivec[1]);
984 return(NULL);
986 close(pivec[1]);
987 l = read(pivec[0], xname, BUFSIZ);
988 close(pivec[0]);
989 while (wait(&s) != pid)
991 s &= 0377;
992 if (s != 0 && s != SIGPIPE) {
993 fprintf(stderr, "\"Echo\" failed\n");
994 return(NULL);
996 if (l < 0) {
997 warn("read");
998 return(NULL);
1000 if (l == 0) {
1001 fprintf(stderr, "\"%s\": No match\n", name);
1002 return(NULL);
1004 if (l == BUFSIZ) {
1005 fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
1006 return(NULL);
1008 xname[l] = 0;
1009 for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
1011 *++cp = '\0';
1012 return(xname);
1016 * Are any of the characters in the two strings the same?
1019 static int
1020 anyof(char *s1, char *s2)
1022 int c;
1024 while ((c = *s1++))
1025 if (any(c, s2))
1026 return(1);
1027 return(0);