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, cl); 89 if (ret != 0) { 90 free(cl); 91 return NULL; 92 } 93 94 cmdline_set_prompt(cl, prompt); 95 rdline_newline(&cl->rdl, cl->prompt); 96 97 return cl; 98 } 99 100 struct rdline* 101 cmdline_get_rdline(struct cmdline *cl) 102 { 103 return &cl->rdl; 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 cmdline_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 int status; 185 ssize_t read_status; 186 char c; 187 188 if (!cl) 189 return -EINVAL; 190 else if (cl->rdl.status == RDLINE_EXITED) 191 return RDLINE_EXITED; 192 193 status = cmdline_poll_char(cl); 194 if (status < 0) 195 return status; 196 else if (status > 0) { 197 c = -1; 198 read_status = cmdline_read_char(cl, &c); 199 if (read_status < 0) 200 return read_status; 201 202 status = cmdline_in(cl, &c, 1); 203 if (status < 0 && cl->rdl.status != RDLINE_EXITED) 204 return status; 205 } 206 207 return cl->rdl.status; 208 } 209 210 void 211 cmdline_interact(struct cmdline *cl) 212 { 213 char c; 214 215 if (!cl) 216 return; 217 218 c = -1; 219 while (1) { 220 if (cmdline_read_char(cl, &c) <= 0) 221 break; 222 if (cmdline_in(cl, &c, 1) < 0) 223 break; 224 } 225 } 226