Review Board 1.7.16


clang compiler warning: fixes for tests to be compiled using clang

Review Request #4555 - Created March 29, 2015 and submitted

Diederik de Groot
13
ASTERISK-24917
Reviewers
asterisk-dev
Asterisk
clang's static analyzer will throw quite a number warnings / errors during compilation, some of which can be very helpfull in finding corner-case bugs. 

fixes for tests to be compiled using clang
executing the tests one-by-one works fine (completes to end) (skipping /main/stdtime) -> 
test show results failed:


=================== /main/message/ ====== 
FAIL   test_message_queue_handler_nom /main/message/             31036ms
[test_message.c:int handler_wait_for_message(struct ast_test *):244]: Test timed out while waiting for handler to get message

Not sure if this is actually a fail or just a timeout. WIP


=================== /main/strings/ ====== 
FAIL   escape_semicolons              /main/strings/             1ms     
[Mar 29 20:13:43] ERROR[2521]: utils.c:493 char *ast_escape_semicolons(const char *, char *, int): FRACK!, Failed assertion string != NULL && outbuf != NULL (0)
-> explainable by the change made to the source. ast_alloca(0) is not being executed -> test2 = NULL: need to resolv the open question how to handle ast_alloca(0) before making any further changes.

(With revision 5 of this code, this test now passes without a problem, had to fix both the test and the function being tested though)


=================== /main/stdtime ====== 
"test execute all" fails, caused by the /main/stdtime/ test. 
START  /main/stdtime/ - timezone_watch 
[test_time.c:enum ast_test_result_state test_timezone_watch(struct ast_test_info *, enum ast_test_command, struct ast_test *):84]: Executing deletion test...
j62747*CLI> 
CLI becomes unresponsive / no further command completion for example.
Guess this will need a little further investigation. Maybe the source changes made to main/stdtime/ where not completely correct.

Seems to be caused by inotify_daemon, at least there is where the segfault happens. WIP
<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" time="181.742" tests="444" n
<properties>
<property name="version" value="SV

Changes between revision 5 and 6

1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9

  1. /branches/13/main/utils.c: Loading...
  2. /branches/13/tests/test_acl.c: Loading...
  3. /branches/13/tests/test_linkedlists.c: Loading...
  4. /branches/13/tests/test_stringfields.c: Loading...
  5. /branches/13/tests/test_strings.c: Loading...
/branches/13/main/utils.c
Diff Revision 5 Diff Revision 6 - File Reverted
1
/*
1
/*
2
 * Asterisk -- An open source telephony toolkit.
2
 * Asterisk -- An open source telephony toolkit.
3
 *
3
 *
4
 * Copyright (C) 1999 - 2006, Digium, Inc.
4
 * Copyright (C) 1999 - 2006, Digium, Inc.
5
 *
5
 *
6
 * See http://www.asterisk.org for more information about
6
 * See http://www.asterisk.org for more information about
7
 * the Asterisk project. Please do not directly contact
7
 * the Asterisk project. Please do not directly contact
8
 * any of the maintainers of this project for assistance;
8
 * any of the maintainers of this project for assistance;
9
 * the project provides a web site, mailing lists and IRC
9
 * the project provides a web site, mailing lists and IRC
10
 * channels for your use.
10
 * channels for your use.
11
 *
11
 *
12
 * This program is free software, distributed under the terms of
12
 * This program is free software, distributed under the terms of
13
 * the GNU General Public License Version 2. See the LICENSE file
13
 * the GNU General Public License Version 2. See the LICENSE file
14
 * at the top of the source tree.
14
 * at the top of the source tree.
15
 */
15
 */
16

    
   
16

   
17
/*! \file
17
/*! \file
18
 *
18
 *
19
 * \brief Utility functions
19
 * \brief Utility functions
20
 *
20
 *
21
 * \note These are important for portability and security,
21
 * \note These are important for portability and security,
22
 * so please use them in favour of other routines.
22
 * so please use them in favour of other routines.
23
 * Please consult the CODING GUIDELINES for more information.
23
 * Please consult the CODING GUIDELINES for more information.
24
 */
24
 */
25

    
   
25

   
26
/*** MODULEINFO
26
/*** MODULEINFO
27
	<support_level>core</support_level>
27
	<support_level>core</support_level>
28
 ***/
28
 ***/
29

    
   
29

   
30
#include "asterisk.h"
30
#include "asterisk.h"
31

    
   
31

   
32
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33

    
   
33

   
34
#include <ctype.h>
34
#include <ctype.h>
35
#include <fcntl.h>
35
#include <fcntl.h>
36
#include <sys/stat.h>
36
#include <sys/stat.h>
37
#include <sys/syscall.h>
37
#include <sys/syscall.h>
38
#include <unistd.h>
38
#include <unistd.h>
39
#if defined(__APPLE__)
39
#if defined(__APPLE__)
40
#include <mach/mach.h>
40
#include <mach/mach.h>
41
#elif defined(HAVE_SYS_THR_H)
41
#elif defined(HAVE_SYS_THR_H)
42
#include <sys/thr.h>
42
#include <sys/thr.h>
43
#endif
43
#endif
44

    
   
44

   
45
#include "asterisk/network.h"
45
#include "asterisk/network.h"
46
#include "asterisk/ast_version.h"
46
#include "asterisk/ast_version.h"
47

    
   
47

   
48
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in lock.h if required */
48
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in lock.h if required */
49
#include "asterisk/lock.h"
49
#include "asterisk/lock.h"
50
#include "asterisk/io.h"
50
#include "asterisk/io.h"
51
#include "asterisk/md5.h"
51
#include "asterisk/md5.h"
52
#include "asterisk/sha1.h"
52
#include "asterisk/sha1.h"
53
#include "asterisk/cli.h"
53
#include "asterisk/cli.h"
54
#include "asterisk/linkedlists.h"
54
#include "asterisk/linkedlists.h"
55
#include "asterisk/astobj2.h"
55
#include "asterisk/astobj2.h"
56

    
   
56

   
57
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
57
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
58
#include "asterisk/strings.h"
58
#include "asterisk/strings.h"
59

    
   
59

   
60
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
60
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
61
#include "asterisk/time.h"
61
#include "asterisk/time.h"
62

    
   
62

   
63
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
63
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
64
#include "asterisk/stringfields.h"
64
#include "asterisk/stringfields.h"
65

    
   
65

   
66
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
66
#define AST_API_MODULE		/* ensure that inlinable API functions will be built in this module if required */
67
#include "asterisk/utils.h"
67
#include "asterisk/utils.h"
68

    
   
68

   
69
#define AST_API_MODULE
69
#define AST_API_MODULE
70
#include "asterisk/threadstorage.h"
70
#include "asterisk/threadstorage.h"
71

    
   
71

   
72
#define AST_API_MODULE
72
#define AST_API_MODULE
73
#include "asterisk/config.h"
73
#include "asterisk/config.h"
74

    
   
74

   
75
static char base64[64];
75
static char base64[64];
76
static char b2a[256];
76
static char b2a[256];
77

    
   
77

   
78
AST_THREADSTORAGE(inet_ntoa_buf);
78
AST_THREADSTORAGE(inet_ntoa_buf);
79

    
   
79

   
80
#if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
80
#if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
81

    
   
81

   
82
#define ERANGE 34	/*!< duh? ERANGE value copied from web... */
82
#define ERANGE 34	/*!< duh? ERANGE value copied from web... */
83
#undef gethostbyname
83
#undef gethostbyname
84

    
   
84

   
85
AST_MUTEX_DEFINE_STATIC(__mutex);
85
AST_MUTEX_DEFINE_STATIC(__mutex);
86

    
   
86

   
87
/*! \brief Reentrant replacement for gethostbyname for BSD-based systems.
87
/*! \brief Reentrant replacement for gethostbyname for BSD-based systems.
88
\note This
88
\note This
89
routine is derived from code originally written and placed in the public
89
routine is derived from code originally written and placed in the public
90
domain by Enzo Michelangeli <em@em.no-ip.com> */
90
domain by Enzo Michelangeli <em@em.no-ip.com> */
91

    
   
91

   
92
static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
92
static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
93
				size_t buflen, struct hostent **result,
93
				size_t buflen, struct hostent **result,
94
				int *h_errnop)
94
				int *h_errnop)
95
{
95
{
96
	int hsave;
96
	int hsave;
97
	struct hostent *ph;
97
	struct hostent *ph;
98
	ast_mutex_lock(&__mutex); /* begin critical area */
98
	ast_mutex_lock(&__mutex); /* begin critical area */
99
	hsave = h_errno;
99
	hsave = h_errno;
100

    
   
100

   
101
	ph = gethostbyname(name);
101
	ph = gethostbyname(name);
102
	*h_errnop = h_errno; /* copy h_errno to *h_herrnop */
102
	*h_errnop = h_errno; /* copy h_errno to *h_herrnop */
103
	if (ph == NULL) {
103
	if (ph == NULL) {
104
		*result = NULL;
104
		*result = NULL;
105
	} else {
105
	} else {
106
		char **p, **q;
106
		char **p, **q;
107
		char *pbuf;
107
		char *pbuf;
108
		int nbytes = 0;
108
		int nbytes = 0;
109
		int naddr = 0, naliases = 0;
109
		int naddr = 0, naliases = 0;
110
		/* determine if we have enough space in buf */
110
		/* determine if we have enough space in buf */
111

    
   
111

   
112
		/* count how many addresses */
112
		/* count how many addresses */
113
		for (p = ph->h_addr_list; *p != 0; p++) {
113
		for (p = ph->h_addr_list; *p != 0; p++) {
114
			nbytes += ph->h_length; /* addresses */
114
			nbytes += ph->h_length; /* addresses */
115
			nbytes += sizeof(*p); /* pointers */
115
			nbytes += sizeof(*p); /* pointers */
116
			naddr++;
116
			naddr++;
117
		}
117
		}
118
		nbytes += sizeof(*p); /* one more for the terminating NULL */
118
		nbytes += sizeof(*p); /* one more for the terminating NULL */
119

    
   
119

   
120
		/* count how many aliases, and total length of strings */
120
		/* count how many aliases, and total length of strings */
121
		for (p = ph->h_aliases; *p != 0; p++) {
121
		for (p = ph->h_aliases; *p != 0; p++) {
122
			nbytes += (strlen(*p)+1); /* aliases */
122
			nbytes += (strlen(*p)+1); /* aliases */
123
			nbytes += sizeof(*p);  /* pointers */
123
			nbytes += sizeof(*p);  /* pointers */
124
			naliases++;
124
			naliases++;
125
		}
125
		}
126
		nbytes += sizeof(*p); /* one more for the terminating NULL */
126
		nbytes += sizeof(*p); /* one more for the terminating NULL */
127

    
   
127

   
128
		/* here nbytes is the number of bytes required in buffer */
128
		/* here nbytes is the number of bytes required in buffer */
129
		/* as a terminator must be there, the minimum value is ph->h_length */
129
		/* as a terminator must be there, the minimum value is ph->h_length */
130
		if (nbytes > buflen) {
130
		if (nbytes > buflen) {
131
			*result = NULL;
131
			*result = NULL;
132
			ast_mutex_unlock(&__mutex); /* end critical area */
132
			ast_mutex_unlock(&__mutex); /* end critical area */
133
			return ERANGE; /* not enough space in buf!! */
133
			return ERANGE; /* not enough space in buf!! */
134
		}
134
		}
135

    
   
135

   
136
		/* There is enough space. Now we need to do a deep copy! */
136
		/* There is enough space. Now we need to do a deep copy! */
137
		/* Allocation in buffer:
137
		/* Allocation in buffer:
138
			from [0] to [(naddr-1) * sizeof(*p)]:
138
			from [0] to [(naddr-1) * sizeof(*p)]:
139
			pointers to addresses
139
			pointers to addresses
140
			at [naddr * sizeof(*p)]:
140
			at [naddr * sizeof(*p)]:
141
			NULL
141
			NULL
142
			from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
142
			from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
143
			pointers to aliases
143
			pointers to aliases
144
			at [(naddr+naliases+1) * sizeof(*p)]:
144
			at [(naddr+naliases+1) * sizeof(*p)]:
145
			NULL
145
			NULL
146
			then naddr addresses (fixed length), and naliases aliases (asciiz).
146
			then naddr addresses (fixed length), and naliases aliases (asciiz).
147
		*/
147
		*/
148

    
   
148

   
149
		*ret = *ph;   /* copy whole structure (not its address!) */
149
		*ret = *ph;   /* copy whole structure (not its address!) */
150

    
   
150

   
151
		/* copy addresses */
151
		/* copy addresses */
152
		q = (char **)buf; /* pointer to pointers area (type: char **) */
152
		q = (char **)buf; /* pointer to pointers area (type: char **) */
153
		ret->h_addr_list = q; /* update pointer to address list */
153
		ret->h_addr_list = q; /* update pointer to address list */
154
		pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */
154
		pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */
155
		for (p = ph->h_addr_list; *p != 0; p++) {
155
		for (p = ph->h_addr_list; *p != 0; p++) {
156
			memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
156
			memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
157
			*q++ = pbuf; /* the pointer is the one inside buf... */
157
			*q++ = pbuf; /* the pointer is the one inside buf... */
158
			pbuf += ph->h_length; /* advance pbuf */
158
			pbuf += ph->h_length; /* advance pbuf */
159
		}
159
		}
160
		*q++ = NULL; /* address list terminator */
160
		*q++ = NULL; /* address list terminator */
161

    
   
161

   
162
		/* copy aliases */
162
		/* copy aliases */
163
		ret->h_aliases = q; /* update pointer to aliases list */
163
		ret->h_aliases = q; /* update pointer to aliases list */
164
		for (p = ph->h_aliases; *p != 0; p++) {
164
		for (p = ph->h_aliases; *p != 0; p++) {
165
			strcpy(pbuf, *p); /* copy alias strings */
165
			strcpy(pbuf, *p); /* copy alias strings */
166
			*q++ = pbuf; /* the pointer is the one inside buf... */
166
			*q++ = pbuf; /* the pointer is the one inside buf... */
167
			pbuf += strlen(*p); /* advance pbuf */
167
			pbuf += strlen(*p); /* advance pbuf */
168
			*pbuf++ = 0; /* string terminator */
168
			*pbuf++ = 0; /* string terminator */
169
		}
169
		}
170
		*q++ = NULL; /* terminator */
170
		*q++ = NULL; /* terminator */
171

    
   
171

   
172
		strcpy(pbuf, ph->h_name); /* copy alias strings */
172
		strcpy(pbuf, ph->h_name); /* copy alias strings */
173
		ret->h_name = pbuf;
173
		ret->h_name = pbuf;
174
		pbuf += strlen(ph->h_name); /* advance pbuf */
174
		pbuf += strlen(ph->h_name); /* advance pbuf */
175
		*pbuf++ = 0; /* string terminator */
175
		*pbuf++ = 0; /* string terminator */
176

    
   
176

   
177
		*result = ret;  /* and let *result point to structure */
177
		*result = ret;  /* and let *result point to structure */
178

    
   
178

   
179
	}
179
	}
180
	h_errno = hsave;  /* restore h_errno */
180
	h_errno = hsave;  /* restore h_errno */
181
	ast_mutex_unlock(&__mutex); /* end critical area */
181
	ast_mutex_unlock(&__mutex); /* end critical area */
182

    
   
182

   
183
	return (*result == NULL); /* return 0 on success, non-zero on error */
183
	return (*result == NULL); /* return 0 on success, non-zero on error */
184
}
184
}
185

    
   
185

   
186

    
   
186

   
187
#endif
187
#endif
188

    
   
188

   
189
/*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the
189
/*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the
190
   standard gethostbyname (which is not thread safe)
190
   standard gethostbyname (which is not thread safe)
191
*/
191
*/
192
struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
192
struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
193
{
193
{
194
	int res;
194
	int res;
195
	int herrno;
195
	int herrno;
196
	int dots = 0;
196
	int dots = 0;
197
	const char *s;
197
	const char *s;
198
	struct hostent *result = NULL;
198
	struct hostent *result = NULL;
199
	/* Although it is perfectly legitimate to lookup a pure integer, for
199
	/* Although it is perfectly legitimate to lookup a pure integer, for
200
	   the sake of the sanity of people who like to name their peers as
200
	   the sake of the sanity of people who like to name their peers as
201
	   integers, we break with tradition and refuse to look up a
201
	   integers, we break with tradition and refuse to look up a
202
	   pure integer */
202
	   pure integer */
203
	s = host;
203
	s = host;
204
	res = 0;
204
	res = 0;
205
	while (s && *s) {
205
	while (s && *s) {
206
		if (*s == '.')
206
		if (*s == '.')
207
			dots++;
207
			dots++;
208
		else if (!isdigit(*s))
208
		else if (!isdigit(*s))
209
			break;
209
			break;
210
		s++;
210
		s++;
211
	}
211
	}
212
	if (!s || !*s) {
212
	if (!s || !*s) {
213
		/* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
213
		/* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
214
		if (dots != 3)
214
		if (dots != 3)
215
			return NULL;
215
			return NULL;
216
		memset(hp, 0, sizeof(struct ast_hostent));
216
		memset(hp, 0, sizeof(struct ast_hostent));
217
		hp->hp.h_addrtype = AF_INET;
217
		hp->hp.h_addrtype = AF_INET;
218
		hp->hp.h_addr_list = (void *) hp->buf;
218
		hp->hp.h_addr_list = (void *) hp->buf;
219
		hp->hp.h_addr = hp->buf + sizeof(void *);
219
		hp->hp.h_addr = hp->buf + sizeof(void *);
220
		/* For AF_INET, this will always be 4 */
220
		/* For AF_INET, this will always be 4 */
221
		hp->hp.h_length = 4;
221
		hp->hp.h_length = 4;
222
		if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
222
		if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
223
			return &hp->hp;
223
			return &hp->hp;
224
		return NULL;
224
		return NULL;
225

    
   
225

   
226
	}
226
	}
227
#ifdef HAVE_GETHOSTBYNAME_R_5
227
#ifdef HAVE_GETHOSTBYNAME_R_5
228
	result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
228
	result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
229

    
   
229

   
230
	if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
230
	if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
231
		return NULL;
231
		return NULL;
232
#else
232
#else
233
	res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
233
	res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
234

    
   
234

   
235
	if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
235
	if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
236
		return NULL;
236
		return NULL;
237
#endif
237
#endif
238
	return &hp->hp;
238
	return &hp->hp;
239
}
239
}
240

    
   
