1/* $Id$ */
2
3/***
4  This file is part of avahi.
5
6  avahi is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as
8  published by the Free Software Foundation; either version 2.1 of the
9  License, or (at your option) any later version.
10
11  avahi is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14  Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with avahi; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA.
20***/
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <getopt.h>
29#include <assert.h>
30#include <string.h>
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <locale.h>
34
35#include <avahi-common/simple-watch.h>
36#include <avahi-common/error.h>
37#include <avahi-common/malloc.h>
38#include <avahi-common/domain.h>
39#include <avahi-common/i18n.h>
40#include <avahi-client/client.h>
41
42#include "sigint.h"
43
44typedef enum {
45    COMMAND_UNSPEC,
46    COMMAND_HELP,
47    COMMAND_VERSION
48} Command;
49
50typedef struct Config {
51    int verbose;
52    Command command;
53} Config;
54
55static AvahiSimplePoll *simple_poll = NULL;
56static AvahiClient *client = NULL;
57
58static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
59    switch (state) {
60        case AVAHI_CLIENT_FAILURE:
61            fprintf(stderr, _("Client failure, exiting: %s\n"), avahi_strerror(avahi_client_errno(c)));
62            avahi_simple_poll_quit(simple_poll);
63            break;
64
65        case AVAHI_CLIENT_S_REGISTERING:
66        case AVAHI_CLIENT_S_RUNNING:
67        case AVAHI_CLIENT_S_COLLISION:
68        case AVAHI_CLIENT_CONNECTING:
69            ;
70    }
71}
72
73static void help(FILE *f, const char *argv0) {
74    fprintf(f,
75            _("%s [options] <new host name>\n\n"
76              "    -h --help            Show this help\n"
77              "    -V --version         Show version\n"
78              "    -v --verbose         Enable verbose mode\n"),
79            argv0);
80}
81
82static int parse_command_line(Config *c, int argc, char *argv[]) {
83    int o;
84
85    static const struct option long_options[] = {
86        { "help",           no_argument,       NULL, 'h' },
87        { "version",        no_argument,       NULL, 'V' },
88        { "verbose",        no_argument,       NULL, 'v' },
89        { NULL, 0, NULL, 0 }
90    };
91
92    assert(c);
93
94    c->command = COMMAND_UNSPEC;
95    c->verbose = 0;
96
97    while ((o = getopt_long(argc, argv, "hVv", long_options, NULL)) >= 0) {
98
99        switch(o) {
100            case 'h':
101                c->command = COMMAND_HELP;
102                break;
103            case 'V':
104                c->command = COMMAND_VERSION;
105                break;
106            case 'v':
107                c->verbose = 1;
108                break;
109            default:
110                return -1;
111        }
112    }
113
114    if (c->command == COMMAND_UNSPEC) {
115        if (optind != argc-1) {
116            fprintf(stderr, _("Invalid number of arguments, expecting exactly one.\n"));
117            return -1;
118        }
119    }
120
121    return 0;
122}
123
124int main(int argc, char *argv[]) {
125    int ret = 1, error;
126    Config config;
127    const char *argv0;
128
129    avahi_init_i18n();
130    setlocale(LC_ALL, "");
131
132    if ((argv0 = strrchr(argv[0], '/')))
133        argv0++;
134    else
135        argv0 = argv[0];
136
137    if (parse_command_line(&config, argc, argv) < 0)
138        goto fail;
139
140    switch (config.command) {
141        case COMMAND_HELP:
142            help(stdout, argv0);
143            ret = 0;
144            break;
145
146        case COMMAND_VERSION:
147            printf("%s "PACKAGE_VERSION"\n", argv0);
148            ret = 0;
149            break;
150
151        case COMMAND_UNSPEC:
152
153            if (!(simple_poll = avahi_simple_poll_new())) {
154                fprintf(stderr, _("Failed to create simple poll object.\n"));
155                goto fail;
156            }
157
158            if (sigint_install(simple_poll) < 0)
159                goto fail;
160
161            if (!(client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error))) {
162                fprintf(stderr, _("Failed to create client object: %s\n"), avahi_strerror(error));
163                goto fail;
164            }
165
166            if (config.verbose) {
167                const char *version, *hn;
168
169                if (!(version = avahi_client_get_version_string(client))) {
170                    fprintf(stderr, _("Failed to query version string: %s\n"), avahi_strerror(avahi_client_errno(client)));
171                    goto fail;
172                }
173
174                if (!(hn = avahi_client_get_host_name_fqdn(client))) {
175                    fprintf(stderr, _("Failed to query host name: %s\n"), avahi_strerror(avahi_client_errno(client)));
176                    goto fail;
177                }
178
179                fprintf(stderr, _("Server version: %s; Host name: %s\n"), version, hn);
180            }
181
182            if (avahi_client_set_host_name(client, argv[optind]) < 0) {
183                fprintf(stderr, _("Failed to create host name resolver: %s\n"), avahi_strerror(avahi_client_errno(client)));
184                goto fail;
185            }
186
187            if (config.verbose) {
188                const char *hn;
189
190                if (!(hn = avahi_client_get_host_name_fqdn(client))) {
191                    fprintf(stderr, _("Failed to query host name: %s\n"), avahi_strerror(avahi_client_errno(client)));
192                    goto fail;
193                }
194
195                fprintf(stderr, _("Host name successfully changed to %s\n"), hn);
196            }
197
198            ret = 0;
199            break;
200    }
201
202fail:
203
204    if (client)
205        avahi_client_free(client);
206
207    sigint_uninstall();
208
209    if (simple_poll)
210        avahi_simple_poll_free(simple_poll);
211
212    return ret;
213}
214