logger.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2006, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Asterisk Logger
  21. *
  22. * Logging routines
  23. *
  24. * \author Mark Spencer <markster@digium.com>
  25. */
  26. /*** MODULEINFO
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  31. /* When we include logger.h again it will trample on some stuff in syslog.h, but
  32. * nothing we care about in here. */
  33. #include <syslog.h>
  34. #include "asterisk/_private.h"
  35. #include "asterisk/paths.h" /* use ast_config_AST_LOG_DIR */
  36. #include "asterisk/logger.h"
  37. #include "asterisk/lock.h"
  38. #include "asterisk/channel.h"
  39. #include "asterisk/config.h"
  40. #include "asterisk/term.h"
  41. #include "asterisk/cli.h"
  42. #include "asterisk/utils.h"
  43. #include "asterisk/manager.h"
  44. #include "asterisk/astobj2.h"
  45. #include "asterisk/threadstorage.h"
  46. #include "asterisk/strings.h"
  47. #include "asterisk/pbx.h"
  48. #include "asterisk/app.h"
  49. #include "asterisk/syslog.h"
  50. #include "asterisk/buildinfo.h"
  51. #include "asterisk/ast_version.h"
  52. #include <signal.h>
  53. #include <time.h>
  54. #include <sys/stat.h>
  55. #include <fcntl.h>
  56. #ifdef HAVE_BKTR
  57. #include <execinfo.h>
  58. #define MAX_BACKTRACE_FRAMES 20
  59. # if defined(HAVE_DLADDR) && defined(HAVE_BFD) && defined(BETTER_BACKTRACES)
  60. # include <dlfcn.h>
  61. # include <bfd.h>
  62. # endif
  63. #endif
  64. /*** DOCUMENTATION
  65. ***/
  66. static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
  67. static char queue_log_name[256] = QUEUELOG;
  68. static char exec_after_rotate[256] = "";
  69. static int filesize_reload_needed;
  70. static unsigned int global_logmask = 0xFFFF;
  71. static int queuelog_init;
  72. static int logger_initialized;
  73. static volatile int next_unique_callid; /* Used to assign unique call_ids to calls */
  74. static int display_callids;
  75. static void unique_callid_cleanup(void *data);
  76. struct ast_callid {
  77. int call_identifier; /* Numerical value of the call displayed in the logs */
  78. };
  79. AST_THREADSTORAGE_CUSTOM(unique_callid, NULL, unique_callid_cleanup);
  80. static enum rotatestrategy {
  81. SEQUENTIAL = 1 << 0, /* Original method - create a new file, in order */
  82. ROTATE = 1 << 1, /* Rotate all files, such that the oldest file has the highest suffix */
  83. TIMESTAMP = 1 << 2, /* Append the epoch timestamp onto the end of the archived file */
  84. } rotatestrategy = SEQUENTIAL;
  85. static struct {
  86. unsigned int queue_log:1;
  87. unsigned int queue_log_to_file:1;
  88. unsigned int queue_adaptive_realtime:1;
  89. } logfiles = { 1 };
  90. static char hostname[MAXHOSTNAMELEN];
  91. AST_THREADSTORAGE_RAW(in_safe_log);
  92. enum logtypes {
  93. LOGTYPE_SYSLOG,
  94. LOGTYPE_FILE,
  95. LOGTYPE_CONSOLE,
  96. };
  97. struct logchannel {
  98. /*! What to log to this channel */
  99. unsigned int logmask;
  100. /*! If this channel is disabled or not */
  101. int disabled;
  102. /*! syslog facility */
  103. int facility;
  104. /*! Verbosity level. (-1 if use option_verbose for the level.) */
  105. int verbosity;
  106. /*! Type of log channel */
  107. enum logtypes type;
  108. /*! logfile logging file pointer */
  109. FILE *fileptr;
  110. /*! Filename */
  111. char filename[PATH_MAX];
  112. /*! field for linking to list */
  113. AST_LIST_ENTRY(logchannel) list;
  114. /*! Line number from configuration file */
  115. int lineno;
  116. /*! Components (levels) from last config load */
  117. char components[0];
  118. };
  119. static AST_RWLIST_HEAD_STATIC(logchannels, logchannel);
  120. enum logmsgtypes {
  121. LOGMSG_NORMAL = 0,
  122. LOGMSG_VERBOSE,
  123. };
  124. struct logmsg {
  125. enum logmsgtypes type;
  126. int level;
  127. int line;
  128. int lwp;
  129. struct ast_callid *callid;
  130. AST_DECLARE_STRING_FIELDS(
  131. AST_STRING_FIELD(date);
  132. AST_STRING_FIELD(file);
  133. AST_STRING_FIELD(function);
  134. AST_STRING_FIELD(message);
  135. AST_STRING_FIELD(level_name);
  136. );
  137. AST_LIST_ENTRY(logmsg) list;
  138. };
  139. static void logmsg_free(struct logmsg *msg)
  140. {
  141. if (msg->callid) {
  142. ast_callid_unref(msg->callid);
  143. }
  144. ast_free(msg);
  145. }
  146. static AST_LIST_HEAD_STATIC(logmsgs, logmsg);
  147. static pthread_t logthread = AST_PTHREADT_NULL;
  148. static ast_cond_t logcond;
  149. static int close_logger_thread = 0;
  150. static FILE *qlog;
  151. /*! \brief Logging channels used in the Asterisk logging system
  152. *
  153. * The first 16 levels are reserved for system usage, and the remaining
  154. * levels are reserved for usage by dynamic levels registered via
  155. * ast_logger_register_level.
  156. */
  157. /* Modifications to this array are protected by the rwlock in the
  158. * logchannels list.
  159. */
  160. static char *levels[NUMLOGLEVELS] = {
  161. "DEBUG",
  162. "---EVENT---", /* no longer used */
  163. "NOTICE",
  164. "WARNING",
  165. "ERROR",
  166. "VERBOSE",
  167. "DTMF",
  168. };
  169. /*! \brief Colors used in the console for logging */
  170. static const int colors[NUMLOGLEVELS] = {
  171. COLOR_BRGREEN,
  172. COLOR_BRBLUE, /* no longer used */
  173. COLOR_YELLOW,
  174. COLOR_BRRED,
  175. COLOR_RED,
  176. COLOR_GREEN,
  177. COLOR_BRGREEN,
  178. 0,
  179. 0,
  180. 0,
  181. 0,
  182. 0,
  183. 0,
  184. 0,
  185. 0,
  186. 0,
  187. COLOR_BRBLUE,
  188. COLOR_BRBLUE,
  189. COLOR_BRBLUE,
  190. COLOR_BRBLUE,
  191. COLOR_BRBLUE,
  192. COLOR_BRBLUE,
  193. COLOR_BRBLUE,
  194. COLOR_BRBLUE,
  195. COLOR_BRBLUE,
  196. COLOR_BRBLUE,
  197. COLOR_BRBLUE,
  198. COLOR_BRBLUE,
  199. COLOR_BRBLUE,
  200. COLOR_BRBLUE,
  201. COLOR_BRBLUE,
  202. COLOR_BRBLUE,
  203. };
  204. AST_THREADSTORAGE(verbose_buf);
  205. #define VERBOSE_BUF_INIT_SIZE 256
  206. AST_THREADSTORAGE(log_buf);
  207. #define LOG_BUF_INIT_SIZE 256
  208. static void make_components(struct logchannel *chan)
  209. {
  210. char *w;
  211. unsigned int logmask = 0;
  212. char *stringp = ast_strdupa(chan->components);
  213. unsigned int x;
  214. unsigned int verb_level;
  215. /* Default to using option_verbose as the verbosity level of the logging channel. */
  216. verb_level = -1;
  217. while ((w = strsep(&stringp, ","))) {
  218. w = ast_strip(w);
  219. if (ast_strlen_zero(w)) {
  220. continue;
  221. }
  222. if (!strcmp(w, "*")) {
  223. logmask = 0xFFFFFFFF;
  224. } else if (!strncasecmp(w, "verbose(", 8)) {
  225. if (levels[__LOG_VERBOSE] && sscanf(w + 8, "%30u)", &verb_level) == 1) {
  226. logmask |= (1 << __LOG_VERBOSE);
  227. }
  228. } else {
  229. for (x = 0; x < ARRAY_LEN(levels); ++x) {
  230. if (levels[x] && !strcasecmp(w, levels[x])) {
  231. logmask |= (1 << x);
  232. break;
  233. }
  234. }
  235. }
  236. }
  237. if (chan->type == LOGTYPE_CONSOLE) {
  238. /*
  239. * Force to use the root console verbose level so if the
  240. * user specified any verbose level then it does not interfere
  241. * with calculating the ast_verb_sys_level value.
  242. */
  243. chan->verbosity = -1;
  244. } else {
  245. chan->verbosity = verb_level;
  246. }
  247. chan->logmask = logmask;
  248. }
  249. static struct logchannel *make_logchannel(const char *channel, const char *components, int lineno)
  250. {
  251. struct logchannel *chan;
  252. char *facility;
  253. struct ast_tm tm;
  254. struct timeval now = ast_tvnow();
  255. char datestring[256];
  256. if (ast_strlen_zero(channel) || !(chan = ast_calloc(1, sizeof(*chan) + strlen(components) + 1)))
  257. return NULL;
  258. strcpy(chan->components, components);
  259. chan->lineno = lineno;
  260. if (!strcasecmp(channel, "console")) {
  261. chan->type = LOGTYPE_CONSOLE;
  262. } else if (!strncasecmp(channel, "syslog", 6)) {
  263. /*
  264. * syntax is:
  265. * syslog.facility => level,level,level
  266. */
  267. facility = strchr(channel, '.');
  268. if (!facility++ || !facility) {
  269. facility = "local0";
  270. }
  271. chan->facility = ast_syslog_facility(facility);
  272. if (chan->facility < 0) {
  273. fprintf(stderr, "Logger Warning: bad syslog facility in logger.conf\n");
  274. ast_free(chan);
  275. return NULL;
  276. }
  277. chan->type = LOGTYPE_SYSLOG;
  278. ast_copy_string(chan->filename, channel, sizeof(chan->filename));
  279. openlog("asterisk", LOG_PID, chan->facility);
  280. } else {
  281. const char *log_dir_prefix = "";
  282. const char *log_dir_separator = "";
  283. if (channel[0] != '/') {
  284. log_dir_prefix = ast_config_AST_LOG_DIR;
  285. log_dir_separator = "/";
  286. }
  287. if (!ast_strlen_zero(hostname)) {
  288. snprintf(chan->filename, sizeof(chan->filename), "%s%s%s.%s",
  289. log_dir_prefix, log_dir_separator, channel, hostname);
  290. } else {
  291. snprintf(chan->filename, sizeof(chan->filename), "%s%s%s",
  292. log_dir_prefix, log_dir_separator, channel);
  293. }
  294. if (!(chan->fileptr = fopen(chan->filename, "a"))) {
  295. /* Can't do real logging here since we're called with a lock
  296. * so log to any attached consoles */
  297. ast_console_puts_mutable("ERROR: Unable to open log file '", __LOG_ERROR);
  298. ast_console_puts_mutable(chan->filename, __LOG_ERROR);
  299. ast_console_puts_mutable("': ", __LOG_ERROR);
  300. ast_console_puts_mutable(strerror(errno), __LOG_ERROR);
  301. ast_console_puts_mutable("'\n", __LOG_ERROR);
  302. ast_free(chan);
  303. return NULL;
  304. } else {
  305. /* Create our date/time */
  306. ast_localtime(&now, &tm, NULL);
  307. ast_strftime(datestring, sizeof(datestring), dateformat, &tm);
  308. fprintf(chan->fileptr, "[%s] Asterisk %s built by %s @ %s on a %s running %s on %s\n",
  309. datestring, ast_get_version(), ast_build_user, ast_build_hostname,
  310. ast_build_machine, ast_build_os, ast_build_date);
  311. fflush(chan->fileptr);
  312. }
  313. chan->type = LOGTYPE_FILE;
  314. }
  315. make_components(chan);
  316. return chan;
  317. }
  318. /* \brief Read config, setup channels.
  319. * \param locked The logchannels list is locked and this is a reload
  320. * \param altconf Alternate configuration file to read.
  321. *
  322. * \retval 0 Success
  323. * \retval -1 No config found or Failed
  324. */
  325. static int init_logger_chain(int locked, const char *altconf)
  326. {
  327. struct logchannel *chan;
  328. struct ast_config *cfg;
  329. struct ast_variable *var;
  330. const char *s;
  331. struct ast_flags config_flags = { 0 };
  332. display_callids = 1;
  333. if (!(cfg = ast_config_load2(S_OR(altconf, "logger.conf"), "logger", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
  334. cfg = NULL;
  335. }
  336. /* delete our list of log channels */
  337. if (!locked) {
  338. AST_RWLIST_WRLOCK(&logchannels);
  339. }
  340. while ((chan = AST_RWLIST_REMOVE_HEAD(&logchannels, list))) {
  341. ast_free(chan);
  342. }
  343. global_logmask = 0;
  344. if (!locked) {
  345. AST_RWLIST_UNLOCK(&logchannels);
  346. }
  347. errno = 0;
  348. /* close syslog */
  349. closelog();
  350. /* If no config file, we're fine, set default options. */
  351. if (!cfg) {
  352. if (!(chan = ast_calloc(1, sizeof(*chan)))) {
  353. fprintf(stderr, "Failed to initialize default logging\n");
  354. return -1;
  355. }
  356. chan->type = LOGTYPE_CONSOLE;
  357. chan->logmask = __LOG_WARNING | __LOG_NOTICE | __LOG_ERROR;
  358. if (!locked) {
  359. AST_RWLIST_WRLOCK(&logchannels);
  360. }
  361. AST_RWLIST_INSERT_HEAD(&logchannels, chan, list);
  362. global_logmask |= chan->logmask;
  363. if (!locked) {
  364. AST_RWLIST_UNLOCK(&logchannels);
  365. }
  366. return -1;
  367. }
  368. if ((s = ast_variable_retrieve(cfg, "general", "appendhostname"))) {
  369. if (ast_true(s)) {
  370. if (gethostname(hostname, sizeof(hostname) - 1)) {
  371. ast_copy_string(hostname, "unknown", sizeof(hostname));
  372. fprintf(stderr, "What box has no hostname???\n");
  373. }
  374. } else
  375. hostname[0] = '\0';
  376. } else
  377. hostname[0] = '\0';
  378. if ((s = ast_variable_retrieve(cfg, "general", "display_callids"))) {
  379. display_callids = ast_true(s);
  380. }
  381. if ((s = ast_variable_retrieve(cfg, "general", "dateformat")))
  382. ast_copy_string(dateformat, s, sizeof(dateformat));
  383. else
  384. ast_copy_string(dateformat, "%b %e %T", sizeof(dateformat));
  385. if ((s = ast_variable_retrieve(cfg, "general", "queue_log"))) {
  386. logfiles.queue_log = ast_true(s);
  387. }
  388. if ((s = ast_variable_retrieve(cfg, "general", "queue_log_to_file"))) {
  389. logfiles.queue_log_to_file = ast_true(s);
  390. }
  391. if ((s = ast_variable_retrieve(cfg, "general", "queue_log_name"))) {
  392. ast_copy_string(queue_log_name, s, sizeof(queue_log_name));
  393. }
  394. if ((s = ast_variable_retrieve(cfg, "general", "exec_after_rotate"))) {
  395. ast_copy_string(exec_after_rotate, s, sizeof(exec_after_rotate));
  396. }
  397. if ((s = ast_variable_retrieve(cfg, "general", "rotatestrategy"))) {
  398. if (strcasecmp(s, "timestamp") == 0) {
  399. rotatestrategy = TIMESTAMP;
  400. } else if (strcasecmp(s, "rotate") == 0) {
  401. rotatestrategy = ROTATE;
  402. } else if (strcasecmp(s, "sequential") == 0) {
  403. rotatestrategy = SEQUENTIAL;
  404. } else {
  405. fprintf(stderr, "Unknown rotatestrategy: %s\n", s);
  406. }
  407. } else {
  408. if ((s = ast_variable_retrieve(cfg, "general", "rotatetimestamp"))) {
  409. rotatestrategy = ast_true(s) ? TIMESTAMP : SEQUENTIAL;
  410. fprintf(stderr, "rotatetimestamp option has been deprecated. Please use rotatestrategy instead.\n");
  411. }
  412. }
  413. if (!locked) {
  414. AST_RWLIST_WRLOCK(&logchannels);
  415. }
  416. var = ast_variable_browse(cfg, "logfiles");
  417. for (; var; var = var->next) {
  418. if (!(chan = make_logchannel(var->name, var->value, var->lineno))) {
  419. /* Print error message directly to the consoles since the lock is held
  420. * and we don't want to unlock with the list partially built */
  421. ast_console_puts_mutable("ERROR: Unable to create log channel '", __LOG_ERROR);
  422. ast_console_puts_mutable(var->name, __LOG_ERROR);
  423. ast_console_puts_mutable("'\n", __LOG_ERROR);
  424. continue;
  425. }
  426. AST_RWLIST_INSERT_HEAD(&logchannels, chan, list);
  427. global_logmask |= chan->logmask;
  428. }
  429. if (qlog) {
  430. fclose(qlog);
  431. qlog = NULL;
  432. }
  433. if (!locked) {
  434. AST_RWLIST_UNLOCK(&logchannels);
  435. }
  436. ast_config_destroy(cfg);
  437. return 0;
  438. }
  439. void ast_child_verbose(int level, const char *fmt, ...)
  440. {
  441. char *msg = NULL, *emsg = NULL, *sptr, *eptr;
  442. va_list ap, aq;
  443. int size;
  444. va_start(ap, fmt);
  445. va_copy(aq, ap);
  446. if ((size = vsnprintf(msg, 0, fmt, ap)) < 0) {
  447. va_end(ap);
  448. va_end(aq);
  449. return;
  450. }
  451. va_end(ap);
  452. if (!(msg = ast_malloc(size + 1))) {
  453. va_end(aq);
  454. return;
  455. }
  456. vsnprintf(msg, size + 1, fmt, aq);
  457. va_end(aq);
  458. if (!(emsg = ast_malloc(size * 2 + 1))) {
  459. ast_free(msg);
  460. return;
  461. }
  462. for (sptr = msg, eptr = emsg; ; sptr++) {
  463. if (*sptr == '"') {
  464. *eptr++ = '\\';
  465. }
  466. *eptr++ = *sptr;
  467. if (*sptr == '\0') {
  468. break;
  469. }
  470. }
  471. ast_free(msg);
  472. fprintf(stdout, "verbose \"%s\" %d\n", emsg, level);
  473. fflush(stdout);
  474. ast_free(emsg);
  475. }
  476. void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
  477. {
  478. va_list ap;
  479. struct timeval tv;
  480. struct ast_tm tm;
  481. char qlog_msg[8192];
  482. int qlog_len;
  483. char time_str[30];
  484. if (!logger_initialized) {
  485. /* You are too early. We are not open yet! */
  486. return;
  487. }
  488. if (!queuelog_init) {
  489. /* We must initialize now since someone is trying to log something. */
  490. logger_queue_start();
  491. }
  492. if (ast_check_realtime("queue_log")) {
  493. tv = ast_tvnow();
  494. ast_localtime(&tv, &tm, NULL);
  495. ast_strftime(time_str, sizeof(time_str), "%F %T.%6q", &tm);
  496. va_start(ap, fmt);
  497. vsnprintf(qlog_msg, sizeof(qlog_msg), fmt, ap);
  498. va_end(ap);
  499. if (logfiles.queue_adaptive_realtime) {
  500. AST_DECLARE_APP_ARGS(args,
  501. AST_APP_ARG(data)[5];
  502. );
  503. AST_NONSTANDARD_APP_ARGS(args, qlog_msg, '|');
  504. /* Ensure fields are large enough to receive data */
  505. ast_realtime_require_field("queue_log",
  506. "data1", RQ_CHAR, strlen(S_OR(args.data[0], "")),
  507. "data2", RQ_CHAR, strlen(S_OR(args.data[1], "")),
  508. "data3", RQ_CHAR, strlen(S_OR(args.data[2], "")),
  509. "data4", RQ_CHAR, strlen(S_OR(args.data[3], "")),
  510. "data5", RQ_CHAR, strlen(S_OR(args.data[4], "")),
  511. SENTINEL);
  512. /* Store the log */
  513. ast_store_realtime("queue_log", "time", time_str,
  514. "callid", callid,
  515. "queuename", queuename,
  516. "agent", agent,
  517. "event", event,
  518. "data1", S_OR(args.data[0], ""),
  519. "data2", S_OR(args.data[1], ""),
  520. "data3", S_OR(args.data[2], ""),
  521. "data4", S_OR(args.data[3], ""),
  522. "data5", S_OR(args.data[4], ""),
  523. SENTINEL);
  524. } else {
  525. ast_store_realtime("queue_log", "time", time_str,
  526. "callid", callid,
  527. "queuename", queuename,
  528. "agent", agent,
  529. "event", event,
  530. "data", qlog_msg,
  531. SENTINEL);
  532. }
  533. if (!logfiles.queue_log_to_file) {
  534. return;
  535. }
  536. }
  537. if (qlog) {
  538. va_start(ap, fmt);
  539. qlog_len = snprintf(qlog_msg, sizeof(qlog_msg), "%ld|%s|%s|%s|%s|", (long)time(NULL), callid, queuename, agent, event);
  540. vsnprintf(qlog_msg + qlog_len, sizeof(qlog_msg) - qlog_len, fmt, ap);
  541. va_end(ap);
  542. AST_RWLIST_RDLOCK(&logchannels);
  543. if (qlog) {
  544. fprintf(qlog, "%s\n", qlog_msg);
  545. fflush(qlog);
  546. }
  547. AST_RWLIST_UNLOCK(&logchannels);
  548. }
  549. }
  550. static int rotate_file(const char *filename)
  551. {
  552. char old[PATH_MAX];
  553. char new[PATH_MAX];
  554. int x, y, which, found, res = 0, fd;
  555. char *suffixes[4] = { "", ".gz", ".bz2", ".Z" };
  556. switch (rotatestrategy) {
  557. case SEQUENTIAL:
  558. for (x = 0; ; x++) {
  559. snprintf(new, sizeof(new), "%s.%d", filename, x);
  560. fd = open(new, O_RDONLY);
  561. if (fd > -1)
  562. close(fd);
  563. else
  564. break;
  565. }
  566. if (rename(filename, new)) {
  567. fprintf(stderr, "Unable to rename file '%s' to '%s'\n", filename, new);
  568. res = -1;
  569. } else {
  570. filename = new;
  571. }
  572. break;
  573. case TIMESTAMP:
  574. snprintf(new, sizeof(new), "%s.%ld", filename, (long)time(NULL));
  575. if (rename(filename, new)) {
  576. fprintf(stderr, "Unable to rename file '%s' to '%s'\n", filename, new);
  577. res = -1;
  578. } else {
  579. filename = new;
  580. }
  581. break;
  582. case ROTATE:
  583. /* Find the next empty slot, including a possible suffix */
  584. for (x = 0; ; x++) {
  585. found = 0;
  586. for (which = 0; which < ARRAY_LEN(suffixes); which++) {
  587. snprintf(new, sizeof(new), "%s.%d%s", filename, x, suffixes[which]);
  588. fd = open(new, O_RDONLY);
  589. if (fd > -1) {
  590. close(fd);
  591. found = 1;
  592. break;
  593. }
  594. }
  595. if (!found) {
  596. break;
  597. }
  598. }
  599. /* Found an empty slot */
  600. for (y = x; y > 0; y--) {
  601. for (which = 0; which < ARRAY_LEN(suffixes); which++) {
  602. snprintf(old, sizeof(old), "%s.%d%s", filename, y - 1, suffixes[which]);
  603. fd = open(old, O_RDONLY);
  604. if (fd > -1) {
  605. /* Found the right suffix */
  606. close(fd);
  607. snprintf(new, sizeof(new), "%s.%d%s", filename, y, suffixes[which]);
  608. if (rename(old, new)) {
  609. fprintf(stderr, "Unable to rename file '%s' to '%s'\n", old, new);
  610. res = -1;
  611. }
  612. break;
  613. }
  614. }
  615. }
  616. /* Finally, rename the current file */
  617. snprintf(new, sizeof(new), "%s.0", filename);
  618. if (rename(filename, new)) {
  619. fprintf(stderr, "Unable to rename file '%s' to '%s'\n", filename, new);
  620. res = -1;
  621. } else {
  622. filename = new;
  623. }
  624. }
  625. if (!ast_strlen_zero(exec_after_rotate)) {
  626. struct ast_channel *c = ast_dummy_channel_alloc();
  627. char buf[512];
  628. pbx_builtin_setvar_helper(c, "filename", filename);
  629. pbx_substitute_variables_helper(c, exec_after_rotate, buf, sizeof(buf));
  630. if (c) {
  631. c = ast_channel_unref(c);
  632. }
  633. if (ast_safe_system(buf) == -1) {
  634. ast_log(LOG_WARNING, "error executing '%s'\n", buf);
  635. }
  636. }
  637. return res;
  638. }
  639. /*!
  640. * \internal
  641. * \brief Start the realtime queue logging if configured.
  642. *
  643. * \retval TRUE if not to open queue log file.
  644. */
  645. static int logger_queue_rt_start(void)
  646. {
  647. if (ast_check_realtime("queue_log")) {
  648. if (!ast_realtime_require_field("queue_log",
  649. "time", RQ_DATETIME, 26,
  650. "data1", RQ_CHAR, 20,
  651. "data2", RQ_CHAR, 20,
  652. "data3", RQ_CHAR, 20,
  653. "data4", RQ_CHAR, 20,
  654. "data5", RQ_CHAR, 20,
  655. SENTINEL)) {
  656. logfiles.queue_adaptive_realtime = 1;
  657. } else {
  658. logfiles.queue_adaptive_realtime = 0;
  659. }
  660. if (!logfiles.queue_log_to_file) {
  661. /* Don't open the log file. */
  662. return 1;
  663. }
  664. }
  665. return 0;
  666. }
  667. /*!
  668. * \internal
  669. * \brief Rotate the queue log file and restart.
  670. *
  671. * \param queue_rotate Log queue rotation mode.
  672. *
  673. * \note Assumes logchannels is write locked on entry.
  674. *
  675. * \retval 0 on success.
  676. * \retval -1 on error.
  677. */
  678. static int logger_queue_restart(int queue_rotate)
  679. {
  680. int res = 0;
  681. char qfname[PATH_MAX];
  682. if (logger_queue_rt_start()) {
  683. return res;
  684. }
  685. snprintf(qfname, sizeof(qfname), "%s/%s", ast_config_AST_LOG_DIR, queue_log_name);
  686. if (qlog) {
  687. /* Just in case it was still open. */
  688. fclose(qlog);
  689. qlog = NULL;
  690. }
  691. if (queue_rotate) {
  692. rotate_file(qfname);
  693. }
  694. /* Open the log file. */
  695. qlog = fopen(qfname, "a");
  696. if (!qlog) {
  697. ast_log(LOG_ERROR, "Unable to create queue log: %s\n", strerror(errno));
  698. res = -1;
  699. }
  700. return res;
  701. }
  702. static int reload_logger(int rotate, const char *altconf)
  703. {
  704. int queue_rotate = rotate;
  705. struct logchannel *f;
  706. int res = 0;
  707. AST_RWLIST_WRLOCK(&logchannels);
  708. if (qlog) {
  709. if (rotate < 0) {
  710. /* Check filesize - this one typically doesn't need an auto-rotate */
  711. if (ftello(qlog) > 0x40000000) { /* Arbitrarily, 1 GB */
  712. fclose(qlog);
  713. qlog = NULL;
  714. } else {
  715. queue_rotate = 0;
  716. }
  717. } else {
  718. fclose(qlog);
  719. qlog = NULL;
  720. }
  721. } else {
  722. queue_rotate = 0;
  723. }
  724. ast_mkdir(ast_config_AST_LOG_DIR, 0777);
  725. AST_RWLIST_TRAVERSE(&logchannels, f, list) {
  726. if (f->disabled) {
  727. f->disabled = 0; /* Re-enable logging at reload */
  728. /*** DOCUMENTATION
  729. <managerEventInstance>
  730. <synopsis>Raised when a logging channel is re-enabled after a reload operation.</synopsis>
  731. <syntax>
  732. <parameter name="Channel">
  733. <para>The name of the logging channel.</para>
  734. </parameter>
  735. </syntax>
  736. </managerEventInstance>
  737. ***/
  738. manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: Yes\r\n", f->filename);
  739. }
  740. if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
  741. int rotate_this = 0;
  742. if (ftello(f->fileptr) > 0x40000000) { /* Arbitrarily, 1 GB */
  743. /* Be more proactive about rotating massive log files */
  744. rotate_this = 1;
  745. }
  746. fclose(f->fileptr); /* Close file */
  747. f->fileptr = NULL;
  748. if (rotate || rotate_this) {
  749. rotate_file(f->filename);
  750. }
  751. }
  752. }
  753. filesize_reload_needed = 0;
  754. init_logger_chain(1 /* locked */, altconf);
  755. ast_unload_realtime("queue_log");
  756. if (logfiles.queue_log) {
  757. res = logger_queue_restart(queue_rotate);
  758. AST_RWLIST_UNLOCK(&logchannels);
  759. ast_verb_update();
  760. ast_queue_log("NONE", "NONE", "NONE", "CONFIGRELOAD", "%s", "");
  761. ast_verb(1, "Asterisk Queue Logger restarted\n");
  762. } else {
  763. AST_RWLIST_UNLOCK(&logchannels);
  764. ast_verb_update();
  765. }
  766. return res;
  767. }
  768. /*! \brief Reload the logger module without rotating log files (also used from loader.c during
  769. a full Asterisk reload) */
  770. int logger_reload(void)
  771. {
  772. if (reload_logger(0, NULL)) {
  773. return RESULT_FAILURE;
  774. }
  775. return RESULT_SUCCESS;
  776. }
  777. static char *handle_logger_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  778. {
  779. switch (cmd) {
  780. case CLI_INIT:
  781. e->command = "logger reload";
  782. e->usage =
  783. "Usage: logger reload [<alt-conf>]\n"
  784. " Reloads the logger subsystem state. Use after restarting syslogd(8) if you are using syslog logging.\n";
  785. return NULL;
  786. case CLI_GENERATE:
  787. return NULL;
  788. }
  789. if (reload_logger(0, a->argc == 3 ? a->argv[2] : NULL)) {
  790. ast_cli(a->fd, "Failed to reload the logger\n");
  791. return CLI_FAILURE;
  792. }
  793. return CLI_SUCCESS;
  794. }
  795. static char *handle_logger_rotate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  796. {
  797. switch (cmd) {
  798. case CLI_INIT:
  799. e->command = "logger rotate";
  800. e->usage =
  801. "Usage: logger rotate\n"
  802. " Rotates and Reopens the log files.\n";
  803. return NULL;
  804. case CLI_GENERATE:
  805. return NULL;
  806. }
  807. if (reload_logger(1, NULL)) {
  808. ast_cli(a->fd, "Failed to reload the logger and rotate log files\n");
  809. return CLI_FAILURE;
  810. }
  811. return CLI_SUCCESS;
  812. }
  813. static char *handle_logger_set_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  814. {
  815. int x;
  816. int state;
  817. int level = -1;
  818. switch (cmd) {
  819. case CLI_INIT:
  820. e->command = "logger set level {DEBUG|NOTICE|WARNING|ERROR|VERBOSE|DTMF} {on|off}";
  821. e->usage =
  822. "Usage: logger set level {DEBUG|NOTICE|WARNING|ERROR|VERBOSE|DTMF} {on|off}\n"
  823. " Set a specific log level to enabled/disabled for this console.\n";
  824. return NULL;
  825. case CLI_GENERATE:
  826. return NULL;
  827. }
  828. if (a->argc < 5)
  829. return CLI_SHOWUSAGE;
  830. AST_RWLIST_WRLOCK(&logchannels);
  831. for (x = 0; x < ARRAY_LEN(levels); x++) {
  832. if (levels[x] && !strcasecmp(a->argv[3], levels[x])) {
  833. level = x;
  834. break;
  835. }
  836. }
  837. AST_RWLIST_UNLOCK(&logchannels);
  838. state = ast_true(a->argv[4]) ? 1 : 0;
  839. if (level != -1) {
  840. ast_console_toggle_loglevel(a->fd, level, state);
  841. ast_cli(a->fd, "Logger status for '%s' has been set to '%s'.\n", levels[level], state ? "on" : "off");
  842. } else
  843. return CLI_SHOWUSAGE;
  844. return CLI_SUCCESS;
  845. }
  846. /*! \brief CLI command to show logging system configuration */
  847. static char *handle_logger_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  848. {
  849. #define FORMATL "%-35.35s %-8.8s %-9.9s "
  850. struct logchannel *chan;
  851. switch (cmd) {
  852. case CLI_INIT:
  853. e->command = "logger show channels";
  854. e->usage =
  855. "Usage: logger show channels\n"
  856. " List configured logger channels.\n";
  857. return NULL;
  858. case CLI_GENERATE:
  859. return NULL;
  860. }
  861. ast_cli(a->fd, FORMATL, "Channel", "Type", "Status");
  862. ast_cli(a->fd, "Configuration\n");
  863. ast_cli(a->fd, FORMATL, "-------", "----", "------");
  864. ast_cli(a->fd, "-------------\n");
  865. AST_RWLIST_RDLOCK(&logchannels);
  866. AST_RWLIST_TRAVERSE(&logchannels, chan, list) {
  867. unsigned int level;
  868. ast_cli(a->fd, FORMATL, chan->filename, chan->type == LOGTYPE_CONSOLE ? "Console" : (chan->type == LOGTYPE_SYSLOG ? "Syslog" : "File"),
  869. chan->disabled ? "Disabled" : "Enabled");
  870. ast_cli(a->fd, " - ");
  871. for (level = 0; level < ARRAY_LEN(levels); level++) {
  872. if ((chan->logmask & (1 << level)) && levels[level]) {
  873. ast_cli(a->fd, "%s ", levels[level]);
  874. }
  875. }
  876. ast_cli(a->fd, "\n");
  877. }
  878. AST_RWLIST_UNLOCK(&logchannels);
  879. ast_cli(a->fd, "\n");
  880. return CLI_SUCCESS;
  881. }
  882. struct verb {
  883. void (*verboser)(const char *string);
  884. AST_LIST_ENTRY(verb) list;
  885. };
  886. static AST_RWLIST_HEAD_STATIC(verbosers, verb);
  887. static struct ast_cli_entry cli_logger[] = {
  888. AST_CLI_DEFINE(handle_logger_show_channels, "List configured log channels"),
  889. AST_CLI_DEFINE(handle_logger_reload, "Reopens the log files"),
  890. AST_CLI_DEFINE(handle_logger_rotate, "Rotates and reopens the log files"),
  891. AST_CLI_DEFINE(handle_logger_set_level, "Enables/Disables a specific logging level for this console"),
  892. };
  893. static void _handle_SIGXFSZ(int sig)
  894. {
  895. /* Indicate need to reload */
  896. filesize_reload_needed = 1;
  897. }
  898. static struct sigaction handle_SIGXFSZ = {
  899. .sa_handler = _handle_SIGXFSZ,
  900. .sa_flags = SA_RESTART,
  901. };
  902. static void ast_log_vsyslog(struct logmsg *msg)
  903. {
  904. char buf[BUFSIZ];
  905. int syslog_level = ast_syslog_priority_from_loglevel(msg->level);
  906. char call_identifier_str[13];
  907. if (msg->callid) {
  908. snprintf(call_identifier_str, sizeof(call_identifier_str), "[C-%08x]", (unsigned)msg->callid->call_identifier);
  909. } else {
  910. call_identifier_str[0] = '\0';
  911. }
  912. if (syslog_level < 0) {
  913. /* we are locked here, so cannot ast_log() */
  914. fprintf(stderr, "ast_log_vsyslog called with bogus level: %d\n", msg->level);
  915. return;
  916. }
  917. snprintf(buf, sizeof(buf), "%s[%d]%s: %s:%d in %s: %s",
  918. levels[msg->level], msg->lwp, call_identifier_str, msg->file, msg->line, msg->function, msg->message);
  919. term_strip(buf, buf, strlen(buf) + 1);
  920. syslog(syslog_level, "%s", buf);
  921. }
  922. static char *logger_strip_verbose_magic(const char *message, int level)
  923. {
  924. const char *begin, *end;
  925. char *stripped_message, *dst;
  926. char magic = -(level + 1);
  927. if (!(stripped_message = ast_malloc(strlen(message) + 1))) {
  928. return NULL;
  929. }
  930. begin = message;
  931. dst = stripped_message;
  932. do {
  933. end = strchr(begin, magic);
  934. if (end) {
  935. size_t len = end - begin;
  936. memcpy(dst, begin, len);
  937. begin = end + 1;
  938. dst += len;
  939. } else {
  940. strcpy(dst, begin); /* safe */
  941. break;
  942. }
  943. } while (1);
  944. return stripped_message;
  945. }
  946. /*! \brief Print a normal log message to the channels */
  947. static void logger_print_normal(struct logmsg *logmsg)
  948. {
  949. struct logchannel *chan = NULL;
  950. char buf[BUFSIZ];
  951. struct verb *v = NULL;
  952. char *tmpmsg;
  953. int level = 0;
  954. if (logmsg->level == __LOG_VERBOSE) {
  955. /* Iterate through the list of verbosers and pass them the log message string */
  956. AST_RWLIST_RDLOCK(&verbosers);
  957. AST_RWLIST_TRAVERSE(&verbosers, v, list)
  958. v->verboser(logmsg->message);
  959. AST_RWLIST_UNLOCK(&verbosers);
  960. level = VERBOSE_MAGIC2LEVEL(logmsg->message);
  961. tmpmsg = logger_strip_verbose_magic(logmsg->message, level);
  962. if (tmpmsg) {
  963. ast_string_field_set(logmsg, message, tmpmsg);
  964. ast_free(tmpmsg);
  965. }
  966. }
  967. AST_RWLIST_RDLOCK(&logchannels);
  968. if (!AST_RWLIST_EMPTY(&logchannels)) {
  969. AST_RWLIST_TRAVERSE(&logchannels, chan, list) {
  970. char call_identifier_str[13];
  971. if (logmsg->callid) {
  972. snprintf(call_identifier_str, sizeof(call_identifier_str), "[C-%08x]", (unsigned)logmsg->callid->call_identifier);
  973. } else {
  974. call_identifier_str[0] = '\0';
  975. }
  976. /* If the channel is disabled, then move on to the next one */
  977. if (chan->disabled) {
  978. continue;
  979. }
  980. if (logmsg->level == __LOG_VERBOSE
  981. && (((chan->verbosity < 0) ? option_verbose : chan->verbosity)) < level) {
  982. continue;
  983. }
  984. /* Check syslog channels */
  985. if (chan->type == LOGTYPE_SYSLOG && (chan->logmask & (1 << logmsg->level))) {
  986. ast_log_vsyslog(logmsg);
  987. /* Console channels */
  988. } else if (chan->type == LOGTYPE_CONSOLE && (chan->logmask & (1 << logmsg->level))) {
  989. char linestr[128];
  990. char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
  991. /* If the level is verbose, then skip it */
  992. if (logmsg->level == __LOG_VERBOSE)
  993. continue;
  994. /* Turn the numerical line number into a string */
  995. snprintf(linestr, sizeof(linestr), "%d", logmsg->line);
  996. /* Build string to print out */
  997. snprintf(buf, sizeof(buf), "[%s] %s[%d]%s: %s:%s %s: %s",
  998. logmsg->date,
  999. term_color(tmp1, logmsg->level_name, colors[logmsg->level], 0, sizeof(tmp1)),
  1000. logmsg->lwp,
  1001. call_identifier_str,
  1002. term_color(tmp2, logmsg->file, COLOR_BRWHITE, 0, sizeof(tmp2)),
  1003. term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
  1004. term_color(tmp4, logmsg->function, COLOR_BRWHITE, 0, sizeof(tmp4)),
  1005. logmsg->message);
  1006. /* Print out */
  1007. ast_console_puts_mutable(buf, logmsg->level);
  1008. /* File channels */
  1009. } else if (chan->type == LOGTYPE_FILE && (chan->logmask & (1 << logmsg->level))) {
  1010. int res = 0;
  1011. /* If no file pointer exists, skip it */
  1012. if (!chan->fileptr) {
  1013. continue;
  1014. }
  1015. /* Print out to the file */
  1016. res = fprintf(chan->fileptr, "[%s] %s[%d]%s %s: %s",
  1017. logmsg->date, logmsg->level_name, logmsg->lwp, call_identifier_str,
  1018. logmsg->file, term_strip(buf, logmsg->message, BUFSIZ));
  1019. if (res <= 0 && !ast_strlen_zero(logmsg->message)) {
  1020. fprintf(stderr, "**** Asterisk Logging Error: ***********\n");
  1021. if (errno == ENOMEM || errno == ENOSPC)
  1022. fprintf(stderr, "Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->filename);
  1023. else
  1024. fprintf(stderr, "Logger Warning: Unable to write to log file '%s': %s (disabled)\n", chan->filename, strerror(errno));
  1025. /*** DOCUMENTATION
  1026. <managerEventInstance>
  1027. <synopsis>Raised when a logging channel is disabled.</synopsis>
  1028. <syntax>
  1029. <parameter name="Channel">
  1030. <para>The name of the logging channel.</para>
  1031. </parameter>
  1032. </syntax>
  1033. </managerEventInstance>
  1034. ***/
  1035. manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: No\r\nReason: %d - %s\r\n", chan->filename, errno, strerror(errno));
  1036. chan->disabled = 1;
  1037. } else if (res > 0) {
  1038. fflush(chan->fileptr);
  1039. }
  1040. }
  1041. }
  1042. } else if (logmsg->level != __LOG_VERBOSE) {
  1043. fputs(logmsg->message, stdout);
  1044. }
  1045. AST_RWLIST_UNLOCK(&logchannels);
  1046. /* If we need to reload because of the file size, then do so */
  1047. if (filesize_reload_needed) {
  1048. reload_logger(-1, NULL);
  1049. ast_verb(1, "Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
  1050. }
  1051. return;
  1052. }
  1053. /*! \brief Actual logging thread */
  1054. static void *logger_thread(void *data)
  1055. {
  1056. struct logmsg *next = NULL, *msg = NULL;
  1057. for (;;) {
  1058. /* We lock the message list, and see if any message exists... if not we wait on the condition to be signalled */
  1059. AST_LIST_LOCK(&logmsgs);
  1060. if (AST_LIST_EMPTY(&logmsgs)) {
  1061. if (close_logger_thread) {
  1062. AST_LIST_UNLOCK(&logmsgs);
  1063. break;
  1064. } else {
  1065. ast_cond_wait(&logcond, &logmsgs.lock);
  1066. }
  1067. }
  1068. next = AST_LIST_FIRST(&logmsgs);
  1069. AST_LIST_HEAD_INIT_NOLOCK(&logmsgs);
  1070. AST_LIST_UNLOCK(&logmsgs);
  1071. /* Otherwise go through and process each message in the order added */
  1072. while ((msg = next)) {
  1073. /* Get the next entry now so that we can free our current structure later */
  1074. next = AST_LIST_NEXT(msg, list);
  1075. /* Depending on the type, send it to the proper function */
  1076. logger_print_normal(msg);
  1077. /* Free the data since we are done */
  1078. logmsg_free(msg);
  1079. }
  1080. }
  1081. return NULL;
  1082. }
  1083. /*!
  1084. * \internal
  1085. * \brief Initialize the logger queue.
  1086. *
  1087. * \note Assumes logchannels is write locked on entry.
  1088. *
  1089. * \return Nothing
  1090. */
  1091. static void logger_queue_init(void)
  1092. {
  1093. ast_unload_realtime("queue_log");
  1094. if (logfiles.queue_log) {
  1095. char qfname[PATH_MAX];
  1096. if (logger_queue_rt_start()) {
  1097. return;
  1098. }
  1099. /* Open the log file. */
  1100. snprintf(qfname, sizeof(qfname), "%s/%s", ast_config_AST_LOG_DIR,
  1101. queue_log_name);
  1102. if (qlog) {
  1103. /* Just in case it was already open. */
  1104. fclose(qlog);
  1105. }
  1106. qlog = fopen(qfname, "a");
  1107. if (!qlog) {
  1108. ast_log(LOG_ERROR, "Unable to create queue log: %s\n", strerror(errno));
  1109. }
  1110. }
  1111. }
  1112. /*!
  1113. * \brief Start the ast_queue_log() logger.
  1114. *
  1115. * \note Called when the system is fully booted after startup
  1116. * so preloaded realtime modules can get up.
  1117. *
  1118. * \return Nothing
  1119. */
  1120. void logger_queue_start(void)
  1121. {
  1122. /* Must not be called before the logger is initialized. */
  1123. ast_assert(logger_initialized);
  1124. AST_RWLIST_WRLOCK(&logchannels);
  1125. if (!queuelog_init) {
  1126. logger_queue_init();
  1127. queuelog_init = 1;
  1128. AST_RWLIST_UNLOCK(&logchannels);
  1129. ast_queue_log("NONE", "NONE", "NONE", "QUEUESTART", "%s", "");
  1130. } else {
  1131. AST_RWLIST_UNLOCK(&logchannels);
  1132. }
  1133. }
  1134. int init_logger(void)
  1135. {
  1136. int res;
  1137. /* auto rotate if sig SIGXFSZ comes a-knockin */
  1138. sigaction(SIGXFSZ, &handle_SIGXFSZ, NULL);
  1139. /* Re-initialize the logmsgs mutex. The recursive mutex can be accessed prior
  1140. * to Asterisk being forked into the background, which can cause the thread
  1141. * ID tracked by the underlying pthread mutex to be different than the ID of
  1142. * the thread that unlocks the mutex. Since init_logger is called after the
  1143. * fork, it is safe to initialize the mutex here for future accesses.
  1144. */
  1145. ast_mutex_destroy(&logmsgs.lock);
  1146. ast_mutex_init(&logmsgs.lock);
  1147. ast_cond_init(&logcond, NULL);
  1148. /* start logger thread */
  1149. if (ast_pthread_create(&logthread, NULL, logger_thread, NULL) < 0) {
  1150. ast_cond_destroy(&logcond);
  1151. return -1;
  1152. }
  1153. /* register the logger cli commands */
  1154. ast_cli_register_multiple(cli_logger, ARRAY_LEN(cli_logger));
  1155. ast_mkdir(ast_config_AST_LOG_DIR, 0777);
  1156. /* create log channels */
  1157. res = init_logger_chain(0 /* locked */, NULL);
  1158. ast_verb_update();
  1159. logger_initialized = 1;
  1160. if (res) {
  1161. ast_log(LOG_ERROR, "Errors detected in logger.conf. Default console logging is being used.\n");
  1162. }
  1163. return 0;
  1164. }
  1165. void close_logger(void)
  1166. {
  1167. struct logchannel *f = NULL;
  1168. struct verb *cur = NULL;
  1169. ast_cli_unregister_multiple(cli_logger, ARRAY_LEN(cli_logger));
  1170. logger_initialized = 0;
  1171. /* Stop logger thread */
  1172. AST_LIST_LOCK(&logmsgs);
  1173. close_logger_thread = 1;
  1174. ast_cond_signal(&logcond);
  1175. AST_LIST_UNLOCK(&logmsgs);
  1176. if (logthread != AST_PTHREADT_NULL)
  1177. pthread_join(logthread, NULL);
  1178. AST_RWLIST_WRLOCK(&verbosers);
  1179. while ((cur = AST_LIST_REMOVE_HEAD(&verbosers, list))) {
  1180. ast_free(cur);
  1181. }
  1182. AST_RWLIST_UNLOCK(&verbosers);
  1183. AST_RWLIST_WRLOCK(&logchannels);
  1184. if (qlog) {
  1185. fclose(qlog);
  1186. qlog = NULL;
  1187. }
  1188. while ((f = AST_LIST_REMOVE_HEAD(&logchannels, list))) {
  1189. if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
  1190. fclose(f->fileptr);
  1191. f->fileptr = NULL;
  1192. }
  1193. ast_free(f);
  1194. }
  1195. closelog(); /* syslog */
  1196. AST_RWLIST_UNLOCK(&logchannels);
  1197. }
  1198. void ast_callid_strnprint(char *buffer, size_t buffer_size, struct ast_callid *callid)
  1199. {
  1200. snprintf(buffer, buffer_size, "[C-%08x]", (unsigned)callid->call_identifier);
  1201. }
  1202. struct ast_callid *ast_create_callid(void)
  1203. {
  1204. struct ast_callid *call;
  1205. call = ao2_alloc_options(sizeof(*call), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
  1206. if (!call) {
  1207. ast_log(LOG_ERROR, "Could not allocate callid struct.\n");
  1208. return NULL;
  1209. }
  1210. call->call_identifier = ast_atomic_fetchadd_int(&next_unique_callid, +1);
  1211. #ifdef TEST_FRAMEWORK
  1212. ast_debug(3, "CALL_ID [C-%08x] created by thread.\n", (unsigned)call->call_identifier);
  1213. #endif
  1214. return call;
  1215. }
  1216. struct ast_callid *ast_read_threadstorage_callid(void)
  1217. {
  1218. struct ast_callid **callid;
  1219. callid = ast_threadstorage_get(&unique_callid, sizeof(*callid));
  1220. if (callid && *callid) {
  1221. ast_callid_ref(*callid);
  1222. return *callid;
  1223. }
  1224. return NULL;
  1225. }
  1226. int ast_callid_threadassoc_change(struct ast_callid *callid)
  1227. {
  1228. struct ast_callid **id = ast_threadstorage_get(&unique_callid, sizeof(*id));
  1229. if (!id) {
  1230. ast_log(LOG_ERROR, "Failed to allocate thread storage.\n");
  1231. return -1;
  1232. }
  1233. if (*id && (*id != callid)) {
  1234. #ifdef TEST_FRAMEWORK
  1235. ast_debug(3, "CALL_ID [C-%08x] being removed from thread.\n", (unsigned)(*id)->call_identifier);
  1236. #endif
  1237. *id = ast_callid_unref(*id);
  1238. *id = NULL;
  1239. }
  1240. if (!(*id) && callid) {
  1241. /* callid will be unreffed at thread destruction */
  1242. ast_callid_ref(callid);
  1243. *id = callid;
  1244. #ifdef TEST_FRAMEWORK
  1245. ast_debug(3, "CALL_ID [C-%08x] bound to thread.\n", (unsigned)callid->call_identifier);
  1246. #endif
  1247. }
  1248. return 0;
  1249. }
  1250. int ast_callid_threadassoc_add(struct ast_callid *callid)
  1251. {
  1252. struct ast_callid **pointing;
  1253. pointing = ast_threadstorage_get(&unique_callid, sizeof(*pointing));
  1254. if (!(pointing)) {
  1255. ast_log(LOG_ERROR, "Failed to allocate thread storage.\n");
  1256. return -1;
  1257. }
  1258. if (!(*pointing)) {
  1259. /* callid will be unreffed at thread destruction */
  1260. ast_callid_ref(callid);
  1261. *pointing = callid;
  1262. #ifdef TEST_FRAMEWORK
  1263. ast_debug(3, "CALL_ID [C-%08x] bound to thread.\n", (unsigned)callid->call_identifier);
  1264. #endif
  1265. } else {
  1266. ast_log(LOG_WARNING, "Attempted to ast_callid_threadassoc_add on thread already associated with a callid.\n");
  1267. return 1;
  1268. }
  1269. return 0;
  1270. }
  1271. int ast_callid_threadassoc_remove(void)
  1272. {
  1273. struct ast_callid **pointing;
  1274. pointing = ast_threadstorage_get(&unique_callid, sizeof(*pointing));
  1275. if (!(pointing)) {
  1276. ast_log(LOG_ERROR, "Failed to allocate thread storage.\n");
  1277. return -1;
  1278. }
  1279. if (!(*pointing)) {
  1280. ast_log(LOG_ERROR, "Tried to clean callid thread storage with no callid in thread storage.\n");
  1281. return -1;
  1282. } else {
  1283. #ifdef TEST_FRAMEWORK
  1284. ast_debug(3, "Call_ID [C-%08x] being removed from thread.\n", (unsigned)(*pointing)->call_identifier);
  1285. #endif
  1286. *pointing = ast_callid_unref(*pointing);
  1287. return 0;
  1288. }
  1289. }
  1290. int ast_callid_threadstorage_auto(struct ast_callid **callid)
  1291. {
  1292. struct ast_callid *tmp;
  1293. /* Start by trying to see if a callid is available from thread storage */
  1294. tmp = ast_read_threadstorage_callid();
  1295. if (tmp) {
  1296. *callid = tmp;
  1297. return 0;
  1298. }
  1299. /* If that failed, try to create a new one and bind it. */
  1300. tmp = ast_create_callid();
  1301. if (tmp) {
  1302. ast_callid_threadassoc_add(tmp);
  1303. *callid = tmp;
  1304. return 1;
  1305. }
  1306. /* If neither worked, then something must have gone wrong. */
  1307. return -1;
  1308. }
  1309. void ast_callid_threadstorage_auto_clean(struct ast_callid *callid, int callid_created)
  1310. {
  1311. if (callid) {
  1312. /* If the callid was created rather than simply grabbed from the thread storage, we need to unbind here. */
  1313. if (callid_created == 1) {
  1314. ast_callid_threadassoc_remove();
  1315. }
  1316. callid = ast_callid_unref(callid);
  1317. }
  1318. }
  1319. /*!
  1320. * \internal
  1321. * \brief thread storage cleanup function for unique_callid
  1322. */
  1323. static void unique_callid_cleanup(void *data)
  1324. {
  1325. struct ast_callid **callid = data;
  1326. if (*callid) {
  1327. ast_callid_unref(*callid);
  1328. }
  1329. ast_free(data);
  1330. }
  1331. /*!
  1332. * \brief send log messages to syslog and/or the console
  1333. */
  1334. static void __attribute__((format(printf, 6, 0))) ast_log_full(int level, const char *file, int line, const char *function, struct ast_callid *callid, const char *fmt, va_list ap)
  1335. {
  1336. struct logmsg *logmsg = NULL;
  1337. struct ast_str *buf = NULL;
  1338. struct ast_tm tm;
  1339. struct timeval now = ast_tvnow();
  1340. int res = 0;
  1341. char datestring[256];
  1342. if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE)))
  1343. return;
  1344. if (level != __LOG_VERBOSE && AST_RWLIST_EMPTY(&logchannels)) {
  1345. /*
  1346. * we don't have the logger chain configured yet,
  1347. * so just log to stdout
  1348. */
  1349. int result;
  1350. result = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */
  1351. if (result != AST_DYNSTR_BUILD_FAILED) {
  1352. term_filter_escapes(ast_str_buffer(buf));
  1353. fputs(ast_str_buffer(buf), stdout);
  1354. }
  1355. return;
  1356. }
  1357. /* Ignore anything that never gets logged anywhere */
  1358. if (level != __LOG_VERBOSE && !(global_logmask & (1 << level)))
  1359. return;
  1360. /* Build string */
  1361. res = ast_str_set_va(&buf, BUFSIZ, fmt, ap);
  1362. /* If the build failed, then abort and free this structure */
  1363. if (res == AST_DYNSTR_BUILD_FAILED)
  1364. return;
  1365. /* Create a new logging message */
  1366. if (!(logmsg = ast_calloc_with_stringfields(1, struct logmsg, res + 128)))
  1367. return;
  1368. /* Copy string over */
  1369. ast_string_field_set(logmsg, message, ast_str_buffer(buf));
  1370. /* Set type */
  1371. if (level == __LOG_VERBOSE) {
  1372. logmsg->type = LOGMSG_VERBOSE;
  1373. } else {
  1374. logmsg->type = LOGMSG_NORMAL;
  1375. }
  1376. if (display_callids && callid) {
  1377. logmsg->callid = ast_callid_ref(callid);
  1378. /* callid will be unreffed at logmsg destruction */
  1379. }
  1380. /* Create our date/time */
  1381. ast_localtime(&now, &tm, NULL);
  1382. ast_strftime(datestring, sizeof(datestring), dateformat, &tm);
  1383. ast_string_field_set(logmsg, date, datestring);
  1384. /* Copy over data */
  1385. logmsg->level = level;
  1386. logmsg->line = line;
  1387. ast_string_field_set(logmsg, level_name, levels[level]);
  1388. ast_string_field_set(logmsg, file, file);
  1389. ast_string_field_set(logmsg, function, function);
  1390. logmsg->lwp = ast_get_tid();
  1391. /* If the logger thread is active, append it to the tail end of the list - otherwise skip that step */
  1392. if (logthread != AST_PTHREADT_NULL) {
  1393. AST_LIST_LOCK(&logmsgs);
  1394. if (close_logger_thread) {
  1395. /* Logger is either closing or closed. We cannot log this message. */
  1396. logmsg_free(logmsg);
  1397. } else {
  1398. AST_LIST_INSERT_TAIL(&logmsgs, logmsg, list);
  1399. ast_cond_signal(&logcond);
  1400. }
  1401. AST_LIST_UNLOCK(&logmsgs);
  1402. } else {
  1403. logger_print_normal(logmsg);
  1404. logmsg_free(logmsg);
  1405. }
  1406. }
  1407. void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
  1408. {
  1409. struct ast_callid *callid;
  1410. va_list ap;
  1411. callid = ast_read_threadstorage_callid();
  1412. va_start(ap, fmt);
  1413. if (level == __LOG_VERBOSE) {
  1414. __ast_verbose_ap(file, line, function, 0, callid, fmt, ap);
  1415. } else {
  1416. ast_log_full(level, file, line, function, callid, fmt, ap);
  1417. }
  1418. va_end(ap);
  1419. if (callid) {
  1420. ast_callid_unref(callid);
  1421. }
  1422. }
  1423. void ast_log_safe(int level, const char *file, int line, const char *function, const char *fmt, ...)
  1424. {
  1425. va_list ap;
  1426. void *recursed = ast_threadstorage_get_ptr(&in_safe_log);
  1427. struct ast_callid *callid;
  1428. if (recursed) {
  1429. return;
  1430. }
  1431. if (ast_threadstorage_set_ptr(&in_safe_log, (void*)1)) {
  1432. /* We've failed to set the flag that protects against
  1433. * recursion, so bail. */
  1434. return;
  1435. }
  1436. callid = ast_read_threadstorage_callid();
  1437. va_start(ap, fmt);
  1438. ast_log_full(level, file, line, function, callid, fmt, ap);
  1439. va_end(ap);
  1440. if (callid) {
  1441. ast_callid_unref(callid);
  1442. }
  1443. /* Clear flag so the next allocation failure can be logged. */
  1444. ast_threadstorage_set_ptr(&in_safe_log, NULL);
  1445. }
  1446. void ast_log_callid(int level, const char *file, int line, const char *function, struct ast_callid *callid, const char *fmt, ...)
  1447. {
  1448. va_list ap;
  1449. va_start(ap, fmt);
  1450. ast_log_full(level, file, line, function, callid, fmt, ap);
  1451. va_end(ap);
  1452. }
  1453. #ifdef HAVE_BKTR
  1454. struct ast_bt *ast_bt_create(void)
  1455. {
  1456. struct ast_bt *bt = ast_calloc(1, sizeof(*bt));
  1457. if (!bt) {
  1458. ast_log(LOG_ERROR, "Unable to allocate memory for backtrace structure!\n");
  1459. return NULL;
  1460. }
  1461. bt->alloced = 1;
  1462. ast_bt_get_addresses(bt);
  1463. return bt;
  1464. }
  1465. int ast_bt_get_addresses(struct ast_bt *bt)
  1466. {
  1467. bt->num_frames = backtrace(bt->addresses, AST_MAX_BT_FRAMES);
  1468. return 0;
  1469. }
  1470. void *ast_bt_destroy(struct ast_bt *bt)
  1471. {
  1472. if (bt->alloced) {
  1473. ast_free(bt);
  1474. }
  1475. return NULL;
  1476. }
  1477. char **ast_bt_get_symbols(void **addresses, size_t num_frames)
  1478. {
  1479. char **strings;
  1480. #if defined(BETTER_BACKTRACES)
  1481. int stackfr;
  1482. bfd *bfdobj; /* bfd.h */
  1483. Dl_info dli; /* dlfcn.h */
  1484. long allocsize;
  1485. asymbol **syms = NULL; /* bfd.h */
  1486. bfd_vma offset; /* bfd.h */
  1487. const char *lastslash;
  1488. asection *section;
  1489. const char *file, *func;
  1490. unsigned int line;
  1491. char address_str[128];
  1492. char msg[1024];
  1493. size_t strings_size;
  1494. size_t *eachlen;
  1495. #endif
  1496. #if defined(BETTER_BACKTRACES)
  1497. strings_size = num_frames * sizeof(*strings);
  1498. eachlen = ast_calloc(num_frames, sizeof(*eachlen));
  1499. strings = ast_std_calloc(num_frames, sizeof(*strings));
  1500. if (!eachlen || !strings) {
  1501. ast_free(eachlen);
  1502. ast_std_free(strings);
  1503. return NULL;
  1504. }
  1505. for (stackfr = 0; stackfr < num_frames; stackfr++) {
  1506. int found = 0, symbolcount;
  1507. msg[0] = '\0';
  1508. if (!dladdr(addresses[stackfr], &dli)) {
  1509. continue;
  1510. }
  1511. if (strcmp(dli.dli_fname, "asterisk") == 0) {
  1512. char asteriskpath[256];
  1513. if (!(dli.dli_fname = ast_utils_which("asterisk", asteriskpath, sizeof(asteriskpath)))) {
  1514. /* This will fail to find symbols */
  1515. ast_debug(1, "Failed to find asterisk binary for debug symbols.\n");
  1516. dli.dli_fname = "asterisk";
  1517. }
  1518. }
  1519. lastslash = strrchr(dli.dli_fname, '/');
  1520. if ((bfdobj = bfd_openr(dli.dli_fname, NULL)) &&
  1521. bfd_check_format(bfdobj, bfd_object) &&
  1522. (allocsize = bfd_get_symtab_upper_bound(bfdobj)) > 0 &&
  1523. (syms = ast_malloc(allocsize)) &&
  1524. (symbolcount = bfd_canonicalize_symtab(bfdobj, syms))) {
  1525. if (bfdobj->flags & DYNAMIC) {
  1526. offset = addresses[stackfr] - dli.dli_fbase;
  1527. } else {
  1528. offset = addresses[stackfr] - (void *) 0;
  1529. }
  1530. for (section = bfdobj->sections; section; section = section->next) {
  1531. if (!bfd_get_section_flags(bfdobj, section) & SEC_ALLOC ||
  1532. section->vma > offset ||
  1533. section->size + section->vma < offset) {
  1534. continue;
  1535. }
  1536. if (!bfd_find_nearest_line(bfdobj, section, syms, offset - section->vma, &file, &func, &line)) {
  1537. continue;
  1538. }
  1539. /* file can possibly be null even with a success result from bfd_find_nearest_line */
  1540. file = file ? file : "";
  1541. /* Stack trace output */
  1542. found++;
  1543. if ((lastslash = strrchr(file, '/'))) {
  1544. const char *prevslash;
  1545. for (prevslash = lastslash - 1; *prevslash != '/' && prevslash >= file; prevslash--) {
  1546. }
  1547. if (prevslash >= file) {
  1548. lastslash = prevslash;
  1549. }
  1550. }
  1551. if (dli.dli_saddr == NULL) {
  1552. address_str[0] = '\0';
  1553. } else {
  1554. snprintf(address_str, sizeof(address_str), " (%p+%lX)",
  1555. dli.dli_saddr,
  1556. (unsigned long) (addresses[stackfr] - dli.dli_saddr));
  1557. }
  1558. snprintf(msg, sizeof(msg), "%s:%u %s()%s",
  1559. lastslash ? lastslash + 1 : file, line,
  1560. S_OR(func, "???"),
  1561. address_str);
  1562. break; /* out of section iteration */
  1563. }
  1564. }
  1565. if (bfdobj) {
  1566. bfd_close(bfdobj);
  1567. ast_free(syms);
  1568. }
  1569. /* Default output, if we cannot find the information within BFD */
  1570. if (!found) {
  1571. if (dli.dli_saddr == NULL) {
  1572. address_str[0] = '\0';
  1573. } else {
  1574. snprintf(address_str, sizeof(address_str), " (%p+%lX)",
  1575. dli.dli_saddr,
  1576. (unsigned long) (addresses[stackfr] - dli.dli_saddr));
  1577. }
  1578. snprintf(msg, sizeof(msg), "%s %s()%s",
  1579. lastslash ? lastslash + 1 : dli.dli_fname,
  1580. S_OR(dli.dli_sname, "<unknown>"),
  1581. address_str);
  1582. }
  1583. if (!ast_strlen_zero(msg)) {
  1584. char **tmp;
  1585. eachlen[stackfr] = strlen(msg) + 1;
  1586. if (!(tmp = ast_std_realloc(strings, strings_size + eachlen[stackfr]))) {
  1587. ast_std_free(strings);
  1588. strings = NULL;
  1589. break; /* out of stack frame iteration */
  1590. }
  1591. strings = tmp;
  1592. strings[stackfr] = (char *) strings + strings_size;
  1593. strcpy(strings[stackfr], msg);/* Safe since we just allocated the room. */
  1594. strings_size += eachlen[stackfr];
  1595. }
  1596. }
  1597. if (strings) {
  1598. /* Recalculate the offset pointers because of the reallocs. */
  1599. strings[0] = (char *) strings + num_frames * sizeof(*strings);
  1600. for (stackfr = 1; stackfr < num_frames; stackfr++) {
  1601. strings[stackfr] = strings[stackfr - 1] + eachlen[stackfr - 1];
  1602. }
  1603. }
  1604. ast_free(eachlen);
  1605. #else /* !defined(BETTER_BACKTRACES) */
  1606. strings = backtrace_symbols(addresses, num_frames);
  1607. #endif /* defined(BETTER_BACKTRACES) */
  1608. return strings;
  1609. }
  1610. #endif /* HAVE_BKTR */
  1611. void ast_backtrace(void)
  1612. {
  1613. #ifdef HAVE_BKTR
  1614. struct ast_bt *bt;
  1615. int i = 0;
  1616. char **strings;
  1617. if (!(bt = ast_bt_create())) {
  1618. ast_log(LOG_WARNING, "Unable to allocate space for backtrace structure\n");
  1619. return;
  1620. }
  1621. if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
  1622. ast_debug(1, "Got %d backtrace record%c\n", bt->num_frames, bt->num_frames != 1 ? 's' : ' ');
  1623. for (i = 3; i < bt->num_frames - 2; i++) {
  1624. ast_debug(1, "#%d: [%p] %s\n", i - 3, bt->addresses[i], strings[i]);
  1625. }
  1626. ast_std_free(strings);
  1627. } else {
  1628. ast_debug(1, "Could not allocate memory for backtrace\n");
  1629. }
  1630. ast_bt_destroy(bt);
  1631. #else
  1632. ast_log(LOG_WARNING, "Must run configure with '--with-execinfo' for stack backtraces.\n");
  1633. #endif /* defined(HAVE_BKTR) */
  1634. }
  1635. void __ast_verbose_ap(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, va_list ap)
  1636. {
  1637. const char *p;
  1638. struct ast_str *prefixed, *buf = NULL;
  1639. int res = 0;
  1640. const char *prefix = level >= 4 ? VERBOSE_PREFIX_4 : level == 3 ? VERBOSE_PREFIX_3 : level == 2 ? VERBOSE_PREFIX_2 : level == 1 ? VERBOSE_PREFIX_1 : "";
  1641. signed char magic = level > 9 ? -10 : -level - 1; /* 0 => -1, 1 => -2, etc. Can't pass NUL, as it is EOS-delimiter */
  1642. /* For compatibility with modules still calling ast_verbose() directly instead of using ast_verb() */
  1643. if (level < 0) {
  1644. if (!strncmp(fmt, VERBOSE_PREFIX_4, strlen(VERBOSE_PREFIX_4))) {
  1645. magic = -5;
  1646. } else if (!strncmp(fmt, VERBOSE_PREFIX_3, strlen(VERBOSE_PREFIX_3))) {
  1647. magic = -4;
  1648. } else if (!strncmp(fmt, VERBOSE_PREFIX_2, strlen(VERBOSE_PREFIX_2))) {
  1649. magic = -3;
  1650. } else if (!strncmp(fmt, VERBOSE_PREFIX_1, strlen(VERBOSE_PREFIX_1))) {
  1651. magic = -2;
  1652. } else {
  1653. magic = -1;
  1654. }
  1655. }
  1656. if (!(prefixed = ast_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE)) ||
  1657. !(buf = ast_str_create(VERBOSE_BUF_INIT_SIZE))) {
  1658. return;
  1659. }
  1660. res = ast_str_set_va(&buf, 0, fmt, ap);
  1661. /* If the build failed then we can drop this allocated message */
  1662. if (res == AST_DYNSTR_BUILD_FAILED) {
  1663. ast_free(buf);
  1664. return;
  1665. }
  1666. ast_str_reset(prefixed);
  1667. /* for every newline found in the buffer add verbose prefix data */
  1668. fmt = ast_str_buffer(buf);
  1669. do {
  1670. if (!(p = strchr(fmt, '\n'))) {
  1671. p = strchr(fmt, '\0') - 1;
  1672. }
  1673. ++p;
  1674. if (ast_opt_timestamp) {
  1675. struct ast_tm tm;
  1676. char date[40];
  1677. struct timeval now = ast_tvnow();
  1678. ast_localtime(&now, &tm, NULL);
  1679. ast_strftime(date, sizeof(date), dateformat, &tm);
  1680. ast_str_append(&prefixed, 0, "%c[%s] %s", (char) magic, date, prefix);
  1681. } else {
  1682. ast_str_append(&prefixed, 0, "%c%s", (char) magic, prefix);
  1683. }
  1684. ast_str_append_substr(&prefixed, 0, fmt, p - fmt);
  1685. fmt = p;
  1686. } while (p && *p);
  1687. ast_log_callid(__LOG_VERBOSE, file, line, func, callid, "%s", ast_str_buffer(prefixed));
  1688. ast_free(buf);
  1689. }
  1690. void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...)
  1691. {
  1692. struct ast_callid *callid;
  1693. va_list ap;
  1694. callid = ast_read_threadstorage_callid();
  1695. va_start(ap, fmt);
  1696. __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
  1697. va_end(ap);
  1698. if (callid) {
  1699. ast_callid_unref(callid);
  1700. }
  1701. }
  1702. void __ast_verbose_callid(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, ...)
  1703. {
  1704. va_list ap;
  1705. va_start(ap, fmt);
  1706. __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
  1707. va_end(ap);
  1708. }
  1709. /* No new code should use this directly, but we have the ABI for backwards compat */
  1710. #undef ast_verbose
  1711. void __attribute__((format(printf, 1,2))) ast_verbose(const char *fmt, ...);
  1712. void ast_verbose(const char *fmt, ...)
  1713. {
  1714. struct ast_callid *callid;
  1715. va_list ap;
  1716. callid = ast_read_threadstorage_callid();
  1717. va_start(ap, fmt);
  1718. __ast_verbose_ap("", 0, "", 0, callid, fmt, ap);
  1719. va_end(ap);
  1720. if (callid) {
  1721. ast_callid_unref(callid);
  1722. }
  1723. }
  1724. /*! Console verbosity level node. */
  1725. struct verb_console {
  1726. /*! List node link */
  1727. AST_LIST_ENTRY(verb_console) node;
  1728. /*! Console verbosity level. */
  1729. int *level;
  1730. };
  1731. /*! Registered console verbosity levels */
  1732. static AST_RWLIST_HEAD_STATIC(verb_consoles, verb_console);
  1733. /*! ast_verb_update() reentrancy protection lock. */
  1734. AST_MUTEX_DEFINE_STATIC(verb_update_lock);
  1735. void ast_verb_update(void)
  1736. {
  1737. struct logchannel *log;
  1738. struct verb_console *console;
  1739. int verb_level;
  1740. ast_mutex_lock(&verb_update_lock);
  1741. AST_RWLIST_RDLOCK(&verb_consoles);
  1742. /* Default to the root console verbosity. */
  1743. verb_level = option_verbose;
  1744. /* Determine max remote console level. */
  1745. AST_LIST_TRAVERSE(&verb_consoles, console, node) {
  1746. if (verb_level < *console->level) {
  1747. verb_level = *console->level;
  1748. }
  1749. }
  1750. AST_RWLIST_UNLOCK(&verb_consoles);
  1751. /* Determine max logger channel level. */
  1752. AST_RWLIST_RDLOCK(&logchannels);
  1753. AST_RWLIST_TRAVERSE(&logchannels, log, list) {
  1754. if (verb_level < log->verbosity) {
  1755. verb_level = log->verbosity;
  1756. }
  1757. }
  1758. AST_RWLIST_UNLOCK(&logchannels);
  1759. ast_verb_sys_level = verb_level;
  1760. ast_mutex_unlock(&verb_update_lock);
  1761. }
  1762. /*!
  1763. * \internal
  1764. * \brief Unregister a console verbose level.
  1765. *
  1766. * \param console Which console to unregister.
  1767. *
  1768. * \return Nothing
  1769. */
  1770. static void verb_console_unregister(struct verb_console *console)
  1771. {
  1772. AST_RWLIST_WRLOCK(&verb_consoles);
  1773. console = AST_RWLIST_REMOVE(&verb_consoles, console, node);
  1774. AST_RWLIST_UNLOCK(&verb_consoles);
  1775. if (console) {
  1776. ast_verb_update();
  1777. }
  1778. }
  1779. static void verb_console_free(void *v_console)
  1780. {
  1781. struct verb_console *console = v_console;
  1782. verb_console_unregister(console);
  1783. ast_free(console);
  1784. }
  1785. /*! Thread specific console verbosity level node. */
  1786. AST_THREADSTORAGE_CUSTOM(my_verb_console, NULL, verb_console_free);
  1787. void ast_verb_console_register(int *level)
  1788. {
  1789. struct verb_console *console;
  1790. console = ast_threadstorage_get(&my_verb_console, sizeof(*console));
  1791. if (!console || !level) {
  1792. return;
  1793. }
  1794. console->level = level;
  1795. AST_RWLIST_WRLOCK(&verb_consoles);
  1796. AST_RWLIST_INSERT_HEAD(&verb_consoles, console, node);
  1797. AST_RWLIST_UNLOCK(&verb_consoles);
  1798. ast_verb_update();
  1799. }
  1800. void ast_verb_console_unregister(void)
  1801. {
  1802. struct verb_console *console;
  1803. console = ast_threadstorage_get(&my_verb_console, sizeof(*console));
  1804. if (!console) {
  1805. return;
  1806. }
  1807. verb_console_unregister(console);
  1808. }
  1809. int ast_verb_console_get(void)
  1810. {
  1811. struct verb_console *console;
  1812. int verb_level;
  1813. console = ast_threadstorage_get(&my_verb_console, sizeof(*console));
  1814. AST_RWLIST_RDLOCK(&verb_consoles);
  1815. if (!console) {
  1816. verb_level = 0;
  1817. } else if (console->level) {
  1818. verb_level = *console->level;
  1819. } else {
  1820. verb_level = option_verbose;
  1821. }
  1822. AST_RWLIST_UNLOCK(&verb_consoles);
  1823. return verb_level;
  1824. }
  1825. void ast_verb_console_set(int verb_level)
  1826. {
  1827. struct verb_console *console;
  1828. console = ast_threadstorage_get(&my_verb_console, sizeof(*console));
  1829. if (!console) {
  1830. return;
  1831. }
  1832. AST_RWLIST_WRLOCK(&verb_consoles);
  1833. if (console->level) {
  1834. *console->level = verb_level;
  1835. } else {
  1836. option_verbose = verb_level;
  1837. }
  1838. AST_RWLIST_UNLOCK(&verb_consoles);
  1839. ast_verb_update();
  1840. }
  1841. int ast_register_verbose(void (*v)(const char *string))
  1842. {
  1843. struct verb *verb;
  1844. if (!(verb = ast_malloc(sizeof(*verb))))
  1845. return -1;
  1846. verb->verboser = v;
  1847. AST_RWLIST_WRLOCK(&verbosers);
  1848. AST_RWLIST_INSERT_HEAD(&verbosers, verb, list);
  1849. AST_RWLIST_UNLOCK(&verbosers);
  1850. return 0;
  1851. }
  1852. int ast_unregister_verbose(void (*v)(const char *string))
  1853. {
  1854. struct verb *cur;
  1855. AST_RWLIST_WRLOCK(&verbosers);
  1856. AST_RWLIST_TRAVERSE_SAFE_BEGIN(&verbosers, cur, list) {
  1857. if (cur->verboser == v) {
  1858. AST_RWLIST_REMOVE_CURRENT(list);
  1859. ast_free(cur);
  1860. break;
  1861. }
  1862. }
  1863. AST_RWLIST_TRAVERSE_SAFE_END;
  1864. AST_RWLIST_UNLOCK(&verbosers);
  1865. return cur ? 0 : -1;
  1866. }
  1867. static void update_logchannels(void)
  1868. {
  1869. struct logchannel *cur;
  1870. AST_RWLIST_WRLOCK(&logchannels);
  1871. global_logmask = 0;
  1872. AST_RWLIST_TRAVERSE(&logchannels, cur, list) {
  1873. make_components(cur);
  1874. global_logmask |= cur->logmask;
  1875. }
  1876. AST_RWLIST_UNLOCK(&logchannels);
  1877. }
  1878. int ast_logger_register_level(const char *name)
  1879. {
  1880. unsigned int level;
  1881. unsigned int available = 0;
  1882. AST_RWLIST_WRLOCK(&logchannels);
  1883. for (level = 0; level < ARRAY_LEN(levels); level++) {
  1884. if ((level >= 16) && !available && !levels[level]) {
  1885. available = level;
  1886. continue;
  1887. }
  1888. if (levels[level] && !strcasecmp(levels[level], name)) {
  1889. ast_log(LOG_WARNING,
  1890. "Unable to register dynamic logger level '%s': a standard logger level uses that name.\n",
  1891. name);
  1892. AST_RWLIST_UNLOCK(&logchannels);
  1893. return -1;
  1894. }
  1895. }
  1896. if (!available) {
  1897. ast_log(LOG_WARNING,
  1898. "Unable to register dynamic logger level '%s'; maximum number of levels registered.\n",
  1899. name);
  1900. AST_RWLIST_UNLOCK(&logchannels);
  1901. return -1;
  1902. }
  1903. levels[available] = ast_strdup(name);
  1904. AST_RWLIST_UNLOCK(&logchannels);
  1905. ast_debug(1, "Registered dynamic logger level '%s' with index %u.\n", name, available);
  1906. update_logchannels();
  1907. return available;
  1908. }
  1909. void ast_logger_unregister_level(const char *name)
  1910. {
  1911. unsigned int found = 0;
  1912. unsigned int x;
  1913. AST_RWLIST_WRLOCK(&logchannels);
  1914. for (x = 16; x < ARRAY_LEN(levels); x++) {
  1915. if (!levels[x]) {
  1916. continue;
  1917. }
  1918. if (strcasecmp(levels[x], name)) {
  1919. continue;
  1920. }
  1921. found = 1;
  1922. break;
  1923. }
  1924. if (found) {
  1925. /* take this level out of the global_logmask, to ensure that no new log messages
  1926. * will be queued for it
  1927. */
  1928. global_logmask &= ~(1 << x);
  1929. ast_free(levels[x]);
  1930. levels[x] = NULL;
  1931. AST_RWLIST_UNLOCK(&logchannels);
  1932. ast_debug(1, "Unregistered dynamic logger level '%s' with index %u.\n", name, x);
  1933. update_logchannels();
  1934. } else {
  1935. AST_RWLIST_UNLOCK(&logchannels);
  1936. }
  1937. }