17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*36e852a1SRaja Andra * Common Development and Distribution License (the "License").
6*36e852a1SRaja Andra * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*36e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <strings.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <lber.h>
307c478bd9Sstevel@tonic-gate #include <ldap.h>
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include "db_item_c.h"
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include "nisdb_mt.h"
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #include "ldap_util.h"
377c478bd9Sstevel@tonic-gate #include "ldap_structs.h"
387c478bd9Sstevel@tonic-gate #include "ldap_val.h"
397c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h"
407c478bd9Sstevel@tonic-gate #include "ldap_op.h"
417c478bd9Sstevel@tonic-gate #include "ldap_nisdbquery.h"
427c478bd9Sstevel@tonic-gate #include "ldap_attr.h"
437c478bd9Sstevel@tonic-gate #include "ldap_xdr.h"
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate item *
buildItem(int len,void * value)477c478bd9Sstevel@tonic-gate buildItem(int len, void *value) {
487c478bd9Sstevel@tonic-gate char *myself = "buildItem";
497c478bd9Sstevel@tonic-gate item *i = am(myself, sizeof (*i));
507c478bd9Sstevel@tonic-gate int mlen = len;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate if (i == 0)
537c478bd9Sstevel@tonic-gate return (0);
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate * To this function, a NULL value, or a length less than or equal
577c478bd9Sstevel@tonic-gate * zero means an item with no value. Hence, buildItem(0, 0) is
587c478bd9Sstevel@tonic-gate * _not_ the right way to create index_value == 0 to indicate
597c478bd9Sstevel@tonic-gate * deletion.
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate if (value == 0 || len <= 0) {
627c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = 0;
637c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = 0;
647c478bd9Sstevel@tonic-gate return (i);
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate * NIS+ usually stores the terminating NUL for strings, so we add
697c478bd9Sstevel@tonic-gate * it here just in case. This means we usually waste a byte for
707c478bd9Sstevel@tonic-gate * binary column values...
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate if (len > 0 && ((char *)value)[len-1] != '\0')
737c478bd9Sstevel@tonic-gate mlen++;
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_len = len;
767c478bd9Sstevel@tonic-gate i->itemvalue.itemvalue_val = am(myself, mlen);
777c478bd9Sstevel@tonic-gate if (mlen > 0 && i->itemvalue.itemvalue_val == 0) {
787c478bd9Sstevel@tonic-gate free(i);
797c478bd9Sstevel@tonic-gate return (0);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate memcpy(i->itemvalue.itemvalue_val, value, len);
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate return (i);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate void
freeItem(item * i)877c478bd9Sstevel@tonic-gate freeItem(item *i) {
887c478bd9Sstevel@tonic-gate if (i != 0) {
897c478bd9Sstevel@tonic-gate sfree(i->itemvalue.itemvalue_val);
907c478bd9Sstevel@tonic-gate free(i);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate void
freeQcomp(db_qcomp * qc,int doFree)957c478bd9Sstevel@tonic-gate freeQcomp(db_qcomp *qc, int doFree) {
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate if (qc == 0)
987c478bd9Sstevel@tonic-gate return;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate freeItem(qc->index_value);
1017c478bd9Sstevel@tonic-gate if (doFree)
1027c478bd9Sstevel@tonic-gate free(qc);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate db_query *
buildQuery(int num_components,db_qcomp * components)1067c478bd9Sstevel@tonic-gate buildQuery(int num_components, db_qcomp *components) {
1077c478bd9Sstevel@tonic-gate char *myself = "buildQuery";
1087c478bd9Sstevel@tonic-gate db_query *q = am(myself, sizeof (*q));
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate if (q == 0)
1117c478bd9Sstevel@tonic-gate return (0);
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate q->components.components_len = num_components;
1147c478bd9Sstevel@tonic-gate q->components.components_val = components;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate return (q);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate * Clone a db_query. The 'numComps' parameter can be used to specify
1217c478bd9Sstevel@tonic-gate * the number of db_qcomp's to allocate (in the 'components.components_val'
1227c478bd9Sstevel@tonic-gate * array), if 'components.components_len' hasn't yet reached its expected
1237c478bd9Sstevel@tonic-gate * maximum value.
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate db_query *
cloneQuery(db_query * old,int numComps)1267c478bd9Sstevel@tonic-gate cloneQuery(db_query *old, int numComps) {
1277c478bd9Sstevel@tonic-gate db_query *new;
1287c478bd9Sstevel@tonic-gate int i;
1297c478bd9Sstevel@tonic-gate char *myself = "cloneQuery";
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate if (old == 0)
1327c478bd9Sstevel@tonic-gate return (0);
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate new = am(myself, sizeof (*new));
1357c478bd9Sstevel@tonic-gate if (new == 0)
1367c478bd9Sstevel@tonic-gate return (0);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (old->components.components_len > numComps)
1397c478bd9Sstevel@tonic-gate numComps = old->components.components_len;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate new->components.components_val = am(myself,
1427c478bd9Sstevel@tonic-gate sizeof (new->components.components_val[0]) *
1437c478bd9Sstevel@tonic-gate numComps);
1447c478bd9Sstevel@tonic-gate if (numComps > 0 && new->components.components_val == 0) {
1457c478bd9Sstevel@tonic-gate free(new);
1467c478bd9Sstevel@tonic-gate return (0);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate for (i = 0; i < old->components.components_len; i++) {
1507c478bd9Sstevel@tonic-gate item *it;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate if (old->components.components_val[i].index_value == 0) {
1537c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = 0;
1547c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index =
1557c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index;
1567c478bd9Sstevel@tonic-gate continue;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate it = buildItem(old->components.components_val[i].index_value->
1607c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len,
1617c478bd9Sstevel@tonic-gate old->components.components_val[i].index_value->
1627c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val);
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate if (it == 0) {
1657c478bd9Sstevel@tonic-gate new->components.components_len = i + 1;
1667c478bd9Sstevel@tonic-gate freeQuery(new);
1677c478bd9Sstevel@tonic-gate return (0);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate new->components.components_val[i].index_value = it;
1717c478bd9Sstevel@tonic-gate new->components.components_val[i].which_index =
1727c478bd9Sstevel@tonic-gate old->components.components_val[i].which_index;
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate new->components.components_len = old->components.components_len;
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate return (new);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate void
freeQuery(db_query * q)1817c478bd9Sstevel@tonic-gate freeQuery(db_query *q) {
1827c478bd9Sstevel@tonic-gate int i;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate if (q == 0)
1857c478bd9Sstevel@tonic-gate return;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) {
1887c478bd9Sstevel@tonic-gate freeItem(q->components.components_val[i].index_value);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate sfree(q->components.components_val);
1927c478bd9Sstevel@tonic-gate sfree(q);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate void
freeQueries(db_query ** q,int numQ)1967c478bd9Sstevel@tonic-gate freeQueries(db_query **q, int numQ) {
1977c478bd9Sstevel@tonic-gate int i;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (q == 0)
2007c478bd9Sstevel@tonic-gate return;
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate for (i = 0; i < numQ; i++)
2037c478bd9Sstevel@tonic-gate freeQuery(q[i]);
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate sfree(q);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate * Given an array index[0..num-1] of pointers to strings of the form
2107c478bd9Sstevel@tonic-gate * "name=value", create the corresponding db_queries. "name=" indicates
2117c478bd9Sstevel@tonic-gate * deletion, which results in a db_query component where index_value == 0.
2127c478bd9Sstevel@tonic-gate *
2137c478bd9Sstevel@tonic-gate * The __nis_table_mapping_t structure is used to translate column
2147c478bd9Sstevel@tonic-gate * names to indices.
2157c478bd9Sstevel@tonic-gate *
2167c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, the searchable columns from the 'index'
2177c478bd9Sstevel@tonic-gate * name/value pairs are used to retrieve copies of the corresponding NIS+
2187c478bd9Sstevel@tonic-gate * entries, and '*rvP' is initialized with the current entry values
2197c478bd9Sstevel@tonic-gate * and object attributes. Names/values supplied in 'index' override
2207c478bd9Sstevel@tonic-gate * those from existing NIS+ entries.
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate db_query **
createQuery(int num,char ** index,__nis_table_mapping_t * t,__nis_rule_value_t ** rvP,int * numVals)2237c478bd9Sstevel@tonic-gate createQuery(int num, char **index, __nis_table_mapping_t *t,
2247c478bd9Sstevel@tonic-gate __nis_rule_value_t **rvP, int *numVals) {
2257c478bd9Sstevel@tonic-gate db_query **q;
2267c478bd9Sstevel@tonic-gate db_qcomp *qc;
2277c478bd9Sstevel@tonic-gate int i, j, n, a, nv, niv, stat, sinum;
2287c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvq;
2297c478bd9Sstevel@tonic-gate __nis_buffer_t b = {0, 0};
2307c478bd9Sstevel@tonic-gate char *table = 0;
2317c478bd9Sstevel@tonic-gate char *myself = "createQuery";
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate rvq = initRuleValue(1, 0);
2347c478bd9Sstevel@tonic-gate if (rvq == 0)
2357c478bd9Sstevel@tonic-gate return (0);
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate if (numVals == 0)
2387c478bd9Sstevel@tonic-gate numVals = &nv;
2397c478bd9Sstevel@tonic-gate *numVals = 0;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate if (rvP != 0) {
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate * Try to obtain a copy of the table object, in order to
2447c478bd9Sstevel@tonic-gate * determine the searchable columns. A failure isn't
2457c478bd9Sstevel@tonic-gate * necessarily fatal; we just try to compose the entire
2467c478bd9Sstevel@tonic-gate * LDAP data from the col=val pairs.
2477c478bd9Sstevel@tonic-gate */
2487c478bd9Sstevel@tonic-gate table = fullObjName(F, t->objName);
2497c478bd9Sstevel@tonic-gate if (table == 0) {
2507c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
2517c478bd9Sstevel@tonic-gate "%s: Error converting \"%s\" to FQ object name",
2527c478bd9Sstevel@tonic-gate myself, NIL(t->objName));
2537c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1);
2547c478bd9Sstevel@tonic-gate return (0);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /* Create a rule-value from the col=val pairs */
2597c478bd9Sstevel@tonic-gate for (n = 0; n < num; n++) {
2607c478bd9Sstevel@tonic-gate char *name;
2617c478bd9Sstevel@tonic-gate char *value;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if ((value = strchr(index[n], '=')) == 0) {
2647c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING,
2657c478bd9Sstevel@tonic-gate "%s: no '=' in \"%s\"",
2667c478bd9Sstevel@tonic-gate myself, index[n]);
2677c478bd9Sstevel@tonic-gate continue;
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate *value = '\0';
2717c478bd9Sstevel@tonic-gate value++;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate for (a = 0; a < t->numColumns; a++) {
2747c478bd9Sstevel@tonic-gate if (strcmp(index[n], t->column[a]) == 0) {
2757c478bd9Sstevel@tonic-gate int i, len = slen(value)+1;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate /* Add col=val pair to 'rvq' */
2787c478bd9Sstevel@tonic-gate if (addSCol2RuleValue(index[n], value, rvq)) {
2797c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1);
2807c478bd9Sstevel@tonic-gate sfree(table);
2817c478bd9Sstevel@tonic-gate return (0);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate break;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate if (a >= t->numColumns) {
2887c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING,
2897c478bd9Sstevel@tonic-gate "%s: Ignoring unknown column \"%s\"",
2907c478bd9Sstevel@tonic-gate myself, NIL(index[n]));
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * Find out if any of the columns specified via the 'index'
2967c478bd9Sstevel@tonic-gate * array are multi-valued.
2977c478bd9Sstevel@tonic-gate */
2987c478bd9Sstevel@tonic-gate for (n = 0, niv = 1; n < rvq->numColumns; n++) {
2997c478bd9Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1)
3007c478bd9Sstevel@tonic-gate niv *= rvq->colVal[n].numVals;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate *numVals = 1;
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate sfree(b.buf);
3067c478bd9Sstevel@tonic-gate sfree(table);
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (rvq->numColumns <= 0) {
3097c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals);
3107c478bd9Sstevel@tonic-gate *numVals = 0;
3117c478bd9Sstevel@tonic-gate return (0);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate * If any column name was repeated in the col=val pairs (but with
3167c478bd9Sstevel@tonic-gate * different values), 'rvq' will have one or more multi-valued
3177c478bd9Sstevel@tonic-gate * column values. We now convert those into an array of rule-values
3187c478bd9Sstevel@tonic-gate * where every column is single-valued.
3197c478bd9Sstevel@tonic-gate *
3207c478bd9Sstevel@tonic-gate * Since we want all combinations of column values, the number
3217c478bd9Sstevel@tonic-gate * of array elements is the product of all column value counts.
3227c478bd9Sstevel@tonic-gate *
3237c478bd9Sstevel@tonic-gate * There are four possible combinations of 'index' and NIS+ data:
3247c478bd9Sstevel@tonic-gate *
3257c478bd9Sstevel@tonic-gate * (1) Only single-valued 'index' columns, and at most one NIS+
3267c478bd9Sstevel@tonic-gate * entry, so 'rvq' is complete, and '*numVals' == 1.
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * (2) Single-valued 'index' columns, but multiple NIS+ entries.
3297c478bd9Sstevel@tonic-gate * '*numVals' reflects the number of NIS+ entries, and no
3307c478bd9Sstevel@tonic-gate * expansion of 'index' column values to array elements is
3317c478bd9Sstevel@tonic-gate * needed.
3327c478bd9Sstevel@tonic-gate *
3337c478bd9Sstevel@tonic-gate * (3) At least one multi-valued 'index', and multiple NIS+
3347c478bd9Sstevel@tonic-gate * entries. We already rejected the NIS+ data for this case
3357c478bd9Sstevel@tonic-gate * above, so it is in fact equivalent to case (4).
3367c478bd9Sstevel@tonic-gate *
3377c478bd9Sstevel@tonic-gate * (4) At least one multi-valued 'index', but at most one NIS+
3387c478bd9Sstevel@tonic-gate * entry. This is the case where we must expand the multi-valued
3397c478bd9Sstevel@tonic-gate * columns to multiple array elements.
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate if (niv > 1 && *numVals == 1) {
3427c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv;
3437c478bd9Sstevel@tonic-gate int repeat;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate /*
3467c478bd9Sstevel@tonic-gate * By using initRuleValue() to create 'rv', and make each
3477c478bd9Sstevel@tonic-gate * element a clone of 'rvq', we save a lot of code. The
3487c478bd9Sstevel@tonic-gate * down side is that 'rv' only really needs one element
3497c478bd9Sstevel@tonic-gate * for each rv[].colVal[].val array, but we know that at
3507c478bd9Sstevel@tonic-gate * least one rvq->colVal[].val array has more than one
3517c478bd9Sstevel@tonic-gate * element. Hence, making 'rv' a clone of 'rvq' will waste
3527c478bd9Sstevel@tonic-gate * memory.
3537c478bd9Sstevel@tonic-gate *
3547c478bd9Sstevel@tonic-gate * However, we believe this waste is acceptable, because
3557c478bd9Sstevel@tonic-gate * we expect that 'niv' will be small. Also, we are executing
3567c478bd9Sstevel@tonic-gate * in the context of a utility command, not in a daemon.
3577c478bd9Sstevel@tonic-gate */
3587c478bd9Sstevel@tonic-gate rv = initRuleValue(niv, rvq);
3597c478bd9Sstevel@tonic-gate if (rv == 0) {
3607c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1);
3617c478bd9Sstevel@tonic-gate *numVals = 0;
3627c478bd9Sstevel@tonic-gate return (0);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /*
3667c478bd9Sstevel@tonic-gate * For each column value in 'rvq', copy to the appropriate
3677c478bd9Sstevel@tonic-gate * place in 'rv', so that the end result is that all
3687c478bd9Sstevel@tonic-gate * combinations of values are enumerated, and each
3697c478bd9Sstevel@tonic-gate * 'rv[n].colVal[i]' is single-valued.
3707c478bd9Sstevel@tonic-gate *
3717c478bd9Sstevel@tonic-gate * We do this by traversing the rv[] array 'rvq->numColumns'
3727c478bd9Sstevel@tonic-gate * times, where each traversal 'i' works on the values
3737c478bd9Sstevel@tonic-gate * for rvq->colVal[i]. A repeat factor 'repeat' starts out
3747c478bd9Sstevel@tonic-gate * at '1', and is multiplied by 'rvq->colVal[i].numVals'
3757c478bd9Sstevel@tonic-gate * at the end of each traversal. Every value
3767c478bd9Sstevel@tonic-gate * rvq->colVal[i].val[j] is repeated 'repeat' times.
3777c478bd9Sstevel@tonic-gate *
3787c478bd9Sstevel@tonic-gate * This algorithm works by regarding the rv[] array as
3797c478bd9Sstevel@tonic-gate * an I-dimensional array (I = rvq->numColumns), where
3807c478bd9Sstevel@tonic-gate * each dimension 'i' corresponds to the values for
3817c478bd9Sstevel@tonic-gate * rvq->colVal[i]. The I-dimensional array is stored
3827c478bd9Sstevel@tonic-gate * in column-major order.
3837c478bd9Sstevel@tonic-gate *
3847c478bd9Sstevel@tonic-gate * Since the 'rv' elements start out as copies of 'rvq',
3857c478bd9Sstevel@tonic-gate * we achieve the "copy" of the 'rvq' column values by
3867c478bd9Sstevel@tonic-gate * deleting those we don't want from the 'rv' elements.
3877c478bd9Sstevel@tonic-gate */
3887c478bd9Sstevel@tonic-gate for (i = 0, repeat = 1; i < rvq->numColumns; i++) {
3897c478bd9Sstevel@tonic-gate int r, k;
3907c478bd9Sstevel@tonic-gate for (n = 0, j = 0, r = 0; n < niv; n++) {
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate * Free all but element 'j' of the
3937c478bd9Sstevel@tonic-gate * rv[n].colVal[i].val array.
3947c478bd9Sstevel@tonic-gate */
3957c478bd9Sstevel@tonic-gate for (k = 0; k < rv[n].colVal[i].numVals; k++) {
3967c478bd9Sstevel@tonic-gate /* Leave element 'j' in place */
3977c478bd9Sstevel@tonic-gate if (k == j)
3987c478bd9Sstevel@tonic-gate continue;
3997c478bd9Sstevel@tonic-gate sfree(rv[n].colVal[i].val[k].
4007c478bd9Sstevel@tonic-gate value);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate rv[n].colVal[i].numVals = 1;
4037c478bd9Sstevel@tonic-gate /* Move element 'j' to zero */
4047c478bd9Sstevel@tonic-gate if (j != 0)
4057c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[0] =
4067c478bd9Sstevel@tonic-gate rv[n].colVal[i].val[j];
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate * Increment the repeat index 'r'. If >=
4107c478bd9Sstevel@tonic-gate * 'repeat', reset 'r' and increment the
4117c478bd9Sstevel@tonic-gate * value index 'j'. If 'j' >=
4127c478bd9Sstevel@tonic-gate * rvq->colVal[i].numVals, start over on
4137c478bd9Sstevel@tonic-gate * the column values for column 'i' (i.e.,
4147c478bd9Sstevel@tonic-gate * reset 'j' to zero).
4157c478bd9Sstevel@tonic-gate */
4167c478bd9Sstevel@tonic-gate r += 1;
4177c478bd9Sstevel@tonic-gate if (r >= repeat) {
4187c478bd9Sstevel@tonic-gate r = 0;
4197c478bd9Sstevel@tonic-gate j += 1;
4207c478bd9Sstevel@tonic-gate if (j >= rvq->colVal[i].numVals)
4217c478bd9Sstevel@tonic-gate j = 0;
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate repeat *= rvq->colVal[i].numVals;
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate *numVals = niv;
4287c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1);
4297c478bd9Sstevel@tonic-gate rvq = rv;
4307c478bd9Sstevel@tonic-gate rv = 0;
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate q = am(myself, *numVals * sizeof (q[0]));
4347c478bd9Sstevel@tonic-gate if (q == 0) {
4357c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals);
4367c478bd9Sstevel@tonic-gate return (0);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate * Create queries from the rvq[] array.
4417c478bd9Sstevel@tonic-gate */
4427c478bd9Sstevel@tonic-gate for (a = 0; a < *numVals; a++) {
4437c478bd9Sstevel@tonic-gate int nn, err = 0;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate qc = am(myself, rvq[a].numColumns * sizeof (*qc));
4467c478bd9Sstevel@tonic-gate if (qc != 0) {
4477c478bd9Sstevel@tonic-gate for (nn = 0, i = 0; i < rvq[a].numColumns; i++) {
4487c478bd9Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) {
4497c478bd9Sstevel@tonic-gate if (strcmp(rvq[a].colName[i],
4507c478bd9Sstevel@tonic-gate t->column[j]) == 0) {
4517c478bd9Sstevel@tonic-gate break;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate if (j >= t->numColumns)
4557c478bd9Sstevel@tonic-gate continue;
4567c478bd9Sstevel@tonic-gate qc[nn].which_index = j;
4577c478bd9Sstevel@tonic-gate if (rvq[a].colVal[i].numVals > 0) {
4587c478bd9Sstevel@tonic-gate qc[nn].index_value = buildItem(
4597c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].length,
4607c478bd9Sstevel@tonic-gate rvq[a].colVal[i].val[0].value);
4617c478bd9Sstevel@tonic-gate if (qc[nn].index_value == 0)
4627c478bd9Sstevel@tonic-gate err++;
4637c478bd9Sstevel@tonic-gate } else {
4647c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
4657c478bd9Sstevel@tonic-gate "%s: No values for [%d]%s",
4667c478bd9Sstevel@tonic-gate myself, a, rvq[a].colName[i]);
4677c478bd9Sstevel@tonic-gate err++;
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate nn++;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate if (err == 0)
4727c478bd9Sstevel@tonic-gate q[a] = buildQuery(nn, qc);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate if (err > 0 || q[a] == 0) {
4757c478bd9Sstevel@tonic-gate freeQueries(q, a);
4767c478bd9Sstevel@tonic-gate for (a = 0; a < nn; a++)
4777c478bd9Sstevel@tonic-gate freeQcomp(&qc[a], F);
4787c478bd9Sstevel@tonic-gate sfree(qc);
4797c478bd9Sstevel@tonic-gate freeRuleValue(rvq, *numVals);
4807c478bd9Sstevel@tonic-gate return (0);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate if (rvP != 0) {
4857c478bd9Sstevel@tonic-gate *rvP = rvq;
4867c478bd9Sstevel@tonic-gate } else {
4877c478bd9Sstevel@tonic-gate freeRuleValue(rvq, 1);
4887c478bd9Sstevel@tonic-gate *numVals = 0;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate return (q);
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate void
printQuery(db_query * q,__nis_table_mapping_t * t)4957c478bd9Sstevel@tonic-gate printQuery(db_query *q, __nis_table_mapping_t *t) {
4967c478bd9Sstevel@tonic-gate int i, mc = -1;
4977c478bd9Sstevel@tonic-gate char *myself = "printQuery";
4987c478bd9Sstevel@tonic-gate char *val[NIS_MAXCOLUMNS];
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate if (q == 0)
5017c478bd9Sstevel@tonic-gate return;
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate (void) memset(val, 0, sizeof (val));
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate * Collect the values, which may be out of order in 'q'.
5077c478bd9Sstevel@tonic-gate * Remember the largest index.
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) {
5107c478bd9Sstevel@tonic-gate int ix = q->components.components_val[i].which_index;
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate if (ix >= NIS_MAXCOLUMNS ||
5137c478bd9Sstevel@tonic-gate (t != 0 && ix >= t->numColumns))
5147c478bd9Sstevel@tonic-gate continue;
5157c478bd9Sstevel@tonic-gate if (ix > mc)
5167c478bd9Sstevel@tonic-gate mc = ix;
5177c478bd9Sstevel@tonic-gate val[ix] = q->components.components_val[i].index_value->
5187c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate /* Print the values we collected */
5227c478bd9Sstevel@tonic-gate for (i = 0; i <= mc; i++) {
5237c478bd9Sstevel@tonic-gate p2buf(myself, "%s%s", (i != 0 ? " " : ""),
5247c478bd9Sstevel@tonic-gate (val[i] != 0 ? val[i] : ""));
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate /* If we printed anything, add a newline */
5277c478bd9Sstevel@tonic-gate if (mc >= 0)
5287c478bd9Sstevel@tonic-gate p2buf(myself, "\n");
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate * Verify that the db_query's 'q' and 'fq' match, in the sense that if
5337c478bd9Sstevel@tonic-gate * they both have a value for a certain index, the values are the same.
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate int
verifyQueryMatch(db_query * q,db_query * fq)5367c478bd9Sstevel@tonic-gate verifyQueryMatch(db_query *q, db_query *fq) {
5377c478bd9Sstevel@tonic-gate int i, j, match;
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate if (fq == 0)
5407c478bd9Sstevel@tonic-gate return (1);
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate if (q == 0)
5437c478bd9Sstevel@tonic-gate return ((fq == 0) ? 1 : 0);
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate for (i = 0, match = 1; match && i < q->components.components_len;
5467c478bd9Sstevel@tonic-gate i++) {
5477c478bd9Sstevel@tonic-gate for (j = 0; j < fq->components.components_len; j++) {
5487c478bd9Sstevel@tonic-gate int len, flen;
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate /* Same index ? */
5517c478bd9Sstevel@tonic-gate if (q->components.components_val[i].which_index !=
5527c478bd9Sstevel@tonic-gate fq->components.components_val[j].
5537c478bd9Sstevel@tonic-gate which_index)
5547c478bd9Sstevel@tonic-gate continue;
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate * If one 'index_value' is NULL, the other one must
5577c478bd9Sstevel@tonic-gate * be NULL as well.
5587c478bd9Sstevel@tonic-gate */
5597c478bd9Sstevel@tonic-gate if (q->components.components_val[i].index_value == 0) {
5607c478bd9Sstevel@tonic-gate if (fq->components.components_val[j].
5617c478bd9Sstevel@tonic-gate index_value == 0)
5627c478bd9Sstevel@tonic-gate continue;
5637c478bd9Sstevel@tonic-gate else {
5647c478bd9Sstevel@tonic-gate match = 0;
5657c478bd9Sstevel@tonic-gate break;
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate if (fq->components.components_val[j].index_value ==
5697c478bd9Sstevel@tonic-gate 0) {
5707c478bd9Sstevel@tonic-gate match = 0;
5717c478bd9Sstevel@tonic-gate break;
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate /* Same value lengths ? */
5747c478bd9Sstevel@tonic-gate len = q->components.components_val[i].index_value->
5757c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len;
5767c478bd9Sstevel@tonic-gate flen = fq->components.components_val[j].index_value->
5777c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len;
5787c478bd9Sstevel@tonic-gate if (len != flen) {
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate * There's a twist here: the input query
5817c478bd9Sstevel@tonic-gate * may well _not_ count a concluding NUL
5827c478bd9Sstevel@tonic-gate * in a string value, while the output
5837c478bd9Sstevel@tonic-gate * usually will. So, if the difference in
5847c478bd9Sstevel@tonic-gate * length is one, and the "extra" byte is
5857c478bd9Sstevel@tonic-gate * a zero-valued one, we accept equality.
5867c478bd9Sstevel@tonic-gate * 'q' is assumed to be the output, and
5877c478bd9Sstevel@tonic-gate * 'fq' the input.
5887c478bd9Sstevel@tonic-gate */
5897c478bd9Sstevel@tonic-gate if (!(len > 0 && len == (flen+1) &&
5907c478bd9Sstevel@tonic-gate q->components.components_val[i].
5917c478bd9Sstevel@tonic-gate index_value->
5927c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val[len-1] == 0)) {
5937c478bd9Sstevel@tonic-gate match = 0;
5947c478bd9Sstevel@tonic-gate break;
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate /* Same value ? */
5987c478bd9Sstevel@tonic-gate if (memcmp(q->components.components_val[i].index_value->
5997c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val,
6007c478bd9Sstevel@tonic-gate fq->components.components_val[j].index_value->
6017c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val,
6027c478bd9Sstevel@tonic-gate flen) != 0) {
6037c478bd9Sstevel@tonic-gate match = 0;
6047c478bd9Sstevel@tonic-gate break;
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate return (match);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate * Remove those queries in 'q' that don't match t->index.
6147c478bd9Sstevel@tonic-gate * Returns a pointer to the filtered array, which could be
6157c478bd9Sstevel@tonic-gate * a compacted version of the original, or a new copy; in
6167c478bd9Sstevel@tonic-gate * the latter case, the original will have been freed.
6177c478bd9Sstevel@tonic-gate *
6187c478bd9Sstevel@tonic-gate * Filtered/removed db_query's are freed.
6197c478bd9Sstevel@tonic-gate */
6207c478bd9Sstevel@tonic-gate db_query **
filterQuery(__nis_table_mapping_t * t,db_query ** q,db_query * qin,__nis_obj_attr_t *** objAttr,int * numQueries)6217c478bd9Sstevel@tonic-gate filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin,
6227c478bd9Sstevel@tonic-gate __nis_obj_attr_t ***objAttr, int *numQueries) {
6237c478bd9Sstevel@tonic-gate db_query **new;
6247c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr;
6257c478bd9Sstevel@tonic-gate int i, nq, nn;
6267c478bd9Sstevel@tonic-gate char *myself = "filterQuery";
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate if ((t == 0 && qin == 0) || q == 0 ||
6297c478bd9Sstevel@tonic-gate numQueries == 0 || *numQueries <= 0)
6307c478bd9Sstevel@tonic-gate return (q);
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate nq = *numQueries;
6337c478bd9Sstevel@tonic-gate new = am(myself, nq * sizeof (new[0]));
6347c478bd9Sstevel@tonic-gate if (objAttr != 0)
6357c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0]));
6367c478bd9Sstevel@tonic-gate else
6377c478bd9Sstevel@tonic-gate attr = 0;
6387c478bd9Sstevel@tonic-gate if (new == 0 || (objAttr != 0 && attr == 0)) {
6397c478bd9Sstevel@tonic-gate sfree(new);
6407c478bd9Sstevel@tonic-gate freeQueries(q, nq);
6417c478bd9Sstevel@tonic-gate sfree(attr);
6427c478bd9Sstevel@tonic-gate if (objAttr != 0) {
6437c478bd9Sstevel@tonic-gate freeObjAttr(*objAttr, nq);
6447c478bd9Sstevel@tonic-gate *objAttr = 0;
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate *numQueries = -1;
6477c478bd9Sstevel@tonic-gate return (0);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate for (i = 0, nn = 0; i < nq; i++) {
6517c478bd9Sstevel@tonic-gate int retain = 1;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate if (t != 0)
6547c478bd9Sstevel@tonic-gate retain = verifyIndexMatch(t, q[i], 0, 0, 0);
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate if (retain && qin != 0)
6577c478bd9Sstevel@tonic-gate retain = verifyQueryMatch(q[i], qin);
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate if (retain) {
6607c478bd9Sstevel@tonic-gate new[nn] = q[i];
6617c478bd9Sstevel@tonic-gate if (objAttr != 0)
6627c478bd9Sstevel@tonic-gate attr[nn] = (*objAttr)[i];
6637c478bd9Sstevel@tonic-gate nn++;
6647c478bd9Sstevel@tonic-gate } else {
6657c478bd9Sstevel@tonic-gate freeQuery(q[i]);
6667c478bd9Sstevel@tonic-gate q[i] = 0;
6677c478bd9Sstevel@tonic-gate if (objAttr != 0) {
6687c478bd9Sstevel@tonic-gate freeSingleObjAttr((*objAttr)[i]);
6697c478bd9Sstevel@tonic-gate (*objAttr)[i] = 0;
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate /* All q[i]'s are either in 'new', or have been deleted */
6757c478bd9Sstevel@tonic-gate free(q);
6767c478bd9Sstevel@tonic-gate if (objAttr != 0) {
6777c478bd9Sstevel@tonic-gate sfree(*objAttr);
6787c478bd9Sstevel@tonic-gate *objAttr = attr;
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate *numQueries = nn;
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate return (new);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate db_query **
createNisPlusEntry(__nis_table_mapping_t * t,__nis_rule_value_t * rv,db_query * qin,__nis_obj_attr_t *** objAttr,int * numQueries)6877c478bd9Sstevel@tonic-gate createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
6887c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr,
6897c478bd9Sstevel@tonic-gate int *numQueries) {
6907c478bd9Sstevel@tonic-gate db_query **query = 0;
6917c478bd9Sstevel@tonic-gate int r, i, j, ir;
6927c478bd9Sstevel@tonic-gate __nis_value_t *rval, *lval;
6937c478bd9Sstevel@tonic-gate __nis_mapping_item_t *litem;
6947c478bd9Sstevel@tonic-gate int numItems;
6957c478bd9Sstevel@tonic-gate int nq, iqc;
6967c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0;
6977c478bd9Sstevel@tonic-gate char **dn = 0;
6987c478bd9Sstevel@tonic-gate int numDN = 0;
6997c478bd9Sstevel@tonic-gate char *myself = "createNisPlusEntry";
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (t == 0 || t->objectDN == 0 || rv == 0)
7027c478bd9Sstevel@tonic-gate return (0);
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate /* Establish default, per-thread, search base */
7057c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base;
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) {
7087c478bd9Sstevel@tonic-gate int nrq, ntq, err;
7097c478bd9Sstevel@tonic-gate db_query **newq;
7107c478bd9Sstevel@tonic-gate __nis_obj_attr_t **newattr;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate rval = buildRvalue(&t->ruleFromLDAP[r]->rhs,
7137c478bd9Sstevel@tonic-gate mit_ldap, rv, NULL);
7147c478bd9Sstevel@tonic-gate if (rval == 0)
7157c478bd9Sstevel@tonic-gate continue;
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval,
7187c478bd9Sstevel@tonic-gate &numItems);
7197c478bd9Sstevel@tonic-gate if (litem == 0) {
7207c478bd9Sstevel@tonic-gate freeValue(rval, 1);
7217c478bd9Sstevel@tonic-gate /* XXX Should this be a fatal error ? */
7227c478bd9Sstevel@tonic-gate continue;
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate lval = 0;
7267c478bd9Sstevel@tonic-gate for (i = 0; i < numItems; i++) {
7277c478bd9Sstevel@tonic-gate __nis_value_t *tmpval, *old;
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate tmpval = getMappingItem(&litem[i],
7307c478bd9Sstevel@tonic-gate mit_nisplus, 0, 0, NULL);
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate * If the LHS specifies an out-of-context LDAP or
7347c478bd9Sstevel@tonic-gate * NIS+ item, we do the update right here. We
7357c478bd9Sstevel@tonic-gate * don't add any values to 'lval'; instead, we
7367c478bd9Sstevel@tonic-gate * skip to the next item. (However, we still
7377c478bd9Sstevel@tonic-gate * get a string representation of the LHS in case
7387c478bd9Sstevel@tonic-gate * we need to report an error.)
7397c478bd9Sstevel@tonic-gate */
740*36e852a1SRaja Andra if (litem[i].type == mit_ldap) {
7417c478bd9Sstevel@tonic-gate int stat;
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate if (dn == 0)
7447c478bd9Sstevel@tonic-gate dn = findDNs(myself, rv, 1,
7457c478bd9Sstevel@tonic-gate t->objectDN->write.base,
7467c478bd9Sstevel@tonic-gate &numDN);
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval,
7497c478bd9Sstevel@tonic-gate t->objectDN, dn, numDN);
7507c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) {
7517c478bd9Sstevel@tonic-gate char *iname = "<unknown>";
7527c478bd9Sstevel@tonic-gate
7537c478bd9Sstevel@tonic-gate if (tmpval != 0 &&
7547c478bd9Sstevel@tonic-gate tmpval->numVals == 1)
7557c478bd9Sstevel@tonic-gate iname = tmpval->val[0].value;
7567c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
7577c478bd9Sstevel@tonic-gate "%s: LDAP store \"%s\": %s",
7587c478bd9Sstevel@tonic-gate myself, iname,
7597c478bd9Sstevel@tonic-gate ldap_err2string(stat));
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate freeValue(tmpval, 1);
7637c478bd9Sstevel@tonic-gate continue;
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate old = lval;
7677c478bd9Sstevel@tonic-gate lval = concatenateValues(old, tmpval);
7687c478bd9Sstevel@tonic-gate freeValue(tmpval, 1);
7697c478bd9Sstevel@tonic-gate freeValue(old, 1);
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate freeMappingItem(litem, numItems);
7737c478bd9Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) {
7747c478bd9Sstevel@tonic-gate freeValue(lval, 1);
7757c478bd9Sstevel@tonic-gate freeValue(rval, 1);
7767c478bd9Sstevel@tonic-gate continue;
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate /*
7807c478bd9Sstevel@tonic-gate * We now have a number of possible cases. The notation
7817c478bd9Sstevel@tonic-gate * used in the table is:
7827c478bd9Sstevel@tonic-gate *
7837c478bd9Sstevel@tonic-gate * single A single value (numVals == 1)
7847c478bd9Sstevel@tonic-gate * single/rep A single value with repeat == 1
7857c478bd9Sstevel@tonic-gate * multi[N] N values
7867c478bd9Sstevel@tonic-gate * multi[N]/rep M values with repeat == 1
7877c478bd9Sstevel@tonic-gate * (M) M resulting db_query's
7887c478bd9Sstevel@tonic-gate *
7897c478bd9Sstevel@tonic-gate * lval \ rval single single/rep multi[N] multi[N]/rep
7907c478bd9Sstevel@tonic-gate * single (1) (1) (1) (1)
7917c478bd9Sstevel@tonic-gate * single/rep (1) (1) (N) (N)
7927c478bd9Sstevel@tonic-gate * multi[M] (1) (1) (1) 1+(N-1)/M
7937c478bd9Sstevel@tonic-gate * multi[M]/rep (1) (1) (1) 1+(N-1)/M
7947c478bd9Sstevel@tonic-gate *
7957c478bd9Sstevel@tonic-gate * Of course, we already have 'nq' db_query's from previous
7967c478bd9Sstevel@tonic-gate * rules, so the resulting number of queries is max(1,nq)
7977c478bd9Sstevel@tonic-gate * times the numbers in the table above.
7987c478bd9Sstevel@tonic-gate */
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate /* The number of queries resulting from the current rule */
8017c478bd9Sstevel@tonic-gate if (rval->numVals > 1) {
8027c478bd9Sstevel@tonic-gate if (lval->numVals == 1 && lval->repeat)
8037c478bd9Sstevel@tonic-gate nrq = rval->numVals;
8047c478bd9Sstevel@tonic-gate else if (lval->numVals > 1 && rval->repeat)
8057c478bd9Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/lval->numVals);
8067c478bd9Sstevel@tonic-gate else
8077c478bd9Sstevel@tonic-gate nrq = 1;
8087c478bd9Sstevel@tonic-gate } else {
8097c478bd9Sstevel@tonic-gate nrq = 1;
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate /* Total number of queries after adding the current rule */
8137c478bd9Sstevel@tonic-gate if (nq <= 0)
8147c478bd9Sstevel@tonic-gate ntq = nrq;
8157c478bd9Sstevel@tonic-gate else
8167c478bd9Sstevel@tonic-gate ntq = nq * nrq;
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate if (ntq > nq) {
8197c478bd9Sstevel@tonic-gate newq = realloc(query, ntq * sizeof (query[0]));
8207c478bd9Sstevel@tonic-gate newattr = realloc(attr, ntq * sizeof (attr[0]));
8217c478bd9Sstevel@tonic-gate if (newq == 0 || newattr == 0) {
8227c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR,
8237c478bd9Sstevel@tonic-gate "%s: realloc(%d) => NULL",
8247c478bd9Sstevel@tonic-gate myself, ntq * sizeof (query[0]));
8257c478bd9Sstevel@tonic-gate freeValue(lval, 1);
8267c478bd9Sstevel@tonic-gate freeValue(rval, 1);
8277c478bd9Sstevel@tonic-gate freeQueries(query, nq);
8287c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq);
8297c478bd9Sstevel@tonic-gate sfree(newq);
8307c478bd9Sstevel@tonic-gate freeDNs(dn, numDN);
8317c478bd9Sstevel@tonic-gate return (0);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate query = newq;
8347c478bd9Sstevel@tonic-gate attr = newattr;
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate /*
8387c478bd9Sstevel@tonic-gate * Copy/clone the existing queries to the new array,
8397c478bd9Sstevel@tonic-gate * remembering that realloc() has done the first 'nq'
8407c478bd9Sstevel@tonic-gate * ones.
8417c478bd9Sstevel@tonic-gate *
8427c478bd9Sstevel@tonic-gate * If there's an error (probably memory allocation), we
8437c478bd9Sstevel@tonic-gate * still go through the rest of the array, so that it's
8447c478bd9Sstevel@tonic-gate * simple to free the elements when we clean up.
8457c478bd9Sstevel@tonic-gate */
8467c478bd9Sstevel@tonic-gate for (i = 1, err = 0; i < nrq; i++) {
8477c478bd9Sstevel@tonic-gate for (j = 0; j < nq; j++) {
8487c478bd9Sstevel@tonic-gate query[(nq*i)+j] = cloneQuery(query[j],
8497c478bd9Sstevel@tonic-gate t->numColumns);
8507c478bd9Sstevel@tonic-gate if (query[(nq*i)+j] == 0 &&
8517c478bd9Sstevel@tonic-gate query[j] != 0)
8527c478bd9Sstevel@tonic-gate err++;
8537c478bd9Sstevel@tonic-gate attr[(nq*i)+j] = cloneObjAttr(attr[j]);
8547c478bd9Sstevel@tonic-gate if (attr[(nq*i)+j] == 0 &&
8557c478bd9Sstevel@tonic-gate attr[j] != 0)
8567c478bd9Sstevel@tonic-gate err++;
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate if (err > 0) {
8617c478bd9Sstevel@tonic-gate freeValue(lval, 1);
8627c478bd9Sstevel@tonic-gate freeValue(rval, 1);
8637c478bd9Sstevel@tonic-gate freeQueries(query, ntq);
8647c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq);
8657c478bd9Sstevel@tonic-gate freeDNs(dn, numDN);
8667c478bd9Sstevel@tonic-gate return (0);
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate * Special case if nq == 0 (i.e., the first time we
8717c478bd9Sstevel@tonic-gate * allocated db_query's). If so, we now allocate empty
8727c478bd9Sstevel@tonic-gate * db_qcomp arrays, which simplifies subsequent
8737c478bd9Sstevel@tonic-gate * copying of values.
8747c478bd9Sstevel@tonic-gate */
8757c478bd9Sstevel@tonic-gate if (nq <= 0) {
8767c478bd9Sstevel@tonic-gate (void) memset(query, 0, ntq * sizeof (query[0]));
8777c478bd9Sstevel@tonic-gate (void) memset(attr, 0, ntq * sizeof (attr[0]));
8787c478bd9Sstevel@tonic-gate for (i = 0, err = 0; i < ntq; i++) {
8797c478bd9Sstevel@tonic-gate query[i] = am(myself, sizeof (*query[i]));
8807c478bd9Sstevel@tonic-gate if (query[i] == 0) {
8817c478bd9Sstevel@tonic-gate err++;
8827c478bd9Sstevel@tonic-gate break;
8837c478bd9Sstevel@tonic-gate }
8847c478bd9Sstevel@tonic-gate query[i]->components.components_val =
8857c478bd9Sstevel@tonic-gate am(myself, t->numColumns *
8867c478bd9Sstevel@tonic-gate sizeof (query[i]->components.components_val[0]));
8877c478bd9Sstevel@tonic-gate if (query[i]->components.components_val == 0) {
8887c478bd9Sstevel@tonic-gate err++;
8897c478bd9Sstevel@tonic-gate break;
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate query[i]->components.components_len = 0;
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate if (err > 0) {
8947c478bd9Sstevel@tonic-gate freeValue(lval, 1);
8957c478bd9Sstevel@tonic-gate freeValue(rval, 1);
8967c478bd9Sstevel@tonic-gate freeQueries(query, ntq);
8977c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq);
8987c478bd9Sstevel@tonic-gate freeDNs(dn, numDN);
8997c478bd9Sstevel@tonic-gate return (0);
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate /* Now we're ready to add the new values */
9047c478bd9Sstevel@tonic-gate for (i = 0, ir = 0; i < lval->numVals; i++) {
9057c478bd9Sstevel@tonic-gate char *oaName = 0;
9067c478bd9Sstevel@tonic-gate int index;
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate /* Find column index */
9097c478bd9Sstevel@tonic-gate for (index = 0; index < t->numColumns;
9107c478bd9Sstevel@tonic-gate index++) {
9117c478bd9Sstevel@tonic-gate if (strncmp(t->column[index],
9127c478bd9Sstevel@tonic-gate lval->val[i].value,
9137c478bd9Sstevel@tonic-gate lval->val[i].length) == 0)
9147c478bd9Sstevel@tonic-gate break;
9157c478bd9Sstevel@tonic-gate }
9167c478bd9Sstevel@tonic-gate if (index >= t->numColumns) {
9177c478bd9Sstevel@tonic-gate /*
9187c478bd9Sstevel@tonic-gate * Could be one of the special object
9197c478bd9Sstevel@tonic-gate * attributes.
9207c478bd9Sstevel@tonic-gate */
9217c478bd9Sstevel@tonic-gate oaName = isObjAttr(&lval->val[i]);
9227c478bd9Sstevel@tonic-gate if (oaName == 0)
9237c478bd9Sstevel@tonic-gate continue;
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate for (j = i*nrq; j < (i+1)*nrq; j++) {
9277c478bd9Sstevel@tonic-gate int k;
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate /* If we're out of values, repeat last one */
9307c478bd9Sstevel@tonic-gate ir = (j < rval->numVals) ?
9317c478bd9Sstevel@tonic-gate j : rval->numVals - 1;
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate * Step through the query array, adding
9357c478bd9Sstevel@tonic-gate * the new value every 'nrq' queries, and
9367c478bd9Sstevel@tonic-gate * starting at 'query[j % nrq]'.
9377c478bd9Sstevel@tonic-gate */
9387c478bd9Sstevel@tonic-gate for (k = j % nrq, err = 0; k < ntq; k += nrq) {
9397c478bd9Sstevel@tonic-gate int ic, c;
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate if (oaName != 0) {
9427c478bd9Sstevel@tonic-gate int fail = setObjAttrField(
9437c478bd9Sstevel@tonic-gate oaName,
9447c478bd9Sstevel@tonic-gate &rval->val[ir],
9457c478bd9Sstevel@tonic-gate &attr[k]);
9467c478bd9Sstevel@tonic-gate if (fail) {
9477c478bd9Sstevel@tonic-gate err++;
9487c478bd9Sstevel@tonic-gate break;
9497c478bd9Sstevel@tonic-gate }
9507c478bd9Sstevel@tonic-gate continue;
9517c478bd9Sstevel@tonic-gate }
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate ic = query[k]->components.
9547c478bd9Sstevel@tonic-gate components_len;
9557c478bd9Sstevel@tonic-gate /*
9567c478bd9Sstevel@tonic-gate * If we've already filled this
9577c478bd9Sstevel@tonic-gate * query, the new value is a dup
9587c478bd9Sstevel@tonic-gate * which we'll ignore.
9597c478bd9Sstevel@tonic-gate */
9607c478bd9Sstevel@tonic-gate if (ic >= t->numColumns)
9617c478bd9Sstevel@tonic-gate continue;
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate * Do we already have a value for
9657c478bd9Sstevel@tonic-gate * this 'index' ?
9667c478bd9Sstevel@tonic-gate */
9677c478bd9Sstevel@tonic-gate for (c = 0; c < ic; c++) {
9687c478bd9Sstevel@tonic-gate if (query[k]->components.
9697c478bd9Sstevel@tonic-gate components_val[c].
9707c478bd9Sstevel@tonic-gate which_index == index)
9717c478bd9Sstevel@tonic-gate break;
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate /* If no previous value, add it */
9757c478bd9Sstevel@tonic-gate if (c >= ic) {
9767c478bd9Sstevel@tonic-gate int l;
9777c478bd9Sstevel@tonic-gate char *v;
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate query[k]->components.
9807c478bd9Sstevel@tonic-gate components_val[ic].
9817c478bd9Sstevel@tonic-gate which_index = index;
9827c478bd9Sstevel@tonic-gate l = rval->val[ir].length;
9837c478bd9Sstevel@tonic-gate v = rval->val[ir].value;
9847c478bd9Sstevel@tonic-gate if (rval->type == vt_string &&
9857c478bd9Sstevel@tonic-gate l > 0 &&
9867c478bd9Sstevel@tonic-gate v[l-1] != '\0' &&
9877c478bd9Sstevel@tonic-gate v[l] == '\0')
9887c478bd9Sstevel@tonic-gate l++;
9897c478bd9Sstevel@tonic-gate query[k]->components.
9907c478bd9Sstevel@tonic-gate components_val[ic].
9917c478bd9Sstevel@tonic-gate index_value =
9927c478bd9Sstevel@tonic-gate buildItem(l, v);
9937c478bd9Sstevel@tonic-gate if (query[k]->
9947c478bd9Sstevel@tonic-gate components.
9957c478bd9Sstevel@tonic-gate components_val[ic].
9967c478bd9Sstevel@tonic-gate index_value == 0) {
9977c478bd9Sstevel@tonic-gate err++;
9987c478bd9Sstevel@tonic-gate break;
9997c478bd9Sstevel@tonic-gate }
10007c478bd9Sstevel@tonic-gate query[k]->components.
10017c478bd9Sstevel@tonic-gate components_len++;
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate if (err > 0) {
10057c478bd9Sstevel@tonic-gate freeValue(lval, 1);
10067c478bd9Sstevel@tonic-gate freeValue(rval, 1);
10077c478bd9Sstevel@tonic-gate freeQueries(query, ntq);
10087c478bd9Sstevel@tonic-gate freeObjAttr(attr, ntq);
10097c478bd9Sstevel@tonic-gate freeDNs(dn, numDN);
10107c478bd9Sstevel@tonic-gate return (0);
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate }
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate freeValue(lval, 1);
10157c478bd9Sstevel@tonic-gate freeValue(rval, 1);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate nq = ntq;
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate freeDNs(dn, numDN);
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate if (nq <= 0) {
10237c478bd9Sstevel@tonic-gate sfree(query);
10247c478bd9Sstevel@tonic-gate query = 0;
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate /* Should we filter on index or input query ? */
10287c478bd9Sstevel@tonic-gate if (query != 0) {
10297c478bd9Sstevel@tonic-gate if (t->index.numIndexes > 0)
10307c478bd9Sstevel@tonic-gate query = filterQuery(t, query, qin, &attr, &nq);
10317c478bd9Sstevel@tonic-gate else if (qin != 0)
10327c478bd9Sstevel@tonic-gate query = filterQuery(0, query, qin, &attr, &nq);
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate
10357c478bd9Sstevel@tonic-gate if (query != 0 && numQueries != 0)
10367c478bd9Sstevel@tonic-gate *numQueries = nq;
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate if (objAttr != 0)
10397c478bd9Sstevel@tonic-gate *objAttr = attr;
10407c478bd9Sstevel@tonic-gate else
10417c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq);
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate return (query);
10447c478bd9Sstevel@tonic-gate }
10457c478bd9Sstevel@tonic-gate /*
10467c478bd9Sstevel@tonic-gate * Given a table mapping and a rule-value, convert to an array of
10477c478bd9Sstevel@tonic-gate * (db_query *), using the fromLDAP ruleset.
10487c478bd9Sstevel@tonic-gate *
10497c478bd9Sstevel@tonic-gate * On entry, '*numQueries' holds the number of elements in the 'rv'
10507c478bd9Sstevel@tonic-gate * array. On exit, it holds the number of (db_query *)'s in the return
10517c478bd9Sstevel@tonic-gate * value array.
10527c478bd9Sstevel@tonic-gate */
10537c478bd9Sstevel@tonic-gate db_query **
ruleValue2Query(__nis_table_mapping_t * t,__nis_rule_value_t * rv,db_query * qin,__nis_obj_attr_t *** objAttr,int * numQueries)10547c478bd9Sstevel@tonic-gate ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
10557c478bd9Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) {
10567c478bd9Sstevel@tonic-gate db_query **q = 0, ***qp = 0;
10577c478bd9Sstevel@tonic-gate int i, nqp, nq, *nnp = 0, nv;
10587c478bd9Sstevel@tonic-gate __nis_obj_attr_t **attr = 0, ***atp = 0;
10597c478bd9Sstevel@tonic-gate char *myself = "ruleValue2Query";
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate if (t == 0 || rv == 0 || numQueries == 0)
10637c478bd9Sstevel@tonic-gate return (0);
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate nv = *numQueries;
10667c478bd9Sstevel@tonic-gate if (nv <= 0)
10677c478bd9Sstevel@tonic-gate return (0);
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /*
10707c478bd9Sstevel@tonic-gate * 'qp' is an array of (db_query **), and we get one element for
10717c478bd9Sstevel@tonic-gate * each call to createNisPlusEntry(); i.e., one for each rule-value.
10727c478bd9Sstevel@tonic-gate *
10737c478bd9Sstevel@tonic-gate * 'nnp[i]' is the count of (db_query *) in each 'qp[i]'.
10747c478bd9Sstevel@tonic-gate */
10757c478bd9Sstevel@tonic-gate qp = am(myself, nv * sizeof (*qp));
10767c478bd9Sstevel@tonic-gate nnp = am(myself, nv * sizeof (*nnp));
10777c478bd9Sstevel@tonic-gate atp = am(myself, nv * sizeof (*atp));
10787c478bd9Sstevel@tonic-gate if (qp == 0 || nnp == 0 || atp == 0) {
10797c478bd9Sstevel@tonic-gate sfree(qp);
10807c478bd9Sstevel@tonic-gate sfree(nnp);
10817c478bd9Sstevel@tonic-gate sfree(atp);
10827c478bd9Sstevel@tonic-gate return (0);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate for (i = 0, nq = 0, nqp = 0; i < nv; i++) {
10867c478bd9Sstevel@tonic-gate qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp],
10877c478bd9Sstevel@tonic-gate &nnp[nqp]);
10887c478bd9Sstevel@tonic-gate /* If we fail, abort (XXX??? or continue ???) */
10897c478bd9Sstevel@tonic-gate if (qp[nqp] == 0)
10907c478bd9Sstevel@tonic-gate goto cleanup;
10917c478bd9Sstevel@tonic-gate nq += nnp[nqp];
10927c478bd9Sstevel@tonic-gate nqp++;
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate /* If we didn't get any (db_query **)'s, return failure */
10967c478bd9Sstevel@tonic-gate if (nqp == 0 || nq <= 0)
10977c478bd9Sstevel@tonic-gate goto cleanup;
10987c478bd9Sstevel@tonic-gate
10997c478bd9Sstevel@tonic-gate q = am(myself, nq * sizeof (q[0]));
11007c478bd9Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0]));
11017c478bd9Sstevel@tonic-gate if (q == 0 || attr == 0) {
11027c478bd9Sstevel@tonic-gate nq = 0;
11037c478bd9Sstevel@tonic-gate goto cleanup;
11047c478bd9Sstevel@tonic-gate }
11057c478bd9Sstevel@tonic-gate
11067c478bd9Sstevel@tonic-gate /* Convert 'qp' to an array of (db_query *)'s */
11077c478bd9Sstevel@tonic-gate for (i = 0, nq = 0; i < nqp; i++) {
11087c478bd9Sstevel@tonic-gate (void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0]));
11097c478bd9Sstevel@tonic-gate (void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0]));
11107c478bd9Sstevel@tonic-gate nq += nnp[i];
11117c478bd9Sstevel@tonic-gate free(qp[i]);
11127c478bd9Sstevel@tonic-gate free(atp[i]);
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate *numQueries = nq;
11167c478bd9Sstevel@tonic-gate if (objAttr != 0)
11177c478bd9Sstevel@tonic-gate *objAttr = attr;
11187c478bd9Sstevel@tonic-gate else
11197c478bd9Sstevel@tonic-gate freeObjAttr(attr, nq);
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate /* Make sure 'cleanup' doesn't free the db_query pointers */
11227c478bd9Sstevel@tonic-gate nqp = 0;
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate cleanup:
11257c478bd9Sstevel@tonic-gate for (i = 0; i < nqp; i++) {
11267c478bd9Sstevel@tonic-gate freeQueries(qp[i], nnp[i]);
11277c478bd9Sstevel@tonic-gate sfree(atp[i]);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate sfree(qp);
11307c478bd9Sstevel@tonic-gate sfree(nnp);
11317c478bd9Sstevel@tonic-gate sfree(atp);
11327c478bd9Sstevel@tonic-gate
11337c478bd9Sstevel@tonic-gate return (q);
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate db_query *
pseudoEntryObj2Query(entry_obj * e,nis_object * tobj,__nis_rule_value_t * rv)11377c478bd9Sstevel@tonic-gate pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) {
11387c478bd9Sstevel@tonic-gate db_query *qbuf;
11397c478bd9Sstevel@tonic-gate db_qcomp *qcbuf;
11407c478bd9Sstevel@tonic-gate int nc, i;
11417c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvt = 0;
11427c478bd9Sstevel@tonic-gate char *myself = "pseudoEntryObj2Query";
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate nc = e->en_cols.en_cols_len - 1;
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS)
11477c478bd9Sstevel@tonic-gate return (0);
11487c478bd9Sstevel@tonic-gate
11497c478bd9Sstevel@tonic-gate /*
11507c478bd9Sstevel@tonic-gate * If 'rvP' is non-NULL, build a rule value from the pseudo-
11517c478bd9Sstevel@tonic-gate * nis_object in e->en_cols.en_cols_val[0].
11527c478bd9Sstevel@tonic-gate */
11537c478bd9Sstevel@tonic-gate if (rv != 0) {
11547c478bd9Sstevel@tonic-gate nis_object *o;
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate o = unmakePseudoEntryObj(e, tobj);
11577c478bd9Sstevel@tonic-gate if (o == 0)
11587c478bd9Sstevel@tonic-gate return (0);
11597c478bd9Sstevel@tonic-gate rvt = addObjAttr2RuleValue(o, 0);
11607c478bd9Sstevel@tonic-gate nis_destroy_object(o);
11617c478bd9Sstevel@tonic-gate if (rvt == 0)
11627c478bd9Sstevel@tonic-gate return (0);
11637c478bd9Sstevel@tonic-gate }
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate qbuf = am(myself, sizeof (*qbuf));
11667c478bd9Sstevel@tonic-gate /*
11677c478bd9Sstevel@tonic-gate * If there are no columns (other than the pseudo-entry object),
11687c478bd9Sstevel@tonic-gate * we're done.
11697c478bd9Sstevel@tonic-gate */
11707c478bd9Sstevel@tonic-gate if (nc == 0)
11717c478bd9Sstevel@tonic-gate return (qbuf);
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate qcbuf = am(myself, nc * sizeof (*qcbuf));
11747c478bd9Sstevel@tonic-gate if (qcbuf == 0) {
11757c478bd9Sstevel@tonic-gate sfree(qcbuf);
11767c478bd9Sstevel@tonic-gate if (rvt != 0)
11777c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1);
11787c478bd9Sstevel@tonic-gate return (0);
11797c478bd9Sstevel@tonic-gate }
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate /*
11827c478bd9Sstevel@tonic-gate * Build the db_query, remembering that e->en_cols.en_cols_val[0]
11837c478bd9Sstevel@tonic-gate * is the pseudo-nis_object.
11847c478bd9Sstevel@tonic-gate */
11857c478bd9Sstevel@tonic-gate qbuf->components.components_val = qcbuf;
11867c478bd9Sstevel@tonic-gate qbuf->components.components_len = nc;
11877c478bd9Sstevel@tonic-gate for (i = 0; i < nc; i++) {
11887c478bd9Sstevel@tonic-gate qcbuf[i].which_index = i;
11897c478bd9Sstevel@tonic-gate qcbuf[i].index_value = buildItem(
11907c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_len,
11917c478bd9Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_val);
11927c478bd9Sstevel@tonic-gate if (qcbuf[i].index_value == 0) {
11937c478bd9Sstevel@tonic-gate freeQuery(qbuf);
11947c478bd9Sstevel@tonic-gate if (rvt != 0)
11957c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1);
11967c478bd9Sstevel@tonic-gate return (0);
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate if (rvt != 0) {
12017c478bd9Sstevel@tonic-gate *rv = *rvt;
12027c478bd9Sstevel@tonic-gate sfree(rvt);
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate return (qbuf);
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gate /*
12097c478bd9Sstevel@tonic-gate * Given an input query 'q', and a db_query work buffer 'qbuf', return
12107c478bd9Sstevel@tonic-gate * a pointer to a query with one component corresponding to component
12117c478bd9Sstevel@tonic-gate * 'index' in 'q'.
12127c478bd9Sstevel@tonic-gate *
12137c478bd9Sstevel@tonic-gate * Note that no memory is allocated, and that the returned query has
12147c478bd9Sstevel@tonic-gate * pointers into 'q'.
12157c478bd9Sstevel@tonic-gate */
12167c478bd9Sstevel@tonic-gate db_query *
queryFromComponent(db_query * q,int index,db_query * qbuf)12177c478bd9Sstevel@tonic-gate queryFromComponent(db_query *q, int index, db_query *qbuf) {
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate if (q == 0 || index < 0 || index >= q->components.components_len ||
12207c478bd9Sstevel@tonic-gate qbuf == 0)
12217c478bd9Sstevel@tonic-gate return (0);
12227c478bd9Sstevel@tonic-gate
12237c478bd9Sstevel@tonic-gate qbuf->components.components_len = 1;
12247c478bd9Sstevel@tonic-gate qbuf->components.components_val = &q->components.components_val[index];
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate return (qbuf);
12277c478bd9Sstevel@tonic-gate }
1228