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