1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/utilsunx.cpp 
   3 // Purpose:     generic Unix implementation of many wx functions 
   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_INPUT_STREAM (wxUSE_STREAMS && wxUSE_FILE) 
  64 #if HAS_PIPE_INPUT_STREAM 
  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_INPUT_STREAM 
  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
, (timespec 
*)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(_T("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( _T("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 // ---------------------------------------------------------------------------- 
 300 #if HAS_PIPE_INPUT_STREAM 
 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(_T("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 #endif // HAS_PIPE_INPUT_STREAM 
 342 // ---------------------------------------------------------------------------- 
 344 // ---------------------------------------------------------------------------- 
 346 static wxString 
wxMakeShellCommand(const wxString
& command
) 
 351         // just an interactive shell 
 356         // execute command in a shell 
 357         cmd 
<< _T("/bin/sh -c '") << command 
<< _T('\''); 
 363 bool wxShell(const wxString
& command
) 
 365     return wxExecute(wxMakeShellCommand(command
), wxEXEC_SYNC
) == 0; 
 368 bool wxShell(const wxString
& command
, wxArrayString
& output
) 
 370     wxCHECK_MSG( !command
.empty(), false, _T("can't exec shell non interactively") ); 
 372     return wxExecute(wxMakeShellCommand(command
), output
); 
 378 // helper class for storing arguments as char** array suitable for passing to 
 379 // execvp(), whatever form they were passed to us 
 383     ArgsArray(const wxArrayString
& args
) 
 387         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 389             m_argv
[i
] = wxStrdup(args
[i
]); 
 394     ArgsArray(wchar_t **wargv
) 
 402         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 404             m_argv
[i
] = wxSafeConvertWX2MB(wargv
[i
]).release(); 
 407 #endif // wxUSE_UNICODE 
 411         for ( int i 
= 0; i 
< m_argc
; i
++ ) 
 419     operator char**() const { return m_argv
; } 
 425         m_argv 
= new char *[m_argc 
+ 1]; 
 426         m_argv
[m_argc
] = NULL
; 
 432     DECLARE_NO_COPY_CLASS(ArgsArray
) 
 435 } // anonymous namespace 
 437 // ---------------------------------------------------------------------------- 
 438 // wxExecute implementations 
 439 // ---------------------------------------------------------------------------- 
 441 #if defined(__DARWIN__) 
 442 bool wxMacLaunch(char **argv
); 
 445 long wxExecute(const wxString
& command
, int flags
, wxProcess 
*process
) 
 447     ArgsArray 
argv(wxCmdLineParser::ConvertStringToArgs(command
, 
 448                                                         wxCMD_LINE_SPLIT_UNIX
)); 
 450     return wxExecute(argv
, flags
, process
); 
 455 long wxExecute(wchar_t **wargv
, int flags
, wxProcess 
*process
) 
 457     ArgsArray 
argv(wargv
); 
 459     return wxExecute(argv
, flags
, process
); 
 462 #endif // wxUSE_UNICODE 
 464 // wxExecute: the real worker function 
 465 long wxExecute(char **argv
, int flags
, wxProcess 
*process
) 
 467     // for the sync execution, we return -1 to indicate failure, but for async 
 468     // case we return 0 which is never a valid PID 
 470     // we define this as a macro, not a variable, to avoid compiler warnings 
 471     // about "ERROR_RETURN_CODE value may be clobbered by fork()" 
 472     #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0) 
 474     wxCHECK_MSG( *argv
, ERROR_RETURN_CODE
, wxT("can't exec empty command") ); 
 477     // fork() doesn't mix well with POSIX threads: on many systems the program 
 478     // deadlocks or crashes for some reason. Probably our code is buggy and 
 479     // doesn't do something which must be done to allow this to work, but I 
 480     // don't know what yet, so for now just warn the user (this is the least we 
 482     wxASSERT_MSG( wxThread::IsMain(), 
 483                     _T("wxExecute() can be called only from the main thread") ); 
 484 #endif // wxUSE_THREADS 
 486 #if defined(__WXCOCOA__) || ( defined(__WXOSX_MAC__) && wxOSX_USE_COCOA_OR_CARBON ) 
 487     // wxMacLaunch() only executes app bundles and only does it asynchronously. 
 488     // It returns false if the target is not an app bundle, thus falling 
 489     // through to the regular code for non app bundles. 
 490     if ( !(flags 
& wxEXEC_SYNC
) && wxMacLaunch(argv
) ) 
 492         // we don't have any PID to return so just make up something non null 
 498     // this struct contains all information which we use for housekeeping 
 499     wxExecuteData execData
; 
 500     execData
.flags 
= flags
; 
 501     execData
.process 
= process
; 
 504     if ( !execData
.pipeEndProcDetect
.Create() ) 
 506         wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 508         return ERROR_RETURN_CODE
; 
 511     // pipes for inter process communication 
 512     wxPipe pipeIn
,      // stdin 
 516     if ( process 
&& process
->IsRedirected() ) 
 518         if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() ) 
 520             wxLogError( _("Failed to execute '%s'\n"), *argv 
); 
 522             return ERROR_RETURN_CODE
; 
 528     // NB: do *not* use vfork() here, it completely breaks this code for some 
 529     //     reason under Solaris (and maybe others, although not under Linux) 
 530     //     But on OpenVMS we do not have fork so we have to use vfork and 
 531     //     cross our fingers that it works. 
 537    if ( pid 
== -1 )     // error? 
 539         wxLogSysError( _("Fork failed") ); 
 541         return ERROR_RETURN_CODE
; 
 543     else if ( pid 
== 0 )  // we're in child 
 545         // NB: we used to close all the unused descriptors of the child here 
 546         //     but this broke some programs which relied on e.g. FD 1 being 
 547         //     always opened so don't do it any more, after all there doesn't 
 548         //     seem to be any real problem with keeping them opened 
 550 #if !defined(__VMS) && !defined(__EMX__) 
 551         if ( flags 
& wxEXEC_MAKE_GROUP_LEADER 
) 
 553             // Set process group to child process' pid.  Then killing -pid 
 554             // of the parent will kill the process and all of its children. 
 559         // reading side can be safely closed but we should keep the write one 
 560         // opened, it will be only closed when the process terminates resulting 
 561         // in a read notification to the parent 
 562         execData
.pipeEndProcDetect
.Detach(wxPipe::Write
); 
 563         execData
.pipeEndProcDetect
.Close(); 
 565         // redirect stdin, stdout and stderr 
 568             if ( dup2(pipeIn
[wxPipe::Read
], STDIN_FILENO
) == -1 || 
 569                  dup2(pipeOut
[wxPipe::Write
], STDOUT_FILENO
) == -1 || 
 570                  dup2(pipeErr
[wxPipe::Write
], STDERR_FILENO
) == -1 ) 
 572                 wxLogSysError(_("Failed to redirect child process input/output")); 
 582         fprintf(stderr
, "execvp("); 
 583         for ( char **a 
= argv
; *a
; a
++ ) 
 584             fprintf(stderr
, "%s%s", a 
== argv 
? "" : ", ", *a
); 
 585         fprintf(stderr
, ") failed with error %d!\n", errno
); 
 587         // there is no return after successful exec() 
 590         // some compilers complain about missing return - of course, they 
 591         // should know that exit() doesn't return but what else can we do if 
 594         // and, sure enough, other compilers complain about unreachable code 
 595         // after exit() call, so we can just always have return here... 
 596 #if defined(__VMS) || defined(__INTEL_COMPILER) 
 600     else // we're in parent 
 602         // save it for WaitForChild() use 
 605         // prepare for IO redirection 
 607 #if HAS_PIPE_INPUT_STREAM 
 608         // the input buffer bufOut is connected to stdout, this is why it is 
 609         // called bufOut and not bufIn 
 610         wxStreamTempInputBuffer bufOut
, 
 613         if ( process 
&& process
->IsRedirected() ) 
 615             wxOutputStream 
*inStream 
= 
 616                 new wxFileOutputStream(pipeIn
.Detach(wxPipe::Write
)); 
 618             const int fdOut 
= pipeOut
.Detach(wxPipe::Read
); 
 619             wxPipeInputStream 
*outStream 
= new wxPipeInputStream(fdOut
); 
 621             const int fdErr 
= pipeErr
.Detach(wxPipe::Read
); 
 622             wxPipeInputStream 
*errStream 
= new wxPipeInputStream(fdErr
); 
 624             process
->SetPipeStreams(outStream
, inStream
, errStream
); 
 626             bufOut
.Init(outStream
); 
 627             bufErr
.Init(errStream
); 
 629             execData
.bufOut 
= &bufOut
; 
 630             execData
.bufErr 
= &bufErr
; 
 632             execData
.fdOut 
= fdOut
; 
 633             execData
.fdErr 
= fdErr
; 
 635 #endif // HAS_PIPE_INPUT_STREAM 
 644         // we want this function to work even if there is no wxApp so ensure 
 645         // that we have a valid traits pointer 
 646         wxConsoleAppTraits traitsConsole
; 
 647         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 649             traits 
= &traitsConsole
; 
 651         return traits
->WaitForChild(execData
); 
 654 #if !defined(__VMS) && !defined(__INTEL_COMPILER) 
 655     return ERROR_RETURN_CODE
; 
 659 #undef ERROR_RETURN_CODE 
 661 // ---------------------------------------------------------------------------- 
 662 // file and directory functions 
 663 // ---------------------------------------------------------------------------- 
 665 const wxChar
* wxGetHomeDir( wxString 
*home  
) 
 667     *home 
= wxGetUserHome(); 
 673     if ( tmp
.Last() != wxT(']')) 
 674         if ( tmp
.Last() != wxT('/')) *home 
<< wxT('/'); 
 676     return home
->c_str(); 
 679 wxString 
wxGetUserHome( const wxString 
&user 
) 
 681     struct passwd 
*who 
= (struct passwd 
*) NULL
; 
 687         if ((ptr 
= wxGetenv(wxT("HOME"))) != NULL
) 
 692         if ((ptr 
= wxGetenv(wxT("USER"))) != NULL 
|| 
 693              (ptr 
= wxGetenv(wxT("LOGNAME"))) != NULL
) 
 695             who 
= getpwnam(wxSafeConvertWX2MB(ptr
)); 
 698         // make sure the user exists! 
 701             who 
= getpwuid(getuid()); 
 706       who 
= getpwnam (user
.mb_str()); 
 709     return wxSafeConvertMB2WX(who 
? who
->pw_dir 
: 0); 
 712 // ---------------------------------------------------------------------------- 
 713 // network and user id routines 
 714 // ---------------------------------------------------------------------------- 
 716 // private utility function which returns output of the given command, removing 
 717 // the trailing newline 
 718 static wxString 
wxGetCommandOutput(const wxString 
&cmd
) 
 720     FILE *f 
= popen(cmd
.ToAscii(), "r"); 
 723         wxLogSysError(_T("Executing \"%s\" failed"), cmd
.c_str()); 
 724         return wxEmptyString
; 
 731         if ( !fgets(buf
, sizeof(buf
), f
) ) 
 734         s 
+= wxString::FromAscii(buf
); 
 739     if ( !s
.empty() && s
.Last() == _T('\n') ) 
 745 // retrieve either the hostname or FQDN depending on platform (caller must 
 746 // check whether it's one or the other, this is why this function is for 
 748 static bool wxGetHostNameInternal(wxChar 
*buf
, int sz
) 
 750     wxCHECK_MSG( buf
, false, wxT("NULL pointer in wxGetHostNameInternal") ); 
 754     // we're using uname() which is POSIX instead of less standard sysinfo() 
 755 #if defined(HAVE_UNAME) 
 757     bool ok 
= uname(&uts
) != -1; 
 760         wxStrlcpy(buf
, wxSafeConvertMB2WX(uts
.nodename
), sz
); 
 762 #elif defined(HAVE_GETHOSTNAME) 
 764     bool ok 
= gethostname(cbuf
, sz
) != -1; 
 767         wxStrlcpy(buf
, wxSafeConvertMB2WX(cbuf
), sz
); 
 769 #else // no uname, no gethostname 
 770     wxFAIL_MSG(wxT("don't know host name for this machine")); 
 773 #endif // uname/gethostname 
 777         wxLogSysError(_("Cannot get the hostname")); 
 783 bool wxGetHostName(wxChar 
*buf
, int sz
) 
 785     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 789         // BSD systems return the FQDN, we only want the hostname, so extract 
 790         // it (we consider that dots are domain separators) 
 791         wxChar 
*dot 
= wxStrchr(buf
, wxT('.')); 
 802 bool wxGetFullHostName(wxChar 
*buf
, int sz
) 
 804     bool ok 
= wxGetHostNameInternal(buf
, sz
); 
 808         if ( !wxStrchr(buf
, wxT('.')) ) 
 810             struct hostent 
*host 
= gethostbyname(wxSafeConvertWX2MB(buf
)); 
 813                 wxLogSysError(_("Cannot get the official hostname")); 
 819                 // the canonical name 
 820                 wxStrlcpy(buf
, wxSafeConvertMB2WX(host
->h_name
), sz
); 
 823         //else: it's already a FQDN (BSD behaves this way) 
 829 bool wxGetUserId(wxChar 
*buf
, int sz
) 
 834     if ((who 
= getpwuid(getuid ())) != NULL
) 
 836         wxStrlcpy (buf
, wxSafeConvertMB2WX(who
->pw_name
), sz
); 
 843 bool wxGetUserName(wxChar 
*buf
, int sz
) 
 849     if ((who 
= getpwuid (getuid ())) != NULL
) 
 851        char *comma 
= strchr(who
->pw_gecos
, ','); 
 853            *comma 
= '\0'; // cut off non-name comment fields 
 854        wxStrlcpy(buf
, wxSafeConvertMB2WX(who
->pw_gecos
), sz
); 
 859 #else // !HAVE_PW_GECOS 
 860     return wxGetUserId(buf
, sz
); 
 861 #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS 
 864 bool wxIsPlatform64Bit() 
 866     const wxString machine 
= wxGetCommandOutput(wxT("uname -m")); 
 868     // the test for "64" is obviously not 100% reliable but seems to work fine 
 870     return machine
.Contains(wxT("64")) || 
 871                 machine
.Contains(wxT("alpha")); 
 874 // these functions are in mac/utils.cpp for wxMac 
 877 wxOperatingSystemId 
wxGetOsVersion(int *verMaj
, int *verMin
) 
 881     wxString release 
= wxGetCommandOutput(wxT("uname -r")); 
 882     if ( release
.empty() || 
 883          wxSscanf(release
.c_str(), wxT("%d.%d"), &major
, &minor
) != 2 ) 
 885         // failed to get version string or unrecognized format 
 895     // try to understand which OS are we running 
 896     wxString kernel 
= wxGetCommandOutput(wxT("uname -s")); 
 897     if ( kernel
.empty() ) 
 898         kernel 
= wxGetCommandOutput(wxT("uname -o")); 
 900     if ( kernel
.empty() ) 
 903     return wxPlatformInfo::GetOperatingSystemId(kernel
); 
 906 wxString 
wxGetOsDescription() 
 908     return wxGetCommandOutput(wxT("uname -s -r -m")); 
 913 unsigned long wxGetProcessId() 
 915     return (unsigned long)getpid(); 
 918 wxMemorySize 
wxGetFreeMemory() 
 920 #if defined(__LINUX__) 
 921     // get it from /proc/meminfo 
 922     FILE *fp 
= fopen("/proc/meminfo", "r"); 
 928         if ( fgets(buf
, WXSIZEOF(buf
), fp
) && fgets(buf
, WXSIZEOF(buf
), fp
) ) 
 930             // /proc/meminfo changed its format in kernel 2.6 
 931             if ( wxPlatformInfo().CheckOSVersion(2, 6) ) 
 933                 unsigned long cached
, buffers
; 
 934                 sscanf(buf
, "MemFree: %ld", &memFree
); 
 936                 fgets(buf
, WXSIZEOF(buf
), fp
); 
 937                 sscanf(buf
, "Buffers: %lu", &buffers
); 
 939                 fgets(buf
, WXSIZEOF(buf
), fp
); 
 940                 sscanf(buf
, "Cached: %lu", &cached
); 
 942                 // add to "MemFree" also the "Buffers" and "Cached" values as 
 943                 // free(1) does as otherwise the value never makes sense: for 
 944                 // kernel 2.6 it's always almost 0 
 945                 memFree 
+= buffers 
+ cached
; 
 947                 // values here are always expressed in kB and we want bytes 
 950             else // Linux 2.4 (or < 2.6, anyhow) 
 952                 long memTotal
, memUsed
; 
 953                 sscanf(buf
, "Mem: %ld %ld %ld", &memTotal
, &memUsed
, &memFree
); 
 959         return (wxMemorySize
)memFree
; 
 961 #elif defined(__SGI__) 
 962     struct rminfo realmem
; 
 963     if ( sysmp(MP_SAGET
, MPSA_RMINFO
, &realmem
, sizeof realmem
) == 0 ) 
 964         return ((wxMemorySize
)realmem
.physmem 
* sysconf(_SC_PAGESIZE
)); 
 965 #elif defined(_SC_AVPHYS_PAGES) 
 966     return ((wxMemorySize
)sysconf(_SC_AVPHYS_PAGES
))*sysconf(_SC_PAGESIZE
); 
 967 //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably 
 974 bool wxGetDiskSpace(const wxString
& path
, wxDiskspaceSize_t 
*pTotal
, wxDiskspaceSize_t 
*pFree
) 
 976 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS) 
 977     // the case to "char *" is needed for AIX 4.3 
 979     if ( wxStatfs((char *)(const char*)path
.fn_str(), &fs
) != 0 ) 
 981         wxLogSysError( wxT("Failed to get file system statistics") ); 
 986     // under Solaris we also have to use f_frsize field instead of f_bsize 
 987     // which is in general a multiple of f_frsize 
 989     wxDiskspaceSize_t blockSize 
= fs
.f_frsize
; 
 991     wxDiskspaceSize_t blockSize 
= fs
.f_bsize
; 
 992 #endif // HAVE_STATVFS/HAVE_STATFS 
 996         *pTotal 
= wxDiskspaceSize_t(fs
.f_blocks
) * blockSize
; 
1001         *pFree 
= wxDiskspaceSize_t(fs
.f_bavail
) * blockSize
; 
1005 #else // !HAVE_STATFS && !HAVE_STATVFS 
1007 #endif // HAVE_STATFS 
1010 // ---------------------------------------------------------------------------- 
1012 // ---------------------------------------------------------------------------- 
1016 WX_DECLARE_STRING_HASH_MAP(char *, wxEnvVars
); 
1018 static wxEnvVars gs_envVars
; 
1020 class wxSetEnvModule 
: public wxModule
 
1023     virtual bool OnInit() { return true; } 
1024     virtual void OnExit() 
1026         for ( wxEnvVars::const_iterator i 
= gs_envVars
.begin(); 
1027               i 
!= gs_envVars
.end(); 
1036     DECLARE_DYNAMIC_CLASS(wxSetEnvModule
) 
1039 IMPLEMENT_DYNAMIC_CLASS(wxSetEnvModule
, wxModule
) 
1041 #endif // USE_PUTENV 
1043 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
1045     // wxGetenv is defined as getenv() 
1046     char *p 
= wxGetenv(var
); 
1058 static bool wxDoSetEnv(const wxString
& variable
, const char *value
) 
1060 #if defined(HAVE_SETENV) 
1063 #ifdef HAVE_UNSETENV 
1064         // don't test unsetenv() return value: it's void on some systems (at 
1066         unsetenv(variable
.mb_str()); 
1069         value 
= ""; // we can't pass NULL to setenv() 
1073     return setenv(variable
.mb_str(), value
, 1 /* overwrite */) == 0; 
1074 #elif defined(HAVE_PUTENV) 
1075     wxString s 
= variable
; 
1077         s 
<< _T('=') << value
; 
1079     // transform to ANSI 
1080     const wxWX2MBbuf p 
= s
.mb_str(); 
1082     char *buf 
= (char *)malloc(strlen(p
) + 1); 
1085     // store the string to free() it later 
1086     wxEnvVars::iterator i 
= gs_envVars
.find(variable
); 
1087     if ( i 
!= gs_envVars
.end() ) 
1092     else // this variable hadn't been set before 
1094         gs_envVars
[variable
] = buf
; 
1097     return putenv(buf
) == 0; 
1098 #else // no way to set an env var 
1103 bool wxSetEnv(const wxString
& variable
, const wxString
& value
) 
1105     return wxDoSetEnv(variable
, value
.mb_str()); 
1108 bool wxUnsetEnv(const wxString
& variable
) 
1110     return wxDoSetEnv(variable
, NULL
); 
1113 // ---------------------------------------------------------------------------- 
1115 // ---------------------------------------------------------------------------- 
1117 #if wxUSE_ON_FATAL_EXCEPTION 
1121 extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER
) 
1125         // give the user a chance to do something special about this 
1126         wxTheApp
->OnFatalException(); 
1132 bool wxHandleFatalExceptions(bool doit
) 
1135     static bool s_savedHandlers 
= false; 
1136     static struct sigaction s_handlerFPE
, 
1142     if ( doit 
&& !s_savedHandlers 
) 
1144         // install the signal handler 
1145         struct sigaction act
; 
1147         // some systems extend it with non std fields, so zero everything 
1148         memset(&act
, 0, sizeof(act
)); 
1150         act
.sa_handler 
= wxFatalSignalHandler
; 
1151         sigemptyset(&act
.sa_mask
); 
1154         ok 
&= sigaction(SIGFPE
, &act
, &s_handlerFPE
) == 0; 
1155         ok 
&= sigaction(SIGILL
, &act
, &s_handlerILL
) == 0; 
1156         ok 
&= sigaction(SIGBUS
, &act
, &s_handlerBUS
) == 0; 
1157         ok 
&= sigaction(SIGSEGV
, &act
, &s_handlerSEGV
) == 0; 
1160             wxLogDebug(_T("Failed to install our signal handler.")); 
1163         s_savedHandlers 
= true; 
1165     else if ( s_savedHandlers 
) 
1167         // uninstall the signal handler 
1168         ok 
&= sigaction(SIGFPE
, &s_handlerFPE
, NULL
) == 0; 
1169         ok 
&= sigaction(SIGILL
, &s_handlerILL
, NULL
) == 0; 
1170         ok 
&= sigaction(SIGBUS
, &s_handlerBUS
, NULL
) == 0; 
1171         ok 
&= sigaction(SIGSEGV
, &s_handlerSEGV
, NULL
) == 0; 
1174             wxLogDebug(_T("Failed to uninstall our signal handler.")); 
1177         s_savedHandlers 
= false; 
1179     //else: nothing to do 
1184 #endif // wxUSE_ON_FATAL_EXCEPTION 
1186 // ---------------------------------------------------------------------------- 
1187 // wxExecute support 
1188 // ---------------------------------------------------------------------------- 
1190 int wxAppTraits::AddProcessCallback(wxEndProcessData 
*data
, int fd
) 
1192     // define a custom handler processing only the closure of the descriptor 
1193     struct wxEndProcessFDIOHandler 
: public wxFDIOHandler
 
1195         wxEndProcessFDIOHandler(wxEndProcessData 
*data
, int fd
) 
1196             : m_data(data
), m_fd(fd
) 
1200         virtual void OnReadWaiting() 
1202             wxFDIODispatcher::Get()->UnregisterFD(m_fd
); 
1205             wxHandleProcessTermination(m_data
); 
1210         virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1211         virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1213         wxEndProcessData 
* const m_data
; 
1217     wxFDIODispatcher::Get()->RegisterFD
 
1220                                  new wxEndProcessFDIOHandler(data
, fd
), 
1223     return fd
; // unused, but return something unique for the tag 
1226 bool wxAppTraits::CheckForRedirectedIO(wxExecuteData
& execData
) 
1228 #if HAS_PIPE_INPUT_STREAM 
1231     if ( execData
.bufOut 
&& execData
.bufOut
->Update() ) 
1234     if ( execData
.bufErr 
&& execData
.bufErr
->Update() ) 
1238 #else // !HAS_PIPE_INPUT_STREAM 
1240 #endif // HAS_PIPE_INPUT_STREAM/!HAS_PIPE_INPUT_STREAM 
1243 // helper classes/functions used by WaitForChild() 
1247 // convenient base class for IO handlers which are registered for read 
1248 // notifications only and which also stores the FD we're reading from 
1250 // the derived classes still have to implement OnReadWaiting() 
1251 class wxReadFDIOHandler 
: public wxFDIOHandler
 
1254     wxReadFDIOHandler(wxFDIODispatcher
& disp
, int fd
) : m_fd(fd
) 
1257             disp
.RegisterFD(fd
, this, wxFDIO_INPUT
); 
1260     virtual void OnWriteWaiting() { wxFAIL_MSG("unreachable"); } 
1261     virtual void OnExceptionWaiting() { wxFAIL_MSG("unreachable"); } 
1266     DECLARE_NO_COPY_CLASS(wxReadFDIOHandler
) 
1269 // class for monitoring our end of the process detection pipe, simply sets a 
1270 // flag when input on the pipe (which must be due to EOF) is detected 
1271 class wxEndHandler 
: public wxReadFDIOHandler
 
1274     wxEndHandler(wxFDIODispatcher
& disp
, int fd
) 
1275         : wxReadFDIOHandler(disp
, fd
) 
1277         m_terminated 
= false; 
1280     bool Terminated() const { return m_terminated
; } 
1282     virtual void OnReadWaiting() { m_terminated 
= true; } 
1287     DECLARE_NO_COPY_CLASS(wxEndHandler
) 
1290 #if HAS_PIPE_INPUT_STREAM 
1292 // class for monitoring our ends of child stdout/err, should be constructed 
1293 // with the FD and stream from wxExecuteData and will do nothing if they're 
1296 // unlike wxEndHandler this class registers itself with the provided dispatcher 
1297 class wxRedirectedIOHandler 
: public wxReadFDIOHandler
 
1300     wxRedirectedIOHandler(wxFDIODispatcher
& disp
, 
1302                           wxStreamTempInputBuffer 
*buf
) 
1303         : wxReadFDIOHandler(disp
, fd
), 
1308     virtual void OnReadWaiting() 
1314     wxStreamTempInputBuffer 
* const m_buf
; 
1316     DECLARE_NO_COPY_CLASS(wxRedirectedIOHandler
) 
1319 #endif // HAS_PIPE_INPUT_STREAM 
1321 // helper function which calls waitpid() and analyzes the result 
1322 int DoWaitForChild(int pid
, int flags 
= 0) 
1324     wxASSERT_MSG( pid 
> 0, "invalid PID" ); 
1328     // loop while we're getting EINTR 
1331         rc 
= waitpid(pid
, &status
, flags
); 
1333         if ( rc 
!= -1 || errno 
!= EINTR 
) 
1339         // This can only happen if the child application closes our dummy pipe 
1340         // that is used to monitor its lifetime; in that case, our best bet is 
1341         // to pretend the process did terminate, because otherwise wxExecute() 
1342         // would hang indefinitely (OnReadWaiting() won't be called again, the 
1343         // descriptor is closed now). 
1344         wxLogDebug("Child process (PID %d) still alive but pipe closed so " 
1345                    "generating a close notification", pid
); 
1347     else if ( rc 
== -1 ) 
1349         wxLogLastError(wxString::Format("waitpid(%d)", pid
)); 
1351     else // child did terminate 
1353         wxASSERT_MSG( rc 
== pid
, "unexpected waitpid() return value" ); 
1355         if ( WIFEXITED(status
) ) 
1356             return WEXITSTATUS(status
); 
1357         else if ( WIFSIGNALED(status
) ) 
1358             return -WTERMSIG(status
); 
1361             wxLogError("Child process (PID %d) exited for unknown reason, " 
1362                        "status = %d", pid
, status
); 
1369 } // anonymous namespace 
1371 int wxAppTraits::WaitForChild(wxExecuteData
& execData
) 
1373     if ( !(execData
.flags 
& wxEXEC_SYNC
) ) 
1375         // asynchronous execution: just launch the process and return, 
1376         // endProcData will be destroyed when it terminates (currently we leak 
1377         // it if the process doesn't terminate before we do and this should be 
1378         // fixed but it's not a real leak so it's not really very high 
1380         wxEndProcessData 
*endProcData 
= new wxEndProcessData
; 
1381         endProcData
->process 
= execData
.process
; 
1382         endProcData
->pid 
= execData
.pid
; 
1383         endProcData
->tag 
= AddProcessCallback
 
