1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate *
3*0Sstevel@tonic-gate * Portions Copyright 07/23/97 Sun Microsystems, Inc. All Rights Reserved
4*0Sstevel@tonic-gate *
5*0Sstevel@tonic-gate */
6*0Sstevel@tonic-gate /* line64.c - routines for dealing with the slapd line format */
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gate #include <stdio.h>
11*0Sstevel@tonic-gate #include <stdlib.h>
12*0Sstevel@tonic-gate #include <unistd.h>
13*0Sstevel@tonic-gate #include <string.h>
14*0Sstevel@tonic-gate #include <ctype.h>
15*0Sstevel@tonic-gate #include <sys/types.h>
16*0Sstevel@tonic-gate #include <sys/socket.h>
17*0Sstevel@tonic-gate #include "lber.h"
18*0Sstevel@tonic-gate #include "ldap.h"
19*0Sstevel@tonic-gate #include "ldif.h"
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gate #define RIGHT2 0x03
22*0Sstevel@tonic-gate #define RIGHT4 0x0f
23*0Sstevel@tonic-gate #define CONTINUED_LINE_MARKER '\001'
24*0Sstevel@tonic-gate
25*0Sstevel@tonic-gate static char nib2b64[0x40f] =
26*0Sstevel@tonic-gate "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gate static unsigned char b642nib[0x80] = {
29*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
30*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
31*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34*0Sstevel@tonic-gate 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
35*0Sstevel@tonic-gate 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
36*0Sstevel@tonic-gate 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37*0Sstevel@tonic-gate 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
38*0Sstevel@tonic-gate 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
39*0Sstevel@tonic-gate 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
40*0Sstevel@tonic-gate 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
41*0Sstevel@tonic-gate 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
42*0Sstevel@tonic-gate 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
43*0Sstevel@tonic-gate 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
44*0Sstevel@tonic-gate 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
45*0Sstevel@tonic-gate };
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate /*
48*0Sstevel@tonic-gate * str_parse_line - takes a line of the form "type:[:] value" and splits it
49*0Sstevel@tonic-gate * into components "type" and "value". if a double colon separates type from
50*0Sstevel@tonic-gate * value, then value is encoded in base 64, and parse_line un-decodes it
51*0Sstevel@tonic-gate * (in place) before returning.
52*0Sstevel@tonic-gate */
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate int
str_parse_line(char * line,char ** type,char ** value,int * vlen)55*0Sstevel@tonic-gate str_parse_line(
56*0Sstevel@tonic-gate char *line,
57*0Sstevel@tonic-gate char **type,
58*0Sstevel@tonic-gate char **value,
59*0Sstevel@tonic-gate int *vlen
60*0Sstevel@tonic-gate )
61*0Sstevel@tonic-gate {
62*0Sstevel@tonic-gate char *p, *s, *d, *byte, *stop;
63*0Sstevel@tonic-gate char nib;
64*0Sstevel@tonic-gate int i = 0, b64 = 0;
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate int url = 0;
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate /* skip any leading space */
69*0Sstevel@tonic-gate while ( isspace( *line ) ) {
70*0Sstevel@tonic-gate line++;
71*0Sstevel@tonic-gate }
72*0Sstevel@tonic-gate *type = line;
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate for ( s = line; *s && *s != ':'; s++ )
75*0Sstevel@tonic-gate ; /* NULL */
76*0Sstevel@tonic-gate if ( *s == '\0' ) {
77*0Sstevel@tonic-gate Debug( LDAP_DEBUG_PARSE, catgets(slapdcat, 1, 263, "parse_line missing ':'\n"), 0, 0, 0 );
78*0Sstevel@tonic-gate return( -1 );
79*0Sstevel@tonic-gate }
80*0Sstevel@tonic-gate
81*0Sstevel@tonic-gate /* trim any space between type and : */
82*0Sstevel@tonic-gate for ( p = s - 1; p > line && isspace( *p ); p-- ) {
83*0Sstevel@tonic-gate *p = '\0';
84*0Sstevel@tonic-gate }
85*0Sstevel@tonic-gate *s++ = '\0';
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gate /* check for double : - indicates base 64 encoded value */
88*0Sstevel@tonic-gate if ( *s == ':' ) {
89*0Sstevel@tonic-gate s++;
90*0Sstevel@tonic-gate b64 = 1;
91*0Sstevel@tonic-gate
92*0Sstevel@tonic-gate } else if ( *s == '<' ) { /* the value indicates an url */
93*0Sstevel@tonic-gate s++;
94*0Sstevel@tonic-gate url = 1;
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gate } else { /* single : - normally encoded value */
97*0Sstevel@tonic-gate b64 = 0;
98*0Sstevel@tonic-gate }
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate /* skip space between : and value */
101*0Sstevel@tonic-gate while ( isspace( *s ) ) {
102*0Sstevel@tonic-gate s++;
103*0Sstevel@tonic-gate }
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate /* if no value is present, error out */
106*0Sstevel@tonic-gate if ( *s == '\0' ) {
107*0Sstevel@tonic-gate Debug( LDAP_DEBUG_PARSE, catgets(slapdcat, 1, 264, "parse_line missing value\n"), 0,0,0 );
108*0Sstevel@tonic-gate return( -1 );
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate /* check for continued line markers that should be deleted */
112*0Sstevel@tonic-gate for ( p = s, d = s; *p; p++ ) {
113*0Sstevel@tonic-gate if ( *p != CONTINUED_LINE_MARKER )
114*0Sstevel@tonic-gate *d++ = *p;
115*0Sstevel@tonic-gate }
116*0Sstevel@tonic-gate *d = '\0';
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate if ( b64 ) {
119*0Sstevel@tonic-gate *value = s;
120*0Sstevel@tonic-gate stop = strchr( s, '\0' );
121*0Sstevel@tonic-gate byte = s;
122*0Sstevel@tonic-gate for ( p = s, *vlen = 0; p < stop; p += 4, *vlen += 3 ) {
123*0Sstevel@tonic-gate for ( i = 0; i < 3; i++ ) {
124*0Sstevel@tonic-gate if ( p[i] != '=' && (p[i] & 0x80 ||
125*0Sstevel@tonic-gate b642nib[ p[i] & 0x7f ] > 0x3f) ) {
126*0Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY,
127*0Sstevel@tonic-gate catgets(slapdcat, 1, 265, "invalid base 64 encoding char (%1$c) 0x%2$x\n"),
128*0Sstevel@tonic-gate p[i], p[i], 0 );
129*0Sstevel@tonic-gate return( -1 );
130*0Sstevel@tonic-gate }
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate /* first digit */
134*0Sstevel@tonic-gate nib = b642nib[ p[0] & 0x7f ];
135*0Sstevel@tonic-gate byte[0] = nib << 2;
136*0Sstevel@tonic-gate /* second digit */
137*0Sstevel@tonic-gate nib = b642nib[ p[1] & 0x7f ];
138*0Sstevel@tonic-gate byte[0] |= nib >> 4;
139*0Sstevel@tonic-gate byte[1] = (nib & RIGHT4) << 4;
140*0Sstevel@tonic-gate /* third digit */
141*0Sstevel@tonic-gate if ( p[2] == '=' ) {
142*0Sstevel@tonic-gate *vlen += 1;
143*0Sstevel@tonic-gate break;
144*0Sstevel@tonic-gate }
145*0Sstevel@tonic-gate nib = b642nib[ p[2] & 0x7f ];
146*0Sstevel@tonic-gate byte[1] |= nib >> 2;
147*0Sstevel@tonic-gate byte[2] = (nib & RIGHT2) << 6;
148*0Sstevel@tonic-gate /* fourth digit */
149*0Sstevel@tonic-gate if ( p[3] == '=' ) {
150*0Sstevel@tonic-gate *vlen += 2;
151*0Sstevel@tonic-gate break;
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate nib = b642nib[ p[3] & 0x7f ];
154*0Sstevel@tonic-gate byte[2] |= nib;
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate byte += 3;
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate s[ *vlen ] = '\0';
159*0Sstevel@tonic-gate } else if ( url ) { /* checks that the url is properly formed */
160*0Sstevel@tonic-gate /* file://[localhost]/<pathname> */
161*0Sstevel@tonic-gate /* value contains the content of the file */
162*0Sstevel@tonic-gate char * s2;
163*0Sstevel@tonic-gate char * filename;
164*0Sstevel@tonic-gate
165*0Sstevel@tonic-gate FILE *fp;
166*0Sstevel@tonic-gate int rlen;
167*0Sstevel@tonic-gate int eof;
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate
170*0Sstevel@tonic-gate if ( strncmp(s, "file://localhost", 16) == 0 )
171*0Sstevel@tonic-gate {
172*0Sstevel@tonic-gate s = s+16;
173*0Sstevel@tonic-gate }
174*0Sstevel@tonic-gate else if ( strncmp(s, "file://", 7) == 0 )
175*0Sstevel@tonic-gate {
176*0Sstevel@tonic-gate s = s+7;
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate else
179*0Sstevel@tonic-gate {
180*0Sstevel@tonic-gate /* url badly formed */
181*0Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1289, "invalid url %s\n"), s, 0, 0);
182*0Sstevel@tonic-gate return -1;
183*0Sstevel@tonic-gate }
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gate filename = strdup(s);
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate /* now we have the filename, read its content and return the value */
188*0Sstevel@tonic-gate if (( fp = fopen( filename, "r" )) == NULL )
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate perror( filename );
191*0Sstevel@tonic-gate return( -1 );
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate if ( fseek( fp, 0, SEEK_END ) != 0 )
195*0Sstevel@tonic-gate {
196*0Sstevel@tonic-gate perror( filename );
197*0Sstevel@tonic-gate fclose( fp );
198*0Sstevel@tonic-gate return( -1 );
199*0Sstevel@tonic-gate }
200*0Sstevel@tonic-gate
201*0Sstevel@tonic-gate *vlen = ftell(fp);
202*0Sstevel@tonic-gate if ( (*value = (char *)malloc(*vlen)) == NULL )
203*0Sstevel@tonic-gate {
204*0Sstevel@tonic-gate perror("malloc");
205*0Sstevel@tonic-gate fclose(fp);
206*0Sstevel@tonic-gate return(-1);
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate if ( fseek( fp, 0, SEEK_SET ) != 0 )
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate perror( filename );
211*0Sstevel@tonic-gate fclose( fp );
212*0Sstevel@tonic-gate return( -1 );
213*0Sstevel@tonic-gate }
214*0Sstevel@tonic-gate
215*0Sstevel@tonic-gate rlen = fread( *value, 1, *vlen, fp );
216*0Sstevel@tonic-gate eof = feof( fp );
217*0Sstevel@tonic-gate fclose( fp );
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate if ( rlen != *vlen )
220*0Sstevel@tonic-gate {
221*0Sstevel@tonic-gate perror( filename );
222*0Sstevel@tonic-gate return( -1 );
223*0Sstevel@tonic-gate }
224*0Sstevel@tonic-gate
225*0Sstevel@tonic-gate } else {
226*0Sstevel@tonic-gate *value = s;
227*0Sstevel@tonic-gate *vlen = (int) (d - s);
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate return( 0 );
231*0Sstevel@tonic-gate }
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate /*
234*0Sstevel@tonic-gate * str_getline - return the next "line" (minus newline) of input from a
235*0Sstevel@tonic-gate * string buffer of lines separated by newlines, terminated by \n\n
236*0Sstevel@tonic-gate * or \0. this routine handles continued lines, bundling them into
237*0Sstevel@tonic-gate * a single big line before returning. if a line begins with a white
238*0Sstevel@tonic-gate * space character, it is a continuation of the previous line. the white
239*0Sstevel@tonic-gate * space character (nb: only one char), and preceeding newline are changed
240*0Sstevel@tonic-gate * into CONTINUED_LINE_MARKER chars, to be deleted later by the
241*0Sstevel@tonic-gate * str_parse_line() routine above.
242*0Sstevel@tonic-gate *
243*0Sstevel@tonic-gate * it takes a pointer to a pointer to the buffer on the first call,
244*0Sstevel@tonic-gate * which it updates and must be supplied on subsequent calls.
245*0Sstevel@tonic-gate */
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate char *
str_getline(char ** next)248*0Sstevel@tonic-gate str_getline( char **next )
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate char *l;
251*0Sstevel@tonic-gate char c;
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gate if ( *next == NULL || **next == '\n' || **next == '\0' ) {
254*0Sstevel@tonic-gate return( NULL );
255*0Sstevel@tonic-gate }
256*0Sstevel@tonic-gate
257*0Sstevel@tonic-gate l = *next;
258*0Sstevel@tonic-gate while ( (*next = strchr( *next, '\n' )) != NULL ) {
259*0Sstevel@tonic-gate c = *(*next + 1);
260*0Sstevel@tonic-gate if ( isspace( c ) && c != '\n' ) {
261*0Sstevel@tonic-gate **next = CONTINUED_LINE_MARKER;
262*0Sstevel@tonic-gate *(*next+1) = CONTINUED_LINE_MARKER;
263*0Sstevel@tonic-gate } else {
264*0Sstevel@tonic-gate *(*next)++ = '\0';
265*0Sstevel@tonic-gate break;
266*0Sstevel@tonic-gate }
267*0Sstevel@tonic-gate *(*next)++;
268*0Sstevel@tonic-gate }
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate return( l );
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate void
put_type_and_value(char ** out,char * t,char * val,int vlen)274*0Sstevel@tonic-gate put_type_and_value( char **out, char *t, char *val, int vlen )
275*0Sstevel@tonic-gate {
276*0Sstevel@tonic-gate unsigned char *byte, *p, *stop;
277*0Sstevel@tonic-gate unsigned char buf[3];
278*0Sstevel@tonic-gate unsigned int bits;
279*0Sstevel@tonic-gate char *save;
280*0Sstevel@tonic-gate int i, b64, pad, len, savelen;
281*0Sstevel@tonic-gate len = 0;
282*0Sstevel@tonic-gate
283*0Sstevel@tonic-gate /* put the type + ": " */
284*0Sstevel@tonic-gate for ( p = (unsigned char *) t; *p; p++, len++ ) {
285*0Sstevel@tonic-gate *(*out)++ = *p;
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate *(*out)++ = ':';
288*0Sstevel@tonic-gate len++;
289*0Sstevel@tonic-gate save = *out;
290*0Sstevel@tonic-gate savelen = len;
291*0Sstevel@tonic-gate *(*out)++ = ' ';
292*0Sstevel@tonic-gate b64 = 0;
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate stop = (unsigned char *) (val + vlen);
295*0Sstevel@tonic-gate if ( isascii( val[0] ) && isspace( val[0] ) || val[0] == ':' ) {
296*0Sstevel@tonic-gate b64 = 1;
297*0Sstevel@tonic-gate } else {
298*0Sstevel@tonic-gate for ( byte = (unsigned char *) val; byte < stop;
299*0Sstevel@tonic-gate byte++, len++ ) {
300*0Sstevel@tonic-gate if ( !isascii( *byte ) || !isprint( *byte ) ) {
301*0Sstevel@tonic-gate b64 = 1;
302*0Sstevel@tonic-gate break;
303*0Sstevel@tonic-gate }
304*0Sstevel@tonic-gate if ( len > LINE_WIDTH ) {
305*0Sstevel@tonic-gate *(*out)++ = '\n';
306*0Sstevel@tonic-gate *(*out)++ = ' ';
307*0Sstevel@tonic-gate len = 1;
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate *(*out)++ = *byte;
310*0Sstevel@tonic-gate }
311*0Sstevel@tonic-gate }
312*0Sstevel@tonic-gate if ( b64 ) {
313*0Sstevel@tonic-gate *out = save;
314*0Sstevel@tonic-gate *(*out)++ = ':';
315*0Sstevel@tonic-gate *(*out)++ = ' ';
316*0Sstevel@tonic-gate len = savelen + 2;
317*0Sstevel@tonic-gate /* convert to base 64 (3 bytes => 4 base 64 digits) */
318*0Sstevel@tonic-gate for ( byte = (unsigned char *) val; byte < stop - 2;
319*0Sstevel@tonic-gate byte += 3 ) {
320*0Sstevel@tonic-gate bits = (byte[0] & 0xff) << 16;
321*0Sstevel@tonic-gate bits |= (byte[1] & 0xff) << 8;
322*0Sstevel@tonic-gate bits |= (byte[2] & 0xff);
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gate for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
325*0Sstevel@tonic-gate if ( len > LINE_WIDTH ) {
326*0Sstevel@tonic-gate *(*out)++ = '\n';
327*0Sstevel@tonic-gate *(*out)++ = ' ';
328*0Sstevel@tonic-gate len = 1;
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate /* get b64 digit from high order 6 bits */
332*0Sstevel@tonic-gate *(*out)++ = nib2b64[ (bits & 0xfc0000) >> 18 ];
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate }
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate /* add padding if necessary */
337*0Sstevel@tonic-gate if ( byte < stop ) {
338*0Sstevel@tonic-gate for ( i = 0; byte + i < stop; i++ ) {
339*0Sstevel@tonic-gate buf[i] = byte[i];
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate for ( pad = 0; i < 3; i++, pad++ ) {
342*0Sstevel@tonic-gate buf[i] = '\0';
343*0Sstevel@tonic-gate }
344*0Sstevel@tonic-gate byte = buf;
345*0Sstevel@tonic-gate bits = (byte[0] & 0xff) << 16;
346*0Sstevel@tonic-gate bits |= (byte[1] & 0xff) << 8;
347*0Sstevel@tonic-gate bits |= (byte[2] & 0xff);
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
350*0Sstevel@tonic-gate if ( len > LINE_WIDTH ) {
351*0Sstevel@tonic-gate *(*out)++ = '\n';
352*0Sstevel@tonic-gate *(*out)++ = ' ';
353*0Sstevel@tonic-gate len = 1;
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gate /* get b64 digit from low order 6 bits */
357*0Sstevel@tonic-gate *(*out)++ = nib2b64[ (bits & 0xfc0000) >> 18 ];
358*0Sstevel@tonic-gate }
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate for ( ; pad > 0; pad-- ) {
361*0Sstevel@tonic-gate *(*out - pad) = '=';
362*0Sstevel@tonic-gate }
363*0Sstevel@tonic-gate }
364*0Sstevel@tonic-gate }
365*0Sstevel@tonic-gate *(*out)++ = '\n';
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate
369*0Sstevel@tonic-gate char *
ldif_type_and_value(char * type,char * val,int vlen)370*0Sstevel@tonic-gate ldif_type_and_value( char *type, char *val, int vlen )
371*0Sstevel@tonic-gate /*
372*0Sstevel@tonic-gate * return malloc'd, zero-terminated LDIF line
373*0Sstevel@tonic-gate */
374*0Sstevel@tonic-gate {
375*0Sstevel@tonic-gate char *buf, *p;
376*0Sstevel@tonic-gate int tlen;
377*0Sstevel@tonic-gate
378*0Sstevel@tonic-gate buf=NULL;
379*0Sstevel@tonic-gate tlen = strlen( type );
380*0Sstevel@tonic-gate if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) !=
381*0Sstevel@tonic-gate NULL ) {
382*0Sstevel@tonic-gate
383*0Sstevel@tonic-gate p = buf;
384*0Sstevel@tonic-gate put_type_and_value( &p, type, val, vlen );
385*0Sstevel@tonic-gate *p = '\0';
386*0Sstevel@tonic-gate }
387*0Sstevel@tonic-gate return( buf );
388*0Sstevel@tonic-gate }
389