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 "cmdl.h"
  17
  18static const struct cmd *find_cmd(const struct cmd *cmds, char *str)
  19{
  20        const struct cmd *c;
  21        const struct cmd *match = NULL;
  22
  23        for (c = cmds; c->cmd; c++) {
  24                if (strstr(c->cmd, str) != c->cmd)
  25                        continue;
  26                if (match)
  27                        return NULL;
  28                match = c;
  29        }
  30
  31        return match;
  32}
  33
  34struct opt *find_opt(struct opt *opts, char *str)
  35{
  36        struct opt *o;
  37        struct opt *match = NULL;
  38
  39        for (o = opts; o->key; o++) {
  40                if (strstr(o->key, str) != o->key)
  41                        continue;
  42                if (match)
  43                        return NULL;
  44
  45                match = o;
  46        }
  47
  48        return match;
  49}
  50
  51struct opt *get_opt(struct opt *opts, char *key)
  52{
  53        struct opt *o;
  54
  55        for (o = opts; o->key; o++) {
  56                if (strcmp(o->key, key) == 0 && o->val)
  57                        return o;
  58        }
  59
  60        return NULL;
  61}
  62
  63bool has_opt(struct opt *opts, char *key)
  64{
  65        return get_opt(opts, key) ? true : false;
  66}
  67
  68char *shift_cmdl(struct cmdl *cmdl)
  69{
  70        int next;
  71
  72        if (cmdl->optind < cmdl->argc)
  73                next = (cmdl->optind)++;
  74        else
  75                next = cmdl->argc;
  76
  77        return cmdl->argv[next];
  78}
  79
  80/* Returns the number of options parsed or a negative error code upon failure */
  81int parse_opts(struct opt *opts, struct cmdl *cmdl)
  82{
  83        int i;
  84        int cnt = 0;
  85
  86        for (i = cmdl->optind; i < cmdl->argc; i++) {
  87                struct opt *o;
  88
  89                o = find_opt(opts, cmdl->argv[i]);
  90                if (!o) {
  91                        fprintf(stderr, "error, invalid option \"%s\"\n",
  92                                        cmdl->argv[i]);
  93                        return -EINVAL;
  94                }
  95                if (o->flag & OPT_KEYVAL) {
  96                        cmdl->optind++;
  97                        i++;
  98                }
  99                cnt++;
 100                o->val = cmdl->argv[i];
 101                cmdl->optind++;
 102        }
 103
 104        return cnt;
 105}
 106
 107int run_cmd(struct nlmsghdr *nlh, const struct cmd *caller,
 108            const struct cmd *cmds, struct cmdl *cmdl, void *data)
 109{
 110        char *name;
 111        const struct cmd *cmd;
 112
 113        if ((cmdl->optind) >= cmdl->argc) {
 114                if (caller->help)
 115                        (caller->help)(cmdl);
 116                return -EINVAL;
 117        }
 118        name = cmdl->argv[cmdl->optind];
 119        (cmdl->optind)++;
 120
 121        cmd = find_cmd(cmds, name);
 122        if (!cmd) {
 123                /* Show help about last command if we don't find this one */
 124                if (help_flag && caller->help) {
 125                        (caller->help)(cmdl);
 126                } else {
 127                        fprintf(stderr, "error, invalid command \"%s\"\n", name);
 128                        fprintf(stderr, "use --help for command help\n");
 129                }
 130                return -EINVAL;
 131        }
 132
 133        return (cmd->func)(nlh, cmd, cmdl, data);
 134}
 135