1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/utilsunx.cpp 
   3 // Purpose:     generic Unix implementation of many wx functions (for wxBase) 
   4 // Author:      Vadim Zeitlin 
   6 // Copyright:   (c) 1998 Robert Roebling, Vadim Zeitlin 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // ============================================================================ 
  12 // ============================================================================ 
  14 // ---------------------------------------------------------------------------- 
  16 // ---------------------------------------------------------------------------- 
  18 // for compilers that support precompilation, includes "wx.h". 
  19 #include "wx/wxprec.h" 
  23 #define USE_PUTENV (!defined(HAVE_SETENV) && defined(HAVE_PUTENV)) 
  26     #include "wx/string.h" 
  30     #include "wx/wxcrtvararg.h" 
  32         #include "wx/module.h" 
  33         #include "wx/hashmap.h" 
  37 #include "wx/apptrait.h" 
  39 #include "wx/process.h" 
  40 #include "wx/thread.h" 
  42 #include "wx/cmdline.h" 
  44 #include "wx/wfstream.h" 
  46 #include "wx/private/selectdispatcher.h" 
  47 #include "wx/private/fdiodispatcher.h" 
  48 #include "wx/unix/execute.h" 
  49 #include "wx/unix/private.h" 
  51 #ifdef wxHAS_GENERIC_PROCESS_CALLBACK 
  52 #include "wx/private/fdiodispatcher.h" 
  56 #include <sys/wait.h>       // waitpid() 
  58 #ifdef HAVE_SYS_SELECT_H 
  59 #   include <sys/select.h> 
  62 #define HAS_PIPE_STREAMS (wxUSE_STREAMS && wxUSE_FILE) 
  66 #include "wx/private/pipestream.h" 
  68 // define this to let wxexec.cpp know that we know what we're doing 
  69 #define _WX_USED_BY_WXEXECUTE_ 
  70 #include "../common/execcmn.cpp" 
  72 #endif // HAS_PIPE_STREAMS 
  74 // not only the statfs syscall is called differently depending on platform, but 
  75 // one of its incarnations, statvfs(), takes different arguments under 
  76 // different platforms and even different versions of the same system (Solaris 
  77 // 7 and 8): if you want to test for this, don't forget that the problems only 
  78 // appear if the large files support is enabled 
  81         #include <sys/param.h> 
  82         #include <sys/mount.h> 
  85     #endif // __BSD__/!__BSD__ 
  87     #define wxStatfs statfs 
  89     #ifndef HAVE_STATFS_DECL 
  90         // some systems lack statfs() prototype in the system headers (AIX 4) 
  91         extern "C" int statfs(const char *path
, struct statfs 
*buf
); 
  96     #include <sys/statvfs.h> 
  98     #define wxStatfs statvfs 
  99 #endif // HAVE_STATVFS 
 101 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) 
 102     // WX_STATFS_T is detected by configure 
 103     #define wxStatfs_t WX_STATFS_T 
 106 // SGI signal.h defines signal handler arguments differently depending on 
 107 // whether _LANGUAGE_C_PLUS_PLUS is set or not - do set it 
 108 #if defined(__SGI__) && !defined(_LANGUAGE_C_PLUS_PLUS) 
 109     #define _LANGUAGE_C_PLUS_PLUS 1 
 115 #include <sys/stat.h> 
 116 #include <sys/types.h> 
 117 #include <sys/wait.h> 
 122 #include <fcntl.h>          // for O_WRONLY and friends 
 123 #include <time.h>           // nanosleep() and/or usleep() 
 124 #include <ctype.h>          // isspace() 
 125 #include <sys/time.h>       // needed for FD_SETSIZE 
 128     #include <sys/utsname.h> // for uname() 
 131 // Used by wxGetFreeMemory(). 
 133     #include <sys/sysmp.h> 
 134     #include <sys/sysinfo.h>   // for SAGET and MINFO structures 
 137 #ifdef HAVE_SETPRIORITY 
 138     #include <sys/resource.h>   // for setpriority() 
 141 // ---------------------------------------------------------------------------- 
 142 // conditional compilation 
 143 // ---------------------------------------------------------------------------- 
 145 // many versions of Unices have this function, but it is not defined in system 
 146 // headers - please add your system here if it is the case for your OS. 
 147 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. 
 148 #if !defined(HAVE_USLEEP) && \ 
 149     ((defined(__SUN__) && !defined(__SunOs_5_6) && \ 
 150                          !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ 
 151      defined(__osf__) || defined(__EMX__)) 
 155             /* I copied this from the XFree86 diffs. AV. */ 
 156             #define INCL_DOSPROCESS 
 158             inline void usleep(unsigned long delay
) 
 160                 DosSleep(delay 
? (delay
/1000l) : 1l); 
 163             int usleep(unsigned int usec
); 
 164         #endif // __EMX__/Unix 
 167     #define HAVE_USLEEP 1 
 168 #endif // Unices without usleep() 
 170 // ============================================================================ 
 172 // ============================================================================ 
 174 // ---------------------------------------------------------------------------- 
 176 // ---------------------------------------------------------------------------- 
 178 void wxSleep(int nSecs
) 
 183 void wxMicroSleep(unsigned long microseconds
) 
 185 #if defined(HAVE_NANOSLEEP) 
 187     tmReq
.tv_sec 
= (time_t)(microseconds 
/ 1000000); 
 188     tmReq
.tv_nsec 
= (microseconds 
% 1000000) * 1000; 
 190     // we're not interested in remaining time nor in return value 
 191     (void)nanosleep(&tmReq
, NULL
); 
 192 #elif defined(HAVE_USLEEP) 
 193     // uncomment this if you feel brave or if you are sure that your version 
 194     // of Solaris has a safe usleep() function but please notice that usleep() 
 195     // is known to lead to crashes in MT programs in Solaris 2.[67] and is not 
 196     // documented as MT-Safe 
 197     #if defined(__SUN__) && wxUSE_THREADS 
 198         #error "usleep() cannot be used in MT programs under Solaris." 
 201     usleep(microseconds
); 
 202 #elif defined(HAVE_SLEEP) 
 203     // under BeOS sleep() takes seconds (what about other platforms, if any?) 
 204     sleep(microseconds 
* 1000000); 
 205 #else // !sleep function 
 206     #error "usleep() or nanosleep() function required for wxMicroSleep" 
 207 #endif // sleep function 
 210 void wxMilliSleep(unsigned long milliseconds
) 
 212     wxMicroSleep(milliseconds
*1000); 
 215 // ---------------------------------------------------------------------------- 
 216 // process management 
 217 // ---------------------------------------------------------------------------- 
 219 int wxKill(long pid
, wxSignal sig
, wxKillError 
*rc
, int flags
) 
 221     int err 
= kill((pid_t
) (flags 
& wxKILL_CHILDREN
) ? -pid 
: pid
, (int)sig
); 
 224         switch ( err 
? errno 
: 0 ) 
 231                 *rc 
= wxKILL_BAD_SIGNAL
; 
 235                 *rc 
= wxKILL_ACCESS_DENIED
; 
 239                 *rc 
= wxKILL_NO_PROCESS
; 
 243                 // this goes against Unix98 docs so log it 
 244                 wxLogDebug(wxT("unexpected kill(2) return value %d"), err
); 
 254 // Shutdown or reboot the PC 
 255 bool wxShutdown(int flags
) 
 257     flags 
&= ~wxSHUTDOWN_FORCE
; 
 262         case wxSHUTDOWN_POWEROFF
: 
 266         case wxSHUTDOWN_REBOOT
: 
 270         case wxSHUTDOWN_LOGOFF
: 
 271             // TODO: use dcop to log off? 
 275             wxFAIL_MSG( wxT("unknown wxShutdown() flag") ); 
 279     return system(wxString::Format("init %c", level
).mb_str()) == 0; 
 282 // ---------------------------------------------------------------------------- 
 283 // wxStream classes to support IO redirection in wxExecute 
 284 // ---------------------------------------------------------------------------- 
 288 bool wxPipeInputStream::CanRead() const 
 290     if ( m_lasterror 
== wxSTREAM_EOF 
) 
 293     // check if there is any input available 
 298     const int fd 
= m_file
->fd(); 
 303     wxFD_SET(fd
, &readfds
); 
 305     switch ( select(fd 
+ 1, &readfds
, NULL
, NULL
, &tv
) ) 
 308             wxLogSysError(_("Impossible to get child process input")); 
 315             wxFAIL_MSG(wxT("unexpected select() return value")); 
 316             // still fall through 
 319             // input available -- or maybe not, as select() returns 1 when a 
 320             // read() will complete without delay, but it could still not read 
 326 size_t wxPipeOutputStream::OnSysWrite(const void *buffer
, size_t size
) 
 328     // We need to suppress error logging here, because on writing to a pipe 
 329     // which is full, wxFile::Write reports a system error. However, this is 
 330     // not an extraordinary situation, and it should not be reported to the 
 331     // user (but if really needed, the program can recognize it by checking 
 332     // whether LastRead() == 0.) Other errors will be reported below. 
 336         ret 
= m_file
->Write(buffer
, size
); 
 339     switch ( m_file
->GetLastError() ) 
 345 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) 
 348            // do not treat it as an error 
 349            m_file
