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