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 * Copyright (c) 1993, 1994 Regents of the University of Michigan. 11*0Sstevel@tonic-gate * All rights reserved. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 14*0Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given 15*0Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University 16*0Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 17*0Sstevel@tonic-gate * software without specific prior written permission. This software 18*0Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty. 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * disptmpl.c: display template library routines for LDAP clients 21*0Sstevel@tonic-gate * 7 March 1994 by Mark C Smith 22*0Sstevel@tonic-gate */ 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate #include <stdio.h> 25*0Sstevel@tonic-gate #include <ctype.h> 26*0Sstevel@tonic-gate #include <string.h> 27*0Sstevel@tonic-gate #include <stdlib.h> 28*0Sstevel@tonic-gate #ifdef MACOS 29*0Sstevel@tonic-gate #include "macos.h" 30*0Sstevel@tonic-gate #else /* MACOS */ 31*0Sstevel@tonic-gate #ifdef DOS 32*0Sstevel@tonic-gate #include <malloc.h> 33*0Sstevel@tonic-gate #include "msdos.h" 34*0Sstevel@tonic-gate #else /* DOS */ 35*0Sstevel@tonic-gate #include <sys/types.h> 36*0Sstevel@tonic-gate #include <sys/file.h> 37*0Sstevel@tonic-gate #ifndef VMS 38*0Sstevel@tonic-gate #include <unistd.h> 39*0Sstevel@tonic-gate #endif /* VMS */ 40*0Sstevel@tonic-gate #endif /* DOS */ 41*0Sstevel@tonic-gate #endif /* MACOS */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include "lber.h" 44*0Sstevel@tonic-gate #include "ldap.h" 45*0Sstevel@tonic-gate #include "ldap-private.h" 46*0Sstevel@tonic-gate #include "ldap-int.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #ifndef NEEDPROTOS 49*0Sstevel@tonic-gate static void free_disptmpl(); 50*0Sstevel@tonic-gate static int read_next_tmpl(); 51*0Sstevel@tonic-gate int next_line_tokens(); 52*0Sstevel@tonic-gate #else /* !NEEDPROTOS */ 53*0Sstevel@tonic-gate static void free_disptmpl( struct ldap_disptmpl *tmpl ); 54*0Sstevel@tonic-gate static int read_next_tmpl( char **bufp, ssize_t *blenp, 55*0Sstevel@tonic-gate struct ldap_disptmpl **tmplp, int dtversion ); 56*0Sstevel@tonic-gate int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp ); 57*0Sstevel@tonic-gate #endif /* !NEEDPROTOS */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static char *tmploptions[] = { 60*0Sstevel@tonic-gate "addable", "modrdn", 61*0Sstevel@tonic-gate "altview", 62*0Sstevel@tonic-gate NULL 63*0Sstevel@tonic-gate }; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate static unsigned int tmploptvals[] = { 67*0Sstevel@tonic-gate LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN, 68*0Sstevel@tonic-gate LDAP_DTMPL_OPT_ALTVIEW, 69*0Sstevel@tonic-gate }; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate static char *itemtypes[] = { 73*0Sstevel@tonic-gate "cis", "mls", "dn", 74*0Sstevel@tonic-gate "bool", "jpeg", "jpegbtn", 75*0Sstevel@tonic-gate "fax", "faxbtn", "audiobtn", 76*0Sstevel@tonic-gate "time", "date", "url", 77*0Sstevel@tonic-gate "searchact", "linkact", "adddnact", 78*0Sstevel@tonic-gate "addact", "verifyact", "mail", 79*0Sstevel@tonic-gate #ifdef SUN 80*0Sstevel@tonic-gate "protected", 81*0Sstevel@tonic-gate #endif 82*0Sstevel@tonic-gate NULL 83*0Sstevel@tonic-gate }; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate static unsigned int itemsynids[] = { 86*0Sstevel@tonic-gate LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN, 87*0Sstevel@tonic-gate LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON, 88*0Sstevel@tonic-gate LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON, 89*0Sstevel@tonic-gate LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL, 90*0Sstevel@tonic-gate LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION, 91*0Sstevel@tonic-gate LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR, 92*0Sstevel@tonic-gate #ifdef SUN 93*0Sstevel@tonic-gate LDAP_SYN_PROTECTED, 94*0Sstevel@tonic-gate #endif 95*0Sstevel@tonic-gate }; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate static char *itemoptions[] = { 99*0Sstevel@tonic-gate "ro", "sort", 100*0Sstevel@tonic-gate "1val", "hide", 101*0Sstevel@tonic-gate "required", "hideiffalse", 102*0Sstevel@tonic-gate NULL 103*0Sstevel@tonic-gate }; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate static unsigned int itemoptvals[] = { 107*0Sstevel@tonic-gate LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, 108*0Sstevel@tonic-gate LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, 109*0Sstevel@tonic-gate LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, 110*0Sstevel@tonic-gate }; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate #define ADDEF_CONSTANT "constant" 114*0Sstevel@tonic-gate #define ADDEF_ADDERSDN "addersdn" 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate #ifdef SUN 117*0Sstevel@tonic-gate /* LP@Sun : right_trim */ 118*0Sstevel@tonic-gate static void right_trim(char *aStr) 119*0Sstevel@tonic-gate { 120*0Sstevel@tonic-gate char * theEnd = aStr + strlen(aStr); 121*0Sstevel@tonic-gate while ((theEnd > aStr) && isspace(*(theEnd - 1))) 122*0Sstevel@tonic-gate theEnd--; 123*0Sstevel@tonic-gate theEnd; 124*0Sstevel@tonic-gate *theEnd= '\0'; 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate #endif 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate int 129*0Sstevel@tonic-gate ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) 130*0Sstevel@tonic-gate { 131*0Sstevel@tonic-gate FILE *fp; 132*0Sstevel@tonic-gate char *buf; 133*0Sstevel@tonic-gate ssize_t rlen, len; 134*0Sstevel@tonic-gate int rc, eof; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate *tmpllistp = NULLDISPTMPL; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate if (( fp = fopen( file, "r" )) == NULL ) { 139*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ 143*0Sstevel@tonic-gate fclose( fp ); 144*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate len = ftell( fp ); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ 150*0Sstevel@tonic-gate fclose( fp ); 151*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate if (( buf = malloc( len )) == NULL ) { 155*0Sstevel@tonic-gate fclose( fp ); 156*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate rlen = fread( buf, (size_t) 1, len, fp ); 160*0Sstevel@tonic-gate eof = feof( fp ); 161*0Sstevel@tonic-gate fclose( fp ); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate if ( rlen != len && !eof ) { /* error: didn't get the whole file */ 164*0Sstevel@tonic-gate free( buf ); 165*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); 169*0Sstevel@tonic-gate free( buf ); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate return( rc ); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate int 176*0Sstevel@tonic-gate ldap_init_templates_buf( char *buf, ssize_t buflen, 177*0Sstevel@tonic-gate struct ldap_disptmpl **tmpllistp ) 178*0Sstevel@tonic-gate { 179*0Sstevel@tonic-gate int rc, version; 180*0Sstevel@tonic-gate char **toks; 181*0Sstevel@tonic-gate struct ldap_disptmpl *prevtmpl, *tmpl; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate *tmpllistp = prevtmpl = NULLDISPTMPL; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate if ( next_line_tokens( &buf, &buflen, &toks ) != 2 || 186*0Sstevel@tonic-gate strcasecmp( toks[ 0 ], "version" ) != 0 ) { 187*0Sstevel@tonic-gate free_strarray( toks ); 188*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate version = atoi( toks[ 1 ] ); 191*0Sstevel@tonic-gate free_strarray( toks ); 192*0Sstevel@tonic-gate if ( version != LDAP_TEMPLATE_VERSION ) { 193*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_VERSION ); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl, 197*0Sstevel@tonic-gate version )) == 0 && tmpl != NULLDISPTMPL ) { 198*0Sstevel@tonic-gate if ( prevtmpl == NULLDISPTMPL ) { 199*0Sstevel@tonic-gate *tmpllistp = tmpl; 200*0Sstevel@tonic-gate } else { 201*0Sstevel@tonic-gate prevtmpl->dt_next = tmpl; 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate prevtmpl = tmpl; 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate if ( rc != 0 ) { 207*0Sstevel@tonic-gate ldap_free_templates( *tmpllistp ); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate return( rc ); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate void 216*0Sstevel@tonic-gate ldap_free_templates( struct ldap_disptmpl *tmpllist ) 217*0Sstevel@tonic-gate { 218*0Sstevel@tonic-gate struct ldap_disptmpl *tp, *nexttp; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if ( tmpllist != NULL ) { 221*0Sstevel@tonic-gate for ( tp = tmpllist; tp != NULL; tp = nexttp ) { 222*0Sstevel@tonic-gate nexttp = tp->dt_next; 223*0Sstevel@tonic-gate free_disptmpl( tp ); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate static void 230*0Sstevel@tonic-gate free_disptmpl( struct ldap_disptmpl *tmpl ) 231*0Sstevel@tonic-gate { 232*0Sstevel@tonic-gate if ( tmpl != NULL ) { 233*0Sstevel@tonic-gate if ( tmpl->dt_name != NULL ) { 234*0Sstevel@tonic-gate free( tmpl->dt_name ); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate if ( tmpl->dt_pluralname != NULL ) { 238*0Sstevel@tonic-gate free( tmpl->dt_pluralname ); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if ( tmpl->dt_iconname != NULL ) { 242*0Sstevel@tonic-gate free( tmpl->dt_iconname ); 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate if ( tmpl->dt_authattrname != NULL ) { 246*0Sstevel@tonic-gate free( tmpl->dt_authattrname ); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if ( tmpl->dt_defrdnattrname != NULL ) { 250*0Sstevel@tonic-gate free( tmpl->dt_defrdnattrname ); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate if ( tmpl->dt_defaddlocation != NULL ) { 254*0Sstevel@tonic-gate free( tmpl->dt_defaddlocation ); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate if ( tmpl->dt_oclist != NULL ) { 258*0Sstevel@tonic-gate struct ldap_oclist *ocp, *nextocp; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { 261*0Sstevel@tonic-gate nextocp = ocp->oc_next; 262*0Sstevel@tonic-gate free_strarray( ocp->oc_objclasses ); 263*0Sstevel@tonic-gate free( ocp ); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate if ( tmpl->dt_adddeflist != NULL ) { 268*0Sstevel@tonic-gate struct ldap_adddeflist *adp, *nextadp; 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) { 271*0Sstevel@tonic-gate nextadp = adp->ad_next; 272*0Sstevel@tonic-gate if( adp->ad_attrname != NULL ) { 273*0Sstevel@tonic-gate free( adp->ad_attrname ); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate if( adp->ad_value != NULL ) { 276*0Sstevel@tonic-gate free( adp->ad_value ); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate free( adp ); 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate if ( tmpl->dt_items != NULL ) { 283*0Sstevel@tonic-gate struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) { 286*0Sstevel@tonic-gate nextrowp = rowp->ti_next_in_col; 287*0Sstevel@tonic-gate for ( colp = rowp; colp != NULL; colp = nextcolp ) { 288*0Sstevel@tonic-gate nextcolp = colp->ti_next_in_row; 289*0Sstevel@tonic-gate if ( colp->ti_attrname != NULL ) { 290*0Sstevel@tonic-gate free( colp->ti_attrname ); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate if ( colp->ti_label != NULL ) { 293*0Sstevel@tonic-gate free( colp->ti_label ); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate if ( colp->ti_args != NULL ) { 296*0Sstevel@tonic-gate free_strarray( colp->ti_args ); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate free( colp ); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate free( tmpl ); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate struct ldap_disptmpl * 309*0Sstevel@tonic-gate ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ) 310*0Sstevel@tonic-gate { 311*0Sstevel@tonic-gate return( tmpllist ); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate struct ldap_disptmpl * 316*0Sstevel@tonic-gate ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, 317*0Sstevel@tonic-gate struct ldap_disptmpl *tmpl ) 318*0Sstevel@tonic-gate { 319*0Sstevel@tonic-gate return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next ); 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate struct ldap_disptmpl * 324*0Sstevel@tonic-gate ldap_name2template( char *name, struct ldap_disptmpl *tmpllist ) 325*0Sstevel@tonic-gate { 326*0Sstevel@tonic-gate struct ldap_disptmpl *dtp; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 329*0Sstevel@tonic-gate dtp = ldap_next_disptmpl( tmpllist, dtp )) { 330*0Sstevel@tonic-gate if ( strcasecmp( name, dtp->dt_name ) == 0 ) { 331*0Sstevel@tonic-gate return( dtp ); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate return( NULLDISPTMPL ); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate struct ldap_disptmpl * 340*0Sstevel@tonic-gate ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist ) 341*0Sstevel@tonic-gate { 342*0Sstevel@tonic-gate struct ldap_disptmpl *dtp; 343*0Sstevel@tonic-gate struct ldap_oclist *oclp; 344*0Sstevel@tonic-gate int i, j, needcnt, matchcnt; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) { 347*0Sstevel@tonic-gate return( NULLDISPTMPL ); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 351*0Sstevel@tonic-gate dtp = ldap_next_disptmpl( tmpllist, dtp )) { 352*0Sstevel@tonic-gate for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST; 353*0Sstevel@tonic-gate oclp = oclp->oc_next ) { 354*0Sstevel@tonic-gate needcnt = matchcnt = 0; 355*0Sstevel@tonic-gate for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) { 356*0Sstevel@tonic-gate for ( j = 0; oclist[ j ] != NULL; ++j ) { 357*0Sstevel@tonic-gate #ifdef SUN 358*0Sstevel@tonic-gate /* LP@Sun : remove ending space from objectclass */ 359*0Sstevel@tonic-gate right_trim(oclist[j]); 360*0Sstevel@tonic-gate #endif 361*0Sstevel@tonic-gate if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] ) 362*0Sstevel@tonic-gate == 0 ) { 363*0Sstevel@tonic-gate ++matchcnt; 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate ++needcnt; 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate if ( matchcnt == needcnt ) { 370*0Sstevel@tonic-gate return( dtp ); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate return( NULLDISPTMPL ); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate struct ldap_tmplitem * 380*0Sstevel@tonic-gate ldap_first_tmplrow( struct ldap_disptmpl *tmpl ) 381*0Sstevel@tonic-gate { 382*0Sstevel@tonic-gate return( tmpl->dt_items ); 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate struct ldap_tmplitem * 387*0Sstevel@tonic-gate ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 388*0Sstevel@tonic-gate { 389*0Sstevel@tonic-gate return( row == NULLTMPLITEM ? row : row->ti_next_in_col ); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate struct ldap_tmplitem * 394*0Sstevel@tonic-gate ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 395*0Sstevel@tonic-gate { 396*0Sstevel@tonic-gate return( row ); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate struct ldap_tmplitem * 401*0Sstevel@tonic-gate ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, 402*0Sstevel@tonic-gate struct ldap_tmplitem *col ) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate return( col == NULLTMPLITEM ? col : col->ti_next_in_row ); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate char ** 409*0Sstevel@tonic-gate ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, 410*0Sstevel@tonic-gate int exclude, unsigned int syntaxmask ) 411*0Sstevel@tonic-gate { 412*0Sstevel@tonic-gate /* 413*0Sstevel@tonic-gate * this routine should filter out duplicate attributes... 414*0Sstevel@tonic-gate */ 415*0Sstevel@tonic-gate struct ldap_tmplitem *tirowp, *ticolp; 416*0Sstevel@tonic-gate int i, attrcnt, memerr; 417*0Sstevel@tonic-gate char **attrs; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate attrcnt = 0; 420*0Sstevel@tonic-gate memerr = 0; 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) { 423*0Sstevel@tonic-gate return( NULL ); 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate if ( includeattrs != NULL ) { 427*0Sstevel@tonic-gate for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { 428*0Sstevel@tonic-gate if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) * 429*0Sstevel@tonic-gate sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 430*0Sstevel@tonic-gate strdup( includeattrs[ i ] )) == NULL ) { 431*0Sstevel@tonic-gate memerr = 1; 432*0Sstevel@tonic-gate } else { 433*0Sstevel@tonic-gate attrs[ attrcnt ] = NULL; 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate for ( tirowp = ldap_first_tmplrow( tmpl ); 439*0Sstevel@tonic-gate !memerr && tirowp != NULLTMPLITEM; 440*0Sstevel@tonic-gate tirowp = ldap_next_tmplrow( tmpl, tirowp )) { 441*0Sstevel@tonic-gate for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); 442*0Sstevel@tonic-gate ticolp != NULLTMPLITEM; 443*0Sstevel@tonic-gate ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate if ( syntaxmask != 0 ) { 446*0Sstevel@tonic-gate if (( exclude && 447*0Sstevel@tonic-gate ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || 448*0Sstevel@tonic-gate ( !exclude && 449*0Sstevel@tonic-gate ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { 450*0Sstevel@tonic-gate continue; 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate if ( ticolp->ti_attrname != NULL ) { 455*0Sstevel@tonic-gate if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) * 456*0Sstevel@tonic-gate sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 457*0Sstevel@tonic-gate strdup( ticolp->ti_attrname )) == NULL ) { 458*0Sstevel@tonic-gate memerr = 1; 459*0Sstevel@tonic-gate } else { 460*0Sstevel@tonic-gate attrs[ attrcnt ] = NULL; 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate if ( memerr || attrcnt == 0 ) { 467*0Sstevel@tonic-gate for ( i = 0; i < attrcnt; ++i ) { 468*0Sstevel@tonic-gate if ( attrs[ i ] != NULL ) { 469*0Sstevel@tonic-gate free( attrs[ i ] ); 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate free( (char *)attrs ); 474*0Sstevel@tonic-gate return( NULL ); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate return( attrs ); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate static int 482*0Sstevel@tonic-gate read_next_tmpl( char **bufp, ssize_t *blenp, struct ldap_disptmpl **tmplp, 483*0Sstevel@tonic-gate int dtversion ) 484*0Sstevel@tonic-gate { 485*0Sstevel@tonic-gate int i, j, tokcnt, samerow, adsource; 486*0Sstevel@tonic-gate char **toks, *itemopts; 487*0Sstevel@tonic-gate struct ldap_disptmpl *tmpl; 488*0Sstevel@tonic-gate struct ldap_oclist *ocp, *prevocp; 489*0Sstevel@tonic-gate struct ldap_adddeflist *adp, *prevadp; 490*0Sstevel@tonic-gate struct ldap_tmplitem *rowp, *ip, *previp; 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate *tmplp = NULL; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate /* 495*0Sstevel@tonic-gate * template name comes first 496*0Sstevel@tonic-gate */ 497*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 498*0Sstevel@tonic-gate free_strarray( toks ); 499*0Sstevel@tonic-gate return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (( tmpl = (struct ldap_disptmpl *)calloc( (size_t) 1, 503*0Sstevel@tonic-gate sizeof( struct ldap_disptmpl ))) == NULL ) { 504*0Sstevel@tonic-gate free_strarray( toks ); 505*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate tmpl->dt_name = toks[ 0 ]; 508*0Sstevel@tonic-gate free( (char *)toks ); 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate /* 511*0Sstevel@tonic-gate * template plural name comes next 512*0Sstevel@tonic-gate */ 513*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 514*0Sstevel@tonic-gate free_strarray( toks ); 515*0Sstevel@tonic-gate free_disptmpl( tmpl ); 516*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate tmpl->dt_pluralname = toks[ 0 ]; 519*0Sstevel@tonic-gate free( (char *)toks ); 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate /* 522*0Sstevel@tonic-gate * template icon name is next 523*0Sstevel@tonic-gate */ 524*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 525*0Sstevel@tonic-gate free_strarray( toks ); 526*0Sstevel@tonic-gate free_disptmpl( tmpl ); 527*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate tmpl->dt_iconname = toks[ 0 ]; 530*0Sstevel@tonic-gate free( (char *)toks ); 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate /* 533*0Sstevel@tonic-gate * template options come next 534*0Sstevel@tonic-gate */ 535*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) { 536*0Sstevel@tonic-gate free_strarray( toks ); 537*0Sstevel@tonic-gate free_disptmpl( tmpl ); 538*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate for ( i = 0; toks[ i ] != NULL; ++i ) { 541*0Sstevel@tonic-gate for ( j = 0; tmploptions[ j ] != NULL; ++j ) { 542*0Sstevel@tonic-gate if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) { 543*0Sstevel@tonic-gate tmpl->dt_options |= tmploptvals[ j ]; 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate free_strarray( toks ); 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /* 550*0Sstevel@tonic-gate * object class list is next 551*0Sstevel@tonic-gate */ 552*0Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 553*0Sstevel@tonic-gate if (( ocp = (struct ldap_oclist *)calloc( (size_t) 1, 554*0Sstevel@tonic-gate sizeof( struct ldap_oclist ))) == NULL ) { 555*0Sstevel@tonic-gate free_strarray( toks ); 556*0Sstevel@tonic-gate free_disptmpl( tmpl ); 557*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate ocp->oc_objclasses = toks; 560*0Sstevel@tonic-gate if ( tmpl->dt_oclist == NULL ) { 561*0Sstevel@tonic-gate tmpl->dt_oclist = ocp; 562*0Sstevel@tonic-gate } else { 563*0Sstevel@tonic-gate prevocp->oc_next = ocp; 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate prevocp = ocp; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate if ( tokcnt < 0 ) { 568*0Sstevel@tonic-gate free_disptmpl( tmpl ); 569*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * read name of attribute to authenticate as 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 576*0Sstevel@tonic-gate free_strarray( toks ); 577*0Sstevel@tonic-gate free_disptmpl( tmpl ); 578*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate if ( toks[ 0 ][ 0 ] != '\0' ) { 581*0Sstevel@tonic-gate tmpl->dt_authattrname = toks[ 0 ]; 582*0Sstevel@tonic-gate } else { 583*0Sstevel@tonic-gate free( toks[ 0 ] ); 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate free( (char *)toks ); 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate /* 588*0Sstevel@tonic-gate * read default attribute to use for RDN 589*0Sstevel@tonic-gate */ 590*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 591*0Sstevel@tonic-gate free_strarray( toks ); 592*0Sstevel@tonic-gate free_disptmpl( tmpl ); 593*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate tmpl->dt_defrdnattrname = toks[ 0 ]; 596*0Sstevel@tonic-gate free( (char *)toks ); 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* 599*0Sstevel@tonic-gate * read default location for new entries 600*0Sstevel@tonic-gate */ 601*0Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 602*0Sstevel@tonic-gate free_strarray( toks ); 603*0Sstevel@tonic-gate free_disptmpl( tmpl ); 604*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate if ( toks[ 0 ][ 0 ] != '\0' ) { 607*0Sstevel@tonic-gate tmpl->dt_defaddlocation = toks[ 0 ]; 608*0Sstevel@tonic-gate } else { 609*0Sstevel@tonic-gate free( toks[ 0 ] ); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate free( (char *)toks ); 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate /* 614*0Sstevel@tonic-gate * read list of rules used to define default values for new entries 615*0Sstevel@tonic-gate */ 616*0Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 617*0Sstevel@tonic-gate if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) { 618*0Sstevel@tonic-gate adsource = LDAP_ADSRC_CONSTANTVALUE; 619*0Sstevel@tonic-gate } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) { 620*0Sstevel@tonic-gate adsource = LDAP_ADSRC_ADDERSDN; 621*0Sstevel@tonic-gate } else { 622*0Sstevel@tonic-gate adsource = 0; 623*0Sstevel@tonic-gate } 624*0Sstevel@tonic-gate if ( adsource == 0 || tokcnt < 2 || 625*0Sstevel@tonic-gate ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || 626*0Sstevel@tonic-gate ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { 627*0Sstevel@tonic-gate free_strarray( toks ); 628*0Sstevel@tonic-gate free_disptmpl( tmpl ); 629*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate if (( adp = (struct ldap_adddeflist *)calloc( (size_t) 1, 633*0Sstevel@tonic-gate sizeof( struct ldap_adddeflist ))) == NULL ) { 634*0Sstevel@tonic-gate free_strarray( toks ); 635*0Sstevel@tonic-gate free_disptmpl( tmpl ); 636*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate adp->ad_source = adsource; 639*0Sstevel@tonic-gate adp->ad_attrname = toks[ 1 ]; 640*0Sstevel@tonic-gate if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) { 641*0Sstevel@tonic-gate adp->ad_value = toks[ 2 ]; 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate free( toks[ 0 ] ); 644*0Sstevel@tonic-gate free( (char *)toks ); 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate if ( tmpl->dt_adddeflist == NULL ) { 647*0Sstevel@tonic-gate tmpl->dt_adddeflist = adp; 648*0Sstevel@tonic-gate } else { 649*0Sstevel@tonic-gate prevadp->ad_next = adp; 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate prevadp = adp; 652*0Sstevel@tonic-gate } 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate /* 655*0Sstevel@tonic-gate * item list is next 656*0Sstevel@tonic-gate */ 657*0Sstevel@tonic-gate samerow = 0; 658*0Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 659*0Sstevel@tonic-gate if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { 660*0Sstevel@tonic-gate if ( tokcnt < 4 ) { 661*0Sstevel@tonic-gate free_strarray( toks ); 662*0Sstevel@tonic-gate free_disptmpl( tmpl ); 663*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate if (( ip = (struct ldap_tmplitem *)calloc( (size_t) 1, 667*0Sstevel@tonic-gate sizeof( struct ldap_tmplitem ))) == NULL ) { 668*0Sstevel@tonic-gate free_strarray( toks ); 669*0Sstevel@tonic-gate free_disptmpl( tmpl ); 670*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* 674*0Sstevel@tonic-gate * find syntaxid from config file string 675*0Sstevel@tonic-gate */ 676*0Sstevel@tonic-gate while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) { 677*0Sstevel@tonic-gate *itemopts++ = '\0'; 678*0Sstevel@tonic-gate for ( i = 0; itemoptions[ i ] != NULL; ++i ) { 679*0Sstevel@tonic-gate if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) { 680*0Sstevel@tonic-gate break; 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate if ( itemoptions[ i ] == NULL ) { 684*0Sstevel@tonic-gate free_strarray( toks ); 685*0Sstevel@tonic-gate free_disptmpl( tmpl ); 686*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate ip->ti_options |= itemoptvals[ i ]; 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate for ( i = 0; itemtypes[ i ] != NULL; ++i ) { 692*0Sstevel@tonic-gate if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) { 693*0Sstevel@tonic-gate break; 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate if ( itemtypes[ i ] == NULL ) { 697*0Sstevel@tonic-gate free_strarray( toks ); 698*0Sstevel@tonic-gate free_disptmpl( tmpl ); 699*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate free( toks[ 0 ] ); 703*0Sstevel@tonic-gate free( toks[ 1 ] ); 704*0Sstevel@tonic-gate ip->ti_syntaxid = itemsynids[ i ]; 705*0Sstevel@tonic-gate ip->ti_label = toks[ 2 ]; 706*0Sstevel@tonic-gate if ( toks[ 3 ][ 0 ] == '\0' ) { 707*0Sstevel@tonic-gate ip->ti_attrname = NULL; 708*0Sstevel@tonic-gate free( toks[ 3 ] ); 709*0Sstevel@tonic-gate } else { 710*0Sstevel@tonic-gate ip->ti_attrname = toks[ 3 ]; 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate if ( toks[ 4 ] != NULL ) { /* extra args. */ 713*0Sstevel@tonic-gate for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 714*0Sstevel@tonic-gate ; 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate if (( ip->ti_args = (char **) calloc( (size_t) (i + 1), sizeof( char * ))) 717*0Sstevel@tonic-gate == NULL ) { 718*0Sstevel@tonic-gate free_disptmpl( tmpl ); 719*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 722*0Sstevel@tonic-gate ip->ti_args[ i ] = toks[ i + 4 ]; 723*0Sstevel@tonic-gate } 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate free( (char *)toks ); 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate if ( tmpl->dt_items == NULL ) { 728*0Sstevel@tonic-gate tmpl->dt_items = rowp = ip; 729*0Sstevel@tonic-gate } else if ( samerow ) { 730*0Sstevel@tonic-gate previp->ti_next_in_row = ip; 731*0Sstevel@tonic-gate } else { 732*0Sstevel@tonic-gate rowp->ti_next_in_col = ip; 733*0Sstevel@tonic-gate rowp = ip; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate previp = ip; 736*0Sstevel@tonic-gate samerow = 0; 737*0Sstevel@tonic-gate } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { 738*0Sstevel@tonic-gate free_strarray( toks ); 739*0Sstevel@tonic-gate samerow = 1; 740*0Sstevel@tonic-gate } else { 741*0Sstevel@tonic-gate free_strarray( toks ); 742*0Sstevel@tonic-gate free_disptmpl( tmpl ); 743*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate if ( tokcnt < 0 ) { 747*0Sstevel@tonic-gate free_disptmpl( tmpl ); 748*0Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate *tmplp = tmpl; 752*0Sstevel@tonic-gate return( 0 ); 753*0Sstevel@tonic-gate } 754