utilsunx.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,275 行 · 第 1/3 页

CPP
1,275
字号
    if ((who = getpwuid (getuid ())) != NULL)
    {
        // pw_gecos field in struct passwd is not standard
#ifdef HAVE_PW_GECOS
       char *comma = strchr(who->pw_gecos, ',');
       if (comma)
           *comma = '\0'; // cut off non-name comment fields
       wxStrncpy (buf, wxConvertMB2WX(who->pw_gecos), sz - 1);
#else // !HAVE_PW_GECOS
       wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1);
#endif // HAVE_PW_GECOS/!HAVE_PW_GECOS
       return true;
    }

    return false;
}

// this function is in mac/utils.cpp for wxMac
#ifndef __WXMAC__

wxString wxGetOsDescription()
{
    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__

unsigned long wxGetProcessId()
{
    return (unsigned long)getpid();
}

wxMemorySize wxGetFreeMemory()
{
#if defined(__LINUX__)
    // get it from /proc/meminfo
    FILE *fp = fopen("/proc/meminfo", "r");
    if ( fp )
    {
        long memFree = -1;

        char buf[1024];
        if ( fgets(buf, WXSIZEOF(buf), fp) && fgets(buf, WXSIZEOF(buf), fp) )
        {
            long memTotal, memUsed;
            sscanf(buf, "Mem: %ld %ld %ld", &memTotal, &memUsed, &memFree);
        }

        fclose(fp);

        return (wxMemorySize)memFree;
    }
#elif defined(__SUN__) && defined(_SC_AVPHYS_PAGES)
    return (wxMemorySize)(sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE));
//#elif defined(__FREEBSD__) -- might use sysctl() to find it out, probably
#endif

    // can't find it out
    return -1;
}

bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
{
#if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
    // the case to "char *" is needed for AIX 4.3
    wxStatfs_t fs;
    if ( wxStatfs((char *)(const char*)path.fn_str(), &fs) != 0 )
    {
        wxLogSysError( wxT("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) * blockSize;
    }

    if ( pFree )
    {
        *pFree = wxLongLong(fs.f_bavail) * blockSize;
    }

    return true;
#else // !HAVE_STATFS && !HAVE_STATVFS
    return false;
#endif // HAVE_STATFS
}

// ----------------------------------------------------------------------------
// env vars
// ----------------------------------------------------------------------------

bool wxGetEnv(const wxString& var, wxString *value)
{
    // wxGetenv is defined as getenv()
    wxChar *p = wxGetenv(var);
    if ( !p )
        return false;

    if ( value )
    {
        *value = p;
    }

    return true;
}

bool wxSetEnv(const wxString& variable, const wxChar *value)
{
#if defined(HAVE_SETENV)
    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 )
        s << _T('=') << 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);

    return putenv(buf) == 0;
#else // no way to set an env var
    return false;
#endif
}

// ----------------------------------------------------------------------------
// signal handling
// ----------------------------------------------------------------------------

#if wxUSE_ON_FATAL_EXCEPTION

#include <signal.h>

extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
{
    if ( wxTheApp )
    {
        // give the user a chance to do something special about this
        wxTheApp->OnFatalException();
    }

    abort();
}

bool wxHandleFatalExceptions(bool doit)
{
    // old sig handlers
    static bool s_savedHandlers = false;
    static struct sigaction s_handlerFPE,
                            s_handlerILL,
                            s_handlerBUS,
                            s_handlerSEGV;

    bool ok = true;
    if ( doit && !s_savedHandlers )
    {
        // install the signal handler
        struct sigaction act;

        // some systems extend it with non std fields, so zero everything
        memset(&act, 0, sizeof(act));

        act.sa_handler = wxFatalSignalHandler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;

        ok &= sigaction(SIGFPE, &act, &s_handlerFPE) == 0;
        ok &= sigaction(SIGILL, &act, &s_handlerILL) == 0;
        ok &= sigaction(SIGBUS, &act, &s_handlerBUS) == 0;
        ok &= sigaction(SIGSEGV, &act, &s_handlerSEGV) == 0;
        if ( !ok )
        {
            wxLogDebug(_T("Failed to install our signal handler."));
        }

        s_savedHandlers = true;
    }
    else if ( s_savedHandlers )
    {
        // uninstall the signal handler
        ok &= sigaction(SIGFPE, &s_handlerFPE, NULL) == 0;
        ok &= sigaction(SIGILL, &s_handlerILL, NULL) == 0;
        ok &= sigaction(SIGBUS, &s_handlerBUS, NULL) == 0;
        ok &= sigaction(SIGSEGV, &s_handlerSEGV, NULL) == 0;
        if ( !ok )
        {
            wxLogDebug(_T("Failed to uninstall our signal handler."));
        }

        s_savedHandlers = false;
    }
    //else: nothing to do

    return ok;
}

