getconf.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke/***********************************************************************
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* *
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder* This software is part of the ast package *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* Copyright (c) 1992-2012 AT&T Intellectual Property *
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu* and is licensed under the *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* Eclipse Public License, Version 1.0 *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* by AT&T Intellectual Property *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* A copy of the License is available at *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* http://www.eclipse.org/org/documents/epl-v10.html *
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder* *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* Information and Software Systems Research *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* AT&T Research *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* Florham Park NJ *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* Glenn Fowler <gsf@research.att.com> *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* David Korn <dgk@research.att.com> *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke* *
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke***********************************************************************/
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke#pragma prototyped
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke/*
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke * Glenn Fowler
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder * AT&T Research
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder *
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder * getconf - get configuration values
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder */
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maederstatic const char usage[] =
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[-?\n@(#)$Id: getconf (AT&T Research) 2012-06-25 $\n]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian MaederUSAGE_LICENSE
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[+NAME?getconf - get configuration values]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \aname\a. If \aname\a is a filesystem specific variable then"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" the value is determined relative to \apath\a or the current"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" directory if \apath\a is omitted. If \avalue\a is specified then"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" \bgetconf\b attempts to change the process local value to \avalue\a."
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" \b-\b may be used in place of \apath\a when it is not relevant."
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" If \apath\a is \b=\b then the the \avalue\a is cached and used"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" for subsequent tests in the calling and all child processes."
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" Only \bwritable\b variables may be set; \breadonly\b variables"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" cannot be changed.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[+?The current value for \aname\a is written to the standard output. If"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" \aname\a is valid but undefined then \bundefined\b is written to"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" the standard output. If \aname\a is invalid or an error occurs in"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" determining its value, then a diagnostic written to the standard error"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" and \bgetconf\b exits with a non-zero exit status.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[+?More than one variable may be set or queried by providing the \aname\a"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \apath\a \avalue\a 3-tuple for each variable, specifying \b-\b for"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \avalue\a when querying.]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[+?If no operands are specified then all known variables are written in"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \aname\a=\avalue\a form to the standard output, one per line."
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" checks only \bast\b specific extensions and the native system calls;"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" invalid options and/or names not supported by \bastgetconf\b(3) cause"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" the \bgetconf\b on \b$PATH\b to be executed.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke
656f17ae9b7610ff2de1b6eedeeadea0c3bcdc8dChristian Maeder"[a:all?Call the native \bgetconf\b(1) with option \b-a\b.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[b:base?List base variable name sans call and standard prefixes.]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[c:call?Display variables with call prefix that matches \aRE\a. The call"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" prefixes are:]:[RE]{"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" [+CS?\bconfstr\b(2)]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" [+PC?\bpathconf\b(2)]"
656f17ae9b7610ff2de1b6eedeeadea0c3bcdc8dChristian Maeder" [+SC?\bsysconf\b(2)]"
656f17ae9b7610ff2de1b6eedeeadea0c3bcdc8dChristian Maeder" [+SI?\bsysinfo\b(2)]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" [+XX?Constant value.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"}"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[d:defined?Only display defined values when no operands are specified.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[l:lowercase?List variable names in lower case.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[n:name?Display variables with name that match \aRE\a.]:[RE]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[p:portable?Display the named \bwritable\b variables and values in a form that"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" can be directly executed by \bsh\b(1) to set the values. If \aname\a"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" is omitted then all \bwritable\b variables are listed.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[q:quote?\"...\" quote values.]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[r:readonly?Display the named \breadonly\b variables in \aname\a=\avalue\a form."
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" If \aname\a is omitted then all \breadonly\b variables are listed.]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"[s:standard?Display variables with standard prefix that matches \aRE\a."
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" Use the \b--table\b option to view all standard prefixes, including"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" local additions. The standard prefixes available on all systems"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" are:]:[RE]{"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" [+AES]"
a23e572c8f957cc051a1b0831abd6fe9380d45c7Christian Maeder" [+AST]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+C]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+GNU]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+POSIX]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+SVID]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+XBS5]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" [+XOPEN]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" [+XPG]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"}"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[t:table?Display the internal table that contains the name, standard,"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" standard section, and system call symbol prefix for each variable.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[w:writable?Display the named \bwritable\b variables in \aname\a=\avalue\a"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" form. If \aname\a is omitted then all \bwritable\b variables are"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke" listed.]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[v:specification?Call the native \bgetconf\b(1) with option"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder" \b-v\b \aname\a.]:[name]"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"\n"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"\n[ name [ path [ value ] ] ... ]\n"
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder"\n"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke"[+ENVIRONMENT]"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke "{"
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke "[+_AST_FEATURES?Process local writable values that are "
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder "different from the default are stored in the \b_AST_FEATURES\b "
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke "environment variable. The \b_AST_FEATURES\b value is a "
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke "space-separated list of \aname\a \apath\a \avalue\a 3-tuples, "
9f93539f2fa4f5b9d935c7baa22fcd750806def9Klaus Hartke "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. \b_AST_FEATURES\b "
"is an implementation detail of process inheritance; it may "
"change or vanish in the future; don't rely on it.]"
"}"
"[+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, Shbltin_t* 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
{
if (native)
flags |= (ASTCONF_system|ASTCONF_error);
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)
{
if (native)
goto defer;
error(2, "%s: unknown name", name);
break;
}
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;
}