X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec67cff1f6e63b3b27613a085f0492958e66a28e..222702b112dcc7bebe018d6f4d66fe469fefd02c:/src/unix/utilsunx.cpp diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 6cf4086cbf..4d670f4ea0 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -15,6 +15,11 @@ // headers // ---------------------------------------------------------------------------- +#include + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + #include "wx/defs.h" #include "wx/string.h" @@ -41,9 +46,24 @@ #if wxUSE_BASE -#if defined( __MWERKS__ ) && defined(__MACH__) -#define WXWIN_OS_DESCRIPTION "MacOS X" -#define HAVE_NANOSLEEP +#if defined(__MWERKS__) && defined(__MACH__) + #ifndef WXWIN_OS_DESCRIPTION + #define WXWIN_OS_DESCRIPTION "MacOS X" + #endif + #ifndef HAVE_NANOSLEEP + #define HAVE_NANOSLEEP + #endif + #ifndef HAVE_UNAME + #define HAVE_UNAME + #endif + + // our configure test believes we can use sigaction() if the function is + // available but Metrowekrs with MSL run-time does have the function but + // doesn't have sigaction struct so finally we can't use it... + #ifdef __MSL__ + #undef wxUSE_ON_FATAL_EXCEPTION + #define wxUSE_ON_FATAL_EXCEPTION 0 + #endif #endif // not only the statfs syscall is called differently depending on platform, but @@ -86,7 +106,6 @@ #include #include #include -#include #include #include #include @@ -107,9 +126,9 @@ // headers - please add your system here if it is the case for your OS. // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. #if !defined(HAVE_USLEEP) && \ - (defined(__SUN__) && !defined(__SunOs_5_6) && \ + ((defined(__SUN__) && !defined(__SunOs_5_6) && \ !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ - defined(__osf__) || defined(__EMX__) + defined(__osf__) || defined(__EMX__)) extern "C" { #ifdef __SUN__ @@ -145,12 +164,12 @@ void wxSleep(int nSecs) sleep(nSecs); } -void wxUsleep(unsigned long milliseconds) +void wxMicroSleep(unsigned long microseconds) { #if defined(HAVE_NANOSLEEP) timespec tmReq; - tmReq.tv_sec = (time_t)(milliseconds / 1000); - tmReq.tv_nsec = (milliseconds % 1000) * 1000 * 1000; + tmReq.tv_sec = (time_t)(microseconds / 1000000); + tmReq.tv_nsec = (microseconds % 1000000) * 1000; // we're not interested in remaining time nor in return value (void)nanosleep(&tmReq, (timespec *)NULL); @@ -163,25 +182,30 @@ void wxUsleep(unsigned long milliseconds) #error "usleep() cannot be used in MT programs under Solaris." #endif // Sun - usleep(milliseconds * 1000); // usleep(3) wants microseconds + usleep(microseconds); #elif defined(HAVE_SLEEP) // under BeOS sleep() takes seconds (what about other platforms, if any?) - sleep(milliseconds * 1000); + sleep(microseconds * 1000000); #else // !sleep function - #error "usleep() or nanosleep() function required for wxUsleep" + #error "usleep() or nanosleep() function required for wxMicroSleep" #endif // sleep function } +void wxMilliSleep(unsigned long milliseconds) +{ + wxMicroSleep(milliseconds*1000); +} + // ---------------------------------------------------------------------------- // process management // ---------------------------------------------------------------------------- -int wxKill(long pid, wxSignal sig, wxKillError *rc) +int wxKill(long pid, wxSignal sig, wxKillError *rc, int flags) { - int err = kill((pid_t)pid, (int)sig); + int err = kill((pid_t) (flags & wxKILL_CHILDREN) ? -pid : pid, (int)sig); if ( rc ) { - switch ( errno ) + switch ( err ? errno : 0 ) { case 0: *rc = wxKILL_OK; @@ -213,9 +237,16 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc) #define WXEXECUTE_NARGS 127 +#if defined(__DARWIN__) +long wxMacExecute(wxChar **argv, + int flags, + wxProcess *process); +#endif + long wxExecute( const wxString& command, int flags, wxProcess *process ) { - wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") ); + wxCHECK_MSG( !command.empty(), 0, wxT("can't exec empty command") ); + wxLogDebug(wxString(wxT("Launching: ")) + command); #if wxUSE_THREADS // fork() doesn't mix well with POSIX threads: on many systems the program @@ -232,7 +263,7 @@ long wxExecute( const wxString& command, int flags, wxProcess *process ) wxString argument; const wxChar *cptr = command.c_str(); wxChar quotechar = wxT('\0'); // is arg quoted? - bool escaped = FALSE; + bool escaped = false; // split the command line in arguments do @@ -251,14 +282,14 @@ long wxExecute( const wxString& command, int flags, wxProcess *process ) { if ( *cptr == wxT('\\') && ! escaped ) { - escaped = TRUE; + escaped = true; cptr++; continue; } // all other characters: argument += *cptr++; - escaped = FALSE; + escaped = false; // have we reached the end of the argument? if ( (*cptr == quotechar && ! escaped) @@ -282,8 +313,18 @@ long wxExecute( const wxString& command, int flags, wxProcess *process ) } while(*cptr); argv[argc] = NULL; + long lRc; +#if defined(__DARWIN__) + // wxMacExecute only executes app bundles. + // It returns an error code if the target is not an app bundle, thus falling + // through to the regular wxExecute for non app bundles. + lRc = wxMacExecute(argv, flags, process); + if( lRc != ((flags & wxEXEC_SYNC) ? -1 : 0)) + return lRc; +#endif + // do execute the command - long lRc = wxExecute(argv, flags, process); + lRc = wxExecute(argv, flags, process); // clean up argc = 0; @@ -321,7 +362,7 @@ bool wxShell(const wxString& command) bool wxShell(const wxString& command, wxArrayString& output) { - wxCHECK_MSG( !!command, FALSE, _T("can't exec shell non interactively") ); + wxCHECK_MSG( !command.empty(), false, _T("can't exec shell non interactively") ); return wxExecute(wxMakeShellCommand(command), output); } @@ -342,12 +383,23 @@ bool wxShutdown(wxShutdownFlags wFlags) default: wxFAIL_MSG( _T("unknown wxShutdown() flag") ); - return FALSE; + return false; } return system(wxString::Format(_T("init %c"), level).mb_str()) == 0; } +wxPowerType wxGetPowerType() +{ + // TODO + return wxPOWER_UNKNOWN; +} + +wxBatteryState wxGetBatteryState() +{ + // TODO + return wxBATTERY_UNKNOWN_STATE; +} // ---------------------------------------------------------------------------- // wxStream classes to support IO redirection in wxExecute @@ -358,7 +410,7 @@ bool wxShutdown(wxShutdownFlags wFlags) bool wxPipeInputStream::CanRead() const { if ( m_lasterror == wxSTREAM_EOF ) - return FALSE; + return false; // check if there is any input available struct timeval tv; @@ -377,7 +429,7 @@ bool wxPipeInputStream::CanRead() const // fall through case 0: - return FALSE; + return false; default: wxFAIL_MSG(_T("unexpected select() return value")); @@ -400,7 +452,7 @@ bool wxPipeInputStream::CanRead() const #ifdef __VMS #pragma message disable codeunreachable #endif - + long wxExecute(wxChar **argv, int flags, wxProcess *process) @@ -504,7 +556,9 @@ long wxExecute(wxChar **argv, // start an xterm executing it. if ( !(flags & wxEXEC_SYNC) ) { - for ( int fd = 0; fd < FD_SETSIZE; fd++ ) + // FD_SETSIZE is unsigned under BSD, signed under other platforms + // so we need a cast to avoid warnings on all platforms + for ( int fd = 0; fd < (int)FD_SETSIZE; fd++ ) { if ( fd == pipeIn[wxPipe::Read] || fd == pipeOut[wxPipe::Write] @@ -550,7 +604,7 @@ long wxExecute(wxChar **argv, } execvp (*mb_argv, mb_argv); - + fprintf(stderr, "execvp("); // CS changed ppc to ppc_ as ppc is not available under mac os CW Mach-O for ( char **ppc_ = mb_argv; *ppc_; ppc_++ ) @@ -574,6 +628,9 @@ long wxExecute(wxChar **argv, { ARGS_CLEANUP; + // save it for WaitForChild() use + execData.pid = pid; + // prepare for IO redirection #if wxUSE_STREAMS @@ -631,9 +688,9 @@ long wxExecute(wxChar **argv, const wxChar* wxGetHomeDir( wxString *home ) { - *home = wxGetUserHome( wxString() ); + *home = wxGetUserHome( wxEmptyString ); wxString tmp; - if ( home->IsEmpty() ) + if ( home->empty() ) *home = wxT("/"); #ifdef __VMS tmp = *home; @@ -692,7 +749,7 @@ char *wxGetUserHome( const wxString &user ) // private use only) static bool wxGetHostNameInternal(wxChar *buf, int sz) { - wxCHECK_MSG( buf, FALSE, wxT("NULL pointer in wxGetHostNameInternal") ); + wxCHECK_MSG( buf, false, wxT("NULL pointer in wxGetHostNameInternal") ); *buf = wxT('\0'); @@ -710,7 +767,7 @@ static bool wxGetHostNameInternal(wxChar *buf, int sz) #else // no uname, no gethostname wxFAIL_MSG(wxT("don't know host name for this machine")); - bool ok = FALSE; + bool ok = false; #endif // uname/gethostname if ( !ok ) @@ -753,7 +810,7 @@ bool wxGetFullHostName(wxChar *buf, int sz) { wxLogSysError(_("Cannot get the official hostname")); - ok = FALSE; + ok = false; } else { @@ -775,10 +832,10 @@ bool wxGetUserId(wxChar *buf, int sz) if ((who = getpwuid(getuid ())) != NULL) { wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1); - return TRUE; + return true; } - return FALSE; + return false; } bool wxGetUserName(wxChar *buf, int sz) @@ -797,10 +854,10 @@ bool wxGetUserName(wxChar *buf, int sz) #else // !HAVE_PW_GECOS wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1); #endif // HAVE_PW_GECOS/!HAVE_PW_GECOS - return TRUE; + return true; } - return FALSE; + return false; } // this function is in mac/utils.cpp for wxMac @@ -808,32 +865,30 @@ bool wxGetUserName(wxChar *buf, int sz) wxString wxGetOsDescription() { -#ifndef WXWIN_OS_DESCRIPTION - #error WXWIN_OS_DESCRIPTION should be defined in config.h by configure -#else - return wxString::FromAscii( WXWIN_OS_DESCRIPTION ); -#endif + FILE *f = popen("uname -s -r -m", "r"); + if (f) + { + char buf[256]; + size_t c = fread(buf, 1, sizeof(buf) - 1, f); + pclose(f); + // Trim newline from output. + if (c && buf[c - 1] == '\n') + --c; + buf[c] = '\0'; + return wxString::FromAscii( buf ); + } + wxFAIL_MSG( _T("uname failed") ); + return _T(""); } #endif // !__WXMAC__ -int wxGetOsVersion(int *verMaj, int *verMin) -{ - // we want this function to work even if there is no wxApp - wxConsoleAppTraits traitsConsole; - wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; - if ( ! traits ) - traits = &traitsConsole; - - return traits->GetOSVersion(verMaj, verMin); -} - unsigned long wxGetProcessId() { return (unsigned long)getpid(); } -long wxGetFreeMemory() +wxMemorySize wxGetFreeMemory() { #if defined(__LINUX__) // get it from /proc/meminfo @@ -851,10 +906,10 @@ long wxGetFreeMemory() fclose(fp); - return memFree; + return (wxMemorySize)memFree; } #elif defined(__SUN__) && defined(_SC_AVPHYS_PAGES) - return sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE); + return (wxMemorySize)(sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE)); //#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably #endif @@ -871,7 +926,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { wxLogSysError( wxT("Failed to get file system statistics") ); - return FALSE; + return false; } // under Solaris we also have to use f_frsize field instead of f_bsize @@ -892,9 +947,9 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) *pFree = wxLongLong(fs.f_bavail) * blockSize; } - return TRUE; + return true; #else // !HAVE_STATFS && !HAVE_STATVFS - return FALSE; + return false; #endif // HAVE_STATFS } @@ -907,14 +962,14 @@ bool wxGetEnv(const wxString& var, wxString *value) // wxGetenv is defined as getenv() wxChar *p = wxGetenv(var); if ( !p ) - return FALSE; + return false; if ( value ) { *value = p; } - return TRUE; + return true; } bool wxSetEnv(const wxString& variable, const wxChar *value) @@ -930,7 +985,7 @@ bool wxSetEnv(const wxString& variable, const wxChar *value) s << _T('=') << value; // transform to ANSI - const char *p = s.mb_str(); + const wxWX2MBbuf p = s.mb_str(); // the string will be free()d by libc char *buf = (char *)malloc(strlen(p) + 1); @@ -938,7 +993,7 @@ bool wxSetEnv(const wxString& variable, const wxChar *value) return putenv(buf) == 0; #else // no way to set an env var - return FALSE; + return false; #endif } @@ -964,13 +1019,13 @@ extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER) bool wxHandleFatalExceptions(bool doit) { // old sig handlers - static bool s_savedHandlers = FALSE; + static bool s_savedHandlers = false; static struct sigaction s_handlerFPE, s_handlerILL, s_handlerBUS, s_handlerSEGV; - bool ok = TRUE; + bool ok = true; if ( doit && !s_savedHandlers ) { // install the signal handler @@ -992,7 +1047,7 @@ bool wxHandleFatalExceptions(bool doit) wxLogDebug(_T("Failed to install our signal handler.")); } - s_savedHandlers = TRUE; + s_savedHandlers = true; } else if ( s_savedHandlers ) { @@ -1006,7 +1061,7 @@ bool wxHandleFatalExceptions(bool doit) wxLogDebug(_T("Failed to uninstall our signal handler.")); } - s_savedHandlers = FALSE; + s_savedHandlers = false; } //else: nothing to do @@ -1103,10 +1158,12 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) { wxEndProcessData *endProcData = new wxEndProcessData; + const int flags = execData.flags; + // wxAddProcessCallback is now (with DARWIN) allowed to call the // callback function directly if the process terminates before // the callback can be added to the run loop. Set up the endProcData. - if ( execData.flags & wxEXEC_SYNC ) + 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 @@ -1125,7 +1182,7 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) } -#if defined(__DARWIN__) && defined(__WXMAC__) +#if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__)) endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid); #else endProcData->tag = wxAddProcessCallback @@ -1135,25 +1192,39 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) ); execData.pipeEndProcDetect.Close(); -#endif // defined(__DARWIN__) && defined(__WXMAC__) +#endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__)) - if ( execData.flags & wxEXEC_SYNC ) + if ( flags & wxEXEC_SYNC ) { wxBusyCursor bc; - wxWindowDisabler wd; + wxWindowDisabler *wd = flags & wxEXEC_NODISABLE ? NULL + : new wxWindowDisabler; // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the // process terminates while ( endProcData->pid != 0 ) { + bool idle = true; + #if wxUSE_STREAMS if ( execData.bufOut ) + { execData.bufOut->Update(); + idle = false; + } if ( execData.bufErr ) + { execData.bufErr->Update(); + idle = false; + } #endif // wxUSE_STREAMS + // 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(); @@ -1161,6 +1232,7 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) int exitcode = endProcData->exitcode; + delete wd; delete endProcData; return exitcode; @@ -1171,6 +1243,9 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData) } } +#endif // wxUSE_GUI +#if wxUSE_BASE + void wxHandleProcessTermination(wxEndProcessData *proc_data) { // notify user about termination if required @@ -1191,5 +1266,4 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) } } -#endif // wxUSE_GUI - +#endif // wxUSE_BASE