1*3688Sroot /* cmds.c 4.1 81/05/09 */ 2*3688Sroot #include "tip.h" 3*3688Sroot /* 4*3688Sroot * tip 5*3688Sroot * 6*3688Sroot * miscellaneous commands 7*3688Sroot */ 8*3688Sroot 9*3688Sroot int quant[] = { 60, 60, 24 }; 10*3688Sroot 11*3688Sroot char null = '\0'; 12*3688Sroot char *sep[] = { "second", "minute", "hour" }; 13*3688Sroot static char *argv[10]; /* argument vector for take and put */ 14*3688Sroot 15*3688Sroot int timeout(); /* timeout function called on alarm */ 16*3688Sroot int stopsnd(); /* SIGINT handler during file transfers */ 17*3688Sroot int intprompt(); /* used in handling SIG_INT during prompt */ 18*3688Sroot int intcopy(); /* interrupt routine for file transfers */ 19*3688Sroot 20*3688Sroot /* 21*3688Sroot * FTP - remote ==> local 22*3688Sroot * get a file from the remote host 23*3688Sroot */ 24*3688Sroot getfl(c) 25*3688Sroot char c; 26*3688Sroot { 27*3688Sroot char buf[256]; 28*3688Sroot 29*3688Sroot putchar(c); 30*3688Sroot /* 31*3688Sroot * get the UNIX receiving file's name 32*3688Sroot */ 33*3688Sroot if (prompt("Local file name? ", copyname)) 34*3688Sroot return; 35*3688Sroot if ((sfd = creat(copyname, 0666)) < 0) { 36*3688Sroot printf("\r\n%s: cannot creat\r\n", copyname); 37*3688Sroot return; 38*3688Sroot } 39*3688Sroot 40*3688Sroot /* 41*3688Sroot * collect parameters 42*3688Sroot */ 43*3688Sroot if (prompt("List command for remote system? ", buf)) { 44*3688Sroot unlink(copyname); 45*3688Sroot return; 46*3688Sroot } 47*3688Sroot transfer(buf, sfd, value(EOFREAD)); 48*3688Sroot } 49*3688Sroot 50*3688Sroot /* 51*3688Sroot * Cu-like take command 52*3688Sroot */ 53*3688Sroot cu_take(cc) 54*3688Sroot char cc; 55*3688Sroot { 56*3688Sroot int fd, argc; 57*3688Sroot char line[BUFSIZ]; 58*3688Sroot 59*3688Sroot if (prompt("[take] ", copyname)) 60*3688Sroot return; 61*3688Sroot if ((argc = args(copyname, argv)) < 1 || argc > 2) { 62*3688Sroot printf("usage: <take> from [to]\r\n"); 63*3688Sroot return; 64*3688Sroot } 65*3688Sroot if (argc == 1) 66*3688Sroot argv[1] = argv[0]; 67*3688Sroot if ((fd = creat(argv[1], 0666)) < 0) { 68*3688Sroot printf("\r\n%s: cannot create\r\n", argv[1]); 69*3688Sroot return; 70*3688Sroot } 71*3688Sroot sprintf(line, "cat '%s';echo \01", argv[0]); 72*3688Sroot transfer(line, fd, "\01"); 73*3688Sroot } 74*3688Sroot 75*3688Sroot /* 76*3688Sroot * Bulk transfer routine -- 77*3688Sroot * used by getfl(), cu_take(), and pipefile() 78*3688Sroot */ 79*3688Sroot transfer(buf, fd, eofchars) 80*3688Sroot char *buf, *eofchars; 81*3688Sroot { 82*3688Sroot register int ct; 83*3688Sroot char c, buffer[BUFSIZ]; 84*3688Sroot register char *p = buffer; 85*3688Sroot register int cnt, eof; 86*3688Sroot time_t start; 87*3688Sroot 88*3688Sroot write(FD, buf, size(buf)); 89*3688Sroot quit = 0; 90*3688Sroot signal(SIGINT, intcopy); 91*3688Sroot kill(pid, SIGIOT); 92*3688Sroot read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 93*3688Sroot 94*3688Sroot /* 95*3688Sroot * finish command 96*3688Sroot */ 97*3688Sroot write(FD, "\r", 1); 98*3688Sroot do 99*3688Sroot read(FD, &c, 1); 100*3688Sroot while ((c&0177) != '\n'); 101*3688Sroot ioctl(0, TIOCSETC, &defchars); 102*3688Sroot 103*3688Sroot start = time(0); 104*3688Sroot for (ct = 0; !quit;) { 105*3688Sroot eof = read(FD, &c, 1) <= 0; 106*3688Sroot c &= 0177; 107*3688Sroot if (quit) 108*3688Sroot continue; 109*3688Sroot if (eof || any(c, eofchars)) 110*3688Sroot break; 111*3688Sroot if (c == 0) 112*3688Sroot continue; /* ignore nulls */ 113*3688Sroot if (c == '\r') 114*3688Sroot continue; 115*3688Sroot *p++ = c; 116*3688Sroot 117*3688Sroot if (c == '\n' && boolean(value(VERBOSE))) 118*3688Sroot printf("\r%d", ++ct); 119*3688Sroot if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) { 120*3688Sroot if (write(fd, buffer, cnt) != cnt) { 121*3688Sroot printf("\r\nwrite error\r\n"); 122*3688Sroot quit = 1; 123*3688Sroot } 124*3688Sroot p = buffer; 125*3688Sroot } 126*3688Sroot } 127*3688Sroot if (cnt = (p-buffer)) 128*3688Sroot if (write(fd, buffer, cnt) != cnt) 129*3688Sroot printf("\r\nwrite error\r\n"); 130*3688Sroot 131*3688Sroot if (boolean(value(VERBOSE))) 132*3688Sroot prtime(" lines transferred in ", time(0)-start); 133*3688Sroot ioctl(0, TIOCSETC, &tchars); 134*3688Sroot write(fildes[1], (char *)&ccc, 1); 135*3688Sroot signal(SIGINT, SIG_DFL); 136*3688Sroot close(fd); 137*3688Sroot } 138*3688Sroot 139*3688Sroot /* 140*3688Sroot * FTP - remote ==> local process 141*3688Sroot * send remote input to local process via pipe 142*3688Sroot */ 143*3688Sroot pipefile() 144*3688Sroot { 145*3688Sroot int cpid, pdes[2]; 146*3688Sroot char buf[256]; 147*3688Sroot int status, p; 148*3688Sroot extern int errno; 149*3688Sroot 150*3688Sroot if (prompt("Local command? ", buf)) 151*3688Sroot return; 152*3688Sroot 153*3688Sroot if (pipe(pdes)) { 154*3688Sroot printf("can't establish pipe\r\n"); 155*3688Sroot return; 156*3688Sroot } 157*3688Sroot 158*3688Sroot if ((cpid = fork()) < 0) { 159*3688Sroot printf("can't fork!\r\n"); 160*3688Sroot return; 161*3688Sroot } else if (cpid) { 162*3688Sroot if (prompt("List command for remote system? ", buf)) { 163*3688Sroot close(pdes[0]), close(pdes[1]); 164*3688Sroot kill (cpid, SIGKILL); 165*3688Sroot } else { 166*3688Sroot close(pdes[0]); 167*3688Sroot signal(SIGPIPE, intcopy); 168*3688Sroot transfer(buf, pdes[1], value(EOFREAD)); 169*3688Sroot signal(SIGPIPE, SIG_DFL); 170*3688Sroot while ((p = wait(&status)) > 0 && p != cpid) 171*3688Sroot ; 172*3688Sroot } 173*3688Sroot } else { 174*3688Sroot register int f; 175*3688Sroot 176*3688Sroot dup2(pdes[0], 0); 177*3688Sroot close(pdes[0]); 178*3688Sroot for (f = 3; f < 20; f++) 179*3688Sroot close(f); 180*3688Sroot execute(buf); 181*3688Sroot printf("can't execl!\r\n"); 182*3688Sroot exit(0); 183*3688Sroot } 184*3688Sroot } 185*3688Sroot 186*3688Sroot /* 187*3688Sroot * Interrupt service routine for FTP 188*3688Sroot */ 189*3688Sroot stopsnd() 190*3688Sroot { 191*3688Sroot stop = 1; 192*3688Sroot signal(SIGINT, SIG_IGN); 193*3688Sroot } 194*3688Sroot 195*3688Sroot /* 196*3688Sroot * FTP - local ==> remote 197*3688Sroot * send local file to remote host 198*3688Sroot * terminate transmission with pseudo EOF sequence 199*3688Sroot */ 200*3688Sroot sendfile(cc) 201*3688Sroot char cc; 202*3688Sroot { 203*3688Sroot FILE *fd; 204*3688Sroot 205*3688Sroot putchar(cc); 206*3688Sroot /* 207*3688Sroot * get file name 208*3688Sroot */ 209*3688Sroot if (prompt("Local file name? ", fname)) 210*3688Sroot return; 211*3688Sroot 212*3688Sroot /* 213*3688Sroot * look up file 214*3688Sroot */ 215*3688Sroot if ((fd = fopen(fname, "r")) == NULL) { 216*3688Sroot printf("%s: cannot open\r\n", fname); 217*3688Sroot return; 218*3688Sroot } 219*3688Sroot transmit(fd, value(EOFWRITE), NULL); 220*3688Sroot } 221*3688Sroot 222*3688Sroot /* 223*3688Sroot * Bulk transfer routine to remote host -- 224*3688Sroot * used by sendfile() and cu_put() 225*3688Sroot */ 226*3688Sroot transmit(fd, eofchars, command) 227*3688Sroot FILE *fd; 228*3688Sroot char *eofchars, *command; 229*3688Sroot { 230*3688Sroot char *pc, lastc; 231*3688Sroot int c, ccount, lcount; 232*3688Sroot time_t start_t, stop_t; 233*3688Sroot 234*3688Sroot kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 235*3688Sroot signal(SIGINT, stopsnd); 236*3688Sroot stop = 0; 237*3688Sroot ioctl(0, TIOCSETC, &defchars); 238*3688Sroot read(repdes[0], (char *)&ccc, 1); 239*3688Sroot if (command != NULL) { 240*3688Sroot for (pc = command; *pc; pc++) 241*3688Sroot send(*pc); 242*3688Sroot read(FD, (char *)&c, 1); /* trailing \n */ 243*3688Sroot } 244*3688Sroot lcount = 0; 245*3688Sroot lastc = '\0'; 246*3688Sroot start_t = time(0); 247*3688Sroot while(1) { 248*3688Sroot ccount = 0; 249*3688Sroot do { 250*3688Sroot c = getc(fd); 251*3688Sroot if (stop) 252*3688Sroot goto out; 253*3688Sroot if (c == EOF) 254*3688Sroot goto out; 255*3688Sroot if (c == 0177) 256*3688Sroot continue; 257*3688Sroot lastc = c; 258*3688Sroot if (c < 040) { 259*3688Sroot if (c == '\n') 260*3688Sroot c = '\r'; 261*3688Sroot else if (c == '\t') { 262*3688Sroot if (boolean(value(TABEXPAND))) { 263*3688Sroot send(' '); 264*3688Sroot while((++ccount % 8) != 0) 265*3688Sroot send(' '); 266*3688Sroot continue; 267*3688Sroot } 268*3688Sroot } else 269*3688Sroot continue; 270*3688Sroot } 271*3688Sroot send(c); 272*3688Sroot } while (c != '\r'); 273*3688Sroot if (boolean(value(VERBOSE))) 274*3688Sroot printf("\r%d", ++lcount); 275*3688Sroot alarm(10); 276*3688Sroot timedout = 0; 277*3688Sroot do { /* wait for prompt */ 278*3688Sroot read(FD, (char *)&c, 1); 279*3688Sroot if (timedout || stop) { 280*3688Sroot if (timedout) 281*3688Sroot printf("\r\ntimed out at eol\r\n"); 282*3688Sroot alarm(0); 283*3688Sroot goto out; 284*3688Sroot } 285*3688Sroot } while ((c&0177) != character(value(PROMPT))); 286*3688Sroot alarm(0); 287*3688Sroot } 288*3688Sroot out: 289*3688Sroot if (lastc != '\n') 290*3688Sroot send('\r'); 291*3688Sroot for (pc = eofchars; *pc; pc++) 292*3688Sroot send(*pc); 293*3688Sroot stop_t = time(0); 294*3688Sroot fclose(fd); 295*3688Sroot signal(SIGINT, SIG_DFL); 296*3688Sroot if (boolean(value(VERBOSE))) 297*3688Sroot prtime(" lines transferred in ", stop_t-start_t); 298*3688Sroot write(fildes[1], (char *)&ccc, 1); 299*3688Sroot ioctl(0, TIOCSETC, &tchars); 300*3688Sroot } 301*3688Sroot 302*3688Sroot /* 303*3688Sroot * Cu-like put command 304*3688Sroot */ 305*3688Sroot cu_put(cc) 306*3688Sroot char cc; 307*3688Sroot { 308*3688Sroot FILE *fd; 309*3688Sroot char line[BUFSIZ]; 310*3688Sroot int argc; 311*3688Sroot 312*3688Sroot if (prompt("[put] ", copyname)) 313*3688Sroot return; 314*3688Sroot if ((argc = args(copyname, argv)) < 1 || argc > 2) { 315*3688Sroot printf("usage: <put> from [to]\r\n"); 316*3688Sroot return; 317*3688Sroot } 318*3688Sroot if (argc == 1) 319*3688Sroot argv[1] = argv[0]; 320*3688Sroot if ((fd = fopen(argv[0], "r")) == NULL) { 321*3688Sroot printf("%s: cannot open\r\n", argv[0]); 322*3688Sroot return; 323*3688Sroot } 324*3688Sroot sprintf(line, "cat>'%s'\r", argv[1]); 325*3688Sroot transmit(fd, "\04", line); 326*3688Sroot } 327*3688Sroot 328*3688Sroot /* 329*3688Sroot * FTP - send single character 330*3688Sroot * wait for echo & handle timeout 331*3688Sroot */ 332*3688Sroot send(c) 333*3688Sroot char c; 334*3688Sroot { 335*3688Sroot int cc; 336*3688Sroot int retry = 0; 337*3688Sroot 338*3688Sroot cc = c; 339*3688Sroot write(FD, (char *)&cc, 1); 340*3688Sroot tryagain: 341*3688Sroot timedout = 0; 342*3688Sroot alarm(10); 343*3688Sroot read(FD, (char *)&cc, 1); 344*3688Sroot alarm(0); 345*3688Sroot if (timedout) { 346*3688Sroot printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 347*3688Sroot if (retry++ > 3) 348*3688Sroot return; 349*3688Sroot write(FD, &null, 1); /* poke it */ 350*3688Sroot goto tryagain; 351*3688Sroot } 352*3688Sroot } 353*3688Sroot 354*3688Sroot timeout() 355*3688Sroot { 356*3688Sroot signal(SIGALRM, timeout); 357*3688Sroot timedout = 1; 358*3688Sroot } 359*3688Sroot 360*3688Sroot #ifdef CONNECT 361*3688Sroot /* 362*3688Sroot * Fork a program with: 363*3688Sroot * 0 <-> local tty in 364*3688Sroot * 1 <-> local tty out 365*3688Sroot * 2 <-> local tty out 366*3688Sroot * 3 <-> remote tty in 367*3688Sroot * 4 <-> remote tty out 368*3688Sroot */ 369*3688Sroot consh(c) 370*3688Sroot { 371*3688Sroot char buf[256]; 372*3688Sroot int cpid, status, p; 373*3688Sroot time_t start; 374*3688Sroot 375*3688Sroot putchar(c); 376*3688Sroot if (prompt("Local command? ", buf)) 377*3688Sroot return; 378*3688Sroot kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 379*3688Sroot signal(SIGINT, SIG_IGN); 380*3688Sroot signal(SIGQUIT, SIG_IGN); 381*3688Sroot ioctl(0, TIOCSETC, &defchars); 382*3688Sroot read(repdes[0], (char *)&ccc, 1); 383*3688Sroot /* 384*3688Sroot * Set up file descriptors in the child and 385*3688Sroot * let it go... 386*3688Sroot */ 387*3688Sroot if ((cpid = fork()) < 0) 388*3688Sroot printf("can't fork!\r\n"); 389*3688Sroot else if (cpid) { 390*3688Sroot start = time(0); 391*3688Sroot while ((p = wait(&status)) > 0 && p != cpid) 392*3688Sroot ; 393*3688Sroot } else { 394*3688Sroot register int i; 395*3688Sroot 396*3688Sroot dup2(FD, 3); 397*3688Sroot dup2(3, 4); 398*3688Sroot for (i = 5; i < 20; i++) 399*3688Sroot close(i); 400*3688Sroot signal(SIGINT, SIG_DFL); 401*3688Sroot signal(SIGQUIT, SIG_DFL); 402*3688Sroot execute(buf); 403*3688Sroot printf("can't find `%s'\r\n", buf); 404*3688Sroot exit(0); 405*3688Sroot } 406*3688Sroot if (boolean(value(VERBOSE))) 407*3688Sroot prtime("away for ", time(0)-start); 408*3688Sroot write(fildes[1], (char *)&ccc, 1); 409*3688Sroot ioctl(0, TIOCSETC, &tchars); 410*3688Sroot signal(SIGINT, SIG_DFL); 411*3688Sroot signal(SIGQUIT, SIG_DFL); 412*3688Sroot } 413*3688Sroot #endif 414*3688Sroot 415*3688Sroot /* 416*3688Sroot * Escape to local shell 417*3688Sroot */ 418*3688Sroot shell() 419*3688Sroot { 420*3688Sroot int shpid, status; 421*3688Sroot extern char **environ; 422*3688Sroot char *cp; 423*3688Sroot 424*3688Sroot printf("[sh]\r\n"); 425*3688Sroot signal(SIGINT, SIG_IGN); 426*3688Sroot signal(SIGQUIT, SIG_IGN); 427*3688Sroot unraw(); 428*3688Sroot if (shpid = fork()) { 429*3688Sroot while (shpid != wait(&status)); 430*3688Sroot raw(); 431*3688Sroot printf("\r\n!\r\n"); 432*3688Sroot signal(SIGINT, SIG_DFL); 433*3688Sroot signal(SIGQUIT, SIG_DFL); 434*3688Sroot return; 435*3688Sroot } else { 436*3688Sroot signal(SIGQUIT, SIG_DFL); 437*3688Sroot signal(SIGINT, SIG_DFL); 438*3688Sroot if ((cp = rindex(value(SHELL), '/')) == NULL) 439*3688Sroot cp = value(SHELL); 440*3688Sroot else 441*3688Sroot cp++; 442*3688Sroot execl(value(SHELL), cp, 0); 443*3688Sroot printf("\r\ncan't execl!\r\n"); 444*3688Sroot exit(1); 445*3688Sroot } 446*3688Sroot } 447*3688Sroot 448*3688Sroot /* 449*3688Sroot * TIPIN portion of scripting 450*3688Sroot * initiate the conversation with TIPOUT 451*3688Sroot */ 452*3688Sroot setscript() 453*3688Sroot { 454*3688Sroot char c; 455*3688Sroot /* 456*3688Sroot * enable TIPOUT side for dialogue 457*3688Sroot */ 458*3688Sroot kill(pid, SIGEMT); 459*3688Sroot if (boolean(value(SCRIPT))) 460*3688Sroot write(fildes[1], value(RECORD), size(value(RECORD))); 461*3688Sroot write(fildes[1], "\n", 1); 462*3688Sroot /* 463*3688Sroot * wait for TIPOUT to finish 464*3688Sroot */ 465*3688Sroot read(repdes[0], &c, 1); 466*3688Sroot if (c == 'n') 467*3688Sroot printf("can't create %s\r\n", value(RECORD)); 468*3688Sroot } 469*3688Sroot 470*3688Sroot /* 471*3688Sroot * Change current working directory of 472*3688Sroot * local portion of tip 473*3688Sroot */ 474*3688Sroot chdirectory() 475*3688Sroot { 476*3688Sroot char dirname[80]; 477*3688Sroot register char *cp = dirname; 478*3688Sroot 479*3688Sroot if (prompt("[cd] ", dirname)) 480*3688Sroot if (stoprompt) 481*3688Sroot return; 482*3688Sroot else 483*3688Sroot cp = value(HOME); 484*3688Sroot if (chdir(cp) < 0) 485*3688Sroot printf("%s: bad directory\r\n", cp); 486*3688Sroot printf("!\r\n"); 487*3688Sroot } 488*3688Sroot 489*3688Sroot finish() 490*3688Sroot { 491*3688Sroot kill(pid, SIGTERM); 492*3688Sroot disconnect(); 493*3688Sroot printf("\r\n[EOT]\r\n"); 494*3688Sroot delock(uucplock); 495*3688Sroot #ifdef VMUNIX 496*3688Sroot ioctl(0, TIOCSETD, (char *)&odisc); 497*3688Sroot #endif 498*3688Sroot unraw(); 499*3688Sroot exit(0); 500*3688Sroot } 501*3688Sroot 502*3688Sroot intcopy() 503*3688Sroot { 504*3688Sroot raw(); 505*3688Sroot quit = 1; 506*3688Sroot } 507*3688Sroot 508*3688Sroot execute(s) 509*3688Sroot char *s; 510*3688Sroot { 511*3688Sroot register char *cp; 512*3688Sroot 513*3688Sroot if ((cp = rindex(value(SHELL), '/')) == NULL) 514*3688Sroot cp = value(SHELL); 515*3688Sroot else 516*3688Sroot cp++; 517*3688Sroot execl(value(SHELL), cp, "-c", s, 0); 518*3688Sroot } 519*3688Sroot 520*3688Sroot args(buf, a) 521*3688Sroot char *buf, *a[]; 522*3688Sroot { 523*3688Sroot register char *p = buf, *start; 524*3688Sroot register char **parg = a; 525*3688Sroot register int n = 0; 526*3688Sroot 527*3688Sroot do { 528*3688Sroot while (*p && (*p == ' ' || *p == '\t')) 529*3688Sroot p++; 530*3688Sroot start = p; 531*3688Sroot if (*p) 532*3688Sroot *parg = p; 533*3688Sroot while (*p && (*p != ' ' && *p != '\t')) 534*3688Sroot p++; 535*3688Sroot if (p != start) 536*3688Sroot parg++, n++; 537*3688Sroot if (*p) 538*3688Sroot *p++ = '\0'; 539*3688Sroot } while (*p); 540*3688Sroot 541*3688Sroot return(n); 542*3688Sroot } 543*3688Sroot 544*3688Sroot prtime(s, a) 545*3688Sroot char *s; 546*3688Sroot time_t a; 547*3688Sroot { 548*3688Sroot register i; 549*3688Sroot int nums[3]; 550*3688Sroot 551*3688Sroot for (i = 0; i < 3; i++) { 552*3688Sroot nums[i] = (int)(a % quant[i]); 553*3688Sroot a /= quant[i]; 554*3688Sroot } 555*3688Sroot printf("%s", s); 556*3688Sroot while (--i >= 0) 557*3688Sroot if (nums[i]) 558*3688Sroot printf("%d %s%c ", nums[i], sep[i], 559*3688Sroot nums[i] == 1 ? '\0' : 's'); 560*3688Sroot printf("\r\n!\r\n"); 561*3688Sroot } 562*3688Sroot 563*3688Sroot variable() 564*3688Sroot { 565*3688Sroot char buf[256]; 566*3688Sroot 567*3688Sroot if (prompt("[set] ", buf)) 568*3688Sroot return; 569*3688Sroot vlex(buf); 570*3688Sroot if (vtable[BEAUTIFY].v_access&CHANGED) { 571*3688Sroot vtable[BEAUTIFY].v_access &= ~CHANGED; 572*3688Sroot signal(pid, SIGSYS); 573*3688Sroot } 574*3688Sroot if (vtable[SCRIPT].v_access&CHANGED) { 575*3688Sroot vtable[SCRIPT].v_access &= ~CHANGED; 576*3688Sroot setscript(); 577*3688Sroot } 578*3688Sroot if (vtable[RECORD].v_access&CHANGED) { 579*3688Sroot vtable[RECORD].v_access &= ~CHANGED; 580*3688Sroot if (boolean(value(SCRIPT))) 581*3688Sroot setscript(); 582*3688Sroot } 583*3688Sroot } 584