logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/

getconf.c (7047B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _ALL_SOURCE
  5. #define _DEFAULT_SOURCE
  6. #include "../libutils/getopt_nolong.h"
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <limits.h>
  10. #include <stdbool.h>
  11. #include <stdio.h> // fputs
  12. #include <stdlib.h> // exit
  13. #include <string.h> // strerror
  14. #include <unistd.h> // getopt, pathconf
  15. // need to be after system headers
  16. #include "getconf_vars.h"
  17. const char *argv0 = "getconf";
  18. static int
  19. print_system_var(const char *var)
  20. {
  21. for(size_t i = 0; i < (sizeof(confstr_vars) / sizeof(*confstr_vars)); i++)
  22. {
  23. if(strcmp(confstr_vars[i].name, var) != 0) continue;
  24. errno = 0;
  25. size_t buflen = confstr(confstr_vars[i].value, (char *)NULL, 0);
  26. if(buflen == 0)
  27. {
  28. if(errno != 0)
  29. {
  30. fprintf(stderr,
  31. "getconf: error: confstr(%d /* \"%s\" */, NULL, 0): %s\n",
  32. confstr_vars[i].value,
  33. var,
  34. strerror(errno));
  35. return 1;
  36. }
  37. printf("undefined\n");
  38. return 0;
  39. }
  40. errno = 0;
  41. char *buf = malloc(buflen);
  42. if(!buf)
  43. {
  44. fprintf(stderr,
  45. "getconf: error: Failed to allocate %zd bytes buffer for confstr: %s\n",
  46. buflen,
  47. strerror(errno));
  48. return 1;
  49. }
  50. errno = 0;
  51. size_t ret = confstr(confstr_vars[i].value, buf, buflen);
  52. if(ret == 0)
  53. {
  54. if(errno != 0)
  55. {
  56. fprintf(stderr,
  57. "getconf: error: confstr(%d /* \"%s\" */, buf, %zd): %s\n",
  58. confstr_vars[i].value,
  59. var,
  60. buflen,
  61. strerror(errno));
  62. free(buf);
  63. return 1;
  64. }
  65. printf("undefined\n");
  66. free(buf);
  67. return 0;
  68. }
  69. fwrite(buf, (ret - 1), 1, stdout);
  70. free(buf);
  71. return 0;
  72. }
  73. for(size_t i = 0; i < (sizeof(sysconf_vars) / sizeof(*sysconf_vars)); i++)
  74. {
  75. if(strcmp(sysconf_vars[i].name, var) != 0) continue;
  76. errno = 0;
  77. long ret = sysconf((int)(sysconf_vars[i].value));
  78. if(ret == -1 && errno != 0)
  79. {
  80. fprintf(stderr,
  81. "getconf: error: sysconf(%d /* \"%s\" */): %s\n",
  82. sysconf_vars[i].value,
  83. var,
  84. strerror(errno));
  85. return 1;
  86. }
  87. if(ret == -1) ret = sysconf_vars[i].limit_h;
  88. if(ret == -1)
  89. {
  90. printf("undefined\n");
  91. return 0;
  92. }
  93. printf("%ld\n", ret);
  94. return 0;
  95. }
  96. for(size_t i = 0; i < (sizeof(limits_vars) / sizeof(*limits_vars)); i++)
  97. {
  98. if(strcmp(limits_vars[i].name, var) != 0) continue;
  99. long ret = limits_vars[i].limit_h;
  100. if(ret == -1)
  101. {
  102. printf("undefined\n");
  103. return 0;
  104. }
  105. printf("%ld\n", ret);
  106. return 0;
  107. }
  108. fprintf(stderr, "getconf: error: unknown system_var \"%s\"\n", var);
  109. return 1;
  110. }
  111. int
  112. main(int argc, char *argv[])
  113. {
  114. bool o_all = false;
  115. int c = -1;
  116. while((c = getopt_nolong(argc, argv, ":av:")) != -1)
  117. {
  118. switch(c)
  119. {
  120. case 'a':
  121. o_all = true;
  122. break;
  123. case 'v':
  124. fputs("getconf: -v option is unsupported\n", stderr);
  125. return 1;
  126. }
  127. }
  128. argc -= optind;
  129. argv += optind;
  130. if(!o_all && argc == 1)
  131. {
  132. return print_system_var(argv[0]);
  133. }
  134. else if(!o_all && argc == 2)
  135. {
  136. for(size_t i = 0; i < (sizeof(pathconf_vars) / sizeof(*pathconf_vars)); i++)
  137. {
  138. if(strcmp(pathconf_vars[i].name, argv[0]) != 0) continue;
  139. errno = 0;
  140. long ret = pathconf(argv[1], (int)(pathconf_vars[i].value));
  141. if(ret == -1 && errno != 0)
  142. {
  143. fprintf(stderr,
  144. "getconf: error: pathconf(\"%s\", %d /* \"%s\" */): %s\n",
  145. argv[1],
  146. pathconf_vars[i].value,
  147. argv[0],
  148. strerror(errno));
  149. return 1;
  150. }
  151. if(ret == -1) ret = pathconf_vars[i].limit_h;
  152. printf("%ld\n", ret);
  153. return 0;
  154. }
  155. fprintf(stderr, "getconf: error: unknown path_var \"%s\"\n", argv[0]);
  156. return 1;
  157. }
  158. else if(o_all && (argc == 0 || argc == 1))
  159. {
  160. int err = 0;
  161. char *buf = NULL;
  162. size_t buflen = 0;
  163. for(size_t i = 0; i < (sizeof(confstr_vars) / sizeof(*confstr_vars)); i++)
  164. {
  165. errno = 0;
  166. size_t buflen_ret = confstr(confstr_vars[i].value, (char *)NULL, 0);
  167. if(buflen_ret == 0)
  168. {
  169. if(errno != 0)
  170. {
  171. fprintf(stderr,
  172. "getconf: error: confstr(%d /* \"%s\" */, NULL, 0): %s\n",
  173. confstr_vars[i].value,
  174. confstr_vars[i].name,
  175. strerror(errno));
  176. err = 1;
  177. continue;
  178. }
  179. printf("%s: undefined\n", confstr_vars[i].name);
  180. continue;
  181. }
  182. if(buflen_ret > buflen)
  183. {
  184. errno = 0;
  185. char *buf_ret = realloc(buf, buflen_ret);
  186. if(!buf_ret)
  187. {
  188. fprintf(stderr,
  189. "getconf: error: Failed to allocate %zd bytes buffer for confstr: %s\n",
  190. buflen,
  191. strerror(errno));
  192. err = 1;
  193. continue;
  194. }
  195. buflen = buflen_ret;
  196. buf = buf_ret;
  197. }
  198. errno = 0;
  199. size_t ret = confstr(confstr_vars[i].value, buf, buflen);
  200. if(ret == 0)
  201. {
  202. if(errno != 0)
  203. {
  204. fprintf(stderr,
  205. "getconf: error: confstr(%d /* \"%s\" */, buf, %zd): %s\n",
  206. confstr_vars[i].value,
  207. confstr_vars[i].name,
  208. buflen,
  209. strerror(errno));
  210. err = 1;
  211. continue;
  212. }
  213. printf("%s: undefined\n", confstr_vars[i].name);
  214. continue;
  215. }
  216. assert(buf);
  217. printf("%s: ", confstr_vars[i].name);
  218. fwrite(buf, (ret - 1), 1, stdout);
  219. printf("\n");
  220. }
  221. free(buf);
  222. for(size_t i = 0; i < (sizeof(sysconf_vars) / sizeof(*sysconf_vars)); i++)
  223. {
  224. errno = 0;
  225. long ret = sysconf((int)(sysconf_vars[i].value));
  226. if(ret == -1 && errno != 0)
  227. {
  228. fprintf(stderr,
  229. "getconf: error: sysconf(%d /* \"%s\" */): %s\n",
  230. sysconf_vars[i].value,
  231. sysconf_vars[i].name,
  232. strerror(errno));
  233. err = 1;
  234. continue;
  235. }
  236. if(ret == -1) ret = sysconf_vars[i].limit_h;
  237. if(ret == -1)
  238. {
  239. printf("%s: undefined\n", sysconf_vars[i].name);
  240. continue;
  241. }
  242. printf("%s: %ld\n", sysconf_vars[i].name, ret);
  243. }
  244. for(size_t i = 0; i < (sizeof(limits_vars) / sizeof(*limits_vars)); i++)
  245. {
  246. long ret = limits_vars[i].limit_h;
  247. if(ret == -1)
  248. {
  249. printf("%s: undefined\n", limits_vars[i].name);
  250. continue;
  251. }
  252. printf("%s: %ld\n", limits_vars[i].name, ret);
  253. }
  254. const char *path = argc == 1 ? argv[0] : ".";
  255. for(size_t i = 0; i < (sizeof(pathconf_vars) / sizeof(*pathconf_vars)); i++)
  256. {
  257. errno = 0;
  258. long ret = pathconf(path, (int)(pathconf_vars[i].value));
  259. if(ret == -1 && errno != 0)
  260. {
  261. fprintf(stderr,
  262. "getconf: error: pathconf(\"%s\", %d /* \"%s\" */): %s\n",
  263. path,
  264. pathconf_vars[i].value,
  265. pathconf_vars[i].name,
  266. strerror(errno));
  267. err = 1;
  268. continue;
  269. }
  270. if(ret == -1) ret = pathconf_vars[i].limit_h;
  271. printf("%s: %ld\n", pathconf_vars[i].name, ret);
  272. }
  273. return err;
  274. }
  275. else
  276. {
  277. fprintf(stderr, "getconf: error: wrong number of arguments\n");
  278. fprintf(stderr, "\
  279. Usage: getconf <system_var>\n\
  280. getconf <path_var> <path>\n\
  281. getconf -a [path]\n\
  282. ");
  283. return 1;
  284. }
  285. }