|
|
| version 1.2.2.5, 2010/06/07 09:04:46 | version 1.2.2.15, 2010/06/08 08:43:47 |
|---|---|
| Line 7 | Line 7 |
| * | * |
| *************************************************************************/ | *************************************************************************/ |
| #include "global.h" | #include "global.h" |
| #include "cli.h" | |
| #pragma GCC visibility push(hidden) | #pragma GCC visibility push(hidden) |
| /* | |
| commands_t cli_stdCmds[] = { | |
| { "test", cli_Cmd_Unsupported, "Test - Don`t use default command structure!", "test <cr>", cli_Comp_Filename }, | |
| { "-------", NULL, "---------------------", NULL, NULL }, | |
| { "help", cli_Cmd_Help, "Help screen", "help [command] <cr>", NULL }, | |
| { "exit", cli_Cmd_Exit, "Exit from console", "exit <cr>", NULL }, | |
| { NULL, NULL, NULL, NULL } | |
| }; | |
| */ | |
| // ------------------------------------------------ | // ------------------------------------------------ |
| int cli_Errno; | int cli_Errno; |
| Line 107 printfNL(linebuffer_t * __restrict buf, int prompt) | Line 98 printfNL(linebuffer_t * __restrict buf, int prompt) |
| } | } |
| } | } |
| static inline void | |
| printfCLI(linebuffer_t * __restrict buf, const unsigned char *text, int textlen, int prompt) | |
| { | |
| if (buf && text && textlen) { | |
| if (prompt && buf->line_prompt) | |
| write(buf->line_out, buf->line_prompt, buf->line_bol); | |
| write(buf->line_out, text, textlen); | |
| } | |
| } | |
| // ------------------------------------------------------------ | // ------------------------------------------------------------ |
| static int | static int |
| Line 144 bufCHAR(int idx, void * __restrict buffer) | Line 124 bufCHAR(int idx, void * __restrict buffer) |
| write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len); | write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len); |
| if (buf->line_mode == LINEMODE_INS) { | if (buf->line_mode == LINEMODE_INS) { |
| printfCLI(buf, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, | write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, |
| buf->line_len - buf->line_eol, 0); | buf->line_len - buf->line_eol); |
| printfEOL(buf, -1, 1); | printfEOL(buf, -1, 1); |
| } | } |
| return RETCODE_OK; | return RETCODE_OK; |
| Line 164 bufEOL(int idx, void * __restrict buffer) | Line 144 bufEOL(int idx, void * __restrict buffer) |
| static int | static int |
| bufEOF(int idx, void * __restrict buffer) | bufEOF(int idx, void * __restrict buffer) |
| { | { |
| linebuffer_t *buf = buffer; | /* |
| if (!buffer || idx < 0 || idx > MAX_BINDKEY) | if (!buffer || idx < 0 || idx > MAX_BINDKEY) |
| return RETCODE_ERR; | return RETCODE_ERR; |
| */ | |
| write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len); | |
| return RETCODE_EOF; | return RETCODE_EOF; |
| } | } |
| Line 383 bufDEL(int idx, void * __restrict buffer) | Line 362 bufDEL(int idx, void * __restrict buffer) |
| return RETCODE_OK; | return RETCODE_OK; |
| } | } |
| static int | |
| bufComp(int idx, void * __restrict buffer) | |
| { | |
| linebuffer_t *buf = buffer; | |
| char *str, *s, **app, *items[MAX_PROMPT_ITEMS], szLine[STRSIZ]; | |
| register int i, j; | |
| struct tagCommand *cmd, *c; | |
| int pos, ret = RETCODE_OK; | |
| if (!buffer || idx < 0 || idx > MAX_BINDKEY) | |
| return RETCODE_ERR; | |
| str = strdup(buf->line_buf); | |
| if (!str) | |
| return RETCODE_ERR; | |
| else { | |
| s = str; | |
| io_TrimStr((u_char*) s); | |
| } | |
| i = j = 0; | |
| c = NULL; | |
| memset(szLine, 0, STRSIZ); | |
| if (*s) { | |
| memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS); | |
| for (app = items, i = 0; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t")); | |
| *app ? i++ : i, *app ? app++ : app); | |
| if (i) { | |
| SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) { | |
| if (cmd->cmd_level == buf->line_level && | |
| !strncmp(cmd->cmd_name, items[0], strlen(items[0]))) { | |
| if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) { | |
| j++; | |
| c = cmd; | |
| strlcat(szLine, " ", STRSIZ); | |
| strlcat(szLine, cmd->cmd_name, STRSIZ); | |
| } | |
| } | |
| } | |
| if (i > 1 && c) { | |
| /* we are on argument of command and has complition info */ | |
| j++; // always must be j > 1 ;) for arguments | |
| strlcpy(szLine, c->cmd_info, STRSIZ); | |
| } | |
| } else { | |
| /* we have valid char but i == 0, this case is illegal */ | |
| ret = RETCODE_ERR; | |
| goto endcomp; | |
| } | |
| } else { | |
| /* we on 0 position of prompt, show commands for this level */ | |
| SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) { | |
| if (cmd->cmd_level == buf->line_level) | |
| if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) { | |
| j++; | |
| c = cmd; | |
| strlcat(szLine, " ", STRSIZ); | |
| strlcat(szLine, cmd->cmd_name, STRSIZ); | |
| } | |
| } | |
| } | |
| /* completion show actions ... */ | |
| if (j > 1 && c) { | |
| printfNL(buf, 0); | |
| write(buf->line_out, szLine, strlen(szLine)); | |
| printfNL(buf, 1); | |
| printfEOL(buf, buf->line_len - 1, 1); | |
| printfEOL(buf, -1, 1); | |
| } | |
| if (j == 1 && c) { | |
| clrscrEOL(buf); | |
| cli_freeLine(buf); | |
| pos = buf->line_eol - buf->line_bol; | |
| buf->line_len += c->cmd_len + 1; | |
| buf->line_eol += c->cmd_len + 1; | |
| memcpy(buf->line_buf + pos, c->cmd_name, c->cmd_len); | |
| buf->line_buf[pos + c->cmd_len] = (u_char) *K_SPACE; | |
| buf->line_buf[buf->line_len - 1] = 0; | |
| printfEOL(buf, -1, 1); | |
| } | |
| endcomp: | |
| free(str); | |
| return ret; | |
| } | |
| static int | |
| bufHelp(int idx, void * __restrict buffer) | |
| { | |
| linebuffer_t *buf = buffer; | |
| if (!buffer || idx < 0 || idx > MAX_BINDKEY) | |
| return RETCODE_ERR; | |
| cli_Cmd_Help(buf, -1, NULL); | |
| printfEOL(buf, buf->line_len - 1, 1); | |
| printfEOL(buf, -1, 1); | |
| return RETCODE_OK; | |
| } | |
| // --------------------------------------------------------------- | // --------------------------------------------------------------- |
| /* | /* |
| Line 413 cli_Printf(linebuffer_t * __restrict buffer, char *fmt | Line 500 cli_Printf(linebuffer_t * __restrict buffer, char *fmt |
| } | } |
| /* | /* |
| * cli_PrintHelp() Print help screen | |
| * @buffer = CLI buffer | |
| * return: none | |
| */ | |
| inline void | |
| cli_PrintHelp(linebuffer_t * __restrict buffer) | |
| { | |
| if (buffer) | |
| bufHelp(0, buffer); | |
| else | |
| cli_SetErr(EINVAL, "Error:: invalid input parameters ..."); | |
| } | |
| /* | |
| * cli_BindKey() Bind function to key | * cli_BindKey() Bind function to key |
| * @key = key structure | * @key = key structure |
| * @buffer = CLI buffer | * @buffer = CLI buffer |
| Line 440 cli_BindKey(bindkey_t * __restrict key, linebuffer_t * | Line 542 cli_BindKey(bindkey_t * __restrict key, linebuffer_t * |
| /* | /* |
| * cli_addCommand() Add command to CLI session | |
| * @buffer = CLI buffer | |
| * @csCmd = Command name | |
| * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... | |
| * @funcCmd = Callback function when user call command | |
| * @csInfo = Inline information for command | |
| * @csHelp = Help line when call help | |
| * return: RETCODE_ERR error, RETCODE_OK ok | |
| */ | |
| int | |
| cli_addCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd, | |
| const char *csInfo, const char *csHelp) | |
| { | |
| struct tagCommand *cmd; | |
| if (!buffer || !csCmd) { | |
| cli_SetErr(EINVAL, "Error:: invalid input parameters ..."); | |
| return RETCODE_ERR; | |
| } | |
| cmd = malloc(sizeof(struct tagCommand)); | |
| if (!cmd) { | |
| LOGERR; | |
| return RETCODE_ERR; | |
| } else | |
| memset(cmd, 0, sizeof(struct tagCommand)); | |
| cmd->cmd_level = cliLevel; | |
| cmd->cmd_func = funcCmd; | |
| cmd->cmd_len = strlcpy(cmd->cmd_name, csCmd, STRSIZ); | |
| if (csInfo) | |
| strlcpy(cmd->cmd_info, csInfo, STRSIZ); | |
| if (csHelp) | |
| strlcpy(cmd->cmd_help, csHelp, STRSIZ); | |
| SLIST_INSERT_HEAD(&buffer->line_cmds, cmd, cmd_next); | |
| return RETCODE_OK; | |
| } | |
| /* | |
| * cli_delCommand() Delete command from CLI session | |
| * @buffer = CLI buffer | |
| * @csCmd = Command name | |
| * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... | |
| * return: RETCODE_ERR error, RETCODE_OK ok | |
| */ | |
| int | |
| cli_delCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel) | |
| { | |
| struct tagCommand *cmd; | |
| int ret = RETCODE_OK; | |
| if (!buffer || !csCmd) { | |
| cli_SetErr(EINVAL, "Error:: invalid input parameters ..."); | |
| return RETCODE_ERR; | |
| } | |
| SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) | |
| if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) { | |
| ret = 1; | |
| SLIST_REMOVE(&buffer->line_cmds, cmd, tagCommand, cmd_next); | |
| free(cmd); | |
| break; | |
| } | |
| return ret; | |
| } | |
| /* | |
| * cli_updCommand() Update command in CLI session | |
| * @buffer = CLI buffer | |
| * @csCmd = Command name | |
| * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... | |
| * @funcCmd = Callback function when user call command | |
| * @csInfo = Inline information for command | |
| * @csHelp = Help line when call help | |
| * return: RETCODE_ERR error, RETCODE_OK ok | |
| */ | |
| int | |
| cli_updCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd, | |
| const char *csInfo, const char *csHelp) | |
| { | |
| struct tagCommand *cmd; | |
| int ret = RETCODE_OK; | |
| if (!buffer || !csCmd) { | |
| cli_SetErr(EINVAL, "Error:: invalid input parameters ..."); | |
| return RETCODE_ERR; | |
| } | |
| SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) | |
| if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) { | |
| ret = 1; | |
| if (funcCmd) | |
| cmd->cmd_func = funcCmd; | |
| if (csInfo) | |
| strlcpy(cmd->cmd_info, csInfo, STRSIZ); | |
| if (csHelp) | |
| strlcpy(cmd->cmd_help, csHelp, STRSIZ); | |
| break; | |
| } | |
| return ret; | |
| } | |
| /* | |
| * cli_addHistory() Add line to history | * cli_addHistory() Add line to history |
| * @buffer = CLI buffer | * @buffer = CLI buffer |
| * @str = Add custom text or if NULL use readed line from CLI buffer | * @str = Add custom text or if NULL use readed line from CLI buffer |
| Line 745 cliInit(int fin, int fout, const char *prompt) | Line 955 cliInit(int fin, int fout, const char *prompt) |
| } else | } else |
| memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1)); | memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1)); |
| /* add helper functions */ | |
| cli_addCommand(buffer, "exit", 0, cli_Cmd_Exit, "exit <cr>", "Exit from console"); | |
| cli_addCommand(buffer, "help", 0, cli_Cmd_Help, "help [command] <cr>", "Help screen"); | |
| cli_addCommand(buffer, "-------", 0, NULL, "-------------------------", NULL); | |
| /* fill key bindings */ | /* fill key bindings */ |
| // ascii chars & ctrl+chars | // ascii chars & ctrl+chars |
| for (i = 0; i < 256; i++) { | for (i = 0; i < 256; i++) { |
| Line 763 cliInit(int fin, int fout, const char *prompt) | Line 978 cliInit(int fin, int fout, const char *prompt) |
| keys[i].key_func = bufBEGIN; | keys[i].key_func = bufBEGIN; |
| if (i == *K_CTRL_E) | if (i == *K_CTRL_E) |
| keys[i].key_func = bufEND; | keys[i].key_func = bufEND; |
| if (i == *K_TAB) | |
| keys[i].key_func = bufComp; | |
| if (i >= *K_SPACE && i < *K_BACKSPACE) | if (i >= *K_SPACE && i < *K_BACKSPACE) |
| keys[i].key_func = bufCHAR; | keys[i].key_func = bufCHAR; |
| if (i > *K_BACKSPACE && i < 0xff) | if (i > *K_BACKSPACE && i < 0xff) |
| keys[i].key_func = bufCHAR; | keys[i].key_func = bufCHAR; |
| if (i == '?') | |
| keys[i].key_func = bufHelp; | |
| } | } |
| // alt+chars | // alt+chars |
| for (i = 256; i < 512; i++) { | for (i = 256; i < 512; i++) { |
| Line 1040 cliNetLoop(linebuffer_t * __restrict buffer, const cha | Line 1259 cliNetLoop(linebuffer_t * __restrict buffer, const cha |
| case 0: | case 0: |
| close(sock); | close(sock); |
| // buffer = cliInit(STDIN_FILENO, STDOUT_FILENO, csPrompt); | if (buffer) |
| // if (!buffer) | ret = cliLoop(buffer, csHistFile) < 0 ? 1 : 0; |
| // return RETCODE_ERR; | else |
| cli_SetErr(EINVAL, "Error:: invalid input parameters ..."); | |
| ret = cliLoop(buffer, csHistFile) < 0 ? 1 : 0; | |
| // cliEnd(buffer); | |
| /* spawn Shell mode */ | /* spawn Shell mode */ |
| /* | /* |
| execl("/bin/tcsh", "tcsh", NULL); | execl("/bin/tcsh", "tcsh", NULL); |
| Line 1141 cliLoop(linebuffer_t * __restrict buffer, const char * | Line 1357 cliLoop(linebuffer_t * __restrict buffer, const char * |
| int ret = RETCODE_OK; | int ret = RETCODE_OK; |
| struct tagCommand *cmd; | struct tagCommand *cmd; |
| /* | |
| inline int inline_help() | |
| { | |
| cli_Cmd_Help(cmdList ? cmdList : cli_stdCmds, -1, out, NULL); | |
| rl_on_new_line(); | |
| return 0; | |
| } | |
| char **cli_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; | |
| } | |
| */ | |
| /* --- main body of CLI --- */ | /* --- main body of CLI --- */ |
| if (cli_loadHistory(buffer, csHistFile) == RETCODE_ERR) | if (cli_loadHistory(buffer, csHistFile) == RETCODE_ERR) |
| Line 1220 cliLoop(linebuffer_t * __restrict buffer, const char * | Line 1394 cliLoop(linebuffer_t * __restrict buffer, const char * |
| cli_Printf(buffer, "\nCommand '%s' not found!\n", items[0]); | cli_Printf(buffer, "\nCommand '%s' not found!\n", items[0]); |
| ret = -1; | ret = -1; |
| } else | } else |
| ret = cmd->cmd_func(buffer, i, items); | if (cmd->cmd_func) |
| ret = cmd->cmd_func(buffer, i, items); | |
| else { | |
| clrscrEOL(buffer); | |
| printfCR(buffer, 1); | |
| } | |
| } | } |
| cli_freeLine(buffer); | cli_freeLine(buffer); |