1 /* $NetBSD: dict_ni.c,v 1.1.1.2 2013/01/02 18:59:12 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. */ 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 = alloca(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 144 return return_val; 145 } 146 147 /* dict_ni_lookup - find table entry */ 148 149 static const char *dict_ni_lookup(DICT *dict, const char *key) 150 { 151 DICT_NI *d = (DICT_NI *) dict; 152 153 dict->error = 0; 154 155 /* 156 * Optionally fold the key. 157 */ 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)); 163 } 164 return dict_ni_do_lookup(d->dict.name, NETINFO_PROP_KEY, 165 key, NETINFO_PROP_VALUE); 166 } 167 168 /* dict_ni_close - disassociate from NetInfo map */ 169 170 static void dict_ni_close(DICT *dict) 171 { 172 DICT_NI *d = (DICT_NI *) dict; 173 174 if (dict->fold_buf) 175 vstring_free(dict->fold_buf); 176 dict_free(dict); 177 } 178 179 /* dict_ni_open - create association with NetInfo map */ 180 181 DICT *dict_ni_open(const char *path, int unused_flags, int dict_flags) 182 { 183 DICT_NI *d = (void *) dict_alloc(DICT_TYPE_NETINFO, path, sizeof(*d)); 184 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); 190 d->dict.owner.status = DICT_OWNER_TRUSTED; 191 192 return (DICT_DEBUG (&d->dict)); 193 } 194 195 #endif 196