/* ************************************************************* RWhois Software Copyright (c) 1994 Scott Williamson and Mark Kosters Copyright (c) 1996-2000 Network Solutions, Inc. See the file LICENSE for conditions of use and distribution. **************************************************************** */ #include "schema.h" #include "attributes.h" #include "auth_area.h" #include "client_msgs.h" #include "defines.h" #include "fileutils.h" #include "log.h" #include "misc.h" #include "strutil.h" #include "main_config.h" static int add_class_alias PROTO((char ***alias_array, int *num_aliases, char *alias)); static int verify_class PROTO((auth_area_struct *aa, class_struct *class)); static int append_class PROTO((class_struct *class, auth_area_struct *aa )); static int count_class_entries PROTO((dl_list_type *class_list, char *class_name)); /* -----------------LOCAL STATICS --------------------------*/ static dl_list_type *class_ref_list = NULL; /* -------------------- LOCAL FUNCTIONS ------------------- */ static int add_class_alias(alias_array, num_aliases, alias) char ***alias_array; int *num_aliases; char *alias; { int i; char **array = *alias_array; if (NOT_STR_EXISTS(alias)) { return FALSE; } /* check the alias list */ for (i = 0; i < *num_aliases; i++ ) { if (STR_EQ(alias, array[i]) ) { log(L_LOG_ERR, CONFIG, "attribute alias '%s' already exists for this attribute %s", alias, file_context_str()); return FALSE; } } array = xrealloc(array, (*num_aliases + 1) * sizeof(char *)); array[(*num_aliases)++] = xstrdup(alias); *alias_array = array; return TRUE; } /* verify the contents of class structure and its attributes. Check for any duplicate use of class names and class aliases across the authority area. */ static int verify_class(aa, class) auth_area_struct *aa; class_struct *class; { int i, errnum; if (!aa || !class) return FALSE; if ((errnum = examin_class_name(class->name))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class name '%s': %s", aa->name, class->name, examin_error_string(errnum)); return FALSE; } if (count_class_entries(&(aa->schema->class_list), class->name) > 1) { log(L_LOG_ERR, CONFIG, "duplicate class name '%s' found in '%s' authority area", class->name, aa->name); return FALSE; } for (i=0; inum_aliases; i++) { if ((errnum = examin_class_name(class->aliases[i]))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area '%s' class alias '%s': %s", aa->name, class->name, class->aliases[i], examin_error_string(errnum)); return FALSE; } if (count_class_entries(&(aa->schema->class_list), class->aliases[i]) > 1) { log(L_LOG_ERR, CONFIG, "duplicate class alias '%s' found in '%s' authority area", class->aliases[i], aa->name); return FALSE; } } if ((errnum = examin_class_db_dir(class->db_dir))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class '%s' data directory '%s': %s", aa->name, class->name, class->db_dir, examin_error_string(errnum)); return FALSE; } if ((errnum = examin_class_attr_file(class->attr_file))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class '%s' attribute file '%s': %s", aa->name, class->name, class->attr_file, examin_error_string(errnum)); return FALSE; } if ((errnum = examin_schema_version(class->version))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class '%s' version '%s': %s", aa->name, class->name, class->version, examin_error_string(errnum)); return FALSE; } if ( class->parse_program && *class->parse_program && (errnum = examin_class_parse_prog(class->parse_program)) ) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class '%s' parse program '%s': %s", aa->name, class->name, class->parse_program, examin_error_string(errnum)); return FALSE; } if (class->id < 0) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area '%s' class id '%d': internal error", aa->name, class->name, class->id); return FALSE; } if (!verify_attribute_list(aa, class)) { return FALSE; } return TRUE; } /* count the number of times a class name occurs in the authority area class list. Looks at the aliases as well. */ static int count_class_entries(class_list, class_name) dl_list_type *class_list; char *class_name; { int not_done; int i, count = 0; class_struct *class; dl_node_type *orig_posn; /* bad parameters */ if (!class_list || !class_name) return( 0 ); /* save the current position */ orig_posn = dl_list_get_pos(class_list); not_done = dl_list_first(class_list); while (not_done) { class = dl_list_value(class_list); if (STR_EQ(class->name, class_name)) { count++; } for (i=0; inum_aliases; i++) { if (STR_EQ(class->aliases[i], class_name)) { count++; } } not_done = dl_list_next(class_list); } /* restore the saved position */ dl_list_put_pos(class_list, orig_posn); return( count ); } /* append a valid class to the authority area class list. */ static int append_class( class, aa ) class_struct *class; auth_area_struct *aa; { dl_list_type *class_list; class_struct *tmp_class; if (!aa || !aa->schema || !class) return FALSE; /* set the id (and initialize the list, if necessary) */ class_list = &(aa->schema->class_list); if (!dl_list_last(class_list)) { class->id = 0; dl_list_default(class_list, FALSE, destroy_class_data); } else { tmp_class = dl_list_value(class_list); class->id = tmp_class->id + 1; } /* add the object to the list */ dl_list_append(class_list, class); return TRUE; } /* -------------------- PUBLIC FUNCTIONS ------------------ */ /* reads the main schema/object configuration file. Returns TRUE if successful, FALSE otherwise. */ int read_schema(aa) auth_area_struct *aa; { char line[MAX_LINE]; char tag[MAX_TEMPLATE_DESC]; char datum[MAX_TEMPLATE_DESC]; FILE *fp = NULL; class_struct *class = NULL; schema_struct *schema; int content_flag = FALSE; if ( !aa || !aa->schema_file || !aa->schema ) { log(L_LOG_ERR, CONFIG, "read_schema: null data detected"); return FALSE; } schema = aa->schema; if ((fp = fopen(aa->schema_file, "r")) == NULL) { log(L_LOG_ERR, CONFIG, "could not open schema file '%s' for auth-area '%s': %s %s", aa->schema_file, aa->name, strerror(errno), file_context_str()); return FALSE; } /* clear out the old schema, if necessary */ if (!dl_list_empty(&(schema->class_list))) { dl_list_destroy(&(schema->class_list)); } if (!dl_list_empty(&(schema->attribute_ref_list))) { dl_list_destroy(&(schema->attribute_ref_list)); } /* read in the schema objects */ class = xcalloc(1, sizeof(*class)); bzero(line, sizeof(line)); set_log_context(aa->schema_file, 0, -1); while ((readline(fp, line, MAX_LINE)) != NULL) { inc_log_context_line_num(1); /* store last record; prepare for reading the next record */ if (new_record(line)) { if (!add_class(schema, class, aa)) { destroy_class_data(class); } /* allocate the next node */ class = xcalloc(1, sizeof(*class)); content_flag = FALSE; continue; } if (parse_line(line, tag, datum)) { content_flag = TRUE; if (STR_EQ(tag, O_SCHEMA_VERSION)) { if (class->version) { log(L_LOG_WARNING, CONFIG, "version '%s' replaces previous value '%s' %s", datum, class->version, file_context_str()); free(class->version); } class->version = xstrdup(datum); } else if (STR_EQ(tag, O_NAME)) { if (class->name) { log(L_LOG_WARNING, CONFIG, "schema object name '%s' replaces previous value '%s' %s", datum, class->name, file_context_str()); free(class->name); } class->name = xstrdup(datum); } else if (STR_EQ(tag, O_CLASS_ALIAS) || STR_EQ(tag, O_COMMAND)) { add_class_alias(&(class->aliases), &(class->num_aliases), datum); } else if (STR_EQ(tag, O_ATTRIBUTEDEF)) { if (class->attr_file) { log(L_LOG_WARNING, CONFIG, "schema object attribute file '%s' replaces previous value '%s' %s", datum, class->attr_file, file_context_str()); free(class->attr_file); } if (!file_exists(datum)) { log(L_LOG_ERR, CONFIG, "attribute file '%s' is unreadable: %s %s", datum, strerror(errno), file_context_str()); destroy_class_data(class); fclose(fp); return FALSE; } class->attr_file = xstrdup(datum); } else if (STR_EQ(tag, O_DBDIR)) { if (class->db_dir) { log(L_LOG_WARNING, CONFIG, "schema object db_dir '%s' replaces previous value '%s' %s", datum, class->db_dir, file_context_str()); free(class->db_dir); } if (!directory_exists(datum)) { if (aa->type == AUTH_AREA_PRIMARY) { log(L_LOG_ERR, CONFIG, "db directory '%s' is unreadable: %s %s", datum, strerror(errno), file_context_str()); destroy_class_data(class); fclose(fp); return FALSE; } } class->db_dir = xstrdup(datum); } else if (STR_EQ(tag, O_DESCRIPTION)) { if (class->description) { log(L_LOG_WARNING, CONFIG, "schema object description '%s' replaces previous value '%s' %s", datum, class->description, file_context_str()); free(class->description); } class->description = xstrdup(datum); } else if (STR_EQ(tag, O_PARSE_PROG)) { if (class->parse_program) { log(L_LOG_WARNING, CONFIG, "schema object parse program '%s' replaces previous value '%s' %s", datum, class->parse_program, file_context_str()); free(class->parse_program); } class->parse_program = xstrdup(datum); } else { log(L_LOG_WARNING, CONFIG, "tag '%s' in '%s:%s' is unrecognized; ignoring %s", tag, aa->name, SAFE_STR(class->name, "unknown"), file_context_str()); } } } /* commit last entry */ if (!content_flag || !add_class(schema, class, aa)) { destroy_class_data(class); } fclose (fp); return TRUE; } int add_class(schema, class, aa) schema_struct *schema; class_struct *class; auth_area_struct *aa; { class_struct *tmp_class; dl_list_type *class_list = &(schema->class_list); log_context_struct local_context; /* take care of "schema_version" */ if ( !class || !class->name ) { log(L_LOG_ERR, CONFIG, "add_class: null data detected %s", file_context_str()); return FALSE; } /* set the id (and initialize the list, if necessary) */ if (!dl_list_last(class_list)) { class->id = 0; dl_list_default(class_list, FALSE, destroy_class_data); } else { tmp_class = dl_list_value(class_list); class->id = tmp_class->id + 1; } /* add the base schema attributes */ if (!add_base_schema(class, &(schema->attribute_ref_list))) { log(L_LOG_ERR, CONFIG, "could not load base schema for '%s'", class->name); return FALSE; } save_log_context(&local_context); /* read the attributes for this object */ log(L_LOG_DEBUG, CONFIG, "loading attributes for class '%s' in auth-area '%s'", class->name, aa->name); if (!read_attributes(class, &(schema->attribute_ref_list))) { log(L_LOG_ERR, CONFIG, "could not load attributes for '%s'", class->name); return FALSE; } restore_log_context(&local_context); /* add the object to the list */ dl_list_append(class_list, class); /* add to the class_ref_list */ if (!add_global_class(class, aa)) { log(L_LOG_ERR, CONFIG, "could not add '%s' to class_ref_list", class->name); return FALSE; } return TRUE; } /* add class to class_ref_list */ int add_global_class(class, aa) class_struct *class; auth_area_struct *aa; { class_ref_struct *ref; class_ref_struct *alias_ref; dl_list_type *aa_list; int i; if ( !class || !aa ) { log(L_LOG_ERR, CONFIG, "add_global_class: null data detected"); return FALSE; } /* first look for an class with same name */ ref = find_global_class_by_name(class->name); if (ref) { aa_list = &(ref->auth_area_list); if (is_duplicate_aa(aa, aa_list)) { log(L_LOG_WARNING, CONFIG, "auth_area '%s' already exists in aa_list", aa->name); return FALSE; } dl_list_append(aa_list, aa); } else /* no class is found, or NULL class_ref_list, add a new node */ { /* take care of empty list too */ if ( !class_ref_list ) { class_ref_list = xcalloc(1, sizeof(*class_ref_list)); dl_list_default(class_ref_list, TRUE, destroy_class_ref_data); } /* allocate and set the new node */ ref = xcalloc(1, sizeof(*ref)); ref->name = xstrdup(class->name); aa_list = &(ref->auth_area_list); dl_list_default(aa_list, FALSE, null_destroy_data); dl_list_append(aa_list, aa); dl_list_append(class_ref_list, ref); } /* aliases */ for (i = 0; i < class->num_aliases; i++) { alias_ref = find_global_class_by_name(class->aliases[i]); /* if we didn't find a match, we will add it to the current global attr ref */ if (!alias_ref) { add_class_alias(&(ref->aliases), &(ref->num_aliases), class->aliases[i]); } else { /* if we *did* find a match, check to see if it is a conflict (the alias may just have already been added */ if (STR_EQ(alias_ref->name, class->name)) { log(L_LOG_WARNING, CONFIG, "class alias '%s' conflicts with the previously defined '%s'class %s", class->aliases[i], alias_ref->name, file_context_str()); } } } return TRUE; } dl_list_type * get_class_list(schema) schema_struct *schema; { return(&(schema->class_list)); } dl_list_type * get_schema_attribute_ref_list(schema) schema_struct *schema; { return(&(schema->attribute_ref_list)); } class_struct * find_class_by_name(schema, name) schema_struct *schema; char *name; { dl_list_type *list; class_struct *class; int not_done; int i; if (!schema) return NULL; list = &(schema->class_list); if (dl_list_empty(list) ) { return NULL; } not_done = dl_list_first(list); while (not_done) { class = dl_list_value(list); if (STR_EQ(class->name, name)) { return(class); } /* search the aliases */ for (i = 0; i < class->num_aliases; i++) { if (STR_EQ(class->aliases[i], name)) { return(class); } } not_done = dl_list_next(list); } return NULL; } class_struct * find_class_by_id(schema, id) schema_struct *schema; int id; { dl_list_type *list; class_struct *class; int not_done; if (!schema) return NULL; list = &(schema->class_list); if (dl_list_empty(list) ) { return NULL; } not_done = dl_list_first(list); while (not_done) { class = dl_list_value(list); if (class->id == id) { return(class); } not_done = dl_list_next(list); } return NULL; } void display_class(class) class_struct *class; { if (!class) return ; printf(" schema: %s\n", SAFE_STR_NONE(class->name)); printf(" id: %d\n", class->id); printf(" description: %s\n", SAFE_STR_NONE(class->description)); printf(" version: %s\n", SAFE_STR_NONE(class->version)); printf(" db-dir: %s\n", SAFE_STR_NONE(class->db_dir)); printf(" attr-file: %s\n", SAFE_STR_NONE(class->attr_file)); printf(" parse_program: %s\n", SAFE_STR_NONE(class->parse_program)); display_attribute_list(&(class->attribute_list)); } void display_schema(schema) schema_struct *schema; { int not_done; if (!schema) return ; not_done = dl_list_first(&(schema->class_list)); while (not_done) { display_class(dl_list_value(&(schema->class_list))); not_done = dl_list_next(&(schema->class_list)); if (not_done) { printf(" --------------------\n"); } } /* don't have to display attribute_ref_list */ } /* search class_ref_list */ class_ref_struct * find_global_class_by_name(name) char *name; { int not_done; int i; class_ref_struct *val; if ( !name || !class_ref_list ) { return NULL; } not_done = dl_list_first(class_ref_list); while (not_done) { val = dl_list_value(class_ref_list); if (STR_EQ(val->name, name)) { return(val); } for (i = 0; i < val->num_aliases; i++) { if (STR_EQ(val->aliases[i], name)) { return(val); } } not_done = dl_list_next(class_ref_list); } return NULL; } /* ---------------- Destructor Components ------------- */ int destroy_class_data(class) class_struct *class; { int i; if (!class) return TRUE; if (class->name) { free(class->name); } if (class->description) { free(class->description); } if (class->db_dir) { free(class->db_dir); } if (class->attr_file) { free(class->attr_file); } if (class->parse_program) { free(class->parse_program); } if (class->version) { free(class->version); } for (i = 0; i < class->num_aliases; i++) { if (class->aliases[i]) { free(class->aliases[i]); } } if (class->aliases) { free(class->aliases); } dl_list_destroy(&(class->attribute_list)); free(class); return TRUE; } int destroy_schema_data(schema) schema_struct *schema; { if (!schema) return TRUE; dl_list_destroy(&(schema->class_list)); dl_list_destroy(&(schema->attribute_ref_list)); free(schema); return TRUE; } /* destroy_class_ref_data: */ int destroy_class_ref_data( class_ref ) class_ref_struct *class_ref; { int i; if (!class_ref) return TRUE; if (class_ref->name) { free(class_ref->name); } for( i = 0; i < class_ref->num_aliases; i++) { if (class_ref->aliases[i]) { free(class_ref->aliases[i]); } } if (class_ref->aliases) { free(class_ref->aliases); } dl_list_destroy(&(class_ref->auth_area_list)); free(class_ref); return TRUE; } int destroy_class_ref_list() { dl_list_destroy(class_ref_list); class_ref_list = NULL; return TRUE; } /* write authority area schema file, and class attributes. Add the file names to 'paths_list' if created on disk. */ int write_schema_file(file, suffix, aa, paths_list) char *file; char *suffix; auth_area_struct *aa; dl_list_type *paths_list; { int i; int not_done; FILE *fp; schema_struct *schema; class_struct *class; dl_list_type *class_list; char new_file[MAX_FILE]; if (!aa || !file || !*file || !paths_list) return FALSE; /* check if secondary auth-area */ if (aa->type == AUTH_AREA_SECONDARY) { return TRUE; } schema = aa->schema; class_list = &schema->class_list; /* write the schema file */ bzero(new_file, sizeof(new_file)); strncpy(new_file, file, sizeof(new_file)-1); strncat(new_file, suffix, sizeof(new_file)-1); if ((fp = open_file_to_write(new_file, 60, paths_list)) == NULL) { log(L_LOG_ERR, CONFIG, "could not create schema file '%s': %s", new_file, strerror(errno)); return FALSE; } not_done = dl_list_first(class_list); while (not_done) { class = dl_list_value(class_list); /* write class info to schema file */ fprintf(fp, "%s: %s\n", O_NAME, SAFE_STR(class->name, "")); for (i = 0; i < class->num_aliases; i++) { fprintf(fp, "%s: %s\n", O_CLASS_ALIAS, SAFE_STR(class->aliases[i], "")); } if (class->description && *class->description) { fprintf(fp, "%s: %s\n", O_DESCRIPTION, SAFE_STR(class->description, "")); } fprintf(fp, "%s: %s\n", O_DBDIR, SAFE_STR(class->db_dir, "")); fprintf(fp, "%s: %s\n", O_ATTRIBUTEDEF, SAFE_STR(class->attr_file, "")); if (class->parse_program && *class->parse_program) { fprintf(fp, "%s: %s\n", O_PARSE_PROG, SAFE_STR(class->parse_program, "")); } if (class->version && *class->version) { fprintf(fp, "%s: %s\n", O_SCHEMA_VERSION, SAFE_STR(class->version, "")); } /* write class template in attribute def directory */ if (!write_class_attributes(class->attr_file, suffix, class, paths_list)) { log(L_LOG_ERR, CONFIG, "error writing attribute definitions file '%s' for '%s:%s' class", class->attr_file, aa->name, class->name); release_file_lock(new_file, fp); dl_list_append(paths_list, xstrdup(new_file)); return FALSE; } not_done = dl_list_next(class_list); if (not_done) { fprintf(fp, "-----\n"); } } release_file_lock(new_file, fp); dl_list_append(paths_list, xstrdup(new_file)); return TRUE; } /* examine the validity of schema version string. Returns non-zero value on failure */ int examin_schema_version(version) char *version; { int ret; if ((ret = examin_timestamp(version))) return( ret ); return( 0 ); } /* examine the validity of class name string. Returns non-zero value on failure */ int examin_class_name(name) char *name; { if (NOT_STR_EXISTS(name)) return ERW_EMTYSTR; if (!is_id_str(name)) return ERW_IDSTR; return( 0 ); } /* examine the validity of class data directory. Returns non-zero value on failure */ int examin_class_db_dir(path) char *path; { int ret; if (NOT_STR_EXISTS(path)) return ERW_EMTYSTR; if ((ret = examin_directory_name(path))) return( ret ); if (!path_under_root_dir(path, get_root_dir())) return ERW_UNDROOT; return( 0 ); } /* examine the validity of attribute file name. Also checks if the file name is under the root directory. Returns non-zero value on failure. */ int examin_class_attr_file(path) char *path; { int ret; if (NOT_STR_EXISTS(path)) return ERW_EMTYSTR; if ((ret = examin_file_name(path))) return( ret ); if (!path_under_root_dir(path, get_root_dir())) return ERW_UNDROOT; return( 0 ); } /* examine the validity of class parse program. If not found at the given path search in the bin-path of the server. Also checks if the program is an executable file on disk. Returns non-zero value on failure. */ int examin_class_parse_prog(path) char *path; { int ret = 0; char new_path[MAX_FILE]; if (!path) return ERW_NDEF; if (!*path) return ERW_EMTYSTR; if (is_rel_path(path)) { ret = examin_executable_name(path); if (ret) { bzero(new_path, sizeof(new_path)); strncpy(new_path, get_bin_path(), sizeof(new_path)-1); strncat(new_path, "/", sizeof(new_path)-1); strncat(new_path, path, sizeof(new_path)-1); ret = examin_executable_name(new_path); } } else { ret = examin_executable_name(new_path); } return( ret ); } /* verify the authority area schema. Makes sure atleast one class is defined in the schema. */ int verify_schema(aa) auth_area_struct *aa; { int not_done; class_struct *class; schema_struct *schema = aa->schema; dl_list_type *class_list = &schema->class_list; if (!aa) return FALSE; if (dl_list_empty(class_list)) { log(L_LOG_ERR, CONFIG, "'%s' authority area does not have any classes defined", aa->name); return FALSE; } not_done = dl_list_first(class_list); while (not_done) { class = dl_list_value(class_list); if (!verify_class(aa, class)) { return FALSE; } not_done = dl_list_next(class_list); } return TRUE; } /* creates a new class using user-defined information or defaults, then appends the created class to the class list of authority area. */ int create_class(class, aa) class_struct *class; auth_area_struct *aa; { int not_done; int i; int errnum; char aa_dir[MAX_FILE]; class_struct *newclass; char buffer[MAX_LINE]; attribute_struct *attr = NULL; if (!class || !class->name || !aa || !aa->schema) return FALSE; /* check if all required fields are initialized and valid */ if ((errnum = examin_class_name(class->name))) { log(L_LOG_ERR, CONFIG, "invalid '%s' authority area class name '%s': %s", aa->name, class->name, examin_error_string(errnum)); return FALSE; } if (find_class_by_name(aa->schema, class->name)) { log(L_LOG_ERR, CONFIG, "'%s' class already exists in '%s' authority area", class->name, aa->name); return FALSE; } /* get the authority area directory */ if (!check_aa_syntax(aa->name, aa_dir)) return FALSE; newclass = xcalloc(1, sizeof(*class)); newclass->name = xstrdup(class->name); /* add class aliases */ for (i = 0; i < class->num_aliases; i++) { if (!add_new_class_alias(aa, newclass, class->aliases[i])) { destroy_class_data(newclass); return FALSE; } } if (class->version && *(class->version)) { newclass->version = xstrdup(class->version); } else { newclass->version = xstrdup(make_timestamp()); } if (class->attr_file && *(class->attr_file)) { newclass->attr_file = xstrdup(class->attr_file); } else { bzero(buffer, sizeof(buffer)); strncpy(buffer, aa_dir, sizeof(buffer)-1); strncat(buffer, "/attribute_defs/", sizeof(buffer)-1); strncat(buffer, class->name, sizeof(buffer)-1); strncat(buffer, ".tmpl", sizeof(buffer)-1); newclass->attr_file = xstrdup(buffer); } if (class->db_dir && *(class->db_dir)) { newclass->db_dir = xstrdup(class->db_dir); } else { bzero(buffer, sizeof(buffer)); strncpy(buffer, aa_dir, sizeof(buffer)-1); strncat(buffer, "/data/", sizeof(buffer)-1); strncat(buffer, class->name, sizeof(buffer)-1); newclass->db_dir = xstrdup(buffer); } /* assign optional fields */ if (class->description && *(class->description)) { newclass->description = xstrdup(class->description); } if (class->parse_program && *(class->parse_program)) { newclass->parse_program = xstrdup(class->parse_program); } /* add base schema attributes to this class */ if (!add_base_schema(newclass, NULL)) { destroy_class_data(newclass); return FALSE; } /* add other attribs if specified */ if (!dl_list_empty(&class->attribute_list)) { not_done = dl_list_first(&class->attribute_list); while (not_done) { attr = dl_list_value(&class->attribute_list); if (!create_attribute_def(attr, newclass, aa)) { destroy_class_data(newclass); return FALSE; } } } /* commit class */ if (!append_class( newclass, aa )) { destroy_class_data(newclass); return FALSE; } return TRUE; } /* sets a new class schema version */ int update_schema_version(class) class_struct *class; { char *tmp_ver; if (!class) return FALSE; if (class->version) { tmp_ver = xstrdup(get_updated_timestamp(class->version)); free(class->version); class->version = tmp_ver; } return TRUE; } /* add a new class after making sure the name does not clash with any other class name or class alias. */ int add_new_class_alias(aa, class, alias) auth_area_struct *aa; class_struct *class; char *alias; { /* bad parameters */ if (!aa || !class || !alias || !*alias) return FALSE; /* check to make sure we are not adding duplicate attribute names */ if (find_class_by_name(aa->schema, alias)) { log(L_LOG_ERR, CONFIG, "class alias name '%s' already used in '%s' authority area", alias, aa->name); return FALSE; } return( add_class_alias(&(class->aliases), &(class->num_aliases), alias) ); } /* add class file names and directories to 'paths_list' if not in the list. Log error if path already in the list. Returns non-zero value on failure. */ int verify_all_class_paths(paths_list, aa) dl_list_type *paths_list; auth_area_struct *aa; { int ret = 0; int not_done; dl_list_type *class_list; class_struct *class; char buffer[MAX_LINE]; if (!paths_list || !aa) return( 1 ); class_list = &(aa->schema->class_list); not_done = dl_list_first(class_list); while (not_done) { class = dl_list_value(class_list); bzero(buffer, sizeof(buffer)); strncpy(buffer, aa->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, class->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, O_DBDIR, sizeof(buffer)-1); ret += dup_config_path_name(paths_list, class->db_dir, buffer); bzero(buffer, sizeof(buffer)); strncpy(buffer, aa->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, class->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, O_ATTRIBUTEDEF, sizeof(buffer)-1); ret += dup_config_path_name(paths_list, class->attr_file, buffer); not_done = dl_list_next(class_list); } return( ret ); } /* make sure the class parse program names are not used in the configuration. Don't want to overwrite something not written out by admin server. */ int verify_class_parse_progs(paths_list, aa) dl_list_type *paths_list; auth_area_struct *aa; { int ret = 0; int not_done; dl_list_type *class_list; class_struct *class; char buffer[MAX_LINE]; if (!paths_list || !aa) return( 1 ); class_list = &(aa->schema->class_list); not_done = dl_list_first(class_list); while (not_done) { class = dl_list_value(class_list); bzero(buffer, sizeof(buffer)); strncpy(buffer, aa->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, class->name, sizeof(buffer)-1); strncat(buffer, ":", sizeof(buffer)-1); strncat(buffer, O_PARSE_PROG, sizeof(buffer)-1); ret += in_config_path_list(paths_list, class->parse_program, buffer); not_done = dl_list_next(class_list); } return( ret ); }