diff --git a/src/err.c b/src/err.c index 6c913adc..497e48fb 100644 --- a/src/err.c +++ b/src/err.c @@ -54,9 +54,15 @@ int err_debuglevel=0; /**< current debuglevel, set from command line with -d */ static int err_logdestination=LOGDEST_STDERR; /**< current log destination */ static FILE *err_file=NULL; /**< if logging to file, the handle of that file */ static pthread_mutex_t err_mutex=PTHREAD_MUTEX_INITIALIZER; /**< for serializing log messages */ -static unsigned int err_debugmask=0xFFFF; /**< what modules to debug, see \ref log_categories */ -#ifdef DEBUG_MEMORY +static unsigned int err_debugmask=0xFFFFFFFF; /**< modules to debug, see \ref log_categories */ +/** text list of modules to match for setting debug mask */ +static char *err_categorylist[] = { + "config","webserver","database","scan","query","index","browse", + "playlist","art","daap","main","rend",NULL +}; + +#ifdef DEBUG_MEMORY /** * Nodes for a linked list of in-use memory. Any malloc/strdup/etc * calls get a new node of this type added to the #err_leak list. @@ -83,13 +89,13 @@ static int err_unlock_mutex(void); /** * Write a printf-style formatted message to the log destination. * This can be stderr, syslog, or a logfile, as determined by - * log_setdest(). Note that this function should not be directly + * err_setdest(). Note that this function should not be directly * used, rather it should be used via the #DPRINTF macro. * * \param level Level at which to log \ref log_levels * \param fmt printf-style */ -void log_err(int level, unsigned int cat, char *fmt, ...) +void err_log(int level, unsigned int cat, char *fmt, ...) { va_list ap; char timebuf[256]; @@ -101,7 +107,7 @@ void log_err(int level, unsigned int cat, char *fmt, ...) if(level > err_debuglevel) return; - if(!(cat && err_debugmask)) + if(!(cat & err_debugmask)) return; } /* we'll *always* process a log level 0 */ @@ -121,7 +127,7 @@ void log_err(int level, unsigned int cat, char *fmt, ...) fflush(err_file); break; case LOGDEST_STDERR: - fprintf(stderr, "%s", errbuf); + fprintf(stderr, "%s",errbuf); if(!level) fprintf(stderr,"Aborting\n"); break; case LOGDEST_SYSLOG: @@ -143,7 +149,7 @@ void log_err(int level, unsigned int cat, char *fmt, ...) * \param app appname (used only for syslog destination) * \param destination where to log to \ref log_dests "as defined in err.h" */ -void log_setdest(char *app, int destination) { +void err_setdest(char *app, int destination) { if(err_logdestination == destination) return; @@ -171,7 +177,46 @@ void log_setdest(char *app, int destination) { err_logdestination=destination; } +/** + * Set the debug mask. Given a comma separated list, this walks + * through the err_categorylist and sets the bitfields for the + * requested log modules. + * + * \param list comma separated list of modules to debug. + */ +extern int err_setdebugmask(char *list) { + char **pcurrent=err_categorylist; + unsigned int rack; + char *token, *str, *last; + err_debugmask=0x80000000; /* always log L_MISC! */ + str=list; + + while(1) { + token=strtok_r(str,",",&last); + str=NULL; + + if(token) { + rack=1; + while((*pcurrent) && (strcasecmp(*pcurrent,token))) { + rack <<= 1; + pcurrent++; + } + + if(!pcurrent) { + DPRINTF(E_LOG,L_MISC,"Unknown module: %s\n",token); + return 1; + } else { + DPRINTF(E_DBG,L_MISC,"Adding module %s to debug list (0x%08x)\n",token,rack); + err_debugmask |= rack; + } + } else break; /* !token */ + } + + DPRINTF(E_LOG,L_MISC,"Debug mask is 0x%08x\n",err_debugmask); + + return 0; +} /** * Lock the error mutex. This is used to serialize diff --git a/src/err.h b/src/err.h index 9300b78b..ee58d5f6 100644 --- a/src/err.h +++ b/src/err.h @@ -59,18 +59,18 @@ extern int err_debuglevel; -extern void log_err(int level, unsigned int cat, char *fmt, ...); -extern void log_setdest(char *app, int destination); - +extern void err_log(int level, unsigned int cat, char *fmt, ...); +extern void err_setdest(char *app, int destination); +extern int err_setdebugmask(char *list); /** * Print a debugging or log message */ #ifdef DEBUG # define DPRINTF(level, cat, fmt, arg...) \ - { log_err(level,cat,"%s, %d: ",__FILE__,__LINE__); log_err(level,cat,fmt,##arg); } + { err_log(level,cat,"%s, %d: ",__FILE__,__LINE__); err_log(level,cat,fmt,##arg); } #else # define DPRINTF(level, cat, fmt, arg...) \ - { log_err(level,cat,fmt,##arg); } + { err_log(level,cat,fmt,##arg); } #endif #ifdef DEBUG_MEMORY diff --git a/src/main.c b/src/main.c index 724cc47e..cfa9e897 100644 --- a/src/main.c +++ b/src/main.c @@ -506,11 +506,16 @@ void usage(char *program) { printf("Usage: %s [options]\n\n",program); printf("Options:\n"); printf(" -d Debuglevel (0-9)\n"); + printf(" -D Debug modules\n"); printf(" -m Disable mDNS\n"); printf(" -c Use configfile specified"); printf(" -p Parse playlist file\n"); printf(" -f Run in foreground\n"); printf("\n\n"); + printf("Valid debug modules:\n"); + printf(" config,webserver,database,scan,query,index,browse\n"); + printf(" playlist,art,daap,main,rend,misc\n"); + printf("\n\n"); } /** @@ -673,11 +678,17 @@ int main(int argc, char *argv[]) { config.use_mdns=1; err_debuglevel=1; - while((option=getopt(argc,argv,"d:c:mpfr")) != -1) { + while((option=getopt(argc,argv,"D:d:c:mpfr")) != -1) { switch(option) { case 'd': err_debuglevel=atoi(optarg); break; + case 'D': + if(err_setdebugmask(optarg)) { + usage(argv[0]); + exit(-1); + } + break; case 'f': foreground=1; break; @@ -717,10 +728,10 @@ int main(int argc, char *argv[]) { } if((config.logfile) && (!parseonly) && (!foreground)) { - log_setdest(config.logfile,LOGDEST_LOGFILE); + err_setdest(config.logfile,LOGDEST_LOGFILE); } else { if(!foreground) { - log_setdest("mt-daapd",LOGDEST_SYSLOG); + err_setdest("mt-daapd",LOGDEST_SYSLOG); } } @@ -872,7 +883,7 @@ int main(int argc, char *argv[]) { DPRINTF(E_LOG,L_MAIN,"Done!\n"); - log_setdest(NULL,LOGDEST_STDERR); + err_setdest(NULL,LOGDEST_STDERR); return EXIT_SUCCESS; }