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