X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/061754f3f8b01d31f88a551ff6eebd26a9437c77..638231e6203d8d8447c87fcb959bb90da83f521f:/usr/src/usr.bin/tip/cmds.c diff --git a/usr/src/usr.bin/tip/cmds.c b/usr/src/usr.bin/tip/cmds.c index d5e007ea81..e3c938f070 100644 --- a/usr/src/usr.bin/tip/cmds.c +++ b/usr/src/usr.bin/tip/cmds.c @@ -1,5 +1,43 @@ -/* cmds.c 4.2 81/05/31 */ +/* + * Copyright (c) 1983 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmds.c 5.15 (Berkeley) 3/4/91"; +#endif /* not lint */ + #include "tip.h" +#include "pathnames.h" + /* * tip * @@ -12,10 +50,9 @@ char null = '\0'; char *sep[] = { "second", "minute", "hour" }; static char *argv[10]; /* argument vector for take and put */ -int timeout(); /* timeout function called on alarm */ -int stopsnd(); /* SIGINT handler during file transfers */ -int intprompt(); /* used in handling SIG_INT during prompt */ -int intcopy(); /* interrupt routine for file transfers */ +void timeout(); /* timeout function called on alarm */ +void stopsnd(); /* SIGINT handler during file transfers */ +void intcopy(); /* interrupt routine for file transfers */ /* * FTP - remote ==> local @@ -24,7 +61,7 @@ int intcopy(); /* interrupt routine for file transfers */ getfl(c) char c; { - char buf[256]; + char buf[256], *cp, *expand(); putchar(c); /* @@ -32,7 +69,8 @@ getfl(c) */ if (prompt("Local file name? ", copyname)) return; - if ((sfd = creat(copyname, 0666)) < 0) { + cp = expand(copyname); + if ((sfd = creat(cp, 0666)) < 0) { printf("\r\n%s: cannot creat\r\n", copyname); return; } @@ -54,7 +92,7 @@ cu_take(cc) char cc; { int fd, argc; - char line[BUFSIZ]; + char line[BUFSIZ], *expand(), *cp; if (prompt("[take] ", copyname)) return; @@ -64,14 +102,16 @@ cu_take(cc) } if (argc == 1) argv[1] = argv[0]; - if ((fd = creat(argv[1], 0666)) < 0) { + cp = expand(argv[1]); + if ((fd = creat(cp, 0666)) < 0) { printf("\r\n%s: cannot create\r\n", argv[1]); return; } - sprintf(line, "cat '%s';echo \01", argv[0]); + sprintf(line, "cat %s;echo \01", argv[0]); transfer(line, fd, "\01"); } +static jmp_buf intbuf; /* * Bulk transfer routine -- * used by getfl(), cu_take(), and pipefile() @@ -84,22 +124,24 @@ transfer(buf, fd, eofchars) register char *p = buffer; register int cnt, eof; time_t start; + sig_t f; - write(FD, buf, size(buf)); + pwrite(FD, buf, size(buf)); quit = 0; - signal(SIGINT, intcopy); kill(pid, SIGIOT); read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ /* * finish command */ - write(FD, "\r", 1); + pwrite(FD, "\r", 1); do read(FD, &c, 1); while ((c&0177) != '\n'); ioctl(0, TIOCSETC, &defchars); + (void) setjmp(intbuf); + f = signal(SIGINT, intcopy); start = time(0); for (ct = 0; !quit;) { eof = read(FD, &c, 1) <= 0; @@ -132,7 +174,7 @@ transfer(buf, fd, eofchars) prtime(" lines transferred in ", time(0)-start); ioctl(0, TIOCSETC, &tchars); write(fildes[1], (char *)&ccc, 1); - signal(SIGINT, SIG_DFL); + signal(SIGINT, f); close(fd); } @@ -186,8 +228,10 @@ pipefile() /* * Interrupt service routine for FTP */ +void stopsnd() { + stop = 1; signal(SIGINT, SIG_IGN); } @@ -201,6 +245,8 @@ sendfile(cc) char cc; { FILE *fd; + char *fnamex; + char *expand(); putchar(cc); /* @@ -212,11 +258,18 @@ sendfile(cc) /* * look up file */ - if ((fd = fopen(fname, "r")) == NULL) { + fnamex = expand(fname); + if ((fd = fopen(fnamex, "r")) == NULL) { printf("%s: cannot open\r\n", fname); return; } transmit(fd, value(EOFWRITE), NULL); + if (!boolean(value(ECHOCHECK))) { + struct sgttyb buf; + + ioctl(FD, TIOCGETP, &buf); /* this does a */ + ioctl(FD, TIOCSETP, &buf); /* wflushtty */ + } } /* @@ -230,21 +283,30 @@ transmit(fd, eofchars, command) char *pc, lastc; int c, ccount, lcount; time_t start_t, stop_t; + sig_t f; kill(pid, SIGIOT); /* put TIPOUT into a wait state */ - signal(SIGINT, stopsnd); stop = 0; + f = signal(SIGINT, stopsnd); ioctl(0, TIOCSETC, &defchars); read(repdes[0], (char *)&ccc, 1); if (command != NULL) { for (pc = command; *pc; pc++) send(*pc); - read(FD, (char *)&c, 1); /* trailing \n */ + if (boolean(value(ECHOCHECK))) + read(FD, (char *)&c, 1); /* trailing \n */ + else { + struct sgttyb buf; + + ioctl(FD, TIOCGETP, &buf); /* this does a */ + ioctl(FD, TIOCSETP, &buf); /* wflushtty */ + sleep(5); /* wait for remote stty to take effect */ + } } lcount = 0; lastc = '\0'; start_t = time(0); - while(1) { + while (1) { ccount = 0; do { c = getc(fd); @@ -252,49 +314,59 @@ transmit(fd, eofchars, command) goto out; if (c == EOF) goto out; - if (c == 0177) + if (c == 0177 && !boolean(value(RAWFTP))) continue; lastc = c; if (c < 040) { - if (c == '\n') - c = '\r'; + if (c == '\n') { + if (!boolean(value(RAWFTP))) + c = '\r'; + } else if (c == '\t') { - if (boolean(value(TABEXPAND))) { - send(' '); - while((++ccount % 8) != 0) + if (!boolean(value(RAWFTP))) { + if (boolean(value(TABEXPAND))) { send(' '); - continue; + while ((++ccount % 8) != 0) + send(' '); + continue; + } } } else - continue; + if (!boolean(value(RAWFTP))) + continue; } send(c); - } while (c != '\r'); + } while (c != '\r' && !boolean(value(RAWFTP))); if (boolean(value(VERBOSE))) printf("\r%d", ++lcount); - alarm(10); - timedout = 0; - do { /* wait for prompt */ - read(FD, (char *)&c, 1); - if (timedout || stop) { - if (timedout) - printf("\r\ntimed out at eol\r\n"); - alarm(0); - goto out; - } - } while ((c&0177) != character(value(PROMPT))); - alarm(0); + if (boolean(value(ECHOCHECK))) { + timedout = 0; + alarm((int)value(ETIMEOUT)); + do { /* wait for prompt */ + read(FD, (char *)&c, 1); + if (timedout || stop) { + if (timedout) + printf("\r\ntimed out at eol\r\n"); + alarm(0); + goto out; + } + } while ((c&0177) != character(value(PROMPT))); + alarm(0); + } } out: - if (lastc != '\n') + if (lastc != '\n' && !boolean(value(RAWFTP))) send('\r'); for (pc = eofchars; *pc; pc++) send(*pc); stop_t = time(0); fclose(fd); - signal(SIGINT, SIG_DFL); + signal(SIGINT, f); if (boolean(value(VERBOSE))) - prtime(" lines transferred in ", stop_t-start_t); + if (boolean(value(RAWFTP))) + prtime(" chars transferred in ", stop_t-start_t); + else + prtime(" lines transferred in ", stop_t-start_t); write(fildes[1], (char *)&ccc, 1); ioctl(0, TIOCSETC, &tchars); } @@ -308,6 +380,8 @@ cu_put(cc) FILE *fd; char line[BUFSIZ]; int argc; + char *expand(); + char *copynamex; if (prompt("[put] ", copyname)) return; @@ -317,11 +391,15 @@ cu_put(cc) } if (argc == 1) argv[1] = argv[0]; - if ((fd = fopen(argv[0], "r")) == NULL) { - printf("%s: cannot open\r\n", argv[0]); + copynamex = expand(argv[0]); + if ((fd = fopen(copynamex, "r")) == NULL) { + printf("%s: cannot open\r\n", copynamex); return; } - sprintf(line, "cat>'%s'\r", argv[1]); + if (boolean(value(ECHOCHECK))) + sprintf(line, "cat>%s\r", argv[1]); + else + sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]); transmit(fd, "\04", line); } @@ -332,39 +410,97 @@ cu_put(cc) send(c) char c; { - int cc; + char cc; int retry = 0; cc = c; - write(FD, (char *)&cc, 1); + pwrite(FD, &cc, 1); +#ifdef notdef + if (number(value(CDELAY)) > 0 && c != '\r') + nap(number(value(CDELAY))); +#endif + if (!boolean(value(ECHOCHECK))) { +#ifdef notdef + if (number(value(LDELAY)) > 0 && c == '\r') + nap(number(value(LDELAY))); +#endif + return; + } tryagain: timedout = 0; - alarm(10); - read(FD, (char *)&cc, 1); + alarm((int)value(ETIMEOUT)); + read(FD, &cc, 1); alarm(0); if (timedout) { printf("\r\ntimeout error (%s)\r\n", ctrl(c)); if (retry++ > 3) return; - write(FD, &null, 1); /* poke it */ + pwrite(FD, &null, 1); /* poke it */ goto tryagain; } } +void timeout() { signal(SIGALRM, timeout); timedout = 1; } +/* + * Stolen from consh() -- puts a remote file on the output of a local command. + * Identical to consh() except for where stdout goes. + */ +pipeout(c) +{ + char buf[256]; + int cpid, status, p; + time_t start; + + putchar(c); + if (prompt("Local command? ", buf)) + return; + kill(pid, SIGIOT); /* put TIPOUT into a wait state */ + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + ioctl(0, TIOCSETC, &defchars); + read(repdes[0], (char *)&ccc, 1); + /* + * Set up file descriptors in the child and + * let it go... + */ + if ((cpid = fork()) < 0) + printf("can't fork!\r\n"); + else if (cpid) { + start = time(0); + while ((p = wait(&status)) > 0 && p != cpid) + ; + } else { + register int i; + + dup2(FD, 1); + for (i = 3; i < 20; i++) + close(i); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + execute(buf); + printf("can't find `%s'\r\n", buf); + exit(0); + } + if (boolean(value(VERBOSE))) + prtime("away for ", time(0)-start); + write(fildes[1], (char *)&ccc, 1); + ioctl(0, TIOCSETC, &tchars); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); +} + #ifdef CONNECT /* * Fork a program with: - * 0 <-> local tty in - * 1 <-> local tty out + * 0 <-> remote tty in + * 1 <-> remote tty out * 2 <-> local tty out - * 3 <-> remote tty in - * 4 <-> remote tty out */ consh(c) { @@ -393,9 +529,10 @@ consh(c) } else { register int i; - dup2(FD, 3); - dup2(3, 4); - for (i = 5; i < 20; i++) + dup2(1, 2); + dup2(FD, 0); + dup2(0, 1); + for (i = 3; i < 20; i++) close(i); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); @@ -439,6 +576,7 @@ shell() cp = value(SHELL); else cp++; + shell_uid(); execl(value(SHELL), cp, 0); printf("\r\ncan't execl!\r\n"); exit(1); @@ -473,36 +611,51 @@ setscript() */ chdirectory() { - char dirname[80]; + char dirname[80]; register char *cp = dirname; - if (prompt("[cd] ", dirname)) + if (prompt("[cd] ", dirname)) { if (stoprompt) return; - else - cp = value(HOME); + cp = value(HOME); + } if (chdir(cp) < 0) printf("%s: bad directory\r\n", cp); printf("!\r\n"); } -finish() +tipabort(msg) + char *msg; { + kill(pid, SIGTERM); - disconnect(); + disconnect(msg); + if (msg != NOSTR) + printf("\r\n%s", msg); printf("\r\n[EOT]\r\n"); - delock(uucplock); -#ifdef VMUNIX - ioctl(0, TIOCSETD, (char *)&odisc); -#endif + daemon_uid(); + (void)uu_unlock(uucplock); unraw(); exit(0); } +finish() +{ + char *dismsg; + + if ((dismsg = value(DISCONNECT)) != NOSTR) { + write(FD, dismsg, strlen(dismsg)); + sleep(5); + } + tipabort(NOSTR); +} + +void intcopy() { raw(); quit = 1; + longjmp(intbuf, 1); } execute(s) @@ -514,6 +667,7 @@ execute(s) cp = value(SHELL); else cp++; + shell_uid(); execl(value(SHELL), cp, "-c", s, 0); } @@ -554,7 +708,7 @@ prtime(s, a) } printf("%s", s); while (--i >= 0) - if (nums[i]) + if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0) printf("%d %s%c ", nums[i], sep[i], nums[i] == 1 ? '\0' : 's'); printf("\r\n!\r\n"); @@ -569,40 +723,165 @@ variable() vlex(buf); if (vtable[BEAUTIFY].v_access&CHANGED) { vtable[BEAUTIFY].v_access &= ~CHANGED; - signal(pid, SIGSYS); + kill(pid, SIGSYS); } if (vtable[SCRIPT].v_access&CHANGED) { vtable[SCRIPT].v_access &= ~CHANGED; setscript(); + /* + * So that "set record=blah script" doesn't + * cause two transactions to occur. + */ + if (vtable[RECORD].v_access&CHANGED) + vtable[RECORD].v_access &= ~CHANGED; } if (vtable[RECORD].v_access&CHANGED) { vtable[RECORD].v_access &= ~CHANGED; if (boolean(value(SCRIPT))) setscript(); } + if (vtable[TAND].v_access&CHANGED) { + vtable[TAND].v_access &= ~CHANGED; + if (boolean(value(TAND))) + tandem("on"); + else + tandem("off"); + } + if (vtable[LECHO].v_access&CHANGED) { + vtable[LECHO].v_access &= ~CHANGED; + HD = boolean(value(LECHO)); + } + if (vtable[PARITY].v_access&CHANGED) { + vtable[PARITY].v_access &= ~CHANGED; + setparity(); + } +} + +/* + * Turn tandem mode on or off for remote tty. + */ +tandem(option) + char *option; +{ + struct sgttyb rmtty; + + ioctl(FD, TIOCGETP, &rmtty); + if (strcmp(option,"on") == 0) { + rmtty.sg_flags |= TANDEM; + arg.sg_flags |= TANDEM; + } else { + rmtty.sg_flags &= ~TANDEM; + arg.sg_flags &= ~TANDEM; + } + ioctl(FD, TIOCSETP, &rmtty); + ioctl(0, TIOCSETP, &arg); } /* * Send a break. - * If we can't do it directly (as on VMUNIX), then simulate it. */ genbrk() { -#ifdef VMUNIX + ioctl(FD, TIOCSBRK, NULL); sleep(1); ioctl(FD, TIOCCBRK, NULL); -#else - struct sgttyb ttbuf; - int sospeed; - - ioctl(FD, TIOCGETP, &ttbuf); - sospeed = ttbuf.sg_ospeed; - ttbuf.sg_ospeed = B150; - ioctl(FD, TIOCSETP, &ttbuf); - write(FD, "\0\0\0\0\0\0\0\0\0\0", 10); - ttbuf.sg_ospeed = sospeed; - ioctl(FD, TIOCSETP, &ttbuf); - write(FD, "@", 1); -#endif +} + +/* + * Suspend tip + */ +suspend(c) + char c; +{ + + unraw(); + kill(c == CTRL('y') ? getpid() : 0, SIGTSTP); + raw(); +} + +/* + * expand a file name if it includes shell meta characters + */ + +char * +expand(name) + char name[]; +{ + static char xname[BUFSIZ]; + char cmdbuf[BUFSIZ]; + register int pid, l, rc; + register char *cp, *Shell; + int s, pivec[2], (*sigint)(); + + if (!anyof(name, "~{[*?$`'\"\\")) + return(name); + /* sigint = signal(SIGINT, SIG_IGN); */ + if (pipe(pivec) < 0) { + perror("pipe"); + /* signal(SIGINT, sigint) */ + return(name); + } + sprintf(cmdbuf, "echo %s", name); + if ((pid = vfork()) == 0) { + Shell = value(SHELL); + if (Shell == NOSTR) + Shell = _PATH_BSHELL; + close(pivec[0]); + close(1); + dup(pivec[1]); + close(pivec[1]); + close(2); + shell_uid(); + execl(Shell, Shell, "-c", cmdbuf, 0); + _exit(1); + } + if (pid == -1) { + perror("fork"); + close(pivec[0]); + close(pivec[1]); + return(NOSTR); + } + close(pivec[1]); + l = read(pivec[0], xname, BUFSIZ); + close(pivec[0]); + while (wait(&s) != pid); + ; + s &= 0377; + if (s != 0 && s != SIGPIPE) { + fprintf(stderr, "\"Echo\" failed\n"); + return(NOSTR); + } + if (l < 0) { + perror("read"); + return(NOSTR); + } + if (l == 0) { + fprintf(stderr, "\"%s\": No match\n", name); + return(NOSTR); + } + if (l == BUFSIZ) { + fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); + return(NOSTR); + } + xname[l] = 0; + for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) + ; + *++cp = '\0'; + return(xname); +} + +/* + * Are any of the characters in the two strings the same? + */ + +anyof(s1, s2) + register char *s1, *s2; +{ + register int c; + + while (c = *s1++) + if (any(c, s2)) + return(1); + return(0); }