1 /* $NetBSD: dict_ni.c,v 1.1.1.1 2009/06/23 10:08:59 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 dict_errno = 0; 86 87 if (msg_verbose) 88 msg_info("ni_lookup %s %s=%s", path, key_prop, key_value); 89 90 r = ni_open(NULL, ".", &domain); 91 if (r != NI_OK) { 92 msg_warn("ni_open `.': %d", r); 93 return NULL; 94 } 95 query = alloca(strlen(path) + strlen(key_prop) + 3 + strlen(key_value)); 96 sprintf(query, "%s/%s=%s", path, key_prop, key_value); 97 98 for (;;) { 99 100 /* 101 * What does it _mean_ if we find the directory but not the value? 102 */ 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; 109 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); 117 } 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++] = ','; 124 } 125 result[l] = '\0'; 126 return_val = result; 127 break; 128 } 129 130 if (++depth >= NETINFO_MAX_DOMAIN_DEPTH) { 131 msg_warn("ni_open: domain depth limit"); 132 break; 133 } 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; 139 } 140 ni_free(domain); 141 domain = next_domain; 142 } 143 144 ni_free(domain); 145 146 return return_val; 147 } 148 149 /* dict_ni_lookup - find table entry */ 150 151 static const char *dict_ni_lookup(DICT *dict, const char *key) 152 { 153 DICT_NI *d = (DICT_NI *) dict; 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 191 return (DICT_DEBUG (&d->dict)); 192 } 193 194 #endif 195