log.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. *
  3. * Embedded Linux library
  4. *
  5. * Copyright (C) 2011-2014 Intel Corporation. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #define _GNU_SOURCE
  26. #include <stdio.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. #include <stdarg.h>
  30. #include <string.h>
  31. #include <fnmatch.h>
  32. #include <sys/socket.h>
  33. #include <sys/un.h>
  34. #include "queue.h"
  35. #include "log.h"
  36. #include "private.h"
  37. struct debug_section {
  38. struct l_debug_desc *start;
  39. struct l_debug_desc *end;
  40. };
  41. struct l_queue *debug_sections;
  42. /**
  43. * SECTION:log
  44. * @short_description: Logging framework
  45. *
  46. * Logging framework
  47. */
  48. /**
  49. * l_debug_desc:
  50. *
  51. * Debug descriptor.
  52. */
  53. static void log_null(int priority, const char *file, const char *line,
  54. const char *func, const char *format, va_list ap)
  55. {
  56. }
  57. static l_log_func_t log_func = log_null;
  58. static const char *log_ident = "";
  59. static int log_fd = -1;
  60. static unsigned long log_pid;
  61. static inline void close_log(void)
  62. {
  63. if (log_fd > 0) {
  64. close(log_fd);
  65. log_fd = -1;
  66. }
  67. }
  68. static int open_log(const char *path)
  69. {
  70. struct sockaddr_un addr;
  71. log_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  72. if (log_fd < 0)
  73. return -1;
  74. memset(&addr, 0, sizeof(addr));
  75. addr.sun_family = AF_UNIX;
  76. strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
  77. if (connect(log_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  78. close_log();
  79. return -1;
  80. }
  81. return 0;
  82. }
  83. /**
  84. * l_log_set_ident:
  85. * @ident: string identifier
  86. *
  87. * Sets the log identifier string.
  88. **/
  89. LIB_EXPORT void l_log_set_ident(const char *ident)
  90. {
  91. log_ident = ident;
  92. }
  93. /**
  94. * l_log_set_handler:
  95. * @function: log handler function
  96. *
  97. * Sets the log handler function.
  98. **/
  99. LIB_EXPORT void l_log_set_handler(l_log_func_t function)
  100. {
  101. L_DEBUG_SYMBOL(__debug_intern, "");
  102. close_log();
  103. if (!function) {
  104. log_func = log_null;
  105. return;
  106. }
  107. log_func = function;
  108. }
  109. /**
  110. * l_log_set_null:
  111. *
  112. * Disable logging.
  113. **/
  114. LIB_EXPORT void l_log_set_null(void)
  115. {
  116. close_log();
  117. log_func = log_null;
  118. }
  119. __attribute__((format(printf, 5, 0)))
  120. static void log_stderr(int priority, const char *file, const char *line,
  121. const char *func, const char *format, va_list ap)
  122. {
  123. vfprintf(stderr, format, ap);
  124. }
  125. /**
  126. * l_log_set_stderr:
  127. *
  128. * Enable logging to stderr.
  129. **/
  130. LIB_EXPORT void l_log_set_stderr(void)
  131. {
  132. close_log();
  133. log_func = log_stderr;
  134. }
  135. __attribute__((format(printf, 5, 0)))
  136. static void log_syslog(int priority, const char *file, const char *line,
  137. const char *func, const char *format, va_list ap)
  138. {
  139. struct msghdr msg;
  140. struct iovec iov[2];
  141. char hdr[64], *str;
  142. int hdr_len, str_len;
  143. str_len = vasprintf(&str, format, ap);
  144. if (str_len < 0)
  145. return;
  146. hdr_len = snprintf(hdr, sizeof(hdr), "<%i>%s[%lu]: ", priority,
  147. log_ident, (unsigned long) log_pid);
  148. iov[0].iov_base = hdr;
  149. iov[0].iov_len = hdr_len;
  150. iov[1].iov_base = str;
  151. iov[1].iov_len = str_len;
  152. memset(&msg, 0, sizeof(msg));
  153. msg.msg_iov = iov;
  154. msg.msg_iovlen = 2;
  155. sendmsg(log_fd, &msg, 0);
  156. free(str);
  157. }
  158. /**
  159. * l_log_set_syslog:
  160. *
  161. * Enable logging to syslog.
  162. **/
  163. LIB_EXPORT void l_log_set_syslog(void)
  164. {
  165. close_log();
  166. if (open_log("/dev/log") < 0) {
  167. log_func = log_null;
  168. return;
  169. }
  170. log_pid = getpid();
  171. log_func = log_syslog;
  172. }
  173. __attribute__((format(printf, 5, 0)))
  174. static void log_journal(int priority, const char *file, const char *line,
  175. const char *func, const char *format, va_list ap)
  176. {
  177. struct msghdr msg;
  178. struct iovec iov[12];
  179. char prio[16], *str;
  180. int prio_len, str_len;
  181. str_len = vasprintf(&str, format, ap);
  182. if (str_len < 0)
  183. return;
  184. prio_len = snprintf(prio, sizeof(prio), "PRIORITY=%u\n", priority);
  185. iov[0].iov_base = "MESSAGE=";
  186. iov[0].iov_len = 8;
  187. iov[1].iov_base = str;
  188. iov[1].iov_len = str_len;
  189. iov[2].iov_base = prio;
  190. iov[2].iov_len = prio_len;
  191. iov[3].iov_base = "CODE_FILE=";
  192. iov[3].iov_len = 10;
  193. iov[4].iov_base = (char *) file;
  194. iov[4].iov_len = strlen(file);
  195. iov[5].iov_base = "\n";
  196. iov[5].iov_len = 1;
  197. iov[6].iov_base = "CODE_LINE=";
  198. iov[6].iov_len = 10;
  199. iov[7].iov_base = (char *) line;
  200. iov[7].iov_len = strlen(line);
  201. iov[8].iov_base = "\n";
  202. iov[8].iov_len = 1;
  203. iov[9].iov_base = "CODE_FUNC=";
  204. iov[9].iov_len = 10;
  205. iov[10].iov_base = (char *) func;
  206. iov[10].iov_len = strlen(func);
  207. iov[11].iov_base = "\n";
  208. iov[11].iov_len = 1;
  209. memset(&msg, 0, sizeof(msg));
  210. msg.msg_iov = iov;
  211. msg.msg_iovlen = 12;
  212. sendmsg(log_fd, &msg, 0);
  213. free(str);
  214. }
  215. /**
  216. * l_log_set_journal:
  217. *
  218. * Enable logging to journal.
  219. **/
  220. LIB_EXPORT void l_log_set_journal(void)
  221. {
  222. close_log();
  223. if (open_log("/run/systemd/journal/socket") < 0) {
  224. log_func = log_null;
  225. return;
  226. }
  227. log_pid = getpid();
  228. log_func = log_journal;
  229. }
  230. /**
  231. * l_log_with_location:
  232. * @priority: priority level
  233. * @file: source file
  234. * @line: source line
  235. * @func: source function
  236. * @format: format string
  237. * @...: format arguments
  238. *
  239. * Log information.
  240. **/
  241. LIB_EXPORT void l_log_with_location(int priority,
  242. const char *file, const char *line,
  243. const char *func, const char *format, ...)
  244. {
  245. va_list ap;
  246. va_start(ap, format);
  247. log_func(priority, file, line, func, format, ap);
  248. va_end(ap);
  249. }
  250. /**
  251. * l_error:
  252. * @format: format string
  253. * @...: format arguments
  254. *
  255. **/
  256. /**
  257. * l_warn:
  258. * @format: format string
  259. * @...: format arguments
  260. *
  261. **/
  262. /**
  263. * l_info:
  264. * @format: format string
  265. * @...: format arguments
  266. *
  267. **/
  268. /**
  269. * l_debug:
  270. * @format: format string
  271. * @...: format arguments
  272. **/
  273. static const char *debug_pattern;
  274. static void debug_enable(struct l_debug_desc *start, struct l_debug_desc *stop)
  275. {
  276. struct l_debug_desc *desc;
  277. char *pattern_copy;
  278. if (!debug_pattern)
  279. return;
  280. pattern_copy = strdupa(debug_pattern);
  281. while (pattern_copy) {
  282. char *str = strsep(&pattern_copy, ":,");
  283. if (!str)
  284. break;
  285. for (desc = start; desc < stop; desc++) {
  286. if (!fnmatch(str, desc->file, 0))
  287. desc->flags |= L_DEBUG_FLAG_PRINT;
  288. if (!fnmatch(str, desc->func, 0))
  289. desc->flags |= L_DEBUG_FLAG_PRINT;
  290. }
  291. }
  292. }
  293. static void debug_disable(struct l_debug_desc *start, struct l_debug_desc *stop)
  294. {
  295. struct l_debug_desc *desc;
  296. for (desc = start; desc < stop; desc++)
  297. desc->flags &= ~L_DEBUG_FLAG_PRINT;
  298. }
  299. /**
  300. * l_debug_add_section:
  301. * @start: start of the debug section
  302. * @stop: stop of the debug section
  303. *
  304. * Add information about a debug section. This is used by shared libraries
  305. * to tell ell about their debug section start & stopping points. This is used
  306. * to make l_debug statements work across all shared libraries that might be
  307. * linked into the executable
  308. */
  309. LIB_EXPORT void l_debug_add_section(struct l_debug_desc *start,
  310. struct l_debug_desc *end)
  311. {
  312. const struct l_queue_entry *entry;
  313. struct debug_section *new_section;
  314. if (!debug_sections) {
  315. debug_sections = l_queue_new();
  316. goto add;
  317. }
  318. for (entry = l_queue_get_entries(debug_sections); entry;
  319. entry = entry->next) {
  320. const struct debug_section *section = entry->data;
  321. if (section->start == start && section->end == end)
  322. return;
  323. }
  324. add:
  325. new_section = l_new(struct debug_section, 1);
  326. new_section->start = start;
  327. new_section->end = end;
  328. l_queue_push_head(debug_sections, new_section);
  329. }
  330. /**
  331. * l_debug_enable_full:
  332. * @pattern: debug pattern
  333. * @start: start of the debug section
  334. * @stop: end of the debug section
  335. *
  336. * Enable debug sections based on @pattern.
  337. **/
  338. LIB_EXPORT void l_debug_enable_full(const char *pattern,
  339. struct l_debug_desc *start,
  340. struct l_debug_desc *end)
  341. {
  342. const struct l_queue_entry *entry;
  343. if (!pattern)
  344. return;
  345. debug_pattern = pattern;
  346. l_debug_add_section(start, end);
  347. for (entry = l_queue_get_entries(debug_sections); entry;
  348. entry = entry->next) {
  349. const struct debug_section *section = entry->data;
  350. debug_enable(section->start, section->end);
  351. }
  352. }
  353. /**
  354. * l_debug_disable:
  355. *
  356. * Disable all debug sections.
  357. **/
  358. LIB_EXPORT void l_debug_disable(void)
  359. {
  360. const struct l_queue_entry *entry;
  361. for (entry = l_queue_get_entries(debug_sections); entry;
  362. entry = entry->next) {
  363. const struct debug_section *section = entry->data;
  364. debug_disable(section->start, section->end);
  365. }
  366. debug_pattern = NULL;
  367. }
  368. __attribute__((constructor)) static void register_debug_section()
  369. {
  370. extern struct l_debug_desc __start___ell_debug[];
  371. extern struct l_debug_desc __stop___ell_debug[];
  372. l_debug_add_section(__start___ell_debug, __stop___ell_debug);
  373. }
  374. __attribute__((destructor(65535))) static void free_debug_sections()
  375. {
  376. l_queue_destroy(debug_sections, l_free);
  377. }