bool field_line::parse_char(char c) { // Ensure that the overall header length is within limitts if (++length_ > max_line_length_) state_ = HEADER_ERROR_LENGTH; switch (state_) { case HEADER_NAME: if (std::isalpha(c) || ('-' == c)) name_.push_back(static_cast<char>(std::tolower(c))); else if (':' == c) state_ = HEADER_VALUE_LS; else return false; break; case HEADER_VALUE_LS: // Ignore leading whitespace if (is_space_or_tab(c)) // but only upto to a limit! if (++ws_count_ > max_whitespace_) { state_ = HEADER_ERROR_WS; return false; } else break; else state_ = HEADER_VALUE; [[fallthrough]]; // intentional fall-through case HEADER_VALUE: // The header line should end with an \r\n... if (!is_end_of_line(c)) value_.push_back(c); else if ('\r' == c) state_ = HEADER_LF; else // ('\n' == c) { if (strict_crlf_) { state_ = HEADER_ERROR_CRLF; return false; } else state_ = HEADER_VALID; } break; case HEADER_LF: if ('\n' == c) state_ = HEADER_VALID; else return false; break; default: return false; } return true; }
int read_config(const char *path, int type) { char line[1024]; FILE *fp; char *s, *key, *val, *end_of_key; const char *error; char *cp, *cp2; int i; int lineno = 0; int got_transport = 0; int min_timeout = 0; struct ticket_config defaults = { { 0 } }; struct ticket_config *current_tk = NULL; fp = fopen(path, "r"); if (!fp) { log_error("failed to open %s: %s", path, strerror(errno)); return -1; } booth_conf = malloc(sizeof(struct booth_config) + TICKET_ALLOC * sizeof(struct ticket_config)); if (!booth_conf) { fclose(fp); log_error("failed to alloc memory for booth config"); return -ENOMEM; } memset(booth_conf, 0, sizeof(struct booth_config) + TICKET_ALLOC * sizeof(struct ticket_config)); ticket_size = TICKET_ALLOC; booth_conf->proto = UDP; booth_conf->port = BOOTH_DEFAULT_PORT; booth_conf->maxtimeskew = BOOTH_DEFAULT_MAX_TIME_SKEW; booth_conf->authkey[0] = '\0'; /* Provide safe defaults. -1 is reserved, though. */ booth_conf->uid = -2; booth_conf->gid = -2; strcpy(booth_conf->site_user, "hacluster"); strcpy(booth_conf->site_group, "haclient"); strcpy(booth_conf->arb_user, "nobody"); strcpy(booth_conf->arb_group, "nobody"); parse_weights("", defaults.weight); defaults.clu_test.path = NULL; defaults.clu_test.pid = 0; defaults.clu_test.status = 0; defaults.clu_test.progstate = EXTPROG_IDLE; defaults.term_duration = DEFAULT_TICKET_EXPIRY; defaults.timeout = DEFAULT_TICKET_TIMEOUT; defaults.retries = DEFAULT_RETRIES; defaults.acquire_after = 0; defaults.mode = TICKET_MODE_AUTO; error = ""; log_debug("reading config file %s", path); while (fgets(line, sizeof(line), fp)) { lineno++; s = skip_while(line, isspace); if (is_end_of_line(s) || *s == '#') continue; key = s; /* Key */ end_of_key = skip_while_in(key, isalnum, "-_"); if (end_of_key == key) { error = "No key"; goto err; } if (!*end_of_key) goto exp_equal; /* whitespace, and something else but nothing more? */ s = skip_while(end_of_key, isspace); if (*s != '=') { exp_equal: error = "Expected '=' after key"; goto err; } s++; /* It's my buffer, and I terminate if I want to. */ /* But not earlier than that, because we had to check for = */ *end_of_key = 0; /* Value tokenizing */ s = skip_while(s, isspace); switch (*s) { case '"': case '\'': val = s+1; s = skip_until(val, *s); /* Terminate value */ if (!*s) { error = "Unterminated quoted string"; goto err; } /* Remove and skip quote */ *s = 0; s++; if (*(s = skip_while(s, isspace)) && *s != '#') { error = "Surplus data after value"; goto err; } *s = 0; break; case 0: no_value: error = "No value"; goto err; break; default: val = s; /* Rest of line. */ i = strlen(s); /* i > 0 because of "case 0" above. */ while (i > 0 && isspace(s[i-1])) i--; s += i; *s = 0; } if (val == s) goto no_value; if (strlen(key) > BOOTH_NAME_LEN || strlen(val) > BOOTH_NAME_LEN) { error = "key/value too long"; goto err; } if (strcmp(key, "transport") == 0) { if (got_transport) { error = "config file has multiple transport lines"; goto err; } if (strcasecmp(val, "UDP") == 0) booth_conf->proto = UDP; else if (strcasecmp(val, "SCTP") == 0) booth_conf->proto = SCTP; else { error = "invalid transport protocol"; goto err; } got_transport = 1; continue; } if (strcmp(key, "port") == 0) { booth_conf->port = atoi(val); continue; } if (strcmp(key, "name") == 0) { safe_copy(booth_conf->name, val, BOOTH_NAME_LEN, "name"); continue; } #if HAVE_LIBGCRYPT || HAVE_LIBMHASH if (strcmp(key, "authfile") == 0) { safe_copy(booth_conf->authfile, val, BOOTH_PATH_LEN, "authfile"); continue; } if (strcmp(key, "maxtimeskew") == 0) { booth_conf->maxtimeskew = atoi(val); continue; } #endif if (strcmp(key, "site") == 0) { if (add_site(val, SITE)) goto err; continue; } if (strcmp(key, "arbitrator") == 0) { if (add_site(val, ARBITRATOR)) goto err; continue; } if (strcmp(key, "site-user") == 0) { safe_copy(booth_conf->site_user, optarg, BOOTH_NAME_LEN, "site-user"); continue; } if (strcmp(key, "site-group") == 0) { safe_copy(booth_conf->site_group, optarg, BOOTH_NAME_LEN, "site-group"); continue; } if (strcmp(key, "arbitrator-user") == 0) { safe_copy(booth_conf->arb_user, optarg, BOOTH_NAME_LEN, "arbitrator-user"); continue; } if (strcmp(key, "arbitrator-group") == 0) { safe_copy(booth_conf->arb_group, optarg, BOOTH_NAME_LEN, "arbitrator-group"); continue; } if (strcmp(key, "debug") == 0) { if (type != CLIENT && type != GEOSTORE) debug_level = max(debug_level, atoi(val)); continue; } if (strcmp(key, "ticket") == 0) { if (current_tk && strcmp(current_tk->name, "__defaults__")) { if (!postproc_ticket(current_tk)) { goto err; } } if (!strcmp(val, "__defaults__")) { current_tk = &defaults; } else if (add_ticket(val, ¤t_tk, &defaults)) { goto err; } continue; } /* current_tk must be allocated at this point, otherwise * we don't know to which ticket the key refers */ if (!current_tk) { error = "Unexpected keyword"; goto err; } if (strcmp(key, "expire") == 0) { current_tk->term_duration = read_time(val); if (current_tk->term_duration <= 0) { error = "Expected time >0 for expire"; goto err; } continue; } if (strcmp(key, "timeout") == 0) { current_tk->timeout = read_time(val); if (current_tk->timeout <= 0) { error = "Expected time >0 for timeout"; goto err; } if (!min_timeout) { min_timeout = current_tk->timeout; } else { min_timeout = min(min_timeout, current_tk->timeout); } continue; } if (strcmp(key, "retries") == 0) { current_tk->retries = strtol(val, &s, 0); if (*s || s == val || current_tk->retries<3 || current_tk->retries > 100) { error = "Expected plain integer value in the range [3, 100] for retries"; goto err; } continue; } if (strcmp(key, "renewal-freq") == 0) { current_tk->renewal_freq = read_time(val); if (current_tk->renewal_freq <= 0) { error = "Expected time >0 for renewal-freq"; goto err; } continue; } if (strcmp(key, "acquire-after") == 0) { current_tk->acquire_after = read_time(val); if (current_tk->acquire_after < 0) { error = "Expected time >=0 for acquire-after"; goto err; } continue; } if (strcmp(key, "before-acquire-handler") == 0) { if (parse_extprog(val, current_tk)) { goto err; } continue; } if (strcmp(key, "attr-prereq") == 0) { if (parse_attr_prereq(val, current_tk)) { goto err; } continue; } if (strcmp(key, "mode") == 0) { current_tk->mode = retrieve_ticket_mode(val); continue; } if (strcmp(key, "weights") == 0) { if (parse_weights(val, current_tk->weight) < 0) goto err; continue; } error = "Unknown keyword"; goto err; } fclose(fp); if ((booth_conf->site_count % 2) == 0) { log_warn("Odd number of nodes is strongly recommended!"); } /* Default: make config name match config filename. */ if (!booth_conf->name[0]) { cp = strrchr(path, '/'); cp = cp ? cp+1 : (char *)path; cp2 = strrchr(cp, '.'); if (!cp2) cp2 = cp + strlen(cp); if (cp2-cp >= BOOTH_NAME_LEN) { log_error("booth config file name too long"); goto out; } strncpy(booth_conf->name, cp, cp2-cp); *(booth_conf->name+(cp2-cp)) = '\0'; } if (!postproc_ticket(current_tk)) { goto out; } poll_timeout = min(POLL_TIMEOUT, min_timeout/10); if (!poll_timeout) poll_timeout = POLL_TIMEOUT; return 0; err: fclose(fp); out: log_error("%s in config file line %d", error, lineno); free(booth_conf); booth_conf = NULL; return -1; }
bool chunk_header::parse_char(char c) { static const size_t MAX_SIZE_DIGITS(16); // enough for a 64 bit number // Ensure that the overall header length is within limits if (++length_ > max_line_length_) state_ = CHUNK_ERROR_LENGTH; switch (state_) { case CHUNK_SIZE_LS: // Ignore leading whitespace if (is_space_or_tab(c)) { // but only upto to a limit! if (++ws_count_ > max_whitespace_) { state_ = CHUNK_ERROR_WS; return false; } else break; } else state_ = CHUNK_SIZE; // intentional fall-through case CHUNK_SIZE: if (std::isxdigit (c)) { hex_size_.push_back(c); // limit the length of the hex string if (hex_size_.size() > MAX_SIZE_DIGITS) { state_ = CHUNK_ERROR_SIZE; return false; } } else { if (is_end_of_line(c) || (';' == c)) { size_ = from_hex_string(hex_size_); size_read_ = true; if (size_ > max_chunk_size_) { state_ = CHUNK_ERROR_SIZE; return false; } if (';' == c) { ws_count_ = 0; state_ = CHUNK_EXTENSION_LS; } else { if ('\r' == c) state_ = CHUNK_LF; else // ('\n' == c) { if (strict_crlf_) return false; else state_ = CHUNK_VALID; } } } else return false; } break; case CHUNK_EXTENSION_LS: // Ignore leading whitespace if (is_space_or_tab(c)) { // but only upto to a limit! if (++ws_count_ > max_whitespace_) return false; else break; } else state_ = CHUNK_EXTENSION; // intentional fall-through case CHUNK_EXTENSION: if (!is_end_of_line(c)) extension_.push_back(c); else if ('\r' == c) state_ = CHUNK_LF; else // ('\n' == c) { if (strict_crlf_) { state_ = CHUNK_ERROR_CRLF; return false; } else state_ = CHUNK_VALID; } break; case CHUNK_LF: if ('\n' == c) state_ = CHUNK_VALID; else return false; break; default: return false; } return true; }
const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, std::pair<const char*, const char*> &command) { PROFILE_FUNC(); // command and args const char *c = ptr; { PROFILE_BLOCK(command_and_args); // Skip the whitespaces. command.first = skip_whitespaces(c); // Skip the command. c = command.second = skip_word(command.first); // Up to the end of line or comment. while (! is_end_of_gcode_line(*c)) { // Skip whitespaces. c = skip_whitespaces(c); if (is_end_of_gcode_line(*c)) break; // Check the name of the axis. Axis axis = NUM_AXES; switch (*c) { case 'X': axis = X; break; case 'Y': axis = Y; break; case 'Z': axis = Z; break; case 'F': axis = F; break; default: if (*c == m_extrusion_axis) axis = E; break; } if (axis != NUM_AXES) { // Try to parse the numeric value. char *pend = nullptr; double v = strtod(++ c, &pend); if (pend != nullptr && is_end_of_word(*pend)) { // The axis value has been parsed correctly. gline.m_axis[int(axis)] = float(v); gline.m_mask |= 1 << int(axis); c = pend; } else // Skip the rest of the word. c = skip_word(c); } else // Skip the rest of the word. c = skip_word(c); } } if (gline.has(E) && m_config.use_relative_e_distances) m_position[E] = 0; // Skip the rest of the line. for (; ! is_end_of_line(*c); ++ c); // Copy the raw string including the comment, without the trailing newlines. if (c > ptr) { PROFILE_BLOCK(copy_raw_string); gline.m_raw.assign(ptr, c); } // Skip the trailing newlines. if (*c == '\r') ++ c; if (*c == '\n') ++ c; if (m_verbose) std::cout << gline.m_raw << std::endl; return c; }
bool request_line::parse_char(char c) { switch (state_) { case REQ_METHOD: // Valid HTTP methods must be uppercase chars if (std::isupper(c)) { method_.push_back(c); if (method_.size() > max_method_length_) { state_ = REQ_ERROR_METHOD_LENGTH; return false; } } // If this char is whitespace and method has been read else if (is_space_or_tab(c) && !method_.empty()) { ws_count_ = 1; state_ = REQ_URI; } else return false; break; case REQ_URI: if (is_end_of_line(c)) return false; else if (is_space_or_tab(c)) { // Ignore leading whitespace // but only upto to a limit! if (++ws_count_ > max_whitespace_) { state_ = REQ_ERROR_WS; return false; } if (!uri_.empty()) { ws_count_ = 1; state_ = REQ_HTTP_H; } } else { uri_.push_back(c); if (uri_.size() > max_uri_length_) { state_ = REQ_ERROR_URI_LENGTH; return false; } } break; case REQ_HTTP_H: // Ignore leading whitespace if (is_space_or_tab(c)) { // but only upto to a limit! if (++ws_count_ > max_whitespace_) { state_ = REQ_ERROR_WS; return false; } } else { if ('H' == c) state_ = REQ_HTTP_T1; else return false; } break; case REQ_HTTP_T1: if ('T' == c) state_ = REQ_HTTP_T2; else return false; break; case REQ_HTTP_T2: if ('T' == c) state_ = REQ_HTTP_P; else return false; break; case REQ_HTTP_P: if ('P' == c) state_ = REQ_HTTP_SLASH; else return false; break; case REQ_HTTP_SLASH: if ('/' == c) state_ = REQ_HTTP_MAJOR; else return false; break; case REQ_HTTP_MAJOR: if (std::isdigit(c)) { major_version_ = c; state_ = REQ_HTTP_DOT; } else return false; break; case REQ_HTTP_DOT: if ('.' == c) state_ = REQ_HTTP_MINOR; else return false; break; case REQ_HTTP_MINOR: if (std::isdigit(c)) { minor_version_ = c; state_ = REQ_CR; } else return false; break; case REQ_CR: // The HTTP line should end with a \r\n... if ('\r' == c) state_ = REQ_LF; else { // but (if not being strict) permit just \n if (!strict_crlf_ && ('\n' == c)) state_ = REQ_VALID; else { state_ = REQ_ERROR_CRLF; return false; } } break; case REQ_LF: if ('\n' == c) { state_ = REQ_VALID; break; } // intentional fall-through (for code coverage) default: return false; } return true; }