240

   
241
/*! \brief Produce 32 char MD5 hash of value. */
241
/*! \brief Produce 32 char MD5 hash of value. */
242
void ast_md5_hash(char *output, const char *input)
242
void ast_md5_hash(char *output, const char *input)
243
{
243
{
244
	struct MD5Context md5;
244
	struct MD5Context md5;
245
	unsigned char digest[16];
245
	unsigned char digest[16];
246
	char *ptr;
246
	char *ptr;
247
	int x;
247
	int x;
248

    
   
248

   
249
	MD5Init(&md5);
249
	MD5Init(&md5);
250
	MD5Update(&md5, (const unsigned char *) input, strlen(input));
250
	MD5Update(&md5, (const unsigned char *) input, strlen(input));
251
	MD5Final(digest, &md5);
251
	MD5Final(digest, &md5);
252
	ptr = output;
252
	ptr = output;
253
	for (x = 0; x < 16; x++)
253
	for (x = 0; x < 16; x++)
254
		ptr += sprintf(ptr, "%02hhx", digest[x]);
254
		ptr += sprintf(ptr, "%02hhx", digest[x]);
255
}
255
}
256

    
   
256

   
257
/*! \brief Produce 40 char SHA1 hash of value. */
257
/*! \brief Produce 40 char SHA1 hash of value. */
258
void ast_sha1_hash(char *output, const char *input)
258
void ast_sha1_hash(char *output, const char *input)
259
{
259
{
260
	struct SHA1Context sha;
260
	struct SHA1Context sha;
261
	char *ptr;
261
	char *ptr;
262
	int x;
262
	int x;
263
	uint8_t Message_Digest[20];
263
	uint8_t Message_Digest[20];
264

    
   
264

   
265
	SHA1Reset(&sha);
265
	SHA1Reset(&sha);
266

    
   
266

   
267
	SHA1Input(&sha, (const unsigned char *) input, strlen(input));
267
	SHA1Input(&sha, (const unsigned char *) input, strlen(input));
268

    
   
268

   
269
	SHA1Result(&sha, Message_Digest);
269
	SHA1Result(&sha, Message_Digest);
270
	ptr = output;
270
	ptr = output;
271
	for (x = 0; x < 20; x++)
271
	for (x = 0; x < 20; x++)
272
		ptr += sprintf(ptr, "%02hhx", Message_Digest[x]);
272
		ptr += sprintf(ptr, "%02hhx", Message_Digest[x]);
273
}
273
}
274

    
   
274

   
275
/*! \brief Produce a 20 byte SHA1 hash of value. */
275
/*! \brief Produce a 20 byte SHA1 hash of value. */
276
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
276
void ast_sha1_hash_uint(uint8_t *digest, const char *input)
277
{
277
{
278
        struct SHA1Context sha;
278
        struct SHA1Context sha;
279

    
   
279

   
280
        SHA1Reset(&sha);
280
        SHA1Reset(&sha);
281

    
   
281

   
282
        SHA1Input(&sha, (const unsigned char *) input, strlen(input));
282
        SHA1Input(&sha, (const unsigned char *) input, strlen(input));
283

    
   
283

   
284
        SHA1Result(&sha, digest);
284
        SHA1Result(&sha, digest);
285
}
285
}
286

    
   
286

   
287
/*! \brief decode BASE64 encoded text */
287
/*! \brief decode BASE64 encoded text */
288
int ast_base64decode(unsigned char *dst, const char *src, int max)
288
int ast_base64decode(unsigned char *dst, const char *src, int max)
289
{
289
{
290
	int cnt = 0;
290
	int cnt = 0;
291
	unsigned int byte = 0;
291
	unsigned int byte = 0;
292
	unsigned int bits = 0;
292
	unsigned int bits = 0;
293
	int incnt = 0;
293
	int incnt = 0;
294
	while(*src && *src != '=' && (cnt < max)) {
294
	while(*src && *src != '=' && (cnt < max)) {
295
		/* Shift in 6 bits of input */
295
		/* Shift in 6 bits of input */
296
		byte <<= 6;
296
		byte <<= 6;
297
		byte |= (b2a[(int)(*src)]) & 0x3f;
297
		byte |= (b2a[(int)(*src)]) & 0x3f;
298
		bits += 6;
298
		bits += 6;
299
		src++;
299
		src++;
300
		incnt++;
300
		incnt++;
301
		/* If we have at least 8 bits left over, take that character
301
		/* If we have at least 8 bits left over, take that character
302
		   off the top */
302
		   off the top */
303
		if (bits >= 8)  {
303
		if (bits >= 8)  {
304
			bits -= 8;
304
			bits -= 8;
305
			*dst = (byte >> bits) & 0xff;
305
			*dst = (byte >> bits) & 0xff;
306
			dst++;
306
			dst++;
307
			cnt++;
307
			cnt++;
308
		}
308
		}
309
	}
309
	}
310
	/* Don't worry about left over bits, they're extra anyway */
310
	/* Don't worry about left over bits, they're extra anyway */
311
	return cnt;
311
	return cnt;
312
}
312
}
313

    
   
313

   
314
/*! \brief encode text to BASE64 coding */
314
/*! \brief encode text to BASE64 coding */
315
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
315
int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
316
{
316
{
317
	int cnt = 0;
317
	int cnt = 0;
318
	int col = 0;
318
	int col = 0;
319
	unsigned int byte = 0;
319
	unsigned int byte = 0;
320
	int bits = 0;
320
	int bits = 0;
321
	int cntin = 0;
321
	int cntin = 0;
322
	/* Reserve space for null byte at end of string */
322
	/* Reserve space for null byte at end of string */
323
	max--;
323
	max--;
324
	while ((cntin < srclen) && (cnt < max)) {
324
	while ((cntin < srclen) && (cnt < max)) {
325
		byte <<= 8;
325
		byte <<= 8;
326
		byte |= *(src++);
326
		byte |= *(src++);
327
		bits += 8;
327
		bits += 8;
328
		cntin++;
328
		cntin++;
329
		if ((bits == 24) && (cnt + 4 <= max)) {
329
		if ((bits == 24) && (cnt + 4 <= max)) {
330
			*dst++ = base64[(byte >> 18) & 0x3f];
330
			*dst++ = base64[(byte >> 18) & 0x3f];
331
			*dst++ = base64[(byte >> 12) & 0x3f];
331
			*dst++ = base64[(byte >> 12) & 0x3f];
332
			*dst++ = base64[(byte >> 6) & 0x3f];
332
			*dst++ = base64[(byte >> 6) & 0x3f];
333
			*dst++ = base64[byte & 0x3f];
333
			*dst++ = base64[byte & 0x3f];
334
			cnt += 4;
334
			cnt += 4;
335
			col += 4;
335
			col += 4;
336
			bits = 0;
336
			bits = 0;
337
			byte = 0;
337
			byte = 0;
338
		}
338
		}
339
		if (linebreaks && (cnt < max) && (col == 64)) {
339
		if (linebreaks && (cnt < max) && (col == 64)) {
340
			*dst++ = '\n';
340
			*dst++ = '\n';
341
			cnt++;
341
			cnt++;
342
			col = 0;
342
			col = 0;
343
		}
343
		}
344
	}
344
	}
345
	if (bits && (cnt + 4 <= max)) {
345
	if (bits && (cnt + 4 <= max)) {
346
		/* Add one last character for the remaining bits,
346
		/* Add one last character for the remaining bits,
347
		   padding the rest with 0 */
347
		   padding the rest with 0 */
348
		byte <<= 24 - bits;
348
		byte <<= 24 - bits;
349
		*dst++ = base64[(byte >> 18) & 0x3f];
349
		*dst++ = base64[(byte >> 18) & 0x3f];
350
		*dst++ = base64[(byte >> 12) & 0x3f];
350
		*dst++ = base64[(byte >> 12) & 0x3f];
351
		if (bits == 16)
351
		if (bits == 16)
352
			*dst++ = base64[(byte >> 6) & 0x3f];
352
			*dst++ = base64[(byte >> 6) & 0x3f];
353
		else
353
		else
354
			*dst++ = '=';
354
			*dst++ = '=';
355
		*dst++ = '=';
355
		*dst++ = '=';
356
		cnt += 4;
356
		cnt += 4;
357
	}
357
	}
358
	if (linebreaks && (cnt < max)) {
358
	if (linebreaks && (cnt < max)) {
359
		*dst++ = '\n';
359
		*dst++ = '\n';
360
		cnt++;
360
		cnt++;
361
	}
361
	}
362
	*dst = '\0';
362
	*dst = '\0';
363
	return cnt;
363
	return cnt;
364
}
364
}
365

    
   
365

   
366
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
366
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
367
{
367
{
368
	return ast_base64encode_full(dst, src, srclen, max, 0);
368
	return ast_base64encode_full(dst, src, srclen, max, 0);
369
}
369
}
370

    
   
370

   
371
static void base64_init(void)
371
static void base64_init(void)
372
{
372
{
373
	int x;
373
	int x;
374
	memset(b2a, -1, sizeof(b2a));
374
	memset(b2a, -1, sizeof(b2a));
375
	/* Initialize base-64 Conversion table */
375
	/* Initialize base-64 Conversion table */
376
	for (x = 0; x < 26; x++) {
376
	for (x = 0; x < 26; x++) {
377
		/* A-Z */
377
		/* A-Z */
378
		base64[x] = 'A' + x;
378
		base64[x] = 'A' + x;
379
		b2a['A' + x] = x;
379
		b2a['A' + x] = x;
380
		/* a-z */
380
		/* a-z */
381
		base64[x + 26] = 'a' + x;
381
		base64[x + 26] = 'a' + x;
382
		b2a['a' + x] = x + 26;
382
		b2a['a' + x] = x + 26;
383
		/* 0-9 */
383
		/* 0-9 */
384
		if (x < 10) {
384
		if (x < 10) {
385
			base64[x + 52] = '0' + x;
385
			base64[x + 52] = '0' + x;
386
			b2a['0' + x] = x + 52;
386
			b2a['0' + x] = x + 52;
387
		}
387
		}
388
	}
388
	}
389
	base64[62] = '+';
389
	base64[62] = '+';
390
	base64[63] = '/';
390
	base64[63] = '/';
391
	b2a[(int)'+'] = 62;
391
	b2a[(int)'+'] = 62;
392
	b2a[(int)'/'] = 63;
392
	b2a[(int)'/'] = 63;
393
}
393
}
394

    
   
394

   
395
const struct ast_flags ast_uri_http = {AST_URI_UNRESERVED};
395
const struct ast_flags ast_uri_http = {AST_URI_UNRESERVED};
396
const struct ast_flags ast_uri_http_legacy = {AST_URI_LEGACY_SPACE | AST_URI_UNRESERVED};
396
const struct ast_flags ast_uri_http_legacy = {AST_URI_LEGACY_SPACE | AST_URI_UNRESERVED};
397
const struct ast_flags ast_uri_sip_user = {AST_URI_UNRESERVED | AST_URI_SIP_USER_UNRESERVED};
397
const struct ast_flags ast_uri_sip_user = {AST_URI_UNRESERVED | AST_URI_SIP_USER_UNRESERVED};
398

    
   
398

   
399
char *ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
399
char *ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
400
{
400
{
401
	const char *ptr  = string;	/* Start with the string */
401
	const char *ptr  = string;	/* Start with the string */
402
	char *out = outbuf;
402
	char *out = outbuf;
403
	const char *mark = "-_.!~*'()"; /* no encode set, RFC 2396 section 2.3, RFC 3261 sec 25 */
403
	const char *mark = "-_.!~*'()"; /* no encode set, RFC 2396 section 2.3, RFC 3261 sec 25 */
404
	const char *user_unreserved = "&=+$,;?/"; /* user-unreserved set, RFC 3261 sec 25 */
404
	const char *user_unreserved = "&=+$,;?/"; /* user-unreserved set, RFC 3261 sec 25 */
405

    
   
405

   
406
	while (*ptr && out - outbuf < buflen - 1) {
406
	while (*ptr && out - outbuf < buflen - 1) {
407
		if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *ptr == ' ') {
407
		if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *ptr == ' ') {
408
			/* for legacy encoding, encode spaces as '+' */
408
			/* for legacy encoding, encode spaces as '+' */
409
			*out = '+';
409
			*out = '+';
410
			out++;
410
			out++;
411
		} else if (!(ast_test_flag(&spec, AST_URI_MARK)
411
		} else if (!(ast_test_flag(&spec, AST_URI_MARK)
412
				&& strchr(mark, *ptr))
412
				&& strchr(mark, *ptr))
413
			&& !(ast_test_flag(&spec, AST_URI_ALPHANUM)
413
			&& !(ast_test_flag(&spec, AST_URI_ALPHANUM)
414
				&& ((*ptr >= '0' && *ptr <= '9')
414
				&& ((*ptr >= '0' && *ptr <= '9')
415
				|| (*ptr >= 'A' && *ptr <= 'Z')
415
				|| (*ptr >= 'A' && *ptr <= 'Z')
416
				|| (*ptr >= 'a' && *ptr <= 'z')))
416
				|| (*ptr >= 'a' && *ptr <= 'z')))
417
			&& !(ast_test_flag(&spec, AST_URI_SIP_USER_UNRESERVED)
417
			&& !(ast_test_flag(&spec, AST_URI_SIP_USER_UNRESERVED)
418
				&& strchr(user_unreserved, *ptr))) {
418
				&& strchr(user_unreserved, *ptr))) {
419

    
   
419

   
420
			if (out - outbuf >= buflen - 3) {
420
			if (out - outbuf >= buflen - 3) {
421
				break;
421
				break;
422
			}
422
			}
423
			out += sprintf(out, "%%%02hhX", (unsigned char) *ptr);
423
			out += sprintf(out, "%%%02hhX", (unsigned char) *ptr);
424
		} else {
424
		} else {
425
			*out = *ptr;	/* Continue copying the string */
425
			*out = *ptr;	/* Continue copying the string */
426
			out++;
426
			out++;
427
		}
427
		}
428
		ptr++;
428
		ptr++;
429
	}
429
	}
430

    
   
430

   
431
	if (buflen) {
431
	if (buflen) {
432
		*out = '\0';
432
		*out = '\0';
433
	}
433
	}
434

    
   
434

   
435
	return outbuf;
435
	return outbuf;
436
}
436
}
437

    
   
437

   
438
void ast_uri_decode(char *s, struct ast_flags spec)
438
void ast_uri_decode(char *s, struct ast_flags spec)
439
{
439
{
440
	char *o;
440
	char *o;
441
	unsigned int tmp;
441
	unsigned int tmp;
442

    
   
442

   
443
	for (o = s; *s; s++, o++) {
443
	for (o = s; *s; s++, o++) {
444
		if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *s == '+') {
444
		if (ast_test_flag(&spec, AST_URI_LEGACY_SPACE) && *s == '+') {
445
			/* legacy mode, decode '+' as space */
445
			/* legacy mode, decode '+' as space */
446
			*o = ' ';
446
			*o = ' ';
447
		} else if (*s == '%' && s[1] != '\0' && s[2] != '\0' && sscanf(s + 1, "%2x", &tmp) == 1) {
447
		} else if (*s == '%' && s[1] != '\0' && s[2] != '\0' && sscanf(s + 1, "%2x", &tmp) == 1) {
448
			/* have '%', two chars and correct parsing */
448
			/* have '%', two chars and correct parsing */
449
			*o = tmp;
449
			*o = tmp;
450
			s += 2;	/* Will be incremented once more when we break out */
450
			s += 2;	/* Will be incremented once more when we break out */
451
		} else /* all other cases, just copy */
451
		} else /* all other cases, just copy */
452
			*o = *s;
452
			*o = *s;
453
	}
453
	}
454
	*o = '\0';
454
	*o = '\0';
455
}
455
}
456

    
   
456

   
457
char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
457
char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
458
{
458
{
459
	const char *ptr  = string;
459
	const char *ptr  = string;
460
	char *out = outbuf;
460
	char *out = outbuf;
461
	char *allow = "\t\v !"; /* allow LWS (minus \r and \n) and "!" */
461
	char *allow = "\t\v !"; /* allow LWS (minus \r and \n) and "!" */
462

    
   
462

   
463
	while (*ptr && out - outbuf < buflen - 1) {
463
	while (*ptr && out - outbuf < buflen - 1) {
464
		if (!(strchr(allow, *ptr))
464
		if (!(strchr(allow, *ptr))
465
			&& !(*ptr >= '#' && *ptr <= '[') /* %x23 - %x5b */
465
			&& !(*ptr >= '#' && *ptr <= '[') /* %x23 - %x5b */
466
			&& !(*ptr >= ']' && *ptr <= '~') /* %x5d - %x7e */
466
			&& !(*ptr >= ']' && *ptr <= '~') /* %x5d - %x7e */
467
			&& !((unsigned char) *ptr > 0x7f)) {             /* UTF8-nonascii */
467
			&& !((unsigned char) *ptr > 0x7f)) {             /* UTF8-nonascii */
468

    
   
468

   
469
			if (out - outbuf >= buflen - 2) {
469
			if (out - outbuf >= buflen - 2) {
470
				break;
470
				break;
471
			}
471
			}
472
			out += sprintf(out, "\\%c", (unsigned char) *ptr);
472
			out += sprintf(out, "\\%c", (unsigned char) *ptr);
473
		} else {
473
		} else {
474
			*out = *ptr;
474
			*out = *ptr;
475
			out++;
475
			out++;
476
		}
476
		}
477
		ptr++;
477
		ptr++;
478
	}
478
	}
479

    
   
479

   
480
	if (buflen) {
480
	if (buflen) {
481
		*out = '\0';
481
		*out = '\0';
482
	}
482
	}
483

    
   
483

   
484
	return outbuf;
484
	return outbuf;
485
}
485
}
486

    
   
486

   
487
char *ast_escape_semicolons(const char *string, char *outbuf, int buflen)
487
char *ast_escape_semicolons(const char *string, char *outbuf, int buflen)
488
{
488
{
489
	const char *ptr = string;
489
	const char *ptr = string;
490
	char *out = outbuf;
490
	char *out = outbuf;
491

    
   
491

   
492
	if (string == NULL || buflen == 0 || outbuf == NULL) {
492
	if (string == NULL || outbuf == NULL) {
493
		ast_assert(string != NULL && (buflen == 0 || outbuf != NULL));
493
		ast_assert(string != NULL && outbuf != NULL);
494
		return NULL;
494
		return NULL;
495
	}
495
	}
496

    
   
496

   
497
	while (*ptr && out - outbuf < buflen - 1) {
497
	while (*ptr && out - outbuf < buflen - 1) {
498
		if (*ptr == ';') {
498
		if (*ptr == ';') {
499
			if (out - outbuf >= buflen - 2) {
499
			if (out - outbuf >= buflen - 2) {
500
				break;
500
				break;
501
			}
501
			}
502
			strcpy(out, "\\;");
502
			strcpy(out, "\\;");
503
			out += 2;
503
			out += 2;
504
		} else {
504
		} else {
505
			*out = *ptr;
505
			*out = *ptr;
506
			out++;
506
			out++;
507
		}
507
		}
508
		ptr++;
508
		ptr++;
509
	}
509
	}
510

    
   
510

   
511
	if (buflen) {
511
	if (buflen) {
512
		*out = '\0';
512
		*out = '\0';
513
	}
513
	}
514

    
   
514

   
515
	return outbuf;
515
	return outbuf;
516
}
516
}
517

    
   
