1 /* $NetBSD: dict_ni.c,v 1.1.1.3 2014/07/06 19:27:58 tron Exp $ */
2
3 /*++
4 /* NAME
5 /* dict_ni 3
6 /* SUMMARY
7 /* dictionary manager interface to NetInfo
8 /* SYNOPSIS
9 /* #include <dict_ni.h>
10 /*
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 /*--*/
33
34 #include "sys_defs.h"
35
36 #ifdef HAS_NETINFO
37
38 /* System library. */
39
40 #include <stdio.h>
41 #include <netinfo/ni.h>
42
43 /* Utility library. */
44
45 #include "dict.h"
46 #include "dict_ni.h"
47 #include "msg.h"
48 #include "mymalloc.h"
49 #include "stringops.h"
50
51 typedef struct {
52 DICT dict; /* my super */
53 char *path; /* directory path */
54 } DICT_NI;
55
56 /*
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.
61 */
62 #define NETINFO_PROP_KEY "name"
63 #define NETINFO_PROP_VALUE "members"
64 #define NETINFO_VALUE_SEP ","
65
66 #define NETINFO_MAX_DOMAIN_DEPTH 100
67
68 /* Hard worker doing lookups. Returned value is statically allocated and
69 reused each call. */
dict_ni_do_lookup(char * path,char * key_prop,const char * key_value,char * val_prop)70 static const char *dict_ni_do_lookup(char *path, char *key_prop,
71 const char *key_value, char *val_prop)
72 {
73 unsigned int result_cap = 0;
74 static char *result = 0;
75
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;
84
85 if (msg_verbose)
86 msg_info("ni_lookup %s %s=%s", path, key_prop, key_value);
87
88 r = ni_open(NULL, ".", &domain);
89 if (r != NI_OK) {
90 msg_warn("ni_open `.': %d", r);
91 return NULL;
92 }
93 query = mymalloc(strlen(path) + strlen(key_prop) + 3 + strlen(key_value));
94 sprintf(query, "%s/%s=%s", path, key_prop, key_value);
95
96 for (;;) {
97
98 /*
99 * What does it _mean_ if we find the directory but not the value?
100 */
101 if (ni_pathsearch(domain, &dir, query) == NI_OK
102 && ni_lookupprop(domain, &dir, val_prop, &values) == NI_OK)
103 if (values.ni_namelist_len <= 0)
104 ni_namelist_free(&values);
105 else {
106 unsigned int i, l, n;
107
108 for (i = l = 0; i < values.ni_namelist_len; i++)
109 l += 1 + strlen(values.ni_namelist_val[i]);
110 if (result_cap < l) {
111 if (result)
112 myfree(result);
113 result_cap = l + 100;
114 result = mymalloc(result_cap);
115 }
116 for (i = l = 0; i < values.ni_namelist_len; i++) {
117 n = strlen(values.ni_namelist_val[i]);
118 memcpy(result + l, values.ni_namelist_val[i], n);
119 l += n;
120 if (i < values.ni_namelist_len - 1)
121 result[l++] = ',';
122 }
123 result[l] = '\0';
124 return_val = result;
125 break;
126 }
127
128 if (++depth >= NETINFO_MAX_DOMAIN_DEPTH) {
129 msg_warn("ni_open: domain depth limit");
130 break;
131 }
132 r = ni_open(domain, "..", &next_domain);
133 if (r != NI_OK) {
134 if (r != NI_FAILED)
135 msg_warn("ni_open `..': %d", r);
136 break;
137 }
138 ni_free(domain);
139 domain = next_domain;
140 }
141
142 ni_free(domain);
143 myfree(query);
144
145 return return_val;
146 }
147
148 /* dict_ni_lookup - find table entry */
149
dict_ni_lookup(DICT * dict,const char * key)150 static const char *dict_ni_lookup(DICT *dict, const char *key)
151 {
152 DICT_NI *d = (DICT_NI *) dict;
153
154 dict->error = 0;
155
156 /*
157 * Optionally fold the key.
158 */
159 if (dict->flags & DICT_FLAG_FOLD_FIX) {
160 if (dict->fold_buf == 0)
161 dict->fold_buf = vstring_alloc(10);
162 vstring_strcpy(dict->fold_buf, key);
163 key = lowercase(vstring_str(dict->fold_buf));
164 }
165 return dict_ni_do_lookup(d->dict.name, NETINFO_PROP_KEY,
166 key, NETINFO_PROP_VALUE);
167 }
168
169 /* dict_ni_close - disassociate from NetInfo map */
170
dict_ni_close(DICT * dict)171 static void dict_ni_close(DICT *dict)
172 {
173 DICT_NI *d = (DICT_NI *) dict;
174
175 if (dict->fold_buf)
176 vstring_free(dict->fold_buf);
177 dict_free(dict);
178 }
179
180 /* dict_ni_open - create association with NetInfo map */
181
dict_ni_open(const char * path,int unused_flags,int dict_flags)182 DICT *dict_ni_open(const char *path, int unused_flags, int dict_flags)
183 {
184 DICT_NI *d = (void *) dict_alloc(DICT_TYPE_NETINFO, path, sizeof(*d));
185
186 d->dict.lookup = dict_ni_lookup;
187 d->dict.close = dict_ni_close;
188 d->dict.flags = dict_flags | DICT_FLAG_FIXED;
189 if (dict_flags & DICT_FLAG_FOLD_FIX)
190 d->dict.fold_buf = vstring_alloc(10);
191 d->dict.owner.status = DICT_OWNER_TRUSTED;
192
193 return (DICT_DEBUG (&d->dict));
194 }
195
196 #endif
197