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