Asterisk - The Open Source Telephony Project  18.5.0
strcompat.c
Go to the documentation of this file.
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  * .. and lots of other functions too.
22  */
23 
24 /*** MODULEINFO
25  <support_level>core</support_level>
26  ***/
27 
28 #define ASTMM_LIBC ASTMM_IGNORE
29 #include "asterisk.h"
30 
31 #include <ctype.h>
32 #include <sys/time.h> /* for getrlimit(2) */
33 #include <sys/resource.h> /* for getrlimit(2) */
34 #include <sys/types.h> /* for opendir(3) */
35 #include <dirent.h> /* for opendir(3) */
36 #include <unistd.h> /* for fcntl(2) */
37 #include <fcntl.h> /* for fcntl(2) */
38 
39 #include "asterisk/utils.h"
40 
41 #define POLL_SIZE 1024
42 
43 #ifndef HAVE_STRSEP
44 char *strsep(char **str, const char *delims)
45 {
46  char *token;
47 
48  if (!*str) {
49  /* No more tokens */
50  return NULL;
51  }
52 
53  token = *str;
54  while (**str != '\0') {
55  if (strchr(delims, **str)) {
56  **str = '\0';
57  (*str)++;
58  return token;
59  }
60  (*str)++;
61  }
62 
63  /* There is no other token */
64  *str = NULL;
65 
66  return token;
67 }
68 #endif
69 
70 #ifndef HAVE_SETENV
71 int setenv(const char *name, const char *value, int overwrite)
72 {
73  unsigned char *buf;
74  int buflen;
75 
76  if (!overwrite && getenv(name))
77  return 0;
78 
79  buflen = strlen(name) + strlen(value) + 2;
80  buf = ast_alloca(buflen);
81 
82  snprintf(buf, buflen, "%s=%s", name, value);
83 
84  return putenv(buf);
85 }
86 #endif
87 
88 #ifndef HAVE_UNSETENV
89 int unsetenv(const char *name)
90 {
91  return setenv(name, "", 0);
92 }
93 #endif
94 
95 #ifndef HAVE_STRCASESTR
96 static char *upper(const char *orig, char *buf, int bufsize)
97 {
98  int i = 0;
99 
100  while (i < (bufsize - 1) && orig[i]) {
101  buf[i] = toupper(orig[i]);
102  i++;
103  }
104 
105  buf[i] = '\0';
106 
107  return buf;
108 }
109 
110 char *strcasestr(const char *haystack, const char *needle)
111 {
112  char *u1, *u2;
113  char *offset;
114  int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
115 
116  if (u2len > u1len) {
117  /* Needle bigger than haystack */
118  return NULL;
119  }
120  u1 = ast_alloca(u1len);
121  u2 = ast_alloca(u2len);
122  offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
123  if (offset) {
124  /* Return the offset into the original string */
125  return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
126  } else {
127  return NULL;
128  }
129 }
130 #endif /* !HAVE_STRCASESTR */
131 
132 #ifndef HAVE_STRNLEN
133 size_t strnlen(const char *s, size_t n)
134 {
135  size_t len;
136 
137  for (len = 0; len < n; len++)
138  if (s[len] == '\0')
139  break;
140 
141  return len;
142 }
143 #endif /* !HAVE_STRNLEN */
144 
145 #if !defined(HAVE_STRNDUP)
146 char *strndup(const char *s, size_t n)
147 {
148  size_t len = strnlen(s, n);
149  char *new = malloc(len + 1);
150 
151  if (!new)
152  return NULL;
153 
154  new[len] = '\0';
155  return memcpy(new, s, len);
156 }
157 #endif /* !defined(HAVE_STRNDUP) */
158 
159 #if !defined(HAVE_VASPRINTF)
160 int vasprintf(char **strp, const char *fmt, va_list ap)
161 {
162  int size;
163  va_list ap2;
164  char s;
165 
166  *strp = NULL;
167  va_copy(ap2, ap);
168  size = vsnprintf(&s, 1, fmt, ap2);
169  va_end(ap2);
170  *strp = malloc(size + 1);
171  if (!*strp)
172  return -1;
173  vsnprintf(*strp, size + 1, fmt, ap);
174 
175  return size;
176 }
177 #endif /* !defined(HAVE_VASPRINTF) */
178 
179 #ifndef HAVE_TIMERSUB
180 void timersub(struct timeval *tvend, struct timeval *tvstart, struct timeval *tvdiff)
181 {
182  tvdiff->tv_sec = tvend->tv_sec - tvstart->tv_sec;
183  tvdiff->tv_usec = tvend->tv_usec - tvstart->tv_usec;
184  if (tvdiff->tv_usec < 0) {
185  tvdiff->tv_sec --;
186  tvdiff->tv_usec += 1000000;
187  }
188 
189 }
190 #endif
191 
192 /*
193  * Based on Code from bsd-asprintf from OpenSSH
194  * Copyright (c) 2004 Darren Tucker.
195  *
196  * Based originally on asprintf.c from OpenBSD:
197  * Copyright (c) 1997 Todd C. Miller <[email protected]>
198  *
199  * Permission to use, copy, modify, and distribute this software for any
200  * purpose with or without fee is hereby granted, provided that the above
201  * copyright notice and this permission notice appear in all copies.
202  *
203  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
204  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
205  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
206  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
207  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
208  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
209  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
210  */
211 #if !defined(HAVE_ASPRINTF)
212 int asprintf(char **str, const char *fmt, ...)
213 {
214  va_list ap;
215  int ret;
216 
217  *str = NULL;
218  va_start(ap, fmt);
219  ret = vasprintf(str, fmt, ap);
220  va_end(ap);
221 
222  return ret;
223 }
224 #endif /* !defined(HAVE_ASPRINTF) */
225 
226 #ifndef HAVE_STRTOQ
227 #ifndef LONG_MIN
228 #define LONG_MIN (-9223372036854775807L-1L)
229  /* min value of a "long int" */
230 #endif
231 #ifndef LONG_MAX
232 #define LONG_MAX 9223372036854775807L
233  /* max value of a "long int" */
234 #endif
235 
236 /*! \brief
237  * Convert a string to a quad integer.
238  *
239  * \note Ignores `locale' stuff. Assumes that the upper and lower case
240  * alphabets and digits are each contiguous.
241  */
242 uint64_t strtoq(const char *nptr, char **endptr, int base)
243 {
244  const char *s;
245  uint64_t acc;
246  unsigned char c;
247  uint64_t qbase, cutoff;
248  int neg, any, cutlim;
249 
250  /*
251  * Skip white space and pick up leading +/- sign if any.
252  * If base is 0, allow 0x for hex and 0 for octal, else
253  * assume decimal; if base is already 16, allow 0x.
254  */
255  s = nptr;
256  do {
257  c = *s++;
258  } while (isspace(c));
259  if (c == '-') {
260  neg = 1;
261  c = *s++;
262  } else {
263  neg = 0;
264  if (c == '+')
265  c = *s++;
266  }
267  if ((base == 0 || base == 16) &&
268  c == '\0' && (*s == 'x' || *s == 'X')) {
269  c = s[1];
270  s += 2;
271  base = 16;
272  }
273  if (base == 0)
274  base = c == '\0' ? 8 : 10;
275 
276  /*
277  * Compute the cutoff value between legal numbers and illegal
278  * numbers. That is the largest legal value, divided by the
279  * base. An input number that is greater than this value, if
280  * followed by a legal input character, is too big. One that
281  * is equal to this value may be valid or not; the limit
282  * between valid and invalid numbers is then based on the last
283  * digit. For instance, if the range for quads is
284  * [-9223372036854775808..9223372036854775807] and the input base
285  * is 10, cutoff will be set to 922337203685477580 and cutlim to
286  * either 7 (neg==0) or 8 (neg==1), meaning that if we have
287  * accumulated a value > 922337203685477580, or equal but the
288  * next digit is > 7 (or 8), the number is too big, and we will
289  * return a range error.
290  *
291  * Set any if any `digits' consumed; make it negative to indicate
292  * overflow.
293  */
294  qbase = (unsigned)base;
295  cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
296  cutlim = cutoff % qbase;
297  cutoff /= qbase;
298  for (acc = 0, any = 0;; c = *s++) {
299  if (!isascii(c))
300  break;
301  if (isdigit(c))
302  c -= '\0';
303  else if (isalpha(c))
304  c -= isupper(c) ? 'A' - 10 : 'a' - 10;
305  else
306  break;
307  if (c >= base)
308  break;
309  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
310  any = -1;
311  else {
312  any = 1;
313  acc *= qbase;
314  acc += c;
315  }
316  }
317  if (any < 0) {
318  acc = neg ? LONG_MIN : LONG_MAX;
319  } else if (neg)
320  acc = -acc;
321  if (endptr != 0)
322  *((const char **)endptr) = any ? s - 1 : nptr;
323  return acc;
324 }
325 #endif /* !HAVE_STRTOQ */
326 
327 #ifndef HAVE_GETLOADAVG
328 #ifdef linux
329 /*! \brief Alternative method of getting load avg on Linux only */
330 int getloadavg(double *list, int nelem)
331 {
332  FILE *LOADAVG;
333  double avg[3] = { 0.0, 0.0, 0.0 };
334  int i, res = -1;
335 
336  if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
337  fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
338  res = 0;
339  fclose(LOADAVG);
340  }
341 
342  for (i = 0; (i < nelem) && (i < 3); i++) {
343  list[i] = avg[i];
344  }
345 
346  return res;
347 }
348 #else /* !linux */
349 /*! \brief Return something that won't cancel the call, but still return -1, in case
350  * we correct the implementation to check return value */
351 int getloadavg(double *list, int nelem)
352 {
353  int i;
354 
355  for (i = 0; i < nelem; i++) {
356  list[i] = 0.1;
357  }
358  return -1;
359 }
360 #endif /* linux */
361 #endif /* !HAVE_GETLOADAVG */
362 
363 #ifndef HAVE_NTOHLL
364 uint64_t ntohll(uint64_t net64)
365 {
366 #if BYTE_ORDER == BIG_ENDIAN
367  return net64;
368 #elif BYTE_ORDER == LITTLE_ENDIAN
369  union {
370  unsigned char c[8];
371  uint64_t u;
372  } number;
373  number.u = net64;
374  return
375  (((uint64_t) number.c[0]) << 56) |
376  (((uint64_t) number.c[1]) << 48) |
377  (((uint64_t) number.c[2]) << 40) |
378  (((uint64_t) number.c[3]) << 32) |
379  (((uint64_t) number.c[4]) << 24) |
380  (((uint64_t) number.c[5]) << 16) |
381  (((uint64_t) number.c[6]) << 8) |
382  (((uint64_t) number.c[7]) << 0);
383 #else
384  #error "Unknown byte order"
385 #endif
386 }
387 #endif
388 
389 #ifndef HAVE_HTONLL
390 uint64_t htonll(uint64_t host64)
391 {
392 #if BYTE_ORDER == BIG_ENDIAN
393  return host64;
394 #elif BYTE_ORDER == LITTLE_ENDIAN
395  union {
396  unsigned char c[8];
397  uint64_t u;
398  } number;
399  number.u = host64;
400  return
401  (((uint64_t) number.c[0]) << 56) |
402  (((uint64_t) number.c[1]) << 48) |
403  (((uint64_t) number.c[2]) << 40) |
404  (((uint64_t) number.c[3]) << 32) |
405  (((uint64_t) number.c[4]) << 24) |
406  (((uint64_t) number.c[5]) << 16) |
407  (((uint64_t) number.c[6]) << 8) |
408  (((uint64_t) number.c[7]) << 0);
409 #else
410  #error "Unknown byte order"
411 #endif
412 }
413 #endif
414 
415 #ifndef HAVE_FFSLL
416 int ffsll(long long n)
417 {
418  int i;
419  for (i = 0; i < 64; i++) {
420  if ((1LL << i) & n) {
421  return i + 1;
422  }
423  }
424  return 0;
425 }
426 #endif
427 
428 #ifndef HAVE_CLOSEFROM
429 void closefrom(int n)
430 {
431  int maxfd;
432 #ifndef _SC_OPEN_MAX
433  struct rlimit rl;
434 #endif
435  struct pollfd fds[POLL_SIZE];
436  int fd=n, loopmax, i;
437 #ifndef STRICT_COMPAT
438  long flags;
439 #endif
440 
441 #ifndef _SC_OPEN_MAX
442  if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
443  maxfd = -1;
444  } else {
445  maxfd = rl.rlim_cur;
446  }
447 #else
448  maxfd = sysconf (_SC_OPEN_MAX);
449 #endif
450 
451  if (maxfd == -1 || maxfd > 65536) {
452  /* A more reasonable value. Consider that the primary source of
453  * file descriptors in Asterisk are UDP sockets, of which we are
454  * limited to 65,535 per address. We additionally limit that down
455  * to about 10,000 sockets per protocol. While the kernel will
456  * allow us to set the fileno limit higher (up to 4.2 billion),
457  * there really is no practical reason for it to be that high.
458  *
459  * sysconf as well as getrlimit can return -1 on error. Let's set
460  * maxfd to the mentioned reasonable value of 65,535 in this case.
461  */
462  maxfd = 65536;
463  }
464 
465  while (fd < maxfd) {
466  loopmax = maxfd - fd;
467  if (loopmax > POLL_SIZE) {
468  loopmax = POLL_SIZE;
469  }
470  for (i = 0; i < loopmax; i++) {
471  fds[i].fd = fd+i;
472  fds[i].events = 0;
473  }
474  poll(fds, loopmax, 0);
475  for (i = 0; i < loopmax; i++) {
476  if (fds[i].revents == POLLNVAL) {
477  continue;
478  }
479 #ifdef STRICT_COMPAT
480  close(fds[i].fd);
481 #else
482  /* This isn't strictly compatible, but it's actually faster
483  * for our purposes to set the CLOEXEC flag than to close
484  * file descriptors.
485  */
486  flags = fcntl(fds[i].fd, F_GETFD);
487  if (flags == -1 && errno == EBADF) {
488  continue;
489  }
490  fcntl(fds[i].fd, F_SETFD, flags | FD_CLOEXEC);
491 #endif
492  }
493  fd += loopmax;
494  }
495 }
496 #endif
497 
498 #ifndef HAVE_MKDTEMP
499 /* $OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */
500 /*
501  * Copyright (c) 1996-1998, 2008 Theo de Raadt
502  * Copyright (c) 1997, 2008-2009 Todd C. Miller
503  *
504  * Permission to use, copy, modify, and distribute this software for any
505  * purpose with or without fee is hereby granted, provided that the above
506  * copyright notice and this permission notice appear in all copies.
507  *
508  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
509  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
510  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
511  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
512  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
513  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
514  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
515  */
516 
517 #define MKTEMP_NAME 0
518 #define MKTEMP_FILE 1
519 #define MKTEMP_DIR 2
520 
521 #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."
522 #define NUM_CHARS (sizeof(TEMPCHARS) - 1)
523 
524 static int mktemp_internal(char *path, int slen, int mode)
525 {
526  char *start, *cp, *ep;
527  const char *tempchars = TEMPCHARS;
528  unsigned int r, tries;
529  struct stat sb;
530  size_t len;
531  int fd;
532 
533  len = strlen(path);
534  if (len == 0 || slen >= len) {
535  errno = EINVAL;
536  return(-1);
537  }
538  ep = path + len - slen;
539 
540  tries = 1;
541  for (start = ep; start > path && start[-1] == 'X'; start--) {
542  if (tries < INT_MAX / NUM_CHARS) {
543  tries *= NUM_CHARS;
544  }
545  }
546  tries *= 2;
547 
548  do {
549  for (cp = start; cp != ep; cp++) {
550  r = ast_random() % NUM_CHARS;
551  *cp = tempchars[r];
552  }
553 
554  switch (mode) {
555  case MKTEMP_NAME:
556  if (lstat(path, &sb) != 0) {
557  return (errno == ENOENT ? 0 : -1);
558  }
559  break;
560  case MKTEMP_FILE:
561  fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
562  if (fd != -1 || errno != EEXIST) {
563  return (fd);
564  }
565  break;
566  case MKTEMP_DIR:
567  if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) == 0) {
568  return (0);
569  }
570  if (errno != EEXIST) {
571  return (-1);
572  }
573  break;
574  }
575  } while (--tries);
576 
577  errno = EEXIST;
578  return(-1);
579 }
580 
581 char *mkdtemp(char *path)
582 {
583  return mktemp_internal(path, 0, MKTEMP_DIR) ? NULL : path;
584 }
585 #endif
586 
587 #ifndef HAVE_ROUNDF
588 #ifndef HAVE_ROUND
589 float roundf(float x) {
590  if (x < 0.0) {
591  return (float)(int)((x) - 0.5);
592  } else {
593  return (float)(int)((x) + 0.5);
594  }
595 }
596 #endif
597 #endif
Asterisk main include file. File version handling, generic pbx functions.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
size_t strnlen(const char *, size_t)
int ffsll(long long n)
#define POLL_SIZE
Definition: strcompat.c:41
static struct test_val c
const char * str
Definition: app_jack.c:147
char * strndup(const char *, size_t)
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
int vasprintf(char **strp, const char *fmt, va_list ap)
Utility functions.
Number structure.
Definition: app_followme.c:154
void timersub(struct timeval *tvend, struct timeval *tvstart, struct timeval *tvdiff)
char * malloc()
long int ast_random(void)
Definition: main/utils.c:2064
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
char * mkdtemp(char *template_s)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
char * strcasestr(const char *, const char *)
void closefrom(int n)
Definition: strcompat.c:429
static const char name[]
Definition: cdr_mysql.c:74
uint64_t htonll(uint64_t host64)
Definition: strcompat.c:390
char * strsep(char **str, const char *delims)
float roundf(float x)
int getloadavg(double *list, int nelem)
int setenv(const char *name, const char *value, int overwrite)
int asprintf(char **str, const char *fmt,...)
uint64_t ntohll(uint64_t net64)
Definition: strcompat.c:364
uint64_t strtoq(const char *nptr, char **endptr, int base)
int unsetenv(const char *name)