]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sysctl/sysctl.c
man: remove "wine" from unrelated man pages
[thirdparty/systemd.git] / src / sysctl / sysctl.c
CommitLineData
8e1bd70d
LP
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
5430f7f2
LP
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
8e1bd70d
LP
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
5430f7f2 16 Lesser General Public License for more details.
8e1bd70d 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
8e1bd70d
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <stdlib.h>
23#include <stdbool.h>
24#include <errno.h>
25#include <string.h>
8e1bd70d
LP
26#include <stdio.h>
27#include <limits.h>
7a2a0b90 28#include <getopt.h>
8e1bd70d
LP
29
30#include "log.h"
db1413d7 31#include "strv.h"
8e1bd70d 32#include "util.h"
f68c5a70 33#include "strv.h"
86fc77c4 34#include "hashmap.h"
9eb977db 35#include "path-util.h"
2c21044f 36#include "conf-files.h"
a5c32cff 37#include "fileio.h"
8e1bd70d 38
fabe5c0e 39static char **arg_prefixes = NULL;
8e1bd70d 40
fabe5c0e
LP
41static const char conf_file_dirs[] =
42 "/etc/sysctl.d\0"
43 "/run/sysctl.d\0"
44 "/usr/local/lib/sysctl.d\0"
45 "/usr/lib/sysctl.d\0"
46#ifdef HAVE_SPLIT_USR
47 "/lib/sysctl.d\0"
48#endif
49 ;
50
51static char *normalize_sysctl(char *s) {
52 char *n;
53
54 for (n = s; *n; n++)
55 if (*n == '.')
56 *n = '/';
57
58 return s;
59}
7a2a0b90 60
c1b664d0 61static int apply_sysctl(const char *property, const char *value) {
fabe5c0e
LP
62 _cleanup_free_ char *p = NULL;
63 char *n;
c1b664d0 64 int r = 0, k;
8e1bd70d
LP
65
66 log_debug("Setting '%s' to '%s'", property, value);
67
fabe5c0e 68 p = new(char, sizeof("/proc/sys/") + strlen(property));
0d0f0c50
SL
69 if (!p)
70 return log_oom();
8e1bd70d 71
fabe5c0e 72 n = stpcpy(p, "/proc/sys/");
8e1bd70d
LP
73 strcpy(n, property);
74
f68c5a70
LP
75 if (!strv_isempty(arg_prefixes)) {
76 char **i;
77 bool good = false;
78
79 STRV_FOREACH(i, arg_prefixes)
80 if (path_startswith(p, *i)) {
81 good = true;
82 break;
83 }
84
85 if (!good) {
86 log_debug("Skipping %s", p);
f68c5a70
LP
87 return 0;
88 }
7a2a0b90
LP
89 }
90
574d5f2d 91 k = write_string_file(p, value);
7a2a0b90 92 if (k < 0) {
c1b664d0
LP
93 log_full(k == -ENOENT ? LOG_DEBUG : LOG_WARNING,
94 "Failed to write '%s' to '%s': %s", value, p, strerror(-k));
24a35973 95
c1b664d0
LP
96 if (k != -ENOENT && r == 0)
97 r = k;
8e1bd70d
LP
98 }
99
c1b664d0 100 return r;
8e1bd70d
LP
101}
102
fabe5c0e 103static int apply_all(Hashmap *sysctl_options) {
86fc77c4
MS
104 int r = 0;
105 char *property, *value;
106 Iterator i;
107
fabe5c0e
LP
108 assert(sysctl_options);
109
86fc77c4
MS
110 HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) {
111 int k;
112
113 k = apply_sysctl(property, value);
114 if (k < 0 && r == 0)
115 r = k;
116 }
117 return r;
118}
119
fabe5c0e
LP
120static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_enoent) {
121 _cleanup_fclose_ FILE *f = NULL;
122 int r;
8e1bd70d
LP
123
124 assert(path);
125
fabe5c0e
LP
126 r = search_and_fopen_nulstr(path, "re", conf_file_dirs, &f);
127 if (r < 0) {
6f6fad96 128 if (ignore_enoent && r == -ENOENT)
c1b664d0
LP
129 return 0;
130
fabe5c0e
LP
131 log_error("Failed to open file '%s', ignoring: %s", path, strerror(-r));
132 return r;
8e1bd70d
LP
133 }
134
86fc77c4 135 log_debug("parse: %s\n", path);
8e1bd70d 136 while (!feof(f)) {
fabe5c0e
LP
137 char l[LINE_MAX], *p, *value, *new_value, *property, *existing;
138 int k;
8e1bd70d
LP
139
140 if (!fgets(l, sizeof(l), f)) {
141 if (feof(f))
142 break;
143
144 log_error("Failed to read file '%s', ignoring: %m", path);
fabe5c0e 145 return -errno;
8e1bd70d
LP
146 }
147
148 p = strstrip(l);
8e1bd70d
LP
149 if (!*p)
150 continue;
151
d3b6d0c2 152 if (strchr(COMMENTS "\n", *p))
8e1bd70d
LP
153 continue;
154
86fc77c4
MS
155 value = strchr(p, '=');
156 if (!value) {
8e1bd70d 157 log_error("Line is not an assignment in file '%s': %s", path, value);
c1b664d0
LP
158
159 if (r == 0)
160 r = -EINVAL;
8e1bd70d
LP
161 continue;
162 }
163
164 *value = 0;
165 value++;
166
fabe5c0e
LP
167 p = normalize_sysctl(strstrip(p));
168 value = strstrip(value);
169
170 existing = hashmap_get(sysctl_options, p);
171 if (existing) {
172 if (!streq(value, existing))
f04e95ba
ZJS
173 log_warning("Duplicate assignment of %s in file '%s', ignoring.",
174 p, path);
fabe5c0e
LP
175
176 continue;
86fc77c4
MS
177 }
178
fabe5c0e
LP
179 property = strdup(p);
180 if (!property)
181 return log_oom();
182
183 new_value = strdup(value);
86fc77c4
MS
184 if (!new_value) {
185 free(property);
fabe5c0e 186 return log_oom();
86fc77c4
MS
187 }
188
fabe5c0e
LP
189 k = hashmap_put(sysctl_options, property, new_value);
190 if (k < 0) {
191 log_error("Failed to add sysctl variable %s to hashmap: %s", property, strerror(-r));
86fc77c4
MS
192 free(property);
193 free(new_value);
fabe5c0e 194 return k;
86fc77c4 195 }
8e1bd70d
LP
196 }
197
c1b664d0 198 return r;
8e1bd70d
LP
199}
200
7a2a0b90
LP
201static int help(void) {
202
203 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
204 "Applies kernel sysctl settings.\n\n"
205 " -h --help Show this help\n"
206 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
207 program_invocation_short_name);
208
209 return 0;
210}
211
212static int parse_argv(int argc, char *argv[]) {
213
214 enum {
215 ARG_PREFIX
216 };
217
218 static const struct option options[] = {
219 { "help", no_argument, NULL, 'h' },
220 { "prefix", required_argument, NULL, ARG_PREFIX },
221 { NULL, 0, NULL, 0 }
222 };
223
224 int c;
225
226 assert(argc >= 0);
227 assert(argv);
228
229 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
230
231 switch (c) {
232
233 case 'h':
234 help();
235 return 0;
236
237 case ARG_PREFIX: {
238 char *p;
f68c5a70 239 char **l;
7a2a0b90
LP
240
241 for (p = optarg; *p; p++)
242 if (*p == '.')
243 *p = '/';
244
f68c5a70 245 l = strv_append(arg_prefixes, optarg);
0d0f0c50
SL
246 if (!l)
247 return log_oom();
f68c5a70
LP
248
249 strv_free(arg_prefixes);
250 arg_prefixes = l;
7a2a0b90
LP
251
252 break;
253 }
254
255 case '?':
256 return -EINVAL;
257
258 default:
259 log_error("Unknown option code %c", c);
260 return -EINVAL;
261 }
262 }
263
264 return 1;
265}
266
8e1bd70d 267int main(int argc, char *argv[]) {
0187f62b 268 int r = 0, k;
fabe5c0e 269 Hashmap *sysctl_options;
8e1bd70d 270
7a2a0b90
LP
271 r = parse_argv(argc, argv);
272 if (r <= 0)
273 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
274
8e1bd70d
LP
275 log_set_target(LOG_TARGET_AUTO);
276 log_parse_environment();
277 log_open();
278
4c12626c
LP
279 umask(0022);
280
86fc77c4
MS
281 sysctl_options = hashmap_new(string_hash_func, string_compare_func);
282 if (!sysctl_options) {
283 r = log_oom();
284 goto finish;
285 }
286
0187f62b
LP
287 r = 0;
288
de19ece7
LP
289 if (argc > optind) {
290 int i;
291
292 for (i = optind; i < argc; i++) {
fabe5c0e
LP
293 k = parse_file(sysctl_options, argv[i], false);
294 if (k < 0 && r == 0)
de19ece7
LP
295 r = k;
296 }
297 } else {
fabe5c0e
LP
298 _cleanup_strv_free_ char **files = NULL;
299 char **f;
c1b664d0 300
fabe5c0e 301 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
44143309
KS
302 if (r < 0) {
303 log_error("Failed to enumerate sysctl.d files: %s", strerror(-r));
304 goto finish;
305 }
db1413d7 306
fabe5c0e 307 r = parse_file(sysctl_options, "/etc/sysctl.conf", true);
86fc77c4 308
fabe5c0e
LP
309 STRV_FOREACH(f, files) {
310 k = parse_file(sysctl_options, *f, true);
311 if (k < 0 && r == 0)
db1413d7
KS
312 r = k;
313 }
8e1bd70d 314 }
86fc77c4 315
fabe5c0e
LP
316 k = apply_all(sysctl_options);
317 if (k < 0 && r == 0)
0187f62b
LP
318 r = k;
319
44143309 320finish:
fabe5c0e 321 hashmap_free_free_free(sysctl_options);
f68c5a70
LP
322 strv_free(arg_prefixes);
323
c1b664d0 324 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
8e1bd70d 325}