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 (at) 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 20 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 36 static struct 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 53 struct 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 65 bool has_opt(struct opt *opts, char *key) 66 { 67 return get_opt(opts, key) ? true : false; 68 } 69 70 char *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 */ 83 int 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 109 int 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