1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation. 3 * Copyright (c) 2009, Olivier MATZ <[email protected]> 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 <poll.h> 15 #include <errno.h> 16 #include <termios.h> 17 #include <netinet/in.h> 18 19 #include <rte_string_fns.h> 20 21 #include "cmdline_parse.h" 22 #include "cmdline_rdline.h" 23 #include "cmdline.h" 24 25 static void 26 cmdline_valid_buffer(struct rdline *rdl, const char *buf, 27 __attribute__((unused)) unsigned int size) 28 { 29 struct cmdline *cl = rdl->opaque; 30 int ret; 31 ret = cmdline_parse(cl, buf); 32 if (ret == CMDLINE_PARSE_AMBIGUOUS) 33 cmdline_printf(cl, "Ambiguous command\n"); 34 else if (ret == CMDLINE_PARSE_NOMATCH) 35 cmdline_printf(cl, "Command not found\n"); 36 else if (ret == CMDLINE_PARSE_BAD_ARGS) 37 cmdline_printf(cl, "Bad arguments\n"); 38 } 39 40 static int 41 cmdline_complete_buffer(struct rdline *rdl, const char *buf, 42 char *dstbuf, unsigned int dstsize, 43 int *state) 44 { 45 struct cmdline *cl = rdl->opaque; 46 return cmdline_complete(cl, buf, state, dstbuf, dstsize); 47 } 48 49 int 50 cmdline_write_char(struct rdline *rdl, char c) 51 { 52 int ret = -1; 53 struct cmdline *cl; 54 55 if (!rdl) 56 return -1; 57 58 cl = rdl->opaque; 59 60 if (cl->s_out >= 0) 61 ret = write(cl->s_out, &c, 1); 62 63 return ret; 64 } 65 66 67 void 68 cmdline_set_prompt(struct cmdline *cl, const char *prompt) 69 { 70 if (!cl || !prompt) 71 return; 72 strlcpy(cl->prompt, prompt, sizeof(cl->prompt)); 73 } 74 75 struct cmdline * 76 cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) 77 { 78 struct cmdline *cl; 79 int ret; 80 81 if (!ctx || !prompt) 82 return NULL; 83 84 cl = malloc(sizeof(struct cmdline)); 85 if (cl == NULL) 86 return NULL; 87 memset(cl, 0, sizeof(struct cmdline)); 88 cl->s_in = s_in; 89 cl->s_out = s_out; 90 cl->ctx = ctx; 91 92 ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, 93 cmdline_complete_buffer); 94 if (ret != 0) { 95 free(cl); 96 return NULL; 97 } 98 99 cl->rdl.opaque = cl; 100 cmdline_set_prompt(cl, prompt); 101 rdline_newline(&cl->rdl, cl->prompt); 102 103 return cl; 104 } 105 106 void 107 cmdline_free(struct cmdline *cl) 108 { 109 dprintf("called\n"); 110 111 if (!cl) 112 return; 113 114 if (cl->s_in > 2) 115 close(cl->s_in); 116 if (cl->s_out != cl->s_in && cl->s_out > 2) 117 close(cl->s_out); 118 free(cl); 119 } 120 121 void 122 cmdline_printf(const struct cmdline *cl, const char *fmt, ...) 123 { 124 va_list ap; 125 126 if (!cl || !fmt) 127 return; 128 129 if (cl->s_out < 0) 130 return; 131 va_start(ap, fmt); 132 vdprintf(cl->s_out, fmt, ap); 133 va_end(ap); 134 } 135 136 int 137 cmdline_in(struct cmdline *cl, const char *buf, int size) 138 { 139 const char *history, *buffer; 140 size_t histlen, buflen; 141 int ret = 0; 142 int i, same; 143 144 if (!cl || !buf) 145 return -1; 146 147 for (i=0; i<size; i++) { 148 ret = rdline_char_in(&cl->rdl, buf[i]); 149 150 if (ret == RDLINE_RES_VALIDATED) { 151 buffer = rdline_get_buffer(&cl->rdl); 152 history = rdline_get_history_item(&cl->rdl, 0); 153 if (history) { 154 histlen = strnlen(history, RDLINE_BUF_SIZE); 155 same = !memcmp(buffer, history, histlen) && 156 buffer[histlen] == '\n'; 157 } 158 else 159 same = 0; 160 buflen = strnlen(buffer, RDLINE_BUF_SIZE); 161 if (buflen > 1 && !same) 162 rdline_add_history(&cl->rdl, buffer); 163 rdline_newline(&cl->rdl, cl->prompt); 164 } 165 else if (ret == RDLINE_RES_EOF) 166 return -1; 167 else if (ret == RDLINE_RES_EXITED) 168 return -1; 169 } 170 return i; 171 } 172 173 void 174 cmdline_quit(struct cmdline *cl) 175 { 176 if (!cl) 177 return; 178 rdline_quit(&cl->rdl); 179 } 180 181 int 182 cmdline_poll(struct cmdline *cl) 183 { 184 struct pollfd pfd; 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 pfd.fd = cl->s_in; 195 pfd.events = POLLIN; 196 pfd.revents = 0; 197 198 status = poll(&pfd, 1, 0); 199 if (status < 0) 200 return status; 201 else if (status > 0) { 202 c = -1; 203 read_status = read(cl->s_in, &c, 1); 204 if (read_status < 0) 205 return read_status; 206 207 status = cmdline_in(cl, &c, 1); 208 if (status < 0 && cl->rdl.status != RDLINE_EXITED) 209 return status; 210 } 211 212 return cl->rdl.status; 213 } 214 215 void 216 cmdline_interact(struct cmdline *cl) 217 { 218 char c; 219 220 if (!cl) 221 return; 222 223 c = -1; 224 while (1) { 225 if (read(cl->s_in, &c, 1) <= 0) 226 break; 227 if (cmdline_in(cl, &c, 1) < 0) 228 break; 229 } 230 } 231