getconf.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* getconf.c - get configuration values
  2. *
  3. * Copyright 2017 Rob Landley <rob@landley.net>
  4. *
  5. * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.c
  6. *
  7. * Deviations from posix: no -v because nothing says what it should DO.
  8. * Added -l, what symbols should be included is a bit unclear.
  9. * Added -a, copied FSF behavior of assuming "/" if no path supplied.
  10. USE_GETCONF(NEWTOY(getconf, ">2al", TOYFLAG_USR|TOYFLAG_BIN))
  11. config GETCONF
  12. bool "getconf"
  13. default y
  14. help
  15. usage: getconf -a [PATH] | -l | NAME [PATH]
  16. Get system configuration values. Values from pathconf(3) require a path.
  17. -a Show all (defaults to "/" if no path given)
  18. -l List available value names (grouped by source)
  19. */
  20. #define FOR_getconf
  21. #include "toys.h"
  22. #include <limits.h>
  23. // This is missing on glibc (bionic has it).
  24. #ifndef _SC_XOPEN_UUCP
  25. #define _SC_XOPEN_UUCP -1
  26. #endif
  27. #ifdef __APPLE__
  28. // macOS doesn't have a bunch of stuff. The actual macOS getconf says
  29. // "no such parameter", but -- unless proven otherwise -- it seems more useful
  30. // for portability if we act like we understood but say "undefined"?
  31. #define _SC_AVPHYS_PAGES -1
  32. #define _SC_THREAD_ROBUST_PRIO_INHERIT -1
  33. #define _SC_THREAD_ROBUST_PRIO_PROTECT -1
  34. #define _SC_UIO_MAXIOV -1
  35. #define _SC_V7_ILP32_OFF32 -1
  36. #define _SC_V7_ILP32_OFFBIG -1
  37. #define _SC_V7_LP64_OFF64 -1
  38. #define _SC_V7_LPBIG_OFFBIG -1
  39. #define _CS_V7_ENV -1
  40. #endif
  41. struct config {
  42. char *name;
  43. long long value;
  44. };
  45. // Lists of symbols getconf can query, broken down by whether we call sysconf(),
  46. // confstr(), or output the macro value directly.
  47. // Probe the live system
  48. static struct config sysconfs[] = {
  49. /* POSIX */
  50. #define CONF(n) {"_POSIX_" #n,_SC_ ## n}
  51. CONF(ADVISORY_INFO), CONF(BARRIERS), CONF(ASYNCHRONOUS_IO),
  52. CONF(CLOCK_SELECTION), CONF(CPUTIME), CONF(FSYNC), CONF(IPV6),
  53. CONF(JOB_CONTROL), CONF(MAPPED_FILES), CONF(MEMLOCK), CONF(MEMLOCK_RANGE),
  54. CONF(MEMORY_PROTECTION), CONF(MESSAGE_PASSING), CONF(MONOTONIC_CLOCK),
  55. CONF(PRIORITY_SCHEDULING), CONF(RAW_SOCKETS), CONF(READER_WRITER_LOCKS),
  56. CONF(REALTIME_SIGNALS), CONF(REGEXP), CONF(SAVED_IDS), CONF(SEMAPHORES),
  57. CONF(SHARED_MEMORY_OBJECTS), CONF(SHELL), CONF(SPAWN), CONF(SPIN_LOCKS),
  58. CONF(SPORADIC_SERVER), CONF(SS_REPL_MAX), CONF(SYNCHRONIZED_IO),
  59. CONF(THREAD_ATTR_STACKADDR), CONF(THREAD_ATTR_STACKSIZE),
  60. CONF(THREAD_CPUTIME), CONF(THREAD_PRIO_INHERIT), CONF(THREAD_PRIO_PROTECT),
  61. CONF(THREAD_PRIORITY_SCHEDULING), CONF(THREAD_PROCESS_SHARED),
  62. CONF(THREAD_ROBUST_PRIO_INHERIT), CONF(THREAD_ROBUST_PRIO_PROTECT),
  63. CONF(THREAD_SAFE_FUNCTIONS), CONF(THREAD_SPORADIC_SERVER), CONF(THREADS),
  64. CONF(TIMEOUTS), CONF(TIMERS), CONF(TRACE), CONF(TRACE_EVENT_FILTER),
  65. CONF(TRACE_EVENT_NAME_MAX), CONF(TRACE_INHERIT), CONF(TRACE_LOG),
  66. CONF(TRACE_NAME_MAX), CONF(TRACE_SYS_MAX), CONF(TRACE_USER_EVENT_MAX),
  67. CONF(TYPED_MEMORY_OBJECTS), CONF(VERSION), CONF(V7_ILP32_OFF32),
  68. CONF(V7_ILP32_OFFBIG), CONF(V7_LP64_OFF64), CONF(V7_LPBIG_OFFBIG),
  69. /* POSIX.2 */
  70. #undef CONF
  71. #define CONF(n) {"POSIX2_" #n,_SC_2_ ## n}
  72. CONF(C_BIND), CONF(C_DEV), CONF(CHAR_TERM), CONF(FORT_DEV), CONF(FORT_RUN),
  73. CONF(LOCALEDEF), CONF(PBS), CONF(PBS_ACCOUNTING), CONF(PBS_CHECKPOINT),
  74. CONF(PBS_LOCATE), CONF(PBS_MESSAGE), CONF(PBS_TRACK), CONF(SW_DEV),
  75. CONF(UPE), CONF(VERSION),
  76. /* X/Open */
  77. #undef CONF
  78. #define CONF(n) {"_XOPEN_" #n,_SC_XOPEN_ ## n}
  79. CONF(CRYPT), CONF(ENH_I18N), CONF(REALTIME), CONF(REALTIME_THREADS),
  80. CONF(SHM), CONF(STREAMS), CONF(UNIX), CONF(UUCP), CONF(VERSION),
  81. /* No obvious standard */
  82. #undef CONF
  83. #define CONF(n) {#n,_SC_ ## n}
  84. CONF(AIO_LISTIO_MAX), CONF(AIO_MAX), CONF(AIO_PRIO_DELTA_MAX), CONF(ARG_MAX),
  85. CONF(ATEXIT_MAX), CONF(BC_BASE_MAX), CONF(BC_DIM_MAX), CONF(BC_SCALE_MAX),
  86. CONF(BC_STRING_MAX), CONF(CHILD_MAX), CONF(CLK_TCK), CONF(COLL_WEIGHTS_MAX),
  87. CONF(DELAYTIMER_MAX), CONF(EXPR_NEST_MAX), CONF(HOST_NAME_MAX),
  88. CONF(IOV_MAX), CONF(LINE_MAX), CONF(LOGIN_NAME_MAX), CONF(NGROUPS_MAX),
  89. CONF(MQ_OPEN_MAX), CONF(MQ_PRIO_MAX), CONF(OPEN_MAX), CONF(PAGE_SIZE),
  90. CONF(PAGESIZE), CONF(RAW_SOCKETS), CONF(RE_DUP_MAX), CONF(RTSIG_MAX),
  91. CONF(SEM_NSEMS_MAX), CONF(SEM_VALUE_MAX), CONF(SIGQUEUE_MAX),
  92. CONF(STREAM_MAX), CONF(SYMLOOP_MAX), CONF(TIMER_MAX), CONF(TTY_NAME_MAX),
  93. CONF(TZNAME_MAX), CONF(UIO_MAXIOV),
  94. /* Names that just don't match the symbol, do it by hand */
  95. {"_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, {"_PHYS_PAGES", _SC_PHYS_PAGES},
  96. {"_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
  97. {"_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
  98. /* There's a weird "PTHREAD" vs "THREAD" mismatch here. */
  99. {"PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
  100. {"PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
  101. {"PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
  102. {"PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
  103. };
  104. // Probe the live system with a path
  105. static struct config pathconfs[] = {
  106. #undef CONF
  107. #define CONF(n) {#n,_PC_ ## n}
  108. CONF(ASYNC_IO), CONF(CHOWN_RESTRICTED), CONF(FILESIZEBITS), CONF(LINK_MAX),
  109. CONF(MAX_CANON), CONF(MAX_INPUT), CONF(NAME_MAX), CONF(NO_TRUNC),
  110. CONF(PATH_MAX), CONF(PIPE_BUF), CONF(PRIO_IO), CONF(SYMLINK_MAX),
  111. CONF(SYNC_IO),
  112. {"_POSIX_VDISABLE", _PC_VDISABLE},
  113. };
  114. // Strings out of a header
  115. static struct config confstrs[] = {
  116. #undef CONF
  117. #define CONF(n) {#n,_CS_ ## n}
  118. CONF(PATH), CONF(V7_ENV)
  119. };
  120. // Integers out of a header
  121. static struct config limits[] = {
  122. #undef CONF
  123. #define CONF(n) {#n,n}
  124. CONF(_POSIX_AIO_LISTIO_MAX), CONF(_POSIX_AIO_MAX), CONF(_POSIX_ARG_MAX),
  125. CONF(_POSIX_CHILD_MAX), CONF(_POSIX_DELAYTIMER_MAX),
  126. CONF(_POSIX_HOST_NAME_MAX), CONF(_POSIX_LINK_MAX),
  127. CONF(_POSIX_LOGIN_NAME_MAX), CONF(_POSIX_MAX_CANON),
  128. CONF(_POSIX_MAX_INPUT), CONF(_POSIX_NAME_MAX), CONF(_POSIX_NGROUPS_MAX),
  129. CONF(_POSIX_OPEN_MAX), CONF(_POSIX_PATH_MAX), CONF(_POSIX_PIPE_BUF),
  130. CONF(_POSIX_RE_DUP_MAX), CONF(_POSIX_RTSIG_MAX), CONF(_POSIX_SEM_NSEMS_MAX),
  131. CONF(_POSIX_SEM_VALUE_MAX), CONF(_POSIX_SIGQUEUE_MAX), CONF(_POSIX_SSIZE_MAX),
  132. CONF(_POSIX_STREAM_MAX), CONF(_POSIX_SYMLINK_MAX), CONF(_POSIX_SYMLOOP_MAX),
  133. CONF(_POSIX_THREAD_DESTRUCTOR_ITERATIONS), CONF(_POSIX_THREAD_KEYS_MAX),
  134. CONF(_POSIX_THREAD_THREADS_MAX), CONF(_POSIX_TIMER_MAX),
  135. CONF(_POSIX_TTY_NAME_MAX), CONF(_POSIX_TZNAME_MAX),
  136. CONF(CHAR_MAX), CONF(CHAR_MIN), CONF(INT_MAX), CONF(INT_MIN), CONF(SCHAR_MAX),
  137. CONF(SCHAR_MIN), CONF(SHRT_MAX), CONF(SHRT_MIN), CONF(SSIZE_MAX),
  138. CONF(UCHAR_MAX), CONF(UINT_MAX), CONF(ULONG_MAX), CONF(USHRT_MAX),
  139. CONF(CHAR_BIT),
  140. /* Not available in glibc without _GNU_SOURCE. */
  141. {"LONG_BIT", 8*sizeof(long)},
  142. {"WORD_BIT", 8*sizeof(int)},
  143. #undef CONF
  144. #define CONF(n) {#n,_ ## n}
  145. CONF(POSIX2_BC_BASE_MAX), CONF(POSIX2_BC_DIM_MAX),
  146. CONF(POSIX2_BC_SCALE_MAX), CONF(POSIX2_BC_STRING_MAX),
  147. CONF(POSIX2_CHARCLASS_NAME_MAX), CONF(POSIX2_COLL_WEIGHTS_MAX),
  148. CONF(POSIX2_EXPR_NEST_MAX), CONF(POSIX2_LINE_MAX), CONF(POSIX2_RE_DUP_MAX),
  149. };
  150. // Names we need to handle ourselves (default to blank but shouldn't error)
  151. static struct config others[] = {
  152. {"LFS_CFLAGS", 0}, {"LFS_LDFLAGS", 0}, {"LFS_LIBS", 0}
  153. };
  154. static void show_conf(int i, struct config *c, const char *path)
  155. {
  156. if (i<2) {
  157. long l = i ? pathconf(path, c->value) : sysconf(c->value);
  158. if (l == -1) puts("undefined");
  159. else printf("%ld\n", l);
  160. } else if (i==2) {
  161. confstr(c->value, toybuf, sizeof(toybuf));
  162. puts(toybuf);
  163. } else if (i==3) printf("%lld\n", c->value);
  164. // LFS_CFLAGS on 32 bit should enable Large File Support for kernel builds
  165. else puts(sizeof(long)==4 && !strcmp(c->name, "LFS_CFLAGS") ?
  166. "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" : "");
  167. }
  168. void getconf_main(void)
  169. {
  170. struct config *configs[] = {sysconfs, pathconfs, confstrs, limits, others},
  171. *c = NULL;
  172. int i, j, lens[] = {ARRAY_LEN(sysconfs), ARRAY_LEN(pathconfs),
  173. ARRAY_LEN(confstrs), ARRAY_LEN(limits), ARRAY_LEN(others)};
  174. char *name, *path = (toys.optc==2) ? toys.optargs[1] : "/",
  175. *config_names[] = {"sysconf(3)", "pathconf(3)", "confstr(3)",
  176. "<limits.h>", "Misc"};
  177. if (toys.optflags&FLAG_a) {
  178. for (i = 0; i<5; i++) {
  179. for (j = 0; j<lens[i]; j++) {
  180. c = &configs[i][j];
  181. printf("%-34s ", c->name);
  182. show_conf(i, c, path);
  183. }
  184. }
  185. return;
  186. }
  187. if (toys.optflags&FLAG_l) {
  188. for (i = 0; i<5; i++) {
  189. printf("%s\n", config_names[i]);
  190. for (j = 0; j<lens[i]; j++) printf(" %s\n", configs[i][j].name);
  191. }
  192. return;
  193. }
  194. if (toys.optc<1) help_exit(0);
  195. name = *toys.optargs;
  196. // Workaround for autogen using CS_PATH instead of PATH
  197. if (!strcmp("CS_PATH", name)) name += 3;
  198. // Find the config.
  199. for (i = j = 0; ; j++) {
  200. if (j==lens[i]) j = 0, i++;
  201. if (i==5) error_exit("bad '%s'", name);
  202. c = &configs[i][j];
  203. if (!strcmp(c->name, name)) break;
  204. }
  205. // Check that we do/don't have the extra path argument.
  206. if (i==1) {
  207. if (toys.optc!=2) help_exit("%s needs a path", name);
  208. } else if (toys.optc!=1) help_exit("%s does not take a path", name);
  209. show_conf(i, c, path);
  210. }