Diff for /libaitcli/src/aitcli.c between versions 1.5 and 1.11

version 1.5, 2012/07/22 22:37:08 version 1.11, 2013/11/20 16:40:02
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, 2012Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
         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 49  SUCH DAMAGE. Line 49  SUCH DAMAGE.
   
 #pragma GCC visibility push(hidden)  #pragma GCC visibility push(hidden)
   
 // ------------------------------------------------  
   
 int cli_Errno;  int cli_Errno;
 char cli_Error[STRSIZ];  char cli_Error[STRSIZ];
   
 #pragma GCC visibility pop  #pragma GCC visibility pop
   
 // cli_GetErrno() Get error code of last operation  // cli_GetErrno() Get error code of last operation
inline intint
 cli_GetErrno()  cli_GetErrno()
 {  {
         return cli_Errno;          return cli_Errno;
 }  }
   
// io_GetError() Get error text of last operation// cli_GetError() Get error text of last operation
inline const char *const char *
 cli_GetError()  cli_GetError()
 {  {
         return cli_Error;          return cli_Error;
 }  }
   
 // cli_SetErr() Set error to variables for internal use!!!  // cli_SetErr() Set error to variables for internal use!!!
inline voidvoid
 cli_SetErr(int eno, char *estr, ...)  cli_SetErr(int eno, char *estr, ...)
 {  {
         va_list lst;          va_list lst;
   
         cli_Errno = eno;          cli_Errno = eno;
        memset(cli_Error, 0, STRSIZ);        memset(cli_Error, 0, sizeof cli_Error);
         va_start(lst, estr);          va_start(lst, estr);
        vsnprintf(cli_Error, STRSIZ, estr, lst);        vsnprintf(cli_Error, sizeof cli_Error, estr, lst);
         va_end(lst);          va_end(lst);
 }  }
   
