Annotation of embedaddon/strongswan/src/pki/command.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2009 Martin Willi
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "command.h"
17: #include "pki.h"
18:
19: #define _GNU_SOURCE
20: #include <getopt.h>
21: #include <stdlib.h>
22: #include <string.h>
23: #include <stdio.h>
24:
25: #include <library.h>
26: #include <utils/debug.h>
27: #include <utils/optionsfrom.h>
28:
29: /**
30: * Registered commands.
31: */
32: static command_t cmds[MAX_COMMANDS];
33:
34: /**
35: * active command.
36: */
37: static int active = 0;
38:
39: /**
40: * number of registered commands
41: */
42: static int registered = 0;
43:
44: /**
45: * help command index
46: */
47: static int help_idx;
48:
49: static int argc;
50:
51: static char **argv;
52:
53: static options_t *options;
54:
55: /**
56: * Global options used by all subcommands
57: */
58: static struct option command_opts[MAX_COMMANDS > MAX_OPTIONS ? MAX_COMMANDS : MAX_OPTIONS];
59:
60: /**
61: * Global optstring used by all subcommands
62: */
63: static char command_optstring[(MAX_COMMANDS > MAX_OPTIONS ? MAX_COMMANDS : MAX_OPTIONS) * 3];
64:
65: /**
66: * Build command_opts/command_optstr for the active command
67: */
68: static void build_opts()
69: {
70: int i, pos = 0;
71:
72: memset(command_opts, 0, sizeof(command_opts));
73: memset(command_optstring, 0, sizeof(command_optstring));
74: if (active == help_idx)
75: {
76: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
77: {
78: command_opts[i].name = cmds[i].cmd;
79: command_opts[i].val = cmds[i].op;
80: command_optstring[i] = cmds[i].op;
81: }
82: }
83: else
84: {
85: for (i = 0; cmds[active].options[i].name; i++)
86: {
87: command_opts[i].name = cmds[active].options[i].name;
88: command_opts[i].has_arg = cmds[active].options[i].arg;
89: command_opts[i].val = cmds[active].options[i].op;
90: command_optstring[pos++] = cmds[active].options[i].op;
91: switch (cmds[active].options[i].arg)
92: {
93: case optional_argument:
94: command_optstring[pos++] = ':';
95: /* FALL */
96: case required_argument:
97: command_optstring[pos++] = ':';
98: /* FALL */
99: case no_argument:
100: default:
101: break;
102: }
103: }
104: }
105: }
106:
107: /**
108: * getopt_long wrapper
109: */
110: int command_getopt(char **arg)
111: {
112: int op;
113:
114: while (TRUE)
115: {
116: op = getopt_long(argc, argv, command_optstring, command_opts, NULL);
117: switch (op)
118: {
119: case '+':
120: if (!options->from(options, optarg, &argc, &argv, optind))
121: {
122: /* a error value */
123: return 255;
124: }
125: continue;
126: case 'v':
127: dbg_default_set_level(atoi(optarg));
128: continue;
129: default:
130: *arg = optarg;
131: return op;
132: }
133: }
134: }
135:
136: /**
137: * Register a command
138: */
139: void command_register(command_t command)
140: {
141: int i;
142:
143: if (registered == MAX_COMMANDS)
144: {
145: fprintf(stderr, "unable to register command, please increase "
146: "MAX_COMMANDS\n");
147: return;
148: }
149:
150: cmds[registered] = command;
151: /* append default options, but not to --help */
152: if (!active)
153: {
154: for (i = 0; i < countof(cmds[registered].options) - 1; i++)
155: {
156: if (!cmds[registered].options[i].name)
157: {
158: break;
159: }
160: }
161: if (i > countof(cmds[registered].options) - 3)
162: {
163: fprintf(stderr, "command '%s' registered too many options, please "
164: "increase MAX_OPTIONS\n", command.cmd);
165: }
166: else
167: {
168: cmds[registered].options[i++] = (command_option_t) {
169: "debug", 'v', 1, "set debug level, default: 1"
170: };
171: cmds[registered].options[i++] = (command_option_t) {
172: "options", '+', 1, "read command line options from file"
173: };
174: }
175: for (i = 0; cmds[registered].line[i]; i++)
176: {
177: if (i == MAX_LINES - 1)
178: {
179: fprintf(stderr, "command '%s' specifies too many usage summary "
180: "lines, please increase MAX_LINES\n", command.cmd);
181: break;
182: }
183: }
184: }
185: registered++;
186: }
187:
188: /**
189: * Print usage text, with an optional error
190: */
191: int command_usage(char *error)
192: {
193: FILE *out = stdout;
194: int i, indent = 0;
195:
196: if (error)
197: {
198: out = stderr;
199: fprintf(out, "Error: %s\n", error);
200: }
201: fprintf(out, "strongSwan %s PKI tool\n", VERSION);
202:
203: if (active == help_idx)
204: {
205: fprintf(out, "loaded plugins: %s\n",
206: lib->plugins->loaded_plugins(lib->plugins));
207: }
208:
209: fprintf(out, "usage:\n");
210: if (active == help_idx)
211: {
212: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
213: {
214: fprintf(out, " pki --%-7s (-%c) %s\n",
215: cmds[i].cmd, cmds[i].op, cmds[i].description);
216: }
217: }
218: else
219: {
220: for (i = 0; i < MAX_LINES && cmds[active].line[i]; i++)
221: {
222: if (i == 0)
223: {
224: indent = fprintf(out, " pki --%s ", cmds[active].cmd);
225: fprintf(out, "%s\n", cmds[active].line[i]);
226: }
227: else
228: {
229: fprintf(out, "%*s%s\n", indent, "", cmds[active].line[i]);
230: }
231: }
232: for (i = 0; cmds[active].options[i].name; i++)
233: {
234: fprintf(out, " --%-15s (-%c) %s\n",
235: cmds[active].options[i].name, cmds[active].options[i].op,
236: cmds[active].options[i].desc);
237: }
238: }
239: return error != NULL;
240: }
241:
242:
243: /**
244: * Show usage information
245: */
246: static int help(int c, char *v[])
247: {
248: return command_usage(NULL);
249: }
250:
251: /**
252: * Dispatch cleanup hook
253: */
254: static void cleanup()
255: {
256: options->destroy(options);
257: }
258:
259: /**
260: * Dispatch commands.
261: */
262: int command_dispatch(int c, char *v[])
263: {
264: int op, i;
265:
266: options = options_create();
267: atexit(cleanup);
268: active = help_idx = registered;
269: argc = c;
270: argv = v;
271: command_register((command_t){help, 'h', "help", "show usage information"});
272:
273: build_opts();
274: op = getopt_long(c, v, command_optstring, command_opts, NULL);
275: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
276: {
277: if (cmds[i].op == op)
278: {
279: active = i;
280: build_opts();
281: return cmds[i].call();
282: }
283: }
284: return command_usage(c > 1 ? "invalid operation" : NULL);
285: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>