From 63ff35280893f84fca60ea5944659edadb21334f Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Thu, 30 Jan 2003 15:03:20 +0000
Subject: [PATCH] Version 0.3.0 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@593 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 app.c                | 104 +++++++++++++
 apps/app_directory.c |  11 +-
 apps/app_qcall.c     |   6 +-
 apps/app_voicemail.c | 322 +++++++++++++++++++++++++++------------
 astconf.h            |  32 ++++
 asterisk.h           |  26 ++--
 astman/Makefile      |  10 +-
 cdr/cdr_csv.c        |  31 ++--
 cli.c                | 132 +++++++++++++++-
 config.c             |   5 +-
 db.c                 | 355 +++++++++++++++++++++++++++++++++++++++++++
 image.c              |  11 +-
 loader.c             |   7 +-
 logger.c             |  26 ++--
 pbx/pbx_config.c     |  71 +++++----
 pbx/pbx_gtkconsole.c |  11 +-
 pbx/pbx_wilcalu.c    |   4 +-
 17 files changed, 969 insertions(+), 195 deletions(-)
 create mode 100755 astconf.h
 create mode 100755 db.c

diff --git a/app.c b/app.c
index 2d2af6de9c..482c2ee3ae 100755
--- a/app.c
+++ b/app.c
@@ -19,9 +19,15 @@
 #include <signal.h>
 #include <errno.h>
 #include <unistd.h>
+#include <dirent.h>
 #include <asterisk/channel.h>
 #include <asterisk/file.h>
 #include <asterisk/app.h>
+#include <asterisk/dsp.h>
+#include <asterisk/logger.h>
+#include <asterisk/options.h>
+#include "asterisk.h"
+#include "astconf.h"
 
 /* set timeout to 0 for "standard" timeouts. Set timeout to -1 for 
    "ludicrous time" (essentially never times out) */
@@ -41,3 +47,101 @@ int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, in
 	return res;
 }
 
