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