Annotation of src/usr.bin/tip/cmds.c, Revision 1.10
1.10 ! deraadt 1: /* $OpenBSD: cmds.c,v 1.9 2001/07/09 07:04:55 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.10 ! deraadt 41: static char rcsid[] = "$OpenBSD: cmds.c,v 1.9 2001/07/09 07:04:55 deraadt 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:
1.8 deraadt 142: parwrite(FD, buf, size(buf));
1.1 deraadt 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';
1.8 deraadt 151: parwrite(FD, &r, 1);
1.1 deraadt 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);
1.10 ! deraadt 377: if (boolean(value(VERBOSE))) {
1.1 deraadt 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);
1.10 ! deraadt 382: }
1.1 deraadt 383: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 384: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 385: }
386:
387: /*
388: * Cu-like put command
389: */
1.7 deraadt 390: void
1.1 deraadt 391: cu_put(cc)
392: char cc;
393: {
394: FILE *fd;
395: char line[BUFSIZ];
396: int argc;
397: char *expand();
398: char *copynamex;
399:
1.6 millert 400: if (prompt("[put] ", copyname, sizeof(copyname)))
1.1 deraadt 401: return;
1.7 deraadt 402: if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 ||
403: argc > 2) {
1.1 deraadt 404: printf("usage: <put> from [to]\r\n");
405: return;
406: }
407: if (argc == 1)
408: argv[1] = argv[0];
409: copynamex = expand(argv[0]);
410: if ((fd = fopen(copynamex, "r")) == NULL) {
411: printf("%s: cannot open\r\n", copynamex);
412: return;
413: }
414: if (boolean(value(ECHOCHECK)))
1.5 millert 415: (void)snprintf(line, sizeof(line), "cat>%s\r", argv[1]);
1.1 deraadt 416: else
1.5 millert 417: (void)snprintf(line, sizeof(line),
418: "stty -echo;cat>%s;stty echo\r", argv[1]);
1.1 deraadt 419: transmit(fd, "\04", line);
420: }
421:
422: /*
423: * FTP - send single character
424: * wait for echo & handle timeout
425: */
1.7 deraadt 426: void
1.1 deraadt 427: send(c)
1.7 deraadt 428: int c;
1.1 deraadt 429: {
430: char cc;
431: int retry = 0;
432:
433: cc = c;
1.8 deraadt 434: parwrite(FD, &cc, 1);
1.1 deraadt 435: #ifdef notdef
436: if (number(value(CDELAY)) > 0 && c != '\r')
437: nap(number(value(CDELAY)));
438: #endif
439: if (!boolean(value(ECHOCHECK))) {
440: #ifdef notdef
441: if (number(value(LDELAY)) > 0 && c == '\r')
442: nap(number(value(LDELAY)));
443: #endif
444: return;
445: }
446: tryagain:
447: timedout = 0;
448: alarm((long)value(ETIMEOUT));
449: read(FD, &cc, 1);
450: alarm(0);
451: if (timedout) {
452: printf("\r\ntimeout error (%s)\r\n", ctrl(c));
453: if (retry++ > 3)
454: return;
1.8 deraadt 455: parwrite(FD, &null, 1); /* poke it */
1.1 deraadt 456: goto tryagain;
457: }
458: }
459:
460: void
461: timeout()
462: {
463: signal(SIGALRM, timeout);
464: timedout = 1;
465: }
466:
467: /*
468: * Stolen from consh() -- puts a remote file on the output of a local command.
469: * Identical to consh() except for where stdout goes.
470: */
1.7 deraadt 471: void
1.1 deraadt 472: pipeout(c)
473: {
474: char buf[256];
475: int cpid, status, p;
1.7 deraadt 476: time_t start = time(NULL);
1.1 deraadt 477:
478: putchar(c);
1.6 millert 479: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 480: return;
481: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
482: signal(SIGINT, SIG_IGN);
483: signal(SIGQUIT, SIG_IGN);
1.2 deraadt 484: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 485: read(repdes[0], (char *)&ccc, 1);
486: /*
487: * Set up file descriptors in the child and
488: * let it go...
489: */
490: if ((cpid = fork()) < 0)
491: printf("can't fork!\r\n");
492: else if (cpid) {
1.7 deraadt 493: start = time(NULL);
1.1 deraadt 494: while ((p = wait(&status)) > 0 && p != cpid)
495: ;
496: } else {
497: register int i;
498:
499: dup2(FD, 1);
500: for (i = 3; i < 20; i++)
501: close(i);
502: signal(SIGINT, SIG_DFL);
503: signal(SIGQUIT, SIG_DFL);
504: execute(buf);
505: printf("can't find `%s'\r\n", buf);
506: exit(0);
507: }
508: if (boolean(value(VERBOSE)))
509: prtime("away for ", time(0)-start);
510: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 511: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 512: signal(SIGINT, SIG_DFL);
513: signal(SIGQUIT, SIG_DFL);
514: }
515:
516: #ifdef CONNECT
517: /*
518: * Fork a program with:
519: * 0 <-> remote tty in
520: * 1 <-> remote tty out
521: * 2 <-> local tty out
522: */
1.7 deraadt 523: void
1.1 deraadt 524: consh(c)
525: {
526: char buf[256];
527: int cpid, status, p;
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 {
549: register int i;
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: {
576: int shpid, status;
577: char *cp;
578:
579: printf("[sh]\r\n");
580: signal(SIGINT, SIG_IGN);
581: signal(SIGQUIT, SIG_IGN);
582: unraw();
1.7 deraadt 583: if ((shpid = fork())) {
1.1 deraadt 584: while (shpid != wait(&status));
585: raw();
586: printf("\r\n!\r\n");
587: signal(SIGINT, SIG_DFL);
588: signal(SIGQUIT, SIG_DFL);
589: return;
590: } else {
591: signal(SIGQUIT, SIG_DFL);
592: signal(SIGINT, SIG_DFL);
1.4 millert 593: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 594: cp = value(SHELL);
595: else
596: cp++;
597: shell_uid();
1.9 deraadt 598: execl(value(SHELL), cp, (char *)NULL);
1.1 deraadt 599: printf("\r\ncan't execl!\r\n");
600: exit(1);
601: }
602: }
603:
604: /*
605: * TIPIN portion of scripting
606: * initiate the conversation with TIPOUT
607: */
1.7 deraadt 608: void
1.1 deraadt 609: setscript()
610: {
611: char c;
612: /*
613: * enable TIPOUT side for dialogue
614: */
615: kill(pid, SIGEMT);
616: if (boolean(value(SCRIPT)))
617: write(fildes[1], value(RECORD), size(value(RECORD)));
618: write(fildes[1], "\n", 1);
619: /*
620: * wait for TIPOUT to finish
621: */
622: read(repdes[0], &c, 1);
623: if (c == 'n')
624: printf("can't create %s\r\n", value(RECORD));
625: }
626:
627: /*
628: * Change current working directory of
629: * local portion of tip
630: */
1.7 deraadt 631: void
1.1 deraadt 632: chdirectory()
633: {
1.6 millert 634: char dirname[PATH_MAX];
1.1 deraadt 635: register char *cp = dirname;
636:
1.6 millert 637: if (prompt("[cd] ", dirname, sizeof(dirname))) {
1.1 deraadt 638: if (stoprompt)
639: return;
640: cp = value(HOME);
641: }
642: if (chdir(cp) < 0)
643: printf("%s: bad directory\r\n", cp);
644: printf("!\r\n");
645: }
646:
1.7 deraadt 647: void
1.1 deraadt 648: tipabort(msg)
649: char *msg;
650: {
651:
652: kill(pid, SIGTERM);
653: disconnect(msg);
654: if (msg != NOSTR)
655: printf("\r\n%s", msg);
656: printf("\r\n[EOT]\r\n");
657: daemon_uid();
658: (void)uu_unlock(uucplock);
659: unraw();
660: exit(0);
661: }
662:
1.7 deraadt 663: void
1.1 deraadt 664: finish()
665: {
666: char *dismsg;
667:
668: if ((dismsg = value(DISCONNECT)) != NOSTR) {
669: write(FD, dismsg, strlen(dismsg));
670: sleep(5);
671: }
672: tipabort(NOSTR);
673: }
674:
675: void
676: intcopy()
677: {
678: raw();
679: quit = 1;
680: longjmp(intbuf, 1);
681: }
682:
1.7 deraadt 683: void
1.1 deraadt 684: execute(s)
685: char *s;
686: {
687: register char *cp;
688:
1.4 millert 689: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 690: cp = value(SHELL);
691: else
692: cp++;
693: shell_uid();
1.9 deraadt 694: execl(value(SHELL), cp, "-c", s, (char *)NULL);
1.1 deraadt 695: }
696:
1.7 deraadt 697: int
698: args(buf, a, num)
1.1 deraadt 699: char *buf, *a[];
1.7 deraadt 700: int num;
1.1 deraadt 701: {
702: register char *p = buf, *start;
703: register char **parg = a;
704: register int n = 0;
705:
706: do {
707: while (*p && (*p == ' ' || *p == '\t'))
708: p++;
709: start = p;
710: if (*p)
711: *parg = p;
712: while (*p && (*p != ' ' && *p != '\t'))
713: p++;
714: if (p != start)
715: parg++, n++;
716: if (*p)
717: *p++ = '\0';
1.7 deraadt 718: } while (*p && n < num);
1.1 deraadt 719:
720: return(n);
721: }
722:
1.7 deraadt 723: void
1.1 deraadt 724: prtime(s, a)
725: char *s;
726: time_t a;
727: {
1.10 ! deraadt 728: register int i;
1.1 deraadt 729: int nums[3];
730:
731: for (i = 0; i < 3; i++) {
732: nums[i] = (int)(a % quant[i]);
733: a /= quant[i];
734: }
735: printf("%s", s);
736: while (--i >= 0)
737: if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
738: printf("%d %s%c ", nums[i], sep[i],
739: nums[i] == 1 ? '\0' : 's');
740: printf("\r\n!\r\n");
741: }
742:
1.7 deraadt 743: void
1.1 deraadt 744: variable()
745: {
746: char buf[256];
747:
1.6 millert 748: if (prompt("[set] ", buf, sizeof(buf)))
1.1 deraadt 749: return;
750: vlex(buf);
751: if (vtable[BEAUTIFY].v_access&CHANGED) {
752: vtable[BEAUTIFY].v_access &= ~CHANGED;
753: kill(pid, SIGSYS);
754: }
755: if (vtable[SCRIPT].v_access&CHANGED) {
756: vtable[SCRIPT].v_access &= ~CHANGED;
757: setscript();
758: /*
759: * So that "set record=blah script" doesn't
760: * cause two transactions to occur.
761: */
762: if (vtable[RECORD].v_access&CHANGED)
763: vtable[RECORD].v_access &= ~CHANGED;
764: }
765: if (vtable[RECORD].v_access&CHANGED) {
766: vtable[RECORD].v_access &= ~CHANGED;
767: if (boolean(value(SCRIPT)))
768: setscript();
769: }
770: if (vtable[TAND].v_access&CHANGED) {
771: vtable[TAND].v_access &= ~CHANGED;
772: if (boolean(value(TAND)))
773: tandem("on");
774: else
775: tandem("off");
776: }
777: if (vtable[LECHO].v_access&CHANGED) {
778: vtable[LECHO].v_access &= ~CHANGED;
779: HD = boolean(value(LECHO));
780: }
781: if (vtable[PARITY].v_access&CHANGED) {
782: vtable[PARITY].v_access &= ~CHANGED;
1.7 deraadt 783: setparity(NOSTR);
1.1 deraadt 784: }
785: }
786:
787: /*
788: * Turn tandem mode on or off for remote tty.
789: */
1.7 deraadt 790: void
1.1 deraadt 791: tandem(option)
792: char *option;
793: {
1.2 deraadt 794: struct termios rmtty;
1.1 deraadt 795:
1.2 deraadt 796: tcgetattr(FD, &rmtty);
797: if (strcmp(option, "on") == 0) {
798: rmtty.c_iflag |= IXOFF;
799: term.c_iflag |= IXOFF;
1.1 deraadt 800: } else {
1.2 deraadt 801: rmtty.c_iflag &= ~IXOFF;
802: term.c_iflag &= ~IXOFF;
1.1 deraadt 803: }
1.2 deraadt 804: tcsetattr(FD, TCSADRAIN, &rmtty);
805: tcsetattr(0, TCSADRAIN, &term);
1.1 deraadt 806: }
807:
808: /*
809: * Send a break.
810: */
1.7 deraadt 811: void
1.1 deraadt 812: genbrk()
813: {
814:
815: ioctl(FD, TIOCSBRK, NULL);
816: sleep(1);
817: ioctl(FD, TIOCCBRK, NULL);
818: }
819:
820: /*
821: * Suspend tip
822: */
1.7 deraadt 823: void
1.1 deraadt 824: suspend(c)
825: char c;
826: {
827:
828: unraw();
829: kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
830: raw();
831: }
832:
833: /*
834: * expand a file name if it includes shell meta characters
835: */
836:
837: char *
838: expand(name)
839: char name[];
840: {
841: static char xname[BUFSIZ];
842: char cmdbuf[BUFSIZ];
1.7 deraadt 843: register int pid, l;
1.1 deraadt 844: register char *cp, *Shell;
1.7 deraadt 845: int s, pivec[2];
1.1 deraadt 846:
847: if (!anyof(name, "~{[*?$`'\"\\"))
848: return(name);
849: /* sigint = signal(SIGINT, SIG_IGN); */
850: if (pipe(pivec) < 0) {
851: perror("pipe");
852: /* signal(SIGINT, sigint) */
853: return(name);
854: }
1.5 millert 855: (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
1.1 deraadt 856: if ((pid = vfork()) == 0) {
857: Shell = value(SHELL);
858: if (Shell == NOSTR)
859: Shell = _PATH_BSHELL;
860: close(pivec[0]);
861: close(1);
862: dup(pivec[1]);
863: close(pivec[1]);
864: close(2);
865: shell_uid();
1.9 deraadt 866: execl(Shell, Shell, "-c", cmdbuf, (char *)NULL);
1.1 deraadt 867: _exit(1);
868: }
869: if (pid == -1) {
870: perror("fork");
871: close(pivec[0]);
872: close(pivec[1]);
873: return(NOSTR);
874: }
875: close(pivec[1]);
876: l = read(pivec[0], xname, BUFSIZ);
877: close(pivec[0]);
878: while (wait(&s) != pid);
879: ;
880: s &= 0377;
881: if (s != 0 && s != SIGPIPE) {
882: fprintf(stderr, "\"Echo\" failed\n");
883: return(NOSTR);
884: }
885: if (l < 0) {
886: perror("read");
887: return(NOSTR);
888: }
889: if (l == 0) {
890: fprintf(stderr, "\"%s\": No match\n", name);
891: return(NOSTR);
892: }
893: if (l == BUFSIZ) {
894: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
895: return(NOSTR);
896: }
897: xname[l] = 0;
898: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
899: ;
900: *++cp = '\0';
901: return(xname);
902: }
903:
904: /*
905: * Are any of the characters in the two strings the same?
906: */
1.7 deraadt 907: int
1.1 deraadt 908: anyof(s1, s2)
909: register char *s1, *s2;
910: {
911: register int c;
912:
1.7 deraadt 913: while ((c = *s1++))
1.1 deraadt 914: if (any(c, s2))
915: return(1);
916: return(0);
917: }