dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libnisdb / nis_parse_ldap_map.c
blob48e12e73948e61bcc7b43520b341795fa5a33f35
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2015 Gary Mills
24 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <locale.h>
36 #include "ldap_parse.h"
37 #include "nis_parse_ldap_conf.h"
38 #include "nis_parse_ldap_yp_util.h"
39 #include "nis_parse_ldap_util.h"
41 /* other attribute functions */
42 static char *getIndex(const char **s_cur, const char *end_s);
43 static bool_t get_ttls(const char *s, const char *s_end,
44 __nis_table_mapping_t *t_mapping);
45 static __nis_object_dn_t *parse_object_dn(const char *s, const char *end);
46 static int parse_name_fields(const char *name_s, const char *name_s_end,
47 __nis_table_mapping_t *t_mapping);
48 static void get_mapping_rule(const char *s, int len,
49 __nis_table_mapping_t *tbl, bool_t to_ldap);
50 static bool_t get_deleteDisp(const char *s_begin, const char *s_end,
51 __nis_object_dn_t *obj_dn);
53 /* mapping rule functions */
54 static const char *get_lhs(const char *s, const char *end_s,
55 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
56 static const char *get_lhs_match(const char *s, const char *end_s,
57 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
58 static const char *get_lhs_paren_item(const char *s, const char *end_s,
59 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
60 static const char *get_rhs(const char *s, const char *end_s,
61 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
62 static const char *get_mapping_item(const char *s, const char *end_s,
63 __nis_mapping_item_t *item, __nis_mapping_item_type_t type);
64 static const char *get_print_mapping_element(const char *s,
65 const char *end_s, char *fmt_string, __nis_mapping_element_t *e,
66 __nis_mapping_item_type_t item_type);
67 static const char *get_subElement(const char *s, const char *end_s,
68 __nis_mapping_sub_element_t *subelement,
69 __nis_mapping_item_type_t type);
70 static bool_t get_mapping_format(const char *fmt_string,
71 __nis_mapping_format_t **fmt, int *nfmt, int *numItems,
72 bool_t print_mapping);
73 extern __yp_domain_context_t ypDomains;
76 * FUNCTION: add_mapping_attribute
78 * Adds the attribute value to __nis_table_mapping_t
79 * if the value is not yet set for the given database.
81 * RETURN VALUE: 0 on success, -1 on failure
83 * INPUT: attribute number and value
86 int
87 add_mapping_attribute(
88 config_key attrib_num,
89 const char *attrib_val,
90 int attrib_len,
91 __nis_table_mapping_t **table_mapping)
93 const char *s;
94 const char *attrib_end;
95 const char *db_id_end;
96 const char *begin_token;
97 char *index_string;
98 __nis_object_dn_t *objectDN;
99 __nis_table_mapping_t *t_mapping;
100 __nis_table_mapping_t *t;
102 bool_t new_mapping = FALSE;
103 int nm;
104 char *tmp_dbId;
106 attrib_end = attrib_val + attrib_len;
107 for (s = attrib_val; s < attrib_end; s++)
108 if (*s == COLON_CHAR)
109 break;
111 if (s == attrib_end || *attrib_val == COLON_CHAR) {
112 p_error = parse_unexpected_data_end_rule;
113 return (-1);
116 db_id_end = s;
117 while (s > attrib_val && is_whitespace(s[-1]))
118 s--;
120 if (s == attrib_val) {
121 p_error = parse_unexpected_data_end_rule;
122 return (-1);
125 if (yp2ldap) {
126 tmp_dbId = s_strndup(attrib_val, s - attrib_val);
127 if (tmp_dbId == NULL) {
128 p_error = parse_no_mem_error;
129 return (-1);
131 if (strchr(tmp_dbId, COMMA_CHAR)) {
132 /* domain explicitly specified */
133 nm = check_domain_specific_order(tmp_dbId,
134 attrib_num, *table_mapping, &ypDomains);
136 * No logging is needed here, as
137 * check_domain_specific_order
138 * will log any appropriate errors.
140 if (nm != 0) {
141 free(tmp_dbId);
142 return (-1);
145 free(tmp_dbId);
148 if ((t_mapping = find_table_mapping(attrib_val,
149 s - attrib_val, *table_mapping)) == NULL) {
150 /* No mapping with this id, create one */
151 t_mapping = (__nis_table_mapping_t *)
152 s_calloc(1, sizeof (__nis_table_mapping_t));
154 if (t_mapping == NULL) {
155 p_error = parse_no_mem_error;
156 return (-1);
158 (void) initialize_table_mapping(t_mapping);
160 /* dbId is the label before the colon */
161 t_mapping->dbId = s_strndup(attrib_val, s - attrib_val);
162 if (t_mapping->dbId == NULL) {
163 p_error = parse_no_mem_error;
164 free(t_mapping);
165 return (-1);
167 new_mapping = TRUE;
168 } else {
169 /* a table mapping already exists, use it */
170 new_mapping = FALSE;
173 s = db_id_end + 1;
174 while (s < attrib_end && is_whitespace(*s))
175 s++;
177 switch (attrib_num) {
178 case key_yp_map_flags:
179 if (t_mapping->usedns_flag != 0 ||
180 t_mapping->securemap_flag != 0) {
181 warn_duplicate_map(t_mapping->dbId,
182 attrib_num);
183 break;
185 while (is_whitespace(*s) && s < attrib_end)
186 s++;
187 while (s < attrib_end) {
188 if (s < attrib_end && *s == 'b')
189 t_mapping->usedns_flag = 1;
190 if (s < attrib_end && *s == 's')
191 t_mapping->securemap_flag = 1;
192 s++;
194 break;
195 case key_yp_comment_char:
196 if (t_mapping->commentChar !=
197 DEFAULT_COMMENT_CHAR) {
198 warn_duplicate_map(t_mapping->dbId, attrib_num);
199 break;
201 while (is_whitespace(*s) && s < attrib_end)
202 s++;
203 if (s < attrib_end && (s+1) < attrib_end &&
204 (s+2) <= attrib_end) {
205 while (is_whitespace(attrib_end[-1]))
206 attrib_end--;
207 while (*s != SINGLE_QUOTE_CHAR)
208 s++;
209 if (*s == SINGLE_QUOTE_CHAR &&
210 *(s+2) == SINGLE_QUOTE_CHAR) {
211 t_mapping->commentChar = *(s+1);
212 } else if (*s == SINGLE_QUOTE_CHAR &&
213 *(s+1) == SINGLE_QUOTE_CHAR) {
214 t_mapping->commentChar = '\0';
215 } else {
216 /* anything else is an error */
217 p_error = parse_bad_yp_comment_error;
219 break;
220 } else {
221 p_error = parse_bad_yp_comment_error;
222 break;
224 case key_yp_repeated_field_separators:
225 while (s < attrib_end && is_whitespace(*s))
226 s++;
227 if (s < attrib_end) {
228 while (is_whitespace(attrib_end[-1]))
229 attrib_end--;
230 while (s < attrib_end &&
231 *s != DOUBLE_QUOTE_CHAR)
232 s++;
233 s++;
234 begin_token = s;
235 while (s < attrib_end &&
236 *s != DOUBLE_QUOTE_CHAR) {
237 if (*s == ESCAPE_CHAR)
238 s++;
239 s++;
241 t_mapping->separatorStr =
242 s_strndup(begin_token, s - begin_token);
243 if (t_mapping->separatorStr == NULL)
244 break;
245 } else {
246 p_error = parse_bad_field_separator_error;
248 break;
249 case key_yp_name_fields:
250 case key_yp_split_field:
251 if (t_mapping->e || t_mapping->numSplits > 0) {
252 warn_duplicate_map(t_mapping->dbId,
253 attrib_num);
254 break;
256 if (parse_name_fields(s, attrib_end, t_mapping)) {
257 p_error = parse_bad_name_field;
259 break;
260 case key_yp_db_id_map:
261 case key_db_id_map:
262 if (t_mapping->objName != NULL) {
263 warn_duplicate_map(t_mapping->dbId, attrib_num);
264 break;
267 if (s < attrib_end && *s == OPEN_BRACKET) {
268 index_string = getIndex(&s, attrib_end);
269 if (index_string == NULL)
270 break;
271 (void) parse_index(index_string,
272 index_string + strlen(index_string),
273 &t_mapping->index);
274 free(index_string);
275 if (p_error != no_parse_error)
276 break;
278 while (is_whitespace(*s) && s < attrib_end)
279 s++;
280 if (s < attrib_end) {
281 while (is_whitespace(attrib_end[-1]))
282 attrib_end--;
283 t_mapping->objName =
284 s_strndup_esc(s, attrib_end - s);
285 } else {
286 if (yp2ldap) {
287 p_error = parse_bad_map_error;
288 } else {
289 t_mapping->objName = s_strndup(s, 0);
292 break;
294 case key_yp_entry_ttl:
295 case key_entry_ttl:
296 if (t_mapping->initTtlLo != (time_t)NO_VALUE_SET) {
297 warn_duplicate_map(t_mapping->dbId, attrib_num);
298 break;
301 if (!get_ttls(s, attrib_end, t_mapping))
302 p_error = parse_bad_ttl_format_error;
303 break;
305 case key_yp_ldap_object_dn:
306 case key_ldap_object_dn:
307 if (t_mapping->objectDN != NULL) {
308 warn_duplicate_map(t_mapping->dbId, attrib_num);
309 break;
311 objectDN = parse_object_dn(s, attrib_end);
312 if (objectDN == NULL)
313 break;
314 t_mapping->objectDN = objectDN;
315 t_mapping->seq_num = seq_num++;
316 break;
318 case key_nis_to_ldap_map:
319 case key_nisplus_to_ldap_map:
320 if (t_mapping->ruleToLDAP != 0) {
321 warn_duplicate_map(t_mapping->dbId, attrib_num);
322 break;
325 get_mapping_rule(s, attrib_end - s, t_mapping, TRUE);
326 break;
328 case key_ldap_to_nis_map:
329 case key_ldap_to_nisplus_map:
330 if (t_mapping->ruleFromLDAP != NULL) {
331 warn_duplicate_map(t_mapping->dbId, attrib_num);
332 break;
335 get_mapping_rule(s, attrib_end - s, t_mapping, FALSE);
336 break;
338 default:
339 p_error = parse_internal_error;
340 break;
342 if (p_error == no_parse_error) {
343 if (new_mapping) {
344 if (*table_mapping == NULL)
345 *table_mapping = t_mapping;
346 else {
347 for (t = *table_mapping; t->next != NULL;
348 t = t->next)
350 t->next = t_mapping;
353 } else {
354 if (new_mapping)
355 free_table_mapping(t_mapping);
357 return (p_error == no_parse_error ? 0 : -1);
361 * FUNCTION: add_ypdomains_attribute
363 * Adds the yp domains information to the __yp_domain_context_t
364 * structure.
366 * RETURN: 0 on success, -1 on failure
368 * INPUT: attribute number and value
372 add_ypdomains_attribute(
373 config_key attrib_num,
374 const char *attrib_val,
375 int attrib_len,
376 __yp_domain_context_t *ypDomains)
378 const char *s;
379 const char *attrib_end;
380 int numDomains = 0;
382 attrib_end = attrib_val + attrib_len;
383 for (s = attrib_val; s < attrib_end; s++) {
384 if (*s == COLON_CHAR) {
385 break;
388 while (s > attrib_val && is_whitespace(s[-1]))
389 s--;
391 if (s == attrib_val) {
392 p_error = parse_unexpected_data_end_rule;
393 return (-1);
396 if (ypDomains == NULL) {
398 * No point allocating. We cant return the resulting structure,
399 * so just return failure. Should not ever happen because we
400 * are always called with a pointer to the global ypDomains
401 * structure.
403 return (-1);
406 switch (attrib_num) {
407 case key_yp_domain_context:
408 numDomains = ypDomains->numDomains;
409 ypDomains->domainLabels =
410 (char **)s_realloc(ypDomains->domainLabels,
411 (numDomains + 1) *
412 sizeof (ypDomains->domainLabels[0]));
413 if (ypDomains->domainLabels == NULL) {
414 p_error = parse_no_mem_error;
415 free_yp_domain_context(ypDomains);
416 break;
418 ypDomains->domainLabels[numDomains] =
419 s_strndup(attrib_val, s - attrib_val);
420 if (ypDomains->domainLabels[numDomains] == NULL) {
421 p_error = parse_no_mem_error;
422 free_yp_domain_context(ypDomains);
423 break;
425 ypDomains->numDomains = numDomains + 1;
426 while (s < attrib_end && is_whitespace(*s))
427 s++;
428 if (*s == COLON_CHAR)
429 s++;
430 while (s < attrib_end && is_whitespace(*s))
431 s++;
432 ypDomains->domains =
433 (char **)s_realloc(ypDomains->domains,
434 (numDomains + 1) *
435 sizeof (ypDomains->domains[0]));
436 if (ypDomains->domains == NULL) {
437 p_error = parse_no_mem_error;
438 free_yp_domain_context(ypDomains);
439 break;
442 if (s < attrib_end) {
443 while (is_whitespace(attrib_end[-1]))
444 attrib_end--;
445 ypDomains->domains[numDomains] =
446 s_strndup_esc(s, attrib_end - s);
447 if (ypDomains->domains[numDomains] == NULL) {
448 p_error = parse_no_mem_error;
449 free_yp_domain_context(ypDomains);
450 break;
452 } else {
453 p_error = parse_unexpected_yp_domain_end_error;
454 free(ypDomains->domainLabels[numDomains]);
455 ypDomains->domainLabels[numDomains] = NULL;
456 ypDomains->numDomains--;
457 free_yp_domain_context(ypDomains);
459 break;
460 case key_yppasswdd_domains:
461 ypDomains->yppasswddDomainLabels =
462 (char **)s_realloc(
463 ypDomains->yppasswddDomainLabels,
464 (ypDomains->numYppasswdd + 1) *
465 sizeof (ypDomains->yppasswddDomainLabels[0]));
466 if (ypDomains->yppasswddDomainLabels == NULL) {
467 p_error = parse_no_mem_error;
468 break;
470 ypDomains->yppasswddDomainLabels
471 [ypDomains->numYppasswdd] =
472 s_strndup(attrib_val, s - attrib_val);
473 if (ypDomains->yppasswddDomainLabels
474 [ypDomains->numYppasswdd] == NULL) {
475 p_error = parse_no_mem_error;
477 ypDomains->numYppasswdd++;
478 break;
481 return (p_error == no_parse_error ? 0 : -1);
485 * FUNCTION: get_ttls
487 * Parse time to live attribute
489 * RETURN VALUE: TRUE on success, FALSE on failure
491 * INPUT: the attribute value
494 static bool_t
495 get_ttls(
496 const char *s,
497 const char *s_end,
498 __nis_table_mapping_t *t_mapping)
500 time_t initTtlHi = 0;
501 time_t initTtlLo = 0;
502 time_t ttl = 0;
503 time_t digit;
506 * attribute should be of the form
507 * initialTTLlo ":" initialTTLhi ":" runningTTL
510 if (s == s_end) {
511 p_error = parse_bad_ttl_format_error;
512 return (FALSE);
515 if (isdigit(*s)) {
516 while (s < s_end && isdigit(*s)) {
517 digit = (*s++) - '0';
518 if (WILL_OVERFLOW_TIME(initTtlLo, digit))
519 initTtlLo = TIME_MAX;
520 else
521 initTtlLo = initTtlLo * 10 + digit;
523 } else {
524 initTtlLo = ONE_HOUR;
527 while (s < s_end && is_whitespace(*s))
528 s++;
529 if (s + 1 >= s_end || *s++ != COLON_CHAR) {
530 p_error = parse_bad_ttl_format_error;
531 return (FALSE);
534 while (s < s_end && is_whitespace(*s))
535 s++;
536 if (isdigit(*s)) {
537 while (s < s_end && isdigit(*s)) {
538 digit = (*s++) - '0';
539 if (WILL_OVERFLOW_TIME(initTtlHi, digit))
540 initTtlHi = TIME_MAX;
541 else
542 initTtlHi = initTtlHi * 10 + digit;
544 } else {
545 initTtlHi = initTtlLo;
548 while (s < s_end && is_whitespace(*s))
549 s++;
550 if (s >= s_end || *s++ != COLON_CHAR) {
551 p_error = parse_bad_ttl_format_error;
552 return (FALSE);
555 while (s < s_end && is_whitespace(*s))
556 s++;
557 if (isdigit(*s)) {
558 while (s < s_end && isdigit(*s)) {
559 digit = (*s++) - '0';
560 if (WILL_OVERFLOW_TIME(ttl, digit))
561 ttl = TIME_MAX;
562 else
563 ttl = ttl * 10 + digit;
565 } else {
566 ttl = ONE_HOUR;
568 while (s < s_end && is_whitespace(*s))
569 s++;
570 if (s != s_end) {
571 p_error = parse_bad_ttl_format_error;
572 return (FALSE);
575 t_mapping->initTtlLo = initTtlLo;
576 t_mapping->initTtlHi = initTtlHi;
577 t_mapping->ttl = ttl;
578 return (TRUE);
582 * FUNCTION: parse_name_fields
584 * Parse yp name fields
586 * RETURN VALUE: 0 on success, non-zero on failure
588 * INPUTS: attrib_value and attribute_end pointers.
591 static int
592 parse_name_fields(const char *name_s,
593 const char *name_s_end,
594 __nis_table_mapping_t *t_map)
596 int i, n = 0;
597 int nElements = 0;
598 int numSplits = 0;
599 int parse_next_line = 1;
600 int itm_count = 0;
601 const char *begin_fmt;
602 const char *end_fmt;
603 const char *begin_token;
604 const char *end_token;
605 char *fmt_string = NULL;
606 __nis_mapping_format_t *base = NULL;
607 __nis_mapping_item_t *item = NULL;
608 __nis_mapping_element_t *elmnt = NULL;
609 __nis_mapping_item_type_t item_type = mit_nisplus;
610 token_type token;
612 t_map->numColumns = 0;
614 for (; parse_next_line > 0; parse_next_line--) {
615 nElements = 0;
616 item = NULL;
617 base = NULL;
618 while (name_s < name_s_end && *name_s != OPEN_PAREN_CHAR)
619 name_s++;
620 if (name_s == name_s_end) {
621 p_error = parse_unexpected_data_end_rule;
622 return (1);
624 while (name_s < name_s_end && *name_s != DOUBLE_QUOTE_CHAR)
625 name_s++;
626 if (name_s == name_s_end) {
627 p_error = parse_unexpected_data_end_rule;
628 return (1);
630 begin_fmt = ++name_s; /* start of format string */
631 while (name_s < name_s_end && *name_s != DOUBLE_QUOTE_CHAR)
632 name_s++;
633 if (name_s == name_s_end) {
634 p_error = parse_unexpected_data_end_rule;
635 return (1);
637 end_fmt = name_s;
638 fmt_string = s_strndup(begin_fmt, end_fmt - begin_fmt);
639 if (fmt_string == NULL) {
640 p_error = parse_no_mem_error;
641 return (2);
643 if (!get_mapping_format(fmt_string, &base, &n, NULL, FALSE)) {
644 p_error = parse_internal_error;
645 free(fmt_string);
646 fmt_string = NULL;
647 return (3);
649 free(fmt_string);
650 fmt_string = NULL;
651 for (n = 0; base[n].type != mmt_end; n++) {
652 if (base[n].type != mmt_item && base[n].type
653 != mmt_berstring) {
654 if (base[n].type == mmt_berstring_null)
655 base[n].type = mmt_berstring;
656 continue;
658 while (name_s < name_s_end && *name_s != COMMA_CHAR)
659 name_s++;
660 name_s++; /* now at comma char */
661 while (name_s < name_s_end && is_whitespace(*name_s))
662 name_s++;
663 begin_token = name_s++;
664 end_token = name_s_end;
665 name_s = get_next_token(
666 &begin_token, &end_token, &token);
667 if (name_s == NULL) {
668 p_error = parse_item_expected_error;
669 return (4);
671 if (token != string_token) {
672 p_error = parse_item_expected_error;
673 return (5);
675 item = (__nis_mapping_item_t *)s_realloc(item,
676 (nElements + 1) *
677 sizeof (__nis_mapping_item_t));
678 if (item == NULL) {
679 p_error = parse_no_mem_error;
680 return (2);
682 name_s = get_mapping_item(begin_token, name_s_end,
683 &item[nElements], item_type);
684 if (name_s == NULL) {
685 p_error = parse_unmatched_escape;
686 for (n = 0; n < (nElements + 1); n++)
687 free_mapping_item(&item[n]);
688 free_mapping_format(base);
689 return (4);
691 nElements++;
693 if (p_error != no_parse_error) {
694 for (n = 0; n < (nElements + 1); n++)
695 free_mapping_item(&item[n]);
696 free_mapping_format(base);
697 return (6);
699 name_s = skip_token(name_s, name_s_end, close_paren_token);
700 if (name_s == NULL) {
701 p_error = parse_close_paren_expected_error;
702 for (n = 0; n < (nElements + 1); n++)
703 free_mapping_item(&item[n]);
704 free_mapping_format(base);
705 return (4);
707 while (name_s < name_s_end && is_whitespace(*name_s))
708 name_s++;
709 if (*name_s == COMMA_CHAR)
710 parse_next_line++;
712 if (nElements == 0) {
713 p_error = parse_no_match_item;
714 for (n = 0; n < (nElements + 1); n++)
715 free_mapping_item(&item[n]);
716 free_mapping_format(base);
717 return (7);
719 elmnt = (__nis_mapping_element_t *)s_realloc(elmnt,
720 (numSplits + 1) *
721 sizeof (__nis_mapping_element_t));
722 if (elmnt == NULL) {
723 for (n = 0; n < (nElements + 1); n++)
724 free_mapping_item(&item[n]);
725 free_mapping_format(base);
726 p_error = parse_no_mem_error;
727 return (2);
729 elmnt[numSplits].type = me_match;
730 elmnt[numSplits].element.match.numItems = nElements;
731 elmnt[numSplits].element.match.item = item;
732 elmnt[numSplits].element.match.fmt = base;
733 item = NULL;
734 base = NULL;
736 t_map->e = elmnt;
737 t_map->numSplits = numSplits;
738 n = t_map->numColumns;
740 for (i = n, itm_count = 0; i < n + nElements; i++) {
741 if (t_map->e[numSplits].element.
742 match.item[itm_count].name) {
743 if (!add_column(t_map,
744 t_map->e[numSplits].element.
745 match.item[itm_count].name))
746 return (1);
747 itm_count++;
748 } else {
749 p_error = parse_internal_error;
750 for (n = 0; n < (nElements + 1); n++)
751 free_mapping_item(&item[n]);
752 free_mapping_format(base);
753 free_mapping_element(elmnt);
754 return (1);
757 numSplits++;
759 elmnt = NULL;
761 if (item != NULL) {
762 for (n = 0; n < t_map->numColumns; n++) {
763 free_mapping_item(&item[n]);
765 free(item);
767 if (elmnt != NULL)
768 free_mapping_element(elmnt);
769 if (base != NULL)
770 free_mapping_format(base);
772 return (p_error == no_parse_error ? 0 : -1);
776 * FUNCTION: parse_object_dn
778 * Parse object dn attribute
780 * RETURN VALUE: __nis_object_dn_t on success
781 * NULL on failure
783 * INPUT: the attribute value
786 static __nis_object_dn_t *
787 parse_object_dn(const char *s, const char *end)
789 const char *s_begin;
790 const char *s_end;
791 object_dn_token token;
792 parse_object_dn_state dn_state = dn_begin_parse;
793 __nis_object_dn_t *obj_dn = NULL;
794 __nis_object_dn_t *next = NULL;
795 __nis_object_dn_t *last = NULL;
798 * The attribute should be of form
799 * objectDN *( ";" objectDN )
800 * objectDN = readObjectSpec [":"[writeObjectSpec]]
801 * readObjectSpec = [baseAndScope [filterAttrValList]]
802 * writeObjectSpec = [baseAndScope [attrValList [":" deleteDisp]]]
805 while (s < end) {
806 s_begin = s;
807 s_end = end;
808 s = get_next_object_dn_token(&s_begin, &s_end, &token);
809 if (s == NULL)
810 break;
812 if (token == dn_no_token || token == dn_semi_token) {
813 if (obj_dn == NULL)
814 obj_dn = next;
815 else
816 last->next = next;
817 last = next;
818 next = NULL;
819 if (token == dn_no_token)
820 break;
821 dn_state = dn_begin_parse;
823 if (next == NULL) {
824 next = (__nis_object_dn_t *)
825 s_calloc(1, sizeof (__nis_object_dn_t));
826 if (next == NULL)
827 break;
828 next->read.scope = LDAP_SCOPE_ONELEVEL;
829 next->write.scope = LDAP_SCOPE_UNKNOWN;
830 next->delDisp = dd_always;
832 if (token == dn_semi_token)
833 continue;
835 switch (dn_state) {
836 case dn_begin_parse:
837 if (token == dn_ques_token)
838 dn_state = dn_got_read_q_scope;
839 else if (token == dn_colon_token) {
840 dn_state = dn_got_write_colon;
841 next->write.scope = LDAP_SCOPE_ONELEVEL;
842 } else {
843 if (!validate_dn(s_begin, s_end - s_begin))
844 break;
845 next->read.base =
846 s_strndup_esc(s_begin, s_end - s_begin);
847 dn_state = dn_got_read_dn;
849 break;
850 case dn_got_read_dn:
851 if (token == dn_ques_token)
852 dn_state = dn_got_read_q_scope;
853 else if (token == dn_colon_token) {
854 dn_state = dn_got_write_colon;
855 next->write.scope = LDAP_SCOPE_ONELEVEL;
856 } else
857 p_error = parse_object_dn_syntax_error;
858 break;
859 case dn_got_read_q_scope:
860 if (token == dn_ques_token)
861 dn_state = dn_got_read_q_filter;
862 else if (token == dn_colon_token) {
863 dn_state = dn_got_write_colon;
864 next->write.scope = LDAP_SCOPE_ONELEVEL;
865 } else if (token == dn_base_token) {
866 next->read.scope = LDAP_SCOPE_BASE;
867 dn_state = dn_got_read_scope;
868 } else if (token == dn_one_token) {
869 next->read.scope = LDAP_SCOPE_ONELEVEL;
870 dn_state = dn_got_read_scope;
871 } else if (token == dn_sub_token) {
872 next->read.scope = LDAP_SCOPE_SUBTREE;
873 dn_state = dn_got_read_scope;
874 } else {
875 p_error = parse_invalid_scope;
877 break;
878 case dn_got_read_scope:
879 if (token == dn_ques_token)
880 dn_state = dn_got_read_q_filter;
881 else if (token == dn_colon_token) {
882 dn_state = dn_got_write_colon;
883 next->write.scope = LDAP_SCOPE_ONELEVEL;
884 } else
885 p_error = parse_object_dn_syntax_error;
886 break;
887 case dn_got_read_q_filter:
888 if (token == dn_ques_token) {
889 p_error = parse_object_dn_syntax_error;
890 } else if (token == dn_colon_token) {
891 dn_state = dn_got_write_colon;
892 next->write.scope = LDAP_SCOPE_ONELEVEL;
893 } else {
894 if (!validate_ldap_filter(s_begin, s_end))
895 break;
896 next->read.attrs =
897 s_strndup_esc(s_begin, s_end - s_begin);
898 dn_state = dn_got_read_filter;
900 break;
901 case dn_got_read_filter:
902 if (token == dn_ques_token) {
903 p_error = parse_object_dn_syntax_error;
904 } else if (token == dn_colon_token) {
905 dn_state = dn_got_write_colon;
906 next->write.scope = LDAP_SCOPE_ONELEVEL;
907 } else
908 p_error = parse_object_dn_syntax_error;
909 break;
910 case dn_got_write_colon:
911 if (token == dn_ques_token)
912 dn_state = dn_got_write_q_scope;
913 else if (token == dn_colon_token) {
914 dn_state = dn_got_delete_colon;
915 } else {
916 if (!validate_dn(s_begin, s_end - s_begin))
917 break;
918 next->write.base =
919 s_strndup_esc(s_begin, s_end - s_begin);
920 dn_state = dn_got_write_dn;
922 break;
923 case dn_got_write_dn:
924 if (token == dn_ques_token)
925 dn_state = dn_got_write_q_scope;
926 else if (token == dn_colon_token) {
927 dn_state = dn_got_delete_colon;
928 } else
929 p_error = parse_object_dn_syntax_error;
930 break;
931 case dn_got_write_q_scope:
932 if (token == dn_ques_token)
933 dn_state = dn_got_write_q_filter;
934 else if (token == dn_colon_token) {
935 dn_state = dn_got_delete_colon;
936 } else if (token == dn_base_token) {
937 next->write.scope = LDAP_SCOPE_BASE;
938 dn_state = dn_got_write_scope;
939 } else if (token == dn_one_token) {
940 next->write.scope = LDAP_SCOPE_ONELEVEL;
941 dn_state = dn_got_write_scope;
942 } else if (token == dn_sub_token) {
943 next->write.scope = LDAP_SCOPE_SUBTREE;
944 dn_state = dn_got_write_scope;
945 } else {
946 p_error = parse_invalid_scope;
948 break;
949 case dn_got_write_scope:
950 if (token == dn_ques_token)
951 dn_state = dn_got_write_q_filter;
952 else if (token == dn_colon_token) {
953 dn_state = dn_got_delete_colon;
954 } else
955 p_error = parse_object_dn_syntax_error;
956 break;
957 case dn_got_write_q_filter:
958 if (token == dn_ques_token) {
959 p_error = parse_object_dn_syntax_error;
960 } else if (token == dn_colon_token) {
961 dn_state = dn_got_delete_colon;
962 } else {
963 if (!validate_ldap_filter(s_begin, s_end))
964 break;
965 next->write.attrs =
966 s_strndup_esc(s_begin, s_end - s_begin);
967 dn_state = dn_got_write_filter;
969 break;
970 case dn_got_write_filter:
971 if (token == dn_ques_token) {
972 p_error = parse_object_dn_syntax_error;
973 } else if (token == dn_colon_token) {
974 dn_state = dn_got_delete_colon;
976 } else
977 p_error = parse_semi_expected_error;
978 break;
979 case dn_got_delete_colon:
980 if (token == dn_ques_token) {
981 p_error = parse_object_dn_syntax_error;
982 } else if (token == dn_colon_token) {
983 p_error = parse_object_dn_syntax_error;
984 } else {
985 if (!get_deleteDisp(s_begin, s_end, next))
986 break;
987 dn_state = dn_got_delete_dsp;
989 break;
990 case dn_got_delete_dsp:
991 p_error = parse_object_dn_syntax_error;
992 break;
995 if (p_error != no_parse_error)
996 break;
998 if (p_error != no_parse_error) {
999 if (obj_dn != NULL)
1000 free_object_dn(obj_dn);
1001 if (next != NULL)
1002 free_object_dn(next);
1003 obj_dn = NULL;
1004 } else if (next != NULL) {
1005 if (obj_dn == NULL)
1006 obj_dn = next;
1007 else
1008 last->next = next;
1009 } else if (obj_dn == NULL)
1010 obj_dn = (__nis_object_dn_t *)
1011 s_calloc(1, sizeof (__nis_object_dn_t));
1013 return (obj_dn);
1017 * FUNCTION: get_mapping_rule
1019 * Parse mapping rule attributes
1021 * RETURN VALUE: None. Errors determined by p_error
1023 * INPUT: the attribute value and mapping rule type
1026 static void
1027 get_mapping_rule(
1028 const char *s,
1029 int len,
1030 __nis_table_mapping_t *tbl,
1031 bool_t to_ldap)
1033 const char *end_s = s + len;
1034 const char *begin_token;
1035 const char *end_token;
1036 __nis_mapping_rule_t **rule = NULL;
1037 __nis_mapping_rule_t *next = NULL;
1038 /* __nis_mapping_rule_t **r; */
1039 token_type t;
1040 int nRules = 0;
1041 const char *s1;
1042 int i;
1045 * The attribute value is of the form
1046 * colattrspec *("," colattrspec)
1047 * colattrspec = lhs "=" rhs
1048 * lhs = lval | namespeclist
1049 * rhs = rval | [namespec]
1052 for (;;) {
1053 if ((next = (__nis_mapping_rule_t *)
1054 s_calloc(1, sizeof (__nis_mapping_rule_t))) == NULL)
1055 break;
1057 s = get_lhs(s, end_s, &next->lhs,
1058 to_ldap ? mit_ldap : mit_nisplus);
1059 if (s == NULL)
1060 break;
1062 begin_token = s;
1063 end_token = end_s;
1064 s1 = get_next_token(&begin_token, &end_token, &t);
1065 if (s1 == NULL)
1066 break;
1067 if (!(to_ldap && (t == comma_token || t == no_token))) {
1068 s = get_rhs(s, end_s, &next->rhs,
1069 to_ldap ? mit_nisplus : mit_ldap);
1070 if (s == NULL)
1071 break;
1074 if (next->lhs.numElements > 1 &&
1075 (next->rhs.numElements != 1 ||
1076 next->rhs.element[0].type != me_split)) {
1077 p_error = parse_lhs_rhs_type_mismatch;
1078 break;
1080 if (rule == NULL) {
1081 rule = (__nis_mapping_rule_t **)
1082 malloc(sizeof (__nis_mapping_rule_t *));
1083 if (rule == NULL)
1084 break;
1085 } else {
1086 rule = (__nis_mapping_rule_t **)s_realloc(rule,
1087 (nRules + 1) *
1088 sizeof (__nis_mapping_rule_t *));
1089 if (rule == NULL)
1090 break;
1093 rule[nRules++] = next;
1094 next = NULL;
1096 begin_token = s;
1097 end_token = end_s;
1098 s = get_next_token(&begin_token, &end_token, &t);
1099 if (s == NULL)
1100 break;
1101 if (t == comma_token)
1102 continue;
1103 if (t != no_token) {
1104 p_error = parse_unexpected_data_end_rule;
1105 break;
1107 if (to_ldap) {
1108 tbl->numRulesToLDAP = nRules;
1109 tbl->ruleToLDAP = rule;
1110 } else {
1111 tbl->numRulesFromLDAP = nRules;
1112 tbl->ruleFromLDAP = rule;
1114 return;
1117 if (rule) {
1118 for (i = 0; i < nRules; i++)
1119 free_mapping_rule(rule[i]);
1120 free(rule);
1122 if (next)
1123 free_mapping_rule(next);
1127 * FUNCTION: get_lhs
1129 * Parse left hand side of mapping rule attribute
1131 * RETURN VALUE: NULL if error
1132 * position of beginning rhs
1134 * INPUT: the attribute value and mapping rule type
1137 static const char *
1138 get_lhs(const char *s,
1139 const char *end_s,
1140 __nis_mapping_rlhs_t *lhs,
1141 __nis_mapping_item_type_t item_type)
1143 token_type t;
1144 const char *begin_token;
1145 const char *end_token;
1146 const char *sav_s;
1147 __nis_mapping_element_t *e = NULL;
1150 * lhs can be expressed as:
1151 * item
1152 * (item)
1153 * (item list)
1154 * (fmt, item list)
1156 * lhs = lval | namespeclist
1157 * lval = "(" formatspec "," namespec *("," namespec) ")"
1158 * namespeclist = namespec | "(" namespec *("," namespec) ")"
1161 for (; p_error == no_parse_error; ) {
1162 begin_token = s;
1163 end_token = end_s;
1164 s = get_next_token(&begin_token, &end_token, &t);
1165 if (s == NULL)
1166 break;
1167 if (t == no_token) {
1168 p_error = parse_unexpected_data_end_rule;
1169 break;
1172 e = (__nis_mapping_element_t *)
1173 s_calloc(1, sizeof (__nis_mapping_element_t));
1174 if (e == NULL)
1175 break;
1177 if (t == open_paren_token) {
1178 free(e);
1179 e = NULL;
1181 begin_token = s;
1182 end_token = end_s;
1183 sav_s = s;
1184 s = get_next_token(&begin_token, &end_token, &t);
1185 if (s == NULL)
1186 break;
1188 if (t == quoted_string_token) {
1189 s = get_lhs_match(sav_s, end_s, lhs, item_type);
1190 if (s == NULL)
1191 break;
1192 } else if (t == string_token) {
1193 s = get_lhs_paren_item(sav_s, end_s, lhs,
1194 item_type);
1195 if (s == NULL)
1196 break;
1197 } else {
1198 p_error = parse_bad_lhs_format_error;
1199 break;
1201 } else if (t == string_token) {
1202 s = get_mapping_item(begin_token, end_s,
1203 &e->element.item, item_type);
1204 if (s == NULL)
1205 break;
1206 e->type = me_item;
1207 if (!add_element(e, lhs))
1208 break;
1209 e = NULL;
1210 } else {
1211 p_error = parse_bad_lhs_format_error;
1212 break;
1215 s = skip_token(s, end_s, equal_token);
1216 if (s == NULL)
1217 break;
1218 if (p_error == no_parse_error)
1219 return (s);
1221 if (e != NULL)
1222 free_mapping_element(e);
1224 return (NULL);
1228 * FUNCTION: get_lhs_match
1230 * Parse left hand side of mapping rule attribute in case of
1231 * matching rule
1233 * RETURN VALUE: NULL if error
1234 * position of beginning rhs
1236 * INPUT: the attribute value and mapping rule type
1239 static const char *
1240 get_lhs_match(
1241 const char *s,
1242 const char *end_s,
1243 __nis_mapping_rlhs_t *lhs,
1244 __nis_mapping_item_type_t item_type)
1246 token_type t;
1247 const char *begin_token;
1248 const char *end_token;
1249 int n = 0;
1250 int nElements = 0;
1251 char *fmt_string = NULL;
1252 __nis_mapping_format_t *base = NULL;
1253 __nis_mapping_item_t *item = NULL;
1254 __nis_mapping_item_t *itm;
1255 __nis_mapping_element_t *e;
1258 * lval = "(" formatspec "," namespec *("," namespec) ")"
1261 for (; p_error == no_parse_error; ) {
1262 begin_token = s;
1263 end_token = end_s;
1264 s = get_next_token(&begin_token, &end_token, &t);
1265 if (s == NULL || t != quoted_string_token) {
1266 p_error = parse_internal_error;
1267 break;
1271 fmt_string = s_strndup(begin_token, end_token - begin_token);
1272 if (fmt_string == NULL)
1273 break;
1275 if (!get_mapping_format(fmt_string, &base, &n, NULL, FALSE))
1276 break;
1278 for (n = 0; base[n].type != mmt_end; n++) {
1279 if (base[n].type != mmt_item &&
1280 base[n].type != mmt_berstring) {
1281 if (base[n].type == mmt_berstring_null)
1282 base[n].type = mmt_berstring;
1283 continue;
1285 s = skip_token(s, end_s, comma_token);
1286 if (s == NULL) {
1287 p_error = parse_not_enough_extract_items;
1288 break;
1290 begin_token = s;
1291 end_token = end_s;
1292 s = get_next_token(&begin_token, &end_token, &t);
1293 if (s == NULL)
1294 break;
1295 if (t != string_token) {
1296 p_error = parse_item_expected_error;
1297 break;
1299 itm = (__nis_mapping_item_t *)
1300 s_realloc(item, (nElements + 1) *
1301 sizeof (__nis_mapping_item_t));
1302 if (itm == NULL)
1303 break;
1304 item = itm;
1306 s = get_mapping_item(begin_token, end_s,
1307 &item[nElements], item_type);
1308 if (s == NULL)
1309 break;
1310 nElements++;
1312 if (p_error != no_parse_error)
1313 break;
1315 s = skip_token(s, end_s, close_paren_token);
1316 if (s == NULL)
1317 break;
1318 free(fmt_string);
1319 fmt_string = NULL;
1321 if (nElements == 0) {
1322 p_error = parse_no_match_item;
1323 break;
1325 e = (__nis_mapping_element_t *)s_calloc(1,
1326 sizeof (__nis_mapping_element_t));
1327 if (e == NULL)
1328 break;
1329 e->type = me_match;
1330 e->element.match.numItems = nElements;
1331 e->element.match.item = item;
1332 e->element.match.fmt = base;
1333 lhs->numElements = 1;
1334 lhs->element = e;
1336 if (p_error == no_parse_error)
1337 return (s);
1339 if (item == NULL) {
1340 for (n = 0; n < nElements; n++)
1341 free_mapping_item(&item[n]);
1342 free(item);
1344 free(fmt_string);
1345 if (base != NULL)
1346 free_mapping_format(base);
1348 return (NULL);
1352 * FUNCTION: get_lhs_paren_item
1354 * Parse left hand side of mapping rule attribute in case of
1355 * (item1, ..., item-n)
1357 * RETURN VALUE: NULL if error
1358 * position of beginning rhs
1360 * INPUT: the attribute value and mapping rule type
1363 static const char *
1364 get_lhs_paren_item(
1365 const char *s,
1366 const char *end_s,
1367 __nis_mapping_rlhs_t *lhs,
1368 __nis_mapping_item_type_t item_type)
1370 token_type t;
1371 const char *begin_token;
1372 const char *end_token;
1373 __nis_mapping_element_t *e = NULL;
1374 int n = 0;
1375 int i;
1378 * "(" namespec *("," namespec) ")"
1381 for (;;) {
1382 e = (__nis_mapping_element_t *)s_realloc(e, (n + 1) *
1383 sizeof (__nis_mapping_element_t));
1384 if (e == NULL)
1385 break;
1387 s = get_mapping_item(s, end_s, &e[n].element.item,
1388 item_type);
1389 if (s == NULL)
1390 break;
1391 e[n].type = me_item;
1392 n++;
1394 begin_token = s;
1395 end_token = end_s;
1396 s = get_next_token(&begin_token, &end_token, &t);
1397 if (s != NULL && t == close_paren_token) {
1398 lhs->numElements = n;
1399 if (n == 1)
1400 e[0].element.item.repeat = TRUE;
1401 lhs->element = e;
1402 return (s);
1404 if (s == NULL || t != comma_token) {
1405 p_error = parse_comma_expected_error;
1406 break;
1409 for (i = 0; i < n; i++)
1410 free_mapping_element(&e[i]);
1411 free(e);
1412 return (NULL);
1416 * FUNCTION: get_rhs
1418 * Parse right hand side of mapping rule attribute
1420 * RETURN VALUE: NULL if error
1421 * position of beginning next mapping rule
1423 * INPUT: the attribute value and mapping rule type
1426 static const char *
1427 get_rhs(
1428 const char *s,
1429 const char *end_s,
1430 __nis_mapping_rlhs_t *rhs,
1431 __nis_mapping_item_type_t item_type)
1434 * This handles the following cases:
1435 * name me_item
1436 * (name) me_item
1437 * (fmt, name-list) me_print
1438 * (item, fmt) me_extract
1441 token_type t;
1442 const char *begin_token;
1443 const char *end_token;
1444 char *str = NULL;
1445 __nis_mapping_format_t *fmt = NULL;
1446 __nis_mapping_element_t *e = NULL;
1447 __nis_mapping_item_t item;
1448 int n;
1450 (void) memset(&item, 0, sizeof (item));
1452 for (; p_error == no_parse_error; ) {
1453 begin_token = s;
1454 end_token = end_s;
1455 s = get_next_token(&begin_token, &end_token, &t);
1456 if (s == NULL)
1457 break;
1459 e = (__nis_mapping_element_t *)
1460 s_calloc(1, sizeof (__nis_mapping_element_t));
1461 if (e == NULL)
1462 break;
1464 if (t == string_token) {
1465 s = get_mapping_item(begin_token, end_s,
1466 &e->element.item, item_type);
1467 } else if (t == open_paren_token) {
1468 begin_token = s;
1469 end_token = end_s;
1470 s = get_next_token(&begin_token, &end_token, &t);
1471 if (s == NULL)
1472 break;
1473 if (t == string_token) {
1474 /* (item, fmt) - me_extract */
1475 /* (item, "c") - me_split */
1476 s = get_mapping_item(begin_token, end_s,
1477 &item, item_type);
1478 if (s == NULL)
1479 break;
1480 begin_token = s;
1481 end_token = end_s;
1482 s = get_next_token(&begin_token, &end_token,
1483 &t);
1484 if (s == NULL)
1485 break;
1486 else if (t == close_paren_token) {
1487 item.repeat = TRUE;
1488 e->element.item = item;
1489 e->type = me_item;
1490 rhs->numElements = 1;
1491 rhs->element = e;
1492 return (s);
1493 } else if (t != comma_token) {
1494 p_error = parse_comma_expected_error;
1495 break;
1498 begin_token = s;
1499 end_token = end_s;
1500 s = get_next_token(&begin_token, &end_token,
1501 &t);
1502 if (s == NULL || t != quoted_string_token) {
1503 p_error =
1504 parse_format_string_expected_error;
1505 break;
1508 if (end_token == begin_token + 1 ||
1509 (*begin_token == ESCAPE_CHAR &&
1510 end_token == begin_token + 2)) {
1511 e->type = me_split;
1512 e->element.split.item = item;
1513 e->element.split.delim = *begin_token;
1514 } else {
1515 str = s_strndup(begin_token,
1516 end_token - begin_token);
1517 if (str == NULL)
1518 break;
1519 if (!get_mapping_format(str, &fmt,
1520 NULL, &n, FALSE))
1521 break;
1522 free(str);
1523 str = NULL;
1524 if (n != 1) {
1525 p_error =
1526 parse_bad_extract_format_spec;
1527 break;
1529 e->type = me_extract;
1530 e->element.extract.item = item;
1531 e->element.extract.fmt = fmt;
1533 s = skip_token(s, end_s, close_paren_token);
1534 } else if (t == quoted_string_token) {
1535 /* (fmt, name-list) - me_print */
1536 str = s_strndup(begin_token,
1537 end_token - begin_token);
1538 if (str == NULL)
1539 break;
1541 s = get_print_mapping_element(s, end_s,
1542 str, e, item_type);
1543 free(str);
1544 str = NULL;
1545 } else {
1546 p_error = parse_start_rhs_unrecognized;
1547 break;
1549 } else {
1550 p_error = parse_start_rhs_unrecognized;
1551 break;
1553 if (s == NULL)
1554 break;
1555 rhs->numElements = 1;
1556 rhs->element = e;
1557 if (p_error == no_parse_error)
1558 return (s);
1560 free(str);
1561 if (fmt != NULL)
1562 free_mapping_format(fmt);
1563 if (e != NULL)
1564 free_mapping_element(e);
1565 free_mapping_item(&item);
1567 return (NULL);
1571 * FUNCTION: get_print_mapping_element
1573 * Parse a print mapping rule attribute in case of the form
1574 * (fmt, name-list)
1576 * RETURN VALUE: NULL if error
1577 * position of beginning next mapping rule
1579 * INPUT: the attribute value and mapping rule type
1582 static const char *
1583 get_print_mapping_element(
1584 const char *s,
1585 const char *end_s,
1586 char *fmt_string,
1587 __nis_mapping_element_t *e,
1588 __nis_mapping_item_type_t item_type)
1590 token_type t;
1591 const char *begin_token;
1592 const char *end_token;
1593 char elide;
1594 bool_t doElide;
1595 __nis_mapping_format_t *base = NULL;
1596 __nis_mapping_sub_element_t *subElement = NULL;
1597 int n = 0;
1598 int nSub = 0;
1599 int numSubElements;
1601 for (; p_error == no_parse_error; ) {
1602 if (!get_mapping_format(fmt_string, &base, &n,
1603 &numSubElements, TRUE))
1604 break;
1605 subElement = (__nis_mapping_sub_element_t *)
1606 s_calloc(numSubElements,
1607 sizeof (__nis_mapping_sub_element_t));
1608 if (subElement == NULL)
1609 break;
1610 for (n = 0; base[n].type != mmt_end; n++) {
1611 if (base[n].type != mmt_item &&
1612 base[n].type != mmt_berstring) {
1613 if (base[n].type == mmt_berstring_null)
1614 base[n].type = mmt_berstring;
1615 continue;
1617 if (nSub < numSubElements) {
1618 s = skip_token(s, end_s, comma_token);
1619 if (s == NULL) {
1620 p_error = parse_bad_print_format;
1621 break;
1625 /* namelist may have parens around it */
1626 s = get_subElement(s, end_s, &subElement[nSub],
1627 item_type);
1628 if (s == NULL)
1629 break;
1630 nSub++;
1632 if (p_error != no_parse_error)
1633 break;
1635 begin_token = s;
1636 end_token = end_s;
1637 s = get_next_token(&begin_token, &end_token, &t);
1638 if (s == NULL || t == no_token) {
1639 p_error = parse_unexpected_data_end_rule;
1640 break;
1641 } else if (t == close_paren_token) {
1642 doElide = FALSE;
1643 elide = '\0';
1644 } else if (t == comma_token) {
1645 begin_token = s;
1646 end_token = end_s;
1647 s = get_next_token(&begin_token, &end_token, &t);
1648 if (s != NULL && t == quoted_string_token &&
1649 (end_token == begin_token + 1 ||
1650 (*begin_token == ESCAPE_CHAR &&
1651 end_token == begin_token + 2))) {
1652 if (numSubElements != 1 ||
1653 subElement->type == me_extract ||
1654 subElement->type == me_split) {
1655 p_error = parse_cannot_elide;
1656 break;
1658 if (subElement->type == me_item &&
1659 !subElement->element.item.repeat) {
1660 p_error = parse_cannot_elide;
1661 break;
1663 elide = *begin_token;
1664 doElide = TRUE;
1666 } else {
1667 p_error = parse_bad_elide_char;
1668 break;
1670 s = skip_token(s, end_s, close_paren_token);
1671 if (s == NULL)
1672 break;
1675 e->type = me_print;
1676 e->element.print.fmt = base;
1677 e->element.print.numSubElements = numSubElements;
1678 e->element.print.subElement = subElement;
1679 e->element.print.elide = elide;
1680 e->element.print.doElide = doElide;
1682 if (p_error == no_parse_error)
1683 return (s);
1685 if (base)
1686 free_mapping_format(base);
1687 if (subElement != NULL) {
1688 for (n = 0; n < numSubElements; n++)
1689 free_mapping_sub_element(&subElement[n]);
1690 free(subElement);
1693 return (NULL);
1697 * FUNCTION: get_mapping_item
1699 * Parse attribute string to get mapping item
1701 * RETURN VALUE: NULL if error
1702 * position of beginning next token after item
1704 * INPUT: the attribute value and mapping rule type
1707 static const char *
1708 get_mapping_item(
1709 const char *s,
1710 const char *end_s,
1711 __nis_mapping_item_t *item,
1712 __nis_mapping_item_type_t type)
1714 token_type t;
1715 const char *begin_token;
1716 const char *end_token;
1717 char *name = NULL;
1718 char *index_string;
1719 const char *s_sav;
1720 int len;
1722 (void) memset(item, 0, sizeof (*item));
1725 * A namepec is defined as follows:
1726 * namespec = ["ldap:"] attrspec [searchTriple] |
1727 * ["nis+:"] colspec [objectspec]
1729 * The form of the item is assumed to be as follows:
1730 * ["ldap:"] attrspec [searchTriple]
1731 * attrspec = attribute | "(" attribute ")"
1732 * searchTriple = ":" [baseDN] ["?" [scope] ["?" [filter]]]
1733 * baseDN = Base DN for search
1734 * scope = "base" | "one" | "sub"
1735 * filter = LDAP search filter
1737 * The form of the objectspec is as follows:
1738 * ["nis+:"] colspec [objectspec]
1739 * objectspec = objectname | "[" indexlist "]" tablename
1740 * objectname = The name of a NIS+ object
1741 * tablename = The name of a NIS+ table
1742 * indexlist = colspec ["," colspec]
1743 * colspec = colname "=" colvalue
1744 * colname = The name of a column in the table
1745 * colvalue = colvaluestring | \" colvaluestring \"
1748 for (; p_error == no_parse_error; ) {
1749 while (s < end_s && is_whitespace(*s))
1750 s++;
1751 len = end_s - s;
1752 if (yp2ldap) {
1753 if ((begin_token = skip_string("ldap:", s,
1754 len)) != NULL) {
1755 item->type = mit_ldap;
1756 } else if ((begin_token = skip_string("yp:", s,
1757 len)) != NULL) {
1758 item->type = mit_nisplus;
1759 } else {
1760 item->type = type;
1761 begin_token = s;
1763 } else {
1764 if ((begin_token = skip_string("ldap:", s,
1765 len)) != NULL) {
1766 item->type = mit_ldap;
1767 } else if ((begin_token = skip_string("nis+:", s,
1768 len)) != NULL) {
1769 item->type = mit_nisplus;
1770 } else if ((begin_token = skip_string("nisplus:", s,
1771 len)) != NULL) {
1772 item->type = mit_nisplus;
1773 } else {
1774 item->type = type;
1775 begin_token = s;
1779 end_token = end_s;
1780 s = get_next_token(&begin_token, &end_token, &t);
1781 if (s == NULL || t != string_token) {
1782 p_error = parse_bad_item_format;
1783 break;
1786 item->name = s_strndup_esc(begin_token,
1787 end_token - begin_token);
1788 if (item->name == NULL)
1789 break;
1790 if (item->type == mit_ldap) {
1791 item->searchSpec.triple.scope = LDAP_SCOPE_UNKNOWN;
1792 begin_token = s;
1793 end_token = end_s;
1794 s_sav = s;
1795 s = get_next_token(&begin_token, &end_token, &t);
1796 if (s != NULL && t == colon_token) {
1797 s = get_search_triple(s, end_s,
1798 &item->searchSpec.triple);
1799 if (s == NULL)
1800 break;
1801 } else
1802 s = s_sav;
1803 } else if (item->type == mit_nisplus) {
1804 while (s < end_s && is_whitespace(*s))
1805 s++;
1807 if (s < end_s && *s == OPEN_BRACKET) {
1808 index_string = getIndex(&s, end_s);
1809 if (index_string == NULL)
1810 break;
1811 (void) parse_index(index_string,
1812 index_string + strlen(index_string),
1813 &item->searchSpec.obj.index);
1814 free(index_string);
1815 if (p_error != no_parse_error)
1816 break;
1818 s_sav = s;
1819 begin_token = s;
1820 end_token = end_s;
1821 s = get_next_token(&begin_token, &end_token, &t);
1822 if (s != NULL && t == string_token) {
1823 name = s_strndup_esc(begin_token,
1824 end_token - begin_token);
1825 if (name == NULL)
1826 break;
1827 item->searchSpec.obj.name = name;
1828 } else
1829 s = s_sav;
1831 if (p_error == no_parse_error)
1832 return (s);
1834 free_mapping_item(item);
1835 (void) memset(item, 0, sizeof (*item));
1836 if (name == NULL)
1837 free(name);
1838 return (NULL);
1841 static const char *
1842 get_print_sub_element(const char *s,
1843 const char *end_s,
1844 __nis_mapping_item_type_t type,
1845 __nis_mapping_sub_element_t *sub)
1848 int k;
1849 int n;
1850 const char *begin_token;
1851 const char *end_token;
1852 token_type t;
1853 __nis_mapping_format_t *base;
1854 __nis_mapping_item_t *print_item;
1856 k = 0;
1857 base = sub->element.print.fmt;
1858 print_item = sub->element.print.item;
1859 sub->element.print.doElide = FALSE;
1860 sub->element.print.elide = '\0';
1862 for (n = 0; base[n].type != mmt_end; n++) {
1863 if (base[n].type != mmt_item && base[n].type != mmt_berstring) {
1864 if (base[n].type == mmt_berstring_null)
1865 base[n].type = mmt_berstring;
1866 continue;
1868 s = skip_token(s, end_s, comma_token);
1869 if (s == NULL) {
1870 p_error = parse_bad_print_format;
1871 break;
1874 begin_token = s;
1875 end_token = end_s;
1876 s = get_next_token(&begin_token, &end_token, &t);
1877 if (s == NULL)
1878 break;
1880 * Determine if of the form
1881 * ("fmt", (item), "delim") or
1882 * ("fmt", item1, item2, ..., item n)
1884 if (t == open_paren_token) {
1885 if (sub->element.print.numItems != 1) {
1886 p_error = parse_invalid_print_arg;
1887 break;
1889 s = get_mapping_item(s, end_s, &print_item[k++], type);
1890 s = skip_token(s, end_s, close_paren_token);
1891 s = skip_token(s, end_s, comma_token);
1892 if (s == NULL) {
1893 p_error = parse_bad_print_format;
1894 break;
1896 begin_token = s;
1897 end_token = end_s;
1898 s = get_next_token(&begin_token, &end_token, &t);
1899 if (s == NULL)
1900 break;
1901 if (t != quoted_string_token ||
1902 begin_token + 1 != end_token) {
1903 p_error = parse_bad_elide_char;
1904 break;
1906 sub->element.print.elide = *begin_token;
1907 sub->element.print.doElide = TRUE;
1908 print_item[0].repeat = TRUE;
1909 break;
1911 s = get_mapping_item(begin_token, end_s,
1912 &print_item[k++], type);
1913 if (s == NULL)
1914 break;
1916 if (p_error != no_parse_error)
1917 break;
1920 return (p_error == no_parse_error ? s : NULL);
1924 * FUNCTION: get_subElement
1926 * Parse attribute string to get sub element item
1928 * RETURN VALUE: NULL if error
1929 * position of beginning next token after item
1931 * INPUT: the attribute value and mapping rule type
1934 static const char *
1935 get_subElement(
1936 const char *s,
1937 const char *end_s,
1938 __nis_mapping_sub_element_t *subelement,
1939 __nis_mapping_item_type_t type)
1941 token_type t;
1942 const char *begin_token;
1943 const char *end_token;
1944 char *fmt_string;
1945 __nis_mapping_item_t item;
1946 __nis_mapping_element_type_t e_type;
1947 __nis_mapping_item_t *print_item = NULL;
1948 __nis_mapping_format_t *base = NULL;
1949 int n = 0;
1950 int numItems = 0;
1951 unsigned char delim;
1952 __nis_mapping_sub_element_t sub;
1955 * What is the form of we are expecting here
1956 * item me_item
1957 * (item) me_item
1958 * ("fmt", item1, item2, ..., item n) me_print
1959 * ("fmt", (item), "elide") me_print
1960 * (name, "delim") me_split
1961 * (item, "fmt") me_extract
1963 (void) memset(&item, 0, sizeof (item));
1965 for (; p_error == no_parse_error; ) {
1966 begin_token = s;
1967 end_token = end_s;
1968 s = get_next_token(&begin_token, &end_token, &t);
1969 if (s == NULL)
1970 break;
1971 if (t == string_token) { /* me_item */
1972 s = get_mapping_item(begin_token, end_s,
1973 &subelement->element.item, type);
1974 if (s == NULL)
1975 break;
1976 subelement->type = me_item;
1977 return (s);
1978 } else if (t != open_paren_token) {
1979 p_error = parse_item_expected_error;
1980 break;
1983 begin_token = s;
1984 end_token = end_s;
1985 s = get_next_token(&begin_token, &end_token, &t);
1986 if (s == NULL)
1987 break;
1989 if (t != string_token && t != quoted_string_token) {
1990 p_error = parse_item_expected_error;
1991 break;
1993 e_type = me_print;
1994 if (t == string_token) {
1995 /* me_item, me_extract or me_split */
1996 s = get_mapping_item(begin_token, end_s, &item, type);
1997 if (s == NULL)
1998 break;
2000 begin_token = s;
2001 end_token = end_s;
2002 s = get_next_token(&begin_token, &end_token, &t);
2003 if (s == NULL) {
2004 p_error = parse_unexpected_data_end_rule;
2005 break;
2006 } else if (t == close_paren_token) {
2007 subelement->type = me_item;
2008 item.repeat = TRUE;
2009 subelement->element.item = item;
2010 if (yp2ldap) {
2011 while (s < end_s && is_whitespace(*s))
2012 s++;
2013 if (s == end_s) {
2014 p_error =
2015 parse_unexpected_data_end_rule;
2016 break;
2018 if (*s == DASH_CHAR && s < end_s) {
2019 s++;
2020 while (s < end_s &&
2021 is_whitespace(*s))
2022 s++;
2023 begin_token = s;
2024 end_token = end_s;
2026 subelement->element.item.exItem
2028 (__nis_mapping_item_t *)
2029 s_malloc(sizeof (__nis_mapping_item_t));
2030 if (!subelement->
2031 element.item.exItem)
2032 break;
2033 s = get_mapping_item(s, end_s,
2034 subelement->
2035 element.item.exItem,
2036 type);
2037 if (s == NULL) {
2038 p_error =
2039 parse_internal_error;
2040 free_mapping_item(
2041 subelement->
2042 element.item.exItem);
2043 subelement->
2044 element.item.exItem =
2045 NULL;
2046 break;
2050 return (s);
2051 } else if (t != comma_token) {
2052 p_error = parse_comma_expected_error;
2053 break;
2056 begin_token = s;
2057 end_token = end_s;
2058 s = get_next_token(&begin_token, &end_token, &t);
2059 if (s == NULL || t != quoted_string_token) {
2060 p_error = parse_format_string_expected_error;
2061 break;
2063 if (end_token == begin_token + 1 ||
2064 (*begin_token == ESCAPE_CHAR &&
2065 end_token == begin_token + 2)) {
2066 /* me_split */
2067 delim = (unsigned char)end_token[-1];
2068 s = skip_token(s, end_s, close_paren_token);
2069 if (s == NULL)
2070 break;
2071 subelement->element.split.item = item;
2072 subelement->element.split.delim = delim;
2073 subelement->type = me_split;
2074 return (s);
2076 e_type = me_extract;
2078 fmt_string = s_strndup(begin_token, end_token - begin_token);
2079 if (fmt_string == NULL)
2080 break;
2081 if (!get_mapping_format(fmt_string, &base, &n, &numItems,
2082 e_type == me_print)) {
2083 free(fmt_string);
2084 break;
2086 free(fmt_string);
2088 if (numItems != 1 && e_type == me_extract) {
2089 p_error = numItems == 0 ?
2090 parse_not_enough_extract_items :
2091 parse_too_many_extract_items;
2092 break;
2093 } else if (numItems > 0 && e_type == me_print) {
2094 print_item = (__nis_mapping_item_t *)s_calloc(numItems,
2095 sizeof (__nis_mapping_item_t));
2096 if (print_item == NULL)
2097 break;
2100 if (e_type == me_print) {
2101 sub.element.print.numItems = numItems;
2102 sub.element.print.fmt = base;
2103 sub.element.print.item = print_item;
2104 s = get_print_sub_element(s, end_s, type, &sub);
2105 if (s == NULL)
2106 break;
2108 s = skip_token(s, end_s, close_paren_token);
2109 if (s == NULL)
2110 break;
2112 subelement->type = e_type;
2113 if (e_type == me_extract) {
2114 subelement->element.extract.fmt = base;
2115 subelement->element.extract.item = item;
2116 } else {
2117 subelement->type = me_print;
2118 subelement->element.print.fmt = base;
2119 subelement->element.print.numItems = numItems;
2120 subelement->element.print.item = print_item;
2121 subelement->element.print.doElide =
2122 sub.element.print.doElide;
2123 subelement->element.print.elide =
2124 sub.element.print.elide;
2126 if (p_error == no_parse_error)
2127 return (s);
2129 free_mapping_item(&item);
2130 if (base != NULL)
2131 free_mapping_format(base);
2132 if (print_item) {
2133 for (n = 0; n < numItems; n++)
2134 free_mapping_item(&print_item[n]);
2135 free(print_item);
2138 return (NULL);
2142 * FUNCTION: skip_get_dn
2144 * Get first token after dn
2146 * RETURN VALUE: NULL if error (not valid dn)
2147 * position of beginning next token after dn
2149 * INPUT: the attribute value
2152 const char *
2153 skip_get_dn(const char *dn, const char *end)
2155 size_t len = 0;
2156 bool_t in_quote = FALSE;
2157 bool_t goteq = FALSE;
2158 bool_t gotch = FALSE;
2159 bool_t done = FALSE;
2160 bool_t last_comma = FALSE;
2161 const char *last_dn = dn;
2163 while (!done) {
2164 dn += len;
2165 if (last_comma) {
2166 last_dn = dn;
2167 last_comma = FALSE;
2169 if (dn >= end)
2170 break;
2171 len = 1;
2172 switch (*dn) {
2173 case ESCAPE_CHAR:
2174 len = 2;
2175 gotch = TRUE;
2176 break;
2177 case DOUBLE_QUOTE_CHAR:
2178 in_quote = !in_quote;
2179 break;
2180 case QUESTION_MARK:
2181 case CLOSE_PAREN_CHAR:
2182 case COLON_CHAR:
2183 done = !in_quote;
2184 /* FALLTHRU */
2185 case SEMI_COLON_CHAR:
2186 case PLUS_SIGN:
2187 case COMMA_CHAR:
2188 if (!in_quote) {
2189 if (!goteq || !gotch)
2190 return (last_dn);
2191 goteq = FALSE;
2192 gotch = FALSE;
2193 if (*dn != PLUS_SIGN)
2194 last_dn = dn;
2195 last_comma = *dn == COMMA_CHAR;
2196 } else {
2197 gotch = TRUE;
2199 break;
2200 case EQUAL_CHAR:
2201 if (!in_quote) {
2202 if (!gotch || goteq)
2203 return (NULL);
2204 goteq = TRUE;
2205 gotch = FALSE;
2206 } else {
2207 gotch = TRUE;
2209 break;
2210 default:
2211 if (!is_whitespace(*dn))
2212 gotch = TRUE;
2213 break;
2217 if (dn == end) {
2218 if (!in_quote && goteq && gotch)
2219 last_dn = dn;
2222 return (last_dn);
2226 * FUNCTION: get_ldap_filter_element
2228 * Get an ldap filter element for a given string
2230 * RETURN VALUE: NULL if error
2231 * __nis_mapping_element_t if success
2233 * INPUT: the string to parse
2236 static __nis_mapping_element_t *
2237 get_ldap_filter_element(
2238 const char *s,
2239 const char *end_s
2242 token_type t;
2243 const char *begin_token;
2244 const char *end_token;
2245 char *format_str;
2246 __nis_mapping_element_t *e = NULL;
2248 begin_token = s;
2249 end_token = end_s;
2250 s = get_next_token(&begin_token, &end_token, &t);
2251 if (s == NULL || t != open_paren_token)
2252 return (NULL);
2254 begin_token = s;
2255 end_token = end_s;
2256 s = get_next_token(&begin_token, &end_token, &t);
2257 if (s == NULL || t != quoted_string_token)
2258 return (NULL);
2260 format_str = s_strndup(begin_token, end_token - begin_token);
2261 if (format_str == NULL)
2262 return (NULL);
2263 e = (__nis_mapping_element_t *)
2264 s_calloc(1, sizeof (__nis_mapping_element_t));
2265 if (e != NULL) {
2266 (void) get_print_mapping_element(s, end_s,
2267 format_str, e, mit_nisplus);
2268 if (p_error != no_parse_error) {
2269 free_mapping_element(e);
2270 e = NULL;
2273 free(format_str);
2274 return (e);
2278 * FUNCTION: get_search_triple
2280 * Get the search triple or if NULL determine if valid
2282 * RETURN VALUE: NULL if error
2283 * position of beginning next token after
2284 * search triple
2286 * INPUT: the attribute value
2289 const char *
2290 get_search_triple(
2291 const char *s,
2292 const char *end_s,
2293 __nis_search_triple_t *triple
2296 const char *begin_token;
2297 const char *end_token;
2298 char *search_base = NULL;
2299 int scope = LDAP_SCOPE_ONELEVEL;
2300 char *filter = NULL;
2301 const char *s1;
2302 __nis_mapping_element_t
2303 *element = NULL;
2306 * The form of the searchTriple is assumed to be as follows:
2307 * searchTriple = [baseDN] ["?" [scope] ["?" [filter]]]
2308 * baseDN = Base DN for search
2309 * scope = "base" | "one" | "sub"
2310 * filter = LDAP search filter
2312 for (; p_error == no_parse_error; ) {
2313 while (s < end_s && is_whitespace(*s))
2314 s++;
2315 if (s == end_s)
2316 break;
2318 if (!IS_TERMINAL_CHAR(*s)) {
2319 begin_token = s;
2320 s = skip_get_dn(begin_token, end_s);
2321 if (s == NULL) {
2322 p_error = parse_invalid_dn;
2323 break;
2325 if (triple != NULL) {
2326 search_base = s_strndup(begin_token,
2327 s - begin_token);
2328 if (search_base == NULL)
2329 break;
2331 while (s < end_s && is_whitespace(*s))
2332 s++;
2333 if (s == end_s)
2334 break;
2337 if (!IS_TERMINAL_CHAR(*s)) {
2338 p_error = parse_bad_ldap_item_format;
2339 break;
2341 if (*s != QUESTION_MARK)
2342 break;
2344 s++;
2345 while (s < end_s && is_whitespace(*s))
2346 s++;
2347 if (s == end_s)
2348 break;
2350 /* base, one, or sub, or empty value */
2351 if (!IS_TERMINAL_CHAR(*s)) {
2352 if ((s1 = skip_string("base", s, end_s - s)) != NULL) {
2353 scope = LDAP_SCOPE_BASE;
2354 } else if ((s1 = skip_string("one", s, end_s - s)) !=
2355 NULL) {
2356 scope = LDAP_SCOPE_ONELEVEL;
2357 } else if ((s1 = skip_string("sub", s, end_s - s)) !=
2358 NULL) {
2359 scope = LDAP_SCOPE_SUBTREE;
2360 } else if (s + 1 < end_s && *s != QUESTION_MARK) {
2361 p_error = parse_invalid_scope;
2362 break;
2364 if (s1 != NULL)
2365 s = s1;
2366 while (s < end_s && is_whitespace(*s))
2367 s++;
2370 if (s == end_s)
2371 break;
2372 if (*s != QUESTION_MARK)
2373 break;
2374 s++;
2375 while (s < end_s && is_whitespace(*s))
2376 s++;
2377 if (s == end_s || IS_TERMINAL_CHAR(*s))
2378 break;
2380 /* LDAP search filter */
2381 if (*s == OPEN_PAREN_CHAR) {
2382 begin_token = s;
2383 end_token = end_s;
2384 s = get_ldap_filter(&begin_token, &end_token);
2385 if (s == NULL)
2386 break;
2387 s = end_token;
2388 element = get_ldap_filter_element(begin_token, end_token);
2389 if (element != NULL)
2390 break;
2391 } else {
2392 begin_token = s;
2393 end_token = end_s;
2394 s = get_ava_list(&begin_token, &end_token, TRUE);
2395 if (s == NULL)
2396 break;
2397 s = end_token;
2399 if (triple != NULL)
2400 filter = s_strndup(begin_token, s - begin_token);
2401 if (p_error == no_parse_error)
2402 break;
2404 if (p_error == no_parse_error && triple != NULL) {
2405 triple->base = search_base;
2406 triple->scope = scope;
2407 triple->attrs = filter;
2408 triple->element = element;
2409 element = NULL;
2410 filter = NULL;
2411 search_base = NULL;
2414 free(search_base);
2415 free(filter);
2416 if (element != NULL) {
2417 free_mapping_element(element);
2418 free(element);
2420 return (p_error == no_parse_error ? s : NULL);
2424 * FUNCTION: get_mapping_format
2426 * Get the __nis_mapping_format_t from the string
2428 * RETURN VALUE: FALSE if error
2429 * TRUE if __nis_mapping_format_t returned
2431 * INPUT: the format string
2434 static bool_t
2435 get_mapping_format(
2436 const char *fmt_string,
2437 __nis_mapping_format_t **fmt,
2438 int *nfmt,
2439 int *numItems,
2440 bool_t print_mapping)
2442 const char *f = fmt_string;
2443 const char *ef;
2444 __nis_mapping_format_t *b;
2445 __nis_mapping_format_t *base = NULL;
2446 int n = 0;
2447 int nItems = 0;
2449 f = fmt_string;
2450 ef = f + strlen(f);
2451 base = (__nis_mapping_format_t *)
2452 s_calloc(1, sizeof (__nis_mapping_format_t));
2454 if (base == NULL)
2455 return (FALSE);
2456 base->type = mmt_begin;
2457 n++;
2459 for (;;) {
2460 b = (__nis_mapping_format_t *)s_realloc(
2461 base, (n + 1) * sizeof (__nis_mapping_format_t));
2463 if (b == NULL)
2464 break;
2465 base = b;
2466 base[n].type = mmt_end;
2467 if (f == ef) {
2468 if (nfmt)
2469 *nfmt = n + 1;
2470 *fmt = base;
2471 if (numItems)
2472 *numItems = nItems;
2473 return (TRUE);
2475 if (print_mapping)
2476 f = get_next_print_format_item(f, ef, &base[n]);
2477 else
2478 f = get_next_extract_format_item(f, ef, &base[n]);
2481 if (f == NULL)
2482 break;
2483 if (base[n].type == mmt_item ||
2484 base[n].type == mmt_berstring)
2485 nItems++;
2486 n++;
2488 if (base != NULL)
2489 free_mapping_format(base);
2490 return (FALSE);
2494 * FUNCTION: getIndex
2496 * Returns a string containing the index
2498 * RETURN VALUE: NULL if error
2499 * a string containing the index
2501 * INPUT: attribute containing the index
2504 static char *
2505 getIndex(const char **s_cur, const char *s_end)
2507 const char *s = *s_cur + 1;
2508 const char *s1;
2509 char *s_index;
2510 char *s_index1;
2511 char *s_index_end;
2512 int n_brackets = 1;
2513 bool_t in_quotes = FALSE;
2514 char *index = NULL;
2516 while (s < s_end && is_whitespace(*s))
2517 s++;
2518 for (s1 = s; s1 < s_end; s1++) {
2519 if (*s1 == ESCAPE_CHAR)
2520 s1++;
2521 else if (*s1 == DOUBLE_QUOTE_CHAR) {
2522 in_quotes = !in_quotes;
2523 } else if (in_quotes)
2525 else if (*s1 == CLOSE_BRACKET) {
2526 if (--n_brackets == 0)
2527 break;
2528 } else if (*s1 == OPEN_BRACKET)
2529 n_brackets++;
2532 if (n_brackets == 0) {
2533 index = s_strndup(s, s1 - s);
2534 if (index != NULL) {
2535 s_index_end = index + (s1 - s);
2536 s_index1 = index;
2537 for (s_index = index; s_index < s_index_end;
2538 s_index++) {
2539 if (*s_index == ESCAPE_CHAR) {
2540 *s_index1++ = *s_index++;
2541 } else if (*s_index == DOUBLE_QUOTE_CHAR) {
2542 in_quotes = !in_quotes;
2543 } else if (!in_quotes &&
2544 is_whitespace(*s_index)) {
2545 continue;
2547 *s_index1++ = *s_index;
2549 *s_index1 = *s_index;
2551 s = s1 + 1;
2553 while (s < s_end && is_whitespace(*s))
2554 s++;
2555 *s_cur = s;
2557 } else
2558 p_error = parse_mismatched_brackets;
2560 return (index);
2564 * FUNCTION: parse_index
2566 * Parse attribute string to get __nis_index_t
2568 * RETURN VALUE: FALSE if error
2569 * TRUE if __nis_index_t returned
2571 * INPUT: the attribute value to parse
2574 bool_t
2575 parse_index(const char *s, const char *end_s, __nis_index_t *index)
2577 const char *begin_token;
2578 const char *end_token;
2579 char *name_str = NULL;
2580 char **name;
2581 char *fmt_string = NULL;
2582 __nis_mapping_format_t *v = NULL;
2583 __nis_mapping_format_t **value;
2584 token_type t;
2585 int n = 0;
2587 if (index != NULL)
2588 (void) memset(index, 0, sizeof (*index));
2590 while (s < end_s) {
2591 if (n > 0) {
2592 s = skip_token(s, end_s, comma_token);
2593 if (s == NULL) {
2594 p_error = parse_bad_index_format;
2595 break;
2598 begin_token = s;
2599 end_token = end_s;
2600 s = get_next_token(&begin_token, &end_token, &t);
2601 if (s == NULL)
2602 break;
2603 if (t != string_token) {
2604 p_error = parse_bad_index_format;
2605 break;
2607 s = skip_token(s, end_s, equal_token);
2608 if (s == NULL) {
2609 p_error = parse_bad_index_format;
2610 break;
2612 if (index != NULL) {
2613 name_str = s_strndup_esc(begin_token,
2614 end_token - begin_token);
2615 if (name_str == NULL)
2616 break;
2618 begin_token = s;
2619 end_token = end_s;
2620 s = get_next_token(&begin_token, &end_token, &t);
2621 if (s == NULL)
2622 break;
2623 if (t != string_token && t != quoted_string_token) {
2624 p_error = parse_bad_index_format;
2625 break;
2627 fmt_string = s_strndup(begin_token, end_token - begin_token);
2628 if (fmt_string == NULL)
2629 break;
2630 if (!get_mapping_format(fmt_string, &v, NULL, NULL, FALSE))
2631 break;
2632 free(fmt_string);
2633 fmt_string = NULL;
2634 if (index != NULL) {
2635 name = s_realloc(index->name,
2636 (n + 1) * sizeof (char *));
2637 if (name == NULL)
2638 break;
2639 value = s_realloc(index->value,
2640 (n + 1) * sizeof (__nis_mapping_format_t *));
2641 if (value == NULL)
2642 break;
2643 name[n] = name_str;
2644 name_str = NULL;
2645 value[n] = v;
2646 v = NULL;
2647 index->numIndexes = ++n;
2648 index->name = name;
2649 index->value = value;
2650 } else if (v != NULL) {
2651 free_mapping_format(v);
2652 v = NULL;
2655 if (p_error != no_parse_error) {
2656 free(name_str);
2657 if (v != NULL)
2658 free_mapping_format(v);
2659 free(fmt_string);
2660 if (index != NULL)
2661 free_index(index);
2663 return (p_error != no_parse_error);
2667 * FUNCTION: get_deleteDisp
2669 * Parse deleteDisp. Sets p_error if an error occurred.
2671 * RETURN VALUE: TRUE on success
2672 * FAILURE on failure
2674 * INPUT: begin and end of string and __nis_object_dn_t
2677 static bool_t
2678 get_deleteDisp(const char *s_begin, const char *s_end,
2679 __nis_object_dn_t *obj_dn)
2682 * deleteDisp: "always" | perDbId | "never"
2683 * perDbId: "dbid" "=" delDatabaseId
2686 if (same_string("always", s_begin, s_end - s_begin)) {
2687 obj_dn->delDisp = dd_always;
2688 } else if (same_string("never", s_begin, s_end - s_begin)) {
2689 obj_dn->delDisp = dd_never;
2690 } else if ((s_begin = skip_string("dbid", s_begin, s_end - s_begin))
2691 != NULL) {
2692 obj_dn->delDisp = dd_perDbId;
2693 while (s_begin < s_end && is_whitespace(*s_begin))
2694 s_begin++;
2695 if (s_begin == s_end || *s_begin != EQUAL_CHAR) {
2696 p_error = parse_object_dn_syntax_error;
2697 } else {
2698 s_begin++;
2699 while (s_begin < s_end && is_whitespace(*s_begin))
2700 s_begin++;
2701 while (s_begin < s_end && is_whitespace(s_end[-1]))
2702 s_end--;
2703 if (s_begin == s_end) {
2704 p_error = parse_object_dn_syntax_error;
2705 } else {
2706 obj_dn->dbIdName =
2707 s_strndup(s_begin, s_end - s_begin);
2710 } else {
2711 p_error = parse_object_dn_syntax_error;
2713 return (p_error == no_parse_error);