1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 7*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 8*7c478bd9Sstevel@tonic-gate */ 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: niprop.c,v 1.6 2001/09/04 22:41:27 ca Exp $") 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #if NETINFO 16*7c478bd9Sstevel@tonic-gate #include <ctype.h> 17*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 18*7c478bd9Sstevel@tonic-gate #include <sm/io.h> 19*7c478bd9Sstevel@tonic-gate #include <sm/assert.h> 20*7c478bd9Sstevel@tonic-gate #include <sm/debug.h> 21*7c478bd9Sstevel@tonic-gate #include <sm/string.h> 22*7c478bd9Sstevel@tonic-gate #include <sm/varargs.h> 23*7c478bd9Sstevel@tonic-gate #include <sm/heap.h> 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate ** NI_PROPVAL -- NetInfo property value lookup routine 27*7c478bd9Sstevel@tonic-gate ** 28*7c478bd9Sstevel@tonic-gate ** Parameters: 29*7c478bd9Sstevel@tonic-gate ** keydir -- the NetInfo directory name in which to search 30*7c478bd9Sstevel@tonic-gate ** for the key. 31*7c478bd9Sstevel@tonic-gate ** keyprop -- the name of the property in which to find the 32*7c478bd9Sstevel@tonic-gate ** property we are interested. Defaults to "name". 33*7c478bd9Sstevel@tonic-gate ** keyval -- the value for which we are really searching. 34*7c478bd9Sstevel@tonic-gate ** valprop -- the property name for the value in which we 35*7c478bd9Sstevel@tonic-gate ** are interested. 36*7c478bd9Sstevel@tonic-gate ** sepchar -- if non-nil, this can be multiple-valued, and 37*7c478bd9Sstevel@tonic-gate ** we should return a string separated by this 38*7c478bd9Sstevel@tonic-gate ** character. 39*7c478bd9Sstevel@tonic-gate ** 40*7c478bd9Sstevel@tonic-gate ** Returns: 41*7c478bd9Sstevel@tonic-gate ** NULL -- if: 42*7c478bd9Sstevel@tonic-gate ** 1. the directory is not found 43*7c478bd9Sstevel@tonic-gate ** 2. the property name is not found 44*7c478bd9Sstevel@tonic-gate ** 3. the property contains multiple values 45*7c478bd9Sstevel@tonic-gate ** 4. some error occurred 46*7c478bd9Sstevel@tonic-gate ** else -- the value of the lookup. 47*7c478bd9Sstevel@tonic-gate ** 48*7c478bd9Sstevel@tonic-gate ** Example: 49*7c478bd9Sstevel@tonic-gate ** To search for an alias value, use: 50*7c478bd9Sstevel@tonic-gate ** ni_propval("/aliases", "name", aliasname, "members", ',') 51*7c478bd9Sstevel@tonic-gate ** 52*7c478bd9Sstevel@tonic-gate ** Notes: 53*7c478bd9Sstevel@tonic-gate ** Caller should free the return value of ni_proval 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate # include <netinfo/ni.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate # define LOCAL_NETINFO_DOMAIN "." 59*7c478bd9Sstevel@tonic-gate # define PARENT_NETINFO_DOMAIN ".." 60*7c478bd9Sstevel@tonic-gate # define MAX_NI_LEVELS 256 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate char * 63*7c478bd9Sstevel@tonic-gate ni_propval(keydir, keyprop, keyval, valprop, sepchar) 64*7c478bd9Sstevel@tonic-gate char *keydir; 65*7c478bd9Sstevel@tonic-gate char *keyprop; 66*7c478bd9Sstevel@tonic-gate char *keyval; 67*7c478bd9Sstevel@tonic-gate char *valprop; 68*7c478bd9Sstevel@tonic-gate int sepchar; 69*7c478bd9Sstevel@tonic-gate { 70*7c478bd9Sstevel@tonic-gate char *propval = NULL; 71*7c478bd9Sstevel@tonic-gate int i; 72*7c478bd9Sstevel@tonic-gate int j, alen, l; 73*7c478bd9Sstevel@tonic-gate void *ni = NULL; 74*7c478bd9Sstevel@tonic-gate void *lastni = NULL; 75*7c478bd9Sstevel@tonic-gate ni_status nis; 76*7c478bd9Sstevel@tonic-gate ni_id nid; 77*7c478bd9Sstevel@tonic-gate ni_namelist ninl; 78*7c478bd9Sstevel@tonic-gate register char *p; 79*7c478bd9Sstevel@tonic-gate char keybuf[1024]; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate ** Create the full key from the two parts. 83*7c478bd9Sstevel@tonic-gate ** 84*7c478bd9Sstevel@tonic-gate ** Note that directory can end with, e.g., "name=" to specify 85*7c478bd9Sstevel@tonic-gate ** an alternate search property. 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate i = strlen(keydir) + strlen(keyval) + 2; 89*7c478bd9Sstevel@tonic-gate if (keyprop != NULL) 90*7c478bd9Sstevel@tonic-gate i += strlen(keyprop) + 1; 91*7c478bd9Sstevel@tonic-gate if (i >= sizeof keybuf) 92*7c478bd9Sstevel@tonic-gate return NULL; 93*7c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/"); 94*7c478bd9Sstevel@tonic-gate if (keyprop != NULL) 95*7c478bd9Sstevel@tonic-gate { 96*7c478bd9Sstevel@tonic-gate (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate (void) sm_strlcat(keybuf, keyval, sizeof keybuf); 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #if 0 101*7c478bd9Sstevel@tonic-gate if (tTd(38, 21)) 102*7c478bd9Sstevel@tonic-gate sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 103*7c478bd9Sstevel@tonic-gate keydir, keyprop, keyval, valprop, sepchar, keybuf); 104*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate ** If the passed directory and property name are found 108*7c478bd9Sstevel@tonic-gate ** in one of netinfo domains we need to search (starting 109*7c478bd9Sstevel@tonic-gate ** from the local domain moving all the way back to the 110*7c478bd9Sstevel@tonic-gate ** root domain) set propval to the property's value 111*7c478bd9Sstevel@tonic-gate ** and return it. 112*7c478bd9Sstevel@tonic-gate */ 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate if (i == 0) 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 119*7c478bd9Sstevel@tonic-gate #if 0 120*7c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 121*7c478bd9Sstevel@tonic-gate sm_dprintf("ni_open(LOCAL) = %d\n", nis); 122*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate else 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate if (lastni != NULL) 127*7c478bd9Sstevel@tonic-gate ni_free(lastni); 128*7c478bd9Sstevel@tonic-gate lastni = ni; 129*7c478bd9Sstevel@tonic-gate nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 130*7c478bd9Sstevel@tonic-gate #if 0 131*7c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 132*7c478bd9Sstevel@tonic-gate sm_dprintf("ni_open(PARENT) = %d\n", nis); 133*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate ** Don't bother if we didn't get a handle on a 138*7c478bd9Sstevel@tonic-gate ** proper domain. This is not necessarily an error. 139*7c478bd9Sstevel@tonic-gate ** We would get a positive ni_status if, for instance 140*7c478bd9Sstevel@tonic-gate ** we never found the directory or property and tried 141*7c478bd9Sstevel@tonic-gate ** to open the parent of the root domain! 142*7c478bd9Sstevel@tonic-gate */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate if (nis != 0) 145*7c478bd9Sstevel@tonic-gate break; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate ** Find the path to the server information. 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if (ni_pathsearch(ni, &nid, keybuf) != 0) 152*7c478bd9Sstevel@tonic-gate continue; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate ** Find associated value information. 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 159*7c478bd9Sstevel@tonic-gate continue; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate #if 0 162*7c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 163*7c478bd9Sstevel@tonic-gate sm_dprintf("ni_lookupprop: len=%d\n", 164*7c478bd9Sstevel@tonic-gate ninl.ni_namelist_len); 165*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* 168*7c478bd9Sstevel@tonic-gate ** See if we have an acceptable number of values. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate if (ninl.ni_namelist_len <= 0) 172*7c478bd9Sstevel@tonic-gate continue; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate if (sepchar == '\0' && ninl.ni_namelist_len > 1) 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate ni_namelist_free(&ninl); 177*7c478bd9Sstevel@tonic-gate continue; 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate ** Calculate number of bytes needed and build result 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate alen = 1; 185*7c478bd9Sstevel@tonic-gate for (j = 0; j < ninl.ni_namelist_len; j++) 186*7c478bd9Sstevel@tonic-gate alen += strlen(ninl.ni_namelist_val[j]) + 1; 187*7c478bd9Sstevel@tonic-gate propval = p = sm_malloc(alen); 188*7c478bd9Sstevel@tonic-gate if (propval == NULL) 189*7c478bd9Sstevel@tonic-gate goto cleanup; 190*7c478bd9Sstevel@tonic-gate for (j = 0; j < ninl.ni_namelist_len; j++) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen); 193*7c478bd9Sstevel@tonic-gate l = strlen(p); 194*7c478bd9Sstevel@tonic-gate p += l; 195*7c478bd9Sstevel@tonic-gate *p++ = sepchar; 196*7c478bd9Sstevel@tonic-gate alen -= l + 1; 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate *--p = '\0'; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate ni_namelist_free(&ninl); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate cleanup: 204*7c478bd9Sstevel@tonic-gate if (ni != NULL) 205*7c478bd9Sstevel@tonic-gate ni_free(ni); 206*7c478bd9Sstevel@tonic-gate if (lastni != NULL && ni != lastni) 207*7c478bd9Sstevel@tonic-gate ni_free(lastni); 208*7c478bd9Sstevel@tonic-gate #if 0 209*7c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 210*7c478bd9Sstevel@tonic-gate sm_dprintf("ni_propval returns: '%s'\n", propval); 211*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate return propval; 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 216