]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/utilsunx.cpp
Applied patch [ 583922 ] Make generic/wxListCtrl avail. in WIN32
[wxWidgets.git] / src / unix / utilsunx.cpp
index fbf5377f76fb6e7412f15e56ac7ab1e9a0bf1cc5..c7f527e9b29b16d55a65469dbe26a21380cbf485 100644 (file)
 #include "wx/process.h"
 #include "wx/thread.h"
 
-#include "wx/stream.h"
+#include "wx/wfstream.h"
 
 #ifdef HAVE_STATFS
-#  ifdef __DARWIN__
+#  ifdef __BSD__
 #    include <sys/param.h>
 #    include <sys/mount.h>
 #  else
 #  endif
 #endif // HAVE_STATFS
 
+// not only the statfs syscall is called differently depending on platform, but
+// we also can't use "struct statvfs" under Solaris because it breaks down if
+// HAVE_LARGEFILE_SUPPORT == 1 and we must use statvfs_t instead
+#ifdef HAVE_STATVFS
+    #include <sys/statvfs.h>
+
+    #define statfs statvfs
+    #define wxStatFs statvfs_t
+#elif HAVE_STATFS
+    #define wxStatFs struct statfs
+#endif // HAVE_STAT[V]FS
+
 #if wxUSE_GUI
     #include "wx/unix/execute.h"
 #endif
@@ -149,7 +161,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc)
     int err = kill((pid_t)pid, (int)sig);
     if ( rc )
     {
-        switch ( err )
+        switch ( errno )
         {
             case 0:
                 *rc = wxKILL_OK;
@@ -181,7 +193,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc)
 
 #define WXEXECUTE_NARGS   127
 
-long wxExecute( const wxString& command, bool sync, wxProcess *process )
+long wxExecute( const wxString& command, int flags, wxProcess *process )
 {
     wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") );
 
@@ -241,7 +253,7 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process )
     argv[argc] = NULL;
 
     // do execute the command
-    long lRc = wxExecute(argv, sync, process);
+    long lRc = wxExecute(argv, flags, process);
 
     // clean up
     argc = 0;
@@ -274,7 +286,7 @@ static wxString wxMakeShellCommand(const wxString& command)
 
 bool wxShell(const wxString& command)
 {
-    return wxExecute(wxMakeShellCommand(command), TRUE /* sync */) == 0;
+    return wxExecute(wxMakeShellCommand(command), wxEXEC_SYNC) == 0;
 }
 
 bool wxShell(const wxString& command, wxArrayString& output)
@@ -284,36 +296,39 @@ bool wxShell(const wxString& command, wxArrayString& output)
     return wxExecute(wxMakeShellCommand(command), output);
 }
 
-#if wxUSE_GUI
-
-void wxHandleProcessTermination(wxEndProcessData *proc_data)
+// Shutdown or reboot the PC
+bool wxShutdown(wxShutdownFlags wFlags)
 {
-    int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid);
+    wxChar level;
+    switch ( wFlags )
+    {
+        case wxSHUTDOWN_POWEROFF:
+            level = _T('0');
+            break;
 
-    // waitpid is POSIX so should be available everywhere, however on older
-    // systems wait() might be used instead in a loop (until the right pid
-    // terminates)
-    int status = 0;
-    int rc;
+        case wxSHUTDOWN_REBOOT:
+            level = _T('6');
+            break;
 
-    // wait for child termination and if waitpid() was interrupted, try again
-    do
-    {
-       rc = waitpid(pid, &status, 0);
+        default:
+            wxFAIL_MSG( _T("unknown wxShutdown() flag") );
+            return FALSE;
     }
-    while ( rc == -1 && errno == EINTR );
 
+    return system(wxString::Format(_T("init %c"), level).mb_str()) == 0;
+}
+
+
+#if wxUSE_GUI
+
+void wxHandleProcessTermination(wxEndProcessData *proc_data)
+{
     // notify user about termination if required
     if ( proc_data->process )
     {
-        proc_data->process->OnTerminate
-                            (
-                                proc_data->pid,
-                                (rc == 0) && WIFEXITED(status)
-                                    ? WEXITSTATUS(status)
-                                    : -1
-                            );
+        proc_data->process->OnTerminate(proc_data->pid, proc_data->exitcode);
     }
+
     // clean up
     if ( proc_data->pid > 0 )
     {
@@ -321,9 +336,7 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data)
     }
     else
     {
-       // wxExecute() will know about it
-       proc_data->exitcode = status;
-
+       // let wxExecute() know that the process has terminated
        proc_data->pid = 0;
     }
 }
