int
checkfullmapname(const char *mapname, const char *domainname,
__nis_table_mapping_t **table_mapping,
__nis_table_mapping_t **found_map)
{
	char *map;

	*found_map = NULL;

	/* This function does not alter mapname */

	if (!mapname || !domainname || *table_mapping == NULL)
		return (-1);

	if (strchr(mapname, COMMA_CHAR))
		return (2);

	if ((map = s_strndup(mapname, strlen(mapname))) == 0)
		return (-1);

	if (getfullmapname(&map, domainname)) {
		free(map);
		return (-1);
	}

	*found_map = find_table_mapping(map, strlen(map), *table_mapping);
	if (*found_map) {
		free(map);
		return (1);
	}

	free(map);
	return (0);
}
Beispiel #2
0
void check_add_file(char *filename, bool given)
{
	const char *bn;

	if (filename == NULL || *filename == '\0')
		return;

	if (access(filename, R_OK) < 0) {
		if (given)
			warn("could not open file: %s", filename);
		return;
	}

	if (fileidx == filecnt) {
		filecnt *= 2;
		files = s_realloc(files, filecnt * sizeof(*files));
		memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files));
	}

#if defined _BSD_SOURCE || defined _XOPEN_SOURCE && \
    ((_XOPEN_SOURCE - 0) >= 500 || defined _XOPEN_SOURCE_EXTENDED)

	if ((files[fileidx].path = realpath(filename, NULL)) == NULL) {
		warn("could not get real path of file: %s\n", filename);
		return;
	}
#else
	if (*filename != '/') {
		if ((files[fileidx].path = absolute_path(filename)) == NULL) {
			warn("could not get absolute path of file: %s\n", filename);
			return;
		}
	} else {
		files[fileidx].path = NULL;
	}
