Revision
15952
Author
anthm
Date
2009-12-14 14:10:06 -0600 (Mon, 14 Dec 2009)

Log Message

cleanup tab completion more and introduce new callback based expansion functions to do real time tab completion in some areas, needs people to add more funcs etc 

Modified Paths

Diff

Modified: freeswitch/trunk/src/include/switch_console.h (15951 => 15952)


--- freeswitch/trunk/src/include/switch_console.h	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/include/switch_console.h	2009-12-14 20:10:06 UTC (rev 15952)
@@ -76,6 +76,16 @@
 
 SWITCH_DECLARE(switch_status_t) switch_stream_write_file_contents(switch_stream_handle_t *stream, const char *path);
 
+
+SWITCH_DECLARE(switch_status_t) switch_console_init(switch_memory_pool_t *pool);
+SWITCH_DECLARE(switch_status_t) switch_console_shutdown(void);
+SWITCH_DECLARE(switch_status_t) switch_console_add_complete_func(const char *name, switch_console_complete_callback_t cb);
+SWITCH_DECLARE(switch_status_t) switch_console_del_complete_func(const char *name);
+SWITCH_DECLARE(switch_status_t) switch_console_run_complete_func(const char *func, const char *line, 
+																 const char *cursor, switch_console_callback_match_t **matches);
+SWITCH_DECLARE(void) switch_console_push_match(switch_console_callback_match_t **matches, const char *new_val);
+SWITCH_DECLARE(void) switch_console_free_matches(switch_console_callback_match_t **matches);
+
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:

Modified: freeswitch/trunk/src/include/switch_types.h (15951 => 15952)


--- freeswitch/trunk/src/include/switch_types.h	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/include/switch_types.h	2009-12-14 20:10:06 UTC (rev 15952)
@@ -1484,6 +1484,21 @@
 typedef struct switch_management_interface switch_management_interface_t;
 typedef struct switch_core_port_allocator switch_core_port_allocator_t;
 typedef struct switch_media_bug switch_media_bug_t;
+
+struct switch_console_callback_match_node {
+	char *val;
+	struct switch_console_callback_match_node *next;
+};
+typedef struct switch_console_callback_match_node switch_console_callback_match_node_t;
+
+struct switch_console_callback_match {
+	struct switch_console_callback_match_node *head;
+	struct switch_console_callback_match_node *end;
+	switch_memory_pool_t *pool;
+};
+typedef struct switch_console_callback_match switch_console_callback_match_t;
+
+typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
 typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
 typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);
 typedef struct switch_xml_binding switch_xml_binding_t;

Modified: freeswitch/trunk/src/include/switch_utils.h (15951 => 15952)


--- freeswitch/trunk/src/include/switch_utils.h	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/include/switch_utils.h	2009-12-14 20:10:06 UTC (rev 15952)
@@ -89,8 +89,12 @@
 	return SWITCH_TRUE;
 }
 
+#define switch_arraylen(_a) (sizeof(_a) / sizeof(_a[0]))
+#define switch_split(_data, _delim, _array) switch_separate_string(_data, _delim, _array, switch_arraylen(_array))
+
 #define switch_is_valid_rate(_tmp) (_tmp == 8000 || _tmp == 16000 || _tmp == 32000 || _tmp == 11025 || _tmp == 22050 || _tmp == 44100 || _tmp == 48000)
 
+
 static inline int switch_string_has_escaped_data(const char *in)
 {
 	const char *i = strchr(in, '\\');

Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c (15951 => 15952)


--- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -3784,140 +3784,163 @@
 
 	switch_thread_rwlock_create(&bgapi_rwlock, pool);
 
+	SWITCH_ADD_API(commands_api_interface, "acl", "compare an ip to an acl list", acl_function, "<ip> <list_name>");
+	SWITCH_ADD_API(commands_api_interface, "alias", "Alias", alias_function, ALIAS_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "bgapi", "Execute an api command in a thread", bgapi_function, "<command>[ <arg>]");
+	SWITCH_ADD_API(commands_api_interface, "bg_system", "Execute a system command in the background", bg_system_function, SYSTEM_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "break", "Break", break_function, BREAK_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "complete", "Complete", complete_function, COMPLETE_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "cond", "Eval a conditional", cond_function, "<expr> ? <true val> : <false val>");
+	SWITCH_ADD_API(commands_api_interface, "create_uuid", "Create a uuid", uuid_function, UUID_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "db_cache", "db cache management", db_cache_function, "status");
+	SWITCH_ADD_API(commands_api_interface, "domain_exists", "check if a domain exists", domain_exists_function, "<domain>");
+	SWITCH_ADD_API(commands_api_interface, "echo", "echo", echo_function, "<data>");
+	SWITCH_ADD_API(commands_api_interface, "escape", "escape a string", escape_function, "<data>");
+	SWITCH_ADD_API(commands_api_interface, "eval", "eval (noop)", eval_function, "[uuid:<uuid> ]<expression>");
+	SWITCH_ADD_API(commands_api_interface, "expand", "expand vars and execute", expand_function, "[uuid:<uuid> ]<cmd> <args>");
+	SWITCH_ADD_API(commands_api_interface, "find_user_xml", "find a user", find_user_function, "<key> <user> <domain>");
+	SWITCH_ADD_API(commands_api_interface, "fsctl", "control messages", ctl_function, CTL_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "global_getvar", "global_getvar", global_getvar_function, GLOBAL_GETVAR_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "global_setvar", "global_setvar", global_setvar_function, GLOBAL_SETVAR_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "group_call", "Generate a dial string to call a group", group_call_function, "<group>[@<domain>]");
+	SWITCH_ADD_API(commands_api_interface, "help", "Show help for all the api commands", help_function, "");
+	SWITCH_ADD_API(commands_api_interface, "host_lookup", "host_lookup", host_lookup_function, "<hostname>");
+	SWITCH_ADD_API(commands_api_interface, "hostname", "Returns the system hostname", hostname_api_function, "");
+	SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, "<cause> [<var> <value>]");
 	SWITCH_ADD_API(commands_api_interface, "in_group", "determine if a user is in a group", in_group_function, "<user>[@<domain>] <group_name>");
