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