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