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 }