initial commit
This commit is contained in:
commit
a4395189ad
5 changed files with 608 additions and 0 deletions
97
ns_child_exec.c
Normal file
97
ns_child_exec.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* ns_child_exec.c
|
||||
|
||||
Copyright 2013, Michael Kerrisk
|
||||
Licensed under GNU General Public License v2 or later
|
||||
|
||||
Create a child process that executes a shell command in new namespace(s).
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* A simple error-handling function: print an error message based
|
||||
on the value in 'errno' and terminate the calling process */
|
||||
|
||||
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
usage(char *pname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options] cmd [arg...]\n", pname);
|
||||
fprintf(stderr, "Options can be:\n");
|
||||
fprintf(stderr, " -i new IPC namespace\n");
|
||||
fprintf(stderr, " -m new mount namespace\n");
|
||||
fprintf(stderr, " -n new network namespace\n");
|
||||
fprintf(stderr, " -p new PID namespace\n");
|
||||
fprintf(stderr, " -u new UTS namespace\n");
|
||||
fprintf(stderr, " -U new user namespace\n");
|
||||
fprintf(stderr, " -v Display verbose messages\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int /* Start function for cloned child */
|
||||
childFunc(void *arg)
|
||||
{
|
||||
char **argv = arg;
|
||||
|
||||
execvp(argv[0], &argv[0]);
|
||||
errExit("execvp");
|
||||
}
|
||||
|
||||
#define STACK_SIZE (1024 * 1024)
|
||||
|
||||
static char child_stack[STACK_SIZE]; /* Space for child's stack */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int flags, opt, verbose;
|
||||
pid_t child_pid;
|
||||
|
||||
flags = 0;
|
||||
verbose = 0;
|
||||
|
||||
/* Parse command-line options. The initial '+' character in
|
||||
the final getopt() argument prevents GNU-style permutation
|
||||
of command-line options. That's useful, since sometimes
|
||||
the 'command' to be executed by this program itself
|
||||
has command-line options. We don't want getopt() to treat
|
||||
those as options to this program. */
|
||||
|
||||
while ((opt = getopt(argc, argv, "+imnpuUv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i': flags |= CLONE_NEWIPC; break;
|
||||
case 'm': flags |= CLONE_NEWNS; break;
|
||||
case 'n': flags |= CLONE_NEWNET; break;
|
||||
case 'p': flags |= CLONE_NEWPID; break;
|
||||
case 'u': flags |= CLONE_NEWUTS; break;
|
||||
case 'U': flags |= CLONE_NEWUSER; break;
|
||||
case 'v': verbose = 1; break;
|
||||
default: usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
child_pid = clone(childFunc,
|
||||
child_stack + STACK_SIZE,
|
||||
flags | SIGCHLD, &argv[optind]);
|
||||
if (child_pid == -1)
|
||||
errExit("clone");
|
||||
|
||||
if (verbose)
|
||||
printf("%s: PID of child created by clone() is %ld\n",
|
||||
argv[0], (long) child_pid);
|
||||
|
||||
/* Parent falls through to here */
|
||||
|
||||
if (waitpid(child_pid, NULL, 0) == -1) /* Wait for child */
|
||||
errExit("waitpid");
|
||||
|
||||
if (verbose)
|
||||
printf("%s: terminating\n", argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue