xref: /openbmc/qemu/util/error-report.c (revision 15002f60)
1*15002f60SMarc-André Lureau /*
2*15002f60SMarc-André Lureau  * Error reporting
3*15002f60SMarc-André Lureau  *
4*15002f60SMarc-André Lureau  * Copyright (C) 2010 Red Hat Inc.
5*15002f60SMarc-André Lureau  *
6*15002f60SMarc-André Lureau  * Authors:
7*15002f60SMarc-André Lureau  *  Markus Armbruster <armbru@redhat.com>,
8*15002f60SMarc-André Lureau  *
9*15002f60SMarc-André Lureau  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10*15002f60SMarc-André Lureau  * See the COPYING file in the top-level directory.
11*15002f60SMarc-André Lureau  */
12*15002f60SMarc-André Lureau 
13*15002f60SMarc-André Lureau #include "qemu/osdep.h"
14*15002f60SMarc-André Lureau #include "monitor/monitor.h"
15*15002f60SMarc-André Lureau #include "qemu/error-report.h"
16*15002f60SMarc-André Lureau 
17*15002f60SMarc-André Lureau /*
18*15002f60SMarc-André Lureau  * @report_type is the type of message: error, warning or
19*15002f60SMarc-André Lureau  * informational.
20*15002f60SMarc-André Lureau  */
21*15002f60SMarc-André Lureau typedef enum {
22*15002f60SMarc-André Lureau     REPORT_TYPE_ERROR,
23*15002f60SMarc-André Lureau     REPORT_TYPE_WARNING,
24*15002f60SMarc-André Lureau     REPORT_TYPE_INFO,
25*15002f60SMarc-André Lureau } report_type;
26*15002f60SMarc-André Lureau 
27*15002f60SMarc-André Lureau /* Prepend timestamp to messages */
28*15002f60SMarc-André Lureau bool message_with_timestamp;
29*15002f60SMarc-André Lureau bool error_with_guestname;
30*15002f60SMarc-André Lureau const char *error_guest_name;
31*15002f60SMarc-André Lureau 
32*15002f60SMarc-André Lureau int error_printf(const char *fmt, ...)
33*15002f60SMarc-André Lureau {
34*15002f60SMarc-André Lureau     va_list ap;
35*15002f60SMarc-André Lureau     int ret;
36*15002f60SMarc-André Lureau 
37*15002f60SMarc-André Lureau     va_start(ap, fmt);
38*15002f60SMarc-André Lureau     ret = error_vprintf(fmt, ap);
39*15002f60SMarc-André Lureau     va_end(ap);
40*15002f60SMarc-André Lureau     return ret;
41*15002f60SMarc-André Lureau }
42*15002f60SMarc-André Lureau 
43*15002f60SMarc-André Lureau int error_printf_unless_qmp(const char *fmt, ...)
44*15002f60SMarc-André Lureau {
45*15002f60SMarc-André Lureau     va_list ap;
46*15002f60SMarc-André Lureau     int ret;
47*15002f60SMarc-André Lureau 
48*15002f60SMarc-André Lureau     va_start(ap, fmt);
49*15002f60SMarc-André Lureau     ret = error_vprintf_unless_qmp(fmt, ap);
50*15002f60SMarc-André Lureau     va_end(ap);
51*15002f60SMarc-André Lureau     return ret;
52*15002f60SMarc-André Lureau }
53*15002f60SMarc-André Lureau 
54*15002f60SMarc-André Lureau static Location std_loc = {
55*15002f60SMarc-André Lureau     .kind = LOC_NONE
56*15002f60SMarc-André Lureau };
57*15002f60SMarc-André Lureau static Location *cur_loc = &std_loc;
58*15002f60SMarc-André Lureau 
59*15002f60SMarc-André Lureau /*
60*15002f60SMarc-André Lureau  * Push location saved in LOC onto the location stack, return it.
61*15002f60SMarc-André Lureau  * The top of that stack is the current location.
62*15002f60SMarc-André Lureau  * Needs a matching loc_pop().
63*15002f60SMarc-André Lureau  */
64*15002f60SMarc-André Lureau Location *loc_push_restore(Location *loc)
65*15002f60SMarc-André Lureau {
66*15002f60SMarc-André Lureau     assert(!loc->prev);
67*15002f60SMarc-André Lureau     loc->prev = cur_loc;
68*15002f60SMarc-André Lureau     cur_loc = loc;
69*15002f60SMarc-André Lureau     return loc;
70*15002f60SMarc-André Lureau }
71*15002f60SMarc-André Lureau 
72*15002f60SMarc-André Lureau /*
73*15002f60SMarc-André Lureau  * Initialize *LOC to "nowhere", push it onto the location stack.
74*15002f60SMarc-André Lureau  * The top of that stack is the current location.
75*15002f60SMarc-André Lureau  * Needs a matching loc_pop().
76*15002f60SMarc-André Lureau  * Return LOC.
77*15002f60SMarc-André Lureau  */
78*15002f60SMarc-André Lureau Location *loc_push_none(Location *loc)
79*15002f60SMarc-André Lureau {
80*15002f60SMarc-André Lureau     loc->kind = LOC_NONE;
81*15002f60SMarc-André Lureau     loc->prev = NULL;
82*15002f60SMarc-André Lureau     return loc_push_restore(loc);
83*15002f60SMarc-André Lureau }
84*15002f60SMarc-André Lureau 
85*15002f60SMarc-André Lureau /*
86*15002f60SMarc-André Lureau  * Pop the location stack.
87*15002f60SMarc-André Lureau  * LOC must be the current location, i.e. the top of the stack.
88*15002f60SMarc-André Lureau  */
89*15002f60SMarc-André Lureau Location *loc_pop(Location *loc)
90*15002f60SMarc-André Lureau {
91*15002f60SMarc-André Lureau     assert(cur_loc == loc && loc->prev);
92*15002f60SMarc-André Lureau     cur_loc = loc->prev;
93*15002f60SMarc-André Lureau     loc->prev = NULL;
94*15002f60SMarc-André Lureau     return loc;
95*15002f60SMarc-André Lureau }
96*15002f60SMarc-André Lureau 
97*15002f60SMarc-André Lureau /*
98*15002f60SMarc-André Lureau  * Save the current location in LOC, return LOC.
99*15002f60SMarc-André Lureau  */
100*15002f60SMarc-André Lureau Location *loc_save(Location *loc)
101*15002f60SMarc-André Lureau {
102*15002f60SMarc-André Lureau     *loc = *cur_loc;
103*15002f60SMarc-André Lureau     loc->prev = NULL;
104*15002f60SMarc-André Lureau     return loc;
105*15002f60SMarc-André Lureau }
106*15002f60SMarc-André Lureau 
107*15002f60SMarc-André Lureau /*
108*15002f60SMarc-André Lureau  * Change the current location to the one saved in LOC.
109*15002f60SMarc-André Lureau  */
110*15002f60SMarc-André Lureau void loc_restore(Location *loc)
111*15002f60SMarc-André Lureau {
112*15002f60SMarc-André Lureau     Location *prev = cur_loc->prev;
113*15002f60SMarc-André Lureau     assert(!loc->prev);
114*15002f60SMarc-André Lureau     *cur_loc = *loc;
115*15002f60SMarc-André Lureau     cur_loc->prev = prev;
116*15002f60SMarc-André Lureau }
117*15002f60SMarc-André Lureau 
118*15002f60SMarc-André Lureau /*
119*15002f60SMarc-André Lureau  * Change the current location to "nowhere in particular".
120*15002f60SMarc-André Lureau  */
121*15002f60SMarc-André Lureau void loc_set_none(void)
122*15002f60SMarc-André Lureau {
123*15002f60SMarc-André Lureau     cur_loc->kind = LOC_NONE;
124*15002f60SMarc-André Lureau }
125*15002f60SMarc-André Lureau 
126*15002f60SMarc-André Lureau /*
127*15002f60SMarc-André Lureau  * Change the current location to argument ARGV[IDX..IDX+CNT-1].
128*15002f60SMarc-André Lureau  */
129*15002f60SMarc-André Lureau void loc_set_cmdline(char **argv, int idx, int cnt)
130*15002f60SMarc-André Lureau {
131*15002f60SMarc-André Lureau     cur_loc->kind = LOC_CMDLINE;
132*15002f60SMarc-André Lureau     cur_loc->num = cnt;
133*15002f60SMarc-André Lureau     cur_loc->ptr = argv + idx;
134*15002f60SMarc-André Lureau }
135*15002f60SMarc-André Lureau 
136*15002f60SMarc-André Lureau /*
137*15002f60SMarc-André Lureau  * Change the current location to file FNAME, line LNO.
138*15002f60SMarc-André Lureau  */
139*15002f60SMarc-André Lureau void loc_set_file(const char *fname, int lno)
140*15002f60SMarc-André Lureau {
141*15002f60SMarc-André Lureau     assert (fname || cur_loc->kind == LOC_FILE);
142*15002f60SMarc-André Lureau     cur_loc->kind = LOC_FILE;
143*15002f60SMarc-André Lureau     cur_loc->num = lno;
144*15002f60SMarc-André Lureau     if (fname) {
145*15002f60SMarc-André Lureau         cur_loc->ptr = fname;
146*15002f60SMarc-André Lureau     }
147*15002f60SMarc-André Lureau }
148*15002f60SMarc-André Lureau 
149*15002f60SMarc-André Lureau /*
150*15002f60SMarc-André Lureau  * Print current location to current monitor if we have one, else to stderr.
151*15002f60SMarc-André Lureau  */
152*15002f60SMarc-André Lureau static void print_loc(void)
153*15002f60SMarc-André Lureau {
154*15002f60SMarc-André Lureau     const char *sep = "";
155*15002f60SMarc-André Lureau     int i;
156*15002f60SMarc-André Lureau     const char *const *argp;
157*15002f60SMarc-André Lureau 
158*15002f60SMarc-André Lureau     if (!monitor_cur() && g_get_prgname()) {
159*15002f60SMarc-André Lureau         fprintf(stderr, "%s:", g_get_prgname());
160*15002f60SMarc-André Lureau         sep = " ";
161*15002f60SMarc-André Lureau     }
162*15002f60SMarc-André Lureau     switch (cur_loc->kind) {
163*15002f60SMarc-André Lureau     case LOC_CMDLINE:
164*15002f60SMarc-André Lureau         argp = cur_loc->ptr;
165*15002f60SMarc-André Lureau         for (i = 0; i < cur_loc->num; i++) {
166*15002f60SMarc-André Lureau             error_printf("%s%s", sep, argp[i]);
167*15002f60SMarc-André Lureau             sep = " ";
168*15002f60SMarc-André Lureau         }
169*15002f60SMarc-André Lureau         error_printf(": ");
170*15002f60SMarc-André Lureau         break;
171*15002f60SMarc-André Lureau     case LOC_FILE:
172*15002f60SMarc-André Lureau         error_printf("%s:", (const char *)cur_loc->ptr);
173*15002f60SMarc-André Lureau         if (cur_loc->num) {
174*15002f60SMarc-André Lureau             error_printf("%d:", cur_loc->num);
175*15002f60SMarc-André Lureau         }
176*15002f60SMarc-André Lureau         error_printf(" ");
177*15002f60SMarc-André Lureau         break;
178*15002f60SMarc-André Lureau     default:
179*15002f60SMarc-André Lureau         error_printf("%s", sep);
180*15002f60SMarc-André Lureau     }
181*15002f60SMarc-André Lureau }
182*15002f60SMarc-André Lureau 
183*15002f60SMarc-André Lureau static char *
184*15002f60SMarc-André Lureau real_time_iso8601(void)
185*15002f60SMarc-André Lureau {
186*15002f60SMarc-André Lureau #if GLIB_CHECK_VERSION(2, 62, 0)
187*15002f60SMarc-André Lureau     g_autoptr(GDateTime) dt = g_date_time_new_from_unix_utc(g_get_real_time());
188*15002f60SMarc-André Lureau     return g_date_time_format_iso8601(dt);
189*15002f60SMarc-André Lureau #else
190*15002f60SMarc-André Lureau     GTimeVal tv;
191*15002f60SMarc-André Lureau     g_get_current_time(&tv);
192*15002f60SMarc-André Lureau     return g_time_val_to_iso8601(&tv);
193*15002f60SMarc-André Lureau #endif
194*15002f60SMarc-André Lureau }
195*15002f60SMarc-André Lureau 
196*15002f60SMarc-André Lureau /*
197*15002f60SMarc-André Lureau  * Print a message to current monitor if we have one, else to stderr.
198*15002f60SMarc-André Lureau  * @report_type is the type of message: error, warning or informational.
199*15002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
200*15002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
201*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
202*15002f60SMarc-André Lureau  */
203*15002f60SMarc-André Lureau static void vreport(report_type type, const char *fmt, va_list ap)
204*15002f60SMarc-André Lureau {
205*15002f60SMarc-André Lureau     gchar *timestr;
206*15002f60SMarc-André Lureau 
207*15002f60SMarc-André Lureau     if (message_with_timestamp && !monitor_cur()) {
208*15002f60SMarc-André Lureau         timestr = real_time_iso8601();
209*15002f60SMarc-André Lureau         error_printf("%s ", timestr);
210*15002f60SMarc-André Lureau         g_free(timestr);
211*15002f60SMarc-André Lureau     }
212*15002f60SMarc-André Lureau 
213*15002f60SMarc-André Lureau     /* Only prepend guest name if -msg guest-name and -name guest=... are set */
214*15002f60SMarc-André Lureau     if (error_with_guestname && error_guest_name && !monitor_cur()) {
215*15002f60SMarc-André Lureau         error_printf("%s ", error_guest_name);
216*15002f60SMarc-André Lureau     }
217*15002f60SMarc-André Lureau 
218*15002f60SMarc-André Lureau     print_loc();
219*15002f60SMarc-André Lureau 
220*15002f60SMarc-André Lureau     switch (type) {
221*15002f60SMarc-André Lureau     case REPORT_TYPE_ERROR:
222*15002f60SMarc-André Lureau         break;
223*15002f60SMarc-André Lureau     case REPORT_TYPE_WARNING:
224*15002f60SMarc-André Lureau         error_printf("warning: ");
225*15002f60SMarc-André Lureau         break;
226*15002f60SMarc-André Lureau     case REPORT_TYPE_INFO:
227*15002f60SMarc-André Lureau         error_printf("info: ");
228*15002f60SMarc-André Lureau         break;
229*15002f60SMarc-André Lureau     }
230*15002f60SMarc-André Lureau 
231*15002f60SMarc-André Lureau     error_vprintf(fmt, ap);
232*15002f60SMarc-André Lureau     error_printf("\n");
233*15002f60SMarc-André Lureau }
234*15002f60SMarc-André Lureau 
235*15002f60SMarc-André Lureau /*
236*15002f60SMarc-André Lureau  * Print an error message to current monitor if we have one, else to stderr.
237*15002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
238*15002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
239*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
240*15002f60SMarc-André Lureau  * It's wrong to call this in a QMP monitor.  Use error_setg() there.
241*15002f60SMarc-André Lureau  */
242*15002f60SMarc-André Lureau void error_vreport(const char *fmt, va_list ap)
243*15002f60SMarc-André Lureau {
244*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
245*15002f60SMarc-André Lureau }
246*15002f60SMarc-André Lureau 
247*15002f60SMarc-André Lureau /*
248*15002f60SMarc-André Lureau  * Print a warning message to current monitor if we have one, else to stderr.
249*15002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
250*15002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
251*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
252*15002f60SMarc-André Lureau  */
253*15002f60SMarc-André Lureau void warn_vreport(const char *fmt, va_list ap)
254*15002f60SMarc-André Lureau {
255*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
256*15002f60SMarc-André Lureau }
257*15002f60SMarc-André Lureau 
258*15002f60SMarc-André Lureau /*
259*15002f60SMarc-André Lureau  * Print an information message to current monitor if we have one, else to
260*15002f60SMarc-André Lureau  * stderr.
261*15002f60SMarc-André Lureau  * Format arguments like vsprintf().  The resulting message should be
262*15002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
263*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
264*15002f60SMarc-André Lureau  */
265*15002f60SMarc-André Lureau void info_vreport(const char *fmt, va_list ap)
266*15002f60SMarc-André Lureau {
267*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_INFO, fmt, ap);
268*15002f60SMarc-André Lureau }
269*15002f60SMarc-André Lureau 
270*15002f60SMarc-André Lureau /*
271*15002f60SMarc-André Lureau  * Print an error message to current monitor if we have one, else to stderr.
272*15002f60SMarc-André Lureau  * Format arguments like sprintf().  The resulting message should be
273*15002f60SMarc-André Lureau  * a single phrase, with no newline or trailing punctuation.
274*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
275*15002f60SMarc-André Lureau  * It's wrong to call this in a QMP monitor.  Use error_setg() there.
276*15002f60SMarc-André Lureau  */
277*15002f60SMarc-André Lureau void error_report(const char *fmt, ...)
278*15002f60SMarc-André Lureau {
279*15002f60SMarc-André Lureau     va_list ap;
280*15002f60SMarc-André Lureau 
281*15002f60SMarc-André Lureau     va_start(ap, fmt);
282*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
283*15002f60SMarc-André Lureau     va_end(ap);
284*15002f60SMarc-André Lureau }
285*15002f60SMarc-André Lureau 
286*15002f60SMarc-André Lureau /*
287*15002f60SMarc-André Lureau  * Print a warning message to current monitor if we have one, else to stderr.
288*15002f60SMarc-André Lureau  * Format arguments like sprintf(). The resulting message should be a
289*15002f60SMarc-André Lureau  * single phrase, with no newline or trailing punctuation.
290*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
291*15002f60SMarc-André Lureau  */
292*15002f60SMarc-André Lureau void warn_report(const char *fmt, ...)
293*15002f60SMarc-André Lureau {
294*15002f60SMarc-André Lureau     va_list ap;
295*15002f60SMarc-André Lureau 
296*15002f60SMarc-André Lureau     va_start(ap, fmt);
297*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
298*15002f60SMarc-André Lureau     va_end(ap);
299*15002f60SMarc-André Lureau }
300*15002f60SMarc-André Lureau 
301*15002f60SMarc-André Lureau /*
302*15002f60SMarc-André Lureau  * Print an information message to current monitor if we have one, else to
303*15002f60SMarc-André Lureau  * stderr.
304*15002f60SMarc-André Lureau  * Format arguments like sprintf(). The resulting message should be a
305*15002f60SMarc-André Lureau  * single phrase, with no newline or trailing punctuation.
306*15002f60SMarc-André Lureau  * Prepend the current location and append a newline.
307*15002f60SMarc-André Lureau  */
308*15002f60SMarc-André Lureau void info_report(const char *fmt, ...)
309*15002f60SMarc-André Lureau {
310*15002f60SMarc-André Lureau     va_list ap;
311*15002f60SMarc-André Lureau 
312*15002f60SMarc-André Lureau     va_start(ap, fmt);
313*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_INFO, fmt, ap);
314*15002f60SMarc-André Lureau     va_end(ap);
315*15002f60SMarc-André Lureau }
316*15002f60SMarc-André Lureau 
317*15002f60SMarc-André Lureau /*
318*15002f60SMarc-André Lureau  * Like error_report(), except print just once.
319*15002f60SMarc-André Lureau  * If *printed is false, print the message, and flip *printed to true.
320*15002f60SMarc-André Lureau  * Return whether the message was printed.
321*15002f60SMarc-André Lureau  */
322*15002f60SMarc-André Lureau bool error_report_once_cond(bool *printed, const char *fmt, ...)
323*15002f60SMarc-André Lureau {
324*15002f60SMarc-André Lureau     va_list ap;
325*15002f60SMarc-André Lureau 
326*15002f60SMarc-André Lureau     assert(printed);
327*15002f60SMarc-André Lureau     if (*printed) {
328*15002f60SMarc-André Lureau         return false;
329*15002f60SMarc-André Lureau     }
330*15002f60SMarc-André Lureau     *printed = true;
331*15002f60SMarc-André Lureau     va_start(ap, fmt);
332*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_ERROR, fmt, ap);
333*15002f60SMarc-André Lureau     va_end(ap);
334*15002f60SMarc-André Lureau     return true;
335*15002f60SMarc-André Lureau }
336*15002f60SMarc-André Lureau 
337*15002f60SMarc-André Lureau /*
338*15002f60SMarc-André Lureau  * Like warn_report(), except print just once.
339*15002f60SMarc-André Lureau  * If *printed is false, print the message, and flip *printed to true.
340*15002f60SMarc-André Lureau  * Return whether the message was printed.
341*15002f60SMarc-André Lureau  */
342*15002f60SMarc-André Lureau bool warn_report_once_cond(bool *printed, const char *fmt, ...)
343*15002f60SMarc-André Lureau {
344*15002f60SMarc-André Lureau     va_list ap;
345*15002f60SMarc-André Lureau 
346*15002f60SMarc-André Lureau     assert(printed);
347*15002f60SMarc-André Lureau     if (*printed) {
348*15002f60SMarc-André Lureau         return false;
349*15002f60SMarc-André Lureau     }
350*15002f60SMarc-André Lureau     *printed = true;
351*15002f60SMarc-André Lureau     va_start(ap, fmt);
352*15002f60SMarc-André Lureau     vreport(REPORT_TYPE_WARNING, fmt, ap);
353*15002f60SMarc-André Lureau     va_end(ap);
354*15002f60SMarc-André Lureau     return true;
355*15002f60SMarc-André Lureau }
356*15002f60SMarc-André Lureau 
357*15002f60SMarc-André Lureau static char *qemu_glog_domains;
358*15002f60SMarc-André Lureau 
359*15002f60SMarc-André Lureau static void qemu_log_func(const gchar *log_domain,
360*15002f60SMarc-André Lureau                           GLogLevelFlags log_level,
361*15002f60SMarc-André Lureau                           const gchar *message,
362*15002f60SMarc-André Lureau                           gpointer user_data)
363*15002f60SMarc-André Lureau {
364*15002f60SMarc-André Lureau     switch (log_level & G_LOG_LEVEL_MASK) {
365*15002f60SMarc-André Lureau     case G_LOG_LEVEL_DEBUG:
366*15002f60SMarc-André Lureau     case G_LOG_LEVEL_INFO:
367*15002f60SMarc-André Lureau         /*
368*15002f60SMarc-André Lureau          * Use same G_MESSAGES_DEBUG logic as glib to enable/disable debug
369*15002f60SMarc-André Lureau          * messages
370*15002f60SMarc-André Lureau          */
371*15002f60SMarc-André Lureau         if (qemu_glog_domains == NULL) {
372*15002f60SMarc-André Lureau             break;
373*15002f60SMarc-André Lureau         }
374*15002f60SMarc-André Lureau         if (strcmp(qemu_glog_domains, "all") != 0 &&
375*15002f60SMarc-André Lureau           (log_domain == NULL || !strstr(qemu_glog_domains, log_domain))) {
376*15002f60SMarc-André Lureau             break;
377*15002f60SMarc-André Lureau         }
378*15002f60SMarc-André Lureau         /* Fall through */
379*15002f60SMarc-André Lureau     case G_LOG_LEVEL_MESSAGE:
380*15002f60SMarc-André Lureau         info_report("%s%s%s",
381*15002f60SMarc-André Lureau                     log_domain ?: "", log_domain ? ": " : "", message);
382*15002f60SMarc-André Lureau 
383*15002f60SMarc-André Lureau         break;
384*15002f60SMarc-André Lureau     case G_LOG_LEVEL_WARNING:
385*15002f60SMarc-André Lureau         warn_report("%s%s%s",
386*15002f60SMarc-André Lureau                     log_domain ?: "", log_domain ? ": " : "", message);
387*15002f60SMarc-André Lureau         break;
388*15002f60SMarc-André Lureau     case G_LOG_LEVEL_CRITICAL:
389*15002f60SMarc-André Lureau     case G_LOG_LEVEL_ERROR:
390*15002f60SMarc-André Lureau         error_report("%s%s%s",
391*15002f60SMarc-André Lureau                      log_domain ?: "", log_domain ? ": " : "", message);
392*15002f60SMarc-André Lureau         break;
393*15002f60SMarc-André Lureau     }
394*15002f60SMarc-André Lureau }
395*15002f60SMarc-André Lureau 
396*15002f60SMarc-André Lureau void error_init(const char *argv0)
397*15002f60SMarc-André Lureau {
398*15002f60SMarc-André Lureau     const char *p = strrchr(argv0, '/');
399*15002f60SMarc-André Lureau 
400*15002f60SMarc-André Lureau     /* Set the program name for error_print_loc(). */
401*15002f60SMarc-André Lureau     g_set_prgname(p ? p + 1 : argv0);
402*15002f60SMarc-André Lureau 
403*15002f60SMarc-André Lureau     /*
404*15002f60SMarc-André Lureau      * This sets up glib logging so libraries using it also print their logs
405*15002f60SMarc-André Lureau      * through error_report(), warn_report(), info_report().
406*15002f60SMarc-André Lureau      */
407*15002f60SMarc-André Lureau     g_log_set_default_handler(qemu_log_func, NULL);
408*15002f60SMarc-André Lureau     g_warn_if_fail(qemu_glog_domains == NULL);
409*15002f60SMarc-André Lureau     qemu_glog_domains = g_strdup(g_getenv("G_MESSAGES_DEBUG"));
410*15002f60SMarc-André Lureau }
411