--- libaitcli/src/aitcli.c 2022/12/05 22:23:38 1.19 +++ libaitcli/src/aitcli.c 2025/12/21 23:21:40 1.21.2.2 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitcli.c,v 1.19 2022/12/05 22:23:38 misho Exp $ +* $Id: aitcli.c,v 1.21.2.2 2025/12/21 23:21:40 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2022 +Copyright 2004 - 2025 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -186,12 +186,18 @@ bufEOL(int idx, void * __restrict cli_buffer) static int bufEOF(int idx, void * __restrict cli_buffer) { + int ret; + /* if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) return RETCODE_ERR; */ - return RETCODE_EOF; + printfNL(cli_buffer, 0); + ret = cli_Cmd_End(cli_buffer, idx, NULL); + printfCR(cli_buffer, (ret != RETCODE_EOF)); + + return ret; } static int @@ -425,7 +431,7 @@ bufComp(int idx, void * __restrict cli_buffer) str_Trim(s); } - i = j = 0; + j = 0; c = NULL; memset(szLine, 0, STRSIZ); if (*s) { @@ -520,6 +526,7 @@ static int bufEndNode(int idx, void * __restrict cli_buffer) { linebuffer_t *buf = cli_buffer; + char szPrompt[STRSIZ + 16] = {[0 ... STRSIZ + 15] = 0}; if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) return RETCODE_ERR; @@ -527,6 +534,8 @@ bufEndNode(int idx, void * __restrict cli_buffer) if (buf->line_level > 0) { printfNL(cli_buffer, 0); buf->line_level--; + snprintf(szPrompt, sizeof szPrompt, "%s{%d}> ", buf->line_porigin, buf->line_level); + cli_setPrompt(buf, szPrompt); cli_Printf(buf, "Enter to config level %d\n", buf->line_level); } @@ -549,7 +558,7 @@ cli_Printf(linebuffer_t * __restrict cli_buffer, char FILE *f; if (fmt) { - f = fdopen(cli_buffer->line_out, "a"); + f = fdopen(dup(cli_buffer->line_out), "a"); if (!f) { LOGERR; return; @@ -558,6 +567,8 @@ cli_Printf(linebuffer_t * __restrict cli_buffer, char va_start(lst, fmt); vfprintf(f, fmt, lst); va_end(lst); + + fclose(f); } else cli_SetErr(EINVAL, "Invalid input parameters ..."); } @@ -967,6 +978,11 @@ cliEnd(linebuffer_t * __restrict cli_buffer) if (cli_buffer->line_buf) e_free(cli_buffer->line_buf); + if (cli_buffer->line_inkeys) + e_free(cli_buffer->line_inkeys); + if (cli_buffer->line_input) + e_free(cli_buffer->line_input); + e_free(cli_buffer); cli_buffer = NULL; } else @@ -985,7 +1001,7 @@ linebuffer_t * cliInit(int fin, int fout, const char *prompt) { linebuffer_t *cli_buffer; - bindkey_t *keys; + bindkey_t *keys, *inkeys; register int i; char szPrompt[STRSIZ + 16] = {[0 ... STRSIZ + 15] = 0}; @@ -1038,6 +1054,17 @@ cliInit(int fin, int fout, const char *prompt) return NULL; } else memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1)); + inkeys = e_calloc(MAX_BINDKEY + 1, sizeof(bindkey_t)); + if (!inkeys) { + LOGERR; + e_free(keys); + if (cli_buffer->line_prompt) + e_free(cli_buffer->line_prompt); + e_free(cli_buffer->line_buf); + e_free(cli_buffer); + return NULL; + } else + memset(inkeys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1)); /* add helper functions */ cli_addCommand(cli_buffer, "exit", 1, cli_Cmd_Exit, "exit ", "Exit from console"); @@ -1054,8 +1081,8 @@ cliInit(int fin, int fout, const char *prompt) /* fill key bindings */ /* ascii chars & ctrl+chars */ for (i = 0; i < 256; i++) { - *keys[i].key_ch = (u_char) i; - keys[i].key_len = 1; + *keys[i].key_ch = *inkeys[i].key_ch = (u_char) i; + keys[i].key_len = inkeys[i].key_len = 1; if (!i || i == *K_CTRL_D) keys[i].key_func = bufEOF; @@ -1082,175 +1109,223 @@ cliInit(int fin, int fout, const char *prompt) } /* alt+chars */ for (i = 256; i < 512; i++) { - keys[i].key_ch[0] = 0x1b; - keys[i].key_ch[1] = (u_char) i - 256; - keys[i].key_len = 2; + keys[i].key_ch[0] = inkeys[i].key_ch[0] = 0x1b; + keys[i].key_ch[1] = inkeys[i].key_ch[1] = (u_char) i - 256; + keys[i].key_len = inkeys[i].key_len = 2; } /* 3 bytes */ - keys[i].key_len = sizeof K_F1 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F1 - 1; memcpy(keys[i].key_ch, K_F1, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F1, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F2 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F2 - 1; memcpy(keys[i].key_ch, K_F2, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F2, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F3 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F3 - 1; memcpy(keys[i].key_ch, K_F3, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F3, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F4 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F4 - 1; memcpy(keys[i].key_ch, K_F4, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F4, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F1 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F1 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F1, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F1, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F2 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F2 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F2, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F2, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F3 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F3 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F3, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F3, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F4 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F4 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F4, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F4, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F5 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F5 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F5, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F5, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F6 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F6 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F6, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F6, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F7 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F7 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F7, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F7, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F8 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F8 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F8, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F8, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F9 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F9 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F9, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F9, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F10 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F10 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F10, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F10, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F11 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F11 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F11, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F11, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_SH_F12 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_SH_F12 - 1; memcpy(keys[i].key_ch, K_CTRL_SH_F12, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_SH_F12, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F1 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F1 - 1; memcpy(keys[i].key_ch, K_CTRL_F1, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F1, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F2 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F2 - 1; memcpy(keys[i].key_ch, K_CTRL_F2, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F2, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F3 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F3 - 1; memcpy(keys[i].key_ch, K_CTRL_F3, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F3, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F4 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F4 - 1; memcpy(keys[i].key_ch, K_CTRL_F4, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F4, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F5 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F5 - 1; memcpy(keys[i].key_ch, K_CTRL_F5, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F5, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F6 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F6 - 1; memcpy(keys[i].key_ch, K_CTRL_F6, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F6, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F7 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F7 - 1; memcpy(keys[i].key_ch, K_CTRL_F7, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F7, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F8 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F8 - 1; memcpy(keys[i].key_ch, K_CTRL_F8, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F8, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F9 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F9 - 1; memcpy(keys[i].key_ch, K_CTRL_F9, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F9, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F10 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F10 - 1; memcpy(keys[i].key_ch, K_CTRL_F10, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F10, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F11 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F11 - 1; memcpy(keys[i].key_ch, K_CTRL_F11, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F11, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_CTRL_F12 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_CTRL_F12 - 1; memcpy(keys[i].key_ch, K_CTRL_F12, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_CTRL_F12, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_HOME - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_HOME - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufBEGIN; memcpy(keys[i].key_ch, K_HOME, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_HOME, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_END - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_END - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufEND; memcpy(keys[i].key_ch, K_END, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_END, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_UP - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_UP - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufUP; memcpy(keys[i].key_ch, K_UP, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_UP, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_DOWN - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_DOWN - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufDOWN; memcpy(keys[i].key_ch, K_DOWN, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_DOWN, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_RIGHT - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_RIGHT - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufRIGHT; memcpy(keys[i].key_ch, K_RIGHT, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_RIGHT, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_LEFT - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_LEFT - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufLEFT; memcpy(keys[i].key_ch, K_LEFT, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_LEFT, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_BTAB - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_BTAB - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufBTAB; memcpy(keys[i].key_ch, K_BTAB, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_BTAB, inkeys[i].key_len); i++; /* 4 bytes */ - keys[i].key_len = sizeof K_INS - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_INS - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufMODE; memcpy(keys[i].key_ch, K_INS, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_INS, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_DEL - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_DEL - 1; if (cli_buffer->line_prompt) keys[i].key_func = bufDEL; memcpy(keys[i].key_ch, K_DEL, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_DEL, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_PGUP - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_PGUP - 1; memcpy(keys[i].key_ch, K_PGUP, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_PGUP, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_PGDN - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_PGDN - 1; memcpy(keys[i].key_ch, K_PGDN, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_PGDN, inkeys[i].key_len); i++; /* 5 bytes */ - keys[i].key_len = sizeof K_F5 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F5 - 1; memcpy(keys[i].key_ch, K_F5, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F5, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F6 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F6 - 1; memcpy(keys[i].key_ch, K_F6, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F6, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F7 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F7 - 1; memcpy(keys[i].key_ch, K_F7, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F7, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F8 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F8 - 1; memcpy(keys[i].key_ch, K_F8, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F8, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F9 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F9 - 1; memcpy(keys[i].key_ch, K_F9, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F9, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F10 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F10 - 1; memcpy(keys[i].key_ch, K_F10, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F10, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F11 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F11 - 1; memcpy(keys[i].key_ch, K_F11, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F11, inkeys[i].key_len); i++; - keys[i].key_len = sizeof K_F12 - 1; + keys[i].key_len = inkeys[i].key_len = sizeof K_F12 - 1; memcpy(keys[i].key_ch, K_F12, keys[i].key_len); + memcpy(inkeys[i].key_ch, K_F12, inkeys[i].key_len); i++; cli_buffer->line_keys = keys; + cli_buffer->line_inkeys = inkeys; return cli_buffer; } @@ -1292,6 +1367,31 @@ cliResetLine(linebuffer_t * __restrict cli_buffer, str } /* + * cliEcho() - Switch echo on or off + * + * @cli_buffer = CLI buffer + * @on = On or off for echo on input handler + * return: -1 error or 0 ok +*/ +int +cliEcho(linebuffer_t * __restrict cli_buffer, int on) +{ + struct termios t; + + if (tcgetattr(cli_buffer->line_in, &t) == -1) { + cli_SetErr(errno, "tcgetattr(%d) - %s", cli_buffer->line_in, strerror(errno)); + return -1; + } + + if (on) + t.c_lflag |= (ECHO); + else + t.c_lflag &= ~(ECHO); + + return tcsetattr(cli_buffer->line_in, TCSANOW, &t); +} + +/* * cliReadLine() - Read line from opened CLI session * * @cli_buffer = CLI buffer @@ -1499,7 +1599,6 @@ int cliRun(linebuffer_t * __restrict cli_buffer, char *psInput, int prompt) { char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS]; - register int i; int ret = RETCODE_OK; struct tagCommand *cmd; @@ -1521,14 +1620,11 @@ cliRun(linebuffer_t * __restrict cli_buffer, char *psI (*app = strsep(&s, " \t")); *app ? app++ : app); // exec_cmd ... - i = 0; SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next) { if (!(cmd->cmd_level & (1 << cli_buffer->line_level))) continue; if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0]))) break; - else - i++; } if (!cmd) {