-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathinvoke_ns1.c
More file actions
126 lines (103 loc) · 3.23 KB
/
invoke_ns1.c
File metadata and controls
126 lines (103 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define _GNU_SOURCE
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
#include <string.h>
// Define size of space for stack used by child process
#define STACK_SIZE (64 * 1024)
struct arguments {
int verbose;
char **command;
};
// Function to print command usage
static void usage(char *prog)
{
fprintf(stderr, "\nUsage: %s [options] [cmd [arg...]]\n", prog);
fprintf(stderr, "Options can be:\n");
fprintf(stderr, " -h display this help message\n");
fprintf(stderr, " -v display verbose messages\n");
fprintf(stderr, " -p new PID namespace\n");
}
// Function passed to the clone system call
int childFunction(void *child_args)
{
struct arguments *args = child_args;
if (args->verbose)
printf(" Child: PID of child is %d\n", getpid());
// Execute command if given
if (args->command != NULL) {
if (clearenv() != 0)
fprintf(stderr, " Child: childFunction: couldn't clear environment\n");
if (args->verbose)
printf(" Child: executing command %s ...\n", args->command[0]);
execvp(args->command[0], &args->command[0]);
}
else
exit(EXIT_SUCCESS);
perror(" Child: childFunction: execvp");
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
char *child_stack;
int i;
int option;
int flags = 0;
pid_t child;
struct arguments args;
args.verbose = 0;
args.command = NULL;
// Parse command line options and construct arguments
// to be passed to childFunction
while ((option = getopt(argc, argv, "+hvp")) != -1) {
switch (option) {
case 'p':
flags |= CLONE_NEWPID;
break;
case 'v':
args.verbose = 1;
break;
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
default:
usage(argv[0]);
exit(EXIT_FAILURE);
}
}
// Assemble command to be executed in namespace
if(optind != argc) {
args.command = malloc(sizeof(char *) * (argc - optind + 1));
for (i = optind; i < argc; i++) {
args.command[i - optind] = malloc(strlen(argv[i]) + 1);
strcpy(args.command[i - optind], argv[i]);
}
args.command[argc - optind] = NULL;
}
if (args.verbose)
printf("Parent: PID of parent is %d\n", getpid());
// Allocate heap for child's stack
child_stack = malloc(STACK_SIZE);
if (child_stack == NULL) {
perror("Parent: main: malloc");
exit(EXIT_FAILURE);
}
// Clone child process
child = clone(childFunction, child_stack + STACK_SIZE, flags | SIGCHLD, &args);
if (child == -1) {
perror("Parent: main: clone");
exit(EXIT_FAILURE);
}
if (args.verbose)
printf("Parent: PID of child is %d\n", child);
// Wait for child to finish
if (waitpid(child, NULL, 0) == -1) {
perror("Parent: main: waitpid");
exit(EXIT_FAILURE);
}
if (args.verbose)
printf("Parent: %s - Finishing up\n", argv[0]);
exit(EXIT_SUCCESS);
}