--- libaitcli/src/aitcli.c 2025/12/17 23:30:11 1.20 +++ libaitcli/src/aitcli.c 2025/12/24 00:00:53 1.21.2.4 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitcli.c,v 1.20 2025/12/17 23:30:11 misho Exp $ +* $Id: aitcli.c,v 1.21.2.4 2025/12/24 00:00:53 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -84,6 +84,33 @@ cli_SetErr(int eno, char *estr, ...) // ------------------------------------------------------------ static inline void +rewindin(linebuffer_t * __restrict buf, int len) +{ + int ign __attribute__((unused)); + + if (buf) { + if (len == -1) + len = buf->line_posin; + while (len-- > 0) + ign = write(buf->line_out, K_CTRL_H, 1); + } +} + +static inline void +clrscrEOLin(linebuffer_t * __restrict buf) +{ + register int i; + int ign __attribute__((unused)); + + if (buf) { + rewindin(buf, -1); + + for (i = 0; i < buf->line_lenin; i++) + ign = write(buf->line_out, K_SPACE, 1); + } +} + +static inline void clrscrEOL(linebuffer_t * __restrict buf) { register int i; @@ -98,15 +125,24 @@ clrscrEOL(linebuffer_t * __restrict buf) } static inline void +printfEOLin(linebuffer_t * __restrict buf) +{ + int ign __attribute__((unused)); + + if (buf) + ign = write(buf->line_out, buf->line_input, buf->line_lenin); +} + +static inline void printfEOL(linebuffer_t * __restrict buf, int len, int prompt) { int ign __attribute__((unused)); if (buf) { - if (prompt && buf->line_prompt) { - ign = write(buf->line_out, K_CR, 1); + ign = write(buf->line_out, K_CR, 1); + + if (prompt && buf->line_prompt) ign = write(buf->line_out, buf->line_prompt, buf->line_bol); - } ign = write(buf->line_out, buf->line_buf, len == -1 ? buf->line_eol - buf->line_bol : len); @@ -118,10 +154,9 @@ printfCR(linebuffer_t * __restrict buf, int prompt) { int ign __attribute__((unused)); - if (buf && prompt && buf->line_prompt) { - ign = write(buf->line_out, K_CR, 1); + ign = write(buf->line_out, K_CR, 1); + if (buf && prompt && buf->line_prompt) ign = write(buf->line_out, buf->line_prompt, buf->line_bol); - } } static inline void @@ -141,6 +176,36 @@ printfNL(linebuffer_t * __restrict buf, int prompt) // ------------------------------------------------------------ static int +bufCHARin(int idx, void * __restrict cli_buffer) +{ + linebuffer_t *buf = cli_buffer; + int pos; + int ign __attribute__((unused)); + + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + pos = buf->line_posin; + + if (buf->line_mode == LINEMODE_INS) + memmove(buf->line_input + pos + buf->line_inkeys[idx].key_len, buf->line_input + pos, + buf->line_lenin - buf->line_posin); + if (buf->line_mode == LINEMODE_INS || buf->line_posin == buf->line_lenin) + buf->line_lenin += buf->line_inkeys[idx].key_len; + buf->line_posin += buf->line_inkeys[idx].key_len; + + memcpy(buf->line_input + pos, buf->line_inkeys[idx].key_ch, buf->line_inkeys[idx].key_len); + buf->line_input[buf->line_lenin] = 0; + + if (buf->line_mode == LINEMODE_INS) { + rewindin(buf, buf->line_posin - buf->line_inkeys[idx].key_len); + printfEOLin(buf); + rewindin(buf, buf->line_lenin - buf->line_posin); + } + return RETCODE_OK; +} + +static int bufCHAR(int idx, void * __restrict cli_buffer) { linebuffer_t *buf = cli_buffer; @@ -174,6 +239,15 @@ bufCHAR(int idx, void * __restrict cli_buffer) } static int +bufEOLin(int idx, void * __restrict cli_buffer) +{ + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + return RETCODE_EOL; +} + +static int bufEOL(int idx, void * __restrict cli_buffer) { if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) @@ -263,6 +337,20 @@ bufDOWN(int idx, void * __restrict cli_buffer) } static int +bufCLRin(int idx, void * __restrict cli_buffer) +{ + linebuffer_t *buf = cli_buffer; + + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + clrscrEOLin(buf); + rewindin(buf, buf->line_lenin); + cli_freeInput(cli_buffer); + return RETCODE_OK; +} + +static int bufCLR(int idx, void * __restrict cli_buffer) { if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) @@ -276,6 +364,33 @@ bufCLR(int idx, void * __restrict cli_buffer) } static int +bufBSin(int idx, void * __restrict cli_buffer) +{ + linebuffer_t *buf = cli_buffer; + + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + if (buf->line_posin > 0) { + clrscrEOLin(buf); + rewindin(buf, -1); + + buf->line_posin--; + buf->line_lenin--; + memmove(buf->line_input + buf->line_posin, + buf->line_input + buf->line_posin + 1, + buf->line_lenin - buf->line_posin); + buf->line_input[buf->line_lenin] = 0; + + rewindin(buf, buf->line_lenin - buf->line_posin); + printfEOLin(buf); + rewindin(buf, buf->line_lenin - buf->line_posin); + } + + return RETCODE_OK; +} + +static int bufBS(int idx, void * __restrict cli_buffer) { linebuffer_t *buf = cli_buffer; @@ -333,6 +448,20 @@ bufMODE(int idx, void * __restrict cli_buffer) } static int +bufBEGINin(int idx, void * __restrict cli_buffer) +{ + linebuffer_t *buf = cli_buffer; + + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + rewindin(buf, -1); + buf->line_posin ^= buf->line_posin; + + return RETCODE_OK; +} + +static int bufBEGIN(int idx, void * __restrict cli_buffer) { linebuffer_t *buf = cli_buffer; @@ -347,6 +476,21 @@ bufBEGIN(int idx, void * __restrict cli_buffer) } static int +bufENDin(int idx, void * __restrict cli_buffer) +{ + linebuffer_t *buf = cli_buffer; + + if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY) + return RETCODE_ERR; + + rewindin(buf, -1); + printfEOLin(buf); + buf->line_posin = buf->line_lenin; + + return RETCODE_OK; +} + +static int bufEND(int idx, void * __restrict cli_buffer) { linebuffer_t *buf = cli_buffer; @@ -558,7 +702,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; @@ -888,6 +1032,28 @@ cli_resetHistory(linebuffer_t * __restrict cli_buffer) /* + * cli_freeInput() - Clear entire input + * + * @cli_buffer = CLI buffer + * return: RETCODE_ERR error, RETCODE_OK ok +*/ +int +cli_freeInput(linebuffer_t * __restrict cli_buffer) +{ + int code = RETCODE_ERR; + + if (cli_buffer) { + memset(cli_buffer->line_input, 0, BUFSIZ); + cli_buffer->line_posin ^= cli_buffer->line_posin; + cli_buffer->line_lenin ^= cli_buffer->line_lenin; + + code = RETCODE_OK; + } else + cli_SetErr(EINVAL, "Invalid input parameters ..."); + + return code; +} +/* * cli_freeLine() - Clear entire line * * @cli_buffer = CLI buffer @@ -899,18 +1065,11 @@ cli_freeLine(linebuffer_t * __restrict cli_buffer) int code = RETCODE_ERR; if (cli_buffer) { - if (cli_buffer->line_buf) - e_free(cli_buffer->line_buf); + memset(cli_buffer->line_buf, 0, BUFSIZ); + cli_buffer->line_eol = cli_buffer->line_bol; + cli_buffer->line_len = 1 + cli_buffer->line_eol; - cli_buffer->line_buf = e_malloc(BUFSIZ); - if (cli_buffer->line_buf) { - memset(cli_buffer->line_buf, 0, BUFSIZ); - cli_buffer->line_eol = cli_buffer->line_bol; - cli_buffer->line_len = 1 + cli_buffer->line_eol; - - code = RETCODE_OK; - } else - LOGERR; + code = RETCODE_OK; } else cli_SetErr(EINVAL, "Invalid input parameters ..."); @@ -978,6 +1137,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 @@ -996,7 +1160,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}; @@ -1039,16 +1203,41 @@ cliInit(int fin, int fout, const char *prompt) memset(cli_buffer->line_buf, 0, BUFSIZ); cli_buffer->line_len = 1 + cli_buffer->line_eol; } + cli_buffer->line_input = e_malloc(BUFSIZ); + if (!cli_buffer->line_input) { + LOGERR; + 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(cli_buffer->line_input, 0, BUFSIZ); + cli_buffer->line_lenin = cli_buffer->line_posin; + } keys = e_calloc(MAX_BINDKEY + 1, sizeof(bindkey_t)); if (!keys) { LOGERR; if (cli_buffer->line_prompt) e_free(cli_buffer->line_prompt); + e_free(cli_buffer->line_input); e_free(cli_buffer->line_buf); e_free(cli_buffer); 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_input); + 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"); @@ -1065,203 +1254,268 @@ 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; - if (i == *K_CTRL_M || i == *K_CTRL_J) + if (i == *K_CTRL_M || i == *K_CTRL_J) { keys[i].key_func = bufEOL; - if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE)) - keys[i].key_func = bufBS; - if (i == *K_CTRL_C) + inkeys[i].key_func = bufEOLin; + } + if (i == *K_CTRL_H || i == *K_BACKSPACE) { + if (cli_buffer->line_prompt) + keys[i].key_func = bufBS; + inkeys[i].key_func = bufBSin; + } + if (i == *K_CTRL_C) { keys[i].key_func = bufCLR; - if (cli_buffer->line_prompt && i == *K_CTRL_A) - keys[i].key_func = bufBEGIN; - if (cli_buffer->line_prompt && i == *K_CTRL_E) - keys[i].key_func = bufEND; + inkeys[i].key_func = bufCLRin; + } + if (i == *K_CTRL_A) { + if (cli_buffer->line_prompt) + keys[i].key_func = bufBEGIN; + inkeys[i].key_func = bufBEGINin; + } + if (i == *K_CTRL_E) { + if (cli_buffer->line_prompt) + keys[i].key_func = bufEND; + inkeys[i].key_func = bufENDin; + } if (cli_buffer->line_prompt && i == *K_TAB) keys[i].key_func = bufComp; if (i == *K_CTRL_Z) keys[i].key_func = bufEndNode; - if (i >= *K_SPACE && i < *K_BACKSPACE) + if (i >= *K_SPACE && i < *K_BACKSPACE) { keys[i].key_func = bufCHAR; - if (i > *K_BACKSPACE && i < 0xff) + inkeys[i].key_func = bufCHARin; + } + if (i > *K_BACKSPACE && i < 0xff) { keys[i].key_func = bufCHAR; + inkeys[i].key_func = bufCHARin; + } if (cli_buffer->line_prompt && i == '?') keys[i].key_func = bufHelp; } /* 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; } @@ -1303,6 +1557,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 @@ -1330,52 +1609,108 @@ cliReadLine(linebuffer_t * __restrict cli_buffer, int printfCR(cli_buffer, 1); while (42) { if ((ret = poll(&fds, 1, timeout)) < 1) { - if (!ret) { + if (!ret) cli_buffer->line_kill = 1; - if (str) { - e_free(str); - str = NULL; - } - } else + else LOGERR; - return str; + return NULL; } memset(buf, 0, sizeof buf); - readLen = read(cli_buffer->line_in, buf, BUFSIZ); + readLen = read(cli_buffer->line_in, buf, sizeof buf - 1); if (readLen < 1) { if (readLen) LOGERR; return NULL; } -recheck: - for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--) - if (readLen >= cli_buffer->line_keys[i].key_len && - !memcmp(cli_buffer->line_keys[i].key_ch, buf, - cli_buffer->line_keys[i].key_len)) { - readLen -= cli_buffer->line_keys[i].key_len; - if (readLen) - memmove(buf, buf + cli_buffer->line_keys[i].key_len, readLen); - else - memset(buf, 0, cli_buffer->line_keys[i].key_len); + while (readLen) + for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--) + if (readLen >= cli_buffer->line_keys[i].key_len && + !memcmp(cli_buffer->line_keys[i].key_ch, buf, + cli_buffer->line_keys[i].key_len)) { + readLen -= cli_buffer->line_keys[i].key_len; + if (readLen) + memmove(buf, buf + cli_buffer->line_keys[i].key_len, readLen); + else + memset(buf, 0, cli_buffer->line_keys[i].key_len); - if (cli_buffer->line_keys[i].key_func) - if ((code = cli_buffer->line_keys[i].key_func(i, cli_buffer))) - readLen = 0; + if (cli_buffer->line_keys[i].key_func) + if ((code = cli_buffer->line_keys[i].key_func(i, cli_buffer))) + readLen = 0; + } - if (readLen) - goto recheck; - else - break; - } - if (code) break; } if (code != RETCODE_ERR && code != RETCODE_EOF && cli_buffer->line_buf) str = e_strdup(cli_buffer->line_buf); + return str; +} + +/* + * cliInputLine() - Input line from opened CLI session + * + * @cli_buffer = CLI buffer + * @timeout = Session timeout (-1 infinit) + * return: NULL if error or !=NULL readed line, must be e_free after use! +*/ +char * +cliInputLine(linebuffer_t * __restrict cli_buffer, int timeout) +{ + int code, readLen, ret; + register int i; + struct pollfd fds; + char buf[BUFSIZ], *str = NULL; + + if (!cli_buffer) { + cli_SetErr(EINVAL, "Invalid input parameters ..."); + return NULL; + } else if (timeout > 0) + timeout *= 1000; /* convert from sec to ms */ + + memset(&fds, 0, sizeof fds); + fds.fd = cli_buffer->line_in; + fds.events = POLLIN; + + while (42) { + if ((ret = poll(&fds, 1, timeout)) < 1) { + if (ret == -1) + LOGERR; + return NULL; + } + + memset(buf, 0, sizeof buf); + readLen = read(cli_buffer->line_in, buf, sizeof buf - 1); + if (readLen < 1) { + if (readLen) + LOGERR; + return NULL; + } + + while (readLen) + for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--) + if (readLen >= cli_buffer->line_inkeys[i].key_len && + !memcmp(cli_buffer->line_inkeys[i].key_ch, buf, + cli_buffer->line_inkeys[i].key_len)) { + readLen -= cli_buffer->line_inkeys[i].key_len; + if (readLen) + memmove(buf, buf + cli_buffer->line_inkeys[i].key_len, readLen); + else + memset(buf, 0, cli_buffer->line_inkeys[i].key_len); + + if (cli_buffer->line_inkeys[i].key_func) + if ((code = cli_buffer->line_inkeys[i].key_func(i, cli_buffer))) + readLen = 0; + } + + if (code) + break; + } + + if (code != RETCODE_ERR && code != RETCODE_EOF && cli_buffer->line_input) + str = e_strdup(cli_buffer->line_input); return str; }