lxc_log_define(lxc_attach, lxc);
+static int my_parser(struct lxc_arguments *args, int c, char *arg);
+static int add_to_simple_array(char ***array, ssize_t *capacity, char *value);
+static bool stdfd_is_pty(void);
+static int lxc_attach_create_log_file(const char *log_file);
+
+static int elevated_privileges;
+static signed long new_personality = -1;
+static int namespace_flags = -1;
+static int remount_sys_proc;
+static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
+static char **extra_env;
+static ssize_t extra_env_size;
+static char **extra_keep;
+static ssize_t extra_keep_size;
+
static const struct option my_longopts[] = {
{"elevated-privileges", optional_argument, 0, 'e'},
{"arch", required_argument, 0, 'a'},
LXC_COMMON_OPTIONS
};
-static int elevated_privileges = 0;
-static signed long new_personality = -1;
-static int namespace_flags = -1;
-static int remount_sys_proc = 0;
-static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
-static char **extra_env = NULL;
-static ssize_t extra_env_size = 0;
-static char **extra_keep = NULL;
-static ssize_t extra_keep_size = 0;
-
-static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
-{
- ssize_t count = 0;
-
- if (!array)
- return -1;
-
- if (*array)
- for (; (*array)[count]; count++);
-
- /* we have to reallocate */
- if (count >= *capacity - 1) {
- ssize_t new_capacity = ((count + 1) / 32 + 1) * 32;
- char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity);
- if (!new_array)
- return -1;
- memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count));
- *array = new_array;
- *capacity = new_capacity;
- }
-
- if (!(*array))
- return -1;
-
- (*array)[count] = value;
- return 0;
-}
+static struct lxc_arguments my_args = {
+ .progname = "lxc-attach",
+ .help = "\
+--name=NAME [-- COMMAND]\n\
+\n\
+Execute the specified COMMAND - enter the container NAME\n\
+\n\
+Options :\n\
+ -n, --name=NAME NAME of the container\n\
+ -e, --elevated-privileges=PRIVILEGES\n\
+ Use elevated privileges instead of those of the\n\
+ container. If you don't specify privileges to be\n\
+ elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\
+ cgroup and restrictions, respectively) then all of them\n\
+ will be elevated.\n\
+ WARNING: This may leak privileges into the container.\n\
+ Use with care.\n\
+ -a, --arch=ARCH Use ARCH for program instead of container's own\n\
+ architecture.\n\
+ -s, --namespaces=FLAGS\n\
+ Don't attach to all the namespaces of the container\n\
+ but just to the following OR'd list of flags:\n\
+ MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\
+ WARNING: Using -s implies -e with all privileges\n\
+ elevated, it may therefore leak privileges into the\n\
+ container. Use with care.\n\
+ -R, --remount-sys-proc\n\
+ Remount /sys and /proc if not attaching to the\n\
+ mount namespace when using -s in order to properly\n\
+ reflect the correct namespace context. See the\n\
+ lxc-attach(1) manual page for details.\n\
+ --clear-env Clear all environment variables before attaching.\n\
+ The attached shell/program will start with only\n\
+ container=lxc set.\n\
+ --keep-env Keep all current environment variables. This\n\
+ is the current default behaviour, but is likely to\n\
+ change in the future.\n\
+ -L, --pty-log=FILE\n\
+ Log pty output to FILE\n\
+ -v, --set-var Set an additional variable that is seen by the\n\
+ attached program in the container. May be specified\n\
+ multiple times.\n\
+ --keep-var Keep an additional environment variable. Only\n\
+ applicable if --clear-env is specified. May be used\n\
+ multiple times.\n\
+ -f, --rcfile=FILE\n\
+ Load configuration file FILE\n\
+",
+ .options = my_longopts,
+ .parser = my_parser,
+ .checker = NULL,
+ .log_priority = "ERROR",
+ .log_file = "none",
+};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
return 0;
}
-static struct lxc_arguments my_args = {
- .progname = "lxc-attach",
- .help = "\
---name=NAME [-- COMMAND]\n\
-\n\
-Execute the specified COMMAND - enter the container NAME\n\
-\n\
-Options :\n\
- -n, --name=NAME NAME of the container\n\
- -e, --elevated-privileges=PRIVILEGES\n\
- Use elevated privileges instead of those of the\n\
- container. If you don't specify privileges to be\n\
- elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\
- cgroup and restrictions, respectively) then all of them\n\
- will be elevated.\n\
- WARNING: This may leak privileges into the container.\n\
- Use with care.\n\
- -a, --arch=ARCH Use ARCH for program instead of container's own\n\
- architecture.\n\
- -s, --namespaces=FLAGS\n\
- Don't attach to all the namespaces of the container\n\
- but just to the following OR'd list of flags:\n\
- MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\
- WARNING: Using -s implies -e with all privileges\n\
- elevated, it may therefore leak privileges into the\n\
- container. Use with care.\n\
- -R, --remount-sys-proc\n\
- Remount /sys and /proc if not attaching to the\n\
- mount namespace when using -s in order to properly\n\
- reflect the correct namespace context. See the\n\
- lxc-attach(1) manual page for details.\n\
- --clear-env Clear all environment variables before attaching.\n\
- The attached shell/program will start with only\n\
- container=lxc set.\n\
- --keep-env Keep all current environment variables. This\n\
- is the current default behaviour, but is likely to\n\
- change in the future.\n\
- -L, --pty-log=FILE\n\
- Log pty output to FILE\n\
- -v, --set-var Set an additional variable that is seen by the\n\
- attached program in the container. May be specified\n\
- multiple times.\n\
- --keep-var Keep an additional environment variable. Only\n\
- applicable if --clear-env is specified. May be used\n\
- multiple times.\n\
- -f, --rcfile=FILE\n\
- Load configuration file FILE\n\
-",
- .options = my_longopts,
- .parser = my_parser,
- .checker = NULL,
-};
+static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
+{
+ ssize_t count = 0;
+
+ if (!array)
+ return -1;
+
+ if (*array)
+ for (; (*array)[count]; count++);
+
+ /* we have to reallocate */
+ if (count >= *capacity - 1) {
+ ssize_t new_capacity = ((count + 1) / 32 + 1) * 32;
+
+ char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity);
+ if (!new_array)
+ return -1;
+
+ memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count));
+
+ *array = new_array;
+ *capacity = new_capacity;
+ }
+
+ if (!(*array))
+ return -1;
+
+ (*array)[count] = value;
+ return 0;
+}
static bool stdfd_is_pty(void)
{
if (isatty(STDIN_FILENO))
return true;
+
if (isatty(STDOUT_FILENO))
return true;
+
if (isatty(STDERR_FILENO))
return true;
int main(int argc, char *argv[])
{
- int ret = -1, r;
+ int ret = -1;
int wexit = 0;
struct lxc_log log;
pid_t pid;
lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL};
- r = lxc_caps_init();
- if (r)
+ if (lxc_caps_init())
exit(EXIT_FAILURE);
- r = lxc_arguments_parse(&my_args, argc, argv);
- if (r)
+ if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
- /* Only create log if explicitly instructed */
- if (my_args.log_file || my_args.log_priority) {
- log.name = my_args.name;
- log.file = my_args.log_file;
- log.level = my_args.log_priority;
- log.prefix = my_args.progname;
- log.quiet = my_args.quiet;
- log.lxcpath = my_args.lxcpath[0];
+ log.name = my_args.name;
+ log.file = my_args.log_file;
+ log.level = my_args.log_priority;
+ log.prefix = my_args.progname;
+ log.quiet = my_args.quiet;
+ log.lxcpath = my_args.lxcpath[0];
- if (lxc_log_init(&log))
- exit(EXIT_FAILURE);
- }
+ if (lxc_log_init(&log))
+ exit(EXIT_FAILURE);
- if (geteuid()) {
+ if (geteuid())
if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
ERROR("You lack access to %s", my_args.lxcpath[0]);
exit(EXIT_FAILURE);
}
- }
struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c)