]> git.meshlink.io Git - catta/commitdiff
Implement avahi-publish{-address, service} in C
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Nov 2005 22:34:12 +0000 (22:34 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 16 Nov 2005 22:34:12 +0000 (22:34 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@988 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

avahi-python/Makefile.am
avahi-python/avahi-publish-address.in [deleted file]
avahi-python/avahi-publish-service.in [deleted file]
avahi-utils/Makefile.am
avahi-utils/avahi-browse.c
avahi-utils/avahi-publish.c [new file with mode: 0644]
avahi-utils/avahi-resolve.c

index efb529ed3a4f80193a8331162fcc2af9d916855c..7f4980ab3cca31dd90f5709f59493dfaffc16573 100644 (file)
@@ -23,8 +23,6 @@ AM_CFLAGS=-I$(top_srcdir)
 AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
 
 EXTRA_DIST = \
 AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
 
 EXTRA_DIST = \
-       avahi-publish-address.in \
-       avahi-publish-service.in \
        avahi-bookmarks.in \
        avahi-discover.in \
        avahi-discover.desktop.in
        avahi-bookmarks.in \
        avahi-discover.in \
        avahi-discover.desktop.in
@@ -36,8 +34,6 @@ if HAVE_PYTHON_DBUS
 if HAVE_PYGTK
 
 pythonscripts = \
 if HAVE_PYGTK
 
 pythonscripts = \
-       avahi-publish-address \
-       avahi-publish-service \
        avahi-bookmarks \
        avahi-discover
 
        avahi-bookmarks \
        avahi-discover
 
@@ -53,14 +49,6 @@ avahi-discover: avahi-discover.in
                -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
        chmod +x $@
 
                -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
        chmod +x $@
 
-avahi-publish-address: avahi-publish-address.in
-       sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
-       chmod +x $@
-
-avahi-publish-service: avahi-publish-service.in
-       sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
-       chmod +x $@
-
 avahi-bookmarks: avahi-bookmarks.in
        sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
        chmod +x $@
 avahi-bookmarks: avahi-bookmarks.in
        sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
        chmod +x $@
diff --git a/avahi-python/avahi-publish-address.in b/avahi-python/avahi-publish-address.in
deleted file mode 100755 (executable)
index 4ffebd7..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi 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 Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import sys, getopt, string
-
-try:
-    import avahi, gobject, dbus
-except ImportError:
-    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
-    sys.exit(1)
-
-try:
-    import dbus.glib
-except ImportError, e:
-    pass
-
-def usage(retval = 0):
-    print "%s <name> <address>" % sys.argv[0]
-    sys.exit(retval)
-
-if len(sys.argv) != 3:
-    usage(2)
-
-name = sys.argv[1]
-address = sys.argv[2]
-
-group = None
-n_rename = 0
-
-def remove_address():
-    global group
-    
-    if not (group is None):
-        group.Free()
-        group = None
-
-def add_address():
-    global server, group, name, address
-    assert group is None
-
-    print "Adding address '%s' for '%s' ..." % (name, address)
-    group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
-    group.connect_to_signal('StateChanged', entry_group_state_changed)
-    group.AddAddress(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, address)
-    group.Commit()
-
-def entry_group_state_changed(state):
-    global name, server, n_rename, main_loop
-    
-    if state == avahi.ENTRY_GROUP_ESTABLISHED:
-        print "Address established."
-    elif state == avahi.ENTRY_GROUP_COLLISION:
-
-        n_rename = n_rename + 1
-        if n_rename >= 12:
-            print "ERROR: No suitable name found after %i retries, exiting." % n_rename
-            main_loop.quit()
-        else:
-            hn = name.split('.')
-            hn[0] = server.GetAlternativeHostName(hn[0])
-            name = string.join(hn, '.')
-            print "WARNING: Address/host name collision, changing name to '%s' ..." % name
-            remove_address()
-            add_address()
-
-main_loop = gobject.MainLoop()
-
-bus = dbus.SystemBus()
-server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-
-add_address()
-
-try:
-    main_loop.run()
-except KeyboardInterrupt, k:
-    pass
-
-remove_address()
diff --git a/avahi-python/avahi-publish-service.in b/avahi-python/avahi-publish-service.in
deleted file mode 100755 (executable)
index 3f40fd0..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi 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 Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import sys, getopt
-
-try:
-    import avahi, gobject, dbus
-except ImportError:
-    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
-    sys.exit(1)
-
-try:
-    import dbus.glib
-except ImportError, e:
-    pass
-
-def usage(retval = 0):
-    print "%s [options] <name> <type> <port> [<txt> ...]\n" % sys.argv[0]
-    print "   -h --help      Show this help"
-    print "   -d --domain    Domain where to register this service"
-    print "   -H --host      Host where this service resides"
-    sys.exit(retval)
-
-try:
-    opts, args = getopt.getopt(sys.argv[1:], "hd:H:", ["help", "domain=", "host="])
-except getopt.GetoptError:
-    usage(2)
-
-domain = ""
-host = ""
-    
-for o, a in opts:
-    if o in ("-h", "--help"):
-        usage()
-
-    if o in ("-d", "--domain"):
-        domain = a
-
-    if o in ("-H", "--host"):
-        host = a
-
-if len(args) < 3:
-    usage(2)
-
-name = args[0]
-stype = args[1]
-port = int(args[2])
-txt = args[3:]
-
-# python-dbus doesn't allow transmission of empty arrays, therefore we "fix" it with a bogus entry
-if len(txt) == 0:
-    txt.append("python-dbus=brain-damage")
-
-group = None
-n_rename = 0
-
-def remove_service():
-    global group
-
-    if not group is None:
-        group.Reset()
-
-def add_service():
-    global server, group, name, stype, domain, host, port, txt
-
-    if group is None:
-        group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
-        group.connect_to_signal('StateChanged', entry_group_state_changed)
-        
-    assert group.IsEmpty()
-
-    print "Adding service '%s' of type '%s' ..." % (name, stype)
-
-    group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, stype, domain, host, dbus.UInt16(port), avahi.string_array_to_txt_array(txt))
-    group.Commit()
-
-def entry_group_state_changed(state):
-    global name, server, n_rename
-
-#    print "state change: %i" % state
-    
-    if state == avahi.ENTRY_GROUP_ESTABLISHED:
-        print "Service established."
-    elif state == avahi.ENTRY_GROUP_COLLISION:
-
-        n_rename = n_rename + 1
-        if n_rename >= 12:
-            print "ERROR: No suitable service name found after %i retries, exiting." % n_rename
-            main_loop.quit()
-        else:
-            name = server.GetAlternativeServiceName(name)
-            print "WARNING: Service name collision, changing name to '%s' ..." % name
-            remove_service()
-            add_service()
-
-def server_state_changed(state):
-    if state == avahi.SERVER_COLLISION:
-        print "WARNING: Server name collision"
-        remove_service()
-    elif state == avahi.SERVER_RUNNING:
-        add_service()
-
-main_loop = gobject.MainLoop()
-
-bus = dbus.SystemBus()
-server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-server.connect_to_signal("StateChanged", server_state_changed)
-server_state_changed(server.GetState())
-
-try:
-    main_loop.run()
-except KeyboardInterrupt, k:
-    pass
-
-if not group is None:
-    group.Free()
index 5d6bb9f5fcd06033442a35a68ae504b124d8e0a0..dc3a127de54b08867e60cf892238a479ad91a2e9 100644 (file)
@@ -24,7 +24,7 @@ AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
 
 if HAVE_DBUS
 
 
 if HAVE_DBUS
 
-bin_PROGRAMS = avahi-browse avahi-resolve
+bin_PROGRAMS = avahi-browse avahi-resolve avahi-publish
 
 avahi_browse_SOURCES = avahi-browse.c sigint.c sigint.h
 avahi_browse_CFLAGS = $(AM_CFLAGS)
 
 avahi_browse_SOURCES = avahi-browse.c sigint.c sigint.h
 avahi_browse_CFLAGS = $(AM_CFLAGS)
@@ -40,11 +40,17 @@ avahi_resolve_SOURCES = avahi-resolve.c sigint.c sigint.h
 avahi_resolve_CFLAGS = $(AM_CFLAGS)
 avahi_resolve_LDADD = $(AM_LDADD) ../avahi-client/libavahi-client.la ../avahi-common/libavahi-common.la
 
 avahi_resolve_CFLAGS = $(AM_CFLAGS)
 avahi_resolve_LDADD = $(AM_LDADD) ../avahi-client/libavahi-client.la ../avahi-common/libavahi-common.la
 
+avahi_publish_SOURCES = avahi-publish.c sigint.c sigint.h
+avahi_publish_CFLAGS = $(AM_CFLAGS)
+avahi_publish_LDADD = $(AM_LDADD) ../avahi-client/libavahi-client.la ../avahi-common/libavahi-common.la
+
 install-exec-local:
        cd $(DESTDIR)/$(bindir) && \
                rm -f avahi-resolve-host-name avahi-resolve-address avahi-browse-domains && \
                $(LN_S) avahi-resolve avahi-resolve-host-name && \
                $(LN_S) avahi-resolve avahi-resolve-address && \
 install-exec-local:
        cd $(DESTDIR)/$(bindir) && \
                rm -f avahi-resolve-host-name avahi-resolve-address avahi-browse-domains && \
                $(LN_S) avahi-resolve avahi-resolve-host-name && \
                $(LN_S) avahi-resolve avahi-resolve-address && \
-               $(LN_S) avahi-browse avahi-browse-domains
+               $(LN_S) avahi-browse avahi-browse-domains && \
+               $(LN_S) avahi-publish avahi-publish-address && \
+               $(LN_S) avahi-publish avahi-publish-service
 
 endif
 
 endif
index e9c4073f3379aec423e7f2a863d5f1cbeb3fa090..a5d9d25f06d2407cf8da5f06de24ae1c512334d8 100644 (file)
@@ -568,7 +568,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UN
             if (config->verbose)
                 fprintf(stderr, "Waiting for daemon ...\n");
 
             if (config->verbose)
                 fprintf(stderr, "Waiting for daemon ...\n");
 
-                break;
+            break;
     }
 }
 
     }
 }
 
