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

version 1.8.2.3, 2013/10/08 09:28:15 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 && buf->line_prompt) {          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) {
                if (prompt && buf->line_prompt) {                ign = write(buf->line_out, K_CR, 1);
                        write(buf->line_out, K_CR, 1); 
                        write(buf->line_out, buf->line_prompt, buf->line_bol); 
                } 
   
                write(buf->line_out, buf->line_buf, len == -1 ?                 if (prompt && buf->line_prompt)
                                buf->line_eol - buf->line_bol: len);                        ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
 
                 ign = write(buf->line_out, buf->line_buf, len == -1 ? 
                                 buf->line_eol - buf->line_bol : len);
         }          }
 }  }
   
 static inline void  static inline void
 printfCR(linebuffer_t * __restrict buf, int prompt)  printfCR(linebuffer_t * __restrict buf, int prompt)
 {  {
        if (buf && prompt && buf->line_prompt) {        int ign __attribute__((unused));
                write(buf->line_out, K_CR, 1);
                write(buf->line_out, buf->line_prompt, buf->line_bol);        ign = write(buf->line_out, K_CR, 1);
        }        if (buf && prompt && buf->line_prompt)
                 ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
 }  }
   
 static inline void  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
   bufCHARin(int idx, void * __restrict cli_buffer)
   {
           linebuffer_t *buf = cli_buffer;
           int pos;
           int ign __attribute__((unused));
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           pos = buf->line_posin;
   
           if (buf->line_mode == LINEMODE_INS)
                   memmove(buf->line_input + pos + buf->line_inkeys[idx].key_len, buf->line_input + pos, 
                                   buf->line_lenin - buf->line_posin);
           if (buf->line_mode == LINEMODE_INS || buf->line_posin == buf->line_lenin)
                   buf->line_lenin += buf->line_inkeys[idx].key_len;
           buf->line_posin += buf->line_inkeys[idx].key_len;
   
           memcpy(buf->line_input + pos, buf->line_inkeys[idx].key_ch, buf->line_inkeys[idx].key_len);
           buf->line_input[buf->line_lenin] = 0;
   
           if (buf->line_mode == LINEMODE_INS) {
                   rewindin(buf, buf->line_posin - buf->line_inkeys[idx].key_len);
                   printfEOLin(buf);
                   rewindin(buf, buf->line_lenin - buf->line_posin);
           }
           return RETCODE_OK;
   }
   
   static int
 bufCHAR(int idx, void * __restrict cli_buffer)  bufCHAR(int idx, void * __restrict cli_buffer)
 {  {
         linebuffer_t *buf = cli_buffer;          linebuffer_t *buf = cli_buffer;
         int pos;          int pos;
           int ign __attribute__((unused));
   
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 154  bufCHAR(int idx, void * __restrict cli_buffer) Line 213  bufCHAR(int idx, void * __restrict cli_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 165  bufCHAR(int idx, void * __restrict cli_buffer) Line 225  bufCHAR(int idx, void * __restrict cli_buffer)
 }  }
   
 static int  static int
   bufEOLin(int idx, void * __restrict cli_buffer)
   {
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           return RETCODE_EOL;
   }
   
   static int
 bufEOL(int idx, void * __restrict cli_buffer)  bufEOL(int idx, void * __restrict cli_buffer)
 {  {
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
Line 177  bufEOL(int idx, void * __restrict cli_buffer) Line 246  bufEOL(int idx, void * __restrict cli_buffer)
 static int  static int
 bufEOF(int idx, void * __restrict cli_buffer)  bufEOF(int idx, void * __restrict cli_buffer)
 {  {
           int ret;
   
         /*          /*
         if (!cli_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
Line 248  bufDOWN(int idx, void * __restrict cli_buffer) Line 323  bufDOWN(int idx, void * __restrict cli_buffer)
 }  }
   
 static int  static int
   bufCLRin(int idx, void * __restrict cli_buffer)
   {
           linebuffer_t *buf = cli_buffer;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           memset(buf->line_input, ' ', buf->line_lenin);
           rewindin(buf, -1);
           printfEOLin(buf);
           rewindin(buf, -1);
           cli_freeInput(cli_buffer);
           return RETCODE_OK;
   }
   
   static int
 bufCLR(int idx, void * __restrict cli_buffer)  bufCLR(int idx, void * __restrict cli_buffer)
 {  {
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
Line 318  bufMODE(int idx, void * __restrict cli_buffer) Line 409  bufMODE(int idx, void * __restrict cli_buffer)
 }  }
   
 static int  static int
   bufBEGINin(int idx, void * __restrict cli_buffer)
   {
           linebuffer_t *buf = cli_buffer;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           rewindin(buf, -1);
           buf->line_posin ^= buf->line_posin;
   
           return RETCODE_OK;
   }
   
   static int
 bufBEGIN(int idx, void * __restrict cli_buffer)  bufBEGIN(int idx, void * __restrict cli_buffer)
 {  {
         linebuffer_t *buf = cli_buffer;          linebuffer_t *buf = cli_buffer;
Line 332  bufBEGIN(int idx, void * __restrict cli_buffer) Line 437  bufBEGIN(int idx, void * __restrict cli_buffer)
 }  }
   
 static int  static int
   bufENDin(int idx, void * __restrict cli_buffer)
   {
           linebuffer_t *buf = cli_buffer;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           rewindin(buf, -1);
           printfEOLin(buf);
           buf->line_posin = buf->line_lenin;
   
           return RETCODE_OK;
   }
   
   static int
 bufEND(int idx, void * __restrict cli_buffer)  bufEND(int idx, void * __restrict cli_buffer)
 {  {
         linebuffer_t *buf = cli_buffer;          linebuffer_t *buf = cli_buffer;
Line 403  bufComp(int idx, void * __restrict cli_buffer) Line 523  bufComp(int idx, void * __restrict cli_buffer)
         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 (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 415  bufComp(int idx, void * __restrict cli_buffer) Line 536  bufComp(int idx, void * __restrict cli_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) {
Line 426  bufComp(int idx, void * __restrict cli_buffer) Line 547  bufComp(int idx, void * __restrict cli_buffer)
   
                 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],                                                   !strncmp(cmd->cmd_name, items[0], 
                                                         strlen(items[0]))) {                                                          strlen(items[0]))) {
                                         if (strncmp(cmd->cmd_name, CLI_CMD_SEP,                                           if (strncmp(cmd->cmd_name, CLI_CMD_SEP, 
Line 452  bufComp(int idx, void * __restrict cli_buffer) Line 573  bufComp(int idx, void * __restrict cli_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 465  bufComp(int idx, void * __restrict cli_buffer) Line 586  bufComp(int idx, void * __restrict cli_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 499  bufHelp(int idx, void * __restrict cli_buffer) Line 620  bufHelp(int idx, void * __restrict cli_buffer)
         if (!cli_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
  *   *
Line 522  cli_Printf(linebuffer_t * __restrict cli_buffer, char  Line 663  cli_Printf(linebuffer_t * __restrict cli_buffer, char 
         FILE *f;          FILE *f;
   
         if (fmt) {          if (fmt) {
                f = fdopen(cli_buffer->line_out, "a");                f = fdopen(dup(cli_buffer->line_out), "a");
                 if (!f) {                  if (!f) {
                         LOGERR;                          LOGERR;
                         return;                          return;
Line 531  cli_Printf(linebuffer_t * __restrict cli_buffer, char  Line 672  cli_Printf(linebuffer_t * __restrict cli_buffer, char 
                 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 586  cli_BindKey(bindkey_t * __restrict key, linebuffer_t * Line 729  cli_BindKey(bindkey_t * __restrict key, linebuffer_t *
  *   *
  * @cli_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
Line 627  cli_addCommand(linebuffer_t * __restrict cli_buffer, c Line 770  cli_addCommand(linebuffer_t * __restrict cli_buffer, c
  *   *
  * @cli_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
Line 657  cli_delCommand(linebuffer_t * __restrict cli_buffer, c Line 800  cli_delCommand(linebuffer_t * __restrict cli_buffer, c
  *   *
  * @cli_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
Line 676  cli_updCommand(linebuffer_t * __restrict cli_buffer, c Line 819  cli_updCommand(linebuffer_t * __restrict cli_buffer, c
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        SLIST_FOREACH(cmd, &cli_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 849  cli_resetHistory(linebuffer_t * __restrict cli_buffer) Line 993  cli_resetHistory(linebuffer_t * __restrict cli_buffer)
   
   
 /*  /*
    * cli_freeInput() - Clear entire input
    *
    * @cli_buffer = CLI buffer
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
   cli_freeInput(linebuffer_t * __restrict cli_buffer)
   {
           int code = RETCODE_ERR;
   
           if (cli_buffer) {
                   memset(cli_buffer->line_input, 0, BUFSIZ);
                   cli_buffer->line_posin ^= cli_buffer->line_posin;
                   cli_buffer->line_lenin ^= cli_buffer->line_lenin;
   
                   code = RETCODE_OK;
           } else
                   cli_SetErr(EINVAL, "Invalid input parameters ...");
   
           return code;
   }
   /*
  * cli_freeLine() - Clear entire line   * cli_freeLine() - Clear entire line
  *   *
  * @cli_buffer = CLI buffer   * @cli_buffer = CLI buffer
Line 860  cli_freeLine(linebuffer_t * __restrict cli_buffer) Line 1026  cli_freeLine(linebuffer_t * __restrict cli_buffer)
         int code = RETCODE_ERR;          int code = RETCODE_ERR;
   
         if (cli_buffer) {          if (cli_buffer) {
                if (cli_buffer->line_buf)                memset(cli_buffer->line_buf, 0, BUFSIZ);
                        e_free(cli_buffer->line_buf);                cli_buffer->line_eol = cli_buffer->line_bol;
                 cli_buffer->line_len = 1 + cli_buffer->line_eol;
   
                cli_buffer->line_buf = e_malloc(BUFSIZ);                code = RETCODE_OK;
                if (cli_buffer->line_buf) { 
                        memset(cli_buffer->line_buf, 0, BUFSIZ); 
                        cli_buffer->line_eol = cli_buffer->line_bol; 
                        cli_buffer->line_len = 1 + cli_buffer->line_eol; 
 
                        code = RETCODE_OK; 
                } else 
                        LOGERR; 
         } else          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
   
Line 939  cliEnd(linebuffer_t * __restrict cli_buffer) Line 1098  cliEnd(linebuffer_t * __restrict cli_buffer)
                 if (cli_buffer->line_buf)                  if (cli_buffer->line_buf)
                         e_free(cli_buffer->line_buf);                          e_free(cli_buffer->line_buf);
   
                   if (cli_buffer->line_inkeys)
                           e_free(cli_buffer->line_inkeys);
                   if (cli_buffer->line_input)
                           e_free(cli_buffer->line_input);
   
                 e_free(cli_buffer);                  e_free(cli_buffer);
                 cli_buffer = NULL;                  cli_buffer = NULL;
         } else          } else
Line 957  linebuffer_t * Line 1121  linebuffer_t *
 cliInit(int fin, int fout, const char *prompt)  cliInit(int fin, int fout, const char *prompt)
 {  {
         linebuffer_t *cli_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 */
         cli_buffer = e_malloc(sizeof(linebuffer_t));          cli_buffer = e_malloc(sizeof(linebuffer_t));
Line 975  cliInit(int fin, int fout, const char *prompt) Line 1140  cliInit(int fin, int fout, const char *prompt)
                 SLIST_INIT(&cli_buffer->line_cmds);                  SLIST_INIT(&cli_buffer->line_cmds);
   
                 if (prompt) {                  if (prompt) {
                        cli_buffer->line_prompt = e_strdup(prompt);                        strlcpy(cli_buffer->line_porigin, prompt, sizeof cli_buffer->line_porigin);
                         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) {                          if (!cli_buffer->line_prompt) {
                                 LOGERR;                                  LOGERR;
                                 e_free(cli_buffer);                                  e_free(cli_buffer);
Line 997  cliInit(int fin, int fout, const char *prompt) Line 1164  cliInit(int fin, int fout, const char *prompt)
                 memset(cli_buffer->line_buf, 0, BUFSIZ);                  memset(cli_buffer->line_buf, 0, BUFSIZ);
                 cli_buffer->line_len = 1 + cli_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 (cli_buffer->line_prompt)                  if (cli_buffer->line_prompt)
                         e_free(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->line_buf);
                 e_free(cli_buffer);                  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(cli_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(cli_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(cli_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;
                           inkeys[i].key_func = bufEOLin;
                   }
                 if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE))                  if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE))
                         keys[i].key_func = bufBS;                          keys[i].key_func = bufBS;
                if (cli_buffer->line_prompt && i == *K_CTRL_C)                if (i == *K_CTRL_C) {
                         keys[i].key_func = bufCLR;                          keys[i].key_func = bufCLR;
                if (cli_buffer->line_prompt && i == *K_CTRL_A)                        inkeys[i].key_func = bufCLRin;
                        keys[i].key_func = bufBEGIN;                }
                if (cli_buffer->line_prompt && i == *K_CTRL_E)                if (i == *K_CTRL_A) {
                        keys[i].key_func = bufEND;                        if (cli_buffer->line_prompt)
                                 keys[i].key_func = bufBEGIN;
                         inkeys[i].key_func = bufBEGINin;
                 }
                 if (i == *K_CTRL_E) {
                         if (cli_buffer->line_prompt)
                                 keys[i].key_func = bufEND;
                         inkeys[i].key_func = bufENDin;
                 }
                 if (cli_buffer->line_prompt && i == *K_TAB)                  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;
                           inkeys[i].key_func = bufCHARin;
                   }
                 if (cli_buffer->line_prompt && i == '?')                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufBEGIN;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufEND;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufUP;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufDOWN;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufRIGHT;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufLEFT;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufBTAB;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufMODE;                  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;
         if (cli_buffer->line_prompt)          if (cli_buffer->line_prompt)
                 keys[i].key_func = bufDEL;                  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++;
   
         cli_buffer->line_keys = keys;          cli_buffer->line_keys = keys;
           cli_buffer->line_inkeys = inkeys;
         return cli_buffer;          return cli_buffer;
 }  }
   
 /*  /*
 * cliInitLine() - Init CLI input line terminal * cliSetLine() - Set CLI input line terminal
  *   *
  * @cli_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 cli_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(cli_buffer->line_in, &t);          tcgetattr(cli_buffer->line_in, &t);
           if (old)
                   memcpy(old, &t, sizeof(struct termios));
         t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO |           t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | 
                         ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);                          ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
         t.c_iflag |= IGNBRK;          t.c_iflag |= IGNBRK;
Line 1236  cliInitLine(linebuffer_t * __restrict cli_buffer) Line 1502  cliInitLine(linebuffer_t * __restrict cli_buffer)
 }  }
   
 /*  /*
    * 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
  *   *
  * @cli_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 cli_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;
Line 1252  cliReadLine(linebuffer_t * __restrict cli_buffer) Line 1557  cliReadLine(linebuffer_t * __restrict cli_buffer)
         if (!cli_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 = cli_buffer->line_in;          fds.fd = cli_buffer->line_in;
Line 1260  cliReadLine(linebuffer_t * __restrict cli_buffer) Line 1566  cliReadLine(linebuffer_t * __restrict cli_buffer)
   
         printfCR(cli_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(cli_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 (cli_buffer->line_buf)  
                                 str = e_strdup(cli_buffer->line_buf);  
                         else  
                                 cli_SetErr(EPIPE, "Unknown state ...");  
                         return str;  
                 }  
   
recheck:                while (readLen)
                for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)                        for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                        if (readLen >= cli_buffer->line_keys[i].key_len &&                                 if (readLen >= cli_buffer->line_keys[i].key_len && 
                                        !memcmp(cli_buffer->line_keys[i].key_ch, buf,                                                 !memcmp(cli_buffer->line_keys[i].key_ch, buf, 
                                                cli_buffer->line_keys[i].key_len)) {                                                        cli_buffer->line_keys[i].key_len)) {
                                readLen -= cli_buffer->line_keys[i].key_len;                                        readLen -= cli_buffer->line_keys[i].key_len;
                                if (readLen)                                        if (readLen)
                                        memmove(buf, buf + cli_buffer->line_keys[i].key_len, readLen);                                                memmove(buf, buf + cli_buffer->line_keys[i].key_len, readLen);
                                else                                        else
                                        memset(buf, 0, cli_buffer->line_keys[i].key_len);                                                memset(buf, 0, cli_buffer->line_keys[i].key_len);
   
                                if (cli_buffer->line_keys[i].key_func)                                        if (cli_buffer->line_keys[i].key_func)
                                        if ((code = cli_buffer->line_keys[i].key_func(i, cli_buffer)))                                                if ((code = cli_buffer->line_keys[i].key_func(i, cli_buffer)))
                                                readLen = 0;                                                        readLen = 0;
                                 }
   
                                 if (readLen)  
                                         goto recheck;  
                                 else  
                                         break;  
                         }  
   
                 if (code)                  if (code)
                         break;                          break;
         }          }
Line 1309  recheck: Line 1607  recheck:
         return str;          return str;
 }  }
   
   /*
    * cliInputLine() - Input line from opened CLI session
    *
    * @cli_buffer = CLI buffer
    * @timeout = Session timeout (-1 infinit)
    * return: NULL if error or !=NULL readed line, must be e_free after use!
   */
   char *
   cliInputLine(linebuffer_t * __restrict cli_buffer, int timeout)
   {
           int code, readLen, ret;
           register int i;
           struct pollfd fds;
           char buf[BUFSIZ], *str = NULL;
   
           if (!cli_buffer) {
                   cli_SetErr(EINVAL, "Invalid input parameters ...");
                   return NULL;
           } else if (timeout > 0)
                   timeout *= 1000;        /* convert from sec to ms */
   
           memset(&fds, 0, sizeof fds);
           fds.fd = cli_buffer->line_in;
           fds.events = POLLIN;
   
           while (42) {
                   if ((ret = poll(&fds, 1, timeout)) < 1) {
                           if (ret == -1)
                                   LOGERR;
                           return NULL;
                   }
   
                   memset(buf, 0, sizeof buf);
                   readLen = read(cli_buffer->line_in, buf, sizeof buf - 1);
                   if (readLen < 1) {
                           if (readLen)
                                   LOGERR;
                           return NULL;
                   }
   
                   while (readLen)
                           for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                                   if (readLen >= cli_buffer->line_inkeys[i].key_len && 
                                                   !memcmp(cli_buffer->line_inkeys[i].key_ch, buf, 
                                                           cli_buffer->line_inkeys[i].key_len)) {
                                           readLen -= cli_buffer->line_inkeys[i].key_len;
                                           if (readLen)
                                                   memmove(buf, buf + cli_buffer->line_inkeys[i].key_len, readLen);
                                           else
                                                   memset(buf, 0, cli_buffer->line_inkeys[i].key_len);
   
                                           if (cli_buffer->line_inkeys[i].key_func)
                                                   if ((code = cli_buffer->line_inkeys[i].key_func(i, cli_buffer)))
                                                           readLen = 0;
                                   }
   
                   if (code)
                           break;
           }
   
           if (code != RETCODE_ERR && code != RETCODE_EOF && cli_buffer->line_input)
                   str = e_strdup(cli_buffer->line_input);
           return str;
   }
   
   
 /*  /*
  * cliNetLoop() - CLI network main loop binded to socket   * cliNetLoop() - CLI network main loop binded to socket
  *   *
  * @cli_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 cli_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 1338  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1703  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
                         } else                          } else
                                 close(sock);                                  close(sock);
   
                        ret = cliLoop(cli_buffer, csHistFile) < 0 ? 1 : 0;                        ret = cliLoop(cli_buffer, csHistFile, timeout) < 0 ? 1 : 0;
                         cliEnd(cli_buffer);                          cliEnd(cli_buffer);
   
                         _exit(ret);                          _exit(ret);
Line 1367  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1732  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
                                         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 1407  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1771  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
   
                                 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 1427  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1792  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
 }  }
   
 /*  /*
 * cliLoop() - CLI main loop * cliRun() - CLI run command line
  *   *
  * @cli_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 cli_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(cli_buffer);        cliSetLine(cli_buffer, &t);
   
         if (cli_loadHistory(cli_buffer, csHistFile) == RETCODE_ERR)          if (cli_loadHistory(cli_buffer, csHistFile) == RETCODE_ERR)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
         do {          do {
                line = cliReadLine(cli_buffer);                line = cliReadLine(cli_buffer, timeout);
                 if (!line) {                  if (!line) {
                         printfNL(cli_buffer, 0);                          printfNL(cli_buffer, 0);
                         break;                          break;
                 } else                  } else
                         cli_addHistory(cli_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 ...  
                         i = 0;  
                         SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next) {  
                                 if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))  
                                         break;  
                                 else  
                                         i++;  
                         }  
   
                         if (!cmd) {  
                                 cli_Printf(cli_buffer, "\nCommand '%s' not found!\n", items[0]);  
                                 ret = -1;  
                         } else  
                                 if (cmd->cmd_func) {  
                                         cli_Printf(cli_buffer, "\n");  
                                         ret = cmd->cmd_func(cli_buffer, i, items);  
                                 } else {  
                                         clrscrEOL(cli_buffer);  
                                         printfCR(cli_buffer, 1);  
                                 }  
                 }  
   
                 cli_freeLine(cli_buffer);                  cli_freeLine(cli_buffer);
                 cli_resetHistory(cli_buffer);                  cli_resetHistory(cli_buffer);
                 e_free(line);                  e_free(line);
        } while (ret < 1);        } while (!cli_buffer->line_kill);
   
         cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);          cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);
   
           /* --- restore tty --- */
           cliResetLine(cli_buffer, &t);
   
         return ret;          return ret;
 }  }

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


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