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