xref: /dpdk/lib/cmdline/cmdline.c (revision f44f2edd198a552b3ede6a1a10e4cf552b3e8b4b)
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