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