Source-Changes-HG archive

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

[src/trunk]: src/bin/sh Add fdflags builtin. Discussed with Chet and he has i...



details:   https://anonhg.NetBSD.org/src/rev/a2d3df0eb91d
branches:  trunk
changeset: 821364:a2d3df0eb91d
user:      christos <christos%NetBSD.org@localhost>
date:      Thu Feb 02 20:00:40 2017 +0000

description:
Add fdflags builtin. Discussed with Chet and he has implemented it for
bash too.

diffstat:

 bin/sh/builtins.def |    3 +-
 bin/sh/redir.c      |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/sh/sh.1         |   26 ++++++-
 3 files changed, 227 insertions(+), 5 deletions(-)

diffs (293 lines):

diff -r 5b37bef2d8f7 -r a2d3df0eb91d bin/sh/builtins.def
--- a/bin/sh/builtins.def       Thu Feb 02 19:55:05 2017 +0000
+++ b/bin/sh/builtins.def       Thu Feb 02 20:00:40 2017 +0000
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#      $NetBSD: builtins.def,v 1.23 2015/05/10 20:30:54 joerg Exp $
+#      $NetBSD: builtins.def,v 1.24 2017/02/02 20:00:40 christos Exp $
 #
 # Copyright (c) 1991, 1993
 #      The Regents of the University of California.  All rights reserved.
@@ -73,6 +73,7 @@
 readcmd                -u read
 returncmd      -s return
 setcmd         -s set
+fdflagscmd     fdflags
 setvarcmd      setvar
 shiftcmd       -s shift
 timescmd       -s times
diff -r 5b37bef2d8f7 -r a2d3df0eb91d bin/sh/redir.c
--- a/bin/sh/redir.c    Thu Feb 02 19:55:05 2017 +0000
+++ b/bin/sh/redir.c    Thu Feb 02 20:00:40 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: redir.c,v 1.49 2017/01/21 23:03:36 christos Exp $      */
+/*     $NetBSD: redir.c,v 1.50 2017/02/02 20:00:40 christos 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.49 2017/01/21 23:03:36 christos Exp $");
+__RCSID("$NetBSD: redir.c,v 1.50 2017/02/02 20:00:40 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -56,6 +56,7 @@
  */
 
 #include "main.h"
+#include "builtins.h"
 #include "shell.h"
 #include "nodes.h"
 #include "jobs.h"
@@ -552,3 +553,201 @@
        (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
        return fd;
 }