1386                              execData
.GetEndProcReadFD() 
1388         endProcData
->async 
= true; 
1390         return execData
.pid
; 
1392     //else: synchronous execution case 
1394 #if HAS_PIPE_INPUT_STREAM 
1395     wxProcess 
* const process 
= execData
.process
; 
1396     if ( process 
&& process
->IsRedirected() ) 
1398         // we can't simply block waiting for the child to terminate as we would 
1399         // dead lock if it writes more than the pipe buffer size (typically 
1400         // 4KB) bytes of output -- it would then block waiting for us to read 
1401         // the data while we'd block waiting for it to terminate 
1403         // so multiplex here waiting for any input from the child or closure of 
1404         // the pipe used to indicate its termination 
1405         wxSelectDispatcher disp
; 
1407         wxEndHandler 
endHandler(disp
, execData
.GetEndProcReadFD()); 
1409         wxRedirectedIOHandler 
outHandler(disp
, execData
.fdOut
, execData
.bufOut
), 
1410                               errHandler(disp
, execData
.fdErr
, execData
.bufErr
); 
1412         while ( !endHandler
.Terminated() ) 
1417     //else: no IO redirection, just block waiting for the child to exit 
1418 #endif // HAS_PIPE_INPUT_STREAM 
1420     return DoWaitForChild(execData
.pid
); 
1423 void wxHandleProcessTermination(wxEndProcessData 
*data
) 
1425     data
->exitcode 
= DoWaitForChild(data
->pid
, WNOHANG
); 
1427     // notify user about termination if required 
1428     if ( data
->process 
) 
1430         data
->process
->OnTerminate(data
->pid
, data
->exitcode
); 
1435         // in case of asynchronous execution we don't need this data any more 
1436         // after the child terminates 
1439     else // sync execution 
1441         // let wxExecute() know that the process has terminated