? o Index: builtins.def =================================================================== RCS file: /cvsroot/src/bin/sh/builtins.def,v retrieving revision 1.23 diff -u -u -r1.23 builtins.def --- builtins.def 10 May 2015 20:30:54 -0000 1.23 +++ builtins.def 31 Oct 2016 20:52:16 -0000 @@ -49,6 +49,7 @@ bgcmd -j -u bg breakcmd -s break -s continue cdcmd -u cd chdir +cloexeccmd cloexec dotcmd -s . echocmd echo evalcmd -s eval Index: redir.c =================================================================== RCS file: /cvsroot/src/bin/sh/redir.c,v retrieving revision 1.47 diff -u -u -r1.47 redir.c --- redir.c 12 May 2016 13:31:37 -0000 1.47 +++ redir.c 31 Oct 2016 20:52:16 -0000 @@ -55,6 +55,7 @@ */ #include "main.h" +#include "builtins.h" #include "shell.h" #include "nodes.h" #include "jobs.h" @@ -551,3 +552,52 @@ (void)fcntl(fd, F_SETFD, FD_CLOEXEC); return fd; } + +static void +printone(int fd, int p) +{ + int c; + if ((c = fcntl(fd, F_GETFD)) == -1) { + if (!p) + return; + error("Can't get status for fd=%d (%s)", fd, strerror(errno)); + } + outfmt(out1, "%c%d\n", "-+"[c & FD_CLOEXEC], fd); +} + +static void +setone(int fd, int how) +{ + if ((fcntl(fd, F_SETFD, how)) == -1) + error("Can't %s close-on-exec for fd=%d (%s)", + how ? "set" : "clear", fd, strerror(errno)); +} + +int +cloexeccmd(int argc, char *argv[]) +{ + char *num; + argptr = argv + 1; + + if (!*argptr) { + 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); + return 0; + } + while ((num = *argptr++) != NULL) { + char c; + switch (c = *num) { + case '+': case '-': + num++; + break; + default: + printone(atoi(num), 1); + continue; + } + setone(atoi(num), c == '+' ? FD_CLOEXEC : 0); + } + return 0; +}