Bug Summary

File:src/usr.sbin/ldapctl/../ldapd/schema.c
Warning:line 538, column 3
Potential leak of memory pointed to by 'kw'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name schema.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ldapctl/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ldapctl/../ldapd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldapctl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/ldapctl/../ldapd/schema.c
1/* $OpenBSD: schema.c,v 1.19 2019/10/24 12:39:26 tb Exp $ */
2
3/*
4 * Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22#include <stdlib.h>
23#include <string.h>
24#include <syslog.h>
25
26#include "ldapd.h"
27#include "log.h"
28
29#define ERROR-1 -1
30#define STRING1 1
31
32static int
33attr_oid_cmp(struct attr_type *a, struct attr_type *b)
34{
35 return strcasecmp(a->oid, b->oid);
36}
37
38static int
39obj_oid_cmp(struct object *a, struct object *b)
40{
41 return strcasecmp(a->oid, b->oid);
42}
43
44static int
45oidname_cmp(struct oidname *a, struct oidname *b)
46{
47 return strcasecmp(a->on_name, b->on_name);
48}
49
50static int
51symoid_cmp(struct symoid *a, struct symoid *b)
52{
53 return strcasecmp(a->name, b->name);
54}
55
56RB_GENERATE(attr_type_tree, attr_type, link, attr_oid_cmp)void attr_type_tree_RB_INSERT_COLOR(struct attr_type_tree *head
, struct attr_type *elm) { struct attr_type *parent, *gparent
, *tmp; while ((parent = (elm)->link.rbe_parent) &&
(parent)->link.rbe_color == 1) { gparent = (parent)->link
.rbe_parent; if (parent == (gparent)->link.rbe_left) { tmp
= (gparent)->link.rbe_right; if (tmp && (tmp)->
link.rbe_color == 1) { (tmp)->link.rbe_color = 0; do { (parent
)->link.rbe_color = 0; (gparent)->link.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->link.
rbe_right == elm) { do { (tmp) = (parent)->link.rbe_right;
if (((parent)->link.rbe_right = (tmp)->link.rbe_left))
{ ((tmp)->link.rbe_left)->link.rbe_parent = (parent); }
do {} while (0); if (((tmp)->link.rbe_parent = (parent)->
link.rbe_parent)) { if ((parent) == ((parent)->link.rbe_parent
)->link.rbe_left) ((parent)->link.rbe_parent)->link.
rbe_left = (tmp); else ((parent)->link.rbe_parent)->link
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->link.rbe_left = (parent); (parent)->link.rbe_parent =
(tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do {
} while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->link.rbe_color = 0; (gparent)->link.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->link.rbe_left
; if (((gparent)->link.rbe_left = (tmp)->link.rbe_right
)) { ((tmp)->link.rbe_right)->link.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->link.rbe_parent = (gparent
)->link.rbe_parent)) { if ((gparent) == ((gparent)->link
.rbe_parent)->link.rbe_left) ((gparent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((gparent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (gparent); (gparent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); } else { tmp = (gparent)->link
.rbe_left; if (tmp && (tmp)->link.rbe_color == 1) {
(tmp)->link.rbe_color = 0; do { (parent)->link.rbe_color
= 0; (gparent)->link.rbe_color = 1; } while (0); elm = gparent
; continue; } if ((parent)->link.rbe_left == elm) { do { (
tmp) = (parent)->link.rbe_left; if (((parent)->link.rbe_left
= (tmp)->link.rbe_right)) { ((tmp)->link.rbe_right)->
link.rbe_parent = (parent); } do {} while (0); if (((tmp)->
link.rbe_parent = (parent)->link.rbe_parent)) { if ((parent
) == ((parent)->link.rbe_parent)->link.rbe_left) ((parent
)->link.rbe_parent)->link.rbe_left = (tmp); else ((parent
)->link.rbe_parent)->link.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->link.rbe_right = (parent); (
parent)->link.rbe_parent = (tmp); do {} while (0); if (((tmp
)->link.rbe_parent)) do {} while (0); } while (0); tmp = parent
; parent = elm; elm = tmp; } do { (parent)->link.rbe_color
= 0; (gparent)->link.rbe_color = 1; } while (0); do { (tmp
) = (gparent)->link.rbe_right; if (((gparent)->link.rbe_right
= (tmp)->link.rbe_left)) { ((tmp)->link.rbe_left)->
link.rbe_parent = (gparent); } do {} while (0); if (((tmp)->
link.rbe_parent = (gparent)->link.rbe_parent)) { if ((gparent
) == ((gparent)->link.rbe_parent)->link.rbe_left) ((gparent
)->link.rbe_parent)->link.rbe_left = (tmp); else ((gparent
)->link.rbe_parent)->link.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->link.rbe_left = (gparent); (
gparent)->link.rbe_parent = (tmp); do {} while (0); if (((
tmp)->link.rbe_parent)) do {} while (0); } while (0); } } (
head->rbh_root)->link.rbe_color = 0; } void attr_type_tree_RB_REMOVE_COLOR
(struct attr_type_tree *head, struct attr_type *parent, struct
attr_type *elm) { struct attr_type *tmp; while ((elm == ((void
*)0) || (elm)->link.rbe_color == 0) && elm != (head
)->rbh_root) { if ((parent)->link.rbe_left == elm) { tmp
= (parent)->link.rbe_right; if ((tmp)->link.rbe_color ==
1) { do { (tmp)->link.rbe_color = 0; (parent)->link.rbe_color
= 1; } while (0); do { (tmp) = (parent)->link.rbe_right; if
(((parent)->link.rbe_right = (tmp)->link.rbe_left)) { (
(tmp)->link.rbe_left)->link.rbe_parent = (parent); } do
{} while (0); if (((tmp)->link.rbe_parent = (parent)->
link.rbe_parent)) { if ((parent) == ((parent)->link.rbe_parent
)->link.rbe_left) ((parent)->link.rbe_parent)->link.
rbe_left = (tmp); else ((parent)->link.rbe_parent)->link
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->link.rbe_left = (parent); (parent)->link.rbe_parent =
(tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do {
} while (0); } while (0); tmp = (parent)->link.rbe_right; }
if (((tmp)->link.rbe_left == ((void*)0) || ((tmp)->link
.rbe_left)->link.rbe_color == 0) && ((tmp)->link
.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->link
.rbe_color == 0)) { (tmp)->link.rbe_color = 1; elm = parent
; parent = (elm)->link.rbe_parent; } else { if ((tmp)->
link.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->
link.rbe_color == 0) { struct attr_type *oleft; if ((oleft = (
tmp)->link.rbe_left)) (oleft)->link.rbe_color = 0; (tmp
)->link.rbe_color = 1; do { (oleft) = (tmp)->link.rbe_left
; if (((tmp)->link.rbe_left = (oleft)->link.rbe_right))
{ ((oleft)->link.rbe_right)->link.rbe_parent = (tmp); }
do {} while (0); if (((oleft)->link.rbe_parent = (tmp)->
link.rbe_parent)) { if ((tmp) == ((tmp)->link.rbe_parent)->
link.rbe_left) ((tmp)->link.rbe_parent)->link.rbe_left =
(oleft); else ((tmp)->link.rbe_parent)->link.rbe_right
= (oleft); } else (head)->rbh_root = (oleft); (oleft)->
link.rbe_right = (tmp); (tmp)->link.rbe_parent = (oleft); do
{} while (0); if (((oleft)->link.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->link.rbe_right; } (tmp)
->link.rbe_color = (parent)->link.rbe_color; (parent)->
link.rbe_color = 0; if ((tmp)->link.rbe_right) ((tmp)->
link.rbe_right)->link.rbe_color = 0; do { (tmp) = (parent)
->link.rbe_right; if (((parent)->link.rbe_right = (tmp)
->link.rbe_left)) { ((tmp)->link.rbe_left)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_left = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } else { tmp = (parent)->link.rbe_left; if ((tmp)->link
.rbe_color == 1) { do { (tmp)->link.rbe_color = 0; (parent
)->link.rbe_color = 1; } while (0); do { (tmp) = (parent)->
link.rbe_left; if (((parent)->link.rbe_left = (tmp)->link
.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->link.rbe_left;
} if (((tmp)->link.rbe_left == ((void*)0) || ((tmp)->link
.rbe_left)->link.rbe_color == 0) && ((tmp)->link
.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->link
.rbe_color == 0)) { (tmp)->link.rbe_color = 1; elm = parent
; parent = (elm)->link.rbe_parent; } else { if ((tmp)->
link.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->
link.rbe_color == 0) { struct attr_type *oright; if ((oright =
(tmp)->link.rbe_right)) (oright)->link.rbe_color = 0; (
tmp)->link.rbe_color = 1; do { (oright) = (tmp)->link.rbe_right
; if (((tmp)->link.rbe_right = (oright)->link.rbe_left)
) { ((oright)->link.rbe_left)->link.rbe_parent = (tmp);
} do {} while (0); if (((oright)->link.rbe_parent = (tmp)
->link.rbe_parent)) { if ((tmp) == ((tmp)->link.rbe_parent
)->link.rbe_left) ((tmp)->link.rbe_parent)->link.rbe_left
= (oright); else ((tmp)->link.rbe_parent)->link.rbe_right
= (oright); } else (head)->rbh_root = (oright); (oright)->
link.rbe_left = (tmp); (tmp)->link.rbe_parent = (oright); do
{} while (0); if (((oright)->link.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->link.rbe_left; } (tmp)->
link.rbe_color = (parent)->link.rbe_color; (parent)->link
.rbe_color = 0; if ((tmp)->link.rbe_left) ((tmp)->link.
rbe_left)->link.rbe_color = 0; do { (tmp) = (parent)->link
.rbe_left; if (((parent)->link.rbe_left = (tmp)->link.rbe_right
)) { ((tmp)->link.rbe_right)->link.rbe_parent = (parent
); } do {} while (0); if (((tmp)->link.rbe_parent = (parent
)->link.rbe_parent)) { if ((parent) == ((parent)->link.
rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent)
->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } } if (elm) (elm)->link.rbe_color = 0; } struct attr_type
* attr_type_tree_RB_REMOVE(struct attr_type_tree *head, struct
attr_type *elm) { struct attr_type *child, *parent, *old = elm
; int color; if ((elm)->link.rbe_left == ((void*)0)) child
= (elm)->link.rbe_right; else if ((elm)->link.rbe_right
== ((void*)0)) child = (elm)->link.rbe_left; else { struct
attr_type *left; elm = (elm)->link.rbe_right; while ((left
= (elm)->link.rbe_left)) elm = left; child = (elm)->link
.rbe_right; parent = (elm)->link.rbe_parent; color = (elm)
->link.rbe_color; if (child) (child)->link.rbe_parent =
parent; if (parent) { if ((parent)->link.rbe_left == elm)
(parent)->link.rbe_left = child; else (parent)->link.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; if ((elm)->link.rbe_parent == old) parent = elm; (elm)->
link = (old)->link; if ((old)->link.rbe_parent) { if ((
(old)->link.rbe_parent)->link.rbe_left == old) ((old)->
link.rbe_parent)->link.rbe_left = elm; else ((old)->link
.rbe_parent)->link.rbe_right = elm; do {} while (0); } else
(head)->rbh_root = elm; ((old)->link.rbe_left)->link
.rbe_parent = elm; if ((old)->link.rbe_right) ((old)->link
.rbe_right)->link.rbe_parent = elm; if (parent) { left = parent
; do { do {} while (0); } while ((left = (left)->link.rbe_parent
)); } goto color; } parent = (elm)->link.rbe_parent; color
= (elm)->link.rbe_color; if (child) (child)->link.rbe_parent
= parent; if (parent) { if ((parent)->link.rbe_left == elm
) (parent)->link.rbe_left = child; else (parent)->link.
rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; color: if (color == 0) attr_type_tree_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct attr_type * attr_type_tree_RB_INSERT
(struct attr_type_tree *head, struct attr_type *elm) { struct
attr_type *tmp; struct attr_type *parent = ((void*)0); int comp
= 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp; comp
= (attr_oid_cmp)(elm, parent); if (comp < 0) tmp = (tmp)->
link.rbe_left; else if (comp > 0) tmp = (tmp)->link.rbe_right
; else return (tmp); } do { (elm)->link.rbe_parent = parent
; (elm)->link.rbe_left = (elm)->link.rbe_right = ((void
*)0); (elm)->link.rbe_color = 1; } while (0); if (parent !=
((void*)0)) { if (comp < 0) (parent)->link.rbe_left = elm
; else (parent)->link.rbe_right = elm; do {} while (0); } else
(head)->rbh_root = elm; attr_type_tree_RB_INSERT_COLOR(head
, elm); return (((void*)0)); } struct attr_type * attr_type_tree_RB_FIND
(struct attr_type_tree *head, struct attr_type *elm) { struct
attr_type *tmp = (head)->rbh_root; int comp; while (tmp) {
comp = attr_oid_cmp(elm, tmp); if (comp < 0) tmp = (tmp)->
link.rbe_left; else if (comp > 0) tmp = (tmp)->link.rbe_right
; else return (tmp); } return (((void*)0)); } struct attr_type
* attr_type_tree_RB_NFIND(struct attr_type_tree *head, struct
attr_type *elm) { struct attr_type *tmp = (head)->rbh_root
; struct attr_type *res = ((void*)0); int comp; while (tmp) {
comp = attr_oid_cmp(elm, tmp); if (comp < 0) { res = tmp;
tmp = (tmp)->link.rbe_left; } else if (comp > 0) tmp =
(tmp)->link.rbe_right; else return (tmp); } return (res);
} struct attr_type * attr_type_tree_RB_NEXT(struct attr_type
*elm) { if ((elm)->link.rbe_right) { elm = (elm)->link
.rbe_right; while ((elm)->link.rbe_left) elm = (elm)->link
.rbe_left; } else { if ((elm)->link.rbe_parent && (
elm == ((elm)->link.rbe_parent)->link.rbe_left)) elm = (
elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_right
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct attr_type * attr_type_tree_RB_PREV
(struct attr_type *elm) { if ((elm)->link.rbe_left) { elm =
(elm)->link.rbe_left; while ((elm)->link.rbe_right) elm
= (elm)->link.rbe_right; } else { if ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_right
)) elm = (elm)->link.rbe_parent; else { while ((elm)->link
.rbe_parent && (elm == ((elm)->link.rbe_parent)->
link.rbe_left)) elm = (elm)->link.rbe_parent; elm = (elm)->
link.rbe_parent; } } return (elm); } struct attr_type * attr_type_tree_RB_MINMAX
(struct attr_type_tree *head, int val) { struct attr_type *tmp
= (head)->rbh_root; struct attr_type *parent = ((void*)0)
; while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->
link.rbe_left; else tmp = (tmp)->link.rbe_right; } return (
parent); }
;
57RB_GENERATE(object_tree, object, link, obj_oid_cmp)void object_tree_RB_INSERT_COLOR(struct object_tree *head, struct
object *elm) { struct object *parent, *gparent, *tmp; while (
(parent = (elm)->link.rbe_parent) && (parent)->
link.rbe_color == 1) { gparent = (parent)->link.rbe_parent
; if (parent == (gparent)->link.rbe_left) { tmp = (gparent
)->link.rbe_right; if (tmp && (tmp)->link.rbe_color
== 1) { (tmp)->link.rbe_color = 0; do { (parent)->link
.rbe_color = 0; (gparent)->link.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->link.rbe_right ==
elm) { do { (tmp) = (parent)->link.rbe_right; if (((parent
)->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
link.rbe_color = 0; (gparent)->link.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->link.rbe_left; if (((gparent
)->link.rbe_left = (tmp)->link.rbe_right)) { ((tmp)->
link.rbe_right)->link.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->link.rbe_parent = (gparent)->link.rbe_parent
)) { if ((gparent) == ((gparent)->link.rbe_parent)->link
.rbe_left) ((gparent)->link.rbe_parent)->link.rbe_left =
(tmp); else ((gparent)->link.rbe_parent)->link.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->link.
rbe_right = (gparent); (gparent)->link.rbe_parent = (tmp);
do {} while (0); if (((tmp)->link.rbe_parent)) do {} while
(0); } while (0); } else { tmp = (gparent)->link.rbe_left
; if (tmp && (tmp)->link.rbe_color == 1) { (tmp)->
link.rbe_color = 0; do { (parent)->link.rbe_color = 0; (gparent
)->link.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->link.rbe_left == elm) { do { (tmp) = (parent
)->link.rbe_left; if (((parent)->link.rbe_left = (tmp)->
link.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = parent; parent = elm; elm =
tmp; } do { (parent)->link.rbe_color = 0; (gparent)->link
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->link.
rbe_right; if (((gparent)->link.rbe_right = (tmp)->link
.rbe_left)) { ((tmp)->link.rbe_left)->link.rbe_parent =
(gparent); } do {} while (0); if (((tmp)->link.rbe_parent
= (gparent)->link.rbe_parent)) { if ((gparent) == ((gparent
)->link.rbe_parent)->link.rbe_left) ((gparent)->link
.rbe_parent)->link.rbe_left = (tmp); else ((gparent)->link
.rbe_parent)->link.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->link.rbe_left = (gparent); (gparent)->
link.rbe_parent = (tmp); do {} while (0); if (((tmp)->link
.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root
)->link.rbe_color = 0; } void object_tree_RB_REMOVE_COLOR(
struct object_tree *head, struct object *parent, struct object
*elm) { struct object *tmp; while ((elm == ((void*)0) || (elm
)->link.rbe_color == 0) && elm != (head)->rbh_root
) { if ((parent)->link.rbe_left == elm) { tmp = (parent)->
link.rbe_right; if ((tmp)->link.rbe_color == 1) { do { (tmp
)->link.rbe_color = 0; (parent)->link.rbe_color = 1; } while
(0); do { (tmp) = (parent)->link.rbe_right; if (((parent)
->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->link.rbe_right; } if (((tmp)->link
.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->link
.rbe_color == 0) && ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0)) {
(tmp)->link.rbe_color = 1; elm = parent; parent = (elm)->
link.rbe_parent; } else { if ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0) {
struct object *oleft; if ((oleft = (tmp)->link.rbe_left))
(oleft)->link.rbe_color = 0; (tmp)->link.rbe_color = 1
; do { (oleft) = (tmp)->link.rbe_left; if (((tmp)->link
.rbe_left = (oleft)->link.rbe_right)) { ((oleft)->link.
rbe_right)->link.rbe_parent = (tmp); } do {} while (0); if
(((oleft)->link.rbe_parent = (tmp)->link.rbe_parent)) {
if ((tmp) == ((tmp)->link.rbe_parent)->link.rbe_left) (
(tmp)->link.rbe_parent)->link.rbe_left = (oleft); else (
(tmp)->link.rbe_parent)->link.rbe_right = (oleft); } else
(head)->rbh_root = (oleft); (oleft)->link.rbe_right = (
tmp); (tmp)->link.rbe_parent = (oleft); do {} while (0); if
(((oleft)->link.rbe_parent)) do {} while (0); } while (0)
; tmp = (parent)->link.rbe_right; } (tmp)->link.rbe_color
= (parent)->link.rbe_color; (parent)->link.rbe_color =
0; if ((tmp)->link.rbe_right) ((tmp)->link.rbe_right)->
link.rbe_color = 0; do { (tmp) = (parent)->link.rbe_right;
if (((parent)->link.rbe_right = (tmp)->link.rbe_left))
{ ((tmp)->link.rbe_left)->link.rbe_parent = (parent); }
do {} while (0); if (((tmp)->link.rbe_parent = (parent)->
link.rbe_parent)) { if ((parent) == ((parent)->link.rbe_parent
)->link.rbe_left) ((parent)->link.rbe_parent)->link.
rbe_left = (tmp); else ((parent)->link.rbe_parent)->link
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->link.rbe_left = (parent); (parent)->link.rbe_parent =
(tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->link.rbe_left; if ((tmp)->link
.rbe_color == 1) { do { (tmp)->link.rbe_color = 0; (parent
)->link.rbe_color = 1; } while (0); do { (tmp) = (parent)->
link.rbe_left; if (((parent)->link.rbe_left = (tmp)->link
.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->link.rbe_left;
} if (((tmp)->link.rbe_left == ((void*)0) || ((tmp)->link
.rbe_left)->link.rbe_color == 0) && ((tmp)->link
.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->link
.rbe_color == 0)) { (tmp)->link.rbe_color = 1; elm = parent
; parent = (elm)->link.rbe_parent; } else { if ((tmp)->
link.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->
link.rbe_color == 0) { struct object *oright; if ((oright = (
tmp)->link.rbe_right)) (oright)->link.rbe_color = 0; (tmp
)->link.rbe_color = 1; do { (oright) = (tmp)->link.rbe_right
; if (((tmp)->link.rbe_right = (oright)->link.rbe_left)
) { ((oright)->link.rbe_left)->link.rbe_parent = (tmp);
} do {} while (0); if (((oright)->link.rbe_parent = (tmp)
->link.rbe_parent)) { if ((tmp) == ((tmp)->link.rbe_parent
)->link.rbe_left) ((tmp)->link.rbe_parent)->link.rbe_left
= (oright); else ((tmp)->link.rbe_parent)->link.rbe_right
= (oright); } else (head)->rbh_root = (oright); (oright)->
link.rbe_left = (tmp); (tmp)->link.rbe_parent = (oright); do
{} while (0); if (((oright)->link.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->link.rbe_left; } (tmp)->
link.rbe_color = (parent)->link.rbe_color; (parent)->link
.rbe_color = 0; if ((tmp)->link.rbe_left) ((tmp)->link.
rbe_left)->link.rbe_color = 0; do { (tmp) = (parent)->link
.rbe_left; if (((parent)->link.rbe_left = (tmp)->link.rbe_right
)) { ((tmp)->link.rbe_right)->link.rbe_parent = (parent
); } do {} while (0); if (((tmp)->link.rbe_parent = (parent
)->link.rbe_parent)) { if ((parent) == ((parent)->link.
rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent)
->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } } if (elm) (elm)->link.rbe_color = 0; } struct object
* object_tree_RB_REMOVE(struct object_tree *head, struct object
*elm) { struct object *child, *parent, *old = elm; int color
; if ((elm)->link.rbe_left == ((void*)0)) child = (elm)->
link.rbe_right; else if ((elm)->link.rbe_right == ((void*)
0)) child = (elm)->link.rbe_left; else { struct object *left
; elm = (elm)->link.rbe_right; while ((left = (elm)->link
.rbe_left)) elm = left; child = (elm)->link.rbe_right; parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; if ((elm)->
link.rbe_parent == old) parent = elm; (elm)->link = (old)->
link; if ((old)->link.rbe_parent) { if (((old)->link.rbe_parent
)->link.rbe_left == old) ((old)->link.rbe_parent)->link
.rbe_left = elm; else ((old)->link.rbe_parent)->link.rbe_right
= elm; do {} while (0); } else (head)->rbh_root = elm; ((
old)->link.rbe_left)->link.rbe_parent = elm; if ((old)->
link.rbe_right) ((old)->link.rbe_right)->link.rbe_parent
= elm; if (parent) { left = parent; do { do {} while (0); } while
((left = (left)->link.rbe_parent)); } goto color; } parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; color: if (
color == 0) object_tree_RB_REMOVE_COLOR(head, parent, child);
return (old); } struct object * object_tree_RB_INSERT(struct
object_tree *head, struct object *elm) { struct object *tmp;
struct object *parent = ((void*)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (obj_oid_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->link.rbe_left
; else if (comp > 0) tmp = (tmp)->link.rbe_right; else return
(tmp); } do { (elm)->link.rbe_parent = parent; (elm)->
link.rbe_left = (elm)->link.rbe_right = ((void*)0); (elm)->
link.rbe_color = 1; } while (0); if (parent != ((void*)0)) { if
(comp < 0) (parent)->link.rbe_left = elm; else (parent
)->link.rbe_right = elm; do {} while (0); } else (head)->
rbh_root = elm; object_tree_RB_INSERT_COLOR(head, elm); return
(((void*)0)); } struct object * object_tree_RB_FIND(struct object_tree
*head, struct object *elm) { struct object *tmp = (head)->
rbh_root; int comp; while (tmp) { comp = obj_oid_cmp(elm, tmp
); if (comp < 0) tmp = (tmp)->link.rbe_left; else if (comp
> 0) tmp = (tmp)->link.rbe_right; else return (tmp); }
return (((void*)0)); } struct object * object_tree_RB_NFIND(
struct object_tree *head, struct object *elm) { struct object
*tmp = (head)->rbh_root; struct object *res = ((void*)0);
int comp; while (tmp) { comp = obj_oid_cmp(elm, tmp); if (comp
< 0) { res = tmp; tmp = (tmp)->link.rbe_left; } else if
(comp > 0) tmp = (tmp)->link.rbe_right; else return (tmp
); } return (res); } struct object * object_tree_RB_NEXT(struct
object *elm) { if ((elm)->link.rbe_right) { elm = (elm)->
link.rbe_right; while ((elm)->link.rbe_left) elm = (elm)->
link.rbe_left; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_left)) elm =
(elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_right
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct object * object_tree_RB_PREV(struct
object *elm) { if ((elm)->link.rbe_left) { elm = (elm)->
link.rbe_left; while ((elm)->link.rbe_right) elm = (elm)->
link.rbe_right; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_right)) elm
= (elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_left
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct object * object_tree_RB_MINMAX(struct
object_tree *head, int val) { struct object *tmp = (head)->
rbh_root; struct object *parent = ((void*)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->link.rbe_left; else tmp
= (tmp)->link.rbe_right; } return (parent); }
;
58RB_GENERATE(oidname_tree, oidname, link, oidname_cmp)void oidname_tree_RB_INSERT_COLOR(struct oidname_tree *head, struct
oidname *elm) { struct oidname *parent, *gparent, *tmp; while
((parent = (elm)->link.rbe_parent) && (parent)->
link.rbe_color == 1) { gparent = (parent)->link.rbe_parent
; if (parent == (gparent)->link.rbe_left) { tmp = (gparent
)->link.rbe_right; if (tmp && (tmp)->link.rbe_color
== 1) { (tmp)->link.rbe_color = 0; do { (parent)->link
.rbe_color = 0; (gparent)->link.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->link.rbe_right ==
elm) { do { (tmp) = (parent)->link.rbe_right; if (((parent
)->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
link.rbe_color = 0; (gparent)->link.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->link.rbe_left; if (((gparent
)->link.rbe_left = (tmp)->link.rbe_right)) { ((tmp)->
link.rbe_right)->link.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->link.rbe_parent = (gparent)->link.rbe_parent
)) { if ((gparent) == ((gparent)->link.rbe_parent)->link
.rbe_left) ((gparent)->link.rbe_parent)->link.rbe_left =
(tmp); else ((gparent)->link.rbe_parent)->link.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->link.
rbe_right = (gparent); (gparent)->link.rbe_parent = (tmp);
do {} while (0); if (((tmp)->link.rbe_parent)) do {} while
(0); } while (0); } else { tmp = (gparent)->link.rbe_left
; if (tmp && (tmp)->link.rbe_color == 1) { (tmp)->
link.rbe_color = 0; do { (parent)->link.rbe_color = 0; (gparent
)->link.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->link.rbe_left == elm) { do { (tmp) = (parent
)->link.rbe_left; if (((parent)->link.rbe_left = (tmp)->
link.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = parent; parent = elm; elm =
tmp; } do { (parent)->link.rbe_color = 0; (gparent)->link
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->link.
rbe_right; if (((gparent)->link.rbe_right = (tmp)->link
.rbe_left)) { ((tmp)->link.rbe_left)->link.rbe_parent =
(gparent); } do {} while (0); if (((tmp)->link.rbe_parent
= (gparent)->link.rbe_parent)) { if ((gparent) == ((gparent
)->link.rbe_parent)->link.rbe_left) ((gparent)->link
.rbe_parent)->link.rbe_left = (tmp); else ((gparent)->link
.rbe_parent)->link.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->link.rbe_left = (gparent); (gparent)->
link.rbe_parent = (tmp); do {} while (0); if (((tmp)->link
.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root
)->link.rbe_color = 0; } void oidname_tree_RB_REMOVE_COLOR
(struct oidname_tree *head, struct oidname *parent, struct oidname
*elm) { struct oidname *tmp; while ((elm == ((void*)0) || (elm
)->link.rbe_color == 0) && elm != (head)->rbh_root
) { if ((parent)->link.rbe_left == elm) { tmp = (parent)->
link.rbe_right; if ((tmp)->link.rbe_color == 1) { do { (tmp
)->link.rbe_color = 0; (parent)->link.rbe_color = 1; } while
(0); do { (tmp) = (parent)->link.rbe_right; if (((parent)
->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->link.rbe_right; } if (((tmp)->link
.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->link
.rbe_color == 0) && ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0)) {
(tmp)->link.rbe_color = 1; elm = parent; parent = (elm)->
link.rbe_parent; } else { if ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0) {
struct oidname *oleft; if ((oleft = (tmp)->link.rbe_left)
) (oleft)->link.rbe_color = 0; (tmp)->link.rbe_color = 1
; do { (oleft) = (tmp)->link.rbe_left; if (((tmp)->link
.rbe_left = (oleft)->link.rbe_right)) { ((oleft)->link.
rbe_right)->link.rbe_parent = (tmp); } do {} while (0); if
(((oleft)->link.rbe_parent = (tmp)->link.rbe_parent)) {
if ((tmp) == ((tmp)->link.rbe_parent)->link.rbe_left) (
(tmp)->link.rbe_parent)->link.rbe_left = (oleft); else (
(tmp)->link.rbe_parent)->link.rbe_right = (oleft); } else
(head)->rbh_root = (oleft); (oleft)->link.rbe_right = (
tmp); (tmp)->link.rbe_parent = (oleft); do {} while (0); if
(((oleft)->link.rbe_parent)) do {} while (0); } while (0)
; tmp = (parent)->link.rbe_right; } (tmp)->link.rbe_color
= (parent)->link.rbe_color; (parent)->link.rbe_color =
0; if ((tmp)->link.rbe_right) ((tmp)->link.rbe_right)->
link.rbe_color = 0; do { (tmp) = (parent)->link.rbe_right;
if (((parent)->link.rbe_right = (tmp)->link.rbe_left))
{ ((tmp)->link.rbe_left)->link.rbe_parent = (parent); }
do {} while (0); if (((tmp)->link.rbe_parent = (parent)->
link.rbe_parent)) { if ((parent) == ((parent)->link.rbe_parent
)->link.rbe_left) ((parent)->link.rbe_parent)->link.
rbe_left = (tmp); else ((parent)->link.rbe_parent)->link
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->link.rbe_left = (parent); (parent)->link.rbe_parent =
(tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->link.rbe_left; if ((tmp)->link
.rbe_color == 1) { do { (tmp)->link.rbe_color = 0; (parent
)->link.rbe_color = 1; } while (0); do { (tmp) = (parent)->
link.rbe_left; if (((parent)->link.rbe_left = (tmp)->link
.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->link.rbe_left;
} if (((tmp)->link.rbe_left == ((void*)0) || ((tmp)->link
.rbe_left)->link.rbe_color == 0) && ((tmp)->link
.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->link
.rbe_color == 0)) { (tmp)->link.rbe_color = 1; elm = parent
; parent = (elm)->link.rbe_parent; } else { if ((tmp)->
link.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->
link.rbe_color == 0) { struct oidname *oright; if ((oright = (
tmp)->link.rbe_right)) (oright)->link.rbe_color = 0; (tmp
)->link.rbe_color = 1; do { (oright) = (tmp)->link.rbe_right
; if (((tmp)->link.rbe_right = (oright)->link.rbe_left)
) { ((oright)->link.rbe_left)->link.rbe_parent = (tmp);
} do {} while (0); if (((oright)->link.rbe_parent = (tmp)
->link.rbe_parent)) { if ((tmp) == ((tmp)->link.rbe_parent
)->link.rbe_left) ((tmp)->link.rbe_parent)->link.rbe_left
= (oright); else ((tmp)->link.rbe_parent)->link.rbe_right
= (oright); } else (head)->rbh_root = (oright); (oright)->
link.rbe_left = (tmp); (tmp)->link.rbe_parent = (oright); do
{} while (0); if (((oright)->link.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->link.rbe_left; } (tmp)->
link.rbe_color = (parent)->link.rbe_color; (parent)->link
.rbe_color = 0; if ((tmp)->link.rbe_left) ((tmp)->link.
rbe_left)->link.rbe_color = 0; do { (tmp) = (parent)->link
.rbe_left; if (((parent)->link.rbe_left = (tmp)->link.rbe_right
)) { ((tmp)->link.rbe_right)->link.rbe_parent = (parent
); } do {} while (0); if (((tmp)->link.rbe_parent = (parent
)->link.rbe_parent)) { if ((parent) == ((parent)->link.
rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent)
->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } } if (elm) (elm)->link.rbe_color = 0; } struct oidname
* oidname_tree_RB_REMOVE(struct oidname_tree *head, struct oidname
*elm) { struct oidname *child, *parent, *old = elm; int color
; if ((elm)->link.rbe_left == ((void*)0)) child = (elm)->
link.rbe_right; else if ((elm)->link.rbe_right == ((void*)
0)) child = (elm)->link.rbe_left; else { struct oidname *left
; elm = (elm)->link.rbe_right; while ((left = (elm)->link
.rbe_left)) elm = left; child = (elm)->link.rbe_right; parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; if ((elm)->
link.rbe_parent == old) parent = elm; (elm)->link = (old)->
link; if ((old)->link.rbe_parent) { if (((old)->link.rbe_parent
)->link.rbe_left == old) ((old)->link.rbe_parent)->link
.rbe_left = elm; else ((old)->link.rbe_parent)->link.rbe_right
= elm; do {} while (0); } else (head)->rbh_root = elm; ((
old)->link.rbe_left)->link.rbe_parent = elm; if ((old)->
link.rbe_right) ((old)->link.rbe_right)->link.rbe_parent
= elm; if (parent) { left = parent; do { do {} while (0); } while
((left = (left)->link.rbe_parent)); } goto color; } parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; color: if (
color == 0) oidname_tree_RB_REMOVE_COLOR(head, parent, child)
; return (old); } struct oidname * oidname_tree_RB_INSERT(struct
oidname_tree *head, struct oidname *elm) { struct oidname *tmp
; struct oidname *parent = ((void*)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (oidname_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->link.rbe_left
; else if (comp > 0) tmp = (tmp)->link.rbe_right; else return
(tmp); } do { (elm)->link.rbe_parent = parent; (elm)->
link.rbe_left = (elm)->link.rbe_right = ((void*)0); (elm)->
link.rbe_color = 1; } while (0); if (parent != ((void*)0)) { if
(comp < 0) (parent)->link.rbe_left = elm; else (parent
)->link.rbe_right = elm; do {} while (0); } else (head)->
rbh_root = elm; oidname_tree_RB_INSERT_COLOR(head, elm); return
(((void*)0)); } struct oidname * oidname_tree_RB_FIND(struct
oidname_tree *head, struct oidname *elm) { struct oidname *tmp
= (head)->rbh_root; int comp; while (tmp) { comp = oidname_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->link.rbe_left; else
if (comp > 0) tmp = (tmp)->link.rbe_right; else return
(tmp); } return (((void*)0)); } struct oidname * oidname_tree_RB_NFIND
(struct oidname_tree *head, struct oidname *elm) { struct oidname
*tmp = (head)->rbh_root; struct oidname *res = ((void*)0)
; int comp; while (tmp) { comp = oidname_cmp(elm, tmp); if (comp
< 0) { res = tmp; tmp = (tmp)->link.rbe_left; } else if
(comp > 0) tmp = (tmp)->link.rbe_right; else return (tmp
); } return (res); } struct oidname * oidname_tree_RB_NEXT(struct
oidname *elm) { if ((elm)->link.rbe_right) { elm = (elm)->
link.rbe_right; while ((elm)->link.rbe_left) elm = (elm)->
link.rbe_left; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_left)) elm =
(elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_right
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct oidname * oidname_tree_RB_PREV(struct
oidname *elm) { if ((elm)->link.rbe_left) { elm = (elm)->
link.rbe_left; while ((elm)->link.rbe_right) elm = (elm)->
link.rbe_right; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_right)) elm
= (elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_left
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct oidname * oidname_tree_RB_MINMAX
(struct oidname_tree *head, int val) { struct oidname *tmp = (
head)->rbh_root; struct oidname *parent = ((void*)0); while
(tmp) { parent = tmp; if (val < 0) tmp = (tmp)->link.rbe_left
; else tmp = (tmp)->link.rbe_right; } return (parent); }
;
59RB_GENERATE(symoid_tree, symoid, link, symoid_cmp)void symoid_tree_RB_INSERT_COLOR(struct symoid_tree *head, struct
symoid *elm) { struct symoid *parent, *gparent, *tmp; while (
(parent = (elm)->link.rbe_parent) && (parent)->
link.rbe_color == 1) { gparent = (parent)->link.rbe_parent
; if (parent == (gparent)->link.rbe_left) { tmp = (gparent
)->link.rbe_right; if (tmp && (tmp)->link.rbe_color
== 1) { (tmp)->link.rbe_color = 0; do { (parent)->link
.rbe_color = 0; (gparent)->link.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->link.rbe_right ==
elm) { do { (tmp) = (parent)->link.rbe_right; if (((parent
)->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
link.rbe_color = 0; (gparent)->link.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->link.rbe_left; if (((gparent
)->link.rbe_left = (tmp)->link.rbe_right)) { ((tmp)->
link.rbe_right)->link.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->link.rbe_parent = (gparent)->link.rbe_parent
)) { if ((gparent) == ((gparent)->link.rbe_parent)->link
.rbe_left) ((gparent)->link.rbe_parent)->link.rbe_left =
(tmp); else ((gparent)->link.rbe_parent)->link.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->link.
rbe_right = (gparent); (gparent)->link.rbe_parent = (tmp);
do {} while (0); if (((tmp)->link.rbe_parent)) do {} while
(0); } while (0); } else { tmp = (gparent)->link.rbe_left
; if (tmp && (tmp)->link.rbe_color == 1) { (tmp)->
link.rbe_color = 0; do { (parent)->link.rbe_color = 0; (gparent
)->link.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->link.rbe_left == elm) { do { (tmp) = (parent
)->link.rbe_left; if (((parent)->link.rbe_left = (tmp)->
link.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = parent; parent = elm; elm =
tmp; } do { (parent)->link.rbe_color = 0; (gparent)->link
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->link.
rbe_right; if (((gparent)->link.rbe_right = (tmp)->link
.rbe_left)) { ((tmp)->link.rbe_left)->link.rbe_parent =
(gparent); } do {} while (0); if (((tmp)->link.rbe_parent
= (gparent)->link.rbe_parent)) { if ((gparent) == ((gparent
)->link.rbe_parent)->link.rbe_left) ((gparent)->link
.rbe_parent)->link.rbe_left = (tmp); else ((gparent)->link
.rbe_parent)->link.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->link.rbe_left = (gparent); (gparent)->
link.rbe_parent = (tmp); do {} while (0); if (((tmp)->link
.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root
)->link.rbe_color = 0; } void symoid_tree_RB_REMOVE_COLOR(
struct symoid_tree *head, struct symoid *parent, struct symoid
*elm) { struct symoid *tmp; while ((elm == ((void*)0) || (elm
)->link.rbe_color == 0) && elm != (head)->rbh_root
) { if ((parent)->link.rbe_left == elm) { tmp = (parent)->
link.rbe_right; if ((tmp)->link.rbe_color == 1) { do { (tmp
)->link.rbe_color = 0; (parent)->link.rbe_color = 1; } while
(0); do { (tmp) = (parent)->link.rbe_right; if (((parent)
->link.rbe_right = (tmp)->link.rbe_left)) { ((tmp)->
link.rbe_left)->link.rbe_parent = (parent); } do {} while (
0); if (((tmp)->link.rbe_parent = (parent)->link.rbe_parent
)) { if ((parent) == ((parent)->link.rbe_parent)->link.
rbe_left) ((parent)->link.rbe_parent)->link.rbe_left = (
tmp); else ((parent)->link.rbe_parent)->link.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->link.rbe_left
= (parent); (parent)->link.rbe_parent = (tmp); do {} while
(0); if (((tmp)->link.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->link.rbe_right; } if (((tmp)->link
.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->link
.rbe_color == 0) && ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0)) {
(tmp)->link.rbe_color = 1; elm = parent; parent = (elm)->
link.rbe_parent; } else { if ((tmp)->link.rbe_right == ((void
*)0) || ((tmp)->link.rbe_right)->link.rbe_color == 0) {
struct symoid *oleft; if ((oleft = (tmp)->link.rbe_left))
(oleft)->link.rbe_color = 0; (tmp)->link.rbe_color = 1
; do { (oleft) = (tmp)->link.rbe_left; if (((tmp)->link
.rbe_left = (oleft)->link.rbe_right)) { ((oleft)->link.
rbe_right)->link.rbe_parent = (tmp); } do {} while (0); if
(((oleft)->link.rbe_parent = (tmp)->link.rbe_parent)) {
if ((tmp) == ((tmp)->link.rbe_parent)->link.rbe_left) (
(tmp)->link.rbe_parent)->link.rbe_left = (oleft); else (
(tmp)->link.rbe_parent)->link.rbe_right = (oleft); } else
(head)->rbh_root = (oleft); (oleft)->link.rbe_right = (
tmp); (tmp)->link.rbe_parent = (oleft); do {} while (0); if
(((oleft)->link.rbe_parent)) do {} while (0); } while (0)
; tmp = (parent)->link.rbe_right; } (tmp)->link.rbe_color
= (parent)->link.rbe_color; (parent)->link.rbe_color =
0; if ((tmp)->link.rbe_right) ((tmp)->link.rbe_right)->
link.rbe_color = 0; do { (tmp) = (parent)->link.rbe_right;
if (((parent)->link.rbe_right = (tmp)->link.rbe_left))
{ ((tmp)->link.rbe_left)->link.rbe_parent = (parent); }
do {} while (0); if (((tmp)->link.rbe_parent = (parent)->
link.rbe_parent)) { if ((parent) == ((parent)->link.rbe_parent
)->link.rbe_left) ((parent)->link.rbe_parent)->link.
rbe_left = (tmp); else ((parent)->link.rbe_parent)->link
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->link.rbe_left = (parent); (parent)->link.rbe_parent =
(tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->link.rbe_left; if ((tmp)->link
.rbe_color == 1) { do { (tmp)->link.rbe_color = 0; (parent
)->link.rbe_color = 1; } while (0); do { (tmp) = (parent)->
link.rbe_left; if (((parent)->link.rbe_left = (tmp)->link
.rbe_right)) { ((tmp)->link.rbe_right)->link.rbe_parent
= (parent); } do {} while (0); if (((tmp)->link.rbe_parent
= (parent)->link.rbe_parent)) { if ((parent) == ((parent)
->link.rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent
)->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->link.rbe_left;
} if (((tmp)->link.rbe_left == ((void*)0) || ((tmp)->link
.rbe_left)->link.rbe_color == 0) && ((tmp)->link
.rbe_right == ((void*)0) || ((tmp)->link.rbe_right)->link
.rbe_color == 0)) { (tmp)->link.rbe_color = 1; elm = parent
; parent = (elm)->link.rbe_parent; } else { if ((tmp)->
link.rbe_left == ((void*)0) || ((tmp)->link.rbe_left)->
link.rbe_color == 0) { struct symoid *oright; if ((oright = (
tmp)->link.rbe_right)) (oright)->link.rbe_color = 0; (tmp
)->link.rbe_color = 1; do { (oright) = (tmp)->link.rbe_right
; if (((tmp)->link.rbe_right = (oright)->link.rbe_left)
) { ((oright)->link.rbe_left)->link.rbe_parent = (tmp);
} do {} while (0); if (((oright)->link.rbe_parent = (tmp)
->link.rbe_parent)) { if ((tmp) == ((tmp)->link.rbe_parent
)->link.rbe_left) ((tmp)->link.rbe_parent)->link.rbe_left
= (oright); else ((tmp)->link.rbe_parent)->link.rbe_right
= (oright); } else (head)->rbh_root = (oright); (oright)->
link.rbe_left = (tmp); (tmp)->link.rbe_parent = (oright); do
{} while (0); if (((oright)->link.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->link.rbe_left; } (tmp)->
link.rbe_color = (parent)->link.rbe_color; (parent)->link
.rbe_color = 0; if ((tmp)->link.rbe_left) ((tmp)->link.
rbe_left)->link.rbe_color = 0; do { (tmp) = (parent)->link
.rbe_left; if (((parent)->link.rbe_left = (tmp)->link.rbe_right
)) { ((tmp)->link.rbe_right)->link.rbe_parent = (parent
); } do {} while (0); if (((tmp)->link.rbe_parent = (parent
)->link.rbe_parent)) { if ((parent) == ((parent)->link.
rbe_parent)->link.rbe_left) ((parent)->link.rbe_parent)
->link.rbe_left = (tmp); else ((parent)->link.rbe_parent
)->link.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->link.rbe_right = (parent); (parent)->link.rbe_parent
= (tmp); do {} while (0); if (((tmp)->link.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } } if (elm) (elm)->link.rbe_color = 0; } struct symoid
* symoid_tree_RB_REMOVE(struct symoid_tree *head, struct symoid
*elm) { struct symoid *child, *parent, *old = elm; int color
; if ((elm)->link.rbe_left == ((void*)0)) child = (elm)->
link.rbe_right; else if ((elm)->link.rbe_right == ((void*)
0)) child = (elm)->link.rbe_left; else { struct symoid *left
; elm = (elm)->link.rbe_right; while ((left = (elm)->link
.rbe_left)) elm = left; child = (elm)->link.rbe_right; parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; if ((elm)->
link.rbe_parent == old) parent = elm; (elm)->link = (old)->
link; if ((old)->link.rbe_parent) { if (((old)->link.rbe_parent
)->link.rbe_left == old) ((old)->link.rbe_parent)->link
.rbe_left = elm; else ((old)->link.rbe_parent)->link.rbe_right
= elm; do {} while (0); } else (head)->rbh_root = elm; ((
old)->link.rbe_left)->link.rbe_parent = elm; if ((old)->
link.rbe_right) ((old)->link.rbe_right)->link.rbe_parent
= elm; if (parent) { left = parent; do { do {} while (0); } while
((left = (left)->link.rbe_parent)); } goto color; } parent
= (elm)->link.rbe_parent; color = (elm)->link.rbe_color
; if (child) (child)->link.rbe_parent = parent; if (parent
) { if ((parent)->link.rbe_left == elm) (parent)->link.
rbe_left = child; else (parent)->link.rbe_right = child; do
{} while (0); } else (head)->rbh_root = child; color: if (
color == 0) symoid_tree_RB_REMOVE_COLOR(head, parent, child);
return (old); } struct symoid * symoid_tree_RB_INSERT(struct
symoid_tree *head, struct symoid *elm) { struct symoid *tmp;
struct symoid *parent = ((void*)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (symoid_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->link.rbe_left
; else if (comp > 0) tmp = (tmp)->link.rbe_right; else return
(tmp); } do { (elm)->link.rbe_parent = parent; (elm)->
link.rbe_left = (elm)->link.rbe_right = ((void*)0); (elm)->
link.rbe_color = 1; } while (0); if (parent != ((void*)0)) { if
(comp < 0) (parent)->link.rbe_left = elm; else (parent
)->link.rbe_right = elm; do {} while (0); } else (head)->
rbh_root = elm; symoid_tree_RB_INSERT_COLOR(head, elm); return
(((void*)0)); } struct symoid * symoid_tree_RB_FIND(struct symoid_tree
*head, struct symoid *elm) { struct symoid *tmp = (head)->
rbh_root; int comp; while (tmp) { comp = symoid_cmp(elm, tmp)
; if (comp < 0) tmp = (tmp)->link.rbe_left; else if (comp
> 0) tmp = (tmp)->link.rbe_right; else return (tmp); }
return (((void*)0)); } struct symoid * symoid_tree_RB_NFIND(
struct symoid_tree *head, struct symoid *elm) { struct symoid
*tmp = (head)->rbh_root; struct symoid *res = ((void*)0);
int comp; while (tmp) { comp = symoid_cmp(elm, tmp); if (comp
< 0) { res = tmp; tmp = (tmp)->link.rbe_left; } else if
(comp > 0) tmp = (tmp)->link.rbe_right; else return (tmp
); } return (res); } struct symoid * symoid_tree_RB_NEXT(struct
symoid *elm) { if ((elm)->link.rbe_right) { elm = (elm)->
link.rbe_right; while ((elm)->link.rbe_left) elm = (elm)->
link.rbe_left; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_left)) elm =
(elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_right
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct symoid * symoid_tree_RB_PREV(struct
symoid *elm) { if ((elm)->link.rbe_left) { elm = (elm)->
link.rbe_left; while ((elm)->link.rbe_right) elm = (elm)->
link.rbe_right; } else { if ((elm)->link.rbe_parent &&
(elm == ((elm)->link.rbe_parent)->link.rbe_right)) elm
= (elm)->link.rbe_parent; else { while ((elm)->link.rbe_parent
&& (elm == ((elm)->link.rbe_parent)->link.rbe_left
)) elm = (elm)->link.rbe_parent; elm = (elm)->link.rbe_parent
; } } return (elm); } struct symoid * symoid_tree_RB_MINMAX(struct
symoid_tree *head, int val) { struct symoid *tmp = (head)->
rbh_root; struct symoid *parent = ((void*)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->link.rbe_left; else tmp
= (tmp)->link.rbe_right; } return (parent); }
;
60
61static struct attr_list *push_attr(struct attr_list *alist, struct attr_type *a);
62static struct obj_list *push_obj(struct obj_list *olist, struct object *obj);
63static struct name_list *push_name(struct name_list *nl, char *name);
64int is_oidstr(const char *oidstr);
65
66struct attr_type *
67lookup_attribute_by_name(struct schema *schema, char *name)
68{
69 struct oidname *on, find;
70
71 find.on_name = name;
72 on = RB_FIND(oidname_tree, &schema->attr_names, &find)oidname_tree_RB_FIND(&schema->attr_names, &find);
73
74 if (on)
75 return on->on_attr_typeon_ptr.ou_attr_type;
76 return NULL((void*)0);
77}
78
79struct attr_type *
80lookup_attribute_by_oid(struct schema *schema, char *oid)
81{
82 struct attr_type find;
83
84 find.oid = oid;
85 return RB_FIND(attr_type_tree, &schema->attr_types, &find)attr_type_tree_RB_FIND(&schema->attr_types, &find);
86}
87
88struct attr_type *
89lookup_attribute(struct schema *schema, char *oid_or_name)
90{
91 if (is_oidstr(oid_or_name))
92 return lookup_attribute_by_oid(schema, oid_or_name);
93 return lookup_attribute_by_name(schema, oid_or_name);
94}
95
96struct object *
97lookup_object_by_oid(struct schema *schema, char *oid)
98{
99 struct object find;
100
101 find.oid = oid;
102 return RB_FIND(object_tree, &schema->objects, &find)object_tree_RB_FIND(&schema->objects, &find);
103}
104
105struct object *
106lookup_object_by_name(struct schema *schema, char *name)
107{
108 struct oidname *on, find;
109
110 find.on_name = name;
111 on = RB_FIND(oidname_tree, &schema->object_names, &find)oidname_tree_RB_FIND(&schema->object_names, &find);
112
113 if (on)
114 return on->on_objecton_ptr.ou_object;
115 return NULL((void*)0);
116}
117
118struct object *
119lookup_object(struct schema *schema, char *oid_or_name)
120{
121 if (is_oidstr(oid_or_name))
122 return lookup_object_by_oid(schema, oid_or_name);
123 return lookup_object_by_name(schema, oid_or_name);
124}
125
126/*
127 * Looks up a symbolic OID, optionally with a suffix OID, so if
128 * SYMBOL = 1.2.3.4
129 * then
130 * SYMBOL:5.6 = 1.2.3.4.5.6
131 *
132 * Returned string must be freed by the caller.
133 * Modifies the name argument.
134 */
135char *
136lookup_symbolic_oid(struct schema *schema, char *name)
137{
138 struct symoid *symoid, find;
139 char *colon, *oid;
140 size_t sz;
141
142 colon = strchr(name, ':');
143 if (colon != NULL((void*)0)) {
144 if (!is_oidstr(colon + 1)) {
145 log_warnx("invalid OID after colon: %s", colon + 1);
146 return NULL((void*)0);
147 }
148 *colon = '\0';
149 }
150
151 find.name = name;
152 symoid = RB_FIND(symoid_tree, &schema->symbolic_oids, &find)symoid_tree_RB_FIND(&schema->symbolic_oids, &find);
153 if (symoid == NULL((void*)0))
154 return NULL((void*)0);
155
156 if (colon == NULL((void*)0))
157 return strdup(symoid->oid);
158
159 /* Expand SYMBOL:OID. */
160 sz = strlen(symoid->oid) + 1 + strlen(colon + 1) + 1;
161 if ((oid = malloc(sz)) == NULL((void*)0)) {
162 log_warnx("malloc");
163 return NULL((void*)0);
164 }
165
166 strlcpy(oid, symoid->oid, sz);
167 strlcat(oid, ".", sz);
168 strlcat(oid, colon + 1, sz);
169
170 return oid;
171}
172
173/*
174 * Push a symbol-OID pair on the tree. Name and OID must be valid pointers
175 * during the lifetime of the tree.
176 */
177static struct symoid *
178push_symbolic_oid(struct schema *schema, char *name, char *oid)
179{
180 struct symoid *symoid, find;
181
182 find.name = name;
183 symoid = RB_FIND(symoid_tree, &schema->symbolic_oids, &find)symoid_tree_RB_FIND(&schema->symbolic_oids, &find);
184
185 if (symoid == NULL((void*)0)) {
186 symoid = calloc(1, sizeof(*symoid));
187 if (symoid == NULL((void*)0)) {
188 log_warnx("calloc");
189 return NULL((void*)0);
190 }
191
192 symoid->name = name;
193 RB_INSERT(symoid_tree, &schema->symbolic_oids, symoid)symoid_tree_RB_INSERT(&schema->symbolic_oids, symoid);
194 }
195
196 free(symoid->oid);
197 symoid->oid = oid;
198
199 return symoid;
200}
201
202static struct attr_list *
203push_attr(struct attr_list *alist, struct attr_type *a)
204{
205 struct attr_ptr *aptr;
206
207 if (alist == NULL((void*)0)) {
208 if ((alist = calloc(1, sizeof(*alist))) == NULL((void*)0)) {
209 log_warn("calloc");
210 return NULL((void*)0);
211 }
212 SLIST_INIT(alist){ ((alist)->slh_first) = ((void*)0); };
213 }
214
215 if ((aptr = calloc(1, sizeof(*aptr))) == NULL((void*)0)) {
216 log_warn("calloc");
217 free(alist);
218 return NULL((void*)0);
219 }
220 aptr->attr_type = a;
221 SLIST_INSERT_HEAD(alist, aptr, next)do { (aptr)->next.sle_next = (alist)->slh_first; (alist
)->slh_first = (aptr); } while (0)
;
222
223 return alist;
224}
225
226static struct obj_list *
227push_obj(struct obj_list *olist, struct object *obj)
228{
229 struct obj_ptr *optr;
230
231 if (olist == NULL((void*)0)) {
232 if ((olist = calloc(1, sizeof(*olist))) == NULL((void*)0)) {
233 log_warn("calloc");
234 return NULL((void*)0);
235 }
236 SLIST_INIT(olist){ ((olist)->slh_first) = ((void*)0); };
237 }
238
239 if ((optr = calloc(1, sizeof(*optr))) == NULL((void*)0)) {
240 log_warn("calloc");
241 free(olist);
242 return NULL((void*)0);
243 }
244 optr->object = obj;
245 SLIST_INSERT_HEAD(olist, optr, next)do { (optr)->next.sle_next = (olist)->slh_first; (olist
)->slh_first = (optr); } while (0)
;
246
247 return olist;
248}
249
250int
251is_oidstr(const char *oidstr)
252{
253 struct ber_oid oid;
254 return (ober_string2oid(oidstr, &oid) == 0);
255}
256
257static struct name_list *
258push_name(struct name_list *nl, char *name)
259{
260 struct name *n;
261
262 if (nl == NULL((void*)0)) {
263 if ((nl = calloc(1, sizeof(*nl))) == NULL((void*)0)) {
264 log_warn("calloc");
265 return NULL((void*)0);
266 }
267 SLIST_INIT(nl){ ((nl)->slh_first) = ((void*)0); };
268 }
269 if ((n = calloc(1, sizeof(*n))) == NULL((void*)0)) {
270 log_warn("calloc");
271 free(nl);
272 return NULL((void*)0);
273 }
274 n->name = name;
275 SLIST_INSERT_HEAD(nl, n, next)do { (n)->next.sle_next = (nl)->slh_first; (nl)->slh_first
= (n); } while (0)
;
276
277 return nl;
278}
279
280static int
281schema_getc(struct schema *schema, int quotec)
282{
283 int c, next;
284
285 if (schema->pushback_index)
286 return (schema->pushback_buffer[--schema->pushback_index]);
287
288 if (quotec) {
289 if ((c = getc(schema->fp)(!__isthreaded ? (--(schema->fp)->_r < 0 ? __srget(schema
->fp) : (int)(*(schema->fp)->_p++)) : (getc)(schema->
fp))
) == EOF(-1)) {
290 log_warnx("reached end of file while parsing "
291 "quoted string");
292 return EOF(-1);
293 }
294 return (c);
295 }
296
297 while ((c = getc(schema->fp)(!__isthreaded ? (--(schema->fp)->_r < 0 ? __srget(schema
->fp) : (int)(*(schema->fp)->_p++)) : (getc)(schema->
fp))
) == '\\') {
298 next = getc(schema->fp)(!__isthreaded ? (--(schema->fp)->_r < 0 ? __srget(schema
->fp) : (int)(*(schema->fp)->_p++)) : (getc)(schema->
fp))
;
299 if (next != '\n') {
300 c = next;
301 break;
302 }
303 schema->lineno++;
304 }
305
306 return (c);
307}
308
309static int
310schema_ungetc(struct schema *schema, int c)
311{
312 if (c == EOF(-1))
313 return EOF(-1);
314
315 if (schema->pushback_index < SCHEMA_MAXPUSHBACK128-1)
316 return (schema->pushback_buffer[schema->pushback_index++] = c);
317 else
318 return (EOF(-1));
319}
320
321static int
322findeol(struct schema *schema)
323{
324 int c;
325
326 /* skip to either EOF or the first real EOL */
327 while (1) {
328 if (schema->pushback_index)
329 c = schema->pushback_buffer[--schema->pushback_index];
330 else
331 c = schema_getc(schema, 0);
332 if (c == '\n') {
333 schema->lineno++;
334 break;
335 }
336 if (c == EOF(-1))
337 break;
338 }
339 return (ERROR-1);
340}
341
342static int
343schema_lex(struct schema *schema, char **kw)
344{
345 char buf[8096];
346 char *p;
347 int quotec, next, c;
348
349 if (kw
22.1
'kw' is non-null
)
23
Taking true branch
350 *kw = NULL((void*)0);
351
352top:
353 p = buf;
354 while ((c = schema_getc(schema, 0)) == ' ' || c == '\t')
24
Assuming the condition is false
25
Assuming the condition is false
26
Loop condition is false. Execution continues on line 357
355 ; /* nothing */
356
357 if (c == '#')
27
Assuming the condition is false
28
Taking false branch
358 while ((c = schema_getc(schema, 0)) != '\n' && c != EOF(-1))
359 ; /* nothing */
360
361 switch (c) {
29
Control jumps to 'case 34:' at line 363
362 case '\'':
363 case '"':
364 quotec = c;
365 while (1) {
30
Loop condition is true. Entering loop body
366 if ((c = schema_getc(schema, quotec)) == EOF(-1))
31
Assuming the condition is false
32
Taking false branch
367 return (0);
368 if (c == '\n') {
33
Assuming the condition is false
34
Taking false branch
369 schema->lineno++;
370 continue;
371 } else if (c == '\\') {
35
Assuming the condition is false
36
Taking false branch
372 if ((next = schema_getc(schema, quotec)) == EOF(-1))
373 return (0);
374 if (next == quotec || c == ' ' || c == '\t')
375 c = next;
376 else if (next == '\n')
377 continue;
378 else
379 schema_ungetc(schema, next);
380 } else if (c == quotec) {
37
Assuming 'c' is equal to 'quotec'
38
Taking true branch
381 *p = '\0';
382 break;
39
Execution continues on line 390
383 }
384 if (p + 1 >= buf + sizeof(buf) - 1) {
385 log_warnx("string too long");
386 return (findeol(schema));
387 }
388 *p++ = (char)c;
389 }
390 if (kw
39.1
'kw' is not equal to NULL
!= NULL((void*)0) && (*kw = strdup(buf)) == NULL((void*)0))
40
Memory is allocated
41
Assuming the condition is false
42
Taking false branch
391 fatal("schema_lex: strdup");
392 return (STRING1);
393 }
394
395#define allowed_in_string(x)(isalnum(x) || (ispunct(x) && x != '(' && x !=
')' && x != '{' && x != '}' && x != '<'
&& x != '>' && x != '!' && x != '='
&& x != '/' && x != '#' && x != ',')
)
\
396 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
397 x != '{' && x != '}' && x != '<' && x != '>' && \
398 x != '!' && x != '=' && x != '/' && x != '#' && \
399 x != ','))
400
401 if (isalnum(c) || c == ':' || c == '_' || c == '*') {
402 do {
403 *p++ = c;
404 if ((size_t)(p-buf) >= sizeof(buf)) {
405 log_warnx("string too long");
406 return (findeol(schema));
407 }
408 } while ((c = schema_getc(schema, 0)) != EOF(-1) && (allowed_in_string(c)(isalnum(c) || (ispunct(c) && c != '(' && c !=
')' && c != '{' && c != '}' && c != '<'
&& c != '>' && c != '!' && c != '='
&& c != '/' && c != '#' && c != ',')
)
));
409 schema_ungetc(schema, c);
410 *p = '\0';
411 if (kw != NULL((void*)0) && (*kw = strdup(buf)) == NULL((void*)0))
412 fatal("schema_lex: strdup");
413 return STRING1;
414 }
415 if (c == '\n') {
416 schema->lineno++;
417 goto top;
418 }
419 if (c == EOF(-1))
420 return (0);
421 return (c);
422}
423
424struct schema *
425schema_new(void)
426{
427 struct schema *schema;
428
429 if ((schema = calloc(1, sizeof(*schema))) == NULL((void*)0))
430 return NULL((void*)0);
431
432 RB_INIT(&schema->attr_types)do { (&schema->attr_types)->rbh_root = ((void*)0); }
while (0)
;
433 RB_INIT(&schema->attr_names)do { (&schema->attr_names)->rbh_root = ((void*)0); }
while (0)
;
434 RB_INIT(&schema->objects)do { (&schema->objects)->rbh_root = ((void*)0); } while
(0)
;
435 RB_INIT(&schema->object_names)do { (&schema->object_names)->rbh_root = ((void*)0)
; } while (0)
;
436 RB_INIT(&schema->symbolic_oids)do { (&schema->symbolic_oids)->rbh_root = ((void*)0
); } while (0)
;
437
438 return schema;
439}
440
441static void
442schema_err(struct schema *schema, const char *fmt, ...)
443{
444 va_list ap;
445 char *msg;
446
447 va_start(ap, fmt)__builtin_va_start(ap, fmt);
448 if (vasprintf(&msg, fmt, ap) == -1)
449 fatal("vasprintf");
450 va_end(ap)__builtin_va_end(ap);
451 logit(LOG_CRIT2, "%s:%d: %s", schema->filename, schema->lineno, msg);
452 free(msg);
453
454 schema->error++;
455}
456
457static int
458schema_link_attr_name(struct schema *schema, const char *name, struct attr_type *attr)
459{
460 struct oidname *oidname, *prev;
461
462 if ((oidname = calloc(1, sizeof(*oidname))) == NULL((void*)0)) {
463 log_warn("calloc");
464 return -1;
465 }
466
467 oidname->on_name = name;
468 oidname->on_attr_typeon_ptr.ou_attr_type = attr;
469 prev = RB_INSERT(oidname_tree, &schema->attr_names, oidname)oidname_tree_RB_INSERT(&schema->attr_names, oidname);
470 if (prev != NULL((void*)0)) {
471 schema_err(schema, "attribute type name '%s'"
472 " already defined for oid %s",
473 name, prev->on_attr_typeon_ptr.ou_attr_type->oid);
474 free(oidname);
475 return -1;
476 }
477
478 return 0;
479}
480
481static int
482schema_link_attr_names(struct schema *schema, struct attr_type *attr)
483{
484 struct name *name;
485
486 SLIST_FOREACH(name, attr->names, next)for((name) = ((attr->names)->slh_first); (name) != ((void
*)0); (name) = ((name)->next.sle_next))
{
487 if (schema_link_attr_name(schema, name->name, attr) != 0)
488 return -1;
489 }
490 return 0;
491}
492
493static int
494schema_link_obj_name(struct schema *schema, const char *name, struct object *obj)
495{
496 struct oidname *oidname, *prev;
497
498 if ((oidname = calloc(1, sizeof(*oidname))) == NULL((void*)0)) {
499 log_warn("calloc");
500 return -1;
501 }
502
503 oidname->on_name = name;
504 oidname->on_objecton_ptr.ou_object = obj;
505 prev = RB_INSERT(oidname_tree, &schema->object_names, oidname)oidname_tree_RB_INSERT(&schema->object_names, oidname);
506 if (prev != NULL((void*)0)) {
507 schema_err(schema, "object class name '%s'"
508 " already defined for oid %s",
509 name, prev->on_objecton_ptr.ou_object->oid);
510 free(oidname);
511 return -1;
512 }
513
514 return 0;
515}
516
517static int
518schema_link_obj_names(struct schema *schema, struct object *obj)
519{
520 struct name *name;
521
522 SLIST_FOREACH(name, obj->names, next)for((name) = ((obj->names)->slh_first); (name) != ((void
*)0); (name) = ((name)->next.sle_next))
{
523 if (schema_link_obj_name(schema, name->name, obj) != 0)
524 return -1;
525 }
526 return 0;
527}
528
529static struct name_list *
530schema_parse_names(struct schema *schema)
531{
532 struct name_list *nlist = NULL((void*)0);
533 char *kw;
534 int token;
535
536 token = schema_lex(schema, &kw);
22
Calling 'schema_lex'
43
Returned allocated memory via 2nd parameter
537 if (token
43.1
'token' is equal to STRING
== STRING1)
44
Taking true branch
538 return push_name(NULL((void*)0), kw);
45
Potential leak of memory pointed to by 'kw'
539
540 if (token != '(')
541 goto fail;
542
543 for (;;) {
544 token = schema_lex(schema, &kw);
545 if (token == ')')
546 break;
547 if (token != STRING1)
548 goto fail;
549 nlist = push_name(nlist, kw);
550 }
551
552 return nlist;
553
554fail:
555 free(kw);
556 /* FIXME: leaks nlist here */
557 return NULL((void*)0);
558}
559
560static void
561schema_free_name_list(struct name_list *nlist)
562{
563 struct name *name;
564
565 while ((name = SLIST_FIRST(nlist)((nlist)->slh_first)) != NULL((void*)0)) {
566 SLIST_REMOVE_HEAD(nlist, next)do { (nlist)->slh_first = (nlist)->slh_first->next.sle_next
; } while (0)
;
567 free(name->name);
568 free(name);
569 }
570 free(nlist);
571}
572
573static struct attr_list *
574schema_parse_attrlist(struct schema *schema)
575{
576 struct attr_list *alist = NULL((void*)0);
577 struct attr_type *attr;
578 char *kw;
579 int token, want_dollar = 0;
580
581 token = schema_lex(schema, &kw);
582 if (token == STRING1) {
583 if ((attr = lookup_attribute(schema, kw)) == NULL((void*)0)) {
584 schema_err(schema, "undeclared attribute type '%s'", kw);
585 goto fail;
586 }
587 free(kw);
588 return push_attr(NULL((void*)0), attr);
589 }
590
591 if (token != '(')
592 goto fail;
593
594 for (;;) {
595 token = schema_lex(schema, &kw);
596 if (token == ')')
597 break;
598 if (token == '$') {
599 if (!want_dollar)
600 goto fail;
601 want_dollar = 0;
602 continue;
603 }
604 if (token != STRING1)
605 goto fail;
606 if ((attr = lookup_attribute(schema, kw)) == NULL((void*)0)) {
607 schema_err(schema, "%s: no such attribute", kw);
608 goto fail;
609 }
610 alist = push_attr(alist, attr);
611 free(kw);
612 want_dollar = 1;
613 }
614
615 return alist;
616
617fail:
618 free(kw);
619 /* FIXME: leaks alist here */
620 return NULL((void*)0);
621}
622
623static struct obj_list *
624schema_parse_objlist(struct schema *schema)
625{
626 struct obj_list *olist = NULL((void*)0);
627 struct object *obj;
628 char *kw;
629 int token, want_dollar = 0;
630
631 token = schema_lex(schema, &kw);
632 if (token == STRING1) {
633 if ((obj = lookup_object(schema, kw)) == NULL((void*)0)) {
634 schema_err(schema, "undeclared object class '%s'", kw);
635 goto fail;
636 }
637 free(kw);
638 return push_obj(NULL((void*)0), obj);
639 }
640
641 if (token != '(')
642 goto fail;
643
644 for (;;) {
645 token = schema_lex(schema, &kw);
646 if (token == ')')
647 break;
648 if (token == '$') {
649 if (!want_dollar)
650 goto fail;
651 want_dollar = 0;
652 continue;
653 }
654 if (token != STRING1)
655 goto fail;
656 if ((obj = lookup_object(schema, kw)) == NULL((void*)0))
657 goto fail;
658 olist = push_obj(olist, obj);
659 want_dollar = 1;
660 }
661
662 return olist;
663
664fail:
665 free(kw);
666 /* FIXME: leaks olist here */
667 return NULL((void*)0);
668}
669
670static int
671schema_validate_match_rule(struct schema *schema, struct attr_type *at,
672 const struct match_rule *mrule, enum match_rule_type type)
673{
674 int i;
675
676 if (mrule == NULL((void*)0))
677 return 0;
678
679 if ((mrule->type & type) != type) {
680 schema_err(schema, "%s: bad matching rule '%s'",
681 ATTR_NAME(at)((at)->names ? (((at)->names)->slh_first)->name :
(at)->oid)
, mrule->name);
682 return -1;
683 }
684
685 /* Is this matching rule compatible with the attribute syntax? */
686 if (strcmp(mrule->syntax_oid, at->syntax->oid) == 0)
687 return 0;
688
689 /* Check any alternative syntaxes for compatibility. */
690 for (i = 0; mrule->alt_syntax_oids && mrule->alt_syntax_oids[i]; i++)
691 if (strcmp(mrule->alt_syntax_oids[i], at->syntax->oid) == 0)
692 return 0;
693
694 schema_err(schema, "%s: inappropriate matching rule '%s' for syntax [%s]",
695 ATTR_NAME(at)((at)->names ? (((at)->names)->slh_first)->name :
(at)->oid)
, mrule->name, at->syntax->oid);
696 return -1;
697}
698
699static int
700schema_parse_attributetype(struct schema *schema)
701{
702 struct attr_type *attr = NULL((void*)0), *prev, *sup;
703 struct name_list *xnames;
704 char *kw = NULL((void*)0), *arg = NULL((void*)0);
705 int token, ret = 0, c;
706
707 if (schema_lex(schema, NULL((void*)0)) != '(')
708 goto fail;
709
710 if (schema_lex(schema, &kw) != STRING1)
711 goto fail;
712
713 if ((attr = calloc(1, sizeof(*attr))) == NULL((void*)0)) {
714 log_warn("calloc");
715 goto fail;
716 }
717 attr->usage = USAGE_USER_APP;
718
719 if (is_oidstr(kw))
720 attr->oid = kw;
721 else {
722 attr->oid = lookup_symbolic_oid(schema, kw);
723 if (attr->oid == NULL((void*)0))
724 goto fail;
725 free(kw);
726 }
727 kw = NULL((void*)0);
728
729 prev = RB_INSERT(attr_type_tree, &schema->attr_types, attr)attr_type_tree_RB_INSERT(&schema->attr_types, attr);
730 if (prev != NULL((void*)0)) {
731 schema_err(schema, "attribute type %s already defined", attr->oid);
732 goto fail;
733 }
734
735 while (ret == 0) {
736 token = schema_lex(schema, &kw);
737 if (token == ')')
738 break;
739 else if (token != STRING1)
740 goto fail;
741 if (strcasecmp(kw, "NAME") == 0) {
742 attr->names = schema_parse_names(schema);
743 if (attr->names == NULL((void*)0))
744 goto fail;
745 schema_link_attr_names(schema, attr);
746 } else if (strcasecmp(kw, "DESC") == 0) {
747 if (schema_lex(schema, &attr->desc) != STRING1)
748 goto fail;
749 } else if (strcasecmp(kw, "OBSOLETE") == 0) {
750 attr->obsolete = 1;
751 } else if (strcasecmp(kw, "SUP") == 0) {
752 if (schema_lex(schema, &arg) != STRING1)
753 goto fail;
754 if ((attr->sup = lookup_attribute(schema, arg)) == NULL((void*)0)) {
755 schema_err(schema, "%s: no such attribute", arg);
756 goto fail;
757 }
758 free(arg);
759 } else if (strcasecmp(kw, "EQUALITY") == 0) {
760 if (schema_lex(schema, &arg) != STRING1)
761 goto fail;
762 if ((attr->equality = match_rule_lookup(arg)) == NULL((void*)0)) {
763 schema_err(schema, "%s: unknown matching rule",
764 arg);
765 goto fail;
766 }
767 free(arg);
768 } else if (strcasecmp(kw, "ORDERING") == 0) {
769 if (schema_lex(schema, &arg) != STRING1)
770 goto fail;
771 if ((attr->ordering = match_rule_lookup(arg)) == NULL((void*)0)) {
772 schema_err(schema, "%s: unknown matching rule",
773 arg);
774 goto fail;
775 }
776 free(arg);
777 } else if (strcasecmp(kw, "SUBSTR") == 0) {
778 if (schema_lex(schema, &arg) != STRING1)
779 goto fail;
780 if ((attr->substr = match_rule_lookup(arg)) == NULL((void*)0)) {
781 schema_err(schema, "%s: unknown matching rule",
782 arg);
783 goto fail;
784 }
785 free(arg);
786 } else if (strcasecmp(kw, "SYNTAX") == 0) {
787 if (schema_lex(schema, &arg) != STRING1 ||
788 !is_oidstr(arg))
789 goto fail;
790
791 if ((attr->syntax = syntax_lookup(arg)) == NULL((void*)0)) {
792 schema_err(schema, "syntax not supported: %s",
793 arg);
794 goto fail;
795 }
796
797 if ((c = schema_getc(schema, 0)) == '{') {
798 if (schema_lex(schema, NULL((void*)0)) != STRING1 ||
799 schema_lex(schema, NULL((void*)0)) != '}')
800 goto fail;
801 } else
802 schema_ungetc(schema, c);
803 free(arg);
804 } else if (strcasecmp(kw, "SINGLE-VALUE") == 0) {
805 attr->single = 1;
806 } else if (strcasecmp(kw, "COLLECTIVE") == 0) {
807 attr->collective = 1;
808 } else if (strcasecmp(kw, "NO-USER-MODIFICATION") == 0) {
809 attr->immutable = 1;
810 } else if (strcasecmp(kw, "USAGE") == 0) {
811 if (schema_lex(schema, &arg) != STRING1)
812 goto fail;
813 if (strcasecmp(arg, "dSAOperation") == 0)
814 attr->usage = USAGE_DSA_OP;
815 else if (strcasecmp(arg, "directoryOperation") == 0)
816 attr->usage = USAGE_DIR_OP;
817 else if (strcasecmp(arg, "distributedOperation") == 0)
818 attr->usage = USAGE_DIST_OP;
819 else if (strcasecmp(arg, "userApplications") == 0)
820 attr->usage = USAGE_USER_APP;
821 else {
822 schema_err(schema, "invalid usage '%s'", arg);
823 goto fail;
824 }
825 free(arg);
826 } else if (strncmp(kw, "X-", 2) == 0) {
827 /* unknown extension, eat argument(s) */
828 xnames = schema_parse_names(schema);
829 if (xnames == NULL((void*)0))
830 goto fail;
831 schema_free_name_list(xnames);
832 } else {
833 schema_err(schema, "syntax error at token '%s'", kw);
834 goto fail;
835 }
836 free(kw);
837 }
838
839 /* Check that a syntax is defined, either directly or
840 * indirectly via a superior attribute type.
841 */
842 sup = attr->sup;
843 while (attr->syntax == NULL((void*)0) && sup != NULL((void*)0)) {
844 attr->syntax = sup->syntax;
845 sup = sup->sup;
846 }
847 if (attr->syntax == NULL((void*)0)) {
848 schema_err(schema, "%s: no syntax defined", ATTR_NAME(attr)((attr)->names ? (((attr)->names)->slh_first)->name
: (attr)->oid)
);
849 goto fail;
850 }
851
852 /* If the attribute type doesn't explicitly define equality, check
853 * if any superior attribute type does.
854 */
855 sup = attr->sup;
856 while (attr->equality == NULL((void*)0) && sup != NULL((void*)0)) {
857 attr->equality = sup->equality;
858 sup = sup->sup;
859 }
860 /* Same thing with ordering matching rule. */
861 sup = attr->sup;
862 while (attr->ordering == NULL((void*)0) && sup != NULL((void*)0)) {
863 attr->ordering = sup->ordering;
864 sup = sup->sup;
865 }
866 /* ...and substring matching rule. */
867 sup = attr->sup;
868 while (attr->substr == NULL((void*)0) && sup != NULL((void*)0)) {
869 attr->substr = sup->substr;
870 sup = sup->sup;
871 }
872
873 if (schema_validate_match_rule(schema, attr, attr->equality, MATCH_EQUALITY) != 0 ||
874 schema_validate_match_rule(schema, attr, attr->ordering, MATCH_ORDERING) != 0 ||
875 schema_validate_match_rule(schema, attr, attr->substr, MATCH_SUBSTR) != 0)
876 goto fail;
877
878 return 0;
879
880fail:
881 free(kw);
882 if (attr != NULL((void*)0)) {
883 if (attr->oid != NULL((void*)0)) {
884 RB_REMOVE(attr_type_tree, &schema->attr_types, attr)attr_type_tree_RB_REMOVE(&schema->attr_types, attr);
885 free(attr->oid);
886 }
887 free(attr->desc);
888 free(attr);
889 }
890 return -1;
891}
892
893static int
894schema_parse_objectclass(struct schema *schema)
895{
896 struct object *obj = NULL((void*)0), *prev;
897 struct obj_ptr *optr;
898 struct name_list *xnames;
899 char *kw = NULL((void*)0);
900 int token, ret = 0;
901
902 if (schema_lex(schema, NULL((void*)0)) != '(')
9
Assuming the condition is false
10
Taking false branch
903 goto fail;
904
905 if (schema_lex(schema, &kw) != STRING1)
11
Assuming the condition is false
12
Taking false branch
906 goto fail;
907
908 if ((obj = calloc(1, sizeof(*obj))) == NULL((void*)0)) {
13
Assuming the condition is false
14
Taking false branch
909 log_warn("calloc");
910 goto fail;
911 }
912 obj->kind = KIND_STRUCTURAL;
913
914 if (is_oidstr(kw))
15
Taking true branch
915 obj->oid = kw;
916 else {
917 obj->oid = lookup_symbolic_oid(schema, kw);
918 if (obj->oid == NULL((void*)0))
919 goto fail;
920 free(kw);
921 }
922 kw = NULL((void*)0);
923
924 prev = RB_INSERT(object_tree, &schema->objects, obj)object_tree_RB_INSERT(&schema->objects, obj);
925 if (prev
15.1
'prev' is equal to NULL
!= NULL((void*)0)) {
16
Taking false branch
926 schema_err(schema, "object class %s already defined", obj->oid);
927 goto fail;
928 }
929
930 while (ret == 0) {
17
Loop condition is true. Entering loop body
931 token = schema_lex(schema, &kw);
932 if (token == ')')
18
Taking false branch
933 break;
934 else if (token
18.1
'token' is equal to STRING
!= STRING1)
19
Taking false branch
935 goto fail;
936 if (strcasecmp(kw, "NAME") == 0) {
20
Taking true branch
937 obj->names = schema_parse_names(schema);
21
Calling 'schema_parse_names'
938 if (obj->names == NULL((void*)0))
939 goto fail;
940 schema_link_obj_names(schema, obj);
941 } else if (strcasecmp(kw, "DESC") == 0) {
942 if (schema_lex(schema, &obj->desc) != STRING1)
943 goto fail;
944 } else if (strcasecmp(kw, "OBSOLETE") == 0) {
945 obj->obsolete = 1;
946 } else if (strcasecmp(kw, "SUP") == 0) {
947 obj->sup = schema_parse_objlist(schema);
948 if (obj->sup == NULL((void*)0))
949 goto fail;
950 } else if (strcasecmp(kw, "ABSTRACT") == 0) {
951 obj->kind = KIND_ABSTRACT;
952 } else if (strcasecmp(kw, "STRUCTURAL") == 0) {
953 obj->kind = KIND_STRUCTURAL;
954 } else if (strcasecmp(kw, "AUXILIARY") == 0) {
955 obj->kind = KIND_AUXILIARY;
956 } else if (strcasecmp(kw, "MUST") == 0) {
957 obj->must = schema_parse_attrlist(schema);
958 if (obj->must == NULL((void*)0))
959 goto fail;
960 } else if (strcasecmp(kw, "MAY") == 0) {
961 obj->may = schema_parse_attrlist(schema);
962 if (obj->may == NULL((void*)0))
963 goto fail;
964 } else if (strncasecmp(kw, "X-", 2) == 0) {
965 /* unknown extension, eat argument(s) */
966 xnames = schema_parse_names(schema);
967 if (xnames == NULL((void*)0))
968 goto fail;
969 schema_free_name_list(xnames);
970 } else {
971 schema_err(schema, "syntax error at token '%s'", kw);
972 goto fail;
973 }
974 free(kw);
975 }
976
977 /* Verify the subclassing is allowed.
978 *
979 * Structural object classes cannot subclass auxiliary object classes.
980 * Auxiliary object classes cannot subclass structural object classes.
981 * Abstract object classes cannot derive from structural or auxiliary
982 * object classes.
983 */
984 if (obj->sup != NULL((void*)0)) {
985 SLIST_FOREACH(optr, obj->sup, next)for((optr) = ((obj->sup)->slh_first); (optr) != ((void*
)0); (optr) = ((optr)->next.sle_next))
{
986 if (obj->kind == KIND_STRUCTURAL &&
987 optr->object->kind == KIND_AUXILIARY) {
988 log_warnx("structural object class '%s' cannot"
989 " subclass auxiliary object class '%s'",
990 OBJ_NAME(obj)((obj)->names ? (((obj)->names)->slh_first)->name
: (obj)->oid)
, OBJ_NAME(optr->object)((optr->object)->names ? (((optr->object)->names)
->slh_first)->name : (optr->object)->oid)
);
991 goto fail;
992 }
993
994 if (obj->kind == KIND_AUXILIARY &&
995 optr->object->kind == KIND_STRUCTURAL) {
996 log_warnx("auxiliary object class '%s' cannot"
997 " subclass structural object class '%s'",
998 OBJ_NAME(obj)((obj)->names ? (((obj)->names)->slh_first)->name
: (obj)->oid)
, OBJ_NAME(optr->object)((optr->object)->names ? (((optr->object)->names)
->slh_first)->name : (optr->object)->oid)
);
999 goto fail;
1000 }
1001
1002 if (obj->kind == KIND_ABSTRACT &&
1003 optr->object->kind != KIND_ABSTRACT) {
1004 log_warnx("abstract object class '%s' cannot"
1005 " subclass non-abstract object class '%s'",
1006 OBJ_NAME(obj)((obj)->names ? (((obj)->names)->slh_first)->name
: (obj)->oid)
, OBJ_NAME(optr->object)((optr->object)->names ? (((optr->object)->names)
->slh_first)->name : (optr->object)->oid)
);
1007 goto fail;
1008 }
1009 }
1010 }
1011
1012 return 0;
1013
1014fail:
1015 free(kw);
1016 if (obj != NULL((void*)0)) {
1017 if (obj->oid != NULL((void*)0)) {
1018 RB_REMOVE(object_tree, &schema->objects, obj)object_tree_RB_REMOVE(&schema->objects, obj);
1019 free(obj->oid);
1020 }
1021 free(obj->desc);
1022 free(obj);
1023 }
1024 return -1;
1025}
1026
1027static int
1028schema_parse_objectidentifier(struct schema *schema)
1029{
1030 char *symname = NULL((void*)0), *symoid = NULL((void*)0);
1031 char *oid = NULL((void*)0);
1032
1033 if (schema_lex(schema, &symname) != STRING1)
1034 goto fail;
1035 if (schema_lex(schema, &symoid) != STRING1)
1036 goto fail;
1037
1038 if (is_oidstr(symoid)) {
1039 oid = symoid;
1040 symoid = NULL((void*)0);
1041 } else if ((oid = lookup_symbolic_oid(schema, symoid)) == NULL((void*)0))
1042 goto fail;
1043
1044 if (push_symbolic_oid(schema, symname, oid) == NULL((void*)0))
1045 goto fail;
1046
1047 free(symoid);
1048 return 0;
1049
1050fail:
1051 free(symname);
1052 free(symoid);
1053 free(oid);
1054 return -1;
1055}
1056
1057int
1058schema_parse(struct schema *schema, const char *filename)
1059{
1060 char *kw;
1061 int token, ret = 0;
1062
1063 log_debug("parsing schema file '%s'", filename);
1064
1065 if ((schema->fp = fopen(filename, "r")) == NULL((void*)0)) {
1
Assuming the condition is false
2
Taking false branch
1066 log_warn("%s", filename);
1067 return -1;
1068 }
1069 schema->filename = filename;
1070 schema->lineno = 1;
1071
1072 while (ret == 0) {
3
Loop condition is true. Entering loop body
1073 token = schema_lex(schema, &kw);
1074 if (token
3.1
'token' is equal to STRING
== STRING1) {
4
Taking true branch
1075 if (strcasecmp(kw, "attributetype") == 0)
5
Assuming the condition is false
6
Taking false branch
1076 ret = schema_parse_attributetype(schema);
1077 else if (strcasecmp(kw, "objectclass") == 0)
7
Taking true branch
1078 ret = schema_parse_objectclass(schema);
8
Calling 'schema_parse_objectclass'
1079 else if (strcasecmp(kw, "objectidentifier") == 0)
1080 ret = schema_parse_objectidentifier(schema);
1081 else {
1082 schema_err(schema, "syntax error at '%s'", kw);
1083 ret = -1;
1084 }
1085 if (ret == -1 && schema->error == 0)
1086 schema_err(schema, "syntax error");
1087 free(kw);
1088 } else if (token == 0) { /* EOF */
1089 break;
1090 } else {
1091 schema_err(schema, "syntax error");
1092 ret = -1;
1093 }
1094 }
1095
1096 fclose(schema->fp);
1097 schema->fp = NULL((void*)0);
1098 schema->filename = NULL((void*)0);
1099
1100 return ret;
1101}
1102
1103static int
1104schema_dump_names(const char *desc, struct name_list *nlist,
1105 char *buf, size_t size)
1106{
1107 struct name *name;
1108
1109 if (nlist == NULL((void*)0) || SLIST_EMPTY(nlist)(((nlist)->slh_first) == ((void*)0)))
1110 return 0;
1111
1112 if (strlcat(buf, " ", size) >= size ||
1113 strlcat(buf, desc, size) >= size)
1114 return -1;
1115
1116 name = SLIST_FIRST(nlist)((nlist)->slh_first);
1117 if (SLIST_NEXT(name, next)((name)->next.sle_next) == NULL((void*)0)) {
1118 /* single name, no parenthesis */
1119 if (strlcat(buf, " '", size) >= size ||
1120 strlcat(buf, name->name, size) >= size ||
1121 strlcat(buf, "'", size) >= size)
1122 return -1;
1123 } else {
1124 if (strlcat(buf, " ( ", size) >= size)
1125 return -1;
1126 SLIST_FOREACH(name, nlist, next)for((name) = ((nlist)->slh_first); (name) != ((void*)0); (
name) = ((name)->next.sle_next))
1127 if (strlcat(buf, "'", size) >= size ||
1128 strlcat(buf, name->name, size) >= size ||
1129 strlcat(buf, "' ", size) >= size)
1130 return -1;
1131 if (strlcat(buf, ")", size) >= size)
1132 return -1;
1133 }
1134
1135 return 0;
1136}
1137
1138static int
1139schema_dump_attrlist(const char *desc, struct attr_list *alist,
1140 char *buf, size_t size)
1141{
1142 struct attr_ptr *aptr;
1143
1144 if (alist == NULL((void*)0) || SLIST_EMPTY(alist)(((alist)->slh_first) == ((void*)0)))
1145 return 0;
1146
1147 if (strlcat(buf, " ", size) >= size ||
1148 strlcat(buf, desc, size) >= size)
1149 return -1;
1150
1151 aptr = SLIST_FIRST(alist)((alist)->slh_first);
1152 if (SLIST_NEXT(aptr, next)((aptr)->next.sle_next) == NULL((void*)0)) {
1153 /* single attribute, no parenthesis */
1154 if (strlcat(buf, " ", size) >= size ||
1155 strlcat(buf, ATTR_NAME(aptr->attr_type)((aptr->attr_type)->names ? (((aptr->attr_type)->
names)->slh_first)->name : (aptr->attr_type)->oid
)
, size) >= size)
1156 return -1;
1157 } else {
1158 if (strlcat(buf, " ( ", size) >= size)
1159 return -1;
1160 SLIST_FOREACH(aptr, alist, next)for((aptr) = ((alist)->slh_first); (aptr) != ((void*)0); (
aptr) = ((aptr)->next.sle_next))
{
1161 if (strlcat(buf, ATTR_NAME(aptr->attr_type)((aptr->attr_type)->names ? (((aptr->attr_type)->
names)->slh_first)->name : (aptr->attr_type)->oid
)
,
1162 size) >= size ||
1163 strlcat(buf, " ", size) >= size)
1164 return -1;
1165 if (SLIST_NEXT(aptr, next)((aptr)->next.sle_next) != NULL((void*)0) &&
1166 strlcat(buf, "$ ", size) >= size)
1167 return -1;
1168 }
1169 if (strlcat(buf, ")", size) >= size)
1170 return -1;
1171 }
1172
1173 return 0;
1174}
1175
1176static int
1177schema_dump_objlist(const char *desc, struct obj_list *olist,
1178 char *buf, size_t size)
1179{
1180 struct obj_ptr *optr;
1181
1182 if (olist == NULL((void*)0) || SLIST_EMPTY(olist)(((olist)->slh_first) == ((void*)0)))
1183 return 0;
1184
1185 if (strlcat(buf, " ", size) >= size ||
1186 strlcat(buf, desc, size) >= size)
1187 return -1;
1188
1189 optr = SLIST_FIRST(olist)((olist)->slh_first);
1190 if (SLIST_NEXT(optr, next)((optr)->next.sle_next) == NULL((void*)0)) {
1191 /* single attribute, no parenthesis */
1192 if (strlcat(buf, " ", size) >= size ||
1193 strlcat(buf, OBJ_NAME(optr->object)((optr->object)->names ? (((optr->object)->names)
->slh_first)->name : (optr->object)->oid)
, size) >= size)
1194 return -1;
1195 } else {
1196 if (strlcat(buf, " ( ", size) >= size)
1197 return -1;
1198 SLIST_FOREACH(optr, olist, next)for((optr) = ((olist)->slh_first); (optr) != ((void*)0); (
optr) = ((optr)->next.sle_next))
{
1199 if (strlcat(buf, OBJ_NAME(optr->object)((optr->object)->names ? (((optr->object)->names)
->slh_first)->name : (optr->object)->oid)
, size) >= size ||
1200 strlcat(buf, " ", size) >= size)
1201 return -1;
1202 if (SLIST_NEXT(optr, next)((optr)->next.sle_next) != NULL((void*)0) &&
1203 strlcat(buf, "$ ", size) >= size)
1204 return -1;
1205 }
1206 if (strlcat(buf, ")", size) >= size)
1207 return -1;
1208 }
1209
1210 return 0;
1211}
1212
1213int
1214schema_dump_object(struct object *obj, char *buf, size_t size)
1215{
1216 if (strlcpy(buf, "( ", size) >= size ||
1217 strlcat(buf, obj->oid, size) >= size)
1218 return -1;
1219
1220 if (schema_dump_names("NAME", obj->names, buf, size) != 0)
1221 return -1;
1222
1223 if (obj->desc != NULL((void*)0))
1224 if (strlcat(buf, " DESC '", size) >= size ||
1225 strlcat(buf, obj->desc, size) >= size ||
1226 strlcat(buf, "'", size) >= size)
1227 return -1;
1228
1229 switch (obj->kind) {
1230 case KIND_STRUCTURAL:
1231 if (strlcat(buf, " STRUCTURAL", size) >= size)
1232 return -1;
1233 break;
1234 case KIND_ABSTRACT:
1235 if (strlcat(buf, " ABSTRACT", size) >= size)
1236 return -1;
1237 break;
1238 case KIND_AUXILIARY:
1239 if (strlcat(buf, " AUXILIARY", size) >= size)
1240 return -1;
1241 break;
1242 }
1243
1244 if (schema_dump_objlist("SUP", obj->sup, buf, size) != 0)
1245 return -1;
1246
1247 if (obj->obsolete && strlcat(buf, " OBSOLETE", size) >= size)
1248 return -1;
1249
1250 if (schema_dump_attrlist("MUST", obj->must, buf, size) != 0)
1251 return -1;
1252
1253 if (schema_dump_attrlist("MAY", obj->may, buf, size) != 0)
1254 return -1;
1255
1256 if (strlcat(buf, " )", size) >= size)
1257 return -1;
1258
1259 return 0;
1260}
1261
1262int
1263schema_dump_attribute(struct attr_type *at, char *buf, size_t size)
1264{
1265 if (strlcpy(buf, "( ", size) >= size ||
1266 strlcat(buf, at->oid, size) >= size)
1267 return -1;
1268
1269 if (schema_dump_names("NAME", at->names, buf, size) != 0)
1270 return -1;
1271
1272 if (at->desc != NULL((void*)0))
1273 if (strlcat(buf, " DESC '", size) >= size ||
1274 strlcat(buf, at->desc, size) >= size ||
1275 strlcat(buf, "'", size) >= size)
1276 return -1;
1277
1278 if (at->obsolete && strlcat(buf, " OBSOLETE", size) >= size)
1279 return -1;
1280
1281 if (at->sup != NULL((void*)0))
1282 if (strlcat(buf, " SUP ", size) >= size ||
1283 strlcat(buf, ATTR_NAME(at->sup)((at->sup)->names ? (((at->sup)->names)->slh_first
)->name : (at->sup)->oid)
, size) >= size)
1284 return -1;
1285
1286 if (at->equality != NULL((void*)0))
1287 if (strlcat(buf, " EQUALITY ", size) >= size ||
1288 strlcat(buf, at->equality->name, size) >= size)
1289 return -1;
1290
1291 if (at->ordering != NULL((void*)0))
1292 if (strlcat(buf, " ORDERING ", size) >= size ||
1293 strlcat(buf, at->ordering->name, size) >= size)
1294 return -1;
1295
1296 if (at->substr != NULL((void*)0))
1297 if (strlcat(buf, " SUBSTR ", size) >= size ||
1298 strlcat(buf, at->substr->name, size) >= size)
1299 return -1;
1300
1301 if (at->syntax != NULL((void*)0))
1302 if (strlcat(buf, " SYNTAX ", size) >= size ||
1303 strlcat(buf, at->syntax->oid, size) >= size)
1304 return -1;
1305
1306 if (at->single && strlcat(buf, " SINGLE-VALUE", size) >= size)
1307 return -1;
1308
1309 if (at->collective && strlcat(buf, " COLLECTIVE", size) >= size)
1310 return -1;
1311
1312 if (at->immutable && strlcat(buf, " NO-USER-MODIFICATION", size) >= size)
1313 return -1;
1314
1315 switch (at->usage) {
1316 case USAGE_USER_APP:
1317 /* User application usage is the default. */
1318 break;
1319 case USAGE_DIR_OP:
1320 if (strlcat(buf, " USAGE directoryOperation", size) >= size)
1321 return -1;
1322 break;
1323 case USAGE_DIST_OP:
1324 if (strlcat(buf, " USAGE distributedOperation", size) >= size)
1325 return -1;
1326 break;
1327 case USAGE_DSA_OP:
1328 if (strlcat(buf, " USAGE dSAOperation", size) >= size)
1329 return -1;
1330 break;
1331 }
1332
1333 if (strlcat(buf, " )", size) >= size)
1334 return -1;
1335
1336 return 0;
1337}
1338
1339int
1340schema_dump_match_rule(struct match_rule *mr, char *buf, size_t size)
1341{
1342 if (strlcpy(buf, "( ", size) >= size ||
1343 strlcat(buf, mr->oid, size) >= size ||
1344 strlcat(buf, " NAME '", size) >= size ||
1345 strlcat(buf, mr->name, size) >= size ||
1346 strlcat(buf, "' SYNTAX ", size) >= size ||
1347 strlcat(buf, mr->syntax_oid, size) >= size ||
1348 strlcat(buf, " )", size) >= size)
1349 return -1;
1350
1351 return 0;
1352}
1353