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