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);