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>