Newer
Older
Steve Murphy
committed
/*!
* \brief A wrapper for calloc()
*
* ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc(num, len) \
_ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
{
if (!(p = calloc(num, len)))
MALLOC_FAILURE_MSG;
}
/*!
* \brief A wrapper for calloc() for use in cache pools
*
* ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails. When memory debugging is in use,
* the memory allocated by this function will be marked as 'cache' so it can be
* distinguished from normal memory allocations.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc_cache(num, len) \
_ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for realloc()
*
* ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as realloc()
*/
#define ast_realloc(p, len) \
_ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
{
void *newp;
if (!(newp = realloc(p, len)))
MALLOC_FAILURE_MSG;
/*!
* \brief A wrapper for strdup()
*
* ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
* argument is provided, ast_strdup will return NULL without generating any
* kind of error log message.
*
* The argument and return value are the same as strdup()
*/
#define ast_strdup(str) \
_ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
if (str) {
if (!(newstr = strdup(str)))
MALLOC_FAILURE_MSG;
}
/*!
* \brief A wrapper for strndup()
*
* ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
* string to duplicate. If a NULL argument is provided, ast_strdup will return
* NULL without generating any kind of error log message.
*
* The arguments and return value are the same as strndup()
*/
#define ast_strndup(str, len) \
_ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
if (str) {
if (!(newstr = strndup(str, len)))
MALLOC_FAILURE_MSG;
}
/*!
* \brief A wrapper for asprintf()
*
* ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as asprintf()
*/
#define ast_asprintf(ret, fmt, ...) \
_ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
__attribute__((format(printf, 5, 6)))
int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...),
{
int res;
va_list ap;
va_start(ap, fmt);
if ((res = vasprintf(ret, fmt, ap)) == -1)
MALLOC_FAILURE_MSG;
va_end(ap);
/*!
* \brief A wrapper for vasprintf()
*
* ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as vasprintf()
*/
#define ast_vasprintf(ret, fmt, ap) \
_ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
__attribute__((format(printf, 5, 0)))
int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
{
int res;
if ((res = vasprintf(ret, fmt, ap)) == -1)
MALLOC_FAILURE_MSG;
return res;
}
)
#if !defined(ast_strdupa) && defined(__GNUC__)
/*!
\brief duplicate a string in memory from the stack
\param s The string to duplicate
This macro will duplicate the given string. It returns a pointer to the stack
allocatted memory for the new string.
*/
#define ast_strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen(__old) + 1; \
char *__new = __builtin_alloca(__len); \
memcpy (__new, __old, __len); \
__new; \
}))
#endif
#define MAX_NESTED_COMMENTS 128
#define COMMENT_START ";--"
#define COMMENT_END "--;"
#define COMMENT_META ';'
#define COMMENT_TAG '-'
/*! Growable string buffer */
static char *comment_buffer; /*!< this will be a comment collector.*/
static int comment_buffer_size; /*!< the amount of storage so far alloc'd for the comment_buffer */
static char *lline_buffer; /*!< A buffer for stuff behind the ; */
static int lline_buffer_size;
#define CB_INCR 250
struct ast_comment {
struct ast_comment *next;
char cmt[0];
};
static void CB_INIT(void)
{
if (!comment_buffer) {
comment_buffer = ast_malloc(CB_INCR);
if (!comment_buffer)
return;
comment_buffer[0] = 0;
comment_buffer_size = CB_INCR;
lline_buffer = ast_malloc(CB_INCR);
if (!lline_buffer)
return;
lline_buffer[0] = 0;
lline_buffer_size = CB_INCR;
} else {
comment_buffer[0] = 0;
lline_buffer[0] = 0;
}
}
{
int rem = comment_buffer_size - strlen(comment_buffer) - 1;
int siz = strlen(str);
if (rem < siz+1) {
comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + siz + 1);
if (!comment_buffer)
return;
comment_buffer_size += CB_INCR+siz+1;
}
strcat(comment_buffer,str);
}
static void CB_ADD_LEN(char *str, int len)
{
int cbl = strlen(comment_buffer) + 1;
int rem = comment_buffer_size - cbl;
if (rem < len+1) {
comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + len + 1);
if (!comment_buffer)
return;
comment_buffer_size += CB_INCR+len+1;
}
strncat(comment_buffer,str,len); /* safe */
comment_buffer[cbl+len-1] = 0;
}
static void LLB_ADD(char *str)
{
int rem = lline_buffer_size - strlen(lline_buffer) - 1;
int siz = strlen(str);
if (rem < siz+1) {
lline_buffer = ast_realloc(lline_buffer, lline_buffer_size + CB_INCR + siz + 1);
if (!lline_buffer)
return;
lline_buffer_size += CB_INCR + siz + 1;
}
strcat(lline_buffer,str);
}
static void CB_RESET(void )
{
comment_buffer[0] = 0;
lline_buffer[0] = 0;
}
/*! \brief Keep track of how many threads are currently trying to wait*() on
* a child process */
static unsigned int safe_system_level = 0;
static struct sigaction safe_system_prev_handler;
/*! \brief NULL handler so we can collect the child exit status */
static void _null_sig_handler(int sig)
}
static struct sigaction null_sig_handler = {
.sa_handler = _null_sig_handler,
void ast_replace_sigchld(void);
void ast_replace_sigchld(void)
{
level = safe_system_level++;
/* only replace the handler if it has not already been done */
if (level == 0) {
sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
}
}
void ast_unreplace_sigchld(void)
{
unsigned int level;
/* only restore the handler if we are the last one */
if (level == 0) {
sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
}
}
int ast_safe_system(const char *s);
int ast_safe_system(const char *s)
{
pid_t pid;
#ifdef HAVE_WORKING_FORK
int x;
#endif
int res;
#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
ast_replace_sigchld();
#else
if (pid == 0) {
#ifdef HAVE_WORKING_FORK
/* Close file descriptors and launch system command */
for (x = STDERR_FILENO + 1; x < 4096; x++)
close(x);
#endif
execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
_exit(1);
} else if (pid > 0) {
for(;;) {
res = wait4(pid, &status, 0, &rusage);
if (res > -1) {
res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
break;
} else if (errno != EINTR)
break;
}
} else {
ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
res = -1;
}
ast_unreplace_sigchld();
#else
res = -1;
#endif
return res;
}
static struct ast_comment *ALLOC_COMMENT(const char *buffer)
{
struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
strcpy(x->cmt, buffer);
return x;
}
static struct ast_config_map {
struct ast_config_map *next;
char *name;
char *driver;
char *database;
char *table;
char stuff[0];
} *config_maps = NULL;
static struct ast_config_engine *config_engine_list;
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
struct ast_category {
char name[80];
int ignored; /*!< do not let user of the config see this category */
int include_level;
char *file; /*!< the file name from whence this declaration was read */
int lineno;
struct ast_comment *precomments;
struct ast_comment *sameline;
struct ast_variable *root;
struct ast_variable *last;
struct ast_category *next;
};
struct ast_config {
struct ast_category *root;
struct ast_category *last;
struct ast_category *current;
struct ast_category *last_browse; /*!< used to cache the last category supplied via category_browse */
int include_level;
int max_include_level;
struct ast_config_include *includes; /*!< a list of inclusions, which should describe the entire tree */
};
struct ast_config_include {
char *include_location_file; /*!< file name in which the include occurs */
int include_location_lineno; /*!< lineno where include occurred */
int exec; /*!< set to non-zero if itsa #exec statement */
char *exec_file; /*!< if it's an exec, you'll have both the /var/tmp to read, and the original script */
char *included_file; /*!< file name included */
int inclusion_count; /*!< if the file is included more than once, a running count thereof -- but, worry not,
we explode the instances and will include those-- so all entries will be unique */
int output; /*!< a flag to indicate if the inclusion has been output */
struct ast_config_include *next; /*!< ptr to next inclusion in the list */
};
typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, int withcomments, const char *suggested_include_file);
typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
/*! \brief Configuration engine structure, used to define realtime drivers */
struct ast_config_engine {
char *name;
config_load_func *load_func;
realtime_var_get *realtime_func;
realtime_multi_get *realtime_multi_func;
realtime_update *update_func;
struct ast_config_engine *next;
};
static struct ast_config_engine *config_engine_list;
static force_inline int ast_strlen_zero(const char *s)
{
}
#define S_OR(a, b) (!ast_strlen_zero(a) ? (a) : (b))
AST_INLINE_API(
void ast_copy_string(char *dst, const char *src, size_t size),
{
while (*src && size) {
*dst++ = *src++;
size--;
}
if (__builtin_expect(!size, 0))
dst--;
*dst = '\0';
}
AST_INLINE_API(
char *ast_skip_blanks(const char *str),
{
while (*str && *str < 33)
str++;
return (char *)str;
}
/*!
\brief Trims trailing whitespace characters from a string.
\param ast_trim_blanks function being used
\param str the input string
\return a pointer to the modified string
*/
AST_INLINE_API(
char *ast_trim_blanks(char *str),
{
if (work) {
work += strlen(work) - 1;
/* It's tempting to only want to erase after we exit this loop,
but since ast_trim_blanks *could* receive a constant string
(which we presumably wouldn't have to touch), we shouldn't
actually set anything unless we must, and it's easier just
to set each position to \0 than to keep track of a variable
for it */
while ((work >= str) && *work < 33)
*(work--) = '\0';
}
}
/*!
\brief Strip leading/trailing whitespace from a string.
\param s The string to be stripped (will be modified).
\return The stripped string.
This functions strips all leading and trailing whitespace
characters from the input string, and returns a pointer to
the resulting string. The string is modified in place.
*/
AST_INLINE_API(
char *ast_strip(char *s),
{
s = ast_skip_blanks(s);
if (s)
ast_trim_blanks(s);
return s;
}
)
struct ast_variable {
char *name;
char *value;
char *file;
int lineno;
int object; /*!< 0 for variable, 1 for object */
int blanklines; /*!< Number of blanklines following entry */
struct ast_comment *precomments;
struct ast_comment *sameline;
struct ast_variable *next;
char stuff[0];
};
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_include_file);
struct ast_config *localized_config_load_with_comments(const char *filename);
static char *ast_category_browse(struct ast_config *config, const char *prev);
static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
static void ast_variables_destroy(struct ast_variable *v);
static void ast_config_destroy(struct ast_config *cfg);
static struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size);
static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file);
void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file);
static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
{
struct ast_variable *variable;
int name_len = strlen(name) + 1;
if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + strlen(filename) + 1 + sizeof(*variable)))) {
variable->name = variable->stuff;
variable->value = variable->stuff + name_len;
variable->file = variable->value + strlen(value) + 1;
strcpy(variable->name,name);
strcpy(variable->value,value);
strcpy(variable->file,filename);
}
}
static struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size)
{
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
/* a file should be included ONCE. Otherwise, if one of the instances is changed,
then all be changed. -- how do we know to include it? -- Handling modified
instances is possible, I'd have
to create a new master for each instance. */
struct ast_config_include *inc;
inc = ast_include_find(conf, included_file);
if (inc)
{
inc->inclusion_count++;
snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
ast_log(LOG_WARNING,"'%s', line %d: Same File included more than once! This data will be saved in %s if saved back to disk.\n", from_file, from_lineno, real_included_file_name);
} else
*real_included_file_name = 0;
inc = ast_calloc(1,sizeof(struct ast_config_include));
inc->include_location_file = ast_strdup(from_file);
inc->include_location_lineno = from_lineno;
if (!ast_strlen_zero(real_included_file_name))
inc->included_file = ast_strdup(real_included_file_name);
else
inc->included_file = ast_strdup(included_file);
inc->exec = is_exec;
if (is_exec)
inc->exec_file = ast_strdup(exec_file);
/* attach this new struct to the conf struct */
inc->next = conf->includes;
conf->includes = inc;
return inc;
}
void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file)
{
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
struct ast_config_include *incl;
struct ast_category *cat;
struct ast_variable *v;
int from_len = strlen(from_file);
int to_len = strlen(to_file);
if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
return;
/* the manager code allows you to read in one config file, then
write it back out under a different name. But, the new arrangement
ties output lines to the file name. So, before you try to write
the config file to disk, better riffle thru the data and make sure
the file names are changed.
*/
/* file names are on categories, includes (of course), and on variables. So,
traverse all this and swap names */
for (incl = conf->includes; incl; incl=incl->next) {
if (strcmp(incl->include_location_file,from_file) == 0) {
if (from_len >= to_len)
strcpy(incl->include_location_file, to_file);
else {
free(incl->include_location_file);
incl->include_location_file = strdup(to_file);
}
}
}
for (cat = conf->root; cat; cat = cat->next) {
if (strcmp(cat->file,from_file) == 0) {
if (from_len >= to_len)
strcpy(cat->file, to_file);
else {
free(cat->file);
cat->file = strdup(to_file);
}
}
for (v = cat->root; v; v = v->next) {
if (strcmp(v->file,from_file) == 0) {
if (from_len >= to_len)
strcpy(v->file, to_file);
else {
free(v->file);
v->file = strdup(to_file);
}
}
}
}
}
static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file)
{
struct ast_config_include *x;
for (x=conf->includes;x;x=x->next)
{
if (strcmp(x->included_file,included_file) == 0)
return x;
}
return 0;
}
static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
{
if (!variable)
return;
if (category->last)
category->last->next = variable;
else
category->root = variable;
category->last = variable;
while (category->last->next)
category->last = category->last->next;
}
static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
{
/* try exact match first, then case-insensitive match */
for (cat = config->root; cat; cat = cat->next) {
if (cat->name == category_name && (ignored || !cat->ignored))
return cat;
}
for (cat = config->root; cat; cat = cat->next) {
if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
return cat;
}
return NULL;
}
static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
{
}
static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
{
if (category && config->last_browse && (config->last_browse->name == category))
cat = config->last_browse;
else
cat = ast_category_get(config, category);
}
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
{
if (category) {
for (v = ast_variable_browse(config, category); v; v = v->next) {
if (!strcasecmp(variable, v->name))
return v->value;
}
} else {
struct ast_category *cat;
for (cat = config->root; cat; cat = cat->next)
for (v = cat->root; v; v = v->next)
if (!strcasecmp(variable, v->name))
return v->value;
}
}
static struct ast_variable *variable_clone(const struct ast_variable *old)
{
struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
if (new) {
new->lineno = old->lineno;
new->object = old->object;
new->blanklines = old->blanklines;
/* TODO: clone comments? */
}
}
static void ast_variables_destroy(struct ast_variable *v)
{
while (v) {
vn = v;
v = v->next;
free(vn);
}
}
static void ast_includes_destroy(struct ast_config_include *incls)
{
struct ast_config_include *incl,*inclnext;
for (incl=incls; incl; incl = inclnext) {
inclnext = incl->next;
if (incl->include_location_file)
free(incl->include_location_file);
if (incl->exec_file)
free(incl->exec_file);
if (incl->included_file)
free(incl->included_file);
free(incl);
}
}
static void ast_config_destroy(struct ast_config *cfg)
{
ast_includes_destroy(cfg->includes);
cat = cfg->root;
while (cat) {
ast_variables_destroy(cat->root);
catn = cat;
cat = cat->next;
free(catn);
}
free(cfg);
}
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
enum ast_option_flags {
/*! Allow \#exec in config files */
AST_OPT_FLAG_EXEC_INCLUDES = (1 << 0),
/*! Do not fork() */
AST_OPT_FLAG_NO_FORK = (1 << 1),
/*! Keep quiet */
AST_OPT_FLAG_QUIET = (1 << 2),
/*! Console mode */
AST_OPT_FLAG_CONSOLE = (1 << 3),
/*! Run in realtime Linux priority */
AST_OPT_FLAG_HIGH_PRIORITY = (1 << 4),
/*! Initialize keys for RSA authentication */
AST_OPT_FLAG_INIT_KEYS = (1 << 5),
/*! Remote console */
AST_OPT_FLAG_REMOTE = (1 << 6),
/*! Execute an asterisk CLI command upon startup */
AST_OPT_FLAG_EXEC = (1 << 7),
/*! Don't use termcap colors */
AST_OPT_FLAG_NO_COLOR = (1 << 8),
/*! Are we fully started yet? */
AST_OPT_FLAG_FULLY_BOOTED = (1 << 9),
/*! Trascode via signed linear */
AST_OPT_FLAG_TRANSCODE_VIA_SLIN = (1 << 10),
/*! Dump core on a seg fault */
AST_OPT_FLAG_DUMP_CORE = (1 << 12),
/*! Cache sound files */
AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13),
/*! Display timestamp in CLI verbose output */
AST_OPT_FLAG_TIMESTAMP = (1 << 14),
/*! Override config */
AST_OPT_FLAG_OVERRIDE_CONFIG = (1 << 15),
/*! Reconnect */
AST_OPT_FLAG_RECONNECT = (1 << 16),
/*! Transmit Silence during Record() and DTMF Generation */
AST_OPT_FLAG_TRANSMIT_SILENCE = (1 << 17),
/*! Suppress some warnings */
AST_OPT_FLAG_DONT_WARN = (1 << 18),
/*! End CDRs before the 'h' extension */
AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),
/*! Use DAHDI Timing for generators if available */
AST_OPT_FLAG_INTERNAL_TIMING = (1 << 20),
/*! Always fork, even if verbose or debug settings are non-zero */
AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
/*! Disable log/verbose output to remote consoles */
AST_OPT_FLAG_MUTE = (1 << 22),
/*! There is a per-file debug setting */
AST_OPT_FLAG_DEBUG_FILE = (1 << 23),
/*! There is a per-file verbose setting */
AST_OPT_FLAG_VERBOSE_FILE = (1 << 24),
/*! Terminal colors should be adjusted for a light-colored background */
AST_OPT_FLAG_LIGHT_BACKGROUND = (1 << 25),
/*! Count Initiated seconds in CDR's */
AST_OPT_FLAG_INITIATED_SECONDS = (1 << 26),
/*! Force black background */
AST_OPT_FLAG_FORCE_BLACK_BACKGROUND = (1 << 27),
};
/* options.h declares ast_options extern; I need it static? */
#define AST_CACHE_DIR_LEN 512
#define AST_FILENAME_MAX 80
/*! These are the options that set by default when Asterisk starts */
#define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
#define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
#define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
#define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
#define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
#define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
#define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
#define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
#define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
#define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
#define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
#define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
#define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
#define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
#define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
#define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
#define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
#define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
#define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
#define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
#define ast_opt_end_cdr_before_h_exten ast_test_flag(&ast_options, AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN)
#define ast_opt_internal_timing ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING)
#define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
#define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
extern int option_verbose;
extern int option_debug; /*!< Debugging */
extern int option_maxcalls; /*!< Maximum number of simultaneous channels */
extern double option_maxload;
extern char defaultlanguage[];
extern char record_cache_dir[AST_CACHE_DIR_LEN];
extern char debug_filename[AST_FILENAME_MAX];
extern int ast_language_is_prefix;
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
/* linkedlists.h */
#define AST_LIST_LOCK(head) \
ast_mutex_lock(&(head)->lock)
/*!
\brief Write locks a list.
\param head This is a pointer to the list head structure
This macro attempts to place an exclusive write lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_WRLOCK(head) \
ast_rwlock_wrlock(&(head)->lock)
/*!
\brief Read locks a list.
\param head This is a pointer to the list head structure
This macro attempts to place a read lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_RDLOCK(head) \
ast_rwlock_rdlock(&(head)->lock)
/*!
\brief Locks a list, without blocking if the list is locked.
\param head This is a pointer to the list head structure
This macro attempts to place an exclusive lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_LIST_TRYLOCK(head) \
ast_mutex_trylock(&(head)->lock)
/*!
\brief Write locks a list, without blocking if the list is locked.
\param head This is a pointer to the list head structure
This macro attempts to place an exclusive write lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_TRYWRLOCK(head) \
ast_rwlock_trywrlock(&(head)->lock)
/*!
\brief Read locks a list, without blocking if the list is locked.
\param head This is a pointer to the list head structure
This macro attempts to place a read lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_TRYRDLOCK(head) \
ast_rwlock_tryrdlock(&(head)->lock)
/*!
\brief Attempts to unlock a list.
\param head This is a pointer to the list head structure
This macro attempts to remove an exclusive lock from the
list head structure pointed to by head. If the list
was not locked by this thread, this macro has no effect.
*/
#define AST_LIST_UNLOCK(head) \
ast_mutex_unlock(&(head)->lock)
/*!
\brief Attempts to unlock a read/write based list.
\param head This is a pointer to the list head structure
This macro attempts to remove a read or write lock from the
list head structure pointed to by head. If the list
was not locked by this thread, this macro has no effect.
*/
#define AST_RWLIST_UNLOCK(head) \
ast_rwlock_unlock(&(head)->lock)
/*!
\brief Defines a structure to be used to hold a list of specified type.
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type. It does not actually
declare (allocate) a structure; to do that, either follow this
macro with the desired name of the instance you wish to declare,