1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <strings.h> 30*7c478bd9Sstevel@tonic-gate #include <string.h> 31*7c478bd9Sstevel@tonic-gate #include <lber.h> 32*7c478bd9Sstevel@tonic-gate #include <ldap.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "db_item_c.h" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include "ldap_util.h" 39*7c478bd9Sstevel@tonic-gate #include "ldap_structs.h" 40*7c478bd9Sstevel@tonic-gate #include "ldap_val.h" 41*7c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h" 42*7c478bd9Sstevel@tonic-gate #include "ldap_op.h" 43*7c478bd9Sstevel@tonic-gate #include "ldap_nisdbquery.h" 44*7c478bd9Sstevel@tonic-gate #include "ldap_attr.h" 45*7c478bd9Sstevel@tonic-gate #include "ldap_nisplus.h" 46*7c478bd9Sstevel@tonic-gate #include "ldap_xdr.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate item * 50*7c478bd9Sstevel@tonic-gate buildItem(int len, void *value) { 51*7c478bd9Sstevel@tonic-gate char *myself = "buildItem"; 52*7c478bd9Sstevel@tonic-gate item *i = am(myself, sizeof (*i)); 53*7c478bd9Sstevel@tonic-gate int mlen = len; 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate if (i == 0) 56*7c478bd9Sstevel@tonic-gate return (0); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * To this function, a NULL value, or a length less than or equal 60*7c478bd9Sstevel@tonic-gate * zero means an item with no value. Hence, buildItem(0, 0) is 61*7c478bd9Sstevel@tonic-gate * _not_ the right way to create index_value == 0 to indicate 62*7c478bd9Sstevel@tonic-gate * deletion. 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate if (value == 0 || len <= 0) { 65*7c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = 0; 66*7c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = 0; 67*7c478bd9Sstevel@tonic-gate return (i); 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * NIS+ usually stores the terminating NUL for strings, so we add 72*7c478bd9Sstevel@tonic-gate * it here just in case. This means we usually waste a byte for 73*7c478bd9Sstevel@tonic-gate * binary column values... 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate if (len > 0 && ((char *)value)[len-1] != '\0') 76*7c478bd9Sstevel@tonic-gate mlen++; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = len; 79*7c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = am(myself, mlen); 80*7c478bd9Sstevel@tonic-gate if (mlen > 0 && i->itemvalue.itemvalue_val == 0) { 81*7c478bd9Sstevel@tonic-gate free(i); 82*7c478bd9Sstevel@tonic-gate return (0); 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate memcpy(i->itemvalue.itemvalue_val, value, len); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate return (i); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate void 90*7c478bd9Sstevel@tonic-gate freeItem(item *i) { 91*7c478bd9Sstevel@tonic-gate if (i != 0) { 92*7c478bd9Sstevel@tonic-gate sfree(i->itemvalue.itemvalue_val); 93*7c478bd9Sstevel@tonic-gate free(i); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate void 98*7c478bd9Sstevel@tonic-gate freeQcomp(db_qcomp *qc, int doFree) { 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if (qc == 0) 101*7c478bd9Sstevel@tonic-gate return; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate freeItem(qc->index_value); 104*7c478bd9Sstevel@tonic-gate if (doFree) 105*7c478bd9Sstevel@tonic-gate free(qc); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate db_query * 109*7c478bd9Sstevel@tonic-gate buildQuery(int num_components, db_qcomp *components) { 110*7c478bd9Sstevel@tonic-gate char *myself = "buildQuery"; 111*7c478bd9Sstevel@tonic-gate db_query *q = am(myself, sizeof (*q)); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (q == 0) 114*7c478bd9Sstevel@tonic-gate return (0); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate q->components.components_len = num_components; 117*7c478bd9Sstevel@tonic-gate q->components.components_val = components; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate return (q); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * Clone a db_query. The 'numComps' parameter can be used to specify 124*7c478bd9Sstevel@tonic-gate * the number of db_qcomp's to allocate (in the 'components.components_val' 125*7c478bd9Sstevel@tonic-gate * array), if 'components.components_len' hasn't yet reached its expected 126*7c478bd9Sstevel@tonic-gate * maximum value. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate db_query * 129*7c478bd9Sstevel@tonic-gate cloneQuery(db_query *old, int numComps) { 130*7c478bd9Sstevel@tonic-gate db_query *new; 131*7c478bd9Sstevel@tonic-gate int i; 132*7c478bd9Sstevel@tonic-gate char *myself = "cloneQuery"; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate if (old == 0) 135*7c478bd9Sstevel@tonic-gate return (0); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate new = am(myself, sizeof (*new)); 138*7c478bd9Sstevel@tonic-gate if (new == 0) 139*7c478bd9Sstevel@tonic-gate return (0); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate if (old->components.components_len > numComps) 142*7c478bd9Sstevel@tonic-gate numComps = old->components.components_len; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate new->components.components_val = am(myself, 145*7c478bd9Sstevel@tonic-gate sizeof (new->components.components_val[0]) * 146*7c478bd9Sstevel@tonic-gate numComps); 147*7c478bd9Sstevel@tonic-gate if (numComps > 0 && new->components.components_val == 0) { 148*7c478bd9Sstevel@tonic-gate free(new); 149*7c478bd9Sstevel@tonic-gate return (0); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate for (i = 0; i < old->components.components_len; i++) { 153*7c478bd9Sstevel@tonic-gate item *it; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (old->components.components_val[i].index_value == 0) { 156*7c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = 0; 157*7c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index = 158*7c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index; 159*7c478bd9Sstevel@tonic-gate continue; 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate it = buildItem(old->components.components_val[i].index_value-> 163*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len, 164*7c478bd9Sstevel@tonic-gate old->components.components_val[i].index_value-> 165*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (it == 0) { 168*7c478bd9Sstevel@tonic-gate new->components.components_len = i + 1; 169*7c478bd9Sstevel@tonic-gate freeQuery(new); 170*7c478bd9Sstevel@tonic-gate return (0); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = it; 174*7c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index = 175*7c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index; 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate new->components.components_len = old->components.components_len; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate return (new); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate void 184*7c478bd9Sstevel@tonic-gate freeQuery(db_query *q) { 185*7c478bd9Sstevel@tonic-gate int i; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if (q == 0) 188*7c478bd9Sstevel@tonic-gate return; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 191*7c478bd9Sstevel@tonic-gate freeItem(q->components.components_val[i].index_value); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate sfree(q->components.components_val); 195*7c478bd9Sstevel@tonic-gate sfree(q); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate void 199*7c478bd9Sstevel@tonic-gate freeQueries(db_query **q, int numQ) { 200*7c478bd9Sstevel@tonic-gate int i; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (q == 0) 203*7c478bd9Sstevel@tonic-gate return; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate for (i = 0; i < numQ; i++) 206*7c478bd9Sstevel@tonic-gate freeQuery(q[i]); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate sfree(q); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Given an array index[0..num-1] of pointers to strings of the form 213*7c478bd9Sstevel@tonic-gate * "name=value", create the corresponding db_queries. "name=" indicates 214*7c478bd9Sstevel@tonic-gate * deletion, which results in a db_query component where index_value == 0. 215*7c478bd9Sstevel@tonic-gate * 216*7c478bd9Sstevel@tonic-gate * The __nis_table_mapping_t structure is used to translate column 217*7c478bd9Sstevel@tonic-gate * names to indices. 218*7c478bd9Sstevel@tonic-gate * 219*7c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, the searchable columns from the 'index' 220*7c478bd9Sstevel@tonic-gate * name/value pairs are used to retrieve copies of the corresponding NIS+ 221*7c478bd9Sstevel@tonic-gate * entries, and '*rvP' is initialized with the current entry values 222*7c478bd9Sstevel@tonic-gate * and object attributes. Names/values supplied in 'index' override 223*7c478bd9Sstevel@tonic-gate * those from existing NIS+ entries. 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate db_query ** 226*7c478bd9Sstevel@tonic-gate createQuery(int num, char **index, __nis_table_mapping_t *t, 227*7c478bd9Sstevel@tonic-gate __nis_rule_value_t **rvP, int *numVals) { 228*7c478bd9Sstevel@tonic-gate db_query **q; 229*7c478bd9Sstevel@tonic-gate db_qcomp *qc; 230*7c478bd9Sstevel@tonic-gate int i, j, n, a, nv, niv, stat, sinum; 231*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvq; 232*7c478bd9Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 233*7c478bd9Sstevel@tonic-gate nis_result *res = 0; 234*7c478bd9Sstevel@tonic-gate char *table = 0; 235*7c478bd9Sstevel@tonic-gate char *myself = "createQuery"; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate rvq = initRuleValue(1, 0); 238*7c478bd9Sstevel@tonic-gate if (rvq == 0) 239*7c478bd9Sstevel@tonic-gate return (0); 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate if (numVals == 0) 242*7c478bd9Sstevel@tonic-gate numVals = &nv; 243*7c478bd9Sstevel@tonic-gate *numVals = 0; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (rvP != 0) { 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Try to obtain a copy of the table object, in order to 248*7c478bd9Sstevel@tonic-gate * determine the searchable columns. A failure isn't 249*7c478bd9Sstevel@tonic-gate * necessarily fatal; we just try to compose the entire 250*7c478bd9Sstevel@tonic-gate * LDAP data from the col=val pairs. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate table = fullObjName(F, t->objName); 253*7c478bd9Sstevel@tonic-gate if (table == 0) { 254*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 255*7c478bd9Sstevel@tonic-gate "%s: Error converting \"%s\" to FQ object name", 256*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 257*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 258*7c478bd9Sstevel@tonic-gate return (0); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate stat = getNisPlusObj(table, myself, &res); 262*7c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 263*7c478bd9Sstevel@tonic-gate if (res->objects.objects_val->zo_data.zo_type != 264*7c478bd9Sstevel@tonic-gate NIS_TABLE_OBJ) { 265*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 266*7c478bd9Sstevel@tonic-gate "%s: \"%s\" isn't a table object", 267*7c478bd9Sstevel@tonic-gate myself, NIL(table)); 268*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 269*7c478bd9Sstevel@tonic-gate res = 0; 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate } else { 272*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 273*7c478bd9Sstevel@tonic-gate "%s: Unable to retrieve \"%s\" object: %s", 274*7c478bd9Sstevel@tonic-gate myself, NIL(table), ldap_err2string(stat)); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* Create a rule-value from the col=val pairs */ 279*7c478bd9Sstevel@tonic-gate for (n = 0; n < num; n++) { 280*7c478bd9Sstevel@tonic-gate char *name; 281*7c478bd9Sstevel@tonic-gate char *value; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate if ((value = strchr(index[n], '=')) == 0) { 284*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 285*7c478bd9Sstevel@tonic-gate "%s: no '=' in \"%s\"", 286*7c478bd9Sstevel@tonic-gate myself, index[n]); 287*7c478bd9Sstevel@tonic-gate continue; 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate *value = '\0'; 291*7c478bd9Sstevel@tonic-gate value++; 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate for (a = 0; a < t->numColumns; a++) { 294*7c478bd9Sstevel@tonic-gate if (strcmp(index[n], t->column[a]) == 0) { 295*7c478bd9Sstevel@tonic-gate int i, len = slen(value)+1; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* Add col=val pair to 'rvq' */ 298*7c478bd9Sstevel@tonic-gate if (addSCol2RuleValue(index[n], value, rvq)) { 299*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 300*7c478bd9Sstevel@tonic-gate sfree(table); 301*7c478bd9Sstevel@tonic-gate if (res != 0) 302*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 303*7c478bd9Sstevel@tonic-gate return (0); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate break; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate if (a >= t->numColumns) { 310*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 311*7c478bd9Sstevel@tonic-gate "%s: Ignoring unknown column \"%s\"", 312*7c478bd9Sstevel@tonic-gate myself, NIL(index[n])); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * Find out if any of the columns specified via the 'index' 318*7c478bd9Sstevel@tonic-gate * array are multi-valued. 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate for (n = 0, niv = 1; n < rvq->numColumns; n++) { 321*7c478bd9Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1) 322*7c478bd9Sstevel@tonic-gate niv *= rvq->colVal[n].numVals; 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * Generate a NIS+ query, provided that the following conditions 327*7c478bd9Sstevel@tonic-gate * are satisfied: 328*7c478bd9Sstevel@tonic-gate * 329*7c478bd9Sstevel@tonic-gate * We were able to get information about the table, and 330*7c478bd9Sstevel@tonic-gate * 331*7c478bd9Sstevel@tonic-gate * The col=val pairs include at least one searchable 332*7c478bd9Sstevel@tonic-gate * column, and 333*7c478bd9Sstevel@tonic-gate * 334*7c478bd9Sstevel@tonic-gate * At most one value was supplied for each searchable 335*7c478bd9Sstevel@tonic-gate * column. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate if (res != 0 && rvq->numColumns > 0) { 338*7c478bd9Sstevel@tonic-gate bp2buf(myself, &b, "["); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate for (n = 0, sinum = 0; n < rvq->numColumns; n++) { 341*7c478bd9Sstevel@tonic-gate table_obj *to = &(NIS_RES_OBJECT(res)->TA_data); 342*7c478bd9Sstevel@tonic-gate table_col *tc; 343*7c478bd9Sstevel@tonic-gate int si = -1; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate for (i = 0; i < to->ta_cols.ta_cols_len; i++) { 346*7c478bd9Sstevel@tonic-gate tc = &to->ta_cols.ta_cols_val[i]; 347*7c478bd9Sstevel@tonic-gate if (strcmp(rvq->colName[n], tc->tc_name) == 0 && 348*7c478bd9Sstevel@tonic-gate (tc->tc_flags & TA_SEARCHABLE) != 0) { 349*7c478bd9Sstevel@tonic-gate si = i; 350*7c478bd9Sstevel@tonic-gate break; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (si >= 0) { 355*7c478bd9Sstevel@tonic-gate if (rvq->colVal[n].numVals < 0) 356*7c478bd9Sstevel@tonic-gate continue; 357*7c478bd9Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1) { 358*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 359*7c478bd9Sstevel@tonic-gate "%s: Multi-valued column \"%s\" excluded from NIS+ search", 360*7c478bd9Sstevel@tonic-gate myself, rvq->colName[n]); 361*7c478bd9Sstevel@tonic-gate continue; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate if (sinum == 0) 364*7c478bd9Sstevel@tonic-gate bp2buf(myself, &b, "%s=%s", 365*7c478bd9Sstevel@tonic-gate rvq->colName[n], 366*7c478bd9Sstevel@tonic-gate rvq->colVal[n].val[0].value); 367*7c478bd9Sstevel@tonic-gate else 368*7c478bd9Sstevel@tonic-gate bp2buf(myself, &b, ",%s=%s", 369*7c478bd9Sstevel@tonic-gate rvq->colName[n], 370*7c478bd9Sstevel@tonic-gate rvq->colVal[n].val[0].value); 371*7c478bd9Sstevel@tonic-gate sinum++; 372*7c478bd9Sstevel@tonic-gate } else { 373*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 374*7c478bd9Sstevel@tonic-gate "%s: \"%s\" not searchable; not included in NIS+ query", 375*7c478bd9Sstevel@tonic-gate myself, index[n]); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate bp2buf(myself, &b, "]"); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (strcmp(b.buf, "[]") == 0) { 381*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 382*7c478bd9Sstevel@tonic-gate "%s: No searchable column specified; skipping NIS+ query", 383*7c478bd9Sstevel@tonic-gate myself); 384*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 385*7c478bd9Sstevel@tonic-gate res = 0; 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate } else if (res != 0) { 388*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 389*7c478bd9Sstevel@tonic-gate res = 0; 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* Query NIS+ */ 393*7c478bd9Sstevel@tonic-gate if (res != 0) { 394*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate bp2buf(myself, &b, "%s", table); 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 399*7c478bd9Sstevel@tonic-gate "%s: NIS+ query: %s", myself, NIL(b.buf)); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate rv = getNisPlusEntrySimple(b.buf, numVals); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate /* 404*7c478bd9Sstevel@tonic-gate * Add values from the NIS+ entry to the ones passed in by 405*7c478bd9Sstevel@tonic-gate * our caller (in the form of col=value pairs). 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate if (rv != 0 && *numVals > 1 && niv > 1) { 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Since we have both multi-valued columns in the 410*7c478bd9Sstevel@tonic-gate * 'index' array, _and_ multiple NIS+ matches, we 411*7c478bd9Sstevel@tonic-gate * don't know how to combine the two in a meaningful 412*7c478bd9Sstevel@tonic-gate * fashion. Ignore the NIS+ values, and use the 413*7c478bd9Sstevel@tonic-gate * 'index' array only. 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 416*7c478bd9Sstevel@tonic-gate "%s: At least one multi-valued input column, and multiple NIS+ matches", 417*7c478bd9Sstevel@tonic-gate myself); 418*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 419*7c478bd9Sstevel@tonic-gate "%s: Ignoring NIS+ lookup results", myself); 420*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, *numVals); 421*7c478bd9Sstevel@tonic-gate rv = 0; 422*7c478bd9Sstevel@tonic-gate *numVals = 1; 423*7c478bd9Sstevel@tonic-gate } else if (rv != 0 && *numVals > 0) { 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * Since passed-in values override those from the 426*7c478bd9Sstevel@tonic-gate * NIS+ entries, we first need to delete the passed-in 427*7c478bd9Sstevel@tonic-gate * columns from the NIS+ data, and then add the 428*7c478bd9Sstevel@tonic-gate * passed-in columns/values. 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate for (i = 0; i < rvq->numColumns; i++) { 431*7c478bd9Sstevel@tonic-gate for (n = 0; n < *numVals; n++) { 432*7c478bd9Sstevel@tonic-gate delColFromRuleValue(&rv[n], 433*7c478bd9Sstevel@tonic-gate rvq->colName[i]); 434*7c478bd9Sstevel@tonic-gate for (j = 0; j < rvq->colVal[i].numVals; 435*7c478bd9Sstevel@tonic-gate j++) { 436*7c478bd9Sstevel@tonic-gate if (addCol2RuleValue( 437*7c478bd9Sstevel@tonic-gate rvq->colVal[i].type, 438*7c478bd9Sstevel@tonic-gate rvq->colName[i], 439*7c478bd9Sstevel@tonic-gate rvq->colVal[i].val[j]. 440*7c478bd9Sstevel@tonic-gate value, 441*7c478bd9Sstevel@tonic-gate rvq->colVal[i].val[j]. 442*7c478bd9Sstevel@tonic-gate length, 443*7c478bd9Sstevel@tonic-gate &rv[n])) { 444*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 445*7c478bd9Sstevel@tonic-gate *numVals); 446*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 447*7c478bd9Sstevel@tonic-gate sfree(b.buf); 448*7c478bd9Sstevel@tonic-gate sfree(table); 449*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 450*7c478bd9Sstevel@tonic-gate return (0); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 456*7c478bd9Sstevel@tonic-gate rvq = rv; 457*7c478bd9Sstevel@tonic-gate } else { 458*7c478bd9Sstevel@tonic-gate if (rv != 0) { 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * Since we got here, '*numVals' <= 0, 461*7c478bd9Sstevel@tonic-gate * so it's unclear if it's safe to call 462*7c478bd9Sstevel@tonic-gate * freeRuleValue(). 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 465*7c478bd9Sstevel@tonic-gate "%s: getNisPlusEntrySimple() => non-NULL, but %d elements", 466*7c478bd9Sstevel@tonic-gate myself, *numVals); 467*7c478bd9Sstevel@tonic-gate } else 468*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 469*7c478bd9Sstevel@tonic-gate "%s: No NIS+ data for \"%s\"", 470*7c478bd9Sstevel@tonic-gate myself, b.buf); 471*7c478bd9Sstevel@tonic-gate *numVals = 1; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate nis_freeresult(res); 474*7c478bd9Sstevel@tonic-gate res = 0; 475*7c478bd9Sstevel@tonic-gate } else { 476*7c478bd9Sstevel@tonic-gate *numVals = 1; 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate sfree(b.buf); 480*7c478bd9Sstevel@tonic-gate sfree(table); 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if (rvq->numColumns <= 0) { 483*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 484*7c478bd9Sstevel@tonic-gate *numVals = 0; 485*7c478bd9Sstevel@tonic-gate return (0); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * If any column name was repeated in the col=val pairs (but with 490*7c478bd9Sstevel@tonic-gate * different values), 'rvq' will have one or more multi-valued 491*7c478bd9Sstevel@tonic-gate * column values. We now convert those into an array of rule-values 492*7c478bd9Sstevel@tonic-gate * where every column is single-valued. 493*7c478bd9Sstevel@tonic-gate * 494*7c478bd9Sstevel@tonic-gate * Since we want all combinations of column values, the number 495*7c478bd9Sstevel@tonic-gate * of array elements is the product of all column value counts. 496*7c478bd9Sstevel@tonic-gate * 497*7c478bd9Sstevel@tonic-gate * There are four possible combinations of 'index' and NIS+ data: 498*7c478bd9Sstevel@tonic-gate * 499*7c478bd9Sstevel@tonic-gate * (1) Only single-valued 'index' columns, and at most one NIS+ 500*7c478bd9Sstevel@tonic-gate * entry, so 'rvq' is complete, and '*numVals' == 1. 501*7c478bd9Sstevel@tonic-gate * 502*7c478bd9Sstevel@tonic-gate * (2) Single-valued 'index' columns, but multiple NIS+ entries. 503*7c478bd9Sstevel@tonic-gate * '*numVals' reflects the number of NIS+ entries, and no 504*7c478bd9Sstevel@tonic-gate * expansion of 'index' column values to array elements is 505*7c478bd9Sstevel@tonic-gate * needed. 506*7c478bd9Sstevel@tonic-gate * 507*7c478bd9Sstevel@tonic-gate * (3) At least one multi-valued 'index', and multiple NIS+ 508*7c478bd9Sstevel@tonic-gate * entries. We already rejected the NIS+ data for this case 509*7c478bd9Sstevel@tonic-gate * above, so it is in fact equivalent to case (4). 510*7c478bd9Sstevel@tonic-gate * 511*7c478bd9Sstevel@tonic-gate * (4) At least one multi-valued 'index', but at most one NIS+ 512*7c478bd9Sstevel@tonic-gate * entry. This is the case where we must expand the multi-valued 513*7c478bd9Sstevel@tonic-gate * columns to multiple array elements. 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate if (niv > 1 && *numVals == 1) { 516*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv; 517*7c478bd9Sstevel@tonic-gate int repeat; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * By using initRuleValue() to create 'rv', and make each 521*7c478bd9Sstevel@tonic-gate * element a clone of 'rvq', we save a lot of code. The 522*7c478bd9Sstevel@tonic-gate * down side is that 'rv' only really needs one element 523*7c478bd9Sstevel@tonic-gate * for each rv[].colVal[].val array, but we know that at 524*7c478bd9Sstevel@tonic-gate * least one rvq->colVal[].val array has more than one 525*7c478bd9Sstevel@tonic-gate * element. Hence, making 'rv' a clone of 'rvq' will waste 526*7c478bd9Sstevel@tonic-gate * memory. 527*7c478bd9Sstevel@tonic-gate * 528*7c478bd9Sstevel@tonic-gate * However, we believe this waste is acceptable, because 529*7c478bd9Sstevel@tonic-gate * we expect that 'niv' will be small. Also, we are executing 530*7c478bd9Sstevel@tonic-gate * in the context of a utility command, not in a daemon. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate rv = initRuleValue(niv, rvq); 533*7c478bd9Sstevel@tonic-gate if (rv == 0) { 534*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 535*7c478bd9Sstevel@tonic-gate *numVals = 0; 536*7c478bd9Sstevel@tonic-gate return (0); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate /* 540*7c478bd9Sstevel@tonic-gate * For each column value in 'rvq', copy to the appropriate 541*7c478bd9Sstevel@tonic-gate * place in 'rv', so that the end result is that all 542*7c478bd9Sstevel@tonic-gate * combinations of values are enumerated, and each 543*7c478bd9Sstevel@tonic-gate * 'rv[n].colVal[i]' is single-valued. 544*7c478bd9Sstevel@tonic-gate * 545*7c478bd9Sstevel@tonic-gate * We do this by traversing the rv[] array 'rvq->numColumns' 546*7c478bd9Sstevel@tonic-gate * times, where each traversal 'i' works on the values 547*7c478bd9Sstevel@tonic-gate * for rvq->colVal[i]. A repeat factor 'repeat' starts out 548*7c478bd9Sstevel@tonic-gate * at '1', and is multiplied by 'rvq->colVal[i].numVals' 549*7c478bd9Sstevel@tonic-gate * at the end of each traversal. Every value 550*7c478bd9Sstevel@tonic-gate * rvq->colVal[i].val[j] is repeated 'repeat' times. 551*7c478bd9Sstevel@tonic-gate * 552*7c478bd9Sstevel@tonic-gate * This algorithm works by regarding the rv[] array as 553*7c478bd9Sstevel@tonic-gate * an I-dimensional array (I = rvq->numColumns), where 554*7c478bd9Sstevel@tonic-gate * each dimension 'i' corresponds to the values for 555*7c478bd9Sstevel@tonic-gate * rvq->colVal[i]. The I-dimensional array is stored 556*7c478bd9Sstevel@tonic-gate * in column-major order. 557*7c478bd9Sstevel@tonic-gate * 558*7c478bd9Sstevel@tonic-gate * Since the 'rv' elements start out as copies of 'rvq', 559*7c478bd9Sstevel@tonic-gate * we achieve the "copy" of the 'rvq' column values by 560*7c478bd9Sstevel@tonic-gate * deleting those we don't want from the 'rv' elements. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate for (i = 0, repeat = 1; i < rvq->numColumns; i++) { 563*7c478bd9Sstevel@tonic-gate int r, k; 564*7c478bd9Sstevel@tonic-gate for (n = 0, j = 0, r = 0; n < niv; n++) { 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * Free all but element 'j' of the 567*7c478bd9Sstevel@tonic-gate * rv[n].colVal[i].val array. 568*7c478bd9Sstevel@tonic-gate */ 569*7c478bd9Sstevel@tonic-gate for (k = 0; k < rv[n].colVal[i].numVals; k++) { 570*7c478bd9Sstevel@tonic-gate /* Leave element 'j' in place */ 571*7c478bd9Sstevel@tonic-gate if (k == j) 572*7c478bd9Sstevel@tonic-gate continue; 573*7c478bd9Sstevel@tonic-gate sfree(rv[n].colVal[i].val[k]. 574*7c478bd9Sstevel@tonic-gate value); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate rv[n].colVal[i].numVals = 1; 577*7c478bd9Sstevel@tonic-gate /* Move element 'j' to zero */ 578*7c478bd9Sstevel@tonic-gate if (j != 0) 579*7c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[0] = 580*7c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[j]; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate /* 583*7c478bd9Sstevel@tonic-gate * Increment the repeat index 'r'. If >= 584*7c478bd9Sstevel@tonic-gate * 'repeat', reset 'r' and increment the 585*7c478bd9Sstevel@tonic-gate * value index 'j'. If 'j' >= 586*7c478bd9Sstevel@tonic-gate * rvq->colVal[i].numVals, start over on 587*7c478bd9Sstevel@tonic-gate * the column values for column 'i' (i.e., 588*7c478bd9Sstevel@tonic-gate * reset 'j' to zero). 589*7c478bd9Sstevel@tonic-gate */ 590*7c478bd9Sstevel@tonic-gate r += 1; 591*7c478bd9Sstevel@tonic-gate if (r >= repeat) { 592*7c478bd9Sstevel@tonic-gate r = 0; 593*7c478bd9Sstevel@tonic-gate j += 1; 594*7c478bd9Sstevel@tonic-gate if (j >= rvq->colVal[i].numVals) 595*7c478bd9Sstevel@tonic-gate j = 0; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate repeat *= rvq->colVal[i].numVals; 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate *numVals = niv; 602*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 603*7c478bd9Sstevel@tonic-gate rvq = rv; 604*7c478bd9Sstevel@tonic-gate rv = 0; 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate q = am(myself, *numVals * sizeof (q[0])); 608*7c478bd9Sstevel@tonic-gate if (q == 0) { 609*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 610*7c478bd9Sstevel@tonic-gate return (0); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate /* 614*7c478bd9Sstevel@tonic-gate * Create queries from the rvq[] array. 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate for (a = 0; a < *numVals; a++) { 617*7c478bd9Sstevel@tonic-gate int nn, err = 0; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate qc = am(myself, rvq[a].numColumns * sizeof (*qc)); 620*7c478bd9Sstevel@tonic-gate if (qc != 0) { 621*7c478bd9Sstevel@tonic-gate for (nn = 0, i = 0; i < rvq[a].numColumns; i++) { 622*7c478bd9Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) { 623*7c478bd9Sstevel@tonic-gate if (strcmp(rvq[a].colName[i], 624*7c478bd9Sstevel@tonic-gate t->column[j]) == 0) { 625*7c478bd9Sstevel@tonic-gate break; 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate if (j >= t->numColumns) 629*7c478bd9Sstevel@tonic-gate continue; 630*7c478bd9Sstevel@tonic-gate qc[nn].which_index = j; 631*7c478bd9Sstevel@tonic-gate if (rvq[a].colVal[i].numVals > 0) { 632*7c478bd9Sstevel@tonic-gate qc[nn].index_value = buildItem( 633*7c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].length, 634*7c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].value); 635*7c478bd9Sstevel@tonic-gate if (qc[nn].index_value == 0) 636*7c478bd9Sstevel@tonic-gate err++; 637*7c478bd9Sstevel@tonic-gate } else { 638*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 639*7c478bd9Sstevel@tonic-gate "%s: No values for [%d]%s", 640*7c478bd9Sstevel@tonic-gate myself, a, rvq[a].colName[i]); 641*7c478bd9Sstevel@tonic-gate err++; 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate nn++; 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate if (err == 0) 646*7c478bd9Sstevel@tonic-gate q[a] = buildQuery(nn, qc); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate if (err > 0 || q[a] == 0) { 649*7c478bd9Sstevel@tonic-gate freeQueries(q, a); 650*7c478bd9Sstevel@tonic-gate for (a = 0; a < nn; a++) 651*7c478bd9Sstevel@tonic-gate freeQcomp(&qc[a], F); 652*7c478bd9Sstevel@tonic-gate sfree(qc); 653*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 654*7c478bd9Sstevel@tonic-gate return (0); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if (rvP != 0) { 659*7c478bd9Sstevel@tonic-gate *rvP = rvq; 660*7c478bd9Sstevel@tonic-gate } else { 661*7c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1); 662*7c478bd9Sstevel@tonic-gate *numVals = 0; 663*7c478bd9Sstevel@tonic-gate } 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate return (q); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate void 669*7c478bd9Sstevel@tonic-gate printQuery(db_query *q, __nis_table_mapping_t *t) { 670*7c478bd9Sstevel@tonic-gate int i, mc = -1; 671*7c478bd9Sstevel@tonic-gate char *myself = "printQuery"; 672*7c478bd9Sstevel@tonic-gate char *val[NIS_MAXCOLUMNS]; 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate if (q == 0) 675*7c478bd9Sstevel@tonic-gate return; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate (void) memset(val, 0, sizeof (val)); 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* 680*7c478bd9Sstevel@tonic-gate * Collect the values, which may be out of order in 'q'. 681*7c478bd9Sstevel@tonic-gate * Remember the largest index. 682*7c478bd9Sstevel@tonic-gate */ 683*7c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 684*7c478bd9Sstevel@tonic-gate int ix = q->components.components_val[i].which_index; 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate if (ix >= NIS_MAXCOLUMNS || 687*7c478bd9Sstevel@tonic-gate (t != 0 && ix >= t->numColumns)) 688*7c478bd9Sstevel@tonic-gate continue; 689*7c478bd9Sstevel@tonic-gate if (ix > mc) 690*7c478bd9Sstevel@tonic-gate mc = ix; 691*7c478bd9Sstevel@tonic-gate val[ix] = q->components.components_val[i].index_value-> 692*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val; 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate /* Print the values we collected */ 696*7c478bd9Sstevel@tonic-gate for (i = 0; i <= mc; i++) { 697*7c478bd9Sstevel@tonic-gate p2buf(myself, "%s%s", (i != 0 ? " " : ""), 698*7c478bd9Sstevel@tonic-gate (val[i] != 0 ? val[i] : "")); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate /* If we printed anything, add a newline */ 701*7c478bd9Sstevel@tonic-gate if (mc >= 0) 702*7c478bd9Sstevel@tonic-gate p2buf(myself, "\n"); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * Verify that the db_query's 'q' and 'fq' match, in the sense that if 707*7c478bd9Sstevel@tonic-gate * they both have a value for a certain index, the values are the same. 708*7c478bd9Sstevel@tonic-gate */ 709*7c478bd9Sstevel@tonic-gate int 710*7c478bd9Sstevel@tonic-gate verifyQueryMatch(db_query *q, db_query *fq) { 711*7c478bd9Sstevel@tonic-gate int i, j, match; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate if (fq == 0) 714*7c478bd9Sstevel@tonic-gate return (1); 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (q == 0) 717*7c478bd9Sstevel@tonic-gate return ((fq == 0) ? 1 : 0); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate for (i = 0, match = 1; match && i < q->components.components_len; 720*7c478bd9Sstevel@tonic-gate i++) { 721*7c478bd9Sstevel@tonic-gate for (j = 0; j < fq->components.components_len; j++) { 722*7c478bd9Sstevel@tonic-gate int len, flen; 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate /* Same index ? */ 725*7c478bd9Sstevel@tonic-gate if (q->components.components_val[i].which_index != 726*7c478bd9Sstevel@tonic-gate fq->components.components_val[j]. 727*7c478bd9Sstevel@tonic-gate which_index) 728*7c478bd9Sstevel@tonic-gate continue; 729*7c478bd9Sstevel@tonic-gate /* 730*7c478bd9Sstevel@tonic-gate * If one 'index_value' is NULL, the other one must 731*7c478bd9Sstevel@tonic-gate * be NULL as well. 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate if (q->components.components_val[i].index_value == 0) { 734*7c478bd9Sstevel@tonic-gate if (fq->components.components_val[j]. 735*7c478bd9Sstevel@tonic-gate index_value == 0) 736*7c478bd9Sstevel@tonic-gate continue; 737*7c478bd9Sstevel@tonic-gate else { 738*7c478bd9Sstevel@tonic-gate match = 0; 739*7c478bd9Sstevel@tonic-gate break; 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate if (fq->components.components_val[j].index_value == 743*7c478bd9Sstevel@tonic-gate 0) { 744*7c478bd9Sstevel@tonic-gate match = 0; 745*7c478bd9Sstevel@tonic-gate break; 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate /* Same value lengths ? */ 748*7c478bd9Sstevel@tonic-gate len = q->components.components_val[i].index_value-> 749*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len; 750*7c478bd9Sstevel@tonic-gate flen = fq->components.components_val[j].index_value-> 751*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len; 752*7c478bd9Sstevel@tonic-gate if (len != flen) { 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * There's a twist here: the input query 755*7c478bd9Sstevel@tonic-gate * may well _not_ count a concluding NUL 756*7c478bd9Sstevel@tonic-gate * in a string value, while the output 757*7c478bd9Sstevel@tonic-gate * usually will. So, if the difference in 758*7c478bd9Sstevel@tonic-gate * length is one, and the "extra" byte is 759*7c478bd9Sstevel@tonic-gate * a zero-valued one, we accept equality. 760*7c478bd9Sstevel@tonic-gate * 'q' is assumed to be the output, and 761*7c478bd9Sstevel@tonic-gate * 'fq' the input. 762*7c478bd9Sstevel@tonic-gate */ 763*7c478bd9Sstevel@tonic-gate if (!(len > 0 && len == (flen+1) && 764*7c478bd9Sstevel@tonic-gate q->components.components_val[i]. 765*7c478bd9Sstevel@tonic-gate index_value-> 766*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val[len-1] == 0)) { 767*7c478bd9Sstevel@tonic-gate match = 0; 768*7c478bd9Sstevel@tonic-gate break; 769*7c478bd9Sstevel@tonic-gate } 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate /* Same value ? */ 772*7c478bd9Sstevel@tonic-gate if (memcmp(q->components.components_val[i].index_value-> 773*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val, 774*7c478bd9Sstevel@tonic-gate fq->components.components_val[j].index_value-> 775*7c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val, 776*7c478bd9Sstevel@tonic-gate flen) != 0) { 777*7c478bd9Sstevel@tonic-gate match = 0; 778*7c478bd9Sstevel@tonic-gate break; 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate return (match); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* 787*7c478bd9Sstevel@tonic-gate * Remove those queries in 'q' that don't match t->index. 788*7c478bd9Sstevel@tonic-gate * Returns a pointer to the filtered array, which could be 789*7c478bd9Sstevel@tonic-gate * a compacted version of the original, or a new copy; in 790*7c478bd9Sstevel@tonic-gate * the latter case, the original will have been freed. 791*7c478bd9Sstevel@tonic-gate * 792*7c478bd9Sstevel@tonic-gate * Filtered/removed db_query's are freed. 793*7c478bd9Sstevel@tonic-gate */ 794*7c478bd9Sstevel@tonic-gate db_query ** 795*7c478bd9Sstevel@tonic-gate filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin, 796*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t ***objAttr, int *numQueries) { 797*7c478bd9Sstevel@tonic-gate db_query **new; 798*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr; 799*7c478bd9Sstevel@tonic-gate int i, nq, nn; 800*7c478bd9Sstevel@tonic-gate char *myself = "filterQuery"; 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate if ((t == 0 && qin == 0) || q == 0 || 803*7c478bd9Sstevel@tonic-gate numQueries == 0 || *numQueries <= 0) 804*7c478bd9Sstevel@tonic-gate return (q); 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate nq = *numQueries; 807*7c478bd9Sstevel@tonic-gate new = am(myself, nq * sizeof (new[0])); 808*7c478bd9Sstevel@tonic-gate if (objAttr != 0) 809*7c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 810*7c478bd9Sstevel@tonic-gate else 811*7c478bd9Sstevel@tonic-gate attr = 0; 812*7c478bd9Sstevel@tonic-gate if (new == 0 || (objAttr != 0 && attr == 0)) { 813*7c478bd9Sstevel@tonic-gate sfree(new); 814*7c478bd9Sstevel@tonic-gate freeQueries(q, nq); 815*7c478bd9Sstevel@tonic-gate sfree(attr); 816*7c478bd9Sstevel@tonic-gate if (objAttr != 0) { 817*7c478bd9Sstevel@tonic-gate freeObjAttr(*objAttr, nq); 818*7c478bd9Sstevel@tonic-gate *objAttr = 0; 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate *numQueries = -1; 821*7c478bd9Sstevel@tonic-gate return (0); 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate for (i = 0, nn = 0; i < nq; i++) { 825*7c478bd9Sstevel@tonic-gate int retain = 1; 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate if (t != 0) 828*7c478bd9Sstevel@tonic-gate retain = verifyIndexMatch(t, q[i], 0, 0, 0); 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate if (retain && qin != 0) 831*7c478bd9Sstevel@tonic-gate retain = verifyQueryMatch(q[i], qin); 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate if (retain) { 834*7c478bd9Sstevel@tonic-gate new[nn] = q[i]; 835*7c478bd9Sstevel@tonic-gate if (objAttr != 0) 836*7c478bd9Sstevel@tonic-gate attr[nn] = (*objAttr)[i]; 837*7c478bd9Sstevel@tonic-gate nn++; 838*7c478bd9Sstevel@tonic-gate } else { 839*7c478bd9Sstevel@tonic-gate freeQuery(q[i]); 840*7c478bd9Sstevel@tonic-gate q[i] = 0; 841*7c478bd9Sstevel@tonic-gate if (objAttr != 0) { 842*7c478bd9Sstevel@tonic-gate freeSingleObjAttr((*objAttr)[i]); 843*7c478bd9Sstevel@tonic-gate (*objAttr)[i] = 0; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* All q[i]'s are either in 'new', or have been deleted */ 849*7c478bd9Sstevel@tonic-gate free(q); 850*7c478bd9Sstevel@tonic-gate if (objAttr != 0) { 851*7c478bd9Sstevel@tonic-gate sfree(*objAttr); 852*7c478bd9Sstevel@tonic-gate *objAttr = attr; 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate *numQueries = nn; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate return (new); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate db_query ** 861*7c478bd9Sstevel@tonic-gate createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 862*7c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, 863*7c478bd9Sstevel@tonic-gate int *numQueries) { 864*7c478bd9Sstevel@tonic-gate db_query **query = 0; 865*7c478bd9Sstevel@tonic-gate int r, i, j, ir; 866*7c478bd9Sstevel@tonic-gate __nis_value_t *rval, *lval; 867*7c478bd9Sstevel@tonic-gate __nis_mapping_item_t *litem; 868*7c478bd9Sstevel@tonic-gate int numItems; 869*7c478bd9Sstevel@tonic-gate int nq, iqc; 870*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0; 871*7c478bd9Sstevel@tonic-gate char **dn = 0; 872*7c478bd9Sstevel@tonic-gate int numDN = 0; 873*7c478bd9Sstevel@tonic-gate char *myself = "createNisPlusEntry"; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate if (t == 0 || t->objectDN == 0 || rv == 0) 876*7c478bd9Sstevel@tonic-gate return (0); 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate /* Establish default, per-thread, search base */ 879*7c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base; 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) { 882*7c478bd9Sstevel@tonic-gate int nrq, ntq, err; 883*7c478bd9Sstevel@tonic-gate db_query **newq; 884*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t **newattr; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate rval = buildRvalue(&t->ruleFromLDAP[r]->rhs, 887*7c478bd9Sstevel@tonic-gate mit_ldap, rv, NULL); 888*7c478bd9Sstevel@tonic-gate if (rval == 0) 889*7c478bd9Sstevel@tonic-gate continue; 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval, 892*7c478bd9Sstevel@tonic-gate &numItems); 893*7c478bd9Sstevel@tonic-gate if (litem == 0) { 894*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 895*7c478bd9Sstevel@tonic-gate /* XXX Should this be a fatal error ? */ 896*7c478bd9Sstevel@tonic-gate continue; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate lval = 0; 900*7c478bd9Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 901*7c478bd9Sstevel@tonic-gate __nis_value_t *tmpval, *old; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], 904*7c478bd9Sstevel@tonic-gate mit_nisplus, 0, 0, NULL); 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate /* 907*7c478bd9Sstevel@tonic-gate * If the LHS specifies an out-of-context LDAP or 908*7c478bd9Sstevel@tonic-gate * NIS+ item, we do the update right here. We 909*7c478bd9Sstevel@tonic-gate * don't add any values to 'lval'; instead, we 910*7c478bd9Sstevel@tonic-gate * skip to the next item. (However, we still 911*7c478bd9Sstevel@tonic-gate * get a string representation of the LHS in case 912*7c478bd9Sstevel@tonic-gate * we need to report an error.) 913*7c478bd9Sstevel@tonic-gate */ 914*7c478bd9Sstevel@tonic-gate if (litem[i].type == mit_nisplus && 915*7c478bd9Sstevel@tonic-gate litem[i].searchSpec.obj.index.numIndexes > 0) { 916*7c478bd9Sstevel@tonic-gate int err; 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate err = storeNisPlus(&litem[i], i, numItems, 919*7c478bd9Sstevel@tonic-gate rv, t->objName, rval); 920*7c478bd9Sstevel@tonic-gate if (err != NIS_SUCCESS) { 921*7c478bd9Sstevel@tonic-gate char *iname = "<unknown>"; 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate if (tmpval != 0 && 924*7c478bd9Sstevel@tonic-gate tmpval->numVals == 1) 925*7c478bd9Sstevel@tonic-gate iname = tmpval->val[0].value; 926*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 927*7c478bd9Sstevel@tonic-gate "%s: NIS+ store \"%s\": %s", 928*7c478bd9Sstevel@tonic-gate myself, iname, 929*7c478bd9Sstevel@tonic-gate nis_sperrno(err)); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 933*7c478bd9Sstevel@tonic-gate continue; 934*7c478bd9Sstevel@tonic-gate } else if (litem[i].type == mit_ldap) { 935*7c478bd9Sstevel@tonic-gate int stat; 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate if (dn == 0) 938*7c478bd9Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 939*7c478bd9Sstevel@tonic-gate t->objectDN->write.base, 940*7c478bd9Sstevel@tonic-gate &numDN); 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 943*7c478bd9Sstevel@tonic-gate t->objectDN, dn, numDN); 944*7c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 945*7c478bd9Sstevel@tonic-gate char *iname = "<unknown>"; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (tmpval != 0 && 948*7c478bd9Sstevel@tonic-gate tmpval->numVals == 1) 949*7c478bd9Sstevel@tonic-gate iname = tmpval->val[0].value; 950*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 951*7c478bd9Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 952*7c478bd9Sstevel@tonic-gate myself, iname, 953*7c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 957*7c478bd9Sstevel@tonic-gate continue; 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate old = lval; 961*7c478bd9Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 962*7c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 963*7c478bd9Sstevel@tonic-gate freeValue(old, 1); 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate freeMappingItem(litem, numItems); 967*7c478bd9Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) { 968*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 969*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 970*7c478bd9Sstevel@tonic-gate continue; 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * We now have a number of possible cases. The notation 975*7c478bd9Sstevel@tonic-gate * used in the table is: 976*7c478bd9Sstevel@tonic-gate * 977*7c478bd9Sstevel@tonic-gate * single A single value (numVals == 1) 978*7c478bd9Sstevel@tonic-gate * single/rep A single value with repeat == 1 979*7c478bd9Sstevel@tonic-gate * multi[N] N values 980*7c478bd9Sstevel@tonic-gate * multi[N]/rep M values with repeat == 1 981*7c478bd9Sstevel@tonic-gate * (M) M resulting db_query's 982*7c478bd9Sstevel@tonic-gate * 983*7c478bd9Sstevel@tonic-gate * lval \ rval single single/rep multi[N] multi[N]/rep 984*7c478bd9Sstevel@tonic-gate * single (1) (1) (1) (1) 985*7c478bd9Sstevel@tonic-gate * single/rep (1) (1) (N) (N) 986*7c478bd9Sstevel@tonic-gate * multi[M] (1) (1) (1) 1+(N-1)/M 987*7c478bd9Sstevel@tonic-gate * multi[M]/rep (1) (1) (1) 1+(N-1)/M 988*7c478bd9Sstevel@tonic-gate * 989*7c478bd9Sstevel@tonic-gate * Of course, we already have 'nq' db_query's from previous 990*7c478bd9Sstevel@tonic-gate * rules, so the resulting number of queries is max(1,nq) 991*7c478bd9Sstevel@tonic-gate * times the numbers in the table above. 992*7c478bd9Sstevel@tonic-gate */ 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate /* The number of queries resulting from the current rule */ 995*7c478bd9Sstevel@tonic-gate if (rval->numVals > 1) { 996*7c478bd9Sstevel@tonic-gate if (lval->numVals == 1 && lval->repeat) 997*7c478bd9Sstevel@tonic-gate nrq = rval->numVals; 998*7c478bd9Sstevel@tonic-gate else if (lval->numVals > 1 && rval->repeat) 999*7c478bd9Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/lval->numVals); 1000*7c478bd9Sstevel@tonic-gate else 1001*7c478bd9Sstevel@tonic-gate nrq = 1; 1002*7c478bd9Sstevel@tonic-gate } else { 1003*7c478bd9Sstevel@tonic-gate nrq = 1; 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate /* Total number of queries after adding the current rule */ 1007*7c478bd9Sstevel@tonic-gate if (nq <= 0) 1008*7c478bd9Sstevel@tonic-gate ntq = nrq; 1009*7c478bd9Sstevel@tonic-gate else 1010*7c478bd9Sstevel@tonic-gate ntq = nq * nrq; 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate if (ntq > nq) { 1013*7c478bd9Sstevel@tonic-gate newq = realloc(query, ntq * sizeof (query[0])); 1014*7c478bd9Sstevel@tonic-gate newattr = realloc(attr, ntq * sizeof (attr[0])); 1015*7c478bd9Sstevel@tonic-gate if (newq == 0 || newattr == 0) { 1016*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 1017*7c478bd9Sstevel@tonic-gate "%s: realloc(%d) => NULL", 1018*7c478bd9Sstevel@tonic-gate myself, ntq * sizeof (query[0])); 1019*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 1020*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 1021*7c478bd9Sstevel@tonic-gate freeQueries(query, nq); 1022*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 1023*7c478bd9Sstevel@tonic-gate sfree(newq); 1024*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 1025*7c478bd9Sstevel@tonic-gate return (0); 1026*7c478bd9Sstevel@tonic-gate } 1027*7c478bd9Sstevel@tonic-gate query = newq; 1028*7c478bd9Sstevel@tonic-gate attr = newattr; 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * Copy/clone the existing queries to the new array, 1033*7c478bd9Sstevel@tonic-gate * remembering that realloc() has done the first 'nq' 1034*7c478bd9Sstevel@tonic-gate * ones. 1035*7c478bd9Sstevel@tonic-gate * 1036*7c478bd9Sstevel@tonic-gate * If there's an error (probably memory allocation), we 1037*7c478bd9Sstevel@tonic-gate * still go through the rest of the array, so that it's 1038*7c478bd9Sstevel@tonic-gate * simple to free the elements when we clean up. 1039*7c478bd9Sstevel@tonic-gate */ 1040*7c478bd9Sstevel@tonic-gate for (i = 1, err = 0; i < nrq; i++) { 1041*7c478bd9Sstevel@tonic-gate for (j = 0; j < nq; j++) { 1042*7c478bd9Sstevel@tonic-gate query[(nq*i)+j] = cloneQuery(query[j], 1043*7c478bd9Sstevel@tonic-gate t->numColumns); 1044*7c478bd9Sstevel@tonic-gate if (query[(nq*i)+j] == 0 && 1045*7c478bd9Sstevel@tonic-gate query[j] != 0) 1046*7c478bd9Sstevel@tonic-gate err++; 1047*7c478bd9Sstevel@tonic-gate attr[(nq*i)+j] = cloneObjAttr(attr[j]); 1048*7c478bd9Sstevel@tonic-gate if (attr[(nq*i)+j] == 0 && 1049*7c478bd9Sstevel@tonic-gate attr[j] != 0) 1050*7c478bd9Sstevel@tonic-gate err++; 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if (err > 0) { 1055*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 1056*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 1057*7c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 1058*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 1059*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 1060*7c478bd9Sstevel@tonic-gate return (0); 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate /* 1064*7c478bd9Sstevel@tonic-gate * Special case if nq == 0 (i.e., the first time we 1065*7c478bd9Sstevel@tonic-gate * allocated db_query's). If so, we now allocate empty 1066*7c478bd9Sstevel@tonic-gate * db_qcomp arrays, which simplifies subsequent 1067*7c478bd9Sstevel@tonic-gate * copying of values. 1068*7c478bd9Sstevel@tonic-gate */ 1069*7c478bd9Sstevel@tonic-gate if (nq <= 0) { 1070*7c478bd9Sstevel@tonic-gate (void) memset(query, 0, ntq * sizeof (query[0])); 1071*7c478bd9Sstevel@tonic-gate (void) memset(attr, 0, ntq * sizeof (attr[0])); 1072*7c478bd9Sstevel@tonic-gate for (i = 0, err = 0; i < ntq; i++) { 1073*7c478bd9Sstevel@tonic-gate query[i] = am(myself, sizeof (*query[i])); 1074*7c478bd9Sstevel@tonic-gate if (query[i] == 0) { 1075*7c478bd9Sstevel@tonic-gate err++; 1076*7c478bd9Sstevel@tonic-gate break; 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate query[i]->components.components_val = 1079*7c478bd9Sstevel@tonic-gate am(myself, t->numColumns * 1080*7c478bd9Sstevel@tonic-gate sizeof (query[i]->components.components_val[0])); 1081*7c478bd9Sstevel@tonic-gate if (query[i]->components.components_val == 0) { 1082*7c478bd9Sstevel@tonic-gate err++; 1083*7c478bd9Sstevel@tonic-gate break; 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate query[i]->components.components_len = 0; 1086*7c478bd9Sstevel@tonic-gate } 1087*7c478bd9Sstevel@tonic-gate if (err > 0) { 1088*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 1089*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 1090*7c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 1091*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 1092*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 1093*7c478bd9Sstevel@tonic-gate return (0); 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate /* Now we're ready to add the new values */ 1098*7c478bd9Sstevel@tonic-gate for (i = 0, ir = 0; i < lval->numVals; i++) { 1099*7c478bd9Sstevel@tonic-gate char *oaName = 0; 1100*7c478bd9Sstevel@tonic-gate int index; 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate /* Find column index */ 1103*7c478bd9Sstevel@tonic-gate for (index = 0; index < t->numColumns; 1104*7c478bd9Sstevel@tonic-gate index++) { 1105*7c478bd9Sstevel@tonic-gate if (strncmp(t->column[index], 1106*7c478bd9Sstevel@tonic-gate lval->val[i].value, 1107*7c478bd9Sstevel@tonic-gate lval->val[i].length) == 0) 1108*7c478bd9Sstevel@tonic-gate break; 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate if (index >= t->numColumns) { 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * Could be one of the special object 1113*7c478bd9Sstevel@tonic-gate * attributes. 1114*7c478bd9Sstevel@tonic-gate */ 1115*7c478bd9Sstevel@tonic-gate oaName = isObjAttr(&lval->val[i]); 1116*7c478bd9Sstevel@tonic-gate if (oaName == 0) 1117*7c478bd9Sstevel@tonic-gate continue; 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate for (j = i*nrq; j < (i+1)*nrq; j++) { 1121*7c478bd9Sstevel@tonic-gate int k; 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate /* If we're out of values, repeat last one */ 1124*7c478bd9Sstevel@tonic-gate ir = (j < rval->numVals) ? 1125*7c478bd9Sstevel@tonic-gate j : rval->numVals - 1; 1126*7c478bd9Sstevel@tonic-gate 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * Step through the query array, adding 1129*7c478bd9Sstevel@tonic-gate * the new value every 'nrq' queries, and 1130*7c478bd9Sstevel@tonic-gate * starting at 'query[j % nrq]'. 1131*7c478bd9Sstevel@tonic-gate */ 1132*7c478bd9Sstevel@tonic-gate for (k = j % nrq, err = 0; k < ntq; k += nrq) { 1133*7c478bd9Sstevel@tonic-gate int ic, c; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate if (oaName != 0) { 1136*7c478bd9Sstevel@tonic-gate int fail = setObjAttrField( 1137*7c478bd9Sstevel@tonic-gate oaName, 1138*7c478bd9Sstevel@tonic-gate &rval->val[ir], 1139*7c478bd9Sstevel@tonic-gate &attr[k]); 1140*7c478bd9Sstevel@tonic-gate if (fail) { 1141*7c478bd9Sstevel@tonic-gate err++; 1142*7c478bd9Sstevel@tonic-gate break; 1143*7c478bd9Sstevel@tonic-gate } 1144*7c478bd9Sstevel@tonic-gate continue; 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate ic = query[k]->components. 1148*7c478bd9Sstevel@tonic-gate components_len; 1149*7c478bd9Sstevel@tonic-gate /* 1150*7c478bd9Sstevel@tonic-gate * If we've already filled this 1151*7c478bd9Sstevel@tonic-gate * query, the new value is a dup 1152*7c478bd9Sstevel@tonic-gate * which we'll ignore. 1153*7c478bd9Sstevel@tonic-gate */ 1154*7c478bd9Sstevel@tonic-gate if (ic >= t->numColumns) 1155*7c478bd9Sstevel@tonic-gate continue; 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate /* 1158*7c478bd9Sstevel@tonic-gate * Do we already have a value for 1159*7c478bd9Sstevel@tonic-gate * this 'index' ? 1160*7c478bd9Sstevel@tonic-gate */ 1161*7c478bd9Sstevel@tonic-gate for (c = 0; c < ic; c++) { 1162*7c478bd9Sstevel@tonic-gate if (query[k]->components. 1163*7c478bd9Sstevel@tonic-gate components_val[c]. 1164*7c478bd9Sstevel@tonic-gate which_index == index) 1165*7c478bd9Sstevel@tonic-gate break; 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate /* If no previous value, add it */ 1169*7c478bd9Sstevel@tonic-gate if (c >= ic) { 1170*7c478bd9Sstevel@tonic-gate int l; 1171*7c478bd9Sstevel@tonic-gate char *v; 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate query[k]->components. 1174*7c478bd9Sstevel@tonic-gate components_val[ic]. 1175*7c478bd9Sstevel@tonic-gate which_index = index; 1176*7c478bd9Sstevel@tonic-gate l = rval->val[ir].length; 1177*7c478bd9Sstevel@tonic-gate v = rval->val[ir].value; 1178*7c478bd9Sstevel@tonic-gate if (rval->type == vt_string && 1179*7c478bd9Sstevel@tonic-gate l > 0 && 1180*7c478bd9Sstevel@tonic-gate v[l-1] != '\0' && 1181*7c478bd9Sstevel@tonic-gate v[l] == '\0') 1182*7c478bd9Sstevel@tonic-gate l++; 1183*7c478bd9Sstevel@tonic-gate query[k]->components. 1184*7c478bd9Sstevel@tonic-gate components_val[ic]. 1185*7c478bd9Sstevel@tonic-gate index_value = 1186*7c478bd9Sstevel@tonic-gate buildItem(l, v); 1187*7c478bd9Sstevel@tonic-gate if (query[k]-> 1188*7c478bd9Sstevel@tonic-gate components. 1189*7c478bd9Sstevel@tonic-gate components_val[ic]. 1190*7c478bd9Sstevel@tonic-gate index_value == 0) { 1191*7c478bd9Sstevel@tonic-gate err++; 1192*7c478bd9Sstevel@tonic-gate break; 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate query[k]->components. 1195*7c478bd9Sstevel@tonic-gate components_len++; 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate if (err > 0) { 1199*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 1200*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 1201*7c478bd9Sstevel@tonic-gate freeQueries(query, ntq); 1202*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq); 1203*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 1204*7c478bd9Sstevel@tonic-gate return (0); 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate } 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate freeValue(lval, 1); 1209*7c478bd9Sstevel@tonic-gate freeValue(rval, 1); 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate nq = ntq; 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate if (nq <= 0) { 1217*7c478bd9Sstevel@tonic-gate sfree(query); 1218*7c478bd9Sstevel@tonic-gate query = 0; 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* Should we filter on index or input query ? */ 1222*7c478bd9Sstevel@tonic-gate if (query != 0) { 1223*7c478bd9Sstevel@tonic-gate if (t->index.numIndexes > 0) 1224*7c478bd9Sstevel@tonic-gate query = filterQuery(t, query, qin, &attr, &nq); 1225*7c478bd9Sstevel@tonic-gate else if (qin != 0) 1226*7c478bd9Sstevel@tonic-gate query = filterQuery(0, query, qin, &attr, &nq); 1227*7c478bd9Sstevel@tonic-gate } 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate if (query != 0 && numQueries != 0) 1230*7c478bd9Sstevel@tonic-gate *numQueries = nq; 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate if (objAttr != 0) 1233*7c478bd9Sstevel@tonic-gate *objAttr = attr; 1234*7c478bd9Sstevel@tonic-gate else 1235*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate return (query); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate /* 1240*7c478bd9Sstevel@tonic-gate * Given a table mapping and a rule-value, convert to an array of 1241*7c478bd9Sstevel@tonic-gate * (db_query *), using the fromLDAP ruleset. 1242*7c478bd9Sstevel@tonic-gate * 1243*7c478bd9Sstevel@tonic-gate * On entry, '*numQueries' holds the number of elements in the 'rv' 1244*7c478bd9Sstevel@tonic-gate * array. On exit, it holds the number of (db_query *)'s in the return 1245*7c478bd9Sstevel@tonic-gate * value array. 1246*7c478bd9Sstevel@tonic-gate */ 1247*7c478bd9Sstevel@tonic-gate db_query ** 1248*7c478bd9Sstevel@tonic-gate ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 1249*7c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) { 1250*7c478bd9Sstevel@tonic-gate db_query **q = 0, ***qp = 0; 1251*7c478bd9Sstevel@tonic-gate int i, nqp, nq, *nnp = 0, nv; 1252*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0, ***atp = 0; 1253*7c478bd9Sstevel@tonic-gate char *myself = "ruleValue2Query"; 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate if (t == 0 || rv == 0 || numQueries == 0) 1257*7c478bd9Sstevel@tonic-gate return (0); 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate nv = *numQueries; 1260*7c478bd9Sstevel@tonic-gate if (nv <= 0) 1261*7c478bd9Sstevel@tonic-gate return (0); 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate /* 1264*7c478bd9Sstevel@tonic-gate * 'qp' is an array of (db_query **), and we get one element for 1265*7c478bd9Sstevel@tonic-gate * each call to createNisPlusEntry(); i.e., one for each rule-value. 1266*7c478bd9Sstevel@tonic-gate * 1267*7c478bd9Sstevel@tonic-gate * 'nnp[i]' is the count of (db_query *) in each 'qp[i]'. 1268*7c478bd9Sstevel@tonic-gate */ 1269*7c478bd9Sstevel@tonic-gate qp = am(myself, nv * sizeof (*qp)); 1270*7c478bd9Sstevel@tonic-gate nnp = am(myself, nv * sizeof (*nnp)); 1271*7c478bd9Sstevel@tonic-gate atp = am(myself, nv * sizeof (*atp)); 1272*7c478bd9Sstevel@tonic-gate if (qp == 0 || nnp == 0 || atp == 0) { 1273*7c478bd9Sstevel@tonic-gate sfree(qp); 1274*7c478bd9Sstevel@tonic-gate sfree(nnp); 1275*7c478bd9Sstevel@tonic-gate sfree(atp); 1276*7c478bd9Sstevel@tonic-gate return (0); 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate for (i = 0, nq = 0, nqp = 0; i < nv; i++) { 1280*7c478bd9Sstevel@tonic-gate qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp], 1281*7c478bd9Sstevel@tonic-gate &nnp[nqp]); 1282*7c478bd9Sstevel@tonic-gate /* If we fail, abort (XXX??? or continue ???) */ 1283*7c478bd9Sstevel@tonic-gate if (qp[nqp] == 0) 1284*7c478bd9Sstevel@tonic-gate goto cleanup; 1285*7c478bd9Sstevel@tonic-gate nq += nnp[nqp]; 1286*7c478bd9Sstevel@tonic-gate nqp++; 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate /* If we didn't get any (db_query **)'s, return failure */ 1290*7c478bd9Sstevel@tonic-gate if (nqp == 0 || nq <= 0) 1291*7c478bd9Sstevel@tonic-gate goto cleanup; 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate q = am(myself, nq * sizeof (q[0])); 1294*7c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 1295*7c478bd9Sstevel@tonic-gate if (q == 0 || attr == 0) { 1296*7c478bd9Sstevel@tonic-gate nq = 0; 1297*7c478bd9Sstevel@tonic-gate goto cleanup; 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate /* Convert 'qp' to an array of (db_query *)'s */ 1301*7c478bd9Sstevel@tonic-gate for (i = 0, nq = 0; i < nqp; i++) { 1302*7c478bd9Sstevel@tonic-gate (void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0])); 1303*7c478bd9Sstevel@tonic-gate (void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0])); 1304*7c478bd9Sstevel@tonic-gate nq += nnp[i]; 1305*7c478bd9Sstevel@tonic-gate free(qp[i]); 1306*7c478bd9Sstevel@tonic-gate free(atp[i]); 1307*7c478bd9Sstevel@tonic-gate } 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate *numQueries = nq; 1310*7c478bd9Sstevel@tonic-gate if (objAttr != 0) 1311*7c478bd9Sstevel@tonic-gate *objAttr = attr; 1312*7c478bd9Sstevel@tonic-gate else 1313*7c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq); 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate /* Make sure 'cleanup' doesn't free the db_query pointers */ 1316*7c478bd9Sstevel@tonic-gate nqp = 0; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate cleanup: 1319*7c478bd9Sstevel@tonic-gate for (i = 0; i < nqp; i++) { 1320*7c478bd9Sstevel@tonic-gate freeQueries(qp[i], nnp[i]); 1321*7c478bd9Sstevel@tonic-gate sfree(atp[i]); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate sfree(qp); 1324*7c478bd9Sstevel@tonic-gate sfree(nnp); 1325*7c478bd9Sstevel@tonic-gate sfree(atp); 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate return (q); 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate db_query * 1331*7c478bd9Sstevel@tonic-gate pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) { 1332*7c478bd9Sstevel@tonic-gate db_query *qbuf; 1333*7c478bd9Sstevel@tonic-gate db_qcomp *qcbuf; 1334*7c478bd9Sstevel@tonic-gate int nc, i; 1335*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvt = 0; 1336*7c478bd9Sstevel@tonic-gate char *myself = "pseudoEntryObj2Query"; 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate nc = e->en_cols.en_cols_len - 1; 1339*7c478bd9Sstevel@tonic-gate 1340*7c478bd9Sstevel@tonic-gate if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS) 1341*7c478bd9Sstevel@tonic-gate return (0); 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate /* 1344*7c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, build a rule value from the pseudo- 1345*7c478bd9Sstevel@tonic-gate * nis_object in e->en_cols.en_cols_val[0]. 1346*7c478bd9Sstevel@tonic-gate */ 1347*7c478bd9Sstevel@tonic-gate if (rv != 0) { 1348*7c478bd9Sstevel@tonic-gate nis_object *o; 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate o = unmakePseudoEntryObj(e, tobj); 1351*7c478bd9Sstevel@tonic-gate if (o == 0) 1352*7c478bd9Sstevel@tonic-gate return (0); 1353*7c478bd9Sstevel@tonic-gate rvt = addObjAttr2RuleValue(o, 0); 1354*7c478bd9Sstevel@tonic-gate nis_destroy_object(o); 1355*7c478bd9Sstevel@tonic-gate if (rvt == 0) 1356*7c478bd9Sstevel@tonic-gate return (0); 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate qbuf = am(myself, sizeof (*qbuf)); 1360*7c478bd9Sstevel@tonic-gate /* 1361*7c478bd9Sstevel@tonic-gate * If there are no columns (other than the pseudo-entry object), 1362*7c478bd9Sstevel@tonic-gate * we're done. 1363*7c478bd9Sstevel@tonic-gate */ 1364*7c478bd9Sstevel@tonic-gate if (nc == 0) 1365*7c478bd9Sstevel@tonic-gate return (qbuf); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate qcbuf = am(myself, nc * sizeof (*qcbuf)); 1368*7c478bd9Sstevel@tonic-gate if (qcbuf == 0) { 1369*7c478bd9Sstevel@tonic-gate sfree(qcbuf); 1370*7c478bd9Sstevel@tonic-gate if (rvt != 0) 1371*7c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 1372*7c478bd9Sstevel@tonic-gate return (0); 1373*7c478bd9Sstevel@tonic-gate } 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate /* 1376*7c478bd9Sstevel@tonic-gate * Build the db_query, remembering that e->en_cols.en_cols_val[0] 1377*7c478bd9Sstevel@tonic-gate * is the pseudo-nis_object. 1378*7c478bd9Sstevel@tonic-gate */ 1379*7c478bd9Sstevel@tonic-gate qbuf->components.components_val = qcbuf; 1380*7c478bd9Sstevel@tonic-gate qbuf->components.components_len = nc; 1381*7c478bd9Sstevel@tonic-gate for (i = 0; i < nc; i++) { 1382*7c478bd9Sstevel@tonic-gate qcbuf[i].which_index = i; 1383*7c478bd9Sstevel@tonic-gate qcbuf[i].index_value = buildItem( 1384*7c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_len, 1385*7c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_val); 1386*7c478bd9Sstevel@tonic-gate if (qcbuf[i].index_value == 0) { 1387*7c478bd9Sstevel@tonic-gate freeQuery(qbuf); 1388*7c478bd9Sstevel@tonic-gate if (rvt != 0) 1389*7c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 1390*7c478bd9Sstevel@tonic-gate return (0); 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate if (rvt != 0) { 1395*7c478bd9Sstevel@tonic-gate *rv = *rvt; 1396*7c478bd9Sstevel@tonic-gate sfree(rvt); 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate return (qbuf); 1400*7c478bd9Sstevel@tonic-gate } 1401*7c478bd9Sstevel@tonic-gate 1402*7c478bd9Sstevel@tonic-gate /* 1403*7c478bd9Sstevel@tonic-gate * Given an input query 'q', and a db_query work buffer 'qbuf', return 1404*7c478bd9Sstevel@tonic-gate * a pointer to a query with one component corresponding to component 1405*7c478bd9Sstevel@tonic-gate * 'index' in 'q'. 1406*7c478bd9Sstevel@tonic-gate * 1407*7c478bd9Sstevel@tonic-gate * Note that no memory is allocated, and that the returned query has 1408*7c478bd9Sstevel@tonic-gate * pointers into 'q'. 1409*7c478bd9Sstevel@tonic-gate */ 1410*7c478bd9Sstevel@tonic-gate db_query * 1411*7c478bd9Sstevel@tonic-gate queryFromComponent(db_query *q, int index, db_query *qbuf) { 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate if (q == 0 || index < 0 || index >= q->components.components_len || 1414*7c478bd9Sstevel@tonic-gate qbuf == 0) 1415*7c478bd9Sstevel@tonic-gate return (0); 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate qbuf->components.components_len = 1; 1418*7c478bd9Sstevel@tonic-gate qbuf->components.components_val = &q->components.components_val[index]; 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate return (qbuf); 1421*7c478bd9Sstevel@tonic-gate } 1422