No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / dict_ni.c
blob1ac34de14c7fbad3b9ff91fdadf76c5fecb87828
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* dict_ni 3
6 /* SUMMARY
7 /* dictionary manager interface to NetInfo
8 /* SYNOPSIS
9 /* #include <dict_ni.h>
11 /* DICT *dict_ni_open(path, dummy, dict_flags)
12 /* char *path;
13 /* int dummy;
14 /* int dict_flags;
15 /* DESCRIPTION
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).
19 /* DIAGNOSTICS
20 /* dict_ni_register() returns 0 in case of success, -1 in case
21 /* of problems.
22 /* Fatal errors: NetInfo errors, out of memory.
23 /* SEE ALSO
24 /* dict(3) generic dictionary manager
25 /* netinfo(3N) data base subroutines
26 /* AUTHOR(S)
27 /* Pieter Schoenmakers
28 /* Eindhoven University of Technology
29 /* P.O. Box 513
30 /* 5600 MB Eindhoven
31 /* The Netherlands
32 /*--*/
34 #include "sys_defs.h"
36 #ifdef HAS_NETINFO
38 /* System library. */
40 #include <stdio.h>
41 #include <netinfo/ni.h>
43 /* Utility library. */
45 #include "dict.h"
46 #include "dict_ni.h"
47 #include "msg.h"
48 #include "mymalloc.h"
49 #include "stringops.h"
51 typedef struct {
52 DICT dict; /* my super */
53 char *path; /* directory path */
54 } DICT_NI;
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
69 reused each call. */
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;
76 char *return_val = 0;
77 ni_namelist values;
78 int depth = 0;
79 void *domain;
80 void *next_domain;
81 char *query;
82 ni_status r;
83 ni_id dir;
85 dict_errno = 0;
87 if (msg_verbose)
88 msg_info("ni_lookup %s %s=%s", path, key_prop, key_value);
90 r = ni_open(NULL, ".", &domain);
91 if (r != NI_OK) {
92 msg_warn("ni_open `.': %d", r);
93 return NULL;
95 query = alloca(strlen(path) + strlen(key_prop) + 3 + strlen(key_value));
96 sprintf(query, "%s/%s=%s", path, key_prop, key_value);
98 for (;;) {
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);
107 else {
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) {
113 if (result)
114 myfree(result);
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);
121 l += n;
122 if (i < values.ni_namelist_len - 1)
123 result[l++] = ',';
125 result[l] = '\0';
126 return_val = result;
127 break;
130 if (++depth >= NETINFO_MAX_DOMAIN_DEPTH) {
131 msg_warn("ni_open: domain depth limit");
132 break;
134 r = ni_open(domain, "..", &next_domain);
135 if (r != NI_OK) {
136 if (r != NI_FAILED)
137 msg_warn("ni_open `..': %d", r);
138 break;
140 ni_free(domain);
141 domain = next_domain;
144 ni_free(domain);
146 return return_val;
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;
174 if (dict->fold_buf)
175 vstring_free(dict->fold_buf);
176 dict_free(dict);
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));
194 #endif