+
+static const struct {
+       const char *name;
+       uint32_t value;
+} nv[] = {
+#ifdef O_APPEND
+       { "append",     O_APPEND        },
+#endif
+#ifdef O_ASYNC
+       { "async",      O_ASYNC         },
+#endif
+#ifdef O_SYNC
+       { "sync",       O_SYNC          },
+#endif
+#ifdef O_NONBLOCK
+       { "nonblock",   O_NONBLOCK      },
+#endif
+#ifdef O_FSYNC
+       { "fsync",      O_FSYNC         },
+#endif
+#ifdef O_DSYNC
+       { "dsync",      O_DSYNC         },
+#endif
+#ifdef O_RSYNC
+       { "rsync",      O_RSYNC         },
+#endif
+#ifdef O_ALTIO
+       { "altio",      O_ALT_IO        },
+#endif
+#ifdef O_DIRECT
+       { "direct",     O_DIRECT        },
+#endif
+#ifdef O_NOSIGPIPE
+       { "nosigpipe",  O_NOSIGPIPE     },
+#endif
+#ifdef O_CLOEXEC
+       { "cloexec",    O_CLOEXEC       },
+#endif
+};
+#define ALLFLAGS (O_APPEND|O_ASYNC|O_SYNC|O_NONBLOCK|O_DSYNC|O_RSYNC|\
+    O_ALT_IO|O_DIRECT|O_NOSIGPIPE|O_CLOEXEC)
+
+static int
+getflags(int fd, int p)
+{
+       int c, f;
+
+       if ((c = fcntl(fd, F_GETFD)) == -1) {
+               if (!p)
+                       return -1;
+               error("Can't get status for fd=%d (%s)", fd, strerror(errno));
+       }
+       if ((f = fcntl(fd, F_GETFL)) == -1) {
+               if (!p)
+                       return -1;
+               error("Can't get flags for fd=%d (%s)", fd, strerror(errno));
+       }
+       if (c)
+               f |= O_CLOEXEC;
+       return f & ALLFLAGS;
+}
+
+static void
+printone(int fd, int p, int verbose)
+{
+       int f = getflags(fd, p);
+
+       if (f == -1)
+               return;
+
+       outfmt(out1, "%d:", fd);
+       for (size_t i = 0; i < __arraycount(nv); i++) {
+               if (f & nv[i].value) {
+                       outfmt(out1, "%s%s", verbose ? "+" : "", nv[i].name);
+                       f &= ~nv[i].value;
+               } else if (verbose)
+                       outfmt(out1, "-%s", nv[i].name);
+               else
+                       continue;
+               if (f || (verbose && i != __arraycount(nv) - 1))
+                       outfmt(out1, ",");
+       }
+       outfmt(out1, "\n");
+}
+
+static int
+parseflags(char *s, int *p, int *n)
+{
+       int f = 0, *v;
+
+       *p = 0;
+       *n = 0;
+       for (s = strtok(s, ","); s; s = strtok(NULL, ",")) {
+               size_t i;
+               switch (*s) {
+               case '+':
+                       v = p;
+                       s++;
+                       break;
+               case '-':
+                       v = n;
+                       s++;
+                       break;
+               default:
+                       v = &f;
+                       break;
+               }
+                       
+               for (i = 0; i < __arraycount(nv); i++)
+                       if (strcmp(s, nv[i].name) == 0) {
+                               *v |= nv[i].value;
+                               break;
+                       }
+               if (i == __arraycount(nv))
+                       error("Bad flag `%s'", s);
+       }
+       return f;
+}
+
+static void
+setone(int fd, int pos, int neg, int verbose)
+{
+       int f = getflags(fd, 1);
+       if (f == -1)
+               return;
+
+       int cloexec = -1;
+       if ((pos & O_CLOEXEC) && !(f & O_CLOEXEC))
+               cloexec = FD_CLOEXEC;
+       if ((neg & O_CLOEXEC) && (f & O_CLOEXEC))
+               cloexec = 0;
+
+       if (cloexec != -1 && fcntl(fd, F_SETFD, cloexec) == -1)
+               error("Can't set status for fd=%d (%s)", fd, strerror(errno));
+
+       pos &= ~O_CLOEXEC;
+       neg &= ~O_CLOEXEC;
+       f &= ~O_CLOEXEC;
+       int n = f;
+       n |= pos;
+       n &= ~neg;
+       if (n != f && fcntl(fd, F_SETFL, n) == -1)
+               error("Can't set flags for fd=%d (%s)", fd, strerror(errno));
+       if (verbose)
+               printone(fd, 1, verbose);
+}
+
+int
+fdflagscmd(int argc, char *argv[])
+{
+       char *num;
+       int verbose = 0, ch, pos = 0, neg = 0;
+       char *setflags = NULL;
+
+       optreset = 1; optind = 1; /* initialize getopt */
+       while ((ch = getopt(argc, argv, ":vs:")) != -1)
+               switch ((char)ch) {
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 's':
+                       setflags = optarg;
+                       break;
+               case '?':
+               default:
+               msg:
+                       error("Usage: fdflags [-v] [-s <flags>] [fd...]");
+                       /* NOTREACHED */
+               }
+
+       argc -= optind, argv += optind;
+
+       if (setflags && parseflags(setflags, &pos, &neg))
+               error("Need + or - before flags");
+
+       if (argc == 0) {
+               if (setflags)
+                       goto msg;
+               int maxfd = fcntl(0, F_MAXFD);
+               if (maxfd == -1)
+                       error("Can't get max fd (%s)", strerror(errno));
+               for (int i = 0; i <= maxfd; i++)
+                       printone(i, 0, verbose);
+               return 0;
+       }
+
+       while ((num = *argv++) != NULL) {
+               int e;
+               int fd = (int)strtoi(num, NULL, 0, 0, INT_MAX, &e);
+               if (e)
+                       error("Can't parse `%s' (%s)", num, strerror(e));
+               if (setflags)
+                       setone(fd, pos, neg, verbose);
+               else
+                       printone(fd, 1, verbose);
+       }
+       return 0;
+}
diff -r 5b37bef2d8f7 -r a2d3df0eb91d bin/sh/sh.1
--- a/bin/sh/sh.1       Thu Feb 02 19:55:05 2017 +0000
+++ b/bin/sh/sh.1       Thu Feb 02 20:00:40 2017 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.123 2016/05/12 13:15:43 kre Exp $
+.\"    $NetBSD: sh.1,v 1.124 2017/02/02 20:00:40 christos Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"    @(#)sh.1        8.6 (Berkeley) 5/4/95
 .\"
-.Dd May 9, 2016
+.Dd February 1, 2017
 .Dt SH 1
 .ds flags abCEeFfhnuvxIimpqV
 .Os
@@ -1685,6 +1685,28 @@
 .El
 .It fg Op Ar job
 Move the specified job or the current job to the foreground.
+.It fdflags Oo Fl v Oc Oo fd ... Oc
+.It fdflags Oo Fl v Oc Fl s Ar flags fd Oo ... Oc
+Get or set file descriptor flags.
+The 
+.Fl v
+argument enables verbose printing, printing flags that are also off, and
+the flags of the file descriptor being set after setting.
+The
+.Fl s
+flag interprets the
+.Ar flags
+argument as a comma separated list of file descriptor flags, each preceded
+with a
+.Dq +
+or a
+.Dq -
+indicating to set or clear the respective flag.
+Valid flags are:
+append,async,sync,nonblock,fsync,dsync,rsync,direct,nosigpipe,cloexec.
+See
+.Xr fcntl 2
+for more information.
 .It getopts Ar optstring var
 The
 .Tn POSIX



Home | Main Index | Thread Index | Old Index