status = inuse = ast_device_state(trychan);
}
if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
- ast_str_append(&tmp_availchan, 0, "%s%s", tmp_availchan->used ? "&" : "", tempchan->name);
+ ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", tempchan->name);
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
- ast_str_append(&tmp_availorig, 0, "%s%s", tmp_availorig->used ? "&" : "", tmp);
+ ast_str_append(&tmp_availorig, 0, "%s%s", ast_str_strlen(tmp_availorig) ? "&" : "", tmp);
snprintf(tmp, sizeof(tmp), "%d", status);
- ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
+ ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp);
ast_hangup(tempchan);
tempchan = NULL;
}
} else {
snprintf(tmp, sizeof(tmp), "%d", status);
- ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
+ ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp);
}
cur = rest;
} while (cur);
}
- pbx_builtin_setvar_helper(chan, "AVAILCHAN", tmp_availchan->str);
+ pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
/* Store the originally used channel too */
- pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp_availorig->str);
- pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp_availstat->str);
+ pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig));
+ pbx_builtin_setvar_helper(chan, "AVAILSTATUS", ast_str_buffer(tmp_availstat));
return 0;
}
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
+#include "asterisk/app.h"
/*** DOCUMENTATION
<application name="DumpChan" language="en_US">
static int dumpchan_exec(struct ast_channel *chan, void *data)
{
- struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX very large! */
+ struct ast_str *vars = ast_str_thread_get(&global_app_buf, 16);
char info[1024];
int level = 0;
static char *line = "================================================================================";
if (!ast_strlen_zero(data))
level = atoi(data);
- pbx_builtin_serialize_variables(chan, &vars);
- serialize_showchan(chan, info, sizeof(info));
- if (option_verbose >= level)
- ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, vars->str, line);
+ if (option_verbose >= level) {
+ serialize_showchan(chan, info, sizeof(info));
+ pbx_builtin_serialize_variables(chan, &vars);
+ ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, ast_str_buffer(vars), line);
+ }
return 0;
}
ast_str_append(&tmp, 0, ",%s", data);
}
- fprintf(handle, "%s\n", tmp->str);
- ast_debug(1, "sent '%s'\n", tmp->str);
+ fprintf(handle, "%s\n", ast_str_buffer(tmp));
+ ast_debug(1, "sent '%s'\n", ast_str_buffer(tmp));
}
static void *gen_alloc(struct ast_channel *chan, void *params)
ast_str_append(&newstring, 0, "%s=%s,", variable, value);
ast_channel_unlock(chan);
- ast_copy_string(outbuf, newstring->str, outbuflen);
+ ast_copy_string(outbuf, ast_str_buffer(newstring), outbuflen);
}
}
continue;
if (input[0] == 'P') {
- send_eivr_event(eivr_events, 'P', args->str, chan);
+ struct ast_str *tmp = (struct ast_str *) args;
+ send_eivr_event(eivr_events, 'P', ast_str_buffer(tmp), chan);
} else if ( input[0] == 'T' ) {
ast_chan_log(LOG_WARNING, chan, "Answering channel if needed and starting generator\n");
if (chan->_state != AST_STATE_UP) {
}
/* This one has to exist; it was part of the query */
ordstr = ast_variable_retrieve(cfg, catg, "ordinal");
- ast_str_make_space(&str, strlen(numstr) + 1);
- ast_copy_string(str->str, numstr, str->len);
- if ((cur = create_followme_number(str->str, timeout, atoi(ordstr)))) {
+ ast_str_set(&str, 0, "%s", numstr);
+ if ((cur = create_followme_number(ast_str_buffer(str), timeout, atoi(ordstr)))) {
AST_LIST_INSERT_TAIL(&new->numbers, cur, entry);
}
}
min = ((now - cnf->start) % 3600) / 60;
sec = (now - cnf->start) % 60;
if (!concise) {
- ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, cmdline->str, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No");
+ ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, ast_str_buffer(cmdline), hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No");
} else {
ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n",
cnf->confno,
return CLI_SHOWUSAGE;
}
- ast_debug(1, "Cmdline: %s\n", cmdline->str);
+ ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline));
- admin_exec(NULL, cmdline->str);
+ admin_exec(NULL, ast_str_buffer(cmdline));
ast_free(cmdline);
return CLI_SUCCESS;
return CLI_SHOWUSAGE;
}
- ast_debug(1, "Cmdline: %s\n", cmdline->str);
+ ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline));
- admin_exec(NULL, cmdline->str);
+ admin_exec(NULL, ast_str_buffer(cmdline));
ast_free(cmdline);
return CLI_SUCCESS;
ast_set_flag(&conf_flags,
CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION);
answer_trunk_chan(trunk_ref->chan);
- conf = build_conf(conf_name->str, "", "", 0, 0, 1, trunk_ref->chan);
+ conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan);
if (conf) {
conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL);
dispose_conf(conf);
if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) &&
trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
ast_str_append(&conf_name, 0, ",K");
- admin_exec(NULL, conf_name->str);
+ admin_exec(NULL, ast_str_buffer(conf_name));
trunk_ref->trunk->hold_stations = 0;
sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
}
/*! \brief convert "\n" to "\nVariable: " ready for manager to use */
static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
{
- struct ast_str *buf = ast_str_alloca(len + 1);
+ struct ast_str *buf = ast_str_thread_get(&global_app_buf, len + 1);
char *tmp;
if (pbx_builtin_serialize_variables(chan, &buf)) {
/* convert "\n" to "\nVariable: " */
strcpy(vars, "Variable: ");
- tmp = buf->str;
+ tmp = ast_str_buffer(buf);
for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
vars[j] = tmp[i];
if (qe->parent->randomperiodicannounce) {
qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
} else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
- ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) {
+ ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
qe->last_periodic_announce_sound = 0;
}
/* play the announcement */
- res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str);
+ res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
if ((res > 0 && !valid_exit(qe, res)) || res < 0)
res = 0;
ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
int2strat(q->strategy), q->holdtime, q->weight,
q->callscompleted, q->callsabandoned,sl,q->servicelevel);
- do_print(s, fd, out->str);
+ do_print(s, fd, ast_str_buffer(out));
if (!ao2_container_count(q->members))
do_print(s, fd, " No Members");
else {
mem->calls, (long) (time(NULL) - mem->lastcall));
else
ast_str_append(&out, 0, " has taken no calls yet");
- do_print(s, fd, out->str);
+ do_print(s, fd, ast_str_buffer(out));
ao2_ref(mem, -1);
}
}
ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)",
pos++, qe->chan->name, (long) (now - qe->start) / 60,
(long) (now - qe->start) % 60, qe->prio);
- do_print(s, fd, out->str);
+ do_print(s, fd, ast_str_buffer(out));
}
}
do_print(s, fd, ""); /* blank line between entries */
ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
else
ast_str_set(&out, 0, "No queues.");
- do_print(s, fd, out->str);
+ do_print(s, fd, ast_str_buffer(out));
}
return CLI_SUCCESS;
}
AST_LIST_UNLOCK(&zones);
}
-static char *substitute_escapes(const char *value)
+static const char *substitute_escapes(const char *value)
{
- char *current, *result;
+ char *current;
/* Add 16 for fudge factor */
- struct ast_str *str = ast_str_create(strlen(value) + 16);
+ struct ast_str *str = ast_str_thread_get(&global_app_buf, strlen(value) + 16);
/* Substitute strings \r, \n, and \t into the appropriate characters */
for (current = (char *) value; *current; current++) {
}
}
- result = ast_strdup(str->str);
- ast_free(str);
-
- return result;
+ return ast_str_buffer(str);
}
static int load_config(int reload)
emailsubject = ast_strdup(val);
}
if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
- emailbody = substitute_escapes(val);
+ emailbody = ast_strdup(substitute_escapes(val));
}
if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
pagersubject = ast_strdup(val);
}
if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
- pagerbody = substitute_escapes(val);
+ pagerbody = ast_strdup(substitute_escapes(val));
}
AST_LIST_UNLOCK(&users);
ast_config_destroy(cfg);
#define LENGTHEN_BUF1(size) \
do { \
/* Lengthen buffer, if necessary */ \
- if (sql->used + size + 1 > sql->len) { \
- if (ast_str_make_space(&sql, ((sql->len + size + 1) / 512 + 1) * 512) != 0) { \
+ if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
+ if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
ast_free(sql); \
ast_free(sql2); \
#define LENGTHEN_BUF2(size) \
do { \
- if (sql2->used + size + 1 > sql2->len) { \
- if (ast_str_make_space(&sql2, ((sql2->len + size + 3) / 512 + 1) * 512) != 0) { \
+ if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
+ if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
ast_free(sql); \
ast_free(sql2); \
}
AST_LIST_TRAVERSE(&odbc_tables, tableptr, list) {
+ int first = 1;
ast_str_set(&sql, 0, "INSERT INTO %s (", tableptr->table);
ast_str_set(&sql2, 0, " VALUES (");
/* No need to check the connection now; we'll handle any failure in prepare_and_execute */
if (!(obj = ast_odbc_request_obj(tableptr->connection, 0))) {
- ast_log(LOG_WARNING, "cdr_adaptive_odbc: Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql->str);
+ ast_log(LOG_WARNING, "cdr_adaptive_odbc: Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, ast_str_buffer(sql));
continue;
}
}
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(strlen(colptr));
/* Encode value, with escaping */
- ast_str_append(&sql2, 0, "'");
+ ast_str_append(&sql2, 0, "%s'", first ? "" : ",");
for (tmp = colptr; *tmp; tmp++) {
if (*tmp == '\'') {
ast_str_append(&sql2, 0, "''");
ast_str_append(&sql2, 0, "%c", *tmp);
}
}
- ast_str_append(&sql2, 0, "',");
+ ast_str_append(&sql2, 0, "'");
break;
case SQL_TYPE_DATE:
{
(month == 2 && year % 4 == 0 && day > 29) ||
(month == 2 && year % 4 != 0 && day > 28)) {
ast_log(LOG_WARNING, "CDR variable %s is not a valid date ('%s').\n", entry->name, colptr);
- break;
+ continue;
}
if (year > 0 && year < 100) {
year += 2000;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(17);
- ast_str_append(&sql2, 0, "{ d '%04d-%02d-%02d' },", year, month, day);
+ ast_str_append(&sql2, 0, "%s{ d '%04d-%02d-%02d' }", first ? "" : ",", year, month, day);
}
break;
case SQL_TYPE_TIME:
if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
ast_log(LOG_WARNING, "CDR variable %s is not a valid time ('%s').\n", entry->name, colptr);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(15);
- ast_str_append(&sql2, 0, "{ t '%02d:%02d:%02d' },", hour, minute, second);
+ ast_str_append(&sql2, 0, "%s{ t '%02d:%02d:%02d' }", first ? "" : ",", hour, minute, second);
}
break;
case SQL_TYPE_TIMESTAMP:
(month == 2 && year % 4 != 0 && day > 28) ||
hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) {
ast_log(LOG_WARNING, "CDR variable %s is not a valid timestamp ('%s').\n", entry->name, colptr);
- break;
+ continue;
}
if (year > 0 && year < 100) {
year += 2000;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(26);
- ast_str_append(&sql2, 0, "{ ts '%04d-%02d-%02d %02d:%02d:%02d' },", year, month, day, hour, minute, second);
+ ast_str_append(&sql2, 0, "%s{ ts '%04d-%02d-%02d %02d:%02d:%02d' }", first ? "" : ",", year, month, day, hour, minute, second);
}
break;
case SQL_INTEGER:
int integer = 0;
if (sscanf(colptr, "%d", &integer) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%d,", integer);
+ ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
}
break;
case SQL_BIGINT:
long long integer = 0;
if (sscanf(colptr, "%lld", &integer) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(24);
- ast_str_append(&sql2, 0, "%lld,", integer);
+ ast_str_append(&sql2, 0, "%s%lld", first ? "" : ",", integer);
}
break;
case SQL_SMALLINT:
short integer = 0;
if (sscanf(colptr, "%hd", &integer) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(6);
- ast_str_append(&sql2, 0, "%d,", integer);
+ ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
}
break;
case SQL_TINYINT:
char integer = 0;
if (sscanf(colptr, "%hhd", &integer) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(4);
- ast_str_append(&sql2, 0, "%d,", integer);
+ ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
}
break;
case SQL_BIT:
char integer = 0;
if (sscanf(colptr, "%hhd", &integer) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name);
- break;
+ continue;
}
if (integer != 0)
integer = 1;
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(2);
- ast_str_append(&sql2, 0, "%d,", integer);
+ ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
}
break;
case SQL_NUMERIC:
double number = 0.0;
if (sscanf(colptr, "%lf", &number) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(entry->decimals);
- ast_str_append(&sql2, 0, "%*.*lf,", entry->decimals, entry->radix, number);
+ ast_str_append(&sql2, 0, "%s%*.*lf", first ? "" : ",", entry->decimals, entry->radix, number);
}
break;
case SQL_FLOAT:
double number = 0.0;
if (sscanf(colptr, "%lf", &number) != 1) {
ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name);
- break;
+ continue;
}
- ast_str_append(&sql, 0, "%s,", entry->name);
+ ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
LENGTHEN_BUF2(entry->decimals);
- ast_str_append(&sql2, 0, "%lf,", number);
+ ast_str_append(&sql2, 0, "%s%lf", first ? "" : ",", number);
}
break;
default:
ast_log(LOG_WARNING, "Column type %d (field '%s:%s:%s') is unsupported at this time.\n", entry->type, tableptr->connection, tableptr->table, entry->name);
+ continue;
}
+ first = 0;
}
}
/* Concatenate the two constructed buffers */
- LENGTHEN_BUF1(sql2->used);
- sql->str[sql->used - 1] = ')';
- sql2->str[sql2->used - 1] = ')';
- ast_str_append(&sql, 0, "%s", sql2->str);
+ LENGTHEN_BUF1(ast_str_strlen(sql2));
+ ast_str_append(&sql, 0, ")");
+ ast_str_append(&sql2, 0, ")");
+ ast_str_append(&sql, 0, "%s", ast_str_buffer(sql2));
- ast_verb(11, "[%s]\n", sql->str);
+ ast_verb(11, "[%s]\n", ast_str_buffer(sql));
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql->str);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, ast_str_buffer(sql));
if (stmt) {
SQLRowCount(stmt, &rows);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
if (rows == 0) {
- ast_log(LOG_WARNING, "cdr_adaptive_odbc: Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql->str);
+ ast_log(LOG_WARNING, "cdr_adaptive_odbc: Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, ast_str_buffer(sql));
}
early_release:
ast_odbc_release_obj(obj);
AST_RWLIST_UNLOCK(&odbc_tables);
/* Next time, just allocate buffers that are that big to start with. */
- if (sql->used > maxsize) {
- maxsize = sql->used;
+ if (ast_str_strlen(sql) > maxsize) {
+ maxsize = ast_str_strlen(sql);
}
- if (sql2->used > maxsize2) {
- maxsize2 = sql2->used;
+ if (ast_str_strlen(sql2) > maxsize2) {
+ maxsize2 = ast_str_strlen(sql2);
}
ast_free(sql);
v = ast_variable_browse(cfg, cat);
while (v) {
if (customfields && !ast_strlen_zero(v->name) && !ast_strlen_zero(v->value)) {
- if( (customfields->used + strlen(v->value) + strlen(v->name) + 14) < customfields->len) {
+ if ((ast_str_strlen(customfields) + strlen(v->value) + strlen(v->name) + 14) < ast_str_size(customfields)) {
ast_str_append(&customfields, -1, "%s: ${CDR(%s)}\r\n", v->value, v->name);
ast_log(LOG_NOTICE, "Added mapping %s: ${CDR(%s)}\n", v->value, v->name);
} else {
buf[0] = 0;
/* Custom fields handling */
- if (customfields != NULL && customfields->used > 0) {
+ if (customfields != NULL && ast_str_strlen(customfields)) {
memset(&dummy, 0, sizeof(dummy));
dummy.cdr = cdr;
- pbx_substitute_variables_helper(&dummy, customfields->str, buf, sizeof(buf) - 1);
+ pbx_substitute_variables_helper(&dummy, ast_str_buffer(customfields), buf, sizeof(buf) - 1);
}
manager_event(EVENT_FLAG_CDR, "Cdr",
static AST_RWLIST_HEAD_STATIC(psql_columns, columns);
-#define LENGTHEN_BUF1(size) \
- do { \
- /* Lengthen buffer, if necessary */ \
- if (sql->used + size + 1 > sql->len) { \
- if (ast_str_make_space(&sql, ((sql->len + size + 1) / 512 + 1) * 512) != 0) { \
+#define LENGTHEN_BUF1(size) \
+ do { \
+ /* Lengthen buffer, if necessary */ \
+ if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
+ if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 3) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR failed.\n"); \
- ast_free(sql); \
- ast_free(sql2); \
- AST_RWLIST_UNLOCK(&psql_columns); \
- return -1; \
- } \
- } \
+ ast_free(sql); \
+ ast_free(sql2); \
+ AST_RWLIST_UNLOCK(&psql_columns); \
+ return -1; \
+ } \
+ } \
} while (0)
-#define LENGTHEN_BUF2(size) \
- do { \
- if (sql2->used + size + 1 > sql2->len) { \
- if (ast_str_make_space(&sql2, ((sql2->len + size + 3) / 512 + 1) * 512) != 0) { \
+#define LENGTHEN_BUF2(size) \
+ do { \
+ if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
+ if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR failed.\n"); \
- ast_free(sql); \
- ast_free(sql2); \
- AST_RWLIST_UNLOCK(&psql_columns); \
- return -1; \
- } \
- } \
+ ast_free(sql); \
+ ast_free(sql2); \
+ AST_RWLIST_UNLOCK(&psql_columns); \
+ return -1; \
+ } \
+ } \
} while (0)
static int pgsql_log(struct ast_cdr *cdr)
struct columns *cur;
struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
char buf[257], escapebuf[513], *value;
-
+ int first = 1;
+
if (!sql || !sql2) {
if (sql) {
ast_free(sql);
if (cur->notnull && !cur->hasdefault) {
/* Field is NOT NULL (but no default), must include it anyway */
LENGTHEN_BUF1(strlen(cur->name) + 2);
- ast_str_append(&sql, 0, "\"%s\",", cur->name);
+ ast_str_append(&sql, 0, "%s\"%s\"", first ? "" : ",", cur->name);
LENGTHEN_BUF2(3);
- ast_str_append(&sql2, 0, "'',");
+ ast_str_append(&sql2, 0, "%s''", first ? "" : ",");
+ first = 0;
}
continue;
}
LENGTHEN_BUF1(strlen(cur->name) + 2);
- ast_str_append(&sql, 0, "\"%s\",", cur->name);
+ ast_str_append(&sql, 0, "%s\"%s\"", first ? "" : ",", cur->name);
if (strcmp(cur->name, "start") == 0 || strcmp(cur->name, "calldate") == 0) {
if (strncmp(cur->type, "int", 3) == 0) {
- LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%ld", cdr->start.tv_sec);
+ LENGTHEN_BUF2(13);
+ ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->start.tv_sec);
} else if (strncmp(cur->type, "float", 5) == 0) {
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "%f", (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0);
} else {
/* char, hopefully */
- LENGTHEN_BUF2(30);
+ LENGTHEN_BUF2(31);
ast_localtime(&cdr->start, &tm, NULL);
ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
- ast_str_append(&sql2, 0, "%s", buf);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf);
}
} else if (strcmp(cur->name, "answer") == 0) {
if (strncmp(cur->type, "int", 3) == 0) {
- LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%ld", cdr->answer.tv_sec);
+ LENGTHEN_BUF2(13);
+ ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->answer.tv_sec);
} else if (strncmp(cur->type, "float", 5) == 0) {
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "%f", (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0);
} else {
/* char, hopefully */
- LENGTHEN_BUF2(30);
+ LENGTHEN_BUF2(31);
ast_localtime(&cdr->start, &tm, NULL);
ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
- ast_str_append(&sql2, 0, "%s", buf);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf);
}
} else if (strcmp(cur->name, "end") == 0) {
if (strncmp(cur->type, "int", 3) == 0) {
- LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%ld", cdr->end.tv_sec);
+ LENGTHEN_BUF2(13);
+ ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->end.tv_sec);
} else if (strncmp(cur->type, "float", 5) == 0) {
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "%f", (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0);
} else {
/* char, hopefully */
- LENGTHEN_BUF2(30);
+ LENGTHEN_BUF2(31);
ast_localtime(&cdr->end, &tm, NULL);
ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
- ast_str_append(&sql2, 0, "%s", buf);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf);
}
} else if (strcmp(cur->name, "duration") == 0 || strcmp(cur->name, "billsec") == 0) {
if (cur->type[0] == 'i') {
/* Get integer, no need to escape anything */
ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
- LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%s", value);
+ LENGTHEN_BUF2(13);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", value);
} else if (strncmp(cur->type, "float", 5) == 0) {
struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer;
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "%f", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
} else {
/* Char field, probably */
struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer;
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "'%f'", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s'%f'", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
}
} else if (strcmp(cur->name, "disposition") == 0 || strcmp(cur->name, "amaflags") == 0) {
if (strncmp(cur->type, "int", 3) == 0) {
/* Integer, no need to escape anything */
ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 1);
- LENGTHEN_BUF2(12);
- ast_str_append(&sql2, 0, "%s", value);
+ LENGTHEN_BUF2(13);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", value);
} else {
/* Although this is a char field, there are no special characters in the values for these fields */
ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
- LENGTHEN_BUF2(30);
- ast_str_append(&sql2, 0, "'%s'", value);
+ LENGTHEN_BUF2(31);
+ ast_str_append(&sql2, 0, "%s'%s'", first ? "" : ",", value);
}
} else {
/* Arbitrary field, could be anything */
if (strncmp(cur->type, "int", 3) == 0) {
long long whatever;
if (value && sscanf(value, "%lld", &whatever) == 1) {
- LENGTHEN_BUF2(25);
- ast_str_append(&sql2, 0, "%lld", whatever);
+ LENGTHEN_BUF2(26);
+ ast_str_append(&sql2, 0, "%s%lld", first ? "" : ",", whatever);
} else {
- LENGTHEN_BUF2(1);
- ast_str_append(&sql2, 0, "0");
+ LENGTHEN_BUF2(2);
+ ast_str_append(&sql2, 0, "%s0", first ? "" : ",");
}
} else if (strncmp(cur->type, "float", 5) == 0) {
long double whatever;
if (value && sscanf(value, "%Lf", &whatever) == 1) {
- LENGTHEN_BUF2(50);
- ast_str_append(&sql2, 0, "%30Lf", whatever);
+ LENGTHEN_BUF2(51);
+ ast_str_append(&sql2, 0, "%s%30Lf", first ? "" : ",", whatever);
} else {
- LENGTHEN_BUF2(1);
- ast_str_append(&sql2, 0, "0");
+ LENGTHEN_BUF2(2);
+ ast_str_append(&sql2, 0, "%s0", first ? "" : ",");
}
/* XXX Might want to handle dates, times, and other misc fields here XXX */
} else {
PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
else
escapebuf[0] = '\0';
- LENGTHEN_BUF2(strlen(escapebuf) + 2);
- ast_str_append(&sql2, 0, "'%s'", escapebuf);
+ LENGTHEN_BUF2(strlen(escapebuf) + 3);
+ ast_str_append(&sql2, 0, "%s'%s'", first ? "" : ",", escapebuf);
}
}
- LENGTHEN_BUF2(1);
- ast_str_append(&sql2, 0, ",");
+ first = 0;
}
AST_RWLIST_UNLOCK(&psql_columns);
- LENGTHEN_BUF1(sql2->len);
- sql->str[sql->used - 1] = ')';
- sql2->str[sql2->used - 1] = ')';
- ast_str_append(&sql, 0, "%s", sql2->str);
- ast_verb(11, "[%s]\n", sql->str);
+ LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
+ ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2));
+ ast_verb(11, "[%s]\n", ast_str_buffer(sql));
ast_debug(2, "inserting a CDR record.\n");
return -1;
}
}
- result = PQexec(conn, sql->str);
+ result = PQexec(conn, ast_str_buffer(sql));
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
pgerror = PQresultErrorMessage(result);
ast_log(LOG_ERROR, "Failed to insert call detail record into database!\n");
ast_log(LOG_ERROR, "Connection reestablished.\n");
connected = 1;
PQclear(result);
- result = PQexec(conn, sql->str);
+ result = PQexec(conn, ast_str_buffer(sql));
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
pgerror = PQresultErrorMessage(result);
ast_log(LOG_ERROR, "HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n");
ast_free(save);
return -1;
}
- if (!column_string->used)
- ast_str_set(&column_string, 0, "%s", escaped);
- else
- ast_str_append(&column_string, 0, ",%s", escaped);
+ ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
sqlite3_free(escaped);
}
- if (!(columns = ast_strdup(column_string->str))) {
+ if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
ast_free(column_string);
ast_free(save);
struct ast_variable *mappingvar;
const char *tmp;
- if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
- if (reload)
- ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
- else
- ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
+ if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
+ ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated.");
return -1;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+ } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
+ }
- if (reload)
+ if (reload) {
free_config();
+ }
ast_mutex_lock(&lock);
}
/* Mapping must have a table name */
- tmp = ast_variable_retrieve(cfg, "master", "table");
- if (!ast_strlen_zero(tmp))
+ if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
ast_copy_string(table, tmp, sizeof(table));
- else {
+ } else {
ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n");
strcpy(table, "cdr");
}
/* Columns */
- tmp = ast_variable_retrieve(cfg, "master", "columns");
- if (load_column_config(tmp)) {
+ if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
ast_mutex_unlock(&lock);
ast_config_destroy(cfg);
free_config();
}
/* Values */
- tmp = ast_variable_retrieve(cfg, "master", "values");
- if (load_values_config(tmp)) {
+ if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
ast_mutex_unlock(&lock);
ast_config_destroy(cfg);
free_config();
columns = NULL;
}
- while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list)))
+ while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
ast_free(value);
+ }
ast_mutex_unlock(&lock);
struct ast_str *value_string = ast_str_create(1024);
dummy.cdr = cdr;
AST_LIST_TRAVERSE(&sql_values, value, list) {
- memset(subst_buf, 0, sizeof(subst_buf));
pbx_substitute_variables_helper(&dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
escaped = sqlite3_mprintf("%q", subst_buf);
- if (!value_string->used)
- ast_str_append(&value_string, 0, "'%s'", escaped);
- else
- ast_str_append(&value_string, 0, ",'%s'", escaped);
+ ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
sqlite3_free(escaped);
}
- sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, value_string->str);
+ sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
ast_debug(1, "About to log: %s\n", sql);
ast_free(value_string);
}
/* XXX This seems awful arbitrary... */
for (count = 0; count < 5; count++) {
res = sqlite3_exec(db, sql, NULL, NULL, &error);
- if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
+ if (res != SQLITE_BUSY && res != SQLITE_LOCKED) {
break;
+ }
usleep(200);
}
sqlite3_free(error);
}
- if (sql)
+ if (sql) {
sqlite3_free(sql);
+ }
ast_mutex_unlock(&lock);
free_config();
return AST_MODULE_LOAD_DECLINE;
}
- } else
+ } else {
return AST_MODULE_LOAD_DECLINE;
+ }
/* is the database there? */
snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
else
ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
for (x = 0; x < 3; x++) {
- if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
+ if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
break;
}
y++;
} while (x < 3);
- tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
+ tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
if (!tmp)
return NULL;
tmp->tech = &dahdi_tech;
/*! \brief A per-thread temporary pvt structure */
AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
+AST_THREADSTORAGE(transmit_state_buffer);
+AST_THREADSTORAGE(mailbox_buffer);
#ifdef LOW_MEMORY
static void ts_ast_rtp_destroy(void *);
static int expire_register(const void *data);
static void *do_monitor(void *data);
static int restart_monitor(void);
-static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
+static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
/* static int sip_addrcmp(char *name, struct sockaddr_in *sin); Support for peer matching */
static int sip_refer_allocate(struct sip_pvt *p);
static void ast_quiet_chan(struct ast_channel *chan);
}
/* Read in headers one line at a time */
- while (req.len < 4 || strncmp((char *)&req.data->str + req.len - 4, "\r\n\r\n", 4)) {
+ while (req.len < 4 || strncmp(ast_str_buffer(req.data) + req.len - 4, "\r\n\r\n", 4)) {
ast_mutex_lock(&tcptls_session->lock);
if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
ast_mutex_unlock(&tcptls_session->lock);
ast_mutex_unlock(&tcptls_session->lock);
if (me->stop)
goto cleanup;
- ast_str_append(&req.data, 0, "%s", buf);
- req.len = req.data->used;
+ ast_str_append(&req.data, -1, "%s", buf);
+ req.len = ast_str_strlen(req.data);
}
copy_request(&reqcpy, &req);
parse_request(&reqcpy);
if (me->stop)
goto cleanup;
cl -= strlen(buf);
- ast_str_append(&req.data, 0, "%s", buf);
- req.len = req.data->used;
+ ast_str_append(&req.data, -1, "%s", buf);
+ req.len = ast_str_strlen(req.data);
}
}
/*! \todo XXX If there's no Content-Length or if the content-length and what
int res = 0;
const struct sockaddr_in *dst = sip_real_dst(p);
- ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
+ ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", ast_str_buffer(data), get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
- if (sip_prepare_socket(p) < 0)
+ if (sip_prepare_socket(p) < 0) {
return XMIT_ERROR;
+ }
- if (p->socket.tcptls_session)
+ if (p->socket.tcptls_session) {
ast_mutex_lock(&p->socket.tcptls_session->lock);
+ }
- if (p->socket.type & SIP_TRANSPORT_UDP)
- res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
- else {
- if (p->socket.tcptls_session->f)
- res = ast_tcptls_server_write(p->socket.tcptls_session, data->str, len);
- else
+ if (p->socket.type & SIP_TRANSPORT_UDP) {
+ res = sendto(p->socket.fd, ast_str_buffer(data), len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+ } else {
+ if (p->socket.tcptls_session->f) {
+ res = ast_tcptls_server_write(p->socket.tcptls_session, ast_str_buffer(data), len);
+ } else {
ast_debug(2, "No p->socket.tcptls_session->f len=%d\n", len);
+ }
}
if (p->socket.tcptls_session)
res = XMIT_ERROR; /* Don't bother with trying to transmit again */
}
}
- if (res != len)
+ if (res != len) {
ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
+ }
return res;
}
ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
pkt->retrans, sip_nat_mode(pkt->owner),
ast_inet_ntoa(dst->sin_addr),
- ntohs(dst->sin_port), pkt->data->str);
+ ntohs(dst->sin_port), ast_str_buffer(pkt->data));
}
- append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
+ append_history(pkt->owner, "ReTx", "%d %s", reschedule, ast_str_buffer(pkt->data));
xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
sip_pvt_unlock(pkt->owner);
if (xmitres == XMIT_ERROR)
ast_free(pkt);
return AST_FAILURE;
}
- ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0");
+ ast_str_set(&pkt->data, 0, "%s", ast_str_buffer(data));
pkt->packetlen = len;
/* copy other parameters from the caller */
pkt->method = sipmethod;
return;
}
cur = p->packets;
- method = (cur->method) ? cur->method : find_sip_method(cur->data->str);
+ method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data));
__sip_ack(p, cur->seqno, cur->is_resp, method);
}
}
for (cur = p->packets; cur; cur = cur->next) {
if (cur->seqno == seqno && cur->is_resp == resp &&
- (cur->is_resp || method_match(sipmethod, cur->data->str))) {
+ (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) {
/* this is our baby */
if (cur->retransid > -1) {
if (sipdebug)
if (!req->lines) {
/* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
ast_str_append(&req->data, 0, "\r\n");
- req->len = req->data->used;
+ req->len = ast_str_strlen(req->data);
}
}
ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
reliable ? "Reliably " : "", sip_nat_mode(p),
ast_inet_ntoa(dst->sin_addr),
- ntohs(dst->sin_port), req->data->str);
+ ntohs(dst->sin_port), ast_str_buffer(req->data));
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = NULL, };
parse_copy(&tmp, req);
- append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"),
+ append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"),
(tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? tmp.rlPart2 : sip_methods[tmp.method].text);
ast_free(tmp.data);
}
add_blank(req);
if (sip_debug_test_pvt(p)) {
- if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
- ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str);
- else
- ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str);
+ if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) {
+ ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), ast_str_buffer(req->data));
+ } else {
+ ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), ast_str_buffer(req->data));
+ }
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = NULL, };
parse_copy(&tmp, req);
- append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
+ append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
ast_free(tmp.data);
}
res = (reliable) ?
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
/* Start the process if it's not already started */
- if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) {
+ if (!p->alreadygone && p->initreq.data && ast_str_strlen(p->initreq.data)) {
if (needcancel) { /* Outgoing call, not up */
if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
/* stop retransmitting an INVITE that has not received a response */
*/
static int parse_request(struct sip_request *req)
{
- char *c = req->data->str, **dst = req->header;
+ char *c = ast_str_buffer(req->data), **dst = req->header;
int i = 0, lim = SIP_MAX_HEADERS - 1;
unsigned int skipping_headers = 0;
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
/* Queue Manager Unhold event */
- append_history(p, "Unhold", "%s", req->data->str);
+ append_history(p, "Unhold", "%s", ast_str_buffer(req->data));
if (sip_cfg.callevents)
manager_event(EVENT_FLAG_CALL, "Hold",
"Status: Off\r\n"
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
/* Queue Manager Hold event */
- append_history(p, "Hold", "%s", req->data->str);
+ append_history(p, "Hold", "%s", ast_str_buffer(req->data));
if (sip_cfg.callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
manager_event(EVENT_FLAG_CALL, "Hold",
"Status: On\r\n"
return -1;
}
- ast_str_append(&req->data, 0, "%s: %s\r\n", var, value);
- req->header[req->headers] = req->data->str + req->len;
+ ast_str_append(&req->data, -1, "%s: %s\r\n", var, value);
+ req->header[req->headers] = ast_str_buffer(req->data) + req->len;
if (sip_cfg.compactheaders)
var = find_alias(var, var);
ast_log(LOG_WARNING, "Out of SIP line space\n");
return -1;
}
- if (!req->lines)
+ if (!req->lines) {
/* Add extra empty return */
- req->len += ast_str_append(&req->data, 0, "\r\n");
- if (req->len >= sizeof(req->data->str) - 4) {
- ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
- return -1;
+ req->len += ast_str_append(&req->data, -1, "\r\n");
}
- req->line[req->lines] = req->data->str + req->len;
- ast_str_append(&req->data, 0, "%s", line);
- req->len += strlen(req->line[req->lines]);
+ req->line[req->lines] = ast_str_buffer(req->data) + ast_str_strlen(req->data);
+ req->len += ast_str_append(&req->data, -1, "%s", line);
req->lines++;
return 0;
}
/* Find ;rport; (empty request) */
rport = strstr(leftmost, ";rport");
- if (rport && *(rport+6) == '=')
+ if (rport && *(rport + 6) == '=')
rport = NULL; /* We already have a parameter to rport */
/* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting) */
resp->method = SIP_RESPONSE;
if (!(resp->data = ast_str_create(SIP_MIN_PACKET)))
return -1;
- resp->header[0] = resp->data->str;
- ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg);
- resp->len = strlen(resp->header[0]);
+ ast_str_set(&resp->data, -1, "SIP/2.0 %s\r\n", msg);
+ resp->header[0] = ast_str_buffer(resp->data);
+ resp->len = ast_str_strlen(resp->data);
resp->headers++;
return 0;
}
if (!(req->data = ast_str_create(SIP_MIN_PACKET)))
return -1;
req->method = sipmethod;
- req->header[0] = req->data->str;
- ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
- req->len = strlen(req->header[0]);
+ ast_str_set(&req->data, -1, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
+ req->header[0] = ast_str_buffer(req->data);
+ req->len = ast_str_strlen(req->data);
req->headers++;
return 0;
}
ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x);
if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
- len = m_modem->used + a_modem->used;
+ len = ast_str_strlen(m_modem) + ast_str_strlen(a_modem);
add_header(resp, "Content-Type", "application/sdp");
add_header_contentLength(resp, len);
- add_line(resp, m_modem->str);
- add_line(resp, a_modem->str);
+ add_line(resp, ast_str_buffer(m_modem));
+ add_line(resp, ast_str_buffer(a_modem));
/* Update lastrtprx when we send our SDP */
p->lastrtprx = p->lastrtptx = time(NULL);
{
/* First, get our address */
ast_rtp_get_us(p->rtp, sin);
- if (p->vrtp)
+ if (p->vrtp) {
ast_rtp_get_us(p->vrtp, vsin);
- if (p->trtp)
+ }
+ if (p->trtp) {
ast_rtp_get_us(p->trtp, tsin);
+ }
/* Now, try to figure out where we want them to send data */
/* Is this a re-invite to move the media out, then use the original offer from caller */
struct sockaddr_in tdest = { 0, };
/* SDP fields */
- char *version = "v=0\r\n"; /* Protocol version */
- char subject[256]; /* Subject of the session */
- char owner[256]; /* Session owner/creator */
- char connection[256]; /* Connection data */
- char *session_time = "t=0 0\r\n"; /* Time the session is active */
- char bandwidth[256] = ""; /* Max bitrate */
+ char *version = "v=0\r\n"; /* Protocol version */
+ char subject[256]; /* Subject of the session */
+ char owner[256]; /* Session owner/creator */
+ char connection[256]; /* Connection data */
+ char *session_time = "t=0 0\r\n"; /* Time the session is active */
+ char bandwidth[256] = ""; /* Max bitrate */
char *hold;
struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */
struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */
/* Set RTP Session ID and version */
if (!p->sessionid) {
- p->sessionid = (int)ast_random();
+ p->sessionid = (int) ast_random();
p->sessionversion = p->sessionid;
} else {
- if (oldsdp == FALSE)
+ if (oldsdp == FALSE) {
p->sessionversion++;
+ }
}
capability = p->jointcapability;
#endif
/* Check if we need audio */
- if (capability & AST_FORMAT_AUDIO_MASK)
+ if (capability & AST_FORMAT_AUDIO_MASK) {
needaudio = TRUE;
+ }
/* Check if we need video in this call */
if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) {
if (p->vrtp) {
needvideo = TRUE;
ast_debug(2, "This call needs video offers!\n");
- } else
+ } else {
ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
+ }
}
/* Get our media addresses */
get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest);
- if (debug)
- ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
+ if (debug) {
+ ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
+ }
/* Ok, we need video. Let's add what we need for video and set codecs.
Video is handled differently than audio since we can not transcode. */
ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
/* Build max bitrate string */
- if (p->maxcallbitrate)
+ if (p->maxcallbitrate) {
snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
- if (debug)
- ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
+ }
+ if (debug) {
+ ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
+ }
}
/* Check if we need text in this call */
if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) {
- if (sipdebug_text)
+ if (sipdebug_text) {
ast_verbose("We think we can do text\n");
+ }
if (p->trtp) {
- if (sipdebug_text)
+ if (sipdebug_text) {
ast_verbose("And we have a text rtp object\n");
+ }
needtext = TRUE;
ast_debug(2, "This call needs text offers! \n");
- } else
+ } else {
ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
+ }
}
/* Ok, we need text. Let's add what we need for text and set codecs.
Text is handled differently than audio since we can not transcode. */
if (needtext) {
- if (sipdebug_text)
+ if (sipdebug_text) {
ast_verbose("Lets set up the text sdp\n");
+ }
/* Determine text destination */
if (p->tredirip.sin_addr.s_addr) {
tdest.sin_addr = p->tredirip.sin_addr;
}
ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port));
- if (debug) /* XXX should I use tdest below ? */
+ if (debug) { /* XXX should I use tdest below ? */
ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port));
-
+ }
}
/* Start building generic SDP headers */
snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) {
hold = "a=recvonly\r\n";
- else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE)
+ } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) {
hold = "a=inactive\r\n";
- else
+ } else {
hold = "a=sendrecv\r\n";
+ }
/* Now, start adding audio codecs. These are added in this order:
- First what was requested by the calling channel
for (x = 0; x < 32; x++) {
int codec;
- if (!(codec = ast_codec_pref_index(&p->prefs, x)))
- break;
-
- if (!(capability & codec))
+ if (!(codec = ast_codec_pref_index(&p->prefs, x))) {
+ break;
+ }
+ if (!(capability & codec)) {
continue;
-
- if (alreadysent & codec)
+ }
+ if (alreadysent & codec) {
continue;
+ }
add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
&m_audio, &a_audio,
/* Now send any other common audio and video codecs, and non-codec formats: */
for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) {
- if (!(capability & x)) /* Codec not requested */
+ if (!(capability & x)) { /* Codec not requested */
continue;
+ }
- if (alreadysent & x) /* Already added to SDP */
+ if (alreadysent & x) { /* Already added to SDP */
continue;
+ }
- if (x & AST_FORMAT_AUDIO_MASK)
+ if (x & AST_FORMAT_AUDIO_MASK) {
add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x),
&m_audio, &a_audio, debug, &min_audio_packet_size);
- else if (x & AST_FORMAT_VIDEO_MASK)
+ } else if (x & AST_FORMAT_VIDEO_MASK) {
add_vcodec_to_sdp(p, x, 90000,
&m_video, &a_video, debug, &min_video_packet_size);
- else if (x & AST_FORMAT_TEXT_MASK)
+ } else if (x & AST_FORMAT_TEXT_MASK) {
add_tcodec_to_sdp(p, x, 1000,
&m_text, &a_text, debug, &min_text_packet_size);
+ }
}
/* Now add DTMF RFC2833 telephony-event as a codec */
for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
- if (!(p->jointnoncodeccapability & x))
+ if (!(p->jointnoncodeccapability & x)) {
continue;
+ }
add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug);
}
ast_debug(3, "-- Done with adding codecs to SDP\n");
- if (!p->owner || !ast_internal_timing_enabled(p->owner))
+ if (!p->owner || !ast_internal_timing_enabled(p->owner)) {
ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n");
+ }
- if (min_audio_packet_size)
+ if (min_audio_packet_size) {
ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size);
+ }
/* XXX don't think you can have ptime for video */
- if (min_video_packet_size)
+ if (min_video_packet_size) {
ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size);
+ }
/* XXX don't think you can have ptime for text */
- if (min_text_packet_size)
+ if (min_text_packet_size) {
ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size);
+ }
- if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
- m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 ||
- a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2)
+ if ( ast_str_size(m_audio) - ast_str_strlen(m_audio) < 2 ||
+ ast_str_size(m_video) - ast_str_strlen(m_video) < 2 ||
+ ast_str_size(m_text) - ast_str_strlen(m_text) < 2 ||
+ ast_str_size(a_text) - ast_str_strlen(a_text) < 2 ||
+ ast_str_size(a_audio) - ast_str_strlen(a_audio) < 2 ||
+ ast_str_size(a_video) - ast_str_strlen(a_video) < 2) {
ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
+ }
- if (needaudio)
+ if (needaudio) {
ast_str_append(&m_audio, 0, "\r\n");
- if (needvideo)
+ }
+ if (needvideo) {
ast_str_append(&m_video, 0, "\r\n");
- if (needtext)
+ }
+ if (needtext) {
ast_str_append(&m_text, 0, "\r\n");
+ }
len = strlen(version) + strlen(subject) + strlen(owner) +
strlen(connection) + strlen(session_time);
- if (needaudio)
- len += m_audio->used + a_audio->used + strlen(hold);
- if (needvideo) /* only if video response is appropriate */
- len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold);
- if (needtext) /* only if text response is appropriate */
- len += m_text->used + a_text->used + strlen(hold);
+ if (needaudio) {
+ len += ast_str_strlen(m_audio) + ast_str_strlen(a_audio) + strlen(hold);
+ }
+ if (needvideo) { /* only if video response is appropriate */
+ len += ast_str_strlen(m_video) + ast_str_strlen(a_video) + strlen(bandwidth) + strlen(hold);
+ }
+ if (needtext) { /* only if text response is appropriate */
+ len += ast_str_strlen(m_text) + ast_str_strlen(a_text) + strlen(hold);
+ }
add_header(resp, "Content-Type", "application/sdp");
add_header_contentLength(resp, len);
add_line(resp, owner);
add_line(resp, subject);
add_line(resp, connection);
- if (needvideo) /* only if video response is appropriate */
+ if (needvideo) { /* only if video response is appropriate */
add_line(resp, bandwidth);
+ }
add_line(resp, session_time);
if (needaudio) {
- add_line(resp, m_audio->str);
- add_line(resp, a_audio->str);
+ add_line(resp, ast_str_buffer(m_audio));
+ add_line(resp, ast_str_buffer(a_audio));
add_line(resp, hold);
}
if (needvideo) { /* only if video response is appropriate */
- add_line(resp, m_video->str);
- add_line(resp, a_video->str);
+ add_line(resp, ast_str_buffer(m_video));
+ add_line(resp, ast_str_buffer(a_video));
add_line(resp, hold); /* Repeat hold for the video stream */
}
if (needtext) { /* only if text response is appropriate */
- add_line(resp, m_text->str);
- add_line(resp, a_text->str);
+ add_line(resp, ast_str_buffer(m_text));
+ add_line(resp, ast_str_buffer(a_text));
add_line(resp, hold); /* Repeat hold for the text stream */
}
* the place and so a memcpy is the only way to accurately copy the string
*/
- if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1)))
+ if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1)))
return;
- else if (dst->data->len < src->data->used + 1)
- ast_str_make_space(&dst->data, src->data->used + 1);
-
- memcpy(dst->data->str, src->data->str, src->data->used + 1);
- dst->data->used = src->data->used;
- offset = ((void *)dst->data->str) - ((void *)src->data->str);
+ else if (ast_str_size(dst->data) < ast_str_strlen(src->data) + 1)
+ ast_str_make_space(&dst->data, ast_str_strlen(src->data) + 1);
+
+ ast_str_set(&dst->data, 0, "%s", ast_str_buffer(src->data));
+ offset = ((void *)ast_str_buffer(dst->data)) - ((void *)ast_str_buffer(src->data));
/* Now fix pointer arithmetic */
for (x = 0; x < src->headers; x++)
dst->header[x] += offset;
/* This is the request URI, which is the next hop of the call
which may or may not be the destination of the call
*/
- ast_string_field_set(p, uri, invite->str);
+ ast_string_field_set(p, uri, ast_str_buffer(invite));
if (!ast_strlen_zero(p->todnid)) {
/*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */
/*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
{
- struct ast_str *tmp = ast_str_alloca(4000);
- char from[256], to[256];
+ struct ast_str *tmp = ast_str_thread_get(&transmit_state_buffer, 4000);
+ char from[256] = "", to[256] = "";
char *c, *mfrom, *mto;
struct sip_request req;
char hint[AST_MAX_EXTENSION];
char *pidfstate = "--";
char *pidfnote= "Ready";
- memset(from, 0, sizeof(from));
- memset(to, 0, sizeof(to));
-
switch (state) {
case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
statestring = (global_notifyringing) ? "early" : "confirmed";
break;
}
- add_header_contentLength(&req, tmp->used);
- add_line(&req, tmp->str);
+ add_header_contentLength(&req, ast_str_strlen(tmp));
+ add_line(&req, ast_str_buffer(tmp));
p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
add_header(&req, "Subscription-State", "terminated;reason=timeout");
}
- add_header_contentLength(&req, out->used);
- add_line(&req, out->str);
+ add_header_contentLength(&req, ast_str_strlen(out));
+ add_line(&req, ast_str_buffer(out));
if (!p->initreq.headers)
initialize_initreq(p, &req);
if (res == AST_DYNSTR_BUILD_FAILED)
return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */
- c = buf->str;
+ c = ast_str_buffer(buf);
while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */
for (i = keys; i->key != NULL; i++) {
}
/*! \brief list peer mailboxes to CLI */
-static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer)
+static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer)
{
struct sip_mailbox *mailbox;
S_OR(mailbox->context, ""),
AST_LIST_NEXT(mailbox, entry) ? "," : "");
}
+ return ast_str_buffer(*mailbox_str);
}
/*! \brief Show one peer in detail (main function) */
}
}
if (peer && type==0 ) { /* Normal listing */
- struct ast_str *mailbox_str = ast_str_alloca(512);
+ struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
ast_cli(fd, "\n\n");
ast_cli(fd, " * Name : %s\n", peer->name);
if (realtimepeers) { /* Realtime is enabled */
print_group(fd, peer->callgroup, 0);
ast_cli(fd, " Pickupgroup : ");
print_group(fd, peer->pickupgroup, 0);
- peer_mailboxes_to_str(&mailbox_str, peer);
- ast_cli(fd, " Mailbox : %s\n", mailbox_str->str);
+ ast_cli(fd, " Mailbox : %s\n", peer_mailboxes_to_str(&mailbox_str, peer));
ast_cli(fd, " VM Extension : %s\n", peer->vmexten);
ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
ast_cli(fd, " Call limit : %d\n", peer->call_limit);
peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr");
} else if (peer && type == 1) { /* manager listing */
char buffer[256];
- struct ast_str *mailbox_str = ast_str_alloca(512);
+ struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
astman_append(s, "Channeltype: SIP\r\n");
astman_append(s, "ObjectName: %s\r\n", peer->name);
astman_append(s, "ChanObjectType: peer\r\n");
astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup));
astman_append(s, "Pickupgroup: ");
astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup));
- peer_mailboxes_to_str(&mailbox_str, peer);
- astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str);
+ astman_append(s, "VoiceMailbox: %s\r\n", peer_mailboxes_to_str(&mailbox_str, peer));
astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
astman_append(s, "Call-limit: %d\r\n", peer->call_limit);
arg->numchans++;
}
if (cur->subscribed != NONE && arg->subscriptions) {
- struct ast_str *mailbox_str = ast_str_alloca(512);
+ struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr),
cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate),
subscription_type2str(cur->subscribed),
- cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>",
+ cur->subscribed == MWI_NOTIFICATION ? AS_OR(mailbox_str, "<none>") : "<none>",
cur->expiry
);
arg->numchans++;
} else if (!strcasecmp(colname, "useragent")) {
ast_copy_string(buf, peer->useragent, len);
} else if (!strcasecmp(colname, "mailbox")) {
- struct ast_str *mailbox_str = ast_str_alloca(512);
- peer_mailboxes_to_str(&mailbox_str, peer);
- ast_copy_string(buf, mailbox_str->str, len);
+ struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
+ ast_copy_string(buf, peer_mailboxes_to_str(&mailbox_str, peer), len);
} else if (!strcasecmp(colname, "context")) {
ast_copy_string(buf, peer->context, len);
} else if (!strcasecmp(colname, "expire")) {
ast_str_set(&str, 0, "%s@%s", extension, context);
- ast_debug(2, "About to call Pickup(%s)\n", str->str);
+ ast_debug(2, "About to call Pickup(%s)\n", ast_str_buffer(str));
/* There is no point in capturing the return value since pickup_exec
doesn't return anything meaningful unless the passed data is an empty
string (which in our case it will not be) */
- pbx_exec(channel, pickup, str->str);
+ pbx_exec(channel, pickup, ast_str_buffer(str));
return 0;
}
return 1;
}
- if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) {
+ if (ast_str_set(&req.data, -1, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) {
return -1;
}
if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */
req->debug = 1;
if (sip_cfg.pedanticsipchecking)
- req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */
+ req->len = lws2sws(ast_str_buffer(req->data), req->len); /* Fix multiline headers */
if (req->debug) {
ast_verbose("\n<--- SIP read from %s:%s:%d --->\n%s\n<------------->\n",
get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr),
- ntohs(sin->sin_port), req->data->str);
+ ntohs(sin->sin_port), ast_str_buffer(req->data));
}
if(parse_request(req) == -1) { /* Bad packet, can't parse */
p->recv = *sin;
if (p->do_history) /* This is a request or response, note what it was for */
- append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), req->rlPart2);
+ append_history(p, "Rx", "%s / %s / %s", ast_str_buffer(req->data), get_header(req, "CSeq"), req->rlPart2);
if (!lockretry) {
if (p->owner)
} else if (cache_only) {
return 0;
} else { /* Fall back to manually checking the mailbox */
- struct ast_str *mailbox_str = ast_str_alloca(512);
- peer_mailboxes_to_str(&mailbox_str, peer);
- ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs);
+ struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
+ ast_app_inboxcount(peer_mailboxes_to_str(&mailbox_str, peer), &newmsgs, &oldmsgs);
}
if (peer->mwipvt) {
ast_copy_string(peer->name, v->value, sizeof(peer->name));
else if (realtime && !strcasecmp(v->name, "fullcontact")) {
/* Reconstruct field, because realtime separates our value at the ';' */
- if (fullcontact->used > 0) {
+ if (ast_str_strlen(fullcontact) > 0) {
ast_str_append(&fullcontact, 0, ";%s", v->value);
} else {
ast_str_set(&fullcontact, 0, "%s", v->value);
peer->socket.type = default_primary_transport;
}
- if (fullcontact->used > 0) {
- ast_string_field_set(peer, fullcontact, fullcontact->str);
+ if (ast_str_strlen(fullcontact) > 0) {
+ ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
peer->rt_fromcontact = TRUE;
/* We have a hostname in the fullcontact, but if we don't have an
* address listed on the entry (or if it's 'dynamic'), then we need to
* register once again). */
/* XXX May need to revisit the final argument; does the realtime DB store whether
* the original contact was over TLS or not? XXX */
- __set_address_from_contact(fullcontact->str, &peer->addr, 0);
+ __set_address_from_contact(ast_str_buffer(fullcontact), &peer->addr, 0);
}
if (srvlookup && peer->dnsmgr == NULL) {
for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
if (strcmp(tmp, var2->name) == 0) {
ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
- var = ast_variable_new(tmp, str->str, var2->file);
+ var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
var->next = var2->next;
if (prev) {
prev->next = var;
#! /bin/sh
-# From configure.ac Revision: 160097 .
+# From configure.ac Revision: 163168 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for asterisk 1.6.
#
register int realsize = size * nmemb;
struct ast_str **pstr = (struct ast_str **)data;
- ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, (*pstr)->len, (*pstr)->used);
+ ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, ast_str_size(*pstr), ast_str_strlen(*pstr));
- if (ast_str_make_space(pstr, (((*pstr)->used + realsize + 1) / 512 + 1) * 512 + 230) == 0) {
- memcpy(&((*pstr)->str[(*pstr)->used]), ptr, realsize);
- (*pstr)->used += realsize;
- }
+ ast_str_append_substr(pstr, 0, ptr, realsize);
- ast_debug(3, "Now, len=%zu, used=%zu\n", (*pstr)->len, (*pstr)->used);
+ ast_debug(3, "Now, len=%zu, used=%zu\n", ast_str_size(*pstr), ast_str_strlen(*pstr));
return realsize;
}
curl_easy_setopt(*curl, CURLOPT_POST, 0);
}
- if (str->used) {
- str->str[str->used] = '\0';
- if (str->str[str->used - 1] == '\n') {
- str->str[str->used - 1] = '\0';
- }
+ if (ast_str_strlen(str)) {
+ ast_str_trim_blanks(str);
- ast_log(LOG_NOTICE, "str='%s'\n", str->str);
+ ast_debug(3, "str='%s'\n", ast_str_buffer(str));
if (hashcompat) {
- char *remainder = str->str;
+ char *remainder = ast_str_buffer(str);
char *piece;
- struct ast_str *fields = ast_str_create(str->used / 2);
- struct ast_str *values = ast_str_create(str->used / 2);
+ struct ast_str *fields = ast_str_create(ast_str_strlen(str) / 2);
+ struct ast_str *values = ast_str_create(ast_str_strlen(str) / 2);
int rowcount = 0;
while ((piece = strsep(&remainder, "&"))) {
char *name = strsep(&piece, "=");
ast_str_append(&values, 0, "%s%s", rowcount ? "," : "", piece);
rowcount++;
}
- pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", fields->str);
- ast_copy_string(buf, values->str, len);
+ pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
+ ast_copy_string(buf, ast_str_buffer(values), len);
ast_free(fields);
ast_free(values);
} else {
- ast_copy_string(buf, str->str, len);
+ ast_copy_string(buf, ast_str_buffer(str), len);
}
ret = 0;
}
<use>iodbc</use>
***/
+#define USE_ODBC
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/res_odbc.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
+#include "asterisk/strings.h"
/*** DOCUMENTATION
<function name="ODBC_FETCH" language="en_US">
/* Additionally set the value as a whole (but push an empty string if value is NULL) */
pbx_builtin_pushvar_helper(chan, "VALUE", value ? value : "");
- pbx_substitute_variables_helper(chan, query->sql_write, buf->str, buf->len - 1);
- pbx_substitute_variables_helper(chan, query->sql_insert, insertbuf->str, insertbuf->len - 1);
+ ast_str_substitute_variables(&buf, 0, chan, query->sql_write);
+ ast_str_substitute_variables(&insertbuf, 0, chan, query->sql_insert);
/* Restore prior values */
for (i = 0; i < args.argc; i++) {
if (!ast_strlen_zero(query->writehandle[dsn])) {
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
if (obj)
- stmt = ast_odbc_direct_execute(obj, generic_execute, buf->str);
+ stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf));
}
if (stmt) {
status = "SUCCESS";
}
}
- if (stmt && rows == 0 && !ast_strlen_zero(insertbuf->str)) {
+ if (stmt && rows == 0 && ast_str_strlen(insertbuf) != 0) {
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
for (dsn = 0; dsn < 5; dsn++) {
if (!ast_strlen_zero(query->writehandle[dsn])) {
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
if (obj) {
- stmt = ast_odbc_direct_execute(obj, generic_execute, insertbuf->str);
+ stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(insertbuf));
}
}
if (stmt) {
pbx_builtin_pushvar_helper(chan, varname, args.field[x]);
}
- ast_str_make_space(&sql, strlen(query->sql_read) * 2 + 300);
- pbx_substitute_variables_helper(chan, query->sql_read, sql->str, sql->len - 1);
+ ast_str_substitute_variables(&sql, 0, chan, query->sql_read);
/* Restore prior values */
for (x = 0; x < args.argc; x++) {
if (!ast_strlen_zero(query->readhandle[dsn])) {
obj = ast_odbc_request_obj(query->readhandle[dsn], 0);
if (obj) {
- stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str);
+ stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql));
}
}
if (stmt) {
}
if (!stmt) {
- ast_log(LOG_ERROR, "Unable to execute query [%s]\n", sql->str);
+ ast_log(LOG_ERROR, "Unable to execute query [%s]\n", ast_str_buffer(sql));
if (obj) {
ast_odbc_release_obj(obj);
}
res = SQLNumResultCols(stmt, &colcount);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql->str);
+ ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", ast_str_buffer(sql));
SQLCloseCursor(stmt);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
int res1 = -1;
if (res == SQL_NO_DATA) {
- ast_verb(4, "Found no rows [%s]\n", sql->str);
+ ast_verb(4, "Found no rows [%s]\n", ast_str_buffer(sql));
res1 = 0;
buf[0] = '\0';
ast_copy_string(rowcount, "0", sizeof(rowcount));
status = "NODATA";
} else {
- ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql->str);
+ ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql));
status = "FETCHERROR";
}
SQLCloseCursor(stmt);
for (x = 0; x < colcount; x++) {
int i;
struct ast_str *coldata = ast_str_thread_get(&coldata_buf, 16);
+ char *ptrcoldata;
if (y == 0) {
char colname[256];
snprintf(colname, sizeof(colname), "field%d", x);
}
- if (coldata->len < maxcol + 1) {
- ast_str_make_space(&coldata, maxcol + 1);
- }
+ ast_str_make_space(&coldata, maxcol + 1);
- if (colnames->used) {
+ if (ast_str_strlen(colnames)) {
ast_str_append(&colnames, 0, ",");
}
- ast_str_make_space(&colnames, strlen(colname) * 2 + 1 + colnames->used);
-
- /* Copy data, encoding '\' and ',' for the argument parser */
- for (i = 0; i < sizeof(colname); i++) {
- if (escapecommas && (colname[i] == '\\' || colname[i] == ',')) {
- colnames->str[colnames->used++] = '\\';
- }
- colnames->str[colnames->used++] = colname[i];
-
- if (colname[i] == '\0') {
- colnames->used--;
- break;
- }
- }
+ ast_str_append_escapecommas(&colnames, 0, colname, sizeof(colname));
if (resultset) {
- void *tmp = ast_realloc(resultset, sizeof(*resultset) + colnames->used + 1);
+ void *tmp = ast_realloc(resultset, sizeof(*resultset) + ast_str_strlen(colnames) + 1);
if (!tmp) {
ast_log(LOG_ERROR, "No space for a new resultset?\n");
ast_free(resultset);
return -1;
}
resultset = tmp;
- strcpy((char *)resultset + sizeof(*resultset), colnames->str);
+ strcpy((char *)resultset + sizeof(*resultset), ast_str_buffer(colnames));
}
}
buflen = strlen(buf);
- res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata->str, coldata->len, &indicator);
+ res = ast_str_SQLGetData(&coldata, -1, stmt, x + 1, SQL_CHAR, &indicator);
if (indicator == SQL_NULL_DATA) {
ast_debug(3, "Got NULL data\n");
ast_str_reset(coldata);
}
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql->str);
+ ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", ast_str_buffer(sql));
y = -1;
buf[0] = '\0';
goto end_acf_read;
}
- ast_debug(2, "Got coldata of '%s'\n", coldata->str);
- coldata->used = strlen(coldata->str);
+ ast_debug(2, "Got coldata of '%s'\n", ast_str_buffer(coldata));
+
+ if (buflen) {
+ buf[buflen++] = ',';
+ }
/* Copy data, encoding '\' and ',' for the argument parser */
- for (i = 0; i < coldata->used; i++) {
- if (escapecommas && (coldata->str[i] == '\\' || coldata->str[i] == ',')) {
+ ptrcoldata = ast_str_buffer(coldata);
+ for (i = 0; i < ast_str_strlen(coldata); i++) {
+ if (escapecommas && (ptrcoldata[i] == '\\' || ptrcoldata[i] == ',')) {
buf[buflen++] = '\\';
}
- buf[buflen++] = coldata->str[i];
+ buf[buflen++] = ptrcoldata[i];
- if (buflen >= len - 2)
+ if (buflen >= len - 2) {
break;
+ }
- if (coldata->str[i] == '\0')
+ if (ptrcoldata[i] == '\0') {
break;
+ }
}
- buf[buflen++] = ',';
buf[buflen] = '\0';
ast_debug(2, "buf is now set to '%s'\n", buf);
}
- /* Trim trailing comma */
- buf[buflen - 1] = '\0';
ast_debug(2, "buf is now set to '%s'\n", buf);
if (resultset) {
- row = ast_calloc(1, sizeof(*row) + buflen);
+ row = ast_calloc(1, sizeof(*row) + buflen + 1);
if (!row) {
ast_log(LOG_ERROR, "Unable to allocate space for more rows in this resultset.\n");
status = "MEMERROR";
/* Get next row */
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- if (res != SQL_NO_DATA)
- ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql->str);
+ if (res != SQL_NO_DATA) {
+ ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql));
+ }
+ /* Number of rows in the resultset */
y++;
break;
}
snprintf(rowcount, sizeof(rowcount), "%d", y);
pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount);
pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status);
- pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames->str);
+ pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(colnames));
if (resultset) {
int uid;
struct ast_datastore *odbc_store;
pbx_builtin_pushvar_helper(chan, varname, args.field[i]);
}
- /*!\note This does not set sql->used, so don't try to use that value. */
- pbx_substitute_variables_helper(chan, query->sql_read, sql->str, sql->len - 1);
+ ast_str_substitute_variables(&sql, 0, chan, query->sql_read);
ast_channel_free(chan);
if (a->argc == 5 && !strcmp(a->argv[4], "exec")) {
}
ast_debug(1, "Got obj\n");
- if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str))) {
+ if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql)))) {
ast_odbc_release_obj(obj);
continue;
}
res = SQLNumResultCols(stmt, &colcount);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_cli(a->fd, "SQL Column Count error!\n[%s]\n\n", sql->str);
+ ast_cli(a->fd, "SQL Column Count error!\n[%s]\n\n", ast_str_buffer(sql));
SQLCloseCursor(stmt);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
if (res == SQL_NO_DATA) {
- ast_cli(a->fd, "Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn, query->readhandle[dsn], sql->str);
+ ast_cli(a->fd, "Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn, query->readhandle[dsn], ast_str_buffer(sql));
break;
} else {
- ast_cli(a->fd, "Error %d in FETCH [%s]\n", res, sql->str);
+ ast_cli(a->fd, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql));
}
AST_RWLIST_UNLOCK(&queries);
return CLI_SUCCESS;
snprintf(colname, sizeof(colname), "field%d", x);
}
- if (coldata->len < maxcol + 1) {
- ast_str_make_space(&coldata, maxcol + 1);
- }
-
- res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata->str, coldata->len, &indicator);
+ res = ast_str_SQLGetData(&coldata, maxcol, stmt, x + 1, SQL_CHAR, &indicator);
if (indicator == SQL_NULL_DATA) {
ast_str_set(&coldata, 0, "(nil)");
res = SQL_SUCCESS;
}
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_cli(a->fd, "SQL Get Data error %d!\n[%s]\n\n", res, sql->str);
+ ast_cli(a->fd, "SQL Get Data error %d!\n[%s]\n\n", res, ast_str_buffer(sql));
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
return CLI_SUCCESS;
}
- ast_cli(a->fd, "%-20.20s %s\n", colname, coldata->str);
+ ast_cli(a->fd, "%-20.20s %s\n", colname, ast_str_buffer(coldata));
}
/* Get next row */
res = SQLFetch(stmt);
ast_odbc_release_obj(obj);
if (!executed) {
- ast_cli(a->fd, "Failed to execute query. [%s]\n", sql->str);
+ ast_cli(a->fd, "Failed to execute query. [%s]\n", ast_str_buffer(sql));
}
} else { /* No execution, just print out the resulting SQL */
- ast_cli(a->fd, "%s\n", sql->str);
+ ast_cli(a->fd, "%s\n", ast_str_buffer(sql));
}
AST_RWLIST_UNLOCK(&queries);
return CLI_SUCCESS;
/* Additionally set the value as a whole (but push an empty string if value is NULL) */
pbx_builtin_pushvar_helper(chan, "VALUE", S_OR(a->argv[4], ""));
- pbx_substitute_variables_helper(chan, query->sql_write, sql->str, sql->len - 1);
- ast_debug(1, "SQL is %s\n", sql->str);
+ ast_str_substitute_variables(&sql, 0, chan, query->sql_write);
+ ast_debug(1, "SQL is %s\n", ast_str_buffer(sql));
ast_channel_free(chan);
if (a->argc == 6 && !strcmp(a->argv[5], "exec")) {
if (!(obj = ast_odbc_request_obj(query->writehandle[dsn], 0))) {
continue;
}
- if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str))) {
+ if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql)))) {
ast_odbc_release_obj(obj);
continue;
}
ast_cli(a->fd, "Failed to execute query.\n");
}
} else { /* No execution, just print out the resulting SQL */
- ast_cli(a->fd, "%s\n", sql->str);
+ ast_cli(a->fd, "%s\n", ast_str_buffer(sql));
}
AST_RWLIST_UNLOCK(&queries);
return CLI_SUCCESS;
AST_THREADSTORAGE(buf2);
AST_THREADSTORAGE(buf3);
-static char *hash_escape(struct ast_str **str, const char *value)
-{
- int len;
- ast_str_reset(*str);
-
- if ((*str)->len < (len = strlen(value) * 2 + 1)) {
- ast_str_make_space(str, len);
- }
- for (; *value; value++) {
- if (*value == ',' || *value == '\\') {
- (*str)->str[(*str)->used++] = '\\';
- }
- (*str)->str[(*str)->used++] = *value;
- }
- (*str)->str[(*str)->used] = '\0';
- return (*str)->str;
-}
-
static int function_realtime_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_variable *var, *head;
out = ast_str_alloca(resultslen);
for (var = head; var; var = var->next)
ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
- ast_copy_string(buf, out->str, len);
+ ast_copy_string(buf, ast_str_buffer(out), len);
if (chan)
ast_autoservice_stop(chan);
}
} else if (which == rthash) {
ast_debug(1, "Setting hash key %s to value %s\n", var->name, var->value);
- ast_str_append(&fields, 0, "%s%s", first ? "" : ",", hash_escape(&escapebuf, var->name));
- ast_str_append(&values, 0, "%s%s", first ? "" : ",", hash_escape(&escapebuf, var->value));
+ ast_str_append(&fields, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->name, INT_MAX));
+ ast_str_append(&values, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->value, INT_MAX));
first = 0;
}
}
ast_variables_destroy(head);
if (which == rthash) {
- pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", fields->str);
- ast_copy_string(buf, values->str, len);
+ pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
+ ast_copy_string(buf, ast_str_buffer(values), len);
}
if (chan) {
for (var = head; var; var = var->next) {
ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
}
- ast_copy_string(buf, out->str, len);
+ ast_copy_string(buf, ast_str_buffer(out), len);
ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL);
);
const char *orig_list, *ptr;
const char *begin, *cur, *next;
- int dlen, flen;
+ int dlen, flen, first = 1;
struct ast_str *result = ast_str_thread_get(&result_buf, 16);
char *delim;
begin += flen + dlen;
} else {
/* Copy field to output */
- if (result->used) {
+ if (!first) {
ast_str_append(&result, 0, "%s", delim);
}
- /* Have to do it this way, since we're not null-terminated. */
- strncpy(result->str + result->used, begin, cur - begin);
- result->used += cur - begin;
- result->str[result->used] = '\0';
-
+ ast_str_append_substr(&result, 0, begin, cur - begin + 1);
+ first = 0;
begin = cur + dlen;
}
} while (*cur != '\0');
ast_channel_unlock(chan);
}
- ast_copy_string(buf, result->str, len);
+ ast_copy_string(buf, ast_str_buffer(result), len);
return 0;
}
#ifndef _ASTERISK_APP_H
#define _ASTERISK_APP_H
+#include "asterisk/strings.h"
+#include "asterisk/threadstorage.h"
+
struct ast_flags64;
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
+AST_THREADSTORAGE_EXTERNAL(global_app_buf);
+
/* IVR stuff */
/*! \brief Callback function for IVR
* Changes the value of the last executed app
* Returns nothing
*/
-void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data);
+void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data);
/*!
* \brief Convert a string to a detail record AMA flag
};
struct ast_timing {
- int hastime; /*!< If time construct exists */
- unsigned int monthmask; /*!< Mask for month */
- unsigned int daymask; /*!< Mask for date */
- unsigned int dowmask; /*!< Mask for day of week (mon-sun) */
- unsigned int minmask[24]; /*!< Mask for minute */
+ int hastime; /*!< If time construct exists */
+ unsigned int monthmask; /*!< Mask for month */
+ unsigned int daymask; /*!< Mask for date */
+ unsigned int dowmask; /*!< Mask for day of week (sun-sat) */
+ unsigned int minmask[48]; /*!< Mask for minute */
};
int ast_build_timing(struct ast_timing *i, const char *info);
void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ);
int ast_extension_patmatch(const char *pattern, const char *data);
#ifndef _ASTERISK_STRINGS_H
#define _ASTERISK_STRINGS_H
+#define DEBUG_OPAQUE
+
#include <ctype.h>
-#include "asterisk/inline_api.h"
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
/* You may see casts in this header that may seem useless but they ensure this file is C++ clean */
+#define AS_OR(a,b) ast_str_strlen(a) ? ast_str_buffer(a) : (b)
+
#ifdef AST_DEVMODE
#define ast_strlen_zero(foo) _ast_strlen_zero(foo, __FILE__, __PRETTY_FUNCTION__, __LINE__)
static force_inline int _ast_strlen_zero(const char *s, const char *file, const char *function, int line)
}
)
-
/*!
\brief Build a string in a buffer, designed to be called repeatedly
* struct ast_threadstorage pointer.
*/
struct ast_str {
+#ifdef DEBUG_OPAQUE
+ size_t len2;
+ size_t used2;
+ struct ast_threadstorage *ts2;
+#else
size_t len; /*!< The current maximum length of the string */
size_t used; /*!< Amount of space used */
struct ast_threadstorage *ts; /*!< What kind of storage is this ? */
+#endif
#define DS_MALLOC ((struct ast_threadstorage *)1)
#define DS_ALLOCA ((struct ast_threadstorage *)2)
#define DS_STATIC ((struct ast_threadstorage *)3) /* not supported yet */
+#ifdef DEBUG_OPAQUE
+ char str2[0];
+#else
char str[0]; /*!< The string buffer */
+#endif
};
/*!
buf = (struct ast_str *)ast_calloc(1, sizeof(*buf) + init_len);
if (buf == NULL)
return NULL;
-
+
+#ifdef DEBUG_OPAQUE
+ buf->len2 = init_len;
+ buf->used2 = 0;
+ buf->ts2 = DS_MALLOC;
+#else
buf->len = init_len;
buf->used = 0;
buf->ts = DS_MALLOC;
+#endif
return buf;
}
void ast_str_reset(struct ast_str *buf),
{
if (buf) {
+#ifdef DEBUG_OPAQUE
+ buf->used2 = 0;
+ if (buf->len2)
+ buf->str2[0] = '\0';
+#else
buf->used = 0;
if (buf->len)
buf->str[0] = '\0';
+#endif
}
}
)
if (!buf) {
return;
}
+#ifdef DEBUG_OPAQUE
+ while (buf->used2 && buf->str2[buf->used2 - 1] < 33) {
+ buf->str2[--(buf->used2)] = '\0';
+ }
+#else
while (buf->used && buf->str[buf->used - 1] < 33) {
buf->str[--(buf->used)] = '\0';
}
+#endif
+}
+)
+
+/*!\brief Returns the current length of the string stored within buf.
+ * \param A pointer to the ast_str string.
+ */
+AST_INLINE_API(
+size_t ast_str_strlen(struct ast_str *buf),
+{
+#ifdef DEBUG_OPAQUE
+ return buf->used2;
+#else
+ return buf->used;
+#endif
+}
+)
+
+/*!\brief Returns the current maximum length (without reallocation) of the current buffer.
+ * \param A pointer to the ast_str string.
+ */
+AST_INLINE_API(
+size_t ast_str_size(struct ast_str *buf),
+{
+#ifdef DEBUG_OPAQUE
+ return buf->len2;
+#else
+ return buf->len;
+#endif
}
)
+/*!\brief Returns the string buffer within the ast_str buf.
+ * \param A pointer to the ast_str string.
+ */
+AST_INLINE_API(
+attribute_pure char *ast_str_buffer(struct ast_str *buf),
+{
+#ifdef DEBUG_OPAQUE
+ return buf->str2;
+#else
+ return buf->str;
+#endif
+}
+)
+
+AST_INLINE_API(
+char *ast_str_truncate(struct ast_str *buf, size_t len),
+{
+#ifdef DEBUG_OPAQUE
+ if (len < 0) {
+ buf->used2 += len;
+ } else {
+ buf->used2 = len;
+ }
+ buf->str2[buf->used2] = '\0';
+ return buf->str2;
+#else
+ if (len < 0) {
+ buf->used += len;
+ } else {
+ buf->used = len;
+ }
+ buf->str[buf->used] = '\0';
+ return buf->str;
+#endif
+}
+)
+
/*
* AST_INLINE_API() is a macro that takes a block of code as an argument.
* Using preprocessor #directives in the argument is not supported by all
{
struct ast_str *old_buf = *buf;
+#ifdef DEBUG_OPAQUE
+ if (new_len <= (*buf)->len2)
+ return 0; /* success */
+ if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC)
+ return -1; /* cannot extend */
+ *buf = (struct ast_str *)__ast_realloc(*buf, new_len + sizeof(struct ast_str), file, lineno, function);
+ if (*buf == NULL) {
+ *buf = old_buf;
+ return -1;
+ }
+ if ((*buf)->ts2 != DS_MALLOC) {
+ pthread_setspecific((*buf)->ts2->key, *buf);
+ _DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));)
+ }
+
+ (*buf)->len2 = new_len;
+#else
if (new_len <= (*buf)->len)
return 0; /* success */
if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC)
}
(*buf)->len = new_len;
+#endif
return 0;
}
)
{
struct ast_str *old_buf = *buf;
+#ifdef DEBUG_OPAQUE
+ if (new_len <= (*buf)->len2)
+ return 0; /* success */
+ if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC)
+ return -1; /* cannot extend */
+ *buf = (struct ast_str *)ast_realloc(*buf, new_len + sizeof(struct ast_str));
+ if (*buf == NULL) {
+ *buf = old_buf;
+ return -1;
+ }
+ if ((*buf)->ts2 != DS_MALLOC) {
+ pthread_setspecific((*buf)->ts2->key, *buf);
+ _DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));)
+ }
+
+ (*buf)->len2 = new_len;
+#else
if (new_len <= (*buf)->len)
return 0; /* success */
if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC)
}
(*buf)->len = new_len;
+#endif
return 0;
}
)
#endif
+#ifdef DEBUG_OPAQUE
+#define ast_str_alloca(init_len) \
+ ({ \
+ struct ast_str *__ast_str_buf; \
+ __ast_str_buf = alloca(sizeof(*__ast_str_buf) + init_len); \
+ __ast_str_buf->len2 = init_len; \
+ __ast_str_buf->used2 = 0; \
+ __ast_str_buf->ts2 = DS_ALLOCA; \
+ __ast_str_buf->str2[0] = '\0'; \
+ (__ast_str_buf); \
+ })
+#else
#define ast_str_alloca(init_len) \
({ \
struct ast_str *__ast_str_buf; \
__ast_str_buf->str[0] = '\0'; \
(__ast_str_buf); \
})
+#endif
/*!
* \brief Retrieve a thread locally stored dynamic string
buf = (struct ast_str *)ast_threadstorage_get(ts, sizeof(*buf) + init_len);
if (buf == NULL)
return NULL;
-
+
+#ifdef DEBUG_OPAQUE
+ if (!buf->len2) {
+ buf->len2 = init_len;
+ buf->used2 = 0;
+ buf->ts2 = ts;
+ }
+#else
if (!buf->len) {
buf->len = init_len;
buf->used = 0;
buf->ts = ts;
}
+#endif
return buf;
}
buf = (struct ast_str *)__ast_threadstorage_get(ts, sizeof(*buf) + init_len, file, function, line);
if (buf == NULL)
return NULL;
-
+
+#ifdef DEBUG_OPAQUE
+ if (!buf->len2) {
+ buf->len2 = init_len;
+ buf->used2 = 0;
+ buf->ts2 = ts;
+ }
+#else
if (!buf->len) {
buf->len = init_len;
buf->used = 0;
buf->ts = ts;
}
+#endif
return buf;
}
*/
int __attribute__((format(printf, 4, 0))) __ast_str_helper(struct ast_str **buf, size_t max_len,
int append, const char *fmt, va_list ap);
+char *__ast_str_helper2(struct ast_str **buf, size_t max_len,
+ const char *src, size_t maxsrc, int append, int escapecommas);
/*!
* \brief Set a dynamic string from a va_list
}
)
+/*!\brief Set a dynamic string to a non-NULL terminated substring. */
+AST_INLINE_API(char *ast_str_set_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
+{
+ return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 0);
+}
+)
+
+/*!\brief Append a non-NULL terminated substring to the end of a dynamic string. */
+AST_INLINE_API(char *ast_str_append_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
+{
+ return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 0);
+}
+)
+
+/*!\brief Set a dynamic string to a non-NULL terminated substring, with escaping of commas. */
+AST_INLINE_API(char *ast_str_set_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
+{
+ return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 1);
+}
+)
+
+/*!\brief Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas. */
+AST_INLINE_API(char *ast_str_append_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
+{
+ return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 1);
+}
+)
+
+/*!\brief Wrapper for SQLGetData to use with dynamic strings
+ * \param buf Address of the pointer to the ast_str structure.
+ * \param maxlen The maximum size of the resulting string, or 0 for no limit.
+ * \param StatementHandle The statement handle from which to retrieve data.
+ * \param ColumnNumber Column number (1-based offset) for which to retrieve data.
+ * \param TargetType The SQL constant indicating what kind of data is to be retrieved (usually SQL_CHAR)
+ * \param StrLen_or_Ind A pointer to a length indicator, specifying the total length of data.
+ */
+#ifdef USE_ODBC
+#include <sql.h>
+#include <sqlext.h>
+#include <sqltypes.h>
+
+AST_INLINE_API(SQLRETURN ast_str_SQLGetData(struct ast_str **buf, size_t maxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind),
+{
+ SQLRETURN res;
+ if (maxlen == 0) {
+#ifdef DEBUG_OPAQUE
+ if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
+ ast_str_make_space(buf, *StrLen_or_Ind + 1);
+ }
+ maxlen = (*buf)->len2;
+ } else if (maxlen > 0) {
+ ast_str_make_space(buf, maxlen);
+ }
+ res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, maxlen, StrLen_or_Ind);
+ (*buf)->used2 = *StrLen_or_Ind;
+#else
+ if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
+ ast_str_make_space(buf, *StrLen_or_Ind + 1);
+ }
+ maxlen = (*buf)->len;
+ } else if (maxlen > 0) {
+ ast_str_make_space(buf, maxlen);
+ }
+ res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, maxlen, StrLen_or_Ind);
+ (*buf)->used = *StrLen_or_Ind;
+#endif
+ return res;
+}
+)
+#endif /* defined(USE_ODBC) */
+
+
/*!
* \brief Set a dynamic string using variable arguments
*
int ast_ssl_setup(struct ast_tls_config *cfg);
HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *ser, void *buf, size_t count);
-HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, void *buf, size_t count);
+HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, const void *buf, size_t count);
#endif /* _ASTERISK_TCPTLS_H */
* \endcode
*/
#define AST_THREADSTORAGE(name) \
- AST_THREADSTORAGE_CUSTOM(name, NULL, ast_free_ptr)
+ AST_THREADSTORAGE_CUSTOM_SCOPE(name, NULL, ast_free_ptr, static)
+#define AST_THREADSTORAGE_PUBLIC(name) \
+ AST_THREADSTORAGE_CUSTOM_SCOPE(name, NULL, ast_free_ptr,)
+#define AST_THREADSTORAGE_EXTERNAL(name) \
+ extern struct ast_threadstorage name
/*!
* \brief Define a thread storage variable, with custom initialization and cleanup
* AST_THREADSTORAGE_CUSTOM(my_buf, my_init, my_cleanup);
* \endcode
*/
+#define AST_THREADSTORAGE_CUSTOM(a,b,c) AST_THREADSTORAGE_CUSTOM_SCOPE(a,b,c,static)
+
#if !defined(DEBUG_THREADLOCALS)
-#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \
+#define AST_THREADSTORAGE_CUSTOM_SCOPE(name, c_init, c_cleanup, scope) \
static void __init_##name(void); \
-static struct ast_threadstorage name = { \
+scope struct ast_threadstorage name = { \
.once = THREADSTORAGE_ONCE_INIT, \
.key_init = __init_##name, \
.custom_init = c_init, \
pthread_key_create(&(name).key, c_cleanup); \
}
#else /* defined(DEBUG_THREADLOCALS) */
-#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \
+#define AST_THREADSTORAGE_CUSTOM_SCOPE(name, c_init, c_cleanup, scope) \
static void __init_##name(void); \
-static struct ast_threadstorage name = { \
+scope struct ast_threadstorage name = { \
.once = THREADSTORAGE_ONCE_INIT, \
.key_init = __init_##name, \
.custom_init = c_init, \
cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
astobj2.o hashtab.o global_datastores.o version.o \
- features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o
+ features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \
+ strings.o
# we need to link in the objects statically, not as a library, because
# otherwise modules will not have them available if none of the static
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/threadstorage.h"
+
+AST_THREADSTORAGE_PUBLIC(global_app_buf);
+
#define MAX_OTHER_FORMATS 10
if (prompt == NULL) {
prompt = ast_str_create(100);
} else if (!cli_prompt_changes) {
- return prompt->str;
+ return ast_str_buffer(prompt);
} else {
ast_str_reset(prompt);
}
}
t++;
} else {
- if (prompt->used + 5 > prompt->len) {
- ast_str_make_space(&prompt, prompt->len + 5);
- }
- prompt->str[prompt->used++] = *t++;
- prompt->str[prompt->used] = '\0';
+ ast_str_append(&prompt, 0, "%c", *t);
}
}
if (color_used) {
ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
}
- return(prompt->str);
+ return ast_str_buffer(prompt);
}
static char **ast_el_strtoarr(char *buf)
char workspace[256];
int total = 0, x = 0, i;
- (*buf)->used = 0;
- (*buf)->str[0] = '\0';
+ ast_str_reset(*buf);
for (; cdr; cdr = recur ? cdr->next : NULL) {
if (++x > 1)
}
}
-void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
+void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data)
{
for (; cdr; cdr = cdr->next) {
res = ast_str_set_va(&buf, 0, fmt, ap);
va_end(ap);
- if (res != AST_DYNSTR_BUILD_FAILED)
- ast_carefulwrite(fd, buf->str, strlen(buf->str), 100);
+ if (res != AST_DYNSTR_BUILD_FAILED) {
+ ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
+ }
}
unsigned int ast_debug_get_by_file(const char *file)
ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
}
x = timeval.tv_sec;
- if (x > 0 || out->used == 0) /* if there is nothing, print 0 seconds */
+ if (x > 0 || ast_str_strlen(out) == 0) /* if there is nothing, print 0 seconds */
ast_str_append(&out, 0, "%d second%s ", x, ESS(x));
- ast_cli(fd, "%s: %s\n", prefix, out->str);
+ ast_cli(fd, "%s: %s\n", prefix, ast_str_buffer(out));
}
static struct ast_cli_entry *cli_next(struct ast_cli_entry *e)
{
struct ast_channel *c=NULL;
struct timeval now;
- struct ast_str *out = ast_str_alloca(2048);
+ struct ast_str *out = ast_str_thread_get(&global_app_buf, 16);
char cdrtime[256];
char nf[256], wf[256], rf[256];
long elapsed_seconds=0;
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
if (pbx_builtin_serialize_variables(c, &out))
- ast_cli(a->fd," Variables:\n%s\n", out->str);
+ ast_cli(a->fd," Variables:\n%s\n", ast_str_buffer(out));
if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
- ast_cli(a->fd," CDR Variables:\n%s\n", out->str);
+ ast_cli(a->fd," CDR Variables:\n%s\n", ast_str_buffer(out));
#ifdef CHANNEL_TRACE
trace_enabled = ast_channel_trace_is_enabled(c);
ast_cli(a->fd, " Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled");
if (trace_enabled && ast_channel_trace_serialize(c, &out))
- ast_cli(a->fd, " Trace:\n%s\n", out->str);
+ ast_cli(a->fd, " Trace:\n%s\n", ast_str_buffer(out));
#endif
ast_channel_unlock(c);
return CLI_SUCCESS;
static void CB_RESET(struct ast_str *cb, struct ast_str *llb)
{
- if (cb)
- cb->used = 0;
- if (llb)
- llb->used = 0;
+ if (cb) {
+ ast_str_reset(cb);
+ }
+ if (llb) {
+ ast_str_reset(llb);
+ }
}
-static struct ast_comment *ALLOC_COMMENT(const struct ast_str *buffer)
+static struct ast_comment *ALLOC_COMMENT(struct ast_str *buffer)
{
struct ast_comment *x = NULL;
- if (buffer && buffer->used)
- x = ast_calloc(1, sizeof(*x) + buffer->used + 1);
- if (x)
- strcpy(x->cmt, buffer->str);
+ if (!buffer || !ast_str_strlen(buffer)) {
+ return NULL;
+ }
+ if ((x = ast_calloc(1, sizeof(*x) + ast_str_strlen(buffer) + 1))) {
+ strcpy(x->cmt, ast_str_buffer(buffer)); /* SAFE */
+ }
return x;
}
static int hash_string(const void *obj, const int flags)
{
- char *str = ((struct inclfile*)obj)->fname;
+ char *str = ((struct inclfile *) obj)->fname;
int total;
- for (total=0; *str; str++) {
+ for (total = 0; *str; str++) {
unsigned int tmp = total;
total <<= 1; /* multiply by 2 */
total += tmp; /* multiply by 3 */
total <<= 2; /* multiply by 12 */
total += tmp; /* multiply by 13 */
- total += ((unsigned int)(*str));
+ total += ((unsigned int) (*str));
}
- if (total < 0)
+ if (total < 0) {
total = -total;
+ }
return total;
}
ast_str_set(str, 0, "%s", replace->value);
ast_str_append(str, 0, "%s", c);
- ast_variable_update(*cat, replace->name, ast_strip((*str)->str), replace->value, object);
+ ast_str_trim_blanks(*str);
+ ast_variable_update(*cat, replace->name, ast_skip_blanks(ast_str_buffer(*str)), replace->value, object);
} else if (c) {
*c = 0;
c++;
while (!feof(f)) {
lineno++;
if (fgets(buf, sizeof(buf), f)) {
- if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && lline_buffer->used) {
- CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */
- lline_buffer->used = 0; /* erase the lline buffer */
+ if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && ast_str_strlen(lline_buffer)) {
+ CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */
+ ast_str_reset(lline_buffer); /* erase the lline buffer */
}
new_buf = buf;
else
process_buf = buf;
- if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) {
+ if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer) && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) {
/* blank line? really? Can we add it to an existing comment and maybe preserve inter- and post- comment spacing? */
CB_ADD(&comment_buffer, "\n"); /* add a newline to the comment buffer */
continue; /* go get a new line, then */
}
while ((comment_p = strchr(new_buf, COMMENT_META))) {
- if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
+ if ((comment_p > new_buf) && (*(comment_p - 1) == '\\')) {
/* Escaped semicolons aren't comments. */
new_buf = comment_p + 1;
} else if (comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
}
/* end of file-- anything in a comment buffer? */
if (last_cat) {
- if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) {
- if (lline_buffer && lline_buffer->used) {
- CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */
- lline_buffer->used = 0; /* erase the lline buffer */
+ if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
+ if (lline_buffer && ast_str_strlen(lline_buffer)) {
+ CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */
+ ast_str_reset(lline_buffer); /* erase the lline buffer */
}
last_cat->trailing = ALLOC_COMMENT(comment_buffer);
}
} else if (last_var) {
- if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) {
- if (lline_buffer && lline_buffer->used) {
- CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */
- lline_buffer->used = 0; /* erase the lline buffer */
+ if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
+ if (lline_buffer && ast_str_strlen(lline_buffer)) {
+ CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */
+ ast_str_reset(lline_buffer); /* erase the lline buffer */
}
last_var->trailing = ALLOC_COMMENT(comment_buffer);
}
} else {
- if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used) {
- ast_debug(1, "Nothing to attach comments to, discarded: %s\n", comment_buffer->str);
+ if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
+ ast_debug(1, "Nothing to attach comments to, discarded: %s\n", ast_str_buffer(comment_buffer));
}
}
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
CB_RESET(comment_buffer, lline_buffer);
- fclose(f);
+ fclose(f);
} while (0);
if (comment) {
ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]);
* append a random variable to your GET request. Ex: 'something.html?r=109987734'
*/
if (!contentlength) { /* opaque body ? just dump it hoping it is properly formatted */
- fprintf(ser->f, "%s", out->str);
+ fprintf(ser->f, "%s", ast_str_buffer(out));
} else {
- char *tmp = strstr(out->str, "\r\n\r\n");
+ char *tmp = strstr(ast_str_buffer(out), "\r\n\r\n");
if (tmp) {
fprintf(ser->f, "Content-length: %d\r\n", contentlength);
/* first write the header, then the body */
- if (fwrite(out->str, 1, (tmp + 4 - out->str), ser->f) != tmp + 4 - out->str) {
+ if (fwrite(ast_str_buffer(out), 1, (tmp + 4 - ast_str_buffer(out)), ser->f) != tmp + 4 - ast_str_buffer(out)) {
ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
}
if (fwrite(tmp + 4, 1, contentlength, ser->f) != contentlength ) {
result = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */
va_end(ap);
if (result != AST_DYNSTR_BUILD_FAILED) {
- term_filter_escapes(buf->str);
- fputs(buf->str, stdout);
+ term_filter_escapes(ast_str_buffer(buf));
+ fputs(ast_str_buffer(buf), stdout);
}
}
return;
return;
/* Copy string over */
- strcpy(logmsg->str, buf->str);
+ strcpy(logmsg->str, ast_str_buffer(buf));
/* Set type to be normal */
logmsg->type = LOGMSG_NORMAL;
if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1)))
return;
- strcpy(logmsg->str, buf->str);
+ strcpy(logmsg->str, ast_str_buffer(buf));
ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->str + 1);
int i;
char *sep = "";
- (*res)->used = 0;
+ ast_str_reset(*res);
for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
if (authority & perms[i].num) {
ast_str_append(res, 0, "%s%s", sep, perms[i].label);
}
}
- if ((*res)->used == 0) /* replace empty string with something sensible */
+ if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */
ast_str_append(res, 0, "<none>");
- return (*res)->str;
+ return ast_str_buffer(*res);
}
/*! Tells you if smallstr exists inside bigstr
ast_str_set_va(&buf, 0, fmt, ap);
va_end(ap);
- if (s->f != NULL)
- send_string(s, buf->str);
- else
+ if (s->f != NULL) {
+ send_string(s, ast_str_buffer(buf));
+ } else {
ast_verbose("fd == -1 in astman_append, should not happen\n");
+ }
}
/*! \note NOTE: XXX this comment is unclear and possibly wrong.
ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
ast_str_append(&filepath, 0, "%s", fn);
- if ((fd = open(filepath->str, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
+ if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
close(fd);
astman_send_ack(s, m, "New configuration file created successfully");
- } else
+ } else {
astman_send_error(s, m, strerror(errno));
+ }
return 0;
}
c->accountcode,
c->_state,
ast_state2str(c->_state), c->context,
- c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, str->str, idText);
+ c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
} else {
astman_append(s,
"Event: Status\r\n"
S_OR(c->cid.cid_num, "<unknown>"),
S_OR(c->cid.cid_name, "<unknown>"),
c->accountcode,
- ast_state2str(c->_state), bridge, c->uniqueid, str->str, idText);
+ ast_state2str(c->_state), bridge, c->uniqueid, ast_str_buffer(str), idText);
}
ast_channel_unlock(c);
if (!all)
ast_str_append(&buf, 0, "\r\n");
- append_event(buf->str, category);
+ append_event(ast_str_buffer(buf), category);
/* Wake up any sleeping sessions */
AST_LIST_LOCK(&sessions);
AST_RWLIST_RDLOCK(&manager_hooks);
AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
- hook->helper(category, event, buf->str);
+ hook->helper(category, event, ast_str_buffer(buf));
}
AST_RWLIST_UNLOCK(&manager_hooks);
ast_str_set(&my_prefix, 0, "%s+ ", prefix);
if (node->next_char)
- log_match_char_tree(node->next_char, my_prefix->str);
+ log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
if (node->alt_char)
log_match_char_tree(node->alt_char, prefix);
ast_str_set(&my_prefix, 0, "%s+ ", prefix);
if (node->next_char)
- cli_match_char_tree(node->next_char, my_prefix->str, fd);
+ cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
if (node->alt_char)
cli_match_char_tree(node->alt_char, prefix, fd);
break;
} else if (eval) {
/* Substitute variables now */
- pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len);
- datap = tmpdata->str;
+ pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
+ datap = ast_str_buffer(tmpdata);
} else {
datap = osw;
}
ast_log(LOG_WARNING, "Can't evaluate switch?!");
continue;
}
- pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len);
+ pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
}
/* equivalent of extension_match_core() at the switch level */
aswf = asw->matchmore;
else /* action == E_MATCH */
aswf = asw->exists;
- datap = sw->eval ? tmpdata->str : sw->data;
+ datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
if (!aswf)
res = 0;
else {
return -1;
}
-static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
{
/* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
char *cp4;
- const char *tmp, *whereweare;
+ const char *tmp, *whereweare, *orig_cp2 = cp2;
int length, offset, offset2, isfunction;
char *workspace = NULL;
char *ltmp = NULL, *var = NULL;
/* Substitute if necessary */
if (needsub) {
+ size_t used;
if (!ltmp)
ltmp = alloca(VAR_BUF_SIZE);
- pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
+ pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
vars = ltmp;
} else {
vars = var;
/* Substitute if necessary */
if (needsub) {
+ size_t used;
if (!ltmp)
ltmp = alloca(VAR_BUF_SIZE);
- pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
+ pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
vars = ltmp;
} else {
vars = var;
}
}
}
+ *used = cp2 - orig_cp2;
}
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
{
- pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
+ size_t used;
+ pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
}
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
{
- pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
+ size_t used;
+ pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
}
static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
ast_str_set(&hint, 0, "%s", ast_get_extension_app(e));
- rest = hint->str; /* One or more devices separated with a & character */
+ rest = ast_str_buffer(hint); /* One or more devices separated with a & character */
while ( (cur = strsep(&rest, "&")) )
ast_devstate_aggregate_add(&agg, ast_device_state(cur));
}
pbx_builtin_serialize_variables(chan, &vars);
- if (vars->str) {
- ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str);
+ if (ast_str_strlen(vars)) {
+ ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
}
ast_channel_unlock(chan);
return CLI_SUCCESS;
{
int i;
- if (names) {
+ if (names && *s > '9') {
for (i = 0; names[i]; i++) {
- if (!strcasecmp(s, names[i]))
- return i+1;
+ if (!strcasecmp(s, names[i])) {
+ return i;
+ }
}
- } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
- return i;
}
- return 0; /* error return */
+
+ /* Allow months and weekdays to be specified as numbers, as well */
+ if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
+ /* What the array offset would have been: "1" would be at offset 0 */
+ return i - 1;
+ }
+ return -1; /* error return */
}
/*! \brief helper function to return a range up to max (7, 12, 31 respectively).
*/
static unsigned get_range(char *src, int max, char *const names[], const char *msg)
{
- int s, e; /* start and ending position */
+ int start, end; /* start and ending position */
unsigned int mask = 0;
+ char *part;
/* Check for whole range */
if (ast_strlen_zero(src) || !strcmp(src, "*")) {
- s = 0;
- e = max - 1;
- } else {
+ return (1 << max) - 1;
+ }
+
+ while ((part = strsep(&src, "&"))) {
/* Get start and ending position */
- char *c = strchr(src, '-');
- if (c)
- *c++ = '\0';
+ char *endpart = strchr(part, '-');
+ if (endpart) {
+ *endpart++ = '\0';
+ }
/* Find the start */
- s = lookup_name(src, names, max);
- if (!s) {
- ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
- return 0;
+ if ((start = lookup_name(part, names, max)) < 0) {
+ ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
+ continue;
}
- s--;
- if (c) { /* find end of range */
- e = lookup_name(c, names, max);
- if (!e) {
- ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
- return 0;
+ if (endpart) { /* find end of range */
+ if ((end = lookup_name(endpart, names, max)) < 0) {
+ ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
+ continue;
}
- e--;
- } else
- e = s;
- }
- /* Fill the mask. Remember that ranges are cyclic */
- mask = 1 << e; /* initialize with last element */
- while (s != e) {
- if (s >= max) {
- s = 0;
- mask |= (1 << s);
} else {
- mask |= (1 << s);
- s++;
+ end = start;
+ }
+ /* Fill the mask. Remember that ranges are cyclic */
+ mask |= (1 << end); /* initialize with last element */
+ while (start != end) {
+ if (start >= max) {
+ start = 0;
+ }
+ mask |= (1 << start);
+ start++;
}
}
return mask;
}
-/*! \brief store a bitmask of valid times, one bit each 2 minute */
+/*! \brief store a bitmask of valid times, one bit each 1 minute */
static void get_timerange(struct ast_timing *i, char *times)
{
- char *e;
+ char *endpart, *part;
int x;
- int s1, s2;
- int e1, e2;
- /* int cth, ctm; */
+ int st_h, st_m;
+ int endh, endm;
+ int minute_start, minute_end;
/* start disabling all times, fill the fields with 0's, as they may contain garbage */
memset(i->minmask, 0, sizeof(i->minmask));
- /* 2-minutes per bit, since the mask has only 32 bits :( */
+ /* 1-minute per bit */
/* Star is all times */
if (ast_strlen_zero(times) || !strcmp(times, "*")) {
- for (x = 0; x < 24; x++)
+ /* 48, because each hour takes 2 integers; 30 bits each */
+ for (x = 0; x < 48; x++) {
i->minmask[x] = 0x3fffffff; /* 30 bits */
+ }
return;
}
/* Otherwise expect a range */
- e = strchr(times, '-');
- if (!e) {
- ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
- return;
- }
- *e++ = '\0';
- /* XXX why skip non digits ? */
- while (*e && !isdigit(*e))
- e++;
- if (!*e) {
- ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n");
- return;
- }
- if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
- ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times);
- return;
- }
- if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
- ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e);
- return;
- }
- /* XXX this needs to be optimized */
-#if 1
- s1 = s1 * 30 + s2/2;
- if ((s1 < 0) || (s1 >= 24*30)) {
- ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
- return;
- }
- e1 = e1 * 30 + e2/2;
- if ((e1 < 0) || (e1 >= 24*30)) {
- ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
- return;
- }
- /* Go through the time and enable each appropriate bit */
- for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
- i->minmask[x/30] |= (1 << (x % 30));
- }
- /* Do the last one */
- i->minmask[x/30] |= (1 << (x % 30));
-#else
- for (cth = 0; cth < 24; cth++) {
- /* Initialize masks to blank */
- i->minmask[cth] = 0;
- for (ctm = 0; ctm < 30; ctm++) {
- if (
- /* First hour with more than one hour */
- (((cth == s1) && (ctm >= s2)) &&
- ((cth < e1)))
- /* Only one hour */
- || (((cth == s1) && (ctm >= s2)) &&
- ((cth == e1) && (ctm <= e2)))
- /* In between first and last hours (more than 2 hours) */
- || ((cth > s1) &&
- (cth < e1))
- /* Last hour with more than one hour */
- || ((cth > s1) &&
- ((cth == e1) && (ctm <= e2)))
- )
- i->minmask[cth] |= (1 << (ctm / 2));
+ while ((part = strsep(×, "&"))) {
+ if (!(endpart = strchr(part, '-'))) {
+ if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
+ ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
+ continue;
+ }
+ i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
+ continue;
+ }
+ *endpart++ = '\0';
+ /* why skip non digits? Mostly to skip spaces */
+ while (*endpart && !isdigit(*endpart)) {
+ endpart++;
+ }
+ if (!*endpart) {
+ ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
+ continue;
+ }
+ if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
+ ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
+ continue;
+ }
+ if (sscanf(endpart, "%d:%d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
+ ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
+ continue;
}
+ minute_start = st_h * 60 + st_m;
+ minute_end = endh * 60 + endm;
+ /* Go through the time and enable each appropriate bit */
+ for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
+ i->minmask[x / 30] |= (1 << (x % 30));
+ }
+ /* Do the last one */
+ i->minmask[x / 30] |= (1 << (x % 30));
}
-#endif
/* All done */
return;
}
/* Now the tough part, we calculate if it fits
in the right time based on min/hour */
- if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
+ if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
return 0;
/* If we got this far, then we're good */
if (!chan)
return 0;
- (*buf)->used = 0;
- (*buf)->str[0] = '\0';
+ ast_str_reset(*buf);
ast_channel_lock(chan);
--- /dev/null
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Digium, Inc.
+ *
+ * Tilghman Lesher <tlesher@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+* the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief String manipulation API
+ *
+ * \author Tilghman Lesher <tilghman@digium.com>
+ */
+
+/*** MAKEOPTS
+<category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes" remove_on_change=".lastclean">
+ <member name="DEBUG_OPAQUE" displayname="Change ast_str internals to detect improper usage">
+ <defaultenabled>yes</defaultenabled>
+ </member>
+</category>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/strings.h"
+#include "asterisk/pbx.h"
+
+/*!
+ * core handler for dynamic strings.
+ * This is not meant to be called directly, but rather through the
+ * various wrapper macros
+ * ast_str_set(...)
+ * ast_str_append(...)
+ * ast_str_set_va(...)
+ * ast_str_append_va(...)
+ */
+
+int __ast_str_helper(struct ast_str **buf, size_t max_len,
+ int append, const char *fmt, va_list ap)
+{
+ int res, need;
+#ifdef DEBUG_OPAQUE
+ int offset = (append && (*buf)->len2) ? (*buf)->used2 : 0;
+#else
+ int offset = (append && (*buf)->len) ? (*buf)->used : 0;
+#endif
+ va_list aq;
+
+ do {
+ if (max_len < 0) {
+#ifdef DEBUG_OPAQUE
+ max_len = (*buf)->len2; /* don't exceed the allocated space */
+#else
+ max_len = (*buf)->len; /* don't exceed the allocated space */
+#endif
+ }
+ /*
+ * Ask vsnprintf how much space we need. Remember that vsnprintf
+ * does not count the final '\0' so we must add 1.
+ */
+ va_copy(aq, ap);
+#ifdef DEBUG_OPAQUE
+ res = vsnprintf((*buf)->str2 + offset, (*buf)->len2 - offset, fmt, aq);
+#else
+ res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq);
+#endif
+
+ need = res + offset + 1;
+ /*
+ * If there is not enough space and we are below the max length,
+ * reallocate the buffer and return a message telling to retry.
+ */
+#ifdef DEBUG_OPAQUE
+ if (need > (*buf)->len2 && (max_len == 0 || (*buf)->len2 < max_len) ) {
+#else
+ if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) {
+#endif
+ if (max_len && max_len < need) { /* truncate as needed */
+ need = max_len;
+ } else if (max_len == 0) { /* if unbounded, give more room for next time */
+ need += 16 + need / 4;
+ }
+ if (0) { /* debugging */
+#ifdef DEBUG_OPAQUE
+ ast_verbose("extend from %d to %d\n", (int)(*buf)->len2, need);
+#else
+ ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need);
+#endif
+ }
+ if (ast_str_make_space(buf, need)) {
+#ifdef DEBUG_OPAQUE
+ ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len2, need);
+#else
+ ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need);
+#endif
+ return AST_DYNSTR_BUILD_FAILED;
+ }
+#ifdef DEBUG_OPAQUE
+ (*buf)->str2[offset] = '\0'; /* Truncate the partial write. */
+#else
+ (*buf)->str[offset] = '\0'; /* Truncate the partial write. */
+#endif
+
+ /* Restart va_copy before calling vsnprintf() again. */
+ va_end(aq);
+ continue;
+ }
+ break;
+ } while (1);
+ /* update space used, keep in mind the truncation */
+#ifdef DEBUG_OPAQUE
+ (*buf)->used2 = (res + offset > (*buf)->len2) ? (*buf)->len2 : res + offset;
+#else
+ (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset;
+#endif
+
+ return res;
+}
+
+void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *template)
+{
+ int first = 1;
+#ifdef DEBUG_OPAQUE
+ do {
+ ast_str_make_space(buf, maxlen ? maxlen :
+ (first ? strlen(template) * 2 : (*buf)->len2 * 2));
+ pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str2, (*buf)->len2 - 1, &((*buf)->used2));
+ first = 0;
+ } while (maxlen == 0 && (*buf)->len2 - 5 < (*buf)->used2);
+#else
+ do {
+ ast_str_make_space(buf, maxlen ? maxlen :
+ (first ? strlen(template) * 2 : (*buf)->len * 2));
+ pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str, (*buf)->len - 1, &((*buf)->used));
+ first = 0;
+ } while (maxlen == 0 && (*buf)->len - 5 < (*buf)->used);
+#endif
+}
+
+char *__ast_str_helper2(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc, int append, int escapecommas)
+{
+ int dynamic = 0;
+#ifdef DEBUG_OPAQUE
+ char *ptr = append ? &((*buf)->str2[(*buf)->used2]) : (*buf)->str2;
+#else
+ char *ptr = append ? &((*buf)->str[(*buf)->used]) : (*buf)->str;
+#endif
+
+ if (!maxlen) {
+ dynamic = 1;
+#ifdef DEBUG_OPAQUE
+ maxlen = (*buf)->len2;
+#else
+ maxlen = (*buf)->len;
+#endif
+ }
+
+ while (*src && maxsrc && maxlen && (!escapecommas || (maxlen - 1))) {
+ if (escapecommas && (*src == '\\' || *src == ',')) {
+ *ptr++ = '\\';
+ maxlen--;
+#ifdef DEBUG_OPAQUE
+ (*buf)->used2++;
+#else
+ (*buf)->used++;
+#endif
+ }
+ *ptr++ = *src++;
+ maxsrc--;
+ maxlen--;
+#ifdef DEBUG_OPAQUE
+ (*buf)->used2++;
+#else
+ (*buf)->used++;
+#endif
+ if (dynamic && (!maxlen || (escapecommas && !(maxlen - 1)))) {
+#ifdef DEBUG_OPAQUE
+ size_t old = (*buf)->len2;
+ if (ast_str_make_space(buf, (*buf)->len2 * 2)) {
+ /* If the buffer can't be extended, end it. */
+ break;
+ }
+#else
+ size_t old = (*buf)->len;
+ if (ast_str_make_space(buf, (*buf)->len * 2)) {
+ /* If the buffer can't be extended, end it. */
+ break;
+ }
+#endif
+ /* What we extended the buffer by */
+ maxlen = old;
+ }
+ }
+ if (__builtin_expect(!(maxsrc && maxlen), 0)) {
+ ptr--;
+ }
+ *ptr = '\0';
+#ifdef DEBUG_OPAQUE
+ (*buf)->used2--;
+ return (*buf)->str2;
+#else
+ (*buf)->used--;
+ return (*buf)->str;
+#endif
+}
+
return read(tcptls_session->fd, buf, count);
}
-HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count)
+HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count)
{
if (tcptls_session->fd == -1) {
ast_log(LOG_ERROR, "server_write called with an fd of -1\n");
}
}
ast_str_append(&out, -1, "\n");
- ast_cli(a->fd, "%s", out->str);
+ ast_cli(a->fd, "%s", ast_str_buffer(out));
}
AST_RWLIST_UNLOCK(&translators);
return CLI_SUCCESS;
return -1;
}
-/*!
- * core handler for dynamic strings.
- * This is not meant to be called directly, but rather through the
- * various wrapper macros
- * ast_str_set(...)
- * ast_str_append(...)
- * ast_str_set_va(...)
- * ast_str_append_va(...)
- */
-
-int __ast_str_helper(struct ast_str **buf, size_t max_len,
- int append, const char *fmt, va_list ap)
-{
- int res, need;
- int offset = (append && (*buf)->len) ? (*buf)->used : 0;
- va_list aq;
-
- do {
- if (max_len < 0) {
- max_len = (*buf)->len; /* don't exceed the allocated space */
- }
- /*
- * Ask vsnprintf how much space we need. Remember that vsnprintf
- * does not count the final '\0' so we must add 1.
- */
- va_copy(aq, ap);
- res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq);
-
- need = res + offset + 1;
- /*
- * If there is not enough space and we are below the max length,
- * reallocate the buffer and return a message telling to retry.
- */
- if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) {
- if (max_len && max_len < need) { /* truncate as needed */
- need = max_len;
- } else if (max_len == 0) { /* if unbounded, give more room for next time */
- need += 16 + need / 4;
- }
- if (0) { /* debugging */
- ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need);
- }
- if (ast_str_make_space(buf, need)) {
- ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need);
- return AST_DYNSTR_BUILD_FAILED;
- }
- (*buf)->str[offset] = '\0'; /* Truncate the partial write. */
-
- /* Restart va_copy before calling vsnprintf() again. */
- va_end(aq);
- continue;
- }
- break;
- } while (1);
- /* update space used, keep in mind the truncation */
- (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset;
-
- return res;
-}
-
void ast_enable_packet_fragmentation(int sock)
{
#if defined(HAVE_IP_MTU_DISCOVER)
backspace = xmldoc_foundspace_backward(text, i, maxdiff);
if (backspace) {
needtobreak = 1;
- tmp->used -= backspace;
- tmp->str[tmp->used] = '\0';
+ ast_str_truncate(tmp, -backspace);
i -= backspace + 1;
continue;
}
ast_str_append(&tmp, 0, "%c", text[i]);
}
- ret = ast_strdup(tmp->str);
+ ret = ast_strdup(ast_str_buffer(tmp));
ast_free(tmp);
return ret;
}
/* Wrap the text, notice that string wrap will avoid cutting an ESC sequence. */
- wrapped = xmldoc_string_wrap(colorized->str, xmldoc_text_columns, xmldoc_max_diff);
+ wrapped = xmldoc_string_wrap(ast_str_buffer(colorized), xmldoc_text_columns, xmldoc_max_diff);
ast_free(colorized);
ast_str_append(¶mname, 0, "}");
- ret = ast_strdup(paramname->str);
+ ret = ast_strdup(ast_str_buffer(paramname));
ast_free(paramname);
return ret;
}
/* return a common string. */
- ret = ast_strdup(syntax->str);
+ ret = ast_strdup(ast_str_buffer(syntax));
ast_free(syntax);
return ret;
if (tmpstr) {
if (strcasecmp(ast_xml_node_get_name(tmp), "text")) {
ast_str_append(buffer, 0, "<%s>%s</%s>", ast_xml_node_get_name(tmp),
- tmpstr->str, ast_xml_node_get_name(tmp));
+ ast_str_buffer(tmpstr), ast_xml_node_get_name(tmp));
} else {
- ast_str_append(buffer, 0, "%s", tmpstr->str);
+ ast_str_append(buffer, 0, "%s", ast_str_buffer(tmpstr));
}
ast_free(tmpstr);
ret = 2;
/* Cleanup text. */
xmldoc_string_cleanup(tmptext, &cleanstr, 1);
ast_xml_free_text(tmptext);
- if (cleanstr && cleanstr->used > 0) {
- ast_str_append(buffer, 0, ":%s", cleanstr->str);
+ if (cleanstr && ast_str_strlen(cleanstr) > 0) {
+ ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr));
}
ast_free(cleanstr);
}
ast_xml_free_text(content);
}
- output = ast_strdup(outputstr->str);
+ output = ast_strdup(ast_str_buffer(outputstr));
ast_free(outputstr);
return output;
xmldoc_parse_parameter(node, "", &ret);
}
- if (ret->used > 0) {
+ if (ast_str_strlen(ret) > 0) {
/* remove last '\n' */
- if (ret->str[ret->used - 1] == '\n') {
- ret->str[ret->used - 1] = '\0';
- ret->used--;
+ char *buf = ast_str_buffer(ret);
+ if (buf[ast_str_strlen(ret) - 1] == '\n') {
+ ast_str_truncate(ret, -1);
}
- retstr = ast_strdup(ret->str);
+ retstr = ast_strdup(ast_str_buffer(ret));
}
ast_free(ret);
}
/* remove last '\n' */
/* XXX Don't modify ast_str internals manually */
- if (ret->str[ret->used-1] == '\n') {
- ret->str[ret->used-1] = '\0';
- ret->used--;
+ tmpstr = ast_str_buffer(ret);
+ if (tmpstr[ast_str_strlen(ret) - 1] == '\n') {
+ ast_str_truncate(ret, -1);
}
}
return ret;
}
formatted = xmldoc_get_formatted(node, raw, raw);
- if (formatted->used > 0) {
- ret = ast_strdup(formatted->str);
+ if (ast_str_strlen(formatted) > 0) {
+ ret = ast_strdup(ast_str_buffer(formatted));
}
ast_free(formatted);
if (agidebug) {
if (chan) {
- ast_verbose("<%s>AGI Tx >> %s", chan->name, buf->str);
+ ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf));
} else {
- ast_verbose("AGI Tx >> %s", buf->str);
+ ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
}
}
- return ast_carefulwrite(fd, buf->str, buf->used, 100);
+ return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
}
/* linked list of AGI commands ready to be executed by Async AGI */
if (!ast_strlen_zero(a->word)) {
struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
- generator = ast_cli_generator(real_cmd->str, a->word, a->n);
+ generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
} else {
generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
}
ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]);
}
- ast_cli_command(a->fd, real_cmd->str);
+ ast_cli_command(a->fd, ast_str_buffer(real_cmd));
} else {
ast_cli_command(a->fd, alias->real_cmd);
}
va_end(ap);
ast_str_append(&query, 0, ")}");
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
/* Remove any trailing newline characters */
if ((stringp = strchr(buffer, '\r')) || (stringp = strchr(buffer, '\n')))
ast_str_append(&query, 0, ")}");
/* Do the CURL query */
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
if (!(cfg = ast_config_new()))
goto exit_multi;
va_end(ap);
ast_str_append(&query, 0, ")}");
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
/* Line oriented output */
stringp = buffer;
ast_str_append(&query, 0, ")}");
/* TODO: Make proxies work */
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
/* Line oriented output */
stringp = buffer;
va_end(ap);
ast_str_append(&query, 0, ")}");
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
stringp = buffer;
while (*stringp <= ' ')
va_end(ap);
ast_str_append(&query, 0, ")}");
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
/* Line oriented output */
stringp = buffer;
va_end(ap);
ast_str_append(&query, 0, ")}");
- pbx_substitute_variables_helper(NULL, query->str, buffer, sizeof(buffer));
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, sizeof(buffer));
return atoi(buffer);
}
ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
/* Do the CURL query */
- pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
+ pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
/* Line oriented output */
stringp = buffer;
do {
/* freeing ldap_result further down */
result = ldap_search_ext_s(ldapConn, clean_basedn,
- LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
+ LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
&ldap_result_msg);
if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
ast_log(LOG_DEBUG, "Failed to query database. Try %d/10\n",
if (result != LDAP_SUCCESS) {
ast_log(LOG_WARNING, "Failed to query database. Check debug for more info.\n");
- ast_log(LOG_WARNING, "Query: %s\n", filter->str);
+ ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
ast_log(LOG_WARNING, "Query Failed because: %s\n", ldap_err2string(result));
} else {
/* this is where we create the variables from the search result
vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
} else {
ast_debug(1, "Could not find any entry matching %s in base dn %s.\n",
- filter->str, clean_basedn);
+ ast_str_buffer(filter), clean_basedn);
}
ldap_msgfree(ldap_result_msg);
do {
/* freeing ldap_result further down */
result = ldap_search_ext_s(ldapConn, clean_basedn,
- LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
+ LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
&ldap_result_msg);
if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n",
if (result != LDAP_SUCCESS) {
ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n");
- ast_log(LOG_WARNING, "Query: %s\n", filter->str);
+ ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
ast_log(LOG_WARNING, "Query Failed because: %s\n",
ldap_err2string(result));
do {
/* freeing ldap_result further down */
result = ldap_search_ext_s(ldapConn, clean_basedn,
- LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
+ LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
&ldap_result_msg);
if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n",
if (result != LDAP_SUCCESS) {
ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n");
- ast_log(LOG_WARNING, "Query: %s\n", filter->str);
+ ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
ast_log(LOG_WARNING, "Query Failed because: %s\n",
ldap_err2string(result));
/* Done with the table metadata */
ast_odbc_release_table(tableptr);
- res = SQLPrepare(stmt, (unsigned char *)sql->str, SQL_NTS);
+ res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql->str);
+ ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql));
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return NULL;
}
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
/* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
sql = ast_str_thread_get(&sql_buf, 16);
- ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", sql->str);
+ ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql));
return -1;
}
#define ESCAPE_STRING(buffer, stringname) \
do { \
int len; \
- if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \
+ if ((len = strlen(stringname)) > (ast_str_size(buffer) - 1) / 2) { \
ast_str_make_space(&buffer, len * 2 + 1); \
} \
- PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \
+ PQescapeStringConn(pgsqlConn, ast_str_buffer(buffer), stringname, len, &pgresult); \
} while (0)
static void destroy_table(struct tables *table)
/* Not found, scan the table */
ast_str_set(&sql, 0, "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM pg_class c, pg_type t, pg_attribute a LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename);
- result = PQexec(pgsqlConn, sql->str);
+ result = PQexec(pgsqlConn, ast_str_buffer(sql));
ast_debug(1, "Query of table structure complete. Now retrieving results.\n");
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
pgerror = PQresultErrorMessage(result);
return NULL;
}
- ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, escapebuf->str);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, ast_str_buffer(escapebuf));
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' '))
return NULL;
}
- ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, ast_str_buffer(escapebuf));
}
va_end(ap);
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
}
}
- ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, ast_str_buffer(sql));
if ((num_rows = PQntuples(result)) > 0) {
int i = 0;
return NULL;
}
- ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf->str);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, ast_str_buffer(escapebuf));
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' '))
return NULL;
}
- ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, ast_str_buffer(escapebuf));
}
if (initfield) {
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
}
}
- ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, ast_str_buffer(sql));
if ((num_rows = PQntuples(result)) > 0) {
int numFields = PQnfields(result);
release_table(table);
return -1;
}
- ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf->str);
+ ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, ast_str_buffer(escapebuf));
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
return -1;
}
- ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf->str);
+ ast_str_append(&sql, 0, ", %s = '%s'", newparam, ast_str_buffer(escapebuf));
}
va_end(ap);
release_table(table);
return -1;
}
- ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf->str);
+ ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, ast_str_buffer(escapebuf));
- ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", ast_str_buffer(sql));
/* We now have our complete statement; Lets connect to the server and execute it. */
ast_mutex_lock(&pgsql_lock);
return -1;
}
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
ast_free(sql);
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
ast_free(sql);
return -1;
}
- ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, escapebuf->str);
+ ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, ast_str_buffer(escapebuf));
first = 0;
}
return -1;
}
- ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, escapebuf->str);
+ ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, ast_str_buffer(escapebuf));
}
release_table(table);
- ast_str_append(&sql, 0, " %s", where->str);
+ ast_str_append(&sql, 0, " %s", ast_str_buffer(where));
- ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", ast_str_buffer(sql));
/* We now have our complete statement; connect to the server and execute it. */
ast_mutex_lock(&pgsql_lock);
return -1;
}
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return -1;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
ESCAPE_STRING(buf, newparam);
- ast_str_set(&sql1, 0, "INSERT INTO %s (%s", table, buf->str);
+ ast_str_set(&sql1, 0, "INSERT INTO %s (%s", table, ast_str_buffer(buf));
ESCAPE_STRING(buf, newval);
- ast_str_set(&sql2, 0, ") VALUES ('%s'", buf->str);
+ ast_str_set(&sql2, 0, ") VALUES ('%s'", ast_str_buffer(buf));
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
ESCAPE_STRING(buf, newparam);
- ast_str_append(&sql1, 0, ", %s", buf->str);
+ ast_str_append(&sql1, 0, ", %s", ast_str_buffer(buf));
ESCAPE_STRING(buf, newval);
- ast_str_append(&sql2, 0, ", '%s'", buf->str);
+ ast_str_append(&sql2, 0, ", '%s'", ast_str_buffer(buf));
}
va_end(ap);
- ast_str_append(&sql1, 0, "%s)", sql2->str);
+ ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2));
- ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", sql1->str);
+ ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", ast_str_buffer(sql1));
- if (!(result = PQexec(pgsqlConn, sql1->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql1)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql1));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return -1;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql1));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
ESCAPE_STRING(buf1, keyfield);
ESCAPE_STRING(buf2, lookup);
- ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, buf1->str, buf2->str);
+ ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, ast_str_buffer(buf1), ast_str_buffer(buf2));
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
ESCAPE_STRING(buf1, newparam);
ESCAPE_STRING(buf2, newval);
- ast_str_append(&sql, 0, " AND %s = '%s'", buf1->str, buf2->str);
+ ast_str_append(&sql, 0, " AND %s = '%s'", ast_str_buffer(buf1), ast_str_buffer(buf2));
}
va_end(ap);
- ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", ast_str_buffer(sql));
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return -1;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
"WHERE filename='%s' and commented=0"
"ORDER BY cat_metric DESC, var_metric ASC, category, var_name ", table, file);
- ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", ast_str_buffer(sql));
/* We now have our complete statement; Lets connect to the server and execute it. */
ast_mutex_lock(&pgsql_lock);
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sql->str))) {
+ if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", table, database);
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql));
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
ast_mutex_lock(&pgsql_lock);
if (!pgsql_reconnect(database)) {
ast_mutex_unlock(&pgsql_lock);
- ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str);
+ ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql));
ast_free(sql);
continue;
}
ast_debug(1, "About to run ALTER query on table '%s' to add column '%s'\n", tablename, elm);
- result = PQexec(pgsqlConn, sql->str);
+ result = PQexec(pgsqlConn, ast_str_buffer(sql));
ast_debug(1, "Finished running ALTER query on table '%s'\n", tablename);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
- ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str);
+ ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql));
}
PQclear(result);
ast_mutex_unlock(&pgsql_lock);
if (!ast_strlen_zero(dbpass))
ast_str_append(&connInfo, 0, " password=%s", dbpass);
- ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str);
- pgsqlConn = PQconnectdb(connInfo->str);
- ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str);
+ ast_debug(1, "%u connInfo=%s\n", (unsigned int)ast_str_size(connInfo), ast_str_buffer(connInfo));
+ pgsqlConn = PQconnectdb(ast_str_buffer(connInfo));
+ ast_debug(1, "%u connInfo=%s\n", (unsigned int)ast_str_size(connInfo), ast_str_buffer(connInfo));
ast_free(connInfo);
connInfo = NULL;
struct sqlite_cache_tables *tbl = find_table(cdr_table);
struct sqlite_cache_columns *col;
struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16);
+ int first = 1;
if (!tbl) {
ast_log(LOG_WARNING, "No such table: %s\n", cdr_table);
continue;
}
if (sscanf(tmp, "%d", &scannum) == 1) {
- ast_str_append(&sql1, 0, "%s,", col->name);
- ast_str_append(&sql2, 0, "%d,", scannum);
+ ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
+ ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", scannum);
}
} else {
ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 0);
if (!tmp) {
continue;
}
- ast_str_append(&sql1, 0, "%s,", col->name);
+ ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
tmp = sqlite_mprintf("%Q", tmp);
- ast_str_append(&sql2, 0, "%s,", tmp);
+ ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", tmp);
sqlite_freemem(tmp);
}
}
release_table(tbl);
- sql1->str[--sql1->used] = '\0';
- sql2->str[--sql2->used] = '\0';
- ast_str_append(&sql1, 0, "%s)", sql2->str);
+ ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2));
ast_free(sql2);
- ast_debug(1, "SQL query: %s\n", sql1->str);
+ ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql1));
ast_mutex_lock(&mutex);
RES_CONFIG_SQLITE_BEGIN
- error = sqlite_exec(db, sql1->str, NULL, NULL, &errormsg);
+ error = sqlite_exec(db, ast_str_buffer(sql1), NULL, NULL, &errormsg);
RES_CONFIG_SQLITE_END(error)
ast_mutex_unlock(&mutex);
first = 0;
}
- ast_str_append(&sql, 0, " %s", where->str);
- ast_debug(1, "SQL query: %s\n", sql->str);
+ ast_str_append(&sql, 0, " %s", ast_str_buffer(where));
+ ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql));
ast_mutex_lock(&mutex);
RES_CONFIG_SQLITE_BEGIN
- error = sqlite_exec(db, sql->str, NULL, NULL, &errormsg);
+ error = sqlite_exec(db, ast_str_buffer(sql), NULL, NULL, &errormsg);
RES_CONFIG_SQLITE_END(error)
if (!error) {
NULL, "The was an error parsing the request.");
}
- if (!(message_count = process_message(message, post_dir->str))) {
+ if (!(message_count = process_message(message, ast_str_buffer(post_dir)))) {
ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n");
g_object_unref(message);
return ast_http_error((*status = 400),
rm -f *.s *.i
rm -f md5.c strcompat.c ast_expr2.c ast_expr2f.c pbx_ael.c pval.c hashtab.c
rm -f aelparse.c aelbison.c conf2ael
- rm -f utils.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter
+ rm -f utils.c strings.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter
md5.c: $(ASTTOPDIR)/main/md5.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
$(CMD_PREFIX) cp "$<" "$@"
utils.o: ASTCFLAGS+=-DSTANDALONE
+strings.c: $(ASTTOPDIR)/main/strings.c
+ $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
+ $(CMD_PREFIX) cp "$<" "$@"
+strings.o: ASTCFLAGS+=-DSTANDALONE
+
sha1.c: $(ASTTOPDIR)/main/sha1.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
$(CMD_PREFIX) cp "$<" "$@"
threadstorage.o: ASTCFLAGS+=-DSTANDALONE
hashtest2.o: ASTCFLAGS+=-O0 -DSTANDALONE
-hashtest2: hashtest2.o md5.o utils.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o
+hashtest2: hashtest2.o md5.o utils.o strings.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o
-hashtest: hashtest.o md5.o hashtab.o utils.o sha1.o strcompat.o threadstorage.o clicompat.o
+hashtest: hashtest.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o
hashtest.o: ASTCFLAGS+=-O0 -DSTANDALONE
-refcounter: refcounter.o md5.o hashtab.o utils.o sha1.o strcompat.o threadstorage.o clicompat.o
+refcounter: refcounter.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o
refcounter.o: ASTCFLAGS+=-O0 -DSTANDALONE
extconf.o: extconf.c
#define AST_API_MODULE 1
#include "asterisk/lock.h"
-#include "asterisk/strings.h"
-
-/* I included this from utils.c, so as not to have everything in that .c
- file included */
-/*!
- * core handler for dynamic strings.
- * This is not meant to be called directly, but rather through the
- * various wrapper macros
- * ast_str_set(...)
- * ast_str_append(...)
- * ast_str_set_va(...)
- * ast_str_append_va(...)
- */
-int __attribute__((format(printf, 4, 0))) __ast_str_helper(struct ast_str **buf, size_t max_len,
- int append, const char *fmt, va_list ap)
-{
- int res, need;
- int offset = (append && (*buf)->len) ? (*buf)->used : 0;
-
- if (max_len < 0)
- max_len = (*buf)->len; /* don't exceed the allocated space */
- /*
- * Ask vsnprintf how much space we need. Remember that vsnprintf
- * does not count the final '\0' so we must add 1.
- */
- res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
-
- need = res + offset + 1;
- /*
- * If there is not enough space and we are below the max length,
- * reallocate the buffer and return a message telling to retry.
- */
- if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) {
- if (max_len && max_len < need) /* truncate as needed */
- need = max_len;
- else if (max_len == 0) /* if unbounded, give more room for next time */
- need += 16 + need/4;
- if (ast_str_make_space(buf, need)) {
- return AST_DYNSTR_BUILD_FAILED;
- }
- (*buf)->str[offset] = '\0'; /* Truncate the partial write. */
-
- /* va_end() and va_start() must be done before calling
- * vsnprintf() again. */
- return AST_DYNSTR_BUILD_RETRY;
- }
- /* update space used, keep in mind the truncation */
- (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset;
-
- return res;
-}
#ifndef DEBUG_THREADS
enum ast_lock_type {
AST_MUTEX,
}
#endif
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used)
+{
+}
+
struct ht_element
{
char *key;
char *val;
};
+char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used);
+char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used)
+{
+ return NULL;
+}
static int hash_string(const void *obj, const int flags)
{
struct rc_hist *last;
};
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used)
+{
+}
+
static unsigned int hashtab_hash_rc(const void *obj)
{
const struct rc_obj *rc = obj;