syslog: allow multiple -R options

function                                             old     new   delta
syslogd_main                                        1082    1177     +95
init_data                                             72      64      -8

Signed-off-by: Thomas Geulig <geulig@nentec.de>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 8338d6b..3320369 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -57,6 +57,15 @@
 	char data[1];   /* data/messages */
 };
 
+#if ENABLE_FEATURE_REMOTE_LOG
+typedef struct {
+	int remoteFD;
+	unsigned last_dns_resolve;
+	len_and_sockaddr *remoteAddr;
+	const char *remoteHostname;
+} remoteHost_t;
+#endif
+
 /* Allows us to have smaller initializer. Ugly. */
 #define GLOBALS \
 	const char *logFilePath;                \
@@ -73,11 +82,6 @@
 	unsigned curFileSize;                   \
 	smallint isRegular;                     \
 ) \
-IF_FEATURE_REMOTE_LOG( \
-	/* udp socket for remote logging */     \
-	int remoteFD;                           \
-	len_and_sockaddr* remoteAddr;           \
-) \
 IF_FEATURE_IPC_SYSLOG( \
 	int shmid; /* ipc shared memory id */   \
 	int s_semid; /* ipc semaphore id */     \
@@ -94,10 +98,8 @@
 	GLOBALS
 
 #if ENABLE_FEATURE_REMOTE_LOG
-	unsigned last_dns_resolve;
-	char *remoteAddrStr;
+	llist_t *remoteHosts;
 #endif
-
 #if ENABLE_FEATURE_IPC_SYSLOG
 	struct shbuf_ds *shbuf;
 #endif
@@ -127,9 +129,6 @@
 	.logFileSize = 200 * 1024,
 	.logFileRotate = 1,
 #endif
-#if ENABLE_FEATURE_REMOTE_LOG
-	.remoteFD = -1,
-#endif
 #if ENABLE_FEATURE_IPC_SYSLOG
 	.shmid = -1,
 	.s_semid = -1,
@@ -185,7 +184,7 @@
 #define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \
 	IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
 	IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
-	IF_FEATURE_REMOTE_LOG(    ,&G.remoteAddrStr) \
+	IF_FEATURE_REMOTE_LOG(	  ,&remoteAddrList) \
 	IF_FEATURE_IPC_SYSLOG(    ,&opt_C)
 
 
@@ -534,20 +533,20 @@
 }
 
 #if ENABLE_FEATURE_REMOTE_LOG
-static int try_to_resolve_remote(void)
+static int try_to_resolve_remote(remoteHost_t *rh)
 {
-	if (!G.remoteAddr) {
+	if (!rh->remoteAddr) {
 		unsigned now = monotonic_sec();
 
 		/* Don't resolve name too often - DNS timeouts can be big */
-		if ((now - G.last_dns_resolve) < DNS_WAIT_SEC)
+		if ((now - rh->last_dns_resolve) < DNS_WAIT_SEC)
 			return -1;
-		G.last_dns_resolve = now;
-		G.remoteAddr = host2sockaddr(G.remoteAddrStr, 514);
-		if (!G.remoteAddr)
+		rh->last_dns_resolve = now;
+		rh->remoteAddr = host2sockaddr(rh->remoteHostname, 514);
+		if (!rh->remoteAddr)
 			return -1;
 	}
-	return socket(G.remoteAddr->u.sa.sa_family, SOCK_DGRAM, 0);
+	return socket(rh->remoteAddr->u.sa.sa_family, SOCK_DGRAM, 0);
 }
 #endif
 
@@ -555,6 +554,9 @@
 static void do_syslogd(void)
 {
 	int sock_fd;
+#if ENABLE_FEATURE_REMOTE_LOG
+	llist_t *item;
+#endif
 #if ENABLE_FEATURE_SYSLOGD_DUP
 	int last_sz = -1;
 	char *last_buf;
@@ -620,23 +622,25 @@
 		last_sz = sz;
 #endif
 #if ENABLE_FEATURE_REMOTE_LOG
+		/* Stock syslogd sends it '\n'-terminated
+		 * over network, mimic that */
+		recvbuf[sz] = '\n';
+
 		/* We are not modifying log messages in any way before send */
 		/* Remote site cannot trust _us_ anyway and need to do validation again */
-		if (G.remoteAddrStr) {
-			if (-1 == G.remoteFD) {
-				G.remoteFD = try_to_resolve_remote();
-				if (-1 == G.remoteFD)
-					goto no_luck;
+		for (item = G.remoteHosts; item != NULL; item = item->link) {
+			remoteHost_t *rh = (remoteHost_t *)item->data;
+
+			if (rh->remoteFD == -1) {
+				rh->remoteFD = try_to_resolve_remote(rh);
+				if (rh->remoteFD == -1)
+					continue;
 			}
-			/* Stock syslogd sends it '\n'-terminated
-			 * over network, mimic that */
-			recvbuf[sz] = '\n';
-			/* send message to remote logger, ignore possible error */
+			/* Send message to remote logger, ignore possible error */
 			/* TODO: on some errors, close and set G.remoteFD to -1
 			 * so that DNS resolution and connect is retried? */
-			sendto(G.remoteFD, recvbuf, sz+1, MSG_DONTWAIT,
-				    &G.remoteAddr->u.sa, G.remoteAddr->len);
- no_luck: ;
+			sendto(rh->remoteFD, recvbuf, sz+1, MSG_DONTWAIT,
+				&(rh->remoteAddr->u.sa), rh->remoteAddr->len);
 		}
 #endif
 		if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
@@ -656,17 +660,27 @@
 int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int syslogd_main(int argc UNUSED_PARAM, char **argv)
 {
-	char OPTION_DECL;
 	int opts;
-
-	INIT_G();
+	char OPTION_DECL;
 #if ENABLE_FEATURE_REMOTE_LOG
-	G.last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1;
+	llist_t *remoteAddrList = NULL;
 #endif
 
-	/* do normal option parsing */
-	opt_complementary = "=0"; /* no non-option params */
+	INIT_G();
+
+	/* No non-option params, -R can occur multiple times */
+	opt_complementary = "=0" IF_FEATURE_REMOTE_LOG(":R::");
 	opts = getopt32(argv, OPTION_STR, OPTION_PARAM);
+#if ENABLE_FEATURE_REMOTE_LOG
+	while (remoteAddrList) {
+		remoteHost_t *rh = xzalloc(sizeof(*rh));
+		rh->remoteHostname = llist_pop(&remoteAddrList);
+		rh->remoteFD = -1;
+		rh->last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1;
+		llist_add_to(&G.remoteHosts, rh);
+	}
+#endif
+
 #ifdef SYSLOGD_MARK
 	if (opts & OPT_mark) // -m
 		G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60;