-
-	SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "<uuid>");
+	SWITCH_ADD_API(commands_api_interface, "is_lan_addr", "see if an ip is a lan addr", lan_addr_function, "<ip>");
+	SWITCH_ADD_API(commands_api_interface, "load", "Load Module", load_function, LOAD_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "md5", "md5", md5_function, "<data>");
-	SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, "<cause> [<var> <value>]");
-	SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [format string]");
+	SWITCH_ADD_API(commands_api_interface, "module_exists", "check if module exists", module_exists_function, "<module>");
+	SWITCH_ADD_API(commands_api_interface, "nat_map", "nat_map", nat_map_function, "[status|republish|reinit] | [add|del] <port> [tcp|udp] [static]");
 	SWITCH_ADD_API(commands_api_interface, "originate", "Originate a Call", originate_function, ORIGINATE_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "tone_detect", "Start Tone Detection on a channel", tone_detect_session_function, TONE_DETECT_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_preprocess", "Pre-process Channel", preprocess_function, PREPROCESS_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_park", "Park Channel", park_function, PARK_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "pause", "Pause", pause_function, PAUSE_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "<data>|<pattern>[|<subst string>]");
 	SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "[reloadxml]");
-	switch_console_set_complete("add reloadacl reloadxml");
+	SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
-	SWITCH_ADD_API(commands_api_interface, "unload", "Unload Module", unload_function, UNLOAD_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "load", "Load Module", load_function, LOAD_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "pause", "Pause", pause_function, PAUSE_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "break", "Break", break_function, BREAK_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, SCHED_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "sched_broadcast", "Schedule a broadcast event to a running call", sched_broadcast_function, SCHED_BROADCAST_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "sched_del", "Delete a Scheduled task", sched_del_function, "<task_id>|<group_id>");
+	SWITCH_ADD_API(commands_api_interface, "sched_hangup", "Schedule a running call to hangup", sched_hangup_function, SCHED_HANGUP_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "sched_transfer", "Schedule a transfer for a running call", sched_transfer_function, SCHED_TRANSFER_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "show", "Show", show_function, SHOW_SYNTAX);
-	switch_console_set_complete("add show channels");
-	switch_console_set_complete("add show codec");
-	switch_console_set_complete("add show application");
-	switch_console_set_complete("add show api");
-	switch_console_set_complete("add show dialplan");
-	switch_console_set_complete("add show file");
-	switch_console_set_complete("add show timer");
-	switch_console_set_complete("add show calls");
-	switch_console_set_complete("add show channels");
-	switch_console_set_complete("add show aliases");
-	switch_console_set_complete("add show complete");
-	switch_console_set_complete("add show distinct_channels");
-	switch_console_set_complete("add show chat");
-	switch_console_set_complete("add show endpoint");
-	switch_console_set_complete("add show management");
-	switch_console_set_complete("add show modules");
-	switch_console_set_complete("add show nat_map");
-	switch_console_set_complete("add nat_map status");
-	switch_console_set_complete("add nat_map republish");
-	switch_console_set_complete("add nat_map reinit");
-	switch_console_set_complete("add show say");
-	switch_console_set_complete("add show interfaces");
-	switch_console_set_complete("add show interface_types");
-	SWITCH_ADD_API(commands_api_interface, "complete", "Complete", complete_function, COMPLETE_SYNTAX);
-	switch_console_set_complete("add complete add");
-	switch_console_set_complete("add complete del");
-	SWITCH_ADD_API(commands_api_interface, "alias", "Alias", alias_function, ALIAS_SYNTAX);
-	switch_console_set_complete("add alias add");
-	switch_console_set_complete("add alias del");
 	SWITCH_ADD_API(commands_api_interface, "status", "status", status_function, "");
