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