Line 90  clrscrEOL(linebuffer_t * __restrict buf) Line 88  clrscrEOL(linebuffer_t * __restrict buf)
 {  {
         register int i;          register int i;
   
        if (buf) {        if (buf && buf->line_prompt) {
                 write(buf->line_out, K_CR, 1);                  write(buf->line_out, K_CR, 1);
   
                 for (i = 0; i < buf->line_len; i++)                  for (i = 0; i < buf->line_len; i++)
Line 102  static inline void Line 100  static inline void
 printfEOL(linebuffer_t * __restrict buf, int len, int prompt)  printfEOL(linebuffer_t * __restrict buf, int len, int prompt)
 {  {
         if (buf) {          if (buf) {
                write(buf->line_out, K_CR, 1);                if (prompt && buf->line_prompt) {
                        write(buf->line_out, K_CR, 1);
                if (prompt && buf->line_prompt) 
                         write(buf->line_out, buf->line_prompt, buf->line_bol);                          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);                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) {        if (buf && prompt && buf->line_prompt) {
                 write(buf->line_out, K_CR, 1);                  write(buf->line_out, K_CR, 1);
                write(buf->line_out, buf->line_prompt, buf->line_bol);
                if (prompt) 
                        if (prompt && buf->line_prompt) 
                                write(buf->line_out, buf->line_prompt, buf->line_bol); 
         }          }
 }  }
   
Line 138  printfNL(linebuffer_t * __restrict buf, int prompt) Line 134  printfNL(linebuffer_t * __restrict buf, int prompt)
 // ------------------------------------------------------------  // ------------------------------------------------------------
   
 static int  static int
bufCHAR(int idx, void * __restrict buffer)bufCHAR(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;
   
         pos = buf->line_eol - buf->line_bol;          pos = buf->line_eol - buf->line_bol;
Line 169  bufCHAR(int idx, void * __restrict buffer) Line 165  bufCHAR(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufEOL(int idx, void * __restrict buffer)bufEOL(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);        printfCR(cli_buffer, 1);
         return RETCODE_EOL;          return RETCODE_EOL;
 }  }
   
 static int  static int
bufEOF(int idx, void * __restrict buffer)bufEOF(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;
         */          */
   
Line 190  bufEOF(int idx, void * __restrict buffer) Line 186  bufEOF(int idx, void * __restrict buffer)
 }  }
   
 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 221  bufUP(int idx, void * __restrict buffer) Line 217  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 252  bufDOWN(int idx, void * __restrict buffer) Line 248  bufDOWN(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufCLR(int idx, void * __restrict buffer)bufCLR(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;
   
        clrscrEOL(buffer);        clrscrEOL(cli_buffer);
        cli_freeLine(buffer);        cli_freeLine(cli_buffer);
   
        printfCR(buffer, 1);        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 290  bufBS(int idx, void * __restrict buffer) Line 286  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 310  bufBTAB(int idx, void * __restrict buffer) Line 306  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 322  bufMODE(int idx, void * __restrict buffer) Line 318  bufMODE(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufBEGIN(int idx, void * __restrict buffer)bufBEGIN(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_eol = buf->line_bol;          buf->line_eol = buf->line_bol;
Line 336  bufBEGIN(int idx, void * __restrict buffer) Line 332  bufBEGIN(int idx, void * __restrict buffer)
 }  }
   
 static int  static int
bufEND(int idx, void * __restrict buffer)bufEND(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_eol = buf->line_len - 1;          buf->line_eol = buf->line_len - 1;
Line 350  bufEND(int idx, void * __restrict buffer) Line 346  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 364  bufLEFT(int idx, void * __restrict buffer) Line 360  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 378  bufRIGHT(int idx, void * __restrict buffer) Line 374  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 400  bufDEL(int idx, void * __restrict buffer) Line 396  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;
   
        if (!buffer || idx < 0 || idx > MAX_BINDKEY)        if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
   
        str = io_strdup(buf->line_buf);        str = e_strdup(buf->line_buf);
         if (!str)          if (!str)
                 return RETCODE_ERR;                  return RETCODE_ERR;
         else {          else {
                 s = str;                  s = str;
                io_TrimStr(s);                str_Trim(s);
         }          }
   
         i = j = 0;          i = j = 0;
Line 424  bufComp(int idx, void * __restrict buffer) Line 420  bufComp(int idx, void * __restrict buffer)
         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 453  bufComp(int idx, void * __restrict buffer) Line 452  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 488  bufComp(int idx, void * __restrict buffer) Line 487  bufComp(int idx, void * __restrict buffer)
         }          }
   
 endcomp:  endcomp:
        io_free(str);        e_free(str);
         return ret;          return ret;
 }  }
   
 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;
   
           if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           if (buf->line_level > 0) {
                   printfNL(cli_buffer, 0);
                   buf->line_level--;
                   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
 */  */
inline voidvoid
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(cli_buffer->line_out, "a");
                 if (!f) {                  if (!f) {
                         LOGERR;                          LOGERR;
                         return;                          return;
Line 533  cli_Printf(linebuffer_t * __restrict buffer, char *fmt Line 549  cli_Printf(linebuffer_t * __restrict buffer, char *fmt
                 vfprintf(f, fmt, lst);                  vfprintf(f, fmt, lst);
                 va_end(lst);                  va_end(lst);
         } else          } else
                cli_SetErr(EINVAL, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
   
 /*  /*
 * cli_PrintHelp() Print help screen * cli_PrintHelp() - Print help screen
 * @buffer = CLI buffer *
  * @cli_buffer = CLI buffer
  * return: none   * return: none
 */  */
inline voidvoid
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, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
   
   
 /*  /*
 * 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, "Error:: 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 580  cli_BindKey(bindkey_t * __restrict key, linebuffer_t * Line 599  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, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        cmd = io_malloc(sizeof(struct tagCommand));        cmd = e_malloc(sizeof(struct tagCommand));
         if (!cmd) {          if (!cmd) {
                 LOGERR;                  LOGERR;
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 614  cli_addCommand(linebuffer_t * __restrict buffer, const Line 635  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, "Error:: 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);
                        io_free(cmd);                        e_free(cmd);
                         break;                          break;
                 }                  }
   
Line 648  cli_delCommand(linebuffer_t * __restrict buffer, const Line 670  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, "Error:: 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 688  cli_updCommand(linebuffer_t * __restrict buffer, const Line 713  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, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        if (!(h = io_malloc(sizeof(struct tagHistory)))) {        if (!(h = e_malloc(sizeof(struct tagHistory)))) {
                 LOGERR;                  LOGERR;
                 return RETCODE_ERR;                  return RETCODE_ERR;
         } else          } else
Line 711  cli_addHistory(linebuffer_t * __restrict buffer, const Line 737  cli_addHistory(linebuffer_t * __restrict buffer, const
   
         if (str) {          if (str) {
                 if (!*str) {                  if (!*str) {
                        io_free(h);                        e_free(h);
                         return RETCODE_OK;                          return RETCODE_OK;
                 }                  }
   
                 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) {
                        io_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));
                io_TrimStr(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, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
         if (!histfile)          if (!histfile)
Line 762  cli_saveHistory(linebuffer_t * __restrict buffer, cons Line 789  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 778  cli_saveHistory(linebuffer_t * __restrict buffer, cons Line 805  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, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
         if (!histfile)          if (!histfile)
Line 807  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 835  cli_loadHistory(linebuffer_t * __restrict buffer, cons
                 if (!*buf || *buf == '#')                  if (!*buf || *buf == '#')
                         continue;                          continue;
                 else                  else
                        io_TrimStr(buf);                        str_Trim(buf);
   
                if (!(h = io_malloc(sizeof(struct tagHistory)))) {                if (!(h = e_malloc(sizeof(struct tagHistory)))) {
                         LOGERR;                          LOGERR;
                         fclose(f);                          fclose(f);
                         return RETCODE_ERR;                          return RETCODE_ERR;
Line 817  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 845  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 826  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 854  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
 */  */
inline voidvoid
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_freeLine() - Clear entire line
 * @buffer = CLI buffer *
  * @cli_buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
inline intint
cli_freeLine(linebuffer_t * __restrict buffer)cli_freeLine(linebuffer_t * __restrict cli_buffer)
 {  {
         int code = RETCODE_ERR;          int code = RETCODE_ERR;
   
        if (buffer) {        if (cli_buffer) {
                if (buffer->line_buf)                if (cli_buffer->line_buf)
                        io_free(buffer->line_buf);                        e_free(cli_buffer->line_buf);
   
                buffer->line_buf = io_malloc(BUFSIZ);                cli_buffer->line_buf = e_malloc(BUFSIZ);
                if (buffer->line_buf) {                if (cli_buffer->line_buf) {
                        memset(buffer->line_buf, 0, BUFSIZ);                        memset(cli_buffer->line_buf, 0, BUFSIZ);
                        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;
   
                         code = RETCODE_OK;                          code = RETCODE_OK;
                 } else                  } else
                         LOGERR;                          LOGERR;
         } else          } else
                cli_SetErr(EINVAL, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
   
         return code;          return code;
 }  }
   
 /*  /*
 * 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
 */  */
inline voidvoid
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) {
                        io_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 = io_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;
                 }                  }
         } else          } else
                cli_SetErr(EINVAL, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
   
   
 /*  /*
 * 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);
                        io_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);
                        io_free(h);                        e_free(h);
                 }                  }
   
                if (buffer->line_prompt)                if (cli_buffer->line_prompt)
                        io_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
   
                if (buffer->line_keys)                if (cli_buffer->line_keys)
                        io_free(buffer->line_keys);                        e_free(cli_buffer->line_keys);
                if (buffer->line_buf)                if (cli_buffer->line_buf)
                        io_free(buffer->line_buf);                        e_free(cli_buffer->line_buf);
   
                io_free(buffer);                e_free(cli_buffer);
                buffer = NULL;                cli_buffer = NULL;
         } else          } else
                cli_SetErr(EINVAL, "Error:: invalid input parameters ...");                cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
   
 /*  /*
 * cliInit() Start CLI session, allocate memory for resources and bind keys * cliInit() - Start CLI session, allocate memory for resources and bind keys
  *
  * @fin = Input device handle   * @fin = Input device handle
  * @fout = Output device handle   * @fout = Output device handle
  * @prompt = text for prompt, if NULL disable prompt   * @prompt = text for prompt, if NULL disable prompt
Line 941  cliEnd(linebuffer_t * __restrict buffer) Line 974  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;
         register int i;          register int i;
   
         /* init buffer */          /* init buffer */
        buffer = io_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 = io_strdup(prompt);                        cli_buffer->line_prompt = e_strdup(prompt);
                        if (!buffer->line_prompt) {                        if (!cli_buffer->line_prompt) {
                                 LOGERR;                                  LOGERR;
                                io_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 = io_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)
                        io_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
                io_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;
         }          }
        keys = io_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)
                        io_free(buffer->line_prompt);                        e_free(cli_buffer->line_prompt);
                io_free(buffer->line_buf);                e_free(cli_buffer->line_buf);
                io_free(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));
   
         /* 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 = (u_char) i;
                 keys[i].key_len = 1;                  keys[i].key_len = 1;
Line 1006  cliInit(int fin, int fout, const char *prompt) Line 1048  cliInit(int fin, int fout, const char *prompt)
                         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)                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 (cli_buffer->line_prompt && i == *K_CTRL_C)
                         keys[i].key_func = bufCLR;                          keys[i].key_func = bufCLR;
                if (i == *K_CTRL_A)                if (cli_buffer->line_prompt && i == *K_CTRL_A)
                         keys[i].key_func = bufBEGIN;                          keys[i].key_func = bufBEGIN;
                if (i == *K_CTRL_E)                if (cli_buffer->line_prompt && i == *K_CTRL_E)
                         keys[i].key_func = bufEND;                          keys[i].key_func = bufEND;
                if (i == *K_TAB)                if (cli_buffer->line_prompt && i == *K_TAB)
                         keys[i].key_func = bufComp;                          keys[i].key_func = bufComp;
                   if (cli_buffer->line_prompt && i == *K_CTRL_Z)
                           keys[i].key_func = bufEndNode;
                 if (i >= *K_SPACE && i < *K_BACKSPACE)                  if (i >= *K_SPACE && i < *K_BACKSPACE)
                         keys[i].key_func = bufCHAR;                          keys[i].key_func = bufCHAR;
                 if (i > *K_BACKSPACE && i < 0xff)                  if (i > *K_BACKSPACE && i < 0xff)
                         keys[i].key_func = bufCHAR;                          keys[i].key_func = bufCHAR;
                if (i == '?')                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] = 0x1b;
                 keys[i].key_ch[1] = (u_char) i - 256;                  keys[i].key_ch[1] = (u_char) i - 256;
                 keys[i].key_len = 2;                  keys[i].key_len = 2;
         }          }
   
        // 3 bytes        /* 3 bytes */
         keys[i].key_len = sizeof K_F1 - 1;          keys[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);
         i++;          i++;
Line 1116  cliInit(int fin, int fout, const char *prompt) Line 1160  cliInit(int fin, int fout, const char *prompt)
         memcpy(keys[i].key_ch, K_CTRL_F12, keys[i].key_len);          memcpy(keys[i].key_ch, K_CTRL_F12, keys[i].key_len);
         i++;          i++;
         keys[i].key_len = sizeof K_HOME - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_END - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_UP - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_DOWN - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_RIGHT - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_LEFT - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_BTAB - 1;          keys[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);
         i++;          i++;
        // 4 bytes        /* 4 bytes */
         keys[i].key_len = sizeof K_INS - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_DEL - 1;          keys[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);
         i++;          i++;
         keys[i].key_len = sizeof K_PGUP - 1;          keys[i].key_len = sizeof K_PGUP - 1;
Line 1158  cliInit(int fin, int fout, const char *prompt) Line 1211  cliInit(int fin, int fout, const char *prompt)
         keys[i].key_len = sizeof K_PGDN - 1;          keys[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);
         i++;          i++;
        // 5 bytes        /* 5 bytes */
         keys[i].key_len = sizeof K_F5 - 1;          keys[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);
         i++;          i++;
Line 1184  cliInit(int fin, int fout, const char *prompt) Line 1237  cliInit(int fin, int fout, const char *prompt)
         memcpy(keys[i].key_ch, K_F12, keys[i].key_len);          memcpy(keys[i].key_ch, K_F12, keys[i].key_len);
         i++;          i++;
   
        buffer->line_keys = keys;        cli_buffer->line_keys = keys;
        return buffer;        return cli_buffer;
 }  }
   
 /*  /*
 * cliInitLine() Init CLI input line terminal * cliInitLine() - Init CLI input line terminal
 * @buffer = CLI buffer *
  * @cli_buffer = CLI buffer
  * return: none   * return: none
 */  */
 int  int
