14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin
244887Schin /*
254887Schin * string interface to confstr(),pathconf(),sysconf(),sysinfo()
264887Schin * extended to allow some features to be set per-process
274887Schin */
284887Schin
2910898Sroland.mainz@nrubsig.org static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2009-07-02 $\0\n";
304887Schin
314887Schin #include "univlib.h"
324887Schin
334887Schin #include <ast.h>
344887Schin #include <error.h>
354887Schin #include <fs3d.h>
364887Schin #include <ctype.h>
374887Schin #include <regex.h>
384887Schin #include <proc.h>
394887Schin
404887Schin #include "conftab.h"
414887Schin #include "FEATURE/libpath"
424887Schin
4310898Sroland.mainz@nrubsig.org #ifndef DEBUG_astconf
4410898Sroland.mainz@nrubsig.org #define DEBUG_astconf 0
4510898Sroland.mainz@nrubsig.org #endif
4610898Sroland.mainz@nrubsig.org
474887Schin #ifndef _pth_getconf
484887Schin #undef ASTCONF_system
494887Schin #define ASTCONF_system 0
504887Schin #endif
514887Schin
524887Schin #if _sys_systeminfo
534887Schin # if !_lib_sysinfo
544887Schin # if _lib_systeminfo
554887Schin # define _lib_sysinfo 1
564887Schin # define sysinfo(a,b,c) systeminfo(a,b,c)
574887Schin # else
584887Schin # if _lib_syscall && _sys_syscall
594887Schin # include <sys/syscall.h>
604887Schin # if defined(SYS_systeminfo)
614887Schin # define _lib_sysinfo 1
624887Schin # define sysinfo(a,b,c) syscall(SYS_systeminfo,a,b,c)
634887Schin # endif
644887Schin # endif
654887Schin # endif
664887Schin # endif
674887Schin #else
684887Schin # undef _lib_sysinfo
694887Schin #endif
704887Schin
714887Schin #define CONF_ERROR (CONF_USER<<0)
724887Schin #define CONF_READONLY (CONF_USER<<1)
734887Schin #define CONF_ALLOC (CONF_USER<<2)
748462SApril.Chin@Sun.COM #define CONF_GLOBAL (CONF_USER<<3)
754887Schin
7610898Sroland.mainz@nrubsig.org #define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast)
774887Schin #define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0)
7810898Sroland.mainz@nrubsig.org #define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen"))
794887Schin
804887Schin #define MAXVAL 256
814887Schin
824887Schin #if MAXVAL <= UNIV_SIZE
834887Schin #undef MAXVAL
844887Schin #define MAXVAL (UNIV_SIZE+1)
854887Schin #endif
864887Schin
874887Schin #ifndef _UNIV_DEFAULT
884887Schin #define _UNIV_DEFAULT "att"
894887Schin #endif
904887Schin
914887Schin static char null[1];
924887Schin static char root[2] = "/";
934887Schin
944887Schin typedef struct Feature_s
954887Schin {
964887Schin struct Feature_s*next;
974887Schin const char* name;
984887Schin char* value;
9910898Sroland.mainz@nrubsig.org char* std;
10010898Sroland.mainz@nrubsig.org char* ast;
1014887Schin short length;
1024887Schin short standard;
1038462SApril.Chin@Sun.COM unsigned int flags;
1044887Schin short op;
1054887Schin } Feature_t;
1064887Schin
1074887Schin typedef struct
1084887Schin {
1094887Schin Conf_t* conf;
1104887Schin const char* name;
1118462SApril.Chin@Sun.COM unsigned int flags;
1124887Schin short call;
1134887Schin short standard;
1144887Schin short section;
1154887Schin } Lookup_t;
1164887Schin
1174887Schin static Feature_t dynamic[] =
1184887Schin {
11910898Sroland.mainz@nrubsig.org #define OP_conformance 0
1204887Schin {
12110898Sroland.mainz@nrubsig.org &dynamic[OP_conformance+1],
1224887Schin "CONFORMANCE",
1234887Schin "ast",
1244887Schin "standard",
12510898Sroland.mainz@nrubsig.org "ast",
1264887Schin 11,
1274887Schin CONF_AST,
1284887Schin 0,
1294887Schin OP_conformance
1304887Schin },
13110898Sroland.mainz@nrubsig.org #define OP_fs_3d 1
1324887Schin {
13310898Sroland.mainz@nrubsig.org &dynamic[OP_fs_3d+1],
1344887Schin "FS_3D",
1354887Schin &null[0],
1364887Schin "0",
13710898Sroland.mainz@nrubsig.org 0,
1384887Schin 5,
1394887Schin CONF_AST,
1404887Schin 0,
1414887Schin OP_fs_3d
1424887Schin },
14310898Sroland.mainz@nrubsig.org #define OP_getconf 2
1444887Schin {
14510898Sroland.mainz@nrubsig.org &dynamic[OP_getconf+1],
1464887Schin "GETCONF",
1474887Schin #ifdef _pth_getconf
1484887Schin _pth_getconf,
1494887Schin #else
1504887Schin &null[0],
1514887Schin #endif
1524887Schin 0,
15310898Sroland.mainz@nrubsig.org 0,
1544887Schin 7,
1554887Schin CONF_AST,
1564887Schin CONF_READONLY,
1574887Schin OP_getconf
1584887Schin },
15910898Sroland.mainz@nrubsig.org #define OP_hosttype 3
1604887Schin {
16110898Sroland.mainz@nrubsig.org &dynamic[OP_hosttype+1],
1624887Schin "HOSTTYPE",
1634887Schin HOSTTYPE,
1644887Schin 0,
16510898Sroland.mainz@nrubsig.org 0,
1664887Schin 8,
1674887Schin CONF_AST,
1684887Schin CONF_READONLY,
1694887Schin OP_hosttype
1704887Schin },
17110898Sroland.mainz@nrubsig.org #define OP_libpath 4
1724887Schin {
17310898Sroland.mainz@nrubsig.org &dynamic[OP_libpath+1],
1744887Schin "LIBPATH",
1754887Schin #ifdef CONF_LIBPATH
1764887Schin CONF_LIBPATH,
1774887Schin #else
1784887Schin &null[0],
1794887Schin #endif
1804887Schin 0,
18110898Sroland.mainz@nrubsig.org 0,
1824887Schin 7,
1834887Schin CONF_AST,
1844887Schin 0,
1854887Schin OP_libpath
1864887Schin },
18710898Sroland.mainz@nrubsig.org #define OP_libprefix 5
1884887Schin {
18910898Sroland.mainz@nrubsig.org &dynamic[OP_libprefix+1],
1904887Schin "LIBPREFIX",
1914887Schin #ifdef CONF_LIBPREFIX
1924887Schin CONF_LIBPREFIX,
1934887Schin #else
1944887Schin "lib",
1954887Schin #endif
1964887Schin 0,
19710898Sroland.mainz@nrubsig.org 0,
1984887Schin 9,
1994887Schin CONF_AST,
2004887Schin 0,
2014887Schin OP_libprefix
2024887Schin },
20310898Sroland.mainz@nrubsig.org #define OP_libsuffix 6
2044887Schin {
20510898Sroland.mainz@nrubsig.org &dynamic[OP_libsuffix+1],
2064887Schin "LIBSUFFIX",
2074887Schin #ifdef CONF_LIBSUFFIX
2084887Schin CONF_LIBSUFFIX,
2094887Schin #else
2104887Schin ".so",
2114887Schin #endif
2124887Schin 0,
21310898Sroland.mainz@nrubsig.org 0,
2144887Schin 9,
2154887Schin CONF_AST,
2164887Schin 0,
2174887Schin OP_libsuffix
2184887Schin },
21910898Sroland.mainz@nrubsig.org #define OP_path_attributes 7
2204887Schin {
22110898Sroland.mainz@nrubsig.org &dynamic[OP_path_attributes+1],
2224887Schin "PATH_ATTRIBUTES",
2234887Schin #if _WINIX
2244887Schin "c",
2254887Schin #else
2264887Schin &null[0],
2274887Schin #endif
2284887Schin &null[0],
22910898Sroland.mainz@nrubsig.org 0,
2304887Schin 15,
2314887Schin CONF_AST,
2324887Schin CONF_READONLY,
2334887Schin OP_path_attributes
2344887Schin },
23510898Sroland.mainz@nrubsig.org #define OP_path_resolve 8
2364887Schin {
23710898Sroland.mainz@nrubsig.org &dynamic[OP_path_resolve+1],
2384887Schin "PATH_RESOLVE",
2394887Schin &null[0],
24010898Sroland.mainz@nrubsig.org "physical",
2414887Schin "metaphysical",
2424887Schin 12,
2434887Schin CONF_AST,
2444887Schin 0,
2454887Schin OP_path_resolve
2464887Schin },
24710898Sroland.mainz@nrubsig.org #define OP_universe 9
2484887Schin {
2494887Schin 0,
2504887Schin "UNIVERSE",
2514887Schin &null[0],
2524887Schin "att",
25310898Sroland.mainz@nrubsig.org 0,
2544887Schin 8,
2554887Schin CONF_AST,
2564887Schin 0,
2574887Schin OP_universe
2584887Schin },
2594887Schin {
2604887Schin 0
2614887Schin }
2624887Schin };
2634887Schin
2644887Schin typedef struct
2654887Schin {
2664887Schin
2674887Schin const char* id;
2684887Schin const char* name;
2694887Schin Feature_t* features;
2704887Schin
27110898Sroland.mainz@nrubsig.org int std;
27210898Sroland.mainz@nrubsig.org
2734887Schin /* default initialization from here down */
2744887Schin
2754887Schin int prefix;
2764887Schin int synthesizing;
2774887Schin
2784887Schin char* data;
2794887Schin char* last;
2804887Schin
2814887Schin Feature_t* recent;
2824887Schin
2834887Schin Ast_confdisc_f notify;
2844887Schin
2854887Schin } State_t;
2864887Schin
28710898Sroland.mainz@nrubsig.org static State_t state = { "getconf", "_AST_FEATURES", dynamic, -1 };
2884887Schin
2898462SApril.Chin@Sun.COM static char* feature(const char*, const char*, const char*, unsigned int, Error_f);
2904887Schin
2914887Schin /*
2924887Schin * return fmtbuf() copy of s
2934887Schin */
2944887Schin
2954887Schin static char*
buffer(char * s)2964887Schin buffer(char* s)
2974887Schin {
2984887Schin return strcpy(fmtbuf(strlen(s) + 1), s);
2994887Schin }
3004887Schin
3014887Schin /*
3024887Schin * synthesize state for fp
3034887Schin * fp==0 initializes from getenv(state.name)
3044887Schin * value==0 just does lookup
3054887Schin * otherwise state is set to value
3064887Schin */
3074887Schin
3084887Schin static char*
synthesize(register Feature_t * fp,const char * path,const char * value)3094887Schin synthesize(register Feature_t* fp, const char* path, const char* value)
3104887Schin {
3114887Schin register char* s;
3124887Schin register char* d;
3134887Schin register char* v;
31410898Sroland.mainz@nrubsig.org register char* p;
3154887Schin register int n;
3164887Schin
31710898Sroland.mainz@nrubsig.org #if DEBUG_astconf
3188462SApril.Chin@Sun.COM if (fp)
3198462SApril.Chin@Sun.COM error(-2, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
3208462SApril.Chin@Sun.COM #endif
3214887Schin if (state.synthesizing)
3224887Schin return null;
3234887Schin if (!state.data)
3244887Schin {
3254887Schin char* se;
3264887Schin char* de;
3274887Schin char* ve;
3284887Schin
3294887Schin state.prefix = strlen(state.name) + 1;
3304887Schin n = state.prefix + 3 * MAXVAL;
3314887Schin if (s = getenv(state.name))
3324887Schin n += strlen(s) + 1;
3334887Schin n = roundof(n, 32);
3344887Schin if (!(state.data = newof(0, char, n, 0)))
3354887Schin return 0;
3364887Schin state.last = state.data + n - 1;
3374887Schin strcpy(state.data, state.name);
3384887Schin state.data += state.prefix - 1;
3394887Schin *state.data++ = '=';
3404887Schin if (s)
3414887Schin strcpy(state.data, s);
3424887Schin ve = state.data;
3434887Schin state.synthesizing = 1;
3444887Schin for (;;)
3454887Schin {
3464887Schin for (s = ve; isspace(*s); s++);
3474887Schin for (d = s; *d && !isspace(*d); d++);
3484887Schin for (se = d; isspace(*d); d++);
3494887Schin for (v = d; *v && !isspace(*v); v++);
3504887Schin for (de = v; isspace(*v); v++);
3514887Schin if (!*v)
3524887Schin break;
3534887Schin for (ve = v; *ve && !isspace(*ve); ve++);
3544887Schin if (*ve)
3554887Schin *ve = 0;
3564887Schin else
3574887Schin ve = 0;
3584887Schin *de = 0;
3594887Schin *se = 0;
3604887Schin feature(s, d, v, 0, 0);
3614887Schin *se = ' ';
3624887Schin *de = ' ';
3634887Schin if (!ve)
3644887Schin break;
3654887Schin *ve++ = ' ';
3664887Schin }
3674887Schin state.synthesizing = 0;
3684887Schin }
3694887Schin if (!fp)
3704887Schin return state.data;
3714887Schin if (!state.last)
3724887Schin {
3734887Schin if (!value)
3744887Schin return 0;
3754887Schin n = strlen(value);
3764887Schin goto ok;
3774887Schin }
3784887Schin s = (char*)fp->name;
3794887Schin n = fp->length;
3804887Schin d = state.data;
3814887Schin for (;;)
3824887Schin {
3834887Schin while (isspace(*d))
3844887Schin d++;
3854887Schin if (!*d)
3864887Schin break;
3874887Schin if (strneq(d, s, n) && isspace(d[n]))
3884887Schin {
3894887Schin if (!value)
3904887Schin {
3914887Schin for (d += n + 1; *d && !isspace(*d); d++);
3924887Schin for (; isspace(*d); d++);
3934887Schin for (s = d; *s && !isspace(*s); s++);
3944887Schin n = s - d;
3954887Schin value = (const char*)d;
3964887Schin goto ok;
3974887Schin }
39810898Sroland.mainz@nrubsig.org for (s = p = d + n + 1; *s && !isspace(*s); s++);
3994887Schin for (; isspace(*s); s++);
4004887Schin for (v = s; *s && !isspace(*s); s++);
4014887Schin n = s - v;
40210898Sroland.mainz@nrubsig.org if ((!path || *path == *p && strlen(path) == (v - p - 1) && !memcmp(path, p, v - p - 1)) && strneq(v, value, n))
4034887Schin goto ok;
4044887Schin for (; isspace(*s); s++);
4054887Schin if (*s)
4064887Schin for (; *d = *s++; d++);
4074887Schin else if (d != state.data)
4084887Schin d--;
4094887Schin break;
4104887Schin }
4114887Schin for (; *d && !isspace(*d); d++);
4124887Schin for (; isspace(*d); d++);
4134887Schin for (; *d && !isspace(*d); d++);
4144887Schin for (; isspace(*d); d++);
4154887Schin for (; *d && !isspace(*d); d++);
4164887Schin }
4174887Schin if (!value)
4184887Schin {
4194887Schin if (!fp->op)
4204887Schin {
4214887Schin if (fp->flags & CONF_ALLOC)
4224887Schin fp->value[0] = 0;
4234887Schin else
4244887Schin fp->value = null;
4254887Schin }
4264887Schin return 0;
4274887Schin }
4284887Schin if (!value[0])
4294887Schin value = "0";
4304887Schin if (!path || !path[0] || path[0] == '/' && !path[1])
4314887Schin path = "-";
4324887Schin n += strlen(path) + strlen(value) + 3;
4334887Schin if (d + n >= state.last)
4344887Schin {
4354887Schin int c;
4364887Schin int i;
4374887Schin
4384887Schin i = d - state.data;
4394887Schin state.data -= state.prefix;
4404887Schin c = n + state.last - state.data + 3 * MAXVAL;
4414887Schin c = roundof(c, 32);
4424887Schin if (!(state.data = newof(state.data, char, c, 0)))
4434887Schin return 0;
4444887Schin state.last = state.data + c - 1;
4454887Schin state.data += state.prefix;
4464887Schin d = state.data + i;
4474887Schin }
4484887Schin if (d != state.data)
4494887Schin *d++ = ' ';
4504887Schin for (s = (char*)fp->name; *d = *s++; d++);
4514887Schin *d++ = ' ';
4524887Schin for (s = (char*)path; *d = *s++; d++);
4534887Schin *d++ = ' ';
4544887Schin for (s = (char*)value; *d = *s++; d++);
45510898Sroland.mainz@nrubsig.org #if DEBUG_astconf
45610898Sroland.mainz@nrubsig.org error(-3, "astconf synthesize %s", state.data - state.prefix);
45710898Sroland.mainz@nrubsig.org #endif
4584887Schin setenviron(state.data - state.prefix);
4594887Schin if (state.notify)
4604887Schin (*state.notify)(NiL, NiL, state.data - state.prefix);
4614887Schin n = s - (char*)value - 1;
4624887Schin ok:
4634887Schin if (!(fp->flags & CONF_ALLOC))
4644887Schin fp->value = 0;
4654887Schin if (n == 1 && (*value == '0' || *value == '-'))
4664887Schin n = 0;
4674887Schin if (!(fp->value = newof(fp->value, char, n, 1)))
4684887Schin fp->value = null;
4694887Schin else
4704887Schin {
4714887Schin fp->flags |= CONF_ALLOC;
4724887Schin memcpy(fp->value, value, n);
4734887Schin fp->value[n] = 0;
4744887Schin }
4754887Schin return fp->value;
4764887Schin }
4774887Schin
4784887Schin /*
4794887Schin * initialize the value for fp
4804887Schin * if command!=0 then it is checked for on $PATH
4814887Schin * synthesize(fp,path,succeed) called on success
4824887Schin * otherwise synthesize(fp,path,fail) called
4834887Schin */
4844887Schin
4854887Schin static void
initialize(register Feature_t * fp,const char * path,const char * command,const char * succeed,const char * fail)4864887Schin initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail)
4874887Schin {
4884887Schin register char* p;
4894887Schin register int ok = 1;
4904887Schin
49110898Sroland.mainz@nrubsig.org #if DEBUG_astconf
4928462SApril.Chin@Sun.COM error(-2, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
4938462SApril.Chin@Sun.COM #endif
4944887Schin switch (fp->op)
4954887Schin {
4964887Schin case OP_conformance:
4974887Schin ok = getenv("POSIXLY_CORRECT") != 0;
4984887Schin break;
4994887Schin case OP_hosttype:
5004887Schin ok = 1;
5014887Schin break;
5024887Schin case OP_path_attributes:
5034887Schin ok = 1;
5044887Schin break;
5054887Schin case OP_path_resolve:
5064887Schin ok = fs3d(FS3D_TEST);
5074887Schin break;
5084887Schin case OP_universe:
50910898Sroland.mainz@nrubsig.org ok = streq(_UNIV_DEFAULT, DEFAULT(OP_universe));
5104887Schin /*FALLTHROUGH...*/
5114887Schin default:
5124887Schin if (p = getenv("PATH"))
5134887Schin {
5144887Schin register int r = 1;
5154887Schin register char* d = p;
5164887Schin Sfio_t* tmp;
5174887Schin
51810898Sroland.mainz@nrubsig.org #if DEBUG_astconf
5198462SApril.Chin@Sun.COM error(-2, "astconf initialize name=%s ok=%d PATH=%s", fp->name, ok, p);
5208462SApril.Chin@Sun.COM #endif
5214887Schin if (tmp = sfstropen())
5224887Schin {
5234887Schin for (;;)
5244887Schin {
5254887Schin switch (*p++)
5264887Schin {
5274887Schin case 0:
5284887Schin break;
5294887Schin case ':':
5304887Schin if (command && (fp->op != OP_universe || !ok))
5314887Schin {
5324887Schin if (r = p - d - 1)
5334887Schin {
5344887Schin sfwrite(tmp, d, r);
5354887Schin sfputc(tmp, '/');
5364887Schin sfputr(tmp, command, 0);
5374887Schin if ((d = sfstruse(tmp)) && !eaccess(d, X_OK))
5384887Schin {
5394887Schin ok = 1;
5404887Schin if (fp->op != OP_universe)
5414887Schin break;
5424887Schin }
5434887Schin }
5444887Schin d = p;
5454887Schin }
5464887Schin r = 1;
5474887Schin continue;
5484887Schin case '/':
5494887Schin if (r)
5504887Schin {
5514887Schin r = 0;
5524887Schin if (fp->op == OP_universe)
5534887Schin {
5548462SApril.Chin@Sun.COM if (p[0] == 'u' && p[1] == 's' && p[2] == 'r' && p[3] == '/')
5558462SApril.Chin@Sun.COM for (p += 4; *p == '/'; p++);
5568462SApril.Chin@Sun.COM if (p[0] == 'b' && p[1] == 'i' && p[2] == 'n')
5578462SApril.Chin@Sun.COM {
5588462SApril.Chin@Sun.COM for (p += 3; *p == '/'; p++);
5598462SApril.Chin@Sun.COM if (!*p || *p == ':')
5608462SApril.Chin@Sun.COM break;
5618462SApril.Chin@Sun.COM }
5624887Schin }
5634887Schin }
5644887Schin if (fp->op == OP_universe)
5654887Schin {
5668462SApril.Chin@Sun.COM if (strneq(p, "xpg", 3) || strneq(p, "5bin", 4))
5674887Schin {
5684887Schin ok = 1;
5694887Schin break;
5704887Schin }
5714887Schin if (strneq(p, "bsd", 3) || strneq(p, "ucb", 3))
5724887Schin {
5734887Schin ok = 0;
5744887Schin break;
5754887Schin }
5764887Schin }
5774887Schin continue;
5784887Schin default:
5794887Schin r = 0;
5804887Schin continue;
5814887Schin }
5824887Schin break;
5834887Schin }
5844887Schin sfclose(tmp);
5854887Schin }
5864887Schin else
5874887Schin ok = 1;
5884887Schin }
5894887Schin break;
5904887Schin }
59110898Sroland.mainz@nrubsig.org #if DEBUG_astconf
59210898Sroland.mainz@nrubsig.org error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", __LINE__, state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok);
59310898Sroland.mainz@nrubsig.org #endif
5944887Schin synthesize(fp, path, ok ? succeed : fail);
5954887Schin }
5964887Schin
5974887Schin /*
5984887Schin * format synthesized value
5994887Schin */
6004887Schin
6014887Schin static char*
format(register Feature_t * fp,const char * path,const char * value,unsigned int flags,Error_f conferror)6028462SApril.Chin@Sun.COM format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror)
6034887Schin {
6044887Schin register Feature_t* sp;
6054887Schin register int n;
6064887Schin
60710898Sroland.mainz@nrubsig.org #if DEBUG_astconf
6088462SApril.Chin@Sun.COM error(-2, "astconf format name=%s path=%s value=%s flags=%04x fp=%p%s", fp->name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : "");
6098462SApril.Chin@Sun.COM #endif
6108462SApril.Chin@Sun.COM if (value)
6118462SApril.Chin@Sun.COM fp->flags &= ~CONF_GLOBAL;
6128462SApril.Chin@Sun.COM else if (fp->flags & CONF_GLOBAL)
6138462SApril.Chin@Sun.COM return fp->value;
6144887Schin switch (fp->op)
6154887Schin {
6164887Schin
6174887Schin case OP_conformance:
61810898Sroland.mainz@nrubsig.org if (value && STANDARD(value))
61910898Sroland.mainz@nrubsig.org value = fp->std;
62010898Sroland.mainz@nrubsig.org n = state.std = streq(fp->value, fp->std);
62110898Sroland.mainz@nrubsig.org #if DEBUG_astconf
62210898Sroland.mainz@nrubsig.org error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
62310898Sroland.mainz@nrubsig.org #endif
6244887Schin if (!synthesize(fp, path, value))
62510898Sroland.mainz@nrubsig.org initialize(fp, path, NiL, fp->std, fp->value);
62610898Sroland.mainz@nrubsig.org #if DEBUG_astconf
62710898Sroland.mainz@nrubsig.org error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
62810898Sroland.mainz@nrubsig.org #endif
62910898Sroland.mainz@nrubsig.org if (!n && STANDARD(fp->value))
63010898Sroland.mainz@nrubsig.org {
63110898Sroland.mainz@nrubsig.org state.std = 1;
6324887Schin for (sp = state.features; sp; sp = sp->next)
63310898Sroland.mainz@nrubsig.org if (sp->std && sp->op && sp->op != OP_conformance)
63410898Sroland.mainz@nrubsig.org astconf(sp->name, path, sp->std);
63510898Sroland.mainz@nrubsig.org }
63610898Sroland.mainz@nrubsig.org #if DEBUG_astconf
63710898Sroland.mainz@nrubsig.org error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
63810898Sroland.mainz@nrubsig.org #endif
6394887Schin break;
6404887Schin
6414887Schin case OP_fs_3d:
6424887Schin fp->value = fs3d(value ? value[0] ? FS3D_ON : FS3D_OFF : FS3D_TEST) ? "1" : null;
6434887Schin break;
6444887Schin
6454887Schin case OP_hosttype:
6464887Schin break;
6474887Schin
6484887Schin case OP_path_attributes:
6494887Schin #ifdef _PC_PATH_ATTRIBUTES
6504887Schin {
6514887Schin register char* s;
6524887Schin register char* e;
6534887Schin intmax_t v;
6544887Schin
6554887Schin /*
6564887Schin * _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z'
6574887Schin */
6584887Schin
6594887Schin if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L)
6604887Schin return 0;
6614887Schin s = fp->value;
6624887Schin e = s + sizeof(fp->value) - 1;
6634887Schin for (n = 'a'; n <= 'z'; n++)
6644887Schin if (v & (1 << (n - 'a')))
6654887Schin {
6664887Schin *s++ = n;
6674887Schin if (s >= e)
6684887Schin break;
6694887Schin }
6704887Schin *s = 0;
6714887Schin }
6724887Schin #endif
6734887Schin break;
6744887Schin
6754887Schin case OP_path_resolve:
6764887Schin if (!synthesize(fp, path, value))
67710898Sroland.mainz@nrubsig.org initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve));
6784887Schin break;
6794887Schin
6804887Schin case OP_universe:
6814887Schin #if _lib_universe
6824887Schin if (getuniverse(fp->value) < 0)
68310898Sroland.mainz@nrubsig.org strcpy(fp->value, DEFAULT(OP_universe));
6844887Schin if (value)
6854887Schin setuniverse(value);
6864887Schin #else
6874887Schin #ifdef UNIV_MAX
6884887Schin n = 0;
6894887Schin if (value)
6904887Schin {
6914887Schin while (n < univ_max && !streq(value, univ_name[n])
6924887Schin n++;
6934887Schin if (n >= univ_max)
6944887Schin {
6954887Schin if (conferror)
6964887Schin (*conferror)(&state, &state, 2, "%s: %s: universe value too large", fp->name, value);
6974887Schin return 0;
6984887Schin }
6994887Schin }
7004887Schin #ifdef ATT_UNIV
7014887Schin n = setuniverse(n + 1);
7024887Schin if (!value && n > 0)
7034887Schin setuniverse(n);
7044887Schin #else
7054887Schin n = universe(value ? n + 1 : U_GET);
7064887Schin #endif
7074887Schin if (n <= 0 || n >= univ_max)
7084887Schin n = 1;
7094887Schin strcpy(fp->value, univ_name[n - 1]);
7104887Schin #else
7118462SApril.Chin@Sun.COM if (value && streq(path, "="))
71210898Sroland.mainz@nrubsig.org {
71310898Sroland.mainz@nrubsig.org if (state.synthesizing)
71410898Sroland.mainz@nrubsig.org {
71510898Sroland.mainz@nrubsig.org if (!(fp->flags & CONF_ALLOC))
71610898Sroland.mainz@nrubsig.org fp->value = 0;
71710898Sroland.mainz@nrubsig.org n = strlen(value);
71810898Sroland.mainz@nrubsig.org if (!(fp->value = newof(fp->value, char, n, 1)))
71910898Sroland.mainz@nrubsig.org fp->value = null;
72010898Sroland.mainz@nrubsig.org else
72110898Sroland.mainz@nrubsig.org {
72210898Sroland.mainz@nrubsig.org fp->flags |= CONF_ALLOC;
72310898Sroland.mainz@nrubsig.org memcpy(fp->value, value, n);
72410898Sroland.mainz@nrubsig.org fp->value[n] = 0;
72510898Sroland.mainz@nrubsig.org }
72610898Sroland.mainz@nrubsig.org }
72710898Sroland.mainz@nrubsig.org else
72810898Sroland.mainz@nrubsig.org synthesize(fp, path, value);
72910898Sroland.mainz@nrubsig.org }
7308462SApril.Chin@Sun.COM else
73110898Sroland.mainz@nrubsig.org initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb");
7324887Schin #endif
7334887Schin #endif
7344887Schin break;
7354887Schin
7364887Schin default:
7374887Schin synthesize(fp, path, value);
7384887Schin break;
7394887Schin
7404887Schin }
7418462SApril.Chin@Sun.COM if (streq(path, "="))
7428462SApril.Chin@Sun.COM fp->flags |= CONF_GLOBAL;
7434887Schin return fp->value;
7444887Schin }
7454887Schin
7464887Schin /*
7474887Schin * value==0 get feature name
7484887Schin * value!=0 set feature name
7494887Schin * 0 returned if error or not defined; otherwise previous value
7504887Schin */
7514887Schin
7524887Schin static char*
7538462SApril.Chin@Sun.COM feature(const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror)
7544887Schin {
7554887Schin register Feature_t* fp;
7564887Schin register int n;
7574887Schin
7584887Schin if (value && (streq(value, "-") || streq(value, "0")))
7594887Schin value = null;
7604887Schin for (fp = state.features; fp && !streq(fp->name, name); fp = fp->next);
76110898Sroland.mainz@nrubsig.org #if DEBUG_astconf
7628462SApril.Chin@Sun.COM error(-2, "astconf feature name=%s path=%s value=%s flags=%04x fp=%p%s", name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : "");
7634887Schin #endif
7644887Schin if (!fp)
7654887Schin {
7664887Schin if (!value)
7674887Schin return 0;
7684887Schin if (state.notify && !(*state.notify)(name, path, value))
7694887Schin return 0;
7704887Schin n = strlen(name);
7714887Schin if (!(fp = newof(0, Feature_t, 1, n + 1)))
7724887Schin {
7734887Schin if (conferror)
7744887Schin (*conferror)(&state, &state, 2, "%s: out of space", name);
7754887Schin return 0;
7764887Schin }
77710898Sroland.mainz@nrubsig.org fp->op = -1;
7784887Schin fp->name = (const char*)fp + sizeof(Feature_t);
7794887Schin strcpy((char*)fp->name, name);
7804887Schin fp->length = n;
78110898Sroland.mainz@nrubsig.org fp->std = &null[0];
7824887Schin fp->next = state.features;
7834887Schin state.features = fp;
7844887Schin }
7854887Schin else if (value)
7864887Schin {
7874887Schin if (fp->flags & CONF_READONLY)
7884887Schin {
7894887Schin if (conferror)
7904887Schin (*conferror)(&state, &state, 2, "%s: cannot set readonly symbol", fp->name);
7914887Schin return 0;
7924887Schin }
7934887Schin if (state.notify && !streq(fp->value, value) && !(*state.notify)(name, path, value))
7944887Schin return 0;
7954887Schin }
7964887Schin else
7974887Schin state.recent = fp;
7984887Schin return format(fp, path, value, flags, conferror);
7994887Schin }
8004887Schin
8014887Schin /*
8024887Schin * binary search for name in conf[]
8034887Schin */
8044887Schin
8054887Schin static int
8068462SApril.Chin@Sun.COM lookup(register Lookup_t* look, const char* name, unsigned int flags)
8074887Schin {
8084887Schin register Conf_t* mid = (Conf_t*)conf;
8094887Schin register Conf_t* lo = mid;
8104887Schin register Conf_t* hi = mid + conf_elements;
8114887Schin register int v;
8124887Schin register int c;
8134887Schin char* e;
8144887Schin const Prefix_t* p;
8154887Schin
8164887Schin static Conf_t num;
8174887Schin
8184887Schin look->flags = 0;
8194887Schin look->call = -1;
8204887Schin look->standard = (flags & ASTCONF_AST) ? CONF_AST : -1;
8214887Schin look->section = -1;
8224887Schin while (*name == '_')
8234887Schin name++;
8244887Schin again:
8254887Schin for (p = prefix; p < &prefix[prefix_elements]; p++)
8268462SApril.Chin@Sun.COM if (strneq(name, p->name, p->length) && ((c = name[p->length] == '_' || name[p->length] == '(' || name[p->length] == '#') || (v = isdigit(name[p->length]) && name[p->length + 1] == '_')))
8274887Schin {
8284887Schin if (p->call < 0)
8294887Schin {
8304887Schin if (look->standard >= 0)
8314887Schin break;
8324887Schin look->standard = p->standard;
8334887Schin }
8344887Schin else
8354887Schin {
8364887Schin if (look->call >= 0)
8374887Schin break;
8384887Schin look->call = p->call;
8394887Schin }
8408462SApril.Chin@Sun.COM if (name[p->length] == '(' || name[p->length] == '#')
8414887Schin {
8424887Schin look->conf = #
8434887Schin strncpy((char*)num.name, name, sizeof(num.name));
8444887Schin num.call = p->call;
8454887Schin num.flags = *name == 'C' ? CONF_STRING : 0;
8464887Schin num.op = (short)strtol(name + p->length + 1, &e, 10);
8478462SApril.Chin@Sun.COM if (name[p->length] == '(' && *e == ')')
8488462SApril.Chin@Sun.COM e++;
8498462SApril.Chin@Sun.COM if (*e)
8504887Schin break;
8514887Schin return 1;
8524887Schin }
8534887Schin name += p->length + c;
8544887Schin if (look->section < 0 && !c && v)
8554887Schin {
8564887Schin look->section = name[0] - '0';
8574887Schin name += 2;
8584887Schin }
8594887Schin goto again;
8604887Schin }
8614887Schin #if HUH_2006_02_10
8624887Schin if (look->section < 0)
8634887Schin look->section = 1;
8644887Schin #endif
8654887Schin look->name = name;
86610898Sroland.mainz@nrubsig.org #if DEBUG_astconf
8674887Schin error(-2, "astconf normal name=%s standard=%d section=%d call=%d flags=%04x elements=%d", look->name, look->standard, look->section, look->call, flags, conf_elements);
8684887Schin #endif
8694887Schin c = *((unsigned char*)name);
8704887Schin while (lo <= hi)
8714887Schin {
8724887Schin mid = lo + (hi - lo) / 2;
87310898Sroland.mainz@nrubsig.org #if DEBUG_astconf
8744887Schin error(-3, "astconf lookup name=%s mid=%s", name, mid->name);
8754887Schin #endif
8764887Schin if (!(v = c - *((unsigned char*)mid->name)) && !(v = strcmp(name, mid->name)))
8774887Schin {
8784887Schin hi = mid;
8794887Schin lo = (Conf_t*)conf;
8804887Schin do
8814887Schin {
8824887Schin if ((look->standard < 0 || look->standard == mid->standard) &&
8834887Schin (look->section < 0 || look->section == mid->section) &&
8844887Schin (look->call < 0 || look->call == mid->call))
8854887Schin goto found;
8864887Schin } while (mid-- > lo && streq(mid->name, look->name));
8874887Schin mid = hi;
8884887Schin hi = lo + conf_elements - 1;
8894887Schin while (++mid < hi && streq(mid->name, look->name))
8904887Schin {
8914887Schin if ((look->standard < 0 || look->standard == mid->standard) &&
8924887Schin (look->section < 0 || look->section == mid->section) &&
8934887Schin (look->call < 0 || look->call == mid->call))
8944887Schin goto found;
8954887Schin }
8964887Schin break;
8974887Schin }
8984887Schin else if (v > 0)
8994887Schin lo = mid + 1;
9004887Schin else
9014887Schin hi = mid - 1;
9024887Schin }
9034887Schin return 0;
9044887Schin found:
9054887Schin if (look->call < 0 && look->standard >= 0 && (look->section <= 1 || (mid->flags & CONF_MINMAX)))
9064887Schin look->flags |= CONF_MINMAX;
9074887Schin look->conf = mid;
90810898Sroland.mainz@nrubsig.org #if DEBUG_astconf
9094887Schin error(-2, "astconf lookup name=%s standard=%d:%d section=%d:%d call=%d:%d", look->name, look->standard, mid->standard, look->section, mid->section, look->call, mid->call);
9104887Schin #endif
9114887Schin return 1;
9124887Schin }
9134887Schin
9144887Schin /*
9154887Schin * return a tolower'd copy of s
9164887Schin */
9174887Schin
9184887Schin static char*
9194887Schin fmtlower(register const char* s)
9204887Schin {
9214887Schin register int c;
9224887Schin register char* t;
9234887Schin char* b;
9244887Schin
9254887Schin b = t = fmtbuf(strlen(s) + 1);
9264887Schin while (c = *s++)
9274887Schin {
9284887Schin if (isupper(c))
9294887Schin c = tolower(c);
9304887Schin *t++ = c;
9314887Schin }
9324887Schin *t = 0;
9334887Schin return b;
9344887Schin }
9354887Schin
9364887Schin /*
9374887Schin * print value line for p
9384887Schin * if !name then value prefixed by "p->name="
9394887Schin * if (flags & CONF_MINMAX) then default minmax value used
9404887Schin */
9414887Schin
9424887Schin static char*
9434887Schin print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror)
9444887Schin {
9454887Schin register Conf_t* p = look->conf;
9468462SApril.Chin@Sun.COM register unsigned int flags = look->flags;
9474887Schin char* call;
9484887Schin char* f;
9494887Schin const char* s;
9504887Schin int i;
9518462SApril.Chin@Sun.COM int n;
9524887Schin int olderrno;
9534887Schin int drop;
9544887Schin int defined;
9554887Schin intmax_t v;
9564887Schin char buf[PATH_MAX];
9574887Schin char flg[16];
9584887Schin
9594887Schin if (!name && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_LIMIT|CONF_MINMAX)) && (p->flags & (CONF_LIMIT|CONF_PREFIXED)) != CONF_LIMIT)
9604887Schin flags |= CONF_PREFIXED;
9614887Schin olderrno = errno;
9624887Schin errno = 0;
96310898Sroland.mainz@nrubsig.org #if DEBUG_astconf
96410898Sroland.mainz@nrubsig.org error(-1, "astconf name=%s:%s:%s standard=%d section=%d call=%s op=%d flags=|%s%s%s%s%s:|%s%s%s%s%s%s%s%s%s%s"
96510898Sroland.mainz@nrubsig.org , name, look->name, p->name, p->standard, p->section, prefix[p->call + CONF_call].name, p->op
9664887Schin , (flags & CONF_FEATURE) ? "FEATURE|" : ""
9674887Schin , (flags & CONF_LIMIT) ? "LIMIT|" : ""
9684887Schin , (flags & CONF_MINMAX) ? "MINMAX|" : ""
9694887Schin , (flags & CONF_PREFIXED) ? "PREFIXED|" : ""
9704887Schin , (flags & CONF_STRING) ? "STRING|" : ""
9714887Schin , (p->flags & CONF_DEFER_CALL) ? "DEFER_CALL|" : ""
9724887Schin , (p->flags & CONF_DEFER_MM) ? "DEFER_MM|" : ""
9734887Schin , (p->flags & CONF_FEATURE) ? "FEATURE|" : ""
9744887Schin , (p->flags & CONF_LIMIT_DEF) ? "LIMIT_DEF|" : (p->flags & CONF_LIMIT) ? "LIMIT|" : ""
9754887Schin , (p->flags & CONF_MINMAX_DEF) ? "MINMAX_DEF|" : (p->flags & CONF_MINMAX) ? "MINMAX|" : ""
9764887Schin , (p->flags & CONF_NOUNDERSCORE) ? "NOUNDERSCORE|" : ""
9774887Schin , (p->flags & CONF_PREFIXED) ? "PREFIXED|" : ""
9784887Schin , (p->flags & CONF_PREFIX_ONLY) ? "PREFIX_ONLY|" : ""
9794887Schin , (p->flags & CONF_STANDARD) ? "STANDARD|" : ""
9804887Schin , (p->flags & CONF_STRING) ? "STRING|" : ""
9814887Schin , (p->flags & CONF_UNDERSCORE) ? "UNDERSCORE|" : ""
9824887Schin );
9834887Schin #endif
9844887Schin flags |= CONF_LIMIT_DEF|CONF_MINMAX_DEF;
9854887Schin if (conferror && name)
9864887Schin {
9874887Schin if ((p->flags & CONF_PREFIX_ONLY) && look->standard < 0)
9884887Schin goto bad;
9894887Schin if (!(flags & CONF_MINMAX) || !(p->flags & CONF_MINMAX))
9904887Schin {
9914887Schin switch (p->call)
9924887Schin {
9934887Schin case CONF_pathconf:
9944887Schin if (path == root)
9954887Schin {
9964887Schin (*conferror)(&state, &state, 2, "%s: path expected", name);
9974887Schin goto bad;
9984887Schin }
9994887Schin break;
10004887Schin default:
10014887Schin if (path != root)
10024887Schin {
10034887Schin (*conferror)(&state, &state, 2, "%s: path not expected", name);
10044887Schin goto bad;
10054887Schin }
10064887Schin break;
10074887Schin }
10084887Schin #ifdef _pth_getconf
10094887Schin if (p->flags & CONF_DEFER_CALL)
10104887Schin goto bad;
10114887Schin #endif
10124887Schin }
10134887Schin else
10144887Schin {
10154887Schin if (path != root)
10164887Schin {
10174887Schin (*conferror)(&state, &state, 2, "%s: path not expected", name);
10184887Schin goto bad;
10194887Schin }
10204887Schin #ifdef _pth_getconf
10214887Schin if ((p->flags & CONF_DEFER_MM) || !(p->flags & CONF_MINMAX_DEF))
10224887Schin goto bad;
10234887Schin #endif
10244887Schin }
10254887Schin if (look->standard >= 0 && (name[0] != '_' && ((p->flags & CONF_UNDERSCORE) || look->section <= 1) || name[0] == '_' && (p->flags & CONF_NOUNDERSCORE)) || look->standard < 0 && name[0] == '_')
10264887Schin goto bad;
10274887Schin }
10284887Schin s = 0;
10294887Schin defined = 1;
10304887Schin switch (i = (p->op < 0 || (flags & CONF_MINMAX) && (p->flags & CONF_MINMAX_DEF)) ? 0 : p->call)
10314887Schin {
10324887Schin case CONF_confstr:
10334887Schin call = "confstr";
10344887Schin #if _lib_confstr
10354887Schin if (!(v = confstr(p->op, buf, sizeof(buf))))
10364887Schin {
10374887Schin defined = 0;
10384887Schin v = -1;
10394887Schin errno = EINVAL;
10404887Schin }
10414887Schin else if (v > 0)
10424887Schin {
10434887Schin buf[sizeof(buf) - 1] = 0;
10444887Schin s = (const char*)buf;
10454887Schin }
10464887Schin else
10474887Schin defined = 0;
10484887Schin break;
10494887Schin #else
10504887Schin goto predef;
10514887Schin #endif
10524887Schin case CONF_pathconf:
10534887Schin call = "pathconf";
10544887Schin #if _lib_pathconf
10554887Schin if ((v = pathconf(path, p->op)) < 0)
10564887Schin defined = 0;
10574887Schin break;
10584887Schin #else
10594887Schin goto predef;
10604887Schin #endif
10614887Schin case CONF_sysconf:
10624887Schin call = "sysconf";
10634887Schin #if _lib_sysconf
10644887Schin if ((v = sysconf(p->op)) < 0)
10654887Schin defined = 0;
10664887Schin break;
10674887Schin #else
10684887Schin goto predef;
10694887Schin #endif
10704887Schin case CONF_sysinfo:
10714887Schin call = "sysinfo";
10724887Schin #if _lib_sysinfo
10734887Schin if ((v = sysinfo(p->op, buf, sizeof(buf))) >= 0)
10744887Schin {
10754887Schin buf[sizeof(buf) - 1] = 0;
10764887Schin s = (const char*)buf;
10774887Schin }
10784887Schin else
10794887Schin defined = 0;
10804887Schin break;
10814887Schin #else
10824887Schin goto predef;
10834887Schin #endif
10844887Schin default:
10854887Schin call = "synthesis";
10864887Schin errno = EINVAL;
10874887Schin v = -1;
10884887Schin defined = 0;
10894887Schin break;
10904887Schin case 0:
10914887Schin call = 0;
10928462SApril.Chin@Sun.COM if (p->standard == CONF_AST)
10938462SApril.Chin@Sun.COM {
109410898Sroland.mainz@nrubsig.org if (streq(p->name, "RELEASE") && (i = open("/proc/version", O_RDONLY)) >= 0)
10958462SApril.Chin@Sun.COM {
10968462SApril.Chin@Sun.COM n = read(i, buf, sizeof(buf) - 1);
10978462SApril.Chin@Sun.COM close(i);
10988462SApril.Chin@Sun.COM if (n > 0 && buf[n - 1] == '\n')
10998462SApril.Chin@Sun.COM n--;
11008462SApril.Chin@Sun.COM if (n > 0 && buf[n - 1] == '\r')
11018462SApril.Chin@Sun.COM n--;
11028462SApril.Chin@Sun.COM buf[n] = 0;
11038462SApril.Chin@Sun.COM if (buf[0])
11048462SApril.Chin@Sun.COM {
11058462SApril.Chin@Sun.COM v = 0;
11068462SApril.Chin@Sun.COM s = buf;
11078462SApril.Chin@Sun.COM break;
11088462SApril.Chin@Sun.COM }
11098462SApril.Chin@Sun.COM }
11108462SApril.Chin@Sun.COM }
11114887Schin if (p->flags & CONF_MINMAX_DEF)
11124887Schin {
11134887Schin if (!((p->flags & CONF_LIMIT_DEF)))
11144887Schin flags |= CONF_MINMAX;
11154887Schin listflags &= ~ASTCONF_system;
11164887Schin }
11174887Schin predef:
11184887Schin if (look->standard == CONF_AST)
11194887Schin {
112010898Sroland.mainz@nrubsig.org if (streq(p->name, "VERSION"))
11214887Schin {
1122*12068SRoger.Faulkner@Oracle.COM v = ast.version;
11234887Schin break;
11244887Schin }
11254887Schin }
11264887Schin if (flags & CONF_MINMAX)
11274887Schin {
11284887Schin if ((p->flags & CONF_MINMAX_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_MM)))
11294887Schin {
11304887Schin v = p->minmax.number;
11314887Schin s = p->minmax.string;
11324887Schin break;
11334887Schin }
11344887Schin }
11354887Schin else if ((p->flags & CONF_LIMIT_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_CALL)))
11364887Schin {
11374887Schin v = p->limit.number;
11384887Schin s = p->limit.string;
11394887Schin break;
11404887Schin }
11414887Schin flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
11424887Schin v = -1;
11434887Schin errno = EINVAL;
11444887Schin defined = 0;
11454887Schin break;
11464887Schin }
11474887Schin if (!defined)
11484887Schin {
11494887Schin if (!errno)
11504887Schin {
11514887Schin if ((p->flags & CONF_FEATURE) || !(p->flags & (CONF_LIMIT|CONF_MINMAX)))
11524887Schin flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
11534887Schin }
11544887Schin else if (flags & CONF_PREFIXED)
11554887Schin flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
11564887Schin else if (errno != EINVAL || !i)
11574887Schin {
11584887Schin if (!sp)
11594887Schin {
11604887Schin if (conferror)
11614887Schin {
11624887Schin if (call)
11634887Schin (*conferror)(&state, &state, ERROR_SYSTEM|2, "%s: %s error", p->name, call);
11644887Schin else if (!(listflags & ASTCONF_system))
11654887Schin (*conferror)(&state, &state, 2, "%s: unknown name", p->name);
11664887Schin }
11674887Schin goto bad;
11684887Schin }
11694887Schin else
11704887Schin {
11714887Schin flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
11724887Schin flags |= CONF_ERROR;
11734887Schin }
11744887Schin }
11754887Schin }
11764887Schin errno = olderrno;
11774887Schin if ((listflags & ASTCONF_defined) && !(flags & (CONF_LIMIT_DEF|CONF_MINMAX_DEF)))
11784887Schin goto bad;
11794887Schin if ((drop = !sp) && !(sp = sfstropen()))
11804887Schin goto bad;
11814887Schin if (listflags & ASTCONF_table)
11824887Schin {
11834887Schin f = flg;
11844887Schin if (p->flags & CONF_DEFER_CALL)
11854887Schin *f++ = 'C';
11864887Schin if (p->flags & CONF_DEFER_MM)
11874887Schin *f++ = 'D';
11884887Schin if (p->flags & CONF_FEATURE)
11894887Schin *f++ = 'F';
11904887Schin if (p->flags & CONF_LIMIT)
11914887Schin *f++ = 'L';
11924887Schin if (p->flags & CONF_MINMAX)
11934887Schin *f++ = 'M';
11944887Schin if (p->flags & CONF_NOSECTION)
11954887Schin *f++ = 'N';
11964887Schin if (p->flags & CONF_PREFIXED)
11974887Schin *f++ = 'P';
11984887Schin if (p->flags & CONF_STANDARD)
11994887Schin *f++ = 'S';
12004887Schin if (p->flags & CONF_UNDERSCORE)
12014887Schin *f++ = 'U';
12024887Schin if (p->flags & CONF_NOUNDERSCORE)
12034887Schin *f++ = 'V';
12044887Schin if (p->flags & CONF_PREFIX_ONLY)
12054887Schin *f++ = 'W';
12064887Schin if (f == flg)
12074887Schin *f++ = 'X';
12084887Schin *f = 0;
12094887Schin sfprintf(sp, "%*s %*s %d %2s %4d %6s ", sizeof(p->name), p->name, sizeof(prefix[p->standard].name), prefix[p->standard].name, p->section, prefix[p->call + CONF_call].name, p->op, flg);
12104887Schin if (p->flags & CONF_LIMIT_DEF)
12114887Schin {
12124887Schin if (p->limit.string)
12134887Schin sfprintf(sp, "L[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->limit.string, "\"", "\"", strlen(p->limit.string), FMT_SHELL) : p->limit.string);
12144887Schin else
12154887Schin sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number);
12164887Schin }
12174887Schin if (p->flags & CONF_MINMAX_DEF)
12184887Schin {
12194887Schin if (p->minmax.string)
12204887Schin sfprintf(sp, "M[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->minmax.string, "\"", "\"", strlen(p->minmax.string), FMT_SHELL) : p->minmax.string);
12214887Schin else
12224887Schin sfprintf(sp, "M[%I*d] ", sizeof(p->minmax.number), p->minmax.number);
12234887Schin }
12244887Schin if (flags & CONF_ERROR)
12254887Schin sfprintf(sp, "error");
12264887Schin else if (defined)
12274887Schin {
12284887Schin if (s)
12294887Schin sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
12304887Schin else if (v != -1)
12314887Schin sfprintf(sp, "%I*d", sizeof(v), v);
12324887Schin else
12334887Schin sfprintf(sp, "%I*u", sizeof(v), v);
12344887Schin }
12354887Schin sfprintf(sp, "\n");
12364887Schin }
12374887Schin else
12384887Schin {
12394887Schin if (!(flags & CONF_PREFIXED) || (listflags & ASTCONF_base))
12404887Schin {
12414887Schin if (!name)
12424887Schin {
12434887Schin if ((p->flags & (CONF_PREFIXED|CONF_STRING)) == (CONF_PREFIXED|CONF_STRING) && (!(listflags & ASTCONF_base) || p->standard != CONF_POSIX))
12444887Schin {
12454887Schin if ((p->flags & CONF_UNDERSCORE) && !(listflags & ASTCONF_base))
12464887Schin sfprintf(sp, "_");
12474887Schin sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name);
12484887Schin if (p->section > 1)
12494887Schin sfprintf(sp, "%d", p->section);
12504887Schin sfprintf(sp, "_");
12514887Schin }
12524887Schin sfprintf(sp, "%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name);
12534887Schin }
12544887Schin if (flags & CONF_ERROR)
12554887Schin sfprintf(sp, "error");
12564887Schin else if (defined)
12574887Schin {
12584887Schin if (s)
12594887Schin sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
12604887Schin else if (v != -1)
12614887Schin sfprintf(sp, "%I*d", sizeof(v), v);
12624887Schin else
12634887Schin sfprintf(sp, "%I*u", sizeof(v), v);
12644887Schin }
12654887Schin else
12664887Schin sfprintf(sp, "undefined");
12674887Schin if (!name)
12684887Schin sfprintf(sp, "\n");
12694887Schin }
12704887Schin if (!name && !(listflags & ASTCONF_base) && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_MINMAX)))
12714887Schin {
12724887Schin if (p->flags & CONF_UNDERSCORE)
12734887Schin sfprintf(sp, "_");
12744887Schin sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name);
12754887Schin if (p->section > 1)
12764887Schin sfprintf(sp, "%d", p->section);
12774887Schin sfprintf(sp, "_%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name);
12784887Schin if (v != -1)
12794887Schin sfprintf(sp, "%I*d", sizeof(v), v);
12804887Schin else if (defined)
12814887Schin sfprintf(sp, "%I*u", sizeof(v), v);
12824887Schin else
12834887Schin sfprintf(sp, "undefined");
12844887Schin sfprintf(sp, "\n");
12854887Schin }
12864887Schin }
12874887Schin if (drop)
12884887Schin {
12894887Schin if (call = sfstruse(sp))
12904887Schin call = buffer(call);
12914887Schin else
12924887Schin call = "[ out of space ]";
12934887Schin sfclose(sp);
12944887Schin return call;
12954887Schin }
12964887Schin bad:
12974887Schin return (listflags & ASTCONF_error) ? (char*)0 : null;
12984887Schin }
12994887Schin
13004887Schin /*
13014887Schin * return read stream to native getconf utility
13024887Schin */
13034887Schin
13044887Schin static Sfio_t*
13054887Schin nativeconf(Proc_t** pp, const char* operand)
13064887Schin {
13074887Schin #ifdef _pth_getconf
13084887Schin Sfio_t* sp;
13094887Schin char* cmd[3];
13104887Schin long ops[2];
13114887Schin
131210898Sroland.mainz@nrubsig.org #if DEBUG_astconf
13134887Schin error(-2, "astconf defer %s %s", _pth_getconf, operand);
13144887Schin #endif
13154887Schin cmd[0] = (char*)state.id;
13164887Schin cmd[1] = (char*)operand;
13174887Schin cmd[2] = 0;
13184887Schin ops[0] = PROC_FD_DUP(open("/dev/null",O_WRONLY,0), 2, PROC_FD_CHILD);
13194887Schin ops[1] = 0;
13204887Schin if (*pp = procopen(_pth_getconf, cmd, environ, ops, PROC_READ))
13214887Schin {
13224887Schin if (sp = sfnew(NiL, NiL, SF_UNBOUND, (*pp)->rfd, SF_READ))
13234887Schin {
13244887Schin sfdisc(sp, SF_POPDISC);
13254887Schin return sp;
13264887Schin }
13274887Schin procclose(*pp);
13284887Schin }
13294887Schin #endif
13304887Schin return 0;
13314887Schin }
13324887Schin
13334887Schin /*
13344887Schin * value==0 gets value for name
13354887Schin * value!=0 sets value for name and returns previous value
13364887Schin * path==0 implies path=="/"
13374887Schin *
13384887Schin * settable return values are in permanent store
13394887Schin * non-settable return values copied to a tmp fmtbuf() buffer
13404887Schin *
13414887Schin * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical"))
13424887Schin * our_way();
13434887Schin *
13444887Schin * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0);
13454887Schin * astgetconf("UNIVERSE", NiL, universe, 0, 0);
13464887Schin *
13474887Schin * if (flags&ASTCONF_error)!=0 then error return value is 0
13484887Schin * otherwise 0 not returned
13494887Schin */
13504887Schin
13514887Schin #define ALT 16
13524887Schin
13534887Schin char*
13544887Schin astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror)
13554887Schin {
13564887Schin register char* s;
13574887Schin int n;
13584887Schin Lookup_t look;
13594887Schin Sfio_t* tmp;
13604887Schin
13614887Schin #if __OBSOLETE__ < 20080101
13624887Schin if (pointerof(flags) == (void*)errorf)
13634887Schin {
13644887Schin conferror = errorf;
13654887Schin flags = ASTCONF_error;
13664887Schin }
13674887Schin else if (conferror && conferror != errorf)
13684887Schin conferror = 0;
13694887Schin #endif
13704887Schin if (!name)
13714887Schin {
13724887Schin if (path)
13734887Schin return null;
13744887Schin if (!(name = value))
13754887Schin {
13764887Schin if (state.data)
13774887Schin {
13784887Schin Ast_confdisc_f notify;
13794887Schin
13804887Schin #if _HUH20000515 /* doesn't work for shell builtins */
13814887Schin free(state.data - state.prefix);
13824887Schin #endif
13834887Schin state.data = 0;
13844887Schin notify = state.notify;
13854887Schin state.notify = 0;
13864887Schin INITIALIZE();
13874887Schin state.notify = notify;
13884887Schin }
13894887Schin return null;
13904887Schin }
13914887Schin value = 0;
13924887Schin }
13934887Schin INITIALIZE();
13944887Schin if (!path)
13954887Schin path = root;
13964887Schin if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror)))
13974887Schin return s;
13984887Schin if (lookup(&look, name, flags))
13994887Schin {
14004887Schin if (value)
14014887Schin {
14024887Schin ro:
14034887Schin errno = EINVAL;
14044887Schin if (conferror)
14054887Schin (*conferror)(&state, &state, 2, "%s: cannot set value", name);
14064887Schin return (flags & ASTCONF_error) ? (char*)0 : null;
14074887Schin }
14084887Schin return print(NiL, &look, name, path, flags, conferror);
14094887Schin }
14104887Schin if ((n = strlen(name)) > 3 && n < (ALT + 3))
14114887Schin {
14124887Schin if (streq(name + n - 3, "DEV"))
14134887Schin {
14144887Schin if (tmp = sfstropen())
14154887Schin {
14164887Schin sfprintf(tmp, "/dev/");
14174887Schin for (s = (char*)name; s < (char*)name + n - 3; s++)
14184887Schin sfputc(tmp, isupper(*s) ? tolower(*s) : *s);
14194887Schin if ((s = sfstruse(tmp)) && !access(s, F_OK))
14204887Schin {
14214887Schin if (value)
14224887Schin goto ro;
14234887Schin s = buffer(s);
14244887Schin sfclose(tmp);
14254887Schin return s;
14264887Schin }
14274887Schin sfclose(tmp);
14284887Schin }
14294887Schin }
14304887Schin else if (streq(name + n - 3, "DIR"))
14314887Schin {
14324887Schin Lookup_t altlook;
14334887Schin char altname[ALT];
14344887Schin
14354887Schin static const char* dirs[] = { "/usr/lib", "/usr", null };
14364887Schin
14374887Schin strcpy(altname, name);
14384887Schin altname[n - 3] = 0;
14394887Schin if (lookup(&altlook, altname, flags))
14404887Schin {
14414887Schin if (value)
14424887Schin {
14434887Schin errno = EINVAL;
14444887Schin if (conferror)
14454887Schin (*conferror)(&state, &state, 2, "%s: cannot set value", altname);
14464887Schin return (flags & ASTCONF_error) ? (char*)0 : null;
14474887Schin }
14484887Schin return print(NiL, &altlook, altname, path, flags, conferror);
14494887Schin }
14504887Schin for (s = altname; *s; s++)
14514887Schin if (isupper(*s))
14524887Schin *s = tolower(*s);
14534887Schin if (tmp = sfstropen())
14544887Schin {
14554887Schin for (n = 0; n < elementsof(dirs); n++)
14564887Schin {
14574887Schin sfprintf(tmp, "%s/%s/.", dirs[n], altname);
14584887Schin if ((s = sfstruse(tmp)) && !access(s, F_OK))
14594887Schin {
14604887Schin if (value)
14614887Schin goto ro;
14624887Schin s = buffer(s);
14634887Schin sfclose(tmp);
14644887Schin return s;
14654887Schin }
14664887Schin }
14674887Schin sfclose(tmp);
14684887Schin }
14694887Schin }
14704887Schin }
14714887Schin if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(look.name, path, value, flags, conferror)))
14724887Schin return s;
14734887Schin errno = EINVAL;
14744887Schin if (conferror && !(flags & ASTCONF_system))
14754887Schin (*conferror)(&state, &state, 2, "%s: unknown name", name);
14764887Schin return (flags & ASTCONF_error) ? (char*)0 : null;
14774887Schin }
14784887Schin
14794887Schin /*
14804887Schin * astconf() never returns 0
14814887Schin */
14824887Schin
14834887Schin char*
14844887Schin astconf(const char* name, const char* path, const char* value)
14854887Schin {
14864887Schin return astgetconf(name, path, value, 0, 0);
14874887Schin }
14884887Schin
14894887Schin /*
14904887Schin * set discipline function to be called when features change
14914887Schin * old discipline function returned
14924887Schin */
14934887Schin
14944887Schin Ast_confdisc_f
14954887Schin astconfdisc(Ast_confdisc_f new_notify)
14964887Schin {
14974887Schin Ast_confdisc_f old_notify;
14984887Schin
14994887Schin INITIALIZE();
15004887Schin old_notify = state.notify;
15014887Schin state.notify = new_notify;
15024887Schin return old_notify;
15034887Schin }
15044887Schin
15054887Schin /*
15064887Schin * list all name=value entries on sp
15074887Schin * path==0 implies path=="/"
15084887Schin */
15094887Schin
15104887Schin void
15114887Schin astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
15124887Schin {
15134887Schin char* s;
15144887Schin char* f;
15154887Schin char* call;
15164887Schin Feature_t* fp;
15174887Schin Lookup_t look;
15184887Schin regex_t re;
15194887Schin regdisc_t redisc;
15204887Schin int olderrno;
15214887Schin char flg[8];
15224887Schin #ifdef _pth_getconf_a
15234887Schin Proc_t* proc;
15244887Schin Sfio_t* pp;
15254887Schin #endif
15264887Schin
15274887Schin INITIALIZE();
15284887Schin if (!path)
15294887Schin path = root;
15304887Schin else if (access(path, F_OK))
15314887Schin {
15324887Schin errorf(&state, &state, 2, "%s: not found", path);
15334887Schin return;
15344887Schin }
15354887Schin olderrno = errno;
15364887Schin look.flags = 0;
15374887Schin if (!(flags & (ASTCONF_read|ASTCONF_write|ASTCONF_parse)))
15384887Schin flags |= ASTCONF_read|ASTCONF_write;
15394887Schin else if (flags & ASTCONF_parse)
15404887Schin flags |= ASTCONF_write;
15414887Schin if (!(flags & (ASTCONF_matchcall|ASTCONF_matchname|ASTCONF_matchstandard)))
15424887Schin pattern = 0;
15434887Schin if (pattern)
15444887Schin {
15454887Schin memset(&redisc, 0, sizeof(redisc));
15464887Schin redisc.re_version = REG_VERSION;
15474887Schin redisc.re_errorf = (regerror_t)errorf;
15484887Schin re.re_disc = &redisc;
15494887Schin if (regcomp(&re, pattern, REG_DISCIPLINE|REG_EXTENDED|REG_LENIENT|REG_NULL))
15504887Schin return;
15514887Schin }
15524887Schin if (flags & ASTCONF_read)
15534887Schin {
15544887Schin for (look.conf = (Conf_t*)conf; look.conf < (Conf_t*)&conf[conf_elements]; look.conf++)
15554887Schin {
15564887Schin if (pattern)
15574887Schin {
15584887Schin if (flags & ASTCONF_matchcall)
15594887Schin {
15604887Schin if (regexec(&re, prefix[look.conf->call + CONF_call].name, 0, NiL, 0))
15614887Schin continue;
15624887Schin }
15634887Schin else if (flags & ASTCONF_matchname)
15644887Schin {
15654887Schin if (regexec(&re, look.conf->name, 0, NiL, 0))
15664887Schin continue;
15674887Schin }
15684887Schin else if (flags & ASTCONF_matchstandard)
15694887Schin {
15704887Schin if (regexec(&re, prefix[look.conf->standard].name, 0, NiL, 0))
15714887Schin continue;
15724887Schin }
15734887Schin }
15744887Schin print(sp, &look, NiL, path, flags, errorf);
15754887Schin }
15764887Schin #ifdef _pth_getconf_a
15774887Schin if (pp = nativeconf(&proc, _pth_getconf_a))
15784887Schin {
15794887Schin call = "GC";
15804887Schin while (f = sfgetr(pp, '\n', 1))
15814887Schin {
15824887Schin for (s = f; *s && *s != '=' && *s != ':' && !isspace(*s); s++);
15834887Schin if (*s)
15844887Schin for (*s++ = 0; isspace(*s); s++);
15854887Schin if (!lookup(&look, f, flags))
15864887Schin {
15874887Schin if (flags & ASTCONF_table)
15884887Schin {
15894887Schin if (look.standard < 0)
15904887Schin look.standard = 0;
15914887Schin if (look.section < 1)
15924887Schin look.section = 1;
15934887Schin sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), f, sizeof(prefix[look.standard].name), prefix[look.standard].name, look.section, call, 0, "N", s);
15944887Schin }
15954887Schin else if (flags & ASTCONF_parse)
15964887Schin sfprintf(sp, "%s %s - %s\n", state.id, f, s);
15974887Schin else
15984887Schin sfprintf(sp, "%s=%s\n", f, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
15994887Schin }
16004887Schin }
16014887Schin sfclose(pp);
16024887Schin procclose(proc);
16034887Schin }
16044887Schin #endif
16054887Schin }
16064887Schin if (flags & ASTCONF_write)
16074887Schin {
16084887Schin call = "AC";
16094887Schin for (fp = state.features; fp; fp = fp->next)
16104887Schin {
16114887Schin if (pattern)
16124887Schin {
16134887Schin if (flags & ASTCONF_matchcall)
16144887Schin {
16154887Schin if (regexec(&re, call, 0, NiL, 0))
16164887Schin continue;
16174887Schin }
16184887Schin else if (flags & ASTCONF_matchname)
16194887Schin {
16204887Schin if (regexec(&re, fp->name, 0, NiL, 0))
16214887Schin continue;
16224887Schin }
16234887Schin else if (flags & ASTCONF_matchstandard)
16244887Schin {
16254887Schin if (regexec(&re, prefix[fp->standard].name, 0, NiL, 0))
16264887Schin continue;
16274887Schin }
16284887Schin }
16294887Schin if (!(s = feature(fp->name, path, NiL, 0, 0)) || !*s)
16304887Schin s = "0";
16314887Schin if (flags & ASTCONF_table)
16324887Schin {
16334887Schin f = flg;
16344887Schin if (fp->flags & CONF_ALLOC)
16354887Schin *f++ = 'A';
16364887Schin if (fp->flags & CONF_READONLY)
16374887Schin *f++ = 'R';
16384887Schin if (f == flg)
16394887Schin *f++ = 'X';
16404887Schin *f = 0;
16414887Schin sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), fp->name, sizeof(prefix[fp->standard].name), prefix[fp->standard].name, 1, call, 0, flg, s);
16424887Schin }
16434887Schin else if (flags & ASTCONF_parse)
16444887Schin sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL));
16454887Schin else
16464887Schin sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
16474887Schin }
16484887Schin }
16494887Schin if (pattern)
16504887Schin regfree(&re);
16514887Schin errno = olderrno;
16524887Schin }
1653