/* $Id$ */ /* Copyright (c) 2020 Pierre Pronchery */ /* This file is part of DeforaOS Unix utils */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include /* constants */ #ifndef PROGNAME # define PROGNAME "getconf" #endif /* getconf */ /* private */ /* types */ typedef struct _getconf_catalog { long name; char const * string; } getconf_catalog; /* constants */ static const getconf_catalog _getconf_catalog_confstr[] = { #ifdef _CS_PATH { _CS_PATH, "_CS_PATH" }, #endif }; static const getconf_catalog _getconf_catalog_pathconf[] = { #ifdef _PC_2_SYMLINKS { _PC_2_SYMLINKS, "POSIX2_SYMLINKS" }, #endif #ifdef _PC_ALLOC_SIZE_MIN { _PC_ALLOC_SIZE_MIN, "POSIX_ALLOC_SIZE_MIN" }, #endif #ifdef _PC_ASYNC_IO { _PC_ASYNC_IO, "_POSIX_ASYNC_IO" }, #endif #ifdef _PC_CHOWN_RESTRICTED { _PC_CHOWN_RESTRICTED, "POSIX_CHOWN_RESTRICTED" }, #endif #ifdef _PC_FILESIZEBITS { _PC_FILESIZEBITS, "FILESIZEBITS" }, #endif #ifdef _PC_LINK_MAX { _PC_LINK_MAX, "LINK_MAX" }, #endif #ifdef _PC_MAX_CANON { _PC_MAX_CANON, "MAX_CANON" }, #endif #ifdef _PC_MAX_INPUT { _PC_MAX_INPUT, "MAX_INPUT" }, #endif #ifdef _PC_NAME_MAX { _PC_NAME_MAX, "NAME_MAX" }, #endif #ifdef _PC_NO_TRUNC { _PC_NO_TRUNC, "POSIX_NO_TRUNC" }, #endif #ifdef _PC_PATH_MAX { _PC_PATH_MAX, "PATH_MAX" }, #endif #ifdef _PC_PIPE_BUF { _PC_PIPE_BUF, "PIPE_BUF" }, #endif #ifdef _PC_PRIO_IO { _PC_PRIO_IO, "_POSIX_PRIO_IO" }, #endif #ifdef _PC_REC_INCR_XFER_SIZE { _PC_REC_INCR_XFER_SIZE, "POSIX_REC_INCR_XFER_SIZE" }, #endif #ifdef _PC_REC_MAX_XFER_SIZE { _PC_REC_MAX_XFER_SIZE, "POSIX_REC_MAX_XFER_SIZE" }, #endif #ifdef _PC_REC_MIN_XFER_SIZE { _PC_REC_MIN_XFER_SIZE, "POSIX_REC_MIN_XFER_SIZE" }, #endif #ifdef _PC_REC_XFER_ALIGN { _PC_REC_XFER_ALIGN, "POSIX_REC_XFER_ALIGN" }, #endif #ifdef _PC_SYMLINK_MAX { _PC_SYMLINK_MAX, "SYMLINK_MAX" }, #endif #ifdef _PC_SYNC_IO { _PC_SYNC_IO, "_POSIX_SYNC_IO" }, #endif #ifdef _PC_TIMESTAMP_RESOLUTION { _PC_TIMESTAMP_RESOLUTION, "_POSIX_TIMESTAMP_RESOLUTION" }, #endif #ifdef _PC_VDISABLE { _PC_VDISABLE, "_POSIX_VDISABLE" }, #endif }; static const getconf_catalog _getconf_catalog_sysconf[] = { #ifdef _SC_2_C_BIND { _SC_2_C_BIND, "_POSIX2_C_BIND" }, #endif #ifdef _SC_2_C_DEV { _SC_2_C_DEV, "_POSIX2_C_DEV" }, #endif #ifdef _SC_2_CHAR_TERM { _SC_2_CHAR_TERM, "_POSIX2_CHAR_TERM" }, #endif #ifdef _SC_2_FORT_DEV { _SC_2_FORT_DEV, "_POSIX2_FORT_DEV" }, #endif #ifdef _SC_2_FORT_RUN { _SC_2_FORT_RUN, "_POSIX2_FORT_RUN" }, #endif #ifdef _SC_2_LOCALEDEF { _SC_2_LOCALEDEF, "_POSIX2_LOCALEDEF" }, #endif #ifdef _SC_2_PBS { _SC_2_PBS, "_POSIX2_PBS" }, #endif #ifdef _SC_2_PBS_ACCOUNTING { _SC_2_PBS_ACCOUNTING, "_POSIX2_PBS_ACCOUNTING" }, #endif #ifdef _SC_2_PBS_CHECKPOINT { _SC_2_PBS_CHECKPOINT, "_POSIX2_PBS_CHECKPOINT" }, #endif #ifdef _SC_2_PBS_LOCATE { _SC_2_PBS_LOCATE, "_POSIX2_PBS_LOCATE" }, #endif #ifdef _SC_2_PBS_MESSAGE { _SC_2_PBS_MESSAGE, "_POSIX2_PBS_MESSAGE" }, #endif #ifdef _SC_2_PBS_TRACK { _SC_2_PBS_TRACK, "_POSIX2_PBS_TRACK" }, #endif #ifdef _SC_2_SW_DEV { _SC_2_SW_DEV, "_POSIX2_SW_DEV" }, #endif #ifdef _SC_2_UPE { _SC_2_UPE, "_POSIX2_UPE" }, #endif #ifdef _SC_2_VERSION { _SC_2_VERSION, "_POSIX2_VERSION" }, #endif #ifdef _SC_AIO_LISTIO_MAX { _SC_AIO_LISTIO_MAX, "AIO_LISTIO_MAX" }, #endif #ifdef _SC_AIO_MAX { _SC_AIO_MAX, "AIO_MAX" }, #endif #ifdef _SC_ARG_MAX { _SC_ARG_MAX, "ARG_MAX" }, #endif #ifdef _SC_ATEXIT_MAX { _SC_ATEXIT_MAX, "ATEXIT_MAX" }, #endif #ifdef _SC_CHILD_MAX { _SC_CHILD_MAX, "CHILD_MAX" }, #endif #ifdef _SC_DELAYTIMER_MAX { _SC_DELAYTIMER_MAX, "DELAYTIMER_MAX" }, #endif #ifdef _SC_EXPR_NEST_MAX { _SC_EXPR_NEST_MAX, "EXPR_NEST_MAX" }, #endif #ifdef _SC_HOST_NAME_MAX { _SC_HOST_NAME_MAX, "HOST_NAME_MAX" }, #endif #ifdef _SC_IOV_MAX { _SC_IOV_MAX, "IOV_MAX" }, #endif #ifdef _SC_LINE_MAX { _SC_LINE_MAX, "LINE_MAX" }, #endif #ifdef _SC_LOGIN_NAME_MAX { _SC_LOGIN_NAME_MAX, "LOGIN_NAME_MAX" }, #endif #ifdef _SC_NGROUPS_MAX { _SC_NGROUPS_MAX, "NGROUPS_MAX" }, #endif #ifdef _SC_OPEN_MAX { _SC_OPEN_MAX, "OPEN_MAX" }, #endif #ifdef _SC_PAGE_SIZE { _SC_PAGE_SIZE, "PAGE_SIZE" }, #endif #ifdef _SC_PAGESIZE { _SC_PAGESIZE, "PAGESIZE" }, #endif #ifdef _SC_STREAM_MAX { _SC_STREAM_MAX, "STREAM_MAX" }, #endif #ifdef _SC_SYMLOOP_MAX { _SC_SYMLOOP_MAX, "SYMLOOP_MAX" }, #endif #ifdef _SC_TIMER_MAX { _SC_TIMER_MAX, "TIMER_MAX" }, #endif #ifdef _SC_TTYNAME_MAX { _SC_TTYNAME_MAX, "TTYNAME_MAX" }, #endif #ifdef _SC_TZNAME_MAX { _SC_TZNAME_MAX, "TZNAME_MAX" }, #endif #ifdef _SC_XOPEN_CRYPT { _SC_XOPEN_CRYPT, "_XOPEN_CRYPT" }, #endif #ifdef _SC_XOPEN_ENH_I18N { _SC_XOPEN_ENH_I18N, "_XOPEN_ENH_I18N" }, #endif #ifdef _SC_XOPEN_REALTIME { _SC_XOPEN_REALTIME, "_XOPEN_REALTIME" }, #endif #ifdef _SC_XOPEN_REALTIME_THREADS { _SC_XOPEN_REALTIME_THREADS, "_XOPEN_REALTIME_THREADS" }, #endif #ifdef _SC_XOPEN_SHM { _SC_XOPEN_SHM, "_XOPEN_SHM" }, #endif #ifdef _SC_XOPEN_STREAMS { _SC_XOPEN_STREAMS, "_XOPEN_STREAMS" }, #endif #ifdef _SC_XOPEN_UNIX { _SC_XOPEN_UNIX, "_XOPEN_UNIX" }, #endif #ifdef _SC_XOPEN_UUCP { _SC_XOPEN_UUCP, "_XOPEN_UUCP" }, #endif #ifdef _SC_XOPEN_VERSION { _SC_XOPEN_VERSION, "_XOPEN_VERSION" }, #endif }; static const getconf_catalog _getconf_catalog_values[] = { #ifdef _POSIX2_BC_BASE_MAX { _POSIX2_BC_BASE_MAX, "POSIX2_BC_BASE_MAX" }, #endif #ifdef _POSIX2_BC_DIM_MAX { _POSIX2_BC_DIM_MAX, "POSIX2_BC_DIM_MAX" }, #endif #ifdef _POSIX2_BC_SCALE_MAX { _POSIX2_BC_SCALE_MAX, "POSIX2_BC_SCALE_MAX" }, #endif #ifdef _POSIX2_BC_STRING_MAX { _POSIX2_BC_STRING_MAX, "POSIX2_BC_STRING_MAX" }, #endif #ifdef _POSIX2_C_BIND { _POSIX2_C_BIND, "POSIX2_C_BIND" }, #endif #ifdef _POSIX2_C_DEV { _POSIX2_C_DEV, "POSIX2_C_DEV" }, #endif #ifdef _POSIX2_CHAR_TERM { _POSIX2_CHAR_TERM, "POSIX2_CHAR_TERM" }, #endif #ifdef _POSIX2_COLL_WEIGHTS_MAX { _POSIX2_COLL_WEIGHTS_MAX, "POSIX2_COLL_WEIGHTS_MAX" }, #endif #ifdef _POSIX2_EXPR_NEST_MAX { _POSIX2_EXPR_NEST_MAX, "POSIX2_EXPR_NEST_MAX" }, #endif #ifdef _POSIX2_FORT_DEV { _POSIX2_FORT_DEV, "POSIX2_FORT_DEV" }, #endif #ifdef _POSIX2_FORT_RUN { _POSIX2_FORT_RUN, "POSIX2_FORT_RUN" }, #endif #ifdef _POSIX2_LINE_MAX { _POSIX2_LINE_MAX, "POSIX2_LINE_MAX" }, #endif #ifdef _POSIX2_LOCALEDEF { _POSIX2_LOCALEDEF, "POSIX2_LOCALEDEF" }, #endif #ifdef _POSIX2_RE_DUP_MAX { _POSIX2_RE_DUP_MAX, "POSIX2_RE_DUP_MAX" }, #endif #ifdef _POSIX2_SW_DEV { _POSIX2_SW_DEV, "POSIX2_SW_DEV" }, #endif #ifdef _POSIX2_UPE { _POSIX2_UPE, "POSIX2_UPE" }, #endif #ifdef _POSIX2_VERSION { _POSIX2_VERSION, "POSIX2_VERSION" }, #endif }; /* prototypes */ static int _getconf(char const * specification, char const * var, char const * path); static int _getconf_error(char const * message, int ret); static int _usage(void); /* functions */ /* getconf */ static int _getconf_confstr(char const * var); static int _getconf_pathconf(char const * var, char const * path); static int _getconf_sysconf(char const * var); static int _getconf_values(char const * var); static int _getconf(char const * specification, char const * var, char const * path) { if(path != NULL) return _getconf_pathconf(var, path); if(strncmp(var, "_SC_", 4) == 0) return _getconf_confstr(var); return _getconf_sysconf(var); } static int _getconf_confstr(char const * var) { size_t i; size_t cnt = sizeof(_getconf_catalog_confstr) / sizeof(*_getconf_catalog_confstr); char * buf; for(i = 0; i < cnt; i++) if(strcmp(_getconf_catalog_confstr[i].string, var) == 0) break; if(i == cnt) return _getconf_error(var, -ENOENT); /* obtain the required size */ if((cnt = confstr(_getconf_catalog_confstr[i].name, NULL, 0)) == 0) return _getconf_error(var, 2); if((buf = malloc(cnt)) == NULL) return _getconf_error(var, 2); if((cnt = confstr(_getconf_catalog_confstr[i].name, buf, cnt)) == 0) { free(buf); return _getconf_error(var, 2); } printf("%s\n", buf); free(buf); return 0; } static int _getconf_pathconf(char const * var, char const * path) { size_t i; size_t cnt = sizeof(_getconf_catalog_pathconf) / sizeof(*_getconf_catalog_pathconf); long value; for(i = 0; i < cnt; i++) if(strcmp(_getconf_catalog_pathconf[i].string, var) == 0) break; if(i == cnt) return _getconf_error(var, -ENOENT); if((value = pathconf(path, _getconf_catalog_pathconf[i].name)) < 0) return _getconf_error(var, 2); printf("%ld\n", value); return 0; } static int _getconf_sysconf(char const * var) { size_t i; size_t cnt = sizeof(_getconf_catalog_sysconf) / sizeof(*_getconf_catalog_sysconf); long value; for(i = 0; i < cnt; i++) if(strcmp(_getconf_catalog_sysconf[i].string, var) == 0) break; if(i == cnt) return _getconf_values(var); errno = 0; if((value = sysconf(_getconf_catalog_sysconf[i].name)) < 0) { if(errno != 0) return _getconf_error(var, 2); printf("%s", "undefined\n"); } else printf("%ld\n", value); return 0; } static int _getconf_values(char const * var) { size_t i; size_t cnt = sizeof(_getconf_catalog_values) / sizeof(*_getconf_catalog_values); for(i = 0; i < cnt; i++) if(strcmp(_getconf_catalog_values[i].string, var) == 0) break; if(i == cnt) return _getconf_error(var, -ENOENT); printf("%ld\n", _getconf_catalog_values[i].name); return 0; } /* error */ static int _getconf_error(char const * message, int ret) { fputs(PROGNAME ": ", stderr); if(ret < 0) { fprintf(stderr, "%s%s%s\n", (message != NULL) ? message : "", (message != NULL) ? ": " : "", strerror(-ret)); return -ret; } perror(message); return ret; } /* usage */ static int _usage(void) { fputs("Usage: " PROGNAME " [-v specification] system_var\n" " " PROGNAME " [-v specification] path_var pathname\n", stderr); return 1; } /* main */ int main(int argc, char * argv[]) { int o; char const * specification = NULL; while((o = getopt(argc, argv, "v:")) != -1) switch(o) { case 'v': specification = optarg; break; default: return _usage(); } if(optind + 1 != argc && optind + 2 != argc) return _usage(); return (_getconf(specification, argv[optind], argv[optind + 1]) == 0) ? 0 : 2; }