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 // define this to let wxexec.cpp know that we know what we're doing 
  67 #define _WX_USED_BY_WXEXECUTE_ 
  68 #include "../common/execcmn.cpp" 
  70 #endif // HAS_PIPE_STREAMS 
  72 #if defined(__MWERKS__) && defined(__MACH__) 
  73     #ifndef WXWIN_OS_DESCRIPTION 
  74         #define WXWIN_OS_DESCRIPTION "MacOS X" 
  76     #ifndef HAVE_NANOSLEEP 
  77         #define HAVE_NANOSLEEP 
  83     // our configure test believes we can use sigaction() if the function is 
  84     // available but Metrowekrs with MSL run-time does have the function but 
  85     // doesn't have sigaction struct so finally we can't use it... 
  87         #undef wxUSE_ON_FATAL_EXCEPTION 
  88         #define wxUSE_ON_FATAL_EXCEPTION 0 
  92 // not only the statfs syscall is called differently depending on platform, but 
  93 // one of its incarnations, statvfs(), takes different arguments under 
  94 // different platforms and even different versions of the same system (Solaris 
  95 // 7 and 8): if you want to test for this, don't forget that the problems only 
  96 // appear if the large files support is enabled 
  99         #include <sys/param.h> 
 100         #include <sys/mount.h> 
 103     #endif // __BSD__/!__BSD__ 
 105     #define wxStatfs statfs 
 107     #ifndef HAVE_STATFS_DECL 
 108         // some systems lack statfs() prototype in the system headers (AIX 4) 
 109         extern "C" int statfs(const char *path
, struct statfs 
*buf
); 
 111 #endif // HAVE_STATFS 
 114     #include <sys/statvfs.h> 
 116     #define wxStatfs statvfs 
 117 #endif // HAVE_STATVFS 
 119 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) 
 120     // WX_STATFS_T is detected by configure 
 121     #define wxStatfs_t WX_STATFS_T 
 124 // SGI signal.h defines signal handler arguments differently depending on 
 125 // whether _LANGUAGE_C_PLUS_PLUS is set or not - do set it 
 126 #if defined(__SGI__) && !defined(_LANGUAGE_C_PLUS_PLUS) 
 127     #define _LANGUAGE_C_PLUS_PLUS 1 
 133 #include <sys/stat.h> 
 134 #include <sys/types.h> 
 135 #include <sys/wait.h> 
 140 #include <fcntl.h>          // for O_WRONLY and friends 
 141 #include <time.h>           // nanosleep() and/or usleep() 
 142 #include <ctype.h>          // isspace() 
 143 #include <sys/time.h>       // needed for FD_SETSIZE 
 146     #include <sys/utsname.h> // for uname() 
 149 // Used by wxGetFreeMemory(). 
 151     #include <sys/sysmp.h> 
 152     #include <sys/sysinfo.h>   // for SAGET and MINFO structures 
 155 // ---------------------------------------------------------------------------- 
 156 // conditional compilation 
 157 // ---------------------------------------------------------------------------- 
 159 // many versions of Unices have this function, but it is not defined in system 
 160 // headers - please add your system here if it is the case for your OS. 
 161 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. 
 162 #if !defined(HAVE_USLEEP) && \ 
 163     ((defined(__SUN__) && !defined(__SunOs_5_6) && \ 
 164                          !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ 
 165      defined(__osf__) || defined(__EMX__)) 
 169             /* I copied this from the XFree86 diffs. AV. */ 
 170             #define INCL_DOSPROCESS 
 172             inline void usleep(unsigned long delay
) 
 174                 DosSleep(delay 
? (delay
/1000l) : 1l); 
 177             int usleep(unsigned int usec
); 
 178         #endif // __EMX__/Unix 
 181     #define HAVE_USLEEP 1 
 182 #endif // Unices without usleep() 
 184 // ============================================================================ 
 186 // ============================================================================ 
 188 // ---------------------------------------------------------------------------- 
 190 // ---------------------------------------------------------------------------- 
 192 void wxSleep(int nSecs
) 
 197 void wxMicroSleep(unsigned long microseconds
) 
 199 #if defined(HAVE_NANOSLEEP) 
 201     tmReq
.tv_sec 
= (time_t)(microseconds 
/ 1000000); 
 202     tmReq
.tv_nsec 
= (microseconds 
% 1000000) * 1000; 
 204     // we're not interested in remaining time nor in return value 
 205     (void)nanosleep(&tmReq
, NULL
); 
 206 #elif defined(HAVE_USLEEP) 
 207     // uncomment this if you feel brave or if you are sure that your version 
 208     // of Solaris has a safe usleep() function but please notice that usleep() 
 209     // is known to lead to crashes in MT programs in Solaris 2.[67] and is not 
 210     // documented as MT-Safe 
 211     #if defined(__SUN__) && wxUSE_THREADS 
 212         #error "usleep() cannot be used in MT programs under Solaris." 
 215     usleep(microseconds
); 
 216 #elif defined(HAVE_SLEEP) 
 217     // under BeOS sleep() takes seconds (what about other platforms, if any?) 
 218     sleep(microseconds 
* 1000000); 
 219 #else // !sleep function 
 220     #error "usleep() or nanosleep() function required for wxMicroSleep" 
 221 #endif // sleep function 
 224 void wxMilliSleep(unsigned long milliseconds
) 
 226     wxMicroSleep(milliseconds
*1000); 
 229 // ---------------------------------------------------------------------------- 
 230 // process management 
 231 // ---------------------------------------------------------------------------- 
 233 int wxKill(long pid
, wxSignal sig
, wxKillError 
*rc
, int flags
) 
 235     int err 
= kill((pid_t
) (flags 
& wxKILL_CHILDREN
) ? -pid 
: pid
, (int)sig
); 
 238         switch ( err 
? errno 
: 0 ) 
 245                 *rc 
= wxKILL_BAD_SIGNAL
; 
 249                 *rc 
= wxKILL_ACCESS_DENIED
; 
 253                 *rc 
= wxKILL_NO_PROCESS
; 
 257                 // this goes against Unix98 docs so log it 
 258                 wxLogDebug(wxT("unexpected kill(2) return value %d"), err
); 
 268 // Shutdown or reboot the PC 
 269 bool wxShutdown(int flags
) 
 271     flags 
&= ~wxSHUTDOWN_FORCE
; 
 276         case wxSHUTDOWN_POWEROFF
: 
 280         case wxSHUTDOWN_REBOOT
: 
 284         case wxSHUTDOWN_LOGOFF
: 
 285             // TODO: use dcop to log off? 
 289             wxFAIL_MSG( wxT("unknown wxShutdown() flag") ); 
 293     return system(wxString::Format("init %c", level
).mb_str()) == 0; 
 296 // ---------------------------------------------------------------------------- 
 297 // wxStream classes to support IO redirection in wxExecute 
 298 // ---------------------------------------------------------------------------- 
 302 bool wxPipeInputStream::CanRead() const 
 304     if ( m_lasterror 
== wxSTREAM_EOF 
) 
 307     // check if there is any input available 
 312     const int fd 
= m_file
->fd(); 
 317     wxFD_SET(fd
, &readfds
); 
 319     switch ( select(fd 
+ 1, &readfds
, NULL
, NULL
, &tv
) ) 
 322             wxLogSysError(_("Impossible to get child process input")); 
 329             wxFAIL_MSG(wxT("unexpected select() return value")); 
 330             // still fall through 
 333             // input available -- or maybe not, as select() returns 1 when a 
 334             // read() will complete without delay, but it could still not read 
 340 size_t wxPipeOutputStream::OnSysWrite(const void *buffer
, size_t size
) 
 342     // We need to suppress error logging here, because on writing to a pipe 
 343     // which is full, wxFile::Write reports a system error. However, this is 
 344     // not an extraordinary situation, and it should not be reported to the 
 345     // user (but if really needed, the program can recognize it by checking 
 346     // whether LastRead() == 0.) Other errors will be reported below. 
 350         ret 
= m_file
->Write(buffer
, size
); 
 353     switch ( m_file
->GetLastError() ) 
 359 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) 
 362            // do not treat it as an error 
 363            m_file