#endif

	files[fileidx].name = s_strdup(filename);
	if (files[fileidx].path == NULL)
		files[fileidx].path = files[fileidx].name;
	if ((bn = strrchr(files[fileidx].name , '/')) != NULL && bn[1] != '\0')
		files[fileidx].base = ++bn;
	else
		files[fileidx].base = files[fileidx].name;
	if (given)
		files[fileidx].flags |= FF_WARN;
	files[fileidx].dir = s_strndup(files[fileidx].path, strlen(files[fileidx].path)-strlen(files[fileidx].base));
	fileidx++;
}
Beispiel #3
0
static ztrie_node_t *
s_ztrie_matches_token (ztrie_node_t *parent, char *token, int len)
{
    char firstbyte = *token;
    ztrie_node_t *child = (ztrie_node_t *) zlistx_first (parent->children);
    while (child) {
        if (child->token_type == NODE_TYPE_STRING) {
            if (firstbyte == *child->token  //  This achieves a small performance boost
                && child->token_len == len
                && strncmp (child->token, token, MIN_LEN (child->token_len, len)) == 0)
                    return child;
        }
        else
        if (child->token_type == NODE_TYPE_ASTERISK) {
            child->asterisk_match = strdup (token);
            return child;
        }
        else {
            //  Need to copy token as zrex_matches expects '\0' terminated string
            char *token_term = s_strndup (token, len);
            if (zrex_matches (child->regex, token_term)) {
                if (child->token_type == NODE_TYPE_PARAM) {
                    //  One hit means no capturing group was defined
                    //  More than one hit indicates that at least on capturing group.
                    //  In this case only the values of the capturing groups are considered.
                    if (zrex_hits (child->regex) == 1)
                        s_ztrie_node_update_param (child, 1, zrex_hit (child->regex, 0));
                    else
                    if (zrex_hits (child->regex) > 1) {
                        int index;
                        for (index = 1; index < zrex_hits (child->regex); index++)
                            s_ztrie_node_update_param (child, index, zrex_hit (child->regex, index));
                    }
                }
                free (token_term);
                return child;
            }
            free (token_term);
        }
        child = (ztrie_node_t *) zlistx_next (parent->children);
    }
    return NULL;
}
Beispiel #4
0
static ztrie_node_t *
s_ztrie_node_new (ztrie_node_t *parent, char *token, int token_len, zlistx_t *param_keys, int token_type)
{
    ztrie_node_t *self = (ztrie_node_t *) zmalloc (sizeof (ztrie_node_t));
    assert (self);

    //  Initialize properties
    self->token = s_strndup (token, token_len);
    self->token_type = token_type;
    self->token_len = token_len;
    self->endpoint = false;
    self->parameter_count = 0;
    self->parameter_names = NULL;
    self->parameter_values = NULL;
    if (param_keys && zlistx_size (param_keys) > 0) {
        self->parameter_count = zlistx_size (param_keys);
        self->parameter_names = (char **) malloc (sizeof (char *) * self->parameter_count);
        self->parameter_values = (char **) malloc (sizeof (char *) * self->parameter_count);
        char *key = (char *) zlistx_first (param_keys);
        int index;
        for (index = 0; index < zlistx_size (param_keys); index++) {
            self->parameter_names [index] = key;
            self->parameter_values [index] = NULL;
            key = (char *) zlistx_next (param_keys);
        }
    }
    if (self->token_type == NODE_TYPE_REGEX || self->token_type == NODE_TYPE_PARAM)
        self->regex = zrex_new (self->token);
    self->data = NULL;
    //  Initialize relationships
    self->parent = parent;
    if (self->parent) {
        zlistx_add_end (self->parent->children, self);
        //  Sort regexes to the end to avoid conlficts
        zlistx_sort (self->parent->children);
    }
    size_t parent_path_len = self->parent? self->parent->path_len: 0;
    self->path_len = parent_path_len + strlen (self->token) + 1; // +1 path delimiter
    self->children = zlistx_new ();
    zlistx_set_comparator (self->children, s_ztrie_node_compare);

    return self;
}
__nis_table_mapping_t *
new_merged_mapping(const char *match,
	__nis_table_mapping_t	*intbl)
{

	__nis_table_mapping_t	*outtable = NULL;

	outtable = (__nis_table_mapping_t *)
		s_calloc(1, sizeof (__nis_table_mapping_t));
	if (outtable == NULL)
		return (NULL);
	initialize_table_mapping(outtable);
	outtable->dbId = s_strndup(match, strlen(match));
	if (outtable->dbId == NULL) {
		free_table_mapping(outtable);
		outtable = NULL;
		return (NULL);
	}
	if (merge_table_mapping(intbl, outtable)) {
		free_table_mapping(outtable);
		outtable = NULL;
	}
	return (outtable);
}
Beispiel #6
0
static ztrie_node_t *
s_ztrie_parse_path (ztrie_t *self, const char *path, int mode)
{
    int state = 0;
    char *needle, *beginToken = NULL, *beginRegex = NULL;
    ztrie_node_t *parent = self->root;
    if (zlistx_size (self->params) > 0)
        zlistx_purge (self->params);

    int len = strlen (path);
    needle = (char *) path;
    char *needle_stop = needle + len;
    //  Ignore trailing delimiter
    if (needle[len-1] == self->delimiter)
        needle_stop -= 1;
    while (needle < needle_stop + 1) {
        //  It is valid not to have an delimiter at the end of the path
        if (*needle == self->delimiter || needle == needle_stop) {
            //  Token starts with delimiter ignore everything that comes before
            if (state == 0) {
                beginToken = needle + 1;
                state++;
                if (mode == MODE_INSERT || mode == MODE_LOOKUP)
                    // Increment so regexes are parsed which is only relevant
                    // during INSERT or LOOKUP. Using different states gives a small
                    // performance boost for matching.
                    state++;
            }
            //  Token ends with delimiter.
            else
            if (state < 3) {
                int matchType = zlistx_size (self->params) > 0? NODE_TYPE_PARAM:
                                    beginRegex? NODE_TYPE_REGEX: NODE_TYPE_STRING;
                char *matchToken = beginRegex? beginRegex: beginToken;
                int matchTokenLen = needle - matchToken - (beginRegex? 1: 0);
                //  Illegal token
                if (matchTokenLen == 0)
                    return NULL;
                ztrie_node_t *match = NULL;
                //  Asterisk nodes are only allowed at the end of a route
                if (needle == needle_stop && *matchToken == '*') {
                    if (zlistx_size (parent->children) == 0) {
                        matchType = NODE_TYPE_ASTERISK;
                        matchToken = needle - 1;
                        matchTokenLen = 1;
                    }
                    //  Asterisk must be a leaf in the tree
                    else
                        return NULL;
                }
                else {
                    matchType = zlistx_size (self->params) > 0? NODE_TYPE_PARAM:
                                        beginRegex? NODE_TYPE_REGEX: NODE_TYPE_STRING;
                    matchToken = beginRegex? beginRegex: beginToken;
                    matchTokenLen = needle - matchToken - (beginRegex? 1: 0);
                }

                //  In insert and lookup mode only do a string comparison
                if (mode == MODE_INSERT || mode == MODE_LOOKUP)
                    match = s_ztrie_compare_token (parent, matchToken, matchTokenLen);
                else
                //  Otherwise evaluate regexes
                if (mode == MODE_MATCH)
                    match = s_ztrie_matches_token (parent, matchToken, matchTokenLen);

                //  Mismatch behavior depends on mode
                if (!match) {
                    //  Append to common prefix
                    if (mode == MODE_INSERT) {
                        //  It's not allowed to append on asterisk
                        if (parent->token_type == NODE_TYPE_ASTERISK ||
                                (zlistx_size (parent->children) == 1 &&
                                ((ztrie_node_t *) (zlistx_first (parent->children)))->token_type == NODE_TYPE_ASTERISK))
                            return NULL;
                        parent = s_ztrie_node_new (parent, matchToken, matchTokenLen, self->params, matchType);
                    }
                    else
                    //  No match for path found
                    if (mode == MODE_MATCH || mode == MODE_LOOKUP)
                        return NULL;
                }
                //  If a match has been found it becomes the parent for next path token
                else {
                    parent = match;
                    //  In case a asterisk match has been made skip the rest of the route
                    if (parent->token_type == NODE_TYPE_ASTERISK)
                        break;
                }
                //  Cleanup for next token
                beginRegex = NULL;
                if (zlistx_size (self->params) > 0)
                    zlistx_purge (self->params);
                //  Token end equals token begin
                beginToken = needle + 1;
            }
        }
        else
        //  regex starts with '{'
        if (state == 2 && *needle == '{') {
            beginRegex = needle + 1;
            state++;
        }
        else
        //  in the middle of the regex. Found a named regex.
        if (state == 3 && (*needle == ':')) {
            zlistx_add_end (self->params, s_strndup (beginRegex, needle - beginRegex));
            beginRegex = needle + 1;

        }
        else
        // regex ends with {
        if (state == 3 && *needle == '}') {
            state--;
        }
        needle++;
    }

    //  In matching mode the discovered node must be an endpoint
    if (parent && mode == MODE_MATCH && !parent->endpoint)
        return NULL;

    return parent;
}
/*
 * FUNCTION:	final_parser_pass
 *
 * completes the final expansion of t_map structures linked list.
 * all structures will have a non-null objPath as well as a objName
 * in the form of "mapname . domainname ." or "splitfieldname .
 * domainname .".
 *
 * RETURN VALUE:	0 on success, -1 on failure, -2 on fatal error.
 */