cliInitLine(linebuffer_t * __restrict buffer)cliInitLine(linebuffer_t * __restrict cli_buffer)
 {  {
         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);        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);
 }  }
   
 /*  /*
 * cliReadLine() Read line from opened CLI session * cliReadLine() - Read line from opened CLI session
 * @buffer = CLI buffer *
 * return: NULL if error or !=NULL readed line, must be io_free after use! * @cli_buffer = CLI buffer
  * @timeout = Session timeout (-1 infinit)
  * @cmd_name = If timeout reached, we should call with this cmd_name (default name is "exit")
  * 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, const char *cmd_name)
 {  {
        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, "Error:: 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) {
                                 if (str)
                                         e_free(str);
                                 str = e_strdup(cmd_name ? cmd_name : "exit");
                         } else
                                 LOGERR;
                         return str;                          return str;
                 }                  }
   
                 memset(buf, 0, sizeof buf);                  memset(buf, 0, sizeof buf);
                readLen = read(buffer->line_in, buf, BUFSIZ);                readLen = read(cli_buffer->line_in, buf, BUFSIZ);
                 if (readLen == -1) {                  if (readLen == -1) {
                         LOGERR;                          LOGERR;
                         return str;                          return str;
                 }                  }
                 if (!readLen) {                  if (!readLen) {
                        if (buffer->line_buf)                        if (cli_buffer->line_buf)
                                str = io_strdup(buffer->line_buf);                                str = e_strdup(cli_buffer->line_buf);
                         else                          else
                                cli_SetErr(EPIPE, "Error:: unknown state ...");                                cli_SetErr(EPIPE, "Unknown state ...");
                         return str;                          return str;
                 }                  }
   
 recheck:  recheck:
                 for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)                  for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                        if (readLen >= buffer->line_keys[i].key_len &&                         if (readLen >= cli_buffer->line_keys[i].key_len && 
                                        !memcmp(buffer->line_keys[i].key_ch, buf,                                         !memcmp(cli_buffer->line_keys[i].key_ch, buf, 
                                                buffer->line_keys[i].key_len)) {                                                cli_buffer->line_keys[i].key_len)) {
                                readLen -= buffer->line_keys[i].key_len;                                readLen -= cli_buffer->line_keys[i].key_len;
                                 if (readLen)                                  if (readLen)
                                        memmove(buf, buf + buffer->line_keys[i].key_len, readLen);                                        memmove(buf, buf + cli_buffer->line_keys[i].key_len, readLen);
                                 else                                  else
                                        memset(buf, 0, buffer->line_keys[i].key_len);                                        memset(buf, 0, cli_buffer->line_keys[i].key_len);
   
                                if (buffer->line_keys[i].key_func)                                if (cli_buffer->line_keys[i].key_func)
                                        if ((code = buffer->line_keys[i].key_func(i, buffer)))                                        if ((code = cli_buffer->line_keys[i].key_func(i, cli_buffer)))
                                                 readLen = 0;                                                  readLen = 0;
   
                                 if (readLen)                                  if (readLen)
Line 1275  recheck: Line 1339  recheck:
                         break;                          break;
         }          }
   
        if (code != RETCODE_ERR && code != RETCODE_EOF && buffer->line_buf)        if (code != RETCODE_ERR && code != RETCODE_EOF && cli_buffer->line_buf)
                str = io_strdup(buffer->line_buf);                str = e_strdup(cli_buffer->line_buf);
         return str;          return str;
 }  }
   
   
 /*  /*
 * 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)
    * @cmd_name = If timeout reached, we should call with this cmd_name (default name is "exit")
  * 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, const char *cmd_name)
 {  {
         u_char buf[BUFSIZ];          u_char buf[BUFSIZ];
         int pid, stat, pty, r, s, alen, flg, attrlen = 0, ret = 0;          int pid, stat, pty, r, s, alen, flg, attrlen = 0, ret = 0;
Line 1302  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1370  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, "Error:: 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, cmd_name) < 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 1344  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1412  cliNetLoop(linebuffer_t * __restrict buffer, const cha
                                         memset(buf, 0, BUFSIZ);                                          memset(buf, 0, BUFSIZ);
                                         if ((ret = cli_telnetRecv(sock, &a, &alen, buf, BUFSIZ)) < 0) {                                          if ((ret = cli_telnetRecv(sock, &a, &alen, buf, BUFSIZ)) < 0) {
                                                 if (a)                                                  if (a)
                                                        io_free(a);                                                        e_free(a);
   
                                                 if (-2 == ret)                                                  if (-2 == ret)
                                                         continue;                                                          continue;
Line 1367  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1435  cliNetLoop(linebuffer_t * __restrict buffer, const cha
                                                 cli_telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_LINEMODE);                                                  cli_telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_LINEMODE);
                                         }                                          }
                                         if (a)                                          if (a)
                                                io_free(a);                                                e_free(a);
   
                                         if ((ret = write(pty, buf, ret)) == -1) {                                          if ((ret = write(pty, buf, ret)) == -1) {
                                                 LOGERR;                                                  LOGERR;
Line 1397  cliNetLoop(linebuffer_t * __restrict buffer, const cha Line 1465  cliNetLoop(linebuffer_t * __restrict buffer, const cha
 }  }
   
 /*  /*
 * cliLoop() CLI main loop * cliLoop() - CLI main loop
 * @buffer = CLI buffer *
  * @cli_buffer = CLI buffer
  * @csHistFile = History file name   * @csHistFile = History file name
    * @timeout = Session timeout (-1 infinit)
    * @cmd_name = If timeout reached, we should call with this cmd_name (default name is "exit")
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
 int  int
cliLoop(linebuffer_t * __restrict buffer, const char *csHistFile)cliLoop(linebuffer_t * __restrict cli_buffer, const char *csHistFile
                 int timeout, const char *cmd_name)
 {  {
         char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];          char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];
         register int i;          register int i;
Line 1411  cliLoop(linebuffer_t * __restrict buffer, const char * Line 1483  cliLoop(linebuffer_t * __restrict buffer, const char *
         struct tagCommand *cmd;          struct tagCommand *cmd;
   
         /* --- main body of CLI --- */          /* --- main body of CLI --- */
        cliInitLine(buffer);        cliInitLine(cli_buffer);
   
        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, cmd_name);
                 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                  // clear whitespaces
                 for (s = line; isspace((int) *s); s++);                  for (s = line; isspace((int) *s); s++);
                 if (*s) {                  if (*s) {
Line 1432  cliLoop(linebuffer_t * __restrict buffer, const char * Line 1504  cliLoop(linebuffer_t * __restrict buffer, const char *
   
                 if (*s) {                  if (*s) {
                         memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);                          memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
                        for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t"));                         for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && 
                                        *app ? app++ : app);                                        (*app = strsep(&s, " \t")); *app ? app++ : app);
   
                         // exec_cmd ...                          // exec_cmd ...
                         i = 0;                          i = 0;
                        SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) {                        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])))                                  if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))
                                         break;                                          break;
                                 else                                  else
