diff --git a/src/getconf.c b/src/getconf.c new file mode 100644 index 0000000..817f34d --- /dev/null +++ b/src/getconf.c @@ -0,0 +1,209 @@ +/* $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 +{ + int 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_limits[] = +{ +#ifdef NGROUPS_MAX + { NGROUPS_MAX, "NGROUPS_MAX" }, +#endif +}; + +static const getconf_catalog _getconf_catalog_pathconf[] = +{ +#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_PATH_MAX + { _PC_PATH_MAX, "PATH_MAX" }, +#endif +#ifdef _PC_PIPE_BUF + { _PC_PIPE_BUF, "PIPE_BUF" }, +#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_limits(char const * var); +static int _getconf_pathconf(char const * var, char const * path); + +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_limits(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_limits(char const * var) +{ + size_t i; + size_t cnt = sizeof(_getconf_catalog_limits) + / sizeof(*_getconf_catalog_limits); + + for(i = 0; i < cnt; i++) + if(strcmp(_getconf_catalog_limits[i].string, var) == 0) + break; + if(i == cnt) + return _getconf_error(var, -ENOENT); + printf("%d\n", _getconf_catalog_limits[i].name); + 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; +} + + +/* 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; +} diff --git a/src/project.conf b/src/project.conf index b18638c..177ff28 100644 --- a/src/project.conf +++ b/src/project.conf @@ -1,4 +1,4 @@ -targets=basename,cat,chgrp,chmod,chown,cksum,cmp,cp,date,df,dirname,du,echo,false,file,find,grep,head,id,kill,link,ln,locale,logname,ls,mkdir,mkfifo,more,mv,nice,pr,printf,ps,pwd,renice,rm,rmdir,sleep,strings,tail,test,time,touch,true,tty,uname,uniq,unlink,wc,who +targets=basename,cat,chgrp,chmod,chown,cksum,cmp,cp,date,df,dirname,du,echo,false,file,find,getconf,grep,head,id,kill,link,ln,locale,logname,ls,mkdir,mkfifo,more,mv,nice,pr,printf,ps,pwd,renice,rm,rmdir,sleep,strings,tail,test,time,touch,true,tty,uname,uniq,unlink,wc,who cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector ldflags=-pie -Wl,-z,relro -Wl,-z,now dist=Makefile,common.c @@ -87,6 +87,11 @@ type=binary sources=find.c install=$(BINDIR) +[getconf] +type=binary +sources=getconf.c +install=$(BINDIR) + [grep] type=binary sources=grep.c