--- clean_asterisk/pbx/pbx_spool.c	2003-10-01 17:01:31.000000000 -0400
+++ asterisk/pbx/pbx_spool.c	2003-12-05 16:30:09.000000000 -0500
@@ -30,17 +30,35 @@
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <asterisk/cli.h>
 #include "../astconf.h"
 
+#define CALL_HASH_TABLE_KEY_SIZE 256
+
+
+#define STATE_SLEEP 1
+#define STATE_FAILED 2
+#define STATE_TRYING 3
+#define STATE_COMPLETE 4
+#define STATE_READY 5
+#define STATE_EXPIRED 6
+
+
+
 /*
  * pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality...
  * The spool file contains a header 
  */
 
+static ast_mutex_t call_lock = AST_MUTEX_INITIALIZER;
+
 static char *tdesc = "Outgoing Spool Support";
 static char qdir[255];
 
 struct outgoing {
+
+	time_t added;
+
 	char fn[256];
 	/* Current number of retries */
 	int retries;
@@ -48,6 +66,21 @@
 	int maxretries;
 	/* How long to wait between retries (in seconds) */
 	int retrytime;
+
+	/* How long to wait after a failure (in seconds) */
+	int failretry;
+
+
+	/* when was cached file last modified */
+	time_t mtime;
+
+	/* waht state am in in */
+	int state;
+
+  
+	/* when did we call */
+	time_t attempt_time;
+
 	/* How long to wait for an answer */
 	int waittime;
 	
@@ -74,19 +107,381 @@
 	
 	/* Maximum length of call */
 	int maxlen;
-	
+
 };
 
