aboutsummaryrefslogtreecommitdiffstats
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rwxr-xr-xres/res_adsi.c2
-rwxr-xr-xres/res_agi.c27
-rwxr-xr-xres/res_config_odbc.c2
-rwxr-xr-xres/res_crypto.c3
-rwxr-xr-xres/res_features.c104
-rwxr-xr-xres/res_indications.c15
-rwxr-xr-xres/res_monitor.c96
-rwxr-xr-xres/res_musiconhold.c10
-rwxr-xr-xres/res_odbc.c112
9 files changed, 262 insertions, 109 deletions
diff --git a/res/res_adsi.c b/res/res_adsi.c
index 2ee440e6a..c6cc0c19c 100755
--- a/res/res_adsi.c
+++ b/res/res_adsi.c
@@ -389,6 +389,8 @@ int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msgl
if (readformat)
ast_set_read_format(chan, readformat);
+ if (!res)
+ res = ast_safe_sleep(chan, 100 );
return res;
}
diff --git a/res/res_agi.c b/res/res_agi.c
index 04cf9eec5..71c636ff8 100755
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -11,12 +11,12 @@
* the GNU General Public License
*/
+#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
-#include <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -119,7 +119,7 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
struct pollfd pfds[1];
char *host;
char *c; int port = AGI_PORT;
- char *script;
+ char *script = "";
struct sockaddr_in sin;
struct hostent *hp;
struct ast_hostent ahp;
@@ -136,7 +136,7 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
if ((c = strchr(host, ':'))) {
*c = '\0';
c++;
- port = atoi(c + 1);
+ port = atoi(c);
}
if (efd) {
ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
@@ -185,6 +185,9 @@ static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int
return -1;
}
ast_log(LOG_DEBUG, "Wow, connected!\n");
+ /* Send the script parameter */
+ if (!ast_strlen_zero(script))
+ fdprintf(s, "agi_network_script: %s\n", script);
fds[0] = s;
fds[1] = s;
*opid = -1;
@@ -393,11 +396,11 @@ static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *ar
if (!strncasecmp(argv[2],"mate",4)) x = 2;
if (!strncasecmp(argv[2],"tdd",3)) x = 1;
res = ast_channel_setoption(chan,AST_OPTION_TDD,&x,sizeof(char),0);
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
+ if (res == RESULT_SUCCESS)
+ fdprintf(agi->fd, "200 result=1\n");
else
- return RESULT_FAILURE;
+ fdprintf(agi->fd, "200 result=0\n");
+ return RESULT_SUCCESS;
}
static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
@@ -432,8 +435,7 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
fs = ast_openstream(chan, argv[2], chan->language);
if(!fs){
fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
- ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
- return RESULT_FAILURE;
+ return RESULT_SUCCESS;
}
ast_seekstream(fs, 0, SEEK_END);
max_length = ast_tellstream(fs);
@@ -472,7 +474,7 @@ static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *
int num;
if (argc != 4)
return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%i", &num) != 1)
+ if (sscanf(argv[2], "%d", &num) != 1)
return RESULT_SHOWUSAGE;
res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
if (res == 1)
@@ -559,10 +561,7 @@ static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *ar
fdprintf(agi->fd, "200 result=-1\n");
else
fdprintf(agi->fd, "200 result=%s\n", data);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
+ return RESULT_SUCCESS;
}
static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index 3f8490530..82e9e681b 100755
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -44,7 +44,7 @@ static struct ast_config *config_odbc (char *file, struct ast_config *new_config
odbc_obj *obj;
SQLINTEGER err=0, commented=0, cat_metric=0, var_metric=0, last_cat_metric=0;
SQLBIGINT id;
- char sql[255] = "", filename[128], category[128], var_name[128], var_val[128];
+ char sql[255]="", filename[128]="", category[128]="", var_name[128]="", var_val[512]="";
SQLSMALLINT rowcount=0;
SQLHSTMT stmt;
char last[80] = "";
diff --git a/res/res_crypto.c b/res/res_crypto.c
index 912d7c8c0..16c879de1 100755
--- a/res/res_crypto.c
+++ b/res/res_crypto.c
@@ -174,6 +174,7 @@ static struct ast_key *try_load_key (char *dir, char *fname, int ifd, int ofd, i
while(!feof(f)) {
/* Calculate a "whatever" quality md5sum of the key */
char buf[256];
+ memset(buf, 0, 256);
fgets(buf, sizeof(buf), f);
if (!feof(f)) {
MD5Update(&md5, buf, strlen(buf));
@@ -441,7 +442,7 @@ int ast_check_signature(struct ast_key *key, char *msg, char *sig)
static void crypto_load(int ifd, int ofd)
{
struct ast_key *key, *nkey, *last;
- DIR *dir;
+ DIR *dir = NULL;
struct dirent *ent;
int note = 0;
/* Mark all keys for deletion */
diff --git a/res/res_features.c b/res/res_features.c
index b2fd1a866..753864d54 100755
--- a/res/res_features.c
+++ b/res/res_features.c
@@ -38,6 +38,15 @@
#include <sys/signal.h>
#include <netinet/in.h>
+#ifdef __AST_DEBUG_MALLOC
+static void FREE(void *ptr)
+{
+ free(ptr);
+}
+#else
+#define FREE free
+#endif
+
#define DEFAULT_PARK_TIME 45000
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
@@ -49,6 +58,9 @@ static int parkingtime = DEFAULT_PARK_TIME;
/* Context for which parking is made accessible */
static char parking_con[AST_MAX_EXTENSION] = "parkedcalls";
+/* Context for dialback for parking (KLUDGE) */
+static char parking_con_dial[AST_MAX_EXTENSION] = "park-dial";
+
/* Extension you type to park the call */
static char parking_ext[AST_MAX_EXTENSION] = "700";
@@ -103,6 +115,8 @@ struct parkeduser {
int priority;
int parkingtime;
int notquiteyet;
+ char peername[1024];
+ unsigned char moh_trys;
struct parkeduser *next;
};
@@ -152,6 +166,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
struct ast_context *con;
pu = malloc(sizeof(struct parkeduser));
if (pu) {
+ memset(pu,0,sizeof(struct parkeduser));
ast_mutex_lock(&parking_lock);
for (x=parking_start;x<=parking_stop;x++) {
cur = parkinglot;
@@ -179,6 +194,8 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pu->parkingtime = parkingtime;
if (extout)
*extout = x;
+ if (peer)
+ strncpy(pu->peername, peer->name, sizeof(pu->peername) - 1);
/* Remember what had been dialed, so that if the parking
expires, we try to come back to the same place */
if (!ast_strlen_zero(chan->macrocontext))
@@ -223,12 +240,6 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
if (adsipark && adsi_available(peer)) {
adsi_unload_session(peer);
}
- if (pu->notquiteyet) {
- /* Wake up parking thread if we're really done */
- ast_moh_start(pu->chan, NULL);
- pu->notquiteyet = 0;
- pthread_kill(parking_thread, SIGURG);
- }
}
con = ast_context_find(parking_con);
if (!con) {
@@ -239,8 +250,15 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
}
if (con) {
snprintf(exten, sizeof(exten), "%d", x);
- ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
+ ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), FREE, registrar);
}
+ if (pu->notquiteyet) {
+ /* Wake up parking thread if we're really done */
+ ast_moh_start(pu->chan, NULL);
+ pu->notquiteyet = 0;
+ pthread_kill(parking_thread, SIGURG);
+ }
+
return 0;
} else {
ast_log(LOG_WARNING, "No more parking spaces\n");
@@ -302,6 +320,12 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
int allowdisconnect_in,allowdisconnect_out,allowredirect_in,allowredirect_out;
char *monitor_exec;
+ if (chan && peer) {
+ pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
+ pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
+ } else if (chan)
+ pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
+
if (monitor_ok) {
if (!monitor_app) {
if (!(monitor_app = pbx_findapp("Monitor")))
@@ -480,6 +504,8 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
}
/* XXX Maybe we should have another message here instead of invalid extension XXX */
} else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->callerid)) {
+ pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
+ pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
ast_moh_stop(transferee);
res=ast_autoservice_stop(transferee);
if (!transferee->pbx) {
@@ -540,20 +566,21 @@ static void *do_parking_thread(void *ignore)
struct timeval tv;
struct ast_frame *f;
char exten[AST_MAX_EXTENSION];
+ char *peername,*cp;
+ char returnexten[AST_MAX_EXTENSION];
struct ast_context *con;
int x;
- int gc=0;
fd_set rfds, efds;
fd_set nrfds, nefds;
FD_ZERO(&rfds);
FD_ZERO(&efds);
+
for (;;) {
ms = -1;
max = -1;
ast_mutex_lock(&parking_lock);
pl = NULL;
pu = parkinglot;
- gettimeofday(&tv, NULL);
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
while(pu) {
@@ -563,21 +590,42 @@ static void *do_parking_thread(void *ignore)
pu = pu->next;
continue;
}
- if (gc < 5 && !pu->chan->generator) {
- gc++;
- ast_moh_start(pu->chan,NULL);
- }
+ gettimeofday(&tv, NULL);
tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
if (tms > pu->parkingtime) {
- /* They've been waiting too long, send them back to where they came. Theoretically they
- should have their original extensions and such, but we copy to be on the safe side */
- strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1);
- strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1);
- pu->chan->priority = pu->priority;
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
/* Stop music on hold */
ast_moh_stop(pu->chan);
+ /* Get chan, exten from derived kludge */
+ if (pu->peername[0]) {
+ peername = ast_strdupa(pu->peername);
+ cp = strrchr(peername, '-');
+ if (cp)
+ *cp = 0;
+ con = ast_context_find(parking_con_dial);
+ if (!con) {
+ con = ast_context_create(NULL, parking_con_dial, registrar);
+ if (!con) {
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
+ }
+ }
+ if (con) {
+ snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
+ ast_add_extension2(con, 1, peername, 1, NULL, "Dial", strdup(returnexten), free, registrar);
+ }
+ strncpy(pu->chan->exten, peername, sizeof(pu->chan->exten) - 1);
+ strncpy(pu->chan->context, parking_con_dial, sizeof(pu->chan->context) - 1);
+ pu->chan->priority = 1;
+
+ } else {
+ /* They've been waiting too long, send them back to where they came. Theoretically they
+ should have their original extensions and such, but we copy to be on the safe side */
+ strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1);
+ strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1);
+ pu->chan->priority = pu->priority;
+ }
+
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
/* Start up the PBX, or hang them up */
if (ast_pbx_start(pu->chan)) {
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
@@ -599,14 +647,17 @@ static void *do_parking_thread(void *ignore)
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
free(pt);
} else {
- for (x=0;x<AST_MAX_FDS;x++) {
+ for (x=0; x<AST_MAX_FDS; x++) {
if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
if (FD_ISSET(pu->chan->fds[x], &efds))
pu->chan->exception = 1;
+ else
+ pu->chan->exception = 0;
pu->chan->fdno = x;
/* See if they need servicing */
f = ast_read(pu->chan);
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
+
/* There's a problem, hang them up*/
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
@@ -630,12 +681,17 @@ static void *do_parking_thread(void *ignore)
} else {
/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
ast_frfree(f);
+ if (pu->moh_trys < 3 && !pu->chan->generatordata) {
+ ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
+ ast_moh_start(pu->chan, NULL);
+ pu->moh_trys++;
+ }
goto std; /* XXX Ick: jumping into an else statement??? XXX */
}
}
}
if (x >= AST_MAX_FDS) {
-std: for (x=0;x<AST_MAX_FDS;x++) {
+std: for (x=0; x<AST_MAX_FDS; x++) {
/* Keep this one for next one */
if (pu->chan->fds[x] > -1) {
FD_SET(pu->chan->fds[x], &nrfds);
@@ -784,7 +840,7 @@ static int park_exec(struct ast_channel *chan, void *data)
dres = 0;
}
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
res = -1;
}
LOCAL_USER_REMOVE(u);
@@ -926,7 +982,7 @@ int load_module(void)
return -1;
}
}
- ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, parkcall, strdup(""),free, registrar);
+ ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, parkcall, strdup(""), FREE, registrar);
ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
if (!res)
diff --git a/res/res_indications.c b/res/res_indications.c
index b289612d5..e998be582 100755
--- a/res/res_indications.c
+++ b/res/res_indications.c
@@ -53,6 +53,14 @@ static char help_show_indications[] =
" Show either a condensed for of all country/indications, or the\n"
" indications for the specified countries.\n";
+char *playtones_desc=
+"PlayTone(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
+"while the tones continue to play.\n"
+"Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
+"specified list of frequencies and durations.\n"
+"See indications.conf for a description of the specification of a tonelist.\n\n"
+"Use the StopPlaytones application to stop the tones playing. \n";
+
/*
* Implementation of functions provided by this module
*/
@@ -367,11 +375,12 @@ int unload_module(void)
ast_cli_unregister(&add_indication_cli);
ast_cli_unregister(&remove_indication_cli);
ast_cli_unregister(&show_indications_cli);
- ast_unregister_application("Playlist");
- ast_unregister_application("StopPlaylist");
+ ast_unregister_application("Playtones");
+ ast_unregister_application("StopPlaytones");
return 0;
}
+
int load_module(void)
{
if (ind_load_module()) return -1;
@@ -379,7 +388,7 @@ int load_module(void)
ast_cli_register(&add_indication_cli);
ast_cli_register(&remove_indication_cli);
ast_cli_register(&show_indications_cli);
- ast_register_application("Playtones", handle_playtones, "Play a tone list","Play a tone list, either registered (through indications.conf) or a direct list of tones and durations.");
+ ast_register_application("Playtones", handle_playtones, "Play a tone list", playtones_desc);
ast_register_application("StopPlaytones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
return 0;
diff --git a/res/res_monitor.c b/res/res_monitor.c
index c36460c5a..76f15b8ee 100755
--- a/res/res_monitor.c
+++ b/res/res_monitor.c
@@ -33,22 +33,24 @@ static char *monitor_descrip = "Monitor([file_format|[fname_base]|[options]]):\n
"Used to start monitoring a channel. The channel's input and output\n"
"voice packets are logged to files until the channel hangs up or\n"
"monitoring is stopped by the StopMonitor application.\n"
-" file_format -- optional, if not set, defaults to \"wav\"\n"
-" fname_base -- if set, changes the filename used to the one specified.\n"
-" options:\n"
-" 'm' - when the recording ends mix the two leg files into one and\n"
-" delete the two leg files. If MONITOR_EXEC is set, the\n"
-" application refernced in it will be executed instead of\n"
-" soxmix and the raw leg files will NOT be deleted automatically.\n"
-" soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
-" and a target mixed file name which is the same as the leg file names\n"
-" only without the in/out designator.\n"
-" If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
-" additional arguements to MONITOR_EXEC\n"
-" Both MONITOR_EXEC and the Mix flag can be set from the\n"
-" administrator interface\n\n"
+" file_format optional, if not set, defaults to \"wav\"\n"
+" fname_base if set, changes the filename used to the one specified.\n"
+" options:\n"
+" m - when the recording ends mix the two leg files into one and\n"
+" delete the two leg files. If the variable MONITOR_EXEC is set, the\n"
+" application referenced in it will be executed instead of\n"
+" soxmix and the raw leg files will NOT be deleted automatically.\n"
+" soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
+" and a target mixed file name which is the same as the leg file names\n"
+" only without the in/out designator.\n"
+" If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
+" additional arguements to MONITOR_EXEC\n"
+" Both MONITOR_EXEC and the Mix flag can be set from the\n"
+" administrator interface\n"
"\n"
-" 'b' - Don't begin recording unless a call is bridged to another channel\n"
+" b - Don't begin recording unless a call is bridged to another channel\n"
+"\nReturns -1 if monitor files can't be opened or if the channel is already\n"
+"monitored, otherwise 0.\n"
;
static char *stopmonitor_synopsis = "Stop monitoring a channel";
@@ -58,10 +60,9 @@ static char *stopmonitor_descrip = "StopMonitor\n"
static char *changemonitor_synopsis = "Change monitoring filename of a channel";
-static char *changemonitor_descrip = "ChangeMonitor\n"
+static char *changemonitor_descrip = "ChangeMonitor(filename_base)\n"
"Changes monitoring filename of a channel. Has no effect if the channel is not monitored\n"
- "The option string may contain the following:\n"
- " filename_base -- if set, changes the filename used to the one specified.\n";
+ "The argument is the new filename base to use for monitoring this channel.\n";
/* Start monitoring a channel */
int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
@@ -90,6 +91,11 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
}
monitor = malloc(sizeof(struct ast_channel_monitor));
+ if (!monitor) {
+ if (need_lock)
+ ast_mutex_unlock(&chan->lock);
+ return -1;
+ }
memset(monitor, 0, sizeof(struct ast_channel_monitor));
/* Determine file names */
@@ -98,9 +104,9 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
/* try creating the directory just in case it doesn't exist */
if (directory) {
char *name = strdup(fname_base);
- snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
+ snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name));
free(name);
- system(tmp);
+ ast_safe_system(tmp);
}
snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in",
directory ? "" : AST_MONITOR_DIR, fname_base);
@@ -238,9 +244,9 @@ int ast_monitor_stop(struct ast_channel *chan, int need_lock)
execute_args = "";
}
- snprintf(tmp, sizeof(tmp), "%s %s/%s-in.%s %s/%s-out.%s %s/%s.%s %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args);
+ snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args);
if (delfiles) {
- snprintf(tmp2,sizeof(tmp2), "( %s& rm -f %s/%s-* ) &",tmp, dir ,name); /* remove legs when done mixing */
+ snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
strncpy(tmp, tmp2, sizeof(tmp) - 1);
}
ast_verbose("monitor executing %s\n",tmp);
@@ -281,12 +287,12 @@ int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, i
char *name = strdup(fname_base);
snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
free(name);
- system(tmp);
+ ast_safe_system(tmp);
}
snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : AST_MONITOR_DIR, fname_base);
} else {
- ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started", chan->name, fname_base);
+ ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
}
if (need_lock)
@@ -362,6 +368,20 @@ static int change_monitor_exec(struct ast_channel *chan, void *data)
return ast_monitor_change_fname(chan, (const char*)data, 1);
}
+static char start_monitor_action_help[] =
+"Description: The 'Monitor' action may be used to record the audio on a\n"
+" specified channel. The following parameters may be used to control\n"
+" this:\n"
+" Channel - Required. Used to specify the channel to record.\n"
+" File - Optional. Is the name of the file created in the\n"
+" monitor spool directory. Defaults to the same name\n"
+" as the channel (with slashes replaced with dashes).\n"
+" Format - Optional. Is the audio recording format. Defaults\n"
+" to \"wav\".\n"
+" Mix - Optional. Boolean parameter as to whether to mix\n"
+" the input and output channels together after the\n"
+" recording is finished.\n";
+
static int start_monitor_action(struct mansession *s, struct message *m)
{
struct ast_channel *c = NULL;
@@ -391,6 +411,11 @@ static int start_monitor_action(struct mansession *s, struct message *m)
if ((!fname) || (ast_strlen_zero(fname))) {
// No filename base specified, default to channel name as per CLI
fname = malloc (FILENAME_MAX);
+ if (!fname) {
+ astman_send_error(s, m, "Could not start monitoring channel");
+ ast_mutex_unlock(&c->lock);
+ return 0;
+ }
memset(fname, 0, FILENAME_MAX);
strncpy(fname, c->name, FILENAME_MAX-1);
// Channels have the format technology/channel_name - have to replace that /
@@ -414,6 +439,11 @@ static int start_monitor_action(struct mansession *s, struct message *m)
return 0;
}
+static char stop_monitor_action_help[] =
+"Description: The 'StopMonitor' action may be used to end a previously\n"
+" started 'Monitor' action. The only parameter is 'Channel', the name\n"
+" of the channel monitored.\n";
+
static int stop_monitor_action(struct mansession *s, struct message *m)
{
struct ast_channel *c = NULL;
@@ -445,6 +475,14 @@ static int stop_monitor_action(struct mansession *s, struct message *m)
return 0;
}
+static char change_monitor_action_help[] =
+"Description: The 'ChangeMonitor' action may be used to change the file\n"
+" started by a previous 'Monitor' action. The following parameters may\n"
+" be used to control this:\n"
+" Channel - Required. Used to specify the channel to record.\n"
+" File - Required. Is the new name of the file created in the\n"
+" monitor spool directory.\n";
+
static int change_monitor_action(struct mansession *s, struct message *m)
{
struct ast_channel *c = NULL;
@@ -491,9 +529,9 @@ int load_module(void)
ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
- ast_manager_register("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis);
- ast_manager_register("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis);
- ast_manager_register("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis);
+ ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
+ ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
+ ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
return 0;
}
@@ -502,6 +540,10 @@ int unload_module(void)
{
ast_unregister_application("Monitor");
ast_unregister_application("StopMonitor");
+ ast_unregister_application("ChangeMonitor");
+ ast_manager_unregister("Monitor");
+ ast_manager_unregister("StopMonitor");
+ ast_manager_unregister("ChangeMonitor");
return 0;
}
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 2dc39a5c6..6cf30db4e 100755
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -224,8 +224,11 @@ static int spawn_mp3(struct mohclass *class)
/* Stdout goes to pipe */
dup2(fds[1], STDOUT_FILENO);
/* Close unused file descriptors */
- for (x=3;x<8192;x++)
- close(x);
+ for (x=3;x<8192;x++) {
+ if (-1 != fcntl(x, F_GETFL)) {
+ close(x);
+ }
+ }
/* Child */
chdir(class->dir);
if(class->custom) {
@@ -352,6 +355,7 @@ static int moh0_exec(struct ast_channel *chan, void *data)
return -1;
}
while(!ast_safe_sleep(chan, 10000));
+ ast_moh_stop(chan);
return -1;
}
@@ -363,7 +367,7 @@ static int moh1_exec(struct ast_channel *chan, void *data)
return -1;
}
if (ast_moh_start(chan, NULL)) {
- ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
+ ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi((char *)data), chan->name);
return -1;
}
res = ast_safe_sleep(chan, atoi(data) * 1000);
diff --git a/res/res_odbc.c b/res/res_odbc.c
index c8efb0620..9c237ddd6 100755
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -99,10 +99,12 @@ static int load_odbc_config(void)
if (!strcmp(cat, "ENV")) {
for (v = ast_variable_browse(config, cat); v; v = v->next) {
env_var = malloc(strlen(v->name) + strlen(v->value) + 2);
- sprintf(env_var, "%s=%s", v->name, v->value);
- ast_log(LOG_NOTICE, "Adding ENV var: %s=%s\n", v->name, v->value);
- putenv(env_var);
- free(env_var);
+ if (env_var) {
+ sprintf(env_var, "%s=%s", v->name, v->value);
+ ast_log(LOG_NOTICE, "Adding ENV var: %s=%s\n", v->name, v->value);
+ putenv(env_var);
+ free(env_var);
+ }
}
cat = ast_category_browse(config, cat);
@@ -145,39 +147,27 @@ static int load_odbc_config(void)
int odbc_dump_fd(int fd, odbc_obj * obj)
{
- ast_cli(fd, "\n\nName: %s\nDSN: %s\nConnected: %s\n\n", obj->name, obj->dsn, obj->up ? "yes" : "no");
+ ast_cli(fd, "Name: %s\nDSN: %s\nConnected: %s\n", obj->name, obj->dsn, obj->up ? "yes" : "no");
+ return 0;
+}
+
+static int odbc_connect_usage(int fd)
+{
+ ast_cli(fd, "usage odbc connect <DSN>\n");
return 0;
}
-static int odbc_usage(int fd)
+static int odbc_disconnect_usage(int fd)
{
- ast_cli(fd, "\n\nusage odbc <command> <arg1> .. <argn>\n\n");
+ ast_cli(fd, "usage odbc disconnect <DSN>\n");
return 0;
}
-static int odbc_command(int fd, int argc, char **argv)
+static int odbc_show_command(int fd, int argc, char **argv)
{
odbc_obj *obj;
int x = 0;
- if (!argv[1])
- return odbc_usage(fd);
-
- ast_cli(fd, "\n\n");
-
- if (!strcmp(argv[1], "connect") || !strcmp(argv[1], "disconnect")) {
- if (!argv[2])
- return odbc_usage(fd);
-
- obj = odbc_read(ODBC_REGISTRY, argv[2]);
- if (obj) {
- if (!strcmp(argv[1], "connect"))
- odbc_obj_connect(obj);
-
- if (!strcmp(argv[1], "disconnect"))
- odbc_obj_disconnect(obj);
- }
-
- } else if (!strcmp(argv[1], "show")) {
+ if (!strcmp(argv[1], "show")) {
if (!argv[2] || (argv[2] && !strcmp(argv[2], "all"))) {
for (x = 0; x < MAX_ODBC_HANDLES; x++) {
if (!ODBC_REGISTRY[x].used)
@@ -190,18 +180,62 @@ static int odbc_command(int fd, int argc, char **argv)
if (obj)
odbc_dump_fd(fd, obj);
}
+ }
+ return 0;
+}
- } else {
- return odbc_usage(fd);
+static int odbc_disconnect_command(int fd, int argc, char **argv){
+ odbc_obj *obj;
+ if (!strcmp(argv[1], "disconnect")) {
+ if (!argv[2])
+ return odbc_disconnect_usage(fd);
+
+ obj = odbc_read(ODBC_REGISTRY, argv[2]);
+ if (obj) {
+ odbc_obj_disconnect(obj);
+ }
}
- ast_cli(fd, "\n");
return 0;
}
-static struct ast_cli_entry odbc_command_struct = {
- {"odbc", NULL}, odbc_command,
- "Execute ODBC Command", "obdc <command> <arg1> .. <argn>", NULL
-};
+static int odbc_connect_command(int fd, int argc, char **argv){
+ odbc_obj *obj;
+ if (!argv[1])
+ return odbc_connect_usage(fd);
+
+ if (!strcmp(argv[1], "connect") || !strcmp(argv[1], "disconnect")) {
+ if (!argv[2])
+ return odbc_connect_usage(fd);
+
+ obj = odbc_read(ODBC_REGISTRY, argv[2]);
+ if (obj) {
+ odbc_obj_connect(obj);
+ }
+ }
+ return 0;
+}
+
+static char connect_usage[] =
+"Usage: odbc connect <DSN>\n"
+" Connect to ODBC DSN\n";
+
+static char disconnect_usage[] =
+"Usage: odbc connect <DSN>\n"
+" Disconnect from ODBC DSN\n";
+
+static char show_usage[] =
+"Usage: odbc show {DSN}\n"
+" Show ODBC {DSN}\n"
+" Specifying DSN will show that DSN else, all DSNs are shown\n";
+
+static struct ast_cli_entry odbc_connect_struct =
+ { { "odbc", "connect", NULL }, odbc_connect_command, "Connect to ODBC DSN", connect_usage };
+
+static struct ast_cli_entry odbc_disconnect_struct =
+ { { "odbc", "disconnect", NULL }, odbc_disconnect_command, "Disconnect from ODBC DSN", disconnect_usage };
+
+static struct ast_cli_entry odbc_show_struct =
+ { { "odbc", "show", NULL }, odbc_show_command, "Show ODBC DSN(s)", show_usage };
/* api calls */
@@ -222,6 +256,8 @@ odbc_obj *new_odbc_obj(char *name, char *dsn, char *username, char *password)
static odbc_obj *new;
new = malloc(sizeof(odbc_obj));
+ if (!new)
+ return NULL;
memset(new, 0, sizeof(odbc_obj));
new->env = SQL_NULL_HANDLE;
@@ -362,7 +398,9 @@ int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
odbc_destroy();
- ast_cli_unregister(&odbc_command_struct);
+ ast_cli_unregister(&odbc_disconnect_struct);
+ ast_cli_unregister(&odbc_connect_struct);
+ ast_cli_unregister(&odbc_show_struct);
ast_log(LOG_NOTICE, "res_odbc unloaded.\n");
return 0;
}
@@ -371,7 +409,9 @@ int load_module(void)
{
odbc_init();
load_odbc_config();
- ast_cli_register(&odbc_command_struct);
+ ast_cli_register(&odbc_disconnect_struct);
+ ast_cli_register(&odbc_connect_struct);
+ ast_cli_register(&odbc_show_struct);
ast_log(LOG_NOTICE, "res_odbc loaded.\n");
return 0;
}