xref: /netbsd-src/external/bsd/openldap/dist/libraries/liblutil/utils.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: utils.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/liblutil/utils.c,v 1.33.2.26 2009/12/02 18:34:37 hyc Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include "portable.h"
19 
20 #include <stdio.h>
21 #include <ac/stdlib.h>
22 #include <ac/stdarg.h>
23 #include <ac/string.h>
24 #include <ac/ctype.h>
25 #include <ac/unistd.h>
26 #include <ac/time.h>
27 #include <ac/errno.h>
28 #ifdef HAVE_IO_H
29 #include <io.h>
30 #endif
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
34 #ifdef _WIN32
35 #include <windows.h>
36 #endif
37 
38 #include "lutil.h"
39 #include "ldap_defaults.h"
40 #include "ldap_pvt.h"
41 #include "lber_pvt.h"
42 
43 #ifdef HAVE_EBCDIC
44 int _trans_argv = 1;
45 #endif
46 
47 #ifdef _WIN32
48 /* Some Windows versions accept both forward and backslashes in
49  * directory paths, but we always use backslashes when generating
50  * and parsing...
51  */
52 void lutil_slashpath( char *path )
53 {
54 	char *c, *p;
55 
56 	p = path;
57 	while (( c=strchr( p, '/' ))) {
58 		*c++ = '\\';
59 		p = c;
60 	}
61 }
62 #endif
63 
64 char* lutil_progname( const char* name, int argc, char *argv[] )
65 {
66 	char *progname;
67 
68 	if(argc == 0) {
69 		return (char *)name;
70 	}
71 
72 #ifdef HAVE_EBCDIC
73 	if (_trans_argv) {
74 		int i;
75 		for (i=0; i<argc; i++) __etoa(argv[i]);
76 		_trans_argv = 0;
77 	}
78 #endif
79 	LUTIL_SLASHPATH( argv[0] );
80 	progname = strrchr ( argv[0], *LDAP_DIRSEP );
81 	progname = progname ? &progname[1] : argv[0];
82 #ifdef _WIN32
83 	{
84 		size_t len = strlen( progname );
85 		if ( len > 4 && strcasecmp( &progname[len - 4], ".exe" ) == 0 )
86 			progname[len - 4] = '\0';
87 	}
88 #endif
89 	return progname;
90 }
91 
92 #if 0
93 size_t lutil_gentime( char *s, size_t smax, const struct tm *tm )
94 {
95 	size_t ret;
96 #ifdef HAVE_EBCDIC
97 /* We've been compiling in ASCII so far, but we want EBCDIC now since
98  * strftime only understands EBCDIC input.
99  */
100 #pragma convlit(suspend)
101 #endif
102 	ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm );
103 #ifdef HAVE_EBCDIC
104 #pragma convlit(resume)
105 	__etoa( s );
106 #endif
107 	return ret;
108 }
109 #endif
110 
111 size_t lutil_localtime( char *s, size_t smax, const struct tm *tm, long delta )
112 {
113 	size_t	ret;
114 	char	*p;
115 
116 	if ( smax < 16 ) {	/* YYYYmmddHHMMSSZ */
117 		return 0;
118 	}
119 
120 #ifdef HAVE_EBCDIC
121 /* We've been compiling in ASCII so far, but we want EBCDIC now since
122  * strftime only understands EBCDIC input.
123  */
124 #pragma convlit(suspend)
125 #endif
126 	ret = strftime( s, smax, "%Y%m%d%H%M%SZ", tm );
127 #ifdef HAVE_EBCDIC
128 #pragma convlit(resume)
129 	__etoa( s );
130 #endif
131 	if ( delta == 0 || ret == 0 ) {
132 		return ret;
133 	}
134 
135 	if ( smax < 20 ) {	/* YYYYmmddHHMMSS+HHMM */
136 		return 0;
137 	}
138 
139 	p = s + 14;
140 
141 	if ( delta < 0 ) {
142 		p[ 0 ] = '-';
143 		delta = -delta;
144 	} else {
145 		p[ 0 ] = '+';
146 	}
147 	p++;
148 
149 	snprintf( p, smax - 15, "%02ld%02ld", delta / 3600,
150 			( delta % 3600 ) / 60 );
151 
152 	return ret + 5;
153 }
154 
155 int lutil_tm2time( struct lutil_tm *tm, struct lutil_timet *tt )
156 {
157 	static int moffset[12] = {
158 		0, 31, 59, 90, 120,
159 		151, 181, 212, 243,
160 		273, 304, 334 };
161 	int sec;
162 
163 	tt->tt_usec = tm->tm_usec;
164 
165 	/* special case 0000/01/01+00:00:00 is returned as zero */
166 	if ( tm->tm_year == -1900 && tm->tm_mon == 0 && tm->tm_mday == 1 &&
167 		tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0 ) {
168 		tt->tt_sec = 0;
169 		tt->tt_gsec = 0;
170 		return 0;
171 	}
172 
173 	/* tm->tm_year is years since 1900 */
174 	/* calculate days from years since 1970 (epoch) */
175 	tt->tt_sec = tm->tm_year - 70;
176 	tt->tt_sec *= 365L;
177 
178 	/* count leap days in preceding years */
179 	tt->tt_sec += ((tm->tm_year -69) >> 2);
180 
181 	/* calculate days from months */
182 	tt->tt_sec += moffset[tm->tm_mon];
183 
184 	/* add in this year's leap day, if any */
185 	if (((tm->tm_year & 3) == 0) && (tm->tm_mon > 1)) {
186 		tt->tt_sec ++;
187 	}
188 
189 	/* add in days in this month */
190 	tt->tt_sec += (tm->tm_mday - 1);
191 
192 	/* this function can handle a range of about 17408 years... */
193 	/* 86400 seconds in a day, divided by 128 = 675 */
194 	tt->tt_sec *= 675;
195 
196 	/* move high 7 bits into tt_gsec */
197 	tt->tt_gsec = tt->tt_sec >> 25;
198 	tt->tt_sec -= tt->tt_gsec << 25;
199 
200 	/* get hours */
201 	sec = tm->tm_hour;
202 
203 	/* convert to minutes */
204 	sec *= 60L;
205 	sec += tm->tm_min;
206 
207 	/* convert to seconds */
208 	sec *= 60L;
209 	sec += tm->tm_sec;
210 
211 	/* add remaining seconds */
212 	tt->tt_sec <<= 7;
213 	tt->tt_sec += sec;
214 
215 	/* return success */
216 	return 0;
217 }
218 
219 int lutil_parsetime( char *atm, struct lutil_tm *tm )
220 {
221 	while (atm && tm) {
222 		char *ptr = atm;
223 		unsigned i, fracs;
224 
225 		/* Is the stamp reasonably long? */
226 		for (i=0; isdigit((unsigned char) atm[i]); i++);
227 		if (i < sizeof("00000101000000")-1)
228 			break;
229 
230 		/*
231 		 * parse the time into a struct tm
232 		 */
233 		/* 4 digit year to year - 1900 */
234 		tm->tm_year = *ptr++ - '0';
235 		tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
236 		tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
237 		tm->tm_year *= 10; tm->tm_year += *ptr++ - '0';
238 		tm->tm_year -= 1900;
239 		/* month 01-12 to 0-11 */
240 		tm->tm_mon = *ptr++ - '0';
241 		tm->tm_mon *=10; tm->tm_mon += *ptr++ - '0';
242 		if (tm->tm_mon < 1 || tm->tm_mon > 12) break;
243 		tm->tm_mon--;
244 
245 		/* day of month 01-31 */
246 		tm->tm_mday = *ptr++ - '0';
247 		tm->tm_mday *=10; tm->tm_mday += *ptr++ - '0';
248 		if (tm->tm_mday < 1 || tm->tm_mday > 31) break;
249 
250 		/* Hour 00-23 */
251 		tm->tm_hour = *ptr++ - '0';
252 		tm->tm_hour *=10; tm->tm_hour += *ptr++ - '0';
253 		if (tm->tm_hour < 0 || tm->tm_hour > 23) break;
254 
255 		/* Minute 00-59 */
256 		tm->tm_min = *ptr++ - '0';
257 		tm->tm_min *=10; tm->tm_min += *ptr++ - '0';
258 		if (tm->tm_min < 0 || tm->tm_min > 59) break;
259 
260 		/* Second 00-61 */
261 		tm->tm_sec = *ptr++ - '0';
262 		tm->tm_sec *=10; tm->tm_sec += *ptr++ - '0';
263 		if (tm->tm_sec < 0 || tm->tm_sec > 61) break;
264 
265 		/* Fractions of seconds */
266 		if ( *ptr == '.' ) {
267 			ptr++;
268 			for (i = 0, fracs = 0; isdigit((unsigned char) *ptr); ) {
269 				i*=10; i+= *ptr++ - '0';
270 				fracs++;
271 			}
272 			tm->tm_usec = i;
273 			if (i) {
274 				for (i = fracs; i<6; i++)
275 					tm->tm_usec *= 10;
276 			}
277 		}
278 
279 		/* Must be UTC */
280 		if (*ptr != 'Z') break;
281 
282 		return 0;
283 	}
284 	return -1;
285 }
286 
287 /* return a broken out time, with microseconds
288  * Must be mutex-protected.
289  */
290 #ifdef _WIN32
291 /* Windows SYSTEMTIME only has 10 millisecond resolution, so we
292  * also need to use a high resolution timer to get microseconds.
293  * This is pretty clunky.
294  */
295 void
296 lutil_gettime( struct lutil_tm *tm )
297 {
298 	static LARGE_INTEGER cFreq;
299 	static LARGE_INTEGER prevCount;
300 	static int subs;
301 	static int offset;
302 	LARGE_INTEGER count;
303 	SYSTEMTIME st;
304 
305 	GetSystemTime( &st );
306 	QueryPerformanceCounter( &count );
307 
308 	/* It shouldn't ever go backwards, but multiple CPUs might
309 	 * be able to hit in the same tick.
310 	 */
311 	if ( count.QuadPart <= prevCount.QuadPart ) {
312 		subs++;
313 	} else {
314 		subs = 0;
315 		prevCount = count;
316 	}
317 
318 	/* We assume Windows has at least a vague idea of
319 	 * when a second begins. So we align our microsecond count
320 	 * with the Windows millisecond count using this offset.
321 	 * We retain the submillisecond portion of our own count.
322 	 *
323 	 * Note - this also assumes that the relationship between
324 	 * the PerformanceCouunter and SystemTime stays constant;
325 	 * that assumption breaks if the SystemTime is adjusted by
326 	 * an external action.
327 	 */
328 	if ( !cFreq.QuadPart ) {
329 		long long t;
330 		int usec;
331 		QueryPerformanceFrequency( &cFreq );
332 
333 		/* just get sub-second portion of counter */
334 		t = count.QuadPart % cFreq.QuadPart;
335 
336 		/* convert to microseconds */
337 		t *= 1000000;
338 		usec = t / cFreq.QuadPart;
339 
340 		offset = usec - st.wMilliseconds * 1000;
341 	}
342 
343 	tm->tm_usub = subs;
344 
345 	/* convert to microseconds */
346 	count.QuadPart %= cFreq.QuadPart;
347 	count.QuadPart *= 1000000;
348 	count.QuadPart /= cFreq.QuadPart;
349 	count.QuadPart -= offset;
350 
351 	tm->tm_usec = count.QuadPart % 1000000;
352 	if ( tm->tm_usec < 0 )
353 		tm->tm_usec += 1000000;
354 
355 	/* any difference larger than microseconds is
356 	 * already reflected in st
357 	 */
358 
359 	tm->tm_sec = st.wSecond;
360 	tm->tm_min = st.wMinute;
361 	tm->tm_hour = st.wHour;
362 	tm->tm_mday = st.wDay;
363 	tm->tm_mon = st.wMonth - 1;
364 	tm->tm_year = st.wYear - 1900;
365 }
366 #else
367 void
368 lutil_gettime( struct lutil_tm *ltm )
369 {
370 	struct timeval tv;
371 	static struct timeval prevTv;
372 	static int subs;
373 
374 #ifdef HAVE_GMTIME_R
375 	struct tm tm_buf;
376 #endif
377 	struct tm *tm;
378 	time_t t;
379 
380 	gettimeofday( &tv, NULL );
381 	t = tv.tv_sec;
382 
383 	if ( tv.tv_sec < prevTv.tv_sec
384 		|| ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec <= prevTv.tv_usec )) {
385 		subs++;
386 	} else {
387 		subs = 0;
388 		prevTv = tv;
389 	}
390 
391 	ltm->tm_usub = subs;
392 
393 #ifdef HAVE_GMTIME_R
394 	tm = gmtime_r( &t, &tm_buf );
395 #else
396 	tm = gmtime( &t );
397 #endif
398 
399 	ltm->tm_sec = tm->tm_sec;
400 	ltm->tm_min = tm->tm_min;
401 	ltm->tm_hour = tm->tm_hour;
402 	ltm->tm_mday = tm->tm_mday;
403 	ltm->tm_mon = tm->tm_mon;
404 	ltm->tm_year = tm->tm_year;
405 	ltm->tm_usec = tv.tv_usec;
406 }
407 #endif
408 
409 /* strcopy is like strcpy except it returns a pointer to the trailing NUL of
410  * the result string. This allows fast construction of catenated strings
411  * without the overhead of strlen/strcat.
412  */
413 char *
414 lutil_strcopy(
415 	char *a,
416 	const char *b
417 )
418 {
419 	if (!a || !b)
420 		return a;
421 
422 	while ((*a++ = *b++)) ;
423 	return a-1;
424 }
425 
426 /* strncopy is like strcpy except it returns a pointer to the trailing NUL of
427  * the result string. This allows fast construction of catenated strings
428  * without the overhead of strlen/strcat.
429  */
430 char *
431 lutil_strncopy(
432 	char *a,
433 	const char *b,
434 	size_t n
435 )
436 {
437 	if (!a || !b || n == 0)
438 		return a;
439 
440 	while ((*a++ = *b++) && n-- > 0) ;
441 	return a-1;
442 }
443 
444 /* memcopy is like memcpy except it returns a pointer to the byte past
445  * the end of the result buffer, set to NULL. This allows fast construction
446  * of catenated buffers.  Provided for API consistency with lutil_str*copy().
447  */
448 char *
449 lutil_memcopy(
450 	char *a,
451 	const char *b,
452 	size_t n
453 )
454 {
455 	AC_MEMCPY(a, b, n);
456 	return a + n;
457 }
458 
459 #ifndef HAVE_MKSTEMP
460 int mkstemp( char * template )
461 {
462 #ifdef HAVE_MKTEMP
463 	return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 );
464 #else
465 	return -1;
466 #endif
467 }
468 #endif
469 
470 #ifdef _MSC_VER
471 /* Equivalent of MS CRT's _dosmaperr().
472  * @param lastError[in] Result of GetLastError().
473  */
474 static errno_t win2errno(DWORD lastError)
475 {
476 	const struct {
477 		DWORD   windows_code;
478 		errno_t errno_code;
479 	} WIN2ERRNO_TABLE[] = {
480 		{ ERROR_SUCCESS, 0 },
481 		{ ERROR_FILE_NOT_FOUND, ENOENT },
482 		{ ERROR_PATH_NOT_FOUND, ENOENT },
483 		{ ERROR_TOO_MANY_OPEN_FILES, EMFILE },
484 		{ ERROR_ACCESS_DENIED, EACCES },
485 		{ ERROR_INVALID_HANDLE, EBADF },
486 		{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
487 		{ ERROR_LOCK_VIOLATION, EACCES },
488 		{ ERROR_FILE_EXISTS, EEXIST },
489 		{ ERROR_INVALID_PARAMETER, EINVAL },
490 		{ ERROR_FILENAME_EXCED_RANGE, ENAMETOOLONG },
491 	};
492 	const unsigned int WIN2ERRNO_TABLE_SIZE = sizeof(WIN2ERRNO_TABLE) /
493 sizeof(WIN2ERRNO_TABLE[0]);
494 	const errno_t DEFAULT_ERRNO_ERROR = -1;
495 	unsigned int i;
496 
497 	for (i = 0; i < WIN2ERRNO_TABLE_SIZE; ++i) {
498 		if (WIN2ERRNO_TABLE[i].windows_code == lastError) {
499 			return WIN2ERRNO_TABLE[i].errno_code;
500 		}
501 	}
502 	return DEFAULT_ERRNO_ERROR;
503 }
504 
505 struct dirent {
506 	char *d_name;
507 };
508 typedef struct DIR {
509 	HANDLE dir;
510 	struct dirent data;
511 	int first;
512 	char buf[MAX_PATH+1];
513 } DIR;
514 DIR *opendir( char *path )
515 {
516 	char tmp[32768];
517 	int len = strlen(path);
518 	DIR *d;
519 	HANDLE h;
520 	WIN32_FIND_DATA data;
521 
522 	if (len+3 >= sizeof(tmp)) {
523 		errno = ENAMETOOLONG;
524 		return NULL;
525 	}
526 
527 	strcpy(tmp, path);
528 	tmp[len++] = '\\';
529 	tmp[len++] = '*';
530 	tmp[len] = '\0';
531 
532 	h = FindFirstFile( tmp, &data );
533 
534 	if ( h == INVALID_HANDLE_VALUE ) {
535 		errno = win2errno( GetLastError());
536 		return NULL;
537 	}
538 
539 	d = ber_memalloc( sizeof(DIR) );
540 	if ( !d )
541 		return NULL;
542 	d->dir = h;
543 	d->data.d_name = d->buf;
544 	d->first = 1;
545 	strcpy(d->data.d_name, data.cFileName);
546 	return d;
547 }
548 struct dirent *readdir(DIR *dir)
549 {
550 	WIN32_FIND_DATA data;
551 
552 	if (dir->first) {
553 		dir->first = 0;
554 	} else {
555 		if (!FindNextFile(dir->dir, &data))
556 			return NULL;
557 		strcpy(dir->data.d_name, data.cFileName);
558 	}
559 	return &dir->data;
560 }
561 int closedir(DIR *dir)
562 {
563 	FindClose(dir->dir);
564 	ber_memfree(dir);
565 }
566 #endif
567 
568 /*
569  * Memory Reverse Search
570  */
571 void *
572 (lutil_memrchr)(const void *b, int c, size_t n)
573 {
574 	if (n != 0) {
575 		const unsigned char *s, *bb = b, cc = c;
576 
577 		for ( s = bb + n; s > bb; ) {
578 			if ( *--s == cc ) {
579 				return (void *) s;
580 			}
581 		}
582 	}
583 
584 	return NULL;
585 }
586 
587 int
588 lutil_atoix( int *v, const char *s, int x )
589 {
590 	char		*next;
591 	long		i;
592 
593 	assert( s != NULL );
594 	assert( v != NULL );
595 
596 	i = strtol( s, &next, x );
597 	if ( next == s || next[ 0 ] != '\0' ) {
598 		return -1;
599 	}
600 
601 	if ( (long)(int)i != i ) {
602 		return 1;
603 	}
604 
605 	*v = (int)i;
606 
607 	return 0;
608 }
609 
610 int
611 lutil_atoux( unsigned *v, const char *s, int x )
612 {
613 	char		*next;
614 	unsigned long	u;
615 
616 	assert( s != NULL );
617 	assert( v != NULL );
618 
619 	/* strtoul() has an odd interface */
620 	if ( s[ 0 ] == '-' ) {
621 		return -1;
622 	}
623 
624 	u = strtoul( s, &next, x );
625 	if ( next == s || next[ 0 ] != '\0' ) {
626 		return -1;
627 	}
628 
629 	if ( (unsigned long)(unsigned)u != u ) {
630 		return 1;
631 	}
632 
633 	*v = u;
634 
635 	return 0;
636 }
637 
638 int
639 lutil_atolx( long *v, const char *s, int x )
640 {
641 	char		*next;
642 	long		l;
643 
644 	assert( s != NULL );
645 	assert( v != NULL );
646 
647 	l = strtol( s, &next, x );
648 	if ( next == s || next[ 0 ] != '\0' ) {
649 		return -1;
650 	}
651 
652 	*v = l;
653 
654 	return 0;
655 }
656 
657 int
658 lutil_atoulx( unsigned long *v, const char *s, int x )
659 {
660 	char		*next;
661 	unsigned long	ul;
662 
663 	assert( s != NULL );
664 	assert( v != NULL );
665 
666 	/* strtoul() has an odd interface */
667 	if ( s[ 0 ] == '-' ) {
668 		return -1;
669 	}
670 
671 	ul = strtoul( s, &next, x );
672 	if ( next == s || next[ 0 ] != '\0' ) {
673 		return -1;
674 	}
675 
676 	*v = ul;
677 
678 	return 0;
679 }
680 
681 /* Multiply an integer by 100000000 and add new */
682 typedef struct lutil_int_decnum {
683 	unsigned char *buf;
684 	int bufsiz;
685 	int beg;
686 	int len;
687 } lutil_int_decnum;
688 
689 #define	FACTOR1	(100000000&0xffff)
690 #define FACTOR2 (100000000>>16)
691 
692 static void
693 scale( int new, lutil_int_decnum *prev, unsigned char *tmp )
694 {
695 	int i, j;
696 	unsigned char *in = prev->buf+prev->beg;
697 	unsigned int part;
698 	unsigned char *out = tmp + prev->bufsiz - prev->len;
699 
700 	memset( tmp, 0, prev->bufsiz );
701 	if ( prev->len ) {
702 		for ( i = prev->len-1; i>=0; i-- ) {
703 			part = in[i] * FACTOR1;
704 			for ( j = i; part; j-- ) {
705 				part += out[j];
706 				out[j] = part & 0xff;
707 				part >>= 8;
708 			}
709 			part = in[i] * FACTOR2;
710 			for ( j = i-2; part; j-- ) {
711 				part += out[j];
712 				out[j] = part & 0xff;
713 				part >>= 8;
714 			}
715 		}
716 		j++;
717 		prev->beg += j;
718 		prev->len -= j;
719 	}
720 
721 	out = tmp + prev->bufsiz;
722 	i = 0;
723 	do {
724 		i--;
725 		new += out[i];
726 		out[i] = new & 0xff;
727 		new >>= 8;
728 	} while ( new );
729 	i = -i;
730 	if ( prev->len < i ) {
731 		prev->beg = prev->bufsiz - i;
732 		prev->len = i;
733 	}
734 	AC_MEMCPY( prev->buf+prev->beg, tmp+prev->beg, prev->len );
735 }
736 
737 /* Convert unlimited length decimal or hex string to binary.
738  * Output buffer must be provided, bv_len must indicate buffer size
739  * Hex input can be "0x1234" or "'1234'H"
740  *
741  * Temporarily modifies the input string.
742  *
743  * Note: High bit of binary form is always the sign bit. If the number
744  * is supposed to be positive but has the high bit set, a zero byte
745  * is prepended. It is assumed that this has already been handled on
746  * any hex input.
747  */
748 int
749 lutil_str2bin( struct berval *in, struct berval *out, void *ctx )
750 {
751 	char *pin, *pout, ctmp;
752 	char *end;
753 	int i, chunk, len, rc = 0, hex = 0;
754 	if ( !out || !out->bv_val || out->bv_len < in->bv_len )
755 		return -1;
756 
757 	pout = out->bv_val;
758 	/* Leading "0x" for hex input */
759 	if ( in->bv_len > 2 && in->bv_val[0] == '0' &&
760 		( in->bv_val[1] == 'x' || in->bv_val[1] == 'X' ) )
761 	{
762 		len = in->bv_len - 2;
763 		pin = in->bv_val + 2;
764 		hex = 1;
765 	} else if ( in->bv_len > 3 && in->bv_val[0] == '\'' &&
766 		in->bv_val[in->bv_len-2] == '\'' &&
767 		in->bv_val[in->bv_len-1] == 'H' )
768 	{
769 		len = in->bv_len - 3;
770 		pin = in->bv_val + 1;
771 		hex = 1;
772 	}
773 	if ( hex ) {
774 #define HEXMAX	(2 * sizeof(long))
775 		unsigned long l;
776 		/* Convert a longword at a time, but handle leading
777 		 * odd bytes first
778 		 */
779 		chunk = len % HEXMAX;
780 		if ( !chunk )
781 			chunk = HEXMAX;
782 
783 		while ( len ) {
784 			int ochunk;
785 			ctmp = pin[chunk];
786 			pin[chunk] = '\0';
787 			errno = 0;
788 			l = strtoul( pin, &end, 16 );
789 			pin[chunk] = ctmp;
790 			if ( errno )
791 				return -1;
792 			ochunk = (chunk + 1)/2;
793 			for ( i = ochunk - 1; i >= 0; i-- ) {
794 				pout[i] = l & 0xff;
795 				l >>= 8;
796 			}
797 			pin += chunk;
798 			pout += ochunk;
799 			len -= chunk;
800 			chunk = HEXMAX;
801 		}
802 		out->bv_len = pout - out->bv_val;
803 	} else {
804 	/* Decimal */
805 		char tmpbuf[64], *tmp;
806 		lutil_int_decnum num;
807 		int neg = 0;
808 		long l;
809 
810 		len = in->bv_len;
811 		pin = in->bv_val;
812 		num.buf = (unsigned char *)out->bv_val;
813 		num.bufsiz = out->bv_len;
814 		num.beg = num.bufsiz-1;
815 		num.len = 0;
816 		if ( pin[0] == '-' ) {
817 			neg = 0xff;
818 			len--;
819 			pin++;
820 		}
821 
822 #define	DECMAX	8	/* 8 digits at a time */
823 
824 		/* tmp must be at least as large as outbuf */
825 		if ( out->bv_len > sizeof(tmpbuf)) {
826 			tmp = ber_memalloc_x( out->bv_len, ctx );
827 		} else {
828 			tmp = tmpbuf;
829 		}
830 		chunk = len & (DECMAX-1);
831 		if ( !chunk )
832 			chunk = DECMAX;
833 
834 		while ( len ) {
835 			ctmp = pin[chunk];
836 			pin[chunk] = '\0';
837 			errno = 0;
838 			l = strtol( pin, &end, 10 );
839 			pin[chunk] = ctmp;
840 			if ( errno ) {
841 				rc = -1;
842 				goto decfail;
843 			}
844 			scale( l, &num, (unsigned char *)tmp );
845 			pin += chunk;
846 			len -= chunk;
847 			chunk = DECMAX;
848 		}
849 		/* Negate the result */
850 		if ( neg ) {
851 			unsigned char *ptr;
852 
853 			ptr = num.buf+num.beg;
854 
855 			/* flip all bits */
856 			for ( i=0; i<num.len; i++ )
857 				ptr[i] ^= 0xff;
858 
859 			/* add 1, with carry - overflow handled below */
860 			while ( i-- && ! (ptr[i] = (ptr[i] + 1) & 0xff )) ;
861 		}
862 		/* Prepend sign byte if wrong sign bit */
863 		if (( num.buf[num.beg] ^ neg ) & 0x80 ) {
864 			num.beg--;
865 			num.len++;
866 			num.buf[num.beg] = neg;
867 		}
868 		if ( num.beg )
869 			AC_MEMCPY( num.buf, num.buf+num.beg, num.len );
870 		out->bv_len = num.len;
871 decfail:
872 		if ( tmp != tmpbuf ) {
873 			ber_memfree_x( tmp, ctx );
874 		}
875 	}
876 	return rc;
877 }
878 
879 static	char		time_unit[] = "dhms";
880 
881 /* Used to parse and unparse time intervals, not timestamps */
882 int
883 lutil_parse_time(
884 	const char	*in,
885 	unsigned long	*tp )
886 {
887 	unsigned long	t = 0;
888 	char		*s,
889 			*next;
890 	int		sofar = -1,
891 			scale[] = { 86400, 3600, 60, 1 };
892 
893 	*tp = 0;
894 
895 	for ( s = (char *)in; s[ 0 ] != '\0'; ) {
896 		unsigned long	u;
897 		char		*what;
898 
899 		/* strtoul() has an odd interface */
900 		if ( s[ 0 ] == '-' ) {
901 			return -1;
902 		}
903 
904 		u = strtoul( s, &next, 10 );
905 		if ( next == s ) {
906 			return -1;
907 		}
908 
909 		if ( next[ 0 ] == '\0' ) {
910 			/* assume seconds */
911 			t += u;
912 			break;
913 		}
914 
915 		what = strchr( time_unit, next[ 0 ] );
916 		if ( what == NULL ) {
917 			return -1;
918 		}
919 
920 		if ( what - time_unit <= sofar ) {
921 			return -1;
922 		}
923 
924 		sofar = what - time_unit;
925 		t += u * scale[ sofar ];
926 
927 		s = &next[ 1 ];
928 	}
929 
930 	*tp = t;
931 	return 0;
932 }
933 
934 int
935 lutil_unparse_time(
936 	char			*buf,
937 	size_t			buflen,
938 	unsigned long		t )
939 {
940 	int		len, i;
941 	unsigned long	v[ 4 ];
942 	char		*ptr = buf;
943 
944 	v[ 0 ] = t/86400;
945 	v[ 1 ] = (t%86400)/3600;
946 	v[ 2 ] = (t%3600)/60;
947 	v[ 3 ] = t%60;
948 
949 	for ( i = 0; i < 4; i++ ) {
950 		if ( v[i] > 0 || ( i == 3 && ptr == buf ) ) {
951 			len = snprintf( ptr, buflen, "%lu%c", v[ i ], time_unit[ i ] );
952 			if ( len < 0 || (unsigned)len >= buflen ) {
953 				return -1;
954 			}
955 			buflen -= len;
956 			ptr += len;
957 		}
958 	}
959 
960 	return 0;
961 }
962 
963 /*
964  * formatted print to string
965  *
966  * - if return code < 0, the error code returned by vsnprintf(3) is returned
967  *
968  * - if return code > 0, the buffer was not long enough;
969  *	- if next is not NULL, *next will be set to buf + bufsize - 1
970  *	- if len is not NULL, *len will contain the required buffer length
971  *
972  * - if return code == 0, the buffer was long enough;
973  *	- if next is not NULL, *next will point to the end of the string printed so far
974  *	- if len is not NULL, *len will contain the length of the string printed so far
975  */
976 int
977 lutil_snprintf( char *buf, ber_len_t bufsize, char **next, ber_len_t *len, LDAP_CONST char *fmt, ... )
978 {
979 	va_list		ap;
980 	int		ret;
981 
982 	assert( buf != NULL );
983 	assert( bufsize > 0 );
984 	assert( fmt != NULL );
985 
986 	va_start( ap, fmt );
987 	ret = vsnprintf( buf, bufsize, fmt, ap );
988 	va_end( ap );
989 
990 	if ( ret < 0 ) {
991 		return ret;
992 	}
993 
994 	if ( len ) {
995 		*len = ret;
996 	}
997 
998 	if ( (unsigned) ret >= bufsize ) {
999 		if ( next ) {
1000 			*next = &buf[ bufsize - 1 ];
1001 		}
1002 
1003 		return 1;
1004 	}
1005 
1006 	if ( next ) {
1007 		*next = &buf[ ret ];
1008 	}
1009 
1010 	return 0;
1011 }
1012 
1013