| 1015 | #endif |
| 1016 | |
| 1017 | static int cbm_subprocess_spawn_posix(cbm_subprocess_t *process) { |
| 1018 | int input_flags = O_RDONLY; |
| 1019 | #ifdef O_CLOEXEC |
| 1020 | input_flags |= O_CLOEXEC; |
| 1021 | #endif |
| 1022 | int input = cbm_posix_fd_at_least_three(open("/dev/null", input_flags)); |
| 1023 | const char *target = process->log_file ? process->log_file : "/dev/null"; |
| 1024 | int output_flags = O_WRONLY | O_CREAT | O_TRUNC; |
| 1025 | #ifdef O_CLOEXEC |
| 1026 | output_flags |= O_CLOEXEC; |
| 1027 | #endif |
| 1028 | #ifdef O_NOFOLLOW |
| 1029 | output_flags |= O_NOFOLLOW; |
| 1030 | #endif |
| 1031 | int output = cbm_posix_fd_at_least_three(open(target, output_flags, 0600)); |
| 1032 | if (input < 0 || output < 0) { |
| 1033 | if (input >= 0) { |
| 1034 | (void)close(input); |
| 1035 | } |
| 1036 | if (output >= 0) { |
| 1037 | (void)close(output); |
| 1038 | } |
| 1039 | return -1; |
| 1040 | } |
| 1041 | struct stat output_status; |
| 1042 | if (fstat(output, &output_status) != 0 || |
| 1043 | (process->log_file && !S_ISREG(output_status.st_mode))) { |
| 1044 | (void)close(input); |
| 1045 | (void)close(output); |
| 1046 | return -1; |
| 1047 | } |
| 1048 | if (process->log_file && fchmod(output, 0600) != 0) { |
| 1049 | (void)close(input); |
| 1050 | (void)close(output); |
| 1051 | return -1; |
| 1052 | } |
| 1053 | |
| 1054 | long max_fd = sysconf(_SC_OPEN_MAX); |
| 1055 | if (max_fd < 0 || max_fd > 1048576L) { |
| 1056 | max_fd = 65536L; |
| 1057 | } |
| 1058 | |
| 1059 | pid_t pid = -1; |
| 1060 | #ifdef __APPLE__ |
| 1061 | int spawn_rc = cbm_posix_spawn_apple(process, input, output, &pid); |
| 1062 | if (spawn_rc < 0) { |
| 1063 | (void)close(input); |
| 1064 | (void)close(output); |
| 1065 | return -1; |
| 1066 | } |
| 1067 | if (spawn_rc > 0) { /* exec-class failure: reproduce the fork+exec 127 */ |
| 1068 | pid = fork(); |
| 1069 | if (pid < 0) { |
| 1070 | (void)close(input); |
| 1071 | (void)close(output); |
| 1072 | return -1; |
| 1073 | } |
| 1074 | if (pid == 0) { |
no test coverage detected