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