38643fdd52a6b2a59e381dc7f2a41d2ab02f2151
[asterisk/asterisk.git] / main / strcompat.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Compatibility functions for strsep and strtoq missing on Solaris 
20  */
21
22 #include "asterisk.h"
23
24 #include <sys/types.h>
25 #include <ctype.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <alloca.h>
29 #include <string.h>
30
31 #ifndef HAVE_STRSEP
32 char *strsep(char **str, const char *delims)
33 {
34     char *token;
35
36     if (!*str) {
37         /* No more tokens */
38         return NULL;
39     }
40
41     token = *str;
42     while (**str != '\0') {
43         if (strchr(delims, **str)) {
44             **str = '\0';
45             (*str)++;
46             return token;
47         }
48         (*str)++;
49     }
50
51     /* There is no other token */
52     *str = NULL;
53
54     return token;
55 }
56 #endif
57
58 #ifndef HAVE_SETENV
59 int setenv(const char *name, const char *value, int overwrite)
60 {
61         unsigned char *buf;
62         int buflen;
63
64         buflen = strlen(name) + strlen(value) + 2;
65         buf = alloca(buflen);
66
67         if (!overwrite && getenv(name))
68                 return 0;
69
70         snprintf(buf, buflen, "%s=%s", name, value);
71
72         return putenv(buf);
73 }
74 #endif
75
76 #ifndef HAVE_UNSETENV
77 int unsetenv(const char *name)
78 {
79         return setenv(name, "", 0);
80 }
81 #endif
82
83 #ifndef HAVE_STRCASESTR
84 static char *upper(const char *orig, char *buf, int bufsize)
85 {
86         int i = 0;
87
88         while (i < (bufsize - 1) && orig[i]) {
89                 buf[i] = toupper(orig[i]);
90                 i++;
91         }
92
93         buf[i] = '\0';
94
95         return buf;
96 }
97
98 char *strcasestr(const char *haystack, const char *needle)
99 {
100         char *u1, *u2;
101         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
102
103         u1 = alloca(u1len);
104         u2 = alloca(u2len);
105         if (u1 && u2) {
106                 char *offset;
107                 if (u2len > u1len) {
108                         /* Needle bigger than haystack */
109                         return NULL;
110                 }
111                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
112                 if (offset) {
113                         /* Return the offset into the original string */
114                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
115                 } else {
116                         return NULL;
117                 }
118         } else {
119                 return NULL;
120         }
121 }
122 #endif /* !HAVE_STRCASESTR */
123
124 #ifndef HAVE_STRNLEN
125 size_t strnlen(const char *s, size_t n)
126 {
127         size_t len;
128
129         for (len = 0; len < n; len++)
130                 if (s[len] == '\0')
131                         break;
132
133         return len;
134 }
135 #endif /* !HAVE_STRNLEN */
136
137 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
138 char *strndup(const char *s, size_t n)
139 {
140         size_t len = strnlen(s, n);
141         char *new = malloc(len + 1);
142
143         if (!new)
144                 return NULL;
145
146         new[len] = '\0';
147         return memcpy(new, s, len);
148 }
149 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
150
151 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
152 int vasprintf(char **strp, const char *fmt, va_list ap)
153 {
154         int size;
155         va_list ap2;
156         char s;
157
158         *strp = NULL;
159         va_copy(ap2, ap);
160         size = vsnprintf(&s, 1, fmt, ap2);
161         va_end(ap2);
162         *strp = malloc(size + 1);
163         if (!*strp)
164                 return -1;
165         vsnprintf(*strp, size + 1, fmt, ap);
166
167         return size;
168 }
169 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
170
171 /*
172  * Based on Code from bsd-asprintf from OpenSSH
173  * Copyright (c) 2004 Darren Tucker.
174  *
175  * Based originally on asprintf.c from OpenBSD:
176  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
177  *
178  * Permission to use, copy, modify, and distribute this software for any
179  * purpose with or without fee is hereby granted, provided that the above
180  * copyright notice and this permission notice appear in all copies.
181  *
182  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
183  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
184  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
185  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
186  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
187  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
188  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
189  */
190 #if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) 
191 int asprintf(char **str, const char *fmt, ...)
192 {
193         va_list ap;
194         int ret;
195
196         *str = NULL;
197         va_start(ap, fmt);
198         ret = vasprintf(str, fmt, ap);
199         va_end(ap);
200
201         return ret;
202 }
203 #endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
204
205 #ifndef HAVE_STRTOQ
206 #ifndef LONG_MIN
207 #define LONG_MIN        (-9223372036854775807L-1L)
208                                          /* min value of a "long int" */
209 #endif
210 #ifndef LONG_MAX
211 #define LONG_MAX        9223372036854775807L
212                                          /* max value of a "long int" */
213 #endif
214
215 /*! \brief
216  * Convert a string to a quad integer.
217  *
218  * \note Ignores `locale' stuff.  Assumes that the upper and lower case
219  * alphabets and digits are each contiguous.
220  */
221 uint64_t strtoq(const char *nptr, char **endptr, int base)
222 {
223          const char *s;
224          uint64_t acc;
225          unsigned char c;
226          uint64_t qbase, cutoff;
227          int neg, any, cutlim;
228
229          /*
230           * Skip white space and pick up leading +/- sign if any.
231           * If base is 0, allow 0x for hex and 0 for octal, else
232           * assume decimal; if base is already 16, allow 0x.
233           */
234          s = nptr;
235          do {
236                  c = *s++;
237          } while (isspace(c));
238          if (c == '-') {
239                  neg = 1;
240                  c = *s++;
241          } else {
242                  neg = 0;
243                  if (c == '+')
244                          c = *s++;
245          }
246          if ((base == 0 || base == 16) &&
247              c == '\0' && (*s == 'x' || *s == 'X')) {
248                  c = s[1];
249                  s += 2;
250                  base = 16;
251          }
252          if (base == 0)
253                  base = c == '\0' ? 8 : 10;
254
255          /*
256           * Compute the cutoff value between legal numbers and illegal
257           * numbers.  That is the largest legal value, divided by the
258           * base.  An input number that is greater than this value, if
259           * followed by a legal input character, is too big.  One that
260           * is equal to this value may be valid or not; the limit
261           * between valid and invalid numbers is then based on the last
262           * digit.  For instance, if the range for quads is
263           * [-9223372036854775808..9223372036854775807] and the input base
264           * is 10, cutoff will be set to 922337203685477580 and cutlim to
265           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
266           * accumulated a value > 922337203685477580, or equal but the
267           * next digit is > 7 (or 8), the number is too big, and we will
268           * return a range error.
269           *
270           * Set any if any `digits' consumed; make it negative to indicate
271           * overflow.
272           */
273          qbase = (unsigned)base;
274          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
275          cutlim = cutoff % qbase;
276          cutoff /= qbase;
277          for (acc = 0, any = 0;; c = *s++) {
278                  if (!isascii(c))
279                          break;
280                  if (isdigit(c))
281                          c -= '\0';
282                  else if (isalpha(c))
283                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
284                  else
285                          break;
286                  if (c >= base)
287                          break;
288                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
289                          any = -1;
290                  else {
291                          any = 1;
292                          acc *= qbase;
293                          acc += c;
294                  }
295          }
296          if (any < 0) {
297                  acc = neg ? LONG_MIN : LONG_MAX;
298          } else if (neg)
299                  acc = -acc;
300          if (endptr != 0)
301                  *((const char **)endptr) = any ? s - 1 : nptr;
302          return acc;
303 }
304 #endif /* !HAVE_STRTOQ */
305
306 #ifndef HAVE_GETLOADAVG
307 #ifdef linux
308 /*! \brief Alternative method of getting load avg on Linux only */
309 int getloadavg(double *list, int nelem)
310 {
311         FILE *LOADAVG;
312         double avg[3] = { 0.0, 0.0, 0.0 };
313         int i, res = -1;
314
315         if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
316                 fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
317                 res = 0;
318                 fclose(LOADAVG);
319         }
320
321         for (i = 0; (i < nelem) && (i < 3); i++) {
322                 list[i] = avg[i];
323         }
324
325         return res;
326 }
327 #else /* !linux */
328 /*! \brief Return something that won't cancel the call, but still return -1, in case
329  * we correct the implementation to check return value */
330 int getloadavg(double *list, int nelem)
331 {
332         int i;
333
334         for (i = 0; i < nelem; i++) {
335                 list[i] = 0.1;
336         }
337         return -1;
338 }
339 #endif /* linux */
340 #endif /* !HAVE_GETLOADAVG */