@@ -336,35 +349,20 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data)
 
 #if wxUSE_STREAMS
 
-class wxProcessFileInputStream : public wxInputStream
-{
-public:
-    wxProcessFileInputStream(int fd) { m_fd = fd; }
-    ~wxProcessFileInputStream() { close(m_fd); }
-
-    virtual bool Eof() const;
-
-protected:
-    size_t OnSysRead(void *buffer, size_t bufsize);
-
-protected:
-    int m_fd;
-};
+// ----------------------------------------------------------------------------
+// wxProcessFileInputStream: stream for reading from a pipe
+// ----------------------------------------------------------------------------
 
-class wxProcessFileOutputStream : public wxOutputStream
+class wxProcessFileInputStream : public wxFileInputStream
 {
 public:
-    wxProcessFileOutputStream(int fd) { m_fd = fd; }
-    ~wxProcessFileOutputStream() { close(m_fd); }
-
-protected:
-    size_t OnSysWrite(const void *buffer, size_t bufsize);
+    wxProcessFileInputStream(int fd) : wxFileInputStream(fd) { }
 
-protected:
-    int m_fd;
+    // return TRUE if we have anything to read, don't block
+    bool IsAvailable() const;
 };
 
-bool wxProcessFileInputStream::Eof() const
+bool wxProcessFileInputStream::IsAvailable() const
 {
     if ( m_lasterror == wxSTREAM_EOF )
         return TRUE;
@@ -374,10 +372,12 @@ bool wxProcessFileInputStream::Eof() const
     tv.tv_sec = 0;
     tv.tv_usec = 0;
 
+    const int fd = m_file->fd();
+
     fd_set readfds;
     FD_ZERO(&readfds);
-    FD_SET(m_fd, &readfds);
-    switch ( select(m_fd + 1, &readfds, NULL, NULL, &tv) )
+    FD_SET(fd, &readfds);
+    switch ( select(fd + 1, &readfds, NULL, NULL, &tv) )
     {
         case -1:
             wxLogSysError(_("Impossible to get child process input"));
@@ -391,49 +391,13 @@ bool wxProcessFileInputStream::Eof() const
             // still fall through
 
         case 1:
-            // input available: check if there is any
-            return wxInputStream::Eof();
-    }
-}
-
-size_t wxProcessFileInputStream::OnSysRead(void *buffer, size_t bufsize)
-{
-    int ret = read(m_fd, buffer, bufsize);
-    if ( ret == 0 )
-    {
-        m_lasterror = wxSTREAM_EOF;
-    }
-    else if ( ret == -1 )
-    {
-        m_lasterror = wxSTREAM_READ_ERROR;
-        ret = 0;
-    }
-    else
-    {
-        m_lasterror = wxSTREAM_NOERROR;
-    }
-
-    return ret;
-}
-
-size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
-{
-    int ret = write(m_fd, buffer, bufsize);
-    if ( ret == -1 )
-    {
-        m_lasterror = wxSTREAM_WRITE_ERROR;
-        ret = 0;
-    }
-    else
-    {
-        m_lasterror = wxSTREAM_NOERROR;
+            // input available
+            return TRUE;
     }
-
-    return ret;
 }
 
 // ----------------------------------------------------------------------------
