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