5910 libnisdb won't build with modern GCC
[unleashed.git] / usr / src / lib / libnisdb / nis_parse_ldap_map.c
blob7874ec3fdb3591d9a52e6933ad067e2298102d53
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 = NULL;
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 if (fmt_string != NULL)
1345 free(fmt_string);
1346 if (base != NULL)
1347 free_mapping_format(base);
1349 return (NULL);
1353 * FUNCTION: get_lhs_paren_item
1355 * Parse left hand side of mapping rule attribute in case of
1356 * (item1, ..., item-n)
1358 * RETURN VALUE: NULL if error
1359 * position of beginning rhs
1361 * INPUT: the attribute value and mapping rule type
1364 static const char *
1365 get_lhs_paren_item(
1366 const char *s,
1367 const char *end_s,
1368 __nis_mapping_rlhs_t *lhs,
1369 __nis_mapping_item_type_t item_type)
1371 token_type t;
1372 const char *begin_token;
1373 const char *end_token;
1374 __nis_mapping_element_t *e = NULL;
1375 int n = 0;
1376 int i;
1379 * "(" namespec *("," namespec) ")"
1382 for (;;) {
1383 e = (__nis_mapping_element_t *)s_realloc(e, (n + 1) *
1384 sizeof (__nis_mapping_element_t));
1385 if (e == NULL)
1386 break;
1388 s = get_mapping_item(s, end_s, &e[n].element.item,
1389 item_type);
1390 if (s == NULL)
1391 break;
1392 e[n].type = me_item;
1393 n++;
1395 begin_token = s;
1396 end_token = end_s;
1397 s = get_next_token(&begin_token, &end_token, &t);
1398 if (s != NULL && t == close_paren_token) {
1399 lhs->numElements = n;
1400 if (n == 1)
1401 e[0].element.item.repeat = TRUE;
1402 lhs->element = e;
1403 return (s);
1405 if (s == NULL || t != comma_token) {
1406 p_error = parse_comma_expected_error;
1407 break;
1410 for (i = 0; i < n; i++)
1411 free_mapping_element(&e[i]);
1412 if (e != NULL)
1413 free(e);
1414 return (NULL);
1418 * FUNCTION: get_rhs
1420 * Parse right hand side of mapping rule attribute
1422 * RETURN VALUE: NULL if error
1423 * position of beginning next mapping rule
1425 * INPUT: the attribute value and mapping rule type
1428 static const char *
1429 get_rhs(
1430 const char *s,
1431 const char *end_s,
1432 __nis_mapping_rlhs_t *rhs,
1433 __nis_mapping_item_type_t item_type)
1436 * This handles the following cases:
1437 * name me_item
1438 * (name) me_item
1439 * (fmt, name-list) me_print
1440 * (item, fmt) me_extract
1443 token_type t;
1444 const char *begin_token;
1445 const char *end_token;
1446 char *str = NULL;
1447 __nis_mapping_format_t *fmt = NULL;
1448 __nis_mapping_element_t *e = NULL;
1449 __nis_mapping_item_t item;
1450 int n;
1452 (void) memset(&item, 0, sizeof (item));
1454 for (; p_error == no_parse_error; ) {
1455 begin_token = s;
1456 end_token = end_s;
1457 s = get_next_token(&begin_token, &end_token, &t);
1458 if (s == NULL)
1459 break;
1461 e = (__nis_mapping_element_t *)
1462 s_calloc(1, sizeof (__nis_mapping_element_t));
1463 if (e == NULL)
1464 break;
1466 if (t == string_token) {
1467 s = get_mapping_item(begin_token, end_s,
1468 &e->element.item, item_type);
1469 } else if (t == open_paren_token) {
1470 begin_token = s;
1471 end_token = end_s;
1472 s = get_next_token(&begin_token, &end_token, &t);
1473 if (s == NULL)
1474 break;
1475 if (t == string_token) {
1476 /* (item, fmt) - me_extract */
1477 /* (item, "c") - me_split */
1478 s = get_mapping_item(begin_token, end_s,
1479 &item, item_type);
1480 if (s == NULL)
1481 break;
1482 begin_token = s;
1483 end_token = end_s;
1484 s = get_next_token(&begin_token, &end_token,
1485 &t);
1486 if (s == NULL)
1487 break;
1488 else if (t == close_paren_token) {
1489 item.repeat = TRUE;
1490 e->element.item = item;
1491 e->type = me_item;
1492 rhs->numElements = 1;
1493 rhs->element = e;
1494 return (s);
1495 } else if (t != comma_token) {
1496 p_error = parse_comma_expected_error;
1497 break;
1500 begin_token = s;
1501 end_token = end_s;
1502 s = get_next_token(&begin_token, &end_token,
1503 &t);
1504 if (s == NULL || t != quoted_string_token) {
1505 p_error =
1506 parse_format_string_expected_error;
1507 break;
1510 if (end_token == begin_token + 1 ||
1511 (*begin_token == ESCAPE_CHAR &&
1512 end_token == begin_token + 2)) {
1513 e->type = me_split;
1514 e->element.split.item = item;
1515 e->element.split.delim = *begin_token;
1516 } else {
1517 str = s_strndup(begin_token,
1518 end_token - begin_token);
1519 if (str == NULL)
1520 break;
1521 if (!get_mapping_format(str, &fmt,
1522 NULL, &n, FALSE))
1523 break;
1524 free(str);
1525 str = NULL;
1526 if (n != 1) {
1527 p_error =
1528 parse_bad_extract_format_spec;
1529 break;
1531 e->type = me_extract;
1532 e->element.extract.item = item;
1533 e->element.extract.fmt = fmt;
1535 s = skip_token(s, end_s, close_paren_token);
1536 } else if (t == quoted_string_token) {
1537 /* (fmt, name-list) - me_print */
1538 str = s_strndup(begin_token,
1539 end_token - begin_token);
1540 if (str == NULL)
1541 break;
1543 s = get_print_mapping_element(s, end_s,
1544 str, e, item_type);
1545 free(str);
1546 str = NULL;
1547 } else {
1548 p_error = parse_start_rhs_unrecognized;
1549 break;
1551 } else {
1552 p_error = parse_start_rhs_unrecognized;
1553 break;
1555 if (s == NULL)
1556 break;
1557 rhs->numElements = 1;
1558 rhs->element = e;
1559 if (p_error == no_parse_error)
1560 return (s);
1562 if (str)
1563 free(str);
1564 if (fmt != NULL)
1565 free_mapping_format(fmt);
1566 if (e != NULL)
1567 free_mapping_element(e);
1568 free_mapping_item(&item);
1570 return (NULL);
1574 * FUNCTION: get_print_mapping_element
1576 * Parse a print mapping rule attribute in case of the form
1577 * (fmt, name-list)
1579 * RETURN VALUE: NULL if error
1580 * position of beginning next mapping rule
1582 * INPUT: the attribute value and mapping rule type
1585 static const char *
1586 get_print_mapping_element(
1587 const char *s,
1588 const char *end_s,
1589 char *fmt_string,
1590 __nis_mapping_element_t *e,
1591 __nis_mapping_item_type_t item_type)
1593 token_type t;
1594 const char *begin_token;
1595 const char *end_token;
1596 char elide;
1597 bool_t doElide;
1598 __nis_mapping_format_t *base = NULL;
1599 __nis_mapping_sub_element_t *subElement = NULL;
1600 int n = 0;
1601 int nSub = 0;
1602 int numSubElements;
1604 for (; p_error == no_parse_error; ) {
1605 if (!get_mapping_format(fmt_string, &base, &n,
1606 &numSubElements, TRUE))
1607 break;
1608 subElement = (__nis_mapping_sub_element_t *)
1609 s_calloc(numSubElements,
1610 sizeof (__nis_mapping_sub_element_t));
1611 if (subElement == NULL)
1612 break;
1613 for (n = 0; base[n].type != mmt_end; n++) {
1614 if (base[n].type != mmt_item &&
1615 base[n].type != mmt_berstring) {
1616 if (base[n].type == mmt_berstring_null)
1617 base[n].type = mmt_berstring;
1618 continue;
1620 if (nSub < numSubElements) {
1621 s = skip_token(s, end_s, comma_token);
1622 if (s == NULL) {
1623 p_error = parse_bad_print_format;
1624 break;
1628 /* namelist may have parens around it */
1629 s = get_subElement(s, end_s, &subElement[nSub],
1630 item_type);
1631 if (s == NULL)
1632 break;
1633 nSub++;
1635 if (p_error != no_parse_error)
1636 break;
1638 begin_token = s;
1639 end_token = end_s;
1640 s = get_next_token(&begin_token, &end_token, &t);
1641 if (s == NULL || t == no_token) {
1642 p_error = parse_unexpected_data_end_rule;
1643 break;
1644 } else if (t == close_paren_token) {
1645 doElide = FALSE;
1646 elide = '\0';
1647 } else if (t == comma_token) {
1648 begin_token = s;
1649 end_token = end_s;
1650 s = get_next_token(&begin_token, &end_token, &t);
1651 if (s != NULL && t == quoted_string_token &&
1652 (end_token == begin_token + 1 ||
1653 (*begin_token == ESCAPE_CHAR &&
1654 end_token == begin_token + 2))) {
1655 if (numSubElements != 1 ||
1656 subElement->type == me_extract ||
1657 subElement->type == me_split) {
1658 p_error = parse_cannot_elide;
1659 break;
1661 if (subElement->type == me_item &&
1662 !subElement->element.item.repeat) {
1663 p_error = parse_cannot_elide;
1664 break;
1666 elide = *begin_token;
1667 doElide = TRUE;
1669 } else {
1670 p_error = parse_bad_elide_char;
1671 break;
1673 s = skip_token(s, end_s, close_paren_token);
1674 if (s == NULL)
1675 break;
1678 e->type = me_print;
1679 e->element.print.fmt = base;
1680 e->element.print.numSubElements = numSubElements;
1681 e->element.print.subElement = subElement;
1682 e->element.print.elide = elide;
1683 e->element.print.doElide = doElide;
1685 if (p_error == no_parse_error)
1686 return (s);
1688 if (base)
1689 free_mapping_format(base);
1690 if (subElement != NULL) {
1691 for (n = 0; n < numSubElements; n++)
1692 free_mapping_sub_element(&subElement[n]);
1693 free(subElement);
1696 return (NULL);
1700 * FUNCTION: get_mapping_item
1702 * Parse attribute string to get mapping item
1704 * RETURN VALUE: NULL if error
1705 * position of beginning next token after item
1707 * INPUT: the attribute value and mapping rule type
1710 static const char *
1711 get_mapping_item(
1712 const char *s,
1713 const char *end_s,
1714 __nis_mapping_item_t *item,
1715 __nis_mapping_item_type_t type)
1717 token_type t;
1718 const char *begin_token;
1719 const char *end_token;
1720 char *name = NULL;
1721 char *index_string;
1722 const char *s_sav;
1723 int len;
1725 (void) memset(item, 0, sizeof (*item));
1728 * A namepec is defined as follows:
1729 * namespec = ["ldap:"] attrspec [searchTriple] |
1730 * ["nis+:"] colspec [objectspec]
1732 * The form of the item is assumed to be as follows:
1733 * ["ldap:"] attrspec [searchTriple]
1734 * attrspec = attribute | "(" attribute ")"
1735 * searchTriple = ":" [baseDN] ["?" [scope] ["?" [filter]]]
1736 * baseDN = Base DN for search
1737 * scope = "base" | "one" | "sub"
1738 * filter = LDAP search filter
1740 * The form of the objectspec is as follows:
1741 * ["nis+:"] colspec [objectspec]
1742 * objectspec = objectname | "[" indexlist "]" tablename
1743 * objectname = The name of a NIS+ object
1744 * tablename = The name of a NIS+ table
1745 * indexlist = colspec ["," colspec]
1746 * colspec = colname "=" colvalue
1747 * colname = The name of a column in the table
1748 * colvalue = colvaluestring | \" colvaluestring \"
1751 for (; p_error == no_parse_error; ) {
1752 while (s < end_s && is_whitespace(*s))
1753 s++;
1754 len = end_s - s;
1755 if (yp2ldap) {
1756 if ((begin_token = skip_string("ldap:", s,
1757 len)) != NULL) {
1758 item->type = mit_ldap;
1759 } else if ((begin_token = skip_string("yp:", s,
1760 len)) != NULL) {
1761 item->type = mit_nisplus;
1762 } else {
1763 item->type = type;
1764 begin_token = s;
1766 } else {
1767 if ((begin_token = skip_string("ldap:", s,
1768 len)) != NULL) {
1769 item->type = mit_ldap;
1770 } else if ((begin_token = skip_string("nis+:", s,
1771 len)) != NULL) {
1772 item->type = mit_nisplus;
1773 } else if ((begin_token = skip_string("nisplus:", s,
1774 len)) != NULL) {
1775 item->type = mit_nisplus;
1776 } else {
1777 item->type = type;
1778 begin_token = s;
1782 end_token = end_s;
1783 s = get_next_token(&begin_token, &end_token, &t);
1784 if (s == NULL || t != string_token) {
1785 p_error = parse_bad_item_format;
1786 break;
1789 item->name = s_strndup_esc(begin_token,
1790 end_token - begin_token);
1791 if (item->name == NULL)
1792 break;
1793 if (item->type == mit_ldap) {
1794 item->searchSpec.triple.scope = LDAP_SCOPE_UNKNOWN;
1795 begin_token = s;
1796 end_token = end_s;
1797 s_sav = s;
1798 s = get_next_token(&begin_token, &end_token, &t);
1799 if (s != NULL && t == colon_token) {
1800 s = get_search_triple(s, end_s,
1801 &item->searchSpec.triple);
1802 if (s == NULL)
1803 break;
1804 } else
1805 s = s_sav;
1806 } else if (item->type == mit_nisplus) {
1807 while (s < end_s && is_whitespace(*s))
1808 s++;
1810 if (s < end_s && *s == OPEN_BRACKET) {
1811 index_string = getIndex(&s, end_s);
1812 if (index_string == NULL)
1813 break;
1814 (void) parse_index(index_string,
1815 index_string + strlen(index_string),
1816 &item->searchSpec.obj.index);
1817 free(index_string);
1818 if (p_error != no_parse_error)
1819 break;
1821 s_sav = s;
1822 begin_token = s;
1823 end_token = end_s;
1824 s = get_next_token(&begin_token, &end_token, &t);
1825 if (s != NULL && t == string_token) {
1826 name = s_strndup_esc(begin_token,
1827 end_token - begin_token);
1828 if (name == NULL)
1829 break;
1830 item->searchSpec.obj.name = name;
1831 } else
1832 s = s_sav;
1834 if (p_error == no_parse_error)
1835 return (s);
1837 free_mapping_item(item);
1838 (void) memset(item, 0, sizeof (*item));
1839 if (name == NULL)
1840 free(name);
1841 return (NULL);
1844 static const char *
1845 get_print_sub_element(const char *s,
1846 const char *end_s,
1847 __nis_mapping_item_type_t type,
1848 __nis_mapping_sub_element_t *sub)
1851 int k;
1852 int n;
1853 const char *begin_token;
1854 const char *end_token;
1855 token_type t;
1856 __nis_mapping_format_t *base;
1857 __nis_mapping_item_t *print_item;
1859 k = 0;
1860 base = sub->element.print.fmt;
1861 print_item = sub->element.print.item;
1862 sub->element.print.doElide = FALSE;
1863 sub->element.print.elide = '\0';
1865 for (n = 0; base[n].type != mmt_end; n++) {
1866 if (base[n].type != mmt_item && base[n].type != mmt_berstring) {
1867 if (base[n].type == mmt_berstring_null)
1868 base[n].type = mmt_berstring;
1869 continue;
1871 s = skip_token(s, end_s, comma_token);
1872 if (s == NULL) {
1873 p_error = parse_bad_print_format;
1874 break;
1877 begin_token = s;
1878 end_token = end_s;
1879 s = get_next_token(&begin_token, &end_token, &t);
1880 if (s == NULL)
1881 break;
1883 * Determine if of the form
1884 * ("fmt", (item), "delim") or
1885 * ("fmt", item1, item2, ..., item n)
1887 if (t == open_paren_token) {
1888 if (sub->element.print.numItems != 1) {
1889 p_error = parse_invalid_print_arg;
1890 break;
1892 s = get_mapping_item(s, end_s, &print_item[k++], type);
1893 s = skip_token(s, end_s, close_paren_token);
1894 s = skip_token(s, end_s, comma_token);
1895 if (s == NULL) {
1896 p_error = parse_bad_print_format;
1897 break;
1899 begin_token = s;
1900 end_token = end_s;
1901 s = get_next_token(&begin_token, &end_token, &t);
1902 if (s == NULL)
1903 break;
1904 if (t != quoted_string_token ||
1905 begin_token + 1 != end_token) {
1906 p_error = parse_bad_elide_char;
1907 break;
1909 sub->element.print.elide = *begin_token;
1910 sub->element.print.doElide = TRUE;
1911 print_item[0].repeat = TRUE;
1912 break;
1914 s = get_mapping_item(begin_token, end_s,
1915 &print_item[k++], type);
1916 if (s == NULL)
1917 break;
1919 if (p_error != no_parse_error)
1920 break;
1923 return (p_error == no_parse_error ? s : NULL);
1927 * FUNCTION: get_subElement
1929 * Parse attribute string to get sub element item
1931 * RETURN VALUE: NULL if error
1932 * position of beginning next token after item
1934 * INPUT: the attribute value and mapping rule type
1937 static const char *
1938 get_subElement(
1939 const char *s,
1940 const char *end_s,
1941 __nis_mapping_sub_element_t *subelement,
1942 __nis_mapping_item_type_t type)
1944 token_type t;
1945 const char *begin_token;
1946 const char *end_token;
1947 char *fmt_string;
1948 __nis_mapping_item_t item;
1949 __nis_mapping_element_type_t e_type;
1950 __nis_mapping_item_t *print_item = NULL;
1951 __nis_mapping_format_t *base = NULL;
1952 int n = 0;
1953 int numItems = 0;
1954 unsigned char delim;
1955 __nis_mapping_sub_element_t sub;
1958 * What is the form of we are expecting here
1959 * item me_item
1960 * (item) me_item
1961 * ("fmt", item1, item2, ..., item n) me_print
1962 * ("fmt", (item), "elide") me_print
1963 * (name, "delim") me_split
1964 * (item, "fmt") me_extract
1966 (void) memset(&item, 0, sizeof (item));
1968 for (; p_error == no_parse_error; ) {
1969 begin_token = s;
1970 end_token = end_s;
1971 s = get_next_token(&begin_token, &end_token, &t);
1972 if (s == NULL)
1973 break;
1974 if (t == string_token) { /* me_item */
1975 s = get_mapping_item(begin_token, end_s,
1976 &subelement->element.item, type);
1977 if (s == NULL)
1978 break;
1979 subelement->type = me_item;
1980 return (s);
1981 } else if (t != open_paren_token) {
1982 p_error = parse_item_expected_error;
1983 break;
1986 begin_token = s;
1987 end_token = end_s;
1988 s = get_next_token(&begin_token, &end_token, &t);
1989 if (s == NULL)
1990 break;
1992 if (t != string_token && t != quoted_string_token) {
1993 p_error = parse_item_expected_error;
1994 break;
1996 e_type = me_print;
1997 if (t == string_token) {
1998 /* me_item, me_extract or me_split */
1999 s = get_mapping_item(begin_token, end_s, &item, type);
2000 if (s == NULL)
2001 break;
2003 begin_token = s;
2004 end_token = end_s;
2005 s = get_next_token(&begin_token, &end_token, &t);
2006 if (s == NULL) {
2007 p_error = parse_unexpected_data_end_rule;
2008 break;
2009 } else if (t == close_paren_token) {
2010 subelement->type = me_item;
2011 item.repeat = TRUE;
2012 subelement->element.item = item;
2013 if (yp2ldap) {
2014 while (s < end_s && is_whitespace(*s))
2015 s++;
2016 if (s == end_s) {
2017 p_error =
2018 parse_unexpected_data_end_rule;
2019 break;
2021 if (*s == DASH_CHAR && s < end_s) {
2022 s++;
2023 while (s < end_s &&
2024 is_whitespace(*s))
2025 s++;
2026 begin_token = s;
2027 end_token = end_s;
2029 subelement->element.item.exItem
2031 (__nis_mapping_item_t *)
2032 s_malloc(sizeof (__nis_mapping_item_t));
2033 if (!subelement->
2034 element.item.exItem)
2035 break;
2036 s = get_mapping_item(s, end_s,
2037 subelement->
2038 element.item.exItem,
2039 type);
2040 if (s == NULL) {
2041 p_error =
2042 parse_internal_error;
2043 free_mapping_item(
2044 subelement->
2045 element.item.exItem);
2046 subelement->
2047 element.item.exItem =
2048 NULL;
2049 break;
2053 return (s);
2054 } else if (t != comma_token) {
2055 p_error = parse_comma_expected_error;
2056 break;
2059 begin_token = s;
2060 end_token = end_s;
2061 s = get_next_token(&begin_token, &end_token, &t);
2062 if (s == NULL || t != quoted_string_token) {
2063 p_error = parse_format_string_expected_error;
2064 break;
2066 if (end_token == begin_token + 1 ||
2067 (*begin_token == ESCAPE_CHAR &&
2068 end_token == begin_token + 2)) {
2069 /* me_split */
2070 delim = (unsigned char)end_token[-1];
2071 s = skip_token(s, end_s, close_paren_token);
2072 if (s == NULL)
2073 break;
2074 subelement->element.split.item = item;
2075 subelement->element.split.delim = delim;
2076 subelement->type = me_split;
2077 return (s);
2079 e_type = me_extract;
2081 fmt_string = s_strndup(begin_token, end_token - begin_token);
2082 if (fmt_string == NULL)
2083 break;
2084 if (!get_mapping_format(fmt_string, &base, &n, &numItems,
2085 e_type == me_print)) {
2086 free(fmt_string);
2087 break;
2089 free(fmt_string);
2091 if (numItems != 1 && e_type == me_extract) {
2092 p_error = numItems == 0 ?
2093 parse_not_enough_extract_items :
2094 parse_too_many_extract_items;
2095 break;
2096 } else if (numItems > 0 && e_type == me_print) {
2097 print_item = (__nis_mapping_item_t *)s_calloc(numItems,
2098 sizeof (__nis_mapping_item_t));
2099 if (print_item == NULL)
2100 break;
2103 if (e_type == me_print) {
2104 sub.element.print.numItems = numItems;
2105 sub.element.print.fmt = base;
2106 sub.element.print.item = print_item;
2107 s = get_print_sub_element(s, end_s, type, &sub);
2108 if (s == NULL)
2109 break;
2111 s = skip_token(s, end_s, close_paren_token);
2112 if (s == NULL)
2113 break;
2115 subelement->type = e_type;
2116 if (e_type == me_extract) {
2117 subelement->element.extract.fmt = base;
2118 subelement->element.extract.item = item;
2119 } else {
2120 subelement->type = me_print;
2121 subelement->element.print.fmt = base;
2122 subelement->element.print.numItems = numItems;
2123 subelement->element.print.item = print_item;
2124 subelement->element.print.doElide =
2125 sub.element.print.doElide;
2126 subelement->element.print.elide =
2127 sub.element.print.elide;
2129 if (p_error == no_parse_error)
2130 return (s);
2132 free_mapping_item(&item);
2133 if (base != NULL)
2134 free_mapping_format(base);
2135 if (print_item) {
2136 for (n = 0; n < numItems; n++)
2137 free_mapping_item(&print_item[n]);
2138 free(print_item);
2141 return (NULL);
2145 * FUNCTION: skip_get_dn
2147 * Get first token after dn
2149 * RETURN VALUE: NULL if error (not valid dn)
2150 * position of beginning next token after dn
2152 * INPUT: the attribute value
2155 const char *
2156 skip_get_dn(const char *dn, const char *end)
2158 size_t len = 0;
2159 bool_t in_quote = FALSE;
2160 bool_t goteq = FALSE;
2161 bool_t gotch = FALSE;
2162 bool_t done = FALSE;
2163 bool_t last_comma = FALSE;
2164 const char *last_dn = dn;
2166 while (!done) {
2167 dn += len;
2168 if (last_comma) {
2169 last_dn = dn;
2170 last_comma = FALSE;
2172 if (dn >= end)
2173 break;
2174 len = 1;
2175 switch (*dn) {
2176 case ESCAPE_CHAR:
2177 len = 2;
2178 gotch = TRUE;
2179 break;
2180 case DOUBLE_QUOTE_CHAR:
2181 in_quote = !in_quote;
2182 break;
2183 case QUESTION_MARK:
2184 case CLOSE_PAREN_CHAR:
2185 case COLON_CHAR:
2186 done = !in_quote;
2187 /* FALLTHRU */
2188 case SEMI_COLON_CHAR:
2189 case PLUS_SIGN:
2190 case COMMA_CHAR:
2191 if (!in_quote) {
2192 if (!goteq || !gotch)
2193 return (last_dn);
2194 goteq = FALSE;
2195 gotch = FALSE;
2196 if (*dn != PLUS_SIGN)
2197 last_dn = dn;
2198 last_comma = *dn == COMMA_CHAR;
2199 } else {
2200 gotch = TRUE;
2202 break;
2203 case EQUAL_CHAR:
2204 if (!in_quote) {
2205 if (!gotch || goteq)
2206 return (NULL);
2207 goteq = TRUE;
2208 gotch = FALSE;
2209 } else {
2210 gotch = TRUE;
2212 break;
2213 default:
2214 if (!is_whitespace(*dn))
2215 gotch = TRUE;
2216 break;
2220 if (dn == end) {
2221 if (!in_quote && goteq && gotch)
2222 last_dn = dn;
2225 return (last_dn);
2229 * FUNCTION: get_ldap_filter_element
2231 * Get an ldap filter element for a given string
2233 * RETURN VALUE: NULL if error
2234 * __nis_mapping_element_t if success
2236 * INPUT: the string to parse
2239 static __nis_mapping_element_t *
2240 get_ldap_filter_element(
2241 const char *s,
2242 const char *end_s
2245 token_type t;
2246 const char *begin_token;
2247 const char *end_token;
2248 char *format_str;
2249 __nis_mapping_element_t *e = NULL;
2251 begin_token = s;
2252 end_token = end_s;
2253 s = get_next_token(&begin_token, &end_token, &t);
2254 if (s == NULL || t != open_paren_token)
2255 return (NULL);
2257 begin_token = s;
2258 end_token = end_s;
2259 s = get_next_token(&begin_token, &end_token, &t);
2260 if (s == NULL || t != quoted_string_token)
2261 return (NULL);
2263 format_str = s_strndup(begin_token, end_token - begin_token);
2264 if (format_str == NULL)
2265 return (NULL);
2266 e = (__nis_mapping_element_t *)
2267 s_calloc(1, sizeof (__nis_mapping_element_t));
2268 if (e != NULL) {
2269 (void) get_print_mapping_element(s, end_s,
2270 format_str, e, mit_nisplus);
2271 if (p_error != no_parse_error) {
2272 free_mapping_element(e);
2273 e = NULL;
2276 free(format_str);
2277 return (e);
2281 * FUNCTION: get_search_triple
2283 * Get the search triple or if NULL determine if valid
2285 * RETURN VALUE: NULL if error
2286 * position of beginning next token after
2287 * search triple
2289 * INPUT: the attribute value
2292 const char *
2293 get_search_triple(
2294 const char *s,
2295 const char *end_s,
2296 __nis_search_triple_t *triple
2299 const char *begin_token;
2300 const char *end_token;
2301 char *search_base = NULL;
2302 int scope = LDAP_SCOPE_ONELEVEL;
2303 char *filter = NULL;
2304 const char *s1;
2305 __nis_mapping_element_t
2306 *element = NULL;
2309 * The form of the searchTriple is assumed to be as follows:
2310 * searchTriple = [baseDN] ["?" [scope] ["?" [filter]]]
2311 * baseDN = Base DN for search
2312 * scope = "base" | "one" | "sub"
2313 * filter = LDAP search filter
2315 for (; p_error == no_parse_error; ) {
2316 while (s < end_s && is_whitespace(*s))
2317 s++;
2318 if (s == end_s)
2319 break;
2321 if (!IS_TERMINAL_CHAR(*s)) {
2322 begin_token = s;
2323 s = skip_get_dn(begin_token, end_s);
2324 if (s == NULL) {
2325 p_error = parse_invalid_dn;
2326 break;
2328 if (triple != NULL) {
2329 search_base = s_strndup(begin_token,
2330 s - begin_token);
2331 if (search_base == NULL)
2332 break;
2334 while (s < end_s && is_whitespace(*s))
2335 s++;
2336 if (s == end_s)
2337 break;
2340 if (!IS_TERMINAL_CHAR(*s)) {
2341 p_error = parse_bad_ldap_item_format;
2342 break;
2344 if (*s != QUESTION_MARK)
2345 break;
2347 s++;
2348 while (s < end_s && is_whitespace(*s))
2349 s++;
2350 if (s == end_s)
2351 break;
2353 /* base, one, or sub, or empty value */
2354 if (!IS_TERMINAL_CHAR(*s)) {
2355 if ((s1 = skip_string("base", s, end_s - s)) != NULL) {
2356 scope = LDAP_SCOPE_BASE;
2357 } else if ((s1 = skip_string("one", s, end_s - s)) !=
2358 NULL) {
2359 scope = LDAP_SCOPE_ONELEVEL;
2360 } else if ((s1 = skip_string("sub", s, end_s - s)) !=
2361 NULL) {
2362 scope = LDAP_SCOPE_SUBTREE;
2363 } else if (s + 1 < end_s && *s != QUESTION_MARK) {
2364 p_error = parse_invalid_scope;
2365 break;
2367 if (s1 != NULL)
2368 s = s1;
2369 while (s < end_s && is_whitespace(*s))
2370 s++;
2373 if (s == end_s)
2374 break;
2375 if (*s != QUESTION_MARK)
2376 break;
2377 s++;
2378 while (s < end_s && is_whitespace(*s))
2379 s++;
2380 if (s == end_s || IS_TERMINAL_CHAR(*s))
2381 break;
2383 /* LDAP search filter */
2384 if (*s == OPEN_PAREN_CHAR) {
2385 begin_token = s;
2386 end_token = end_s;
2387 s = get_ldap_filter(&begin_token, &end_token);
2388 if (s == NULL)
2389 break;
2390 s = end_token;
2391 element = get_ldap_filter_element(begin_token, end_token);
2392 if (element != NULL)
2393 break;
2394 } else {
2395 begin_token = s;
2396 end_token = end_s;
2397 s = get_ava_list(&begin_token, &end_token, TRUE);
2398 if (s == NULL)
2399 break;
2400 s = end_token;
2402 if (triple != NULL)
2403 filter = s_strndup(begin_token, s - begin_token);
2404 if (p_error == no_parse_error)
2405 break;
2407 if (p_error == no_parse_error && triple != NULL) {
2408 triple->base = search_base;
2409 triple->scope = scope;
2410 triple->attrs = filter;
2411 triple->element = element;
2412 element = NULL;
2413 filter = NULL;
2414 search_base = NULL;
2417 if (search_base != NULL)
2418 free(search_base);
2419 if (filter != NULL)
2420 free(filter);
2421 if (element != NULL) {
2422 free_mapping_element(element);
2423 free(element);
2425 return (p_error == no_parse_error ? s : NULL);
2429 * FUNCTION: get_mapping_format
2431 * Get the __nis_mapping_format_t from the string
2433 * RETURN VALUE: FALSE if error
2434 * TRUE if __nis_mapping_format_t returned
2436 * INPUT: the format string
2439 static bool_t
2440 get_mapping_format(
2441 const char *fmt_string,
2442 __nis_mapping_format_t **fmt,
2443 int *nfmt,
2444 int *numItems,
2445 bool_t print_mapping)
2447 const char *f = fmt_string;
2448 const char *ef;
2449 __nis_mapping_format_t *b;
2450 __nis_mapping_format_t *base = NULL;
2451 int n = 0;
2452 int nItems = 0;
2454 f = fmt_string;
2455 ef = f + strlen(f);
2456 base = (__nis_mapping_format_t *)
2457 s_calloc(1, sizeof (__nis_mapping_format_t));
2459 if (base == NULL)
2460 return (FALSE);
2461 base->type = mmt_begin;
2462 n++;
2464 for (;;) {
2465 b = (__nis_mapping_format_t *)s_realloc(
2466 base, (n + 1) * sizeof (__nis_mapping_format_t));
2468 if (b == NULL)
2469 break;
2470 base = b;
2471 base[n].type = mmt_end;
2472 if (f == ef) {
2473 if (nfmt)
2474 *nfmt = n + 1;
2475 *fmt = base;
2476 if (numItems)
2477 *numItems = nItems;
2478 return (TRUE);
2480 if (print_mapping)
2481 f = get_next_print_format_item(f, ef, &base[n]);
2482 else
2483 f = get_next_extract_format_item(f, ef, &base[n]);
2486 if (f == NULL)
2487 break;
2488 if (base[n].type == mmt_item ||
2489 base[n].type == mmt_berstring)
2490 nItems++;
2491 n++;
2493 if (base != NULL)
2494 free_mapping_format(base);
2495 return (FALSE);
2499 * FUNCTION: getIndex
2501 * Returns a string containing the index
2503 * RETURN VALUE: NULL if error
2504 * a string containing the index
2506 * INPUT: attribute containing the index
2509 static char *
2510 getIndex(const char **s_cur, const char *s_end)
2512 const char *s = *s_cur + 1;
2513 const char *s1;
2514 char *s_index;
2515 char *s_index1;
2516 char *s_index_end;
2517 int n_brackets = 1;
2518 bool_t in_quotes = FALSE;
2519 char *index = NULL;
2521 while (s < s_end && is_whitespace(*s))
2522 s++;
2523 for (s1 = s; s1 < s_end; s1++) {
2524 if (*s1 == ESCAPE_CHAR)
2525 s1++;
2526 else if (*s1 == DOUBLE_QUOTE_CHAR) {
2527 in_quotes = !in_quotes;
2528 } else if (in_quotes)
2530 else if (*s1 == CLOSE_BRACKET) {
2531 if (--n_brackets == 0)
2532 break;
2533 } else if (*s1 == OPEN_BRACKET)
2534 n_brackets++;
2537 if (n_brackets == 0) {
2538 index = s_strndup(s, s1 - s);
2539 if (index != NULL) {
2540 s_index_end = index + (s1 - s);
2541 s_index1 = index;
2542 for (s_index = index; s_index < s_index_end;
2543 s_index++) {
2544 if (*s_index == ESCAPE_CHAR) {
2545 *s_index1++ = *s_index++;
2546 } else if (*s_index == DOUBLE_QUOTE_CHAR) {
2547 in_quotes = !in_quotes;
2548 } else if (!in_quotes &&
2549 is_whitespace(*s_index)) {
2550 continue;
2552 *s_index1++ = *s_index;
2554 *s_index1 = *s_index;
2556 s = s1 + 1;
2558 while (s < s_end && is_whitespace(*s))
2559 s++;
2560 *s_cur = s;
2562 } else
2563 p_error = parse_mismatched_brackets;
2565 return (index);
2569 * FUNCTION: parse_index
2571 * Parse attribute string to get __nis_index_t
2573 * RETURN VALUE: FALSE if error
2574 * TRUE if __nis_index_t returned
2576 * INPUT: the attribute value to parse
2579 bool_t
2580 parse_index(const char *s, const char *end_s, __nis_index_t *index)
2582 const char *begin_token;
2583 const char *end_token;
2584 char *name_str = NULL;
2585 char **name;
2586 char *fmt_string = NULL;
2587 __nis_mapping_format_t *v = NULL;
2588 __nis_mapping_format_t **value;
2589 token_type t;
2590 int n = 0;
2592 if (index != NULL)
2593 (void) memset(index, 0, sizeof (*index));
2595 while (s < end_s) {
2596 if (n > 0) {
2597 s = skip_token(s, end_s, comma_token);
2598 if (s == NULL) {
2599 p_error = parse_bad_index_format;
2600 break;
2603 begin_token = s;
2604 end_token = end_s;
2605 s = get_next_token(&begin_token, &end_token, &t);
2606 if (s == NULL)
2607 break;
2608 if (t != string_token) {
2609 p_error = parse_bad_index_format;
2610 break;
2612 s = skip_token(s, end_s, equal_token);
2613 if (s == NULL) {
2614 p_error = parse_bad_index_format;
2615 break;
2617 if (index != NULL) {
2618 name_str = s_strndup_esc(begin_token,
2619 end_token - begin_token);
2620 if (name_str == NULL)
2621 break;
2623 begin_token = s;
2624 end_token = end_s;
2625 s = get_next_token(&begin_token, &end_token, &t);
2626 if (s == NULL)
2627 break;
2628 if (t != string_token && t != quoted_string_token) {
2629 p_error = parse_bad_index_format;
2630 break;
2632 fmt_string = s_strndup(begin_token, end_token - begin_token);
2633 if (fmt_string == NULL)
2634 break;
2635 if (!get_mapping_format(fmt_string, &v, NULL, NULL, FALSE))
2636 break;
2637 free(fmt_string);
2638 fmt_string = NULL;
2639 if (index != NULL) {
2640 name = s_realloc(index->name,
2641 (n + 1) * sizeof (char *));
2642 if (name == NULL)
2643 break;
2644 value = s_realloc(index->value,
2645 (n + 1) * sizeof (__nis_mapping_format_t *));
2646 if (value == NULL)
2647 break;
2648 name[n] = name_str;
2649 name_str = NULL;
2650 value[n] = v;
2651 v = NULL;
2652 index->numIndexes = ++n;
2653 index->name = name;
2654 index->value = value;
2655 } else if (v != NULL) {
2656 free_mapping_format(v);
2657 v = NULL;
2660 if (p_error != no_parse_error) {
2661 if (name_str != NULL)
2662 free(name_str);
2663 if (v != NULL)
2664 free_mapping_format(v);
2665 if (fmt_string != NULL)
2666 free(fmt_string);
2667 if (index != NULL)
2668 free_index(index);
2670 return (p_error != no_parse_error);
2674 * FUNCTION: get_deleteDisp
2676 * Parse deleteDisp. Sets p_error if an error occurred.
2678 * RETURN VALUE: TRUE on success
2679 * FAILURE on failure
2681 * INPUT: begin and end of string and __nis_object_dn_t
2684 static bool_t
2685 get_deleteDisp(const char *s_begin, const char *s_end,
2686 __nis_object_dn_t *obj_dn)
2689 * deleteDisp: "always" | perDbId | "never"
2690 * perDbId: "dbid" "=" delDatabaseId
2693 if (same_string("always", s_begin, s_end - s_begin)) {
2694 obj_dn->delDisp = dd_always;
2695 } else if (same_string("never", s_begin, s_end - s_begin)) {
2696 obj_dn->delDisp = dd_never;
2697 } else if ((s_begin = skip_string("dbid", s_begin, s_end - s_begin))
2698 != NULL) {
2699 obj_dn->delDisp = dd_perDbId;
2700 while (s_begin < s_end && is_whitespace(*s_begin))
2701 s_begin++;
2702 if (s_begin == s_end || *s_begin != EQUAL_CHAR) {
2703 p_error = parse_object_dn_syntax_error;
2704 } else {
2705 s_begin++;
2706 while (s_begin < s_end && is_whitespace(*s_begin))
2707 s_begin++;
2708 while (s_begin < s_end && is_whitespace(s_end[-1]))
2709 s_end--;
2710 if (s_begin == s_end) {
2711 p_error = parse_object_dn_syntax_error;
2712 } else {
2713 obj_dn->dbIdName =
2714 s_strndup(s_begin, s_end - s_begin);
2717 } else {
2718 p_error = parse_object_dn_syntax_error;
2720 return (p_error == no_parse_error);