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: 158135 $")
00036
00037 #include <time.h>
00038
00039 #include "asterisk/paths.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/cdr.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/config.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/utils.h"
00046 #include "asterisk/lock.h"
00047
00048 #define CUSTOM_LOG_DIR "/cdr_custom"
00049
00050 #define DATE_FORMAT "%Y-%m-%d %T"
00051
00052 AST_MUTEX_DEFINE_STATIC(lock);
00053 AST_MUTEX_DEFINE_STATIC(mf_lock);
00054
00055 static char *name = "cdr-custom";
00056
00057 static char master[PATH_MAX];
00058 static char format[1024]="";
00059
00060 static int load_config(int reload)
00061 {
00062 struct ast_config *cfg;
00063 struct ast_variable *var;
00064 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00065 int res = -1;
00066
00067 if ((cfg = ast_config_load("cdr_custom.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
00068 return 0;
00069
00070 strcpy(format, "");
00071 strcpy(master, "");
00072 ast_mutex_lock(&lock);
00073 if (cfg) {
00074 var = ast_variable_browse(cfg, "mappings");
00075 while(var) {
00076 if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
00077 if (strlen(var->value) > (sizeof(format) - 1))
00078 ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
00079 ast_copy_string(format, var->value, sizeof(format) - 1);
00080 strcat(format,"\n");
00081 snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
00082 if (var->next) {
00083 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);
00084 break;
00085 }
00086 } else
00087 ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
00088 var = var->next;
00089 }
00090 ast_config_destroy(cfg);
00091 res = 0;
00092 } else {
00093 if (reload)
00094 ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
00095 else
00096 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
00097 }
00098 ast_mutex_unlock(&lock);
00099
00100 return res;
00101 }
00102
00103
00104
00105 static int custom_log(struct ast_cdr *cdr)
00106 {
00107 FILE *mf = NULL;
00108
00109
00110 char buf[2048];
00111 struct ast_channel dummy;
00112
00113
00114 if (ast_strlen_zero(master))
00115 return 0;
00116
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 ast_mutex_lock(&mf_lock);
00126 mf = fopen(master, "a");
00127 if (mf) {
00128 fputs(buf, mf);
00129 fflush(mf);
00130 fclose(mf);
00131 mf = NULL;
00132 ast_mutex_unlock(&mf_lock);
00133 } else {
00134 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
00135 ast_mutex_unlock(&mf_lock);
00136 }
00137
00138 return 0;
00139 }
00140
00141 static int unload_module(void)
00142 {
00143 ast_cdr_unregister(name);
00144 return 0;
00145 }
00146
00147 static int load_module(void)
00148 {
00149 int res = 0;
00150
00151 if (!load_config(0)) {
00152 res = ast_cdr_register(name, ast_module_info->description, custom_log);
00153 if (res)
00154 ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
00155 return res;
00156 } else
00157 return AST_MODULE_LOAD_DECLINE;
00158 }
00159
00160 static int reload(void)
00161 {
00162 return load_config(1);
00163 }
00164
00165 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
00166 .load = load_module,
00167 .unload = unload_module,
00168 .reload = reload,
00169 );
00170