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