chiark / gitweb /
macro: introduce _cleanup_free_ macro for automatic freeing of scoped vars and make...
[elogind.git] / src / core / hostname-setup.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 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 <unistd.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "hostname-setup.h"
29 #include "macro.h"
30 #include "util.h"
31 #include "log.h"
32
33 #if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
34 #define FILENAME "/etc/sysconfig/network"
35 #elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
36 #define FILENAME "/etc/HOSTNAME"
37 #elif defined(TARGET_ARCH)
38 #define FILENAME "/etc/rc.conf"
39 #elif defined(TARGET_GENTOO)
40 #define FILENAME "/etc/conf.d/hostname"
41 #endif
42
43 static int read_and_strip_hostname(const char *path, char **hn) {
44         char *s;
45         int r;
46
47         assert(path);
48         assert(hn);
49
50         r = read_one_line_file(path, &s);
51         if (r < 0)
52                 return r;
53
54         hostname_cleanup(s);
55
56         if (isempty(s)) {
57                 free(s);
58                 return -ENOENT;
59         }
60
61         *hn = s;
62
63         return 0;
64 }
65
66 static int read_distro_hostname(char **hn) {
67
68 #if defined(TARGET_FEDORA) || defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
69         int r;
70         _cleanup_fclose_ FILE *f = NULL;
71
72         assert(hn);
73
74         f = fopen(FILENAME, "re");
75         if (!f)
76                 return -errno;
77
78         for (;;) {
79                 char line[LINE_MAX];
80                 char *s, *k;
81
82                 if (!fgets(line, sizeof(line), f)) {
83                         if (feof(f))
84                                 break;
85
86                         r = -errno;
87                         goto finish;
88                 }
89
90                 s = strstrip(line);
91
92                 if (!startswith_no_case(s, "HOSTNAME="))
93                         continue;
94
95                 k = strdup(s+9);
96                 if (!k) {
97                         r = -ENOMEM;
98                         goto finish;
99                 }
100
101                 hostname_cleanup(k);
102
103                 if (isempty(k)) {
104                         free(k);
105                         r = -ENOENT;
106                         goto finish;
107                 }
108
109                 *hn = k;
110                 r = 0;
111                 goto finish;
112         }
113
114         r = -ENOENT;
115
116 finish:
117         return r;
118
119 #elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
120         return read_and_strip_hostname(FILENAME, hn);
121 #else
122         return -ENOENT;
123 #endif
124 }
125
126 static int read_hostname(char **hn) {
127         int r;
128
129         assert(hn);
130
131         /* First, try to load the generic hostname configuration file,
132          * that we support on all distributions */
133
134         r = read_and_strip_hostname("/etc/hostname", hn);
135         if (r < 0) {
136                 if (r == -ENOENT)
137                         return read_distro_hostname(hn);
138
139                 return r;
140         }
141
142         return 0;
143 }
144
145 int hostname_setup(void) {
146         int r;
147         char *b = NULL;
148         const char *hn = NULL;
149         bool enoent = false;
150
151         r = read_hostname(&b);
152         if (r < 0) {
153                 hn = NULL;
154
155                 if (r == -ENOENT)
156                         enoent = true;
157                 else
158                         log_warning("Failed to read configured hostname: %s", strerror(-r));
159         } else
160                 hn = b;
161
162         if (isempty(hn)) {
163                 /* Don't override the hostname if it is already set
164                  * and not explicitly configured */
165                 if (hostname_is_set())
166                         goto finish;
167
168                 if (enoent)
169                         log_info("No hostname configured.");
170
171                 hn = "localhost";
172         }
173
174         if (sethostname(hn, strlen(hn)) < 0) {
175                 log_warning("Failed to set hostname to <%s>: %m", hn);
176                 r = -errno;
177         } else
178                 log_info("Set hostname to <%s>.", hn);
179
180 finish:
181         free(b);
182
183         return r;
184 }