xref: /openbmc/qemu/util/error-report.c (revision beede7e8)
115002f60SMarc-André Lureau /*
215002f60SMarc-André Lureau  * Error reporting
315002f60SMarc-André Lureau  *
415002f60SMarc-André Lureau  * Copyright (C) 2010 Red Hat Inc.
515002f60SMarc-André Lureau  *
615002f60SMarc-André Lureau  * Authors:
715002f60SMarc-André Lureau  *  Markus Armbruster <armbru@redhat.com>,
815002f60SMarc-André Lureau  *
915002f60SMarc-André Lureau  * This work is licensed under the terms of the GNU GPL, version 2 or later.
1015002f60SMarc-André Lureau  * See the COPYING file in the top-level directory.
1115002f60SMarc-André Lureau  */
1215002f60SMarc-André Lureau 
1315002f60SMarc-André Lureau #include "qemu/osdep.h"
1415002f60SMarc-André Lureau #include "monitor/monitor.h"
1515002f60SMarc-André Lureau #include "qemu/error-report.h"
1615002f60SMarc-André Lureau 
1715002f60SMarc-André Lureau /*
1815002f60SMarc-André Lureau  * @report_type is the type of message: error, warning or
1915002f60SMarc-André Lureau  * informational.
2015002f60SMarc-André Lureau  */
2115002f60SMarc-André Lureau typedef enum {
2215002f60SMarc-André Lureau     REPORT_TYPE_ERROR,
2315002f60SMarc-André Lureau     REPORT_TYPE_WARNING,
2415002f60SMarc-André Lureau     REPORT_TYPE_INFO,
2515002f60SMarc-André Lureau } report_type;
2615002f60SMarc-André Lureau 
2715002f60SMarc-André Lureau /* Prepend timestamp to messages */
2815002f60SMarc-André Lureau bool message_with_timestamp;
2915002f60SMarc-André Lureau bool error_with_guestname;
3015002f60SMarc-André Lureau const char *error_guest_name;
3115002f60SMarc-André Lureau 
error_printf(const char * fmt,...)3215002f60SMarc-André Lureau int error_printf(const char *fmt, ...)
3315002f60SMarc-André Lureau {
3415002f60SMarc-André Lureau     va_list ap;
3515002f60SMarc-André Lureau     int ret;
3615002f60SMarc-André Lureau 
3715002f60SMarc-André Lureau     va_start(ap, fmt);
3815002f60SMarc-André Lureau     ret = error_vprintf(fmt, ap);
3915002f60SMarc-André Lureau     va_end(ap);
4015002f60SMarc-André Lureau     return ret;
4115002f60SMarc-André Lureau }
4215002f60SMarc-André Lureau 
4315002f60SMarc-André Lureau static Location std_loc = {
4415002f60SMarc-André Lureau     .kind = LOC_NONE
4515002f60SMarc-André Lureau };
4615002f60SMarc-André Lureau static Location *cur_loc = &std_loc;
4715002f60SMarc-André Lureau 
4815002f60SMarc-André Lureau /*
4915002f60SMarc-André Lureau  * Push location saved in LOC onto the location stack, return it.
5015002f60SMarc-André Lureau  * The top of that stack is the current location.
5115002f60SMarc-André Lureau  * Needs a matching loc_pop().
5215002f60SMarc-André Lureau  */
loc_push_restore(Location * loc)5315002f60SMarc-André Lureau Location *loc_push_restore(Location *loc)
5415002f60SMarc-André Lureau {
5515002f60SMarc-André Lureau     assert(!loc->prev);
5615002f60SMarc-André Lureau     loc->prev = cur_loc;
5715002f60SMarc-André Lureau     cur_loc = loc;
5815002f60SMarc-André Lureau     return loc;
5915002f60SMarc-André Lureau }
6015002f60SMarc-André Lureau 
6115002f60SMarc-André Lureau /*
6215002f60SMarc-André Lureau  * Initialize *LOC to "nowhere", push it onto the location stack.
6315002f60SMarc-André Lureau  * The top of that stack is the current location.
6415002f60SMarc-André Lureau  * Needs a matching loc_pop().
6515002f60SMarc-André Lureau  * Return LOC.
6615002f60SMarc-André Lureau  */
loc_push_none(Location * loc)6715002f60SMarc-André Lureau Location *loc_push_none(Location *loc)
6815002f60SMarc-André Lureau {
6915002f60SMarc-André Lureau     loc->kind = LOC_NONE;
7015002f60SMarc-André Lureau     loc->prev = NULL;
7115002f60SMarc-André Lureau     return loc_push_restore(loc);
7215002f60SMarc-André Lureau }
7315002f60SMarc-André Lureau 
7415002f60SMarc-André Lureau /*
7515002f60SMarc-André Lureau  * Pop the location stack.
7615002f60SMarc-André Lureau  * LOC must be the current location, i.e. the top of the stack.
7715002f60SMarc-André Lureau  */
loc_pop(Location * loc)7815002f60SMarc-André Lureau Location *loc_pop(Location *loc)
7915002f60SMarc-André Lureau {
8015002f60SMarc-André Lureau     assert(cur_loc == loc && loc->prev);
8115002f60SMarc-André Lureau     cur_loc = loc->prev;
8215002f60SMarc-André Lureau     loc->prev = NULL;
8315002f60SMarc-André Lureau     return loc;
8415002f60SMarc-André Lureau }
8515002f60SMarc-André Lureau 
8615002f60SMarc-André Lureau /*
8715002f60SMarc-André Lureau  * Save the current location in LOC, return LOC.
8815002f60SMarc-André Lureau  */
loc_save(Location * loc)8915002f60SMarc-André Lureau Location *loc_save(Location *loc)
9015002f60SMarc-André Lureau {
9115002f60SMarc-André Lureau     *loc = *cur_loc;
9215002f60SMarc-André Lureau     loc->prev = NULL;
9315002f60SMarc-André Lureau     return loc;
9415002f60SMarc-André Lureau }
9515002f60SMarc-André Lureau 
9615002f60SMarc-André Lureau /*
9715002f60SMarc-André Lureau  * Change the current location to the one saved in LOC.
9815002f60SMarc-André Lureau  */
loc_restore(Location * loc)9915002f60SMarc-André Lureau void loc_restore(Location *loc)
10015002f60SMarc-André Lureau {
10115002f60SMarc-André Lureau     Location *prev = cur_loc->prev;
10215002f60SMarc-André Lureau     assert(!loc->prev);
10315002f60SMarc-André Lureau     *cur_loc = *loc;
10415002f60SMarc-André Lureau     cur_loc->prev = prev;
10515002f60SMarc-André Lureau }
10615002f60SMarc-André Lureau 
10715002f60SMarc-André Lureau /*
10815002f60SMarc-André Lureau  * Change the current location to "nowhere in particular".
10915002f60SMarc-André Lureau  */
loc_set_none(void)11015002f60SMarc-André Lureau void loc_set_none(void)
11115002f60SMarc-André Lureau {
11215002f60SMarc-André Lureau     cur_loc->kind = LOC_NONE;
11315002f60SMarc-André Lureau }
11415002f60SMarc-André Lureau 
11515002f60SMarc-André Lureau /*
11615002f60SMarc-André Lureau  * Change the current location to argument ARGV[IDX..IDX+CNT-1].
11715002f60SMarc-André Lureau  */
loc_set_cmdline(char ** argv,int idx,int cnt)11815002f60SMarc-André Lureau void loc_set_cmdline(char **argv, int idx, int cnt)
11915002f60SMarc-André Lureau {
12015002f60SMarc-André Lureau     cur_loc->kind = LOC_CMDLINE;
12115002f60SMarc-André Lureau     cur_loc->num = cnt;
12215002f60SMarc-André Lureau     cur_loc->ptr = argv + idx;
12315002f60SMarc-André Lureau }
12415002f60SMarc-André Lureau 
12515002f60SMarc-André Lureau /*
12615002f60SMarc-André Lureau  * Change the current location to file FNAME, line LNO.
12715002f60SMarc-André Lureau  */
loc_set_file(const char * fname,int lno)12815002f60SMarc-André Lureau void loc_set_file(const char *fname, int lno)
12915002f60SMarc-André Lureau {
13015002f60SMarc-André Lureau     assert (fname || cur_loc->kind == LOC_FILE);
13115002f60SMarc-André Lureau     cur_loc->kind = LOC_FILE;
13215002f60SMarc-André Lureau     cur_loc->num = lno;
13315002f60SMarc-André Lureau     if (fname) {
13415002f60SMarc-André Lureau         cur_loc->ptr = fname;
13515002f60SMarc-André Lureau     }
13615002f60SMarc-André Lureau }
13715002f60SMarc-André Lureau 
13815002f60SMarc-André Lureau /*
13915002f60SMarc-André Lureau  * Print current location to current monitor if we have one, else to stderr.
14015002f60SMarc-André Lureau  */
print_loc(void)14115002f60SMarc-André Lureau static void print_loc(void)
14215002f60SMarc-André Lureau {
14315002f60SMarc-André Lureau     const char *sep = "";
14415002f60SMarc-André Lureau     int i;
14515002f60SMarc-André Lureau     const char *const *argp;
14615002f60SMarc-André Lureau 
14715002f60SMarc-André Lureau     if (!monitor_cur() && g_get_prgname()) {
14811fd78dcSMarc-André Lureau         error_printf("%s:", g_get_prgname());
14915002f60SMarc-André Lureau         sep = " ";
15015002f60SMarc-André Lureau     }
15115002f60SMarc-André Lureau     switch (cur_loc->kind) {
15215002f60SMarc-André Lureau     case LOC_CMDLINE:
15315002f60SMarc-André Lureau         argp = cur_loc->ptr;
15415002f60SMarc-André Lureau         for (i = 0; i < cur_loc->num; i++) {
15515002f60SMarc-André Lureau             error_printf("%s%s", sep, argp[i]);
15615002f60SMarc-André Lureau             sep = " ";
15715002f60SMarc-André Lureau         }
15815002f60SMarc-André Lureau         error_printf(": ");
15915002f60SMarc-André Lureau         break;
16015002f60SMarc-André Lureau     case LOC_FILE:
16115002f60SMarc-André Lureau         error_printf("%s:", (const char *)cur_loc->ptr);
16215002f60SMarc-André Lureau         if (cur_loc->num) {
16315002f60SMarc-André Lureau             error_printf("%d:", cur_loc->num);
16415002f60SMarc-André Lureau         }
16515002f60SMarc-André Lureau         error_printf(" ");
16615002f60SMarc-André Lureau         break;
16715002f60SMarc-André Lureau     default:
16815002f60SMarc-André Lureau         error_printf("%s", sep);
16915002f60SMarc-André Lureau     }
17015002f60SMarc-André Lureau }
17115002f60SMarc-André Lureau 
17215002f60SMarc-André Lureau static char *
real_time_iso8601(void)17315002f60SMarc-André Lureau real_time_iso8601(void)
17415002f60SMarc-André Lureau {
17515002f60SMarc-André Lureau #if GLIB_CHECK_VERSION(2,62,0)
1765c08edd1SHaiyue Wang     g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
177951cc9dfSMarc-André Lureau     /* ignore deprecation warning, since GLIB_VERSION_MAX_ALLOWED is 2.56 */
178951cc9dfSMarc-André Lureau #pragma GCC diagnostic push
179951cc9dfSMarc-André Lureau #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
18015002f60SMarc-André Lureau     return g_date_time_format_iso8601(dt);
181951cc9dfSMarc-André Lureau #pragma GCC diagnostic pop
18215002f60SMarc-André Lureau #else
18315002f60SMarc-André Lureau     GTimeVal tv;
18415002f60SMarc-André Lureau     g_get_current_time(&tv);
18515002f60SMarc-André Lureau     return g_time_val_to_iso8601(&tv);
18615002f60SMarc-André Lureau #endif
18715002f60SMarc-André Lureau }
18815002f60SMarc-André Lureau 
18915002f60SMarc-André Lureau /*
19015002f60SMarc-André Lureau  * Print a message to current monitor if we have one, else to stderr.
19115002f60SMarc-André Lureau  * @report_type is the type of message: error, warning or informational.
19215002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
19315002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
19415002f60SMarc-André Lureau  * Prepend the current location and append a newline.
19515002f60SMarc-André Lureau  */
196*beede7e8SDaniel P. Berrangé G_GNUC_PRINTF(2, 0)
vreport(report_type type,const char * fmt,va_list ap)19715002f60SMarc-André Lureau static void vreport(report_type type, const char *fmt, va_list ap)
19815002f60SMarc-André Lureau {
19915002f60SMarc-André Lureau     gchar *timestr;
20015002f60SMarc-André Lureau 
20115002f60SMarc-André Lureau     if (message_with_timestamp && !monitor_cur()) {
20215002f60SMarc-André Lureau         timestr = real_time_iso8601();
20315002f60SMarc-André Lureau         error_printf("%s ", timestr);
20415002f60SMarc-André Lureau         g_free(timestr);
20515002f60SMarc-André Lureau     }
20615002f60SMarc-André Lureau 
20715002f60SMarc-André Lureau     /* Only prepend guest name if -msg guest-name and -name guest=... are set */
20815002f60SMarc-André Lureau     if (error_with_guestname && error_guest_name && !monitor_cur()) {
20915002f60SMarc-André Lureau         error_printf("%s ", error_guest_name);
21015002f60SMarc-André Lureau     }
21115002f60SMarc-André Lureau 
21215002f60SMarc-André Lureau     print_loc();
21315002f60SMarc-André Lureau 
21415002f60SMarc-André Lureau     switch (type) {
21515002f60SMarc-André Lureau     case REPORT_TYPE_ERROR:
21615002f60SMarc-André Lureau         break;
21715002f60SMarc-André Lureau     case REPORT_TYPE_WARNING:
21815002f60SMarc-André Lureau         error_printf("warning: ");
21915002f60SMarc-André Lureau         break;
22015002f60SMarc-André Lureau     case REPORT_TYPE_INFO:
22115002f60SMarc-André Lureau         error_printf("info: ");
22215002f60SMarc-André Lureau         break;
22315002f60SMarc-André Lureau     }
22415002f60SMarc-André Lureau 
22515002f60SMarc-André Lureau     error_vprintf(fmt, ap);
22615002f60SMarc-André Lureau     error_printf("\n");
22715002f60SMarc-André Lureau }
22815002f60SMarc-André Lureau 
22915002f60SMarc-André Lureau /*
23015002f60SMarc-André Lureau  * Print an error message to current monitor if we have one, else to stderr.
23115002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
23215002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
23315002f60SMarc-André Lureau  * Prepend the current location and append a newline.
23415002f60SMarc-André Lureau  * It's wrong to call this in a QMP monitor.  Use error_setg() there.
23515002f60SMarc-André Lureau  */
error_vreport(const char * fmt,va_list ap)23615002f60SMarc-André Lureau void error_vreport(const char *fmt, va_list ap)
23715002f60SMarc-André Lureau {
23815002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
23915002f60SMarc-André Lureau }
24015002f60SMarc-André Lureau 
24115002f60SMarc-André Lureau /*
24215002f60SMarc-André Lureau  * Print a warning message to current monitor if we have one, else to stderr.
24315002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
24415002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
24515002f60SMarc-André Lureau  * Prepend the current location and append a newline.
24615002f60SMarc-André Lureau  */
warn_vreport(const char * fmt,va_list ap)24715002f60SMarc-André Lureau void warn_vreport(const char *fmt, va_list ap)
24815002f60SMarc-André Lureau {
24915002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
25015002f60SMarc-André Lureau }
25115002f60SMarc-André Lureau 
25215002f60SMarc-André Lureau /*
25315002f60SMarc-André Lureau  * Print an information message to current monitor if we have one, else to
25415002f60SMarc-André Lureau  * stderr.
25515002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
25615002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
25715002f60SMarc-André Lureau  * Prepend the current location and append a newline.
25815002f60SMarc-André Lureau  */
info_vreport(const char * fmt,va_list ap)25915002f60SMarc-André Lureau void info_vreport(const char *fmt, va_list ap)
26015002f60SMarc-André Lureau {
26115002f60SMarc-André Lureau     vreport(REPORT_TYPE_INFO, fmt, ap);
26215002f60SMarc-André Lureau }
26315002f60SMarc-André Lureau 
26415002f60SMarc-André Lureau /*
26515002f60SMarc-André Lureau  * Print an error message to current monitor if we have one, else to stderr.
26615002f60SMarc-André Lureau  * Format arguments like sprintf().  The resulting message should be
26715002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
26815002f60SMarc-André Lureau  * Prepend the current location and append a newline.
26915002f60SMarc-André Lureau  * It's wrong to call this in a QMP monitor.  Use error_setg() there.
27015002f60SMarc-André Lureau  */
error_report(const char * fmt,...)27115002f60SMarc-André Lureau void error_report(const char *fmt, ...)
27215002f60SMarc-André Lureau {
27315002f60SMarc-André Lureau     va_list ap;
27415002f60SMarc-André Lureau 
27515002f60SMarc-André Lureau     va_start(ap, fmt);
27615002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
27715002f60SMarc-André Lureau     va_end(ap);
27815002f60SMarc-André Lureau }
27915002f60SMarc-André Lureau 
28015002f60SMarc-André Lureau /*
28115002f60SMarc-André Lureau  * Print a warning message to current monitor if we have one, else to stderr.
28215002f60SMarc-André Lureau  * Format arguments like sprintf(). The resulting message should be a
28315002f60SMarc-André Lureau  * single phrase, with no newline or trailing punctuation.
28415002f60SMarc-André Lureau  * Prepend the current location and append a newline.
28515002f60SMarc-André Lureau  */
warn_report(const char * fmt,...)28615002f60SMarc-André Lureau void warn_report(const char *fmt, ...)
28715002f60SMarc-André Lureau {
28815002f60SMarc-André Lureau     va_list ap;
28915002f60SMarc-André Lureau 
29015002f60SMarc-André Lureau     va_start(ap, fmt);
29115002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
29215002f60SMarc-André Lureau     va_end(ap);
29315002f60SMarc-André Lureau }
29415002f60SMarc-André Lureau 
29515002f60SMarc-André Lureau /*
29615002f60SMarc-André Lureau  * Print an information message to current monitor if we have one, else to
29715002f60SMarc-André Lureau  * stderr.
29815002f60SMarc-André Lureau  * Format arguments like sprintf(). The resulting message should be a
29915002f60SMarc-André Lureau  * single phrase, with no newline or trailing punctuation.
30015002f60SMarc-André Lureau  * Prepend the current location and append a newline.
30115002f60SMarc-André Lureau  */
info_report(const char * fmt,...)30215002f60SMarc-André Lureau void info_report(const char *fmt, ...)
30315002f60SMarc-André Lureau {
30415002f60SMarc-André Lureau     va_list ap;
30515002f60SMarc-André Lureau 
30615002f60SMarc-André Lureau     va_start(ap, fmt);
30715002f60SMarc-André Lureau     vreport(REPORT_TYPE_INFO, fmt, ap);
30815002f60SMarc-André Lureau     va_end(ap);
30915002f60SMarc-André Lureau }
31015002f60SMarc-André Lureau 
31115002f60SMarc-André Lureau /*
31215002f60SMarc-André Lureau  * Like error_report(), except print just once.
31315002f60SMarc-André Lureau  * If *printed is false, print the message, and flip *printed to true.
31415002f60SMarc-André Lureau  * Return whether the message was printed.
31515002f60SMarc-André Lureau  */
error_report_once_cond(bool * printed,const char * fmt,...)31615002f60SMarc-André Lureau bool error_report_once_cond(bool *printed, const char *fmt, ...)
31715002f60SMarc-André Lureau {
31815002f60SMarc-André Lureau     va_list ap;
31915002f60SMarc-André Lureau 
32015002f60SMarc-André Lureau     assert(printed);
32115002f60SMarc-André Lureau     if (*printed) {
32215002f60SMarc-André Lureau         return false;
32315002f60SMarc-André Lureau     }
32415002f60SMarc-André Lureau     *printed = true;
32515002f60SMarc-André Lureau     va_start(ap, fmt);
32615002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
32715002f60SMarc-André Lureau     va_end(ap);
32815002f60SMarc-André Lureau     return true;
32915002f60SMarc-André Lureau }
33015002f60SMarc-André Lureau 
33115002f60SMarc-André Lureau /*
33215002f60SMarc-André Lureau  * Like warn_report(), except print just once.
33315002f60SMarc-André Lureau  * If *printed is false, print the message, and flip *printed to true.
33415002f60SMarc-André Lureau  * Return whether the message was printed.
33515002f60SMarc-André Lureau  */
warn_report_once_cond(bool * printed,const char * fmt,...)33615002f60SMarc-André Lureau bool warn_report_once_cond(bool *printed, const char *fmt, ...)
33715002f60SMarc-André Lureau {
33815002f60SMarc-André Lureau     va_list ap;
33915002f60SMarc-André Lureau 
34015002f60SMarc-André Lureau     assert(printed);
34115002f60SMarc-André Lureau     if (*printed) {
34215002f60SMarc-André Lureau         return false;
34315002f60SMarc-André Lureau     }
34415002f60SMarc-André Lureau     *printed = true;
34515002f60SMarc-André Lureau     va_start(ap, fmt);
34615002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
34715002f60SMarc-André Lureau     va_end(ap);
34815002f60SMarc-André Lureau     return true;
34915002f60SMarc-André Lureau }
35015002f60SMarc-André Lureau 
35115002f60SMarc-André Lureau static char *qemu_glog_domains;
35215002f60SMarc-André Lureau 
qemu_log_func(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer user_data)35315002f60SMarc-André Lureau static void qemu_log_func(const gchar *log_domain,
35415002f60SMarc-André Lureau                           GLogLevelFlags log_level,
35515002f60SMarc-André Lureau                           const gchar *message,
35615002f60SMarc-André Lureau                           gpointer user_data)
35715002f60SMarc-André Lureau {
35815002f60SMarc-André Lureau     switch (log_level & G_LOG_LEVEL_MASK) {
35915002f60SMarc-André Lureau     case G_LOG_LEVEL_DEBUG:
36015002f60SMarc-André Lureau     case G_LOG_LEVEL_INFO:
36115002f60SMarc-André Lureau         /*
36215002f60SMarc-André Lureau          * Use same G_MESSAGES_DEBUG logic as glib to enable/disable debug
36315002f60SMarc-André Lureau          * messages
36415002f60SMarc-André Lureau          */
36515002f60SMarc-André Lureau         if (qemu_glog_domains == NULL) {
36615002f60SMarc-André Lureau             break;
36715002f60SMarc-André Lureau         }
36815002f60SMarc-André Lureau         if (strcmp(qemu_glog_domains, "all") != 0 &&
36915002f60SMarc-André Lureau           (log_domain == NULL || !strstr(qemu_glog_domains, log_domain))) {
37015002f60SMarc-André Lureau             break;
37115002f60SMarc-André Lureau         }
37215002f60SMarc-André Lureau         /* Fall through */
37315002f60SMarc-André Lureau     case G_LOG_LEVEL_MESSAGE:
37415002f60SMarc-André Lureau         info_report("%s%s%s",
37515002f60SMarc-André Lureau                     log_domain ?: "", log_domain ? ": " : "", message);
37615002f60SMarc-André Lureau 
37715002f60SMarc-André Lureau         break;
37815002f60SMarc-André Lureau     case G_LOG_LEVEL_WARNING:
37915002f60SMarc-André Lureau         warn_report("%s%s%s",
38015002f60SMarc-André Lureau                     log_domain ?: "", log_domain ? ": " : "", message);
38115002f60SMarc-André Lureau         break;
38215002f60SMarc-André Lureau     case G_LOG_LEVEL_CRITICAL:
38315002f60SMarc-André Lureau     case G_LOG_LEVEL_ERROR:
38415002f60SMarc-André Lureau         error_report("%s%s%s",
38515002f60SMarc-André Lureau                      log_domain ?: "", log_domain ? ": " : "", message);
38615002f60SMarc-André Lureau         break;
38715002f60SMarc-André Lureau     }
38815002f60SMarc-André Lureau }
38915002f60SMarc-André Lureau 
error_init(const char * argv0)39015002f60SMarc-André Lureau void error_init(const char *argv0)
39115002f60SMarc-André Lureau {
39215002f60SMarc-André Lureau     const char *p = strrchr(argv0, '/');
39315002f60SMarc-André Lureau 
39415002f60SMarc-André Lureau     /* Set the program name for error_print_loc(). */
39515002f60SMarc-André Lureau     g_set_prgname(p ? p + 1 : argv0);
39615002f60SMarc-André Lureau 
39715002f60SMarc-André Lureau     /*
39815002f60SMarc-André Lureau      * This sets up glib logging so libraries using it also print their logs
39915002f60SMarc-André Lureau      * through error_report(), warn_report(), info_report().
40015002f60SMarc-André Lureau      */
40115002f60SMarc-André Lureau     g_log_set_default_handler(qemu_log_func, NULL);
40215002f60SMarc-André Lureau     g_warn_if_fail(qemu_glog_domains == NULL);
40315002f60SMarc-André Lureau     qemu_glog_domains = g_strdup(g_getenv("G_MESSAGES_DEBUG"));
40415002f60SMarc-André Lureau }
405