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