]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation. | |
7c673cae FG |
3 | * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> |
4 | * All rights reserved. | |
7c673cae FG |
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 <termios.h> | |
17 | #include <netinet/in.h> | |
18 | ||
19 | #include <rte_string_fns.h> | |
20 | ||
21 | #include "cmdline_parse.h" | |
22 | #include "cmdline_rdline.h" | |
23 | #include "cmdline.h" | |
24 | ||
25 | static void | |
26 | cmdline_valid_buffer(struct rdline *rdl, const char *buf, | |
27 | __attribute__((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 | |
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 | |
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 | |
68 | cmdline_set_prompt(struct cmdline *cl, const char *prompt) | |
69 | { | |
70 | if (!cl || !prompt) | |
71 | return; | |
9f95a23c | 72 | strlcpy(cl->prompt, prompt, sizeof(cl->prompt)); |
7c673cae FG |
73 | } |
74 | ||
75 | struct cmdline * | |
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 | 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 | ||
7c673cae FG |
129 | if (cl->s_out < 0) |
130 | return; | |
131 | va_start(ap, fmt); | |
132 | vdprintf(cl->s_out, fmt, ap); | |
133 | va_end(ap); | |
7c673cae FG |
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 | struct pollfd pfd; | |
185 | int status; | |
186 | ssize_t read_status; | |
187 | char c; | |
188 | ||
189 | if (!cl) | |
190 | return -EINVAL; | |
191 | else if (cl->rdl.status == RDLINE_EXITED) | |
192 | return RDLINE_EXITED; | |
193 | ||
194 | pfd.fd = cl->s_in; | |
195 | pfd.events = POLLIN; | |
196 | pfd.revents = 0; | |
197 | ||
198 | status = poll(&pfd, 1, 0); | |
199 | if (status < 0) | |
200 | return status; | |
201 | else if (status > 0) { | |
202 | c = -1; | |
203 | read_status = read(cl->s_in, &c, 1); | |
204 | if (read_status < 0) | |
205 | return read_status; | |
206 | ||
207 | status = cmdline_in(cl, &c, 1); | |
208 | if (status < 0 && cl->rdl.status != RDLINE_EXITED) | |
209 | return status; | |
210 | } | |
211 | ||
212 | return cl->rdl.status; | |
213 | } | |
214 | ||
215 | void | |
216 | cmdline_interact(struct cmdline *cl) | |
217 | { | |
218 | char c; | |
219 | ||
220 | if (!cl) | |
221 | return; | |
222 | ||
223 | c = -1; | |
224 | while (1) { | |
225 | if (read(cl->s_in, &c, 1) <= 0) | |
226 | break; | |
227 | if (cmdline_in(cl, &c, 1) < 0) | |
228 | break; | |
229 | } | |
230 | } |