199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation.
399a2dd95SBruce Richardson * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
499a2dd95SBruce Richardson * All rights reserved.
599a2dd95SBruce Richardson */
699a2dd95SBruce Richardson
799a2dd95SBruce Richardson #include <stdio.h>
899a2dd95SBruce Richardson #include <string.h>
999a2dd95SBruce Richardson #include <unistd.h>
1099a2dd95SBruce Richardson #include <stdlib.h>
1199a2dd95SBruce Richardson #include <stdarg.h>
1299a2dd95SBruce Richardson #include <errno.h>
1399a2dd95SBruce Richardson
1499a2dd95SBruce Richardson #include <rte_string_fns.h>
1599a2dd95SBruce Richardson
1699a2dd95SBruce Richardson #include "cmdline_private.h"
1799a2dd95SBruce Richardson
1899a2dd95SBruce Richardson static void
cmdline_valid_buffer(struct rdline * rdl,const char * buf,__rte_unused unsigned int size)1999a2dd95SBruce Richardson cmdline_valid_buffer(struct rdline *rdl, const char *buf,
2099a2dd95SBruce Richardson __rte_unused unsigned int size)
2199a2dd95SBruce Richardson {
2299a2dd95SBruce Richardson struct cmdline *cl = rdl->opaque;
2399a2dd95SBruce Richardson int ret;
2499a2dd95SBruce Richardson ret = cmdline_parse(cl, buf);
2599a2dd95SBruce Richardson if (ret == CMDLINE_PARSE_AMBIGUOUS)
2699a2dd95SBruce Richardson cmdline_printf(cl, "Ambiguous command\n");
2799a2dd95SBruce Richardson else if (ret == CMDLINE_PARSE_NOMATCH)
2899a2dd95SBruce Richardson cmdline_printf(cl, "Command not found\n");
2999a2dd95SBruce Richardson else if (ret == CMDLINE_PARSE_BAD_ARGS)
3099a2dd95SBruce Richardson cmdline_printf(cl, "Bad arguments\n");
3199a2dd95SBruce Richardson }
3299a2dd95SBruce Richardson
3399a2dd95SBruce Richardson static int
cmdline_complete_buffer(struct rdline * rdl,const char * buf,char * dstbuf,unsigned int dstsize,int * state)3499a2dd95SBruce Richardson cmdline_complete_buffer(struct rdline *rdl, const char *buf,
3599a2dd95SBruce Richardson char *dstbuf, unsigned int dstsize,
3699a2dd95SBruce Richardson int *state)
3799a2dd95SBruce Richardson {
3899a2dd95SBruce Richardson struct cmdline *cl = rdl->opaque;
3999a2dd95SBruce Richardson return cmdline_complete(cl, buf, state, dstbuf, dstsize);
4099a2dd95SBruce Richardson }
4199a2dd95SBruce Richardson
4299a2dd95SBruce Richardson int
cmdline_write_char(struct rdline * rdl,char c)4399a2dd95SBruce Richardson cmdline_write_char(struct rdline *rdl, char c)
4499a2dd95SBruce Richardson {
4599a2dd95SBruce Richardson int ret = -1;
4699a2dd95SBruce Richardson struct cmdline *cl;
4799a2dd95SBruce Richardson
4899a2dd95SBruce Richardson if (!rdl)
4999a2dd95SBruce Richardson return -1;
5099a2dd95SBruce Richardson
5199a2dd95SBruce Richardson cl = rdl->opaque;
5299a2dd95SBruce Richardson
5399a2dd95SBruce Richardson if (cl->s_out >= 0)
5499a2dd95SBruce Richardson ret = write(cl->s_out, &c, 1);
5599a2dd95SBruce Richardson
5699a2dd95SBruce Richardson return ret;
5799a2dd95SBruce Richardson }
5899a2dd95SBruce Richardson
5999a2dd95SBruce Richardson
6099a2dd95SBruce Richardson void
cmdline_set_prompt(struct cmdline * cl,const char * prompt)6199a2dd95SBruce Richardson cmdline_set_prompt(struct cmdline *cl, const char *prompt)
6299a2dd95SBruce Richardson {
6399a2dd95SBruce Richardson if (!cl || !prompt)
6499a2dd95SBruce Richardson return;
6599a2dd95SBruce Richardson strlcpy(cl->prompt, prompt, sizeof(cl->prompt));
6699a2dd95SBruce Richardson }
6799a2dd95SBruce Richardson
6899a2dd95SBruce Richardson struct cmdline *
cmdline_new(cmdline_parse_ctx_t * ctx,const char * prompt,int s_in,int s_out)6999a2dd95SBruce Richardson cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out)
7099a2dd95SBruce Richardson {
7199a2dd95SBruce Richardson struct cmdline *cl;
7299a2dd95SBruce Richardson int ret;
7399a2dd95SBruce Richardson
7499a2dd95SBruce Richardson if (!ctx || !prompt)
7599a2dd95SBruce Richardson return NULL;
7699a2dd95SBruce Richardson
7799a2dd95SBruce Richardson cl = malloc(sizeof(struct cmdline));
7899a2dd95SBruce Richardson if (cl == NULL)
7999a2dd95SBruce Richardson return NULL;
8099a2dd95SBruce Richardson memset(cl, 0, sizeof(struct cmdline));
8199a2dd95SBruce Richardson cl->s_in = s_in;
8299a2dd95SBruce Richardson cl->s_out = s_out;
8399a2dd95SBruce Richardson cl->ctx = ctx;
8499a2dd95SBruce Richardson
8599a2dd95SBruce Richardson ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer,
86f8f8dc28SDmitry Kozlyuk cmdline_complete_buffer, cl);
8799a2dd95SBruce Richardson if (ret != 0) {
8899a2dd95SBruce Richardson free(cl);
8999a2dd95SBruce Richardson return NULL;
9099a2dd95SBruce Richardson }
9199a2dd95SBruce Richardson
9299a2dd95SBruce Richardson cmdline_set_prompt(cl, prompt);
9399a2dd95SBruce Richardson rdline_newline(&cl->rdl, cl->prompt);
9499a2dd95SBruce Richardson
9599a2dd95SBruce Richardson return cl;
9699a2dd95SBruce Richardson }
9799a2dd95SBruce Richardson
9899a2dd95SBruce Richardson struct rdline*
cmdline_get_rdline(struct cmdline * cl)9999a2dd95SBruce Richardson cmdline_get_rdline(struct cmdline *cl)
10099a2dd95SBruce Richardson {
10199a2dd95SBruce Richardson return &cl->rdl;
10299a2dd95SBruce Richardson }
10399a2dd95SBruce Richardson
10499a2dd95SBruce Richardson void
cmdline_free(struct cmdline * cl)10599a2dd95SBruce Richardson cmdline_free(struct cmdline *cl)
10699a2dd95SBruce Richardson {
10799a2dd95SBruce Richardson dprintf("called\n");
10899a2dd95SBruce Richardson
10999a2dd95SBruce Richardson if (!cl)
11099a2dd95SBruce Richardson return;
11199a2dd95SBruce Richardson
11299a2dd95SBruce Richardson if (cl->s_in > 2)
11399a2dd95SBruce Richardson close(cl->s_in);
11499a2dd95SBruce Richardson if (cl->s_out != cl->s_in && cl->s_out > 2)
11599a2dd95SBruce Richardson close(cl->s_out);
11699a2dd95SBruce Richardson free(cl);
11799a2dd95SBruce Richardson }
11899a2dd95SBruce Richardson
11999a2dd95SBruce Richardson void
cmdline_printf(const struct cmdline * cl,const char * fmt,...)12099a2dd95SBruce Richardson cmdline_printf(const struct cmdline *cl, const char *fmt, ...)
12199a2dd95SBruce Richardson {
12299a2dd95SBruce Richardson va_list ap;
12399a2dd95SBruce Richardson
12499a2dd95SBruce Richardson if (!cl || !fmt)
12599a2dd95SBruce Richardson return;
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson if (cl->s_out < 0)
12899a2dd95SBruce Richardson return;
12999a2dd95SBruce Richardson va_start(ap, fmt);
13099a2dd95SBruce Richardson cmdline_vdprintf(cl->s_out, fmt, ap);
13199a2dd95SBruce Richardson va_end(ap);
13299a2dd95SBruce Richardson }
13399a2dd95SBruce Richardson
13499a2dd95SBruce Richardson int
cmdline_in(struct cmdline * cl,const char * buf,int size)13599a2dd95SBruce Richardson cmdline_in(struct cmdline *cl, const char *buf, int size)
13699a2dd95SBruce Richardson {
13799a2dd95SBruce Richardson const char *history, *buffer;
13899a2dd95SBruce Richardson size_t histlen, buflen;
13999a2dd95SBruce Richardson int ret = 0;
14099a2dd95SBruce Richardson int i, same;
14199a2dd95SBruce Richardson
14299a2dd95SBruce Richardson if (!cl || !buf)
14399a2dd95SBruce Richardson return -1;
14499a2dd95SBruce Richardson
14599a2dd95SBruce Richardson for (i=0; i<size; i++) {
14699a2dd95SBruce Richardson ret = rdline_char_in(&cl->rdl, buf[i]);
14799a2dd95SBruce Richardson
14899a2dd95SBruce Richardson if (ret == RDLINE_RES_VALIDATED) {
14999a2dd95SBruce Richardson buffer = rdline_get_buffer(&cl->rdl);
15099a2dd95SBruce Richardson history = rdline_get_history_item(&cl->rdl, 0);
15199a2dd95SBruce Richardson if (history) {
15299a2dd95SBruce Richardson histlen = strnlen(history, RDLINE_BUF_SIZE);
15399a2dd95SBruce Richardson same = !memcmp(buffer, history, histlen) &&
15499a2dd95SBruce Richardson buffer[histlen] == '\n';
15599a2dd95SBruce Richardson }
15699a2dd95SBruce Richardson else
15799a2dd95SBruce Richardson same = 0;
15899a2dd95SBruce Richardson buflen = strnlen(buffer, RDLINE_BUF_SIZE);
15999a2dd95SBruce Richardson if (buflen > 1 && !same)
16099a2dd95SBruce Richardson rdline_add_history(&cl->rdl, buffer);
16199a2dd95SBruce Richardson rdline_newline(&cl->rdl, cl->prompt);
16299a2dd95SBruce Richardson }
16399a2dd95SBruce Richardson else if (ret == RDLINE_RES_EOF)
16499a2dd95SBruce Richardson return -1;
16599a2dd95SBruce Richardson else if (ret == RDLINE_RES_EXITED)
16699a2dd95SBruce Richardson return -1;
16799a2dd95SBruce Richardson }
16899a2dd95SBruce Richardson return i;
16999a2dd95SBruce Richardson }
17099a2dd95SBruce Richardson
17199a2dd95SBruce Richardson void
cmdline_quit(struct cmdline * cl)17299a2dd95SBruce Richardson cmdline_quit(struct cmdline *cl)
17399a2dd95SBruce Richardson {
17499a2dd95SBruce Richardson if (!cl)
17599a2dd95SBruce Richardson return;
176*f1d0993eSStephen Hemminger cmdline_cancel(cl);
17799a2dd95SBruce Richardson rdline_quit(&cl->rdl);
17899a2dd95SBruce Richardson }
17999a2dd95SBruce Richardson
18099a2dd95SBruce Richardson void
cmdline_interact(struct cmdline * cl)18199a2dd95SBruce Richardson cmdline_interact(struct cmdline *cl)
18299a2dd95SBruce Richardson {
18399a2dd95SBruce Richardson char c;
18499a2dd95SBruce Richardson
18599a2dd95SBruce Richardson if (!cl)
18699a2dd95SBruce Richardson return;
18799a2dd95SBruce Richardson
18899a2dd95SBruce Richardson c = -1;
18999a2dd95SBruce Richardson while (1) {
19099a2dd95SBruce Richardson if (cmdline_read_char(cl, &c) <= 0)
19199a2dd95SBruce Richardson break;
19299a2dd95SBruce Richardson if (cmdline_in(cl, &c, 1) < 0)
19399a2dd95SBruce Richardson break;
19499a2dd95SBruce Richardson }
19599a2dd95SBruce Richardson }
196