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