Line 1445  cliLoop(linebuffer_t * __restrict buffer, const char * Line 1519  cliLoop(linebuffer_t * __restrict buffer, const char *
                         }                          }
   
                         if (!cmd) {                          if (!cmd) {
                                cli_Printf(buffer, "\nCommand '%s' not found!\n", items[0]);                                cli_Printf(cli_buffer, "\nCommand '%s' not found!\n", items[0]);
                                 ret = -1;                                  ret = -1;
                         } else                          } else
                                 if (cmd->cmd_func) {                                  if (cmd->cmd_func) {
                                        cli_Printf(buffer, "\n");                                        cli_Printf(cli_buffer, "\n");
                                        ret = cmd->cmd_func(buffer, i, items);                                        ret = cmd->cmd_func(cli_buffer, 
                                                         cli_buffer->line_level, items);
                                 } else {                                  } else {
                                        clrscrEOL(buffer);                                        clrscrEOL(cli_buffer);
                                        printfCR(buffer, 1);                                        printfCR(cli_buffer, 1);
                                 }                                  }
                 }                  }
   
                cli_freeLine(buffer);                cli_freeLine(cli_buffer);
                cli_resetHistory(buffer);                cli_resetHistory(cli_buffer);
                io_free(line);                e_free(line);
         } while (ret < 1);          } while (ret < 1);
   
        cli_saveHistory(buffer, csHistFile, HISTORY_LINES);        cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);
         return ret;          return ret;
 }  }

Removed from v.1.5  
changed lines
  Added in v.1.11


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