Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | #include <stdlib.h>␊ |
2 | #include <ctype.h>␊ |
3 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
4 | #undef UNICODE␊ |
5 | #include <windows.h>␊ |
6 | #else␊ |
7 | #include <unistd.h>␊ |
8 | #include <stdlib.h>␊ |
9 | #include <sys/types.h>␊ |
10 | #include <sys/wait.h>␊ |
11 | #include <errno.h>␊ |
12 | extern char **environ;␊ |
13 | #endif␊ |
14 | ␊ |
15 | #include <qglobal.h>␊ |
16 | #include <qdatetime.h>␊ |
17 | ␊ |
18 | #if defined(_MSC_VER) || defined(__BORLANDC__)␊ |
19 | #define popen _popen␊ |
20 | #define pclose _pclose␊ |
21 | #endif␊ |
22 | ␊ |
23 | #include "portable.h"␊ |
24 | #ifndef NODEBUG␊ |
25 | #include "debug.h"␊ |
26 | #endif␊ |
27 | //#include "doxygen.h"␊ |
28 | ␊ |
29 | static double g_sysElapsedTime;␊ |
30 | static QTime g_time;␊ |
31 | ␊ |
32 | int portable_system(const char *command,const char *args,bool commandHasConsole)␊ |
33 | {␊ |
34 | ␊ |
35 | if (command==0) return 1;␊ |
36 | ␊ |
37 | QCString fullCmd=command;␊ |
38 | fullCmd=fullCmd.stripWhiteSpace();␊ |
39 | if (fullCmd.at(0)!='"' && fullCmd.find(' ')!=-1)␊ |
40 | {␊ |
41 | // add quotes around command as it contains spaces and is not quoted already␊ |
42 | fullCmd="\""+fullCmd+"\"";␊ |
43 | }␊ |
44 | fullCmd += " ";␊ |
45 | fullCmd += args;␊ |
46 | #ifndef NODEBUG␊ |
47 | Debug::print(Debug::ExtCmd,0,"Executing external command `%s`\n",fullCmd.data());␊ |
48 | #endif␊ |
49 | ␊ |
50 | #if !defined(_WIN32) || defined(__CYGWIN__)␊ |
51 | commandHasConsole=commandHasConsole;␊ |
52 | /*! taken from the system() manpage on my Linux box */␊ |
53 | int pid,status=0;␊ |
54 | ␊ |
55 | #ifdef _OS_SOLARIS // for Solaris we use vfork since it is more memory efficient␊ |
56 | ␊ |
57 | // on Solaris fork() duplicates the memory usage␊ |
58 | // so we use vfork instead␊ |
59 | ␊ |
60 | // spawn shell␊ |
61 | if ((pid=vfork())<0)␊ |
62 | {␊ |
63 | status=-1;␊ |
64 | }␊ |
65 | else if (pid==0)␊ |
66 | {␊ |
67 | execl("/bin/sh","sh","-c",fullCmd.data(),(char*)0);␊ |
68 | _exit(127);␊ |
69 | }␊ |
70 | else␊ |
71 | {␊ |
72 | while (waitpid(pid,&status,0 )<0)␊ |
73 | {␊ |
74 | if (errno!=EINTR)␊ |
75 | {␊ |
76 | status=-1;␊ |
77 | break;␊ |
78 | }␊ |
79 | }␊ |
80 | }␊ |
81 | return status;␊ |
82 | ␊ |
83 | #else // Other Unices just use fork␊ |
84 | ␊ |
85 | pid = fork();␊ |
86 | if (pid==-1) return -1;␊ |
87 | if (pid==0)␊ |
88 | {␊ |
89 | const char * argv[4];␊ |
90 | argv[0] = "sh";␊ |
91 | argv[1] = "-c";␊ |
92 | argv[2] = fullCmd.data();␊ |
93 | argv[3] = 0;␊ |
94 | execve("/bin/sh",(char * const *)argv,environ);␊ |
95 | exit(127);␊ |
96 | }␊ |
97 | for (;;)␊ |
98 | {␊ |
99 | if (waitpid(pid,&status,0)==-1)␊ |
100 | {␊ |
101 | if (errno!=EINTR) return -1;␊ |
102 | }␊ |
103 | else␊ |
104 | {␊ |
105 | if (WIFEXITED(status))␊ |
106 | {␊ |
107 | return WEXITSTATUS(status);␊ |
108 | }␊ |
109 | else␊ |
110 | {␊ |
111 | return status;␊ |
112 | }␊ |
113 | }␊ |
114 | }␊ |
115 | #endif // !_OS_SOLARIS␊ |
116 | ␊ |
117 | #else // Win32 specific␊ |
118 | if (commandHasConsole)␊ |
119 | {␊ |
120 | return system(fullCmd);␊ |
121 | }␊ |
122 | else␊ |
123 | {␊ |
124 | // gswin32 is a GUI api which will pop up a window and run␊ |
125 | // asynchronously. To prevent both, we use ShellExecuteEx and␊ |
126 | // WaitForSingleObject (thanks to Robert Golias for the code)␊ |
127 | ␊ |
128 | SHELLEXECUTEINFO sInfo = {␊ |
129 | sizeof(SHELLEXECUTEINFO), /* structure size */␊ |
130 | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI, /* tell us the process␊ |
131 | * handle so we can wait till it's done | ␊ |
132 | * do not display msg box if error ␊ |
133 | */␊ |
134 | NULL, /* window handle */␊ |
135 | NULL, /* action to perform: open */␊ |
136 | command, /* file to execute */␊ |
137 | args, /* argument list */ ␊ |
138 | NULL, /* use current working dir */␊ |
139 | SW_HIDE, /* minimize on start-up */␊ |
140 | 0, /* application instance handle */␊ |
141 | NULL, /* ignored: id list */␊ |
142 | NULL, /* ignored: class name */␊ |
143 | NULL, /* ignored: key class */␊ |
144 | 0, /* ignored: hot key */␊ |
145 | NULL, /* ignored: icon */␊ |
146 | NULL /* resulting application handle */␊ |
147 | };␊ |
148 | if (!ShellExecuteEx(&sInfo))␊ |
149 | {␊ |
150 | return -1;␊ |
151 | }␊ |
152 | else if (sInfo.hProcess) /* executable was launched, wait for it to finish */␊ |
153 | {␊ |
154 | WaitForSingleObject(sInfo.hProcess,INFINITE); ␊ |
155 | CloseHandle(sInfo.hProcess);␊ |
156 | }␊ |
157 | }␊ |
158 | return 0;␊ |
159 | #endif␊ |
160 | ␊ |
161 | }␊ |
162 | ␊ |
163 | uint portable_pid()␊ |
164 | {␊ |
165 | uint pid;␊ |
166 | #if !defined(_WIN32) || defined(__CYGWIN__)␊ |
167 | pid = (uint)getpid();␊ |
168 | #else␊ |
169 | pid = (uint)GetCurrentProcessId();␊ |
170 | #endif␊ |
171 | return pid;␊ |
172 | }␊ |
173 | ␊ |
174 | static char **last_environ;␊ |
175 | ␊ |
176 | void portable_setenv(const char *name,const char *value)␊ |
177 | {␊ |
178 | if (value==0) value="";␊ |
179 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
180 | SetEnvironmentVariable(name,value);␊ |
181 | #else␊ |
182 | register char **ep = 0;␊ |
183 | register size_t size;␊ |
184 | const size_t namelen=strlen(name);␊ |
185 | const size_t vallen=strlen(value) + 1;␊ |
186 | ␊ |
187 | size = 0;␊ |
188 | if (environ!=0)␊ |
189 | {␊ |
190 | for (ep = environ; *ep; ++ep)␊ |
191 | {␊ |
192 | if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')␊ |
193 | break;␊ |
194 | else␊ |
195 | ++size;␊ |
196 | }␊ |
197 | }␊ |
198 | ␊ |
199 | if (environ==0 || *ep==0) /* add new string */␊ |
200 | {␊ |
201 | char **new_environ;␊ |
202 | if (environ == last_environ && environ!=0)␊ |
203 | {␊ |
204 | // We allocated this space; we can extend it. ␊ |
205 | new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *));␊ |
206 | }␊ |
207 | else␊ |
208 | {␊ |
209 | new_environ = (char **) malloc ((size + 2) * sizeof (char *));␊ |
210 | }␊ |
211 | ␊ |
212 | if (new_environ==0) // no more memory ␊ |
213 | {␊ |
214 | return;␊ |
215 | }␊ |
216 | ␊ |
217 | new_environ[size] = (char *)malloc (namelen + 1 + vallen);␊ |
218 | if (new_environ[size]==0)␊ |
219 | {␊ |
220 | free (new_environ);␊ |
221 | return;␊ |
222 | }␊ |
223 | ␊ |
224 | if (environ != last_environ)␊ |
225 | {␊ |
226 | memcpy ((char *) new_environ, environ, size * sizeof (char *));␊ |
227 | }␊ |
228 | ␊ |
229 | memcpy(new_environ[size], name, namelen);␊ |
230 | new_environ[size][namelen] = '=';␊ |
231 | memcpy(&new_environ[size][namelen + 1], value, vallen);␊ |
232 | new_environ[size + 1] = 0;␊ |
233 | last_environ = environ = new_environ;␊ |
234 | }␊ |
235 | else /* replace existing string */␊ |
236 | {␊ |
237 | size_t len = strlen (*ep);␊ |
238 | if (len + 1 < namelen + 1 + vallen)␊ |
239 | {␊ |
240 | /* The existing string is too short; malloc a new one. */␊ |
241 | char *newString = (char *)malloc(namelen + 1 + vallen);␊ |
242 | if (newString==0)␊ |
243 | {␊ |
244 | return;␊ |
245 | }␊ |
246 | *ep = newString;␊ |
247 | }␊ |
248 | memcpy(*ep, name, namelen);␊ |
249 | (*ep)[namelen] = '=';␊ |
250 | memcpy(&(*ep)[namelen + 1], value, vallen);␊ |
251 | }␊ |
252 | ␊ |
253 | #endif␊ |
254 | }␊ |
255 | ␊ |
256 | void portable_unsetenv(const char *variable)␊ |
257 | {␊ |
258 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
259 | SetEnvironmentVariable(variable,0);␊ |
260 | #else␊ |
261 | /* Some systems don't have unsetenv(), so we do it ourselves */␊ |
262 | size_t len;␊ |
263 | char **ep;␊ |
264 | ␊ |
265 | if (variable == NULL || *variable == '\0' || strchr (variable, '=') != NULL)␊ |
266 | {␊ |
267 | return; // not properly formatted␊ |
268 | }␊ |
269 | ␊ |
270 | len = strlen(variable);␊ |
271 | ␊ |
272 | ep = environ;␊ |
273 | while (*ep != NULL)␊ |
274 | {␊ |
275 | if (!strncmp(*ep, variable, len) && (*ep)[len]=='=')␊ |
276 | {␊ |
277 | /* Found it. Remove this pointer by moving later ones back. */␊ |
278 | char **dp = ep;␊ |
279 | do dp[0] = dp[1]; while (*dp++);␊ |
280 | /* Continue the loop in case NAME appears again. */␊ |
281 | }␊ |
282 | else␊ |
283 | {␊ |
284 | ++ep;␊ |
285 | }␊ |
286 | }␊ |
287 | #endif␊ |
288 | }␊ |
289 | ␊ |
290 | const char *portable_getenv(const char *variable)␊ |
291 | {␊ |
292 | return getenv(variable);␊ |
293 | }␊ |
294 | ␊ |
295 | portable_off_t portable_fseek(FILE *f,portable_off_t offset, int whence)␊ |
296 | {␊ |
297 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
298 | return _fseeki64(f,offset,whence);␊ |
299 | #else␊ |
300 | return fseeko(f,offset,whence);␊ |
301 | #endif␊ |
302 | }␊ |
303 | ␊ |
304 | portable_off_t portable_ftell(FILE *f)␊ |
305 | {␊ |
306 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
307 | return _ftelli64(f);␊ |
308 | #else␊ |
309 | return ftello(f);␊ |
310 | #endif␊ |
311 | }␊ |
312 | ␊ |
313 | FILE *portable_fopen(const char *fileName,const char *mode)␊ |
314 | {␊ |
315 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
316 | QString fn(fileName);␊ |
317 | QString m(mode);␊ |
318 | return _wfopen((wchar_t*)fn.ucs2(),(wchar_t*)m.ucs2());␊ |
319 | #else␊ |
320 | return fopen(fileName,mode);␊ |
321 | #endif␊ |
322 | }␊ |
323 | ␊ |
324 | char portable_pathSeparator()␊ |
325 | {␊ |
326 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
327 | return '\\';␊ |
328 | #else␊ |
329 | return '/';␊ |
330 | #endif␊ |
331 | }␊ |
332 | ␊ |
333 | char portable_pathListSeparator()␊ |
334 | {␊ |
335 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
336 | return ';';␊ |
337 | #else␊ |
338 | return ':';␊ |
339 | #endif␊ |
340 | }␊ |
341 | ␊ |
342 | const char *portable_ghostScriptCommand()␊ |
343 | {␊ |
344 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
345 | return "gswin32c.exe";␊ |
346 | #else␊ |
347 | return "gs";␊ |
348 | #endif␊ |
349 | }␊ |
350 | ␊ |
351 | const char *portable_commandExtension()␊ |
352 | {␊ |
353 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
354 | return ".exe";␊ |
355 | #else␊ |
356 | return "";␊ |
357 | #endif␊ |
358 | }␊ |
359 | ␊ |
360 | bool portable_fileSystemIsCaseSensitive()␊ |
361 | {␊ |
362 | #if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__)␊ |
363 | return FALSE;␊ |
364 | #else␊ |
365 | return TRUE;␊ |
366 | #endif␊ |
367 | }␊ |
368 | ␊ |
369 | FILE * portable_popen(const char *name,const char *type)␊ |
370 | {␊ |
371 | return popen(name,type);␊ |
372 | }␊ |
373 | ␊ |
374 | int portable_pclose(FILE *stream)␊ |
375 | {␊ |
376 | return pclose(stream);␊ |
377 | }␊ |
378 | ␊ |
379 | void portable_sysTimerStart()␊ |
380 | {␊ |
381 | g_time.start();␊ |
382 | }␊ |
383 | ␊ |
384 | void portable_sysTimerStop()␊ |
385 | {␊ |
386 | g_sysElapsedTime+=((double)g_time.elapsed())/1000.0;␊ |
387 | }␊ |
388 | ␊ |
389 | double portable_getSysElapsedTime()␊ |
390 | {␊ |
391 | return g_sysElapsedTime;␊ |
392 | }␊ |
393 | ␊ |
394 | void portable_sleep(int ms)␊ |
395 | {␊ |
396 | #if defined(_WIN32) && !defined(__CYGWIN__)␊ |
397 | Sleep(ms);␊ |
398 | #else␊ |
399 | usleep(1000*ms);␊ |
400 | #endif␊ |
401 | }␊ |
402 |