517

   
518
void ast_unescape_quoted(char *quote_str)
518
void ast_unescape_quoted(char *quote_str)
519
{
519
{
520
	int esc_pos;
520
	int esc_pos;
521
	int unesc_pos;
521
	int unesc_pos;
522
	int quote_str_len = strlen(quote_str);
522
	int quote_str_len = strlen(quote_str);
523

    
   
523

   
524
	for (esc_pos = 0, unesc_pos = 0;
524
	for (esc_pos = 0, unesc_pos = 0;
525
		esc_pos < quote_str_len;
525
		esc_pos < quote_str_len;
526
		esc_pos++, unesc_pos++) {
526
		esc_pos++, unesc_pos++) {
527
		if (quote_str[esc_pos] == '\\') {
527
		if (quote_str[esc_pos] == '\\') {
528
			/* at least one more char and current is \\ */
528
			/* at least one more char and current is \\ */
529
			esc_pos++;
529
			esc_pos++;
530
			if (esc_pos >= quote_str_len) {
530
			if (esc_pos >= quote_str_len) {
531
				break;
531
				break;
532
			}
532
			}
533
		}
533
		}
534

    
   
534

   
535
		quote_str[unesc_pos] = quote_str[esc_pos];
535
		quote_str[unesc_pos] = quote_str[esc_pos];
536
	}
536
	}
537
	quote_str[unesc_pos] = '\0';
537
	quote_str[unesc_pos] = '\0';
538
}
538
}
539

    
   
539

   
540
int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
540
int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
541
{
541
{
542
	char *dst = outbuf;
542
	char *dst = outbuf;
543
	char *end = outbuf + buflen - 1; /* save one for the null terminator */
543
	char *end = outbuf + buflen - 1; /* save one for the null terminator */
544

    
   
544

   
545
	/* Handle the case for the empty output buffer */
545
	/* Handle the case for the empty output buffer */
546
	if (buflen == 0) {
546
	if (buflen == 0) {
547
		return -1;
547
		return -1;
548
	}
548
	}
549

    
   
549

   
550
	/* Escaping rules from http://www.w3.org/TR/REC-xml/#syntax */
550
	/* Escaping rules from http://www.w3.org/TR/REC-xml/#syntax */
551
	/* This also prevents partial entities at the end of a string */
551
	/* This also prevents partial entities at the end of a string */
552
	while (*string && dst < end) {
552
	while (*string && dst < end) {
553
		const char *entity = NULL;
553
		const char *entity = NULL;
554
		int len = 0;
554
		int len = 0;
555

    
   
555

   
556
		switch (*string) {
556
		switch (*string) {
557
		case '<':
557
		case '<':
558
			entity = "&lt;";
558
			entity = "&lt;";
559
			len = 4;
559
			len = 4;
560
			break;
560
			break;
561
		case '&':
561
		case '&':
562
			entity = "&amp;";
562
			entity = "&amp;";
563
			len = 5;
563
			len = 5;
564
			break;
564
			break;
565
		case '>':
565
		case '>':
566
			/* necessary if ]]> is in the string; easier to escape them all */
566
			/* necessary if ]]> is in the string; easier to escape them all */
567
			entity = "&gt;";
567
			entity = "&gt;";
568
			len = 4;
568
			len = 4;
569
			break;
569
			break;
570
		case '\'':
570
		case '\'':
571
			/* necessary in single-quoted strings; easier to escape them all */
571
			/* necessary in single-quoted strings; easier to escape them all */
572
			entity = "&apos;";
572
			entity = "&apos;";
573
			len = 6;
573
			len = 6;
574
			break;
574
			break;
575
		case '"':
575
		case '"':
576
			/* necessary in double-quoted strings; easier to escape them all */
576
			/* necessary in double-quoted strings; easier to escape them all */
577
			entity = "&quot;";
577
			entity = "&quot;";
578
			len = 6;
578
			len = 6;
579
			break;
579
			break;
580
		default:
580
		default:
581
			*dst++ = *string++;
581
			*dst++ = *string++;
582
			break;
582
			break;
583
		}
583
		}
584

    
   
584

   
585
		if (entity) {
585
		if (entity) {
586
			ast_assert(len == strlen(entity));
586
			ast_assert(len == strlen(entity));
587
			if (end - dst < len) {
587
			if (end - dst < len) {
588
				/* no room for the entity; stop */
588
				/* no room for the entity; stop */
589
				break;
589
				break;
590
			}
590
			}
591
			/* just checked for length; strcpy is fine */
591
			/* just checked for length; strcpy is fine */
592
			strcpy(dst, entity);
592
			strcpy(dst, entity);
593
			dst += len;
593
			dst += len;
594
			++string;
594
			++string;
595
		}
595
		}
596
	}
596
	}
597
	/* Write null terminator */
597
	/* Write null terminator */
598
	*dst = '\0';
598
	*dst = '\0';
599
	/* If any chars are left in string, return failure */
599
	/* If any chars are left in string, return failure */
600
	return *string == '\0' ? 0 : -1;
600
	return *string == '\0' ? 0 : -1;
601
}
601
}
602

    
   
602

   
603
/*! \brief  ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
603
/*! \brief  ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
604
const char *ast_inet_ntoa(struct in_addr ia)
604
const char *ast_inet_ntoa(struct in_addr ia)
605
{
605
{
606
	char *buf;
606
	char *buf;
607

    
   
607

   
608
	if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
608
	if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
609
		return "";
609
		return "";
610

    
   
610

   
611
	return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
611
	return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
612
}
612
}
613

    
   
613

   
614
static int dev_urandom_fd = -1;
614
static int dev_urandom_fd = -1;
615

    
   
615

   
616
#ifndef __linux__
616
#ifndef __linux__
617
#undef pthread_create /* For ast_pthread_create function only */
617
#undef pthread_create /* For ast_pthread_create function only */
618
#endif /* !__linux__ */
618
#endif /* !__linux__ */
619

    
   
619

   
620
#if !defined(LOW_MEMORY)
620
#if !defined(LOW_MEMORY)
621

    
   
621

   
622
#ifdef DEBUG_THREADS
622
#ifdef DEBUG_THREADS
623

    
   
623

   
624
/*! \brief A reasonable maximum number of locks a thread would be holding ... */
624
/*! \brief A reasonable maximum number of locks a thread would be holding ... */
625
#define AST_MAX_LOCKS 64
625
#define AST_MAX_LOCKS 64
626

    
   
626

   
627
/* Allow direct use of pthread_mutex_t and friends */
627
/* Allow direct use of pthread_mutex_t and friends */
628
#undef pthread_mutex_t
628
#undef pthread_mutex_t
629
#undef pthread_mutex_lock
629
#undef pthread_mutex_lock
630
#undef pthread_mutex_unlock
630
#undef pthread_mutex_unlock
631
#undef pthread_mutex_init
631
#undef pthread_mutex_init
632
#undef pthread_mutex_destroy
632
#undef pthread_mutex_destroy
633

    
   
633

   
634
/*!
634
/*!
635
 * \brief Keep track of which locks a thread holds
635
 * \brief Keep track of which locks a thread holds
636
 *
636
 *
637
 * There is an instance of this struct for every active thread
637
 * There is an instance of this struct for every active thread
638
 */
638
 */
639
struct thr_lock_info {
639
struct thr_lock_info {
640
	/*! The thread's ID */
640
	/*! The thread's ID */
641
	pthread_t thread_id;
641
	pthread_t thread_id;
642
	/*! The thread name which includes where the thread was started */
642
	/*! The thread name which includes where the thread was started */
643
	const char *thread_name;
643
	const char *thread_name;
644
	/*! This is the actual container of info for what locks this thread holds */
644
	/*! This is the actual container of info for what locks this thread holds */
645
	struct {
645
	struct {
646
		const char *file;
646
		const char *file;
647
		const char *func;
647
		const char *func;
648
		const char *lock_name;
648
		const char *lock_name;
649
		void *lock_addr;
649
		void *lock_addr;
650
		int times_locked;
650
		int times_locked;
651
		int line_num;
651
		int line_num;
652
		enum ast_lock_type type;
652
		enum ast_lock_type type;
653
		/*! This thread is waiting on this lock */
653
		/*! This thread is waiting on this lock */
654
		int pending:2;
654
		int pending:2;
655
		/*! A condition has suspended this lock */
655
		/*! A condition has suspended this lock */
656
		int suspended:1;
656
		int suspended:1;
657
#ifdef HAVE_BKTR
657
#ifdef HAVE_BKTR
658
		struct ast_bt *backtrace;
658
		struct ast_bt *backtrace;
659
#endif
659
#endif
660
	} locks[AST_MAX_LOCKS];
660
	} locks[AST_MAX_LOCKS];
661
	/*! This is the number of locks currently held by this thread.
661
	/*! This is the number of locks currently held by this thread.
662
	 *  The index (num_locks - 1) has the info on the last one in the
662
	 *  The index (num_locks - 1) has the info on the last one in the
663
	 *  locks member */
663
	 *  locks member */
664
	unsigned int num_locks;
664
	unsigned int num_locks;
665
	/*! The LWP id (which GDB prints) */
665
	/*! The LWP id (which GDB prints) */
666
	int lwp;
666
	int lwp;
667
	/*! Protects the contents of the locks member
667
	/*! Protects the contents of the locks member
668
	 * Intentionally not ast_mutex_t */
668
	 * Intentionally not ast_mutex_t */
669
	pthread_mutex_t lock;
669
	pthread_mutex_t lock;
670
	AST_LIST_ENTRY(thr_lock_info) entry;
670
	AST_LIST_ENTRY(thr_lock_info) entry;
671
};
671
};
672

    
   
672

   
673
/*!
673
/*!
674
 * \brief Locked when accessing the lock_infos list
674
 * \brief Locked when accessing the lock_infos list
675
 */
675
 */
676
AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
676
AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
677
/*!
677
/*!
678
 * \brief A list of each thread's lock info
678
 * \brief A list of each thread's lock info
679
 */
679
 */
680
static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
680
static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
681

    
   
681

   
682
/*!
682
/*!
683
 * \brief Destroy a thread's lock info
683
 * \brief Destroy a thread's lock info
684
 *
684
 *
685
 * This gets called automatically when the thread stops
685
 * This gets called automatically when the thread stops
686
 */
686
 */
687
static void lock_info_destroy(void *data)
687
static void lock_info_destroy(void *data)
688
{
688
{
689
	struct thr_lock_info *lock_info = data;
689
	struct thr_lock_info *lock_info = data;
690
	int i;
690
	int i;
691

    
   
691

   
692
	pthread_mutex_lock(&lock_infos_lock.mutex);
692
	pthread_mutex_lock(&lock_infos_lock.mutex);
693
	AST_LIST_REMOVE(&lock_infos, lock_info, entry);
693
	AST_LIST_REMOVE(&lock_infos, lock_info, entry);
694
	pthread_mutex_unlock(&lock_infos_lock.mutex);
694
	pthread_mutex_unlock(&lock_infos_lock.mutex);
695

    
   
695

   
696

    
   
696

   
697
	for (i = 0; i < lock_info->num_locks; i++) {
697
	for (i = 0; i < lock_info->num_locks; i++) {
698
		if (lock_info->locks[i].pending == -1) {
698
		if (lock_info->locks[i].pending == -1) {
699
			/* This just means that the last lock this thread went for was by
699
			/* This just means that the last lock this thread went for was by
700
			 * using trylock, and it failed.  This is fine. */
700
			 * using trylock, and it failed.  This is fine. */
701
			break;
701
			break;
702
		}
702
		}
703

    
   
703

   
704
		ast_log(LOG_ERROR,
704
		ast_log(LOG_ERROR,
705
			"Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
705
			"Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
706
			lock_info->thread_name,
706
			lock_info->thread_name,
707
			lock_info->locks[i].lock_name,
707
			lock_info->locks[i].lock_name,
708
			lock_info->locks[i].lock_addr,
708
			lock_info->locks[i].lock_addr,
709
			lock_info->locks[i].func,
709
			lock_info->locks[i].func,
710
			lock_info->locks[i].file,
710
			lock_info->locks[i].file,
711
			lock_info->locks[i].line_num
711
			lock_info->locks[i].line_num
712
		);
712
		);
713
	}
713
	}
714

    
   
714

   
715
	pthread_mutex_destroy(&lock_info->lock);
715
	pthread_mutex_destroy(&lock_info->lock);
716
	if (lock_info->thread_name) {
716
	if (lock_info->thread_name) {
717
		ast_free((void *) lock_info->thread_name);
717
		ast_free((void *) lock_info->thread_name);
718
	}
718
	}
719
	ast_free(lock_info);
719
	ast_free(lock_info);
720
}
720
}
721

    
   
721

   
722
/*!
722
/*!
723
 * \brief The thread storage key for per-thread lock info
723
 * \brief The thread storage key for per-thread lock info
724
 */
724
 */
725
AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
725
AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
726
#ifdef HAVE_BKTR
726
#ifdef HAVE_BKTR
727
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
727
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
728
	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
728
	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
729
#else
729
#else
730
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
730
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
731
	int line_num, const char *func, const char *lock_name, void *lock_addr)
731
	int line_num, const char *func, const char *lock_name, void *lock_addr)
732
#endif
732
#endif
733
{
733
{
734
	struct thr_lock_info *lock_info;
734
	struct thr_lock_info *lock_info;
735
	int i;
735
	int i;
736

    
   
736

   
737
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
737
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
738
		return;
738
		return;
739

    
   
739

   
740
	pthread_mutex_lock(&lock_info->lock);
740
	pthread_mutex_lock(&lock_info->lock);
741

    
   
741

   
742
	for (i = 0; i < lock_info->num_locks; i++) {
742
	for (i = 0; i < lock_info->num_locks; i++) {
743
		if (lock_info->locks[i].lock_addr == lock_addr) {
743
		if (lock_info->locks[i].lock_addr == lock_addr) {
744
			lock_info->locks[i].times_locked++;
744
			lock_info->locks[i].times_locked++;
745
#ifdef HAVE_BKTR
745
#ifdef HAVE_BKTR
746
			lock_info->locks[i].backtrace = bt;
746
			lock_info->locks[i].backtrace = bt;
747
#endif
747
#endif
748
			pthread_mutex_unlock(&lock_info->lock);
748
			pthread_mutex_unlock(&lock_info->lock);
749
			return;
749
			return;
750
		}
750
		}
751
	}
751
	}
752

    
   
752

   
753
	if (lock_info->num_locks == AST_MAX_LOCKS) {
753
	if (lock_info->num_locks == AST_MAX_LOCKS) {
754
		/* Can't use ast_log here, because it will cause infinite recursion */
754
		/* Can't use ast_log here, because it will cause infinite recursion */
755
		fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
755
		fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
756
			"  Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
756
			"  Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
757
		pthread_mutex_unlock(&lock_info->lock);
757
		pthread_mutex_unlock(&lock_info->lock);
758
		return;
758
		return;
759
	}
759
	}
760

    
   
760

   
761
	if (i && lock_info->locks[i - 1].pending == -1) {
761
	if (i && lock_info->locks[i - 1].pending == -1) {
762
		/* The last lock on the list was one that this thread tried to lock but
762
		/* The last lock on the list was one that this thread tried to lock but
763
		 * failed at doing so.  It has now moved on to something else, so remove
763
		 * failed at doing so.  It has now moved on to something else, so remove
764
		 * the old lock from the list. */
764
		 * the old lock from the list. */
765
		i--;
765
		i--;
766
		lock_info->num_locks--;
766
		lock_info->num_locks--;
767
		memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
767
		memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
768
	}
768
	}
769

    
   
769

   
770
	lock_info->locks[i].file = filename;
770
	lock_info->locks[i].file = filename;
771
	lock_info->locks[i].line_num = line_num;
771
	lock_info->locks[i].line_num = line_num;
772
	lock_info->locks[i].func = func;
772
	lock_info->locks[i].func = func;
773
	lock_info->locks[i].lock_name = lock_name;
773
	lock_info->locks[i].lock_name = lock_name;
774
	lock_info->locks[i].lock_addr = lock_addr;
774
	lock_info->locks[i].lock_addr = lock_addr;
775
	lock_info->locks[i].times_locked = 1;
775
	lock_info->locks[i].times_locked = 1;
776
	lock_info->locks[i].type = type;
776
	lock_info->locks[i].type = type;
777
	lock_info->locks[i].pending = 1;
777
	lock_info->locks[i].pending = 1;
778
#ifdef HAVE_BKTR
778
#ifdef HAVE_BKTR
779
	lock_info->locks[i].backtrace = bt;
779
	lock_info->locks[i].backtrace = bt;
780
#endif
780
#endif
781
	lock_info->num_locks++;
781
	lock_info->num_locks++;
782

    
   
782

   
783
	pthread_mutex_unlock(&lock_info->lock);
783
	pthread_mutex_unlock(&lock_info->lock);
784
}
784
}
785

    
   
785

   
786
void ast_mark_lock_acquired(void *lock_addr)
786
void ast_mark_lock_acquired(void *lock_addr)
787
{
787
{
788
	struct thr_lock_info *lock_info;
788
	struct thr_lock_info *lock_info;
789

    
   
789

   
790
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
790
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
791
		return;
791
		return;
792

    
   
792

   
793
	pthread_mutex_lock(&lock_info->lock);
793
	pthread_mutex_lock(&lock_info->lock);
794
	if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
794
	if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
795
		lock_info->locks[lock_info->num_locks - 1].pending = 0;
795
		lock_info->locks[lock_info->num_locks - 1].pending = 0;
796
	}
796
	}
797
	pthread_mutex_unlock(&lock_info->lock);
797
	pthread_mutex_unlock(&lock_info->lock);
798
}
798
}
799

    
   
799

   
800
void ast_mark_lock_failed(void *lock_addr)
800
void ast_mark_lock_failed(void *lock_addr)
801
{
801
{
802
	struct thr_lock_info *lock_info;
802
	struct thr_lock_info *lock_info;
803

    
   
803

   
804
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
804
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
805
		return;
805
		return;
806

    
   
806

   
807
	pthread_mutex_lock(&lock_info->lock);
807
	pthread_mutex_lock(&lock_info->lock);
808
	if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
808
	if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
809
		lock_info->locks[lock_info->num_locks - 1].pending = -1;
809
		lock_info->locks[lock_info->num_locks - 1].pending = -1;
810
		lock_info->locks[lock_info->num_locks - 1].times_locked--;
810
		lock_info->locks[lock_info->num_locks - 1].times_locked--;
811
	}
811
	}
812
	pthread_mutex_unlock(&lock_info->lock);
812
	pthread_mutex_unlock(&lock_info->lock);
813
}
813
}
814

    
   
