1161754Sru/* $OpenBSD: cmds.c,v 1.26 2006/06/06 23:24:52 deraadt Exp $ */ 288276Smarkm/* $NetBSD: cmds.c,v 1.7 1997/02/11 09:24:03 mrg Exp $ */ 388276Smarkm 47527Sjkh/* 57527Sjkh * Copyright (c) 1983, 1993 67527Sjkh * The Regents of the University of California. All rights reserved. 77527Sjkh * 87527Sjkh * Redistribution and use in source and binary forms, with or without 97527Sjkh * modification, are permitted provided that the following conditions 107527Sjkh * are met: 117527Sjkh * 1. Redistributions of source code must retain the above copyright 127527Sjkh * notice, this list of conditions and the following disclaimer. 137527Sjkh * 2. Redistributions in binary form must reproduce the above copyright 147527Sjkh * notice, this list of conditions and the following disclaimer in the 157527Sjkh * documentation and/or other materials provided with the distribution. 16161754Sru * 3. Neither the name of the University nor the names of its contributors 177527Sjkh * may be used to endorse or promote products derived from this software 187527Sjkh * without specific prior written permission. 197527Sjkh * 207527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 217527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 227527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 237527Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 247527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 257527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 267527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 277527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 287527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 297527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 307527Sjkh * SUCH DAMAGE. 317527Sjkh */ 327527Sjkh 3388276Smarkm#include <sys/cdefs.h> 3488276Smarkm__FBSDID("$FreeBSD$"); 3588276Smarkm 367527Sjkh#ifndef lint 3728365Scharnier#if 0 387527Sjkhstatic char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; 39161754Srustatic const char rcsid[] = "$OpenBSD: cmds.c,v 1.26 2006/06/06 23:24:52 deraadt Exp $"; 4028365Scharnier#endif 417527Sjkh#endif /* not lint */ 427527Sjkh 437527Sjkh#include "tip.h" 447527Sjkh#include "pathnames.h" 457527Sjkh 4688276Smarkm#include <vis.h> 477527Sjkh 487527Sjkh/* 497527Sjkh * tip 507527Sjkh * 517527Sjkh * miscellaneous commands 527527Sjkh */ 537527Sjkh 547527Sjkhint quant[] = { 60, 60, 24 }; 557527Sjkh 567527Sjkhchar null = '\0'; 577527Sjkhchar *sep[] = { "second", "minute", "hour" }; 587527Sjkhstatic char *argv[10]; /* argument vector for take and put */ 597527Sjkh 60161754Srustatic void transfer(char *, int, char *); 61161754Srustatic void stopsnd(int); /* SIGINT handler during file transfers */ 62161754Srustatic void intcopy(int); /* interrupt routine for file transfers */ 63161754Srustatic void transmit(FILE *, char *, char *); 64161754Srustatic void send(int); 65161754Srustatic void execute(char *); 66161754Srustatic int args(char *, char **, int); 67161754Srustatic void prtime(char *, time_t); 68161754Srustatic void tandem(char *); 69161754Srustatic void hardwareflow(char *); 70161754Sruvoid linedisc(char *); 71161754Srustatic int anyof(char *, char *); 7228788Seivind 737527Sjkh/* 747527Sjkh * FTP - remote ==> local 757527Sjkh * get a file from the remote host 767527Sjkh */ 7728365Scharniervoid 78161754Srugetfl(int c) 797527Sjkh{ 80161754Sru char buf[256], *cp; 81161754Sru 827527Sjkh putchar(c); 837527Sjkh /* 847527Sjkh * get the UNIX receiving file's name 857527Sjkh */ 8628606Simp if (prompt("Local file name? ", copyname, sizeof(copyname))) 877527Sjkh return; 887527Sjkh cp = expand(copyname); 897527Sjkh if ((sfd = creat(cp, 0666)) < 0) { 907527Sjkh printf("\r\n%s: cannot creat\r\n", copyname); 917527Sjkh return; 927527Sjkh } 93161754Sru 947527Sjkh /* 957527Sjkh * collect parameters 967527Sjkh */ 9728606Simp if (prompt("List command for remote system? ", buf, sizeof(buf))) { 987527Sjkh unlink(copyname); 997527Sjkh return; 1007527Sjkh } 1017527Sjkh transfer(buf, sfd, value(EOFREAD)); 1027527Sjkh} 1037527Sjkh 1047527Sjkh/* 1057527Sjkh * Cu-like take command 1067527Sjkh */ 10728365Scharniervoid 108161754Srucu_take(int c) 1097527Sjkh{ 1107527Sjkh int fd, argc; 111161754Sru char line[BUFSIZ], *cp; 1127527Sjkh 11328606Simp if (prompt("[take] ", copyname, sizeof(copyname))) 1147527Sjkh return; 11588276Smarkm if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || 11688276Smarkm argc > 2) { 1177527Sjkh printf("usage: <take> from [to]\r\n"); 1187527Sjkh return; 1197527Sjkh } 1207527Sjkh if (argc == 1) 1217527Sjkh argv[1] = argv[0]; 1227527Sjkh cp = expand(argv[1]); 1237527Sjkh if ((fd = creat(cp, 0666)) < 0) { 1247527Sjkh printf("\r\n%s: cannot create\r\n", argv[1]); 1257527Sjkh return; 1267527Sjkh } 127161754Sru (void)snprintf(line, sizeof(line), "cat %s;echo ''|tr '\\012' '\\01'", argv[0]); 12888276Smarkm transfer(line, fd, "\01"); 1297527Sjkh} 1307527Sjkh 13188276Smarkmstatic jmp_buf intbuf; 1327527Sjkh 1337527Sjkh/* 1347527Sjkh * Bulk transfer routine -- 1357527Sjkh * used by getfl(), cu_take(), and pipefile() 1367527Sjkh */ 137161754Srustatic void 138161754Srutransfer(char *buf, int fd, char *eofchars) 1397527Sjkh{ 140161754Sru int ct, eof; 14188276Smarkm char c, buffer[BUFSIZ]; 14288276Smarkm char *p = buffer; 143161754Sru size_t cnt; 1447527Sjkh time_t start; 1457527Sjkh sig_t f; 1467527Sjkh char r; 1477527Sjkh 148161754Sru if (number(value(FRAMESIZE)) > BUFSIZ || number(value(FRAMESIZE)) < 1) { 149161754Sru printf("framesize must be >= 1 and <= %d\r\n", BUFSIZ); 150161754Sru close(fd); 151161754Sru return; 152161754Sru } 153161754Sru 15488276Smarkm parwrite(FD, buf, size(buf)); 1557527Sjkh quit = 0; 156161754Sru kill(tipout_pid, SIGIOT); 1577527Sjkh read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 158161754Sru 1597527Sjkh /* 1607527Sjkh * finish command 1617527Sjkh */ 1627527Sjkh r = '\r'; 16388276Smarkm parwrite(FD, &r, 1); 1647527Sjkh do 165161754Sru read(FD, &c, 1); 16688276Smarkm while ((c&STRIP_PAR) != '\n'); 16788276Smarkm tcsetattr(0, TCSAFLUSH, &defchars); 168161754Sru 1697527Sjkh (void) setjmp(intbuf); 1707527Sjkh f = signal(SIGINT, intcopy); 1717527Sjkh start = time(0); 1727527Sjkh for (ct = 0; !quit;) { 1737527Sjkh eof = read(FD, &c, 1) <= 0; 17488276Smarkm c &= STRIP_PAR; 1757527Sjkh if (quit) 1767527Sjkh continue; 1777527Sjkh if (eof || any(c, eofchars)) 1787527Sjkh break; 1797527Sjkh if (c == 0) 1807527Sjkh continue; /* ignore nulls */ 1817527Sjkh if (c == '\r') 1827527Sjkh continue; 18388276Smarkm *p++ = c; 18488276Smarkm 18588276Smarkm if (c == '\n' && boolean(value(VERBOSE))) 1867527Sjkh printf("\r%d", ++ct); 187161781Sru if ((cnt = (p-buffer)) == (size_t)number(value(FRAMESIZE))) { 188161781Sru if ((size_t)write(fd, buffer, cnt) != cnt) { 18988276Smarkm printf("\r\nwrite error\r\n"); 19088276Smarkm quit = 1; 19188276Smarkm } 19288276Smarkm p = buffer; 19388276Smarkm } 1947527Sjkh } 19588276Smarkm if ((cnt = (p-buffer))) 196161781Sru if ((size_t)write(fd, buffer, cnt) != cnt) 19788276Smarkm printf("\r\nwrite error\r\n"); 19888276Smarkm 19988276Smarkm if (boolean(value(VERBOSE))) 2007527Sjkh prtime(" lines transferred in ", time(0)-start); 20188276Smarkm tcsetattr(0, TCSAFLUSH, &term); 2027527Sjkh write(fildes[1], (char *)&ccc, 1); 2037527Sjkh signal(SIGINT, f); 20488276Smarkm close(fd); 2057527Sjkh} 2067527Sjkh 2077527Sjkh/* 2087527Sjkh * FTP - remote ==> local process 2097527Sjkh * send remote input to local process via pipe 2107527Sjkh */ 211161754Sru/*ARGSUSED*/ 21228365Scharniervoid 213161754Srupipefile(int c) 2147527Sjkh{ 215161754Sru int pdes[2]; 2167527Sjkh char buf[256]; 2177527Sjkh int status, p; 218161754Sru pid_t cpid; 2197527Sjkh 22028606Simp if (prompt("Local command? ", buf, sizeof(buf))) 2217527Sjkh return; 2227527Sjkh 2237527Sjkh if (pipe(pdes)) { 2247527Sjkh printf("can't establish pipe\r\n"); 2257527Sjkh return; 2267527Sjkh } 2277527Sjkh 2287527Sjkh if ((cpid = fork()) < 0) { 2297527Sjkh printf("can't fork!\r\n"); 2307527Sjkh return; 2317527Sjkh } else if (cpid) { 23228606Simp if (prompt("List command for remote system? ", buf, sizeof(buf))) { 2337527Sjkh close(pdes[0]), close(pdes[1]); 2347527Sjkh kill (cpid, SIGKILL); 2357527Sjkh } else { 2367527Sjkh close(pdes[0]); 2377527Sjkh signal(SIGPIPE, intcopy); 2387527Sjkh transfer(buf, pdes[1], value(EOFREAD)); 2397527Sjkh signal(SIGPIPE, SIG_DFL); 2407527Sjkh while ((p = wait(&status)) > 0 && p != cpid) 2417527Sjkh ; 2427527Sjkh } 2437527Sjkh } else { 24488276Smarkm int f; 2457527Sjkh 2467527Sjkh dup2(pdes[0], 0); 2477527Sjkh close(pdes[0]); 2487527Sjkh for (f = 3; f < 20; f++) 2497527Sjkh close(f); 2507527Sjkh execute(buf); 2517527Sjkh printf("can't execl!\r\n"); 2527527Sjkh exit(0); 2537527Sjkh } 2547527Sjkh} 2557527Sjkh 2567527Sjkh/* 2577527Sjkh * Interrupt service routine for FTP 2587527Sjkh */ 259161754Sru/*ARGSUSED*/ 260161754Srustatic void 261161754Srustopsnd(int signo) 2627527Sjkh{ 2637527Sjkh stop = 1; 2647527Sjkh signal(SIGINT, SIG_IGN); 2657527Sjkh} 2667527Sjkh 2677527Sjkh/* 2687527Sjkh * FTP - local ==> remote 2697527Sjkh * send local file to remote host 2707527Sjkh * terminate transmission with pseudo EOF sequence 2717527Sjkh */ 27228365Scharniervoid 273161754Srusendfile(int c) 2747527Sjkh{ 275161754Sru FILE *fp; 2767527Sjkh char *fnamex; 2777527Sjkh 278161754Sru putchar(c); 2797527Sjkh /* 2807527Sjkh * get file name 2817527Sjkh */ 28228606Simp if (prompt("Local file name? ", fname, sizeof(fname))) 2837527Sjkh return; 2847527Sjkh 2857527Sjkh /* 2867527Sjkh * look up file 2877527Sjkh */ 2887527Sjkh fnamex = expand(fname); 289161754Sru if ((fp = fopen(fnamex, "r")) == NULL) { 2907527Sjkh printf("%s: cannot open\r\n", fname); 2917527Sjkh return; 2927527Sjkh } 293161754Sru transmit(fp, value(EOFWRITE), NULL); 29488276Smarkm if (!boolean(value(ECHOCHECK))) 29588276Smarkm tcdrain(FD); 2967527Sjkh} 2977527Sjkh 2987527Sjkh/* 2997527Sjkh * Bulk transfer routine to remote host -- 3007527Sjkh * used by sendfile() and cu_put() 3017527Sjkh */ 302161754Srustatic void 303161754Srutransmit(FILE *fp, char *eofchars, char *command) 3047527Sjkh{ 3057527Sjkh char *pc, lastc; 3067527Sjkh int c, ccount, lcount; 3077527Sjkh time_t start_t, stop_t; 3087527Sjkh sig_t f; 3097527Sjkh 310161754Sru kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ 3117527Sjkh stop = 0; 3127527Sjkh f = signal(SIGINT, stopsnd); 31388276Smarkm tcsetattr(0, TCSAFLUSH, &defchars); 3147527Sjkh read(repdes[0], (char *)&ccc, 1); 3157527Sjkh if (command != NULL) { 3167527Sjkh for (pc = command; *pc; pc++) 3177527Sjkh send(*pc); 3187527Sjkh if (boolean(value(ECHOCHECK))) 3197527Sjkh read(FD, (char *)&c, 1); /* trailing \n */ 3207527Sjkh else { 32188276Smarkm tcdrain(FD); 3227527Sjkh sleep(5); /* wait for remote stty to take effect */ 3237527Sjkh } 3247527Sjkh } 3257527Sjkh lcount = 0; 3267527Sjkh lastc = '\0'; 3277527Sjkh start_t = time(0); 3287527Sjkh while (1) { 3297527Sjkh ccount = 0; 3307527Sjkh do { 331161754Sru c = getc(fp); 3327527Sjkh if (stop) 3337527Sjkh goto out; 3347527Sjkh if (c == EOF) 3357527Sjkh goto out; 3367527Sjkh if (c == 0177 && !boolean(value(RAWFTP))) 3377527Sjkh continue; 3387527Sjkh lastc = c; 3397527Sjkh if (c < 040) { 3407527Sjkh if (c == '\n') { 3417527Sjkh if (!boolean(value(RAWFTP))) 3427527Sjkh c = '\r'; 343161754Sru } else if (c == '\t') { 3447527Sjkh if (!boolean(value(RAWFTP))) { 3457527Sjkh if (boolean(value(TABEXPAND))) { 3467527Sjkh send(' '); 3477527Sjkh while ((++ccount % 8) != 0) 3487527Sjkh send(' '); 3497527Sjkh continue; 3507527Sjkh } 3517527Sjkh } 3527527Sjkh } else 3537527Sjkh if (!boolean(value(RAWFTP))) 3547527Sjkh continue; 3557527Sjkh } 3567527Sjkh send(c); 3577527Sjkh } while (c != '\r' && !boolean(value(RAWFTP))); 3587527Sjkh if (boolean(value(VERBOSE))) 3597527Sjkh printf("\r%d", ++lcount); 3607527Sjkh if (boolean(value(ECHOCHECK))) { 3617527Sjkh timedout = 0; 362161754Sru alarm((unsigned int)lvalue(ETIMEOUT)); 3637527Sjkh do { /* wait for prompt */ 3647527Sjkh read(FD, (char *)&c, 1); 3657527Sjkh if (timedout || stop) { 3667527Sjkh if (timedout) 3677527Sjkh printf("\r\ntimed out at eol\r\n"); 3687527Sjkh alarm(0); 3697527Sjkh goto out; 3707527Sjkh } 37188276Smarkm } while ((c&STRIP_PAR) != character(value(PROMPT))); 3727527Sjkh alarm(0); 3737527Sjkh } 3747527Sjkh } 3757527Sjkhout: 3767527Sjkh if (lastc != '\n' && !boolean(value(RAWFTP))) 3777527Sjkh send('\r'); 37888276Smarkm if (eofchars) { 37988276Smarkm for (pc = eofchars; *pc; pc++) 38088276Smarkm send(*pc); 38188276Smarkm } 3827527Sjkh stop_t = time(0); 383161754Sru fclose(fp); 3847527Sjkh signal(SIGINT, f); 38588276Smarkm if (boolean(value(VERBOSE))) { 3867527Sjkh if (boolean(value(RAWFTP))) 3877527Sjkh prtime(" chars transferred in ", stop_t-start_t); 3887527Sjkh else 3897527Sjkh prtime(" lines transferred in ", stop_t-start_t); 39088276Smarkm } 3917527Sjkh write(fildes[1], (char *)&ccc, 1); 39288276Smarkm tcsetattr(0, TCSAFLUSH, &term); 3937527Sjkh} 3947527Sjkh 3957527Sjkh/* 3967527Sjkh * Cu-like put command 3977527Sjkh */ 398161754Sru/*ARGSUSED*/ 39928365Scharniervoid 400161754Srucu_put(int c) 4017527Sjkh{ 402161754Sru FILE *fp; 4037527Sjkh char line[BUFSIZ]; 4047527Sjkh int argc; 4057527Sjkh char *copynamex; 4067527Sjkh 40728606Simp if (prompt("[put] ", copyname, sizeof(copyname))) 4087527Sjkh return; 40988276Smarkm if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || 41088276Smarkm argc > 2) { 4117527Sjkh printf("usage: <put> from [to]\r\n"); 4127527Sjkh return; 4137527Sjkh } 4147527Sjkh if (argc == 1) 4157527Sjkh argv[1] = argv[0]; 4167527Sjkh copynamex = expand(argv[0]); 417161754Sru if ((fp = fopen(copynamex, "r")) == NULL) { 4187527Sjkh printf("%s: cannot open\r\n", copynamex); 4197527Sjkh return; 4207527Sjkh } 4217527Sjkh if (boolean(value(ECHOCHECK))) 42288276Smarkm (void)snprintf(line, sizeof(line), "cat>%s\r", argv[1]); 4237527Sjkh else 42488276Smarkm (void)snprintf(line, sizeof(line), 42588276Smarkm "stty -echo;cat>%s;stty echo\r", argv[1]); 426161754Sru transmit(fp, "\04", line); 4277527Sjkh} 4287527Sjkh 4297527Sjkh/* 4307527Sjkh * FTP - send single character 4317527Sjkh * wait for echo & handle timeout 4327527Sjkh */ 433161754Srustatic void 434161754Srusend(int c) 4357527Sjkh{ 4367527Sjkh char cc; 4377527Sjkh int retry = 0; 4387527Sjkh 4397527Sjkh cc = c; 44088276Smarkm parwrite(FD, &cc, 1); 4417527Sjkh if (number(value(CDELAY)) > 0 && c != '\r') 442161754Sru usleep(number(value(CDELAY))); 4437527Sjkh if (!boolean(value(ECHOCHECK))) { 4447527Sjkh if (number(value(LDELAY)) > 0 && c == '\r') 445161754Sru usleep(number(value(LDELAY))); 4467527Sjkh return; 4477527Sjkh } 4487527Sjkhtryagain: 4497527Sjkh timedout = 0; 450161754Sru alarm((unsigned int)lvalue(ETIMEOUT)); 4517527Sjkh read(FD, &cc, 1); 4527527Sjkh alarm(0); 4537527Sjkh if (timedout) { 4547527Sjkh printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 4557527Sjkh if (retry++ > 3) 4567527Sjkh return; 45788276Smarkm parwrite(FD, &null, 1); /* poke it */ 4587527Sjkh goto tryagain; 4597527Sjkh } 4607527Sjkh} 4617527Sjkh 462161754Sru/*ARGSUSED*/ 4637527Sjkhvoid 464161754Srutimeout(int signo) 4657527Sjkh{ 4667527Sjkh signal(SIGALRM, timeout); 4677527Sjkh timedout = 1; 4687527Sjkh} 4697527Sjkh 4707527Sjkh/* 4717527Sjkh * Stolen from consh() -- puts a remote file on the output of a local command. 4727527Sjkh * Identical to consh() except for where stdout goes. 4737527Sjkh */ 47428365Scharniervoid 475161754Srupipeout(int c) 4767527Sjkh{ 4777527Sjkh char buf[256]; 478161754Sru int status, p; 479161754Sru pid_t cpid; 48088276Smarkm time_t start = time(NULL); 4817527Sjkh 4827527Sjkh putchar(c); 48328606Simp if (prompt("Local command? ", buf, sizeof(buf))) 4847527Sjkh return; 485161754Sru kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ 4867527Sjkh signal(SIGINT, SIG_IGN); 4877527Sjkh signal(SIGQUIT, SIG_IGN); 48888276Smarkm tcsetattr(0, TCSAFLUSH, &defchars); 4897527Sjkh read(repdes[0], (char *)&ccc, 1); 4907527Sjkh /* 4917527Sjkh * Set up file descriptors in the child and 4927527Sjkh * let it go... 4937527Sjkh */ 4947527Sjkh if ((cpid = fork()) < 0) 4957527Sjkh printf("can't fork!\r\n"); 4967527Sjkh else if (cpid) { 49788276Smarkm start = time(NULL); 4987527Sjkh while ((p = wait(&status)) > 0 && p != cpid) 4997527Sjkh ; 5007527Sjkh } else { 50188276Smarkm int i; 5027527Sjkh 5037527Sjkh dup2(FD, 1); 5047527Sjkh for (i = 3; i < 20; i++) 5057527Sjkh close(i); 5067527Sjkh signal(SIGINT, SIG_DFL); 5077527Sjkh signal(SIGQUIT, SIG_DFL); 5087527Sjkh execute(buf); 5097527Sjkh printf("can't find `%s'\r\n", buf); 5107527Sjkh exit(0); 5117527Sjkh } 5127527Sjkh if (boolean(value(VERBOSE))) 5137527Sjkh prtime("away for ", time(0)-start); 5147527Sjkh write(fildes[1], (char *)&ccc, 1); 51588276Smarkm tcsetattr(0, TCSAFLUSH, &term); 5167527Sjkh signal(SIGINT, SIG_DFL); 5177527Sjkh signal(SIGQUIT, SIG_DFL); 5187527Sjkh} 5197527Sjkh 52088276Smarkm#ifdef CONNECT 52188276Smarkm/* 52288276Smarkm * Fork a program with: 52388276Smarkm * 0 <-> remote tty in 52488276Smarkm * 1 <-> remote tty out 525161754Sru * 2 <-> local tty stderr 52688276Smarkm */ 52788276Smarkmvoid 528161754Sruconsh(int c) 5297527Sjkh{ 53088276Smarkm char buf[256]; 531161754Sru int status, p; 532161754Sru pid_t cpid; 53388276Smarkm time_t start = time(NULL); 5347527Sjkh 53588276Smarkm putchar(c); 53688276Smarkm if (prompt("Local command? ", buf, sizeof(buf))) 53788276Smarkm return; 538161754Sru kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ 53988276Smarkm signal(SIGINT, SIG_IGN); 54088276Smarkm signal(SIGQUIT, SIG_IGN); 54188276Smarkm tcsetattr(0, TCSAFLUSH, &defchars); 54288276Smarkm read(repdes[0], (char *)&ccc, 1); 5437527Sjkh /* 5447527Sjkh * Set up file descriptors in the child and 5457527Sjkh * let it go... 5467527Sjkh */ 5477527Sjkh if ((cpid = fork()) < 0) 5487527Sjkh printf("can't fork!\r\n"); 5497527Sjkh else if (cpid) { 5507527Sjkh start = time(0); 5517527Sjkh while ((p = wait(&status)) > 0 && p != cpid) 5527527Sjkh ; 5537527Sjkh } else { 55488276Smarkm int i; 5557527Sjkh 5567527Sjkh dup2(FD, 0); 5577527Sjkh dup2(3, 1); 55888276Smarkm for (i = 3; i < 20; i++) 55988276Smarkm close(i); 5607527Sjkh signal(SIGINT, SIG_DFL); 5617527Sjkh signal(SIGQUIT, SIG_DFL); 56288276Smarkm execute(buf); 56388276Smarkm printf("can't find `%s'\r\n", buf); 5647527Sjkh exit(0); 5657527Sjkh } 56688276Smarkm if (boolean(value(VERBOSE))) 5677527Sjkh prtime("away for ", time(0)-start); 56888276Smarkm write(fildes[1], (char *)&ccc, 1); 56988276Smarkm tcsetattr(0, TCSAFLUSH, &term); 57088276Smarkm signal(SIGINT, SIG_DFL); 57188276Smarkm signal(SIGQUIT, SIG_DFL); 5727527Sjkh} 5737527Sjkh#endif 5747527Sjkh 5757527Sjkh/* 5767527Sjkh * Escape to local shell 5777527Sjkh */ 578161754Sru/*ARGSUSED*/ 57928365Scharniervoid 580161754Srushell(int c) 5817527Sjkh{ 582161754Sru int status; 5837527Sjkh char *cp; 584161754Sru pid_t shpid; 5857527Sjkh 5867527Sjkh printf("[sh]\r\n"); 5877527Sjkh signal(SIGINT, SIG_IGN); 5887527Sjkh signal(SIGQUIT, SIG_IGN); 5897527Sjkh unraw(); 59028365Scharnier if ((shpid = fork())) { 5917527Sjkh while (shpid != wait(&status)); 5927527Sjkh raw(); 5937527Sjkh printf("\r\n!\r\n"); 5947527Sjkh signal(SIGINT, SIG_DFL); 5957527Sjkh signal(SIGQUIT, SIG_DFL); 5967527Sjkh return; 5977527Sjkh } else { 5987527Sjkh signal(SIGQUIT, SIG_DFL); 5997527Sjkh signal(SIGINT, SIG_DFL); 60088276Smarkm if ((cp = strrchr(value(SHELL), '/')) == NULL) 6017527Sjkh cp = value(SHELL); 6027527Sjkh else 6037527Sjkh cp++; 6047527Sjkh shell_uid(); 60588276Smarkm execl(value(SHELL), cp, (char *)NULL); 6067527Sjkh printf("\r\ncan't execl!\r\n"); 6077527Sjkh exit(1); 6087527Sjkh } 6097527Sjkh} 6107527Sjkh 6117527Sjkh/* 6127527Sjkh * TIPIN portion of scripting 6137527Sjkh * initiate the conversation with TIPOUT 6147527Sjkh */ 61528365Scharniervoid 616161754Srusetscript(void) 6177527Sjkh{ 6187527Sjkh char c; 619161754Sru 6207527Sjkh /* 6217527Sjkh * enable TIPOUT side for dialogue 6227527Sjkh */ 623161754Sru kill(tipout_pid, SIGEMT); 6247527Sjkh if (boolean(value(SCRIPT))) 6257527Sjkh write(fildes[1], value(RECORD), size(value(RECORD))); 6267527Sjkh write(fildes[1], "\n", 1); 6277527Sjkh /* 6287527Sjkh * wait for TIPOUT to finish 6297527Sjkh */ 6307527Sjkh read(repdes[0], &c, 1); 6317527Sjkh if (c == 'n') 6327527Sjkh printf("can't create %s\r\n", value(RECORD)); 6337527Sjkh} 6347527Sjkh 6357527Sjkh/* 6367527Sjkh * Change current working directory of 6377527Sjkh * local portion of tip 6387527Sjkh */ 639161754Sru/*ARGSUSED*/ 64028365Scharniervoid 641161754Sruchdirectory(int c) 6427527Sjkh{ 64328686Simp char dirname[PATH_MAX]; 64488276Smarkm char *cp = dirname; 6457527Sjkh 64628606Simp if (prompt("[cd] ", dirname, sizeof(dirname))) { 6477527Sjkh if (stoprompt) 6487527Sjkh return; 6497527Sjkh cp = value(HOME); 6507527Sjkh } 6517527Sjkh if (chdir(cp) < 0) 6527527Sjkh printf("%s: bad directory\r\n", cp); 6537527Sjkh printf("!\r\n"); 6547527Sjkh} 6557527Sjkh 65628365Scharniervoid 657161754Srutipabort(char *msg) 6587527Sjkh{ 6597527Sjkh 660161754Sru signal(SIGTERM, SIG_IGN); 661161754Sru kill(tipout_pid, SIGTERM); 6627527Sjkh disconnect(msg); 6637527Sjkh if (msg != NOSTR) 6647527Sjkh printf("\r\n%s", msg); 6657527Sjkh printf("\r\n[EOT]\r\n"); 6667527Sjkh daemon_uid(); 6677527Sjkh (void)uu_unlock(uucplock); 6687527Sjkh unraw(); 669178736Sbms unexcl(); 6707527Sjkh exit(0); 6717527Sjkh} 6727527Sjkh 673161754Sru/*ARGSUSED*/ 67428365Scharniervoid 675161754Srufinish(int c) 6767527Sjkh{ 67788276Smarkm char *dismsg; 6787527Sjkh 6797527Sjkh if ((dismsg = value(DISCONNECT)) != NOSTR) { 6807527Sjkh write(FD, dismsg, strlen(dismsg)); 68188276Smarkm sleep(5); 6827527Sjkh } 68388276Smarkm tipabort(NOSTR); 6847527Sjkh} 6857527Sjkh 686161754Sru/*ARGSUSED*/ 687161754Srustatic void 688161754Sruintcopy(int signo) 6897527Sjkh{ 6907527Sjkh raw(); 6917527Sjkh quit = 1; 6927527Sjkh longjmp(intbuf, 1); 6937527Sjkh} 6947527Sjkh 695161754Srustatic void 696161754Sruexecute(char *s) 6977527Sjkh{ 69888276Smarkm char *cp; 6997527Sjkh 70088276Smarkm if ((cp = strrchr(value(SHELL), '/')) == NULL) 7017527Sjkh cp = value(SHELL); 7027527Sjkh else 7037527Sjkh cp++; 7047527Sjkh shell_uid(); 70588276Smarkm execl(value(SHELL), cp, "-c", s, (char *)NULL); 7067527Sjkh} 7077527Sjkh 708161754Srustatic int 709161754Sruargs(char *buf, char *a[], int num) 7107527Sjkh{ 71188276Smarkm char *p = buf, *start; 71288276Smarkm char **parg = a; 71388276Smarkm int n = 0; 7147527Sjkh 71588276Smarkm do { 7167527Sjkh while (*p && (*p == ' ' || *p == '\t')) 7177527Sjkh p++; 7187527Sjkh start = p; 7197527Sjkh if (*p) 7207527Sjkh *parg = p; 7217527Sjkh while (*p && (*p != ' ' && *p != '\t')) 7227527Sjkh p++; 7237527Sjkh if (p != start) 7247527Sjkh parg++, n++; 7257527Sjkh if (*p) 7267527Sjkh *p++ = '\0'; 72788276Smarkm } while (*p && n < num); 72888276Smarkm 7297527Sjkh return(n); 7307527Sjkh} 7317527Sjkh 732161754Srustatic void 733161754Sruprtime(char *s, time_t a) 7347527Sjkh{ 73588276Smarkm int i; 7367527Sjkh int nums[3]; 7377527Sjkh 7387527Sjkh for (i = 0; i < 3; i++) { 7397527Sjkh nums[i] = (int)(a % quant[i]); 7407527Sjkh a /= quant[i]; 7417527Sjkh } 7427527Sjkh printf("%s", s); 7437527Sjkh while (--i >= 0) 744161754Sru if (nums[i] || (i == 0 && nums[1] == 0 && nums[2] == 0)) 7457527Sjkh printf("%d %s%c ", nums[i], sep[i], 7467527Sjkh nums[i] == 1 ? '\0' : 's'); 7477527Sjkh printf("\r\n!\r\n"); 7487527Sjkh} 7497527Sjkh 750161754Sru/*ARGSUSED*/ 75128365Scharniervoid 752161754Sruvariable(int c) 7537527Sjkh{ 7547527Sjkh char buf[256]; 7557527Sjkh 75628606Simp if (prompt("[set] ", buf, sizeof(buf))) 7577527Sjkh return; 7587527Sjkh vlex(buf); 7597527Sjkh if (vtable[BEAUTIFY].v_access&CHANGED) { 7607527Sjkh vtable[BEAUTIFY].v_access &= ~CHANGED; 761161754Sru kill(tipout_pid, SIGSYS); 7627527Sjkh } 7637527Sjkh if (vtable[SCRIPT].v_access&CHANGED) { 7647527Sjkh vtable[SCRIPT].v_access &= ~CHANGED; 7657527Sjkh setscript(); 7667527Sjkh /* 7677527Sjkh * So that "set record=blah script" doesn't 7687527Sjkh * cause two transactions to occur. 7697527Sjkh */ 7707527Sjkh if (vtable[RECORD].v_access&CHANGED) 7717527Sjkh vtable[RECORD].v_access &= ~CHANGED; 7727527Sjkh } 7737527Sjkh if (vtable[RECORD].v_access&CHANGED) { 7747527Sjkh vtable[RECORD].v_access &= ~CHANGED; 7757527Sjkh if (boolean(value(SCRIPT))) 7767527Sjkh setscript(); 7777527Sjkh } 7787527Sjkh if (vtable[TAND].v_access&CHANGED) { 7797527Sjkh vtable[TAND].v_access &= ~CHANGED; 7807527Sjkh if (boolean(value(TAND))) 7817527Sjkh tandem("on"); 7827527Sjkh else 7837527Sjkh tandem("off"); 7847527Sjkh } 785161754Sru if (vtable[LECHO].v_access&CHANGED) { 786161754Sru vtable[LECHO].v_access &= ~CHANGED; 787161754Sru HD = boolean(value(LECHO)); 788161754Sru } 7897527Sjkh if (vtable[PARITY].v_access&CHANGED) { 7907527Sjkh vtable[PARITY].v_access &= ~CHANGED; 79188276Smarkm setparity(NOSTR); 7927527Sjkh } 793161754Sru if (vtable[HARDWAREFLOW].v_access&CHANGED) { 794161754Sru vtable[HARDWAREFLOW].v_access &= ~CHANGED; 795161754Sru if (boolean(value(HARDWAREFLOW))) 796161754Sru hardwareflow("on"); 797161754Sru else 798161754Sru hardwareflow("off"); 799161754Sru } 800161754Sru if (vtable[LINEDISC].v_access&CHANGED) { 801161754Sru vtable[LINEDISC].v_access &= ~CHANGED; 802161754Sru linedisc(NOSTR); 803161754Sru } 8047527Sjkh} 8057527Sjkh 806161754Sru/*ARGSUSED*/ 80788276Smarkmvoid 808161754Srulistvariables(int c) 80988276Smarkm{ 81088276Smarkm value_t *p; 81188276Smarkm char *buf; 81288276Smarkm char charbuf[5]; /* for vis(3), 4 chars for encoding, plus nul */ 81388276Smarkm 81488276Smarkm puts("v\r"); 81588276Smarkm for (p = vtable; p->v_name; p++) { 81688276Smarkm fputs(p->v_name, stdout); 81788276Smarkm switch (p->v_type&TMASK) { 81888276Smarkm case STRING: 81988276Smarkm if (p->v_value) { 82088276Smarkm buf = malloc(4*strlen(p->v_value) + 1); 82188276Smarkm if (buf == NULL) { 82288276Smarkm fprintf(stderr, "Unable to malloc()\n"); 82388276Smarkm abort(); 82488276Smarkm } 82588276Smarkm strvis(buf, p->v_value, VIS_WHITE); 82688276Smarkm printf(" %s", buf); 82788276Smarkm free(buf); 82888276Smarkm } 82988276Smarkm putchar('\r'); 83088276Smarkm putchar('\n'); 83188276Smarkm break; 83288276Smarkm case NUMBER: 83388276Smarkm printf(" %ld\r\n", number(p->v_value)); 83488276Smarkm break; 83588276Smarkm case BOOL: 83688276Smarkm printf(" %s\r\n", 837161754Sru !boolean(p->v_value) ? "false" : "true"); 83888276Smarkm break; 83988276Smarkm case CHAR: 84088276Smarkm vis(charbuf, character(p->v_value), VIS_WHITE, 0); 84188276Smarkm printf(" %s\r\n", charbuf); 84288276Smarkm break; 84388276Smarkm } 844161754Sru } 84588276Smarkm} 84688276Smarkm 8477527Sjkh/* 8487527Sjkh * Turn tandem mode on or off for remote tty. 8497527Sjkh */ 850161754Srustatic void 851161754Srutandem(char *option) 8527527Sjkh{ 85388276Smarkm struct termios rmtty; 8547527Sjkh 85588276Smarkm tcgetattr(FD, &rmtty); 85688276Smarkm if (strcmp(option, "on") == 0) { 85788276Smarkm rmtty.c_iflag |= IXOFF; 85888276Smarkm term.c_iflag |= IXOFF; 8597527Sjkh } else { 86088276Smarkm rmtty.c_iflag &= ~IXOFF; 86188276Smarkm term.c_iflag &= ~IXOFF; 8627527Sjkh } 86388276Smarkm tcsetattr(FD, TCSADRAIN, &rmtty); 86488276Smarkm tcsetattr(0, TCSADRAIN, &term); 8657527Sjkh} 8667527Sjkh 8677527Sjkh/* 868161754Sru * Turn hardware flow control on or off for remote tty. 869161754Sru */ 870161754Srustatic void 871161754Sruhardwareflow(char *option) 872161754Sru{ 873161754Sru struct termios rmtty; 874161754Sru 875161754Sru tcgetattr(FD, &rmtty); 876161754Sru if (strcmp(option, "on") == 0) 877161754Sru rmtty.c_iflag |= CRTSCTS; 878161754Sru else 879161754Sru rmtty.c_iflag &= ~CRTSCTS; 880161754Sru tcsetattr(FD, TCSADRAIN, &rmtty); 881161754Sru} 882161754Sru 883161754Sru/* 884161754Sru * Change line discipline to the specified one. 885161754Sru */ 886161754Sruvoid 887161754Srulinedisc(char *option) 888161754Sru{ 889161781Sru int ld = (int)(intptr_t)value(LINEDISC); 890161754Sru 891161754Sru ioctl(FD, TIOCSETD, &ld); 892161754Sru} 893161754Sru 894161754Sru/* 8957527Sjkh * Send a break. 8967527Sjkh */ 897161754Sru/*ARGSUSED*/ 89828365Scharniervoid 899161754Srugenbrk(int c) 9007527Sjkh{ 9017527Sjkh ioctl(FD, TIOCSBRK, NULL); 9027527Sjkh sleep(1); 9037527Sjkh ioctl(FD, TIOCCBRK, NULL); 9047527Sjkh} 9057527Sjkh 9067527Sjkh/* 9077527Sjkh * Suspend tip 9087527Sjkh */ 90928365Scharniervoid 910161754Srususpend(int c) 9117527Sjkh{ 9127527Sjkh unraw(); 9137527Sjkh kill(c == CTRL('y') ? getpid() : 0, SIGTSTP); 9147527Sjkh raw(); 9157527Sjkh} 9167527Sjkh 9177527Sjkh/* 9187527Sjkh * expand a file name if it includes shell meta characters 9197527Sjkh */ 9207527Sjkhchar * 921161754Sruexpand(char name[]) 9227527Sjkh{ 9237527Sjkh static char xname[BUFSIZ]; 9247527Sjkh char cmdbuf[BUFSIZ]; 925161754Sru int l; 92688276Smarkm char *cp, *Shell; 92788276Smarkm int s, pivec[2]; 928161754Sru pid_t pid; 9297527Sjkh 9307527Sjkh if (!anyof(name, "~{[*?$`'\"\\")) 9317527Sjkh return(name); 9327527Sjkh /* sigint = signal(SIGINT, SIG_IGN); */ 9337527Sjkh if (pipe(pivec) < 0) { 93488276Smarkm perror("pipe"); 9357527Sjkh /* signal(SIGINT, sigint) */ 9367527Sjkh return(name); 9377527Sjkh } 93888276Smarkm (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name); 9397527Sjkh if ((pid = vfork()) == 0) { 9407527Sjkh Shell = value(SHELL); 9417527Sjkh if (Shell == NOSTR) 9427527Sjkh Shell = _PATH_BSHELL; 9437527Sjkh close(pivec[0]); 9447527Sjkh close(1); 9457527Sjkh dup(pivec[1]); 9467527Sjkh close(pivec[1]); 9477527Sjkh close(2); 9487527Sjkh shell_uid(); 94988276Smarkm execl(Shell, Shell, "-c", cmdbuf, (char *)NULL); 9507527Sjkh _exit(1); 9517527Sjkh } 9527527Sjkh if (pid == -1) { 95388276Smarkm perror("fork"); 9547527Sjkh close(pivec[0]); 9557527Sjkh close(pivec[1]); 9567527Sjkh return(NOSTR); 9577527Sjkh } 9587527Sjkh close(pivec[1]); 9597527Sjkh l = read(pivec[0], xname, BUFSIZ); 9607527Sjkh close(pivec[0]); 9617527Sjkh while (wait(&s) != pid); 9627527Sjkh ; 9637527Sjkh s &= 0377; 9647527Sjkh if (s != 0 && s != SIGPIPE) { 9657527Sjkh fprintf(stderr, "\"Echo\" failed\n"); 9667527Sjkh return(NOSTR); 9677527Sjkh } 9687527Sjkh if (l < 0) { 96988276Smarkm perror("read"); 9707527Sjkh return(NOSTR); 9717527Sjkh } 9727527Sjkh if (l == 0) { 9737527Sjkh fprintf(stderr, "\"%s\": No match\n", name); 9747527Sjkh return(NOSTR); 9757527Sjkh } 9767527Sjkh if (l == BUFSIZ) { 9777527Sjkh fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); 9787527Sjkh return(NOSTR); 9797527Sjkh } 9807527Sjkh xname[l] = 0; 9817527Sjkh for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) 9827527Sjkh ; 9837527Sjkh *++cp = '\0'; 9847527Sjkh return(xname); 9857527Sjkh} 9867527Sjkh 9877527Sjkh/* 9887527Sjkh * Are any of the characters in the two strings the same? 9897527Sjkh */ 990161754Srustatic int 991161754Sruanyof(char *s1, char *s2) 9927527Sjkh{ 99388276Smarkm int c; 9947527Sjkh 99528365Scharnier while ((c = *s1++)) 9967527Sjkh if (any(c, s2)) 9977527Sjkh return(1); 9987527Sjkh return(0); 9997527Sjkh} 1000