Skip to content

Instantly share code, notes, and snippets.

@egtra
Created September 15, 2014 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egtra/fe0920d469b1e3936b48 to your computer and use it in GitHub Desktop.
Save egtra/fe0920d469b1e3936b48 to your computer and use it in GitHub Desktop.
Linuxディストリビューションの名前を収集してみるテスト
#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