#import <pthread.h>
#import <mach/mach_error.h>
#import <stdio.h>
#import <syslog.h>
#import <sys/syslimits.h>
#import <libc.h>
#import <errno.h>
#import "bootstrap_internal.h"
#import "error_log.h"
static pthread_mutex_t errlog_lock = PTHREAD_MUTEX_INITIALIZER;
static boolean_t stderr_open = FALSE;
static boolean_t log_stopped = FALSE;
void
init_errlog(boolean_t daemon)
{
int nfds, fd;
if (!daemon) {
stderr_open = TRUE;
nfds = getdtablesize();
for (fd = 3; fd < nfds; fd++)
close(fd);
} else {
openlog((char *)program_name, LOG_PID|LOG_CONS, LOG_DAEMON);
setlogmask(LOG_UPTO(LOG_DEBUG));
}
}
void
stop_errlog(void)
{
log_stopped = TRUE;
}
void
close_errlog(void)
{
stop_errlog();
closelog();
}
static void do_log(const int level, const char *format, va_list ap)
{
if (!log_stopped && (debugging || level <= LOG_NOTICE)) {
pthread_mutex_lock(&errlog_lock);
if (stderr_open) {
fprintf(stderr, "%s[%d]%s: ",
level == LOG_ALERT ? " FATAL" : "",
getpid(), program_name);
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
} else {
vsyslog(level, format, ap);
}
pthread_mutex_unlock(&errlog_lock);
}
}
void debug(const char *format, ...)
{
if (debugging) {
va_list ap;
va_start(ap, format);
do_log(LOG_DEBUG, format, ap);
va_end(ap);
}
}
void info(const char *format, ...)
{
va_list ap;
va_start(ap, format);
do_log(LOG_INFO, format, ap);
va_end(ap);
}
void notice(const char *format, ...)
{
va_list ap;
va_start(ap, format);
do_log(LOG_NOTICE, format, ap);
va_end(ap);
}
void error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
do_log(LOG_CRIT, format, ap);
va_end(ap);
}
void kern_error(kern_return_t result, const char *format, ...)
{
va_list ap;
char buf[1000];
sprintf(buf, "%s: %s(%d)", format, mach_error_string(result), result);
va_start(ap, format);
do_log(LOG_CRIT, buf, ap);
va_end(ap);
}
void unix_error(const char *format, ...)
{
va_list ap;
char buf[1000];
sprintf(buf, "%s: %s(%d)", format, strerror(errno), errno);
va_start(ap, format);
do_log(LOG_CRIT, buf, ap);
va_end(ap);
}
void parse_error(const char *token_string, const char *format, ...)
{
va_list ap;
char buf[1000];
sprintf(buf, "%s unexpected: %s", token_string, format);
va_start(ap, format);
do_log(LOG_CRIT, buf, ap);
va_end(ap);
}
void fatal(const char *format, ...)
{
va_list ap;
va_start(ap, format);
do_log(LOG_ALERT, format, ap);
va_end(ap);
exit(1);
}
void kern_fatal(kern_return_t result, const char *format, ...)
{
va_list ap;
char buf[1000];
sprintf(buf, "%s: %s(%d)", format, mach_error_string(result), result);
va_start(ap, format);
do_log(LOG_ALERT, buf, ap);
va_end(ap);
exit(1);
}
void unix_fatal(const char *format, ...)
{
va_list ap;
char buf[1000];
sprintf(buf, "%s: %s(%d)", format, strerror(errno), errno);
va_start(ap, format);
do_log(LOG_ALERT, buf, ap);
va_end(ap);
exit(1);
}