/*
 * hostsfile_clusterlist_setup
 *
 * hostsfile clusterlist module setup function
 */
static int 
hostsfile_clusterlist_setup(nodeupdown_t handle) 
{
  int fd = -1, len;
  char buf[NODEUPDOWN_BUFFERLEN];
  char *p;

  if (!(hosts = list_create((ListDelF)free)))
    {
#ifndef NDEBUG
      fprintf(stderr, "list_create: %s\n", strerror(errno));
#endif /* NDEBUG */
      nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_OUTMEM);
      goto cleanup;
    }
                                                                                    
  if ((fd = open(NODEUPDOWN_CLUSTERLIST_HOSTSFILE_DEFAULT, O_RDONLY)) < 0)
    {
#ifndef NDEBUG
      fprintf(stderr, "open: %s\n", strerror(errno));
#endif /* NDEBUG */

      /* no nodes, just get out */
      if (errno == ENOENT)
        goto out;

      nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_CLUSTERLIST_MODULE);
      goto cleanup;
    }
                                                                                     
  while ((len = _readline(handle, fd, buf, NODEUPDOWN_BUFFERLEN)) > 0)
    {
      char *hostPtr;
      char *str;
                                                                                     
      if ((len = _remove_comments(buf, len)) == 0)
        continue;
                                                                                     
      if ((len = _remove_trailing_whitespace(buf, len)) == 0)
        continue;
                                                                                     
      if (!(hostPtr = _move_past_whitespace(buf)))
        continue;
                                                                                     
      if (hostPtr[0] == '\0')
        continue;
                                                                                     
      if (strchr(hostPtr, ' ') || strchr(hostPtr, '\t'))
        {
#ifndef NDEBUG
	  fprintf(stderr, "parse error\n");
#endif /* NDEBUG */
	  nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_CLUSTERLIST_MODULE);
          goto cleanup;
        }
                                                                                     
      if (strlen(hostPtr) > NODEUPDOWN_MAXHOSTNAMELEN)
        {
#ifndef NDEBUG
	  fprintf(stderr, "parse error\n");
#endif /* NDEBUG */
	  nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_CLUSTERLIST_MODULE);
          goto cleanup;
        }
          
      /* Shorten hostname if necessary */
      if ((p = strchr(hostPtr, '.')))
        *p = '\0';
      
      if (!(str = strdup(hostPtr)))
        {
	  nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_OUTMEM);
          goto cleanup;
        }

      if (!list_append(hosts, str))
        {
#ifndef NDEBUG
	  fprintf(stderr, "list_append: %s\n", strerror(errno));
#endif /* NDEBUG */
	  nodeupdown_set_errnum(handle, NODEUPDOWN_ERR_CLUSTERLIST_MODULE);
          goto cleanup;
        }
    }
                                                                                     
 out:
  /* ignore potential error, just return result */
  close(fd);
  return 0;

 cleanup:
  /* ignore potential error, just return result */
  close(fd);
  return -1;
}
Exemplo n.º 2
0
static int
_parseline(conffile_t cf, char *linebuf, int linebuflen)
{
    int i, optionlen, rv, numargs = 0;
    char args[CONFFILE_MAX_ARGS][CONFFILE_MAX_ARGLEN];
    struct conffile_option *option = NULL;
    struct conffile_data data;
    char *ptr;

    memset(&data, '\0', sizeof(struct conffile_data));

    linebuflen = _remove_trailing_whitespace(cf, linebuf, linebuflen);
    if (linebuflen == 0)
        return 0;

    if ((linebuf = _move_past_whitespace(cf, linebuf)) == NULL)
        return 0;

    optionlen = 0;
    memset(cf->optionname, '\0', CONFFILE_MAX_OPTIONNAMELEN);
    while (optionlen < (CONFFILE_MAX_OPTIONNAMELEN-1) 
           && !isspace(*linebuf)
           && *linebuf != '\0') {
        cf->optionname[optionlen++] = *linebuf;
        linebuf++;
    }

    /* minus one to guarantee null termination */
    if (optionlen == (CONFFILE_MAX_OPTIONNAMELEN-1)) {
        cf->errnum = CONFFILE_ERR_PARSE_OVERFLOW_OPTIONLEN;
        return -1;
    }

    for (i = 0; i < cf->options_len; i++) {
        int rv;
        if (cf->flags & CONFFILE_FLAG_OPTION_CASESENSITIVE) 
            rv = strcmp(cf->options[i].optionname, cf->optionname);
        else
            rv = strcasecmp(cf->options[i].optionname, cf->optionname);

        if (rv == 0) {
            option = &(cf->options[i]);
            break;
        }
    }

    if (option == NULL) {
        if (cf->flags & CONFFILE_FLAG_OPTION_IGNORE_UNKNOWN)
            return 0;
        cf->errnum = CONFFILE_ERR_PARSE_OPTION_UNKNOWN;
        return -1;
    }

    if (option->option_type == CONFFILE_OPTION_IGNORE)
        return 0;

    (*option->count_ptr)++;

    if (option->max_count > 0) {
        if ((*option->count_ptr) > option->max_count) {
            cf->errnum = CONFFILE_ERR_PARSE_OPTION_TOOMANY;
            return -1;
        }
    }

    if ((linebuf = _move_past_whitespace(cf, linebuf)) != NULL) {
        if ((numargs = _parse_args(cf, linebuf, args)) < 0)
            return -1;
    }

    /* Argument checks */

    if (option->option_type == CONFFILE_OPTION_FLAG && numargs != 0) {
        cf->errnum = CONFFILE_ERR_PARSE_ARG_TOOMANY;
        return -1;
    }

    if (((option->option_type == CONFFILE_OPTION_BOOL
          || option->option_type == CONFFILE_OPTION_INT
          || option->option_type == CONFFILE_OPTION_DOUBLE
          || option->option_type == CONFFILE_OPTION_STRING
          || option->option_type == CONFFILE_OPTION_LIST_INT
          || option->option_type == CONFFILE_OPTION_LIST_DOUBLE
          || option->option_type == CONFFILE_OPTION_LIST_STRING)
         && numargs == 0)) {
        cf->errnum = CONFFILE_ERR_PARSE_ARG_MISSING;
        return -1;
    }

    if (((option->option_type == CONFFILE_OPTION_BOOL
          || option->option_type == CONFFILE_OPTION_INT
          || option->option_type == CONFFILE_OPTION_DOUBLE
          || option->option_type == CONFFILE_OPTION_STRING)
         && numargs > 1)) {
        cf->errnum = CONFFILE_ERR_PARSE_ARG_TOOMANY;
        return -1;
    }

    if ((option->option_type == CONFFILE_OPTION_LIST_INT
         || option->option_type == CONFFILE_OPTION_LIST_DOUBLE
         || option->option_type == CONFFILE_OPTION_LIST_STRING)
        && ((int)option->option_type_arg) > 0
        && numargs != ((int)option->option_type_arg)) {
        if (numargs < ((int)option->option_type_arg))
            cf->errnum = CONFFILE_ERR_PARSE_ARG_MISSING;
        else
            cf->errnum = CONFFILE_ERR_PARSE_ARG_TOOMANY;
        return -1;
    }

    if (option->option_type == CONFFILE_OPTION_BOOL) {
        if (strcmp(args[0], "1") != 0
            && strcmp(args[0], "0") != 0
            && strcasecmp(args[0], "y") != 0
            && strcasecmp(args[0], "n") != 0
            && strcasecmp(args[0], "yes") != 0
            && strcasecmp(args[0], "no") != 0
            && strcasecmp(args[0], "on") != 0
            && strcasecmp(args[0], "off") != 0
            && strcasecmp(args[0], "t") != 0
            && strcasecmp(args[0], "f") != 0
            && strcasecmp(args[0], "true") != 0
            && strcasecmp(args[0], "false") != 0
            && strcasecmp(args[0], "enable") != 0
            && strcasecmp(args[0], "disable") != 0) {
            cf->errnum = CONFFILE_ERR_PARSE_ARG_INVALID;
            return -1;
        }
    }

    /* Calculate Data */

    if (option->option_type == CONFFILE_OPTION_BOOL) {
        if (!strcmp(args[0], "1")
            || !strcasecmp(args[0], "y")
            || !strcasecmp(args[0], "yes")
            || !strcasecmp(args[0], "on")
            || !strcasecmp(args[0], "t")
            || !strcasecmp(args[0], "true")
            || !strcasecmp(args[0], "enable"))
            data.boolval = 1;
        else
            data.boolval = 0;
    }
    else if (option->option_type == CONFFILE_OPTION_INT) {
        errno = 0;
        data.intval = strtol(args[0], &ptr, 0);
        if (errno || (args[0] + strlen(args[0])) != ptr) {
            cf->errnum = CONFFILE_ERR_PARSE_ARG_INVALID;
            return -1;
        }
    }
    else if (option->option_type == CONFFILE_OPTION_DOUBLE) {
        errno = 0;
        data.doubleval = strtod(args[0], &ptr);
        if (errno || (args[0] + strlen(args[0])) != ptr) {
            cf->errnum = CONFFILE_ERR_PARSE_ARG_INVALID;
            return -1;
        }
    }
    else if (option->option_type == CONFFILE_OPTION_STRING) {
        strncpy(data.string, args[0], CONFFILE_MAX_ARGLEN);
        data.string[CONFFILE_MAX_ARGLEN - 1] = '\0';
    }
    else if (option->option_type == CONFFILE_OPTION_LIST_INT) {
        int i;
        for (i = 0; i < numargs; i++) {
            errno = 0;
            data.intlist[i] = strtol(args[i], &ptr, 0);
            if (errno || (args[i] + strlen(args[i])) != ptr) {
                cf->errnum = CONFFILE_ERR_PARSE_ARG_INVALID;
                return -1;
            }
        }
        data.intlist_len = numargs;
    }
    else if (option->option_type == CONFFILE_OPTION_LIST_DOUBLE) {
        int i;
        for (i = 0; i < numargs; i++) {
            errno = 0;
            data.doublelist[i] = strtod(args[i], &ptr);
            if (errno || (args[i] + strlen(args[i])) != ptr) {
                cf->errnum = CONFFILE_ERR_PARSE_ARG_INVALID;
                return -1;
            }
        }
        data.doublelist_len = numargs;
    }
    else if (option->option_type == CONFFILE_OPTION_LIST_STRING) {
        int i;
        for (i = 0; i < numargs; i++) {
            strncpy(data.stringlist[i], args[i], CONFFILE_MAX_ARGLEN);
            data.stringlist[i][CONFFILE_MAX_ARGLEN - 1] = '\0';
        }
        data.stringlist_len = numargs;
    }

    cf->errnum = CONFFILE_ERR_SUCCESS;
    if (option->callback_func) {
        rv = (option->callback_func)(cf,
                                     &data,
                                     option->optionname,
                                     option->option_type,
                                     option->option_ptr,
                                     option->option_data,
                                     cf->app_ptr,
                                     cf->app_data);
        if (rv < 0) {
            if (cf->errnum == CONFFILE_ERR_SUCCESS)
                cf->errnum = CONFFILE_ERR_PARSE_CALLBACK;
            return -1;
        }
    }

    return 0;
}
/* 
 * hostsfile_clusterlist_setup
 *
 * hostsfile clusterlist module setup function.  Open hostsfile, read
 * each line of the hostsfile, and save hosts into hosts list.
 */
