logo

utils-std

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

getconf.c (7600B)


  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. int_least64_t 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("%" PRIdLEAST64 "\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. int_least64_t ret = limits_vars[i].limit_h;
  100. if(ret == -1)
  101. {
  102. printf("undefined\n");
  103. return 0;
  104. }
  105. printf("%" PRIdLEAST64 "\n", ret);
  106. return 0;
  107. }
  108. for(size_t i = 0; i < (sizeof(ulimits_vars) / sizeof(*ulimits_vars)); i++)
  109. {
  110. if(strcmp(ulimits_vars[i].name, var) != 0) continue;
  111. unsigned long long ret = ulimits_vars[i].limit_h;
  112. printf("%llu\n", ret);
  113. return 0;
  114. }
  115. fprintf(stderr, "getconf: error: unknown system_var \"%s\"\n", var);
  116. return 1;
  117. }
  118. int
  119. main(int argc, char *argv[])
  120. {
  121. bool o_all = false;
  122. int c = -1;
  123. while((c = getopt_nolong(argc, argv, ":av:")) != -1)
  124. {
  125. switch(c)
  126. {
  127. case 'a':
  128. o_all = true;
  129. break;
  130. case 'v':
  131. fputs("getconf: -v option is unsupported\n", stderr);
  132. return 1;
  133. }
  134. }
  135. argc -= optind;
  136. argv += optind;
  137. if(!o_all && argc == 1)
  138. {
  139. return print_system_var(argv[0]);
  140. }
  141. else if(!o_all && argc == 2)
  142. {
  143. for(size_t i = 0; i < (sizeof(pathconf_vars) / sizeof(*pathconf_vars)); i++)
  144. {
  145. if(strcmp(pathconf_vars[i].name, argv[0]) != 0) continue;
  146. errno = 0;
  147. int_least64_t ret = pathconf(argv[1], (int)(pathconf_vars[i].value));
  148. if(ret == -1 && errno != 0)
  149. {
  150. fprintf(stderr,
  151. "getconf: error: pathconf(\"%s\", %d /* \"%s\" */): %s\n",
  152. argv[1],
  153. pathconf_vars[i].value,
  154. argv[0],
  155. strerror(errno));
  156. return 1;
  157. }
  158. if(ret == -1) ret = pathconf_vars[i].limit_h;
  159. printf("%" PRIdLEAST64 "\n", ret);
  160. return 0;
  161. }
  162. fprintf(stderr, "getconf: error: unknown path_var \"%s\"\n", argv[0]);
  163. return 1;
  164. }
  165. else if(o_all && (argc == 0 || argc == 1))
  166. {
  167. int err = 0;
  168. char *buf = NULL;
  169. size_t buflen = 0;
  170. for(size_t i = 0; i < (sizeof(confstr_vars) / sizeof(*confstr_vars)); i++)
  171. {
  172. errno = 0;
  173. size_t buflen_ret = confstr(confstr_vars[i].value, (char *)NULL, 0);
  174. if(buflen_ret == 0)
  175. {
  176. if(errno != 0)
  177. {
  178. fprintf(stderr,
  179. "getconf: error: confstr(%d /* \"%s\" */, NULL, 0): %s\n",
  180. confstr_vars[i].value,
  181. confstr_vars[i].name,
  182. strerror(errno));
  183. err = 1;
  184. continue;
  185. }
  186. printf("%s: undefined\n", confstr_vars[i].name);
  187. continue;
  188. }
  189. if(buflen_ret > buflen)
  190. {
  191. errno = 0;
  192. char *buf_ret = realloc(buf, buflen_ret);
  193. if(!buf_ret)
  194. {
  195. fprintf(stderr,
  196. "getconf: error: Failed to allocate %zd bytes buffer for confstr: %s\n",
  197. buflen,
  198. strerror(errno));
  199. err = 1;
  200. continue;
  201. }
  202. buflen = buflen_ret;
  203. buf = buf_ret;
  204. }
  205. errno = 0;
  206. size_t ret = confstr(confstr_vars[i].value, buf, buflen);
  207. if(ret == 0)
  208. {
  209. if(errno != 0)
  210. {
  211. fprintf(stderr,
  212. "getconf: error: confstr(%d /* \"%s\" */, buf, %zd): %s\n",
  213. confstr_vars[i].value,
  214. confstr_vars[i].name,
  215. buflen,
  216. strerror(errno));
  217. err = 1;
  218. continue;
  219. }
  220. printf("%s: undefined\n", confstr_vars[i].name);
  221. continue;
  222. }
  223. assert(buf);
  224. printf("%s: ", confstr_vars[i].name);
  225. fwrite(buf, (ret - 1), 1, stdout);
  226. printf("\n");
  227. }
  228. free(buf);
  229. for(size_t i = 0; i < (sizeof(sysconf_vars) / sizeof(*sysconf_vars)); i++)
  230. {
  231. errno = 0;
  232. int_least64_t ret = sysconf((int)(sysconf_vars[i].value));
  233. if(ret == -1 && errno != 0)
  234. {
  235. fprintf(stderr,
  236. "getconf: error: sysconf(%d /* \"%s\" */): %s\n",
  237. sysconf_vars[i].value,
  238. sysconf_vars[i].name,
  239. strerror(errno));
  240. err = 1;
  241. continue;
  242. }
  243. if(ret == -1) ret = sysconf_vars[i].limit_h;
  244. if(ret == -1)
  245. {
  246. printf("%s: undefined\n", sysconf_vars[i].name);
  247. continue;
  248. }
  249. printf("%s: %" PRIdLEAST64 "\n", sysconf_vars[i].name, ret);
  250. }
  251. for(size_t i = 0; i < (sizeof(limits_vars) / sizeof(*limits_vars)); i++)
  252. {
  253. int_least64_t ret = limits_vars[i].limit_h;
  254. if(ret == -1)
  255. {
  256. printf("%s: undefined\n", limits_vars[i].name);
  257. continue;
  258. }
  259. printf("%s: %" PRIdLEAST64 "\n", limits_vars[i].name, ret);
  260. }
  261. for(size_t i = 0; i < (sizeof(ulimits_vars) / sizeof(*ulimits_vars)); i++)
  262. {
  263. unsigned long long ret = ulimits_vars[i].limit_h;
  264. printf("%s: %llu\n", ulimits_vars[i].name, ret);
  265. }
  266. const char *path = argc == 1 ? argv[0] : ".";
  267. for(size_t i = 0; i < (sizeof(pathconf_vars) / sizeof(*pathconf_vars)); i++)
  268. {
  269. errno = 0;
  270. int_least64_t ret = pathconf(path, (int)(pathconf_vars[i].value));
  271. if(ret == -1 && errno != 0)
  272. {
  273. fprintf(stderr,
  274. "getconf: error: pathconf(\"%s\", %d /* \"%s\" */): %s\n",
  275. path,
  276. pathconf_vars[i].value,
  277. pathconf_vars[i].name,
  278. strerror(errno));
  279. err = 1;
  280. continue;
  281. }
  282. if(ret == -1) ret = pathconf_vars[i].limit_h;
  283. printf("%s: %" PRIdLEAST64 "\n", pathconf_vars[i].name, ret);
  284. }
  285. return err;
  286. }
  287. else
  288. {
  289. fprintf(stderr, "getconf: error: wrong number of arguments\n");
  290. fprintf(stderr, "\
  291. Usage: getconf <system_var>\n\
  292. getconf <path_var> <path>\n\
  293. getconf -a [path]\n\
  294. ");
  295. return 1;
  296. }
  297. }