iproute2/tipc/cmdl.c
<<
>>
Prefs
   1/*
   2 * cmdl.c       Framework for handling command line options.
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Richard Alpe <richard.alpe@ericsson.com>
  10 */
  11
  12#include <stdio.h>
  13#include <string.h>
  14#include <errno.h>
  15
  16#include <libmnl/libmnl.h>
  17
  18#include "cmdl.h"
  19
  20static const struct cmd *find_cmd(const struct cmd *cmds, char *str)
  21{
  22        const struct cmd *c;
  23        const struct cmd *match = NULL;
  24
  25        for (c = cmds; c->cmd; c++) {
  26                if (strstr(c->cmd, str) != c->cmd)
  27                        continue;
  28                if (match)
  29                        return NULL;
  30                match = c;
  31        }
  32
  33        return match;
  34}
  35
  36struct opt *find_opt(struct opt *opts, char *str)
  37{
  38        struct opt *o;
  39        struct opt *match = NULL;
  40
  41        for (o = opts; o->key; o++) {
  42                if (strstr(o->key, str) != o->key)
  43                        continue;
  44                if (match)
  45                        return NULL;
  46
  47                match = o;
  48        }
  49
  50        return match;
  51}
  52
  53struct opt *get_opt(struct opt *opts, char *key)
  54{
  55        struct opt *o;
  56
  57        for (o = opts; o->key; o++) {
  58                if (strcmp(o->key, key) == 0 && o->val)
  59                        return o;
  60        }
  61
  62        return NULL;
  63}
  64
  65bool has_opt(struct opt *opts, char *key)
  66{
  67        return get_opt(opts, key) ? true : false;
  68}
  69
  70char *shift_cmdl(struct cmdl *cmdl)
  71{
  72        int next;
  73
  74        if (cmdl->optind < cmdl->argc)
  75                next = (cmdl->optind)++;
  76        else
  77                next = cmdl->argc;
  78
  79        return cmdl->argv[next];
  80}
  81
  82/* Returns the number of options parsed or a negative error code upon failure */
  83int parse_opts(struct opt *opts, struct cmdl *cmdl)
  84{
  85        int i;
  86        int cnt = 0;
  87
  88        for (i = cmdl->optind; i < cmdl->argc; i++) {
  89                struct opt *o;
  90
  91                o = find_opt(opts, cmdl->argv[i]);
  92                if (!o) {
  93                        fprintf(stderr, "error, invalid option \"%s\"\n",
  94                                        cmdl->argv[i]);
  95                        return -EINVAL;
  96                }
  97                if (o->flag & OPT_KEYVAL) {
  98                        cmdl->optind++;
  99                        i++;
 100                }
 101                cnt++;
 102                o->val = cmdl->argv[i];
 103                cmdl->optind++;
 104        }
 105
 106        return cnt;
 107}
 108
 109int run_cmd(struct nlmsghdr *nlh, const struct cmd *caller,
 110            const struct cmd *cmds, struct cmdl *cmdl, void *data)
 111{
 112        char *name;
 113        const struct cmd *cmd;
 114
 115        if ((cmdl->optind) >= cmdl->argc) {
 116                if (caller->help)
 117                        (caller->help)(cmdl);
 118                return -EINVAL;
 119        }
 120        name = cmdl->argv[cmdl->optind];
 121        (cmdl->optind)++;
 122
 123        cmd = find_cmd(cmds, name);
 124        if (!cmd) {
 125                /* Show help about last command if we don't find this one */
 126                if (help_flag && caller->help) {
 127                        (caller->help)(cmdl);
 128                } else {
 129                        fprintf(stderr, "error, invalid command \"%s\"\n", name);
 130                        fprintf(stderr, "use --help for command help\n");
 131                }
 132                return -EINVAL;
 133        }
 134
 135        return (cmd->func)(nlh, cmd, cmdl, data);
 136}
 137