net: provide IP-related API on any OS
[dpdk.git] / lib / librte_cmdline / cmdline.c
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 }