1 /* $OpenBSD: getconf.c,v 1.16 2013/03/28 03:29:45 guenther Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by J.T. Conklin. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Winning Strategies, Inc. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* 37 * POSIX.2 getconf utility 38 * 39 * Written by: 40 * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. 41 */ 42 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <limits.h> 47 #include <locale.h> 48 #include <unistd.h> 49 #include <err.h> 50 #include <errno.h> 51 52 static void usage(void); 53 static void list_var(int); 54 static int compilation_spec_valid(const char *); 55 56 struct conf_variable 57 { 58 const char *name; 59 enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT } type; 60 long value; 61 }; 62 63 64 #define constant_row(name) { #name, CONSTANT, name }, 65 #define sysconf_row(name) { #name, SYSCONF, _SC_##name }, 66 #define pathconf_row(name) { #name, PATHCONF, _PC_##name }, 67 #define confstr_row(name) { #name, CONFSTR, _CS_##name }, 68 #define posix_constant_row(name) { #name, CONSTANT, _POSIX_##name }, 69 #define posix_confstr_row(name) { #name, CONFSTR, _CS_POSIX_##name }, 70 #define compat_posix2_sysconf_row(name) { #name, SYSCONF, _SC_2_##name }, 71 #define compat_posix2_constant_row(name) { #name, CONSTANT, _POSIX2_##name }, 72 73 /* Some sysconf variables don't follow the pattern of the others */ 74 #define posix2_sysconf_row(name) \ 75 { "_POSIX2_" #name, SYSCONF, _SC_2_##name }, 76 #define posix2_pathconf_row(name) \ 77 { "_POSIX2_" #name, PATHCONF, _PC_2_##name }, 78 #define pthread_sysconf_row(name) \ 79 { "_PTHREAD_" #name, SYSCONF, _SC_THREAD_##name }, 80 #define xopen_sysconf_row(name) \ 81 { "_XOPEN_" #name, SYSCONF, _SC_XOPEN_##name }, 82 83 const struct conf_variable conf_table[] = 84 { 85 /* Configuration strings */ 86 confstr_row(PATH) 87 confstr_row(V7_ENV) 88 confstr_row(V6_ENV) 89 90 /* Symbolic Utility Limits */ 91 sysconf_row(BC_BASE_MAX) 92 sysconf_row(BC_DIM_MAX) 93 sysconf_row(BC_SCALE_MAX) 94 sysconf_row(BC_STRING_MAX) 95 sysconf_row(COLL_WEIGHTS_MAX) 96 sysconf_row(EXPR_NEST_MAX) 97 sysconf_row(LINE_MAX) 98 sysconf_row(RE_DUP_MAX) 99 100 /* POSIX.1 Configurable System Variables */ 101 sysconf_row(AIO_LISTIO_MAX) 102 sysconf_row(AIO_MAX) 103 sysconf_row(AIO_PRIO_DELTA_MAX) 104 sysconf_row(ARG_MAX) 105 sysconf_row(CHILD_MAX) 106 sysconf_row(CLK_TCK) 107 sysconf_row(NGROUPS_MAX) 108 sysconf_row(OPEN_MAX) 109 sysconf_row(STREAM_MAX) 110 sysconf_row(TZNAME_MAX) 111 sysconf_row(PAGE_SIZE) 112 sysconf_row(PAGESIZE) 113 114 sysconf_row(SEM_NSEMS_MAX) 115 sysconf_row(SEM_VALUE_MAX) 116 sysconf_row(HOST_NAME_MAX) 117 sysconf_row(LOGIN_NAME_MAX) 118 119 sysconf_row(ATEXIT_MAX) 120 sysconf_row(DELAYTIMER_MAX) 121 sysconf_row(IOV_MAX) 122 sysconf_row(MQ_OPEN_MAX) 123 sysconf_row(MQ_PRIO_MAX) 124 sysconf_row(RTSIG_MAX) 125 sysconf_row(SIGQUEUE_MAX) 126 sysconf_row(SYMLOOP_MAX) 127 sysconf_row(TIMER_MAX) 128 sysconf_row(TTY_NAME_MAX) 129 130 posix2_sysconf_row(PBS) 131 posix2_sysconf_row(PBS_ACCOUNTING) 132 posix2_sysconf_row(PBS_CHECKPOINT) 133 posix2_sysconf_row(PBS_LOCATE) 134 posix2_sysconf_row(PBS_MESSAGE) 135 posix2_sysconf_row(PBS_TRACK) 136 137 pthread_sysconf_row(DESTRUCTOR_ITERATIONS) 138 pthread_sysconf_row(KEYS_MAX) 139 pthread_sysconf_row(STACK_MIN) 140 pthread_sysconf_row(THREADS_MAX) 141 142 xopen_sysconf_row(SHM) 143 xopen_sysconf_row(CRYPT) 144 xopen_sysconf_row(ENH_I18N) 145 xopen_sysconf_row(REALTIME) 146 xopen_sysconf_row(REALTIME_THREADS) 147 xopen_sysconf_row(STREAMS) 148 xopen_sysconf_row(UNIX) 149 xopen_sysconf_row(UUCP) 150 xopen_sysconf_row(VERSION) 151 152 pathconf_row(FILESIZEBITS) 153 pathconf_row(LINK_MAX) 154 pathconf_row(MAX_CANON) 155 pathconf_row(MAX_INPUT) 156 pathconf_row(NAME_MAX) 157 pathconf_row(PATH_MAX) 158 pathconf_row(PIPE_BUF) 159 pathconf_row(SYMLINK_MAX) 160 161 posix2_pathconf_row(SYMLINKS) 162 163 constant_row(_POSIX2_CHARCLASS_NAME_MAX) 164 constant_row(_XOPEN_IOV_MAX) 165 constant_row(_XOPEN_NAME_MAX) 166 constant_row(_XOPEN_PATH_MAX) 167 168 { NULL } 169 }; 170 171 /* 172 * Lots of names have a leading "_POSIX_", so put them in a table with 173 * that prefix trimmed 174 */ 175 const char uposix_prefix[] = "_POSIX_"; 176 const struct conf_variable uposix_conf_table[] = 177 { 178 /* POSIX.1 Maximum Values */ 179 posix_constant_row(CLOCKRES_MIN) 180 181 /* POSIX.1 Minimum Values */ 182 /*posix_constant_row(AIO_LISTIO_MAX)*/ 183 /*posix_constant_row(AIO_MAX)*/ 184 posix_constant_row(ARG_MAX) 185 posix_constant_row(CHILD_MAX) 186 /*posix_constant_row(DELAYTIMER_MAX)*/ 187 posix_constant_row(HOST_NAME_MAX) 188 posix_constant_row(LINK_MAX) 189 posix_constant_row(LOGIN_NAME_MAX) 190 posix_constant_row(MAX_CANON) 191 posix_constant_row(MAX_INPUT) 192 /*posix_constant_row(MQ_OPEN_MAX)*/ 193 /*posix_constant_row(MQ_PRIO_MAX)*/ 194 posix_constant_row(NAME_MAX) 195 posix_constant_row(NGROUPS_MAX) 196 posix_constant_row(OPEN_MAX) 197 posix_constant_row(PATH_MAX) 198 posix_constant_row(PIPE_BUF) 199 posix_constant_row(RE_DUP_MAX) 200 /*posix_constant_row(RTSIG_MAX)*/ 201 posix_constant_row(SEM_NSEMS_MAX) 202 posix_constant_row(SEM_VALUE_MAX) 203 /*posix_constant_row(SIGQUEUE_MAX)*/ 204 posix_constant_row(SSIZE_MAX) 205 /*posix_constant_row(SS_REPL_MAX)*/ 206 posix_constant_row(STREAM_MAX) 207 posix_constant_row(SYMLINK_MAX) 208 posix_constant_row(SYMLOOP_MAX) 209 posix_constant_row(THREAD_DESTRUCTOR_ITERATIONS) 210 posix_constant_row(THREAD_KEYS_MAX) 211 posix_constant_row(THREAD_THREADS_MAX) 212 /*posix_constant_row(TIMER_MAX)*/ 213 posix_constant_row(TTY_NAME_MAX) 214 posix_constant_row(TZNAME_MAX) 215 216 /* POSIX.1 Configurable System Variables */ 217 sysconf_row(JOB_CONTROL) 218 sysconf_row(SAVED_IDS) 219 sysconf_row(VERSION) 220 sysconf_row(FSYNC) 221 sysconf_row(MONOTONIC_CLOCK) 222 sysconf_row(THREAD_SAFE_FUNCTIONS) 223 sysconf_row(ADVISORY_INFO) 224 sysconf_row(BARRIERS) 225 sysconf_row(ASYNCHRONOUS_IO) 226 sysconf_row(CLOCK_SELECTION) 227 sysconf_row(CPUTIME) 228 sysconf_row(IPV6) 229 sysconf_row(MAPPED_FILES) 230 sysconf_row(MEMLOCK) 231 sysconf_row(MEMLOCK_RANGE) 232 sysconf_row(MEMORY_PROTECTION) 233 sysconf_row(MESSAGE_PASSING) 234 sysconf_row(PRIORITIZED_IO) 235 sysconf_row(PRIORITY_SCHEDULING) 236 sysconf_row(RAW_SOCKETS) 237 sysconf_row(READER_WRITER_LOCKS) 238 sysconf_row(REALTIME_SIGNALS) 239 sysconf_row(REGEXP) 240 sysconf_row(SEMAPHORES) 241 sysconf_row(SHARED_MEMORY_OBJECTS) 242 sysconf_row(SHELL) 243 sysconf_row(SPAWN) 244 sysconf_row(SPIN_LOCKS) 245 sysconf_row(SPORADIC_SERVER) 246 sysconf_row(SS_REPL_MAX) 247 sysconf_row(SYNCHRONIZED_IO) 248 sysconf_row(THREAD_ATTR_STACKADDR) 249 sysconf_row(THREAD_ATTR_STACKSIZE) 250 sysconf_row(THREAD_CPUTIME) 251 sysconf_row(THREAD_PRIO_INHERIT) 252 sysconf_row(THREAD_PRIO_PROTECT) 253 sysconf_row(THREAD_PRIORITY_SCHEDULING) 254 sysconf_row(THREAD_PROCESS_SHARED) 255 sysconf_row(THREAD_ROBUST_PRIO_INHERIT) 256 sysconf_row(THREAD_SPORADIC_SERVER) 257 sysconf_row(THREADS) 258 sysconf_row(TIMEOUTS) 259 sysconf_row(TIMERS) 260 sysconf_row(TRACE) 261 sysconf_row(TRACE_EVENT_FILTER) 262 sysconf_row(TRACE_EVENT_NAME_MAX) 263 sysconf_row(TRACE_INHERIT) 264 sysconf_row(TRACE_LOG) 265 sysconf_row(TRACE_NAME_MAX) 266 sysconf_row(TRACE_SYS_MAX) 267 sysconf_row(TRACE_USER_EVENT_MAX) 268 sysconf_row(TYPED_MEMORY_OBJECTS) 269 270 /* 271 * If new compilation specification are added (V8_*?) then add them 272 * to the compilation_specs array below too 273 */ 274 sysconf_row(V7_ILP32_OFF32) 275 sysconf_row(V7_ILP32_OFFBIG) 276 sysconf_row(V7_LP64_OFF64) 277 sysconf_row(V7_LPBIG_OFFBIG) 278 sysconf_row(V6_ILP32_OFF32) 279 sysconf_row(V6_ILP32_OFFBIG) 280 sysconf_row(V6_LP64_OFF64) 281 sysconf_row(V6_LPBIG_OFFBIG) 282 283 /* POSIX.1 Configurable Path Variables */ 284 pathconf_row(CHOWN_RESTRICTED) 285 pathconf_row(NO_TRUNC) 286 pathconf_row(VDISABLE) 287 pathconf_row(ASYNC_IO) 288 pathconf_row(PRIO_IO) 289 pathconf_row(SYNC_IO) 290 pathconf_row(TIMESTAMP_RESOLUTION) 291 292 { NULL } 293 }; 294 295 /* 296 * Then there are the "POSIX_*" values 297 */ 298 const char posix_prefix[] = "POSIX_"; 299 const struct conf_variable posix_conf_table[] = 300 { 301 pathconf_row(ALLOC_SIZE_MIN) 302 pathconf_row(REC_INCR_XFER_SIZE) 303 pathconf_row(REC_MAX_XFER_SIZE) 304 pathconf_row(REC_MIN_XFER_SIZE) 305 pathconf_row(REC_XFER_ALIGN) 306 307 posix_confstr_row(V7_ILP32_OFF32_CFLAGS) 308 posix_confstr_row(V7_ILP32_OFF32_LDFLAGS) 309 posix_confstr_row(V7_ILP32_OFF32_LIBS) 310 posix_confstr_row(V7_ILP32_OFFBIG_CFLAGS) 311 posix_confstr_row(V7_ILP32_OFFBIG_LDFLAGS) 312 posix_confstr_row(V7_ILP32_OFFBIG_LIBS) 313 posix_confstr_row(V7_LP64_OFF64_CFLAGS) 314 posix_confstr_row(V7_LP64_OFF64_LDFLAGS) 315 posix_confstr_row(V7_LP64_OFF64_LIBS) 316 posix_confstr_row(V7_LPBIG_OFFBIG_CFLAGS) 317 posix_confstr_row(V7_LPBIG_OFFBIG_LDFLAGS) 318 posix_confstr_row(V7_LPBIG_OFFBIG_LIBS) 319 posix_confstr_row(V7_THREADS_CFLAGS) 320 posix_confstr_row(V7_THREADS_LDFLAGS) 321 posix_confstr_row(V7_WIDTH_RESTRICTED_ENVS) 322 posix_confstr_row(V6_ILP32_OFF32_CFLAGS) 323 posix_confstr_row(V6_ILP32_OFF32_LDFLAGS) 324 posix_confstr_row(V6_ILP32_OFF32_LIBS) 325 posix_confstr_row(V6_ILP32_OFFBIG_CFLAGS) 326 posix_confstr_row(V6_ILP32_OFFBIG_LDFLAGS) 327 posix_confstr_row(V6_ILP32_OFFBIG_LIBS) 328 posix_confstr_row(V6_LP64_OFF64_CFLAGS) 329 posix_confstr_row(V6_LP64_OFF64_LDFLAGS) 330 posix_confstr_row(V6_LP64_OFF64_LIBS) 331 posix_confstr_row(V6_LPBIG_OFFBIG_CFLAGS) 332 posix_confstr_row(V6_LPBIG_OFFBIG_LDFLAGS) 333 posix_confstr_row(V6_LPBIG_OFFBIG_LIBS) 334 posix_confstr_row(V6_WIDTH_RESTRICTED_ENVS) 335 336 { NULL } 337 }; 338 339 /* 340 * Finally, there are variables that are accepted with a prefix 341 * of either "_POSIX2_" or "POSIX2_" 342 */ 343 const char compat_posix2_prefix[] = "POSIX2_"; 344 const struct conf_variable compat_posix2_conf_table[] = 345 { 346 /* Optional Facility Configuration Values */ 347 compat_posix2_sysconf_row(VERSION) 348 compat_posix2_sysconf_row(C_BIND) 349 compat_posix2_sysconf_row(C_DEV) 350 compat_posix2_sysconf_row(CHAR_TERM) 351 compat_posix2_sysconf_row(FORT_DEV) 352 compat_posix2_sysconf_row(FORT_RUN) 353 compat_posix2_sysconf_row(LOCALEDEF) 354 compat_posix2_sysconf_row(SW_DEV) 355 compat_posix2_sysconf_row(UPE) 356 357 /* Utility Limit Minimum Values */ 358 compat_posix2_constant_row(BC_BASE_MAX) 359 compat_posix2_constant_row(BC_DIM_MAX) 360 compat_posix2_constant_row(BC_SCALE_MAX) 361 compat_posix2_constant_row(BC_STRING_MAX) 362 compat_posix2_constant_row(COLL_WEIGHTS_MAX) 363 compat_posix2_constant_row(EXPR_NEST_MAX) 364 compat_posix2_constant_row(LINE_MAX) 365 compat_posix2_constant_row(RE_DUP_MAX) 366 367 { NULL } 368 }; 369 370 #undef constant_row 371 #undef sysconf_row 372 #undef pathconf_row 373 #undef confstr_row 374 #undef posix_constant_row 375 #undef posix_confstr_row 376 #undef compat_posix2_sysconf_row 377 #undef compat_posix2_constant_row 378 379 380 /* 381 * What values are possibly accepted by the -v option? 382 * These are implied to have a prefix of posix_prefix 383 */ 384 const char *compilation_specs[] = { 385 "V7_ILP32_OFF32", 386 "V7_ILP32_OFFBIG", 387 "V7_LP64_OFF64", 388 "V7_LPBIG_OFFBIG", 389 "V6_ILP32_OFF32", 390 "V6_ILP32_OFFBIG", 391 "V6_LP64_OFF64", 392 "V6_LPBIG_OFFBIG", 393 NULL 394 }; 395 396 int 397 main(int argc, char *argv[]) 398 { 399 int ch; 400 const struct conf_variable *cp; 401 402 long val; 403 size_t slen; 404 char * sval; 405 406 setlocale(LC_ALL, ""); 407 408 while ((ch = getopt(argc, argv, "lLv:")) != -1) { 409 switch (ch) { 410 case 'l': /* nonstandard: list system variables */ 411 list_var(0); 412 return (0); 413 case 'L': /* nonstandard: list path variables */ 414 list_var(1); 415 return (0); 416 case 'v': 417 if (! compilation_spec_valid(optarg)) 418 errx(1, "%s: unknown specification", optarg); 419 break; 420 case '?': 421 default: 422 usage(); 423 } 424 } 425 argc -= optind; 426 argv += optind; 427 428 if (argc < 1 || argc > 2) 429 usage(); 430 431 /* pick a table based on a possible prefix */ 432 if (strncmp(*argv, uposix_prefix, sizeof(uposix_prefix) - 1) == 0) { 433 cp = uposix_conf_table; 434 slen = sizeof(uposix_prefix) - 1; 435 } else if (strncmp(*argv, posix_prefix, 436 sizeof(posix_prefix) - 1) == 0) { 437 cp = posix_conf_table; 438 slen = sizeof(posix_prefix) - 1; 439 } else { 440 cp = conf_table; 441 slen = 0; 442 } 443 444 /* scan the table */ 445 for (; cp->name != NULL; cp++) 446 if (strcmp(*argv + slen, cp->name) == 0) 447 break; 448 449 /* 450 * If no match, then make a final check against 451 * compat_posix2_conf_table, with special magic to accept/skip 452 * a leading underbar 453 */ 454 slen = argv[0][0] == '_'; 455 if (cp->name == NULL && strncmp(*argv + slen, compat_posix2_prefix, 456 sizeof(compat_posix2_prefix) - 1) == 0) { 457 slen += sizeof(compat_posix2_prefix) - 1; 458 for (cp = compat_posix2_conf_table; cp->name != NULL; cp++) { 459 if (strcmp(*argv + slen, cp->name) == 0) 460 break; 461 } 462 } 463 464 if (cp->name == NULL) 465 errx(1, "%s: unknown variable", *argv); 466 467 if (cp->type == PATHCONF) { 468 if (argc != 2) usage(); 469 } else { 470 if (argc != 1) usage(); 471 } 472 473 switch (cp->type) { 474 case CONSTANT: 475 printf("%ld\n", cp->value); 476 break; 477 478 case CONFSTR: 479 errno = 0; 480 if ((slen = confstr(cp->value, NULL, 0)) == 0) { 481 if (errno != 0) 482 err(1, NULL); 483 484 printf("undefined\n"); 485 } else { 486 if ((sval = malloc(slen)) == NULL) 487 err(1, NULL); 488 489 confstr(cp->value, sval, slen); 490 printf("%s\n", sval); 491 } 492 break; 493 494 case SYSCONF: 495 errno = 0; 496 if ((val = sysconf(cp->value)) == -1) { 497 if (errno != 0) 498 err(1, NULL); 499 500 printf("undefined\n"); 501 } else { 502 printf("%ld\n", val); 503 } 504 break; 505 506 case PATHCONF: 507 errno = 0; 508 if ((val = pathconf(argv[1], cp->value)) == -1) { 509 if (errno != 0) 510 err(1, "%s", argv[1]); 511 512 printf("undefined\n"); 513 } else { 514 printf("%ld\n", val); 515 } 516 break; 517 } 518 519 exit(ferror(stdout)); 520 } 521 522 523 static void 524 usage(void) 525 { 526 extern char *__progname; 527 528 (void)fprintf(stderr, 529 "usage: %s [-Ll] [-v specification] name [pathname]\n", 530 __progname); 531 exit(1); 532 } 533 534 static void 535 list_var(int do_pathconf) 536 { 537 const struct conf_variable *cp; 538 539 for (cp = uposix_conf_table; cp->name != NULL; cp++) 540 if ((cp->type == PATHCONF) == do_pathconf) 541 printf("%s%s\n", uposix_prefix, cp->name); 542 for (cp = posix_conf_table; cp->name != NULL; cp++) 543 if ((cp->type == PATHCONF) == do_pathconf) 544 printf("%s%s\n", posix_prefix, cp->name); 545 for (cp = conf_table; cp->name != NULL; cp++) 546 if ((cp->type == PATHCONF) == do_pathconf) 547 printf("%s\n", cp->name); 548 for (cp = compat_posix2_conf_table; cp->name != NULL; cp++) 549 if ((cp->type == PATHCONF) == do_pathconf) 550 printf("_%s%s\n", compat_posix2_prefix, cp->name); 551 } 552 553 static int 554 compilation_spec_valid(const char *spec) 555 { 556 const char **sp; 557 const struct conf_variable *cp; 558 559 if (strncmp(spec, posix_prefix, sizeof(posix_prefix) - 1) != 0) 560 return (0); 561 562 spec += sizeof(posix_prefix) - 1; 563 for (sp = compilation_specs; *sp != NULL; sp++) 564 if (strcmp(spec, *sp) == 0) 565 break; 566 if (*sp == NULL) 567 return (0); 568 569 for (cp = uposix_conf_table; cp->name != NULL; cp++) 570 if (strcmp(spec, cp->name) == 0 && cp->type == SYSCONF) 571 return (sysconf(cp->value) != -1); 572 573 return (0); 574 } 575