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