Diff for /libaitcli/src/aitcli.c between versions 1.2.2.3 and 1.5.4.1

version 1.2.2.3, 2010/06/04 13:51:21 version 1.5.4.1, 2013/01/17 16:04:31
Line 5 Line 5
 * $Author$  * $Author$
 * $Id$  * $Id$
 *  *
*************************************************************************/**************************************************************************
#include "global.h"The ELWIX and AITNET software is distributed under the following
 terms:
   
   All of the documentation and software included in the ELWIX and AITNET
   Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
#pragma GCC visibility push(hidden)Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
         by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
/*Redistribution and use in source and binary forms, with or without
commands_t cli_stdCmds[] = {modification, are permitted provided that the following conditions
        { "test", cli_Cmd_Unsupported, "Test - Don`t use default command structure!", "test <cr>", cli_Comp_Filename }, are met:
        { "-------", NULL, "---------------------", NULL, NULL }, 1. Redistributions of source code must retain the above copyright
        { "help", cli_Cmd_Help, "Help screen", "help [command] <cr>", NULL },    notice, this list of conditions and the following disclaimer.
        { "exit", cli_Cmd_Exit, "Exit from console", "exit <cr>", NULL }, 2. Redistributions in binary form must reproduce the above copyright
        { NULL, NULL, NULL, NULL }   notice, this list of conditions and the following disclaimer in the
};   documentation and/or other materials provided with the distribution.
 3. All advertising materials mentioning features or use of this software
    must display the following acknowledgement:
 This product includes software developed by Michael Pounov <misho@elwix.org>
 ELWIX - Embedded LightWeight unIX and its contributors.
 4. Neither the name of AITNET nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.
 */  */
   #include "global.h"
   #include "cli.h"
   
 // ------------------------------------------------  
   
   #pragma GCC visibility push(hidden)
   
 int cli_Errno;  int cli_Errno;
 char cli_Error[STRSIZ];  char cli_Error[STRSIZ];
   
Line 35  cli_GetErrno() Line 61  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 *  inline const char *
 cli_GetError()  cli_GetError()
 {  {
Line 49  cli_SetErr(int eno, char *estr, ...) Line 75  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 96  printfCR(linebuffer_t * __restrict buf, int prompt) Line 122  printfCR(linebuffer_t * __restrict buf, int prompt)
 }  }
   
 static inline void  static inline void
printfCLI(linebuffer_t * __restrict buf, const unsigned char *text, int textlen, int prompt)printfNL(linebuffer_t * __restrict buf, int prompt)
 {  {
        if (buf && text && textlen) {        if (buf) {
                if (prompt && buf->line_prompt)                write(buf->line_out, K_ENTER, 1);
                        write(buf->line_out, buf->line_prompt, buf->line_bol); 
   
                write(buf->line_out, text, textlen);                if (prompt)
                         if (prompt && buf->line_prompt)
                                 write(buf->line_out, buf->line_prompt, buf->line_bol);
         }          }
 }  }
   
Line 132  bufCHAR(int idx, void * __restrict buffer) Line 159  bufCHAR(int idx, void * __restrict buffer)
         write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);          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) {
                printfCLI(buf, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len,                 write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, 
                                buf->line_len - buf->line_eol, 0);                                buf->line_len - buf->line_eol);
                 printfEOL(buf, -1, 1);                  printfEOL(buf, -1, 1);
         }          }
         return RETCODE_OK;          return RETCODE_OK;
Line 152  bufEOL(int idx, void * __restrict buffer) Line 179  bufEOL(int idx, void * __restrict buffer)
 static int  static int
 bufEOF(int idx, void * __restrict buffer)  bufEOF(int idx, void * __restrict buffer)
 {  {
        linebuffer_t *buf = buffer;        /*
 
         if (!buffer || idx < 0 || idx > MAX_BINDKEY)          if (!buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
           */
   
         write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);  
         return RETCODE_EOF;          return RETCODE_EOF;
 }  }
   
Line 371  bufDEL(int idx, void * __restrict buffer) Line 397  bufDEL(int idx, void * __restrict buffer)
         return RETCODE_OK;          return RETCODE_OK;
 }  }
   