-	SWITCH_ADD_API(commands_api_interface, "uuid_session_heartbeat", "uuid_session_heartbeat", uuid_session_heartbeat_function, HEARTBEAT_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [format string]");
+	SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "<stun_server>[:port]");
+	SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "time_test", "time_test", time_test_function, "<mss>");
+	SWITCH_ADD_API(commands_api_interface, "tone_detect", "Start Tone Detection on a channel", tone_detect_session_function, TONE_DETECT_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "unload", "Unload Module", unload_function, UNLOAD_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "unsched_api", "Unschedule an api command", unsched_api_function, UNSCHED_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "url_decode", "url decode a string", url_decode_function, "<string>");
+	SWITCH_ADD_API(commands_api_interface, "url_encode", "url encode a string", url_encode_function, "<string>");
+	SWITCH_ADD_API(commands_api_interface, "user_data", "find user data", user_data_function, "<user>@<domain> [var|param|attr] <name>");
+	SWITCH_ADD_API(commands_api_interface, "user_exists", "find a user", user_exists_function, "<key> <user> <domain>");
 	SWITCH_ADD_API(commands_api_interface, "uuid_bridge", "uuid_bridge", uuid_bridge_function, "");
-	SWITCH_ADD_API(commands_api_interface, "uuid_setvar", "uuid_setvar", uuid_setvar_function, SETVAR_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_setvar_multi", "uuid_setvar_multi", uuid_setvar_multi_function, SETVAR_MULTI_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "broadcast", uuid_broadcast_function, BROADCAST_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_debug_audio", "debug audio", uuid_debug_audio_function, DEBUG_AUDIO_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_deflect", "Send a deflect", uuid_deflect, UUID_DEFLECT_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_displace", "session displace", session_displace_function, "<uuid> [start|stop] <path> [<limit>] [mux]");
+	SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "<uuid>");
 	SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "global_setvar", "global_setvar", global_setvar_function, GLOBAL_SETVAR_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "global_getvar", "global_getvar", global_getvar_function, GLOBAL_GETVAR_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_displace", "session displace", session_displace_function, "<uuid> [start|stop] <path> [<limit>] [mux]");
+	SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_media", "media", uuid_media_function, MEDIA_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_park", "Park Channel", park_function, PARK_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_preprocess", "Pre-process Channel", preprocess_function, PREPROCESS_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_record", "session record", session_record_function, SESS_REC_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "broadcast", uuid_broadcast_function, BROADCAST_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_recv_dtmf", "receive dtmf digits", uuid_recv_dtmf_function, UUID_RECV_DTMF_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_send_dtmf", "send dtmf digits", uuid_send_dtmf_function, UUID_SEND_DTMF_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_session_heartbeat", "uuid_session_heartbeat", uuid_session_heartbeat_function, HEARTBEAT_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_setvar_multi", "uuid_setvar_multi", uuid_setvar_multi_function, SETVAR_MULTI_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_setvar", "uuid_setvar", uuid_setvar_function, SETVAR_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_warning", "send popup", uuid_warning_function, WARNING_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_debug_audio", "debug audio", uuid_debug_audio_function, DEBUG_AUDIO_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_media", "media", uuid_media_function, MEDIA_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "fsctl", "control messages", ctl_function, CTL_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "version", "Show version of the switch", version_function, "");
+	SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
+	SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
+	switch_console_set_complete("add alias add");
+	switch_console_set_complete("add alias del");
+	switch_console_set_complete("add complete add");
+	switch_console_set_complete("add complete del");
+	switch_console_set_complete("add fsctl debug_level");
+	switch_console_set_complete("add fsctl default_dtmf_duration");
 	switch_console_set_complete("add fsctl hupall");
 	switch_console_set_complete("add fsctl loglevel");
-	switch_console_set_complete("add fsctl debug_level");
+	switch_console_set_complete("add fsctl max_dtmf_duration");
+	switch_console_set_complete("add fsctl max_sessions");
+	switch_console_set_complete("add fsctl min_dtmf_duration");
 	switch_console_set_complete("add fsctl pause");
+	switch_console_set_complete("add fsctl reclaim_mem");
 	switch_console_set_complete("add fsctl resume");
 	switch_console_set_complete("add fsctl shutdown");
-	switch_console_set_complete("add fsctl shutdown restart");
+	switch_console_set_complete("add fsctl shutdown asap");
+	switch_console_set_complete("add fsctl shutdown asap restart");
+	switch_console_set_complete("add fsctl shutdown cancel");
 	switch_console_set_complete("add fsctl shutdown elegant");
