Diff for /libaitcli/src/aitcli.c between versions 1.12 and 1.21

version 1.12, 2013/11/22 15:17:22 version 1.21, 2025/12/17 23:41:04
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013Copyright 2004 - 2025
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 87  static inline void Line 87  static inline void
 clrscrEOL(linebuffer_t * __restrict buf)  clrscrEOL(linebuffer_t * __restrict buf)
 {  {
         register int i;          register int i;
           int ign __attribute__((unused));
   
         if (buf && buf->line_prompt) {          if (buf && buf->line_prompt) {
                write(buf->line_out, K_CR, 1);                ign = write(buf->line_out, K_CR, 1);
   
                 for (i = 0; i < buf->line_len; i++)                  for (i = 0; i < buf->line_len; i++)
                        write(buf->line_out, K_SPACE, 1);                        ign = write(buf->line_out, K_SPACE, 1);
         }          }
 }  }
   
 static inline void  static inline void
 printfEOL(linebuffer_t * __restrict buf, int len, int prompt)  printfEOL(linebuffer_t * __restrict buf, int len, int prompt)
 {  {
           int ign __attribute__((unused));
   
         if (buf) {          if (buf) {
                 if (prompt && buf->line_prompt) {                  if (prompt && buf->line_prompt) {
                        write(buf->line_out, K_CR, 1);                        ign = write(buf->line_out, K_CR, 1);
                        write(buf->line_out, buf->line_prompt, buf->line_bol);                        ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
                 }                  }
   
                write(buf->line_out, buf->line_buf, len == -1 ?                 ign = write(buf->line_out, buf->line_buf, len == -1 ? 
                                buf->line_eol - buf->line_bol: len);                                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)
 {  {
           int ign __attribute__((unused));
   
         if (buf && prompt && buf->line_prompt) {          if (buf && prompt && buf->line_prompt) {
                write(buf->line_out, K_CR, 1);                ign = write(buf->line_out, K_CR, 1);
                write(buf->line_out, buf->line_prompt, buf->line_bol);                ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
         }          }
 }  }
   
 static inline void  static inline void
 printfNL(linebuffer_t * __restrict buf, int prompt)  printfNL(linebuffer_t * __restrict buf, int prompt)
 {  {
           int ign __attribute__((unused));
   
         if (buf) {          if (buf) {
                write(buf->line_out, K_ENTER, 1);                ign = write(buf->line_out, K_ENTER, 1);
   
                 if (prompt)                  if (prompt)
                         if (prompt && buf->line_prompt)                          if (prompt && buf->line_prompt)
                                write(buf->line_out, buf->line_prompt, buf->line_bol);                                ign = write(buf->line_out, buf->line_prompt, buf->line_bol);
         }          }
 }  }
   
Line 138  bufCHAR(int idx, void * __restrict cli_buffer) Line 145  bufCHAR(int idx, void * __restrict cli_buffer)
 {  {
         linebuffer_t *buf = cli_buffer;          linebuffer_t *buf = cli_buffer;
         int pos;          int pos;
           int ign __attribute__((unused));
   
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 154  bufCHAR(int idx, void * __restrict cli_buffer) Line 162  bufCHAR(int idx, void * __restrict cli_buffer)
         memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);          memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
         buf->line_buf[buf->line_len - 1] = 0;          buf->line_buf[buf->line_len - 1] = 0;
   
        write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);        if (buf->line_prompt)
                 ign = write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
   
         if (buf->line_mode == LINEMODE_INS) {          if (buf->line_mode == LINEMODE_INS) {
                write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len,                 ign = write(buf->line_out, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, 
                                 buf->line_len - buf->line_eol);                                  buf->line_len - buf->line_eol);
                 printfEOL(buf, -1, 1);                  printfEOL(buf, -1, 1);
         }          }
Line 177  bufEOL(int idx, void * __restrict cli_buffer) Line 186  bufEOL(int idx, void * __restrict cli_buffer)
 static int  static int
 bufEOF(int idx, void * __restrict cli_buffer)  bufEOF(int idx, void * __restrict cli_buffer)
 {  {
           int ret;
   
         /*          /*
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
         */          */
   
        return RETCODE_EOF;        printfNL(cli_buffer, 0);
         ret = cli_Cmd_End(cli_buffer, idx, NULL);
         printfCR(cli_buffer, (ret != RETCODE_EOF));
 
         return ret;
 }  }
   
 static int  static int
Line 403  bufComp(int idx, void * __restrict cli_buffer) Line 418  bufComp(int idx, void * __restrict cli_buffer)
         register int i, j;          register int i, j;
         struct tagCommand *cmd, *c;          struct tagCommand *cmd, *c;
         int pos, ret = RETCODE_OK;          int pos, ret = RETCODE_OK;
           int ign __attribute__((unused));
   
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 415  bufComp(int idx, void * __restrict cli_buffer) Line 431  bufComp(int idx, void * __restrict cli_buffer)
                 str_Trim(s);                  str_Trim(s);
         }          }
   
        i = j = 0;        j = 0;
         c = NULL;          c = NULL;
         memset(szLine, 0, STRSIZ);          memset(szLine, 0, STRSIZ);
         if (*s) {          if (*s) {
Line 465  bufComp(int idx, void * __restrict cli_buffer) Line 481  bufComp(int idx, void * __restrict cli_buffer)
         /* completion show actions ... */          /* completion show actions ... */
         if (j > 1 && c) {          if (j > 1 && c) {
                 printfNL(buf, 0);                  printfNL(buf, 0);
                write(buf->line_out, szLine, strlen(szLine));                ign = write(buf->line_out, szLine, strlen(szLine));
                 printfNL(buf, 1);                  printfNL(buf, 1);
                 printfEOL(buf, buf->line_len - 1, 1);                  printfEOL(buf, buf->line_len - 1, 1);
                 printfEOL(buf, -1, 1);                  printfEOL(buf, -1, 1);
Line 510  static int Line 526  static int
 bufEndNode(int idx, void * __restrict cli_buffer)  bufEndNode(int idx, void * __restrict cli_buffer)
 {  {
         linebuffer_t *buf = cli_buffer;          linebuffer_t *buf = cli_buffer;
           char szPrompt[STRSIZ + 16] = {[0 ... STRSIZ + 15] = 0};
   
         if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)          if (!cli_buffer || idx < 0 || idx > MAX_BINDKEY)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 517  bufEndNode(int idx, void * __restrict cli_buffer) Line 534  bufEndNode(int idx, void * __restrict cli_buffer)
         if (buf->line_level > 0) {          if (buf->line_level > 0) {
                 printfNL(cli_buffer, 0);                  printfNL(cli_buffer, 0);
                 buf->line_level--;                  buf->line_level--;
                   snprintf(szPrompt, sizeof szPrompt, "%s{%d}> ", buf->line_porigin, buf->line_level);
                   cli_setPrompt(buf, szPrompt);
                 cli_Printf(buf, "Enter to config level %d\n", buf->line_level);                  cli_Printf(buf, "Enter to config level %d\n", buf->line_level);
         }          }
   
Line 539  cli_Printf(linebuffer_t * __restrict cli_buffer, char  Line 558  cli_Printf(linebuffer_t * __restrict cli_buffer, char 
         FILE *f;          FILE *f;
   
         if (fmt) {          if (fmt) {
                f = fdopen(cli_buffer->line_out, "a");                f = fdopen(dup(cli_buffer->line_out), "a");
                 if (!f) {                  if (!f) {
                         LOGERR;                          LOGERR;
                         return;                          return;
Line 548  cli_Printf(linebuffer_t * __restrict cli_buffer, char  Line 567  cli_Printf(linebuffer_t * __restrict cli_buffer, char 
                 va_start(lst, fmt);                  va_start(lst, fmt);
                 vfprintf(f, fmt, lst);                  vfprintf(f, fmt, lst);
                 va_end(lst);                  va_end(lst);
   
                   fclose(f);
         } else          } else
                 cli_SetErr(EINVAL, "Invalid input parameters ...");                  cli_SetErr(EINVAL, "Invalid input parameters ...");
 }  }
Line 977  cliInit(int fin, int fout, const char *prompt) Line 998  cliInit(int fin, int fout, const char *prompt)
         linebuffer_t *cli_buffer;          linebuffer_t *cli_buffer;
         bindkey_t *keys;          bindkey_t *keys;
         register int i;          register int i;
           char szPrompt[STRSIZ + 16] = {[0 ... STRSIZ + 15] = 0};
   
         /* init buffer */          /* init buffer */
         cli_buffer = e_malloc(sizeof(linebuffer_t));          cli_buffer = e_malloc(sizeof(linebuffer_t));
Line 993  cliInit(int fin, int fout, const char *prompt) Line 1015  cliInit(int fin, int fout, const char *prompt)
                 SLIST_INIT(&cli_buffer->line_cmds);                  SLIST_INIT(&cli_buffer->line_cmds);
   
                 if (prompt) {                  if (prompt) {
                        cli_buffer->line_prompt = e_strdup(prompt);                        strlcpy(cli_buffer->line_porigin, prompt, sizeof cli_buffer->line_porigin);
                         snprintf(szPrompt, sizeof szPrompt, "%s{%d}> ", cli_buffer->line_porigin, cli_buffer->line_level);
                         cli_buffer->line_prompt = e_strdup(szPrompt);
                         if (!cli_buffer->line_prompt) {                          if (!cli_buffer->line_prompt) {
                                 LOGERR;                                  LOGERR;
                                 e_free(cli_buffer);                                  e_free(cli_buffer);
Line 1050  cliInit(int fin, int fout, const char *prompt) Line 1074  cliInit(int fin, int fout, const char *prompt)
                         keys[i].key_func = bufEOL;                          keys[i].key_func = bufEOL;
                 if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE))                  if (cli_buffer->line_prompt && (i == *K_CTRL_H || i == *K_BACKSPACE))
                         keys[i].key_func = bufBS;                          keys[i].key_func = bufBS;
                if (cli_buffer->line_prompt && i == *K_CTRL_C)                if (i == *K_CTRL_C)
                         keys[i].key_func = bufCLR;                          keys[i].key_func = bufCLR;
                 if (cli_buffer->line_prompt && i == *K_CTRL_A)                  if (cli_buffer->line_prompt && i == *K_CTRL_A)
                         keys[i].key_func = bufBEGIN;                          keys[i].key_func = bufBEGIN;
Line 1058  cliInit(int fin, int fout, const char *prompt) Line 1082  cliInit(int fin, int fout, const char *prompt)
                         keys[i].key_func = bufEND;                          keys[i].key_func = bufEND;
                 if (cli_buffer->line_prompt && i == *K_TAB)                  if (cli_buffer->line_prompt && i == *K_TAB)
                         keys[i].key_func = bufComp;                          keys[i].key_func = bufComp;
                if (cli_buffer->line_prompt && i == *K_CTRL_Z)                if (i == *K_CTRL_Z)
                         keys[i].key_func = bufEndNode;                          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;
Line 1242  cliInit(int fin, int fout, const char *prompt) Line 1266  cliInit(int fin, int fout, const char *prompt)
 }  }
   
 /*  /*
 * cliInitLine() - Init CLI input line terminal * cliSetLine() - Set CLI input line terminal
  *   *
  * @cli_buffer = CLI buffer   * @cli_buffer = CLI buffer
 * return: none * @old = Old terminal settings
  * return: -1 error or 0 ok
 */  */
 int  int
cliInitLine(linebuffer_t * __restrict cli_buffer)cliSetLine(linebuffer_t * __restrict cli_buffer, struct termios * __restrict old)
 {  {
         struct termios t;          struct termios t;
   
         memset(&t, 0, sizeof t);          memset(&t, 0, sizeof t);
         tcgetattr(cli_buffer->line_in, &t);          tcgetattr(cli_buffer->line_in, &t);
           if (old)
                   memcpy(old, &t, sizeof(struct termios));
         t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO |           t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | 
                         ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);                          ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
         t.c_iflag |= IGNBRK;          t.c_iflag |= IGNBRK;
Line 1263  cliInitLine(linebuffer_t * __restrict cli_buffer) Line 1290  cliInitLine(linebuffer_t * __restrict cli_buffer)
 }  }
   
 /*  /*
    * cliResetLine() - Reset CLI input line terminal
    *
    * @cli_buffer = CLI buffer
    * @old = Original terminal settings
    * return: -1 error or 0 ok
   */
   int
   cliResetLine(linebuffer_t * __restrict cli_buffer, struct termios * __restrict orig)
   {
           return tcsetattr(cli_buffer->line_in, TCSANOW, orig);
   }
   
   /*
  * cliReadLine() - Read line from opened CLI session   * cliReadLine() - Read line from opened CLI session
  *   *
  * @cli_buffer = CLI buffer   * @cli_buffer = CLI buffer
Line 1303  cliReadLine(linebuffer_t * __restrict cli_buffer, int  Line 1343  cliReadLine(linebuffer_t * __restrict cli_buffer, int 
   
                 memset(buf, 0, sizeof buf);                  memset(buf, 0, sizeof buf);
                 readLen = read(cli_buffer->line_in, buf, BUFSIZ);                  readLen = read(cli_buffer->line_in, buf, BUFSIZ);
                if (readLen == -1) {                if (readLen < 1) {
                        LOGERR;                        if (readLen)
                        return str;                                LOGERR;
                         return NULL;
                 }                  }
                 if (!readLen) {  
                         if (cli_buffer->line_buf)  
                                 str = e_strdup(cli_buffer->line_buf);  
                         else  
                                 cli_SetErr(EPIPE, "Unknown state ...");  
                         return str;  
                 }  
   
 recheck:  recheck:
                 for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)                  for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
Line 1360  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1394  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
                 int sock, int timeout)                  int sock, int timeout)
 {  {
         u_char buf[BUFSIZ];          u_char buf[BUFSIZ];
        int pid, stat, pty, r, s, alen, flg, attrlen = 0, ret = 0;        int pid, stat, pty, s, alen, flg, attrlen = 0, ret = 0;
         fd_set fds;          fd_set fds;
         struct timeval tv = { DEFAULT_SOCK_TIMEOUT, 0 };          struct timeval tv = { DEFAULT_SOCK_TIMEOUT, 0 };
         struct telnetAttrs *a, Attr[10];          struct telnetAttrs *a, Attr[10];
Line 1405  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1439  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
                                         break;                                          break;
                                 }                                  }
   
                                 r = FD_ISSET(sock, &fds) ? sock : pty;  
                                 s = FD_ISSET(sock, &fds) ? pty : sock;                                  s = FD_ISSET(sock, &fds) ? pty : sock;
   
                                 if (FD_ISSET(sock, &fds)) {                                  if (FD_ISSET(sock, &fds)) {
Line 1445  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1478  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
   
                                 if (FD_ISSET(pty, &fds)) {                                  if (FD_ISSET(pty, &fds)) {
                                         memset(buf, 0, BUFSIZ);                                          memset(buf, 0, BUFSIZ);
                                        if ((ret = read(pty, buf, BUFSIZ)) == -1) {                                        if ((ret = read(pty, buf, BUFSIZ)) < 1) {
                                                LOGERR;                                                if (ret)
                                                         LOGERR;
                                                 break;                                                  break;
                                         }                                          }
   
Line 1465  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1499  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
 }  }
   
 /*  /*
    * cliRun() - CLI run command line
    *
    * @cli_buffer = CLI buffer
    * @psInput = Input command line
    * @prompt = Display prompt after command
    * return: RETCODE_ERR error, RETCODE_OK ok
   */
   int
   cliRun(linebuffer_t * __restrict cli_buffer, char *psInput, int prompt)
   {
           char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];
           int ret = RETCODE_OK;
           struct tagCommand *cmd;
   
           if (!psInput)
                   return RETCODE_ERR;
           else
                   line = psInput;
   
           // clear whitespaces
           for (s = line; isspace((int) *s); s++);
           if (*s) {
                   for (t = s + strlen(s) - 1; t > s && isspace((int) *t); t--);
                   *++t = 0;
           }
   
           if (*s) {
                   memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS);
                   for (app = items; app < items + MAX_PROMPT_ITEMS - 1 && 
                                   (*app = strsep(&s, " \t")); *app ? app++ : app);
   
                   // exec_cmd ...
                   SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next) {
                           if (!(cmd->cmd_level & (1 << cli_buffer->line_level)))
                                   continue;
                           if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))
                                   break;
                   }
   
                   if (!cmd) {
                           cli_Printf(cli_buffer, "%sCommand '%s' not found!\n", 
                                           cli_buffer->line_prompt ? "\n" : "", items[0]);
                           ret = RETCODE_ERR;
                   } else
                           if (cmd->cmd_func) {
                                   if (prompt && cli_buffer->line_prompt)
                                           cli_Printf(cli_buffer, "\n");
                                   ret = cmd->cmd_func(cli_buffer, 
                                                   cli_buffer->line_level, items);
                           } else if (prompt) {
                                   clrscrEOL(cli_buffer);
                                   printfCR(cli_buffer, 1);
                           }
           }
   
           return ret;
   }
   
   /*
  * cliLoop() - CLI main loop   * cliLoop() - CLI main loop
  *   *
  * @cli_buffer = CLI buffer   * @cli_buffer = CLI buffer
Line 1475  cliNetLoop(linebuffer_t * __restrict cli_buffer, const Line 1568  cliNetLoop(linebuffer_t * __restrict cli_buffer, const
 int  int
 cliLoop(linebuffer_t * __restrict cli_buffer, const char *csHistFile, int timeout)  cliLoop(linebuffer_t * __restrict cli_buffer, const char *csHistFile, int timeout)
 {  {
        char *line, *s, *t, **app, *items[MAX_PROMPT_ITEMS];        char *line;
        register int i; 
         int ret = RETCODE_OK;          int ret = RETCODE_OK;
        struct tagCommand *cmd;        struct termios t;
   
         /* --- main body of CLI --- */          /* --- main body of CLI --- */
        cliInitLine(cli_buffer);        cliSetLine(cli_buffer, &t);
   
         if (cli_loadHistory(cli_buffer, csHistFile) == RETCODE_ERR)          if (cli_loadHistory(cli_buffer, csHistFile) == RETCODE_ERR)
                 return RETCODE_ERR;                  return RETCODE_ERR;
Line 1493  cliLoop(linebuffer_t * __restrict cli_buffer, const ch Line 1585  cliLoop(linebuffer_t * __restrict cli_buffer, const ch
                         break;                          break;
                 } else                  } else
                         cli_addHistory(cli_buffer, NULL);                          cli_addHistory(cli_buffer, NULL);
                 // clear whitespaces  
                 for (s = line; isspace((int) *s); s++);  
                 if (*s) {  
                         for (t = s + strlen(s) - 1; t > s && isspace((int) *t); t--);  
                         *++t = 0;  
                 }  
   
                if (*s) {                ret = cliRun(cli_buffer, line, 42);
                        memset(items, 0, sizeof(char*) * MAX_PROMPT_ITEMS); 
                        for (app = items; app < items + MAX_PROMPT_ITEMS - 1 &&  
                                        (*app = strsep(&s, " \t")); *app ? app++ : app); 
   
                         // exec_cmd ...  
                         i = 0;  
                         SLIST_FOREACH(cmd, &cli_buffer->line_cmds, cmd_next) {  
                                 if (!(cmd->cmd_level & (1 << cli_buffer->line_level)))  
                                         continue;  
                                 if (*items[0] && !strncmp(cmd->cmd_name, items[0], strlen(items[0])))  
                                         break;  
                                 else  
                                         i++;  
                         }  
   
                         if (!cmd) {  
                                 cli_Printf(cli_buffer, "\nCommand '%s' not found!\n", items[0]);  
                                 ret = -1;  
                         } else  
                                 if (cmd->cmd_func) {  
                                         cli_Printf(cli_buffer, "\n");  
                                         ret = cmd->cmd_func(cli_buffer,   
                                                         cli_buffer->line_level, items);  
                                 } else {  
                                         clrscrEOL(cli_buffer);  
                                         printfCR(cli_buffer, 1);  
                                 }  
                 }  
   
                 cli_freeLine(cli_buffer);                  cli_freeLine(cli_buffer);
                 cli_resetHistory(cli_buffer);                  cli_resetHistory(cli_buffer);
                 e_free(line);                  e_free(line);
        } while (cli_buffer->line_kill || ret < 1);        } while (!cli_buffer->line_kill);
   
         cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);          cli_saveHistory(cli_buffer, csHistFile, HISTORY_LINES);
   
           /* --- restore tty --- */
           cliResetLine(cli_buffer, &t);
   
         return ret;          return ret;
 }  }

Removed from v.1.12  
changed lines
  Added in v.1.21


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