814

   
815
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)
815
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)
816
{
816
{
817
	struct thr_lock_info *lock_info;
817
	struct thr_lock_info *lock_info;
818
	int i = 0;
818
	int i = 0;
819

    
   
819

   
820
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
820
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
821
		return -1;
821
		return -1;
822

    
   
822

   
823
	pthread_mutex_lock(&lock_info->lock);
823
	pthread_mutex_lock(&lock_info->lock);
824

    
   
824

   
825
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
825
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
826
		if (lock_info->locks[i].lock_addr == lock_addr)
826
		if (lock_info->locks[i].lock_addr == lock_addr)
827
			break;
827
			break;
828
	}
828
	}
829

    
   
829

   
830
	if (i == -1) {
830
	if (i == -1) {
831
		/* Lock not found :( */
831
		/* Lock not found :( */
832
		pthread_mutex_unlock(&lock_info->lock);
832
		pthread_mutex_unlock(&lock_info->lock);
833
		return -1;
833
		return -1;
834
	}
834
	}
835

    
   
835

   
836
	ast_copy_string(filename, lock_info->locks[i].file, filename_size);
836
	ast_copy_string(filename, lock_info->locks[i].file, filename_size);
837
	*lineno = lock_info->locks[i].line_num;
837
	*lineno = lock_info->locks[i].line_num;
838
	ast_copy_string(func, lock_info->locks[i].func, func_size);
838
	ast_copy_string(func, lock_info->locks[i].func, func_size);
839
	ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
839
	ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
840

    
   
840

   
841
	pthread_mutex_unlock(&lock_info->lock);
841
	pthread_mutex_unlock(&lock_info->lock);
842

    
   
842

   
843
	return 0;
843
	return 0;
844
}
844
}
845

    
   
845

   
846
void ast_suspend_lock_info(void *lock_addr)
846
void ast_suspend_lock_info(void *lock_addr)
847
{
847
{
848
	struct thr_lock_info *lock_info;
848
	struct thr_lock_info *lock_info;
849
	int i = 0;
849
	int i = 0;
850

    
   
850

   
851
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) {
851
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) {
852
		return;
852
		return;
853
	}
853
	}
854

    
   
854

   
855
	pthread_mutex_lock(&lock_info->lock);
855
	pthread_mutex_lock(&lock_info->lock);
856

    
   
856

   
857
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
857
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
858
		if (lock_info->locks[i].lock_addr == lock_addr)
858
		if (lock_info->locks[i].lock_addr == lock_addr)
859
			break;
859
			break;
860
	}
860
	}
861

    
   
861

   
862
	if (i == -1) {
862
	if (i == -1) {
863
		/* Lock not found :( */
863
		/* Lock not found :( */
864
		pthread_mutex_unlock(&lock_info->lock);
864
		pthread_mutex_unlock(&lock_info->lock);
865
		return;
865
		return;
866
	}
866
	}
867

    
   
867

   
868
	lock_info->locks[i].suspended = 1;
868
	lock_info->locks[i].suspended = 1;
869

    
   
869

   
870
	pthread_mutex_unlock(&lock_info->lock);
870
	pthread_mutex_unlock(&lock_info->lock);
871
}
871
}
872

    
   
872

   
873
void ast_restore_lock_info(void *lock_addr)
873
void ast_restore_lock_info(void *lock_addr)
874
{
874
{
875
	struct thr_lock_info *lock_info;
875
	struct thr_lock_info *lock_info;
876
	int i = 0;
876
	int i = 0;
877

    
   
877

   
878
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
878
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
879
		return;
879
		return;
880

    
   
880

   
881
	pthread_mutex_lock(&lock_info->lock);
881
	pthread_mutex_lock(&lock_info->lock);
882

    
   
882

   
883
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
883
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
884
		if (lock_info->locks[i].lock_addr == lock_addr)
884
		if (lock_info->locks[i].lock_addr == lock_addr)
885
			break;
885
			break;
886
	}
886
	}
887

    
   
887

   
888
	if (i == -1) {
888
	if (i == -1) {
889
		/* Lock not found :( */
889
		/* Lock not found :( */
890
		pthread_mutex_unlock(&lock_info->lock);
890
		pthread_mutex_unlock(&lock_info->lock);
891
		return;
891
		return;
892
	}
892
	}
893

    
   
893

   
894
	lock_info->locks[i].suspended = 0;
894
	lock_info->locks[i].suspended = 0;
895

    
   
895

   
896
	pthread_mutex_unlock(&lock_info->lock);
896
	pthread_mutex_unlock(&lock_info->lock);
897
}
897
}
898

    
   
898

   
899

    
   
899

   
900
#ifdef HAVE_BKTR
900
#ifdef HAVE_BKTR
901
void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
901
void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
902
#else
902
#else
903
void ast_remove_lock_info(void *lock_addr)
903
void ast_remove_lock_info(void *lock_addr)
904
#endif
904
#endif
905
{
905
{
906
	struct thr_lock_info *lock_info;
906
	struct thr_lock_info *lock_info;
907
	int i = 0;
907
	int i = 0;
908

    
   
908

   
909
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
909
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
910
		return;
910
		return;
911

    
   
911

   
912
	pthread_mutex_lock(&lock_info->lock);
912
	pthread_mutex_lock(&lock_info->lock);
913

    
   
913

   
914
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
914
	for (i = lock_info->num_locks - 1; i >= 0; i--) {
915
		if (lock_info->locks[i].lock_addr == lock_addr)
915
		if (lock_info->locks[i].lock_addr == lock_addr)
916
			break;
916
			break;
917
	}
917
	}
918

    
   
918

   
919
	if (i == -1) {
919
	if (i == -1) {
920
		/* Lock not found :( */
920
		/* Lock not found :( */
921
		pthread_mutex_unlock(&lock_info->lock);
921
		pthread_mutex_unlock(&lock_info->lock);
922
		return;
922
		return;
923
	}
923
	}
924

    
   
924

   
925
	if (lock_info->locks[i].times_locked > 1) {
925
	if (lock_info->locks[i].times_locked > 1) {
926
		lock_info->locks[i].times_locked--;
926
		lock_info->locks[i].times_locked--;
927
#ifdef HAVE_BKTR
927
#ifdef HAVE_BKTR
928
		lock_info->locks[i].backtrace = bt;
928
		lock_info->locks[i].backtrace = bt;
929
#endif
929
#endif
930
		pthread_mutex_unlock(&lock_info->lock);
930
		pthread_mutex_unlock(&lock_info->lock);
931
		return;
931
		return;
932
	}
932
	}
933

    
   
933

   
934
	if (i < lock_info->num_locks - 1) {
934
	if (i < lock_info->num_locks - 1) {
935
		/* Not the last one ... *should* be rare! */
935
		/* Not the last one ... *should* be rare! */
936
		memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
936
		memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
937
			(lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
937
			(lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
938
	}
938
	}
939

    
   
939

   
940
	lock_info->num_locks--;
940
	lock_info->num_locks--;
941

    
   
941

   
942
	pthread_mutex_unlock(&lock_info->lock);
942
	pthread_mutex_unlock(&lock_info->lock);
943
}
943
}
944

    
   
944

   
945
static const char *locktype2str(enum ast_lock_type type)
945
static const char *locktype2str(enum ast_lock_type type)
946
{
946
{
947
	switch (type) {
947
	switch (type) {
948
	case AST_MUTEX:
948
	case AST_MUTEX:
949
		return "MUTEX";
949
		return "MUTEX";
950
	case AST_RDLOCK:
950
	case AST_RDLOCK:
951
		return "RDLOCK";
951
		return "RDLOCK";
952
	case AST_WRLOCK:
952
	case AST_WRLOCK:
953
		return "WRLOCK";
953
		return "WRLOCK";
954
	}
954
	}
955

    
   
955

   
956
	return "UNKNOWN";
956
	return "UNKNOWN";
957
}
957
}
958

    
   
958

   
959
#ifdef HAVE_BKTR
959
#ifdef HAVE_BKTR
960
static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
960
static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
961
{
961
{
962
	char **symbols;
962
	char **symbols;
963
	int num_frames;
963
	int num_frames;
964

    
   
964

   
965
	if (!bt) {
965
	if (!bt) {
966
		ast_str_append(str, 0, "\tNo backtrace to print\n");
966
		ast_str_append(str, 0, "\tNo backtrace to print\n");
967
		return;
967
		return;
968
	}
968
	}
969

    
   
969

   
970
	/* store frame count locally to avoid the memory corruption that
970
	/* store frame count locally to avoid the memory corruption that
971
	 * sometimes happens on virtualized CentOS 6.x systems */
971
	 * sometimes happens on virtualized CentOS 6.x systems */
972
	num_frames = bt->num_frames;
972
	num_frames = bt->num_frames;
973
	if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
973
	if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
974
		int frame_iterator;
974
		int frame_iterator;
975

    
   
975

   
976
		for (frame_iterator = 0; frame_iterator < num_frames; ++frame_iterator) {
976
		for (frame_iterator = 0; frame_iterator < num_frames; ++frame_iterator) {
977
			ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
977
			ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
978
		}
978
		}
979

    
   
979

   
980
		ast_std_free(symbols);
980
		ast_std_free(symbols);
981
	} else {
981
	} else {
982
		ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
982
		ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
983
	}
983
	}
984
}
984
}
985
#endif
985
#endif
986

    
   
986

   
987
static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
987
static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
988
{
988
{
989
	int j;
989
	int j;
990
	ast_mutex_t *lock;
990
	ast_mutex_t *lock;
991
	struct ast_lock_track *lt;
991
	struct ast_lock_track *lt;
992

    
   
992

   
993
	ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d%s)\n",
993
	ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d%s)\n",
994
				   lock_info->locks[i].pending > 0 ? "Waiting for " :
994
				   lock_info->locks[i].pending > 0 ? "Waiting for " :
995
				   lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
995
				   lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
996
				   lock_info->locks[i].file,
996
				   lock_info->locks[i].file,
997
				   locktype2str(lock_info->locks[i].type),
997
				   locktype2str(lock_info->locks[i].type),
998
				   lock_info->locks[i].line_num,
998
				   lock_info->locks[i].line_num,
999
				   lock_info->locks[i].func, lock_info->locks[i].lock_name,
999
				   lock_info->locks[i].func, lock_info->locks[i].lock_name,
1000
				   lock_info->locks[i].lock_addr,
1000
				   lock_info->locks[i].lock_addr,
1001
				   lock_info->locks[i].times_locked,
1001
				   lock_info->locks[i].times_locked,
1002
				   lock_info->locks[i].suspended ? " - suspended" : "");
1002
				   lock_info->locks[i].suspended ? " - suspended" : "");
1003
#ifdef HAVE_BKTR
1003
#ifdef HAVE_BKTR
1004
	append_backtrace_information(str, lock_info->locks[i].backtrace);
1004
	append_backtrace_information(str, lock_info->locks[i].backtrace);
1005
#endif
1005
#endif
1006

    
   
1006

   
1007
	if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
1007
	if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
1008
		return;
1008
		return;
1009

    
   
1009

   
1010
	/* We only have further details for mutexes right now */
1010
	/* We only have further details for mutexes right now */
1011
	if (lock_info->locks[i].type != AST_MUTEX)
1011
	if (lock_info->locks[i].type != AST_MUTEX)
1012
		return;
1012
		return;
1013

    
   
1013

   
1014
	lock = lock_info->locks[i].lock_addr;
1014
	lock = lock_info->locks[i].lock_addr;
1015
	lt = lock->track;
1015
	lt = lock->track;
1016
	ast_reentrancy_lock(lt);
1016
	ast_reentrancy_lock(lt);
1017
	for (j = 0; *str && j < lt->reentrancy; j++) {
1017
	for (j = 0; *str && j < lt->reentrancy; j++) {
1018
		ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
1018
		ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
1019
					   lt->file[j], lt->lineno[j], lt->func[j]);
1019
					   lt->file[j], lt->lineno[j], lt->func[j]);
1020
	}
1020
	}
1021
	ast_reentrancy_unlock(lt);
1021
	ast_reentrancy_unlock(lt);
1022
}
1022
}
1023

    
   
1023

   
1024

    
   
1024

   
1025
/*! This function can help you find highly temporal locks; locks that happen for a
1025
/*! This function can help you find highly temporal locks; locks that happen for a
1026
    short time, but at unexpected times, usually at times that create a deadlock,
1026
    short time, but at unexpected times, usually at times that create a deadlock,
1027
	Why is this thing locked right then? Who is locking it? Who am I fighting
1027
	Why is this thing locked right then? Who is locking it? Who am I fighting
1028
    with for this lock?
1028
    with for this lock?
1029

    
   
1029

   
1030
	To answer such questions, just call this routine before you would normally try
1030
	To answer such questions, just call this routine before you would normally try
1031
	to aquire a lock. It doesn't do anything if the lock is not acquired. If the
1031
	to aquire a lock. It doesn't do anything if the lock is not acquired. If the
1032
	lock is taken, it will publish a line or two to the console via ast_log().
1032
	lock is taken, it will publish a line or two to the console via ast_log().
1033

    
   
1033

   
1034
	Sometimes, the lock message is pretty uninformative. For instance, you might
1034
	Sometimes, the lock message is pretty uninformative. For instance, you might
1035
	find that the lock is being aquired deep within the astobj2 code; this tells
1035
	find that the lock is being aquired deep within the astobj2 code; this tells
1036
	you little about higher level routines that call the astobj2 routines.
1036
	you little about higher level routines that call the astobj2 routines.
1037
	But, using gdb, you can set a break at the ast_log below, and for that
1037
	But, using gdb, you can set a break at the ast_log below, and for that
1038
	breakpoint, you can set the commands:
1038
	breakpoint, you can set the commands:
1039
	  where
1039
	  where
1040
	  cont
1040
	  cont
1041
	which will give a stack trace and continue. -- that aught to do the job!
1041
	which will give a stack trace and continue. -- that aught to do the job!
1042

    
   
1042

   
1043
*/
1043
*/
1044
void ast_log_show_lock(void *this_lock_addr)
1044
void ast_log_show_lock(void *this_lock_addr)
1045
{
1045
{
1046
	struct thr_lock_info *lock_info;
1046
	struct thr_lock_info *lock_info;
1047
	struct ast_str *str;
1047
	struct ast_str *str;
1048

    
   
1048

   
1049
	if (!(str = ast_str_create(4096))) {
1049
	if (!(str = ast_str_create(4096))) {
1050
		ast_log(LOG_NOTICE,"Could not create str\n");
1050
		ast_log(LOG_NOTICE,"Could not create str\n");
1051
		return;
1051
		return;
1052
	}
1052
	}
1053

    
   
1053

   
1054

    
   
1054

   
1055
	pthread_mutex_lock(&lock_infos_lock.mutex);
1055
	pthread_mutex_lock(&lock_infos_lock.mutex);
1056
	AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1056
	AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1057
		int i;
1057
		int i;
1058
		pthread_mutex_lock(&lock_info->lock);
1058
		pthread_mutex_lock(&lock_info->lock);
1059
		for (i = 0; str && i < lock_info->num_locks; i++) {
1059
		for (i = 0; str && i < lock_info->num_locks; i++) {
1060
			/* ONLY show info about this particular lock, if
1060
			/* ONLY show info about this particular lock, if
1061
			   it's acquired... */
1061
			   it's acquired... */
1062
			if (lock_info->locks[i].lock_addr == this_lock_addr) {
1062
			if (lock_info->locks[i].lock_addr == this_lock_addr) {
1063
				append_lock_information(&str, lock_info, i);
1063
				append_lock_information(&str, lock_info, i);
1064
				ast_log(LOG_NOTICE, "%s", ast_str_buffer(str));
1064
				ast_log(LOG_NOTICE, "%s", ast_str_buffer(str));
1065
				break;
1065
				break;
1066
			}
1066
			}
1067
		}
1067
		}
1068
		pthread_mutex_unlock(&lock_info->lock);
1068
		pthread_mutex_unlock(&lock_info->lock);
1069
	}
1069
	}
1070
	pthread_mutex_unlock(&lock_infos_lock.mutex);
1070
	pthread_mutex_unlock(&lock_infos_lock.mutex);
1071
	ast_free(str);
1071
	ast_free(str);
1072
}
1072
}
1073

    
   
1073

   
1074

    
   
1074

   
1075
struct ast_str *ast_dump_locks(void)
1075
struct ast_str *ast_dump_locks(void)
1076
{
1076
{
1077
	struct thr_lock_info *lock_info;
1077
	struct thr_lock_info *lock_info;
1078
	struct ast_str *str;
1078
	struct ast_str *str;
1079

    
   
1079

   
1080
	if (!(str = ast_str_create(4096))) {
1080
	if (!(str = ast_str_create(4096))) {
1081
		return NULL;
1081
		return NULL;
1082
	}
1082
	}
1083

    
   
1083

   
1084
	ast_str_append(&str, 0, "\n"
1084
	ast_str_append(&str, 0, "\n"
1085
	               "=======================================================================\n"
1085
	               "=======================================================================\n"
1086
	               "=== %s\n"
1086
	               "=== %s\n"
1087
	               "=== Currently Held Locks\n"
1087
	               "=== Currently Held Locks\n"
1088
	               "=======================================================================\n"
1088
	               "=======================================================================\n"
1089
	               "===\n"
1089
	               "===\n"
1090
	               "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
1090
	               "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
1091
	               "===\n", ast_get_version());
1091
	               "===\n", ast_get_version());
1092

    
   
1092

   
1093
	if (!str) {
1093
	if (!str) {
1094
		return NULL;
1094
		return NULL;
1095
	}
1095
	}
1096

    
   
1096

   
1097
	pthread_mutex_lock(&lock_infos_lock.mutex);
1097
	pthread_mutex_lock(&lock_infos_lock.mutex);
1098
	AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1098
	AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
1099
		int i;
1099
		int i;
1100
		int header_printed = 0;
1100
		int header_printed = 0;
1101
		pthread_mutex_lock(&lock_info->lock);
1101
		pthread_mutex_lock(&lock_info->lock);
1102
		for (i = 0; str && i < lock_info->num_locks; i++) {
1102
		for (i = 0; str && i < lock_info->num_locks; i++) {
1103
			/* Don't show suspended locks */
1103
			/* Don't show suspended locks */
1104
			if (lock_info->locks[i].suspended) {
1104
			if (lock_info->locks[i].suspended) {
1105
				continue;
1105
				continue;
1106
			}
1106
			}
1107

    
   
1107

   
1108
			if (!header_printed) {
1108
			if (!header_printed) {
1109
				if (lock_info->lwp != -1) {
1109
				if (lock_info->lwp != -1) {
1110
					ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
1110
					ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
1111
						(long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
1111
						(long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
1112
				} else {
1112
				} else {
1113
					ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
1113
					ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
1114
						(long unsigned) lock_info->thread_id, lock_info->thread_name);
1114
						(long unsigned) lock_info->thread_id, lock_info->thread_name);
1115
				}
1115
				}
1116
				header_printed = 1;
1116
				header_printed = 1;
1117
			}
1117
			}
1118

    
   
1118

   
1119
			append_lock_information(&str, lock_info, i);
1119
			append_lock_information(&str, lock_info, i);
1120
		}
1120
		}
1121
		pthread_mutex_unlock(&lock_info->lock);
1121
		pthread_mutex_unlock(&lock_info->lock);
1122
		if (!str) {
1122
		if (!str) {
1123
			break;
1123
			break;
1124
		}
1124
		}
1125
		if (header_printed) {
1125
		if (header_printed) {
1126
			ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
1126
			ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
1127
				"===\n");
1127
				"===\n");
1128
		}
1128
		}