-	switch_console_set_complete("add fsctl shutdown asap");
 	switch_console_set_complete("add fsctl shutdown elegant restart");
+	switch_console_set_complete("add fsctl shutdown restart");
+	switch_console_set_complete("add fsctl shutdown restart asap");
 	switch_console_set_complete("add fsctl shutdown restart elegant");
-	switch_console_set_complete("add fsctl shutdown asap restart");
-	switch_console_set_complete("add fsctl shutdown restart asap");
-	switch_console_set_complete("add fsctl shutdown cancel");
 	switch_console_set_complete("add fsctl sps");
  	switch_console_set_complete("add fsctl sync_clock");
-	switch_console_set_complete("add fsctl reclaim_mem");
-	switch_console_set_complete("add fsctl max_sessions");
-	switch_console_set_complete("add fsctl max_dtmf_duration");
-	switch_console_set_complete("add fsctl min_dtmf_duration");
-	switch_console_set_complete("add fsctl default_dtmf_duration");
-	SWITCH_ADD_API(commands_api_interface, "help", "Show help for all the api commands", help_function, "");
-	SWITCH_ADD_API(commands_api_interface, "version", "Show version of the switch", version_function, "");
-	SWITCH_ADD_API(commands_api_interface, "sched_hangup", "Schedule a running call to hangup", sched_hangup_function, SCHED_HANGUP_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "sched_broadcast", "Schedule a broadcast event to a running call", sched_broadcast_function,
-				   SCHED_BROADCAST_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "sched_transfer", "Schedule a transfer for a running call", sched_transfer_function,
-				   SCHED_TRANSFER_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "create_uuid", "Create a uuid", uuid_function, UUID_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, SCHED_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "unsched_api", "Unschedule an api command", unsched_api_function, UNSCHED_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "bgapi", "Execute an api command in a thread", bgapi_function, "<command>[ <arg>]");
-	SWITCH_ADD_API(commands_api_interface, "sched_del", "Delete a Scheduled task", sched_del_function, "<task_id>|<group_id>");
-	SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
-	SWITCH_ADD_API(commands_api_interface, "is_lan_addr", "see if an ip is a lan addr", lan_addr_function, "<ip>");
-	SWITCH_ADD_API(commands_api_interface, "cond", "Eval a conditional", cond_function, "<expr> ? <true val> : <false val>");
-	SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "<data>|<pattern>[|<subst string>]");
-	SWITCH_ADD_API(commands_api_interface, "acl", "compare an ip to an acl list", acl_function, "<ip> <list_name>");
-	SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_deflect", "Send a deflect", uuid_deflect, UUID_DEFLECT_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "find_user_xml", "find a user", find_user_function, "<key> <user> <domain>");
-	SWITCH_ADD_API(commands_api_interface, "user_exists", "find a user", user_exists_function, "<key> <user> <domain>");
-	SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
-	SWITCH_ADD_API(commands_api_interface, "user_data", "find user data", user_data_function, "<user>@<domain> [var|param|attr] <name>");
-	SWITCH_ADD_API(commands_api_interface, "url_encode", "url encode a string", url_encode_function, "<string>");
-	SWITCH_ADD_API(commands_api_interface, "url_decode", "url decode a string", url_decode_function, "<string>");
-	SWITCH_ADD_API(commands_api_interface, "module_exists", "check if module exists", module_exists_function, "<module>");
-	SWITCH_ADD_API(commands_api_interface, "domain_exists", "check if a domain exists", domain_exists_function, "<domain>");
-	SWITCH_ADD_API(commands_api_interface, "uuid_send_dtmf", "send dtmf digits", uuid_send_dtmf_function, UUID_SEND_DTMF_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "uuid_recv_dtmf", "receive dtmf digits", uuid_recv_dtmf_function, UUID_RECV_DTMF_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "eval", "eval (noop)", eval_function, "[uuid:<uuid> ]<expression>");
-	SWITCH_ADD_API(commands_api_interface, "expand", "expand vars and execute", expand_function, "[uuid:<uuid> ]<cmd> <args>");
-	SWITCH_ADD_API(commands_api_interface, "echo", "echo", echo_function, "<data>");
-	SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "<stun_server>[:port]");
-	SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "bg_system", "Execute a system command in the background", bg_system_function, SYSTEM_SYNTAX);
-	SWITCH_ADD_API(commands_api_interface, "time_test", "time_test", time_test_function, "<mss>");
-	SWITCH_ADD_API(commands_api_interface, "nat_map", "nat_map", nat_map_function, "[status|republish|reinit] | [add|del] <port> [tcp|udp] [static]");
-	SWITCH_ADD_API(commands_api_interface, "host_lookup", "host_lookup", host_lookup_function, "<hostname>");
-	SWITCH_ADD_API(commands_api_interface, "hostname", "Returns the system hostname", hostname_api_function, "");
-	SWITCH_ADD_API(commands_api_interface, "db_cache", "db cache management", db_cache_function, "status");
-	SWITCH_ADD_API(commands_api_interface, "escape", "escape a string", escape_function, "<data>");
+	switch_console_set_complete("add nat_map reinit");
+	switch_console_set_complete("add nat_map republish");
+	switch_console_set_complete("add nat_map status");
+	switch_console_set_complete("add reloadacl reloadxml");
+	switch_console_set_complete("add show aliases");
+	switch_console_set_complete("add show api");
+	switch_console_set_complete("add show application");
+	switch_console_set_complete("add show calls");
+	switch_console_set_complete("add show channels");
+	switch_console_set_complete("add show channels");
+	switch_console_set_complete("add show chat");
+	switch_console_set_complete("add show codec");
+	switch_console_set_complete("add show complete");
+	switch_console_set_complete("add show dialplan");
+	switch_console_set_complete("add show distinct_channels");
+	switch_console_set_complete("add show endpoint");
+	switch_console_set_complete("add show file");
+	switch_console_set_complete("add show interfaces");
+	switch_console_set_complete("add show interface_types");
+	switch_console_set_complete("add show management");
+	switch_console_set_complete("add show modules");
+	switch_console_set_complete("add show nat_map");
+	switch_console_set_complete("add show say");
+	switch_console_set_complete("add show timer");
+	switch_console_set_complete("add uuid_bridge ::console::list_uuid ::console::list_uuid");
+	switch_console_set_complete("add uuid_broadcast ::console::list_uuid");
+	switch_console_set_complete("add uuid_chat ::console::list_uuid");
+	switch_console_set_complete("add uuid_debug_audio ::console::list_uuid");
+	switch_console_set_complete("add uuid_deflect ::console::list_uuid");
+	switch_console_set_complete("add uuid_displace ::console::list_uuid");
+	switch_console_set_complete("add uuid_display ::console::list_uuid");
+	switch_console_set_complete("add uuid_dump ::console::list_uuid");
+	switch_console_set_complete("add uuid_exists ::console::list_uuid");
+	switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
+	switch_console_set_complete("add uuid_getvar ::console::list_uuid");
+	switch_console_set_complete("add uuid_hold ::console::list_uuid");
+	switch_console_set_complete("add uuid_kill ::console::list_uuid");
+	switch_console_set_complete("add uuid_media ::console::list_uuid");
+	switch_console_set_complete("add uuid_park ::console::list_uuid");
+	switch_console_set_complete("add uuid_preprocess ::console::list_uuid");
+	switch_console_set_complete("add uuid_record ::console::list_uuid");
+	switch_console_set_complete("add uuid_recv_dtmf ::console::list_uuid");
+	switch_console_set_complete("add uuid_send_dtmf ::console::list_uuid");
+	switch_console_set_complete("add uuid_session_heartbeat ::console::list_uuid");
+	switch_console_set_complete("add uuid_setvar_multi ::console::list_uuid");
+	switch_console_set_complete("add uuid_setvar ::console::list_uuid");
+	switch_console_set_complete("add uuid_transfer ::console::list_uuid");
+	switch_console_set_complete("add uuid_warning ::console::list_uuid");
 	switch_console_set_complete("db_cache status");
 
