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