->ClearLastError(); 
 372            wxLogSysError(_("Can't write to child process's stdin")); 
 373            m_lasterror 
= wxSTREAM_WRITE_ERROR
; 
 379 #endif // HAS_PIPE_STREAMS 
 381 // ---------------------------------------------------------------------------- 
 383 // ---------------------------------------------------------------------------- 
 385 static wxString 
wxMakeShellCommand(const wxString
& command
) 
 390         // just an interactive shell 
 395         // execute command in a shell 
 396         cmd 
<< wxT("/bin/sh -c '") << command 
<< wxT('\''); 
 402 bool wxShell(const wxString
& command
) 
 404     return wxExecute(wxMakeShellCommand(command
), wxEXEC_SYNC
) == 0; 
 407 bool wxShell(const wxString
& command
, wxArrayString
& output
) 
 409     wxCHECK_MSG( !command
.empty(), false, wxT("can't exec shell non interactively") ); 
 411     return wxExecute(wxMakeShellCommand(command
), output
); 
 417 // helper class for storing arguments as char** array suitable for passing to 
 418 // execvp(), whatever form they were passed to us 
 422     ArgsArray(const wxArrayString
& args
) 
 426         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 428             m_argv
[i
] = wxStrdup(args
[i
]); 
 433     ArgsArray(wchar_t **wargv
) 
 436         while ( wargv
[argc
] ) 
 441         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 443             m_argv
[i
] = wxSafeConvertWX2MB(wargv
[i
]).release(); 
 446 #endif // wxUSE_UNICODE 
 450         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 458     operator char**() const { return m_argv
; } 
 464         m_argv 
= new char *[m_argc 
+ 1]; 
 465         m_argv
[m_argc
] = NULL
; 
 471     wxDECLARE_NO_COPY_CLASS(ArgsArray
); 
 474 } // anonymous namespace 
 476 // ---------------------------------------------------------------------------- 
 477 // wxExecute implementations 
 478 // ---------------------------------------------------------------------------- 
 480 #if defined(__DARWIN__) 
 481 bool wxMacLaunch(char **argv
); 
 484 long wxExecute(const wxString
& command
, int flags
, wxProcess 
*process
, 
 485         const wxExecuteEnv 
*env
) 
 487     ArgsArray 
argv(wxCmdLineParser::ConvertStringToArgs(command
, 
 488                                                         wxCMD_LINE_SPLIT_UNIX
)); 
 490     return wxExecute(argv
, flags
, process
, env
); 
 495 long wxExecute(wchar_t **wargv
, int flags
, wxProcess 
*process
, 
 496         const wxExecuteEnv 
*env
) 
 498     ArgsArray 
