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