]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/arguments.c
ovl_rsync: make sure to umount
[mirror_lxc.git] / src / lxc / arguments.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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"
35 #include "utils.h"
36 #include "version.h"
37
38 /*---------------------------------------------------------------------------*/
39 static int build_shortopts(const struct option *a_options,
40 char *a_shortopts, size_t a_size)
41 {
42 const struct option *opt;
43 int i = 0;
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 /*---------------------------------------------------------------------------*/
88 static 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
101 if (!uppername)
102 exit(-ENOMEM);
103
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
132 static void print_version() {
133 printf("%s\n", LXC_VERSION);
134 exit(0);
135 }
136
137 static void print_help(const struct lxc_arguments *args, int code)
138 {
139 fprintf(stderr, "\
140 Usage: %s %s\
141 \n\
142 Common 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\
146 -P, --lxcpath=PATH Use specified container path\n\
147 -?, --help Give this help list\n\
148 --usage Give a short usage message\n\
149 --version Print the version number\n\
150 \n\
151 Mandatory or optional arguments to long options are also mandatory or optional\n\
152 for any corresponding short options.\n\
153 \n\
154 See the %s man page for further information.\n\n",
155 args->progname, args->help, args->progname);
156
157 if (args->helpfn)
158 args->helpfn(args);
159 exit(code);
160 }
161
162 static 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");
176 return -ENOMEM;
177 }
178 args->lxcpath[args->lxcpath_cnt++] = lxcpath;
179 return 0;
180 }
181
182 extern 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;
206 case 'P':
207 remove_trailing_slashes(optarg);
208 ret = lxc_arguments_lxcpath_add(args, optarg);
209 if (ret < 0)
210 return ret;
211 break;
212 case OPT_USAGE: print_usage(args->options, args);
213 case OPT_VERSION: print_version();
214 case '?': print_help(args, 1);
215 case 'h': print_help(args, 0);
216 default:
217 if (args->parser) {
218 ret = args->parser(args, c, optarg);
219 if (ret)
220 goto error;
221 }
222 }
223 }
224
225 /*
226 * Reclaim the remaining command arguments
227 */
228 args->argv = &argv[optind];
229 args->argc = argc - optind;
230
231 /* If no lxcpaths were given, use default */
232 if (!args->lxcpath_cnt) {
233 ret = lxc_arguments_lxcpath_add(args, lxc_global_config_value("lxc.lxcpath"));
234 if (ret < 0)
235 return ret;
236 }
237
238 /* Check the command options */
239
240 if (!args->name && strcmp(args->progname, "lxc-autostart") != 0) {
241 lxc_error(args, "missing container name, use --name option");
242 return -1;
243 }
244
245 if (args->checker)
246 ret = args->checker(args);
247 error:
248 if (ret)
249 lxc_error(args, "could not parse command line");
250 return ret;
251 }
252
253 int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str)
254 {
255 long val;
256 char *endptr;
257
258 errno = 0;
259 val = strtol(str, &endptr, 10);
260 if (errno) {
261 lxc_error(args, "invalid statefd '%s' : %m", str);
262 return -1;
263 }
264
265 if (*endptr) {
266 lxc_error(args, "invalid digit for statefd '%s'", str);
267 return -1;
268 }
269
270 return (int)val;
271 }