diff -Naur distcc-2.18.3.old/Makefile.in distcc-2.18.3/Makefile.in
--- distcc-2.18.3.old/Makefile.in	2004-10-23 22:05:48.000000000 -0700
+++ distcc-2.18.3/Makefile.in	2005-10-13 16:55:55.000000000 -0700
@@ -189,6 +189,9 @@
 	src/serve.o src/setuid.o src/srvnet.o src/srvrpc.o src/state.o	\
 	$(common_obj) @BUILD_POPT@
 
+lsdistcc_obj = src/lsdistcc.o \
+	src/clinet.o src/io.o src/netutil.o src/trace.o src/util.o src/rslave.o
+
 # Objects that need to be linked in to build monitors
 mon_obj =								\
 	src/cleanup.o							\
@@ -228,12 +231,12 @@
 	src/h_sa2str.c src/h_scanargs.c src/h_strip.c			\
 	src/help.c src/history.c src/hosts.c src/hostfile.c		\
 	src/implicit.c src/io.c						\
-	src/loadfile.c src/lock.c 					\
+	src/loadfile.c src/lock.c src/lsdistcc.c			\
 	src/mon.c src/mon-notify.c src/mon-text.c			\
 	src/mon-gnome.c							\
 	src/ncpus.c src/netutil.c					\
 	src/prefork.c src/pump.c					\
-	src/remote.c src/renderer.c src/rpc.c				\
+	src/remote.c src/renderer.c src/rpc.c src/rslave.c		\
 	src/safeguard.c src/sendfile.c src/setuid.c src/serve.c		\
 	src/snprintf.c src/state.c					\
 	src/srvnet.c src/srvrpc.c src/ssh.c src/strip.c			\
@@ -250,7 +253,7 @@
 	src/hosts.h src/implicit.h					\
 	src/mon.h							\
 	src/netutil.h							\
-	src/renderer.h src/rpc.h					\
+	src/renderer.h src/rpc.h src/rslave.h				\
 	src/snprintf.h src/state.h		 			\
 	src/timefile.h src/timeval.h src/trace.h			\
 	src/types.h							\
@@ -291,6 +294,7 @@
 	distcc@EXEEXT@ \
 	distccd@EXEEXT@ \
 	distccmon-text@EXEEXT@ \
+	lsdistcc@EXEEXT@ \
 	@GNOME_BIN@ 
 
 check_PROGRAMS = \
@@ -339,6 +343,9 @@
 distccmon-text@EXEEXT@: $(mon_obj) src/mon-text.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(mon_obj) src/mon-text.o $(LIBS)
 
+lsdistcc@EXEEXT@: $(lsdistcc_obj)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(lsdistcc_obj) $(LIBS)
+
 h_exten@EXEEXT@: $(h_exten_obj)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_exten_obj) $(LIBS)
 
diff -Naur distcc-2.18.3/src/lsdistcc.c distcc-2.18.3.new/src/lsdistcc.c
--- distcc-2.18.3/src/lsdistcc.c	1969-12-31 16:00:00.000000000 -0800
+++ distcc-2.18.3.new/src/lsdistcc.c	2005-10-15 17:47:44.000000000 -0700
@@ -0,0 +1,501 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ * 
+ * lsdistcc -- A simple distcc server discovery program
+ *
+ * Copyright (C) 2005 by Google
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Program to autodetect listening distcc servers by looking in DNS
+ * for hosts named according to a given format.
+ * hosts are considered good servers based solely on whether their
+ * name fits the format and whether they are listening on the right port. 
+ * Stops looking for servers after the first one it doesn't find in DNS.
+ * Prints results to stdout.
+ * Terminates with error status if no servers found.
+ * 
+ * Examples:
+ * 
+ * In your build script, add the lines
+ *   DISTCC_HOSTS=`lsdistcc`
+ *   export DISTCC_HOSTS
+ * before the line that invokes make.
+ *  
+ * Or, in your Makefile, add the lines
+ *   export DISTCC_HOSTS = $(shell lsdistcc) 
+ *
+ * Changelog:
+ * Thu Oct 13 2005 - Dan Kegel, Google
+ *  use rslave to do asynchronous-ish hostname lookup, do all connects in parallel
+ *
+ * Wed Oct  5 2005 - Dan Kegel, Google
+ *  Added -d, -m options
+ *
+ * Fri Sep 16 2005 - Dan Kegel, Google 
+ *  Created
+ *  Added -v option
+--------------------------------------------------------------------------*/
+
+#include <netdb.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#include "distcc.h"
+#include "clinet.h"
+#include "netutil.h"
+#include "util.h"
+#include "trace.h"
+#include "rslave.h"
+
+/* Default parameters */
+#define DEFAULT_FORMAT "distcc%d"   /* hostname format */
+#define DEFAULT_PORT 3632           /* TCP port to connect to */
+#define DEFAULT_BIGTIMEOUT 7        /* max total runtime, seconds */
+#define DEFAULT_DNSTIMEOUT_MS 500  /* individual DNS timeout, msec */
+#define DEFAULT_CONNTIMEOUT_MS 1500 /* individual connect timeout, msec */
+#define DEFAULT_OVERLAP 0           /* number of simultaneous DNS queries - 1 */
+#define DEFAULT_DNSGAP 0   /* number of missing hosts in DNS before we stop looking */
+
+#define MAXHOSTS 500
+#define MAXTRIES 5
+#define MAXFDS (MAXHOSTS+2)
+
+
+/* globals used by other compilation units */
+const char *rs_program_name = "lsdistcc";
+
+/* Forward declarations (solely to prevent compiler warnings) */
+void usage(void);
+int bitcompare(const char *a, const char *b, int nbits);
+void timeout_handler(int x);
+int detect_distcc_servers(const char *sformat, int port, int numeric, int bigtimeout, int conntimeout, int verbose, int matchbits, int overlap, int dnsgap);
+
+int g_verbose = 0;
+
+void usage(void) {
+	printf("Usage: lsdistcc [-tTIMEOUT] [-mBITS] [-nvd] [format]\n\
+Uses 'for i=1... sprintf(format, i)' to construct names of servers,\n\
+stops after %d seconds or at second server that doesn't resolve,\n\
+prints the names of all such servers listening on distcc's port.\n\
+Default format is %s.\n\
+Options:\n\
+-n         Print IP address rather than name\n\
+-tTIMEOUT  Set number of seconds to stop searching after [%d]\n\
+-cCTIMEOUT Set number of milliseconds before giving up on connect [%d]\n\
+-mBITS     Set number of bits of address that must match first host found [0]\n\
+-oOVERLAP  Set number of extra DNS requests to send [%d]\n\
+-gDNSGAP   Set number of missing DNS entries to tolerate [%d]\n\
+-d         append DNS domain name to format\n\
+-v         verbose\n\
+", DEFAULT_BIGTIMEOUT, DEFAULT_FORMAT, DEFAULT_BIGTIMEOUT, DEFAULT_CONNTIMEOUT_MS, DEFAULT_OVERLAP, DEFAULT_DNSGAP);
+	exit(1);
+}
+
+
+/* Compare first nbits of a[] and b[] 
+ * If nbits is 1, only compares the MSB of a[0] and b[0]
+ * Return 0 on equal, nonzero on nonequal
+ */
+int bitcompare(const char *a, const char *b, int nbits)
+{
+	int fullbytes = nbits/8;
+	int leftoverbits = nbits & 7;
+
+	if (fullbytes) {
+	    int d = memcmp((char *)a, (char *)b, (size_t) fullbytes);
+	    if (d)
+		    return d;
+	}
+
+	if (leftoverbits) {
+	    int mask = 0;
+	    int i;
+	    for (i=0; i<leftoverbits; i++)
+		mask |= (1 << (7-i));
+	    /* printf("mask %x, a[%d] %x, b[%d] %x\n", mask, fullbytes, a[fullbytes], fullbytes, b[fullbytes]); */
+	    return ((a[fullbytes] ^ b[fullbytes]) & mask);
+	}
+	return 0;
+}
+
+#if 0
+#include <assert.h>
+main()
+{
+	assert(bitcompare("0", "0", 8) == 0);
+	assert(bitcompare("0", "1", 8) != 0);
+	assert(bitcompare("0", "1", 7) == 0);
+}
+#endif
+	
+
+/* On timeout, silently terminate program  */
+void timeout_handler(int x)
+{
+	(void) x;
+
+	if (g_verbose > 0)
+		fprintf(stderr, "Timeout!\n");
+
+	/* FIXME: is it legal to call exit here? */
+	exit(0);
+}
+
+/* Detect all listening distcc servers and print their names to stdout.
+ * Looks for servers numbered 1 through infinity, stops at
+ * first server that doesn't resolve in DNS, or after 'timeout' seconds,
+ * whichever comes first.
+ * On entry:
+ *  sformat: format of names of distcc servers to check
+ *  port:    port number distcc servers listen on
+ *  numeric: whether to print the IP address instead of the hostname
+ *  bigtimeout: how many seconds to terminate slow run after 
+ *  conntimeout: how many milliseconds to give up on tcp connect after
+ *  verbose: whether to print verbose log
+ *  matchbits: top matchbits of address must match first host found, else stop searching
+ *  overlap: how many extra DNS queries to keep in flight normally
+ *  dnsgap: how many missing DNS entries to tolerate
+ * On exit:
+ *  returns number of servers found.
+ */
+int detect_distcc_servers(const char *sformat, int port, int numeric, int bigtimeout, int conntimeout, int verbose, int matchbits, int overlap, int dnsgap)
+{
+    unsigned char firstipaddr[4];
+    int dnstimeout_usec = DEFAULT_DNSTIMEOUT_MS * 1000;   /* how long before resending gethostbyname */
+    int conntimeout_usec = conntimeout * 1000;	/* how long before giving up on host connect */
+    int n = MAXHOSTS;
+    int i;
+    char thename[256];
+    struct pollfd pollfds[MAXFDS];
+
+    enum status_e { STATE_LOOKUP, STATE_CONNECTING, STATE_DONE };
+    struct state_s {
+	rslave_request_t req;
+	rslave_result_t res;
+	struct timeval deadline;
+	enum status_e status;
+        int ntries;
+	int fd;
+    };
+    typedef struct state_s state_t;
+    struct state_s states[MAXHOSTS+1];
+    int ndone;
+    int ngotaddr;
+    int nok;
+    int nbaddns;
+    int nwithtries[MAXTRIES+1];
+    int nfds;
+    int fd2state[MAXHOSTS+1000];	/* kludge - fragile */
+
+    struct rslave_s rs;
+
+    /* Don't run longer than bigtimeout seconds */
+    signal(SIGALRM, timeout_handler);
+    alarm((unsigned) bigtimeout);
+
+    if (rslave_init(&rs))
+	return 0;
+
+    ngotaddr = 0;
+    memset(nwithtries, 0, sizeof(nwithtries));
+    memset(pollfds, 0, sizeof(pollfds));
+    memset(states, 0, sizeof(states));
+
+    /* all hosts start off in state 'sent 0' */
+    for (i=1; i<=n; i++) {
+	rslave_request_t *req = &states[i].req;
+        sprintf(thename, sformat, i);
+	rslave_request_init(req, thename, i);
+	states[i].status = STATE_LOOKUP;
+	states[i].ntries = 0;
+	nwithtries[0]++;
+    }
+
+    ndone = 0;
+    nok = 0;
+    nbaddns = 0;
+    while (ndone < n) {
+	struct state_s *sp;
+	int nready;
+	struct timeval now;
+	int found;
+
+	nfds = 0;
+	pollfds[nfds].fd = rslave_getfd_fromSlaves(&rs);
+	pollfds[nfds++].events = POLLIN;
+	pollfds[nfds].fd = rslave_getfd_toSlaves(&rs);
+        pollfds[nfds++].events = ((nwithtries[1] <= overlap) && (nwithtries[1]+nwithtries[2]+nwithtries[3]+nwithtries[4]+ngotaddr < n)) ? POLLOUT : 0;
+	for (i=1; i<=n; i++) {
+	    if (states[i].status == STATE_CONNECTING) {
+		pollfds[nfds].fd = states[i].fd;
+		pollfds[nfds++].events = POLLOUT;
+	    }
+	}
+
+	nready = poll(pollfds, (unsigned)nfds, 50);
+	gettimeofday(&now, 0);
+
+	sp = NULL;
+	found = FALSE;
+	/* Detect timeouts */
+	for (i=1; i<=n; i++) {
+	    sp = &states[i];
+	    if (sp->status == STATE_LOOKUP 
+	    && sp->ntries > 0 && sp->ntries < MAXTRIES 
+	    && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) {
+		found = TRUE;
+		nwithtries[sp->ntries]--;
+		sp->ntries++;
+		nwithtries[sp->ntries]++;
+		if (verbose > 0)
+		    fprintf(stderr, "now %ld %ld: Resending %s because deadline was %ld %ld\n",
+		       now.tv_sec, now.tv_usec/1000, sp->req.hname, sp->deadline.tv_sec, sp->deadline.tv_usec/1000);  
+		break;
+	    }
+
+            if (sp->status == STATE_CONNECTING
+            && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) {
+		sp->status = STATE_DONE;
+	        close(sp->fd);
+	        sp->fd = -1;
+		ndone++;
+		if (verbose > 0)
+		    fprintf(stderr, "now %ld %ld: %s timed out while connecting\n", now.tv_sec, now.tv_usec/1000, sp->req.hname);
+            }
+	}
+	if (!found && (nwithtries[1] <= overlap) && (pollfds[1].revents & POLLOUT)) {
+	    /* Look for a fresh record to send */
+	    for (i=1; i<=n; i++) {
+	        sp = &states[i];
+		if (sp->status == STATE_LOOKUP && sp->ntries == 0) {
+		    found = TRUE;
+		    nwithtries[sp->ntries]--;
+		    sp->ntries++;
+		    nwithtries[sp->ntries]++;
+		    break;
+		}
+	    }
+	}
+	/* If we found a record to send or resend, send it, and mark its timeout. */
+	if (found) {
+	    if (verbose)
+		fprintf(stderr, "now %ld %ld: Looking up %s\n", now.tv_sec, now.tv_usec/1000, sp->req.hname);
+	    rslave_writeRequest(&rs, &sp->req);
+	    sp->deadline = now;
+	    sp->deadline.tv_usec += dnstimeout_usec;
+	    sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000;
+	    sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000;
+	}
+
+	if (pollfds[0].revents & POLLIN) {
+	    /* A reply is ready, huzzah! */
+	    rslave_result_t result;
+	    if (rslave_readResult(&rs, &result)) {
+		printf("bug: can't read from pipe\n");
+	    } else {
+		/* Find the matching state_t, save the result, and mark it as done */
+		/* printf("result.id %d\n", result.id); fflush(stdout); */
+		assert(result.id > 0 && result.id <= n);
+		sp = &states[result.id];
+		if (sp->status == STATE_LOOKUP) {
+		    nwithtries[sp->ntries]--;
+		    sp->res = result;
+		    ngotaddr++;
+		    if (matchbits > 0) {
+			if (ngotaddr == 1) {
+			    memcpy(firstipaddr, result.addr, 4);
+			} else {
+			    /* break if new server on a 'different network' than first server */
+			    if (bitcompare(firstipaddr, result.addr, matchbits))
+				result.err = -1;
+			}
+		    }
+
+		    if (result.err) {
+			if (verbose)
+			    fprintf(stderr, "now %ld %ld: %s not found\n", now.tv_sec, now.tv_usec/1000, sp->req.hname);
+			sp->status = STATE_DONE;
+			ndone++;
+			nbaddns++;
+			if (nbaddns > dnsgap) {
+			    int highest = 0;
+			    /* start no more lookups */
+			    for (i=1; i <= n; i++)
+				if (states[i].ntries > 0)
+				    highest = i;
+			    assert(highest <= n);
+			    if (verbose && n != highest)
+			        fprintf(stderr, "Already searching up to host %d, won't search any higher\n", highest);
+			    n = highest;
+			    assert(n <= MAXHOSTS);
+			}
+		    } else {
+			int fd;
+			struct sockaddr_in sa;
+
+			if (verbose > 0)
+			    fprintf(stderr, "now %ld %ld: Connecting to %s\n", now.tv_sec, now.tv_usec/1000, sp->req.hname);
+
+			/* Now do a nonblocking connect to that address */
+			memset(&sa, 0, sizeof sa);
+			sa.sin_family = AF_INET;
+			sa.sin_port = htons(port);
+			memcpy(&sa.sin_addr, result.addr, 4);
+
+			if ((fd = socket(sa.sin_family, SOCK_STREAM, 0)) == -1) {
+			    fprintf(stderr, "failed to create socket: %s", strerror(errno));
+			    sp->status = STATE_DONE;
+			} else {
+                            dcc_set_nonblocking(fd);
+			    /* start the nonblocking connect... */
+			    if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) && errno != EINPROGRESS) {
+				if (verbose > 0)
+				    fprintf(stderr, "failed to connect socket: %s", strerror(errno));
+				sp->status = STATE_DONE;
+				close(fd);
+				sp->fd = -1;
+			    } else {
+				sp->status = STATE_CONNECTING;
+				sp->fd = fd;
+				fd2state[fd] = result.id;
+                                sp->deadline = now;
+                                sp->deadline.tv_usec += conntimeout_usec;
+			        sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000;
+			        sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	for (i=2; i<nfds; i++) {
+	    if (i < MAXFDS && pollfds[i].revents) {
+		int connecterr;
+		int len = sizeof(connecterr);
+		sp = states + fd2state[pollfds[i].fd];	/* FIXME */
+		if (getsockopt(pollfds[i].fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) {
+		    fprintf(stderr, "getsockopt SO_ERROR failed?!");
+		} else {
+		    if (!connecterr) {
+			if (numeric)
+			        printf("%d.%d.%d.%d\n", sp->res.addr[0], sp->res.addr[1], sp->res.addr[2], sp->res.addr[3]);
+			else
+				puts(sp->req.hname);
+			if (verbose)
+				fflush(stdout);
+			nok++;
+		    }
+		}
+		sp->status = STATE_DONE;
+		close(sp->fd);
+		sp->fd = -1;
+		ndone++;
+	    }
+	}
+    }
+    return nok;
+}
+
+int main(int argc, char **argv)
+{
+    const char *sformat;
+    int opt_numeric = 0;
+    int opt_overlap = DEFAULT_OVERLAP;
+    int opt_dnsgap = DEFAULT_DNSGAP;
+    int opt_port = DEFAULT_PORT;
+    int opt_bigtimeout = DEFAULT_BIGTIMEOUT;
+    int opt_conntimeout = DEFAULT_CONNTIMEOUT_MS;
+    int opt_verbose = 0;
+    int opt_domain = 0;
+    int opt_match = 0;
+    int opti;
+    int nfound;
+
+    for (opti = 1; opti < argc && argv[opti][0] == '-'; opti++) {
+	switch (argv[opti][1]) {
+	case 'm':
+	    opt_match = atoi(argv[opti]+2);
+	    if (opt_match > 31 || opt_match < 0)
+		usage();
+	    break;
+	case 't':
+	    opt_bigtimeout = atoi(argv[opti]+2);
+	    if (opt_bigtimeout < 0)
+		usage();
+	    break;
+	case 'c':
+	    opt_conntimeout = atoi(argv[opti]+2);
+	    if (opt_conntimeout < 0)
+		usage();
+	    break;
+	case 'o':
+	    opt_overlap = atoi(argv[opti]+2);
+	    if (opt_overlap < 0)
+		usage();
+	    break;
+	case 'g':
+	    opt_dnsgap = atoi(argv[opti]+2);
+	    if (opt_dnsgap < 0)
+		usage();
+	    break;
+	case 'n':
+	    opt_numeric = 1;
+	    break;
+	case 'v':
+	    opt_verbose++;
+	    break;
+	case 'd':
+	    opt_domain++;
+	    break;
+	default:
+	    usage();
+	}
+    }
+    g_verbose = opt_verbose;
+
+    if (opti < argc)
+	sformat = argv[opti++];
+    else
+	sformat = DEFAULT_FORMAT;
+
+    if (opt_domain) {
+	char formatbuf[1024];
+	const char *domain_name;
+	if (dcc_get_dns_domain(&domain_name)) {
+		fprintf(stderr, "Can't get domain name\n");
+		exit(1);
+	}
+	strcpy(formatbuf, sformat);
+	strcat(formatbuf, ".");
+	strcat(formatbuf, domain_name);
+	sformat = formatbuf;
+    }
+
+    nfound = detect_distcc_servers(sformat, opt_port, opt_numeric, opt_bigtimeout, opt_conntimeout, opt_verbose, opt_match, opt_overlap, opt_dnsgap);
+
+    /* return failure if no servers found */
+    return (nfound > 0) ? 0 : 1;
+}

diff -Naur distcc-2.18.3.old/src/rslave.c distcc-2.18.3/src/rslave.c
--- distcc-2.18.3.old/src/rslave.c	1969-12-31 16:00:00.000000000 -0800
+++ distcc-2.18.3/src/rslave.c	2005-10-13 16:55:55.000000000 -0700
@@ -0,0 +1,162 @@
+/* Copyright (C) 2005 by Google
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/* don't blame me, I was in a hurry */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#include "rslave.h"
+
+/*--------------------------------------------------------------------------
+ Class to provide asynchronous DNS lookup.
+ To use, first call rslave_init() very early in your program to fork the
+ dns slave processes.
+ Then call rslave_write() any time you need a DNS name resolved
+ and rslave_read() to retrieve the next result.  Order of lookup requests
+ is not preserved.
+ Call rslave_getfd() and select on that fd for readability if you 
+ want to only call rslave_read() once it won't block.
+ The slaves will shut down when their input file descriptor is closed,
+ which normally happens when your program exits.
+--------------------------------------------------------------------------*/
+
+int rslave_getfd_fromSlaves(struct rslave_s *rslave)
+{
+    return rslave->pipeFromSlaves[0];
+}
+
+int rslave_getfd_toSlaves(struct rslave_s *rslave)
+{
+    return rslave->pipeToSlaves[1];
+}
+
+void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id)
+{
+    memset(buf, 0, sizeof(*buf));
+    strncpy(buf->hname, hostname, rslave_HOSTLEN);
+    buf->id = id;
+}
+
+int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req)
+{
+    if (write(rslave->pipeToSlaves[1], req, sizeof(*req)) != sizeof(*req))
+	return -1;
+    return 0;
+}
+
+int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id)
+{
+    struct rslave_request_s buf;
+    rslave_request_init(&buf, hostname, id);
+    return rslave_writeRequest(rslave, &buf);
+}
+
+int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req)
+{
+    if (read(rslave->pipeToSlaves[0], req, sizeof(*req)) != sizeof(*req))
+	return -1;
+    return 0;
+}
+
+int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result)
+{
+    if (write(rslave->pipeFromSlaves[1], result, sizeof(*result)) != sizeof(*result))
+	return -1;
+    return 0;
+}
+
+int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result)
+{
+    if (read(rslave->pipeFromSlaves[0], result, sizeof(*result)) != sizeof(*result))
+	return -1;
+    return 0;
+}
+
+void be_a_dnsslave(struct rslave_s *rslave);
+void be_a_dnsslave(struct rslave_s *rslave)
+{
+     struct rslave_request_s req;
+     sethostent(1);
+     while (rslave_readRequest(rslave, &req) == 0) {
+        struct rslave_result_s result;
+	struct hostent *h;
+	//fprintf(stderr, "Calling gethostbyname on %s\n", req.hname);
+	h = gethostbyname(req.hname);
+	memset(&result, 0, sizeof(result));
+        result.id = req.id;
+	result.err = h_errno;
+	if (h && (h->h_length == sizeof(result.addr))) { 
+	    memcpy(result.addr, h->h_addr_list[0], (unsigned) h->h_length);
+	    result.err = 0;
+	} 
+	if (rslave_writeResult(rslave, &result))
+	    break;
+    }
+    exit(0);
+}
+
+/*--------------------------------------------------------------------------
+ Initialize an rslave_s and fork slave processes.
+ Returns 0 on success, -1 on error.
+--------------------------------------------------------------------------*/
+
+int rslave_init(struct rslave_s *rslave)
+{
+    int err;
+    int i;
+    int nslaves = rslave_NSLAVES;
+
+    memset(rslave, 0, sizeof(*rslave));
+    err = pipe(rslave->pipeToSlaves);
+    if (err == -1)
+	return -1;
+    err = pipe(rslave->pipeFromSlaves);
+    if (err == -1)
+	return -1;
+
+    for (i=0; i<nslaves; i++) {
+	switch (fork()) {
+	case -1:
+	    return -1;
+	    break;
+
+	case 0:	/* child */
+	    close(rslave->pipeToSlaves[1]);
+	    close(rslave->pipeFromSlaves[0]);
+	    be_a_dnsslave(rslave);
+	    break;
+	default: /* parent */
+	    break;
+	}
+    }
+    close(rslave->pipeToSlaves[0]);
+    close(rslave->pipeFromSlaves[1]);
+
+    rslave->nslaves = nslaves;
+    return 0;
+}
+
diff -Naur distcc-2.18.3.old/src/rslave.h distcc-2.18.3/src/rslave.h
--- distcc-2.18.3.old/src/rslave.h	1969-12-31 16:00:00.000000000 -0800
+++ distcc-2.18.3/src/rslave.h	2005-10-13 16:55:55.000000000 -0700
@@ -0,0 +1,59 @@
+/* Copyright (C) 2005 by Google
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#ifndef rslave_H
+#define rslave_H
+
+/* don't blame me, I was in a hurry */
+
+#include <unistd.h>	/* for pid_t */
+
+/* maximum length of hostname */
+#define rslave_HOSTLEN 200
+
+#define rslave_NSLAVES 6
+struct rslave_s {
+    int nslaves;
+    int pipeToSlaves[2];
+    int pipeFromSlaves[2];
+    pid_t pids[rslave_NSLAVES];
+};
+
+struct rslave_request_s {
+    int id;
+    char hname[rslave_HOSTLEN+1];
+};
+typedef struct rslave_request_s rslave_request_t;
+
+struct rslave_result_s {
+    int id;
+    int err;
+    unsigned char addr[4];
+};
+typedef struct rslave_result_s rslave_result_t;
+
+int rslave_init(struct rslave_s *rslave);
+int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id);
+void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id);
+int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req);
+int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req);
+int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result);
+int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result);
+int rslave_getfd_fromSlaves(struct rslave_s *rslave);
+int rslave_getfd_toSlaves(struct rslave_s *rslave);
+
+#endif
diff -Naur distcc-2.18.3.old/src/util.c distcc-2.18.3/src/util.c
--- distcc-2.18.3.old/src/util.c	2004-10-23 22:05:49.000000000 -0700
+++ distcc-2.18.3/src/util.c	2005-10-14 16:38:00.000000000 -0700
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <netdb.h>
+#include <ctype.h>
 
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -345,6 +346,89 @@
 }
 
 
