Annotation of src/usr.bin/tip/cmds.c, Revision 1.6
1.6 ! millert 1: /* $OpenBSD: cmds.c,v 1.5 1997/04/02 01:47:01 millert 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.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
40: #endif
1.6 ! millert 41: static char rcsid[] = "$OpenBSD: cmds.c,v 1.5 1997/04/02 01:47:01 millert Exp $";
1.1 deraadt 42: #endif /* not lint */
43:
44: #include "tip.h"
45: #include "pathnames.h"
46:
47: /*
48: * tip
49: *
50: * miscellaneous commands
51: */
52:
53: int quant[] = { 60, 60, 24 };
54:
55: char null = '\0';
56: char *sep[] = { "second", "minute", "hour" };
57: static char *argv[10]; /* argument vector for take and put */
58:
59: void timeout(); /* timeout function called on alarm */
60: void stopsnd(); /* SIGINT handler during file transfers */
61: void intcopy(); /* interrupt routine for file transfers */
62:
63: /*
64: * FTP - remote ==> local
65: * get a file from the remote host
66: */
67: getfl(c)
68: char c;
69: {
70: char buf[256], *cp, *expand();
71:
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: }
83:
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: */
97: cu_take(cc)
98: char cc;
99: {
100: int fd, argc;
101: char line[BUFSIZ], *expand(), *cp;
102:
1.6 ! millert 103: if (prompt("[take] ", copyname, sizeof(copyname)))
1.1 deraadt 104: return;
105: if ((argc = args(copyname, argv)) < 1 || argc > 2) {
106: printf("usage: <take> from [to]\r\n");
107: return;
108: }
109: if (argc == 1)
110: argv[1] = argv[0];
111: cp = expand(argv[1]);
112: if ((fd = creat(cp, 0666)) < 0) {
113: printf("\r\n%s: cannot create\r\n", argv[1]);
114: return;
115: }
1.5 millert 116: (void)snprintf(line, sizeof(line), "cat %s;echo \01", argv[0]);
1.1 deraadt 117: transfer(line, fd, "\01");
118: }
119:
120: static jmp_buf intbuf;
121: /*
122: * Bulk transfer routine --
123: * used by getfl(), cu_take(), and pipefile()
124: */
125: transfer(buf, fd, eofchars)
126: char *buf, *eofchars;
127: {
128: register int ct;
129: char c, buffer[BUFSIZ];
130: register char *p = buffer;
131: register int cnt, eof;
132: time_t start;
133: sig_t f;
134: char r;
135:
136: pwrite(FD, buf, size(buf));
137: quit = 0;
138: kill(pid, SIGIOT);
139: read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
140:
141: /*
142: * finish command
143: */
144: r = '\r';
145: pwrite(FD, &r, 1);
146: do
147: read(FD, &c, 1);
1.2 deraadt 148: while ((c&STRIP_PAR) != '\n');
149: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 150:
151: (void) setjmp(intbuf);
152: f = signal(SIGINT, intcopy);
153: start = time(0);
154: for (ct = 0; !quit;) {
155: eof = read(FD, &c, 1) <= 0;
1.2 deraadt 156: c &= STRIP_PAR;
1.1 deraadt 157: if (quit)
158: continue;
159: if (eof || any(c, eofchars))
160: break;
161: if (c == 0)
162: continue; /* ignore nulls */
163: if (c == '\r')
164: continue;
165: *p++ = c;
166:
167: if (c == '\n' && boolean(value(VERBOSE)))
168: printf("\r%d", ++ct);
169: if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
170: if (write(fd, buffer, cnt) != cnt) {
171: printf("\r\nwrite error\r\n");
172: quit = 1;
173: }
174: p = buffer;
175: }
176: }
177: if (cnt = (p-buffer))
178: if (write(fd, buffer, cnt) != cnt)
179: printf("\r\nwrite error\r\n");
180:
181: if (boolean(value(VERBOSE)))
182: prtime(" lines transferred in ", time(0)-start);
1.2 deraadt 183: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 184: write(fildes[1], (char *)&ccc, 1);
185: signal(SIGINT, f);
186: close(fd);
187: }
188:
189: /*
190: * FTP - remote ==> local process
191: * send remote input to local process via pipe
192: */
193: pipefile()
194: {
195: int cpid, pdes[2];
196: char buf[256];
197: int status, p;
198: extern int errno;
199:
1.6 ! millert 200: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 201: return;
202:
203: if (pipe(pdes)) {
204: printf("can't establish pipe\r\n");
205: return;
206: }
207:
208: if ((cpid = fork()) < 0) {
209: printf("can't fork!\r\n");
210: return;
211: } else if (cpid) {
1.6 ! millert 212: if (prompt("List command for remote system? ", buf, sizeof(buf))) {
1.1 deraadt 213: close(pdes[0]), close(pdes[1]);
214: kill (cpid, SIGKILL);
215: } else {
216: close(pdes[0]);
217: signal(SIGPIPE, intcopy);
218: transfer(buf, pdes[1], value(EOFREAD));
219: signal(SIGPIPE, SIG_DFL);
220: while ((p = wait(&status)) > 0 && p != cpid)
221: ;
222: }
223: } else {
224: register int f;
225:
226: dup2(pdes[0], 0);
227: close(pdes[0]);
228: for (f = 3; f < 20; f++)
229: close(f);
230: execute(buf);
231: printf("can't execl!\r\n");
232: exit(0);
233: }
234: }
235:
236: /*
237: * Interrupt service routine for FTP
238: */
239: void
240: stopsnd()
241: {
242:
243: stop = 1;
244: signal(SIGINT, SIG_IGN);
245: }
246:
247: /*
248: * FTP - local ==> remote
249: * send local file to remote host
250: * terminate transmission with pseudo EOF sequence
251: */
252: sendfile(cc)
253: char cc;
254: {
255: FILE *fd;
256: char *fnamex;
257: char *expand();
258:
259: putchar(cc);
260: /*
261: * get file name
262: */
1.6 ! millert 263: if (prompt("Local file name? ", fname, sizeof(fname)))
1.1 deraadt 264: return;
265:
266: /*
267: * look up file
268: */
269: fnamex = expand(fname);
270: if ((fd = fopen(fnamex, "r")) == NULL) {
271: printf("%s: cannot open\r\n", fname);
272: return;
273: }
274: transmit(fd, value(EOFWRITE), NULL);
1.2 deraadt 275: if (!boolean(value(ECHOCHECK)))
276: tcdrain(FD);
1.1 deraadt 277: }
278:
279: /*
280: * Bulk transfer routine to remote host --
281: * used by sendfile() and cu_put()
282: */
283: transmit(fd, eofchars, command)
284: FILE *fd;
285: char *eofchars, *command;
286: {
287: char *pc, lastc;
288: int c, ccount, lcount;
289: time_t start_t, stop_t;
290: sig_t f;
291:
292: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
293: stop = 0;
294: f = signal(SIGINT, stopsnd);
1.2 deraadt 295: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 296: read(repdes[0], (char *)&ccc, 1);
297: if (command != NULL) {
298: for (pc = command; *pc; pc++)
299: send(*pc);
300: if (boolean(value(ECHOCHECK)))
301: read(FD, (char *)&c, 1); /* trailing \n */
302: else {
1.2 deraadt 303: tcdrain(FD);
1.1 deraadt 304: sleep(5); /* wait for remote stty to take effect */
305: }
306: }
307: lcount = 0;
308: lastc = '\0';
309: start_t = time(0);
310: while (1) {
311: ccount = 0;
312: do {
313: c = getc(fd);
314: if (stop)
315: goto out;
316: if (c == EOF)
317: goto out;
318: if (c == 0177 && !boolean(value(RAWFTP)))
319: continue;
320: lastc = c;
321: if (c < 040) {
322: if (c == '\n') {
323: if (!boolean(value(RAWFTP)))
324: c = '\r';
325: }
326: else if (c == '\t') {
327: if (!boolean(value(RAWFTP))) {
328: if (boolean(value(TABEXPAND))) {
329: send(' ');
330: while ((++ccount % 8) != 0)
331: send(' ');
332: continue;
333: }
334: }
335: } else
336: if (!boolean(value(RAWFTP)))
337: continue;
338: }
339: send(c);
340: } while (c != '\r' && !boolean(value(RAWFTP)));
341: if (boolean(value(VERBOSE)))
342: printf("\r%d", ++lcount);
343: if (boolean(value(ECHOCHECK))) {
344: timedout = 0;
345: alarm((long)value(ETIMEOUT));
346: do { /* wait for prompt */
347: read(FD, (char *)&c, 1);
348: if (timedout || stop) {
349: if (timedout)
350: printf("\r\ntimed out at eol\r\n");
351: alarm(0);
352: goto out;
353: }
1.2 deraadt 354: } while ((c&STRIP_PAR) != character(value(PROMPT)));
1.1 deraadt 355: alarm(0);
356: }
357: }
358: out:
359: if (lastc != '\n' && !boolean(value(RAWFTP)))
360: send('\r');
361: if (eofchars) {
362: for (pc = eofchars; *pc; pc++)
363: send(*pc);
364: }
365: stop_t = time(0);
366: fclose(fd);
367: signal(SIGINT, f);
368: if (boolean(value(VERBOSE)))
369: if (boolean(value(RAWFTP)))
370: prtime(" chars transferred in ", stop_t-start_t);
371: else
372: prtime(" lines transferred in ", stop_t-start_t);
373: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 374: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 375: }
376:
377: /*
378: * Cu-like put command
379: */
380: cu_put(cc)
381: char cc;
382: {
383: FILE *fd;
384: char line[BUFSIZ];
385: int argc;
386: char *expand();
387: char *copynamex;
388:
1.6 ! millert 389: if (prompt("[put] ", copyname, sizeof(copyname)))
1.1 deraadt 390: return;
391: if ((argc = args(copyname, argv)) < 1 || argc > 2) {
392: printf("usage: <put> from [to]\r\n");
393: return;
394: }
395: if (argc == 1)
396: argv[1] = argv[0];
397: copynamex = expand(argv[0]);
398: if ((fd = fopen(copynamex, "r")) == NULL) {
399: printf("%s: cannot open\r\n", copynamex);
400: return;
401: }
402: if (boolean(value(ECHOCHECK)))
1.5 millert 403: (void)snprintf(line, sizeof(line), "cat>%s\r", argv[1]);
1.1 deraadt 404: else
1.5 millert 405: (void)snprintf(line, sizeof(line),
406: "stty -echo;cat>%s;stty echo\r", argv[1]);
1.1 deraadt 407: transmit(fd, "\04", line);
408: }
409:
410: /*
411: * FTP - send single character
412: * wait for echo & handle timeout
413: */
414: send(c)
415: char c;
416: {
417: char cc;
418: int retry = 0;
419:
420: cc = c;
421: pwrite(FD, &cc, 1);
422: #ifdef notdef
423: if (number(value(CDELAY)) > 0 && c != '\r')
424: nap(number(value(CDELAY)));
425: #endif
426: if (!boolean(value(ECHOCHECK))) {
427: #ifdef notdef
428: if (number(value(LDELAY)) > 0 && c == '\r')
429: nap(number(value(LDELAY)));
430: #endif
431: return;
432: }
433: tryagain:
434: timedout = 0;
435: alarm((long)value(ETIMEOUT));
436: read(FD, &cc, 1);
437: alarm(0);
438: if (timedout) {
439: printf("\r\ntimeout error (%s)\r\n", ctrl(c));
440: if (retry++ > 3)
441: return;
442: pwrite(FD, &null, 1); /* poke it */
443: goto tryagain;
444: }
445: }
446:
447: void
448: timeout()
449: {
450: signal(SIGALRM, timeout);
451: timedout = 1;
452: }
453:
454: /*
455: * Stolen from consh() -- puts a remote file on the output of a local command.
456: * Identical to consh() except for where stdout goes.
457: */
458: pipeout(c)
459: {
460: char buf[256];
461: int cpid, status, p;
462: time_t start;
463:
464: putchar(c);
1.6 ! millert 465: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 466: return;
467: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
468: signal(SIGINT, SIG_IGN);
469: signal(SIGQUIT, SIG_IGN);
1.2 deraadt 470: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 471: read(repdes[0], (char *)&ccc, 1);
472: /*
473: * Set up file descriptors in the child and
474: * let it go...
475: */
476: if ((cpid = fork()) < 0)
477: printf("can't fork!\r\n");
478: else if (cpid) {
479: start = time(0);
480: while ((p = wait(&status)) > 0 && p != cpid)
481: ;
482: } else {
483: register int i;
484:
485: dup2(FD, 1);
486: for (i = 3; i < 20; i++)
487: close(i);
488: signal(SIGINT, SIG_DFL);
489: signal(SIGQUIT, SIG_DFL);
490: execute(buf);
491: printf("can't find `%s'\r\n", buf);
492: exit(0);
493: }
494: if (boolean(value(VERBOSE)))
495: prtime("away for ", time(0)-start);
496: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 497: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 498: signal(SIGINT, SIG_DFL);
499: signal(SIGQUIT, SIG_DFL);
500: }
501:
502: #ifdef CONNECT
503: /*
504: * Fork a program with:
505: * 0 <-> remote tty in
506: * 1 <-> remote tty out
507: * 2 <-> local tty out
508: */
509: consh(c)
510: {
511: char buf[256];
512: int cpid, status, p;
513: time_t start;
514:
515: putchar(c);
1.6 ! millert 516: if (prompt("Local command? ", buf, sizeof(buf)))
1.1 deraadt 517: return;
518: kill(pid, SIGIOT); /* put TIPOUT into a wait state */
519: signal(SIGINT, SIG_IGN);
520: signal(SIGQUIT, SIG_IGN);
1.2 deraadt 521: tcsetattr(0, TCSAFLUSH, &defchars);
1.1 deraadt 522: read(repdes[0], (char *)&ccc, 1);
523: /*
524: * Set up file descriptors in the child and
525: * let it go...
526: */
527: if ((cpid = fork()) < 0)
528: printf("can't fork!\r\n");
529: else if (cpid) {
530: start = time(0);
531: while ((p = wait(&status)) > 0 && p != cpid)
532: ;
533: } else {
534: register int i;
535:
536: dup2(FD, 0);
537: dup2(3, 1);
538: for (i = 3; i < 20; i++)
539: close(i);
540: signal(SIGINT, SIG_DFL);
541: signal(SIGQUIT, SIG_DFL);
542: execute(buf);
543: printf("can't find `%s'\r\n", buf);
544: exit(0);
545: }
546: if (boolean(value(VERBOSE)))
547: prtime("away for ", time(0)-start);
548: write(fildes[1], (char *)&ccc, 1);
1.2 deraadt 549: tcsetattr(0, TCSAFLUSH, &term);
1.1 deraadt 550: signal(SIGINT, SIG_DFL);
551: signal(SIGQUIT, SIG_DFL);
552: }
553: #endif
554:
555: /*
556: * Escape to local shell
557: */
558: shell()
559: {
560: int shpid, status;
561: extern char **environ;
562: char *cp;
563:
564: printf("[sh]\r\n");
565: signal(SIGINT, SIG_IGN);
566: signal(SIGQUIT, SIG_IGN);
567: unraw();
568: if (shpid = fork()) {
569: while (shpid != wait(&status));
570: raw();
571: printf("\r\n!\r\n");
572: signal(SIGINT, SIG_DFL);
573: signal(SIGQUIT, SIG_DFL);
574: return;
575: } else {
576: signal(SIGQUIT, SIG_DFL);
577: signal(SIGINT, SIG_DFL);
1.4 millert 578: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 579: cp = value(SHELL);
580: else
581: cp++;
582: shell_uid();
583: execl(value(SHELL), cp, 0);
584: printf("\r\ncan't execl!\r\n");
585: exit(1);
586: }
587: }
588:
589: /*
590: * TIPIN portion of scripting
591: * initiate the conversation with TIPOUT
592: */
593: setscript()
594: {
595: char c;
596: /*
597: * enable TIPOUT side for dialogue
598: */
599: kill(pid, SIGEMT);
600: if (boolean(value(SCRIPT)))
601: write(fildes[1], value(RECORD), size(value(RECORD)));
602: write(fildes[1], "\n", 1);
603: /*
604: * wait for TIPOUT to finish
605: */
606: read(repdes[0], &c, 1);
607: if (c == 'n')
608: printf("can't create %s\r\n", value(RECORD));
609: }
610:
611: /*
612: * Change current working directory of
613: * local portion of tip
614: */
615: chdirectory()
616: {
1.6 ! millert 617: char dirname[PATH_MAX];
1.1 deraadt 618: register char *cp = dirname;
619:
1.6 ! millert 620: if (prompt("[cd] ", dirname, sizeof(dirname))) {
1.1 deraadt 621: if (stoprompt)
622: return;
623: cp = value(HOME);
624: }
625: if (chdir(cp) < 0)
626: printf("%s: bad directory\r\n", cp);
627: printf("!\r\n");
628: }
629:
630: tipabort(msg)
631: char *msg;
632: {
633:
634: kill(pid, SIGTERM);
635: disconnect(msg);
636: if (msg != NOSTR)
637: printf("\r\n%s", msg);
638: printf("\r\n[EOT]\r\n");
639: daemon_uid();
640: (void)uu_unlock(uucplock);
641: unraw();
642: exit(0);
643: }
644:
645: finish()
646: {
647: char *dismsg;
648:
649: if ((dismsg = value(DISCONNECT)) != NOSTR) {
650: write(FD, dismsg, strlen(dismsg));
651: sleep(5);
652: }
653: tipabort(NOSTR);
654: }
655:
656: void
657: intcopy()
658: {
659: raw();
660: quit = 1;
661: longjmp(intbuf, 1);
662: }
663:
664: execute(s)
665: char *s;
666: {
667: register char *cp;
668:
1.4 millert 669: if ((cp = strrchr(value(SHELL), '/')) == NULL)
1.1 deraadt 670: cp = value(SHELL);
671: else
672: cp++;
673: shell_uid();
674: execl(value(SHELL), cp, "-c", s, 0);
675: }
676:
677: args(buf, a)
678: char *buf, *a[];
679: {
680: register char *p = buf, *start;
681: register char **parg = a;
682: register int n = 0;
683:
684: do {
685: while (*p && (*p == ' ' || *p == '\t'))
686: p++;
687: start = p;
688: if (*p)
689: *parg = p;
690: while (*p && (*p != ' ' && *p != '\t'))
691: p++;
692: if (p != start)
693: parg++, n++;
694: if (*p)
695: *p++ = '\0';
696: } while (*p);
697:
698: return(n);
699: }
700:
701: prtime(s, a)
702: char *s;
703: time_t a;
704: {
705: register i;
706: int nums[3];
707:
708: for (i = 0; i < 3; i++) {
709: nums[i] = (int)(a % quant[i]);
710: a /= quant[i];
711: }
712: printf("%s", s);
713: while (--i >= 0)
714: if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
715: printf("%d %s%c ", nums[i], sep[i],
716: nums[i] == 1 ? '\0' : 's');
717: printf("\r\n!\r\n");
718: }
719:
720: variable()
721: {
722: char buf[256];
723:
1.6 ! millert 724: if (prompt("[set] ", buf, sizeof(buf)))
1.1 deraadt 725: return;
726: vlex(buf);
727: if (vtable[BEAUTIFY].v_access&CHANGED) {
728: vtable[BEAUTIFY].v_access &= ~CHANGED;
729: kill(pid, SIGSYS);
730: }
731: if (vtable[SCRIPT].v_access&CHANGED) {
732: vtable[SCRIPT].v_access &= ~CHANGED;
733: setscript();
734: /*
735: * So that "set record=blah script" doesn't
736: * cause two transactions to occur.
737: */
738: if (vtable[RECORD].v_access&CHANGED)
739: vtable[RECORD].v_access &= ~CHANGED;
740: }
741: if (vtable[RECORD].v_access&CHANGED) {
742: vtable[RECORD].v_access &= ~CHANGED;
743: if (boolean(value(SCRIPT)))
744: setscript();
745: }
746: if (vtable[TAND].v_access&CHANGED) {
747: vtable[TAND].v_access &= ~CHANGED;
748: if (boolean(value(TAND)))
749: tandem("on");
750: else
751: tandem("off");
752: }
753: if (vtable[LECHO].v_access&CHANGED) {
754: vtable[LECHO].v_access &= ~CHANGED;
755: HD = boolean(value(LECHO));
756: }
757: if (vtable[PARITY].v_access&CHANGED) {
758: vtable[PARITY].v_access &= ~CHANGED;
759: setparity();
760: }
761: }
762:
763: /*
764: * Turn tandem mode on or off for remote tty.
765: */
766: tandem(option)
767: char *option;
768: {
1.2 deraadt 769: struct termios rmtty;
1.1 deraadt 770:
1.2 deraadt 771: tcgetattr(FD, &rmtty);
772: if (strcmp(option, "on") == 0) {
773: rmtty.c_iflag |= IXOFF;
774: term.c_iflag |= IXOFF;
1.1 deraadt 775: } else {
1.2 deraadt 776: rmtty.c_iflag &= ~IXOFF;
777: term.c_iflag &= ~IXOFF;
1.1 deraadt 778: }
1.2 deraadt 779: tcsetattr(FD, TCSADRAIN, &rmtty);
780: tcsetattr(0, TCSADRAIN, &term);
1.1 deraadt 781: }
782:
783: /*
784: * Send a break.
785: */
786: genbrk()
787: {
788:
789: ioctl(FD, TIOCSBRK, NULL);
790: sleep(1);
791: ioctl(FD, TIOCCBRK, NULL);
792: }
793:
794: /*
795: * Suspend tip
796: */
797: suspend(c)
798: char c;
799: {
800:
801: unraw();
802: kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
803: raw();
804: }
805:
806: /*
807: * expand a file name if it includes shell meta characters
808: */
809:
810: char *
811: expand(name)
812: char name[];
813: {
814: static char xname[BUFSIZ];
815: char cmdbuf[BUFSIZ];
816: register int pid, l, rc;
817: register char *cp, *Shell;
818: int s, pivec[2], (*sigint)();
819:
820: if (!anyof(name, "~{[*?$`'\"\\"))
821: return(name);
822: /* sigint = signal(SIGINT, SIG_IGN); */
823: if (pipe(pivec) < 0) {
824: perror("pipe");
825: /* signal(SIGINT, sigint) */
826: return(name);
827: }
1.5 millert 828: (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
1.1 deraadt 829: if ((pid = vfork()) == 0) {
830: Shell = value(SHELL);
831: if (Shell == NOSTR)
832: Shell = _PATH_BSHELL;
833: close(pivec[0]);
834: close(1);
835: dup(pivec[1]);
836: close(pivec[1]);
837: close(2);
838: shell_uid();
839: execl(Shell, Shell, "-c", cmdbuf, 0);
840: _exit(1);
841: }
842: if (pid == -1) {
843: perror("fork");
844: close(pivec[0]);
845: close(pivec[1]);
846: return(NOSTR);
847: }
848: close(pivec[1]);
849: l = read(pivec[0], xname, BUFSIZ);
850: close(pivec[0]);
851: while (wait(&s) != pid);
852: ;
853: s &= 0377;
854: if (s != 0 && s != SIGPIPE) {
855: fprintf(stderr, "\"Echo\" failed\n");
856: return(NOSTR);
857: }
858: if (l < 0) {
859: perror("read");
860: return(NOSTR);
861: }
862: if (l == 0) {
863: fprintf(stderr, "\"%s\": No match\n", name);
864: return(NOSTR);
865: }
866: if (l == BUFSIZ) {
867: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
868: return(NOSTR);
869: }
870: xname[l] = 0;
871: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
872: ;
873: *++cp = '\0';
874: return(xname);
875: }
876:
877: /*
878: * Are any of the characters in the two strings the same?
879: */
880:
881: anyof(s1, s2)
882: register char *s1, *s2;
883: {
884: register int c;
885:
886: while (c = *s1++)
887: if (any(c, s2))
888: return(1);
889: return(0);
890: }