add missing break (issue #5154)
[asterisk/asterisk.git] / utils.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Utility functions
5  *
6  * Copyright (C)  2004 - 2005, Digium, Inc.
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #include <ctype.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <stdarg.h>
24
25 #include "asterisk.h"
26
27 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28
29 #include "asterisk/lock.h"
30 #include "asterisk/io.h"
31 #include "asterisk/logger.h"
32 #include "asterisk/md5.h"
33 #include "asterisk/options.h"
34
35 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
36 #include "asterisk/strings.h"
37
38 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
39 #include "asterisk/time.h"
40
41 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
42 #include "asterisk/utils.h"
43
44 static char base64[64];
45 static char b2a[256];
46
47 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
48
49 /* duh? ERANGE value copied from web... */
50 #define ERANGE 34
51 #undef gethostbyname
52
53 AST_MUTEX_DEFINE_STATIC(__mutex);
54
55 /* Recursive replacement for gethostbyname for BSD-based systems.  This
56 routine is derived from code originally written and placed in the public 
57 domain by Enzo Michelangeli <em@em.no-ip.com> */
58
59 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
60                                 size_t buflen, struct hostent **result, 
61                                 int *h_errnop) 
62 {
63         int hsave;
64         struct hostent *ph;
65         ast_mutex_lock(&__mutex); /* begin critical area */
66         hsave = h_errno;
67
68         ph = gethostbyname(name);
69         *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
70         if (ph == NULL) {
71                 *result = NULL;
72         } else {
73                 char **p, **q;
74                 char *pbuf;
75                 int nbytes=0;
76                 int naddr=0, naliases=0;
77                 /* determine if we have enough space in buf */
78
79                 /* count how many addresses */
80                 for (p = ph->h_addr_list; *p != 0; p++) {
81                         nbytes += ph->h_length; /* addresses */
82                         nbytes += sizeof(*p); /* pointers */
83                         naddr++;
84                 }
85                 nbytes += sizeof(*p); /* one more for the terminating NULL */
86
87                 /* count how many aliases, and total length of strings */
88                 for (p = ph->h_aliases; *p != 0; p++) {
89                         nbytes += (strlen(*p)+1); /* aliases */
90                         nbytes += sizeof(*p);  /* pointers */
91                         naliases++;
92                 }
93                 nbytes += sizeof(*p); /* one more for the terminating NULL */
94
95                 /* here nbytes is the number of bytes required in buffer */
96                 /* as a terminator must be there, the minimum value is ph->h_length */
97                 if(nbytes > buflen) {
98                         *result = NULL;
99                         ast_mutex_unlock(&__mutex); /* end critical area */
100                         return ERANGE; /* not enough space in buf!! */
101                 }
102
103                 /* There is enough space. Now we need to do a deep copy! */
104                 /* Allocation in buffer:
105                         from [0] to [(naddr-1) * sizeof(*p)]:
106                         pointers to addresses
107                         at [naddr * sizeof(*p)]:
108                         NULL
109                         from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
110                         pointers to aliases
111                         at [(naddr+naliases+1) * sizeof(*p)]:
112                         NULL
113                         then naddr addresses (fixed length), and naliases aliases (asciiz).
114                 */
115
116                 *ret = *ph;   /* copy whole structure (not its address!) */
117
118                 /* copy addresses */
119                 q = (char **)buf; /* pointer to pointers area (type: char **) */
120                 ret->h_addr_list = q; /* update pointer to address list */
121                 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
122                 for (p = ph->h_addr_list; *p != 0; p++) {
123                         memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
124                         *q++ = pbuf; /* the pointer is the one inside buf... */
125                         pbuf += ph->h_length; /* advance pbuf */
126                 }
127                 *q++ = NULL; /* address list terminator */
128
129                 /* copy aliases */
130                 ret->h_aliases = q; /* update pointer to aliases list */
131                 for (p = ph->h_aliases; *p != 0; p++) {
132                         strcpy(pbuf, *p); /* copy alias strings */
133                         *q++ = pbuf; /* the pointer is the one inside buf... */
134                         pbuf += strlen(*p); /* advance pbuf */
135                         *pbuf++ = 0; /* string terminator */
136                 }
137                 *q++ = NULL; /* terminator */
138
139                 strcpy(pbuf, ph->h_name); /* copy alias strings */
140                 ret->h_name = pbuf;
141                 pbuf += strlen(ph->h_name); /* advance pbuf */
142                 *pbuf++ = 0; /* string terminator */
143
144                 *result = ret;  /* and let *result point to structure */
145
146         }
147         h_errno = hsave;  /* restore h_errno */
148         ast_mutex_unlock(&__mutex); /* end critical area */
149
150         return (*result == NULL); /* return 0 on success, non-zero on error */
151 }
152
153
154 #endif
155
156 /* Re-entrant (thread safe) version of gethostbyname that replaces the 
157    standard gethostbyname (which is not thread safe)
158 */
159 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
160 {
161         int res;
162         int herrno;
163         const char *s;
164         struct hostent *result = NULL;
165         /* Although it is perfectly legitimate to lookup a pure integer, for
166            the sake of the sanity of people who like to name their peers as
167            integers, we break with tradition and refuse to look up a
168            pure integer */
169         s = host;
170         res = 0;
171         while(s && *s) {
172                 if (!isdigit(*s))
173                         break;
174                 s++;
175         }
176         if (!s || !*s)
177                 return NULL;
178 #ifdef SOLARIS
179         result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
180
181         if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
182                 return NULL;
183 #else
184         res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
185
186         if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
187                 return NULL;
188 #endif
189         return &hp->hp;
190 }
191
192
193 /* This is a regression test for recursive mutexes.
194    test_for_thread_safety() will return 0 if recursive mutex locks are
195    working properly, and non-zero if they are not working properly. */
196
197 AST_MUTEX_DEFINE_STATIC(test_lock);
198 AST_MUTEX_DEFINE_STATIC(test_lock2);
199 static pthread_t test_thread; 
200 static int lock_count = 0;
201 static int test_errors = 0;
202
203 static void *test_thread_body(void *data) 
204
205         ast_mutex_lock(&test_lock);
206         lock_count += 10;
207         if (lock_count != 10) 
208                 test_errors++;
209         ast_mutex_lock(&test_lock);
210         lock_count += 10;
211         if (lock_count != 20) 
212                 test_errors++;
213         ast_mutex_lock(&test_lock2);
214         ast_mutex_unlock(&test_lock);
215         lock_count -= 10;
216         if (lock_count != 10) 
217                 test_errors++;
218         ast_mutex_unlock(&test_lock);
219         lock_count -= 10;
220         ast_mutex_unlock(&test_lock2);
221         if (lock_count != 0) 
222                 test_errors++;
223         return NULL;
224
225
226 int test_for_thread_safety(void)
227
228         ast_mutex_lock(&test_lock2);
229         ast_mutex_lock(&test_lock);
230         lock_count += 1;
231         ast_mutex_lock(&test_lock);
232         lock_count += 1;
233         ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
234         usleep(100);
235         if (lock_count != 2) 
236                 test_errors++;
237         ast_mutex_unlock(&test_lock);
238         lock_count -= 1;
239         usleep(100); 
240         if (lock_count != 1) 
241                 test_errors++;
242         ast_mutex_unlock(&test_lock);
243         lock_count -= 1;
244         if (lock_count != 0) 
245                 test_errors++;
246         ast_mutex_unlock(&test_lock2);
247         usleep(100);
248         if (lock_count != 0) 
249                 test_errors++;
250         pthread_join(test_thread, NULL);
251         return(test_errors);          /* return 0 on success. */
252 }
253
254 /*--- ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
255 void ast_md5_hash(char *output, char *input)
256 {
257         struct MD5Context md5;
258         unsigned char digest[16];
259         char *ptr;
260         int x;
261
262         MD5Init(&md5);
263         MD5Update(&md5, (unsigned char *)input, strlen(input));
264         MD5Final(digest, &md5);
265         ptr = output;
266         for (x=0; x<16; x++)
267                 ptr += sprintf(ptr, "%2.2x", digest[x]);
268 }
269
270 int ast_base64decode(unsigned char *dst, char *src, int max)
271 {
272         int cnt = 0;
273         unsigned int byte = 0;
274         unsigned int bits = 0;
275         int incnt = 0;
276 #if 0
277         unsigned char *odst = dst;
278 #endif
279         while(*src && (cnt < max)) {
280                 /* Shift in 6 bits of input */
281                 byte <<= 6;
282                 byte |= (b2a[(int)(*src)]) & 0x3f;
283                 bits += 6;
284 #if 0
285                 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
286 #endif
287                 src++;
288                 incnt++;
289                 /* If we have at least 8 bits left over, take that character 
290                    off the top */
291                 if (bits >= 8)  {
292                         bits -= 8;
293                         *dst = (byte >> bits) & 0xff;
294 #if 0
295                         printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
296 #endif
297                         dst++;
298                         cnt++;
299                 }
300         }
301 #if 0
302         dump(odst, cnt);
303 #endif
304         /* Dont worry about left over bits, they're extra anyway */
305         return cnt;
306 }
307
308 int ast_base64encode(char *dst, unsigned char *src, int srclen, int max)
309 {
310         int cnt = 0;
311         unsigned int byte = 0;
312         int bits = 0;
313         int index;
314         int cntin = 0;
315 #if 0
316         char *odst = dst;
317         dump(src, srclen);
318 #endif
319         /* Reserve one bit for end */
320         max--;
321         while((cntin < srclen) && (cnt < max)) {
322                 byte <<= 8;
323 #if 0
324                 printf("Add: %02x %s\n", *src, binary(*src, 8));
325 #endif
326                 byte |= *(src++);
327                 bits += 8;
328                 cntin++;
329                 while((bits >= 6) && (cnt < max)) {
330                         bits -= 6;
331                         /* We want only the top */
332                         index = (byte >> bits) & 0x3f;
333                         *dst = base64[index];
334 #if 0
335                         printf("Remove: %c %s\n", *dst, binary(index, 6));
336 #endif
337                         dst++;
338                         cnt++;
339                 }
340         }
341         if (bits && (cnt < max)) {
342                 /* Add one last character for the remaining bits, 
343                    padding the rest with 0 */
344                 byte <<= (6 - bits);
345                 index = (byte) & 0x3f;
346                 *(dst++) = base64[index];
347                 cnt++;
348         }
349         *dst = '\0';
350         return cnt;
351 }
352
353 static void base64_init(void)
354 {
355         int x;
356         memset(b2a, -1, sizeof(b2a));
357         /* Initialize base-64 Conversion table */
358         for (x=0;x<26;x++) {
359                 /* A-Z */
360                 base64[x] = 'A' + x;
361                 b2a['A' + x] = x;
362                 /* a-z */
363                 base64[x + 26] = 'a' + x;
364                 b2a['a' + x] = x + 26;
365                 /* 0-9 */
366                 if (x < 10) {
367                         base64[x + 52] = '0' + x;
368                         b2a['0' + x] = x + 52;
369                 }
370         }
371         base64[62] = '+';
372         base64[63] = '/';
373         b2a[(int)'+'] = 62;
374         b2a[(int)'/'] = 63;
375 #if 0
376         for (x=0;x<64;x++) {
377                 if (b2a[(int)base64[x]] != x) {
378                         fprintf(stderr, "!!! %d failed\n", x);
379                 } else
380                         fprintf(stderr, "--- %d passed\n", x);
381         }
382 #endif
383 }
384
385 /*--- ast_uri_encode: Turn text string to URI-encoded %XX version ---*/
386 /*      At this point, we're converting from ISO-8859-x (8-bit), not UTF8
387         as in the SIP protocol spec 
388         If doreserved == 1 we will convert reserved characters also.
389         RFC 2396, section 2.4
390         outbuf needs to have more memory allocated than the instring
391         to have room for the expansion. Every char that is converted
392         is replaced by three ASCII characters.
393
394         Note: The doreserved option is needed for replaces header in
395         SIP transfers.
396 */
397 char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved) 
398 {
399         char *reserved = ";/?:@&=+$, "; /* Reserved chars */
400
401         char *ptr  = string;    /* Start with the string */
402         char *out = NULL;
403         char *buf = NULL;
404
405         strncpy(outbuf, string, buflen);
406
407         /* If there's no characters to convert, just go through and don't do anything */
408         while (*ptr) {
409                 if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
410                         /* Oops, we need to start working here */
411                         if (!buf) {
412                                 buf = outbuf;
413                                 out = buf + (ptr - string) ;    /* Set output ptr */
414                         }
415                         out += sprintf(out, "%%%02x", (unsigned char) *ptr);
416                 } else if (buf) {
417                         *out = *ptr;    /* Continue copying the string */
418                         out++;
419                 } 
420                 ptr++;
421         }
422         if (buf)
423                 *out = '\0';
424         return outbuf;
425 }
426
427 /*--- ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string)  ---*/
428 void ast_uri_decode(char *s) 
429 {
430         char *o;
431         unsigned int tmp;
432
433         for (o = s; *s; s++, o++) {
434                 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
435                         /* have '%', two chars and correct parsing */
436                         *o = tmp;
437                         s += 2; /* Will be incremented once more when we break out */
438                 } else /* all other cases, just copy */
439                         *o = *s;
440         }
441         *o = '\0';
442 }
443
444 /*--- ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
445 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
446 {
447         return inet_ntop(AF_INET, &ia, buf, bufsiz);
448 }
449
450 int ast_utils_init(void)
451 {
452         base64_init();
453         return 0;
454 }
455
456 #ifndef __linux__
457 #undef pthread_create /* For ast_pthread_create function only */
458 #endif /* ! LINUX */
459
460 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
461 {
462         pthread_attr_t lattr;
463         if (!attr) {
464                 pthread_attr_init(&lattr);
465                 attr = &lattr;
466         }
467         if (!stacksize)
468                 stacksize = AST_STACKSIZE;
469         errno = pthread_attr_setstacksize(attr, stacksize);
470         if (errno)
471                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
472         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
473 }
474
475 int ast_wait_for_input(int fd, int ms)
476 {
477         struct pollfd pfd[1];
478         memset(pfd, 0, sizeof(pfd));
479         pfd[0].fd = fd;
480         pfd[0].events = POLLIN|POLLPRI;
481         return poll(pfd, 1, ms);
482 }
483
484 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
485 {
486         char *e;
487         char *q;
488
489         s = ast_strip(s);
490         if ((q = strchr(beg_quotes, *s))) {
491                 e = s + strlen(s) - 1;
492                 if (*e == *(end_quotes + (q - beg_quotes))) {
493                         s++;
494                         *e = '\0';
495                 }
496         }
497
498         return s;
499 }
500
501 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
502 {
503         va_list ap;
504         int result;
505
506         if (!buffer || !*buffer || !space || !*space)
507                 return -1;
508
509         va_start(ap, fmt);
510         result = vsnprintf(*buffer, *space, fmt, ap);
511         va_end(ap);
512
513         if (result < 0)
514                 return -1;
515         else if (result > *space)
516                 result = *space;
517
518         *buffer += result;
519         *space -= result;
520         return 0;
521 }
522
523 int ast_true(const char *s)
524 {
525         if (!s || ast_strlen_zero(s))
526                 return 0;
527
528         /* Determine if this is a true value */
529         if (!strcasecmp(s, "yes") ||
530             !strcasecmp(s, "true") ||
531             !strcasecmp(s, "y") ||
532             !strcasecmp(s, "t") ||
533             !strcasecmp(s, "1") ||
534             !strcasecmp(s, "on"))
535                 return -1;
536
537         return 0;
538 }
539
540 int ast_false(const char *s)
541 {
542         if (!s || ast_strlen_zero(s))
543                 return 0;
544
545         /* Determine if this is a false value */
546         if (!strcasecmp(s, "no") ||
547             !strcasecmp(s, "false") ||
548             !strcasecmp(s, "n") ||
549             !strcasecmp(s, "f") ||
550             !strcasecmp(s, "0") ||
551             !strcasecmp(s, "off"))
552                 return -1;
553
554         return 0;
555 }
556
557 #define ONE_MILLION     1000000
558 /*
559  * put timeval in a valid range. usec is 0..999999
560  * negative values are not allowed and truncated.
561  */
562 static struct timeval tvfix(struct timeval a)
563 {
564         if (a.tv_usec >= ONE_MILLION) {
565                 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
566                         a.tv_sec, (long int) a.tv_usec);
567                 a.tv_sec += a.tv_usec % ONE_MILLION;
568                 a.tv_usec %= ONE_MILLION;
569         } else if (a.tv_usec < 0) {
570                 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
571                                 a.tv_sec, (long int) a.tv_usec);
572                 a.tv_usec = 0;
573         }
574         return a;
575 }
576
577 struct timeval ast_tvadd(struct timeval a, struct timeval b)
578 {
579         /* consistency checks to guarantee usec in 0..999999 */
580         a = tvfix(a);
581         b = tvfix(b);
582         a.tv_sec += b.tv_sec;
583         a.tv_usec += b.tv_usec;
584         if (a.tv_usec >= ONE_MILLION) {
585                 a.tv_sec++;
586                 a.tv_usec -= ONE_MILLION;
587         }
588         return a;
589 }
590
591 struct timeval ast_tvsub(struct timeval a, struct timeval b)
592 {
593         /* consistency checks to guarantee usec in 0..999999 */
594         a = tvfix(a);
595         b = tvfix(b);
596         a.tv_sec -= b.tv_sec;
597         a.tv_usec -= b.tv_usec;
598         if (a.tv_usec < 0) {
599                 a.tv_sec-- ;
600                 a.tv_usec += ONE_MILLION;
601         }
602         return a;
603 }
604 #undef ONE_MILLION
605
606 #ifndef HAVE_STRCASESTR
607 static char *upper(const char *orig, char *buf, int bufsize)
608 {
609         int i = 0;
610
611         while (i < (bufsize - 1) && orig[i]) {
612                 buf[i] = toupper(orig[i]);
613                 i++;
614         }
615
616         buf[i] = '\0';
617
618         return buf;
619 }
620
621 char *strcasestr(const char *haystack, const char *needle)
622 {
623         char *u1, *u2;
624         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
625
626         u1 = alloca(u1len);
627         u2 = alloca(u2len);
628         if (u1 && u2) {
629                 char *offset;
630                 if (u2len > u1len) {
631                         /* Needle bigger than haystack */
632                         return NULL;
633                 }
634                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
635                 if (offset) {
636                         /* Return the offset into the original string */
637                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
638                 } else {
639                         return NULL;
640                 }
641         } else {
642                 ast_log(LOG_ERROR, "Out of memory\n");
643                 return NULL;
644         }
645 }
646 #endif
647
648 #ifndef HAVE_STRNLEN
649 size_t strnlen(const char *s, size_t n)
650 {
651         size_t len;
652
653         for (len=0; len < n; len++)
654                 if (s[len] == '\0')
655                         break;
656
657         return len;
658 }
659 #endif
660
661 #ifndef HAVE_STRNDUP
662 char *strndup(const char *s, size_t n)
663 {
664         size_t len = strnlen(s, n);
665         char *new = malloc(len + 1);
666
667         if (!new)
668                 return NULL;
669
670         new[len] = '\0';
671         return memcpy(new, s, len);
672 }
673 #endif
674
675 #ifndef HAVE_VASPRINTF
676 int vasprintf(char **strp, const char *fmt, va_list ap)
677 {
678         int size;
679         va_list ap2;
680         char s;
681
682         *strp = NULL;
683         va_copy(ap2, ap);
684         size = vsnprintf(&s, 1, fmt, ap2);
685         va_end(ap2);
686         *strp = malloc(size + 1);
687         if (!*strp)
688                 return -1;
689         vsnprintf(*strp, size + 1, fmt, ap);
690
691         return size;
692 }
693 #endif
694
695 #ifndef HAVE_STRTOQ
696 #define LONG_MIN        (-9223372036854775807L-1L)
697                                          /* min value of a "long int" */
698 #define LONG_MAX        9223372036854775807L
699                                          /* max value of a "long int" */
700
701 /*
702  * Convert a string to a quad integer.
703  *
704  * Ignores `locale' stuff.  Assumes that the upper and lower case
705  * alphabets and digits are each contiguous.
706  */
707 uint64_t strtoq(const char *nptr, char **endptr, int base)
708 {
709          const char *s;
710          uint64_t acc;
711          unsigned char c;
712          uint64_t qbase, cutoff;
713          int neg, any, cutlim;
714
715          /*
716           * Skip white space and pick up leading +/- sign if any.
717           * If base is 0, allow 0x for hex and 0 for octal, else
718           * assume decimal; if base is already 16, allow 0x.
719           */
720          s = nptr;
721          do {
722                  c = *s++;
723          } while (isspace(c));
724          if (c == '-') {
725                  neg = 1;
726                  c = *s++;
727          } else {
728                  neg = 0;
729                  if (c == '+')
730                          c = *s++;
731          }
732          if ((base == 0 || base == 16) &&
733              c == '\0' && (*s == 'x' || *s == 'X')) {
734                  c = s[1];
735                  s += 2;
736                  base = 16;
737          }
738          if (base == 0)
739                  base = c == '\0' ? 8 : 10;
740
741          /*
742           * Compute the cutoff value between legal numbers and illegal
743           * numbers.  That is the largest legal value, divided by the
744           * base.  An input number that is greater than this value, if
745           * followed by a legal input character, is too big.  One that
746           * is equal to this value may be valid or not; the limit
747           * between valid and invalid numbers is then based on the last
748           * digit.  For instance, if the range for quads is
749           * [-9223372036854775808..9223372036854775807] and the input base
750           * is 10, cutoff will be set to 922337203685477580 and cutlim to
751           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
752           * accumulated a value > 922337203685477580, or equal but the
753           * next digit is > 7 (or 8), the number is too big, and we will
754           * return a range error.
755           *
756           * Set any if any `digits' consumed; make it negative to indicate
757           * overflow.
758           */
759          qbase = (unsigned)base;
760          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
761          cutlim = cutoff % qbase;
762          cutoff /= qbase;
763          for (acc = 0, any = 0;; c = *s++) {
764                  if (!isascii(c))
765                          break;
766                  if (isdigit(c))
767                          c -= '\0';
768                  else if (isalpha(c))
769                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
770                  else
771                          break;
772                  if (c >= base)
773                          break;
774                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
775                          any = -1;
776                  else {
777                          any = 1;
778                          acc *= qbase;
779                          acc += c;
780                  }
781          }
782          if (any < 0) {
783                  acc = neg ? LONG_MIN : LONG_MAX;
784          } else if (neg)
785                  acc = -acc;
786          if (endptr != 0)
787                  *((const char **)endptr) = any ? s - 1 : nptr;
788          return acc;
789 }
790 #endif