From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Wed, 20 Jun 2001 11:21:09 -0400 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: getconf rev3 Message-ID: <3B308725.26537.2D5651@localhost> X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com This version adds variables added over the past several days and uses errno determine bad variables for pathconf and sysconf instead of comparing against -1. /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #define constant_var 0 #define confstr_var 1 #define pathconf_var 2 #define sysconf_var 3 struct variable { const char *name; long value; unsigned int type; }; const struct variable var_list[] = { { "ARG_MAX", _SC_ARG_MAX, sysconf_var }, { "CHILD_MAX", _SC_CHILD_MAX, sysconf_var }, { "CLK_TCK", _SC_CLK_TCK, sysconf_var }, { "LINK_MAX", _PC_LINK_MAX, pathconf_var }, { "MAX_CANON", _PC_MAX_CANON, pathconf_var }, { "MAX_INPUT", _PC_MAX_INPUT, pathconf_var }, { "NAME_MAX", _PC_NAME_MAX, pathconf_var }, { "NGROUPS_MAX", _SC_NGROUPS_MAX, sysconf_var }, { "OPEN_MAX", _SC_OPEN_MAX, sysconf_var }, { "PATH", _CS_PATH, confstr_var }, { "PATH_MAX", _PC_PATH_MAX, pathconf_var }, { "PIPE_BUF", _PC_PIPE_BUF, pathconf_var }, { "POSIX_V6_ILP32_OFF32_CFLAGS", _CS_POSIX_V6_ILP32_OFF32_CFLAGS, confstr_var }, { "POSIX_V6_ILP32_OFF32_LDFLAGS", _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, confstr_var }, { "POSIX_V6_ILP32_OFF32_LIBS", _CS_POSIX_V6_ILP32_OFF32_LIBS, confstr_var }, { "STREAM_MAX", _SC_STREAM_MAX, sysconf_var }, #ifdef _PC_SYMLINK_MAX { "SYMLINK_MAX", _PC_SYMLINK_MAX, pathconf_var }, #endif { "TZNAME_MAX", _SC_TZNAME_MAX, sysconf_var }, { "_POSIX_ARG_MAX", _POSIX_ARG_MAX, constant_var }, { "_POSIX_CHILD_MAX", _POSIX_CHILD_MAX, constant_var }, { "_POSIX_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED, pathconf_var }, { "_POSIX_LINK_MAX", _POSIX_LINK_MAX, constant_var }, { "_POSIX_MAX_CANON", _POSIX_MAX_CANON, constant_var }, { "_POSIX_MAX_INPUT", _POSIX_MAX_INPUT, constant_var }, { "_POSIX_NAME_MAX", _POSIX_NAME_MAX, constant_var }, { "_POSIX_NGROUPS_MAX", _POSIX_NGROUPS_MAX, constant_var }, { "_POSIX_NO_TRUNC", _PC_NO_TRUNC, pathconf_var }, { "_POSIX_JOB_CONTROL", _SC_JOB_CONTROL, sysconf_var }, { "_POSIX_OPEN_MAX", _POSIX_OPEN_MAX, constant_var }, { "_POSIX_PATH_MAX", _POSIX_PATH_MAX, constant_var }, { "_POSIX_PIPE_BUF", _POSIX_PIPE_BUF, constant_var }, { "_POSIX_SAVED_IDS", _SC_SAVED_IDS, sysconf_var }, { "_POSIX_SSIZE_MAX", _POSIX_SSIZE_MAX, constant_var }, { "_POSIX_STREAM_MAX", _POSIX_STREAM_MAX, constant_var }, { "_POSIX_TZNAME_MAX", _POSIX_TZNAME_MAX, constant_var }, { "_POSIX_V6_ILP32_OFF32", _POSIX_V6_ILP32_OFF32, sysconf_var }, { "_POSIX_VERSION", _SC_VERSION, sysconf_var }, { "_POSIX_VDISABLE", _PC_VDISABLE, pathconf_var }, }; const char *conf_specs[] = { "POSIX_V6_ILP32_OFF32", }; #define SIZEOF_ARRAY(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) static void print_usage(void); static void usage(void); static void help(void); static void undefined(void); static int var_compare(const void *key, const void *elem) { return strcmp((const char *)key, ((const struct variable *)elem)->name); } int main(int argc, char *argv[]) { char c; const char *spec; const char *var_name; const struct variable *var; if (argc == 1) usage(); while ((c = getopt(argc, argv, ":hv:")) != -1) { switch (c) { case 'h': { help(); break; } case 'v': { const char *spec = optarg; const int num_specs = sizeof(conf_specs) / sizeof(conf_specs[0]); int i; /* Verify the specification is valid. */ for (i = 0; i < num_specs; ++i) { if (strcmp (spec, conf_specs[i]) == 0) break; } if (i == num_specs) { fprintf(stderr, "undefined specification\n", spec); } /* Since only one specification is supported, there's nothing more to do. */ } default: { usage(); break; } } } var_name = argv[optind]; var = bsearch(var_name, var_list, sizeof(var_list) / sizeof(var_list[0]), sizeof(var_list[0]), var_compare); if (var == NULL) undefined(); if ((argc - optind) != ((var->type == pathconf_var) ? 2 : 1)) usage(); /* Ensure sysconf and pathconf errors are detected. */ errno = 0; switch (var->type) { case constant_var: { printf("%l\n", var->value); break; } case confstr_var: { size_t buf_len, ret; char *buf; buf_len = confstr(var->value, 0, 0); if (buf_len) { buf = alloca(buf_len); ret = confstr(var->value, buf, buf_len); printf("%s\n", buf); } else undefined(); /* Shouldn't happen, but you never know. */ break; } case sysconf_var: { long val; val = sysconf(var->value); if (errno == 0) printf("%d\n", val); else undefined(); break; } case pathconf_var: { long val; val = pathconf(argv[optind + 1], var->value); if (errno == 0) printf("%d\n", val); else undefined(); break; } } return 0; } static void undefined(void) { fprintf(stderr, "undefined\n"); exit(1); } static void print_usage(void) { fprintf(stderr, "Usage: getconv [-v specification] [-h] [sysvar] [pathvar path]\n"); } static void usage(void) { print_usage(); exit(1); } static void help(void) { int i; print_usage(); fprintf(stderr, "\nValid specifications:\n"); for (i = 0; i < SIZEOF_ARRAY(conf_specs); ++i) fprintf(stderr, "%s\n", conf_specs[i]); fprintf(stderr, "\nValid variable names:\n"); for (i = 0; i < SIZEOF_ARRAY(var_list); ++i) { if (var_list[i].type != pathconf_var) fprintf(stderr, "%s\n", var_list[i].name); else fprintf(stderr, "%s [path]\n", var_list[i].name); } exit(1); }