+#define IS_LEGAL_DOMAIN_CHAR(c) (isalnum(c) || ((c) == '-') || ((c) == '.'))
+
+/* Copy domain part of hostname to static buffer.
+ * If hostname has no domain part, returns -1.
+ * If domain lookup fails, returns -1.  
+ * Otherwise places pointer to domain in *domain_name and returns 0.
+ *
+ * This should yield the same result as the linux command 
+ * 'dnsdomainname' or 'hostname -d'.
+ **/
+int dcc_get_dns_domain(const char **domain_name)
+{
+#if 0 /* Too expensive */
+
+    static char host_name[1024];
+    struct hostent *h;
+    int ret;
+
+    ret = gethostname(host_name, sizeof(host_name));
+    if (ret != 0)
+        return -1;
+
+    h = gethostbyname(host_name);
+    if (h == NULL) {
+	rs_log_error("failed to look up self \"%s\": %s", host_name,
+                     hstrerror(h_errno));
+	return -1;
+    }
+
+    strncpy(host_name, h->h_name, sizeof(host_name));
+    *domain_name = strchr(h->h_name, '.');
+
+#else  /* cheaper */
+    const char *envh;
+    int i;
+    const int MAXDOMAINLEN = 512;
+
+    /* try to retrieve FQDN from environment */
+    envh = getenv("HOST");           /* Solaris, BSD */
+    if (!envh)
+        envh = getenv("HOSTNAME");   /* Linux, but not when ssh'd in noninteractively */
+    if (!envh) {
+	static char host_name[1024];
+	struct hostent *h;
+	int ret;
+
+	ret = gethostname(host_name, sizeof(host_name));
+	if (ret != 0)
+	    return -1;
+
+	/* If hostname has a dot in it, assume it's the DNS address */
+	if (!strchr(host_name, '.')) {
+	    /* Otherwise ask DNS what our full hostname is */
+	    h = gethostbyname(host_name);
+	    if (h == NULL) {
+		rs_log_error("failed to look up self \"%s\": %s", host_name,
+			     hstrerror(h_errno));
+		return -1;
+	    }
+	    strncpy(host_name, h->h_name, sizeof(host_name));
+	}
+        envh = host_name;
+    }
+
+    /* validate to avoid possible errors from bad chars or huge value */
+    for (i=0; envh[i] != '\0'; i++) {
+        if (i > MAXDOMAINLEN || !IS_LEGAL_DOMAIN_CHAR(envh[i])) {
+	    rs_log_error("HOST/HOSTNAME present in environment but illegal: '%s'", envh);
+	    return -1;
+        }
+    }
+    *domain_name = strchr(envh, '.');
+#endif
+
+    if (*domain_name == NULL)
+        return -1;
+
+    (*domain_name)++; 
+    /* Return 0 on success, or -1 if the domain name is illegal, e.g. empty */
+    return ((*domain_name)[0] == '\0') ? -1 : 0;
+}
+
+
 
 /**
  * Duplicate the part of the string @p psrc up to a character in @p sep
diff -Naur distcc-2.18.3.old/src/util.h distcc-2.18.3/src/util.h
--- distcc-2.18.3.old/src/util.h	2004-07-29 18:12:14.000000000 -0700
+++ distcc-2.18.3/src/util.h	2005-10-13 16:55:55.000000000 -0700
@@ -35,6 +35,7 @@
 int dcc_trim_path(const char *compiler_name);
 int dcc_set_path(const char *newpath);
 char *dcc_abspath(const char *path, int path_len);
+int dcc_get_dns_domain(const char **domain_name);
 
 #define str_equal(a, b) (!strcmp((a), (b)))
 
