| 29 | |
| 30 | #ifndef _WIN32 |
| 31 | std::string run_cmd(const char *cmd, ...) |
| 32 | { |
| 33 | std::vector <const char *> arr; |
| 34 | va_list ap; |
| 35 | va_start(ap, cmd); |
| 36 | const char *c = cmd; |
| 37 | do { |
| 38 | arr.push_back(c); |
| 39 | c = va_arg(ap, const char*); |
| 40 | } while (c != NULL); |
| 41 | va_end(ap); |
| 42 | arr.push_back(NULL); |
| 43 | |
| 44 | int fret = fork(); |
| 45 | if (fret == -1) { |
| 46 | int err = errno; |
| 47 | ostringstream oss; |
| 48 | oss << "run_cmd(" << cmd << "): unable to fork(): " << cpp_strerror(err); |
| 49 | return oss.str(); |
| 50 | } |
| 51 | else if (fret == 0) { |
| 52 | // execvp doesn't modify its arguments, so the const-cast here is safe. |
| 53 | close(STDIN_FILENO); |
| 54 | close(STDOUT_FILENO); |
| 55 | close(STDERR_FILENO); |
| 56 | execvp(cmd, (char * const*)&arr[0]); |
| 57 | _exit(127); |
| 58 | } |
| 59 | int status; |
| 60 | while (waitpid(fret, &status, 0) == -1) { |
| 61 | int err = errno; |
| 62 | if (err == EINTR) |
| 63 | continue; |
| 64 | ostringstream oss; |
| 65 | oss << "run_cmd(" << cmd << "): waitpid error: " |
| 66 | << cpp_strerror(err); |
| 67 | return oss.str(); |
| 68 | } |
| 69 | if (WIFEXITED(status)) { |
| 70 | int wexitstatus = WEXITSTATUS(status); |
| 71 | if (wexitstatus != 0) { |
| 72 | ostringstream oss; |
| 73 | oss << "run_cmd(" << cmd << "): exited with status " << wexitstatus; |
| 74 | return oss.str(); |
| 75 | } |
| 76 | return ""; |
| 77 | } |
| 78 | else if (WIFSIGNALED(status)) { |
| 79 | ostringstream oss; |
| 80 | oss << "run_cmd(" << cmd << "): terminated by signal"; |
| 81 | return oss.str(); |
| 82 | } |
| 83 | ostringstream oss; |
| 84 | oss << "run_cmd(" << cmd << "): terminated by unknown mechanism"; |
| 85 | return oss.str(); |
| 86 | } |
| 87 | #else |
| 88 | std::string run_cmd(const char *cmd, ...) |