The behaviour mimics chroot.
Possibly it would have been nicer to to query the password database in
the new namepace and run the shell of the user there, but it's hard to
do correctly. getpwuid() might need to load nss plugins, and the arch
in the new namespace might be different (in case of NEWNS mounts), or
the hostname might be different, etc. So in general it's not possible
to do it reliably.
Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
--- /dev/null
+extern void __attribute__((__noreturn__)) exec_shell(void);
lib/tt.c \
lib/wholedisk.c \
lib/ttyutils.c \
- lib/xgetpass.c
+ lib/xgetpass.c \
+ lib/exec_shell.c
if LINUX
libcommon_la_SOURCES += \
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "nls.h"
+#include "c.h"
+#include "xalloc.h"
+
+#include "exec_shell.h"
+
+#define DEFAULT_SHELL "/bin/sh"
+
+void __attribute__((__noreturn__)) exec_shell(void) {
+ const char *shell = getenv("SHELL"), *shell_basename;
+ char *arg0;
+ if (!shell)
+ shell = DEFAULT_SHELL;
+
+ shell_basename = basename(shell);
+ arg0 = xmalloc(strlen(shell_basename) + 2);
+ arg0[0] = '-';
+ strcpy(arg0 + 1, shell_basename);
+
+ execl(shell, arg0, NULL);
+ err(EXIT_FAILURE, _("failed to execute %s"), shell);
+}
usrbin_exec_PROGRAMS += unshare
dist_man_MANS += sys-utils/unshare.1
unshare_SOURCES = sys-utils/unshare.c
+unshare_LDADD = $(LDADD) libcommon.la
endif
if BUILD_NSENTER
.SH SYNOPSIS
.B nsenter
.RI [ options ]
-program
+.RI [ program ]
.RI [ arguments ]
.SH DESCRIPTION
Enters the contexts of one or more other processes and then executes specified
See the
.BR clone (2)
for exact semantics of the flags.
+.TP
+If program is not given, run ``${SHELL}'' (default: /bin\:/sh).
+
.SH OPTIONS
Argument with square brakets, such as [\fIfile\fR], means optional argument.
Command line syntax to specify optional argument \-\-mount=/path\:/to\:/file.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <sys/types.h>
-#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <unistd.h>
#include <assert.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "strutils.h"
#include "nls.h"
#include "c.h"
#include "closestream.h"
#include "namespace.h"
+#include "exec_shell.h"
static struct namespace_file {
int nstype;
}
}
- if (optind >= argc)
- usage(EXIT_FAILURE);
-
/*
* Open remaining namespace and directory descriptors.
*/
if (do_fork == 1)
continue_as_child();
- execvp(argv[optind], argv + optind);
-
- err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
+ if (optind < argc) {
+ execvp(argv[optind], argv + optind);
+ err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
+ }
+ exec_shell();
}
#include "c.h"
#include "closestream.h"
#include "namespace.h"
+#include "exec_shell.h"
static void usage(int status)
{
}
}
- if(optind >= argc)
- usage(EXIT_FAILURE);
-
if(-1 == unshare(unshare_flags))
err(EXIT_FAILURE, _("unshare failed"));
- execvp(argv[optind], argv + optind);
-
- err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
+ if (optind < argc) {
+ execvp(argv[optind], argv + optind);
+ err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
+ }
+ exec_shell();
}