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