portable.cpp

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <ctype.h>
00003 #if defined(_WIN32) && !defined(__CYGWIN__)
00004 #undef UNICODE
00005 #include <windows.h>
00006 #else
00007 #include <unistd.h>
00008 #include <stdlib.h>
00009 #include <sys/types.h>
00010 #include <sys/wait.h>
00011 #include <errno.h>
00012 extern char **environ;
00013 #endif
00014 
00015 #include <qglobal.h>
00016 #include <qdatetime.h>
00017 #include <iconv.h>
00018 
00019 #if defined(_MSC_VER) || defined(__BORLANDC__)
00020 #define popen _popen
00021 #define pclose _pclose
00022 #endif
00023 
00024 #include "portable.h"
00025 #ifndef NODEBUG
00026 #include "debug.h"
00027 #endif
00028 //#include "doxygen.h"
00029 
00030 static double  sysElapsedTime;
00031 
00032 int  portable_system(const char *command,const char *args,bool commandHasConsole)
00033 {
00034   QTime time;
00035   time.start();
00036 
00037   if (command==0) return 1;
00038 
00039   QCString fullCmd=command;
00040   fullCmd=fullCmd.stripWhiteSpace();
00041   if (fullCmd.at(0)!='"' && fullCmd.find(' ')!=-1)
00042   {
00043     // add quotes around command as it contains spaces and is not quoted already
00044     fullCmd="\""+fullCmd+"\"";
00045   }
00046   fullCmd += " ";
00047   fullCmd += args;
00048 #ifndef NODEBUG
00049   Debug::print(Debug::ExtCmd,0,"Executing external command `%s`\n",fullCmd.data());
00050 #endif
00051 
00052 #if !defined(_WIN32) || defined(__CYGWIN__)
00053   commandHasConsole=commandHasConsole;
00055   int pid,status=0;
00056 
00057 #ifdef _OS_SOLARIS // for Solaris we use vfork since it is more memory efficient
00058 
00059   // on Solaris fork() duplicates the memory usage
00060   // so we use vfork instead
00061   
00062   // spawn shell
00063   if ((pid=vfork())<0)
00064   {
00065     status=-1;
00066   }
00067   else if (pid==0)
00068   {
00069      execl("/bin/sh","sh","-c",fullCmd.data(),(char*)0);
00070      _exit(127);
00071   }
00072   else
00073   {
00074     while (waitpid(pid,&status,0 )<0)
00075     {
00076       if (errno!=EINTR)
00077       {
00078         status=-1;
00079         break;
00080       }
00081     }
00082   }
00083   sysElapsedTime+=((double)time.elapsed())/1000.0;
00084   return status;
00085 
00086 #else  // Other Unices just use fork
00087 
00088   pid = fork();
00089   if (pid==-1) return -1;
00090   if (pid==0)
00091   {
00092     const char * argv[4];
00093     argv[0] = "sh";
00094     argv[1] = "-c";
00095     argv[2] = fullCmd.data();
00096     argv[3] = 0;
00097     execve("/bin/sh",(char * const *)argv,environ);
00098     exit(127);
00099   }
00100   for (;;)
00101   {
00102     if (waitpid(pid,&status,0)==-1)
00103     {
00104       if (errno!=EINTR) return -1;
00105     }
00106     else
00107     {
00108       sysElapsedTime+=((double)time.elapsed())/1000.0;
00109       if (WIFEXITED(status))
00110       {
00111         return WEXITSTATUS(status);
00112       }
00113       else
00114       {
00115         return status;
00116       }
00117     }
00118   }
00119 #endif // !_OS_SOLARIS
00120 
00121 #else // Win32 specific
00122   if (commandHasConsole)
00123   {
00124     return system(fullCmd);
00125   }
00126   else
00127   {
00128     // gswin32 is a GUI api which will pop up a window and run
00129     // asynchronously. To prevent both, we use ShellExecuteEx and
00130     // WaitForSingleObject (thanks to Robert Golias for the code)
00131 
00132     SHELLEXECUTEINFO sInfo = {
00133       sizeof(SHELLEXECUTEINFO),   /* structure size */
00134       SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI,  /* tell us the process
00135                                                        *  handle so we can wait till it's done | 
00136                                                        *  do not display msg box if error 
00137                                                        */
00138       NULL,                       /* window handle */
00139       NULL,                       /* action to perform: open */
00140       command,                    /* file to execute */
00141       args,                       /* argument list */ 
00142       NULL,                       /* use current working dir */
00143       SW_HIDE,                    /* minimize on start-up */
00144       0,                          /* application instance handle */
00145       NULL,                       /* ignored: id list */
00146       NULL,                       /* ignored: class name */
00147       NULL,                       /* ignored: key class */
00148       0,                          /* ignored: hot key */
00149       NULL,                       /* ignored: icon */
00150       NULL                        /* resulting application handle */
00151     };
00152     if (!ShellExecuteEx(&sInfo))
00153     {
00154       return -1;
00155     }
00156     else if (sInfo.hProcess)      /* executable was launched, wait for it to finish */
00157     {
00158       WaitForSingleObject(sInfo.hProcess,INFINITE); 
00159       CloseHandle(sInfo.hProcess);
00160     }
00161   }
00162   sysElapsedTime+=((double)time.elapsed())/1000.0;
00163   return 0;
00164 #endif
00165 
00166 }
00167 
00168 uint portable_pid()
00169 {
00170   uint pid;
00171 #if !defined(_WIN32) || defined(__CYGWIN__)
00172   pid = (uint)getpid();
00173 #else
00174   pid = (uint)GetCurrentProcessId();
00175 #endif
00176   return pid;
00177 }
00178 
00179 static char **last_environ;
00180 
00181 void portable_setenv(const char *name,const char *value)
00182 {
00183 #ifdef _WIN32
00184     SetEnvironmentVariable(name,value);
00185 #else
00186     register char **ep = 0;
00187     register size_t size;
00188     const size_t namelen=strlen(name);
00189     const size_t vallen=strlen(value) + 1;
00190 
00191     size = 0;
00192     if (environ!=0)
00193     {
00194       for (ep = environ; *ep; ++ep)
00195       {
00196         if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
00197           break;
00198         else
00199           ++size;
00200       }
00201     }
00202 
00203     if (environ==0 || *ep==0) /* add new string */
00204     {
00205       char **new_environ;
00206       if (environ == last_environ && environ!=0)
00207       {
00208         // We allocated this space; we can extend it. 
00209         new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *));
00210       }
00211       else
00212       {
00213         new_environ = (char **) malloc ((size + 2) * sizeof (char *));
00214       }
00215 
00216       if (new_environ==0) // no more memory 
00217       {
00218         return;
00219       }
00220 
00221       new_environ[size] = (char *)malloc (namelen + 1 + vallen);
00222       if (new_environ[size]==0)
00223       {
00224         free (new_environ);
00225         return;
00226       }
00227 
00228       if (environ != last_environ)
00229       {
00230         memcpy ((char *) new_environ, environ, size * sizeof (char *));
00231       }
00232 
00233       memcpy(new_environ[size], name, namelen);
00234       new_environ[size][namelen] = '=';
00235       memcpy(&new_environ[size][namelen + 1], value, vallen);
00236       new_environ[size + 1] = 0;
00237       last_environ = environ = new_environ;
00238     }
00239     else /* replace existing string */
00240     {
00241       size_t len = strlen (*ep);
00242       if (len + 1 < namelen + 1 + vallen)
00243       {
00244         /* The existing string is too short; malloc a new one.  */
00245         char *newString = (char *)malloc(namelen + 1 + vallen);
00246         if (newString==0)
00247         {
00248           return;
00249         }
00250         *ep = newString;
00251       }
00252       memcpy(*ep, name, namelen);
00253       (*ep)[namelen] = '=';
00254       memcpy(&(*ep)[namelen + 1], value, vallen);
00255     }
00256 
00257 #endif
00258 }
00259 
00260 void portable_unsetenv(const char *variable)
00261 {
00262 #ifdef _WIN32
00263     SetEnvironmentVariable(variable,0);
00264 #else
00265     /* Some systems don't have unsetenv(), so we do it ourselves */
00266     size_t len;
00267     char **ep;
00268 
00269     if (variable == NULL || *variable == '\0' || strchr (variable, '=') != NULL)
00270     {
00271       return; // not properly formatted
00272     }
00273 
00274     len = strlen(variable);
00275 
00276     ep = environ;
00277     while (*ep != NULL)
00278     {
00279       if (!strncmp(*ep, variable, len) && (*ep)[len]=='=')
00280       {
00281         /* Found it.  Remove this pointer by moving later ones back.  */
00282         char **dp = ep;
00283         do dp[0] = dp[1]; while (*dp++);
00284         /* Continue the loop in case NAME appears again.  */
00285       }
00286       else
00287       {
00288         ++ep;
00289       }
00290     }
00291 #endif
00292 }
00293 
00294 const char *portable_getenv(const char *variable)
00295 {
00296   return getenv(variable);
00297 }
00298 
00299 portable_off_t portable_fseek(FILE *f,portable_off_t offset, int whence)
00300 {
00301 #if defined(_WIN32) && !defined(__CYGWIN__)
00302   return _fseeki64(f,offset,whence);
00303 #else
00304   return fseeko(f,offset,whence);
00305 #endif
00306 }
00307 
00308 portable_off_t portable_ftell(FILE *f)
00309 {
00310 #if defined(_WIN32) && !defined(__CYGWIN__)
00311   return _ftelli64(f);
00312 #else
00313   return ftello(f);
00314 #endif
00315 }
00316 
00317 char  portable_pathSeparator()
00318 {
00319 #if defined(_WIN32) && !defined(__CYGWIN__)
00320   return '\\';
00321 #else
00322   return '/';
00323 #endif
00324 }
00325 
00326 char  portable_pathListSeparator()
00327 {
00328 #if defined(_WIN32) && !defined(__CYGWIN__)
00329   return ';';
00330 #else
00331   return ':';
00332 #endif
00333 }
00334 
00335 const char *portable_ghostScriptCommand()
00336 {
00337 #if defined(_WIN32) && !defined(__CYGWIN__)
00338     return "gswin32c.exe";
00339 #else
00340     return "gs";
00341 #endif
00342 }
00343 
00344 const char *portable_commandExtension()
00345 {
00346 #if defined(_WIN32) && !defined(__CYGWIN__)
00347     return ".exe";
00348 #else
00349     return "";
00350 #endif
00351 }
00352 
00353 bool portable_fileSystemIsCaseSensitive()
00354 {
00355 #if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__)
00356   return FALSE;
00357 #else
00358   return TRUE;
00359 #endif
00360 }
00361 
00362 FILE * portable_popen(const char *name,const char *type)
00363 {
00364   return popen(name,type);
00365 }
00366 
00367 int portable_pclose(FILE *stream)
00368 {
00369   return pclose(stream);
00370 }
00371 
00372 void * portable_iconv_open(const char* tocode, const char* fromcode)
00373 {
00374   return iconv_open(tocode,fromcode);
00375 }
00376 
00377 size_t portable_iconv (void *cd, const char** inbuf,  size_t *inbytesleft, 
00378                                        char** outbuf, size_t *outbytesleft)
00379 {
00380 // libiconv is a mess. For some platforms/version the prototype of inbuf is
00381 // "const char **", for others it is "char **". C++ requires the proper cast to
00382 // avoid a compile error, that is were the CASTNEEDED is for.
00383 #if ((defined(_LIBICONV_VERSION) && (_LIBICONV_VERSION>=0x0109) && \
00384       !((defined(_OS_MAC_) || defined(Q_OS_MACX) )&& (_LIBICONV_VERSION==0x010B))) \
00385     || defined(_OS_SOLARIS_))
00386 #define CASTNEEDED(x) (x)
00387 #else
00388 #define CASTNEEDED(x) (char **)(x)
00389 #endif
00390   return iconv((iconv_t)cd,CASTNEEDED(inbuf),inbytesleft,outbuf,outbytesleft);
00391 }
00392 
00393 int portable_iconv_close (void *cd)
00394 {
00395   return iconv_close((iconv_t)cd);
00396 }
00397 



Generated on Mon Mar 31 10:58:41 2008 by  doxygen 1.5.1