Diff for /libaitcli/src/aitcli.c between versions 1.5.4.3 and 1.21.2.3

version 1.5.4.3, 2013/05/26 20:36:41 version 1.21.2.3, 2025/12/23 23:11:13
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013Copyright 2004 - 2025
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 87  static inline void Line 87  static inline void
 clrscrEOL(linebuffer_t * __restrict buf)  clrscrEOL(linebuffer_t * __restrict buf)
 {  {
         register int i;          register int i;
           int ign __attribute__((unused));
   
        if (buf) {        if (buf && buf->line_prompt) {
                write(buf->line_out, K_CR, 1);                ign = write(buf->line_out, K_CR, 1);
   
                 for (i = 0; i < buf->line_len; i++)                  for (i = 0; i < buf->line_len; i++)
                        write(buf->line_out, K_SPACE, 1);                        ign = write(buf->line_out, K_SPACE, 1);
         }          }
 }  }
   
 static inline void  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
   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)  printfEOL(linebuffer_t * __restrict buf, int len, int prompt)
 {  {
           int ign __attribute__((unused));
   
         if (buf) {          if (buf) {
                write(buf->line_out, K_CR, 1);                ign = write(buf->line_out, K_CR, 1);
   
                 if (prompt && buf->line_prompt)                  if (prompt && buf->line_prompt)
                        write(buf->line_out, buf->line_prompt, buf->line_bol);                        ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
   
                write(buf->line_out, buf->line_buf, len == -1 ? buf->line_eol - buf->line_bol: len);                ign = write(buf->line_out, buf->line_buf, len == -1 ? 
                                 buf->line_eol - buf->line_bol : len);
         }          }
 }  }
   
 static inline void  static inline void
 printfCR(linebuffer_t * __restrict buf, int prompt)  printfCR(linebuffer_t * __restrict buf, int prompt)
 {  {
        if (buf) {        int ign __attribute__((unused));
                write(buf->line_out, K_CR, 1); 
   
                if (prompt)        ign = write(buf->line_out, K_CR, 1);
                        if (prompt && buf->line_prompt)        if (buf && prompt && buf->line_prompt)
                                write(buf->line_out, buf->line_prompt, buf->line_bol);                ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
        } 
 }  }
   
 static inline void  static inline void
 printfNL(linebuffer_t * __restrict buf, int prompt)  printfNL(linebuffer_t * __restrict buf, int prompt)
 {  {
           int ign __attribute__((unused));
   
         if (buf) {          if (buf) {
                write(buf->line_out, K_ENTER, 1);                ign = write(buf->line_out, K_ENTER, 1);
   
                 if (prompt)                  if (prompt)
                         if (prompt && buf->line_prompt)                          if (prompt && buf->line_prompt)
                                write(buf->line_out, buf->line_prompt, buf->line_bol);                                ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
         }          }
 }  }
   
 // ------------------------------------------------------------  // ------------------------------------------------------------
   
 static int  static int
bufCHAR(int idx, void * __restrict buffer)bufCHARin(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
         int pos;          int pos;
           int ign __attribute__((unused));
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  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;
           int pos;
           int ign __attribute__((unused));
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
         pos = buf->line_eol - buf->line_bol;          pos = buf->line_eol - buf->line_bol;
   
         if (buf->line_mode == LINEMODE_INS)          if (buf->line_mode == LINEMODE_INS)
Line 156  bufCHAR(int idx, void * __restrict buffer) Line 213  bufCHAR(int idx, void * __restrict buffer)
         memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);          memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
         buf->line_buf[buf->line_len - 1] = 0;          buf->line_buf[buf->line_len - 1] = 0;
   
        write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);        if (buf->line_prompt)
                 ign = 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) {
                write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len,                 ign = write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, 
                                 buf->line_len - buf->line_eol);                                  buf->line_len - buf->line_eol);
                 printfEOL(buf, -1, 1);                  printfEOL(buf, -1, 1);
         }          }
