1 /* 2 * Common hostapd/wpa_supplicant command line interface functions 3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "utils/common.h" 12 #include "common/cli.h" 13 14 15 const char *const cli_license = 16 "This software may be distributed under the terms of the BSD license.\n" 17 "See README for more details.\n"; 18 19 const char *const cli_full_license = 20 "This software may be distributed under the terms of the BSD license.\n" 21 "\n" 22 "Redistribution and use in source and binary forms, with or without\n" 23 "modification, are permitted provided that the following conditions are\n" 24 "met:\n" 25 "\n" 26 "1. Redistributions of source code must retain the above copyright\n" 27 " notice, this list of conditions and the following disclaimer.\n" 28 "\n" 29 "2. Redistributions in binary form must reproduce the above copyright\n" 30 " notice, this list of conditions and the following disclaimer in the\n" 31 " documentation and/or other materials provided with the distribution.\n" 32 "\n" 33 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 34 " names of its contributors may be used to endorse or promote products\n" 35 " derived from this software without specific prior written permission.\n" 36 "\n" 37 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 38 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 39 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 40 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 41 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 42 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 43 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 44 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 45 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 46 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 47 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 48 "\n"; 49 50 51 void cli_txt_list_free(struct cli_txt_entry *e) 52 { 53 dl_list_del(&e->list); 54 os_free(e->txt); 55 os_free(e); 56 } 57 58 59 void cli_txt_list_flush(struct dl_list *list) 60 { 61 struct cli_txt_entry *e; 62 63 while ((e = dl_list_first(list, struct cli_txt_entry, list))) 64 cli_txt_list_free(e); 65 } 66 67 68 struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list, 69 const char *txt) 70 { 71 struct cli_txt_entry *e; 72 73 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) { 74 if (os_strcmp(e->txt, txt) == 0) 75 return e; 76 } 77 return NULL; 78 } 79 80 81 void cli_txt_list_del(struct dl_list *txt_list, const char *txt) 82 { 83 struct cli_txt_entry *e; 84 85 e = cli_txt_list_get(txt_list, txt); 86 if (e) 87 cli_txt_list_free(e); 88 } 89 90 91 void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt) 92 { 93 u8 addr[ETH_ALEN]; 94 char buf[18]; 95 96 if (hwaddr_aton(txt, addr) < 0) 97 return; 98 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 99 cli_txt_list_del(txt_list, buf); 100 } 101 102 103 void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt, 104 int separator) 105 { 106 const char *end; 107 char *buf; 108 109 end = os_strchr(txt, separator); 110 if (end == NULL) 111 end = txt + os_strlen(txt); 112 buf = dup_binstr(txt, end - txt); 113 if (buf == NULL) 114 return; 115 cli_txt_list_del(txt_list, buf); 116 os_free(buf); 117 } 118 119 120 int cli_txt_list_add(struct dl_list *txt_list, const char *txt) 121 { 122 struct cli_txt_entry *e; 123 124 e = cli_txt_list_get(txt_list, txt); 125 if (e) 126 return 0; 127 e = os_zalloc(sizeof(*e)); 128 if (e == NULL) 129 return -1; 130 e->txt = os_strdup(txt); 131 if (e->txt == NULL) { 132 os_free(e); 133 return -1; 134 } 135 dl_list_add(txt_list, &e->list); 136 return 0; 137 } 138 139 140 int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt) 141 { 142 u8 addr[ETH_ALEN]; 143 char buf[18]; 144 145 if (hwaddr_aton(txt, addr) < 0) 146 return -1; 147 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 148 return cli_txt_list_add(txt_list, buf); 149 } 150 151 152 int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt, 153 int separator) 154 { 155 const char *end; 156 char *buf; 157 int ret; 158 159 end = os_strchr(txt, separator); 160 if (end == NULL) 161 end = txt + os_strlen(txt); 162 buf = dup_binstr(txt, end - txt); 163 if (buf == NULL) 164 return -1; 165 ret = cli_txt_list_add(txt_list, buf); 166 os_free(buf); 167 return ret; 168 } 169 170 171 char ** cli_txt_list_array(struct dl_list *txt_list) 172 { 173 unsigned int i, count = dl_list_len(txt_list); 174 char **res; 175 struct cli_txt_entry *e; 176 177 res = os_calloc(count + 1, sizeof(char *)); 178 if (res == NULL) 179 return NULL; 180 181 i = 0; 182 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) { 183 res[i] = os_strdup(e->txt); 184 if (res[i] == NULL) 185 break; 186 i++; 187 } 188 189 return res; 190 } 191 192 193 int get_cmd_arg_num(const char *str, int pos) 194 { 195 int arg = 0, i; 196 197 for (i = 0; i <= pos; i++) { 198 if (str[i] != ' ') { 199 arg++; 200 while (i <= pos && str[i] != ' ') 201 i++; 202 } 203 } 204 205 if (arg > 0) 206 arg--; 207 return arg; 208 } 209 210 211 int write_cmd(char *buf, size_t buflen, const char *cmd, int argc, char *argv[]) 212 { 213 int i, res; 214 char *pos, *end; 215 216 pos = buf; 217 end = buf + buflen; 218 219 res = os_snprintf(pos, end - pos, "%s", cmd); 220 if (os_snprintf_error(end - pos, res)) 221 goto fail; 222 pos += res; 223 224 for (i = 0; i < argc; i++) { 225 res = os_snprintf(pos, end - pos, " %s", argv[i]); 226 if (os_snprintf_error(end - pos, res)) 227 goto fail; 228 pos += res; 229 } 230 231 buf[buflen - 1] = '\0'; 232 return 0; 233 234 fail: 235 printf("Too long command\n"); 236 return -1; 237 } 238 239 240 int tokenize_cmd(char *cmd, char *argv[]) 241 { 242 char *pos; 243 int argc = 0; 244 245 pos = cmd; 246 for (;;) { 247 while (*pos == ' ') 248 pos++; 249 if (*pos == '\0') 250 break; 251 argv[argc] = pos; 252 argc++; 253 if (argc == max_args) 254 break; 255 if (*pos == '"') { 256 char *pos2 = os_strrchr(pos, '"'); 257 if (pos2) 258 pos = pos2 + 1; 259 } 260 while (*pos != '\0' && *pos != ' ') 261 pos++; 262 if (*pos == ' ') 263 *pos++ = '\0'; 264 } 265 266 return argc; 267 } 268