devtools/cocci: create safer version of strlcpy script
[dpdk.git] / lib / librte_cmdline / cmdline_parse_string.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4  * All rights reserved.
5  */
6
7 #include <stdio.h>
8 #include <inttypes.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <errno.h>
13 #include <rte_string_fns.h>
14
15 #include "cmdline_parse.h"
16 #include "cmdline_parse_string.h"
17
18 struct cmdline_token_ops cmdline_token_string_ops = {
19         .parse = cmdline_parse_string,
20         .complete_get_nb = cmdline_complete_get_nb_string,
21         .complete_get_elt = cmdline_complete_get_elt_string,
22         .get_help = cmdline_get_help_string,
23 };
24
25 #define CHOICESTRING_HELP "Mul-choice STRING"
26 #define ANYSTRING_HELP    "Any STRING"
27 #define ANYSTRINGS_HELP   "Any STRINGS"
28 #define FIXEDSTRING_HELP  "Fixed STRING"
29
30 static unsigned int
31 get_token_len(const char *s)
32 {
33         char c;
34         unsigned int i=0;
35
36         c = s[i];
37         while (c!='#' && c!='\0') {
38                 i++;
39                 c = s[i];
40         }
41         return i;
42 }
43
44 static const char *
45 get_next_token(const char *s)
46 {
47         unsigned int i;
48         i = get_token_len(s);
49         if (s[i] == '#')
50                 return s+i+1;
51         return NULL;
52 }
53
54 int
55 cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
56         unsigned ressize)
57 {
58         struct cmdline_token_string *tk2;
59         struct cmdline_token_string_data *sd;
60         unsigned int token_len;
61         const char *str;
62
63         if (res && ressize < STR_TOKEN_SIZE)
64                 return -1;
65
66         if (!tk || !buf || ! *buf)
67                 return -1;
68
69         tk2 = (struct cmdline_token_string *)tk;
70
71         sd = &tk2->string_data;
72
73         /* fixed string (known single token) */
74         if ((sd->str != NULL) && (strcmp(sd->str, TOKEN_STRING_MULTI) != 0)) {
75                 str = sd->str;
76                 do {
77                         token_len = get_token_len(str);
78
79                         /* if token is too big... */
80                         if (token_len >= STR_TOKEN_SIZE - 1) {
81                                 continue;
82                         }
83
84                         if ( strncmp(buf, str, token_len) ) {
85                                 continue;
86                         }
87
88                         if ( !cmdline_isendoftoken(*(buf+token_len)) ) {
89                                 continue;
90                         }
91
92                         break;
93                 } while ( (str = get_next_token(str)) != NULL );
94
95                 if (!str)
96                         return -1;
97         }
98         /* multi string */
99         else if (sd->str != NULL) {
100                 if (ressize < STR_MULTI_TOKEN_SIZE)
101                         return -1;
102
103                 token_len = 0;
104                 while (!cmdline_isendofcommand(buf[token_len]) &&
105                       token_len < (STR_MULTI_TOKEN_SIZE - 1))
106                         token_len++;
107
108                 /* return if token too long */
109                 if (token_len >= (STR_MULTI_TOKEN_SIZE - 1))
110                         return -1;
111         }
112         /* unspecified string (unknown single token) */
113         else {
114                 token_len = 0;
115                 while(!cmdline_isendoftoken(buf[token_len]) &&
116                       token_len < (STR_TOKEN_SIZE-1))
117                         token_len++;
118
119                 /* return if token too long */
120                 if (token_len >= STR_TOKEN_SIZE - 1) {
121                         return -1;
122                 }
123         }
124
125         if (res) {
126                 if ((sd->str != NULL) && (strcmp(sd->str, TOKEN_STRING_MULTI) == 0))
127                         /* we are sure that token_len is < STR_MULTI_TOKEN_SIZE-1 */
128                         strlcpy(res, buf, STR_MULTI_TOKEN_SIZE);
129                 else
130                         /* we are sure that token_len is < STR_TOKEN_SIZE-1 */
131                         strlcpy(res, buf, STR_TOKEN_SIZE);
132
133                 *((char *)res + token_len) = 0;
134         }
135
136         return token_len;
137 }
138
139 int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk)
140 {
141         struct cmdline_token_string *tk2;
142         struct cmdline_token_string_data *sd;
143         const char *str;
144         int ret = 1;
145
146         if (!tk)
147                 return -1;
148
149         tk2 = (struct cmdline_token_string *)tk;
150         sd = &tk2->string_data;
151
152         if (!sd->str)
153                 return 0;
154
155         str = sd->str;
156         while( (str = get_next_token(str)) != NULL ) {
157                 ret++;
158         }
159         return ret;
160 }
161
162 int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx,
163                                     char *dstbuf, unsigned int size)
164 {
165         struct cmdline_token_string *tk2;
166         struct cmdline_token_string_data *sd;
167         const char *s;
168         unsigned int len;
169
170         if (!tk || !dstbuf || idx < 0)
171                 return -1;
172
173         tk2 = (struct cmdline_token_string *)tk;
174         sd = &tk2->string_data;
175
176         s = sd->str;
177
178         while (idx-- && s)
179                 s = get_next_token(s);
180
181         if (!s)
182                 return -1;
183
184         len = get_token_len(s);
185         if (len > size - 1)
186                 return -1;
187
188         memcpy(dstbuf, s, len);
189         dstbuf[len] = '\0';
190         return 0;
191 }
192
193
194 int cmdline_get_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf,
195                             unsigned int size)
196 {
197         struct cmdline_token_string *tk2;
198         struct cmdline_token_string_data *sd;
199         const char *s;
200
201         if (!tk || !dstbuf)
202                 return -1;
203
204         tk2 = (struct cmdline_token_string *)tk;
205         sd = &tk2->string_data;
206
207         s = sd->str;
208
209         if (s) {
210                 if (strcmp(s, TOKEN_STRING_MULTI) == 0)
211                         snprintf(dstbuf, size, ANYSTRINGS_HELP);
212                 else if (get_next_token(s))
213                         snprintf(dstbuf, size, CHOICESTRING_HELP);
214                 else
215                         snprintf(dstbuf, size, FIXEDSTRING_HELP);
216         } else
217                 snprintf(dstbuf, size, ANYSTRING_HELP);
218
219         return 0;
220 }