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 } 227