xref: /freebsd/contrib/wpa/src/common/cli.c (revision 780fb4a2fa9a9aee5ac48a60b790f567c0dc13e9)
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