Index: trunk/src/emx/src/libsyslog/syslog.c
===================================================================
--- trunk/src/emx/src/libsyslog/syslog.c	(revision 1199)
+++ trunk/src/emx/src/libsyslog/syslog.c	(revision 1200)
@@ -33,74 +33,83 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)syslog.c    8.8 (Berkeley) 8/30/95";
+static char sccsid[] = "@(#)syslog.c	8.5 (Berkeley) 4/29/95";
 #endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/syslog.c,v 1.29 2003/02/10 08:31:28 alfred Exp $");
+
+#include "namespace.h"
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/syslog.h>
 #include <sys/uio.h>
-#include <sys/syslog.h>
+#include <sys/un.h>
 #include <netdb.h>
 #ifdef __EMX__
-#include <netinet/in.h>
+# include <netinet/in.h>
 #endif
 
 #include <errno.h>
 #include <fcntl.h>
+#ifndef __EMX__
+# include <paths.h>
+#else
+# define _PATH_CONSOLE "/dev/con"
+#endif
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
-#if defined(BSD4_4) && !defined(__EMX__)
-# include <paths.h>
-#else
-# if defined(__EMX__)
-#  define _PATH_CONSOLE "con"
-# endif
-
-# ifndef _PATH_CONSOLE
-#  define _PATH_CONSOLE "/dev/console"
-# endif
-# ifndef _PATH_LOG
-#  define _PATH_LOG     "/dev/log"
-# endif
-#endif
-
-#if __STDC__
-# include <stdarg.h>
-#else
-# include <varargs.h>
-# define const  /* */
-#endif
-
-#ifndef USESNPRINTF
-# if defined(BSD4_4) || defined(__EMX__)
-#  define USESNPRINTF   1       /* has snprintf(3), vsnprintf(3), etc. */
-# else
-#  define USESNPRINTF   0       /* cheesy old C library */
-# endif
-#endif
-
-#ifndef LOG_PRI
-# define LOG_PRI(p)     ((p) & LOG_PRIMASK)
-#endif
-
-#ifndef LOG_PERROR
-# define LOG_PERROR     0
-#endif
-
-#define BUFSLOP         1024    /* overflow space */
+#include <stdarg.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
 
 static int      LogFile = -1;           /* fd for log */
 static int      connected;              /* have done connect */
+static int	opened;			/* have done openlog() */
 static int      LogStat = 0;            /* status bits, set by openlog() */
 static const char *LogTag = NULL;       /* string to tag the entry with */
 static int      LogFacility = LOG_USER; /* default facility code */
 static int      LogMask = 0xff;         /* mask of priorities to be logged */
-#if defined(BSD4_4) && !defined(__EMX__)
-extern char     *__progname;            /* Program name, from crt0. */
-#else
-char            *__progname = NULL;
+
+static void	disconnectlog(void); /* disconnect from syslogd */
+static void	connectlog(void);	/* (re)connect to syslogd */
+
+#ifndef __EMX__
+/*
+ * Format of the magic cookie passed through the stdio hook
+ */
+struct bufcookie {
+	char	*base;	/* start of buffer */
+	int	left;
+};
+
+/*
+ * stdio write hook for writing to a static string buffer
+ * XXX: Maybe one day, dynamically allocate it so that the line length
+ *      is `unlimited'.
+ */
+static
+int writehook(cookie, buf, len)
+	void	*cookie;	/* really [struct bufcookie *] */
+	char	*buf;		/* characters to copy */
+	int	len;		/* length to copy */
+{
+	struct bufcookie *h;	/* private `handle' */
+
+	h = (struct bufcookie *)cookie;
+	if (len > h->left) {
+		/* clip in case of wraparound */
+		len = h->left;
+	}
+	if (len > 0) {
+		(void)memcpy(h->base, buf, len); /* `write' it. */
+		h->base += len;
+		h->left -= len;
+	}
+	return 0;
+}
 #endif
 
@@ -110,39 +119,29 @@
  */
 void
-#if __STDC__
 syslog(int pri, const char *fmt, ...)
