35#include <sys/syscall.h>
39#elif defined(__FreeBSD__)
41#elif defined(__NetBSD__)
87#if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
99static int gethostbyname_r (
const char *
name,
struct hostent *ret,
char *
buf,
100 size_t buflen,
struct hostent **
result,
116 int naddr = 0, naliases = 0;
120 for (p = ph->h_addr_list; *p != 0; p++) {
121 nbytes += ph->h_length;
122 nbytes +=
sizeof(*p);
125 nbytes +=
sizeof(*p);
128 for (p = ph->h_aliases; *p != 0; p++) {
129 nbytes += (strlen(*p)+1);
130 nbytes +=
sizeof(*p);
133 nbytes +=
sizeof(*p);
137 if (nbytes > buflen) {
160 ret->h_addr_list = q;
161 pbuf =
buf + ((naddr + naliases + 2) *
sizeof(*p));
162 for (p = ph->h_addr_list; *p != 0; p++) {
163 memcpy(pbuf, *p, ph->h_length);
165 pbuf += ph->h_length;
171 for (p = ph->h_aliases; *p != 0; p++) {
179 strcpy(pbuf, ph->h_name);
181 pbuf += strlen(ph->h_name);
201#ifndef HAVE_GETHOSTBYNAME_R_5
216 else if (!isdigit(*s))
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 *);
230 if (inet_pton(AF_INET, host, hp->
hp.h_addr) > 0)
235#ifdef HAVE_GETHOSTBYNAME_R_5
236 result = gethostbyname_r(host, &hp->
hp, hp->
buf,
sizeof(hp->
buf), &herrno);
238 if (!
result || !hp->
hp.h_addr_list || !hp->
hp.h_addr_list[0])
241 res = gethostbyname_r(host, &hp->
hp, hp->
buf,
sizeof(hp->
buf), &
result, &herrno);
243 if (res || !
result || !hp->
hp.h_addr_list || !hp->
hp.h_addr_list[0])
253 unsigned char digest[16];
261 for (x = 0; x < 16; x++)
262 ptr += sprintf(ptr,
"%02hhx", digest[x]);
271 uint8_t Message_Digest[20];
279 for (x = 0; x < 20; x++)
280 ptr += sprintf(ptr,
"%02hhx", Message_Digest[x]);
299 unsigned int byte = 0;
300 unsigned int bits = 0;
302 while(*src && *src !=
'=' && (cnt <
max)) {
305 byte |= (
b2a[(int)(*src)]) & 0x3f;
313 *dst = (
byte >> bits) & 0xff;
328 unsigned char *decoded_string;
334 encoded_len = strlen(src);
335 if (encoded_len > 2 && src[encoded_len - 1] ==
'=') {
337 if (src[encoded_len - 2] ==
'=') {
342 decoded_len = (encoded_len / 4 * 3) - padding;
344 if (!decoded_string) {
349 decoded_string[decoded_len] =
'\0';
351 return (
char *)decoded_string;
359 unsigned int byte = 0;
364 while ((cntin < srclen) && (cnt <
max)) {
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];
379 if (linebreaks && (cnt <
max) && (col == 64)) {
385 if (bits && (cnt + 4 <=
max)) {
389 *dst++ =
base64[(
byte >> 18) & 0x3f];
390 *dst++ =
base64[(
byte >> 12) & 0x3f];
392 *dst++ =
base64[(
byte >> 6) & 0x3f];
398 if (linebreaks && (cnt <
max)) {
415 char *encoded_string;
421 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
424 ast_base64encode(encoded_string, (
const unsigned char *)src, strlen(src), encoded_len);
426 return encoded_string;
432 unsigned int byte = 0;
433 unsigned int bits = 0;
435 while (*src && (cnt <
max)) {
437 byte |= (
b2a_url[(int)(*src)]) & 0x3f;
442 *dst = (
byte >> bits) & 0xff;
453 unsigned char *decoded_string;
459 decoded_len = strlen(src) * 3 / 4;
461 if (!decoded_string) {
466 decoded_string[decoded_len] =
'\0';
468 return (
char *)decoded_string;
475 unsigned int byte = 0;
480 while ((cntin < srclen) && (cnt <
max)) {
485 if ((bits == 24) && (cnt + 4 <=
max)) {
495 if (linebreaks && (cnt <
max) && (col == 64)) {
501 if (bits && (cnt + 4 <=
max)) {
510 if (linebreaks && (cnt <
max)) {
526 char *encoded_string;
532 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
537 return encoded_string;
543 memset(
b2a, -1,
sizeof(
b2a));
546 for (x = 0; x < 26; x++) {
555 b2a[
'a' + x] = x + 26;
561 b2a[
'0' + x] = x + 52;
575#define BASELINELEN 72
576#define BASEMAXINLINE 256
618 if (!
inbuf(bio, fi)) {
632 if (fputs(endl, so) == EOF) {
639 if (putc(((
unsigned char)
c), so) == EOF) {
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',
'+',
'/'};
657 memset(&bio, 0,
sizeof(bio));
661 unsigned char igroup[3], ogroup[4];
664 memset(igroup, 0,
sizeof(igroup));
666 for (n = 0; n < 3; n++) {
667 if ((
c =
inchar(&bio, inputfile)) == EOF) {
672 igroup[n] = (
unsigned char)
c;
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];
689 for (i = 0; i < 4; i++) {
690 ochar(&bio, ogroup[i], outputfile, endl);
695 if (fputs(endl, outputfile) == EOF) {
707 if (!(fi = fopen(filename,
"rb"))) {
727 const char *mark =
"-_.!~*'()";
728 const char *user_unreserved =
"&=+$,;?/";
730 while (*ptr &&
out - outbuf < buflen - 1) {
736 && strchr(mark, *ptr))
738 && ((*ptr >=
'0' && *ptr <=
'9')
739 || (*ptr >=
'A' && *ptr <=
'Z')
740 || (*ptr >=
'a' && *ptr <=
'z')))
742 && strchr(user_unreserved, *ptr))) {
744 if (
out - outbuf >= buflen - 3) {
747 out += sprintf(
out,
"%%%02hhX", (
unsigned char) *ptr);
767 for (o = s; *s; s++, o++) {
771 }
else if (*s ==
'%' && s[1] !=
'\0' && s[2] !=
'\0' && sscanf(s + 1,
"%2x", &
tmp) == 1) {
785 char *allow =
"\t\v !";
787 while (*ptr &&
out - outbuf < buflen - 1) {
788 if (!(strchr(allow, *ptr))
789 && !(*ptr >=
'#' && *ptr <=
'[')
790 && !(*ptr >=
']' && *ptr <=
'~')
791 && !((
unsigned char) *ptr > 0x7f)) {
793 if (
out - outbuf >= buflen - 2) {
796 out += sprintf(
out,
"\\%c", (
unsigned char) *ptr);
816 if (
string ==
NULL || outbuf ==
NULL) {
821 while (*ptr &&
out - outbuf < buflen - 1) {
823 if (
out - outbuf >= buflen - 2) {
846 int quote_str_len = strlen(quote_str);
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] ==
'\\') {
854 if (esc_pos >= quote_str_len) {
859 quote_str[unesc_pos] = quote_str[esc_pos];
861 quote_str[unesc_pos] =
'\0';
867 char *
end = outbuf + buflen - 1;
876 while (*
string && dst <
end) {
877 const char *entity =
NULL;
924 return *
string ==
'\0' ? 0 : -1;
935 return inet_ntop(AF_INET, &ia,
buf, INET_ADDRSTRLEN);
946#if !defined(LOW_MEMORY)
948#define AST_MAX_LOCKS 64
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
962struct thr_lock_info {
966 const char *thread_name;
971 const char *lock_name;
974 int times_lock_attempted;
975 struct timeval last_locked;
976 struct timeval last_unlocked;
986 } locks[AST_MAX_LOCKS];
990 unsigned int num_locks;
1013static void lock_info_destroy(
void *data)
1023 for (i = 0; i <
lock_info->num_locks; i++) {
1024 if (
lock_info->locks[i].pending == -1) {
1031 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
1055 int line_num,
const char *func,
const char *lock_name,
void *lock_addr,
struct ast_bt *bt)
1057#if !defined(LOW_MEMORY)
1066 for (i = 0; i <
lock_info->num_locks; i++) {
1067 if (
lock_info->locks[i].lock_addr == lock_addr) {
1069 lock_info->locks[i].times_lock_attempted++;
1079 if (
lock_info->num_locks == AST_MAX_LOCKS) {
1081 fprintf(stderr,
"XXX ERROR XXX A thread holds more locks than '%d'."
1082 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
1087 if (i &&
lock_info->locks[i - 1].pending == -1) {
1097 lock_info->locks[i].line_num = line_num;
1099 lock_info->locks[i].lock_name = lock_name;
1100 lock_info->locks[i].lock_addr = lock_addr;
1102 lock_info->locks[i].times_lock_attempted = 1;
1115void ast_mark_lock_acquired(
void *lock_addr)
1117#if !defined(LOW_MEMORY)
1133#if !defined(LOW_MEMORY)
1149int ast_find_lock_info(
void *lock_addr,
char *filename,
size_t filename_size,
int *lineno,
char *func,
size_t func_size,
char *mutex_name,
size_t mutex_name_size)
1151#if !defined(LOW_MEMORY)
1160 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1161 if (
lock_info->locks[i].lock_addr == lock_addr)
1184void ast_suspend_lock_info(
void *lock_addr)
1186#if !defined(LOW_MEMORY)
1196 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1197 if (
lock_info->locks[i].lock_addr == lock_addr)
1213void ast_restore_lock_info(
void *lock_addr)
1215#if !defined(LOW_MEMORY)
1224 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1225 if (
lock_info->locks[i].lock_addr == lock_addr)
1242void ast_remove_lock_info(
void *lock_addr,
struct ast_bt *bt)
1244#if !defined(LOW_MEMORY)
1253 for (i =
lock_info->num_locks - 1; i >= 0; i--) {
1254 if (
lock_info->locks[i].lock_addr == lock_addr)
1264 if (
lock_info->locks[i].times_locked > 1) {
1274 if (i < lock_info->num_locks - 1) {
1286#if !defined(LOW_MEMORY)
1302static void append_backtrace_information(
struct ast_str **
str,
struct ast_bt *bt)
1318 for (frame_iterator = 1; frame_iterator <
AST_VECTOR_SIZE(symbols); ++frame_iterator) {
1329static void append_lock_information(
struct ast_str **
str,
struct thr_lock_info *
lock_info,
int i)
1334 struct timeval held_for;
1336 char lock_time[32], unlock_time[32], held_time[32];
1341 lock_time,
sizeof(lock_time));
1343 unlock_time,
sizeof(unlock_time));
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,
1357 lock_info->locks[i].last_locked.tv_usec,
1359 lock_info->locks[i].last_unlocked.tv_usec,
1363 lock_info->locks[i].times_lock_attempted,
1364 lock_info->locks[i].suspended ?
" - suspended" :
"");
1366 append_backtrace_information(
str,
lock_info->locks[i].backtrace);
1378 ast_reentrancy_lock(lt);
1383 ast_reentrancy_unlock(lt);
1406void ast_log_show_lock(
void *this_lock_addr)
1408#if !defined(LOW_MEMORY)
1425 if (
lock_info->locks[i].lock_addr == this_lock_addr) {
1439struct ast_str *ast_dump_locks(
void)
1441#if !defined(LOW_MEMORY)
1444 char print_time[32];
1454 "=======================================================================\n"
1456 "=== Currently Held Locks at Time: %s.%06ld =================\n"
1457 "=======================================================================\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"
1469 int header_printed = 0;
1477 if (!header_printed) {
1494 if (header_printed) {
1495 ast_str_append(&
str, 0,
"=== -------------------------------------------------------------------\n"
1508 ast_str_append(&
str, 0,
"=======================================================================\n"
1517#if !defined(LOW_MEMORY)
1524 e->
command =
"core show locks";
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";
1536 str = ast_dump_locks();
1549 AST_CLI_DEFINE(handle_show_locks,
"Show which locks are held by which thread"),
1554#if !defined(LOW_MEMORY)
1561 void *(*start_routine)(
void *);
1579 pthread_mutexattr_t mutex_attr;
1588 pthread_mutexattr_init(&mutex_attr);
1591 pthread_mutexattr_destroy(&mutex_attr);
1607 ret =
a.start_routine(
a.data);
1609 pthread_cleanup_pop(1);
1618#if !defined(LOW_MEMORY)
1626 void *data,
size_t stacksize,
const char *
file,
const char *caller,
1627 int line,
const char *start_fn)
1629#if !defined(LOW_MEMORY)
1635 pthread_attr_init(attr);
1638#if defined(__linux__) || defined(__FreeBSD__)
1646 if ((
errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1653 if ((
errno = pthread_attr_setstacksize(attr, stacksize ? stacksize :
AST_STACKSIZE)))
1656#if !defined(LOW_MEMORY)
1662 start_fn, line,
file, caller) < 0) {
1674 void *
data,
size_t stacksize,
const char *
file,
const char *caller,
1675 int line,
const char *start_fn)
1677 unsigned char attr_destroy = 0;
1682 pthread_attr_init(attr);
1686 if ((
errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1690 stacksize,
file, caller, line, start_fn);
1693 pthread_attr_destroy(attr);
1700 struct pollfd pfd[1];
1702 memset(pfd, 0,
sizeof(pfd));
1704 pfd[0].events = POLLIN | POLLPRI;
1710 struct pollfd pfd[1];
1712 memset(pfd, 0,
sizeof(pfd));
1714 pfd[0].events = POLLOUT;
1720 struct pollfd pfd = {
1729 while ((res =
ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1733 ast_debug(1,
"Timed out trying to write\n");
1736 }
else if (res == -1) {
1741 if (elapsed >= timeoutms) {
1754 if (elapsed >= timeoutms) {
1782 res = write(fd, s,
len);
1784 if (res < 0 &&
errno != EAGAIN &&
errno != EINTR) {
1786 if (
errno == EPIPE) {
1788 ast_debug(1,
"write() failed due to reading end being closed: %s\n", strerror(
errno));
1807 if (elapsed >= timeoutms) {
1824 if ((q = strchr(beg_quotes, *s)) && *q !=
'\0') {
1825 e = s + strlen(s) - 1;
1826 if (*e == *(end_quotes + (q - beg_quotes))) {
1848 memset(stack, 0,
sizeof(stack));
1850 for(is = st; *is; is++) {
1852 if (*++is !=
'\0') {
1859 if (*is ==
'\'' || *is ==
'"') {
1860 if (*is == stack[inquote]) {
1861 stack[inquote--] =
'\0';
1863 if (++inquote >=
sizeof(stack)) {
1866 stack[inquote] = *is;
1870 if (*is == sep && !inquote) {
1906 const char qstr[] = {
quote };
1913 memset(stack, 0,
sizeof(stack));
1915 for(is = st; *is; is++) {
1917 if (*++is !=
'\0') {
1925 if (*is == stack[inquote]) {
1926 stack[inquote--] =
'\0';
1928 if (++inquote >=
sizeof(stack)) {
1931 stack[inquote] = *is;
1935 if (*is == sep && !inquote) {
1969 while ((e = strchr(work,
';'))) {
1970 if ((e > work) && (*(e-1) ==
'\\')) {
1971 memmove(e - 1, e, strlen(e) + 1);
1989 for (ret = dst = src; (
c = *src++); *dst++ =
c ) {
1992 switch ((
c = *src++)) {
2023 '\a',
'\b',
'\f',
'\n',
'\r',
'\t',
'\v',
'\\',
'\'',
'\"',
'\?',
'\0'
2031 'a',
'b',
'f',
'n',
'r',
't',
'v',
'\\',
'\'',
'"',
'?',
'\0'
2034char *
ast_escape(
char *dest,
const char *s,
size_t size,
const char *to_escape)
2039 if (!dest || !size) {
2052 for (p = dest; *s && --size; ++s, ++p) {
2054 if (strchr(to_escape, *s)) {
2087 if (!dest || !size) {
2095 for (p = dest; *s && --size; ++s, ++p) {
2128 *size = strlen(s) * 2 + 1;
2152 if (!buffer || !*buffer || !space || !*space)
2155 result = vsnprintf(*buffer, *space, fmt, ap);
2159 else if (
result > *space)
2181 int regex_len = strlen(regex_string);
2185 if ((regex_len >= 1) && (regex_string[0] ==
'/')) {
2186 ast_str_set(regex_pattern, 0,
"%s", regex_string + 1);
2191 if ((regex_len > 1) && (regex_string[regex_len - 1] ==
'/')) {
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"))
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"))
2233#define ONE_MILLION 1000000
2242 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2245 }
else if (
a.tv_usec < 0) {
2247 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2258 a.tv_sec +=
b.tv_sec;
2259 a.tv_usec +=
b.tv_usec;
2272 a.tv_sec -=
b.tv_sec;
2273 a.tv_usec -=
b.tv_usec;
2274 if (
a.tv_usec < 0) {
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);
2319 long int rm = RAND_MAX;
2320 res = res < 0 ? ~res : res;
2354 char *dataPut = start;
2358 for (; *start; start++) {
2360 *dataPut++ = *start;
2363 if (*start ==
'\\') {
2365 }
else if (*start ==
'\'') {
2366 inQuotes = 1 - inQuotes;
2369 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2373 if (start != dataPut)
2386 for (x = 0; ofs <
len && x < size && w[x] ; x++) {
2389 for (src = w[x]; *src && ofs <
len; src++)
2400 char *front, *back, *
buf = res;
2403 front = strtok_r(
buf, delim, &back);
2406 size = strlen(front);
2407 *front = toupper(*front);
2410 front = strtok_r(
NULL, delim, &back);
2419int ast_get_timeval(
const char *src,
struct timeval *dst,
struct timeval _default,
int *consumed)
2421 long double dtv = 0.0;
2433 if (sscanf(src,
"%30Lf%n", &dtv, &scanned) > 0) {
2435 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2437 *consumed = scanned;
2460 if (sscanf(src,
"%30ld%n", &t, &scanned) == 1) {
2463 *consumed = scanned;
2471#if defined(HAVE_IP_MTU_DISCOVER)
2472 int val = IP_PMTUDISC_DONT;
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");
2482 int len = strlen(path), count = 0, x, piececount = 0;
2488 for (ptr =
tmp; *ptr; ptr++) {
2494 pieces =
ast_alloca(count *
sizeof(*pieces));
2495 for (ptr =
tmp; *ptr; ptr++) {
2498 pieces[piececount++] = ptr + 1;
2503 for (x = 0; x < piececount; x++) {
2505 strcat(fullpath,
"/");
2506 strcat(fullpath, pieces[x]);
2507 res = mkdir(fullpath, mode);
2508 if (res &&
errno != EEXIST)
2514static int safe_mkdir(
const char *base_path,
char *path,
int mode)
2518 absolute_path = realpath(path,
NULL);
2520 if (absolute_path) {
2532 char *path_term = strchr(path,
'/');
2534 int parent_is_safe = 0;
2541 char c = *(path_term + 1);
2542 *(path_term + 1) =
'\0';
2543 absolute_subpath = realpath(path,
NULL);
2545 if (absolute_subpath) {
2548 absolute_subpath, base_path);
2549 }
else if (parent_is_safe) {
2552 res = mkdir(path, mode);
2564 *(path_term + 1) =
c;
2566 path_term = strchr(path_term + 1,
'/');
2570 if (!parent_is_safe) {
2575 res = mkdir(path, mode);
2576 if (res != 0 &&
errno != EEXIST) {
2589 if (base_path ==
NULL || path ==
NULL) {
2600 absolute_base_path = realpath(base_path,
NULL);
2601 if (absolute_base_path ==
NULL) {
2605 return safe_mkdir(absolute_base_path, p, mode);
2612#if defined(DEBUG_THREADS) && !defined(LOW_MEMORY)
2622#if !defined(LOW_MEMORY)
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 },
2656 {
"algorithm=",
NULL },
2671 if (strncasecmp(
c,
"Digest ", strlen(
"Digest "))) {
2676 c += strlen(
"Digest ");
2681 for (i =
keys; i->key !=
NULL; i++) {
2682 char *src, *separator;
2684 if (strncasecmp(
c, i->key, strlen(i->key)) != 0) {
2689 c += strlen(i->key);
2706 if (!strcasecmp(i->key,
"algorithm=")) {
2707 if (strcasecmp(src,
"MD5")) {
2712 }
else if (!strcasecmp(i->key,
"qop=") && !strcasecmp(src,
"auth")) {
2714 }
else if (!strcasecmp(i->key,
"nc=")) {
2716 if (sscanf(src,
"%30lx", &u) != 1) {
2726 if (i->key ==
NULL) {
2755#if defined (__linux) && defined(SYS_gettid)
2756 ret = syscall(SYS_gettid);
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__)
2766#elif defined(__NetBSD__)
2768#elif defined(__OpenBSD__)
2776 const char *envPATH = getenv(
"PATH");
2783 while ((path =
strsep(&tpath,
":"))) {
2784 snprintf(fullpath, fullpath_size,
"%s/%s", path, binary);
2785 if (!stat(fullpath, &unused)) {
2794 int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
2796 if (udp6_socket < 0) {
2806#if defined(DO_CRASH)
2822 fprintf(stderr,
"FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
2823 condition_str, condition, line, function,
file);
2825 condition_str, condition);
2844 if (s && (maxlen > 0)) {
2848 for (x = 0; x < 5; x++) {
2849 sprintf(s,
"%02hhx:", eid->
eid[x]);
2852 sprintf(s,
"%02hhx", eid->
eid[5]);
2857#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Darwin__)
2859#include <net/if_dl.h>
2863 struct ifaddrs *ifap, *ifaphead;
2865 const struct sockaddr_dl *sdl;
2869 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2870 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2872 rtnerr = getifaddrs(&ifaphead);
2875 "You will have to set it manually.\n");
2881 "You will have to set it manually.\n");
2885 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
2886 if (ifap->ifa_addr->sa_family != AF_LINK) {
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))) {
2897 memcpy(eid, ap,
sizeof(*eid));
2898 ast_debug(1,
"Seeding global EID '%s'\n",
2900 freeifaddrs(ifaphead);
2905 "You will have to set it manually.\n");
2906 freeifaddrs(ifaphead);
2911#elif defined(SOLARIS)
2912#include <sys/sockio.h>
2913#include <net/if_arp.h>
2919 struct lifreq *ifr =
NULL;
2923 struct sockaddr_in *sa, *sa2;
2927 unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
2928 unsigned char full_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2930 s = socket(AF_INET, SOCK_STREAM, 0);
2933 " You will have to set it manually.\n");
2938 ifn.lifn_family = AF_UNSPEC;
2941 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
2943 " You will have to set it manually.\n");
2948 bufsz = ifn.lifn_count *
sizeof(
struct lifreq);
2951 "You will have to set it manually.\n");
2955 memset(
buf, 0, bufsz);
2958 ifc.lifc_len = bufsz;
2960 ifc.lifc_family = AF_UNSPEC;
2962 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
2964 "You will have to set it manually.\n");
2970 for (ifr = (
struct lifreq *)
buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
2973 sa = (
struct sockaddr_in *)&(ifr->lifr_addr);
2974 sa2 = (
struct sockaddr_in *)&(ar.arp_pa);
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))) {
2983 memcpy(eid, p,
sizeof(*eid));
2984 ast_debug(1,
"Seeding global EID '%s'\n",
2993 "You will have to set it manually.\n");
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};
3014 s = socket(AF_INET, SOCK_STREAM, 0);
3017 "You will have to set it manually.\n");
3023 if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
3025 "You will have to set it manually.\n");
3029 bufsz = ifc.ifc_len;
3033 "You will have to set it manually.\n");
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");
3048 num_interfaces = ifc.ifc_len /
sizeof(*ifr);
3050 for (i = 0; i < num_interfaces; i++) {
3052 if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
3053 unsigned char *hwaddr = (
unsigned char *) ifr->ifr_hwaddr.sa_data;
3055 if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
3059 memcpy(eid, hwaddr,
sizeof(*eid));
3060 ast_debug(1,
"Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
3069 "You will have to set it manually.\n");
3079 unsigned int eid_int[6];
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) {
3087 for (x = 0; x < 6; x++) {
3088 eid->
eid[x] = eid_int[x];
3096 return memcmp(eid1, eid2,
sizeof(*eid1));
3109#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3110#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3111#define eaccess euidaccess
3113 return eaccess(filename, R_OK) == 0;
3115 int fd = open(filename, O_RDONLY | O_NONBLOCK);
3126 unsigned int major[2] = { 0 };
3127 unsigned int minor[2] = { 0 };
3128 unsigned int patch[2] = { 0 };
3129 unsigned int extra[2] = { 0 };
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]);
3135 res = major[0] - major[1];
3139 res = minor[0] - minor[1];
3143 res = patch[0] - patch[1];
3147 return extra[0] - extra[1];
3151 const char *
file,
int lineno,
const char *function)
3155 f = fcntl(fd, F_GETFL);
3158 "Failed to get fcntl() flags for file descriptor: %s\n", strerror(
errno));
3164 if ((f & flags) == flags) {
3182 f = fcntl(fd, F_SETFL, f);
3185 "Failed to set fcntl() flags for file descriptor: %s\n", strerror(
errno));
3192#ifndef HAVE_SOCK_NONBLOCK
3195 int s = socket(domain,
type, protocol);
3212 int p = pipe(filedes);
3235 int *thread_user_interface;
3239 if (thread_user_interface ==
NULL) {
3240 ast_log(
LOG_ERROR,
"Error setting user interface status for current thread\n");
3244 *thread_user_interface = !!is_user_interface;
3250 int *thread_user_interface;
3254 if (thread_user_interface ==
NULL) {
3260 return *thread_user_interface;
3265 char *token, *saveptr, *path = getenv(
"PATH");
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)) {
3286 if (access(filename, X_OK) == 0) {
3291 token = strtok_r(
NULL,
":", &saveptr);
static int input(yyscan_t yyscanner)
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
void ast_std_free(void *ptr)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ast_bt_free_symbols(string_vector)
#define ast_bt_get_symbols(addresses, num_frames)
static int request(void *obj)
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_mark_lock_failed(void *lock_addr)
static const struct ast_datastore_info lock_info
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
I/O Management (derived from Cheops-NG)
A set of macros to manage forward-linked lists.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Asterisk locking-related definitions:
#define pthread_mutex_lock
#define ast_mutex_unlock(a)
#define pthread_mutex_unlock
#define pthread_mutex_destroy
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
#define pthread_mutex_init
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
void MD5Init(struct MD5Context *context)
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Wrapper for network related headers, masking differences between various operating systems....
static dundi_eid empty_eid
#define ast_poll(a, b, c)
int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
SHA1Result Returns the resulting 160-bit digest.
int SHA1Input(SHA1Context *, const uint8_t *bytes, unsigned int bytecount)
int SHA1Reset(SHA1Context *)
SHA1Reset.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
const char * ast_string_field
#define ast_string_field_ptr_set(x, ptr, data)
Set a field to a simple string value.
String manipulation functions.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
void * addresses[AST_MAX_BT_FRAMES]
descriptor for a cli entry.
An Entity ID is essentially a MAC address, brief and unique.
Structure used to handle boolean flags.
Lock tracking information.
int lineno[AST_MAX_REENTRANCY]
const char * file[AST_MAX_REENTRANCY]
const char * func[AST_MAX_REENTRANCY]
Structure for mutex and tracking information.
Support for dynamic strings.
String vector definitions.
Structure used for base64 encoding.
unsigned char iobuf[BASEMAXINLINE]
void *(* start_routine)(void *)
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Time-related functions and macros.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
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.
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
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.
int ast_base64_encode_file(FILE *inputfile, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
int ast_base64decode(unsigned char *dst, const char *src, int max)
decode BASE64 encoded text
int ast_check_command_in_path(const char *cmd)
Test for the presence of an executable command in $PATH.
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.
static char base64url[64]
static int dev_urandom_fd
int ast_xml_escape(const char *string, char *const outbuf, const size_t buflen)
Escape reserved characters for use in XML.
static struct ast_threadstorage thread_user_interface_tl
char * ast_base64url_encode_string(const char *src)
Encode string in base64 URL.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
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.
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, const char *file, int lineno, const char *function)
int ast_background_stacksize(void)
char * ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
Resolve a binary to a full pathname.
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
void ast_set_default_eid(struct ast_eid *eid)
Fill in an ast_eid with the default eid of this machine.
int ast_thread_user_interface_set(int is_user_interface)
Set the current thread's user interface status.
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
static void * dummy_start(void *data)
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
char * ast_unescape_c(char *src)
Convert some C escape sequences.
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
int ast_wait_for_input(int fd, int ms)
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
char * ast_base64decode_string(const char *src)
Decode BASE64 encoded text and return the string.
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
static void utils_shutdown(void)
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
get values from config variables.
char * ast_unescape_semicolon(char *s)
Strip backslash for "escaped" semicolons, the string to be stripped (will be modified).
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
char * ast_base64encode_string(const char *src)
Encode to BASE64 and return encoded string.
char * ast_escape_c(char *dest, const char *s, size_t size)
Escape standard 'C' sequences in the given string.
int ast_get_tid(void)
Get current thread ID.
char * ast_strsep(char **iss, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
long int ast_random(void)
static void base64_init(void)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
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.
char * ast_escape_alloc(const char *s, const char *to_escape)
Escape the 'to_escape' characters in the given string.
const struct ast_flags ast_uri_http
int ast_wait_for_output(int fd, int ms)
static char * escape_alloc(const char *s, size_t *size)
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
int ast_base64url_decode(unsigned char *dst, const char *src, int max)
Decode data from base64 URL.
int ast_compare_versions(const char *version1, const char *version2)
Compare 2 major.minor.patch.extra version strings.
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.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64 URL.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
char * ast_process_quotes_and_slashes(char *start, char find, char replace_with)
Process a string to find and replace characters.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
static int safe_mkdir(const char *base_path, char *path, int mode)
char * ast_escape_semicolons(const char *string, char *outbuf, int buflen)
Escape semicolons found in a string.
int ast_false(const char *s)
Make sure something is false. Determine if a string containing a boolean value is "false"....
static char escape_sequences_map[]
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
encode text to BASE64 coding
int ast_true(const char *s)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static struct ast_threadstorage inet_ntoa_buf
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
Produce a 20 byte SHA1 hash of value.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static int ochar(struct baseio *bio, int c, FILE *so, const char *endl)
utility used by base_encode()
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
char * ast_base64url_decode_string(const char *src)
Decode string from base64 URL.
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
const char * ast_inet_ntoa(struct in_addr ia)
ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
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.
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 ...
static struct timeval tvfix(struct timeval a)
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
const struct ast_flags ast_uri_sip_user
void ast_md5_hash(char *output, const char *input)
Produce 32 char MD5 hash of value.
int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
void ast_sha1_hash(char *output, const char *input)
Produce 40 char SHA1 hash of value.
int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn)
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".
const struct ast_flags ast_uri_http_legacy
static int wait_for_output(int fd, int timeoutms)
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.
char * ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
Escape the 'to_escape' characters in the given string.
static ast_mutex_t randomlock
#define ast_test_flag(p, flag)
#define AST_URI_LEGACY_SPACE
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_URI_SIP_USER_UNRESERVED
#define DO_CRASH_NORETURN
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
#define AST_URI_UNRESERVED
#define AST_STACKSIZE_LOW
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
void ast_register_thread(char *name)
void ast_unregister_thread(void *id)
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.