Changeset a7f575acc420cc6e5ca474d23cf07149299a3bbd

Show
Ignore:
Timestamp:
02/09/08 06:05:17 (6 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1202537117 +0000
git-parent:

[1d69a01311e58ce6ddb007d690b4e9aa4ac08c8c]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1202537117 +0000
Message:

start the framework for a console state machine

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/Makefile.in

    r3070001 ra7f575a  
    2525SUBS=utils jlog eventer modules noitedit 
    2626 
    27 OBJS=noitd.o noit_listener.o noit_console.o noit_console_telnet.o \ 
     27OBJS=noitd.o noit_listener.o \ 
     28        noit_console.o noit_console_state.o noit_console_telnet.o \ 
    2829        noit_check.o \ 
    2930        noit_module.o noit_conf.o noit_tokenizer.o 
  • src/noit_console.c

    r1d69a01 ra7f575a  
    2424#include "noit_tokenizer.h" 
    2525 
     26static void 
     27nc_telnet_cooker(noit_console_closure_t ncct) { 
     28  char *tmpbuf, *p, *n; 
     29  int r; 
     30 
     31  tmpbuf = ncct->outbuf; 
     32  if(ncct->outbuf_len == 0) return; 
     33 
     34  p = ncct->outbuf + ncct->outbuf_completed; 
     35  r = ncct->outbuf_len - ncct->outbuf_completed; 
     36  n = memchr(p, '\n', r); 
     37  /* No '\n'? Nothin' to do */ 
     38  if(!n) { 
     39    ncct->outbuf_cooked = ncct->outbuf_len; 
     40    return; 
     41  } 
     42 
     43  /* Forget the outbuf -- it is now tmpbuf */ 
     44  ncct->outbuf = NULL; 
     45  ncct->outbuf_allocd = 0; 
     46  ncct->outbuf_len = 0; 
     47  ncct->outbuf_completed = 0; 
     48  ncct->outbuf_cooked = 0; 
     49  do { 
     50    if(n == tmpbuf || *(n-1) != '\r') { 
     51      nc_write(ncct, p, n-p);   r -= n-p; 
     52      nc_write(ncct, "\r", 1); 
     53      p = n; 
     54    } 
     55    n = memchr(p+1, '\n', r-1); 
     56  } while(n); 
     57  nc_write(ncct, p, r); 
     58  ncct->outbuf_cooked = ncct->outbuf_len; 
     59  free(tmpbuf); 
     60} 
    2661int 
    2762nc_printf(noit_console_closure_t ncct, const char *fmt, ...) { 
     
    104139  if(ncct->outbuf) free(ncct->outbuf); 
    105140  if(ncct->telnet) noit_console_telnet_free(ncct->telnet); 
     141  while(ncct->state) { 
     142    noit_console_state_t *tmp; 
     143    tmp = ncct->state; 
     144    ncct->state = tmp->stacked; 
     145    noit_console_state_free(tmp); 
     146  } 
    106147  free(ncct); 
    107148} 
     
    122163  eventer_t e = ncct->e; 
    123164  if(!ncct->outbuf_len) return 0; 
     165  if(ncct->output_cooker) ncct->output_cooker(ncct); 
    124166  while(ncct->outbuf_len > ncct->outbuf_completed) { 
    125167    len = e->opset->write(e->fd, ncct->outbuf + ncct->outbuf_completed, 
     
    136178  free(ncct->outbuf); 
    137179  ncct->outbuf = NULL; 
    138   ncct->outbuf_allocd = 0; 
    139   ncct->outbuf_len = ncct->outbuf_completed = 0; 
     180  ncct->outbuf_allocd = ncct->outbuf_len = 
     181    ncct->outbuf_completed = ncct->outbuf_cooked = 0; 
    140182  return len; 
    141183} 
     
    151193noit_console_dispatch(eventer_t e, const char *buffer, 
    152194                      noit_console_closure_t ncct) { 
    153   char *cmds[32]
     195  char **cmds
    154196  int i, cnt = 32; 
    155   nc_printf(ncct, "You said: %s\r\n", buffer); 
     197  cmds = alloca(32 * sizeof(*cmds)); 
     198  nc_printf(ncct, "You said: %s\n", buffer); 
    156199  i = noit_tokenize(buffer, cmds, &cnt); 
    157200  if(i>cnt) nc_printf(ncct, "Command length too long.\n"); 
    158   if(i<0) nc_printf(ncct, "Error at offset: %d\n", 0-i); 
     201  else if(i<0) nc_printf(ncct, "Error at offset: %d\n", 0-i); 
     202  else noit_console_state_do(ncct, cnt, cmds); 
    159203  for(i=0;i<cnt;i++) { 
    160     nc_printf(ncct, "[%d] '%s'\r\n", i, cmds[i]); 
     204    nc_printf(ncct, "[%d] '%s'\n", i, cmds[i]); 
    161205    free(cmds[i]); 
    162206  } 
     
    196240      el_set(ncct->el, EL_HIST, history, ncct->hist); 
    197241      ncct->telnet = noit_console_telnet_alloc(ncct); 
     242      ncct->output_cooker = nc_telnet_cooker; 
     243      ncct->state = noit_console_state_initial(); 
     244      noit_console_state_init(ncct); 
    198245    } 
    199246  } 
     
    202249   * care of that 
    203250   */ 
    204   if(noit_console_continue_sending(ncct, &newmask) == -1) { 
    205     if(errno != EAGAIN) goto socket_error; 
     251  if(noit_console_continue_sending(ncct, &newmask) < 0) { 
     252    if(ncct->wants_shutdown || errno != EAGAIN) goto socket_error; 
    206253    return newmask | EVENTER_EXCEPTION; 
    207254  } 
     
    218265 
    219266    len = e->opset->read(e->fd, sbuf, sizeof(sbuf)-1, &newmask, e); 
    220 noitL(noit_stderr, "opset->read => %d bytes\n", len); 
    221267    if(len == 0 || (len < 0 && errno != EAGAIN)) { 
    222268      eventer_remove_fd(e->fd); 
     
    247293      noit_console_dispatch(e, cmd_buffer, ncct); 
    248294      free(cmd_buffer); 
    249       if(noit_console_continue_sending(ncct, &newmask) == -1) { 
    250         if(errno != EAGAIN) goto socket_error; 
    251         return newmask | EVENTER_EXCEPTION; 
    252       } 
    253     } 
     295    } 
     296    if(noit_console_continue_sending(ncct, &newmask) == -1) { 
     297      if(ncct->wants_shutdown || errno != EAGAIN) goto socket_error; 
     298      return newmask | EVENTER_EXCEPTION; 
     299    } 
     300    if(ncct->wants_shutdown) goto socket_error; 
    254301  } 
    255302  return newmask | EVENTER_EXCEPTION; 
  • src/noit_console.h

    r1d69a01 ra7f575a  
    1111#include "noitedit/histedit.h" 
    1212#include "noit_console_telnet.h" 
     13#include "utils/noit_hash.h" 
    1314#include <stdarg.h> 
     15 
     16struct _console_state; 
     17struct __noit_console_closure; 
     18 
     19typedef int (*console_cmd_func_t)(struct __noit_console_closure *, 
     20                                  int, char **); 
     21typedef char *(*console_prompt_func_t)(EditLine *); 
     22typedef void (*state_free_func_t)(struct _console_state *); 
     23 
     24typedef struct cmd_info { 
     25  const char          *name; 
     26  console_cmd_func_t   func; 
     27} cmd_info_t; 
     28 
     29typedef struct _console_state { 
     30  console_prompt_func_t  console_prompt_function; 
     31  noit_hash_table        cmds; 
     32  struct _console_state *stacked; 
     33  state_free_func_t      statefree; 
     34} noit_console_state_t; 
    1435 
    1536typedef struct __noit_console_closure { 
     
    2243  History *hist; 
    2344 
     45  noit_console_state_t *state; 
     46 
    2447  int   pty_master; 
    2548  int   pty_slave; 
     
    2952  int   outbuf_allocd; 
    3053  int   outbuf_len; 
     54  int   outbuf_cooked; 
    3155  int   outbuf_completed; 
    3256 
    3357  /* This tracks telnet protocol state (if we're doing telnet) */ 
    3458  noit_console_telnet_closure_t telnet; 
    35  
    36 } * noit_console_closure_t;; 
     59  void (*output_cooker)(struct __noit_console_closure *); 
     60} * noit_console_closure_t; 
    3761 
    3862API_EXPORT(void) noit_console_init(); 
     
    5579  noit_console_continue_sending(noit_console_closure_t ncct, 
    5680                                int *mask); 
     81 
     82API_EXPORT(int) 
     83  noit_console_state_init(noit_console_closure_t ncct); 
     84 
     85API_EXPORT(char *) 
     86  noit_console_state_prompt(EditLine *el); 
     87 
     88API_EXPORT(int) 
     89  noit_console_state_pop(noit_console_closure_t ncct, int argc, char **argv); 
     90 
     91API_EXPORT(noit_console_state_t *) 
     92  noit_console_state_initial(); 
     93 
     94API_EXPORT(void) 
     95  noit_console_state_free(noit_console_state_t *st); 
     96 
     97API_EXPORT(int) 
     98  noit_console_state_do(noit_console_closure_t ncct, int argc, char **argv); 
     99 
    57100#endif