#endif // wxUSE_ON_FATAL_EXCEPTION

// ----------------------------------------------------------------------------
// error and debug output routines (deprecated, use wxLog)
// ----------------------------------------------------------------------------

#if WXWIN_COMPATIBILITY_2_2

void wxDebugMsg( const char *format, ... )
{
  va_list ap;
  va_start( ap, format );
  vfprintf( stderr, format, ap );
  fflush( stderr );
  va_end(ap);
}

void wxError( const wxString &msg, const wxString &title )
{
  wxFprintf( stderr, _("Error ") );
  if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) );
  if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) );
  wxFprintf( stderr, wxT(".\n") );
}

void wxFatalError( const wxString &msg, const wxString &title )
{
  wxFprintf( stderr, _("Error ") );
  if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) );
  if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) );
  wxFprintf( stderr, wxT(".\n") );
  exit(3); // the same exit code as for abort()
}

#endif // WXWIN_COMPATIBILITY_2_2

#endif // wxUSE_BASE

#if wxUSE_GUI

// ----------------------------------------------------------------------------
// wxExecute support
// ----------------------------------------------------------------------------

// Darwin doesn't use the same process end detection mechanisms so we don't
// need wxExecute-related helpers for it
#if !(defined(__DARWIN__) && defined(__WXMAC__))

bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& execData)
{
    return execData.pipeEndProcDetect.Create();
}

bool wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& execData, int fd)
{
    return fd == (execData.pipeEndProcDetect)[wxPipe::Write];
}

void wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& execData)
{
    execData.pipeEndProcDetect.Detach(wxPipe::Write);
    execData.pipeEndProcDetect.Close();
}

#else // !Darwin

bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& WXUNUSED(execData))
{
    return true;
}

bool
wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData),
                                          int WXUNUSED(fd))
{
    return false;
}

void
wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData))
{
    // nothing to do here, we don't use the pipe
}

#endif // !Darwin/Darwin

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 ( 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
        endProcData->process = NULL;

        // sync execution: indicate it by negating the pid
        endProcData->pid = -execData.pid;
    }
    else
    {
        // async execution, nothing special to do -- caller will be
        // notified about the process termination if process != NULL, endProcData
        // will be deleted in GTK_EndProcessDetector
        endProcData->process  = execData.process;
        endProcData->pid      = execData.pid;
    }


#if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
    endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
#else
    endProcData->tag = wxAddProcessCallback
                (
                    endProcData,
                    execData.pipeEndProcDetect.Detach(wxPipe::Read)
                );

    execData.pipeEndProcDetect.Close();
#endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))

    if ( flags & wxEXEC_SYNC )
    {
        wxBusyCursor bc;
        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();
        }

        int exitcode = endProcData->exitcode;

        delete wd;
        delete endProcData;

        return exitcode;
    }
    else // async execution
    {
        return execData.pid;
    }
}

#endif // wxUSE_GUI
#if wxUSE_BASE

void wxHandleProcessTermination(wxEndProcessData *proc_data)
{
    // notify user about termination if required
    if ( proc_data->process )
    {
        proc_data->process->OnTerminate(proc_data->pid, proc_data->exitcode);
    }

    // clean up
    if ( proc_data->pid > 0 )
    {
       delete proc_data;
    }
    else
    {
       // let wxExecute() know that the process has terminated
       proc_data->pid = 0;
    }
}

#endif // wxUSE_BASE

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?