logo

utils-std

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

getconf.c (7041B)


  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 _POSIX_C_SOURCE 202405L
  5. #define _XOPEN_SOURCE 800
  6. #include "../lib/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. printf("%s: ", confstr_vars[i].name);
  217. fwrite(buf, (ret - 1), 1, stdout);
  218. printf("\n");
  219. }
  220. free(buf);
  221. for(size_t i = 0; i < (sizeof(sysconf_vars) / sizeof(*sysconf_vars)); i++)
  222. {
  223. errno = 0;
  224. long ret = sysconf((int)(sysconf_vars[i].value));
  225. if(ret == -1 && errno != 0)
  226. {
  227. fprintf(stderr,
  228. "getconf: error: sysconf(%d /* \"%s\" */): %s\n",
  229. sysconf_vars[i].value,
  230. sysconf_vars[i].name,
  231. strerror(errno));
  232. err = 1;
  233. continue;
  234. }
  235. if(ret == -1) ret = sysconf_vars[i].limit_h;
  236. if(ret == -1)
  237. {
  238. printf("%s: undefined\n", sysconf_vars[i].name);
  239. continue;
  240. }
  241. printf("%s: %ld\n", sysconf_vars[i].name, ret);
  242. }
  243. for(size_t i = 0; i < (sizeof(limits_vars) / sizeof(*limits_vars)); i++)
  244. {
  245. long ret = limits_vars[i].limit_h;
  246. if(ret == -1)
  247. {
  248. printf("%s: undefined\n", limits_vars[i].name);
  249. continue;
  250. }
  251. printf("%s: %ld\n", limits_vars[i].name, ret);
  252. }
  253. const char *path = argc == 1 ? argv[0] : ".";
  254. for(size_t i = 0; i < (sizeof(pathconf_vars) / sizeof(*pathconf_vars)); i++)
  255. {
  256. errno = 0;
  257. long ret = pathconf(path, (int)(pathconf_vars[i].value));
  258. if(ret == -1 && errno != 0)
  259. {
  260. fprintf(stderr,
  261. "getconf: error: pathconf(\"%s\", %d /* \"%s\" */): %s\n",
  262. path,
  263. pathconf_vars[i].value,
  264. pathconf_vars[i].name,
  265. strerror(errno));
  266. err = 1;
  267. continue;
  268. }
  269. if(ret == -1) ret = pathconf_vars[i].limit_h;
  270. printf("%s: %ld\n", pathconf_vars[i].name, ret);
  271. }
  272. return err;
  273. }
  274. else
  275. {
  276. fprintf(stderr, "getconf: error: wrong number of arguments\n");
  277. fprintf(stderr, "\
  278. Usage: getconf <system_var>\n\
  279. getconf <path_var> <path>\n\
  280. getconf -a [path]\n\
  281. ");
  282. return 1;
  283. }
  284. }