| sysctl.c - ubase - suckless linux base utils | |
| git clone git://git.suckless.org/ubase | |
| Log | |
| Files | |
| Refs | |
| README | |
| 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", variab… | |
| 141 return -1; | |
| 142 } | |
| 143 } else { | |
| 144 if (getsysctl(variable, &value) < 0) { | |
| 145 weprintf("failed to get sysctl for %s\n", variab… | |
| 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 } |