+
+
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_NOUNLOAD;
 }

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (15951 => 15952)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -3623,6 +3623,105 @@
 	}
 }
 
+static switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+	sofia_profile_t *profile = NULL;
+	switch_hash_index_t *hi;
+	void *val;
+	const void *vvar;
+	switch_console_callback_match_t *my_matches = NULL;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	switch_mutex_lock(mod_sofia_globals.hash_mutex);
+	for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+		switch_hash_this(hi, &vvar, NULL, &val);
+		profile = (sofia_profile_t *) val;
+		if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
+			switch_console_push_match(&my_matches, (const char *)vvar);
+		}
+	}
+	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+
+	if (my_matches) {
+		*matches = my_matches;
+		status = SWITCH_STATUS_SUCCESS;
+	}
+
+
+	return status;
+}
+
+static switch_status_t list_gateways(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+	sofia_profile_t *profile = NULL;
+	switch_hash_index_t *hi;
+	void *val;
+	const void *vvar;
+	switch_console_callback_match_t *my_matches = NULL;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	switch_mutex_lock(mod_sofia_globals.hash_mutex);
+	for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+		switch_hash_this(hi, &vvar, NULL, &val);
+		profile = (sofia_profile_t *) val;
+		if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
+			sofia_gateway_t *gp;
+			for (gp = profile->gateways; gp; gp = gp->next) {
+				switch_console_push_match(&my_matches, gp->name);
+			}
+		}
+	}
+	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+
+	if (my_matches) {
+		*matches = my_matches;
+		status = SWITCH_STATUS_SUCCESS;
+	}
+	
+	return status;
+}
+
+
+static switch_status_t list_profile_gateway(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+	sofia_profile_t *profile = NULL;
+	switch_console_callback_match_t *my_matches = NULL;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	char *dup = NULL;
+	int argc;
+	char *argv[4] = { 0 };
+
+	if (zstr(line)) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	dup = strdup(line);
+	argc = switch_split(dup, ' ', argv);
+	
+	if (!argv[2]) {
+		goto end;
+	}
+
+	if ((profile = sofia_glue_find_profile(argv[2]))) {
+		sofia_gateway_t *gp;
+		for (gp = profile->gateways; gp; gp = gp->next) {
+			switch_console_push_match(&my_matches, gp->name);
+		}
+		sofia_glue_release_profile(profile);
+	}
+
+	if (my_matches) {
+		*matches = my_matches;
+		status = SWITCH_STATUS_SUCCESS;
+	}
+	
+ end:
+
+	switch_safe_free(dup);
+
+	return status;
+}
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
 {
 	switch_chat_interface_t *chat_interface;
@@ -3744,18 +3843,26 @@
 	switch_console_set_complete("add sofia profile");
 	switch_console_set_complete("add sofia profile restart all");
 
-	switch_console_set_complete("add sofia profile _any_ start reloadxml");
-	switch_console_set_complete("add sofia profile _any_ stop reloadxml");
-	switch_console_set_complete("add sofia profile _any_ rescan reloadxml");
-	switch_console_set_complete("add sofia profile _any_ restart reloadxml");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles start reloadxml");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles stop reloadxml");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan reloadxml");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles restart reloadxml");
 
