]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/arguments.c
commands: add lxc_cmd_state_server()
[mirror_lxc.git] / src / lxc / 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
MN
23 */
24#include <stdio.h>
25#include <stdlib.h>
26#include <limits.h>
27#include <string.h>
28#include <ctype.h> /* for isprint() */
29#include <errno.h>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <unistd.h>
33
34#include "arguments.h"
67e571de 35#include "utils.h"
7f12cae9 36#include "version.h"
cda02a28
MN
37
38/*---------------------------------------------------------------------------*/
39static int build_shortopts(const struct option *a_options,
40 char *a_shortopts, size_t a_size)
41{
42 const struct option *opt;
84760c11 43 size_t i = 0;
cda02a28
MN
44
45 if (!a_options || !a_shortopts || !a_size)
46 return -1;
47
48 for (opt = a_options; opt->name; opt++) {
49
50 if (!isascii(opt->val))
51 continue;
52
53 if (i < a_size)
54 a_shortopts[i++] = opt->val;
55 else
56 goto is2big;
57
58 if (opt->has_arg == no_argument)
59 continue;
60
61 if (i < a_size)
62 a_shortopts[i++] = ':';
63 else
64 goto is2big;
65
66 if (opt->has_arg == required_argument)
67 continue;
68
69 if (i < a_size)
70 a_shortopts[i++] = ':';
71 else
72 goto is2big;
73 }
74
75 if (i < a_size)
76 a_shortopts[i] = '\0';
77 else
78 goto is2big;
79
80 return 0;
81
82 is2big:
83 errno = E2BIG;
84 return -1;
85}
86
87/*---------------------------------------------------------------------------*/
88static void print_usage(const struct option longopts[],
89 const struct lxc_arguments *a_args)
90
91{
92 int i;
93 const struct option *opt;
94
95 fprintf(stderr, "Usage: %s ", a_args->progname);
96
97 for (opt = longopts, i = 1; opt->name; opt++, i++) {
98 int j;
99 char *uppername = strdup(opt->name);
100
6d10f1fc
MS
101 if (!uppername)
102 exit(-ENOMEM);
103
cda02a28
MN
104 for (j = 0; uppername[j]; j++)
105 uppername[j] = toupper(uppername[j]);
106
107 fprintf(stderr, "[");
108
109 if (isprint(opt->val))
110 fprintf(stderr, "-%c|", opt->val);
111
112 fprintf(stderr, "--%s", opt->name);
113
114 if (opt->has_arg == required_argument)
115 fprintf(stderr, "=%s", uppername);
116
117 if (opt->has_arg == optional_argument)
118 fprintf(stderr, "[=%s]", uppername);
119
120 fprintf(stderr, "] ");
121
122 if (!(i % 4))
123 fprintf(stderr, "\n\t");
124
125 free(uppername);
126 }
127
128 fprintf(stderr, "\n");
129 exit(0);
130}
131
7f12cae9
SG
132static void print_version() {
133 printf("%s\n", LXC_VERSION);
134 exit(0);
135}
136
cda02a28
MN
137static void print_help(const struct lxc_arguments *args, int code)
138{
139 fprintf(stderr, "\
140Usage: %s %s\
141\n\
142Common options :\n\
143 -o, --logfile=FILE Output log to FILE instead of stderr\n\
144 -l, --logpriority=LEVEL Set log priority to LEVEL\n\
145 -q, --quiet Don't produce any output\n\
67e571de 146 -P, --lxcpath=PATH Use specified container path\n\
cda02a28
MN
147 -?, --help Give this help list\n\
148 --usage Give a short usage message\n\
7f12cae9 149 --version Print the version number\n\
cda02a28
MN
150\n\
151Mandatory or optional arguments to long options are also mandatory or optional\n\
152for any corresponding short options.\n\
153\n\
154See the %s man page for further information.\n\n",
155 args->progname, args->help, args->progname);
156
f002c8a7
SH
157 if (args->helpfn)
158 args->helpfn(args);
cda02a28
MN
159 exit(code);
160}
161
8d06bd13
DE
162static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
163 const char *lxcpath)
164{
165 if (args->lxcpath_additional != -1 &&
166 args->lxcpath_cnt > args->lxcpath_additional) {
167 fprintf(stderr, "This command only accepts %d -P,--lxcpath arguments\n",
168 args->lxcpath_additional + 1);
169 exit(EXIT_FAILURE);
170 }
171
172 args->lxcpath = realloc(args->lxcpath, (args->lxcpath_cnt + 1) *
173 sizeof(args->lxcpath[0]));
174 if (args->lxcpath == NULL) {
175 lxc_error(args, "no memory");
63c3090c 176 return -ENOMEM;
8d06bd13
DE
177 }
178 args->lxcpath[args->lxcpath_cnt++] = lxcpath;
179 return 0;
180}
181
cda02a28
MN
182extern int lxc_arguments_parse(struct lxc_arguments *args,
183 int argc, char * const argv[])
184{
185 char shortopts[256];
186 int ret = 0;
187
188 ret = build_shortopts(args->options, shortopts, sizeof(shortopts));
189 if (ret < 0) {
190 lxc_error(args, "build_shortopts() failed : %s",
191 strerror(errno));
192 return ret;
193 }
194
195 while (1) {
196 int c, index = 0;
197
198 c = getopt_long(argc, argv, shortopts, args->options, &index);
199 if (c == -1)
200 break;
201 switch (c) {
202 case 'n': args->name = optarg; break;
203 case 'o': args->log_file = optarg; break;
204 case 'l': args->log_priority = optarg; break;
205 case 'q': args->quiet = 1; break;
50b737a3 206 case OPT_RCFILE: args->rcfile = optarg; break;
8d06bd13 207 case 'P':
e555005b 208 remove_trailing_slashes(optarg);
8d06bd13
DE
209 ret = lxc_arguments_lxcpath_add(args, optarg);
210 if (ret < 0)
211 return ret;
212 break;
cda02a28 213 case OPT_USAGE: print_usage(args->options, args);
7f12cae9 214 case OPT_VERSION: print_version();
cda02a28
MN
215 case '?': print_help(args, 1);
216 case 'h': print_help(args, 0);
217 default:
218 if (args->parser) {
219 ret = args->parser(args, c, optarg);
220 if (ret)
221 goto error;
222 }
223 }
224 }
225
226 /*
227 * Reclaim the remaining command arguments
228 */
229 args->argv = &argv[optind];
230 args->argc = argc - optind;
231
8d06bd13
DE
232 /* If no lxcpaths were given, use default */
233 if (!args->lxcpath_cnt) {
593e8478 234 ret = lxc_arguments_lxcpath_add(args, lxc_global_config_value("lxc.lxcpath"));
8d06bd13
DE
235 if (ret < 0)
236 return ret;
237 }
238
cda02a28
MN
239 /* Check the command options */
240
a6adab20 241 if (!args->name && strcmp(args->progname, "lxc-autostart") != 0) {
cda02a28
MN
242 lxc_error(args, "missing container name, use --name option");
243 return -1;
244 }
245
246 if (args->checker)
247 ret = args->checker(args);
248error:
249 if (ret)
250 lxc_error(args, "could not parse command line");
251 return ret;
252}
fa7eddbb 253
501cbc71
MN
254int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str)
255{
256 long val;
257 char *endptr;
258
259 errno = 0;
260 val = strtol(str, &endptr, 10);
261 if (errno) {
262 lxc_error(args, "invalid statefd '%s' : %m", str);
263 return -1;
264 }
265
266 if (*endptr) {
267 lxc_error(args, "invalid digit for statefd '%s'", str);
268 return -1;
269 }
270
271 return (int)val;
272}