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