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