Asterisk - The Open Source Telephony Project GIT-master-0a46be9
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
781int ast_uri_verify_encoded(const char *string)
782{
783 const char *ptr = string;
784 size_t length;
785 char *endl;
786
787 if (!string) {
788 return 0;
789 }
790
791 length = strlen(string);
792 endl = (char *)string + length;
793
794 while (*ptr) {
795 if (*ptr == '%') {
796 unsigned int tmp;
797 /* Make sure there are at least 2 characters left to decode */
798 if (ptr + 2 >= endl) {
799 return 0;
800 }
801 /* Try to parse the next two characters as hex */
802 if (sscanf(ptr + 1, "%2x", &tmp) != 1) {
803 return 0;
804 }
805 /* All good, move past the '%' and the two hex digits */
806 ptr += 3;
807 } else if (!isalnum((unsigned char ) *ptr) && !strchr("-_.+", *ptr)) {
808 return 0;
809 } else {
810 ptr++;
811 }
812 }
813
814 return 1; /* all characters are valid */
815}
816
817char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
818{
819 const char *ptr = string;
820 char *out = outbuf;
821 char *allow = "\t\v !"; /* allow LWS (minus \r and \n) and "!" */
822
823 while (*ptr && out - outbuf < buflen - 1) {
824 if (!(strchr(allow, *ptr))
825 && !(*ptr >= '#' && *ptr <= '[') /* %x23 - %x5b */
826 && !(*ptr >= ']' && *ptr <= '~') /* %x5d - %x7e */
827 && !((unsigned char) *ptr > 0x7f)) { /* UTF8-nonascii */
828
829 if (out - outbuf >= buflen - 2) {
830 break;
831 }
832 out += sprintf(out, "\\%c", (unsigned char) *ptr);
833 } else {
834 *out = *ptr;
835 out++;
836 }
837 ptr++;
838 }
839
840 if (buflen) {
841 *out = '\0';
842 }
843
844 return outbuf;
845}
846
847char *ast_escape_semicolons(const char *string, char *outbuf, int buflen)
848{
849 const char *ptr = string;
850 char *out = outbuf;
851
852 if (string == NULL || outbuf == NULL) {
853 ast_assert(string != NULL && outbuf != NULL);
854 return NULL;
855 }
856
857 while (*ptr && out - outbuf < buflen - 1) {
858 if (*ptr == ';') {
859 if (out - outbuf >= buflen - 2) {
860 break;
861 }
862 strcpy(out, "\\;");
863 out += 2;
864 } else {
865 *out = *ptr;
866 out++;
867 }
868 ptr++;
869 }
870
871 if (buflen) {
872 *out = '\0';
873 }
874
875 return outbuf;
876}
877
878void ast_unescape_quoted(char *quote_str)
879{
880 int esc_pos;
881 int unesc_pos;
882 int quote_str_len = strlen(quote_str);
883
884 for (esc_pos = 0, unesc_pos = 0;
885 esc_pos < quote_str_len;
886 esc_pos++, unesc_pos++) {
887 if (quote_str[esc_pos] == '\\') {
888 /* at least one more char and current is \\ */
889 esc_pos++;
890 if (esc_pos >= quote_str_len) {
891 break;
892 }
893 }
894
895 quote_str[unesc_pos] = quote_str[esc_pos];
896 }
897 quote_str[unesc_pos] = '\0';
898}
899
900int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
901{
902 char *dst = outbuf;
903 char *end = outbuf + buflen - 1; /* save one for the null terminator */
904
905 /* Handle the case for the empty output buffer */
906 if (buflen == 0) {
907 return -1;
908 }
909
910 /* Escaping rules from http://www.w3.org/TR/REC-xml/#syntax */
911 /* This also prevents partial entities at the end of a string */
912 while (*string && dst < end) {
913 const char *entity = NULL;
914 int len = 0;
915
916 switch (*string) {
917 case '<':
918 entity = "&lt;";
919 len = 4;
920 break;
921 case '&':
922 entity = "&amp;";
923 len = 5;
924 break;
925 case '>':
926 /* necessary if ]]> is in the string; easier to escape them all */
927 entity = "&gt;";
928 len = 4;
929 break;
930 case '\'':
931 /* necessary in single-quoted strings; easier to escape them all */
932 entity = "&apos;";
933 len = 6;
934 break;
935 case '"':
936 /* necessary in double-quoted strings; easier to escape them all */
937 entity = "&quot;";
938 len = 6;
939 break;
940 default:
941 *dst++ = *string++;
942 break;
943 }
944
945 if (entity) {
946 ast_assert(len == strlen(entity));
947 if (end - dst < len) {
948 /* no room for the entity; stop */
949 break;
950 }
951 /* just checked for length; strcpy is fine */
952 strcpy(dst, entity);
953 dst += len;
954 ++string;
955 }
956 }
957 /* Write null terminator */
958 *dst = '\0';
959 /* If any chars are left in string, return failure */
960 return *string == '\0' ? 0 : -1;
961}
962
963/*! \brief ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
964const char *ast_inet_ntoa(struct in_addr ia)
965{
966 char *buf;
967
968 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
969 return "";
970
971 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
972}
973
974static int dev_urandom_fd = -1;
975
976#ifndef __linux__
977#undef pthread_create /* For ast_pthread_create function only */
978#endif /* !__linux__ */
979
980#ifdef DEBUG_THREADS
981
982#if !defined(LOW_MEMORY)
983/*! \brief A reasonable maximum number of locks a thread would be holding ... */
984#define AST_MAX_LOCKS 64
985
986/* Allow direct use of pthread_mutex_t and friends */
987#undef pthread_mutex_t
988#undef pthread_mutex_lock
989#undef pthread_mutex_unlock
990#undef pthread_mutex_init
991#undef pthread_mutex_destroy
992
993/*!
994 * \brief Keep track of which locks a thread holds
995 *
996 * There is an instance of this struct for every active thread
997 */
998struct thr_lock_info {
999 /*! The thread's ID */
1000 pthread_t thread_id;
1001 /*! The thread name which includes where the thread was started */
1002 const char *thread_name;
1003 /*! This is the actual container of info for what locks this thread holds */
1004 struct {
1005 const char *file;
1006 const char *func;
1007 const char *lock_name;
1008 void *lock_addr;
1009 int times_locked;
1010 int times_lock_attempted;
1011 struct timeval last_locked;
1012 struct timeval last_unlocked;
1013 int line_num;
1014 enum ast_lock_type type;
1015 /*! This thread is waiting on this lock */
1016 int pending:2;
1017 /*! A condition has suspended this lock */
1018 int suspended:1;
1019#ifdef HAVE_BKTR
1020 struct ast_bt *backtrace;
1021#endif
1022 } locks[AST_MAX_LOCKS];
1023 /*! This is the number of locks currently held by this thread.
1024 * The index (num_locks - 1) has the info on the last one in the
1025 * locks member */
1026 unsigned int num_locks;
1027 /*! The LWP id (which GDB prints) */
1028 int lwp;
1029 /*! Protects the contents of the locks member
1030 * Intentionally not ast_mutex_t */
1032 AST_LIST_ENTRY(thr_lock_info) entry;
1033};
1034
1035/*!
1036 * \brief Locked when accessing the lock_infos list
1037 */
1038AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
1039/*!
1040 * \brief A list of each thread's lock info
1041 */
1042static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
1043
1044/*!
1045 * \brief Destroy a thread's lock info
1046 *
1047 * This gets called automatically when the thread stops
1048 */
1049static void lock_info_destroy(void *data)
1050{
1051 struct thr_lock_info *lock_info = data;
1052 int i;
1053
1054 pthread_mutex_lock(&lock_infos_lock.mutex);
1055 AST_LIST_REMOVE(&lock_infos, lock_info, entry);
1056 pthread_mutex_unlock(&lock_infos_lock.mutex);
1057
1058
1059 for (i = 0; i < lock_info->num_locks; i++) {
1060 if (lock_info->locks[i].pending == -1) {
1061 /* This just means that the last lock this thread went for was by
1062 * using trylock, and it failed. This is fine. */
1063 break;
1064 }
1065
1067 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
1068 lock_info->thread_name,
1069 lock_info->locks[i].lock_name,
1070 lock_info->locks[i].lock_addr,
1071 lock_info->locks[i].func,
1072 lock_info->locks[i].file,
1073 lock_info->locks[i].line_num
1074 );
1075 }
1076
1078 if (lock_info->thread_name) {
1079 ast_free((void *) lock_info->thread_name);
1080 }
1082}
1083
1084/*!
1085 * \brief The thread storage key for per-thread lock info
1086 */
1087AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
1088#endif /* ! LOW_MEMORY */
1089
1090void ast_store_lock_info(enum ast_lock_type type, const char *filename,
1091 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
1092{
1093#if !defined(LOW_MEMORY)
1094 struct thr_lock_info *lock_info;
1095 int i;
1096
1097 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1098 return;
1099
1101
1102 for (i = 0; i < lock_info->num_locks; i++) {
1103 if (lock_info->locks[i].lock_addr == lock_addr) {
1104 lock_info->locks[i].times_locked++;
1105 lock_info->locks[i].times_lock_attempted++;
1106 lock_info->locks[i].last_locked = ast_tvnow();
1107#ifdef HAVE_BKTR
1108 lock_info->locks[i].backtrace = bt;
1109#endif
1111 return;
1112 }
1113 }
1114
1115 if (lock_info->num_locks == AST_MAX_LOCKS) {
1116 /* Can't use ast_log here, because it will cause infinite recursion */
1117 fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
1118 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
1120 return;
1121 }
1122
1123 if (i && lock_info->locks[i - 1].pending == -1) {
1124 /* The last lock on the list was one that this thread tried to lock but
1125 * failed at doing so. It has now moved on to something else, so remove
1126 * the old lock from the list. */
1127 i--;
1128 lock_info->num_locks--;
1129 memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
1130 }
1131
1132 lock_info->locks[i].file = filename;
1133 lock_info->locks[i].line_num = line_num;
1134 lock_info->locks[i].func = func;
1135 lock_info->locks[i].lock_name = lock_name;
1136 lock_info->locks[i].lock_addr = lock_addr;
1137 lock_info->locks[i].times_locked = 1;
1138 lock_info->locks[i].times_lock_attempted = 1;
1139 lock_info->locks[i].last_locked = ast_tvnow();
1140 lock_info->locks[i].type = type;
1141 lock_info->locks[i].pending = 1;
1142#ifdef HAVE_BKTR
1143 lock_info->locks[i].backtrace = bt;
1144#endif
1145 lock_info->num_locks++;
1146
1148#endif /* ! LOW_MEMORY */
1149}
1150
1151void ast_mark_lock_acquired(void *lock_addr)
1152{
1153#if !defined(LOW_MEMORY)
1154 struct thr_lock_info *lock_info;
1155
1156 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1157 return;
1158
1160 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
1161 lock_info->locks[lock_info->num_locks - 1].pending = 0;
1162 }
1164#endif /* ! LOW_MEMORY */
1165}
1166
1167void ast_mark_lock_failed(void *lock_addr)
1168{
1169#if !defined(LOW_MEMORY)
1170 struct thr_lock_info *lock_info;
1171
1172 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1173 return;
1174
1176 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
1177 lock_info->locks[lock_info->num_locks - 1].pending = -1;
1178 lock_info->locks[lock_info->num_locks - 1].times_locked--;
1179 lock_info->locks[lock_info->num_locks - 1].last_unlocked = ast_tvnow();
1180 }
1182#endif /* ! LOW_MEMORY */
1183}
1184
1185int 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)
1186{
1187#if !defined(LOW_MEMORY)
1188 struct thr_lock_info *lock_info;
1189 int i = 0;
1190
1191 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1192 return -1;
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 -1;
1205 }
1206
1207 ast_copy_string(filename, lock_info->locks[i].file, filename_size);
1208 *lineno = lock_info->locks[i].line_num;
1209 ast_copy_string(func, lock_info->locks[i].func, func_size);
1210 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
1211
1213
1214 return 0;
1215#else /* if defined(LOW_MEMORY) */
1216 return -1;
1217#endif
1218}
1219
1220void ast_suspend_lock_info(void *lock_addr)
1221{
1222#if !defined(LOW_MEMORY)
1223 struct thr_lock_info *lock_info;
1224 int i = 0;
1225
1226 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) {
1227 return;
1228 }
1229
1231
1232 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1233 if (lock_info->locks[i].lock_addr == lock_addr)
1234 break;
1235 }
1236
1237 if (i == -1) {
1238 /* Lock not found :( */
1240 return;
1241 }
1242
1243 lock_info->locks[i].suspended = 1;
1244
1246#endif /* ! LOW_MEMORY */
1247}
1248
1249void ast_restore_lock_info(void *lock_addr)
1250{
1251#if !defined(LOW_MEMORY)
1252 struct thr_lock_info *lock_info;
1253 int i = 0;
1254
1255 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1256 return;
1257
1259
1260 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1261 if (lock_info->locks[i].lock_addr == lock_addr)
1262 break;
1263 }
1264
1265 if (i == -1) {
1266 /* Lock not found :( */
1268 return;
1269 }
1270
1271 lock_info->locks[i].suspended = 0;
1272
1274#endif /* ! LOW_MEMORY */
1275}
1276
1277
1278void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
1279{
1280#if !defined(LOW_MEMORY)
1281 struct thr_lock_info *lock_info;
1282 int i = 0;
1283
1284 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1285 return;
1286
1288
1289 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1290 if (lock_info->locks[i].lock_addr == lock_addr)
1291 break;
1292 }
1293
1294 if (i == -1) {
1295 /* Lock not found :( */
1297 return;
1298 }
1299
1300 if (lock_info->locks[i].times_locked > 1) {
1301 lock_info->locks[i].times_locked--;
1302 lock_info->locks[i].last_unlocked = ast_tvnow();
1303#ifdef HAVE_BKTR
1304 lock_info->locks[i].backtrace = bt;
1305#endif
1307 return;
1308 }
1309
1310 if (i < lock_info->num_locks - 1) {
1311 /* Not the last one ... *should* be rare! */
1312 memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
1313 (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
1314 }
1315
1316 lock_info->num_locks--;
1317
1319#endif /* ! LOW_MEMORY */
1320}
1321
1322#if !defined(LOW_MEMORY)
1323static const char *locktype2str(enum ast_lock_type type)
1324{
1325 switch (type) {
1326 case AST_MUTEX:
1327 return "MUTEX";
1328 case AST_RDLOCK:
1329 return "RDLOCK";
1330 case AST_WRLOCK:
1331 return "WRLOCK";
1332 }
1333
1334 return "UNKNOWN";
1335}
1336
1337#ifdef HAVE_BKTR
1338static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
1339{
1340 struct ast_vector_string *symbols;
1341 int num_frames;
1342
1343 if (!bt) {
1344 ast_str_append(str, 0, "\tNo backtrace to print\n");
1345 return;
1346 }
1347
1348 /* store frame count locally to avoid the memory corruption that
1349 * sometimes happens on virtualized CentOS 6.x systems */
1350 num_frames = bt->num_frames;
1351 if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
1352 int frame_iterator;
1353
1354 for (frame_iterator = 1; frame_iterator < AST_VECTOR_SIZE(symbols); ++frame_iterator) {
1355 ast_str_append(str, 0, "\t%s\n", AST_VECTOR_GET(symbols, frame_iterator));
1356 }
1357
1358 ast_bt_free_symbols(symbols);
1359 } else {
1360 ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
1361 }
1362}
1363#endif
1364
1365static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
1366{
1367 int j;
1369 struct ast_lock_track *lt;
1370 struct timeval held_for;
1371 struct timeval now = ast_tvnow();
1372 char lock_time[32], unlock_time[32], held_time[32];
1373
1374 held_for = ast_tvsub(now, lock_info->locks[i].last_locked);
1375 /* format time duration strings */
1376 ast_format_duration_hh_mm_ss(lock_info->locks[i].last_locked.tv_sec,
1377 lock_time, sizeof(lock_time));
1378 ast_format_duration_hh_mm_ss(lock_info->locks[i].last_unlocked.tv_sec,
1379 unlock_time, sizeof(unlock_time));
1380 ast_format_duration_hh_mm_ss(held_for.tv_sec, held_time, sizeof(held_time));
1381
1382 ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p\n"
1383 "=== %s.%06ld, %s.%06ld, %s.%06ld (%d, %d%s)\n",
1384 lock_info->locks[i].pending > 0 ? "Waiting for " :
1385 lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
1386 lock_info->locks[i].file,
1387 locktype2str(lock_info->locks[i].type),
1388 lock_info->locks[i].line_num,
1389 lock_info->locks[i].func,
1390 lock_info->locks[i].lock_name,
1391 lock_info->locks[i].lock_addr,
1392 lock_time,
1393 lock_info->locks[i].last_locked.tv_usec,
1394 unlock_time,
1395 lock_info->locks[i].last_unlocked.tv_usec,
1396 held_time,
1397 held_for.tv_usec,
1398 lock_info->locks[i].times_locked,
1399 lock_info->locks[i].times_lock_attempted,
1400 lock_info->locks[i].suspended ? " - suspended" : "");
1401#ifdef HAVE_BKTR
1402 append_backtrace_information(str, lock_info->locks[i].backtrace);
1403#endif
1404
1405 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
1406 return;
1407
1408 /* We only have further details for mutexes right now */
1409 if (lock_info->locks[i].type != AST_MUTEX)
1410 return;
1411
1412 lock = lock_info->locks[i].lock_addr;
1413 lt = lock->track;
1414 ast_reentrancy_lock(lt);
1415 for (j = 0; *str && j < lt->reentrancy; j++) {
1416 ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
1417 lt->file[j], lt->lineno[j], lt->func[j]);
1418 }
1419 ast_reentrancy_unlock(lt);
1420}
1421#endif /* ! LOW_MEMORY */
1422
1423/*! This function can help you find highly temporal locks; locks that happen for a
1424 short time, but at unexpected times, usually at times that create a deadlock,
1425 Why is this thing locked right then? Who is locking it? Who am I fighting
1426 with for this lock?
1427
1428 To answer such questions, just call this routine before you would normally try
1429 to acquire a lock. It doesn't do anything if the lock is not acquired. If the
1430 lock is taken, it will publish a line or two to the console via ast_log().
1431
1432 Sometimes, the lock message is pretty uninformative. For instance, you might
1433 find that the lock is being acquired deep within the astobj2 code; this tells
1434 you little about higher level routines that call the astobj2 routines.
1435 But, using gdb, you can set a break at the ast_log below, and for that
1436 breakpoint, you can set the commands:
1437 where
1438 cont
1439 which will give a stack trace and continue. -- that aught to do the job!
1440
1441*/
1442void ast_log_show_lock(void *this_lock_addr)
1443{
1444#if !defined(LOW_MEMORY)
1445 struct thr_lock_info *lock_info;
1446 struct ast_str *str;
1447
1448 if (!(str = ast_str_create(4096))) {
1449 ast_log(LOG_NOTICE,"Could not create str\n");
1450 return;
1451 }
1452
1453
1454 pthread_mutex_lock(&lock_infos_lock.mutex);
1455 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1456 int i;
1458 for (i = 0; str && i < lock_info->num_locks; i++) {
1459 /* ONLY show info about this particular lock, if
1460 it's acquired... */
1461 if (lock_info->locks[i].lock_addr == this_lock_addr) {
1462 append_lock_information(&str, lock_info, i);
1464 break;
1465 }
1466 }
1468 }
1469 pthread_mutex_unlock(&lock_infos_lock.mutex);
1470 ast_free(str);
1471#endif /* ! LOW_MEMORY */
1472}
1473
1474
1475struct ast_str *ast_dump_locks(void)
1476{
1477#if !defined(LOW_MEMORY)
1478 struct thr_lock_info *lock_info;
1479 struct ast_str *str;
1480 char print_time[32];
1481 struct timeval now = ast_tvnow();
1482
1483 if (!(str = ast_str_create(4096))) {
1484 return NULL;
1485 }
1486
1487 ast_format_duration_hh_mm_ss(now.tv_sec, print_time, sizeof(print_time));
1488
1489 ast_str_append(&str, 0, "\n"
1490 "=======================================================================\n"
1491 "=== %s\n"
1492 "=== Currently Held Locks at Time: %s.%06ld =================\n"
1493 "=======================================================================\n"
1494 "===\n"
1495 "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr>\n"
1496 "=== <locked at>, <failed at>, <held for> (attempts, times locked)\n"
1497 "===\n", ast_get_version(), print_time, now.tv_usec);
1498 if (!str) {
1499 return NULL;
1500 }
1501
1502 pthread_mutex_lock(&lock_infos_lock.mutex);
1503 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1504 int i;
1505 int header_printed = 0;
1507 for (i = 0; str && i < lock_info->num_locks; i++) {
1508 /* Don't show suspended locks */
1509 if (lock_info->locks[i].suspended) {
1510 continue;
1511 }
1512
1513 if (!header_printed) {
1514 if (lock_info->lwp != -1) {
1515 ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
1516 (long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
1517 } else {
1518 ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
1519 (long unsigned) lock_info->thread_id, lock_info->thread_name);
1520 }
1521 header_printed = 1;
1522 }
1523
1524 append_lock_information(&str, lock_info, i);
1525 }
1527 if (!str) {
1528 break;
1529 }
1530 if (header_printed) {
1531 ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
1532 "===\n");
1533 }
1534 if (!str) {
1535 break;
1536 }
1537 }
1538 pthread_mutex_unlock(&lock_infos_lock.mutex);
1539
1540 if (!str) {
1541 return NULL;
1542 }
1543
1544 ast_str_append(&str, 0, "=======================================================================\n"
1545 "\n");
1546
1547 return str;
1548#else /* if defined(LOW_MEMORY) */
1549 return NULL;
1550#endif
1551}
1552
1553#if !defined(LOW_MEMORY)
1554static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1555{
1556 struct ast_str *str;
1557
1558 switch (cmd) {
1559 case CLI_INIT:
1560 e->command = "core show locks";
1561 e->usage =
1562 "Usage: core show locks\n"
1563 " This command is for lock debugging. It prints out which locks\n"
1564 "are owned by each active thread.\n";
1566 return NULL;
1567
1568 case CLI_GENERATE:
1569 return NULL;
1570 }
1571
1572 str = ast_dump_locks();
1573 if (!str) {
1574 return CLI_FAILURE;
1575 }
1576
1577 ast_cli(a->fd, "%s", ast_str_buffer(str));
1578
1579 ast_free(str);
1580
1581 return CLI_SUCCESS;
1582}
1583
1584static struct ast_cli_entry utils_cli[] = {
1585 AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
1586};
1587#endif /* ! LOW_MEMORY */
1588#endif /* DEBUG_THREADS */
1589
1590#if !defined(LOW_MEMORY)
1591/*
1592 * support for 'show threads'. The start routine is wrapped by
1593 * dummy_start(), so that ast_register_thread() and
1594 * ast_unregister_thread() know the thread identifier.
1595 */
1596struct thr_arg {
1597 void *(*start_routine)(void *);
1598 void *data;
1599 char *name;
1600};
1601
1602/*
1603 * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
1604 * are odd macros which start and end a block, so they _must_ be
1605 * used in pairs (the latter with a '1' argument to call the
1606 * handler on exit.
1607 * On BSD we don't need this, but we keep it for compatibility.
1608 */
1609static void *dummy_start(void *data)
1610{
1611 void *ret;
1612 struct thr_arg a = *((struct thr_arg *) data); /* make a local copy */
1613#ifdef DEBUG_THREADS
1614 struct thr_lock_info *lock_info;
1615 pthread_mutexattr_t mutex_attr;
1616
1617 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1618 return NULL;
1619
1620 lock_info->thread_id = pthread_self();
1621 lock_info->lwp = ast_get_tid();
1622 lock_info->thread_name = ast_strdup(a.name);
1623
1624 pthread_mutexattr_init(&mutex_attr);
1625 pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
1626 pthread_mutex_init(&lock_info->lock, &mutex_attr);
1627 pthread_mutexattr_destroy(&mutex_attr);
1628
1629 pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1630 AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
1631 pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1632#endif /* DEBUG_THREADS */
1633
1634 /* note that even though data->name is a pointer to allocated memory,
1635 we are not freeing it here because ast_register_thread is going to
1636 keep a copy of the pointer and then ast_unregister_thread will
1637 free the memory
1638 */
1639 ast_free(data);
1641 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
1642
1643 ret = a.start_routine(a.data);
1644
1645 pthread_cleanup_pop(1);
1646
1647 return ret;
1648}
1649
1650#endif /* !LOW_MEMORY */
1651
1653{
1654#if !defined(LOW_MEMORY)
1655 return AST_STACKSIZE;
1656#else
1657 return AST_STACKSIZE_LOW;
1658#endif
1659}
1660
1661int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1662 void *data, size_t stacksize, const char *file, const char *caller,
1663 int line, const char *start_fn)
1664{
1665#if !defined(LOW_MEMORY)
1666 struct thr_arg *a;
1667#endif
1668
1669 if (!attr) {
1670 attr = ast_alloca(sizeof(*attr));
1671 pthread_attr_init(attr);
1672 }
1673
1674#if defined(__linux__) || defined(__FreeBSD__)
1675 /* On Linux and FreeBSD , pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
1676 which is kind of useless. Change this here to
1677 PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
1678 priority will propagate down to new threads by default.
1679 This does mean that callers cannot set a different priority using
1680 PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
1681 the priority afterwards with pthread_setschedparam(). */
1682 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1683 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
1684#endif
1685
1686 if (!stacksize)
1687 stacksize = AST_STACKSIZE;
1688
1689 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
1690 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
1691
1692#if !defined(LOW_MEMORY)
1693 if ((a = ast_malloc(sizeof(*a)))) {
1694 a->start_routine = start_routine;
1695 a->data = data;
1697 if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
1698 start_fn, line, file, caller) < 0) {
1699 a->name = NULL;
1700 }
1701 data = a;
1702 }
1703#endif /* !LOW_MEMORY */
1704
1705 return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
1706}
1707
1708
1709int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1710 void *data, size_t stacksize, const char *file, const char *caller,
1711 int line, const char *start_fn)
1712{
1713 unsigned char attr_destroy = 0;
1714 int res;
1715
1716 if (!attr) {
1717 attr = ast_alloca(sizeof(*attr));
1718 pthread_attr_init(attr);
1719 attr_destroy = 1;
1720 }
1721
1722 if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1723 ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
1724
1726 stacksize, file, caller, line, start_fn);
1727
1728 if (attr_destroy)
1729 pthread_attr_destroy(attr);
1730
1731 return res;
1732}
1733
1734int ast_wait_for_input(int fd, int ms)
1735{
1736 struct pollfd pfd[1];
1737
1738 memset(pfd, 0, sizeof(pfd));
1739 pfd[0].fd = fd;
1740 pfd[0].events = POLLIN | POLLPRI;
1741 return ast_poll(pfd, 1, ms);
1742}
1743
1744int ast_wait_for_output(int fd, int ms)
1745{
1746 struct pollfd pfd[1];
1747
1748 memset(pfd, 0, sizeof(pfd));
1749 pfd[0].fd = fd;
1750 pfd[0].events = POLLOUT;
1751 return ast_poll(pfd, 1, ms);
1752}
1753
1754static int wait_for_output(int fd, int timeoutms)
1755{
1756 struct pollfd pfd = {
1757 .fd = fd,
1758 .events = POLLOUT,
1759 };
1760 int res;
1761 struct timeval start = ast_tvnow();
1762 int elapsed = 0;
1763
1764 /* poll() until the fd is writable without blocking */
1765 while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1766 if (res == 0) {
1767 /* timed out. */
1768#ifndef STANDALONE
1769 ast_debug(1, "Timed out trying to write\n");
1770#endif
1771 return -1;
1772 } else if (res == -1) {
1773 /* poll() returned an error, check to see if it was fatal */
1774
1775 if (errno == EINTR || errno == EAGAIN) {
1776 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1777 if (elapsed >= timeoutms) {
1778 return -1;
1779 }
1780 /* This was an acceptable error, go back into poll() */
1781 continue;
1782 }
1783
1784 /* Fatal error, bail. */
1785 ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
1786
1787 return -1;
1788 }
1789 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1790 if (elapsed >= timeoutms) {
1791 return -1;
1792 }
1793 }
1794
1795 return 0;
1796}
1797
1798/*!
1799 * Try to write string, but wait no more than ms milliseconds before timing out.
1800 *
1801 * \note The code assumes that the file descriptor has NONBLOCK set,
1802 * so there is only one system call made to do a write, unless we actually
1803 * have a need to wait. This way, we get better performance.
1804 * If the descriptor is blocking, all assumptions on the guaranteed
1805 * detail do not apply anymore.
1806 */
1807int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
1808{
1809 struct timeval start = ast_tvnow();
1810 int res = 0;
1811 int elapsed = 0;
1812
1813 while (len) {
1814 if (wait_for_output(fd, timeoutms - elapsed)) {
1815 return -1;
1816 }
1817
1818 res = write(fd, s, len);
1819
1820 if (res < 0 && errno != EAGAIN && errno != EINTR) {
1821 /* fatal error from write() */
1822 if (errno == EPIPE) {
1823#ifndef STANDALONE
1824 ast_debug(1, "write() failed due to reading end being closed: %s\n", strerror(errno));
1825#endif
1826 } else {
1827 ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
1828 }
1829 return -1;
1830 }
1831
1832 if (res < 0) {
1833 /* It was an acceptable error */
1834 res = 0;
1835 }
1836
1837 /* Update how much data we have left to write */
1838 len -= res;
1839 s += res;
1840 res = 0;
1841
1842 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1843 if (elapsed >= timeoutms) {
1844 /* We've taken too long to write
1845 * This is only an error condition if we haven't finished writing. */
1846 res = len ? -1 : 0;
1847 break;
1848 }
1849 }
1850
1851 return res;
1852}
1853
1854char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
1855{
1856 char *e;
1857 char *q;
1858
1859 s = ast_strip(s);
1860 if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
1861 e = s + strlen(s) - 1;
1862 if (*e == *(end_quotes + (q - beg_quotes))) {
1863 s++;
1864 *e = '\0';
1865 }
1866 }
1867
1868 return s;
1869}
1870
1871char *ast_strsep(char **iss, const char sep, uint32_t flags)
1872{
1873 char *st = *iss;
1874 char *is;
1875 int inquote = 0;
1876 int found = 0;
1877 char stack[8];
1878
1879 if (ast_strlen_zero(st)) {
1880 *iss = NULL;
1881 return st;
1882 }
1883
1884 memset(stack, 0, sizeof(stack));
1885
1886 for(is = st; *is; is++) {
1887 if (*is == '\\') {
1888 if (*++is != '\0') {
1889 is++;
1890 } else {
1891 break;
1892 }
1893 }
1894
1895 if (*is == '\'' || *is == '"') {
1896 if (*is == stack[inquote]) {
1897 stack[inquote--] = '\0';
1898 } else {
1899 if (++inquote >= sizeof(stack)) {
1900 return NULL;
1901 }
1902 stack[inquote] = *is;
1903 }
1904 }
1905
1906 if (*is == sep && !inquote) {
1907 *is = '\0';
1908 found = 1;
1909 *iss = is + 1;
1910 break;
1911 }
1912 }
1913 if (!found) {
1914 *iss = NULL;
1915 }
1916
1917 if (flags & AST_STRSEP_STRIP) {
1918 st = ast_strip_quoted(st, "'\"", "'\"");
1919 }
1920
1921 if (flags & AST_STRSEP_TRIM) {
1922 char *trimmed = ast_strip(st);
1923 if (!ast_strlen_zero(trimmed)) {
1924 st = trimmed;
1925 }
1926 }
1927
1928 if (flags & AST_STRSEP_UNESCAPE) {
1930 }
1931
1932 return st;
1933}
1934
1935char *ast_strsep_quoted(char **iss, const char sep, const char quote, uint32_t flags)
1936{
1937 char *st = *iss;
1938 char *is;
1939 int inquote = 0;
1940 int found = 0;
1941 char stack[8];
1942 const char qstr[] = { quote };
1943
1944 if (ast_strlen_zero(st)) {
1945 *iss = NULL;
1946 return st;
1947 }
1948
1949 memset(stack, 0, sizeof(stack));
1950
1951 for(is = st; *is; is++) {
1952 if (*is == '\\') {
1953 if (*++is != '\0') {
1954 is++;
1955 } else {
1956 break;
1957 }
1958 }
1959
1960 if (*is == quote) {
1961 if (*is == stack[inquote]) {
1962 stack[inquote--] = '\0';
1963 } else {
1964 if (++inquote >= sizeof(stack)) {
1965 return NULL;
1966 }
1967 stack[inquote] = *is;
1968 }
1969 }
1970
1971 if (*is == sep && !inquote) {
1972 *is = '\0';
1973 found = 1;
1974 *iss = is + 1;
1975 break;
1976 }
1977 }
1978 if (!found) {
1979 *iss = NULL;
1980 }
1981
1982 if (flags & AST_STRSEP_STRIP) {
1983 st = ast_strip_quoted(st, qstr, qstr);
1984 }
1985
1986 if (flags & AST_STRSEP_TRIM) {
1987 char *trimmed = ast_strip(st);
1988 if (!ast_strlen_zero(trimmed)) {
1989 st = trimmed;
1990 }
1991 }
1992
1993 if (flags & AST_STRSEP_UNESCAPE) {
1995 }
1996
1997 return st;
1998}
1999
2001{
2002 char *e;
2003 char *work = s;
2004
2005 while ((e = strchr(work, ';'))) {
2006 if ((e > work) && (*(e-1) == '\\')) {
2007 memmove(e - 1, e, strlen(e) + 1);
2008 work = e;
2009 } else {
2010 work = e + 1;
2011 }
2012 }
2013
2014 return s;
2015}
2016
2017/* !\brief unescape some C sequences in place, return pointer to the original string.
2018 */
2019char *ast_unescape_c(char *src)
2020{
2021 char c, *ret, *dst;
2022
2023 if (src == NULL)
2024 return NULL;
2025 for (ret = dst = src; (c = *src++); *dst++ = c ) {
2026 if (c != '\\')
2027 continue; /* copy char at the end of the loop */
2028 switch ((c = *src++)) {
2029 case '\0': /* special, trailing '\' */
2030 c = '\\';
2031 break;
2032 case 'b': /* backspace */
2033 c = '\b';
2034 break;
2035 case 'f': /* form feed */
2036 c = '\f';
2037 break;
2038 case 'n':
2039 c = '\n';
2040 break;
2041 case 'r':
2042 c = '\r';
2043 break;
2044 case 't':
2045 c = '\t';
2046 break;
2047 }
2048 /* default, use the char literally */
2049 }
2050 *dst = '\0';
2051 return ret;
2052}
2053
2054/*
2055 * Standard escape sequences - Note, '\0' is not included as a valid character
2056 * to escape, but instead is used here as a NULL terminator for the string.
2057 */
2059 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\'', '\"', '\?', '\0'
2060};
2061
2062/*
2063 * Standard escape sequences output map (has to maintain matching order with
2064 * escape_sequences). '\0' is included here as a NULL terminator for the string.
2065 */
2066static char escape_sequences_map[] = {
2067 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"', '?', '\0'
2068};
2069
2070char *ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
2071{
2072 char *p;
2073 char *c;
2074
2075 if (!dest || !size) {
2076 return dest;
2077 }
2078 if (ast_strlen_zero(s)) {
2079 *dest = '\0';
2080 return dest;
2081 }
2082
2083 if (ast_strlen_zero(to_escape)) {
2084 ast_copy_string(dest, s, size);
2085 return dest;
2086 }
2087
2088 for (p = dest; *s && --size; ++s, ++p) {
2089 /* If in the list of characters to escape then escape it */
2090 if (strchr(to_escape, *s)) {
2091 if (!--size) {
2092 /* Not enough room left for the escape sequence. */
2093 break;
2094 }
2095
2096 /*
2097 * See if the character to escape is part of the standard escape
2098 * sequences. If so we'll have to use its mapped counterpart
2099 * otherwise just use the current character.
2100 */
2101 c = strchr(escape_sequences, *s);
2102 *p++ = '\\';
2104 } else {
2105 *p = *s;
2106 }
2107 }
2108 *p = '\0';
2109
2110 return dest;
2111}
2112
2113char *ast_escape_c(char *dest, const char *s, size_t size)
2114{
2115 /*
2116 * Note - This is an optimized version of ast_escape. When looking only
2117 * for escape_sequences a couple of checks used in the generic case can
2118 * be left out thus making it slightly more efficient.
2119 */
2120 char *p;
2121 char *c;
2122
2123 if (!dest || !size) {
2124 return dest;
2125 }
2126 if (ast_strlen_zero(s)) {
2127 *dest = '\0';
2128 return dest;
2129 }
2130
2131 for (p = dest; *s && --size; ++s, ++p) {
2132 /*
2133 * See if the character to escape is part of the standard escape
2134 * sequences. If so use its mapped counterpart.
2135 */
2136 c = strchr(escape_sequences, *s);
2137 if (c) {
2138 if (!--size) {
2139 /* Not enough room left for the escape sequence. */
2140 break;
2141 }
2142
2143 *p++ = '\\';
2145 } else {
2146 *p = *s;
2147 }
2148 }
2149 *p = '\0';
2150
2151 return dest;
2152}
2153
2154static char *escape_alloc(const char *s, size_t *size)
2155{
2156 if (!s) {
2157 return NULL;
2158 }
2159
2160 /*
2161 * The result string needs to be twice the size of the given
2162 * string just in case every character in it needs to be escaped.
2163 */
2164 *size = strlen(s) * 2 + 1;
2165 return ast_malloc(*size);
2166}
2167
2168char *ast_escape_alloc(const char *s, const char *to_escape)
2169{
2170 size_t size = 0;
2171 char *dest = escape_alloc(s, &size);
2172
2173 return ast_escape(dest, s, size, to_escape);
2174}
2175
2176char *ast_escape_c_alloc(const char *s)
2177{
2178 size_t size = 0;
2179 char *dest = escape_alloc(s, &size);
2180
2181 return ast_escape_c(dest, s, size);
2182}
2183
2184int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
2185{
2186 int result;
2187
2188 if (!buffer || !*buffer || !space || !*space)
2189 return -1;
2190
2191 result = vsnprintf(*buffer, *space, fmt, ap);
2192
2193 if (result < 0)
2194 return -1;
2195 else if (result > *space)
2196 result = *space;
2197
2198 *buffer += result;
2199 *space -= result;
2200 return 0;
2201}
2202
2203int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
2204{
2205 va_list ap;
2206 int result;
2207
2208 va_start(ap, fmt);
2209 result = ast_build_string_va(buffer, space, fmt, ap);
2210 va_end(ap);
2211
2212 return result;
2213}
2214
2215int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
2216{
2217 int regex_len = strlen(regex_string);
2218 int ret = 3;
2219
2220 /* Chop off the leading / if there is one */
2221 if ((regex_len >= 1) && (regex_string[0] == '/')) {
2222 ast_str_set(regex_pattern, 0, "%s", regex_string + 1);
2223 ret -= 2;
2224 }
2225
2226 /* Chop off the ending / if there is one */
2227 if ((regex_len > 1) && (regex_string[regex_len - 1] == '/')) {
2228 ast_str_truncate(*regex_pattern, -1);
2229 ret -= 1;
2230 }
2231
2232 return ret;
2233}
2234
2235int ast_true(const char *s)
2236{
2237 if (ast_strlen_zero(s))
2238 return 0;
2239
2240 /* Determine if this is a true value */
2241 if (!strcasecmp(s, "yes") ||
2242 !strcasecmp(s, "true") ||
2243 !strcasecmp(s, "y") ||
2244 !strcasecmp(s, "t") ||
2245 !strcasecmp(s, "1") ||
2246 !strcasecmp(s, "on"))
2247 return -1;
2248
2249 return 0;
2250}
2251
2252int ast_false(const char *s)
2253{
2254 if (ast_strlen_zero(s))
2255 return 0;
2256
2257 /* Determine if this is a false value */
2258 if (!strcasecmp(s, "no") ||
2259 !strcasecmp(s, "false") ||
2260 !strcasecmp(s, "n") ||
2261 !strcasecmp(s, "f") ||
2262 !strcasecmp(s, "0") ||
2263 !strcasecmp(s, "off"))
2264 return -1;
2265
2266 return 0;
2267}
2268
2269#define ONE_MILLION 1000000
2270/*
2271 * put timeval in a valid range. usec is 0..999999
2272 * negative values are not allowed and truncated.
2273 */
2274static struct timeval tvfix(struct timeval a)
2275{
2276 if (a.tv_usec >= ONE_MILLION) {
2277 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
2278 (long)a.tv_sec, (long int) a.tv_usec);
2279 a.tv_sec += a.tv_usec / ONE_MILLION;
2280 a.tv_usec %= ONE_MILLION;
2281 } else if (a.tv_usec < 0) {
2282 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
2283 (long)a.tv_sec, (long int) a.tv_usec);
2284 a.tv_usec = 0;
2285 }
2286 return a;
2287}
2288
2289struct timeval ast_tvadd(struct timeval a, struct timeval b)
2290{
2291 /* consistency checks to guarantee usec in 0..999999 */
2292 a = tvfix(a);
2293 b = tvfix(b);
2294 a.tv_sec += b.tv_sec;
2295 a.tv_usec += b.tv_usec;
2296 if (a.tv_usec >= ONE_MILLION) {
2297 a.tv_sec++;
2298 a.tv_usec -= ONE_MILLION;
2299 }
2300 return a;
2301}
2302
2303struct timeval ast_tvsub(struct timeval a, struct timeval b)
2304{
2305 /* consistency checks to guarantee usec in 0..999999 */
2306 a = tvfix(a);
2307 b = tvfix(b);
2308 a.tv_sec -= b.tv_sec;
2309 a.tv_usec -= b.tv_usec;
2310 if (a.tv_usec < 0) {
2311 a.tv_sec-- ;
2312 a.tv_usec += ONE_MILLION;
2313 }
2314 return a;
2315}
2316
2317int ast_remaining_ms(struct timeval start, int max_ms)
2318{
2319 int ms;
2320
2321 if (max_ms < 0) {
2322 ms = max_ms;
2323 } else {
2324 ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
2325 if (ms < 0) {
2326 ms = 0;
2327 }
2328 }
2329
2330 return ms;
2331}
2332
2333void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
2334{
2335 int durh, durm, durs;
2336 durh = duration / 3600;
2337 durm = (duration % 3600) / 60;
2338 durs = duration % 60;
2339 snprintf(buf, length, "%02d:%02d:%02d", durh, durm, durs);
2340}
2341
2342#undef ONE_MILLION
2343
2344#ifndef linux
2346#endif
2347
2348long int ast_random(void)
2349{
2350 long int res;
2351
2352 if (dev_urandom_fd >= 0) {
2353 int read_res = read(dev_urandom_fd, &res, sizeof(res));
2354 if (read_res > 0) {
2355 long int rm = RAND_MAX;
2356 res = res < 0 ? ~res : res;
2357 rm++;
2358 return res % rm;
2359 }
2360 }
2361
2362 /* XXX - Thread safety really depends on the libc, not the OS.
2363 *
2364 * But... popular Linux libc's (uClibc, glibc, eglibc), all have a
2365 * somewhat thread safe random(3) (results are random, but not
2366 * reproducible). The libc's for other systems (BSD, et al.), not so
2367 * much.
2368 */
2369#ifdef linux
2370 res = random();
2371#else
2373 res = random();
2375#endif
2376 return res;
2377}
2378
2380{
2381 for (; *s; s++) {
2382 if (*s == '^') {
2383 *s = ',';
2384 }
2385 }
2386}
2387
2388char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2389{
2390 char *dataPut = start;
2391 int inEscape = 0;
2392 int inQuotes = 0;
2393
2394 for (; *start; start++) {
2395 if (inEscape) {
2396 *dataPut++ = *start; /* Always goes verbatim */
2397 inEscape = 0;
2398 } else {
2399 if (*start == '\\') {
2400 inEscape = 1; /* Do not copy \ into the data */
2401 } else if (*start == '\'') {
2402 inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
2403 } else {
2404 /* Replace , with |, unless in quotes */
2405 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2406 }
2407 }
2408 }
2409 if (start != dataPut)
2410 *dataPut = 0;
2411 return dataPut;
2412}
2413
2414void ast_join_delim(char *s, size_t len, const char * const w[], unsigned int size, char delim)
2415{
2416 int x, ofs = 0;
2417 const char *src;
2418
2419 /* Join words into a string */
2420 if (!s)
2421 return;
2422 for (x = 0; ofs < len && x < size && w[x] ; x++) {
2423 if (x > 0)
2424 s[ofs++] = delim;
2425 for (src = w[x]; *src && ofs < len; src++)
2426 s[ofs++] = *src;
2427 }
2428 if (ofs == len)
2429 ofs--;
2430 s[ofs] = '\0';
2431}
2432
2433char *ast_to_camel_case_delim(const char *s, const char *delim)
2434{
2435 char *res = ast_strdup(s);
2436 char *front, *back, *buf = res;
2437 int size;
2438
2439 front = strtok_r(buf, delim, &back);
2440
2441 while (front) {
2442 size = strlen(front);
2443 *front = toupper(*front);
2444 ast_copy_string(buf, front, size + 1);
2445 buf += size;
2446 front = strtok_r(NULL, delim, &back);
2447 }
2448
2449 return res;
2450}
2451
2452/*! \brief
2453 * get values from config variables.
2454 */
2455int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
2456{
2457 long double dtv = 0.0;
2458 int scanned;
2459
2460 if (dst == NULL)
2461 return -1;
2462
2463 *dst = _default;
2464
2465 if (ast_strlen_zero(src))
2466 return -1;
2467
2468 /* only integer at the moment, but one day we could accept more formats */
2469 if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
2470 dst->tv_sec = dtv;
2471 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2472 if (consumed)
2473 *consumed = scanned;
2474 return 0;
2475 } else
2476 return -1;
2477}
2478
2479/*! \brief
2480 * get values from config variables.
2481 */
2482int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
2483{
2484 long t;
2485 int scanned;
2486
2487 if (dst == NULL)
2488 return -1;
2489
2490 *dst = _default;
2491
2492 if (ast_strlen_zero(src))
2493 return -1;
2494
2495 /* only integer at the moment, but one day we could accept more formats */
2496 if (sscanf(src, "%30ld%n", &t, &scanned) == 1) {
2497 *dst = t;
2498 if (consumed)
2499 *consumed = scanned;
2500 return 0;
2501 } else
2502 return -1;
2503}
2504
2506{
2507#if defined(HAVE_IP_MTU_DISCOVER)
2508 int val = IP_PMTUDISC_DONT;
2509
2510 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
2511 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
2512#endif /* HAVE_IP_MTU_DISCOVER */
2513}
2514
2515int ast_mkdir(const char *path, int mode)
2516{
2517 char *ptr;
2518 int len = strlen(path), count = 0, x, piececount = 0;
2519 char *tmp = ast_strdupa(path);
2520 char **pieces;
2521 char *fullpath = ast_alloca(len + 1);
2522 int res = 0;
2523
2524 for (ptr = tmp; *ptr; ptr++) {
2525 if (*ptr == '/')
2526 count++;
2527 }
2528
2529 /* Count the components to the directory path */
2530 pieces = ast_alloca(count * sizeof(*pieces));
2531 for (ptr = tmp; *ptr; ptr++) {
2532 if (*ptr == '/') {
2533 *ptr = '\0';
2534 pieces[piececount++] = ptr + 1;
2535 }
2536 }
2537
2538 *fullpath = '\0';
2539 for (x = 0; x < piececount; x++) {
2540 /* This looks funky, but the buffer is always ideally-sized, so it's fine. */
2541 strcat(fullpath, "/");
2542 strcat(fullpath, pieces[x]);
2543 res = mkdir(fullpath, mode);
2544 if (res && errno != EEXIST)
2545 return errno;
2546 }
2547 return 0;
2548}
2549
2550static int safe_mkdir(const char *base_path, char *path, int mode)
2551{
2552 RAII_VAR(char *, absolute_path, NULL, ast_std_free);
2553
2554 absolute_path = realpath(path, NULL);
2555
2556 if (absolute_path) {
2557 /* Path exists, but is it in the right place? */
2558 if (!ast_begins_with(absolute_path, base_path)) {
2559 return EPERM;
2560 }
2561
2562 /* It is in the right place! */
2563 return 0;
2564 } else {
2565 /* Path doesn't exist. */
2566
2567 /* The slash terminating the subpath we're checking */
2568 char *path_term = strchr(path, '/');
2569 /* True indicates the parent path is within base_path */
2570 int parent_is_safe = 0;
2571 int res;
2572
2573 while (path_term) {
2574 RAII_VAR(char *, absolute_subpath, NULL, ast_std_free);
2575
2576 /* Truncate the path one past the slash */
2577 char c = *(path_term + 1);
2578 *(path_term + 1) = '\0';
2579 absolute_subpath = realpath(path, NULL);
2580
2581 if (absolute_subpath) {
2582 /* Subpath exists, but is it safe? */
2583 parent_is_safe = ast_begins_with(
2584 absolute_subpath, base_path);
2585 } else if (parent_is_safe) {
2586 /* Subpath does not exist, but parent is safe
2587 * Create it */
2588 res = mkdir(path, mode);
2589 if (res != 0) {
2590 ast_assert(errno != EEXIST);
2591 return errno;
2592 }
2593 } else {
2594 /* Subpath did not exist, parent was not safe
2595 * Fail! */
2596 errno = EPERM;
2597 return errno;
2598 }
2599 /* Restore the path */
2600 *(path_term + 1) = c;
2601 /* Move on to the next slash */
2602 path_term = strchr(path_term + 1, '/');
2603 }
2604
2605 /* Now to build the final path, but only if it's safe */
2606 if (!parent_is_safe) {
2607 errno = EPERM;
2608 return errno;
2609 }
2610
2611 res = mkdir(path, mode);
2612 if (res != 0 && errno != EEXIST) {
2613 return errno;
2614 }
2615
2616 return 0;
2617 }
2618}
2619
2620int ast_safe_mkdir(const char *base_path, const char *path, int mode)
2621{
2622 RAII_VAR(char *, absolute_base_path, NULL, ast_std_free);
2623 RAII_VAR(char *, p, NULL, ast_free);
2624
2625 if (base_path == NULL || path == NULL) {
2626 errno = EFAULT;
2627 return errno;
2628 }
2629
2630 p = ast_strdup(path);
2631 if (p == NULL) {
2632 errno = ENOMEM;
2633 return errno;
2634 }
2635
2636 absolute_base_path = realpath(base_path, NULL);
2637 if (absolute_base_path == NULL) {
2638 return errno;
2639 }
2640
2641 return safe_mkdir(absolute_base_path, p, mode);
2642}
2643
2644static void utils_shutdown(void)
2645{
2646 close(dev_urandom_fd);
2647 dev_urandom_fd = -1;
2648#if defined(DEBUG_THREADS) && !defined(LOW_MEMORY)
2649 ast_cli_unregister_multiple(utils_cli, ARRAY_LEN(utils_cli));
2650#endif
2651}
2652
2654{
2655 dev_urandom_fd = open("/dev/urandom", O_RDONLY);
2656 base64_init();
2657#ifdef DEBUG_THREADS
2658#if !defined(LOW_MEMORY)
2659 ast_cli_register_multiple(utils_cli, ARRAY_LEN(utils_cli));
2660#endif
2661#endif
2663 return 0;
2664}
2665
2666
2667/*!
2668 *\brief Parse digest authorization header.
2669 *\return Returns -1 if we have no auth or something wrong with digest.
2670 *\note This function may be used for Digest request and response header.
2671 * request arg is set to nonzero, if we parse Digest Request.
2672 * pedantic arg can be set to nonzero if we need to do addition Digest check.
2673 */
2674int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
2675 char *c;
2676 struct ast_str *str = ast_str_create(16);
2677
2678 /* table of recognised keywords, and places where they should be copied */
2679 const struct x {
2680 const char *key;
2681 const ast_string_field *field;
2682 } *i, keys[] = {
2683 { "username=", &d->username },
2684 { "realm=", &d->realm },
2685 { "nonce=", &d->nonce },
2686 { "uri=", &d->uri },
2687 { "domain=", &d->domain },
2688 { "response=", &d->response },
2689 { "cnonce=", &d->cnonce },
2690 { "opaque=", &d->opaque },
2691 /* Special cases that cannot be directly copied */
2692 { "algorithm=", NULL },
2693 { "qop=", NULL },
2694 { "nc=", NULL },
2695 { NULL, 0 },
2696 };
2697
2698 if (ast_strlen_zero(digest) || !d || !str) {
2699 ast_free(str);
2700 return -1;
2701 }
2702
2703 ast_str_set(&str, 0, "%s", digest);
2704
2706
2707 if (strncasecmp(c, "Digest ", strlen("Digest "))) {
2708 ast_log(LOG_WARNING, "Missing Digest.\n");
2709 ast_free(str);
2710 return -1;
2711 }
2712 c += strlen("Digest ");
2713
2714 /* lookup for keys/value pair */
2715 while (c && *c && *(c = ast_skip_blanks(c))) {
2716 /* find key */
2717 for (i = keys; i->key != NULL; i++) {
2718 char *src, *separator;
2719 int unescape = 0;
2720 if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
2721 continue;
2722 }
2723
2724 /* Found. Skip keyword, take text in quotes or up to the separator. */
2725 c += strlen(i->key);
2726 if (*c == '"') {
2727 src = ++c;
2728 separator = "\"";
2729 unescape = 1;
2730 } else {
2731 src = c;
2732 separator = ",";
2733 }
2734 strsep(&c, separator); /* clear separator and move ptr */
2735 if (unescape) {
2736 ast_unescape_c(src);
2737 }
2738 if (i->field) {
2739 ast_string_field_ptr_set(d, i->field, src);
2740 } else {
2741 /* Special cases that require additional processing */
2742 if (!strcasecmp(i->key, "algorithm=")) {
2743 if (strcasecmp(src, "MD5")) {
2744 ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", src);
2745 ast_free(str);
2746 return -1;
2747 }
2748 } else if (!strcasecmp(i->key, "qop=") && !strcasecmp(src, "auth")) {
2749 d->qop = 1;
2750 } else if (!strcasecmp(i->key, "nc=")) {
2751 unsigned long u;
2752 if (sscanf(src, "%30lx", &u) != 1) {
2753 ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", src);
2754 ast_free(str);
2755 return -1;
2756 }
2757 ast_string_field_set(d, nc, src);
2758 }
2759 }
2760 break;
2761 }
2762 if (i->key == NULL) { /* not found, try ',' */
2763 strsep(&c, ",");
2764 }
2765 }
2766 ast_free(str);
2767
2768 /* Digest checkout */
2769 if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
2770 /* "realm" and "nonce" MUST be always exist */
2771 return -1;
2772 }
2773
2774 if (!request) {
2775 /* Additional check for Digest response */
2776 if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
2777 return -1;
2778 }
2779
2780 if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
2781 return -1;
2782 }
2783 }
2784
2785 return 0;
2786}
2787
2789{
2790 int ret = -1;
2791#if defined (__linux) && defined(SYS_gettid)
2792 ret = syscall(SYS_gettid); /* available since Linux 1.4.11 */
2793#elif defined(__sun)
2794 ret = pthread_self();
2795#elif defined(__APPLE__)
2796 ret = mach_thread_self();
2797 mach_port_deallocate(mach_task_self(), ret);
2798#elif defined(__FreeBSD__)
2799 long lwpid;
2800 thr_self(&lwpid);
2801 ret = lwpid;
2802#elif defined(__NetBSD__)
2803 ret = _lwp_self();
2804#elif defined(__OpenBSD__)
2805 ret = getthrid();
2806#endif
2807 return ret;
2808}
2809
2810char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
2811{
2812 const char *envPATH = getenv("PATH");
2813 char *tpath, *path;
2814 struct stat unused;
2815 if (!envPATH) {
2816 return NULL;
2817 }
2818 tpath = ast_strdupa(envPATH);
2819 while ((path = strsep(&tpath, ":"))) {
2820 snprintf(fullpath, fullpath_size, "%s/%s", path, binary);
2821 if (!stat(fullpath, &unused)) {
2822 return fullpath;
2823 }
2824 }
2825 return NULL;
2826}
2827
2829{
2830 int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
2831
2832 if (udp6_socket < 0) {
2833 return 0;
2834 }
2835
2836 close(udp6_socket);
2837 return 1;
2838}
2839
2841{
2842#if defined(DO_CRASH)
2843 abort();
2844 /*
2845 * Just in case abort() doesn't work or something else super
2846 * silly, and for Qwell's amusement.
2847 */
2848 *((int *) 0) = 0;
2849#endif /* defined(DO_CRASH) */
2850}
2851
2852void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
2853{
2854 /*
2855 * Attempt to put it into the logger, but hope that at least
2856 * someone saw the message on stderr ...
2857 */
2858 fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
2859 condition_str, condition, line, function, file);
2860 ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
2861 condition_str, condition);
2862
2863 /* Generate a backtrace for the assert */
2865
2866 /*
2867 * Give the logger a chance to get the message out, just in case
2868 * we abort(), or Asterisk crashes due to whatever problem just
2869 * happened after we exit ast_assert().
2870 */
2871 usleep(1);
2872 ast_do_crash();
2873}
2874
2875char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
2876{
2877 int x;
2878 char *os = s;
2879 if (maxlen < 18) {
2880 if (s && (maxlen > 0)) {
2881 *s = '\0';
2882 }
2883 } else {
2884 for (x = 0; x < 5; x++) {
2885 sprintf(s, "%02hhx:", eid->eid[x]);
2886 s += 3;
2887 }
2888 sprintf(s, "%02hhx", eid->eid[5]);
2889 }
2890 return os;
2891}
2892
2893#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Darwin__)
2894#include <ifaddrs.h>
2895#include <net/if_dl.h>
2896
2897void ast_set_default_eid(struct ast_eid *eid)
2898{
2899 struct ifaddrs *ifap, *ifaphead;
2900 int rtnerr;
2901 const struct sockaddr_dl *sdl;
2902 int alen;
2903 caddr_t ap;
2904 char eid_str[20];
2905 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2906 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2907
2908 rtnerr = getifaddrs(&ifaphead);
2909 if (rtnerr) {
2910 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2911 "You will have to set it manually.\n");
2912 return;
2913 }
2914
2915 if (!ifaphead) {
2916 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2917 "You will have to set it manually.\n");
2918 return;
2919 }
2920
2921 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
2922 if (ifap->ifa_addr->sa_family != AF_LINK) {
2923 continue;
2924 }
2925
2926 sdl = (const struct sockaddr_dl *) ifap->ifa_addr;
2927 ap = ((caddr_t) ((sdl)->sdl_data + (sdl)->sdl_nlen));
2928 alen = sdl->sdl_alen;
2929 if (alen != 6 || !(memcmp(ap, &empty_mac, 6) && memcmp(ap, &full_mac, 6))) {
2930 continue;
2931 }
2932
2933 memcpy(eid, ap, sizeof(*eid));
2934 ast_debug(1, "Seeding global EID '%s'\n",
2935 ast_eid_to_str(eid_str, sizeof(eid_str), eid));
2936 freeifaddrs(ifaphead);
2937 return;
2938 }
2939
2940 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2941 "You will have to set it manually.\n");
2942 freeifaddrs(ifaphead);
2943
2944 return;
2945}
2946
2947#elif defined(SOLARIS)
2948#include <sys/sockio.h>
2949#include <net/if_arp.h>
2950
2951void ast_set_default_eid(struct ast_eid *eid)
2952{
2953 int s;
2954 int x;
2955 struct lifreq *ifr = NULL;
2956 struct lifnum ifn;
2957 struct lifconf ifc;
2958 struct arpreq ar;
2959 struct sockaddr_in *sa, *sa2;
2960 char *buf = NULL;
2961 char eid_str[20];
2962 int bufsz;
2963 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2964 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2965
2966 s = socket(AF_INET, SOCK_STREAM, 0);
2967 if (s <= 0) {
2968 ast_log(LOG_WARNING, "Unable to open a socket for seeding global EID. "
2969 " You will have to set it manually.\n");
2970 return;
2971 }
2972
2973 /* Get a count of interfaces on the machine */
2974 ifn.lifn_family = AF_UNSPEC;
2975 ifn.lifn_flags = 0;
2976 ifn.lifn_count = 0;
2977 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
2978 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
2979 " You will have to set it manually.\n");
2980 close(s);
2981 return;
2982 }
2983
2984 bufsz = ifn.lifn_count * sizeof(struct lifreq);
2985 if (!(buf = ast_malloc(bufsz))) {
2986 ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
2987 "You will have to set it manually.\n");
2988 close(s);
2989 return;
2990 }
2991 memset(buf, 0, bufsz);
2992
2993 /* Get a list of interfaces on the machine */
2994 ifc.lifc_len = bufsz;
2995 ifc.lifc_buf = buf;
2996 ifc.lifc_family = AF_UNSPEC;
2997 ifc.lifc_flags = 0;
2998 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
2999 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3000 "You will have to set it manually.\n");
3001 ast_free(buf);
3002 close(s);
3003 return;
3004 }
3005
3006 for (ifr = (struct lifreq *)buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
3007 unsigned char *p;
3008
3009 sa = (struct sockaddr_in *)&(ifr->lifr_addr);
3010 sa2 = (struct sockaddr_in *)&(ar.arp_pa);
3011 *sa2 = *sa;
3012
3013 if(ioctl(s, SIOCGARP, &ar) >= 0) {
3014 p = (unsigned char *)&(ar.arp_ha.sa_data);
3015 if (!(memcmp(p, &empty_mac, 6) && memcmp(p, &full_mac, 6))) {
3016 continue;
3017 }
3018
3019 memcpy(eid, p, sizeof(*eid));
3020 ast_debug(1, "Seeding global EID '%s'\n",
3021 ast_eid_to_str(eid_str, sizeof(eid_str), eid));
3022 ast_free(buf);
3023 close(s);
3024 return;
3025 }
3026 }
3027
3028 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3029 "You will have to set it manually.\n");
3030 ast_free(buf);
3031 close(s);
3032
3033 return;
3034}
3035
3036#else
3038{
3039 int s;
3040 int i;
3041 struct ifreq *ifr;
3042 struct ifreq *ifrp;
3043 struct ifconf ifc;
3044 char *buf = NULL;
3045 char eid_str[20];
3046 int bufsz, num_interfaces;
3047 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
3048 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3049
3050 s = socket(AF_INET, SOCK_STREAM, 0);
3051 if (s < 0) {
3052 ast_log(LOG_WARNING, "Unable to open socket for seeding global EID. "
3053 "You will have to set it manually.\n");
3054 return;
3055 }
3056
3057 ifc.ifc_len = 0;
3058 ifc.ifc_buf = NULL;
3059 if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
3060 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3061 "You will have to set it manually.\n");
3062 close(s);
3063 return;
3064 }
3065 bufsz = ifc.ifc_len;
3066
3067 if (!(buf = ast_malloc(bufsz))) {
3068 ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
3069 "You will have to set it manually.\n");
3070 close(s);
3071 return;
3072 }
3073
3074 ifc.ifc_buf = buf;
3075 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
3076 ast_log(LOG_WARNING, "Unable to retrieve ethernet interfaces for seeding global EID. "
3077 "You will have to set it manually.\n");
3078 ast_free(buf);
3079 close(s);
3080 return;
3081 }
3082
3083 ifrp = ifc.ifc_req;
3084 num_interfaces = ifc.ifc_len / sizeof(*ifr);
3085
3086 for (i = 0; i < num_interfaces; i++) {
3087 ifr = &ifrp[i];
3088 if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
3089 unsigned char *hwaddr = (unsigned char *) ifr->ifr_hwaddr.sa_data;
3090
3091 if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
3092 continue;
3093 }
3094
3095 memcpy(eid, hwaddr, sizeof(*eid));
3096 ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
3097 ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr->ifr_name);
3098 ast_free(buf);
3099 close(s);
3100 return;
3101 }
3102 }
3103
3104 ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
3105 "You will have to set it manually.\n");
3106 ast_free(buf);
3107 close(s);
3108
3109 return;
3110}
3111#endif /* LINUX */
3112
3113int ast_str_to_eid(struct ast_eid *eid, const char *s)
3114{
3115 unsigned int eid_int[6];
3116 int x;
3117
3118 if (sscanf(s, "%2x:%2x:%2x:%2x:%2x:%2x", &eid_int[0], &eid_int[1], &eid_int[2],
3119 &eid_int[3], &eid_int[4], &eid_int[5]) != 6) {
3120 return -1;
3121 }
3122
3123 for (x = 0; x < 6; x++) {
3124 eid->eid[x] = eid_int[x];
3125 }
3126
3127 return 0;
3128}
3129
3130int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
3131{
3132 return memcmp(eid1, eid2, sizeof(*eid1));
3133}
3134
3135int ast_eid_is_empty(const struct ast_eid *eid)
3136{
3137 struct ast_eid empty_eid;
3138
3139 memset(&empty_eid, 0, sizeof(empty_eid));
3140 return memcmp(eid, &empty_eid, sizeof(empty_eid)) ? 0 : 1;
3141}
3142
3143int ast_file_is_readable(const char *filename)
3144{
3145#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3146#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3147#define eaccess euidaccess
3148#endif
3149 return eaccess(filename, R_OK) == 0;
3150#else
3151 int fd = open(filename, O_RDONLY | O_NONBLOCK);
3152 if (fd < 0) {
3153 return 0;
3154 }
3155 close(fd);
3156 return 1;
3157#endif
3158}
3159
3160int ast_compare_versions(const char *version1, const char *version2)
3161{
3162 unsigned int major[2] = { 0 };
3163 unsigned int minor[2] = { 0 };
3164 unsigned int patch[2] = { 0 };
3165 unsigned int extra[2] = { 0 };
3166 int res;
3167
3168 sscanf(version1, "%u.%u.%u.%u", &major[0], &minor[0], &patch[0], &extra[0]);
3169 sscanf(version2, "%u.%u.%u.%u", &major[1], &minor[1], &patch[1], &extra[1]);
3170
3171 res = major[0] - major[1];
3172 if (res) {
3173 return res;
3174 }
3175 res = minor[0] - minor[1];
3176 if (res) {
3177 return res;
3178 }
3179 res = patch[0] - patch[1];
3180 if (res) {
3181 return res;
3182 }
3183 return extra[0] - extra[1];
3184}
3185
3186int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
3187 const char *file, int lineno, const char *function)
3188{
3189 int f;
3190
3191 f = fcntl(fd, F_GETFL);
3192 if (f == -1) {
3193 ast_log(__LOG_ERROR, file, lineno, function,
3194 "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
3195 return -1;
3196 }
3197
3198 switch (op) {
3199 case AST_FD_FLAG_SET:
3200 if ((f & flags) == flags) {
3201 /* There is nothing to set */
3202 return 0;
3203 }
3204 f |= flags;
3205 break;
3206 case AST_FD_FLAG_CLEAR:
3207 if (!(f & flags)) {
3208 /* There is nothing to clear */
3209 return 0;
3210 }
3211 f &= ~flags;
3212 break;
3213 default:
3214 ast_assert(0);
3215 break;
3216 }
3217
3218 f = fcntl(fd, F_SETFL, f);
3219 if (f == -1) {
3220 ast_log(__LOG_ERROR, file, lineno, function,
3221 "Failed to set fcntl() flags for file descriptor: %s\n", strerror(errno));
3222 return -1;
3223 }
3224
3225 return 0;
3226}
3227
3228#ifndef HAVE_SOCK_NONBLOCK
3229int ast_socket_nonblock(int domain, int type, int protocol)
3230{
3231 int s = socket(domain, type, protocol);
3232 if (s < 0) {
3233 return -1;
3234 }
3235
3236 if (ast_fd_set_flags(s, O_NONBLOCK)) {
3237 close(s);
3238 return -1;
3239 }
3240
3241 return s;
3242}
3243#endif
3244
3245#ifndef HAVE_PIPE2
3246int ast_pipe_nonblock(int filedes[2])
3247{
3248 int p = pipe(filedes);
3249 if (p < 0) {
3250 return -1;
3251 }
3252
3253 if (ast_fd_set_flags(filedes[0], O_NONBLOCK)
3254 || ast_fd_set_flags(filedes[1], O_NONBLOCK)) {
3255 close(filedes[0]);
3256 close(filedes[1]);
3257 return -1;
3258 }
3259
3260 return 0;
3261}
3262#endif
3263
3264/*!
3265 * \brief A thread local indicating whether the current thread is a user interface.
3266 */
3268
3269int ast_thread_user_interface_set(int is_user_interface)
3270{
3271 int *thread_user_interface;
3272
3273 thread_user_interface = ast_threadstorage_get(
3274 &thread_user_interface_tl, sizeof(*thread_user_interface));
3275 if (thread_user_interface == NULL) {
3276 ast_log(LOG_ERROR, "Error setting user interface status for current thread\n");
3277 return -1;
3278 }
3279
3280 *thread_user_interface = !!is_user_interface;
3281 return 0;
3282}
3283
3285{
3286 int *thread_user_interface;
3287
3288 thread_user_interface = ast_threadstorage_get(
3289 &thread_user_interface_tl, sizeof(*thread_user_interface));
3290 if (thread_user_interface == NULL) {
3291 ast_log(LOG_ERROR, "Error checking thread's user interface status\n");
3292 /* On error, assume that we are not a user interface thread */
3293 return 0;
3294 }
3295
3296 return *thread_user_interface;
3297}
3298
3299int ast_check_command_in_path(const char *cmd)
3300{
3301 char *token, *saveptr, *path = getenv("PATH");
3302 char filename[PATH_MAX];
3303 int len;
3304
3305 if (path == NULL) {
3306 return 0;
3307 }
3308
3309 path = ast_strdup(path);
3310 if (path == NULL) {
3311 return 0;
3312 }
3313
3314 token = strtok_r(path, ":", &saveptr);
3315 while (token != NULL) {
3316 len = snprintf(filename, sizeof(filename), "%s/%s", token, cmd);
3317 if (len < 0 || len >= sizeof(filename)) {
3318 ast_log(LOG_WARNING, "Path constructed with '%s' too long; skipping\n", token);
3319 continue;
3320 }
3321
3322 if (access(filename, X_OK) == 0) {
3323 ast_free(path);
3324 return 1;
3325 }
3326
3327 token = strtok_r(NULL, ":", &saveptr);
3328 }
3329 ast_free(path);
3330 return 0;
3331}
3332
const char * str
Definition: app_jack.c:150
pthread_t thread
Definition: app_sla.c:335
ast_mutex_t lock
Definition: app_sla.c:337
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.
char * strsep(char **str, const char *delims)
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 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:2619
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:3037
@ 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:136
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:55
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)
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:2480
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:646
#define pthread_create
Definition: lock.h:649
#define pthread_mutex_lock
Definition: lock.h:632
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define pthread_mutex_t
Definition: lock.h:629
#define AST_MUTEX_KIND
Definition: lock.h:84
#define pthread_mutex_unlock
Definition: lock.h:633
#define pthread_mutex_destroy
Definition: lock.h:636
#define ast_mutex_lock(a)
Definition: lock.h:196
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:527
#define pthread_mutex_init
Definition: lock.h:635
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[MD5_DIGEST_LENGTH], 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:223
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
const char * string
Definition: presencestate.c:74
#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:30
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:850
unsigned char eid[6]
Definition: utils.h:851
Structure used to handle boolean flags.
Definition: utils.h:217
char buf[1024]
Definition: utils.h:228
struct hostent hp
Definition: utils.h:227
Lock tracking information.
Definition: lock.h:118
int reentrancy
Definition: lock.h:121
int lineno[AST_MAX_REENTRANCY]
Definition: lock.h:120
const char * file[AST_MAX_REENTRANCY]
Definition: lock.h:119
const char * func[AST_MAX_REENTRANCY]
Definition: lock.h:122
Structure for mutex and tracking information.
Definition: lock.h:142
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
const char * name
char * name
Definition: utils.c:1599
void * data
Definition: utils.c:1598
void *(* start_routine)(void *)
Definition: utils.c:1597
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:2433
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
Definition: utils.c:3284
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: utils.c:878
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:3299
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:2620
static char base64url[64]
Definition: utils.c:81
static int dev_urandom_fd
Definition: utils.c:974
int ast_xml_escape(const char *string, char *const outbuf, const size_t buflen)
Escape reserved characters for use in XML.
Definition: utils.c:900
static struct ast_threadstorage thread_user_interface_tl
Definition: utils.c:3267
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:3143
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:1807
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2482
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:3186
int ast_background_stacksize(void)
Definition: utils.c:1652
char escape_sequences[]
Definition: utils.c:2058
char * ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
Resolve a binary to a full pathname.
Definition: utils.c:2810
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:3037
int ast_thread_user_interface_set(int is_user_interface)
Set the current thread's user interface status.
Definition: utils.c:3269
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: utils.c:3130
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: utils.c:817
static void * dummy_start(void *data)
Definition: utils.c:1609
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:2019
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:2203
int ast_wait_for_input(int fd, int ms)
Definition: utils.c:1734
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
Definition: utils.c:2674
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:2333
#define ONE_MILLION
Definition: utils.c:2269
static void utils_shutdown(void)
Definition: utils.c:2644
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
get values from config variables.
Definition: utils.c:2455
char * ast_unescape_semicolon(char *s)
Strip backslash for "escaped" semicolons, the string to be stripped (will be modified).
Definition: utils.c:2000
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2875
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:2113
int ast_get_tid(void)
Get current thread ID.
Definition: utils.c:2788
char * ast_strsep(char **iss, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1871
long int ast_random(void)
Definition: utils.c:2348
static void base64_init(void)
Definition: utils.c:540
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2515
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:2184
char * ast_escape_alloc(const char *s, const char *to_escape)
Escape the 'to_escape' characters in the given string.
Definition: utils.c:2168
const struct ast_flags ast_uri_http
Definition: utils.c:719
int ast_utils_init(void)
Definition: utils.c:2653
int ast_wait_for_output(int fd, int ms)
Definition: utils.c:1744
static char * escape_alloc(const char *s, size_t *size)
Definition: utils.c:2154
static char b2a[256]
Definition: utils.c:82
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
Definition: utils.c:2505
#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:3160
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:1935
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2317
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: utils.c:3135
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:1854
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:2289
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
Definition: utils.c:2840
char * ast_process_quotes_and_slashes(char *start, char find, char replace_with)
Process a string to find and replace characters.
Definition: utils.c:2388
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: utils.c:2303
static int safe_mkdir(const char *base_path, char *path, int mode)
Definition: utils.c:2550
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:847
int ast_false(const char *s)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2252
static char escape_sequences_map[]
Definition: utils.c:2066
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:2235
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_uri_verify_encoded(const char *string)
Verify if a string is valid as a URI component.
Definition: utils.c:781
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: utils.c:2828
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:2176
const char * ast_inet_ntoa(struct in_addr ia)
ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa
Definition: utils.c:964
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: utils.c:3113
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:2274
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
Definition: utils.c:2379
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
Definition: utils.c:2852
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:1709
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:1661
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:2215
const struct ast_flags ast_uri_http_legacy
Definition: utils.c:720
static int wait_for_output(int fd, int timeoutms)
Definition: utils.c:1754
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:2414
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:2070
static ast_mutex_t randomlock
Definition: utils.c:2345
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_URI_LEGACY_SPACE
Definition: utils.h:385
#define AST_URI_MARK
Definition: utils.h:383
#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:978
#define ast_assert(a)
Definition: utils.h:776
#define AST_URI_SIP_USER_UNRESERVED
Definition: utils.h:387
#define DO_CRASH_NORETURN
Definition: utils.h:754
ast_fd_flag_operation
Definition: utils.h:1058
@ AST_FD_FLAG_SET
Definition: utils.h:1059
@ AST_FD_FLAG_CLEAR
Definition: utils.h:1060
#define AST_URI_ALPHANUM
Definition: utils.h:382
#define AST_STACKSIZE
Definition: utils.h:602
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1110
#define AST_URI_UNRESERVED
Definition: utils.h:384
#define AST_STACKSIZE_LOW
Definition: utils.h:603
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1076
void ast_register_thread(char *name)
Definition: asterisk.c:421
void ast_unregister_thread(void *id)
Definition: asterisk.c:437
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
Definition: utils.h:1127
#define ARRAY_LEN(a)
Definition: utils.h:703
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691