mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
dcffad8326
If treated as a complete associative array or scanned (retrieving individual values was not affected), it incorrectly unmetafied the value so multibyte characters got confused. Add test.
2209 lines
50 KiB
C
2209 lines
50 KiB
C
/*
|
|
* parameter.c - parameter interface to zsh internals
|
|
*
|
|
* This file is part of zsh, the Z shell.
|
|
*
|
|
* Copyright (c) 1999 Sven Wischnowsky
|
|
* All rights reserved.
|
|
*
|
|
* Permission is hereby granted, without written agreement and without
|
|
* license or royalty fees, to use, copy, modify, and distribute this
|
|
* software and to distribute modified versions of this software for any
|
|
* purpose, provided that the above copyright notice and the following
|
|
* two paragraphs appear in all copies of this software.
|
|
*
|
|
* In no event shall Sven Wischnowsky or the Zsh Development Group be liable
|
|
* to any party for direct, indirect, special, incidental, or consequential
|
|
* damages arising out of the use of this software and its documentation,
|
|
* even if Sven Wischnowsky and the Zsh Development Group have been advised of
|
|
* the possibility of such damage.
|
|
*
|
|
* Sven Wischnowsky and the Zsh Development Group specifically disclaim any
|
|
* warranties, including, but not limited to, the implied warranties of
|
|
* merchantability and fitness for a particular purpose. The software
|
|
* provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
|
|
* Zsh Development Group have no obligation to provide maintenance,
|
|
* support, updates, enhancements, or modifications.
|
|
*
|
|
*/
|
|
|
|
#include "parameter.mdh"
|
|
#include "parameter.pro"
|
|
|
|
/* This says if we are cleaning up when the module is unloaded. */
|
|
|
|
static int incleanup;
|
|
|
|
/* Functions for the parameters special parameter. */
|
|
|
|
/* Return a string describing the type of a parameter. */
|
|
|
|
/**/
|
|
static char *
|
|
paramtypestr(Param pm)
|
|
{
|
|
char *val = NULL;
|
|
int f = pm->node.flags;
|
|
|
|
if (!(f & PM_UNSET)) {
|
|
if (pm->node.flags & PM_AUTOLOAD)
|
|
return dupstring("undefined");
|
|
|
|
switch (PM_TYPE(f)) {
|
|
case PM_SCALAR: val = "scalar"; break;
|
|
case PM_ARRAY: val = "array"; break;
|
|
case PM_INTEGER: val = "integer"; break;
|
|
case PM_EFLOAT:
|
|
case PM_FFLOAT: val = "float"; break;
|
|
case PM_HASHED: val = "association"; break;
|
|
}
|
|
DPUTS(!val, "BUG: type not handled in parameter");
|
|
val = dupstring(val);
|
|
if (pm->level)
|
|
val = dyncat(val, "-local");
|
|
if (f & PM_LEFT)
|
|
val = dyncat(val, "-left");
|
|
if (f & PM_RIGHT_B)
|
|
val = dyncat(val, "-right_blanks");
|
|
if (f & PM_RIGHT_Z)
|
|
val = dyncat(val, "-right_zeros");
|
|
if (f & PM_LOWER)
|
|
val = dyncat(val, "-lower");
|
|
if (f & PM_UPPER)
|
|
val = dyncat(val, "-upper");
|
|
if (f & PM_READONLY)
|
|
val = dyncat(val, "-readonly");
|
|
if (f & PM_TAGGED)
|
|
val = dyncat(val, "-tag");
|
|
if (f & PM_EXPORTED)
|
|
val = dyncat(val, "-export");
|
|
if (f & PM_UNIQUE)
|
|
val = dyncat(val, "-unique");
|
|
if (f & PM_HIDE)
|
|
val = dyncat(val, "-hide");
|
|
if (f & PM_HIDEVAL)
|
|
val = dyncat(val, "-hideval");
|
|
if (f & PM_SPECIAL)
|
|
val = dyncat(val, "-special");
|
|
} else
|
|
val = dupstring("");
|
|
|
|
return val;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmparameter(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param rpm, pm = NULL;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
|
|
!(rpm->node.flags & PM_UNSET))
|
|
pm->u.str = paramtypestr(rpm);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (i = 0; i < realparamtab->hsize; i++)
|
|
for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
|
|
if (((Param)hn)->node.flags & PM_UNSET)
|
|
continue;
|
|
pm.node.nam = hn->nam;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS)))
|
|
pm.u.str = paramtypestr((Param) hn);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
|
|
/* Functions for the commands special parameter. */
|
|
|
|
/**/
|
|
static void
|
|
setpmcommand(Param pm, char *value)
|
|
{
|
|
if (isset(RESTRICTED)) {
|
|
zwarn("restricted: %s", value);
|
|
zsfree(value);
|
|
} else {
|
|
Cmdnam cn = zshcalloc(sizeof(*cn));
|
|
|
|
cn->node.flags = HASHED;
|
|
cn->u.cmd = value;
|
|
|
|
cmdnamtab->addnode(cmdnamtab, ztrdup(pm->node.nam), &cn->node);
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmcommand(Param pm, UNUSED(int exp))
|
|
{
|
|
HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->node.nam);
|
|
|
|
if (hn)
|
|
cmdnamtab->freenode(hn);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmcommands(UNUSED(Param pm), HashTable ht)
|
|
{
|
|
int i;
|
|
HashNode hn;
|
|
|
|
if (!ht)
|
|
return;
|
|
|
|
for (i = 0; i < ht->hsize; i++)
|
|
for (hn = ht->nodes[i]; hn; hn = hn->next) {
|
|
Cmdnam cn = zshcalloc(sizeof(*cn));
|
|
struct value v;
|
|
|
|
v.isarr = v.flags = v.start = 0;
|
|
v.end = -1;
|
|
v.arr = NULL;
|
|
v.pm = (Param) hn;
|
|
|
|
cn->node.flags = HASHED;
|
|
cn->u.cmd = ztrdup(getstrvalue(&v));
|
|
|
|
cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), &cn->node);
|
|
}
|
|
deleteparamtable(ht);
|
|
}
|
|
|
|
static const struct gsu_scalar pmcommand_gsu =
|
|
{ strgetfn, setpmcommand, unsetpmcommand };
|
|
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmcommand(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Cmdnam cmd;
|
|
Param pm = NULL;
|
|
|
|
if (!(cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name)) &&
|
|
isset(HASHLISTALL)) {
|
|
cmdnamtab->filltable(cmdnamtab);
|
|
cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name);
|
|
}
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR;
|
|
pm->gsu.s = &pmcommand_gsu;
|
|
if (cmd) {
|
|
if (cmd->node.flags & HASHED)
|
|
pm->u.str = cmd->u.cmd;
|
|
else {
|
|
pm->u.str = zhalloc(strlen(*(cmd->u.name)) + strlen(name) + 2);
|
|
strcpy(pm->u.str, *(cmd->u.name));
|
|
strcat(pm->u.str, "/");
|
|
strcat(pm->u.str, name);
|
|
}
|
|
} else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmcommands(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
Cmdnam cmd;
|
|
|
|
if (isset(HASHLISTALL))
|
|
cmdnamtab->filltable(cmdnamtab);
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR;
|
|
pm.gsu.s = &pmcommand_gsu;
|
|
|
|
for (i = 0; i < cmdnamtab->hsize; i++)
|
|
for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) {
|
|
pm.node.nam = hn->nam;
|
|
cmd = (Cmdnam) hn;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))) {
|
|
if (cmd->node.flags & HASHED)
|
|
pm.u.str = cmd->u.cmd;
|
|
else {
|
|
pm.u.str = zhalloc(strlen(*(cmd->u.name)) +
|
|
strlen(cmd->node.nam) + 2);
|
|
strcpy(pm.u.str, *(cmd->u.name));
|
|
strcat(pm.u.str, "/");
|
|
strcat(pm.u.str, cmd->node.nam);
|
|
}
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
|
|
/* Functions for the functions special parameter. */
|
|
|
|
/**/
|
|
static void
|
|
setfunction(char *name, char *val, int dis)
|
|
{
|
|
char *value = dupstring(val);
|
|
Shfunc shf;
|
|
Eprog prog;
|
|
int sn;
|
|
|
|
val = metafy(val, strlen(val), META_REALLOC);
|
|
|
|
prog = parse_string(val, 1);
|
|
|
|
if (!prog || prog == &dummy_eprog) {
|
|
zwarn("invalid function definition", value);
|
|
zsfree(val);
|
|
return;
|
|
}
|
|
shf = (Shfunc) zshcalloc(sizeof(*shf));
|
|
shf->funcdef = dupeprog(prog, 0);
|
|
shf->node.flags = dis;
|
|
shfunc_set_sticky(shf);
|
|
|
|
if (!strncmp(name, "TRAP", 4) &&
|
|
(sn = getsignum(name + 4)) != -1) {
|
|
if (settrap(sn, NULL, ZSIG_FUNC)) {
|
|
freeeprog(shf->funcdef);
|
|
zfree(shf, sizeof(*shf));
|
|
zsfree(val);
|
|
return;
|
|
}
|
|
}
|
|
shfunctab->addnode(shfunctab, ztrdup(name), shf);
|
|
zsfree(val);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmfunction(Param pm, char *value)
|
|
{
|
|
setfunction(pm->node.nam, value, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisfunction(Param pm, char *value)
|
|
{
|
|
setfunction(pm->node.nam, value, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmfunction(Param pm, UNUSED(int exp))
|
|
{
|
|
HashNode hn = shfunctab->removenode(shfunctab, pm->node.nam);
|
|
|
|
if (hn)
|
|
shfunctab->freenode(hn);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setfunctions(UNUSED(Param pm), HashTable ht, int dis)
|
|
{
|
|
int i;
|
|
HashNode hn;
|
|
|
|
if (!ht)
|
|
return;
|
|
|
|
for (i = 0; i < ht->hsize; i++)
|
|
for (hn = ht->nodes[i]; hn; hn = hn->next) {
|
|
struct value v;
|
|
|
|
v.isarr = v.flags = v.start = 0;
|
|
v.end = -1;
|
|
v.arr = NULL;
|
|
v.pm = (Param) hn;
|
|
|
|
setfunction(hn->nam, ztrdup(getstrvalue(&v)), dis);
|
|
}
|
|
deleteparamtable(ht);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmfunctions(Param pm, HashTable ht)
|
|
{
|
|
setfunctions(pm, ht, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisfunctions(Param pm, HashTable ht)
|
|
{
|
|
setfunctions(pm, ht, DISABLED);
|
|
}
|
|
|
|
static const struct gsu_scalar pmfunction_gsu =
|
|
{ strgetfn, setpmfunction, unsetpmfunction };
|
|
static const struct gsu_scalar pmdisfunction_gsu =
|
|
{ strgetfn, setpmdisfunction, unsetpmfunction };
|
|
|
|
/**/
|
|
static HashNode
|
|
getfunction(UNUSED(HashTable ht), const char *name, int dis)
|
|
{
|
|
Shfunc shf;
|
|
Param pm = NULL;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR;
|
|
pm->gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
|
|
|
|
if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
|
|
(dis ? (shf->node.flags & DISABLED) : !(shf->node.flags & DISABLED))) {
|
|
if (shf->node.flags & PM_UNDEFINED) {
|
|
pm->u.str = dyncat("builtin autoload -X",
|
|
((shf->node.flags & PM_UNALIASED) ?
|
|
((shf->node.flags & PM_TAGGED) ? "Ut" : "U") :
|
|
((shf->node.flags & PM_TAGGED) ? "t" : "")));
|
|
} else {
|
|
char *t = getpermtext(shf->funcdef, NULL, 1), *n, *h;
|
|
char *start;
|
|
|
|
if (shf->redir)
|
|
start = "{\n\t";
|
|
else
|
|
start = "\t";
|
|
|
|
if (shf->funcdef->flags & EF_RUN) {
|
|
n = nicedupstring(name);
|
|
h = (char *) zhalloc(strlen(start) + strlen(t) + strlen(n) + 8);
|
|
strcpy(h, start);
|
|
strcat(h, t);
|
|
strcat(h, "\n\t");
|
|
strcat(h, n);
|
|
strcat(h, " \"$@\"");
|
|
} else
|
|
h = dyncat(start, t);
|
|
zsfree(t);
|
|
|
|
if (shf->redir) {
|
|
t = getpermtext(shf->redir, NULL, 1);
|
|
h = zhtricat(h, "\n}", t);
|
|
zsfree(t);
|
|
}
|
|
|
|
pm->u.str = h;
|
|
}
|
|
} else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmfunction(HashTable ht, const char *name)
|
|
{
|
|
return getfunction(ht, name, 0);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmdisfunction(HashTable ht, const char *name)
|
|
{
|
|
return getfunction(ht, name, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanfunctions(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR;
|
|
pm.gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
|
|
|
|
for (i = 0; i < shfunctab->hsize; i++)
|
|
for (hn = shfunctab->nodes[i]; hn; hn = hn->next) {
|
|
if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
|
|
pm.node.nam = hn->nam;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))) {
|
|
if (((Shfunc) hn)->node.flags & PM_UNDEFINED) {
|
|
Shfunc shf = (Shfunc) hn;
|
|
pm.u.str =
|
|
dyncat("builtin autoload -X",
|
|
((shf->node.flags & PM_UNALIASED) ?
|
|
((shf->node.flags & PM_TAGGED) ? "Ut" : "U") :
|
|
((shf->node.flags & PM_TAGGED) ? "t" : "")));
|
|
} else {
|
|
Shfunc shf = (Shfunc)hn;
|
|
char *t = getpermtext(shf->funcdef, NULL, 1);
|
|
char *n, *start;
|
|
|
|
if (shf->redir)
|
|
start = "{\n\t";
|
|
else
|
|
start = "\t";
|
|
|
|
if (shf->funcdef->flags & EF_RUN) {
|
|
n = nicedupstring(hn->nam);
|
|
pm.u.str = (char *) zhalloc(
|
|
strlen(start) + strlen(t) + strlen(n) + 8);
|
|
strcpy(pm.u.str, start);
|
|
strcat(pm.u.str, t);
|
|
strcat(pm.u.str, "\n\t");
|
|
strcat(pm.u.str, n);
|
|
strcat(pm.u.str, " \"$@\"");
|
|
} else
|
|
pm.u.str = dyncat(start, t);
|
|
zsfree(t);
|
|
|
|
if (shf->redir) {
|
|
t = getpermtext(shf->redir, NULL, 1);
|
|
pm.u.str = zhtricat(pm.u.str, "\n}", t);
|
|
zsfree(t);
|
|
}
|
|
}
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmfunctions(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanfunctions(ht, func, flags, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmdisfunctions(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanfunctions(ht, func, flags, DISABLED);
|
|
}
|
|
|
|
/* Functions for the funcstack special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
funcstackgetfn(UNUSED(Param pm))
|
|
{
|
|
Funcstack f;
|
|
int num;
|
|
char **ret, **p;
|
|
|
|
for (f = funcstack, num = 0; f; f = f->prev, num++);
|
|
|
|
ret = (char **) zhalloc((num + 1) * sizeof(char *));
|
|
|
|
for (f = funcstack, p = ret; f; f = f->prev, p++)
|
|
*p = f->name;
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Functions for the functrace special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
functracegetfn(UNUSED(Param pm))
|
|
{
|
|
Funcstack f;
|
|
int num;
|
|
char **ret, **p;
|
|
|
|
for (f = funcstack, num = 0; f; f = f->prev, num++);
|
|
|
|
ret = (char **) zhalloc((num + 1) * sizeof(char *));
|
|
|
|
for (f = funcstack, p = ret; f; f = f->prev, p++) {
|
|
char *colonpair;
|
|
|
|
colonpair = zhalloc(strlen(f->caller) + (f->lineno > 9999 ? 24 : 6));
|
|
#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
|
|
sprintf(colonpair, "%s:%lld", f->caller, f->lineno);
|
|
#else
|
|
sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
|
|
#endif
|
|
|
|
*p = colonpair;
|
|
}
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Functions for the funcsourcetrace special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
funcsourcetracegetfn(UNUSED(Param pm))
|
|
{
|
|
Funcstack f;
|
|
int num;
|
|
char **ret, **p;
|
|
|
|
for (f = funcstack, num = 0; f; f = f->prev, num++);
|
|
|
|
ret = (char **) zhalloc((num + 1) * sizeof(char *));
|
|
|
|
for (f = funcstack, p = ret; f; f = f->prev, p++) {
|
|
char *colonpair;
|
|
char *fname = f->filename ? f->filename : "";
|
|
|
|
colonpair = zhalloc(strlen(fname) + (f->flineno > 9999 ? 24 : 6));
|
|
#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
|
|
sprintf(colonpair, "%s:%lld", fname, f->flineno);
|
|
#else
|
|
sprintf(colonpair, "%s:%ld", fname, (long)f->flineno);
|
|
#endif
|
|
|
|
*p = colonpair;
|
|
}
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Functions for the funcfiletrace special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
funcfiletracegetfn(UNUSED(Param pm))
|
|
{
|
|
Funcstack f;
|
|
int num;
|
|
char **ret, **p;
|
|
|
|
for (f = funcstack, num = 0; f; f = f->prev, num++);
|
|
|
|
ret = (char **) zhalloc((num + 1) * sizeof(char *));
|
|
|
|
for (f = funcstack, p = ret; f; f = f->prev, p++) {
|
|
char *colonpair, *fname;
|
|
|
|
if (!f->prev || f->prev->tp == FS_SOURCE) {
|
|
/*
|
|
* Calling context is a file---either the parent
|
|
* script or interactive shell, or a sourced
|
|
* script. Just print the file information for the caller
|
|
* (same as $functrace)
|
|
*/
|
|
colonpair = zhalloc(strlen(f->caller) +
|
|
(f->lineno > 9999 ? 24 : 6));
|
|
#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
|
|
sprintf(colonpair, "%s:%lld", f->caller, f->lineno);
|
|
#else
|
|
sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
|
|
#endif
|
|
} else {
|
|
/*
|
|
* Calling context is a function or eval; we need to find
|
|
* the line number in the file where that function was
|
|
* defined or the eval was called. For this we need the
|
|
* $funcsourcetrace information for the context above,
|
|
* together with the $functrace line number for the current
|
|
* context.
|
|
*/
|
|
zlong flineno = f->prev->flineno + f->lineno;
|
|
/*
|
|
* Line numbers in eval start from 1, not zero,
|
|
* so offset by one to get line in file.
|
|
*/
|
|
if (f->prev->tp == FS_EVAL)
|
|
flineno--;
|
|
fname = f->prev->filename ? f->prev->filename : "";
|
|
|
|
colonpair = zhalloc(strlen(fname) + (flineno > 9999 ? 24 : 6));
|
|
#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
|
|
sprintf(colonpair, "%s:%lld", fname, flineno);
|
|
#else
|
|
sprintf(colonpair, "%s:%ld", fname, (long)flineno);
|
|
#endif
|
|
}
|
|
|
|
*p = colonpair;
|
|
}
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Functions for the builtins special parameter. */
|
|
|
|
/**/
|
|
static HashNode
|
|
getbuiltin(UNUSED(HashTable ht), const char *name, int dis)
|
|
{
|
|
Param pm = NULL;
|
|
Builtin bn;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) &&
|
|
(dis ? (bn->node.flags & DISABLED) : !(bn->node.flags & DISABLED))) {
|
|
char *t = ((bn->handlerfunc || (bn->node.flags & BINF_PREFIX)) ?
|
|
"defined" : "undefined");
|
|
|
|
pm->u.str = dupstring(t);
|
|
} else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmbuiltin(HashTable ht, const char *name)
|
|
{
|
|
return getbuiltin(ht, name, 0);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmdisbuiltin(HashTable ht, const char *name)
|
|
{
|
|
return getbuiltin(ht, name, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanbuiltins(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (i = 0; i < builtintab->hsize; i++)
|
|
for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
|
|
if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
|
|
pm.node.nam = hn->nam;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))) {
|
|
char *t = ((((Builtin) hn)->handlerfunc ||
|
|
(hn->flags & BINF_PREFIX)) ?
|
|
"defined" : "undefined");
|
|
|
|
pm.u.str = dupstring(t);
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmbuiltins(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanbuiltins(ht, func, flags, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmdisbuiltins(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanbuiltins(ht, func, flags, DISABLED);
|
|
}
|
|
|
|
/* Functions for the reswords special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
getreswords(int dis)
|
|
{
|
|
int i;
|
|
HashNode hn;
|
|
char **ret, **p;
|
|
|
|
p = ret = (char **) zhalloc((reswdtab->ct + 1) * sizeof(char *));
|
|
|
|
for (i = 0; i < reswdtab->hsize; i++)
|
|
for (hn = reswdtab->nodes[i]; hn; hn = hn->next)
|
|
if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED))
|
|
*p++ = dupstring(hn->nam);
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
static char **
|
|
reswordsgetfn(UNUSED(Param pm))
|
|
{
|
|
return getreswords(0);
|
|
}
|
|
|
|
/**/
|
|
static char **
|
|
disreswordsgetfn(UNUSED(Param pm))
|
|
{
|
|
return getreswords(DISABLED);
|
|
}
|
|
|
|
/* Functions for the patchars special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
getpatchars(int dis)
|
|
{
|
|
int i;
|
|
char **ret, **p;
|
|
|
|
p = ret = (char **) zhalloc(ZPC_COUNT * sizeof(char *));
|
|
|
|
for (i = 0; i < ZPC_COUNT; i++)
|
|
if (zpc_strings[i] && !dis == !zpc_disables[i])
|
|
*p++ = dupstring(zpc_strings[i]);
|
|
|
|
*p = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static char **
|
|
patcharsgetfn(UNUSED(Param pm))
|
|
{
|
|
return getpatchars(0);
|
|
}
|
|
|
|
static char **
|
|
dispatcharsgetfn(UNUSED(Param pm))
|
|
{
|
|
return getpatchars(1);
|
|
}
|
|
|
|
/* Functions for the options special parameter. */
|
|
|
|
/**/
|
|
static void
|
|
setpmoption(Param pm, char *value)
|
|
{
|
|
int n;
|
|
|
|
if (!value || (strcmp(value, "on") && strcmp(value, "off")))
|
|
zwarn("invalid value: %s", value);
|
|
else if (!(n = optlookup(pm->node.nam)))
|
|
zwarn("no such option: %s", pm->node.nam);
|
|
else if (dosetopt(n, (value && strcmp(value, "off")), 0, opts))
|
|
zwarn("can't change option: %s", pm->node.nam);
|
|
zsfree(value);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmoption(Param pm, UNUSED(int exp))
|
|
{
|
|
int n;
|
|
|
|
if (!(n = optlookup(pm->node.nam)))
|
|
zwarn("no such option: %s", pm->node.nam);
|
|
else if (dosetopt(n, 0, 0, opts))
|
|
zwarn("can't change option: %s", pm->node.nam);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmoptions(UNUSED(Param pm), HashTable ht)
|
|
{
|
|
int i;
|
|
HashNode hn;
|
|
|
|
if (!ht)
|
|
return;
|
|
|
|
for (i = 0; i < ht->hsize; i++)
|
|
for (hn = ht->nodes[i]; hn; hn = hn->next) {
|
|
struct value v;
|
|
char *val;
|
|
|
|
v.isarr = v.flags = v.start = 0;
|
|
v.end = -1;
|
|
v.arr = NULL;
|
|
v.pm = (Param) hn;
|
|
|
|
val = getstrvalue(&v);
|
|
if (!val || (strcmp(val, "on") && strcmp(val, "off")))
|
|
zwarn("invalid value: %s", val);
|
|
else if (dosetopt(optlookup(hn->nam),
|
|
(val && strcmp(val, "off")), 0, opts))
|
|
zwarn("can't change option: %s", hn->nam);
|
|
}
|
|
deleteparamtable(ht);
|
|
}
|
|
|
|
static const struct gsu_scalar pmoption_gsu =
|
|
{ strgetfn, setpmoption, unsetpmoption };
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmoption(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
int n;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR;
|
|
pm->gsu.s = &pmoption_gsu;
|
|
|
|
if ((n = optlookup(name)))
|
|
{
|
|
int ison;
|
|
if (n > 0)
|
|
ison = opts[n];
|
|
else
|
|
ison = !opts[-n];
|
|
pm->u.str = dupstring(ison ? "on" : "off");
|
|
}
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmoptions(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR;
|
|
pm.gsu.s = &pmoption_gsu;
|
|
|
|
for (i = 0; i < optiontab->hsize; i++)
|
|
for (hn = optiontab->nodes[i]; hn; hn = hn->next) {
|
|
int optno = ((Optname) hn)->optno, ison;
|
|
pm.node.nam = hn->nam;
|
|
ison = optno < 0 ? !opts[-optno] : opts[optno];
|
|
pm.u.str = dupstring(ison ? "on" : "off");
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
|
|
/* Functions for the modules special parameter. */
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmmodule(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
char *type = NULL;
|
|
Module m;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
m = (Module)modulestab->getnode2(modulestab, name);
|
|
|
|
if (!m)
|
|
return NULL;
|
|
if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) {
|
|
type = ((m->node.flags & MOD_ALIAS) ?
|
|
dyncat("alias:", m->u.alias) : "loaded");
|
|
}
|
|
if (!type) {
|
|
if (m->autoloads && firstnode(m->autoloads))
|
|
type = "autoloaded";
|
|
}
|
|
if (type)
|
|
pm->u.str = dupstring(type);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
LinkList done = newlinklist();
|
|
Module m;
|
|
Conddef p;
|
|
char *loaded = dupstring("loaded");
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (i = 0; i < modulestab->hsize; i++) {
|
|
for (hn = modulestab->nodes[i]; hn; hn = hn->next) {
|
|
m = (Module) hn;
|
|
if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) {
|
|
pm.node.nam = m->node.nam;
|
|
pm.u.str = ((m->node.flags & MOD_ALIAS) ?
|
|
dyncat("alias:", m->u.alias) : loaded);
|
|
addlinknode(done, pm.node.nam);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
pm.u.str = dupstring("autoloaded");
|
|
for (i = 0; i < builtintab->hsize; i++)
|
|
for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
|
|
if (!(((Builtin) hn)->node.flags & BINF_ADDED) &&
|
|
!linknodebystring(done, ((Builtin) hn)->optstr)) {
|
|
pm.node.nam = ((Builtin) hn)->optstr;
|
|
addlinknode(done, pm.node.nam);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
for (p = condtab; p; p = p->next)
|
|
if (p->module && !linknodebystring(done, p->module)) {
|
|
pm.node.nam = p->module;
|
|
addlinknode(done, pm.node.nam);
|
|
func(&pm.node, flags);
|
|
}
|
|
for (i = 0; i < realparamtab->hsize; i++)
|
|
for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
|
|
if ((((Param) hn)->node.flags & PM_AUTOLOAD) &&
|
|
!linknodebystring(done, ((Param) hn)->u.str)) {
|
|
pm.node.nam = ((Param) hn)->u.str;
|
|
addlinknode(done, pm.node.nam);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the dirstack special parameter. */
|
|
|
|
/**/
|
|
static void
|
|
dirssetfn(UNUSED(Param pm), char **x)
|
|
{
|
|
char **ox = x;
|
|
|
|
if (!incleanup) {
|
|
freelinklist(dirstack, freestr);
|
|
dirstack = znewlinklist();
|
|
while (x && *x)
|
|
zaddlinknode(dirstack, ztrdup(*x++));
|
|
}
|
|
if (ox)
|
|
freearray(ox);
|
|
}
|
|
|
|
/**/
|
|
static char **
|
|
dirsgetfn(UNUSED(Param pm))
|
|
{
|
|
return hlinklist2array(dirstack, 1);
|
|
}
|
|
|
|
/* Functions for the history special parameter. */
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmhistory(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
Histent he;
|
|
const char *p;
|
|
int ok = 1;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
if (*name != '0' || name[1]) {
|
|
if (*name == '0')
|
|
ok = 0;
|
|
else {
|
|
for (p = name; *p && idigit(*p); p++);
|
|
if (*p)
|
|
ok = 0;
|
|
}
|
|
}
|
|
if (ok && (he = quietgethist(atoi(name))))
|
|
pm->u.str = dupstring(he->node.nam);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmhistory(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i = addhistnum(curhist, -1, HIST_FOREIGN);
|
|
Histent he = gethistent(i, GETHIST_UPWARD);
|
|
char buf[40];
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
while (he) {
|
|
if (func != scancountparams) {
|
|
convbase(buf, he->histnum, 10);
|
|
pm.node.nam = dupstring(buf);
|
|
if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))
|
|
pm.u.str = dupstring(he->node.nam);
|
|
}
|
|
func(&pm.node, flags);
|
|
|
|
he = up_histent(he);
|
|
}
|
|
}
|
|
|
|
/* Function for the historywords special parameter. */
|
|
|
|
/**/
|
|
static char **
|
|
histwgetfn(UNUSED(Param pm))
|
|
{
|
|
char *h, *e, sav;
|
|
LinkList l = newlinklist(), ll;
|
|
LinkNode n;
|
|
int i = addhistnum(curhist, -1, HIST_FOREIGN), iw;
|
|
Histent he = gethistent(i, GETHIST_UPWARD);
|
|
|
|
if ((ll = bufferwords(NULL, NULL, NULL, 0)))
|
|
for (n = firstnode(ll); n; incnode(n))
|
|
pushnode(l, getdata(n));
|
|
|
|
while (he) {
|
|
for (iw = he->nwords - 1; iw >= 0; iw--) {
|
|
h = he->node.nam + he->words[iw * 2];
|
|
e = he->node.nam + he->words[iw * 2 + 1];
|
|
sav = *e;
|
|
*e = '\0';
|
|
addlinknode(l, dupstring(h));
|
|
*e = sav;
|
|
}
|
|
he = up_histent(he);
|
|
}
|
|
|
|
return hlinklist2array(l, 0);
|
|
}
|
|
|
|
/* Functions for the jobtexts special parameter. */
|
|
|
|
/**/
|
|
static char *
|
|
pmjobtext(int job)
|
|
{
|
|
Process pn;
|
|
int len = 1;
|
|
char *ret;
|
|
|
|
for (pn = jobtab[job].procs; pn; pn = pn->next)
|
|
len += strlen(pn->text) + 3;
|
|
|
|
ret = (char *) zhalloc(len);
|
|
ret[0] = '\0';
|
|
|
|
for (pn = jobtab[job].procs; pn; pn = pn->next) {
|
|
strcat(ret, pn->text);
|
|
if (pn->next)
|
|
strcat(ret, " | ");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmjobtext(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
int job;
|
|
char *pend;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
job = strtod(name, &pend);
|
|
/* Non-numeric keys are looked up by job name */
|
|
if (*pend)
|
|
job = getjob(name, NULL);
|
|
if (job >= 1 && job <= maxjob &&
|
|
jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT))
|
|
pm->u.str = pmjobtext(job);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int job;
|
|
char buf[40];
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (job = 1; job <= maxjob; job++) {
|
|
if (jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT)) {
|
|
if (func != scancountparams) {
|
|
sprintf(buf, "%d", job);
|
|
pm.node.nam = dupstring(buf);
|
|
if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))
|
|
pm.u.str = pmjobtext(job);
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the jobstates special parameter. */
|
|
|
|
/**/
|
|
static char *
|
|
pmjobstate(int job)
|
|
{
|
|
Process pn;
|
|
char buf[256], buf2[128], *ret, *state, *cp;
|
|
|
|
if (job == curjob)
|
|
cp = ":+";
|
|
else if (job == prevjob)
|
|
cp = ":-";
|
|
else
|
|
cp = ":";
|
|
|
|
if (jobtab[job].stat & STAT_DONE)
|
|
ret = dyncat("done", cp);
|
|
else if (jobtab[job].stat & STAT_STOPPED)
|
|
ret = dyncat("suspended", cp);
|
|
else
|
|
ret = dyncat("running", cp);
|
|
|
|
for (pn = jobtab[job].procs; pn; pn = pn->next) {
|
|
|
|
if (pn->status == SP_RUNNING)
|
|
state = "running";
|
|
else if (WIFEXITED(pn->status)) {
|
|
if (WEXITSTATUS(pn->status))
|
|
sprintf((state = buf2), "exit %d", (pn->status));
|
|
else
|
|
state = "done";
|
|
} else if (WIFSTOPPED(pn->status))
|
|
state = sigmsg(WSTOPSIG(pn->status));
|
|
else if (WCOREDUMP(pn->status))
|
|
sprintf((state = buf2), "%s (core dumped)",
|
|
sigmsg(WTERMSIG(pn->status)));
|
|
else
|
|
state = sigmsg(WTERMSIG(pn->status));
|
|
|
|
sprintf(buf, ":%d=%s", (int)pn->pid, state);
|
|
|
|
ret = dyncat(ret, buf);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmjobstate(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
int job;
|
|
char *pend;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
job = strtod(name, &pend);
|
|
if (*pend)
|
|
job = getjob(name, NULL);
|
|
if (job >= 1 && job <= maxjob &&
|
|
jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT))
|
|
pm->u.str = pmjobstate(job);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmjobstates(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int job;
|
|
char buf[40];
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (job = 1; job <= maxjob; job++) {
|
|
if (jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT)) {
|
|
if (func != scancountparams) {
|
|
sprintf(buf, "%d", job);
|
|
pm.node.nam = dupstring(buf);
|
|
if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))
|
|
pm.u.str = pmjobstate(job);
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the jobdirs special parameter. */
|
|
|
|
/**/
|
|
static char *
|
|
pmjobdir(int job)
|
|
{
|
|
char *ret;
|
|
|
|
ret = dupstring(jobtab[job].pwd ? jobtab[job].pwd : pwd);
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmjobdir(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
int job;
|
|
char *pend;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
job = strtod(name, &pend);
|
|
if (*pend)
|
|
job = getjob(name, NULL);
|
|
if (job >= 1 && job <= maxjob &&
|
|
jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT))
|
|
pm->u.str = pmjobdir(job);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmjobdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int job;
|
|
char buf[40];
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (job = 1; job <= maxjob; job++) {
|
|
if (jobtab[job].stat && jobtab[job].procs &&
|
|
!(jobtab[job].stat & STAT_NOPRINT)) {
|
|
if (func != scancountparams) {
|
|
sprintf(buf, "%d", job);
|
|
pm.node.nam = dupstring(buf);
|
|
if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))
|
|
pm.u.str = pmjobdir(job);
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the nameddirs special parameter. */
|
|
|
|
/**/
|
|
static void
|
|
setpmnameddir(Param pm, char *value)
|
|
{
|
|
if (!value)
|
|
zwarn("invalid value: ''");
|
|
else {
|
|
Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
|
|
|
|
nd->node.flags = 0;
|
|
nd->dir = value;
|
|
nameddirtab->addnode(nameddirtab, ztrdup(pm->node.nam), nd);
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmnameddir(Param pm, UNUSED(int exp))
|
|
{
|
|
HashNode hd = nameddirtab->removenode(nameddirtab, pm->node.nam);
|
|
|
|
if (hd)
|
|
nameddirtab->freenode(hd);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmnameddirs(UNUSED(Param pm), HashTable ht)
|
|
{
|
|
int i;
|
|
HashNode hn, next, hd;
|
|
|
|
if (!ht)
|
|
return;
|
|
|
|
for (i = 0; i < nameddirtab->hsize; i++)
|
|
for (hn = nameddirtab->nodes[i]; hn; hn = next) {
|
|
next = hn->next;
|
|
if (!(((Nameddir) hn)->node.flags & ND_USERNAME) &&
|
|
(hd = nameddirtab->removenode(nameddirtab, hn->nam)))
|
|
nameddirtab->freenode(hd);
|
|
}
|
|
|
|
for (i = 0; i < ht->hsize; i++)
|
|
for (hn = ht->nodes[i]; hn; hn = hn->next) {
|
|
struct value v;
|
|
char *val;
|
|
|
|
v.isarr = v.flags = v.start = 0;
|
|
v.end = -1;
|
|
v.arr = NULL;
|
|
v.pm = (Param) hn;
|
|
|
|
if (!(val = getstrvalue(&v)))
|
|
zwarn("invalid value: ''");
|
|
else {
|
|
Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
|
|
|
|
nd->node.flags = 0;
|
|
nd->dir = ztrdup(val);
|
|
nameddirtab->addnode(nameddirtab, ztrdup(hn->nam), nd);
|
|
}
|
|
}
|
|
|
|
/* The INTERACTIVE stuff ensures that the dirs are not immediatly removed
|
|
* when the sub-pms are deleted. */
|
|
|
|
i = opts[INTERACTIVE];
|
|
opts[INTERACTIVE] = 0;
|
|
deleteparamtable(ht);
|
|
opts[INTERACTIVE] = i;
|
|
}
|
|
|
|
static const struct gsu_scalar pmnamedir_gsu =
|
|
{ strgetfn, setpmnameddir, unsetpmnameddir };
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmnameddir(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
Nameddir nd;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR;
|
|
pm->gsu.s = &pmnamedir_gsu;
|
|
if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
|
|
!(nd->node.flags & ND_USERNAME))
|
|
pm->u.str = dupstring(nd->dir);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmnameddirs(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
Nameddir nd;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR;
|
|
pm.gsu.s = &pmnamedir_gsu;
|
|
|
|
for (i = 0; i < nameddirtab->hsize; i++)
|
|
for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
|
|
if (!((nd = (Nameddir) hn)->node.flags & ND_USERNAME)) {
|
|
pm.node.nam = hn->nam;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS)))
|
|
pm.u.str = dupstring(nd->dir);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the userdirs special parameter. */
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmuserdir(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
Nameddir nd;
|
|
|
|
nameddirtab->filltable(nameddirtab);
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
|
|
(nd->node.flags & ND_USERNAME))
|
|
pm->u.str = dupstring(nd->dir);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmuserdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
HashNode hn;
|
|
Nameddir nd;
|
|
|
|
nameddirtab->filltable(nameddirtab);
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (i = 0; i < nameddirtab->hsize; i++)
|
|
for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
|
|
if ((nd = (Nameddir) hn)->node.flags & ND_USERNAME) {
|
|
pm.node.nam = hn->nam;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS)))
|
|
pm.u.str = dupstring(nd->dir);
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions for the raliases, galiases and saliases special parameters. */
|
|
|
|
/**/
|
|
static void
|
|
setalias(HashTable ht, Param pm, char *value, int flags)
|
|
{
|
|
ht->addnode(ht, ztrdup(pm->node.nam),
|
|
createaliasnode(value, flags));
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmralias(Param pm, char *value)
|
|
{
|
|
setalias(aliastab, pm, value, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisralias(Param pm, char *value)
|
|
{
|
|
setalias(aliastab, pm, value, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmgalias(Param pm, char *value)
|
|
{
|
|
setalias(aliastab, pm, value, ALIAS_GLOBAL);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisgalias(Param pm, char *value)
|
|
{
|
|
setalias(aliastab, pm, value, ALIAS_GLOBAL|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmsalias(Param pm, char *value)
|
|
{
|
|
setalias(sufaliastab, pm, value, ALIAS_SUFFIX);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdissalias(Param pm, char *value)
|
|
{
|
|
setalias(sufaliastab, pm, value, ALIAS_SUFFIX|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmalias(Param pm, UNUSED(int exp))
|
|
{
|
|
HashNode hd = aliastab->removenode(aliastab, pm->node.nam);
|
|
|
|
if (hd)
|
|
aliastab->freenode(hd);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
unsetpmsalias(Param pm, UNUSED(int exp))
|
|
{
|
|
HashNode hd = sufaliastab->removenode(sufaliastab, pm->node.nam);
|
|
|
|
if (hd)
|
|
sufaliastab->freenode(hd);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setaliases(HashTable alht, UNUSED(Param pm), HashTable ht, int flags)
|
|
{
|
|
int i;
|
|
HashNode hn, next, hd;
|
|
|
|
if (!ht)
|
|
return;
|
|
|
|
for (i = 0; i < alht->hsize; i++)
|
|
for (hn = alht->nodes[i]; hn; hn = next) {
|
|
next = hn->next;
|
|
/*
|
|
* The following respects the DISABLED flag, e.g.
|
|
* we get a different behaviour for raliases and dis_raliases.
|
|
* The predecessor to this code didn't do that; presumably
|
|
* that was a bug.
|
|
*/
|
|
if (flags == ((Alias)hn)->node.flags &&
|
|
(hd = alht->removenode(alht, hn->nam)))
|
|
alht->freenode(hd);
|
|
}
|
|
|
|
for (i = 0; i < ht->hsize; i++)
|
|
for (hn = ht->nodes[i]; hn; hn = hn->next) {
|
|
struct value v;
|
|
char *val;
|
|
|
|
v.isarr = v.flags = v.start = 0;
|
|
v.end = -1;
|
|
v.arr = NULL;
|
|
v.pm = (Param) hn;
|
|
|
|
if ((val = getstrvalue(&v)))
|
|
alht->addnode(alht, ztrdup(hn->nam),
|
|
createaliasnode(ztrdup(val), flags));
|
|
}
|
|
deleteparamtable(ht);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmraliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(aliastab, pm, ht, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisraliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(aliastab, pm, ht, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmgaliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(aliastab, pm, ht, ALIAS_GLOBAL);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdisgaliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(aliastab, pm, ht, ALIAS_GLOBAL|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmsaliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
setpmdissaliases(Param pm, HashTable ht)
|
|
{
|
|
setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX|DISABLED);
|
|
}
|
|
|
|
static const struct gsu_scalar pmralias_gsu =
|
|
{ strgetfn, setpmralias, unsetpmalias };
|
|
static const struct gsu_scalar pmgalias_gsu =
|
|
{ strgetfn, setpmgalias, unsetpmalias };
|
|
static const struct gsu_scalar pmsalias_gsu =
|
|
{ strgetfn, setpmsalias, unsetpmsalias };
|
|
static const struct gsu_scalar pmdisralias_gsu =
|
|
{ strgetfn, setpmdisralias, unsetpmalias };
|
|
static const struct gsu_scalar pmdisgalias_gsu =
|
|
{ strgetfn, setpmdisgalias, unsetpmalias };
|
|
static const struct gsu_scalar pmdissalias_gsu =
|
|
{ strgetfn, setpmdissalias, unsetpmsalias };
|
|
|
|
/**/
|
|
static void
|
|
assignaliasdefs(Param pm, int flags)
|
|
{
|
|
pm->node.flags = PM_SCALAR;
|
|
|
|
/* we really need to squirrel the flags away somewhere... */
|
|
switch (flags) {
|
|
case 0:
|
|
pm->gsu.s = &pmralias_gsu;
|
|
break;
|
|
|
|
case ALIAS_GLOBAL:
|
|
pm->gsu.s = &pmgalias_gsu;
|
|
break;
|
|
|
|
case ALIAS_SUFFIX:
|
|
pm->gsu.s = &pmsalias_gsu;
|
|
break;
|
|
|
|
case DISABLED:
|
|
pm->gsu.s = &pmdisralias_gsu;
|
|
break;
|
|
|
|
case ALIAS_GLOBAL|DISABLED:
|
|
pm->gsu.s = &pmdisgalias_gsu;
|
|
break;
|
|
|
|
case ALIAS_SUFFIX|DISABLED:
|
|
pm->gsu.s = &pmdissalias_gsu;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getalias(HashTable alht, UNUSED(HashTable ht), const char *name, int flags)
|
|
{
|
|
Param pm = NULL;
|
|
Alias al;
|
|
|
|
pm = (Param) hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
|
|
assignaliasdefs(pm, flags);
|
|
|
|
if ((al = (Alias) alht->getnode2(alht, name)) &&
|
|
flags == al->node.flags)
|
|
pm->u.str = dupstring(al->text);
|
|
else {
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
}
|
|
return &pm->node;
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmralias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(aliastab, ht, name, 0);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmdisralias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(aliastab, ht, name, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmgalias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(aliastab, ht, name, ALIAS_GLOBAL);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmdisgalias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmsalias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(sufaliastab, ht, name, ALIAS_SUFFIX);
|
|
}
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmdissalias(HashTable ht, const char *name)
|
|
{
|
|
return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanaliases(HashTable alht, UNUSED(HashTable ht), ScanFunc func,
|
|
int pmflags, int alflags)
|
|
{
|
|
struct param pm;
|
|
int i;
|
|
Alias al;
|
|
|
|
memset((void *)&pm, 0, sizeof(struct param));
|
|
assignaliasdefs(&pm, alflags);
|
|
|
|
for (i = 0; i < alht->hsize; i++)
|
|
for (al = (Alias) alht->nodes[i]; al; al = (Alias) al->node.next) {
|
|
if (alflags == al->node.flags) {
|
|
pm.node.nam = al->node.nam;
|
|
if (func != scancountparams &&
|
|
((pmflags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(pmflags & SCANPM_WANTKEYS)))
|
|
pm.u.str = dupstring(al->text);
|
|
func(&pm.node, pmflags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmraliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(aliastab, ht, func, flags, 0);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmdisraliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(aliastab, ht, func, flags, DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmgaliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmdisgaliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL|DISABLED);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmsaliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX);
|
|
}
|
|
|
|
/**/
|
|
static void
|
|
scanpmdissaliases(HashTable ht, ScanFunc func, int flags)
|
|
{
|
|
scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED);
|
|
}
|
|
|
|
|
|
/* Functions for the usergroups special parameter */
|
|
|
|
/*
|
|
* Get GID and names for groups of which the current user is a member.
|
|
*/
|
|
|
|
/**/
|
|
static Groupset get_all_groups(void)
|
|
{
|
|
Groupset gs = zhalloc(sizeof(*gs));
|
|
Groupmap gaptr;
|
|
gid_t *list, *lptr, egid;
|
|
int add_egid;
|
|
struct group *grptr;
|
|
|
|
egid = getegid();
|
|
add_egid = 1;
|
|
gs->num = getgroups(0, NULL);
|
|
if (gs->num > 0) {
|
|
list = zhalloc(gs->num * sizeof(*list));
|
|
if (getgroups(gs->num, list) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* It's unspecified whether $EGID is included in the
|
|
* group set, so check.
|
|
*/
|
|
for (lptr = list; lptr < list + gs->num; lptr++) {
|
|
if (*lptr == egid) {
|
|
add_egid = 0;
|
|
break;
|
|
}
|
|
}
|
|
gs->array = zhalloc((gs->num + add_egid) * sizeof(*gs->array));
|
|
/* Put EGID if needed first */
|
|
gaptr = gs->array + add_egid;
|
|
for (lptr = list; lptr < list + gs->num; lptr++) {
|
|
gaptr->gid = *lptr;
|
|
gaptr++;
|
|
}
|
|
gs->num += add_egid;
|
|
} else {
|
|
/* Just use effective GID */
|
|
gs->num = 1;
|
|
gs->array = zhalloc(sizeof(*gs->array));
|
|
}
|
|
if (add_egid) {
|
|
gs->array->gid = egid;
|
|
}
|
|
|
|
/* Get group names */
|
|
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
|
|
grptr = getgrgid(gaptr->gid);
|
|
if (!grptr) {
|
|
return NULL;
|
|
}
|
|
gaptr->name = dupstring(grptr->gr_name);
|
|
}
|
|
|
|
return gs;
|
|
}
|
|
|
|
/* Standard hash element lookup. */
|
|
|
|
/**/
|
|
static HashNode
|
|
getpmusergroups(UNUSED(HashTable ht), const char *name)
|
|
{
|
|
Param pm = NULL;
|
|
Groupset gs = get_all_groups();
|
|
Groupmap gaptr;
|
|
|
|
pm = (Param)hcalloc(sizeof(struct param));
|
|
pm->node.nam = dupstring(name);
|
|
pm->node.flags = PM_SCALAR | PM_READONLY;
|
|
pm->gsu.s = &nullsetscalar_gsu;
|
|
|
|
if (!gs) {
|
|
zerr("failed to retrieve groups for user: %e", errno);
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
return &pm->node;
|
|
}
|
|
|
|
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
|
|
if (!strcmp(name, gaptr->name)) {
|
|
char buf[DIGBUFSIZE];
|
|
|
|
sprintf(buf, "%d", (int)gaptr->gid);
|
|
pm->u.str = dupstring(buf);
|
|
return &pm->node;
|
|
}
|
|
}
|
|
|
|
pm->u.str = dupstring("");
|
|
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
|
|
return &pm->node;
|
|
}
|
|
|
|
/* Standard hash scan. */
|
|
|
|
/**/
|
|
static void
|
|
scanpmusergroups(UNUSED(HashTable ht), ScanFunc func, int flags)
|
|
{
|
|
struct param pm;
|
|
Groupset gs = get_all_groups();
|
|
Groupmap gaptr;
|
|
|
|
if (!gs) {
|
|
zerr("failed to retrieve groups for user: %e", errno);
|
|
return;
|
|
}
|
|
|
|
memset((void *)&pm, 0, sizeof(pm));
|
|
pm.node.flags = PM_SCALAR | PM_READONLY;
|
|
pm.gsu.s = &nullsetscalar_gsu;
|
|
|
|
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
|
|
pm.node.nam = gaptr->name;
|
|
if (func != scancountparams &&
|
|
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
|
|
!(flags & SCANPM_WANTKEYS))) {
|
|
char buf[DIGBUFSIZE];
|
|
|
|
sprintf(buf, "%d", (int)gaptr->gid);
|
|
pm.u.str = dupstring(buf);
|
|
}
|
|
func(&pm.node, flags);
|
|
}
|
|
}
|
|
|
|
|
|
/* Table for defined parameters. */
|
|
|
|
struct pardef {
|
|
char *name;
|
|
int flags;
|
|
GetNodeFunc getnfn;
|
|
ScanTabFunc scantfn;
|
|
GsuHash hash_gsu;
|
|
GsuArray array_gsu;
|
|
Param pm;
|
|
};
|
|
|
|
static const struct gsu_hash pmcommands_gsu =
|
|
{ hashgetfn, setpmcommands, stdunsetfn };
|
|
static const struct gsu_hash pmfunctions_gsu =
|
|
{ hashgetfn, setpmfunctions, stdunsetfn };
|
|
static const struct gsu_hash pmdisfunctions_gsu =
|
|
{ hashgetfn, setpmdisfunctions, stdunsetfn };
|
|
static const struct gsu_hash pmoptions_gsu =
|
|
{ hashgetfn, setpmoptions, stdunsetfn };
|
|
static const struct gsu_hash pmnameddirs_gsu =
|
|
{ hashgetfn, setpmnameddirs, stdunsetfn };
|
|
static const struct gsu_hash pmraliases_gsu =
|
|
{ hashgetfn, setpmraliases, stdunsetfn };
|
|
static const struct gsu_hash pmgaliases_gsu =
|
|
{ hashgetfn, setpmgaliases, stdunsetfn };
|
|
static const struct gsu_hash pmsaliases_gsu =
|
|
{ hashgetfn, setpmsaliases, stdunsetfn };
|
|
static const struct gsu_hash pmdisraliases_gsu =
|
|
{ hashgetfn, setpmdisraliases, stdunsetfn };
|
|
static const struct gsu_hash pmdisgaliases_gsu =
|
|
{ hashgetfn, setpmdisgaliases, stdunsetfn };
|
|
static const struct gsu_hash pmdissaliases_gsu =
|
|
{ hashgetfn, setpmdissaliases, stdunsetfn };
|
|
|
|
static const struct gsu_array funcstack_gsu =
|
|
{ funcstackgetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array functrace_gsu =
|
|
{ functracegetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array funcsourcetrace_gsu =
|
|
{ funcsourcetracegetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array funcfiletrace_gsu =
|
|
{ funcfiletracegetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array reswords_gsu =
|
|
{ reswordsgetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array disreswords_gsu =
|
|
{ disreswordsgetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array patchars_gsu =
|
|
{ patcharsgetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array dispatchars_gsu =
|
|
{ dispatcharsgetfn, arrsetfn, stdunsetfn };
|
|
static const struct gsu_array dirs_gsu =
|
|
{ dirsgetfn, dirssetfn, stdunsetfn };
|
|
static const struct gsu_array historywords_gsu =
|
|
{ histwgetfn, arrsetfn, stdunsetfn };
|
|
|
|
static struct paramdef partab[] = {
|
|
SPECIALPMDEF("aliases", 0,
|
|
&pmraliases_gsu, getpmralias, scanpmraliases),
|
|
SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins),
|
|
SPECIALPMDEF("commands", 0, &pmcommands_gsu, getpmcommand, scanpmcommands),
|
|
SPECIALPMDEF("dirstack", PM_ARRAY,
|
|
&dirs_gsu, NULL, NULL),
|
|
SPECIALPMDEF("dis_aliases", 0,
|
|
&pmdisraliases_gsu, getpmdisralias, scanpmdisraliases),
|
|
SPECIALPMDEF("dis_builtins", PM_READONLY,
|
|
NULL, getpmdisbuiltin, scanpmdisbuiltins),
|
|
SPECIALPMDEF("dis_functions", 0,
|
|
&pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
|
|
SPECIALPMDEF("dis_galiases", 0,
|
|
&pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
|
|
SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY,
|
|
&dispatchars_gsu, NULL, NULL),
|
|
SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY,
|
|
&disreswords_gsu, NULL, NULL),
|
|
SPECIALPMDEF("dis_saliases", 0,
|
|
&pmdissaliases_gsu, getpmdissalias, scanpmdissaliases),
|
|
SPECIALPMDEF("funcfiletrace", PM_ARRAY|PM_READONLY,
|
|
&funcfiletrace_gsu, NULL, NULL),
|
|
SPECIALPMDEF("funcsourcetrace", PM_ARRAY|PM_READONLY,
|
|
&funcsourcetrace_gsu, NULL, NULL),
|
|
SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY,
|
|
&funcstack_gsu, NULL, NULL),
|
|
SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
|
|
scanpmfunctions),
|
|
SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY,
|
|
&functrace_gsu, NULL, NULL),
|
|
SPECIALPMDEF("galiases", 0,
|
|
&pmgaliases_gsu, getpmgalias, scanpmgaliases),
|
|
SPECIALPMDEF("history", PM_READONLY,
|
|
NULL, getpmhistory, scanpmhistory),
|
|
SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY,
|
|
&historywords_gsu, NULL, NULL),
|
|
SPECIALPMDEF("jobdirs", PM_READONLY,
|
|
NULL, getpmjobdir, scanpmjobdirs),
|
|
SPECIALPMDEF("jobstates", PM_READONLY,
|
|
NULL, getpmjobstate, scanpmjobstates),
|
|
SPECIALPMDEF("jobtexts", PM_READONLY,
|
|
NULL, getpmjobtext, scanpmjobtexts),
|
|
SPECIALPMDEF("modules", PM_READONLY,
|
|
NULL, getpmmodule, scanpmmodules),
|
|
SPECIALPMDEF("nameddirs", 0,
|
|
&pmnameddirs_gsu, getpmnameddir, scanpmnameddirs),
|
|
SPECIALPMDEF("options", 0,
|
|
&pmoptions_gsu, getpmoption, scanpmoptions),
|
|
SPECIALPMDEF("parameters", PM_READONLY,
|
|
NULL, getpmparameter, scanpmparameters),
|
|
SPECIALPMDEF("patchars", PM_ARRAY|PM_READONLY,
|
|
&patchars_gsu, NULL, NULL),
|
|
SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY,
|
|
&reswords_gsu, NULL, NULL),
|
|
SPECIALPMDEF("saliases", 0,
|
|
&pmsaliases_gsu, getpmsalias, scanpmsaliases),
|
|
SPECIALPMDEF("userdirs", PM_READONLY,
|
|
NULL, getpmuserdir, scanpmuserdirs),
|
|
SPECIALPMDEF("usergroups", PM_READONLY,
|
|
NULL, getpmusergroups, scanpmusergroups)
|
|
};
|
|
|
|
static struct features module_features = {
|
|
NULL, 0,
|
|
NULL, 0,
|
|
NULL, 0,
|
|
partab, sizeof(partab)/sizeof(*partab),
|
|
0
|
|
};
|
|
|
|
/**/
|
|
int
|
|
setup_(UNUSED(Module m))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**/
|
|
int
|
|
features_(Module m, char ***features)
|
|
{
|
|
*features = featuresarray(m, &module_features);
|
|
return 0;
|
|
}
|
|
|
|
/**/
|
|
int
|
|
enables_(Module m, int **enables)
|
|
{
|
|
int ret;
|
|
/*
|
|
* If we remove features, we shouldn't have an effect
|
|
* on the main shell, so set the flag to indicate.
|
|
*/
|
|
incleanup = 1;
|
|
ret = handlefeatures(m, &module_features, enables);
|
|
incleanup = 0;
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
int
|
|
boot_(UNUSED(Module m))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**/
|
|
int
|
|
cleanup_(Module m)
|
|
{
|
|
int ret;
|
|
incleanup = 1;
|
|
ret = setfeatureenables(m, &module_features, NULL);
|
|
incleanup = 0;
|
|
return ret;
|
|
}
|
|
|
|
/**/
|
|
int
|
|
finish_(UNUSED(Module m))
|
|
{
|
|
return 0;
|
|
}
|