1 // Copyright (C) 2002 Andrew Tridgell
2 // Copyright (C) 2011-2019 Joel Rosdahl
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License as published by the Free
6 // Software Foundation; either version 3 of the License, or (at your option)
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 // You should have received a copy of the GNU General Public License along with
15 // this program; if not, write to the Free Software Foundation, Inc., 51
16 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 extern struct conf *conf;
23 find_executable_in_path(const char *name, const char *exclude_name, char *path);
26 // Re-create a win32 command line string based on **argv.
27 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
29 win32argvtos(char *prefix, char **argv, int *length)
33 char *arg = prefix ? prefix : argv[i++];
36 for (int j = 0; arg[j]; j++) {
50 } while ((arg = argv[i++]));
52 char *ptr = malloc(k + 1);
60 arg = prefix ? prefix : argv[i++];
64 for (int j = 0; arg[j]; j++) {
84 } while ((arg = argv[i++]));
87 *length = ptr - str - 1;
92 win32getshell(char *path)
96 const char *ext = get_extension(path);
97 if (ext && strcasecmp(ext, ".sh") == 0 && (path_env = getenv("PATH"))) {
98 sh = find_executable_in_path("sh.exe", NULL, path_env);
100 if (!sh && getenv("CCACHE_DETECT_SHEBANG")) {
102 FILE *fp = fopen(path, "r");
105 fgets(buf, sizeof(buf), fp);
107 if (str_eq(buf, "#!/bin/sh") && (path_env = getenv("PATH"))) {
108 sh = find_executable_in_path("sh.exe", NULL, path_env);
117 void add_exe_ext_if_no_to_fullpath(char *full_path_win_ext, size_t max_size,
118 const char *ext, const char *path) {
119 if (!ext || (!str_eq(".exe", ext)
120 && !str_eq(".sh", ext)
121 && !str_eq(".bat", ext)
122 && !str_eq(".EXE", ext)
123 && !str_eq(".BAT", ext))) {
124 snprintf(full_path_win_ext, max_size, "%s.exe", path);
126 snprintf(full_path_win_ext, max_size, "%s", path);
131 win32execute(char *path, char **argv, int doreturn,
132 int fd_stdout, int fd_stderr)
134 PROCESS_INFORMATION pi;
135 memset(&pi, 0x00, sizeof(pi));
138 memset(&si, 0x00, sizeof(si));
140 char *sh = win32getshell(path);
145 si.cb = sizeof(STARTUPINFO);
146 if (fd_stdout != -1) {
147 si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
148 si.hStdError = (HANDLE)_get_osfhandle(fd_stderr);
149 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
150 si.dwFlags = STARTF_USESTDHANDLES;
151 if (si.hStdOutput == INVALID_HANDLE_VALUE
152 || si.hStdError == INVALID_HANDLE_VALUE) {
156 // Redirect subprocess stdout, stderr into current process.
157 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
158 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
159 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
160 si.dwFlags = STARTF_USESTDHANDLES;
161 if (si.hStdOutput == INVALID_HANDLE_VALUE
162 || si.hStdError == INVALID_HANDLE_VALUE) {
168 char *args = win32argvtos(sh, argv, &length);
169 const char *ext = strrchr(path, '.');
170 char full_path_win_ext[MAX_PATH] = {0};
171 add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path);
174 char *tmp_file = format("%s.tmp", path);
175 FILE *fp = create_tmp_file(&tmp_file, "w");
176 char atfile[MAX_PATH + 3];
177 fwrite(args, 1, length, fp);
179 cc_log("Error writing @file; this command will probably fail: %s", args);
182 snprintf(atfile, sizeof(atfile), "\"@%s\"", tmp_file);
183 ret = CreateProcess(NULL, atfile, NULL, NULL, 1, 0, NULL, NULL,
185 tmp_unlink(tmp_file);
189 ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL,
192 if (fd_stdout != -1) {
199 DWORD dw = GetLastError();
201 FORMAT_MESSAGE_ALLOCATE_BUFFER |
202 FORMAT_MESSAGE_FROM_SYSTEM |
203 FORMAT_MESSAGE_IGNORE_INSERTS,
204 NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
207 LPVOID lpDisplayBuf =
208 (LPVOID) LocalAlloc(LMEM_ZEROINIT,
209 (lstrlen((LPCTSTR) lpMsgBuf)
210 + lstrlen((LPCTSTR) __FILE__) + 200)
212 _snprintf((LPTSTR) lpDisplayBuf,
213 LocalSize(lpDisplayBuf) / sizeof(TCHAR),
214 TEXT("%s failed with error %lu: %s"), __FILE__, dw,
215 (const char *)lpMsgBuf);
217 cc_log("can't execute %s; OS returned error: %s",
218 full_path_win_ext, (char *)lpDisplayBuf);
221 LocalFree(lpDisplayBuf);
225 WaitForSingleObject(pi.hProcess, INFINITE);
228 GetExitCodeProcess(pi.hProcess, &exitcode);
229 CloseHandle(pi.hProcess);
230 CloseHandle(pi.hThread);
239 // Execute a compiler backend, capturing all output to the given paths the full
240 // path to the compiler to run is in argv[0].
242 execute(char **argv, int fd_out, int fd_err, pid_t *pid)
244 cc_log_argv("Executing ", argv);
251 fatal("Failed to fork: %s", strerror(errno));
260 x_exit(execv(argv[0], argv));
267 if (waitpid(*pid, &status, 0) != *pid) {
268 fatal("waitpid failed: %s", strerror(errno));
275 if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
279 return WEXITSTATUS(status);
283 // Find an executable by name in $PATH. Exclude any that are links to
286 find_executable(const char *name, const char *exclude_name)
288 if (is_absolute_path(name)) {
289 return x_strdup(name);
292 char *path = conf->path;
293 if (str_eq(path, "")) {
294 path = getenv("PATH");
297 cc_log("No PATH variable");
301 return find_executable_in_path(name, exclude_name, path);
305 find_executable_in_path(const char *name, const char *exclude_name, char *path)
307 path = x_strdup(path);
309 // Search the path looking for the first compiler of the right name that
311 char *saveptr = NULL;
312 for (char *tok = strtok_r(path, PATH_DELIM, &saveptr);
314 tok = strtok_r(NULL, PATH_DELIM, &saveptr)) {
316 char namebuf[MAX_PATH];
317 int ret = SearchPath(tok, name, NULL, sizeof(namebuf), namebuf, NULL);
319 char *exename = format("%s.exe", name);
320 ret = SearchPath(tok, exename, NULL, sizeof(namebuf), namebuf, NULL);
326 return x_strdup(namebuf);
329 struct stat st1, st2;
330 char *fname = format("%s/%s", tok, name);
331 // Look for a normal executable file.
332 if (access(fname, X_OK) == 0 &&
333 lstat(fname, &st1) == 0 &&
334 stat(fname, &st2) == 0 &&
335 S_ISREG(st2.st_mode)) {
336 if (S_ISLNK(st1.st_mode)) {
337 char *buf = x_realpath(fname);
339 char *p = basename(buf);
340 if (str_eq(p, exclude_name)) {
341 // It's a link to "ccache"!
364 print_command(FILE *fp, char **argv)
366 for (int i = 0; argv[i]; i++) {
367 fprintf(fp, "%s%s", (i == 0) ? "" : " ", argv[i]);
373 format_command(char **argv)
376 for (int i = 0; argv[i]; i++) {
377 len += (i == 0) ? 0 : 1;
378 len += strlen(argv[i]);
381 char *buf = x_malloc(len + 1);
383 for (int i = 0; argv[i]; i++) {
387 for (char *q = argv[i]; *q != '\0'; q++) {