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