1/*-
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 *   All rights reserved.
6 *
7 *   Redistribution and use in source and binary forms, with or without
8 *   modification, are permitted provided that the following conditions
9 *   are met:
10 *
11 *     * Redistributions of source code must retain the above copyright
12 *       notice, this list of conditions and the following disclaimer.
13 *     * Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *     * Neither the name of Intel Corporation nor the names of its
18 *       contributors may be used to endorse or promote products derived
19 *       from this software without specific prior written permission.
20 *
21 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
36 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions are met:
39 *
40 *     * Redistributions of source code must retain the above copyright
41 *       notice, this list of conditions and the following disclaimer.
42 *     * Redistributions in binary form must reproduce the above copyright
43 *       notice, this list of conditions and the following disclaimer in the
44 *       documentation and/or other materials provided with the distribution.
45 *     * Neither the name of the University of California, Berkeley nor the
46 *       names of its contributors may be used to endorse or promote products
47 *       derived from this software without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
50 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
53 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
56 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61#include <stdio.h>
62#include <inttypes.h>
63#include <ctype.h>
64#include <string.h>
65#include <stdarg.h>
66#include <errno.h>
67#include <rte_string_fns.h>
68
69#include "cmdline_parse.h"
70#include "cmdline_parse_string.h"
71
72struct cmdline_token_ops cmdline_token_string_ops = {
73	.parse = cmdline_parse_string,
74	.complete_get_nb = cmdline_complete_get_nb_string,
75	.complete_get_elt = cmdline_complete_get_elt_string,
76	.get_help = cmdline_get_help_string,
77};
78
79#define CHOICESTRING_HELP "Mul-choice STRING"
80#define ANYSTRING_HELP    "Any STRING"
81#define ANYSTRINGS_HELP   "Any STRINGS"
82#define FIXEDSTRING_HELP  "Fixed STRING"
83
84static unsigned int
85get_token_len(const char *s)
86{
87	char c;
88	unsigned int i=0;
89
90	c = s[i];
91	while (c!='#' && c!='\0') {
92		i++;
93		c = s[i];
94	}
95	return i;
96}
97
98static const char *
99get_next_token(const char *s)
100{
101	unsigned int i;
102	i = get_token_len(s);
103	if (s[i] == '#')
104		return s+i+1;
105	return NULL;
106}
107
108int
109cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
110	unsigned ressize)
111{
112	struct cmdline_token_string *tk2;
113	struct cmdline_token_string_data *sd;
114	unsigned int token_len;
115	const char *str;
116
117	if (res && ressize < STR_TOKEN_SIZE)
118		return -1;
119
120	if (!tk || !buf || ! *buf)
121		return -1;
122
123	tk2 = (struct cmdline_token_string *)tk;
124
125	sd = &tk2->string_data;
126
127	/* fixed string (known single token) */
128	if ((sd->str != NULL) && (strcmp(sd->str, TOKEN_STRING_MULTI) != 0)) {
129		str = sd->str;
130		do {
131			token_len = get_token_len(str);
132
133			/* if token is too big... */
134			if (token_len >= STR_TOKEN_SIZE - 1) {
135				continue;
136			}
137
138			if ( strncmp(buf, str, token_len) ) {
139				continue;
140			}
141
142			if ( !cmdline_isendoftoken(*(buf+token_len)) ) {
143				continue;
144			}
145
146			break;
147		} while ( (str = get_next_token(str)) != NULL );
148
149		if (!str)
150			return -1;
151	}
152	/* multi string */
153	else if (sd->str != NULL) {
154		if (ressize < STR_MULTI_TOKEN_SIZE)
155			return -1;
156
157		token_len = 0;
158		while (!cmdline_isendofcommand(buf[token_len]) &&
159		      token_len < (STR_MULTI_TOKEN_SIZE - 1))
160			token_len++;
161
162		/* return if token too long */
163		if (token_len >= (STR_MULTI_TOKEN_SIZE - 1))
164			return -1;
165	}
166	/* unspecified string (unknown single token) */
167	else {
168		token_len = 0;
169		while(!cmdline_isendoftoken(buf[token_len]) &&
170		      token_len < (STR_TOKEN_SIZE-1))
171			token_len++;
172
173		/* return if token too long */
174		if (token_len >= STR_TOKEN_SIZE - 1) {
175			return -1;
176		}
177	}
178
179	if (res) {
180		if ((sd->str != NULL) && (strcmp(sd->str, TOKEN_STRING_MULTI) == 0))
181			/* we are sure that token_len is < STR_MULTI_TOKEN_SIZE-1 */
182			snprintf(res, STR_MULTI_TOKEN_SIZE, "%s", buf);
183		else
184			/* we are sure that token_len is < STR_TOKEN_SIZE-1 */
185			snprintf(res, STR_TOKEN_SIZE, "%s", buf);
186
187		*((char *)res + token_len) = 0;
188	}
189
190	return token_len;
191}
192
193int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk)
194{
195	struct cmdline_token_string *tk2;
196	struct cmdline_token_string_data *sd;
197	const char *str;
198	int ret = 1;
199
200	if (!tk)
201		return -1;
202
203	tk2 = (struct cmdline_token_string *)tk;
204	sd = &tk2->string_data;
205
206	if (!sd->str)
207		return 0;
208
209	str = sd->str;
210	while( (str = get_next_token(str)) != NULL ) {
211		ret++;
212	}
213	return ret;
214}
215
216int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx,
217				    char *dstbuf, unsigned int size)
218{
219	struct cmdline_token_string *tk2;
220	struct cmdline_token_string_data *sd;
221	const char *s;
222	unsigned int len;
223
224	if (!tk || !dstbuf || idx < 0)
225		return -1;
226
227	tk2 = (struct cmdline_token_string *)tk;
228	sd = &tk2->string_data;
229
230	s = sd->str;
231
232	while (idx-- && s)
233		s = get_next_token(s);
234
235	if (!s)
236		return -1;
237
238	len = get_token_len(s);
239	if (len > size - 1)
240		return -1;
241
242	memcpy(dstbuf, s, len);
243	dstbuf[len] = '\0';
244	return 0;
245}
246
247
248int cmdline_get_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf,
249			    unsigned int size)
250{
251	struct cmdline_token_string *tk2;
252	struct cmdline_token_string_data *sd;
253	const char *s;
254
255	if (!tk || !dstbuf)
256		return -1;
257
258	tk2 = (struct cmdline_token_string *)tk;
259	sd = &tk2->string_data;
260
261	s = sd->str;
262
263	if (s) {
264		if (strcmp(s, TOKEN_STRING_MULTI) == 0)
265			snprintf(dstbuf, size, ANYSTRINGS_HELP);
266		else if (get_next_token(s))
267			snprintf(dstbuf, size, CHOICESTRING_HELP);
268		else
269			snprintf(dstbuf, size, FIXEDSTRING_HELP);
270	} else
271		snprintf(dstbuf, size, ANYSTRING_HELP);
272
273	return 0;
274}
275