10f66f451Sopenharmony_ci/* getconf.c - get configuration values
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2017 Rob Landley <rob@landley.net>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.c
60f66f451Sopenharmony_ci *
70f66f451Sopenharmony_ci * Deviations from posix: no -v because nothing says what it should DO.
80f66f451Sopenharmony_ci * Added -l, what symbols should be included is a bit unclear.
90f66f451Sopenharmony_ci * Added -a, copied FSF behavior of assuming "/" if no path supplied.
100f66f451Sopenharmony_ci
110f66f451Sopenharmony_ciUSE_GETCONF(NEWTOY(getconf, ">2al", TOYFLAG_USR|TOYFLAG_BIN))
120f66f451Sopenharmony_ci
130f66f451Sopenharmony_ciconfig GETCONF
140f66f451Sopenharmony_ci  bool "getconf"
150f66f451Sopenharmony_ci  default y
160f66f451Sopenharmony_ci  help
170f66f451Sopenharmony_ci    usage: getconf -a [PATH] | -l | NAME [PATH]
180f66f451Sopenharmony_ci
190f66f451Sopenharmony_ci    Get system configuration values. Values from pathconf(3) require a path.
200f66f451Sopenharmony_ci
210f66f451Sopenharmony_ci    -a	Show all (defaults to "/" if no path given)
220f66f451Sopenharmony_ci    -l	List available value names (grouped by source)
230f66f451Sopenharmony_ci*/
240f66f451Sopenharmony_ci
250f66f451Sopenharmony_ci#define FOR_getconf
260f66f451Sopenharmony_ci#include "toys.h"
270f66f451Sopenharmony_ci#include <limits.h>
280f66f451Sopenharmony_ci
290f66f451Sopenharmony_ci// This is missing on glibc (bionic has it).
300f66f451Sopenharmony_ci#ifndef _SC_XOPEN_UUCP
310f66f451Sopenharmony_ci#define _SC_XOPEN_UUCP -1
320f66f451Sopenharmony_ci#endif
330f66f451Sopenharmony_ci
340f66f451Sopenharmony_ci#ifdef __APPLE__
350f66f451Sopenharmony_ci// macOS doesn't have a bunch of stuff. The actual macOS getconf says
360f66f451Sopenharmony_ci// "no such parameter", but -- unless proven otherwise -- it seems more useful
370f66f451Sopenharmony_ci// for portability if we act like we understood but say "undefined"?
380f66f451Sopenharmony_ci#define _SC_AVPHYS_PAGES -1
390f66f451Sopenharmony_ci#define _SC_THREAD_ROBUST_PRIO_INHERIT -1
400f66f451Sopenharmony_ci#define _SC_THREAD_ROBUST_PRIO_PROTECT -1
410f66f451Sopenharmony_ci#define _SC_UIO_MAXIOV -1
420f66f451Sopenharmony_ci#define _SC_V7_ILP32_OFF32 -1
430f66f451Sopenharmony_ci#define _SC_V7_ILP32_OFFBIG -1
440f66f451Sopenharmony_ci#define _SC_V7_LP64_OFF64 -1
450f66f451Sopenharmony_ci#define _SC_V7_LPBIG_OFFBIG -1
460f66f451Sopenharmony_ci#define _CS_V7_ENV -1
470f66f451Sopenharmony_ci#endif
480f66f451Sopenharmony_ci
490f66f451Sopenharmony_cistruct config {
500f66f451Sopenharmony_ci  char *name;
510f66f451Sopenharmony_ci  long long value;
520f66f451Sopenharmony_ci};
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci// Lists of symbols getconf can query, broken down by whether we call sysconf(),
550f66f451Sopenharmony_ci// confstr(), or output the macro value directly.
560f66f451Sopenharmony_ci
570f66f451Sopenharmony_ci// Probe the live system
580f66f451Sopenharmony_cistruct config sysconfs[] = {
590f66f451Sopenharmony_ci  /* POSIX */
600f66f451Sopenharmony_ci#define CONF(n) {"_POSIX_" #n,_SC_ ## n}
610f66f451Sopenharmony_ci  CONF(ADVISORY_INFO), CONF(BARRIERS), CONF(ASYNCHRONOUS_IO),
620f66f451Sopenharmony_ci  CONF(CLOCK_SELECTION), CONF(CPUTIME), CONF(FSYNC), CONF(IPV6),
630f66f451Sopenharmony_ci  CONF(JOB_CONTROL), CONF(MAPPED_FILES), CONF(MEMLOCK), CONF(MEMLOCK_RANGE),
640f66f451Sopenharmony_ci  CONF(MEMORY_PROTECTION), CONF(MESSAGE_PASSING), CONF(MONOTONIC_CLOCK),
650f66f451Sopenharmony_ci  CONF(PRIORITY_SCHEDULING), CONF(RAW_SOCKETS), CONF(READER_WRITER_LOCKS),
660f66f451Sopenharmony_ci  CONF(REALTIME_SIGNALS), CONF(REGEXP), CONF(SAVED_IDS), CONF(SEMAPHORES),
670f66f451Sopenharmony_ci  CONF(SHARED_MEMORY_OBJECTS), CONF(SHELL), CONF(SPAWN), CONF(SPIN_LOCKS),
680f66f451Sopenharmony_ci  CONF(SPORADIC_SERVER), CONF(SS_REPL_MAX), CONF(SYNCHRONIZED_IO),
690f66f451Sopenharmony_ci  CONF(THREAD_ATTR_STACKADDR), CONF(THREAD_ATTR_STACKSIZE),
700f66f451Sopenharmony_ci  CONF(THREAD_CPUTIME), CONF(THREAD_PRIO_INHERIT), CONF(THREAD_PRIO_PROTECT),
710f66f451Sopenharmony_ci  CONF(THREAD_PRIORITY_SCHEDULING), CONF(THREAD_PROCESS_SHARED),
720f66f451Sopenharmony_ci  CONF(THREAD_ROBUST_PRIO_INHERIT), CONF(THREAD_ROBUST_PRIO_PROTECT),
730f66f451Sopenharmony_ci  CONF(THREAD_SAFE_FUNCTIONS), CONF(THREAD_SPORADIC_SERVER), CONF(THREADS),
740f66f451Sopenharmony_ci  CONF(TIMEOUTS), CONF(TIMERS), CONF(TRACE), CONF(TRACE_EVENT_FILTER),
750f66f451Sopenharmony_ci  CONF(TRACE_EVENT_NAME_MAX), CONF(TRACE_INHERIT), CONF(TRACE_LOG),
760f66f451Sopenharmony_ci  CONF(TRACE_NAME_MAX), CONF(TRACE_SYS_MAX), CONF(TRACE_USER_EVENT_MAX),
770f66f451Sopenharmony_ci  CONF(TYPED_MEMORY_OBJECTS), CONF(VERSION), CONF(V7_ILP32_OFF32),
780f66f451Sopenharmony_ci  CONF(V7_ILP32_OFFBIG), CONF(V7_LP64_OFF64), CONF(V7_LPBIG_OFFBIG),
790f66f451Sopenharmony_ci
800f66f451Sopenharmony_ci  /* POSIX.2 */
810f66f451Sopenharmony_ci#undef CONF
820f66f451Sopenharmony_ci#define CONF(n) {"POSIX2_" #n,_SC_2_ ## n}
830f66f451Sopenharmony_ci  CONF(C_BIND), CONF(C_DEV), CONF(CHAR_TERM), CONF(FORT_DEV), CONF(FORT_RUN),
840f66f451Sopenharmony_ci  CONF(LOCALEDEF), CONF(PBS), CONF(PBS_ACCOUNTING), CONF(PBS_CHECKPOINT),
850f66f451Sopenharmony_ci  CONF(PBS_LOCATE), CONF(PBS_MESSAGE), CONF(PBS_TRACK), CONF(SW_DEV),
860f66f451Sopenharmony_ci  CONF(UPE), CONF(VERSION),
870f66f451Sopenharmony_ci
880f66f451Sopenharmony_ci  /* X/Open */
890f66f451Sopenharmony_ci#undef CONF
900f66f451Sopenharmony_ci#define CONF(n) {"_XOPEN_" #n,_SC_XOPEN_ ## n}
910f66f451Sopenharmony_ci  CONF(CRYPT), CONF(ENH_I18N), CONF(REALTIME), CONF(REALTIME_THREADS),
920f66f451Sopenharmony_ci  CONF(SHM), CONF(STREAMS), CONF(UNIX), CONF(UUCP), CONF(VERSION),
930f66f451Sopenharmony_ci
940f66f451Sopenharmony_ci  /* No obvious standard */
950f66f451Sopenharmony_ci#undef CONF
960f66f451Sopenharmony_ci#define CONF(n) {#n,_SC_ ## n}
970f66f451Sopenharmony_ci  CONF(AIO_LISTIO_MAX), CONF(AIO_MAX), CONF(AIO_PRIO_DELTA_MAX), CONF(ARG_MAX),
980f66f451Sopenharmony_ci  CONF(ATEXIT_MAX), CONF(BC_BASE_MAX), CONF(BC_DIM_MAX), CONF(BC_SCALE_MAX),
990f66f451Sopenharmony_ci  CONF(BC_STRING_MAX), CONF(CHILD_MAX), CONF(CLK_TCK), CONF(COLL_WEIGHTS_MAX),
1000f66f451Sopenharmony_ci  CONF(DELAYTIMER_MAX), CONF(EXPR_NEST_MAX), CONF(HOST_NAME_MAX),
1010f66f451Sopenharmony_ci  CONF(IOV_MAX), CONF(LINE_MAX), CONF(LOGIN_NAME_MAX), CONF(NGROUPS_MAX),
1020f66f451Sopenharmony_ci  CONF(MQ_OPEN_MAX), CONF(MQ_PRIO_MAX), CONF(OPEN_MAX), CONF(PAGE_SIZE),
1030f66f451Sopenharmony_ci  CONF(PAGESIZE), CONF(RAW_SOCKETS), CONF(RE_DUP_MAX), CONF(RTSIG_MAX),
1040f66f451Sopenharmony_ci  CONF(SEM_NSEMS_MAX), CONF(SEM_VALUE_MAX), CONF(SIGQUEUE_MAX),
1050f66f451Sopenharmony_ci  CONF(STREAM_MAX), CONF(SYMLOOP_MAX), CONF(TIMER_MAX), CONF(TTY_NAME_MAX),
1060f66f451Sopenharmony_ci  CONF(TZNAME_MAX), CONF(UIO_MAXIOV),
1070f66f451Sopenharmony_ci
1080f66f451Sopenharmony_ci  /* Names that just don't match the symbol, do it by hand */
1090f66f451Sopenharmony_ci  {"_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, {"_PHYS_PAGES", _SC_PHYS_PAGES},
1100f66f451Sopenharmony_ci  {"_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
1110f66f451Sopenharmony_ci  {"_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
1120f66f451Sopenharmony_ci
1130f66f451Sopenharmony_ci  /* There's a weird "PTHREAD" vs "THREAD" mismatch here. */
1140f66f451Sopenharmony_ci  {"PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
1150f66f451Sopenharmony_ci  {"PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
1160f66f451Sopenharmony_ci  {"PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
1170f66f451Sopenharmony_ci  {"PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
1180f66f451Sopenharmony_ci};
1190f66f451Sopenharmony_ci
1200f66f451Sopenharmony_ci// Probe the live system with a path
1210f66f451Sopenharmony_cistruct config pathconfs[] = {
1220f66f451Sopenharmony_ci#undef CONF
1230f66f451Sopenharmony_ci#define CONF(n) {#n,_PC_ ## n}
1240f66f451Sopenharmony_ci  CONF(ASYNC_IO), CONF(CHOWN_RESTRICTED), CONF(FILESIZEBITS), CONF(LINK_MAX),
1250f66f451Sopenharmony_ci  CONF(MAX_CANON), CONF(MAX_INPUT), CONF(NAME_MAX), CONF(NO_TRUNC),
1260f66f451Sopenharmony_ci  CONF(PATH_MAX), CONF(PIPE_BUF), CONF(PRIO_IO), CONF(SYMLINK_MAX),
1270f66f451Sopenharmony_ci  CONF(SYNC_IO),
1280f66f451Sopenharmony_ci  {"_POSIX_VDISABLE", _PC_VDISABLE},
1290f66f451Sopenharmony_ci};
1300f66f451Sopenharmony_ci
1310f66f451Sopenharmony_ci// Strings out of a header
1320f66f451Sopenharmony_cistruct config confstrs[] = {
1330f66f451Sopenharmony_ci#undef CONF
1340f66f451Sopenharmony_ci#define CONF(n) {#n,_CS_ ## n}
1350f66f451Sopenharmony_ci  CONF(PATH), CONF(V7_ENV)
1360f66f451Sopenharmony_ci};
1370f66f451Sopenharmony_ci
1380f66f451Sopenharmony_ci// Integers out of a header
1390f66f451Sopenharmony_cistruct config limits[] = {
1400f66f451Sopenharmony_ci#undef CONF
1410f66f451Sopenharmony_ci#define CONF(n) {#n,n}
1420f66f451Sopenharmony_ci  CONF(_POSIX_AIO_LISTIO_MAX), CONF(_POSIX_AIO_MAX), CONF(_POSIX_ARG_MAX),
1430f66f451Sopenharmony_ci  CONF(_POSIX_CHILD_MAX), CONF(_POSIX_DELAYTIMER_MAX),
1440f66f451Sopenharmony_ci  CONF(_POSIX_HOST_NAME_MAX), CONF(_POSIX_LINK_MAX),
1450f66f451Sopenharmony_ci  CONF(_POSIX_LOGIN_NAME_MAX), CONF(_POSIX_MAX_CANON),
1460f66f451Sopenharmony_ci  CONF(_POSIX_MAX_INPUT), CONF(_POSIX_NAME_MAX), CONF(_POSIX_NGROUPS_MAX),
1470f66f451Sopenharmony_ci  CONF(_POSIX_OPEN_MAX), CONF(_POSIX_PATH_MAX), CONF(_POSIX_PIPE_BUF),
1480f66f451Sopenharmony_ci  CONF(_POSIX_RE_DUP_MAX), CONF(_POSIX_RTSIG_MAX), CONF(_POSIX_SEM_NSEMS_MAX),
1490f66f451Sopenharmony_ci  CONF(_POSIX_SEM_VALUE_MAX), CONF(_POSIX_SIGQUEUE_MAX), CONF(_POSIX_SSIZE_MAX),
1500f66f451Sopenharmony_ci  CONF(_POSIX_STREAM_MAX), CONF(_POSIX_SYMLINK_MAX), CONF(_POSIX_SYMLOOP_MAX),
1510f66f451Sopenharmony_ci  CONF(_POSIX_THREAD_DESTRUCTOR_ITERATIONS), CONF(_POSIX_THREAD_KEYS_MAX),
1520f66f451Sopenharmony_ci  CONF(_POSIX_THREAD_THREADS_MAX), CONF(_POSIX_TIMER_MAX),
1530f66f451Sopenharmony_ci  CONF(_POSIX_TTY_NAME_MAX), CONF(_POSIX_TZNAME_MAX),
1540f66f451Sopenharmony_ci  CONF(CHAR_MAX), CONF(CHAR_MIN), CONF(INT_MAX), CONF(INT_MIN), CONF(SCHAR_MAX),
1550f66f451Sopenharmony_ci  CONF(SCHAR_MIN), CONF(SHRT_MAX), CONF(SHRT_MIN), CONF(SSIZE_MAX),
1560f66f451Sopenharmony_ci  CONF(UCHAR_MAX), CONF(UINT_MAX), CONF(ULONG_MAX), CONF(USHRT_MAX),
1570f66f451Sopenharmony_ci  CONF(CHAR_BIT),
1580f66f451Sopenharmony_ci  /* Not available in glibc without _GNU_SOURCE. */
1590f66f451Sopenharmony_ci  {"LONG_BIT", 8*sizeof(long)},
1600f66f451Sopenharmony_ci  {"WORD_BIT", 8*sizeof(int)},
1610f66f451Sopenharmony_ci#undef CONF
1620f66f451Sopenharmony_ci#define CONF(n) {#n,_ ## n}
1630f66f451Sopenharmony_ci  CONF(POSIX2_BC_BASE_MAX), CONF(POSIX2_BC_DIM_MAX),
1640f66f451Sopenharmony_ci  CONF(POSIX2_BC_SCALE_MAX), CONF(POSIX2_BC_STRING_MAX),
1650f66f451Sopenharmony_ci  CONF(POSIX2_CHARCLASS_NAME_MAX), CONF(POSIX2_COLL_WEIGHTS_MAX),
1660f66f451Sopenharmony_ci  CONF(POSIX2_EXPR_NEST_MAX), CONF(POSIX2_LINE_MAX), CONF(POSIX2_RE_DUP_MAX),
1670f66f451Sopenharmony_ci};
1680f66f451Sopenharmony_ci
1690f66f451Sopenharmony_ci// Names we need to handle ourselves (default to blank but shouldn't error)
1700f66f451Sopenharmony_cistruct config others[] = {
1710f66f451Sopenharmony_ci  {"LFS_CFLAGS", 0}, {"LFS_LDFLAGS", 0}, {"LFS_LIBS", 0}
1720f66f451Sopenharmony_ci};
1730f66f451Sopenharmony_ci
1740f66f451Sopenharmony_cistatic void show_conf(int i, struct config *c, const char *path)
1750f66f451Sopenharmony_ci{
1760f66f451Sopenharmony_ci  if (i<2) {
1770f66f451Sopenharmony_ci    long l = i ? pathconf(path, c->value) : sysconf(c->value);
1780f66f451Sopenharmony_ci
1790f66f451Sopenharmony_ci    if (l == -1) puts("undefined");
1800f66f451Sopenharmony_ci    else printf("%ld\n", l);
1810f66f451Sopenharmony_ci  } else if (i==2) {
1820f66f451Sopenharmony_ci    confstr(c->value, toybuf, sizeof(toybuf));
1830f66f451Sopenharmony_ci    puts(toybuf);
1840f66f451Sopenharmony_ci  } else if (i==3) printf("%lld\n", c->value);
1850f66f451Sopenharmony_ci  // LFS_CFLAGS on 32 bit should enable Large File Support for kernel builds
1860f66f451Sopenharmony_ci  else puts(sizeof(long)==4 && !strcmp(c->name, "LFS_CFLAGS") ?
1870f66f451Sopenharmony_ci    "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" : "");
1880f66f451Sopenharmony_ci}
1890f66f451Sopenharmony_ci
1900f66f451Sopenharmony_civoid getconf_main(void)
1910f66f451Sopenharmony_ci{
1920f66f451Sopenharmony_ci  struct config *configs[] = {sysconfs, pathconfs, confstrs, limits, others},
1930f66f451Sopenharmony_ci    *c = NULL;
1940f66f451Sopenharmony_ci  int i, j, lens[] = {ARRAY_LEN(sysconfs), ARRAY_LEN(pathconfs),
1950f66f451Sopenharmony_ci    ARRAY_LEN(confstrs), ARRAY_LEN(limits), ARRAY_LEN(others)};
1960f66f451Sopenharmony_ci  char *name, *path = (toys.optc==2) ? toys.optargs[1] : "/",
1970f66f451Sopenharmony_ci    *config_names[] = {"sysconf(3)", "pathconf(3)", "confstr(3)",
1980f66f451Sopenharmony_ci    "<limits.h>", "Misc"};
1990f66f451Sopenharmony_ci
2000f66f451Sopenharmony_ci  if (toys.optflags&FLAG_a) {
2010f66f451Sopenharmony_ci    for (i = 0; i<5; i++) {
2020f66f451Sopenharmony_ci      for (j = 0; j<lens[i]; j++) {
2030f66f451Sopenharmony_ci        c = &configs[i][j];
2040f66f451Sopenharmony_ci        printf("%-34s ", c->name);
2050f66f451Sopenharmony_ci        show_conf(i, c, path);
2060f66f451Sopenharmony_ci      }
2070f66f451Sopenharmony_ci    }
2080f66f451Sopenharmony_ci    return;
2090f66f451Sopenharmony_ci  }
2100f66f451Sopenharmony_ci
2110f66f451Sopenharmony_ci  if (toys.optflags&FLAG_l) {
2120f66f451Sopenharmony_ci    for (i = 0; i<5; i++) {
2130f66f451Sopenharmony_ci      printf("%s\n", config_names[i]);
2140f66f451Sopenharmony_ci      for (j = 0; j<lens[i]; j++) printf("  %s\n", configs[i][j].name);
2150f66f451Sopenharmony_ci    }
2160f66f451Sopenharmony_ci    return;
2170f66f451Sopenharmony_ci  }
2180f66f451Sopenharmony_ci
2190f66f451Sopenharmony_ci  if (toys.optc<1) help_exit(0);
2200f66f451Sopenharmony_ci  name = *toys.optargs;
2210f66f451Sopenharmony_ci
2220f66f451Sopenharmony_ci  // Workaround for autogen using CS_PATH instead of PATH
2230f66f451Sopenharmony_ci  if (!strcmp("CS_PATH", name)) name += 3;
2240f66f451Sopenharmony_ci
2250f66f451Sopenharmony_ci  // Find the config.
2260f66f451Sopenharmony_ci  for (i = j = 0; ; j++) {
2270f66f451Sopenharmony_ci    if (j==lens[i]) j = 0, i++;
2280f66f451Sopenharmony_ci    if (i==5) error_exit("bad '%s'", name);
2290f66f451Sopenharmony_ci    c = &configs[i][j];
2300f66f451Sopenharmony_ci    if (!strcmp(c->name, name)) break;
2310f66f451Sopenharmony_ci  }
2320f66f451Sopenharmony_ci
2330f66f451Sopenharmony_ci  // Check that we do/don't have the extra path argument.
2340f66f451Sopenharmony_ci  if (i==1) {
2350f66f451Sopenharmony_ci    if (toys.optc!=2) help_exit("%s needs a path", name);
2360f66f451Sopenharmony_ci  } else if (toys.optc!=1) help_exit("%s does not take a path", name);
2370f66f451Sopenharmony_ci
2380f66f451Sopenharmony_ci  show_conf(i, c, path);
2390f66f451Sopenharmony_ci}
240