Index: asterisk/apps/app_queue.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v
retrieving revision 1.4
diff -u -r1.4 app_queue.c
--- asterisk/apps/app_queue.c	19 May 2003 01:07:06 -0000	1.4
+++ asterisk/apps/app_queue.c	26 Jun 2003 16:35:18 -0000
@@ -35,6 +35,8 @@
 #include <sys/signal.h>
 #include <netinet/in.h>
 
+#include <tonezone.h>
+
 #include <pthread.h>
 
 #define DEFAULT_RETRY		5
@@ -63,6 +65,28 @@
 "  The optionnal URL will be sent to the called party if the channel supports\n"
 "it.\n";
 
+// [PHM 06/26/03]
+static char *app_aqm = "AddQueueMember" ;
+static char *app_aqm_synopsis = "Dynamically adds queue members" ;
+static char *app_aqm_descrip =
+"   AddQueueMember(queuename[|interface]):\n"
+"Dynamically adds interface to an existing queue\n"
+"Returns -1 if there is an error.\n"
+"Example: AddQueueMember(techsupport|SIP/3000)\n"
+"";
+
+static char *app_rqm = "RemoveQueueMember" ;
+static char *app_rqm_synopsis = "Dynamically removes queue members" ;
+static char *app_rqm_descrip =
+"   RemoveQueueMember(queuename[|interface]):\n"
+"Dynamically removes interface to an existing queue\n"
+"Returns -1 if there is an error.\n"
+"Example: RemoveQueueMember(techsupport|SIP/3000)\n"
+"";
+
+
+
+
 /* We define a customer "local user" structure because we
    use it not only for keeping track of what is in use but
    also for keeping track of who we're dialing. */
@@ -158,7 +182,9 @@
 				manager_event(EVENT_FLAG_CALL, "Join", 
 							 	"Channel: %s\r\nQueue: %s\r\nPosition: %d\r\n",
 								qe->chan->name, q->name, qe->pos );
-
+#if 1
+ast_log(LOG_NOTICE, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
+#endif
 			}
 			ast_pthread_mutex_unlock(&q->lock);
 			break;
@@ -211,15 +237,20 @@
 	if (!q)
 		return;
 	ast_pthread_mutex_lock(&q->lock);
