xref: /dpdk/lib/cmdline/cmdline.c (revision f44f2edd198a552b3ede6a1a10e4cf552b3e8b4b)
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
cmdline_valid_buffer(struct rdline * rdl,const char * buf,__rte_unused unsigned int size)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
cmdline_complete_buffer(struct rdline * rdl,const char * buf,char * dstbuf,unsigned int dstsize,int * state)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
cmdline_write_char(struct rdline * rdl,char c)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
cmdline_set_prompt(struct cmdline * cl,const char * prompt)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 *
cmdline_new(cmdline_parse_ctx_t * ctx,const char * prompt,int s_in,int s_out)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*
cmdline_get_rdline(struct cmdline * cl)99 cmdline_get_rdline(struct cmdline *cl)
100 {
101 	return &cl->rdl;
102 }
103 
104 void
cmdline_free(struct cmdline * cl)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
cmdline_printf(const struct cmdline * cl,const char * fmt,...)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
cmdline_in(struct cmdline * cl,const char * buf,int size)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
cmdline_quit(struct cmdline * cl)172 cmdline_quit(struct cmdline *cl)
173 {
174 	if (!cl)
175 		return;
176 	cmdline_cancel(cl);
177 	rdline_quit(&cl->rdl);
178 }
179 
180 void
cmdline_interact(struct cmdline * cl)181 cmdline_interact(struct cmdline *cl)
182 {
183 	char c;
184 
185 	if (!cl)
186 		return;
187 
188 	c = -1;
189 	while (1) {
190 		if (cmdline_read_char(cl, &c) <= 0)
191 			break;
192 		if (cmdline_in(cl, &c, 1) < 0)
193 			break;
194 	}
195 }
196