-// wxStreamTempBuffer
+// wxStreamTempInputBuffer
 // ----------------------------------------------------------------------------
 
 /*
@@ -452,34 +416,38 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
     command we set up a pipe with a valid file descriptor on the reading side
     when the output is redirected. So the subprocess happily writes to it ...
     until the pipe buffer (which is usually quite big on Unix, I think the
-    default is 4Mb) is full. Then the writing process stops and waits until we
+    default is 4Kb) is full. Then the writing process stops and waits until we
     read some data from the pipe to be able to continue writing to it but we
     never do it because we wait until it terminates to start reading and so we
     have a classical deadlock.
 
    Here is the fix: we now read the output as soon as it appears into a temp
-   buffer (wxStreamTempBuffer object) and later just stuff it back into the
+   buffer (wxStreamTempInputBuffer object) and later just stuff it back into the
    stream when the process terminates. See supporting code in wxExecute()
-   itself as well.   
+   itself as well.
+
+   Note that this is horribly inefficient for large amounts of output (count
+   the number of times we copy the data around) and so a better API is badly
+   needed!
 */
 
-class wxStreamTempBuffer
+class wxStreamTempInputBuffer
 {
 public:
-    wxStreamTempBuffer();
+    wxStreamTempInputBuffer();
 
     // call to associate a stream with this buffer, otherwise nothing happens
     // at all
-    void Init(wxInputStream *stream);
+    void Init(wxProcessFileInputStream *stream);
 
     // check for input on our stream and cache it in our buffer if any
     void Update();
 
-    ~wxStreamTempBuffer();
+    ~wxStreamTempInputBuffer();
 
 private:
     // the stream we're buffering, if NULL we don't do anything at all
-    wxInputStream *m_stream;
+    wxProcessFileInputStream *m_stream;
 
     // the buffer of size m_size (NULL if m_size == 0)
     void *m_buffer;
@@ -488,25 +456,25 @@ private:
     size_t m_size;
 };
 
-wxStreamTempBuffer::wxStreamTempBuffer()
+wxStreamTempInputBuffer::wxStreamTempInputBuffer()
 {
-    m_stream = NULL; 
+    m_stream = NULL;
     m_buffer = NULL;
     m_size = 0;
 }
 
-void wxStreamTempBuffer::Init(wxInputStream *stream)
+void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream)
 {
     m_stream = stream;
 }
 
-void wxStreamTempBuffer::Update()
+void wxStreamTempInputBuffer::Update()
 {
-    if ( m_stream && !m_stream->Eof() )
+    if ( m_stream && m_stream->IsAvailable() )
     {
-        // realloc in blocks of 1Kb - surely not the best strategy but which
-        // one is?
-        static const size_t incSize = 1024;
+        // realloc in blocks of 4Kb: this is the default (and minimal) buffer
+        // size of the Unix pipes so it should be the optimal step
+        static const size_t incSize = 4096;
 
         void *buf = realloc(m_buffer, m_size + incSize);
         if ( !buf )
@@ -518,12 +486,12 @@ void wxStreamTempBuffer::Update()
         {
             m_buffer = buf;
             m_stream->Read((char *)m_buffer + m_size, incSize);
-            m_size += incSize;
+            m_size += m_stream->LastRead();
         }
     }
 }
 