argv(wargv
); 
 500     return wxExecute(argv
, flags
, process
, env
); 
 503 #endif // wxUSE_UNICODE 
 505 // wxExecute: the real worker function 
 506 long wxExecute(char **argv
, int flags
, wxProcess 
*process
, 
 507         const wxExecuteEnv 
*env
) 
 509     // for the sync execution, we return -1 to indicate failure, but for async 
 510     // case we return 0 which is never a valid PID 
 512     // we define this as a macro, not a variable, to avoid compiler warnings 
 513     // about "ERROR_RETURN_CODE value may be clobbered by fork()" 
 514     #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0) 
 516     wxCHECK_MSG( *argv
, ERROR_RETURN_CODE
, wxT("can't exec empty command") ); 
 519     // fork() doesn't mix well with POSIX threads: on many systems the program 
 520     // deadlocks or crashes for some reason. Probably our code is buggy and 
 521     // doesn't do something which must be done to allow this to work, but I 
 522     // don't know what yet, so for now just warn the user (this is the least we 
 524     wxASSERT_MSG( wxThread::IsMain(), 
 525                     wxT("wxExecute() can be called only from the main thread") ); 
 526 #endif // wxUSE_THREADS 
 528 #if defined(__WXCOCOA__) || ( defined(__WXOSX_MAC__) && wxOSX_USE_COCOA_OR_CARBON ) 
 529     // wxMacLaunch() only executes app bundles and only does it asynchronously. 
 530     // It returns false if the target is not an app bundle, thus falling 
 531     // through to the regular code for non app bundles. 
 532     if ( !(flags 
& wxEXEC_SYNC
) && wxMacLaunch(argv
) ) 
 534         // we don't have any PID to return so just make up something non null 
 540     // this struct contains all information which we use for housekeeping 
 541     wxExecuteData execData
; 
 542     execData
.flags 
= flags
; 
 543     execData
.process 
= process
; 
 546     if ( !execData
.pipeEndProcDetect
.Create() ) 
 548         wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 550         return ERROR_RETURN_CODE
; 
 553     // pipes for inter process communication 
 554     wxPipe pipeIn
,      // stdin 
 558     if ( process 
&& process
->IsRedirected() ) 
 560         if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() ) 
 562             wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 564             return ERROR_RETURN_CODE
; 
 570     // NB: do *not* use vfork() here, it completely breaks this code for some 
 571     //     reason under Solaris (and maybe others, although not under Linux) 
 572     //     But on OpenVMS we do not have fork so we have to use vfork and 
 573     //     cross our fingers that it works. 
 579    if ( pid 
== -1 )     // error? 
 581         wxLogSysError( _("Fork failed") ); 
 583         return ERROR_RETURN_CODE
; 
 585     else if ( pid 
== 0 )  // we're in child 
 587         // NB: we used to close all the unused descriptors of the child here 
 588         //     but this broke some programs which relied on e.g. FD 1 being 
 589         //     always opened so don't do it any more, after all there doesn't 
 590         //     seem to be any real problem with keeping them opened 
 592 #if !defined(__VMS) && !defined(__EMX__) 
 593         if ( flags 
& wxEXEC_MAKE_GROUP_LEADER 
) 
 595             // Set process group to child process' pid.  Then killing -pid 
 596             // of the parent will kill the process and all of its children. 
 601         // redirect stdin, stdout and stderr 
 604             if ( dup2(pipeIn
[wxPipe::Read
], STDIN_FILENO
) == -1 || 
 605                  dup2(pipeOut
[wxPipe::Write
], STDOUT_FILENO
) == -1 || 
 606                  dup2(pipeErr
[wxPipe::Write
], STDERR_FILENO
) == -1 ) 
 608                 wxLogSysError(_("Failed to redirect child process input/output")); 
 616         // Close all (presumably accidentally) inherited file descriptors to 
 617         // avoid descriptor leaks. This means that we don't allow inheriting 
 618         // them purposefully but this seems like a lesser evil in wx code. 
 619         // Ideally we'd provide some flag to indicate that none (or some?) of 
 620         // the descriptors do not need to be closed but for now this is better 
 621         // than never closing them at all as wx code never used FD_CLOEXEC. 
 623         // Note that while the reading side of the end process detection pipe 
 624         // can be safely closed, we should keep the write one opened, it will 
 625         // be only closed when the process terminates resulting in a read 
 626         // notification to the parent 
 627         const int fdEndProc 
= execData
.pipeEndProcDetect
.Detach(wxPipe::Write
); 
 628         execData
