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