Package: schroot
Version: 1.6.10-1
Severity: important
Debian Release: 8.0
Tags: patch

schroot allows to set a Linux personality for chroots, e.g. to run a
32bit chroot on a 64bit system. And there is a schroot setup script to
start services when entering the schroot. But these service setup script
ignores the personality; that's my problem.

So what is actually happening. Pasted From the RfC mails - thread is
here:
http://lists.alioth.debian.org/pipermail/buildd-tools-devel/2015-February/009398.html

> I don't have any own setup script.
> 
> I have a build / development system (Debian Wheezy), which is running
> icecc. It's 64bit. The build schroot is an Ubuntu Precise schroot, 32bit.
> 
> The config for the schroot contains the line "setup.services=iceccd", so
> an iceccd instance is started per schroot session. The schroots iceccd
> runs without remote connect, so just distributes jobs.
> 
> So the user hacks on LibreOffice in the schroot and compiles using all
> free icecc resources on several machines.
> 
> But without the patch / personality-helper, the schroot sessions iceccd
> is started in the host system context, so it thinks, it's running on a
> 64bit system and generates 64bit object files, which obviuosly fails to
> link, when the build system expects 32bit object files.

So I've basically derivated a small schroot helper "schroot-impersonate"
from "schroot-mount", which understands the schroot personality types
and starts a command with the chroots personality. This program is now
used in the service setup script and fixes my build problem.

Actually I think all command run in inside the chroot from a setup
scripts should set the personality, so this should become a schroot
chroot personality wrapper, as the personality should always and just be
applied in the chroot.

The two attached patches:

For schroot 1.6: was tested with the schroot-wheezy-backport git branch.
At applies to schroot-1.6 FWIW. The original patch was done 1/2 year
ago, but I did some cleanup and just a quick test and it still "seems to
work".

For schroot 1.7: was just compile tested - I currently don't have a
Jessie environment.

Regards,

Jan-Marek
From 83603af12eb28314baf8330de244acc3c5f45374 Mon Sep 17 00:00:00 2001
From: Jan-Marek Glogowski <glo...@fbihome.de>
Date: Mon, 11 Aug 2014 17:28:32 +0200
Subject: [PATCH] Add personality impersonator

A little binary to run a program with the same personality then the
chroot. This is currently used to run the chroot services with the
correct personality.
---
 bin/CMakeLists.txt                                 |   1 +
 bin/schroot-impersonate/CMakeLists.txt             |  30 +++++
 .../schroot-impersonate-main.cc                    | 148 +++++++++++++++++++++
 bin/schroot-impersonate/schroot-impersonate-main.h |  89 +++++++++++++
 .../schroot-impersonate-options.cc                 | 106 +++++++++++++++
 .../schroot-impersonate-options.h                  |  75 +++++++++++
 bin/schroot-impersonate/schroot-impersonate.cc     |  47 +++++++
 etc/setup.d/70services                             |   6 +-
 sbuild/sbuild-chroot-facet-personality.cc          |   2 +
 9 files changed, 502 insertions(+), 2 deletions(-)
 create mode 100644 bin/schroot-impersonate/CMakeLists.txt
 create mode 100644 bin/schroot-impersonate/schroot-impersonate-main.cc
 create mode 100644 bin/schroot-impersonate/schroot-impersonate-main.h
 create mode 100644 bin/schroot-impersonate/schroot-impersonate-options.cc
 create mode 100644 bin/schroot-impersonate/schroot-impersonate-options.h
 create mode 100644 bin/schroot-impersonate/schroot-impersonate.cc

diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt
index 87cf774..1e69d34 100644
--- a/bin/CMakeLists.txt
+++ b/bin/CMakeLists.txt
@@ -22,5 +22,6 @@ add_subdirectory(dchroot)
 add_subdirectory(dchroot-dsa)
 add_subdirectory(schroot)
 add_subdirectory(schroot-base)
