|
|
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: }
1.1.1.2 ! root 550: signal(SIGCHLD, SIG_IGN);
1.1 root 551: kill(pid, SIGTERM);
1.1.1.2 ! root 552: ioctl(FD,TIOCNXCL); /* remove exclusive use lock */
1.1 root 553: disconnect();
554: printf("\r\n[EOT]\r\n");
555: delock(uucplock);
556: unraw();
557: exit(0);
558: }
559:
560: intcopy()
561: {
562:
563: raw();
564: quit = 1;
565: longjmp(intbuf, 1);
566: }
567:
568: execute(s)
569: char *s;
570: {
571: register char *cp;
572:
573: if ((cp = rindex(value(SHELL), '/')) == NULL)
574: cp = value(SHELL);
575: else
576: cp++;
577: execl(value(SHELL), cp, "-c", s, 0);
578: }
579:
580: args(buf, a)
581: char *buf, *a[];
582: {
583: register char *p = buf, *start;
584: register char **parg = a;
585: register int n = 0;
586:
587: do {
588: while (*p && (*p == ' ' || *p == '\t'))
589: p++;
590: start = p;
591: if (*p)
592: *parg = p;
593: while (*p && (*p != ' ' && *p != '\t'))
594: p++;
595: if (p != start)
596: parg++, n++;
597: if (*p)
598: *p++ = '\0';
599: } while (*p);
600:
601: return(n);
602: }
603:
604: prtime(s, a)
605: char *s;
606: time_t a;
607: {
608: register i;
609: int nums[3];
610:
611: for (i = 0; i < 3; i++) {
612: nums[i] = (int)(a % quant[i]);
613: a /= quant[i];
614: }
615: printf("%s", s);
616: while (--i >= 0)
617: if (nums[i])
618: printf("%d %s%c ", nums[i], sep[i],
619: nums[i] == 1 ? '\0' : 's');
620: printf("\r\n!\r\n");
621: }
622:
623: variable()
624: {
625: char buf[256];
626:
627: if (prompt("[set] ", buf))
628: return;
629: vlex(buf);
630: if (vtable[BEAUTIFY].v_access&CHANGED) {
631: vtable[BEAUTIFY].v_access &= ~CHANGED;
632: kill(pid, SIGSYS);
633: }
634: if (vtable[SCRIPT].v_access&CHANGED) {
635: vtable[SCRIPT].v_access &= ~CHANGED;
636: setscript();
637: /*
638: * So that "set record=blah script" doesn't
639: * cause two transactions to occur.
640: */
641: if (vtable[RECORD].v_access&CHANGED)
642: vtable[RECORD].v_access &= ~CHANGED;
643: }
644: if (vtable[RECORD].v_access&CHANGED) {
645: vtable[RECORD].v_access &= ~CHANGED;
646: if (boolean(value(SCRIPT)))
647: setscript();
648: }
649: if (vtable[TAND].v_access&CHANGED) {
650: vtable[TAND].v_access &= ~CHANGED;
651: if (boolean(value(TAND)))
652: tandem("on");
653: else
654: tandem("off");
655: }
656: if (vtable[LECHO].v_access&CHANGED) {
657: vtable[LECHO].v_access &= ~CHANGED;
658: HD = boolean(value(LECHO));
659: }
660: if (vtable[PARITY].v_access&CHANGED) {
661: vtable[PARITY].v_access &= ~CHANGED;
662: setparity();
663: }
664: }
665:
666: /*
667: * Turn tandem mode on or off for remote tty.
668: */
669: tandem(option)
670: char *option;
671: {
672: struct sgttyb rmtty;
673:
674: ioctl(FD, TIOCGETP, &rmtty);
675: if (strcmp(option,"on") == 0) {
676: rmtty.sg_flags |= TANDEM;
677: arg.sg_flags |= TANDEM;
678: } else {
679: rmtty.sg_flags &= ~TANDEM;
680: arg.sg_flags &= ~TANDEM;
681: }
682: ioctl(FD, TIOCSETP, &rmtty);
683: ioctl(0, TIOCSETP, &arg);
684: }
685:
686: /*
687: * Send a break.
688: */
689: genbrk()
690: {
691:
692: ioctl(FD, TIOCSBRK, NULL);
693: sleep(1);
694: ioctl(FD, TIOCCBRK, NULL);
695: }
696:
697: /*
698: * Suspend tip
699: */
700: suspend()
701: {
702:
703: unraw();
704: kill(0, SIGTSTP);
705: raw();
706: }
707:
708: /*
1.1.1.2 ! root 709: * Set logout timer
! 710: */
! 711: settimer()
! 712: {
! 713: char c;
! 714:
! 715: if (prompt("[minutes] ", minutes))
! 716: return;
! 717: if (args(minutes, argv) != 1) {
! 718: printf("usage: <minutes> number\r\n");
! 719: return;
! 720: }
! 721: /*
! 722: * enable TIPOUT side for dialogue
! 723: */
! 724: kill(pid, SIGFPE);
! 725: write(fildes[1], minutes, sizeof(minutes));
! 726: write(fildes[1], "\n", 1);
! 727: /*
! 728: * wait for TIPOUT to finish
! 729: */
! 730: read(repdes[0], &c, 1);
! 731: }
! 732:
! 733: /*
1.1 root 734: * expand a file name if it includes shell meta characters
735: */
736:
737: char *
738: expand(name)
739: char name[];
740: {
741: static char xname[BUFSIZ];
742: char cmdbuf[BUFSIZ];
743: register int pid, l, rc;
744: register char *cp, *Shell;
745: int s, pivec[2], (*sigint)();
746:
747: if (!anyof(name, "~{[*?$`'\"\\"))
748: return(name);
749: /* sigint = signal(SIGINT, SIG_IGN); */
750: if (pipe(pivec) < 0) {
751: perror("pipe");
752: /* signal(SIGINT, sigint) */
753: return(name);
754: }
755: sprintf(cmdbuf, "echo %s", name);
756: if ((pid = vfork()) == 0) {
757: Shell = value(SHELL);
758: if (Shell == NOSTR)
759: Shell = "/bin/sh";
760: close(pivec[0]);
761: close(1);
762: dup(pivec[1]);
763: close(pivec[1]);
764: close(2);
765: execl(Shell, Shell, "-c", cmdbuf, 0);
766: _exit(1);
767: }
768: if (pid == -1) {
769: perror("fork");
770: close(pivec[0]);
771: close(pivec[1]);
772: return(NOSTR);
773: }
774: close(pivec[1]);
775: l = read(pivec[0], xname, BUFSIZ);
776: close(pivec[0]);
777: while (wait(&s) != pid);
778: ;
779: s &= 0377;
780: if (s != 0 && s != SIGPIPE) {
781: fprintf(stderr, "\"Echo\" failed\n");
782: return(NOSTR);
783: }
784: if (l < 0) {
785: perror("read");
786: return(NOSTR);
787: }
788: if (l == 0) {
789: fprintf(stderr, "\"%s\": No match\n", name);
790: return(NOSTR);
791: }
792: if (l == BUFSIZ) {
793: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
794: return(NOSTR);
795: }
796: xname[l] = 0;
797: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
798: ;
799: *++cp = '\0';
800: return(xname);
801: }
802:
803: /*
804: * Are any of the characters in the two strings the same?
805: */
806:
807: anyof(s1, s2)
808: register char *s1, *s2;
809: {
810: register int c;
811:
812: while (c = *s1++)
813: if (any(c, s2))
814: return(1);
815: return(0);
816: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.