From c187732f09e477d9a611ad18bfa1739befb86074 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 24 Aug 2010 21:52:32 +0000 Subject: add profile include support Add support for "include" and "includedir" directives in profile files. See http://k5wiki.kerberos.org/wiki/Projects/Profile_Includes for more details. ticket: 6761 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24253 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/profile/prof_parse.c | 105 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 13 deletions(-) (limited to 'src/util/profile/prof_parse.c') diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c index 413c7dfbb0..1ed4484430 100644 --- a/src/util/profile/prof_parse.c +++ b/src/util/profile/prof_parse.c @@ -1,6 +1,7 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ #include "prof_int.h" +#include #include #include #ifdef HAVE_STDLIB_H @@ -8,6 +9,7 @@ #endif #include #include +#include #define SECTION_SEP_CHAR '/' @@ -22,6 +24,8 @@ struct parse_state { struct profile_node *current_section; }; +static errcode_t parse_file(FILE *f, struct parse_state *state); + static char *skip_over_blanks(char *cp) { while (*cp && isspace((int) (*cp))) @@ -33,7 +37,7 @@ static void strip_line(char *line) { char *p = line + strlen(line); while (p > line && (p[-1] == '\n' || p[-1] == '\r')) - *p-- = 0; + *--p = 0; } static void parse_quoted_string(char *str) @@ -201,10 +205,76 @@ static errcode_t parse_std_line(char *line, struct parse_state *state) return 0; } +/* Parse lines from filename as if they were part of the profile file. */ +static errcode_t parse_include_file(char *filename, struct parse_state *state) +{ + FILE *fp; + errcode_t retval = 0; + + fp = fopen(filename, "r"); + if (fp == NULL) + return PROF_FAIL_INCLUDE_FILE; + retval = parse_file(fp, state); + fclose(fp); + return retval; +} + +/* Return non-zero if filename contains only alphanumeric characters and + * underscores. */ +static int valid_name(const char *filename) +{ + const char *p; + + for (p = filename; *p != '\0'; p++) { + if (!isalnum((unsigned char)*p) && *p != '-' && *p != '_') + return 0; + } + return 1; +} + +/* + * Parse lines from files in dirname as if they were part of the profile file. + * Only files with names consisting entirely of alphanumeric chracters and + * underscores are parsed, in order to avoid parsing editor backup files, + * .rpmsave files, and the like. + */ +static errcode_t parse_include_dir(char *dirname, struct parse_state *state) +{ + DIR *dir; + char *pathname; + errcode_t retval; + struct dirent *ent; + + dir = opendir(dirname); + if (dir == NULL) + return PROF_FAIL_INCLUDE_DIR; + while ((ent = readdir(dir)) != NULL) { + if (!valid_name(ent->d_name)) + continue; + if (asprintf(&pathname, "%s/%s", dirname, ent->d_name) < 0) + return ENOMEM; + retval = parse_include_file(pathname, state); + free(pathname); + if (retval) + return retval; + } + return 0; +} + static errcode_t parse_line(char *line, struct parse_state *state) { char *cp; + if (strncmp(line, "include", 7) == 0 && isspace(line[7])) { + cp = skip_over_blanks(line + 7); + strip_line(cp); + return parse_include_file(cp, state); + } + if (strncmp(line, "includedir", 10) == 0 && isspace(line[10])) { + cp = skip_over_blanks(line + 10); + strip_line(cp); + return parse_include_dir(cp, state); + } switch (state->state) { case STATE_INIT_COMMENT: if (line[0] != '[') @@ -221,29 +291,22 @@ static errcode_t parse_line(char *line, struct parse_state *state) return 0; } -errcode_t profile_parse_file(FILE *f, struct profile_node **root) +static errcode_t parse_file(FILE *f, struct parse_state *state) { #define BUF_SIZE 2048 char *bptr; errcode_t retval; - struct parse_state state; bptr = malloc (BUF_SIZE); if (!bptr) return ENOMEM; - retval = parse_init_state(&state); - if (retval) { - free (bptr); - return retval; - } while (!feof(f)) { if (fgets(bptr, BUF_SIZE, f) == NULL) break; #ifndef PROFILE_SUPPORTS_FOREIGN_NEWLINES - retval = parse_line(bptr, &state); + retval = parse_line(bptr, state); if (retval) { - profile_free_node(state.root_section); free (bptr); return retval; } @@ -286,9 +349,8 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root) /* parse_line modifies contents of p */ newp = p + strlen (p) + 1; - retval = parse_line (p, &state); + retval = parse_line (p, state); if (retval) { - profile_free_node(state.root_section); free (bptr); return retval; } @@ -298,12 +360,29 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root) } #endif } - *root = state.root_section; free (bptr); return 0; } +errcode_t profile_parse_file(FILE *f, struct profile_node **root) +{ + struct parse_state state; + errcode_t retval; + + *root = NULL; + retval = parse_init_state(&state); + if (retval) + return retval; + retval = parse_file(f, &state); + if (retval) { + profile_free_node(state.root_section); + return retval; + } + *root = state.root_section; + return 0; +} + /* * Return TRUE if the string begins or ends with whitespace */ -- cgit