.pipeEndProcDetect
.Close(); 
 630         // TODO: Iterating up to FD_SETSIZE is both inefficient (because it may 
 631         //       be quite big) and incorrect (because in principle we could 
 632         //       have more opened descriptions than this number). Unfortunately 
 633         //       there is no good portable solution for closing all descriptors 
 634         //       above a certain threshold but non-portable solutions exist for 
 635         //       most platforms, see [http://stackoverflow.com/questions/899038/ 
 636         //          getting-the-highest-allocated-file-descriptor] 
 637         for ( int fd 
= 0; fd 
< (int)FD_SETSIZE
; ++fd 
) 
 639             if ( fd 
!= STDIN_FILENO  
&& 
 640                  fd 
!= STDOUT_FILENO 
&& 
 641                  fd 
!= STDERR_FILENO 
&& 
 649         // Process additional options if we have any 
 652             // Change working directory if it is specified 
 653             if ( !env
->cwd
.empty() ) 
 654                 wxSetWorkingDirectory(env
->cwd
); 
 656             // Change environment if needed. 
 658             // NB: We can't use execve() currently because we allow using 
 659             //     non full paths to wxExecute(), i.e. we want to search for 
 660             //     the program in PATH. However it just might be simpler/better 
 661             //     to do the search manually and use execve() envp parameter to 
 662             //     set up the environment of the child process explicitly 
 663             //     instead of doing what we do below. 
 664             if ( !env
->env
.empty() ) 
 666                 wxEnvVariableHashMap oldenv
; 
 667                 wxGetEnvMap(&oldenv
); 
 669                 // Remove unwanted variables 
 670                 wxEnvVariableHashMap::const_iterator it
; 
 671                 for ( it 
= oldenv
.begin(); it 
!= oldenv
.end(); ++it 
) 
 673                     if ( env
->env
.find(it
->first
) == env
->env
.end() ) 
 674                         wxUnsetEnv(it
->first
); 
 677                 // And add the new ones (possibly replacing the old values) 
 678                 for ( it 
= env
->env
.begin(); it 
!= env
->env
.end(); ++it 
) 
 679                     wxSetEnv(it
->first
, it
->second
); 
 685         fprintf(stderr
, "execvp("); 
 686         for ( char **a 
= argv
; *a
; a
++ ) 
 687             fprintf(stderr
, "%s%s", a 
== argv 
? "" : ", ", *a
); 
 688         fprintf(stderr
, ") failed with error %d!\n", errno
); 
 690         // there is no return after successful exec() 
 693         // some compilers complain about missing return - of course, they 
 694         // should know that exit() doesn't return but what else can we do if 
 697         // and, sure enough, other compilers complain about unreachable code 
 698         // after exit() call, so we can just always have return here... 
 699 #if defined(__VMS) || defined(__INTEL_COMPILER) 
 703     else // we're in parent 
 705         // save it for WaitForChild() use 
 707         if (execData
.process
) 
 708             execData
.process
->SetPid(pid
);  // and also in the wxProcess 
 710         // prepare for IO redirection 
 713         // the input buffer bufOut is connected to stdout, this is why it is 
 714         // called bufOut and not bufIn 
 715         wxStreamTempInputBuffer bufOut
, 
 718         if ( process 
&& process
->IsRedirected() ) 
 720             // Avoid deadlocks which could result from trying to write to the 
 721             // child input pipe end while the child itself is writing to its 
 722             // output end and waiting for us to read from it. 
 723             if ( !pipeIn
.MakeNonBlocking(wxPipe::Write
) ) 
 725                 // This message is not terrible useful for the user but what 
 726                 // else can we do? Also, should we fail here or take the risk 
 727                 // to continue and deadlock? Currently we choose the latter but 
 728                 // it might not be the best idea. 
 729                 wxLogSysError(_("Failed to set up non-blocking pipe, " 
 730                                 "the program might hang.")); 
 732                 wxLog::FlushActive(); 
 736             wxOutputStream 
*inStream 
= 
 737                 new wxPipeOutputStream(pipeIn
.Detach(wxPipe::Write
)); 
 739             const int fdOut 
= pipeOut
.Detach(wxPipe::Read
); 
 740             wxPipeInputStream 
*outStream 
= new wxPipeInputStream(fdOut
); 
 742             const int fdErr 
= pipeErr
.Detach(wxPipe::Read
); 
 743             wxPipeInputStream 
*errStream 
= new wxPipeInputStream(fdErr
); 
 745             process
->SetPipeStreams(outStream
, inStream
, errStream
); 
 747             bufOut
.Init(outStream
); 
 748             bufErr
.Init(errStream
); 
 750             execData
.bufOut 
= &bufOut
; 
 751             execData
.bufErr 
= &bufErr
; 
 753             execData
.fdOut 
= fdOut
; 
 754             execData
.fdErr 
= fdErr
; 
 756 #endif // HAS_PIPE_STREAMS 
 765         // we want this function to work even if there is no wxApp so ensure 
 766         // that we have a valid traits pointer 
 767         wxConsoleAppTraits traitsConsole
; 
 768         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 770             traits 
= &traitsConsole
; 
 772         return traits
->WaitForChild(execData
); 
 775 #if !defined(__VMS) && !defined(__INTEL_COMPILER) 
 776     return ERROR_RETURN_CODE
; 
 780 #undef ERROR_RETURN_CODE 
 782 // ---------------------------------------------------------------------------- 
 783 // file and directory functions 
 784 // ---------------------------------------------------------------------------- 
 786 const wxChar
* wxGetHomeDir( wxString 
*home  
) 
 788     *home 
= wxGetUserHome(); 
 794     if ( tmp
.Last() != wxT(']')) 
 795         if ( tmp
.Last() != wxT('/')) *home 
<< wxT('/'); 
 797     return home
->c_str(); 
 800 wxString 
wxGetUserHome( const wxString 
&user 
) 
 802     struct passwd 
*who 
= (struct passwd 
*) NULL
; 
 808         if ((ptr 
= wxGetenv(wxT("HOME"))) != NULL
) 
 813         if ((ptr 
= wxGetenv(wxT("USER"))) != NULL 
|| 
 814              (ptr 
= wxGetenv(wxT("LOGNAME"))) != NULL
) 
 816             who 
= getpwnam(wxSafeConvertWX2MB(ptr
)); 
 819         // make sure the user exists! 
 822             who 
= getpwuid(getuid()); 
 827       who 
= getpwnam (user
.mb_str()); 
 830     return wxSafeConvertMB2WX(who 
? who
->pw_dir 
: 0); 
 833 // ---------------------------------------------------------------------------- 
 834 // network and user id routines 
 835 // ---------------------------------------------------------------------------- 
 837 // private utility function which returns output of the given command, removing 
 838 // the trailing newline 
 839 static wxString 
wxGetCommandOutput(const wxString 
&cmd
) 
 841     FILE *f 
= popen(cmd
.ToAscii(), "r"); 
 844         wxLogSysError(wxT("Executing \"%s\" failed"), cmd
.c_str()); 
 845         return wxEmptyString
; 
 852         if ( !fgets(buf
, sizeof(buf
), f
) ) 
 855         s 
+= wxString::FromAscii(buf
); 
 860     if ( !s
.empty() && s
.Last() == wxT('\n') ) 
 866 // retrieve either the hostname or FQDN depending on platform (caller must 
 867 // check whether it's one or the other, this is why this function is for 
 869 static bool wxGetHostNameInternal(wxChar 
*buf
, int sz
) 
 871     wxCHECK_MSG( buf
, false, wxT("NULL pointer in wxGetHostNameInternal") ); 
 875     // we're using uname() which is POSIX instead of less standard sysinfo() 
 876 #if defined(HAVE_UNAME) 
 878     bool ok 
= uname(&uts
) != -1; 
 881         wxStrlcpy(buf
, wxSafeConvertMB2WX(uts
.nodename
), sz
); 
 883 #elif defined(HAVE_GETHOSTNAME) 
 885     bool ok 
= gethostname(cbuf
, sz
) != -1; 
 888         wxStrlcpy(buf
, wxSafeConvertMB2WX(cbuf
), sz
); 
 890 #else // no uname, no gethostname 
 891     wxFAIL_MSG(wxT("don't know host name for this machine")); 
 894 #endif // uname/gethostname 
 898         wxLogSysError(_("Cannot get the hostname")); 
 904 bool wxGetHostName(wxChar 
*buf
, int sz
) 
 906     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 910         // BSD systems return the FQDN, we only want the hostname, so extract 
 911         // it (we consider that dots are domain separators) 
 912         wxChar 
*dot 
= wxStrchr(buf
, wxT('.')); 
 923 bool wxGetFullHostName(wxChar 
*buf
, int sz
) 
 925     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 929         if ( !wxStrchr(buf
, wxT('.')) ) 
 931             struct hostent 
*host 
= gethostbyname(wxSafeConvertWX2MB(buf
)); 
 934                 wxLogSysError(_("Cannot get the official hostname")); 
 940                 // the canonical name 
 941                 wxStrlcpy(buf
, wxSafeConvertMB2WX(host
->h_name
), sz
); 
 944         //else: it's already a FQDN (BSD behaves this way) 
 950 bool wxGetUserId(wxChar 
*buf
, int sz
) 
 955     if ((who 
= getpwuid(getuid ())) != NULL
) 
 957         wxStrlcpy (buf
, wxSafeConvertMB2WX(who
->pw_name
), sz
); 
 964 bool wxGetUserName(wxChar 
*buf
, int sz
) 
 970     if ((who 
= getpwuid (getuid ())) != NULL
) 
 972        char *comma 
= strchr(who
->pw_gecos
, ','); 
 974            *comma 
= '\0'; // cut off non-name comment fields 
 975        wxStrlcpy(buf
, wxSafeConvertMB2WX(who
->pw_gecos
), sz
); 
 980 #else // !HAVE_PW_GECOS 
 981     return wxGetUserId(buf
, sz
); 
 982 #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS 
 985 bool wxIsPlatform64Bit() 
 987     const wxString machine 
= wxGetCommandOutput(wxT("uname -m")); 
 989     // the test for "64" is obviously not 100% reliable but seems to work fine 
 991     return machine
.Contains(wxT("64")) || 
 992                 machine
.Contains(wxT("alpha")); 
 996 wxLinuxDistributionInfo 
wxGetLinuxDistributionInfo() 
 998     const wxString id 
= wxGetCommandOutput(wxT("lsb_release --id")); 
 999     const wxString desc 
= wxGetCommandOutput(wxT("lsb_release --description")); 
1000     const wxString rel 
= wxGetCommandOutput(wxT("lsb_release --release")); 
1001     const wxString codename 
= wxGetCommandOutput(wxT("lsb_release --codename")); 
1003     wxLinuxDistributionInfo ret
; 
1005     id
.StartsWith("Distributor ID:\t", &ret
.Id
); 
1006     desc
.StartsWith("Description:\t", &ret
.Description
); 
1007     rel
.StartsWith("Release:\t", &ret
.Release
); 
1008     codename
.StartsWith("Codename:\t", &ret
.CodeName
); 
1014 // these functions are in src/osx/utilsexc_base.cpp for wxMac 
1017 wxOperatingSystemId 
wxGetOsVersion(int *verMaj
, int *verMin
) 
1021     wxString release 
= wxGetCommandOutput(wxT("uname -r")); 
1022     if ( release
.empty() || 
1023          wxSscanf(release
.c_str(), wxT("%d.%d"), &major
, &minor
) != 2 ) 
1025         // failed to get version string or unrecognized format 
1035     // try to understand which OS are we running 
1036     wxString kernel 
= wxGetCommandOutput(wxT("uname -s")); 
1037     if ( kernel
.empty() ) 
1038         kernel 
= wxGetCommandOutput(wxT("uname -o")); 
1040     if ( kernel
.empty() ) 
1041         return wxOS_UNKNOWN
; 
1043     return wxPlatformInfo::GetOperatingSystemId(kernel
); 
1046 wxString 
wxGetOsDescription() 
1048     return wxGetCommandOutput(wxT("uname -s -r -m")); 
1051 #endif // !__WXMAC__ 
1053 unsigned long wxGetProcessId() 
1055     return (unsigned long)getpid(); 
1058 wxMemorySize 
wxGetFreeMemory() 
1060 #if defined(__LINUX__) 
1061     // get it from /proc/meminfo 
1062     FILE *fp 
= fopen("/proc/meminfo", "r"); 
1068         if ( fgets(buf
, WXSIZEOF(buf
), fp
) && fgets(buf
, WXSIZEOF(buf
), fp
) ) 
1070             // /proc/meminfo changed its format in kernel 2.6 
1071             if ( wxPlatformInfo().CheckOSVersion(2, 6) ) 
1073                 unsigned long cached
, buffers
; 
1074                 sscanf(buf
, "MemFree: %ld", &memFree
); 
1076                 fgets(buf
, WXSIZEOF(buf
), fp
); 
1077                 sscanf(buf
, "Buffers: %lu", &buffers
); 
1079                 fgets(buf
, WXSIZEOF(buf
), fp
); 
1080                 sscanf(buf
, "Cached: %lu", &cached
); 
1082                 // add to "MemFree" also the "Buffers" and "Cached" values as 
1083                 // free(1) does as otherwise the value never makes sense: for 
1084                 // kernel 2.6 it's always almost 0 
1085                 memFree 
+= buffers 
+ cached
; 
1087                 // values here are always expressed in kB and we want bytes 
1090             else // Linux 2.4 (or < 2.6, anyhow) 
1092                 long memTotal
, memUsed
; 
1093                 sscanf(buf
, "Mem: %ld %ld %ld", &memTotal
, &memUsed
, &memFree
); 
1099         return (wxMemorySize
)memFree
; 
1101 #elif defined(__SGI__) 
1102     struct rminfo realmem
; 
1103     if ( sysmp(MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0 ) 
1104         return ((wxMemorySize
)realmem
.physmem 
* sysconf(_SC_PAGESIZE
)); 
1105 #elif defined(_SC_AVPHYS_PAGES) 
1106     return ((wxMemorySize
)sysconf(_SC_AVPHYS_PAGES
))*sysconf(_SC_PAGESIZE
); 
1107 //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably 
1110     // can't find it out 
1114 bool wxGetDiskSpace(const wxString
& path
, wxDiskspaceSize_t 
*pTotal
, wxDiskspaceSize_t 
*pFree
) 
1116 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) 
1117     // the case to "char *" is needed for AIX 4.3 
1119     if ( wxStatfs((char *)(const char*)path
.fn_str(), &fs
) != 0 ) 
1121         wxLogSysError( wxT("Failed to get file system statistics") ); 
1126     // under Solaris we also have to use f_frsize field instead of f_bsize 
1127     // which is in general a multiple of f_frsize 
1129     wxDiskspaceSize_t blockSize 
= fs
.f_frsize
; 
1130 #else // HAVE_STATFS 
1131     wxDiskspaceSize_t blockSize 
= fs
.f_bsize
; 
1132 #endif // HAVE_STATVFS/HAVE_STATFS 
1136         *pTotal 
= wxDiskspaceSize_t(fs
.f_blocks
) * blockSize
; 
1141         *pFree 
= wxDiskspaceSize_t(fs
.f_bavail
) * blockSize
; 
1145 #else // !HAVE_STATFS && !HAVE_STATVFS 
1147 #endif // HAVE_STATFS 
1150 // ---------------------------------------------------------------------------- 
1152 // ---------------------------------------------------------------------------- 
1156 WX_DECLARE_STRING_HASH_MAP(char *, wxEnvVars
); 
1158 static wxEnvVars gs_envVars
; 
1160 class wxSetEnvModule 
: public wxModule
 
1163     virtual bool OnInit() { return true; } 
1164     virtual void OnExit() 
1166         for ( wxEnvVars::const_iterator i 
= gs_envVars
.begin(); 
1167               i 
!= gs_envVars
.end(); 
1176     DECLARE_DYNAMIC_CLASS(wxSetEnvModule
) 
1179 IMPLEMENT_DYNAMIC_CLASS(wxSetEnvModule
, wxModule
) 
1181 #endif // USE_PUTENV 
1183 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
1185     // wxGetenv is defined as getenv() 
1186     char *p 
= wxGetenv(var
); 
1198 static bool wxDoSetEnv(const wxString
& variable
, const char *value
) 
1200 #if defined(HAVE_SETENV) 
1203 #ifdef HAVE_UNSETENV 
1204         // don't test unsetenv() return value: it's void on some systems (at 
1206         unsetenv(variable
.mb_str()); 
1209         value 
= ""; // we can't pass NULL to setenv() 
1213     return setenv(variable
.mb_str(), value
, 1 /* overwrite */) == 0; 
1214 #elif defined(HAVE_PUTENV) 
1215     wxString s 
= variable
; 
1217         s 
<< wxT('=') << value
; 
1219     // transform to ANSI 
1220     const wxWX2MBbuf p 
= s
.mb_str(); 
1222     char *buf 
= (char *)malloc(strlen(p
) + 1); 
1225     // store the string to free() it later 
1226     wxEnvVars::iterator i 
= gs_envVars
.find(variable
); 
1227     if ( i 
!= gs_envVars
.end() ) 
1232     else // this variable hadn't been set before 
1234         gs_envVars
[variable
] = buf
; 
1237     return putenv(buf
) == 0; 
1238 #else // no way to set an env var 
1243 bool wxSetEnv(const wxString
& variable
, const wxString
& value
) 
1245     return wxDoSetEnv(variable
, value
.mb_str()); 
1248 bool wxUnsetEnv(const wxString
& variable
) 
1250     return wxDoSetEnv(variable
, NULL
); 
1253 // ---------------------------------------------------------------------------- 
1255 // ---------------------------------------------------------------------------- 
1257 #if wxUSE_ON_FATAL_EXCEPTION 
1261 extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER
) 
1265         // give the user a chance to do something special about this 
1266         wxTheApp
->OnFatalException(); 
1272 bool wxHandleFatalExceptions(bool doit
) 
1275     static bool s_savedHandlers 
= false; 
1276     static struct sigaction s_handlerFPE
, 
1282     if ( doit 
&& !s_savedHandlers 
) 
1284         // install the signal handler 
1285         struct sigaction act
; 
1287         // some systems extend it with non std fields, so zero everything 
1288         memset(&act
, 0, sizeof(act
)); 
1290         act
.sa_handler 
= wxFatalSignalHandler
; 
1291         sigemptyset(&act
.sa_mask
); 
1294         ok 
&= sigaction(SIGFPE
, &act
, &s_handlerFPE
) == 0; 
1295         ok 
&= sigaction(SIGILL
, &act
, &s_handlerILL
) == 0; 
1296         ok 
&= sigaction(SIGBUS
, &act
, &s_handlerBUS
) == 0; 
1297         ok 
&= sigaction(SIGSEGV
, &act
, &s_handlerSEGV
) == 0; 
1300             wxLogDebug(wxT("Failed to install our signal handler.")); 
1303         s_savedHandlers 
= true; 
1305     else if ( s_savedHandlers 
) 
1307         // uninstall the signal handler 
1308         ok 
&= sigaction(SIGFPE
, &s_handlerFPE
, NULL
) == 0; 
1309         ok 
&= sigaction(SIGILL
, &s_handlerILL
, NULL
) == 0; 
1310         ok 
&= sigaction(SIGBUS
, &s_handlerBUS
, NULL
) == 0; 
1311         ok 
&= sigaction(SIGSEGV
, &s_handlerSEGV
, NULL
) == 0; 
1314             wxLogDebug(wxT("Failed to uninstall our signal handler.")); 
1317         s_savedHandlers 
= false; 
1319     //else: nothing to do 
1324 #endif // wxUSE_ON_FATAL_EXCEPTION 
1326 // ---------------------------------------------------------------------------- 
1327 // wxExecute support 
1328 // ---------------------------------------------------------------------------- 
1330 int wxAppTraits::AddProcessCallback(wxEndProcessData 
*data
, int fd
) 
1332     // define a custom handler processing only the closure of the descriptor 
1333     struct wxEndProcessFDIOHandler 
: public wxFDIOHandler
 
1335         wxEndProcessFDIOHandler(wxEndProcessData 
*data
, int fd
) 
1336             : m_data(data
), m_fd(fd
) 
1340         virtual void OnReadWaiting() 
1342             wxFDIODispatcher::Get()->UnregisterFD(m_fd
); 
1345             wxHandleProcessTermination(m_data
); 
1350         virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1351         virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1353         wxEndProcessData 
* const m_data
; 
1357     wxFDIODispatcher::Get()->RegisterFD
 
1360                                  new wxEndProcessFDIOHandler(data
, fd
), 
1363     return fd
; // unused, but return something unique for the tag 
1366 bool wxAppTraits::CheckForRedirectedIO(wxExecuteData
& execData
) 
1368 #if HAS_PIPE_STREAMS 
1371     if ( execData
.bufOut 
&& execData
.bufOut
->Update() ) 
1374     if ( execData
.bufErr 
&& execData
.bufErr
->Update() ) 
1378 #else // !HAS_PIPE_STREAMS 
1379     wxUnusedVar(execData
); 
1382 #endif // HAS_PIPE_STREAMS/!HAS_PIPE_STREAMS 
1385 // helper classes/functions used by WaitForChild() 
1389 // convenient base class for IO handlers which are registered for read 
1390 // notifications only and which also stores the FD we're reading from 
1392 // the derived classes still have to implement OnReadWaiting() 
1393 class wxReadFDIOHandler 
: public wxFDIOHandler
 
1396     wxReadFDIOHandler(wxFDIODispatcher
& disp
, int fd
) : m_fd(fd
) 
1399             disp
.RegisterFD(fd
, this, wxFDIO_INPUT
); 
1402     virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1403     virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1408     wxDECLARE_NO_COPY_CLASS(wxReadFDIOHandler
); 
1411 // class for monitoring our end of the process detection pipe, simply sets a 
1412 // flag when input on the pipe (which must be due to EOF) is detected 
1413 class wxEndHandler 
: public wxReadFDIOHandler
 
1416     wxEndHandler(wxFDIODispatcher
& disp
, int fd
) 
1417         : wxReadFDIOHandler(disp
, fd
) 
1419         m_terminated 
= false; 
1422     bool Terminated() const { return m_terminated
; } 
1424     virtual void OnReadWaiting() { m_terminated 
= true; } 
1429     wxDECLARE_NO_COPY_CLASS(wxEndHandler
); 
1432 #if HAS_PIPE_STREAMS 
1434 // class for monitoring our ends of child stdout/err, should be constructed 
1435 // with the FD and stream from wxExecuteData and will do nothing if they're 
1438 // unlike wxEndHandler this class registers itself with the provided dispatcher 
1439 class wxRedirectedIOHandler 
: public wxReadFDIOHandler
 
1442     wxRedirectedIOHandler(wxFDIODispatcher
& disp
, 
1444                           wxStreamTempInputBuffer 
*buf
) 
1445         : wxReadFDIOHandler(disp
, fd
), 
1450     virtual void OnReadWaiting() 
1456     wxStreamTempInputBuffer 
* const m_buf
; 
1458     wxDECLARE_NO_COPY_CLASS(wxRedirectedIOHandler
); 
1461 #endif // HAS_PIPE_STREAMS 
1463 // helper function which calls waitpid() and analyzes the result 
1464 int DoWaitForChild(int pid
, int flags 
= 0) 
1466     wxASSERT_MSG( pid 
> 0, "invalid PID" ); 
1470     // loop while we're getting EINTR 
1473         rc 
= waitpid(pid
, &status
, flags
); 
1475         if ( rc 
!= -1 || errno 
!= EINTR 
) 
1481         // This can only happen if the child application closes our dummy pipe 
1482         // that is used to monitor its lifetime; in that case, our best bet is 
1483         // to pretend the process did terminate, because otherwise wxExecute() 
1484         // would hang indefinitely (OnReadWaiting() won't be called again, the 
1485         // descriptor is closed now). 
1486         wxLogDebug("Child process (PID %d) still alive but pipe closed so " 
1487                    "generating a close notification", pid
); 
1489     else if ( rc 
== -1 ) 
1491         wxLogLastError(wxString::Format("waitpid(%d)", pid
)); 
1493     else // child did terminate 
1495         wxASSERT_MSG( rc 
== pid
, "unexpected waitpid() return value" ); 
1497         // notice that the caller expects the exit code to be signed, e.g. -1 
1498         // instead of 255 so don't assign WEXITSTATUS() to an int 
1499         signed char exitcode
; 
1500         if ( WIFEXITED(status
) ) 
1501             exitcode 
= WEXITSTATUS(status
); 
1502         else if ( WIFSIGNALED(status
) ) 
1503             exitcode 
= -WTERMSIG(status
); 
1506             wxLogError("Child process (PID %d) exited for unknown reason, " 
1507                        "status = %d", pid
, status
); 
1517 } // anonymous namespace 
1519 int wxAppTraits::WaitForChild(wxExecuteData
& execData
) 
1521     if ( !(execData
.flags 
& wxEXEC_SYNC
) ) 
1523         // asynchronous execution: just launch the process and return, 
1524         // endProcData will be destroyed when it terminates (currently we leak 
1525         // it if the process doesn't terminate before we do and this should be 
1526         // fixed but it's not a real leak so it's not really very high 
1528         wxEndProcessData 
*endProcData 
= new wxEndProcessData
; 
1529         endProcData
->process 
= execData
.process
; 
1530         endProcData
->pid 
= execData
.pid
; 
1531         endProcData
->tag 
= AddProcessCallback
 