-#else
-syslog(pri, fmt, va_alist)
-        int pri;
-        char *fmt;
-        va_dcl
-#endif
 {
         va_list ap;
-        extern void vsyslog();
-
-#if __STDC__
-        va_start(ap, fmt);
-#else
-        va_start(ap);
-#endif
-        vsyslog(pri, fmt, ap);
-        va_end(ap);
+
+	va_start(ap, fmt);
+	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;
+	int pri;
+	const char *fmt;
+	va_list ap;
+{
+        int cnt;
+        char ch, *p;
         time_t now;
         int fd, saved_errno;
-        int panic = 0;
-        static int maxsend = BUFSIZ;
-        char *stdp, fmt_cpy[1024], tbuf[BUFSIZ + BUFSLOP];
-        extern void openlog();
+	char *stdp, tbuf[2048], fmt_cpy[1024], timbuf[26];
+#ifndef __EMX__
+	FILE *fp, *fmt_fp;
+	struct bufcookie tbuf_cookie;
+	struct bufcookie fmt_cookie;
+#endif
 
 #define INTERNALLOG     LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
@@ -164,54 +163,122 @@
                 pri |= LogFacility;
 
-        /* Get connected. */
-        if (!connected)
-                openlog(LogTag, LogStat | LOG_NDELAY, 0);
+#ifndef __EMX__
+	/* Create the primary stdio hook */
+	tbuf_cookie.base = tbuf;
+	tbuf_cookie.left = sizeof(tbuf);
+	fp = fwopen(&tbuf_cookie, writehook);
+	if (fp == NULL)
+		return;
+#endif
 
         /* Build the message. */
         (void)time(&now);
-        sprintf(tbuf, "<%d>", pri);
-        p = tbuf + strlen(tbuf);
-        strftime(p, sizeof (tbuf) - (p - tbuf), "%h %d %T ", localtime(&now));
-        p += strlen(p);
-        stdp = p;
+#ifndef __EMX__
+	(void)fprintf(fp, "<%d>", pri);
+	(void)fprintf(fp, "%.15s ", ctime_r(&now, timbuf) + 4);
+#else
+        p = tbuf + sprintf(tbuf, "<%d>", pri);
+        p += sprintf(p, "%.15s ", ctime_r(&now, timbuf) + 4);
+#endif
+	if (LogStat & LOG_PERROR) {
+#ifndef __EMX__
+		/* Transfer to string buffer */
+		(void)fflush(fp);
+		stdp = tbuf + (sizeof(tbuf) - tbuf_cookie.left);
+#else
+                stdp = p;
+#endif
+	}
         if (LogTag == NULL)
-                LogTag = __progname;
+                LogTag = _getprogname();
+        if (LogTag != NULL)
+#ifndef __EMX__
+            (void)fprintf(fp, "%s", LogTag);
+#else
+            p += sprintf(p, "%s", LogTag);
+#endif
+        if (LogStat & LOG_PID)
+#ifndef __EMX__
+            (void)fprintf(fp, "[%d]", getpid());
+#else
+            p += sprintf(p, "[%d]", getpid());
+#endif
         if (LogTag != NULL) {
-                sprintf(p, "%s", LogTag);
-                p += strlen(p);
-        }
-        if (LogStat & LOG_PID) {
-                sprintf(p, "[%d]", getpid());
-                p += strlen(p);
-        }
-        if (LogTag != NULL) {
+#ifndef __EMX__
+            (void)fprintf(fp, ": ");
+#else
                 *p++ = ':';
                 *p++ = ' ';
+#endif
         }
 
-        /* Substitute error message for %m. */
-        for (t = fmt_cpy; ch = *fmt; ++fmt)
-                if (ch == '%' && fmt[1] == 'm') {
-                        ++fmt;
-                        sprintf(t, "%s", strerror(saved_errno));
-                        t += strlen(t);
-                } else
-                        *t++ = ch;
-        *t = '\0';
-
-#if USESNPRINTF
-        cnt = maxsend - (p - tbuf) + 1;
-        p += vsnprintf(p, cnt, fmt_cpy, ap);
+	/* Check to see if we can skip expanding the %m */
+	if (strstr(fmt, "%m")) {
+#ifndef __EMX__
+		/* Create the second stdio hook */
+		fmt_cookie.base = fmt_cpy;
+		fmt_cookie.left = sizeof(fmt_cpy) - 1;
+		fmt_fp = fwopen(&fmt_cookie, writehook);
+		if (fmt_fp == NULL) {
+			fclose(fp);
+			return;
+		}
+#else
+            char *t = fmt_cpy;
+#endif
+
+            /*
+             * Substitute error message for %m.  Be careful not to
+             * molest an escaped percent "%%m".  We want to pass it
+             * on untouched as the format is later parsed by vfprintf.
+             */
+            for ( ; (ch = *fmt); ++fmt) {
+                    if (ch == '%' && fmt[1] == 'm') {
+                            ++fmt;
+#ifndef __EMX__
+                            fputs(strerror(saved_errno), fmt_fp);
+#else
+                            t += sprintf(t, "%s", strerror(saved_errno));
+#endif
+                    } else if (ch == '%' && fmt[1] == '%') {
+                            ++fmt;
+#ifndef __EMX__
+                            fputc(ch, fmt_fp);
+                            fputc(ch, fmt_fp);
+#else
+                            *t++ = ch;
+                            *t++ = ch;
+#endif
+                    } else {
+#ifndef __EMX__
+                        fputc(ch, fmt_fp);
+#else
+                            *t++ = ch;
+#endif
+                    }
+            }
+
+            /* Null terminate if room */
+#ifndef __EMX__
+            /* Null terminate if room */
+            fputc(0, fmt_fp);
+            fclose(fmt_fp);
+#else
+            *t = '\0';
+#endif
+            /* Guarantee null termination */
+            fmt_cpy[sizeof(fmt_cpy) - 1] = '\0';
+
+            fmt = fmt_cpy;
+        }
+
+#ifndef __EMX__
+	(void)vfprintf(fp, fmt, ap);
+	(void)fclose(fp);
+
+	cnt = sizeof(tbuf) - tbuf_cookie.left;
+#else
         cnt = p - tbuf;
-#else
-        vsprintf(p, fmt_cpy, ap);
-        p += strlen(p);
-        cnt = p - tbuf;
-        if (cnt > sizeof tbuf) {
-                /* Panic condition. */
-                panic = 1;
-        }
-        if (cnt > maxsend)
-                cnt = maxsend;
+        cnt += vsnprintf(p, sizeof(tbuf) - cnt - 1, fmt, ap);
 #endif
 
@@ -219,5 +286,5 @@
         if (LogStat & LOG_PERROR) {
                 struct iovec iov[2];
-                register struct iovec *v = iov;
+		struct iovec *v = iov;
 
                 v->iov_base = stdp;
@@ -226,53 +293,119 @@
                 v->iov_base = "\n";
                 v->iov_len = 1;
-                (void)writev(STDERR_FILENO, iov, 2);
+		(void)_writev(STDERR_FILENO, iov, 2);
         }
 
-        /* Output the message to the local logger. */
-        for (;;) {
-                if (send(LogFile, tbuf, cnt, 0) >= 0)
-                        goto done;
-                if (errno != EMSGSIZE || maxsend <= 256)
-                        break;
-
-                /* Message was too large -- back it off. */
-                do {
-                        maxsend -= 128;
-                } while (cnt < maxsend && maxsend > 256);
-                cnt = maxsend;
-        }
+	/* Get connected, output the message to the local logger. */
+	if (!opened)
+		openlog(LogTag, LogStat | LOG_NDELAY, 0);
+	connectlog();
+	if (send(LogFile, tbuf, cnt, 0) >= 0)
+		return;
+
+	/*
+	 * If the send() failed, the odds are syslogd was restarted.
+	 * Make one (only) attempt to reconnect to /dev/log.
+	 */
+	disconnectlog();
+	connectlog();
+	if (send(LogFile, tbuf, cnt, 0) >= 0)
+		return;
 
         /*
-         * 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.
+	 * Output the message to the console; try not to block
+	 * as a blocking console should not stop other processes.
+	 * Make sure the error reported is the one from the syslogd failure.
          */
         if (LogStat & LOG_CONS &&
-            (fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
-                (void)strcat(tbuf, "\r\n");
-                cnt += 2;
+#ifndef __EMX__
+	    (fd = _open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) {
+#else
+	    (fd = _open(_PATH_CONSOLE, O_WRONLY/*|O_NONBLOCK*/, 0)) >= 0) {
+#endif
+
+		struct iovec iov[2];
+		struct iovec *v = iov;
+
                 p = strchr(tbuf, '>') + 1;
-                (void)write(fd, p, cnt - (p - tbuf));
-                (void)close(fd);
+		v->iov_base = p;
+		v->iov_len = cnt - (p - tbuf);
+		++v;
+		v->iov_base = "\r\n";
+		v->iov_len = 2;
+		(void)_writev(fd, iov, 2);
+		(void)_close(fd);
         }
-
-  done:
-#if !USESNPRINTF
-        /*
-         * If we had a buffer overrun, log a panic and abort.
-         * We can't return because our stack is probably toast.
-         */
-        if (panic) {
-                syslog(LOG_EMERG, "SYSLOG BUFFER OVERRUN -- EXITING");
-                abort();
-        }
-#endif
-}
-
-#ifdef __EMX__
-static struct sockaddr_in SyslogAddr;   /* AF_INET address of local logger */
-#else
-static struct sockaddr SyslogAddr;      /* AF_UNIX address of local logger */
-#endif
+}
+static void
+disconnectlog()
+{
+	/*
+	 * If the user closed the FD and opened another in the same slot,
+	 * that's their problem.  They should close it before calling on
+	 * system services.
+	 */
+	if (LogFile != -1) {
+		_close(LogFile);
+		LogFile = -1;
+	}
+	connected = 0;			/* retry connect */
+}
+
+static void
+connectlog()
+{
+#ifndef __EMX__
+	struct sockaddr_un SyslogAddr;	/* AF_UNIX address of local logger */
+#else
+	struct sockaddr_in SyslogAddr;	/* AF_INET address of local logger */
+#endif
+
+	if (LogFile == -1) {
+#ifndef __EMX__
+		if ((LogFile = _socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
+#else
+		if ((LogFile = _socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+#endif
+			return;
+		(void)_fcntl(LogFile, F_SETFD, 1);
+	}
+	if (LogFile != -1 && !connected) {
+#ifndef __EMX__
+		SyslogAddr.sun_len = sizeof(SyslogAddr);
+		SyslogAddr.sun_family = AF_UNIX;
+		(void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
+		    sizeof SyslogAddr.sun_path);
+#else
+                memset(&SyslogAddr, 0, sizeof(SyslogAddr));
+#ifndef TCPV40HDRS
+                SyslogAddr.sin_len = sizeof(SyslogAddr);
+#endif
+                SyslogAddr.sin_family = AF_INET;
+                SyslogAddr.sin_port = htons(514);
+                SyslogAddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+		connected = _connect(LogFile, (struct sockaddr *)&SyslogAddr,
+			sizeof(SyslogAddr)) != -1;
+
+#ifndef __EMX__
+		if (!connected) {
+			/*
+			 * Try the old "/dev/log" path, for backward
+			 * compatibility.
+			 */
+			(void)strncpy(SyslogAddr.sun_path, _PATH_OLDLOG,
+			    sizeof SyslogAddr.sun_path);
+			connected = _connect(LogFile,
+				(struct sockaddr *)&SyslogAddr,
+				sizeof(SyslogAddr)) != -1;
+		}
+#endif
+
+		if (!connected) {
+			(void)_close(LogFile);
+			LogFile = -1;
+		}
+	}
+}
 
 void
@@ -281,40 +414,14 @@
         int logstat, logfac;
 {
-        if (ident != NULL)
-                LogTag = ident;
-        LogStat = logstat;
-        if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
-                LogFacility = logfac;
-
-        if (LogFile == -1) {
-#ifdef __EMX__
-                memset(&SyslogAddr, 0, sizeof(SyslogAddr));
-                SyslogAddr.sin_len = sizeof(SyslogAddr);
-                SyslogAddr.sin_family = AF_INET;
-                SyslogAddr.sin_port = htons(514);
-                SyslogAddr.sin_addr.s_addr = INADDR_ANY;
-#else
-                SyslogAddr.sa_family = AF_UNIX;
-                (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
-                    sizeof(SyslogAddr.sa_data));
-#endif
-                if (LogStat & LOG_NDELAY) {
-#ifdef __EMX__
-                        if ((LogFile = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
-#else
-                        if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
-#endif
-                                return;
-#ifndef __EMX__
-                        (void)fcntl(LogFile, F_SETFD, 1);
-#endif
-                }
-        }
-        if (LogFile != -1 && !connected)
-                if (connect(LogFile, (struct sockaddr*) &SyslogAddr, sizeof(SyslogAddr)) == -1) {
-                        (void)close(LogFile);
-                        LogFile = -1;
-                } else
-                        connected = 1;
+    if (ident != NULL)
+            LogTag = ident;
+    LogStat = logstat;
+    if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+            LogFacility = logfac;
+
+    if (LogStat & LOG_NDELAY)	/* open immediately */
+            connectlog();
+
+    opened = 1;	/* ident and facility has been set */
 }
 
@@ -322,6 +429,7 @@
 closelog()
 {
-        (void)close(LogFile);
+	(void)_close(LogFile);
         LogFile = -1;
+        LogTag = NULL;
         connected = 0;
 }
@@ -339,3 +447,2 @@
         return (omask);
 }
-
