Use dynamic registration/usage invocation of command types
[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 * Build long_opts for a specific command
50 */
51 static void build_opts()
52 {
53 int i;
54
55 memset(command_opts, 0, sizeof(command_opts));
56 if (active == help_idx)
57 {
58 for (i = 0; cmds[i].cmd; i++)
59 {
60 command_opts[i].name = cmds[i].cmd;
61 command_opts[i].val = cmds[i].op;
62 }
63 }
64 else
65 {
66 for (i = 0; cmds[active].options[i].name; i++)
67 {
68 command_opts[i].name = cmds[active].options[i].name;
69 command_opts[i].has_arg = cmds[active].options[i].arg;
70 command_opts[i].val = cmds[active].options[i].op;
71 }
72 }
73 }
74
75 /**
76 * Register a command
77 */
78 void command_register(command_t command)
79 {
80 cmds[registered++] = command;
81 }
82
83 /**
84 * Print usage text, with an optional error
85 */
86 int command_usage(char *error)
87 {
88 FILE *out = stdout;
89 int i;
90
91 if (error)
92 {
93 out = stderr;
94 fprintf(out, "Error: %s\n", error);
95 }
96 fprintf(out, "strongSwan %s PKI tool\n", VERSION);
97 fprintf(out, "usage:\n");
98 if (active == help_idx)
99 {
100 for (i = 0; cmds[i].cmd; i++)
101 {
102 fprintf(out, " pki --%-6s %s\n", cmds[i].cmd, cmds[i].description);
103 }
104 }
105 else
106 {
107 for (i = 0; cmds[active].line[i]; i++)
108 {
109 if (i == 0)
110 {
111 fprintf(out, " pki --%s %s\n",
112 cmds[active].cmd, cmds[active].line[i]);
113 }
114 else
115 {
116 fprintf(out, " %s\n", cmds[active].line[i]);
117 }
118 }
119 for (i = 0; cmds[active].options[i].name; i++)
120 {
121 fprintf(out, " --%-8s %s\n",
122 cmds[active].options[i].name, cmds[active].options[i].desc);
123 }
124 }
125 return error != NULL;
126 }
127
128
129 /**
130 * Show usage information
131 */
132 static int help(int argc, char *argv[])
133 {
134 return command_usage(NULL);
135 }
136
137 /**
138 * Dispatch commands.
139 */
140 int command_dispatch(int argc, char *argv[])
141 {
142 int op, i;
143
144 active = help_idx = registered;
145 command_register((command_t){help, 'h', "help", "show usage information"});
146
147 build_opts();
148 op = getopt_long(argc, argv, "", command_opts, NULL);
149 for (i = 0; cmds[i].cmd; i++)
150 {
151 if (cmds[i].op == op)
152 {
153 active = i;
154 build_opts();
155 return cmds[i].call(argc, argv);
156 }
157 }
158 return command_usage("invalid operation");
159 }
160