--- cdr_csv.c.orig	2006-11-25 15:09:47.084010360 +0300
+++ cdr_csv.c	2006-11-25 15:31:14.599781113 +0300
@@ -58,9 +58,12 @@
 static int loguniqueid = 0;
 static int loguserfield = 0;
 static char *config = "cdr.conf";
+static unsigned int mode_master = 1;
+static unsigned int mode_split = 1;
+static char splitby[AST_MAX_USER_FIELD];
+static char masterfile[PATH_MAX];
+static char splitfile[PATH_MAX];
 
-/* #define CSV_LOGUNIQUEID 1 */
-/* #define CSV_LOGUSERFIELD 1 */
 
 /*----------------------------------------------------
   The values are as follows:
@@ -104,6 +107,9 @@
 	usegmtime = 0;
 	loguniqueid = 0;
 	loguserfield = 0;
+	memset(splitby, 0, sizeof(splitby));
+	memset(masterfile, 0, sizeof(masterfile));
+	memset(splitfile, 0, sizeof(splitfile));
 	
 	cfg = ast_config_load(config);
 	
@@ -145,6 +151,47 @@
 		}
 	}
 
+	tmp = ast_variable_retrieve(cfg, "csv", "splitby");
+	if (tmp) {
+		strncpy(splitby, tmp, sizeof(splitby)-1);		
+		ast_log(LOG_DEBUG, "split log files by '%s'\n", splitby);
+	} else
+		strcpy(splitby, "accountcode");
+
+	tmp = ast_variable_retrieve(cfg, "csv", "logmode");
+	if (tmp) {
+		char *tmp1 = NULL, *tmp2 = NULL;
+		mode_master = 0;
+		mode_split = 0;
+		tmp1 = ast_strdupa(tmp);
+		while ((tmp2 = strsep(&tmp1, ","))) {
+			if (!strcasecmp(tmp2, "master"))
+				mode_master = 1;
+			else if (!strcasecmp(tmp2, "split"))
+				mode_split = 1;
+			else
+				ast_log(LOG_DEBUG, "unknown logmode '%s'\n", tmp2);
+		}
+		ast_log(LOG_DEBUG, "using logmode '%s %s'\n", mode_master ? "master" : "", mode_split ? "split" : "");
+	} else {
+		mode_master = 1;
+		mode_split = 1;
+	}
+
+	tmp = ast_variable_retrieve(cfg, "csv", "masterfile");
+	if (tmp) {
+		strncpy(masterfile, tmp, sizeof(masterfile)-1);		
+		ast_log(LOG_DEBUG, "master log file '%s'\n", masterfile);
+	} else
+		memset(masterfile, 0, sizeof(masterfile));
+
+	tmp = ast_variable_retrieve(cfg, "csv", "splitfile");
+	if (tmp) {
+		strncpy(splitfile, tmp, sizeof(splitfile)-1);
+		ast_log(LOG_DEBUG, "split log file '%s'\n", splitfile);
+	} else
+		memset(splitfile, 0, sizeof(splitfile));
+
 	ast_config_destroy(cfg);
 	return 1;
 }
@@ -200,11 +247,10 @@
 		strncat(buf, ",", bufsize - strlen(buf) - 1);
 		return 0;
 	}
-	if (usegmtime) {
-		gmtime_r(&t,&tm);
-	} else {
-		localtime_r(&t,&tm);
-	}
+	if (usegmtime)
+		gmtime_r(&t, &tm);
+	else
+		localtime_r(&t, &tm);
 	strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
 	return append_string(buf, tmp, bufsize);
 }
@@ -261,53 +307,73 @@
 	return -1;
 }
 
-static int writefile(char *s, char *acc)
-{
-	char tmp[PATH_MAX];
-	FILE *f;
-	if (strchr(acc, '/') || (acc[0] == '.')) {
-		ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
-		return -1;
-	}
-	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;
-	fputs(s, f);
-	fflush(f);
-	fclose(f);
-	return 0;
-}
-
-
 static int csv_log(struct ast_cdr *cdr)
 {
 	/* Make sure we have a big enough buf */
 	char buf[1024];
 	char csvmaster[PATH_MAX];
-	snprintf(csvmaster, sizeof(csvmaster),"%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER);
+	char csvsplit[PATH_MAX];
+	char tmp[80];
+	char *ret;
+	struct tm tm;
+	time_t t;
+
+	time(&t);
+	if (usegmtime)
+		gmtime_r(&t, &tm);
+	else
+		localtime_r(&t, &tm);
+	if (mode_master) {
+		if (strchr(masterfile, '%'))
+			strftime(tmp, sizeof(tmp), masterfile, &tm);
+		else
+			snprintf(tmp, sizeof(tmp), "%s", masterfile);
+		if (ast_strlen_zero(masterfile))
+			snprintf(csvmaster, sizeof(csvmaster), "%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER);
+		else
+			snprintf(csvmaster, sizeof(csvmaster), "%s/%s/Master-%s.csv", ast_config_AST_LOG_DIR, CSV_LOG_DIR, tmp);
+	}
+	if (mode_split) {
+		if (strchr(splitfile, '%'))
+			strftime(tmp, sizeof(tmp), splitfile, &tm);
+		else
+			snprintf(tmp, sizeof(tmp), "%s", splitfile);
+		ast_cdr_getvar(cdr, splitby, &ret, buf, sizeof(buf), 0, 0);
+		if (ret)
+			snprintf(csvsplit, sizeof(csvsplit), "%s/%s/%s-%s.csv", ast_config_AST_LOG_DIR, CSV_LOG_DIR, ret, tmp);
+		else
+			snprintf(csvsplit, sizeof(csvsplit), "%s/%s/%s.csv", ast_config_AST_LOG_DIR, CSV_LOG_DIR, tmp);
+	}
 #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
-	if (build_csv_record(buf, sizeof(buf), cdr)) {
+	if (build_csv_record(buf, sizeof(buf), cdr))
 		ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes.  CDR not recorded!\n", (int)sizeof(buf));
-	} else {
+	else {
 		/* 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(csvmaster, "a");
-		if (!mf) {
-			ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
-		}
-		if (mf) {
-			fputs(buf, mf);
-			fflush(mf); /* be particularly anal here */
-			fclose(mf);
-			mf = NULL;
+		if (mode_master) {
+			mf = fopen(csvmaster, "a");
+			if (!mf)
+				ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
+			else {
+				fputs(buf, mf);
+				fflush(mf); /* be particularly anal here */
+				fclose(mf);
+				mf = NULL;
+			}
 		}
-		if (!ast_strlen_zero(cdr->accountcode)) {
-			if (writefile(buf, cdr->accountcode))
-				ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
+		if (mode_split) {
+			mf = fopen(csvsplit, "a");
+			if (!mf)
+				ast_log(LOG_ERROR, "Unable to re-open split file %s : %s\n", csvsplit, strerror(errno));
+			else {
+				fputs(buf, mf);
+				fflush(mf); /* be particularly anal here */
+				fclose(mf);
+				mf = NULL;
+			}
 		}
 	}
 	return 0;
