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: 70841 $")
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 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
00111 char buf[2048];
00112 struct ast_channel dummy;
00113
00114
00115 if (ast_strlen_zero(master))
00116 return 0;
00117
00118 memset(buf, 0 , sizeof(buf));
00119
00120 memset(&dummy, 0, sizeof(dummy));
00121 dummy.cdr = cdr;
00122 pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
00123
00124
00125
00126
00127 mf = fopen(master, "a");
00128 if (!mf) {
00129 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
00130 }
00131 if (mf) {
00132 fputs(buf, mf);
00133 fflush(mf);
00134 fclose(mf);
00135 mf = NULL;
00136 }
00137 return 0;
00138 }
00139
00140 static int unload_module(void)
00141 {
00142 if (mf)
00143 fclose(mf);
00144 ast_cdr_unregister(name);
00145 return 0;
00146 }
00147
00148 static int load_module(void)
00149 {
00150 int res = 0;
00151
00152 if (!load_config(0)) {
00153 res = ast_cdr_register(name, ast_module_info->description, custom_log);
00154 if (res)
00155 ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
00156 if (mf)
00157 fclose(mf);
00158 return res;
00159 } else
00160 return AST_MODULE_LOAD_DECLINE;
00161 }
00162
00163 static int reload(void)
00164 {
00165 return load_config(1);
00166 }
00167
00168 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
00169 .load = load_module,
00170 .unload = unload_module,
00171 .reload = reload,
00172 );
00173