source: trunk/debathena/third/schroot/bin/schroot/schroot-main-base.cc @ 24167

Revision 24167, 9.1 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2005-2007  Roger Leigh <rleigh@debian.org>
2 *
3 * schroot is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * schroot is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#include <config.h>
20
21#include "schroot-main-base.h"
22
23#include <sbuild/sbuild-config.h>
24#ifdef SBUILD_FEATURE_PAM
25#include <sbuild/sbuild-auth-pam-conv.h>
26#include <sbuild/sbuild-auth-pam-conv-tty.h>
27#endif // SBUILD_FEATURE_PAM
28
29#include <cstdlib>
30#include <ctime>
31#include <iostream>
32#include <locale>
33
34#include <termios.h>
35#include <unistd.h>
36
37#include <boost/format.hpp>
38
39using std::endl;
40using boost::format;
41using sbuild::_;
42using sbuild::N_;
43using namespace schroot;
44
45namespace
46{
47
48  typedef std::pair<main_base::error_code,const char *> emap;
49
50  /**
51   * This is a list of the supported error codes.  It's used to
52   * construct the real error codes map.
53   */
54  emap init_errors[] =
55    {
56      // TRANSLATORS: %1% = comma-separated list of chroot names
57      emap(main_base::CHROOTS_NOTFOUND,  N_("%1%: Chroots not found")),
58      // TRANSLATORS: %4% = file
59      emap(main_base::CHROOT_FILE,       N_("No chroots are defined in '%4%'")),
60      // TRANSLATORS: %4% = file
61      // TRANSLATORS: %5% = file
62      emap(main_base::CHROOT_FILE2,      N_("No chroots are defined in '%4%' or '%5%'")),
63      // TRANSLATORS: %1% = file
64      emap(main_base::CHROOT_NOTDEFINED, N_("The specified chroots are not defined in '%1%'")),
65      // TRANSLATORS: %1% = chroot name
66      emap(main_base::CHROOT_NOTFOUND,   N_("%1%: Chroot not found"))
67    };
68
69}
70
71/// Error code to description mapping.
72template<>
73sbuild::error<main_base::error_code>::map_type
74sbuild::error<main_base::error_code>::error_strings
75(init_errors,
76 init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
77
78main_base::main_base (std::string const& program_name,
79                      std::string const& program_usage,
80                      options_base::ptr& options,
81                      bool               use_syslog):
82  schroot_base::main(program_name, program_usage,
83                     std::tr1::static_pointer_cast<schroot_base::options>(options),
84                     use_syslog),
85  options(options)
86{
87}
88
89main_base::~main_base ()
90{
91}
92
93void
94main_base::action_version (std::ostream& stream)
95{
96  schroot_base::main::action_version(stream);
97
98  format feature("  %1$-12s %2%\n");
99
100  stream << '\n'
101         << _("Available chroot types:") << '\n';
102#ifdef SBUILD_FEATURE_BLOCKDEV
103  stream << feature % "BLOCKDEV" % _("Support for 'block-device' chroots");
104#endif
105  stream << feature % "DIRECTORY" % _("Support for 'directory' chroots");
106  stream << feature % "FILE" % _("Support for 'file' chroots");
107#ifdef SBUILD_FEATURE_LOOPBACK
108  stream << feature % "LOOPBACK" % _("Support for 'loopback' chroots");
109#endif
110#ifdef SBUILD_FEATURE_LVMSNAP
111  stream << feature % "LVMSNAP" % _("Support for 'lvm-snapshot' chroots");
112#endif
113  stream << feature % "PLAIN" % _("Support for 'plain' chroots");
114  stream << std::flush;
115}
116
117void
118main_base::action_info ()
119{
120  this->config->print_chroot_info(this->chroots, std::cout);
121}
122
123void
124main_base::action_location ()
125{
126  this->config->print_chroot_location(this->chroots, std::cout);
127}
128
129void
130main_base::compat_check ()
131{
132}
133
134sbuild::string_list
135main_base::get_chroot_options ()
136{
137  sbuild::string_list ret;
138
139  if (this->options->all_chroots == true ||
140      this->options->all_sessions == true)
141    {
142      sbuild::chroot_config::chroot_list const& list =
143        this->config->get_chroots();
144
145      for (sbuild::chroot_config::chroot_list::const_iterator chroot =
146             list.begin();
147           chroot != list.end();
148           ++chroot)
149        {
150          if (((*chroot)->get_active() == false &&
151               this->options->all_chroots == false) ||
152              ((*chroot)->get_active() == true &&
153               this->options->all_sessions == false))
154            continue;
155          ret.push_back((*chroot)->get_name());
156        }
157    }
158  else
159    {
160      sbuild::string_list invalid_chroots =
161        this->config->validate_chroots(this->options->chroots);
162
163      if (!invalid_chroots.empty())
164        {
165          std::string invalid_list;
166          for (sbuild::string_list::const_iterator chroot =
167                 invalid_chroots.begin();
168               chroot != invalid_chroots.end();
169               ++chroot)
170            {
171              invalid_list += *chroot;
172              if (chroot + 1 != invalid_chroots.end())
173                invalid_list += ", ";
174            }
175          throw error(invalid_list,
176                      (invalid_chroots.size() == 1)
177                      ? CHROOT_NOTFOUND : CHROOTS_NOTFOUND);
178        }
179      ret = this->options->chroots;
180    }
181
182  return ret;
183}
184
185void
186main_base::load_config ()
187{
188  this->config = sbuild::chroot_config::ptr(new sbuild::chroot_config);
189  /* The normal chroot list is used when starting a session or running
190     any chroot type or session, or displaying chroot information. */
191  if (this->options->load_chroots == true)
192    {
193      this->config->add(SCHROOT_CONF, false);
194      this->config->add(SCHROOT_CONF_CHROOT_D, false);
195    }
196  /* The session chroot list is used when running or ending an
197     existing session, or displaying chroot information. */
198  if (this->options->load_sessions == true)
199    this->config->add(SCHROOT_SESSION_DIR, true);
200}
201
202int
203main_base::run_impl ()
204{
205  compat_check();
206
207  if (this->options->action == options_base::ACTION_HELP)
208    {
209      action_help(std::cout);
210      return EXIT_SUCCESS;
211    }
212
213  if (this->options->action == options_base::ACTION_VERSION)
214    {
215      action_version(std::cout);
216      return EXIT_SUCCESS;
217    }
218
219  /* Initialise chroot configuration. */
220  load_config();
221
222  if (this->config->get_chroots().empty() && this->options->quiet == false)
223    {
224      if (this->options->load_chroots == true &&
225          this->options->load_sessions == true)
226        log_exception_warning
227          (error(CHROOT_FILE2, SCHROOT_CONF, SCHROOT_SESSION_DIR));
228      else
229        {
230          const char *cfile = (this->options->load_sessions)
231            ? SCHROOT_SESSION_DIR : SCHROOT_CONF;
232          log_exception_warning(error(CHROOT_FILE, cfile));
233        }
234    }
235
236  /* Print chroot list (including aliases). */
237  if (this->options->action == options_base::ACTION_LIST)
238    {
239      action_list();
240      return EXIT_SUCCESS;
241    }
242
243  /* Get list of chroots to use */
244  chroots = get_chroot_options();
245  if (this->chroots.empty())
246    {
247      if (!(this->options->all_chroots == true ||
248            this->options->all_sessions == true))
249        throw error(SCHROOT_CONF, CHROOT_NOTDEFINED);
250      else
251        {
252          // If one of the --all options was used, then don't treat
253          // the lack of chroots as an error.  TODO: Also check if any
254          // additional chroots were specified with -c; this needs
255          // changes in get_chroot_options.
256          log_exception_warning(error((this->options->all_chroots == true) ?
257                                      SCHROOT_CONF : SCHROOT_SESSION_DIR,
258                                      CHROOT_NOTDEFINED));
259          return EXIT_SUCCESS;
260        }
261    }
262
263  /* Print chroot information for specified chroots. */
264  if (this->options->action == options_base::ACTION_INFO)
265    {
266      action_info();
267      return EXIT_SUCCESS;
268    }
269  if (this->options->action == options_base::ACTION_LOCATION)
270    {
271      action_location();
272      return EXIT_SUCCESS;
273    }
274  if (this->options->action == options_base::ACTION_CONFIG)
275    {
276      action_config();
277      return EXIT_SUCCESS;
278    }
279
280  /* Create a session. */
281  sbuild::session::operation sess_op(sbuild::session::OPERATION_AUTOMATIC);
282  if (this->options->action == options_base::ACTION_SESSION_BEGIN)
283    sess_op = sbuild::session::OPERATION_BEGIN;
284  else if (this->options->action == options_base::ACTION_SESSION_RECOVER)
285    sess_op = sbuild::session::OPERATION_RECOVER;
286  else if (this->options->action == options_base::ACTION_SESSION_RUN)
287    sess_op = sbuild::session::OPERATION_RUN;
288  else if (this->options->action == options_base::ACTION_SESSION_END)
289    sess_op = sbuild::session::OPERATION_END;
290
291  try
292    {
293      create_session(sess_op);
294
295      if (!this->options->command.empty())
296        this->session->get_auth()->set_command(this->options->command);
297      if (!this->options->directory.empty())
298        this->session->get_auth()->set_wd(this->options->directory);
299      if (this->options->preserve)
300        this->session->get_auth()->set_environment(environ);
301      this->session->set_session_id(this->options->session_name);
302      this->session->set_force(this->options->session_force);
303      sbuild::auth::verbosity verbosity = sbuild::auth::VERBOSITY_NORMAL;
304      if (this->options->quiet)
305        verbosity = sbuild::auth::VERBOSITY_QUIET;
306      else if (this->options->verbose)
307        verbosity = sbuild::auth::VERBOSITY_VERBOSE;
308      this->session->get_auth()->set_verbosity(verbosity);
309
310      /* Run session. */
311      this->session->run();
312    }
313  catch (std::runtime_error const& e)
314    {
315      if (!this->options->quiet)
316        sbuild::log_exception_error(e);
317    }
318
319  if (this->session)
320    return this->session->get_child_status();
321  else
322    return EXIT_FAILURE;
323}
Note: See TracBrowser for help on using the repository browser.