// ---------------------------------------------------------------static int
 bufComp(int idx, void * __restrict buffer)
 {
         linebuffer_t *buf = buffer;
         char *str, *s, **app, *items[MAX_PROMPT_ITEMS], szLine[STRSIZ];
         register int i, j;
         struct tagCommand *cmd, *c;
         int pos, ret = RETCODE_OK;
   
           if (!buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           str = e_strdup(buf->line_buf);
           if (!str)
                   return RETCODE_ERR;
           else {
                   s = str;
                   str_Trim(s);
           }
   
           i = j = 0;
           c = NULL;
           memset(szLine, 0, STRSIZ);
           if (*s) {
                   memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
                   for (app = items, i = 0; app < items + MAX_PROMPT_ITEMS - 1 && (*app = strsep(&s, " \t")); 
                                   *app ? i++ : i, *app ? app++ : app);
   
                   if (i) {
                           SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {
                                   if (cmd->cmd_level == buf->line_level && 
                                                   !strncmp(cmd->cmd_name, items[0], strlen(items[0]))) {
                                           if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) {
                                                   j++;
                                                   c = cmd;
                                                   strlcat(szLine, " ", STRSIZ);
                                                   strlcat(szLine, cmd->cmd_name, STRSIZ);
                                           }
                                   }
                           }
   
                           if (i > 1 && c) {
                                   /* we are on argument of command and has complition info */
                                   j++;    // always must be j > 1 ;) for arguments
                                   strlcpy(szLine, c->cmd_info, STRSIZ);
                           }
                   } else {
                           /* we have valid char but i == 0, this case is illegal */
                           ret = RETCODE_ERR;
                           goto endcomp;
                   }
           } else {
                   /* we on 0 position of prompt, show commands for this level */
                   SLIST_FOREACH(cmd, &buf->line_cmds, cmd_next) {
                           if (cmd->cmd_level == buf->line_level)
                                   if (strncmp(cmd->cmd_name, CLI_CMD_SEP, strlen(CLI_CMD_SEP))) {
                                           j++;
                                           c = cmd;
                                           strlcat(szLine, " ", STRSIZ);
                                           strlcat(szLine, cmd->cmd_name, STRSIZ);
                                   }
                   }
           }
   
           /* completion show actions ... */
           if (j > 1 && c) {
                   printfNL(buf, 0);
                   write(buf->line_out, szLine, strlen(szLine));
                   printfNL(buf, 1);
                   printfEOL(buf, buf->line_len - 1, 1);
                   printfEOL(buf, -1, 1);
           }
           if (j == 1 && c) {
                   clrscrEOL(buf);
                   cli_freeLine(buf);
   
                   pos = buf->line_eol - buf->line_bol;
   
                   buf->line_len += c->cmd_len + 1;
                   buf->line_eol += c->cmd_len + 1;
   
                   memcpy(buf->line_buf + pos, c->cmd_name, c->cmd_len);
                   buf->line_buf[pos + c->cmd_len] = (u_char) *K_SPACE;
                   buf->line_buf[buf->line_len - 1] = 0;
   
                   printfEOL(buf, -1, 1);
           }
   
   endcomp:
           e_free(str);
           return ret;
   }
   
   static int
   bufHelp(int idx, void * __restrict buffer)
   {
           linebuffer_t *buf = buffer;
   
           if (!buffer || idx < 0 || idx > MAX_BINDKEY)
                   return RETCODE_ERR;
   
           cli_Cmd_Help(buf, -1, NULL);
   
           printfEOL(buf, buf->line_len - 1, 1);
           printfEOL(buf, -1, 1);
           return RETCODE_OK;
   }
   
   
 /*  /*
 * cli_BindKey() Bind function to key * cli_Printf() - Send message to CLI session
  *
  * @buffer = CLI buffer
  * @fmt = printf format string
  * @... = arguments defined in fmt
  * return: none
 */
 inline void
 cli_Printf(linebuffer_t * __restrict buffer, char *fmt, ...)
 {
         va_list lst;
         FILE *f;
 
         if (fmt) {
                 f = fdopen(buffer->line_out, "a");
                 if (!f) {
                         LOGERR;
                         return;
                 }
 
                 va_start(lst, fmt);
                 vfprintf(f, fmt, lst);
                 va_end(lst);
         } else
                 cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
 }
 
 /*
  * cli_PrintHelp() - Print help screen
  *
  * @buffer = CLI buffer
  * return: none
 */
 inline void
 cli_PrintHelp(linebuffer_t * __restrict buffer)
 {
         if (buffer) {
                 bufHelp(0, buffer);
                 clrscrEOL(buffer);
         } else
                 cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
 }
 
 
 /*
  * cli_BindKey() - Bind function to key
  *
  * @key = key structure   * @key = key structure
  * @buffer = CLI buffer   * @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
Line 401  cli_BindKey(bindkey_t * __restrict key, linebuffer_t * Line 580  cli_BindKey(bindkey_t * __restrict key, linebuffer_t *
   
   
 /*  /*
 * cli_addHistory() Add line to history * cli_addCommand() - Add command to CLI session
  *
  * @buffer = CLI buffer   * @buffer = CLI buffer
 * @str = Add text * @csCmd = Command name
  * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
  * @funcCmd = Callback function when user call command
  * @csInfo = Inline information for command
  * @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, 
                   const char *csInfo, const char *csHelp)
   {
           struct tagCommand *cmd;
   
           if (!buffer || !csCmd) {
                   cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
                   return RETCODE_ERR;
           }
   
           cmd = e_malloc(sizeof(struct tagCommand));
           if (!cmd) {
                   LOGERR;
                   return RETCODE_ERR;
           } else
                   memset(cmd, 0, sizeof(struct tagCommand));
   
           cmd->cmd_level = cliLevel;
           cmd->cmd_func = funcCmd;
           cmd->cmd_len = strlcpy(cmd->cmd_name, csCmd, STRSIZ);
           if (csInfo)
                   strlcpy(cmd->cmd_info, csInfo, STRSIZ);
           if (csHelp)
                   strlcpy(cmd->cmd_help, csHelp, STRSIZ);
           SLIST_INSERT_HEAD(&buffer->line_cmds, cmd, cmd_next);
           return RETCODE_OK;
   }
   
   /*
    * cli_delCommand() - Delete command from CLI session
    *
    * @buffer = CLI buffer
    * @csCmd = Command name
    * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
   cli_delCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel)
   {
           struct tagCommand *cmd;
           int ret = RETCODE_OK;
   
           if (!buffer || !csCmd) {
                   cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
                   return RETCODE_ERR;
           }
   
           SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) 
                   if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) {
                           ret = 1;
                           SLIST_REMOVE(&buffer->line_cmds, cmd, tagCommand, cmd_next);
                           e_free(cmd);
                           break;
                   }
   
           return ret;
   }
   
   /*
    * cli_updCommand() - Update command in CLI session
    *
    * @buffer = CLI buffer
    * @csCmd = Command name
    * @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
    * @funcCmd = Callback function when user call command
    * @csInfo = Inline information for command
    * @csHelp = Help line when call help
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
   cli_updCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd, 
                   const char *csInfo, const char *csHelp)
   {
           struct tagCommand *cmd;
           int ret = RETCODE_OK;
   
           if (!buffer || !csCmd) {
                   cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
                   return RETCODE_ERR;
           }
   
           SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) 
                   if (cmd->cmd_level == cliLevel && !strcmp(cmd->cmd_name, csCmd)) {
                           ret = 1;
   
                           if (funcCmd)
                                   cmd->cmd_func = funcCmd;
                           if (csInfo)
                                   strlcpy(cmd->cmd_info, csInfo, STRSIZ);
                           if (csHelp)
                                   strlcpy(cmd->cmd_help, csHelp, STRSIZ);
   
                           break;
                   }
   
           return ret;
   }
   
   
   /*
    * cli_addHistory() - Add line to history
    *
    * @buffer = CLI buffer
    * @str = Add custom text or if NULL use readed line from CLI buffer
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
 cli_addHistory(linebuffer_t * __restrict buffer, const char * __restrict str)  cli_addHistory(linebuffer_t * __restrict buffer, const char * __restrict str)
 {  {
         struct tagHistory *h;          struct tagHistory *h;
Line 416  cli_addHistory(linebuffer_t * __restrict buffer, const Line 707  cli_addHistory(linebuffer_t * __restrict buffer, const
                 return RETCODE_ERR;                  return RETCODE_ERR;
         }          }
   
        if (!(h = malloc(sizeof(struct tagHistory)))) {        if (!(h = e_malloc(sizeof(struct tagHistory)))) {
                 LOGERR;                  LOGERR;
                 return RETCODE_ERR;                  return RETCODE_ERR;
         } else          } else
Line 424  cli_addHistory(linebuffer_t * __restrict buffer, const Line 715  cli_addHistory(linebuffer_t * __restrict buffer, const
   
         if (str) {          if (str) {
                 if (!*str) {                  if (!*str) {
                        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 (!*buffer->line_buf || buffer->line_len < 2) {
                        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, buffer->line_buf, (h->hist_len = buffer->line_len));
                io_TrimStr((u_char*) h->hist_line);                str_Trim(h->hist_line);
                 h->hist_len = strlen(h->hist_line);                  h->hist_len = strlen(h->hist_line);
         }          }
   
Line 445  cli_addHistory(linebuffer_t * __restrict buffer, const Line 736  cli_addHistory(linebuffer_t * __restrict buffer, const
 }  }
   
 /*  /*
 * cli_saveHistory() Save history to file * cli_saveHistory() - Save history to file
  *
  * @buffer = CLI buffer   * @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
Line 491  cli_saveHistory(linebuffer_t * __restrict buffer, cons Line 783  cli_saveHistory(linebuffer_t * __restrict buffer, cons
 }  }
   
 /*  /*
 * cli_loadHistory() Load history from file * cli_loadHistory() - Load history from file
  *
  * @buffer = CLI buffer   * @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
Line 513  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 806  cli_loadHistory(linebuffer_t * __restrict buffer, cons
                 strlcpy(szFName, histfile, MAXPATHLEN);                  strlcpy(szFName, histfile, MAXPATHLEN);
   
         f = fopen(szFName, "r");          f = fopen(szFName, "r");
        if (!f) {        if (!f)
                LOGERR;                return RETCODE_OK;
                return RETCODE_ERR; 
        } 
   
         while (fgets(buf, BUFSIZ, f)) {          while (fgets(buf, BUFSIZ, f)) {
                 if (!*buf || *buf == '#')                  if (!*buf || *buf == '#')
                         continue;                          continue;
                 else                  else
                        io_TrimStr((u_char*) buf);                        str_Trim(buf);
   
                if (!(h = malloc(sizeof(struct tagHistory)))) {                if (!(h = e_malloc(sizeof(struct tagHistory)))) {
                         LOGERR;                          LOGERR;
                         fclose(f);                          fclose(f);
                         return RETCODE_ERR;                          return RETCODE_ERR;
Line 541  cli_loadHistory(linebuffer_t * __restrict buffer, cons Line 832  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   * @buffer = CLI buffer
  * return: none   * return: none
 */  */
