app/testpmd: fix packet burst spreading stats
[dpdk.git] / lib / cmdline / cmdline.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 <string.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <inttypes.h>
13 #include <fcntl.h>
14 #include <errno.h>
15
16 #include <rte_string_fns.h>
17
18 #include "cmdline_private.h"
19
20 static void
21 cmdline_valid_buffer(struct rdline *rdl, const char *buf,
22                      __rte_unused unsigned int size)
23 {
24         struct cmdline *cl = rdl->opaque;
25         int ret;
26         ret = cmdline_parse(cl, buf);
27         if (ret == CMDLINE_PARSE_AMBIGUOUS)
28                 cmdline_printf(cl, "Ambiguous command\n");
29         else if (ret == CMDLINE_PARSE_NOMATCH)
30                 cmdline_printf(cl, "Command not found\n");
31         else if (ret == CMDLINE_PARSE_BAD_ARGS)
32                 cmdline_printf(cl, "Bad arguments\n");
33 }
34
35 static int
36 cmdline_complete_buffer(struct rdline *rdl, const char *buf,
37                         char *dstbuf, unsigned int dstsize,
38                         int *state)
39 {
40         struct cmdline *cl = rdl->opaque;
41         return cmdline_complete(cl, buf, state, dstbuf, dstsize);
42 }
43
44 int
45 cmdline_write_char(struct rdline *rdl, char c)
46 {
47         int ret = -1;
48         struct cmdline *cl;
49
50         if (!rdl)
51                 return -1;
52
53         cl = rdl->opaque;
54
55         if (cl->s_out >= 0)
56                 ret = write(cl->s_out, &c, 1);
57
58         return ret;
59 }
60
61
62 void
63 cmdline_set_prompt(struct cmdline *cl, const char *prompt)
64 {
65         if (!cl || !prompt)
66                 return;
67         strlcpy(cl->prompt, prompt, sizeof(cl->prompt));
68 }
69
70 struct cmdline *
71 cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out)
72 {
73         struct cmdline *cl;
74         int ret;
75
76         if (!ctx || !prompt)
77                 return NULL;
78
79         cl = malloc(sizeof(struct cmdline));
80         if (cl == NULL)
81                 return NULL;
82         memset(cl, 0, sizeof(struct cmdline));
83         cl->s_in = s_in;
84         cl->s_out = s_out;
85         cl->ctx = ctx;
86
87         ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer,
88                         cmdline_complete_buffer, cl);
89         if (ret != 0) {
90                 free(cl);
91                 return NULL;
92         }
93
94         cmdline_set_prompt(cl, prompt);
95         rdline_newline(&cl->rdl, cl->prompt);
96
97         return cl;
98 }
99
100 struct rdline*
101 cmdline_get_rdline(struct cmdline *cl)
102 {
103         return &cl->rdl;
104 }
105
106 void
107 cmdline_free(struct cmdline *cl)
108 {
109         dprintf("called\n");
110
111         if (!cl)
112                 return;
113
114         if (cl->s_in > 2)
115                 close(cl->s_in);
116         if (cl->s_out != cl->s_in && cl->s_out > 2)
117                 close(cl->s_out);
118         free(cl);
119 }
120
121 void
122 cmdline_printf(const struct cmdline *cl, const char *fmt, ...)
123 {
124         va_list ap;
125
126         if (!cl || !fmt)
127                 return;
128
129         if (cl->s_out < 0)
130                 return;
131         va_start(ap, fmt);
132         cmdline_vdprintf(cl->s_out, fmt, ap);
133         va_end(ap);
134 }
135
136 int
137 cmdline_in(struct cmdline *cl, const char *buf, int size)
138 {
139         const char *history, *buffer;
140         size_t histlen, buflen;
141         int ret = 0;
142         int i, same;
143
144         if (!cl || !buf)
145                 return -1;
146
147         for (i=0; i<size; i++) {
148                 ret = rdline_char_in(&cl->rdl, buf[i]);
149
150                 if (ret == RDLINE_RES_VALIDATED) {
151                         buffer = rdline_get_buffer(&cl->rdl);
152                         history = rdline_get_history_item(&cl->rdl, 0);
153                         if (history) {
154                                 histlen = strnlen(history, RDLINE_BUF_SIZE);
155                                 same = !memcmp(buffer, history, histlen) &&
156                                         buffer[histlen] == '\n';
157                         }
158                         else
159                                 same = 0;
160                         buflen = strnlen(buffer, RDLINE_BUF_SIZE);
161                         if (buflen > 1 && !same)
162                                 rdline_add_history(&cl->rdl, buffer);
163                         rdline_newline(&cl->rdl, cl->prompt);
164                 }
165                 else if (ret == RDLINE_RES_EOF)
166                         return -1;
167                 else if (ret == RDLINE_RES_EXITED)
168                         return -1;
169         }
170         return i;
171 }
172
173 void
174 cmdline_quit(struct cmdline *cl)
175 {
176         if (!cl)
177                 return;
178         rdline_quit(&cl->rdl);
179 }
180
181 int
182 cmdline_poll(struct cmdline *cl)
183 {
184         int status;
185         ssize_t read_status;
186         char c;
187
188         if (!cl)
189                 return -EINVAL;
190         else if (cl->rdl.status == RDLINE_EXITED)
191                 return RDLINE_EXITED;
192
193         status = cmdline_poll_char(cl);
194         if (status < 0)
195                 return status;
196         else if (status > 0) {
197                 c = -1;
198                 read_status = cmdline_read_char(cl, &c);
199                 if (read_status < 0)
200                         return read_status;
201
202                 status = cmdline_in(cl, &c, 1);
203                 if (status < 0 && cl->rdl.status != RDLINE_EXITED)
204                         return status;
205         }
206
207         return cl->rdl.status;
208 }
209
210 void
211 cmdline_interact(struct cmdline *cl)
212 {
213         char c;
214
215         if (!cl)
216                 return;
217
218         c = -1;
219         while (1) {
220                 if (cmdline_read_char(cl, &c) <= 0)
221                         break;
222                 if (cmdline_in(cl, &c, 1) < 0)
223                         break;
224         }
225 }