#include <stdio.h>
#include <stdlib.h>
+#include <sys/wait.h>
#include "error.h"
+#include "log.h"
+
+lxc_log_define(lxc_error, lxc);
static const char *const catalogue[] = {
return catalogue[error];
}
+
+/*---------------------------------------------------------------------------*/
+/* lxc_error_set_and_log
+ * function is here to convert
+ * the reported status to an exit code as detailed here:
+ *
+ * 0-126 exit code of the application
+ * 128+n signal n received by the application
+ * 255 lxc error
+ */
+extern int lxc_error_set_and_log(int pid, int status)
+{
+ int ret = 0;
+
+ if (WIFEXITED(status)) {
+ ret = WEXITSTATUS(status);
+ if (ret)
+ INFO("child <%d> ended on error (%d)", pid, ret);
+ }
+
+ if (WIFSIGNALED(status)) {
+ int signal = WTERMSIG(status);
+ ret = ret + 128 + signal;
+
+ INFO("child <%d> ended on signal (%d)", pid, signal);
+ }
+
+ return ret;
+}
int main(int argc, char *argv[])
{
char *const *args;
- int err;
+ int err = -1;
struct termios tios;
char *const default_args[] = {
'\0',
};
- err = lxc_arguments_parse(&my_args, argc, argv);
- if (err)
- return 1;
+ if (lxc_arguments_parse(&my_args, argc, argv))
+ return err;
if (!my_args.argc)
args = default_args;
if (lxc_log_init(my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
- return 1;
+ return err;
if (tcgetattr(0, &tios)) {
ERROR("failed to get current terminal settings : %s",
strerror(errno));
- return 1;
+ return err;
}
err = lxc_start(my_args.name, args);
- if (err) {
- ERROR("failed to start '%s'", my_args.name);
- err = 1;
- }
if (tcsetattr(0, TCSAFLUSH, &tios))
ERROR("failed to restore terminal settings : %s",
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("failed to set sigprocmask");
- return -1;
+ goto out_child;
}
close(sv[1]);
}
/* Setup the container, ip, names, utsname, ... */
- err = lxc_setup(name, handler->tty, &handler->tty_info);
- if (err) {
+ if (lxc_setup(name, handler->tty, &handler->tty_info)) {
ERROR("failed to setup the container");
- if (write(sv[0], &err, sizeof(err)) < 0)
- SYSERROR("failed to write the socket");
- goto out_child;
+ goto out_warn_father;
}
if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
execvp(argv[0], argv);
SYSERROR("failed to exec %s", argv[0]);
- err = LXC_ERROR_WRONG_COMMAND;
+ out_warn_father:
/* If the exec fails, tell that to our father */
if (write(sv[0], &err, sizeof(err)) < 0)
SYSERROR("failed to write the socket");
-
out_child:
exit(err);
}
}
/* Wait for the child to exec or returning an error */
- err = read(sv[1], &sync, sizeof(sync));
- if (err < 0) {
+ if (read(sv[1], &sync, sizeof(sync)) < 0) {
ERROR("failed to read the socket");
goto out_abort;
}
int lxc_start(const char *name, char *const argv[])
{
struct lxc_handler handler = { 0 };
- int err = -LXC_ERROR_INTERNAL;
+ int err = -1;
int status;
if (lxc_init(name, &handler)) {
goto out;
}
- if (lxc_poll(name, &handler)) {
+ err = lxc_poll(name, &handler);
+ if (err) {
ERROR("mainloop exited with an error");
goto out_abort;
}
while (waitpid(handler.pid, &status, 0) < 0 && errno == EINTR)
continue;
- err = 0;
+
+ err = lxc_error_set_and_log(handler.pid, status);
out:
lxc_fini(name, &handler);
return err;