pki tool supports single letter short options
[strongswan.git] / src / pki / command.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * 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
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
22
23 /**
24 * Registered commands.
25 */
26 command_t cmds[MAX_COMMANDS];
27
28 /**
29 * active command.
30 */
31 static int active = 0;
32
33 /**
34 * number of registered commands
35 */
36 static int registered = 0;
37
38 /**
39 * help command index
40 */
41 static int help_idx;
42
43 /**
44 * Global options used by all subcommands
45 */
46 struct option command_opts[MAX_COMMANDS > MAX_OPTIONS ?: MAX_OPTIONS];
47
48 /**
49 * Global optstring used by all subcommands
50 */
51 char command_optstring[(MAX_COMMANDS > MAX_OPTIONS ?: MAX_OPTIONS) * 3];
52
53 /**
54 * Build command_opts/command_optstr for the active command
55 */
56 static void build_opts()
57 {
58 int i, pos = 0;
59
60 memset(command_opts, 0, sizeof(command_opts));
61 memset(command_optstring, 0, sizeof(command_optstring));
62 if (active == help_idx)
63 {
64 for (i = 0; cmds[i].cmd; i++)
65 {
66 command_opts[i].name = cmds[i].cmd;
67 command_opts[i].val = cmds[i].op;
68 command_optstring[i] = cmds[i].op;
69 }
70 }
71 else
72 {
73 for (i = 0; cmds[active].options[i].name; i++)
74 {
75 command_opts[i].name = cmds[active].options[i].name;
76 command_opts[i].has_arg = cmds[active].options[i].arg;
77 command_opts[i].val = cmds[active].options[i].op;
78 command_optstring[pos++] = cmds[active].options[i].op;
79 switch (cmds[active].options[i].arg)
80 {
81 case optional_argument:
82 command_optstring[pos++] = ':';
83 /* FALL */
84 case required_argument:
85 command_optstring[pos++] = ':';
86 /* FALL */
87 case no_argument:
88 default:
89 break;
90 }
91 }
92 }
93 }
94
95 /**
96 * Register a command
97 */
98 void command_register(command_t command)
99 {
100 cmds[registered++] = command;
101 }
102
103 /**
104 * Print usage text, with an optional error
105 */
106 int command_usage(char *error)
107 {
108 FILE *out = stdout;
109 char buf[64];
110 int i;
111
112 if (error)
113 {
114 out = stderr;
115 fprintf(out, "Error: %s\n", error);
116 }
117 fprintf(out, "strongSwan %s PKI tool\n", VERSION);
118 fprintf(out, "usage:\n");
119 if (active == help_idx)
120 {
121 for (i = 0; cmds[i].cmd; i++)
122 {
123 snprintf(buf, sizeof(buf), "--%s (-%c)", cmds[i].cmd, cmds[i].op);
124 fprintf(out, " pki %-14s %s\n", buf, cmds[i].description);
125 }
126 }
127 else
128 {
129 for (i = 0; cmds[active].line[i]; i++)
130 {
131 if (i == 0)
132 {
133 fprintf(out, " pki --%s %s\n",
134 cmds[active].cmd, cmds[active].line[i]);
135 }
136 else
137 {
138 fprintf(out, " %s\n", cmds[active].line[i]);
139 }
140 }
141 for (i = 0; cmds[active].options[i].name; i++)
142 {
143 snprintf(buf, sizeof(buf), "--%s (-%c)",
144 cmds[active].options[i].name, cmds[active].options[i].op);
145 fprintf(out, " %-15s %s\n",
146 buf, cmds[active].options[i].desc);
147 }
148 }
149 return error != NULL;
150 }
151
152
153 /**
154 * Show usage information
155 */
156 static int help(int argc, char *argv[])
157 {
158 return command_usage(NULL);
159 }
160
161 /**
162 * Dispatch commands.
163 */
164 int command_dispatch(int argc, char *argv[])
165 {
166 int op, i;
167
168 active = help_idx = registered;
169 command_register((command_t){help, 'h', "help", "show usage information"});
170
171 build_opts();
172 op = getopt_long(argc, argv, command_optstring, command_opts, NULL);
173 for (i = 0; cmds[i].cmd; i++)
174 {
175 if (cmds[i].op == op)
176 {
177 active = i;
178 build_opts();
179 return cmds[i].call(argc, argv);
180 }
181 }
182 return command_usage("invalid operation");
183 }
184