xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_ni.c (revision 16d67a18c4cbb2d3cb426b01120f4938ca6dbbf9)
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