]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hostname-util.c
hostname-util: get rid of unused parameter of hostname_cleanup()
[thirdparty/systemd.git] / src / basic / hostname-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/utsname.h>
23 #include <ctype.h>
24
25 #include "util.h"
26 #include "hostname-util.h"
27
28 bool hostname_is_set(void) {
29 struct utsname u;
30
31 assert_se(uname(&u) >= 0);
32
33 if (isempty(u.nodename))
34 return false;
35
36 /* This is the built-in kernel default host name */
37 if (streq(u.nodename, "(none)"))
38 return false;
39
40 return true;
41 }
42
43 char* gethostname_malloc(void) {
44 struct utsname u;
45
46 assert_se(uname(&u) >= 0);
47
48 if (isempty(u.nodename) || streq(u.nodename, "(none)"))
49 return strdup(u.sysname);
50
51 return strdup(u.nodename);
52 }
53
54 static bool hostname_valid_char(char c) {
55 return
56 (c >= 'a' && c <= 'z') ||
57 (c >= 'A' && c <= 'Z') ||
58 (c >= '0' && c <= '9') ||
59 c == '-' ||
60 c == '_' ||
61 c == '.';
62 }
63
64 /**
65 * Check if s looks like a valid host name or fqdn. This does not do
66 * full DNS validation, but only checks if the name is composed of
67 * allowed characters and the length is not above the maximum allowed
68 * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
69 * relax is true and at least two components are present in the name.
70 */
71 bool hostname_is_valid(const char *s, bool relax) {
72 const char *p;
73 bool dot;
74 unsigned dots = 0;
75
76 if (isempty(s))
77 return false;
78
79 /* Doesn't accept empty hostnames, hostnames with
80 * leading dots, and hostnames with multiple dots in a
81 * sequence. Also ensures that the length stays below
82 * HOST_NAME_MAX. */
83
84 for (p = s, dot = true; *p; p++) {
85 if (*p == '.') {
86 if (dot)
87 return false;
88
89 dot = true;
90 dots ++;
91 } else {
92 if (!hostname_valid_char(*p))
93 return false;
94
95 dot = false;
96 }
97 }
98
99 if (dot && (dots < 2 || !relax))
100 return false;
101
102 if (p-s > HOST_NAME_MAX)
103 return false;
104
105 return true;
106 }
107
108 char* hostname_cleanup(char *s) {
109 char *p, *d;
110 bool dot;
111
112 assert(s);
113
114 for (p = s, d = s, dot = true; *p; p++) {
115 if (*p == '.') {
116 if (dot)
117 continue;
118
119 *(d++) = '.';
120 dot = true;
121 } else if (hostname_valid_char(*p)) {
122 *(d++) = *p;
123 dot = false;
124 }
125
126 }
127
128 if (dot && d > s)
129 d[-1] = 0;
130 else
131 *d = 0;
132
133 strshorten(s, HOST_NAME_MAX);
134
135 return s;
136 }
137
138 bool is_localhost(const char *hostname) {
139 assert(hostname);
140
141 /* This tries to identify local host and domain names
142 * described in RFC6761 plus the redhatism of .localdomain */
143
144 return streq(hostname, "localhost") ||
145 streq(hostname, "localhost.") ||
146 streq(hostname, "localdomain.") ||
147 streq(hostname, "localdomain") ||
148 endswith(hostname, ".localhost") ||
149 endswith(hostname, ".localhost.") ||
150 endswith(hostname, ".localdomain") ||
151 endswith(hostname, ".localdomain.");
152 }
153
154 int sethostname_idempotent(const char *s) {
155 char buf[HOST_NAME_MAX + 1] = {};
156
157 assert(s);
158
159 if (gethostname(buf, sizeof(buf)) < 0)
160 return -errno;
161
162 if (streq(buf, s))
163 return 0;
164
165 if (sethostname(s, strlen(s)) < 0)
166 return -errno;
167
168 return 1;
169 }
170
171 int read_hostname_config(const char *path, char **hostname) {
172 _cleanup_fclose_ FILE *f = NULL;
173 char l[LINE_MAX];
174 char *name = NULL;
175
176 assert(path);
177 assert(hostname);
178
179 f = fopen(path, "re");
180 if (!f)
181 return -errno;
182
183 /* may have comments, ignore them */
184 FOREACH_LINE(l, f, return -errno) {
185 truncate_nl(l);
186 if (l[0] != '\0' && l[0] != '#') {
187 /* found line with value */
188 name = hostname_cleanup(l);
189 name = strdup(name);
190 if (!name)
191 return -ENOMEM;
192 break;
193 }
194 }
195
196 if (!name)
197 /* no non-empty line found */
198 return -ENOENT;
199
200 *hostname = name;
201 return 0;
202 }