#include <sys/types.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <crt_externs.h>
#ifdef BUILDING_VARIANT
__private_extern__ int _sl_LogFile;
__private_extern__ int _sl_connected;
__private_extern__ int _sl_LogStat;
__private_extern__ const char *_sl_LogTag;
__private_extern__ int _sl_LogFacility;
__private_extern__ int _sl_LogMask;
#else
__private_extern__ int _sl_LogFile = -1;
__private_extern__ int _sl_connected = 0;
__private_extern__ int _sl_LogStat = 0;
__private_extern__ const char *_sl_LogTag = NULL;
__private_extern__ int _sl_LogFacility = LOG_USER;
__private_extern__ int _sl_LogMask = 0xff;
#endif
void
#ifdef __STDC__
syslog(int pri, const char *fmt, ...)
#else
syslog(pri, fmt, va_alist)
int pri;
char *fmt;
va_dcl
#endif
{
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vsyslog(pri, fmt, ap);
va_end(ap);
}
void
vsyslog(pri, fmt, ap)
int pri;
register const char *fmt;
va_list ap;
{
register int cnt;
register char ch, *p, *t;
time_t now;
int fd, saved_errno;
#define TBUF_LEN 2048
#define FMT_LEN 1024
char *stdp, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
int tbuf_left, fmt_left, prlen;
#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
syslog(INTERNALLOG,
"syslog: unknown facility/priority: %x", pri);
pri &= LOG_PRIMASK|LOG_FACMASK;
}
if (!(LOG_MASK(LOG_PRI(pri)) & _sl_LogMask))
return;
saved_errno = errno;
if ((pri & LOG_FACMASK) == 0)
pri |= _sl_LogFacility;
(void)time(&now);
p = tbuf;
tbuf_left = TBUF_LEN;
#define DEC() \
do { \
if (prlen >= tbuf_left) \
prlen = tbuf_left - 1; \
p += prlen; \
tbuf_left -= prlen; \
} while (0)
prlen = snprintf(p, tbuf_left, "<%d>", pri);
DEC();
prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
DEC();
if (_sl_LogStat & LOG_PERROR)
stdp = p;
if (_sl_LogTag == NULL)
_sl_LogTag = *(*_NSGetArgv());
if (_sl_LogTag != NULL) {
prlen = snprintf(p, tbuf_left, "%s", _sl_LogTag);
DEC();
}
if (_sl_LogStat & LOG_PID) {
prlen = snprintf(p, tbuf_left, "[%d]", getpid());
DEC();
}
if (_sl_LogTag != NULL) {
if (tbuf_left > 1) {
*p++ = ':';
tbuf_left--;
}
if (tbuf_left > 1) {
*p++ = ' ';
tbuf_left--;
}
}
for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
if (ch == '%' && fmt[1] == 'm') {
++fmt;
prlen = snprintf(t, fmt_left, "%s",
strerror(saved_errno));
if (prlen >= fmt_left)
prlen = fmt_left - 1;
t += prlen;
fmt_left -= prlen;
} else {
if (fmt_left > 1) {
*t++ = ch;
fmt_left--;
}
}
}
*t = '\0';
prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap);
DEC();
cnt = p - tbuf;
if (_sl_LogStat & LOG_PERROR) {
struct iovec iov[2];
iov[0].iov_base = stdp;
iov[0].iov_len = cnt - (stdp - tbuf);
iov[1].iov_base = "\n";
iov[1].iov_len = 1;
(void)writev(STDERR_FILENO, iov, 2);
}
if (!_sl_connected)
openlog(_sl_LogTag, _sl_LogStat | LOG_NDELAY, 0);
if (send(_sl_LogFile, tbuf, cnt, 0) >= 0)
return;
if (_sl_LogStat & LOG_CONS &&
(fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
struct iovec iov[2];
p = strchr(tbuf, '>') + 1;
iov[0].iov_base = p;
iov[0].iov_len = cnt - (p - tbuf);
iov[1].iov_base = "\r\n";
iov[1].iov_len = 2;
(void)writev(fd, iov, 2);
(void)close(fd);
}
}
#ifndef BUILDING_VARIANT
static struct sockaddr_un SyslogAddr;
void
openlog(ident, logstat, logfac)
const char *ident;
int logstat, logfac;
{
if (ident != NULL)
_sl_LogTag = ident;
_sl_LogStat = logstat;
if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
_sl_LogFacility = logfac;
if (_sl_LogFile == -1) {
SyslogAddr.sun_family = AF_UNIX;
(void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
sizeof(SyslogAddr.sun_path));
if (_sl_LogStat & LOG_NDELAY) {
if ((_sl_LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
return;
(void)fcntl(_sl_LogFile, F_SETFD, 1);
}
}
if (_sl_LogFile != -1 && !_sl_connected)
if (connect(_sl_LogFile, (struct sockaddr *)&SyslogAddr, sizeof(SyslogAddr)) == -1) {
(void)close(_sl_LogFile);
_sl_LogFile = -1;
} else
_sl_connected = 1;
}
void
closelog()
{
(void)close(_sl_LogFile);
_sl_LogFile = -1;
_sl_connected = 0;
}
int
setlogmask(pmask)
int pmask;
{
int omask;
omask = _sl_LogMask;
if (pmask != 0)
_sl_LogMask = pmask;
return (omask);
}
#endif