1/***
2  This file is part of avahi.
3
4  avahi is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) any later version.
8
9  avahi is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12  Public License for more details.
13
14  You should have received a copy of the GNU Lesser General Public
15  License along with avahi; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  USA.
18***/
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <unistd.h>
28#include <ctype.h>
29#include <sys/utsname.h>
30#include <stdio.h>
31
32#include <avahi-common/malloc.h>
33
34#include "log.h"
35#include "domain-util.h"
36#include "util.h"
37
38static void strip_bad_chars(char *s) {
39    char *p, *d;
40
41    s[strcspn(s, ".")] = 0;
42
43    for (p = s, d = s; *p; p++)
44        if ((*p >= 'a' && *p <= 'z') ||
45            (*p >= 'A' && *p <= 'Z') ||
46            (*p >= '0' && *p <= '9') ||
47            *p == '-')
48            *(d++) = *p;
49
50    *d = 0;
51}
52
53#ifdef __linux__
54static int load_lsb_distrib_id(char *ret_s, size_t size) {
55    FILE *f;
56
57    assert(ret_s);
58    assert(size > 0);
59
60    if (!(f = fopen("/etc/lsb-release", "r")))
61        return -1;
62
63    while (!feof(f)) {
64        char ln[256], *p;
65
66        if (!fgets(ln, sizeof(ln), f))
67            break;
68
69        if (strncmp(ln, "DISTRIB_ID=", 11))
70            continue;
71
72        p = ln + 11;
73        p += strspn(p, "\"");
74        p[strcspn(p, "\"")] = 0;
75
76        snprintf(ret_s, size, "%s", p);
77
78        fclose(f);
79        return 0;
80    }
81
82    fclose(f);
83    return -1;
84}
85#endif
86
87char *avahi_get_host_name(char *ret_s, size_t size) {
88    assert(ret_s);
89    assert(size > 0);
90
91    if (gethostname(ret_s, size) >= 0) {
92        ret_s[size-1] = 0;
93        strip_bad_chars(ret_s);
94    } else
95        *ret_s = 0;
96
97    if (strcmp(ret_s, "localhost") == 0 || strncmp(ret_s, "localhost.", 10) == 0) {
98        *ret_s = 0;
99        avahi_log_warn("System host name is set to 'localhost'. This is not a suitable mDNS host name, looking for alternatives.");
100    }
101
102    if (*ret_s == 0) {
103        /* No hostname was set, so let's take the OS name */
104
105#ifdef __linux__
106
107        /* Try LSB distribution name first */
108        if (load_lsb_distrib_id(ret_s, size) >= 0) {
109            strip_bad_chars(ret_s);
110            avahi_strdown(ret_s);
111        }
112
113        if (*ret_s == 0)
114#endif
115
116        {
117            /* Try uname() second */
118            struct utsname utsname;
119
120            if (uname(&utsname) >= 0) {
121                snprintf(ret_s, size, "%s", utsname.sysname);
122                strip_bad_chars(ret_s);
123                avahi_strdown(ret_s);
124            }
125
126            /* Give up */
127            if (*ret_s == 0)
128                snprintf(ret_s, size, "unnamed");
129        }
130    }
131
132    if (size >= AVAHI_LABEL_MAX)
133	ret_s[AVAHI_LABEL_MAX-1] = 0;
134
135    return ret_s;
136}
137
138char *avahi_get_host_name_strdup(void) {
139    char t[AVAHI_DOMAIN_NAME_MAX];
140
141    if (!(avahi_get_host_name(t, sizeof(t))))
142        return NULL;
143
144    return avahi_strdup(t);
145}
146
147int avahi_binary_domain_cmp(const char *a, const char *b) {
148    assert(a);
149    assert(b);
150
151    if (a == b)
152        return 0;
153
154    for (;;) {
155        char ca[AVAHI_LABEL_MAX], cb[AVAHI_LABEL_MAX], *p;
156        int r;
157
158        p = avahi_unescape_label(&a, ca, sizeof(ca));
159        assert(p);
160        p = avahi_unescape_label(&b, cb, sizeof(cb));
161        assert(p);
162
163        if ((r = strcmp(ca, cb)))
164            return r;
165
166        if (!*a && !*b)
167            return 0;
168    }
169}
170
171int avahi_domain_ends_with(const char *domain, const char *suffix) {
172    assert(domain);
173    assert(suffix);
174
175    for (;;) {
176        char dummy[AVAHI_LABEL_MAX], *r;
177
178        if (*domain == 0)
179            return 0;
180
181        if (avahi_domain_equal(domain, suffix))
182            return 1;
183
184        r = avahi_unescape_label(&domain, dummy, sizeof(dummy));
185        assert(r);
186    }
187}
188
189