00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 110779 $")
00036
00037 #include <sys/types.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <errno.h>
00041
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <time.h>
00045
00046 #include "asterisk/channel.h"
00047 #include "asterisk/cdr.h"
00048 #include "asterisk/module.h"
00049 #include "asterisk/config.h"
00050 #include "asterisk/pbx.h"
00051 #include "asterisk/logger.h"
00052 #include "asterisk/utils.h"
00053 #include "asterisk/lock.h"
00054
00055 #define CUSTOM_LOG_DIR "/cdr_custom"
00056
00057 #define DATE_FORMAT "%Y-%m-%d %T"
00058
00059 AST_MUTEX_DEFINE_STATIC(lock);
00060 AST_MUTEX_DEFINE_STATIC(mf_lock);
00061
00062 static char *name = "cdr-custom";
00063
00064 static char master[PATH_MAX];
00065 static char format[1024]="";
00066
00067 static int load_config(int reload)
00068 {
00069 struct ast_config *cfg;
00070 struct ast_variable *var;
00071 int res = -1;
00072
00073 strcpy(format, "");
00074 strcpy(master, "");
00075 ast_mutex_lock(&lock);
00076 if((cfg = ast_config_load("cdr_custom.conf"))) {
00077 var = ast_variable_browse(cfg, "mappings");
00078 while(var) {
00079 if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
00080 if (strlen(var->value) > (sizeof(format) - 1))
00081 ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
00082 ast_copy_string(format, var->value, sizeof(format) - 1);
00083 strcat(format,"\n");
00084 snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
00085 if (var->next) {
00086 ast_log(LOG_NOTICE, "Sorry, only one mapping is supported at this time, mapping '%s' will be ignored at line %d.\n", var->next->name, var->next->lineno);
00087 break;
00088 }
00089 } else
00090 ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
00091 var = var->next;
00092 }
00093 ast_config_destroy(cfg);
00094 res = 0;
00095 } else {
00096 if (reload)
00097 ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
00098 else
00099 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
00100 }
00101 ast_mutex_unlock(&lock);
00102
00103 return res;
00104 }
00105
00106
00107
00108 static int custom_log(struct ast_cdr *cdr)
00109 {
00110 FILE *mf = NULL;
00111
00112
00113 char buf[2048];
00114 struct ast_channel dummy;
00115
00116
00117 if (ast_strlen_zero(master))
00118 return 0;
00119
00120 memset(buf, 0 , sizeof(buf));
00121
00122 memset(&dummy, 0, sizeof(dummy));
00123 dummy.cdr = cdr;
00124 pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
00125
00126
00127
00128
00129 ast_mutex_lock(&mf_lock);
00130 mf = fopen(master, "a");
00131 if (mf) {
00132 fputs(buf, mf);
00133 fflush(mf);
00134 fclose(mf);
00135 mf = NULL;
00136 ast_mutex_unlock(&mf_lock);
00137 } else {
00138 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
00139 ast_mutex_unlock(&mf_lock);
00140 }
00141
00142 return 0;
00143 }
00144
00145 static int unload_module(void)
00146 {
00147 ast_cdr_unregister(name);
00148 return 0;
00149 }
00150
00151 static int load_module(void)
00152 {
00153 int res = 0;
00154
00155 if (!load_config(0)) {
00156 res = ast_cdr_register(name, ast_module_info->description, custom_log);
00157 if (res)
00158 ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
00159 return res;
00160 } else
00161 return AST_MODULE_LOAD_DECLINE;
00162 }
00163
00164 static int reload(void)
00165 {
00166 return load_config(1);
00167 }
00168
00169 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
00170 .load = load_module,
00171 .unload = unload_module,
00172 .reload = reload,
00173 );
00174