/* ----------------------------------------------------------------------- * * * log.c - applcation logging routines. * * Copyright 2004 Denis Vlasenko * - All Rights Reserved * Copyright 2005 Ian Kent - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, * USA; either version 2 of the License, or (at your option) any later * version; incorporated herein by reference. * * This module has been adapted from patches submitted by: * Denis Vlasenko * Thanks Denis. * * ----------------------------------------------------------------------- */ #include #include #include #include #include "automount.h" static unsigned int syslog_open = 0; static unsigned int logging_to_syslog = 0; /* log notification level */ static unsigned int do_verbose = 0; /* Verbose feedback option */ static unsigned int do_debug = 0; /* Full debug output */ static char *prepare_attempt_prefix(const char *msg) { unsigned long *attempt_id; char buffer[ATTEMPT_ID_SIZE + 1]; char *prefixed_msg = NULL; attempt_id = pthread_getspecific(key_thread_attempt_id); if (attempt_id) { int len = sizeof(buffer) + 1 + strlen(msg) + 1; snprintf(buffer, ATTEMPT_ID_SIZE, "%02lx", *attempt_id); prefixed_msg = (char *) calloc(len, sizeof(char)); if (!prefixed_msg) return NULL; strcpy(prefixed_msg, buffer); strcat(prefixed_msg, "|"); strcat(prefixed_msg, msg); } return prefixed_msg; } void set_log_norm(void) { do_verbose = 0; do_debug = 0; return; } void set_log_verbose(void) { do_verbose = 1; return; } void set_log_debug(void) { do_debug = 1; return; } void set_log_norm_ap(struct autofs_point *ap) { ap->logopt = LOGOPT_ERROR; return; } void set_log_verbose_ap(struct autofs_point *ap) { ap->logopt = LOGOPT_VERBOSE; return; } void set_log_debug_ap(struct autofs_point *ap) { ap->logopt = LOGOPT_DEBUG; return; } void log_info(unsigned int logopt, const char *msg, ...) { unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); char *prefixed_msg; va_list ap; if (!do_debug && !do_verbose && !opt_log) return; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_INFO, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void log_notice(unsigned int logopt, const char *msg, ...) { unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); char *prefixed_msg; va_list ap; if (!do_debug && !do_verbose && !opt_log) return; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_NOTICE, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void log_warn(unsigned int logopt, const char *msg, ...) { unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); char *prefixed_msg; va_list ap; if (!do_debug && !do_verbose && !opt_log) return; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_WARNING, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void log_error(unsigned logopt, const char *msg, ...) { char *prefixed_msg; va_list ap; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_ERR, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void log_crit(unsigned logopt, const char *msg, ...) { char *prefixed_msg; va_list ap; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_CRIT, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void log_debug(unsigned int logopt, const char *msg, ...) { unsigned int opt_log = logopt & LOGOPT_DEBUG; char *prefixed_msg; va_list ap; if (!do_debug && !opt_log) return; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_WARNING, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void logmsg(const char *msg, ...) { char *prefixed_msg; va_list ap; prefixed_msg = prepare_attempt_prefix(msg); va_start(ap, msg); if (logging_to_syslog) { if (prefixed_msg) vsyslog(LOG_CRIT, prefixed_msg, ap); else vsyslog(LOG_INFO, msg, ap); } else { if (prefixed_msg) vfprintf(stderr, prefixed_msg, ap); else vfprintf(stderr, msg, ap); fputc('\n', stderr); } va_end(ap); if (prefixed_msg) free(prefixed_msg); return; } void open_log(void) { if (!syslog_open) { syslog_open = 1; openlog("automount", LOG_PID, LOG_DAEMON); } logging_to_syslog = 1; return; } void log_to_stderr(void) { if (syslog_open) { syslog_open = 0; closelog(); } logging_to_syslog = 0; return; } pid_t log_pidinfo(struct autofs_point *ap, pid_t pid, char *label) { char buf[PATH_MAX + 1] = ""; FILE *statfile; pid_t tgid, ppid; int uid, euid, gid, egid; char comm[64] = ""; sprintf(buf, "/proc/%d/status", pid); statfile = fopen(buf, "r"); if (statfile == NULL) { info(ap->logopt, "pidinfo %s: failed to open %s", label, buf); return -1; } while (fgets(buf, sizeof(buf), statfile) != NULL) { if (strncmp(buf, "Name:", 5) == 0) { sscanf(buf, "Name:\t%s", (char *) &comm); } else if (strncmp(buf, "Tgid:", 5) == 0) { sscanf(buf, "Tgid:\t%d", (int *) &tgid); } else if (strncmp(buf, "PPid:", 5) == 0) { sscanf(buf, "PPid:\t%d", (int *) &ppid); } else if (strncmp(buf, "Uid:", 4) == 0) { sscanf(buf, "Uid:\t%d\t%d", (int *) &uid, (int *) &euid); } else if (strncmp(buf, "Gid:", 4) == 0) { sscanf(buf, "Gid:\t%d\t%d", (int *) &gid, (int *) &egid); } } fclose(statfile); info(ap->logopt, "pidinfo %s: pid:%d comm:%s tgid:%d uid:%d euid:%d gid:%d egid:%d", label, pid, comm, tgid, uid, euid, gid, egid); return ppid; }