1 diff -ur netbsd-sh/eval.c netbsd-sh-/eval.c
2 --- netbsd-sh/eval.c Tue May 23 12:03:18 2000
3 +++ netbsd-sh-/eval.c Mon Apr 23 23:33:34 2001
9 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
10 redir->nfile.expfname = fn.list->text;
12 diff -ur netbsd-sh/exec.c netbsd-sh-/exec.c
13 --- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001
14 +++ netbsd-sh-/exec.c Mon Apr 23 23:33:34 2001
19 + if (fd2 >= 0 && fd2 != 2) {
23 if (strchr(argv[0], '/') != NULL) {
24 tryexec(argv[0], argv, envp);
26 diff -ur netbsd-sh/jobs.c netbsd-sh-/jobs.c
27 --- netbsd-sh/jobs.c Mon Apr 23 23:34:53 2001
28 +++ netbsd-sh-/jobs.c Mon Apr 23 23:34:30 2001
31 do { /* while we are in the background */
33 - if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
34 + if (ioctl(fd2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
36 - initialpgrp = tcgetpgrp(2);
37 + initialpgrp = tcgetpgrp(fd2);
38 if (initialpgrp < 0) {
40 out2str("sh: can't access tty; job control turned off\n");
45 - if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
46 + if (ioctl(fd2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
47 out2str("sh: need new tty driver to run job control; job control turned off\n");
54 - ioctl(2, TIOCSPGRP, (char *)&rootpid);
55 + ioctl(fd2, TIOCSPGRP, (char *)&rootpid);
57 - tcsetpgrp(2, rootpid);
58 + tcsetpgrp(fd2, rootpid);
60 } else { /* turning job control off */
61 setpgid(0, initialpgrp);
63 - ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
64 + ioctl(fd2, TIOCSPGRP, (char *)&initialpgrp);
66 - tcsetpgrp(2, initialpgrp);
67 + tcsetpgrp(fd2, initialpgrp);
72 error("job not created under job control");
75 - ioctl(2, TIOCSPGRP, (char *)&pgrp);
76 + ioctl(fd2, TIOCSPGRP, (char *)&pgrp);
79 + tcsetpgrp(fd2, pgrp);
84 if (mode == FORK_FG) {
85 /*** this causes superfluous TIOCSPGRPS ***/
87 - if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
88 + if (ioctl(fd2, TIOCSPGRP, (char *)&pgrp) < 0)
89 error("TIOCSPGRP failed, errno=%d", errno);
91 - if (tcsetpgrp(2, pgrp) < 0)
92 + if (tcsetpgrp(fd2, pgrp) < 0)
93 error("tcsetpgrp failed, errno=%d", errno);
100 - if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
101 + if (ioctl(fd2, TIOCSPGRP, (char *)&mypgrp) < 0)
102 error("TIOCSPGRP failed, errno=%d\n", errno);
104 - if (tcsetpgrp(2, mypgrp) < 0)
105 + if (tcsetpgrp(fd2, mypgrp) < 0)
106 error("tcsetpgrp failed, errno=%d\n", errno);
109 @@ -1092,6 +1092,8 @@
110 p = ">>"; i = 1; goto redir;
112 p = ">&"; i = 1; goto redir;
114 + p = ">|"; i = 1; goto redir;
116 p = "<"; i = 0; goto redir;
118 Only in netbsd-sh-: jobs.c.orig
119 diff -ur netbsd-sh/nodetypes netbsd-sh-/nodetypes
120 --- netbsd-sh/nodetypes Fri Feb 5 13:04:52 1999
121 +++ netbsd-sh-/nodetypes Mon Apr 23 23:33:34 2001
123 NFROM nfile # fd< fname
124 NFROMTO nfile # fd<> fname
125 NAPPEND nfile # fd>> fname
126 +NTOOV nfile # fd>| fname
128 next nodeptr # next redirection in list
129 fd int # file descriptor being redirected
130 diff -ur netbsd-sh/parser.c netbsd-sh-/parser.c
131 --- netbsd-sh/parser.c Fri Jan 12 17:50:39 2001
132 +++ netbsd-sh-/parser.c Mon Apr 23 23:33:34 2001
133 @@ -1125,6 +1125,8 @@
142 diff -ur netbsd-sh/redir.c netbsd-sh-/redir.c
143 --- netbsd-sh/redir.c Tue May 23 12:03:19 2000
144 +++ netbsd-sh-/redir.c Mon Apr 23 23:33:34 2001
147 #endif /* not lint */
149 +#include <sys/stat.h>
150 #include <sys/types.h>
151 #include <sys/param.h> /* PIPE_BUF */
155 #include "memalloc.h"
157 +#include "options.h"
160 #define EMPTY -2 /* marks an unused slot in redirtab */
163 int fd0_redirected = 0;
165 -STATIC void openredirect __P((union node *, char[10 ]));
167 + * We also keep track of where fd2 goes.
171 +STATIC int openredirect __P((union node *));
172 +STATIC void dupredirect __P((union node *, int, char[10 ]));
173 STATIC int openhere __P((union node *));
174 +STATIC int noclobberopen __P((const char *));
179 struct redirtab *sv = NULL;
184 char memory[10]; /* file descriptors to write to memory */
186 @@ -133,36 +143,47 @@
188 continue; /* redirect from/to same file descriptor */
190 - if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
193 - if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
195 + newfd = openredirect(n);
196 + if (((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) ||
200 + } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
204 - openredirect(n, memory);
205 + dupredirect(n, newfd, memory);
216 error("%d: %s", fd, strerror(errno));
221 - sv->renamed[fd] = i;
223 + if (flags & REDIR_PUSH) {
224 + sv->renamed[fd] = i;
232 + } else if (fd != newfd) {
238 - openredirect(n, memory);
239 + dupredirect(n, newfd, memory);
244 @@ -171,22 +192,13 @@
249 -openredirect(redir, memory)
255 - int fd = redir->nfile.fd;
260 - * We suppress interrupts so that we won't leave open file
261 - * descriptors around. This may not be such a good idea because
262 - * an open of a device or a fifo can block indefinitely.
266 switch (redir->nfile.type) {
268 fname = redir->nfile.expfname;
273 + /* Take care of noclobber mode. */
275 + fname = redir->nfile.expfname;
276 + if ((f = noclobberopen(fname)) < 0)
281 fname = redir->nfile.expfname;
283 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
284 @@ -222,32 +242,48 @@
292 + f = openhere(redir);
300 + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
302 + error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
307 +dupredirect(redir, f, memory)
312 + int fd = redir->nfile.fd;
315 + if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
316 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
317 if (memory[redir->ndup.dupfd])
320 copyfd(redir->ndup.dupfd, fd);
326 - f = openhere(redir);
339 - error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
341 - error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
346 struct redirtab *rp = redirlist;
350 for (i = 0 ; i < 10 ; i++) {
351 if (rp->renamed[i] != EMPTY) {
354 copyfd(rp->renamed[i], i);
355 close(rp->renamed[i]);
357 + if (rp->renamed[i] == fd2) {
363 redirlist = rp->next;
367 for (i = 0 ; i < 10 ; i++) {
368 if (rp->renamed[i] >= 0) {
369 close(rp->renamed[i]);
370 + if (rp->renamed[i] == fd2) {
374 rp->renamed[i] = EMPTY;
377 error("%d: %s", from, strerror(errno));
383 + * Open a file in noclobber mode.
384 + * The code was copied from bash.
387 +noclobberopen(fname)
391 + struct stat finfo, finfo2;
394 + * If the file exists and is a regular file, return an error
397 + r = stat(fname, &finfo);
398 + if (r == 0 && S_ISREG(finfo.st_mode)) {
404 + * If the file was not present (r != 0), make sure we open it
405 + * exclusively so that if it is created before we open it, our open
406 + * will fail. Make sure that we do not truncate an existing file.
407 + * Note that we don't turn on O_EXCL unless the stat failed -- if the
408 + * file was not a regular file, we leave O_EXCL off.
411 + return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
412 + fd = open(fname, O_WRONLY|O_CREAT, 0666);
414 + /* If the open failed, return the file descriptor right away. */
419 + * OK, the open succeeded, but the file may have been changed from a
420 + * non-regular file to a regular file between the stat and the open.
421 + * We are assuming that the O_EXCL open handles the case where FILENAME
422 + * did not exist and is symlinked to an existing file between the stat
427 + * If we can open it and fstat the file descriptor, and neither check
428 + * revealed that it was a regular file, and the file has not been
429 + * replaced, return the file descriptor.
431 + if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
432 + finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
435 + /* The file has been replaced. badness. */
440 Only in netbsd-sh-: redir.c.orig
441 diff -ur netbsd-sh/redir.h netbsd-sh-/redir.h
442 --- netbsd-sh/redir.h Tue May 23 12:03:19 2000
443 +++ netbsd-sh-/redir.h Mon Apr 23 23:33:34 2001
445 #define REDIR_PUSH 01 /* save previous values of file descriptors */
446 #define REDIR_BACKQ 02 /* save the command output in memory */
451 void redirect __P((union node *, int));
452 void popredir __P((void));
453 diff -ur netbsd-sh/show.c netbsd-sh-/show.c
454 --- netbsd-sh/show.c Sat Oct 9 13:02:09 1999
455 +++ netbsd-sh-/show.c Mon Apr 23 23:33:34 2001
457 case NTO: s = ">"; dftfd = 1; break;
458 case NAPPEND: s = ">>"; dftfd = 1; break;
459 case NTOFD: s = ">&"; dftfd = 1; break;
460 + case NTOOV: s = ">|"; dftfd = 1; break;
461 case NFROM: s = "<"; dftfd = 0; break;
462 case NFROMFD: s = "<&"; dftfd = 0; break;
463 case NFROMTO: s = "<>"; dftfd = 0; break;