Line 167  bufCHAR(int idx, void * __restrict buffer) Line 225  bufCHAR(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufEOL(int idx, void * __restrict buffer)bufEOLin(int idx, void * __restrict cli_buffer)
 {  {
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         printfCR(buffer, 1);  
         return RETCODE_EOL;          return RETCODE_EOL;
 }  }
   
 static int  static int
bufEOF(int idx, void * __restrict buffer)bufEOL(int idx, void * __restrict cli_buffer)
 {  {
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           printfCR(cli_buffer, 1);
           return RETCODE_EOL;
   }
   
   static int
   bufEOF(int idx, void * __restrict cli_buffer)
   {
           int ret;
   
         /*          /*
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  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  static int
bufUP(int idx, void * __restrict buffer)bufUP(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
         int pos;          int pos;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (!buf->line_h)          if (!buf->line_h)
Line 219  bufUP(int idx, void * __restrict buffer) Line 292  bufUP(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufDOWN(int idx, void * __restrict buffer)bufDOWN(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
         int pos;          int pos;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (!buf->line_h)          if (!buf->line_h)
Line 250  bufDOWN(int idx, void * __restrict buffer) Line 323  bufDOWN(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufCLR(int idx, void * __restrict buffer)bufCLRin(int idx, void * __restrict cli_buffer)
 {  {
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        linebuffer_t *buf = cli_buffer;
 
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
        clrscrEOL(buffer);        memset(buf->line_input, ' ', buf->line_lenin);
        cli_freeLine(buffer);        rewindin(buf, -1);
         printfEOLin(buf);
         rewindin(buf, -1);
         cli_freeInput(cli_buffer);
         return RETCODE_OK;
 }
   
        printfCR(buffer, 1);static int
 bufCLR(int idx, void * __restrict cli_buffer)
 {
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;
 
         clrscrEOL(cli_buffer);
         cli_freeLine(cli_buffer);
 
         printfCR(cli_buffer, 1);
         return RETCODE_OK;          return RETCODE_OK;
 }  }
   
 static int  static int
bufBS(int idx, void * __restrict buffer)bufBS(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (buf->line_bol < buf->line_eol) {          if (buf->line_bol < buf->line_eol) {
Line 288  bufBS(int idx, void * __restrict buffer) Line 377  bufBS(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufBTAB(int idx, void * __restrict buffer)bufBTAB(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (buf->line_bol < buf->line_eol) {          if (buf->line_bol < buf->line_eol) {
Line 308  bufBTAB(int idx, void * __restrict buffer) Line 397  bufBTAB(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufMODE(int idx, void * __restrict buffer)bufMODE(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         buf->line_mode = !buf->line_mode ? LINEMODE_OVER : LINEMODE_INS;          buf->line_mode = !buf->line_mode ? LINEMODE_OVER : LINEMODE_INS;
Line 320  bufMODE(int idx, void * __restrict buffer) Line 409  bufMODE(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufBEGIN(int idx, void * __restrict buffer)bufBEGINin(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  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;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
         buf->line_eol = buf->line_bol;          buf->line_eol = buf->line_bol;
   
         printfCR(buf, 1);          printfCR(buf, 1);
Line 334  bufBEGIN(int idx, void * __restrict buffer) Line 437  bufBEGIN(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufEND(int idx, void * __restrict buffer)bufENDin(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  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;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
         buf->line_eol = buf->line_len - 1;          buf->line_eol = buf->line_len - 1;
   
         printfEOL(buf, -1, 1);          printfEOL(buf, -1, 1);
Line 348  bufEND(int idx, void * __restrict buffer) Line 466  bufEND(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufLEFT(int idx, void * __restrict buffer)bufLEFT(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (buf->line_bol < buf->line_eol)          if (buf->line_bol < buf->line_eol)
Line 362  bufLEFT(int idx, void * __restrict buffer) Line 480  bufLEFT(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufRIGHT(int idx, void * __restrict buffer)bufRIGHT(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         if (buf->line_eol < buf->line_len - 1)          if (buf->line_eol < buf->line_len - 1)
Line 376  bufRIGHT(int idx, void * __restrict buffer) Line 494  bufRIGHT(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufDEL(int idx, void * __restrict buffer)bufDEL(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         clrscrEOL(buf);          clrscrEOL(buf);
Line 398  bufDEL(int idx, void * __restrict buffer) Line 516  bufDEL(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufComp(int idx, void * __restrict buffer)bufComp(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
         char *str, *s, **app, *items[MAX_PROMPT_ITEMS], szLine[STRSIZ];          char *str, *s, **app, *items[MAX_PROMPT_ITEMS], szLine[STRSIZ];
         register int i, j;          register int i, j;
         struct tagCommand *cmd, *c;          struct tagCommand *cmd, *c;
         int pos, ret = RETCODE_OK;          int pos, ret = RETCODE_OK;
           int ign __attribute__((unused));
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         str = e_strdup(buf->line_buf);          str = e_strdup(buf->line_buf);
Line 417  bufComp(int idx, void * __restrict buffer) Line 536  bufComp(int idx, void * __restrict buffer)
                 str_Trim(s);                  str_Trim(s);
         }          }
   
        i = j = 0;        j = 0;
         c = NULL;          c = NULL;
         memset(szLine, 0, STRSIZ);          memset(szLine, 0, STRSIZ);
         if (*s) {          if (*s) {
                 memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);                  memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
                for (app = items, i = 0; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t"));                 for (app = items, i = 0; app < items + MAX_PROMPT_ITEMS - 1 && 
                                 (*app = strsep(&s, " \t")); 
                                 *app ? i++ : i, *app ? app++ : app);                                  *app ? i++ : i, *app ? app++ : app);
   
                 if (i) {                  if (i) {
                         SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {                          SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {
                                if (cmd->cmd_level == buf->line_level &&                                 if (cmd->cmd_level & (1 << buf->line_level) && 
                                                !strncmp(cmd->cmd_name, items[0], strlen(items[0]))) {                                                !strncmp(cmd->cmd_name, items[0], 
                                        if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) {                                                        strlen(items[0]))) {
                                         if (strncmp(cmd->cmd_name, CLI_CMD_SEP, 
                                                                 strlen(CLI_CMD_SEP))) {
                                                 j++;                                                  j++;
                                                 c = cmd;                                                  c = cmd;
                                                 strlcat(szLine, " ", STRSIZ);                                                  strlcat(szLine, " ", STRSIZ);
Line 451  bufComp(int idx, void * __restrict buffer) Line 573  bufComp(int idx, void * __restrict buffer)
         } else {          } else {
                 /* we on 0 position of prompt, show commands for this level */                  /* we on 0 position of prompt, show commands for this level */
                 SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {                  SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {
                        if (cmd->cmd_level == buf->line_level)                        if (cmd->cmd_level & (1 << buf->line_level))
                                 if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) {                                  if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) {
                                         j++;                                          j++;
                                         c = cmd;                                          c = cmd;
Line 464  bufComp(int idx, void * __restrict buffer) Line 586  bufComp(int idx, void * __restrict buffer)
         /* completion show actions ... */          /* completion show actions ... */
         if (j > 1 && c) {          if (j > 1 && c) {
                 printfNL(buf, 0);                  printfNL(buf, 0);
                write(buf->line_out, szLine, strlen(szLine));                ign = write(buf->line_out, szLine, strlen(szLine));
                 printfNL(buf, 1);                  printfNL(buf, 1);
                 printfEOL(buf, buf->line_len - 1, 1);                  printfEOL(buf, buf->line_len - 1, 1);
                 printfEOL(buf, -1, 1);                  printfEOL(buf, -1, 1);
Line 491  endcomp: Line 613  endcomp:
 }  }
   
 static int  static int
bufHelp(int idx, void * __restrict buffer)bufHelp(int idx, void * __restrict cli_buffer)
 {  {
        linebuffer_t *buf = buffer;        linebuffer_t *buf = cli_buffer;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
        cli_Cmd_Help(buf, -1, NULL);        cli_Cmd_Help(buf, buf->line_level, NULL);
   
         printfEOL(buf, buf->line_len - 1, 1);          printfEOL(buf, buf->line_len - 1, 1);
         printfEOL(buf, -1, 1);          printfEOL(buf, -1, 1);
         return RETCODE_OK;          return RETCODE_OK;
 }  }
   
   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;
   
           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);
           }
   
           return bufCLR(idx, cli_buffer);
   }
   
   
 /*  /*
  * cli_Printf() - Send message to CLI session   * cli_Printf() - Send message to CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @fmt = printf format string   * @fmt = printf format string
  * @... = arguments defined in fmt   * @... = arguments defined in fmt
  * return: none   * return: none
 */  */
 void  void
cli_Printf(linebuffer_t * __restrict buffer, char *fmt, ...)cli_Printf(linebuffer_t * __restrict cli_buffer, char *fmt, ...)
 {  {
         va_list lst;          va_list lst;
         FILE *f;          FILE *f;
   
         if (fmt) {          if (fmt) {
                f = fdopen(buffer->line_out, "a");                f = fdopen(dup(cli_buffer->line_out), "a");
                 if (!f) {                  if (!f) {
                         LOGERR;                          LOGERR;
                         return;                          return;
Line 530  cli_Printf(linebuffer_t * __restrict buffer, char *fmt Line 672  cli_Printf(linebuffer_t * __restrict buffer, char *fmt
                 va_start(lst, fmt);                  va_start(lst, fmt);
                 vfprintf(f, fmt, lst);                  vfprintf(f, fmt, lst);
                 va_end(lst);                  va_end(lst);
   
                   fclose(f);
         } else          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
Line 537  cli_Printf(linebuffer_t * __restrict buffer, char *fmt Line 681  cli_Printf(linebuffer_t * __restrict buffer, char *fmt
 /*  /*
  * cli_PrintHelp() - Print help screen   * cli_PrintHelp() - Print help screen
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * return: none   * return: none
 */  */
 void  void
cli_PrintHelp(linebuffer_t * __restrict buffer)cli_PrintHelp(linebuffer_t * __restrict cli_buffer)
 {  {
        if (buffer) {        if (cli_buffer) {
                bufHelp(0, buffer);                bufHelp(0, cli_buffer);
                clrscrEOL(buffer);                clrscrEOL(cli_buffer);
         } else          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
Line 555  cli_PrintHelp(linebuffer_t * __restrict buffer) Line 699  cli_PrintHelp(linebuffer_t * __restrict buffer)
  * cli_BindKey() - Bind function to key   * cli_BindKey() - Bind function to key
  *   *
  * @key = key structure   * @key = key structure
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok, >0 bind at position   * return: RETCODE_ERR error, RETCODE_OK ok, >0 bind at position
 */  */
 int  int
cli_BindKey(bindkey_t * __restrict key, linebuffer_t * __restrict buffer)cli_BindKey(bindkey_t * __restrict key, linebuffer_t * __restrict cli_buffer)
 {  {
         register int i;          register int i;
   
        if (!key || !buffer) {        if (!key || !cli_buffer) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
         for (i = 0; i < MAX_BINDKEY; i++)          for (i = 0; i < MAX_BINDKEY; i++)
                if (key->key_len == buffer->line_keys[i].key_len &&                 if (key->key_len == cli_buffer->line_keys[i].key_len && 
                                !memcmp(key->key_ch, buffer->line_keys[i].key_ch, key->key_len)) {                                !memcmp(key->key_ch, cli_buffer->line_keys[i].key_ch, 
                        buffer->line_keys[i].key_func = key->key_func;                                        key->key_len)) {
                         cli_buffer->line_keys[i].key_func = key->key_func;
                         return i;                          return i;
                 }                  }
   
Line 582  cli_BindKey(bindkey_t * __restrict key, linebuffer_t * Line 727  cli_BindKey(bindkey_t * __restrict key, linebuffer_t *
 /*  /*
  * cli_addCommand() - Add command to CLI session   * cli_addCommand() - Add command to CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @csCmd = Command name   * @csCmd = Command name
 * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... * @cliLevel = Level in CLI, -1 view from all levels, 0 hidden, >0 mask levels
  * @funcCmd = Callback function when user call command   * @funcCmd = Callback function when user call command
  * @csInfo = Inline information for command   * @csInfo = Inline information for command
  * @csHelp = Help line when call help   * @csHelp = Help line when call help
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_addCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd, cli_addCommand(linebuffer_t * __restrict cli_buffer, const char *csCmd, 
                 int cliLevel, cmd_func_t funcCmd, 
                 const char *csInfo, const char *csHelp)                  const char *csInfo, const char *csHelp)
 {  {
         struct tagCommand *cmd;          struct tagCommand *cmd;
   
        if (!buffer || !csCmd) {        if (!cli_buffer || !csCmd) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
Line 615  cli_addCommand(linebuffer_t * __restrict buffer, const Line 761  cli_addCommand(linebuffer_t * __restrict buffer, const
                 strlcpy(cmd->cmd_info, csInfo, STRSIZ);                  strlcpy(cmd->cmd_info, csInfo, STRSIZ);
         if (csHelp)          if (csHelp)
                 strlcpy(cmd->cmd_help, csHelp, STRSIZ);                  strlcpy(cmd->cmd_help, csHelp, STRSIZ);
        SLIST_INSERT_HEAD(&buffer->line_cmds, cmd, cmd_next);        SLIST_INSERT_HEAD(&cli_buffer->line_cmds, cmd, cmd_next);
         return RETCODE_OK;          return RETCODE_OK;
 }  }
   
 /*  /*
  * cli_delCommand() - Delete command from CLI session   * cli_delCommand() - Delete command from CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @csCmd = Command name   * @csCmd = Command name
 * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... * @cliLevel = Level in CLI, -1 view from all levels, 0 hidden, >0 mask levels
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_delCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel)cli_delCommand(linebuffer_t * __restrict cli_buffer, const char *csCmd, int cliLevel)
 {  {
         struct tagCommand *cmd;          struct tagCommand *cmd;
         int ret = RETCODE_OK;          int ret = RETCODE_OK;
   
        if (!buffer || !csCmd) {        if (!cli_buffer || !csCmd) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next)         SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next) 
                 if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) {                  if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) {
                         ret = 1;                          ret = 1;
                        SLIST_REMOVE(&buffer->line_cmds, cmd, tagCommand, cmd_next);                        SLIST_REMOVE(&cli_buffer->line_cmds, cmd, tagCommand, cmd_next);
                         e_free(cmd);                          e_free(cmd);
                         break;                          break;
                 }                  }
Line 652  cli_delCommand(linebuffer_t * __restrict buffer, const Line 798  cli_delCommand(linebuffer_t * __restrict buffer, const
 /*  /*
  * cli_updCommand() - Update command in CLI session   * cli_updCommand() - Update command in CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @csCmd = Command name   * @csCmd = Command name
 * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ... * @cliLevel = Level in CLI, -1 view from all levels, 0 hidden, >0 mask levels
  * @funcCmd = Callback function when user call command   * @funcCmd = Callback function when user call command
  * @csInfo = Inline information for command   * @csInfo = Inline information for command
  * @csHelp = Help line when call help   * @csHelp = Help line when call help
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_updCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd, cli_updCommand(linebuffer_t * __restrict cli_buffer, const char *csCmd, 
                 int cliLevel, cmd_func_t funcCmd, 
                 const char *csInfo, const char *csHelp)                  const char *csInfo, const char *csHelp)
 {  {
         struct tagCommand *cmd;          struct tagCommand *cmd;
         int ret = RETCODE_OK;          int ret = RETCODE_OK;
   
        if (!buffer || !csCmd) {        if (!cli_buffer || !csCmd) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next)         SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next)
                if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) {                if ((!cmd->cmd_level || cmd->cmd_level == cliLevel) && 
                        ret = 1;                                !strcmp(cmd->cmd_name, csCmd)) {
                        if (!cmd->cmd_level)
                                 cmd->cmd_level = cliLevel;
                         if (funcCmd)                          if (funcCmd)
                                 cmd->cmd_func = funcCmd;                                  cmd->cmd_func = funcCmd;
                         if (csInfo)                          if (csInfo)
Line 693  cli_updCommand(linebuffer_t * __restrict buffer, const Line 841  cli_updCommand(linebuffer_t * __restrict buffer, const
 /*  /*
  * cli_addHistory() - Add line to history   * cli_addHistory() - Add line to history
  *   *
 * @buffer = CLI buffer * @cli_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
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_addHistory(linebuffer_t * __restrict buffer, const char * __restrict str)cli_addHistory(linebuffer_t * __restrict cli_buffer, const char * __restrict str)
 {  {
         struct tagHistory *h;          struct tagHistory *h;
   
        if (!buffer) {        if (!cli_buffer) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
Line 721  cli_addHistory(linebuffer_t * __restrict buffer, const Line 869  cli_addHistory(linebuffer_t * __restrict buffer, const
   
                 h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);                  h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);
         } else {          } else {
                if (!*buffer->line_buf || buffer->line_len < 2) {                if (!*cli_buffer->line_buf || cli_buffer->line_len < 2) {
                         e_free(h);                          e_free(h);
                         return RETCODE_OK;                          return RETCODE_OK;
                 }                  }
   
                memcpy(h->hist_line, buffer->line_buf, (h->hist_len = buffer->line_len));                memcpy(h->hist_line, cli_buffer->line_buf, (h->hist_len = cli_buffer->line_len));
                 str_Trim(h->hist_line);                  str_Trim(h->hist_line);
                 h->hist_len = strlen(h->hist_line);                  h->hist_len = strlen(h->hist_line);
         }          }
   
        TAILQ_INSERT_HEAD(&buffer->line_history, h, hist_next);        TAILQ_INSERT_HEAD(&cli_buffer->line_history, h, hist_next);
         return h->hist_len;          return h->hist_len;
 }  }
   
 /*  /*
  * cli_saveHistory() - Save history to file   * cli_saveHistory() - Save history to file
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @histfile = History filename, if NULL will be use default name   * @histfile = History filename, if NULL will be use default name
  * @lines = Maximum history lines to save   * @lines = Maximum history lines to save
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_saveHistory(linebuffer_t * __restrict buffer, const char *histfile, int lines)cli_saveHistory(linebuffer_t * __restrict cli_buffer, const char *histfile, int lines)
 {  {
         FILE *f;          FILE *f;
         mode_t mode;          mode_t mode;
         char szFName[MAXPATHLEN];          char szFName[MAXPATHLEN];
         struct tagHistory *h;          struct tagHistory *h;
   
        if (!buffer) {        if (!cli_buffer) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
Line 767  cli_saveHistory(linebuffer_t * __restrict buffer, cons Line 915  cli_saveHistory(linebuffer_t * __restrict buffer, cons
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        TAILQ_FOREACH(h, &buffer->line_history, hist_next) {        TAILQ_FOREACH(h, &cli_buffer->line_history, hist_next) {
                 fprintf(f, "%s\n", h->hist_line);                  fprintf(f, "%s\n", h->hist_line);
   
                 if (lines)                  if (lines)
Line 785  cli_saveHistory(linebuffer_t * __restrict buffer, cons Line 933  cli_saveHistory(linebuffer_t * __restrict buffer, cons
 /*  /*
  * cli_loadHistory() - Load history from file   * cli_loadHistory() - Load history from file
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @histfile = History filename, if NULL will be use default name   * @histfile = History filename, if NULL will be use default name
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_loadHistory(linebuffer_t * __restrict buffer, const char *histfile)cli_loadHistory(linebuffer_t * __restrict cli_buffer, const char *histfile)
 {  {
         FILE *f;          FILE *f;
         char szFName[MAXPATHLEN], buf[BUFSIZ];          char szFName[MAXPATHLEN], buf[BUFSIZ];
         struct tagHistory *h;          struct tagHistory *h;
   
        if (!buffer) {        if (!cli_buffer) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
Line 823  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 971  cli_loadHistory(linebuffer_t * __restrict buffer, cons
                         memset(h, 0, sizeof(struct tagHistory));                          memset(h, 0, sizeof(struct tagHistory));
   
                 h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);                  h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);
                TAILQ_INSERT_TAIL(&buffer->line_history, h, hist_next);                TAILQ_INSERT_TAIL(&cli_buffer->line_history, h, hist_next);
         }          }
   
         fclose(f);          fclose(f);
Line 834  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 982  cli_loadHistory(linebuffer_t * __restrict buffer, cons
 /*  /*
  * cli_resetHistory() - Reset history search in CLI session   * cli_resetHistory() - Reset history search in CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * return: none   * return: none
 */  */
 void  void
cli_resetHistory(linebuffer_t * __restrict buffer)cli_resetHistory(linebuffer_t * __restrict cli_buffer)
 {  {
        buffer->line_h = NULL;        cli_buffer->line_h = NULL;
 }  }
   
   
 /*  /*
 * cli_freeLine() - Clear entire line * cli_freeInput() - Clear entire input
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cli_freeLine(linebuffer_t * __restrict buffer)cli_freeInput(linebuffer_t * __restrict cli_buffer)
 {  {
         int code = RETCODE_ERR;          int code = RETCODE_ERR;
   
        if (buffer) {        if (cli_buffer) {
                if (buffer->line_buf)                memset(cli_buffer->line_input, 0, BUFSIZ);
                        e_free(buffer->line_buf);                cli_buffer->line_posin ^= cli_buffer->line_posin;
                 cli_buffer->line_lenin ^= cli_buffer->line_lenin;
   
                buffer->line_buf = e_malloc(BUFSIZ);                code = RETCODE_OK;
                if (buffer->line_buf) {        } else
                        memset(buffer->line_buf, 0, BUFSIZ);                cli_SetErr(EINVAL, "Invalid input parameters ...");
                        buffer->line_eol = buffer->line_bol; 
                        buffer->line_len = 1 + buffer->line_eol; 
   
                        code = RETCODE_OK;        return code;
                } else}
                        LOGERR;/*
  * cli_freeLine() - Clear entire line
  *
  * @cli_buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok
 */
 int
 cli_freeLine(linebuffer_t * __restrict cli_buffer)
 {
         int code = RETCODE_ERR;
 
         if (cli_buffer) {
                 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          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
   
Line 877  cli_freeLine(linebuffer_t * __restrict buffer) Line 1040  cli_freeLine(linebuffer_t * __restrict buffer)
 /*  /*
  * cli_setPrompt() - Set new prompt for CLI session   * cli_setPrompt() - Set new prompt for CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @prompt = new text for prompt or if NULL disable prompt   * @prompt = new text for prompt or if NULL disable prompt
  * return: none   * return: none
 */  */
 void  void
cli_setPrompt(linebuffer_t * __restrict buffer, const char *prompt)cli_setPrompt(linebuffer_t * __restrict cli_buffer, const char *prompt)
 {  {
        if (buffer) {        if (cli_buffer) {
                if (buffer->line_prompt) {                if (cli_buffer->line_prompt) {
                        e_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
                        buffer->line_prompt = NULL;                        cli_buffer->line_prompt = NULL;
                        buffer->line_bol = 0;                        cli_buffer->line_bol = 0;
                 }                  }
   
                 if (prompt) {                  if (prompt) {
                        buffer->line_prompt = e_strdup(prompt);                        cli_buffer->line_prompt = e_strdup(prompt);
                        if (buffer->line_prompt) {                        if (cli_buffer->line_prompt) {
                                buffer->line_bol = strlen(buffer->line_prompt);                                cli_buffer->line_bol = strlen(cli_buffer->line_prompt);
                                buffer->line_eol = buffer->line_bol;                                cli_buffer->line_eol = cli_buffer->line_bol;
                                buffer->line_len = 1 + buffer->line_eol;                                cli_buffer->line_len = 1 + cli_buffer->line_eol;
                         } else                          } else
                                 LOGERR;                                  LOGERR;
                 }                  }
Line 908  cli_setPrompt(linebuffer_t * __restrict buffer, const  Line 1071  cli_setPrompt(linebuffer_t * __restrict buffer, const 
 /*  /*
  * cliEnd() - Clear data, Free resources and close CLI session   * cliEnd() - Clear data, Free resources and close CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 void  void
cliEnd(linebuffer_t * __restrict buffer)cliEnd(linebuffer_t * __restrict cli_buffer)
 {  {
         struct tagHistory *h;          struct tagHistory *h;
         struct tagCommand *c;          struct tagCommand *c;
   
        if (buffer) {        if (cli_buffer) {
                while ((c = SLIST_FIRST(&buffer->line_cmds))) {                while ((c = SLIST_FIRST(&cli_buffer->line_cmds))) {
                        SLIST_REMOVE_HEAD(&buffer->line_cmds, cmd_next);                        SLIST_REMOVE_HEAD(&cli_buffer->line_cmds, cmd_next);
                         e_free(c);                          e_free(c);
                 }                  }
                while ((h = TAILQ_FIRST(&buffer->line_history))) {                while ((h = TAILQ_FIRST(&cli_buffer->line_history))) {
                        TAILQ_REMOVE(&buffer->line_history, h, hist_next);                        TAILQ_REMOVE(&cli_buffer->line_history, h, hist_next);
                         e_free(h);                          e_free(h);
                 }                  }
   
                if (buffer->line_prompt)                if (cli_buffer->line_prompt)
                        e_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
   
                if (buffer->line_keys)                if (cli_buffer->line_keys)
                        e_free(buffer->line_keys);                        e_free(cli_buffer->line_keys);
                if (buffer->line_buf)                if (cli_buffer->line_buf)
                        e_free(buffer->line_buf);                        e_free(cli_buffer->line_buf);
   
                e_free(buffer);                if (cli_buffer->line_inkeys)
                buffer = NULL;                        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          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
Line 952  cliEnd(linebuffer_t * __restrict buffer) Line 1120  cliEnd(linebuffer_t * __restrict buffer)
 linebuffer_t *  linebuffer_t *
 cliInit(int fin, int fout, const char *prompt)  cliInit(int fin, int fout, const char *prompt)
 {  {
        linebuffer_t *buffer;        linebuffer_t *cli_buffer;
        bindkey_t *keys;        bindkey_t *keys, *inkeys;
         register int i;          register int i;
           char szPrompt[STRSIZ + 16] = {[0 ... STRSIZ + 15] = 0};
   
         /* init buffer */          /* init buffer */
        buffer = e_malloc(sizeof(linebuffer_t));        cli_buffer = e_malloc(sizeof(linebuffer_t));
        if (!buffer) {        if (!cli_buffer) {
                 LOGERR;                  LOGERR;
                 return NULL;                  return NULL;
         } else {          } else {
                memset(buffer, 0, sizeof(linebuffer_t));                memset(cli_buffer, 0, sizeof(linebuffer_t));
   
                buffer->line_in = fin;                cli_buffer->line_in = fin;
                buffer->line_out = fout;                cli_buffer->line_out = fout;
   
                TAILQ_INIT(&buffer->line_history);                TAILQ_INIT(&cli_buffer->line_history);
                SLIST_INIT(&buffer->line_cmds);                SLIST_INIT(&cli_buffer->line_cmds);
   
                 if (prompt) {                  if (prompt) {
                        buffer->line_prompt = e_strdup(prompt);                        strlcpy(cli_buffer->line_porigin, prompt, sizeof cli_buffer->line_porigin);
                        if (!buffer->line_prompt) {                        snprintf(szPrompt, sizeof szPrompt, "%s{%d}> ", cli_buffer->line_porigin, cli_buffer->line_level);
                         cli_buffer->line_prompt = e_strdup(szPrompt);
                         if (!cli_buffer->line_prompt) {
                                 LOGERR;                                  LOGERR;
                                e_free(buffer);                                e_free(cli_buffer);
                                 return NULL;                                  return NULL;
                         } else                          } else
                                buffer->line_eol = buffer->line_bol = strlen(buffer->line_prompt);                                cli_buffer->line_eol = cli_buffer->line_bol = 
                }                                        strlen(cli_buffer->line_prompt);
                 } else
                         cli_buffer->line_mode = LINEMODE_OVER;
         }          }
        buffer->line_buf = e_malloc(BUFSIZ);        cli_buffer->line_buf = e_malloc(BUFSIZ);
        if (!buffer->line_buf) {        if (!cli_buffer->line_buf) {
                 LOGERR;                  LOGERR;
                if (buffer->line_prompt)                if (cli_buffer->line_prompt)
                        e_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
                e_free(buffer);                e_free(cli_buffer);
                 return NULL;                  return NULL;
         } else {          } else {
                memset(buffer->line_buf, 0, BUFSIZ);                memset(cli_buffer->line_buf, 0, BUFSIZ);
                buffer->line_len = 1 + buffer->line_eol;                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));          keys = e_calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
         if (!keys) {          if (!keys) {
                 LOGERR;                  LOGERR;
                if (buffer->line_prompt)                if (cli_buffer->line_prompt)
                        e_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
                e_free(buffer->line_buf);                e_free(cli_buffer->line_input);
                e_free(buffer);                e_free(cli_buffer->line_buf);
                 e_free(cli_buffer);
                 return NULL;                  return NULL;
         } else          } else
                 memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1));                  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 */          /* add helper functions */
        cli_addCommand(buffer, "exit", 0, cli_Cmd_Exit, "exit <cr>", "Exit from console");        cli_addCommand(cli_buffer, "exit", 1, cli_Cmd_Exit, "exit <cr>", "Exit from console");
        cli_addCommand(buffer, "help", 0, cli_Cmd_Help, "help [command] <cr>", "Help screen");        cli_addCommand(cli_buffer, "help", -1, cli_Cmd_Help, "help [command] <cr>", "Help screen");
        cli_addCommand(buffer, "-------", 0, NULL, "-------------------------", NULL);        cli_addCommand(cli_buffer, "-------", -1, NULL, "-------------------------", NULL);
         cli_addCommand(cli_buffer, "where", -1, cli_Cmd_WhereAmI, "where <cr>", 
                         "Query current level of console");
         cli_addCommand(cli_buffer, "top", -1, cli_Cmd_Top, "top <cr>", "Top level of console");
         cli_addCommand(cli_buffer, "end", -1, cli_Cmd_End, "end <cr>", "End level of console");
         cli_addCommand(cli_buffer, "config", -1, cli_Cmd_Config, "config <cr>", 
                         "Config next level of console");
         cli_addCommand(cli_buffer, "-------", -1, 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++) {
                *keys[i].key_ch = (u_char) i;                *keys[i].key_ch = *inkeys[i].key_ch = (u_char) i;
                keys[i].key_len = 1;                keys[i].key_len = inkeys[i].key_len = 1;
   
                 if (!i || i == *K_CTRL_D)                  if (!i || i == *K_CTRL_D)
                         keys[i].key_func = bufEOF;                          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;                          keys[i].key_func = bufEOL;
                if (i == *K_CTRL_H || i == *K_BACKSPACE)                        inkeys[i].key_func = bufEOLin;
                 }
                 if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE))
                         keys[i].key_func = bufBS;                          keys[i].key_func = bufBS;
                if (i == *K_CTRL_C)                if (i == *K_CTRL_C) {
                         keys[i].key_func = bufCLR;                          keys[i].key_func = bufCLR;
                if (i == *K_CTRL_A)                        inkeys[i].key_func = bufCLRin;
                        keys[i].key_func = bufBEGIN;                }
                if (i == *K_CTRL_E)                if (i == *K_CTRL_A) {
                        keys[i].key_func = bufEND;                        if (cli_buffer->line_prompt)
                if (i == *K_TAB)                                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;                          keys[i].key_func = bufComp;
                if (i >= *K_SPACE && i < *K_BACKSPACE)                if (i == *K_CTRL_Z)
                         keys[i].key_func = bufEndNode;
                 if (i >= *K_SPACE && i < *K_BACKSPACE) {
                         keys[i].key_func = bufCHAR;                          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;                          keys[i].key_func = bufCHAR;
                if (i == '?')                        inkeys[i].key_func = bufCHARin;
                 }
                 if (cli_buffer->line_prompt && i == '?')
                         keys[i].key_func = bufHelp;                          keys[i].key_func = bufHelp;
         }          }
         /* alt+chars */          /* alt+chars */
         for (i = 256; i < 512; i++) {          for (i = 256; i < 512; i++) {
                keys[i].key_ch[0] = 0x1b;                keys[i].key_ch[0] = inkeys[i].key_ch[0] = 0x1b;
                keys[i].key_ch[1] = (u_char) i - 256;                keys[i].key_ch[1] = inkeys[i].key_ch[1] = (u_char) i - 256;
                keys[i].key_len = 2;                keys[i].key_len = inkeys[i].key_len = 2;
         }          }
   
         /* 3 bytes */          /* 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(keys[i].key_ch, K_F1, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F1, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F2, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F2, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F3, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F3, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F4, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F4, inkeys[i].key_len);
         i++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(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++;          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(keys[i].key_ch, K_CTRL_F1, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F1, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F2, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F2, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F3, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F3, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F4, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F4, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F5, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F5, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F6, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F6, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F7, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F7, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F8, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F8, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F9, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F9, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F10, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F10, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F11, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F11, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_CTRL_F12, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_CTRL_F12, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_HOME - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_HOME - 1;
        keys[i].key_func = bufBEGIN;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufBEGIN;
         memcpy(keys[i].key_ch, K_HOME, keys[i].key_len);          memcpy(keys[i].key_ch, K_HOME, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_HOME, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_END - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_END - 1;
        keys[i].key_func = bufEND;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufEND;
         memcpy(keys[i].key_ch, K_END, keys[i].key_len);          memcpy(keys[i].key_ch, K_END, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_END, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_UP - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_UP - 1;
        keys[i].key_func = bufUP;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufUP;
         memcpy(keys[i].key_ch, K_UP, keys[i].key_len);          memcpy(keys[i].key_ch, K_UP, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_UP, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_DOWN - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_DOWN - 1;
        keys[i].key_func = bufDOWN;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufDOWN;
         memcpy(keys[i].key_ch, K_DOWN, keys[i].key_len);          memcpy(keys[i].key_ch, K_DOWN, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_DOWN, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_RIGHT - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_RIGHT - 1;
        keys[i].key_func = bufRIGHT;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufRIGHT;
         memcpy(keys[i].key_ch, K_RIGHT, keys[i].key_len);          memcpy(keys[i].key_ch, K_RIGHT, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_RIGHT, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_LEFT - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_LEFT - 1;
        keys[i].key_func = bufLEFT;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufLEFT;
         memcpy(keys[i].key_ch, K_LEFT, keys[i].key_len);          memcpy(keys[i].key_ch, K_LEFT, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_LEFT, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_BTAB - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_BTAB - 1;
        keys[i].key_func = bufBTAB;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufBTAB;
         memcpy(keys[i].key_ch, K_BTAB, keys[i].key_len);          memcpy(keys[i].key_ch, K_BTAB, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_BTAB, inkeys[i].key_len);
         i++;          i++;
         /* 4 bytes */          /* 4 bytes */
        keys[i].key_len = sizeof K_INS - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_INS - 1;
        keys[i].key_func = bufMODE;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufMODE;
         memcpy(keys[i].key_ch, K_INS, keys[i].key_len);          memcpy(keys[i].key_ch, K_INS, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_INS, inkeys[i].key_len);
         i++;          i++;
        keys[i].key_len = sizeof K_DEL - 1;        keys[i].key_len = inkeys[i].key_len = sizeof K_DEL - 1;
        keys[i].key_func = bufDEL;        if (cli_buffer->line_prompt)
                 keys[i].key_func = bufDEL;
         memcpy(keys[i].key_ch, K_DEL, keys[i].key_len);          memcpy(keys[i].key_ch, K_DEL, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_DEL, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_PGUP, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_PGUP, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_PGDN, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_PGDN, inkeys[i].key_len);
         i++;          i++;
         /* 5 bytes */          /* 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(keys[i].key_ch, K_F5, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F5, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F6, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F6, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F7, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F7, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F8, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F8, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F9, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F9, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F10, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F10, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F11, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F11, inkeys[i].key_len);
         i++;          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(keys[i].key_ch, K_F12, keys[i].key_len);
           memcpy(inkeys[i].key_ch, K_F12, inkeys[i].key_len);
         i++;          i++;
   
        buffer->line_keys = keys;        cli_buffer->line_keys = keys;
        return buffer;        cli_buffer->line_inkeys = inkeys;
         return cli_buffer;
 }  }
   
 /*  /*
 * cliInitLine() - Init CLI input line terminal * cliSetLine() - Set CLI input line terminal
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
 * return: none * @old = Old terminal settings
  * return: -1 error or 0 ok
 */  */
 int  int
cliInitLine(linebuffer_t * __restrict buffer)cliSetLine(linebuffer_t * __restrict cli_buffer, struct termios * __restrict old)
 {  {
         struct termios t;          struct termios t;
   
         memset(&t, 0, sizeof t);          memset(&t, 0, sizeof t);
        tcgetattr(buffer->line_in, &t);        tcgetattr(cli_buffer->line_in, &t);
        t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);        if (old)
                 memcpy(old, &t, sizeof(struct termios));
         t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | 
                         ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
         t.c_iflag |= IGNBRK;          t.c_iflag |= IGNBRK;
         t.c_cc[VMIN] = 1;          t.c_cc[VMIN] = 1;
         t.c_cc[VTIME] = 0;          t.c_cc[VTIME] = 0;
        return tcsetattr(buffer->line_in, TCSANOW, &t);        return tcsetattr(cli_buffer->line_in, TCSANOW, &t);
 }  }
   
 /*  /*
    * cliResetLine() - Reset CLI input line terminal
    *
    * @cli_buffer = CLI buffer
    * @old = Original terminal settings
    * return: -1 error or 0 ok
   */
   int
   cliResetLine(linebuffer_t * __restrict cli_buffer, struct termios * __restrict orig)
   {
           return tcsetattr(cli_buffer->line_in, TCSANOW, orig);
   }
   
   /*
    * 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   * cliReadLine() - Read line from opened CLI session
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @timeout = Session timeout (-1 infinit)
  * return: NULL if error or !=NULL readed line, must be e_free after use!   * return: NULL if error or !=NULL readed line, must be e_free after use!
 */  */
 char *  char *
cliReadLine(linebuffer_t * __restrict buffer)cliReadLine(linebuffer_t * __restrict cli_buffer, int timeout)
 {  {
        int code, readLen;        int code, readLen, ret;
         register int i;          register int i;
         struct pollfd fds;          struct pollfd fds;
         char buf[BUFSIZ], *str = NULL;          char buf[BUFSIZ], *str = NULL;
   
        if (!buffer) {        if (!cli_buffer) {
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return NULL;                  return NULL;
        }        } else if (timeout > 0)
                 timeout *= 1000;        /* convert from sec to ms */
   
         memset(&fds, 0, sizeof fds);          memset(&fds, 0, sizeof fds);
        fds.fd = buffer->line_in;        fds.fd = cli_buffer->line_in;
         fds.events = POLLIN;          fds.events = POLLIN;
   
        printfCR(buffer, 1);        printfCR(cli_buffer, 1);
         while (42) {          while (42) {
                if (poll(&fds, 1, -1) < 1) {                if ((ret = poll(&fds, 1, timeout)) < 1) {
                        LOGERR;                        if (!ret)
                        return str;                                cli_buffer->line_kill = 1;
                         else
                                 LOGERR;
                         return NULL;
                 }                  }
   
                 memset(buf, 0, sizeof buf);                  memset(buf, 0, sizeof buf);
                readLen = read(buffer->line_in, buf, BUFSIZ);                readLen = read(cli_buffer->line_in, buf, sizeof buf - 1);
                if (readLen == -1) {                if (readLen < 1) {
                        LOGERR;                        if (readLen)
                        return str;                                LOGERR;
                         return NULL;
                 }                  }
                if (!readLen) {
                        if (buffer->line_buf)                while (readLen)
                                str = e_strdup(buffer->line_buf);                        for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                        else                                if (readLen >= cli_buffer->line_keys[i].key_len && 
                                cli_SetErr(EPIPE, "Unknown state ...");                                                !memcmp(cli_buffer->line_keys[i].key_ch, buf, 
                        return str;                                                        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 (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;
                 }                  }
   
recheck:                memset(buf, 0, sizeof buf);
                for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)                readLen = read(cli_buffer->line_in, buf, sizeof buf - 1);
                        if (readLen >= buffer->line_keys[i].key_len &&                 if (readLen < 1) {
                                        !memcmp(buffer->line_keys[i].key_ch, buf,                         if (readLen)
                                                buffer->line_keys[i].key_len)) {                                LOGERR;
                                readLen -= buffer->line_keys[i].key_len;                        return NULL;
                                if (readLen)                }
                                        memmove(buf, buf + buffer->line_keys[i].key_len, readLen); 
                                else 
                                        memset(buf, 0, buffer->line_keys[i].key_len); 
   
                                if (buffer->line_keys[i].key_func)                while (readLen)
                                        if ((code = buffer->line_keys[i].key_func(i, buffer)))                        for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                                                readLen = 0;                                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 (readLen)                                        if (cli_buffer->line_inkeys[i].key_func)
                                        goto recheck;                                                if ((code = cli_buffer->line_inkeys[i].key_func(i, cli_buffer)))
                                else                                                        readLen = 0;
                                        break;                                }
                        } 
   
                 if (code)                  if (code)
                         break;                          break;
         }          }
   
        if (code != RETCODE_ERR && code != RETCODE_EOF && buffer->line_buf)        if (code != RETCODE_ERR && code != RETCODE_EOF && cli_buffer->line_input)
                str = e_strdup(buffer->line_buf);                str = e_strdup(cli_buffer->line_input);
         return str;          return str;
 }  }
   
Line 1297  recheck: Line 1676  recheck:
 /*  /*
  * cliNetLoop() - CLI network main loop binded to socket   * cliNetLoop() - CLI network main loop binded to socket
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
  * @csHistFile = History file name   * @csHistFile = History file name
  * @sock = client socket   * @sock = client socket
    * @timeout = Session timeout (-1 infinit)
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cliNetLoop(linebuffer_t * __restrict buffer, const char *csHistFile, int sock)cliNetLoop(linebuffer_t * __restrict cli_buffer, const char *csHistFile, 
                 int sock, int timeout)
 {  {
         u_char buf[BUFSIZ];          u_char buf[BUFSIZ];
        int pid, stat, pty, r, s, alen, flg, attrlen = 0, ret = 0;        int pid, stat, pty, s, alen, flg, attrlen = 0, ret = 0;
         fd_set fds;          fd_set fds;
         struct timeval tv = { DEFAULT_SOCK_TIMEOUT, 0 };          struct timeval tv = { DEFAULT_SOCK_TIMEOUT, 0 };
         struct telnetAttrs *a, Attr[10];          struct telnetAttrs *a, Attr[10];
Line 1316  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1697  cliNetLoop(linebuffer_t * __restrict buffer, const cha
                         LOGERR;                          LOGERR;
                         return -1;                          return -1;
                 case 0:                  case 0:
                        if (!buffer) {                        if (!cli_buffer) {
                                 cli_SetErr(EINVAL, "Invalid input parameters ...");                                  cli_SetErr(EINVAL, "Invalid input parameters ...");
                                 return -1;                                  return -1;
                         } else                          } else
                                 close(sock);                                  close(sock);
   
                        ret = cliLoop(buffer, csHistFile) < 0 ? 1 : 0;                        ret = cliLoop(cli_buffer, csHistFile, timeout) < 0 ? 1 : 0;
                        cliEnd(buffer);                        cliEnd(cli_buffer);
   
                        exit(ret);                        _exit(ret);
                 default:                  default:
                         cli_telnet_SetCmd(Attr + 0, DO, TELOPT_TTYPE);                          cli_telnet_SetCmd(Attr + 0, DO, TELOPT_TTYPE);
                         cli_telnet_SetCmd(Attr + 1, WILL, TELOPT_ECHO);                          cli_telnet_SetCmd(Attr + 1, WILL, TELOPT_ECHO);
Line 1351  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1732  cliNetLoop(linebuffer_t * __restrict buffer, const cha
                                         break;                                          break;
                                 }                                  }
   
                                 r = FD_ISSET(sock, &fds) ? sock : pty;  
                                 s = FD_ISSET(sock, &fds) ? pty : sock;                                  s = FD_ISSET(sock, &fds) ? pty : sock;
   
                                 if (FD_ISSET(sock, &fds)) {                                  if (FD_ISSET(sock, &fds)) {
Line 1391  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1771  cliNetLoop(linebuffer_t * __restrict buffer, const cha
   
                                 if (FD_ISSET(pty, &fds)) {                                  if (FD_ISSET(pty, &fds)) {
                                         memset(buf, 0, BUFSIZ);                                          memset(buf, 0, BUFSIZ);
                                        if ((ret = read(pty, buf, BUFSIZ)) == -1) {                                        if ((ret = read(pty, buf, BUFSIZ)) < 1) {
                                                LOGERR;                                                if (ret)
                                                         LOGERR;
                                                 break;                                                  break;
                                         }                                          }
   
Line 1411  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1792  cliNetLoop(linebuffer_t * __restrict buffer, const cha
 }  }
   
 /*  /*
 * cliLoop() - CLI main loop * cliRun() - CLI run command line
  *   *
 * @buffer = CLI buffer * @cli_buffer = CLI buffer
 * @csHistFile = History file name * @psInput = Input command line
  * @prompt = Display prompt after command
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cliLoop(linebuffer_t * __restrict buffer, const char *csHistFile)cliRun(linebuffer_t * __restrict cli_buffer, char *psInput, int prompt)
 {  {
         char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];          char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];
         register int i;  
         int ret = RETCODE_OK;          int ret = RETCODE_OK;
         struct tagCommand *cmd;          struct tagCommand *cmd;
   
           if (!psInput)
                   return RETCODE_ERR;
           else
                   line = psInput;
   
           // clear whitespaces
           for (s = line; isspace((int) *s); s++);
           if (*s) {
                   for (t = s + strlen(s) - 1; t > s && isspace((int) *t); t--);
                   *++t = 0;
           }
   
           if (*s) {
                   memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
                   for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && 
                                   (*app = strsep(&s, " \t")); *app ? app++ : app);
   
                   // exec_cmd ...
                   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;
                   }
   
                   if (!cmd) {
                           cli_Printf(cli_buffer, "%sCommand '%s' not found!\n", 
                                           cli_buffer->line_prompt ? "\n" : "", items[0]);
                           ret = RETCODE_ERR;
                   } else
                           if (cmd->cmd_func) {
                                   if (prompt && cli_buffer->line_prompt)
                                           cli_Printf(cli_buffer, "\n");
                                   ret = cmd->cmd_func(cli_buffer, 
                                                   cli_buffer->line_level, items);
                           } else if (prompt) {
                                   clrscrEOL(cli_buffer);
                                   printfCR(cli_buffer, 1);
                           }
           }
   
           return ret;
   }
   
   /*
    * cliLoop() - CLI main loop
    *
    * @cli_buffer = CLI buffer
    * @csHistFile = History file name
    * @timeout = Session timeout (-1 infinit)
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
   cliLoop(linebuffer_t * __restrict cli_buffer, const char *csHistFile, int timeout)
   {
           char *line;
           int ret = RETCODE_OK;
           struct termios t;
   
         /* --- main body of CLI --- */          /* --- main body of CLI --- */
        cliInitLine(buffer);        cliSetLine(cli_buffer, &t);
   
        if (cli_loadHistory(buffer, csHistFile) == RETCODE_ERR)        if (cli_loadHistory(cli_buffer, csHistFile) == RETCODE_ERR)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         do {          do {
                line = cliReadLine(buffer);                line = cliReadLine(cli_buffer, timeout);
                 if (!line) {                  if (!line) {
                        printfNL(buffer, 0);                        printfNL(cli_buffer, 0);
                         break;                          break;
                 } else                  } else
                        cli_addHistory(buffer, NULL);                        cli_addHistory(cli_buffer, NULL);
                // clear whitespaces 
                for (s = line; isspace((int) *s); s++); 
                if (*s) { 
                        for (t = s + strlen(s) - 1; t > s && isspace((int) *t); t--); 
                        *++t = 0; 
                } 
   
                if (*s) {                ret = cliRun(cli_buffer, line, 42);
                        memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS); 
                        for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t"));  
                                        *app ? app++ : app); 
   
                        // exec_cmd ...                cli_freeLine(cli_buffer);
                        i = 0;                cli_resetHistory(cli_buffer);
                        SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) {                e_free(line);
                                if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))        } while (!cli_buffer->line_kill);
                                        break; 
                                else 
                                        i++; 
                        } 
   
                        if (!cmd) {        cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);
                                cli_Printf(buffer, "\nCommand '%s' not found!\n", items[0]); 
                                ret = -1; 
                        } else 
                                if (cmd->cmd_func) { 
                                        cli_Printf(buffer, "\n"); 
                                        ret = cmd->cmd_func(buffer, i, items); 
                                } else { 
                                        clrscrEOL(buffer); 
                                        printfCR(buffer, 1); 
                                } 
                } 
   
                cli_freeLine(buffer);        /* --- restore tty --- */
                cli_resetHistory(buffer);        cliResetLine(cli_buffer, &t);
                e_free(line); 
        } while (ret < 1); 
   
         cli_saveHistory(buffer, csHistFile, HISTORY_LINES);  
         return ret;          return ret;
 }  }

Removed from v.1.5.4.3  
changed lines
  Added in v.1.21.2.3


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