Line 553  cli_resetHistory(linebuffer_t * __restrict buffer) Line 845  cli_resetHistory(linebuffer_t * __restrict buffer)
   
   
 /*  /*
 * cli_freeLine() Clear entire line * cli_freeLine() - Clear entire line
  *
  * @buffer = CLI buffer   * @buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
Line 564  cli_freeLine(linebuffer_t * __restrict buffer) Line 857  cli_freeLine(linebuffer_t * __restrict buffer)
   
         if (buffer) {          if (buffer) {
                 if (buffer->line_buf)                  if (buffer->line_buf)
                        free(buffer->line_buf);                        e_free(buffer->line_buf);
   
                buffer->line_buf = malloc(BUFSIZ);                buffer->line_buf = e_malloc(BUFSIZ);
                 if (buffer->line_buf) {                  if (buffer->line_buf) {
                         memset(buffer->line_buf, 0, BUFSIZ);                          memset(buffer->line_buf, 0, BUFSIZ);
                         buffer->line_eol = buffer->line_bol;                          buffer->line_eol = buffer->line_bol;
Line 582  cli_freeLine(linebuffer_t * __restrict buffer) Line 875  cli_freeLine(linebuffer_t * __restrict buffer)
 }  }
   
 /*  /*
 * cli_setPrompt() Set new prompt for CLI session * cli_setPrompt() - Set new prompt for CLI session
  *
  * @buffer = CLI buffer   * @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
Line 592  cli_setPrompt(linebuffer_t * __restrict buffer, const  Line 886  cli_setPrompt(linebuffer_t * __restrict buffer, const 
 {  {
         if (buffer) {          if (buffer) {
                 if (buffer->line_prompt) {                  if (buffer->line_prompt) {
                        free(buffer->line_prompt);                        e_free(buffer->line_prompt);
                         buffer->line_prompt = NULL;                          buffer->line_prompt = NULL;
                         buffer->line_bol = 0;                          buffer->line_bol = 0;
                 }                  }
   
                 if (prompt) {                  if (prompt) {
                        buffer->line_prompt = strdup(prompt);                        buffer->line_prompt = e_strdup(prompt);
                         if (buffer->line_prompt) {                          if (buffer->line_prompt) {
                                 buffer->line_bol = strlen(buffer->line_prompt);                                  buffer->line_bol = strlen(buffer->line_prompt);
                                 buffer->line_eol = buffer->line_bol;                                  buffer->line_eol = buffer->line_bol;
Line 612  cli_setPrompt(linebuffer_t * __restrict buffer, const  Line 906  cli_setPrompt(linebuffer_t * __restrict buffer, const 
   
   
 /*  /*
 * cliEnd() Clear data, Free resources and close CLI session * cliEnd() - Clear data, Free resources and close CLI session
  *
  * @buffer = CLI buffer   * @buffer = CLI buffer
  * return: RETCODE_ERR error, RETCODE_OK ok   * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
Line 620  void Line 915  void
 cliEnd(linebuffer_t * __restrict buffer)  cliEnd(linebuffer_t * __restrict buffer)
 {  {
         struct tagHistory *h;          struct tagHistory *h;
           struct tagCommand *c;
   
         if (buffer) {          if (buffer) {
                   while ((c = SLIST_FIRST(&buffer->line_cmds))) {
                           SLIST_REMOVE_HEAD(&buffer->line_cmds, cmd_next);
                           e_free(c);
                   }
                 while ((h = TAILQ_FIRST(&buffer->line_history))) {                  while ((h = TAILQ_FIRST(&buffer->line_history))) {
                         TAILQ_REMOVE(&buffer->line_history, h, hist_next);                          TAILQ_REMOVE(&buffer->line_history, h, hist_next);
                        free(h);                        e_free(h);
                 }                  }
   
                 if (buffer->line_prompt)                  if (buffer->line_prompt)
                        free(buffer->line_prompt);                        e_free(buffer->line_prompt);
   
                 if (buffer->line_keys)                  if (buffer->line_keys)
                        free(buffer->line_keys);                        e_free(buffer->line_keys);
                 if (buffer->line_buf)                  if (buffer->line_buf)
                        free(buffer->line_buf);                        e_free(buffer->line_buf);
   
                free(buffer);                e_free(buffer);
                 buffer = NULL;                  buffer = NULL;
         } else          } else
                 cli_SetErr(EINVAL, "Error:: invalid input parameters ...");                  cli_SetErr(EINVAL, "Error:: 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 654  cliInit(int fin, int fout, const char *prompt) Line 955  cliInit(int fin, int fout, const char *prompt)
         linebuffer_t *buffer;          linebuffer_t *buffer;
         bindkey_t *keys;          bindkey_t *keys;
         register int i;          register int i;
         struct termios t;  
   
         memset(&t, 0, sizeof t);  
         /* init buffer */          /* init buffer */
        buffer = malloc(sizeof (linebuffer_t));        buffer = e_malloc(sizeof(linebuffer_t));
         if (!buffer) {          if (!buffer) {
                 LOGERR;                  LOGERR;
                 return NULL;                  return NULL;
Line 669  cliInit(int fin, int fout, const char *prompt) Line 968  cliInit(int fin, int fout, const char *prompt)
                 buffer->line_out = fout;                  buffer->line_out = fout;
   
                 TAILQ_INIT(&buffer->line_history);                  TAILQ_INIT(&buffer->line_history);
                   SLIST_INIT(&buffer->line_cmds);
   
                 if (prompt) {                  if (prompt) {
                        buffer->line_prompt = strdup(prompt);                        buffer->line_prompt = e_strdup(prompt);
                         if (!buffer->line_prompt) {                          if (!buffer->line_prompt) {
                                 LOGERR;                                  LOGERR;
                                free(buffer);                                e_free(buffer);
                                 return NULL;                                  return NULL;
                         } else                          } else
                                 buffer->line_eol = buffer->line_bol = strlen(buffer->line_prompt);                                  buffer->line_eol = buffer->line_bol = strlen(buffer->line_prompt);
                 }                  }
         }          }
        buffer->line_buf = malloc(BUFSIZ);        buffer->line_buf = e_malloc(BUFSIZ);
         if (!buffer->line_buf) {          if (!buffer->line_buf) {
                 LOGERR;                  LOGERR;
                 if (buffer->line_prompt)                  if (buffer->line_prompt)
                        free(buffer->line_prompt);                        e_free(buffer->line_prompt);
                free(buffer);                e_free(buffer);
                 return NULL;                  return NULL;
         } else {          } else {
                 memset(buffer->line_buf, 0, BUFSIZ);                  memset(buffer->line_buf, 0, BUFSIZ);
                 buffer->line_len = 1 + buffer->line_eol;                  buffer->line_len = 1 + buffer->line_eol;
         }          }
        keys = 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 (buffer->line_prompt)
                        free(buffer->line_prompt);                        e_free(buffer->line_prompt);
                free(buffer->line_buf);                e_free(buffer->line_buf);
                free(buffer);                e_free(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 */
           cli_addCommand(buffer, "exit", 0, cli_Cmd_Exit, "exit <cr>", "Exit from console");
           cli_addCommand(buffer, "help", 0, cli_Cmd_Help, "help [command] <cr>", "Help screen");
           cli_addCommand(buffer, "-------", 0, 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 720  cliInit(int fin, int fout, const char *prompt) Line 1025  cliInit(int fin, int fout, const char *prompt)
                         keys[i].key_func = bufBEGIN;                          keys[i].key_func = bufBEGIN;
                 if (i == *K_CTRL_E)                  if (i == *K_CTRL_E)
                         keys[i].key_func = bufEND;                          keys[i].key_func = bufEND;
                   if (i == *K_TAB)
                           keys[i].key_func = bufComp;
                 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 == '?')
                           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 845  cliInit(int fin, int fout, const char *prompt) Line 1154  cliInit(int fin, int fout, const char *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);
         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;          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);
