From e3ed156eeb241234f0ad7d12363172e655209654 Mon Sep 17 00:00:00 2001
From: Erik Andersen <andersen@codepoet.org>
Date: Wed, 19 Apr 2000 18:52:56 +0000
Subject: Make the sys logger for so that concurrent logging will work properly
 (see tests/syslog_test.c for example).  -Erik

---
 sysklogd/syslogd.c  | 104 ++++++++++++++++++++++++++++++++--------------------
 syslogd.c           | 104 ++++++++++++++++++++++++++++++++--------------------
 tests/.cvsignore    |   1 +
 tests/Makefile      |   2 +
 tests/syslog_test.c |  19 ++++++++++
 5 files changed, 150 insertions(+), 80 deletions(-)
 create mode 100644 tests/syslog_test.c

diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 4cfb458ed..004e6ab1d 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -80,14 +80,23 @@ static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
 static void message (char *fmt, ...)
 {
 	int fd;
+	struct flock fl;
 	va_list arguments;
 
+	fl.l_whence = SEEK_SET;
+	fl.l_start  = 0;
+	fl.l_len    = 1;
+
 	if ((fd = device_open (logFilePath,
 						   O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
 						   O_NONBLOCK)) >= 0) {
+		fl.l_type = F_WRLCK;
+		fcntl (fd, F_SETLKW, &fl);
 		va_start (arguments, fmt);
 		vdprintf (fd, fmt, arguments);
 		va_end (arguments);
+		fl.l_type = F_UNLCK;
+		fcntl (fd, F_SETLKW, &fl);
 		close (fd);
 	} else {
 		/* Always send console messages to /dev/console so people will see them. */
@@ -173,6 +182,7 @@ static void doSyslogd (void)
 	signal (SIGTERM, quit_signal);
 	signal (SIGQUIT, quit_signal);
 	signal (SIGHUP,  SIG_IGN);
+	signal (SIGCLD,  SIG_IGN);
 	signal (SIGALRM, domark);
 	alarm (MarkInterval);
 
@@ -216,54 +226,68 @@ static void doSyslogd (void)
 
 		for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
 			if (FD_ISSET (fd, &readfds)) {
+
 				--n_ready;
+
 				if (fd == sock_fd) {
-					int conn;
+
+					int   conn;
+					pid_t pid;
+
 					if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
 						fatalError ("accept error: %s\n", strerror (errno));
 					}
-					FD_SET (conn, &fds);
-					continue;
-				}
-				else {
-#					define BUFSIZE 1023
-					char buf[ BUFSIZE + 1 ];
-					int n_read;
 
-					while ((n_read = read (fd, buf, BUFSIZE )) > 0) {
+					pid = fork();
 
-						int pri = (LOG_USER | LOG_NOTICE);
-						char line[ BUFSIZE + 1 ];
-						unsigned char c;
-						char *p = buf, *q = line;
+					if (pid < 0) {
+						perror ("syslogd: fork");
+						close (conn);
+						continue;
+					}
 
-						buf[ n_read - 1 ] = '\0';
+					if (pid > 0) {
 
-						while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
-							if (c == '<') {
+#						define BUFSIZE 1023
+						char   buf[ BUFSIZE + 1 ];
+						int    n_read;
+
+						while ((n_read = read (conn, buf, BUFSIZE )) > 0) {
+
+							int           pri = (LOG_USER | LOG_NOTICE);
+							char          line[ BUFSIZE + 1 ];
+							unsigned char c;
+
+							char *p = buf, *q = line;
+
+							buf[ n_read - 1 ] = '\0';
+
+							while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
+								if (c == '<') {
 								/* Parse the magic priority number. */
-								pri = 0;
-								while (isdigit (*(++p))) {
-									pri = 10 * pri + (*p - '0');
+									pri = 0;
+									while (isdigit (*(++p))) {
+										pri = 10 * pri + (*p - '0');
+									}
+									if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
+										pri = (LOG_USER | LOG_NOTICE);
+								} else if (c == '\n') {
+									*q++ = ' ';
+								} else if (iscntrl (c) && (c < 0177)) {
+									*q++ = '^';
+									*q++ = c ^ 0100;
+								} else {
+									*q++ = c;
 								}
-								if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
-									pri = (LOG_USER | LOG_NOTICE);
-							} else if (c == '\n') {
-								*q++ = ' ';
-							} else if (iscntrl (c) && (c < 0177)) {
-								*q++ = '^';
-								*q++ = c ^ 0100;
-							} else {
-								*q++ = c;
+								p++;
 							}
-							p++;
+							*q = '\0';
+							/* Now log it */
+							logMessage (pri, line);
 						}
-						*q = '\0';
-						/* Now log it */
-						logMessage (pri, line);
+						exit (0);
 					}
-					close (fd);
-					FD_CLR (fd, &fds);
+					close (conn);
 				}
 			}
 		}
@@ -432,9 +456,9 @@ extern int syslogd_main(int argc, char **argv)
 }
 
 /*
- * Local Variables
- * c-file-style: "linux"
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+Local Variables
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/syslogd.c b/syslogd.c
index 4cfb458ed..004e6ab1d 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -80,14 +80,23 @@ static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
 static void message (char *fmt, ...)
 {
 	int fd;
+	struct flock fl;
 	va_list arguments;
 
+	fl.l_whence = SEEK_SET;
+	fl.l_start  = 0;
+	fl.l_len    = 1;
+
 	if ((fd = device_open (logFilePath,
 						   O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
 						   O_NONBLOCK)) >= 0) {
+		fl.l_type = F_WRLCK;
+		fcntl (fd, F_SETLKW, &fl);
 		va_start (arguments, fmt);
 		vdprintf (fd, fmt, arguments);
 		va_end (arguments);
+		fl.l_type = F_UNLCK;
+		fcntl (fd, F_SETLKW, &fl);
 		close (fd);
 	} else {
 		/* Always send console messages to /dev/console so people will see them. */
@@ -173,6 +182,7 @@ static void doSyslogd (void)
 	signal (SIGTERM, quit_signal);
 	signal (SIGQUIT, quit_signal);
 	signal (SIGHUP,  SIG_IGN);
+	signal (SIGCLD,  SIG_IGN);
 	signal (SIGALRM, domark);
 	alarm (MarkInterval);
 
@@ -216,54 +226,68 @@ static void doSyslogd (void)
 
 		for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
 			if (FD_ISSET (fd, &readfds)) {
+
 				--n_ready;
+
 				if (fd == sock_fd) {
-					int conn;
+
+					int   conn;
+					pid_t pid;
+
 					if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
 						fatalError ("accept error: %s\n", strerror (errno));
 					}
-					FD_SET (conn, &fds);
-					continue;
-				}
-				else {
-#					define BUFSIZE 1023
-					char buf[ BUFSIZE + 1 ];
-					int n_read;
 
-					while ((n_read = read (fd, buf, BUFSIZE )) > 0) {
+					pid = fork();
 
-						int pri = (LOG_USER | LOG_NOTICE);
-						char line[ BUFSIZE + 1 ];
-						unsigned char c;
-						char *p = buf, *q = line;
+					if (pid < 0) {
+						perror ("syslogd: fork");
+						close (conn);
+						continue;
+					}
 
-						buf[ n_read - 1 ] = '\0';
+					if (pid > 0) {
 
-						while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
-							if (c == '<') {
+#						define BUFSIZE 1023
+						char   buf[ BUFSIZE + 1 ];
+						int    n_read;
+
+						while ((n_read = read (conn, buf, BUFSIZE )) > 0) {
+
+							int           pri = (LOG_USER | LOG_NOTICE);
+							char          line[ BUFSIZE + 1 ];
+							unsigned char c;
+
+							char *p = buf, *q = line;
+
+							buf[ n_read - 1 ] = '\0';
+
+							while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
+								if (c == '<') {
 								/* Parse the magic priority number. */
-								pri = 0;
-								while (isdigit (*(++p))) {
-									pri = 10 * pri + (*p - '0');
+									pri = 0;
+									while (isdigit (*(++p))) {
+										pri = 10 * pri + (*p - '0');
+									}
+									if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
+										pri = (LOG_USER | LOG_NOTICE);
+								} else if (c == '\n') {
+									*q++ = ' ';
+								} else if (iscntrl (c) && (c < 0177)) {
+									*q++ = '^';
+									*q++ = c ^ 0100;
+								} else {
+									*q++ = c;
 								}
-								if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
-									pri = (LOG_USER | LOG_NOTICE);
-							} else if (c == '\n') {
-								*q++ = ' ';
-							} else if (iscntrl (c) && (c < 0177)) {
-								*q++ = '^';
-								*q++ = c ^ 0100;
-							} else {
-								*q++ = c;
+								p++;
 							}
-							p++;
+							*q = '\0';
+							/* Now log it */
+							logMessage (pri, line);
 						}
-						*q = '\0';
-						/* Now log it */
-						logMessage (pri, line);
+						exit (0);
 					}
-					close (fd);
-					FD_CLR (fd, &fds);
+					close (conn);
 				}
 			}
 		}
@@ -432,9 +456,9 @@ extern int syslogd_main(int argc, char **argv)
 }
 
 /*
- * Local Variables
- * c-file-style: "linux"
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+Local Variables
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/tests/.cvsignore b/tests/.cvsignore
index 5f8452313..3645cf92f 100644
--- a/tests/.cvsignore
+++ b/tests/.cvsignore
@@ -13,3 +13,4 @@ mv
 mv_*.bb
 mv_*.gnu
 mv_tests
+syslog_test
diff --git a/tests/Makefile b/tests/Makefile
index c4fb0e911..508bc64f2 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -29,3 +29,5 @@ BBL := $(shell pushd .. >/dev/null &&		\
 ${BBL}: ../busybox
 	rm -f $@
 	ln ../busybox $@
+
+syslog_test: syslog_test.c
diff --git a/tests/syslog_test.c b/tests/syslog_test.c
new file mode 100644
index 000000000..fb4c691b1
--- /dev/null
+++ b/tests/syslog_test.c
@@ -0,0 +1,19 @@
+#include <syslog.h>
+
+int do_log(char* msg, int delay)
+{
+  openlog("testlog", LOG_PID, LOG_DAEMON);
+  while(1) {
+    syslog(LOG_ERR, "%s: testing one, two, three\n", msg);
+    sleep(delay);
+  }
+  closelog();
+  return(0);
+};
+
+int main(void)
+{
+  if (fork()==0)
+    do_log("A", 2);
+  do_log("B", 3);
+}
-- 
cgit v1.2.3-55-g6feb