sysctl.c - ubase - suckless linux base utils
(HTM) git clone git://git.suckless.org/ubase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
sysctl.c (3285B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <fcntl.h>
3 #include <limits.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 #include "text.h"
10 #include "util.h"
11
12 static void
13 replacestr(char *s, int a, int b)
14 {
15 for (; *s; s++)
16 if (*s == a)
17 *s = b;
18 }
19
20 static int
21 getsysctl(char *variable, char **value)
22 {
23 char path[PATH_MAX];
24 char *p;
25 char *buf, *tmp, c;
26 int fd;
27 ssize_t n;
28 size_t sz, i;
29
30 replacestr(variable, '.', '/');
31
32 strlcpy(path, "/proc/sys/", sizeof(path));
33 if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
34 replacestr(variable, '/', '.');
35 return -1;
36 }
37
38 replacestr(variable, '/', '.');
39
40 fd = open(path, O_RDONLY);
41 if (fd < 0)
42 return -1;
43
44 i = 0;
45 sz = 1;
46 buf = NULL;
47 while (1) {
48 n = read(fd, &c, 1);
49 if (n < 0) {
50 close(fd);
51 free(buf);
52 return -1;
53 }
54 if (n == 0)
55 break;
56 if (i == sz - 1) {
57 sz *= 2;
58 tmp = realloc(buf, sz);
59 if (!tmp) {
60 close(fd);
61 free(buf);
62 return -1;
63 }
64 buf = tmp;
65 }
66 buf[i++] = c;
67 }
68 buf[i] = '\0';
69
70 p = strrchr(buf, '\n');
71 if (p)
72 *p = '\0';
73
74 *value = buf;
75
76 close(fd);
77
78 return 0;
79 }
80
81 static int
82 setsysctl(char *variable, char *value)
83 {
84 char path[PATH_MAX];
85 int fd;
86 ssize_t n;
87
88 replacestr(variable, '.', '/');
89
90 strlcpy(path, "/proc/sys/", sizeof(path));
91 if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
92 replacestr(variable, '/', '.');
93 return -1;
94 }
95
96 replacestr(variable, '/', '.');
97
98 fd = open(path, O_WRONLY);
99 if (fd < 0)
100 return -1;
101
102 n = write(fd, value, strlen(value));
103 if ((size_t)n != strlen(value)) {
104 close(fd);
105 return -1;
106 }
107
108 close(fd);
109
110 return 0;
111 }
112
113 static int
114 parsepair(char *pair)
115 {
116 char *p;
117 char *variable;
118 char *value;
119
120 for (p = pair; *p; p++) {
121 if (p[0] == '.' && p[1] == '.') {
122 weprintf("malformed input: %s\n", pair);
123 return -1;
124 }
125 }
126 p = strchr(pair, '=');
127 if (p) {
128 if (p[1] == '\0') {
129 weprintf("malformed input: %s\n", pair);
130 return -1;
131 }
132 *p = '\0';
133 value = &p[1];
134 } else {
135 value = NULL;
136 }
137 variable = pair;
138 if (value) {
139 if (setsysctl(variable, value) < 0) {
140 weprintf("failed to set sysctl for %s\n", variable);
141 return -1;
142 }
143 } else {
144 if (getsysctl(variable, &value) < 0) {
145 weprintf("failed to get sysctl for %s\n", variable);
146 return -1;
147 }
148 printf("%s = %s\n", variable, value);
149 free(value);
150 }
151
152 return 0;
153 }
154
155 static void
156 usage(void)
157 {
158 eprintf("usage: %s [-p file] variable[=value]...\n", argv0);
159 }
160
161 int
162 main(int argc, char *argv[])
163 {
164 FILE *fp;
165 char *buf = NULL, *p;
166 char *file = NULL;
167 size_t size = 0;
168 int i;
169 int r = 0;
170
171 ARGBEGIN {
172 case 'p':
173 file = EARGF(usage());
174 break;
175 default:
176 usage();
177 } ARGEND;
178
179 if (!file && argc < 1)
180 usage();
181
182 if (!file) {
183 for (i = 0; i < argc; i++)
184 if (parsepair(argv[i]) < 0)
185 r = 1;
186 } else {
187 fp = fopen(file, "r");
188 if (!fp)
189 eprintf("fopen %s:", file);
190 while (agetline(&buf, &size, fp) != -1) {
191 p = buf;
192 for (p = buf; *p == ' ' || *p == '\t'; p++)
193 ;
194 if (*p == '#' || *p == '\n')
195 continue;
196 for (p = buf; *p; p++) {
197 if (*p == '\n') {
198 *p = '\0';
199 break;
200 }
201 }
202 p = buf;
203 if (parsepair(p) < 0)
204 r = 1;
205 }
206 if (ferror(fp))
207 eprintf("%s: read error:", file);
208 free(buf);
209 fclose(fp);
210 }
211
212 return r;
213 }