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