Mercurial > mm7
comparison lib/swig/swigwin-2.0.11/CCache/execute.c @ 1899:b3009adc0e2f
Adding swig, gitignore, hgignore
author | Nomad |
---|---|
date | Mon, 21 Oct 2013 10:42:27 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1867:eb580660bbbb | 1899:b3009adc0e2f |
---|---|
1 /* | |
2 Copyright (C) Andrew Tridgell 2002 | |
3 | |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2 of the License, or | |
7 (at your option) any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; if not, write to the Free Software | |
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 */ | |
18 | |
19 #include "ccache.h" | |
20 | |
21 #ifdef _WIN32 | |
22 char *argvtos(char **argv) | |
23 { | |
24 int i, len; | |
25 char *ptr, *str; | |
26 | |
27 for (i = 0, len = 0; argv[i]; i++) { | |
28 len += strlen(argv[i]) + 3; | |
29 } | |
30 | |
31 str = ptr = (char *)malloc(len + 1); | |
32 if (str == NULL) | |
33 return NULL; | |
34 | |
35 for (i = 0; argv[i]; i++) { | |
36 len = strlen(argv[i]); | |
37 *ptr++ = '"'; | |
38 memcpy(ptr, argv[i], len); | |
39 ptr += len; | |
40 *ptr++ = '"'; | |
41 *ptr++ = ' '; | |
42 } | |
43 *ptr = 0; | |
44 | |
45 return str; | |
46 } | |
47 #endif | |
48 | |
49 /* | |
50 execute a compiler backend, capturing all output to the given paths | |
51 the full path to the compiler to run is in argv[0] | |
52 */ | |
53 int execute(char **argv, | |
54 const char *path_stdout, | |
55 const char *path_stderr) | |
56 { | |
57 #ifdef _WIN32 | |
58 | |
59 #if 1 | |
60 PROCESS_INFORMATION pinfo; | |
61 STARTUPINFO sinfo; | |
62 BOOL ret; | |
63 DWORD exitcode; | |
64 char *args; | |
65 HANDLE fd_out, fd_err; | |
66 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; | |
67 | |
68 /* TODO: needs moving after possible exit() below, but before stdout is redirected */ | |
69 if (ccache_verbose) { | |
70 display_execute_args(argv); | |
71 } | |
72 | |
73 fd_out = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, | |
74 FILE_ATTRIBUTE_NORMAL, NULL); | |
75 if (fd_out == INVALID_HANDLE_VALUE) { | |
76 return STATUS_NOCACHE; | |
77 } | |
78 | |
79 fd_err = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, | |
80 FILE_ATTRIBUTE_NORMAL, NULL); | |
81 if (fd_err == INVALID_HANDLE_VALUE) { | |
82 return STATUS_NOCACHE; | |
83 } | |
84 | |
85 ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); | |
86 ZeroMemory(&sinfo, sizeof(STARTUPINFO)); | |
87 | |
88 sinfo.cb = sizeof(STARTUPINFO); | |
89 sinfo.hStdError = fd_err; | |
90 sinfo.hStdOutput = fd_out; | |
91 sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | |
92 sinfo.dwFlags |= STARTF_USESTDHANDLES; | |
93 | |
94 args = argvtos(argv); | |
95 | |
96 ret = CreateProcessA(argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL, | |
97 &sinfo, &pinfo); | |
98 | |
99 free(args); | |
100 CloseHandle(fd_out); | |
101 CloseHandle(fd_err); | |
102 | |
103 if (ret == 0) | |
104 return -1; | |
105 | |
106 WaitForSingleObject(pinfo.hProcess, INFINITE); | |
107 GetExitCodeProcess(pinfo.hProcess, &exitcode); | |
108 CloseHandle(pinfo.hProcess); | |
109 CloseHandle(pinfo.hThread); | |
110 | |
111 return exitcode; | |
112 #else /* possibly slightly faster */ | |
113 /* needs fixing to quote commandline options to handle spaces in CCACHE_DIR etc */ | |
114 int status = -2; | |
115 int fd, std_od = -1, std_ed = -1; | |
116 | |
117 /* TODO: needs moving after possible exit() below, but before stdout is redirected */ | |
118 if (ccache_verbose) { | |
119 display_execute_args(argv); | |
120 } | |
121 | |
122 unlink(path_stdout); | |
123 std_od = _dup(1); | |
124 fd = _open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); | |
125 if (fd == -1) { | |
126 exit(STATUS_NOCACHE); | |
127 } | |
128 _dup2(fd, 1); | |
129 _close(fd); | |
130 | |
131 unlink(path_stderr); | |
132 fd = _open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); | |
133 std_ed = _dup(2); | |
134 if (fd == -1) { | |
135 exit(STATUS_NOCACHE); | |
136 } | |
137 _dup2(fd, 2); | |
138 _close(fd); | |
139 | |
140 /* Spawn process (_exec* familly doesn't return) */ | |
141 status = _spawnv(_P_WAIT, argv[0], (const char **)argv); | |
142 | |
143 /* Restore descriptors */ | |
144 if (std_od != -1) _dup2(std_od, 1); | |
145 if (std_ed != -1) _dup2(std_ed, 2); | |
146 _flushall(); | |
147 | |
148 return (status>0); | |
149 | |
150 #endif | |
151 | |
152 #else | |
153 pid_t pid; | |
154 int status; | |
155 | |
156 pid = fork(); | |
157 if (pid == -1) fatal("Failed to fork"); | |
158 | |
159 if (pid == 0) { | |
160 int fd; | |
161 | |
162 /* TODO: needs moving after possible exit() below, but before stdout is redirected */ | |
163 if (ccache_verbose) { | |
164 display_execute_args(argv); | |
165 } | |
166 | |
167 unlink(path_stdout); | |
168 fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); | |
169 if (fd == -1) { | |
170 exit(STATUS_NOCACHE); | |
171 } | |
172 dup2(fd, 1); | |
173 close(fd); | |
174 | |
175 unlink(path_stderr); | |
176 fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); | |
177 if (fd == -1) { | |
178 exit(STATUS_NOCACHE); | |
179 } | |
180 dup2(fd, 2); | |
181 close(fd); | |
182 | |
183 exit(execv(argv[0], argv)); | |
184 } | |
185 | |
186 if (waitpid(pid, &status, 0) != pid) { | |
187 fatal("waitpid failed"); | |
188 } | |
189 | |
190 if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { | |
191 return -1; | |
192 } | |
193 | |
194 return WEXITSTATUS(status); | |
195 #endif | |
196 } | |
197 | |
198 | |
199 /* | |
200 find an executable by name in $PATH. Exclude any that are links to exclude_name | |
201 */ | |
202 char *find_executable(const char *name, const char *exclude_name) | |
203 { | |
204 #if _WIN32 | |
205 (void)exclude_name; | |
206 DWORD ret; | |
207 char namebuf[MAX_PATH]; | |
208 | |
209 ret = SearchPathA(getenv("CCACHE_PATH"), name, ".exe", | |
210 sizeof(namebuf), namebuf, NULL); | |
211 if (ret != 0) { | |
212 return x_strdup(namebuf); | |
213 } | |
214 | |
215 return NULL; | |
216 #else | |
217 char *path; | |
218 char *tok; | |
219 struct stat st1, st2; | |
220 | |
221 if (*name == '/') { | |
222 return x_strdup(name); | |
223 } | |
224 | |
225 path = getenv("CCACHE_PATH"); | |
226 if (!path) { | |
227 path = getenv("PATH"); | |
228 } | |
229 if (!path) { | |
230 cc_log("no PATH variable!?\n"); | |
231 stats_update(STATS_ENVIRONMMENT); | |
232 return NULL; | |
233 } | |
234 | |
235 path = x_strdup(path); | |
236 | |
237 /* search the path looking for the first compiler of the right name | |
238 that isn't us */ | |
239 for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) { | |
240 char *fname; | |
241 x_asprintf(&fname, "%s/%s", tok, name); | |
242 /* look for a normal executable file */ | |
243 if (access(fname, X_OK) == 0 && | |
244 lstat(fname, &st1) == 0 && | |
245 stat(fname, &st2) == 0 && | |
246 S_ISREG(st2.st_mode)) { | |
247 /* if its a symlink then ensure it doesn't | |
248 point at something called exclude_name */ | |
249 if (S_ISLNK(st1.st_mode)) { | |
250 char *buf = x_realpath(fname); | |
251 if (buf) { | |
252 char *p = str_basename(buf); | |
253 if (strcmp(p, exclude_name) == 0) { | |
254 /* its a link to "ccache" ! */ | |
255 free(p); | |
256 free(buf); | |
257 continue; | |
258 } | |
259 free(buf); | |
260 free(p); | |
261 } | |
262 } | |
263 | |
264 /* found it! */ | |
265 free(path); | |
266 return fname; | |
267 } | |
268 free(fname); | |
269 } | |
270 | |
271 return NULL; | |
272 #endif | |
273 } | |
274 | |
275 void display_execute_args(char **argv) | |
276 { | |
277 if (argv) { | |
278 printf("ccache executing: "); | |
279 while (*argv) { | |
280 printf("%s ", *argv); | |
281 ++argv; | |
282 } | |
283 printf("\n"); | |
284 fflush(stdout); | |
285 } | |
286 } |