Line 860  cliInit(int fin, int fout, const char *prompt) Line 1169  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 886  cliInit(int fin, int fout, const char *prompt) Line 1195  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++;
   
         tcgetattr(buffer->line_in, &t);  
         t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);  
         t.c_iflag |= IGNBRK;  
         t.c_cc[VMIN] = 1;  
         t.c_cc[VTIME] = 0;  
         tcsetattr(buffer->line_in, TCSANOW, &t);  
   
         buffer->line_keys = keys;          buffer->line_keys = keys;
         return buffer;          return buffer;
 }  }
   
   
   
 /*  /*
 * cliNetInit() Initialize Readline if CLI bind to socket * cliInitLine() - Init CLI input line terminal
 * @csProg = program name *
 * @pty = Master pty * @buffer = CLI buffer
 * @term = stdin termios 
  * return: none   * return: none
 */  */
/*int
void cliNetInit(const char *csProg, int pty, struct termios *term)cliInitLine(linebuffer_t * __restrict buffer)
 {  {
         struct termios t;          struct termios t;
         int on = 1;  
   
         memset(&t, 0, sizeof t);          memset(&t, 0, sizeof t);
        if (term)        tcgetattr(buffer->line_in, &t);
                t = *term; 
        else { 
                t.c_lflag = TTYDEF_LFLAG; 
                t.c_iflag = TTYDEF_IFLAG; 
                t.c_oflag = TTYDEF_OFLAG; 
                t.c_cflag = TTYDEF_CFLAG; 
                cfsetspeed(&t, B9600); 
        } 
 
         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 &= ~(ICRNL | BRKINT | INPCK | ISTRIP | IXON);  
         t.c_iflag &= ~ICRNL;  
         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;
        tcsetattr(pty, TCSANOW, &t);        return tcsetattr(buffer->line_in, TCSANOW, &t);
 }
   
        ioctl(pty, TIOCPKT, &on);/*
  * cliReadLine() - Read line from opened CLI session
  *
  * @buffer = CLI buffer
  * return: NULL if error or !=NULL readed line, must be e_free after use!
 */
 char *
 cliReadLine(linebuffer_t * __restrict buffer)
 {
         int code, readLen;
         register int i;
         struct pollfd fds;
         char buf[BUFSIZ], *str = NULL;
   
        rl_readline_name = csProg;        if (!buffer) {
        rl_variable_bind("editing-mode", "emacs");                cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
                 return NULL;
         }
   
        rl_instream = fdopen(pty, "r");        memset(&fds, 0, sizeof fds);
        rl_outstream = NULL;        fds.fd = buffer->line_in;
         fds.events = POLLIN;
 
         printfCR(buffer, 1);
         while (42) {
                 if (poll(&fds, 1, -1) < 1) {
                         LOGERR;
                         return str;
                 }
 
                 memset(buf, 0, sizeof buf);
                 readLen = read(buffer->line_in, buf, BUFSIZ);
                 if (readLen == -1) {
                         LOGERR;
                         return str;
                 }
                 if (!readLen) {
                         if (buffer->line_buf)
                                 str = e_strdup(buffer->line_buf);
                         else
                                 cli_SetErr(EPIPE, "Error:: unknown state ...");
                         return str;
                 }
 
 recheck:
                 for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                         if (readLen >= buffer->line_keys[i].key_len && 
                                         !memcmp(buffer->line_keys[i].key_ch, buf, 
                                                 buffer->line_keys[i].key_len)) {
                                 readLen -= buffer->line_keys[i].key_len;
                                 if (readLen)
                                         memmove(buf, buf + buffer->line_keys[i].key_len, readLen);
                                 else
                                         memset(buf, 0, buffer->line_keys[i].key_len);
 
                                 if (buffer->line_keys[i].key_func)
                                         if ((code = buffer->line_keys[i].key_func(i, buffer)))
                                                 readLen = 0;
 
                                 if (readLen)
                                         goto recheck;
                                 else
                                         break;
                         }
 
                 if (code)
                         break;
         }
 
         if (code != RETCODE_ERR && code != RETCODE_EOF && buffer->line_buf)
                 str = e_strdup(buffer->line_buf);
         return str;
 }  }
