Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Keep track of which file descriptors the shell is usi...



details:   https://anonhg.NetBSD.org/src/rev/ec38af90d0f0
branches:  trunk
changeset: 823628:ec38af90d0f0
user:      kre <kre%NetBSD.org@localhost>
date:      Sat Apr 29 15:14:28 2017 +0000

description:
Keep track of which file descriptors the shell is using for its
own purposes, and move them elsewhere whenever a user redirection
happens to pick the same number.   With this we can move the shell
file descriptors back to lower values (be slightly kinder to the kernel)
since we can no longer clash.   (Also get rid of a little old unneeded code.)

This also completes the fdflags command, which no longer permits access
to (by way or either obtaining, or changing) the shell's internal fds.

diffstat:

 bin/sh/input.c |   29 +++++++++++--
 bin/sh/jobs.c  |   35 +++++++---------
 bin/sh/redir.c |  115 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 bin/sh/redir.h |    4 +-
 4 files changed, 151 insertions(+), 32 deletions(-)

diffs (truncated from 372 to 300 lines):

diff -r e6c7624e2faa -r ec38af90d0f0 bin/sh/input.c
--- a/bin/sh/input.c    Sat Apr 29 15:12:21 2017 +0000
+++ b/bin/sh/input.c    Sat Apr 29 15:14:28 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: input.c,v 1.51 2016/06/01 05:11:52 kre Exp $   */
+/*     $NetBSD: input.c,v 1.52 2017/04/29 15:14:28 kre Exp $   */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)input.c    8.3 (Berkeley) 6/9/95";
 #else
-__RCSID("$NetBSD: input.c,v 1.51 2016/06/01 05:11:52 kre Exp $");
+__RCSID("$NetBSD: input.c,v 1.52 2017/04/29 15:14:28 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -428,6 +428,24 @@
        INTON;
 }
 
+/*
+ * When a shell fd needs to be altered (when the user wants to use
+ * the same fd - rare, but happens - we need to locate the ref to
+ * the fd, and update it.  This happens via a callback.
+ * This is the callback func for fd's used for shell input
+ */
+static void
+input_fd_swap(int from, int to)
+{
+       struct parsefile *pf;
+
+       pf = parsefile;
+       while (pf != NULL) {            /* don't need to stop at basepf */
+               if (pf->fd == from)
+                       pf->fd = to;
+               pf = pf->prev;
+       }
+}
 
 /*
  * Like setinputfile, but takes an open file descriptor.  Call this with
@@ -437,13 +455,14 @@
 void
 setinputfd(int fd, int push)
 {
+       register_sh_fd(fd, input_fd_swap);
        (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
        if (push) {
                pushfile();
                parsefile->buf = ckmalloc(BUFSIZ);
        }
        if (parsefile->fd > 0)
-               close(parsefile->fd);
+               sh_close(parsefile->fd);
        parsefile->fd = fd;
        if (parsefile->buf == NULL)
                parsefile->buf = ckmalloc(BUFSIZ);
@@ -502,7 +521,7 @@
 
        INTOFF;
        if (pf->fd >= 0)
-               close(pf->fd);
+               sh_close(pf->fd);
        if (pf->buf)
                ckfree(pf->buf);
        while (pf->strpush)
@@ -551,7 +570,7 @@
                return;
        popallfiles();
        if (parsefile->fd > 0) {
-               close(parsefile->fd);
+               sh_close(parsefile->fd);
                parsefile->fd = 0;
        }
 }
diff -r e6c7624e2faa -r ec38af90d0f0 bin/sh/jobs.c
--- a/bin/sh/jobs.c     Sat Apr 29 15:12:21 2017 +0000
+++ b/bin/sh/jobs.c     Sat Apr 29 15:14:28 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: jobs.c,v 1.79 2016/05/07 20:07:47 kre Exp $    */
+/*     $NetBSD: jobs.c,v 1.80 2017/04/29 15:14:28 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)jobs.c     8.5 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: jobs.c,v 1.79 2016/05/07 20:07:47 kre Exp $");
+__RCSID("$NetBSD: jobs.c,v 1.80 2017/04/29 15:14:28 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -129,6 +129,13 @@
 }
 #endif
 
+static void
+ttyfd_change(int from, int to)
+{
+       if (ttyfd == from)
+               ttyfd = to;
+}
+
 /*
  * Turn job control on and off.
  *
@@ -150,10 +157,10 @@
                return;
        if (on) {
 #if defined(FIOCLEX) || defined(FD_CLOEXEC)
-               int err;
                int i;
+
                if (ttyfd != -1)
-                       close(ttyfd);
+                       sh_close(ttyfd);
                if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {
                        for (i = 0; i < 3; i++) {
                                if (isatty(i) && (ttyfd = dup(i)) != -1)
@@ -163,24 +170,14 @@
                                goto out;
                }
                ttyfd = to_upper_fd(ttyfd);     /* Move to a high fd */