int
final_parser_pass(
	__nis_table_mapping_t   **table_mapping,
	__yp_domain_context_t   *ypDomains)
{
	__nis_table_mapping_t   *t;
	__nis_table_mapping_t	*t1, *returned_map;
	__nis_table_mapping_t   *prev = NULL;
	int			i;
	char			*myself = "final_parser_pass";
	int			nm;
	bool_t			r;
	int			del_tbl_flag = 0;

	if (ypDomains) {
		if (!ypDomains->numDomains) {
			p_error = parse_internal_error;
			logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"%s:No domains specified.", myself);
			return (-1);
		}
	} else {
		p_error = parse_internal_error;
		logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"%s:No domain structure supplied.", myself);
		return (-1);
	}
	prev = NULL;

	for (t = *table_mapping; t != NULL; ) {

		/* Delete if marked for deletion by second_parser_pass */
		if (t->isMaster == 1) {
			if (prev != NULL)
				prev->next = t->next;
			else
				*table_mapping = t->next;
			t1 = t;
			t = t->next;
			free_table_mapping(t1);
			continue;
		}

		if (!t->objName && t->dbId) {
			t->objName = s_strndup(t->dbId, strlen(t->dbId));
			if (!t->objName) {
				logmsg(MSG_NOMEM, LOG_ERR,
					"%s:Could not allocate.", myself);
				return (-1);
			}
		}
		i = ypDomains->numDomains;
		while (i > 0) {
			if (i == 1) {
			/* modify existing table_mapping's */
				nm = checkfullmapname(t->dbId,
					ypDomains->domainLabels[0],
					table_mapping, &returned_map);
				if (nm == 1) {
					/* delete this mapping structure */
					logmsg(MSG_NOTIMECHECK,
						LOG_WARNING,
						"Mapping structure %s,%s "
						"already exists.",
						t->dbId,
						ypDomains->domainLabels[0]);
					if (merge_table_mapping(t,
						returned_map)) {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
						    "Error merging information "
						    "from the %s to the %s "
						    "mapping structure.",
						t->dbId, returned_map->dbId);
						return (-1);
					}
					if (del_tbl_flag == 0)
						del_tbl_flag = 1;
				} else if (nm == -1) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
			"Error searching for %s,%s structure",
					t->dbId, ypDomains->domainLabels[0]);
					return (-1);
				} else if (nm == 0 || nm == 2) {
					if ((append_domainContext(&t,
					ypDomains->domainLabels[0],
					ypDomains->domains[0])) != 0) {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
					"Error appending domainContext %s",
						ypDomains->domainLabels[0]);
						return (-1);
					}
					del_tbl_flag = 0;
				}
			} else { /* if (i > 1) */
				/* need to create new table_mapping's */
				nm = checkfullmapname(t->dbId,
					ypDomains->domainLabels[i - 1],
					table_mapping, &returned_map);
				if (nm == -1) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"Error searching for %s,%s structure",
				t->dbId, ypDomains->domainLabels[i - 1]);
					return (-1);
				} else if (nm == 0) {
					t1 = new_merged_mapping(t->dbId, t);
					/* we clone ourselves */
					if (t1) {
						if ((append_domainContext(&t1,
					ypDomains->domainLabels[i - 1],
					ypDomains->domains[i - 1])) != 0) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
					"Error appending domainContext %s",
					ypDomains->domainLabels[i - 1]);
							free(t1);
							return (-1);
						}
						if (prev != NULL) {
							t1->next = prev->next;
							prev->next = t1;
							prev = prev->next;
						} else {
							t1->next =
								*table_mapping;
							*table_mapping = t1;
							prev = t1;
						}
					} else { /* if !t1 */
						p_error = parse_internal_error;
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
					"%s:Could not create new table -"
					" check all instances of %s for errors",
						myself, t->dbId);
						return (-1);
					}
				} else if (nm == 1) {
					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
				"Mapping structure %s,%s already exists.",
						t->dbId,
						ypDomains->domainLabels[i - 1]);
					/*
					 * We should be deleting this, but can't
					 * really do it here, because we need to
					 * match with the domainLabels[0] case
					 * too. So we will just flag it for now.
					 */
					if (merge_table_mapping(t,
						returned_map)) {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
	"Error merging information from the %s to the %s mapping structure.",
							t->dbId,
							returned_map->dbId);
						return (-1);
					}
					del_tbl_flag = 1;
				} else if (nm == 2) {
					if ((append_domainContext(&t,
						ypDomains->domainLabels[i - 1],
						ypDomains->domains[i - 1]))
						!= 0) {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
					"Error appending domainContext %s",
						ypDomains->domainLabels[i - 1]);
						return (-1);
					}
				} /* end of "if (nm == 0)" */
			} /* end of else if (i > 1) */


			/*
			 * 'merge_table_mapping' only copies unexpanded
			 * objectDN values into returned_map. Hence,
			 * read.base and write.base in returned_map
			 * needs to be expanded.
			 */
			if (nm == 1 && returned_map && returned_map->objectDN) {
				r = make_fqdn(
					returned_map->objectDN,
					ypDomains->domains[i - 1]);
				if (r == TRUE &&
					returned_map->objectDN->write.base) {
					r = make_full_dn(
					&returned_map->objectDN->write.base,
					ypDomains->domains[i - 1]);
				}

				if (r == FALSE) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
						"Error appending domainContext "
						"%s to %s",
						ypDomains->domainLabels[i - 1],
						returned_map->dbId);
					return (-2);
				}
			}
			i--;
		} /* end of while i > 0 loop */

		if (del_tbl_flag == 1) {
			if (prev != NULL) {
				prev->next = t->next;
				free_table_mapping(t);
				t = prev->next;
			} else {
				*table_mapping = t->next;
				free_table_mapping(t);
				t = *table_mapping;
			}
			del_tbl_flag = 0;
		} else {
			prev = t;
			t = t->next;
		}
	} /* end of table mapping loop */

	for (t = *table_mapping; t != NULL; t = t->next) {
		if (!t->dbId) {
			logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"%s:Fatal error: structure with no dbId found.",
				myself);
				return (-2);
		}
		append_dot(&t->dbId);
		if (!t->objectDN) {
			p_error = parse_internal_error;
			logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"%s:No objectDN for %s.", myself, t->dbId);
			return (-1);
		}
	}

	return (0);
}
/*
 * FUNCTION:	second_parser_pass
 *
 * Prepares the linked list of table_mappings for processing
 * by finish_parse(), adding, merging and deleting structures
 * as necessary. Also adds dummy objectDN info. for splitField's.
 *
 * RETURN VALUE: 0 on success, > 0 on failure.
 */
