Hi,
While studying the behavior of csh using ktrace I did notice it trying
to close every single fd up to _SC_OPEN_MAX except for the ones in use.
This seems a bit excessive, here's a different approach: since the fds
in use can vary one can't make assumptions about the largest fd in use.
Instead of looping over [0, _SC_OPEN_MAX), close all fds that reside in
between the gaps of fds in use. Once the largest fd in use is reached,
use closefrom().

Comments? OK?

Index: misc.c
===================================================================
RCS file: /cvs/src/bin/csh/misc.c,v
retrieving revision 1.19
diff -u -p -r1.19 misc.c
--- misc.c      14 Aug 2016 19:45:24 -0000      1.19
+++ misc.c      14 Jun 2017 16:50:38 -0000
@@ -38,6 +38,7 @@
 #include "csh.h"
 #include "extern.h"
 
+static int     fdcmp(int);
 static int     renum(int, int);
 
 int
@@ -163,6 +164,29 @@ lastchr(Char *cp)
 }
 
 /*
+ * Returns 0 if fd is in use, 1 if fd is greater than the largest used file
+ * descriptor and -1 otherwise.
+ */
+static int
+fdcmp(int fd)
+{
+    int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY };
+    int i, max;
+
+    max = -1;
+    for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) {
+       if (fd == fds[i])
+           return (0);
+       if (fds[i] > max)
+           max = fds[i];
+    }
+    if (fd > max)
+       return (1);
+
+    return (-1);
+}
+
+/*
  * This routine is called after an error to close up
  * any units which may have been left open accidentally.
  */
@@ -173,9 +197,15 @@ closem(void)
     int max = sysconf(_SC_OPEN_MAX);
 
     for (f = 0; f < max; f++)
-       if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
-           f != FSHTTY)
-           (void) close(f);
+       switch (fdcmp(f)) {
+       case 0:
+           continue;
+       case 1:
+           closefrom(f);
+           return;
+       default:
+           close(f);
+       }
 }
 
 void

Reply via email to