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