/**
       Find out operating system name and version

       This method caches system information in m_osName, m_osVersion and m_osAlias.
       It requires m_unameInfo to be set prior to call. 

    */
    void SCXOSTypeInfo::Init()  // private
    {
        m_osVersion = L"";
        m_osName = L"Unknown";

        assert(m_unameIsValid);

#if defined(hpux) || defined(sun)

        if (m_unameIsValid)
        {
            m_osName = StrFromMultibyte(m_unameInfo.sysname);
            m_osVersion = StrFromMultibyte(m_unameInfo.release);
        }

#if defined(hpux)
        m_osAlias = L"HPUX";
#elif defined(sun)
        m_osAlias = L"Solaris";
#endif

#elif defined(aix)

        if (m_unameIsValid)
        {
            m_osName = StrFromMultibyte(m_unameInfo.sysname);

            // To get "5.3" we must read "5" and "3" from different fields.
            string ver(m_unameInfo.version);
            ver.append(".");
            ver.append(m_unameInfo.release);
            m_osVersion = StrFromMultibyte(ver);
        }
        m_osAlias = L"AIX";

#elif defined(linux)

        vector<wstring> lines;
        SCXStream::NLFs nlfs;

#if defined(PF_DISTRO_SUSE)

        static const string relFileName = "/etc/SuSE-release";
        wifstream relfile(relFileName.c_str());
        wstring version(L"");
        wstring patchlevel(L"");

        SCXStream::ReadAllLines(relfile, lines, nlfs);

        if (!lines.empty()) {
            m_osName = ExtractOSName(lines[0]);
        }

        // Set the Linux Caption (get first line of the /etc/SuSE-release file)
        m_linuxDistroCaption = lines[0];
        if (0 == m_linuxDistroCaption.length())
        {
            // Fallback - should not normally happen
            m_linuxDistroCaption = L"SuSE";
        }

        // File contains one or more lines looking like this:
        // SUSE Linux Enterprise Server 10 (i586)
        // VERSION = 10
        // PATCHLEVEL = 1
        for (size_t i = 0; i<lines.size(); i++)
        {
            if (StrIsPrefix(StrTrim(lines[i]), L"VERSION", true))
            {
                wstring::size_type n = lines[i].find_first_of(L"=");
                if (n != wstring::npos)
                {
                    version = StrTrim(lines[i].substr(n+1));
                }
            }
            else if (StrIsPrefix(StrTrim(lines[i]), L"PATCHLEVEL", true))
            {
                wstring::size_type n = lines[i].find_first_of(L"=");
                if (n != wstring::npos)
                {
                    patchlevel = StrTrim(lines[i].substr(n+1));
                }
            }
        }

        if (version.length() > 0)
        {
            m_osVersion = version;

            if (patchlevel.length() > 0)
            {
                m_osVersion = version.append(L".").append(patchlevel);
            }
        }
        
        if (std::wstring::npos != m_osName.find(L"Desktop"))
        { 
            m_osAlias = L"SLED";
        }
        else
        { // Assume server.
            m_osAlias = L"SLES";
        }
#elif defined(PF_DISTRO_REDHAT)

        static const string relFileName = "/etc/redhat-release";
        wifstream relfile(relFileName.c_str());

        SCXStream::ReadAllLines(relfile, lines, nlfs);

        if (!lines.empty()) {
            m_osName = ExtractOSName(lines[0]);
        }

        // Set the Linux Caption (get first line of the /etc/redhat-release file)
        m_linuxDistroCaption = lines[0];
        if (0 == m_linuxDistroCaption.length())
        {
            // Fallback - should not normally happen
            m_linuxDistroCaption = L"Red Hat";
        }

        // File should contain one line that looks like this:
        // Red Hat Enterprise Linux Server release 5.1 (Tikanga)
        if (lines.size() > 0)
        {
            wstring::size_type n = lines[0].find_first_of(L"0123456789");
            if (n != wstring::npos)
            {
                wstring::size_type n2 = lines[0].substr(n).find_first_of(L" \t\n\t");
                m_osVersion = StrTrim(lines[0].substr(n,n2));
            }
        }
        
        if ((std::wstring::npos != m_osName.find(L"Client")) // RHED5
            || (std::wstring::npos != m_osName.find(L"Desktop"))) // RHED4
        { 
            m_osAlias = L"RHED";
        }
        else
        { // Assume server.
            m_osAlias = L"RHEL";
        }
#elif defined(PF_DISTRO_UBUNTU)

        static const string relFileName = "/etc/lsb-release";
        wifstream relfile(relFileName.c_str());
        wstring version(L"");
        wstring patchlevel(L"");

        SCXStream::ReadAllLines(relfile, lines, nlfs);

        // File contains one or more lines looking like this:
        // DISTRIB_ID=Ubuntu
        // DISTRIB_RELEASE=6.06
        // DISTRIB_CODENAME=dapper
        // DISTRIB_DESCRIPTION="Ubuntu 6.06.2 LTS"

        for (size_t i = 0; i<lines.size(); i++)
        {
            if (StrIsPrefix(StrTrim(lines[i]), L"DISTRIB_DESCRIPTION", true))
            {
                wstring::size_type n = lines[i].find_first_of(L"\"");
                if (n != wstring::npos)
                {
                    // Strip the quote (") characters ...
                    m_osName = StrTrim(lines[i].substr(n+1));
                    m_osName = m_osName.erase(m_osName.length()-1);
                    // This is an alias on Ubuntu (and not used for SCX_STACK_ONLY)
                    m_linuxDistroCaption = m_osName;
                }
            }
        }

        if (! m_osName.empty())
        {
            wstring::size_type n = m_osName.find_first_of(L"0123456789");
            if (n != wstring::npos)
            {
                wstring::size_type n2 = m_osName.substr(n).find_first_of(L" \t\n\t");
                m_osVersion = StrTrim(m_osName.substr(n,n2));
            }

            m_osName = ExtractOSName(m_osName);
        }
        m_osAlias = L"Ubuntu";

#else
#error "Linux Platform not supported"
#endif

#elif defined(macos)
        m_osAlias = L"MacOS";

        if (m_unameIsValid)
        {
            // MacOS is called "Darwin" in uname info, so we hard-code here
            m_osName = L"Mac OS";

            // This value we could read dynamically from the xml file
            // /System/Library/CoreServices/SystemVersion.plist, but that
            // file may be named differently based on client/server, and
            // reading the plist file would require framework stuff.
            //
            // Rather than using the plist, we'll use Gestalt, which is an
            // API designed to figure out versions of anything and everything.
            // Note that use of Gestalt requires the use of framework stuff
            // as well, so the Makefiles for MacOS are modified for that.

            SInt32 major, minor, bugfix;
            if (0 != Gestalt(gestaltSystemVersionMajor, &major)
                || 0 != Gestalt(gestaltSystemVersionMinor, &minor)
                || 0 != Gestalt(gestaltSystemVersionBugFix, &bugfix))
            {
                throw SCXCoreLib::SCXErrnoException(L"Gestalt", errno, SCXSRCLOCATION);
            }

            wostringstream sout;
            sout << major << L"." << minor << L"." << bugfix;
            m_osVersion = sout.str();
        }
#else
#error "Platform not supported"
#endif

    }
