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
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]
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"
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
86 add_mapping_attribute(
87 config_key attrib_num
,
88 const char *attrib_val
,
90 __nis_table_mapping_t
**table_mapping
)
93 const char *attrib_end
;
94 const char *db_id_end
;
95 const char *begin_token
;
96 const char *end_token
;
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
;
106 attrib_end
= attrib_val
+ attrib_len
;
107 for (s
= attrib_val
; s
< attrib_end
; s
++)
108 if (*s
== COLON_CHAR
)
111 if (s
== attrib_end
|| *attrib_val
== COLON_CHAR
) {
112 p_error
= parse_unexpected_data_end_rule
;
117 while (s
> attrib_val
&& is_whitespace(s
[-1]))
120 if (s
== attrib_val
) {
121 p_error
= parse_unexpected_data_end_rule
;
126 tmp_dbId
= s_strndup(attrib_val
, s
- attrib_val
);
127 if (tmp_dbId
== NULL
) {
128 p_error
= parse_no_mem_error
;
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.
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
;
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
;
169 /* a table mapping already exists, use it */
174 while (s
< attrib_end
&& is_whitespace(*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
,
185 while (is_whitespace(*s
) && s
< attrib_end
)
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;
195 case key_yp_comment_char
:
196 if (t_mapping
->commentChar
!=
197 DEFAULT_COMMENT_CHAR
) {
198 warn_duplicate_map(t_mapping
->dbId
, attrib_num
);
201 while (is_whitespace(*s
) && s
< attrib_end
)
203 if (s
< attrib_end
&& (s
+1) < attrib_end
&&
204 (s
+2) <= attrib_end
) {
205 while (is_whitespace(attrib_end
[-1]))
207 while (*s
!= SINGLE_QUOTE_CHAR
)
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
;
216 /* anything else is an error */
217 p_error
= parse_bad_yp_comment_error
;
221 p_error
= parse_bad_yp_comment_error
;
224 case key_yp_repeated_field_separators
:
225 while (s
< attrib_end
&& is_whitespace(*s
))
227 if (s
< attrib_end
) {
228 while (is_whitespace(attrib_end
[-1]))
230 while (s
< attrib_end
&&
231 *s
!= DOUBLE_QUOTE_CHAR
)
235 while (s
< attrib_end
&&
236 *s
!= DOUBLE_QUOTE_CHAR
) {
237 if (*s
== ESCAPE_CHAR
)
241 t_mapping
->separatorStr
=
242 s_strndup(begin_token
, s
- begin_token
);
243 if (t_mapping
->separatorStr
== NULL
)
246 p_error
= parse_bad_field_separator_error
;
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
,
256 if (parse_name_fields(s
, attrib_end
, t_mapping
)) {
257 p_error
= parse_bad_name_field
;
260 case key_yp_db_id_map
:
262 if (t_mapping
->objName
!= NULL
) {
263 warn_duplicate_map(t_mapping
->dbId
, attrib_num
);
267 if (s
< attrib_end
&& *s
== OPEN_BRACKET
) {
268 index_string
= getIndex(&s
, attrib_end
);
269 if (index_string
== NULL
)
271 (void) parse_index(index_string
,
272 index_string
+ strlen(index_string
),
275 if (p_error
!= no_parse_error
)
278 while (is_whitespace(*s
) && s
< attrib_end
)
280 if (s
< attrib_end
) {
281 while (is_whitespace(attrib_end
[-1]))
284 s_strndup_esc(s
, attrib_end
- s
);
287 p_error
= parse_bad_map_error
;
289 t_mapping
->objName
= s_strndup(s
, 0);
294 case key_yp_entry_ttl
:
296 if (t_mapping
->initTtlLo
!= (time_t)NO_VALUE_SET
) {
297 warn_duplicate_map(t_mapping
->dbId
, attrib_num
);
301 if (!get_ttls(s
, attrib_end
, t_mapping
))
302 p_error
= parse_bad_ttl_format_error
;
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
);
311 objectDN
= parse_object_dn(s
, attrib_end
);
312 if (objectDN
== NULL
)
314 t_mapping
->objectDN
= objectDN
;
315 t_mapping
->seq_num
= seq_num
++;
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
);
325 get_mapping_rule(s
, attrib_end
- s
, t_mapping
, TRUE
);
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
);
335 get_mapping_rule(s
, attrib_end
- s
, t_mapping
, FALSE
);
339 p_error
= parse_internal_error
;
342 if (p_error
== no_parse_error
) {
344 if (*table_mapping
== NULL
)
345 *table_mapping
= t_mapping
;
347 for (t
= *table_mapping
; t
->next
!= NULL
;
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
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
,
376 __yp_domain_context_t
*ypDomains
)
379 const char *attrib_end
;
385 attrib_end
= attrib_val
+ attrib_len
;
386 for (s
= attrib_val
; s
< attrib_end
; s
++) {
387 if (*s
== COLON_CHAR
) {
391 while (s
> attrib_val
&& is_whitespace(s
[-1]))
394 if (s
== attrib_val
) {
395 p_error
= parse_unexpected_data_end_rule
;
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
409 switch (attrib_num
) {
410 case key_yp_domain_context
:
411 numDomains
= ypDomains
->numDomains
;
412 ypDomains
->domainLabels
=
413 (char **)s_realloc(ypDomains
->domainLabels
,
415 sizeof (ypDomains
->domainLabels
[0]));
416 if (ypDomains
->domainLabels
== NULL
) {
417 p_error
= parse_no_mem_error
;
418 free_yp_domain_context(ypDomains
);
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
);
428 ypDomains
->numDomains
= numDomains
+ 1;
429 while (s
< attrib_end
&& is_whitespace(*s
))
431 if (*s
== COLON_CHAR
)
433 while (s
< attrib_end
&& is_whitespace(*s
))
436 (char **)s_realloc(ypDomains
->domains
,
438 sizeof (ypDomains
->domains
[0]));
439 if (ypDomains
->domains
== NULL
) {
440 p_error
= parse_no_mem_error
;
441 free_yp_domain_context(ypDomains
);
445 if (s
< attrib_end
) {
446 while (is_whitespace(attrib_end
[-1]))
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
);
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
);
463 case key_yppasswdd_domains
:
464 ypDomains
->yppasswddDomainLabels
=
466 ypDomains
->yppasswddDomainLabels
,
467 (ypDomains
->numYppasswdd
+ 1) *
468 sizeof (ypDomains
->yppasswddDomainLabels
[0]));
469 if (ypDomains
->yppasswddDomainLabels
== NULL
) {
470 p_error
= parse_no_mem_error
;
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
++;
484 return (p_error
== no_parse_error
? 0 : -1);
490 * Parse time to live attribute
492 * RETURN VALUE: TRUE on success, FALSE on failure
494 * INPUT: the attribute value
501 __nis_table_mapping_t
*t_mapping
)
503 time_t initTtlHi
= 0;
504 time_t initTtlLo
= 0;
509 * attribute should be of the form
510 * initialTTLlo ":" initialTTLhi ":" runningTTL
514 p_error
= parse_bad_ttl_format_error
;
519 while (s
< s_end
&& isdigit(*s
)) {
520 digit
= (*s
++) - '0';
521 if (WILL_OVERFLOW_TIME(initTtlLo
, digit
))
522 initTtlLo
= TIME_MAX
;
524 initTtlLo
= initTtlLo
* 10 + digit
;
527 initTtlLo
= ONE_HOUR
;
530 while (s
< s_end
&& is_whitespace(*s
))
532 if (s
+ 1 >= s_end
|| *s
++ != COLON_CHAR
) {
533 p_error
= parse_bad_ttl_format_error
;
537 while (s
< s_end
&& is_whitespace(*s
))
540 while (s
< s_end
&& isdigit(*s
)) {
541 digit
= (*s
++) - '0';
542 if (WILL_OVERFLOW_TIME(initTtlHi
, digit
))
543 initTtlHi
= TIME_MAX
;
545 initTtlHi
= initTtlHi
* 10 + digit
;
548 initTtlHi
= initTtlLo
;
551 while (s
< s_end
&& is_whitespace(*s
))
553 if (s
>= s_end
|| *s
++ != COLON_CHAR
) {
554 p_error
= parse_bad_ttl_format_error
;
558 while (s
< s_end
&& is_whitespace(*s
))
561 while (s
< s_end
&& isdigit(*s
)) {
562 digit
= (*s
++) - '0';
563 if (WILL_OVERFLOW_TIME(ttl
, digit
))
566 ttl
= ttl
* 10 + digit
;
571 while (s
< s_end
&& is_whitespace(*s
))
574 p_error
= parse_bad_ttl_format_error
;
578 t_mapping
->initTtlLo
= initTtlLo
;
579 t_mapping
->initTtlHi
= initTtlHi
;
580 t_mapping
->ttl
= ttl
;
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.
595 parse_name_fields(const char *name_s
,
596 const char *name_s_end
,
597 __nis_table_mapping_t
*t_map
)
602 int parse_next_line
= 1;
604 const char *begin_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
;
615 t_map
->numColumns
= 0;
617 for (; parse_next_line
> 0; parse_next_line
--) {
621 while (name_s
< name_s_end
&& *name_s
!= OPEN_PAREN_CHAR
)
623 if (name_s
== name_s_end
) {
624 p_error
= parse_unexpected_data_end_rule
;
627 while (name_s
< name_s_end
&& *name_s
!= DOUBLE_QUOTE_CHAR
)
629 if (name_s
== name_s_end
) {
630 p_error
= parse_unexpected_data_end_rule
;
633 begin_fmt
= ++name_s
; /* start of format string */
634 while (name_s
< name_s_end
&& *name_s
!= DOUBLE_QUOTE_CHAR
)
636 if (name_s
== name_s_end
) {
637 p_error
= parse_unexpected_data_end_rule
;
641 fmt_string
= s_strndup(begin_fmt
, end_fmt
- begin_fmt
);
642 if (fmt_string
== NULL
) {
643 p_error
= parse_no_mem_error
;
646 if (!get_mapping_format(fmt_string
, &base
, &n
, NULL
, FALSE
)) {
647 p_error
= parse_internal_error
;
654 for (n
= 0; base
[n
].type
!= mmt_end
; n
++) {
655 if (base
[n
].type
!= mmt_item
&& base
[n
].type
657 if (base
[n
].type
== mmt_berstring_null
)
658 base
[n
].type
= mmt_berstring
;
661 while (name_s
< name_s_end
&& *name_s
!= COMMA_CHAR
)
663 name_s
++; /* now at comma char */
664 while (name_s
< name_s_end
&& is_whitespace(*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
;
674 if (token
!= string_token
) {
675 p_error
= parse_item_expected_error
;
678 item
= (__nis_mapping_item_t
*)s_realloc(item
,
680 sizeof (__nis_mapping_item_t
));
682 p_error
= parse_no_mem_error
;
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
);
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
);
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
);
710 while (name_s
< name_s_end
&& is_whitespace(*name_s
))
712 if (*name_s
== COMMA_CHAR
)
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
);
722 elmnt
= (__nis_mapping_element_t
*)s_realloc(elmnt
,
724 sizeof (__nis_mapping_element_t
));
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
;
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
;
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
))
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
);
765 for (n
= 0; n
< t_map
->numColumns
; n
++) {
766 free_mapping_item(&item
[n
]);
771 free_mapping_element(elmnt
);
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
786 * INPUT: the attribute value
789 static __nis_object_dn_t
*
790 parse_object_dn(const char *s
, const char *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]]]
811 s
= get_next_object_dn_token(&s_begin
, &s_end
, &token
);
815 if (token
== dn_no_token
|| token
== dn_semi_token
) {
822 if (token
== dn_no_token
)
824 dn_state
= dn_begin_parse
;
827 next
= (__nis_object_dn_t
*)
828 s_calloc(1, sizeof (__nis_object_dn_t
));
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
)
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
;
846 if (!validate_dn(s_begin
, s_end
- s_begin
))
849 s_strndup_esc(s_begin
, s_end
- s_begin
);
850 dn_state
= 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
;
860 p_error
= parse_object_dn_syntax_error
;
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
;
878 p_error
= parse_invalid_scope
;
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
;
888 p_error
= parse_object_dn_syntax_error
;
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
;
897 if (!validate_ldap_filter(s_begin
, s_end
))
900 s_strndup_esc(s_begin
, s_end
- s_begin
);
901 dn_state
= dn_got_read_filter
;
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
;
911 p_error
= parse_object_dn_syntax_error
;
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
;
919 if (!validate_dn(s_begin
, s_end
- s_begin
))
922 s_strndup_esc(s_begin
, s_end
- s_begin
);
923 dn_state
= dn_got_write_dn
;
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
;
932 p_error
= parse_object_dn_syntax_error
;
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
;
949 p_error
= parse_invalid_scope
;
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
;
958 p_error
= parse_object_dn_syntax_error
;
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
;
966 if (!validate_ldap_filter(s_begin
, s_end
))
969 s_strndup_esc(s_begin
, s_end
- s_begin
);
970 dn_state
= dn_got_write_filter
;
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
;
980 p_error
= parse_semi_expected_error
;
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
;
988 if (!get_deleteDisp(s_begin
, s_end
, next
))
990 dn_state
= dn_got_delete_dsp
;
993 case dn_got_delete_dsp
:
994 p_error
= parse_object_dn_syntax_error
;
998 if (p_error
!= no_parse_error
)
1001 if (p_error
!= no_parse_error
) {
1003 free_object_dn(obj_dn
);
1005 free_object_dn(next
);
1007 } else if (next
!= NULL
) {
1012 } else if (obj_dn
== NULL
)
1013 obj_dn
= (__nis_object_dn_t
*)
1014 s_calloc(1, sizeof (__nis_object_dn_t
));
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
1033 __nis_table_mapping_t
*tbl
,
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; */
1048 * The attribute value is of the form
1049 * colattrspec *("," colattrspec)
1050 * colattrspec = lhs "=" rhs
1051 * lhs = lval | namespeclist
1052 * rhs = rval | [namespec]
1056 if ((next
= (__nis_mapping_rule_t
*)
1057 s_calloc(1, sizeof (__nis_mapping_rule_t
))) == NULL
)
1060 s
= get_lhs(s
, end_s
, &next
->lhs
,
1061 to_ldap
? mit_ldap
: mit_nisplus
);
1067 s1
= get_next_token(&begin_token
, &end_token
, &t
);
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
);
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
;
1084 rule
= (__nis_mapping_rule_t
**)
1085 malloc(sizeof (__nis_mapping_rule_t
*));
1089 rule
= (__nis_mapping_rule_t
**)s_realloc(rule
,
1091 sizeof (__nis_mapping_rule_t
*));
1096 rule
[nRules
++] = next
;
1101 s
= get_next_token(&begin_token
, &end_token
, &t
);
1104 if (t
== comma_token
)
1106 if (t
!= no_token
) {
1107 p_error
= parse_unexpected_data_end_rule
;
1111 tbl
->numRulesToLDAP
= nRules
;
1112 tbl
->ruleToLDAP
= rule
;
1114 tbl
->numRulesFromLDAP
= nRules
;
1115 tbl
->ruleFromLDAP
= rule
;
1121 for (i
= 0; i
< nRules
; i
++)
1122 free_mapping_rule(rule
[i
]);
1126 free_mapping_rule(next
);
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
1141 get_lhs(const char *s
,
1143 __nis_mapping_rlhs_t
*lhs
,
1144 __nis_mapping_item_type_t item_type
)
1147 const char *begin_token
;
1148 const char *end_token
;
1150 __nis_mapping_element_t
*e
= NULL
;
1153 * lhs can be expressed as:
1159 * lhs = lval | namespeclist
1160 * lval = "(" formatspec "," namespec *("," namespec) ")"
1161 * namespeclist = namespec | "(" namespec *("," namespec) ")"
1164 for (; p_error
== no_parse_error
; ) {
1167 s
= get_next_token(&begin_token
, &end_token
, &t
);
1170 if (t
== no_token
) {
1171 p_error
= parse_unexpected_data_end_rule
;
1175 e
= (__nis_mapping_element_t
*)
1176 s_calloc(1, sizeof (__nis_mapping_element_t
));
1180 if (t
== open_paren_token
) {
1187 s
= get_next_token(&begin_token
, &end_token
, &t
);
1191 if (t
== quoted_string_token
) {
1192 s
= get_lhs_match(sav_s
, end_s
, lhs
, item_type
);
1195 } else if (t
== string_token
) {
1196 s
= get_lhs_paren_item(sav_s
, end_s
, lhs
,
1201 p_error
= parse_bad_lhs_format_error
;
1204 } else if (t
== string_token
) {
1205 s
= get_mapping_item(begin_token
, end_s
,
1206 &e
->element
.item
, item_type
);
1210 if (!add_element(e
, lhs
))
1214 p_error
= parse_bad_lhs_format_error
;
1218 s
= skip_token(s
, end_s
, equal_token
);
1221 if (p_error
== no_parse_error
)
1225 free_mapping_element(e
);
1231 * FUNCTION: get_lhs_match
1233 * Parse left hand side of mapping rule attribute in case of
1236 * RETURN VALUE: NULL if error
1237 * position of beginning rhs
1239 * INPUT: the attribute value and mapping rule type
1246 __nis_mapping_rlhs_t
*lhs
,
1247 __nis_mapping_item_type_t item_type
)
1250 const char *begin_token
;
1251 const char *end_token
;
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
; ) {
1267 s
= get_next_token(&begin_token
, &end_token
, &t
);
1268 if (s
== NULL
|| t
!= quoted_string_token
) {
1269 p_error
= parse_internal_error
;
1274 fmt_string
= s_strndup(begin_token
, end_token
- begin_token
);
1275 if (fmt_string
== NULL
)
1278 if (!get_mapping_format(fmt_string
, &base
, &n
, NULL
, FALSE
))
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
;
1288 s
= skip_token(s
, end_s
, comma_token
);
1290 p_error
= parse_not_enough_extract_items
;
1295 s
= get_next_token(&begin_token
, &end_token
, &t
);
1298 if (t
!= string_token
) {
1299 p_error
= parse_item_expected_error
;
1302 itm
= (__nis_mapping_item_t
*)
1303 s_realloc(item
, (nElements
+ 1) *
1304 sizeof (__nis_mapping_item_t
));
1309 s
= get_mapping_item(begin_token
, end_s
,
1310 &item
[nElements
], item_type
);
1315 if (p_error
!= no_parse_error
)
1318 s
= skip_token(s
, end_s
, close_paren_token
);
1324 if (nElements
== 0) {
1325 p_error
= parse_no_match_item
;
1328 e
= (__nis_mapping_element_t
*)s_calloc(1,
1329 sizeof (__nis_mapping_element_t
));
1333 e
->element
.match
.numItems
= nElements
;
1334 e
->element
.match
.item
= item
;
1335 e
->element
.match
.fmt
= base
;
1336 lhs
->numElements
= 1;
1339 if (p_error
== no_parse_error
)
1343 for (n
= 0; n
< nElements
; n
++)
1344 free_mapping_item(&item
[n
]);
1347 if (fmt_string
!= NULL
)
1350 free_mapping_format(base
);
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
1371 __nis_mapping_rlhs_t
*lhs
,
1372 __nis_mapping_item_type_t item_type
)
1375 const char *begin_token
;
1376 const char *end_token
;
1377 __nis_mapping_element_t
*e
= NULL
;
1382 * "(" namespec *("," namespec) ")"
1386 e
= (__nis_mapping_element_t
*)s_realloc(e
, (n
+ 1) *
1387 sizeof (__nis_mapping_element_t
));
1391 s
= get_mapping_item(s
, end_s
, &e
[n
].element
.item
,
1395 e
[n
].type
= me_item
;
1400 s
= get_next_token(&begin_token
, &end_token
, &t
);
1401 if (s
!= NULL
&& t
== close_paren_token
) {
1402 lhs
->numElements
= n
;
1404 e
[0].element
.item
.repeat
= TRUE
;
1408 if (s
== NULL
|| t
!= comma_token
) {
1409 p_error
= parse_comma_expected_error
;
1413 for (i
= 0; i
< n
; i
++)
1414 free_mapping_element(&e
[i
]);
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
1435 __nis_mapping_rlhs_t
*rhs
,
1436 __nis_mapping_item_type_t item_type
)
1439 * This handles the following cases:
1442 * (fmt, name-list) me_print
1443 * (item, fmt) me_extract
1447 const char *begin_token
;
1448 const char *end_token
;
1450 __nis_mapping_format_t
*fmt
= NULL
;
1451 __nis_mapping_element_t
*e
= NULL
;
1452 __nis_mapping_item_t item
;
1455 (void) memset(&item
, 0, sizeof (item
));
1457 for (; p_error
== no_parse_error
; ) {
1460 s
= get_next_token(&begin_token
, &end_token
, &t
);
1464 e
= (__nis_mapping_element_t
*)
1465 s_calloc(1, sizeof (__nis_mapping_element_t
));
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
) {
1475 s
= get_next_token(&begin_token
, &end_token
, &t
);
1478 if (t
== string_token
) {
1479 /* (item, fmt) - me_extract */
1480 /* (item, "c") - me_split */
1481 s
= get_mapping_item(begin_token
, end_s
,
1487 s
= get_next_token(&begin_token
, &end_token
,
1491 else if (t
== close_paren_token
) {
1493 e
->element
.item
= item
;
1495 rhs
->numElements
= 1;
1498 } else if (t
!= comma_token
) {
1499 p_error
= parse_comma_expected_error
;
1505 s
= get_next_token(&begin_token
, &end_token
,
1507 if (s
== NULL
|| t
!= quoted_string_token
) {
1509 parse_format_string_expected_error
;
1513 if (end_token
== begin_token
+ 1 ||
1514 *begin_token
== ESCAPE_CHAR
&&
1515 end_token
== begin_token
+ 2) {
1517 e
->element
.split
.item
= item
;
1518 e
->element
.split
.delim
= *begin_token
;
1520 str
= s_strndup(begin_token
,
1521 end_token
- begin_token
);
1524 if (!get_mapping_format(str
, &fmt
,
1531 parse_bad_extract_format_spec
;
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
);
1546 s
= get_print_mapping_element(s
, end_s
,
1551 p_error
= parse_start_rhs_unrecognized
;
1555 p_error
= parse_start_rhs_unrecognized
;
1560 rhs
->numElements
= 1;
1562 if (p_error
== no_parse_error
)
1568 free_mapping_format(fmt
);
1570 free_mapping_element(e
);
1571 free_mapping_item(&item
);
1577 * FUNCTION: get_print_mapping_element
1579 * Parse a print mapping rule attribute in case of the form
1582 * RETURN VALUE: NULL if error
1583 * position of beginning next mapping rule
1585 * INPUT: the attribute value and mapping rule type
1589 get_print_mapping_element(
1593 __nis_mapping_element_t
*e
,
1594 __nis_mapping_item_type_t item_type
)
1597 const char *begin_token
;
1598 const char *end_token
;
1601 __nis_mapping_format_t
*base
= NULL
;
1602 __nis_mapping_sub_element_t
*subElement
= NULL
;
1607 for (; p_error
== no_parse_error
; ) {
1608 if (!get_mapping_format(fmt_string
, &base
, &n
,
1609 &numSubElements
, TRUE
))
1611 subElement
= (__nis_mapping_sub_element_t
*)
1612 s_calloc(numSubElements
,
1613 sizeof (__nis_mapping_sub_element_t
));
1614 if (subElement
== NULL
)
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
;
1623 if (nSub
< numSubElements
) {
1624 s
= skip_token(s
, end_s
, comma_token
);
1626 p_error
= parse_bad_print_format
;
1631 /* namelist may have parens around it */
1632 s
= get_subElement(s
, end_s
, &subElement
[nSub
],
1638 if (p_error
!= no_parse_error
)
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
;
1647 } else if (t
== close_paren_token
) {
1650 } else if (t
== comma_token
) {
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
;
1664 if (subElement
->type
== me_item
&&
1665 !subElement
->element
.item
.repeat
) {
1666 p_error
= parse_cannot_elide
;
1669 elide
= *begin_token
;
1673 p_error
= parse_bad_elide_char
;
1676 s
= skip_token(s
, end_s
, close_paren_token
);
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
)
1692 free_mapping_format(base
);
1693 if (subElement
!= NULL
) {
1694 for (n
= 0; n
< numSubElements
; n
++)
1695 free_mapping_sub_element(&subElement
[n
]);
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
1717 __nis_mapping_item_t
*item
,
1718 __nis_mapping_item_type_t type
)
1721 const char *begin_token
;
1722 const char *end_token
;
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
))
1759 if ((begin_token
= skip_string("ldap:", s
,
1761 item
->type
= mit_ldap
;
1762 } else if ((begin_token
= skip_string("yp:", s
,
1764 item
->type
= mit_nisplus
;
1770 if ((begin_token
= skip_string("ldap:", s
,
1772 item
->type
= mit_ldap
;
1773 } else if ((begin_token
= skip_string("nis+:", s
,
1775 item
->type
= mit_nisplus
;
1776 } else if ((begin_token
= skip_string("nisplus:", s
,
1778 item
->type
= mit_nisplus
;
1786 s
= get_next_token(&begin_token
, &end_token
, &t
);
1787 if (s
== NULL
|| t
!= string_token
) {
1788 p_error
= parse_bad_item_format
;
1792 item
->name
= s_strndup_esc(begin_token
,
1793 end_token
- begin_token
);
1794 if (item
->name
== NULL
)
1796 if (item
->type
== mit_ldap
) {
1797 item
->searchSpec
.triple
.scope
= LDAP_SCOPE_UNKNOWN
;
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
);
1809 } else if (item
->type
== mit_nisplus
) {
1810 while (s
< end_s
&& is_whitespace(*s
))
1813 if (s
< end_s
&& *s
== OPEN_BRACKET
) {
1814 index_string
= getIndex(&s
, end_s
);
1815 if (index_string
== NULL
)
1817 (void) parse_index(index_string
,
1818 index_string
+ strlen(index_string
),
1819 &item
->searchSpec
.obj
.index
);
1821 if (p_error
!= no_parse_error
)
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
);
1833 item
->searchSpec
.obj
.name
= name
;
1837 if (p_error
== no_parse_error
)
1840 free_mapping_item(item
);
1841 (void) memset(item
, 0, sizeof (*item
));
1848 get_print_sub_element(const char *s
,
1850 __nis_mapping_item_type_t type
,
1851 __nis_mapping_sub_element_t
*sub
)
1856 const char *begin_token
;
1857 const char *end_token
;
1859 __nis_mapping_format_t
*base
;
1860 __nis_mapping_item_t
*print_item
;
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
;
1874 s
= skip_token(s
, end_s
, comma_token
);
1876 p_error
= parse_bad_print_format
;
1882 s
= get_next_token(&begin_token
, &end_token
, &t
);
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
;
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
);
1899 p_error
= parse_bad_print_format
;
1904 s
= get_next_token(&begin_token
, &end_token
, &t
);
1907 if (t
!= quoted_string_token
||
1908 begin_token
+ 1 != end_token
) {
1909 p_error
= parse_bad_elide_char
;
1912 sub
->element
.print
.elide
= *begin_token
;
1913 sub
->element
.print
.doElide
= TRUE
;
1914 print_item
[0].repeat
= TRUE
;
1917 s
= get_mapping_item(begin_token
, end_s
,
1918 &print_item
[k
++], type
);
1922 if (p_error
!= no_parse_error
)
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
1944 __nis_mapping_sub_element_t
*subelement
,
1945 __nis_mapping_item_type_t type
)
1948 const char *begin_token
;
1949 const char *end_token
;
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
;
1957 unsigned char delim
;
1958 __nis_mapping_sub_element_t sub
;
1961 * What is the form of we are expecting here
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
; ) {
1974 s
= get_next_token(&begin_token
, &end_token
, &t
);
1977 if (t
== string_token
) { /* me_item */
1978 s
= get_mapping_item(begin_token
, end_s
,
1979 &subelement
->element
.item
, type
);
1982 subelement
->type
= me_item
;
1984 } else if (t
!= open_paren_token
) {
1985 p_error
= parse_item_expected_error
;
1991 s
= get_next_token(&begin_token
, &end_token
, &t
);
1995 if (t
!= string_token
&& t
!= quoted_string_token
) {
1996 p_error
= parse_item_expected_error
;
2000 if (t
== string_token
) {
2001 /* me_item, me_extract or me_split */
2002 s
= get_mapping_item(begin_token
, end_s
, &item
, type
);
2008 s
= get_next_token(&begin_token
, &end_token
, &t
);
2010 p_error
= parse_unexpected_data_end_rule
;
2012 } else if (t
== close_paren_token
) {
2013 subelement
->type
= me_item
;
2015 subelement
->element
.item
= item
;
2017 while (s
< end_s
&& is_whitespace(*s
))
2021 parse_unexpected_data_end_rule
;
2024 if (*s
== DASH_CHAR
&& s
< end_s
) {
2032 subelement
->element
.item
.exItem
2034 (__nis_mapping_item_t
*)
2035 s_malloc(sizeof (__nis_mapping_item_t
));
2037 element
.item
.exItem
)
2039 s
= get_mapping_item(s
, end_s
,
2041 element
.item
.exItem
,
2045 parse_internal_error
;
2048 element
.item
.exItem
);
2050 element
.item
.exItem
=
2057 } else if (t
!= comma_token
) {
2058 p_error
= parse_comma_expected_error
;
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
;
2069 if (end_token
== begin_token
+ 1 ||
2070 *begin_token
== ESCAPE_CHAR
&&
2071 end_token
== begin_token
+ 2) {
2073 delim
= (unsigned char)end_token
[-1];
2074 s
= skip_token(s
, end_s
, close_paren_token
);
2077 subelement
->element
.split
.item
= item
;
2078 subelement
->element
.split
.delim
= delim
;
2079 subelement
->type
= me_split
;
2082 e_type
= me_extract
;
2084 fmt_string
= s_strndup(begin_token
, end_token
- begin_token
);
2085 if (fmt_string
== NULL
)
2087 if (!get_mapping_format(fmt_string
, &base
, &n
, &numItems
,
2088 e_type
== me_print
)) {
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
;
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
)
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
);
2114 s
= skip_token(s
, end_s
, close_paren_token
);
2118 subelement
->type
= e_type
;
2119 if (e_type
== me_extract
) {
2120 subelement
->element
.extract
.fmt
= base
;
2121 subelement
->element
.extract
.item
= item
;
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
)
2135 free_mapping_item(&item
);
2137 free_mapping_format(base
);
2139 for (n
= 0; n
< numItems
; n
++)
2140 free_mapping_item(&print_item
[n
]);
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
2159 skip_get_dn(const char *dn
, const char *end
)
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
;
2183 case DOUBLE_QUOTE_CHAR
:
2184 in_quote
= !in_quote
;
2187 case CLOSE_PAREN_CHAR
:
2191 case SEMI_COLON_CHAR
:
2195 if (!goteq
|| !gotch
)
2199 if (*dn
!= PLUS_SIGN
)
2201 last_comma
= *dn
== COMMA_CHAR
;
2208 if (!gotch
|| goteq
)
2217 if (!is_whitespace(*dn
))
2224 if (!in_quote
&& goteq
&& gotch
)
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(
2249 const char *begin_token
;
2250 const char *end_token
;
2252 __nis_mapping_element_t
*e
= NULL
;
2256 s
= get_next_token(&begin_token
, &end_token
, &t
);
2257 if (s
== NULL
|| t
!= open_paren_token
)
2262 s
= get_next_token(&begin_token
, &end_token
, &t
);
2263 if (s
== NULL
|| t
!= quoted_string_token
)
2266 format_str
= s_strndup(begin_token
, end_token
- begin_token
);
2267 if (format_str
== NULL
)
2269 e
= (__nis_mapping_element_t
*)
2270 s_calloc(1, sizeof (__nis_mapping_element_t
));
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
);
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
2292 * INPUT: the attribute value
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
;
2308 __nis_mapping_element_t
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
))
2324 if (!IS_TERMINAL_CHAR(*s
)) {
2326 s
= skip_get_dn(begin_token
, end_s
);
2328 p_error
= parse_invalid_dn
;
2331 if (triple
!= NULL
) {
2332 search_base
= s_strndup(begin_token
,
2334 if (search_base
== NULL
)
2337 while (s
< end_s
&& is_whitespace(*s
))
2343 if (!IS_TERMINAL_CHAR(*s
)) {
2344 p_error
= parse_bad_ldap_item_format
;
2347 if (*s
!= QUESTION_MARK
)
2351 while (s
< end_s
&& is_whitespace(*s
))
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
)) !=
2362 scope
= LDAP_SCOPE_ONELEVEL
;
2363 } else if ((s1
= skip_string("sub", s
, end_s
- s
)) !=
2365 scope
= LDAP_SCOPE_SUBTREE
;
2366 } else if (s
+ 1 < end_s
&& *s
!= QUESTION_MARK
) {
2367 p_error
= parse_invalid_scope
;
2372 while (s
< end_s
&& is_whitespace(*s
))
2378 if (*s
!= QUESTION_MARK
)
2381 while (s
< end_s
&& is_whitespace(*s
))
2383 if (s
== end_s
|| IS_TERMINAL_CHAR(*s
))
2386 /* LDAP search filter */
2387 if (*s
== OPEN_PAREN_CHAR
) {
2390 s
= get_ldap_filter(&begin_token
, &end_token
);
2394 element
= get_ldap_filter_element(begin_token
, end_token
);
2395 if (element
!= NULL
)
2400 s
= get_ava_list(&begin_token
, &end_token
, TRUE
);
2406 filter
= s_strndup(begin_token
, s
- begin_token
);
2407 if (p_error
== no_parse_error
)
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
;
2420 if (search_base
!= NULL
)
2424 if (element
!= NULL
) {
2425 free_mapping_element(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
2444 const char *fmt_string
,
2445 __nis_mapping_format_t
**fmt
,
2448 bool_t print_mapping
)
2450 const char *f
= fmt_string
;
2452 __nis_mapping_format_t
*b
;
2453 __nis_mapping_format_t
*base
= NULL
;
2459 base
= (__nis_mapping_format_t
*)
2460 s_calloc(1, sizeof (__nis_mapping_format_t
));
2464 base
->type
= mmt_begin
;
2468 b
= (__nis_mapping_format_t
*)s_realloc(
2469 base
, (n
+ 1) * sizeof (__nis_mapping_format_t
));
2474 base
[n
].type
= mmt_end
;
2484 f
= get_next_print_format_item(f
, ef
, &base
[n
]);
2486 f
= get_next_extract_format_item(f
, ef
, &base
[n
]);
2491 if (base
[n
].type
== mmt_item
||
2492 base
[n
].type
== mmt_berstring
)
2497 free_mapping_format(base
);
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
2513 getIndex(const char **s_cur
, const char *s_end
)
2515 const char *s
= *s_cur
+ 1;
2521 bool_t in_quotes
= FALSE
;
2524 while (s
< s_end
&& is_whitespace(*s
))
2526 for (s1
= s
; s1
< s_end
; s1
++) {
2527 if (*s1
== ESCAPE_CHAR
)
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)
2536 } else if (*s1
== OPEN_BRACKET
)
2540 if (n_brackets
== 0) {
2541 index
= s_strndup(s
, s1
- s
);
2542 if (index
!= NULL
) {
2543 s_index_end
= index
+ (s1
- s
);
2545 for (s_index
= index
; s_index
< s_index_end
;
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
)) {
2555 *s_index1
++ = *s_index
;
2557 *s_index1
= *s_index
;
2561 while (s
< s_end
&& is_whitespace(*s
))
2566 p_error
= parse_mismatched_brackets
;
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
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
;
2589 char *fmt_string
= NULL
;
2590 __nis_mapping_format_t
*v
= NULL
;
2591 __nis_mapping_format_t
**value
;
2596 (void) memset(index
, 0, sizeof (*index
));
2600 s
= skip_token(s
, end_s
, comma_token
);
2602 p_error
= parse_bad_index_format
;
2608 s
= get_next_token(&begin_token
, &end_token
, &t
);
2611 if (t
!= string_token
) {
2612 p_error
= parse_bad_index_format
;
2615 s
= skip_token(s
, end_s
, equal_token
);
2617 p_error
= parse_bad_index_format
;
2620 if (index
!= NULL
) {
2621 name_str
= s_strndup_esc(begin_token
,
2622 end_token
- begin_token
);
2623 if (name_str
== NULL
)
2628 s
= get_next_token(&begin_token
, &end_token
, &t
);
2631 if (t
!= string_token
&& t
!= quoted_string_token
) {
2632 p_error
= parse_bad_index_format
;
2635 fmt_string
= s_strndup(begin_token
, end_token
- begin_token
);
2636 if (fmt_string
== NULL
)
2638 if (!get_mapping_format(fmt_string
, &v
, NULL
, NULL
, FALSE
))
2642 if (index
!= NULL
) {
2643 name
= s_realloc(index
->name
,
2644 (n
+ 1) * sizeof (char *));
2647 value
= s_realloc(index
->value
,
2648 (n
+ 1) * sizeof (__nis_mapping_format_t
*));
2655 index
->numIndexes
= ++n
;
2657 index
->value
= value
;
2658 } else if (v
!= NULL
) {
2659 free_mapping_format(v
);
2663 if (p_error
!= no_parse_error
) {
2664 if (name_str
!= NULL
)
2667 free_mapping_format(v
);
2668 if (fmt_string
!= NULL
)
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
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
))
2702 obj_dn
->delDisp
= dd_perDbId
;
2703 while (s_begin
< s_end
&& is_whitespace(*s_begin
))
2705 if (s_begin
== s_end
|| *s_begin
!= EQUAL_CHAR
) {
2706 p_error
= parse_object_dn_syntax_error
;
2709 while (s_begin
< s_end
&& is_whitespace(*s_begin
))
2711 while (s_begin
< s_end
&& is_whitespace(s_end
[-1]))
2713 if (s_begin
== s_end
) {
2714 p_error
= parse_object_dn_syntax_error
;
2717 s_strndup(s_begin
, s_end
- s_begin
);
2721 p_error
= parse_object_dn_syntax_error
;
2723 return (p_error
== no_parse_error
);