+int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
+{
+	int res;
+	struct ast_filestream *writer;
+	int rfmt;
+	int totalms, total;
+	
+	struct ast_frame *f;
+	struct ast_dsp *sildet;
+	/* Play prompt if requested */
+	if (prompt) {
+		res = ast_streamfile(c, prompt, c->language);
+		if (res < 0)
+			return res;
+		res = ast_waitstream(c,"");
+		if (res < 0)
+			return res;
+	}
+	rfmt = c->readformat;
+	res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
+		return -1;
+	}
+	sildet = ast_dsp_new();
+	if (!sildet) {
+		ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
+		return -1;
+	}
+	writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
+	if (!writer) {
+		ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
+		ast_dsp_free(sildet);
+		return -1;
+	}
+	for(;;) {
+		if ((res = ast_waitfor(c, 2000)) < 0) {
+			ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
+			break;
+		}
+		if (res) {
+			f = ast_read(c);
+			if (!f) {
+				ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
+				break;
+			}
+			if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
+				/* Ended happily with DTMF */
+				ast_frfree(f);
+				break;
+			} else if (f->frametype == AST_FRAME_VOICE) {
+				ast_dsp_silence(sildet, f, &total); 
+				if (total > silence) {
+					/* Ended happily with silence */
+					ast_frfree(f);
+					break;
+				}
+				totalms += f->samples / 8;
+				if (totalms > maxsec * 1000) {
+					/* Ended happily with too much stuff */
+					ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
+					ast_frfree(f);
+					break;
+				}
+			}
+			ast_frfree(f);
+		}
+	}
+	res = ast_set_read_format(c, rfmt);
+	if (res)
+		ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
+	ast_dsp_free(sildet);
+	ast_closestream(writer);
+	return 0;
+}
+
+int ast_app_has_voicemail(char *mailbox)
+{
+	DIR *dir;
+	struct dirent *de;
+	char fn[256];
+
+	/* If no mailbox, return immediately */
+	if (!strlen(mailbox))
+		return 0;
+	snprintf(fn, sizeof(fn), "%s/vm/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, mailbox);
+	dir = opendir(fn);
+	if (!dir)
+		return 0;
+	while ((de = readdir(dir))) {
+		if (!strncasecmp(de->d_name, "msg", 3))
+			break;
+	}
+	closedir(dir);
+	if (de)
+		return 1;
+	return 0;
+}
diff --git a/apps/app_directory.c b/apps/app_directory.c
index 8618030fce..868badb020 100755
--- a/apps/app_directory.c
+++ b/apps/app_directory.c
@@ -25,6 +25,7 @@
 #include <pthread.h>
 #include <stdio.h>
 #include "../asterisk.h"
+#include "../astconf.h"
 
 static char *tdesc = "Extension Directory";
 static char *app = "Directory";
@@ -127,13 +128,12 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
 	struct ast_variable *v;
 	int res;
 	int found=0;
-	char *start, *pos, *conv;
+	char *start, *pos, *conv,*stringp=NULL;
 	char fn[256];
 	memset(ext, 0, sizeof(ext));
 	ext[0] = digit;
 	res = 0;
 	if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1;
-	printf("Res: %d, ext: %s\n", res, ext);
 	if (!res) {
 		/* Search for all names which start with those digits */
 		v = ast_variable_browse(cfg, context);
@@ -143,8 +143,9 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
 				/* Find a candidate extension */
 				start = strdup(v->value);
 				if (start) {
-					strtok(start, ",");
-					pos = strtok(NULL, ",");
+					stringp=start;
+					strsep(&stringp, ",");
+					pos = strsep(&stringp, ",");
 					if (pos) {
 						/* Grab the last name */
 						if (strrchr(pos, ' '))
@@ -167,7 +168,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
 			}
 			if (v) {
 				/* We have a match -- play a greeting if they have it */
-				snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name);
+				snprintf(fn, sizeof(fn), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, v->name);
 				if (ast_fileexists(fn, NULL, chan->language) > 0) {
 					res = ast_streamfile(chan, fn, chan->language);
 					if (!res)
diff --git a/apps/app_qcall.c b/apps/app_qcall.c
index 5a1df97262..a68239abc0 100755
--- a/apps/app_qcall.c
+++ b/apps/app_qcall.c
@@ -71,8 +71,9 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/file.h>
+#include "../astconf.h"
 
-const   char *qdir="/var/spool/asterisk/qcall";
+char qdir[255];
 static  char *tdesc = "Call from Queue";
 static  pthread_t qcall_thread;
 static int debug = 0;
@@ -132,7 +133,7 @@ pthread_attr_t attr;
 			  /* if not a regular file, skip it */
 			if ((mystat.st_mode & S_IFMT) != S_IFREG) continue;
 			  /* if not yet .... */
-			if (mystat.st_atime == mystat.st_ctime)
+			if (mystat.st_atime == mystat.st_mtime)
 			   {  /* first time */
 				if ((mystat.st_atime + INITIALONE) > t) 
 					continue;
@@ -361,6 +362,7 @@ int unload_module(void)
 
 int load_module(void)
 {
+	snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
 	mkdir(qdir,0660);
 	pthread_create(&qcall_thread,NULL,qcall,NULL);
 	return 0;
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 2d77f891bb..0646b0601f 100755
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -21,6 +21,7 @@
 #include <asterisk/say.h>
 #include <asterisk/module.h>
 #include <asterisk/adsi.h>
+#include <asterisk/app.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
@@ -33,6 +34,7 @@
 
 #include <pthread.h>
 #include "../asterisk.h"
+#include "../astconf.h"
 
 #define COMMAND_TIMEOUT 5000
 
@@ -95,8 +97,10 @@ static char *synopsis_vmain =
 "Enter voicemail system";
 
 static char *descrip_vmain =
-"  VoiceMailMain(): Enters the main voicemail system for the checking of voicemail.  Returns\n"
-"  -1 if the user hangs up or 0 otherwise.\n";
+"  VoiceMailMain(): Enters the main voicemail system for the checking of voicemail.  The mailbox\n"
+"can be passed as the option, which will stop the voicemail system from prompting the user\n"
+"for the mailbox.  If the mailbox is preceeded by 's' then the passsword check will be skipped.\n"
+"Returns -1 if the user hangs up or 0 otherwise.\n";
 
 /* Leave a message */
 static char *app = "VoiceMail";
@@ -110,7 +114,7 @@ LOCAL_USER_DECL;
 
 static int make_dir(char *dest, int len, char *ext, char *mailbox)
 {
-	return snprintf(dest, len, "%s/%s/%s", VM_SPOOL_DIR, ext, mailbox);
+	return snprintf(dest, len, "%s/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", ext, mailbox);
 }
 
 static int make_file(char *dest, int len, char *dir, int num)
@@ -127,9 +131,13 @@ static int vm_change_password(char *username, char *password, char *newpassword)
         FILE *configout;
 		char inbuf[256];
 		char orig[256];
+		char tmpin[AST_CONFIG_MAX_PATH];
+		char tmpout[AST_CONFIG_MAX_PATH];
 		char *user, *pass, *rest, *trim;
-        configin = fopen("/etc/asterisk/voicemail.conf","r");
-        configout = fopen("/etc/asterisk/voicemail.conf.new","w+");
+	snprintf((char *)tmpin, sizeof(tmpin)-1, "%s/voicemail.conf",(char *)ast_config_AST_CONFIG_DIR);
+	snprintf((char *)tmpout, sizeof(tmpout)-1, "%s/voicemail.conf.new",(char *)ast_config_AST_CONFIG_DIR);
+        configin = fopen((char *)tmpin,"r");
+        configout = fopen((char *)tmpout,"w+");
 
         while (!feof(configin)) {
 			/* Read in the line */
@@ -185,38 +193,11 @@ static int vm_change_password(char *username, char *password, char *newpassword)
         fclose(configin);
         fclose(configout);
 
-        unlink("/etc/asterisk/voicemail.conf");
-        rename("/etc/asterisk/voicemail.conf.new","/etc/asterisk/voicemail.conf");
+        unlink((char *)tmpin);
+        rename((char *)tmpout,(char *)tmpin);
 	return(1);
 }
 
-#if 0
-
-static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
-{
-	char *fn;
-	int res;
-
-	res = ast_streamfile(chan, "vm-message", chan->language);
-	if (!res) {
-		res = ast_waitstream(chan, AST_DIGIT_ANY);
-		if (!res) {
-			res = ast_say_number(chan, msgcnt+1, chan->language);
-			if (!res) {
-				fn = get_fn(dir, msgcnt);
-				if (fn) {
-					res = ast_streamfile(chan, fn, chan->language);
-					free(fn);
-				}
-			}
-		}
-	}
-	if (res < 0)
-		ast_log(LOG_WARNING, "Unable to announce message\n");
-	return res;
-}
-#endif
-
 static int
 inbuf(FILE *fi)
 {
@@ -351,13 +332,17 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
 	char dur[256];
 	time_t t;
 	struct tm *tm;
+	char *astattach;
+	struct ast_config *cfg;
 	p = popen(SENDMAIL, "w");
-
+	cfg = ast_load(VOICEMAIL_CONFIG);
+	if (!(astattach = ast_variable_retrieve(cfg, "general", "attach"))) 
+		astattach = "yes";
 	if (p) {
+		gethostname(host, sizeof(host));
 		if (strchr(srcemail, '@'))
 			strncpy(who, srcemail, sizeof(who)-1);
 		else {
-			gethostname(host, sizeof(host));
 			snprintf(who, sizeof(who), "%s@%s", srcemail, host);
 		}
 		snprintf(dur, sizeof(dur), "%ld:%02ld", duration / 60, duration % 60);
@@ -370,30 +355,32 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
 		fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n", msgnum, mailbox);
 		fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
 		fprintf(p, "MIME-Version: 1.0\n");
+		if (ast_true(astattach)) {
+			// Something unique.
+			snprintf(bound, sizeof(bound), "Boundary=%d%s%d", msgnum, mailbox, getpid());
 
-		// Something unique.
-		snprintf(bound, sizeof(bound), "Boundary=%d%s%d", msgnum, mailbox, getpid());
+			fprintf(p, "Content-Type: MULTIPART/MIXED; BOUNDARY=\"%s\"\n\n\n", bound);
 
-		fprintf(p, "Content-Type: MULTIPART/MIXED; BOUNDARY=\"%s\"\n\n\n", bound);
-
-		fprintf(p, "--%s\n", bound);
-		fprintf(p, "Content-Type: TEXT/PLAIN; charset=US-ASCII\n\n");
-		strftime(date, sizeof(date), "%A, %B %d, %Y at %r", tm);
-		fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message (number %d)\n"
+			fprintf(p, "--%s\n", bound);
+		}
+			fprintf(p, "Content-Type: TEXT/PLAIN; charset=US-ASCII\n\n");
+			strftime(date, sizeof(date), "%A, %B %d, %Y at %r", tm);
+			fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message (number %d)\n"
 
 		           "in mailbox %s from %s, on %s so you might\n"
 				   "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", name, 
-			dur, msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
-
-		fprintf(p, "--%s\n", bound);
-		fprintf(p, "Content-Type: audio/x-wav; name=\"msg%04d\"\n", msgnum);
-		fprintf(p, "Content-Transfer-Encoding: BASE64\n");
-		fprintf(p, "Content-Description: Voicemail sound attachment.\n");
-		fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
-
-		snprintf(fname, sizeof(fname), "%s.%s", attach, format);
-		base_encode(fname, p);
-		fprintf(p, "\n\n--%s--\n.\n", bound);
+				dur, msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
+		if (ast_true(astattach)) {
+			fprintf(p, "--%s\n", bound);
+			fprintf(p, "Content-Type: audio/x-wav; name=\"msg%04d.%s\"\n", msgnum, format);
+			fprintf(p, "Content-Transfer-Encoding: BASE64\n");
+			fprintf(p, "Content-Description: Voicemail sound attachment.\n");
+			fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
+
+			snprintf(fname, sizeof(fname), "%s.%s", attach, format);
+			base_encode(fname, p);
+			fprintf(p, "\n\n--%s--\n.\n", bound);
+		}
 		pclose(p);
 	} else {
 		ast_log(LOG_WARNING, "Unable to launch '%s'\n", SENDMAIL);
@@ -411,7 +398,7 @@ static int get_date(char *s, int len)
 	return strftime(s, len, "%a %b %e %r %Z %Y", tm);
 }
 
-static int invent_message(struct ast_channel *chan, char *ext, int busy)
+static int invent_message(struct ast_channel *chan, char *ext, int busy, char *ecodes)
 {
 	int res;
 	char fn[256];
@@ -420,17 +407,17 @@ static int invent_message(struct ast_channel *chan, char *ext, int busy)
 		res = ast_streamfile(chan, fn, chan->language);
 		if (res)
 			return -1;
-		res = ast_waitstream(chan, "#");
+		res = ast_waitstream(chan, ecodes);
 		if (res)
 			return res;
 	} else {
 		res = ast_streamfile(chan, "vm-theperson", chan->language);
 		if (res)
 			return -1;
-		res = ast_waitstream(chan, "#");
+		res = ast_waitstream(chan, ecodes);
 		if (res)
 			return res;
-		res = ast_say_digit_str(chan, ext, "#", chan->language);
+		res = ast_say_digit_str(chan, ext, ecodes, chan->language);
 		if (res)
 			return res;
 	}
@@ -440,7 +427,7 @@ static int invent_message(struct ast_channel *chan, char *ext, int busy)
 		res = ast_streamfile(chan, "vm-isunavail", chan->language);
 	if (res)
 		return -1;
-	res = ast_waitstream(chan, "#");
+	res = ast_waitstream(chan, ecodes);
 	return res;
 }
 
@@ -457,12 +444,15 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 	int msgnum;
 	int outmsg=0;
 	int wavother=0;
+	int maxmessage=0;
 	struct ast_frame *f;
 	char date[256];
 	char dir[256];
 	char fn[256];
 	char prefile[256]="";
 	char *astemail;
+	char *ecodes = "#";
+	char *s;
 	time_t start;
 	time_t end;
 
@@ -473,7 +463,15 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 	}
 	if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail"))) 
 		astemail = ASTERISK_USERNAME;
+	if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
+		if (sscanf(s, "%d", &x) == 1) {
+			maxmessage = x;
+		} else {
+			ast_log(LOG_WARNING, "Invalid max message time length\n");
+		}
+	}
 	if ((copy = ast_variable_retrieve(cfg, NULL, ext))) {
+		char *stringp=NULL;
 		/* Setup pre-file if appropriate */
 		if (busy)
 			snprintf(prefile, sizeof(prefile), "vm/%s/busy", ext);
@@ -481,9 +479,10 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 			snprintf(prefile, sizeof(prefile), "vm/%s/unavail", ext);
 		/* Make sure they have an entry in the config */
 		copy = strdup(copy);
-		passwd = strtok(copy, ",");
-		name = strtok(NULL, ",");
-		email = strtok(NULL, ",");
+		stringp=copy;
+		passwd = strsep(&stringp, ",");
+		name = strsep(&stringp, ",");
+		email = strsep(&stringp, ",");
 		make_dir(dir, sizeof(dir), ext, "");
 		/* It's easier just to try to make it than to check for its existence */
 		if (mkdir(dir, 0700) && (errno != EEXIST))
@@ -491,14 +490,16 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 		make_dir(dir, sizeof(dir), ext, "INBOX");
 		if (mkdir(dir, 0700) && (errno != EEXIST))
 			ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
+		if (ast_exists_extension(chan, chan->context, "o", 1, chan->callerid))
+			ecodes = "#0";
 		/* Play the beginning intro if desired */
 		if (strlen(prefile)) {
 			if (ast_fileexists(prefile, NULL, NULL) > 0) {
 				if (ast_streamfile(chan, prefile, chan->language) > -1) 
-				    silent = ast_waitstream(chan, "#");
+				    silent = ast_waitstream(chan, "#0");
 			} else {
 				ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
-				silent = invent_message(chan, ext, busy);
+				silent = invent_message(chan, ext, busy, ecodes);
 			}
 			if (silent < 0) {
 				ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
@@ -515,15 +516,29 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 				free(copy);
 				return -1;
 			}
+		} else if (silent == '0') {
+			strncpy(chan->exten, "0", sizeof(chan->exten) - 1);
+			chan->priority = 0;
+			free(copy);
+			return 0;
 		}
 		/* Stream an info message */
 		if (silent || !ast_streamfile(chan, INTRO, chan->language)) {
 			/* Wait for the message to finish */
 			if (silent || !ast_waitstream(chan, "")) {
+				if (!ast_streamfile(chan, "beep", chan->language) < 0)
+					silent = 1;
+				if (ast_waitstream(chan, "") <0) {
+					ast_log(LOG_DEBUG, "Hangup during beep\n");
+					free(copy);
+					return -1;
+				}
 				fmt = ast_variable_retrieve(cfg, "general", "format");
 				if (fmt) {
+					char *stringp=NULL;
 					fmts = strdup(fmt);
-					fmt = strtok(fmts, "|");
+					stringp=fmts;
+					fmt = strsep(&stringp, "|");
 					msgnum = 0;
 					do {
 						make_file(fn, sizeof(fn), dir, msgnum);
@@ -540,6 +555,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 						msgnum++;
 					} while(!writer && (msgnum < MAXMSG));
 					if (writer) {
+						char *stringp=NULL;
 						/* Store information */
 						snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
  						txt = fopen(txtfile, "w+");
@@ -573,8 +589,9 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 						free(fmts);
 						fmt = ast_variable_retrieve(cfg, "general", "format");
 						fmts = strdup(fmt);
-						strtok(fmts, "|");
-						while((fmt = strtok(NULL, "|"))) {
+						stringp=fmts;
+						strsep(&stringp, "|");
+						while((fmt = strsep(&stringp, "|"))) {
 							if (fmtcnt > MAX_OTHER_FORMATS - 1) {
 								ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
 								break;
@@ -604,8 +621,13 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 							for(;;) {
 								res = ast_waitfor(chan, 2000);
 								if (!res) {
-									ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
-									res = -1;
+									ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
+									/* Try one more time in case of masq */
+								 	res = ast_waitfor(chan, 2000);
+									if (!res) {
+										ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
+										res = -1;
+									}
 								}
 								
 								if (res < 0) {
@@ -639,10 +661,19 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 											ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
 										outmsg=2;
 										ast_frfree(f);
+										res = 0;
 										break;
 									}
 								}
 								ast_frfree(f);
+								time(&end);
+								if (maxmessage && (end - start > maxmessage)) {
+									if (option_verbose > 2) 
+										ast_verbose( VERBOSE_PREFIX_3 "Message is too long, ending it now...\n");
+									outmsg = 2;
+									res = 0;
+									break;
+								}
 							}
 							if (!f) {
 								if (option_verbose > 2) 
@@ -674,6 +705,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 								fclose(txt);
 							}
 							/* Send e-mail if applicable */
+							if (email)
 								sendmail(astemail, email, name, msgnum, ext, chan->callerid, fn, wavother ? "wav" : fmts, end - start);
 						}
 					} else {
@@ -1069,8 +1101,10 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
 		while(!feof(f)) {	
 			fgets(buf, sizeof(buf), f);
 			if (!feof(f)) {
-				strtok(buf, "=");
-				val = strtok(NULL, "=");
+				char *stringp=NULL;
+				stringp=buf;
+				strsep(&stringp, "=");
+				val = strsep(&stringp, "=");
 				if (val && strlen(val)) {
 					if (!strcmp(buf, "callerid"))
 						strncpy(cid, val, sizeof(cid) - 1);
@@ -1326,7 +1360,7 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int
 			if (play_and_wait(chan, "vm-savedto"))
 				break;
 
-			snprintf(todir, sizeof(todir), "%s/%s/INBOX", VM_SPOOL_DIR, username);
+			snprintf(todir, sizeof(todir), "%s/%s/%s/INBOX",  (char *)ast_config_AST_SPOOL_DIR,"vm", username);
 			snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
 			puts(sys);
 			system(sys);
@@ -1434,7 +1468,7 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int
 	snprintf(vmbox, sizeof(vmbox), "vm-%s", curbox); \
 } while (0)
 
-static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile)
+static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime)
 {
 	char d, *fmt, *fmts;
 	char comment[256];
@@ -1443,6 +1477,9 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor
 	struct ast_config *cfg;
 	struct ast_filestream *others[MAX_OTHER_FORMATS];
 	char *sfmt[MAX_OTHER_FORMATS];
+	char *stringp=NULL;
+	time_t start, end;
+	
 	
 	ast_log(LOG_DEBUG,"play_and_record: %s, %s\n", playfile, recordfile);
 	snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile, recordfile, chan->name);
@@ -1461,11 +1498,12 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor
 	
 	ast_destroy(cfg);
 
-	strtok(fmts, "|");
+	stringp=fmts;
+	strsep(&stringp, "|");
 	ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);	
 	sfmt[0] = strdup(fmts);
 	
-	while((fmt = strtok(NULL, "|"))) {
+	while((fmt = strsep(&stringp, "|"))) {
 		if (fmtcnt > MAX_OTHER_FORMATS - 1) {
 			ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
 			break;
@@ -1473,6 +1511,8 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor
 		sfmt[fmtcnt++] = strdup(fmt);
 		}
 
+	if (maxtime)
+		time(&start);
 	for (x=0;x<fmtcnt;x++) {
 		others[x] = ast_writefile(recordfile, sfmt[x], comment, 0, 0, 0700);
 		ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing:  %s format: %s\n", x, recordfile, sfmt[x]);
@@ -1496,14 +1536,19 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor
 			for(;;) {
 			 	res = ast_waitfor(chan, 2000);
 				if (!res) {
-					ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
-					res = -1;
+					ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
+					/* Try one more time in case of masq */
+				 	res = ast_waitfor(chan, 2000);
+					if (!res) {
+						ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
+						res = -1;
 					}
+				}
 				
 				if (res < 0) {
 					f = NULL;
 					break;
-					}
+				}
 
 				f = ast_read(chan);
 				if (!f)
@@ -1527,6 +1572,15 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor
 						break;
 					}
 				}
+				if (maxtime) {
+					time(&end);
+					if (maxtime < (end - start)) {
+						if (option_verbose > 2)
+							ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
+						outmsg=2;
+						break;
+					}
+				}
 				ast_frfree(f);
 			}
 			if (!f) {
@@ -1567,9 +1621,12 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 	   like I'm back in my GWBASIC days. XXX */
 	int res=-1;
 	int valid = 0;
+	int prefix = 0;
 	char d;
 	struct localuser *u;
 	char username[80] ="";
+	char prefixstr[80] ="";
+	char empty[80] = "";
 	char password[80] = "", *copy;
 	char newpassword[80] = "";
 	char newpassword2[80] = "";
@@ -1592,6 +1649,10 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 	int starting = 1;
 	int box;
 	int useadsi = 0;
+	int skipuser = 0;
+	char *s;
+	int maxgreet = 0;
+	char tmp[256], *ext;
 	struct ast_config *cfg;
 
 	LOCAL_USER_ADD(u);
@@ -1600,26 +1661,63 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 		ast_log(LOG_WARNING, "No voicemail configuration\n");
 		goto out;
 	}
+	if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
+		if (sscanf(s, "%d", &x) == 1) {
+			maxgreet = x;
+		} else {
+			ast_log(LOG_WARNING, "Invalid max message greeting length\n");
+		}
+	}
 	if (chan->_state != AST_STATE_UP)
 		ast_answer(chan);
 
+	if (strlen(data)) {
+		strncpy(tmp, data, sizeof(tmp) - 1);
+		ext = tmp;
+
+		switch (*ext) {
+			case 's':
+		 /* We should skip the user's password */
+				valid++;
+				ext++;
+				break;
+			case 'p':
+		 /* We should prefix the mailbox with the supplied data */
+				prefix++;
+				ext++;
+				break;
+		}
+
+
+		if (prefix)
+			strncpy(prefixstr, ext, sizeof(prefixstr) - 1);
+		else
+			strncpy(username, ext, sizeof(username) - 1);
+		/* make sure username passed as an option is valid */
+		if (ast_variable_retrieve(cfg, NULL, username)) 
+			skipuser++;
+		else
+			valid = 0;
+
+	}
+
 	/* If ADSI is supported, setup login screen */
 	adsi_begin(chan, &useadsi);
-	if (useadsi)
+	if (!skipuser && useadsi)
 		adsi_login(chan);
-	if (ast_streamfile(chan, "vm-login", chan->language)) {
+	if (!skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
 		ast_log(LOG_WARNING, "Couldn't stream login file\n");
 		goto out;
 	}
 	
 	/* Authenticate them and get their mailbox/password */
 	
-	do {
+	while (!valid) {
 		/* Prompt for, and read in the username */
-		if (ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) {
+		if (!skipuser && ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) {
 			ast_log(LOG_WARNING, "Couldn't read username\n");
 			goto out;
-		}			
+		}
 		if (!strlen(username)) {
 			if (option_verbose > 2)
 				ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
@@ -1636,17 +1734,32 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 			ast_log(LOG_WARNING, "Unable to read password\n");
 			goto out;
 		}
+		if (prefix) {
+			char fullusername[80] = "";
+			strncpy(fullusername, prefixstr, sizeof(fullusername) - 1);
+			strncat(fullusername, username, sizeof(fullusername) - 1);
+			strncpy(username, fullusername, sizeof(username) - 1);
+		}
 		copy = ast_variable_retrieve(cfg, NULL, username);
 		if (copy) {
+			char *stringp=NULL;
 			copy = strdup(copy);
-			strtok(copy, ",");
+			stringp=copy;
+			strsep(&stringp, ",");
 			if (!strcmp(password,copy))
 				valid++;
-			else if (option_verbose > 2)
-				ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s'\n", password, username);
+			else {
+				if (option_verbose > 2)
+					ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s'\n", password, username);
+				if (prefix)
+					strncpy(username, empty, sizeof(username) -1);
+			}
 			free(copy);
-		} else if (option_verbose > 2)
-			ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", username);
+		} else {
+			skipuser = 0;
+			if (option_verbose > 2)
+				ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", username);
+		}
 		if (!valid) {
 			if (useadsi)
 				adsi_login(chan);
@@ -1657,9 +1770,11 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 				break;
 #endif
 		}
-	} while (!valid);
+	}
 
 	if (valid) {
+		snprintf(curdir, sizeof(curdir), "%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", username);
+		mkdir(curdir, 0700);
 		OPEN_MAILBOX(1);
 		oldmessages = lastmsg + 1;
 		/* Start in INBOX */
@@ -1879,15 +1994,15 @@ vm_options:
 		
 		case '1':
 			snprintf(prefile,sizeof(prefile),"vm/%s/unavail",username);
-			play_and_record(chan,"vm-rec-unv",prefile);
+			play_and_record(chan,"vm-rec-unv",prefile, maxgreet);
 			break;
 		case '2': 
 			snprintf(prefile,sizeof(prefile),"vm/%s/busy",username);
-			play_and_record(chan,"vm-rec-busy",prefile);
+			play_and_record(chan,"vm-rec-busy",prefile, maxgreet);
 			break;
 		case '3': 
 			snprintf(prefile,sizeof(prefile),"vm/%s/greet",username);
-			play_and_record(chan,"vm-rec-name",prefile);
+			play_and_record(chan,"vm-rec-name",prefile, maxgreet);
 			break;
 		case '4':
 			newpassword[1] = '\0';
@@ -1930,14 +2045,21 @@ static int vm_exec(struct ast_channel *chan, void *data)
 {
 	int res=0, silent=0, busy=0, unavail=0;
 	struct localuser *u;
-	char *ext = (char *)data;
+	char tmp[256], *ext;
 	
-
-	if (!data) {
-		ast_log(LOG_WARNING, "vm requires an argument (extension)\n");
-		return -1;
-	}
 	LOCAL_USER_ADD(u);
+	if (chan->_state != AST_STATE_UP)
+		ast_answer(chan);
+	if (data)
+		strncpy(tmp, data, sizeof(tmp) - 1);
+	else {
+		res = ast_app_getdata(chan, "vm-whichbox", tmp, sizeof(tmp) - 1, 0);
+		if (res < 0)
+			return res;
+		if (!strlen(tmp))
+			return 0;
+	}
+	ext = tmp;
 	if (*ext == 's') {
 		silent++;
 		ext++;
@@ -1948,8 +2070,6 @@ static int vm_exec(struct ast_channel *chan, void *data)
 		unavail++;
 		ext++;
 	}
-	if (chan->_state != AST_STATE_UP)
-		ast_answer(chan);
 	res = leave_voicemail(chan, ext, silent, busy, unavail);
 	LOCAL_USER_REMOVE(u);
 	return res;
diff --git a/astconf.h b/astconf.h
new file mode 100755
index 0000000000..da3301f6de
--- /dev/null
+++ b/astconf.h
@@ -0,0 +1,32 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * General Definitions for Asterisk top level program
+ * 
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#ifndef _ASTCONF_H
+#define _ASTCONF_H
+
+#define AST_CONFIG_MAX_PATH 255
+
+extern char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
+extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
+
+#endif
diff --git a/asterisk.h b/asterisk.h
index eafb1597dc..ea3a9a7f2d 100755
--- a/asterisk.h
+++ b/asterisk.h
@@ -16,17 +16,20 @@
 
 #define DEFAULT_LANGUAGE "en"
 
-#define AST_CONFIG_DIR "/etc/asterisk"
-#define AST_SOCKET		"/var/run/asterisk.ctl"
-#define AST_PID			"/var/run/asterisk.pid"
-#define AST_MODULE_DIR "/usr/lib/asterisk/modules"
-#define AST_SPOOL_DIR  "/var/spool/asterisk"
-#define AST_VAR_DIR    "/var/lib/asterisk"
-#define AST_LOG_DIR	   "/var/log/asterisk"
-#define AST_AGI_DIR		"/var/lib/asterisk/agi-bin"
-#define AST_KEY_DIR	"/var/lib/asterisk/keys"
+#define AST_CONFIG_MAX_PATH 255
+#define AST_CONFIG_DIR 	ASTETCDIR
+#define AST_RUN_DIR	ASTVARRUNDIR
+#define AST_SOCKET	ASTVARRUNDIR "/asterisk.ctl"
+#define AST_PID		ASTVARRUNDIR "/asterisk.pid"
+#define AST_MODULE_DIR 	ASTMODDIR
+#define AST_SPOOL_DIR  	ASTSPOOLDIR
+#define AST_VAR_DIR    	ASTVARLIBDIR
+#define AST_LOG_DIR	ASTLOGDIR
+#define AST_AGI_DIR	ASTAGIDIR
+#define AST_KEY_DIR	ASTVARLIBDIR "/keys"
+#define AST_DB		ASTVARLIBDIR "/astdb"
 
-#define AST_CONFIG_FILE "asterisk.conf"
+#define AST_CONFIG_FILE ASTCONFPATH
 
 #define AST_SOUNDS AST_VAR_DIR "/sounds"
 #define AST_IMAGES AST_VAR_DIR "/images"
@@ -43,4 +46,7 @@ extern int init_framer(void);
 extern int reload_logger(void);
 /* Provided by term.c */
 extern int term_init(void);
+/* Provided by db.c */
+extern int astdb_init(void);
+
 #endif
diff --git a/astman/Makefile b/astman/Makefile
index f932ffb9ff..106affcd83 100755
--- a/astman/Makefile
+++ b/astman/Makefile
@@ -1,15 +1,17 @@
 
-TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; fi)
+TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else echo "none" ; fi)
 all: $(TARGET)
 
 install:
-	mkdir -p /usr/sbin
-	if [ "$(TARGET)" != "" ]; then \
+	if [ "$(TARGET)" != "none" ]; then \
 		for x in $(TARGET); do \
-			install -m 755 $$x /usr/sbin/astman; \
+			install -m 755 $$x $(ASTSBINDIR)/astman; \
 		done ; \
 	fi
 
+none:
+	@echo Not building the Asterisk Manager "astman"
+
 clean:
 	rm -f *.o astman
 
diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c
index a46c9bfbbf..da7b07edc3 100755
--- a/cdr/cdr_csv.c
+++ b/cdr/cdr_csv.c
@@ -19,9 +19,10 @@
 #include <asterisk/module.h>
 #include <asterisk/logger.h>
 #include "../asterisk.h"
+#include "../astconf.h"
 
-#define CSV_LOG_DIR AST_LOG_DIR "/cdr-csv"
-#define CSV_MASTER CSV_LOG_DIR "/Master.csv"
+#define CSV_LOG_DIR "/cdr-csv"
+#define CSV_MASTER  "/Master.csv"
 
 #define DATE_FORMAT "%Y-%m-%d %T"
 
@@ -35,22 +36,26 @@
 /* The values are as follows:
 
 
-  "accountcode", 
+  "accountcode", 	// accountcode is the account name of detail records, Master.csv contains all records
+  			// Detail records are configured on a channel basis, IAX and SIP are determined by user
+			// Zap is determined by channel in zaptel.conf
   "source",
   "destination",
   "destination context", 
   "callerid",
   "channel",
   "destination channel",	(if applicable)
-  "last application",
-  "last app argument",
+  "last application",	// Last application run on the channel
+  "last app argument",	// argument to the last channel
   "start time", 
   "answer time", 
   "end time", 
-  duration, 
-  billable seconds, 
-  "disposition", 
-  "amaflags",
+  duration,   		// Duration is the whole length that the entire call lasted. ie. call rx'd to hangup 
+  			// "end time" minus "start time"
+  billable seconds, 	// the duration that a call was up after other end answered which will be <= to duration 
+  			// "end time" minus "answer time"
+  "disposition",    	// ANSWERED, NO ANSWER, BUSY
+  "amaflags",       	// DOCUMENTATION, BILL, IGNORE etc, specified on a per channel basis like accountcode.
 
 */
 
@@ -170,7 +175,7 @@ static int writefile(char *s, char *acc)
 		ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
 		return -1;
 	}
-	snprintf(tmp, sizeof(tmp), "%s/%s.csv", CSV_LOG_DIR, acc);
+	snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
 	f = fopen(tmp, "a");
 	if (!f)
 		return -1;
@@ -184,6 +189,8 @@ static int csv_log(struct ast_cdr *cdr)
 {
 	/* Make sure we have a big enough buf */
 	char buf[1024];
+	char csvmaster[AST_CONFIG_MAX_PATH];
+	snprintf((char *)csvmaster,sizeof(csvmaster)-1,"%s/%s/%s",(char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR,CSV_MASTER);
 #if 0
 	printf("[CDR] %s ('%s' -> '%s') Dur: %ds Bill: %ds Disp: %s Flags: %s Account: [%s]\n", cdr->channel, cdr->src, cdr->dst, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), cdr->accountcode);
 #endif
@@ -193,9 +200,9 @@ static int csv_log(struct ast_cdr *cdr)
 		/* because of the absolutely unconditional need for the
 		   highest reliability possible in writing billing records,
 		   we open write and close the log file each time */
-		mf = fopen(CSV_MASTER, "a");
+		mf = fopen(csvmaster, "a");
 		if (!mf) {
-			ast_log(LOG_ERROR, "Unable to re-open master file %s\n", CSV_MASTER);
+			ast_log(LOG_ERROR, "Unable to re-open master file %s\n", csvmaster);
 		}
 		if (mf) {
 			fputs(buf, mf);
diff --git a/cli.c b/cli.c
index 5cc39bddc4..14cf3956ca 100755
--- a/cli.c
+++ b/cli.c
@@ -25,15 +25,15 @@
 #include <string.h>
 #include <pthread.h>
 /* For rl_filename_completion */
-#include <readline/readline.h>
+#include "editline/readline/readline.h"
 /* For module directory */
 #include "asterisk.h"
 #include "build.h"
+#include "astconf.h"
 
 #define VERSION_INFO "Asterisk " ASTERISK_VERSION " built by " BUILD_USER "@" BUILD_HOSTNAME \
 	" on a " BUILD_MACHINE " running " BUILD_OS
 	
-
 void ast_cli(int fd, char *fmt, ...)
 {
 	char stuff[4096];
@@ -219,6 +219,16 @@ static char commandcomplete_help[] =
 "       This function is used internally to help with command completion and should.\n"
 "       never be called by the user directly.\n";
 
+static char commandnummatches_help[] = 
+"Usage: _command nummatches \"<line>\" text \n"
+"       This function is used internally to help with command completion and should.\n"
+"       never be called by the user directly.\n";
+
+static char commandmatchesarray_help[] = 
+"Usage: _command matchesarray \"<line>\" text \n"
+"       This function is used internally to help with command completion and should.\n"
+"       never be called by the user directly.\n";
+
 static int handle_softhangup(int fd, int argc, char *argv[])
 {
 	struct ast_channel *c=NULL;
@@ -240,6 +250,56 @@ static int handle_softhangup(int fd, int argc, char *argv[])
 
 static char *__ast_cli_generator(char *text, char *word, int state, int lock);
 
+static int handle_commandmatchesarray(int fd, int argc, char *argv[])
+{
+	char buf[2048];
+	int len = 0;
+	char **matches;
+	int x;
+
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	buf[len] = '\0';
+	matches = ast_cli_completion_matches(argv[2], argv[3]);
+	if (matches) {
+		for (x=0; matches[x]; x++) {
+#if 0
+			printf("command matchesarray for '%s' %s got '%s'\n", argv[2], argv[3], matches[x]);
+#endif
+			len += sprintf( buf + len, "%s ", matches[x]);
+		}
+	}
+#if 0
+	printf("array for '%s' %s got '%s'\n", argv[2], argv[3], buf);
+#endif
+	
+	if (buf) {
+		ast_cli(fd, buf);
+	} else
+		ast_cli(fd, "NULL\n");
+
+	return RESULT_SUCCESS;
+}
+
+
+
+static int handle_commandnummatches(int fd, int argc, char *argv[])
+{
+	int matches = 0;
+
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+
+	matches = ast_cli_generatornummatches(argv[2], argv[3]);
+
+#if 0
+	printf("Search for '%s' %s got '%d'\n", argv[2], argv[3], matches);
+#endif
+	ast_cli(fd, "%d", matches);
+
+	return RESULT_SUCCESS;
+}
+
 static int handle_commandcomplete(int fd, int argc, char *argv[])
 {
 	char *buf;
@@ -276,10 +336,12 @@ static int handle_showchan(int fd, int argc, char *argv[])
 	"    DNID Digits: %s\n"
 	"          State: %s (%d)\n"
 	"          Rings: %d\n"
+	"   NativeFormat: %d\n"
 	"    WriteFormat: %d\n"
 	"     ReadFormat: %d\n"
-	"   NativeFormat: %d\n"
 	"1st File Descriptor: %d\n"
+	"      Frames in: %d\n"
+	"     Frames out: %d\n"
 	" --   PBX   --\n"
 	"        Context: %s\n"
 	"      Extension: %s\n"
@@ -291,7 +353,7 @@ static int handle_showchan(int fd, int argc, char *argv[])
 	c->name, c->type, 
 	(c->callerid ? c->callerid : "(N/A)"),
 	(c->dnid ? c->dnid : "(N/A)" ), ast_state2str(c->_state), c->_state, c->rings, c->nativeformats, c->writeformat, c->readformat,
-	c->fds[0], c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
+	c->fds[0], c->fin, c->fout, c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
 	( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
 	c->stack, (c->blocking ? c->blockproc : "(Not Blocking)"));
 	
@@ -328,10 +390,10 @@ static char *complete_fn(char *line, char *word, int pos, int state)
 	if (word[0] == '/')
 		strncpy(filename, word, sizeof(filename)-1);
 	else
-		snprintf(filename, sizeof(filename), "%s/%s", AST_MODULE_DIR, word);
+		snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_MODULE_DIR, word);
 	c = (char*)filename_completion_function(filename, state);
 	if (c && word[0] != '/')
-		c += (strlen(AST_MODULE_DIR) + 1);
+		c += (strlen((char*)ast_config_AST_MODULE_DIR) + 1);
 	return c ? strdup(c) : c;
 }
 
@@ -341,6 +403,8 @@ static struct ast_cli_entry builtins[] = {
 	/* Keep alphabetized */
 	{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help },
 	{ { "_command", "complete", NULL }, handle_commandcomplete, "Command complete", commandcomplete_help },
+	{ { "_command", "nummatches", NULL }, handle_commandnummatches, "Returns number of command matches", commandnummatches_help },
+	{ { "_command", "matchesarray", NULL }, handle_commandmatchesarray, "Returns command matches array", commandmatchesarray_help },
 	{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
 	{ { "reload", NULL }, handle_reload, "Reload configuration", reload_help },
 	{ { "set", "verbose", NULL }, handle_set_verbose, "Set level of verboseness", set_verbose_help },
@@ -637,6 +701,62 @@ normal:
 	return dup;
 }
 
+/* This returns the number of unique matches for the generator */
+int ast_cli_generatornummatches(char *text, char *word)
+{
+	int matches = 0, i = 0;
+	char *buf, *oldbuf;
+
+
+	while ( (buf = ast_cli_generator(text, word, i)) ) {
+		if (++i > 1 && strcmp(buf,oldbuf) == 0)  
+				continue;
+		oldbuf = buf;
+		matches++;
+	}
+
+	return matches;
+}
+
+char **ast_cli_completion_matches(char *text, char *word)
+{
+	char **match_list = NULL, *retstr, *prevstr;
+	size_t match_list_len, max_equal, which, i;
+	int matches = 0;
+
+	match_list_len = 1;
+	while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
+		if (matches + 1 >= match_list_len) {
+			match_list_len <<= 1;
+			match_list = realloc(match_list, match_list_len * sizeof(char *));
+		}
+		match_list[++matches] = retstr;
+	}
+
+	if (!match_list)
+		return (char **) NULL;
+
+	which = 2;
+	prevstr = match_list[1];
+	max_equal = strlen(prevstr);
+	for (; which <= matches; which++) {
+		for (i = 0; i < max_equal && prevstr[i] == match_list[which][i]; i++)
+			continue;
+		max_equal = i;
+	}
+
+	retstr = malloc(max_equal + 1);
+	(void) strncpy(retstr, match_list[1], max_equal);
+	retstr[max_equal] = '\0';
+	match_list[0] = retstr;
+
+	if (matches + 1 >= match_list_len)
+		match_list = realloc(match_list, (match_list_len + 1) * sizeof(char *));
+	match_list[matches + 1] = (char *) NULL;
+
+	return (match_list);
+}
+
 static char *__ast_cli_generator(char *text, char *word, int state, int lock)
 {
 	char *argv[AST_MAX_ARGS];
diff --git a/config.c b/config.c
index d758d7fac1..114d6584aa 100755
--- a/config.c
+++ b/config.c
@@ -20,6 +20,7 @@
 #include <asterisk/options.h>
 #include <asterisk/logger.h>
 #include "asterisk.h"
+#include "astconf.h"
 
 #define MAX_INCLUDE_LEVEL 10
 
@@ -228,6 +229,8 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
 			if (!*_tmpc) {
 				ast_log(LOG_WARNING,
 					"parse error: No category context for line %d of %s\n", lineno, configfile);
+				ast_destroy(tmp);
+				return -1;
 			}
 			c = strchr(cur, '=');
 			if (c) {
@@ -272,7 +275,7 @@ static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, s
 	if (configfile[0] == '/') {
 		strncpy(fn, configfile, sizeof(fn)-1);
 	} else {
-		snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, configfile);
+		snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, configfile);
 	}
 	if ((option_verbose > 1) && !option_debug) {
 		ast_verbose(  VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
diff --git a/db.c b/db.c
new file mode 100755
index 0000000000..cbecc4d505
--- /dev/null
+++ b/db.c
@@ -0,0 +1,355 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Channel Management
+ * 
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+/* DB3 is licensed under Sleepycat Public License and is thus incompatible
+   with GPL.  To avoid having to make another exception (and complicate 
+   licensing even further) we elect to use DB1 which is BSD licensed */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <asterisk/channel.h>
+#include <asterisk/file.h>
+#include <asterisk/app.h>
+#include <asterisk/dsp.h>
+#include <asterisk/logger.h>
+#include <asterisk/options.h>
+#include <asterisk/astdb.h>
+#include <asterisk/cli.h>
+#include "db1-ast/include/db.h"
+#include "asterisk.h"
+#include "astconf.h"
+
+static DB *astdb;
+static pthread_mutex_t dblock = AST_MUTEX_INITIALIZER;
+
+static int dbinit(void) 
+{
+	if (!astdb) {
+		if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
+			ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
+		}
+	}
+	if (astdb)
+		return 0;
+	return -1;
+}
+
+
+static inline int keymatch(const char *key, const char *prefix)
+{
+	if (!strlen(prefix))
+		return 1;
+	if (!strcasecmp(key, prefix))
+		return 1;
+	if ((strlen(key) > strlen(prefix)) &&
+		!strncasecmp(key, prefix, strlen(prefix))) {
+		if (key[strlen(prefix)] == '/')
+			return 1;
+	}
+	return 0;
+}
+
+int ast_db_deltree(const char *family, const char *keytree)
+{
+	char prefix[256];
+	DBT key, data;
+	char *keys;
+	int res;
+	int pass;
+	
+	if (family) {
+		if (keytree)
+			snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
+		else
+			snprintf(prefix, sizeof(prefix), "/%s", family);
+	} else if (keytree)
+		return -1;
+	else
+		strcpy(prefix, "");
+	
+	ast_pthread_mutex_lock(&dblock);
+	if (dbinit()) 
+		return -1;
+	
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	pass = 0;
+	while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
+		if (key.size) {
+			keys = key.data;
+			keys[key.size - 1] = '\0';
+		} else
+			keys = "<bad key>";
+		if (keymatch(keys, prefix)) {
+			astdb->del(astdb, &key, 0);
+		}
+	}
+	astdb->sync(astdb, 0);
+	ast_pthread_mutex_unlock(&dblock);
+	return 0;
+}
+
+int ast_db_put(const char *family, const char *keys, char *value)
+{
+	char fullkey[256];
+	DBT key, data;
+	int res;
+
+	ast_pthread_mutex_lock(&dblock);
+	if (dbinit()) {
+		ast_pthread_mutex_unlock(&dblock);
+		return -1;
+	}
+
+	snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	key.data = fullkey;
+	key.size = strlen(fullkey) + 1;
+	data.data = value;
+	data.size = strlen(value) + 1;
+	res = astdb->put(astdb, &key, &data, 0);
+	astdb->sync(astdb, 0);
+	ast_pthread_mutex_unlock(&dblock);
+	if (res)
+		ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
+	return res;
+}
+
+int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
+{
+	char fullkey[256];
+	DBT key, data;
+	int res;
+
+	ast_pthread_mutex_lock(&dblock);
+	if (dbinit()) {
+		ast_pthread_mutex_unlock(&dblock);
+		return -1;
+	}
+
+	snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	key.data = fullkey;
+	key.size = strlen(fullkey) + 1;
+	
+	res = astdb->get(astdb, &key, &data, 0);
+	
+	ast_pthread_mutex_unlock(&dblock);
+
+	/* Be sure to NULL terminate our data either way */
+	if (res) {
+		value[0] = 0;
+		ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
+	} else {
+		printf("Got value of size %d\n", data.size);
+		if (data.size) {
+			((char *)data.data)[data.size - 1] = '\0';
+			strncpy(value, data.data, valuelen - 1);
+			value[valuelen - 1] = '\0';
+		} else {
+			ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
+			value[0] = '\0';
+		}
+	}
+	return res;
+}
+
+int ast_db_del(const char *family, const char *keys)
+{
+	char fullkey[256];
+	DBT key;
+	int res;
+
+	ast_pthread_mutex_lock(&dblock);
+	if (dbinit()) {
+		ast_pthread_mutex_unlock(&dblock);
+		return -1;
+	}
+	
+	snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
+	memset(&key, 0, sizeof(key));
+	key.data = fullkey;
+	key.size = strlen(fullkey) + 1;
+	
+	res = astdb->del(astdb, &key, 0);
+	astdb->sync(astdb, 0);
+	
+	ast_pthread_mutex_unlock(&dblock);
+
+	if (res) 
+		ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
+	return res;
+}
+
+static int database_put(int fd, int argc, char *argv[])
+{
+	int res;
+	if (argc != 5)
+		return RESULT_SHOWUSAGE;
+	res = ast_db_put(argv[2], argv[3], argv[4]);
+	if (res) 
+		ast_cli(fd, "Failed to update entry\n");
+	else
+		ast_cli(fd, "Updated database successfully\n");
+	return RESULT_SUCCESS;
+}
+
+static int database_get(int fd, int argc, char *argv[])
+{
+	int res;
+	char tmp[256];
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
+	if (res) 
+		ast_cli(fd, "Database entry not found.\n");
+	else
+		ast_cli(fd, "Value: %s\n", tmp);
+	return RESULT_SUCCESS;
+}
+
+static int database_del(int fd, int argc, char *argv[])
+{
+	int res;
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	res = ast_db_del(argv[2], argv[3]);
+	if (res) 
+		ast_cli(fd, "Database entry does not exist.\n");
+	else
+		ast_cli(fd, "Database entry removed.\n");
+	return RESULT_SUCCESS;
+}
+
+static int database_deltree(int fd, int argc, char *argv[])
+{
+	int res;
+	if ((argc < 3) || (argc > 4))
+		return RESULT_SHOWUSAGE;
+	if (argc == 4)
+		res = ast_db_deltree(argv[2], argv[3]);
+	else
+		res = ast_db_deltree(argv[2], NULL);
+	if (res) 
+		ast_cli(fd, "Database entries do not exist.\n");
+	else
+		ast_cli(fd, "Database entries removed.\n");
+	return RESULT_SUCCESS;
+}
+
+static int database_show(int fd, int argc, char *argv[])
+{
+	char prefix[256];
+	DBT key, data;
+	char *keys, *values;
+	int res;
+	int pass;
+
+	if (argc == 4) {
+		/* Family and key tree */
+		snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
+	} else if (argc == 3) {
+		/* Family only */
+		snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
+	} else if (argc == 2) {
+		/* Neither */
+		strcpy(prefix, "");
+	} else
+		return RESULT_SHOWUSAGE;
+	ast_pthread_mutex_lock(&dblock);
+	if (dbinit()) {
+		ast_pthread_mutex_unlock(&dblock);
+		ast_cli(fd, "Database unavailable\n");
+		return RESULT_SUCCESS;	
+	}
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	pass = 0;
+	while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
+		if (key.size) {
+			keys = key.data;
+			keys[key.size - 1] = '\0';
+		} else
+			keys = "<bad key>";
+		if (data.size) {
+			values = data.data;
+			values[data.size - 1]='\0';
+		} else
+			values = "<vad value>";
+		if (keymatch(keys, prefix)) {
+				ast_cli(fd, "%-50s: %-25s\n", keys, values);
+		}
+	}
+	ast_pthread_mutex_unlock(&dblock);
+	return RESULT_SUCCESS;	
+}
+
+static char database_show_usage[] =
+"Usage: database show [family [keytree]]\n"
+"       Shows Asterisk database contents, optionally restricted\n"
+"to a given family, or family and keytree.\n";
+
+static char database_put_usage[] =
+"Usage: database put <family> <key> <value>\n"
+"       Adds or updates an entry in the Asterisk database for\n"
+"a given family, key, and value.\n";
+
+static char database_get_usage[] =
+"Usage: database get <family> <key>\n"
+"       Retrieves an entry in the Asterisk database for a given\n"
+"family and key.\n";
+
+static char database_del_usage[] =
+"Usage: database del <family> <key>\n"
+"       Deletes an entry in the Asterisk database for a given\n"
+"family and key.\n";
+
+static char database_deltree_usage[] =
+"Usage: database deltree <family> [keytree]\n"
+"       Deletes a family or specific keytree within a family\n"
+"in the Asterisk database.\n";
+
+struct ast_cli_entry cli_database_show =
+{ { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
+
+struct ast_cli_entry cli_database_get =
+{ { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
+
+struct ast_cli_entry cli_database_put =
+{ { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
+
+struct ast_cli_entry cli_database_del =
+{ { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
+
+struct ast_cli_entry cli_database_deltree =
+{ { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
+
+int astdb_init(void)
+{
+	dbinit();
+	ast_cli_register(&cli_database_show);
+	ast_cli_register(&cli_database_get);
+	ast_cli_register(&cli_database_put);
+	ast_cli_register(&cli_database_del);
+	ast_cli_register(&cli_database_deltree);
+	return 0;
+}
diff --git a/image.c b/image.c
index 785e8ddfd0..7ee2b080ac 100755
--- a/image.c
+++ b/image.c
@@ -30,6 +30,7 @@
 #include <asterisk/translate.h>
 #include <asterisk/cli.h>
 #include "asterisk.h"
+#include "astconf.h"
 
 static struct ast_imager *list;
 static pthread_mutex_t listlock = AST_MUTEX_INITIALIZER;
@@ -94,9 +95,9 @@ static void make_filename(char *buf, int len, char *filename, char *preflang, ch
 			snprintf(buf, len, "%s.%s", filename, ext);
 	} else {
 		if (preflang && strlen(preflang))
-			snprintf(buf, len, "%s/%s-%s.%s", AST_IMAGES, filename, preflang, ext);
+			snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_VAR_DIR, "images", filename, preflang, ext);
 		else
-			snprintf(buf, len, "%s/%s.%s", AST_IMAGES, filename, ext);
+			snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_VAR_DIR, "images", filename, ext);
 	}
 }
 
@@ -116,8 +117,10 @@ struct ast_frame *ast_read_image(char *filename, char *preflang, int format)
 	i = list;
 	while(!found && i) {
 		if (i->format & format) {
+			char *stringp=NULL;
 			strncpy(tmp, i->exts, sizeof(tmp)-1);
-			e = strtok(tmp, "|");
+			stringp=tmp;
+			e = strsep(&stringp, "|");
 			while(e) {
 				make_filename(buf, sizeof(buf), filename, preflang, e);
 				if ((len = file_exists(buf))) {
@@ -129,7 +132,7 @@ struct ast_frame *ast_read_image(char *filename, char *preflang, int format)
 					found = i;
 					break;
 				}
-				e = strtok(NULL, "|");
+				e = strsep(&stringp, "|");
 			}
 		}
 		i = i->next;
diff --git a/loader.c b/loader.c
index 6835fd8d0a..cd18b353e5 100755
--- a/loader.c
+++ b/loader.c
@@ -28,6 +28,7 @@
 #define __USE_GNU
 #include <pthread.h>
 #include "asterisk.h"
+#include "astconf.h"
 
 static char expected_key[] =
 { 0x8e, 0x93, 0x22, 0x83, 0xf5, 0xc3, 0xc0, 0x75,
@@ -204,7 +205,7 @@ int ast_load_resource(char *resource_name)
 	if (resource_name[0] == '/') {
 		strncpy(fn, resource_name, sizeof(fn)-1);
 	} else {
-		snprintf(fn, sizeof(fn), "%s/%s", AST_MODULE_DIR, resource_name);
+		snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_MODULE_DIR, resource_name);
 	}
 	m->lib = dlopen(fn, flags);
 	if (!m->lib) {
@@ -331,7 +332,7 @@ int load_modules()
 		int x;
 		/* Make two passes.  First, load any resource modules, then load the others. */
 		for (x=0;x<2;x++) {
-			mods = opendir(AST_MODULE_DIR);
+			mods = opendir((char *)ast_config_AST_MODULE_DIR);
 			if (mods) {
 				while((d = readdir(mods))) {
 					/* Must end in .so to load it.  */
@@ -374,7 +375,7 @@ int load_modules()
 				closedir(mods);
 			} else {
 				if (!option_quiet)
-					ast_log(LOG_WARNING, "Unable to open modules directory " AST_MODULE_DIR ".\n");
+					ast_log(LOG_WARNING, "Unable to open modules directory %s.\n", (char *)ast_config_AST_MODULE_DIR);
 			}
 		}
 	} 
diff --git a/logger.c b/logger.c
index f48296130c..c7089d3188 100755
--- a/logger.c
+++ b/logger.c
@@ -27,8 +27,7 @@
 #include <pthread.h>
 #include <sys/stat.h>
 #include "asterisk.h"
-
-#define AST_EVENT_LOG AST_LOG_DIR "/" EVENTLOG
+#include "astconf.h"
 
 #define MAX_MSG_QUEUE 200
 
@@ -73,7 +72,9 @@ static int make_components(char *s, int lineno)
 {
 	char *w;
 	int res = 0;
-	w = strtok(s, ",");
+	char *stringp=NULL;
+	stringp=s;
+	w = strsep(&stringp, ",");
 	while(w) {
 		while(*w && (*w < 33))
 			w++;
@@ -88,7 +89,7 @@ static int make_components(char *s, int lineno)
 		else {
 			fprintf(stderr, "Logfile Warning: Unknown keyword '%s' at line %d of logger.conf\n", w, lineno);
 		}
-		w = strtok(NULL, ",");
+		w = strsep(&stringp, ",");
 	}
 	return res;
 }
@@ -111,7 +112,7 @@ static struct logfile *make_logfile(char *fn, char *components, int lineno)
 			if (fn[0] == '/') 
 				strncpy(tmp, fn, sizeof(tmp) - 1);
 			else
-				snprintf(tmp, sizeof(tmp), "%s/%s", AST_LOG_DIR, fn);
+				snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, fn);
 			f->f = fopen(tmp, "a");
 			if (!f->f) {
 				/* Can't log here, since we're called with a lock */
@@ -179,14 +180,15 @@ static struct verb {
 
 int init_logger(void)
 {
-
-	mkdir(AST_LOG_DIR, 0755);
-	eventlog = fopen(AST_EVENT_LOG, "a");
+	char tmp[AST_CONFIG_MAX_PATH];
+	mkdir((char *)ast_config_AST_LOG_DIR, 0755);
+	snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
+	eventlog = fopen((char *)tmp, "a");
 	if (eventlog) {
 		init_logger_chain();
 		ast_log(LOG_EVENT, "Started Asterisk Event Logger\n");
 		if (option_verbose)
-			ast_verbose("Asterisk Event Logger Started\n");
+			ast_verbose("Asterisk Event Logger Started %s\n",(char *)tmp);
 		return 0;
 	} else 
 		ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
@@ -196,11 +198,13 @@ int init_logger(void)
 
 int reload_logger(void)
 {
+	char tmp[AST_CONFIG_MAX_PATH];
 	ast_pthread_mutex_lock(&loglock);
 	if (eventlog)
 		fclose(eventlog);
-	mkdir(AST_LOG_DIR, 0755);
-	eventlog = fopen(AST_EVENT_LOG, "a");
+	mkdir((char *)ast_config_AST_LOG_DIR, 0755);
+	snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
+	eventlog = fopen((char *)tmp, "a");
 	ast_pthread_mutex_unlock(&loglock);
 
 	if (eventlog) {
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index fbcb04a2e9..b37a98f629 100755
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -23,6 +23,7 @@
 #include <errno.h>
 /* For where to put dynamic tables */
 #include "../asterisk.h"
+#include "../astconf.h"
 
 static char *dtext = "Text Extension Configuration";
 static char *config = "extensions.conf";
@@ -919,7 +920,7 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
 	} else
 		/* no config file, default one */
 		snprintf(filename, sizeof(filename), "%s/%s",
-			AST_CONFIG_DIR, config);
+			(char *)ast_config_AST_CONFIG_DIR, config);
 
 	/* try to lock contexts list */
 	if (ast_lock_contexts()) {
@@ -1463,7 +1464,6 @@ static int pbx_load_module(void)
 {
 	struct ast_config *cfg;
 	struct ast_variable *v;
-	char *ptrptr;
 	char *cxt, *ext, *pri, *appl, *data, *tc, *cidmatch;
 	struct ast_context *con;
 
@@ -1485,36 +1485,41 @@ static int pbx_load_module(void)
 				v = ast_variable_browse(cfg, cxt);
 				while(v) {
 					if (!strcasecmp(v->name, "exten")) {
+						char *stringp=NULL;
 						tc = strdup(v->value);
-						ext = strtok_r(tc, ",",&ptrptr);
-						if (!ext)
-							ext="";
-						pri = strtok_r(NULL, ",",&ptrptr);
-						if (!pri)
-							pri="";
-						appl = strtok_r(NULL, ",",&ptrptr);
-						if (!appl)
-							appl="";
- 						if (*ptrptr=='"') {
- 							ptrptr++;
- 							data = strtok_r(NULL, "\"",&ptrptr);
- 							ptrptr++;
- 						} else {
- 							data = strtok_r(NULL, ",",&ptrptr);
- 						}
-						cidmatch = strchr(ext, '/');
-						if (cidmatch) {
-							*cidmatch = '\0';
-							cidmatch++;
-						}
-						strtok(ext, "/");
+						if(tc!=NULL){
+							stringp=tc;
+							ext = strsep(&stringp, ",");
+							if (!ext)
+								ext="";
+							pri = strsep(&stringp, ",");
+							if (!pri)
+								pri="";
+							appl = strsep(&stringp, ",");
+							if (!appl)
+								appl="";
+							if (stringp!=NULL && *stringp=='"') {
+								stringp++;
+								data = strsep(&stringp, "\"");
+								stringp++;
+							} else {
+								data = strsep(&stringp, ",");
+							}
+							cidmatch = strchr(ext, '/');
+							if (cidmatch) {
+								*cidmatch = '\0';
+								cidmatch++;
+							}
+							stringp=ext;
+							strsep(&stringp, "/");
 
-						if (!data)
-							data="";
-						if (ast_add_extension2(con, 0, ext, atoi(pri), cidmatch, appl, strdup(data), free, registrar)) {
-							ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
-						}
-						free(tc);
+							if (!data)
+								data="";
+							if (ast_add_extension2(con, 0, ext, atoi(pri), cidmatch, appl, strdup(data), free, registrar)) {
+								ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
+							}
+							free(tc);
+						} else fprintf(stderr,"Error strdup returned NULL in %s\n",__PRETTY_FUNCTION__);
 					} else if(!strcasecmp(v->name, "include")) {
 						if (ast_context_add_include2(con, v->value, registrar))
 							ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
@@ -1522,9 +1527,11 @@ static int pbx_load_module(void)
 						if (ast_context_add_ignorepat2(con, v->value, registrar))
 							ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
 					} else if (!strcasecmp(v->name, "switch")) {
+						char *stringp=NULL;
 						tc = strdup(v->value);
-						appl = strtok(tc, "/");
-						data = strtok(NULL, "");
+						stringp=tc;
+						appl = strsep(&stringp, "/");
+						data = strsep(&stringp, "");
 						if (!data)
 							data = "";
 						if (ast_context_add_switch2(con, appl, data, registrar))
diff --git a/pbx/pbx_gtkconsole.c b/pbx/pbx_gtkconsole.c
index d93ef6fa98..727fe38f38 100755
--- a/pbx/pbx_gtkconsole.c
+++ b/pbx/pbx_gtkconsole.c
@@ -39,6 +39,7 @@
 #include <glib.h>
 /* For where to put dynamic tables */
 #include "../asterisk.h"
+#include "../astconf.h"
 
 static pthread_mutex_t verb_lock = AST_MUTEX_INITIALIZER;
 
@@ -228,10 +229,12 @@ static void reload_module()
 
 static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs)
 {
+	char tmp[AST_CONFIG_MAX_PATH];
 	char *module = gtk_file_selection_get_filename(fs);
 	char buf[256];
-	if (!strncmp(module, AST_MODULE_DIR "/", strlen(AST_MODULE_DIR "/"))) 
-		module += strlen(AST_MODULE_DIR "/");
+	snprintf((char *)tmp,sizeof(tmp)-1,"%s/",(char *)ast_config_AST_MODULE_DIR);
+	if (!strncmp(module, (char *)tmp, strlen(tmp))) 
+		module += strlen(tmp);
 	gdk_threads_leave();
 	if (ast_load_resource(module)) {
 		snprintf(buf, sizeof(buf), "Error loading module '%s'.", module);
@@ -246,13 +249,15 @@ static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs)
 
 static void add_module()
 {
+	char tmp[AST_CONFIG_MAX_PATH];
 	GtkWidget *filew;
+	snprintf((char *)tmp,sizeof(tmp)-1,"%s/*.so",(char *)ast_config_AST_MODULE_DIR);
 	filew = gtk_file_selection_new("Load Module");
 	gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(filew)->ok_button),
 					"clicked", GTK_SIGNAL_FUNC(file_ok_sel), filew);
 	gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(filew)->cancel_button),
 					"clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew));
-	gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), AST_MODULE_DIR "/*.so");
+	gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), (char *)tmp);
 	gtk_widget_show(filew);
 }
 
diff --git a/pbx/pbx_wilcalu.c b/pbx/pbx_wilcalu.c
index a125bd1020..56270733b8 100755
--- a/pbx/pbx_wilcalu.c
+++ b/pbx/pbx_wilcalu.c
@@ -31,10 +31,11 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include "../astconf.h"
 
 
 // Globals
-const   char *dialfile="/var/run/autodial.ctl";
+const   char dialfile[255];
 static  char *tdesc = "Wil Cal U (Auto Dialer)";
 static  pthread_t autodialer_thread;
 static  char buf[257];
@@ -245,6 +246,7 @@ int unload_module(void)
 int load_module(void)
 {
 	int val;
+	snprintf((char *)dialfile,sizeof(dialfile)-1,"%s/%s",(char *)ast_config_AST_RUN_DIR,"autodial.ctl");
 	if((val=mkfifo(dialfile, 0700))){
 		if(errno!=EEXIST){
 			printf("Error:%d Creating Autodial FIFO\n",errno);
-- 
GitLab