/* * 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; }
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; }
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; }