*/
 
 /*  /*
 * cliNetExec() Execute net CLI main loop * cliNetLoop() - CLI network main loop binded to socket
 * @cmdList = Commands list *
 * @csPrompt = Prompt text * @buffer = CLI buffer
  * @csHistFile = History file name
  * @sock = client socket   * @sock = client socket
 * @term = stdin termios * return: RETCODE_ERR error, RETCODE_OK ok
 * @win = window size of tty 
 * return: -1 error, 0 = exit w/^+D, 1 done. 
 */  */
 int  int
cliNetExec(commands_t *cmdList, const char *csPrompt, int sock, struct termios *term, struct winsize *win)cliNetLoop(linebuffer_t * __restrict buffer, const char *csHistFile, int sock)
 {  {
        int pty, ret = 0, r, s, alen, attrlen, flg;        u_char buf[BUFSIZ];
         int pid, stat, pty, r, 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 };
         u_char buf[BUFSIZ];  
         struct telnetAttrs *a, Attr[10];          struct telnetAttrs *a, Attr[10];
   
        switch (forkpty(&pty, NULL, term, win)) {        switch ((pid = forkpty(&pty, NULL, NULL, NULL))) {
                 case -1:                  case -1:
                         LOGERR;                          LOGERR;
                         return -1;                          return -1;
                 case 0:                  case 0:
                        close(sock);                        if (!buffer) {
                                 cli_SetErr(EINVAL, "Error:: invalid input parameters ...");
                                 return -1;
                         } else
                                 close(sock);
   
                        ret = cliExec(cmdList, csPrompt) < 0 ? 1 : 0;                        ret = cliLoop(buffer, csHistFile) < 0 ? 1 : 0;
                        /* spawn Shell mode */                        cliEnd(buffer);
                        /*
                        execl("/bin/tcsh", "tcsh", NULL);                        exit(ret);
                        */ 
                        _exit(ret); 
                 default:                  default:
                        /* spawn Shell mode */                        cli_telnet_SetCmd(Attr + 0, DO, TELOPT_TTYPE);
                        telnet_SetCmd(Attr + 0, DO, TELOPT_TTYPE);                        cli_telnet_SetCmd(Attr + 1, WILL, TELOPT_ECHO);
                        telnet_SetCmd(Attr + 1, WILL, TELOPT_ECHO);                        cli_telnet_Set_SubOpt(Attr + 2, TELOPT_LFLOW, LFLOW_OFF, NULL, 0);
                        telnet_Set_SubOpt(Attr + 2, TELOPT_LFLOW, LFLOW_OFF, NULL, 0);                        cli_telnet_Set_SubOpt(Attr + 3, TELOPT_LFLOW, LFLOW_RESTART_XON, NULL, 0);
                        telnet_Set_SubOpt(Attr + 3, TELOPT_LFLOW, LFLOW_RESTART_XON, NULL, 0);                        cli_telnet_SetCmd(Attr + 4, DO, TELOPT_LINEMODE);
                        telnet_SetCmd(Attr + 4, DO, TELOPT_LINEMODE);                        if ((ret = cli_telnetSend(sock, Attr, 5, NULL, 0, 0)) == -1)
                        if ((ret = telnetSend(sock, Attr, 5, NULL, 0, 0)) == -1) { 
                                cli_Errno = telnet_GetErrno(); 
                                strlcpy(cli_Error, telnet_GetError(), STRSIZ); 
                                 return -1;                                  return -1;
                        } else                        else
                                 flg = 0;                                  flg = 0;
   
                         while (42) {                          while (42) {
                                   if (waitpid(pid, &stat, WNOHANG))
                                           break;
   
                                 FD_ZERO(&fds);                                  FD_ZERO(&fds);
                                 FD_SET(sock, &fds);                                  FD_SET(sock, &fds);
                                 FD_SET(pty, &fds);                                  FD_SET(pty, &fds);
Line 999  cliNetExec(commands_t *cmdList, const char *csPrompt,  Line 1354  cliNetExec(commands_t *cmdList, const char *csPrompt, 
                                 r = FD_ISSET(sock, &fds) ? sock : pty;                                  r = FD_ISSET(sock, &fds) ? sock : pty;
                                 s = FD_ISSET(sock, &fds) ? pty : sock;                                  s = FD_ISSET(sock, &fds) ? pty : sock;
   
                                if ((ret = telnetRecv(r, &a, &alen, buf, BUFSIZ)) < 0) {                                if (FD_ISSET(sock, &fds)) {
                                         memset(buf, 0, BUFSIZ);
                                         if ((ret = cli_telnetRecv(sock, &a, &alen, buf, BUFSIZ)) < 0) {
                                                 if (a)
                                                         e_free(a);
 
                                                 if (-2 == ret)
                                                         continue;
                                                 // EOF
                                                 if (-3 == ret)
                                                         shutdown(sock, SHUT_RD);
                                                 break;
                                         }
                                         attrlen = 0;
                                         if (1 == flg && alen) {
                                                 cli_telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_SGA);
                                                 cli_telnet_SetCmd(&Attr[attrlen++], DO, TELOPT_ECHO);
                                         }
                                         if (2 == flg && alen) {
                                                 cli_telnet_SetCmd(&Attr[attrlen++], WILL, TELOPT_ECHO);
                                                 cli_telnet_Set_SubOpt(&Attr[attrlen++], TELOPT_LFLOW, 
                                                                 LFLOW_OFF, NULL, 0);
                                                 cli_telnet_Set_SubOpt(&Attr[attrlen++], TELOPT_LFLOW, 
                                                                 LFLOW_RESTART_XON, NULL, 0);
                                                 cli_telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_LINEMODE);
                                         }
                                         if (a)                                          if (a)
                                                free(a);                                                e_free(a);
   
                                        if (-2 == ret)                                        if ((ret = write(pty, buf, ret)) == -1) {
                                                continue;                                                LOGERR;
                                        // EOF                                                break;
                                        if (-3 == ret) 
                                                shutdown(r, SHUT_RD); 
                                        else { 
                                                cli_Errno = telnet_GetErrno(); 
                                                strlcpy(cli_Error, telnet_GetError(), STRSIZ); 
                                         }                                          }
                                         break;  
                                 }                                  }
                                 attrlen = 0;  
                                 if (1 == flg && alen) {  
                                         telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_SGA);  
                                         telnet_SetCmd(&Attr[attrlen++], DO, TELOPT_ECHO);  
                                 }  
                                 if (2 == flg && alen) {  
                                         telnet_SetCmd(&Attr[attrlen++], WILL, TELOPT_ECHO);  
                                         telnet_Set_SubOpt(&Attr[attrlen++], TELOPT_LFLOW,   
                                                         LFLOW_OFF, NULL, 0);  
                                         telnet_Set_SubOpt(&Attr[attrlen++], TELOPT_LFLOW,   
                                                         LFLOW_RESTART_XON, NULL, 0);  
                                         telnet_SetCmd(&Attr[attrlen++], DONT, TELOPT_LINEMODE);  
                                 }  
                                 if (a)  
                                         free(a);  
   
                                if ((ret = telnetSend(s, Attr, pty == s ? 0 : attrlen, buf, ret, 0)) == -1) {                                if (FD_ISSET(pty, &fds)) {
                                        cli_Errno = telnet_GetErrno();                                        memset(buf, 0, BUFSIZ);
                                        strlcpy(cli_Error, telnet_GetError(), STRSIZ);                                        if ((ret = read(pty, buf, BUFSIZ)) == -1) {
                                        break;                                                LOGERR;
                                } else                                                break;
                                        flg++;                                        }
 
                                         if ((ret = cli_telnetSend(sock, Attr, pty == s ? 0 : attrlen, 
                                                                         buf, ret, 0)) == -1)
                                                 break;
                                         else
                                                 flg++;
                                 }
                         }                          }
   
                         close(pty);                          close(pty);
Line 1045  cliNetExec(commands_t *cmdList, const char *csPrompt,  Line 1411  cliNetExec(commands_t *cmdList, const char *csPrompt, 
 }  }
   
 /*  /*
 * cliExec() Execute CLI main loop * cliLoop() - CLI main loop
 * @cmdList = Commands list *
 * @csPrompt = Prompt text * @buffer = CLI buffer
 * return: -1 error, 0 = exit w/^+D, 1 done. * @csHistFile = History file name
  * return: RETCODE_ERR error, RETCODE_OK ok
 */  */
/*int
int cliExec(cliCommands_t *cmdList, const char *csPrompt)cliLoop(linebuffer_t * __restrict buffer, const char *csHistFile)
 {  {
         char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];          char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];
         int ret = 0;  
         register int i;          register int i;
        cliCommands_t *cmd = NULL;        int ret = RETCODE_OK;
        FILE *out;        struct tagCommand *cmd;
   
         inline int inline_help()  
         {  
                 cli_Cmd_Help(cmdList ? cmdList : cli_stdCmds, -1, out, NULL);  
                 rl_on_new_line();  
                 return 0;  
         }  
   
         char **cli_stdCompletion(const char *text, int start, int end)  
         {  
                 register int i;  
                 char **matches = NULL;  
   
                 char *cmdCompGet(const char *text, int state)  
                 {  
                         int len = strlen(text);  
   
                         for (i = state; cmdList[i].cmd_name; i++) {  
                                 if (strncmp(cmdList[i].cmd_name, "---", 3) &&   
                                                 !strncmp(cmdList[i].cmd_name, text, len))  
                                         return strdup(cmdList[i].cmd_name);  
                         }  
   
                         return NULL;  
                 }  
   
                 if (!start)  
                         matches = rl_completion_matches(text, cmdCompGet);  
                 else  
                         for (i = 0; cmdList[i].cmd_name; i++) {  
                                 if (!cmdList[i].cmd_comp)  
                                         continue;  
                                 if (!strncmp(rl_line_buffer, cmdList[i].cmd_name, strlen(cmdList[i].cmd_name)))  
                                         matches = rl_completion_matches(text, cmdList[i].cmd_comp);  
                         }  
   
                 return matches;  
         }  
         char *cli_stdCompEntry(const char *ignore, int invoking_key)  
         {  
                 return NULL;  
         }  
 */  
         /* --- main body of CLI --- */          /* --- main body of CLI --- */
/*        cliInitLine(buffer);
        out = rl_outstream; 
        if (!out) 
                out = stdout; 
   
        rl_bind_key('?', inline_help);        if (cli_loadHistory(buffer, csHistFile) == RETCODE_ERR)
        if (!rl_attempted_completion_function)                 return RETCODE_ERR;
                cliComp(cli_stdCompletion, cli_stdCompEntry); 
   
         do {          do {
                line = readline(csPrompt);                line = cliReadLine(buffer);
                if (!line) {    // ^+d                if (!line) {
                        cli_Printf(out, "\n");                        printfNL(buffer, 0);
                         break;                          break;
                }                } else
                         cli_addHistory(buffer, NULL);
                 // clear whitespaces                  // clear whitespaces
                for (s = line; isspace(*s); s++);                for (s = line; isspace((int) *s); s++);
                 if (*s) {                  if (*s) {
                        for (t = s + strlen(s) - 1; t > s && isspace(*t); t--);                        for (t = s + strlen(s) - 1; t > s && isspace((int) *t); t--);
                         *++t = 0;                          *++t = 0;
                 }                  }
   
                 if (*s) {                  if (*s) {
                         add_history(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 = strsep(&s, " \t")); 
                                         *app ? app++ : app);                                          *app ? app++ : app);
   
                         // exec_cmd ...                          // exec_cmd ...
                        for (cmd = NULL, i = 0; cmdList[i].cmd_name; i++)                        i = 0;
                                if (*items[0] && !strncmp(cmdList[i].cmd_name, items[0], strlen(items[0]))) {                        SLIST_FOREACH(cmd, &buffer->line_cmds, cmd_next) {
                                        cmd = &cmdList[i];                                if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))
                                         break;                                          break;
                                }                                else
                                         i++;
                         }
 
                         if (!cmd) {                          if (!cmd) {
                                cli_Printf(out, "Command '%s' not found!\n", items[0]);                                cli_Printf(buffer, "\nCommand '%s' not found!\n", items[0]);
                                 ret = -1;                                  ret = -1;
                         } else                          } else
                                ret = cmd->cmd_func(cmdList, i, out, items);                                if (cmd->cmd_func) {
                                         cli_Printf(buffer, "\n");
                                         ret = cmd->cmd_func(buffer, i, items);
                                 } else {
                                         clrscrEOL(buffer);
                                         printfCR(buffer, 1);
                                 }
                 }                  }
   
                free(line);                cli_freeLine(buffer);
                 cli_resetHistory(buffer);
                 e_free(line);
         } while (ret < 1);          } while (ret < 1);
   
           cli_saveHistory(buffer, csHistFile, HISTORY_LINES);
         return ret;          return ret;
 }  }
 */  

Removed from v.1.2.2.3  
changed lines
  Added in v.1.5.4.1


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