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: 158072 $")
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 if (cfg == CONFIG_STATUS_FILEINVALID) {
00071 ast_log(LOG_ERROR, "Invalid config file\n");
00072 return 1;
00073 }
00074
00075 strcpy(format, "");
00076 strcpy(master, "");
00077 ast_mutex_lock(&lock);
00078 if (cfg) {
00079 var = ast_variable_browse(cfg, "mappings");
00080 while(var) {
00081 if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
00082 if (strlen(var->value) > (sizeof(format) - 1))
00083 ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
00084 ast_copy_string(format, var->value, sizeof(format) - 1);
00085 strcat(format,"\n");
00086 snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
00087 if (var->next) {
00088 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);
00089 break;
00090 }
00091 } else
00092 ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
00093 var = var->next;
00094 }
00095 ast_config_destroy(cfg);
00096 res = 0;
00097 } else {
00098 if (reload)
00099 ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
00100 else
00101 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
00102 }
00103 ast_mutex_unlock(&lock);
00104
00105 return res;
00106 }
00107
00108
00109
00110 static int custom_log(struct ast_cdr *cdr)
00111 {
00112 FILE *mf = NULL;
00113
00114
00115 char buf[2048];
00116 struct ast_channel dummy;
00117
00118
00119 if (ast_strlen_zero(master))
00120 return 0;
00121
00122
00123 memset(&dummy, 0, sizeof(dummy));
00124 dummy.cdr = cdr;
00125 pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
00126
00127
00128
00129
00130 ast_mutex_lock(&mf_lock);
00131 mf = fopen(master, "a");
00132 if (mf) {
00133 fputs(buf, mf);
00134 fflush(mf);
00135 fclose(mf);
00136 mf = NULL;
00137 ast_mutex_unlock(&mf_lock);
00138 } else {
00139 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
00140 ast_mutex_unlock(&mf_lock);
00141 }
00142
00143 return 0;
00144 }
00145
00146 static int unload_module(void)
00147 {
00148 ast_cdr_unregister(name);
00149 return 0;
00150 }
00151
00152 static int load_module(void)
00153 {
00154 int res = 0;
00155
00156 if (!load_config(0)) {
00157 res = ast_cdr_register(name, ast_module_info->description, custom_log);
00158 if (res)
00159 ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
00160 return res;
00161 } else
00162 return AST_MODULE_LOAD_DECLINE;
00163 }
00164
00165 static int reload(void)
00166 {
00167 return load_config(1);
00168 }
00169
00170 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
00171 .load = load_module,
00172 .unload = unload_module,
00173 .reload = reload,
00174 );
00175