xref: /titanic_41/usr/src/lib/libldap5/sources/ldap/util/line64.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate 
7*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
11*7c478bd9Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
12*7c478bd9Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
13*7c478bd9Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
16*7c478bd9Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17*7c478bd9Sstevel@tonic-gate  * implied. See the License for the specific language governing
18*7c478bd9Sstevel@tonic-gate  * rights and limitations under the License.
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
21*7c478bd9Sstevel@tonic-gate  * March 31, 1998.
22*7c478bd9Sstevel@tonic-gate  *
23*7c478bd9Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
24*7c478bd9Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
25*7c478bd9Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
26*7c478bd9Sstevel@tonic-gate  * Rights Reserved.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * Contributor(s):
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /* line64.c - routines for dealing with the slapd line format */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #ifndef macintosh
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #endif
40*7c478bd9Sstevel@tonic-gate #ifdef _WIN32
41*7c478bd9Sstevel@tonic-gate #include <windows.h>
42*7c478bd9Sstevel@tonic-gate #elif !defined( macintosh )
43*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
44*7c478bd9Sstevel@tonic-gate #endif
45*7c478bd9Sstevel@tonic-gate #include "ldaplog.h"
46*7c478bd9Sstevel@tonic-gate #include "ldif.h"
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #ifndef isascii
49*7c478bd9Sstevel@tonic-gate #define isascii( c )	(!((c) & ~0177))
50*7c478bd9Sstevel@tonic-gate #endif
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #define RIGHT2			0x03
53*7c478bd9Sstevel@tonic-gate #define RIGHT4			0x0f
54*7c478bd9Sstevel@tonic-gate #define CONTINUED_LINE_MARKER	'\001'
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #define ISBLANK(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') /* not "\r\v\f" */
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #define LDIF_OPT_ISSET( value, opt )	(((value) & (opt)) != 0 )
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate static char nib2b64[0x40] =
61*7c478bd9Sstevel@tonic-gate         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static unsigned char b642nib[0x80] = {
64*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69*7c478bd9Sstevel@tonic-gate 	0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
70*7c478bd9Sstevel@tonic-gate 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
71*7c478bd9Sstevel@tonic-gate 	0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72*7c478bd9Sstevel@tonic-gate 	0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
73*7c478bd9Sstevel@tonic-gate 	0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
74*7c478bd9Sstevel@tonic-gate 	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
75*7c478bd9Sstevel@tonic-gate 	0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
76*7c478bd9Sstevel@tonic-gate 	0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
77*7c478bd9Sstevel@tonic-gate 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
78*7c478bd9Sstevel@tonic-gate 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
79*7c478bd9Sstevel@tonic-gate 	0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
80*7c478bd9Sstevel@tonic-gate };
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate static int ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen,
83*7c478bd9Sstevel@tonic-gate 	int lenused, int wraplen );
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate /*
86*7c478bd9Sstevel@tonic-gate  * str_parse_line - takes a line of the form "type:[:] value" and splits it
87*7c478bd9Sstevel@tonic-gate  * into components "type" and "value".  if a double colon separates type from
88*7c478bd9Sstevel@tonic-gate  * value, then value is encoded in base 64, and parse_line un-decodes it
89*7c478bd9Sstevel@tonic-gate  * (in place) before returning.
90*7c478bd9Sstevel@tonic-gate  */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate int
str_parse_line(char * line,char ** type,char ** value,int * vlen)93*7c478bd9Sstevel@tonic-gate str_parse_line(
94*7c478bd9Sstevel@tonic-gate     char	*line,
95*7c478bd9Sstevel@tonic-gate     char	**type,
96*7c478bd9Sstevel@tonic-gate     char	**value,
97*7c478bd9Sstevel@tonic-gate     int		*vlen
98*7c478bd9Sstevel@tonic-gate )
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	char	*p, *s, *d;
101*7c478bd9Sstevel@tonic-gate 	int	b64;
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	/* skip any leading space */
104*7c478bd9Sstevel@tonic-gate 	while ( ISBLANK( *line ) ) {
105*7c478bd9Sstevel@tonic-gate 		line++;
106*7c478bd9Sstevel@tonic-gate 	}
107*7c478bd9Sstevel@tonic-gate 	*type = line;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	for ( s = line; *s && *s != ':'; s++ )
110*7c478bd9Sstevel@tonic-gate 		;	/* NULL */
111*7c478bd9Sstevel@tonic-gate 	if ( *s == '\0' ) {
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 		/* Comment-out while we address calling libldif from ns-back-ldbm
114*7c478bd9Sstevel@tonic-gate 			on NT. 1 of 3 */
115*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
116*7c478bd9Sstevel@tonic-gate 		/*
117*7c478bd9Sstevel@tonic-gate #endif
118*7c478bd9Sstevel@tonic-gate 		 LDAPDebug( LDAP_DEBUG_PARSE, "str_parse_line: missing ':' "
119*7c478bd9Sstevel@tonic-gate 			"on line \"%s\"\n", line, 0, 0 );
120*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
121*7c478bd9Sstevel@tonic-gate 		*/
122*7c478bd9Sstevel@tonic-gate #endif
123*7c478bd9Sstevel@tonic-gate 		return( -1 );
124*7c478bd9Sstevel@tonic-gate 	}
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	/* trim any space between type and : */
127*7c478bd9Sstevel@tonic-gate 	for ( p = s - 1; p > line && ISBLANK( *p ); p-- ) {
128*7c478bd9Sstevel@tonic-gate 		*p = '\0';
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate 	*s++ = '\0';
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	/* check for double : - indicates base 64 encoded value */
133*7c478bd9Sstevel@tonic-gate 	if ( *s == ':' ) {
134*7c478bd9Sstevel@tonic-gate 		s++;
135*7c478bd9Sstevel@tonic-gate 		b64 = 1;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	/* single : - normally encoded value */
138*7c478bd9Sstevel@tonic-gate 	} else {
139*7c478bd9Sstevel@tonic-gate 		b64 = 0;
140*7c478bd9Sstevel@tonic-gate 	}
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	/* skip space between : and value */
143*7c478bd9Sstevel@tonic-gate 	while ( ISBLANK( *s ) ) {
144*7c478bd9Sstevel@tonic-gate 		s++;
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	/*
148*7c478bd9Sstevel@tonic-gate 	 * If no value is present, return a zero-length string for
149*7c478bd9Sstevel@tonic-gate 	 * *value, with *vlen set to zero.
150*7c478bd9Sstevel@tonic-gate 	 */
151*7c478bd9Sstevel@tonic-gate 	if ( *s == '\0' ) {
152*7c478bd9Sstevel@tonic-gate 		*value = s;
153*7c478bd9Sstevel@tonic-gate 		*vlen = 0;
154*7c478bd9Sstevel@tonic-gate 		return( 0 );
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/* check for continued line markers that should be deleted */
158*7c478bd9Sstevel@tonic-gate 	for ( p = s, d = s; *p; p++ ) {
159*7c478bd9Sstevel@tonic-gate 		if ( *p != CONTINUED_LINE_MARKER )
160*7c478bd9Sstevel@tonic-gate 			*d++ = *p;
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	*d = '\0';
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	*value = s;
165*7c478bd9Sstevel@tonic-gate 	if ( b64 ) {
166*7c478bd9Sstevel@tonic-gate 		if (( *vlen = ldif_base64_decode( s, (unsigned char *)s ))
167*7c478bd9Sstevel@tonic-gate 		    < 0 ) {
168*7c478bd9Sstevel@tonic-gate 			/* Comment-out while we address calling libldif from ns-back-ldbm
169*7c478bd9Sstevel@tonic-gate 				on NT. 3 of 3 */
170*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
171*7c478bd9Sstevel@tonic-gate 		/*
172*7c478bd9Sstevel@tonic-gate #endif
173*7c478bd9Sstevel@tonic-gate 			 LDAPDebug( LDAP_DEBUG_ANY,
174*7c478bd9Sstevel@tonic-gate 			    "str_parse_line: invalid base 64 char on line \"%s\"\n",
175*7c478bd9Sstevel@tonic-gate 			    line, 0, 0 );
176*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
177*7c478bd9Sstevel@tonic-gate 		*/
178*7c478bd9Sstevel@tonic-gate #endif
179*7c478bd9Sstevel@tonic-gate 			return( -1 );
180*7c478bd9Sstevel@tonic-gate 		}
181*7c478bd9Sstevel@tonic-gate 		s[ *vlen ] = '\0';
182*7c478bd9Sstevel@tonic-gate 	} else {
183*7c478bd9Sstevel@tonic-gate 		*vlen = (int) (d - s);
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	return( 0 );
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate /*
191*7c478bd9Sstevel@tonic-gate  * ldif_base64_decode - take the BASE64-encoded characters in "src"
192*7c478bd9Sstevel@tonic-gate  * (a zero-terminated string) and decode them into the the buffer "dst".
193*7c478bd9Sstevel@tonic-gate  * "src" and "dst" can be the same if in-place decoding is desired.
194*7c478bd9Sstevel@tonic-gate  * "dst" must be large enough to hold the decoded octets.  No more than
195*7c478bd9Sstevel@tonic-gate  *	3 * strlen( src ) / 4 bytes will be produced.
196*7c478bd9Sstevel@tonic-gate  * "dst" may contain zero octets anywhere within it, but it is not
197*7c478bd9Sstevel@tonic-gate  *	zero-terminated by this function.
198*7c478bd9Sstevel@tonic-gate  *
199*7c478bd9Sstevel@tonic-gate  * The number of bytes copied to "dst" is returned if all goes well.
200*7c478bd9Sstevel@tonic-gate  * -1 is returned if the BASE64 encoding in "src" is invalid.
201*7c478bd9Sstevel@tonic-gate  */
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate int
ldif_base64_decode(char * src,unsigned char * dst)204*7c478bd9Sstevel@tonic-gate ldif_base64_decode( char *src, unsigned char *dst )
205*7c478bd9Sstevel@tonic-gate {
206*7c478bd9Sstevel@tonic-gate 	char		*p, *stop;
207*7c478bd9Sstevel@tonic-gate 	unsigned char	nib, *byte;
208*7c478bd9Sstevel@tonic-gate 	int		i, len;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	stop = strchr( src, '\0' );
211*7c478bd9Sstevel@tonic-gate 	byte = dst;
212*7c478bd9Sstevel@tonic-gate 	for ( p = src, len = 0; p < stop; p += 4, len += 3 ) {
213*7c478bd9Sstevel@tonic-gate 		for ( i = 0; i < 4; i++ ) {
214*7c478bd9Sstevel@tonic-gate 			if ( p[i] != '=' && (p[i] & 0x80 ||
215*7c478bd9Sstevel@tonic-gate 			    b642nib[ p[i] & 0x7f ] > 0x3f) ) {
216*7c478bd9Sstevel@tonic-gate 				return( -1 );
217*7c478bd9Sstevel@tonic-gate 			}
218*7c478bd9Sstevel@tonic-gate 		}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 		/* first digit */
221*7c478bd9Sstevel@tonic-gate 		nib = b642nib[ p[0] & 0x7f ];
222*7c478bd9Sstevel@tonic-gate 		byte[0] = nib << 2;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 		/* second digit */
225*7c478bd9Sstevel@tonic-gate 		nib = b642nib[ p[1] & 0x7f ];
226*7c478bd9Sstevel@tonic-gate 		byte[0] |= nib >> 4;
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 		/* third digit */
229*7c478bd9Sstevel@tonic-gate 		if ( p[2] == '=' ) {
230*7c478bd9Sstevel@tonic-gate 			len += 1;
231*7c478bd9Sstevel@tonic-gate 			break;
232*7c478bd9Sstevel@tonic-gate 		}
233*7c478bd9Sstevel@tonic-gate 		byte[1] = (nib & RIGHT4) << 4;
234*7c478bd9Sstevel@tonic-gate 		nib = b642nib[ p[2] & 0x7f ];
235*7c478bd9Sstevel@tonic-gate 		byte[1] |= nib >> 2;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		/* fourth digit */
238*7c478bd9Sstevel@tonic-gate 		if ( p[3] == '=' ) {
239*7c478bd9Sstevel@tonic-gate 			len += 2;
240*7c478bd9Sstevel@tonic-gate 			break;
241*7c478bd9Sstevel@tonic-gate 		}
242*7c478bd9Sstevel@tonic-gate 		byte[2] = (nib & RIGHT2) << 6;
243*7c478bd9Sstevel@tonic-gate 		nib = b642nib[ p[3] & 0x7f ];
244*7c478bd9Sstevel@tonic-gate 		byte[2] |= nib;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 		byte += 3;
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	return( len );
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate /*
253*7c478bd9Sstevel@tonic-gate  * str_getline - return the next "line" (minus newline) of input from a
254*7c478bd9Sstevel@tonic-gate  * string buffer of lines separated by newlines, terminated by \n\n
255*7c478bd9Sstevel@tonic-gate  * or \0.  this routine handles continued lines, bundling them into
256*7c478bd9Sstevel@tonic-gate  * a single big line before returning.  if a line begins with a white
257*7c478bd9Sstevel@tonic-gate  * space character, it is a continuation of the previous line. the white
258*7c478bd9Sstevel@tonic-gate  * space character (nb: only one char), and preceeding newline are changed
259*7c478bd9Sstevel@tonic-gate  * into CONTINUED_LINE_MARKER chars, to be deleted later by the
260*7c478bd9Sstevel@tonic-gate  * str_parse_line() routine above.
261*7c478bd9Sstevel@tonic-gate  *
262*7c478bd9Sstevel@tonic-gate  * it takes a pointer to a pointer to the buffer on the first call,
263*7c478bd9Sstevel@tonic-gate  * which it updates and must be supplied on subsequent calls.
264*7c478bd9Sstevel@tonic-gate  *
265*7c478bd9Sstevel@tonic-gate  * XXX need to update this function to also support <CR><LF> as EOL.
266*7c478bd9Sstevel@tonic-gate  * XXX supports <CR><LF> as of 07/29/1998 (richm)
267*7c478bd9Sstevel@tonic-gate  */
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate char *
str_getline(char ** next)270*7c478bd9Sstevel@tonic-gate str_getline( char **next )
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	char	*l;
273*7c478bd9Sstevel@tonic-gate 	char	c;
274*7c478bd9Sstevel@tonic-gate 	char	*p;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	if ( *next == NULL || **next == '\n' || **next == '\0' ) {
277*7c478bd9Sstevel@tonic-gate 		return( NULL );
278*7c478bd9Sstevel@tonic-gate 	}
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	while ( **next == '#' ) {	/* skip comment lines */
281*7c478bd9Sstevel@tonic-gate 		if (( *next = strchr( *next, '\n' )) == NULL ) {
282*7c478bd9Sstevel@tonic-gate 			return( NULL );
283*7c478bd9Sstevel@tonic-gate 		}
284*7c478bd9Sstevel@tonic-gate 		(*next)++;
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	l = *next;
288*7c478bd9Sstevel@tonic-gate 	while ( (*next = strchr( *next, '\n' )) != NULL ) {
289*7c478bd9Sstevel@tonic-gate 		p = *next - 1; /* pointer to character previous to the newline */
290*7c478bd9Sstevel@tonic-gate 		c = *(*next + 1); /* character after the newline */
291*7c478bd9Sstevel@tonic-gate 		if ( ISBLANK( c ) && c != '\n' ) {
292*7c478bd9Sstevel@tonic-gate 			/* DOS EOL is \r\n, so if the character before */
293*7c478bd9Sstevel@tonic-gate 			/* the \n is \r, continue it too */
294*7c478bd9Sstevel@tonic-gate 			if (*p == '\r')
295*7c478bd9Sstevel@tonic-gate 				*p = CONTINUED_LINE_MARKER;
296*7c478bd9Sstevel@tonic-gate 			**next = CONTINUED_LINE_MARKER;
297*7c478bd9Sstevel@tonic-gate 			*(*next+1) = CONTINUED_LINE_MARKER;
298*7c478bd9Sstevel@tonic-gate 		} else {
299*7c478bd9Sstevel@tonic-gate 			/* DOS EOL is \r\n, so if the character before */
300*7c478bd9Sstevel@tonic-gate 			/* the \n is \r, null it too */
301*7c478bd9Sstevel@tonic-gate 			if (*p == '\r')
302*7c478bd9Sstevel@tonic-gate 				*p = '\0';
303*7c478bd9Sstevel@tonic-gate 			*(*next)++ = '\0';
304*7c478bd9Sstevel@tonic-gate 			break;
305*7c478bd9Sstevel@tonic-gate 		}
306*7c478bd9Sstevel@tonic-gate 		(*next)++;
307*7c478bd9Sstevel@tonic-gate 	}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	return( l );
310*7c478bd9Sstevel@tonic-gate }
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate #define LDIF_SAFE_CHAR( c )		( (c) != '\r' && (c) != '\n' )
314*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_CHAR( c )	( LDIF_SAFE_CHAR(c) && isascii((c)) \
315*7c478bd9Sstevel@tonic-gate 					 && ( isprint((c)) || (c) == '\t' ))
316*7c478bd9Sstevel@tonic-gate #define LDIF_SAFE_INITCHAR( c )		( LDIF_SAFE_CHAR(c) && (c) != ':' \
317*7c478bd9Sstevel@tonic-gate 					 && (c) != ' ' && (c) != '<' )
318*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_INITCHAR( c ) ( LDIF_SAFE_INITCHAR( c ) && \
319*7c478bd9Sstevel@tonic-gate 					 ! ( isascii((c)) && isspace((c))))
320*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_FINALCHAR( c ) ( (c) != ' ' )
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value_with_options(char ** out,char * t,char * val,int vlen,unsigned long options)324*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_with_options( char **out, char *t, char *val,
325*7c478bd9Sstevel@tonic-gate 	int vlen, unsigned long options )
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	unsigned char	*p, *byte, *stop;
328*7c478bd9Sstevel@tonic-gate 	char		*save;
329*7c478bd9Sstevel@tonic-gate 	int		b64, len, savelen, wraplen;
330*7c478bd9Sstevel@tonic-gate 	len = 0;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	if ( LDIF_OPT_ISSET( options, LDIF_OPT_NOWRAP )) {
333*7c478bd9Sstevel@tonic-gate 		wraplen = -1;
334*7c478bd9Sstevel@tonic-gate 	} else {
335*7c478bd9Sstevel@tonic-gate 		wraplen = LDIF_MAX_LINE_WIDTH;
336*7c478bd9Sstevel@tonic-gate 	}
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	/* put the type + ": " */
339*7c478bd9Sstevel@tonic-gate 	for ( p = (unsigned char *) t; *p; p++, len++ ) {
340*7c478bd9Sstevel@tonic-gate 		*(*out)++ = *p;
341*7c478bd9Sstevel@tonic-gate 	}
342*7c478bd9Sstevel@tonic-gate 	*(*out)++ = ':';
343*7c478bd9Sstevel@tonic-gate 	len++;
344*7c478bd9Sstevel@tonic-gate 	if ( LDIF_OPT_ISSET( options, LDIF_OPT_VALUE_IS_URL )) {
345*7c478bd9Sstevel@tonic-gate 		*(*out)++ = '<';	/* add '<' for URLs */
346*7c478bd9Sstevel@tonic-gate 		len++;
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate 	save = *out;
349*7c478bd9Sstevel@tonic-gate 	savelen = len;
350*7c478bd9Sstevel@tonic-gate 	b64 = 0;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	stop = (unsigned char *)val;
353*7c478bd9Sstevel@tonic-gate 	if ( val && vlen > 0 ) {
354*7c478bd9Sstevel@tonic-gate 		*(*out)++ = ' ';
355*7c478bd9Sstevel@tonic-gate 		stop = (unsigned char *) (val + vlen);
356*7c478bd9Sstevel@tonic-gate 		if ( LDIF_OPT_ISSET( options, LDIF_OPT_MINIMAL_ENCODING )) {
357*7c478bd9Sstevel@tonic-gate 			if ( !LDIF_SAFE_INITCHAR( val[0] )) {
358*7c478bd9Sstevel@tonic-gate 				b64 = 1;
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 		} else {
361*7c478bd9Sstevel@tonic-gate 			if ( !LDIF_CONSERVATIVE_INITCHAR( val[0] ) ||
362*7c478bd9Sstevel@tonic-gate 				 !LDIF_CONSERVATIVE_FINALCHAR( val[vlen-1] )) {
363*7c478bd9Sstevel@tonic-gate 				b64 = 1;
364*7c478bd9Sstevel@tonic-gate 			}
365*7c478bd9Sstevel@tonic-gate 		}
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	if ( !b64 ) {
369*7c478bd9Sstevel@tonic-gate 		for ( byte = (unsigned char *) val; byte < stop;
370*7c478bd9Sstevel@tonic-gate 		    byte++, len++ ) {
371*7c478bd9Sstevel@tonic-gate 			if ( LDIF_OPT_ISSET( options,
372*7c478bd9Sstevel@tonic-gate 			    LDIF_OPT_MINIMAL_ENCODING )) {
373*7c478bd9Sstevel@tonic-gate 				if ( !LDIF_SAFE_CHAR( *byte )) {
374*7c478bd9Sstevel@tonic-gate 					b64 = 1;
375*7c478bd9Sstevel@tonic-gate 					break;
376*7c478bd9Sstevel@tonic-gate 				}
377*7c478bd9Sstevel@tonic-gate 			} else if ( !LDIF_CONSERVATIVE_CHAR( *byte )) {
378*7c478bd9Sstevel@tonic-gate 				b64 = 1;
379*7c478bd9Sstevel@tonic-gate 				break;
380*7c478bd9Sstevel@tonic-gate 			}
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 			if ( wraplen != -1 && len > wraplen ) {
383*7c478bd9Sstevel@tonic-gate 				*(*out)++ = '\n';
384*7c478bd9Sstevel@tonic-gate 				*(*out)++ = ' ';
385*7c478bd9Sstevel@tonic-gate 				len = 1;
386*7c478bd9Sstevel@tonic-gate 			}
387*7c478bd9Sstevel@tonic-gate 			*(*out)++ = *byte;
388*7c478bd9Sstevel@tonic-gate 		}
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	if ( b64 ) {
392*7c478bd9Sstevel@tonic-gate 		*out = save;
393*7c478bd9Sstevel@tonic-gate 		*(*out)++ = ':';
394*7c478bd9Sstevel@tonic-gate 		*(*out)++ = ' ';
395*7c478bd9Sstevel@tonic-gate 		len = ldif_base64_encode_internal( (unsigned char *)val, *out, vlen,
396*7c478bd9Sstevel@tonic-gate 		    savelen + 2, wraplen );
397*7c478bd9Sstevel@tonic-gate 		*out += len;
398*7c478bd9Sstevel@tonic-gate 	}
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	*(*out)++ = '\n';
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value(char ** out,char * t,char * val,int vlen)404*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value( char **out, char *t, char *val, int vlen )
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate     ldif_put_type_and_value_with_options( out, t, val, vlen, 0 );
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value_nowrap(char ** out,char * t,char * val,int vlen)410*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_nowrap( char **out, char *t, char *val, int vlen )
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate     ldif_put_type_and_value_with_options( out, t, val, vlen, LDIF_OPT_NOWRAP );
413*7c478bd9Sstevel@tonic-gate }
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate /*
416*7c478bd9Sstevel@tonic-gate  * ldif_base64_encode_internal - encode "srclen" bytes in "src", place BASE64
417*7c478bd9Sstevel@tonic-gate  * encoded bytes in "dst" and return the length of the BASE64
418*7c478bd9Sstevel@tonic-gate  * encoded string.  "dst" is also zero-terminated by this function.
419*7c478bd9Sstevel@tonic-gate  *
420*7c478bd9Sstevel@tonic-gate  * If "lenused" >= 0, newlines will be included in "dst" and "lenused" if
421*7c478bd9Sstevel@tonic-gate  * appropriate.  "lenused" should be a count of characters already used
422*7c478bd9Sstevel@tonic-gate  * on the current line.  The LDIF lines we create will contain at most
423*7c478bd9Sstevel@tonic-gate  * "wraplen" characters on each line, unless "wraplen" is -1, in which
424*7c478bd9Sstevel@tonic-gate  * case output line length is unlimited.
425*7c478bd9Sstevel@tonic-gate  *
426*7c478bd9Sstevel@tonic-gate  * If "lenused" < 0, no newlines will be included, and the LDIF_BASE64_LEN()
427*7c478bd9Sstevel@tonic-gate  * macro can be used to determine how many bytes will be placed in "dst."
428*7c478bd9Sstevel@tonic-gate  */
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate static int
ldif_base64_encode_internal(unsigned char * src,char * dst,int srclen,int lenused,int wraplen)431*7c478bd9Sstevel@tonic-gate ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, int lenused, int wraplen )
432*7c478bd9Sstevel@tonic-gate {
433*7c478bd9Sstevel@tonic-gate 	unsigned char	*byte, *stop;
434*7c478bd9Sstevel@tonic-gate 	unsigned char	buf[3];
435*7c478bd9Sstevel@tonic-gate 	char		*out;
436*7c478bd9Sstevel@tonic-gate 	unsigned long	bits;
437*7c478bd9Sstevel@tonic-gate 	int		i, pad, len;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	len = 0;
440*7c478bd9Sstevel@tonic-gate 	out = dst;
441*7c478bd9Sstevel@tonic-gate 	stop = src + srclen;
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	/* convert to base 64 (3 bytes => 4 base 64 digits) */
444*7c478bd9Sstevel@tonic-gate 	for ( byte = src; byte < stop - 2; byte += 3 ) {
445*7c478bd9Sstevel@tonic-gate 		bits = (byte[0] & 0xff) << 16;
446*7c478bd9Sstevel@tonic-gate 		bits |= (byte[1] & 0xff) << 8;
447*7c478bd9Sstevel@tonic-gate 		bits |= (byte[2] & 0xff);
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 		for ( i = 0; i < 4; i++, bits <<= 6 ) {
450*7c478bd9Sstevel@tonic-gate 			if ( wraplen != -1 &&  lenused >= 0 && lenused++ > wraplen ) {
451*7c478bd9Sstevel@tonic-gate 				*out++ = '\n';
452*7c478bd9Sstevel@tonic-gate 				*out++ = ' ';
453*7c478bd9Sstevel@tonic-gate 				lenused = 2;
454*7c478bd9Sstevel@tonic-gate 			}
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 			/* get b64 digit from high order 6 bits */
457*7c478bd9Sstevel@tonic-gate 			*out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
458*7c478bd9Sstevel@tonic-gate 		}
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	/* add padding if necessary */
462*7c478bd9Sstevel@tonic-gate 	if ( byte < stop ) {
463*7c478bd9Sstevel@tonic-gate 		for ( i = 0; byte + i < stop; i++ ) {
464*7c478bd9Sstevel@tonic-gate 			buf[i] = byte[i];
465*7c478bd9Sstevel@tonic-gate 		}
466*7c478bd9Sstevel@tonic-gate 		for ( pad = 0; i < 3; i++, pad++ ) {
467*7c478bd9Sstevel@tonic-gate 			buf[i] = '\0';
468*7c478bd9Sstevel@tonic-gate 		}
469*7c478bd9Sstevel@tonic-gate 		byte = buf;
470*7c478bd9Sstevel@tonic-gate 		bits = (byte[0] & 0xff) << 16;
471*7c478bd9Sstevel@tonic-gate 		bits |= (byte[1] & 0xff) << 8;
472*7c478bd9Sstevel@tonic-gate 		bits |= (byte[2] & 0xff);
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		for ( i = 0; i < 4; i++, bits <<= 6 ) {
475*7c478bd9Sstevel@tonic-gate 			if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) {
476*7c478bd9Sstevel@tonic-gate 				*out++ = '\n';
477*7c478bd9Sstevel@tonic-gate 				*out++ = ' ';
478*7c478bd9Sstevel@tonic-gate 				lenused = 2;
479*7c478bd9Sstevel@tonic-gate 			}
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 			if (( i == 3 && pad > 0 ) || ( i == 2 && pad == 2 )) {
482*7c478bd9Sstevel@tonic-gate 				/* Pad as appropriate */
483*7c478bd9Sstevel@tonic-gate 				*out++ = '=';
484*7c478bd9Sstevel@tonic-gate 			} else {
485*7c478bd9Sstevel@tonic-gate 				/* get b64 digit from low order 6 bits */
486*7c478bd9Sstevel@tonic-gate 				*out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
487*7c478bd9Sstevel@tonic-gate 			}
488*7c478bd9Sstevel@tonic-gate 		}
489*7c478bd9Sstevel@tonic-gate 	}
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	*out = '\0';
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	return( out - dst );
494*7c478bd9Sstevel@tonic-gate }
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate int
ldif_base64_encode(unsigned char * src,char * dst,int srclen,int lenused)497*7c478bd9Sstevel@tonic-gate ldif_base64_encode( unsigned char *src, char *dst, int srclen, int lenused )
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate     return ldif_base64_encode_internal( src, dst, srclen, lenused, LDIF_MAX_LINE_WIDTH );
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate int
ldif_base64_encode_nowrap(unsigned char * src,char * dst,int srclen,int lenused)503*7c478bd9Sstevel@tonic-gate ldif_base64_encode_nowrap( unsigned char *src, char *dst, int srclen, int lenused )
504*7c478bd9Sstevel@tonic-gate {
505*7c478bd9Sstevel@tonic-gate     return ldif_base64_encode_internal( src, dst, srclen, lenused, -1 );
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate /*
510*7c478bd9Sstevel@tonic-gate  * return malloc'd, zero-terminated LDIF line
511*7c478bd9Sstevel@tonic-gate  */
512*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value_with_options(char * type,char * val,int vlen,unsigned long options)513*7c478bd9Sstevel@tonic-gate ldif_type_and_value_with_options( char *type, char *val, int vlen,
514*7c478bd9Sstevel@tonic-gate 	unsigned long options )
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate     char	*buf, *p;
517*7c478bd9Sstevel@tonic-gate     int		tlen;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate     tlen = strlen( type );
520*7c478bd9Sstevel@tonic-gate     if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) !=
521*7c478bd9Sstevel@tonic-gate 	    NULL ) {
522*7c478bd9Sstevel@tonic-gate 	p = buf;
523*7c478bd9Sstevel@tonic-gate 	ldif_put_type_and_value_with_options( &p, type, val, vlen, options );
524*7c478bd9Sstevel@tonic-gate 	*p = '\0';
525*7c478bd9Sstevel@tonic-gate     }
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate     return( buf );
528*7c478bd9Sstevel@tonic-gate }
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value(char * type,char * val,int vlen)531*7c478bd9Sstevel@tonic-gate ldif_type_and_value( char *type, char *val, int vlen )
532*7c478bd9Sstevel@tonic-gate {
533*7c478bd9Sstevel@tonic-gate     return ldif_type_and_value_with_options( type, val, vlen, 0 );
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value_nowrap(char * type,char * val,int vlen)537*7c478bd9Sstevel@tonic-gate ldif_type_and_value_nowrap( char *type, char *val, int vlen )
538*7c478bd9Sstevel@tonic-gate {
539*7c478bd9Sstevel@tonic-gate     return ldif_type_and_value_with_options( type, val, vlen, LDIF_OPT_NOWRAP );
540*7c478bd9Sstevel@tonic-gate }
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate /*
543*7c478bd9Sstevel@tonic-gate  * ldif_get_entry - read the next ldif entry from the FILE referenced
544*7c478bd9Sstevel@tonic-gate  * by fp. return a pointer to a malloc'd, null-terminated buffer. also
545*7c478bd9Sstevel@tonic-gate  * returned is the last line number read, in *lineno.
546*7c478bd9Sstevel@tonic-gate  */
547*7c478bd9Sstevel@tonic-gate char *
ldif_get_entry(FILE * fp,int * lineno)548*7c478bd9Sstevel@tonic-gate ldif_get_entry( FILE *fp, int *lineno )
549*7c478bd9Sstevel@tonic-gate {
550*7c478bd9Sstevel@tonic-gate 	char	line[BUFSIZ];
551*7c478bd9Sstevel@tonic-gate 	char	*buf;
552*7c478bd9Sstevel@tonic-gate 	int	max, cur, len, gotsome;
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	buf = NULL;
555*7c478bd9Sstevel@tonic-gate 	max = cur = gotsome = 0;
556*7c478bd9Sstevel@tonic-gate 	while ( fgets( line, sizeof(line), fp ) != NULL ) {
557*7c478bd9Sstevel@tonic-gate 		if ( lineno != NULL ) {
558*7c478bd9Sstevel@tonic-gate 			(*lineno)++;
559*7c478bd9Sstevel@tonic-gate 		}
560*7c478bd9Sstevel@tonic-gate 		/* ldif entries are terminated by a \n on a line by itself */
561*7c478bd9Sstevel@tonic-gate 		if ( line[0] == '\0' || line[0] == '\n'
562*7c478bd9Sstevel@tonic-gate #if !defined( XP_WIN32 )
563*7c478bd9Sstevel@tonic-gate 		     || ( line[0] == '\r' && line[1] == '\n' ) /* DOS format */
564*7c478bd9Sstevel@tonic-gate #endif
565*7c478bd9Sstevel@tonic-gate 		   ) {
566*7c478bd9Sstevel@tonic-gate 			if ( gotsome ) {
567*7c478bd9Sstevel@tonic-gate 				break;
568*7c478bd9Sstevel@tonic-gate 			} else {
569*7c478bd9Sstevel@tonic-gate 				continue;
570*7c478bd9Sstevel@tonic-gate 			}
571*7c478bd9Sstevel@tonic-gate 		} else if ( line[0] == '#' ) {
572*7c478bd9Sstevel@tonic-gate 			continue;
573*7c478bd9Sstevel@tonic-gate 		}
574*7c478bd9Sstevel@tonic-gate 		gotsome = 1;
575*7c478bd9Sstevel@tonic-gate 		len = strlen( line );
576*7c478bd9Sstevel@tonic-gate #if !defined( XP_WIN32 )
577*7c478bd9Sstevel@tonic-gate 		/* DOS format */
578*7c478bd9Sstevel@tonic-gate 		if ( len > 0 && line[len-1] == '\r' ) {
579*7c478bd9Sstevel@tonic-gate 			--len;
580*7c478bd9Sstevel@tonic-gate 			line[len] = '\0';
581*7c478bd9Sstevel@tonic-gate 		} else if ( len > 1 && line[len-2] == '\r' && line[len-1] == '\n' ) {
582*7c478bd9Sstevel@tonic-gate 			--len;
583*7c478bd9Sstevel@tonic-gate 			line[len-1] = line[len];
584*7c478bd9Sstevel@tonic-gate 			line[len] = '\0';
585*7c478bd9Sstevel@tonic-gate 		}
586*7c478bd9Sstevel@tonic-gate #endif
587*7c478bd9Sstevel@tonic-gate 		while ( cur + (len + 1) > max ) {
588*7c478bd9Sstevel@tonic-gate 			if ( buf == NULL ) {
589*7c478bd9Sstevel@tonic-gate 				max += BUFSIZ;
590*7c478bd9Sstevel@tonic-gate 				buf = (char *) malloc( max );
591*7c478bd9Sstevel@tonic-gate 			} else {
592*7c478bd9Sstevel@tonic-gate 				max *= 2;
593*7c478bd9Sstevel@tonic-gate 				buf = (char *) realloc( buf, max );
594*7c478bd9Sstevel@tonic-gate 			}
595*7c478bd9Sstevel@tonic-gate 			if ( buf == NULL ) {
596*7c478bd9Sstevel@tonic-gate 				return( NULL );
597*7c478bd9Sstevel@tonic-gate 			}
598*7c478bd9Sstevel@tonic-gate 		}
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 		memcpy( buf + cur, line, len + 1 );
601*7c478bd9Sstevel@tonic-gate 		cur += len;
602*7c478bd9Sstevel@tonic-gate 	}
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 	return( buf );
605*7c478bd9Sstevel@tonic-gate }
606