command.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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. #include "command.h"
  16. #include "pki.h"
  17. #define _GNU_SOURCE
  18. #include <getopt.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <library.h>
  23. #include <utils/debug.h>
  24. #include <utils/optionsfrom.h>
  25. /**
  26. * Registered commands.
  27. */
  28. static command_t cmds[MAX_COMMANDS];
  29. /**
  30. * active command.
  31. */
  32. static int active = 0;
  33. /**
  34. * number of registered commands
  35. */
  36. static int registered = 0;
  37. /**
  38. * help command index
  39. */
  40. static int help_idx;
  41. static int argc;
  42. static char **argv;
  43. static options_t *options;
  44. /**
  45. * Global options used by all subcommands
  46. */
  47. static struct option command_opts[MAX_COMMANDS > MAX_OPTIONS ? MAX_COMMANDS : MAX_OPTIONS];
  48. /**
  49. * Global optstring used by all subcommands
  50. */
  51. static char command_optstring[(MAX_COMMANDS > MAX_OPTIONS ? MAX_COMMANDS : MAX_OPTIONS) * 3];
  52. /**
  53. * Build command_opts/command_optstr for the active command
  54. */
  55. static void build_opts()
  56. {
  57. int i, pos = 0;
  58. memset(command_opts, 0, sizeof(command_opts));
  59. memset(command_optstring, 0, sizeof(command_optstring));
  60. if (active == help_idx)
  61. {
  62. for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
  63. {
  64. command_opts[i].name = cmds[i].cmd;
  65. command_opts[i].val = cmds[i].op;
  66. command_optstring[i] = cmds[i].op;
  67. }
  68. }
  69. else
  70. {
  71. for (i = 0; cmds[active].options[i].name; i++)
  72. {
  73. command_opts[i].name = cmds[active].options[i].name;
  74. command_opts[i].has_arg = cmds[active].options[i].arg;
  75. command_opts[i].val = cmds[active].options[i].op;
  76. command_optstring[pos++] = cmds[active].options[i].op;
  77. switch (cmds[active].options[i].arg)
  78. {
  79. case optional_argument:
  80. command_optstring[pos++] = ':';
  81. /* FALL */
  82. case required_argument:
  83. command_optstring[pos++] = ':';
  84. /* FALL */
  85. case no_argument:
  86. default:
  87. break;
  88. }
  89. }
  90. }
  91. }
  92. /**
  93. * getopt_long wrapper
  94. */
  95. int command_getopt(char **arg)
  96. {
  97. int op;
  98. while (TRUE)
  99. {
  100. op = getopt_long(argc, argv, command_optstring, command_opts, NULL);
  101. switch (op)
  102. {
  103. case '+':
  104. if (!options->from(options, optarg, &argc, &argv, optind))
  105. {
  106. /* a error value */
  107. return 255;
  108. }
  109. continue;
  110. case 'v':
  111. dbg_default_set_level(atoi(optarg));
  112. continue;
  113. default:
  114. *arg = optarg;
  115. return op;
  116. }
  117. }
  118. }
  119. /**
  120. * Register a command
  121. */
  122. void command_register(command_t command)
  123. {
  124. int i;
  125. if (registered == MAX_COMMANDS)
  126. {
  127. fprintf(stderr, "unable to register command, please increase "
  128. "MAX_COMMANDS\n");
  129. return;
  130. }
  131. cmds[registered] = command;
  132. /* append default options, but not to --help */
  133. if (!active)
  134. {
  135. for (i = 0; i < countof(cmds[registered].options) - 1; i++)
  136. {
  137. if (!cmds[registered].options[i].name)
  138. {
  139. break;
  140. }
  141. }
  142. if (i > countof(cmds[registered].options) - 3)
  143. {
  144. fprintf(stderr, "command '%s' registered too many options, please "
  145. "increase MAX_OPTIONS\n", command.cmd);
  146. }
  147. else
  148. {
  149. cmds[registered].options[i++] = (command_option_t) {
  150. "debug", 'v', 1, "set debug level, default: 1"
  151. };
  152. cmds[registered].options[i++] = (command_option_t) {
  153. "options", '+', 1, "read command line options from file"
  154. };
  155. }
  156. for (i = 0; cmds[registered].line[i]; i++)
  157. {
  158. if (i == MAX_LINES - 1)
  159. {
  160. fprintf(stderr, "command '%s' specifies too many usage summary "
  161. "lines, please increase MAX_LINES\n", command.cmd);
  162. break;
  163. }
  164. }
  165. }
  166. registered++;
  167. }
  168. /**
  169. * Print usage text, with an optional error
  170. */
  171. int command_usage(char *error)
  172. {
  173. FILE *out = stdout;
  174. int i, indent = 0;
  175. if (error)
  176. {
  177. out = stderr;
  178. fprintf(out, "Error: %s\n", error);
  179. }
  180. fprintf(out, "strongSwan %s PKI tool\n", VERSION);
  181. if (active == help_idx)
  182. {
  183. fprintf(out, "loaded plugins: %s\n",
  184. lib->plugins->loaded_plugins(lib->plugins));
  185. }
  186. fprintf(out, "usage:\n");
  187. if (active == help_idx)
  188. {
  189. for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
  190. {
  191. fprintf(out, " pki --%-7s (-%c) %s\n",
  192. cmds[i].cmd, cmds[i].op, cmds[i].description);
  193. }
  194. }
  195. else
  196. {
  197. for (i = 0; i < MAX_LINES && cmds[active].line[i]; i++)
  198. {
  199. if (i == 0)
  200. {
  201. indent = fprintf(out, " pki --%s ", cmds[active].cmd);
  202. fprintf(out, "%s\n", cmds[active].line[i]);
  203. }
  204. else
  205. {
  206. fprintf(out, "%*s%s\n", indent, "", cmds[active].line[i]);
  207. }
  208. }
  209. for (i = 0; cmds[active].options[i].name; i++)
  210. {
  211. fprintf(out, " --%-15s (-%c) %s\n",
  212. cmds[active].options[i].name, cmds[active].options[i].op,
  213. cmds[active].options[i].desc);
  214. }
  215. }
  216. return error != NULL;
  217. }
  218. /**
  219. * Show usage information
  220. */
  221. static int help(int argc, char *argv[])
  222. {
  223. return command_usage(NULL);
  224. }
  225. /**
  226. * Dispatch cleanup hook
  227. */
  228. static void cleanup()
  229. {
  230. options->destroy(options);
  231. }
  232. /**
  233. * Dispatch commands.
  234. */
  235. int command_dispatch(int c, char *v[])
  236. {
  237. int op, i;
  238. options = options_create();
  239. atexit(cleanup);
  240. active = help_idx = registered;
  241. argc = c;
  242. argv = v;
  243. command_register((command_t){help, 'h', "help", "show usage information"});
  244. build_opts();
  245. op = getopt_long(c, v, command_optstring, command_opts, NULL);
  246. for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
  247. {
  248. if (cmds[i].op == op)
  249. {
  250. active = i;
  251. build_opts();
  252. return cmds[i].call();
  253. }
  254. }
  255. return command_usage(c > 1 ? "invalid operation" : NULL);
  256. }