ubase

suckless linux base utils
git clone git://git.2f30.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", 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 }