-	/* Take us out of the queue */
-	manager_event(EVENT_FLAG_CALL, "Leave",
-						 "Channel: %s\r\nQueue: %s\r\n", 
-						 qe->chan->name, q->name );
+
 	prev = NULL;
 	cur = q->head;
 	while(cur) {
 		if (cur == qe) {
 			q->count--;
+
+			/* Take us out of the queue */
+			manager_event(EVENT_FLAG_CALL, "Leave",
+				 "Channel: %s\r\nQueue: %s\r\n", 
+				 qe->chan->name, q->name );
+#if 1
+ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
+#endif
 			/* Take us out of the queue */
 			if (prev)
 				prev->next = cur->next;
@@ -636,6 +667,217 @@
 	return 0;
 }
 
+// [PHM 06/26/03]
+
+static struct member * interface_exists( struct ast_call_queue * q, char * interface )
+{
+	struct member * ret = NULL ;
+	struct member *mem;
+	char buf[500] ;
+
+	if( q != NULL )
+	{
+		mem = q->members ;
+
+		while( mem != NULL ) {
+			sprintf( buf, "%s/%s", mem->tech, mem->loc);
+
+			if( strcmp( buf, interface ) == 0 ) {
+				ret = mem ;
+				break ;
+			}
+			else
+				mem = mem->next ;
+		}
+	}
+
+	return( ret ) ;
+}
+
+
+static struct member * create_queue_node( char * interface )
+{
+	struct member * cur ;
+	char * tmp ;
+	
+	/* Add a new member */
+
+	cur = malloc(sizeof(struct member));
+
+	if (cur) {
+		memset(cur, 0, sizeof(struct member));
+		strncpy(cur->tech, interface, sizeof(cur->tech) - 1);
+		if ((tmp = strchr(cur->tech, '/')))
+			*tmp = '\0';
+		if ((tmp = strchr(interface, '/'))) {
+			tmp++;
+			strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
+		} else
+			ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
+	}
+
+	return( cur ) ;
+}
+
+
+static int rqm_exec(struct ast_channel *chan, void *data)
+{
+	int res=-1;
+	struct localuser *u;
+	char *queuename;
+	struct member * node ;
+	struct member * look ;
+	char info[512];
+	char *interface=NULL;
+	struct ast_call_queue *q;
+	int found=0 ;
+
+	if (!data) {
+		ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename|optional interface)\n");
+		return -1;
+	}
+	
+	LOCAL_USER_ADD(u); // not sure if we need this, but better be safe than sorry ;-)
+	
+	/* Parse our arguments XXX Check for failure XXX */
+	strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
+	queuename = info;
+	if (queuename) {
+		interface = strchr(queuename, '|');
+		if (interface) {
+			*interface = '\0';
+			interface++;
+		}
+		else
+			interface = chan->name ;
+	}
+
+	if( ( q = queues) != NULL )
+	{
+		while( q && ( res != 0 ) && (!found) ) 
+		{
+			ast_pthread_mutex_lock(&q->lock);
+			if( strcmp( q->name, queuename) == 0 )
+			{
+				// found queue, try to remove  interface
+				found=1 ;
+
+				if( ( node = interface_exists( q, interface ) ) != NULL )
+				{
+					if( ( look = q->members ) == node )
+					{
+						// 1st
+						q->members = node->next;
+					}
+					else
+					{
+						while( look != NULL )
+							if( look->next == node )
+							{
+								look->next = node->next ;
+								break ;
+							}
+							else
+								look = look->next ;
+					}
+
+					free( node ) ;
+
+					ast_log(LOG_NOTICE, "Removed interface '%s' to queue '%s'\n", 
+						interface, queuename);
+					res = 0 ;
+				}
+				else
+					ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': "
+						"Not there\n", interface, queuename);
+			}
+
+			ast_pthread_mutex_unlock(&q->lock);
+			q = q->next;
+		}
+	}
+
+	if( ! found )
+		ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", queuename);
+
+	LOCAL_USER_REMOVE(u);
+	return res;
+}
+
+
+
+static int aqm_exec(struct ast_channel *chan, void *data)
+{
+	int res=-1;
+	struct localuser *u;
+	char *queuename;
+	char info[512];
+	char *interface=NULL;
+	struct ast_call_queue *q;
+	struct member *save;
+	int found=0 ;
+
+	if (!data) {
+		ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename|optional interface)\n");
+		return -1;
+	}
+	
+	LOCAL_USER_ADD(u); // not sure if we need this, but better be safe than sorry ;-)
+	
+	/* Parse our arguments XXX Check for failure XXX */
+	strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
+	queuename = info;
+	if (queuename) {
+		interface = strchr(queuename, '|');
+		if (interface) {
+			*interface = '\0';
+			interface++;
+		}
+		else
+			interface = chan->name ;
+	}
+
+	if( ( q = queues) != NULL )
+	{
+		while( q && ( res != 0 ) && (!found) ) 
+		{
+			ast_pthread_mutex_lock(&q->lock);
+			if( strcmp( q->name, queuename) == 0 )
+			{
+				// found queue, try to enable interface
+				found=1 ;
+
+				if( interface_exists( q, interface ) == NULL )
+				{
+					save = q->members ;
+					q->members = create_queue_node( interface ) ;
+
+					if( q->members != NULL )
+						q->members->next = save ;
+					else
+						q->members = save ;
+
+					ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
+					res = 0 ;
+				}
+				else
+					ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': "
+						"Already there\n", interface, queuename);
+			}
+
+			ast_pthread_mutex_unlock(&q->lock);
+			q = q->next;
+		}
+	}
+
+	if( ! found )
+		ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", queuename);
+
+	LOCAL_USER_REMOVE(u);
+	return res;
+}
+
+
 static int queue_exec(struct ast_channel *chan, void *data)
 {
 	int res=-1;
@@ -936,10 +1178,15 @@
 	if (!res) {
 		ast_cli_register(&cli_show_queues);
 		ast_manager_register( "Queues", 0, manager_queues_show, "Queues" );
+
+		// [PHM 06/26/03]
+		ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip) ;
+		ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip) ;
 	}
 	reload_queues();
 	return res;
 }
+
 
 int reload(void)
 {
