/* # # DESCRIPTION # # $Id: sysconf.c,v 1.1.1.1 2003/12/13 11:17:03 nemies Exp $ # # Copyright (C) 2003 Kees Cook # kees@outflux.net, http://outflux.net/ # # 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; either version 2 # of the License, or (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # http://www.gnu.org/copyleft/gpl.html # */ #include "sysconf.h" #include #include struct conf_list_t { int cfvar; char * name; int category; int rettype; }; #define CONF(a,t) { (a) , #a, (t) } #define STR(a) CONF(a,RET_STR) #define NUM(a) CONF(a,RET_NUM) /* grab values for pathconf, sysconf, and confstr */ struct conf_list_t conf_list[]={ #include "defs.h" { -1, NULL, -1, -1 }, }; /* copyright info */ char * copyright="Copyright 2003 Kees Cook "; char * gpl="\ This program is free software; you may redistribute it under the terms of\n\ the GNU General Public License. This program has absolutely no warranty."; /* global settings */ int show_many=0; int show_all=0; char * use_path=NULL; void Usage(char * title) { printf("Usage: %s [OPTIONS] [VARIABLE ...]\n\ \n\ -h, --help This help\n\ -v, --verbose Display variable name along with value\n\ -V, --version Return program version\n\ -p, --path FILE Use FILE as the path argument to 'pathconf' variables\n\ -l, --all Show all configuration variables (may need --path)\n\ \n", title); exit(1); } void handle_args(int argc, char *argv[]) { static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "verbose", 0, NULL, 'v' }, { "version", 0, NULL, 'V' }, { "path", 1, NULL, 'p' }, { "all", 0, NULL, 'l' }, { 0, 0, 0, 0 } }; /* do our option handling */ while (1) { int c; int index; c = getopt_long(argc, argv, "hvVp:l", long_options, &index); if (c == -1) break; // done with args switch (c) { case 0: // got a matching long argument (with no short equiv) switch (index) { default: fprintf(stderr, "Unknown long argument index %d found!\n", index); } break; case 'h': Usage(PACKAGE_NAME); break; case 'v': show_many=1; break; case 'l': show_all=1; show_many=1; break; case 'V': printf("%s version %s\n%s\n%s\n", PACKAGE,PACKAGE_VERSION,copyright,gpl); exit(0); case 'p': use_path=optarg; break; default: fprintf(stderr, "Unknown short argument '%c' found?!\n", c); /* fall through to the Usage ... */ case '?': Usage(argv[0]); break; } } } /* 0 on success, -1 if something bad happens */ int report_variable(int index, char * path) { // for RET_STR size_t n=0; size_t len; char *pathbuf=NULL; char *category=NULL; // for RET_NUM long result; // our option char * name = conf_list[index].name; int cfvar = conf_list[index].cfvar; /* decide if we want to deal with this config variable */ switch (conf_list[index].rettype) { case RET_STR: n = confstr(cfvar,NULL,(size_t)0); if (n == 0) { fprintf(stderr,"confstr: "); fprintf(stderr, "%s: bad configuration variable\n", name); break; } if ((pathbuf = malloc(n)) == NULL) { perror("malloc"); return -1; } if ((len=confstr(cfvar, pathbuf, n))<1 || len!=n) { fprintf(stderr,"confstr: "); perror(name); return -1; } else { if (show_many) printf("%s: ",name); printf("%s\n",pathbuf); free(pathbuf); } break; case RET_NUM: errno=0; switch (conf_list[index].category) { case SYSCONF: category="sysconf"; result=sysconf(cfvar); break; case PATHCONF: category="pathconf"; if (!use_path) { fprintf(stderr,"%s: requires a path (use --path)\n",name); /* only an error on a specific request */ return (show_all ? 0 : -1); } result=pathconf(use_path,cfvar); break; default: category="unknown"; fprintf(stderr,"%s: I don't know how to fetch this!?\n",name); return -1; } if (result==-1 && errno!=0) { fprintf(stderr,"%s: ",category); perror(name); return -1; } else { if (show_many) printf("%s: ",name); printf("%ld\n",result); } break; default: fprintf(stderr,"Cannot handle '%s' type %d\n", name,conf_list[index].rettype); return -1; } return 0; } /* returns 1 on match, 0 on failure */ int match_name(int index, char * name) { char * var_name = conf_list[index].name; /* skip past the leading "_" if they didn't include it */ if (name && name[0]!='_' && var_name[0]=='_') var_name++; /* let's do this without case sensitivity */ return (!strcasecmp(var_name,name)); } /* * Usage methods: * report a single value (most common) * report multiple values (one per line?) * show name on line? with colon? "batch" mode? * show all possible conf names * show only nums * show only strs * show all values for all conf names (part of "multi" above) */ int main(int argc, char *argv[]) { int i,opt; int exitcode=0; int var_count; int found; /* handle our command line args */ handle_args(argc, argv); /* with many args, turn on show_many */ if (optind <= argc) { var_count = (argc - optind); if (var_count > 1) show_many=1; } /* need either "show_all" or a variable to display */ if (var_count == 0 && !show_all) Usage(PACKAGE_NAME); if (show_all) { for (i=0;conf_list[i].name;i++) { if (report_variable(i,use_path)<0) exitcode=1; } } else { for (opt=optind;opt