@@ -593,10 +593,11 @@ static void help(FILE *f, const char *argv0) {
             "    -c --cache           Terminate after dumping all entries from the cache\n"
             "    -l --ignore-local    Ignore local services\n"
             "    -r --resolve         Resolve services found\n"
             "    -c --cache           Terminate after dumping all entries from the cache\n"
             "    -l --ignore-local    Ignore local services\n"
             "    -r --resolve         Resolve services found\n"
-            "    -f --no-fail         Don't fail if the server is not available\n"
+            "    -f --no-fail         Don't fail if the daemon is not available\n"
 #ifdef HAVE_GDBM
 #ifdef HAVE_GDBM
-                    "    -k --no-db-lookup    Don't lookup service types\n");
+            "    -k --no-db-lookup    Don't lookup service types\n"
 #endif
 #endif
+            );
 }
 
 static int parse_command_line(Config *c, const char *argv0, int argc, char *argv[]) {
 }
 
 static int parse_command_line(Config *c, const char *argv0, int argc, char *argv[]) {
@@ -656,6 +657,7 @@ static int parse_command_line(Config *c, const char *argv0, int argc, char *argv
                 c->command = COMMAND_BROWSE_DOMAINS;
                 break;
             case 'd':
                 c->command = COMMAND_BROWSE_DOMAINS;
                 break;
             case 'd':
+                avahi_free(c->domain);
                 c->domain = avahi_strdup(optarg);
                 break;
             case 'v':
                 c->domain = avahi_strdup(optarg);
                 break;
             case 'v':
diff --git a/avahi-utils/avahi-publish.c b/avahi-utils/avahi-publish.c
new file mode 100644 (file)
index 0000000..e0dea9f
--- /dev/null
@@ -0,0 +1,417 @@
+/* $Id$ */
+
+/***
+  This file is part of avahi.
+  avahi is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+  avahi 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 Lesser General
+  Public License for more details.
+  You should have received a copy of the GNU Lesser General Public
+  License along with avahi; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <avahi-common/simple-watch.h>
+#include <avahi-common/error.h>
+#include <avahi-common/malloc.h>
+#include <avahi-common/alternative.h>
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+
+#include "sigint.h"
+
+typedef enum {
+    COMMAND_UNSPEC, 
+    COMMAND_HELP,
+    COMMAND_VERSION,
+    COMMAND_PUBLISH_SERVICE,
+    COMMAND_PUBLISH_ADDRESS
+} Command;
+
+typedef struct Config {
+    int verbose, no_fail;
+    Command command;
+    char *name, *stype, *domain, *host;
+    uint16_t port;
+    AvahiStringList *txt, *subtypes;
+    AvahiAddress address;
+} Config;
+
+static AvahiSimplePoll *simple_poll = NULL;
+static AvahiClient *client = NULL;
+static AvahiEntryGroup *entry_group = NULL;
+
+static int register_stuff(Config *config);
+
+static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
+    Config *config = userdata;
+
+    assert(g);
+    assert(config);
+
+    switch (state) {
+
+        case AVAHI_ENTRY_GROUP_ESTABLISHED:
+
+            fprintf(stderr, "Established under name '%s'\n", config->name);
+            break;
+
+        case AVAHI_ENTRY_GROUP_FAILURE:
+            
+            fprintf(stderr, "Failed to register: %s\n", avahi_strerror(avahi_client_errno(client)));
+            break;
+
+        case AVAHI_ENTRY_GROUP_COLLISION: {
+            char *n;
+
+            if (config->command == COMMAND_PUBLISH_SERVICE)
+                n = avahi_alternative_service_name(config->name);
+            else {
+                assert(config->command == COMMAND_PUBLISH_ADDRESS);
+                n = avahi_alternative_host_name(config->name);
+            }
+
+            fprintf(stderr, "Name collision, picking new name '%s'.\n", n);
+            avahi_free(config->name);
+            config->name = n;
+            
+            register_stuff(config);
+                
+            break;
+        }
+            
+        case AVAHI_ENTRY_GROUP_UNCOMMITED:
+        case AVAHI_ENTRY_GROUP_REGISTERING:
+            ;
+    }
+}
+
+static int register_stuff(Config *config) {
+    assert(config);
+
+    if (!entry_group) {
+        if (!(entry_group = avahi_entry_group_new(client, entry_group_callback, config))) {
+            fprintf(stderr, "Failed to create entry group: %s\n", avahi_strerror(avahi_client_errno(client)));
+            return -1;
+        }
+    }
+
+    assert(avahi_entry_group_is_empty(entry_group));
+
+    if (config->command == COMMAND_PUBLISH_ADDRESS) {
+
+        if (avahi_entry_group_add_address(entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, config->name, &config->address) < 0) {
+            fprintf(stderr, "Failed to add address: %s\n", avahi_strerror(avahi_client_errno(client)));
+            return -1;
+        }
+        
+    } else {
+        AvahiStringList *i;
+        
+        assert(config->command == COMMAND_PUBLISH_SERVICE);
+
+        if (avahi_entry_group_add_service_strlst(entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, config->name, config->stype, config->domain, config->host, config->port, config->txt) < 0) {
+            fprintf(stderr, "Failed to add service: %s\n", avahi_strerror(avahi_client_errno(client)));
+            return -1;
+        }
+
+        for (i = config->subtypes; i; i = i->next)
+            if (avahi_entry_group_add_service_subtype(entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, config->name, config->stype, config->domain, (char*) i->text) < 0) {
+                fprintf(stderr, "Failed to add subtype '%s': %s\n", i->text, avahi_strerror(avahi_client_errno(client)));
+                return -1;
+            }
+    }
+
+    avahi_entry_group_commit(entry_group);
+
+    return 0;
+}
+
+static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
+    Config *config = userdata;
+    
+    client = c;
+    
+    switch (state) {
+        case AVAHI_CLIENT_FAILURE:
+
+            if (config->no_fail && avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) {
+                int error;
+
+                /* We have been disconnected, so let reconnect */
+
+                fprintf(stderr, "Disconnected, reconnecting ...\n");
+
+                avahi_client_free(client);
+                client = NULL;
+                entry_group = NULL;
+
+                if (!(client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL, client_callback, config, &error))) {
+                    fprintf(stderr, "Failed to create client object: %s\n", avahi_strerror(error));
+                    avahi_simple_poll_quit(simple_poll);
+                }
+
+            } else {
+                fprintf(stderr, "Client failure, exiting: %s\n", avahi_strerror(avahi_client_errno(c)));
+                avahi_simple_poll_quit(simple_poll);
+            }
+
+            break;
+            
+        case AVAHI_CLIENT_S_RUNNING:
+
+            if (register_stuff(config) < 0)
+                avahi_simple_poll_quit(simple_poll);
+            
+            break;
+
+        case AVAHI_CLIENT_S_COLLISION:
+
+            if (config->verbose)
+                fprintf(stderr, "Host name conflict\n");
+            
+            if (entry_group) {
+                avahi_entry_group_free(entry_group);
+                entry_group = NULL;
+            }
+            break;
+            
+        case AVAHI_CLIENT_CONNECTING:
+            
+            if (config->verbose)
+                fprintf(stderr, "Waiting for daemon ...\n");
+            break;
+            
+        case AVAHI_CLIENT_S_REGISTERING:
+            ;
+    }
+}
+
+static void help(FILE *f, const char *argv0) {
+    fprintf(f,
+            "%s [options] %s <name> <type> <port> [<txt ...>]\n"
+            "%s [options] %s <host-name> <address>\n\n"
+            "    -h --help            Show this help\n"
+            "    -V --version         Show version\n"
+            "    -s --service         Publish service\n"
+            "    -a --address         Publish address\n"
+            "    -v --verbose         Enable verbose mode\n"
+            "    -d --domain=DOMAIN   Domain to publish service in\n"
+            "    -H --host=DOMAIN     Host where service resides\n"
+            "       --subtype=SUBTYPE An additional subtype to register this service with\n"
+            "    -f --no-fail         Don't fail if the daemon is not available\n",
+            argv0, strstr(argv0, "address") ? "[-a]" : "-a",
+            argv0, strstr(argv0, "service") ? "[-s]" : "-s");
+}
+
+static int parse_command_line(Config *c, const char *argv0, int argc, char *argv[]) {
+    int o;
+
+    enum {
+        ARG_SUBTYPE = 256
+    };
+    
+    static const struct option long_options[] = {
+        { "help",           no_argument,       NULL, 'h' },
+        { "version",        no_argument,       NULL, 'V' },
+        { "service",        no_argument,       NULL, 's' },
+        { "address",        no_argument,       NULL, 'a' },
+        { "verbose",        no_argument,       NULL, 'v' },
+        { "domain",         required_argument, NULL, 'd' },
+        { "host",           required_argument, NULL, 'H' },
+        { "subtype",        required_argument, NULL, ARG_SUBTYPE},
+        { "no-fail",        no_argument,       NULL, 'f' },
+        { NULL, 0, NULL, 0 }
+    };
+
+    assert(c);
+
+    c->command = strstr(argv0, "address") ? COMMAND_PUBLISH_ADDRESS : (strstr(argv0, "service") ? COMMAND_PUBLISH_SERVICE : COMMAND_UNSPEC);
+    c->verbose = c->no_fail = 0;
+    c->host = c->name = c->domain = c->stype = NULL;
+    c->port = 0;
+    c->txt = c->subtypes = NULL;
+
+    opterr = 0;
+    while ((o = getopt_long(argc, argv, "hVsavd:H:f", long_options, NULL)) >= 0) {
+
+        switch(o) {
+            case 'h':
+                c->command = COMMAND_HELP;
+                break;
+            case 'V':
+                c->command = COMMAND_VERSION;
+                break;
+            case 's':
+                c->command = COMMAND_PUBLISH_SERVICE;
+                break;
+            case 'a':
+                c->command = COMMAND_PUBLISH_ADDRESS;
+                break;
+            case 'v':
+                c->verbose = 1;
+                break;
+            case 'd':
+                avahi_free(c->domain);
+                c->domain = avahi_strdup(optarg);
+                break;
+            case 'H':
+                avahi_free(c->host);
+                c->host = avahi_strdup(optarg);
+                break;
+            case 'f':
+                c->no_fail = 1;
+                break;
+            case ARG_SUBTYPE:
+                c->subtypes = avahi_string_list_add(c->subtypes, optarg);
+                break;
+            default:
+                fprintf(stderr, "Invalid command line argument: %c\n", o);
+                return -1;
+        }
+    }
+
+    if (c->command == COMMAND_PUBLISH_ADDRESS) {
+        if (optind+2 !=  argc) {
+            fprintf(stderr, "Bad number of arguments\n");
+            return -1;
+        }
+
+        avahi_free(c->name);
+        c->name = avahi_strdup(argv[optind]);
+        avahi_address_parse(argv[optind+1], AVAHI_PROTO_UNSPEC, &c->address);
+        
+    } else if (c->command == COMMAND_PUBLISH_SERVICE) {
+
+        char *e;
+        long int p;
+        int i;
+        
+        if (optind+3 > argc) {
+            fprintf(stderr, "Bad number of arguments\n");
+            return -1;
+        }
+
+        c->name = avahi_strdup(argv[optind]);
+        c->stype = avahi_strdup(argv[optind+1]);
+
+        errno = 0;
+        p = strtol(argv[optind+2], &e, 0);
+
+        if (errno != 0 || *e || p < 0 || p > 0xFFFF) {
+            fprintf(stderr, "Failed to parse port number: %s\n", argv[optind+2]);
+            return -1;
+        }
+            
+        for (i = optind+3; i < argc; i++)
+            c->txt = avahi_string_list_add(c->txt, argv[i]);
+    }
+        
+    return 0;
+}
+
+int main(int argc, char *argv[]) {
+    int ret = 1, error;
+    Config config;
+    const char *argv0;
+
+    if ((argv0 = strrchr(argv[0], '/')))
+        argv0++;
+    else
+        argv0 = argv[0];
+
+    if (parse_command_line(&config, argv0, argc, argv) < 0)
+        goto fail;
+
+    switch (config.command) {
+        case COMMAND_UNSPEC:
+            ret = 1;
+            fprintf(stderr, "No command specified.\n");
+            break;
+            
+        case COMMAND_HELP:
+            help(stdout, argv0);
+            ret = 0;
+            break;
+            
+        case COMMAND_VERSION:
+            printf("%s "PACKAGE_VERSION"\n", argv0);
+            ret = 0;
+            break;
+
+        case COMMAND_PUBLISH_SERVICE:
+        case COMMAND_PUBLISH_ADDRESS:
+            
+            if (!(simple_poll = avahi_simple_poll_new())) {
+                fprintf(stderr, "Failed to create simple poll object.\n");
+                goto fail;
+            }
+            
+            if (sigint_install(simple_poll) < 0)
+                goto fail;
+            
+            if (!(client = avahi_client_new(avahi_simple_poll_get(simple_poll), config.no_fail ? AVAHI_CLIENT_NO_FAIL : 0, client_callback, &config, &error))) {
+                fprintf(stderr, "Failed to create client object: %s\n", avahi_strerror(error));
+                goto fail;
+            }
+
+            if (avahi_client_get_state(client) != AVAHI_CLIENT_CONNECTING && config.verbose) {
+                const char *version, *hn;
+
+                if (!(version = avahi_client_get_version_string(client))) {
+                    fprintf(stderr, "Failed to query version string: %s\n", avahi_strerror(avahi_client_errno(client)));
+                    goto fail;
+                }
+
+                if (!(hn = avahi_client_get_host_name_fqdn(client))) {
+                    fprintf(stderr, "Failed to query host name: %s\n", avahi_strerror(avahi_client_errno(client)));
+                    goto fail;
+                }
+                
+                fprintf(stderr, "Server version: %s; Host name: %s\n", version, hn);
+            }
+
+            avahi_simple_poll_loop(simple_poll);
+            ret = 0;
+            break;
+    }
+    
+fail:
+
+    if (client)
+        avahi_client_free(client);
+
+    sigint_uninstall();
+    
+    if (simple_poll)
+        avahi_simple_poll_free(simple_poll);
+
+    avahi_free(config.host);
+    avahi_free(config.name);
+    avahi_free(config.stype);
+    avahi_free(config.domain);
+    avahi_string_list_free(config.subtypes);
+    avahi_string_list_free(config.txt);
+
+    return ret;
+}
index 477a4a57ae4c09d15550e1f12f393702bd863bea..2dafbf07e796c4d0ad8402063074e3637effd7d1 100644 (file)
@@ -167,8 +167,7 @@ static void help(FILE *f, const char *argv0) {
             "    -a --address         Resolve address\n"
             "    -v --verbose         Enable verbose mode\n"
             "    -6                   Lookup IPv6 address\n"
             "    -a --address         Resolve address\n"
             "    -v --verbose         Enable verbose mode\n"
             "    -6                   Lookup IPv6 address\n"
-            "    -4                   Lookup IPv4 address\n"
-            ,
+            "    -4                   Lookup IPv4 address\n",
             argv0, strstr(argv0, "address") ? "[-a]" : "-a",
             argv0, strstr(argv0, "host-name") ? "[-n]" : "-n");
 }
             argv0, strstr(argv0, "address") ? "[-a]" : "-a",
             argv0, strstr(argv0, "host-name") ? "[-n]" : "-n");
 }