-static void init_outgoing(struct outgoing *o)
+
+static unsigned long ElfHash ( const unsigned char *name )
 {
+	unsigned long   h = 0, g;
+	while ( *name )
+		{
+			h = ( h << 4 ) + *name++;
+			if (( g = h & 0xF0000000 ))
+				h ^= g >> 24;
+			h &= ~g;
+		}
+	return h;
+}
+
+
+struct hash_storage {
+	char *name;
+	struct outgoing *outgoing;
+	struct hash_storage *next;
+};
+
+struct call_hash_table {
+	char name[100];
+	struct hash_storage *data[CALL_HASH_TABLE_KEY_SIZE];
+	struct call_hash_table *next;
+};
+
+
+static struct hash_storage *init_hash_storage(void) {
+	struct hash_storage *new_store = malloc(sizeof(struct hash_storage));
+	memset(new_store,0,sizeof(struct hash_storage));
+	return new_store;
+}
+
+static struct call_hash_table *init_call_hash(char *name) {
+	struct call_hash_table *newhash = malloc(sizeof(struct call_hash_table));
+	memset(newhash,0,sizeof(struct call_hash_table));
+
+	strncpy(newhash->name,name,sizeof(newhash->name));
+	int key;
+	for(key=0;key<=CALL_HASH_TABLE_KEY_SIZE;key++) {
+		newhash->data[key] = (struct hash_storage *) init_hash_storage();
+	}
+  
+	return newhash;
+
+}
+
+
+
+
+
+static int call_hash_write(struct call_hash_table *hash,char *name,struct outgoing *value) {
+	struct hash_storage *store,*last;
+	unsigned long key = ElfHash(name) & CALL_HASH_TABLE_KEY_SIZE;
+	int ow = 0;
+	store=last=NULL;
+  
+	if(! name || ! strlen(name) || ! value || ! value->fn)
+		return 0;
+  
+	ast_mutex_lock(&call_lock);
+
+
+	store = hash->data[key];
+	while(store) {
+		if(store->name && !strcmp(store->name,name))
+			break;
+    
+		last=store;
+		store=store->next;
+	}
+
+	if(store)
+		ow=1;
+
+	store = (struct hash_storage *) init_hash_storage();
+	store->name = malloc(strlen(name)+1);
+	strcpy(store->name,name);
+	store->outgoing = malloc(sizeof(struct outgoing));
+	memset(store->outgoing, 0, sizeof(struct outgoing));
+	*store->outgoing = *value;
+  
+
+	if(! ow) {
+		if(last) 
+			last->next = store;
+		else 
+			hash->data[key] = store;
+	}
+
+	ast_mutex_unlock(&call_lock);
+	return key;
+}
+
+
+static struct outgoing *call_hash_read(struct call_hash_table *hash,char *name) {
+	unsigned long key = ElfHash(name) & CALL_HASH_TABLE_KEY_SIZE;
+	struct hash_storage *store;
+
+	ast_mutex_lock(&call_lock);
+
+	store = hash->data[key];
+	if(store) {
+
+		if(! store->next) {
+			ast_mutex_unlock(&call_lock);
+			return store->outgoing;
+		}
+		else {
+			store = store->next;
+			while(store) {
+				if(name && store->name && !strcmp(name,store->name)) {
+					ast_mutex_unlock(&call_lock);
+					return store->outgoing;
+				}
+				store = store->next;
+			}
+		}
+	}
+  
+	ast_mutex_unlock(&call_lock);
+	return NULL;
+}
+
+
+static int call_hash_delete(struct call_hash_table *hash,char *name) {
+	unsigned long key = ElfHash(name) & CALL_HASH_TABLE_KEY_SIZE;
+	struct hash_storage *store=NULL,*last=NULL;
+	int ret=0;
+  
+
+	store = hash->data[key];
+	if(store) {
+		if(! store->next) {
+			hash->data[key] = (struct hash_storage *) init_hash_storage();
+			ret=1;
+		}
+		else {
+			store = store->next;
+      
+			while(store) {
+				if(name && store->name && !strcmp(store->name,name)) {
+					if(last) {
+						last->next = store->next;
+						free(store);
+					}
+					else {
+						hash->data[key] = (struct hash_storage *) init_hash_storage();
+					}
+
+					ret=1;
+				}
+				last = store;
+				store = store->next;
+			}
+      
+		}
+	}
+  
+	return ret;
+}
+
+
+
+static char *pop_delim(char *fn,char delim) {
+	char *p=NULL;
+	int x=0,sl=0;
+
+	for(p=fn;strlen(p);p++) {
+		if(p[0] == delim)
+			sl = x;
+		x++;
+	}
+
+	p=fn;
+	for(x=0;x<=sl;x++)
+		p++;
+
+	return p;
+}
+
+
+static struct call_hash_table *call_list;
+
+
+
+
+
+
+
+
+
+static void dump_call_info(int fd,struct outgoing *outgoing,int do_long) {
+	char *do1=NULL;
+	time_t now;
+	int hr,min=0,sec=0;
+	char state[20];
+
+
+
+	switch(outgoing->state) {
+	case STATE_SLEEP:
+		strcpy(state,"sleep");
+		break;
+	case STATE_FAILED:
+		strcpy(state,"failed");
+		break;
+	case STATE_TRYING:
+		strcpy(state,"trying");
+		break;      
+	case STATE_COMPLETE:
+		strcpy(state,"complete");
+		break;      
+	case STATE_READY:
+		strcpy(state,"ready");
+		break;      
+	case STATE_EXPIRED:
+		strcpy(state,"expired");
+		break;      
+	default:
+		sprintf(state,"invalid: %d",outgoing->state);
+		break;
+	}
+
+
+	time(&now);
+
+
+	if(outgoing->app) {
+		do1=malloc(strlen(outgoing->app)+strlen(outgoing->data)+4);
+		sprintf(do1,"%s->%s",outgoing->app,outgoing->data);
+	}
+	else {
+		do1=malloc(strlen(outgoing->exten)+strlen(outgoing->context)+4);
+		sprintf(do1,"%s@%s",outgoing->exten,outgoing->context);
+	}
+    
+	min = (now - outgoing->attempt_time) / 60;
+	sec = (now - outgoing->attempt_time) % 60;
+
+	hr = (min / 60);
+	if(hr > 0) {
+		min = min % 60;
+	}
+
+
+	if(do_long) {
+		ast_cli(fd,"\n{\n\tfn => '%s',\n\tadded => '%ld',\n\tretries => '%d',\n\tmaxretries => '%d',\n\tretrytime => '%d',\n\twaittime => '%d',\n\ttech => '%s',\n\tdest => '%s',\n\tapp => '%s',\n\tdata => '%s',\n\texten => '%s',\n\tcontext => '%s',\n\tpriority => '%d',\n\tcallerid => '%s',\n\taccount => '%s',\n\tmaxlen => '%d',\n\tfailretry => '%d',\n\tmtime => '%ld',\n\tstate => '%s',\n\tattempt_time => '%ld',\n\tinfo => '%s',\n\telapsed => '%.2d:%.2d:%.2d'\n};\n\n",outgoing->fn,outgoing->added,outgoing->retries,outgoing->maxretries,outgoing->retrytime,outgoing->waittime,outgoing->tech,outgoing->dest,outgoing->app,outgoing->data,outgoing->exten,outgoing->context,outgoing->priority,outgoing->callerid,outgoing->account,outgoing->maxlen,outgoing->failretry,outgoing->mtime,state,outgoing->attempt_time,do1,hr,min,sec);
+
+	}
+	else {
+
+
+		ast_cli(fd,"%s\t%s\t%.2d:%.2d:%.2d\t%d/%d\t\t%s\t%s\n",
+			pop_delim(outgoing->fn,'/'),state,
+			hr,min,sec,outgoing->retries,outgoing->maxretries,outgoing->dest,do1);
+
+		free(do1);
+	}
+}
+
+
+
+static int spool_show(int fd, int argc, char **argv) {
+	struct call_hash_table *hash=call_list;
+	int key,do_long=0;
+	struct hash_storage *store;
+	struct outgoing *o=NULL;
+
+	if(! hash) {
+		return(1);
+	}
+
+
+	ast_mutex_lock(&call_lock);
+
+
+	if(argc >= 3 && !strcmp(argv[2],"long")) {
+		do_long=1;
+	}
+	else if(argc >= 3) {
+		do_long=1;
+		ast_mutex_unlock(&call_lock);
+		o = call_hash_read(call_list,argv[2]);
+		ast_mutex_lock(&call_lock);
+		if(o) {
+			dump_call_info(fd,o,do_long);
+		}
+		else { 
+			ast_cli(fd,"ERROR! Entry '%s' does not exist\n",argv[2]);
+		}
+		ast_mutex_unlock(&call_lock);
+		return(0);
+	}
+	else {
+		ast_cli(fd,"Spooled Calls\n");
+		ast_cli(fd,"FILE\t\tSTATE\tELAPSED\t\tTRY/MAX\t\tDEST\t\tINFO\n");
+	}
+  
+
+  
+
+	for(key=0;key<=CALL_HASH_TABLE_KEY_SIZE;key++) {
+
+		if(hash->data[key]) {
+
+			store = hash->data[key];
+
+			if(store) {
+
+				if(! store->next) {
+					if(store->name){
+						dump_call_info(fd,store->outgoing,do_long);
+					}
+				}
+				else {
+					store = store->next;
+					while(store) {
+						if(store->outgoing->fn){
+							dump_call_info(fd,store->outgoing,do_long);
+						}
+						store = store->next;
+					}
+				}
+			}
+      
+		}
+	}
+
+	ast_mutex_unlock(&call_lock);
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
+static char show_spool_usage[] =
+"Usage: show spool\n"
+"       Provides summary information about spooled calls.\n";
+
+
+static struct ast_cli_entry cli_show_spool = {
+	{ "show", "spool", NULL }, spool_show,
+	"Show status of spool", show_spool_usage, NULL };
+
+
+
+static void init_outgoing(struct outgoing *o) {
+
 	memset(o, 0, sizeof(struct outgoing));
 	o->priority = 1;
 	o->retrytime = 300;
+	o->failretry = 20;
 	o->waittime = 45;
+	o->state = STATE_READY;
+	time(&o->added);
+	o->attempt_time = (time_t) NULL;
+  
 }
 
-static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
+
+
+static int scan_filesystem(struct outgoing *o, char *fn, FILE *f)
 {
+
 	char buf[256];
 	char *c, *c2;
 	int lineno = 0;
@@ -97,10 +492,10 @@
 			/* Trim comments */
 			c = strchr(buf, '#');
 			if (c)
-				 *c = '\0';
+				*c = '\0';
 			c = strchr(buf, ';');
 			if (c)
-				 *c = '\0';
+				*c = '\0';
 
 			/* Trim trailing white space */
 			while(strlen(buf) && buf[strlen(buf) - 1] < 33)
@@ -112,9 +507,8 @@
 					c++;
 					while(*c < 33)
 						c++;
-#if 0
-					printf("'%s' is '%s' at line %d\n", buf, c, lineno);
-#endif					
+
+
 					if (!strcasecmp(buf, "channel")) {
 						strncpy(o->tech, c, sizeof(o->tech) - 1);
 						if ((c2 = strchr(o->tech, '/'))) {
@@ -155,8 +549,17 @@
 							ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
 							o->waittime = 45;
 						}
+					} else if (!strcasecmp(buf, "failretry")) {
+						if ((sscanf(c, "%d", &o->failretry) != 1) || (o->failretry < 1)) {
+							ast_log(LOG_WARNING, "Invalid failretry at line %d of %s\n", lineno, fn);
+							o->failretry=20;
+						}
+	  
 					} else if (!strcasecmp(buf, "retry")) {
-						o->retries++;
+						if ((sscanf(c, "%d", &o->retries) != 1) || (o->retries < 1)) {
+							ast_log(LOG_WARNING, "Invalid retry at line %d of %s\n", lineno, fn);
+							o->retries=1;
+						}
 					} else if (!strcasecmp(buf, "setvar")) { /* JDG variable support */
 						strncat(o->variable, c, sizeof(o->variable) - strlen(o->variable) - 1);
 						strncat(o->variable, "|", sizeof(o->variable) - strlen(o->variable) - 1);
@@ -179,6 +582,8 @@
 		ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
 		return -1;
 	}
+
+
 	return 0;
 }
 
@@ -186,113 +591,204 @@
 {
 	struct outgoing *o = data;
 	int res, reason;
+	FILE *f;
+
+	ast_mutex_lock(&call_lock);
+	o->state = STATE_TRYING;
+	time(&o->attempt_time);
+	ast_mutex_unlock(&call_lock);
+  
+
+	if((f=fopen(o->fn,"r+"))) {
+		fseek(f, 0L, SEEK_END);
+		fprintf(f, "Retry: %d (%ld)\n", o->retries, (long) o->attempt_time);
+		fclose(f);
+	}
+
+
 	if (strlen(o->app)) {
+
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
 		res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->callerid, o->variable, o->account);
 	} else {
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
+
+
 		res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->callerid, o->variable, o->account);
 	}
