O_CLOEXEC was added in Mac OS X 10.7. Revert to fcntl() to set the CLOEXEC flag for older system versions. --- builtin/dot.c.orig +++ builtin/dot.c @@ -28,11 +28,13 @@ int builtin_dot(struct mrsh_state *state, int argc, char *argv[]) { return 1; } - int fd = open(path, O_RDONLY | O_CLOEXEC); + int fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, "unable to open %s for reading: %s\n", argv[1], strerror(errno)); goto error; + } else { + fcntl(fd, F_SETFD, FD_CLOEXEC); } free(path); --- main.c.orig +++ main.c @@ -41,11 +41,13 @@ int main(int argc, char *argv[]) { strlen(init_args.command_str)); } else { if (init_args.command_file) { - fd = open(init_args.command_file, O_RDONLY | O_CLOEXEC); + fd = open(init_args.command_file, O_RDONLY); if (fd < 0) { fprintf(stderr, "failed to open %s for reading: %s\n", init_args.command_file, strerror(errno)); return 1; + } else { + fcntl(fd, F_SETFD, FD_CLOEXEC); } } else { fd = STDIN_FILENO; --- shell/redir.c.orig +++ shell/redir.c @@ -116,18 +116,27 @@ int process_redir(const struct mrsh_io_redirect *redir, int *redir_fd) { errno = 0; switch (redir->op) { case MRSH_IO_LESS: // < - fd = open(filename, O_CLOEXEC | O_RDONLY); + fd = open(filename, O_RDONLY); + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + } default_redir_fd = STDIN_FILENO; break; case MRSH_IO_GREAT: // > case MRSH_IO_CLOBBER: // >| fd = open(filename, - O_CLOEXEC | O_WRONLY | O_CREAT | O_TRUNC, 0644); + O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + } default_redir_fd = STDOUT_FILENO; break; case MRSH_IO_DGREAT: // >> fd = open(filename, - O_CLOEXEC | O_WRONLY | O_CREAT | O_APPEND, 0644); + O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + } default_redir_fd = STDOUT_FILENO; break; case MRSH_IO_LESSAND: // <& @@ -141,7 +150,10 @@ int process_redir(const struct mrsh_io_redirect *redir, int *redir_fd) { default_redir_fd = STDOUT_FILENO; break; case MRSH_IO_LESSGREAT: // <> - fd = open(filename, O_CLOEXEC | O_RDWR | O_CREAT, 0644); + fd = open(filename, O_RDWR | O_CREAT, 0644); + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + } default_redir_fd = STDIN_FILENO; break; case MRSH_IO_DLESS: // << --- shell/task/task.c.orig +++ shell/task/task.c @@ -26,11 +26,13 @@ static int run_subshell(struct mrsh_context *ctx, struct mrsh_array *array) { if (!(ctx->state->options & MRSH_OPT_MONITOR)) { // If job control is disabled, stdin is /dev/null - int fd = open("/dev/null", O_CLOEXEC | O_RDONLY); + int fd = open("/dev/null", O_RDONLY); if (fd < 0) { fprintf(stderr, "failed to open /dev/null: %s\n", strerror(errno)); exit(1); + } else { + fcntl(fd, F_SETFD, FD_CLOEXEC); } if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO); @@ -354,11 +356,13 @@ int run_command_list_array(struct mrsh_context *ctx, struct mrsh_array *array) { if (!(state->options & MRSH_OPT_MONITOR)) { // If job control is disabled, stdin is /dev/null - int fd = open("/dev/null", O_CLOEXEC | O_RDONLY); + int fd = open("/dev/null", O_RDONLY); if (fd < 0) { fprintf(stderr, "failed to open /dev/null: %s\n", strerror(errno)); exit(1); + } else { + fcntl(fd, F_SETFD, FD_CLOEXEC); } if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO);