--- netkit-rwho-0.17/rwhod/rwhod.c	2000-07-23 05:19:48.000000000 +0200
+++ netkit-rwho-0.17-new/rwhod/rwhod.c	2004-10-25 16:57:35.002325112 +0200
@@ -47,6 +47,7 @@
 #include <signal.h>
 #include <sys/ioctl.h>
 #include <sys/file.h>
+#include <dirent.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -96,6 +97,7 @@
 static int	configure(int s);
 static int	verify(const char *name);
 static int	getloadavg(double ptr[3], int n);
+static void     sendspool(char *myname);
 
 /*
  * We communicate with each neighbor in
@@ -114,6 +116,7 @@
 static struct neighbor *neighbors;
 static struct servent *sp;
 static int sk;
+static int route = 0;
 static int use_pointopoint = 0;
 static int use_broadcast = 0;
 static int need_init = 1;
@@ -123,6 +126,7 @@
 			- ((caddr_t) 0))
 
 static void huphandler(int);
+static time_t getsendtime(char *);
 static void termhandler(int);
 static void sendpacket(struct whod *);
 static void getboottime(struct whod *);
@@ -137,14 +141,18 @@
 	char *user = NULL;
 	int on = 1;
 	int opt;
+	size_t len;
 
 	if (getuid()) {
 		fprintf(stderr, "rwhod: not super user\n");
 		exit(1);
 	}
 
-	while ((opt = getopt(argc, argv, "bpau:")) != EOF) {
+	while ((opt = getopt(argc, argv, "rbpau:")) != EOF) {
 	    switch (opt) {
+	      case 'r':
+		  route = 1;
+		  break;
 	      case 'b':
 		  use_broadcast = 1;
 		  break;
@@ -201,6 +209,7 @@
 	}
 	sine.sin_family = AF_INET;
 	sine.sin_port = sp->s_port;
+	len = sizeof(sine);
 	if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) {
 		syslog(LOG_ERR, "bind: %m");
 		exit(1);
@@ -247,7 +256,7 @@
 	for (;;) {
 		struct whod wd;
 		int cc, whod;
-		size_t len = sizeof(from);
+		len = sizeof(from);
 
 		memset(&wd, 0, sizeof(wd));
 		cc = recvfrom(sk, (char *)&wd, sizeof(struct whod), 0,
@@ -276,6 +285,8 @@
 				from.sin_addr);
 			continue;
 		}
+		if((time_t)ntohl(wd.wd_sendtime) == getsendtime(wd.wd_hostname))
+			continue;
 		snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname);
 		/*
 		 * Rather than truncating and growing the file each time,
@@ -325,6 +336,28 @@
 	exit(0);
 }
 
+static time_t getsendtime(char *hostname)
+{
+	int f, ret;
+	struct whod wd;
+	char path[64];
+    
+	snprintf(path, sizeof(path), "whod.%s", hostname);
+	if((f = open(path, O_RDONLY)) < 0) {
+		if(errno != ENOENT)
+			fprintf(stderr, "rwhod: %s: %s\n", path, strerror(errno));
+		return(0);
+	}
+	if((ret = read(f, &wd, sizeof(wd))) < 0) {
+		fprintf(stderr, "rwhod: %s: %s\n", path, strerror(errno));
+		return(0);
+	}
+	close(f);
+	if(ret < WHDRSIZE)
+		return(0);
+	return(wd.wd_sendtime);
+}
+
 /*
  * Obtain boot time again
  */
@@ -366,6 +399,8 @@
 	getboottime(&mywd);
 
 	while (1) {
+		if(route)
+			sendspool(mywd.wd_hostname);
 		sendpacket(&mywd);
 		(void) sleep(AL_INTERVAL);
 	}
@@ -390,6 +425,56 @@
 	return size > 0;
 }
 
+static int down(time_t rcv, time_t now) {
+	return (now - rcv > 11 * 60);
+}
+
+static void sendspool(char *myname)
+{
+	DIR *dirp;
+	struct dirent *dp;
+	int i, f, ret;
+	struct whod wd;
+	struct whoent *we;
+	struct neighbor *np;
+    
+	if((dirp = opendir(".")) == NULL) {
+		fprintf(stderr, "rwhod: opening spool dir: %s\n", strerror(errno));
+		exit(1);
+	}
+	while((dp = readdir(dirp)) != NULL) {
+		if(strncmp(dp->d_name, "whod.", 5))
+			continue;
+		if(!strcmp(dp->d_name + 5, myname))
+			continue;
+		if((f = open(dp->d_name, O_RDONLY)) < 0) {
+			fprintf(stderr, "rwhod: %s: %s\n", dp->d_name, strerror(errno));
+			continue;
+		}
+		if((ret = read(f, &wd, sizeof(wd))) < 0) {
+			fprintf(stderr, "rwhod: %s: %s\n", dp->d_name, strerror(errno));
+			continue;
+		}
+		close(f);
+		if(ret < WHDRSIZE)
+			continue;
+		if(down(wd.wd_recvtime, time(NULL)))
+			continue;
+		wd.wd_sendtime = htonl(wd.wd_sendtime);
+		for(i = 0; i < 3; i++)
+			wd.wd_loadav[i] = htonl(wd.wd_loadav[i]);
+		wd.wd_boottime = htonl(wd.wd_boottime);
+		for(we = wd.wd_we; (char *)we < ((char *)&wd) + ret; we++) {
+			we->we_idle = htonl(we->we_idle);
+			we->we_utmp.out_time = htonl(we->we_utmp.out_time);
+		}
+		for(np = neighbors; np != NULL; np = np->n_next) {
+			if(sendto(sk, &wd, ret, 0, (struct sockaddr *) np->n_addr, np->n_addrlen) < 0) 
+				syslog(LOG_ERR, "sendto(%s): %m", inet_ntoa(((struct sockaddr_in *)np->n_addr)->sin_addr));
+		}
+	}
+	closedir(dirp);
+}
 
 static void
 sendpacket(struct whod *wd)

