1/* $NetBSD$ */ 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 51typedef 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. */ 70static 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 150static 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 171static 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 182DICT *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