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