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