->ClearLastError(); 
 358            wxLogSysError(_("Can't write to child process's stdin")); 
 359            m_lasterror 
= wxSTREAM_WRITE_ERROR
; 
 365 #endif // HAS_PIPE_STREAMS 
 367 // ---------------------------------------------------------------------------- 
 369 // ---------------------------------------------------------------------------- 
 371 static wxString 
wxMakeShellCommand(const wxString
& command
) 
 376         // just an interactive shell 
 381         // execute command in a shell 
 382         cmd 
<< wxT("/bin/sh -c '") << command 
<< wxT('\''); 
 388 bool wxShell(const wxString
& command
) 
 390     return wxExecute(wxMakeShellCommand(command
), wxEXEC_SYNC
) == 0; 
 393 bool wxShell(const wxString
& command
, wxArrayString
& output
) 
 395     wxCHECK_MSG( !command
.empty(), false, wxT("can't exec shell non interactively") ); 
 397     return wxExecute(wxMakeShellCommand(command
), output
); 
 403 // helper class for storing arguments as char** array suitable for passing to 
 404 // execvp(), whatever form they were passed to us 
 408     ArgsArray(const wxArrayString
& args
) 
 412         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 414             m_argv
[i
] = wxStrdup(args
[i
]); 
 419     ArgsArray(wchar_t **wargv
) 
 422         while ( wargv
[argc
] ) 
 427         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 429             m_argv
[i
] = wxSafeConvertWX2MB(wargv
[i
]).release(); 
 432 #endif // wxUSE_UNICODE 
 436         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 444     operator char**() const { return m_argv
; } 
 450         m_argv 
= new char *[m_argc 
+ 1]; 
 451         m_argv
[m_argc
] = NULL
; 
 457     wxDECLARE_NO_COPY_CLASS(ArgsArray
); 
 460 } // anonymous namespace 
 462 // ---------------------------------------------------------------------------- 
 463 // wxExecute implementations 
 464 // ---------------------------------------------------------------------------- 
 466 #if defined(__DARWIN__) 
 467 bool wxMacLaunch(char **argv
); 
 470 long wxExecute(const wxString
& command
, int flags
, wxProcess 
*process
, 
 471         const wxExecuteEnv 
*env
) 
 473     ArgsArray 
