sysctl.c 3.2 KB

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