1534                              execData
.GetEndProcReadFD() 
1536         endProcData
->async 
= true; 
1538         return execData
.pid
; 
1540     //else: synchronous execution case 
1542 #if HAS_PIPE_STREAMS && wxUSE_SOCKETS 
1543     wxProcess 
* const process 
= execData
.process
; 
1544     if ( process 
&& process
->IsRedirected() ) 
1546         // we can't simply block waiting for the child to terminate as we would 
1547         // dead lock if it writes more than the pipe buffer size (typically 
1548         // 4KB) bytes of output -- it would then block waiting for us to read 
1549         // the data while we'd block waiting for it to terminate 
1551         // so multiplex here waiting for any input from the child or closure of 
1552         // the pipe used to indicate its termination 
1553         wxSelectDispatcher disp
; 
1555         wxEndHandler 
endHandler(disp
, execData
.GetEndProcReadFD()); 
1557         wxRedirectedIOHandler 
outHandler(disp
, execData
.fdOut
, execData
.bufOut
), 
1558                               errHandler(disp
, execData
.fdErr
, execData
.bufErr
); 
1560         while ( !endHandler
.Terminated() ) 
1565     //else: no IO redirection, just block waiting for the child to exit 
1566 #endif // HAS_PIPE_STREAMS 
1568     return DoWaitForChild(execData
.pid
); 
1571 void wxHandleProcessTermination(wxEndProcessData 
*data
) 
1573     data
->exitcode 
= DoWaitForChild(data
->pid
, WNOHANG
); 
1575     // notify user about termination if required 
1576     if ( data
->process 
) 
1578         data
->process
->OnTerminate(data
->pid
, data
->exitcode
); 
1583         // in case of asynchronous execution we don't need this data any more 
1584         // after the child terminates 
1587     else // sync execution 
1589         // let wxExecute() know that the process has terminated