Changeset 7a1324aa50711b4d7f5d81f7e901081a150cf9fe

Show
Ignore:
Timestamp:
02/12/08 03:35:01 (10 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1202787301 +0000
git-parent:

[998fcf4e10bc37cda542d39850f8da317f74f79d]

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

online editing of attributes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_check.c

    r67a2095 r7a1324a  
    8484} 
    8585void 
    86 noit_poller_load_checks() { 
     86noit_poller_process_checks(char *xpath) { 
    8787  int i, cnt = 0; 
    8888  noit_conf_section_t *sec; 
    8989  __config_load_generation++; 
    90   sec = noit_conf_get_sections(NULL, "/noit/checks//check", &cnt); 
     90  sec = noit_conf_get_sections(NULL, xpath, &cnt); 
    9191  for(i=0; i<cnt; i++) { 
     92    noit_check_t *existing_check; 
    9293    char uuid_str[37]; 
    9394    char target[256]; 
     
    9899    int no_oncheck = 0; 
    99100    int period = 0, timeout = 0; 
     101    noit_conf_boolean disabled = noit_false; 
    100102    uuid_t uuid, out_uuid; 
    101103    noit_hash_table *options; 
     
    118120    if(!INHERIT(stringbuf, target, target, sizeof(target))) { 
    119121      noitL(noit_stderr, "check uuid: '%s' has no target\n", uuid_str); 
    120       continue; 
     122      disabled = noit_true; 
    121123    } 
    122124    if(!INHERIT(stringbuf, module, module, sizeof(module))) { 
    123125      noitL(noit_stderr, "check uuid: '%s' has no module\n", uuid_str); 
    124       continue; 
     126      disabled = noit_true; 
    125127    } 
    126128 
     
    137139      noitL(noit_stderr, "check uuid: '%s' has neither period nor oncheck\n", 
    138140            uuid_str); 
    139       continue; 
     141      disabled = noit_true; 
    140142    } 
    141143    if(!(no_period || no_oncheck)) { 
    142144      noitL(noit_stderr, "check uuid: '%s' has oncheck and period.\n", 
    143145            uuid_str); 
    144       continue; 
     146      disabled = noit_true; 
    145147    } 
    146148    if(!INHERIT(int, timeout, &timeout)) { 
    147149      noitL(noit_stderr, "check uuid: '%s' has no timeout\n", uuid_str); 
    148       continue; 
     150      disabled = noit_true; 
    149151    } 
    150152    if(!no_period && timeout >= period) { 
     
    153155    } 
    154156    options = noit_conf_get_hash(sec[i], "ancestor-or-self::node()/config/*"); 
    155     noit_poller_schedule(target, module, name, options, 
    156                          period, timeout, oncheck[0] ? oncheck : NULL, 
    157                          uuid, out_uuid); 
    158     noitL(noit_debug, "loaded uuid: %s\n", uuid_str); 
    159   } 
     157 
     158    if(noit_hash_retrieve(&polls, (char *)uuid, UUID_SIZE, 
     159                          (void **)&existing_check)) { 
     160      noit_check_update(existing_check, target, name, options, 
     161                           period, timeout, oncheck[0] ? oncheck : NULL, 
     162                           disabled); 
     163      noitL(noit_debug, "reloaded uuid: %s\n", uuid_str); 
     164    } 
     165    else { 
     166      noit_poller_schedule(target, module, name, options, 
     167                           period, timeout, oncheck[0] ? oncheck : NULL, 
     168                           disabled, uuid, out_uuid); 
     169      noitL(noit_debug, "loaded uuid: %s\n", uuid_str); 
     170    } 
     171  } 
     172
     173 
     174void 
     175noit_poller_load_checks() { 
     176  noit_poller_process_checks("/noit/checks//check"); 
    160177} 
    161178 
     
    171188    mod = noit_module_lookup(check->module); 
    172189    if(mod) { 
     190      if(NOIT_CHECK_LIVE(check)) 
     191        continue; 
    173192      if((check->flags & NP_DISABLED) == 0) 
    174193        mod->initiate_check(mod, check, 0, NULL); 
     194      else 
     195        noitL(noit_debug, "Skipping %s`%s, disabled.\n", 
     196              check->target, check->name); 
    175197    } 
    176198    else { 
     
    233255 
    234256int 
     257noit_check_update(noit_check_t *new_check, 
     258                  const char *target, 
     259                  const char *name, 
     260                  noit_hash_table *config, 
     261                  u_int32_t period, 
     262                  u_int32_t timeout, 
     263                  const char *oncheck, 
     264                  noit_conf_boolean disabled) { 
     265  int8_t family; 
     266  int rv; 
     267  union { 
     268    struct in_addr addr4; 
     269    struct in6_addr addr6; 
     270  } a; 
     271 
     272 
     273  family = AF_INET; 
     274  rv = inet_pton(family, target, &a); 
     275  if(rv != 1) { 
     276    family = AF_INET6; 
     277    rv = inet_pton(family, target, &a); 
     278    if(rv != 1) { 
     279      noitL(noit_stderr, "Cannot translate '%s' to IP\n", target); 
     280      memset(&a, 0, sizeof(a)); 
     281      disabled = noit_true; 
     282    } 
     283  } 
     284 
     285  new_check->generation = __config_load_generation; 
     286  new_check->target_family = family; 
     287  memcpy(&new_check->target_addr, &a, sizeof(a)); 
     288  if(new_check->target) free(new_check->target); 
     289  new_check->target = strdup(target); 
     290  if(new_check->name) free(new_check->name); 
     291  new_check->name = name ? strdup(name): NULL; 
     292 
     293  if(config != NULL) { 
     294    noit_hash_iter iter = NOIT_HASH_ITER_ZERO; 
     295    const char *k; 
     296    int klen; 
     297    void *data; 
     298    if(new_check->config) noit_hash_delete_all(new_check->config, free, free); 
     299    else new_check->config = calloc(1, sizeof(*new_check->config)); 
     300    while(noit_hash_next(config, &iter, &k, &klen, &data)) { 
     301      noit_hash_store(new_check->config, strdup(k), klen, strdup((char *)data)); 
     302    } 
     303  } 
     304  if(new_check->oncheck) free(new_check->oncheck); 
     305  new_check->oncheck = oncheck ? strdup(oncheck) : NULL; 
     306  new_check->period = period; 
     307  new_check->timeout = timeout; 
     308 
     309  if(disabled) new_check->flags |= NP_DISABLED; 
     310 
     311  /* This remove could fail -- no big deal */ 
     312  noit_skiplist_remove(&polls_by_name, new_check, NULL); 
     313 
     314  /* This insert could fail.. which means we have a conflict on 
     315   * target`name.  That should result in the check being disabled. */ 
     316  if(!noit_skiplist_insert(&polls_by_name, new_check)) { 
     317    noitL(noit_stderr, "Check %s`%s disabled due to naming conflict\n", 
     318          new_check->target, new_check->name); 
     319    new_check->flags |= NP_DISABLED; 
     320  } 
     321  return 0; 
     322} 
     323int 
    235324noit_poller_schedule(const char *target, 
    236325                     const char *module, 
     
    240329                     u_int32_t timeout, 
    241330                     const char *oncheck, 
     331                     noit_conf_boolean disabled, 
    242332                     uuid_t in, 
    243333                     uuid_t out) { 
    244   int8_t family; 
    245   int rv; 
    246   union { 
    247     struct in_addr addr4; 
    248     struct in6_addr addr6; 
    249   } a; 
    250334  noit_check_t *new_check; 
    251  
    252  
    253   family = AF_INET; 
    254   rv = inet_pton(family, target, &a); 
    255   if(rv != 1) { 
    256     family = AF_INET6; 
    257     rv = inet_pton(family, target, &a); 
    258     if(rv != 1) { 
    259       noitL(noit_stderr, "Cannot translate '%s' to IP\n", target); 
    260       return -1; 
    261     } 
    262   } 
    263  
    264335  new_check = calloc(1, sizeof(*new_check)); 
    265336  if(!new_check) return -1; 
    266   new_check->generation = __config_load_generation; 
    267   new_check->target_family = family; 
    268   memcpy(&new_check->target_addr, &a, sizeof(a)); 
    269   new_check->target = strdup(target); 
     337 
     338  /* The module and the UUID can never be changed */ 
    270339  new_check->module = strdup(module); 
    271   new_check->name = name ? strdup(name): NULL; 
    272  
    273   if(config != NULL) { 
    274     noit_hash_iter iter = NOIT_HASH_ITER_ZERO; 
    275     const char *k; 
    276     int klen; 
    277     void *data; 
    278     new_check->config = calloc(1, sizeof(*new_check->config)); 
    279     while(noit_hash_next(config, &iter, &k, &klen, &data)) { 
    280       noit_hash_store(new_check->config, strdup(k), klen, strdup((char *)data)); 
    281     } 
    282   } 
    283   new_check->oncheck = oncheck ? strdup(oncheck) : NULL; 
    284   new_check->period = period; 
    285   new_check->timeout = timeout; 
    286   new_check->flags = 0; 
    287340  if(uuid_is_null(in)) 
    288341    uuid_generate(new_check->checkid); 
     
    290343    uuid_copy(new_check->checkid, in); 
    291344 
     345  noit_check_update(new_check, target, name, config, 
     346                    period, timeout, oncheck, disabled); 
    292347  assert(noit_hash_store(&polls, 
    293348                         (char *)new_check->checkid, UUID_SIZE, 
    294349                         new_check)); 
    295   noit_skiplist_insert(&polls_by_name, new_check); 
    296350  uuid_copy(out, new_check->checkid); 
     351 
    297352  return 0; 
    298353} 
     
    310365    return 0; 
    311366  } 
     367  checker->flags |= NP_KILLED; 
    312368  if(checker->fire_event) { 
    313369     eventer_remove(checker->fire_event); 
     
    468524  return 0; 
    469525} 
     526 
    470527static void 
    471528register_console_check_commands() { 
  • src/noit_check.h

    ra2e53dc r7a1324a  
    1414#include "eventer/eventer.h" 
    1515#include "utils/noit_hash.h" 
     16#include "noit_conf.h" 
     17#include "noit_console.h" 
    1618 
    1719/* 
     
    9395} noit_check_t; 
    9496 
     97#define NOIT_CHECK_LIVE(a) ((a)->fire_event != NULL) 
     98 
    9599API_EXPORT(void) noit_poller_init(); 
    96100API_EXPORT(void) noit_poller_load_checks(); 
     101API_EXPORT(void) noit_poller_process_checks(char *xpath); 
    97102 
    98103API_EXPORT(void) 
     
    109114                       u_int32_t timeout, 
    110115                       const char *oncheck, 
     116                       noit_conf_boolean disabled, 
    111117                       uuid_t in, 
    112118                       uuid_t out); 
     119 
     120API_EXPORT(int) 
     121  noit_check_update(noit_check_t *new_check, 
     122                    const char *target, 
     123                    const char *name, 
     124                    noit_hash_table *config, 
     125                    u_int32_t period, 
     126                    u_int32_t timeout, 
     127                    const char *oncheck, 
     128                    noit_conf_boolean disabled); 
    113129 
    114130API_EXPORT(int) 
  • src/noit_conf.c

    r07ad265 r7a1324a  
    577577} 
    578578 
     579static struct _valid_attr_t { 
     580  const char *scope; 
     581  const char *name; 
     582  const char *xpath; 
     583  int checks_fixate; 
     584} valid_attrs[] = { 
     585  { "/checks", "name", "@name", 0 }, 
     586  { "/checks", "target", "@target", 0 }, 
     587  { "/checks", "period", "@period", 0 }, 
     588  { "/checks", "timeout", "@timeout", 0 }, 
     589  { "/checks", "oncheck", "@oncheck", 0 }, 
     590  { "/checks", "module", "@module", 1 }, 
     591}; 
     592 
     593void 
     594noit_console_state_add_check_attrs(noit_console_state_t *state, 
     595                                   console_cmd_func_t f) { 
     596  int i; 
     597  for(i = 0; 
     598      i < sizeof(valid_attrs)/sizeof(valid_attrs[0]); 
     599      i++) { 
     600    noit_console_state_add_cmd(state, 
     601      NCSCMD(valid_attrs[i].name, f, 
     602             NULL, &valid_attrs[i])); 
     603  } 
     604} 
     605 
     606static int 
     607validate_attr_set_scope(noit_conf_t_userdata_t *info, 
     608                        struct _valid_attr_t *attrinfo) { 
     609  int len; 
     610  len = strlen(attrinfo->scope); 
     611  if(strncmp(info->path, attrinfo->scope, len) || 
     612     (info->path[len] != '\0' && info->path[len] != '/')) { 
     613    return -1; 
     614  } 
     615  return 0; 
     616} 
     617static int 
     618replace_attr(noit_console_closure_t ncct, 
     619             noit_conf_t_userdata_t *info, struct _valid_attr_t *attrinfo, 
     620             const char *value) { 
     621  int cnt, rv = -1; 
     622  xmlXPathObjectPtr pobj = NULL; 
     623  xmlNodePtr node; 
     624  char xpath[1024], *path; 
     625 
     626  path = info->path; 
     627  if(!strcmp(path, "/")) path = ""; 
     628 
     629  if(attrinfo->checks_fixate) { 
     630    /* Only if checks will fixate this attribute shall we check for 
     631     * child <check> nodes. 
     632     * NOTE: this return nothing and "seems" okay if we are _in_ 
     633     *       a <check> node.  That case is handled below. 
     634     */ 
     635    snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); 
     636    pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     637    if(pobj && pobj->type == XPATH_NODESET && 
     638       !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     639      nc_printf(ncct, "Cannot set '%s', it would effect live checks\n", 
     640                attrinfo->name); 
     641      goto out; 
     642    } 
     643    if(pobj) xmlXPathFreeObject(pobj); 
     644  } 
     645  snprintf(xpath, sizeof(xpath), "/noit/%s", path); 
     646  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     647  if(!pobj || pobj->type != XPATH_NODESET) goto out; 
     648  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     649  if(cnt != 1) { 
     650    nc_printf(ncct, "Internal error: context node disappeared\n"); 
     651    goto out; 
     652  } 
     653  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     654  if(attrinfo->checks_fixate && 
     655     !strcmp((const char *)node->name, "check")) { 
     656    /* Detect if  we are actually a <check> node and attempting to 
     657     * change something we shouldn't. 
     658     * This is the counterpart noted above. 
     659     */ 
     660    nc_printf(ncct, "Cannot set '%s', it would effect live checks\n"); 
     661    goto out; 
     662  } 
     663  xmlUnsetProp(node, (xmlChar *)attrinfo->name); 
     664  if(value) 
     665    xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)value); 
     666  rv = 0; 
     667 out: 
     668  if(pobj) xmlXPathFreeObject(pobj); 
     669  return rv; 
     670} 
     671static void  
     672refresh_subchecks(noit_console_closure_t ncct, 
     673                  noit_conf_t_userdata_t *info) { 
     674  char *path; 
     675  char xpath[1024]; 
     676  
     677  path = info->path; 
     678  if(!strcmp(path, "/")) path = ""; 
     679 
     680  snprintf(xpath, sizeof(xpath), "/noit/%s[@uuid]", path); 
     681  noit_poller_process_checks(xpath); 
     682  snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); 
     683  noit_poller_process_checks(xpath); 
     684} 
     685int 
     686noit_conf_check_set_attr(noit_console_closure_t ncct, 
     687                         int argc, char **argv, 
     688                         noit_console_state_t *state, void *closure) { 
     689  struct _valid_attr_t *attrinfo = closure; 
     690  noit_conf_t_userdata_t *info; 
     691 
     692  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     693  if(!info || validate_attr_set_scope(info, attrinfo)) { 
     694    nc_printf(ncct, "'%s' attribute only valid in %s scope\n", 
     695              attrinfo->name, attrinfo->scope); 
     696    return -1; 
     697  } 
     698 
     699  if(argc != 1) { 
     700    nc_printf(ncct, "set requires exactly one value\n"); 
     701    return -1; 
     702  } 
     703  /* Okay, we have an attribute and it should be set/replaced on the 
     704   * current path. 
     705   */ 
     706  if(replace_attr(ncct, info, attrinfo, argv[0])) { 
     707    return -1; 
     708  } 
     709 
     710  /* So, we updated an attribute, so we need to reload all checks 
     711   * that are descendent-or-self of this node. 
     712   */ 
     713  refresh_subchecks(ncct, info); 
     714  return 0; 
     715} 
     716 
     717int 
     718noit_conf_check_unset_attr(noit_console_closure_t ncct, 
     719                           int argc, char **argv, 
     720                           noit_console_state_t *state, void *closure) { 
     721  struct _valid_attr_t *attrinfo = closure; 
     722  noit_conf_t_userdata_t *info; 
     723 
     724  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     725  if(!info || validate_attr_set_scope(info, attrinfo)) { 
     726    nc_printf(ncct, "'%s' attribute only valid in %s scope\n", 
     727              attrinfo->name, attrinfo->scope); 
     728    return -1; 
     729  } 
     730 
     731  if(argc != 0) { 
     732    nc_printf(ncct, "no arguments allowed to this command.\n"); 
     733    return -1; 
     734  } 
     735  /* Okay, we have an attribute and it should be set/replaced on the 
     736   * current path. 
     737   */ 
     738  if(replace_attr(ncct, info, attrinfo, NULL)) { 
     739    return -1; 
     740  } 
     741 
     742  /* So, we updated an attribute, so we need to reload all checks 
     743   * that are descendent-or-self of this node. 
     744   */ 
     745  refresh_subchecks(ncct, info); 
     746  return 0; 
     747} 
     748 
     749#define NEW_STATE(a) (a) = calloc(1, sizeof(*(a))) 
     750#define ADD_CMD(a,cmd,func,ss,c) \ 
     751  noit_console_state_add_cmd((a), \ 
     752    NCSCMD(cmd, func, ss, c)) 
     753#define DELEGATE_CMD(a,cmd,ss) \ 
     754  noit_console_state_add_cmd((a), \ 
     755    NCSCMD(cmd, noit_console_state_delegate, ss, NULL)) 
     756 
    579757static 
    580758void register_console_config_commands() { 
    581759  noit_console_state_t *tl, *_conf_state, *_conf_t_state, 
    582                        *_write_state; 
     760                       *_write_state, *_attr_state, 
     761                       *_unset_state, *_uattr_state; 
    583762 
    584763  tl = noit_console_state_initial(); 
    585764 
    586   _write_state = calloc(1, sizeof(*_write_state)); 
    587   noit_console_state_add_cmd(_write_state, 
    588     NCSCMD("terminal", noit_conf_write_terminal, NULL, NULL)); 
    589   noit_console_state_add_cmd(_write_state, 
    590     NCSCMD("file", noit_conf_write_file, NULL, NULL)); 
    591   /* write mememory?  It's to a file, but I like router syntax */ 
    592   noit_console_state_add_cmd(_write_state, 
    593     NCSCMD("memory", noit_conf_write_file, NULL, NULL)); 
    594  
    595   _conf_t_state = calloc(1, sizeof(*_conf_t_state)); 
     765  /* write <terimal|memory|file> */ 
     766  NEW_STATE(_write_state); 
     767  ADD_CMD(_write_state, "terminal", noit_conf_write_terminal, NULL, NULL); 
     768  ADD_CMD(_write_state, "file", noit_conf_write_file, NULL, NULL); 
     769  /* write memory?  It's to a file, but I like router syntax */ 
     770  ADD_CMD(_write_state, "memory", noit_conf_write_file, NULL, NULL); 
     771 
     772  /* attribute <attrname> <value> */ 
     773  NEW_STATE(_attr_state); 
     774  noit_console_state_add_check_attrs(_attr_state, noit_conf_check_set_attr); 
     775  
     776  /* no attribute <attrname> <value> */ 
     777  NEW_STATE(_uattr_state); 
     778  noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr); 
     779  NEW_STATE(_unset_state); 
     780  DELEGATE_CMD(_unset_state, "attribute", _uattr_state); 
     781  
     782  NEW_STATE(_conf_t_state);  
    596783  _conf_t_state->console_prompt_function = conf_t_prompt; 
    597784  noit_console_state_add_cmd(_conf_t_state, &console_command_exit); 
    598   noit_console_state_add_cmd(_conf_t_state, 
    599     NCSCMD("ls", noit_console_config_show, NULL, NULL)); 
    600   noit_console_state_add_cmd(_conf_t_state, 
    601     NCSCMD("cd", noit_console_config_cd, NULL, NULL)); 
    602   noit_console_state_add_cmd(_conf_t_state, 
    603     NCSCMD("write", noit_console_state_delegate, _write_state, NULL)); 
    604  
    605   _conf_state = calloc(1, sizeof(*_conf_state)); 
    606   noit_console_state_add_cmd(_conf_state, 
    607     NCSCMD("terminal", noit_console_state_conf_terminal, _conf_t_state, NULL)); 
    608  
    609   noit_console_state_add_cmd(tl, 
    610     NCSCMD("configure", noit_console_state_delegate, _conf_state, NULL)); 
    611   noit_console_state_add_cmd(tl, 
    612     NCSCMD("write", noit_console_state_delegate, _write_state, NULL)); 
    613 
     785  ADD_CMD(_conf_t_state, "ls", noit_console_config_show, NULL, NULL); 
     786  ADD_CMD(_conf_t_state, "cd", noit_console_config_cd, NULL, NULL); 
     787  DELEGATE_CMD(_conf_t_state, "write", _write_state); 
     788  DELEGATE_CMD(_conf_t_state, "attribute", _attr_state); 
     789  DELEGATE_CMD(_conf_t_state, "no", _unset_state); 
     790 
     791  NEW_STATE(_conf_state); 
     792  ADD_CMD(_conf_state, "terminal", noit_console_state_conf_terminal, _conf_t_state, NULL); 
     793 
     794  ADD_CMD(tl, "configure", noit_console_state_delegate, _conf_state, NULL); 
     795  ADD_CMD(tl, "write", noit_console_state_delegate, _write_state, NULL); 
     796
  • src/noit_conf.h

    r1fe89bb r7a1324a  
    99#include "noit_defines.h" 
    1010#include "utils/noit_hash.h" 
     11#include "noit_console.h" 
    1112 
    12 typedef enum { noit_true, noit_false } noit_conf_boolean; 
     13typedef enum { noit_false = 0, noit_true } noit_conf_boolean; 
    1314typedef void * noit_conf_section_t; 
    1415 
     
    5253                                      const char *path, noit_conf_boolean value); 
    5354 
     55API_EXPORT(int) 
     56  noit_conf_check_set_attr(noit_console_closure_t ncct, 
     57                           int argc, char **argv, 
     58                           noit_console_state_t *state, void *closure); 
     59 
    5460#endif 
  • src/noit_console.c

    ra9f9cf2 r7a1324a  
    231231                      noit_console_closure_t ncct) { 
    232232  char **cmds; 
     233  HistEvent ev; 
    233234  int i, cnt = 32; 
     235 
    234236  cmds = alloca(32 * sizeof(*cmds)); 
    235237  i = noit_tokenize(buffer, cmds, &cnt); 
     238 
     239  /* < 0 is an error, that's fine.  We want it in the history to "fix" */ 
     240  /* > 0 means we had arguments, so let's put it in the history */ 
     241  /* 0 means nothing -- and that isn't worthy of history inclusion */ 
     242  if(i) history(ncct->hist, &ev, H_ENTER, buffer); 
     243 
    236244  if(i>cnt) nc_printf(ncct, "Command length too long.\n"); 
    237245  else if(i<0) nc_printf(ncct, "Error at offset: %d\n", 0-i); 
     
    322330    if(buffer) { 
    323331      char *cmd_buffer; 
    324       HistEvent ev; 
    325332      cmd_buffer = malloc(plen+1); 
    326333      memcpy(cmd_buffer, buffer, plen); 
     
    329336      if(cmd_buffer[plen-1] == '\n') cmd_buffer[plen-1] = '\0'; 
    330337      noitL(noit_debug, "IN: '%s'\n", cmd_buffer); 
    331       history(ncct->hist, &ev, H_ENTER, cmd_buffer); 
    332338      noit_console_dispatch(e, cmd_buffer, ncct); 
    333339      free(cmd_buffer);