]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/sysctl.c
76ce9d864067f196f29e6c3327215d5a6cfe8d39
[thirdparty/systemd.git] / src / sysctl.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 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>
26 #include <stdio.h>
27 #include <limits.h>
28
29 #include "log.h"
30 #include "strv.h"
31 #include "util.h"
32
33 #define PROC_SYS_PREFIX "/proc/sys/"
34
35 static int apply_sysctl(const char *property, const char *value) {
36 char *p, *n;
37 int r = 0, k;
38
39 log_debug("Setting '%s' to '%s'", property, value);
40
41 if (!(p = new(char, sizeof(PROC_SYS_PREFIX) + strlen(property)))) {
42 log_error("Out of memory");
43 return -ENOMEM;
44 }
45
46 n = stpcpy(p, PROC_SYS_PREFIX);
47 strcpy(n, property);
48
49 for (; *n; n++)
50 if (*n == '.')
51 *n = '/';
52
53 if ((k = write_one_line_file(p, value)) < 0) {
54
55 log_full(k == -ENOENT ? LOG_DEBUG : LOG_WARNING,
56 "Failed to write '%s' to '%s': %s", value, p, strerror(-k));
57
58 if (k != -ENOENT && r == 0)
59 r = k;
60 }
61
62 free(p);
63
64 return r;
65 }
66
67 static int apply_file(const char *path, bool ignore_enoent) {
68 FILE *f;
69 int r = 0;
70
71 assert(path);
72
73 if (!(f = fopen(path, "re"))) {
74 if (ignore_enoent && errno == ENOENT)
75 return 0;
76
77 log_error("Failed to open file '%s', ignoring: %m", path);
78 return -errno;
79 }
80
81 log_debug("apply: %s\n", path);
82 while (!feof(f)) {
83 char l[LINE_MAX], *p, *value;
84 int k;
85
86 if (!fgets(l, sizeof(l), f)) {
87 if (feof(f))
88 break;
89
90 log_error("Failed to read file '%s', ignoring: %m", path);
91 r = -errno;
92 goto finish;
93 }
94
95 p = strstrip(l);
96
97 if (!*p)
98 continue;
99
100 if (strchr(COMMENTS, *p))
101 continue;
102
103 if (!(value = strchr(p, '='))) {
104 log_error("Line is not an assignment in file '%s': %s", path, value);
105
106 if (r == 0)
107 r = -EINVAL;
108 continue;
109 }
110
111 *value = 0;
112 value++;
113
114 if ((k = apply_sysctl(strstrip(p), strstrip(value))) < 0 && r == 0)
115 r = k;
116 }
117
118 finish:
119 fclose(f);
120
121 return r;
122 }
123
124 int main(int argc, char *argv[]) {
125 int r = 0;
126
127 if (argc > 2) {
128 log_error("This program expects one or no arguments.");
129 return EXIT_FAILURE;
130 }
131
132 log_set_target(LOG_TARGET_AUTO);
133 log_parse_environment();
134 log_open();
135
136 if (argc > 1)
137 r = apply_file(argv[1], false);
138 else {
139 char **files, **f;
140
141
142 r = conf_files_list(&files, ".conf",
143 "/run/sysctl.d",
144 "/etc/sysctl.d",
145 "/usr/local/lib/sysctl.d",
146 "/usr/lib/sysctl.d",
147 "/lib/sysctl.d",
148 NULL);
149 if (r < 0) {
150 log_error("Failed to enumerate sysctl.d files: %s", strerror(-r));
151 goto finish;
152 }
153
154 STRV_FOREACH(f, files) {
155 int k;
156
157 k = apply_file(*f, true);
158 if (k < 0 && r == 0)
159 r = k;
160 }
161
162 apply_file("/etc/sysctl.conf", true);
163
164 strv_free(files);
165 }
166 finish:
167 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
168 }