cli: Share a common write_cmd() implementation
[mech_eap.git] / src / common / cli.c
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 }