fdflags -s  was re-parsing the setspec for each fd argument.
This is problematic because it is using  strtok()  to parse it
destructively.
So, only the first part of the setspec will be set for all file
descriptors; the other parts will only be set for the first file
descriptor:

  $ enable fdflags
  $ exec {foo1}</dev/null {foo2}</dev/null
  $ fdflags -s +nonblock,+cloexec -- "$foo1" "$foo2"
  $ ls -ld /proc/self/fd/"$foo1" /proc/self/fd/"$foo2"
  ls: cannot access '/proc/self/fd/10': No such file or directory
  lr-x------ 1 emanuele6 wheel 64 Nov  5 14:45 /proc/self/fd/11 -> /dev/null
  $ fdflags -- "$foo1" "$foo2"
  10:nonblock,cloexec
  11:nonblock
  $ exec {foo1}<&- {foo2}<&- {foo3}</dev/null {foo4}</dev/null
  $ fdflags -s +cloexec,+nonblock -- "$foo3" "$foo4"
  $ fdflags -- "$foo3" "$foo4"
  11:nonblock,cloexec
  13:nonblock

With this patch, the setspec string is only parsed once destructively,
and then the parsed values are reused. That fixes the bug.
---
 examples/loadables/fdflags.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/examples/loadables/fdflags.c b/examples/loadables/fdflags.c
index 48a1417f..d95b4815 100644
--- a/examples/loadables/fdflags.c
+++ b/examples/loadables/fdflags.c
@@ -224,16 +224,14 @@ parseflags(char *s, int *p, int *n)
 }
 
 static void
-setone(int fd, char *v, int verbose)
+setone(int fd, int pos, int neg, int verbose)
 {
-  int f, n, pos, neg, cloexec;
+  int f, n, cloexec;
 
   f = getflags(fd, 1);
   if (f == -1)
     return;
 
-  parseflags(v, &pos, &neg);
-
   cloexec = -1;
 
   if ((pos & O_CLOEXEC) && (f & O_CLOEXEC) == 0)
@@ -280,7 +278,7 @@ getmaxfd (void)
 int
 fdflags_builtin (WORD_LIST *list)
 {
-  int opt, maxfd, i, num, verbose, setflag;
+  int opt, maxfd, i, num, verbose, setflag, setpos, setneg;
   char *setspec;
   WORD_LIST *l;
   intmax_t inum;
@@ -324,6 +322,9 @@ fdflags_builtin (WORD_LIST *list)
       return (EXECUTION_SUCCESS);
     }
 
+  if (setflag)
+    parseflags (setspec, &setpos, &setneg);
+
   opt = EXECUTION_SUCCESS;
   for (l = list; l; l = l->next)
     {
@@ -335,7 +336,7 @@ fdflags_builtin (WORD_LIST *list)
        }
       num = inum;              /* truncate to int */
       if (setflag)
-       setone (num, setspec, verbose);
+       setone (num, setpos, setneg, verbose);
       else
        printone (num, 1, verbose);
     }
-- 
2.42.0


Reply via email to