1129
		if (!str) {
1129
		if (!str) {
1130
			break;
1130
			break;
1131
		}
1131
		}
1132
	}
1132
	}
1133
	pthread_mutex_unlock(&lock_infos_lock.mutex);
1133
	pthread_mutex_unlock(&lock_infos_lock.mutex);
1134

    
   
1134

   
1135
	if (!str) {
1135
	if (!str) {
1136
		return NULL;
1136
		return NULL;
1137
	}
1137
	}
1138

    
   
1138

   
1139
	ast_str_append(&str, 0, "=======================================================================\n"
1139
	ast_str_append(&str, 0, "=======================================================================\n"
1140
	               "\n");
1140
	               "\n");
1141

    
   
1141

   
1142
	return str;
1142
	return str;
1143
}
1143
}
1144

    
   
1144

   
1145
static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1145
static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1146
{
1146
{
1147
	struct ast_str *str;
1147
	struct ast_str *str;
1148

    
   
1148

   
1149
	switch (cmd) {
1149
	switch (cmd) {
1150
	case CLI_INIT:
1150
	case CLI_INIT:
1151
		e->command = "core show locks";
1151
		e->command = "core show locks";
1152
		e->usage =
1152
		e->usage =
1153
			"Usage: core show locks\n"
1153
			"Usage: core show locks\n"
1154
			"       This command is for lock debugging.  It prints out which locks\n"
1154
			"       This command is for lock debugging.  It prints out which locks\n"
1155
			"are owned by each active thread.\n";
1155
			"are owned by each active thread.\n";
1156
		return NULL;
1156
		return NULL;
1157

    
   
1157

   
1158
	case CLI_GENERATE:
1158
	case CLI_GENERATE:
1159
		return NULL;
1159
		return NULL;
1160
	}
1160
	}
1161

    
   
1161

   
1162
	str = ast_dump_locks();
1162
	str = ast_dump_locks();
1163
	if (!str) {
1163
	if (!str) {
1164
		return CLI_FAILURE;
1164
		return CLI_FAILURE;
1165
	}
1165
	}
1166

    
   
1166

   
1167
	ast_cli(a->fd, "%s", ast_str_buffer(str));
1167
	ast_cli(a->fd, "%s", ast_str_buffer(str));
1168

    
   
1168

   
1169
	ast_free(str);
1169
	ast_free(str);
1170

    
   
1170

   
1171
	return CLI_SUCCESS;
1171
	return CLI_SUCCESS;
1172
}
1172
}
1173

    
   
1173

   
1174
static struct ast_cli_entry utils_cli[] = {
1174
static struct ast_cli_entry utils_cli[] = {
1175
	AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
1175
	AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
1176
};
1176
};
1177

    
   
1177

   
1178
#endif /* DEBUG_THREADS */
1178
#endif /* DEBUG_THREADS */
1179

    
   
1179

   
1180
/*
1180
/*
1181
 * support for 'show threads'. The start routine is wrapped by
1181
 * support for 'show threads'. The start routine is wrapped by
1182
 * dummy_start(), so that ast_register_thread() and
1182
 * dummy_start(), so that ast_register_thread() and
1183
 * ast_unregister_thread() know the thread identifier.
1183
 * ast_unregister_thread() know the thread identifier.
1184
 */
1184
 */
1185
struct thr_arg {
1185
struct thr_arg {
1186
	void *(*start_routine)(void *);
1186
	void *(*start_routine)(void *);
1187
	void *data;
1187
	void *data;
1188
	char *name;
1188
	char *name;
1189
};
1189
};
1190

    
   
1190

   
1191
/*
1191
/*
1192
 * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
1192
 * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
1193
 * are odd macros which start and end a block, so they _must_ be
1193
 * are odd macros which start and end a block, so they _must_ be
1194
 * used in pairs (the latter with a '1' argument to call the
1194
 * used in pairs (the latter with a '1' argument to call the
1195
 * handler on exit.
1195
 * handler on exit.
1196
 * On BSD we don't need this, but we keep it for compatibility.
1196
 * On BSD we don't need this, but we keep it for compatibility.
1197
 */
1197
 */
1198
static void *dummy_start(void *data)
1198
static void *dummy_start(void *data)
1199
{
1199
{
1200
	void *ret;
1200
	void *ret;
1201
	struct thr_arg a = *((struct thr_arg *) data);	/* make a local copy */
1201
	struct thr_arg a = *((struct thr_arg *) data);	/* make a local copy */
1202
#ifdef DEBUG_THREADS
1202
#ifdef DEBUG_THREADS
1203
	struct thr_lock_info *lock_info;
1203
	struct thr_lock_info *lock_info;
1204
	pthread_mutexattr_t mutex_attr;
1204
	pthread_mutexattr_t mutex_attr;
1205

    
   
1205

   
1206
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1206
	if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
1207
		return NULL;
1207
		return NULL;
1208

    
   
1208

   
1209
	lock_info->thread_id = pthread_self();
1209
	lock_info->thread_id = pthread_self();
1210
	lock_info->lwp = ast_get_tid();
1210
	lock_info->lwp = ast_get_tid();
1211
	lock_info->thread_name = strdup(a.name);
1211
	lock_info->thread_name = strdup(a.name);
1212

    
   
1212

   
1213
	pthread_mutexattr_init(&mutex_attr);
1213
	pthread_mutexattr_init(&mutex_attr);
1214
	pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
1214
	pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
1215
	pthread_mutex_init(&lock_info->lock, &mutex_attr);
1215
	pthread_mutex_init(&lock_info->lock, &mutex_attr);
1216
	pthread_mutexattr_destroy(&mutex_attr);
1216
	pthread_mutexattr_destroy(&mutex_attr);
1217

    
   
1217

   
1218
	pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1218
	pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1219
	AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
1219
	AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
1220
	pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1220
	pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
1221
#endif /* DEBUG_THREADS */
1221
#endif /* DEBUG_THREADS */
1222

    
   
1222

   
1223
	/* note that even though data->name is a pointer to allocated memory,
1223
	/* note that even though data->name is a pointer to allocated memory,
1224
	   we are not freeing it here because ast_register_thread is going to
1224
	   we are not freeing it here because ast_register_thread is going to
1225
	   keep a copy of the pointer and then ast_unregister_thread will
1225
	   keep a copy of the pointer and then ast_unregister_thread will
1226
	   free the memory
1226
	   free the memory
1227
	*/
1227
	*/
1228
	ast_free(data);
1228
	ast_free(data);
1229
	ast_register_thread(a.name);
1229
	ast_register_thread(a.name);
1230
	pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
1230
	pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
1231

    
   
1231

   
1232
	ret = a.start_routine(a.data);
1232
	ret = a.start_routine(a.data);
1233

    
   
1233

   
1234
	pthread_cleanup_pop(1);
1234
	pthread_cleanup_pop(1);
1235

    
   
1235

   
1236
	return ret;
1236
	return ret;
1237
}
1237
}
1238

    
   
1238

   
1239
#endif /* !LOW_MEMORY */
1239
#endif /* !LOW_MEMORY */
1240

    
   
1240

   
1241
int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1241
int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1242
			     void *data, size_t stacksize, const char *file, const char *caller,
1242
			     void *data, size_t stacksize, const char *file, const char *caller,
1243
			     int line, const char *start_fn)
1243
			     int line, const char *start_fn)
1244
{
1244
{
1245
#if !defined(LOW_MEMORY)
1245
#if !defined(LOW_MEMORY)
1246
	struct thr_arg *a;
1246
	struct thr_arg *a;
1247
#endif
1247
#endif
1248

    
   
1248

   
1249
	if (!attr) {
1249
	if (!attr) {
1250
		attr = ast_alloca(sizeof(*attr));
1250
		attr = ast_alloca(sizeof(*attr));
1251
		pthread_attr_init(attr);
1251
		pthread_attr_init(attr);
1252
	}
1252
	}
1253

    
   
1253

   
1254
#ifdef __linux__
1254
#ifdef __linux__
1255
	/* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
1255
	/* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
1256
	   which is kind of useless. Change this here to
1256
	   which is kind of useless. Change this here to
1257
	   PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
1257
	   PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
1258
	   priority will propagate down to new threads by default.
1258
	   priority will propagate down to new threads by default.
1259
	   This does mean that callers cannot set a different priority using
1259
	   This does mean that callers cannot set a different priority using
1260
	   PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
1260
	   PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
1261
	   the priority afterwards with pthread_setschedparam(). */
1261
	   the priority afterwards with pthread_setschedparam(). */
1262
	if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1262
	if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
1263
		ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
1263
		ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
1264
#endif
1264
#endif
1265

    
   
1265

   
1266
	if (!stacksize)
1266
	if (!stacksize)
1267
		stacksize = AST_STACKSIZE;
1267
		stacksize = AST_STACKSIZE;
1268

    
   
1268

   
1269
	if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
1269
	if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
1270
		ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
1270
		ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
1271

    
   
1271

   
1272
#if !defined(LOW_MEMORY)
1272
#if !defined(LOW_MEMORY)
1273
	if ((a = ast_malloc(sizeof(*a)))) {
1273
	if ((a = ast_malloc(sizeof(*a)))) {
1274
		a->start_routine = start_routine;
1274
		a->start_routine = start_routine;
1275
		a->data = data;
1275
		a->data = data;
1276
		start_routine = dummy_start;
1276
		start_routine = dummy_start;
1277
		if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
1277
		if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
1278
			     start_fn, line, file, caller) < 0) {
1278
			     start_fn, line, file, caller) < 0) {
1279
			a->name = NULL;
1279
			a->name = NULL;
1280
		}
1280
		}
1281
		data = a;
1281
		data = a;
1282
	}
1282
	}
1283
#endif /* !LOW_MEMORY */
1283
#endif /* !LOW_MEMORY */
1284

    
   
1284

   
1285
	return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
1285
	return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
1286
}
1286
}
1287

    
   
1287

   
1288

    
   
1288

   
1289
int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1289
int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
1290
			     void *data, size_t stacksize, const char *file, const char *caller,
1290
			     void *data, size_t stacksize, const char *file, const char *caller,
1291
			     int line, const char *start_fn)
1291
			     int line, const char *start_fn)
1292
{
1292
{
1293
	unsigned char attr_destroy = 0;
1293
	unsigned char attr_destroy = 0;
1294
	int res;
1294
	int res;
1295

    
   
1295

   
1296
	if (!attr) {
1296
	if (!attr) {
1297
		attr = ast_alloca(sizeof(*attr));
1297
		attr = ast_alloca(sizeof(*attr));
1298
		pthread_attr_init(attr);
1298
		pthread_attr_init(attr);
1299
		attr_destroy = 1;
1299
		attr_destroy = 1;
1300
	}
1300
	}
1301

    
   
1301

   
1302
	if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1302
	if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
1303
		ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
1303
		ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
1304

    
   
1304

   
1305
	res = ast_pthread_create_stack(thread, attr, start_routine, data,
1305
	res = ast_pthread_create_stack(thread, attr, start_routine, data,
1306
	                               stacksize, file, caller, line, start_fn);
1306
	                               stacksize, file, caller, line, start_fn);
1307

    
   
1307

   
1308
	if (attr_destroy)
1308
	if (attr_destroy)
1309
		pthread_attr_destroy(attr);
1309
		pthread_attr_destroy(attr);
1310

    
   
1310

   
1311
	return res;
1311
	return res;
1312
}
1312
}
1313

    
   
1313

   
1314
int ast_wait_for_input(int fd, int ms)
1314
int ast_wait_for_input(int fd, int ms)
1315
{
1315
{
1316
	struct pollfd pfd[1];
1316
	struct pollfd pfd[1];
1317

    
   
1317

   
1318
	memset(pfd, 0, sizeof(pfd));
1318
	memset(pfd, 0, sizeof(pfd));
1319
	pfd[0].fd = fd;
1319
	pfd[0].fd = fd;
1320
	pfd[0].events = POLLIN | POLLPRI;
1320
	pfd[0].events = POLLIN | POLLPRI;
1321
	return ast_poll(pfd, 1, ms);
1321
	return ast_poll(pfd, 1, ms);
1322
}
1322
}
1323

    
   
1323

   
1324
int ast_wait_for_output(int fd, int ms)
1324
int ast_wait_for_output(int fd, int ms)
1325
{
1325
{
1326
	struct pollfd pfd[1];
1326
	struct pollfd pfd[1];
1327

    
   
1327

   
1328
	memset(pfd, 0, sizeof(pfd));
1328
	memset(pfd, 0, sizeof(pfd));
1329
	pfd[0].fd = fd;
1329
	pfd[0].fd = fd;
1330
	pfd[0].events = POLLOUT;
1330
	pfd[0].events = POLLOUT;
1331
	return ast_poll(pfd, 1, ms);
1331
	return ast_poll(pfd, 1, ms);
1332
}
1332
}
1333

    
   
1333

   
1334
static int wait_for_output(int fd, int timeoutms)
1334
static int wait_for_output(int fd, int timeoutms)
1335
{
1335
{
1336
	struct pollfd pfd = {
1336
	struct pollfd pfd = {
1337
		.fd = fd,
1337
		.fd = fd,
1338
		.events = POLLOUT,
1338
		.events = POLLOUT,
1339
	};
1339
	};
1340
	int res;
1340
	int res;
1341
	struct timeval start = ast_tvnow();
1341
	struct timeval start = ast_tvnow();
1342
	int elapsed = 0;
1342
	int elapsed = 0;
1343

    
   
1343

   
1344
	/* poll() until the fd is writable without blocking */
1344
	/* poll() until the fd is writable without blocking */
1345
	while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1345
	while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
1346
		if (res == 0) {
1346
		if (res == 0) {
1347
			/* timed out. */
1347
			/* timed out. */
1348
#ifndef STANDALONE
1348
#ifndef STANDALONE
1349
			ast_debug(1, "Timed out trying to write\n");
1349
			ast_debug(1, "Timed out trying to write\n");
1350
#endif
1350
#endif
1351
			return -1;
1351
			return -1;
1352
		} else if (res == -1) {
1352
		} else if (res == -1) {
1353
			/* poll() returned an error, check to see if it was fatal */
1353
			/* poll() returned an error, check to see if it was fatal */
1354

    
   
1354

   
1355
			if (errno == EINTR || errno == EAGAIN) {
1355
			if (errno == EINTR || errno == EAGAIN) {
1356
				elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1356
				elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1357
				if (elapsed >= timeoutms) {
1357
				if (elapsed >= timeoutms) {
1358
					return -1;
1358
					return -1;
1359
				}
1359
				}
1360
				/* This was an acceptable error, go back into poll() */
1360
				/* This was an acceptable error, go back into poll() */
1361
				continue;
1361
				continue;
1362
			}
1362
			}
1363

    
   
1363

   
1364
			/* Fatal error, bail. */
1364
			/* Fatal error, bail. */
1365
			ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
1365
			ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
1366

    
   
1366

   
1367
			return -1;
1367
			return -1;
1368
		}
1368
		}
1369
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1369
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1370
		if (elapsed >= timeoutms) {
1370
		if (elapsed >= timeoutms) {
1371
			return -1;
1371
			return -1;
1372
		}
1372
		}
1373
	}
1373
	}
1374

    
   
1374

   
1375
	return 0;
1375
	return 0;
1376
}
1376
}
1377

    
   
1377

   
1378
/*!
1378
/*!
1379
 * Try to write string, but wait no more than ms milliseconds before timing out.
1379
 * Try to write string, but wait no more than ms milliseconds before timing out.
1380
 *
1380
 *
1381
 * \note The code assumes that the file descriptor has NONBLOCK set,
1381
 * \note The code assumes that the file descriptor has NONBLOCK set,
1382
 * so there is only one system call made to do a write, unless we actually
1382
 * so there is only one system call made to do a write, unless we actually
1383
 * have a need to wait.  This way, we get better performance.
1383
 * have a need to wait.  This way, we get better performance.
1384
 * If the descriptor is blocking, all assumptions on the guaranteed
1384
 * If the descriptor is blocking, all assumptions on the guaranteed
1385
 * detail do not apply anymore.
1385
 * detail do not apply anymore.
1386
 */
1386
 */
1387
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
1387
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
1388
{
1388
{
1389
	struct timeval start = ast_tvnow();
1389
	struct timeval start = ast_tvnow();
1390
	int res = 0;
1390
	int res = 0;
1391
	int elapsed = 0;
1391
	int elapsed = 0;
1392

    
   
1392

   
1393
	while (len) {
1393
	while (len) {
1394
		if (wait_for_output(fd, timeoutms - elapsed)) {
1394
		if (wait_for_output(fd, timeoutms - elapsed)) {
1395
			return -1;
1395
			return -1;
1396
		}
1396
		}
1397

    
   
1397

   
1398
		res = write(fd, s, len);
1398
		res = write(fd, s, len);
1399

    
   
1399

   
1400
		if (res < 0 && errno != EAGAIN && errno != EINTR) {
1400
		if (res < 0 && errno != EAGAIN && errno != EINTR) {
1401
			/* fatal error from write() */
1401
			/* fatal error from write() */
1402
			ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
1402
			ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
1403
			return -1;
1403
			return -1;
1404
		}
1404
		}
1405

    
   
1405

   
1406
		if (res < 0) {
1406
		if (res < 0) {
1407
			/* It was an acceptable error */
1407
			/* It was an acceptable error */
1408
			res = 0;
1408
			res = 0;
1409
		}
1409
		}
1410

    
   
1410

   
1411
		/* Update how much data we have left to write */
1411
		/* Update how much data we have left to write */
1412
		len -= res;
1412
		len -= res;
1413
		s += res;
1413
		s += res;
1414
		res = 0;
1414
		res = 0;
1415

    
   
1415

   
1416
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1416
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1417
		if (elapsed >= timeoutms) {
1417
		if (elapsed >= timeoutms) {
1418
			/* We've taken too long to write
1418
			/* We've taken too long to write
1419
			 * This is only an error condition if we haven't finished writing. */
1419
			 * This is only an error condition if we haven't finished writing. */
1420
			res = len ? -1 : 0;
1420
			res = len ? -1 : 0;
1421
			break;
1421
			break;
1422
		}
1422
		}
1423
	}
1423
	}
1424

    
   
1424

   
1425
	return res;
1425
	return res;
1426
}
1426
}
1427

    
   
