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