argv(wxCmdLineParser::ConvertStringToArgs(command
, 
 474                                                         wxCMD_LINE_SPLIT_UNIX
)); 
 476     return wxExecute(argv
, flags
, process
, env
); 
 481 long wxExecute(wchar_t **wargv
, int flags
, wxProcess 
*process
, 
 482         const wxExecuteEnv 
*env
) 
 484     ArgsArray 
argv(wargv
); 
 486     return wxExecute(argv
, flags
, process
, env
); 
 489 #endif // wxUSE_UNICODE 
 491 // wxExecute: the real worker function 
 492 long wxExecute(char **argv
, int flags
, wxProcess 
*process
, 
 493         const wxExecuteEnv 
*env
) 
 495     // for the sync execution, we return -1 to indicate failure, but for async 
 496     // case we return 0 which is never a valid PID 
 498     // we define this as a macro, not a variable, to avoid compiler warnings 
 499     // about "ERROR_RETURN_CODE value may be clobbered by fork()" 
 500     #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0) 
 502     wxCHECK_MSG( *argv
, ERROR_RETURN_CODE
, wxT("can't exec empty command") ); 
 505     // fork() doesn't mix well with POSIX threads: on many systems the program 
 506     // deadlocks or crashes for some reason. Probably our code is buggy and 
 507     // doesn't do something which must be done to allow this to work, but I 
 508     // don't know what yet, so for now just warn the user (this is the least we 
 510     wxASSERT_MSG( wxThread::IsMain(), 
 511                     wxT("wxExecute() can be called only from the main thread") ); 
 512 #endif // wxUSE_THREADS 
 514 #if defined(__WXCOCOA__) || ( defined(__WXOSX_MAC__) && wxOSX_USE_COCOA_OR_CARBON ) 
 515     // wxMacLaunch() only executes app bundles and only does it asynchronously. 
 516     // It returns false if the target is not an app bundle, thus falling 
 517     // through to the regular code for non app bundles. 
 518     if ( !(flags 
& wxEXEC_SYNC
) && wxMacLaunch(argv
) ) 
 520         // we don't have any PID to return so just make up something non null 
 526     // this struct contains all information which we use for housekeeping 
 527     wxExecuteData execData
; 
 528     execData
.flags 
= flags
; 
 529     execData
.process 
= process
; 
 532     if ( !execData
.pipeEndProcDetect
.Create() ) 
 534         wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 536         return ERROR_RETURN_CODE
; 
 539     // pipes for inter process communication 
 540     wxPipe pipeIn
,      // stdin 
 544     if ( process 
&& process
->IsRedirected() ) 
 546         if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() ) 
 548             wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 550             return ERROR_RETURN_CODE
; 
 554     // priority: we need to map wxWidgets priority which is in the range 0..100 
 555     // to Unix nice value which is in the range -20..19. As there is an odd 
 556     // number of elements in our range and an even number in the Unix one, we 
 557     // have to do it in this rather ugly way to guarantee that: 
 558     //  1. wxPRIORITY_{MIN,DEFAULT,MAX} map to -20, 0 and 19 respectively. 
 559     //  2. The mapping is monotonously increasing. 
 560     //  3. The mapping is onto the target range. 
 561     int prio 
= process 
? process
->GetPriority() : 0; 
 563         prio 
= (2*prio
)/5 - 20; 
 564     else if ( prio 
< 55 ) 
 567         prio 
= (2*prio
)/5 - 21; 
 571     // NB: do *not* use vfork() here, it completely breaks this code for some 
 572     //     reason under Solaris (and maybe others, although not under Linux) 
 573     //     But on OpenVMS we do not have fork so we have to use vfork and 
 574     //     cross our fingers that it works. 
 580    if ( pid 
== -1 )     // error? 
 582         wxLogSysError( _("Fork failed") ); 
 584         return ERROR_RETURN_CODE
; 
 586     else if ( pid 
== 0 )  // we're in child 
 588         // NB: we used to close all the unused descriptors of the child here 
 589         //     but this broke some programs which relied on e.g. FD 1 being 
 590         //     always opened so don't do it any more, after all there doesn't 
 591         //     seem to be any real problem with keeping them opened 
 593 #if !defined(__VMS) && !defined(__EMX__) 
 594         if ( flags 
& wxEXEC_MAKE_GROUP_LEADER 
) 
 596             // Set process group to child process' pid.  Then killing -pid 
 597             // of the parent will kill the process and all of its children. 
 602 #if defined(HAVE_SETPRIORITY) 
 603         if ( prio 
&& setpriority(PRIO_PROCESS
, 0, prio
) != 0 ) 
 605             wxLogSysError(_("Failed to set process priority")); 
 607 #endif // HAVE_SETPRIORITY 
 609         // redirect stdin, stdout and stderr 
 612             if ( dup2(pipeIn
[wxPipe::Read
], STDIN_FILENO
) == -1 || 
 613                  dup2(pipeOut
[wxPipe::Write
], STDOUT_FILENO
) == -1 || 
 614                  dup2(pipeErr
[wxPipe::Write
], STDERR_FILENO
) == -1 ) 
 616                 wxLogSysError(_("Failed to redirect child process input/output")); 
 624         // Close all (presumably accidentally) inherited file descriptors to 
 625         // avoid descriptor leaks. This means that we don't allow inheriting 
 626         // them purposefully but this seems like a lesser evil in wx code. 
 627         // Ideally we'd provide some flag to indicate that none (or some?) of 
 628         // the descriptors do not need to be closed but for now this is better 
 629         // than never closing them at all as wx code never used FD_CLOEXEC. 
 631         // Note that while the reading side of the end process detection pipe 
 632         // can be safely closed, we should keep the write one opened, it will 
 633         // be only closed when the process terminates resulting in a read 
 634         // notification to the parent 
 635         const int fdEndProc 
