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;