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