Exemple #2
0
/**
   Find out operating system name and version

   This method caches system information in m_osName, m_osVersion and m_osAlias.
   It requires m_unameInfo to be set prior to call.

*/
void SCXOSTypeInfo::Init()  // private
{
    m_osVersion = L"";
    m_osName = L"Unknown";

    assert(m_unameIsValid);

#if defined(hpux) || defined(sun)

    if (m_unameIsValid)
    {
        m_osName = StrFromUTF8(m_unameInfo.sysname);
        m_osVersion = StrFromUTF8(m_unameInfo.release);
    }
#if defined(hpux)
    m_osAlias = L"HPUX";
    m_osManufacturer = L"Hewlett-Packard Company";
#elif defined(sun)
    m_osAlias = L"Solaris";
    m_osManufacturer = L"Oracle Corporation";
#endif
#elif defined(aix)

    if (m_unameIsValid)
    {
        m_osName = StrFromUTF8(m_unameInfo.sysname);

        // To get "5.3" we must read "5" and "3" from different fields.
        string ver(m_unameInfo.version);
        ver.append(".");
        ver.append(m_unameInfo.release);
        m_osVersion = StrFromUTF8(ver);
    }
    m_osAlias = L"AIX";
    m_osManufacturer = L"International Business Machines Corporation";
#elif defined(linux)
    vector<wstring> lines;
    SCXStream::NLFs nlfs;
#if defined(PF_DISTRO_SUSE)
    static const string relFileName = "/etc/SuSE-release";
    wifstream relfile(relFileName.c_str());
    wstring version(L"");
    wstring patchlevel(L"");

    SCXStream::ReadAllLines(relfile, lines, nlfs);

    if (!lines.empty()) {
        m_osName = ExtractOSName(lines[0]);
    }

    // Set the Linux Caption (get first line of the /etc/SuSE-release file)
    m_linuxDistroCaption = lines[0];
    if (0 == m_linuxDistroCaption.length())
    {
        // Fallback - should not normally happen
        m_linuxDistroCaption = L"SuSE";
    }

    // File contains one or more lines looking like this:
    // SUSE Linux Enterprise Server 10 (i586)
    // VERSION = 10
    // PATCHLEVEL = 1
    for (size_t i = 0; i<lines.size(); i++)
    {
        if (StrIsPrefix(StrTrim(lines[i]), L"VERSION", true))
        {
            wstring::size_type n = lines[i].find_first_of(L"=");
            if (n != wstring::npos)
            {
                version = StrTrim(lines[i].substr(n+1));
            }
        }
        else if (StrIsPrefix(StrTrim(lines[i]), L"PATCHLEVEL", true))
        {
            wstring::size_type n = lines[i].find_first_of(L"=");
            if (n != wstring::npos)
            {
                patchlevel = StrTrim(lines[i].substr(n+1));
            }
        }
    }

    if (version.length() > 0)
    {
        m_osVersion = version;

        if (patchlevel.length() > 0)
        {
            m_osVersion = version.append(L".").append(patchlevel);
        }
    }

    if (std::wstring::npos != m_osName.find(L"Desktop"))
    {
        m_osAlias = L"SLED";
    }
    else
    {   // Assume server.
        m_osAlias = L"SLES";
    }
    m_osManufacturer = L"SUSE GmbH";
#elif defined(PF_DISTRO_REDHAT)
    static const string relFileName = "/etc/redhat-release";
    wifstream relfile(relFileName.c_str());

    SCXStream::ReadAllLines(relfile, lines, nlfs);

    if (!lines.empty()) {
        m_osName = ExtractOSName(lines[0]);
    }

    // Set the Linux Caption (get first line of the /etc/redhat-release file)
    m_linuxDistroCaption = lines[0];
    if (0 == m_linuxDistroCaption.length())
    {
        // Fallback - should not normally happen
        m_linuxDistroCaption = L"Red Hat";
    }

    // File should contain one line that looks like this:
    // Red Hat Enterprise Linux Server release 5.1 (Tikanga)
    if (lines.size() > 0)
    {
        wstring::size_type n = lines[0].find_first_of(L"0123456789");
        if (n != wstring::npos)
        {
            wstring::size_type n2 = lines[0].substr(n).find_first_of(L" \t\n\t");
            m_osVersion = StrTrim(lines[0].substr(n,n2));
        }
    }

    if ((std::wstring::npos != m_osName.find(L"Client")) // RHED5
            || (std::wstring::npos != m_osName.find(L"Desktop"))) // RHED4
    {
        m_osAlias = L"RHED";
    }
    else
    {   // Assume server.
        m_osAlias = L"RHEL";
    }
    m_osManufacturer = L"Red Hat, Inc.";

#elif defined(PF_DISTRO_ULINUX)
    // The release file is created at agent start time by init.d startup script
    // This is done to insure that we can write to the appropriate directory at
    // the time (since, at agent run-time, we may not have root privileges).
    //
    // If we CAN create the file here (if we're running as root), then we'll
    // do so here. But in the normal case, this shouldn't be necessary.  Only
    // in "weird" cases (i.e. starting omiserver by hand, for example).

    // Create the release file by running GetLinuxOS.sh script
    // (if we have root privileges)

    try
    {
        if ( !SCXFile::Exists(m_deps->getReleasePath()) &&
                SCXFile::Exists(m_deps->getScriptPath()) &&
                m_deps->isReleasePathWritable() )
        {
            std::istringstream in;
            std::ostringstream out;
            std::ostringstream err;

            int ret = SCXCoreLib::SCXProcess::Run(m_deps->getScriptPath().c_str(), in, out, err, 10000);

            if ( ret || out.str().length() || err.str().length() )
            {
                wostringstream sout;
                sout << L"Unexpected errors running script: " << m_deps->getScriptPath().c_str()
                     << L", return code: " << ret
                     << L", stdout: " << StrFromUTF8(out.str())
                     << L", stderr: " << StrFromUTF8(err.str());

                SCX_LOGERROR(m_log, sout.str() );
            }
        }
    }
    catch(SCXCoreLib::SCXInterruptedProcessException &e)
    {
        wstring msg;
        msg = L"Timeout running script \"" + m_deps->getScriptPath() +
              L"\", " + e.Where() + L'.';
        SCX_LOGERROR(m_log, msg );
    };

    // Look in release file for O/S information

    string sFile = StrToUTF8(m_deps->getReleasePath());
    wifstream fin(sFile.c_str());
    SCXStream::ReadAllLines(fin, lines, nlfs);

    if (!lines.empty())
    {
        ExtractToken(L"OSName",     lines, m_osName);
        ExtractToken(L"OSVersion",  lines, m_osVersion);
        ExtractToken(L"OSFullName", lines, m_linuxDistroCaption);
        ExtractToken(L"OSAlias",    lines, m_osAlias);
        ExtractToken(L"OSManufacturer", lines, m_osManufacturer);
    }
    else
    {
        m_osAlias = L"Universal";
    }

    // Behavior for m_osCompatName (method GetOSName) should be as follows:
    //   PostInstall scripts will first look for SCX-RELEASE file (only on universal kits)
    //   If found, add "ORIGINAL_KIT_TYPE=Universal" to scxconfig.conf file,
    //      else   add "ORIGINAL_KIT_TYPE=!Universal" to scxconfig.conf file.
    //   After that is set up, the SCX-RELEASE file is created.
    //
    //   A RHEL system should of OSAlias of "RHEL, SLES system should have "SuSE" (in scx-release)
    //
    //   We need to mimic return values for RHEL and SLES on universal kits that did not
    //   have a universal kit installed previously, but only for RHEL and SLES kits.  In
    //   all other cases, continue to return "Linux Distribution".

    wstring configFilename(m_deps->getConfigPath());
    SCXConfigFile configFile(configFilename);

    try
    {
        configFile.LoadConfig();
    }
    catch(SCXFilePathNotFoundException &e)
    {
        // Something's whacky with postinstall, so we can't follow algorithm
        static SCXCoreLib::LogSuppressor suppressor(SCXCoreLib::eError, SCXCoreLib::eTrace);
        wstring logMessage(L"Unable to load configuration file " + configFilename);
        SCX_LOG(m_log, suppressor.GetSeverity(logMessage), logMessage);

        m_osCompatName = L"Unknown Linux Distribution";
    }

    if ( m_osCompatName.empty() )
    {
        wstring kitType;
        if ( configFile.GetValue(L"ORIGINAL_KIT_TYPE", kitType) )
        {
            if ( L"!Universal" == kitType )
            {
                if ( L"RHEL" == m_osAlias )
                {
                    m_osCompatName = L"Red Hat Distribution";
                }
                else if ( L"SLES" == m_osAlias )
                {
                    m_osCompatName = L"SuSE Distribution";
                }
            }
        }

        if ( m_osCompatName.empty() )
        {
            m_osCompatName = L"Linux Distribution";
        }
    }
#else
#error "Linux Platform not supported";
#endif

#elif defined(macos)
    m_osAlias = L"MacOS";
    m_osManufacturer = L"Apple Inc.";
    if (m_unameIsValid)
    {
        // MacOS is called "Darwin" in uname info, so we hard-code here
        m_osName = L"Mac OS";

        // This value we could read dynamically from the xml file
        // /System/Library/CoreServices/SystemVersion.plist, but that
        // file may be named differently based on client/server, and
        // reading the plist file would require framework stuff.
        //
        // Rather than using the plist, we'll use Gestalt, which is an
        // API designed to figure out versions of anything and everything.
        // Note that use of Gestalt requires the use of framework stuff
        // as well, so the Makefiles for MacOS are modified for that.

        SInt32 major, minor, bugfix;
        if (0 != Gestalt(gestaltSystemVersionMajor, &major)
                || 0 != Gestalt(gestaltSystemVersionMinor, &minor)
                || 0 != Gestalt(gestaltSystemVersionBugFix, &bugfix))
        {
            throw SCXCoreLib::SCXErrnoException(L"Gestalt", errno, SCXSRCLOCATION);
        }

        wostringstream sout;
        sout << major << L"." << minor << L"." << bugfix;
        m_osVersion = sout.str();
    }

#else
#error "Platform not supported"
#endif
}