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 }