Annotation of embedaddon/strongswan/src/swanctl/command.c, revision 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:
! 18: #define _GNU_SOURCE
! 19: #include <getopt.h>
! 20: #include <stdlib.h>
! 21: #include <string.h>
! 22: #include <stdio.h>
! 23: #include <errno.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: /**
! 50: * Uri to connect to
! 51: */
! 52: static char *uri = NULL;
! 53:
! 54: static int argc;
! 55:
! 56: static char **argv;
! 57:
! 58: static options_t *options;
! 59:
! 60: /**
! 61: * Global options used by all subcommands
! 62: */
! 63: static struct option command_opts[MAX_COMMANDS > MAX_OPTIONS ?
! 64: MAX_COMMANDS : MAX_OPTIONS];
! 65:
! 66: /**
! 67: * Global optstring used by all subcommands
! 68: */
! 69: static char command_optstring[(MAX_COMMANDS > MAX_OPTIONS ?
! 70: MAX_COMMANDS : MAX_OPTIONS) * 3];
! 71:
! 72: /**
! 73: * Build command_opts/command_optstr for the active command
! 74: */
! 75: static void build_opts()
! 76: {
! 77: int i, pos = 0;
! 78:
! 79: memset(command_opts, 0, sizeof(command_opts));
! 80: memset(command_optstring, 0, sizeof(command_optstring));
! 81: if (active == help_idx)
! 82: {
! 83: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
! 84: {
! 85: command_opts[i].name = cmds[i].cmd;
! 86: command_opts[i].val = cmds[i].op;
! 87: command_optstring[i] = cmds[i].op;
! 88: }
! 89: }
! 90: else
! 91: {
! 92: for (i = 0; cmds[active].options[i].name; i++)
! 93: {
! 94: command_opts[i].name = cmds[active].options[i].name;
! 95: command_opts[i].has_arg = cmds[active].options[i].arg;
! 96: command_opts[i].val = cmds[active].options[i].op;
! 97: command_optstring[pos++] = cmds[active].options[i].op;
! 98: switch (cmds[active].options[i].arg)
! 99: {
! 100: case optional_argument:
! 101: command_optstring[pos++] = ':';
! 102: /* FALL */
! 103: case required_argument:
! 104: command_optstring[pos++] = ':';
! 105: /* FALL */
! 106: case no_argument:
! 107: default:
! 108: break;
! 109: }
! 110: }
! 111: }
! 112: }
! 113:
! 114: /**
! 115: * getopt_long wrapper
! 116: */
! 117: int command_getopt(char **arg)
! 118: {
! 119: int op;
! 120:
! 121: while (TRUE)
! 122: {
! 123: op = getopt_long(argc, argv, command_optstring, command_opts, NULL);
! 124: switch (op)
! 125: {
! 126: case '+':
! 127: case 'v':
! 128: case 'u':
! 129: continue;
! 130: default:
! 131: *arg = optarg;
! 132: return op;
! 133: }
! 134: }
! 135: }
! 136:
! 137: /**
! 138: * Register a command
! 139: */
! 140: void command_register(command_t command)
! 141: {
! 142: int i;
! 143:
! 144: if (registered == MAX_COMMANDS)
! 145: {
! 146: fprintf(stderr, "unable to register command, please increase "
! 147: "MAX_COMMANDS\n");
! 148: return;
! 149: }
! 150: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
! 151: {
! 152: if (cmds[i].op == command.op)
! 153: {
! 154: fprintf(stderr, "unable to register command --%s, short option "
! 155: "conflicts with --%s\n", command.cmd, cmds[i].cmd);
! 156: return;
! 157: }
! 158: }
! 159:
! 160: cmds[registered] = command;
! 161: /* append default options, but not to --help */
! 162: if (!active)
! 163: {
! 164: for (i = 0; i < countof(cmds[registered].options) - 1; i++)
! 165: {
! 166: if (!cmds[registered].options[i].name)
! 167: {
! 168: break;
! 169: }
! 170: }
! 171: if (i > countof(cmds[registered].options) - 3)
! 172: {
! 173: fprintf(stderr, "command '%s' registered too many options, please "
! 174: "increase MAX_OPTIONS\n", command.cmd);
! 175: }
! 176: else
! 177: {
! 178: cmds[registered].options[i++] = (command_option_t) {
! 179: "debug", 'v', 1, "set debug level, default: 1"
! 180: };
! 181: cmds[registered].options[i++] = (command_option_t) {
! 182: "options", '+', 1, "read command line options from file"
! 183: };
! 184: cmds[registered].options[i++] = (command_option_t) {
! 185: "uri", 'u', 1, "service URI to connect to"
! 186: };
! 187: }
! 188: for (i = 0; cmds[registered].line[i]; i++)
! 189: {
! 190: if (i == MAX_LINES - 1)
! 191: {
! 192: fprintf(stderr, "command '%s' specifies too many usage summary "
! 193: "lines, please increase MAX_LINES\n", command.cmd);
! 194: break;
! 195: }
! 196: }
! 197: }
! 198: registered++;
! 199: }
! 200:
! 201: /**
! 202: * Print usage text, with an optional error
! 203: */
! 204: int command_usage(char *error, ...)
! 205: {
! 206: va_list args;
! 207: FILE *out = stdout;
! 208: int i;
! 209:
! 210: if (error)
! 211: {
! 212: out = stderr;
! 213: fprintf(out, "Error: ");
! 214: va_start(args, error);
! 215: vfprintf(out, error, args);
! 216: va_end(args);
! 217: fprintf(out, "\n");
! 218: }
! 219: fprintf(out, "strongSwan %s swanctl\n", VERSION);
! 220:
! 221: if (active == help_idx)
! 222: {
! 223: fprintf(out, "loaded plugins: %s\n",
! 224: lib->plugins->loaded_plugins(lib->plugins));
! 225: }
! 226:
! 227: fprintf(out, "usage:\n");
! 228: if (active == help_idx)
! 229: {
! 230: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
! 231: {
! 232: fprintf(out, " swanctl --%-16s (-%c) %s\n",
! 233: cmds[i].cmd, cmds[i].op, cmds[i].description);
! 234: }
! 235: }
! 236: else
! 237: {
! 238: for (i = 0; i < MAX_LINES && cmds[active].line[i]; i++)
! 239: {
! 240: if (i == 0)
! 241: {
! 242: fprintf(out, " swanctl --%s %s\n",
! 243: cmds[active].cmd, cmds[active].line[i]);
! 244: }
! 245: else
! 246: {
! 247: fprintf(out, " %s\n", cmds[active].line[i]);
! 248: }
! 249: }
! 250: for (i = 0; cmds[active].options[i].name; i++)
! 251: {
! 252: fprintf(out, " --%-15s (-%c) %s\n",
! 253: cmds[active].options[i].name, cmds[active].options[i].op,
! 254: cmds[active].options[i].desc);
! 255: }
! 256: }
! 257: return error != NULL;
! 258: }
! 259:
! 260: /**
! 261: * Dispatch cleanup hook
! 262: */
! 263: static void cleanup()
! 264: {
! 265: options->destroy(options);
! 266: }
! 267:
! 268: /**
! 269: * Process options common for all commands
! 270: */
! 271: static bool process_common_opts()
! 272: {
! 273: while (TRUE)
! 274: {
! 275: switch (getopt_long(argc, argv, command_optstring, command_opts, NULL))
! 276: {
! 277: case '+':
! 278: if (!options->from(options, optarg, &argc, &argv, optind))
! 279: {
! 280: return FALSE;
! 281: }
! 282: continue;
! 283: case 'v':
! 284: dbg_default_set_level(atoi(optarg));
! 285: continue;
! 286: case 'u':
! 287: uri = optarg;
! 288: continue;
! 289: default:
! 290: continue;
! 291: case '?':
! 292: return FALSE;
! 293: case EOF:
! 294: return TRUE;
! 295: }
! 296: }
! 297: }
! 298:
! 299: /**
! 300: * Open vici connection, call a command
! 301: */
! 302: static int call_command(command_t *cmd)
! 303: {
! 304: vici_conn_t *conn;
! 305: int ret;
! 306:
! 307: conn = vici_connect(uri);
! 308: if (!conn)
! 309: {
! 310: ret = errno;
! 311: command_usage("connecting to '%s' URI failed: %s",
! 312: uri ?: "default", strerror(errno));
! 313: return ret;
! 314: }
! 315: ret = cmd->call(conn);
! 316: vici_disconnect(conn);
! 317: return ret;
! 318: }
! 319:
! 320: /**
! 321: * Dispatch commands.
! 322: */
! 323: int command_dispatch(int c, char *v[])
! 324: {
! 325: int op, i;
! 326:
! 327: uri = lib->settings->get_str(lib->settings, "%s.socket",
! 328: lib->settings->get_str(lib->settings, "%s.plugins.vici.socket",
! 329: NULL, lib->ns), lib->ns);
! 330:
! 331: options = options_create();
! 332: atexit(cleanup);
! 333: active = help_idx = registered;
! 334: argc = c;
! 335: argv = v;
! 336: command_register((command_t){NULL, 'h', "help", "show usage information"});
! 337:
! 338: build_opts();
! 339: op = getopt_long(c, v, command_optstring, command_opts, NULL);
! 340: for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
! 341: {
! 342: if (cmds[i].op == op)
! 343: {
! 344: active = i;
! 345: build_opts();
! 346: if (help_idx == i)
! 347: {
! 348: return command_usage(NULL);
! 349: }
! 350: if (!process_common_opts())
! 351: {
! 352: return command_usage("invalid options");
! 353: }
! 354: optind = 2;
! 355: return call_command(&cmds[i]);
! 356: }
! 357: }
! 358: return command_usage(c > 1 ? "invalid operation" : NULL);
! 359: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>