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