-	switch_console_set_complete("add sofia profile _any_ flush_inbound_reg");
-	switch_console_set_complete("add sofia profile _any_ register");
-	switch_console_set_complete("add sofia profile _any_ killgw");
-	switch_console_set_complete("add sofia profile _any_ siptrace on");
-	switch_console_set_complete("add sofia profile _any_ siptrace off");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles register ::sofia::list_profile_gateway");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles unregister ::sofia::list_profile_gateway");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles killgw ::sofia::list_profile_gateway");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles siptrace on");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles siptrace off");
 
+	switch_console_set_complete("add sofia status profile ::sofia::list_profiles");
+	switch_console_set_complete("add sofia status gateway ::sofia::list_gateways");
 
+	switch_console_add_complete_func("::sofia::list_profiles", list_profiles);
+	switch_console_add_complete_func("::sofia::list_gateways", list_gateways);
+	switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
+
+
 	SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
 	SWITCH_ADD_CHAT(chat_interface, SOFIA_CHAT_PROTO, sofia_presence_chat_send);
 
@@ -3767,6 +3874,7 @@
 {
 	int sanity = 0;
 
+	switch_console_del_complete_func("::sofia::list_profiles");
 	switch_console_set_complete("del sofia");
 
 	switch_mutex_lock(mod_sofia_globals.mutex);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (15951 => 15952)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -1063,8 +1063,6 @@
 	int sanity;
 	switch_thread_t *worker_thread;
 	switch_status_t st;
-	char cbuf[512] = "";
-	
 
 	switch_mutex_lock(mod_sofia_globals.mutex);
 	mod_sofia_globals.threads++;
@@ -1229,17 +1227,11 @@
 
 	switch_yield(1000000);
 
-	switch_snprintf(cbuf, sizeof(cbuf), "add sofia profile %s", profile->name);
-	switch_console_set_complete(cbuf);
 
-
 	while (mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING) && sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) {
 		su_root_step(profile->s_root, 1000);
 	}
 
