]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/tools/arguments.c
tree-wide: fix lxc header inclusion
[mirror_lxc.git] / src / lxc / tools / arguments.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
ea0eb48b 2
b53f80d4
CB
3#include "config.h"
4
ea0eb48b
CB
5#include <ctype.h>
6#include <errno.h>
7#include <limits.h>
cda02a28
MN
8#include <stdio.h>
9#include <stdlib.h>
cda02a28 10#include <string.h>
cda02a28
MN
11#include <sys/stat.h>
12#include <sys/types.h>
d38dd64a 13#include <unistd.h>
cda02a28 14
12ae2a33 15#include "lxc.h"
791e7a73 16
cda02a28 17#include "arguments.h"
ac2cecc4 18#include "initutils.h"
d38dd64a 19#include "namespace.h"
cda02a28 20
ea0eb48b
CB
21static int build_shortopts(const struct option *a_options, char *a_shortopts,
22 size_t a_size)
cda02a28 23{
84760c11 24 size_t i = 0;
ea0eb48b 25 const struct option *opt;
cda02a28
MN
26
27 if (!a_options || !a_shortopts || !a_size)
28 return -1;
29
30 for (opt = a_options; opt->name; opt++) {
cda02a28
MN
31 if (!isascii(opt->val))
32 continue;
33
34 if (i < a_size)
35 a_shortopts[i++] = opt->val;
36 else
37 goto is2big;
38
39 if (opt->has_arg == no_argument)
40 continue;
41
42 if (i < a_size)
43 a_shortopts[i++] = ':';
44 else
45 goto is2big;
46
47 if (opt->has_arg == required_argument)
48 continue;
49
50 if (i < a_size)
51 a_shortopts[i++] = ':';
52 else
53 goto is2big;
54 }
55
56 if (i < a_size)
57 a_shortopts[i] = '\0';
58 else
59 goto is2big;
60
61 return 0;
62
ea0eb48b 63is2big:
cda02a28
MN
64 errno = E2BIG;
65 return -1;
66}
67
181a780f 68__noreturn static void print_usage_exit(const struct option longopts[],
cf0fd972 69 const struct lxc_arguments *a_args)
cda02a28
MN
70
71{
72 int i;
73 const struct option *opt;
74
75 fprintf(stderr, "Usage: %s ", a_args->progname);
76
77 for (opt = longopts, i = 1; opt->name; opt++, i++) {
cda02a28
MN
78 fprintf(stderr, "[");
79
80 if (isprint(opt->val))
81 fprintf(stderr, "-%c|", opt->val);
82
83 fprintf(stderr, "--%s", opt->name);
84
97d7e88f
DJ
85 if ((opt->has_arg == required_argument) ||
86 (opt->has_arg == optional_argument)) {
87 int j;
88 char *uppername;
cda02a28 89
97d7e88f
DJ
90 uppername = strdup(opt->name);
91 if (!uppername)
92 exit(-ENOMEM);
93
94 for (j = 0; uppername[j]; j++)
95 uppername[j] = toupper(uppername[j]);
96
97 if (opt->has_arg == required_argument)
98 fprintf(stderr, "=%s", uppername);
99 else // optional_argument
100 fprintf(stderr, "[=%s]", uppername);
101
102 free(uppername);
103 }
cda02a28
MN
104
105 fprintf(stderr, "] ");
106
107 if (!(i % 4))
108 fprintf(stderr, "\n\t");
cda02a28
MN
109 }
110
111 fprintf(stderr, "\n");
57017714 112 exit(EXIT_SUCCESS);
cda02a28
MN
113}
114
39b72573 115__noreturn static void print_version_exit(void)
ea0eb48b 116{
5f98011c 117 printf("%s\n", lxc_get_version());
57017714 118 exit(EXIT_SUCCESS);
7f12cae9
SG
119}
120
181a780f 121__noreturn static void print_help_exit(const struct lxc_arguments *args,
cf0fd972 122 int code)
cda02a28
MN
123{
124 fprintf(stderr, "\
125Usage: %s %s\
126\n\
127Common options :\n\
128 -o, --logfile=FILE Output log to FILE instead of stderr\n\
129 -l, --logpriority=LEVEL Set log priority to LEVEL\n\
130 -q, --quiet Don't produce any output\n\
67e571de 131 -P, --lxcpath=PATH Use specified container path\n\
cda02a28
MN
132 -?, --help Give this help list\n\
133 --usage Give a short usage message\n\
7f12cae9 134 --version Print the version number\n\
cda02a28
MN
135\n\
136Mandatory or optional arguments to long options are also mandatory or optional\n\
137for any corresponding short options.\n\
138\n\
139See the %s man page for further information.\n\n",
140 args->progname, args->help, args->progname);
141
f002c8a7
SH
142 if (args->helpfn)
143 args->helpfn(args);
727b9b16 144
cda02a28
MN
145 exit(code);
146}
147
8d06bd13
DE
148static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
149 const char *lxcpath)
150{
151 if (args->lxcpath_additional != -1 &&
152 args->lxcpath_cnt > args->lxcpath_additional) {
ea0eb48b
CB
153 fprintf(stderr,
154 "This command only accepts %d -P,--lxcpath arguments\n",
8d06bd13
DE
155 args->lxcpath_additional + 1);
156 exit(EXIT_FAILURE);
157 }
158
ea0eb48b
CB
159 args->lxcpath = realloc(
160 args->lxcpath, (args->lxcpath_cnt + 1) * sizeof(args->lxcpath[0]));
8d06bd13
DE
161 if (args->lxcpath == NULL) {
162 lxc_error(args, "no memory");
63c3090c 163 return -ENOMEM;
8d06bd13 164 }
727b9b16 165
8d06bd13
DE
166 args->lxcpath[args->lxcpath_cnt++] = lxcpath;
167 return 0;
168}
169
ea0eb48b
CB
170extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
171 char *const argv[])
cda02a28 172{
ea0eb48b 173 int ret = 0;
03c6d266 174 bool logfile = false;
cda02a28 175 char shortopts[256];
cda02a28
MN
176
177 ret = build_shortopts(args->options, shortopts, sizeof(shortopts));
178 if (ret < 0) {
179 lxc_error(args, "build_shortopts() failed : %s",
180 strerror(errno));
181 return ret;
182 }
183
51a8a74c 184 for (;;) {
ea0eb48b
CB
185 int c;
186 int index = 0;
cda02a28
MN
187
188 c = getopt_long(argc, argv, shortopts, args->options, &index);
189 if (c == -1)
190 break;
727b9b16 191
cda02a28 192 switch (c) {
ea0eb48b
CB
193 case 'n':
194 args->name = optarg;
195 break;
196 case 'o':
197 args->log_file = optarg;
03c6d266 198 logfile = true;
ea0eb48b
CB
199 break;
200 case 'l':
201 args->log_priority = optarg;
03c6d266 202 if (!logfile &&
203 args->log_file &&
204 strcmp(args->log_file, "none") == 0)
205 args->log_file = NULL;
ea0eb48b
CB
206 break;
207 case 'q':
208 args->quiet = 1;
209 break;
210 case OPT_RCFILE:
211 args->rcfile = optarg;
212 break;
8d06bd13 213 case 'P':
e555005b 214 remove_trailing_slashes(optarg);
8d06bd13
DE
215 ret = lxc_arguments_lxcpath_add(args, optarg);
216 if (ret < 0)
217 return ret;
218 break;
ea0eb48b 219 case OPT_USAGE:
1a836092 220 print_usage_exit(args->options, args);
ea0eb48b 221 case OPT_VERSION:
1a836092 222 print_version_exit();
ea0eb48b 223 case '?':
1a836092 224 print_help_exit(args, 1);
ea0eb48b 225 case 'h':
1a836092 226 print_help_exit(args, 0);
cda02a28
MN
227 default:
228 if (args->parser) {
229 ret = args->parser(args, c, optarg);
230 if (ret)
231 goto error;
232 }
233 }
234 }
235
236 /*
237 * Reclaim the remaining command arguments
238 */
239 args->argv = &argv[optind];
240 args->argc = argc - optind;
241
8d06bd13
DE
242 /* If no lxcpaths were given, use default */
243 if (!args->lxcpath_cnt) {
ea0eb48b 244 ret = lxc_arguments_lxcpath_add(
9267beba 245 args, lxc_get_global_config_item("lxc.lxcpath"));
8d06bd13
DE
246 if (ret < 0)
247 return ret;
248 }
249
cda02a28 250 /* Check the command options */
727b9b16 251 if (!args->name && strncmp(args->progname, "lxc-autostart", strlen(args->progname)) != 0
252 && strncmp(args->progname, "lxc-unshare", strlen(args->progname)) != 0) {
817a0e46
CB
253 if (args->argv) {
254 args->name = argv[optind];
255 optind++;
256 args->argv = &argv[optind];
257 args->argc = argc - optind;
258 }
259
260 if (!args->name) {
261 lxc_error(args, "No container name specified");
262 return -1;
263 }
cda02a28
MN
264 }
265
266 if (args->checker)
267 ret = args->checker(args);
727b9b16 268
cda02a28
MN
269error:
270 if (ret)
271 lxc_error(args, "could not parse command line");
727b9b16 272
cda02a28
MN
273 return ret;
274}
fa7eddbb 275
501cbc71
MN
276int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str)
277{
278 long val;
279 char *endptr;
280
281 errno = 0;
282 val = strtol(str, &endptr, 10);
283 if (errno) {
13277ec4 284 lxc_error(args, "invalid statefd '%s' : %s", str,
285 strerror(errno));
501cbc71
MN
286 return -1;
287 }
288
289 if (*endptr) {
290 lxc_error(args, "invalid digit for statefd '%s'", str);
291 return -1;
292 }
293
294 return (int)val;
295}
4be48327
TA
296
297bool lxc_setup_shared_ns(struct lxc_arguments *args, struct lxc_container *c)
298{
299 int i;
300
301 for (i = 0; i < LXC_NS_MAX; i++) {
302 const char *key, *value;
303
304 value = args->share_ns[i];
305 if (!value)
306 continue;
307
308 if (i == LXC_NS_NET)
b074bbf1 309 key = "lxc.namespace.share.net";
4be48327 310 else if (i == LXC_NS_IPC)
b074bbf1 311 key = "lxc.namespace.share.ipc";
4be48327 312 else if (i == LXC_NS_UTS)
b074bbf1 313 key = "lxc.namespace.share.uts";
4be48327 314 else if (i == LXC_NS_PID)
b074bbf1 315 key = "lxc.namespace.share.pid";
4be48327
TA
316 else
317 continue;
318
319 if (!c->set_config_item(c, key, value)) {
c379af4c 320 lxc_error(args, "Failed to set \"%s = %s\"", key, value);
4be48327
TA
321 return false;
322 }
323 }
324
325 return true;
35bfea7a 326}