|
Packit Service |
3880ab |
/*
|
|
Packit Service |
3880ab |
* cmdl.c Framework for handling command line options.
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
3880ab |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
3880ab |
* as published by the Free Software Foundation; either version
|
|
Packit Service |
3880ab |
* 2 of the License, or (at your option) any later version.
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* Authors: Richard Alpe <richard.alpe@ericsson.com>
|
|
Packit Service |
3880ab |
*/
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include <stdio.h>
|
|
Packit Service |
3880ab |
#include <string.h>
|
|
Packit Service |
3880ab |
#include <errno.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include <libmnl/libmnl.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include "cmdl.h"
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static const struct cmd *find_cmd(const struct cmd *cmds, char *str)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
const struct cmd *c;
|
|
Packit Service |
3880ab |
const struct cmd *match = NULL;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (c = cmds; c->cmd; c++) {
|
|
Packit Service |
3880ab |
if (strstr(c->cmd, str) != c->cmd)
|
|
Packit Service |
3880ab |
continue;
|
|
Packit Service |
3880ab |
if (match)
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
match = c;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return match;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct opt *find_opt(struct opt *opts, char *str)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct opt *o;
|
|
Packit Service |
3880ab |
struct opt *match = NULL;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (o = opts; o->key; o++) {
|
|
Packit Service |
3880ab |
if (strstr(o->key, str) != o->key)
|
|
Packit Service |
3880ab |
continue;
|
|
Packit Service |
3880ab |
if (match)
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
match = o;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return match;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct opt *get_opt(struct opt *opts, char *key)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct opt *o;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (o = opts; o->key; o++) {
|
|
Packit Service |
3880ab |
if (strcmp(o->key, key) == 0 && o->val)
|
|
Packit Service |
3880ab |
return o;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
bool has_opt(struct opt *opts, char *key)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
return get_opt(opts, key) ? true : false;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
char *shift_cmdl(struct cmdl *cmdl)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
int next;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (cmdl->optind < cmdl->argc)
|
|
Packit Service |
3880ab |
next = (cmdl->optind)++;
|
|
Packit Service |
3880ab |
else
|
|
Packit Service |
3880ab |
next = cmdl->argc;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return cmdl->argv[next];
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
/* Returns the number of options parsed or a negative error code upon failure */
|
|
Packit Service |
3880ab |
int parse_opts(struct opt *opts, struct cmdl *cmdl)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
int i;
|
|
Packit Service |
3880ab |
int cnt = 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
for (i = cmdl->optind; i < cmdl->argc; i++) {
|
|
Packit Service |
3880ab |
struct opt *o;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
o = find_opt(opts, cmdl->argv[i]);
|
|
Packit Service |
3880ab |
if (!o) {
|
|
Packit Service |
3880ab |
fprintf(stderr, "error, invalid option \"%s\"\n",
|
|
Packit Service |
3880ab |
cmdl->argv[i]);
|
|
Packit Service |
3880ab |
return -EINVAL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
if (o->flag & OPT_KEYVAL) {
|
|
Packit Service |
3880ab |
cmdl->optind++;
|
|
Packit Service |
3880ab |
i++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
cnt++;
|
|
Packit Service |
3880ab |
o->val = cmdl->argv[i];
|
|
Packit Service |
3880ab |
cmdl->optind++;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return cnt;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
int run_cmd(struct nlmsghdr *nlh, const struct cmd *caller,
|
|
Packit Service |
3880ab |
const struct cmd *cmds, struct cmdl *cmdl, void *data)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
char *name;
|
|
Packit Service |
3880ab |
const struct cmd *cmd;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if ((cmdl->optind) >= cmdl->argc) {
|
|
Packit Service |
3880ab |
if (caller->help)
|
|
Packit Service |
3880ab |
(caller->help)(cmdl);
|
|
Packit Service |
3880ab |
return -EINVAL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
name = cmdl->argv[cmdl->optind];
|
|
Packit Service |
3880ab |
(cmdl->optind)++;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
cmd = find_cmd(cmds, name);
|
|
Packit Service |
3880ab |
if (!cmd) {
|
|
Packit Service |
3880ab |
/* Show help about last command if we don't find this one */
|
|
Packit Service |
3880ab |
if (help_flag && caller->help) {
|
|
Packit Service |
3880ab |
(caller->help)(cmdl);
|
|
Packit Service |
3880ab |
} else {
|
|
Packit Service |
3880ab |
fprintf(stderr, "error, invalid command \"%s\"\n", name);
|
|
Packit Service |
3880ab |
fprintf(stderr, "use --help for command help\n");
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
return -EINVAL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return (cmd->func)(nlh, cmd, cmdl, data);
|
|
Packit Service |
3880ab |
}
|