/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include "nscd_log.h" #include "nscd_config.h" #include "nscd_switch.h" #include "cache.h" /* * old nscd debug levels */ #define DBG_OFF 0 #define DBG_CANT_FIND 2 #define DBG_NETLOOKUPS 4 #define DBG_ALL 6 /* max. chars in a nscd log entry */ #define LOGBUFLEN 1024 /* configuration for the nscd log component */ int _nscd_log_comp = 0x0; int _nscd_log_level = 0x0; static char _nscd_logfile[PATH_MAX] = { 0 }; #define NSCD_DEBUG_NONE '0' #define NSCD_DEBUG_OPEN '1' #define NSCD_DEBUG_CLOSE '2' static char _nscd_debug = NSCD_DEBUG_NONE; static char _nscd_logfile_d[PATH_MAX] = { 0 }; static char _nscd_logfile_s[PATH_MAX] = { 0 }; /* statistics data */ static nscd_cfg_stat_global_log_t logstats = { NSCD_CFG_STAT_GROUP_INFO_GLOBAL_LOG, 0 }; /* if no log file specified, log entry goes to stderr */ int _logfd = 2; /* close old log file and open a new one */ static nscd_rc_t _nscd_set_lf( char *lf) { int newlogfd; char *me = "_nscd_set_lf"; /* * don't try and open the log file /dev/null */ if (lf == NULL || *lf == 0) { /* ignore empty log file specs */ return (NSCD_SUCCESS); } else if (strcmp(lf, "/dev/null") == 0) { (void) strlcpy(_nscd_logfile, lf, PATH_MAX); if (_logfd >= 0) (void) close(_logfd); _logfd = -1; return (NSCD_SUCCESS); } else if (strcmp(lf, "stderr") == 0) { (void) strlcpy(_nscd_logfile, lf, PATH_MAX); if (_logfd != -1 && _logfd != 2) (void) close(_logfd); _logfd = 2; return (NSCD_SUCCESS); } else { /* * In order to open this file securely, we'll try a few tricks */ if ((newlogfd = open(lf, O_EXCL|O_WRONLY|O_CREAT, 0644)) < 0) { /* * File already exists... now we need to get cute * since opening a file in a world-writeable directory * safely is hard = it could be a hard link or a * symbolic link to a system file. */ struct stat before; if (lstat(lf, &before) < 0) { if (_nscd_debug == NSCD_DEBUG_NONE) _nscd_logit(me, "Cannot open new " "logfile \"%s\": %sn", lf, strerror(errno)); return (NSCD_CFG_FILE_OPEN_ERROR); } if (S_ISREG(before.st_mode) && /* no symbolic links */ (before.st_nlink == 1) && /* no hard links */ (before.st_uid == 0)) { /* owned by root */ if ((newlogfd = open(lf, O_APPEND|O_WRONLY, 0644)) < 0) { if (_nscd_debug == NSCD_DEBUG_NONE) _nscd_logit(me, "Cannot open new "\ "logfile \"%s\": %s\n", lf, strerror(errno)); return (NSCD_CFG_FILE_OPEN_ERROR); } } else { if (_nscd_debug == NSCD_DEBUG_NONE) _nscd_logit(me, "Cannot use specified " "logfile \"%s\": "\ "file is/has links or isn't " "owned by root\n", lf); return (NSCD_CFG_FILE_OPEN_ERROR); } } (void) close(_logfd); (void) strlcpy(_nscd_logfile, lf, PATH_MAX); _logfd = newlogfd; if (_nscd_debug == NSCD_DEBUG_NONE) _nscd_logit(me, "Start of new logfile %s\n", lf); } return (NSCD_SUCCESS); } /* log an entry to the configured nscd log file */ void _nscd_logit( char *funcname, char *format, ...) { static mutex_t loglock = DEFAULTMUTEX; struct timeval tv; char tid_buf[32]; char pid_buf[32]; char buffer[LOGBUFLEN]; int safechars, offset; va_list ap; if (_logfd < 0) return; if (_nscd_debug == NSCD_DEBUG_OPEN) { (void) mutex_lock(&loglock); if (_nscd_debug == NSCD_DEBUG_OPEN && *_nscd_logfile_d != '\0' && (strcmp(_nscd_logfile, "/dev/null") == 0 || strcmp(_nscd_logfile, "stderr") == 0)) { (void) strlcpy(_nscd_logfile_s, _nscd_logfile, PATH_MAX); (void) _nscd_set_lf(_nscd_logfile_d); } _nscd_debug = NSCD_DEBUG_NONE; (void) mutex_unlock(&loglock); } else if (_nscd_debug == NSCD_DEBUG_CLOSE) { (void) mutex_lock(&loglock); if (_nscd_debug == NSCD_DEBUG_CLOSE) (void) _nscd_set_lf(_nscd_logfile_s); _nscd_debug = NSCD_DEBUG_NONE; (void) mutex_unlock(&loglock); } va_start(ap, format); if (gettimeofday(&tv, NULL) != 0 || ctime_r(&tv.tv_sec, buffer, LOGBUFLEN) == NULL) { (void) snprintf(buffer, LOGBUFLEN, "