1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * 3*0Sstevel@tonic-gate * Portions Copyright %G% Sun Microsystems, Inc. 4*0Sstevel@tonic-gate * All Rights Reserved 5*0Sstevel@tonic-gate * 6*0Sstevel@tonic-gate */ 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gate /* 11*0Sstevel@tonic-gate * Copyright (c) 1993, 1994 Regents of the University of Michigan. 12*0Sstevel@tonic-gate * All rights reserved. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 15*0Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given 16*0Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University 17*0Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 18*0Sstevel@tonic-gate * software without specific prior written permission. This software 19*0Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty. 20*0Sstevel@tonic-gate * 21*0Sstevel@tonic-gate * searchpref.c: search preferences library routines for LDAP clients 22*0Sstevel@tonic-gate * 17 May 1994 by Gordon Good 23*0Sstevel@tonic-gate */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate #include <stdio.h> 26*0Sstevel@tonic-gate #include <ctype.h> 27*0Sstevel@tonic-gate #include <string.h> 28*0Sstevel@tonic-gate #include <stdlib.h> 29*0Sstevel@tonic-gate #ifdef MACOS 30*0Sstevel@tonic-gate #include "macos.h" 31*0Sstevel@tonic-gate #else /* MACOS */ 32*0Sstevel@tonic-gate #ifdef DOS 33*0Sstevel@tonic-gate #include <malloc.h> 34*0Sstevel@tonic-gate #include "msdos.h" 35*0Sstevel@tonic-gate #else /* DOS */ 36*0Sstevel@tonic-gate #include <sys/types.h> 37*0Sstevel@tonic-gate #include <sys/file.h> 38*0Sstevel@tonic-gate #ifndef VMS 39*0Sstevel@tonic-gate #include <unistd.h> 40*0Sstevel@tonic-gate #endif /* VMS */ 41*0Sstevel@tonic-gate #endif /* DOS */ 42*0Sstevel@tonic-gate #endif /* MACOS */ 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #include "lber.h" 45*0Sstevel@tonic-gate #include "ldap.h" 46*0Sstevel@tonic-gate #include "ldap-private.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #ifndef NEEDPROTOS 49*0Sstevel@tonic-gate int next_line_tokens(); 50*0Sstevel@tonic-gate void free_strarray(); 51*0Sstevel@tonic-gate static void free_searchobj(); 52*0Sstevel@tonic-gate static int read_next_searchobj(); 53*0Sstevel@tonic-gate #else /* !NEEDPROTOS */ 54*0Sstevel@tonic-gate int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp ); 55*0Sstevel@tonic-gate void free_strarray( char **sap ); 56*0Sstevel@tonic-gate static void free_searchobj( struct ldap_searchobj *so ); 57*0Sstevel@tonic-gate static int read_next_searchobj( char **bufp, ssize_t *blenp, 58*0Sstevel@tonic-gate struct ldap_searchobj **sop, int soversion ); 59*0Sstevel@tonic-gate #endif /* !NEEDPROTOS */ 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate static char *sobjoptions[] = { 63*0Sstevel@tonic-gate "internal", 64*0Sstevel@tonic-gate NULL 65*0Sstevel@tonic-gate }; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate static unsigned int sobjoptvals[] = { 69*0Sstevel@tonic-gate LDAP_SEARCHOBJ_OPT_INTERNAL, 70*0Sstevel@tonic-gate }; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate int 74*0Sstevel@tonic-gate ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp ) 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate FILE *fp; 77*0Sstevel@tonic-gate char *buf; 78*0Sstevel@tonic-gate ssize_t rlen, len; 79*0Sstevel@tonic-gate int rc, eof; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate if (( fp = fopen( file, "r" )) == NULL ) { 82*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_FILE ); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ 86*0Sstevel@tonic-gate fclose( fp ); 87*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_FILE ); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate len = ftell( fp ); 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ 93*0Sstevel@tonic-gate fclose( fp ); 94*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_FILE ); 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate if (( buf = malloc( (size_t)len )) == NULL ) { 98*0Sstevel@tonic-gate fclose( fp ); 99*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_MEM ); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate rlen = fread( buf, (size_t) 1, (size_t)len, fp ); 103*0Sstevel@tonic-gate eof = feof( fp ); 104*0Sstevel@tonic-gate fclose( fp ); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate if ( rlen != len && !eof ) { /* error: didn't get the whole file */ 107*0Sstevel@tonic-gate free( buf ); 108*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_FILE ); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate rc = ldap_init_searchprefs_buf( buf, rlen, solistp ); 112*0Sstevel@tonic-gate free( buf ); 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate return( rc ); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate int 119*0Sstevel@tonic-gate ldap_init_searchprefs_buf( char *buf, ssize_t buflen, 120*0Sstevel@tonic-gate struct ldap_searchobj **solistp ) 121*0Sstevel@tonic-gate { 122*0Sstevel@tonic-gate int rc, version; 123*0Sstevel@tonic-gate char **toks; 124*0Sstevel@tonic-gate struct ldap_searchobj *prevso, *so; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate *solistp = prevso = NULLSEARCHOBJ; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate if ( next_line_tokens( &buf, &buflen, &toks ) != 2 || 129*0Sstevel@tonic-gate strcasecmp( toks[ 0 ], "version" ) != 0 ) { 130*0Sstevel@tonic-gate free_strarray( toks ); 131*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate version = atoi( toks[ 1 ] ); 134*0Sstevel@tonic-gate free_strarray( toks ); 135*0Sstevel@tonic-gate if ( version != LDAP_SEARCHPREF_VERSION && 136*0Sstevel@tonic-gate version != LDAP_SEARCHPREF_VERSION_ZERO ) { 137*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_VERSION ); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so, 141*0Sstevel@tonic-gate version )) == 0 && so != NULLSEARCHOBJ ) { 142*0Sstevel@tonic-gate if ( prevso == NULLSEARCHOBJ ) { 143*0Sstevel@tonic-gate *solistp = so; 144*0Sstevel@tonic-gate } else { 145*0Sstevel@tonic-gate prevso->so_next = so; 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate prevso = so; 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate if ( rc != 0 ) { 151*0Sstevel@tonic-gate ldap_free_searchprefs( *solistp ); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate return( rc ); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate void 160*0Sstevel@tonic-gate ldap_free_searchprefs( struct ldap_searchobj *solist ) 161*0Sstevel@tonic-gate { 162*0Sstevel@tonic-gate struct ldap_searchobj *so, *nextso; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if ( solist != NULL ) { 165*0Sstevel@tonic-gate for ( so = solist; so != NULL; so = nextso ) { 166*0Sstevel@tonic-gate nextso = so->so_next; 167*0Sstevel@tonic-gate free_searchobj( so ); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate /* XXX XXX need to do some work here */ 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate static void 175*0Sstevel@tonic-gate free_searchobj( struct ldap_searchobj *so ) 176*0Sstevel@tonic-gate { 177*0Sstevel@tonic-gate if ( so != NULL ) { 178*0Sstevel@tonic-gate if ( so->so_objtypeprompt != NULL ) { 179*0Sstevel@tonic-gate free( so->so_objtypeprompt ); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate if ( so->so_prompt != NULL ) { 182*0Sstevel@tonic-gate free( so->so_prompt ); 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate if ( so->so_filterprefix != NULL ) { 185*0Sstevel@tonic-gate free( so->so_filterprefix ); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate if ( so->so_filtertag != NULL ) { 188*0Sstevel@tonic-gate free( so->so_filtertag ); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate if ( so->so_defaultselectattr != NULL ) { 191*0Sstevel@tonic-gate free( so->so_defaultselectattr ); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate if ( so->so_defaultselecttext != NULL ) { 194*0Sstevel@tonic-gate free( so->so_defaultselecttext ); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate if ( so->so_salist != NULL ) { 197*0Sstevel@tonic-gate struct ldap_searchattr *sa, *nextsa; 198*0Sstevel@tonic-gate for ( sa = so->so_salist; sa != NULL; sa = nextsa ) { 199*0Sstevel@tonic-gate nextsa = sa->sa_next; 200*0Sstevel@tonic-gate if ( sa->sa_attrlabel != NULL ) { 201*0Sstevel@tonic-gate free( sa->sa_attrlabel ); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate if ( sa->sa_attr != NULL ) { 204*0Sstevel@tonic-gate free( sa->sa_attr ); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate if ( sa->sa_selectattr != NULL ) { 207*0Sstevel@tonic-gate free( sa->sa_selectattr ); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate if ( sa->sa_selecttext != NULL ) { 210*0Sstevel@tonic-gate free( sa->sa_selecttext ); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate free( sa ); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate if ( so->so_smlist != NULL ) { 216*0Sstevel@tonic-gate struct ldap_searchmatch *sm, *nextsm; 217*0Sstevel@tonic-gate for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) { 218*0Sstevel@tonic-gate nextsm = sm->sm_next; 219*0Sstevel@tonic-gate if ( sm->sm_matchprompt != NULL ) { 220*0Sstevel@tonic-gate free( sm->sm_matchprompt ); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate if ( sm->sm_filter != NULL ) { 223*0Sstevel@tonic-gate free( sm->sm_filter ); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate free( sm ); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate free( so ); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate struct ldap_searchobj * 235*0Sstevel@tonic-gate ldap_first_searchobj( struct ldap_searchobj *solist ) 236*0Sstevel@tonic-gate { 237*0Sstevel@tonic-gate return( solist ); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate struct ldap_searchobj * 242*0Sstevel@tonic-gate ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so ) 243*0Sstevel@tonic-gate { 244*0Sstevel@tonic-gate return( so == NULLSEARCHOBJ ? so : so->so_next ); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate static int 250*0Sstevel@tonic-gate read_next_searchobj( char **bufp, ssize_t *blenp, struct ldap_searchobj **sop, 251*0Sstevel@tonic-gate int soversion ) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate int i, j, tokcnt; 254*0Sstevel@tonic-gate char **toks; 255*0Sstevel@tonic-gate struct ldap_searchobj *so; 256*0Sstevel@tonic-gate struct ldap_searchattr **sa; 257*0Sstevel@tonic-gate struct ldap_searchmatch **sm; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate *sop = NULL; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * Object type prompt comes first 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 265*0Sstevel@tonic-gate free_strarray( toks ); 266*0Sstevel@tonic-gate return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX ); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate if (( so = (struct ldap_searchobj *)calloc( (size_t) 1, 270*0Sstevel@tonic-gate sizeof( struct ldap_searchobj ))) == NULL ) { 271*0Sstevel@tonic-gate free_strarray( toks ); 272*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_MEM ); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate so->so_objtypeprompt = toks[ 0 ]; 275*0Sstevel@tonic-gate free( (char *)toks ); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * if this is post-version zero, options come next 279*0Sstevel@tonic-gate */ 280*0Sstevel@tonic-gate if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) { 281*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) { 282*0Sstevel@tonic-gate free_strarray( toks ); 283*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 284*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate for ( i = 0; toks[ i ] != NULL; ++i ) { 287*0Sstevel@tonic-gate for ( j = 0; sobjoptions[ j ] != NULL; ++j ) { 288*0Sstevel@tonic-gate if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) { 289*0Sstevel@tonic-gate so->so_options |= sobjoptvals[ j ]; 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate free_strarray( toks ); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* 297*0Sstevel@tonic-gate * "Fewer choices" prompt is next 298*0Sstevel@tonic-gate */ 299*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 300*0Sstevel@tonic-gate free_strarray( toks ); 301*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 302*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate so->so_prompt = toks[ 0 ]; 305*0Sstevel@tonic-gate free( (char *)toks ); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * Filter prefix for "More Choices" searching is next 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 311*0Sstevel@tonic-gate free_strarray( toks ); 312*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 313*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate so->so_filterprefix = toks[ 0 ]; 316*0Sstevel@tonic-gate free( (char *)toks ); 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate /* 319*0Sstevel@tonic-gate * "Fewer Choices" filter tag comes next 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 322*0Sstevel@tonic-gate free_strarray( toks ); 323*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 324*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate so->so_filtertag = toks[ 0 ]; 327*0Sstevel@tonic-gate free( (char *)toks ); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * Selection (disambiguation) attribute comes next 331*0Sstevel@tonic-gate */ 332*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 333*0Sstevel@tonic-gate free_strarray( toks ); 334*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 335*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate so->so_defaultselectattr = toks[ 0 ]; 338*0Sstevel@tonic-gate free( (char *)toks ); 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* 341*0Sstevel@tonic-gate * Label for selection (disambiguation) attribute 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 344*0Sstevel@tonic-gate free_strarray( toks ); 345*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 346*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate so->so_defaultselecttext = toks[ 0 ]; 349*0Sstevel@tonic-gate free( (char *)toks ); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * Search scope is next 353*0Sstevel@tonic-gate */ 354*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 355*0Sstevel@tonic-gate free_strarray( toks ); 356*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 357*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate if ( !strcasecmp(toks[ 0 ], "subtree" )) { 360*0Sstevel@tonic-gate so->so_defaultscope = LDAP_SCOPE_SUBTREE; 361*0Sstevel@tonic-gate } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) { 362*0Sstevel@tonic-gate so->so_defaultscope = LDAP_SCOPE_ONELEVEL; 363*0Sstevel@tonic-gate } else if ( !strcasecmp(toks[ 0 ], "base" )) { 364*0Sstevel@tonic-gate so->so_defaultscope = LDAP_SCOPE_BASE; 365*0Sstevel@tonic-gate } else { 366*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 367*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate free_strarray( toks ); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * "More Choices" search option list comes next 374*0Sstevel@tonic-gate */ 375*0Sstevel@tonic-gate sa = &( so->so_salist ); 376*0Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 377*0Sstevel@tonic-gate if ( tokcnt < 5 ) { 378*0Sstevel@tonic-gate free_strarray( toks ); 379*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 380*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate if (( *sa = ( struct ldap_searchattr * ) calloc( (size_t) 1, 383*0Sstevel@tonic-gate sizeof( struct ldap_searchattr ))) == NULL ) { 384*0Sstevel@tonic-gate free_strarray( toks ); 385*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 386*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_MEM ); 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate ( *sa )->sa_attrlabel = toks[ 0 ]; 389*0Sstevel@tonic-gate ( *sa )->sa_attr = toks[ 1 ]; 390*0Sstevel@tonic-gate ( *sa )->sa_selectattr = toks[ 3 ]; 391*0Sstevel@tonic-gate ( *sa )->sa_selecttext = toks[ 4 ]; 392*0Sstevel@tonic-gate /* Deal with bitmap */ 393*0Sstevel@tonic-gate ( *sa )->sa_matchtypebitmap = 0; 394*0Sstevel@tonic-gate for ( i = (int) strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) { 395*0Sstevel@tonic-gate if ( toks[ 2 ][ i ] == '1' ) { 396*0Sstevel@tonic-gate ( *sa )->sa_matchtypebitmap |= (1 << j); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate free( toks[ 2 ] ); 400*0Sstevel@tonic-gate free( ( char * ) toks ); 401*0Sstevel@tonic-gate sa = &(( *sa )->sa_next); 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate *sa = NULL; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * Match types are last 407*0Sstevel@tonic-gate */ 408*0Sstevel@tonic-gate sm = &( so->so_smlist ); 409*0Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 410*0Sstevel@tonic-gate if ( tokcnt < 2 ) { 411*0Sstevel@tonic-gate free_strarray( toks ); 412*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 413*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_SYNTAX ); 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate if (( *sm = ( struct ldap_searchmatch * ) calloc( (size_t) 1, 416*0Sstevel@tonic-gate sizeof( struct ldap_searchmatch ))) == NULL ) { 417*0Sstevel@tonic-gate free_strarray( toks ); 418*0Sstevel@tonic-gate ldap_free_searchprefs( so ); 419*0Sstevel@tonic-gate return( LDAP_SEARCHPREF_ERR_MEM ); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate ( *sm )->sm_matchprompt = toks[ 0 ]; 422*0Sstevel@tonic-gate ( *sm )->sm_filter = toks[ 1 ]; 423*0Sstevel@tonic-gate free( ( char * ) toks ); 424*0Sstevel@tonic-gate sm = &(( *sm )->sm_next ); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate *sm = NULL; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate *sop = so; 429*0Sstevel@tonic-gate return( 0 ); 430*0Sstevel@tonic-gate } 431