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$")
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
00054 #define CUSTOM_LOG_DIR "/cdr_custom"
00055
00056 #define DATE_FORMAT "%Y-%m-%d %T"
00057
00058 AST_MUTEX_DEFINE_STATIC(lock);
00059
00060 static char *name = "cdr-custom";
00061
00062 static FILE *mf = NULL;
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 if((cfg = ast_config_load("cdr_custom.conf"))) {
00076 var = ast_variable_browse(cfg, "mappings");
00077 while(var) {
00078 ast_mutex_lock(&lock);
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 ast_mutex_unlock(&lock);
00086 } else
00087 ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
00088 if (var->next)
00089 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);
00090 var = var->next;
00091 }
00092 ast_config_destroy(cfg);
00093 res = 0;
00094 } else {
00095 if (reload)
00096 ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
00097 else
00098 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
00099 }
00100
00101 return res;
00102 }
00103
00104
00105
00106 static int custom_log(struct ast_cdr *cdr)
00107 {
00108
00109 char buf[2048];
00110 struct ast_channel dummy;
00111
00112
00113 if (ast_strlen_zero(master))
00114 return 0;
00115
00116 memset(buf, 0 , sizeof(buf));
00117
00118 memset(&dummy, 0, sizeof(dummy));
00119 dummy.cdr = cdr;
00120 pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
00121
00122
00123
00124
00125 mf = fopen(master, "a");
00126 if (!mf) {
00127 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
00128 }
00129 if (mf) {
00130 fputs(buf, mf);
00131 fflush(mf);
00132 fclose(mf);
00133 mf = NULL;
00134 }
00135 return 0;
00136 }
00137
00138 static int unload_module(void)
00139 {
00140 if (mf)
00141 fclose(mf);
00142 ast_cdr_unregister(name);
00143 return 0;
00144 }
00145
00146 static int load_module(void)
00147 {
00148 int res = 0;
00149
00150 if (!load_config(0)) {
00151 res = ast_cdr_register(name, ast_module_info->description, custom_log);
00152 if (res)
00153 ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
00154 if (mf)
00155 fclose(mf);
00156 return res;
00157 } else
00158 return AST_MODULE_LOAD_DECLINE;
00159 }
00160
00161 static int reload(void)
00162 {
00163 return load_config(1);
00164 }
00165
00166 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
00167 .load = load_module,
00168 .unload = unload_module,
00169 .reload = reload,
00170 );
00171