Skip to content

Commit df6fbfa

Browse files
mtjhrcslp
authored andcommitted
examples/chrootvm: Add proper argument parsing using getopt_long
Signed-off-by: Matej Hrica <[email protected]>
1 parent b2e550b commit df6fbfa

File tree

1 file changed

+85
-8
lines changed

1 file changed

+85
-8
lines changed

examples/chroot_vm.c

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,85 @@
1111
#include <string.h>
1212
#include <unistd.h>
1313
#include <libkrun.h>
14+
#include <getopt.h>
15+
#include <stdbool.h>
16+
#include <assert.h>
1417

1518
#define MAX_ARGS_LEN 4096
1619
#ifndef MAX_PATH
1720
#define MAX_PATH 4096
1821
#endif
1922

23+
static void print_help(char *const name)
24+
{
25+
fprintf(stderr,
26+
"Usage: %s [OPTIONS] NEWROOT COMMAND [COMMAND_ARGS...]\n"
27+
"OPTIONS: \n"
28+
" -h --help Show help\n"
29+
"\n"
30+
"NEWROOT: the root directory of the vm\n"
31+
"COMMAND: the command you want to execute in the vm\n"
32+
"COMMAND_ARGS: arguments of COMMAND\n",
33+
name
34+
);
35+
}
36+
37+
static const struct option long_options[] = {
38+
{ "help", no_argument, NULL, 'h' },
39+
{ NULL, 0, NULL, 0 }
40+
};
41+
42+
struct cmdline {
43+
bool show_help;
44+
char const *new_root;
45+
char *const *guest_argv;
46+
};
47+
48+
bool parse_cmdline(int argc, char *const argv[], struct cmdline *cmdline)
49+
{
50+
assert(cmdline != NULL);
51+
52+
// set the defaults
53+
*cmdline = (struct cmdline){
54+
.show_help = false,
55+
.new_root = NULL,
56+
.guest_argv = NULL,
57+
};
58+
59+
int option_index = 0;
60+
int c;
61+
// the '+' in optstring is a GNU extension that disables permutating argv
62+
while ((c = getopt_long(argc, argv, "+h", long_options, &option_index)) != -1) {
63+
switch (c) {
64+
case 'h':
65+
cmdline->show_help = true;
66+
return true;
67+
case '?':
68+
return false;
69+
default:
70+
fprintf(stderr, "internal argument parsing error (returned character code 0x%x)\n", c);
71+
return false;
72+
}
73+
}
74+
75+
if (optind <= argc - 2) {
76+
cmdline->new_root = argv[optind];
77+
cmdline->guest_argv = &argv[optind + 1];
78+
return true;
79+
}
80+
81+
if (optind >= argc - 1) {
82+
fprintf(stderr, "Missing COMMAND argument\n");
83+
}
84+
85+
if (optind == argc) {
86+
fprintf(stderr, "Missing NEWROOT argument\n");
87+
}
88+
89+
return false;
90+
}
91+
92+
2093
int main(int argc, char *const argv[])
2194
{
2295
char *const envp[] =
@@ -43,13 +116,19 @@ int main(int argc, char *const argv[])
43116
int ctx_id;
44117
int err;
45118
int i;
119+
struct cmdline cmdline;
46120

47-
if (argc < 3) {
48-
printf("Invalid arguments\n");
49-
printf("Usage: %s NEWROOT COMMAND [ARG...]\n", argv[0]);
121+
if (!parse_cmdline(argc, argv, &cmdline)) {
122+
putchar('\n');
123+
print_help(argv[0]);
50124
return -1;
51125
}
52126

127+
if (cmdline.show_help){
128+
print_help(argv[0]);
129+
return 0;
130+
}
131+
53132
// Set the log level to "off".
54133
err = krun_set_log_level(0);
55134
if (err) {
@@ -73,8 +152,7 @@ int main(int argc, char *const argv[])
73152
return -1;
74153
}
75154

76-
// Use the first command line argument as the path to be used as root.
77-
if (err = krun_set_root(ctx_id, argv[1])) {
155+
if (err = krun_set_root(ctx_id, cmdline.new_root)) {
78156
errno = -err;
79157
perror("Error configuring root path");
80158
return -1;
@@ -125,9 +203,8 @@ int main(int argc, char *const argv[])
125203
return -1;
126204
}
127205

128-
// Use the second argument as the path of the binary to be executed in the isolated
129-
// context, relative to the root path.
130-
if (err = krun_set_exec(ctx_id, argv[2], &argv[3], &envp[0])) {
206+
// Specify the path of the binary to be executed in the isolated context, relative to the root path.
207+
if (err = krun_set_exec(ctx_id, cmdline.guest_argv[0], &cmdline.guest_argv[1], &envp[0])) {
131208
errno = -err;
132209
perror("Error configuring the parameters for the executable to be run");
133210
return -1;

0 commit comments

Comments
 (0)