first public release
[dpdk.git] / lib / librte_cmdline / cmdline.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
33  *  version: DPDK.L.1.2.3-3
34  */
35
36 /*
37  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
38  * All rights reserved.
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  *     * Redistributions of source code must retain the above copyright
43  *       notice, this list of conditions and the following disclaimer.
44  *     * Redistributions in binary form must reproduce the above copyright
45  *       notice, this list of conditions and the following disclaimer in the
46  *       documentation and/or other materials provided with the distribution.
47  *     * Neither the name of the University of California, Berkeley nor the
48  *       names of its contributors may be used to endorse or promote products
49  *       derived from this software without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
52  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
55  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62
63 #include <stdio.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <stdlib.h>
67 #include <stdarg.h>
68 #include <inttypes.h>
69 #include <fcntl.h>
70 #include <errno.h>
71 #include <termios.h>
72 #include <netinet/in.h>
73
74 #include <rte_string_fns.h>
75
76 #include "cmdline_parse.h"
77 #include "cmdline_rdline.h"
78 #include "cmdline.h"
79
80 static void
81 cmdline_valid_buffer(struct rdline *rdl, const char *buf,
82                      __attribute__((unused)) unsigned int size)
83 {
84         struct cmdline *cl = rdl->opaque;
85         int ret;
86         ret = cmdline_parse(cl, buf);
87         if (ret == CMDLINE_PARSE_AMBIGUOUS)
88                 cmdline_printf(cl, "Ambiguous command\n");
89         else if (ret == CMDLINE_PARSE_NOMATCH)
90                 cmdline_printf(cl, "Command not found\n");
91         else if (ret == CMDLINE_PARSE_BAD_ARGS)
92                 cmdline_printf(cl, "Bad arguments\n");
93 }
94
95 static int
96 cmdline_complete_buffer(struct rdline *rdl, const char *buf,
97                         char *dstbuf, unsigned int dstsize,
98                         int *state)
99 {
100         struct cmdline *cl = rdl->opaque;
101         return cmdline_complete(cl, buf, state, dstbuf, dstsize);
102 }
103
104 int
105 cmdline_write_char(struct rdline *rdl, char c)
106 {
107         int ret = -1;
108         struct cmdline *cl = rdl->opaque;
109
110         if (cl->s_out >= 0)
111                 ret = write(cl->s_out, &c, 1);
112
113         return ret;
114 }
115
116
117 void
118 cmdline_set_prompt(struct cmdline *cl, const char *prompt)
119 {
120         rte_snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt);
121 }
122
123 struct cmdline *
124 cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out)
125 {
126         struct cmdline *cl;
127         cl = malloc(sizeof(struct cmdline));
128         if (cl == NULL)
129                 return NULL;
130         memset(cl, 0, sizeof(struct cmdline));
131         cl->s_in = s_in;
132         cl->s_out = s_out;
133         cl->ctx = ctx;
134
135         rdline_init(&cl->rdl, cmdline_write_char,
136                     cmdline_valid_buffer, cmdline_complete_buffer);
137         cl->rdl.opaque = cl;
138         cmdline_set_prompt(cl, prompt);
139         rdline_newline(&cl->rdl, cl->prompt);
140
141         return cl;
142 }
143
144 void
145 cmdline_free(struct cmdline *cl)
146 {
147         dprintf("called\n");
148         if (cl->s_in > 2)
149                 close(cl->s_in);
150         if (cl->s_out != cl->s_in && cl->s_out > 2)
151                 close(cl->s_out);
152         free(cl);
153 }
154
155 void
156 cmdline_printf(const struct cmdline *cl, const char *fmt, ...)
157 {
158         va_list ap;
159
160 #ifdef _GNU_SOURCE
161         if (cl->s_out < 0)
162                 return;
163         va_start(ap, fmt);
164         vdprintf(cl->s_out, fmt, ap);
165         va_end(ap);
166 #else
167         int ret;
168         char *buf;
169
170         if (cl->s_out < 0)
171                 return;
172
173         buf = malloc(BUFSIZ);
174         if (buf == NULL)
175                 return;
176         va_start(ap, fmt);
177         ret = vsnprintf(buf, BUFSIZ, fmt, ap);
178         va_end(ap);
179         if (ret < 0)
180                 return;
181         if (ret >= BUFSIZ)
182                 ret = BUFSIZ - 1;
183         write(cl->s_out, buf, ret);
184         free(buf);
185 #endif
186 }
187
188 int
189 cmdline_in(struct cmdline *cl, const char *buf, int size)
190 {
191         const char *history, *buffer;
192         size_t histlen, buflen;
193         int ret = 0;
194         int i, same;
195
196         for (i=0; i<size; i++) {
197                 ret = rdline_char_in(&cl->rdl, buf[i]);
198
199                 if (ret == RDLINE_RES_VALIDATED) {
200                         buffer = rdline_get_buffer(&cl->rdl);
201                         history = rdline_get_history_item(&cl->rdl, 0);
202                         if (history) {
203                                 histlen = strnlen(history, RDLINE_BUF_SIZE);
204                                 same = !memcmp(buffer, history, histlen) &&
205                                         buffer[histlen] == '\n';
206                         }
207                         else
208                                 same = 0;
209                         buflen = strnlen(buffer, RDLINE_BUF_SIZE);
210                         if (buflen > 1 && !same)
211                                 rdline_add_history(&cl->rdl, buffer);
212                         rdline_newline(&cl->rdl, cl->prompt);
213                 }
214                 else if (ret == RDLINE_RES_EOF)
215                         return -1;
216                 else if (ret == RDLINE_RES_EXITED)
217                         return -1;
218         }
219         return i;
220 }
221
222 void
223 cmdline_quit(struct cmdline *cl)
224 {
225         rdline_quit(&cl->rdl);
226 }
227
228 void
229 cmdline_interact(struct cmdline *cl)
230 {
231         char c;
232
233         c = -1;
234         while (1) {
235                 if (read(cl->s_in, &c, 1) < 0)
236                         break;
237                 if (cmdline_in(cl, &c, 1) < 0)
238                         break;
239         }
240 }