File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / Attic / cli.c
Revision 1.1.2.5: download - view: text, annotated - select for diffs - revision graph
Thu Mar 18 23:40:56 2010 UTC (14 years, 5 months ago) by misho
Branches: io1_1
added flush stream

/*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
*  by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: cli.c,v 1.1.2.5 2010/03/18 23:40:56 misho Exp $
*
*************************************************************************/
#include "global.h"


/*
 * io_Cmd_Exit() Builtin helper function for Exit from Cli
 * @cmds = Commands list
 * @out = Output handle
 * @args = Parsed arguments array
 * return: 1 exit from Cli!
*/
int io_Cmd_Exit(void *cmds, FILE *out, char ** __restrict args)
{
	return 1;
}

/*
 * io_Cmd_Help() Builtin helper function for Help screen
 * @cmds = Commands list
 * @out = Output handle
 * @args = Parsed arguments array
 * return: -1 error, 0 = ok
*/
int io_Cmd_Help(void *cmds, FILE *out, char ** __restrict args)
{
	register int i;
	ioCommands_t *commands = cmds;

	if (!cmds)
		return -1;

	if (!args) {
		fprintf(out, "\n");
		fflush(out);
		for (i = 0; commands[i].cmd_name; i++) {
			fprintf(out, "%s\t\t%s\n", commands[i].cmd_name, commands[i].cmd_doc);
			fflush(out);
		}
	} else {
		if (!args[1]) {
			fprintf(out, "Help screen::\n");
			fflush(out);
		} else
			if (!strncmp(args[1], "---", 3))
				return 0;

		for (i = 0; commands[i].cmd_name; i++) {
			if (args[1] && strcmp(args[1], commands[i].cmd_name))
				continue;

			fprintf(out, "%s%s\t\t%s\n", args[1] ? "Syntax::\n\t" : "", commands[i].cmd_name, 
					args[1] ? commands[i].cmd_help : commands[i].cmd_doc);
			fflush(out);
		}
	}

	return 0;
}

/*
 * io_Cmd_Unsupported() Builtin helper function for unsupported commands
 * @cmds = Commands list
 * @out = Output handle
 * @args = Parsed arguments array
 * return: -1 error, 0 = ok, 1 exit from Cli!
*/
int io_Cmd_Unsupported(void *cmds, FILE *out, char ** __restrict args)
{
	fprintf(out, "Command %s not supported in this version ...\n", args[0]);
	fflush(out);
	return 0;
}

// ------------------------------------------------------------

/*
 * io_Comp_Filename() Builtin helper function for filename completion arguments
 * @text = Text line
 * @state = Position state
 * return: NULL not found filename, != NULL filename
*/
char *io_Comp_Filename(const char *text, int state)
{
	return rl_filename_completion_function(text, state);
}

// ------------------------------------------------------------

#pragma GCC visibility push(hidden)

ioCommands_t io_stdCmds[] = {
	{ "test", io_Cmd_Unsupported, "Test - Don`t use default command structure!", "test <cr>", io_Comp_Filename }, 
	{ "-------", NULL, "---------------------", NULL, NULL }, 
	{ "help", io_Cmd_Help, "Help screen", "help [command] <cr>", NULL }, 
	{ "exit", io_Cmd_Exit, "Exit from console", "exit <cr>", NULL }, 
	{ NULL, NULL, NULL, NULL }
};

#pragma GCC visibility pop

// ------------------------------------------------------------

/*
 * ioCLIComp() Initialize completion CLI features
 * @cmdComplete = Completion function
 * @cmdEntry = Compentry function
 * return: none
*/
inline void ioCLIComp(io_Completion_t *cmdComplete, io_CompEntry_t *cmdEntry)
{
	// command completon
	rl_attempted_completion_function = cmdComplete;
	rl_completion_entry_function = cmdEntry;
}

/*
 * ioCLIExec() Execute CLI main loop
 * @cmdList = Commands list
 * @out = Output handle
 * @csPrompt = Prompt text
 * return: -1 error, 0 = exit w/^+D, 1 done.
*/
int ioCLIExec(ioCommands_t *cmdList, FILE *out, const char *csPrompt)
{
	char *line, *s, *t, **app, *items[20];
	int ret = 0;
	register int i;
	ioCommands_t *cmd = NULL;

	inline int inline_help()
	{
		io_Cmd_Help(cmdList ? cmdList : io_stdCmds, out, NULL);
		rl_on_new_line();
		return 0;
	}

	char **io_stdCompletion(const char *text, int start, int end)
	{
		register int i;
		char **matches = NULL;

		char *cmdCompGet(const char *text, int state)
		{
			int len = strlen(text);

			for (i = state; cmdList[i].cmd_name; i++) {
				if (strncmp(cmdList[i].cmd_name, "---", 3) && 
						!strncmp(cmdList[i].cmd_name, text, len))
					return strdup(cmdList[i].cmd_name);
			}

			return NULL;
		}

		if (!start)
			matches = rl_completion_matches(text, cmdCompGet);
		else
			for (i = 0; cmdList[i].cmd_name; i++) {
				if (!cmdList[i].cmd_comp)
					continue;
				if (!strncmp(rl_line_buffer, cmdList[i].cmd_name, strlen(cmdList[i].cmd_name)))
					matches = rl_completion_matches(text, cmdList[i].cmd_comp);
			}

		return matches;
	}
	char *io_stdCompEntry(const char *ignore, int invoking_key)
	{
		return NULL;
	}

	rl_bind_key('?', inline_help);
	if (!rl_attempted_completion_function) 
		ioCLIComp(io_stdCompletion, io_stdCompEntry);

	do {
		line = readline(csPrompt);
		if (!line) {	// ^+d
			fprintf(out, "\n");
			fflush(out);
			break;
		}
		// clear whitespaces
		for (s = line; isspace(*s); s++);
		if (*s) {
			for (t = s + strlen(s) - 1; t > s && isspace(*t); t--);
			*++t = 0;
		}

		if (*s) {
			add_history(s);

			memset(items, 0, sizeof(char*) * 20);
			for (app = items; app < items + 19 && (*app = strsep(&s, " \t")); *app ? app++ : app);

			/*
			for (i = 0; i < 20; i++)
				printf("i=%d %s\n", i, items[i]);
				*/

			// exec_cmd ...
			for (cmd = NULL, i = 0; cmdList[i].cmd_name; i++)
				if (*items[0] && !strncmp(cmdList[i].cmd_name, items[0], strlen(items[0]))) {
					cmd = &cmdList[i];
					break;
				}
			if (!cmd) {
				fprintf(out, "Command '%s' not found!\n", items[0]);
				fflush(out);
				ret = -1;
			} else
				ret = cmd->cmd_func(cmdList, out, items);
		}

		free(line);
	} while (ret < 1);

	return ret;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>