Source-Changes-HG archive

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

[src/trunk]: src/bin/sh Inspired by (really the need for) Maya's patch to pkg...



details:   https://anonhg.NetBSD.org/src/rev/aed38c296b95
branches:  trunk
changeset: 449261:aed38c296b95
user:      kre <kre%NetBSD.org@localhost>
date:      Fri Mar 01 05:23:35 2019 +0000

description:
Inspired by (really the need for) Maya's patch to pkgsrc/shells/bash
to allow bash to build fdflags on Solaris 10, here are some mods that
fix that, and some other similar issues in the NetBSD version of fdflags.

The bash implementation of fdflags is based upon the one Christos did for
the NetBSD sh, so the issues are similar ... the NetBSD sh cannot yet
(easily anyway) build on anything except NetBSD, so this change makes
no current difference at all (just adds some compile time tests (#ifdef)
which always work out the way things did before, when built on NetBSD).

However, there is no system on which any modern shell can hope to work
which does not support close on exec, or fcntl(F_SETFD,...) to set it.
The O_CLOEXEC and FD_CLOEXEC definitions might not exist, but close on
exec can still be manipulated.   Since the primary rationale for
the fdflags builtin was to be able to manipulate that state bit from
scripts, it would be annoying to lose that one, and keep all the (less
important) others, just because O_CLOEXEC is not defined, so do the
fix (workaround) a different way than was done in the bash patch.

Further, more than fdflags() will fail if O_CLOEXEC is not defined,
so handle that as well.

Also fix another oddity ... (noticed by reading the code) - if
fcntl(F_GETFL,...) returned any bits set that we don't understand,
the code was supposed to simply print their values as a hex constant,
when fdflags is run with -v.    However, the getflags() function was
clearing all bits that the code did not know about ... so there is
no way any unknown bit could ever make it out to be printed.  Handle
that a different way - instead of clearing unknown bits, clear any
bits that get returned which we understand, but do not want to deal
with (stuff like O_WRONLY, which should not be returned from the
fcntl(), but who knows...)   Leave any unknown bits that happen to be
set, set, so that printone() can display them if appropriate.
(This is most likely to happen when running an older shell on a new
kernel where the kernel supports some new flag that the shell has
not been taught to understand).

NFCI that anyone should notice anytime soon.

diffstat:

 bin/sh/redir.c |  116 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 100 insertions(+), 16 deletions(-)

diffs (199 lines):

diff -r ec426018cd2f -r aed38c296b95 bin/sh/redir.c
--- a/bin/sh/redir.c    Fri Mar 01 04:39:37 2019 +0000
+++ b/bin/sh/redir.c    Fri Mar 01 05:23:35 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: redir.c,v 1.64 2019/02/09 09:34:43 kre Exp $   */
+/*     $NetBSD: redir.c,v 1.65 2019/03/01 05:23:35 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.64 2019/02/09 09:34:43 kre Exp $");
+__RCSID("$NetBSD: redir.c,v 1.65 2019/03/01 05:23:35 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -78,6 +78,17 @@
 # define PIPESIZE PIPE_BUF
 #endif
 
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC    1       /* well known from before there was a name */
+#endif
+
+#ifndef F_DUPFD_CLOEXEC
+#define F_DUPFD_CLOEXEC        F_DUPFD
+#define CLOEXEC(fd)    (fcntl((fd), F_SETFD, fcntl((fd),F_GETFD) | FD_CLOEXEC))
+#else
+#define CLOEXEC(fd)
+#endif
+
 
 MKINIT
 struct renamelist {
@@ -511,9 +522,14 @@
 {
        int newfd;
 
-       if (cloexec && to > 2)
+       if (cloexec && to > 2) {
+#ifdef O_CLOEXEC
                newfd = dup3(from, to, O_CLOEXEC);
-       else
+#else
+               newfd = dup2(from, to);
+               fcntl(newfd, F_SETFD, fcntl(newfd,F_GETFD) | FD_CLOEXEC);
+#endif
+       } else
                newfd = dup2(from, to);
 
        return newfd;
@@ -658,13 +674,6 @@
        if (fp == NULL)
                return;
 
-#ifndef        F_DUPFD_CLOEXEC
-#define        F_DUPFD_CLOEXEC F_DUPFD
-#define        CLOEXEC(fd)     (fcntl((fd), F_SETFD, fcntl((fd),F_GETFD) | FD_CLOEXEC))
-#else
-#define        CLOEXEC(fd)
-#endif
-
        /*
         * if we have had a collision, and the sh fd was a "big" one
         * try moving the sh fd base to a higher number (if possible)
@@ -702,41 +711,115 @@
 } nv[] = {
 #ifdef O_APPEND
        { "append",     2,      O_APPEND        },
+#else
+# define O_APPEND 0
 #endif
 #ifdef O_ASYNC
        { "async",      2,      O_ASYNC         },
+#else
+# define O_ASYNC 0
 #endif
 #ifdef O_SYNC
        { "sync",       2,      O_SYNC          },
+#else
+# define O_SYNC 0
 #endif
 #ifdef O_NONBLOCK
        { "nonblock",   3,      O_NONBLOCK      },
+#else
+# define O_NONBLOCK 0
 #endif
 #ifdef O_FSYNC
        { "fsync",      2,      O_FSYNC         },
+#else
+# define O_FSYNC 0
 #endif
 #ifdef O_DSYNC
        { "dsync",      2,      O_DSYNC         },
+#else
+# define O_DSYNC 0
 #endif
 #ifdef O_RSYNC
        { "rsync",      2,      O_RSYNC         },
+#else
+# define O_RSYNC 0
 #endif
 #ifdef O_ALT_IO
        { "altio",      2,      O_ALT_IO        },
+#else
+# define O_ALT_IO 0
 #endif
 #ifdef O_DIRECT
        { "direct",     2,      O_DIRECT        },
+#else
+# define O_DIRECT 0
 #endif
 #ifdef O_NOSIGPIPE
        { "nosigpipe",  3,      O_NOSIGPIPE     },
+#else
+# define O_NOSIGPIPE 0
 #endif
-#ifdef O_CLOEXEC
+
+#define ALLFLAGS (O_APPEND|O_ASYNC|O_SYNC|O_NONBLOCK|O_DSYNC|O_RSYNC|\
+    O_ALT_IO|O_DIRECT|O_NOSIGPIPE)
+
+#ifndef        O_CLOEXEC
+# define O_CLOEXEC     ((~0 & ~ALLFLAGS) ^      \
+                               ((~0 & ~ALLFLAGS) & ((~0 & ~ALLFLAGS) - 1)))
+#endif
+
+       /* for any system we support, close on exec is always defined */
        { "cloexec",    2,      O_CLOEXEC       },
-#endif
        { 0, 0, 0 }
 };
-#define ALLFLAGS (O_APPEND|O_ASYNC|O_SYNC|O_NONBLOCK|O_DSYNC|O_RSYNC|\
-    O_ALT_IO|O_DIRECT|O_NOSIGPIPE|O_CLOEXEC)
+
+#ifndef O_ACCMODE
+# define O_ACCMODE     0
+#endif
+#ifndef O_RDONLY
+# define O_RDONLY      0
+#endif
+#ifndef O_WRONLY
+# define O_WRONLY      0
+#endif
+#ifndef O_RWDR
+# define O_RWDR                0
+#endif
+#ifndef O_SHLOCK
+# define O_SHLOCK      0
+#endif
+#ifndef O_EXLOCK
+# define O_EXLOCK      0
+#endif
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW    0
+#endif
+#ifndef O_CREAT
+# define O_CREAT       0
+#endif
+#ifndef O_TRUNC
+# define O_TRUNC       0
+#endif
+#ifndef O_EXCL
+# define O_EXCL                0
+#endif
+#ifndef O_NOCTTY
+# define O_NOCTTY      0
+#endif
+#ifndef O_DIRECTORY
+# define O_DIRECTORY   0
+#endif
+#ifndef O_REGULAR
+# define O_REGULAR     0
+#endif
+/*
+ * flags that F_GETFL might return that we want to ignore
+ *
+ * F_GETFL should not actually return these, they're all just open()
+ * modifiers, rather than state, but just in case...
+ */
+#define IGNFLAGS (O_ACCMODE|O_RDONLY|O_WRONLY|O_RDWR|O_SHLOCK|O_EXLOCK| \
+    O_NOFOLLOW|O_CREAT|O_TRUNC|O_EXCL|O_NOCTTY|O_DIRECTORY|O_REGULAR)
 
 static int
 getflags(int fd, int p)
@@ -760,9 +843,10 @@
                        return -1;
                error("Can't get flags for fd=%d (%s)", fd, strerror(errno));
        }
+       f &= ~IGNFLAGS;         /* clear anything we know about, but ignore */
        if (c & FD_CLOEXEC)
                f |= O_CLOEXEC;
-       return f & ALLFLAGS;
+       return f;
 }
 
 static void



Home | Main Index | Thread Index | Old Index