Created
September 15, 2014 16:23
-
-
Save egtra/fe0920d469b1e3936b48 to your computer and use it in GitHub Desktop.
Linuxディストリビューションの名前を収集してみるテスト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#include <functional> | |
#include <string> | |
#include <system_error> | |
#include <cerrno> | |
#include <boost/algorithm/string/trim.hpp> | |
#include <boost/iostreams/device/file_descriptor.hpp> | |
#include <boost/iostreams/stream.hpp> | |
#include <boost/optional/optional.hpp> | |
#include <boost/range/istream_range.hpp> | |
#include <boost/range.hpp> | |
#include <boost/regex.hpp> | |
#include <boost/scope_exit.hpp> | |
#include <boost/throw_exception.hpp> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <sys/utsname.h> | |
static boost::optional<std::string> GetValueFromReleaseFile(const char* file, const char* key) | |
{ | |
static const boost::regex r("(.*)=(.*)"); | |
std::ifstream is(file); | |
if (is) | |
{ | |
is.exceptions(std::ios_base::badbit); | |
std::string s; | |
boost::smatch m; | |
while (std::getline(is, s)) | |
{ | |
if (boost::regex_match(s, m, r)) | |
{ | |
if (m[1] == key) | |
{ | |
return m[2].str(); | |
} | |
} | |
} | |
} | |
return {}; | |
} | |
boost::optional<std::string> ReadFirstLineFromFile(const char* file) | |
{ | |
std::ifstream is(file); | |
std::string s; | |
if (std::getline(is, s) && !s.empty()) | |
{ | |
return s; | |
} | |
return {}; | |
} | |
int POpen(const char* cmdLine, const char* mode, const std::function<void (FILE*)>& f) | |
{ | |
errno = 0; | |
auto fp = popen(cmdLine, mode); | |
if (fp == nullptr) | |
{ | |
if (errno == 0) | |
{ | |
throw std::bad_alloc(); | |
} | |
BOOST_THROW_EXCEPTION(std::system_error(errno, std::system_category())); | |
} | |
try | |
{ | |
f(fp); | |
} | |
catch(...) | |
{ | |
pclose(fp); | |
throw; | |
} | |
return pclose(fp); | |
} | |
boost::optional<std::string> ReadOutput(const char* cmdLine) | |
{ | |
namespace io = boost::iostreams; | |
std::string s; | |
auto result = POpen(cmdLine, "r", [&](FILE* fp) | |
{ | |
io::stream<io::file_descriptor_source> is(fileno(fp), boost::iostreams::never_close_handle); | |
is >> std::noskipws; | |
s = boost::copy_range<std::string>(boost::istream_range<char>(is)); | |
}); | |
return boost::make_optional(result == 0, s); | |
} | |
boost::optional<std::string> ReadLsbRelease() | |
{ | |
if (auto result = ReadOutput("lsb_release -d 2> /dev/null")) | |
{ | |
static boost::regex r("[^\\t]+\\t(.*)\\s*"); | |
boost::smatch m; | |
if (boost::regex_match(*result, m, r)) | |
{ | |
return m[1].str(); | |
} | |
} | |
return {}; | |
} | |
std::string GetOSName() | |
{ | |
if (auto lsb = ReadLsbRelease()) | |
{ | |
boost::algorithm::trim(*lsb, std::locale::classic()); | |
return *lsb; | |
} | |
if (auto lsb = GetValueFromReleaseFile("/etc/lsb-release", "DISTRIB_DESCRIPTION")) | |
{ | |
return *lsb; | |
} | |
if (auto lsb = GetValueFromReleaseFile("/etc/lsb-release", "DISTRIB_ID")) | |
{ | |
return *lsb; | |
} | |
if (auto os = GetValueFromReleaseFile("/etc/os-release", "PRETTY_NAME")) | |
{ | |
return *os; | |
} | |
if (auto os = GetValueFromReleaseFile("/usr/lib/os-release", "PRETTY_NAME")) | |
{ | |
return *os; | |
} | |
if (auto redhat = ReadFirstLineFromFile("/etc/redhat-release")) | |
{ | |
return *redhat; | |
} | |
auto osName = ReadOutput("uname -o 2> /dev/null"); | |
utsname uts; | |
if (uname(&uts) != 0) | |
{ | |
BOOST_THROW_EXCEPTION(std::system_error(errno, std::system_category())); | |
} | |
std::ostringstream os; | |
if (osName) | |
{ | |
boost::algorithm::trim(*osName, std::locale::classic()); | |
if (*osName != uts.sysname) | |
{ | |
os << *osName << " - "; | |
} | |
} | |
os << uts.sysname << ' ' << uts.release; | |
return os.str(); | |
} | |
int main() | |
{ | |
try | |
{ | |
if (setenv("PATH", "/bin:/usr/bin", 1) != 0) | |
{ | |
BOOST_THROW_EXCEPTION(std::system_error(errno, std::system_category())); | |
} | |
std::cout << GetOSName() << std::endl; | |
} | |
catch (const std::exception& e) | |
{ | |
std::cerr << typeid(e).name() << std::endl; | |
std::cerr << e.what() << std::endl; | |
return 1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment