Annotation of src/usr.bin/tip/cmds.c, Revision 1.11
1.11 ! millert 1: /* $OpenBSD: cmds.c,v 1.10 2001/07/12 05:17:23 deraadt 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.11 ! millert 41: static char rcsid[] = "$OpenBSD: cmds.c,v 1.10 2001/07/12 05:17:23 deraadt 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: {
136: register int ct;
137: char c, buffer[BUFSIZ];
1.7 deraadt 138: char *p = buffer;
1.1 deraadt 139: register int cnt, eof;
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: {
204: int cpid, pdes[2];
205: char buf[256];
206: int status, p;
207: extern int errno;
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 {
233: register int f;
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];
477: int cpid, status, p;
1.7 deraadt 478: time_t start = time(NULL);
1.1 deraadt 479:
480: putchar(c);
1.6 millert 481: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 482: return;
483: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
484: signal(SIGINT, SIG_IGN);
485: signal(SIGQUIT, SIG_IGN);
1.2 deraadt 486: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 487: read(repdes[0], (char *)&ccc, 1);
488: /*
489: * Set up file descriptors in the child and
490: * let it go...
491: */
492: if ((cpid = fork()) < 0)
493: printf("can't fork!\r\n");
494: else if (cpid) {
1.7 deraadt 495: start = time(NULL);
1.1 deraadt 496: while ((p = wait(&status)) > 0 && p != cpid)
497: ;
498: } else {
499: register int i;
500:
501: dup2(FD, 1);
502: for (i = 3; i < 20; i++)
503: close(i);
504: signal(SIGINT, SIG_DFL);
505: signal(SIGQUIT, SIG_DFL);
506: execute(buf);
507: printf("can't find `%s'\r\n", buf);
508: exit(0);
509: }
510: if (boolean(value(VERBOSE)))
511: prtime("away for ", time(0)-start);
512: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 513: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 514: signal(SIGINT, SIG_DFL);
515: signal(SIGQUIT, SIG_DFL);
516: }
517:
518: #ifdef CONNECT
519: /*
520: * Fork a program with:
521: * 0 <-> remote tty in
522: * 1 <-> remote tty out
523: * 2 <-> local tty out
524: */
1.7 deraadt 525: void
1.1 deraadt 526: consh(c)
527: {
528: char buf[256];
529: int cpid, status, p;
1.7 deraadt 530: time_t start = time(NULL);
1.1 deraadt 531:
532: putchar(c);
1.6 millert 533: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 534: return;
535: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
536: signal(SIGINT, SIG_IGN);
537: signal(SIGQUIT, SIG_IGN);
1.2 deraadt 538: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 539: read(repdes[0], (char *)&ccc, 1);
540: /*
541: * Set up file descriptors in the child and
542: * let it go...
543: */
544: if ((cpid = fork()) < 0)
545: printf("can't fork!\r\n");
546: else if (cpid) {
547: start = time(0);
548: while ((p = wait(&status)) > 0 && p != cpid)
549: ;
550: } else {
551: register int i;
552:
553: dup2(FD, 0);
554: dup2(3, 1);
555: for (i = 3; i < 20; i++)
556: close(i);
557: signal(SIGINT, SIG_DFL);
558: signal(SIGQUIT, SIG_DFL);
559: execute(buf);
560: printf("can't find `%s'\r\n", buf);
561: exit(0);
562: }
563: if (boolean(value(VERBOSE)))
564: prtime("away for ", time(0)-start);
565: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 566: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 567: signal(SIGINT, SIG_DFL);
568: signal(SIGQUIT, SIG_DFL);
569: }
570: #endif
571:
572: /*
573: * Escape to local shell
574: */
1.7 deraadt 575: void
1.1 deraadt 576: shell()
577: {
578: int shpid, status;
579: char *cp;
580:
581: printf("[sh]\r\n");
582: signal(SIGINT, SIG_IGN);
583: signal(SIGQUIT, SIG_IGN);
584: unraw();
1.7 deraadt 585: if ((shpid = fork())) {
1.1 deraadt 586: while (shpid != wait(&status));
587: raw();
588: printf("\r\n!\r\n");
589: signal(SIGINT, SIG_DFL);
590: signal(SIGQUIT, SIG_DFL);
591: return;
592: } else {
593: signal(SIGQUIT, SIG_DFL);
594: signal(SIGINT, SIG_DFL);
1.4 millert 595: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 596: cp = value(SHELL);
597: else
598: cp++;
599: shell_uid();
1.9 deraadt 600: execl(value(SHELL), cp, (char *)NULL);
1.1 deraadt 601: printf("\r\ncan't execl!\r\n");
602: exit(1);
603: }
604: }
605:
606: /*
607: * TIPIN portion of scripting
608: * initiate the conversation with TIPOUT
609: */
1.7 deraadt 610: void
1.1 deraadt 611: setscript()
612: {
613: char c;
614: /*
615: * enable TIPOUT side for dialogue
616: */
617: kill(pid, SIGEMT);
618: if (boolean(value(SCRIPT)))
619: write(fildes[1], value(RECORD), size(value(RECORD)));
620: write(fildes[1], "\n", 1);
621: /*
622: * wait for TIPOUT to finish
623: */
624: read(repdes[0], &c, 1);
625: if (c == 'n')
626: printf("can't create %s\r\n", value(RECORD));
627: }
628:
629: /*
630: * Change current working directory of
631: * local portion of tip
632: */
1.7 deraadt 633: void
1.1 deraadt 634: chdirectory()
635: {
1.6 millert 636: char dirname[PATH_MAX];
1.1 deraadt 637: register char *cp = dirname;
638:
1.6 millert 639: if (prompt("[cd] ", dirname, sizeof(dirname))) {
1.1 deraadt 640: if (stoprompt)
641: return;
642: cp = value(HOME);
643: }
644: if (chdir(cp) < 0)
645: printf("%s: bad directory\r\n", cp);
646: printf("!\r\n");
647: }
648:
1.7 deraadt 649: void
1.1 deraadt 650: tipabort(msg)
651: char *msg;
652: {
653:
654: kill(pid, SIGTERM);
655: disconnect(msg);
656: if (msg != NOSTR)
657: printf("\r\n%s", msg);
658: printf("\r\n[EOT]\r\n");
659: daemon_uid();
660: (void)uu_unlock(uucplock);
661: unraw();
662: exit(0);
663: }
664:
1.7 deraadt 665: void
1.1 deraadt 666: finish()
667: {
668: char *dismsg;
669:
670: if ((dismsg = value(DISCONNECT)) != NOSTR) {
671: write(FD, dismsg, strlen(dismsg));
672: sleep(5);
673: }
674: tipabort(NOSTR);
675: }
676:
677: void
678: intcopy()
679: {
680: raw();
681: quit = 1;
682: longjmp(intbuf, 1);
683: }
684:
1.7 deraadt 685: void
1.1 deraadt 686: execute(s)
687: char *s;
688: {
689: register char *cp;
690:
1.4 millert 691: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 692: cp = value(SHELL);
693: else
694: cp++;
695: shell_uid();
1.9 deraadt 696: execl(value(SHELL), cp, "-c", s, (char *)NULL);
1.1 deraadt 697: }
698:
1.7 deraadt 699: int
700: args(buf, a, num)
1.1 deraadt 701: char *buf, *a[];
1.7 deraadt 702: int num;
1.1 deraadt 703: {
704: register char *p = buf, *start;
705: register char **parg = a;
706: register int n = 0;
707:
708: do {
709: while (*p && (*p == ' ' || *p == '\t'))
710: p++;
711: start = p;
712: if (*p)
713: *parg = p;
714: while (*p && (*p != ' ' && *p != '\t'))
715: p++;
716: if (p != start)
717: parg++, n++;
718: if (*p)
719: *p++ = '\0';
1.7 deraadt 720: } while (*p && n < num);
1.1 deraadt 721:
722: return(n);
723: }
724:
1.7 deraadt 725: void
1.1 deraadt 726: prtime(s, a)
727: char *s;
728: time_t a;
729: {
1.10 deraadt 730: register int i;
1.1 deraadt 731: int nums[3];
732:
733: for (i = 0; i < 3; i++) {
734: nums[i] = (int)(a % quant[i]);
735: a /= quant[i];
736: }
737: printf("%s", s);
738: while (--i >= 0)
739: if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
740: printf("%d %s%c ", nums[i], sep[i],
741: nums[i] == 1 ? '\0' : 's');
742: printf("\r\n!\r\n");
743: }
744:
1.7 deraadt 745: void
1.1 deraadt 746: variable()
747: {
748: char buf[256];
749:
1.6 millert 750: if (prompt("[set] ", buf, sizeof(buf)))
1.1 deraadt 751: return;
752: vlex(buf);
753: if (vtable[BEAUTIFY].v_access&CHANGED) {
754: vtable[BEAUTIFY].v_access &= ~CHANGED;
755: kill(pid, SIGSYS);
756: }
757: if (vtable[SCRIPT].v_access&CHANGED) {
758: vtable[SCRIPT].v_access &= ~CHANGED;
759: setscript();
760: /*
761: * So that "set record=blah script" doesn't
762: * cause two transactions to occur.
763: */
764: if (vtable[RECORD].v_access&CHANGED)
765: vtable[RECORD].v_access &= ~CHANGED;
766: }
767: if (vtable[RECORD].v_access&CHANGED) {
768: vtable[RECORD].v_access &= ~CHANGED;
769: if (boolean(value(SCRIPT)))
770: setscript();
771: }
772: if (vtable[TAND].v_access&CHANGED) {
773: vtable[TAND].v_access &= ~CHANGED;
774: if (boolean(value(TAND)))
775: tandem("on");
776: else
777: tandem("off");
778: }
779: if (vtable[LECHO].v_access&CHANGED) {
780: vtable[LECHO].v_access &= ~CHANGED;
781: HD = boolean(value(LECHO));
782: }
783: if (vtable[PARITY].v_access&CHANGED) {
784: vtable[PARITY].v_access &= ~CHANGED;
1.7 deraadt 785: setparity(NOSTR);
1.1 deraadt 786: }
1.11 ! millert 787: }
! 788:
! 789: void
! 790: listvariables()
! 791: {
! 792: value_t *p;
! 793: char buf[BUFSIZ];
! 794:
! 795: puts("v\r");
! 796: for (p = vtable; p->v_name; p++) {
! 797: fputs(p->v_name, stdout);
! 798: switch (p->v_type&TMASK) {
! 799: case STRING:
! 800: if (p->v_value) {
! 801: strnvis(buf, p->v_value, sizeof(buf),
! 802: VIS_WHITE|VIS_OCTAL);
! 803: printf(" %s", buf);
! 804: }
! 805: putchar('\r');
! 806: putchar('\n');
! 807: break;
! 808: case NUMBER:
! 809: printf(" %d\r\n", number(p->v_value));
! 810: break;
! 811: case BOOL:
! 812: printf(" %s\r\n",
! 813: boolean(p->v_value) == '!' ? "false" : "true");
! 814: break;
! 815: case CHAR:
! 816: vis(buf, character(p->v_value), VIS_WHITE|VIS_OCTAL, 0);
! 817: printf(" %s\r\n", buf);
! 818: break;
! 819: }
! 820: }
1.1 deraadt 821: }
822:
823: /*
824: * Turn tandem mode on or off for remote tty.
825: */
1.7 deraadt 826: void
1.1 deraadt 827: tandem(option)
828: char *option;
829: {
1.2 deraadt 830: struct termios rmtty;
1.1 deraadt 831:
1.2 deraadt 832: tcgetattr(FD, &rmtty);
833: if (strcmp(option, "on") == 0) {
834: rmtty.c_iflag |= IXOFF;
835: term.c_iflag |= IXOFF;
1.1 deraadt 836: } else {
1.2 deraadt 837: rmtty.c_iflag &= ~IXOFF;
838: term.c_iflag &= ~IXOFF;
1.1 deraadt 839: }
1.2 deraadt 840: tcsetattr(FD, TCSADRAIN, &rmtty);
841: tcsetattr(0, TCSADRAIN, &term);
1.1 deraadt 842: }
843:
844: /*
845: * Send a break.
846: */
1.7 deraadt 847: void
1.1 deraadt 848: genbrk()
849: {
850:
851: ioctl(FD, TIOCSBRK, NULL);
852: sleep(1);
853: ioctl(FD, TIOCCBRK, NULL);
854: }
855:
856: /*
857: * Suspend tip
858: */
1.7 deraadt 859: void
1.1 deraadt 860: suspend(c)
861: char c;
862: {
863:
864: unraw();
865: kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
866: raw();
867: }
868:
869: /*
870: * expand a file name if it includes shell meta characters
871: */
872:
873: char *
874: expand(name)
875: char name[];
876: {
877: static char xname[BUFSIZ];
878: char cmdbuf[BUFSIZ];
1.7 deraadt 879: register int pid, l;
1.1 deraadt 880: register char *cp, *Shell;
1.7 deraadt 881: int s, pivec[2];
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)
945: register char *s1, *s2;
946: {
947: register int c;
948:
1.7 deraadt 949: while ((c = *s1++))
1.1 deraadt 950: if (any(c, s2))
951: return(1);
952: return(0);
953: }