xref: /dpdk/lib/cmdline/cmdline.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
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, cl);
89 	if (ret != 0) {
90 		free(cl);
91 		return NULL;
92 	}
93 
94 	cmdline_set_prompt(cl, prompt);
95 	rdline_newline(&cl->rdl, cl->prompt);
96 
97 	return cl;
98 }
99 
100 struct rdline*
101 cmdline_get_rdline(struct cmdline *cl)
102 {
103 	return &cl->rdl;
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 	cmdline_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 	int status;
185 	ssize_t read_status;
186 	char c;
187 
188 	if (!cl)
189 		return -EINVAL;
190 	else if (cl->rdl.status == RDLINE_EXITED)
191 		return RDLINE_EXITED;
192 
193 	status = cmdline_poll_char(cl);
194 	if (status < 0)
195 		return status;
196 	else if (status > 0) {
197 		c = -1;
198 		read_status = cmdline_read_char(cl, &c);
199 		if (read_status < 0)
200 			return read_status;
201 
202 		status = cmdline_in(cl, &c, 1);
203 		if (status < 0 && cl->rdl.status != RDLINE_EXITED)
204 			return status;
205 	}
206 
207 	return cl->rdl.status;
208 }
209 
210 void
211 cmdline_interact(struct cmdline *cl)
212 {
213 	char c;
214 
215 	if (!cl)
216 		return;
217 
218 	c = -1;
219 	while (1) {
220 		if (cmdline_read_char(cl, &c) <= 0)
221 			break;
222 		if (cmdline_in(cl, &c, 1) < 0)
223 			break;
224 	}
225 }
226