7 /* dictionary manager interface to NetInfo
9 /* #include <dict_ni.h>
11 /* DICT *dict_ni_open(path, dummy, dict_flags)
16 /* dict_ni_open() `opens' the named NetInfo database. The result is
17 /* a pointer to a structure that can be used to access the dictionary
18 /* using the generic methods documented in dict_open(3).
20 /* dict_ni_register() returns 0 in case of success, -1 in case
22 /* Fatal errors: NetInfo errors, out of memory.
24 /* dict(3) generic dictionary manager
25 /* netinfo(3N) data base subroutines
27 /* Pieter Schoenmakers
28 /* Eindhoven University of Technology
41 #include <netinfo/ni.h>
43 /* Utility library. */
49 #include "stringops.h"
52 DICT dict
; /* my super */
53 char *path
; /* directory path */
57 * We'd like other possibilities, but that is not possible in the current
58 * dictionary setup... An example of a different setup: use `members' for
59 * multi-valued lookups (to be compatible with /aliases), and `value' for
60 * single-valued tables.
62 #define NETINFO_PROP_KEY "name"
63 #define NETINFO_PROP_VALUE "members"
64 #define NETINFO_VALUE_SEP ","
66 #define NETINFO_MAX_DOMAIN_DEPTH 100
68 /* Hard worker doing lookups. Returned value is statically allocated and
70 static const char *dict_ni_do_lookup(char *path
, char *key_prop
,
71 const char *key_value
, char *val_prop
)
73 unsigned int result_cap
= 0;
74 static char *result
= 0;
88 msg_info("ni_lookup %s %s=%s", path
, key_prop
, key_value
);
90 r
= ni_open(NULL
, ".", &domain
);
92 msg_warn("ni_open `.': %d", r
);
95 query
= alloca(strlen(path
) + strlen(key_prop
) + 3 + strlen(key_value
));
96 sprintf(query
, "%s/%s=%s", path
, key_prop
, key_value
);
101 * What does it _mean_ if we find the directory but not the value?
103 if (ni_pathsearch(domain
, &dir
, query
) == NI_OK
104 && ni_lookupprop(domain
, &dir
, val_prop
, &values
) == NI_OK
)
105 if (values
.ni_namelist_len
<= 0)
106 ni_namelist_free(&values
);
108 unsigned int i
, l
, n
;
110 for (i
= l
= 0; i
< values
.ni_namelist_len
; i
++)
111 l
+= 1 + strlen(values
.ni_namelist_val
[i
]);
112 if (result_cap
< l
) {
115 result_cap
= l
+ 100;
116 result
= mymalloc(result_cap
);
118 for (i
= l
= 0; i
< values
.ni_namelist_len
; i
++) {
119 n
= strlen(values
.ni_namelist_val
[i
]);
120 memcpy(result
+ l
, values
.ni_namelist_val
[i
], n
);
122 if (i
< values
.ni_namelist_len
- 1)
130 if (++depth
>= NETINFO_MAX_DOMAIN_DEPTH
) {
131 msg_warn("ni_open: domain depth limit");
134 r
= ni_open(domain
, "..", &next_domain
);
137 msg_warn("ni_open `..': %d", r
);
141 domain
= next_domain
;
149 /* dict_ni_lookup - find table entry */
151 static const char *dict_ni_lookup(DICT
*dict
, const char *key
)
153 DICT_NI
*d
= (DICT_NI
*) dict
;
156 * Optionally fold the key.
158 if (dict
->flags
& DICT_FLAG_FOLD_FIX
) {
159 if (dict
->fold_buf
== 0)
160 dict
->fold_buf
= vstring_alloc(10);
161 vstring_strcpy(dict
->fold_buf
, key
);
162 key
= lowercase(vstring_str(dict
->fold_buf
));
164 return dict_ni_do_lookup(d
->dict
.name
, NETINFO_PROP_KEY
,
165 key
, NETINFO_PROP_VALUE
);
168 /* dict_ni_close - disassociate from NetInfo map */
170 static void dict_ni_close(DICT
*dict
)
172 DICT_NI
*d
= (DICT_NI
*) dict
;
175 vstring_free(dict
->fold_buf
);
179 /* dict_ni_open - create association with NetInfo map */
181 DICT
*dict_ni_open(const char *path
, int unused_flags
, int dict_flags
)
183 DICT_NI
*d
= (void *) dict_alloc(DICT_TYPE_NETINFO
, path
, sizeof(*d
));
185 d
->dict
.lookup
= dict_ni_lookup
;
186 d
->dict
.close
= dict_ni_close
;
187 d
->dict
.flags
= dict_flags
| DICT_FLAG_FIXED
;
188 if (dict_flags
& DICT_FLAG_FOLD_FIX
)
189 d
->dict
.fold_buf
= vstring_alloc(10);
191 return (DICT_DEBUG (&d
->dict
));