int
second_parser_pass(
	__nis_table_mapping_t   **table_mapping)
{
	__nis_table_mapping_t   *t, *t2;
	__nis_table_mapping_t   *t_new = NULL, *tg;
	__nis_table_mapping_t	*prev = NULL;
	__nis_object_dn_t   *objectDN;
	char	*objs, *dom;
	char	*objName = NULL;
	char	*lasts;
	char	*tobj, *alias, *dupalias, *tmp;
	char	*myself = "second_parser_pass";
	int	i = 0, len;
	int	remove_t = 0;
	int	add_t = 0;

	prev = NULL;
	for (t = *table_mapping; t != NULL; ) {
		/*
		 * Temporarily using this field to flag deletion.
		 * 0 : don't delete
		 * 1 : delete
		 * The mapping structure will be deleted in final_parser_pass
		 */
		t->isMaster = 0;

		if (!t->dbId) {
			p_error = parse_bad_map_error;
			logmsg(MSG_NOTIMECHECK, LOG_ERR,
			"%s: no dbId field", myself);
			return (1);
		}
		tg = NULL;
		dom = strchr(t->dbId, COMMA_CHAR);
		if (t->objName != NULL) {
			objName = strdup(t->objName);
			if (objName == NULL) {
				p_error = parse_no_mem_error;
				logmsg(MSG_NOMEM, LOG_ERR,
		"%s: Cannot allocate memory for objName", myself);
				return (1);
			}
			objs = (char *)strtok_r(objName, " ", &lasts);
			/* Get the generic mapping */
			if (dom != NULL) {
				tg = find_table_mapping(t->dbId, dom - t->dbId,
								*table_mapping);
			}
		} else {
			objs = NULL;
			if (dom == NULL) {
				t->objName = s_strndup(t->dbId,
						strlen(t->dbId));
				if (!t->objName) {
					logmsg(MSG_NOMEM, LOG_ERR,
"%s: Cannot allocate memory for t->objName",
						myself);
					objs = NULL;
					return (2);
				}
			} else {
				/* Force relationship for domain specific */

				/* Get the generic mapping */
				tg = find_table_mapping(t->dbId, dom - t->dbId,
								*table_mapping);
				if (tg == NULL || tg->objName == NULL) {
					/* If not found, use dbId for objName */
					t->objName = s_strndup(t->dbId,
							strlen(t->dbId));
					if (t->objName == NULL) {
						logmsg(MSG_NOMEM, LOG_ERR,
"%s: Cannot allocate memory for t->objName",
							myself);
						return (2);
					}
				} else {
					dom++;
					tobj = s_strndup(tg->objName,
							strlen(tg->objName));
					if (tobj == NULL) {
						logmsg(MSG_NOMEM, LOG_ERR,
"%s: Cannot allocate memory for t->objName",
							myself);
						return (2);
					}
					alias = (char *)strtok_r(tobj, " ",
									&lasts);

					/* Loop 'breaks' on errors */
					while (alias) {
						tmp = NULL;
						dupalias = s_strndup(alias,
								strlen(alias));
						if (!dupalias)
							break;
						if (getfullmapname(&dupalias,
								dom)) {
							i = 1;
							break;
						}
						if (t->objName == NULL)
							t->objName = dupalias;
						else {
							len = strlen(t->objName)
							+ strlen(dupalias) + 2;
							tmp = s_calloc(1, len);
							if (tmp == NULL)
								break;
							snprintf(tmp, len,
								"%s %s",
								t->objName,
								dupalias);
							free(dupalias);
							dupalias = NULL;
							free(t->objName);
							t->objName = tmp;
						}
						alias = (char *)strtok_r(NULL,
								" ", &lasts);
					}

					if (tobj)
						free(tobj);

					if (alias ||
						(objName = s_strdup(t->objName))
								== NULL) {
						if (i)
							logmsg(MSG_NOTIMECHECK,
							LOG_ERR,
"%s: getfullmapname failed for %s for domain \"%s\"",
							myself, dupalias, dom);
						else {
							p_error =
							parse_no_mem_error;
							logmsg(MSG_NOMEM,
							LOG_ERR,
"%s: Cannot allocate memory",
							myself);
						}
						if (dupalias)
							free(dupalias);
						if (t->objName)
							free(t->objName);
						return (2);

					}
					objs = (char *)strtok_r(objName, " ",
								&lasts);
				}
			}
		}

		if (tg != NULL) {
			if (merge_table_mapping(tg, t)) {
				logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Error merging information from the %s to the %s mapping structure",
					tg->dbId, t->dbId);
				objs = NULL;
				if (objName)
					free(objName);
				return (1);
			}
		}

		/*
		 * If objName is "map1 map2" then do the second pass.
		 * If it is just "map1" however skip the expansion.
		 * Also skip it if t->objName is null.
		 */
		if (objs && strncasecmp(objs, t->objName,
			strlen(t->objName))) {
			t2 = find_table_mapping(objs, strlen(objs),
							*table_mapping);
			if (t2) {
				if (merge_table_mapping(t, t2)) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Error merging information from the %s to the %s mapping structure",
						t->dbId, t2->dbId);
					objs = NULL;
					if (objName)
						free(objName);
					return (1);
				}
				t->isMaster = 1;
			} else {
				t_new = new_merged_mapping(objs, t);
				if (t_new) {
					t->isMaster = 1;
					if (prev != NULL)
						prev->next = t_new;
					else
						*table_mapping = t_new;
					prev = t_new;
					prev->next = t;
				} else {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Error creating a new mapping structure %s",
						objs);
					objs = NULL;
					if (objName)
						free(objName);
					return (1);
				}
			}
			while ((objs = (char *)strtok_r(NULL, " ", &lasts))
				!= NULL) {
				t2 = find_table_mapping(objs, strlen(objs),
								*table_mapping);
				if (t2) {
					if (merge_table_mapping(t, t2)) {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Error merging information from the %s to the %s mapping structure",
							t->dbId, t2->dbId);
						objs = NULL;
						if (objName)
							free(objName);
						return (1);
					}
					t->isMaster = 1;
				} else {
					/*
					 * create a new t_map with dbId = objs
					 * and copy t->* into new t_map
					 */
					t_new = new_merged_mapping(objs, t);
					if (t_new) {
						t->isMaster = 1;
						if (prev != NULL)
							prev->next = t_new;
						else
							*table_mapping = t_new;
						prev = t_new;
						prev->next = t;
					} else {
						logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Error creating a new mapping structure %s",
							objs);
						objs = NULL;
						if (objName)
							free(objName);
						return (1);
					}
				}
			}
		} /* if objs!= NULL */

		prev = t;
		t = t->next;

		if (objName) {
			free(objName);
			objName = NULL;
			objs = NULL;
		}
	} /* for t = table_mapping loop */
	return (0);
}
static int
copy_object_dn(
	__nis_object_dn_t	*in,
	__nis_object_dn_t	*newdn)
{
	if (in == NULL) {
		p_error = parse_no_object_dn;
		return (1);
	}
	while (in != NULL) {
		if (in->read.base == NULL) {
			newdn->read.base = NULL;
		} else {
			newdn->read.base = s_strndup(
				in->read.base,
				strlen(in->read.base));
			if (newdn->read.base == NULL)
				return (2);
		}
		newdn->read.scope = in->read.scope;
		if (in->read.attrs) {
			newdn->read.attrs = s_strndup(
					in->read.attrs,
					strlen(in->read.attrs));
			if (newdn->read.attrs == NULL) {
				return (2);
			}
		} else {
			newdn->read.attrs = NULL;
		}
		newdn->read.element = in->read.element;
		if (in->write.base != NULL) {
			newdn->write.base = s_strndup(
				in->write.base,
				strlen(in->write.base));
			if (newdn->write.base == NULL)
				return (2);
		} else {
			newdn->write.base = NULL;
		}
		newdn->write.scope = in->write.scope;
		if (in->write.attrs != NULL) {
			newdn->write.attrs = s_strndup(
				in->write.attrs,
				strlen(in->write.attrs));
			if (newdn->write.attrs == NULL) {
				return (2);
			}
		} else {
			newdn->write.attrs = NULL;
		}
		newdn->write.element = in->write.element;
		if (in->dbIdName) {
			newdn->dbIdName = s_strndup(in->dbIdName,
						strlen(in->dbIdName));
			if (newdn->dbIdName == NULL)
				return (2);
		}

		if (in->delDisp)
			newdn->delDisp = in->delDisp;

		if (in->dbId && in->numDbIds > 0) {
			newdn->dbId = dup_mapping_rules(in->dbId,
					in->numDbIds);
			if (!newdn->dbId)
				return (1);
			newdn->numDbIds = in->numDbIds;
		}
		if (in->next != NULL) {
			newdn->next = (__nis_object_dn_t *)s_calloc(1,
					sizeof (__nis_object_dn_t));
			if (newdn->next == NULL)
				return (1);
			newdn = newdn->next;
			in = in->next;
		} else {
			return (0);
		}
	} /* End of while on in */

	return (0);
}
static int
merge_table_mapping(
	__nis_table_mapping_t *in,
	__nis_table_mapping_t *out)
{
	int i;
	int len;
	int orig_num_rules;
	int append;

	if (in == NULL)
		return (1);

	if (in->dbId == NULL)
		return (1);

	/*
	 * If 'in' is generic (non-expanded) and 'out' is domain-specific,
	 * then rules from 'in' should not be appended to those in 'out'.
	 */
	if (!strchr(in->dbId, COMMA_CHAR) && strchr(out->dbId, COMMA_CHAR))
		append = 0;
	else
		append = 1;


	if (!out->index.numIndexes && in->index.numIndexes > 0) {
		if (!dup_index(&in->index, &out->index))
			return (1);
	}

	/* add_column() increments numColumns, so we don't */
	if (!out->numColumns && in->numColumns > 0) {
		for (i = 0; i < in->numColumns; i++) {
			if (!add_column(out, in->column[i]))
				return (1);
		}
	}

	if (out->commentChar == DEFAULT_COMMENT_CHAR &&
		in->commentChar != DEFAULT_COMMENT_CHAR)
		out->commentChar = in->commentChar;

	if (out->usedns_flag == 0)
		out->usedns_flag = in->usedns_flag;

	if (out->securemap_flag == 0)
		out->securemap_flag = in->securemap_flag;

	if (out->separatorStr == DEFAULT_SEP_STRING &&
		in->separatorStr != DEFAULT_SEP_STRING) {
		out->separatorStr = s_strdup(in->separatorStr);
		if (!out->separatorStr)
			return (2);
	}

	if (!out->numSplits && !out->e && in->e) {
		out->numSplits = in->numSplits;
		out->e = (__nis_mapping_element_t *)
			s_calloc(1, (in->numSplits+1) *
			sizeof (__nis_mapping_element_t));
		if (!out->e)
			return (2);
		for (i = 0; i <= in->numSplits; i++) {
			if (!dup_mapping_element(&in->e[i], &out->e[i])) {
				for (; i > 0; i--) {
					free_mapping_element(&out->e[i - 1]);
				}
				out->e = NULL;
				return (1);
			}
		}
	}

	if (out->initTtlLo == (time_t)NO_VALUE_SET &&
		in->initTtlLo != (time_t)NO_VALUE_SET)
		out->initTtlLo = in->initTtlLo;

	if (out->initTtlHi == (time_t)NO_VALUE_SET &&
		in->initTtlHi != (time_t)NO_VALUE_SET)
		out->initTtlHi = in->initTtlHi;

	if (out->ttl == (time_t)NO_VALUE_SET &&
		in->ttl != (time_t)NO_VALUE_SET)
		out->ttl = in->ttl;

	if (!out->numRulesFromLDAP && in->numRulesFromLDAP) {
		out->ruleFromLDAP = dup_mapping_rules(in->ruleFromLDAP,
			in->numRulesFromLDAP);
		if (!out->ruleFromLDAP)
			return (1);
		out->numRulesFromLDAP = in->numRulesFromLDAP;
	} else if (append && out->numRulesFromLDAP && in->numRulesFromLDAP) {
		orig_num_rules = out->numRulesFromLDAP;
		for (i = 0; i < in->numRulesFromLDAP; i++) {
			if (append_mapping_rule(in->ruleFromLDAP[i], out, 0)) {
				for (i = out->numRulesFromLDAP;
					i > orig_num_rules; i--) {
					free_mapping_rule(out->ruleFromLDAP[i]);
					out->ruleFromLDAP[i] = NULL;
				}
				return (1);

			}
		}
	}

	if (!out->numRulesToLDAP && in->numRulesToLDAP) {
		out->ruleToLDAP = dup_mapping_rules(in->ruleToLDAP,
			in->numRulesToLDAP);
		if (!out->ruleToLDAP)
			return (1);
		out->numRulesToLDAP = in->numRulesToLDAP;
	} else if (append && out->numRulesToLDAP && in->numRulesToLDAP) {
		orig_num_rules = out->numRulesToLDAP;
		for (i = 0; i < in->numRulesToLDAP; i++) {
			if (append_mapping_rule(in->ruleToLDAP[i], out, 1)) {
				for (i = out->numRulesToLDAP;
					i > orig_num_rules; i--) {
					free_mapping_rule(out->ruleToLDAP[i]);
					out->ruleToLDAP[i] = NULL;
				}
				return (1);
			}
		}
	}
	if (!out->objectDN && in->objectDN) {
		out->objectDN = (__nis_object_dn_t *)
			s_calloc(1, sizeof (__nis_object_dn_t));
		if (!out->objectDN)
			return (2);
		if (copy_object_dn(in->objectDN, out->objectDN)) {
			free_object_dn(out->objectDN);
			out->objectDN = NULL;
			return (1);
		}
	}

	if (!out->objName && in->objName) {
		if (!strchr(in->objName, SPACE_CHAR)) {
		/* objName has no space- a single map dbIdMapping */
			out->objName = s_strndup(in->objName,
				strlen(in->objName));
			if (!out->objName)
				return (2);
		}
	}

	if (!out->objName && out->dbId) {
		out->objName = s_strndup(out->dbId, strlen(out->dbId));
		if (!out->objName)
			return (2);
	}

	if (out->seq_num == NO_VALUE_SET && in->seq_num >= 0)
		out->seq_num = in->seq_num;

	return (p_error == no_parse_error ? 0 : 1);
}
int
append_domainContext(__nis_table_mapping_t **table_map,
char   *DomainLabel, char *Domain)
{
	__nis_table_mapping_t *tmp_map = *table_map;
	char *lasts;
	char *tmp_dbId = NULL;
	char *id = NULL;
	int  domain_specific = 0;
	char *myself = "append_domainContext";

	if (!DomainLabel || !Domain || !tmp_map)
		return (-1);
	if (tmp_map->dbId == NULL || tmp_map->objName == NULL) {
		p_error = parse_bad_map_error;
		return (-1);
	}
	tmp_dbId = s_strndup(tmp_map->dbId, strlen(tmp_map->dbId));
	if (!tmp_dbId)
		return (-1);
	if (strchr(tmp_map->dbId, COMMA_CHAR)) {
		domain_specific = 1;
		id = (char *)strtok_r(tmp_dbId, COMMA_STRING, &lasts);
		if (id)
			id = (char *)strtok_r(NULL, COMMA_STRING, &lasts);
		else {
			free(tmp_dbId);
			return (-1);
		}
		if (!id) {
			free(tmp_dbId);
			return (-1);
		}
		if (strcasecmp(id, DomainLabel)) {
			free(tmp_dbId);
			return (0);
		}
	} else {
		if (getfullmapname(&tmp_map->dbId, DomainLabel)) {
			free(tmp_dbId);
			return (-1);
		}
		append_dot(&tmp_map->dbId);
	}
	if (tmp_dbId)
		free(tmp_dbId);
	tmp_dbId = NULL;

	if (getfullmapname(&tmp_map->objName, DomainLabel))
		return (-1);
	append_dot(&tmp_map->objName);

	/*
	 * If domain specific mapping doesn't have objectDN,
	 * then don't touch. Most probably, pass for the generic mapping
	 * will handle this by coping over it's own objectDN
	 */
	if (domain_specific && tmp_map->objectDN == NULL)
		return (0);

	if (tmp_map->objectDN == NULL) {
		/* Allocate memory to objectDN */
		tmp_map->objectDN = (__nis_object_dn_t *)
			s_calloc(1, sizeof (__nis_object_dn_t));
		if (tmp_map->objectDN == NULL) {
			logmsg(MSG_NOMEM, LOG_ERR,
"%s: Cannot allocate memory for objectDN",
				myself);
			return (2);
		}
		tmp_map->objectDN->read.base = NULL;
		tmp_map->objectDN->write.base = NULL;
		tmp_map->objectDN->read.attrs = NULL;
		tmp_map->objectDN->write.attrs = NULL;
		tmp_map->objectDN->read.scope = LDAP_SCOPE_ONELEVEL;
		tmp_map->objectDN->write.scope = LDAP_SCOPE_UNKNOWN;
	}

	if (!make_fqdn(tmp_map->objectDN, Domain))
		return (-1);
	if (tmp_map->objectDN->write.base) {
		if (!make_full_dn(&tmp_map->objectDN->write.base, Domain))
			return (-1);
	}

	return (0);
}
int
check_domain_specific_order(const char *sd,
	config_key	attrib_num,
	__nis_table_mapping_t *table_mapping,
	__yp_domain_context_t   *ypDomains)
{
	__nis_table_mapping_t *t;
	char    *myself = "check_domain_specific_order";
	char	*type;
	char	*dbId = 0;
	int 	i, len;
	int		match = 0;

	if (ypDomains) {
		if (!ypDomains->numDomains) {
			logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"%s:No domains specified.", myself);
			return (-1);
		}
	} else {
		logmsg(MSG_NOTIMECHECK, LOG_ERR,
			"%s:No domain structure supplied.", myself);
		return (-1);
	}

	for (i = 0; i < ypDomains->numDomains; i++) {
		for (t = table_mapping; t != NULL; t = t->next) {
			len = strlen(sd);
			if ((strcasecmp(t->dbId, sd) == 0) && (len ==
				strlen(t->dbId)))
				/* prevent from matching against itself */
				continue;
			dbId = s_strndup(t->dbId, strlen(t->dbId));
			if (dbId == NULL) {
				logmsg(MSG_NOMEM, LOG_ERR,
					"%s:Memory allocation error.", myself);
				return (-1);
			}

			if (getfullmapname(&dbId,
				ypDomains->domainLabels[i])) {
				logmsg(MSG_NOTIMECHECK, LOG_ERR,
				"Error getting fully qualified name for %s",
					dbId);
				free(dbId);
				return (-1);
			}
			if ((strcasecmp(dbId, sd) == 0) && (len ==
				strlen(dbId))) {
				match = 0;
				switch (attrib_num) {
					case key_yp_map_flags:
						if (t->usedns_flag != 0 ||
							t->securemap_flag != 0)
							match = 1;
						type = YP_MAP_FLAGS;
						break;
					case key_yp_comment_char:
						if (t->commentChar !=
							DEFAULT_COMMENT_CHAR)
							match = 1;
						type = YP_COMMENT_CHAR;
						break;
					case key_yp_repeated_field_separators:
						if (t->separatorStr !=
							DEFAULT_SEP_STRING)
							match = 1;
						type =
					YP_REPEATED_FIELD_SEPARATORS;
						break;
					case key_yp_name_fields:
						if (t->e && t->numColumns)
							match = 1;
						type = YP_NAME_FIELDS;
					case key_yp_split_field:
						if (t->e && t->numColumns)
							match = 1;
						type = YP_SPLIT_FIELD;
						break;
					case key_yp_db_id_map:
						if (t->objName)
							match = 1;
						type = YP_DB_ID_MAP;
						break;
					case key_yp_entry_ttl:
						if (t->initTtlLo !=
							(time_t)NO_VALUE_SET)
							match = 1;
						type = YP_ENTRY_TTL;
						break;
					case key_yp_ldap_object_dn:
						if (t->objectDN)
							match = 1;
						type = YP_LDAP_OBJECT_DN;
						break;
					case key_nis_to_ldap_map:
						if (t->ruleToLDAP)
							match = 1;
						type = NIS_TO_LDAP_MAP;
						break;
					case key_ldap_to_nis_map:
						if (t->ruleFromLDAP)
							match = 1;
						type = LDAP_TO_NIS_MAP;
						break;
					default:
						type = "unknown";
						match = 0;
						break;
				}	/* end of switch */
				if (match) {
					logmsg(MSG_NOTIMECHECK, LOG_ERR,
"Relative attribute '%s' of type '%s' found before fully qualified one '%s'",
						t->dbId, type, sd);
					free(dbId);
					dbId = NULL;
					return (1);
				}
			} /* end of strncasecmp */
			free(dbId);
			dbId = NULL;
		} /* end of t loop */
	} /* end of i loop */
	if (dbId)
		free(dbId);
	dbId = NULL;
	return (0);
}