//debug.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2013 * * This file is part of libroar a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * libroar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * NOTE for everyone want's to change something and send patches: * read README and HACKING! There a addition information on * the license of this document you need to read before you send * any patches. * * NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc * or libpulse*: * The libs libroaresd, libroararts and libroarpulse link this lib * and are therefore GPL. Because of this it may be illigal to use * them with any software that uses libesd, libartsc or libpulse*. */ #include "libroar.h" static int roar_debug_stderr_mode = ROAR_DEBUG_MODE_SYSIO; static int roar_debug_stderr_fh = ROAR_STDERR; static struct roar_vio_calls * roar_debug_stderr_vio = NULL; void roar_debug_warn_sysio_real(char * func, char * newfunc, char * info) { struct roar_libroar_config * config = roar_libroar_get_config(); if ( !roar_libroar_iswarn(config) ) return; if ( config->warnings.sysio == ROAR_WARNING_ALWAYS ) { if ( newfunc == NULL ) { ROAR_WARN("%s(*): This function is obsolete. %s", func, info == NULL ? "" : info); } else { ROAR_WARN("%s(*): This function is obsolete. Please use %s(...). %s", func, newfunc, info == NULL ? "" : info); } } } void roar_debug_warn_obsolete_real(char * func, char * newfunc, char * info) { struct roar_libroar_config * config = roar_libroar_get_config(); if ( !roar_libroar_iswarn(config) ) return; if ( config->warnings.obsolete == ROAR_WARNING_ALWAYS ) { if ( newfunc == NULL ) { ROAR_WARN("%s(*): This function is obsolete. %s", func, info == NULL ? "" : info); } else { ROAR_WARN("%s(*): This function is obsolete. Please use %s(...). %s", func, newfunc, info == NULL ? "" : info); } } } void roar_debug_bin_obsolete(const char * progname, const char * newprog, const char * info) { if ( info == NULL ) info = ""; if ( newprog == NULL ) { roar_debug_msg(ROAR_DEBUG_TYPE_ERROR, 0, progname, ROAR_DBG_PREFIX, "This program is obsolete and will be removed soon. %s", info); } else { roar_debug_msg(ROAR_DEBUG_TYPE_ERROR, 0, progname, ROAR_DBG_PREFIX, "This program is obsolete and will be removed soon. Please use %s. %s", newprog, info); } } void roar_debug_set_stderr_fh(int fh) { roar_debug_stderr_fh = fh; } void roar_debug_set_stderr_vio(struct roar_vio_calls * vio) { roar_debug_stderr_vio = vio; } void roar_debug_set_stderr_mode(int mode) { roar_debug_stderr_mode = mode; } struct roar_vio_calls * roar_debug_get_stderr(void) { static struct roar_vio_calls STDERR; switch (roar_debug_stderr_mode) { case ROAR_DEBUG_MODE_SYSIO: if ( roar_debug_stderr_fh == -1 ) return NULL; roar_vio_open_fh(&STDERR, roar_debug_stderr_fh); return &STDERR; break; case ROAR_DEBUG_MODE_VIO: return roar_debug_stderr_vio; break; default: return NULL; break; } } // NOTE: This function MUST NOT alter RA's error values nor errno! void roar_debug_msg_simple(const char *format, ...) { struct roar_vio_calls * vio; va_list ap; int ret; char buf[8192]; #ifdef ROAR_HAVE_SYSLOG size_t len; #endif int _ra_error = roar_error; int _sys_error = errno; vio = roar_debug_get_stderr(); va_start(ap, format); ret = vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); buf[sizeof(buf)-1] = 0; if ( vio != NULL ) { _LIBROAR_IGNORE_RET(roar_vio_write(vio, buf, ret)); roar_vio_sync(vio); } else { switch (roar_debug_stderr_mode) { #ifdef ROAR_HAVE_SYSLOG case ROAR_DEBUG_MODE_SYSLOG: // strip \n if needed for syslog: len = strlen(buf); if ( buf[len-1] == '\n' ) buf[len-1] = 0; syslog(LOG_ERR, "%s", buf); // bad to use some defaults break; #endif default: // do nothing. break; } } roar_error = _ra_error; errno = _sys_error; } void roar_debug_msg(int type, unsigned long int line, const char * file, const char * prefix, const char * format, ...) { struct roar_vio_calls * vio; va_list ap; char buf[8192]; char * bufp = buf; char * typename; int ret; #ifdef ROAR_HAVE_SYSLOG int priority; #endif size_t len; struct roar_error_state error_state; roar_err_store(&error_state); switch (type) { case ROAR_DEBUG_TYPE_ERROR: typename = "Error"; break; case ROAR_DEBUG_TYPE_WARNING: typename = "Warning"; break; case ROAR_DEBUG_TYPE_INFO: typename = "Info"; break; case ROAR_DEBUG_TYPE_DEBUG: typename = "Debug"; break; default: typename = "Unknown Type"; break; } ret = snprintf(buf, sizeof(buf), "(%s: %s:%lu): %s: ", prefix, file, line, typename); if ( ret > 0 && ret < (int)sizeof(buf) ) { bufp += ret; } else { ret = 0; } len = ret; va_start(ap, format); ret = vsnprintf(bufp, sizeof(buf)-ret, format, ap); va_end(ap); buf[sizeof(buf)-1] = 0; len += ret; switch (roar_debug_stderr_mode) { case ROAR_DEBUG_MODE_SYSIO: case ROAR_DEBUG_MODE_VIO: if ( (vio = roar_debug_get_stderr()) == NULL ) { roar_err_restore(&error_state); return; } _LIBROAR_IGNORE_RET(roar_vio_write(vio, buf, len)); _LIBROAR_IGNORE_RET(roar_vio_write(vio, "\n", 1)); roar_vio_sync(vio); break; #ifdef ROAR_HAVE_SYSLOG case ROAR_DEBUG_MODE_SYSLOG: switch (type) { case ROAR_DEBUG_TYPE_ERROR: priority = LOG_ERR; break; case ROAR_DEBUG_TYPE_WARNING: priority = LOG_WARNING; break; case ROAR_DEBUG_TYPE_INFO: priority = LOG_INFO; break; case ROAR_DEBUG_TYPE_DEBUG: priority = LOG_DEBUG; break; default: priority = LOG_ERR; break; } syslog(priority, "%s", buf); break; #endif } roar_err_restore(&error_state); } //ll