Remove status_response callbacks where they are not needed.
[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 <ctype.h>
25 #include <sys/time.h>       /* for getrlimit(2) */
26 #include <sys/resource.h>   /* for getrlimit(2) */
27 #include <sys/types.h>      /* for opendir(3) */
28 #include <dirent.h>         /* for opendir(3) */
29
30 #ifndef HAVE_STRSEP
31 char *strsep(char **str, const char *delims)
32 {
33         char *token;
34
35         if (!*str) {
36                 /* No more tokens */
37                 return NULL;
38         }
39
40         token = *str;
41         while (**str != '\0') {
42                 if (strchr(delims, **str)) {
43                         **str = '\0';
44                         (*str)++;
45                         return token;
46                 }
47                 (*str)++;
48         }
49
50         /* There is no other token */
51         *str = NULL;
52
53         return token;
54 }
55 #endif
56
57 #ifndef HAVE_SETENV
58 int setenv(const char *name, const char *value, int overwrite)
59 {
60         unsigned char *buf;
61         int buflen;
62
63         buflen = strlen(name) + strlen(value) + 2;
64         buf = alloca(buflen);
65
66         if (!overwrite && getenv(name))
67                 return 0;
68
69         snprintf(buf, buflen, "%s=%s", name, value);
70
71         return putenv(buf);
72 }
73 #endif
74
75 #ifndef HAVE_UNSETENV
76 int unsetenv(const char *name)
77 {
78         return setenv(name, "", 0);
79 }
80 #endif
81
82 #ifndef HAVE_STRCASESTR
83 static char *upper(const char *orig, char *buf, int bufsize)
84 {
85         int i = 0;
86
87         while (i < (bufsize - 1) && orig[i]) {
88                 buf[i] = toupper(orig[i]);
89                 i++;
90         }
91
92         buf[i] = '\0';
93
94         return buf;
95 }
96
97 char *strcasestr(const char *haystack, const char *needle)
98 {
99         char *u1, *u2;
100         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
101
102         u1 = alloca(u1len);
103         u2 = alloca(u2len);
104         if (u1 && u2) {
105                 char *offset;
106                 if (u2len > u1len) {
107                         /* Needle bigger than haystack */
108                         return NULL;
109                 }
110                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
111                 if (offset) {
112                         /* Return the offset into the original string */
113                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
114                 } else {
115                         return NULL;
116                 }
117         } else {
118                 return NULL;
119         }
120 }
121 #endif /* !HAVE_STRCASESTR */
122
123 #ifndef HAVE_STRNLEN
124 size_t strnlen(const char *s, size_t n)
125 {
126         size_t len;
127
128         for (len = 0; len < n; len++)
129                 if (s[len] == '\0')
130                         break;
131
132         return len;
133 }
134 #endif /* !HAVE_STRNLEN */
135
136 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
137 char *strndup(const char *s, size_t n)
138 {
139         size_t len = strnlen(s, n);
140         char *new = malloc(len + 1);
141
142         if (!new)
143                 return NULL;
144
145         new[len] = '\0';
146         return memcpy(new, s, len);
147 }
148 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
149
150 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
151 int vasprintf(char **strp, const char *fmt, va_list ap)
152 {
153         int size;
154         va_list ap2;
155         char s;
156
157         *strp = NULL;
158         va_copy(ap2, ap);
159         size = vsnprintf(&s, 1, fmt, ap2);
160         va_end(ap2);
161         *strp = malloc(size + 1);
162         if (!*strp)
163                 return -1;
164         vsnprintf(*strp, size + 1, fmt, ap);
165
166         return size;
167 }
168 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
169
170 /*
171  * Based on Code from bsd-asprintf from OpenSSH
172  * Copyright (c) 2004 Darren Tucker.
173  *
174  * Based originally on asprintf.c from OpenBSD:
175  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
176  *
177  * Permission to use, copy, modify, and distribute this software for any
178  * purpose with or without fee is hereby granted, provided that the above
179  * copyright notice and this permission notice appear in all copies.
180  *
181  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
182  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
183  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
184  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
185  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
186  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
187  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
188  */
189 #if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) 
190 int asprintf(char **str, const char *fmt, ...)
191 {
192         va_list ap;
193         int ret;
194
195         *str = NULL;
196         va_start(ap, fmt);
197         ret = vasprintf(str, fmt, ap);
198         va_end(ap);
199
200         return ret;
201 }
202 #endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
203
204 #ifndef HAVE_STRTOQ
205 #ifndef LONG_MIN
206 #define LONG_MIN        (-9223372036854775807L-1L)
207                                          /* min value of a "long int" */
208 #endif
209 #ifndef LONG_MAX
210 #define LONG_MAX        9223372036854775807L
211                                          /* max value of a "long int" */
212 #endif
213
214 /*! \brief
215  * Convert a string to a quad integer.
216  *
217  * \note Ignores `locale' stuff.  Assumes that the upper and lower case
218  * alphabets and digits are each contiguous.
219  */
220 uint64_t strtoq(const char *nptr, char **endptr, int base)
221 {
222          const char *s;
223          uint64_t acc;
224          unsigned char c;
225          uint64_t qbase, cutoff;
226          int neg, any, cutlim;
227
228          /*
229           * Skip white space and pick up leading +/- sign if any.
230           * If base is 0, allow 0x for hex and 0 for octal, else
231           * assume decimal; if base is already 16, allow 0x.
232           */
233          s = nptr;
234          do {
235                  c = *s++;
236          } while (isspace(c));
237          if (c == '-') {
238                  neg = 1;
239                  c = *s++;
240          } else {
241                  neg = 0;
242                  if (c == '+')
243                          c = *s++;
244          }
245          if ((base == 0 || base == 16) &&
246              c == '\0' && (*s == 'x' || *s == 'X')) {
247                  c = s[1];
248                  s += 2;
249                  base = 16;
250          }
251          if (base == 0)
252                  base = c == '\0' ? 8 : 10;
253
254          /*
255           * Compute the cutoff value between legal numbers and illegal
256           * numbers.  That is the largest legal value, divided by the
257           * base.  An input number that is greater than this value, if
258           * followed by a legal input character, is too big.  One that
259           * is equal to this value may be valid or not; the limit
260           * between valid and invalid numbers is then based on the last
261           * digit.  For instance, if the range for quads is
262           * [-9223372036854775808..9223372036854775807] and the input base
263           * is 10, cutoff will be set to 922337203685477580 and cutlim to
264           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
265           * accumulated a value > 922337203685477580, or equal but the
266           * next digit is > 7 (or 8), the number is too big, and we will
267           * return a range error.
268           *
269           * Set any if any `digits' consumed; make it negative to indicate
270           * overflow.
271           */
272          qbase = (unsigned)base;
273          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
274          cutlim = cutoff % qbase;
275          cutoff /= qbase;
276          for (acc = 0, any = 0;; c = *s++) {
277                  if (!isascii(c))
278                          break;
279                  if (isdigit(c))
280                          c -= '\0';
281                  else if (isalpha(c))
282                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
283                  else
284                          break;
285                  if (c >= base)
286                          break;
287                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
288                          any = -1;
289                  else {
290                          any = 1;
291                          acc *= qbase;
292                          acc += c;
293                  }
294          }
295          if (any < 0) {
296                  acc = neg ? LONG_MIN : LONG_MAX;
297          } else if (neg)
298                  acc = -acc;
299          if (endptr != 0)
300                  *((const char **)endptr) = any ? s - 1 : nptr;
301          return acc;
302 }
303 #endif /* !HAVE_STRTOQ */
304
305 #ifndef HAVE_GETLOADAVG
306 #ifdef linux
307 /*! \brief Alternative method of getting load avg on Linux only */
308 int getloadavg(double *list, int nelem)
309 {
310         FILE *LOADAVG;
311         double avg[3] = { 0.0, 0.0, 0.0 };
312         int i, res = -1;
313
314         if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
315                 fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
316                 res = 0;
317                 fclose(LOADAVG);
318         }
319
320         for (i = 0; (i < nelem) && (i < 3); i++) {
321                 list[i] = avg[i];
322         }
323
324         return res;
325 }
326 #else /* !linux */
327 /*! \brief Return something that won't cancel the call, but still return -1, in case
328  * we correct the implementation to check return value */
329 int getloadavg(double *list, int nelem)
330 {
331         int i;
332
333         for (i = 0; i < nelem; i++) {
334                 list[i] = 0.1;
335         }
336         return -1;
337 }
338 #endif /* linux */
339 #endif /* !HAVE_GETLOADAVG */
340
341 #ifndef HAVE_NTOHLL
342 uint64_t ntohll(uint64_t net64)
343 {
344 #if BYTE_ORDER == BIG_ENDIAN
345         return net64;
346 #elif BYTE_ORDER == LITTLE_ENDIAN
347         union {
348                 unsigned char c[8];
349                 uint64_t u;
350         } number;
351         number.u = net64;
352         return
353                 (((uint64_t) number.c[0]) <<  0) |
354                 (((uint64_t) number.c[1]) <<  8) |
355                 (((uint64_t) number.c[2]) << 16) |
356                 (((uint64_t) number.c[3]) << 24) |
357                 (((uint64_t) number.c[4]) << 32) |
358                 (((uint64_t) number.c[5]) << 40) |
359                 (((uint64_t) number.c[6]) << 48) |
360                 (((uint64_t) number.c[7]) << 56);
361 #else
362         #error "Unknown byte order"
363 #endif
364 }
365 #endif
366
367 #ifndef HAVE_HTONLL
368 uint64_t htonll(uint64_t host64)
369 {
370 #if BYTE_ORDER == BIG_ENDIAN
371         return host64;
372 #elif BYTE_ORDER == LITTLE_ENDIAN
373         union {
374                 unsigned char c[8];
375                 uint64_t u;
376         } number;
377         number.u = host64;
378         return
379                 (((uint64_t) number.c[0]) <<  0) |
380                 (((uint64_t) number.c[1]) <<  8) |
381                 (((uint64_t) number.c[2]) << 16) |
382                 (((uint64_t) number.c[3]) << 24) |
383                 (((uint64_t) number.c[4]) << 32) |
384                 (((uint64_t) number.c[5]) << 40) |
385                 (((uint64_t) number.c[6]) << 48) |
386                 (((uint64_t) number.c[7]) << 56);
387 #else
388         #error "Unknown byte order"
389 #endif
390 }
391 #endif
392
393 #ifndef HAVE_FFSLL
394 int ffsll(long long n)
395 {
396         int i;
397         for (i = 0; i < 64; i++) {
398                 if ((1LL << i) & n) {
399                         return i + 1;
400                 }
401         }
402         return 0;
403 }
404 #endif
405
406 #ifndef HAVE_CLOSEFROM
407 void closefrom(int n)
408 {
409         long x;
410         struct rlimit rl;
411         DIR *dir;
412         char path[16], *result;
413         struct dirent *entry;
414
415         snprintf(path, sizeof(path), "/proc/%d/fd", (int) getpid());
416         if ((dir = opendir(path))) {
417                 while ((entry = readdir(dir))) {
418                         /* Skip . and .. */
419                         if (entry->d_name[0] == '.') {
420                                 continue;
421                         }
422                         if ((x = strtol(entry->d_name, &result, 10)) && x >= n) {
423                                 close(x);
424                         }
425                 }
426                 closedir(dir);
427         } else {
428                 getrlimit(RLIMIT_NOFILE, &rl);
429                 for (x = n; x < rl.rlim_cur; x++) {
430                         close(x);
431                 }
432         }
433 }
434 #endif
435