Greenbone Vulnerability Management Libraries: base/logging.c Source File

Greenbone Vulnerability Management Libraries 23.1.1

logging.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017-2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
15
16#include "logging.h"
17
18#include "gvm_sentry.h" /* for gvm_sentry_log */
19#include "logging_domain.h"
20
21#include <errno.h> /* for errno */
22#include <libgen.h> /* for dirname */
23#include <stdio.h> /* for fflush, fprintf, stderr */
24#include <stdlib.h> /* for atoi */
25#include <string.h> /* for strcasecmp, strlen, strerror */
26#define SYSLOG_NAMES
27#include <syslog.h> /* for LOG_INFO, facilitynames, closelog, openlog */
28#undef SYSLOG_NAMES
29#include <time.h> /* for localtime, time, time_t */
30#include <unistd.h> /* for getpid */
31
32#undef G_LOG_DOMAIN
36#define G_LOG_DOMAIN "libgvm base"
37
43 static gchar *log_tz = NULL;
44
56gchar *
57get_time (gchar *time_fmt)
58{
59 time_t now;
60 struct tm ts;
61 gchar buf[80], *original_tz;
62
63 if (!time_fmt)
64 return NULL;
65
66 if (log_tz)
67 {
68 original_tz = getenv ("TZ") ? g_strdup (getenv ("TZ")) : NULL;
69 setenv ("TZ", log_tz, 1);
70 tzset ();
71 }
72
73 /* Get the current time. */
74 now = time (NULL);
75
76 /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz." */
77 localtime_r (&now, &ts);
78 strftime (buf, sizeof (buf), time_fmt, &ts);
79
80 if (log_tz)
81 {
82 /* Revert to stored TZ. */
83 if (original_tz)
84 {
85 setenv ("TZ", original_tz, 1);
86 g_free (original_tz);
87 tzset ();
88 }
89 else
90 unsetenv ("TZ");
91 }
92
93 return g_strdup_printf ("%s", buf);
94}
95
103static gint
104level_int_from_string (const gchar *level)
105{
106 if (level && strlen (level) > 0)
107 {
108 if (level[0] >= '0' && level[0] <= '9')
109 return atoi (level);
110 if (strcasecmp (level, "critical") == 0)
111 return G_LOG_LEVEL_CRITICAL;
112 if (strcasecmp (level, "debug") == 0)
113 return G_LOG_LEVEL_DEBUG;
114 if (strcasecmp (level, "error") == 0)
115 return G_LOG_LEVEL_ERROR;
116 if (strcasecmp (level, "info") == 0)
117 return G_LOG_LEVEL_INFO;
118 if (strcasecmp (level, "message") == 0)
119 return G_LOG_LEVEL_MESSAGE;
120 if (strcasecmp (level, "warning") == 0)
121 return G_LOG_LEVEL_WARNING;
122 }
123 return 0;
124}
125
134static gint
135facility_int_from_string (const gchar *facility)
136{
137 if (facility && strlen (facility) > 0)
138 {
139 int i = 0;
140 while (facilitynames[i].c_name != NULL)
141 {
142 if (g_ascii_strcasecmp (facility, facilitynames[i].c_name) == 0)
143 return facilitynames[i].c_val;
144 i++;
145 }
146 }
147 return LOG_LOCAL0;
148}
149
160GSList *
161load_log_configuration (const gchar *config_file)
162{
163 GKeyFile *key_file;
164 GKeyFileFlags flags;
165 GError *error = NULL;
166 /* key_file *_has_* functions requires this. */
167
168 // FIXME: If a g_* function that takes error fails, then free error.
169
170 /* Groups found in the conf file. */
171 gchar **groups;
172 /* Temp variable to iterate over groups. */
173 gchar **group;
174
175 /* The link list for the structure above and it's tmp helper */
176 GSList *log_domain_list = NULL;
177
178 /* Create a new GKeyFile object and a bitwise list of flags. */
179 key_file = g_key_file_new ();
180 flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
181
182 /* Load the GKeyFile from conf or return. */
183 if (!g_key_file_load_from_file (key_file, config_file, flags, &error))
184 {
185 g_error ("%s: %s", config_file, error->message);
186 }
187
188 /* Get all the groups available. */
189 groups = g_key_file_get_groups (key_file, NULL);
190
191 /* Point to the group head. */
192 group = groups;
193 /* Iterate till we get to the end of the array. */
194 while (*group != NULL)
195 {
196 /* Structure to hold per group settings. */
197 gvm_logging_domain_t *log_domain_entry =
198 gvm_logging_domain_new (g_strdup (*group));
199
200 /* Look for the prepend string. */
201 if (g_key_file_has_key (key_file, *group, "prepend", &error))
202 {
203 gvm_logging_domain_set_prepend_string (
204 log_domain_entry,
205 g_key_file_get_value (key_file, *group, "prepend", &error));
206 }
207
208 /* Look for the log_separator string. */
209 if (g_key_file_has_key (key_file, *group, "separator", &error))
210 {
211 gvm_logging_domain_set_prepend_separator (
212 log_domain_entry,
213 g_key_file_get_value (key_file, *group, "separator", &error));
214 }
215
216 /* Look for the prepend time format string. */
217 if (g_key_file_has_key (key_file, *group, "prepend_time_format", &error))
218 {
219 gvm_logging_domain_set_prepend_time_format (
220 log_domain_entry,
221 g_key_file_get_value (key_file, *group, "prepend_time_format",
222 &error));
223 }
224
225 /* Look for the log file string. */
226 if (g_key_file_has_key (key_file, *group, "file", &error))
227 {
228 gvm_logging_domain_set_log_file (
229 log_domain_entry,
230 g_key_file_get_value (key_file, *group, "file", &error));
231 }
232
233 /* Look for the prepend log level string. */
234 if (g_key_file_has_key (key_file, *group, "level", &error))
235 {
236 gchar *level;
237
238 level = g_key_file_get_value (key_file, *group, "level", &error);
239 level = g_strchug (level);
240 gvm_logging_domain_set_default_level (log_domain_entry,
241 level_int_from_string (level));
242 g_free (level);
243 }
244
245 /* Look for the syslog_facility string. */
246 if (g_key_file_has_key (key_file, *group, "syslog_facility", &error))
247 {
248 gvm_logging_domain_set_syslog_facility (
249 log_domain_entry,
250 g_key_file_get_value (key_file, *group, "syslog_facility", &error));
251 }
252 else
253 gvm_logging_domain_set_syslog_facility (log_domain_entry,
254 g_strdup ("local0"));
255
256 /* Look for the syslog_ident string. */
257 if (g_key_file_has_key (key_file, *group, "syslog_ident", &error))
258 {
259 gvm_logging_domain_set_syslog_ident (
260 log_domain_entry,
261 g_key_file_get_value (key_file, *group, "syslog_ident", &error));
262 }
263 else
264 gvm_logging_domain_set_syslog_ident (log_domain_entry,
265 g_strdup (*group));
266
267 /* Attach the struct to the list. */
268 log_domain_list = g_slist_prepend (log_domain_list, log_domain_entry);
269 group++;
270 }
271 /* Free the groups array. */
272 g_strfreev (groups);
273
274 /* Free the key file. */
275 g_key_file_free (key_file);
276
277 return log_domain_list;
278}
279
285void
286free_log_configuration (GSList *log_domain_list)
287{
288 GSList *log_domain_list_tmp;
289
290 /* Free the struct fields then the struct and then go the next
291 * item in the link list.
292 */
293
294 /* Go to the head of the list. */
295 log_domain_list_tmp = log_domain_list;
296 while (log_domain_list_tmp != NULL)
297 {
298 gvm_logging_domain_t *log_domain_entry;
299
300 /* Get the list data which is an gvm_logging_t struct. */
301 log_domain_entry = log_domain_list_tmp->data;
302
303 /* Free the struct contents. */
304 gvm_logging_domain_free (log_domain_entry);
305
306 /* Go to the next item. */
307 log_domain_list_tmp = g_slist_next (log_domain_list_tmp);
308 }
309 /* Free the link list. */
310 g_slist_free (log_domain_list);
311}
312
321void
322gvm_log_silent (const char *log_domain, GLogLevelFlags log_level,
323 const char *message, gpointer gvm_log_config_list)
324{
325 (void) log_domain;
326 (void) log_level;
327 (void) message;
328 (void) gvm_log_config_list;
329 return;
330}
331
332 static GMutex *logger_mutex = NULL;
333
337static void
338gvm_log_lock_init (void)
339{
340 if (logger_mutex == NULL)
341 {
342 logger_mutex = g_malloc (sizeof (*logger_mutex));
343 g_mutex_init (logger_mutex);
344 }
345}
346
350void
351gvm_log_lock (void)
352{
353 /* Initialize logger lock if not done already. */
354 gvm_log_lock_init ();
355
356 g_mutex_lock (logger_mutex);
357}
358
362void
363gvm_log_unlock (void)
364{
365 g_mutex_unlock (logger_mutex);
366}
367
368 static char *reference = NULL;
369
383void
384set_log_reference (char *ref)
385{
386 g_free (reference);
387 reference = ref;
388}
389
398char *
399get_log_reference (void)
400{
401 return (char *) reference;
402}
403
410void
411free_log_reference (void)
412{
413 g_free (reference);
414 reference = NULL;
415}
416
425void
426gvm_log_func (const char *log_domain, GLogLevelFlags log_level,
427 const char *message, gpointer gvm_log_config_list)
428{
429 gchar *prepend;
430 gchar *prepend_buf;
431 gchar *prepend_tmp;
432 gchar *prepend_tmp1;
433 gchar *tmp;
434 gchar *tmpstr;
435 int messagelen;
436
437 /* For link list operations. */
438 GSList *log_domain_list_tmp;
439 gvm_logging_domain_t *log_domain_entry = NULL;
440
441 /* Channel to log through. */
442 GIOChannel *channel = NULL;
443 GError *error = NULL;
444
445 /* The default parameters to be used. The group '*' will override
446 * these defaults if it's found.
447 */
448 gchar *prepend_format = "%t %s %p - ";
449 gchar *time_format = "%Y-%m-%d %Hh%M.%S %Z";
450 gchar *log_separator = ":";
451 gchar *log_file = "-";
452 GLogLevelFlags default_level = G_LOG_LEVEL_DEBUG;
453 gchar *syslog_facility = "local0";
454 gchar *syslog_ident = NULL;
455
456 /* Let's load the default configuration file directives from the
457 * linked list. Scanning the link list twice is inefficient but
458 * leaves the source cleaner.
459 */
460 if (gvm_log_config_list != NULL && log_domain != NULL)
461 {
462 /* Go to the head of the list. */
463 log_domain_list_tmp = (GSList *) gvm_log_config_list;
464
465 while (log_domain_list_tmp != NULL)
466 {
467 gvm_logging_domain_t *entry;
468
469 entry = log_domain_list_tmp->data;
470
471 /* Override defaults if the current linklist group name is '*'. */
472 if (g_ascii_strcasecmp (gvm_logging_domain_get_log_domain (entry),
473 "*")
474 == 0)
475 {
476 /* Get the list data for later use. */
477 log_domain_entry = entry;
478
479 /* Override defaults if the group items are not null. */
480 if (gvm_logging_domain_get_prepend_string (log_domain_entry))
481 prepend_format =
482 gvm_logging_domain_get_prepend_string (log_domain_entry);
483 if (gvm_logging_domain_get_prepend_time_format (log_domain_entry))
484 time_format =
485 gvm_logging_domain_get_prepend_time_format (log_domain_entry);
486 if (gvm_logging_domain_get_log_file (log_domain_entry))
487 log_file = gvm_logging_domain_get_log_file (log_domain_entry);
488 if (gvm_logging_domain_get_default_level (log_domain_entry))
489 default_level =
490 *gvm_logging_domain_get_default_level (log_domain_entry);
491 if (gvm_logging_domain_get_log_channel (log_domain_entry))
492 channel = gvm_logging_domain_get_log_channel (log_domain_entry);
493 if (gvm_logging_domain_get_syslog_facility (log_domain_entry))
494 syslog_facility =
495 gvm_logging_domain_get_syslog_facility (log_domain_entry);
496 if (gvm_logging_domain_get_prepend_separator (log_domain_entry))
497 log_separator =
498 gvm_logging_domain_get_prepend_separator (log_domain_entry);
499 break;
500 }
501
502 /* Go to the next item. */
503 log_domain_list_tmp = g_slist_next (log_domain_list_tmp);
504 }
505 }
506
507 /* Let's load the configuration file directives if a linked list item for
508 * the log domain group exists.
509 */
510 if (gvm_log_config_list != NULL && log_domain != NULL)
511 {
512 /* Go to the head of the list. */
513 log_domain_list_tmp = (GSList *) gvm_log_config_list;
514
515 while (log_domain_list_tmp != NULL)
516 {
517 gvm_logging_domain_t *entry;
518
519 entry = log_domain_list_tmp->data;
520
521 /* Search for the log domain in the link list. */
522 if (g_ascii_strcasecmp (gvm_logging_domain_get_log_domain (entry),
523 log_domain)
524 == 0)
525 {
526 /* Get the list data which is an gvm_logging_t struct. */
527 log_domain_entry = entry;
528
529 /* Get the struct contents. */
530 if (gvm_logging_domain_get_prepend_string (log_domain_entry))
531 prepend_format =
532 gvm_logging_domain_get_prepend_string (log_domain_entry);
533 if (gvm_logging_domain_get_prepend_time_format (log_domain_entry))
534 time_format =
535 gvm_logging_domain_get_prepend_time_format (log_domain_entry);
536 if (gvm_logging_domain_get_log_file (log_domain_entry))
537 log_file = gvm_logging_domain_get_log_file (log_domain_entry);
538 if (gvm_logging_domain_get_default_level (log_domain_entry))
539 default_level =
540 *gvm_logging_domain_get_default_level (log_domain_entry);
541 if (gvm_logging_domain_get_log_channel (log_domain_entry))
542 channel = gvm_logging_domain_get_log_channel (log_domain_entry);
543 if (gvm_logging_domain_get_syslog_facility (log_domain_entry))
544 syslog_facility =
545 gvm_logging_domain_get_syslog_facility (log_domain_entry);
546 if (gvm_logging_domain_get_syslog_ident (log_domain_entry))
547 syslog_ident =
548 gvm_logging_domain_get_syslog_ident (log_domain_entry);
549 if (gvm_logging_domain_get_prepend_separator (log_domain_entry))
550 log_separator =
551 gvm_logging_domain_get_prepend_separator (log_domain_entry);
552 break;
553 }
554
555 /* Go to the next item. */
556 log_domain_list_tmp = g_slist_next (log_domain_list_tmp);
557 }
558 }
559
560 /* If the current log entry is less severe than the specified log level,
561 * let's exit.
562 */
563 if (default_level < log_level)
564 return;
565
566 /* Prepend buf is a newly allocated empty string. Makes life easier. */
567 prepend_buf = g_strdup ("");
568
569 /* Make the tmp pointer (for iteration) point to the format string. */
570 tmp = prepend_format;
571
572 while (*tmp != '\0')
573 {
574 /* If the current char is a % and the next one is a p, get the pid. */
575 if ((*tmp == '%') && (*(tmp + 1) == 'p'))
576 {
577 if (reference)
578 {
579 prepend_tmp =
580 g_strdup_printf ("%s%d%s%s", prepend_buf, (int) getpid (),
581 log_separator, reference);
582 }
583 else
584 {
585 /* Use g_strdup, a new string returned. Store it in a tmp var
586 * until we free the old one. */
587 prepend_tmp =
588 g_strdup_printf ("%s%d", prepend_buf, (int) getpid ());
589 }
590 /* Free the old string. */
591 g_free (prepend_buf);
592 /* Point the buf ptr to the new string. */
593 prepend_buf = prepend_tmp;
594 /* Skip over the two chars we've processed '%p'. */
595 tmp += 2;
596 }
597 else if ((*tmp == '%') && (*(tmp + 1) == 't'))
598 {
599 /* Get time returns a newly allocated string.
600 * Store it in a tmp var.
601 */
602 prepend_tmp1 = get_time (time_format);
603 if (!prepend_tmp1)
604 {
605 prepend_tmp1 = g_strdup ("");
606 }
607 /* Use g_strdup. New string returned. Store it in a tmp var until
608 * we free the old one.
609 */
610 prepend_tmp = g_strdup_printf ("%s%s", prepend_buf, prepend_tmp1);
611 /* Free the time tmp var. */
612 g_free (prepend_tmp1);
613 /* Free the old string. */
614 g_free (prepend_buf);
615 /* Point the buf ptr to the new string. */
616 prepend_buf = prepend_tmp;
617 /* Skip over the two chars we've processed '%t.' */
618 tmp += 2;
619 }
620 else if ((*tmp == '%') && (*(tmp + 1) == 's'))
621 {
622 /* Use g_strdup. New string returned. Store it in a tmp var until
623 * we free the old one.
624 */
625 prepend_tmp = g_strdup_printf ("%s%s", prepend_buf, log_separator);
626 /* Free the old string. */
627 g_free (prepend_buf);
628 /* Point the buf ptr to the new string. */
629 prepend_buf = prepend_tmp;
630 /* Skip over the two chars we've processed '%s.' */
631 tmp += 2;
632 }
633 else
634 {
635 /* Jump to the next character. */
636 tmp++;
637 }
638 }
639
640 /* Step through all possible messages prefixing them with an appropriate
641 * tag.
642 */
643 switch (log_level)
644 {
645 case G_LOG_FLAG_RECURSION:
646 prepend = g_strdup_printf ("RECURSION%s%s", log_separator, prepend_buf);
647 break;
648
649 case G_LOG_FLAG_FATAL:
650 prepend = g_strdup_printf ("FATAL%s%s", log_separator, prepend_buf);
651 break;
652
653 case G_LOG_LEVEL_ERROR:
654 prepend = g_strdup_printf ("ERROR%s%s", log_separator, prepend_buf);
655 break;
656
657 case G_LOG_LEVEL_CRITICAL:
658 prepend = g_strdup_printf ("CRITICAL%s%s", log_separator, prepend_buf);
659 break;
660
661 case G_LOG_LEVEL_WARNING:
662 prepend = g_strdup_printf ("WARNING%s%s", log_separator, prepend_buf);
663 break;
664
665 case G_LOG_LEVEL_MESSAGE:
666 prepend = g_strdup_printf ("MESSAGE%s%s", log_separator, prepend_buf);
667 break;
668
669 case G_LOG_LEVEL_INFO:
670 prepend = g_strdup_printf (" INFO%s%s", log_separator, prepend_buf);
671 break;
672
673 case G_LOG_LEVEL_DEBUG:
674 prepend = g_strdup_printf (" DEBUG%s%s", log_separator, prepend_buf);
675 break;
676
677 default:
678 prepend = g_strdup_printf ("UNKNOWN%s%s", log_separator, prepend_buf);
679 break;
680 }
681
682 /* If the current log entry is more severe than the specified log
683 * level, print out the message. In case MESSAGE already ends in a
684 * LF and there is not only the LF, remove the LF to avoid empty
685 * lines in the log.
686 */
687 messagelen = message ? strlen (message) : 0;
688 if (messagelen > 1 && message[messagelen - 1] == '\n')
689 messagelen--;
690 tmpstr = g_strdup_printf ("%s%s%s%s %.*s\n", log_domain ? log_domain : "",
691 log_separator, prepend, log_separator, messagelen,
692 message);
693 g_free (prepend);
694
695 if (log_level <= G_LOG_LEVEL_WARNING)
696 gvm_sentry_log (message);
697
698 gvm_log_lock ();
699 /* Output everything to stderr if logfile is NULL, an empty string or "-". */
700 if (!log_file || g_ascii_strcasecmp (log_file, "-") == 0
701 || !g_strcmp0 (log_file, ""))
702 {
703 fprintf (stderr, "%s", tmpstr);
704 fflush (stderr);
705 }
706 /* Output everything to syslog if logfile is "syslog" */
707 else if (g_ascii_strcasecmp (log_file, "syslog") == 0)
708 {
709 int facility = facility_int_from_string (syslog_facility);
710 int syslog_level = LOG_INFO;
711
712 openlog (syslog_ident, LOG_CONS | LOG_PID | LOG_NDELAY, facility);
713
714 switch (log_level)
715 {
716 case G_LOG_FLAG_FATAL:
717 syslog_level = LOG_ALERT;
718 break;
719 case G_LOG_LEVEL_ERROR:
720 syslog_level = LOG_ERR;
721 break;
722 case G_LOG_LEVEL_CRITICAL:
723 syslog_level = LOG_CRIT;
724 break;
725 case G_LOG_LEVEL_WARNING:
726 syslog_level = LOG_WARNING;
727 break;
728 case G_LOG_LEVEL_MESSAGE:
729 syslog_level = LOG_NOTICE;
730 break;
731 case G_LOG_LEVEL_INFO:
732 syslog_level = LOG_INFO;
733 break;
734 case G_LOG_LEVEL_DEBUG:
735 syslog_level = LOG_DEBUG;
736 break;
737 default:
738 syslog_level = LOG_INFO;
739 break;
740 }
741
742 /* Syslog doesn't support messages longer than 1kb. The overflow data
743 will not be logged or will be shown in the hypervisor console
744 if it runs on a virtual machine. */
745 if (messagelen > 1000)
746 {
747 int pos;
748 char *message_aux, *message_aux2;
749 char buffer[1000];
750
751 message_aux2 = g_strdup (message);
752 message_aux = message_aux2;
753 for (pos = 0; pos <= messagelen; pos = pos + sizeof (buffer) - 1)
754 {
755 memcpy (buffer, message_aux, sizeof (buffer) - 1);
756 buffer[sizeof (buffer) - 1] = '\0';
757 message_aux = &(message_aux[sizeof (buffer) - 1]);
758 syslog (syslog_level, "%s", buffer);
759 }
760 g_free (message_aux2);
761 }
762 else
763 syslog (syslog_level, "%s", message);
764
765 closelog ();
766 }
767 else
768 {
769 /* Open a channel and store it in the struct or
770 * retrieve and use an already existing channel.
771 */
772 if (channel == NULL)
773 {
774 channel = g_io_channel_new_file (log_file, "a", &error);
775 if (!channel)
776 {
777 gchar *log = g_strdup (log_file);
778 gchar *dir = dirname (log);
779
780 /* Check error. In case of the directory does not exist, it will
781 * be handle below. In other case a message is printed to the
782 * stderr since the channel is still not created/accessible.
783 */
784 if (error->code != G_FILE_ERROR_NOENT)
785 fprintf (stderr, "Can not open '%s' logfile: %s\n", log_file,
786 error->message);
787 g_error_free (error);
788
789 /* Ensure directory exists. */
790 if (g_mkdir_with_parents (dir, 0755)) /* "rwxr-xr-x" */
791 {
792 g_warning ("Failed to create log file directory %s: %s", dir,
793 strerror (errno));
794 g_free (log);
795 g_free (tmpstr);
796 g_free (prepend_buf);
797 return;
798 }
799 g_free (log);
800
801 /* Try again. */
802 error = NULL;
803 channel = g_io_channel_new_file (log_file, "a", &error);
804 if (!channel)
805 {
806 g_error ("Can not open '%s' logfile: %s", log_file,
807 error->message);
808 }
809 }
810
811 /* Store it in the struct for later use. */
812 if (log_domain_entry != NULL)
813 gvm_logging_domain_set_log_channel (log_domain_entry, channel);
814 }
815 g_io_channel_write_chars (channel, (const gchar *) tmpstr, -1, NULL,
816 &error);
817 g_io_channel_flush (channel, NULL);
818 }
819 gvm_log_unlock ();
820 g_free (tmpstr);
821 g_free (prepend_buf);
822}
823
835void
836log_func_for_gnutls (int level, const char *message)
837{
838 g_log ("x gnutls", G_LOG_LEVEL_INFO, "tls(%d): %s", level, message);
839}
840
850static int
851check_log_file (gvm_logging_domain_t *log_domain_entry)
852{
853 GIOChannel *channel = NULL;
854 const gchar *log_file;
855
856 log_file = gvm_logging_domain_get_log_file (log_domain_entry);
857
858 // No log file was specified, log file is empty or set to "-" then
859 // stderr will be used as default later on. See gvm_log_func.
860 if (!log_file || g_ascii_strcasecmp (log_file, "-") == 0
861 || !g_strcmp0 (log_file, ""))
862 return 0;
863
864 // If syslog is used we do not need to check the log file permissions.
865 if (g_ascii_strcasecmp (log_file, "syslog") == 0)
866 return 0;
867
868 channel = g_io_channel_new_file (log_file, "a", NULL);
869 if (!channel)
870 {
871 gchar *log = g_strdup (log_file);
872 gchar *dir = dirname (log);
873
874 /* Ensure directory exists. */
875 if (g_mkdir_with_parents (dir, 0755)) /* "rwxr-xr-x" */
876 {
877 g_free (log);
878 return -1;
879 }
880 g_free (log);
881
882 /* Try again. */
883 channel = g_io_channel_new_file (log_file, "a", NULL);
884 if (!channel)
885 return -1;
886 }
887 g_io_channel_shutdown (channel, TRUE, NULL);
888 g_io_channel_unref (channel);
889 return 0;
890}
891
900void
901set_log_tz (const gchar *tz)
902{
903 g_free (log_tz);
904 log_tz = tz ? g_strdup (tz) : NULL;
905}
906
907static int
908setup_log_handlers_internal (GSList *gvm_log_config_list, GLogFunc log_func,
909 GLogFunc default_log_func,
910 GLogFunc default_domain_log_func)
911{
912 GSList *log_domain_list_tmp;
913 int err;
914 int ret = 0;
915
916 if (gvm_log_config_list != NULL)
917 {
918 /* Go to the head of the list. */
919 log_domain_list_tmp = (GSList *) gvm_log_config_list;
920
921 while (log_domain_list_tmp != NULL)
922 {
923 gvm_logging_domain_t *log_domain_entry;
924
925 /* Get the list data which is an gvm_logging_t struct. */
926 log_domain_entry = log_domain_list_tmp->data;
927
928 err = check_log_file (log_domain_entry);
929 if (err)
930 {
931 ret = -1;
932 /* Go to the next item. */
933 log_domain_list_tmp = g_slist_next (log_domain_list_tmp);
934 continue;
935 }
936
937 if (g_ascii_strcasecmp (
938 gvm_logging_domain_get_log_domain (log_domain_entry), "*"))
939 {
940 g_log_set_handler (
941 gvm_logging_domain_get_log_domain (log_domain_entry),
942 (GLogLevelFlags) (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO
943 | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING
944 | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR
945 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION),
946 (GLogFunc) log_func, gvm_log_config_list);
947 }
948 else
949 {
950 g_log_set_default_handler (default_log_func, gvm_log_config_list);
951 }
952
953 /* Go to the next item. */
954 log_domain_list_tmp = g_slist_next (log_domain_list_tmp);
955 }
956 }
957 g_log_set_handler (
958 "",
959 (GLogLevelFlags) (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE
960 | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL
961 | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL
962 | G_LOG_FLAG_RECURSION),
963 default_domain_log_func, gvm_log_config_list);
964
965 return ret;
966}
967
978int
979setup_log_handlers (GSList *gvm_log_config_list)
980{
981 return setup_log_handlers_internal (gvm_log_config_list, gvm_log_func,
982 gvm_log_func, gvm_log_func);
983}
gvm_sentry_log
void gvm_sentry_log(const char *message)
Send a message to Sentry server if it was initialized.
Definition gvm_sentry.c:97
gvm_sentry.h
Implementation of sentry methods.
gvm_log_func
void gvm_log_func(const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer gvm_log_config_list)
Creates the formatted string and outputs it to the log destination.
Definition logging.c:426
free_log_reference
void free_log_reference(void)
Free the log reference object.
Definition logging.c:411
get_log_reference
char * get_log_reference(void)
Get the log reference object.
Definition logging.c:399
set_log_reference
void set_log_reference(char *ref)
Set the log reference object.
Definition logging.c:384
check_log_file
static int check_log_file(gvm_logging_domain_t *log_domain_entry)
Check permissions of log file and log file directory.
Definition logging.c:851
log_func_for_gnutls
void log_func_for_gnutls(int level, const char *message)
This function logs debug messages from gnutls.
Definition logging.c:836
free_log_configuration
void free_log_configuration(GSList *log_domain_list)
Frees all resources loaded by the config loader.
Definition logging.c:286
get_time
gchar * get_time(gchar *time_fmt)
Returns time as specified in time_fmt strftime format.
Definition logging.c:57
level_int_from_string
static gint level_int_from_string(const gchar *level)
Return the integer corresponding to a log level string.
Definition logging.c:104
load_log_configuration
GSList * load_log_configuration(const gchar *config_file)
Loads parameters from a config file into a linked list.
Definition logging.c:161
gvm_log_unlock
void gvm_log_unlock(void)
Unlock logger_mutex.
Definition logging.c:363
log_tz
static gchar * log_tz
Timezone to use for logs.
Definition logging.c:43
gvm_log_lock
void gvm_log_lock(void)
Try to lock logger_mutex.
Definition logging.c:351
logger_mutex
static GMutex * logger_mutex
Definition logging.c:332
set_log_tz
void set_log_tz(const gchar *tz)
Set the log timezone.
Definition logging.c:901
gvm_log_lock_init
static void gvm_log_lock_init(void)
Initialize logger_mutex mutex if it was not done before.
Definition logging.c:338
facility_int_from_string
static gint facility_int_from_string(const gchar *facility)
Return the integer corresponding to a syslog facility string.
Definition logging.c:135
reference
static char * reference
Definition logging.c:368
setup_log_handlers
int setup_log_handlers(GSList *gvm_log_config_list)
Sets up routing of logdomains to log handlers.
Definition logging.c:979
gvm_log_silent
void gvm_log_silent(const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer gvm_log_config_list)
Returns immediately.
Definition logging.c:322
setup_log_handlers_internal
static int setup_log_handlers_internal(GSList *gvm_log_config_list, GLogFunc log_func, GLogFunc default_log_func, GLogFunc default_domain_log_func)
Definition logging.c:908
logging.h
Implementation of logging methods.
gvm_logging_domain_set_prepend_separator
void gvm_logging_domain_set_prepend_separator(gvm_logging_domain_t *log_domain, gchar *prepend_separator)
Sets the prepend separator for the logging domain.
Definition logging_domain.c:341
gvm_logging_domain_get_log_channel
GIOChannel * gvm_logging_domain_get_log_channel(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:359
gvm_logging_domain_set_log_file
void gvm_logging_domain_set_log_file(gvm_logging_domain_t *log_domain, gchar *log_file)
Sets the log file for the logging domain.
Definition logging_domain.c:137
gvm_logging_domain_set_syslog_ident
void gvm_logging_domain_set_syslog_ident(gvm_logging_domain_t *log_domain, gchar *syslog_ident)
Sets the syslog ident for the logging domain.
Definition logging_domain.c:307
gvm_logging_domain_set_prepend_time_format
void gvm_logging_domain_set_prepend_time_format(gvm_logging_domain_t *log_domain, gchar *prepend_time_format)
Sets the prepend time format for the logging domain.
Definition logging_domain.c:206
gvm_logging_domain_set_syslog_facility
void gvm_logging_domain_set_syslog_facility(gvm_logging_domain_t *log_domain, gchar *syslog_facility)
Sets the syslog facility for the logging domain.
Definition logging_domain.c:274
gvm_logging_domain_get_default_level
GLogLevelFlags * gvm_logging_domain_get_default_level(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:224
gvm_logging_domain_new
gvm_logging_domain_t * gvm_logging_domain_new(gchar *log_domain)
Function to initialize logging instance.
Definition logging_domain.c:40
gvm_logging_domain_get_prepend_time_format
gchar * gvm_logging_domain_get_prepend_time_format(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:189
gvm_logging_domain_get_syslog_ident
gchar * gvm_logging_domain_get_syslog_ident(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:292
gvm_logging_domain_set_log_channel
void gvm_logging_domain_set_log_channel(gvm_logging_domain_t *log_domain, GIOChannel *log_channel)
Sets the log channel for the logging domain.
Definition logging_domain.c:374
gvm_logging_domain_free
void gvm_logging_domain_free(gvm_logging_domain_t *log_domain)
Frees the resources associated with the given logging domain.
Definition logging_domain.c:72
gvm_logging_domain_get_log_file
gchar * gvm_logging_domain_get_log_file(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:121
gvm_logging_domain_set_prepend_string
void gvm_logging_domain_set_prepend_string(gvm_logging_domain_t *log_domain, gchar *prepend_string)
Sets the preprend string for the logging domain.
Definition logging_domain.c:171
gvm_logging_domain_get_log_domain
gchar * gvm_logging_domain_get_log_domain(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:105
gvm_logging_domain_set_default_level
void gvm_logging_domain_set_default_level(gvm_logging_domain_t *log_domain, GLogLevelFlags default_level)
Sets the default log level for the logging domain.
Definition logging_domain.c:239
gvm_logging_domain_get_prepend_separator
gchar * gvm_logging_domain_get_prepend_separator(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:325
gvm_logging_domain_get_prepend_string
gchar * gvm_logging_domain_get_prepend_string(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:155
gvm_logging_domain_get_syslog_facility
gchar * gvm_logging_domain_get_syslog_facility(gvm_logging_domain_t *log_domain)
Definition logging_domain.c:258
logging_domain.h
Implementation of logging domain handling.
gvm_logging_domain_t
struct gvm_logging_domain gvm_logging_domain_t
Definition logging_domain.h:15