#include "wx/utils.h"
+#define USE_PUTENV (!defined(HAVE_SETENV) && defined(HAVE_PUTENV))
+
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/app.h"
+ #include "wx/wxcrtvararg.h"
+ #if USE_PUTENV
+ #include "wx/module.h"
+ #include "wx/hashmap.h"
+ #endif
#endif
#include "wx/apptrait.h"
#include "wx/unix/private.h"
#include <pwd.h>
+#include <sys/wait.h> // waitpid()
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
bool wxIsPlatform64Bit()
{
- wxString machine = wxGetCommandOutput(wxT("uname -m"));
-
- // NOTE: these tests are not 100% reliable!
- return machine.Contains(wxT("AMD64")) ||
- machine.Contains(wxT("IA64")) ||
- machine.Contains(wxT("x64")) ||
- machine.Contains(wxT("X64")) ||
- machine.Contains(wxT("alpha")) ||
- machine.Contains(wxT("hppa64")) ||
- machine.Contains(wxT("ppc64"));
+ const wxString machine = wxGetCommandOutput(wxT("uname -m"));
+
+ // the test for "64" is obviously not 100% reliable but seems to work fine
+ // in practice
+ return machine.Contains(wxT("64")) ||
+ machine.Contains(wxT("alpha"));
}
// these functions are in mac/utils.cpp for wxMac
// get OS version
int major, minor;
wxString release = wxGetCommandOutput(wxT("uname -r"));
- if ( !release.empty() && wxSscanf(release, wxT("%d.%d"), &major, &minor) != 2 )
+ if ( release.empty() ||
+ wxSscanf(release.c_str(), wxT("%d.%d"), &major, &minor) != 2 )
{
- // unrecognized uname string format
+ // failed to get version string or unrecognized format
major =
minor = -1;
}
// env vars
// ----------------------------------------------------------------------------
+#if USE_PUTENV
+
+WX_DECLARE_STRING_HASH_MAP(char *, wxEnvVars);
+
+static wxEnvVars gs_envVars;
+
+class wxSetEnvModule : public wxModule
+{
+public:
+ virtual bool OnInit() { return true; }
+ virtual void OnExit()
+ {
+ for ( wxEnvVars::const_iterator i = gs_envVars.begin();
+ i != gs_envVars.end();
+ ++i )
+ {
+ free(i->second);
+ }
+
+ gs_envVars.clear();
+ }
+
+ DECLARE_DYNAMIC_CLASS(wxSetEnvModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxSetEnvModule, wxModule)
+
+#endif // USE_PUTENV
+
bool wxGetEnv(const wxString& var, wxString *value)
{
// wxGetenv is defined as getenv()
- wxChar *p = wxGetenv(var);
+ char *p = wxGetenv(var);
if ( !p )
return false;
return true;
}
-bool wxSetEnv(const wxString& variable, const wxChar *value)
+static bool wxDoSetEnv(const wxString& variable, const char *value)
{
#if defined(HAVE_SETENV)
- return setenv(variable.mb_str(),
- value ? (const char *)wxString(value).mb_str()
- : NULL,
- 1 /* overwrite */) == 0;
+ if ( !value )
+ {
+#ifdef HAVE_UNSETENV
+ // don't test unsetenv() return value: it's void on some systems (at
+ // least Darwin)
+ unsetenv(variable.mb_str());
+ return true;
+#else
+ value = ""; // we can't pass NULL to setenv()
+#endif
+ }
+
+ return setenv(variable.mb_str(), value, 1 /* overwrite */) == 0;
#elif defined(HAVE_PUTENV)
wxString s = variable;
if ( value )
// transform to ANSI
const wxWX2MBbuf p = s.mb_str();
- // the string will be free()d by libc
char *buf = (char *)malloc(strlen(p) + 1);
strcpy(buf, p);
+ // store the string to free() it later
+ wxEnvVars::iterator i = gs_envVars.find(variable);
+ if ( i != gs_envVars.end() )
+ {
+ free(i->second);
+ i->second = buf;
+ }
+ else // this variable hadn't been set before
+ {
+ gs_envVars[variable] = buf;
+ }
+
return putenv(buf) == 0;
#else // no way to set an env var
return false;
#endif
}
+bool wxSetEnv(const wxString& variable, const wxString& value)
+{
+ return wxDoSetEnv(variable, value.mb_str());
+}
+
+bool wxUnsetEnv(const wxString& variable)
+{
+ return wxDoSetEnv(variable, NULL);
+}
+
// ----------------------------------------------------------------------------
// signal handling
// ----------------------------------------------------------------------------
}
+ if ( !(flags & wxEXEC_NOEVENTS) )
+ {
#if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
- endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
+ endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
#else
- endProcData->tag = wxAddProcessCallback
- (
- endProcData,
- execData.pipeEndProcDetect.Detach(wxPipe::Read)
- );
+ endProcData->tag = wxAddProcessCallback
+ (
+ endProcData,
+ execData.pipeEndProcDetect.Detach(wxPipe::Read)
+ );
- execData.pipeEndProcDetect.Close();
+ execData.pipeEndProcDetect.Close();
#endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
+ }
if ( flags & wxEXEC_SYNC )
{
wxBusyCursor bc;
- wxWindowDisabler *wd = flags & wxEXEC_NODISABLE ? NULL
- : new wxWindowDisabler;
+ int exitcode = 0;
- // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
- // process terminates
- while ( endProcData->pid != 0 )
+ wxWindowDisabler *wd = flags & (wxEXEC_NODISABLE | wxEXEC_NOEVENTS)
+ ? NULL
+ : new wxWindowDisabler;
+
+ if ( flags & wxEXEC_NOEVENTS )
{
- bool idle = true;
+ // just block waiting for the child to exit
+ int status = 0;
-#if HAS_PIPE_INPUT_STREAM
- if ( execData.bufOut )
+ int result = waitpid(execData.pid, &status, 0);
+
+ if ( result == -1 )
{
- execData.bufOut->Update();
- idle = false;
+ wxLogLastError(_T("waitpid"));
+ exitcode = -1;
}
-
- if ( execData.bufErr )
+ else
{
- execData.bufErr->Update();
- idle = false;
+ wxASSERT_MSG( result == execData.pid,
+ _T("unexpected waitpid() return value") );
+
+ if ( WIFEXITED(status) )
+ {
+ exitcode = WEXITSTATUS(status);
+ }
+ else // abnormal termination?
+ {
+ wxASSERT_MSG( WIFSIGNALED(status),
+ _T("unexpected child wait status") );
+ exitcode = -1;
+ }
}
+ }
+ else // !wxEXEC_NOEVENTS
+ {
+ // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
+ // process terminates
+ while ( endProcData->pid != 0 )
+ {
+ bool idle = true;
+
+#if HAS_PIPE_INPUT_STREAM
+ if ( execData.bufOut )
+ {
+ execData.bufOut->Update();
+ idle = false;
+ }
+
+ if ( execData.bufErr )
+ {
+ execData.bufErr->Update();
+ idle = false;
+ }
#endif // HAS_PIPE_INPUT_STREAM
- // don't consume 100% of the CPU while we're sitting in this
- // loop
- if ( idle )
- wxMilliSleep(1);
+ // don't consume 100% of the CPU while we're sitting in this
+ // loop
+ if ( idle )
+ wxMilliSleep(1);
- // give GTK+ a chance to call GTK_EndProcessDetector here and
- // also repaint the GUI
- wxYield();
- }
+ // give GTK+ a chance to call GTK_EndProcessDetector here and
+ // also repaint the GUI
+ wxYield();
+ }
- int exitcode = endProcData->exitcode;
+ exitcode = endProcData->exitcode;
+ }
delete wd;
delete endProcData;