-	switch_snprintf(cbuf, sizeof(cbuf), "del sofia profile %s", profile->name);
-	switch_console_set_complete(cbuf);
-
 	sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
 
 	switch_core_session_hupall_matching_var("sofia_profile_name", profile->name, SWITCH_CAUSE_MANAGER_REQUEST);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (15951 => 15952)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -3647,12 +3647,10 @@
 switch_status_t sofia_glue_add_profile(char *key, sofia_profile_t *profile)
 {
 	switch_status_t status = SWITCH_STATUS_FALSE;
-	char cbuf[512] = "";
+
 	switch_mutex_lock(mod_sofia_globals.hash_mutex);
 	if (!switch_core_hash_find(mod_sofia_globals.profile_hash, key)) {
 		status = switch_core_hash_insert(mod_sofia_globals.profile_hash, key, profile);
-		switch_snprintf(cbuf, sizeof(cbuf), "add sofia profile %s", key);
-		switch_console_set_complete(cbuf);
 	}
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 
@@ -3721,7 +3719,6 @@
 	const void *var;
 	void *val;
 	sofia_profile_t *pptr;
-	char cbuf[512] = "";
 	
 	switch_mutex_lock(mod_sofia_globals.hash_mutex);
 	if (mod_sofia_globals.profile_hash) {
@@ -3729,8 +3726,6 @@
 			switch_hash_this(hi, &var, NULL, &val);
 			if ((pptr = (sofia_profile_t *) val) && pptr == profile) {
 				aliases[i++] = strdup((char *) var);
-				switch_snprintf(cbuf, sizeof(cbuf), "del sofia profile %s", var);
-				switch_console_set_complete(cbuf);
 				if (i == 512) {
 					abort();
 				}

Modified: freeswitch/trunk/src/switch_console.c (15951 => 15952)


--- freeswitch/trunk/src/switch_console.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/switch_console.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -518,16 +518,42 @@
 static int comp_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
 	struct helper *h = (struct helper *) pArg;
-	char *target = NULL;
+	char *target = NULL, *str = NULL, *cur = NULL;
 	switch_size_t x, y;
 	int i;
 	
-	target = argv[0];
+	if (argc > 0) target = argv[0];
+	if (argc > 1) str = argv[1];
+	if (argc > 2) cur = argv[2];
 
+	if (cur) {
+		while (*cur == ' ') cur++;
+	}
+
+	if (zstr(cur)) cur = NULL;
+	if (zstr(str)) str = NULL;
+
 	if (!target) {
 		return -1;
 	}
 
+	if (!zstr(target) && *target == ':' && *(target+1) == ':') {
+		char *r_argv[3] = { 0 }, *r_cols[3] = { 0 };
+		switch_console_callback_match_t *matches;
+		r_cols[0] = "match";
+		if (switch_console_run_complete_func(target, str, cur, &matches) == SWITCH_STATUS_SUCCESS) {
+			switch_console_callback_match_node_t *m;
+			for (m = matches->head; m; m = m->next) {
+				if (!cur || !strncmp(m->val, cur, strlen(cur))) {
+					r_argv[0] = m->val;
+					comp_callback(h, 1, r_argv, r_cols);
+				}
+			}
+			switch_console_free_matches(&matches);
+		}
+		return 0;
+	}
+
 	if (!zstr(target)) {
 		fprintf(h->out, "[%20s]\t", target);
 		switch_copy_string(h->last, target, sizeof(h->last));
@@ -557,6 +583,54 @@
 	return 0;
 }
 
+
+
+struct match_helper {
+	switch_console_callback_match_t *my_matches;
+};
+
+static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+	struct match_helper *h = (struct match_helper *) pArg;
+
+	switch_console_push_match(&h->my_matches, argv[0]);
+	return 0;
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_console_list_uuid(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+	char *sql;
+	struct match_helper h = { 0 };
+	switch_cache_db_handle_t *db = NULL;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	char *errmsg;
+	
+	switch_core_db_handle(&db);
+
+	if (!zstr(cursor)) {
+		sql = switch_mprintf("select distinct uuid from channels where uuid like '%q%%' and hostname='%q' order by uuid", 
+							 cursor, switch_core_get_variable("hostname"));
+	} else {
+		sql = switch_mprintf("select distinct uuid from channels where hostname='%q' order by uuid", 
+							 switch_core_get_variable("hostname"));
+	}
+
+	switch_cache_db_execute_sql_callback(db, sql, uuid_callback, &h, &errmsg);
+	free(sql);
+
+	switch_cache_db_release_db_handle(&db);
+
+	if (h.my_matches) {
+		*matches = h.my_matches;
+		status = SWITCH_STATUS_SUCCESS;
+	}
+
+
+	return status;
+}
+
+
 static unsigned char complete(EditLine * el, int ch)
 {
 	switch_cache_db_handle_t *db = NULL;
@@ -608,11 +682,8 @@
 	if (h.words == 0) {
 		sql = switch_mprintf("select distinct name from interfaces where type='api' and name like '%q%%' and hostname='%q' order by name", 
 							 buf, switch_core_get_variable("hostname"));
-	} else if (h.words == 1) {
-		sql = switch_mprintf("select distinct uuid from channels where uuid like '%q%%' and hostname='%q' order by uuid", 
-							 buf, switch_core_get_variable("hostname"));
 	}
-
+	
 	if (sql) {
 		switch_cache_db_execute_sql_callback(db, sql, comp_callback, &h, &errmsg);
 
@@ -640,22 +711,29 @@
 			stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%s') %s ", 
 								  switch_core_get_variable("hostname"), argc ? "and" : "");
 		} else {
-			stream.write_function(&stream, "select distinct a%d from complete where ", h.words + 1);
-
+			if (db->type == SCDB_TYPE_CORE_DB) {
+				stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
+			} else {
+				stream.write_function(&stream, "select distinct a%d,'%q','%w' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
+			}
 		}
 
 		for (x = 0; x < argc && x < 11; x++) {
 			if (h.words + 1 > argc) {
 				if (db->type == SCDB_TYPE_CORE_DB) {
-					stream.write_function(&stream, "(a%d = '' or a%d = '%q')%q", x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
+					stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%q')%q", 
+										  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
 				} else {
-					stream.write_function(&stream, "(a%d = '' or a%d = '%w')%w", x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
+					stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%w')%w", 
+										  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
 				}
 			} else {
 				if (db->type == SCDB_TYPE_CORE_DB) {
-					stream.write_function(&stream, "(a%d = '' or a%d like '%q%%')%q", x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
+					stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%q%%')%q",
+										  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
 				} else {
-					stream.write_function(&stream, "(a%d = '' or a%d like '%w%%')%w", x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
+					stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%w%%')%w",
+										  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
 				}
 			}
 		}
@@ -700,7 +778,99 @@
 	return (ret);
 }
 
+static struct {
+	switch_hash_t *func_hash;
+	switch_mutex_t *func_mutex;
+} globals;
 
+SWITCH_DECLARE(switch_status_t) switch_console_init(switch_memory_pool_t *pool)
+{
+	switch_mutex_init(&globals.func_mutex, SWITCH_MUTEX_NESTED, pool);
+	switch_core_hash_init(&globals.func_hash, pool);
+	switch_console_add_complete_func("::console::list_uuid", switch_console_list_uuid);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_console_shutdown(void)
+{
+	return switch_core_hash_destroy(&globals.func_hash);
+}
+
+SWITCH_DECLARE(switch_status_t) switch_console_add_complete_func(const char *name, switch_console_complete_callback_t cb)
+{
+	switch_status_t status;
+	
+	switch_mutex_lock(globals.func_mutex);
+	status = switch_core_hash_insert(globals.func_hash, name, (void *)(intptr_t)cb);
+	switch_mutex_unlock(globals.func_mutex);
+
+	return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_console_del_complete_func(const char *name)
+{
+	switch_status_t status;
+	
+	switch_mutex_lock(globals.func_mutex);
+	status = switch_core_hash_insert(globals.func_hash, name, NULL);
+	switch_mutex_unlock(globals.func_mutex);
+
+    return status;
+}
+
+SWITCH_DECLARE(void) switch_console_free_matches(switch_console_callback_match_t **matches)
+{
+	switch_console_callback_match_t *my_match = *matches;
+	switch_console_callback_match_node_t *m, *cur;
+
+	/* Don't play with matches */
+	*matches = NULL;
+
+	m = my_match->head;
+	while(m) {
+		cur = m;
+		m = m->next;
+		free(cur->val);
+		free(cur);
+	}
+}
+
+SWITCH_DECLARE(void) switch_console_push_match(switch_console_callback_match_t **matches, const char *new_val)
+{
+	switch_console_callback_match_node_t *match;
+
+	if (!*matches) {
+		switch_zmalloc(*matches, sizeof(**matches));
+	}
+
+	switch_zmalloc(match, sizeof(*match));
+	match->val = strdup(new_val);
+
+	if ((*matches)->head) {
+		(*matches)->end->next = match;
+	} else {
+		(*matches)->head = match;
+	}
+
+	(*matches)->end = match;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_console_run_complete_func(const char *func, const char *line, const char *cursor,
+																 switch_console_callback_match_t **matches)
+{
+	switch_console_complete_callback_t cb;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	switch_mutex_lock(globals.func_mutex);
+	if ((cb = (switch_console_complete_callback_t)(intptr_t)switch_core_hash_find(globals.func_hash, func))) {
+		status = cb(line, cursor, matches);
+	}
+	switch_mutex_unlock(globals.func_mutex);
+
+	return status;
+}
+
+
 SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
 {
 	char *mydata = NULL, *argv[11] = { 0 };

Modified: freeswitch/trunk/src/switch_core.c (15951 => 15952)


--- freeswitch/trunk/src/switch_core.c	2009-12-14 20:10:01 UTC (rev 15951)
+++ freeswitch/trunk/src/switch_core.c	2009-12-14 20:10:06 UTC (rev 15952)
@@ -1249,6 +1249,7 @@
 	switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
 	switch_core_set_serial();
 
+	switch_console_init(runtime.memory_pool);
 	switch_event_init(runtime.memory_pool);
 
 	if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
@@ -1741,6 +1742,8 @@
 	}
 	switch_xml_destroy();
 
+	switch_console_shutdown();
+
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");
 	switch_event_shutdown();