#include "dietfeatures.h" #include #include #include #include #include #include #include #include #include #include #include #include #define _PATH_CONSOLE "/dev/console" #define BUF_SIZE 512 /* messagebuffer size (>= 200) */ #define MAX_LOGTAG 80 /* those have to be global *sigh* */ static volatile int connected = 0; /* have done connect */ static volatile int LogMask = 0xff; /* mask of priorities to be logged */ static char LogTag[MAX_LOGTAG]; /* string to tag the entry with */ static int LogFile = -1; /* fd for log */ static int LogType = SOCK_DGRAM; /* type of socket connection */ static int LogFacility = LOG_USER; /* default facility code */ static int LogStat; /* status bits, set by openlog() */ extern char *__progname; /* Program name, from crt0. */ static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ static void closelog_intern(void) { if (!connected) return; close(LogFile); LogFile = -1; connected = 0; } void closelog(void) { closelog_intern(); LogTag[0]=0; LogType = SOCK_DGRAM; } static void openlog_intern(int option, int facility) { LogStat = option; if (facility && ((facility & ~LOG_FACMASK) == 0)) LogFacility = facility; /* yep, there is a continue inside ;) */ while(1) { if (LogFile == -1) { SyslogAddr.sa_family = AF_UNIX; strncpy(SyslogAddr.sa_data, _PATH_LOG, sizeof(SyslogAddr.sa_data)); if (LogStat & LOG_NDELAY) { if ((LogFile = socket(AF_UNIX, LogType, 0)) == -1) return; fcntl(LogFile, F_SETFD, 1); } } if ((LogFile != -1) && !connected) { #ifdef WANT_THREAD_SAFE int old_errno = (*(__errno_location())); #else int old_errno=errno; #endif if(connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) { #ifdef WANT_THREAD_SAFE int saved_errno = (*(__errno_location())); #else int saved_errno=errno; #endif close(LogFile); LogFile = -1; if((LogType == SOCK_DGRAM) && (saved_errno == EPROTOTYPE)) { /* retry with SOCK_STREAM instead of SOCK_DGRAM */ LogType = SOCK_STREAM; #ifdef WANT_THREAD_SAFE (*(__errno_location()))=old_errno; #else errno=old_errno; #endif continue; } } else connected = 1; } break; } } /* has to be secured against multiple, simultanious call's in threaded environment */ void openlog(const char *ident, int option, int facility) { if (ident) { strncpy(LogTag,ident,MAX_LOGTAG); LogTag[MAX_LOGTAG-1]=0; } openlog_intern(option, facility); } int setlogmask(int mask) { int old = LogMask; if (mask) LogMask = mask; return old; } void vsyslog(int priority, const char *format, va_list arg_ptr) { char buffer[BUF_SIZE]; char time_buf[20]; int buflen, headerlen; time_t now; struct tm now_tm; pid_t pid; int fd; int sigpipe; struct sigaction action, oldaction; struct sigaction *oldaction_ptr = NULL; #ifdef WANT_THREAD_SAFE int saved_errno = (*(__errno_location())); #else int saved_errno = errno; #endif /* check for invalid priority/facility bits */ if (priority & ~(LOG_PRIMASK|LOG_FACMASK)) { syslog(LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID, "syslog: unknown facility/priorityority: %x", priority); priority &= LOG_PRIMASK|LOG_FACMASK; } /* check priority against setlogmask */ if ((LOG_MASK(LOG_PRI(priority)) && LogMask) == 0) return; /* Set default facility if none specified. */ if ((priority & LOG_FACMASK) == 0) priority |= LogFacility; pid = getpid(); time(&now); strftime(time_buf, 20, "%h %e %T", localtime_r (&now, &now_tm)); if (LogStat & LOG_PID) headerlen = snprintf(buffer, 130, "<%d>%s %s[%d]: ", priority, time_buf, LogTag, pid); else headerlen = snprintf(buffer, 130, "<%d>%s %s: ", priority, time_buf, LogTag); if (!LogTag[0]) { if ((LogStat & LOG_PID) != LOG_PID) headerlen = snprintf(buffer, 130, "<%d>%s (unknown)[%d]: ", priority, time_buf, pid); strcat(buffer+headerlen, "syslog without openlog w/ ident, please check code!"); buflen = 41; } else { #ifdef WANT_THREAD_SAFE (*(__errno_location()))=saved_errno; #else errno=saved_errno; #endif buflen = vsnprintf(buffer+headerlen, BUF_SIZE - headerlen, format, arg_ptr); } if (LogStat & LOG_PERROR) { write(1, buffer+headerlen, buflen); if (buffer[headerlen+buflen] != '\n') write(1,"\n", 1); } /* prepare for broken connection */ memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigemptyset(&action.sa_mask); if ((sigpipe = sigaction (SIGPIPE, &action, &oldaction))==0) oldaction_ptr = &oldaction; if (!connected) openlog_intern(LogStat | LOG_NDELAY, 0); /* If we have a SOCK_STREAM connection, also send ASCII NUL as a * record terminator. */ if (LogType == SOCK_STREAM) buflen++; if (!connected || (send(LogFile, buffer, buflen+headerlen, 0) != buflen+headerlen)) { if (LogType == SOCK_STREAM) buflen--; closelog_intern(); /* * Output the message to the console; don't worry about blocking, * if console blocks everything will. Make sure the error reported * is the one from the syslogd failure. */ if ((LogStat & LOG_CONS) && ((fd = open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)) { write(fd, buffer, buflen+headerlen); write(fd, "\r\n", 2); } } if (sigpipe == 0) sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL); } void syslog(int priority, const char *format, ...) { va_list arg_ptr; va_start(arg_ptr, format); vsyslog(priority, format, arg_ptr); va_end(arg_ptr); }