= execData
.pipeEndProcDetect
.Detach(wxPipe::Write
); 
 636         execData
.pipeEndProcDetect
.Close(); 
 638         // TODO: Iterating up to FD_SETSIZE is both inefficient (because it may 
 639         //       be quite big) and incorrect (because in principle we could 
 640         //       have more opened descriptions than this number). Unfortunately 
 641         //       there is no good portable solution for closing all descriptors 
 642         //       above a certain threshold but non-portable solutions exist for 
 643         //       most platforms, see [http://stackoverflow.com/questions/899038/ 
 644         //          getting-the-highest-allocated-file-descriptor] 
 645         for ( int fd 
= 0; fd 
< (int)FD_SETSIZE
; ++fd 
) 
 647             if ( fd 
!= STDIN_FILENO  
&& 
 648                  fd 
!= STDOUT_FILENO 
&& 
 649                  fd 
!= STDERR_FILENO 
&& 
 657         // Process additional options if we have any 
 660             // Change working directory if it is specified 
 661             if ( !env
->cwd
.empty() ) 
 662                 wxSetWorkingDirectory(env
->cwd
); 
 664             // Change environment if needed. 
 666             // NB: We can't use execve() currently because we allow using 
 667             //     non full paths to wxExecute(), i.e. we want to search for 
 668             //     the program in PATH. However it just might be simpler/better 
 669             //     to do the search manually and use execve() envp parameter to 
 670             //     set up the environment of the child process explicitly 
 671             //     instead of doing what we do below. 
 672             if ( !env
->env
.empty() ) 
 674                 wxEnvVariableHashMap oldenv
; 
 675                 wxGetEnvMap(&oldenv
); 
 677                 // Remove unwanted variables 
 678                 wxEnvVariableHashMap::const_iterator it
; 
 679                 for ( it 
= oldenv
.begin(); it 
!= oldenv
.end(); ++it 
) 
 681                     if ( env
->env
.find(it
->first
) == env
->env
.end() ) 
 682                         wxUnsetEnv(it
->first
); 
 685                 // And add the new ones (possibly replacing the old values) 
 686                 for ( it 
= env
->env
.begin(); it 
!= env
->env
.end(); ++it 
) 
 687                     wxSetEnv(it
->first
, it
->second
); 
 693         fprintf(stderr
, "execvp("); 
 694         for ( char **a 
= argv
; *a
; a
++ ) 
 695             fprintf(stderr
, "%s%s", a 
== argv 
? "" : ", ", *a
); 
 696         fprintf(stderr
, ") failed with error %d!\n", errno
); 
 698         // there is no return after successful exec() 
 701         // some compilers complain about missing return - of course, they 
 702         // should know that exit() doesn't return but what else can we do if 
 705         // and, sure enough, other compilers complain about unreachable code 
 706         // after exit() call, so we can just always have return here... 
 707 #if defined(__VMS) || defined(__INTEL_COMPILER) 
 711     else // we're in parent 
 713         // save it for WaitForChild() use 
 715         if (execData
.process
) 
 716             execData
.process
->SetPid(pid
);  // and also in the wxProcess 
 718         // prepare for IO redirection 
 721         // the input buffer bufOut is connected to stdout, this is why it is 
 722         // called bufOut and not bufIn 
 723         wxStreamTempInputBuffer bufOut
, 
 726         if ( process 
&& process
->IsRedirected() ) 
 728             // Avoid deadlocks which could result from trying to write to the 
 729             // child input pipe end while the child itself is writing to its 
 730             // output end and waiting for us to read from it. 
 731             if ( !pipeIn
.MakeNonBlocking(wxPipe::Write
) ) 
 733                 // This message is not terrible useful for the user but what 
 734                 // else can we do? Also, should we fail here or take the risk 
 735                 // to continue and deadlock? Currently we choose the latter but 
 736                 // it might not be the best idea. 
 737                 wxLogSysError(_("Failed to set up non-blocking pipe, " 
 738                                 "the program might hang.")); 
 740                 wxLog::FlushActive(); 
 744             wxOutputStream 
*inStream 
= 
 745                 new wxPipeOutputStream(pipeIn
.Detach(wxPipe::Write
)); 
 747             const int fdOut 
= pipeOut
.Detach(wxPipe::Read
); 
 748             wxPipeInputStream 
*outStream 
= new wxPipeInputStream(fdOut
); 
 750             const int fdErr 
= pipeErr
.Detach(wxPipe::Read
); 
 751             wxPipeInputStream 
*errStream 
= new wxPipeInputStream(fdErr
); 
 753             process
->SetPipeStreams(outStream
, inStream
, errStream
); 
 755             bufOut
.Init(outStream
); 
 756             bufErr
.Init(errStream
); 
 758             execData
.bufOut 
= &bufOut
; 
 759             execData
.bufErr 
= &bufErr
; 
 761             execData
.fdOut 
= fdOut
; 
 762             execData
.fdErr 
= fdErr
; 
 764 #endif // HAS_PIPE_STREAMS 
 773         // we want this function to work even if there is no wxApp so ensure 
 774         // that we have a valid traits pointer 
 775         wxConsoleAppTraits traitsConsole
; 
 776         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 778             traits 
= &traitsConsole
; 
 780         return traits
->WaitForChild(execData
); 
 783 #if !defined(__VMS) && !defined(__INTEL_COMPILER) 
 784     return ERROR_RETURN_CODE
; 
 788 #undef ERROR_RETURN_CODE 
 790 // ---------------------------------------------------------------------------- 
 791 // file and directory functions 
 792 // ---------------------------------------------------------------------------- 
 794 const wxChar
* wxGetHomeDir( wxString 
*home  
) 
 796     *home 
= wxGetUserHome(); 
 802     if ( tmp
.Last() != wxT(']')) 
 803         if ( tmp
.Last() != wxT('/')) *home 
<< wxT('/'); 
 805     return home
->c_str(); 
 808 wxString 
wxGetUserHome( const wxString 
&user 
) 
 810     struct passwd 
*who 
= (struct passwd 
*) NULL
; 
 816         if ((ptr 
= wxGetenv(wxT("HOME"))) != NULL
) 
 821         if ((ptr 
= wxGetenv(wxT("USER"))) != NULL 
|| 
 822              (ptr 
= wxGetenv(wxT("LOGNAME"))) != NULL
) 
 824             who 
= getpwnam(wxSafeConvertWX2MB(ptr
)); 
 827         // make sure the user exists! 
 830             who 
= getpwuid(getuid()); 
 835       who 
= getpwnam (user
.mb_str()); 
 838     return wxSafeConvertMB2WX(who 
? who
->pw_dir 
: 0); 
 841 // ---------------------------------------------------------------------------- 
 842 // network and user id routines 
 843 // ---------------------------------------------------------------------------- 
 845 // private utility function which returns output of the given command, removing 
 846 // the trailing newline 
 847 static wxString 
wxGetCommandOutput(const wxString 
&cmd
) 
 849     // Suppress stderr from the shell to avoid outputting errors if the command 
 851     FILE *f 
= popen((cmd 
+ " 2>/dev/null").ToAscii(), "r"); 
 854         // Notice that this doesn't happen simply if the command doesn't exist, 
 855         // but only in case of some really catastrophic failure inside popen() 
 856         // so we should really notify the user about this as this is not normal. 
 857         wxLogSysError(wxT("Executing \"%s\" failed"), cmd
); 
 865         if ( !fgets(buf
, sizeof(buf
), f
) ) 
 868         s 
+= wxString::FromAscii(buf
); 
 873     if ( !s
.empty() && s
.Last() == wxT('\n') ) 
 879 // retrieve either the hostname or FQDN depending on platform (caller must 
 880 // check whether it's one or the other, this is why this function is for 
 882 static bool wxGetHostNameInternal(wxChar 
*buf
, int sz
) 
 884     wxCHECK_MSG( buf
, false, wxT("NULL pointer in wxGetHostNameInternal") ); 
 888     // we're using uname() which is POSIX instead of less standard sysinfo() 
 889 #if defined(HAVE_UNAME) 
 891     bool ok 
= uname(&uts
) != -1; 
 894         wxStrlcpy(buf
, wxSafeConvertMB2WX(uts
.nodename
), sz
); 
 896 #elif defined(HAVE_GETHOSTNAME) 
 898     bool ok 
= gethostname(cbuf
, sz
) != -1; 
 901         wxStrlcpy(buf
, wxSafeConvertMB2WX(cbuf
), sz
); 
 903 #else // no uname, no gethostname 
 904     wxFAIL_MSG(wxT("don't know host name for this machine")); 
 907 #endif // uname/gethostname 
 911         wxLogSysError(_("Cannot get the hostname")); 
 917 bool wxGetHostName(wxChar 
*buf
, int sz
) 
 919     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 923         // BSD systems return the FQDN, we only want the hostname, so extract 
 924         // it (we consider that dots are domain separators) 
 925         wxChar 
*dot 
= wxStrchr(buf
, wxT('.')); 
 936 bool wxGetFullHostName(wxChar 
*buf
, int sz
) 
 938     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 942         if ( !wxStrchr(buf
, wxT('.')) ) 
 944             struct hostent 
*host 
= gethostbyname(wxSafeConvertWX2MB(buf
)); 
 947                 wxLogSysError(_("Cannot get the official hostname")); 
 953                 // the canonical name 
 954                 wxStrlcpy(buf
, wxSafeConvertMB2WX(host
->h_name
), sz
); 
 957         //else: it's already a FQDN (BSD behaves this way) 
 963 bool wxGetUserId(wxChar 
*buf
, int sz
) 
 968     if ((who 
= getpwuid(getuid ())) != NULL
) 
 970         wxStrlcpy (buf
, wxSafeConvertMB2WX(who
->pw_name
), sz
); 
 977 bool wxGetUserName(wxChar 
*buf
, int sz
) 
 983     if ((who 
= getpwuid (getuid ())) != NULL
) 
 985        char *comma 
= strchr(who
->pw_gecos
, ','); 
 987            *comma 
= '\0'; // cut off non-name comment fields 
 988        wxStrlcpy(buf
, wxSafeConvertMB2WX(who
->pw_gecos
), sz
); 
 993 #else // !HAVE_PW_GECOS 
 994     return wxGetUserId(buf
, sz
); 
 995 #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS 
 998 bool wxIsPlatform64Bit() 
1000     const wxString machine 
= wxGetCommandOutput(wxT("uname -m")); 
1002     // the test for "64" is obviously not 100% reliable but seems to work fine 
1004     return machine
.Contains(wxT("64")) || 
1005                 machine
.Contains(wxT("alpha")); 
1009 wxLinuxDistributionInfo 
wxGetLinuxDistributionInfo() 
1011     const wxString id 
= wxGetCommandOutput(wxT("lsb_release --id")); 
1012     const wxString desc 
= wxGetCommandOutput(wxT("lsb_release --description")); 
1013     const wxString rel 
= wxGetCommandOutput(wxT("lsb_release --release")); 
1014     const wxString codename 
= wxGetCommandOutput(wxT("lsb_release --codename")); 
1016     wxLinuxDistributionInfo ret
; 
1018     id
.StartsWith("Distributor ID:\t", &ret
.Id
); 
1019     desc
.StartsWith("Description:\t", &ret
.Description
); 
1020     rel
.StartsWith("Release:\t", &ret
.Release
); 
1021     codename
.StartsWith("Codename:\t", &ret
.CodeName
); 
1027 // these functions are in src/osx/utilsexc_base.cpp for wxMac 
1030 wxOperatingSystemId 
wxGetOsVersion(int *verMaj
, int *verMin
) 
1034     wxString release 
= wxGetCommandOutput(wxT("uname -r")); 
1035     if ( release
.empty() || 
1036          wxSscanf(release
.c_str(), wxT("%d.%d"), &major
, &minor
) != 2 ) 
1038         // failed to get version string or unrecognized format 
1048     // try to understand which OS are we running 
1049     wxString kernel 
= wxGetCommandOutput(wxT("uname -s")); 
1050     if ( kernel
.empty() ) 
1051         kernel 
= wxGetCommandOutput(wxT("uname -o")); 
1053     if ( kernel
.empty() ) 
1054         return wxOS_UNKNOWN
; 
1056     return wxPlatformInfo::GetOperatingSystemId(kernel
); 
1059 wxString 
wxGetOsDescription() 
1061     return wxGetCommandOutput(wxT("uname -s -r -m")); 
1064 #endif // !__DARWIN__ 
1066 unsigned long wxGetProcessId() 
1068     return (unsigned long)getpid(); 
1071 wxMemorySize 
wxGetFreeMemory() 
1073 #if defined(__LINUX__) 
1074     // get it from /proc/meminfo 
1075     FILE *fp 
= fopen("/proc/meminfo", "r"); 
1081         if ( fgets(buf
, WXSIZEOF(buf
), fp
) && fgets(buf
, WXSIZEOF(buf
), fp
) ) 
1083             // /proc/meminfo changed its format in kernel 2.6 
1084             if ( wxPlatformInfo().CheckOSVersion(2, 6) ) 
1086                 unsigned long cached
, buffers
; 
1087                 sscanf(buf
, "MemFree: %ld", &memFree
); 
1089                 fgets(buf
, WXSIZEOF(buf
), fp
); 
1090                 sscanf(buf
, "Buffers: %lu", &buffers
); 
1092                 fgets(buf
, WXSIZEOF(buf
), fp
); 
1093                 sscanf(buf
, "Cached: %lu", &cached
); 
1095                 // add to "MemFree" also the "Buffers" and "Cached" values as 
1096                 // free(1) does as otherwise the value never makes sense: for 
1097                 // kernel 2.6 it's always almost 0 
1098                 memFree 
+= buffers 
+ cached
; 
1100                 // values here are always expressed in kB and we want bytes 
1103             else // Linux 2.4 (or < 2.6, anyhow) 
1105                 long memTotal
, memUsed
; 
1106                 sscanf(buf
, "Mem: %ld %ld %ld", &memTotal
, &memUsed
, &memFree
); 
1112         return (wxMemorySize
)memFree
; 
1114 #elif defined(__SGI__) 
1115     struct rminfo realmem
; 
1116     if ( sysmp(MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0 ) 
1117         return ((wxMemorySize
)realmem
.physmem 
* sysconf(_SC_PAGESIZE
)); 
1118 #elif defined(_SC_AVPHYS_PAGES) 
1119     return ((wxMemorySize
)sysconf(_SC_AVPHYS_PAGES
))*sysconf(_SC_PAGESIZE
); 
1120 //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably 
1123     // can't find it out 
1127 bool wxGetDiskSpace(const wxString
& path
, wxDiskspaceSize_t 
*pTotal
, wxDiskspaceSize_t 
*pFree
) 
1129 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) 
1130     // the case to "char *" is needed for AIX 4.3 
1132     if ( wxStatfs((char *)(const char*)path
.fn_str(), &fs
) != 0 ) 
1134         wxLogSysError( wxT("Failed to get file system statistics") ); 
1139     // under Solaris we also have to use f_frsize field instead of f_bsize 
1140     // which is in general a multiple of f_frsize 
1142     wxDiskspaceSize_t blockSize 
= fs
.f_frsize
; 
1143 #else // HAVE_STATFS 
1144     wxDiskspaceSize_t blockSize 
= fs
.f_bsize
; 
1145 #endif // HAVE_STATVFS/HAVE_STATFS 
1149         *pTotal 
= wxDiskspaceSize_t(fs
.f_blocks
) * blockSize
; 
1154         *pFree 
= wxDiskspaceSize_t(fs
.f_bavail
) * blockSize
; 
1158 #else // !HAVE_STATFS && !HAVE_STATVFS 
1160 #endif // HAVE_STATFS 
1163 // ---------------------------------------------------------------------------- 
1165 // ---------------------------------------------------------------------------- 
1169 WX_DECLARE_STRING_HASH_MAP(char *, wxEnvVars
); 
1171 static wxEnvVars gs_envVars
; 
1173 class wxSetEnvModule 
: public wxModule
 
1176     virtual bool OnInit() { return true; } 
1177     virtual void OnExit() 
1179         for ( wxEnvVars::const_iterator i 
= gs_envVars
.begin(); 
1180               i 
!= gs_envVars
.end(); 
1189     DECLARE_DYNAMIC_CLASS(wxSetEnvModule
) 
1192 IMPLEMENT_DYNAMIC_CLASS(wxSetEnvModule
, wxModule
) 
1194 #endif // USE_PUTENV 
1196 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
1198     // wxGetenv is defined as getenv() 
1199     char *p 
= wxGetenv(var
); 
1211 static bool wxDoSetEnv(const wxString
& variable
, const char *value
) 
1213 #if defined(HAVE_SETENV) 
1216 #ifdef HAVE_UNSETENV 
1217         // don't test unsetenv() return value: it's void on some systems (at 
1219         unsetenv(variable
.mb_str()); 
1222         value 
= ""; // we can't pass NULL to setenv() 
1226     return setenv(variable
.mb_str(), value
, 1 /* overwrite */) == 0; 
1227 #elif defined(HAVE_PUTENV) 
1228     wxString s 
= variable
; 
1230         s 
<< wxT('=') << value
; 
1232     // transform to ANSI 
1233     const wxWX2MBbuf p 
= s
.mb_str(); 
1235     char *buf 
= (char *)malloc(strlen(p
) + 1); 
1238     // store the string to free() it later 
1239     wxEnvVars::iterator i 
= gs_envVars
.find(variable
); 
1240     if ( i 
!= gs_envVars
.end() ) 
1245     else // this variable hadn't been set before 
1247         gs_envVars
[variable
] = buf
; 
1250     return putenv(buf
) == 0; 
1251 #else // no way to set an env var 
1256 bool wxSetEnv(const wxString
& variable
, const wxString
& value
) 
1258     return wxDoSetEnv(variable
, value
.mb_str()); 
1261 bool wxUnsetEnv(const wxString
& variable
) 
1263     return wxDoSetEnv(variable
, NULL
); 
1266 // ---------------------------------------------------------------------------- 
1268 // ---------------------------------------------------------------------------- 
1270 #if wxUSE_ON_FATAL_EXCEPTION 
1274 extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER
) 
1278         // give the user a chance to do something special about this 
1279         wxTheApp
->OnFatalException(); 
1285 bool wxHandleFatalExceptions(bool doit
) 
1288     static bool s_savedHandlers 
= false; 
1289     static struct sigaction s_handlerFPE
, 
1295     if ( doit 
&& !s_savedHandlers 
) 
1297         // install the signal handler 
1298         struct sigaction act
; 
1300         // some systems extend it with non std fields, so zero everything 
1301         memset(&act
, 0, sizeof(act
)); 
1303         act
.sa_handler 
= wxFatalSignalHandler
; 
1304         sigemptyset(&act
.sa_mask
); 
1307         ok 
&= sigaction(SIGFPE
, &act
, &s_handlerFPE
) == 0; 
1308         ok 
&= sigaction(SIGILL
, &act
, &s_handlerILL
) == 0; 
1309         ok 
&= sigaction(SIGBUS
, &act
, &s_handlerBUS
) == 0; 
1310         ok 
&= sigaction(SIGSEGV
, &act
, &s_handlerSEGV
) == 0; 
1313             wxLogDebug(wxT("Failed to install our signal handler.")); 
1316         s_savedHandlers 
= true; 
1318     else if ( s_savedHandlers 
) 
1320         // uninstall the signal handler 
1321         ok 
&= sigaction(SIGFPE
, &s_handlerFPE
, NULL
) == 0; 
1322         ok 
&= sigaction(SIGILL
, &s_handlerILL
, NULL
) == 0; 
1323         ok 
&= sigaction(SIGBUS
, &s_handlerBUS
, NULL
) == 0; 
1324         ok 
&= sigaction(SIGSEGV
, &s_handlerSEGV
, NULL
) == 0; 
1327             wxLogDebug(wxT("Failed to uninstall our signal handler.")); 
1330         s_savedHandlers 
= false; 
1332     //else: nothing to do 
1337 #endif // wxUSE_ON_FATAL_EXCEPTION 
1339 // ---------------------------------------------------------------------------- 
1340 // wxExecute support 
1341 // ---------------------------------------------------------------------------- 
1343 int wxAppTraits::AddProcessCallback(wxEndProcessData 
*data
, int fd
) 
1345     // define a custom handler processing only the closure of the descriptor 
1346     struct wxEndProcessFDIOHandler 
: public wxFDIOHandler
 
1348         wxEndProcessFDIOHandler(wxEndProcessData 
*data
, int fd
) 
1349             : m_data(data
), m_fd(fd
) 
1353         virtual void OnReadWaiting() 
1355             wxFDIODispatcher::Get()->UnregisterFD(m_fd
); 
1358             wxHandleProcessTermination(m_data
); 
1363         virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1364         virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1366         wxEndProcessData 
* const m_data
; 
1370     wxFDIODispatcher::Get()->RegisterFD
 
1373                                  new wxEndProcessFDIOHandler(data
, fd
), 
1376     return fd
; // unused, but return something unique for the tag 
1379 bool wxAppTraits::CheckForRedirectedIO(wxExecuteData
& execData
) 
1381 #if HAS_PIPE_STREAMS 
1384     if ( execData
.bufOut 
&& execData
.bufOut
->Update() ) 
1387     if ( execData
.bufErr 
&& execData
.bufErr
->Update() ) 
1391 #else // !HAS_PIPE_STREAMS 
1392     wxUnusedVar(execData
); 
1395 #endif // HAS_PIPE_STREAMS/!HAS_PIPE_STREAMS 
1398 // helper classes/functions used by WaitForChild() 
1402 // convenient base class for IO handlers which are registered for read 
1403 // notifications only and which also stores the FD we're reading from 
1405 // the derived classes still have to implement OnReadWaiting() 
1406 class wxReadFDIOHandler 
: public wxFDIOHandler
 
1409     wxReadFDIOHandler(wxFDIODispatcher
& disp
, int fd
) : m_fd(fd
) 
1412             disp
.RegisterFD(fd
, this, wxFDIO_INPUT
); 
1415     virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1416     virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1421     wxDECLARE_NO_COPY_CLASS(wxReadFDIOHandler
); 
1424 // class for monitoring our end of the process detection pipe, simply sets a 
1425 // flag when input on the pipe (which must be due to EOF) is detected 
1426 class wxEndHandler 
: public wxReadFDIOHandler
 
1429     wxEndHandler(wxFDIODispatcher
& disp
, int fd
) 
1430         : wxReadFDIOHandler(disp
, fd
) 
1432         m_terminated 
= false; 
1435     bool Terminated() const { return m_terminated
; } 
1437     virtual void OnReadWaiting() { m_terminated 
= true; } 
1442     wxDECLARE_NO_COPY_CLASS(wxEndHandler
); 
1445 #if HAS_PIPE_STREAMS 
1447 // class for monitoring our ends of child stdout/err, should be constructed 
1448 // with the FD and stream from wxExecuteData and will do nothing if they're 
1451 // unlike wxEndHandler this class registers itself with the provided dispatcher 
1452 class wxRedirectedIOHandler 
: public wxReadFDIOHandler
 
1455     wxRedirectedIOHandler(wxFDIODispatcher
& disp
, 
1457                           wxStreamTempInputBuffer 
*buf
) 
1458         : wxReadFDIOHandler(disp
, fd
), 
1463     virtual void OnReadWaiting() 
1469     wxStreamTempInputBuffer 
* const m_buf
; 
1471     wxDECLARE_NO_COPY_CLASS(wxRedirectedIOHandler
); 
1474 #endif // HAS_PIPE_STREAMS 
1476 // helper function which calls waitpid() and analyzes the result 
1477 int DoWaitForChild(int pid
, int flags 
= 0) 
1479     wxASSERT_MSG( pid 
> 0, "invalid PID" ); 
1483     // loop while we're getting EINTR 
1486         rc 
= waitpid(pid
, &status
, flags
); 
1488         if ( rc 
!= -1 || errno 
!= EINTR 
) 
1494         // This can only happen if the child application closes our dummy pipe 
1495         // that is used to monitor its lifetime; in that case, our best bet is 
1496         // to pretend the process did terminate, because otherwise wxExecute() 
1497         // would hang indefinitely (OnReadWaiting() won't be called again, the 
1498         // descriptor is closed now). 
1499         wxLogDebug("Child process (PID %d) still alive but pipe closed so " 
1500                    "generating a close notification", pid
); 
1502     else if ( rc 
== -1 ) 
1504         wxLogLastError(wxString::Format("waitpid(%d)", pid
)); 
1506     else // child did terminate 
1508         wxASSERT_MSG( rc 
== pid
, "unexpected waitpid() return value" ); 
1510         // notice that the caller expects the exit code to be signed, e.g. -1 
1511         // instead of 255 so don't assign WEXITSTATUS() to an int 
1512         signed char exitcode
; 
1513         if ( WIFEXITED(status
) ) 
1514             exitcode 
= WEXITSTATUS(status
); 
1515         else if ( WIFSIGNALED(status
) ) 
1516             exitcode 
= -WTERMSIG(status
); 
1519             wxLogError("Child process (PID %d) exited for unknown reason, " 
1520                        "status = %d", pid
, status
); 
1530 } // anonymous namespace 
1532 int wxAppTraits::WaitForChild(wxExecuteData
& execData
) 
1534     if ( !(execData
.flags 
& wxEXEC_SYNC
) ) 
1536         // asynchronous execution: just launch the process and return, 
1537         // endProcData will be destroyed when it terminates (currently we leak 
1538         // it if the process doesn't terminate before we do and this should be 
1539         // fixed but it's not a real leak so it's not really very high 
1541         wxEndProcessData 
*endProcData 
= new wxEndProcessData
; 
1542         endProcData
->process 
= execData
.process
; 
1543         endProcData
->pid 
= execData
.pid
; 
1544         endProcData
->tag 
= AddProcessCallback
 