-wxStreamTempBuffer::~wxStreamTempBuffer()
+wxStreamTempInputBuffer::~wxStreamTempInputBuffer()
 {
     if ( m_buffer )
     {
@@ -534,8 +502,89 @@ wxStreamTempBuffer::~wxStreamTempBuffer()
 
 #endif // wxUSE_STREAMS
 
+// ----------------------------------------------------------------------------
+// wxPipe: this encapsulates pipe() system call
+// ----------------------------------------------------------------------------
+
+class wxPipe
+{
+public:
+    // the symbolic names for the pipe ends
+    enum Direction
+    {
+        Read,
+        Write
+    };
+
+    enum
+    {
+        INVALID_FD = -1
+    };
+
+    // default ctor doesn't do anything
+    wxPipe() { m_fds[Read] = m_fds[Write] = INVALID_FD; }
+
+    // create the pipe, return TRUE if ok, FALSE on error
+    bool Create()
+    {
+        if ( pipe(m_fds) == -1 )
+        {
+            wxLogSysError(_("Pipe creation failed"));
+
+            return FALSE;
+        }
+
+        return TRUE;
+    }
+
+    // return TRUE if we were created successfully
+    bool IsOk() const { return m_fds[Read] != INVALID_FD; }
+
+    // return the descriptor for one of the pipe ends
+    int operator[](Direction which) const
+    {
+        wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+                      _T("invalid pipe index") );
+
+        return m_fds[which];
+    }
+
+    // detach a descriptor, meaning that the pipe dtor won't close it, and
+    // return it
+    int Detach(Direction which)
+    {
+        wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+                      _T("invalid pipe index") );
+
+        int fd = m_fds[which];
+        m_fds[which] = INVALID_FD;
+
+        return fd;
+    }
+
+    // close the pipe descriptors
+    void Close()
+    {
+        for ( size_t n = 0; n < WXSIZEOF(m_fds); n++ )
+        {
+            if ( m_fds[n] != INVALID_FD )
+                close(m_fds[n]);
+        }
+    }
+
+    // dtor closes the pipe descriptors
+    ~wxPipe() { Close(); }
+
+private:
+    int m_fds[2];
+};
+
+// ----------------------------------------------------------------------------
+// wxExecute: the real worker function
+// ----------------------------------------------------------------------------
+
 long wxExecute(wxChar **argv,
-               bool sync,
+               int flags,
                wxProcess *process)
 {
     // for the sync execution, we return -1 to indicate failure, but for async
@@ -543,7 +592,7 @@ long wxExecute(wxChar **argv,
     //
     // we define this as a macro, not a variable, to avoid compiler warnings
     // about "ERROR_RETURN_CODE value may be clobbered by fork()"
-    #define ERROR_RETURN_CODE ((sync) ? -1 : 0)
+    #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0)
 
     wxCHECK_MSG( *argv, ERROR_RETURN_CODE, wxT("can't exec empty command") );
 
@@ -572,10 +621,9 @@ long wxExecute(wxChar **argv,
 
 #if wxUSE_GUI
     // create pipes
-    int end_proc_detect[2];
-    if ( pipe(end_proc_detect) == -1 )
+    wxPipe pipeEndProcDetect;
+    if ( !pipeEndProcDetect.Create() )
     {
-        wxLogSysError( _("Pipe creation failed") );
         wxLogError( _("Failed to execute '%s'\n"), *argv );
 
         ARGS_CLEANUP;
@@ -585,25 +633,14 @@ long wxExecute(wxChar **argv,
 #endif // wxUSE_GUI
 
     // pipes for inter process communication
-    int pipeIn[2],      // stdin
-        pipeOut[2],     // stdout
-        pipeErr[2];     // stderr
-
-    pipeIn[0] = pipeIn[1] =
-    pipeOut[0] = pipeOut[1] =
-    pipeErr[0] = pipeErr[1] = -1;
+    wxPipe pipeIn,      // stdin
+           pipeOut,     // stdout
+           pipeErr;     // stderr
 
     if ( process && process->IsRedirected() )
     {
-        if ( pipe(pipeIn) == -1 || pipe(pipeOut) == -1 || pipe(pipeErr) == -1 )
+        if ( !pipeIn.Create() || !pipeOut.Create() || !pipeErr.Create() )
         {
-#if wxUSE_GUI
-            // free previously allocated resources
-            close(end_proc_detect[0]);
-            close(end_proc_detect[1]);
-#endif // wxUSE_GUI
-
-            wxLogSysError( _("Pipe creation failed") );
             wxLogError( _("Failed to execute '%s'\n"), *argv );
 
             ARGS_CLEANUP;
@@ -621,17 +658,6 @@ long wxExecute(wxChar **argv,
 
     if ( pid == -1 )     // error?
     {
-#if wxUSE_GUI
-        close(end_proc_detect[0]);
-        close(end_proc_detect[1]);
-        close(pipeIn[0]);
-        close(pipeIn[1]);
-        close(pipeOut[0]);
-        close(pipeOut[1]);
-        close(pipeErr[0]);
-        close(pipeErr[1]);
-#endif // wxUSE_GUI
-
         wxLogSysError( _("Fork failed") );
 
         ARGS_CLEANUP;
@@ -640,21 +666,19 @@ long wxExecute(wxChar **argv,
     }
     else if ( pid == 0 )  // we're in child
     {
-#if wxUSE_GUI
-        close(end_proc_detect[0]); // close reading side
-#endif // wxUSE_GUI
-
         // These lines close the open file descriptors to to avoid any
         // input/output which might block the process or irritate the user. If
         // one wants proper IO for the subprocess, the right thing to do is to
         // start an xterm executing it.
-        if ( !sync )
+        if ( !(flags & wxEXEC_SYNC) )
         {
             for ( int fd = 0; fd < FD_SETSIZE; fd++ )
             {
-                if ( fd == pipeIn[0] || fd == pipeOut[1] || fd == pipeErr[1]
+                if ( fd == pipeIn[wxPipe::Read]
+                        || fd == pipeOut[wxPipe::Write]
+                        || fd == pipeErr[wxPipe::Write]
 #if wxUSE_GUI
-                     || fd == end_proc_detect[1]
+                        || fd == pipeEndProcDetect[wxPipe::Write]
 #endif // wxUSE_GUI
                    )
                 {
@@ -662,25 +686,41 @@ long wxExecute(wxChar **argv,
                     continue;
                 }
 
-                // leave stderr opened too, it won't do any hurm
+                // leave stderr opened too, it won't do any harm
                 if ( fd != STDERR_FILENO )
                     close(fd);
             }
         }
 
-        // redirect stdio, stdout and stderr
-        if ( pipeIn[0] != -1 )
+#ifndef __VMS
+        if ( flags & wxEXEC_MAKE_GROUP_LEADER )
+        {
+            // Set process group to child process' pid.  Then killing -pid
+            // of the parent will kill the process and all of its children.
+            setsid();
+        }
+#endif // !__VMS
+
+#if wxUSE_GUI
+        // reading side can be safely closed but we should keep the write one
+        // opened
+        pipeEndProcDetect.Detach(wxPipe::Write);
+        pipeEndProcDetect.Close();
+#endif // wxUSE_GUI
+
+        // redirect stdin, stdout and stderr
+        if ( pipeIn.IsOk() )
         {
-            if ( dup2(pipeIn[0], STDIN_FILENO) == -1 ||
-                 dup2(pipeOut[1], STDOUT_FILENO) == -1 ||
-                 dup2(pipeErr[1], STDERR_FILENO) == -1 )
+            if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 ||
+                 dup2(pipeOut[wxPipe::Write], STDOUT_FILENO) == -1 ||
+                 dup2(pipeErr[wxPipe::Write], STDERR_FILENO) == -1 )
             {
                 wxLogSysError(_("Failed to redirect child process input/output"));
             }
 
-            close(pipeIn[0]);
-            close(pipeOut[1]);
-            close(pipeErr[1]);
+            pipeIn.Close();
+            pipeOut.Close();
+            pipeErr.Close();
         }
 
         execvp (*mb_argv, mb_argv);
@@ -691,6 +731,9 @@ long wxExecute(wxChar **argv,
         // some compilers complain about missing return - of course, they
         // should know that exit() doesn't return but what else can we do if
         // they don't?
+        //
+        // and, sure enough, other compilers complain about unreachable code
+        // after exit() call, so we can just always have return here...
 #if defined(__VMS) || defined(__INTEL_COMPILER)
         return 0;
 #endif
@@ -699,34 +742,53 @@ long wxExecute(wxChar **argv,
     {
         ARGS_CLEANUP;
 
-        // pipe initialization: construction of the wxStreams
+        // prepare for IO redirection
+
 #if wxUSE_STREAMS
-        wxStreamTempBuffer bufIn, bufErr;
+        // the input buffer bufOut is connected to stdout, this is why it is
+        // called bufOut and not bufIn
+        wxStreamTempInputBuffer bufOut,
+                                bufErr;
 #endif // wxUSE_STREAMS
 
         if ( process && process->IsRedirected() )
         {
 #if wxUSE_STREAMS
-            // in/out for subprocess correspond to our out/in
-            wxOutputStream *outStream = new wxProcessFileOutputStream(pipeIn[1]);
-            wxInputStream *inStream = new wxProcessFileInputStream(pipeOut[0]);
-            wxInputStream *errStream = new wxProcessFileInputStream(pipeErr[0]);
+            wxOutputStream *inStream =
+                new wxFileOutputStream(pipeIn.Detach(wxPipe::Write));
+
+            wxProcessFileInputStream *outStream =
+                new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read));
+
+            wxProcessFileInputStream *errStream =
+                new wxProcessFileInputStream(pipeErr.Detach(wxPipe::Read));
 
-            process->SetPipeStreams(inStream, outStream, errStream);
+            process->SetPipeStreams(outStream, inStream, errStream);
 
-            bufIn.Init(inStream);
-            bufErr.Init(inStream);
+            bufOut.Init(outStream);
+            bufErr.Init(errStream);
 #endif // wxUSE_STREAMS
+        }
 
-            close(pipeIn[0]); // close reading side
-            close(pipeOut[1]); // close writing side
-            close(pipeErr[1]); // close writing side
+        if ( pipeIn.IsOk() )
+        {
+            pipeIn.Close();
+            pipeOut.Close();
+            pipeErr.Close();
         }
 
 #if wxUSE_GUI && !defined(__WXMICROWIN__)
         wxEndProcessData *data = new wxEndProcessData;
 
-        if ( sync )
+        data->tag = wxAddProcessCallback
+                    (
+                        data,
+                        pipeEndProcDetect.Detach(wxPipe::Read)
+                    );
+
+        pipeEndProcDetect.Close();
+
+        if ( flags & wxEXEC_SYNC )
         {
             // we may have process for capturing the program output, but it's
             // not used in wxEndProcessData in the case of sync execution
@@ -734,9 +796,6 @@ long wxExecute(wxChar **argv,
 
             // sync execution: indicate it by negating the pid
             data->pid = -pid;
-            data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
-
-            close(end_proc_detect[1]); // close writing side
 
             wxBusyCursor bc;
             wxWindowDisabler wd;
@@ -746,7 +805,7 @@ long wxExecute(wxChar **argv,
             while ( data->pid != 0 )
             {
 #if wxUSE_STREAMS
-                bufIn.Update();
+                bufOut.Update();
                 bufErr.Update();
 #endif // wxUSE_STREAMS
 
@@ -768,14 +827,13 @@ long wxExecute(wxChar **argv,
             // will be deleted in GTK_EndProcessDetector
             data->process  = process;
             data->pid      = pid;
-            data->tag      = wxAddProcessCallback(data, end_proc_detect[0]);
-
-            close(end_proc_detect[1]); // close writing side
 
             return pid;
         }
 #else // !wxUSE_GUI
-        wxASSERT_MSG( sync, wxT("async execution not supported yet") );
+
+        wxASSERT_MSG( flags & wxEXEC_SYNC,
+                      wxT("async execution not supported yet") );
 
         int exitcode = 0;
         if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) )
@@ -786,6 +844,8 @@ long wxExecute(wxChar **argv,
         return exitcode;
 #endif // wxUSE_GUI
     }
+
+    return ERROR_RETURN_CODE;
 }
 
 #undef ERROR_RETURN_CODE
@@ -964,6 +1024,7 @@ bool wxGetUserName(wxChar *buf, int sz)
     return FALSE;
 }
 
+#ifndef __WXMAC__
 wxString wxGetOsDescription()
 {
 #ifndef WXWIN_OS_DESCRIPTION
@@ -972,6 +1033,7 @@ wxString wxGetOsDescription()
     return WXWIN_OS_DESCRIPTION;
 #endif
 }
+#endif
 
 // this function returns the GUI toolkit version in GUI programs, but OS
 // version in non-GUI ones
@@ -998,6 +1060,11 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 
 #endif // !wxUSE_GUI
 
+unsigned long wxGetProcessId()
+{
+    return (unsigned long)getpid();
+}
+
 long wxGetFreeMemory()
 {
 #if defined(__LINUX__)
@@ -1029,30 +1096,38 @@ long wxGetFreeMemory()
 
 bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
 {
-#ifdef HAVE_STATFS
-
-    struct statfs fs;
-    if ( statfs(path, &fs) != 0 )
+#if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
+    // the case to "char *" is needed for AIX 4.3
+    wxStatFs fs;
+    if ( statfs((char *)path.fn_str(), &fs) != 0 )
     {
         wxLogSysError("Failed to get file system statistics");
 
         return FALSE;
     }
 
+    // under Solaris we also have to use f_frsize field instead of f_bsize
+    // which is in general a multiple of f_frsize
+#ifdef HAVE_STATVFS
+    wxLongLong blockSize = fs.f_frsize;
+#else // HAVE_STATFS
+    wxLongLong blockSize = fs.f_bsize;
+#endif // HAVE_STATVFS/HAVE_STATFS
+
     if ( pTotal )
     {
-        *pTotal = wxLongLong(fs.f_blocks) * fs.f_bsize;
+        *pTotal = wxLongLong(fs.f_blocks) * blockSize;
     }
 
     if ( pFree )
     {
-        *pFree = wxLongLong(fs.f_bavail) * fs.f_bsize;
+        *pFree = wxLongLong(fs.f_bavail) * blockSize;
     }
 
     return TRUE;
-#endif // HAVE_STATFS
-
+#else // !HAVE_STATFS && !HAVE_STATVFS
     return FALSE;
+#endif // HAVE_STATFS
 }
 
 // ----------------------------------------------------------------------------
@@ -1077,8 +1152,10 @@ bool wxGetEnv(const wxString& var, wxString *value)
 bool wxSetEnv(const wxString& variable, const wxChar *value)
 {
 #if defined(HAVE_SETENV)
-    return setenv(variable.mb_str(), value ? wxString(value).mb_str().data()
-                                           : NULL, 1 /* overwrite */) == 0;
+    return setenv(variable.mb_str(),
+                  value ? (const char *)wxString(value).mb_str()
+                        : NULL,
+                  1 /* overwrite */) == 0;
 #elif defined(HAVE_PUTENV)
     wxString s = variable;
     if ( value )
@@ -1105,7 +1182,7 @@ bool wxSetEnv(const wxString& variable, const wxChar *value)
 
 #include <signal.h>
 
-static void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
+extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
 {
     if ( wxTheApp )
     {
@@ -1174,6 +1251,8 @@ bool wxHandleFatalExceptions(bool doit)
 // error and debug output routines (deprecated, use wxLog)
 // ----------------------------------------------------------------------------
 
+#if WXWIN_COMPATIBILITY_2_2
+
 void wxDebugMsg( const char *format, ... )
 {
   va_list ap;
@@ -1200,3 +1279,5 @@ void wxFatalError( const wxString &msg, const wxString &title )
   exit(3); // the same exit code as for abort()
 }
 
+#endif // WXWIN_COMPATIBILITY_2_2
+