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