+
+
+
 	if (res) {
+
 		ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
-		if (o->retries >= o->maxretries + 1) {
+
+		ast_mutex_lock(&call_lock);
+		o->state = STATE_FAILED;
+		time(&o->attempt_time);
+		ast_mutex_unlock(&call_lock);
+
+
+		if (o->retries >= o->maxretries) {
 			/* Max retries exceeded */
-			ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1);
+			ast_log(LOG_EVENT, "Queued call to %s/%s expired 'a' without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1);
 			unlink(o->fn);
+			call_hash_delete(call_list,pop_delim(o->fn,'/'));
 		}
-	} else {
+
+
+	} 
+	else {
 		ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
 		ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
 		unlink(o->fn);
+		call_hash_delete(call_list,pop_delim(o->fn,'/'));
+
 	}
-	free(o);
+
 	return NULL;
 }
 
 static void launch_service(struct outgoing *o)
 {
+
 	pthread_t t;
 	pthread_attr_t attr;
-	pthread_attr_init(&attr);
- 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-	if (pthread_create(&t,&attr,attempt_thread, o) == -1) {
-		ast_log(LOG_WARNING, "Unable to create thread :(\n");
-		free(o);
+
+	if(o->state == STATE_READY) {
+		pthread_attr_init(&attr);
+		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  
+		if (pthread_create(&t,&attr,attempt_thread, o) == -1) {
+			ast_log(LOG_WARNING, "Unable to create thread :(\n");
+			free(o);
+		}
 	}
+  
 }
 
-static int scan_service(char *fn, time_t now, time_t atime)
-{
-	struct outgoing *o;
-	struct utimbuf tbuf;
+
+static void spooling_engine(void) {
+	int key;
 	FILE *f;
-	o = malloc(sizeof(struct outgoing));
-	if (o) {
-		init_outgoing(o);
-		f = fopen(fn, "r+");
-		if (f) {
-			if (!apply_outgoing(o, fn, f)) {
-				/* Update the file time */
-				tbuf.actime = atime;
-				tbuf.modtime = now + o->retrytime;
-				if (utime(o->fn, &tbuf))
-					ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", fn, strerror(errno));
-				/* Increment retries */
-				o->retries++;
-#if 0
-				printf("Retries: %d, max: %d\n", o->retries, o->maxretries);
-#endif
-				if (o->retries <= o->maxretries + 1) {
-					/* Add a retry line at the end */
-					fseek(f, 0L, SEEK_END);
-					fprintf(f, "Retry: %d (%ld)\n", o->retries, (long) now);
-					fclose(f);
-					now += o->retrytime;
-					launch_service(o);
-					return now;
-				} else {
-					ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1);
-					fclose(f);
-					free(o);
-					unlink(fn);
-					return 0;
+	time_t now;
+	struct call_hash_table *hash=call_list;
+	struct hash_storage *store;
+	struct stat st;
+
+
+	if(! hash) {
+		return;
+	}
+	ast_mutex_lock(&call_lock);
+
+	for(key=0;key<=CALL_HASH_TABLE_KEY_SIZE;key++) {
+
+		if(hash->data[key]) {
+
+			store = hash->data[key];
+
+			while(store) {
+				if(store->name && store->outgoing->fn){
+
+					if (stat(store->outgoing->fn, &st)) { /* wtf */
+						ast_mutex_unlock(&call_lock);
+						call_hash_delete(call_list,pop_delim(store->outgoing->fn,'/'));
+						ast_mutex_lock(&call_lock);
+					}
+					else {
+	    
+
+
+						if(store->outgoing->mtime != st.st_mtime && (f = fopen(store->outgoing->fn,"r"))) {
+							ast_log(LOG_WARNING, "Reading Cache File: %s\n",pop_delim(store->outgoing->fn,'/'));
+							scan_filesystem(store->outgoing,store->outgoing->fn,f);
+							fclose(f);
+							if (!stat(store->outgoing->fn, &st)) {
+								store->outgoing->mtime = st.st_mtime;
+							}
+						}
+	    
+						time(&now);
+
+	    
+						if(
+						   ((store->outgoing->state == STATE_FAILED) &&  ((store->outgoing->attempt_time + store->outgoing->failretry) <= now)) 
+						   || (
+						       ((store->outgoing->state == STATE_SLEEP || store->outgoing->state == STATE_FAILED)) &&  
+						       ((store->outgoing->attempt_time + store->outgoing->retrytime) <= now)) ) {
+							store->outgoing->state = STATE_READY;
+						}
+	    
+
+						if((store->outgoing->state  != STATE_TRYING) && (store->outgoing->retries > store->outgoing->maxretries)) {
+							store->outgoing->state = STATE_EXPIRED;
+						}
+
+	       
+						if (store->outgoing->state == STATE_READY) {
+							store->outgoing->retries++;
+							ast_log(LOG_WARNING, "Queueing call: %s\n",pop_delim(store->outgoing->fn,'/'));
+							ast_mutex_unlock(&call_lock);
+							launch_service(store->outgoing);
+							ast_mutex_lock(&call_lock);
+						}
+
+
+						else if((store->outgoing->state  == STATE_EXPIRED)){
+							ast_log(LOG_EVENT, "Queued call to %s/%s expired 'c' without completion after %d attempt(s)\n", store->outgoing->tech, store->outgoing->dest, store->outgoing->retries - 1);
+							ast_mutex_unlock(&call_lock);
+							call_hash_delete(call_list,pop_delim(store->outgoing->fn,'/'));
+							ast_mutex_lock(&call_lock);
+							unlink(store->outgoing->fn);
+	      
+						}
+
+
+
+
+
+					}
 				}
-			} else {
-				free(o);
-				ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
-				fclose(f);
-				unlink(fn);
+				store = store->next;
 			}
-		} else {
-			free(o);
-			ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
-			unlink(fn);
+
 		}
-	} else
-		ast_log(LOG_WARNING, "Out of memory :(\n");
-	return -1;
+	}
+
+	ast_mutex_unlock(&call_lock);
 }
 
+
+
+
+
+
 static void *scan_thread(void *unused)
 {
 	struct stat st;
 	DIR *dir;
 	struct dirent *de;
+	struct outgoing *o;
+	FILE *f;
 	char fn[256];
-	int res;
 	time_t last = 0, next = 0, now;
+
 	for(;;) {
 		/* Wait a sec */
 		sleep(1);
 		time(&now);
+
 		if (!stat(qdir, &st)) {
 			if ((st.st_mtime != last) || (next && (now > next))) {
 #if 0
 				printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime);
 				printf("Ooh, something changed / timeout\n");
 #endif				
+
+
 				next = 0;
 				last = st.st_mtime;
 				dir = opendir(qdir);
@@ -301,20 +797,17 @@
 						snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name);
 						if (!stat(fn, &st)) {
 							if (S_ISREG(st.st_mode)) {
-								if (st.st_mtime <= now) {
-									res = scan_service(fn, now, st.st_atime);
-									if (res > 0) {
-										/* Update next service time */
-										if (!next || (res < next)) {
-											next = res;
-										}
-									} else if (res)
-										ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn);
-								} else {
-									/* Update "next" update if necessary */
-									if (!next || (st.st_mtime < next))
-										next = st.st_mtime;
+								o = malloc(sizeof(struct outgoing));
+								if (o) {
+									init_outgoing(o);
+
+									if(fn && (f=fopen(fn,"r"))) {
+										if (!scan_filesystem(o, fn, f))
+											call_hash_write(call_list,pop_delim(fn,'/'),o);
+										fclose(f);
+									}
 								}
+		
 							}
 						} else
 							ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno));
@@ -325,6 +818,10 @@
 			}
 		} else
 			ast_log(LOG_WARNING, "Unable to stat %s\n", qdir);
+
+
+		/* perform accounting etc */
+		spooling_engine();
 	}
 	return NULL;
 }
@@ -338,14 +835,17 @@
 {
 	pthread_t thread;
 	pthread_attr_t attr;
+
+	call_list = (struct call_hash_table *) init_call_hash("call_list");
+
+	ast_cli_register(&cli_show_spool);
 	snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"outgoing");
-printf("%s\n",qdir);
-    	if (mkdir(qdir, 0700) && (errno != EEXIST)) {
+	if (mkdir(qdir, 0700) && (errno != EEXIST)) {
 		ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
 		return 0;
 	}
 	pthread_attr_init(&attr);
- 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	if (pthread_create(&thread,&attr,scan_thread, NULL) == -1) {
 		ast_log(LOG_WARNING, "Unable to create thread :(\n");
 		return -1;
@@ -367,3 +867,5 @@
 {
 	return ASTERISK_GPL_KEY;
 }
+
+