+add_subdirectory(schroot-impersonate)
 add_subdirectory(schroot-listmounts)
 add_subdirectory(schroot-mount)
diff --git a/bin/schroot-impersonate/CMakeLists.txt b/bin/schroot-impersonate/CMakeLists.txt
new file mode 100644
index 0000000..56f8753
--- /dev/null
+++ b/bin/schroot-impersonate/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+#
+# schroot is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# schroot is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+#####################################################################
+
+set(impersonate_sources
+    schroot-impersonate-main.h
+    schroot-impersonate-main.cc
+    schroot-impersonate-options.h
+    schroot-impersonate-options.cc
+    schroot-impersonate.cc)
+
+add_executable(schroot-impersonate ${impersonate_sources})
+target_link_libraries(schroot-impersonate sbuild schroot-base)
+
+install(TARGETS schroot-impersonate RUNTIME
+        DESTINATION ${SCHROOT_LIBEXEC_DIR})
diff --git a/bin/schroot-impersonate/schroot-impersonate-main.cc b/bin/schroot-impersonate/schroot-impersonate-main.cc
new file mode 100644
index 0000000..e662762
--- /dev/null
+++ b/bin/schroot-impersonate/schroot-impersonate-main.cc
@@ -0,0 +1,148 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "schroot-impersonate-main.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <locale>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <boost/format.hpp>
+
+#include <sbuild/sbuild-personality.h>
+
+
+using std::endl;
+using boost::format;
+using sbuild::_;
+using sbuild::N_;
+using namespace schroot_impersonate;
+
+namespace
+{
+
+  typedef std::pair<main::error_code,const char *> emap;
+
+  /**
+   * This is a list of the supported error codes.  It's used to
+   * construct the real error codes map.
+   */
+  emap init_errors[] =
+    {
+      // TRANSLATORS: %1% = command name
+      emap(main::EXEC,  N_("Failed to execute “%1%”")),
+    };
+
+}
+
+template<>
+sbuild::error<main::error_code>::map_type
+sbuild::error<main::error_code>::error_strings
+(init_errors,
+ init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
+
+main::main (options::ptr& options):
+  schroot_base::main("schroot-impersonate",
+                     // TRANSLATORS: '...' is an ellipsis e.g. U+2026,
+                     // and '-' is an em-dash.
+                     _("[OPTION…] [COMMAND] — run command with persona"),
+                     options,
+                     false),
+  opts(options)
+{
+}
+
+main::~main ()
+{
+}
+
+void
+main::action_impersonate ()
+{
+#ifdef SBUILD_FEATURE_PERSONALITY
+
+  /* Set the process execution domain. */
+  if (!opts->persona.empty())
+    {
+      sbuild::personality execPersonality( opts->persona );
+      execPersonality.set();
+      log_debug(sbuild::DEBUG_NOTICE) << "Set personality="
+                                      << opts->persona << std::endl;
+    }
+
+#endif // SCHROOT_FEATURE_PERSONALITY
+
+  sbuild::string_list command;
+  sbuild::environment env(environ);
+
+  std::copy(opts->command.begin(), opts->command.end(),
+            std::back_inserter(command));
+
+  sbuild::log_debug(sbuild::DEBUG_NOTICE)
+    << "command="
+    << sbuild::string_list_to_string(command, ", ")
+    << std::endl;
+
+  try
+    {
+      sbuild::log_debug(sbuild::DEBUG_INFO)
+        << "impersonate_main: executing "
+        << sbuild::string_list_to_string(command, ", ")
+        << std::endl;
+      exec(command[0], command, env);
+      error e(command[0], EXEC, strerror(errno));
+      sbuild::log_exception_error(e);
+    }
+  catch (std::exception const& e)
+    {
+      sbuild::log_exception_error(e);
+    }
+  catch (...)
+    {
+      sbuild::log_error()
+        << _("An unknown exception occurred") << std::endl;
+    }
+
+  // This should never be reached.
+  exit(EXIT_FAILURE);
+}
+
+int
+main::run_impl ()
+{
+  if (this->opts->action == options::ACTION_HELP)
+    action_help(std::cerr);
+  else if (this->opts->action == options::ACTION_VERSION)
+    action_version(std::cerr);
+  else if (this->opts->action == options::ACTION_IMPERSONATE)
+    action_impersonate();
+  else
+    assert(0); // Invalid action.
+
+  return EXIT_SUCCESS;
+}
diff --git a/bin/schroot-impersonate/schroot-impersonate-main.h b/bin/schroot-impersonate/schroot-impersonate-main.h
new file mode 100644
index 0000000..ec2e095
--- /dev/null
+++ b/bin/schroot-impersonate/schroot-impersonate-main.h
@@ -0,0 +1,89 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef SCHROOT_IMPERSONATE_MAIN_H
+#define SCHROOT_IMPERSONATE_MAIN_H
+
+#include <schroot-base/schroot-base-main.h>
+
+#include <schroot-impersonate/schroot-impersonate-options.h>
+
+#include <sbuild/sbuild-custom-error.h>
+
+/**
+ * schroot-impersonate program components
+ */
+namespace schroot_impersonate
+{
+
+  /**
+   * Frontend for schroot.  This class is used to "run" schroot.
+   */
+  class main : public schroot_base::main
+  {
+  public:
+    /// Error codes.
+    enum error_code
+      {
+        EXEC  ///< Failed to execute command.
+      };
+
+    /// Exception type.
+    typedef sbuild::custom_error<error_code> error;
+
+    /**
+     * The constructor.
+     *
+     * @param options the command-line options to use.
+     */
+    main (options::ptr& options);
+
+    /// The destructor.
+    virtual ~main ();
+
+  private:
+    /**
+     * List mounts.
+     */
+    virtual void
+    action_impersonate ();
+
+  protected:
+    /**
+     * Run the program.
+     *
+     * @returns 0 on success, 1 on failure or the exit status of the
+     * chroot command.
+     */
+    virtual int
+    run_impl ();
+
+  private:
+    /// The program options.
+    options::ptr opts;
+  };
+
+}
+
+#endif /* SCHROOT_IMPERSONATE_MAIN_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/bin/schroot-impersonate/schroot-impersonate-options.cc b/bin/schroot-impersonate/schroot-impersonate-options.cc
new file mode 100644
index 0000000..5caf8b0
--- /dev/null
+++ b/bin/schroot-impersonate/schroot-impersonate-options.cc
@@ -0,0 +1,106 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include <sbuild/sbuild-i18n.h>
+
+#include "schroot-impersonate-options.h"
+
+#include <cstdlib>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+
+using std::endl;
+using boost::format;
+using sbuild::_;
+namespace opt = boost::program_options;
+using namespace schroot_impersonate;
+
+const options::action_type options::ACTION_IMPERSONATE ("impersonate");
+
+options::options ():
+  schroot_base::options(),
+  persona(),
+  command(),
+  persona_opts(_("Persona"))
+{
+}
+
+options::~options ()
+{
+}
+
+void
+options::add_options ()
+{
+  // Chain up to add basic options.
+  schroot_base::options::add_options();
+
+  action.add(ACTION_IMPERSONATE);
+  action.set_default(ACTION_IMPERSONATE);
+
+  persona_opts.add_options()
+    ("persona,p", opt::value<std::string>(&this->persona),
+     _("Persona to use"));
+
+  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.
+  schroot_base::options::add_option_groups();
+
+#ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
+  if (!persona_opts.options().empty())
+#else
+  if (!persona_opts.primary_keys().empty())
+#endif
+    {
+      visible.add(persona_opts);
+      global.add(persona_opts);
+    }
+}
+
+void
+options::check_options ()
+{
+  // Chain up to check basic options.
+  schroot_base::options::check_options();
+
+  if (this->action == ACTION_IMPERSONATE)
+    {
+      if (this->command.begin() == this->command.end())
+        throw error(_("No command specified"));
+
+      if (!vm.count("persona"))
+        {
+          const char *env_persona = getenv("CHROOT_PERSONALITY");
+          if (env_persona)
+              this->persona = env_persona;
+        }
+    }
+}
diff --git a/bin/schroot-impersonate/schroot-impersonate-options.h b/bin/schroot-impersonate/schroot-impersonate-options.h
new file mode 100644
index 0000000..e0a36c9
--- /dev/null
+++ b/bin/schroot-impersonate/schroot-impersonate-options.h
@@ -0,0 +1,75 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef SCHROOT_IMPERSONATE_OPTIONS_H
+#define SCHROOT_IMPERSONATE_OPTIONS_H
+
+#include <schroot-base/schroot-base-options.h>
+
+#include <string>
+
+namespace schroot_impersonate
+{
+
+  /**
+   * schroot-impersonate command-line options.
+   */
+  class options : public schroot_base::options
+  {
+  public:
+    /// A shared_ptr to an options object.
+    typedef std::shared_ptr<options> ptr;
+
+    /// Begin, run and end a session.
+    static const action_type ACTION_IMPERSONATE;
+
+    /// The constructor.
+    options ();
+
+    /// The destructor.
+    virtual ~options ();
+
+    /// The persona to use.
+    std::string persona;
+
+    /// Command to run.
+    sbuild::string_list command;
+
+  protected:
+    virtual void
+    add_options ();
+
+    virtual void
+    add_option_groups ();
+
+    virtual void
+    check_options ();
+
+    /// Mount options group.
+    boost::program_options::options_description persona_opts;
+  };
+
+}
+
+#endif /* SCHROOT_IMPERSONATE_OPTIONS_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/bin/schroot-impersonate/schroot-impersonate.cc b/bin/schroot-impersonate/schroot-impersonate.cc
new file mode 100644
index 0000000..53b5510
--- /dev/null
+++ b/bin/schroot-impersonate/schroot-impersonate.cc
@@ -0,0 +1,47 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "schroot-impersonate-options.h"
+#include "schroot-impersonate-main.h"
+
+#include <schroot-base/schroot-base-run.h>
+
+using std::endl;
+using boost::format;
+namespace opt = boost::program_options;
+
+using namespace schroot_impersonate;
+
+/**
+ * Main routine.
+ *
+ * @param argc the number of arguments
+ * @param argv argument vector
+ *
+ * @returns 0 on success, 1 on failure or the exit status of the
+ * chroot command.
+ */
+int
+main (int   argc,
+      char *argv[])
+{
+  return schroot_base::run
+    <schroot_impersonate::options, schroot_impersonate::main>(argc, argv);
+}
diff --git a/etc/setup.d/70services b/etc/setup.d/70services
index c0cc1b2..6775e1a 100755
--- a/etc/setup.d/70services
+++ b/etc/setup.d/70services
@@ -38,7 +38,8 @@ if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then
     SETUP_SERVICES=$(echo "$SETUP_SERVICES" | tr ',' '\n')
 
     for service in $SETUP_SERVICES; do
-        chroot "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" start
+        "$LIBEXEC_DIR"/schroot-impersonate -- $(which chroot) \
+            "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" start
     done
 
 elif [ $STAGE = "setup-stop" ]; then
@@ -48,7 +49,8 @@ elif [ $STAGE = "setup-stop" ]; then
     SETUP_SERVICES=$(echo "$SETUP_SERVICES" | tr ',' '\n' | tac)
 
     for service in $SETUP_SERVICES; do
-        chroot "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" stop || true
+        "$LIBEXEC_DIR"/schroot-impersonate -- $(which chroot) "$CHROOT_PATH" \
+            /usr/sbin/invoke-rc.d --force "$service" stop || true
     done
 fi
 
diff --git a/sbuild/sbuild-chroot-facet-personality.cc b/sbuild/sbuild-chroot-facet-personality.cc
index ef9ad10..20af301 100644
--- a/sbuild/sbuild-chroot-facet-personality.cc
+++ b/sbuild/sbuild-chroot-facet-personality.cc
@@ -72,6 +72,8 @@ void
 chroot_facet_personality::setup_env (chroot const& chroot,
                                      environment&  env) const
 {
+  if (get_persona().get_name() != "undefined")
+    env.add("CHROOT_PERSONALITY", get_persona().get_name());
 }
 
 sbuild::chroot::session_flags
-- 
1.9.1

From 9ba8b8573f13157dffb371391f1440bc78e5037c Mon Sep 17 00:00:00 2001
From: Jan-Marek Glogowski <jan-marek.glogow...@muenchen.de>
Date: Thu, 5 Feb 2015 12:00:40 +0100
Subject: [PATCH 1/2] Add personality impersonator

A little binary to run a program with the same personality then the
chroot. This is currently used to run the chroot services with the
correct personality.
---
 CMakeLists.txt                          |   1 +
 etc/setup.d/70services                  |   6 +-
 lib/schroot/chroot/facet/personality.cc |   6 ++
 lib/schroot/chroot/facet/personality.h  |   3 +
 libexec/impersonate/CMakeLists.txt      |  30 +++++++
 libexec/impersonate/impersonate.cc      |  45 ++++++++++
 libexec/impersonate/main.cc             | 140 ++++++++++++++++++++++++++++++++
 libexec/impersonate/main.h              |  93 +++++++++++++++++++++
 libexec/impersonate/options.cc          | 113 ++++++++++++++++++++++++++
 libexec/impersonate/options.h           |  78 ++++++++++++++++++
 libexec/mount/options.cc                |  10 +--
 11 files changed, 518 insertions(+), 7 deletions(-)
 create mode 100644 libexec/impersonate/CMakeLists.txt
 create mode 100644 libexec/impersonate/impersonate.cc
 create mode 100644 libexec/impersonate/main.cc
 create mode 100644 libexec/impersonate/main.h
 create mode 100644 libexec/impersonate/options.cc
 create mode 100644 libexec/impersonate/options.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd9c5da..babf44c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -317,6 +317,7 @@ add_subdirectory(lib/test)
 add_subdirectory(bin/schroot)
 add_subdirectory(bin/dchroot)
 add_subdirectory(bin/dchroot-dsa)
+add_subdirectory(libexec/impersonate)
 add_subdirectory(libexec/listmounts)
 add_subdirectory(libexec/mount)
 add_subdirectory(test)
diff --git a/etc/setup.d/70services b/etc/setup.d/70services
index aff3c10..eddb98a 100755
--- a/etc/setup.d/70services
+++ b/etc/setup.d/70services
@@ -38,7 +38,8 @@ if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then
     SETUP_SERVICES=$(echo "$SETUP_SERVICES" | tr ',' '\n')
 
     for service in $SETUP_SERVICES; do
-        chroot "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" start
+        "$LIBEXEC_DIR"/impersonate -- $(which chroot) \
+            "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" start
     done
 
 elif [ $STAGE = "setup-stop" ]; then
@@ -48,7 +49,8 @@ elif [ $STAGE = "setup-stop" ]; then
     SETUP_SERVICES=$(echo "$SETUP_SERVICES" | tr ',' '\n' | tac)
 
     for service in $SETUP_SERVICES; do
-        chroot "$CHROOT_PATH" /usr/sbin/invoke-rc.d --force "$service" stop || true
+        "$LIBEXEC_DIR"/impersonate -- $(which chroot) "$CHROOT_PATH" \
+            /usr/sbin/invoke-rc.d --force "$service" stop || true
     done
 fi
 
diff --git a/lib/schroot/chroot/facet/personality.cc b/lib/schroot/chroot/facet/personality.cc
index 044df6d..d6f0da7 100644
--- a/lib/schroot/chroot/facet/personality.cc
+++ b/lib/schroot/chroot/facet/personality.cc
@@ -119,6 +119,12 @@ namespace schroot
                                   keyfile::PRIORITY_OPTIONAL);
       }
 