1427

   
1428
int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeoutms)
1428
int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeoutms)
1429
{
1429
{
1430
	struct timeval start = ast_tvnow();
1430
	struct timeval start = ast_tvnow();
1431
	int n = 0;
1431
	int n = 0;
1432
	int elapsed = 0;
1432
	int elapsed = 0;
1433

    
   
1433

   
1434
	while (len) {
1434
	while (len) {
1435
		if (wait_for_output(fd, timeoutms - elapsed)) {
1435
		if (wait_for_output(fd, timeoutms - elapsed)) {
1436
			/* poll returned a fatal error, so bail out immediately. */
1436
			/* poll returned a fatal error, so bail out immediately. */
1437
			return -1;
1437
			return -1;
1438
		}
1438
		}
1439

    
   
1439

   
1440
		/* Clear any errors from a previous write */
1440
		/* Clear any errors from a previous write */
1441
		clearerr(f);
1441
		clearerr(f);
1442

    
   
1442

   
1443
		n = fwrite(src, 1, len, f);
1443
		n = fwrite(src, 1, len, f);
1444

    
   
1444

   
1445
		if (ferror(f) && errno != EINTR && errno != EAGAIN) {
1445
		if (ferror(f) && errno != EINTR && errno != EAGAIN) {
1446
			/* fatal error from fwrite() */
1446
			/* fatal error from fwrite() */
1447
			if (!feof(f)) {
1447
			if (!feof(f)) {
1448
				/* Don't spam the logs if it was just that the connection is closed. */
1448
				/* Don't spam the logs if it was just that the connection is closed. */
1449
				ast_log(LOG_ERROR, "fwrite() returned error: %s\n", strerror(errno));
1449
				ast_log(LOG_ERROR, "fwrite() returned error: %s\n", strerror(errno));
1450
			}
1450
			}
1451
			n = -1;
1451
			n = -1;
1452
			break;
1452
			break;
1453
		}
1453
		}
1454

    
   
1454

   
1455
		/* Update for data already written to the socket */
1455
		/* Update for data already written to the socket */
1456
		len -= n;
1456
		len -= n;
1457
		src += n;
1457
		src += n;
1458

    
   
1458

   
1459
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1459
		elapsed = ast_tvdiff_ms(ast_tvnow(), start);
1460
		if (elapsed >= timeoutms) {
1460
		if (elapsed >= timeoutms) {
1461
			/* We've taken too long to write
1461
			/* We've taken too long to write
1462
			 * This is only an error condition if we haven't finished writing. */
1462
			 * This is only an error condition if we haven't finished writing. */
1463
			n = len ? -1 : 0;
1463
			n = len ? -1 : 0;
1464
			break;
1464
			break;
1465
		}
1465
		}
1466
	}
1466
	}
1467

    
   
1467

   
1468
	errno = 0;
1468
	errno = 0;
1469
	while (fflush(f)) {
1469
	while (fflush(f)) {
1470
		if (errno == EAGAIN || errno == EINTR) {
1470
		if (errno == EAGAIN || errno == EINTR) {
1471
			/* fflush() does not appear to reset errno if it flushes
1471
			/* fflush() does not appear to reset errno if it flushes
1472
			 * and reaches EOF at the same time. It returns EOF with
1472
			 * and reaches EOF at the same time. It returns EOF with
1473
			 * the last seen value of errno, causing a possible loop.
1473
			 * the last seen value of errno, causing a possible loop.
1474
			 * Also usleep() to reduce CPU eating if it does loop */
1474
			 * Also usleep() to reduce CPU eating if it does loop */
1475
			errno = 0;
1475
			errno = 0;
1476
			usleep(1);
1476
			usleep(1);
1477
			continue;
1477
			continue;
1478
		}
1478
		}
1479
		if (errno && !feof(f)) {
1479
		if (errno && !feof(f)) {
1480
			/* Don't spam the logs if it was just that the connection is closed. */
1480
			/* Don't spam the logs if it was just that the connection is closed. */
1481
			ast_log(LOG_ERROR, "fflush() returned error: %s\n", strerror(errno));
1481
			ast_log(LOG_ERROR, "fflush() returned error: %s\n", strerror(errno));
1482
		}
1482
		}
1483
		n = -1;
1483
		n = -1;
1484
		break;
1484
		break;
1485
	}
1485
	}
1486

    
   
1486

   
1487
	return n < 0 ? -1 : 0;
1487
	return n < 0 ? -1 : 0;
1488
}
1488
}
1489

    
   
1489

   
1490
char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
1490
char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
1491
{
1491
{
1492
	char *e;
1492
	char *e;
1493
	char *q;
1493
	char *q;
1494

    
   
1494

   
1495
	s = ast_strip(s);
1495
	s = ast_strip(s);
1496
	if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
1496
	if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
1497
		e = s + strlen(s) - 1;
1497
		e = s + strlen(s) - 1;
1498
		if (*e == *(end_quotes + (q - beg_quotes))) {
1498
		if (*e == *(end_quotes + (q - beg_quotes))) {
1499
			s++;
1499
			s++;
1500
			*e = '\0';
1500
			*e = '\0';
1501
		}
1501
		}
1502
	}
1502
	}
1503

    
   
1503

   
1504
	return s;
1504
	return s;
1505
}
1505
}
1506

    
   
1506

   
1507
char *ast_strsep(char **iss, const char sep, uint32_t flags)
1507
char *ast_strsep(char **iss, const char sep, uint32_t flags)
1508
{
1508
{
1509
	char *st = *iss;
1509
	char *st = *iss;
1510
	char *is;
1510
	char *is;
1511
	int inquote = 0;
1511
	int inquote = 0;
1512
	int found = 0;
1512
	int found = 0;
1513
	char stack[8];
1513
	char stack[8];
1514

    
   
1514

   
1515
	if (iss == NULL || *iss == '\0') {
1515
	if (iss == NULL || *iss == '\0') {
1516
		return NULL;
1516
		return NULL;
1517
	}
1517
	}
1518

    
   
1518

   
1519
	memset(stack, 0, sizeof(stack));
1519
	memset(stack, 0, sizeof(stack));
1520

    
   
1520

   
1521
	for(is = st; *is; is++) {
1521
	for(is = st; *is; is++) {
1522
		if (*is == '\\') {
1522
		if (*is == '\\') {
1523
			if (*++is != '\0') {
1523
			if (*++is != '\0') {
1524
				is++;
1524
				is++;
1525
			} else {
1525
			} else {
1526
				break;
1526
				break;
1527
			}
1527
			}
1528
		}
1528
		}
1529

    
   
1529

   
1530
		if (*is == '\'' || *is == '"') {
1530
		if (*is == '\'' || *is == '"') {
1531
			if (*is == stack[inquote]) {
1531
			if (*is == stack[inquote]) {
1532
				stack[inquote--] = '\0';
1532
				stack[inquote--] = '\0';
1533
			} else {
1533
			} else {
1534
				if (++inquote >= sizeof(stack)) {
1534
				if (++inquote >= sizeof(stack)) {
1535
					return NULL;
1535
					return NULL;
1536
				}
1536
				}
1537
				stack[inquote] = *is;
1537
				stack[inquote] = *is;
1538
			}
1538
			}
1539
		}
1539
		}
1540

    
   
1540

   
1541
		if (*is == sep && !inquote) {
1541
		if (*is == sep && !inquote) {
1542
			*is = '\0';
1542
			*is = '\0';
1543
			found = 1;
1543
			found = 1;
1544
			*iss = is + 1;
1544
			*iss = is + 1;
1545
			break;
1545
			break;
1546
		}
1546
		}
1547
	}
1547
	}
1548
	if (!found) {
1548
	if (!found) {
1549
		*iss = NULL;
1549
		*iss = NULL;
1550
	}
1550
	}
1551

    
   
1551

   
1552
	if (flags & AST_STRSEP_STRIP) {
1552
	if (flags & AST_STRSEP_STRIP) {
1553
		st = ast_strip_quoted(st, "'\"", "'\"");
1553
		st = ast_strip_quoted(st, "'\"", "'\"");
1554
	}
1554
	}
1555

    
   
1555

   
1556
	if (flags & AST_STRSEP_TRIM) {
1556
	if (flags & AST_STRSEP_TRIM) {
1557
		st = ast_strip(st);
1557
		st = ast_strip(st);
1558
	}
1558
	}
1559

    
   
1559

   
1560
	if (flags & AST_STRSEP_UNESCAPE) {
1560
	if (flags & AST_STRSEP_UNESCAPE) {
1561
		ast_unescape_quoted(st);
1561
		ast_unescape_quoted(st);
1562
	}
1562
	}
1563

    
   
1563

   
1564
	return st;
1564
	return st;
1565
}
1565
}
1566

    
   
1566

   
1567
char *ast_unescape_semicolon(char *s)
1567
char *ast_unescape_semicolon(char *s)
1568
{
1568
{
1569
	char *e;
1569
	char *e;
1570
	char *work = s;
1570
	char *work = s;
1571

    
   
1571

   
1572
	while ((e = strchr(work, ';'))) {
1572
	while ((e = strchr(work, ';'))) {
1573
		if ((e > work) && (*(e-1) == '\\')) {
1573
		if ((e > work) && (*(e-1) == '\\')) {
1574
			memmove(e - 1, e, strlen(e) + 1);
1574
			memmove(e - 1, e, strlen(e) + 1);
1575
			work = e;
1575
			work = e;
1576
		} else {
1576
		} else {
1577
			work = e + 1;
1577
			work = e + 1;
1578
		}
1578
		}
1579
	}
1579
	}
1580

    
   
1580

   
1581
	return s;
1581
	return s;
1582
}
1582
}
1583

    
   
1583

   
1584
/* !\brief unescape some C sequences in place, return pointer to the original string.
1584
/* !\brief unescape some C sequences in place, return pointer to the original string.
1585
 */
1585
 */
1586
char *ast_unescape_c(char *src)
1586
char *ast_unescape_c(char *src)
1587
{
1587
{
1588
	char c, *ret, *dst;
1588
	char c, *ret, *dst;
1589

    
   
1589

   
1590
	if (src == NULL)
1590
	if (src == NULL)
1591
		return NULL;
1591
		return NULL;
1592
	for (ret = dst = src; (c = *src++); *dst++ = c ) {
1592
	for (ret = dst = src; (c = *src++); *dst++ = c ) {
1593
		if (c != '\\')
1593
		if (c != '\\')
1594
			continue;	/* copy char at the end of the loop */
1594
			continue;	/* copy char at the end of the loop */
1595
		switch ((c = *src++)) {
1595
		switch ((c = *src++)) {
1596
		case '\0':	/* special, trailing '\' */
1596
		case '\0':	/* special, trailing '\' */
1597
			c = '\\';
1597
			c = '\\';
1598
			break;
1598
			break;
1599
		case 'b':	/* backspace */
1599
		case 'b':	/* backspace */
1600
			c = '\b';
1600
			c = '\b';
1601
			break;
1601
			break;
1602
		case 'f':	/* form feed */
1602
		case 'f':	/* form feed */
1603
			c = '\f';
1603
			c = '\f';
1604
			break;
1604
			break;
1605
		case 'n':
1605
		case 'n':
1606
			c = '\n';
1606
			c = '\n';
1607
			break;
1607
			break;
1608
		case 'r':
1608
		case 'r':
1609
			c = '\r';
1609
			c = '\r';
1610
			break;
1610
			break;
1611
		case 't':
1611
		case 't':
1612
			c = '\t';
1612
			c = '\t';
1613
			break;
1613
			break;
1614
		}
1614
		}
1615
		/* default, use the char literally */
1615
		/* default, use the char literally */
1616
	}
1616
	}
1617
	*dst = '\0';
1617
	*dst = '\0';
1618
	return ret;
1618
	return ret;
1619
}
1619
}
1620

    
   
1620

   
1621
int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
1621
int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
1622
{
1622
{
1623
	int result;
1623
	int result;
1624

    
   
1624

   
1625
	if (!buffer || !*buffer || !space || !*space)
1625
	if (!buffer || !*buffer || !space || !*space)
1626
		return -1;
1626
		return -1;
1627

    
   
1627

   
1628
	result = vsnprintf(*buffer, *space, fmt, ap);
1628
	result = vsnprintf(*buffer, *space, fmt, ap);
1629

    
   
1629

   
1630
	if (result < 0)
1630
	if (result < 0)
1631
		return -1;
1631
		return -1;
1632
	else if (result > *space)
1632
	else if (result > *space)
1633
		result = *space;
1633
		result = *space;
1634

    
   
1634

   
1635
	*buffer += result;
1635
	*buffer += result;
1636
	*space -= result;
1636
	*space -= result;
1637
	return 0;
1637
	return 0;
1638
}
1638
}
1639

    
   
1639

   
1640
int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
1640
int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
1641
{
1641
{
1642
	va_list ap;
1642
	va_list ap;
1643
	int result;
1643
	int result;
1644

    
   
1644

   
1645
	va_start(ap, fmt);
1645
	va_start(ap, fmt);
1646
	result = ast_build_string_va(buffer, space, fmt, ap);
1646
	result = ast_build_string_va(buffer, space, fmt, ap);
1647
	va_end(ap);
1647
	va_end(ap);
1648

    
   
1648

   
1649
	return result;
1649
	return result;
1650
}
1650
}
1651

    
   
1651

   
1652
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
1652
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
1653
{
1653
{
1654
	int regex_len = strlen(regex_string);
1654
	int regex_len = strlen(regex_string);
1655
	int ret = 3;
1655
	int ret = 3;
1656

    
   
1656

   
1657
	/* Chop off the leading / if there is one */
1657
	/* Chop off the leading / if there is one */
1658
	if ((regex_len >= 1) && (regex_string[0] == '/')) {
1658
	if ((regex_len >= 1) && (regex_string[0] == '/')) {
1659
		ast_str_set(regex_pattern, 0, "%s", regex_string + 1);
1659
		ast_str_set(regex_pattern, 0, "%s", regex_string + 1);
1660
		ret -= 2;
1660
		ret -= 2;
1661
	}
1661
	}
1662

    
   
1662

   
1663
	/* Chop off the ending / if there is one */
1663
	/* Chop off the ending / if there is one */
1664
	if ((regex_len > 1) && (regex_string[regex_len - 1] == '/')) {
1664
	if ((regex_len > 1) && (regex_string[regex_len - 1] == '/')) {
1665
		ast_str_truncate(*regex_pattern, -1);
1665
		ast_str_truncate(*regex_pattern, -1);
1666
		ret -= 1;
1666
		ret -= 1;
1667
	}
1667
	}
1668

    
   
1668

   
1669
	return ret;
1669
	return ret;
1670
}
1670
}
1671

    
   
1671

   
1672
int ast_true(const char *s)
1672
int ast_true(const char *s)
1673
{
1673
{
1674
	if (ast_strlen_zero(s))
1674
	if (ast_strlen_zero(s))
1675
		return 0;
1675
		return 0;
1676

    
   
1676

   
1677
	/* Determine if this is a true value */
1677
	/* Determine if this is a true value */
1678
	if (!strcasecmp(s, "yes") ||
1678
	if (!strcasecmp(s, "yes") ||
1679
	    !strcasecmp(s, "true") ||
1679
	    !strcasecmp(s, "true") ||
1680
	    !strcasecmp(s, "y") ||
1680
	    !strcasecmp(s, "y") ||
1681
	    !strcasecmp(s, "t") ||
1681
	    !strcasecmp(s, "t") ||
1682
	    !strcasecmp(s, "1") ||
1682
	    !strcasecmp(s, "1") ||
1683
	    !strcasecmp(s, "on"))
1683
	    !strcasecmp(s, "on"))
1684
		return -1;
1684
		return -1;
1685

    
   
1685

   
1686
	return 0;
1686
	return 0;
1687
}
1687
}
1688

    
   
1688

   
1689
int ast_false(const char *s)
1689
int ast_false(const char *s)
1690
{
1690
{
1691
	if (ast_strlen_zero(s))
1691
	if (ast_strlen_zero(s))
1692
		return 0;
1692
		return 0;
1693

    
   
1693

   
1694
	/* Determine if this is a false value */
1694
	/* Determine if this is a false value */
1695
	if (!strcasecmp(s, "no") ||
1695
	if (!strcasecmp(s, "no") ||
1696
	    !strcasecmp(s, "false") ||
1696
	    !strcasecmp(s, "false") ||
1697
	    !strcasecmp(s, "n") ||
1697
	    !strcasecmp(s, "n") ||
1698
	    !strcasecmp(s, "f") ||
1698
	    !strcasecmp(s, "f") ||
1699
	    !strcasecmp(s, "0") ||
1699
	    !strcasecmp(s, "0") ||
1700
	    !strcasecmp(s, "off"))
1700
	    !strcasecmp(s, "off"))
1701
		return -1;
1701
		return -1;
1702

    
   
1702

   
1703
	return 0;
1703
	return 0;
1704
}
1704
}
1705

    
   
1705

   
1706
#define ONE_MILLION	1000000
1706
#define ONE_MILLION	1000000
1707
/*
1707
/*
1708
 * put timeval in a valid range. usec is 0..999999
1708
 * put timeval in a valid range. usec is 0..999999
1709
 * negative values are not allowed and truncated.
1709
 * negative values are not allowed and truncated.
1710
 */
1710
 */
1711
static struct timeval tvfix(struct timeval a)
1711
static struct timeval tvfix(struct timeval a)
1712
{
1712
{
1713
	if (a.tv_usec >= ONE_MILLION) {
1713
	if (a.tv_usec >= ONE_MILLION) {
1714
		ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
1714
		ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
1715
			(long)a.tv_sec, (long int) a.tv_usec);
1715
			(long)a.tv_sec, (long int) a.tv_usec);
1716
		a.tv_sec += a.tv_usec / ONE_MILLION;
1716
		a.tv_sec += a.tv_usec / ONE_MILLION;
1717
		a.tv_usec %= ONE_MILLION;
1717
		a.tv_usec %= ONE_MILLION;
1718
	} else if (a.tv_usec < 0) {
1718
	} else if (a.tv_usec < 0) {
1719
		ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
1719
		ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
1720
			(long)a.tv_sec, (long int) a.tv_usec);
1720
			(long)a.tv_sec, (long int) a.tv_usec);
1721
		a.tv_usec = 0;
1721
		a.tv_usec = 0;
1722
	}
1722
	}
1723
	return a;
1723
	return a;
1724
}
1724
}
1725

    
   
