* Search $PATH for a command. This emulates the path search that * execvp would perform, without actually executing the command so it * can be used before fork() to prepare to run a command using * execve() or after execvp() to diagnose why it failed. * * The caller should ensure that file contains no directory * separators. * * Returns the path to the command, as found in $PATH or NULL i
| 189 | * "foo.exe"). |
| 190 | */ |
| 191 | static char *locate_in_PATH(const char *file) |
| 192 | { |
| 193 | const char *p = getenv("PATH"); |
| 194 | struct strbuf buf = STRBUF_INIT; |
| 195 | |
| 196 | if (!p || !*p) |
| 197 | return NULL; |
| 198 | |
| 199 | while (1) { |
| 200 | const char *end = strchrnul(p, ':'); |
| 201 | |
| 202 | strbuf_reset(&buf); |
| 203 | |
| 204 | /* POSIX specifies an empty entry as the current directory. */ |
| 205 | if (end != p) { |
| 206 | strbuf_add(&buf, p, end - p); |
| 207 | strbuf_addch(&buf, '/'); |
| 208 | } |
| 209 | strbuf_addstr(&buf, file); |
| 210 | |
| 211 | if (is_executable(buf.buf)) |
| 212 | return strbuf_detach(&buf, NULL); |
| 213 | |
| 214 | if (!*end) |
| 215 | break; |
| 216 | p = end + 1; |
| 217 | } |
| 218 | |
| 219 | strbuf_release(&buf); |
| 220 | return NULL; |
| 221 | } |
| 222 | #endif |
| 223 | |
| 224 | int exists_in_PATH(const char *command) |
no test coverage detected