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