6811333 Remove prom_printf() message in emlxs driver
[opensolaris.git] / usr / src / lib / libnisdb / nis_parse_ldap_map.c
blobe0e4d1b7c842ddbbf6ef3c17cf7b1cfd00859c92
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 2001-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <locale.h>
37 #include "ldap_parse.h"
38 #include "nis_parse_ldap_conf.h"
40 /* other attribute functions */
41 static char *getIndex(const char **s_cur, const char *end_s);
42 static bool_t get_ttls(const char *s, const char *s_end,
43 __nis_table_mapping_t *t_mapping);
44 static __nis_object_dn_t *parse_object_dn(const char *s, const char *end);
45 static int parse_name_fields(const char *name_s, const char *name_s_end,
46 __nis_table_mapping_t *t_mapping);
47 static void get_mapping_rule(const char *s, int len,
48 __nis_table_mapping_t *tbl, bool_t to_ldap);
49 static bool_t get_deleteDisp(const char *s_begin, const char *s_end,
50 __nis_object_dn_t *obj_dn);
52 /* mapping rule functions */
53 static const char *get_lhs(const char *s, const char *end_s,
54 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
55 static const char *get_lhs_match(const char *s, const char *end_s,
56 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
57 static const char *get_lhs_paren_item(const char *s, const char *end_s,
58 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
59 static const char *get_rhs(const char *s, const char *end_s,
60 __nis_mapping_rlhs_t *lhs, __nis_mapping_item_type_t item_type);
61 static const char *get_mapping_item(const char *s, const char *end_s,
62 __nis_mapping_item_t *item, __nis_mapping_item_type_t type);
63 static const char *get_print_mapping_element(const char *s,
64 const char *end_s, char *fmt_string, __nis_mapping_element_t *e,
65 __nis_mapping_item_type_t item_type);
66 static const char *get_subElement(const char *s, const char *end_s,
67 __nis_mapping_sub_element_t *subelement,
68 __nis_mapping_item_type_t type);
69 static bool_t get_mapping_format(const char *fmt_string,
70 __nis_mapping_format_t **fmt, int *nfmt, int *numItems,
71 bool_t print_mapping);
72 extern __yp_domain_context_t ypDomains;
75 * FUNCTION: add_mapping_attribute
77 * Adds the attribute value to __nis_table_mapping_t
78 * if the value is not yet set for the given database.
80 * RETURN VALUE: 0 on success, -1 on failure
82 * INPUT: attribute number and value
85 int
86 add_mapping_attribute(
87 config_key attrib_num,
88 const char *attrib_val,
89 int attrib_len,
90 __nis_table_mapping_t **table_mapping)
92 const char *s;
93 const char *attrib_end;
94 const char *db_id_end;
95 const char *begin_token;
96 const char *end_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;
381 int i;
382 char *tmp_str;
383 int ret = 0;
385 attrib_end = attrib_val + attrib_len;
386 for (s = attrib_val; s < attrib_end; s++) {
387 if (*s == COLON_CHAR) {
388 break;
391 while (s > attrib_val && is_whitespace(s[-1]))
392 s--;
394 if (s == attrib_val) {
395 p_error = parse_unexpected_data_end_rule;
396 return (-1);
399 if (ypDomains == NULL) {
401 * No point allocating. We cant return the resulting structure,
402 * so just return failure. Should not ever happen because we
403 * are always called with a pointer to the global ypDomains
404 * structure.
406 return (-1);
409 switch (attrib_num) {
410 case key_yp_domain_context:
411 numDomains = ypDomains->numDomains;
412 ypDomains->domainLabels =
413 (char **)s_realloc(ypDomains->domainLabels,
414 (numDomains + 1) *
415 sizeof (ypDomains->domainLabels[0]));
416 if (ypDomains->domainLabels == NULL) {
417 p_error = parse_no_mem_error;
418 free_yp_domain_context(ypDomains);
419 break;
421 ypDomains->domainLabels[numDomains] =
422 s_strndup(attrib_val, s - attrib_val);
423 if (ypDomains->domainLabels[numDomains] == NULL) {
424 p_error = parse_no_mem_error;
425 free_yp_domain_context(ypDomains);
426 break;
428 ypDomains->numDomains = numDomains + 1;
429 while (s < attrib_end && is_whitespace(*s))
430 s++;
431 if (*s == COLON_CHAR)
432 s++;
433 while (s < attrib_end && is_whitespace(*s))
434 s++;
435 ypDomains->domains =
436 (char **)s_realloc(ypDomains->domains,
437 (numDomains + 1) *
438 sizeof (ypDomains->domains[0]));
439 if (ypDomains->domains == NULL) {
440 p_error = parse_no_mem_error;
441 free_yp_domain_context(ypDomains);
442 break;
445 if (s < attrib_end) {
446 while (is_whitespace(attrib_end[-1]))
447 attrib_end--;
448 ypDomains->domains[numDomains] =
449 s_strndup_esc(s, attrib_end - s);
450 if (ypDomains->domains[numDomains] == NULL) {
451 p_error = parse_no_mem_error;
452 free_yp_domain_context(ypDomains);
453 break;
455 } else {
456 p_error = parse_unexpected_yp_domain_end_error;
457 free(ypDomains->domainLabels[numDomains]);
458 ypDomains->domainLabels[numDomains] = NULL;
459 ypDomains->numDomains--;
460 free_yp_domain_context(ypDomains);
462 break;
463 case key_yppasswdd_domains:
464 ypDomains->yppasswddDomainLabels =
465 (char **)s_realloc(
466 ypDomains->yppasswddDomainLabels,
467 (ypDomains->numYppasswdd + 1) *
468 sizeof (ypDomains->yppasswddDomainLabels[0]));
469 if (ypDomains->yppasswddDomainLabels == NULL) {
470 p_error = parse_no_mem_error;
471 break;
473 ypDomains->yppasswddDomainLabels
474 [ypDomains->numYppasswdd] =
475 s_strndup(attrib_val, s - attrib_val);
476 if (ypDomains->yppasswddDomainLabels
477 [ypDomains->numYppasswdd] == NULL) {
478 p_error = parse_no_mem_error;
480 ypDomains->numYppasswdd++;
481 break;
484 return (p_error == no_parse_error ? 0 : -1);
488 * FUNCTION: get_ttls
490 * Parse time to live attribute
492 * RETURN VALUE: TRUE on success, FALSE on failure
494 * INPUT: the attribute value
497 static bool_t
498 get_ttls(
499 const char *s,
500 const char *s_end,
501 __nis_table_mapping_t *t_mapping)
503 time_t initTtlHi = 0;
504 time_t initTtlLo = 0;
505 time_t ttl = 0;
506 time_t digit;
509 * attribute should be of the form
510 * initialTTLlo ":" initialTTLhi ":" runningTTL
513 if (s == s_end) {
514 p_error = parse_bad_ttl_format_error;
515 return (FALSE);
518 if (isdigit(*s)) {
519 while (s < s_end && isdigit(*s)) {
520 digit = (*s++) - '0';
521 if (WILL_OVERFLOW_TIME(initTtlLo, digit))
522 initTtlLo = TIME_MAX;
523 else
524 initTtlLo = initTtlLo * 10 + digit;
526 } else {
527 initTtlLo = ONE_HOUR;
530 while (s < s_end && is_whitespace(*s))
531 s++;
532 if (s + 1 >= s_end || *s++ != COLON_CHAR) {
533 p_error = parse_bad_ttl_format_error;
534 return (FALSE);
537 while (s < s_end && is_whitespace(*s))
538 s++;
539 if (isdigit(*s)) {
540 while (s < s_end && isdigit(*s)) {
541 digit = (*s++) - '0';
542 if (WILL_OVERFLOW_TIME(initTtlHi, digit))
543 initTtlHi = TIME_MAX;
544 else
545 initTtlHi = initTtlHi * 10 + digit;
547 } else {
548 initTtlHi = initTtlLo;
551 while (s < s_end && is_whitespace(*s))
552 s++;
553 if (s >= s_end || *s++ != COLON_CHAR) {
554 p_error = parse_bad_ttl_format_error;
555 return (FALSE);
558 while (s < s_end && is_whitespace(*s))
559 s++;
560 if (isdigit(*s)) {
561 while (s < s_end && isdigit(*s)) {
562 digit = (*s++) - '0';
563 if (WILL_OVERFLOW_TIME(ttl, digit))
564 ttl = TIME_MAX;
565 else
566 ttl = ttl * 10 + digit;
568 } else {
569 ttl = ONE_HOUR;
571 while (s < s_end && is_whitespace(*s))
572 s++;
573 if (s != s_end) {
574 p_error = parse_bad_ttl_format_error;
575 return (FALSE);
578 t_mapping->initTtlLo = initTtlLo;
579 t_mapping->initTtlHi = initTtlHi;
580 t_mapping->ttl = ttl;
581 return (TRUE);
585 * FUNCTION: parse_name_fields
587 * Parse yp name fields
589 * RETURN VALUE: 0 on success, non-zero on failure
591 * INPUTS: attrib_value and attribute_end pointers.
594 static int
595 parse_name_fields(const char *name_s,
596 const char *name_s_end,
597 __nis_table_mapping_t *t_map)
599 int i, n = 0;
600 int nElements = 0;
601 int numSplits = 0;
602 int parse_next_line = 1;
603 int itm_count = 0;
604 const char *begin_fmt;
605 const char *end_fmt;
606 const char *begin_token;
607 const char *end_token;
608 char *fmt_string = NULL;
609 __nis_mapping_format_t *base = NULL;
610 __nis_mapping_item_t *item = NULL;
611 __nis_mapping_element_t *elmnt = NULL;
612 __nis_mapping_item_type_t item_type = mit_nisplus;
613 token_type token;
615 t_map->numColumns = 0;
617 for (; parse_next_line > 0; parse_next_line--) {
618 nElements = 0;
619 item = NULL;
620 base = NULL;
621 while (name_s < name_s_end && *name_s != OPEN_PAREN_CHAR)
622 name_s++;
623 if (name_s == name_s_end) {
624 p_error = parse_unexpected_data_end_rule;
625 return (1);
627 while (name_s < name_s_end && *name_s != DOUBLE_QUOTE_CHAR)
628 name_s++;
629 if (name_s == name_s_end) {
630 p_error = parse_unexpected_data_end_rule;
631 return (1);
633 begin_fmt = ++name_s; /* start of format string */
634 while (name_s < name_s_end && *name_s != DOUBLE_QUOTE_CHAR)
635 name_s++;
636 if (name_s == name_s_end) {
637 p_error = parse_unexpected_data_end_rule;
638 return (1);
640 end_fmt = name_s;
641 fmt_string = s_strndup(begin_fmt, end_fmt - begin_fmt);
642 if (fmt_string == NULL) {
643 p_error = parse_no_mem_error;
644 return (2);
646 if (!get_mapping_format(fmt_string, &base, &n, NULL, FALSE)) {
647 p_error = parse_internal_error;
648 free(fmt_string);
649 fmt_string = NULL;
650 return (3);
652 free(fmt_string);
653 fmt_string = NULL;
654 for (n = 0; base[n].type != mmt_end; n++) {
655 if (base[n].type != mmt_item && base[n].type
656 != mmt_berstring) {
657 if (base[n].type == mmt_berstring_null)
658 base[n].type = mmt_berstring;
659 continue;
661 while (name_s < name_s_end && *name_s != COMMA_CHAR)
662 name_s++;
663 name_s++; /* now at comma char */
664 while (name_s < name_s_end && is_whitespace(*name_s))
665 name_s++;
666 begin_token = name_s++;
667 end_token = name_s_end;
668 name_s = get_next_token(
669 &begin_token, &end_token, &token);
670 if (name_s == NULL) {
671 p_error = parse_item_expected_error;
672 return (4);
674 if (token != string_token) {
675 p_error = parse_item_expected_error;
676 return (5);
678 item = (__nis_mapping_item_t *)s_realloc(item,
679 (nElements + 1) *
680 sizeof (__nis_mapping_item_t));
681 if (item == NULL) {
682 p_error = parse_no_mem_error;
683 return (2);
685 name_s = get_mapping_item(begin_token, name_s_end,
686 &item[nElements], item_type);
687 if (name_s == NULL) {
688 p_error = parse_unmatched_escape;
689 for (n = 0; n < (nElements + 1); n++)
690 free_mapping_item(&item[n]);
691 free_mapping_format(base);
692 return (4);
694 nElements++;
696 if (p_error != no_parse_error) {
697 for (n = 0; n < (nElements + 1); n++)
698 free_mapping_item(&item[n]);
699 free_mapping_format(base);
700 return (6);
702 name_s = skip_token(name_s, name_s_end, close_paren_token);
703 if (name_s == NULL) {
704 p_error = parse_close_paren_expected_error;
705 for (n = 0; n < (nElements + 1); n++)
706 free_mapping_item(&item[n]);
707 free_mapping_format(base);
708 return (4);
710 while (name_s < name_s_end && is_whitespace(*name_s))
711 name_s++;
712 if (*name_s == COMMA_CHAR)
713 parse_next_line++;
715 if (nElements == 0) {
716 p_error = parse_no_match_item;
717 for (n = 0; n < (nElements + 1); n++)
718 free_mapping_item(&item[n]);
719 free_mapping_format(base);
720 return (7);
722 elmnt = (__nis_mapping_element_t *)s_realloc(elmnt,
723 (numSplits + 1) *
724 sizeof (__nis_mapping_element_t));
725 if (elmnt == NULL) {
726 for (n = 0; n < (nElements + 1); n++)
727 free_mapping_item(&item[n]);
728 free_mapping_format(base);
729 p_error = parse_no_mem_error;
730 return (2);
732 elmnt[numSplits].type = me_match;
733 elmnt[numSplits].element.match.numItems = nElements;
734 elmnt[numSplits].element.match.item = item;
735 elmnt[numSplits].element.match.fmt = base;
736 item = NULL;
737 base = NULL;
739 t_map->e = elmnt;
740 t_map->numSplits = numSplits;
741 n = t_map->numColumns;
743 for (i = n, itm_count = 0; i < n + nElements; i++) {
744 if (t_map->e[numSplits].element.
745 match.item[itm_count].name) {
746 if (!add_column(t_map,
747 t_map->e[numSplits].element.
748 match.item[itm_count].name))
749 return (1);
750 itm_count++;
751 } else {
752 p_error = parse_internal_error;
753 for (n = 0; n < (nElements + 1); n++)
754 free_mapping_item(&item[n]);
755 free_mapping_format(base);
756 free_mapping_element(elmnt);
757 return (1);
760 numSplits++;
762 elmnt = NULL;
764 if (item != NULL) {
765 for (n = 0; n < t_map->numColumns; n++) {
766 free_mapping_item(&item[n]);
768 free(item);
770 if (elmnt != NULL)
771 free_mapping_element(elmnt);
772 if (base != NULL)
773 free_mapping_format(base);
775 return (p_error == no_parse_error ? 0 : -1);
779 * FUNCTION: parse_object_dn
781 * Parse object dn attribute
783 * RETURN VALUE: __nis_object_dn_t on success
784 * NULL on failure
786 * INPUT: the attribute value
789 static __nis_object_dn_t *
790 parse_object_dn(const char *s, const char *end)
792 const char *s_begin;
793 const char *s_end;
794 object_dn_token token;
795 parse_object_dn_state dn_state = dn_begin_parse;
796 __nis_object_dn_t *obj_dn = NULL;
797 __nis_object_dn_t *next = NULL;
798 __nis_object_dn_t *last = NULL;
801 * The attribute should be of form
802 * objectDN *( ";" objectDN )
803 * objectDN = readObjectSpec [":"[writeObjectSpec]]
804 * readObjectSpec = [baseAndScope [filterAttrValList]]
805 * writeObjectSpec = [baseAndScope [attrValList [":" deleteDisp]]]
808 while (s < end) {
809 s_begin = s;
810 s_end = end;
811 s = get_next_object_dn_token(&s_begin, &s_end, &token);
812 if (s == NULL)
813 break;
815 if (token == dn_no_token || token == dn_semi_token) {
816 if (obj_dn == NULL)
817 obj_dn = next;
818 else
819 last->next = next;
820 last = next;
821 next = NULL;
822 if (token == dn_no_token)
823 break;
824 dn_state = dn_begin_parse;
826 if (next == NULL) {
827 next = (__nis_object_dn_t *)
828 s_calloc(1, sizeof (__nis_object_dn_t));
829 if (next == NULL)
830 break;
831 next->read.scope = LDAP_SCOPE_ONELEVEL;
832 next->write.scope = LDAP_SCOPE_UNKNOWN;
833 next->delDisp = dd_always;
835 if (token == dn_semi_token)
836 continue;
838 switch (dn_state) {
839 case dn_begin_parse:
840 if (token == dn_ques_token)
841 dn_state = dn_got_read_q_scope;
842 else if (token == dn_colon_token) {
843 dn_state = dn_got_write_colon;
844 next->write.scope = LDAP_SCOPE_ONELEVEL;
845 } else {
846 if (!validate_dn(s_begin, s_end - s_begin))
847 break;
848 next->read.base =
849 s_strndup_esc(s_begin, s_end - s_begin);
850 dn_state = dn_got_read_dn;
852 break;
853 case dn_got_read_dn:
854 if (token == dn_ques_token)
855 dn_state = dn_got_read_q_scope;
856 else if (token == dn_colon_token) {
857 dn_state = dn_got_write_colon;
858 next->write.scope = LDAP_SCOPE_ONELEVEL;
859 } else
860 p_error = parse_object_dn_syntax_error;
861 break;
862 case dn_got_read_q_scope:
863 if (token == dn_ques_token)
864 dn_state = dn_got_read_q_filter;
865 else if (token == dn_colon_token) {
866 dn_state = dn_got_write_colon;
867 next->write.scope = LDAP_SCOPE_ONELEVEL;
868 } else if (token == dn_base_token) {
869 next->read.scope = LDAP_SCOPE_BASE;
870 dn_state = dn_got_read_scope;
871 } else if (token == dn_one_token) {
872 next->read.scope = LDAP_SCOPE_ONELEVEL;
873 dn_state = dn_got_read_scope;
874 } else if (token == dn_sub_token) {
875 next->read.scope = LDAP_SCOPE_SUBTREE;
876 dn_state = dn_got_read_scope;
877 } else {
878 p_error = parse_invalid_scope;
880 break;
881 case dn_got_read_scope:
882 if (token == dn_ques_token)
883 dn_state = dn_got_read_q_filter;
884 else if (token == dn_colon_token) {
885 dn_state = dn_got_write_colon;
886 next->write.scope = LDAP_SCOPE_ONELEVEL;
887 } else
888 p_error = parse_object_dn_syntax_error;
889 break;
890 case dn_got_read_q_filter:
891 if (token == dn_ques_token) {
892 p_error = parse_object_dn_syntax_error;
893 } else if (token == dn_colon_token) {
894 dn_state = dn_got_write_colon;
895 next->write.scope = LDAP_SCOPE_ONELEVEL;
896 } else {
897 if (!validate_ldap_filter(s_begin, s_end))
898 break;
899 next->read.attrs =
900 s_strndup_esc(s_begin, s_end - s_begin);
901 dn_state = dn_got_read_filter;
903 break;
904 case dn_got_read_filter:
905 if (token == dn_ques_token) {
906 p_error = parse_object_dn_syntax_error;
907 } else if (token == dn_colon_token) {
908 dn_state = dn_got_write_colon;
909 next->write.scope = LDAP_SCOPE_ONELEVEL;
910 } else
911 p_error = parse_object_dn_syntax_error;
912 break;
913 case dn_got_write_colon:
914 if (token == dn_ques_token)
915 dn_state = dn_got_write_q_scope;
916 else if (token == dn_colon_token) {
917 dn_state = dn_got_delete_colon;
918 } else {
919 if (!validate_dn(s_begin, s_end - s_begin))
920 break;
921 next->write.base =
922 s_strndup_esc(s_begin, s_end - s_begin);
923 dn_state = dn_got_write_dn;
925 break;
926 case dn_got_write_dn:
927 if (token == dn_ques_token)
928 dn_state = dn_got_write_q_scope;
929 else if (token == dn_colon_token) {
930 dn_state = dn_got_delete_colon;
931 } else
932 p_error = parse_object_dn_syntax_error;
933 break;
934 case dn_got_write_q_scope:
935 if (token == dn_ques_token)
936 dn_state = dn_got_write_q_filter;
937 else if (token == dn_colon_token) {
938 dn_state = dn_got_delete_colon;
939 } else if (token == dn_base_token) {
940 next->write.scope = LDAP_SCOPE_BASE;
941 dn_state = dn_got_write_scope;
942 } else if (token == dn_one_token) {
943 next->write.scope = LDAP_SCOPE_ONELEVEL;
944 dn_state = dn_got_write_scope;
945 } else if (token == dn_sub_token) {
946 next->write.scope = LDAP_SCOPE_SUBTREE;
947 dn_state = dn_got_write_scope;
948 } else {
949 p_error = parse_invalid_scope;
951 break;
952 case dn_got_write_scope:
953 if (token == dn_ques_token)
954 dn_state = dn_got_write_q_filter;
955 else if (token == dn_colon_token) {
956 dn_state = dn_got_delete_colon;
957 } else
958 p_error = parse_object_dn_syntax_error;
959 break;
960 case dn_got_write_q_filter:
961 if (token == dn_ques_token) {
962 p_error = parse_object_dn_syntax_error;
963 } else if (token == dn_colon_token) {
964 dn_state = dn_got_delete_colon;
965 } else {
966 if (!validate_ldap_filter(s_begin, s_end))
967 break;
968 next->write.attrs =
969 s_strndup_esc(s_begin, s_end - s_begin);
970 dn_state = dn_got_write_filter;
972 break;
973 case dn_got_write_filter:
974 if (token == dn_ques_token) {
975 p_error = parse_object_dn_syntax_error;
976 } else if (token == dn_colon_token) {
977 dn_state = dn_got_delete_colon;
979 } else
980 p_error = parse_semi_expected_error;
981 break;
982 case dn_got_delete_colon:
983 if (token == dn_ques_token) {
984 p_error = parse_object_dn_syntax_error;
985 } else if (token == dn_colon_token) {
986 p_error = parse_object_dn_syntax_error;
987 } else {
988 if (!get_deleteDisp(s_begin, s_end, next))
989 break;
990 dn_state = dn_got_delete_dsp;
992 break;
993 case dn_got_delete_dsp:
994 p_error = parse_object_dn_syntax_error;
995 break;
998 if (p_error != no_parse_error)
999 break;
1001 if (p_error != no_parse_error) {
1002 if (obj_dn != NULL)
1003 free_object_dn(obj_dn);
1004 if (next != NULL)
1005 free_object_dn(next);
1006 obj_dn = NULL;
1007 } else if (next != NULL) {
1008 if (obj_dn == NULL)
1009 obj_dn = next;
1010 else
1011 last->next = next;
1012 } else if (obj_dn == NULL)
1013 obj_dn = (__nis_object_dn_t *)
1014 s_calloc(1, sizeof (__nis_object_dn_t));
1016 return (obj_dn);
1020 * FUNCTION: get_mapping_rule
1022 * Parse mapping rule attributes
1024 * RETURN VALUE: None. Errors determined by p_error
1026 * INPUT: the attribute value and mapping rule type
1029 static void
1030 get_mapping_rule(
1031 const char *s,
1032 int len,
1033 __nis_table_mapping_t *tbl,
1034 bool_t to_ldap)
1036 const char *end_s = s + len;
1037 const char *begin_token;
1038 const char *end_token;
1039 __nis_mapping_rule_t **rule = NULL;
1040 __nis_mapping_rule_t *next = NULL;
1041 /* __nis_mapping_rule_t **r; */
1042 token_type t;
1043 int nRules = 0;
1044 const char *s1;
1045 int i;
1048 * The attribute value is of the form
1049 * colattrspec *("," colattrspec)
1050 * colattrspec = lhs "=" rhs
1051 * lhs = lval | namespeclist
1052 * rhs = rval | [namespec]
1055 for (;;) {
1056 if ((next = (__nis_mapping_rule_t *)
1057 s_calloc(1, sizeof (__nis_mapping_rule_t))) == NULL)
1058 break;
1060 s = get_lhs(s, end_s, &next->lhs,
1061 to_ldap ? mit_ldap : mit_nisplus);
1062 if (s == NULL)
1063 break;
1065 begin_token = s;
1066 end_token = end_s;
1067 s1 = get_next_token(&begin_token, &end_token, &t);
1068 if (s1 == NULL)
1069 break;
1070 if (!(to_ldap && (t == comma_token || t == no_token))) {
1071 s = get_rhs(s, end_s, &next->rhs,
1072 to_ldap ? mit_nisplus : mit_ldap);
1073 if (s == NULL)
1074 break;
1077 if (next->lhs.numElements > 1 &&
1078 (next->rhs.numElements != 1 ||
1079 next->rhs.element[0].type != me_split)) {
1080 p_error = parse_lhs_rhs_type_mismatch;
1081 break;
1083 if (rule == NULL) {
1084 rule = (__nis_mapping_rule_t **)
1085 malloc(sizeof (__nis_mapping_rule_t *));
1086 if (rule == NULL)
1087 break;
1088 } else {
1089 rule = (__nis_mapping_rule_t **)s_realloc(rule,
1090 (nRules + 1) *
1091 sizeof (__nis_mapping_rule_t *));
1092 if (rule == NULL)
1093 break;
1096 rule[nRules++] = next;
1097 next = NULL;
1099 begin_token = s;
1100 end_token = end_s;
1101 s = get_next_token(&begin_token, &end_token, &t);
1102 if (s == NULL)
1103 break;
1104 if (t == comma_token)
1105 continue;
1106 if (t != no_token) {
1107 p_error = parse_unexpected_data_end_rule;
1108 break;
1110 if (to_ldap) {
1111 tbl->numRulesToLDAP = nRules;
1112 tbl->ruleToLDAP = rule;
1113 } else {
1114 tbl->numRulesFromLDAP = nRules;
1115 tbl->ruleFromLDAP = rule;
1117 return;
1120 if (rule) {
1121 for (i = 0; i < nRules; i++)
1122 free_mapping_rule(rule[i]);
1123 free(rule);
1125 if (next)
1126 free_mapping_rule(next);
1130 * FUNCTION: get_lhs
1132 * Parse left hand side of mapping rule attribute
1134 * RETURN VALUE: NULL if error
1135 * position of beginning rhs
1137 * INPUT: the attribute value and mapping rule type
1140 static const char *
1141 get_lhs(const char *s,
1142 const char *end_s,
1143 __nis_mapping_rlhs_t *lhs,
1144 __nis_mapping_item_type_t item_type)
1146 token_type t;
1147 const char *begin_token;
1148 const char *end_token;
1149 const char *sav_s;
1150 __nis_mapping_element_t *e = NULL;
1153 * lhs can be expressed as:
1154 * item
1155 * (item)
1156 * (item list)
1157 * (fmt, item list)
1159 * lhs = lval | namespeclist
1160 * lval = "(" formatspec "," namespec *("," namespec) ")"
1161 * namespeclist = namespec | "(" namespec *("," namespec) ")"
1164 for (; p_error == no_parse_error; ) {
1165 begin_token = s;
1166 end_token = end_s;
1167 s = get_next_token(&begin_token, &end_token, &t);
1168 if (s == NULL)
1169 break;
1170 if (t == no_token) {
1171 p_error = parse_unexpected_data_end_rule;
1172 break;
1175 e = (__nis_mapping_element_t *)
1176 s_calloc(1, sizeof (__nis_mapping_element_t));
1177 if (e == NULL)
1178 break;
1180 if (t == open_paren_token) {
1181 free(e);
1182 e = NULL;
1184 begin_token = s;
1185 end_token = end_s;
1186 sav_s = s;
1187 s = get_next_token(&begin_token, &end_token, &t);
1188 if (s == NULL)
1189 break;
1191 if (t == quoted_string_token) {
1192 s = get_lhs_match(sav_s, end_s, lhs, item_type);
1193 if (s == NULL)
1194 break;
1195 } else if (t == string_token) {
1196 s = get_lhs_paren_item(sav_s, end_s, lhs,
1197 item_type);
1198 if (s == NULL)
1199 break;
1200 } else {
1201 p_error = parse_bad_lhs_format_error;
1202 break;
1204 } else if (t == string_token) {
1205 s = get_mapping_item(begin_token, end_s,
1206 &e->element.item, item_type);
1207 if (s == NULL)
1208 break;
1209 e->type = me_item;
1210 if (!add_element(e, lhs))
1211 break;
1212 e = NULL;
1213 } else {
1214 p_error = parse_bad_lhs_format_error;
1215 break;
1218 s = skip_token(s, end_s, equal_token);
1219 if (s == NULL)
1220 break;
1221 if (p_error == no_parse_error)
1222 return (s);
1224 if (e != NULL)
1225 free_mapping_element(e);
1227 return (NULL);
1231 * FUNCTION: get_lhs_match
1233 * Parse left hand side of mapping rule attribute in case of
1234 * matching rule
1236 * RETURN VALUE: NULL if error
1237 * position of beginning rhs
1239 * INPUT: the attribute value and mapping rule type
1242 static const char *
1243 get_lhs_match(
1244 const char *s,
1245 const char *end_s,
1246 __nis_mapping_rlhs_t *lhs,
1247 __nis_mapping_item_type_t item_type)
1249 token_type t;
1250 const char *begin_token;
1251 const char *end_token;
1252 int n = 0;
1253 int nElements = 0;
1254 char *fmt_string = NULL;
1255 __nis_mapping_format_t *base = NULL;
1256 __nis_mapping_item_t *item = NULL;
1257 __nis_mapping_item_t *itm;
1258 __nis_mapping_element_t *e;
1261 * lval = "(" formatspec "," namespec *("," namespec) ")"
1264 for (; p_error == no_parse_error; ) {
1265 begin_token = s;
1266 end_token = end_s;
1267 s = get_next_token(&begin_token, &end_token, &t);
1268 if (s == NULL || t != quoted_string_token) {
1269 p_error = parse_internal_error;
1270 break;
1274 fmt_string = s_strndup(begin_token, end_token - begin_token);
1275 if (fmt_string == NULL)
1276 break;
1278 if (!get_mapping_format(fmt_string, &base, &n, NULL, FALSE))
1279 break;
1281 for (n = 0; base[n].type != mmt_end; n++) {
1282 if (base[n].type != mmt_item &&
1283 base[n].type != mmt_berstring) {
1284 if (base[n].type == mmt_berstring_null)
1285 base[n].type = mmt_berstring;
1286 continue;
1288 s = skip_token(s, end_s, comma_token);
1289 if (s == NULL) {
1290 p_error = parse_not_enough_extract_items;
1291 break;
1293 begin_token = s;
1294 end_token = end_s;
1295 s = get_next_token(&begin_token, &end_token, &t);
1296 if (s == NULL)
1297 break;
1298 if (t != string_token) {
1299 p_error = parse_item_expected_error;
1300 break;
1302 itm = (__nis_mapping_item_t *)
1303 s_realloc(item, (nElements + 1) *
1304 sizeof (__nis_mapping_item_t));
1305 if (itm == NULL)
1306 break;
1307 item = itm;
1309 s = get_mapping_item(begin_token, end_s,
1310 &item[nElements], item_type);
1311 if (s == NULL)
1312 break;
1313 nElements++;
1315 if (p_error != no_parse_error)
1316 break;
1318 s = skip_token(s, end_s, close_paren_token);
1319 if (s == NULL)
1320 break;
1321 free(fmt_string);
1322 fmt_string = NULL;
1324 if (nElements == 0) {
1325 p_error = parse_no_match_item;
1326 break;
1328 e = (__nis_mapping_element_t *)s_calloc(1,
1329 sizeof (__nis_mapping_element_t));
1330 if (e == NULL)
1331 break;
1332 e->type = me_match;
1333 e->element.match.numItems = nElements;
1334 e->element.match.item = item;
1335 e->element.match.fmt = base;
1336 lhs->numElements = 1;
1337 lhs->element = e;
1339 if (p_error == no_parse_error)
1340 return (s);
1342 if (item == NULL) {
1343 for (n = 0; n < nElements; n++)
1344 free_mapping_item(&item[n]);
1345 free(item);
1347 if (fmt_string != NULL)
1348 free(fmt_string);
1349 if (base != NULL)
1350 free_mapping_format(base);
1352 return (NULL);
1356 * FUNCTION: get_lhs_paren_item
1358 * Parse left hand side of mapping rule attribute in case of
1359 * (item1, ..., item-n)
1361 * RETURN VALUE: NULL if error
1362 * position of beginning rhs
1364 * INPUT: the attribute value and mapping rule type
1367 static const char *
1368 get_lhs_paren_item(
1369 const char *s,
1370 const char *end_s,
1371 __nis_mapping_rlhs_t *lhs,
1372 __nis_mapping_item_type_t item_type)
1374 token_type t;
1375 const char *begin_token;
1376 const char *end_token;
1377 __nis_mapping_element_t *e = NULL;
1378 int n = 0;
1379 int i;
1382 * "(" namespec *("," namespec) ")"
1385 for (;;) {
1386 e = (__nis_mapping_element_t *)s_realloc(e, (n + 1) *
1387 sizeof (__nis_mapping_element_t));
1388 if (e == NULL)
1389 break;
1391 s = get_mapping_item(s, end_s, &e[n].element.item,
1392 item_type);
1393 if (s == NULL)
1394 break;
1395 e[n].type = me_item;
1396 n++;
1398 begin_token = s;
1399 end_token = end_s;
1400 s = get_next_token(&begin_token, &end_token, &t);
1401 if (s != NULL && t == close_paren_token) {
1402 lhs->numElements = n;
1403 if (n == 1)
1404 e[0].element.item.repeat = TRUE;
1405 lhs->element = e;
1406 return (s);
1408 if (s == NULL || t != comma_token) {
1409 p_error = parse_comma_expected_error;
1410 break;
1413 for (i = 0; i < n; i++)
1414 free_mapping_element(&e[i]);
1415 if (e != NULL)
1416 free(e);
1417 return (NULL);
1421 * FUNCTION: get_rhs
1423 * Parse right hand side of mapping rule attribute
1425 * RETURN VALUE: NULL if error
1426 * position of beginning next mapping rule
1428 * INPUT: the attribute value and mapping rule type
1431 static const char *
1432 get_rhs(
1433 const char *s,
1434 const char *end_s,
1435 __nis_mapping_rlhs_t *rhs,
1436 __nis_mapping_item_type_t item_type)
1439 * This handles the following cases:
1440 * name me_item
1441 * (name) me_item
1442 * (fmt, name-list) me_print
1443 * (item, fmt) me_extract
1446 token_type t;
1447 const char *begin_token;
1448 const char *end_token;
1449 char *str = NULL;
1450 __nis_mapping_format_t *fmt = NULL;
1451 __nis_mapping_element_t *e = NULL;
1452 __nis_mapping_item_t item;
1453 int n;
1455 (void) memset(&item, 0, sizeof (item));
1457 for (; p_error == no_parse_error; ) {
1458 begin_token = s;
1459 end_token = end_s;
1460 s = get_next_token(&begin_token, &end_token, &t);
1461 if (s == NULL)
1462 break;
1464 e = (__nis_mapping_element_t *)
1465 s_calloc(1, sizeof (__nis_mapping_element_t));
1466 if (e == NULL)
1467 break;
1469 if (t == string_token) {
1470 s = get_mapping_item(begin_token, end_s,
1471 &e->element.item, item_type);
1472 } else if (t == open_paren_token) {
1473 begin_token = s;
1474 end_token = end_s;
1475 s = get_next_token(&begin_token, &end_token, &t);
1476 if (s == NULL)
1477 break;
1478 if (t == string_token) {
1479 /* (item, fmt) - me_extract */
1480 /* (item, "c") - me_split */
1481 s = get_mapping_item(begin_token, end_s,
1482 &item, item_type);
1483 if (s == NULL)
1484 break;
1485 begin_token = s;
1486 end_token = end_s;
1487 s = get_next_token(&begin_token, &end_token,
1488 &t);
1489 if (s == NULL)
1490 break;
1491 else if (t == close_paren_token) {
1492 item.repeat = TRUE;
1493 e->element.item = item;
1494 e->type = me_item;
1495 rhs->numElements = 1;
1496 rhs->element = e;
1497 return (s);
1498 } else if (t != comma_token) {
1499 p_error = parse_comma_expected_error;
1500 break;
1503 begin_token = s;
1504 end_token = end_s;
1505 s = get_next_token(&begin_token, &end_token,
1506 &t);
1507 if (s == NULL || t != quoted_string_token) {
1508 p_error =
1509 parse_format_string_expected_error;
1510 break;
1513 if (end_token == begin_token + 1 ||
1514 *begin_token == ESCAPE_CHAR &&
1515 end_token == begin_token + 2) {
1516 e->type = me_split;
1517 e->element.split.item = item;
1518 e->element.split.delim = *begin_token;
1519 } else {
1520 str = s_strndup(begin_token,
1521 end_token - begin_token);
1522 if (str == NULL)
1523 break;
1524 if (!get_mapping_format(str, &fmt,
1525 NULL, &n, FALSE))
1526 break;
1527 free(str);
1528 str = NULL;
1529 if (n != 1) {
1530 p_error =
1531 parse_bad_extract_format_spec;
1532 break;
1534 e->type = me_extract;
1535 e->element.extract.item = item;
1536 e->element.extract.fmt = fmt;
1538 s = skip_token(s, end_s, close_paren_token);
1539 } else if (t == quoted_string_token) {
1540 /* (fmt, name-list) - me_print */
1541 str = s_strndup(begin_token,
1542 end_token - begin_token);
1543 if (str == NULL)
1544 break;
1546 s = get_print_mapping_element(s, end_s,
1547 str, e, item_type);
1548 free(str);
1549 str = NULL;
1550 } else {
1551 p_error = parse_start_rhs_unrecognized;
1552 break;
1554 } else {
1555 p_error = parse_start_rhs_unrecognized;
1556 break;
1558 if (s == NULL)
1559 break;
1560 rhs->numElements = 1;
1561 rhs->element = e;
1562 if (p_error == no_parse_error)
1563 return (s);
1565 if (str)
1566 free(str);
1567 if (fmt != NULL)
1568 free_mapping_format(fmt);
1569 if (e != NULL)
1570 free_mapping_element(e);
1571 free_mapping_item(&item);
1573 return (NULL);
1577 * FUNCTION: get_print_mapping_element
1579 * Parse a print mapping rule attribute in case of the form
1580 * (fmt, name-list)
1582 * RETURN VALUE: NULL if error
1583 * position of beginning next mapping rule
1585 * INPUT: the attribute value and mapping rule type
1588 static const char *
1589 get_print_mapping_element(
1590 const char *s,
1591 const char *end_s,
1592 char *fmt_string,
1593 __nis_mapping_element_t *e,
1594 __nis_mapping_item_type_t item_type)
1596 token_type t;
1597 const char *begin_token;
1598 const char *end_token;
1599 char elide;
1600 bool_t doElide;
1601 __nis_mapping_format_t *base = NULL;
1602 __nis_mapping_sub_element_t *subElement = NULL;
1603 int n = 0;
1604 int nSub = 0;
1605 int numSubElements;
1607 for (; p_error == no_parse_error; ) {
1608 if (!get_mapping_format(fmt_string, &base, &n,
1609 &numSubElements, TRUE))
1610 break;
1611 subElement = (__nis_mapping_sub_element_t *)
1612 s_calloc(numSubElements,
1613 sizeof (__nis_mapping_sub_element_t));
1614 if (subElement == NULL)
1615 break;
1616 for (n = 0; base[n].type != mmt_end; n++) {
1617 if (base[n].type != mmt_item &&
1618 base[n].type != mmt_berstring) {
1619 if (base[n].type == mmt_berstring_null)
1620 base[n].type = mmt_berstring;
1621 continue;
1623 if (nSub < numSubElements) {
1624 s = skip_token(s, end_s, comma_token);
1625 if (s == NULL) {
1626 p_error = parse_bad_print_format;
1627 break;
1631 /* namelist may have parens around it */
1632 s = get_subElement(s, end_s, &subElement[nSub],
1633 item_type);
1634 if (s == NULL)
1635 break;
1636 nSub++;
1638 if (p_error != no_parse_error)
1639 break;
1641 begin_token = s;
1642 end_token = end_s;
1643 s = get_next_token(&begin_token, &end_token, &t);
1644 if (s == NULL || t == no_token) {
1645 p_error = parse_unexpected_data_end_rule;
1646 break;
1647 } else if (t == close_paren_token) {
1648 doElide = FALSE;
1649 elide = '\0';
1650 } else if (t == comma_token) {
1651 begin_token = s;
1652 end_token = end_s;
1653 s = get_next_token(&begin_token, &end_token, &t);
1654 if (s != NULL && t == quoted_string_token &&
1655 (end_token == begin_token + 1 ||
1656 *begin_token == ESCAPE_CHAR &&
1657 end_token == begin_token + 2)) {
1658 if (numSubElements != 1 ||
1659 subElement->type == me_extract ||
1660 subElement->type == me_split) {
1661 p_error = parse_cannot_elide;
1662 break;
1664 if (subElement->type == me_item &&
1665 !subElement->element.item.repeat) {
1666 p_error = parse_cannot_elide;
1667 break;
1669 elide = *begin_token;
1670 doElide = TRUE;
1672 } else {
1673 p_error = parse_bad_elide_char;
1674 break;
1676 s = skip_token(s, end_s, close_paren_token);
1677 if (s == NULL)
1678 break;
1681 e->type = me_print;
1682 e->element.print.fmt = base;
1683 e->element.print.numSubElements = numSubElements;
1684 e->element.print.subElement = subElement;
1685 e->element.print.elide = elide;
1686 e->element.print.doElide = doElide;
1688 if (p_error == no_parse_error)
1689 return (s);
1691 if (base)
1692 free_mapping_format(base);
1693 if (subElement != NULL) {
1694 for (n = 0; n < numSubElements; n++)
1695 free_mapping_sub_element(&subElement[n]);
1696 free(subElement);
1699 return (NULL);
1703 * FUNCTION: get_mapping_item
1705 * Parse attribute string to get mapping item
1707 * RETURN VALUE: NULL if error
1708 * position of beginning next token after item
1710 * INPUT: the attribute value and mapping rule type
1713 static const char *
1714 get_mapping_item(
1715 const char *s,
1716 const char *end_s,
1717 __nis_mapping_item_t *item,
1718 __nis_mapping_item_type_t type)
1720 token_type t;
1721 const char *begin_token;
1722 const char *end_token;
1723 char *name = NULL;
1724 char *index_string;
1725 const char *s_sav;
1726 int len;
1728 (void) memset(item, 0, sizeof (*item));
1731 * A namepec is defined as follows:
1732 * namespec = ["ldap:"] attrspec [searchTriple] |
1733 * ["nis+:"] colspec [objectspec]
1735 * The form of the item is assumed to be as follows:
1736 * ["ldap:"] attrspec [searchTriple]
1737 * attrspec = attribute | "(" attribute ")"
1738 * searchTriple = ":" [baseDN] ["?" [scope] ["?" [filter]]]
1739 * baseDN = Base DN for search
1740 * scope = "base" | "one" | "sub"
1741 * filter = LDAP search filter
1743 * The form of the objectspec is as follows:
1744 * ["nis+:"] colspec [objectspec]
1745 * objectspec = objectname | "[" indexlist "]" tablename
1746 * objectname = The name of a NIS+ object
1747 * tablename = The name of a NIS+ table
1748 * indexlist = colspec ["," colspec]
1749 * colspec = colname "=" colvalue
1750 * colname = The name of a column in the table
1751 * colvalue = colvaluestring | \" colvaluestring \"
1754 for (; p_error == no_parse_error; ) {
1755 while (s < end_s && is_whitespace(*s))
1756 s++;
1757 len = end_s - s;
1758 if (yp2ldap) {
1759 if ((begin_token = skip_string("ldap:", s,
1760 len)) != NULL) {
1761 item->type = mit_ldap;
1762 } else if ((begin_token = skip_string("yp:", s,
1763 len)) != NULL) {
1764 item->type = mit_nisplus;
1765 } else {
1766 item->type = type;
1767 begin_token = s;
1769 } else {
1770 if ((begin_token = skip_string("ldap:", s,
1771 len)) != NULL) {
1772 item->type = mit_ldap;
1773 } else if ((begin_token = skip_string("nis+:", s,
1774 len)) != NULL) {
1775 item->type = mit_nisplus;
1776 } else if ((begin_token = skip_string("nisplus:", s,
1777 len)) != NULL) {
1778 item->type = mit_nisplus;
1779 } else {
1780 item->type = type;
1781 begin_token = s;
1785 end_token = end_s;
1786 s = get_next_token(&begin_token, &end_token, &t);
1787 if (s == NULL || t != string_token) {
1788 p_error = parse_bad_item_format;
1789 break;
1792 item->name = s_strndup_esc(begin_token,
1793 end_token - begin_token);
1794 if (item->name == NULL)
1795 break;
1796 if (item->type == mit_ldap) {
1797 item->searchSpec.triple.scope = LDAP_SCOPE_UNKNOWN;
1798 begin_token = s;
1799 end_token = end_s;
1800 s_sav = s;
1801 s = get_next_token(&begin_token, &end_token, &t);
1802 if (s != NULL && t == colon_token) {
1803 s = get_search_triple(s, end_s,
1804 &item->searchSpec.triple);
1805 if (s == NULL)
1806 break;
1807 } else
1808 s = s_sav;
1809 } else if (item->type == mit_nisplus) {
1810 while (s < end_s && is_whitespace(*s))
1811 s++;
1813 if (s < end_s && *s == OPEN_BRACKET) {
1814 index_string = getIndex(&s, end_s);
1815 if (index_string == NULL)
1816 break;
1817 (void) parse_index(index_string,
1818 index_string + strlen(index_string),
1819 &item->searchSpec.obj.index);
1820 free(index_string);
1821 if (p_error != no_parse_error)
1822 break;
1824 s_sav = s;
1825 begin_token = s;
1826 end_token = end_s;
1827 s = get_next_token(&begin_token, &end_token, &t);
1828 if (s != NULL && t == string_token) {
1829 name = s_strndup_esc(begin_token,
1830 end_token - begin_token);
1831 if (name == NULL)
1832 break;
1833 item->searchSpec.obj.name = name;
1834 } else
1835 s = s_sav;
1837 if (p_error == no_parse_error)
1838 return (s);
1840 free_mapping_item(item);
1841 (void) memset(item, 0, sizeof (*item));
1842 if (name == NULL)
1843 free(name);
1844 return (NULL);
1847 static const char *
1848 get_print_sub_element(const char *s,
1849 const char *end_s,
1850 __nis_mapping_item_type_t type,
1851 __nis_mapping_sub_element_t *sub)
1854 int k;
1855 int n;
1856 const char *begin_token;
1857 const char *end_token;
1858 token_type t;
1859 __nis_mapping_format_t *base;
1860 __nis_mapping_item_t *print_item;
1862 k = 0;
1863 base = sub->element.print.fmt;
1864 print_item = sub->element.print.item;
1865 sub->element.print.doElide = FALSE;
1866 sub->element.print.elide = '\0';
1868 for (n = 0; base[n].type != mmt_end; n++) {
1869 if (base[n].type != mmt_item && base[n].type != mmt_berstring) {
1870 if (base[n].type == mmt_berstring_null)
1871 base[n].type = mmt_berstring;
1872 continue;
1874 s = skip_token(s, end_s, comma_token);
1875 if (s == NULL) {
1876 p_error = parse_bad_print_format;
1877 break;
1880 begin_token = s;
1881 end_token = end_s;
1882 s = get_next_token(&begin_token, &end_token, &t);
1883 if (s == NULL)
1884 break;
1886 * Determine if of the form
1887 * ("fmt", (item), "delim") or
1888 * ("fmt", item1, item2, ..., item n)
1890 if (t == open_paren_token) {
1891 if (sub->element.print.numItems != 1) {
1892 p_error = parse_invalid_print_arg;
1893 break;
1895 s = get_mapping_item(s, end_s, &print_item[k++], type);
1896 s = skip_token(s, end_s, close_paren_token);
1897 s = skip_token(s, end_s, comma_token);
1898 if (s == NULL) {
1899 p_error = parse_bad_print_format;
1900 break;
1902 begin_token = s;
1903 end_token = end_s;
1904 s = get_next_token(&begin_token, &end_token, &t);
1905 if (s == NULL)
1906 break;
1907 if (t != quoted_string_token ||
1908 begin_token + 1 != end_token) {
1909 p_error = parse_bad_elide_char;
1910 break;
1912 sub->element.print.elide = *begin_token;
1913 sub->element.print.doElide = TRUE;
1914 print_item[0].repeat = TRUE;
1915 break;
1917 s = get_mapping_item(begin_token, end_s,
1918 &print_item[k++], type);
1919 if (s == NULL)
1920 break;
1922 if (p_error != no_parse_error)
1923 break;
1926 return (p_error == no_parse_error ? s : NULL);
1930 * FUNCTION: get_subElement
1932 * Parse attribute string to get sub element item
1934 * RETURN VALUE: NULL if error
1935 * position of beginning next token after item
1937 * INPUT: the attribute value and mapping rule type
1940 static const char *
1941 get_subElement(
1942 const char *s,
1943 const char *end_s,
1944 __nis_mapping_sub_element_t *subelement,
1945 __nis_mapping_item_type_t type)
1947 token_type t;
1948 const char *begin_token;
1949 const char *end_token;
1950 char *fmt_string;
1951 __nis_mapping_item_t item;
1952 __nis_mapping_element_type_t e_type;
1953 __nis_mapping_item_t *print_item = NULL;
1954 __nis_mapping_format_t *base = NULL;
1955 int n = 0;
1956 int numItems = 0;
1957 unsigned char delim;
1958 __nis_mapping_sub_element_t sub;
1961 * What is the form of we are expecting here
1962 * item me_item
1963 * (item) me_item
1964 * ("fmt", item1, item2, ..., item n) me_print
1965 * ("fmt", (item), "elide") me_print
1966 * (name, "delim") me_split
1967 * (item, "fmt") me_extract
1969 (void) memset(&item, 0, sizeof (item));
1971 for (; p_error == no_parse_error; ) {
1972 begin_token = s;
1973 end_token = end_s;
1974 s = get_next_token(&begin_token, &end_token, &t);
1975 if (s == NULL)
1976 break;
1977 if (t == string_token) { /* me_item */
1978 s = get_mapping_item(begin_token, end_s,
1979 &subelement->element.item, type);
1980 if (s == NULL)
1981 break;
1982 subelement->type = me_item;
1983 return (s);
1984 } else if (t != open_paren_token) {
1985 p_error = parse_item_expected_error;
1986 break;
1989 begin_token = s;
1990 end_token = end_s;
1991 s = get_next_token(&begin_token, &end_token, &t);
1992 if (s == NULL)
1993 break;
1995 if (t != string_token && t != quoted_string_token) {
1996 p_error = parse_item_expected_error;
1997 break;
1999 e_type = me_print;
2000 if (t == string_token) {
2001 /* me_item, me_extract or me_split */
2002 s = get_mapping_item(begin_token, end_s, &item, type);
2003 if (s == NULL)
2004 break;
2006 begin_token = s;
2007 end_token = end_s;
2008 s = get_next_token(&begin_token, &end_token, &t);
2009 if (s == NULL) {
2010 p_error = parse_unexpected_data_end_rule;
2011 break;
2012 } else if (t == close_paren_token) {
2013 subelement->type = me_item;
2014 item.repeat = TRUE;
2015 subelement->element.item = item;
2016 if (yp2ldap) {
2017 while (s < end_s && is_whitespace(*s))
2018 s++;
2019 if (s == end_s) {
2020 p_error =
2021 parse_unexpected_data_end_rule;
2022 break;
2024 if (*s == DASH_CHAR && s < end_s) {
2025 s++;
2026 while (s < end_s &&
2027 is_whitespace(*s))
2028 s++;
2029 begin_token = s;
2030 end_token = end_s;
2032 subelement->element.item.exItem
2034 (__nis_mapping_item_t *)
2035 s_malloc(sizeof (__nis_mapping_item_t));
2036 if (!subelement->
2037 element.item.exItem)
2038 break;
2039 s = get_mapping_item(s, end_s,
2040 subelement->
2041 element.item.exItem,
2042 type);
2043 if (s == NULL) {
2044 p_error =
2045 parse_internal_error;
2046 free_mapping_item(
2047 subelement->
2048 element.item.exItem);
2049 subelement->
2050 element.item.exItem =
2051 NULL;
2052 break;
2056 return (s);
2057 } else if (t != comma_token) {
2058 p_error = parse_comma_expected_error;
2059 break;
2062 begin_token = s;
2063 end_token = end_s;
2064 s = get_next_token(&begin_token, &end_token, &t);
2065 if (s == NULL || t != quoted_string_token) {
2066 p_error = parse_format_string_expected_error;
2067 break;
2069 if (end_token == begin_token + 1 ||
2070 *begin_token == ESCAPE_CHAR &&
2071 end_token == begin_token + 2) {
2072 /* me_split */
2073 delim = (unsigned char)end_token[-1];
2074 s = skip_token(s, end_s, close_paren_token);
2075 if (s == NULL)
2076 break;
2077 subelement->element.split.item = item;
2078 subelement->element.split.delim = delim;
2079 subelement->type = me_split;
2080 return (s);
2082 e_type = me_extract;
2084 fmt_string = s_strndup(begin_token, end_token - begin_token);
2085 if (fmt_string == NULL)
2086 break;
2087 if (!get_mapping_format(fmt_string, &base, &n, &numItems,
2088 e_type == me_print)) {
2089 free(fmt_string);
2090 break;
2092 free(fmt_string);
2094 if (numItems != 1 && e_type == me_extract) {
2095 p_error = numItems == 0 ?
2096 parse_not_enough_extract_items :
2097 parse_too_many_extract_items;
2098 break;
2099 } else if (numItems > 0 && e_type == me_print) {
2100 print_item = (__nis_mapping_item_t *)s_calloc(numItems,
2101 sizeof (__nis_mapping_item_t));
2102 if (print_item == NULL)
2103 break;
2106 if (e_type == me_print) {
2107 sub.element.print.numItems = numItems;
2108 sub.element.print.fmt = base;
2109 sub.element.print.item = print_item;
2110 s = get_print_sub_element(s, end_s, type, &sub);
2111 if (s == NULL)
2112 break;
2114 s = skip_token(s, end_s, close_paren_token);
2115 if (s == NULL)
2116 break;
2118 subelement->type = e_type;
2119 if (e_type == me_extract) {
2120 subelement->element.extract.fmt = base;
2121 subelement->element.extract.item = item;
2122 } else {
2123 subelement->type = me_print;
2124 subelement->element.print.fmt = base;
2125 subelement->element.print.numItems = numItems;
2126 subelement->element.print.item = print_item;
2127 subelement->element.print.doElide =
2128 sub.element.print.doElide;
2129 subelement->element.print.elide =
2130 sub.element.print.elide;
2132 if (p_error == no_parse_error)
2133 return (s);
2135 free_mapping_item(&item);
2136 if (base != NULL)
2137 free_mapping_format(base);
2138 if (print_item) {
2139 for (n = 0; n < numItems; n++)
2140 free_mapping_item(&print_item[n]);
2141 free(print_item);
2144 return (NULL);
2148 * FUNCTION: skip_get_dn
2150 * Get first token after dn
2152 * RETURN VALUE: NULL if error (not valid dn)
2153 * position of beginning next token after dn
2155 * INPUT: the attribute value
2158 const char *
2159 skip_get_dn(const char *dn, const char *end)
2161 size_t len = 0;
2162 bool_t in_quote = FALSE;
2163 bool_t goteq = FALSE;
2164 bool_t gotch = FALSE;
2165 bool_t done = FALSE;
2166 bool_t last_comma = FALSE;
2167 const char *last_dn = dn;
2169 while (!done) {
2170 dn += len;
2171 if (last_comma) {
2172 last_dn = dn;
2173 last_comma = FALSE;
2175 if (dn >= end)
2176 break;
2177 len = 1;
2178 switch (*dn) {
2179 case ESCAPE_CHAR:
2180 len = 2;
2181 gotch = TRUE;
2182 break;
2183 case DOUBLE_QUOTE_CHAR:
2184 in_quote = !in_quote;
2185 break;
2186 case QUESTION_MARK:
2187 case CLOSE_PAREN_CHAR:
2188 case COLON_CHAR:
2189 done = !in_quote;
2190 /* FALLTHRU */
2191 case SEMI_COLON_CHAR:
2192 case PLUS_SIGN:
2193 case COMMA_CHAR:
2194 if (!in_quote) {
2195 if (!goteq || !gotch)
2196 return (last_dn);
2197 goteq = FALSE;
2198 gotch = FALSE;
2199 if (*dn != PLUS_SIGN)
2200 last_dn = dn;
2201 last_comma = *dn == COMMA_CHAR;
2202 } else {
2203 gotch = TRUE;
2205 break;
2206 case EQUAL_CHAR:
2207 if (!in_quote) {
2208 if (!gotch || goteq)
2209 return (NULL);
2210 goteq = TRUE;
2211 gotch = FALSE;
2212 } else {
2213 gotch = TRUE;
2215 break;
2216 default:
2217 if (!is_whitespace(*dn))
2218 gotch = TRUE;
2219 break;
2223 if (dn == end) {
2224 if (!in_quote && goteq && gotch)
2225 last_dn = dn;
2228 return (last_dn);
2232 * FUNCTION: get_ldap_filter_element
2234 * Get an ldap filter element for a given string
2236 * RETURN VALUE: NULL if error
2237 * __nis_mapping_element_t if success
2239 * INPUT: the string to parse
2242 static __nis_mapping_element_t *
2243 get_ldap_filter_element(
2244 const char *s,
2245 const char *end_s
2248 token_type t;
2249 const char *begin_token;
2250 const char *end_token;
2251 char *format_str;
2252 __nis_mapping_element_t *e = 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 != open_paren_token)
2258 return (NULL);
2260 begin_token = s;
2261 end_token = end_s;
2262 s = get_next_token(&begin_token, &end_token, &t);
2263 if (s == NULL || t != quoted_string_token)
2264 return (NULL);
2266 format_str = s_strndup(begin_token, end_token - begin_token);
2267 if (format_str == NULL)
2268 return (NULL);
2269 e = (__nis_mapping_element_t *)
2270 s_calloc(1, sizeof (__nis_mapping_element_t));
2271 if (e != NULL) {
2272 (void) get_print_mapping_element(s, end_s,
2273 format_str, e, mit_nisplus);
2274 if (p_error != no_parse_error) {
2275 free_mapping_element(e);
2276 e = NULL;
2279 free(format_str);
2280 return (e);
2284 * FUNCTION: get_search_triple
2286 * Get the search triple or if NULL determine if valid
2288 * RETURN VALUE: NULL if error
2289 * position of beginning next token after
2290 * search triple
2292 * INPUT: the attribute value
2295 const char *
2296 get_search_triple(
2297 const char *s,
2298 const char *end_s,
2299 __nis_search_triple_t *triple
2302 const char *begin_token;
2303 const char *end_token;
2304 char *search_base = NULL;
2305 int scope = LDAP_SCOPE_ONELEVEL;
2306 char *filter = NULL;
2307 const char *s1;
2308 __nis_mapping_element_t
2309 *element = NULL;
2312 * The form of the searchTriple is assumed to be as follows:
2313 * searchTriple = [baseDN] ["?" [scope] ["?" [filter]]]
2314 * baseDN = Base DN for search
2315 * scope = "base" | "one" | "sub"
2316 * filter = LDAP search filter
2318 for (; p_error == no_parse_error; ) {
2319 while (s < end_s && is_whitespace(*s))
2320 s++;
2321 if (s == end_s)
2322 break;
2324 if (!IS_TERMINAL_CHAR(*s)) {
2325 begin_token = s;
2326 s = skip_get_dn(begin_token, end_s);
2327 if (s == NULL) {
2328 p_error = parse_invalid_dn;
2329 break;
2331 if (triple != NULL) {
2332 search_base = s_strndup(begin_token,
2333 s - begin_token);
2334 if (search_base == NULL)
2335 break;
2337 while (s < end_s && is_whitespace(*s))
2338 s++;
2339 if (s == end_s)
2340 break;
2343 if (!IS_TERMINAL_CHAR(*s)) {
2344 p_error = parse_bad_ldap_item_format;
2345 break;
2347 if (*s != QUESTION_MARK)
2348 break;
2350 s++;
2351 while (s < end_s && is_whitespace(*s))
2352 s++;
2353 if (s == end_s)
2354 break;
2356 /* base, one, or sub, or empty value */
2357 if (!IS_TERMINAL_CHAR(*s)) {
2358 if ((s1 = skip_string("base", s, end_s - s)) != NULL) {
2359 scope = LDAP_SCOPE_BASE;
2360 } else if ((s1 = skip_string("one", s, end_s - s)) !=
2361 NULL) {
2362 scope = LDAP_SCOPE_ONELEVEL;
2363 } else if ((s1 = skip_string("sub", s, end_s - s)) !=
2364 NULL) {
2365 scope = LDAP_SCOPE_SUBTREE;
2366 } else if (s + 1 < end_s && *s != QUESTION_MARK) {
2367 p_error = parse_invalid_scope;
2368 break;
2370 if (s1 != NULL)
2371 s = s1;
2372 while (s < end_s && is_whitespace(*s))
2373 s++;
2376 if (s == end_s)
2377 break;
2378 if (*s != QUESTION_MARK)
2379 break;
2380 s++;
2381 while (s < end_s && is_whitespace(*s))
2382 s++;
2383 if (s == end_s || IS_TERMINAL_CHAR(*s))
2384 break;
2386 /* LDAP search filter */
2387 if (*s == OPEN_PAREN_CHAR) {
2388 begin_token = s;
2389 end_token = end_s;
2390 s = get_ldap_filter(&begin_token, &end_token);
2391 if (s == NULL)
2392 break;
2393 s = end_token;
2394 element = get_ldap_filter_element(begin_token, end_token);
2395 if (element != NULL)
2396 break;
2397 } else {
2398 begin_token = s;
2399 end_token = end_s;
2400 s = get_ava_list(&begin_token, &end_token, TRUE);
2401 if (s == NULL)
2402 break;
2403 s = end_token;
2405 if (triple != NULL)
2406 filter = s_strndup(begin_token, s - begin_token);
2407 if (p_error == no_parse_error)
2408 break;
2410 if (p_error == no_parse_error && triple != NULL) {
2411 triple->base = search_base;
2412 triple->scope = scope;
2413 triple->attrs = filter;
2414 triple->element = element;
2415 element = NULL;
2416 filter = NULL;
2417 search_base = NULL;
2420 if (search_base != NULL)
2421 free(search_base);
2422 if (filter != NULL)
2423 free(filter);
2424 if (element != NULL) {
2425 free_mapping_element(element);
2426 free(element);
2428 return (p_error == no_parse_error ? s : NULL);
2432 * FUNCTION: get_mapping_format
2434 * Get the __nis_mapping_format_t from the string
2436 * RETURN VALUE: FALSE if error
2437 * TRUE if __nis_mapping_format_t returned
2439 * INPUT: the format string
2442 static bool_t
2443 get_mapping_format(
2444 const char *fmt_string,
2445 __nis_mapping_format_t **fmt,
2446 int *nfmt,
2447 int *numItems,
2448 bool_t print_mapping)
2450 const char *f = fmt_string;
2451 const char *ef;
2452 __nis_mapping_format_t *b;
2453 __nis_mapping_format_t *base = NULL;
2454 int n = 0;
2455 int nItems = 0;
2457 f = fmt_string;
2458 ef = f + strlen(f);
2459 base = (__nis_mapping_format_t *)
2460 s_calloc(1, sizeof (__nis_mapping_format_t));
2462 if (base == NULL)
2463 return (FALSE);
2464 base->type = mmt_begin;
2465 n++;
2467 for (;;) {
2468 b = (__nis_mapping_format_t *)s_realloc(
2469 base, (n + 1) * sizeof (__nis_mapping_format_t));
2471 if (b == NULL)
2472 break;
2473 base = b;
2474 base[n].type = mmt_end;
2475 if (f == ef) {
2476 if (nfmt)
2477 *nfmt = n + 1;
2478 *fmt = base;
2479 if (numItems)
2480 *numItems = nItems;
2481 return (TRUE);
2483 if (print_mapping)
2484 f = get_next_print_format_item(f, ef, &base[n]);
2485 else
2486 f = get_next_extract_format_item(f, ef, &base[n]);
2489 if (f == NULL)
2490 break;
2491 if (base[n].type == mmt_item ||
2492 base[n].type == mmt_berstring)
2493 nItems++;
2494 n++;
2496 if (base != NULL)
2497 free_mapping_format(base);
2498 return (FALSE);
2502 * FUNCTION: getIndex
2504 * Returns a string containing the index
2506 * RETURN VALUE: NULL if error
2507 * a string containing the index
2509 * INPUT: attribute containing the index
2512 static char *
2513 getIndex(const char **s_cur, const char *s_end)
2515 const char *s = *s_cur + 1;
2516 const char *s1;
2517 char *s_index;
2518 char *s_index1;
2519 char *s_index_end;
2520 int n_brackets = 1;
2521 bool_t in_quotes = FALSE;
2522 char *index = NULL;
2524 while (s < s_end && is_whitespace(*s))
2525 s++;
2526 for (s1 = s; s1 < s_end; s1++) {
2527 if (*s1 == ESCAPE_CHAR)
2528 s1++;
2529 else if (*s1 == DOUBLE_QUOTE_CHAR) {
2530 in_quotes = !in_quotes;
2531 } else if (in_quotes)
2533 else if (*s1 == CLOSE_BRACKET) {
2534 if (--n_brackets == 0)
2535 break;
2536 } else if (*s1 == OPEN_BRACKET)
2537 n_brackets++;
2540 if (n_brackets == 0) {
2541 index = s_strndup(s, s1 - s);
2542 if (index != NULL) {
2543 s_index_end = index + (s1 - s);
2544 s_index1 = index;
2545 for (s_index = index; s_index < s_index_end;
2546 s_index++) {
2547 if (*s_index == ESCAPE_CHAR) {
2548 *s_index1++ = *s_index++;
2549 } else if (*s_index == DOUBLE_QUOTE_CHAR) {
2550 in_quotes = !in_quotes;
2551 } else if (!in_quotes &&
2552 is_whitespace(*s_index)) {
2553 continue;
2555 *s_index1++ = *s_index;
2557 *s_index1 = *s_index;
2559 s = s1 + 1;
2561 while (s < s_end && is_whitespace(*s))
2562 s++;
2563 *s_cur = s;
2565 } else
2566 p_error = parse_mismatched_brackets;
2568 return (index);
2572 * FUNCTION: parse_index
2574 * Parse attribute string to get __nis_index_t
2576 * RETURN VALUE: FALSE if error
2577 * TRUE if __nis_index_t returned
2579 * INPUT: the attribute value to parse
2582 bool_t
2583 parse_index(const char *s, const char *end_s, __nis_index_t *index)
2585 const char *begin_token;
2586 const char *end_token;
2587 char *name_str = NULL;
2588 char **name;
2589 char *fmt_string = NULL;
2590 __nis_mapping_format_t *v = NULL;
2591 __nis_mapping_format_t **value;
2592 token_type t;
2593 int n = 0;
2595 if (index != NULL)
2596 (void) memset(index, 0, sizeof (*index));
2598 while (s < end_s) {
2599 if (n > 0) {
2600 s = skip_token(s, end_s, comma_token);
2601 if (s == NULL) {
2602 p_error = parse_bad_index_format;
2603 break;
2606 begin_token = s;
2607 end_token = end_s;
2608 s = get_next_token(&begin_token, &end_token, &t);
2609 if (s == NULL)
2610 break;
2611 if (t != string_token) {
2612 p_error = parse_bad_index_format;
2613 break;
2615 s = skip_token(s, end_s, equal_token);
2616 if (s == NULL) {
2617 p_error = parse_bad_index_format;
2618 break;
2620 if (index != NULL) {
2621 name_str = s_strndup_esc(begin_token,
2622 end_token - begin_token);
2623 if (name_str == NULL)
2624 break;
2626 begin_token = s;
2627 end_token = end_s;
2628 s = get_next_token(&begin_token, &end_token, &t);
2629 if (s == NULL)
2630 break;
2631 if (t != string_token && t != quoted_string_token) {
2632 p_error = parse_bad_index_format;
2633 break;
2635 fmt_string = s_strndup(begin_token, end_token - begin_token);
2636 if (fmt_string == NULL)
2637 break;
2638 if (!get_mapping_format(fmt_string, &v, NULL, NULL, FALSE))
2639 break;
2640 free(fmt_string);
2641 fmt_string = NULL;
2642 if (index != NULL) {
2643 name = s_realloc(index->name,
2644 (n + 1) * sizeof (char *));
2645 if (name == NULL)
2646 break;
2647 value = s_realloc(index->value,
2648 (n + 1) * sizeof (__nis_mapping_format_t *));
2649 if (value == NULL)
2650 break;
2651 name[n] = name_str;
2652 name_str = NULL;
2653 value[n] = v;
2654 v = NULL;
2655 index->numIndexes = ++n;
2656 index->name = name;
2657 index->value = value;
2658 } else if (v != NULL) {
2659 free_mapping_format(v);
2660 v = NULL;
2663 if (p_error != no_parse_error) {
2664 if (name_str != NULL)
2665 free(name_str);
2666 if (v != NULL)
2667 free_mapping_format(v);
2668 if (fmt_string != NULL)
2669 free(fmt_string);
2670 if (index != NULL)
2671 free_index(index);
2673 return (p_error != no_parse_error);
2677 * FUNCTION: get_deleteDisp
2679 * Parse deleteDisp. Sets p_error if an error occurred.
2681 * RETURN VALUE: TRUE on success
2682 * FAILURE on failure
2684 * INPUT: begin and end of string and __nis_object_dn_t
2687 static bool_t
2688 get_deleteDisp(const char *s_begin, const char *s_end,
2689 __nis_object_dn_t *obj_dn)
2692 * deleteDisp: "always" | perDbId | "never"
2693 * perDbId: "dbid" "=" delDatabaseId
2696 if (same_string("always", s_begin, s_end - s_begin)) {
2697 obj_dn->delDisp = dd_always;
2698 } else if (same_string("never", s_begin, s_end - s_begin)) {
2699 obj_dn->delDisp = dd_never;
2700 } else if ((s_begin = skip_string("dbid", s_begin, s_end - s_begin))
2701 != NULL) {
2702 obj_dn->delDisp = dd_perDbId;
2703 while (s_begin < s_end && is_whitespace(*s_begin))
2704 s_begin++;
2705 if (s_begin == s_end || *s_begin != EQUAL_CHAR) {
2706 p_error = parse_object_dn_syntax_error;
2707 } else {
2708 s_begin++;
2709 while (s_begin < s_end && is_whitespace(*s_begin))
2710 s_begin++;
2711 while (s_begin < s_end && is_whitespace(s_end[-1]))
2712 s_end--;
2713 if (s_begin == s_end) {
2714 p_error = parse_object_dn_syntax_error;
2715 } else {
2716 obj_dn->dbIdName =
2717 s_strndup(s_begin, s_end - s_begin);
2720 } else {
2721 p_error = parse_object_dn_syntax_error;
2723 return (p_error == no_parse_error);