/** 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 }
/** 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 }