Asterisk - The Open Source Telephony Project GIT-master-7e7a603
utils.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 Utility functions
20 *
21 * \note These are important for portability and security,
22 * so please use them in favour of other routines.
23 * Please consult the CODING GUIDELINES for more information.
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include <ctype.h>
33#include <fcntl.h>
34#include <sys/stat.h>
35#include <sys/syscall.h>
36#include <unistd.h>
37#if defined(__APPLE__)
38#include <mach/mach.h>
39#elif defined(__FreeBSD__)
40#include <sys/thr.h>
41#elif defined(__NetBSD__)
42#include <lwp.h>
43#endif
44
45#include "asterisk/network.h"
47
48#define AST_API_MODULE /* ensure that inlinable API functions will be built in lock.h if required */
49#include "asterisk/lock.h"
50#include "asterisk/io.h"
51#include "asterisk/md5.h"
52#include "asterisk/sha1.h"
53#include "asterisk/cli.h"
55#include "asterisk/astobj2.h"
56
57#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
58#include "asterisk/strings.h"
59
60#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
61#include "asterisk/time.h"
62
63#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
64#include "asterisk/utils.h"
65
66#define AST_API_MODULE
68
69#define AST_API_MODULE
70#include "asterisk/config.h"
71
72#define AST_API_MODULE
73#include "asterisk/alertpipe.h"
74
75/* These arrays are global static variables because they are only modified
76 * once - in base64_init. The only purpose they have is to serve as a dictionary
77 * for encoding and decoding base64 and base64 URL, so there's no harm in
78 * accessing these arrays in multiple threads.
79 */
80static char base64[64];
81static char base64url[64];
82static char b2a[256];
83static char b2a_url[256];
84
86
87#if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
88
89#define ERANGE 34 /*!< duh? ERANGE value copied from web... */
90#undef gethostbyname
91
93
94/*! \brief Reentrant replacement for gethostbyname for BSD-based systems.
95\note This
96routine is derived from code originally written and placed in the public
97domain by Enzo Michelangeli <em@em.no-ip.com> */
98
99static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
100 size_t buflen, struct hostent **result,
101 int *h_errnop)
102{
103 int hsave;
104 struct hostent *ph;
105 ast_mutex_lock(&__mutex); /* begin critical area */
106 hsave = h_errno;
107
108 ph = gethostbyname(name);
109 *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
110 if (ph == NULL) {
111 *result = NULL;
112 } else {
113 char **p, **q;
114 char *pbuf;
115 int nbytes = 0;
116 int naddr = 0, naliases = 0;
117 /* determine if we have enough space in buf */
118
119 /* count how many addresses */
120 for (p = ph->h_addr_list; *p != 0; p++) {
121 nbytes += ph->h_length; /* addresses */
122 nbytes += sizeof(*p); /* pointers */
123 naddr++;
124 }
125 nbytes += sizeof(*p); /* one more for the terminating NULL */
126
127 /* count how many aliases, and total length of strings */
128 for (p = ph->h_aliases; *p != 0; p++) {
129 nbytes += (strlen(*p)+1); /* aliases */
130 nbytes += sizeof(*p); /* pointers */
131 naliases++;
132 }
133 nbytes += sizeof(*p); /* one more for the terminating NULL */
134
135 /* here nbytes is the number of bytes required in buffer */
136 /* as a terminator must be there, the minimum value is ph->h_length */
137 if (nbytes > buflen) {
138 *result = NULL;
139 ast_mutex_unlock(&__mutex); /* end critical area */
140 return ERANGE; /* not enough space in buf!! */
141 }
142
143 /* There is enough space. Now we need to do a deep copy! */
144 /* Allocation in buffer:
145 from [0] to [(naddr-1) * sizeof(*p)]:
146 pointers to addresses
147 at [naddr * sizeof(*p)]:
148 NULL
149 from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
150 pointers to aliases
151 at [(naddr+naliases+1) * sizeof(*p)]:
152 NULL
153 then naddr addresses (fixed length), and naliases aliases (asciiz).
154 */
155
156 *ret = *ph; /* copy whole structure (not its address!) */
157
158 /* copy addresses */
159 q = (char **)buf; /* pointer to pointers area (type: char **) */
160 ret->h_addr_list = q; /* update pointer to address list */
161 pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */
162 for (p = ph->h_addr_list; *p != 0; p++) {
163 memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
164 *q++ = pbuf; /* the pointer is the one inside buf... */
165 pbuf += ph->h_length; /* advance pbuf */
166 }
167 *q++ = NULL; /* address list terminator */
168
169 /* copy aliases */
170 ret->h_aliases = q; /* update pointer to aliases list */
171 for (p = ph->h_aliases; *p != 0; p++) {
172 strcpy(pbuf, *p); /* copy alias strings */
173 *q++ = pbuf; /* the pointer is the one inside buf... */
174 pbuf += strlen(*p); /* advance pbuf */
175 *pbuf++ = 0; /* string terminator */
176 }
177 *q++ = NULL; /* terminator */
178
179 strcpy(pbuf, ph->h_name); /* copy alias strings */
180 ret->h_name = pbuf;
181 pbuf += strlen(ph->h_name); /* advance pbuf */
182 *pbuf++ = 0; /* string terminator */
183
184 *result = ret; /* and let *result point to structure */
185
186 }
187 h_errno = hsave; /* restore h_errno */
188 ast_mutex_unlock(&__mutex); /* end critical area */
189
190 return (*result == NULL); /* return 0 on success, non-zero on error */
191}
192
193
194#endif
195
196/*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the
197 standard gethostbyname (which is not thread safe)
198*/
199struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
200{
201#ifndef HAVE_GETHOSTBYNAME_R_5
202 int res;
203#endif
204 int herrno;
205 int dots = 0;
206 const char *s;
207 struct hostent *result = NULL;
208 /* Although it is perfectly legitimate to lookup a pure integer, for
209 the sake of the sanity of people who like to name their peers as
210 integers, we break with tradition and refuse to look up a
211 pure integer */
212 s = host;
213 while (s && *s) {
214 if (*s == '.')
215 dots++;
216 else if (!isdigit(*s))
217 break;
218 s++;
219 }
220 if (!s || !*s) {
221 /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
222 if (dots != 3)
223 return NULL;
224 memset(hp, 0, sizeof(struct ast_hostent));
225 hp->hp.h_addrtype = AF_INET;
226 hp->hp.h_addr_list = (void *) hp->buf;
227 hp->hp.h_addr = hp->buf + sizeof(void *);
228 /* For AF_INET, this will always be 4 */
229 hp->hp.h_length = 4;
230 if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
231 return &hp->hp;
232 return NULL;
233
234 }
235#ifdef HAVE_GETHOSTBYNAME_R_5
236 result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
237
238 if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
239 return NULL;
240#else
241 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
242
243 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
244 return NULL;
245#endif
246 return &hp->hp;
247}
248
249/*! \brief Produce 32 char MD5 hash of value. */
250void ast_md5_hash(char *output, const char *input)
251{
252 struct MD5Context md5;
253 unsigned char digest[16];
254 char *ptr;
255 int x;
256
257 MD5Init(&md5);
258 MD5Update(&md5, (const unsigned char *) input, strlen(input));
259 MD5Final(digest, &md5);
260 ptr = output;
261 for (x = 0; x < 16; x++)
262 ptr += sprintf(ptr, "%02hhx", digest[x]);
263}
264
265/*! \brief Produce 40 char SHA1 hash of value. */
266void ast_sha1_hash(char *output, const char *input)
267{
268 struct SHA1Context sha;
269 char *ptr;
270 int x;
271 uint8_t Message_Digest[20];
272
273 SHA1Reset(&sha);
274
275 SHA1Input(&sha, (const unsigned char *) input, strlen(input));
276
277 SHA1Result(&sha, Message_Digest);
278 ptr = output;
279 for (x = 0; x < 20; x++)
280 ptr += sprintf(ptr, "%02hhx", Message_Digest[x]);
281}
282
283/*! \brief Produce a 20 byte SHA1 hash of value. */
284void ast_sha1_hash_uint(uint8_t *digest, const char *input)
285{
286 struct SHA1Context sha;
287
288 SHA1Reset(&sha);
289
290 SHA1Input(&sha, (const unsigned char *) input, strlen(input));
291
292 SHA1Result(&sha, digest);
293}
294
295/*! \brief decode BASE64 encoded text */
296int ast_base64decode(unsigned char *dst, const char *src, int max)
297{
298 int cnt = 0;
299 unsigned int byte = 0;
300 unsigned int bits = 0;
301 int incnt = 0;
302 while(*src && *src != '=' && (cnt < max)) {
303 /* Shift in 6 bits of input */
304 byte <<= 6;
305 byte |= (b2a[(int)(*src)]) & 0x3f;
306 bits += 6;
307 src++;
308 incnt++;
309 /* If we have at least 8 bits left over, take that character
310 off the top */
311 if (bits >= 8) {
312 bits -= 8;
313 *dst = (byte >> bits) & 0xff;
314 dst++;
315 cnt++;
316 }
317 }
318 /* Don't worry about left over bits, they're extra anyway */
319 return cnt;
320}
321
322/*! \brief Decode BASE64 encoded text and return the string */
323char *ast_base64decode_string(const char *src)
324{
325 size_t encoded_len;
326 size_t decoded_len;
327 int padding = 0;
328 unsigned char *decoded_string;
329
330 if (ast_strlen_zero(src)) {
331 return NULL;
332 }
333
334 encoded_len = strlen(src);
335 if (encoded_len > 2 && src[encoded_len - 1] == '=') {
336 padding++;
337 if (src[encoded_len - 2] == '=') {
338 padding++;
339 }
340 }
341
342 decoded_len = (encoded_len / 4 * 3) - padding;
343 decoded_string = ast_malloc(decoded_len + 1);
344 if (!decoded_string) {
345 return NULL;
346 }
347
348 ast_base64decode(decoded_string, src, decoded_len);
349 decoded_string[decoded_len] = '\0';
350
351 return (char *)decoded_string;
352}
353
354/*! \brief encode text to BASE64 coding */
355int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
356{
357 int cnt = 0;
358 int col = 0;
359 unsigned int byte = 0;
360 int bits = 0;
361 int cntin = 0;
362 /* Reserve space for null byte at end of string */
363 max--;
364 while ((cntin < srclen) && (cnt < max)) {
365 byte <<= 8;
366 byte |= *(src++);
367 bits += 8;
368 cntin++;
369 if ((bits == 24) && (cnt + 4 <= max)) {
370 *dst++ = base64[(byte >> 18) & 0x3f];
371 *dst++ = base64[(byte >> 12) & 0x3f];
372 *dst++ = base64[(byte >> 6) & 0x3f];
373 *dst++ = base64[byte & 0x3f];
374 cnt += 4;
375 col += 4;
376 bits = 0;
377 byte = 0;
378 }
379 if (linebreaks && (cnt < max) && (col == 64)) {
380 *dst++ = '\n';
381 cnt++;
382 col = 0;
383 }
384 }
385 if (bits && (cnt + 4 <= max)) {
386 /* Add one last character for the remaining bits,
387 padding the rest with 0 */
388 byte <<= 24 - bits;
389 *dst++ = base64[(byte >> 18) & 0x3f];
390 *dst++ = base64[(byte >> 12) & 0x3f];
391 if (bits == 16)
392 *dst++ = base64[(byte >> 6) & 0x3f];
393 else
394 *dst++ = '=';
395 *dst++ = '=';
396 cnt += 4;
397 }
398 if (linebreaks && (cnt < max)) {
399 *dst++ = '\n';
400 cnt++;
401 }
402 *dst = '\0';
403 return cnt;
404}
405
406int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
407{
408 return ast_base64encode_full(dst, src, srclen, max, 0);
409}
410
411/*! \brief Encode to BASE64 and return encoded string */
412char *ast_base64encode_string(const char *src)
413{
414 size_t encoded_len;
415 char *encoded_string;
416
417 if (ast_strlen_zero(src)) {
418 return NULL;
419 }
420
421 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
422 encoded_string = ast_calloc(1, encoded_len);
423
424 ast_base64encode(encoded_string, (const unsigned char *)src, strlen(src), encoded_len);
425
426 return encoded_string;
427}
428
429int ast_base64url_decode(unsigned char *dst, const char *src, int max)
430{
431 int cnt = 0;
432 unsigned int byte = 0;
433 unsigned int bits = 0;
434
435 while (*src && (cnt < max)) {
436 byte <<= 6;
437 byte |= (b2a_url[(int)(*src)]) & 0x3f;
438 bits += 6;
439 src++;
440 if (bits >= 8) {
441 bits -= 8;
442 *dst = (byte >> bits) & 0xff;
443 dst++;
444 cnt++;
445 }
446 }
447 return cnt;
448}
449
450char *ast_base64url_decode_string(const char *src)
451{
452 size_t decoded_len;
453 unsigned char *decoded_string;
454
455 if (ast_strlen_zero(src)) {
456 return NULL;
457 }
458
459 decoded_len = strlen(src) * 3 / 4;
460 decoded_string = ast_malloc(decoded_len + 1);
461 if (!decoded_string) {
462 return NULL;
463 }
464
465 ast_base64url_decode(decoded_string, src, decoded_len);
466 decoded_string[decoded_len] = '\0';
467
468 return (char *)decoded_string;
469}
470
471int ast_base64url_encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
472{
473 int cnt = 0;
474 int col = 0;
475 unsigned int byte = 0;
476 int bits = 0;
477 int cntin = 0;
478
479 max--;
480 while ((cntin < srclen) && (cnt < max)) {
481 byte <<= 8;
482 byte |= *(src++);
483 bits += 8;
484 cntin++;
485 if ((bits == 24) && (cnt + 4 <= max)) {
486 *dst++ = base64url[(byte >> 18) & 0x3f];
487 *dst++ = base64url[(byte >> 12) & 0x3f];
488 *dst++ = base64url[(byte >> 6) & 0x3f];
489 *dst++ = base64url[(byte) & 0x3f];
490 cnt += 4;
491 col += 4;
492 bits = 0;
493 byte = 0;
494 }
495 if (linebreaks && (cnt < max) && (col == 64)) {
496 *dst++ = '\n';
497 cnt++;
498 col = 0;
499 }
500 }
501 if (bits && (cnt + 4 <= max)) {
502 byte <<= 24 - bits;
503 *dst++ = base64url[(byte >> 18) & 0x3f];
504 *dst++ = base64url[(byte >> 12) & 0x3f];
505 if (bits == 16) {
506 *dst++ = base64url[(byte >> 6) & 0x3f];
507 }
508 cnt += 4;
509 }
510 if (linebreaks && (cnt < max)) {
511 *dst++ = '\n';
512 cnt++;
513 }
514 *dst = '\0';
515 return cnt;
516}
517
518int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)
519{
520 return ast_base64url_encode_full(dst, src, srclen, max, 0);
521}
522
523char *ast_base64url_encode_string(const char *src)
524{
525 size_t encoded_len;
526 char *encoded_string;
527
528 if (ast_strlen_zero(src)) {
529 return NULL;
530 }
531
532 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
533 encoded_string = ast_malloc(encoded_len);
534
535 ast_base64url_encode(encoded_string, (const unsigned char *)src, strlen(src), encoded_len);
536
537 return encoded_string;
538}
539
540static void base64_init(void)
541{
542 int x;
543 memset(b2a, -1, sizeof(b2a));
544 memset(b2a_url, -1, sizeof(b2a_url));
545 /* Initialize base-64 Conversion table */
546 for (x = 0; x < 26; x++) {
547 /* A-Z */
548 base64[x] = 'A' + x;
549 base64url[x] = 'A' + x;
550 b2a['A' + x] = x;
551 b2a_url['A' + x] = x;
552 /* a-z */
553 base64[x + 26] = 'a' + x;
554 base64url[x + 26] = 'a' + x;
555 b2a['a' + x] = x + 26;
556 b2a_url['a' + x] = x + 26;
557 /* 0-9 */
558 if (x < 10) {
559 base64[x + 52] = '0' + x;
560 base64url[x + 52] = '0' + x;
561 b2a['0' + x] = x + 52;
562 b2a_url['0' + x] = x + 52;
563 }
564 }
565 base64[62] = '+';
566 base64[63] = '/';
567 base64url[62] = '-';
568 base64url[63] = '_';
569 b2a[(int)'+'] = 62;
570 b2a[(int)'/'] = 63;
571 b2a_url[(int)'-'] = 62;
572 b2a_url[(int)'_'] = 63;
573}
574
575#define BASELINELEN 72 /*!< Line length for Base 64 encoded messages */
576#define BASEMAXINLINE 256 /*!< Buffer size for Base 64 attachment encoding */
577
578/*! \brief Structure used for base64 encoding */
579struct baseio {
580 int iocp;
581 int iolen;
583 int ateof;
584 unsigned char iobuf[BASEMAXINLINE];
585};
586
587/*!
588 * \brief utility used by inchar(), for base_encode()
589 */
590static int inbuf(struct baseio *bio, FILE *fi)
591{
592 int l;
593
594 if (bio->ateof) {
595 return 0;
596 }
597
598 if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) != BASEMAXINLINE) {
599 bio->ateof = 1;
600 if (l == 0) {
601 /* Assume EOF */
602 return 0;
603 }
604 }
605
606 bio->iolen = l;
607 bio->iocp = 0;
608
609 return 1;
610}
611
612/*!
613 * \brief utility used by base_encode()
614 */
615static int inchar(struct baseio *bio, FILE *fi)
616{
617 if (bio->iocp >= bio->iolen) {
618 if (!inbuf(bio, fi)) {
619 return EOF;
620 }
621 }
622
623 return bio->iobuf[bio->iocp++];
624}
625
626/*!
627 * \brief utility used by base_encode()
628 */
629static int ochar(struct baseio *bio, int c, FILE *so, const char *endl)
630{
631 if (bio->linelength >= BASELINELEN) {
632 if (fputs(endl, so) == EOF) {
633 return -1;
634 }
635
636 bio->linelength = 0;
637 }
638
639 if (putc(((unsigned char) c), so) == EOF) {
640 return -1;
641 }
642
643 bio->linelength++;
644
645 return 1;
646}
647
648int ast_base64_encode_file(FILE *inputfile, FILE *outputfile, const char *endl)
649{
650 static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
651 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
652 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
653 '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
654 int i, hiteof = 0;
655 struct baseio bio;
656
657 memset(&bio, 0, sizeof(bio));
658 bio.iocp = BASEMAXINLINE;
659
660 while (!hiteof){
661 unsigned char igroup[3], ogroup[4];
662 int c, n;
663
664 memset(igroup, 0, sizeof(igroup));
665
666 for (n = 0; n < 3; n++) {
667 if ((c = inchar(&bio, inputfile)) == EOF) {
668 hiteof = 1;
669 break;
670 }
671
672 igroup[n] = (unsigned char) c;
673 }
674
675 if (n > 0) {
676 ogroup[0]= dtable[igroup[0] >> 2];
677 ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
678 ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
679 ogroup[3]= dtable[igroup[2] & 0x3F];
680
681 if (n < 3) {
682 ogroup[3] = '=';
683
684 if (n < 2) {
685 ogroup[2] = '=';
686 }
687 }
688
689 for (i = 0; i < 4; i++) {
690 ochar(&bio, ogroup[i], outputfile, endl);
691 }
692 }
693 }
694
695 if (fputs(endl, outputfile) == EOF) {
696 return 0;
697 }
698
699 return 1;
700}
701
702int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
703{
704 FILE *fi;
705 int res;
706
707 if (!(fi = fopen(filename, "rb"))) {
708 ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
709 return -1;
710 }
711
712 res = ast_base64_encode_file(fi, outputfile, endl);
713
714 fclose(fi);
715
716 return res;
717}
718
722
723char *ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
724{
725 const char *ptr = string; /* Start with the string */
726 char *out = outbuf;
727 const char *mark = "-_.!~*'()"; /* no encode set, RFC 2396 section 2.3, RFC 3261 sec 25 */
728 const char *user_unreserved = "&=+$,;?/"; /* user-unreserved set, RFC 3261 sec 25 */
729
730 while (*ptr && out - outbuf < buflen - 1) {
731 if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *ptr == ' ') {
732 /* for legacy encoding, encode spaces as '+' */
733 *out = '+';
734 out++;
735 } else if (!(ast_test_flag(&spec, AST_URI_MARK)
736 && strchr(mark, *ptr))
738 && ((*ptr >= '0' && *ptr <= '9')
739 || (*ptr >= 'A' && *ptr <= 'Z')
740 || (*ptr >= 'a' && *ptr <= 'z')))
742 && strchr(user_unreserved, *ptr))) {
743
744 if (out - outbuf >= buflen - 3) {
745 break;
746 }
747 out += sprintf(out, "%%%02hhX", (unsigned char) *ptr);
748 } else {
749 *out = *ptr; /* Continue copying the string */
750 out++;
751 }
752 ptr++;
753 }
754
755 if (buflen) {
756 *out = '\0';
757 }
758
759 return outbuf;
760}
761
762void ast_uri_decode(char *s, struct ast_flags spec)
763{
764 char *o;
765 unsigned int tmp;
766
767 for (o = s; *s; s++, o++) {
768 if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *s == '+') {
769 /* legacy mode, decode '+' as space */
770 *o = ' ';
771 } else if (*s == '%' && s[1] != '\0' && s[2] != '\0' && sscanf(s + 1, "%2x", &tmp) == 1) {
772 /* have '%', two chars and correct parsing */
773 *o = tmp;
774 s += 2; /* Will be incremented once more when we break out */
775 } else /* all other cases, just copy */
776 *o = *s;
777 }
778 *o = '\0';
779}
780
781char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
782{
783 const char *ptr = string;
784 char *out = outbuf;
785 char *allow = "\t\v !"; /* allow LWS (minus \r and \n) and "!" */
786
787 while (*ptr && out - outbuf < buflen - 1) {
788 if (!(strchr(allow, *ptr))
789 && !(*ptr >= '#' && *ptr <= '[') /* %x23 - %x5b */
790 && !(*ptr >= ']' && *ptr <= '~') /* %x5d - %x7e */
791 && !((unsigned char) *ptr > 0x7f)) { /* UTF8-nonascii */
792
793 if (out - outbuf >= buflen - 2) {
794 break;
795 }
796 out += sprintf(out, "\\%c", (unsigned char) *ptr);
797 } else {
798 *out = *ptr;
799 out++;
800 }
801 ptr++;
802 }
803
804 if (buflen) {
805 *out = '\0';
806 }
807
808 return outbuf;
809}
810
811char *ast_escape_semicolons(const char *string, char *outbuf, int buflen)
812{
813 const char *ptr = string;
814 char *out = outbuf;
815
816 if (string == NULL || outbuf == NULL) {
817 ast_assert(string != NULL && outbuf != NULL);
818 return NULL;
819 }
820
821 while (*ptr && out - outbuf < buflen - 1) {
822 if (*ptr == ';') {
823 if (out - outbuf >= buflen - 2) {
824 break;
825 }
826 strcpy(out, "\\;");
827 out += 2;
828 } else {
829 *out = *ptr;
830 out++;
831 }
832 ptr++;
833 }
834
835 if (buflen) {
836 *out = '\0';
837 }
838
839 return outbuf;
840}
841
842void ast_unescape_quoted(char *quote_str)
843{
844 int esc_pos;
845 int unesc_pos;
846 int quote_str_len = strlen(quote_str);
847
848 for (esc_pos = 0, unesc_pos = 0;
849 esc_pos < quote_str_len;
850 esc_pos++, unesc_pos++) {
851 if (quote_str[esc_pos] == '\\') {
852 /* at least one more char and current is \\ */
853 esc_pos++;
854 if (esc_pos >= quote_str_len) {
855 break;
856 }
857 }
858
859 quote_str[unesc_pos] = quote_str[esc_pos];
860 }
861 quote_str[unesc_pos] = '\0';
862}
863
864int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
865{
866 char *dst = outbuf;
867 char *end = outbuf + buflen - 1; /* save one for the null terminator */
868
869 /* Handle the case for the empty output buffer */
870 if (buflen == 0) {
871 return -1;
872 }
873
874 /* Escaping rules from http://www.w3.org/TR/REC-xml/#syntax */
875 /* This also prevents partial entities at the end of a string */
876 while (*string && dst < end) {
877 const char *entity = NULL;
878 int len = 0;
879
880 switch (*string) {
881 case '<':
882 entity = "&lt;";
883 len = 4;
884 break;
885 case '&':
886 entity = "&amp;";
887 len = 5;
888 break;
889 case '>':
890 /* necessary if ]]> is in the string; easier to escape them all */
891 entity = "&gt;";
892 len = 4;
893 break;
894 case '\'':
895 /* necessary in single-quoted strings; easier to escape them all */
896 entity = "&apos;";
897 len = 6;
898 break;
899 case '"':
900 /* necessary in double-quoted strings; easier to escape them all */
901 entity = "&quot;";
902 len = 6;
903 break;
904 default:
905 *dst++ = *string++;
906 break;
907 }
908
909 if (entity) {
910 ast_assert(len == strlen(entity));
911 if (end - dst < len) {
912 /* no room for the entity; stop */
913 break;
914 }
915 /* just checked for length; strcpy is fine */
916 strcpy(dst, entity);
917 dst += len;
918 ++string;
919 }
920 }
921 /* Write null terminator */
922 *dst = '\0';
923 /* If any chars are left in string, return failure */
924 return *string == '\0' ? 0 : -1;
925}
926
927/*! \brief ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
928const char *ast_inet_ntoa(struct in_addr ia)
929{
930 char *buf;
931
932 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
933 return "";
934
935 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
936}
937
938static int dev_urandom_fd = -1;
939
940#ifndef __linux__
941#undef pthread_create /* For ast_pthread_create function only */
942#endif /* !__linux__ */
943
944#ifdef DEBUG_THREADS
945
946#if !defined(LOW_MEMORY)
947/*! \brief A reasonable maximum number of locks a thread would be holding ... */
948#define AST_MAX_LOCKS 64
949
950/* Allow direct use of pthread_mutex_t and friends */
951#undef pthread_mutex_t
952#undef pthread_mutex_lock
953#undef pthread_mutex_unlock
954#undef pthread_mutex_init
955#undef pthread_mutex_destroy
956
957/*!
958 * \brief Keep track of which locks a thread holds
959 *
960 * There is an instance of this struct for every active thread
961 */
962struct thr_lock_info {
963 /*! The thread's ID */
964 pthread_t thread_id;
965 /*! The thread name which includes where the thread was started */
966 const char *thread_name;
967 /*! This is the actual container of info for what locks this thread holds */
968 struct {
969 const char *file;
970 const char *func;
971 const char *lock_name;
972 void *lock_addr;
973 int times_locked;
974 int times_lock_attempted;
975 struct timeval last_locked;
976 struct timeval last_unlocked;
977 int line_num;
978 enum ast_lock_type type;
979 /*! This thread is waiting on this lock */
980 int pending:2;
981 /*! A condition has suspended this lock */
982 int suspended:1;
983#ifdef HAVE_BKTR
984 struct ast_bt *backtrace;
985#endif
986 } locks[AST_MAX_LOCKS];
987 /*! This is the number of locks currently held by this thread.
988 * The index (num_locks - 1) has the info on the last one in the
989 * locks member */
990 unsigned int num_locks;
991 /*! The LWP id (which GDB prints) */
992 int lwp;
993 /*! Protects the contents of the locks member
994 * Intentionally not ast_mutex_t */
996 AST_LIST_ENTRY(thr_lock_info) entry;
997};
998
999/*!
1000 * \brief Locked when accessing the lock_infos list
1001 */
1002AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
1003/*!
1004 * \brief A list of each thread's lock info
1005 */
1006static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
1007
1008/*!
1009 * \brief Destroy a thread's lock info
1010 *
1011 * This gets called automatically when the thread stops
1012 */
1013static void lock_info_destroy(void *data)
1014{
1015 struct thr_lock_info *lock_info = data;
1016 int i;
1017
1018 pthread_mutex_lock(&lock_infos_lock.mutex);
1019 AST_LIST_REMOVE(&lock_infos, lock_info, entry);
1020 pthread_mutex_unlock(&lock_infos_lock.mutex);
1021
1022
1023 for (i = 0; i < lock_info->num_locks; i++) {
1024 if (lock_info->locks[i].pending == -1) {
1025 /* This just means that the last lock this thread went for was by
1026 * using trylock, and it failed. This is fine. */
1027 break;
1028 }
1029
1031 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
1032 lock_info->thread_name,
1033 lock_info->locks[i].lock_name,
1034 lock_info->locks[i].lock_addr,
1035 lock_info->locks[i].func,
1036 lock_info->locks[i].file,
1037 lock_info->locks[i].line_num
1038 );
1039 }
1040
1042 if (lock_info->thread_name) {
1043 ast_free((void *) lock_info->thread_name);
1044 }
1046}
1047
1048/*!
1049 * \brief The thread storage key for per-thread lock info
1050 */
1051AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
1052#endif /* ! LOW_MEMORY */
1053
1054void ast_store_lock_info(enum ast_lock_type type, const char *filename,
1055 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
1056{
1057#if !defined(LOW_MEMORY)
1058 struct thr_lock_info *lock_info;
1059 int i;
1060
1061 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1062 return;
1063
1065
1066 for (i = 0; i < lock_info->num_locks; i++) {
1067 if (lock_info->locks[i].lock_addr == lock_addr) {
1068 lock_info->locks[i].times_locked++;
1069 lock_info->locks[i].times_lock_attempted++;
1070 lock_info->locks[i].last_locked = ast_tvnow();
1071#ifdef HAVE_BKTR
1072 lock_info->locks[i].backtrace = bt;
1073#endif
1075 return;
1076 }
1077 }
1078
1079 if (lock_info->num_locks == AST_MAX_LOCKS) {
1080 /* Can't use ast_log here, because it will cause infinite recursion */
1081 fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
1082 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
1084 return;
1085 }
1086
1087 if (i && lock_info->locks[i - 1].pending == -1) {
1088 /* The last lock on the list was one that this thread tried to lock but
1089 * failed at doing so. It has now moved on to something else, so remove
1090 * the old lock from the list. */
1091 i--;
1092 lock_info->num_locks--;
1093 memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
1094 }
1095
1096 lock_info->locks[i].file = filename;
1097 lock_info->locks[i].line_num = line_num;
1098 lock_info->locks[i].func = func;
1099 lock_info->locks[i].lock_name = lock_name;
1100 lock_info->locks[i].lock_addr = lock_addr;
1101 lock_info->locks[i].times_locked = 1;
1102 lock_info->locks[i].times_lock_attempted = 1;
1103 lock_info->locks[i].last_locked = ast_tvnow();
1104 lock_info->locks[i].type = type;
1105 lock_info->locks[i].pending = 1;
1106#ifdef HAVE_BKTR
1107 lock_info->locks[i].backtrace = bt;
1108#endif
1109 lock_info->num_locks++;
1110
1112#endif /* ! LOW_MEMORY */
1113}
1114
1115void ast_mark_lock_acquired(void *lock_addr)
1116{
1117#if !defined(LOW_MEMORY)
1118 struct thr_lock_info *lock_info;
1119
1120 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1121 return;
1122
1124 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
1125 lock_info->locks[lock_info->num_locks - 1].pending = 0;
1126 }
1128#endif /* ! LOW_MEMORY */
1129}
1130
1131void ast_mark_lock_failed(void *lock_addr)
1132{
1133#if !defined(LOW_MEMORY)
1134 struct thr_lock_info *lock_info;
1135
1136 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1137 return;
1138
1140 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
1141 lock_info->locks[lock_info->num_locks - 1].pending = -1;
1142 lock_info->locks[lock_info->num_locks - 1].times_locked--;
1143 lock_info->locks[lock_info->num_locks - 1].last_unlocked = ast_tvnow();
1144 }
1146#endif /* ! LOW_MEMORY */
1147}
1148
1149int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size)
1150{
1151#if !defined(LOW_MEMORY)
1152 struct thr_lock_info *lock_info;
1153 int i = 0;
1154
1155 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1156 return -1;
1157
1159
1160 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1161 if (lock_info->locks[i].lock_addr == lock_addr)
1162 break;
1163 }
1164
1165 if (i == -1) {
1166 /* Lock not found :( */
1168 return -1;
1169 }
1170
1171 ast_copy_string(filename, lock_info->locks[i].file, filename_size);
1172 *lineno = lock_info->locks[i].line_num;
1173 ast_copy_string(func, lock_info->locks[i].func, func_size);
1174 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
1175
1177
1178 return 0;
1179#else /* if defined(LOW_MEMORY) */
1180 return -1;
1181#endif
1182}
1183
1184void ast_suspend_lock_info(void *lock_addr)
1185{
1186#if !defined(LOW_MEMORY)
1187 struct thr_lock_info *lock_info;
1188 int i = 0;
1189
1190 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) {
1191 return;
1192 }
1193
1195
1196 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1197 if (lock_info->locks[i].lock_addr == lock_addr)
1198 break;
1199 }
1200
1201 if (i == -1) {
1202 /* Lock not found :( */
1204 return;
1205 }
1206
1207 lock_info->locks[i].suspended = 1;
1208
1210#endif /* ! LOW_MEMORY */
1211}
1212
1213void ast_restore_lock_info(void *lock_addr)
1214{
1215#if !defined(LOW_MEMORY)
1216 struct thr_lock_info *lock_info;
1217 int i = 0;
1218
1219 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1220 return;
1221
1223
1224 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1225 if (lock_info->locks[i].lock_addr == lock_addr)
1226 break;
1227 }
1228
1229 if (i == -1) {
1230 /* Lock not found :( */
1232 return;
1233 }
1234
1235 lock_info->locks[i].suspended = 0;
1236
1238#endif /* ! LOW_MEMORY */
1239}
1240
1241
1242void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
1243{
1244#if !defined(LOW_MEMORY)
1245 struct thr_lock_info *lock_info;
1246 int i = 0;
1247
1248 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1249 return;
1250
1252
1253 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1254 if (lock_info->locks[i].lock_addr == lock_addr)
1255 break;
1256 }
1257
1258 if (i == -1) {
1259 /* Lock not found :( */
1261 return;
1262 }
1263
1264 if (lock_info->locks[i].times_locked > 1) {
1265 lock_info->locks[i].times_locked--;
1266 lock_info->locks[i].last_unlocked = ast_tvnow();
1267#ifdef HAVE_BKTR
1268 lock_info->locks[i].backtrace = bt;
1269#endif
1271 return;
1272 }
1273
1274 if (i < lock_info->num_locks - 1) {
1275 /* Not the last one ... *should* be rare! */
1276 memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
1277 (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
1278 }
1279
1280 lock_info->num_locks--;
1281
1283#endif /* ! LOW_MEMORY */
1284}
1285
1286#if !defined(LOW_MEMORY)
1287static const char *locktype2str(enum ast_lock_type type)
1288{
1289 switch (type) {
1290 case AST_MUTEX:
1291 return "MUTEX";
1292 case AST_RDLOCK:
1293 return "RDLOCK";
1294 case AST_WRLOCK:
1295 return "WRLOCK";
1296 }
1297
1298 return "UNKNOWN";
1299}
1300
1301#ifdef HAVE_BKTR
1302static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
1303{
1304 struct ast_vector_string *symbols;
1305 int num_frames;
1306
1307 if (!bt) {
1308 ast_str_append(str, 0, "\tNo backtrace to print\n");
1309 return;
1310 }
1311
1312 /* store frame count locally to avoid the memory corruption that
1313 * sometimes happens on virtualized CentOS 6.x systems */
1314 num_frames = bt->num_frames;
1315 if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
1316 int frame_iterator;
1317
1318 for (frame_iterator = 1; frame_iterator < AST_VECTOR_SIZE(symbols); ++frame_iterator) {
1319 ast_str_append(str, 0, "\t%s\n", AST_VECTOR_GET(symbols, frame_iterator));
1320 }
1321
1322 ast_bt_free_symbols(symbols);
1323 } else {
1324 ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
1325 }
1326}
1327#endif
1328
1329static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
1330{
1331 int j;
1333 struct ast_lock_track *lt;
1334 struct timeval held_for;
1335 struct timeval now = ast_tvnow();
1336 char lock_time[32], unlock_time[32], held_time[32];
1337
1338 held_for = ast_tvsub(now, lock_info->locks[i].last_locked);
1339 /* format time duration strings */
1340 ast_format_duration_hh_mm_ss(lock_info->locks[i].last_locked.tv_sec,
1341 lock_time, sizeof(lock_time));
1342 ast_format_duration_hh_mm_ss(lock_info->locks[i].last_unlocked.tv_sec,
1343 unlock_time, sizeof(unlock_time));
1344 ast_format_duration_hh_mm_ss(held_for.tv_sec, held_time, sizeof(held_time));
1345
1346 ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p\n"
1347 "=== %s.%06ld, %s.%06ld, %s.%06ld (%d, %d%s)\n",
1348 lock_info->locks[i].pending > 0 ? "Waiting for " :
1349 lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
1350 lock_info->locks[i].file,
1351 locktype2str(lock_info->locks[i].type),
1352 lock_info->locks[i].line_num,
1353 lock_info->locks[i].func,
1354 lock_info->locks[i].lock_name,
1355 lock_info->locks[i].lock_addr,
1356 lock_time,
1357 lock_info->locks[i].last_locked.tv_usec,
1358 unlock_time,
1359 lock_info->locks[i].last_unlocked.tv_usec,
1360 held_time,
1361 held_for.tv_usec,
1362 lock_info->locks[i].times_locked,
1363 lock_info->locks[i].times_lock_attempted,
1364 lock_info->locks[i].suspended ? " - suspended" : "");
1365#ifdef HAVE_BKTR
1366 append_backtrace_information(str, lock_info->locks[i].backtrace);
1367#endif
1368
1369 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
1370 return;
1371
1372 /* We only have further details for mutexes right now */
1373 if (lock_info->locks[i].type != AST_MUTEX)
1374 return;
1375
1376 lock = lock_info->locks[i].lock_addr;
1377 lt = lock->track;
1378 ast_reentrancy_lock(lt);
1379 for (j = 0; *str && j < lt->reentrancy; j++) {
1380 ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
1381 lt->file[j], lt->lineno[j], lt->func[j]);
1382 }
1383 ast_reentrancy_unlock(lt);
1384}
1385#endif /* ! LOW_MEMORY */
1386
1387/*! This function can help you find highly temporal locks; locks that happen for a
1388 short time, but at unexpected times, usually at times that create a deadlock,
1389 Why is this thing locked right then? Who is locking it? Who am I fighting
1390 with for this lock?
1391
1392 To answer such questions, just call this routine before you would normally try
1393 to acquire a lock. It doesn't do anything if the lock is not acquired. If the
1394 lock is taken, it will publish a line or two to the console via ast_log().
1395
1396 Sometimes, the lock message is pretty uninformative. For instance, you might
1397 find that the lock is being acquired deep within the astobj2 code; this tells
1398 you little about higher level routines that call the astobj2 routines.
1399 But, using gdb, you can set a break at the ast_log below, and for that
1400 breakpoint, you can set the commands:
1401 where
1402 cont
1403 which will give a stack trace and continue. -- that aught to do the job!
1404
1405*/
1406void ast_log_show_lock(void *this_lock_addr)
1407{
1408#if !defined(LOW_MEMORY)
1409 struct thr_lock_info *lock_info;
1410 struct ast_str *str;
1411
1412 if (!(str = ast_str_create(4096))) {
1413 ast_log(LOG_NOTICE,"Could not create str\n");
1414 return;
1415 }
1416
1417
1418 pthread_mutex_lock(&lock_infos_lock.mutex);
1419 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1420 int i;
1422 for (i = 0; str && i < lock_info->num_locks; i++) {
1423 /* ONLY show info about this particular lock, if
1424 it's acquired... */
1425 if (lock_info->locks[i].lock_addr == this_lock_addr) {
1426 append_lock_information(&str, lock_info, i);
1428 break;
1429 }
1430 }
1432 }
1433 pthread_mutex_unlock(&lock_infos_lock.mutex);
1434 ast_free(str);
1435#endif /* ! LOW_MEMORY */
1436}
1437
1438
1439struct ast_str *ast_dump_locks(void)
1440{
1441#if !defined(LOW_MEMORY)
1442 struct thr_lock_info *lock_info;
1443 struct ast_str *str;
1444 char print_time[32];
1445 struct timeval now = ast_tvnow();
1446
1447 if (!(str = ast_str_create(4096))) {
1448 return NULL;
1449 }
1450
1451 ast_format_duration_hh_mm_ss(now.tv_sec, print_time, sizeof(print_time));
1452
1453 ast_str_append(&str, 0, "\n"
1454 "=======================================================================\n"
1455 "=== %s\n"
1456 "=== Currently Held Locks at Time: %s.%06ld =================\n"
1457 "=======================================================================\n"
1458 "===\n"
1459 "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr>\n"
1460 "=== <locked at>, <failed at>, <held for> (attempts, times locked)\n"
1461 "===\n", ast_get_version(), print_time, now.tv_usec);
1462 if (!str) {
1463 return NULL;
1464 }
1465
1466 pthread_mutex_lock(&lock_infos_lock.mutex);
1467 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1468 int i;
1469 int header_printed = 0;
1471 for (i = 0; str && i < lock_info->num_locks; i++) {
1472 /* Don't show suspended locks */
1473 if (lock_info->locks[i].suspended) {
1474 continue;
1475 }
1476
1477 if (!header_printed) {
1478 if (lock_info->lwp != -1) {
1479 ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
1480 (long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
1481 } else {
1482 ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
1483 (long unsigned) lock_info->thread_id, lock_info->thread_name);
1484 }
1485 header_printed = 1;
1486 }
1487
1488 append_lock_information(&str, lock_info, i);
1489 }
1491 if (!str) {
1492 break;
1493 }
1494 if (header_printed) {
1495 ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
1496 "===\n");
1497 }
1498 if (!str) {
1499 break;
1500 }
1501 }
1502 pthread_mutex_unlock(&lock_infos_lock.mutex);
1503
1504 if (!str) {
1505 return NULL;
1506 }
1507
1508 ast_str_append(&str, 0, "=======================================================================\n"
1509 "\n");
1510
1511 return str;
1512#else /* if defined(LOW_MEMORY) */
1513 return NULL;
1514#endif
1515}
1516
1517#if !defined(LOW_MEMORY)
1518static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1519{
1520 struct ast_str *str;
1521
1522 switch (cmd) {
1523 case CLI_INIT:
1524 e->command = "core show locks";
1525 e->usage =
1526 "Usage: core show locks\n"
1527 " This command is for lock debugging. It prints out which locks\n"
1528 "are owned by each active thread.\n";
1530 return NULL;
1531
1532 case CLI_GENERATE:
1533 return NULL;
1534 }
1535
1536 str = ast_dump_locks();
1537 if (!str) {
1538 return CLI_FAILURE;
1539 }
1540
1541 ast_cli(a->fd, "%s", ast_str_buffer(str));
1542
1543 ast_free(str);
1544
1545 return CLI_SUCCESS;
1546}
1547
1548static struct ast_cli_entry utils_cli[] = {
1549 AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
1550};
1551#endif /* ! LOW_MEMORY */
1552#endif /* DEBUG_THREADS */
1553
1554#if !defined(LOW_MEMORY)
1555/*
1556 * support for 'show threads'. The start routine is wrapped by
1557 * dummy_start(), so that ast_register_thread() and
1558 * ast_unregister_thread() know the thread identifier.
1559 */
1560struct thr_arg {
1561 void *(*start_routine)(void *);
1562 void *data;
1563 char *name;
1564};
1565
1566/*
1567 * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
1568 * are odd macros which start and end a block, so they _must_ be
1569 * used in pairs (the latter with a '1' argument to call the
1570 * handler on exit.
1571 * On BSD we don't need this, but we keep it for compatibility.
1572 */
1573static void *dummy_start(void *data)
1574{
1575 void *ret;
1576 struct thr_arg a = *((struct thr_arg *) data); /* make a local copy */
1577#ifdef DEBUG_THREADS
1578 struct thr_lock_info *lock_info;
1579 pthread_mutexattr_t mutex_attr;
1580
1581 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1582 return NULL;
1583
1584 lock_info->thread_id = pthread_self();
1585 lock_info->lwp = ast_get_tid();
1586 lock_info->thread_name = ast_strdup(a.name);
1587
1588 pthread_mutexattr_init(&mutex_attr);
1589 pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
1590 pthread_mutex_init(&lock_info->lock, &mutex_attr);
1591 pthread_mutexattr_destroy(&mutex_attr);
1592
1593 pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1594 AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
1595 pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1596#endif /* DEBUG_THREADS */
1597
1598 /* note that even though data->name is a pointer to allocated memory,
1599 we are not freeing it here because ast_register_thread is going to
1600 keep a copy of the pointer and then ast_unregister_thread will
1601 free the memory
1602 */
1603 ast_free(data);
1605 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
1606
1607 ret = a.start_routine(a.data);
1608
1609 pthread_cleanup_pop(1);
1610
1611 return ret;
1612}
1613
1614#endif /* !LOW_MEMORY */
1615
1617{
1618#if !defined(LOW_MEMORY)
1619 return AST_STACKSIZE;
1620#else
1621 return AST_STACKSIZE_LOW;
1622#endif
1623}
1624
1625int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1626 void *data, size_t stacksize, const char *file, const char *caller,
1627 int line, const char *start_fn)
1628{
1629#if !defined(LOW_MEMORY)
1630 struct thr_arg *a;
1631#endif
1632
1633 if (!attr) {
1634 attr = ast_alloca(sizeof(*attr));
1635 pthread_attr_init(attr);
1636 }
1637
1638#if defined(__linux__) || defined(__FreeBSD__)
1639 /* On Linux and FreeBSD , pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
1640 which is kind of useless. Change this here to
1641 PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
1642 priority will propagate down to new threads by default.
1643 This does mean that callers cannot set a different priority using
1644 PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
1645 the priority afterwards with pthread_setschedparam(). */
1646 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1647 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
1648#endif
1649
1650 if (!stacksize)
1651 stacksize = AST_STACKSIZE;
1652
1653 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
1654 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
1655
1656#if !defined(LOW_MEMORY)
1657 if ((a = ast_malloc(sizeof(*a)))) {
1658 a->start_routine = start_routine;
1659 a->data = data;
1661 if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
1662 start_fn, line, file, caller) < 0) {
1663 a->name = NULL;
1664 }
1665 data = a;
1666 }
1667#endif /* !LOW_MEMORY */
1668
1669 return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
1670}
1671
1672
1673int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1674 void *data, size_t stacksize, const char *file, const char *caller,
1675 int line, const char *start_fn)
1676{
1677 unsigned char attr_destroy = 0;
1678 int res;
1679
1680 if (!attr) {
1681 attr = ast_alloca(sizeof(*attr));
1682 pthread_attr_init(attr);
1683 attr_destroy = 1;
1684 }
1685
1686 if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1687 ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
1688
1690 stacksize, file, caller, line, start_fn);
1691
1692 if (attr_destroy)
1693 pthread_attr_destroy(attr);
1694
1695 return res;
1696}
1697
1698int ast_wait_for_input(int fd, int ms)
1699{
1700 struct pollfd pfd[1];
1701
1702 memset(pfd, 0, sizeof(pfd));
1703 pfd[0].fd = fd;
1704 pfd[0].events = POLLIN | POLLPRI;
1705 return ast_poll(pfd, 1, ms);
1706}
1707
1708int ast_wait_for_output(int fd, int ms)
1709{
1710 struct pollfd pfd[1];
1711
1712 memset(pfd, 0, sizeof(pfd));
1713 pfd[0].fd = fd;
1714 pfd[0].events = POLLOUT;
1715 return ast_poll(pfd, 1, ms);
1716}
1717
1718static int wait_for_output(int fd, int timeoutms)
1719{
1720 struct pollfd pfd = {
1721 .fd = fd,
1722 .events = POLLOUT,
1723 };
1724 int res;
1725 struct timeval start = ast_tvnow();
1726 int elapsed = 0;
1727
1728 /* poll() until the fd is writable without blocking */
1729 while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1730 if (res == 0) {
1731 /* timed out. */
1732#ifndef STANDALONE
1733 ast_debug(1, "Timed out trying to write\n");
1734#endif
1735 return -1;
1736 } else if (res == -1) {
1737 /* poll() returned an error, check to see if it was fatal */
1738
1739 if (errno == EINTR || errno == EAGAIN) {
1740 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1741 if (elapsed >= timeoutms) {
1742 return -1;
1743 }
1744 /* This was an acceptable error, go back into poll() */
1745 continue;
1746 }
1747
1748 /* Fatal error, bail. */
1749 ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
1750
1751 return -1;
1752 }
1753 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1754 if (elapsed >= timeoutms) {
1755 return -1;
1756 }
1757 }
1758
1759 return 0;
1760}
1761
1762/*!
1763 * Try to write string, but wait no more than ms milliseconds before timing out.
1764 *
1765 * \note The code assumes that the file descriptor has NONBLOCK set,
1766 * so there is only one system call made to do a write, unless we actually
1767 * have a need to wait. This way, we get better performance.
1768 * If the descriptor is blocking, all assumptions on the guaranteed
1769 * detail do not apply anymore.
1770 */
1771int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
1772{
1773 struct timeval start = ast_tvnow();
1774 int res = 0;
1775 int elapsed = 0;
1776
1777 while (len) {
1778 if (wait_for_output(fd, timeoutms - elapsed)) {
1779 return -1;
1780 }
1781
1782 res = write(fd, s, len);
1783
1784 if (res < 0 && errno != EAGAIN && errno != EINTR) {
1785 /* fatal error from write() */
1786 if (errno == EPIPE) {
1787#ifndef STANDALONE
1788 ast_debug(1, "write() failed due to reading end being closed: %s\n", strerror(errno));
1789#endif
1790 } else {
1791 ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
1792 }
1793 return -1;
1794 }
1795
1796 if (res < 0) {
1797 /* It was an acceptable error */
1798 res = 0;
1799 }
1800
1801 /* Update how much data we have left to write */
1802 len -= res;
1803 s += res;
1804 res = 0;
1805
1806 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1807 if (elapsed >= timeoutms) {
1808 /* We've taken too long to write
1809 * This is only an error condition if we haven't finished writing. */
1810 res = len ? -1 : 0;
1811 break;
1812 }
1813 }
1814
1815 return res;
1816}
1817
1818char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
1819{
1820 char *e;
1821 char *q;
1822
1823 s = ast_strip(s);
1824 if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
1825 e = s + strlen(s) - 1;
1826 if (*e == *(end_quotes + (q - beg_quotes))) {
1827 s++;
1828 *e = '\0';
1829 }
1830 }
1831
1832 return s;
1833}
1834
1835char *ast_strsep(char **iss, const char sep, uint32_t flags)
1836{
1837 char *st = *iss;
1838 char *is;
1839 int inquote = 0;
1840 int found = 0;
1841 char stack[8];
1842
1843 if (ast_strlen_zero(st)) {
1844 *iss = NULL;
1845 return st;
1846 }
1847
1848 memset(stack, 0, sizeof(stack));
1849
1850 for(is = st; *is; is++) {
1851 if (*is == '\\') {
1852 if (*++is != '\0') {
1853 is++;
1854 } else {
1855 break;
1856 }
1857 }
1858
1859 if (*is == '\'' || *is == '"') {
1860 if (*is == stack[inquote]) {
1861 stack[inquote--] = '\0';
1862 } else {
1863 if (++inquote >= sizeof(stack)) {
1864 return NULL;
1865 }
1866 stack[inquote] = *is;
1867 }
1868 }
1869
1870 if (*is == sep && !inquote) {
1871 *is = '\0';
1872 found = 1;
1873 *iss = is + 1;
1874 break;
1875 }
1876 }
1877 if (!found) {
1878 *iss = NULL;
1879 }
1880
1881 if (flags & AST_STRSEP_STRIP) {
1882 st = ast_strip_quoted(st, "'\"", "'\"");
1883 }
1884
1885 if (flags & AST_STRSEP_TRIM) {
1886 char *trimmed = ast_strip(st);
1887 if (!ast_strlen_zero(trimmed)) {
1888 st = trimmed;
1889 }
1890 }
1891
1892 if (flags & AST_STRSEP_UNESCAPE) {
1894 }
1895
1896 return st;
1897}
1898
1899char *ast_strsep_quoted(char **iss, const char sep, const char quote, uint32_t flags)
1900{
1901 char *st = *iss;
1902 char *is;
1903 int inquote = 0;
1904 int found = 0;
1905 char stack[8];
1906 const char qstr[] = { quote };
1907
1908 if (ast_strlen_zero(st)) {
1909 *iss = NULL;
1910 return st;
1911 }
1912
1913 memset(stack, 0, sizeof(stack));
1914
1915 for(is = st; *is; is++) {
1916 if (*is == '\\') {
1917 if (*++is != '\0') {
1918 is++;
1919 } else {
1920 break;
1921 }
1922 }
1923
1924 if (*is == quote) {
1925 if (*is == stack[inquote]) {
1926 stack[inquote--] = '\0';
1927 } else {
1928 if (++inquote >= sizeof(stack)) {
1929 return NULL;
1930 }
1931 stack[inquote] = *is;
1932 }
1933 }
1934
1935 if (*is == sep && !inquote) {
1936 *is = '\0';
1937 found = 1;
1938 *iss = is + 1;
1939 break;
1940 }
1941 }
1942 if (!found) {
1943 *iss = NULL;
1944 }
1945
1946 if (flags & AST_STRSEP_STRIP) {
1947 st = ast_strip_quoted(st, qstr, qstr);
1948 }
1949
1950 if (flags & AST_STRSEP_TRIM) {
1951 char *trimmed = ast_strip(st);
1952 if (!ast_strlen_zero(trimmed)) {
1953 st = trimmed;
1954 }
1955 }
1956
1957 if (flags & AST_STRSEP_UNESCAPE) {
1959 }
1960
1961 return st;
1962}
1963
1965{
1966 char *e;
1967 char *work = s;
1968
1969 while ((e = strchr(work, ';'))) {
1970 if ((e > work) && (*(e-1) == '\\')) {
1971 memmove(e - 1, e, strlen(e) + 1);
1972 work = e;
1973 } else {
1974 work = e + 1;
1975 }
1976 }
1977
1978 return s;
1979}
1980
1981/* !\brief unescape some C sequences in place, return pointer to the original string.
1982 */
1983char *ast_unescape_c(char *src)
1984{
1985 char c, *ret, *dst;
1986
1987 if (src == NULL)
1988 return NULL;
1989 for (ret = dst = src; (c = *src++); *dst++ = c ) {
1990 if (c != '\\')
1991 continue; /* copy char at the end of the loop */
1992 switch ((c = *src++)) {
1993 case '\0': /* special, trailing '\' */
1994 c = '\\';
1995 break;
1996 case 'b': /* backspace */
1997 c = '\b';
1998 break;
1999 case 'f': /* form feed */
2000 c = '\f';
2001 break;
2002 case 'n':
2003 c = '\n';
2004 break;
2005 case 'r':
2006 c = '\r';
2007 break;
2008 case 't':
2009 c = '\t';
2010 break;
2011 }
2012 /* default, use the char literally */
2013 }
2014 *dst = '\0';
2015 return ret;
2016}
2017
2018/*
2019 * Standard escape sequences - Note, '\0' is not included as a valid character
2020 * to escape, but instead is used here as a NULL terminator for the string.
2021 */
2023 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\'', '\"', '\?', '\0'
2024};
2025
2026/*
2027 * Standard escape sequences output map (has to maintain matching order with
2028 * escape_sequences). '\0' is included here as a NULL terminator for the string.
2029 */
2030static char escape_sequences_map[] = {
2031 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"', '?', '\0'
2032};
2033
2034char *ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
2035{
2036 char *p;
2037 char *c;
2038
2039 if (!dest || !size) {
2040 return dest;
2041 }
2042 if (ast_strlen_zero(s)) {
2043 *dest = '\0';
2044 return dest;
2045 }
2046
2047 if (ast_strlen_zero(to_escape)) {
2048 ast_copy_string(dest, s, size);
2049 return dest;
2050 }
2051
2052 for (p = dest; *s && --size; ++s, ++p) {
2053 /* If in the list of characters to escape then escape it */
2054 if (strchr(to_escape, *s)) {
2055 if (!--size) {
2056 /* Not enough room left for the escape sequence. */
2057 break;
2058 }
2059
2060 /*
2061 * See if the character to escape is part of the standard escape
2062 * sequences. If so we'll have to use its mapped counterpart
2063 * otherwise just use the current character.
2064 */
2065 c = strchr(escape_sequences, *s);
2066 *p++ = '\\';
2068 } else {
2069 *p = *s;
2070 }
2071 }
2072 *p = '\0';
2073
2074 return dest;
2075}
2076
2077char *ast_escape_c(char *dest, const char *s, size_t size)
2078{
2079 /*
2080 * Note - This is an optimized version of ast_escape. When looking only
2081 * for escape_sequences a couple of checks used in the generic case can
2082 * be left out thus making it slightly more efficient.
2083 */
2084 char *p;
2085 char *c;
2086
2087 if (!dest || !size) {
2088 return dest;
2089 }
2090 if (ast_strlen_zero(s)) {
2091 *dest = '\0';
2092 return dest;
2093 }
2094
2095 for (p = dest; *s && --size; ++s, ++p) {
2096 /*
2097 * See if the character to escape is part of the standard escape
2098 * sequences. If so use its mapped counterpart.
2099 */
2100 c = strchr(escape_sequences, *s);
2101 if (c) {
2102 if (!--size) {
2103 /* Not enough room left for the escape sequence. */
2104 break;
2105 }
2106
2107 *p++ = '\\';
2109 } else {
2110 *p = *s;
2111 }
2112 }
2113 *p = '\0';
2114
2115 return dest;
2116}
2117
2118static char *escape_alloc(const char *s, size_t *size)
2119{
2120 if (!s) {
2121 return NULL;
2122 }
2123
2124 /*
2125 * The result string needs to be twice the size of the given
2126 * string just in case every character in it needs to be escaped.
2127 */
2128 *size = strlen(s) * 2 + 1;
2129 return ast_malloc(*size);
2130}
2131
2132char *ast_escape_alloc(const char *s, const char *to_escape)
2133{
2134 size_t size = 0;
2135 char *dest = escape_alloc(s, &size);
2136
2137 return ast_escape(dest, s, size, to_escape);
2138}
2139
2140char *ast_escape_c_alloc(const char *s)
2141{
2142 size_t size = 0;
2143 char *dest = escape_alloc(s, &size);
2144
2145 return ast_escape_c(dest, s, size);
2146}
2147
2148int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
2149{
2150 int result;
2151
2152 if (!buffer || !*buffer || !space || !*space)
2153 return -1;
2154
2155 result = vsnprintf(*buffer, *space, fmt, ap);
2156
2157 if (result < 0)
2158 return -1;
2159 else if (result > *space)
2160 result = *space;
2161
2162 *buffer += result;
2163 *space -= result;
2164 return 0;
2165}
2166
2167int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
2168{
2169 va_list ap;
2170 int result;
2171
2172 va_start(ap, fmt);
2173 result = ast_build_string_va(buffer, space, fmt, ap);
2174 va_end(ap);
2175
2176 return result;
2177}
2178
2179int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
2180{
2181 int regex_len = strlen(regex_string);
2182 int ret = 3;
2183
2184 /* Chop off the leading / if there is one */
2185 if ((regex_len >= 1) && (regex_string[0] == '/')) {
2186 ast_str_set(regex_pattern, 0, "%s", regex_string + 1);
2187 ret -= 2;
2188 }
2189
2190 /* Chop off the ending / if there is one */
2191 if ((regex_len > 1) && (regex_string[regex_len - 1] == '/')) {
2192 ast_str_truncate(*regex_pattern, -1);
2193 ret -= 1;
2194 }
2195
2196 return ret;
2197}
2198
2199int ast_true(const char *s)
2200{
2201 if (ast_strlen_zero(s))
2202 return 0;
2203
2204 /* Determine if this is a true value */
2205 if (!strcasecmp(s, "yes") ||
2206 !strcasecmp(s, "true") ||
2207 !strcasecmp(s, "y") ||
2208 !strcasecmp(s, "t") ||
2209 !strcasecmp(s, "1") ||
2210 !strcasecmp(s, "on"))
2211 return -1;
2212
2213 return 0;
2214}
2215
2216int ast_false(const char *s)
2217{
2218 if (ast_strlen_zero(s))
2219 return 0;
2220
2221 /* Determine if this is a false value */
2222 if (!strcasecmp(s, "no") ||
2223 !strcasecmp(s, "false") ||
2224 !strcasecmp(s, "n") ||
2225 !strcasecmp(s, "f") ||
2226 !strcasecmp(s, "0") ||
2227 !strcasecmp(s, "off"))
2228 return -1;
2229
2230 return 0;
2231}
2232
2233#define ONE_MILLION 1000000
2234/*
2235 * put timeval in a valid range. usec is 0..999999
2236 * negative values are not allowed and truncated.
2237 */
2238static struct timeval tvfix(struct timeval a)
2239{
2240 if (a.tv_usec >= ONE_MILLION) {
2241 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
2242 (long)a.tv_sec, (long int) a.tv_usec);
2243 a.tv_sec += a.tv_usec / ONE_MILLION;
2244 a.tv_usec %= ONE_MILLION;
2245 } else if (a.tv_usec < 0) {
2246 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
2247 (long)a.tv_sec, (long int) a.tv_usec);
2248 a.tv_usec = 0;
2249 }
2250 return a;
2251}
2252
2253struct timeval ast_tvadd(struct timeval a, struct timeval b)
2254{
2255 /* consistency checks to guarantee usec in 0..999999 */
2256 a = tvfix(a);
2257 b = tvfix(b);
2258 a.tv_sec += b.tv_sec;
2259 a.tv_usec += b.tv_usec;
2260 if (a.tv_usec >= ONE_MILLION) {
2261 a.tv_sec++;
2262 a.tv_usec -= ONE_MILLION;
2263 }
2264 return a;
2265}
2266
2267struct timeval ast_tvsub(struct timeval a, struct timeval b)
2268{
2269 /* consistency checks to guarantee usec in 0..999999 */
2270 a = tvfix(a);
2271 b = tvfix(b);
2272 a.tv_sec -= b.tv_sec;
2273 a.tv_usec -= b.tv_usec;
2274 if (a.tv_usec < 0) {
2275 a.tv_sec-- ;
2276 a.tv_usec += ONE_MILLION;
2277 }
2278 return a;
2279}
2280
2281int ast_remaining_ms(struct timeval start, int max_ms)
2282{
2283 int ms;
2284
2285 if (max_ms < 0) {
2286 ms = max_ms;
2287 } else {
2288 ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
2289 if (ms < 0) {
2290 ms = 0;
2291 }
2292 }
2293
2294 return ms;
2295}
2296
2297void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
2298{
2299 int durh, durm, durs;
2300 durh = duration / 3600;
2301 durm = (duration % 3600) / 60;
2302 durs = duration % 60;
2303 snprintf(buf, length, "%02d:%02d:%02d", durh, durm, durs);
2304}
2305
2306#undef ONE_MILLION
2307
2308#ifndef linux
2310#endif
2311
2312long int ast_random(void)
2313{
2314 long int res;
2315
2316 if (dev_urandom_fd >= 0) {
2317 int read_res = read(dev_urandom_fd, &res, sizeof(res));
2318 if (read_res > 0) {
2319 long int rm = RAND_MAX;
2320 res = res < 0 ? ~res : res;
2321 rm++;
2322 return res % rm;
2323 }
2324 }
2325
2326 /* XXX - Thread safety really depends on the libc, not the OS.
2327 *
2328 * But... popular Linux libc's (uClibc, glibc, eglibc), all have a
2329 * somewhat thread safe random(3) (results are random, but not
2330 * reproducible). The libc's for other systems (BSD, et al.), not so
2331 * much.
2332 */
2333#ifdef linux
2334 res = random();
2335#else
2337 res = random();
2339#endif
2340 return res;
2341}
2342
2344{
2345 for (; *s; s++) {
2346 if (*s == '^') {
2347 *s = ',';
2348 }
2349 }
2350}
2351
2352char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2353{
2354 char *dataPut = start;
2355 int inEscape = 0;
2356 int inQuotes = 0;
2357
2358 for (; *start; start++) {
2359 if (inEscape) {
2360 *dataPut++ = *start; /* Always goes verbatim */
2361 inEscape = 0;
2362 } else {
2363 if (*start == '\\') {
2364 inEscape = 1; /* Do not copy \ into the data */
2365 } else if (*start == '\'') {
2366 inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
2367 } else {
2368 /* Replace , with |, unless in quotes */
2369 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2370 }
2371 }
2372 }
2373 if (start != dataPut)
2374 *dataPut = 0;
2375 return dataPut;
2376}
2377
2378void ast_join_delim(char *s, size_t len, const char * const w[], unsigned int size, char delim)
2379{
2380 int x, ofs = 0;
2381 const char *src;
2382
2383 /* Join words into a string */
2384 if (!s)
2385 return;
2386 for (x = 0; ofs < len && x < size && w[x] ; x++) {
2387 if (x > 0)
2388 s[ofs++] = delim;
2389 for (src = w[x]; *src && ofs < len; src++)
2390 s[ofs++] = *src;
2391 }
2392 if (ofs == len)
2393 ofs--;
2394 s[ofs] = '\0';
2395}
2396
2397char *ast_to_camel_case_delim(const char *s, const char *delim)
2398{
2399 char *res = ast_strdup(s);
2400 char *front, *back, *buf = res;
2401 int size;
2402
2403 front = strtok_r(buf, delim, &back);
2404
2405 while (front) {
2406 size = strlen(front);
2407 *front = toupper(*front);
2408 ast_copy_string(buf, front, size + 1);
2409 buf += size;
2410 front = strtok_r(NULL, delim, &back);
2411 }
2412
2413 return res;
2414}
2415
2416/*! \brief
2417 * get values from config variables.
2418 */
2419int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
2420{
2421 long double dtv = 0.0;
2422 int scanned;
2423
2424 if (dst == NULL)
2425 return -1;
2426
2427 *dst = _default;
2428
2429 if (ast_strlen_zero(src))
2430 return -1;
2431
2432 /* only integer at the moment, but one day we could accept more formats */
2433 if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
2434 dst->tv_sec = dtv;
2435 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2436 if (consumed)
2437 *consumed = scanned;
2438 return 0;
2439 } else
2440 return -1;
2441}
2442
2443/*! \brief
2444 * get values from config variables.
2445 */
2446int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
2447{
2448 long t;
2449 int scanned;
2450
2451 if (dst == NULL)
2452 return -1;
2453
2454 *dst = _default;
2455
2456 if (ast_strlen_zero(src))
2457 return -1;
2458
2459 /* only integer at the moment, but one day we could accept more formats */
2460 if (sscanf(src, "%30ld%n", &t, &scanned) == 1) {
2461 *dst = t;
2462 if (consumed)
2463 *consumed = scanned;
2464 return 0;
2465 } else
2466 return -1;
2467}
2468
2470{
2471#if defined(HAVE_IP_MTU_DISCOVER)
2472 int val = IP_PMTUDISC_DONT;
2473
2474 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
2475 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
2476#endif /* HAVE_IP_MTU_DISCOVER */
2477}
2478
2479int ast_mkdir(const char *path, int mode)
2480{
2481 char *ptr;
2482 int len = strlen(path), count = 0, x, piececount = 0;
2483 char *tmp = ast_strdupa(path);
2484 char **pieces;
2485 char *fullpath = ast_alloca(len + 1);
2486 int res = 0;
2487
2488 for (ptr = tmp; *ptr; ptr++) {
2489 if (*ptr == '/')
2490 count++;
2491 }
2492
2493 /* Count the components to the directory path */
2494 pieces = ast_alloca(count * sizeof(*pieces));
2495 for (ptr = tmp; *ptr; ptr++) {
2496 if (*ptr == '/') {
2497 *ptr = '\0';
2498 pieces[piececount++] = ptr + 1;
2499 }
2500 }
2501
2502 *fullpath = '\0';
2503 for (x = 0; x < piececount; x++) {
2504 /* This looks funky, but the buffer is always ideally-sized, so it's fine. */
2505 strcat(fullpath, "/");
2506 strcat(fullpath, pieces[x]);
2507 res = mkdir(fullpath, mode);
2508 if (res && errno != EEXIST)
2509 return errno;
2510 }
2511 return 0;
2512}
2513
2514static int safe_mkdir(const char *base_path, char *path, int mode)
2515{
2516 RAII_VAR(char *, absolute_path, NULL, ast_std_free);
2517
2518 absolute_path = realpath(path, NULL);
2519
2520 if (absolute_path) {
2521 /* Path exists, but is it in the right place? */
2522 if (!ast_begins_with(absolute_path, base_path)) {
2523 return EPERM;
2524 }
2525
2526 /* It is in the right place! */
2527 return 0;
2528 } else {
2529 /* Path doesn't exist. */
2530
2531 /* The slash terminating the subpath we're checking */
2532 char *path_term = strchr(path, '/');
2533 /* True indicates the parent path is within base_path */
2534 int parent_is_safe = 0;
2535 int res;
2536
2537 while (path_term) {
2538 RAII_VAR(char *, absolute_subpath, NULL, ast_std_free);
2539
2540 /* Truncate the path one past the slash */
2541 char c = *(path_term + 1);
2542 *(path_term + 1) = '\0';
2543 absolute_subpath = realpath(path, NULL);
2544
2545 if (absolute_subpath) {
2546 /* Subpath exists, but is it safe? */
2547 parent_is_safe = ast_begins_with(
2548 absolute_subpath, base_path);
2549 } else if (parent_is_safe) {
2550 /* Subpath does not exist, but parent is safe
2551 * Create it */
2552 res = mkdir(path, mode);
2553 if (res != 0) {
2554 ast_assert(errno != EEXIST);
2555 return errno;
2556 }
2557 } else {
2558 /* Subpath did not exist, parent was not safe
2559 * Fail! */
2560 errno = EPERM;
2561 return errno;
2562 }
2563 /* Restore the path */
2564 *(path_term + 1) = c;
2565 /* Move on to the next slash */
2566 path_term = strchr(path_term + 1, '/');
2567 }
2568
2569 /* Now to build the final path, but only if it's safe */
2570 if (!parent_is_safe) {
2571 errno = EPERM;
2572 return errno;
2573 }
2574
2575 res = mkdir(path, mode);
2576 if (res != 0 && errno != EEXIST) {
2577 return errno;
2578 }
2579
2580 return 0;
2581 }
2582}
2583
2584int ast_safe_mkdir(const char *base_path, const char *path, int mode)
2585{
2586 RAII_VAR(char *, absolute_base_path, NULL, ast_std_free);
2587 RAII_VAR(char *, p, NULL, ast_free);
2588
2589 if (base_path == NULL || path == NULL) {
2590 errno = EFAULT;
2591 return errno;
2592 }
2593
2594 p = ast_strdup(path);
2595 if (p == NULL) {
2596 errno = ENOMEM;
2597 return errno;
2598 }
2599
2600 absolute_base_path = realpath(base_path, NULL);
2601 if (absolute_base_path == NULL) {
2602 return errno;
2603 }
2604
2605 return safe_mkdir(absolute_base_path, p, mode);
2606}
2607
2608static void utils_shutdown(void)
2609{
2610 close(dev_urandom_fd);
2611 dev_urandom_fd = -1;
2612#if defined(DEBUG_THREADS) && !defined(LOW_MEMORY)
2613 ast_cli_unregister_multiple(utils_cli, ARRAY_LEN(utils_cli));
2614#endif
2615}
2616
2618{
2619 dev_urandom_fd = open("/dev/urandom", O_RDONLY);
2620 base64_init();
2621#ifdef DEBUG_THREADS
2622#if !defined(LOW_MEMORY)
2623 ast_cli_register_multiple(utils_cli, ARRAY_LEN(utils_cli));
2624#endif
2625#endif
2627 return 0;
2628}
2629
2630
2631/*!
2632 *\brief Parse digest authorization header.
2633 *\return Returns -1 if we have no auth or something wrong with digest.
2634 *\note This function may be used for Digest request and responce header.
2635 * request arg is set to nonzero, if we parse Digest Request.
2636 * pedantic arg can be set to nonzero if we need to do addition Digest check.
2637 */
2638int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
2639 char *c;
2640 struct ast_str *str = ast_str_create(16);
2641
2642 /* table of recognised keywords, and places where they should be copied */
2643 const struct x {
2644 const char *key;
2645 const ast_string_field *field;
2646 } *i, keys[] = {
2647 { "username=", &d->username },
2648 { "realm=", &d->realm },
2649 { "nonce=", &d->nonce },
2650 { "uri=", &d->uri },
2651 { "domain=", &d->domain },
2652 { "response=", &d->response },
2653 { "cnonce=", &d->cnonce },
2654 { "opaque=", &d->opaque },
2655 /* Special cases that cannot be directly copied */
2656 { "algorithm=", NULL },
2657 { "qop=", NULL },
2658 { "nc=", NULL },
2659 { NULL, 0 },
2660 };
2661
2662 if (ast_strlen_zero(digest) || !d || !str) {
2663 ast_free(str);
2664 return -1;
2665 }
2666
2667 ast_str_set(&str, 0, "%s", digest);
2668
2670
2671 if (strncasecmp(c, "Digest ", strlen("Digest "))) {
2672 ast_log(LOG_WARNING, "Missing Digest.\n");
2673 ast_free(str);
2674 return -1;
2675 }
2676 c += strlen("Digest ");
2677
2678 /* lookup for keys/value pair */
2679 while (c && *c && *(c = ast_skip_blanks(c))) {
2680 /* find key */
2681 for (i = keys; i->key != NULL; i++) {
2682 char *src, *separator;
2683 int unescape = 0;
2684 if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
2685 continue;
2686 }
2687
2688 /* Found. Skip keyword, take text in quotes or up to the separator. */
2689 c += strlen(i->key);
2690 if (*c == '"') {
2691 src = ++c;
2692 separator = "\"";
2693 unescape = 1;
2694 } else {
2695 src = c;
2696 separator = ",";
2697 }
2698 strsep(&c, separator); /* clear separator and move ptr */
2699 if (unescape) {
2700 ast_unescape_c(src);
2701 }
2702 if (i->field) {
2703 ast_string_field_ptr_set(d, i->field, src);
2704 } else {
2705 /* Special cases that require additional processing */
2706 if (!strcasecmp(i->key, "algorithm=")) {
2707 if (strcasecmp(src, "MD5")) {
2708 ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", src);
2709 ast_free(str);
2710 return -1;
2711 }
2712 } else if (!strcasecmp(i->key, "qop=") && !strcasecmp(src, "auth")) {
2713 d->qop = 1;
2714 } else if (!strcasecmp(i->key, "nc=")) {
2715 unsigned long u;
2716 if (sscanf(src, "%30lx", &u) != 1) {
2717 ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", src);
2718 ast_free(str);
2719 return -1;
2720 }
2721 ast_string_field_set(d, nc, src);
2722 }
2723 }
2724 break;
2725 }
2726 if (i->key == NULL) { /* not found, try ',' */
2727 strsep(&c, ",");
2728 }
2729 }
2730 ast_free(str);
2731
2732 /* Digest checkout */
2733 if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
2734 /* "realm" and "nonce" MUST be always exist */
2735 return -1;
2736 }
2737
2738 if (!request) {
2739 /* Additional check for Digest response */
2740 if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
2741 return -1;
2742 }
2743
2744 if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
2745 return -1;
2746 }
2747 }
2748
2749 return 0;
2750}
2751
2753{
2754 int ret = -1;
2755#if defined (__linux) && defined(SYS_gettid)
2756 ret = syscall(SYS_gettid); /* available since Linux 1.4.11 */
2757#elif defined(__sun)
2758 ret = pthread_self();
2759#elif defined(__APPLE__)
2760 ret = mach_thread_self();
2761 mach_port_deallocate(mach_task_self(), ret);
2762#elif defined(__FreeBSD__)
2763 long lwpid;
2764 thr_self(&lwpid);
2765 ret = lwpid;
2766#elif defined(__NetBSD__)
2767 ret = _lwp_self();
2768#elif defined(__OpenBSD__)
2769 ret = getthrid();
2770#endif
2771 return ret;
2772}
2773
2774char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
2775{
2776 const char *envPATH = getenv("PATH");
2777 char *tpath, *path;
2778 struct stat unused;
2779 if (!envPATH) {
2780 return NULL;
2781 }
2782 tpath = ast_strdupa(envPATH);
2783 while ((path = strsep(&tpath, ":"))) {
2784 snprintf(fullpath, fullpath_size, "%s/%s", path, binary);
2785 if (!stat(fullpath, &unused)) {
2786 return fullpath;
2787 }
2788 }
2789 return NULL;
2790}
2791
2793{
2794 int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
2795
2796 if (udp6_socket < 0) {
2797 return 0;
2798 }
2799
2800 close(udp6_socket);
2801 return 1;
2802}
2803
2805{
2806#if defined(DO_CRASH)
2807 abort();
2808 /*
2809 * Just in case abort() doesn't work or something else super
2810 * silly, and for Qwell's amusement.
2811 */
2812 *((int *) 0) = 0;
2813#endif /* defined(DO_CRASH) */
2814}
2815
2816void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
2817{
2818 /*
2819 * Attempt to put it into the logger, but hope that at least
2820 * someone saw the message on stderr ...
2821 */
2822 fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
2823 condition_str, condition, line, function, file);
2824 ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
2825 condition_str, condition);
2826
2827 /* Generate a backtrace for the assert */
2829
2830 /*
2831 * Give the logger a chance to get the message out, just in case
2832 * we abort(), or Asterisk crashes due to whatever problem just
2833 * happened after we exit ast_assert().
2834 */
2835 usleep(1);
2836 ast_do_crash();
2837}
2838
2839char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
2840{
2841 int x;
2842 char *os = s;
2843 if (maxlen < 18) {
2844 if (s && (maxlen > 0)) {
2845 *s = '\0';
2846 }
2847 } else {
2848 for (x = 0; x < 5; x++) {
2849 sprintf(s, "%02hhx:", eid->eid[x]);
2850 s += 3;
2851 }
2852 sprintf(s, "%02hhx", eid->eid[5]);
2853 }
2854 return os;
2855}
2856
2857#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Darwin__)
2858#include <ifaddrs.h>
2859#include <net/if_dl.h>
2860
2861void ast_set_default_eid(struct ast_eid *eid)
2862{
2863 struct ifaddrs *ifap, *ifaphead;
2864 int rtnerr;
2865 const struct sockaddr_dl *sdl;
2866 int alen;
2867 caddr_t ap;
2868 char eid_str[20];
2869 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2870 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2871
2872 rtnerr = getifaddrs(&ifaphead);
2873 if (rtnerr) {
2874 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2875 "You will have to set it manually.\n");
2876 return;
2877 }
2878
2879 if (!ifaphead) {
2880 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2881 "You will have to set it manually.\n");
2882 return;
2883 }
2884
2885 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
2886 if (ifap->ifa_addr->sa_family != AF_LINK) {
2887 continue;
2888 }
2889
2890 sdl = (const struct sockaddr_dl *) ifap->ifa_addr;
2891 ap = ((caddr_t) ((sdl)->sdl_data + (sdl)->sdl_nlen));
2892 alen = sdl->sdl_alen;
2893 if (alen != 6 || !(memcmp(ap, &empty_mac, 6) && memcmp(ap, &full_mac, 6))) {
2894 continue;
2895 }
2896
2897 memcpy(eid, ap, sizeof(*eid));
2898 ast_debug(1, "Seeding global EID '%s'\n",
2899 ast_eid_to_str(eid_str, sizeof(eid_str), eid));
2900 freeifaddrs(ifaphead);
2901 return;
2902 }
2903
2904 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2905 "You will have to set it manually.\n");
2906 freeifaddrs(ifaphead);
2907
2908 return;
2909}
2910
2911#elif defined(SOLARIS)
2912#include <sys/sockio.h>
2913#include <net/if_arp.h>
2914
2915void ast_set_default_eid(struct ast_eid *eid)
2916{
2917 int s;
2918 int x;
2919 struct lifreq *ifr = NULL;
2920 struct lifnum ifn;
2921 struct lifconf ifc;
2922 struct arpreq ar;
2923 struct sockaddr_in *sa, *sa2;
2924 char *buf = NULL;
2925 char eid_str[20];
2926 int bufsz;
2927 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2928 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2929
2930 s = socket(AF_INET, SOCK_STREAM, 0);
2931 if (s <= 0) {
2932 ast_log(LOG_WARNING, "Unable to open a socket for seeding global EID. "
2933 " You will have to set it manually.\n");
2934 return;
2935 }
2936
2937 /* Get a count of interfaces on the machine */
2938 ifn.lifn_family = AF_UNSPEC;
2939 ifn.lifn_flags = 0;
2940 ifn.lifn_count = 0;
2941 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
2942 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2943 " You will have to set it manually.\n");
2944 close(s);
2945 return;
2946 }
2947
2948 bufsz = ifn.lifn_count * sizeof(struct lifreq);
2949 if (!(buf = ast_malloc(bufsz))) {
2950 ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
2951 "You will have to set it manually.\n");
2952 close(s);
2953 return;
2954 }
2955 memset(buf, 0, bufsz);
2956
2957 /* Get a list of interfaces on the machine */
2958 ifc.lifc_len = bufsz;
2959 ifc.lifc_buf = buf;
2960 ifc.lifc_family = AF_UNSPEC;
2961 ifc.lifc_flags = 0;
2962 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
2963 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2964 "You will have to set it manually.\n");
2965 ast_free(buf);
2966 close(s);
2967 return;
2968 }
2969
2970 for (ifr = (struct lifreq *)buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
2971 unsigned char *p;
2972
2973 sa = (struct sockaddr_in *)&(ifr->lifr_addr);
2974 sa2 = (struct sockaddr_in *)&(ar.arp_pa);
2975 *sa2 = *sa;
2976
2977 if(ioctl(s, SIOCGARP, &ar) >= 0) {
2978 p = (unsigned char *)&(ar.arp_ha.sa_data);
2979 if (!(memcmp(p, &empty_mac, 6) && memcmp(p, &full_mac, 6))) {
2980 continue;
2981 }
2982
2983 memcpy(eid, p, sizeof(*eid));
2984 ast_debug(1, "Seeding global EID '%s'\n",
2985 ast_eid_to_str(eid_str, sizeof(eid_str), eid));
2986 ast_free(buf);
2987 close(s);
2988 return;
2989 }
2990 }
2991
2992 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2993 "You will have to set it manually.\n");
2994 ast_free(buf);
2995 close(s);
2996
2997 return;
2998}
2999
3000#else
3002{
3003 int s;
3004 int i;
3005 struct ifreq *ifr;
3006 struct ifreq *ifrp;
3007 struct ifconf ifc;
3008 char *buf = NULL;
3009 char eid_str[20];
3010 int bufsz, num_interfaces;
3011 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
3012 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3013
3014 s = socket(AF_INET, SOCK_STREAM, 0);
3015 if (s < 0) {
3016 ast_log(LOG_WARNING, "Unable to open socket for seeding global EID. "
3017 "You will have to set it manually.\n");
3018 return;
3019 }
3020
3021 ifc.ifc_len = 0;
3022 ifc.ifc_buf = NULL;
3023 if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
3024 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3025 "You will have to set it manually.\n");
3026 close(s);
3027 return;
3028 }
3029 bufsz = ifc.ifc_len;
3030
3031 if (!(buf = ast_malloc(bufsz))) {
3032 ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
3033 "You will have to set it manually.\n");
3034 close(s);
3035 return;
3036 }
3037
3038 ifc.ifc_buf = buf;
3039 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
3040 ast_log(LOG_WARNING, "Unable to retrieve ethernet interfaces for seeding global EID. "
3041 "You will have to set it manually.\n");
3042 ast_free(buf);
3043 close(s);
3044 return;
3045 }
3046
3047 ifrp = ifc.ifc_req;
3048 num_interfaces = ifc.ifc_len / sizeof(*ifr);
3049
3050 for (i = 0; i < num_interfaces; i++) {
3051 ifr = &ifrp[i];
3052 if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
3053 unsigned char *hwaddr = (unsigned char *) ifr->ifr_hwaddr.sa_data;
3054
3055 if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
3056 continue;
3057 }
3058
3059 memcpy(eid, hwaddr, sizeof(*eid));
3060 ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
3061 ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr->ifr_name);
3062 ast_free(buf);
3063 close(s);
3064 return;
3065 }
3066 }
3067
3068 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3069 "You will have to set it manually.\n");
3070 ast_free(buf);
3071 close(s);
3072
3073 return;
3074}
3075#endif /* LINUX */
3076
3077int ast_str_to_eid(struct ast_eid *eid, const char *s)
3078{
3079 unsigned int eid_int[6];
3080 int x;
3081
3082 if (sscanf(s, "%2x:%2x:%2x:%2x:%2x:%2x", &eid_int[0], &eid_int[1], &eid_int[2],
3083 &eid_int[3], &eid_int[4], &eid_int[5]) != 6) {
3084 return -1;
3085 }
3086
3087 for (x = 0; x < 6; x++) {
3088 eid->eid[x] = eid_int[x];
3089 }
3090
3091 return 0;
3092}
3093
3094int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
3095{
3096 return memcmp(eid1, eid2, sizeof(*eid1));
3097}
3098
3099int ast_eid_is_empty(const struct ast_eid *eid)
3100{
3101 struct ast_eid empty_eid;
3102
3103 memset(&empty_eid, 0, sizeof(empty_eid));
3104 return memcmp(eid, &empty_eid, sizeof(empty_eid)) ? 0 : 1;
3105}
3106
3107int ast_file_is_readable(const char *filename)
3108{
3109#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3110#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3111#define eaccess euidaccess
3112#endif
3113 return eaccess(filename, R_OK) == 0;
3114#else
3115 int fd = open(filename, O_RDONLY | O_NONBLOCK);
3116 if (fd < 0) {
3117 return 0;
3118 }
3119 close(fd);
3120 return 1;
3121#endif
3122}
3123
3124int ast_compare_versions(const char *version1, const char *version2)
3125{
3126 unsigned int major[2] = { 0 };
3127 unsigned int minor[2] = { 0 };
3128 unsigned int patch[2] = { 0 };
3129 unsigned int extra[2] = { 0 };
3130 int res;
3131
3132 sscanf(version1, "%u.%u.%u.%u", &major[0], &minor[0], &patch[0], &extra[0]);
3133 sscanf(version2, "%u.%u.%u.%u", &major[1], &minor[1], &patch[1], &extra[1]);
3134
3135 res = major[0] - major[1];
3136 if (res) {
3137 return res;
3138 }
3139 res = minor[0] - minor[1];
3140 if (res) {
3141 return res;
3142 }
3143 res = patch[0] - patch[1];
3144 if (res) {
3145 return res;
3146 }
3147 return extra[0] - extra[1];
3148}
3149
3150int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
3151 const char *file, int lineno, const char *function)
3152{
3153 int f;
3154
3155 f = fcntl(fd, F_GETFL);
3156 if (f == -1) {
3157 ast_log(__LOG_ERROR, file, lineno, function,
3158 "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
3159 return -1;
3160 }
3161
3162 switch (op) {
3163 case AST_FD_FLAG_SET:
3164 if ((f & flags) == flags) {
3165 /* There is nothing to set */
3166 return 0;
3167 }
3168 f |= flags;
3169 break;
3170 case AST_FD_FLAG_CLEAR:
3171 if (!(f & flags)) {
3172 /* There is nothing to clear */
3173 return 0;
3174 }
3175 f &= ~flags;
3176 break;
3177 default:
3178 ast_assert(0);
3179 break;
3180 }
3181
3182 f = fcntl(fd, F_SETFL, f);
3183 if (f == -1) {
3184 ast_log(__LOG_ERROR, file, lineno, function,
3185 "Failed to set fcntl() flags for file descriptor: %s\n", strerror(errno));
3186 return -1;
3187 }
3188
3189 return 0;
3190}
3191
3192#ifndef HAVE_SOCK_NONBLOCK
3193int ast_socket_nonblock(int domain, int type, int protocol)
3194{
3195 int s = socket(domain, type, protocol);
3196 if (s < 0) {
3197 return -1;
3198 }
3199
3200 if (ast_fd_set_flags(s, O_NONBLOCK)) {
3201 close(s);
3202 return -1;
3203 }
3204
3205 return s;
3206}
3207#endif
3208
3209#ifndef HAVE_PIPE2
3210int ast_pipe_nonblock(int filedes[2])
3211{
3212 int p = pipe(filedes);
3213 if (p < 0) {
3214 return -1;
3215 }
3216
3217 if (ast_fd_set_flags(filedes[0], O_NONBLOCK)
3218 || ast_fd_set_flags(filedes[1], O_NONBLOCK)) {
3219 close(filedes[0]);
3220 close(filedes[1]);
3221 return -1;
3222 }
3223
3224 return 0;
3225}
3226#endif
3227
3228/*!
3229 * \brief A thread local indicating whether the current thread is a user interface.
3230 */
3232
3233int ast_thread_user_interface_set(int is_user_interface)
3234{
3235 int *thread_user_interface;
3236
3237 thread_user_interface = ast_threadstorage_get(
3238 &thread_user_interface_tl, sizeof(*thread_user_interface));
3239 if (thread_user_interface == NULL) {
3240 ast_log(LOG_ERROR, "Error setting user interface status for current thread\n");
3241 return -1;
3242 }
3243
3244 *thread_user_interface = !!is_user_interface;
3245 return 0;
3246}
3247
3249{
3250 int *thread_user_interface;
3251
3252 thread_user_interface = ast_threadstorage_get(
3253 &thread_user_interface_tl, sizeof(*thread_user_interface));
3254 if (thread_user_interface == NULL) {
3255 ast_log(LOG_ERROR, "Error checking thread's user interface status\n");
3256 /* On error, assume that we are not a user interface thread */
3257 return 0;
3258 }
3259
3260 return *thread_user_interface;
3261}
3262
3263int ast_check_command_in_path(const char *cmd)
3264{
3265 char *token, *saveptr, *path = getenv("PATH");
3266 char filename[PATH_MAX];
3267 int len;
3268
3269 if (path == NULL) {
3270 return 0;
3271 }
3272
3273 path = ast_strdup(path);
3274 if (path == NULL) {
3275 return 0;
3276 }
3277
3278 token = strtok_r(path, ":", &saveptr);
3279 while (token != NULL) {
3280 len = snprintf(filename, sizeof(filename), "%s/%s", token, cmd);
3281 if (len < 0 || len >= sizeof(filename)) {
3282 ast_log(LOG_WARNING, "Path constructed with '%s' too long; skipping\n", token);
3283 continue;
3284 }
3285
3286 if (access(filename, X_OK) == 0) {
3287 ast_free(path);
3288 return 1;
3289 }
3290
3291 token = strtok_r(NULL, ":", &saveptr);
3292 }
3293 ast_free(path);
3294 return 0;
3295}
3296
const char * str
Definition: app_jack.c:147
pthread_t thread
Definition: app_sla.c:329
ast_mutex_t lock
Definition: app_sla.c:331
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define PATH_MAX
Definition: asterisk.h:40
void ast_std_free(void *ptr)
Definition: astmm.c:1734
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ast_bt_free_symbols(string_vector)
Definition: backtrace.h:42
#define ast_bt_get_symbols(addresses, num_frames)
Definition: backtrace.h:41
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
static const char type[]
Definition: chan_ooh323.c:109
static int request(void *obj)
Definition: chan_pjsip.c:2601
ast_lock_type
Definition: check_expr.c:35
@ AST_RDLOCK
Definition: check_expr.c:37
@ AST_WRLOCK
Definition: check_expr.c:38
@ AST_MUTEX
Definition: check_expr.c:36
Standard Command Line Interface.
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
Definition: main/cli.c:3056
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_mark_lock_failed(void *lock_addr)
Definition: extconf.c:2313
#define max(a, b)
Definition: f2c.h:198
static const char name[]
Definition: format_mp3.c:68
static const struct ast_datastore_info lock_info
Definition: func_lock.c:127
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:52
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define __LOG_ERROR
#define AST_LOG_WARNING
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
Definition: logger.c:2498
I/O Management (derived from Cheops-NG)
A set of macros to manage forward-linked lists.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:346
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
Asterisk locking-related definitions:
#define gethostbyname
Definition: lock.h:639
#define pthread_create
Definition: lock.h:642
#define pthread_mutex_lock
Definition: lock.h:625
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define pthread_mutex_t
Definition: lock.h:622
#define AST_MUTEX_KIND
Definition: lock.h:77
#define pthread_mutex_unlock
Definition: lock.h:626
#define pthread_mutex_destroy
Definition: lock.h:629
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define pthread_mutex_init
Definition: lock.h:628
int errno
MD5 digest functions.
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:72
void MD5Init(struct MD5Context *context)
Definition: md5.c:57
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Definition: md5.c:120
Wrapper for network related headers, masking differences between various operating systems....
static dundi_eid empty_eid
Definition: pbx_dundi.c:214
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
const char * string
Definition: presencestate.c:71
#define NULL
Definition: resample.c:96
int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
SHA1Result Returns the resulting 160-bit digest.
Definition: sha1.c:226
int SHA1Input(SHA1Context *, const uint8_t *bytes, unsigned int bytecount)
int SHA1Reset(SHA1Context *)
SHA1Reset.
Definition: sha1.c:101
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
const char * ast_string_field
Definition: stringfields.h:190
#define ast_string_field_ptr_set(x, ptr, data)
Set a field to a simple string value.
Definition: stringfields.h:475
String manipulation functions.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:786
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
@ AST_STRSEP_TRIM
Definition: strings.h:256
@ AST_STRSEP_UNESCAPE
Definition: strings.h:257
@ AST_STRSEP_STRIP
Definition: strings.h:255
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Definition: md5.h:26
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
Definition: backtrace.h:50
void * addresses[AST_MAX_BT_FRAMES]
Definition: backtrace.h:52
int num_frames
Definition: backtrace.h:54
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
const char * type
Definition: datastore.h:32
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
unsigned char eid[6]
Definition: utils.h:814
Structure used to handle boolean flags.
Definition: utils.h:199
char buf[1024]
Definition: utils.h:210
struct hostent hp
Definition: utils.h:209
Lock tracking information.
Definition: lock.h:111
int reentrancy
Definition: lock.h:114
int lineno[AST_MAX_REENTRANCY]
Definition: lock.h:113
const char * file[AST_MAX_REENTRANCY]
Definition: lock.h:112
const char * func[AST_MAX_REENTRANCY]
Definition: lock.h:115
Structure for mutex and tracking information.
Definition: lock.h:135
Support for dynamic strings.
Definition: strings.h:623
String vector definitions.
Definition: vector.h:55
Structure used for base64 encoding.
Definition: utils.c:579
int iolen
Definition: utils.c:581
unsigned char iobuf[BASEMAXINLINE]
Definition: utils.c:584
int linelength
Definition: utils.c:582
int ateof
Definition: utils.c:583
int iocp
Definition: utils.c:580
Definition: search.h:40
const char * name
char * name
Definition: utils.c:1563
void * data
Definition: utils.c:1562
void *(* start_routine)(void *)
Definition: utils.c:1561
Definition: ast_expr2.c:325
static struct test_val b
static struct test_val a
static struct test_val d
static struct test_val c
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
Time-related functions and macros.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
FILE * out
Definition: utils/frame.c:33
char * ast_to_camel_case_delim(const char *s, const char *delim)
Attempts to convert the given string to camel case using the specified delimiter.
Definition: utils.c:2397
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
Definition: utils.c:3248
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: utils.c:842
static char base64[64]
Definition: utils.c:80
int ast_base64url_encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
Same as ast_base64encode_full but for base64 URL.
Definition: utils.c:471
int ast_base64_encode_file(FILE *inputfile, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
Definition: utils.c:648
#define BASELINELEN
Definition: utils.c:575
int ast_base64decode(unsigned char *dst, const char *src, int max)
decode BASE64 encoded text
Definition: utils.c:296
int ast_check_command_in_path(const char *cmd)
Test for the presence of an executable command in $PATH.
Definition: utils.c:3263
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
Definition: utils.c:2584
static char base64url[64]
Definition: utils.c:81
static int dev_urandom_fd
Definition: utils.c:938
int ast_xml_escape(const char *string, char *const outbuf, const size_t buflen)
Escape reserved characters for use in XML.
Definition: utils.c:864
static struct ast_threadstorage thread_user_interface_tl
Definition: utils.c:3231
char * ast_base64url_encode_string(const char *src)
Encode string in base64 URL.
Definition: utils.c:523
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: utils.c:3107
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
Definition: utils.c:1771
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2446
int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, const char *file, int lineno, const char *function)
Definition: utils.c:3150
int ast_background_stacksize(void)
Definition: utils.c:1616
char escape_sequences[]
Definition: utils.c:2022
char * ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
Resolve a binary to a full pathname.
Definition: utils.c:2774
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: utils.c:723
void ast_set_default_eid(struct ast_eid *eid)
Fill in an ast_eid with the default eid of this machine.
Definition: utils.c:3001
int ast_thread_user_interface_set(int is_user_interface)
Set the current thread's user interface status.
Definition: utils.c:3233
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: utils.c:3094
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: utils.c:781
static void * dummy_start(void *data)
Definition: utils.c:1573
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:406
char * ast_unescape_c(char *src)
Convert some C escape sequences.
Definition: utils.c:1983
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
Definition: utils.c:615
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:2167
int ast_wait_for_input(int fd, int ms)
Definition: utils.c:1698
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
Definition: utils.c:2638
char * ast_base64decode_string(const char *src)
Decode BASE64 encoded text and return the string.
Definition: utils.c:323
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
Definition: utils.c:2297
#define ONE_MILLION
Definition: utils.c:2233
static void utils_shutdown(void)
Definition: utils.c:2608
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
get values from config variables.
Definition: utils.c:2419
char * ast_unescape_semicolon(char *s)
Strip backslash for "escaped" semicolons, the string to be stripped (will be modified).
Definition: utils.c:1964
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
char * ast_base64encode_string(const char *src)
Encode to BASE64 and return encoded string.
Definition: utils.c:412
char * ast_escape_c(char *dest, const char *s, size_t size)
Escape standard 'C' sequences in the given string.
Definition: utils.c:2077
int ast_get_tid(void)
Get current thread ID.
Definition: utils.c:2752
char * ast_strsep(char **iss, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
long int ast_random(void)
Definition: utils.c:2312
static void base64_init(void)
Definition: utils.c:540
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2479
int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:2148
char * ast_escape_alloc(const char *s, const char *to_escape)
Escape the 'to_escape' characters in the given string.
Definition: utils.c:2132
const struct ast_flags ast_uri_http
Definition: utils.c:719
int ast_utils_init(void)
Definition: utils.c:2617
int ast_wait_for_output(int fd, int ms)
Definition: utils.c:1708
static char * escape_alloc(const char *s, size_t *size)
Definition: utils.c:2118
static char b2a[256]
Definition: utils.c:82
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
Definition: utils.c:2469
#define BASEMAXINLINE
Definition: utils.c:576
int ast_base64url_decode(unsigned char *dst, const char *src, int max)
Decode data from base64 URL.
Definition: utils.c:429
int ast_compare_versions(const char *version1, const char *version2)
Compare 2 major.minor.patch.extra version strings.
Definition: utils.c:3124
char * ast_strsep_quoted(char **iss, const char sep, const char quote, uint32_t flags)
Like ast_strsep() except you can specify a specific quote character.
Definition: utils.c:1899
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: utils.c:3099
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64 URL.
Definition: utils.c:518
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: utils.c:2253
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
Definition: utils.c:2804
char * ast_process_quotes_and_slashes(char *start, char find, char replace_with)
Process a string to find and replace characters.
Definition: utils.c:2352
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: utils.c:2267
static int safe_mkdir(const char *base_path, char *path, int mode)
Definition: utils.c:2514
static char b2a_url[256]
Definition: utils.c:83
char * ast_escape_semicolons(const char *string, char *outbuf, int buflen)
Escape semicolons found in a string.
Definition: utils.c:811
int ast_false(const char *s)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
static char escape_sequences_map[]
Definition: utils.c:2030
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
encode text to BASE64 coding
Definition: utils.c:355
int ast_true(const char *s)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static struct ast_threadstorage inet_ntoa_buf
Definition: utils.c:85
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
Produce a 20 byte SHA1 hash of value.
Definition: utils.c:284
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
Definition: utils.c:590
static int ochar(struct baseio *bio, int c, FILE *so, const char *endl)
utility used by base_encode()
Definition: utils.c:629
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: utils.c:2792
char * ast_base64url_decode_string(const char *src)
Decode string from base64 URL.
Definition: utils.c:450
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
Definition: utils.c:2140
const char * ast_inet_ntoa(struct in_addr ia)
ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa
Definition: utils.c:928
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: utils.c:3077
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: utils.c:762
int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
Definition: utils.c:702
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Re-entrant (thread safe) version of gethostbyname that replaces the standard gethostbyname (which is ...
Definition: utils.c:199
static struct timeval tvfix(struct timeval a)
Definition: utils.c:2238
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
Definition: utils.c:2343
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
Definition: utils.c:2816
const struct ast_flags ast_uri_sip_user
Definition: utils.c:721
void ast_md5_hash(char *output, const char *input)
Produce 32 char MD5 hash of value.
Definition: utils.c:250
int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
Definition: utils.c:1673
void ast_sha1_hash(char *output, const char *input)
Produce 40 char SHA1 hash of value.
Definition: utils.c:266
int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
Definition: utils.c:1625
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
Given a string regex_string in the form of "/regex/", convert it into the form of "regex".
Definition: utils.c:2179
const struct ast_flags ast_uri_http_legacy
Definition: utils.c:720
static int wait_for_output(int fd, int timeoutms)
Definition: utils.c:1718
void ast_join_delim(char *s, size_t len, const char *const w[], unsigned int size, char delim)
Join an array of strings into a single string.
Definition: utils.c:2378
char * ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
Escape the 'to_escape' characters in the given string.
Definition: utils.c:2034
static ast_mutex_t randomlock
Definition: utils.c:2309
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_URI_LEGACY_SPACE
Definition: utils.h:367
#define AST_URI_MARK
Definition: utils.h:365
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739
#define AST_URI_SIP_USER_UNRESERVED
Definition: utils.h:369
#define DO_CRASH_NORETURN
Definition: utils.h:717
ast_fd_flag_operation
Definition: utils.h:1021
@ AST_FD_FLAG_SET
Definition: utils.h:1022
@ AST_FD_FLAG_CLEAR
Definition: utils.h:1023
#define AST_URI_ALPHANUM
Definition: utils.h:364
#define AST_STACKSIZE
Definition: utils.h:565
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1073
#define AST_URI_UNRESERVED
Definition: utils.h:366
#define AST_STACKSIZE_LOW
Definition: utils.h:566
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1039
void ast_register_thread(char *name)
Definition: asterisk.c:414
void ast_unregister_thread(void *id)
Definition: asterisk.c:430
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
Definition: utils.h:1090
#define ARRAY_LEN(a)
Definition: utils.h:666
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680