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