3 #if defined(_WIN32) && !defined(__CYGWIN__)
10 #include <sys/types.h>
13 extern char **environ;
17 #include <qdatetime.h>
19 #if defined(_MSC_VER) || defined(__BORLANDC__)
21 #define pclose _pclose
30 static double g_sysElapsedTime;
33 int portable_system(const char *command,const char *args,bool commandHasConsole)
36 if (command==0) return 1;
38 #if defined(_WIN32) && !defined(__CYGWIN__)
39 QCString commandCorrectedPath = substitute(command,'/','\\');
40 QCString fullCmd=commandCorrectedPath;
42 QCString fullCmd=command;
44 fullCmd=fullCmd.stripWhiteSpace();
45 if (fullCmd.at(0)!='"' && fullCmd.find(' ')!=-1)
47 // add quotes around command as it contains spaces and is not quoted already
48 fullCmd="\""+fullCmd+"\"";
53 Debug::print(Debug::ExtCmd,0,"Executing external command `%s`\n",qPrint(fullCmd));
56 #if !defined(_WIN32) || defined(__CYGWIN__)
57 (void)commandHasConsole;
58 /*! taken from the system() manpage on my Linux box */
61 #ifdef _OS_SOLARIS // for Solaris we use vfork since it is more memory efficient
63 // on Solaris fork() duplicates the memory usage
64 // so we use vfork instead
73 execl("/bin/sh","sh","-c",fullCmd.data(),(char*)0);
78 while (waitpid(pid,&status,0 )<0)
89 #else // Other Unices just use fork
102 argv[2] = fullCmd.data();
104 execve("/bin/sh",(char * const *)argv,environ);
109 if (waitpid(pid,&status,0)==-1)
111 if (errno!=EINTR) return -1;
115 if (WIFEXITED(status))
117 return WEXITSTATUS(status);
125 #endif // !_OS_SOLARIS
127 #else // Win32 specific
128 if (commandHasConsole)
130 return system(fullCmd);
134 // Because ShellExecuteEx can delegate execution to Shell extensions
135 // (data sources, context menu handlers, verb implementations) that
136 // are activated using Component Object Model (COM), COM should be
137 // initialized before ShellExecuteEx is called. Some Shell extensions
138 // require the COM single-threaded apartment (STA) type.
139 // For that case COM is initialized as follows
140 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
142 QString commandw = QString::fromUtf8( commandCorrectedPath );
143 QString argsw = QString::fromUtf8( args );
145 // gswin32 is a GUI api which will pop up a window and run
146 // asynchronously. To prevent both, we use ShellExecuteEx and
147 // WaitForSingleObject (thanks to Robert Golias for the code)
149 SHELLEXECUTEINFOW sInfo = {
150 sizeof(SHELLEXECUTEINFOW), /* structure size */
151 SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI, /* tell us the process
152 * handle so we can wait till it's done |
153 * do not display msg box if error
155 NULL, /* window handle */
156 NULL, /* action to perform: open */
157 (LPCWSTR)commandw.ucs2(), /* file to execute */
158 (LPCWSTR)argsw.ucs2(), /* argument list */
159 NULL, /* use current working dir */
160 SW_HIDE, /* minimize on start-up */
161 0, /* application instance handle */
162 NULL, /* ignored: id list */
163 NULL, /* ignored: class name */
164 NULL, /* ignored: key class */
165 0, /* ignored: hot key */
166 NULL, /* ignored: icon */
167 NULL /* resulting application handle */
170 if (!ShellExecuteExW(&sInfo))
174 else if (sInfo.hProcess) /* executable was launched, wait for it to finish */
176 WaitForSingleObject(sInfo.hProcess,INFINITE);
177 /* get process exit code */
179 if (!GetExitCodeProcess(sInfo.hProcess,&exitCode))
183 CloseHandle(sInfo.hProcess);
188 return 1; // we should never get here
195 #if !defined(_WIN32) || defined(__CYGWIN__)
196 pid = (uint)getpid();
198 pid = (uint)GetCurrentProcessId();
203 #if defined(_WIN32) && !defined(__CYGWIN__)
205 static char **last_environ;
208 void portable_setenv(const char *name,const char *value)
210 if (value==0) value="";
211 #if defined(_WIN32) && !defined(__CYGWIN__)
212 SetEnvironmentVariable(name,value);
216 const size_t namelen=qstrlen(name);
217 const size_t vallen=qstrlen(value) + 1;
222 for (ep = environ; *ep; ++ep)
224 if (!qstrncmp (*ep, name, (uint)namelen) &&
225 (*ep)[namelen] == '=')
232 if (environ==0 || *ep==0) /* add new string */
235 if (environ == last_environ && environ!=0)
237 // We allocated this space; we can extend it.
238 new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *));
242 new_environ = (char **) malloc ((size + 2) * sizeof (char *));
245 if (new_environ==0) // no more memory
250 new_environ[size] = (char *)malloc (namelen + 1 + vallen);
251 if (new_environ[size]==0)
257 if (environ != last_environ)
259 memcpy ((char *) new_environ, environ, size * sizeof (char *));
262 memcpy(new_environ[size], name, namelen);
263 new_environ[size][namelen] = '=';
264 memcpy(&new_environ[size][namelen + 1], value, vallen);
265 new_environ[size + 1] = 0;
266 last_environ = environ = new_environ;
268 else /* replace existing string */
270 size_t len = qstrlen (*ep);
271 if (len + 1 < namelen + 1 + vallen)
273 /* The existing string is too short; malloc a new one. */
274 char *newString = (char *)malloc(namelen + 1 + vallen);
281 memcpy(*ep, name, namelen);
282 (*ep)[namelen] = '=';
283 memcpy(&(*ep)[namelen + 1], value, vallen);
289 void portable_unsetenv(const char *variable)
291 #if defined(_WIN32) && !defined(__CYGWIN__)
292 SetEnvironmentVariable(variable,0);
294 /* Some systems don't have unsetenv(), so we do it ourselves */
298 if (variable == NULL || *variable == '\0' || strchr (variable, '=') != NULL)
300 return; // not properly formatted
303 len = qstrlen(variable);
308 if (!qstrncmp(*ep, variable, (uint)len) && (*ep)[len]=='=')
310 /* Found it. Remove this pointer by moving later ones back. */
312 do dp[0] = dp[1]; while (*dp++);
313 /* Continue the loop in case NAME appears again. */
323 const char *portable_getenv(const char *variable)
325 return getenv(variable);
328 portable_off_t portable_fseek(FILE *f,portable_off_t offset, int whence)
330 #if defined(__MINGW32__)
331 return fseeko64(f,offset,whence);
332 #elif defined(_WIN32) && !defined(__CYGWIN__)
333 return _fseeki64(f,offset,whence);
335 return fseeko(f,offset,whence);
339 portable_off_t portable_ftell(FILE *f)
341 #if defined(__MINGW32__)
343 #elif defined(_WIN32) && !defined(__CYGWIN__)
350 FILE *portable_fopen(const char *fileName,const char *mode)
352 #if defined(_WIN32) && !defined(__CYGWIN__)
353 QString fn(fileName);
355 return _wfopen((wchar_t*)fn.ucs2(),(wchar_t*)m.ucs2());
357 return fopen(fileName,mode);
361 char portable_pathSeparator()
363 #if defined(_WIN32) && !defined(__CYGWIN__)
370 char portable_pathListSeparator()
372 #if defined(_WIN32) && !defined(__CYGWIN__)
379 const char *portable_ghostScriptCommand()
381 #if defined(_WIN32) && !defined(__CYGWIN__)
382 return "gswin32c.exe";
388 const char *portable_commandExtension()
390 #if defined(_WIN32) && !defined(__CYGWIN__)
397 bool portable_fileSystemIsCaseSensitive()
399 #if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__)
406 FILE * portable_popen(const char *name,const char *type)
408 return popen(name,type);
411 int portable_pclose(FILE *stream)
413 return pclose(stream);
416 void portable_sysTimerStart()
421 void portable_sysTimerStop()
423 g_sysElapsedTime+=((double)g_time.elapsed())/1000.0;
426 double portable_getSysElapsedTime()
428 return g_sysElapsedTime;
431 void portable_sleep(int ms)
433 #if defined(_WIN32) && !defined(__CYGWIN__)
440 bool portable_isAbsolutePath(const char *fileName)
443 if (isalpha (fileName [0]) && fileName[1] == ':')
446 char const fst = fileName [0];
458 * Correct a possible wrong PATH variable
460 * This routine was inspired by the cause for bug 766059 was that in the Windows path there were forward slahes.
462 void portable_correct_path(void)
464 #if defined(_WIN32) && !defined(__CYGWIN__)
465 const char *p = portable_getenv("PATH");
466 QCString result = substitute(p,'/','\\');
467 if (result!=p) portable_setenv("PATH",result.data());