/* Ensures that the expanded string contains required number of mandatory * macros. Returns reallocated expanded. */ static char * add_missing_macros(char expanded[], size_t len, size_t nmacros, custom_macro_t macros[]) { int groups[nmacros]; size_t i; memset(&groups, 0, sizeof(groups)); for(i = 0U; i < nmacros; ++i) { custom_macro_t *const macro = ¯os[i]; const int group = macro->group; if(group >= 0) { groups[group] += macro->uses_left; } } for(i = 0U; i < nmacros; ++i) { custom_macro_t *const macro = ¯os[i]; const int group = macro->group; int *const uses_left = (group >= 0) ? &groups[group] : ¯o->uses_left; while(*uses_left > 0) { expanded = extend_string(expanded, " ", &len); expanded = extend_string(expanded, macro->value, &len); --*uses_left; } } return expanded; }
/* append string to stringbuffer */ void stringbuffer_append(stringbuffer_t *sb, const char *s) { int len = strlen(s); /* increase capacity if needed. */ if (sb->capacity <= (len + sb->len)) { /* if we're bigger than the chunksize then allocate len. */ if (len > STRINGBUFFER_CHUNKSIZE) { sb->buf = extend_string(sb->buf, sb->capacity, len); sb->capacity += len; } else { /* otherwise allocate chunksize. */ sb->buf = extend_string(sb->buf, sb->capacity, STRINGBUFFER_CHUNKSIZE); sb->capacity += STRINGBUFFER_CHUNKSIZE; } } /* copy new string into place: keep in mind we know all * lengths so strcat() would be less effecient. */ memcpy(&sb->buf[sb->len], s, len); sb->len += len; sb->buf[sb->len] = 0; return; }
char * expand_envvars(const char str[], int escape_vals) { char *result = NULL; size_t len = 0; int prev_slash = 0; while(*str != '\0') { if(!prev_slash && *str == '$' && isalpha(str[1])) { char var_name[NAME_MAX]; const char *p = str + 1; char *q = var_name; const char *var_value; while((isalnum(*p) || *p == '_') && q - var_name < sizeof(var_name) - 1) *q++ = *p++; *q = '\0'; var_value = env_get(var_name); if(var_value != NULL) { char *escaped_var_value = NULL; if(escape_vals) { escaped_var_value = escape_filename(var_value, 1); var_value = escaped_var_value; } result = extend_string(result, var_value, &len); free(escaped_var_value); str = p; } else { str++; } } else { prev_slash = (*str == '\\') ? !prev_slash : 0; if(!prev_slash || escape_vals) { const char single_char[] = { *str, '\0' }; result = extend_string(result, single_char, &len); } str++; } } if(result == NULL) result = strdup(""); return result; }
char * eval_arglist(const char args[], const char **stop_ptr) { size_t len = 0; char *eval_result = NULL; assert(args[0] != '\0'); while(args[0] != '\0') { char *free_this = NULL; const char *tmp_result = NULL; var_t result = var_false(); const ParsingErrors parsing_error = parse(args, &result); if(parsing_error == PE_INVALID_EXPRESSION && is_prev_token_whitespace()) { result = get_parsing_result(); tmp_result = free_this = var_to_string(result); args = get_last_parsed_char(); } else if(parsing_error == PE_NO_ERROR) { tmp_result = free_this = var_to_string(result); args = get_last_position(); } if(tmp_result == NULL) { var_free(result); break; } if(!is_null_or_empty(eval_result)) { eval_result = extend_string(eval_result, " ", &len); } eval_result = extend_string(eval_result, tmp_result, &len); var_free(result); free(free_this); args = skip_whitespace(args); } if(args[0] == '\0') { return eval_result; } else { free(eval_result); *stop_ptr = args; return NULL; } }
/* append character to stringbuffer */ void stringbuffer_append_c(stringbuffer_t *sb, char c) { if (sb->capacity <= (sb->len)) { sb->buf = extend_string(sb->buf, sb->len, STRINGBUFFER_CHUNKSIZE); sb->capacity += STRINGBUFFER_CHUNKSIZE; } sb->buf[sb->len] = c; sb->len++; sb->buf[sb->len] = 0; }
char * expand_custom_macros(const char pattern[], size_t nmacros, custom_macro_t macros[]) { char *expanded = strdup(""); size_t len = 0; while(*pattern != '\0') { if(pattern[0] != '%') { const char single_char[] = { *pattern, '\0' }; expanded = extend_string(expanded, single_char, &len); } else if(pattern[1] == '%' || pattern[1] == '\0') { expanded = extend_string(expanded, "%", &len); pattern += pattern[1] == '%'; } else { size_t i = 0U; ++pattern; while(i < nmacros && macros[i].letter != *pattern) { ++i; } if(i < nmacros) { expanded = extend_string(expanded, macros[i].value, &len); --macros[i].uses_left; macros[i].explicit_use = 1; } } pattern++; } expanded = add_missing_macros(expanded, len, nmacros, macros); return expanded; }
/* Appends value to filter expression (using logical or and whole pattern * matching). Returns zero on success, otherwise non-zero is returned. */ static int append_to_filter(filter_t *filter, const char value[]) { size_t len = strlen(filter->raw); char *const escaped_value = escape_name_for_filter(value); if(len != 0) { filter->raw = extend_string(filter->raw, "|", &len); } filter->raw = extend_string(filter->raw, "^", &len); filter->raw = extend_string(filter->raw, escaped_value, &len); free(escaped_value); filter->raw = extend_string(filter->raw, "$", &len); reset_regex(filter, filter->raw); return (filter->is_regex_valid || filter->raw[0] == '\0') ? 0 : 1; }
break; case '"': if(html) { strcpy(dst2, """); dst2 += 6; break; } default: def: *dst2++ = *src; } src++; } pop_stack(); *dst2 = 0; push_malloced_string(extend_string(dst, dst2 - dst)); } #endif #ifdef F_REPLACE_HTML void f_replace_html() {replace_mxp_html(1,0);} #endif #ifdef F_REPLACE_MXP void f_replace_mxp() {replace_mxp_html(0,1);} #endif
char *read_file(const char * file, int start, int len) { struct stat st; #ifndef PACKAGE_COMPRESS FILE *f; #else gzFile f; #endif int chunk; char *str, *p, *p2; if (len < 0) return 0; file = check_valid_path(file, current_object, "read_file", 0); if (!file) return 0; /* * file doesn't exist, or is really a directory */ if (stat(file, &st) == -1 || (st.st_mode & S_IFDIR)) return 0; #ifndef PACKAGE_COMPRESS f = fopen(file, FOPEN_READ); #else f = gzopen(file, "rb"); #endif if (f == 0) return 0; if (start < 1) start = 1; if (len == 0) len = 2*READ_FILE_MAX_SIZE; str = new_string(2*READ_FILE_MAX_SIZE, "read_file: str"); if (st.st_size== 0) { /* zero length file */ str[0] = 0; #ifndef PACKAGE_COMPRESS fclose(f); #else gzclose(f); #endif str = extend_string(str, 0); /* fix string length */ return str; } do { #ifndef PACKAGE_COMPRESS chunk = fread(str, 1, 2*READ_FILE_MAX_SIZE, f); #else chunk = gzread(f, str, 2*READ_FILE_MAX_SIZE); #endif if (chunk < 1) goto free_str; p = str; while (start > 1) { /* skip newlines */ p2 = (char *)memchr(p, '\n', 2*READ_FILE_MAX_SIZE+str-p); if (p2) { p = p2 + 1; start--; } else break; } } while (start > 1); p2 = str; while (1) { char c; c = *p++; if (p-str > chunk) { if (chunk == 2*READ_FILE_MAX_SIZE) { goto free_str; //file too big } else break; //reached the end } if (p2-str > READ_FILE_MAX_SIZE) goto free_str; //file too big if (c == '\0') { FREE_MSTR(str); #ifndef PACKAGE_COMPRESS fclose(f); #else gzclose(f); #endif error("Attempted to read '\\0' into string!\n"); } if (c != '\r' || *p != '\n') { *p2++ = c; if (c == '\n' && --len == 0) break; /* done */ } } *p2 = 0; str = extend_string(str, p2 - str); /* fix string length */ #ifndef PACKAGE_COMPRESS fclose(f); #else gzclose(f); #endif return str; /* Error path: unwind allocated resources */ free_str: FREE_MSTR(str); #ifndef PACKAGE_COMPRESS fclose(f); #else gzclose(f); #endif return 0; }
char *read_file (const char * file, int start, int len) { struct stat st; FILE *f; int lastchunk, chunk, ssize, fsize; char *str, *p, *p2; if (len < 0) return 0; file = check_valid_path(file, current_object, "read_file", 0); if (!file) return 0; /* * file doesn't exist, or is really a directory */ if (stat(file, &st) == -1 || (st.st_mode & S_IFDIR)) return 0; f = fopen(file, FOPEN_READ); if (f == 0) return 0; #ifndef LATTICE if (fstat(fileno(f), &st) == -1) fatal("Could not stat an open file.\n"); #endif /* lastchunk = the size of the last chunk we read * chunk = size of the next chunk we will read (always < fsize) * fsize = amount left in file */ lastchunk = chunk = ssize = fsize = st.st_size; if (fsize > READ_FILE_MAX_SIZE) lastchunk = chunk = ssize = READ_FILE_MAX_SIZE; /* Can't shortcut out if size > max even if start and len aren't specified, since we still need to check for \0, and \r's may pull the size into range */ if (start < 1) start = 1; if (len == 0) len = READ_FILE_MAX_SIZE; str = new_string(ssize, "read_file: str"); if (fsize == 0) { /* zero length file */ str[0] = 0; fclose(f); return str; } do { /* read another chunk */ if (fsize == 0 || fread(str, chunk, 1, f) != 1) goto free_str; p = str; lastchunk = chunk; fsize -= chunk; if (chunk > fsize) chunk = fsize; while (start > 1) { /* skip newlines */ p2 = memchr(p, '\n', str + lastchunk - p); if (p2) { p = p2 + 1; start--; } else break; /* get another chunk */ } } while (start > 1); /* until we've skipped enough */ p2 = str; while (1) { char c; if (p == str + lastchunk) { /* need another chunk */ if (chunk > ssize - (p2 - str)) chunk = ssize - (p2 - str); /* space remaining */ if (fsize == 0) break; /* nothing left */ if (chunk == 0 || fread(p2, chunk, 1, f) != 1) goto free_str; p = p2; lastchunk = chunk + (p2 - str); /* fudge since we didn't start at str */ fsize -= chunk; if (chunk > fsize) chunk = fsize; } c = *p++; if (c == '\0') { FREE_MSTR(str); fclose(f); error("Attempted to read '\\0' into string!\n"); } if (c != '\r' || *p != '\n') { *p2++ = c; if (c == '\n' && --len == 0) break; /* done */ } } *p2 = 0; str = extend_string(str, p2 - str); /* fix string length */ fclose(f); return str; /* Error path: unwind allocated resources */ free_str: FREE_MSTR(str); fclose(f); return 0; }