7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller/***********************************************************************
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* This software is part of the ast package *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* Copyright (c) 1992-2010 AT&T Intellectual Property *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* and is licensed under the *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* Common Public License, Version 1.0 *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* by AT&T Intellectual Property *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* A copy of the License is available at *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* http://www.opensource.org/licenses/cpl1.0.txt *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* Information and Software Systems Research *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* AT&T Research *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* Florham Park NJ *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* Glenn Fowler <gsf@research.att.com> *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* David Korn <dgk@research.att.com> *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller* *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller***********************************************************************/
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller#pragma prototyped
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller/*
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller * Glenn Fowler
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller * AT&T Research
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller *
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller * getconf - get configuration values
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller */
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmillerstatic const char usage[] =
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[-?\n@(#)$Id: getconf (AT&T Research) 2008-04-24 $\n]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan MmillerUSAGE_LICENSE
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+NAME?getconf - get configuration values]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \aname\a. If \aname\a is a filesystem specific variable then"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" the value is determined relative to \apath\a or the current"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" directory if \apath\a is omitted. If \avalue\a is specified then"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \bgetconf\b attempts to change the process local value to \avalue\a."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \b-\b may be used in place of \apath\a when it is not relevant."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" If \apath\a is \b=\b then the the \avalue\a is cached and used"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" for subsequent tests in the calling and all child processes."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" Only \bwritable\b variables may be set; \breadonly\b variables"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" cannot be changed.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+?The current value for \aname\a is written to the standard output. If"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \aname\a is valid but undefined then \bundefined\b is written to"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" the standard output. If \aname\a is invalid or an error occurs in"
18f2985c5be44e17aff0b118ee2c6f18967fa150Brendan Mmiller" determining its value, then a diagnostic written to the standard error"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" and \bgetconf\b exits with a non-zero exit status.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+?More than one variable may be set or queried by providing the \aname\a"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \apath\a \avalue\a 3-tuple for each variable, specifying \b-\b for"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \avalue\a when querying.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+?If no operands are specified then all known variables are written in"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \aname\a=\avalue\a form to the standard output, one per line."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" checks only \bast\b specific extensions and the native system calls;"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" invalid options and/or names not supported by \bastgetconf\b(3) cause"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" the \bgetconf\b on \b$PATH\b to be executed.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[a:all?Call the native \bgetconf\b(1) with option \b-a\b.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[b:base?List base variable name sans call and standard prefixes.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[c:call?Display variables with call prefix that matches \aRE\a. The call"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" prefixes are:]:[RE]{"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+CS?\bconfstr\b(2)]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+PC?\bpathconf\b(2)]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+SC?\bsysconf\b(2)]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+SI?\bsysinfo\b(2)]"
18f2985c5be44e17aff0b118ee2c6f18967fa150Brendan Mmiller" [+XX?Constant value.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"}"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[d:defined?Only display defined values when no operands are specified.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[l:lowercase?List variable names in lower case.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[n:name?Display variables with name that match \aRE\a.]:[RE]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[p:portable?Display the named \bwritable\b variables and values in a form that"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" can be directly executed by \bsh\b(1) to set the values. If \aname\a"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" is omitted then all \bwritable\b variables are listed.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[q:quote?\"...\" quote values.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[r:readonly?Display the named \breadonly\b variables in \aname\a=\avalue\a form."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" If \aname\a is omitted then all \breadonly\b variables are listed.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[s:standard?Display variables with standard prefix that matches \aRE\a."
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" Use the \b--table\b option to view all standard prefixes, including"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" local additions. The standard prefixes available on all systems"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" are:]:[RE]{"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+AES]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+AST]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+C]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+GNU]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+POSIX]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+SVID]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+XBS5]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+XOPEN]"
18f2985c5be44e17aff0b118ee2c6f18967fa150Brendan Mmiller" [+XPG]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"}"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[t:table?Display the internal table that contains the name, standard,"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" standard section, and system call symbol prefix for each variable.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[w:writable?Display the named \bwritable\b variables in \aname\a=\avalue\a"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" form. If \aname\a is omitted then all \bwritable\b variables are"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" listed.]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[v:specification?Call the native \bgetconf\b(1) with option"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" \b-v\b \aname\a.]:[name]"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"\n"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"\n[ name [ path [ value ] ] ... ]\n"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"\n"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller"[+ENVIRONMENT]{"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" [+_AST_FEATURES?Process local writable values that are different from"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" the default are stored in the \b_AST_FEATURES\b environment"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" variable. The \b_AST_FEATURES\b value is a space-separated"
7dcb2f62e25d05f2afeb4e79f10102350d7c2c7bBrendan Mmiller" list of \aname\a \apath\a \avalue\a 3-tuples, where"
" \aname\a is the system configuration name, \apath\a is the"
" corresponding path, \b-\b if no path is applicable, and"
" \avalue\a is the system configuration value.]"
"}"
"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2),"
" \bsysconf\b(2), \bastgetconf\b(3)]"
;
#include <cmd.h>
#include <proc.h>
#include <ls.h>
typedef struct Path_s
{
const char* path;
int len;
} Path_t;
int
b_getconf(int argc, char** argv, void* context)
{
register char* name;
register char* path;
register char* value;
register const char* s;
register const char* t;
char* pattern;
char* native;
char* cmd;
Path_t* e;
Path_t* p;
int flags;
int n;
int i;
int m;
int q;
char** oargv;
char buf[PATH_MAX];
Path_t std[64];
struct stat st0;
struct stat st1;
static const char empty[] = "-";
static const Path_t equiv[] = { { "/bin", 4 }, { "/usr/bin", 8 } };
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
oargv = argv;
if (*(native = astconf("GETCONF", NiL, NiL)) != '/')
native = 0;
flags = 0;
name = 0;
pattern = 0;
for (;;)
{
switch (optget(argv, usage))
{
case 'a':
if (native)
goto defer;
continue;
case 'b':
flags |= ASTCONF_base;
continue;
case 'c':
flags |= ASTCONF_matchcall;
pattern = opt_info.arg;
continue;
case 'd':
flags |= ASTCONF_defined;
continue;
case 'l':
flags |= ASTCONF_lower;
continue;
case 'n':
flags |= ASTCONF_matchname;
pattern = opt_info.arg;
continue;
case 'p':
flags |= ASTCONF_parse;
continue;
case 'q':
flags |= ASTCONF_quote;
continue;
case 'r':
flags |= ASTCONF_read;
continue;
case 's':
flags |= ASTCONF_matchstandard;
pattern = opt_info.arg;
continue;
case 't':
flags |= ASTCONF_table;
continue;
case 'v':
if (native)
goto defer;
continue;
case 'w':
flags |= ASTCONF_write;
continue;
case ':':
if (native)
goto defer;
error(2, "%s", opt_info.arg);
break;
case '?':
error(ERROR_usage(2), "%s", opt_info.arg);
break;
}
break;
}
argv += opt_info.index;
if (!(name = *argv))
path = 0;
else if (streq(name, empty))
{
name = 0;
if (path = *++argv)
{
argv++;
if (streq(path, empty))
path = 0;
}
}
if (error_info.errors || !name && *argv)
error(ERROR_usage(2), "%s", optusage(NiL));
if (!name)
astconflist(sfstdout, path, flags, pattern);
else
{
flags = native ? (ASTCONF_system|ASTCONF_error) : 0;
do
{
if (!(path = *++argv))
value = 0;
else
{
if (streq(path, empty))
{
path = 0;
flags = 0;
}
if ((value = *++argv) && (streq(value, empty)))
{
value = 0;
flags = 0;
}
}
s = astgetconf(name, path, value, flags, errorf);
if (error_info.errors)
break;
if (!s)
goto defer;
if (!value)
{
if (flags & ASTCONF_write)
{
sfputr(sfstdout, name, ' ');
sfputr(sfstdout, path ? path : empty, ' ');
}
sfputr(sfstdout, s, '\n');
}
} while (*argv && (name = *++argv));
}
return error_info.errors != 0;
defer:
/*
* defer to argv[0] if absolute and it exists
*/
if ((cmd = oargv[0]) && *cmd == '/' && !access(cmd, X_OK))
goto found;
/*
* defer to the first getconf on $PATH that is also on the standard PATH
*/
e = std;
s = astconf("PATH", NiL, NiL);
q = !stat(equiv[0].path, &st0) && !stat(equiv[1].path, &st1) && st0.st_ino == st1.st_ino && st0.st_dev == st1.st_dev;
m = 0;
do
{
for (t = s; *s && *s != ':'; s++);
if ((n = s - t) && *t == '/')
{
if (q)
for (i = 0; i < 2; i++)
if (n == equiv[i].len && !strncmp(t, equiv[i].path, n))
{
if (m & (i+1))
t = 0;
else
{
m |= (i+1);
if (!(m & (!i+1)))
{
m |= (!i+1);
e->path = t;
e->len = n;
e++;
if (e >= &std[elementsof(std)])
break;
t = equiv[!i].path;
n = equiv[!i].len;
}
}
}
if (t)
{
e->path = t;
e->len = n;
e++;
}
}
while (*s == ':')
s++;
} while (*s && e < &std[elementsof(std)]);
if (e < &std[elementsof(std)])
{
e->len = strlen(e->path = "/usr/sbin");
if (++e < &std[elementsof(std)])
{
e->len = strlen(e->path = "/sbin");
e++;
}
}
if (s = getenv("PATH"))
do
{
for (t = s; *s && *s != ':'; s++);
if ((n = s - t) && *t == '/')
{
for (p = std; p < e; p++)
if (p->len == n && !strncmp(t, p->path, n))
{
sfsprintf(buf, sizeof(buf), "%-*.*s/%s", n, n, t, error_info.id);
if (!access(buf, X_OK))
{
cmd = buf;
goto found;
}
}
}
while (*s == ':')
s++;
} while (*s);
/*
* defer to the first getconf on the standard PATH
*/
for (p = std; p < e; p++)
{
sfsprintf(buf, sizeof(buf), "%-*.*s/%s", p->len, p->len, p->path, error_info.id);
if (!access(buf, X_OK))
{
cmd = buf;
goto found;
}
}
/*
* out of deferrals
*/
if (name)
error(4, "%s: unknown name -- no native getconf(1) to defer to", name);
else
error(4, "no native getconf(1) to defer to");
return 2;
found:
/*
* don't blame us for crappy diagnostics
*/
oargv[0] = cmd;
if ((n = sh_run(context, argc, oargv)) >= EXIT_NOEXEC)
error(ERROR_SYSTEM|2, "%s: exec error [%d]", cmd, n);
return n;
}