summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRoger Leigh <rleigh@debian.org>2013-05-04 23:22:29 +0100
committerRoger Leigh <rleigh@debian.org>2013-05-04 23:22:29 +0100
commitef61a2aa84a4913ff5a9d4478767a1e3e6224e7c (patch)
treeeb1a8eaa5c0e7565edd465e5370692503e9175a2 /lib
parent4ec183f4fa454c8ddbe41e306ab9ba12e098e098 (diff)
downloadschroot-ef61a2aa84a4913ff5a9d4478767a1e3e6224e7c.tar.gz
lib: Sources use namespace scoping
Enclose in namespace as for all other sources.
Diffstat (limited to 'lib')
-rw-r--r--lib/bin-common/main.cc178
-rw-r--r--lib/bin-common/option-action.cc111
-rw-r--r--lib/bin-common/options.cc244
-rw-r--r--lib/dchroot-common/main.cc30
-rw-r--r--lib/dchroot-common/session.cc52
-rw-r--r--lib/sbuild/auth/auth.cc1
-rw-r--r--lib/sbuild/auth/deny.cc1
-rw-r--r--lib/sbuild/auth/pam-conv-tty.cc1
-rw-r--r--lib/sbuild/auth/pam-conv.cc2
-rw-r--r--lib/sbuild/auth/pam-message.cc2
-rw-r--r--lib/sbuild/auth/pam.cc145
-rw-r--r--lib/sbuild/chroot/config.cc25
-rw-r--r--lib/sbuild/chroot/facet/block-device-base.cc2
-rw-r--r--lib/sbuild/chroot/facet/block-device.cc1
-rw-r--r--lib/sbuild/chroot/facet/btrfs-snapshot.cc1
-rw-r--r--lib/sbuild/chroot/facet/custom.cc1
-rw-r--r--lib/sbuild/chroot/facet/directory-base.cc2
-rw-r--r--lib/sbuild/chroot/facet/directory.cc1
-rw-r--r--lib/sbuild/chroot/facet/facet.cc1
-rw-r--r--lib/sbuild/chroot/facet/file.cc1
-rw-r--r--lib/sbuild/chroot/facet/fsunion.cc10
-rw-r--r--lib/sbuild/chroot/facet/loopback.cc1
-rw-r--r--lib/sbuild/chroot/facet/lvm-snapshot.cc1
-rw-r--r--lib/sbuild/chroot/facet/mountable.cc1
-rw-r--r--lib/sbuild/chroot/facet/personality.cc1
-rw-r--r--lib/sbuild/chroot/facet/plain.cc1
-rw-r--r--lib/sbuild/chroot/facet/session-clonable.cc1
-rw-r--r--lib/sbuild/chroot/facet/session.cc1
-rw-r--r--lib/sbuild/chroot/facet/source-clonable.cc1
-rw-r--r--lib/sbuild/chroot/facet/source.cc1
-rw-r--r--lib/sbuild/chroot/facet/storage.cc2
-rw-r--r--lib/sbuild/chroot/facet/unshare.cc18
-rw-r--r--lib/sbuild/chroot/facet/userdata.cc74
-rw-r--r--lib/sbuild/ctty.cc143
-rw-r--r--lib/sbuild/environment.cc282
-rw-r--r--lib/sbuild/feature.cc49
-rw-r--r--lib/sbuild/format-detail.cc115
-rw-r--r--lib/sbuild/keyfile-reader.cc321
-rw-r--r--lib/sbuild/keyfile-writer.cc172
-rw-r--r--lib/sbuild/keyfile.cc923
-rw-r--r--lib/sbuild/lock.cc328
-rw-r--r--lib/sbuild/log.cc240
-rw-r--r--lib/sbuild/mntstream.cc259
-rw-r--r--lib/sbuild/nostream.cc7
-rw-r--r--lib/sbuild/parse-value.cc59
-rw-r--r--lib/sbuild/personality.cc262
-rw-r--r--lib/sbuild/run-parts.cc638
-rw-r--r--lib/sbuild/session.cc2843
-rw-r--r--lib/sbuild/types.cc39
-rw-r--r--lib/sbuild/util.cc1237
-rw-r--r--lib/schroot-common/main.cc638
-rw-r--r--lib/schroot-common/options.cc402
52 files changed, 4952 insertions, 4920 deletions
diff --git a/lib/bin-common/main.cc b/lib/bin-common/main.cc
index 17ae2ef7..1e2df2ab 100644
--- a/lib/bin-common/main.cc
+++ b/lib/bin-common/main.cc
@@ -36,100 +36,104 @@
using std::endl;
using boost::format;
using sbuild::_;
-using namespace bin_common;
-
-main::main (std::string const& program_name,
- std::string const& program_usage,
- options::ptr const& program_options,
- bool use_syslog):
- program_name(program_name),
- program_usage(program_usage),
- program_options(program_options),
- use_syslog(use_syslog)
-{
-}
-
-main::~main ()
-{
-}
-
-void
-main::action_version (std::ostream& stream)
-{
- // TRANSLATORS: %1% = program name
- // TRANSLATORS: %2% = program version
- // TRANSLATORS: %3% = release date
- format fmtr(_("%1% (Debian sbuild) %2% (%3%)"));
- fmtr % this->program_name % VERSION % sbuild::gmdate(RELEASE_DATE);
-
- // TRANSLATORS: %1% = copyright year (start)
- // TRANSLATORS: %2% = copyright year (end)
- format fmtc(_("Copyright © %1%–%2% Roger Leigh"));
- fmtc % "2004" % "2012";
-
- stream << fmtr << '\n'
- << _("Written by Roger Leigh") << '\n' << '\n'
- << fmtc << '\n'
- << _("This is free software; see the source for copying conditions. There is NO\n"
- "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")
- << '\n'
- << _("Configured features:") << '\n';
- sbuild::feature::print_features(stream);
- stream << std::flush;
-}
-void
-main::action_help (std::ostream& stream)
+namespace bin_common
{
- stream
- << _("Usage:") << '\n'
- << " " << this->program_name << " "
- << this->program_usage << std::endl;
-
- stream << this->program_options->get_visible_options() << std::flush;
-}
-int
-main::run (int argc,
- char *argv[])
-{
- try
- {
- this->program_options->parse(argc, argv);
+ main::main (std::string const& program_name,
+ std::string const& program_usage,
+ options::ptr const& program_options,
+ bool use_syslog):
+ program_name(program_name),
+ program_usage(program_usage),
+ program_options(program_options),
+ use_syslog(use_syslog)
+ {
+ }
+
+ main::~main ()
+ {
+ }
+
+ void
+ main::action_version (std::ostream& stream)
+ {
+ // TRANSLATORS: %1% = program name
+ // TRANSLATORS: %2% = program version
+ // TRANSLATORS: %3% = release date
+ format fmtr(_("%1% (Debian sbuild) %2% (%3%)"));
+ fmtr % this->program_name % VERSION % sbuild::gmdate(RELEASE_DATE);
+
+ // TRANSLATORS: %1% = copyright year (start)
+ // TRANSLATORS: %2% = copyright year (end)
+ format fmtc(_("Copyright © %1%–%2% Roger Leigh"));
+ fmtc % "2004" % "2012";
+
+ stream << fmtr << '\n'
+ << _("Written by Roger Leigh") << '\n' << '\n'
+ << fmtc << '\n'
+ << _("This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")
+ << '\n'
+ << _("Configured features:") << '\n';
+ sbuild::feature::print_features(stream);
+ stream << std::flush;
+ }
+
+ void
+ main::action_help (std::ostream& stream)
+ {
+ stream
+ << _("Usage:") << '\n'
+ << " " << this->program_name << " "
+ << this->program_usage << std::endl;
+
+ stream << this->program_options->get_visible_options() << std::flush;
+ }
+
+ int
+ main::run (int argc,
+ char *argv[])
+ {
+ try
+ {
+ this->program_options->parse(argc, argv);
#ifdef SBUILD_DEBUG
- sbuild::debug_log_level = sbuild::DEBUG_CRITICAL;
+ sbuild::debug_log_level = sbuild::DEBUG_CRITICAL;
#endif
- if (this->use_syslog)
- openlog(this->program_name.c_str(), LOG_PID|LOG_NDELAY, LOG_AUTHPRIV);
-
- int status = run_impl();
-
- closelog();
-
- return status;
- }
- catch (std::exception const& e)
- {
- sbuild::log_exception_error(e);
-
- try
- {
- dynamic_cast<bin_common::options::error const&>(e);
- sbuild::log_info()
- // TRANSLATORS: %1% = program name
- << format(_("Run “%1% --help” to list usage example and all available options"))
- % argv[0]
- << endl;
- }
- catch (std::bad_cast const& discard)
- {
- }
-
- if (this->use_syslog)
+ if (this->use_syslog)
+ openlog(this->program_name.c_str(), LOG_PID|LOG_NDELAY, LOG_AUTHPRIV);
+
+ int status = run_impl();
+
closelog();
- return EXIT_FAILURE;
- }
+ return status;
+ }
+ catch (std::exception const& e)
+ {
+ sbuild::log_exception_error(e);
+
+ try
+ {
+ dynamic_cast<bin_common::options::error const&>(e);
+ sbuild::log_info()
+ // TRANSLATORS: %1% = program name
+ << format(_("Run “%1% --help” to list usage example and all available options"))
+ % argv[0]
+ << endl;
+ }
+ catch (std::bad_cast const& discard)
+ {
+ }
+
+ if (this->use_syslog)
+ closelog();
+
+ return EXIT_FAILURE;
+ }
+ }
+
}
diff --git a/lib/bin-common/option-action.cc b/lib/bin-common/option-action.cc
index 65dbd46e..06107599 100644
--- a/lib/bin-common/option-action.cc
+++ b/lib/bin-common/option-action.cc
@@ -32,67 +32,70 @@ using std::endl;
using boost::format;
using sbuild::_;
namespace opt = boost::program_options;
-using namespace bin_common;
-option_action::option_action ():
- default_action(),
- current_action(),
- actions()
+namespace bin_common
{
-}
-option_action::~option_action ()
-{
-}
-
-void
-option_action::add (action_type const& action)
-{
- this->actions.insert(action);
-}
+ option_action::option_action ():
+ default_action(),
+ current_action(),
+ actions()
+ {
+ }
-option_action::action_type const&
-option_action::get_default ()
-{
- return this->default_action;
-}
+ option_action::~option_action ()
+ {
+ }
-void
-option_action::set_default (action_type const& action)
-{
- if (valid(action))
- this->default_action = action;
- else
- throw bin_common::options::error((format(_("%1%: invalid action")) % action).str());
-}
+ void
+ option_action::add (action_type const& action)
+ {
+ this->actions.insert(action);
+ }
-option_action::action_type const&
-option_action::get ()
-{
- if (this->current_action != "")
- return this->current_action;
- else
+ option_action::action_type const&
+ option_action::get_default ()
+ {
return this->default_action;
-}
+ }
-void
-option_action::set (action_type const& action)
-{
- if (valid(action))
- {
- if (this->current_action == "")
- this->current_action = action;
- else
- throw bin_common::options::error
- (_("Only one action may be specified"));
- }
- else
- throw bin_common::options::error((format(_("%1%: invalid action")) % action).str());
-}
+ void
+ option_action::set_default (action_type const& action)
+ {
+ if (valid(action))
+ this->default_action = action;
+ else
+ throw bin_common::options::error((format(_("%1%: invalid action")) % action).str());
+ }
-bool
-option_action::valid (action_type const& action)
-{
- return this->actions.find(action) != this->actions.end();
-}
+ option_action::action_type const&
+ option_action::get ()
+ {
+ if (this->current_action != "")
+ return this->current_action;
+ else
+ return this->default_action;
+ }
+
+ void
+ option_action::set (action_type const& action)
+ {
+ if (valid(action))
+ {
+ if (this->current_action == "")
+ this->current_action = action;
+ else
+ throw bin_common::options::error
+ (_("Only one action may be specified"));
+ }
+ else
+ throw bin_common::options::error((format(_("%1%: invalid action")) % action).str());
+ }
+ bool
+ option_action::valid (action_type const& action)
+ {
+ return this->actions.find(action) != this->actions.end();
+ }
+
+}
diff --git a/lib/bin-common/options.cc b/lib/bin-common/options.cc
index 26af2662..6c5e3977 100644
--- a/lib/bin-common/options.cc
+++ b/lib/bin-common/options.cc
@@ -33,138 +33,142 @@ using std::endl;
using boost::format;
using sbuild::_;
namespace opt = boost::program_options;
-using namespace bin_common;
-
-/// Display program help.
-const options::action_type options::ACTION_HELP ("help");
-/// Display program version.
-const options::action_type options::ACTION_VERSION ("version");
-
-options::options ():
- action(),
- quiet(false),
- verbose(false),
- actions(_("Actions")),
- general(_("General options")),
- hidden(_("Hidden options")),
- positional(),
- visible(),
- global(),
- vm()
-{
-}
-
-options::~options ()
-{
-}
-
-boost::program_options::options_description const&
-options::get_visible_options() const
-{
- return this->visible;
-}
-void
-options::parse (int argc,
- char *argv[])
+namespace bin_common
{
- add_options();
- add_option_groups();
- opt::store(opt::command_line_parser(argc, argv).
- options(global).positional(positional).run(), vm);
- opt::notify(vm);
-
- check_options();
- check_actions();
-}
-
-void
-options::add_options ()
-{
- this->action.add(ACTION_HELP);
- this->action.add(ACTION_VERSION);
-
- actions.add_options()
- ("help,h",
- _("Show help options"))
- ("version,V",
- _("Print version information"));
-
- general.add_options()
- ("quiet,q",
- _("Show less output"))
- ("verbose,v",
- _("Show more output"));
-
- hidden.add_options()
- ("debug", opt::value<std::string>(&this->debug_level),
- _("Enable debugging messages"));
-}
-
-void
-options::add_option_groups ()
-{
+ /// Display program help.
+ const options::action_type options::ACTION_HELP ("help");
+ /// Display program version.
+ const options::action_type options::ACTION_VERSION ("version");
+
+ options::options ():
+ action(),
+ quiet(false),
+ verbose(false),
+ actions(_("Actions")),
+ general(_("General options")),
+ hidden(_("Hidden options")),
+ positional(),
+ visible(),
+ global(),
+ vm()
+ {
+ }
+
+ options::~options ()
+ {
+ }
+
+ boost::program_options::options_description const&
+ options::get_visible_options() const
+ {
+ return this->visible;
+ }
+
+ void
+ options::parse (int argc,
+ char *argv[])
+ {
+ add_options();
+ add_option_groups();
+
+ opt::store(opt::command_line_parser(argc, argv).
+ options(global).positional(positional).run(), vm);
+ opt::notify(vm);
+
+ check_options();
+ check_actions();
+ }
+
+ void
+ options::add_options ()
+ {
+ this->action.add(ACTION_HELP);
+ this->action.add(ACTION_VERSION);
+
+ actions.add_options()
+ ("help,h",
+ _("Show help options"))
+ ("version,V",
+ _("Print version information"));
+
+ general.add_options()
+ ("quiet,q",
+ _("Show less output"))
+ ("verbose,v",
+ _("Show more output"));
+
+ hidden.add_options()
+ ("debug", opt::value<std::string>(&this->debug_level),
+ _("Enable debugging messages"));
+ }
+
+ void
+ options::add_option_groups ()
+ {
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!actions.options().empty())
+ if (!actions.options().empty())
#else
- if (!actions.primary_keys().empty())
+ if (!actions.primary_keys().empty())
#endif
- {
- visible.add(actions);
- global.add(actions);
- }
+ {
+ visible.add(actions);
+ global.add(actions);
+ }
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!general.options().empty())
+ if (!general.options().empty())
#else
- if (!general.primary_keys().empty())
+ if (!general.primary_keys().empty())
#endif
- {
- visible.add(general);
- global.add(general);
- }
+ {
+ visible.add(general);
+ global.add(general);
+ }
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!hidden.options().empty())
+ if (!hidden.options().empty())
#else
- if (!hidden.primary_keys().empty())
+ if (!hidden.primary_keys().empty())
#endif
- global.add(hidden);
-}
+ global.add(hidden);
+ }
-void
-options::check_options ()
-{
- if (vm.count("help"))
- this->action = ACTION_HELP;
-
- if (vm.count("version"))
- this->action = ACTION_VERSION;
-
- if (vm.count("quiet"))
- this->quiet = true;
- if (vm.count("verbose"))
- this->verbose = true;
-
- if (vm.count("debug"))
- {
- if (this->debug_level == "none")
- sbuild::debug_log_level = sbuild::DEBUG_NONE;
- else if (this->debug_level == "notice")
- sbuild::debug_log_level = sbuild::DEBUG_NOTICE;
- else if (this->debug_level == "info")
- sbuild::debug_log_level = sbuild::DEBUG_INFO;
- else if (this->debug_level == "warning")
- sbuild::debug_log_level = sbuild::DEBUG_WARNING;
- else if (this->debug_level == "critical")
- sbuild::debug_log_level = sbuild::DEBUG_CRITICAL;
- else
- throw error(_("Invalid debug level"));
- }
- else
- sbuild::debug_log_level = sbuild::DEBUG_NONE;
-}
+ void
+ options::check_options ()
+ {
+ if (vm.count("help"))
+ this->action = ACTION_HELP;
+
+ if (vm.count("version"))
+ this->action = ACTION_VERSION;
+
+ if (vm.count("quiet"))
+ this->quiet = true;
+ if (vm.count("verbose"))
+ this->verbose = true;
+
+ if (vm.count("debug"))
+ {
+ if (this->debug_level == "none")
+ sbuild::debug_log_level = sbuild::DEBUG_NONE;
+ else if (this->debug_level == "notice")
+ sbuild::debug_log_level = sbuild::DEBUG_NOTICE;
+ else if (this->debug_level == "info")
+ sbuild::debug_log_level = sbuild::DEBUG_INFO;
+ else if (this->debug_level == "warning")
+ sbuild::debug_log_level = sbuild::DEBUG_WARNING;
+ else if (this->debug_level == "critical")
+ sbuild::debug_log_level = sbuild::DEBUG_CRITICAL;
+ else
+ throw error(_("Invalid debug level"));
+ }
+ else
+ sbuild::debug_log_level = sbuild::DEBUG_NONE;
+ }
+
+ void
+ options::check_actions ()
+ {
+ }
-void
-options::check_actions ()
-{
}
diff --git a/lib/dchroot-common/main.cc b/lib/dchroot-common/main.cc
index cc789cd1..a0e3e856 100644
--- a/lib/dchroot-common/main.cc
+++ b/lib/dchroot-common/main.cc
@@ -36,21 +36,25 @@
using std::endl;
using boost::format;
using sbuild::_;
-using namespace dchroot_common;
-main::main (std::string const& program_name,
- std::string const& program_usage,
- schroot_common::options::ptr& options):
- schroot_common::main(program_name, program_usage, options, true)
+namespace dchroot_common
{
-}
-main::~main ()
-{
-}
+ main::main (std::string const& program_name,
+ std::string const& program_usage,
+ schroot_common::options::ptr& options):
+ schroot_common::main(program_name, program_usage, options, true)
+ {
+ }
+
+ main::~main ()
+ {
+ }
+
+ void
+ main::action_list ()
+ {
+ this->config->print_chroot_list_simple(std::cout);
+ }
-void
-main::action_list ()
-{
- this->config->print_chroot_list_simple(std::cout);
}
diff --git a/lib/dchroot-common/session.cc b/lib/dchroot-common/session.cc
index adbfdb7d..992d0a4c 100644
--- a/lib/dchroot-common/session.cc
+++ b/lib/dchroot-common/session.cc
@@ -37,34 +37,38 @@ using std::cout;
using std::endl;
using sbuild::_;
using boost::format;
-using namespace dchroot_common;
-session::session (std::string const& service,
- operation operation,
- sbuild::session::chroot_list const& chroots):
- sbuild::session(service, operation, chroots)
+namespace dchroot_common
{
-}
-session::~session ()
-{
-}
+ session::session (std::string const& service,
+ operation operation,
+ sbuild::session::chroot_list const& chroots):
+ sbuild::session(service, operation, chroots)
+ {
+ }
-void
-session::run_impl ()
-{
- if (get_auth()->get_ruid() != get_auth()->get_uid())
- throw error(get_auth()->get_ruser(), get_auth()->get_user(), USER_SWITCH,
- _("dchroot session restriction"));
+ session::~session ()
+ {
+ }
- sbuild::session::run_impl();
-}
+ void
+ session::run_impl ()
+ {
+ if (get_auth()->get_ruid() != get_auth()->get_uid())
+ throw error(get_auth()->get_ruser(), get_auth()->get_user(), USER_SWITCH,
+ _("dchroot session restriction"));
+
+ sbuild::session::run_impl();
+ }
+
+ sbuild::string_list
+ session::get_command_directories (sbuild::chroot::chroot::ptr& session_chroot,
+ sbuild::environment const& env) const
+ {
+ // dchroot does not treat logins differently from commands with
+ // respect to the cwd inside the chroot.
+ return get_login_directories(session_chroot, env);
+ }
-sbuild::string_list
-session::get_command_directories (sbuild::chroot::chroot::ptr& session_chroot,
- sbuild::environment const& env) const
-{
- // dchroot does not treat logins differently from commands with
- // respect to the cwd inside the chroot.
- return get_login_directories(session_chroot, env);
}
diff --git a/lib/sbuild/auth/auth.cc b/lib/sbuild/auth/auth.cc
index 2083d019..46911310 100644
--- a/lib/sbuild/auth/auth.cc
+++ b/lib/sbuild/auth/auth.cc
@@ -36,7 +36,6 @@
using std::cerr;
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/auth/deny.cc b/lib/sbuild/auth/deny.cc
index e7e81d30..6eae07fd 100644
--- a/lib/sbuild/auth/deny.cc
+++ b/lib/sbuild/auth/deny.cc
@@ -34,7 +34,6 @@
using std::cerr;
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/auth/pam-conv-tty.cc b/lib/sbuild/auth/pam-conv-tty.cc
index a139cbbb..614462da 100644
--- a/lib/sbuild/auth/pam-conv-tty.cc
+++ b/lib/sbuild/auth/pam-conv-tty.cc
@@ -32,7 +32,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace
{
diff --git a/lib/sbuild/auth/pam-conv.cc b/lib/sbuild/auth/pam-conv.cc
index d085b892..019aa29c 100644
--- a/lib/sbuild/auth/pam-conv.cc
+++ b/lib/sbuild/auth/pam-conv.cc
@@ -20,8 +20,6 @@
#include <sbuild/auth/pam-conv.h>
-using namespace sbuild;
-
namespace sbuild
{
namespace auth
diff --git a/lib/sbuild/auth/pam-message.cc b/lib/sbuild/auth/pam-message.cc
index d9278ba5..d88e5deb 100644
--- a/lib/sbuild/auth/pam-message.cc
+++ b/lib/sbuild/auth/pam-message.cc
@@ -20,8 +20,6 @@
#include <sbuild/auth/pam-message.h>
-using namespace sbuild;
-
namespace sbuild
{
namespace auth
diff --git a/lib/sbuild/auth/pam.cc b/lib/sbuild/auth/pam.cc
index 9a7665c4..6fcc0aa0 100644
--- a/lib/sbuild/auth/pam.cc
+++ b/lib/sbuild/auth/pam.cc
@@ -36,7 +36,6 @@
using std::cerr;
using std::endl;
using boost::format;
-using namespace sbuild;
#if defined(__LINUX_PAM__)
#define PAM_TEXT_DOMAIN "Linux-PAM"
@@ -44,99 +43,99 @@ using namespace sbuild;
#define PAM_TEXT_DOMAIN "SUNW_OST_SYSOSPAM"
#endif
-namespace
+namespace sbuild
{
-
- /* This is the glue to link PAM user interaction with pam_conv. */
- int
- pam_conv_hook (int num_msg,
- const struct pam_message **msgm,
- struct pam_response **response,
- void *appdata_ptr)
+ namespace auth
{
- log_debug(DEBUG_NOTICE) << "PAM conversation hook started" << endl;
-
- try
- {
- if (appdata_ptr == 0)
- return PAM_CONV_ERR;
- auth::pam_conv *conv = static_cast<auth::pam_conv *>(appdata_ptr);
- assert (conv != 0);
+ namespace
+ {
- log_debug(DEBUG_INFO) << "Found PAM conversation handler" << endl;
+ /* This is the glue to link PAM user interaction with pam_conv. */
+ int
+ pam_conv_hook (int num_msg,
+ const struct ::pam_message **msgm,
+ struct ::pam_response **response,
+ void *appdata_ptr)
+ {
+ log_debug(DEBUG_NOTICE) << "PAM conversation hook started" << endl;
- /* Construct a message vector */
- auth::pam_conv::message_list messages;
- for (int i = 0; i < num_msg; ++i)
+ try
{
- const struct ::pam_message *source = msgm[i];
+ if (appdata_ptr == 0)
+ return PAM_CONV_ERR;
+
+ pam_conv *conv = static_cast<pam_conv *>(appdata_ptr);
+ assert (conv != 0);
- auth::pam_message
- message(static_cast<auth::pam_message::message_type>(source->msg_style),
- source->msg);
+ log_debug(DEBUG_INFO) << "Found PAM conversation handler" << endl;
- /* Replace PAM prompt */
- if (message.message == dgettext(PAM_TEXT_DOMAIN, "Password: ") ||
- message.message == dgettext(PAM_TEXT_DOMAIN, "Password:"))
+ /* Construct a message vector */
+ pam_conv::message_list messages;
+ for (int i = 0; i < num_msg; ++i)
{
- std::string user = "unknown"; // Set in case auth is void
- std::shared_ptr<auth::pam> auth = conv->get_auth();
- assert(auth && auth.get() != 0); // Check auth is not void
- if (auth && auth.get() != 0)
- user = auth->get_user();
- format fmt(_("[schroot] password for %1%: "));
- fmt % user;
- message.message = fmt.str();
+ const struct ::pam_message *source = msgm[i];
+
+ pam_message
+ message(static_cast<pam_message::message_type>(source->msg_style),
+ source->msg);
+
+ /* Replace PAM prompt */
+ if (message.message == dgettext(PAM_TEXT_DOMAIN, "Password: ") ||
+ message.message == dgettext(PAM_TEXT_DOMAIN, "Password:"))
+ {
+ std::string user = "unknown"; // Set in case auth is void
+ std::shared_ptr<pam> auth = conv->get_auth();
+ assert(auth && auth.get() != 0); // Check auth is not void
+ if (auth && auth.get() != 0)
+ user = auth->get_user();
+ format fmt(_("[schroot] password for %1%: "));
+ fmt % user;
+ message.message = fmt.str();
+ }
+
+ messages.push_back(message);
}
- messages.push_back(message);
- }
+ log_debug(DEBUG_INFO) << "Set PAM conversation message vector" << endl;
- log_debug(DEBUG_INFO) << "Set PAM conversation message vector" << endl;
+ /* Do the conversation; an exception will be thrown on failure */
+ conv->conversation(messages);
- /* Do the conversation; an exception will be thrown on failure */
- conv->conversation(messages);
+ log_debug(DEBUG_INFO) << "Run PAM conversation" << endl;
- log_debug(DEBUG_INFO) << "Run PAM conversation" << endl;
+ /* Copy response into **reponse */
+ struct pam_response *reply =
+ static_cast<struct pam_response *>
+ (malloc(sizeof(struct pam_response) * num_msg));
- /* Copy response into **reponse */
- struct pam_response *reply =
- static_cast<struct pam_response *>
- (malloc(sizeof(struct pam_response) * num_msg));
+ for (int i = 0; i < num_msg; ++i)
+ {
+ reply[i].resp_retcode = 0;
+ reply[i].resp = strdup(messages[i].response.c_str());
+ }
- for (int i = 0; i < num_msg; ++i)
- {
- reply[i].resp_retcode = 0;
- reply[i].resp = strdup(messages[i].response.c_str());
- }
+ *response = reply;
+ reply = 0;
- *response = reply;
- reply = 0;
+ log_debug(DEBUG_INFO) << "Set PAM conversation reply" << endl;
- log_debug(DEBUG_INFO) << "Set PAM conversation reply" << endl;
+ return PAM_SUCCESS;
+ }
+ catch (std::exception const& e)
+ {
+ log_exception_error(e);
+ }
+ catch (...)
+ {
+ log_error() << _("An unknown exception occurred") << endl;
+ }
- return PAM_SUCCESS;
- }
- catch (std::exception const& e)
- {
- log_exception_error(e);
+ return PAM_CONV_ERR;
}
- catch (...)
- {
- log_error() << _("An unknown exception occurred") << endl;
- }
-
- return PAM_CONV_ERR;
- }
- sbuild::feature feature_pam("PAM", N_("Pluggable Authentication Modules"));
-}
-
-namespace sbuild
-{
- namespace auth
- {
+ sbuild::feature feature_pam("PAM", N_("Pluggable Authentication Modules"));
+ }
pam::pam (std::string const& service_name):
auth(service_name),
diff --git a/lib/sbuild/chroot/config.cc b/lib/sbuild/chroot/config.cc
index 1020bbe6..1bccaf65 100644
--- a/lib/sbuild/chroot/config.cc
+++ b/lib/sbuild/chroot/config.cc
@@ -42,25 +42,24 @@
using std::endl;
using boost::format;
-using namespace sbuild;
-
-namespace
-{
-
- bool
- chroot_alphasort (chroot::chroot::ptr const& c1,
- chroot::chroot::ptr const& c2)
- {
- return c1->get_name() < c2->get_name();
- }
-
-}
namespace sbuild
{
namespace chroot
{
+ namespace
+ {
+
+ bool
+ chroot_alphasort (chroot::chroot::ptr const& c1,
+ chroot::chroot::ptr const& c2)
+ {
+ return c1->get_name() < c2->get_name();
+ }
+
+ }
+
template<>
error<config::error_code>::map_type
error<config::error_code>::error_strings =
diff --git a/lib/sbuild/chroot/facet/block-device-base.cc b/lib/sbuild/chroot/facet/block-device-base.cc
index d3ca94b2..a0388717 100644
--- a/lib/sbuild/chroot/facet/block-device-base.cc
+++ b/lib/sbuild/chroot/facet/block-device-base.cc
@@ -28,8 +28,6 @@
#include <cstring>
#include <iostream>
-using namespace sbuild;
-
namespace sbuild
{
namespace chroot
diff --git a/lib/sbuild/chroot/facet/block-device.cc b/lib/sbuild/chroot/facet/block-device.cc
index f3427280..166e33d0 100644
--- a/lib/sbuild/chroot/facet/block-device.cc
+++ b/lib/sbuild/chroot/facet/block-device.cc
@@ -37,7 +37,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/btrfs-snapshot.cc b/lib/sbuild/chroot/facet/btrfs-snapshot.cc
index afa3fbb7..170da0ca 100644
--- a/lib/sbuild/chroot/facet/btrfs-snapshot.cc
+++ b/lib/sbuild/chroot/facet/btrfs-snapshot.cc
@@ -34,7 +34,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/custom.cc b/lib/sbuild/chroot/facet/custom.cc
index 97f81529..9bccd220 100644
--- a/lib/sbuild/chroot/facet/custom.cc
+++ b/lib/sbuild/chroot/facet/custom.cc
@@ -33,7 +33,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/directory-base.cc b/lib/sbuild/chroot/facet/directory-base.cc
index 2240550e..11a44080 100644
--- a/lib/sbuild/chroot/facet/directory-base.cc
+++ b/lib/sbuild/chroot/facet/directory-base.cc
@@ -27,8 +27,6 @@
#include <cstring>
#include <iostream>
-using namespace sbuild;
-
namespace sbuild
{
namespace chroot
diff --git a/lib/sbuild/chroot/facet/directory.cc b/lib/sbuild/chroot/facet/directory.cc
index 5f87a8ef..90bd5b66 100644
--- a/lib/sbuild/chroot/facet/directory.cc
+++ b/lib/sbuild/chroot/facet/directory.cc
@@ -33,7 +33,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/facet.cc b/lib/sbuild/chroot/facet/facet.cc
index b905dbfc..4c94feab 100644
--- a/lib/sbuild/chroot/facet/facet.cc
+++ b/lib/sbuild/chroot/facet/facet.cc
@@ -24,7 +24,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/file.cc b/lib/sbuild/chroot/facet/file.cc
index 4999415d..3f45746c 100644
--- a/lib/sbuild/chroot/facet/file.cc
+++ b/lib/sbuild/chroot/facet/file.cc
@@ -33,7 +33,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/fsunion.cc b/lib/sbuild/chroot/facet/fsunion.cc
index bb154a5e..3db40e5b 100644
--- a/lib/sbuild/chroot/facet/fsunion.cc
+++ b/lib/sbuild/chroot/facet/fsunion.cc
@@ -30,14 +30,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
-
-namespace
-{
-
- sbuild::feature feature_union("UNION", N_("Support for filesystem unioning"));
-
-}
namespace sbuild
{
@@ -49,6 +41,8 @@ namespace sbuild
namespace
{
+ feature feature_union("UNION", N_("Support for filesystem unioning"));
+
factory::facet_info fsunion_info =
{
"union",
diff --git a/lib/sbuild/chroot/facet/loopback.cc b/lib/sbuild/chroot/facet/loopback.cc
index fb23e278..73a7a96d 100644
--- a/lib/sbuild/chroot/facet/loopback.cc
+++ b/lib/sbuild/chroot/facet/loopback.cc
@@ -33,7 +33,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/lvm-snapshot.cc b/lib/sbuild/chroot/facet/lvm-snapshot.cc
index c138a869..113f3d69 100644
--- a/lib/sbuild/chroot/facet/lvm-snapshot.cc
+++ b/lib/sbuild/chroot/facet/lvm-snapshot.cc
@@ -34,7 +34,6 @@
using std::endl;
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/mountable.cc b/lib/sbuild/chroot/facet/mountable.cc
index 5ef62a78..fce24281 100644
--- a/lib/sbuild/chroot/facet/mountable.cc
+++ b/lib/sbuild/chroot/facet/mountable.cc
@@ -29,7 +29,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/personality.cc b/lib/sbuild/chroot/facet/personality.cc
index 7ba38c75..0936ad34 100644
--- a/lib/sbuild/chroot/facet/personality.cc
+++ b/lib/sbuild/chroot/facet/personality.cc
@@ -25,7 +25,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/plain.cc b/lib/sbuild/chroot/facet/plain.cc
index ff452b56..b8cc9eae 100644
--- a/lib/sbuild/chroot/facet/plain.cc
+++ b/lib/sbuild/chroot/facet/plain.cc
@@ -31,7 +31,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/session-clonable.cc b/lib/sbuild/chroot/facet/session-clonable.cc
index cb6b97e1..35924385 100644
--- a/lib/sbuild/chroot/facet/session-clonable.cc
+++ b/lib/sbuild/chroot/facet/session-clonable.cc
@@ -33,7 +33,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/session.cc b/lib/sbuild/chroot/facet/session.cc
index 0e13ff29..e45dbf39 100644
--- a/lib/sbuild/chroot/facet/session.cc
+++ b/lib/sbuild/chroot/facet/session.cc
@@ -37,7 +37,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/source-clonable.cc b/lib/sbuild/chroot/facet/source-clonable.cc
index ff70e9b5..7f3f5716 100644
--- a/lib/sbuild/chroot/facet/source-clonable.cc
+++ b/lib/sbuild/chroot/facet/source-clonable.cc
@@ -31,7 +31,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/source.cc b/lib/sbuild/chroot/facet/source.cc
index 638f3d0f..e5ade412 100644
--- a/lib/sbuild/chroot/facet/source.cc
+++ b/lib/sbuild/chroot/facet/source.cc
@@ -26,7 +26,6 @@
using boost::format;
using std::endl;
-using namespace sbuild;
namespace sbuild
{
diff --git a/lib/sbuild/chroot/facet/storage.cc b/lib/sbuild/chroot/facet/storage.cc
index a54167e7..e47d513e 100644
--- a/lib/sbuild/chroot/facet/storage.cc
+++ b/lib/sbuild/chroot/facet/storage.cc
@@ -20,8 +20,6 @@
#include <sbuild/chroot/facet/storage.h>
-using namespace sbuild;
-
namespace sbuild
{
namespace chroot
diff --git a/lib/sbuild/chroot/facet/unshare.cc b/lib/sbuild/chroot/facet/unshare.cc
index 9d421a51..bd6184b3 100644
--- a/lib/sbuild/chroot/facet/unshare.cc
+++ b/lib/sbuild/chroot/facet/unshare.cc
@@ -30,18 +30,7 @@
#endif // SBUILD_FEATURE_UNSHARE
using boost::format;
-using namespace sbuild;
-namespace
-{
-
-#ifdef SBUILD_FEATURE_UNSHARE
- sbuild::feature feature_unshare
- ("UNSHARE",
- N_("Linux dissassociation of shared execution context"));
-#endif
-
-}
namespace sbuild
{
@@ -50,9 +39,16 @@ namespace sbuild
namespace facet
{
+
namespace
{
+#ifdef SBUILD_FEATURE_UNSHARE
+ feature feature_unshare
+ ("UNSHARE",
+ N_("Linux dissassociation of shared execution context"));
+#endif
+
factory::facet_info unshare_info =
{
"unshare",
diff --git a/lib/sbuild/chroot/facet/userdata.cc b/lib/sbuild/chroot/facet/userdata.cc
index b1c30a04..95182ecd 100644
--- a/lib/sbuild/chroot/facet/userdata.cc
+++ b/lib/sbuild/chroot/facet/userdata.cc
@@ -28,46 +28,6 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
-
-namespace
-{
-
- bool
- validate_keyname(std::string const& key)
- {
- // Valid names consist of one (or more) namespaces which consist
- // of [a-z][a-z0-9] followed by a . (namespace separator). The
- // key name following the separator is [a-z][a-z0-9-]. When
- // converted to an environment variable, all alphabet characters
- // are uppercased, and all periods and hyphens converted to
- // underscores.
- static sbuild::regex permitted("^([a-z][a-z0-9]*\\.)+[a-z][a-z0-9-]*$");
-
- // These would permit clashes with existing setup environment
- // variables, and potentially security issues if they were
- // user-settable.
- static sbuild::regex reserved("^(((auth|chroot|host|libexec|mount|session|status|sysconf)\\..*)|setup.data.dir)$");
-
- return regex_search(key, permitted) && !regex_search(key, reserved);
- }
-
- std::string
- envname(std::string const& key)
- {
- std::string ret(key);
-
- static const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(std::locale::classic());
- for (auto& chr : ret)
- {
- chr = ct.toupper(chr);
- if (chr == '-' || chr == '.')
- chr = '_';
- }
- return ret;
- }
-
-}
namespace sbuild
{
@@ -79,6 +39,40 @@ namespace sbuild
namespace
{
+ bool
+ validate_keyname(std::string const& key)
+ {
+ // Valid names consist of one (or more) namespaces which consist
+ // of [a-z][a-z0-9] followed by a . (namespace separator). The
+ // key name following the separator is [a-z][a-z0-9-]. When
+ // converted to an environment variable, all alphabet characters
+ // are uppercased, and all periods and hyphens converted to
+ // underscores.
+ static sbuild::regex permitted("^([a-z][a-z0-9]*\\.)+[a-z][a-z0-9-]*$");
+
+ // These would permit clashes with existing setup environment
+ // variables, and potentially security issues if they were
+ // user-settable.
+ static sbuild::regex reserved("^(((auth|chroot|host|libexec|mount|session|status|sysconf)\\..*)|setup.data.dir)$");
+
+ return regex_search(key, permitted) && !regex_search(key, reserved);
+ }
+
+ std::string
+ envname(std::string const& key)
+ {
+ std::string ret(key);
+
+ static const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(std::locale::classic());
+ for (auto& chr : ret)
+ {
+ chr = ct.toupper(chr);
+ if (chr == '-' || chr == '.')
+ chr = '_';
+ }
+ return ret;
+ }
+
factory::facet_info userdata_info =
{
"userdata",
diff --git a/lib/sbuild/ctty.cc b/lib/sbuild/ctty.cc
index e707b1b1..b7c12a45 100644
--- a/lib/sbuild/ctty.cc
+++ b/lib/sbuild/ctty.cc
@@ -28,93 +28,96 @@
#include <fcntl.h>
#include <unistd.h>
-using namespace sbuild;
-
-namespace
+namespace sbuild
{
- /**
- * Set close-on-exec flag. An error will be thrown on failure.
- *
- * @param fd the file descriptor to set.
- */
- void
- set_cloexec (int fd)
+ namespace
{
- int flags = fcntl(fd, F_GETFD);
- flags |= FD_CLOEXEC;
- if (fcntl(fd, F_SETFD, flags) < 0)
- throw ctty_error(CTTY_CLOEXEC, strerror(errno));
- }
- /**
- * Open the controlling terminal and return its file descriptor.
- *
- * @returns the CTTY fd, or -1 on failure.
- */
- int
- open_ctty ()
- {
- int ctty = open("/dev/tty", O_RDWR|O_NOCTTY);
- if (ctty >= 0)
- {
- set_cloexec(ctty);
- }
- else
- {
- ctty = -1;
- }
-
- return ctty;
+ /**
+ * Set close-on-exec flag. An error will be thrown on failure.
+ *
+ * @param fd the file descriptor to set.
+ */
+ void
+ set_cloexec (int fd)
+ {
+ int flags = fcntl(fd, F_GETFD);
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) < 0)
+ throw ctty_error(CTTY_CLOEXEC, strerror(errno));
+ }
+
+ /**
+ * Open the controlling terminal and return its file descriptor.
+ *
+ * @returns the CTTY fd, or -1 on failure.
+ */
+ int
+ open_ctty ()
+ {
+ int ctty = open("/dev/tty", O_RDWR|O_NOCTTY);
+ if (ctty >= 0)
+ {
+ set_cloexec(ctty);
+ }
+ else
+ {
+ ctty = -1;
+ }
+
+ return ctty;
+ }
+
}
-}
+ template<>
+ error<ctty_error_code>::map_type
+ error<ctty_error_code>::error_strings =
+ {
+ {sbuild::CTTY_CLOEXEC, N_("The controlling terminal close-on-execute flag could not be set")},
+ {sbuild::CTTY_DUP, N_("The controlling terminal file descriptor could not be duplicated")}
+ };
+
+ const int CTTY_FILENO(open_ctty());
-template<>
-error<ctty_error_code>::map_type
-error<ctty_error_code>::error_strings =
+ namespace
{
- {CTTY_CLOEXEC, N_("The controlling terminal close-on-execute flag could not be set")},
- {CTTY_DUP, N_("The controlling terminal file descriptor could not be duplicated")}
- };
-const int sbuild::CTTY_FILENO(open_ctty());
+ /**
+ * Get the file descriptor for cttybuf. An error will be thrown on
+ * failure.
+ *
+ * @returns the CTTY_FILENO file descriptor if there is a CTTY, or a
+ * duplicated file descriptor for stdin otherwise.
+ */
+ int
+ cttybuf_fd ()
+ {
+ int ctty = CTTY_FILENO;
-namespace
-{
+ if (ctty < 0)
+ {
+ ctty = dup(STDIN_FILENO);
- /**
- * Get the file descriptor for cttybuf. An error will be thrown on
- * failure.
- *
- * @returns the CTTY_FILENO file descriptor if there is a CTTY, or a
- * duplicated file descriptor for stdin otherwise.
- */
- int
- cttybuf_fd ()
- {
- int ctty = CTTY_FILENO;
+ if (ctty < 0)
+ throw ctty_error(CTTY_DUP, strerror(errno));
- if (ctty < 0)
- {
- ctty = dup(STDIN_FILENO);
+ set_cloexec(ctty);
+ }
- if (ctty < 0)
- throw ctty_error(CTTY_DUP, strerror(errno));
+ return ctty;
+ }
- set_cloexec(ctty);
- }
+ /// A streambuf for cctty.
+ // boost::iostreams::file_descriptor cttybuf(cttybuf_fd(), close_handle);
- return ctty;
}
- /// A streambuf for cctty.
- // boost::iostreams::file_descriptor cttybuf(cttybuf_fd(), close_handle);
-
-}
-
#ifdef BOOST_IOSTREAMS_CLOSE_HANDLE_OLD
-fdstream sbuild::cctty(cttybuf_fd(), true);
+ fdstream cctty(cttybuf_fd(), true);
#else
-fdstream sbuild::cctty(cttybuf_fd(), boost::iostreams::close_handle);
+ fdstream cctty(cttybuf_fd(), boost::iostreams::close_handle);
#endif
+
+}
diff --git a/lib/sbuild/environment.cc b/lib/sbuild/environment.cc
index 8754763d..cd7f5599 100644
--- a/lib/sbuild/environment.cc
+++ b/lib/sbuild/environment.cc
@@ -23,147 +23,151 @@
#include <cstring>
using boost::format;
-using namespace sbuild;
-environment::environment ():
- std::map<std::string,std::string>(),
- filter()
+namespace sbuild
{
-}
-
-environment::environment (char **environment):
- std::map<std::string,std::string>()
-{
- add(environment);
-}
-
-environment::~environment ()
-{
-}
-void
-environment::set_filter (regex const& filter)
-{
- this->filter = filter;
-}
+ environment::environment ():
+ std::map<std::string,std::string>(),
+ filter()
+ {
+ }
+
+ environment::environment (char **environment):
+ std::map<std::string,std::string>()
+ {
+ add(environment);
+ }
+
+ environment::~environment ()
+ {
+ }
+
+ void
+ environment::set_filter (regex const& filter)
+ {
+ this->filter = filter;
+ }
+
+ regex const&
+ environment::get_filter () const
+ {
+ return this->filter;
+ }
+
+ void
+ environment::add (char **environment)
+ {
+ if (environment)
+ {
+ for (char **ev = environment; ev != 0 && *ev != 0; ++ev)
+ add(std::string(*ev));
+ }
+ }
+
+ void
+ environment::add (environment const& environment)
+ {
+ for (const auto& env : environment)
+ add(env);
+ }
+
+ void
+ environment::add (std::string const& value)
+ {
+ std::string::size_type pos = value.find('=');
+ if (pos != std::string::npos && pos != 0)
+ {
+ std::string key = value.substr(0, pos);
+ std::string val;
+ if (pos < value.length())
+ val = value.substr(pos + 1);
+ add(std::make_pair(key, val));
+ }
+ else
+ {
+ add(std::make_pair(value, std::string()));
+ }
+ }
+
+ void
+ environment::add (value_type const& value)
+ {
+ remove(value);
+ if (!value.first.empty() && !value.second.empty())
+ {
+ if (this->filter.str().empty() ||
+ !regex_search(value.first, this->filter))
+ {
+ insert(value);
+ log_debug(DEBUG_NOTICE) << "Inserted into environment: "
+ << value.first << '=' << value.second
+ << std::endl;
+ }
+ else
+ log_debug(DEBUG_INFO) << "Filtered from environment: " << value.first
+ << std::endl;
+ }
+ }
+
+ void
+ environment::remove (char **environment)
+ {
+ if (environment)
+ {
+ for (char **ev = environment; ev != 0 && *ev != 0; ++ev)
+ remove(std::string(*ev));
+ }
+ }
+
+ void
+ environment::remove (environment const& environment)
+ {
+ for (const auto& env : environment)
+ remove(env);
+ }
+
+ void
+ environment::remove (std::string const& value)
+ {
+ std::string::size_type pos = value.find('=');
+ if (pos != std::string::npos && pos != 0)
+ {
+ std::string key = value.substr(0, pos);
+ std::string val;
+ if (pos < value.length())
+ val = value.substr(pos + 1);
+ remove(std::make_pair(key, val));
+ }
+ else
+ {
+ remove(std::make_pair(value, std::string()));
+ }
+ }
+
+ void
+ environment::remove (value_type const& value)
+ {
+ iterator pos = find(value.first);
+ if (pos != end())
+ erase(pos);
+ }
+
+ char **
+ environment::get_strv () const
+ {
+ char **ret = new char *[size() + 1];
+
+ size_type idx = 0;
+ for (const_iterator pos = begin(); pos != end(); ++pos, ++idx)
+ {
+ std::string envitem = pos->first + "=" + pos->second;
+ ret[idx] = new char[envitem.length() + 1];
+ std::strcpy(ret[idx], envitem.c_str());
+ }
+ ret[size()] = 0;
+
+ return ret;
+ }
-regex const&
-environment::get_filter () const
-{
- return this->filter;
-}
-
-void
-environment::add (char **environment)
-{
- if (environment)
- {
- for (char **ev = environment; ev != 0 && *ev != 0; ++ev)
- add(std::string(*ev));
- }
-}
-
-void
-environment::add (environment const& environment)
-{
- for (const auto& env : environment)
- add(env);
-}
-
-void
-environment::add (std::string const& value)
-{
- std::string::size_type pos = value.find('=');
- if (pos != std::string::npos && pos != 0)
- {
- std::string key = value.substr(0, pos);
- std::string val;
- if (pos < value.length())
- val = value.substr(pos + 1);
- add(std::make_pair(key, val));
- }
- else
- {
- add(std::make_pair(value, std::string()));
- }
-}
-
-void
-environment::add (value_type const& value)
-{
- remove(value);
- if (!value.first.empty() && !value.second.empty())
- {
- if (this->filter.str().empty() ||
- !regex_search(value.first, this->filter))
- {
- insert(value);
- log_debug(DEBUG_NOTICE) << "Inserted into environment: "
- << value.first << '=' << value.second
- << std::endl;
- }
- else
- log_debug(DEBUG_INFO) << "Filtered from environment: " << value.first
- << std::endl;
- }
-}
-
-void
-environment::remove (char **environment)
-{
- if (environment)
- {
- for (char **ev = environment; ev != 0 && *ev != 0; ++ev)
- remove(std::string(*ev));
- }
-}
-
-void
-environment::remove (environment const& environment)
-{
- for (const auto& env : environment)
- remove(env);
-}
-
-void
-environment::remove (std::string const& value)
-{
- std::string::size_type pos = value.find('=');
- if (pos != std::string::npos && pos != 0)
- {
- std::string key = value.substr(0, pos);
- std::string val;
- if (pos < value.length())
- val = value.substr(pos + 1);
- remove(std::make_pair(key, val));
- }
- else
- {
- remove(std::make_pair(value, std::string()));
- }
-}
-
-void
-environment::remove (value_type const& value)
-{
- iterator pos = find(value.first);
- if (pos != end())
- erase(pos);
-}
-
-char **
-environment::get_strv () const
-{
- char **ret = new char *[size() + 1];
-
- size_type idx = 0;
- for (const_iterator pos = begin(); pos != end(); ++pos, ++idx)
- {
- std::string envitem = pos->first + "=" + pos->second;
- ret[idx] = new char[envitem.length() + 1];
- std::strcpy(ret[idx], envitem.c_str());
- }
- ret[size()] = 0;
-
- return ret;
}
diff --git a/lib/sbuild/feature.cc b/lib/sbuild/feature.cc
index 13f53036..d1583e8f 100644
--- a/lib/sbuild/feature.cc
+++ b/lib/sbuild/feature.cc
@@ -23,33 +23,36 @@
#include <sbuild/feature.h>
#include <sbuild/i18n.h>
-using namespace sbuild;
-
-feature::feature(std::string const& feature,
- std::string const& description)
+namespace sbuild
{
- registered_features().insert(std::make_pair(feature, description));
-}
-feature::~feature()
-{
-}
+ feature::feature(std::string const& feature,
+ std::string const& description)
+ {
+ registered_features().insert(std::make_pair(feature, description));
+ }
-std::ostream&
-feature::print_features(std::ostream& stream)
-{
- boost::format fmt(" %1$-12s %2%\n");
+ feature::~feature()
+ {
+ }
- std::map<std::string,std::string>& features = registered_features();
- for (const auto& feature : features)
- stream << fmt % feature.first % gettext(feature.second);
+ std::ostream&
+ feature::print_features(std::ostream& stream)
+ {
+ boost::format fmt(" %1$-12s %2%\n");
- return stream;
-}
+ std::map<std::string,std::string>& features = registered_features();
+ for (const auto& feature : features)
+ stream << fmt % feature.first % gettext(feature.second);
+
+ return stream;
+ }
+
+ std::map<std::string,std::string>&
+ feature::registered_features ()
+ {
+ static std::map<std::string,std::string> features;
+ return features;
+ }
-std::map<std::string,std::string>&
-feature::registered_features ()
-{
- static std::map<std::string,std::string> features;
- return features;
}
diff --git a/lib/sbuild/format-detail.cc b/lib/sbuild/format-detail.cc
index d38ecfea..eda875c7 100644
--- a/lib/sbuild/format-detail.cc
+++ b/lib/sbuild/format-detail.cc
@@ -24,70 +24,73 @@
#include <boost/format.hpp>
-using namespace sbuild;
-
-format_detail::format_detail (std::string const& title,
- std::locale locale):
- title(title),
- locale(locale),
- items()
+namespace sbuild
{
-}
-format_detail::~format_detail ()
-{
-}
+ format_detail::format_detail (std::string const& title,
+ std::locale locale):
+ title(title),
+ locale(locale),
+ items()
+ {
+ }
-format_detail&
-format_detail::add (std::string const& name,
- std::string const& value)
-{
- for (const auto& item : this->items)
- {
- if (item.first == name)
- {
- log_debug(DEBUG_WARNING) << "format_detail: name \""
- << name << "\" is already added"
- << std::endl;
- return *this;
- }
- }
+ format_detail::~format_detail ()
+ {
+ }
- this->items.push_back(value_type(name, value));
- log_debug(DEBUG_INFO) << "format_detail: added name \""
- << name << "\""
- << std::endl;
+ format_detail&
+ format_detail::add (std::string const& name,
+ std::string const& value)
+ {
+ for (const auto& item : this->items)
+ {
+ if (item.first == name)
+ {
+ log_debug(DEBUG_WARNING) << "format_detail: name \""
+ << name << "\" is already added"
+ << std::endl;
+ return *this;
+ }
+ }
- return *this;
-}
+ this->items.push_back(value_type(name, value));
+ log_debug(DEBUG_INFO) << "format_detail: added name \""
+ << name << "\""
+ << std::endl;
-format_detail&
-format_detail::add (std::string const& name,
- bool value)
-{
- const char *desc = 0;
- if (value)
- desc = _("true");
- else
- desc = _("false");
+ return *this;
+ }
- return add(name, std::string(desc));
-}
+ format_detail&
+ format_detail::add (std::string const& name,
+ bool value)
+ {
+ const char *desc = 0;
+ if (value)
+ desc = _("true");
+ else
+ desc = _("false");
-format_detail&
-format_detail::add (std::string const& name,
- string_list const& value)
-{
- return add(name, string_list_to_string(value, " "));
-}
+ return add(name, std::string(desc));
+ }
-std::string
-format_detail::get_title () const
-{
- // TRANSLATORS: %1% = title of section
- // TRANSLATORS: Please format the --- as a continuous line, e.g. U+2500
- boost::format fmt(_("─── %1% ───"));
- fmt %this->title;
+ format_detail&
+ format_detail::add (std::string const& name,
+ string_list const& value)
+ {
+ return add(name, string_list_to_string(value, " "));
+ }
+
+ std::string
+ format_detail::get_title () const
+ {
+ // TRANSLATORS: %1% = title of section
+ // TRANSLATORS: Please format the --- as a continuous line, e.g. U+2500
+ boost::format fmt(_("─── %1% ───"));
+ fmt %this->title;
+
+ return fmt.str();
+ }
- return fmt.str();
}
diff --git a/lib/sbuild/keyfile-reader.cc b/lib/sbuild/keyfile-reader.cc
index 237d286a..ec62c596 100644
--- a/lib/sbuild/keyfile-reader.cc
+++ b/lib/sbuild/keyfile-reader.cc
@@ -22,166 +22,169 @@
#include <sbuild/keyfile-reader.h>
-using namespace sbuild;
-
-keyfile_reader::keyfile_reader(keyfile& store):
- store(store),
- group(),
- group_set(false),
- key(),
- key_set(false),
- value(),
- value_set(false),
- comment(),
- comment_set(false),
- line_number(0)
-{}
-
-keyfile_reader::keyfile_reader (keyfile& store,
- std::string const& file):
- keyfile_reader(store)
+namespace sbuild
{
- std::ifstream fs(file.c_str());
- if (fs)
- {
- fs.imbue(std::locale::classic());
- read_stream(fs);
- }
- else
- {
- throw error(file, keyfile::BAD_FILE);
- }
-}
-
-keyfile_reader::keyfile_reader (keyfile& store,
- std::istream& stream):
- keyfile_reader(store)
-{
- read_stream(stream);
-}
-
-keyfile_reader::~keyfile_reader()
-{}
-
-void
-keyfile_reader::read_stream(std::istream& stream)
-{
- keyfile tmp;
- std::string line;
-
- begin();
-
- while (std::getline(stream, line))
- {
- parse_line(line);
-
- // Insert group
- if (this->group_set)
- {
- if (tmp.has_group(this->group))
- throw error(this->line_number, keyfile::DUPLICATE_GROUP, this->group);
- else
- tmp.set_group(this->group, this->comment, this->line_number);
- }
-
- // Insert item
- if (this->key_set && this->value_set)
- {
- if (tmp.has_key(this->group, this->key))
- throw error(this->line_number, this->group, keyfile::DUPLICATE_KEY, this->key);
- else
- tmp.set_value(this->group, this->key, this->value, this->comment, this->line_number);
- }
- }
-
- end();
-
- // TODO: do inserts here as well.
-
- this->store += tmp;
-}
-void
-keyfile_reader::begin()
-{
- line_number = 0;
-}
+ keyfile_reader::keyfile_reader(keyfile& store):
+ store(store),
+ group(),
+ group_set(false),
+ key(),
+ key_set(false),
+ value(),
+ value_set(false),
+ comment(),
+ comment_set(false),
+ line_number(0)
+ {}
+
+ keyfile_reader::keyfile_reader (keyfile& store,
+ std::string const& file):
+ keyfile_reader(store)
+ {
+ std::ifstream fs(file.c_str());
+ if (fs)
+ {
+ fs.imbue(std::locale::classic());
+ read_stream(fs);
+ }
+ else
+ {
+ throw error(file, keyfile::BAD_FILE);
+ }
+ }
+
+ keyfile_reader::keyfile_reader (keyfile& store,
+ std::istream& stream):
+ keyfile_reader(store)
+ {
+ read_stream(stream);
+ }
+
+ keyfile_reader::~keyfile_reader()
+ {}
+
+ void
+ keyfile_reader::read_stream(std::istream& stream)
+ {
+ keyfile tmp;
+ std::string line;
+
+ begin();
+
+ while (std::getline(stream, line))
+ {
+ parse_line(line);
+
+ // Insert group
+ if (this->group_set)
+ {
+ if (tmp.has_group(this->group))
+ throw error(this->line_number, keyfile::DUPLICATE_GROUP, this->group);
+ else
+ tmp.set_group(this->group, this->comment, this->line_number);
+ }
+
+ // Insert item
+ if (this->key_set && this->value_set)
+ {
+ if (tmp.has_key(this->group, this->key))
+ throw error(this->line_number, this->group, keyfile::DUPLICATE_KEY, this->key);
+ else
+ tmp.set_value(this->group, this->key, this->value, this->comment, this->line_number);
+ }
+ }
+
+ end();
+
+ // TODO: do inserts here as well.
+
+ this->store += tmp;
+ }
+
+ void
+ keyfile_reader::begin()
+ {
+ line_number = 0;
+ }
+
+ void
+ keyfile_reader::parse_line (std::string const& line)
+ {
+ if (comment_set == true)
+ {
+ comment.clear();
+ comment_set = false;
+ }
+ if (group_set == true)
+ {
+ // The group isn't cleared
+ group_set = false;
+ }
+ if (key_set == true)
+ {
+ key.clear();
+ key_set = false;
+ }
+ if (value_set == true)
+ {
+ value.clear();
+ value_set = false;
+ }
+
+ if (line.length() == 0)
+ {
+ // Empty line; do nothing.
+ }
+ else if (line[0] == '#') // Comment line
+ {
+ if (!comment.empty())
+ comment += '\n';
+ comment += line.substr(1);
+ }
+ else if (line[0] == '[') // Group
+ {
+ std::string::size_type fpos = line.find_first_of(']');
+ std::string::size_type lpos = line.find_last_of(']');
+ if (fpos == std::string::npos || lpos == std::string::npos ||
+ fpos != lpos)
+ throw error(line_number, keyfile::INVALID_GROUP, line);
+ group = line.substr(1, fpos - 1);
+
+ if (group.length() == 0)
+ throw error(line_number, keyfile::INVALID_GROUP, line);
+
+ comment_set = true;
+ group_set = true;
+ }
+ else // Item
+ {
+ std::string::size_type pos = line.find_first_of('=');
+ if (pos == std::string::npos)
+ throw error(line_number, keyfile::INVALID_LINE, line);
+ if (pos == 0)
+ throw error(line_number, keyfile::NO_KEY, line);
+ key = line.substr(0, pos);
+ if (pos == line.length() - 1)
+ value = "";
+ else
+ value = line.substr(pos + 1);
+
+ // No group specified
+ if (group.empty())
+ throw error(line_number, keyfile::NO_GROUP, line);
+
+ comment_set = true;
+ key_set = true;
+ value_set = true;
+ }
+
+ ++line_number;
+ }
+
+ void
+ keyfile_reader::end()
+ {
+ }
-void
-keyfile_reader::parse_line (std::string const& line)
-{
- if (comment_set == true)
- {
- comment.clear();
- comment_set = false;
- }
- if (group_set == true)
- {
- // The group isn't cleared
- group_set = false;
- }
- if (key_set == true)
- {
- key.clear();
- key_set = false;
- }
- if (value_set == true)
- {
- value.clear();
- value_set = false;
- }
-
- if (line.length() == 0)
- {
- // Empty line; do nothing.
- }
- else if (line[0] == '#') // Comment line
- {
- if (!comment.empty())
- comment += '\n';
- comment += line.substr(1);
- }
- else if (line[0] == '[') // Group
- {
- std::string::size_type fpos = line.find_first_of(']');
- std::string::size_type lpos = line.find_last_of(']');
- if (fpos == std::string::npos || lpos == std::string::npos ||
- fpos != lpos)
- throw error(line_number, keyfile::INVALID_GROUP, line);
- group = line.substr(1, fpos - 1);
-
- if (group.length() == 0)
- throw error(line_number, keyfile::INVALID_GROUP, line);
-
- comment_set = true;
- group_set = true;
- }
- else // Item
- {
- std::string::size_type pos = line.find_first_of('=');
- if (pos == std::string::npos)
- throw error(line_number, keyfile::INVALID_LINE, line);
- if (pos == 0)
- throw error(line_number, keyfile::NO_KEY, line);
- key = line.substr(0, pos);
- if (pos == line.length() - 1)
- value = "";
- else
- value = line.substr(pos + 1);
-
- // No group specified
- if (group.empty())
- throw error(line_number, keyfile::NO_GROUP, line);
-
- comment_set = true;
- key_set = true;
- value_set = true;
- }
-
- ++line_number;
-}
-
-void
-keyfile_reader::end()
-{
}
diff --git a/lib/sbuild/keyfile-writer.cc b/lib/sbuild/keyfile-writer.cc
index b3a62552..c00ca000 100644
--- a/lib/sbuild/keyfile-writer.cc
+++ b/lib/sbuild/keyfile-writer.cc
@@ -22,92 +22,94 @@
#include <sbuild/keyfile-writer.h>
-using namespace sbuild;
-
-keyfile_writer::keyfile_writer(keyfile const& store):
- store(store)
-{}
-
-keyfile_writer::keyfile_writer (keyfile const& store,
- std::string const& file):
- keyfile_writer(store)
-{
- std::ofstream fs(file.c_str());
- if (fs)
- {
- fs.imbue(std::locale::classic());
- write_stream(fs);
- }
- else
- {
- throw error(file, keyfile::BAD_FILE);
- }
-}
-
-keyfile_writer::keyfile_writer (keyfile const& store,
- std::ostream& stream):
- keyfile_writer(store)
-{
- write_stream(stream);
-}
-
-keyfile_writer::~keyfile_writer()
-{}
-
-void
-keyfile_writer::write_stream(std::ostream& stream) const
+namespace sbuild
{
- keyfile::size_type group_count = 0;
- for (const auto& group : this->store.get_groups())
- {
- if (group_count > 0)
- stream << '\n';
- ++group_count;
+ keyfile_writer::keyfile_writer(keyfile const& store):
+ store(store)
+ {}
+
+ keyfile_writer::keyfile_writer (keyfile const& store,
+ std::string const& file):
+ keyfile_writer(store)
+ {
+ std::ofstream fs(file.c_str());
+ if (fs)
+ {
+ fs.imbue(std::locale::classic());
+ write_stream(fs);
+ }
+ else
+ {
+ throw error(file, keyfile::BAD_FILE);
+ }
+ }
+
+ keyfile_writer::keyfile_writer (keyfile const& store,
+ std::ostream& stream):
+ keyfile_writer(store)
+ {
+ write_stream(stream);
+ }
+
+ keyfile_writer::~keyfile_writer()
+ {}
+
+ void
+ keyfile_writer::write_stream(std::ostream& stream) const
+ {
+ keyfile::size_type group_count = 0;
+
+ for (const auto& group : this->store.get_groups())
+ {
+ if (group_count > 0)
+ stream << '\n';
+ ++group_count;
+
+ keyfile::comment_type comment = this->store.get_comment(group);
+
+ if (comment.length() > 0)
+ print_comment(comment, stream);
+
+ stream << '[' << group << ']' << '\n';
+
+ for (const auto& key : this->store.get_keys(group))
+ {
+ std::string value;
+ this->store.get_value(group, key, value);
+ keyfile::comment_type comment = this->store.get_comment(group, key);
+
+ if (comment.length() > 0)
+ print_comment(comment, stream);
+
+ stream << key << '=' << value << '\n';
+ }
+ }
+ }
+
+ void
+ sbuild::keyfile_writer::print_comment (keyfile::comment_type const& comment,
+ std::ostream& stream)
+ {
+ std::string::size_type last_pos = 0;
+ std::string::size_type pos = comment.find_first_of('\n', last_pos);
+
+ while (1)
+ {
+ if (last_pos == pos)
+ stream << "#\n";
+ else
+ stream << '#' << comment.substr(last_pos, pos - last_pos) << '\n';
+
+ // Find next
+ if (pos < comment.length() - 1)
+ {
+ last_pos = pos + 1;
+ pos = comment.find_first_of('\n', last_pos);
+ }
+ else
+ break;
+ }
+ }
- keyfile::comment_type comment = this->store.get_comment(group);
-
- if (comment.length() > 0)
- print_comment(comment, stream);
-
- stream << '[' << group << ']' << '\n';
-
- for (const auto& key : this->store.get_keys(group))
- {
- std::string value;
- this->store.get_value(group, key, value);
- keyfile::comment_type comment = this->store.get_comment(group, key);
-
- if (comment.length() > 0)
- print_comment(comment, stream);
-
- stream << key << '=' << value << '\n';
- }
- }
}
-
-void
-sbuild::keyfile_writer::print_comment (keyfile::comment_type const& comment,
- std::ostream& stream)
-{
- std::string::size_type last_pos = 0;
- std::string::size_type pos = comment.find_first_of('\n', last_pos);
-
- while (1)
- {
- if (last_pos == pos)
- stream << "#\n";
- else
- stream << '#' << comment.substr(last_pos, pos - last_pos) << '\n';
-
- // Find next
- if (pos < comment.length() - 1)
- {
- last_pos = pos + 1;
- pos = comment.find_first_of('\n', last_pos);
- }
- else
- break;
- }
-}
-
diff --git a/lib/sbuild/keyfile.cc b/lib/sbuild/keyfile.cc
index 7d74b2f9..cd648ab7 100644
--- a/lib/sbuild/keyfile.cc
+++ b/lib/sbuild/keyfile.cc
@@ -27,501 +27,498 @@
using boost::format;
-using namespace sbuild;
-
-template<>
-error<keyfile::error_code>::map_type
-error<keyfile::error_code>::error_strings =
- {
- // TRANSLATORS: %1% = file
- {keyfile::BAD_FILE,
- N_("Can't open file ‘%1%’")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::DEPRECATED_KEY,
- N_("line %1% [%2%]: Deprecated key ‘%4%’ used")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::DEPRECATED_KEY_NL,
- N_("[%1%]: Deprecated key ‘%4%’ used")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::DISALLOWED_KEY,
- N_("line %1% [%2%]: Disallowed key ‘%4%’ used")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::DISALLOWED_KEY_NL,
- N_("[%1%]: Disallowed key ‘%4%’ used")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %4% = group name ("[groupname]" in configuration file)
- {keyfile::DUPLICATE_GROUP,
- N_("line %1%: Duplicate group ‘%4%’")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::DUPLICATE_KEY,
- N_("line %1% [%2%]: Duplicate key ‘%4%’")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %4% = line contents as read from the configuration file
- {keyfile::INVALID_GROUP,
- N_("line %1%: Invalid group: “%4%”")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::INVALID_KEY,
- N_("line %1% [%2%]: Invalid key ‘%4%’ used")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %4% = line contents as read from the configuration file
- {keyfile::INVALID_LINE,
- N_("line %1%: Invalid line: “%4%”")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::MISSING_KEY,
- N_("line %1% [%2%]: Required key ‘%4%’ is missing")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::MISSING_KEY_NL,
- N_("[%1%]: Required key ‘%4%’ is missing")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %4% = line contents as read from the configuration file
- {keyfile::NO_GROUP,
- N_("line %1%: No group specified: “%4%”")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %4% = line contents as read from the configuration file
- {keyfile::NO_KEY,
- N_("line %1%: No key specified: “%4%”")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::OBSOLETE_KEY,
- N_("line %1% [%2%]: Obsolete key ‘%4%’ used")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::OBSOLETE_KEY_NL,
- N_("[%1%]: Obsolete key ‘%4%’ used")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = additional details
- {keyfile::PASSTHROUGH_G,
- N_("[%1%]: %4%")},
- // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %2% = key name ("keyname=value" in configuration file)
- // TRANSLATORS: %4% = additional details
- {keyfile::PASSTHROUGH_GK,
- N_("[%1%] %2%: %4%")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = additional details
- {keyfile::PASSTHROUGH_LG,
- N_("line %1% [%2%]: %4%")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %3% = key name ("keyname=value" in configuration file)
- // TRANSLATORS: %4% = additional details
- {keyfile::PASSTHROUGH_LGK,
- N_("line %1% [%2%] %3%: %4%")},
- // TRANSLATORS: %1% = line number in configuration file
- // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
- // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
- {keyfile::UNKNOWN_KEY,
- N_("line %1% [%2%]: Unknown key ‘%4%’ used")}
- };
-
-sbuild::keyfile::keyfile ():
- groups(),
- separator(",")
-{
-}
-
-sbuild::keyfile::~keyfile()
-{
-}
-
-sbuild::keyfile::group_list
-sbuild::keyfile::get_groups () const
+namespace sbuild
{
- group_list ret;
- for (const auto& group : this->groups)
- ret.push_back(group.first);
-
- return ret;
-}
-
-sbuild::keyfile::key_list
-sbuild::keyfile::get_keys (group_name_type const& group) const
-{
- key_list ret;
-
- const group_type *found_group = find_group(group);
- if (found_group)
+ template<>
+ error<keyfile::error_code>::map_type
+ error<keyfile::error_code>::error_strings =
{
- item_map_type const& items(std::get<1>(*found_group));
- for (const auto& item : items)
- ret.push_back(item.first);
- }
-
- return ret;
-}
-
-void
-sbuild::keyfile::check_keys (group_name_type const& group,
- key_list const& keys) const
-{
- const string_list total(get_keys(group));
+ // TRANSLATORS: %1% = file
+ {keyfile::BAD_FILE,
+ N_("Can't open file ‘%1%’")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::DEPRECATED_KEY,
+ N_("line %1% [%2%]: Deprecated key ‘%4%’ used")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::DEPRECATED_KEY_NL,
+ N_("[%1%]: Deprecated key ‘%4%’ used")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::DISALLOWED_KEY,
+ N_("line %1% [%2%]: Disallowed key ‘%4%’ used")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::DISALLOWED_KEY_NL,
+ N_("[%1%]: Disallowed key ‘%4%’ used")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %4% = group name ("[groupname]" in configuration file)
+ {keyfile::DUPLICATE_GROUP,
+ N_("line %1%: Duplicate group ‘%4%’")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::DUPLICATE_KEY,
+ N_("line %1% [%2%]: Duplicate key ‘%4%’")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %4% = line contents as read from the configuration file
+ {keyfile::INVALID_GROUP,
+ N_("line %1%: Invalid group: “%4%”")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::INVALID_KEY,
+ N_("line %1% [%2%]: Invalid key ‘%4%’ used")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %4% = line contents as read from the configuration file
+ {keyfile::INVALID_LINE,
+ N_("line %1%: Invalid line: “%4%”")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::MISSING_KEY,
+ N_("line %1% [%2%]: Required key ‘%4%’ is missing")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::MISSING_KEY_NL,
+ N_("[%1%]: Required key ‘%4%’ is missing")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %4% = line contents as read from the configuration file
+ {keyfile::NO_GROUP,
+ N_("line %1%: No group specified: “%4%”")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %4% = line contents as read from the configuration file
+ {keyfile::NO_KEY,
+ N_("line %1%: No key specified: “%4%”")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::OBSOLETE_KEY,
+ N_("line %1% [%2%]: Obsolete key ‘%4%’ used")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::OBSOLETE_KEY_NL,
+ N_("[%1%]: Obsolete key ‘%4%’ used")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = additional details
+ {keyfile::PASSTHROUGH_G,
+ N_("[%1%]: %4%")},
+ // TRANSLATORS: %1% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %2% = key name ("keyname=value" in configuration file)
+ // TRANSLATORS: %4% = additional details
+ {keyfile::PASSTHROUGH_GK,
+ N_("[%1%] %2%: %4%")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = additional details
+ {keyfile::PASSTHROUGH_LG,
+ N_("line %1% [%2%]: %4%")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %3% = key name ("keyname=value" in configuration file)
+ // TRANSLATORS: %4% = additional details
+ {keyfile::PASSTHROUGH_LGK,
+ N_("line %1% [%2%] %3%: %4%")},
+ // TRANSLATORS: %1% = line number in configuration file
+ // TRANSLATORS: %2% = group name ("[groupname]" in configuration file)
+ // TRANSLATORS: %4% = key name ("keyname=value" in configuration file)
+ {keyfile::UNKNOWN_KEY,
+ N_("line %1% [%2%]: Unknown key ‘%4%’ used")}
+ };
+
+ sbuild::keyfile::keyfile ():
+ groups(),
+ separator(",")
+ {
+ }
- const string_set a(total.begin(), total.end());
- const string_set b(keys.begin(), keys.end());
+ sbuild::keyfile::~keyfile()
+ {
+ }
- string_set unused;
+ sbuild::keyfile::group_list
+ sbuild::keyfile::get_groups () const
+ {
+ group_list ret;
- set_difference(a.begin(), a.end(),
- b.begin(), b.end(),
- inserter(unused, unused.begin()));
+ for (const auto& group : this->groups)
+ ret.push_back(group.first);
- for (const auto& item : unused)
- {
- size_type line = get_line(group, item);
- error e(line, group, UNKNOWN_KEY, item);
- e.set_reason(_("This option may be present in a newer version"));
- log_exception_warning(e);
- }
-}
+ return ret;
+ }
-bool
-sbuild::keyfile::has_group (group_name_type const& group) const
-{
- return (find_group(group) != 0);
-}
+ sbuild::keyfile::key_list
+ sbuild::keyfile::get_keys (group_name_type const& group) const
+ {
+ key_list ret;
+
+ const group_type *found_group = find_group(group);
+ if (found_group)
+ {
+ item_map_type const& items(std::get<1>(*found_group));
+ for (const auto& item : items)
+ ret.push_back(item.first);
+ }
+
+ return ret;
+ }
+
+ void
+ sbuild::keyfile::check_keys (group_name_type const& group,
+ key_list const& keys) const
+ {
+ const string_list total(get_keys(group));
-bool
-sbuild::keyfile::has_key (group_name_type const& group,
- key_type const& key) const
-{
- return (find_item(group, key) != 0);
-}
+ const string_set a(total.begin(), total.end());
+ const string_set b(keys.begin(), keys.end());
-void
-sbuild::keyfile::set_group (group_name_type const& group,
- comment_type const& comment)
-{
- set_group(group, comment, 0);
-}
+ string_set unused;
-void
-sbuild::keyfile::set_group (group_name_type const& group,
- comment_type const& comment,
- size_type line)
-{
- if (!has_group(group))
- this->groups.insert
- (group_map_type::value_type(group,
- group_type(group,
- item_map_type(),
- comment,
- line)));
-}
+ set_difference(a.begin(), a.end(),
+ b.begin(), b.end(),
+ inserter(unused, unused.begin()));
-sbuild::keyfile::comment_type
-sbuild::keyfile::get_comment (group_name_type const& group) const
-{
- const group_type *found_group = find_group(group);
- if (found_group)
- return std::get<2>(*found_group);
- else
- return comment_type();
-}
+ for (const auto& item : unused)
+ {
+ size_type line = get_line(group, item);
+ error e(line, group, UNKNOWN_KEY, item);
+ e.set_reason(_("This option may be present in a newer version"));
+ log_exception_warning(e);
+ }
+ }
-sbuild::keyfile::comment_type
-sbuild::keyfile::get_comment (group_name_type const& group,
- key_type const& key) const
-{
- const item_type *found_item = find_item(group, key);
- if (found_item)
- return std::get<2>(*found_item);
- else
- return comment_type();
-}
+ bool
+ sbuild::keyfile::has_group (group_name_type const& group) const
+ {
+ return (find_group(group) != 0);
+ }
-sbuild::keyfile::size_type
-sbuild::keyfile::get_line (group_name_type const& group) const
-{
- const group_type *found_group = find_group(group);
- if (found_group)
- return std::get<3>(*found_group);
- else
- return 0;
-}
+ bool
+ sbuild::keyfile::has_key (group_name_type const& group,
+ key_type const& key) const
+ {
+ return (find_item(group, key) != 0);
+ }
-sbuild::keyfile::size_type
-sbuild::keyfile::get_line (group_name_type const& group,
- key_type const& key) const
-{
- const item_type *found_item = find_item(group, key);
- if (found_item)
- return std::get<3>(*found_item);
- else
- return 0;
-}
+ void
+ sbuild::keyfile::set_group (group_name_type const& group,
+ comment_type const& comment)
+ {
+ set_group(group, comment, 0);
+ }
-bool
-sbuild::keyfile::get_locale_string (group_name_type const& group,
- key_type const& key,
- value_type& value) const
-{
- std::string localename;
- try
- {
- localename = std::locale("").name();
- }
- catch (std::runtime_error const& e) // Invalid locale
- {
- localename = std::locale::classic().name();
- }
- std::string::size_type pos;
- bool status = false;
-
- // Strip off any charset.
- if ((pos = localename.find_first_of('.')) != std::string::npos)
- localename = localename.substr(0, pos);
- status = get_locale_string(group, key, localename, value);
-
- // Strip off territory.
- if (status == false &&
- (pos = localename.find_first_of('_')) != std::string::npos)
- {
+ void
+ sbuild::keyfile::set_group (group_name_type const& group,
+ comment_type const& comment,
+ size_type line)
+ {
+ if (!has_group(group))
+ this->groups.insert
+ (group_map_type::value_type(group,
+ group_type(group,
+ item_map_type(),
+ comment,
+ line)));
+ }
+
+ sbuild::keyfile::comment_type
+ sbuild::keyfile::get_comment (group_name_type const& group) const
+ {
+ const group_type *found_group = find_group(group);
+ if (found_group)
+ return std::get<2>(*found_group);
+ else
+ return comment_type();
+ }
+
+ sbuild::keyfile::comment_type
+ sbuild::keyfile::get_comment (group_name_type const& group,
+ key_type const& key) const
+ {
+ const item_type *found_item = find_item(group, key);
+ if (found_item)
+ return std::get<2>(*found_item);
+ else
+ return comment_type();
+ }
+
+ sbuild::keyfile::size_type
+ sbuild::keyfile::get_line (group_name_type const& group) const
+ {
+ const group_type *found_group = find_group(group);
+ if (found_group)
+ return std::get<3>(*found_group);
+ else
+ return 0;
+ }
+
+ sbuild::keyfile::size_type
+ sbuild::keyfile::get_line (group_name_type const& group,
+ key_type const& key) const
+ {
+ const item_type *found_item = find_item(group, key);
+ if (found_item)
+ return std::get<3>(*found_item);
+ else
+ return 0;
+ }
+
+ bool
+ sbuild::keyfile::get_locale_string (group_name_type const& group,
+ key_type const& key,
+ value_type& value) const
+ {
+ std::string localename;
+ try
+ {
+ localename = std::locale("").name();
+ }
+ catch (std::runtime_error const& e) // Invalid locale
+ {
+ localename = std::locale::classic().name();
+ }
+ std::string::size_type pos;
+ bool status = false;
+
+ // Strip off any charset.
+ if ((pos = localename.find_first_of('.')) != std::string::npos)
localename = localename.substr(0, pos);
- status = get_locale_string(group, key, localename, value);
- }
-
- // Fall back to non-localised version.
- if (status == false)
- status = get_value(group, key, value);
-
- return status;
-}
-
-bool
-sbuild::keyfile::get_locale_string (group_name_type const& group,
- key_type const& key,
- priority priority,
- value_type& value) const
-{
- bool status = get_locale_string(group, key, value);
- check_priority(group, key, priority, status);
- return status;
-}
-
-bool
-sbuild::keyfile::get_locale_string (group_name_type const& group,
- key_type const& key,
- std::string const& locale,
- value_type& value) const
-{
- std::string lkey = key + '[' + locale + ']';
- return get_value(group, lkey, value);
-}
-
-bool
-sbuild::keyfile::get_locale_string (group_name_type const& group,
- key_type const& key,
- std::string const& locale,
- priority priority,
- value_type& value) const
-{
- bool status = get_locale_string(group, key, locale, value);
- check_priority(group, key, priority, status);
- return status;
-}
-
-void
-sbuild::keyfile::remove_group (group_name_type const& group)
-{
- group_map_type::iterator pos = this->groups.find(group);
- if (pos != this->groups.end())
- this->groups.erase(pos);
-}
-
-void
-sbuild::keyfile::remove_key (group_name_type const& group,
- key_type const& key)
-{
- group_type *found_group = find_group(group);
- if (found_group)
- {
- item_map_type& items = std::get<1>(*found_group);
- item_map_type::iterator pos = items.find(key);
- if (pos != items.end())
- items.erase(pos);
- }
-}
+ status = get_locale_string(group, key, localename, value);
+
+ // Strip off territory.
+ if (status == false &&
+ (pos = localename.find_first_of('_')) != std::string::npos)
+ {
+ localename = localename.substr(0, pos);
+ status = get_locale_string(group, key, localename, value);
+ }
+
+ // Fall back to non-localised version.
+ if (status == false)
+ status = get_value(group, key, value);
+
+ return status;
+ }
+
+ bool
+ sbuild::keyfile::get_locale_string (group_name_type const& group,
+ key_type const& key,
+ priority priority,
+ value_type& value) const
+ {
+ bool status = get_locale_string(group, key, value);
+ check_priority(group, key, priority, status);
+ return status;
+ }
+
+ bool
+ sbuild::keyfile::get_locale_string (group_name_type const& group,
+ key_type const& key,
+ std::string const& locale,
+ value_type& value) const
+ {
+ std::string lkey = key + '[' + locale + ']';
+ return get_value(group, lkey, value);
+ }
+
+ bool
+ sbuild::keyfile::get_locale_string (group_name_type const& group,
+ key_type const& key,
+ std::string const& locale,
+ priority priority,
+ value_type& value) const
+ {
+ bool status = get_locale_string(group, key, locale, value);
+ check_priority(group, key, priority, status);
+ return status;
+ }
-sbuild::keyfile&
-sbuild::keyfile::operator += (keyfile const& rhs)
-{
- for (const auto& gp : rhs.groups)
- {
- group_type const& group = gp.second;
- group_name_type const& groupname = std::get<0>(group);
- comment_type const& comment = std::get<2>(group);
- size_type const& line = std::get<3>(group);
- set_group(groupname, comment, line);
-
- item_map_type const& items(std::get<1>(group));
- for (const auto& it : items)
- {
- item_type const& item = it.second;
- key_type const& key(std::get<0>(item));
- internal_value_type const& value(std::get<1>(item));
- comment_type const& comment(std::get<2>(item));
- size_type const& line(std::get<3>(item));
- set_value(groupname, key, value, comment, line);
- }
- }
- return *this;
-}
+ void
+ sbuild::keyfile::remove_group (group_name_type const& group)
+ {
+ group_map_type::iterator pos = this->groups.find(group);
+ if (pos != this->groups.end())
+ this->groups.erase(pos);
+ }
+
+ void
+ sbuild::keyfile::remove_key (group_name_type const& group,
+ key_type const& key)
+ {
+ group_type *found_group = find_group(group);
+ if (found_group)
+ {
+ item_map_type& items = std::get<1>(*found_group);
+ item_map_type::iterator pos = items.find(key);
+ if (pos != items.end())
+ items.erase(pos);
+ }
+ }
+
+ sbuild::keyfile&
+ sbuild::keyfile::operator += (keyfile const& rhs)
+ {
+ for (const auto& gp : rhs.groups)
+ {
+ group_type const& group = gp.second;
+ group_name_type const& groupname = std::get<0>(group);
+ comment_type const& comment = std::get<2>(group);
+ size_type const& line = std::get<3>(group);
+ set_group(groupname, comment, line);
+
+ item_map_type const& items(std::get<1>(group));
+ for (const auto& it : items)
+ {
+ item_type const& item = it.second;
+ key_type const& key(std::get<0>(item));
+ internal_value_type const& value(std::get<1>(item));
+ comment_type const& comment(std::get<2>(item));
+ size_type const& line(std::get<3>(item));
+ set_value(groupname, key, value, comment, line);
+ }
+ }
+ return *this;
+ }
-sbuild::keyfile
-operator + (sbuild::keyfile const& lhs,
- sbuild::keyfile const& rhs)
-{
- sbuild::keyfile ret(lhs);
- ret += rhs;
- return ret;
-}
+ sbuild::keyfile
+ operator + (sbuild::keyfile const& lhs,
+ sbuild::keyfile const& rhs)
+ {
+ sbuild::keyfile ret(lhs);
+ ret += rhs;
+ return ret;
+ }
-const sbuild::keyfile::group_type *
-sbuild::keyfile::find_group (group_name_type const& group) const
-{
- group_map_type::const_iterator pos = this->groups.find(group);
- if (pos != this->groups.end())
- return &pos->second;
+ const sbuild::keyfile::group_type *
+ sbuild::keyfile::find_group (group_name_type const& group) const
+ {
+ group_map_type::const_iterator pos = this->groups.find(group);
+ if (pos != this->groups.end())
+ return &pos->second;
- return 0;
-}
+ return 0;
+ }
-sbuild::keyfile::group_type *
-sbuild::keyfile::find_group (group_name_type const& group)
-{
- group_map_type::iterator pos = this->groups.find(group);
- if (pos != this->groups.end())
- return &pos->second;
+ sbuild::keyfile::group_type *
+ sbuild::keyfile::find_group (group_name_type const& group)
+ {
+ group_map_type::iterator pos = this->groups.find(group);
+ if (pos != this->groups.end())
+ return &pos->second;
- return 0;
-}
+ return 0;
+ }
-const sbuild::keyfile::item_type *
-sbuild::keyfile::find_item (group_name_type const& group,
- key_type const& key) const
-{
- const group_type *found_group = find_group(group);
- if (found_group)
- {
- item_map_type const& items = std::get<1>(*found_group);
- item_map_type::const_iterator pos = items.find(key);
- if (pos != items.end())
- return &pos->second;
- }
+ const sbuild::keyfile::item_type *
+ sbuild::keyfile::find_item (group_name_type const& group,
+ key_type const& key) const
+ {
+ const group_type *found_group = find_group(group);
+ if (found_group)
+ {
+ item_map_type const& items = std::get<1>(*found_group);
+ item_map_type::const_iterator pos = items.find(key);
+ if (pos != items.end())
+ return &pos->second;
+ }
- return 0;
-}
+ return 0;
+ }
-sbuild::keyfile::item_type *
-sbuild::keyfile::find_item (group_name_type const& group,
- key_type const& key)
-{
- group_type *found_group = find_group(group);
- if (found_group)
- {
- item_map_type& items = std::get<1>(*found_group);
- item_map_type::iterator pos = items.find(key);
- if (pos != items.end())
- return &pos->second;
- }
+ sbuild::keyfile::item_type *
+ sbuild::keyfile::find_item (group_name_type const& group,
+ key_type const& key)
+ {
+ group_type *found_group = find_group(group);
+ if (found_group)
+ {
+ item_map_type& items = std::get<1>(*found_group);
+ item_map_type::iterator pos = items.find(key);
+ if (pos != items.end())
+ return &pos->second;
+ }
- return 0;
-}
+ return 0;
+ }
-void
-sbuild::keyfile::check_priority (group_name_type const& group,
- key_type const& key,
- priority priority,
- bool valid) const
-{
- if (valid == false)
- {
- size_type gline = get_line(group);
+ void
+ sbuild::keyfile::check_priority (group_name_type const& group,
+ key_type const& key,
+ priority priority,
+ bool valid) const
+ {
+ if (valid == false)
+ {
+ size_type gline = get_line(group);
- switch (priority)
- {
- case PRIORITY_REQUIRED:
+ switch (priority)
{
- if (gline)
- throw error(gline, group, MISSING_KEY, key);
- else
- throw error(group, MISSING_KEY_NL, key);
+ case PRIORITY_REQUIRED:
+ {
+ if (gline)
+ throw error(gline, group, MISSING_KEY, key);
+ else
+ throw error(group, MISSING_KEY_NL, key);
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
- }
- }
- else
- {
- size_type line = get_line(group, key);
+ }
+ else
+ {
+ size_type line = get_line(group, key);
- switch (priority)
- {
- case PRIORITY_DEPRECATED:
- {
- if (line)
- {
- error e(line, group, DEPRECATED_KEY, key);
- e.set_reason(_("This option will be removed in the future; please update your configuration"));
- log_exception_warning(e);
- }
- else
- {
- error e(group, DEPRECATED_KEY_NL, key);
- e.set_reason(_("This option will be removed in the future; please update your configuration"));
- log_exception_warning(e);
- }
- }
- break;
- case PRIORITY_OBSOLETE:
+ switch (priority)
{
- if (line)
- {
- error e(line, group, OBSOLETE_KEY, key);
- e.set_reason(_("This option has been removed, and no longer has any effect"));
- log_exception_warning(e);
- }
- else
- {
- error e(group, OBSOLETE_KEY_NL, key);
- e.set_reason(_("This option has been removed, and no longer has any effect"));
- log_exception_warning(e);
- }
+ case PRIORITY_DEPRECATED:
+ {
+ if (line)
+ {
+ error e(line, group, DEPRECATED_KEY, key);
+ e.set_reason(_("This option will be removed in the future; please update your configuration"));
+ log_exception_warning(e);
+ }
+ else
+ {
+ error e(group, DEPRECATED_KEY_NL, key);
+ e.set_reason(_("This option will be removed in the future; please update your configuration"));
+ log_exception_warning(e);
+ }
+ }
+ break;
+ case PRIORITY_OBSOLETE:
+ {
+ if (line)
+ {
+ error e(line, group, OBSOLETE_KEY, key);
+ e.set_reason(_("This option has been removed, and no longer has any effect"));
+ log_exception_warning(e);
+ }
+ else
+ {
+ error e(group, OBSOLETE_KEY_NL, key);
+ e.set_reason(_("This option has been removed, and no longer has any effect"));
+ log_exception_warning(e);
+ }
+ }
+ break;
+ case PRIORITY_DISALLOWED:
+ {
+ if (line)
+ throw error(line, group, DISALLOWED_KEY, key);
+ else
+ throw error(group, DISALLOWED_KEY_NL, key);
+ }
+ break;
+ default:
+ break;
}
- break;
- case PRIORITY_DISALLOWED:
- {
- if (line)
- throw error(line, group, DISALLOWED_KEY, key);
- else
- throw error(group, DISALLOWED_KEY_NL, key);
- }
- break;
- default:
- break;
- }
- }
-}
+ }
+ }
-/*
- * Local Variables:
- * mode:C++
- * End:
- */
+}
diff --git a/lib/sbuild/lock.cc b/lib/sbuild/lock.cc
index dfa8fe9a..8eac089c 100644
--- a/lib/sbuild/lock.cc
+++ b/lib/sbuild/lock.cc
@@ -31,184 +31,188 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
-template<>
-error<lock::error_code>::map_type
-error<lock::error_code>::error_strings =
- {
- {lock::TIMEOUT_HANDLER, N_("Failed to set timeout handler")},
- {lock::TIMEOUT_SET, N_("Failed to set timeout")},
- {lock::TIMEOUT_CANCEL, N_("Failed to cancel timeout")},
- {lock::LOCK, N_("Failed to lock file")},
- {lock::UNLOCK, N_("Failed to unlock file")},
- // TRANSLATORS: %4% = time in seconds
- {lock::LOCK_TIMEOUT, N_("Failed to lock file (timed out after %4% seconds)")},
- // TRANSLATORS: %4% = time in seconds
- {lock::UNLOCK_TIMEOUT, N_("Failed to unlock file (timed out after %4% seconds)")},
- {lock::DEVICE_LOCK, N_("Failed to lock device")},
- // TRANSLATORS: %4% = time in seconds
- // TRANSLATORS: %5% = integer process ID
- {lock::DEVICE_LOCK_TIMEOUT, N_("Failed to lock device (timed out after %4% seconds; lock held by PID %5%)")},
- {lock::DEVICE_TEST, N_("Failed to test device lock")},
- {lock::DEVICE_UNLOCK, N_("Failed to unlock device")},
- // TRANSLATORS: %4% = time in seconds
- // TRANSLATORS: %5% = integer process ID
- {lock::DEVICE_UNLOCK_TIMEOUT, N_("Failed to unlock device (timed out after %4% seconds; lock held by PID %5%)")}
- };
-
-namespace
+namespace sbuild
{
- /**
- * Handle the SIGALRM signal. This exists so that system calls get
- * interrupted.
- *
- * @param ignore the signal number.
- */
- void
- alarm_handler (int ignore)
+
+ template<>
+ error<lock::error_code>::map_type
+ error<lock::error_code>::error_strings =
+ {
+ {lock::TIMEOUT_HANDLER, N_("Failed to set timeout handler")},
+ {lock::TIMEOUT_SET, N_("Failed to set timeout")},
+ {lock::TIMEOUT_CANCEL, N_("Failed to cancel timeout")},
+ {lock::LOCK, N_("Failed to lock file")},
+ {lock::UNLOCK, N_("Failed to unlock file")},
+ // TRANSLATORS: %4% = time in seconds
+ {lock::LOCK_TIMEOUT, N_("Failed to lock file (timed out after %4% seconds)")},
+ // TRANSLATORS: %4% = time in seconds
+ {lock::UNLOCK_TIMEOUT, N_("Failed to unlock file (timed out after %4% seconds)")},
+ {lock::DEVICE_LOCK, N_("Failed to lock device")},
+ // TRANSLATORS: %4% = time in seconds
+ // TRANSLATORS: %5% = integer process ID
+ {lock::DEVICE_LOCK_TIMEOUT, N_("Failed to lock device (timed out after %4% seconds; lock held by PID %5%)")},
+ {lock::DEVICE_TEST, N_("Failed to test device lock")},
+ {lock::DEVICE_UNLOCK, N_("Failed to unlock device")},
+ // TRANSLATORS: %4% = time in seconds
+ // TRANSLATORS: %5% = integer process ID
+ {lock::DEVICE_UNLOCK_TIMEOUT, N_("Failed to unlock device (timed out after %4% seconds; lock held by PID %5%)")}
+ };
+
+ namespace
{
+ /**
+ * Handle the SIGALRM signal. This exists so that system calls get
+ * interrupted.
+ *
+ * @param ignore the signal number.
+ */
+ void
+ alarm_handler (int ignore)
+ {
+ }
}
-}
-lock::lock ():
- saved_signals()
-{
-}
+ lock::lock ():
+ saved_signals()
+ {
+ }
-lock::~lock ()
-{
-}
+ lock::~lock ()
+ {
+ }
-void
-lock::set_alarm ()
-{
- struct sigaction new_sa;
- sigemptyset(&new_sa.sa_mask);
- new_sa.sa_flags = 0;
- new_sa.sa_handler = alarm_handler;
+ void
+ lock::set_alarm ()
+ {
+ struct sigaction new_sa;
+ sigemptyset(&new_sa.sa_mask);
+ new_sa.sa_flags = 0;
+ new_sa.sa_handler = alarm_handler;
- if (sigaction(SIGALRM, &new_sa, &this->saved_signals) != 0)
- throw error(TIMEOUT_HANDLER, strerror(errno));
-}
+ if (sigaction(SIGALRM, &new_sa, &this->saved_signals) != 0)
+ throw error(TIMEOUT_HANDLER, strerror(errno));
+ }
-void
-lock::clear_alarm ()
-{
- /* Restore original handler */
- sigaction (SIGALRM, &this->saved_signals, 0);
-}
+ void
+ lock::clear_alarm ()
+ {
+ /* Restore original handler */
+ sigaction (SIGALRM, &this->saved_signals, 0);
+ }
-void
-lock::set_timer(struct itimerval const& timer)
-{
- set_alarm();
+ void
+ lock::set_timer(struct itimerval const& timer)
+ {
+ set_alarm();
- if (setitimer(ITIMER_REAL, &timer, 0) == -1)
- {
- clear_alarm();
- throw error(TIMEOUT_SET, strerror(errno));
- }
-}
+ if (setitimer(ITIMER_REAL, &timer, 0) == -1)
+ {
+ clear_alarm();
+ throw error(TIMEOUT_SET, strerror(errno));
+ }
+ }
-void
-lock::unset_timer ()
-{
- struct itimerval disable_timer;
- disable_timer.it_interval.tv_sec = disable_timer.it_interval.tv_usec = 0;
- disable_timer.it_value.tv_sec = disable_timer.it_value.tv_usec = 0;
+ void
+ lock::unset_timer ()
+ {
+ struct itimerval disable_timer;
+ disable_timer.it_interval.tv_sec = disable_timer.it_interval.tv_usec = 0;
+ disable_timer.it_value.tv_sec = disable_timer.it_value.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &disable_timer, 0) == -1)
- {
- clear_alarm();
- throw error(TIMEOUT_CANCEL, strerror(errno));
- }
+ if (setitimer(ITIMER_REAL, &disable_timer, 0) == -1)
+ {
+ clear_alarm();
+ throw error(TIMEOUT_CANCEL, strerror(errno));
+ }
- clear_alarm();
-}
+ clear_alarm();
+ }
-file_lock::file_lock (int fd):
- lock(),
- fd(fd),
- locked(false)
-{
-}
+ file_lock::file_lock (int fd):
+ lock(),
+ fd(fd),
+ locked(false)
+ {
+ }
-file_lock::~file_lock ()
-{
- // Release a lock if held. Note that the code is duplicated from
- // set_lock because we don't want to throw an exception in a
- // destructor under any circumstances. Any error is logged.
- if (locked)
- {
- struct flock read_lock;
- read_lock.l_type = LOCK_NONE;
- read_lock.l_whence = SEEK_SET;
- read_lock.l_start = 0;
- read_lock.l_len = 0; // Lock entire file
- read_lock.l_pid = 0;
-
- if (fcntl(this->fd, F_SETLK, &read_lock) == -1)
- log_exception_warning(error(UNLOCK, strerror(errno)));
- }
-}
+ file_lock::~file_lock ()
+ {
+ // Release a lock if held. Note that the code is duplicated from
+ // set_lock because we don't want to throw an exception in a
+ // destructor under any circumstances. Any error is logged.
+ if (locked)
+ {
+ struct flock read_lock;
+ read_lock.l_type = LOCK_NONE;
+ read_lock.l_whence = SEEK_SET;
+ read_lock.l_start = 0;
+ read_lock.l_len = 0; // Lock entire file
+ read_lock.l_pid = 0;
+
+ if (fcntl(this->fd, F_SETLK, &read_lock) == -1)
+ log_exception_warning(error(UNLOCK, strerror(errno)));
+ }
+ }
-void
-file_lock::set_lock (lock::type lock_type,
- unsigned int timeout)
-{
- try
- {
- struct itimerval timeout_timer;
- timeout_timer.it_interval.tv_sec = timeout_timer.it_interval.tv_usec = 0;
- timeout_timer.it_value.tv_sec = timeout;
- timeout_timer.it_value.tv_usec = 0;
- set_timer(timeout_timer);
-
- /* Now the signal handler and itimer are set, the function can't
- return without stopping the timer and restoring the signal
- handler to its original state. */
-
- /* Wait on lock until interrupted by a signal if a timeout was set,
- otherwise return immediately. */
- struct flock read_lock;
- read_lock.l_type = lock_type;
- read_lock.l_whence = SEEK_SET;
- read_lock.l_start = 0;
- read_lock.l_len = 0; // Lock entire file
- read_lock.l_pid = 0;
-
- if (fcntl(this->fd,
- (timeout != 0) ? F_SETLKW : F_SETLK,
- &read_lock) == -1)
- {
- if (errno == EINTR)
- throw error((lock_type == LOCK_SHARED ||
- lock_type == LOCK_EXCLUSIVE)
- ? LOCK_TIMEOUT : UNLOCK_TIMEOUT,
- timeout);
- else
- throw error((lock_type == LOCK_SHARED ||
- lock_type == LOCK_EXCLUSIVE) ? LOCK : UNLOCK,
- strerror(errno));
- }
-
- if (lock_type == LOCK_SHARED || lock_type == LOCK_EXCLUSIVE)
- this->locked = true;
- else
- this->locked = false;
-
- unset_timer();
- }
- catch (error const& e)
- {
- unset_timer();
- throw;
- }
-}
+ void
+ file_lock::set_lock (lock::type lock_type,
+ unsigned int timeout)
+ {
+ try
+ {
+ struct itimerval timeout_timer;
+ timeout_timer.it_interval.tv_sec = timeout_timer.it_interval.tv_usec = 0;
+ timeout_timer.it_value.tv_sec = timeout;
+ timeout_timer.it_value.tv_usec = 0;
+ set_timer(timeout_timer);
+
+ /* Now the signal handler and itimer are set, the function can't
+ return without stopping the timer and restoring the signal
+ handler to its original state. */
+
+ /* Wait on lock until interrupted by a signal if a timeout was set,
+ otherwise return immediately. */
+ struct flock read_lock;
+ read_lock.l_type = lock_type;
+ read_lock.l_whence = SEEK_SET;
+ read_lock.l_start = 0;
+ read_lock.l_len = 0; // Lock entire file
+ read_lock.l_pid = 0;
+
+ if (fcntl(this->fd,
+ (timeout != 0) ? F_SETLKW : F_SETLK,
+ &read_lock) == -1)
+ {
+ if (errno == EINTR)
+ throw error((lock_type == LOCK_SHARED ||
+ lock_type == LOCK_EXCLUSIVE)
+ ? LOCK_TIMEOUT : UNLOCK_TIMEOUT,
+ timeout);
+ else
+ throw error((lock_type == LOCK_SHARED ||
+ lock_type == LOCK_EXCLUSIVE) ? LOCK : UNLOCK,
+ strerror(errno));
+ }
+
+ if (lock_type == LOCK_SHARED || lock_type == LOCK_EXCLUSIVE)
+ this->locked = true;
+ else
+ this->locked = false;
+
+ unset_timer();
+ }
+ catch (error const& e)
+ {
+ unset_timer();
+ throw;
+ }
+ }
+
+ void
+ file_lock::unset_lock ()
+ {
+ set_lock(LOCK_NONE, 0);
+ }
-void
-file_lock::unset_lock ()
-{
- set_lock(LOCK_NONE, 0);
}
diff --git a/lib/sbuild/log.cc b/lib/sbuild/log.cc
index 7f7a5697..3fbaa94a 100644
--- a/lib/sbuild/log.cc
+++ b/lib/sbuild/log.cc
@@ -30,145 +30,149 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
-namespace
+namespace sbuild
{
- /**
- * Log an exception reason. Log the reason an exception was thrown,
- * if the exception contains reason information.
- *
- * @param e the exception to log.
- * @param ctty true to log to the CTTY or false to log to cerr.
- */
- void
- log_reason (std::exception const& e,
- bool ctty)
+ namespace
{
- try
- {
- error_base const& eb(dynamic_cast<error_base const&>(e));
- string_list lines = split_string(eb.why(), "\n");
- for (const auto& line : lines)
- ctty ? log_ctty_info() : log_info()
- << line << std::endl;
- }
- catch (std::bad_cast const& discard)
- {
- }
+
+ /**
+ * Log an exception reason. Log the reason an exception was thrown,
+ * if the exception contains reason information.
+ *
+ * @param e the exception to log.
+ * @param ctty true to log to the CTTY or false to log to cerr.
+ */
+ void
+ log_reason (std::exception const& e,
+ bool ctty)
+ {
+ try
+ {
+ error_base const& eb(dynamic_cast<error_base const&>(e));
+ string_list lines = split_string(eb.why(), "\n");
+ for (const auto& line : lines)
+ ctty ? log_ctty_info() : log_info()
+ << line << std::endl;
+ }
+ catch (std::bad_cast const& discard)
+ {
+ }
+ }
+
+ /**
+ * Log an exception reason as an informational message.
+ *
+ * @param e the exception to log.
+ */
+ void
+ log_exception_reason (std::exception const& e)
+ {
+ log_reason(e, false);
+ }
+
+ /**
+ * Log an exception reason as as an informational message to the
+ * Controlling TTY.
+ *
+ * @param e the exception to log.
+ */
+ void
+ log_ctty_exception_reason (std::exception const& e)
+ {
+ log_reason(e, true);
+ }
}
- /**
- * Log an exception reason as an informational message.
- *
- * @param e the exception to log.
- */
- void
- log_exception_reason (std::exception const& e)
+ std::ostream&
+ log_info ()
{
- log_reason(e, false);
+ // TRANSLATORS: "I" is an abbreviation of "Information"
+ return std::cerr << _("I: ");
}
- /**
- * Log an exception reason as as an informational message to the
- * Controlling TTY.
- *
- * @param e the exception to log.
- */
- void
- log_ctty_exception_reason (std::exception const& e)
+ std::ostream&
+ log_warning ()
{
- log_reason(e, true);
+ // TRANSLATORS: "W" is an abbreviation of "Warning"
+ return std::cerr << _("W: ");
}
-}
-std::ostream&
-sbuild::log_info ()
-{
- // TRANSLATORS: "I" is an abbreviation of "Information"
- return std::cerr << _("I: ");
-}
+ std::ostream&
+ log_error ()
+ {
+ // TRANSLATORS: "E" is an abbreviation of "Error"
+ return std::cerr << _("E: ");
+ }
-std::ostream&
-sbuild::log_warning ()
-{
- // TRANSLATORS: "W" is an abbreviation of "Warning"
- return std::cerr << _("W: ");
-}
+ std::ostream&
+ log_debug (debug_level level)
+ {
+ if (debug_log_level > 0 &&
+ level >= debug_log_level)
+ // TRANSLATORS: %1% = integer debug level
+ // TRANSLATORS: "D" is an abbreviation of "Debug"
+ return std::cerr << format(_("D(%1%): ")) % level;
+ else
+ return cnull;
+ }
-std::ostream&
-sbuild::log_error ()
-{
- // TRANSLATORS: "E" is an abbreviation of "Error"
- return std::cerr << _("E: ");
-}
+ std::ostream&
+ log_ctty_info ()
+ {
+ // TRANSLATORS: "I" is an abbreviation of "Information"
+ return cctty << _("I: ");
+ }
-std::ostream&
-sbuild::log_debug (sbuild::debug_level level)
-{
- if (debug_log_level > 0 &&
- level >= debug_log_level)
- // TRANSLATORS: %1% = integer debug level
- // TRANSLATORS: "D" is an abbreviation of "Debug"
- return std::cerr << format(_("D(%1%): ")) % level;
- else
- return sbuild::cnull;
-}
+ std::ostream&
+ log_ctty_warning ()
+ {
+ // TRANSLATORS: "W" is an abbreviation of "Warning"
+ return cctty << _("W: ");
+ }
-std::ostream&
-sbuild::log_ctty_info ()
-{
- // TRANSLATORS: "I" is an abbreviation of "Information"
- return cctty << _("I: ");
-}
+ std::ostream&
+ log_ctty_error ()
+ {
+ // TRANSLATORS: "E" is an abbreviation of "Error"
+ return cctty << _("E: ");
+ }
-std::ostream&
-sbuild::log_ctty_warning ()
-{
- // TRANSLATORS: "W" is an abbreviation of "Warning"
- return cctty << _("W: ");
-}
+ void
+ log_exception_warning (std::exception const& e)
+ {
+ log_warning() << e.what() << std::endl;
+ log_exception_reason(e);
+ }
-std::ostream&
-sbuild::log_ctty_error ()
-{
- // TRANSLATORS: "E" is an abbreviation of "Error"
- return cctty << _("E: ");
-}
+ void
+ log_exception_error (std::exception const& e)
+ {
+ log_error() << e.what() << std::endl;
+ log_exception_reason(e);
+ }
-void
-sbuild::log_exception_warning (std::exception const& e)
-{
- log_warning() << e.what() << std::endl;
- log_exception_reason(e);
-}
+ void
+ log_ctty_exception_warning (std::exception const& e)
+ {
+ log_ctty_warning() << e.what() << std::endl;
+ log_ctty_exception_reason(e);
+ }
-void
-sbuild::log_exception_error (std::exception const& e)
-{
- log_error() << e.what() << std::endl;
- log_exception_reason(e);
-}
+ void
+ log_ctty_exception_error (std::exception const& e)
+ {
+ log_ctty_error() << e.what() << std::endl;
+ log_ctty_exception_reason(e);
+ }
-void
-sbuild::log_ctty_exception_warning (std::exception const& e)
-{
- log_ctty_warning() << e.what() << std::endl;
- log_ctty_exception_reason(e);
-}
+ void
+ log_unknown_exception_error ()
+ {
+ log_error() << _("An unknown exception occurred") << std::endl;
+ }
-void
-sbuild::log_ctty_exception_error (std::exception const& e)
-{
- log_ctty_error() << e.what() << std::endl;
- log_ctty_exception_reason(e);
-}
+ debug_level debug_log_level = DEBUG_NONE;
-void
-sbuild::log_unknown_exception_error ()
-{
- log_error() << _("An unknown exception occurred") << std::endl;
}
-
-sbuild::debug_level sbuild::debug_log_level = sbuild::DEBUG_NONE;
diff --git a/lib/sbuild/mntstream.cc b/lib/sbuild/mntstream.cc
index 3f1e1601..c67d5ff9 100644
--- a/lib/sbuild/mntstream.cc
+++ b/lib/sbuild/mntstream.cc
@@ -23,146 +23,149 @@
#include <cerrno>
#include <cstring>
-using namespace sbuild;
-
-template<>
-error<mntstream::error_code>::map_type
-error<mntstream::error_code>::error_strings =
- {
- // TRANSLATORS: %1% = mount file name
- {mntstream::MNT_OPEN, N_("Failed to open mount file ‘%1%’")},
- // TRANSLATORS: %1% = mount file name
- {mntstream::MNT_READ, N_("Failed to read mount file ‘%1%’")}
- };
-
-mntstream::mntentry::mntentry (struct mntent const& entry):
- filesystem_name(entry.mnt_fsname),
- directory(entry.mnt_dir),
- type(entry.mnt_type),
- options(entry.mnt_opts),
- dump_frequency(entry.mnt_freq),
- fsck_pass(entry.mnt_passno)
-{
-}
-
-
-mntstream::mntstream(std::string const& file):
- file(),
- mntfile(0),
- data(),
- error_status(true),
- eof_status(true)
+namespace sbuild
{
- open(file);
-}
-
-
-mntstream::~mntstream()
-{
- close();
-}
-void
-mntstream::open(std::string const& file)
-{
- this->mntfile = setmntent(file.c_str(), "r");
- if (this->mntfile == 0)
+ template<>
+ error<mntstream::error_code>::map_type
+ error<mntstream::error_code>::error_strings =
{
- this->file.clear();
- this->error_status = true;
- this->eof_status = true;
- throw error(file, MNT_OPEN, strerror(errno));
- }
- this->file = file;
- this->error_status = false;
- this->eof_status = false;
- read();
-}
-
-void
-mntstream::read(int quantity)
-{
- int i;
+ // TRANSLATORS: %1% = mount file name
+ {mntstream::MNT_OPEN, N_("Failed to open mount file ‘%1%’")},
+ // TRANSLATORS: %1% = mount file name
+ {mntstream::MNT_READ, N_("Failed to read mount file ‘%1%’")}
+ };
+
+ mntstream::mntentry::mntentry (struct mntent const& entry):
+ filesystem_name(entry.mnt_fsname),
+ directory(entry.mnt_dir),
+ type(entry.mnt_type),
+ options(entry.mnt_opts),
+ dump_frequency(entry.mnt_freq),
+ fsck_pass(entry.mnt_passno)
+ {
+ }
- if (this->mntfile == 0)
- return;
- for (i = 0; i < quantity; ++i)
- {
- struct mntent* entry;
- errno = 0;
- entry = getmntent(mntfile);
-
- if (entry == 0) // EOF or error
- {
- //std::cerr << "Mount file read error: ";
- if (errno) // error
- {
- this->error_status = true;
- throw error(this->file, MNT_READ, strerror(errno));
- }
- return;
- }
-
- mntentry newentry(*entry); // make a mntentry
- this->data.push_back(newentry); // push onto the end of the list
- }
-}
+ mntstream::mntstream(std::string const& file):
+ file(),
+ mntfile(0),
+ data(),
+ error_status(true),
+ eof_status(true)
+ {
+ open(file);
+ }
-void
-mntstream::close()
-{
- if (this->mntfile)
- endmntent(this->mntfile); // don't throw an exception on failure
- // -- it could be called in the
- // destructor
- this->mntfile = 0;
- this->data.clear(); // clear all data
- this->file.clear();
- this->error_status = true;
- this->eof_status = true;
-}
+ mntstream::~mntstream()
+ {
+ close();
+ }
-bool
-mntstream::eof() const
-{
- return this->eof_status;
-}
+ void
+ mntstream::open(std::string const& file)
+ {
+ this->mntfile = setmntent(file.c_str(), "r");
+ if (this->mntfile == 0)
+ {
+ this->file.clear();
+ this->error_status = true;
+ this->eof_status = true;
+ throw error(file, MNT_OPEN, strerror(errno));
+ }
+ this->file = file;
+ this->error_status = false;
+ this->eof_status = false;
+ read();
+ }
+
+ void
+ mntstream::read(int quantity)
+ {
+ int i;
+
+ if (this->mntfile == 0)
+ return;
+
+ for (i = 0; i < quantity; ++i)
+ {
+ struct mntent* entry;
+ errno = 0;
+ entry = getmntent(mntfile);
+
+ if (entry == 0) // EOF or error
+ {
+ //std::cerr << "Mount file read error: ";
+ if (errno) // error
+ {
+ this->error_status = true;
+ throw error(this->file, MNT_READ, strerror(errno));
+ }
+ return;
+ }
+
+ mntentry newentry(*entry); // make a mntentry
+ this->data.push_back(newentry); // push onto the end of the list
+ }
+ }
+
+ void
+ mntstream::close()
+ {
+ if (this->mntfile)
+ endmntent(this->mntfile); // don't throw an exception on failure
+ // -- it could be called in the
+ // destructor
+ this->mntfile = 0;
+ this->data.clear(); // clear all data
+ this->file.clear();
+ this->error_status = true;
+ this->eof_status = true;
+ }
+
+
+ bool
+ mntstream::eof() const
+ {
+ return this->eof_status;
+ }
-bool
-mntstream::bad() const
-{
- return this->error_status;
-}
+ bool
+ mntstream::bad() const
+ {
+ return this->error_status;
+ }
-mntstream::operator bool ()
-{
- return !(bad() || eof());
-}
+ mntstream::operator bool ()
+ {
+ return !(bad() || eof());
+ }
-bool
-mntstream::operator ! ()
-{
- return bad() || eof();
-}
+ bool
+ mntstream::operator ! ()
+ {
+ return bad() || eof();
+ }
-mntstream&
-sbuild::operator >> (mntstream& stream,
- mntstream::mntentry& entry)
-{
- stream.read(); // read a new entry
- if (stream && !stream.data.empty()) // not at end of file or bad.
- {
- entry = stream.data.front(); // assign next mntentry to entry
- stream.data.pop_front(); // remove the entry
- }
- else // blank the mntentry and set EOF status
- {
- entry = mntstream::mntentry();
- stream.eof_status = true;
- }
+ mntstream&
+ operator >> (mntstream& stream,
+ mntstream::mntentry& entry)
+ {
+ stream.read(); // read a new entry
+ if (stream && !stream.data.empty()) // not at end of file or bad.
+ {
+ entry = stream.data.front(); // assign next mntentry to entry
+ stream.data.pop_front(); // remove the entry
+ }
+ else // blank the mntentry and set EOF status
+ {
+ entry = mntstream::mntentry();
+ stream.eof_status = true;
+ }
+
+ return stream;
+ }
- return stream;
}
diff --git a/lib/sbuild/nostream.cc b/lib/sbuild/nostream.cc
index 7d38299e..1186bf5f 100644
--- a/lib/sbuild/nostream.cc
+++ b/lib/sbuild/nostream.cc
@@ -18,4 +18,9 @@
#include <sbuild/nostream.h>
-sbuild::nostream sbuild::cnull;
+namespace sbuild
+{
+
+ nostream cnull;
+
+}
diff --git a/lib/sbuild/parse-value.cc b/lib/sbuild/parse-value.cc
index 08e3b0d7..987aa9a8 100644
--- a/lib/sbuild/parse-value.cc
+++ b/lib/sbuild/parse-value.cc
@@ -20,37 +20,40 @@
#include <sbuild/parse-value.h>
-using namespace sbuild;
+namespace sbuild
+{
+
+ template<>
+ error<parse_value_error_code>::map_type
+ error<parse_value_error_code>::error_strings =
+ {
+ // TRANSLATORS: %1% = value (arbitrary text)
+ {BAD_VALUE, N_("Could not parse value ‘%1%’")}
+ };
-template<>
-error<parse_value_error_code>::map_type
-error<parse_value_error_code>::error_strings =
+ void
+ parse_value (std::string const& value,
+ bool& parsed_value)
{
- // TRANSLATORS: %1% = value (arbitrary text)
- {BAD_VALUE, N_("Could not parse value ‘%1%’")}
- };
+ if (value == "true" || value == "yes" || value == "1")
+ parsed_value = true;
+ else if (value == "false" || value == "no" || value == "0")
+ parsed_value = false;
+ else
+ {
+ log_debug(DEBUG_NOTICE) << "parse error" << std::endl;
+ throw parse_value_error(value, BAD_VALUE);
+ }
-void
-sbuild::parse_value (std::string const& value,
- bool& parsed_value)
-{
- if (value == "true" || value == "yes" || value == "1")
- parsed_value = true;
- else if (value == "false" || value == "no" || value == "0")
- parsed_value = false;
- else
- {
- log_debug(DEBUG_NOTICE) << "parse error" << std::endl;
- throw parse_value_error(value, BAD_VALUE);
- }
+ log_debug(DEBUG_NOTICE) << "value=" << parsed_value << std::endl;
+ }
- log_debug(DEBUG_NOTICE) << "value=" << parsed_value << std::endl;
-}
+ void
+ parse_value (std::string const& value,
+ std::string& parsed_value)
+ {
+ parsed_value = value;
+ log_debug(DEBUG_NOTICE) << "value=" << parsed_value << std::endl;
+ }
-void
-sbuild::parse_value (std::string const& value,
- std::string& parsed_value)
-{
- parsed_value = value;
- log_debug(DEBUG_NOTICE) << "value=" << parsed_value << std::endl;
}
diff --git a/lib/sbuild/personality.cc b/lib/sbuild/personality.cc
index abf4beab..3c7eb1b6 100644
--- a/lib/sbuild/personality.cc
+++ b/lib/sbuild/personality.cc
@@ -31,155 +31,159 @@
#include <boost/format.hpp>
using boost::format;
-using namespace sbuild;
-namespace
+namespace sbuild
{
- sbuild::feature feature_personality
- ("PERSONALITY",
- N_("Linux kernel Application Binary Interface switching"));
-
-}
-
-template<>
-error<sbuild::personality::error_code>::map_type
-error<sbuild::personality::error_code>::error_strings =
+ namespace
{
- // TRANSLATORS: %1% = integer personality ID
- {sbuild::personality::BAD, N_("Personality ‘%1%’ is unknown")},
- // TRANSLATORS: %1% = personality name
- {sbuild::personality::SET, N_("Failed to set personality ‘%1%’")}
- };
-
-std::map<std::string,sbuild::personality::type>
-sbuild::personality::personalities =
- {
- {"undefined", 0xffffffff},
- {"linux", PER_LINUX},
- {"linux_32bit", PER_LINUX_32BIT},
- {"svr4", PER_SVR4},
- {"scorvr3", PER_SCOSVR3},
- {"osr5", PER_OSR5},
- {"wysev386", PER_WYSEV386},
- {"iscr4", PER_ISCR4},
- {"bsd", PER_BSD},
- {"sunos", PER_SUNOS},
- {"xenix", PER_XENIX},
- {"linux32", PER_LINUX32},
- {"irix32", PER_IRIX32},
- {"irixn32", PER_IRIXN32},
- {"irix64", PER_IRIX64},
- {"riscos", PER_RISCOS},
- {"solaris", PER_SOLARIS},
- {"uw7", PER_UW7},
- {"hpux", PER_HPUX},
- {"osf4", PER_OSF4}
- };
-
-sbuild::personality::personality ():
- persona_name("undefined"),
- persona(find_personality("undefined"))
-{
- set_name("undefined");
-}
-sbuild::personality::personality (std::string const& persona):
- persona_name("undefined"),
- persona(find_personality("undefined"))
-{
- set_name(persona);
-}
+ sbuild::feature feature_personality
+ ("PERSONALITY",
+ N_("Linux kernel Application Binary Interface switching"));
-sbuild::personality::~personality ()
-{
-}
+ }
-sbuild::personality::type
-sbuild::personality::find_personality (std::string const& persona)
-{
- std::map<std::string,type>::const_iterator pos =
- personalities.find(persona);
+ template<>
+ error<sbuild::personality::error_code>::map_type
+ error<sbuild::personality::error_code>::error_strings =
+ {
+ // TRANSLATORS: %1% = integer personality ID
+ {sbuild::personality::BAD, N_("Personality ‘%1%’ is unknown")},
+ // TRANSLATORS: %1% = personality name
+ {sbuild::personality::SET, N_("Failed to set personality ‘%1%’")}
+ };
+
+ std::map<std::string,sbuild::personality::type>
+ sbuild::personality::personalities =
+ {
+ {"undefined", 0xffffffff},
+ {"linux", PER_LINUX},
+ {"linux_32bit", PER_LINUX_32BIT},
+ {"svr4", PER_SVR4},
+ {"scorvr3", PER_SCOSVR3},
+ {"osr5", PER_OSR5},
+ {"wysev386", PER_WYSEV386},
+ {"iscr4", PER_ISCR4},
+ {"bsd", PER_BSD},
+ {"sunos", PER_SUNOS},
+ {"xenix", PER_XENIX},
+ {"linux32", PER_LINUX32},
+ {"irix32", PER_IRIX32},
+ {"irixn32", PER_IRIXN32},
+ {"irix64", PER_IRIX64},
+ {"riscos", PER_RISCOS},
+ {"solaris", PER_SOLARIS},
+ {"uw7", PER_UW7},
+ {"hpux", PER_HPUX},
+ {"osf4", PER_OSF4}
+ };
+
+ sbuild::personality::personality ():
+ persona_name("undefined"),
+ persona(find_personality("undefined"))
+ {
+ set_name("undefined");
+ }
- if (pos != personalities.end())
- return pos->second;
+ sbuild::personality::personality (std::string const& persona):
+ persona_name("undefined"),
+ persona(find_personality("undefined"))
+ {
+ set_name(persona);
+ }
- return 0xffffffff;
-}
+ sbuild::personality::~personality ()
+ {
+ }
-std::string const&
-sbuild::personality::find_personality (type persona)
-{
- static const std::string unknown("unknown");
+ sbuild::personality::type
+ sbuild::personality::find_personality (std::string const& persona)
+ {
+ std::map<std::string,type>::const_iterator pos =
+ personalities.find(persona);
- for (std::map<std::string,type>::const_iterator pos = personalities.begin();
- pos != personalities.end();
- ++pos)
- if (pos->second == persona)
- return pos->first;
+ if (pos != personalities.end())
+ return pos->second;
- return unknown;
-}
+ return 0xffffffff;
+ }
-std::string const&
-sbuild::personality::get_name () const
-{
- return this->persona_name;
-}
+ std::string const&
+ sbuild::personality::find_personality (type persona)
+ {
+ static const std::string unknown("unknown");
-void
-sbuild::personality::set_name (std::string const& persona)
-{
- this->persona_name = persona;
- this->persona = find_personality(persona);
+ for (std::map<std::string,type>::const_iterator pos = personalities.begin();
+ pos != personalities.end();
+ ++pos)
+ if (pos->second == persona)
+ return pos->first;
- if (this->persona_name != "undefined" &&
- this->persona == find_personality("undefined"))
- {
- this->persona_name = "undefined";
- this->persona = find_personality("undefined");
+ return unknown;
+ }
- personality::error e(persona, personality::BAD);
- e.set_reason(personality::get_personalities());
- throw e;
- }
-}
+ std::string const&
+ sbuild::personality::get_name () const
+ {
+ return this->persona_name;
+ }
-sbuild::personality::type
-sbuild::personality::get () const
-{
- return this->persona;
-}
+ void
+ sbuild::personality::set_name (std::string const& persona)
+ {
+ this->persona_name = persona;
+ this->persona = find_personality(persona);
+
+ if (this->persona_name != "undefined" &&
+ this->persona == find_personality("undefined"))
+ {
+ this->persona_name = "undefined";
+ this->persona = find_personality("undefined");
+
+ personality::error e(persona, personality::BAD);
+ e.set_reason(personality::get_personalities());
+ throw e;
+ }
+ }
+
+ sbuild::personality::type
+ sbuild::personality::get () const
+ {
+ return this->persona;
+ }
-void
-sbuild::personality::set () const
-{
- /* Set the process execution domain using personality(2). */
- if (this->persona != find_personality("undefined") &&
- ::personality (this->persona) < 0)
- {
- throw error(get_name(), SET, strerror(errno));
- }
-}
+ void
+ sbuild::personality::set () const
+ {
+ /* Set the process execution domain using personality(2). */
+ if (this->persona != find_personality("undefined") &&
+ ::personality (this->persona) < 0)
+ {
+ throw error(get_name(), SET, strerror(errno));
+ }
+ }
+
+ std::string
+ sbuild::personality::get_personalities ()
+ {
+ // TRANSLATORS: %1% = a comma-separated list of personality names
+ format fmt(_("Valid personalities: %1%\n"));
+ std::string ps;
-std::string
-sbuild::personality::get_personalities ()
-{
- // TRANSLATORS: %1% = a comma-separated list of personality names
- format fmt(_("Valid personalities: %1%\n"));
- std::string ps;
+ for (std::map<std::string,type>::const_iterator pos = personalities.begin();
+ pos != personalities.end();
+ ++pos)
+ {
+ ps += pos->first;
+ std::map<std::string,type>::const_iterator stpos = pos;
+ if (++stpos != personalities.end())
+ ps += ", ";
+ }
- for (std::map<std::string,type>::const_iterator pos = personalities.begin();
- pos != personalities.end();
- ++pos)
- {
- ps += pos->first;
- std::map<std::string,type>::const_iterator stpos = pos;
- if (++stpos != personalities.end())
- ps += ", ";
- }
+ fmt % ps;
- fmt % ps;
+ return fmt.str();
+ }
- return fmt.str();
}
diff --git a/lib/sbuild/run-parts.cc b/lib/sbuild/run-parts.cc
index a1ec39c1..6803631b 100644
--- a/lib/sbuild/run-parts.cc
+++ b/lib/sbuild/run-parts.cc
@@ -32,336 +32,340 @@
#include <boost/filesystem/operations.hpp>
using boost::format;
-using namespace sbuild;
-template<>
-error<run_parts::error_code>::map_type
-error<run_parts::error_code>::error_strings =
- {
- {run_parts::CHILD_FORK, N_("Failed to fork child")},
- {run_parts::CHILD_WAIT, N_("Wait for child failed")},
- // TRANSLATORS: %1% = command name
- {run_parts::EXEC, N_("Failed to execute “%1%”")},
- {run_parts::PIPE, N_("Failed to create pipe")},
- {run_parts::DUP, N_("Failed to duplicate file descriptor")},
- {run_parts::POLL, N_("Failed to poll file descriptor")},
- {run_parts::READ, N_("Failed to read file descriptor")}
- };
-
-run_parts::run_parts (std::string const& directory,
- bool lsb_mode,
- bool abort_on_error,
- mode_t umask):
- lsb_mode(true),
- abort_on_error(abort_on_error),
- umask(umask),
- verbose(false),
- reverse(false),
- directory(directory),
- programs()
+namespace sbuild
{
- boost::filesystem::path dirpath(directory);
- boost::filesystem::directory_iterator end_iter;
- for (boost::filesystem::directory_iterator dirent(dirpath);
- dirent != end_iter;
- ++dirent)
+
+ template<>
+ error<run_parts::error_code>::map_type
+ error<run_parts::error_code>::error_strings =
{
+ {run_parts::CHILD_FORK, N_("Failed to fork child")},
+ {run_parts::CHILD_WAIT, N_("Wait for child failed")},
+ // TRANSLATORS: %1% = command name
+ {run_parts::EXEC, N_("Failed to execute “%1%”")},
+ {run_parts::PIPE, N_("Failed to create pipe")},
+ {run_parts::DUP, N_("Failed to duplicate file descriptor")},
+ {run_parts::POLL, N_("Failed to poll file descriptor")},
+ {run_parts::READ, N_("Failed to read file descriptor")}
+ };
+
+ run_parts::run_parts (std::string const& directory,
+ bool lsb_mode,
+ bool abort_on_error,
+ mode_t umask):
+ lsb_mode(true),
+ abort_on_error(abort_on_error),
+ umask(umask),
+ verbose(false),
+ reverse(false),
+ directory(directory),
+ programs()
+ {
+ boost::filesystem::path dirpath(directory);
+ boost::filesystem::directory_iterator end_iter;
+ for (boost::filesystem::directory_iterator dirent(dirpath);
+ dirent != end_iter;
+ ++dirent)
+ {
#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2
- std::string name(dirent->leaf());
+ std::string name(dirent->leaf());
#else
- std::string name(dirent->path().filename().string());
+ std::string name(dirent->path().filename().string());
#endif
- // Skip common directories.
- if (name == "." || name == "..")
- continue;
-
- // Skip backup files and dpkg configuration backup files.
- if (is_valid_filename(name, this->lsb_mode))
- this->programs.insert(name);
- }
-}
-
-run_parts::~run_parts ()
-{
-}
+ // Skip common directories.
+ if (name == "." || name == "..")
+ continue;
-bool
-run_parts::get_verbose () const
-{
- return this->verbose;
-}
-
-void
-run_parts::set_verbose (bool verbose)
-{
- this->verbose = verbose;
-}
-
-bool
-run_parts::get_reverse () const
-{
- return this->reverse;
-}
-
-void
-run_parts::set_reverse (bool reverse)
-{
- this->reverse = reverse;
-}
+ // Skip backup files and dpkg configuration backup files.
+ if (is_valid_filename(name, this->lsb_mode))
+ this->programs.insert(name);
+ }
+ }
-int
-run_parts::run (string_list const& command,
- environment const& env)
-{
- int exit_status = 0;
+ run_parts::~run_parts ()
+ {
+ }
- if (!this->reverse)
- {
- for (const auto& program : this->programs)
- {
- string_list real_command;
- real_command.push_back(program);
- for (const auto& arg : command)
- real_command.push_back(arg);
-
- exit_status = run_child(program, real_command, env);
-
- if (exit_status && this->abort_on_error)
- return exit_status;
- }
- }
- else
- {
- for (program_set::const_reverse_iterator program = this->programs.rbegin();
- program != this->programs.rend();
- ++program)
- {
- string_list real_command;
- real_command.push_back(*program);
- for (const auto& arg : command)
- real_command.push_back(arg);
-
- exit_status = run_child(*program, real_command, env);
-
- if (exit_status && this->abort_on_error)
- return exit_status;
- }
- }
-
- return exit_status;
-}
+ bool
+ run_parts::get_verbose () const
+ {
+ return this->verbose;
+ }
-int
-run_parts::run_child (std::string const& file,
- string_list const& command,
- environment const& env)
-{
- int stdout_pipe[2];
- int stderr_pipe[2];
- int exit_status = 0;
- pid_t pid;
+ void
+ run_parts::set_verbose (bool verbose)
+ {
+ this->verbose = verbose;
+ }
- try
- {
- if (pipe(stdout_pipe) < 0)
- throw error(PIPE, strerror(errno));
- if (pipe(stderr_pipe) < 0)
- throw error(PIPE, strerror(errno));
-
- if ((pid = fork()) == -1)
- {
- throw error(CHILD_FORK, strerror(errno));
- }
- else if (pid == 0)
- {
- try
- {
- log_debug(DEBUG_INFO) << "run_parts: executing "
- << string_list_to_string(command, ", ")
- << std::endl;
- if (this->verbose)
- // TRANSLATORS: %1% = command
- log_info() << format(_("Executing ‘%1%’"))
- % string_list_to_string(command, " ")
- << std::endl;
- ::umask(this->umask);
-
- // Don't leak syslog file descriptor to child processes.
- closelog();
-
- // Set up pipes for stdout and stderr
- if (dup2(stdout_pipe[1], STDOUT_FILENO) < 0)
- throw error(DUP, strerror(errno));
- if (dup2(stderr_pipe[1], STDERR_FILENO) < 0)
- throw error(DUP, strerror(errno));
-
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
-
- exec(this->directory + '/' + file, command, env);
- error e(file, EXEC, strerror(errno));
- log_exception_error(e);
- }
- catch (std::exception const& e)
- {
- log_exception_error(e);
- }
- catch (...)
- {
- log_error()
- << _("An unknown exception occurred") << std::endl;
- }
- _exit(EXIT_FAILURE);
- }
-
- // Log stdout and stderr.
- close(stdout_pipe[1]);
- close(stderr_pipe[1]);
-
- struct pollfd pollfds[2];
- pollfds[0].fd = stdout_pipe[0];
- pollfds[0].events = POLLIN;
- pollfds[0].revents = 0;
- pollfds[1].fd = stderr_pipe[0];
- pollfds[1].events = POLLIN;
- pollfds[1].revents = 0;
-
- char buffer[BUFSIZ];
-
- std::string stdout_buf;
- std::string stderr_buf;
-
- while (1)
- {
- int status;
- if ((status = poll(pollfds, 2, -1)) < 0)
- throw error(POLL, strerror(errno));
-
- int outdata = 0;
- int errdata = 0;
-
- if (pollfds[1].revents & POLLIN)
- {
- if ((errdata = read(pollfds[1].fd, buffer, BUFSIZ)) < 0
- && errno != EINTR)
- throw error(READ, strerror(errno));
-
- if (errdata)
- stderr_buf += std::string(&buffer[0], errdata);
- }
-
- if (pollfds[0].revents & POLLIN)
- {
- if ((outdata = read(pollfds[0].fd, buffer, BUFSIZ)) < 0
- && errno != EINTR)
- throw error(READ, strerror(errno));
-
- if (outdata)
- stdout_buf += std::string(&buffer[0], outdata);
- }
-
- if (!stderr_buf.empty())
- {
- string_list lines = split_string_strict(stderr_buf, "\n");
- // If the buffer ends in a newline before splitting,
- // it's OK to flush all lines.
- bool flush = *stderr_buf.rbegin() == '\n';
-
- for (string_list::const_iterator pos = lines.begin();
- pos != lines.end();
- ++pos)
- {
- if (pos + 1 != lines.end() || flush)
- log_error() << file << ": " << *pos << '\n';
- else // Save possibly incompete line
- stderr_buf = *pos;
- }
-
- if (flush)
- stderr_buf.clear();
- }
-
- if (!stdout_buf.empty())
- {
- string_list lines = split_string_strict(stdout_buf, "\n");
- // If the buffer ends in a newline before splitting,
- // it's OK to flush all lines.
- bool flush = *stdout_buf.rbegin() == '\n';
-
- for (string_list::const_iterator pos = lines.begin();
- pos != lines.end();
- ++pos)
- {
- if (pos + 1 != lines.end() || flush)
- log_info() << file << ": " << *pos << '\n';
- else // Save possibly incompete line
- stdout_buf = *pos;
- }
-
- if (flush)
- stdout_buf.clear();
- }
-
- if (outdata == 0 && errdata == 0) // pipes closed
- {
- // Flush any remaining lines
- if (!stderr_buf.empty())
- log_error() << file << ": " << stderr_buf << '\n';
- if (!stdout_buf.empty())
- log_info() << file << ": " << stdout_buf << '\n';
- break;
- }
- }
-
- close(stdout_pipe[0]);
- close(stderr_pipe[0]);
- wait_for_child(pid, exit_status);
- }
- catch (error const& e)
- {
- close(stdout_pipe[0]);
- close(stdout_pipe[1]);
- close(stderr_pipe[0]);
- close(stderr_pipe[1]);
- throw;
- }
-
- if (exit_status)
- log_debug(DEBUG_INFO) << "run_parts: " << file
- << " failed with status " << exit_status
- << std::endl;
- else
- log_debug(DEBUG_INFO) << "run_parts: " << file
- << " succeeded"
- << std::endl;
-
- return exit_status;
-}
+ bool
+ run_parts::get_reverse () const
+ {
+ return this->reverse;
+ }
-void
-run_parts::wait_for_child (pid_t pid,
- int& child_status)
-{
- child_status = EXIT_FAILURE; // Default exit status
+ void
+ run_parts::set_reverse (bool reverse)
+ {
+ this->reverse = reverse;
+ }
- int status;
+ int
+ run_parts::run (string_list const& command,
+ environment const& env)
+ {
+ int exit_status = 0;
+
+ if (!this->reverse)
+ {
+ for (const auto& program : this->programs)
+ {
+ string_list real_command;
+ real_command.push_back(program);
+ for (const auto& arg : command)
+ real_command.push_back(arg);
+
+ exit_status = run_child(program, real_command, env);
+
+ if (exit_status && this->abort_on_error)
+ return exit_status;
+ }
+ }
+ else
+ {
+ for (program_set::const_reverse_iterator program = this->programs.rbegin();
+ program != this->programs.rend();
+ ++program)
+ {
+ string_list real_command;
+ real_command.push_back(*program);
+ for (const auto& arg : command)
+ real_command.push_back(arg);
+
+ exit_status = run_child(*program, real_command, env);
+
+ if (exit_status && this->abort_on_error)
+ return exit_status;
+ }
+ }
+
+ return exit_status;
+ }
+
+ int
+ run_parts::run_child (std::string const& file,
+ string_list const& command,
+ environment const& env)
+ {
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+ int exit_status = 0;
+ pid_t pid;
+
+ try
+ {
+ if (pipe(stdout_pipe) < 0)
+ throw error(PIPE, strerror(errno));
+ if (pipe(stderr_pipe) < 0)
+ throw error(PIPE, strerror(errno));
+
+ if ((pid = fork()) == -1)
+ {
+ throw error(CHILD_FORK, strerror(errno));
+ }
+ else if (pid == 0)
+ {
+ try
+ {
+ log_debug(DEBUG_INFO) << "run_parts: executing "
+ << string_list_to_string(command, ", ")
+ << std::endl;
+ if (this->verbose)
+ // TRANSLATORS: %1% = command
+ log_info() << format(_("Executing ‘%1%’"))
+ % string_list_to_string(command, " ")
+ << std::endl;
+ ::umask(this->umask);
+
+ // Don't leak syslog file descriptor to child processes.
+ closelog();
+
+ // Set up pipes for stdout and stderr
+ if (dup2(stdout_pipe[1], STDOUT_FILENO) < 0)
+ throw error(DUP, strerror(errno));
+ if (dup2(stderr_pipe[1], STDERR_FILENO) < 0)
+ throw error(DUP, strerror(errno));
+
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+
+ exec(this->directory + '/' + file, command, env);
+ error e(file, EXEC, strerror(errno));
+ log_exception_error(e);
+ }
+ catch (std::exception const& e)
+ {
+ log_exception_error(e);
+ }
+ catch (...)
+ {
+ log_error()
+ << _("An unknown exception occurred") << std::endl;
+ }
+ _exit(EXIT_FAILURE);
+ }
+
+ // Log stdout and stderr.
+ close(stdout_pipe[1]);
+ close(stderr_pipe[1]);
+
+ struct pollfd pollfds[2];
+ pollfds[0].fd = stdout_pipe[0];
+ pollfds[0].events = POLLIN;
+ pollfds[0].revents = 0;
+ pollfds[1].fd = stderr_pipe[0];
+ pollfds[1].events = POLLIN;
+ pollfds[1].revents = 0;
+
+ char buffer[BUFSIZ];
+
+ std::string stdout_buf;
+ std::string stderr_buf;
+
+ while (1)
+ {
+ int status;
+ if ((status = poll(pollfds, 2, -1)) < 0)
+ throw error(POLL, strerror(errno));
+
+ int outdata = 0;
+ int errdata = 0;
+
+ if (pollfds[1].revents & POLLIN)
+ {
+ if ((errdata = read(pollfds[1].fd, buffer, BUFSIZ)) < 0
+ && errno != EINTR)
+ throw error(READ, strerror(errno));
+
+ if (errdata)
+ stderr_buf += std::string(&buffer[0], errdata);
+ }
+
+ if (pollfds[0].revents & POLLIN)
+ {
+ if ((outdata = read(pollfds[0].fd, buffer, BUFSIZ)) < 0
+ && errno != EINTR)
+ throw error(READ, strerror(errno));
+
+ if (outdata)
+ stdout_buf += std::string(&buffer[0], outdata);
+ }
+
+ if (!stderr_buf.empty())
+ {
+ string_list lines = split_string_strict(stderr_buf, "\n");
+ // If the buffer ends in a newline before splitting,
+ // it's OK to flush all lines.
+ bool flush = *stderr_buf.rbegin() == '\n';
+
+ for (string_list::const_iterator pos = lines.begin();
+ pos != lines.end();
+ ++pos)
+ {
+ if (pos + 1 != lines.end() || flush)
+ log_error() << file << ": " << *pos << '\n';
+ else // Save possibly incompete line
+ stderr_buf = *pos;
+ }
+
+ if (flush)
+ stderr_buf.clear();
+ }
+
+ if (!stdout_buf.empty())
+ {
+ string_list lines = split_string_strict(stdout_buf, "\n");
+ // If the buffer ends in a newline before splitting,
+ // it's OK to flush all lines.
+ bool flush = *stdout_buf.rbegin() == '\n';
+
+ for (string_list::const_iterator pos = lines.begin();
+ pos != lines.end();
+ ++pos)
+ {
+ if (pos + 1 != lines.end() || flush)
+ log_info() << file << ": " << *pos << '\n';
+ else // Save possibly incompete line
+ stdout_buf = *pos;
+ }
+
+ if (flush)
+ stdout_buf.clear();
+ }
+
+ if (outdata == 0 && errdata == 0) // pipes closed
+ {
+ // Flush any remaining lines
+ if (!stderr_buf.empty())
+ log_error() << file << ": " << stderr_buf << '\n';
+ if (!stdout_buf.empty())
+ log_info() << file << ": " << stdout_buf << '\n';
+ break;
+ }
+ }
+
+ close(stdout_pipe[0]);
+ close(stderr_pipe[0]);
+ wait_for_child(pid, exit_status);
+ }
+ catch (error const& e)
+ {
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ throw;
+ }
+
+ if (exit_status)
+ log_debug(DEBUG_INFO) << "run_parts: " << file
+ << " failed with status " << exit_status
+ << std::endl;
+ else
+ log_debug(DEBUG_INFO) << "run_parts: " << file
+ << " succeeded"
+ << std::endl;
+
+ return exit_status;
+ }
+
+ void
+ run_parts::wait_for_child (pid_t pid,
+ int& child_status)
+ {
+ child_status = EXIT_FAILURE; // Default exit status
+
+ int status;
+
+ while (1)
+ {
+ if (waitpid(pid, &status, 0) == -1)
+ {
+ if (errno == EINTR)
+ continue; // Wait again.
+ else
+ throw error(CHILD_WAIT, strerror(errno));
+ }
+ else
+ break;
+ }
+
+ if (WIFEXITED(status))
+ child_status = WEXITSTATUS(status);
+ }
- while (1)
- {
- if (waitpid(pid, &status, 0) == -1)
- {
- if (errno == EINTR)
- continue; // Wait again.
- else
- throw error(CHILD_WAIT, strerror(errno));
- }
- else
- break;
- }
-
- if (WIFEXITED(status))
- child_status = WEXITSTATUS(status);
}
diff --git a/lib/sbuild/session.cc b/lib/sbuild/session.cc
index c24146f3..b198781e 100644
--- a/lib/sbuild/session.cc
+++ b/lib/sbuild/session.cc
@@ -56,1529 +56,1532 @@
#include <syslog.h>
-
#include <boost/format.hpp>
using std::cout;
using std::endl;
using boost::format;
-using namespace sbuild;
-namespace
+namespace sbuild
{
- volatile bool sighup_called = false;
- volatile bool sigint_called = false;
- volatile bool sigterm_called = false;
-
- /**
- * Handle the SIGHUP signal.
- *
- * @param ignore the signal number.
- */
- void
- sighup_handler (int ignore)
+ namespace
{
- /* This exists so that system calls get interrupted. */
- sighup_called = true;
- }
- /**
- * Handle the SIGINT signal.
- *
- * We explicitly do nothing with SIGINT, and rely on the exit status
- * of child processes to determine if we should care. We want to
- * make sure any child process (which will also have received
- * SIGINT) has exited before we do anything, and some child
- * processes (for example, emacs) may expect SIGINT during normal
- * operation. See http://www.cons.org/cracauer/sigint.html for a
- * good discussion of SIGINT handling.
-
- * @param ignore the signal number.
- */
- void
- sigint_handler (int ignore)
- {
- /*
- * Allows us to detect if an interrupted waitpid() was interrupted
- * due to SIGINT or something else. We may also want to use this
- * at exit time to see if we should re-kill ourselves with SIGINT.
+ volatile bool sighup_called = false;
+ volatile bool sigint_called = false;
+ volatile bool sigterm_called = false;
+
+ /**
+ * Handle the SIGHUP signal.
+ *
+ * @param ignore the signal number.
*/
- sigint_called = true;
- }
+ void
+ sighup_handler (int ignore)
+ {
+ /* This exists so that system calls get interrupted. */
+ sighup_called = true;
+ }
- /**
- * Handle the SIGTERM signal.
- *
- * @param ignore the signal number.
- */
- void
- sigterm_handler (int ignore)
- {
- /* This exists so that system calls get interrupted. */
- sigterm_called = true;
- }
+ /**
+ * Handle the SIGINT signal.
+ *
+ * We explicitly do nothing with SIGINT, and rely on the exit status
+ * of child processes to determine if we should care. We want to
+ * make sure any child process (which will also have received
+ * SIGINT) has exited before we do anything, and some child
+ * processes (for example, emacs) may expect SIGINT during normal
+ * operation. See http://www.cons.org/cracauer/sigint.html for a
+ * good discussion of SIGINT handling.
+
+ * @param ignore the signal number.
+ */
+ void
+ sigint_handler (int ignore)
+ {
+ /*
+ * Allows us to detect if an interrupted waitpid() was interrupted
+ * due to SIGINT or something else. We may also want to use this
+ * at exit time to see if we should re-kill ourselves with SIGINT.
+ */
+ sigint_called = true;
+ }
+
+ /**
+ * Handle the SIGTERM signal.
+ *
+ * @param ignore the signal number.
+ */
+ void
+ sigterm_handler (int ignore)
+ {
+ /* This exists so that system calls get interrupted. */
+ sigterm_called = true;
+ }
#ifdef SBUILD_DEBUG
- volatile bool child_wait = true;
+ volatile bool child_wait = true;
#endif
-}
+ }
-template<>
-error<session::error_code>::map_type
-error<session::error_code>::error_strings =
- {
- // TRANSLATORS: %1% = directory
- {session::CHDIR, N_("Failed to change to directory ‘%1%’")},
- // TRANSLATORS: %4% = directory
- {session::CHDIR_FB, N_("Falling back to directory ‘%4%’")},
- {session::CHILD_CORE, N_("Child dumped core")},
- {session::CHILD_FAIL, N_("Child exited abnormally (reason unknown; not a signal or core dump)")},
- {session::CHILD_FORK, N_("Failed to fork child")},
- // TRANSLATORS: %4% = signal name
- {session::CHILD_SIGNAL, N_("Child terminated by signal ‘%4%’")},
- {session::CHILD_WAIT, N_("Wait for child failed")},
- // TRANSLATORS: %1% = directory
- {session::CHROOT, N_("Failed to change root to directory ‘%1%’")},
- // TRANSLATORS: %1% = chroot name
- {session::CHROOT_ALIAS, N_("No chroot found matching name or alias ‘%1%’")},
- {session::CHROOT_LOCK, N_("Failed to lock chroot")},
- {session::CHROOT_NOTFOUND,N_("%1%: Chroot not found")},
- {session::CHROOT_SETUP, N_("Chroot setup failed")},
- // TRANSLATORS: %1% = chroot name
- {session::CHROOT_UNLOCK, N_("Failed to unlock chroot")},
- // TRANSLATORS: %1% = command
- {session::COMMAND_ABS, N_("Command “%1%” must have an absolute path")},
- // TRANSLATORS: %1% = command
- {session::EXEC, N_("Failed to execute “%1%”")},
- // TRANSLATORS: A supplementary group is the list of additional
- // system groups a user belongs to, in addition to their default
- // group.
- {session::GROUP_GET_SUP, N_("Failed to get supplementary groups")},
- // TRANSLATORS: A supplementary group is the list of additional
- // system groups a user belongs to, in addition to their default
- // group.
- {session::GROUP_GET_SUPC, N_("Failed to get supplementary group count")},
- // TRANSLATORS: %1% = integer group ID
- {session::GROUP_SET, N_("Failed to set group ‘%1%’")},
- {session::GROUP_SET_SUP, N_("Failed to set supplementary groups")},
- // TRANSLATORS: %1% = group name
- {session::GROUP_UNKNOWN, N_("Group ‘%1%’ not found")},
- {session::PAM, N_("PAM error")},
- {session::ROOT_DROP, N_("Failed to drop root permissions")},
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %4% = session identifier
- {session::SET_SESSION_ID, N_("%1%: Chroot does not support setting a session ID; ignoring session ID ‘%4%’")},
- // TRANSLATORS: %1% = command
- {session::SHELL, N_("Shell ‘%1%’ not available")},
- // TRANSLATORS: %4% = command
- {session::SHELL_FB, N_("Falling back to shell ‘%4%’")},
- // TRANSLATORS: %4% = signal name
- {session::SIGNAL_CATCH, N_("Caught signal ‘%4%’")},
- // TRANSLATORS: %4% = signal name
- {session::SIGNAL_SET, N_("Failed to set signal handler ‘%4%’")},
- // TRANSLATORS: %1% = integer user ID
- {session::USER_SET, N_("Failed to set user ‘%1%’")},
- // TRANSLATORS: %1% = user name
- // TRANSLATORS: %2% = user name
- // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
- {session::USER_SWITCH, N_("(%1%→%2%): User switching is not permitted")}
- };
-
-session::session (std::string const& service,
- operation operation,
- chroot_list const& chroots):
- authstat(
+ template<>
+ error<session::error_code>::map_type
+ error<session::error_code>::error_strings =
+ {
+ // TRANSLATORS: %1% = directory
+ {session::CHDIR, N_("Failed to change to directory ‘%1%’")},
+ // TRANSLATORS: %4% = directory
+ {session::CHDIR_FB, N_("Falling back to directory ‘%4%’")},
+ {session::CHILD_CORE, N_("Child dumped core")},
+ {session::CHILD_FAIL, N_("Child exited abnormally (reason unknown; not a signal or core dump)")},
+ {session::CHILD_FORK, N_("Failed to fork child")},
+ // TRANSLATORS: %4% = signal name
+ {session::CHILD_SIGNAL, N_("Child terminated by signal ‘%4%’")},
+ {session::CHILD_WAIT, N_("Wait for child failed")},
+ // TRANSLATORS: %1% = directory
+ {session::CHROOT, N_("Failed to change root to directory ‘%1%’")},
+ // TRANSLATORS: %1% = chroot name
+ {session::CHROOT_ALIAS, N_("No chroot found matching name or alias ‘%1%’")},
+ {session::CHROOT_LOCK, N_("Failed to lock chroot")},
+ {session::CHROOT_NOTFOUND,N_("%1%: Chroot not found")},
+ {session::CHROOT_SETUP, N_("Chroot setup failed")},
+ // TRANSLATORS: %1% = chroot name
+ {session::CHROOT_UNLOCK, N_("Failed to unlock chroot")},
+ // TRANSLATORS: %1% = command
+ {session::COMMAND_ABS, N_("Command “%1%” must have an absolute path")},
+ // TRANSLATORS: %1% = command
+ {session::EXEC, N_("Failed to execute “%1%”")},
+ // TRANSLATORS: A supplementary group is the list of additional
+ // system groups a user belongs to, in addition to their default
+ // group.
+ {session::GROUP_GET_SUP, N_("Failed to get supplementary groups")},
+ // TRANSLATORS: A supplementary group is the list of additional
+ // system groups a user belongs to, in addition to their default
+ // group.
+ {session::GROUP_GET_SUPC, N_("Failed to get supplementary group count")},
+ // TRANSLATORS: %1% = integer group ID
+ {session::GROUP_SET, N_("Failed to set group ‘%1%’")},
+ {session::GROUP_SET_SUP, N_("Failed to set supplementary groups")},
+ // TRANSLATORS: %1% = group name
+ {session::GROUP_UNKNOWN, N_("Group ‘%1%’ not found")},
+ {session::PAM, N_("PAM error")},
+ {session::ROOT_DROP, N_("Failed to drop root permissions")},
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %4% = session identifier
+ {session::SET_SESSION_ID, N_("%1%: Chroot does not support setting a session ID; ignoring session ID ‘%4%’")},
+ // TRANSLATORS: %1% = command
+ {session::SHELL, N_("Shell ‘%1%’ not available")},
+ // TRANSLATORS: %4% = command
+ {session::SHELL_FB, N_("Falling back to shell ‘%4%’")},
+ // TRANSLATORS: %4% = signal name
+ {session::SIGNAL_CATCH, N_("Caught signal ‘%4%’")},
+ // TRANSLATORS: %4% = signal name
+ {session::SIGNAL_SET, N_("Failed to set signal handler ‘%4%’")},
+ // TRANSLATORS: %1% = integer user ID
+ {session::USER_SET, N_("Failed to set user ‘%1%’")},
+ // TRANSLATORS: %1% = user name
+ // TRANSLATORS: %2% = user name
+ // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
+ {session::USER_SWITCH, N_("(%1%→%2%): User switching is not permitted")}
+ };
+
+ session::session (std::string const& service,
+ operation operation,
+ chroot_list const& chroots):
+ authstat(
#ifdef SBUILD_FEATURE_PAM
- auth::pam::create(service)
+ auth::pam::create(service)
#else
- auth::deny::create(service)
+ auth::deny::create(service)
#endif // SBUILD_FEATURE_PAM
- ),
- chroots(chroots),
- chroot_status(true),
- lock_status(true),
- child_status(EXIT_FAILURE),
- session_operation(operation),
- session_id(),
- force(false),
- saved_sighup_signal(),
- saved_sigint_signal(),
- saved_sigterm_signal(),
- saved_termios(),
- termios_ok(false),
- verbosity(),
- preserve_environment(false),
- shell(),
- user_options(),
- cwd(sbuild::getcwd())
-{
-}
-
-session::~session ()
-{
-}
+ ),
+ chroots(chroots),
+ chroot_status(true),
+ lock_status(true),
+ child_status(EXIT_FAILURE),
+ session_operation(operation),
+ session_id(),
+ force(false),
+ saved_sighup_signal(),
+ saved_sigint_signal(),
+ saved_sigterm_signal(),
+ saved_termios(),
+ termios_ok(false),
+ verbosity(),
+ preserve_environment(false),
+ shell(),
+ user_options(),
+ cwd(sbuild::getcwd())
+ {
+ }
-auth::auth::ptr const&
-session::get_auth () const
-{
- return this->authstat;
-}
+ session::~session ()
+ {
+ }
-void
-session::set_auth (auth::auth::ptr& auth)
-{
- this->authstat = auth;
-}
+ auth::auth::ptr const&
+ session::get_auth () const
+ {
+ return this->authstat;
+ }
-session::chroot_list const&
-session::get_chroots () const
-{
- return this->chroots;
-}
+ void
+ session::set_auth (auth::auth::ptr& auth)
+ {
+ this->authstat = auth;
+ }
-void
-session::set_chroots (chroot_list const& chroots)
-{
- this->chroots = chroots;
-}
+ session::chroot_list const&
+ session::get_chroots () const
+ {
+ return this->chroots;
+ }
-session::operation
-session::get_operation () const
-{
- return this->session_operation;
-}
+ void
+ session::set_chroots (chroot_list const& chroots)
+ {
+ this->chroots = chroots;
+ }
-void
-session::set_operation (operation operation)
-{
- this->session_operation = operation;
-}
+ session::operation
+ session::get_operation () const
+ {
+ return this->session_operation;
+ }
-std::string const&
-session::get_session_id () const
-{
- return this->session_id;
-}
+ void
+ session::set_operation (operation operation)
+ {
+ this->session_operation = operation;
+ }
-void
-session::set_session_id (std::string const& session_id)
-{
- this->session_id = session_id;
-}
+ std::string const&
+ session::get_session_id () const
+ {
+ return this->session_id;
+ }
-std::string const&
-session::get_verbosity () const
-{
- return this->verbosity;
-}
+ void
+ session::set_session_id (std::string const& session_id)
+ {
+ this->session_id = session_id;
+ }
-void
-session::set_verbosity (std::string const& verbosity)
-{
- this->verbosity = verbosity;
-}
+ std::string const&
+ session::get_verbosity () const
+ {
+ return this->verbosity;
+ }
-bool
-session::get_preserve_environment () const
-{
- return this->preserve_environment;
-}
+ void
+ session::set_verbosity (std::string const& verbosity)
+ {
+ this->verbosity = verbosity;
+ }
-void
-session::set_preserve_environment (bool preserve_environment)
-{
- this->preserve_environment = preserve_environment;
-}
+ bool
+ session::get_preserve_environment () const
+ {
+ return this->preserve_environment;
+ }
-std::string const&
-session::get_shell_override () const
-{
- return this->shell;
-}
+ void
+ session::set_preserve_environment (bool preserve_environment)
+ {
+ this->preserve_environment = preserve_environment;
+ }
-void
-session::set_shell_override (std::string const& shell)
-{
- this->shell = shell;
-}
+ std::string const&
+ session::get_shell_override () const
+ {
+ return this->shell;
+ }
-string_map const&
-session::get_user_options () const
-{
- return this->user_options;
-}
+ void
+ session::set_shell_override (std::string const& shell)
+ {
+ this->shell = shell;
+ }
-void
-session::set_user_options (string_map const& user_options)
-{
- this->user_options = user_options;
-}
+ string_map const&
+ session::get_user_options () const
+ {
+ return this->user_options;
+ }
-bool
-session::get_force () const
-{
- return this->force;
-}
+ void
+ session::set_user_options (string_map const& user_options)
+ {
+ this->user_options = user_options;
+ }
-void
-session::set_force (bool force)
-{
- this->force = force;
-}
+ bool
+ session::get_force () const
+ {
+ return this->force;
+ }
-void
-session::save_termios ()
-{
- string_list const& command(this->authstat->get_command());
+ void
+ session::set_force (bool force)
+ {
+ this->force = force;
+ }
- this->termios_ok = false;
+ void
+ session::save_termios ()
+ {
+ string_list const& command(this->authstat->get_command());
+
+ this->termios_ok = false;
+
+ // Save if running a login shell and have a controlling terminal.
+ if (CTTY_FILENO >= 0 &&
+ (command.empty() || command[0].empty()))
+ {
+ if (tcgetattr(CTTY_FILENO, &this->saved_termios) < 0)
+ {
+ log_warning()
+ << _("Error saving terminal settings")
+ << endl;
+ }
+ else
+ this->termios_ok = true;
+ }
+ }
- // Save if running a login shell and have a controlling terminal.
- if (CTTY_FILENO >= 0 &&
- (command.empty() || command[0].empty()))
- {
- if (tcgetattr(CTTY_FILENO, &this->saved_termios) < 0)
- {
+ void
+ session::restore_termios ()
+ {
+ string_list const& command(this->authstat->get_command());
+
+ // Restore if running a login shell and have a controlling terminal,
+ // and have previously saved the terminal state.
+ if (CTTY_FILENO >= 0 &&
+ (command.empty() || command[0].empty()) &&
+ termios_ok)
+ {
+ if (tcsetattr(CTTY_FILENO, TCSANOW, &this->saved_termios) < 0)
log_warning()
- << _("Error saving terminal settings")
+ << _("Error restoring terminal settings")
<< endl;
- }
- else
- this->termios_ok = true;
- }
-}
-
-void
-session::restore_termios ()
-{
- string_list const& command(this->authstat->get_command());
-
- // Restore if running a login shell and have a controlling terminal,
- // and have previously saved the terminal state.
- if (CTTY_FILENO >= 0 &&
- (command.empty() || command[0].empty()) &&
- termios_ok)
- {
- if (tcsetattr(CTTY_FILENO, TCSANOW, &this->saved_termios) < 0)
- log_warning()
- << _("Error restoring terminal settings")
- << endl;
- }
-}
-
-int
-session::get_child_status () const
-{
- return this->child_status;
-}
-
-/**
- * Check group membership.
- *
- * @param group the group to check for.
- * @returns true if the user is a member of group, otherwise false.
- */
-bool
-session::is_group_member (std::string const& groupname) const
-{
- errno = 0;
- sbuild::group grp(groupname);
- if (!grp)
- {
- if (errno == 0)
- log_debug(DEBUG_INFO) << "Group " << groupname << "not found" << endl;
- else
- log_debug(DEBUG_INFO) << "Group " << groupname
- << "not found: " << strerror(errno) << endl;
- return false;
- }
+ }
+ }
- bool group_member = false;
- if (grp.gr_gid == getgid())
- {
- group_member = true;
- }
- else
- {
- int supp_group_count = getgroups(0, 0);
- if (supp_group_count < 0)
- throw session::error(session::GROUP_GET_SUPC, strerror(errno));
- if (supp_group_count > 0)
- {
- gid_t *supp_groups = new gid_t[supp_group_count];
- assert (supp_groups);
- if (getgroups(supp_group_count, supp_groups) < 1)
- {
- // Free supp_groups before throwing to avoid leak.
- delete[] supp_groups;
- throw session::error(session::GROUP_GET_SUP, strerror(errno));
- }
-
- for (int i = 0; i < supp_group_count; ++i)
- {
- if (grp.gr_gid == supp_groups[i])
- group_member = true;
- }
- delete[] supp_groups;
- }
- }
+ int
+ session::get_child_status () const
+ {
+ return this->child_status;
+ }
- return group_member;
-}
+ /**
+ * Check group membership.
+ *
+ * @param group the group to check for.
+ * @returns true if the user is a member of group, otherwise false.
+ */
+ bool
+ session::is_group_member (std::string const& groupname) const
+ {
+ errno = 0;
+ sbuild::group grp(groupname);
+ if (!grp)
+ {
+ if (errno == 0)
+ log_debug(DEBUG_INFO) << "Group " << groupname << "not found" << endl;
+ else
+ log_debug(DEBUG_INFO) << "Group " << groupname
+ << "not found: " << strerror(errno) << endl;
+ return false;
+ }
+
+ bool group_member = false;
+ if (grp.gr_gid == getgid())
+ {
+ group_member = true;
+ }
+ else
+ {
+ int supp_group_count = getgroups(0, 0);
+ if (supp_group_count < 0)
+ throw session::error(session::GROUP_GET_SUPC, strerror(errno));
+ if (supp_group_count > 0)
+ {
+ gid_t *supp_groups = new gid_t[supp_group_count];
+ assert (supp_groups);
+ if (getgroups(supp_group_count, supp_groups) < 1)
+ {
+ // Free supp_groups before throwing to avoid leak.
+ delete[] supp_groups;
+ throw session::error(session::GROUP_GET_SUP, strerror(errno));
+ }
+
+ for (int i = 0; i < supp_group_count; ++i)
+ {
+ if (grp.gr_gid == supp_groups[i])
+ group_member = true;
+ }
+ delete[] supp_groups;
+ }
+ }
+
+ return group_member;
+ }
-void
-session::get_chroot_membership (chroot::chroot::ptr const& chroot,
- bool& in_users,
- bool& in_root_users,
- bool& in_groups,
- bool& in_root_groups) const
-{
- string_list const& users = chroot->get_users();
- string_list const& root_users = chroot->get_root_users();
- string_list const& groups = chroot->get_groups();
- string_list const& root_groups = chroot->get_root_groups();
-
- in_users = false;
- in_root_users = false;
- in_groups = false;
- in_root_groups = false;
-
- string_list::const_iterator upos =
- find(users.begin(), users.end(), this->authstat->get_ruser());
- if (upos != users.end())
- in_users = true;
-
- string_list::const_iterator rupos =
- find(root_users.begin(), root_users.end(), this->authstat->get_ruser());
- if (rupos != root_users.end())
- in_root_users = true;
-
- if (!groups.empty())
- {
- for (const auto& gp : groups)
- if (is_group_member(gp))
- in_groups = true;
- }
+ void
+ session::get_chroot_membership (chroot::chroot::ptr const& chroot,
+ bool& in_users,
+ bool& in_root_users,
+ bool& in_groups,
+ bool& in_root_groups) const
+ {
+ string_list const& users = chroot->get_users();
+ string_list const& root_users = chroot->get_root_users();
+ string_list const& groups = chroot->get_groups();
+ string_list const& root_groups = chroot->get_root_groups();
+
+ in_users = false;
+ in_root_users = false;
+ in_groups = false;
+ in_root_groups = false;
+
+ string_list::const_iterator upos =
+ find(users.begin(), users.end(), this->authstat->get_ruser());
+ if (upos != users.end())
+ in_users = true;
+
+ string_list::const_iterator rupos =
+ find(root_users.begin(), root_users.end(), this->authstat->get_ruser());
+ if (rupos != root_users.end())
+ in_root_users = true;
+
+ if (!groups.empty())
+ {
+ for (const auto& gp : groups)
+ if (is_group_member(gp))
+ in_groups = true;
+ }
+
+ if (!root_groups.empty())
+ {
+ for (const auto& rgp : root_groups)
+ if (is_group_member(rgp))
+ in_root_groups = true;
+ }
+
+ log_debug(DEBUG_INFO)
+ << "In users: " << in_users << endl
+ << "In groups: " << in_groups << endl
+ << "In root-users: " << in_root_users << endl
+ << "In root-groups: " << in_root_groups << endl;
- if (!root_groups.empty())
- {
- for (const auto& rgp : root_groups)
- if (is_group_member(rgp))
- in_root_groups = true;
- }
+ }
- log_debug(DEBUG_INFO)
- << "In users: " << in_users << endl
- << "In groups: " << in_groups << endl
- << "In root-users: " << in_root_users << endl
- << "In root-groups: " << in_root_groups << endl;
+ auth::auth::status
+ session::get_chroot_auth_status (auth::auth::status status,
+ chroot::chroot::ptr const& chroot) const
+ {
+ bool in_users = false;
+ bool in_root_users = false;
+ bool in_groups = false;
+ bool in_root_groups = false;
-}
+ get_chroot_membership(chroot,
+ in_users, in_root_users,
+ in_groups, in_root_groups);
-auth::auth::status
-session::get_chroot_auth_status (auth::auth::status status,
- chroot::chroot::ptr const& chroot) const
-{
- bool in_users = false;
- bool in_root_users = false;
- bool in_groups = false;
- bool in_root_groups = false;
-
- get_chroot_membership(chroot,
- in_users, in_root_users,
- in_groups, in_root_groups);
-
- /*
- * No auth required if in root users or root groups and
- * changing to root, or if the uid is not changing. If not
- * in user or group, authentication fails immediately.
- */
- if ((in_users == true || in_groups == true ||
- in_root_users == true || in_root_groups == true) &&
- this->authstat->get_ruid() == this->authstat->get_uid())
- {
- status = auth::auth::change_auth(status, auth::auth::STATUS_NONE);
- }
- else if ((in_root_users == true || in_root_groups == true) &&
- this->authstat->get_uid() == 0)
- {
- status = auth::auth::change_auth(status, auth::auth::STATUS_NONE);
- }
- else if (in_users == true || in_groups == true)
- // Auth required if not in root group
- {
- status = auth::auth::change_auth(status, auth::auth::STATUS_USER);
- }
- else // Not in any groups
- {
- if (this->authstat->get_ruid() == 0)
+ /*
+ * No auth required if in root users or root groups and
+ * changing to root, or if the uid is not changing. If not
+ * in user or group, authentication fails immediately.
+ */
+ if ((in_users == true || in_groups == true ||
+ in_root_users == true || in_root_groups == true) &&
+ this->authstat->get_ruid() == this->authstat->get_uid())
+ {
+ status = auth::auth::change_auth(status, auth::auth::STATUS_NONE);
+ }
+ else if ((in_root_users == true || in_root_groups == true) &&
+ this->authstat->get_uid() == 0)
+ {
+ status = auth::auth::change_auth(status, auth::auth::STATUS_NONE);
+ }
+ else if (in_users == true || in_groups == true)
+ // Auth required if not in root group
+ {
status = auth::auth::change_auth(status, auth::auth::STATUS_USER);
- else
- status = auth::auth::change_auth(status, auth::auth::STATUS_FAIL);
- }
-
- return status;
-}
-
-auth::auth::status
-session::get_auth_status () const
-{
- assert(!this->chroots.empty());
-
- /*
- * Note that the root user can't escape authentication. This is
- * because pam_rootok.so should be used in the PAM configuration if
- * root should automatically be granted access. The only exception
- * is that the root group doesn't need to be added to the groups or
- * root groups lists.
- */
+ }
+ else // Not in any groups
+ {
+ if (this->authstat->get_ruid() == 0)
+ status = auth::auth::change_auth(status, auth::auth::STATUS_USER);
+ else
+ status = auth::auth::change_auth(status, auth::auth::STATUS_FAIL);
+ }
+
+ return status;
+ }
- auth::auth::status status = auth::auth::STATUS_NONE;
+ auth::auth::status
+ session::get_auth_status () const
+ {
+ assert(!this->chroots.empty());
- /** @todo Use set difference rather than iteration and
- * is_group_member.
- */
- for (const auto& chrootent : this->chroots)
- status = auth::auth::change_auth(status,
- get_chroot_auth_status(status, chrootent.chroot));
+ /*
+ * Note that the root user can't escape authentication. This is
+ * because pam_rootok.so should be used in the PAM configuration if
+ * root should automatically be granted access. The only exception
+ * is that the root group doesn't need to be added to the groups or
+ * root groups lists.
+ */
- return status;
-}
+ auth::auth::status status = auth::auth::STATUS_NONE;
-void
-session::run ()
-{
- try
- {
- this->authstat->start();
- this->authstat->authenticate(get_auth_status());
- this->authstat->setupenv();
- this->authstat->account();
- try
- {
- this->authstat->cred_establish();
-
- run_impl();
-
- /* The session is now finished, either
- successfully or not. All PAM operations are
- now for cleanup and shutdown, and we must
- clean up whether or not errors were raised at
- any previous point. This means only the
- first error is reported back to the user. */
-
- /* Don't cope with failure, since we are now
- already bailing out, and an error may already
- have been raised */
- }
- catch (auth::auth::error const& e)
- {
- try
- {
- this->authstat->cred_delete();
- }
- catch (auth::auth::error const& discard)
- {
- }
- throw;
- }
- this->authstat->cred_delete();
- }
- catch (auth::auth::error const& e)
- {
- try
- {
- /* Don't cope with failure, since we are now already bailing out,
- and an error may already have been raised */
- this->authstat->stop();
- }
- catch (auth::auth::error const& discard)
- {
- }
- throw;
- }
- this->authstat->stop();
-}
+ /** @todo Use set difference rather than iteration and
+ * is_group_member.
+ */
+ for (const auto& chrootent : this->chroots)
+ status = auth::auth::change_auth(status,
+ get_chroot_auth_status(status, chrootent.chroot));
-void
-session::run_impl ()
-{
- assert(!this->chroots.empty());
+ return status;
+ }
- try
- {
- sighup_called = false;
- set_sighup_handler();
- sigint_called = false;
- set_sigint_handler();
- sigterm_called = false;
- set_sigterm_handler();
-
- for (const auto& chrootent : this->chroots)
- {
- log_debug(DEBUG_NOTICE)
- << format("Running session in %1% chroot:") % chrootent.alias
- << endl;
+ void
+ session::run ()
+ {
+ try
+ {
+ this->authstat->start();
+ this->authstat->authenticate(get_auth_status());
+ this->authstat->setupenv();
+ this->authstat->account();
+ try
+ {
+ this->authstat->cred_establish();
+
+ run_impl();
+
+ /* The session is now finished, either
+ successfully or not. All PAM operations are
+ now for cleanup and shutdown, and we must
+ clean up whether or not errors were raised at
+ any previous point. This means only the
+ first error is reported back to the user. */
+
+ /* Don't cope with failure, since we are now
+ already bailing out, and an error may already
+ have been raised */
+ }
+ catch (auth::auth::error const& e)
+ {
+ try
+ {
+ this->authstat->cred_delete();
+ }
+ catch (auth::auth::error const& discard)
+ {
+ }
+ throw;
+ }
+ this->authstat->cred_delete();
+ }
+ catch (auth::auth::error const& e)
+ {
+ try
+ {
+ /* Don't cope with failure, since we are now already bailing out,
+ and an error may already have been raised */
+ this->authstat->stop();
+ }
+ catch (auth::auth::error const& discard)
+ {
+ }
+ throw;
+ }
+ this->authstat->stop();
+ }
- const chroot::chroot::ptr ch = chrootent.chroot;
-
- // TODO: Make chroot/session selection automatically fail
- // if no session exists earlier on when selecting chroots.
- if (ch->get_session_flags() & chroot::facet::facet::SESSION_CREATE &&
- (this->session_operation != OPERATION_AUTOMATIC &&
- this->session_operation != OPERATION_BEGIN))
- throw error(chrootent.alias, CHROOT_NOTFOUND);
-
- // For now, use a copy of the chroot; if we create a session
- // later, we will replace it.
- chroot::chroot::ptr chroot(ch->clone());
- assert(chroot);
-
- /* Create a session using randomly-generated session ID. */
- if (ch->get_session_flags() & chroot::facet::facet::SESSION_CREATE)
- {
- assert(ch->get_facet<chroot::facet::session_clonable>());
-
- std::string new_session_id;
-
- if (!get_session_id().empty())
- {
- new_session_id = get_session_id();
- }
- else
- {
- new_session_id =
- ch->get_name() + '-' + unique_identifier();
- }
-
- // Replace clone of chroot with cloned session.
-
- bool in_users = false;
- bool in_root_users = false;
- bool in_groups = false;
- bool in_root_groups = false;
-
- get_chroot_membership(chroot,
- in_users, in_root_users,
- in_groups, in_root_groups);
-
- chroot = ch->clone_session(new_session_id,
- chrootent.alias,
- this->authstat->get_ruser(),
- (in_root_users || in_root_groups));
- assert(chroot->get_facet<chroot::facet::session>());
- }
- assert(chroot);
-
- // Override chroot verbosity if needed.
- if (!this->verbosity.empty())
- chroot->set_verbosity(this->verbosity);
-
- // Set user options.
- chroot::facet::userdata::ptr userdata =
- chroot->get_facet<chroot::facet::userdata>();
- if (userdata)
- {
- // If the user running the command is root, or the user
- // being switched to is root, permit setting of
- // root-modifiable options in addition to
- // user-modifiable options.
- if (this->authstat->get_uid() == 0 ||
- this->authstat->get_ruid() == 0)
- userdata->set_root_data(this->user_options);
- else
- userdata->set_user_data(this->user_options);
- }
-
- // Following authentication success, default child status to
- // success so that operations such as beginning, ending and
- // recovering sessions will return success unless an
- // exception is thrown.
- this->child_status = EXIT_SUCCESS;
-
- try
- {
- /* Run setup-start chroot setup scripts. */
- setup_chroot(chroot, chroot::chroot::SETUP_START);
- if (this->session_operation == OPERATION_BEGIN)
- {
- cout << chroot->get_name() << endl;
- }
-
- /* Run recover scripts. */
- setup_chroot(chroot, chroot::chroot::SETUP_RECOVER);
-
- try
- {
+ void
+ session::run_impl ()
+ {
+ assert(!this->chroots.empty());
+
+ try
+ {
+ sighup_called = false;
+ set_sighup_handler();
+ sigint_called = false;
+ set_sigint_handler();
+ sigterm_called = false;
+ set_sigterm_handler();
+
+ for (const auto& chrootent : this->chroots)
+ {
+ log_debug(DEBUG_NOTICE)
+ << format("Running session in %1% chroot:") % chrootent.alias
+ << endl;
+
+ const chroot::chroot::ptr ch = chrootent.chroot;
+
+ // TODO: Make chroot/session selection automatically fail
+ // if no session exists earlier on when selecting chroots.
+ if (ch->get_session_flags() & chroot::facet::facet::SESSION_CREATE &&
+ (this->session_operation != OPERATION_AUTOMATIC &&
+ this->session_operation != OPERATION_BEGIN))
+ throw error(chrootent.alias, CHROOT_NOTFOUND);
+
+ // For now, use a copy of the chroot; if we create a session
+ // later, we will replace it.
+ chroot::chroot::ptr chroot(ch->clone());
+ assert(chroot);
+
+ /* Create a session using randomly-generated session ID. */
+ if (ch->get_session_flags() & chroot::facet::facet::SESSION_CREATE)
+ {
+ assert(ch->get_facet<chroot::facet::session_clonable>());
+
+ std::string new_session_id;
+
+ if (!get_session_id().empty())
+ {
+ new_session_id = get_session_id();
+ }
+ else
+ {
+ new_session_id =
+ ch->get_name() + '-' + unique_identifier();
+ }
+
+ // Replace clone of chroot with cloned session.
+
+ bool in_users = false;
+ bool in_root_users = false;
+ bool in_groups = false;
+ bool in_root_groups = false;
+
+ get_chroot_membership(chroot,
+ in_users, in_root_users,
+ in_groups, in_root_groups);
+
+ chroot = ch->clone_session(new_session_id,
+ chrootent.alias,
+ this->authstat->get_ruser(),
+ (in_root_users || in_root_groups));
+ assert(chroot->get_facet<chroot::facet::session>());
+ }
+ assert(chroot);
+
+ // Override chroot verbosity if needed.
+ if (!this->verbosity.empty())
+ chroot->set_verbosity(this->verbosity);
+
+ // Set user options.
+ chroot::facet::userdata::ptr userdata =
+ chroot->get_facet<chroot::facet::userdata>();
+ if (userdata)
+ {
+ // If the user running the command is root, or the user
+ // being switched to is root, permit setting of
+ // root-modifiable options in addition to
+ // user-modifiable options.
+ if (this->authstat->get_uid() == 0 ||
+ this->authstat->get_ruid() == 0)
+ userdata->set_root_data(this->user_options);
+ else
+ userdata->set_user_data(this->user_options);
+ }
+
+ // Following authentication success, default child status to
+ // success so that operations such as beginning, ending and
+ // recovering sessions will return success unless an
+ // exception is thrown.
+ this->child_status = EXIT_SUCCESS;
+
+ try
+ {
+ /* Run setup-start chroot setup scripts. */
+ setup_chroot(chroot, chroot::chroot::SETUP_START);
+ if (this->session_operation == OPERATION_BEGIN)
+ {
+ cout << chroot->get_name() << endl;
+ }
+
+ /* Run recover scripts. */
+ setup_chroot(chroot, chroot::chroot::SETUP_RECOVER);
+
+ try
+ {
#ifdef SBUILD_FEATURE_UNSHARE
- /* Unshare execution context */
- chroot::facet::unshare::const_ptr pu = chroot->get_facet<chroot::facet::unshare>();
- if (pu)
- pu->do_unshare();
+ /* Unshare execution context */
+ chroot::facet::unshare::const_ptr pu = chroot->get_facet<chroot::facet::unshare>();
+ if (pu)
+ pu->do_unshare();
#endif // SBUILD_FEATURE_UNSHARE
- /* Run exec-start scripts. */
- setup_chroot(chroot, chroot::chroot::EXEC_START);
-
- /* Run session if setup succeeded. */
- if (this->session_operation == OPERATION_AUTOMATIC ||
- this->session_operation == OPERATION_RUN)
- {
- try
- {
- this->authstat->open_session();
- save_termios();
- run_chroot(chroot);
- }
- catch (std::runtime_error const& e)
- {
- log_debug(DEBUG_WARNING)
- << "Chroot session failed" << endl;
- restore_termios();
- this->authstat->close_session();
- throw;
- }
- restore_termios();
- this->authstat->close_session();
- }
- }
- catch (error const& e)
- {
- log_debug(DEBUG_WARNING)
- << "Chroot exec scripts or session failed" << endl;
- setup_chroot(chroot, chroot::chroot::EXEC_STOP);
- throw;
- }
-
- /* Run exec-stop scripts whether or not there was an
- error. */
- setup_chroot(chroot, chroot::chroot::EXEC_STOP);
- }
- catch (error const& e)
- {
- log_debug(DEBUG_WARNING)
- << "Chroot setup scripts, exec scripts or session failed" << endl;
- try
- {
- setup_chroot(chroot, chroot::chroot::SETUP_STOP);
- }
- catch (error const& discard)
- {
- log_debug(DEBUG_WARNING)
- << "Chroot setup scripts failed during stop" << endl;
- }
- throw;
- }
-
- /* Run setup-stop chroot setup scripts whether or not there
- was an error. */
- setup_chroot(chroot, chroot::chroot::SETUP_STOP);
- }
- }
- catch (error const& e)
- {
- clear_sigterm_handler();
- clear_sigint_handler();
- clear_sighup_handler();
-
- /* If a command was not run, but something failed, the exit
- status still needs setting. */
- if (this->child_status == 0)
- this->child_status = EXIT_FAILURE;
- throw;
- }
+ /* Run exec-start scripts. */
+ setup_chroot(chroot, chroot::chroot::EXEC_START);
+
+ /* Run session if setup succeeded. */
+ if (this->session_operation == OPERATION_AUTOMATIC ||
+ this->session_operation == OPERATION_RUN)
+ {
+ try
+ {
+ this->authstat->open_session();
+ save_termios();
+ run_chroot(chroot);
+ }
+ catch (std::runtime_error const& e)
+ {
+ log_debug(DEBUG_WARNING)
+ << "Chroot session failed" << endl;
+ restore_termios();
+ this->authstat->close_session();
+ throw;
+ }
+ restore_termios();
+ this->authstat->close_session();
+ }
+ }
+ catch (error const& e)
+ {
+ log_debug(DEBUG_WARNING)
+ << "Chroot exec scripts or session failed" << endl;
+ setup_chroot(chroot, chroot::chroot::EXEC_STOP);
+ throw;
+ }
+
+ /* Run exec-stop scripts whether or not there was an
+ error. */
+ setup_chroot(chroot, chroot::chroot::EXEC_STOP);
+ }
+ catch (error const& e)
+ {
+ log_debug(DEBUG_WARNING)
+ << "Chroot setup scripts, exec scripts or session failed" << endl;
+ try
+ {
+ setup_chroot(chroot, chroot::chroot::SETUP_STOP);
+ }
+ catch (error const& discard)
+ {
+ log_debug(DEBUG_WARNING)
+ << "Chroot setup scripts failed during stop" << endl;
+ }
+ throw;
+ }
+
+ /* Run setup-stop chroot setup scripts whether or not there
+ was an error. */
+ setup_chroot(chroot, chroot::chroot::SETUP_STOP);
+ }
+ }
+ catch (error const& e)
+ {
+ clear_sigterm_handler();
+ clear_sigint_handler();
+ clear_sighup_handler();
+
+ /* If a command was not run, but something failed, the exit
+ status still needs setting. */
+ if (this->child_status == 0)
+ this->child_status = EXIT_FAILURE;
+ throw;
+ }
+
+ clear_sigterm_handler();
+ clear_sigint_handler();
+ clear_sighup_handler();
+ }
- clear_sigterm_handler();
- clear_sigint_handler();
- clear_sighup_handler();
-}
+ string_list
+ session::get_login_directories (chroot::chroot::ptr& session_chroot,
+ environment const& env) const
+ {
+ string_list ret;
+
+ std::string const& wd(this->authstat->get_wd());
+ if (!wd.empty())
+ {
+ // Set specified working directory.
+ ret.push_back(wd);
+ }
+ else
+ {
+ // Set current working directory.
+ ret.push_back(this->cwd);
+
+ // Set $HOME.
+ std::string home;
+ if (env.get("HOME", home) &&
+ std::find(ret.begin(), ret.end(), home) == ret.end())
+ ret.push_back(home);
+
+ // Set passwd home.
+ if (std::find(ret.begin(), ret.end(), this->authstat->get_home()) == ret.end())
+ ret.push_back(this->authstat->get_home());
+
+ // Final fallback to root.
+ if (std::find(ret.begin(), ret.end(), "/") == ret.end())
+ ret.push_back("/");
+ }
+
+ return ret;
+ }
-string_list
-session::get_login_directories (chroot::chroot::ptr& session_chroot,
- environment const& env) const
-{
- string_list ret;
+ string_list
+ session::get_command_directories (chroot::chroot::ptr& session_chroot,
+ environment const& env) const
+ {
+ string_list ret;
- std::string const& wd(this->authstat->get_wd());
- if (!wd.empty())
- {
+ std::string const& wd(this->authstat->get_wd());
+ if (!wd.empty())
// Set specified working directory.
ret.push_back(wd);
- }
- else
- {
+ else
// Set current working directory.
ret.push_back(this->cwd);
- // Set $HOME.
- std::string home;
- if (env.get("HOME", home) &&
- std::find(ret.begin(), ret.end(), home) == ret.end())
- ret.push_back(home);
-
- // Set passwd home.
- if (std::find(ret.begin(), ret.end(), this->authstat->get_home()) == ret.end())
- ret.push_back(this->authstat->get_home());
-
- // Final fallback to root.
- if (std::find(ret.begin(), ret.end(), "/") == ret.end())
- ret.push_back("/");
- }
-
- return ret;
-}
-
-string_list
-session::get_command_directories (chroot::chroot::ptr& session_chroot,
- environment const& env) const
-{
- string_list ret;
-
- std::string const& wd(this->authstat->get_wd());
- if (!wd.empty())
- // Set specified working directory.
- ret.push_back(wd);
- else
- // Set current working directory.
- ret.push_back(this->cwd);
-
- return ret;
-}
-
-string_list
-session::get_shells (chroot::chroot::ptr& session_chroot) const
-{
- string_list ret;
-
- // Shell set with --shell (if any)
- if (!this->shell.empty())
- {
- ret.push_back(this->shell);
- }
- else if (!session_chroot->get_default_shell().empty())
- {
- ret.push_back(session_chroot->get_default_shell());
- }
- else
- {
- if (get_preserve_environment())
- {
- // $SHELL (if --preserve-environment used)
- environment const& env(this->authstat->get_complete_environment());
-
- std::string envshell;
- if (env.get("SHELL", envshell) &&
- std::find(ret.begin(), ret.end(), envshell) == ret.end())
- ret.push_back(envshell);
- }
-
- // passwd pw_shell
- std::string const& shell = this->authstat->get_shell();
- if (!shell.empty())
- ret.push_back(shell);
-
- // Fallback nice interactive shell
- if (std::find(ret.begin(), ret.end(), "/bin/bash") == ret.end())
- ret.push_back("/bin/bash");
-
- // Fallback basic interactive shell
- if (std::find(ret.begin(), ret.end(), "/bin/sh") == ret.end())
- ret.push_back("/bin/sh");
- }
-
- return ret;
-}
-
-std::string
-session::get_shell (chroot::chroot::ptr& session_chroot) const
-{
- string_list shells(get_shells(session_chroot));
-
- std::string found_shell;
-
- for (const auto& shell : shells)
- {
- try
- {
- stat(shell).check();
- found_shell = shell;
- break;
- }
- catch (std::runtime_error const& e)
- {
- error e1(shell, SHELL, e.what());
- log_exception_warning(e1);
- }
- }
-
- if (found_shell != *shells.begin())
- {
- error e2(SHELL_FB, shell);
- log_exception_warning(e2);
- }
-
- return found_shell;
-}
+ return ret;
+ }
-void
-session::get_command (chroot::chroot::ptr& session_chroot,
- std::string& file,
- string_list& command,
- environment& env) const
-{
- /* Run login shell */
- if (command.empty() ||
- command[0].empty()) // No command
- get_login_command(session_chroot, file, command, env);
- else
- get_user_command(session_chroot, file, command, env);
-}
+ string_list
+ session::get_shells (chroot::chroot::ptr& session_chroot) const
+ {
+ string_list ret;
+
+ // Shell set with --shell (if any)
+ if (!this->shell.empty())
+ {
+ ret.push_back(this->shell);
+ }
+ else if (!session_chroot->get_default_shell().empty())
+ {
+ ret.push_back(session_chroot->get_default_shell());
+ }
+ else
+ {
+ if (get_preserve_environment())
+ {
+ // $SHELL (if --preserve-environment used)
+ environment const& env(this->authstat->get_complete_environment());
+
+ std::string envshell;
+ if (env.get("SHELL", envshell) &&
+ std::find(ret.begin(), ret.end(), envshell) == ret.end())
+ ret.push_back(envshell);
+ }
+
+ // passwd pw_shell
+ std::string const& shell = this->authstat->get_shell();
+ if (!shell.empty())
+ ret.push_back(shell);
+
+ // Fallback nice interactive shell
+ if (std::find(ret.begin(), ret.end(), "/bin/bash") == ret.end())
+ ret.push_back("/bin/bash");
+
+ // Fallback basic interactive shell
+ if (std::find(ret.begin(), ret.end(), "/bin/sh") == ret.end())
+ ret.push_back("/bin/sh");
+ }
+
+ return ret;
+ }
-void
-session::get_login_command (chroot::chroot::ptr& session_chroot,
- std::string& file,
- string_list& command,
- environment& env) const
-{
- command.clear();
+ std::string
+ session::get_shell (chroot::chroot::ptr& session_chroot) const
+ {
+ string_list shells(get_shells(session_chroot));
+
+ std::string found_shell;
+
+ for (const auto& shell : shells)
+ {
+ try
+ {
+ stat(shell).check();
+ found_shell = shell;
+ break;
+ }
+ catch (std::runtime_error const& e)
+ {
+ error e1(shell, SHELL, e.what());
+ log_exception_warning(e1);
+ }
+ }
+
+ if (found_shell != *shells.begin())
+ {
+ error e2(SHELL_FB, shell);
+ log_exception_warning(e2);
+ }
+
+ return found_shell;
+ }
- std::string shell = get_shell(session_chroot);
- file = shell;
- env.add("SHELL", shell);
+ void
+ session::get_command (chroot::chroot::ptr& session_chroot,
+ std::string& file,
+ string_list& command,
+ environment& env) const
+ {
+ /* Run login shell */
+ if (command.empty() ||
+ command[0].empty()) // No command
+ get_login_command(session_chroot, file, command, env);
+ else
+ get_user_command(session_chroot, file, command, env);
+ }
- bool login_shell =
- !(get_preserve_environment() ||
- session_chroot->get_preserve_environment()) &&
- session_chroot->get_command_prefix().empty();
+ void
+ session::get_login_command (chroot::chroot::ptr& session_chroot,
+ std::string& file,
+ string_list& command,
+ environment& env) const
+ {
+ command.clear();
+
+ std::string shell = get_shell(session_chroot);
+ file = shell;
+ env.add("SHELL", shell);
+
+ bool login_shell =
+ !(get_preserve_environment() ||
+ session_chroot->get_preserve_environment()) &&
+ session_chroot->get_command_prefix().empty();
+
+ // Not keeping environment and can setup argv correctly; login shell
+ if (login_shell)
+ {
+ std::string shellbase = basename(shell);
+ std::string loginshell = "-" + shellbase;
+ command.push_back(loginshell);
+
+ log_debug(DEBUG_NOTICE)
+ << format("Running login shell: %1%") % shell << endl;
+ if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
+ syslog(LOG_USER|LOG_NOTICE,
+ "[%s chroot] (%s->%s) Running login shell: '%s'",
+ session_chroot->get_name().c_str(),
+ this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(),
+ shell.c_str());
+ }
+ else
+ {
+ command.push_back(shell);
+ log_debug(DEBUG_NOTICE)
+ << format("Running shell: %1%") % shell << endl;
+ if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
+ syslog(LOG_USER|LOG_NOTICE,
+ "[%s chroot] (%s->%s) Running shell: '%s'",
+ session_chroot->get_name().c_str(),
+ this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(),
+ shell.c_str());
+ }
+
+ if (session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE)
+ {
+ std::string format_string;
+ if (this->authstat->get_ruid() == this->authstat->get_uid())
+ {
+ if (login_shell)
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %4% = command
+ format_string = _("[%1% chroot] Running login shell: ‘%4%’");
+ else
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %4% = command
+ format_string = _("[%1% chroot] Running shell: ‘%4%’");
+ }
+ else
+ {
+ if (login_shell)
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %2% = user name
+ // TRANSLATORS: %3% = user name
+ // TRANSLATORS: %4% = command
+ // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
+ format_string = _("[%1% chroot] (%2%→%3%) Running login shell: ‘%4%’");
+ else
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %2% = user name
+ // TRANSLATORS: %3% = user name
+ // TRANSLATORS: %4% = command
+ // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
+ format_string = _("[%1% chroot] (%2%→%3%) Running shell: ‘%4%’");
+ }
+
+ format fmt(format_string);
+ fmt % session_chroot->get_name()
+ % this->authstat->get_ruser() % this->authstat->get_user()
+ % shell;
+ log_info() << fmt << endl;
+ }
+ }
- // Not keeping environment and can setup argv correctly; login shell
- if (login_shell)
- {
- std::string shellbase = basename(shell);
- std::string loginshell = "-" + shellbase;
- command.push_back(loginshell);
-
- log_debug(DEBUG_NOTICE)
- << format("Running login shell: %1%") % shell << endl;
- if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
- syslog(LOG_USER|LOG_NOTICE,
- "[%s chroot] (%s->%s) Running login shell: '%s'",
- session_chroot->get_name().c_str(),
- this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(),
- shell.c_str());
- }
- else
- {
- command.push_back(shell);
- log_debug(DEBUG_NOTICE)
- << format("Running shell: %1%") % shell << endl;
- if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
- syslog(LOG_USER|LOG_NOTICE,
- "[%s chroot] (%s->%s) Running shell: '%s'",
- session_chroot->get_name().c_str(),
- this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(),
- shell.c_str());
- }
+ void
+ session::get_user_command (chroot::chroot::ptr& session_chroot,
+ std::string& file,
+ string_list& command,
+ environment const& env) const
+ {
+ /* Search for program in path. */
+ std::string path;
+ if (!env.get("PATH", path))
+ path.clear();
+
+ file = find_program_in_path(command[0], path, "");
+ if (file.empty())
+ file = command[0];
+ std::string commandstring = string_list_to_string(command, " ");
+ log_debug(DEBUG_NOTICE)
+ << format("Running command: %1%") % commandstring << endl;
+ if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
+ syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
+ session_chroot->get_name().c_str(), this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(), commandstring.c_str());
+
+ if (session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE)
+ {
+ std::string format_string;
+ if (this->authstat->get_ruid() == this->authstat->get_uid())
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %4% = command
+ format_string = _("[%1% chroot] Running command: “%4%”");
+ else
+ // TRANSLATORS: %1% = chroot name
+ // TRANSLATORS: %2% = user name
+ // TRANSLATORS: %3% = user name
+ // TRANSLATORS: %4% = command
+ // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
+ format_string = (_("[%1% chroot] (%2%→%3%) Running command: “%4%”"));
+
+ format fmt(format_string);
+ fmt % session_chroot->get_name()
+ % this->authstat->get_ruser() % this->authstat->get_user()
+ % commandstring;
+ log_info() << fmt << endl;
+ }
+ }
- if (session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE)
- {
- std::string format_string;
- if (this->authstat->get_ruid() == this->authstat->get_uid())
- {
- if (login_shell)
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %4% = command
- format_string = _("[%1% chroot] Running login shell: ‘%4%’");
- else
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %4% = command
- format_string = _("[%1% chroot] Running shell: ‘%4%’");
- }
- else
- {
- if (login_shell)
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %2% = user name
- // TRANSLATORS: %3% = user name
- // TRANSLATORS: %4% = command
- // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
- format_string = _("[%1% chroot] (%2%→%3%) Running login shell: ‘%4%’");
- else
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %2% = user name
- // TRANSLATORS: %3% = user name
- // TRANSLATORS: %4% = command
- // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
- format_string = _("[%1% chroot] (%2%→%3%) Running shell: ‘%4%’");
- }
-
- format fmt(format_string);
- fmt % session_chroot->get_name()
- % this->authstat->get_ruser() % this->authstat->get_user()
- % shell;
- log_info() << fmt << endl;
- }
-}
+ void
+ session::setup_chroot (chroot::chroot::ptr& session_chroot,
+ chroot::chroot::setup_type setup_type)
+ {
+ assert(!session_chroot->get_name().empty());
-void
-session::get_user_command (chroot::chroot::ptr& session_chroot,
- std::string& file,
- string_list& command,
- environment const& env) const
-{
- /* Search for program in path. */
- std::string path;
- if (!env.get("PATH", path))
- path.clear();
-
- file = find_program_in_path(command[0], path, "");
- if (file.empty())
- file = command[0];
- std::string commandstring = string_list_to_string(command, " ");
- log_debug(DEBUG_NOTICE)
- << format("Running command: %1%") % commandstring << endl;
- if (this->authstat->get_uid() == 0 || this->authstat->get_ruid() != this->authstat->get_uid())
- syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
- session_chroot->get_name().c_str(), this->authstat->get_ruser().c_str(), this->authstat->get_user().c_str(), commandstring.c_str());
-
- if (session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE)
- {
- std::string format_string;
- if (this->authstat->get_ruid() == this->authstat->get_uid())
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %4% = command
- format_string = _("[%1% chroot] Running command: “%4%”");
- else
- // TRANSLATORS: %1% = chroot name
- // TRANSLATORS: %2% = user name
- // TRANSLATORS: %3% = user name
- // TRANSLATORS: %4% = command
- // TRANSLATORS: Please translate "->" as a right arrow, e.g. U+2192
- format_string = (_("[%1% chroot] (%2%→%3%) Running command: “%4%”"));
-
- format fmt(format_string);
- fmt % session_chroot->get_name()
- % this->authstat->get_ruser() % this->authstat->get_user()
- % commandstring;
- log_info() << fmt << endl;
- }
-}
+ log_debug(DEBUG_INFO) << format("setup_chroot: chroot=%1%, setup_type=%2%, chroot_status=%3%, lock_status=%4%")
+ % session_chroot->get_name() % setup_type % chroot_status % lock_status
+ << std::endl;
-void
-session::setup_chroot (chroot::chroot::ptr& session_chroot,
- chroot::chroot::setup_type setup_type)
-{
- assert(!session_chroot->get_name().empty());
-
- log_debug(DEBUG_INFO) << format("setup_chroot: chroot=%1%, setup_type=%2%, chroot_status=%3%, lock_status=%4%")
- % session_chroot->get_name() % setup_type % chroot_status % lock_status
- << std::endl;
-
- if (!((this->session_operation == OPERATION_BEGIN &&
- setup_type == chroot::chroot::SETUP_START) ||
- (this->session_operation == OPERATION_RECOVER &&
- setup_type == chroot::chroot::SETUP_RECOVER) ||
- (this->session_operation == OPERATION_END &&
- setup_type == chroot::chroot::SETUP_STOP) ||
- (this->session_operation == OPERATION_RUN &&
- (setup_type == chroot::chroot::EXEC_START ||
- setup_type == chroot::chroot::EXEC_STOP)) ||
- (this->session_operation == OPERATION_AUTOMATIC &&
- (setup_type == chroot::chroot::SETUP_START ||
+ if (!((this->session_operation == OPERATION_BEGIN &&
+ setup_type == chroot::chroot::SETUP_START) ||
+ (this->session_operation == OPERATION_RECOVER &&
+ setup_type == chroot::chroot::SETUP_RECOVER) ||
+ (this->session_operation == OPERATION_END &&
+ setup_type == chroot::chroot::SETUP_STOP) ||
+ (this->session_operation == OPERATION_RUN &&
+ (setup_type == chroot::chroot::EXEC_START ||
+ setup_type == chroot::chroot::EXEC_STOP)) ||
+ (this->session_operation == OPERATION_AUTOMATIC &&
+ (setup_type == chroot::chroot::SETUP_START ||
+ setup_type == chroot::chroot::SETUP_STOP ||
+ setup_type == chroot::chroot::EXEC_START ||
+ setup_type == chroot::chroot::EXEC_STOP))))
+ return;
+
+ // Don't clean up chroot on a lock failure--it's actually in use.
+ if (this->lock_status == false)
+ return;
+
+ if (((setup_type == chroot::chroot::SETUP_START ||
+ setup_type == chroot::chroot::SETUP_RECOVER ||
setup_type == chroot::chroot::SETUP_STOP ||
setup_type == chroot::chroot::EXEC_START ||
- setup_type == chroot::chroot::EXEC_STOP))))
- return;
-
- // Don't clean up chroot on a lock failure--it's actually in use.
- if (this->lock_status == false)
- return;
-
- if (((setup_type == chroot::chroot::SETUP_START ||
- setup_type == chroot::chroot::SETUP_RECOVER ||
- setup_type == chroot::chroot::SETUP_STOP ||
- setup_type == chroot::chroot::EXEC_START ||
- setup_type == chroot::chroot::EXEC_STOP) &&
- session_chroot->get_run_setup_scripts() == false))
- return;
-
- if (setup_type == chroot::chroot::SETUP_START)
- this->chroot_status = true;
-
- try
- {
- session_chroot->lock(setup_type);
- }
- catch (chroot::chroot::error const& e)
- {
- this->chroot_status = false;
- this->lock_status = false;
- try
- {
- // Release lock, which also removes session metadata.
- session_chroot->unlock(setup_type, 0);
- }
- catch (chroot::chroot::error const& ignore)
- {
- }
- throw error(session_chroot->get_name(), CHROOT_LOCK, e);
- }
-
- std::string setup_type_string;
- if (setup_type == chroot::chroot::SETUP_START)
- setup_type_string = "setup-start";
- else if (setup_type == chroot::chroot::SETUP_RECOVER)
- setup_type_string = "setup-recover";
- else if (setup_type == chroot::chroot::SETUP_STOP)
- setup_type_string = "setup-stop";
- else if (setup_type == chroot::chroot::EXEC_START)
- setup_type_string = "exec-start";
- else if (setup_type == chroot::chroot::EXEC_STOP)
- setup_type_string = "exec-stop";
-
- std::string chroot_status_string;
- if (this->chroot_status)
- chroot_status_string = "ok";
- else
- chroot_status_string = "fail";
-
- string_list arg_list;
- arg_list.push_back(setup_type_string);
- arg_list.push_back(chroot_status_string);
-
- /* Get a complete list of environment variables to set. We need to
- query the chroot here, since this can vary depending upon the
- chroot type. */
- environment env;
- session_chroot->setup_env(env);
- env.add("AUTH_USER", this->authstat->get_user());
- env.add("AUTH_RUSER", this->authstat->get_ruser());
- env.add("AUTH_RGROUP", this->authstat->get_rgroup());
- env.add("AUTH_UID", this->authstat->get_uid());
- env.add("AUTH_GID", this->authstat->get_gid());
- env.add("AUTH_RUID", this->authstat->get_ruid());
- env.add("AUTH_RGID", this->authstat->get_rgid());
- env.add("AUTH_HOME", this->authstat->get_home());
- env.add("AUTH_SHELL", this->authstat->get_shell());
-
- env.add("VERBOSE", session_chroot->get_verbosity_string());
- env.add("MOUNT_DIR", SCHROOT_MOUNT_DIR);
- env.add("LIBEXEC_DIR", SCHROOT_LIBEXEC_DIR);
- env.add("SYSCONF_DIR", SCHROOT_SYSCONF_DIR);
- env.add("DATA_DIR", SCHROOT_DATA_DIR);
- env.add("SETUP_DATA_DIR", SCHROOT_SETUP_DATA_DIR);
- env.add("PID", getpid());
- env.add("HOST", SBUILD_HOST);
- env.add("HOST_OS", SBUILD_HOST_OS);
- env.add("HOST_VENDOR", SBUILD_HOST_VENDOR);
- env.add("HOST_CPU", SBUILD_HOST_CPU);
- env.add("PLATFORM", SBUILD_PLATFORM);
-
- env.add("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
-
- run_parts rp(SCHROOT_CONF_SETUP_D,
- true, true, 022);
- rp.set_reverse(setup_type == chroot::chroot::SETUP_STOP ||
- setup_type == chroot::chroot::EXEC_STOP);
- rp.set_verbose(session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE);
-
- log_debug(DEBUG_INFO) << rp << std::endl;
-
- int exit_status = 0;
- pid_t pid;
-
- if ((pid = fork()) == -1)
- {
- this->chroot_status = false;
- throw error(session_chroot->get_name(), CHILD_FORK, strerror(errno));
- }
- else if (pid == 0)
- {
- try
- {
- // The setup scripts don't use our syslog fd.
- closelog();
-
- if (chdir("/"))
- throw error("/", CHDIR, strerror(errno));
- /* This is required to ensure the scripts run with uid=0 and gid=0,
- otherwise setuid programs such as mount(8) will fail. This
- should always succeed, because our euid=0 and egid=0.*/
- setuid(0);
- setgid(0);
- initgroups("root", 0);
-
- int status = rp.run(arg_list, env);
-
- _exit (status);
- }
- catch (std::exception const& e)
- {
- log_exception_error(e);
- }
- catch (...)
- {
- log_error()
- << _("An unknown exception occurred") << std::endl;
- }
- _exit(EXIT_FAILURE);
- }
- else
- {
- wait_for_child(pid, exit_status);
- }
-
- try
- {
- session_chroot->unlock(setup_type, exit_status);
- }
- catch (chroot::chroot::error const& e)
- {
- this->chroot_status = false;
- this->lock_status = false;
- throw error(session_chroot->get_name(), CHROOT_UNLOCK, e);
- }
-
- if (exit_status != 0)
- {
- this->chroot_status = false;
-
- format fmt(_("stage=%1%"));
- fmt % setup_type_string;
- throw error(session_chroot->get_name(), CHROOT_SETUP, fmt.str());
- }
-}
+ setup_type == chroot::chroot::EXEC_STOP) &&
+ session_chroot->get_run_setup_scripts() == false))
+ return;
+
+ if (setup_type == chroot::chroot::SETUP_START)
+ this->chroot_status = true;
+
+ try
+ {
+ session_chroot->lock(setup_type);
+ }
+ catch (chroot::chroot::error const& e)
+ {
+ this->chroot_status = false;
+ this->lock_status = false;
+ try
+ {
+ // Release lock, which also removes session metadata.
+ session_chroot->unlock(setup_type, 0);
+ }
+ catch (chroot::chroot::error const& ignore)
+ {
+ }
+ throw error(session_chroot->get_name(), CHROOT_LOCK, e);
+ }
+
+ std::string setup_type_string;
+ if (setup_type == chroot::chroot::SETUP_START)
+ setup_type_string = "setup-start";
+ else if (setup_type == chroot::chroot::SETUP_RECOVER)
+ setup_type_string = "setup-recover";
+ else if (setup_type == chroot::chroot::SETUP_STOP)
+ setup_type_string = "setup-stop";
+ else if (setup_type == chroot::chroot::EXEC_START)
+ setup_type_string = "exec-start";
+ else if (setup_type == chroot::chroot::EXEC_STOP)
+ setup_type_string = "exec-stop";
+
+ std::string chroot_status_string;
+ if (this->chroot_status)
+ chroot_status_string = "ok";
+ else
+ chroot_status_string = "fail";
+
+ string_list arg_list;
+ arg_list.push_back(setup_type_string);
+ arg_list.push_back(chroot_status_string);
+
+ /* Get a complete list of environment variables to set. We need to
+ query the chroot here, since this can vary depending upon the
+ chroot type. */
+ environment env;
+ session_chroot->setup_env(env);
+ env.add("AUTH_USER", this->authstat->get_user());
+ env.add("AUTH_RUSER", this->authstat->get_ruser());
+ env.add("AUTH_RGROUP", this->authstat->get_rgroup());
+ env.add("AUTH_UID", this->authstat->get_uid());
+ env.add("AUTH_GID", this->authstat->get_gid());
+ env.add("AUTH_RUID", this->authstat->get_ruid());
+ env.add("AUTH_RGID", this->authstat->get_rgid());
+ env.add("AUTH_HOME", this->authstat->get_home());
+ env.add("AUTH_SHELL", this->authstat->get_shell());
+
+ env.add("VERBOSE", session_chroot->get_verbosity_string());
+ env.add("MOUNT_DIR", SCHROOT_MOUNT_DIR);
+ env.add("LIBEXEC_DIR", SCHROOT_LIBEXEC_DIR);
+ env.add("SYSCONF_DIR", SCHROOT_SYSCONF_DIR);
+ env.add("DATA_DIR", SCHROOT_DATA_DIR);
+ env.add("SETUP_DATA_DIR", SCHROOT_SETUP_DATA_DIR);
+ env.add("PID", getpid());
+ env.add("HOST", SBUILD_HOST);
+ env.add("HOST_OS", SBUILD_HOST_OS);
+ env.add("HOST_VENDOR", SBUILD_HOST_VENDOR);
+ env.add("HOST_CPU", SBUILD_HOST_CPU);
+ env.add("PLATFORM", SBUILD_PLATFORM);
+
+ env.add("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
+
+ run_parts rp(SCHROOT_CONF_SETUP_D,
+ true, true, 022);
+ rp.set_reverse(setup_type == chroot::chroot::SETUP_STOP ||
+ setup_type == chroot::chroot::EXEC_STOP);
+ rp.set_verbose(session_chroot->get_verbosity() == chroot::chroot::VERBOSITY_VERBOSE);
+
+ log_debug(DEBUG_INFO) << rp << std::endl;
+
+ int exit_status = 0;
+ pid_t pid;
+
+ if ((pid = fork()) == -1)
+ {
+ this->chroot_status = false;
+ throw error(session_chroot->get_name(), CHILD_FORK, strerror(errno));
+ }
+ else if (pid == 0)
+ {
+ try
+ {
+ // The setup scripts don't use our syslog fd.
+ closelog();
+
+ if (chdir("/"))
+ throw error("/", CHDIR, strerror(errno));
+ /* This is required to ensure the scripts run with uid=0 and gid=0,
+ otherwise setuid programs such as mount(8) will fail. This
+ should always succeed, because our euid=0 and egid=0.*/
+ setuid(0);
+ setgid(0);
+ initgroups("root", 0);
+
+ int status = rp.run(arg_list, env);
+
+ _exit (status);
+ }
+ catch (std::exception const& e)
+ {
+ log_exception_error(e);
+ }
+ catch (...)
+ {
+ log_error()
+ << _("An unknown exception occurred") << std::endl;
+ }
+ _exit(EXIT_FAILURE);
+ }
+ else
+ {
+ wait_for_child(pid, exit_status);
+ }
+
+ try
+ {
+ session_chroot->unlock(setup_type, exit_status);
+ }
+ catch (chroot::chroot::error const& e)
+ {
+ this->chroot_status = false;
+ this->lock_status = false;
+ throw error(session_chroot->get_name(), CHROOT_UNLOCK, e);
+ }
+
+ if (exit_status != 0)
+ {
+ this->chroot_status = false;
+
+ format fmt(_("stage=%1%"));
+ fmt % setup_type_string;
+ throw error(session_chroot->get_name(), CHROOT_SETUP, fmt.str());
+ }
+ }
-void
-session::run_child (chroot::chroot::ptr& session_chroot)
-{
- assert(!session_chroot->get_name().empty());
+ void
+ session::run_child (chroot::chroot::ptr& session_chroot)
+ {
+ assert(!session_chroot->get_name().empty());
- assert(!this->authstat->get_user().empty());
- assert(this->authstat->is_initialised()); // PAM must be initialised
+ assert(!this->authstat->get_user().empty());
+ assert(this->authstat->is_initialised()); // PAM must be initialised
- /* Set up environment */
- environment env;
- env.set_filter(session_chroot->get_environment_filter());
+ /* Set up environment */
+ environment env;
+ env.set_filter(session_chroot->get_environment_filter());
- if (get_preserve_environment() || session_chroot->get_preserve_environment())
- env += this->authstat->get_complete_environment();
- else
- env += this->authstat->get_auth_environment();
+ if (get_preserve_environment() || session_chroot->get_preserve_environment())
+ env += this->authstat->get_complete_environment();
+ else
+ env += this->authstat->get_auth_environment();
- // Store before chroot call.
- this->cwd = sbuild::getcwd();
- log_debug(DEBUG_INFO) << "CWD=" << this->cwd << std::endl;
+ // Store before chroot call.
+ this->cwd = sbuild::getcwd();
+ log_debug(DEBUG_INFO) << "CWD=" << this->cwd << std::endl;
- std::string location(session_chroot->get_path());
- log_debug(DEBUG_INFO) << "location=" << location << std::endl;
+ std::string location(session_chroot->get_path());
+ log_debug(DEBUG_INFO) << "location=" << location << std::endl;
- /* Set group ID and supplementary groups */
- if (setgid (this->authstat->get_gid()))
- throw error(this->authstat->get_gid(), GROUP_SET, strerror(errno));
- log_debug(DEBUG_NOTICE) << "Set GID=" << this->authstat->get_gid() << std::endl;
- if (initgroups (this->authstat->get_user().c_str(), this->authstat->get_gid()))
- throw error(GROUP_SET_SUP, strerror(errno));
- log_debug(DEBUG_NOTICE) << "Set supplementary groups" << std::endl;
+ /* Set group ID and supplementary groups */
+ if (setgid (this->authstat->get_gid()))
+ throw error(this->authstat->get_gid(), GROUP_SET, strerror(errno));
+ log_debug(DEBUG_NOTICE) << "Set GID=" << this->authstat->get_gid() << std::endl;
+ if (initgroups (this->authstat->get_user().c_str(), this->authstat->get_gid()))
+ throw error(GROUP_SET_SUP, strerror(errno));
+ log_debug(DEBUG_NOTICE) << "Set supplementary groups" << std::endl;
#ifdef SBUILD_FEATURE_PERSONALITY
- /* Set the process execution domain. */
- /* Will throw on failure. */
- chroot::facet::personality::const_ptr pfac =
- session_chroot->get_facet<chroot::facet::personality>();
- if (pfac)
- {
- pfac->get_persona().set();
- log_debug(DEBUG_NOTICE) << "Set personality="
- << pfac->get_persona() << std::endl;
- }
- else
- {
- log_debug(DEBUG_NOTICE) << "Personality support unavailable" << std::endl;
- }
+ /* Set the process execution domain. */
+ /* Will throw on failure. */
+ chroot::facet::personality::const_ptr pfac =
+ session_chroot->get_facet<chroot::facet::personality>();
+ if (pfac)
+ {
+ pfac->get_persona().set();
+ log_debug(DEBUG_NOTICE) << "Set personality="
+ << pfac->get_persona() << std::endl;
+ }
+ else
+ {
+ log_debug(DEBUG_NOTICE) << "Personality support unavailable" << std::endl;
+ }
#endif // SBUILD_FEATURE_PERSONALITY
- /* Enter the chroot */
- if (chdir (location.c_str()))
- throw error(location, CHDIR, strerror(errno));
- log_debug(DEBUG_NOTICE) << "Changed directory to " << location << std::endl;
- if (::chroot (location.c_str()))
- throw error(location, CHROOT, strerror(errno));
- log_debug(DEBUG_NOTICE) << "Changed root to " << location << std::endl;
-
- /* Set uid and check we are not still root */
- if (setuid (this->authstat->get_uid()))
- throw error(this->authstat->get_uid(), USER_SET, strerror(errno));
- log_debug(DEBUG_NOTICE) << "Set UID=" << this->authstat->get_uid() << std::endl;
- if (!setuid (0) && this->authstat->get_uid())
- throw error(ROOT_DROP);
- if (this->authstat->get_uid())
- log_debug(DEBUG_NOTICE) << "Dropped root privileges" << std::endl;
-
- std::string file;
- string_list command(this->authstat->get_command());
-
- string_list dlist;
- if (command.empty() ||
- command[0].empty()) // No command
- dlist = get_login_directories(session_chroot, env);
- else
- dlist = get_command_directories(session_chroot, env);
- log_debug(DEBUG_INFO)
- << format("Directory fallbacks: %1%") % string_list_to_string(dlist, ", ") << endl;
-
- /* Attempt to chdir to current directory. */
- for (string_list::const_iterator dpos = dlist.begin();
- dpos != dlist.end();
- ++dpos)
- {
- if (chdir ((*dpos).c_str()) < 0)
- {
- error e(*dpos, CHDIR, strerror(errno));
- e.set_reason(_("The directory does not exist inside the chroot. Use the --directory option to run the command in a different directory."));
-
- if (dpos + 1 == dlist.end())
- throw e;
- else
- log_exception_warning(e);
- }
- else
- {
- log_debug(DEBUG_NOTICE) << "Changed directory to "
- << *dpos << std::endl;
- if (dpos != dlist.begin())
- {
- error e(CHDIR_FB, *dpos);
+ /* Enter the chroot */
+ if (chdir (location.c_str()))
+ throw error(location, CHDIR, strerror(errno));
+ log_debug(DEBUG_NOTICE) << "Changed directory to " << location << std::endl;
+ if (::chroot (location.c_str()))
+ throw error(location, CHROOT, strerror(errno));
+ log_debug(DEBUG_NOTICE) << "Changed root to " << location << std::endl;
+
+ /* Set uid and check we are not still root */
+ if (setuid (this->authstat->get_uid()))
+ throw error(this->authstat->get_uid(), USER_SET, strerror(errno));
+ log_debug(DEBUG_NOTICE) << "Set UID=" << this->authstat->get_uid() << std::endl;
+ if (!setuid (0) && this->authstat->get_uid())
+ throw error(ROOT_DROP);
+ if (this->authstat->get_uid())
+ log_debug(DEBUG_NOTICE) << "Dropped root privileges" << std::endl;
+
+ std::string file;
+ string_list command(this->authstat->get_command());
+
+ string_list dlist;
+ if (command.empty() ||
+ command[0].empty()) // No command
+ dlist = get_login_directories(session_chroot, env);
+ else
+ dlist = get_command_directories(session_chroot, env);
+ log_debug(DEBUG_INFO)
+ << format("Directory fallbacks: %1%") % string_list_to_string(dlist, ", ") << endl;
+
+ /* Attempt to chdir to current directory. */
+ for (string_list::const_iterator dpos = dlist.begin();
+ dpos != dlist.end();
+ ++dpos)
+ {
+ if (chdir ((*dpos).c_str()) < 0)
+ {
+ error e(*dpos, CHDIR, strerror(errno));
+ e.set_reason(_("The directory does not exist inside the chroot. Use the --directory option to run the command in a different directory."));
+
+ if (dpos + 1 == dlist.end())
+ throw e;
+ else
log_exception_warning(e);
- }
- break;
- }
- }
-
- /* Fix up the command for exec. */
- get_command(session_chroot, file, command, env);
- log_debug(DEBUG_NOTICE) << "command="
- << string_list_to_string(command, ", ")
- << std::endl;
-
- // Add equivalents to sudo's SUDO_USER, SUDO_UID, SUDO_GID, and
- // SUDO_COMMAND.
- env.add(std::make_pair("SCHROOT_COMMAND",
- string_list_to_string(command, " ")));
- env.add(std::make_pair("SCHROOT_USER", this->authstat->get_ruser()));
- env.add(std::make_pair("SCHROOT_GROUP", this->authstat->get_rgroup()));
- env.add("SCHROOT_UID", this->authstat->get_ruid());
- env.add("SCHROOT_GID", this->authstat->get_rgid());
- // Add session ID.
- chroot::facet::session::const_ptr psess =
- session_chroot->get_facet<chroot::facet::session>();
- if (psess && psess->get_original_name().length())
- env.add("SCHROOT_CHROOT_NAME", psess->get_original_name());
- else
- env.add("SCHROOT_CHROOT_NAME", session_chroot->get_name());
- if (psess && psess->get_selected_name().length())
- env.add("SCHROOT_ALIAS_NAME", psess->get_selected_name());
- else
- env.add("SCHROOT_ALIAS_NAME", session_chroot->get_name());
- env.add("SCHROOT_SESSION_ID", session_chroot->get_name());
-
- log_debug(DEBUG_INFO) << "Set environment:\n" << env;
-
- // The user's command does not use our syslog fd.
- closelog();
-
- // Add command prefix.
- string_list full_command(session_chroot->get_command_prefix());
- if (full_command.size() > 0)
- {
- std::string path;
- if (!env.get("PATH", path))
- path.clear();
- file = find_program_in_path(full_command[0], path, "");
- if (file.empty())
- file = full_command[0];
- }
- for (const auto& arg : command)
- full_command.push_back(arg);
-
- /* Execute */
- if (exec (file, full_command, env))
- throw error(file, EXEC, strerror(errno));
-
- /* This should never be reached */
- _exit(EXIT_FAILURE);
-}
-
-void
-session::wait_for_child (pid_t pid,
- int& child_status)
-{
- child_status = EXIT_FAILURE; // Default exit status
-
- int status;
- bool child_killed = false;
-
- while (1)
- {
- /*
- * If we (the parent process) gets SIGHUP or SIGTERM, pass this
- * signal on to the child (once). Note that we do not handle
- * SIGINT this way, because when a user presses Ctrl-C, the
- * SIGINT is sent to all processes attached to that TTY (so the
- * child will already have gotten it). In any case, once the
- * child gets the signal, we just have to continue waiting for
- * it to exit.
- */
- if ((sighup_called || sigterm_called) && !child_killed)
- {
- if (sighup_called)
- {
- error e(SIGNAL_CATCH, strsignal(SIGHUP),
- _("terminating immediately"));
- log_exception_error(e);
- kill(pid, SIGHUP);
- }
- else // SIGTERM
- {
- error e(SIGNAL_CATCH, strsignal(SIGTERM),
- _("terminating immediately"));
- log_exception_error(e);
- kill(pid, SIGTERM);
- }
- this->chroot_status = false;
- child_killed = true;
- }
-
- if (waitpid(pid, &status, 0) == -1)
- {
- if (errno == EINTR && (sighup_called || sigterm_called || sigint_called))
- continue; // Kill child and wait again.
- else
- throw error(CHILD_WAIT, strerror(errno));
- }
- else if (sighup_called)
- {
- sighup_called = false;
- throw error(SIGNAL_CATCH, strsignal(SIGHUP));
- }
- else if (sigterm_called)
- {
- sigterm_called = false;
- throw error(SIGNAL_CATCH, strsignal(SIGTERM));
- }
- // No need to handle the SIGINT case here; it is handled
- // correctly below
- else
- break;
- }
-
- if (!WIFEXITED(status))
- {
- if (WIFSIGNALED(status))
- throw error(CHILD_SIGNAL, strsignal(WTERMSIG(status)));
- else if (WCOREDUMP(status))
- throw error(CHILD_CORE);
- else
- throw error(CHILD_FAIL);
- }
-
- child_status = WEXITSTATUS(status);
-}
+ }
+ else
+ {
+ log_debug(DEBUG_NOTICE) << "Changed directory to "
+ << *dpos << std::endl;
+ if (dpos != dlist.begin())
+ {
+ error e(CHDIR_FB, *dpos);
+ log_exception_warning(e);
+ }
+ break;
+ }
+ }
+
+ /* Fix up the command for exec. */
+ get_command(session_chroot, file, command, env);
+ log_debug(DEBUG_NOTICE) << "command="
+ << string_list_to_string(command, ", ")
+ << std::endl;
+
+ // Add equivalents to sudo's SUDO_USER, SUDO_UID, SUDO_GID, and
+ // SUDO_COMMAND.
+ env.add(std::make_pair("SCHROOT_COMMAND",
+ string_list_to_string(command, " ")));
+ env.add(std::make_pair("SCHROOT_USER", this->authstat->get_ruser()));
+ env.add(std::make_pair("SCHROOT_GROUP", this->authstat->get_rgroup()));
+ env.add("SCHROOT_UID", this->authstat->get_ruid());
+ env.add("SCHROOT_GID", this->authstat->get_rgid());
+ // Add session ID.
+ chroot::facet::session::const_ptr psess =
+ session_chroot->get_facet<chroot::facet::session>();
+ if (psess && psess->get_original_name().length())
+ env.add("SCHROOT_CHROOT_NAME", psess->get_original_name());
+ else
+ env.add("SCHROOT_CHROOT_NAME", session_chroot->get_name());
+ if (psess && psess->get_selected_name().length())
+ env.add("SCHROOT_ALIAS_NAME", psess->get_selected_name());
+ else
+ env.add("SCHROOT_ALIAS_NAME", session_chroot->get_name());
+ env.add("SCHROOT_SESSION_ID", session_chroot->get_name());
+
+ log_debug(DEBUG_INFO) << "Set environment:\n" << env;
+
+ // The user's command does not use our syslog fd.
+ closelog();
+
+ // Add command prefix.
+ string_list full_command(session_chroot->get_command_prefix());
+ if (full_command.size() > 0)
+ {
+ std::string path;
+ if (!env.get("PATH", path))
+ path.clear();
+ file = find_program_in_path(full_command[0], path, "");
+ if (file.empty())
+ file = full_command[0];
+ }
+ for (const auto& arg : command)
+ full_command.push_back(arg);
+
+ /* Execute */
+ if (exec (file, full_command, env))
+ throw error(file, EXEC, strerror(errno));
+
+ /* This should never be reached */
+ _exit(EXIT_FAILURE);
+ }
-void
-session::run_chroot (chroot::chroot::ptr& session_chroot)
-{
- assert(!session_chroot->get_name().empty());
+ void
+ session::wait_for_child (pid_t pid,
+ int& child_status)
+ {
+ child_status = EXIT_FAILURE; // Default exit status
+
+ int status;
+ bool child_killed = false;
+
+ while (1)
+ {
+ /*
+ * If we (the parent process) gets SIGHUP or SIGTERM, pass this
+ * signal on to the child (once). Note that we do not handle
+ * SIGINT this way, because when a user presses Ctrl-C, the
+ * SIGINT is sent to all processes attached to that TTY (so the
+ * child will already have gotten it). In any case, once the
+ * child gets the signal, we just have to continue waiting for
+ * it to exit.
+ */
+ if ((sighup_called || sigterm_called) && !child_killed)
+ {
+ if (sighup_called)
+ {
+ error e(SIGNAL_CATCH, strsignal(SIGHUP),
+ _("terminating immediately"));
+ log_exception_error(e);
+ kill(pid, SIGHUP);
+ }
+ else // SIGTERM
+ {
+ error e(SIGNAL_CATCH, strsignal(SIGTERM),
+ _("terminating immediately"));
+ log_exception_error(e);
+ kill(pid, SIGTERM);
+ }
+ this->chroot_status = false;
+ child_killed = true;
+ }
+
+ if (waitpid(pid, &status, 0) == -1)
+ {
+ if (errno == EINTR && (sighup_called || sigterm_called || sigint_called))
+ continue; // Kill child and wait again.
+ else
+ throw error(CHILD_WAIT, strerror(errno));
+ }
+ else if (sighup_called)
+ {
+ sighup_called = false;
+ throw error(SIGNAL_CATCH, strsignal(SIGHUP));
+ }
+ else if (sigterm_called)
+ {
+ sigterm_called = false;
+ throw error(SIGNAL_CATCH, strsignal(SIGTERM));
+ }
+ // No need to handle the SIGINT case here; it is handled
+ // correctly below
+ else
+ break;
+ }
+
+ if (!WIFEXITED(status))
+ {
+ if (WIFSIGNALED(status))
+ throw error(CHILD_SIGNAL, strsignal(WTERMSIG(status)));
+ else if (WCOREDUMP(status))
+ throw error(CHILD_CORE);
+ else
+ throw error(CHILD_FAIL);
+ }
+
+ child_status = WEXITSTATUS(status);
+ }
- pid_t pid;
- if ((pid = fork()) == -1)
- {
- throw error(CHILD_FORK, strerror(errno));
- }
- else if (pid == 0)
- {
+ void
+ session::run_chroot (chroot::chroot::ptr& session_chroot)
+ {
+ assert(!session_chroot->get_name().empty());
+
+ pid_t pid;
+ if ((pid = fork()) == -1)
+ {
+ throw error(CHILD_FORK, strerror(errno));
+ }
+ else if (pid == 0)
+ {
#ifdef SBUILD_DEBUG
- while (child_wait)
- ;
+ while (child_wait)
+ ;
#endif
- try
- {
- run_child(session_chroot);
- }
- catch (std::runtime_error const& e)
- {
- log_exception_error(e);
- }
- catch (...)
- {
- log_error()
- << _("An unknown exception occurred") << std::endl;
- }
- _exit (EXIT_FAILURE);
- }
- else
- {
- wait_for_child(pid, this->child_status);
- }
-}
+ try
+ {
+ run_child(session_chroot);
+ }
+ catch (std::runtime_error const& e)
+ {
+ log_exception_error(e);
+ }
+ catch (...)
+ {
+ log_error()
+ << _("An unknown exception occurred") << std::endl;
+ }
+ _exit (EXIT_FAILURE);
+ }
+ else
+ {
+ wait_for_child(pid, this->child_status);
+ }
+ }
-void
-session::set_sighup_handler ()
-{
- set_signal_handler(SIGHUP, &this->saved_sighup_signal, sighup_handler);
-}
+ void
+ session::set_sighup_handler ()
+ {
+ set_signal_handler(SIGHUP, &this->saved_sighup_signal, sighup_handler);
+ }
-void
-session::clear_sighup_handler ()
-{
- clear_signal_handler(SIGHUP, &this->saved_sighup_signal);
-}
+ void
+ session::clear_sighup_handler ()
+ {
+ clear_signal_handler(SIGHUP, &this->saved_sighup_signal);
+ }
-void
-session::set_sigint_handler ()
-{
- set_signal_handler(SIGINT, &this->saved_sigint_signal, sigint_handler);
-}
+ void
+ session::set_sigint_handler ()
+ {
+ set_signal_handler(SIGINT, &this->saved_sigint_signal, sigint_handler);
+ }
-void
-session::clear_sigint_handler ()
-{
- clear_signal_handler(SIGINT, &this->saved_sigint_signal);
-}
+ void
+ session::clear_sigint_handler ()
+ {
+ clear_signal_handler(SIGINT, &this->saved_sigint_signal);
+ }
-void
-session::set_sigterm_handler ()
-{
- set_signal_handler(SIGTERM, &this->saved_sigterm_signal, sigterm_handler);
-}
+ void
+ session::set_sigterm_handler ()
+ {
+ set_signal_handler(SIGTERM, &this->saved_sigterm_signal, sigterm_handler);
+ }
-void
-session::clear_sigterm_handler ()
-{
- clear_signal_handler(SIGTERM, &this->saved_sigterm_signal);
-}
+ void
+ session::clear_sigterm_handler ()
+ {
+ clear_signal_handler(SIGTERM, &this->saved_sigterm_signal);
+ }
-void
-session::set_signal_handler (int signal,
- struct sigaction *saved_signal,
- void (*handler)(int))
-{
- struct sigaction new_sa;
- sigemptyset(&new_sa.sa_mask);
- new_sa.sa_flags = 0;
- new_sa.sa_handler = handler;
+ void
+ session::set_signal_handler (int signal,
+ struct sigaction *saved_signal,
+ void (*handler)(int))
+ {
+ struct sigaction new_sa;
+ sigemptyset(&new_sa.sa_mask);
+ new_sa.sa_flags = 0;
+ new_sa.sa_handler = handler;
- if (sigaction(signal, &new_sa, saved_signal) != 0)
- throw error(SIGNAL_SET, strsignal(signal), strerror(errno));
-}
+ if (sigaction(signal, &new_sa, saved_signal) != 0)
+ throw error(SIGNAL_SET, strsignal(signal), strerror(errno));
+ }
+
+ void
+ session::clear_signal_handler (int signal,
+ struct sigaction *saved_signal)
+ {
+ /* Restore original handler */
+ sigaction (signal, saved_signal, 0);
+ }
-void
-session::clear_signal_handler (int signal,
- struct sigaction *saved_signal)
-{
- /* Restore original handler */
- sigaction (signal, saved_signal, 0);
}
diff --git a/lib/sbuild/types.cc b/lib/sbuild/types.cc
index d033c84e..2b2501f9 100644
--- a/lib/sbuild/types.cc
+++ b/lib/sbuild/types.cc
@@ -21,24 +21,27 @@
#include <sbuild/types.h>
#include <sbuild/i18n.h>
-using namespace sbuild;
-
-const char *
-sbuild::date_base::get_date_format () const
+namespace sbuild
{
- // TRANSLATORS: Format string for date representation:
- // %d = day (number, e.g. 14)
- // %b = month (three letters, e.g. Jul)
- // %Y = year (four digits, e.g. 2006)
- // If required, any of the standard strftime(3)
- // format specifiers may be used instead, as long as
- // the day, month and year are clearly displayed in
- // the equivalent standard method for your locale.
- return _("%d %b %Y");
-}
-const char *
-sbuild::isodate::get_date_format () const
-{
- return "%Y-%m-%dT%H:%M:%SZ";
+ const char *
+ date_base::get_date_format () const
+ {
+ // TRANSLATORS: Format string for date representation:
+ // %d = day (number, e.g. 14)
+ // %b = month (three letters, e.g. Jul)
+ // %Y = year (four digits, e.g. 2006)
+ // If required, any of the standard strftime(3)
+ // format specifiers may be used instead, as long as
+ // the day, month and year are clearly displayed in
+ // the equivalent standard method for your locale.
+ return _("%d %b %Y");
+ }
+
+ const char *
+ isodate::get_date_format () const
+ {
+ return "%Y-%m-%dT%H:%M:%SZ";
+ }
+
}
diff --git a/lib/sbuild/util.cc b/lib/sbuild/util.cc
index 68cf9a1f..44058e94 100644
--- a/lib/sbuild/util.cc
+++ b/lib/sbuild/util.cc
@@ -31,738 +31,741 @@
#include <boost/filesystem/convenience.hpp>
-using namespace sbuild;
-
-namespace
+namespace sbuild
{
- /**
- * Remove duplicate adjacent characters from a string.
- *
- * @param str the string to check.
- * @param dup the duplicate character to check for.
- * @returns a string with any duplicates removed.
- */
- std::string remove_duplicates (std::string const& str,
- char dup)
+ namespace
{
- std::string ret;
- for (std::string::size_type pos = 0;
- pos < str.length();
- ++pos)
- {
- ret += str[pos];
- if (str[pos] == dup)
- {
- while (pos + 1 < str.length() &&
- str[pos + 1] == dup)
- ++pos;
- }
- }
+ /**
+ * Remove duplicate adjacent characters from a string.
+ *
+ * @param str the string to check.
+ * @param dup the duplicate character to check for.
+ * @returns a string with any duplicates removed.
+ */
+ std::string remove_duplicates (std::string const& str,
+ char dup)
+ {
+ std::string ret;
- return ret;
- }
+ for (std::string::size_type pos = 0;
+ pos < str.length();
+ ++pos)
+ {
+ ret += str[pos];
+ if (str[pos] == dup)
+ {
+ while (pos + 1 < str.length() &&
+ str[pos + 1] == dup)
+ ++pos;
+ }
+ }
+ return ret;
+ }
-}
-template<>
-error<sbuild::stat::error_code>::map_type
-error<sbuild::stat::error_code>::error_strings =
+ }
+
+ template<>
+ error<stat::error_code>::map_type
+ error<stat::error_code>::error_strings =
+ {
+ {stat::FILE, N_("Failed to stat file")},
+ {stat::FD, N_("Failed to stat file descriptor")}
+ };
+
+ std::string
+ basename (std::string name)
{
- {sbuild::stat::FILE, N_("Failed to stat file")},
- {sbuild::stat::FD, N_("Failed to stat file descriptor")}
- };
+ const char separator = '/';
-std::string
-sbuild::basename (std::string name)
-{
- const char separator = '/';
-
- // Remove trailing separators
- std::string::size_type cur = name.length();
- while (cur - 1 != 0 && name[cur - 1] == separator)
- --cur;
- name.resize(cur);
-
- // Find last separator
- std::string::size_type pos = name.rfind(separator);
-
- std::string ret;
- if (pos == std::string::npos)
- ret = name; // No separators
- else if (pos == 0 && name.length() == 1 && name[0] == separator)
- ret = separator; // Only separators
- else
- ret = name.substr(pos + 1); // Basename only
-
- return remove_duplicates(ret, separator);
-}
+ // Remove trailing separators
+ std::string::size_type cur = name.length();
+ while (cur - 1 != 0 && name[cur - 1] == separator)
+ --cur;
+ name.resize(cur);
-std::string
-sbuild::dirname (std::string name)
-{
- const char separator = '/';
-
- // Remove trailing separators
- std::string::size_type cur = name.length();
- while (cur - 1 != 0 && name[cur - 1] == separator)
- --cur;
- name.resize(cur);
-
- // Find last separator
- std::string::size_type pos = name.rfind(separator);
-
- std::string ret;
- if (pos == std::string::npos)
- ret = "."; // No directory components
- else if (pos == 0)
- ret = separator;
- else
- ret = name.substr(0, pos); // Dirname part
-
- return remove_duplicates(ret, separator);
-}
+ // Find last separator
+ std::string::size_type pos = name.rfind(separator);
-std::string
-sbuild::normalname (std::string name)
-{
- const char separator = '/';
+ std::string ret;
+ if (pos == std::string::npos)
+ ret = name; // No separators
+ else if (pos == 0 && name.length() == 1 && name[0] == separator)
+ ret = separator; // Only separators
+ else
+ ret = name.substr(pos + 1); // Basename only
+
+ return remove_duplicates(ret, separator);
+ }
- // Remove trailing separators
- std::string::size_type cur = name.length();
- while (cur - 1 != 0 && name[cur - 1] == separator)
- --cur;
- name.resize(cur);
+ std::string
+ dirname (std::string name)
+ {
+ const char separator = '/';
- return remove_duplicates(name, separator);
-}
+ // Remove trailing separators
+ std::string::size_type cur = name.length();
+ while (cur - 1 != 0 && name[cur - 1] == separator)
+ --cur;
+ name.resize(cur);
-bool
-sbuild::is_absname (std::string const& name)
-{
- if (name.empty() || name[0] != '/')
- return false;
- else
- return true;
-}
+ // Find last separator
+ std::string::size_type pos = name.rfind(separator);
-bool
-sbuild::is_valid_sessionname (std::string const& name)
-{
- bool match = false;
+ std::string ret;
+ if (pos == std::string::npos)
+ ret = "."; // No directory components
+ else if (pos == 0)
+ ret = separator;
+ else
+ ret = name.substr(0, pos); // Dirname part
+
+ return remove_duplicates(ret, separator);
+ }
+
+ std::string
+ normalname (std::string name)
+ {
+ const char separator = '/';
- static regex file_namespace("^[^:/,.][^:/,]*$");
- static regex editor_backup("~$");
- static regex debian_dpkg_conffile_cruft("dpkg-(old|dist|new|tmp)$");
+ // Remove trailing separators
+ std::string::size_type cur = name.length();
+ while (cur - 1 != 0 && name[cur - 1] == separator)
+ --cur;
+ name.resize(cur);
- if (regex_search(name, file_namespace) &&
- !regex_search(name, editor_backup) &&
- !regex_search(name, debian_dpkg_conffile_cruft)) {
- match = true;
+ return remove_duplicates(name, separator);
}
- return match;
-}
+ bool
+ is_absname (std::string const& name)
+ {
+ if (name.empty() || name[0] != '/')
+ return false;
+ else
+ return true;
+ }
-bool
-sbuild::is_valid_filename (std::string const& name,
- bool lsb_mode)
-{
- bool match = false;
+ bool
+ is_valid_sessionname (std::string const& name)
+ {
+ bool match = false;
- if (lsb_mode)
- {
- static regex lanana_namespace("^[a-z0-9]+$");
- static regex lsb_namespace("^_?([a-z0-9_.]+-)+[a-z0-9]+$");
- static regex debian_cron_namespace("^[a-z0-9][a-z0-9-]*$");
- static regex debian_dpkg_conffile_cruft("dpkg-(old|dist|new|tmp)$");
-
- if ((regex_search(name, lanana_namespace) ||
- regex_search(name, lsb_namespace) ||
- regex_search(name, debian_cron_namespace)) &&
- !regex_search(name, debian_dpkg_conffile_cruft))
- match = true;
- }
- else
- {
- static regex traditional_namespace("^[a-zA-Z0-9_-]$");
- if (regex_search(name, traditional_namespace))
- match = true;
+ static regex file_namespace("^[^:/,.][^:/,]*$");
+ static regex editor_backup("~$");
+ static regex debian_dpkg_conffile_cruft("dpkg-(old|dist|new|tmp)$");
+
+ if (regex_search(name, file_namespace) &&
+ !regex_search(name, editor_backup) &&
+ !regex_search(name, debian_dpkg_conffile_cruft)) {
+ match = true;
}
- return match;
-}
+ return match;
+ }
-std::string
-sbuild::getcwd ()
-{
- std::string cwd;
+ bool
+ is_valid_filename (std::string const& name,
+ bool lsb_mode)
+ {
+ bool match = false;
- char *raw_cwd = ::getcwd (0, 0);
- if (raw_cwd)
- cwd = raw_cwd;
- else
- cwd = "/";
- free(raw_cwd);
+ if (lsb_mode)
+ {
+ static regex lanana_namespace("^[a-z0-9]+$");
+ static regex lsb_namespace("^_?([a-z0-9_.]+-)+[a-z0-9]+$");
+ static regex debian_cron_namespace("^[a-z0-9][a-z0-9-]*$");
+ static regex debian_dpkg_conffile_cruft("dpkg-(old|dist|new|tmp)$");
+
+ if ((regex_search(name, lanana_namespace) ||
+ regex_search(name, lsb_namespace) ||
+ regex_search(name, debian_cron_namespace)) &&
+ !regex_search(name, debian_dpkg_conffile_cruft))
+ match = true;
+ }
+ else
+ {
+ static regex traditional_namespace("^[a-zA-Z0-9_-]$");
+ if (regex_search(name, traditional_namespace))
+ match = true;
+ }
- return cwd;
-}
+ return match;
+ }
-std::string
-sbuild::unique_identifier ()
-{
- std::ostringstream id;
- id.imbue(std::locale::classic());
+ std::string
+ getcwd ()
+ {
+ std::string cwd;
- struct timeval tv;
- gettimeofday(&tv, nullptr);
+ char *raw_cwd = ::getcwd (0, 0);
+ if (raw_cwd)
+ cwd = raw_cwd;
+ else
+ cwd = "/";
+ free(raw_cwd);
- uint64_t bits = static_cast<uint64_t>(tv.tv_usec << 16) ^ tv.tv_sec;
- static const std::string letters("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
- std::string ids;
- for (int i=0; i<6; ++i)
- {
- ids += letters[bits % 62];
- bits /= 62;
- }
+ return cwd;
+ }
- id << ids << '-' << getpid();
+ std::string
+ unique_identifier ()
+ {
+ std::ostringstream id;
+ id.imbue(std::locale::classic());
- return id.str();
-}
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
-std::string
-sbuild::string_list_to_string (string_list const& list,
- std::string const& separator)
-{
- std::string ret;
+ uint64_t bits = static_cast<uint64_t>(tv.tv_usec << 16) ^ tv.tv_sec;
+ static const std::string letters("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+ std::string ids;
+ for (int i=0; i<6; ++i)
+ {
+ ids += letters[bits % 62];
+ bits /= 62;
+ }
- for (string_list::const_iterator cur = list.begin();
- cur != list.end();
- ++cur)
- {
- ret += *cur;
- if (cur + 1 != list.end())
- ret += separator;
- }
+ id << ids << '-' << getpid();
- return ret;
-}
+ return id.str();
+ }
-string_list
-sbuild::split_string (std::string const& value,
- std::string const& separator)
-{
- string_list ret;
+ std::string
+ string_list_to_string (string_list const& list,
+ std::string const& separator)
+ {
+ std::string ret;
- // Skip any separators at the start
- std::string::size_type last_pos =
- value.find_first_not_of(separator, 0);
- // Find first separator.
- std::string::size_type pos = value.find_first_of(separator, last_pos);
+ for (string_list::const_iterator cur = list.begin();
+ cur != list.end();
+ ++cur)
+ {
+ ret += *cur;
+ if (cur + 1 != list.end())
+ ret += separator;
+ }
- while (pos !=std::string::npos || last_pos != std::string::npos)
- {
- // Add to list
- if (pos == std::string::npos)
- // Entire string from last_pos
- ret.push_back(value.substr(last_pos, pos));
- else
- // Between pos and last_pos
- ret.push_back(value.substr(last_pos, pos - last_pos));
-
- // Find next
- last_pos = value.find_first_not_of(separator, pos);
- pos = value.find_first_of(separator, last_pos);
- }
+ return ret;
+ }
- return ret;
-}
+ string_list
+ split_string (std::string const& value,
+ std::string const& separator)
+ {
+ string_list ret;
-string_list
-sbuild::split_string_strict (std::string const& value,
- std::string const& separator)
-{
- string_list ret;
+ // Skip any separators at the start
+ std::string::size_type last_pos =
+ value.find_first_not_of(separator, 0);
+ // Find first separator.
+ std::string::size_type pos = value.find_first_of(separator, last_pos);
- std::string::size_type last_pos = 0;
- // Find first separator.
- std::string::size_type pos = value.find_first_of(separator, last_pos);
+ while (pos !=std::string::npos || last_pos != std::string::npos)
+ {
+ // Add to list
+ if (pos == std::string::npos)
+ // Entire string from last_pos
+ ret.push_back(value.substr(last_pos, pos));
+ else
+ // Between pos and last_pos
+ ret.push_back(value.substr(last_pos, pos - last_pos));
+
+ // Find next
+ last_pos = value.find_first_not_of(separator, pos);
+ pos = value.find_first_of(separator, last_pos);
+ }
- while (pos !=std::string::npos)
- {
- // Add to list
- if (pos == std::string::npos)
- // Entire string from last_pos
- ret.push_back(value.substr(last_pos, pos));
- else
- // Between pos and last_pos
- ret.push_back(value.substr(last_pos, pos - last_pos));
-
- // Find next
- last_pos = pos + separator.length();
- pos = value.find_first_of(separator, last_pos);
- }
+ return ret;
+ }
- return ret;
-}
+ string_list
+ split_string_strict (std::string const& value,
+ std::string const& separator)
+ {
+ string_list ret;
-std::wstring
-sbuild::widen_string (std::string const& str,
- std::locale locale)
-{
- typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
- codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
- mbstate_t state;
- const char *cbegin = str.data(), *cend = str.data() + str.size(), *cnext;
- wchar_t *wcnext;
- wchar_t wcbuf[80];
- std::wstring ret;
+ std::string::size_type last_pos = 0;
+ // Find first separator.
+ std::string::size_type pos = value.find_first_of(separator, last_pos);
- std::memset(&state, 0, sizeof(mbstate_t));
+ while (pos !=std::string::npos)
+ {
+ // Add to list
+ if (pos == std::string::npos)
+ // Entire string from last_pos
+ ret.push_back(value.substr(last_pos, pos));
+ else
+ // Between pos and last_pos
+ ret.push_back(value.substr(last_pos, pos - last_pos));
+
+ // Find next
+ last_pos = pos + separator.length();
+ pos = value.find_first_of(separator, last_pos);
+ }
- while (1)
- {
- std::codecvt_base::result res =
- cvt.in(state,
- cbegin, cend, cnext,
- wcbuf, wcbuf + (sizeof(wcbuf) / sizeof(wcbuf[0])), wcnext);
+ return ret;
+ }
- if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
- {
- ret += std::wstring(wcbuf, wcnext);
- if (cend == cnext)
+ std::wstring
+ widen_string (std::string const& str,
+ std::locale locale)
+ {
+ typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
+ codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
+ mbstate_t state;
+ const char *cbegin = str.data(), *cend = str.data() + str.size(), *cnext;
+ wchar_t *wcnext;
+ wchar_t wcbuf[80];
+ std::wstring ret;
+
+ std::memset(&state, 0, sizeof(mbstate_t));
+
+ while (1)
+ {
+ std::codecvt_base::result res =
+ cvt.in(state,
+ cbegin, cend, cnext,
+ wcbuf, wcbuf + (sizeof(wcbuf) / sizeof(wcbuf[0])), wcnext);
+
+ if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
+ {
+ ret += std::wstring(wcbuf, wcnext);
+ if (cend == cnext)
+ break;
+ }
+ else if (res == std::codecvt_base::noconv)
+ {
+ ret += std::wstring(cbegin, cend);
break;
- }
- else if (res == std::codecvt_base::noconv)
- {
- ret += std::wstring(cbegin, cend);
- break;
- }
- else if (res == std::codecvt_base::error)
- {
- throw std::runtime_error
- ("A character set conversion failed. Please report this bug.");
+ }
+ else if (res == std::codecvt_base::error)
+ {
+ throw std::runtime_error
+ ("A character set conversion failed. Please report this bug.");
+ break;
+ }
+ else
break;
- }
- else
- break;
- cbegin = cnext;
- }
+ cbegin = cnext;
+ }
- return ret;
-}
+ return ret;
+ }
-std::string
-sbuild::narrow_string (std::wstring const& str,
- std::locale locale)
-{
- typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
- codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
- mbstate_t state;
- const wchar_t *wcbegin = str.data(), *wcend = str.data() + str.size(), *wcnext;
- char *cnext;
- char cbuf[80];
- std::string ret;
+ std::string
+ narrow_string (std::wstring const& str,
+ std::locale locale)
+ {
+ typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
+ codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
+ mbstate_t state;
+ const wchar_t *wcbegin = str.data(), *wcend = str.data() + str.size(), *wcnext;
+ char *cnext;
+ char cbuf[80];
+ std::string ret;
- std::memset(&state, 0, sizeof(mbstate_t));
+ std::memset(&state, 0, sizeof(mbstate_t));
- while (1)
- {
- std::codecvt_base::result res =
- cvt.out(state,
- wcbegin, wcend, wcnext,
- cbuf, cbuf + (sizeof(cbuf) / sizeof(cbuf[0])), cnext);
+ while (1)
+ {
+ std::codecvt_base::result res =
+ cvt.out(state,
+ wcbegin, wcend, wcnext,
+ cbuf, cbuf + (sizeof(cbuf) / sizeof(cbuf[0])), cnext);
- if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
- {
- ret += std::string(cbuf, cnext);
- if (wcend == wcnext)
+ if (res == std::codecvt_base::ok || res == std::codecvt_base::partial)
+ {
+ ret += std::string(cbuf, cnext);
+ if (wcend == wcnext)
+ break;
+ }
+ else if (res == std::codecvt_base::noconv)
+ {
+ ret += std::string(wcbegin, wcend);
break;
- }
- else if (res == std::codecvt_base::noconv)
- {
- ret += std::string(wcbegin, wcend);
- break;
- }
- else if (res == std::codecvt_base::error)
- {
- throw std::runtime_error
- ("A character set conversion failed. Please report this bug.");
+ }
+ else if (res == std::codecvt_base::error)
+ {
+ throw std::runtime_error
+ ("A character set conversion failed. Please report this bug.");
+ break;
+ }
+ else
break;
- }
- else
- break;
- wcbegin = wcnext;
- }
+ wcbegin = wcnext;
+ }
- return ret;
-}
+ return ret;
+ }
-std::string
-sbuild::find_program_in_path (std::string const& program,
- std::string const& path,
- std::string const& prefix)
-{
- if (program.find_first_of('/') != std::string::npos)
- return program;
+ std::string
+ find_program_in_path (std::string const& program,
+ std::string const& path,
+ std::string const& prefix)
+ {
+ if (program.find_first_of('/') != std::string::npos)
+ return program;
- string_list dirs = split_string(path, std::string(1, ':'));
+ string_list dirs = split_string(path, std::string(1, ':'));
- for (const auto& dir : dirs)
- {
- std::string realname = dir + '/' + program;
- std::string absname;
- if (prefix.length() > 0)
- {
- absname = prefix;
- if (dir.length() > 0 && (dir)[0] != '/')
- absname += '/';
- }
- absname += realname;
+ for (const auto& dir : dirs)
+ {
+ std::string realname = dir + '/' + program;
+ std::string absname;
+ if (prefix.length() > 0)
+ {
+ absname = prefix;
+ if (dir.length() > 0 && (dir)[0] != '/')
+ absname += '/';
+ }
+ absname += realname;
- try
- {
- if (stat(absname).is_regular() &&
- access (absname.c_str(), X_OK) == 0)
- return realname;
- }
- catch (std::runtime_error const& e)
- {
- }
- }
+ try
+ {
+ if (stat(absname).is_regular() &&
+ access (absname.c_str(), X_OK) == 0)
+ return realname;
+ }
+ catch (std::runtime_error const& e)
+ {
+ }
+ }
- return "";
-}
+ return "";
+ }
-char **
-sbuild::string_list_to_strv (string_list const& str)
-{
- char **ret = new char *[str.size() + 1];
+ char **
+ string_list_to_strv (string_list const& str)
+ {
+ char **ret = new char *[str.size() + 1];
- for (string_list::size_type i = 0;
- i < str.size();
- ++i)
- {
- ret[i] = new char[str[i].length() + 1];
- std::strcpy(ret[i], str[i].c_str());
- }
- ret[str.size()] = 0;
+ for (string_list::size_type i = 0;
+ i < str.size();
+ ++i)
+ {
+ ret[i] = new char[str[i].length() + 1];
+ std::strcpy(ret[i], str[i].c_str());
+ }
+ ret[str.size()] = 0;
- return ret;
-}
+ return ret;
+ }
-void
-sbuild::strv_delete (char **strv)
-{
- for (char **pos = strv; pos != 0 && *pos != 0; ++pos)
- delete *pos;
- delete[] strv;
-}
+ void
+ strv_delete (char **strv)
+ {
+ for (char **pos = strv; pos != 0 && *pos != 0; ++pos)
+ delete *pos;
+ delete[] strv;
+ }
-int
-sbuild::exec (std::string const& file,
- string_list const& command,
- environment const& env)
-{
- char **argv = string_list_to_strv(command);
- char **envp = env.get_strv();
- int status;
+ int
+ exec (std::string const& file,
+ string_list const& command,
+ environment const& env)
+ {
+ char **argv = string_list_to_strv(command);
+ char **envp = env.get_strv();
+ int status;
- if ((status = execve(file.c_str(), argv, envp)) != 0)
- {
- strv_delete(argv);
- strv_delete(envp);
- }
+ if ((status = execve(file.c_str(), argv, envp)) != 0)
+ {
+ strv_delete(argv);
+ strv_delete(envp);
+ }
- return status;
-}
+ return status;
+ }
-sbuild::stat::stat (const char *file,
- bool link):
- file(file),
- fd(0),
- errorno(0),
- status()
-{
- if (link)
- {
- if (::lstat(file, &this->status) < 0)
- this->errorno = errno;
- }
- else
- {
- if (::stat(file, &this->status) < 0)
- this->errorno = errno;
- }
-}
+ stat::stat (const char *file,
+ bool link):
+ file(file),
+ fd(0),
+ errorno(0),
+ status()
+ {
+ if (link)
+ {
+ if (::lstat(file, &this->status) < 0)
+ this->errorno = errno;
+ }
+ else
+ {
+ if (::stat(file, &this->status) < 0)
+ this->errorno = errno;
+ }
+ }
-sbuild::stat::stat (std::string const& file,
- bool link):
- file(file),
- fd(0),
- errorno(0),
- status()
-{
- if (link)
- {
- if (::lstat(file.c_str(), &this->status) < 0)
- this->errorno = errno;
- }
- else
- {
- if (::stat(file.c_str(), &this->status) < 0)
- this->errorno = errno;
- }
-}
+ stat::stat (std::string const& file,
+ bool link):
+ file(file),
+ fd(0),
+ errorno(0),
+ status()
+ {
+ if (link)
+ {
+ if (::lstat(file.c_str(), &this->status) < 0)
+ this->errorno = errno;
+ }
+ else
+ {
+ if (::stat(file.c_str(), &this->status) < 0)
+ this->errorno = errno;
+ }
+ }
-sbuild::stat::stat (std::string const& file,
- int fd):
- file(file),
- fd(fd),
- errorno(0),
- status()
-{
- if (::fstat(fd, &this->status) < 0)
- this->errorno = errno;
-}
+ stat::stat (std::string const& file,
+ int fd):
+ file(file),
+ fd(fd),
+ errorno(0),
+ status()
+ {
+ if (::fstat(fd, &this->status) < 0)
+ this->errorno = errno;
+ }
-sbuild::stat::stat (int fd):
- file(),
- fd(fd),
- errorno(0),
- status()
-{
- if (::fstat(fd, &this->status) < 0)
- this->errorno = errno;
-}
+ stat::stat (int fd):
+ file(),
+ fd(fd),
+ errorno(0),
+ status()
+ {
+ if (::fstat(fd, &this->status) < 0)
+ this->errorno = errno;
+ }
-sbuild::stat::~stat ()
-{
-}
+ stat::~stat ()
+ {
+ }
-sbuild::passwd::passwd ():
- ::passwd(),
- buffer(),
- valid(false)
-{
- clear();
-}
+ passwd::passwd ():
+ ::passwd(),
+ buffer(),
+ valid(false)
+ {
+ clear();
+ }
-sbuild::passwd::passwd (uid_t uid):
- ::passwd(),
- buffer(),
- valid(false)
-{
- clear();
+ passwd::passwd (uid_t uid):
+ ::passwd(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_uid(uid);
-}
+ query_uid(uid);
+ }
-sbuild::passwd::passwd (const char *name):
- ::passwd(),
- buffer(),
- valid(false)
-{
- clear();
+ passwd::passwd (const char *name):
+ ::passwd(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_name(name);
-}
+ query_name(name);
+ }
-sbuild::passwd::passwd (std::string const& name):
- ::passwd(),
- buffer(),
- valid(false)
-{
- clear();
+ passwd::passwd (std::string const& name):
+ ::passwd(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_name(name);
-}
+ query_name(name);
+ }
-void
-sbuild::passwd::clear ()
-{
- valid = false;
+ void
+ passwd::clear ()
+ {
+ valid = false;
- buffer.clear();
+ buffer.clear();
- ::passwd::pw_name = 0;
- ::passwd::pw_passwd = 0;
- ::passwd::pw_uid = 0;
- ::passwd::pw_gid = 0;
- ::passwd::pw_gecos = 0;
- ::passwd::pw_dir = 0;
- ::passwd::pw_shell = 0;
-}
+ ::passwd::pw_name = 0;
+ ::passwd::pw_passwd = 0;
+ ::passwd::pw_uid = 0;
+ ::passwd::pw_gid = 0;
+ ::passwd::pw_gecos = 0;
+ ::passwd::pw_dir = 0;
+ ::passwd::pw_shell = 0;
+ }
-void
-sbuild::passwd::query_uid (uid_t uid)
-{
- buffer_type::size_type size = 1 << 7;
- buffer.reserve(size);
- int error;
+ void
+ passwd::query_uid (uid_t uid)
+ {
+ buffer_type::size_type size = 1 << 7;
+ buffer.reserve(size);
+ int error;
- ::passwd *pwd_result;
+ ::passwd *pwd_result;
- while ((error = getpwuid_r(uid, this,
- &buffer[0], buffer.capacity(),
- &pwd_result)))
- {
- size <<= 1;
- buffer.reserve(size);
- }
+ while ((error = getpwuid_r(uid, this,
+ &buffer[0], buffer.capacity(),
+ &pwd_result)))
+ {
+ size <<= 1;
+ buffer.reserve(size);
+ }
- if (pwd_result)
- valid = true;
- else
- errno = error;
-}
+ if (pwd_result)
+ valid = true;
+ else
+ errno = error;
+ }
-void
-sbuild::passwd::query_name (const char *name)
-{
- buffer_type::size_type size = 1 << 8;
- buffer.reserve(size);
- int error;
+ void
+ passwd::query_name (const char *name)
+ {
+ buffer_type::size_type size = 1 << 8;
+ buffer.reserve(size);
+ int error;
- ::passwd *pwd_result;
+ ::passwd *pwd_result;
- while ((error = getpwnam_r(name, this,
- &buffer[0], buffer.capacity(),
- &pwd_result)))
- {
- size <<= 1;
- buffer.reserve(size);
- }
+ while ((error = getpwnam_r(name, this,
+ &buffer[0], buffer.capacity(),
+ &pwd_result)))
+ {
+ size <<= 1;
+ buffer.reserve(size);
+ }
- if (pwd_result)
- valid = true;
- else
- errno = error;
-}
+ if (pwd_result)
+ valid = true;
+ else
+ errno = error;
+ }
-void
-sbuild::passwd::query_name (std::string const& name)
-{
- query_name(name.c_str());
-}
+ void
+ passwd::query_name (std::string const& name)
+ {
+ query_name(name.c_str());
+ }
-bool
-sbuild::passwd::operator ! () const
-{
- return !valid;
-}
+ bool
+ passwd::operator ! () const
+ {
+ return !valid;
+ }
-sbuild::group::group ():
- ::group(),
- buffer(),
- valid(false)
-{
- clear();
-}
+ group::group ():
+ ::group(),
+ buffer(),
+ valid(false)
+ {
+ clear();
+ }
-sbuild::group::group (gid_t gid):
- ::group(),
- buffer(),
- valid(false)
-{
- clear();
+ group::group (gid_t gid):
+ ::group(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_gid(gid);
-}
+ query_gid(gid);
+ }
-sbuild::group::group (const char *name):
- ::group(),
- buffer(),
- valid(false)
-{
- clear();
+ group::group (const char *name):
+ ::group(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_name(name);
-}
+ query_name(name);
+ }
-sbuild::group::group (std::string const& name):
- ::group(),
- buffer(),
- valid(false)
-{
- clear();
+ group::group (std::string const& name):
+ ::group(),
+ buffer(),
+ valid(false)
+ {
+ clear();
- query_name(name);
-}
+ query_name(name);
+ }
-void
-sbuild::group::clear ()
-{
- valid = false;
+ void
+ group::clear ()
+ {
+ valid = false;
- buffer.clear();
+ buffer.clear();
- ::group::gr_name = 0;
- ::group::gr_passwd = 0;
- ::group::gr_gid = 0;
- ::group::gr_mem = 0;
-}
+ ::group::gr_name = 0;
+ ::group::gr_passwd = 0;
+ ::group::gr_gid = 0;
+ ::group::gr_mem = 0;
+ }
-void
-sbuild::group::query_gid (gid_t gid)
-{
- buffer_type::size_type size = 1 << 7;
- buffer.reserve(size);
- int error;
+ void
+ group::query_gid (gid_t gid)
+ {
+ buffer_type::size_type size = 1 << 7;
+ buffer.reserve(size);
+ int error;
- ::group *grp_result;
+ ::group *grp_result;
- while ((error = getgrgid_r(gid, this,
- &buffer[0], buffer.capacity(),
- &grp_result)))
- {
- size <<= 1;
- buffer.reserve(size);
- }
+ while ((error = getgrgid_r(gid, this,
+ &buffer[0], buffer.capacity(),
+ &grp_result)))
+ {
+ size <<= 1;
+ buffer.reserve(size);
+ }
- if (grp_result)
- valid = true;
- else
- errno = error;
-}
+ if (grp_result)
+ valid = true;
+ else
+ errno = error;
+ }
-void
-sbuild::group::query_name (const char *name)
-{
- buffer_type::size_type size = 1 << 8;
- buffer.reserve(size);
- int error;
+ void
+ group::query_name (const char *name)
+ {
+ buffer_type::size_type size = 1 << 8;
+ buffer.reserve(size);
+ int error;
- ::group *grp_result;
+ ::group *grp_result;
- while ((error = getgrnam_r(name, this,
- &buffer[0], buffer.capacity(),
- &grp_result)))
- {
- size <<= 1;
- buffer.reserve(size);
- }
+ while ((error = getgrnam_r(name, this,
+ &buffer[0], buffer.capacity(),
+ &grp_result)))
+ {
+ size <<= 1;
+ buffer.reserve(size);
+ }
- if (grp_result)
- valid = true;
- else
- errno = error;
-}
+ if (grp_result)
+ valid = true;
+ else
+ errno = error;
+ }
-void
-sbuild::group::query_name (std::string const& name)
-{
- query_name(name.c_str());
-}
+ void
+ group::query_name (std::string const& name)
+ {
+ query_name(name.c_str());
+ }
+
+ bool
+ group::operator ! () const
+ {
+ return !valid;
+ }
-bool
-sbuild::group::operator ! () const
-{
- return !valid;
}
diff --git a/lib/schroot-common/main.cc b/lib/schroot-common/main.cc
index ebd44ccb..65f7a34f 100644
--- a/lib/schroot-common/main.cc
+++ b/lib/schroot-common/main.cc
@@ -43,342 +43,346 @@ using std::endl;
using boost::format;
using sbuild::_;
using sbuild::N_;
-using namespace schroot_common;
-template<>
-sbuild::error<main::error_code>::map_type
-sbuild::error<main::error_code>::error_strings =
- {
- // TRANSLATORS: %4% = file
- {main::CHROOT_FILE, N_("No chroots are defined in ‘%4%’")},
- // TRANSLATORS: %4% = file
- // TRANSLATORS: %5% = file
- {main::CHROOT_FILE2, N_("No chroots are defined in ‘%4%’ or ‘%5%’")},
- // TRANSLATORS: %1% = file
- {main::CHROOT_NOTDEFINED, N_("The specified chroots are not defined in ‘%1%’")},
- {main::SESSION_INVALID, N_("%1%: Invalid session name")}
- };
-
-main::main (std::string const& program_name,
- std::string const& program_usage,
- options::ptr& options,
- bool use_syslog):
- bin_common::main(program_name, program_usage,
- std::static_pointer_cast<bin_common::options>(options),
- use_syslog),
- options(options)
-{
-}
-
-main::~main ()
-{
-}
-
-void
-main::action_version (std::ostream& stream)
-{
- bin_common::main::action_version(stream);
-
- stream << '\n'
- << _("Installed chroot facets:")
- << '\n';
- sbuild::chroot::facet::factory::print_facets(stream);
-
- stream << std::flush;
-}
-
-void
-main::action_info ()
-{
- for(auto chroot_name = this->chroot_names.begin();
- chroot_name != this->chroot_names.end();
- ++chroot_name)
- {
- // This should never fail, so no error handling here--we already
- // validated everything when we got the chroot map.
- sbuild::chroot::config::chroot_map::const_iterator c = this->chroots.find(*chroot_name);
- assert(c->second);
-
- std::cout << c->second;
- if (chroot_name + 1 != this->chroot_names.end())
- std::cout << '\n';
- }
-
- std::cout << std::flush;
-}
-
-void
-main::action_location ()
-{
- for(const auto& chroot_name : this->chroot_names)
- {
- // This should never fail, so no error handling here--we already
- // validated everything when we got the chroot map.
- const auto chroot = this->chroots.find(chroot_name);
- assert(chroot->second);
-
- std::cout << chroot->second->get_path() << '\n';
- }
-
- std::cout << std::flush;
-}
-
-void
-main::action_config ()
-{
- std::cout << "# "
- // TRANSLATORS: %1% = program name
- // TRANSLATORS: %2% = program version
- // TRANSLATORS: %3% = current date
- << format(_("schroot configuration generated by %1% %2% on %3%"))
- % this->program_name % VERSION % sbuild::date(time(0))
- << endl;
- std::cout << endl;
-
- sbuild::keyfile info;
-
- for(const auto& chroot_name : this->chroot_names)
- {
- // This should never fail, so no error handling here--we already
- // validated everything when we got the chroot map.
- const auto chroot = this->chroots.find(chroot_name);
- assert(chroot->second);
-
- // Generated chroots (e.g. source chroots) are not printed.
- if (chroot->second->get_original())
- info << chroot->second;
- }
-
- std::cout << sbuild::keyfile_writer(info) << std::flush;
-}
-
-void
-main::get_chroot_options ()
+namespace schroot_common
{
- if (this->options->all_chroots == true ||
- this->options->all_sessions == true ||
- this->options->all_source_chroots == true)
+ template<>
+ sbuild::error<main::error_code>::map_type
+ sbuild::error<main::error_code>::error_strings =
{
- if (this->options->all_chroots)
- {
- sbuild::string_list chroots;
- if (this->options->action == options::ACTION_LIST &&
- !this->options->exclude_aliases)
- chroots = this->config->get_alias_list("chroot");
- else
- chroots = this->config->get_chroot_list("chroot");
- this->chroot_names.insert(this->chroot_names.end(), chroots.begin(), chroots.end());
- }
- if (this->options->all_sessions)
- {
- sbuild::string_list sessions;
- if (this->options->action == options::ACTION_LIST &&
- !this->options->exclude_aliases)
- sessions = this->config->get_alias_list("session");
- else
- sessions = this->config->get_chroot_list("session");
- this->chroot_names.insert(this->chroot_names.end(), sessions.begin(), sessions.end());
- }
- if (this->options->all_source_chroots)
- {
- sbuild::string_list sources;
- if (this->options->action == options::ACTION_LIST &&
- !this->options->exclude_aliases)
- sources = this->config->get_alias_list("source");
- else
- sources = this->config->get_chroot_list("source");
- this->chroot_names.insert(this->chroot_names.end(), sources.begin(), sources.end());
- }
-
- // Validate and normalise
- this->chroots = this->config->validate_chroots("", this->chroot_names);
- }
- else
- {
- // Search in the appropriate namespace.
- std::string chroot_namespace("chroot");
- if (this->options->action == options::ACTION_SESSION_RECOVER ||
- this->options->action == options::ACTION_SESSION_RUN ||
- this->options->action == options::ACTION_SESSION_END)
- chroot_namespace = "session";
-
- // Validate and normalise
- this->chroot_names = this->options->chroots;
- this->chroots = this->config->validate_chroots
- (chroot_namespace, this->chroot_names);
- }
-}
+ // TRANSLATORS: %4% = file
+ {schroot_common::main::CHROOT_FILE, N_("No chroots are defined in ‘%4%’")},
+ // TRANSLATORS: %4% = file
+ // TRANSLATORS: %5% = file
+ {schroot_common::main::CHROOT_FILE2, N_("No chroots are defined in ‘%4%’ or ‘%5%’")},
+ // TRANSLATORS: %1% = file
+ {schroot_common::main::CHROOT_NOTDEFINED, N_("The specified chroots are not defined in ‘%1%’")},
+ {schroot_common::main::SESSION_INVALID, N_("%1%: Invalid session name")}
+ };
+
+ main::main (std::string const& program_name,
+ std::string const& program_usage,
+ options::ptr& options,
+ bool use_syslog):
+ bin_common::main(program_name, program_usage,
+ std::static_pointer_cast<bin_common::options>(options),
+ use_syslog),
+ options(options)
+ {
+ }
-void
-main::load_config ()
-{
- this->config = sbuild::chroot::config::ptr(new sbuild::chroot::config);
- /* The normal chroot list is used when starting a session or running
- any chroot type or session, or displaying chroot information. */
- if (this->options->load_chroots == true)
- {
- this->config->add("chroot", SCHROOT_CONF);
- this->config->add("chroot", SCHROOT_CONF_CHROOT_D);
- }
- /* The session chroot list is used when running or ending an
- existing session, or displaying chroot information. */
- if (this->options->load_sessions == true)
- this->config->add("session", SCHROOT_SESSION_DIR);
-}
+ main::~main ()
+ {
+ }
-int
-main::run_impl ()
-{
- if (this->options->action == options::ACTION_HELP)
- {
- action_help(std::cout);
- return EXIT_SUCCESS;
- }
+ void
+ main::action_version (std::ostream& stream)
+ {
+ bin_common::main::action_version(stream);
- if (this->options->action == options::ACTION_VERSION)
- {
- action_version(std::cout);
- return EXIT_SUCCESS;
- }
+ stream << '\n'
+ << _("Installed chroot facets:")
+ << '\n';
+ sbuild::chroot::facet::factory::print_facets(stream);
- /* Initialise chroot configuration. */
- load_config();
+ stream << std::flush;
+ }
- if (this->options->load_chroots &&
- this->config->get_chroots("chroot").empty() &&
- this->options->quiet == false)
- log_exception_warning(error(CHROOT_FILE2, SCHROOT_CONF, SCHROOT_CONF_CHROOT_D));
+ void
+ main::action_info ()
+ {
+ for(auto chroot_name = this->chroot_names.begin();
+ chroot_name != this->chroot_names.end();
+ ++chroot_name)
+ {
+ // This should never fail, so no error handling here--we already
+ // validated everything when we got the chroot map.
+ sbuild::chroot::config::chroot_map::const_iterator c = this->chroots.find(*chroot_name);
+ assert(c->second);
+
+ std::cout << c->second;
+ if (chroot_name + 1 != this->chroot_names.end())
+ std::cout << '\n';
+ }
+
+ std::cout << std::flush;
+ }
+
+ void
+ main::action_location ()
+ {
+ for(const auto& chroot_name : this->chroot_names)
+ {
+ // This should never fail, so no error handling here--we already
+ // validated everything when we got the chroot map.
+ const auto chroot = this->chroots.find(chroot_name);
+ assert(chroot->second);
- /* Get list of chroots to use */
- get_chroot_options();
- if (this->chroots.empty())
- {
- if (!(this->options->all_chroots == true ||
- this->options->all_sessions == true ||
- this->options->all_source_chroots == true))
- throw error(SCHROOT_CONF, CHROOT_NOTDEFINED);
- else
- {
- // If one of the --all options was used, then don't treat
- // the lack of chroots as an error. TODO: Also check if any
- // additional chroots were specified with -c; this needs
- // changes in get_chroot_options.
- if (this->options->verbose)
- log_exception_warning(error((this->options->all_chroots == true) ?
- SCHROOT_CONF : SCHROOT_SESSION_DIR,
- CHROOT_NOTDEFINED));
- return EXIT_SUCCESS;
- }
- }
- this->chroot_objects.clear();
- for(const auto& chroot_name : this->chroot_names)
- {
- // This should never fail, so no error handling here--we already
- // validated everything when we got the chroot map.
- const auto chroot = this->chroots.find(chroot_name);
- assert(chroot->second);
- sbuild::session::chroot_list::value_type e;
- e.alias = chroot->first;
- e.chroot = chroot->second;
- chroot_objects.push_back(e);
- }
-
- /* Print chroot list. */
- if (this->options->action == options::ACTION_LIST)
- {
- action_list();
- return EXIT_SUCCESS;
- }
+ std::cout << chroot->second->get_path() << '\n';
+ }
- if (this->config->find_alias("session", this->options->session_name))
- throw error(this->options->session_name, SESSION_INVALID);
+ std::cout << std::flush;
+ }
- /* Print chroot information for specified chroots. */
- if (this->options->action == options::ACTION_INFO)
- {
- action_info();
- return EXIT_SUCCESS;
- }
- if (this->options->action == options::ACTION_LOCATION)
- {
- action_location();
- return EXIT_SUCCESS;
- }
- if (this->options->action == options::ACTION_CONFIG)
- {
- action_config();
- return EXIT_SUCCESS;
- }
-
- /* Create a session. */
- sbuild::session::operation sess_op(sbuild::session::OPERATION_AUTOMATIC);
- if (this->options->action == options::ACTION_SESSION_BEGIN)
- sess_op = sbuild::session::OPERATION_BEGIN;
- else if (this->options->action == options::ACTION_SESSION_RECOVER)
- sess_op = sbuild::session::OPERATION_RECOVER;
- else if (this->options->action == options::ACTION_SESSION_RUN)
- sess_op = sbuild::session::OPERATION_RUN;
- else if (this->options->action == options::ACTION_SESSION_END)
- sess_op = sbuild::session::OPERATION_END;
-
- try
- {
- create_session(sess_op);
- add_session_auth();
-
- if (!this->options->command.empty())
- this->session->get_auth()->set_command(this->options->command);
- if (!this->options->directory.empty())
- this->session->get_auth()->set_wd(this->options->directory);
- if (!this->options->shell.empty())
- this->session->set_shell_override(this->options->shell);
- this->session->set_preserve_environment(this->options->preserve);
- this->session->set_session_id(this->options->session_name);
- this->session->set_force(this->options->session_force);
- if (this->options->quiet)
- this->session->set_verbosity("quiet");
- else if (this->options->verbose)
- this->session->set_verbosity("verbose");
- this->session->set_user_options(this->options->useroptions_map);
-
- /* Run session. */
- this->session->run();
- }
- catch (std::runtime_error const& e)
- {
- if (!this->options->quiet)
- sbuild::log_exception_error(e);
- }
-
- if (this->session)
- return this->session->get_child_status();
- else
- return EXIT_FAILURE;
-}
+ void
+ main::action_config ()
+ {
+ std::cout << "# "
+ // TRANSLATORS: %1% = program name
+ // TRANSLATORS: %2% = program version
+ // TRANSLATORS: %3% = current date
+ << format(_("schroot configuration generated by %1% %2% on %3%"))
+ % this->program_name % VERSION % sbuild::date(time(0))
+ << endl;
+ std::cout << endl;
+
+ sbuild::keyfile info;
+
+ for(const auto& chroot_name : this->chroot_names)
+ {
+ // This should never fail, so no error handling here--we already
+ // validated everything when we got the chroot map.
+ const auto chroot = this->chroots.find(chroot_name);
+ assert(chroot->second);
+
+ // Generated chroots (e.g. source chroots) are not printed.
+ if (chroot->second->get_original())
+ info << chroot->second;
+ }
+
+ std::cout << sbuild::keyfile_writer(info) << std::flush;
+ }
+
+ void
+ main::get_chroot_options ()
+ {
-void
-main::add_session_auth ()
-{
- // Add PAM authentication handler. If PAM isn't available, just
- // continue to use the default handler
+ if (this->options->all_chroots == true ||
+ this->options->all_sessions == true ||
+ this->options->all_source_chroots == true)
+ {
+ if (this->options->all_chroots)
+ {
+ sbuild::string_list chroots;
+ if (this->options->action == options::ACTION_LIST &&
+ !this->options->exclude_aliases)
+ chroots = this->config->get_alias_list("chroot");
+ else
+ chroots = this->config->get_chroot_list("chroot");
+ this->chroot_names.insert(this->chroot_names.end(), chroots.begin(), chroots.end());
+ }
+ if (this->options->all_sessions)
+ {
+ sbuild::string_list sessions;
+ if (this->options->action == options::ACTION_LIST &&
+ !this->options->exclude_aliases)
+ sessions = this->config->get_alias_list("session");
+ else
+ sessions = this->config->get_chroot_list("session");
+ this->chroot_names.insert(this->chroot_names.end(), sessions.begin(), sessions.end());
+ }
+ if (this->options->all_source_chroots)
+ {
+ sbuild::string_list sources;
+ if (this->options->action == options::ACTION_LIST &&
+ !this->options->exclude_aliases)
+ sources = this->config->get_alias_list("source");
+ else
+ sources = this->config->get_chroot_list("source");
+ this->chroot_names.insert(this->chroot_names.end(), sources.begin(), sources.end());
+ }
+
+ // Validate and normalise
+ this->chroots = this->config->validate_chroots("", this->chroot_names);
+ }
+ else
+ {
+ // Search in the appropriate namespace.
+ std::string chroot_namespace("chroot");
+ if (this->options->action == options::ACTION_SESSION_RECOVER ||
+ this->options->action == options::ACTION_SESSION_RUN ||
+ this->options->action == options::ACTION_SESSION_END)
+ chroot_namespace = "session";
+
+ // Validate and normalise
+ this->chroot_names = this->options->chroots;
+ this->chroots = this->config->validate_chroots
+ (chroot_namespace, this->chroot_names);
+ }
+ }
+
+ void
+ main::load_config ()
+ {
+ this->config = sbuild::chroot::config::ptr(new sbuild::chroot::config);
+ /* The normal chroot list is used when starting a session or running
+ any chroot type or session, or displaying chroot information. */
+ if (this->options->load_chroots == true)
+ {
+ this->config->add("chroot", SCHROOT_CONF);
+ this->config->add("chroot", SCHROOT_CONF_CHROOT_D);
+ }
+ /* The session chroot list is used when running or ending an
+ existing session, or displaying chroot information. */
+ if (this->options->load_sessions == true)
+ this->config->add("session", SCHROOT_SESSION_DIR);
+ }
+
+ int
+ main::run_impl ()
+ {
+ if (this->options->action == options::ACTION_HELP)
+ {
+ action_help(std::cout);
+ return EXIT_SUCCESS;
+ }
+
+ if (this->options->action == options::ACTION_VERSION)
+ {
+ action_version(std::cout);
+ return EXIT_SUCCESS;
+ }
+
+ /* Initialise chroot configuration. */
+ load_config();
+
+ if (this->options->load_chroots &&
+ this->config->get_chroots("chroot").empty() &&
+ this->options->quiet == false)
+ log_exception_warning(error(CHROOT_FILE2, SCHROOT_CONF, SCHROOT_CONF_CHROOT_D));
+
+ /* Get list of chroots to use */
+ get_chroot_options();
+ if (this->chroots.empty())
+ {
+ if (!(this->options->all_chroots == true ||
+ this->options->all_sessions == true ||
+ this->options->all_source_chroots == true))
+ throw error(SCHROOT_CONF, CHROOT_NOTDEFINED);
+ else
+ {
+ // If one of the --all options was used, then don't treat
+ // the lack of chroots as an error. TODO: Also check if any
+ // additional chroots were specified with -c; this needs
+ // changes in get_chroot_options.
+ if (this->options->verbose)
+ log_exception_warning(error((this->options->all_chroots == true) ?
+ SCHROOT_CONF : SCHROOT_SESSION_DIR,
+ CHROOT_NOTDEFINED));
+ return EXIT_SUCCESS;
+ }
+ }
+ this->chroot_objects.clear();
+ for(const auto& chroot_name : this->chroot_names)
+ {
+ // This should never fail, so no error handling here--we already
+ // validated everything when we got the chroot map.
+ const auto chroot = this->chroots.find(chroot_name);
+ assert(chroot->second);
+ sbuild::session::chroot_list::value_type e;
+ e.alias = chroot->first;
+ e.chroot = chroot->second;
+ chroot_objects.push_back(e);
+ }
+
+ /* Print chroot list. */
+ if (this->options->action == options::ACTION_LIST)
+ {
+ action_list();
+ return EXIT_SUCCESS;
+ }
+
+ if (this->config->find_alias("session", this->options->session_name))
+ throw error(this->options->session_name, SESSION_INVALID);
+
+ /* Print chroot information for specified chroots. */
+ if (this->options->action == options::ACTION_INFO)
+ {
+ action_info();
+ return EXIT_SUCCESS;
+ }
+ if (this->options->action == options::ACTION_LOCATION)
+ {
+ action_location();
+ return EXIT_SUCCESS;
+ }
+ if (this->options->action == options::ACTION_CONFIG)
+ {
+ action_config();
+ return EXIT_SUCCESS;
+ }
+
+ /* Create a session. */
+ sbuild::session::operation sess_op(sbuild::session::OPERATION_AUTOMATIC);
+ if (this->options->action == options::ACTION_SESSION_BEGIN)
+ sess_op = sbuild::session::OPERATION_BEGIN;
+ else if (this->options->action == options::ACTION_SESSION_RECOVER)
+ sess_op = sbuild::session::OPERATION_RECOVER;
+ else if (this->options->action == options::ACTION_SESSION_RUN)
+ sess_op = sbuild::session::OPERATION_RUN;
+ else if (this->options->action == options::ACTION_SESSION_END)
+ sess_op = sbuild::session::OPERATION_END;
+
+ try
+ {
+ create_session(sess_op);
+ add_session_auth();
+
+ if (!this->options->command.empty())
+ this->session->get_auth()->set_command(this->options->command);
+ if (!this->options->directory.empty())
+ this->session->get_auth()->set_wd(this->options->directory);
+ if (!this->options->shell.empty())
+ this->session->set_shell_override(this->options->shell);
+ this->session->set_preserve_environment(this->options->preserve);
+ this->session->set_session_id(this->options->session_name);
+ this->session->set_force(this->options->session_force);
+ if (this->options->quiet)
+ this->session->set_verbosity("quiet");
+ else if (this->options->verbose)
+ this->session->set_verbosity("verbose");
+ this->session->set_user_options(this->options->useroptions_map);
+
+ /* Run session. */
+ this->session->run();
+ }
+ catch (std::runtime_error const& e)
+ {
+ if (!this->options->quiet)
+ sbuild::log_exception_error(e);
+ }
+
+ if (this->session)
+ return this->session->get_child_status();
+ else
+ return EXIT_FAILURE;
+ }
+
+ void
+ main::add_session_auth ()
+ {
+ // Add PAM authentication handler. If PAM isn't available, just
+ // continue to use the default handler
#ifdef SBUILD_FEATURE_PAM
- sbuild::auth::auth::ptr auth = sbuild::auth::pam::create("schroot");
+ sbuild::auth::auth::ptr auth = sbuild::auth::pam::create("schroot");
- sbuild::auth::pam_conv::auth_ptr pam_auth =
- std::dynamic_pointer_cast<sbuild::auth::pam>(auth);
+ sbuild::auth::pam_conv::auth_ptr pam_auth =
+ std::dynamic_pointer_cast<sbuild::auth::pam>(auth);
- sbuild::auth::pam_conv::ptr conv = sbuild::auth::pam_conv_tty::create(pam_auth);
+ sbuild::auth::pam_conv::ptr conv = sbuild::auth::pam_conv_tty::create(pam_auth);
- /* Set up authentication timeouts. */
- time_t curtime = 0;
- time(&curtime);
- conv->set_warning_timeout(curtime + 15);
- conv->set_fatal_timeout(curtime + 20);
- pam_auth->set_conv(conv);
+ /* Set up authentication timeouts. */
+ time_t curtime = 0;
+ time(&curtime);
+ conv->set_warning_timeout(curtime + 15);
+ conv->set_fatal_timeout(curtime + 20);
+ pam_auth->set_conv(conv);
- this->session->set_auth(auth);
+ this->session->set_auth(auth);
#endif // SBUILD_FEATURE_PAM
+ }
+
}
diff --git a/lib/schroot-common/options.cc b/lib/schroot-common/options.cc
index 4e5f6d52..b0af5ae0 100644
--- a/lib/schroot-common/options.cc
+++ b/lib/schroot-common/options.cc
@@ -33,239 +33,243 @@ using std::endl;
using boost::format;
using sbuild::_;
namespace opt = boost::program_options;
-using namespace schroot_common;
-const options::action_type options::ACTION_SESSION_AUTO ("session_auto");
-const options::action_type options::ACTION_SESSION_BEGIN ("session_begin");
-const options::action_type options::ACTION_SESSION_RECOVER ("session_recover");
-const options::action_type options::ACTION_SESSION_RUN ("session_run");
-const options::action_type options::ACTION_SESSION_END ("session_end");
-const options::action_type options::ACTION_LIST ("list");
-const options::action_type options::ACTION_INFO ("info");
-const options::action_type options::ACTION_LOCATION ("location");
-const options::action_type options::ACTION_CONFIG ("config");
-
-options::options ():
- bin_common::options (),
- chroots(),
- command(),
- directory(),
- shell(),
- user(),
- preserve(false),
- all(false),
- all_chroots(false),
- all_sessions(false),
- all_source_chroots(false),
- exclude_aliases(false),
- session_name(),
- session_force(false),
- useroptions(),
- useroptions_map(),
- chroot(_("Chroot selection")),
- chrootenv(_("Chroot environment")),
- session_actions(_("Session actions")),
- session_options(_("Session options"))
+namespace schroot_common
{
-}
-options::~options ()
-{
-}
+ const options::action_type options::ACTION_SESSION_AUTO ("session_auto");
+ const options::action_type options::ACTION_SESSION_BEGIN ("session_begin");
+ const options::action_type options::ACTION_SESSION_RECOVER ("session_recover");
+ const options::action_type options::ACTION_SESSION_RUN ("session_run");
+ const options::action_type options::ACTION_SESSION_END ("session_end");
+ const options::action_type options::ACTION_LIST ("list");
+ const options::action_type options::ACTION_INFO ("info");
+ const options::action_type options::ACTION_LOCATION ("location");
+ const options::action_type options::ACTION_CONFIG ("config");
-void
-options::add_options ()
-{
- // Chain up to add basic options.
- bin_common::options::add_options();
+ options::options ():
+ bin_common::options (),
+ chroots(),
+ command(),
+ directory(),
+ shell(),
+ user(),
+ preserve(false),
+ all(false),
+ all_chroots(false),
+ all_sessions(false),
+ all_source_chroots(false),
+ exclude_aliases(false),
+ session_name(),
+ session_force(false),
+ useroptions(),
+ useroptions_map(),
+ chroot(_("Chroot selection")),
+ chrootenv(_("Chroot environment")),
+ session_actions(_("Session actions")),
+ session_options(_("Session options"))
+ {
+ }
- action.add(ACTION_SESSION_AUTO);
- action.set_default(ACTION_SESSION_AUTO);
- action.add(ACTION_SESSION_BEGIN);
- action.add(ACTION_SESSION_RECOVER);
- action.add(ACTION_SESSION_RUN);
- action.add(ACTION_SESSION_END);
- action.add(ACTION_LIST);
- action.add(ACTION_INFO);
- action.add(ACTION_LOCATION);
- action.add(ACTION_CONFIG);
+ options::~options ()
+ {
+ }
- actions.add_options()
- ("list,l",
- _("List available chroots"))
- ("info,i",
- _("Show information about selected chroots"))
- ("config",
- _("Dump configuration of selected chroots"));
+ void
+ options::add_options ()
+ {
+ // Chain up to add basic options.
+ bin_common::options::add_options();
- chroot.add_options()
- ("chroot,c", opt::value<sbuild::string_list>(&this->chroots),
- _("Use specified chroot"));
+ action.add(ACTION_SESSION_AUTO);
+ action.set_default(ACTION_SESSION_AUTO);
+ action.add(ACTION_SESSION_BEGIN);
+ action.add(ACTION_SESSION_RECOVER);
+ action.add(ACTION_SESSION_RUN);
+ action.add(ACTION_SESSION_END);
+ action.add(ACTION_LIST);
+ action.add(ACTION_INFO);
+ action.add(ACTION_LOCATION);
+ action.add(ACTION_CONFIG);
- hidden.add_options()
- ("command", opt::value<sbuild::string_list>(&this->command),
- _("Command to run"));
+ actions.add_options()
+ ("list,l",
+ _("List available chroots"))
+ ("info,i",
+ _("Show information about selected chroots"))
+ ("config",
+ _("Dump configuration of selected chroots"));
- positional.add("command", -1);
-}
+ chroot.add_options()
+ ("chroot,c", opt::value<sbuild::string_list>(&this->chroots),
+ _("Use specified chroot"));
-void
-options::add_option_groups ()
-{
- // Chain up to add basic option groups.
- bin_common::options::add_option_groups();
+ hidden.add_options()
+ ("command", opt::value<sbuild::string_list>(&this->command),
+ _("Command to run"));
+
+ positional.add("command", -1);
+ }
+
+ void
+ options::add_option_groups ()
+ {
+ // Chain up to add basic option groups.
+ bin_common::options::add_option_groups();
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!chroot.options().empty())
+ if (!chroot.options().empty())
#else
- if (!chroot.primary_keys().empty())
+ if (!chroot.primary_keys().empty())
#endif
- {
- visible.add(chroot);
- global.add(chroot);
- }
+ {
+ visible.add(chroot);
+ global.add(chroot);
+ }
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!chrootenv.options().empty())
+ if (!chrootenv.options().empty())
#else
- if (!chrootenv.primary_keys().empty())
+ if (!chrootenv.primary_keys().empty())
#endif
- {
- visible.add(chrootenv);
- global.add(chrootenv);
- }
+ {
+ visible.add(chrootenv);
+ global.add(chrootenv);
+ }
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!session_actions.options().empty())
+ if (!session_actions.options().empty())
#else
- if (!session_actions.primary_keys().empty())
+ if (!session_actions.primary_keys().empty())
#endif
- {
- visible.add(session_actions);
- global.add(session_actions);
- }
+ {
+ visible.add(session_actions);
+ global.add(session_actions);
+ }
#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
- if (!session_options.options().empty())
+ if (!session_options.options().empty())
#else
- if (!session_options.primary_keys().empty())
+ if (!session_options.primary_keys().empty())
#endif
- {
- visible.add(session_options);
- global.add(session_options);
- }
-}
-
-void
-options::check_options ()
-{
- // Chain up to check basic options.
- bin_common::options::check_options();
+ {
+ visible.add(session_options);
+ global.add(session_options);
+ }
+ }
- if (vm.count("list"))
- this->action = ACTION_LIST;
- if (vm.count("info"))
- this->action = ACTION_INFO;
- if (vm.count("config"))
- this->action = ACTION_CONFIG;
-}
+ void
+ options::check_options ()
+ {
+ // Chain up to check basic options.
+ bin_common::options::check_options();
-void
-options::check_actions ()
-{
- // Chain up to check basic actions.
- bin_common::options::check_actions();
+ if (vm.count("list"))
+ this->action = ACTION_LIST;
+ if (vm.count("info"))
+ this->action = ACTION_INFO;
+ if (vm.count("config"))
+ this->action = ACTION_CONFIG;
+ }
- if (this->quiet && this->verbose)
- {
- sbuild::log_warning()
- << _("--quiet and --verbose may not be used at the same time")
- << endl;
- sbuild::log_info() << _("Using verbose output") << endl;
- }
+ void
+ options::check_actions ()
+ {
+ // Chain up to check basic actions.
+ bin_common::options::check_actions();
- if (!this->chroots.empty() && all_used())
- {
- sbuild::log_warning()
- << _("--chroot and --all may not be used at the same time")
- << endl;
- sbuild::log_info() << _("Using --chroots only") << endl;
- this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
- }
+ if (this->quiet && this->verbose)
+ {
+ sbuild::log_warning()
+ << _("--quiet and --verbose may not be used at the same time")
+ << endl;
+ sbuild::log_info() << _("Using verbose output") << endl;
+ }
- /* Determine which chroots to load and use. */
- if (this->action == ACTION_SESSION_AUTO)
- {
- // Only allow normal chroots
- this->load_chroots = true;
- this->load_sessions = false;
- this->all = this->all_sessions = false;
+ if (!this->chroots.empty() && all_used())
+ {
+ sbuild::log_warning()
+ << _("--chroot and --all may not be used at the same time")
+ << endl;
+ sbuild::log_info() << _("Using --chroots only") << endl;
+ this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
+ }
- // If no chroot was specified, fall back to the "default" chroot.
- if (this->chroots.empty() && all_used() == false)
- this->chroots.push_back("default");
- }
- else if (this->action == ACTION_SESSION_BEGIN)
- {
- // Only allow one session chroot
- this->load_chroots = true;
- this->load_sessions = false;
- if (this->chroots.size() != 1 || all_used())
- throw error
- (_("Exactly one chroot must be specified when beginning a session"));
+ /* Determine which chroots to load and use. */
+ if (this->action == ACTION_SESSION_AUTO)
+ {
+ // Only allow normal chroots
+ this->load_chroots = true;
+ this->load_sessions = false;
+ this->all = this->all_sessions = false;
- this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
- }
- else if (this->action == ACTION_SESSION_RECOVER ||
- this->action == ACTION_SESSION_RUN ||
- this->action == ACTION_SESSION_END)
- {
- // Session operations work on all chroots.
- this->load_chroots = this->load_sessions = true;
+ // If no chroot was specified, fall back to the "default" chroot.
+ if (this->chroots.empty() && all_used() == false)
+ this->chroots.push_back("default");
+ }
+ else if (this->action == ACTION_SESSION_BEGIN)
+ {
+ // Only allow one session chroot
+ this->load_chroots = true;
+ this->load_sessions = false;
+ if (this->chroots.size() != 1 || all_used())
+ throw error
+ (_("Exactly one chroot must be specified when beginning a session"));
- if (!this->session_name.empty())
- throw error
- (_("--session-name is not permitted for the specified action; did you mean to use --chroot?"));
- }
- else if (this->action == ACTION_HELP ||
- this->action == ACTION_VERSION)
- {
- // Chroots don't make sense here.
- this->load_chroots = this->load_sessions = false;
- this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
- }
- else if (this->action == ACTION_LIST ||
- this->action == ACTION_INFO ||
- this->action == ACTION_LOCATION ||
- this->action == ACTION_CONFIG)
- {
- // If not specified otherwise, load normal chroots, but allow
- // --all options.
- if (!this->chroots.empty()) // chroot specified
+ this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
+ }
+ else if (this->action == ACTION_SESSION_RECOVER ||
+ this->action == ACTION_SESSION_RUN ||
+ this->action == ACTION_SESSION_END)
+ {
+ // Session operations work on all chroots.
this->load_chroots = this->load_sessions = true;
- else if (!all_used()) // no chroots specified
- {
- this->all_chroots = true;
- if (this->action == ACTION_LIST || this->action == ACTION_INFO)
- this->all_source_chroots = true;
+
+ if (!this->session_name.empty())
+ throw error
+ (_("--session-name is not permitted for the specified action; did you mean to use --chroot?"));
+ }
+ else if (this->action == ACTION_HELP ||
+ this->action == ACTION_VERSION)
+ {
+ // Chroots don't make sense here.
+ this->load_chroots = this->load_sessions = false;
+ this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
+ }
+ else if (this->action == ACTION_LIST ||
+ this->action == ACTION_INFO ||
+ this->action == ACTION_LOCATION ||
+ this->action == ACTION_CONFIG)
+ {
+ // If not specified otherwise, load normal chroots, but allow
+ // --all options.
+ if (!this->chroots.empty()) // chroot specified
+ this->load_chroots = this->load_sessions = true;
+ else if (!all_used()) // no chroots specified
+ {
+ this->all_chroots = true;
+ if (this->action == ACTION_LIST || this->action == ACTION_INFO)
+ this->all_source_chroots = true;
+ this->load_chroots = true;
+ }
+ if (this->all_chroots || this->all_source_chroots)
this->load_chroots = true;
- }
- if (this->all_chroots || this->all_source_chroots)
- this->load_chroots = true;
- if (this->all_sessions)
- this->load_chroots = this->load_sessions = true;
- }
- else
- {
- // Something went wrong
- this->load_chroots = this->load_sessions = false;
- this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
- throw error(_("Unknown action specified"));
- }
+ if (this->all_sessions)
+ this->load_chroots = this->load_sessions = true;
+ }
+ else
+ {
+ // Something went wrong
+ this->load_chroots = this->load_sessions = false;
+ this->all = this->all_chroots = this->all_source_chroots = this->all_sessions = false;
+ throw error(_("Unknown action specified"));
+ }
+
+ if (!this->session_name.empty() && this->action != ACTION_SESSION_BEGIN)
+ throw error
+ (_("--session-name is not permitted for the specified action"));
- if (!this->session_name.empty() && this->action != ACTION_SESSION_BEGIN)
- throw error
- (_("--session-name is not permitted for the specified action"));
+ if (!this->session_name.empty() &&
+ !sbuild::is_valid_sessionname(this->session_name))
+ throw error(_("Invalid session name"));
+ }
- if (!this->session_name.empty() &&
- !sbuild::is_valid_sessionname(this->session_name))
- throw error(_("Invalid session name"));
}