summaryrefslogtreecommitdiffstats
path: root/source/ap/ash/patches/ash-redir.patch
diff options
context:
space:
mode:
Diffstat (limited to 'source/ap/ash/patches/ash-redir.patch')
-rw-r--r--source/ap/ash/patches/ash-redir.patch463
1 files changed, 463 insertions, 0 deletions
diff --git a/source/ap/ash/patches/ash-redir.patch b/source/ap/ash/patches/ash-redir.patch
new file mode 100644
index 000000000..40cdbe9ac
--- /dev/null
+++ b/source/ap/ash/patches/ash-redir.patch
@@ -0,0 +1,463 @@
+diff -ur netbsd-sh/eval.c netbsd-sh-/eval.c
+--- netbsd-sh/eval.c Tue May 23 12:03:18 2000
++++ netbsd-sh-/eval.c Mon Apr 23 23:33:34 2001
+@@ -442,6 +442,7 @@
+ case NFROM:
+ case NTO:
+ case NAPPEND:
++ case NTOOV:
+ expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+ redir->nfile.expfname = fn.list->text;
+ break;
+diff -ur netbsd-sh/exec.c netbsd-sh-/exec.c
+--- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001
++++ netbsd-sh-/exec.c Mon Apr 23 23:33:34 2001
+@@ -125,6 +125,10 @@
+ char *cmdname;
+ int e;
+
++ if (fd2 >= 0 && fd2 != 2) {
++ close(fd2);
++ }
++
+ if (strchr(argv[0], '/') != NULL) {
+ tryexec(argv[0], argv, envp);
+ e = errno;
+diff -ur netbsd-sh/jobs.c netbsd-sh-/jobs.c
+--- netbsd-sh/jobs.c Mon Apr 23 23:34:53 2001
++++ netbsd-sh-/jobs.c Mon Apr 23 23:34:30 2001
+@@ -129,9 +129,9 @@
+ if (on) {
+ do { /* while we are in the background */
+ #ifdef OLD_TTY_DRIVER
+- if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
++ if (ioctl(fd2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
+ #else
+- initialpgrp = tcgetpgrp(2);
++ initialpgrp = tcgetpgrp(fd2);
+ if (initialpgrp < 0) {
+ #endif
+ out2str("sh: can't access tty; job control turned off\n");
+@@ -146,7 +146,7 @@
+ }
+ } while (0);
+ #ifdef OLD_TTY_DRIVER
+- if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
++ if (ioctl(fd2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
+ out2str("sh: need new tty driver to run job control; job control turned off\n");
+ mflag = 0;
+ return;
+@@ -157,16 +157,16 @@
+ setsignal(SIGTTIN);
+ setpgid(0, rootpid);
+ #ifdef OLD_TTY_DRIVER
+- ioctl(2, TIOCSPGRP, (char *)&rootpid);
++ ioctl(fd2, TIOCSPGRP, (char *)&rootpid);
+ #else
+- tcsetpgrp(2, rootpid);
++ tcsetpgrp(fd2, rootpid);
+ #endif
+ } else { /* turning job control off */
+ setpgid(0, initialpgrp);
+ #ifdef OLD_TTY_DRIVER
+- ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
++ ioctl(fd2, TIOCSPGRP, (char *)&initialpgrp);
+ #else
+- tcsetpgrp(2, initialpgrp);
++ tcsetpgrp(fd2, initialpgrp);
+ #endif
+ setsignal(SIGTSTP);
+ setsignal(SIGTTOU);
+@@ -206,9 +206,9 @@
+ error("job not created under job control");
+ pgrp = jp->ps[0].pid;
+ #ifdef OLD_TTY_DRIVER
+- ioctl(2, TIOCSPGRP, (char *)&pgrp);
++ ioctl(fd2, TIOCSPGRP, (char *)&pgrp);
+ #else
+- tcsetpgrp(2, pgrp);
++ tcsetpgrp(fd2, pgrp);
+ #endif
+ restartjob(jp);
+ INTOFF;
+@@ -612,10 +612,10 @@
+ if (mode == FORK_FG) {
+ /*** this causes superfluous TIOCSPGRPS ***/
+ #ifdef OLD_TTY_DRIVER
+- if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
++ if (ioctl(fd2, TIOCSPGRP, (char *)&pgrp) < 0)
+ error("TIOCSPGRP failed, errno=%d", errno);
+ #else
+- if (tcsetpgrp(2, pgrp) < 0)
++ if (tcsetpgrp(fd2, pgrp) < 0)
+ error("tcsetpgrp failed, errno=%d", errno);
+ #endif
+ }
+@@ -734,10 +734,10 @@
+ #if JOBS
+ if (jp->jobctl) {
+ #ifdef OLD_TTY_DRIVER
+- if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
++ if (ioctl(fd2, TIOCSPGRP, (char *)&mypgrp) < 0)
+ error("TIOCSPGRP failed, errno=%d\n", errno);
+ #else
+- if (tcsetpgrp(2, mypgrp) < 0)
++ if (tcsetpgrp(fd2, mypgrp) < 0)
+ error("tcsetpgrp failed, errno=%d\n", errno);
+ #endif
+ }
+@@ -1092,6 +1092,8 @@
+ p = ">>"; i = 1; goto redir;
+ case NTOFD:
+ p = ">&"; i = 1; goto redir;
++ case NTOOV:
++ p = ">|"; i = 1; goto redir;
+ case NFROM:
+ p = "<"; i = 0; goto redir;
+ case NFROMFD:
+Only in netbsd-sh-: jobs.c.orig
+diff -ur netbsd-sh/nodetypes netbsd-sh-/nodetypes
+--- netbsd-sh/nodetypes Fri Feb 5 13:04:52 1999
++++ netbsd-sh-/nodetypes Mon Apr 23 23:33:34 2001
+@@ -119,6 +119,7 @@
+ NFROM nfile # fd< fname
+ NFROMTO nfile # fd<> fname
+ NAPPEND nfile # fd>> fname
++NTOOV nfile # fd>| fname
+ type int
+ next nodeptr # next redirection in list
+ fd int # file descriptor being redirected
+diff -ur netbsd-sh/parser.c netbsd-sh-/parser.c
+--- netbsd-sh/parser.c Fri Jan 12 17:50:39 2001
++++ netbsd-sh-/parser.c Mon Apr 23 23:33:34 2001
+@@ -1125,6 +1125,8 @@
+ np->type = NAPPEND;
+ else if (c == '&')
+ np->type = NTOFD;
++ else if (c == '|')
++ np->type = NTOOV;
+ else {
+ np->type = NTO;
+ pungetc();
+diff -ur netbsd-sh/redir.c netbsd-sh-/redir.c
+--- netbsd-sh/redir.c Tue May 23 12:03:19 2000
++++ netbsd-sh-/redir.c Mon Apr 23 23:33:34 2001
+@@ -45,6 +45,7 @@
+ #endif
+ #endif /* not lint */
+
++#include <sys/stat.h>
+ #include <sys/types.h>
+ #include <sys/param.h> /* PIPE_BUF */
+ #include <signal.h>
+@@ -66,6 +67,7 @@
+ #include "output.h"
+ #include "memalloc.h"
+ #include "error.h"
++#include "options.h"
+
+
+ #define EMPTY -2 /* marks an unused slot in redirtab */
+@@ -92,8 +94,15 @@
+ */
+ int fd0_redirected = 0;
+
+-STATIC void openredirect __P((union node *, char[10 ]));
++/*
++ * We also keep track of where fd2 goes.
++ */
++int fd2 = 2;
++
++STATIC int openredirect __P((union node *));
++STATIC void dupredirect __P((union node *, int, char[10 ]));
+ STATIC int openhere __P((union node *));
++STATIC int noclobberopen __P((const char *));
+
+
+ /*
+@@ -113,6 +122,7 @@
+ struct redirtab *sv = NULL;
+ int i;
+ int fd;
++ int newfd;
+ int try;
+ char memory[10]; /* file descriptors to write to memory */
+
+@@ -133,36 +143,47 @@
+ n->ndup.dupfd == fd)
+ continue; /* redirect from/to same file descriptor */
+
+- if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
+- INTOFF;
+-again:
+- if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
++ INTOFF;
++ newfd = openredirect(n);
++ if (((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) ||
++ (fd == fd2)) {
++ if (newfd == fd) {
++ try++;
++ } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
+ switch (errno) {
+ case EBADF:
+ if (!try) {
+- openredirect(n, memory);
++ dupredirect(n, newfd, memory);
+ try++;
+- goto again;
++ break;
+ }
+ /* FALLTHROUGH*/
+ default:
++ if (newfd >= 0) {
++ close(newfd);
++ }
+ INTON;
+ error("%d: %s", fd, strerror(errno));
+ /* NOTREACHED */
+ }
+ }
+ if (!try) {
+- sv->renamed[fd] = i;
+ close(fd);
++ if (flags & REDIR_PUSH) {
++ sv->renamed[fd] = i;
++ }
++ if (fd == fd2) {
++ fd2 = i;
++ }
+ }
+- INTON;
+- } else {
++ } else if (fd != newfd) {
+ close(fd);
+ }
+ if (fd == 0)
+ fd0_redirected++;
+ if (!try)
+- openredirect(n, memory);
++ dupredirect(n, newfd, memory);
++ INTON;
+ }
+ if (memory[1])
+ out1 = &memout;
+@@ -171,22 +192,13 @@
+ }
+
+
+-STATIC void
+-openredirect(redir, memory)
++STATIC int
++openredirect(redir)
+ union node *redir;
+- char memory[10];
+ {
+- int fd = redir->nfile.fd;
+ char *fname;
+ int f;
+
+- /*
+- * We suppress interrupts so that we won't leave open file
+- * descriptors around. This may not be such a good idea because
+- * an open of a device or a fifo can block indefinitely.
+- */
+- INTOFF;
+- memory[fd] = 0;
+ switch (redir->nfile.type) {
+ case NFROM:
+ fname = redir->nfile.expfname;
+@@ -199,6 +211,14 @@
+ goto ecreate;
+ break;
+ case NTO:
++ /* Take care of noclobber mode. */
++ if (Cflag) {
++ fname = redir->nfile.expfname;
++ if ((f = noclobberopen(fname)) < 0)
++ goto ecreate;
++ break;
++ }
++ case NTOOV:
+ fname = redir->nfile.expfname;
+ #ifdef O_CREAT
+ if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+@@ -222,32 +242,48 @@
+ break;
+ case NTOFD:
+ case NFROMFD:
++ f = -1;
++ break;
++ case NHERE:
++ case NXHERE:
++ f = openhere(redir);
++ break;
++ default:
++ abort();
++ }
++
++ return f;
++ecreate:
++ error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
++eopen:
++ error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
++}
++
++
++STATIC void
++dupredirect(redir, f, memory)
++ union node *redir;
++ int f;
++ char memory[10];
++ {
++ int fd = redir->nfile.fd;
++
++ memory[fd] = 0;
++ if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
+ if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
+ if (memory[redir->ndup.dupfd])
+ memory[fd] = 1;
+ else
+ copyfd(redir->ndup.dupfd, fd);
+ }
+- INTON;
+ return;
+- case NHERE:
+- case NXHERE:
+- f = openhere(redir);
+- break;
+- default:
+- abort();
+ }
+
+ if (f != fd) {
+ copyfd(f, fd);
+ close(f);
+ }
+- INTON;
+ return;
+-ecreate:
+- error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+-eopen:
+- error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+ }
+
+
+@@ -304,6 +340,7 @@
+ struct redirtab *rp = redirlist;
+ int i;
+
++ INTOFF;
+ for (i = 0 ; i < 10 ; i++) {
+ if (rp->renamed[i] != EMPTY) {
+ if (i == 0)
+@@ -313,9 +350,11 @@
+ copyfd(rp->renamed[i], i);
+ close(rp->renamed[i]);
+ }
++ if (rp->renamed[i] == fd2) {
++ fd2 = i;
++ }
+ }
+ }
+- INTOFF;
+ redirlist = rp->next;
+ ckfree(rp);
+ INTON;
+@@ -359,6 +398,9 @@
+ for (i = 0 ; i < 10 ; i++) {
+ if (rp->renamed[i] >= 0) {
+ close(rp->renamed[i]);
++ if (rp->renamed[i] == fd2) {
++ fd2 = -1;
++ }
+ }
+ rp->renamed[i] = EMPTY;
+ }
+@@ -388,4 +430,63 @@
+ error("%d: %s", from, strerror(errno));
+ }
+ return newfd;
++}
++
++/*
++ * Open a file in noclobber mode.
++ * The code was copied from bash.
++ */
++int
++noclobberopen(fname)
++ const char *fname;
++{
++ int r, fd;
++ struct stat finfo, finfo2;
++
++ /*
++ * If the file exists and is a regular file, return an error
++ * immediately.
++ */
++ r = stat(fname, &finfo);
++ if (r == 0 && S_ISREG(finfo.st_mode)) {
++ errno = EEXIST;
++ return -1;
++ }
++
++ /*
++ * If the file was not present (r != 0), make sure we open it
++ * exclusively so that if it is created before we open it, our open
++ * will fail. Make sure that we do not truncate an existing file.
++ * Note that we don't turn on O_EXCL unless the stat failed -- if the
++ * file was not a regular file, we leave O_EXCL off.
++ */
++ if (r != 0)
++ return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
++ fd = open(fname, O_WRONLY|O_CREAT, 0666);
++
++ /* If the open failed, return the file descriptor right away. */
++ if (fd < 0)
++ return fd;
++
++ /*
++ * OK, the open succeeded, but the file may have been changed from a
++ * non-regular file to a regular file between the stat and the open.
++ * We are assuming that the O_EXCL open handles the case where FILENAME
++ * did not exist and is symlinked to an existing file between the stat
++ * and open.
++ */
++
++ /*
++ * If we can open it and fstat the file descriptor, and neither check
++ * revealed that it was a regular file, and the file has not been
++ * replaced, return the file descriptor.
++ */
++ if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
++ finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
++ return fd;
++
++ /* The file has been replaced. badness. */
++ close(fd);
++ errno = EEXIST;
++ return -1;
+ }
+Only in netbsd-sh-: redir.c.orig
+diff -ur netbsd-sh/redir.h netbsd-sh-/redir.h
+--- netbsd-sh/redir.h Tue May 23 12:03:19 2000
++++ netbsd-sh-/redir.h Mon Apr 23 23:33:34 2001
+@@ -42,6 +42,8 @@
+ #define REDIR_PUSH 01 /* save previous values of file descriptors */
+ #define REDIR_BACKQ 02 /* save the command output in memory */
+
++extern int fd2;
++
+ union node;
+ void redirect __P((union node *, int));
+ void popredir __P((void));
+diff -ur netbsd-sh/show.c netbsd-sh-/show.c
+--- netbsd-sh/show.c Sat Oct 9 13:02:09 1999
++++ netbsd-sh-/show.c Mon Apr 23 23:33:34 2001
+@@ -155,6 +155,7 @@
+ case NTO: s = ">"; dftfd = 1; break;
+ case NAPPEND: s = ">>"; dftfd = 1; break;
+ case NTOFD: s = ">&"; dftfd = 1; break;
++ case NTOOV: s = ">|"; dftfd = 1; break;
+ case NFROM: s = "<"; dftfd = 0; break;
+ case NFROMFD: s = "<&"; dftfd = 0; break;
+ case NFROMTO: s = "<>"; dftfd = 0; break;