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