1547                              execData
.GetEndProcReadFD() 
1549         endProcData
->async 
= true; 
1551         return execData
.pid
; 
1553     //else: synchronous execution case 
1555 #if HAS_PIPE_STREAMS && wxUSE_SOCKETS 
1556     wxProcess 
* const process 
= execData
.process
; 
1557     if ( process 
&& process
->IsRedirected() ) 
1559         // we can't simply block waiting for the child to terminate as we would 
1560         // dead lock if it writes more than the pipe buffer size (typically 
1561         // 4KB) bytes of output -- it would then block waiting for us to read 
1562         // the data while we'd block waiting for it to terminate 
1564         // so multiplex here waiting for any input from the child or closure of 
1565         // the pipe used to indicate its termination 
1566         wxSelectDispatcher disp
; 
1568         wxEndHandler 
endHandler(disp
, execData
.GetEndProcReadFD()); 
1570         wxRedirectedIOHandler 
outHandler(disp
, execData
.fdOut
, execData
.bufOut
), 
1571                               errHandler(disp
, execData
.fdErr
, execData
.bufErr
); 
1573         while ( !endHandler
.Terminated() ) 
1578     //else: no IO redirection, just block waiting for the child to exit 
1579 #endif // HAS_PIPE_STREAMS 
1581     return DoWaitForChild(execData
.pid
); 
1584 void wxHandleProcessTermination(wxEndProcessData 
*data
) 
1586     data
->exitcode 
= DoWaitForChild(data
->pid
, WNOHANG
); 
1588     // notify user about termination if required 
1589     if ( data
->process 
) 
1591         data
->process
->OnTerminate(data
->pid
, data
->exitcode
); 
1596         // in case of asynchronous execution we don't need this data any more 
1597         // after the child terminates 
1600     else // sync execution 
1602         // let wxExecute() know that the process has terminated