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