static int 
hostsfile_clusterlist_setup(void)
{
  int len, fd = -1;
  char buf[HOSTSFILE_PARSE_BUFLEN];
  char *p;

  if (hosts)
    {
      CEREBRO_DBG(("hosts non-null"));
      return 0;
    }

  if (!(hosts = list_create((ListDelF)free)))
    {
      CEREBRO_ERR(("list_create: %s", strerror(errno)));
      goto cleanup;
    }

  if ((fd = open(CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, O_RDONLY)) < 0)
    {
      CEREBRO_ERR(("hostsfile '%s' cannot be opened: %s", 
                   CEREBRO_CLUSTERLIST_HOSTSFILE_DEFAULT, strerror(errno)));
      goto cleanup;
    }
 
  while ((len = _readline(fd, buf, HOSTSFILE_PARSE_BUFLEN)) > 0)
    {
      char *hostPtr;
      char *str;

      if (!(len = _remove_comments(buf, len)))
        continue;

      if (len < 0)
        goto cleanup;

      if (!(len = _remove_trailing_whitespace(buf, len)))
        continue;

      if (len < 0)
        goto cleanup;

      if (!(hostPtr = _move_past_whitespace(buf)))
        goto cleanup;

      if (hostPtr[0] == '\0')
        continue;

      if (strchr(hostPtr, ' ') || strchr(hostPtr, '\t'))
        {
          cerebro_err_output("hostsfile host contains whitespace");
          goto cleanup;
        }

      if (strlen(hostPtr) > CEREBRO_MAX_NODENAME_LEN)
        {
          cerebro_err_output("hostsfile node '%s' exceeds max length", hostPtr);
          goto cleanup;
        }
      
      /* Shorten hostname if necessary */
      if ((p = strchr(hostPtr, '.')))
        *p = '\0';

      if (!(str = strdup(hostPtr)))
        {
          CEREBRO_ERR(("strdup: %s", strerror(errno)));
          goto cleanup;
        }

      if (!list_append(hosts, str))
        {
          CEREBRO_ERR(("list_append: %s", strerror(errno)));
          goto cleanup;
        }
    }
  
  if (len < 0)
    goto cleanup;

  /* ignore potential error, just return result */
  close(fd);
  return 0;

 cleanup:
  /* ignore potential error, just return result */
  close(fd);
  if (hosts)
    list_destroy(hosts);
  hosts = NULL;
  return -1;
}
Exemplo n.º 4
0
int
_parse_args(conffile_t cf, 
            char *linebuf, 
            char args[CONFFILE_MAX_ARGS][CONFFILE_MAX_ARGLEN])
{
    int quote_flag, numargs = 0;

    while (1) {
        int arglen = 0;

        /* Following is needed for the following corner case
         *
         * optionname1    arg        \
         *
         * optionname2    arg
         *
         * In other words, a continuation character is used, but
         * there is no data on the next line.  There may be
         * remaining whitespace.
         */
         if ((linebuf = _move_past_whitespace(cf, linebuf)) == NULL)
            break;
        
        quote_flag = 0;
        memset(args[numargs], '\0', CONFFILE_MAX_ARGLEN);
        while (*linebuf != '\0' 
               && (quote_flag == 1 || !isspace(*linebuf))) {

            if (*linebuf == '"') {
                quote_flag = !quote_flag;
                linebuf++;
                continue;
            }

            /* All continuation character parse errors should be
             * discovered by _readline and _remove_comments.  But
             * we'll check again just in case.
             */
            if (*linebuf == '\\') {
                linebuf++;
                if (*linebuf != '\\'
                    && *linebuf != '#'
                    && *linebuf != '"') {
                    cf->errnum = CONFFILE_ERR_PARSE_CONTINUATION;
                    return -1;
                }
            }

            args[numargs][arglen] = *linebuf;
            linebuf++;
            arglen++;

            /* minus one to guarantee null termination */
            if (arglen == (CONFFILE_MAX_ARGLEN-1)) {
                cf->errnum = CONFFILE_ERR_PARSE_OVERFLOW_ARGLEN;
                return -1;
            }

        }

        if (quote_flag > 0) {
            cf->errnum = CONFFILE_ERR_PARSE_QUOTE;
            return -1;
        }

        numargs++;
                                
        if (*linebuf == '\0')
            break;
    }

    return numargs;
}