+      void
+      personality::setup_env (environment& env) const
+      {
+        if (get_persona().get_name() != "undefined")
+          env.add("CHROOT_PERSONALITY", get_persona().get_name());
+      }
     }
   }
 }
diff --git a/lib/schroot/chroot/facet/personality.h b/lib/schroot/chroot/facet/personality.h
index 82bcf52..23de596 100644
--- a/lib/schroot/chroot/facet/personality.h
+++ b/lib/schroot/chroot/facet/personality.h
@@ -91,6 +91,9 @@ namespace schroot
         virtual void
         set_keyfile (const keyfile& keyfile);
 
+        virtual void
+        setup_env (environment& env) const;
+
       private:
         /// Process execution domain (Linux only).
         schroot::personality  persona;
diff --git a/libexec/impersonate/CMakeLists.txt b/libexec/impersonate/CMakeLists.txt
new file mode 100644
index 0000000..ef7ba6e
--- /dev/null
+++ b/libexec/impersonate/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+#
+# schroot is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# schroot is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+#####################################################################
+
+set(impersonate_sources
+    main.h
+    main.cc
+    options.h
+    options.cc
+    impersonate.cc)
+
+add_executable(impersonate ${impersonate_sources})
+target_link_libraries(impersonate libschroot bin-common)
+
+install(TARGETS impersonate RUNTIME
+        DESTINATION ${SCHROOT_LIBEXEC_DIR})
diff --git a/libexec/impersonate/impersonate.cc b/libexec/impersonate/impersonate.cc
new file mode 100644
index 0000000..fd1b206
--- /dev/null
+++ b/libexec/impersonate/impersonate.cc
@@ -0,0 +1,45 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include <libexec/impersonate/options.h>
+#include <libexec/impersonate/main.h>
+
+#include <bin-common/run.h>
+
+using std::endl;
+using boost::format;
+namespace opt = boost::program_options;
+
+/**
+ * Main routine.
+ *
+ * @param argc the number of arguments
+ * @param argv argument vector
+ *
+ * @returns 0 on success, 1 on failure or the exit status of the
+ * chroot command.
+ */
+int
+main (int   argc,
+      char *argv[])
+{
+  return bin::common::run
+    <bin::schroot_impersonate::options, bin::schroot_impersonate::main>(argc, argv);
+}
diff --git a/libexec/impersonate/main.cc b/libexec/impersonate/main.cc
new file mode 100644
index 0000000..7418e19
--- /dev/null
+++ b/libexec/impersonate/main.cc
@@ -0,0 +1,140 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "main.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <locale>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <boost/format.hpp>
+
+#include <schroot/personality.h>
+#include <schroot/util.h>
+
+using std::endl;
+using boost::format;
+using schroot::_;
+using schroot::N_;
+
+namespace schroot
+{
+
+    template<>
+    error<bin::schroot_impersonate::main::error_code>::map_type
+    error<bin::schroot_impersonate::main::error_code>::error_strings =
+      {
+        // TRANSLATORS: %1% = command name
+        {bin::schroot_impersonate::main::EXEC,    N_("Failed to execute “%1%”")}
+      };
+
+}
+
+namespace bin
+{
+  namespace schroot_impersonate
+  {
+
+    main::main (options::ptr& options):
+      bin::common::main("schroot-impersonate",
+                        // TRANSLATORS: '...' is an ellipsis e.g. U+2026,
+                        // and '-' is an em-dash.
+                        _("[OPTION…] [COMMAND] — run command with persona"),
+                        options,
+                        false),
+      opts(options)
+    {
+    }
+
+    main::~main ()
+    {
+    }
+
+    void
+    main::action_impersonate ()
+    {
+#ifdef SCHROOT_FEATURE_PERSONALITY
+
+      /* Set the process execution domain. */
+      if (!opts->persona.empty())
+        {
+          schroot::personality execPersonality( opts->persona );
+          execPersonality.set();
+          schroot::log_debug(schroot::DEBUG_NOTICE)
+             << "Set personality=" << opts->persona << std::endl;
+        }
+
+#endif // SCHROOT_FEATURE_PERSONALITY
+
+      schroot::string_list command;
+      schroot::environment env(environ);
+
+      std::copy(opts->command.begin(), opts->command.end(),
+                std::back_inserter(command));
+
+      try
+        {
+          schroot::log_debug(schroot::DEBUG_INFO)
+            << "impersonate_main: executing "
+            << schroot::string_list_to_string(command, ", ")
+            << std::endl;
+          exec(command[0], command, env);
+          error e(command[0], EXEC, strerror(errno));
+          schroot::log_exception_error(e);
+        }
+      catch (const std::exception& e)
+        {
+          schroot::log_exception_error(e);
+        }
+      catch (...)
+        {
+          schroot::log_error()
+            << _("An unknown exception occurred") << std::endl;
+        }
+
+      // This should never be reached.
+      exit(EXIT_FAILURE);
+    }
+
+    int
+    main::run_impl ()
+    {
+      if (this->opts->action == options::ACTION_HELP)
+        action_help(std::cerr);
+      else if (this->opts->action == options::ACTION_VERSION)
+        action_version(std::cerr);
+      else if (this->opts->action == options::ACTION_IMPERSONATE)
+        action_impersonate();
+      else
+        assert(0); // Invalid action.
+
+      return EXIT_SUCCESS;
+    }
+
+  }
+}
diff --git a/libexec/impersonate/main.h b/libexec/impersonate/main.h
new file mode 100644
index 0000000..4bea482
--- /dev/null
+++ b/libexec/impersonate/main.h
@@ -0,0 +1,93 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef LIBEXEC_IMPERSONATE_MAIN_H
+#define LIBEXEC_IMPERSONATE_MAIN_H
+
+#include <bin-common/main.h>
+
+#include <libexec/impersonate/options.h>
+
+#include <schroot/custom-error.h>
+#include <schroot/environment.h>
+
+namespace bin
+{
+  /**
+   * schroot-mount program components
+   */
+  namespace schroot_impersonate
+  {
+
+    /**
+     * Frontend for schroot-impersonate.  This class is used to "run" schroot-impersonate.
+     */
+    class main : public bin::common::main
+    {
+    public:
+      /// Error codes.
+      enum error_code
+        {
+          EXEC     ///< Failed to execute command.
+        };
+
+      /// Exception type.
+      typedef schroot::custom_error<error_code> error;
+
+      /**
+       * The constructor.
+       *
+       * @param options the command-line options to use.
+       */
+      main (options::ptr& options);
+
+      /// The destructor.
+      virtual ~main ();
+
+    private:
+      /**
+       * Run command with personality.
+       */
+      virtual void
+      action_impersonate ();
+
+    protected:
+      /**
+       * Run the program.
+       *
+       * @returns 0 on success, 1 on failure or the exit status of the
+       * chroot command.
+       */
+      virtual int
+      run_impl ();
+
+    private:
+      /// The program options.
+      options::ptr opts;
+    };
+
+  }
+}
+
+#endif /* LIBEXEC_IMPERSONATE_MAIN_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/libexec/impersonate/options.cc b/libexec/impersonate/options.cc
new file mode 100644
index 0000000..0839222
--- /dev/null
+++ b/libexec/impersonate/options.cc
@@ -0,0 +1,113 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include <schroot/i18n.h>
+
+#include <libexec/impersonate/options.h>
+
+#include <cstdlib>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+
+using std::endl;
+using boost::format;
+using schroot::_;
+namespace opt = boost::program_options;
+
+namespace bin
+{
+  namespace schroot_impersonate
+  {
+
+    const options::action_type options::ACTION_IMPERSONATE ("impersonate");
+
+    options::options ():
+      bin::common::options(),
+      persona(),
+      command(),
+      persona_opts(_("Persona"))
+    {
+    }
+
+    options::~options ()
+    {
+    }
+
+    void
+    options::add_options ()
+    {
+      // Chain up to add basic options.
+      bin::common::options::add_options();
+
+      action.add(ACTION_IMPERSONATE);
+      action.set_default(ACTION_IMPERSONATE);
+
+      persona_opts.add_options()
+        ("persona,p", opt::value<std::string>(&this->persona),
+         _("Persona to use"));
+
+      hidden.add_options()
+        ("command", opt::value<schroot::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 (!persona_opts.options().empty())
+#else
+      if (!persona_opts.primary_keys().empty())
+#endif
+        {
+          visible.add(persona_opts);
+          global.add(persona_opts);
+        }
+    }
+
+    void
+    options::check_options ()
+    {
+      // Chain up to check basic options.
+      bin::common::options::check_options();
+
+      if (this->action == ACTION_IMPERSONATE)
+        {
+          if (this->command.begin() == this->command.end())
+            throw error(_("No command specified"));
+
+          if (!vm.count("persona"))
+            {
+              const char *env_persona = getenv("CHROOT_PERSONALITY");
+              if (env_persona)
+                this->persona = env_persona;
+            }
+        }
+    }
+
+  }
+}
diff --git a/libexec/impersonate/options.h b/libexec/impersonate/options.h
new file mode 100644
index 0000000..e4c3db9
--- /dev/null
+++ b/libexec/impersonate/options.h
@@ -0,0 +1,78 @@
+/* Copyright © 2015  Jan-Marek Glogowski <glo...@fbihome.de>
+ *
+ * schroot is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef LIBEXEC_IMPERSONATE_OPTIONS_H
+#define LIBEXEC_IMPERSONATE_OPTIONS_H
+
+#include <bin-common/options.h>
+
+#include <string>
+
+namespace bin
+{
+  namespace schroot_impersonate
+  {
+
+    /**
+     * schroot-impersonate command-line options.
+     */
+    class options : public bin::common::options
+    {
+    public:
+      /// A shared_ptr to an options object.
+      typedef std::shared_ptr<options> ptr;
+
+      /// Begin, run and end a session.
+      static const action_type ACTION_IMPERSONATE;
+
+      /// The constructor.
+      options ();
+
+      /// The destructor.
+      virtual ~options ();
+
+      /// The persona to use.
+      std::string persona;
+
+      /// Command to run.
+      schroot::string_list command;
+
+    protected:
+      virtual void
+      add_options ();
+
+      virtual void
+      add_option_groups ();
+
+      virtual void
+      check_options ();
+
+      /// Mount options group.
+      boost::program_options::options_description persona_opts;
+    };
+
+  }
+}
+
+#endif /* LIBEXEC_IMPERSONATE_OPTIONS_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/libexec/mount/options.cc b/libexec/mount/options.cc
index 9045c6f..a33a977 100644
--- a/libexec/mount/options.cc
+++ b/libexec/mount/options.cc
@@ -82,12 +82,12 @@ namespace bin
 #ifndef BOOST_PROGRAM_OPTIONS_DESCRIPTION_OLD
       if (!mount.options().empty())
 #else
-        if (!mount.primary_keys().empty())
+      if (!mount.primary_keys().empty())
 #endif
-          {
-            visible.add(mount);
-            global.add(mount);
-          }
+        {
+          visible.add(mount);
+          global.add(mount);
+        }
     }
 
     void
-- 
1.9.1

Reply via email to