-#ifdef FIOCLEX
-               err = ioctl(ttyfd, FIOCLEX, 0);
-#elif FD_CLOEXEC
-               err = fcntl(ttyfd, F_SETFD,
-                   fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC);
-#endif
-               if (err == -1) {
-                       close(ttyfd);
-                       ttyfd = -1;
-                       goto out;
-               }
+               register_sh_fd(ttyfd, ttyfd_change);
 #else
                out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");
                goto out;
 #endif
                do { /* while we are in the background */
                        if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {
-out:
+ out:
                                out2str("sh: can't access tty; job control turned off\n");
                                mflag = 0;
                                return;
@@ -217,7 +214,7 @@
                if (tcsetpgrp(ttyfd, initialpgrp) == -1)
                        error("Cannot set tty process group (%s) at %d",
                            strerror(errno), __LINE__);
-               close(ttyfd);
+               sh_close(ttyfd);
                ttyfd = -1;
                setsignal(SIGTSTP, 0);
                setsignal(SIGTTOU, 0);
@@ -1312,7 +1309,7 @@
                goto until;
        case NUNTIL:
                cmdputs("until ");
-until:
+ until:
                cmdtxt(n->nbinary.ch1);
                cmdputs("; do ");
                cmdtxt(n->nbinary.ch2);
@@ -1366,7 +1363,7 @@
                p = "<&";  i = 0;  goto redir;
        case NFROMTO:
                p = "<>";  i = 0;  goto redir;
-redir:
+ redir:
                if (n->nfile.fd != i)
                        cmdputi(n->nfile.fd);
                cmdputs(p);
diff -r e6c7624e2faa -r ec38af90d0f0 bin/sh/redir.c
--- a/bin/sh/redir.c    Sat Apr 29 15:12:21 2017 +0000
+++ b/bin/sh/redir.c    Sat Apr 29 15:14:28 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: redir.c,v 1.53 2017/04/22 16:02:39 kre Exp $   */
+/*     $NetBSD: redir.c,v 1.54 2017/04/29 15:14:28 kre Exp $   */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)redir.c    8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: redir.c,v 1.53 2017/04/22 16:02:39 kre Exp $");
+__RCSID("$NetBSD: redir.c,v 1.54 2017/04/29 15:14:28 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -115,6 +115,18 @@
 STATIC int copyfd(int, int, int);
 STATIC void find_big_fd(void);
 
+
+struct shell_fds {             /* keep track of internal shell fds */
+       struct shell_fds *nxt;
+       void (*cb)(int, int);
+       int fd;
+};
+
+STATIC struct shell_fds *sh_fd_list;
+
+STATIC void renumber_sh_fd(struct shell_fds *);
+STATIC struct shell_fds *sh_fd(int);
+
 STATIC const struct renamelist *
 is_renamed(const struct renamelist *rl, int fd)
 {
@@ -191,6 +203,7 @@
                fd = n->nfile.fd;
                if (fd > max_user_fd)
                        max_user_fd = fd;
+               renumber_sh_fd(sh_fd(fd));
                if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
                    n->ndup.dupfd == fd) {
                        /* redirect from/to same file descriptor */
@@ -505,8 +518,12 @@
 find_big_fd(void)
 {
        int i, fd;
+       static int last_start = 6;
 
-       for (i = (1 << 10); i >= 10; i >>= 1) {
+       if (last_start < 10)
+               last_start++;
+
+       for (i = (1 << last_start); i >= 10; i >>= 1) {
                if ((fd = fcntl(0, F_DUPFD, i - 1)) >= 0) {
                        close(fd);
                        break;
@@ -514,9 +531,7 @@
        }
 
        fd = (i / 5) * 4;
-       if ((i - fd) > 100)
-               fd = i - 100;
-       else if (fd < 10)
+       if (fd < 10)
                fd = 10;
 
        big_sh_fd = fd;
@@ -543,7 +558,7 @@
                                close(fd);
                        return i;
                }
-               if (errno != EMFILE)
+               if (errno != EMFILE && errno != EINVAL)
                        break;
                find_big_fd();
        } while (big_sh_fd > 10);
@@ -557,6 +572,85 @@
        return fd;
 }
 
+void
+register_sh_fd(int fd, void (*cb)(int, int))
+{
+       struct shell_fds *fp;
+
+       fp = ckmalloc(sizeof (struct shell_fds));
+       if (fp != NULL) {
+               fp->nxt = sh_fd_list;
+               sh_fd_list = fp;
+
+               fp->fd = fd;
+               fp->cb = cb;
+       }
+}
+
+void
+sh_close(int fd)
+{
+       struct shell_fds **fpp, *fp;
+
+       fpp = &sh_fd_list;
+       while ((fp = *fpp) != NULL) {
+               if (fp->fd == fd) {
+                       *fpp = fp->nxt;
+                       ckfree(fp);
+                       break;
+               }
+               fpp = &fp->nxt;
+       }
+       (void)close(fd);
+}
+
+STATIC struct shell_fds *
+sh_fd(int fd)
+{
+       struct shell_fds *fp;
+
+       for (fp = sh_fd_list; fp != NULL; fp = fp->nxt)
+               if (fp->fd == fd)
+                       return fp;
+       return NULL;



Home | Main Index | Thread Index | Old Index