Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 65576 Details for
Bug 80219
SLP and/or Howl support for DISTCC
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to enable howl support for distcc-2.18.3-r7 On second thought, this may not be the right place. If not, lemme know and I'll make a new bug.
distcc-howl.patch (text/plain), 33.65 KB, created by
Derek Ditch
on 2005-08-09 21:38:56 UTC
(
hide
)
Description:
Patch to enable howl support for distcc-2.18.3-r7 On second thought, this may not be the right place. If not, lemme know and I'll make a new bug.
Filename:
MIME Type:
Creator:
Derek Ditch
Created:
2005-08-09 21:38:56 UTC
Size:
33.65 KB
patch
obsolete
>This patch isn't all that clean, but it works. I would say that it will only work >if you *DO* have Howl installed, however. This patch explicitly defines HAVE_HOWL >so as to compile support for it. It wasn't working dynamically for some reason. > >This patch was originally posted by Lennart Poettering<mzqvfgpp@0pointer.de> here: > >http://lists.samba.org/archive/distcc/2004q4/002774.html > >I simply modified it to get it to patch agains 2.18.3-r7 in Gentoo. I've tested it >only on PPC. > >Quick start for the impatient: > >Add '--zeroconf' to the daemon startup to register with mDNSResponder. mDNS must be >running for this to work. (Set 'need mDNSRepsonder' in the init file) > >Client will expand '+zeroconf' if found in DISTCC_HOSTS. It will be replaced by a list >of all Zeroconf-enabled hosts on the subnet. > >Client option "--show-hosts" will display all hosts detected by zeroconf and all otherwise >listed in DISTCC_HOSTS. Useful for testing. > >Client will calculate a numeric concurrency level with new option "-j". It is calculated >from entries in the host list. I haven't found a useful way to get this into make.conf yet. > >Be sure to read the original list posting. Explains more technical details. > >Derek Ditch ><derek@ditch.name> > > > >diff -Naur distcc-2.18.3.orig/Makefile.in distcc-2.18.3/Makefile.in >--- distcc-2.18.3.orig/Makefile.in 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/Makefile.in 2005-08-04 11:02:57.000000000 -0500 >@@ -21,11 +21,11 @@ > # These autoconf variables may contain recursive Make expansions, and > # so they have to be done here rather than written into config.h. > >-CFLAGS = @CFLAGS@ >+CFLAGS = @CFLAGS@ -I/usr/include/howl > LDFLAGS = @LDFLAGS@ > CC = @CC@ > CPP = @CPP@ >-CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} -Isrc -I$(srcdir)/lzo >+CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} -Isrc -I$(srcdir)/lzo -DHAVE_HOWL > > srcdir = @srcdir@ > top_srcdir = @top_srcdir@ >@@ -56,7 +56,7 @@ > GNOME_CFLAGS = @GNOME_CFLAGS@ > GNOME_LIBS = @GNOME_LIBS@ > >-LIBS = @LIBS@ >+LIBS = @LIBS@ -lhowl -lpthread > > DESTDIR = > >@@ -180,6 +180,7 @@ > src/ssh.o src/state.o src/strip.o \ > src/timefile.o src/traceenv.o \ > src/where.o \ >+ src/zeroconf.o \ > $(common_obj) > > distccd_obj = src/access.o \ >@@ -187,6 +188,7 @@ > src/ncpus.o \ > src/prefork.o \ > src/serve.o src/setuid.o src/srvnet.o src/srvrpc.o src/state.o \ >+ src/zeroconf-reg.o \ > $(common_obj) @BUILD_POPT@ > > # Objects that need to be linked in to build monitors >diff -Naur distcc-2.18.3.orig/aclocal.m4 distcc-2.18.3/aclocal.m4 >--- distcc-2.18.3.orig/aclocal.m4 1969-12-31 18:00:00.000000000 -0600 >+++ distcc-2.18.3/aclocal.m4 2005-08-04 11:02:25.000000000 -0500 >@@ -0,0 +1,57 @@ >+ >+dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) >+dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page >+dnl also defines GSTUFF_PKG_ERRORS on error >+AC_DEFUN(PKG_CHECK_MODULES, [ >+ succeeded=no >+ >+ if test -z "$PKG_CONFIG"; then >+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no) >+ fi >+ >+ if test "$PKG_CONFIG" = "no" ; then >+ echo "*** The pkg-config script could not be found. Make sure it is" >+ echo "*** in your path, or set the PKG_CONFIG environment variable" >+ echo "*** to the full path to pkg-config." >+ echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." >+ else >+ PKG_CONFIG_MIN_VERSION=0.9.0 >+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then >+ AC_MSG_CHECKING(for $2) >+ >+ if $PKG_CONFIG --exists "$2" ; then >+ AC_MSG_RESULT(yes) >+ succeeded=yes >+ >+ AC_MSG_CHECKING($1_CFLAGS) >+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` >+ AC_MSG_RESULT($$1_CFLAGS) >+ >+ AC_MSG_CHECKING($1_LIBS) >+ $1_LIBS=`$PKG_CONFIG --libs "$2"` >+ AC_MSG_RESULT($$1_LIBS) >+ else >+ $1_CFLAGS="" >+ $1_LIBS="" >+ ## If we have a custom action on failure, don't print errors, but >+ ## do set a variable so people can do so. >+ $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` >+ ifelse([$4], ,echo $$1_PKG_ERRORS,) >+ fi >+ >+ AC_SUBST($1_CFLAGS) >+ AC_SUBST($1_LIBS) >+ else >+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." >+ echo "*** See http://www.freedesktop.org/software/pkgconfig" >+ fi >+ fi >+ >+ if test $succeeded = yes; then >+ ifelse([$3], , :, [$3]) >+ else >+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) >+ fi >+]) >+ >+ >diff -Naur distcc-2.18.3.orig/configure.ac distcc-2.18.3/configure.ac >--- distcc-2.18.3.orig/configure.ac 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/configure.ac 2005-08-04 11:02:25.000000000 -0500 >@@ -386,6 +386,20 @@ > AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [define if you have struct sockaddr_storage]),, > [#include <sys/socket.h>]) > >+dnl check for howl >+PKG_CHECK_MODULES(HOWL, [howl], >+[AC_DEFINE(HAVE_HOWL, 1, [defined if howl is available]) >+CFLAGS="$CFLAGS $HOWL_CFLAGS" >+LIBS="$LIBS $HOWL_LIBS" >+ZEROCONF_DISTCC_OBJS="src/zeroconf.o" >+ZEROCONF_DISTCCD_OBJS="src/zeroconf-reg.o"], >+[ZEROCONF_DISTCC_OBJS="" >+ZEROCONF_DISTCCD_OBJS=""]) >+AC_SUBST(ZEROCONF_DISTCC_OBJS) >+AC_SUBST(ZEROCONF_DISTCCD_OBJS) >+ >+AC_DEFINE(HAVE_HOWL, 1, [defined because I do]) >+ > dnl ##### Output > AC_SUBST(docdir) > AC_SUBST(CFLAGS) >diff -Naur distcc-2.18.3.orig/src/distcc.c distcc-2.18.3/src/distcc.c >--- distcc-2.18.3.orig/src/distcc.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/distcc.c 2005-08-04 11:02:25.000000000 -0500 >@@ -83,6 +83,9 @@ > " COMPILER defaults to \"cc\"\n" > " --help explain usage and exit\n" > " --version show version and exit\n" >+" --show-hosts show host list and exit\n" >+" -j calculate the concurrency level from\n" >+" the host list.\n" > "\n" > "Environment variables:\n" > " See the manual page for a complete list.\n" >@@ -135,6 +138,47 @@ > signal(SIGHUP, &dcc_client_signalled); > } > >+static void dcc_free_hostlist(struct dcc_hostdef *list) { >+ while (list) { >+ struct dcc_hostdef *l = list; >+ list = list->next; >+ dcc_free_hostdef(l); >+ } >+} >+ >+static void dcc_show_hosts(void) { >+ struct dcc_hostdef *list, *l; >+ int nhosts; >+ >+ if (dcc_get_hostlist(&list, &nhosts) != 0) { >+ rs_log_crit("Failed to get host list"); >+ return; >+ } >+ >+ for (l = list; l; l = l->next) >+ printf("%s\n", l->hostdef_string); >+ >+ dcc_free_hostlist(list); >+} >+ >+static void dcc_concurrency_level(void) { >+ struct dcc_hostdef *list, *l; >+ int nhosts; >+ int nslots = 0; >+ >+ if (dcc_get_hostlist(&list, &nhosts) != 0) { >+ rs_log_crit("Failed to get host list"); >+ return; >+ } >+ >+ for (l = list; l; l = l->next) >+ nslots += l->n_slots; >+ >+ dcc_free_hostlist(list); >+ >+ printf("%i\n", nslots); >+} >+ > #define MAXNEWFLAGS 32 > #define MAXFLAGLEN 127 > >@@ -282,6 +326,18 @@ > ret = 0; > goto out; > } >+ >+ if (!strcmp(argv[1], "--show-hosts")) { >+ dcc_show_hosts(); >+ ret = 0; >+ goto out; >+ } >+ >+ if (!strcmp(argv[1], "-j")) { >+ dcc_concurrency_level(); >+ ret = 0; >+ goto out; >+ } > > if(!(newargv = getNewArgvFromEnv(argv))) { > ret = EXIT_OUT_OF_MEMORY; >diff -Naur distcc-2.18.3.orig/src/distcc.h distcc-2.18.3/src/distcc.h >--- distcc-2.18.3.orig/src/distcc.h 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/distcc.h 2005-08-04 11:02:25.000000000 -0500 >@@ -112,7 +112,7 @@ > int *ret_nhosts); > int dcc_parse_hosts(const char *where, const char *source_name, > struct dcc_hostdef **ret_list, >- int *ret_nhosts); >+ int *ret_nhosts, struct dcc_hostdef **ret_prev); > > /* ncpu.c */ > int dcc_ncpus(int *); >@@ -226,6 +226,7 @@ > int dcc_make_tmpnam(const char *, const char *suffix, char **); > > int dcc_mkdir(const char *path) WARN_UNUSED; >+int dcc_get_subdir(const char *name, char **path_ret) WARN_UNUSED; > int dcc_get_lock_dir(char **path_ret) WARN_UNUSED; > int dcc_get_state_dir(char **path_ret) WARN_UNUSED; > int dcc_get_top_dir(char **path_ret) WARN_UNUSED; >diff -Naur distcc-2.18.3.orig/src/dopt.c distcc-2.18.3/src/dopt.c >--- distcc-2.18.3.orig/src/dopt.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/dopt.c 2005-08-04 11:02:25.000000000 -0500 >@@ -93,6 +93,9 @@ > opt_log_level > }; > >+#ifdef HAVE_HOWL >+int opt_zeroconf = 0; >+#endif > > const struct poptOption options[] = { > { "allow", 'a', POPT_ARG_STRING, 0, 'a', 0, 0 }, >@@ -115,6 +118,9 @@ > { "verbose", 0, POPT_ARG_NONE, 0, 'v', 0, 0 }, > { "version", 0, POPT_ARG_NONE, 0, 'V', 0, 0 }, > { "wizard", 'W', POPT_ARG_NONE, 0, 'W', 0, 0 }, >+#ifdef HAVE_HOWL >+ { "zeroconf", 0, POPT_ARG_NONE, &opt_zeroconf, 0, 0, 0 }, >+#endif > { 0, 0, 0, 0, 0, 0, 0 } > }; > >@@ -137,6 +143,9 @@ > " -p, --port PORT TCP port to listen on\n" > " --listen ADDRESS IP address to listen on\n" > " -a, --allow IP[/BITS] client address access control\n" >+#ifdef HAVE_HOWL >+" --zeroconf register via mDNS/DNS-SD\n" >+#endif > " Debug and trace:\n" > " --log-level=LEVEL set detail level for log file\n" > " levels: critical, error, warning, notice, info, debug\n" >diff -Naur distcc-2.18.3.orig/src/dopt.h distcc-2.18.3/src/dopt.h >--- distcc-2.18.3.orig/src/dopt.h 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/dopt.h 2005-08-04 11:02:25.000000000 -0500 >@@ -38,3 +38,5 @@ > extern int opt_lifetime; > extern char *opt_listen_addr; > extern int opt_niceness; >+ >+extern int opt_zeroconf; >diff -Naur distcc-2.18.3.orig/src/dparent.c distcc-2.18.3/src/dparent.c >--- distcc-2.18.3.orig/src/dparent.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/dparent.c 2005-08-04 11:02:25.000000000 -0500 >@@ -70,6 +70,7 @@ > #include "types.h" > #include "daemon.h" > #include "netutil.h" >+#include "zeroconf.h" > > static void dcc_nofork_parent(int listen_fd) NORETURN; > static void dcc_detach(void); >@@ -94,6 +95,9 @@ > int listen_fd; > int n_cpus; > int ret; >+#ifdef HAVE_HOWL >+ sw_discovery discovery; >+#endif > > if ((ret = dcc_socket_listen(arg_port, &listen_fd, opt_listen_addr)) != 0) > return ret; >@@ -131,6 +135,14 @@ > /* Don't catch signals until we've detached or created a process group. */ > dcc_daemon_catch_signals(); > >+#ifdef HAVE_HOWL >+ /* Zeroconf registration */ >+ if (opt_zeroconf) { >+ if ((ret = dcc_zeroconf_register(&discovery, arg_port, n_cpus)) != 0) >+ return EXIT_CONNECT_FAILED; >+ } >+#endif >+ > /* This is called in the master daemon, whether that is detached or > * not. */ > dcc_master_pid = getpid(); >@@ -138,10 +150,21 @@ > if (opt_no_fork) { > dcc_log_daemon_started("non-forking daemon"); > dcc_nofork_parent(listen_fd); >+ ret = 0; > } else { > dcc_log_daemon_started("preforking daemon"); >- return dcc_preforking_parent(listen_fd); >+ ret = dcc_preforking_parent(listen_fd); > } >+ >+#ifdef HAVE_HOWL >+ /* Remove zeroconf registration */ >+ if (opt_zeroconf) { >+ if ((ret = dcc_zeroconf_unregister(discovery)) != 0) >+ return EXIT_CONNECT_FAILED; >+ } >+#endif >+ >+ return ret; > } > > >diff -Naur distcc-2.18.3.orig/src/help.c distcc-2.18.3/src/help.c >--- distcc-2.18.3.orig/src/help.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/help.c 2005-08-04 11:02:25.000000000 -0500 >@@ -62,6 +62,9 @@ > "distcc comes with ABSOLUTELY NO WARRANTY. distcc is free software, and\n" > "you may use, modify and redistribute it under the terms of the GNU \n" > "General Public License version 2 or later.\n" >+#ifdef HAVE_HOWL >+"\nBuilt with Zeroconf support.\n" >+#endif > "\n" > , > prog, PACKAGE_VERSION, GNU_HOST, DISTCC_DEFAULT_PORT, >diff -Naur distcc-2.18.3.orig/src/hostfile.c distcc-2.18.3/src/hostfile.c >--- distcc-2.18.3.orig/src/hostfile.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/hostfile.c 2005-08-04 11:02:25.000000000 -0500 >@@ -59,7 +59,7 @@ > if ((ret = dcc_load_file_string(fname, &body)) != 0) > return ret; > >- ret = dcc_parse_hosts(body, fname, ret_list, ret_nhosts); >+ ret = dcc_parse_hosts(body, fname, ret_list, ret_nhosts, NULL); > > free(body); > >diff -Naur distcc-2.18.3.orig/src/hosts.c distcc-2.18.3/src/hosts.c >--- distcc-2.18.3.orig/src/hosts.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/hosts.c 2005-08-04 11:02:25.000000000 -0500 >@@ -96,6 +96,10 @@ > #include "hosts.h" > #include "exitcode.h" > #include "snprintf.h" >+#ifdef HAVE_HOWL >+#include "zeroconf.h" >+#define ZEROCONF_MAGIC "+zeroconf" >+#endif > > const int dcc_default_port = DISTCC_DEFAULT_PORT; > >@@ -134,9 +138,12 @@ > char *path, *top; > int ret; > >+ *ret_list = NULL; >+ *ret_nhosts = 0; >+ > if ((env = getenv("DISTCC_HOSTS")) != NULL) { > rs_trace("read hosts from environment"); >- return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts); >+ return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts, NULL); > } > > /* $DISTCC_DIR or ~/.distcc */ >@@ -163,7 +170,7 @@ > rs_trace("not reading %s: %s", path, strerror(errno)); > free(path); > } >- >+ > /* FIXME: Clearer message? */ > rs_log_warning("no hostlist is set; can't distribute work"); > >@@ -346,17 +353,19 @@ > **/ > int dcc_parse_hosts(const char *where, const char *source_name, > struct dcc_hostdef **ret_list, >- int *ret_nhosts) >+ int *ret_nhosts, struct dcc_hostdef **ret_prev) > { > int ret; >- struct dcc_hostdef *prev, *curr; >+ struct dcc_hostdef *curr, *_prev; >+ >+ if (!ret_prev) { >+ ret_prev = &_prev; >+ _prev = NULL; >+ } > > /* TODO: Check for '/' in places where it might cause trouble with > * a lock file name. */ > >- prev = NULL; >- *ret_list = NULL; >- *ret_nhosts = 0; > /* A simple, hardcoded scanner. Some of the GNU routines might be > * useful here, but they won't work on less capable systems. > * >@@ -390,6 +399,15 @@ > token_start = where; > token_len = strcspn(where, " #\t\n\f\r"); > >+#ifdef HAVE_HOWL >+ if (token_len == sizeof(ZEROCONF_MAGIC)-1 && >+ !strncmp(token_start, ZEROCONF_MAGIC, (unsigned) token_len)) { >+ if ((ret = dcc_zeroconf_add_hosts(ret_list, ret_nhosts, 4, ret_prev) != 0)) >+ return ret; >+ goto skip; >+ } >+#endif >+ > /* Allocate new list item */ > curr = calloc(1, sizeof(struct dcc_hostdef)); > if (!curr) { >@@ -404,8 +422,8 @@ > } > > /* Link into list */ >- if (prev) { >- prev->next = curr; >+ if (*ret_prev) { >+ (*ret_prev)->next = curr; > } else { > *ret_list = curr; /* first */ > } >@@ -434,10 +452,15 @@ > return ret; > } > >+ (*ret_nhosts)++; >+ *ret_prev = curr; >+ >+#ifdef HAVE_HOWL >+ skip: >+#endif >+ > /* continue to next token if any */ > where = token_start + token_len; >- prev = curr; >- (*ret_nhosts)++; > } > > if (*ret_nhosts) { >diff -Naur distcc-2.18.3.orig/src/io.c distcc-2.18.3/src/io.c >--- distcc-2.18.3.orig/src/io.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/io.c 2005-08-04 11:02:25.000000000 -0500 >@@ -160,7 +160,7 @@ > return ret; > else > continue; >- } else if (r == -1 && errno == EAGAIN) { >+ } else if (r == -1 && errno == EINTR) { > continue; > } else if (r == -1) { > rs_log_error("failed to read: %s", strerror(errno)); >@@ -202,9 +202,6 @@ > } else if (r == -1) { > rs_log_error("failed to write: %s", strerror(errno)); > return EXIT_IO_ERROR; >- } else if (r == 0) { >- rs_log_error("unexpected eof on fd%d", fd); >- return EXIT_TRUNCATED; > } else { > buf = &((char *) buf)[r]; > len -= r; >diff -Naur distcc-2.18.3.orig/src/tempfile.c distcc-2.18.3/src/tempfile.c >--- distcc-2.18.3.orig/src/tempfile.c 2005-08-04 10:27:18.000000000 -0500 >+++ distcc-2.18.3/src/tempfile.c 2005-08-04 11:02:25.000000000 -0500 >@@ -161,7 +161,7 @@ > * Return a subdirectory of the DISTCC_DIR of the given name, making > * sure that the directory exists. > **/ >-static int dcc_get_subdir(const char *name, >+int dcc_get_subdir(const char *name, > char **dir_ret) > { > int ret; >diff -Naur distcc-2.18.3.orig/src/zeroconf-reg.c distcc-2.18.3/src/zeroconf-reg.c >--- distcc-2.18.3.orig/src/zeroconf-reg.c 1969-12-31 18:00:00.000000000 -0600 >+++ distcc-2.18.3/src/zeroconf-reg.c 2005-08-04 11:02:25.000000000 -0500 >@@ -0,0 +1,110 @@ >+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- */ >+ >+#include "config.h" >+ >+#include <assert.h> >+#include <stdio.h> >+#include <sys/select.h> >+#include <signal.h> >+#include <sys/file.h> >+#include <sys/time.h> >+#include <time.h> >+#include <sys/stat.h> >+ >+#include "distcc.h" >+#include "zeroconf.h" >+#include "trace.h" >+#include "exitcode.h" >+ >+/* Called when publishing of service data completes */ >+static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid oid, sw_opaque extra) { >+ int *done = extra; >+ *done = 1; >+ >+ if (status != SW_DISCOVERY_PUBLISH_STARTED && status != SW_DISCOVERY_PUBLISH_STOPPED) >+ rs_log_crit("zeroconf publishing failed (%i)", status); >+ >+ return SW_OKAY; >+} >+ >+/* register a distcc service in DNS-SD/mDNS with the given port and number of CPUs */ >+int dcc_zeroconf_register(sw_discovery *discovery, int port, int n_cpus) { >+ sw_salt salt; >+ sw_discovery_oid oid; >+ int done = 0; >+ char service[256], hn[256], t[16]; >+ sw_text_record txt; >+ >+ if (sw_discovery_init(discovery) != SW_OKAY) { >+ rs_log_crit("sw_discovery_init() failed.\n"); >+ return EXIT_CONNECT_FAILED; >+ } >+ >+ /* Prepare TXT RR */ >+ if (sw_text_record_init(&txt) != SW_OKAY) { >+ rs_log_crit("sw_text_record_init() failed.\n"); >+ sw_discovery_fina(*discovery); >+ return EXIT_CONNECT_FAILED; >+ } >+ >+ if (sw_discovery_salt(*discovery, &salt) != SW_OKAY) { >+ rs_log_crit("sw_discovery_salt() failed.\n"); >+ goto fail; >+ } >+ >+ /* Prepare service name */ >+ gethostname(hn, sizeof(hn)-1); >+ hn[sizeof(hn)-1] = 0; >+ snprintf(service, sizeof(service), "distcc@%s", hn); >+ >+ /* Prepare TXT RR */ >+ snprintf(t, sizeof(t), "cpus=%i", n_cpus); >+ sw_text_record_add_string(txt, t); >+ >+ /* Publish the info */ >+ if (sw_discovery_publish( >+ *discovery, >+ 0, >+ service, >+ "_distcc._tcp", >+ NULL, >+ NULL, >+ (sw_port) port, >+ sw_text_record_bytes(txt), >+ sw_text_record_len(txt), >+ publish_reply, >+ &done, >+ &oid) != SW_OKAY) { >+ >+ rs_log_crit("sw_discovery_publish() failed.\n"); >+ goto fail; >+ } >+ >+ /* Wait until the publishing is finished */ >+ while (!done) { >+ if (sw_salt_step(salt, NULL) != SW_OKAY) { >+ rs_log_crit("sw_salt() failed.\n"); >+ goto fail; >+ } >+ >+ } >+ >+ rs_log_info("zeroconf publishing complete"); >+ >+ sw_text_record_fina(txt); >+ >+ return 0; >+ >+ fail: >+ >+ sw_discovery_fina(*discovery); >+ sw_text_record_fina(txt); >+ return EXIT_CONNECT_FAILED; >+} >+ >+/* Unregister this server from DNS-SD/mDNS */ >+int dcc_zeroconf_unregister(sw_discovery discovery) { >+ >+ sw_discovery_fina(discovery); >+ return 0; >+} >diff -Naur distcc-2.18.3.orig/src/zeroconf.c distcc-2.18.3/src/zeroconf.c >--- distcc-2.18.3.orig/src/zeroconf.c 1969-12-31 18:00:00.000000000 -0600 >+++ distcc-2.18.3/src/zeroconf.c 2005-08-04 11:02:25.000000000 -0500 >@@ -0,0 +1,493 @@ >+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- */ >+ >+#include "config.h" >+ >+#include <assert.h> >+#include <stdio.h> >+#include <sys/select.h> >+#include <signal.h> >+#include <sys/file.h> >+#include <sys/time.h> >+#include <time.h> >+#include <sys/stat.h> >+ >+#include "distcc.h" >+#include "hosts.h" >+#include "zeroconf.h" >+#include "trace.h" >+#include "exitcode.h" >+ >+/* How long shall the background daemon be idle before i terminates itself? */ >+#define MAX_IDLE_TIME 20 >+ >+/* Maxium size of host file to load */ >+#define MAX_FILE_SIZE (1024*100) >+ >+/* Zeroconf service wrapper */ >+struct host { >+ struct host *next; >+ sw_ipv4_address address; >+ sw_port port; >+ sw_uint32 iface; >+ char *service; >+ char *domain; >+ int n_cpus; >+}; >+ >+/* General daemon data */ >+struct daemon_data { >+ struct host *hosts; >+ int fd; >+ int n_slots; >+}; >+ >+/* A generic, system independant lock routine, similar to sys_lock, >+ * but more powerful: >+ * rw: if non-zero: r/w lock instead of r/o lock >+ * enable: lock or unlock >+ * block: block when locking */ >+static int generic_lock(int fd, int rw, int enable, int block) { >+#if defined(F_SETLK) >+ struct flock lockparam; >+ >+ lockparam.l_type = enable ? (rw ? F_WRLCK : F_RDLCK) : F_UNLCK; >+ lockparam.l_whence = SEEK_SET; >+ lockparam.l_start = 0; >+ lockparam.l_len = 0; /* whole file */ >+ >+ return fcntl(fd, block ? F_SETLKW : F_SETLK, &lockparam); >+#elif defined(HAVE_FLOCK) >+ return flock(fd, (enable ? (rw ? LOCK_EX : LOCK_SH) : LOCK_UN) | (block ? LOCK_NB : 0)); >+#elif defined(HAVE_LOCKF) >+ return lockf(fd, (enable ? (block ? F_LOCK : F_TLOCK) : F_ULOCK)); >+#else >+# error "No supported lock method. Please port this code." >+#endif >+} >+ >+/* Return the number of seconds, when the specified file was last >+ * read. If the atime of that file is < clip_time, use clip_time >+ * instead */ >+static time_t fd_last_used(int fd, time_t clip_time) { >+ struct stat st; >+ time_t now, ft; >+ assert(fd >= 0); >+ >+ if (fstat(fd, &st) < 0) { >+ rs_log_crit("fstat() failed: %s\n", strerror(errno)); >+ return -1; >+ } >+ >+ if ((now = time(NULL)) == (time_t) -1) { >+ rs_log_crit("time() failed: %s\n", strerror(errno)); >+ return -1; >+ } >+ >+ ft = clip_time ? (st.st_atime < clip_time ? clip_time : st.st_atime) : st.st_atime; >+ assert(ft <= now); >+ >+ return now - ft; >+} >+ >+/* Write host data to host file */ >+static int write_hosts(struct daemon_data *d) { >+ struct host *h; >+ int r = 0; >+ assert(d); >+ >+ rs_log_info("writing zeroconf data.\n"); >+ >+ if (generic_lock(d->fd, 1, 1, 1) < 0) { >+ rs_log_crit("lock failed: %s\n", strerror(errno)); >+ return -1; >+ } >+ >+ if (lseek(d->fd, 0, SEEK_SET) < 0) { >+ rs_log_crit("lseek() failed: %s\n", strerror(errno)); >+ return -1; >+ } >+ >+ if (ftruncate(d->fd, 0) < 0) { >+ rs_log_crit("ftruncate() failed: %s\n", strerror(errno)); >+ return -1; >+ } >+ >+ for (h = d->hosts; h; h = h->next) { >+ char t[256], a[16]; >+ snprintf(t, sizeof(t), "%s:%u/%i\n", sw_ipv4_address_name(h->address, a, sizeof(a)), h->port, d->n_slots * h->n_cpus); >+ >+ if (dcc_writex(d->fd, t, strlen(t)) != 0) { >+ rs_log_crit("write() failed: %s\n", strerror(errno)); >+ goto finish; >+ } >+ } >+ >+ r = 0; >+ >+finish: >+ >+ generic_lock(d->fd, 1, 0, 1); >+ return r; >+ >+}; >+ >+/* Free host data */ >+static void free_host(struct host *h) { >+ assert(h); >+ free(h->service); >+ free(h->domain); >+ free(h); >+} >+ >+/* Remove a service from the host list */ >+static void remove_service(struct daemon_data *d, sw_uint32 iface, const char *name, const char *domain) { >+ struct host *h, *p = NULL; >+ assert(d); >+ >+ for (h = d->hosts; h; h = h->next) { >+ if (h->iface == iface && !strcmp(h->service, name) && !strcmp(h->domain, domain)) { >+ >+ if (p) >+ p->next = h->next; >+ else >+ d->hosts = h->next; >+ >+ free_host(h); >+ >+ break; >+ } else >+ p = h; >+ } >+} >+ >+/* Called when a resolve call completes */ >+static sw_result resolve_reply( >+ sw_discovery discovery, >+ sw_discovery_oid oid, >+ sw_uint32 interface_index, >+ sw_const_string name, >+ sw_const_string type, >+ sw_const_string domain, >+ sw_ipv4_address address, >+ sw_port port, >+ sw_octets text_record, >+ sw_ulong text_record_len, >+ sw_opaque extra) { >+ >+ struct host *h; >+ struct daemon_data *d = extra; >+ int n_cpus = 1; >+ sw_text_record_iterator it; >+ >+ /* Look for the number of CPUs in TXT RRs */ >+ if (sw_text_record_iterator_init(&it, text_record, text_record_len) == SW_OKAY) { >+ sw_char key[255]; >+ sw_octet val[256]; >+ sw_ulong val_len = sizeof(val)-1; >+ >+ memset(val, 0, sizeof(val)); >+ >+ while (sw_text_record_iterator_next(it, key, val, &val_len) == SW_OKAY) { >+ if (!strcmp(key, "cpus")) { >+ if ((n_cpus = atoi((char*) val)) <= 0) >+ n_cpus = 1; >+ } >+ } >+ >+ sw_text_record_iterator_fina(it); >+ } >+ >+ /* Add a new host */ >+ h = malloc(sizeof(struct host)); >+ assert(h); >+ h->service = strdup(name); >+ assert(h->service); >+ h->domain = strdup(domain); >+ assert(h->domain); >+ h->address = address; >+ h->port = port; >+ h->iface = interface_index; >+ h->next = d->hosts; >+ h->n_cpus = n_cpus; >+ d->hosts = h; >+ >+ /* Write modified hosts file */ >+ write_hosts(d); >+ >+ /* Let's cancel this resolve request, we only need a single adress for this service */ >+ sw_discovery_cancel(discovery, oid); >+ >+ return SW_OKAY; >+} >+ >+/* Called whenever a new service is found or removed */ >+static sw_result browse_reply( >+ sw_discovery discovery, >+ sw_discovery_oid oid, >+ sw_discovery_browse_status status, >+ sw_uint32 interface_index, >+ sw_const_string name, >+ sw_const_string type, >+ sw_const_string domain, >+ sw_opaque extra) { >+ >+ struct daemon_data *d = extra; >+ assert(d); >+ >+ switch (status) { >+ case SW_DISCOVERY_BROWSE_ADD_SERVICE: { >+ sw_discovery_oid noid; >+ >+ rs_log_info("new service: %s\n", name); >+ >+ sw_discovery_resolve(discovery, 0, name, type, domain, resolve_reply, extra, &noid); >+ break; >+ } >+ case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: { >+ >+ rs_log_info("removed service: %s\n", name); >+ >+ remove_service(d, interface_index, name, domain); >+ write_hosts(d); >+ break; >+ } >+ default: >+ ; >+ } >+ >+ return SW_OKAY; >+} >+ >+/* The main function of the background daemon */ >+static void daemon_proc(const char *host_file, const char *lock_file, int n_slots) { >+ sw_discovery_oid oid; >+ sw_discovery discovery; >+ int ret = 1; >+ int lock_fd = -1; >+ struct daemon_data d; >+ sw_salt salt; >+ time_t clip_time; >+ >+ /* Prepare daemon data structure */ >+ d.fd = -1; >+ d.hosts = NULL; >+ d.n_slots = n_slots; >+ clip_time = time(NULL); >+ >+ rs_log_info("zeroconf daemon running.\n"); >+ >+ /* Open daemon lock file and lock it */ >+ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { >+ rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); >+ goto finish; >+ } >+ >+ if (generic_lock(lock_fd, 1, 1, 0) < 0) { >+ /* lock failed, there's probably already another daemon running */ >+ goto finish; >+ } >+ >+ /* Open host file */ >+ if ((d.fd = open(host_file, O_RDWR|O_CREAT, 0666)) < 0) { >+ rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); >+ goto finish; >+ } >+ >+ /* Clear host file */ >+ write_hosts(&d); >+ >+ if (sw_discovery_init(&discovery) != SW_OKAY) { >+ rs_log_crit("sw_discovery_init() failed.\n"); >+ goto finish; >+ } >+ >+ /* Start discovery */ >+ if (sw_discovery_browse(discovery, 0, "_distcc._tcp", NULL, browse_reply, &d, &oid) != SW_OKAY) { >+ rs_log_crit("sw_discovery_browse() failed.\n"); >+ goto finish; >+ } >+ >+ /* Get "salt" object for the main loop */ >+ if (sw_discovery_salt(discovery, &salt) != SW_OKAY) { >+ rs_log_crit("sw_discovery_salt() failed.\n"); >+ goto finish; >+ } >+ >+ /* Check whether the host file has been used recently */ >+ while (fd_last_used(d.fd, clip_time) <= MAX_IDLE_TIME) { >+ sw_ulong msecs = 500; >+ >+ /* Iterate the main loop for 500ms */ >+ if (sw_salt_step(salt, &msecs) != SW_OKAY) { >+ rs_log_crit("sw_salt_step() failed.\n"); >+ goto finish; >+ } >+ } >+ >+ /* Wer are idle */ >+ rs_log_info("zeroconf daemon unused.\n"); >+ >+ ret = 0; >+ >+finish: >+ >+ /* Cleanup */ >+ if (lock_fd >= 0) { >+ generic_lock(lock_fd, 1, 0, 0); >+ close(lock_fd); >+ } >+ >+ if (d.fd >= 0) >+ close(d.fd); >+ >+ while (d.hosts) { >+ struct host *h = d.hosts; >+ d.hosts = d.hosts->next; >+ free_host(h); >+ } >+ >+ rs_log_info("zeroconf daemon ended.\n"); >+ >+ exit(ret); >+} >+ >+/* Return path to the zeroconf directory in ~/.distcc */ >+static int get_zeroconf_dir(char **dir_ret) { >+ static char *cached; >+ int ret; >+ >+ if (cached) { >+ *dir_ret = cached; >+ return 0; >+ } else { >+ ret = dcc_get_subdir("zeroconf", dir_ret); >+ if (ret == 0) >+ cached = *dir_ret; >+ return ret; >+ } >+} >+ >+/* Get the host list from zeroconf */ >+int dcc_zeroconf_add_hosts(struct dcc_hostdef **ret_list, int *ret_nhosts, int n_slots, struct dcc_hostdef **ret_prev) { >+ char host_file[PATH_MAX], lock_file[PATH_MAX], *s = NULL; >+ int lock_fd = -1, host_fd = -1; >+ int fork_daemon = 0; >+ int r = -1; >+ char *dir; >+ struct stat st; >+ >+ if (get_zeroconf_dir(&dir) != 0) { >+ rs_log_crit("failed to get zeroconf dir.\n"); >+ goto finish; >+ } >+ >+ snprintf(lock_file, sizeof(lock_file), "%s/lock", dir); >+ snprintf(host_file, sizeof(host_file), "%s/hosts", dir); >+ >+ /* Open lock file */ >+ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { >+ rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); >+ goto finish; >+ } >+ >+ /* Try to lock the lock file */ >+ if (generic_lock(lock_fd, 1, 1, 0) >= 0) { >+ /* The lock succeeded => there's no daemon running yet! */ >+ fork_daemon = 1; >+ generic_lock(lock_fd, 1, 0, 0); >+ } >+ >+ close(lock_fd); >+ >+ /* Shall we fork a new daemon? */ >+ if (fork_daemon) { >+ pid_t pid; >+ >+ rs_log_info("Spawning zeroconf daemon.\n"); >+ >+ if ((pid = fork()) == -1) { >+ rs_log_crit("fork() failed: %s\n", strerror(errno)); >+ goto finish; >+ } else if (pid == 0) { >+ int fd; >+ /* Child */ >+ >+ /* Close file descriptors and replace them by /dev/null */ >+ close(0); >+ close(1); >+ close(2); >+ fd = open("/dev/null", O_RDWR); >+ assert(fd == 0); >+ fd = dup(0); >+ assert(fd == 1); >+ fd = dup(0); >+ assert(fd == 2); >+ >+#ifdef HAVE_SETSID >+ setsid(); >+#endif >+ >+ chdir("/"); >+ rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); >+ daemon_proc(host_file, lock_file, n_slots); >+ } >+ >+ /* Parent */ >+ >+ /* Wait some time for initial host gathering */ >+ usleep(1000000); /* 100 ms */ >+ >+ } >+ >+ /* Open host list read-only */ >+ if ((host_fd = open(host_file, O_RDONLY)) < 0) { >+ rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); >+ goto finish; >+ } >+ >+ /* A read lock */ >+ if (generic_lock(host_fd, 0, 1, 1) < 0) { >+ rs_log_crit("lock failed: %s\n", strerror(errno)); >+ goto finish; >+ } >+ >+ /* Get file size */ >+ if (fstat(host_fd, &st) < 0) { >+ rs_log_crit("stat() failed: %s\n", strerror(errno)); >+ goto finish; >+ } >+ >+ if (st.st_size >= MAX_FILE_SIZE) { >+ rs_log_crit("file too large.\n"); >+ goto finish; >+ } >+ >+ /* read file data */ >+ s = malloc((size_t) st.st_size+1); >+ assert(s); >+ >+ if (dcc_readx(host_fd, s, (size_t) st.st_size) != 0) { >+ rs_log_crit("failed to read from file.\n"); >+ goto finish; >+ } >+ s[st.st_size] = 0; >+ >+ /* Parse host data */ >+ if (dcc_parse_hosts(s, host_file, ret_list, ret_nhosts, ret_prev) != 0) { >+ rs_log_crit("failed to parse host file.\n"); >+ goto finish; >+ } >+ >+ r = 0; >+ >+finish: >+ if (host_fd >= 0) { >+ generic_lock(host_fd, 0, 0, 1); >+ close(host_fd); >+ } >+ >+ free(s); >+ >+ return r; >+} >+ >diff -Naur distcc-2.18.3.orig/src/zeroconf.h distcc-2.18.3/src/zeroconf.h >--- distcc-2.18.3.orig/src/zeroconf.h 1969-12-31 18:00:00.000000000 -0600 >+++ distcc-2.18.3/src/zeroconf.h 2005-08-04 11:02:25.000000000 -0500 >@@ -0,0 +1,22 @@ >+#ifndef foozeroconfhfoo >+#define foozeroconfhfoo >+ >+#include <inttypes.h> >+ >+/* HOWL 0.9.6 defines PACKAGE_NAME and friends. This is broken. As a >+ * workaround we undfined those macros here */ >+ >+#undef PACKAGE_NAME >+#undef PACKAGE_BUGREPORT >+#undef PACKAGE_TARNAME >+#undef PACKAGE_VERSION >+#undef PACKAGE_STRING >+ >+#include <howl.h> >+ >+int dcc_zeroconf_add_hosts(struct dcc_hostdef **re_list, int *ret_nhosts, int slots, struct dcc_hostdef **ret_prev); >+ >+int dcc_zeroconf_register(sw_discovery *discovery, int port, int n_cpus); >+int dcc_zeroconf_unregister(sw_discovery discovery); >+ >+#endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 80219
:
50379
|
50468
|
50469
| 65576 |
72077
|
72078
|
73258