35 #include <sys/syscall.h>
37 #if defined(__APPLE__)
38 #include <mach/mach.h>
39 #elif defined(__FreeBSD__)
41 #elif defined(__NetBSD__)
48 #define AST_API_MODULE
52 #include "asterisk/sha1.h"
57 #define AST_API_MODULE
60 #define AST_API_MODULE
63 #define AST_API_MODULE
66 #define AST_API_MODULE
69 #define AST_API_MODULE
72 #define AST_API_MODULE
73 #include "asterisk/alertpipe.h"
80 static char base64[64];
81 static char base64url[64];
83 static char b2a_url[256];
87 #if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
92 AST_MUTEX_DEFINE_STATIC(__mutex);
99 static int gethostbyname_r (
const char *name,
struct hostent *ret,
char *buf,
100 size_t buflen,
struct hostent **result,
105 ast_mutex_lock(&__mutex);
108 ph = gethostbyname(name);
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) {
139 ast_mutex_unlock(&__mutex);
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);
188 ast_mutex_unlock(&__mutex);
190 return (*result == NULL);
201 #ifndef HAVE_GETHOSTBYNAME_R_5
207 struct hostent *result = NULL;
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];
258 MD5Update(&md5, (
const unsigned char *) input, strlen(input));
259 MD5Final(digest, &md5);
261 for (x = 0; x < 16; x++)
262 ptr += sprintf(ptr,
"%02hhx", digest[x]);
271 uint8_t Message_Digest[20];
275 SHA1Input(&sha, (
const unsigned char *) input, strlen(input));
279 for (x = 0; x < 20; x++)
280 ptr += sprintf(ptr,
"%02hhx", Message_Digest[x]);
290 SHA1Input(&sha, (
const unsigned char *) input, strlen(input));
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;
330 if (ast_strlen_zero(src)) {
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;
417 if (ast_strlen_zero(src)) {
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;
455 if (ast_strlen_zero(src)) {
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)) {
486 *dst++ = base64url[(byte >> 18) & 0x3f];
487 *dst++ = base64url[(byte >> 12) & 0x3f];
488 *dst++ = base64url[(byte >> 6) & 0x3f];
489 *dst++ = base64url[(byte) & 0x3f];
495 if (linebreaks && (cnt < max) && (col == 64)) {
501 if (bits && (cnt + 4 <= max)) {
503 *dst++ = base64url[(byte >> 18) & 0x3f];
504 *dst++ = base64url[(byte >> 12) & 0x3f];
506 *dst++ = base64url[(byte >> 6) & 0x3f];
510 if (linebreaks && (cnt < max)) {
526 char *encoded_string;
528 if (ast_strlen_zero(src)) {
532 encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;
537 return encoded_string;
540 static void base64_init(
void)
543 memset(b2a, -1,
sizeof(b2a));
544 memset(b2a_url, -1,
sizeof(b2a_url));
546 for (x = 0; x < 26; x++) {
549 base64url[x] =
'A' + x;
551 b2a_url[
'A' + x] = x;
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;
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;
571 b2a_url[(int)
'-'] = 62;
572 b2a_url[(int)
'_'] = 63;
575 #define BASELINELEN 72
576 #define BASEMAXINLINE 256
617 if (bio->iocp >= bio->iolen) {
618 if (!
inbuf(bio, fi)) {
623 return bio->iobuf[bio->iocp++];
629 static int ochar(
struct baseio *bio,
int c, FILE *so,
const char *endl)
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"))) {
708 ast_log(AST_LOG_WARNING,
"Failed to open file: %s: %s\n", filename, strerror(errno));
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};
725 const char *ptr = string;
727 const char *mark =
"-_.!~*'()";
728 const char *user_unreserved =
"&=+$,;?/";
730 while (*ptr && out - outbuf < buflen - 1) {
731 if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *ptr ==
' ') {
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))) {
744 if (out - outbuf >= buflen - 3) {
747 out += sprintf(out,
"%%%02hhX", (
unsigned char) *ptr);
767 for (o = s; *s; s++, o++) {
768 if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *s ==
'+') {
771 }
else if (*s ==
'%' && s[1] !=
'\0' && s[2] !=
'\0' && sscanf(s + 1,
"%2x", &tmp) == 1) {
783 const char *ptr = string;
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);
813 const char *ptr = string;
816 if (
string == NULL || outbuf == NULL) {
817 ast_assert(
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;
910 ast_assert(len == strlen(entity));
911 if (end - dst < len) {
924 return *
string ==
'\0' ? 0 : -1;
935 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
938 static int dev_urandom_fd = -1;
941 #undef pthread_create
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
962 struct 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;
978 enum ast_lock_type type;
986 } locks[AST_MAX_LOCKS];
990 unsigned int num_locks;
995 pthread_mutex_t
lock;
1002 AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
1013 static
void lock_info_destroy(
void *data)
1015 struct thr_lock_info *lock_info = data;
1018 pthread_mutex_lock(&lock_infos_lock.mutex);
1020 pthread_mutex_unlock(&lock_infos_lock.mutex);
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",
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
1041 pthread_mutex_destroy(&lock_info->lock);
1042 if (lock_info->thread_name) {
1043 ast_free((
void *) lock_info->thread_name);
1045 ast_free(lock_info);
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)
1057 #if !defined(LOW_MEMORY)
1058 struct thr_lock_info *lock_info;
1064 pthread_mutex_lock(&lock_info->lock);
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();
1072 lock_info->locks[i].backtrace = bt;
1074 pthread_mutex_unlock(&lock_info->lock);
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);
1083 pthread_mutex_unlock(&lock_info->lock);
1087 if (i && lock_info->locks[i - 1].pending == -1) {
1092 lock_info->num_locks--;
1093 memset(&lock_info->locks[i], 0,
sizeof(lock_info->locks[0]));
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;
1107 lock_info->locks[i].backtrace = bt;
1109 lock_info->num_locks++;
1111 pthread_mutex_unlock(&lock_info->lock);
1115 void ast_mark_lock_acquired(
void *lock_addr)
1117 #if !defined(LOW_MEMORY)
1118 struct thr_lock_info *lock_info;
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;
1127 pthread_mutex_unlock(&lock_info->lock);
1131 void ast_mark_lock_failed(
void *lock_addr)
1133 #if !defined(LOW_MEMORY)
1134 struct thr_lock_info *lock_info;
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();
1145 pthread_mutex_unlock(&lock_info->lock);
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)
1151 #if !defined(LOW_MEMORY)
1152 struct thr_lock_info *lock_info;
1158 pthread_mutex_lock(&lock_info->lock);
1160 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1161 if (lock_info->locks[i].lock_addr == lock_addr)
1167 pthread_mutex_unlock(&lock_info->lock);
1172 *lineno = lock_info->locks[i].line_num;
1174 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
1176 pthread_mutex_unlock(&lock_info->lock);
1184 void ast_suspend_lock_info(
void *lock_addr)
1186 #if !defined(LOW_MEMORY)
1187 struct thr_lock_info *lock_info;
1194 pthread_mutex_lock(&lock_info->lock);
1196 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1197 if (lock_info->locks[i].lock_addr == lock_addr)
1203 pthread_mutex_unlock(&lock_info->lock);
1207 lock_info->locks[i].suspended = 1;
1209 pthread_mutex_unlock(&lock_info->lock);
1213 void ast_restore_lock_info(
void *lock_addr)
1215 #if !defined(LOW_MEMORY)
1216 struct thr_lock_info *lock_info;
1222 pthread_mutex_lock(&lock_info->lock);
1224 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1225 if (lock_info->locks[i].lock_addr == lock_addr)
1231 pthread_mutex_unlock(&lock_info->lock);
1235 lock_info->locks[i].suspended = 0;
1237 pthread_mutex_unlock(&lock_info->lock);
1242 void ast_remove_lock_info(
void *lock_addr,
struct ast_bt *bt)
1244 #if !defined(LOW_MEMORY)
1245 struct thr_lock_info *lock_info;
1251 pthread_mutex_lock(&lock_info->lock);
1253 for (i = lock_info->num_locks - 1; i >= 0; i--) {
1254 if (lock_info->locks[i].lock_addr == lock_addr)
1260 pthread_mutex_unlock(&lock_info->lock);
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();
1268 lock_info->locks[i].backtrace = bt;
1270 pthread_mutex_unlock(&lock_info->lock);
1274 if (i < lock_info->num_locks - 1) {
1276 memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
1277 (lock_info->num_locks - (i + 1)) *
sizeof(lock_info->locks[0]));
1280 lock_info->num_locks--;
1282 pthread_mutex_unlock(&lock_info->lock);
1286 #if !defined(LOW_MEMORY)
1287 static const char *locktype2str(
enum ast_lock_type type)
1302 static void append_backtrace_information(
struct ast_str **str,
struct ast_bt *bt)
1315 if ((symbols = ast_bt_get_symbols(bt->
addresses, num_frames))) {
1318 for (frame_iterator = 1; frame_iterator <
AST_VECTOR_SIZE(symbols); ++frame_iterator) {
1322 ast_bt_free_symbols(symbols);
1324 ast_str_append(str, 0,
"\tCouldn't retrieve backtrace symbols\n");
1329 static 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];
1338 held_for =
ast_tvsub(now, lock_info->locks[i].last_locked);
1341 lock_time,
sizeof(lock_time));
1343 unlock_time,
sizeof(unlock_time));
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,
1357 lock_info->locks[i].last_locked.tv_usec,
1359 lock_info->locks[i].last_unlocked.tv_usec,
1362 lock_info->locks[i].times_locked,
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);
1369 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
1373 if (lock_info->locks[i].type != AST_MUTEX)
1376 lock = lock_info->locks[i].lock_addr;
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]);
1383 ast_reentrancy_unlock(lt);
1406 void ast_log_show_lock(
void *this_lock_addr)
1408 #if !defined(LOW_MEMORY)
1409 struct thr_lock_info *lock_info;
1413 ast_log(LOG_NOTICE,
"Could not create str\n");
1418 pthread_mutex_lock(&lock_infos_lock.mutex);
1421 pthread_mutex_lock(&lock_info->lock);
1422 for (i = 0; str && i < lock_info->num_locks; i++) {
1425 if (lock_info->locks[i].lock_addr == this_lock_addr) {
1426 append_lock_information(&str, lock_info, i);
1431 pthread_mutex_unlock(&lock_info->lock);
1433 pthread_mutex_unlock(&lock_infos_lock.mutex);
1439 struct ast_str *ast_dump_locks(
void)
1441 #if !defined(LOW_MEMORY)
1442 struct thr_lock_info *lock_info;
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"
1466 pthread_mutex_lock(&lock_infos_lock.mutex);
1469 int header_printed = 0;
1470 pthread_mutex_lock(&lock_info->lock);
1471 for (i = 0; str && i < lock_info->num_locks; i++) {
1473 if (lock_info->locks[i].suspended) {
1477 if (!header_printed) {
1478 if (lock_info->lwp != -1) {
1480 (
long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
1483 (
long unsigned) lock_info->thread_id, lock_info->thread_name);
1488 append_lock_information(&str, lock_info, i);
1490 pthread_mutex_unlock(&lock_info->lock);
1494 if (header_printed) {
1495 ast_str_append(&str, 0,
"=== -------------------------------------------------------------------\n"
1502 pthread_mutex_unlock(&lock_infos_lock.mutex);
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 *);
1573 static void *dummy_start(
void *data)
1577 #ifdef DEBUG_THREADS
1578 struct thr_lock_info *lock_info;
1579 pthread_mutexattr_t mutex_attr;
1584 lock_info->thread_id = pthread_self();
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);
1593 pthread_mutex_lock(&lock_infos_lock.mutex);
1595 pthread_mutex_unlock(&lock_infos_lock.mutex);
1604 ast_register_thread(a.name);
1605 pthread_cleanup_push(ast_unregister_thread, (
void *) pthread_self());
1607 ret = a.start_routine(a.data);
1609 pthread_cleanup_pop(1);
1616 int ast_background_stacksize(
void)
1618 #if !defined(LOW_MEMORY)
1619 return AST_STACKSIZE;
1621 return AST_STACKSIZE_LOW;
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)
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)))
1647 ast_log(LOG_WARNING,
"pthread_attr_setinheritsched: %s\n", strerror(errno));
1651 stacksize = AST_STACKSIZE;
1653 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
1654 ast_log(LOG_WARNING,
"pthread_attr_setstacksize: %s\n", strerror(errno));
1656 #if !defined(LOW_MEMORY)
1658 a->start_routine = start_routine;
1660 start_routine = dummy_start;
1661 if (
ast_asprintf(&a->name,
"%-20s started at [%5d] %s %s()",
1662 start_fn, line, file, caller) < 0) {
1669 return pthread_create(thread, attr, start_routine, data);
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)
1677 unsigned char attr_destroy = 0;
1682 pthread_attr_init(attr);
1686 if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1687 ast_log(LOG_WARNING,
"pthread_attr_setdetachstate: %s\n", strerror(errno));
1689 res = ast_pthread_create_stack(thread, attr, start_routine, data,
1690 stacksize, file, caller, line, start_fn);
1693 pthread_attr_destroy(attr);
1698 int ast_wait_for_input(
int fd,
int ms)
1700 struct pollfd pfd[1];
1702 memset(pfd, 0,
sizeof(pfd));
1704 pfd[0].events = POLLIN | POLLPRI;
1705 return ast_poll(pfd, 1, ms);
1708 int ast_wait_for_output(
int fd,
int ms)
1710 struct pollfd pfd[1];
1712 memset(pfd, 0,
sizeof(pfd));
1714 pfd[0].events = POLLOUT;
1715 return ast_poll(pfd, 1, ms);
1718 static int wait_for_output(
int fd,
int timeoutms)
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) {
1739 if (errno == EINTR || errno == EAGAIN) {
1741 if (elapsed >= timeoutms) {
1749 ast_log(LOG_ERROR,
"poll returned error: %s\n", strerror(errno));
1754 if (elapsed >= timeoutms) {
1778 if (wait_for_output(fd, timeoutms - elapsed)) {
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));
1791 ast_log(LOG_ERROR,
"write() returned error: %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))) {
1843 if (ast_strlen_zero(st)) {
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) {
1887 if (!ast_strlen_zero(trimmed)) {
1906 const char qstr[] = { quote };
1908 if (ast_strlen_zero(st)) {
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) {
1952 if (!ast_strlen_zero(trimmed)) {
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++)) {
2022 char escape_sequences[] = {
2023 '\a',
'\b',
'\f',
'\n',
'\r',
'\t',
'\v',
'\\',
'\'',
'\"',
'\?',
'\0'
2030 static char escape_sequences_map[] = {
2031 'a',
'b',
'f',
'n',
'r',
't',
'v',
'\\',
'\'',
'"',
'?',
'\0'
2034 char *
ast_escape(
char *dest,
const char *s,
size_t size,
const char *to_escape)
2039 if (!dest || !size) {
2042 if (ast_strlen_zero(s)) {
2047 if (ast_strlen_zero(to_escape)) {
2052 for (p = dest; *s && --size; ++s, ++p) {
2054 if (strchr(to_escape, *s)) {
2065 c = strchr(escape_sequences, *s);
2067 *p = c ? escape_sequences_map[c - escape_sequences] : *s;
2087 if (!dest || !size) {
2090 if (ast_strlen_zero(s)) {
2095 for (p = dest; *s && --size; ++s, ++p) {
2100 c = strchr(escape_sequences, *s);
2108 *p = escape_sequences_map[c - escape_sequences];
2118 static char *escape_alloc(
const char *s,
size_t *size)
2128 *size = strlen(s) * 2 + 1;
2135 char *dest = escape_alloc(s, &size);
2143 char *dest = escape_alloc(s, &size);
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] ==
'/')) {
2201 if (ast_strlen_zero(s))
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"))
2218 if (ast_strlen_zero(s))
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
2238 static struct timeval tvfix(struct timeval a)
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);
2253 struct timeval
ast_tvadd(struct timeval a, struct timeval b)
2258 a.tv_sec += b.tv_sec;
2259 a.tv_usec += b.tv_usec;
2260 if (a.tv_usec >= ONE_MILLION) {
2262 a.tv_usec -= ONE_MILLION;
2267 struct timeval
ast_tvsub(struct timeval a, struct timeval b)
2272 a.tv_sec -= b.tv_sec;
2273 a.tv_usec -= b.tv_usec;
2274 if (a.tv_usec < 0) {
2276 a.tv_usec += ONE_MILLION;
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);
2309 AST_MUTEX_DEFINE_STATIC(randomlock);
2312 long int ast_random(
void)
2316 if (dev_urandom_fd >= 0) {
2317 int read_res = read(dev_urandom_fd, &res,
sizeof(res));
2319 long int rm = RAND_MAX;
2320 res = res < 0 ? ~res : res;
2336 ast_mutex_lock(&randomlock);
2338 ast_mutex_unlock(&randomlock);
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)
2378 void ast_join_delim(
char *s,
size_t len,
const char *
const w[],
unsigned int size,
char delim)
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);
2419 int ast_get_timeval(
const char *src,
struct timeval *dst,
struct timeval _default,
int *consumed)
2421 long double dtv = 0.0;
2429 if (ast_strlen_zero(src))
2433 if (sscanf(src,
"%30Lf%n", &dtv, &scanned) > 0) {
2435 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2437 *consumed = scanned;
2456 if (ast_strlen_zero(src))
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)
2514 static int safe_mkdir(
const char *base_path,
char *path,
int mode)
2516 RAII_VAR(
char *, absolute_path, NULL, ast_std_free);
2518 absolute_path = realpath(path, NULL);
2520 if (absolute_path) {
2532 char *path_term = strchr(path,
'/');
2534 int parent_is_safe = 0;
2538 RAII_VAR(
char *, absolute_subpath, NULL, ast_std_free);
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);
2554 ast_assert(errno != EEXIST);
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) {
2586 RAII_VAR(
char *, absolute_base_path, NULL, ast_std_free);
2587 RAII_VAR(
char *, p, NULL, ast_free);
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);
2608 static void utils_shutdown(
void)
2610 close(dev_urandom_fd);
2611 dev_urandom_fd = -1;
2612 #if defined(DEBUG_THREADS) && !defined(LOW_MEMORY)
2617 int ast_utils_init(
void)
2619 dev_urandom_fd = open(
"/dev/urandom", O_RDONLY);
2621 #ifdef DEBUG_THREADS
2622 #if !defined(LOW_MEMORY)
2645 const ast_string_field *field;
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 },
2662 if (ast_strlen_zero(digest) || !d || !str) {
2671 if (strncasecmp(c,
"Digest ", strlen(
"Digest "))) {
2672 ast_log(LOG_WARNING,
"Missing Digest.\n");
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);
2698 strsep(&c, separator);
2706 if (!strcasecmp(i->key,
"algorithm=")) {
2707 if (strcasecmp(src,
"MD5")) {
2708 ast_log(LOG_WARNING,
"Digest algorithm: \"%s\" not supported.\n", src);
2712 }
else if (!strcasecmp(i->key,
"qop=") && !strcasecmp(src,
"auth")) {
2714 }
else if (!strcasecmp(i->key,
"nc=")) {
2716 if (sscanf(src,
"%30lx", &u) != 1) {
2717 ast_log(LOG_WARNING,
"Incorrect Digest nc value: \"%s\".\n", src);
2726 if (i->key == NULL) {
2733 if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
2740 if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
2744 if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
2755 #if defined (__linux) && defined(SYS_gettid)
2756 ret = syscall(SYS_gettid);
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__)
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)
2816 void DO_CRASH_NORETURN __ast_assert_failed(
int condition,
const char *condition_str,
const char *file,
int line,
const char *
function)
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);
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__)
2858 #include <ifaddrs.h>
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);
2874 ast_log(LOG_WARNING,
"No ethernet interface found for seeding global EID. "
2875 "You will have to set it manually.\n");
2880 ast_log(LOG_WARNING,
"No ethernet interface found for seeding global EID. "
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);
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);
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);
2932 ast_log(LOG_WARNING,
"Unable to open a socket for seeding global EID. "
2933 " You will have to set it manually.\n");
2938 ifn.lifn_family = AF_UNSPEC;
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");
2948 bufsz = ifn.lifn_count *
sizeof(
struct lifreq);
2950 ast_log(LOG_WARNING,
"Unable to allocate memory for seeding global EID. "
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) {
2963 ast_log(LOG_WARNING,
"No ethernet interface found for seeding global EID. "
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",
2992 ast_log(LOG_WARNING,
"No ethernet interface found for seeding global EID. "
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);
3016 ast_log(LOG_WARNING,
"Unable to open socket for seeding global EID. "
3017 "You will have to set it manually.\n");
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");
3029 bufsz = ifc.ifc_len;
3032 ast_log(LOG_WARNING,
"Unable to allocate memory for seeding global EID. "
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",
3068 ast_log(LOG_WARNING,
"No ethernet interface found for seeding global EID. "
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));
3103 memset(&empty_eid, 0,
sizeof(empty_eid));
3104 return memcmp(eid, &empty_eid,
sizeof(empty_eid)) ? 0 : 1;
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];
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)
3155 f = fcntl(fd, F_GETFL);
3157 ast_log(__LOG_ERROR, file, lineno,
function,
3158 "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
3163 case AST_FD_FLAG_SET:
3164 if ((f & flags) == flags) {
3170 case AST_FD_FLAG_CLEAR:
3182 f = fcntl(fd, F_SETFL, f);
3184 ast_log(__LOG_ERROR, file, lineno,
function,
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;
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");
3244 *thread_user_interface = !!is_user_interface;
3250 int *thread_user_interface;
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");
3260 return *thread_user_interface;
3265 char *token, *saveptr, *path = getenv(
"PATH");
3266 char filename[PATH_MAX];
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);
3286 if (access(filename, X_OK) == 0) {
3291 token = strtok_r(NULL,
":", &saveptr);
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 ...
#define ast_string_field_ptr_set(x, ptr, data)
Set a field to a simple string value.
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.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
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_check_ipv6(void)
Test that an OS supports IPv6 Networking.
void ast_set_default_eid(struct ast_eid *eid)
Fill in an ast_eid with the default eid of this machine.
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
get values from config variables.
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.
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. ...
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.
Asterisk version information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
Time-related functions and macros.
void ast_md5_hash(char *output, const char *input)
Produce 32 char MD5 hash of value.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
descriptor for a cli entry.
char * ast_escape(char *dest, const char *s, size_t size, const char *to_escape)
Escape the 'to_escape' characters in the given string.
int ast_base64decode(unsigned char *dst, const char *src, int max)
decode BASE64 encoded text
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Structure used for base64 encoding.
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
int ast_thread_user_interface_set(int is_user_interface)
Set the current thread's user interface status.
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_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
char * ast_base64url_decode_string(const char *src)
Decode string from base64 URL.
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
int SHA1Result(SHA1Context *context, uint8_t Message_Digest[SHA1HashSize])
SHA1Result Returns the resulting 160-bit digest.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
int ast_check_command_in_path(const char *cmd)
Test for the presence of an executable command in $PATH.
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.
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
Produce a 20 byte SHA1 hash of value.
An Entity ID is essentially a MAC address, brief and unique.
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
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_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
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".
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
int SHA1Reset(SHA1Context *context)
SHA1Reset.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
Lock tracking information.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64 URL.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
#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.
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
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.
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
static int ochar(struct baseio *bio, int c, FILE *so, const char *endl)
utility used by base_encode()
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
encode text to BASE64 coding
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
int ast_xml_escape(const char *string, char *const outbuf, const size_t buflen)
Escape reserved characters for use in XML.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Support for dynamic strings.
char * ast_base64encode_string(const char *src)
Encode to BASE64 and return encoded string.
int SHA1Input(SHA1Context *context, const uint8_t *message_array, unsigned length)
SHA1Input.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
int ast_base64url_decode(unsigned char *dst, const char *src, int max)
Decode data from base64 URL.
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
const char * ast_inet_ntoa(struct in_addr ia)
ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_escape_semicolons(const char *string, char *outbuf, int buflen)
Escape semicolons found in a string.
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
char * ast_escape_c(char *dest, const char *s, size_t size)
Escape standard 'C' sequences in the given string.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
void * addresses[AST_MAX_BT_FRAMES]
int ast_base64_encode_file(FILE *inputfile, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
Structure used to handle boolean flags.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
char * ast_base64decode_string(const char *src)
Decode BASE64 encoded text and return the string.
#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).
void ast_sha1_hash(char *output, const char *input)
Produce 40 char SHA1 hash of value.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
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"...
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.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
int ast_get_tid(void)
Get current thread ID.
char * ast_unescape_c(char *src)
Convert some C escape sequences.
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
String vector definitions.
char * ast_base64url_encode_string(const char *src)
Encode string in base64 URL.
int ast_false(const char *s)
Make sure something is false. Determine if a string containing a boolean value is "false"...
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
char * ast_strsep(char **iss, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
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.
char * ast_escape_alloc(const char *s, const char *to_escape)
Escape the 'to_escape' characters in the given string.
char * ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
Resolve a binary to a full pathname.
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.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Structure for mutex and tracking information.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_thread_is_user_interface(void)
Indicates whether the current thread is a user interface.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.