1725

   
1726
struct timeval ast_tvadd(struct timeval a, struct timeval b)
1726
struct timeval ast_tvadd(struct timeval a, struct timeval b)
1727
{
1727
{
1728
	/* consistency checks to guarantee usec in 0..999999 */
1728
	/* consistency checks to guarantee usec in 0..999999 */
1729
	a = tvfix(a);
1729
	a = tvfix(a);
1730
	b = tvfix(b);
1730
	b = tvfix(b);
1731
	a.tv_sec += b.tv_sec;
1731
	a.tv_sec += b.tv_sec;
1732
	a.tv_usec += b.tv_usec;
1732
	a.tv_usec += b.tv_usec;
1733
	if (a.tv_usec >= ONE_MILLION) {
1733
	if (a.tv_usec >= ONE_MILLION) {
1734
		a.tv_sec++;
1734
		a.tv_sec++;
1735
		a.tv_usec -= ONE_MILLION;
1735
		a.tv_usec -= ONE_MILLION;
1736
	}
1736
	}
1737
	return a;
1737
	return a;
1738
}
1738
}
1739

    
   
1739

   
1740
struct timeval ast_tvsub(struct timeval a, struct timeval b)
1740
struct timeval ast_tvsub(struct timeval a, struct timeval b)
1741
{
1741
{
1742
	/* consistency checks to guarantee usec in 0..999999 */
1742
	/* consistency checks to guarantee usec in 0..999999 */
1743
	a = tvfix(a);
1743
	a = tvfix(a);
1744
	b = tvfix(b);
1744
	b = tvfix(b);
1745
	a.tv_sec -= b.tv_sec;
1745
	a.tv_sec -= b.tv_sec;
1746
	a.tv_usec -= b.tv_usec;
1746
	a.tv_usec -= b.tv_usec;
1747
	if (a.tv_usec < 0) {
1747
	if (a.tv_usec < 0) {
1748
		a.tv_sec-- ;
1748
		a.tv_sec-- ;
1749
		a.tv_usec += ONE_MILLION;
1749
		a.tv_usec += ONE_MILLION;
1750
	}
1750
	}
1751
	return a;
1751
	return a;
1752
}
1752
}
1753

    
   
1753

   
1754
int ast_remaining_ms(struct timeval start, int max_ms)
1754
int ast_remaining_ms(struct timeval start, int max_ms)
1755
{
1755
{
1756
	int ms;
1756
	int ms;
1757

    
   
1757

   
1758
	if (max_ms < 0) {
1758
	if (max_ms < 0) {
1759
		ms = max_ms;
1759
		ms = max_ms;
1760
	} else {
1760
	} else {
1761
		ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
1761
		ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
1762
		if (ms < 0) {
1762
		if (ms < 0) {
1763
			ms = 0;
1763
			ms = 0;
1764
		}
1764
		}
1765
	}
1765
	}
1766

    
   
1766

   
1767
	return ms;
1767
	return ms;
1768
}
1768
}
1769

    
   
1769

   
1770
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
1770
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
1771
{
1771
{
1772
	int durh, durm, durs;
1772
	int durh, durm, durs;
1773
	durh = duration / 3600;
1773
	durh = duration / 3600;
1774
	durm = (duration % 3600) / 60;
1774
	durm = (duration % 3600) / 60;
1775
	durs = duration % 60;
1775
	durs = duration % 60;
1776
	snprintf(buf, length, "%02d:%02d:%02d", durh, durm, durs);
1776
	snprintf(buf, length, "%02d:%02d:%02d", durh, durm, durs);
1777
}
1777
}
1778

    
   
1778

   
1779
#undef ONE_MILLION
1779
#undef ONE_MILLION
1780

    
   
1780

   
1781
#ifndef linux
1781
#ifndef linux
1782
AST_MUTEX_DEFINE_STATIC(randomlock);
1782
AST_MUTEX_DEFINE_STATIC(randomlock);
1783
#endif
1783
#endif
1784

    
   
1784

   
1785
long int ast_random(void)
1785
long int ast_random(void)
1786
{
1786
{
1787
	long int res;
1787
	long int res;
1788

    
   
1788

   
1789
	if (dev_urandom_fd >= 0) {
1789
	if (dev_urandom_fd >= 0) {
1790
		int read_res = read(dev_urandom_fd, &res, sizeof(res));
1790
		int read_res = read(dev_urandom_fd, &res, sizeof(res));
1791
		if (read_res > 0) {
1791
		if (read_res > 0) {
1792
			long int rm = RAND_MAX;
1792
			long int rm = RAND_MAX;
1793
			res = res < 0 ? ~res : res;
1793
			res = res < 0 ? ~res : res;
1794
			rm++;
1794
			rm++;
1795
			return res % rm;
1795
			return res % rm;
1796
		}
1796
		}
1797
	}
1797
	}
1798

    
   
1798

   
1799
	/* XXX - Thread safety really depends on the libc, not the OS.
1799
	/* XXX - Thread safety really depends on the libc, not the OS.
1800
	 *
1800
	 *
1801
	 * But... popular Linux libc's (uClibc, glibc, eglibc), all have a
1801
	 * But... popular Linux libc's (uClibc, glibc, eglibc), all have a
1802
	 * somewhat thread safe random(3) (results are random, but not
1802
	 * somewhat thread safe random(3) (results are random, but not
1803
	 * reproducible). The libc's for other systems (BSD, et al.), not so
1803
	 * reproducible). The libc's for other systems (BSD, et al.), not so
1804
	 * much.
1804
	 * much.
1805
	 */
1805
	 */
1806
#ifdef linux
1806
#ifdef linux
1807
	res = random();
1807
	res = random();
1808
#else
1808
#else
1809
	ast_mutex_lock(&randomlock);
1809
	ast_mutex_lock(&randomlock);
1810
	res = random();
1810
	res = random();
1811
	ast_mutex_unlock(&randomlock);
1811
	ast_mutex_unlock(&randomlock);
1812
#endif
1812
#endif
1813
	return res;
1813
	return res;
1814
}
1814
}
1815

    
   
1815

   
1816
void ast_replace_subargument_delimiter(char *s)
1816
void ast_replace_subargument_delimiter(char *s)
1817
{
1817
{
1818
	for (; *s; s++) {
1818
	for (; *s; s++) {
1819
		if (*s == '^') {
1819
		if (*s == '^') {
1820
			*s = ',';
1820
			*s = ',';
1821
		}
1821
		}
1822
	}
1822
	}
1823
}
1823
}
1824

    
   
1824

   
1825
char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
1825
char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
1826
{
1826
{
1827
	char *dataPut = start;
1827
	char *dataPut = start;
1828
	int inEscape = 0;
1828
	int inEscape = 0;
1829
	int inQuotes = 0;
1829
	int inQuotes = 0;
1830

    
   
1830

   
1831
	for (; *start; start++) {
1831
	for (; *start; start++) {
1832
		if (inEscape) {
1832
		if (inEscape) {
1833
			*dataPut++ = *start;       /* Always goes verbatim */
1833
			*dataPut++ = *start;       /* Always goes verbatim */
1834
			inEscape = 0;
1834
			inEscape = 0;
1835
		} else {
1835
		} else {
1836
			if (*start == '\\') {
1836
			if (*start == '\\') {
1837
				inEscape = 1;      /* Do not copy \ into the data */
1837
				inEscape = 1;      /* Do not copy \ into the data */
1838
			} else if (*start == '\'') {
1838
			} else if (*start == '\'') {
1839
				inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
1839
				inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
1840
			} else {
1840
			} else {
1841
				/* Replace , with |, unless in quotes */
1841
				/* Replace , with |, unless in quotes */
1842
				*dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
1842
				*dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
1843
			}
1843
			}
1844
		}
1844
		}
1845
	}
1845
	}
1846
	if (start != dataPut)
1846
	if (start != dataPut)
1847
		*dataPut = 0;
1847
		*dataPut = 0;
1848
	return dataPut;
1848
	return dataPut;
1849
}
1849
}
1850

    
   
1850

   
1851
void ast_join_delim(char *s, size_t len, const char * const w[], unsigned int size, char delim)
1851
void ast_join_delim(char *s, size_t len, const char * const w[], unsigned int size, char delim)
1852
{
1852
{
1853
	int x, ofs = 0;
1853
	int x, ofs = 0;
1854
	const char *src;
1854
	const char *src;
1855

    
   
1855

   
1856
	/* Join words into a string */
1856
	/* Join words into a string */
1857
	if (!s)
1857
	if (!s)
1858
		return;
1858
		return;
1859
	for (x = 0; ofs < len && x < size && w[x] ; x++) {
1859
	for (x = 0; ofs < len && x < size && w[x] ; x++) {
1860
		if (x > 0)
1860
		if (x > 0)
1861
			s[ofs++] = delim;
1861
			s[ofs++] = delim;
1862
		for (src = w[x]; *src && ofs < len; src++)
1862
		for (src = w[x]; *src && ofs < len; src++)
1863
			s[ofs++] = *src;
1863
			s[ofs++] = *src;
1864
	}
1864
	}
1865
	if (ofs == len)
1865
	if (ofs == len)
1866
		ofs--;
1866
		ofs--;
1867
	s[ofs] = '\0';
1867
	s[ofs] = '\0';
1868
}
1868
}
1869

    
   
1869

   
1870
char *ast_to_camel_case_delim(const char *s, const char *delim)
1870
char *ast_to_camel_case_delim(const char *s, const char *delim)
1871
{
1871
{
1872
	char *res = ast_strdup(s);
1872
	char *res = ast_strdup(s);
1873
	char *front, *back, *buf = res;
1873
	char *front, *back, *buf = res;
1874
	int size;
1874
	int size;
1875

    
   
1875

   
1876
	front = strtok_r(buf, delim, &back);
1876
	front = strtok_r(buf, delim, &back);
1877

    
   
1877

   
1878
	while (front) {
1878
	while (front) {
1879
		size = strlen(front);
1879
		size = strlen(front);
1880
		*front = toupper(*front);
1880
		*front = toupper(*front);
1881
		ast_copy_string(buf, front, size + 1);
1881
		ast_copy_string(buf, front, size + 1);
1882
		buf += size;
1882
		buf += size;
1883
		front = strtok_r(NULL, delim, &back);
1883
		front = strtok_r(NULL, delim, &back);
1884
	}
1884
	}
1885

    
   
1885

   
1886
	return res;
1886
	return res;
1887
}
1887
}
1888

    
   
1888

   
1889
/*
1889
/*
1890
 * stringfields support routines.
1890
 * stringfields support routines.
1891
 */
1891
 */
1892

    
   
1892

   
1893
/* this is a little complex... string fields are stored with their
1893
/* this is a little complex... string fields are stored with their
1894
   allocated size in the bytes preceding the string; even the
1894
   allocated size in the bytes preceding the string; even the
1895
   constant 'empty' string has to be this way, so the code that
1895
   constant 'empty' string has to be this way, so the code that
1896
   checks to see if there is enough room for a new string doesn't
1896
   checks to see if there is enough room for a new string doesn't
1897
   have to have any special case checks
1897
   have to have any special case checks
1898
*/
1898
*/
1899

    
   
1899

   
1900
static const struct {
1900
static const struct {
1901
	ast_string_field_allocation allocation;
1901
	ast_string_field_allocation allocation;
1902
	char string[1];
1902
	char string[1];
1903
} __ast_string_field_empty_buffer;
1903
} __ast_string_field_empty_buffer;
1904

    
   
1904

   
1905
ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
1905
ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
1906

    
   
1906

   
1907
#define ALLOCATOR_OVERHEAD 48
1907
#define ALLOCATOR_OVERHEAD 48
1908

    
   
1908

   
1909
static size_t optimal_alloc_size(size_t size)
1909
static size_t optimal_alloc_size(size_t size)
1910
{
1910
{
1911
	unsigned int count;
1911
	unsigned int count;
1912

    
   
1912

   
1913
	size += ALLOCATOR_OVERHEAD;
1913
	size += ALLOCATOR_OVERHEAD;
1914

    
   
1914

   
1915
	for (count = 1; size; size >>= 1, count++);
1915
	for (count = 1; size; size >>= 1, count++);
1916

    
   
1916

   
1917
	return (1 << count) - ALLOCATOR_OVERHEAD;
1917
	return (1 << count) - ALLOCATOR_OVERHEAD;
1918
}
1918
}
1919

    
   
1919

   
1920
/*! \brief add a new block to the pool.
1920
/*! \brief add a new block to the pool.
1921
 * We can only allocate from the topmost pool, so the
1921
 * We can only allocate from the topmost pool, so the
1922
 * fields in *mgr reflect the size of that only.
1922
 * fields in *mgr reflect the size of that only.
1923
 */
1923
 */
1924
static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
1924
static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
1925
			   size_t size, const char *file, int lineno, const char *func)
1925
			   size_t size, const char *file, int lineno, const char *func)
1926
{
1926
{
1927
	struct ast_string_field_pool *pool;
1927
	struct ast_string_field_pool *pool;
1928
	size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
1928
	size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
1929

    
   
1929

   
1930
#if defined(__AST_DEBUG_MALLOC)
1930
#if defined(__AST_DEBUG_MALLOC)
1931
	if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
1931
	if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
1932
		return -1;
1932
		return -1;
1933
	}
1933
	}
1934
#else
1934
#else
1935
	if (!(pool = ast_calloc(1, alloc_size))) {
1935
	if (!(pool = ast_calloc(1, alloc_size))) {
1936
		return -1;
1936
		return -1;
1937
	}
1937
	}
1938
#endif
1938
#endif
1939

    
   
1939

   
1940
	pool->prev = *pool_head;
1940
	pool->prev = *pool_head;
1941
	pool->size = alloc_size - sizeof(*pool);
1941
	pool->size = alloc_size - sizeof(*pool);
1942
	*pool_head = pool;
1942
	*pool_head = pool;
1943
	mgr->last_alloc = NULL;
1943
	mgr->last_alloc = NULL;
1944

    
   
1944

   
1945
	return 0;
1945
	return 0;
1946
}
1946
}
1947

    
   
1947

   
1948
/*
1948
/*
1949
 * This is an internal API, code should not use it directly.
1949
 * This is an internal API, code should not use it directly.
1950
 * It initializes all fields as empty, then uses 'size' for 3 functions:
1950
 * It initializes all fields as empty, then uses 'size' for 3 functions:
1951
 * size > 0 means initialize the pool list with a pool of given size.
1951
 * size > 0 means initialize the pool list with a pool of given size.
1952
 *	This must be called right after allocating the object.
1952
 *	This must be called right after allocating the object.
1953
 * size = 0 means release all pools except the most recent one.
1953
 * size = 0 means release all pools except the most recent one.
1954
 *      If the first pool was allocated via embedding in another
1954
 *      If the first pool was allocated via embedding in another
1955
 *      object, that pool will be preserved instead.
1955
 *      object, that pool will be preserved instead.
1956
 *	This is useful to e.g. reset an object to the initial value.
1956
 *	This is useful to e.g. reset an object to the initial value.
1957
 * size < 0 means release all pools.
1957
 * size < 0 means release all pools.
1958
 *	This must be done before destroying the object.
1958
 *	This must be done before destroying the object.
1959
 */
1959
 */
1960
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
1960
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
1961
			    int needed, const char *file, int lineno, const char *func)
1961
			    int needed, const char *file, int lineno, const char *func)
1962
{
1962
{
1963
	const char **p = (const char **) pool_head + 1;
1963
	const char **p = (const char **) pool_head + 1;
1964
	struct ast_string_field_pool *cur = NULL;
1964
	struct ast_string_field_pool *cur = NULL;
1965
	struct ast_string_field_pool *preserve = NULL;
1965
	struct ast_string_field_pool *preserve = NULL;
1966

    
   
1966

   
1967
	/* clear fields - this is always necessary */
1967
	/* clear fields - this is always necessary */
1968
	while ((struct ast_string_field_mgr *) p != mgr) {
1968
	while ((struct ast_string_field_mgr *) p != mgr) {
1969
		*p++ = __ast_string_field_empty;
1969
		*p++ = __ast_string_field_empty;
1970
	}
1970
	}
1971

    
   
1971

   
1972
	mgr->last_alloc = NULL;
1972
	mgr->last_alloc = NULL;
1973
#if defined(__AST_DEBUG_MALLOC)
1973
#if defined(__AST_DEBUG_MALLOC)
1974
	mgr->owner_file = file;
1974
	mgr->owner_file = file;
1975
	mgr->owner_func = func;
1975
	mgr->owner_func = func;
1976
	mgr->owner_line = lineno;
1976
	mgr->owner_line = lineno;
1977
#endif
1977
#endif
1978
	if (needed > 0) {		/* allocate the initial pool */
1978
	if (needed > 0) {		/* allocate the initial pool */
1979
		*pool_head = NULL;
1979
		*pool_head = NULL;
1980
		mgr->embedded_pool = NULL;
1980
		mgr->embedded_pool = NULL;
1981
		return add_string_pool(mgr, pool_head, needed, file, lineno, func);
1981
		return add_string_pool(mgr, pool_head, needed, file, lineno, func);
1982
	}
1982
	}
1983

    
   
1983

   
1984
	/* if there is an embedded pool, we can't actually release *all*
1984
	/* if there is an embedded pool, we can't actually release *all*
1985
	 * pools, we must keep the embedded one. if the caller is about
1985
	 * pools, we must keep the embedded one. if the caller is about
1986
	 * to free the structure that contains the stringfield manager
1986
	 * to free the structure that contains the stringfield manager
1987
	 * and embedded pool anyway, it will be freed as part of that
1987
	 * and embedded pool anyway, it will be freed as part of that
1988
	 * operation.
1988
	 * operation.
1989
	 */
1989
	 */
1990
	if ((needed < 0) && mgr->embedded_pool) {
1990
	if ((needed < 0) && mgr->embedded_pool) {
1991
		needed = 0;
1991
		needed = 0;
1992
	}
1992
	}
1993

    
   
1993

   
1994
	if (needed < 0) {		/* reset all pools */
1994
	if (needed < 0) {		/* reset all pools */
1995
		cur = *pool_head;
1995
		cur = *pool_head;
1996
	} else if (mgr->embedded_pool) { /* preserve the embedded pool */
1996
	} else if (mgr->embedded_pool) { /* preserve the embedded pool */
1997
		preserve = mgr->embedded_pool;
1997
		preserve = mgr->embedded_pool;
1998
		cur = *pool_head;
1998
		cur = *pool_head;
1999
	} else {			/* preserve the last pool */
1999
	} else {			/* preserve the last pool */
2000
		if (*pool_head == NULL) {
2000
		if (*pool_head == NULL) {
2001
			ast_log(LOG_WARNING, "trying to reset empty pool\n");
2001
			ast_log(LOG_WARNING, "trying to reset empty pool\n");
2002
			return -1;
2002
			return -1;
2003
		}
2003
		}
2004
		preserve = *pool_head;
2004
		preserve = *pool_head;
2005
		cur = preserve->prev;
2005
		cur = preserve->prev;
2006
	}
2006
	}
2007

    
   
2007

   
2008
	if (preserve) {
2008
	if (preserve) {
2009
		preserve->prev = NULL;
2009
		preserve->prev = NULL;
2010
		preserve->used = preserve->active = 0;
2010
		preserve->used = preserve->active = 0;
2011
	}
2011
	}
2012

    
   
2012

   
2013
	while (cur) {
2013
	while (cur) {
2014
		struct ast_string_field_pool *prev = cur->prev;
2014
		struct ast_string_field_pool *prev = cur->prev;
2015

    
   
2015

   
2016
		if (cur != preserve) {
2016
		if (cur != preserve) {
2017
			ast_free(cur);
2017
			ast_free(cur);
2018
		}
2018
		}
2019
		cur = prev;
2019
		cur = prev;
2020
	}
2020
	}
2021

    
   
2021

   
2022
	*pool_head = preserve;
2022
	*pool_head = preserve;
2023

    
   
2023

   
2024
	return 0;
2024
	return 0;
2025
}
2025
}
2026

    
   
