xref: /f-stack/dpdk/lib/librte_cmdline/cmdline.c (revision 2d9fd380)
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