common/cnxk: fix null pointer dereference
[dpdk.git] / lib / 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 <errno.h>
13
14 #include <rte_string_fns.h>
15
16 #include "cmdline_private.h"
17
18 static void
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
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
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
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 *
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*
99 cmdline_get_rdline(struct cmdline *cl)
100 {
101         return &cl->rdl;
102 }
103
104 void
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
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
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
172 cmdline_quit(struct cmdline *cl)
173 {
174         if (!cl)
175                 return;
176         rdline_quit(&cl->rdl);
177 }
178
179 int
180 cmdline_poll(struct cmdline *cl)
181 {
182         int status;
183         ssize_t read_status;
184         char c;
185
186         if (!cl)
187                 return -EINVAL;
188         else if (cl->rdl.status == RDLINE_EXITED)
189                 return RDLINE_EXITED;
190
191         status = cmdline_poll_char(cl);
192         if (status < 0)
193                 return status;
194         else if (status > 0) {
195                 c = -1;
196                 read_status = cmdline_read_char(cl, &c);
197                 if (read_status < 0)
198                         return read_status;
199
200                 status = cmdline_in(cl, &c, 1);
201                 if (status < 0 && cl->rdl.status != RDLINE_EXITED)
202                         return status;
203         }
204
205         return cl->rdl.status;
206 }
207
208 void
209 cmdline_interact(struct cmdline *cl)
210 {
211         char c;
212
213         if (!cl)
214                 return;
215
216         c = -1;
217         while (1) {
218                 if (cmdline_read_char(cl, &c) <= 0)
219                         break;
220                 if (cmdline_in(cl, &c, 1) < 0)
221                         break;
222         }
223 }