]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sysctl/sysctl.c
update TODO
[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"
9eb977db 34#include "path-util.h"
2c21044f 35#include "conf-files.h"
8e1bd70d
LP
36
37#define PROC_SYS_PREFIX "/proc/sys/"
38
f68c5a70 39static char **arg_prefixes = NULL;
7a2a0b90 40
c1b664d0 41static int apply_sysctl(const char *property, const char *value) {
8e1bd70d 42 char *p, *n;
c1b664d0 43 int r = 0, k;
8e1bd70d
LP
44
45 log_debug("Setting '%s' to '%s'", property, value);
46
7a2a0b90
LP
47 p = new(char, sizeof(PROC_SYS_PREFIX) + strlen(property));
48 if (!p) {
669241a0 49 log_error("Out of memory.");
c1b664d0 50 return -ENOMEM;
8e1bd70d
LP
51 }
52
53 n = stpcpy(p, PROC_SYS_PREFIX);
54 strcpy(n, property);
55
56 for (; *n; n++)
57 if (*n == '.')
58 *n = '/';
59
f68c5a70
LP
60 if (!strv_isempty(arg_prefixes)) {
61 char **i;
62 bool good = false;
63
64 STRV_FOREACH(i, arg_prefixes)
65 if (path_startswith(p, *i)) {
66 good = true;
67 break;
68 }
69
70 if (!good) {
71 log_debug("Skipping %s", p);
72 free(p);
73 return 0;
74 }
7a2a0b90
LP
75 }
76
77 k = write_one_line_file(p, value);
78 if (k < 0) {
5707631e 79
c1b664d0
LP
80 log_full(k == -ENOENT ? LOG_DEBUG : LOG_WARNING,
81 "Failed to write '%s' to '%s': %s", value, p, strerror(-k));
24a35973 82
c1b664d0
LP
83 if (k != -ENOENT && r == 0)
84 r = k;
8e1bd70d
LP
85 }
86
87 free(p);
c1b664d0
LP
88
89 return r;
8e1bd70d
LP
90}
91
c1b664d0 92static int apply_file(const char *path, bool ignore_enoent) {
8e1bd70d 93 FILE *f;
c1b664d0 94 int r = 0;
8e1bd70d
LP
95
96 assert(path);
97
98 if (!(f = fopen(path, "re"))) {
c1b664d0
LP
99 if (ignore_enoent && errno == ENOENT)
100 return 0;
101
8e1bd70d 102 log_error("Failed to open file '%s', ignoring: %m", path);
c1b664d0 103 return -errno;
8e1bd70d
LP
104 }
105
db1413d7 106 log_debug("apply: %s\n", path);
8e1bd70d
LP
107 while (!feof(f)) {
108 char l[LINE_MAX], *p, *value;
c1b664d0 109 int k;
8e1bd70d
LP
110
111 if (!fgets(l, sizeof(l), f)) {
112 if (feof(f))
113 break;
114
115 log_error("Failed to read file '%s', ignoring: %m", path);
c1b664d0 116 r = -errno;
8e1bd70d
LP
117 goto finish;
118 }
119
120 p = strstrip(l);
121
122 if (!*p)
123 continue;
124
125 if (strchr(COMMENTS, *p))
126 continue;
127
128 if (!(value = strchr(p, '='))) {
129 log_error("Line is not an assignment in file '%s': %s", path, value);
c1b664d0
LP
130
131 if (r == 0)
132 r = -EINVAL;
8e1bd70d
LP
133 continue;
134 }
135
136 *value = 0;
137 value++;
138
c1b664d0
LP
139 if ((k = apply_sysctl(strstrip(p), strstrip(value))) < 0 && r == 0)
140 r = k;
8e1bd70d
LP
141 }
142
143finish:
144 fclose(f);
c1b664d0
LP
145
146 return r;
8e1bd70d
LP
147}
148
7a2a0b90
LP
149static int help(void) {
150
151 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
152 "Applies kernel sysctl settings.\n\n"
153 " -h --help Show this help\n"
154 " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
155 program_invocation_short_name);
156
157 return 0;
158}
159
160static int parse_argv(int argc, char *argv[]) {
161
162 enum {
163 ARG_PREFIX
164 };
165
166 static const struct option options[] = {
167 { "help", no_argument, NULL, 'h' },
168 { "prefix", required_argument, NULL, ARG_PREFIX },
169 { NULL, 0, NULL, 0 }
170 };
171
172 int c;
173
174 assert(argc >= 0);
175 assert(argv);
176
177 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
178
179 switch (c) {
180
181 case 'h':
182 help();
183 return 0;
184
185 case ARG_PREFIX: {
186 char *p;
f68c5a70 187 char **l;
7a2a0b90
LP
188
189 for (p = optarg; *p; p++)
190 if (*p == '.')
191 *p = '/';
192
f68c5a70
LP
193 l = strv_append(arg_prefixes, optarg);
194 if (!l) {
669241a0 195 log_error("Out of memory.");
f68c5a70
LP
196 return -ENOMEM;
197 }
198
199 strv_free(arg_prefixes);
200 arg_prefixes = l;
7a2a0b90
LP
201
202 break;
203 }
204
205 case '?':
206 return -EINVAL;
207
208 default:
209 log_error("Unknown option code %c", c);
210 return -EINVAL;
211 }
212 }
213
214 return 1;
215}
216
8e1bd70d 217int main(int argc, char *argv[]) {
c1b664d0 218 int r = 0;
8e1bd70d 219
7a2a0b90
LP
220 r = parse_argv(argc, argv);
221 if (r <= 0)
222 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
223
8e1bd70d
LP
224 log_set_target(LOG_TARGET_AUTO);
225 log_parse_environment();
226 log_open();
227
4c12626c
LP
228 umask(0022);
229
de19ece7
LP
230 if (argc > optind) {
231 int i;
232
233 for (i = optind; i < argc; i++) {
234 int k;
235
236 k = apply_file(argv[i], false);
237 if (k < 0 && r == 0)
238 r = k;
239 }
240 } else {
db1413d7 241 char **files, **f;
de19ece7 242 int k;
c1b664d0 243
44143309 244 r = conf_files_list(&files, ".conf",
44143309 245 "/etc/sysctl.d",
fc1a2e06 246 "/run/sysctl.d",
40013ebc 247 "/usr/local/lib/sysctl.d",
44143309 248 "/usr/lib/sysctl.d",
de19ece7 249#ifdef HAVE_SPLIT_USR
223a3558 250 "/lib/sysctl.d",
de19ece7 251#endif
44143309
KS
252 NULL);
253 if (r < 0) {
254 log_error("Failed to enumerate sysctl.d files: %s", strerror(-r));
255 goto finish;
256 }
db1413d7
KS
257
258 STRV_FOREACH(f, files) {
db1413d7
KS
259 k = apply_file(*f, true);
260 if (k < 0 && r == 0)
261 r = k;
262 }
263
de19ece7
LP
264 k = apply_file("/etc/sysctl.conf", true);
265 if (k < 0 && r == 0)
266 r = k;
cb804011 267
db1413d7 268 strv_free(files);
8e1bd70d 269 }
44143309 270finish:
f68c5a70
LP
271 strv_free(arg_prefixes);
272
c1b664d0 273 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
8e1bd70d 274}