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