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