diff options
Diffstat (limited to 'res')
-rwxr-xr-x | res/res_adsi.c | 2 | ||||
-rwxr-xr-x | res/res_agi.c | 27 | ||||
-rwxr-xr-x | res/res_config_odbc.c | 2 | ||||
-rwxr-xr-x | res/res_crypto.c | 3 | ||||
-rwxr-xr-x | res/res_features.c | 104 | ||||
-rwxr-xr-x | res/res_indications.c | 15 | ||||
-rwxr-xr-x | res/res_monitor.c | 96 | ||||
-rwxr-xr-x | res/res_musiconhold.c | 10 | ||||
-rwxr-xr-x | res/res_odbc.c | 112 |
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; } |