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