2026

   
2027
ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
2027
ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
2028
						struct ast_string_field_pool **pool_head, size_t needed)
2028
						struct ast_string_field_pool **pool_head, size_t needed)
2029
{
2029
{
2030
	char *result = NULL;
2030
	char *result = NULL;
2031
	size_t space = (*pool_head)->size - (*pool_head)->used;
2031
	size_t space = (*pool_head)->size - (*pool_head)->used;
2032
	size_t to_alloc;
2032
	size_t to_alloc;
2033

    
   
2033

   
2034
	/* Make room for ast_string_field_allocation and make it a multiple of that. */
2034
	/* Make room for ast_string_field_allocation and make it a multiple of that. */
2035
	to_alloc = ast_make_room_for(needed, ast_string_field_allocation);
2035
	to_alloc = ast_make_room_for(needed, ast_string_field_allocation);
2036
	ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0);
2036
	ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0);
2037

    
   
2037

   
2038
	if (__builtin_expect(to_alloc > space, 0)) {
2038
	if (__builtin_expect(to_alloc > space, 0)) {
2039
		size_t new_size = (*pool_head)->size;
2039
		size_t new_size = (*pool_head)->size;
2040

    
   
2040

   
2041
		while (new_size < to_alloc) {
2041
		while (new_size < to_alloc) {
2042
			new_size *= 2;
2042
			new_size *= 2;
2043
		}
2043
		}
2044

    
   
2044

   
2045
#if defined(__AST_DEBUG_MALLOC)
2045
#if defined(__AST_DEBUG_MALLOC)
2046
		if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
2046
		if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
2047
			return NULL;
2047
			return NULL;
2048
#else
2048
#else
2049
		if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__))
2049
		if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__))
2050
			return NULL;
2050
			return NULL;
2051
#endif
2051
#endif
2052
	}
2052
	}
2053

    
   
2053

   
2054
	/* pool->base is always aligned (gcc aligned attribute). We ensure that
2054
	/* pool->base is always aligned (gcc aligned attribute). We ensure that
2055
	 * to_alloc is also a multiple of ast_alignof(ast_string_field_allocation)
2055
	 * to_alloc is also a multiple of ast_alignof(ast_string_field_allocation)
2056
	 * causing result to always be aligned as well; which in turn fixes that
2056
	 * causing result to always be aligned as well; which in turn fixes that
2057
	 * AST_STRING_FIELD_ALLOCATION(result) is aligned. */
2057
	 * AST_STRING_FIELD_ALLOCATION(result) is aligned. */
2058
	result = (*pool_head)->base + (*pool_head)->used;
2058
	result = (*pool_head)->base + (*pool_head)->used;
2059
	(*pool_head)->used += to_alloc;
2059
	(*pool_head)->used += to_alloc;
2060
	(*pool_head)->active += needed;
2060
	(*pool_head)->active += needed;
2061
	result += ast_alignof(ast_string_field_allocation);
2061
	result += ast_alignof(ast_string_field_allocation);
2062
	AST_STRING_FIELD_ALLOCATION(result) = needed;
2062
	AST_STRING_FIELD_ALLOCATION(result) = needed;
2063
	mgr->last_alloc = result;
2063
	mgr->last_alloc = result;
2064

    
   
2064

   
2065
	return result;
2065
	return result;
2066
}
2066
}
2067

    
   
2067

   
2068
int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
2068
int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
2069
				struct ast_string_field_pool **pool_head, size_t needed,
2069
				struct ast_string_field_pool **pool_head, size_t needed,
2070
				const ast_string_field *ptr)
2070
				const ast_string_field *ptr)
2071
{
2071
{
2072
	ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
2072
	ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
2073
	size_t space = (*pool_head)->size - (*pool_head)->used;
2073
	size_t space = (*pool_head)->size - (*pool_head)->used;
2074

    
   
2074

   
2075
	if (*ptr != mgr->last_alloc) {
2075
	if (*ptr != mgr->last_alloc) {
2076
		return 1;
2076
		return 1;
2077
	}
2077
	}
2078

    
   
2078

   
2079
	if (space < grow) {
2079
	if (space < grow) {
2080
		return 1;
2080
		return 1;
2081
	}
2081
	}
2082

    
   
2082

   
2083
	(*pool_head)->used += grow;
2083
	(*pool_head)->used += grow;
2084
	(*pool_head)->active += grow;
2084
	(*pool_head)->active += grow;
2085
	AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
2085
	AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
2086

    
   
2086

   
2087
	return 0;
2087
	return 0;
2088
}
2088
}
2089

    
   
2089

   
2090
void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
2090
void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
2091
				       const ast_string_field ptr)
2091
				       const ast_string_field ptr)
2092
{
2092
{
2093
	struct ast_string_field_pool *pool, *prev;
2093
	struct ast_string_field_pool *pool, *prev;
2094

    
   
2094

   
2095
	if (ptr == __ast_string_field_empty) {
2095
	if (ptr == __ast_string_field_empty) {
2096
		return;
2096
		return;
2097
	}
2097
	}
2098

    
   
2098

   
2099
	for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
2099
	for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
2100
		if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
2100
		if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
2101
			pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
2101
			pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
2102
			if (pool->active == 0) {
2102
			if (pool->active == 0) {
2103
				if (prev) {
2103
				if (prev) {
2104
					prev->prev = pool->prev;
2104
					prev->prev = pool->prev;
2105
					ast_free(pool);
2105
					ast_free(pool);
2106
				} else {
2106
				} else {
2107
					pool->used = 0;
2107
					pool->used = 0;
2108
				}
2108
				}
2109
			}
2109
			}
2110
			break;
2110
			break;
2111
		}
2111
		}
2112
	}
2112
	}
2113
}
2113
}
2114

    
   
2114

   
2115
void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
2115
void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
2116
				     struct ast_string_field_pool **pool_head,
2116
				     struct ast_string_field_pool **pool_head,
2117
				     ast_string_field *ptr, const char *format, va_list ap)
2117
				     ast_string_field *ptr, const char *format, va_list ap)
2118
{
2118
{
2119
	size_t needed;
2119
	size_t needed;
2120
	size_t available;
2120
	size_t available;
2121
	size_t space = (*pool_head)->size - (*pool_head)->used;
2121
	size_t space = (*pool_head)->size - (*pool_head)->used;
2122
	int res;
2122
	int res;
2123
	ssize_t grow;
2123
	ssize_t grow;
2124
	char *target;
2124
	char *target;
2125
	va_list ap2;
2125
	va_list ap2;
2126

    
   
2126

   
2127
	/* if the field already has space allocated, try to reuse it;
2127
	/* if the field already has space allocated, try to reuse it;
2128
	   otherwise, try to use the empty space at the end of the current
2128
	   otherwise, try to use the empty space at the end of the current
2129
	   pool
2129
	   pool
2130
	*/
2130
	*/
2131
	if (*ptr != __ast_string_field_empty) {
2131
	if (*ptr != __ast_string_field_empty) {
2132
		target = (char *) *ptr;
2132
		target = (char *) *ptr;
2133
		available = AST_STRING_FIELD_ALLOCATION(*ptr);
2133
		available = AST_STRING_FIELD_ALLOCATION(*ptr);
2134
		if (*ptr == mgr->last_alloc) {
2134
		if (*ptr == mgr->last_alloc) {
2135
			available += space;
2135
			available += space;
2136
		}
2136
		}
2137
	} else {
2137
	} else {
2138
		/* pool->used is always a multiple of ast_alignof(ast_string_field_allocation)
2138
		/* pool->used is always a multiple of ast_alignof(ast_string_field_allocation)
2139
		 * so we don't need to re-align anything here.
2139
		 * so we don't need to re-align anything here.
2140
		 */
2140
		 */
2141
		target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
2141
		target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
2142
		if (space > ast_alignof(ast_string_field_allocation)) {
2142
		if (space > ast_alignof(ast_string_field_allocation)) {
2143
			available = space - ast_alignof(ast_string_field_allocation);
2143
			available = space - ast_alignof(ast_string_field_allocation);
2144
		} else {
2144
		} else {
2145
			available = 0;
2145
			available = 0;
2146
		}
2146
		}
2147
	}
2147
	}
2148

    
   
2148

   
2149
	va_copy(ap2, ap);
2149
	va_copy(ap2, ap);
2150
	res = vsnprintf(target, available, format, ap2);
2150
	res = vsnprintf(target, available, format, ap2);
2151
	va_end(ap2);
2151
	va_end(ap2);
2152

    
   
2152

   
2153
	if (res < 0) {
2153
	if (res < 0) {
2154
		/* Are we out of memory? */
2154
		/* Are we out of memory? */
2155
		return;
2155
		return;
2156
	}
2156
	}
2157
	if (res == 0) {
2157
	if (res == 0) {
2158
		__ast_string_field_release_active(*pool_head, *ptr);
2158
		__ast_string_field_release_active(*pool_head, *ptr);
2159
		*ptr = __ast_string_field_empty;
2159
		*ptr = __ast_string_field_empty;
2160
		return;
2160
		return;
2161
	}
2161
	}
2162
	needed = (size_t)res + 1; /* NUL byte */
2162
	needed = (size_t)res + 1; /* NUL byte */
2163

    
   
2163

   
2164
	if (needed > available) {
2164
	if (needed > available) {
2165
		/* the allocation could not be satisfied using the field's current allocation
2165
		/* the allocation could not be satisfied using the field's current allocation
2166
		   (if it has one), or the space available in the pool (if it does not). allocate
2166
		   (if it has one), or the space available in the pool (if it does not). allocate
2167
		   space for it, adding a new string pool if necessary.
2167
		   space for it, adding a new string pool if necessary.
2168
		*/
2168
		*/
2169
		if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
2169
		if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
2170
			return;
2170
			return;
2171
		}
2171
		}
2172
		vsprintf(target, format, ap);
2172
		vsprintf(target, format, ap);
2173
		va_end(ap); /* XXX va_end without va_start? */
2173
		va_end(ap); /* XXX va_end without va_start? */
2174
		__ast_string_field_release_active(*pool_head, *ptr);
2174
		__ast_string_field_release_active(*pool_head, *ptr);
2175
		*ptr = target;
2175
		*ptr = target;
2176
	} else if (*ptr != target) {
2176
	} else if (*ptr != target) {
2177
		/* the allocation was satisfied using available space in the pool, but not
2177
		/* the allocation was satisfied using available space in the pool, but not
2178
		   using the space already allocated to the field
2178
		   using the space already allocated to the field
2179
		*/
2179
		*/
2180
		__ast_string_field_release_active(*pool_head, *ptr);
2180
		__ast_string_field_release_active(*pool_head, *ptr);
2181
		mgr->last_alloc = *ptr = target;
2181
		mgr->last_alloc = *ptr = target;
2182
	        ast_assert(needed < (ast_string_field_allocation)-1);
2182
	        ast_assert(needed < (ast_string_field_allocation)-1);
2183
		AST_STRING_FIELD_ALLOCATION(target) = (ast_string_field_allocation)needed;
2183
		AST_STRING_FIELD_ALLOCATION(target) = (ast_string_field_allocation)needed;
2184
		(*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
2184
		(*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
2185
		(*pool_head)->active += needed;
2185
		(*pool_head)->active += needed;
2186
	} else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
2186
	} else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
2187
		/* the allocation was satisfied by using available space in the pool *and*
2187
		/* the allocation was satisfied by using available space in the pool *and*
2188
		   the field was the last allocated field from the pool, so it grew
2188
		   the field was the last allocated field from the pool, so it grew
2189
		*/
2189
		*/
2190
		AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
2190
		AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
2191
		(*pool_head)->used += ast_align_for(grow, ast_string_field_allocation);
2191
		(*pool_head)->used += ast_align_for(grow, ast_string_field_allocation);
2192
		(*pool_head)->active += grow;
2192
		(*pool_head)->active += grow;
2193
	}
2193
	}
2194
}
2194
}
2195

    
   
2195

   
2196
void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
2196
void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
2197
				  struct ast_string_field_pool **pool_head,
2197
				  struct ast_string_field_pool **pool_head,
2198
				  ast_string_field *ptr, const char *format, ...)
2198
				  ast_string_field *ptr, const char *format, ...)
2199
{
2199
{
2200
	va_list ap;
2200
	va_list ap;
2201

    
   
2201

   
2202
	va_start(ap, format);
2202
	va_start(ap, format);
2203
	__ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap);
2203
	__ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap);
2204
	va_end(ap);
2204
	va_end(ap);
2205
}
2205
}
2206

    
   
2206

   
2207
void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
2207
void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
2208
				     size_t field_mgr_pool_offset, size_t pool_size, const char *file,
2208
				     size_t field_mgr_pool_offset, size_t pool_size, const char *file,
2209
				     int lineno, const char *func)
2209
				     int lineno, const char *func)
2210
{
2210
{
2211
	struct ast_string_field_mgr *mgr;
2211
	struct ast_string_field_mgr *mgr;
2212
	struct ast_string_field_pool *pool;
2212
	struct ast_string_field_pool *pool;
2213
	struct ast_string_field_pool **pool_head;
2213
	struct ast_string_field_pool **pool_head;
2214
	size_t pool_size_needed = sizeof(*pool) + pool_size;
2214
	size_t pool_size_needed = sizeof(*pool) + pool_size;
2215
	size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
2215
	size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
2216
	void *allocation;
2216
	void *allocation;
2217
	unsigned int x;
2217
	unsigned int x;
2218

    
   
2218

   
2219
#if defined(__AST_DEBUG_MALLOC)
2219
#if defined(__AST_DEBUG_MALLOC)
2220
	if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
2220
	if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
2221
		return NULL;
2221
		return NULL;
2222
	}
2222
	}
2223
#else
2223
#else
2224
	if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
2224
	if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
2225
		return NULL;
2225
		return NULL;
2226
	}
2226
	}
2227
#endif
2227
#endif
2228

    
   
2228

   
2229
	for (x = 0; x < num_structs; x++) {
2229
	for (x = 0; x < num_structs; x++) {
2230
		void *base = allocation + (size_to_alloc * x);
2230
		void *base = allocation + (size_to_alloc * x);
2231
		const char **p;
2231
		const char **p;
2232

    
   
2232

   
2233
		mgr = base + field_mgr_offset;
2233
		mgr = base + field_mgr_offset;
2234
		pool_head = base + field_mgr_pool_offset;
2234
		pool_head = base + field_mgr_pool_offset;
2235
		pool = base + struct_size;
2235
		pool = base + struct_size;
2236

    
   
2236

   
2237
		p = (const char **) pool_head + 1;
2237
		p = (const char **) pool_head + 1;
2238
		while ((struct ast_string_field_mgr *) p != mgr) {
2238
		while ((struct ast_string_field_mgr *) p != mgr) {
2239
			*p++ = __ast_string_field_empty;
2239
			*p++ = __ast_string_field_empty;
2240
		}
2240
		}
2241

    
   
2241

   
2242
		mgr->embedded_pool = pool;
2242
		mgr->embedded_pool = pool;
2243
		*pool_head = pool;
2243
		*pool_head = pool;
2244
		pool->size = size_to_alloc - struct_size - sizeof(*pool);
2244
		pool->size = size_to_alloc - struct_size - sizeof(*pool);
2245
#if defined(__AST_DEBUG_MALLOC)
2245
#if defined(__AST_DEBUG_MALLOC)
2246
		mgr->owner_file = file;
2246
		mgr->owner_file = file;
2247
		mgr->owner_func = func;
2247
		mgr->owner_func = func;
2248
		mgr->owner_line = lineno;
2248
		mgr->owner_line = lineno;
2249
#endif
2249
#endif
2250
	}
2250
	}
2251

    
   
2251

   
2252
	return allocation;
2252
	return allocation;
2253
}
2253
}
2254

    
   
2254

   
2255
/* end of stringfields support */
2255
/* end of stringfields support */
2256

    
   
2256

   
2257
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
2257
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
2258

    
   
2258

   
2259
int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
2259
int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
2260
{
2260
{
2261
	int ret;
2261
	int ret;
2262
	ast_mutex_lock(&fetchadd_m);
2262
	ast_mutex_lock(&fetchadd_m);
2263
	ret = *p;
2263
	ret = *p;
2264
	*p += v;
2264
	*p += v;
2265
	ast_mutex_unlock(&fetchadd_m);
2265
	ast_mutex_unlock(&fetchadd_m);
2266
	return ret;
2266
	return ret;
2267
}
2267
}
2268

    
   
2268

   
2269
/*! \brief
2269
/*! \brief
2270
 * get values from config variables.
2270
 * get values from config variables.
2271
 */
2271
 */
2272
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
2272
int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
2273
{
2273
{
2274
	long double dtv = 0.0;
2274
	long double dtv = 0.0;
2275
	int scanned;
2275
	int scanned;
2276

    
   
2276

   
2277
	if (dst == NULL)
2277
	if (dst == NULL)
2278
		return -1;
2278
		return -1;
2279

    
   
2279

   
2280
	*dst = _default;
2280
	*dst = _default;
2281

    
   
2281

   
2282
	if (ast_strlen_zero(src))
2282
	if (ast_strlen_zero(src))
2283
		return -1;
2283
		return -1;
2284

    
   
2284

   
2285
	/* only integer at the moment, but one day we could accept more formats */
2285
	/* only integer at the moment, but one day we could accept more formats */
2286
	if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
2286
	if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
2287
		dst->tv_sec = dtv;
2287
		dst->tv_sec = dtv;
2288
		dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2288
		dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
2289
		if (consumed)
2289
		if (consumed)
2290
			*consumed = scanned;
2290
			*consumed = scanned;
2291
		return 0;
2291
		return 0;
2292
	} else
2292
	} else
2293
		return -1;
2293
		return -1;
2294
}
2294
}
2295

    
   
2295

   
2296
/*! \brief
2296
/*! \brief
2297
 * get values from config variables.
2297
 * get values from config variables.
2298
 */
2298
 */
2299
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
2299
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
2300
{
2300
{
2301
	long t;
2301
	long t;
2302
	int scanned;
2302