xref: /f-stack/dpdk/lib/librte_cmdline/cmdline.c (revision ebf5cedb)
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 <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;
72 	strlcpy(cl->prompt, prompt, sizeof(cl->prompt));
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 
129 	if (cl->s_out < 0)
130 		return;
131 	va_start(ap, fmt);
132 	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 	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 }
231