1*3822Ssam /* cmds.c 4.2 81/05/31 */ 23688Sroot #include "tip.h" 33688Sroot /* 43688Sroot * tip 53688Sroot * 63688Sroot * miscellaneous commands 73688Sroot */ 83688Sroot 93688Sroot int quant[] = { 60, 60, 24 }; 103688Sroot 113688Sroot char null = '\0'; 123688Sroot char *sep[] = { "second", "minute", "hour" }; 133688Sroot static char *argv[10]; /* argument vector for take and put */ 143688Sroot 153688Sroot int timeout(); /* timeout function called on alarm */ 163688Sroot int stopsnd(); /* SIGINT handler during file transfers */ 173688Sroot int intprompt(); /* used in handling SIG_INT during prompt */ 183688Sroot int intcopy(); /* interrupt routine for file transfers */ 193688Sroot 203688Sroot /* 213688Sroot * FTP - remote ==> local 223688Sroot * get a file from the remote host 233688Sroot */ 243688Sroot getfl(c) 253688Sroot char c; 263688Sroot { 273688Sroot char buf[256]; 283688Sroot 293688Sroot putchar(c); 303688Sroot /* 313688Sroot * get the UNIX receiving file's name 323688Sroot */ 333688Sroot if (prompt("Local file name? ", copyname)) 343688Sroot return; 353688Sroot if ((sfd = creat(copyname, 0666)) < 0) { 363688Sroot printf("\r\n%s: cannot creat\r\n", copyname); 373688Sroot return; 383688Sroot } 393688Sroot 403688Sroot /* 413688Sroot * collect parameters 423688Sroot */ 433688Sroot if (prompt("List command for remote system? ", buf)) { 443688Sroot unlink(copyname); 453688Sroot return; 463688Sroot } 473688Sroot transfer(buf, sfd, value(EOFREAD)); 483688Sroot } 493688Sroot 503688Sroot /* 513688Sroot * Cu-like take command 523688Sroot */ 533688Sroot cu_take(cc) 543688Sroot char cc; 553688Sroot { 563688Sroot int fd, argc; 573688Sroot char line[BUFSIZ]; 583688Sroot 593688Sroot if (prompt("[take] ", copyname)) 603688Sroot return; 613688Sroot if ((argc = args(copyname, argv)) < 1 || argc > 2) { 623688Sroot printf("usage: <take> from [to]\r\n"); 633688Sroot return; 643688Sroot } 653688Sroot if (argc == 1) 663688Sroot argv[1] = argv[0]; 673688Sroot if ((fd = creat(argv[1], 0666)) < 0) { 683688Sroot printf("\r\n%s: cannot create\r\n", argv[1]); 693688Sroot return; 703688Sroot } 713688Sroot sprintf(line, "cat '%s';echo \01", argv[0]); 723688Sroot transfer(line, fd, "\01"); 733688Sroot } 743688Sroot 753688Sroot /* 763688Sroot * Bulk transfer routine -- 773688Sroot * used by getfl(), cu_take(), and pipefile() 783688Sroot */ 793688Sroot transfer(buf, fd, eofchars) 803688Sroot char *buf, *eofchars; 813688Sroot { 823688Sroot register int ct; 833688Sroot char c, buffer[BUFSIZ]; 843688Sroot register char *p = buffer; 853688Sroot register int cnt, eof; 863688Sroot time_t start; 873688Sroot 883688Sroot write(FD, buf, size(buf)); 893688Sroot quit = 0; 903688Sroot signal(SIGINT, intcopy); 913688Sroot kill(pid, SIGIOT); 923688Sroot read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 933688Sroot 943688Sroot /* 953688Sroot * finish command 963688Sroot */ 973688Sroot write(FD, "\r", 1); 983688Sroot do 993688Sroot read(FD, &c, 1); 1003688Sroot while ((c&0177) != '\n'); 1013688Sroot ioctl(0, TIOCSETC, &defchars); 1023688Sroot 1033688Sroot start = time(0); 1043688Sroot for (ct = 0; !quit;) { 1053688Sroot eof = read(FD, &c, 1) <= 0; 1063688Sroot c &= 0177; 1073688Sroot if (quit) 1083688Sroot continue; 1093688Sroot if (eof || any(c, eofchars)) 1103688Sroot break; 1113688Sroot if (c == 0) 1123688Sroot continue; /* ignore nulls */ 1133688Sroot if (c == '\r') 1143688Sroot continue; 1153688Sroot *p++ = c; 1163688Sroot 1173688Sroot if (c == '\n' && boolean(value(VERBOSE))) 1183688Sroot printf("\r%d", ++ct); 1193688Sroot if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) { 1203688Sroot if (write(fd, buffer, cnt) != cnt) { 1213688Sroot printf("\r\nwrite error\r\n"); 1223688Sroot quit = 1; 1233688Sroot } 1243688Sroot p = buffer; 1253688Sroot } 1263688Sroot } 1273688Sroot if (cnt = (p-buffer)) 1283688Sroot if (write(fd, buffer, cnt) != cnt) 1293688Sroot printf("\r\nwrite error\r\n"); 1303688Sroot 1313688Sroot if (boolean(value(VERBOSE))) 1323688Sroot prtime(" lines transferred in ", time(0)-start); 1333688Sroot ioctl(0, TIOCSETC, &tchars); 1343688Sroot write(fildes[1], (char *)&ccc, 1); 1353688Sroot signal(SIGINT, SIG_DFL); 1363688Sroot close(fd); 1373688Sroot } 1383688Sroot 1393688Sroot /* 1403688Sroot * FTP - remote ==> local process 1413688Sroot * send remote input to local process via pipe 1423688Sroot */ 1433688Sroot pipefile() 1443688Sroot { 1453688Sroot int cpid, pdes[2]; 1463688Sroot char buf[256]; 1473688Sroot int status, p; 1483688Sroot extern int errno; 1493688Sroot 1503688Sroot if (prompt("Local command? ", buf)) 1513688Sroot return; 1523688Sroot 1533688Sroot if (pipe(pdes)) { 1543688Sroot printf("can't establish pipe\r\n"); 1553688Sroot return; 1563688Sroot } 1573688Sroot 1583688Sroot if ((cpid = fork()) < 0) { 1593688Sroot printf("can't fork!\r\n"); 1603688Sroot return; 1613688Sroot } else if (cpid) { 1623688Sroot if (prompt("List command for remote system? ", buf)) { 1633688Sroot close(pdes[0]), close(pdes[1]); 1643688Sroot kill (cpid, SIGKILL); 1653688Sroot } else { 1663688Sroot close(pdes[0]); 1673688Sroot signal(SIGPIPE, intcopy); 1683688Sroot transfer(buf, pdes[1], value(EOFREAD)); 1693688Sroot signal(SIGPIPE, SIG_DFL); 1703688Sroot while ((p = wait(&status)) > 0 && p != cpid) 1713688Sroot ; 1723688Sroot } 1733688Sroot } else { 1743688Sroot register int f; 1753688Sroot 1763688Sroot dup2(pdes[0], 0); 1773688Sroot close(pdes[0]); 1783688Sroot for (f = 3; f < 20; f++) 1793688Sroot close(f); 1803688Sroot execute(buf); 1813688Sroot printf("can't execl!\r\n"); 1823688Sroot exit(0); 1833688Sroot } 1843688Sroot } 1853688Sroot 1863688Sroot /* 1873688Sroot * Interrupt service routine for FTP 1883688Sroot */ 1893688Sroot stopsnd() 1903688Sroot { 1913688Sroot stop = 1; 1923688Sroot signal(SIGINT, SIG_IGN); 1933688Sroot } 1943688Sroot 1953688Sroot /* 1963688Sroot * FTP - local ==> remote 1973688Sroot * send local file to remote host 1983688Sroot * terminate transmission with pseudo EOF sequence 1993688Sroot */ 2003688Sroot sendfile(cc) 2013688Sroot char cc; 2023688Sroot { 2033688Sroot FILE *fd; 2043688Sroot 2053688Sroot putchar(cc); 2063688Sroot /* 2073688Sroot * get file name 2083688Sroot */ 2093688Sroot if (prompt("Local file name? ", fname)) 2103688Sroot return; 2113688Sroot 2123688Sroot /* 2133688Sroot * look up file 2143688Sroot */ 2153688Sroot if ((fd = fopen(fname, "r")) == NULL) { 2163688Sroot printf("%s: cannot open\r\n", fname); 2173688Sroot return; 2183688Sroot } 2193688Sroot transmit(fd, value(EOFWRITE), NULL); 2203688Sroot } 2213688Sroot 2223688Sroot /* 2233688Sroot * Bulk transfer routine to remote host -- 2243688Sroot * used by sendfile() and cu_put() 2253688Sroot */ 2263688Sroot transmit(fd, eofchars, command) 2273688Sroot FILE *fd; 2283688Sroot char *eofchars, *command; 2293688Sroot { 2303688Sroot char *pc, lastc; 2313688Sroot int c, ccount, lcount; 2323688Sroot time_t start_t, stop_t; 2333688Sroot 2343688Sroot kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 2353688Sroot signal(SIGINT, stopsnd); 2363688Sroot stop = 0; 2373688Sroot ioctl(0, TIOCSETC, &defchars); 2383688Sroot read(repdes[0], (char *)&ccc, 1); 2393688Sroot if (command != NULL) { 2403688Sroot for (pc = command; *pc; pc++) 2413688Sroot send(*pc); 2423688Sroot read(FD, (char *)&c, 1); /* trailing \n */ 2433688Sroot } 2443688Sroot lcount = 0; 2453688Sroot lastc = '\0'; 2463688Sroot start_t = time(0); 2473688Sroot while(1) { 2483688Sroot ccount = 0; 2493688Sroot do { 2503688Sroot c = getc(fd); 2513688Sroot if (stop) 2523688Sroot goto out; 2533688Sroot if (c == EOF) 2543688Sroot goto out; 2553688Sroot if (c == 0177) 2563688Sroot continue; 2573688Sroot lastc = c; 2583688Sroot if (c < 040) { 2593688Sroot if (c == '\n') 2603688Sroot c = '\r'; 2613688Sroot else if (c == '\t') { 2623688Sroot if (boolean(value(TABEXPAND))) { 2633688Sroot send(' '); 2643688Sroot while((++ccount % 8) != 0) 2653688Sroot send(' '); 2663688Sroot continue; 2673688Sroot } 2683688Sroot } else 2693688Sroot continue; 2703688Sroot } 2713688Sroot send(c); 2723688Sroot } while (c != '\r'); 2733688Sroot if (boolean(value(VERBOSE))) 2743688Sroot printf("\r%d", ++lcount); 2753688Sroot alarm(10); 2763688Sroot timedout = 0; 2773688Sroot do { /* wait for prompt */ 2783688Sroot read(FD, (char *)&c, 1); 2793688Sroot if (timedout || stop) { 2803688Sroot if (timedout) 2813688Sroot printf("\r\ntimed out at eol\r\n"); 2823688Sroot alarm(0); 2833688Sroot goto out; 2843688Sroot } 2853688Sroot } while ((c&0177) != character(value(PROMPT))); 2863688Sroot alarm(0); 2873688Sroot } 2883688Sroot out: 2893688Sroot if (lastc != '\n') 2903688Sroot send('\r'); 2913688Sroot for (pc = eofchars; *pc; pc++) 2923688Sroot send(*pc); 2933688Sroot stop_t = time(0); 2943688Sroot fclose(fd); 2953688Sroot signal(SIGINT, SIG_DFL); 2963688Sroot if (boolean(value(VERBOSE))) 2973688Sroot prtime(" lines transferred in ", stop_t-start_t); 2983688Sroot write(fildes[1], (char *)&ccc, 1); 2993688Sroot ioctl(0, TIOCSETC, &tchars); 3003688Sroot } 3013688Sroot 3023688Sroot /* 3033688Sroot * Cu-like put command 3043688Sroot */ 3053688Sroot cu_put(cc) 3063688Sroot char cc; 3073688Sroot { 3083688Sroot FILE *fd; 3093688Sroot char line[BUFSIZ]; 3103688Sroot int argc; 3113688Sroot 3123688Sroot if (prompt("[put] ", copyname)) 3133688Sroot return; 3143688Sroot if ((argc = args(copyname, argv)) < 1 || argc > 2) { 3153688Sroot printf("usage: <put> from [to]\r\n"); 3163688Sroot return; 3173688Sroot } 3183688Sroot if (argc == 1) 3193688Sroot argv[1] = argv[0]; 3203688Sroot if ((fd = fopen(argv[0], "r")) == NULL) { 3213688Sroot printf("%s: cannot open\r\n", argv[0]); 3223688Sroot return; 3233688Sroot } 3243688Sroot sprintf(line, "cat>'%s'\r", argv[1]); 3253688Sroot transmit(fd, "\04", line); 3263688Sroot } 3273688Sroot 3283688Sroot /* 3293688Sroot * FTP - send single character 3303688Sroot * wait for echo & handle timeout 3313688Sroot */ 3323688Sroot send(c) 3333688Sroot char c; 3343688Sroot { 3353688Sroot int cc; 3363688Sroot int retry = 0; 3373688Sroot 3383688Sroot cc = c; 3393688Sroot write(FD, (char *)&cc, 1); 3403688Sroot tryagain: 3413688Sroot timedout = 0; 3423688Sroot alarm(10); 3433688Sroot read(FD, (char *)&cc, 1); 3443688Sroot alarm(0); 3453688Sroot if (timedout) { 3463688Sroot printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 3473688Sroot if (retry++ > 3) 3483688Sroot return; 3493688Sroot write(FD, &null, 1); /* poke it */ 3503688Sroot goto tryagain; 3513688Sroot } 3523688Sroot } 3533688Sroot 3543688Sroot timeout() 3553688Sroot { 3563688Sroot signal(SIGALRM, timeout); 3573688Sroot timedout = 1; 3583688Sroot } 3593688Sroot 3603688Sroot #ifdef CONNECT 3613688Sroot /* 3623688Sroot * Fork a program with: 3633688Sroot * 0 <-> local tty in 3643688Sroot * 1 <-> local tty out 3653688Sroot * 2 <-> local tty out 3663688Sroot * 3 <-> remote tty in 3673688Sroot * 4 <-> remote tty out 3683688Sroot */ 3693688Sroot consh(c) 3703688Sroot { 3713688Sroot char buf[256]; 3723688Sroot int cpid, status, p; 3733688Sroot time_t start; 3743688Sroot 3753688Sroot putchar(c); 3763688Sroot if (prompt("Local command? ", buf)) 3773688Sroot return; 3783688Sroot kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 3793688Sroot signal(SIGINT, SIG_IGN); 3803688Sroot signal(SIGQUIT, SIG_IGN); 3813688Sroot ioctl(0, TIOCSETC, &defchars); 3823688Sroot read(repdes[0], (char *)&ccc, 1); 3833688Sroot /* 3843688Sroot * Set up file descriptors in the child and 3853688Sroot * let it go... 3863688Sroot */ 3873688Sroot if ((cpid = fork()) < 0) 3883688Sroot printf("can't fork!\r\n"); 3893688Sroot else if (cpid) { 3903688Sroot start = time(0); 3913688Sroot while ((p = wait(&status)) > 0 && p != cpid) 3923688Sroot ; 3933688Sroot } else { 3943688Sroot register int i; 3953688Sroot 3963688Sroot dup2(FD, 3); 3973688Sroot dup2(3, 4); 3983688Sroot for (i = 5; i < 20; i++) 3993688Sroot close(i); 4003688Sroot signal(SIGINT, SIG_DFL); 4013688Sroot signal(SIGQUIT, SIG_DFL); 4023688Sroot execute(buf); 4033688Sroot printf("can't find `%s'\r\n", buf); 4043688Sroot exit(0); 4053688Sroot } 4063688Sroot if (boolean(value(VERBOSE))) 4073688Sroot prtime("away for ", time(0)-start); 4083688Sroot write(fildes[1], (char *)&ccc, 1); 4093688Sroot ioctl(0, TIOCSETC, &tchars); 4103688Sroot signal(SIGINT, SIG_DFL); 4113688Sroot signal(SIGQUIT, SIG_DFL); 4123688Sroot } 4133688Sroot #endif 4143688Sroot 4153688Sroot /* 4163688Sroot * Escape to local shell 4173688Sroot */ 4183688Sroot shell() 4193688Sroot { 4203688Sroot int shpid, status; 4213688Sroot extern char **environ; 4223688Sroot char *cp; 4233688Sroot 4243688Sroot printf("[sh]\r\n"); 4253688Sroot signal(SIGINT, SIG_IGN); 4263688Sroot signal(SIGQUIT, SIG_IGN); 4273688Sroot unraw(); 4283688Sroot if (shpid = fork()) { 4293688Sroot while (shpid != wait(&status)); 4303688Sroot raw(); 4313688Sroot printf("\r\n!\r\n"); 4323688Sroot signal(SIGINT, SIG_DFL); 4333688Sroot signal(SIGQUIT, SIG_DFL); 4343688Sroot return; 4353688Sroot } else { 4363688Sroot signal(SIGQUIT, SIG_DFL); 4373688Sroot signal(SIGINT, SIG_DFL); 4383688Sroot if ((cp = rindex(value(SHELL), '/')) == NULL) 4393688Sroot cp = value(SHELL); 4403688Sroot else 4413688Sroot cp++; 4423688Sroot execl(value(SHELL), cp, 0); 4433688Sroot printf("\r\ncan't execl!\r\n"); 4443688Sroot exit(1); 4453688Sroot } 4463688Sroot } 4473688Sroot 4483688Sroot /* 4493688Sroot * TIPIN portion of scripting 4503688Sroot * initiate the conversation with TIPOUT 4513688Sroot */ 4523688Sroot setscript() 4533688Sroot { 4543688Sroot char c; 4553688Sroot /* 4563688Sroot * enable TIPOUT side for dialogue 4573688Sroot */ 4583688Sroot kill(pid, SIGEMT); 4593688Sroot if (boolean(value(SCRIPT))) 4603688Sroot write(fildes[1], value(RECORD), size(value(RECORD))); 4613688Sroot write(fildes[1], "\n", 1); 4623688Sroot /* 4633688Sroot * wait for TIPOUT to finish 4643688Sroot */ 4653688Sroot read(repdes[0], &c, 1); 4663688Sroot if (c == 'n') 4673688Sroot printf("can't create %s\r\n", value(RECORD)); 4683688Sroot } 4693688Sroot 4703688Sroot /* 4713688Sroot * Change current working directory of 4723688Sroot * local portion of tip 4733688Sroot */ 4743688Sroot chdirectory() 4753688Sroot { 4763688Sroot char dirname[80]; 4773688Sroot register char *cp = dirname; 4783688Sroot 4793688Sroot if (prompt("[cd] ", dirname)) 4803688Sroot if (stoprompt) 4813688Sroot return; 4823688Sroot else 4833688Sroot cp = value(HOME); 4843688Sroot if (chdir(cp) < 0) 4853688Sroot printf("%s: bad directory\r\n", cp); 4863688Sroot printf("!\r\n"); 4873688Sroot } 4883688Sroot 4893688Sroot finish() 4903688Sroot { 4913688Sroot kill(pid, SIGTERM); 4923688Sroot disconnect(); 4933688Sroot printf("\r\n[EOT]\r\n"); 4943688Sroot delock(uucplock); 4953688Sroot #ifdef VMUNIX 4963688Sroot ioctl(0, TIOCSETD, (char *)&odisc); 4973688Sroot #endif 4983688Sroot unraw(); 4993688Sroot exit(0); 5003688Sroot } 5013688Sroot 5023688Sroot intcopy() 5033688Sroot { 5043688Sroot raw(); 5053688Sroot quit = 1; 5063688Sroot } 5073688Sroot 5083688Sroot execute(s) 5093688Sroot char *s; 5103688Sroot { 5113688Sroot register char *cp; 5123688Sroot 5133688Sroot if ((cp = rindex(value(SHELL), '/')) == NULL) 5143688Sroot cp = value(SHELL); 5153688Sroot else 5163688Sroot cp++; 5173688Sroot execl(value(SHELL), cp, "-c", s, 0); 5183688Sroot } 5193688Sroot 5203688Sroot args(buf, a) 5213688Sroot char *buf, *a[]; 5223688Sroot { 5233688Sroot register char *p = buf, *start; 5243688Sroot register char **parg = a; 5253688Sroot register int n = 0; 5263688Sroot 5273688Sroot do { 5283688Sroot while (*p && (*p == ' ' || *p == '\t')) 5293688Sroot p++; 5303688Sroot start = p; 5313688Sroot if (*p) 5323688Sroot *parg = p; 5333688Sroot while (*p && (*p != ' ' && *p != '\t')) 5343688Sroot p++; 5353688Sroot if (p != start) 5363688Sroot parg++, n++; 5373688Sroot if (*p) 5383688Sroot *p++ = '\0'; 5393688Sroot } while (*p); 5403688Sroot 5413688Sroot return(n); 5423688Sroot } 5433688Sroot 5443688Sroot prtime(s, a) 5453688Sroot char *s; 5463688Sroot time_t a; 5473688Sroot { 5483688Sroot register i; 5493688Sroot int nums[3]; 5503688Sroot 5513688Sroot for (i = 0; i < 3; i++) { 5523688Sroot nums[i] = (int)(a % quant[i]); 5533688Sroot a /= quant[i]; 5543688Sroot } 5553688Sroot printf("%s", s); 5563688Sroot while (--i >= 0) 5573688Sroot if (nums[i]) 5583688Sroot printf("%d %s%c ", nums[i], sep[i], 5593688Sroot nums[i] == 1 ? '\0' : 's'); 5603688Sroot printf("\r\n!\r\n"); 5613688Sroot } 5623688Sroot 5633688Sroot variable() 5643688Sroot { 5653688Sroot char buf[256]; 5663688Sroot 5673688Sroot if (prompt("[set] ", buf)) 5683688Sroot return; 5693688Sroot vlex(buf); 5703688Sroot if (vtable[BEAUTIFY].v_access&CHANGED) { 5713688Sroot vtable[BEAUTIFY].v_access &= ~CHANGED; 5723688Sroot signal(pid, SIGSYS); 5733688Sroot } 5743688Sroot if (vtable[SCRIPT].v_access&CHANGED) { 5753688Sroot vtable[SCRIPT].v_access &= ~CHANGED; 5763688Sroot setscript(); 5773688Sroot } 5783688Sroot if (vtable[RECORD].v_access&CHANGED) { 5793688Sroot vtable[RECORD].v_access &= ~CHANGED; 5803688Sroot if (boolean(value(SCRIPT))) 5813688Sroot setscript(); 5823688Sroot } 5833688Sroot } 584*3822Ssam 585*3822Ssam /* 586*3822Ssam * Send a break. 587*3822Ssam * If we can't do it directly (as on VMUNIX), then simulate it. 588*3822Ssam */ 589*3822Ssam genbrk() 590*3822Ssam { 591*3822Ssam #ifdef VMUNIX 592*3822Ssam ioctl(FD, TIOCSBRK, NULL); 593*3822Ssam sleep(1); 594*3822Ssam ioctl(FD, TIOCCBRK, NULL); 595*3822Ssam #else 596*3822Ssam struct sgttyb ttbuf; 597*3822Ssam int sospeed; 598*3822Ssam 599*3822Ssam ioctl(FD, TIOCGETP, &ttbuf); 600*3822Ssam sospeed = ttbuf.sg_ospeed; 601*3822Ssam ttbuf.sg_ospeed = B150; 602*3822Ssam ioctl(FD, TIOCSETP, &ttbuf); 603*3822Ssam write(FD, "\0\0\0\0\0\0\0\0\0\0", 10); 604*3822Ssam ttbuf.sg_ospeed = sospeed; 605*3822Ssam ioctl(FD, TIOCSETP, &ttbuf); 606*3822Ssam write(FD, "@", 1); 607*3822Ssam #endif 608*3822Ssam } 609