diff options
Diffstat (limited to 'Src/Modules')
-rw-r--r-- | Src/Modules/parameter.c | 1699 | ||||
-rw-r--r-- | Src/Modules/zpty.c | 153 |
2 files changed, 1615 insertions, 237 deletions
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 2257933f5..e8e387a59 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -30,6 +30,10 @@ #include "parameter.mdh" #include "parameter.pro" +/* This says if we are cleaning up when the module is unloaded. */ + +static int incleanup; + /* Empty dummy function for special hash parameters. */ /**/ @@ -47,14 +51,14 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan) Param pm; HashTable ht; - if (!(pm = createparam(name, PM_SPECIAL|PM_REMOVABLE|PM_HASHED))) + if (!(pm = createparam(name, PM_SPECIAL|PM_HIDE|PM_REMOVABLE|PM_HASHED))) return NULL; pm->level = pm->old ? locallevel : 0; pm->gets.hfn = hashgetfn; pm->sets.hfn = hashsetfn; pm->unsetfn = stdunsetfn; - pm->u.hash = ht = newhashtable(7, name, NULL); + pm->u.hash = ht = newhashtable(0, name, NULL); ht->hash = hasher; ht->emptytable = (TableFunc) shempty; @@ -83,14 +87,21 @@ paramtypestr(Param pm) int f = pm->flags; if (!(f & PM_UNSET)) { + if (pm->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) @@ -109,6 +120,10 @@ paramtypestr(Param pm) val = dyncat(val, "-export"); if (f & PM_UNIQUE) val = dyncat(val, "-unique"); + if (f & PM_HIDE) + val = dyncat(val, "-hide"); + if (f & PM_SPECIAL) + val = dyncat(val, "-special"); } else val = dupstring(""); @@ -121,27 +136,24 @@ getpmparameter(HashTable ht, char *name) { Param rpm, pm = NULL; - HEAPALLOC { - pm = (Param) zhalloc(sizeof(struct param)); - pm->nam = dupstring(name); - pm->flags = PM_SCALAR | PM_READONLY; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; - if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) && - !(rpm->flags & PM_UNSET)) - pm->u.str = paramtypestr(rpm); - else { - pm->u.str = ""; - pm->flags |= PM_UNSET; - } - } LASTALLOC; - + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) && + !(rpm->flags & PM_UNSET)) + pm->u.str = paramtypestr(rpm); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } return (HashNode) pm; } @@ -166,7 +178,9 @@ scanpmparameters(HashTable ht, ScanFunc func, int flags) for (i = 0; i < realparamtab->hsize; i++) for (hn = realparamtab->nodes[i]; hn; hn = hn->next) { pm.nam = hn->nam; - if (func != scancountparams) + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) pm.u.str = paramtypestr((Param) hn); func((HashNode) &pm, flags); } @@ -179,12 +193,12 @@ static void setpmcommand(Param pm, char *value) { if (isset(RESTRICTED)) - zwarnnam(NULL, "restricted: %s", value, 0); + zwarn("restricted: %s", value, 0); else { Cmdnam cn = zcalloc(sizeof(*cn)); cn->flags = HASHED; - cn->u.cmd = ztrdup(value); + cn->u.cmd = value; cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn); } @@ -207,6 +221,9 @@ setpmcommands(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 = zcalloc(sizeof(*cn)); @@ -222,6 +239,7 @@ setpmcommands(Param pm, HashTable ht) cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), (HashNode) cn); } + deleteparamtable(ht); } /**/ @@ -236,34 +254,30 @@ getpmcommand(HashTable ht, char *name) cmdnamtab->filltable(cmdnamtab); cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name); } - HEAPALLOC { - pm = (Param) zhalloc(sizeof(struct param)); - pm->nam = dupstring(name); - pm->flags = PM_SCALAR; - pm->sets.cfn = setpmcommand; - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmcommand; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; - if (cmd) { - if (cmd->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 = ""; - pm->flags |= PM_UNSET; + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmcommand; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmcommand; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if (cmd) { + if (cmd->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); } - } LASTALLOC; - + } else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } return (HashNode) pm; } @@ -293,7 +307,9 @@ scanpmcommands(HashTable ht, ScanFunc func, int flags) for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) { pm.nam = hn->nam; cmd = (Cmdnam) hn; - if (func != scancountparams) { + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) { if (cmd->flags & HASHED) pm.u.str = cmd->u.cmd; else { @@ -312,43 +328,37 @@ scanpmcommands(HashTable ht, ScanFunc func, int flags) /**/ static void -setfunction(char *name, char *value) +setfunction(char *name, char *val, int dis) { - char *val; + char *value = dupstring(val); Shfunc shf; - List list; + Eprog prog; int sn; - val = ztrdup(value); val = metafy(val, strlen(val), META_REALLOC); - HEAPALLOC { - list = parse_string(val); - } LASTALLOC; + prog = parse_string(val, 1); - if (!list || list == &dummy_list) { - zwarnnam(NULL, "invalid function definition", val, 0); + if (!prog || prog == &dummy_eprog) { + zwarn("invalid function definition", value, 0); zsfree(val); return; } - PERMALLOC { - shf = (Shfunc) zalloc(sizeof(*shf)); - shf->funcdef = (List) dupstruct(list); - shf->flags = 0; - - if (!strncmp(name, "TRAP", 4) && - (sn = getsignum(name + 4)) != -1) { - if (settrap(sn, shf->funcdef)) { - freestruct(shf->funcdef); - zfree(shf, sizeof(*shf)); - zsfree(val); - LASTALLOC_RETURN; - } - sigtrapped[sn] |= ZSIG_FUNC; + shf = (Shfunc) zalloc(sizeof(*shf)); + shf->funcdef = dupeprog(prog, 0); + shf->flags = dis; + + if (!strncmp(name, "TRAP", 4) && + (sn = getsignum(name + 4)) != -1) { + if (settrap(sn, shf->funcdef)) { + freeeprog(shf->funcdef); + zfree(shf, sizeof(*shf)); + zsfree(val); + return; } - shfunctab->addnode(shfunctab, ztrdup(name), shf); - } LASTALLOC; - + sigtrapped[sn] |= ZSIG_FUNC; + } + shfunctab->addnode(shfunctab, ztrdup(name), shf); zsfree(val); } @@ -356,7 +366,14 @@ setfunction(char *name, char *value) static void setpmfunction(Param pm, char *value) { - setfunction(pm->nam, value); + setfunction(pm->nam, value, 0); +} + +/**/ +static void +setpmdisfunction(Param pm, char *value) +{ + setfunction(pm->nam, value, DISABLED); } /**/ @@ -371,11 +388,14 @@ unsetpmfunction(Param pm, int exp) /**/ static void -setpmfunctions(Param pm, HashTable ht) +setfunctions(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; @@ -385,62 +405,100 @@ setpmfunctions(Param pm, HashTable ht) v.arr = NULL; v.pm = (Param) hn; - setfunction(hn->nam, getstrvalue(&v)); + 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 HashNode -getpmfunction(HashTable ht, char *name) +getfunction(HashTable ht, char *name, int dis) { Shfunc shf; Param pm = NULL; - HEAPALLOC { - pm = (Param) zhalloc(sizeof(struct param)); - pm->nam = dupstring(name); - pm->flags = PM_SCALAR; - pm->sets.cfn = setpmfunction; - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmfunction; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; - - if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) { - if (shf->flags & PM_UNDEFINED) - pm->u.str = "undefined"; - else { - char *t = getpermtext((void *) dupstruct((void *) - shf->funcdef)), *h; - - h = dupstring(t); - zsfree(t); - unmetafy(h, NULL); - - pm->u.str = h; - } + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = (dis ? setpmdisfunction : setpmfunction); + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmfunction; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) && + (dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) { + if (shf->flags & PM_UNDEFINED) { + pm->u.str = dyncat("builtin autoload -X", + ((shf->flags & PM_UNALIASED) ? + ((shf->flags & PM_TAGGED) ? "Ut" : "U") : + ((shf->flags & PM_TAGGED) ? "t" : ""))); } else { - pm->u.str = ""; - pm->flags |= PM_UNSET; + char *t = getpermtext(shf->funcdef, NULL), *n, *h; + + if (shf->funcdef->flags & EF_RUN) { + n = nicedupstring(name); + h = (char *) zhalloc(strlen(t) + strlen(n) + 9); + h[0] = '\t'; + strcpy(h + 1, t); + strcat(h, "\n\t"); + strcat(h, n); + strcat(h, " \"$@\""); + } else + h = dyncat("\t", t); + zsfree(t); + unmetafy(h, NULL); + + pm->u.str = h; } - } LASTALLOC; - + } else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } return (HashNode) pm; } /**/ +static HashNode +getpmfunction(HashTable ht, char *name) +{ + return getfunction(ht, name, 0); +} + +/**/ +static HashNode +getpmdisfunction(HashTable ht, char *name) +{ + return getfunction(ht, name, DISABLED); +} + +/**/ static void -scanpmfunctions(HashTable ht, ScanFunc func, int flags) +scanfunctions(HashTable ht, ScanFunc func, int flags, int dis) { struct param pm; int i; HashNode hn; pm.flags = PM_SCALAR; - pm.sets.cfn = setpmcommand; + pm.sets.cfn = (dis ? setpmdisfunction : setpmfunction); pm.gets.cfn = strgetfn; pm.unsetfn = unsetpmcommand; pm.ct = 0; @@ -451,16 +509,32 @@ scanpmfunctions(HashTable ht, ScanFunc func, int flags) for (i = 0; i < shfunctab->hsize; i++) for (hn = shfunctab->nodes[i]; hn; hn = hn->next) { - if (!(hn->flags & DISABLED)) { + if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) { pm.nam = hn->nam; - if (func != scancountparams) { - if (((Shfunc) hn)->flags & PM_UNDEFINED) - pm.u.str = "undefined"; - else { - char *t = getpermtext((void *) - dupstruct((void *) ((Shfunc) hn)->funcdef)); - - unmetafy((pm.u.str = dupstring(t)), NULL); + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) { + if (((Shfunc) hn)->flags & PM_UNDEFINED) { + Shfunc shf = (Shfunc) hn; + pm.u.str = + dyncat("builtin autoload -X", + ((shf->flags & PM_UNALIASED) ? + ((shf->flags & PM_TAGGED) ? "Ut" : "U") : + ((shf->flags & PM_TAGGED) ? "t" : ""))); + } else { + char *t = getpermtext(((Shfunc) hn)->funcdef, NULL), *n; + + if (((Shfunc) hn)->funcdef->flags & EF_RUN) { + n = nicedupstring(hn->nam); + pm.u.str = (char *) zhalloc(strlen(t) + strlen(n) + 9); + pm.u.str[0] = '\t'; + strcpy(pm.u.str + 1, t); + strcat(pm.u.str, "\n\t"); + strcat(pm.u.str, n); + strcat(pm.u.str, " \"$@\""); + } else + pm.u.str = dyncat("\t", t); + unmetafy(pm.u.str, NULL); zsfree(t); } } @@ -469,6 +543,173 @@ scanpmfunctions(HashTable ht, ScanFunc func, int 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(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 builtins special parameter. */ + +/**/ +static HashNode +getbuiltin(HashTable ht, char *name, int dis) +{ + Param pm = NULL; + Builtin bn; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) && + (dis ? (bn->flags & DISABLED) : !(bn->flags & DISABLED))) { + char *t = ((bn->handlerfunc || (bn->flags & BINF_PREFIX)) ? + "defined" : "undefined"); + + pm->u.str = dupstring(t); + } else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static HashNode +getpmbuiltin(HashTable ht, char *name) +{ + return getbuiltin(ht, name, 0); +} + +/**/ +static HashNode +getpmdisbuiltin(HashTable ht, char *name) +{ + return getbuiltin(ht, name, DISABLED); +} + +/**/ +static void +scanbuiltins(HashTable ht, ScanFunc func, int flags, int dis) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + 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.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((HashNode) &pm, 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(Param pm) +{ + return getreswords(0); +} + +/**/ +static char ** +disreswordsgetfn(Param pm) +{ + return getreswords(DISABLED); +} + /* Functions for the options special parameter. */ /**/ @@ -478,11 +719,12 @@ setpmoption(Param pm, char *value) int n; if (!value || (strcmp(value, "on") && strcmp(value, "off"))) - zwarnnam(NULL, "invalid value: %s", value, 0); + zwarn("invalid value: %s", value, 0); else if (!(n = optlookup(pm->nam))) - zwarnnam(NULL, "no such option: %s", pm->nam, 0); + zwarn("no such option: %s", pm->nam, 0); else if (dosetopt(n, (value && strcmp(value, "off")), 0)) - zwarnnam(NULL, "can't change option: %s", pm->nam, 0); + zwarn("can't change option: %s", pm->nam, 0); + zsfree(value); } /**/ @@ -492,9 +734,9 @@ unsetpmoption(Param pm, int exp) int n; if (!(n = optlookup(pm->nam))) - zwarnnam(NULL, "no such option: %s", pm->nam, 0); + zwarn("no such option: %s", pm->nam, 0); else if (dosetopt(n, 0, 0)) - zwarnnam(NULL, "can't change option: %s", pm->nam, 0); + zwarn("can't change option: %s", pm->nam, 0); } /**/ @@ -504,6 +746,9 @@ setpmoptions(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; @@ -516,11 +761,12 @@ setpmoptions(Param pm, HashTable ht) val = getstrvalue(&v); if (!val || (strcmp(val, "on") && strcmp(val, "off"))) - zwarnnam(NULL, "invalid value: %s", val, 0); + zwarn("invalid value: %s", val, 0); else if (dosetopt(optlookup(hn->nam), (val && strcmp(val, "off")), 0)) - zwarnnam(NULL, "can't change option: %s", hn->nam, 0); + zwarn("can't change option: %s", hn->nam, 0); } + deleteparamtable(ht); } /**/ @@ -530,27 +776,24 @@ getpmoption(HashTable ht, char *name) Param pm = NULL; int n; - HEAPALLOC { - pm = (Param) zhalloc(sizeof(struct param)); - pm->nam = dupstring(name); - pm->flags = PM_SCALAR; - pm->sets.cfn = setpmoption; - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmoption; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; - - if ((n = optlookup(name))) - pm->u.str = dupstring(opts[n] ? "on" : "off"); - else { - pm->u.str = ""; - pm->flags |= PM_UNSET; - } - } LASTALLOC; - + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmoption; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmoption; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((n = optlookup(name))) + pm->u.str = dupstring(opts[n] ? "on" : "off"); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } return (HashNode) pm; } @@ -574,89 +817,1147 @@ scanpmoptions(HashTable ht, ScanFunc func, int flags) for (i = 0; i < optiontab->hsize; i++) for (hn = optiontab->nodes[i]; hn; hn = hn->next) { + int optno = ((Optname) hn)->optno, ison; pm.nam = hn->nam; - pm.u.str = opts[((Optname) hn)->optno] ? "on" : "off"; + ison = optno < 0 ? !opts[-optno] : opts[optno]; + pm.u.str = dupstring(ison ? "on" : "off"); func((HashNode) &pm, flags); } } -/* Names and Params for the special parameters. */ +/* Functions for the modules special parameter. */ -#define PAR_NAM "parameters" -#define CMD_NAM "commands" -#define FUN_NAM "functions" -#define OPT_NAM "options" +static char *modpmname; +static int modpmfound; -static Param parpm, cmdpm, funpm, optpm; +/**/ +static void +modpmbuiltinscan(HashNode hn, int dummy) +{ + if (!(((Builtin) hn)->flags & BINF_ADDED) && + !strcmp(((Builtin) hn)->optstr, modpmname)) + modpmfound = 1; +} + +/**/ +static void +modpmparamscan(HashNode hn, int dummy) +{ + if ((((Param) hn)->flags & PM_AUTOLOAD) && + !strcmp(((Param) hn)->u.str, modpmname)) + modpmfound = 1; +} + +/**/ +static int +findmodnode(LinkList l, char *nam) +{ + LinkNode node; + + for (node = firstnode(l); node; incnode(node)) + if (!strcmp(nam, (char *) getdata(node))) + return 1; + + return 0; +} + +/**/ +static HashNode +getpmmodule(HashTable ht, char *name) +{ + Param pm = NULL; + char *type = NULL; + LinkNode node; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if (!type) { + Module m; + + for (node = firstnode(modules); node; incnode(node)) { + m = (Module) getdata(node); + if (m->u.handle && !(m->flags & MOD_UNLOAD) && + !strcmp(name, m->nam)) { + type = "loaded"; + break; + } + } + } + modpmname = name; + modpmfound = 0; + if (!type) { + scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0); + if (!modpmfound) { + Conddef p; + + for (p = condtab; p; p = p->next) + if (p->module && !strcmp(name, p->module)) { + modpmfound = 1; + break; + } + if (!modpmfound) + scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0); + } + if (modpmfound) + type = "autoloaded"; + } + if (type) + pm->u.str = dupstring(type); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmmodules(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + LinkList done = newlinklist(); + LinkNode node; + Module m; + Conddef p; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + pm.u.str = dupstring("builtin"); + pm.u.str = dupstring("loaded"); + for (node = firstnode(modules); node; incnode(node)) { + m = (Module) getdata(node); + if (m->u.handle && !(m->flags & MOD_UNLOAD)) { + pm.nam = m->nam; + addlinknode(done, pm.nam); + func((HashNode) &pm, 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)->flags & BINF_ADDED) && + !findmodnode(done, ((Builtin) hn)->optstr)) { + pm.nam = ((Builtin) hn)->optstr; + addlinknode(done, pm.nam); + func((HashNode) &pm, flags); + } + } + for (p = condtab; p; p = p->next) + if (p->module && !findmodnode(done, p->module)) { + pm.nam = p->module; + addlinknode(done, pm.nam); + func((HashNode) &pm, flags); + } + for (i = 0; i < realparamtab->hsize; i++) + for (hn = realparamtab->nodes[i]; hn; hn = hn->next) { + if ((((Param) hn)->flags & PM_AUTOLOAD) && + !findmodnode(done, ((Param) hn)->u.str)) { + pm.nam = ((Param) hn)->u.str; + addlinknode(done, pm.nam); + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the dirstack special parameter. */ + +/**/ +static void +dirssetfn(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(Param pm) +{ + int l = countlinknodes(dirstack); + char **ret = (char **) zhalloc((l + 1) * sizeof(char *)), **p; + LinkNode n; + + for (n = firstnode(dirstack), p = ret; n; incnode(n), p++) + *p = dupstring((char *) getdata(n)); + *p = NULL; + + return ret; +} + +/* Functions for the history special parameter. */ + +/**/ +static HashNode +getpmhistory(HashTable ht, char *name) +{ + Param pm = NULL; + Histent he; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((he = quietgethist(atoi(name)))) + pm->u.str = dupstring(he->text); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmhistory(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i = addhistnum(curhist, -1, HIST_FOREIGN); + Histent he = quietgethistent(i, GETHIST_UPWARD); + char buf[40]; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + while (he) { + if (func != scancountparams) { + sprintf(buf, "%d", he->histnum); + pm.nam = dupstring(buf); + if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS)) + pm.u.str = dupstring(he->text); + } + func((HashNode) &pm, flags); + + he = up_histent(he); + } +} + +/* Function for the historywords special parameter. */ + +/**/ +static char ** +histwgetfn(Param pm) +{ + char **ret, **p, *h, *e, sav; + LinkList l = newlinklist(); + LinkNode n; + int i = addhistnum(curhist, -1, HIST_FOREIGN), iw; + Histent he = quietgethistent(i, GETHIST_UPWARD); + + while (he) { + for (iw = he->nwords - 1; iw >= 0; iw--) { + h = he->text + he->words[iw * 2]; + e = he->text + he->words[iw * 2 + 1]; + sav = *e; + *e = '\0'; + addlinknode(l, dupstring(h)); + *e = sav; + } + he = up_histent(he); + } + ret = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char *)); + + for (p = ret, n = firstnode(l); n; incnode(n), p++) + *p = (char *) getdata(n); + *p = NULL; + + return ret; +} + +/* 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(HashTable ht, char *name) +{ + Param pm = NULL; + int job; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((job = atoi(name)) >= 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->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmjobtexts(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int job; + char buf[40]; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + 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.nam = dupstring(buf); + if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS)) + pm.u.str = pmjobtext(job); + } + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the jobstates special parameter. */ + +/**/ +static char * +pmjobstate(int job) +{ + Process pn; + char buf[256], buf2[128], *ret, *state; + + if (jobtab[job].stat & STAT_DONE) + ret = dupstring("done"); + else if (jobtab[job].stat & STAT_STOPPED) + ret = dupstring("suspended"); + else + ret = dupstring("running"); + + 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", pn->pid, state); + + ret = dyncat(ret, buf); + } + return ret; +} + +/**/ +static HashNode +getpmjobstate(HashTable ht, char *name) +{ + Param pm = NULL; + int job; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((job = atoi(name)) >= 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->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmjobstates(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int job; + char buf[40]; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + 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.nam = dupstring(buf); + if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS)) + pm.u.str = pmjobstate(job); + } + func((HashNode) &pm, 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(HashTable ht, char *name) +{ + Param pm = NULL; + int job; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((job = atoi(name)) >= 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->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmjobdirs(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int job; + char buf[40]; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + 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.nam = dupstring(buf); + if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS)) + pm.u.str = pmjobdir(job); + } + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the nameddirs special parameter. */ + +/**/ +static void +setpmnameddir(Param pm, char *value) +{ + if (!value || *value != '/' || strlen(value) >= PATH_MAX) + zwarn("invalid value: %s", value, 0); + else + adduserdir(pm->nam, value, 0, 1); + zsfree(value); +} + +/**/ +static void +unsetpmnameddir(Param pm, int exp) +{ + HashNode hd = nameddirtab->removenode(nameddirtab, pm->nam); + + if (hd) + nameddirtab->freenode(hd); +} + +/**/ +static void +setpmnameddirs(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)->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.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + if (!(val = getstrvalue(&v)) || *val != '/' || + strlen(val) >= PATH_MAX) + zwarn("invalid value: %s", val, 0); + else + adduserdir(hn->nam, val, 0, 1); + } + + /* 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 HashNode +getpmnameddir(HashTable ht, char *name) +{ + Param pm = NULL; + Nameddir nd; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmnameddir; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmnameddir; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) && + !(nd->flags & ND_USERNAME)) + pm->u.str = dupstring(nd->dir); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmnameddirs(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + Nameddir nd; + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmnameddir; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmnameddir; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < nameddirtab->hsize; i++) + for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) { + if (!((nd = (Nameddir) hn)->flags & ND_USERNAME)) { + pm.nam = hn->nam; + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) + pm.u.str = dupstring(nd->dir); + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the userdirs special parameter. */ + +/**/ +static HashNode +getpmuserdir(HashTable ht, char *name) +{ + Param pm = NULL; + Nameddir nd; + + nameddirtab->filltable(nameddirtab); + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) && + (nd->flags & ND_USERNAME)) + pm->u.str = dupstring(nd->dir); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static void +scanpmuserdirs(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + Nameddir nd; + + nameddirtab->filltable(nameddirtab); + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < nameddirtab->hsize; i++) + for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) { + if ((nd = (Nameddir) hn)->flags & ND_USERNAME) { + pm.nam = hn->nam; + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) + pm.u.str = dupstring(nd->dir); + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the regularaliases and globalaliases special parameters. */ + +/**/ +static void +setralias(Param pm, char *value, int dis) +{ + aliastab->addnode(aliastab, ztrdup(pm->nam), createaliasnode(value, dis)); +} + +/**/ +static void +setpmralias(Param pm, char *value) +{ + setralias(pm, value, 0); +} + +/**/ +static void +setpmdisralias(Param pm, char *value) +{ + setralias(pm, value, DISABLED); +} + +/**/ +static void +setgalias(Param pm, char *value, int dis) +{ + aliastab->addnode(aliastab, ztrdup(pm->nam), + createaliasnode(value, dis | ALIAS_GLOBAL)); +} + +/**/ +static void +setpmgalias(Param pm, char *value) +{ + setgalias(pm, value, 0); +} + +/**/ +static void +setpmdisgalias(Param pm, char *value) +{ + setgalias(pm, value, DISABLED); +} + +/**/ +static void +unsetpmalias(Param pm, int exp) +{ + HashNode hd = aliastab->removenode(aliastab, pm->nam); + + if (hd) + aliastab->freenode(hd); +} + +/**/ +static void +setaliases(Param pm, HashTable ht, int global, int dis) +{ + int i; + HashNode hn, next, hd; + + if (!ht) + return; + + for (i = 0; i < aliastab->hsize; i++) + for (hn = aliastab->nodes[i]; hn; hn = next) { + next = hn->next; + if (((global && (((Alias) hn)->flags & ALIAS_GLOBAL)) || + (!global && !(((Alias) hn)->flags & ALIAS_GLOBAL))) && + (hd = aliastab->removenode(aliastab, hn->nam))) + aliastab->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.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + if ((val = getstrvalue(&v))) + aliastab->addnode(aliastab, ztrdup(hn->nam), + createaliasnode(ztrdup(val), + (global ? ALIAS_GLOBAL : 0) | + (dis ? DISABLED : 0))); + } + deleteparamtable(ht); +} + +/**/ +static void +setpmraliases(Param pm, HashTable ht) +{ + setaliases(pm, ht, 0, 0); +} + +/**/ +static void +setpmdisraliases(Param pm, HashTable ht) +{ + setaliases(pm, ht, 0, DISABLED); +} + +/**/ +static void +setpmgaliases(Param pm, HashTable ht) +{ + setaliases(pm, ht, 1, 0); +} + +/**/ +static void +setpmdisgaliases(Param pm, HashTable ht) +{ + setaliases(pm, ht, 1, DISABLED); +} + +/**/ +static HashNode +getalias(HashTable ht, char *name, int global, int dis) +{ + Param pm = NULL; + Alias al; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) : + (dis ? setpmdisralias : setpmralias)); + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmalias; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((al = (Alias) aliastab->getnode2(aliastab, name)) && + ((global && (al->flags & ALIAS_GLOBAL)) || + (!global && !(al->flags & ALIAS_GLOBAL))) && + (dis ? (al->flags & DISABLED) : !(al->flags & DISABLED))) + pm->u.str = dupstring(al->text); + else { + pm->u.str = dupstring(""); + pm->flags |= PM_UNSET; + } + return (HashNode) pm; +} + +/**/ +static HashNode +getpmralias(HashTable ht, char *name) +{ + return getalias(ht, name, 0, 0); +} + +/**/ +static HashNode +getpmdisralias(HashTable ht, char *name) +{ + return getalias(ht, name, 0, 0); +} + +/**/ +static HashNode +getpmgalias(HashTable ht, char *name) +{ + return getalias(ht, name, 1, 0); +} + +/**/ +static HashNode +getpmdisgalias(HashTable ht, char *name) +{ + return getalias(ht, name, 1, DISABLED); +} + +/**/ +static void +scanaliases(HashTable ht, ScanFunc func, int flags, int global, int dis) +{ + struct param pm; + int i; + HashNode hn; + Alias al; + + pm.flags = PM_SCALAR; + pm.sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) : + (dis ? setpmdisralias : setpmralias)); + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmalias; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < aliastab->hsize; i++) + for (hn = aliastab->nodes[i]; hn; hn = hn->next) { + if (((global && ((al = (Alias) hn)->flags & ALIAS_GLOBAL)) || + (!global && !((al = (Alias) hn)->flags & ALIAS_GLOBAL))) && + (dis ? (al->flags & DISABLED) : !(al->flags & DISABLED))) { + pm.nam = hn->nam; + if (func != scancountparams && + ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(flags & SCANPM_WANTKEYS))) + pm.u.str = dupstring(al->text); + func((HashNode) &pm, flags); + } + } +} + +/**/ +static void +scanpmraliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(ht, func, flags, 0, 0); +} + +/**/ +static void +scanpmdisraliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(ht, func, flags, 0, DISABLED); +} + +/**/ +static void +scanpmgaliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(ht, func, flags, 1, 0); +} + +/**/ +static void +scanpmdisgaliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(ht, func, flags, 1, DISABLED); +} + +/* Table for defined parameters. */ + +struct pardef { + char *name; + int flags; + GetNodeFunc getnfn; + ScanTabFunc scantfn; + void (*hsetfn) _((Param, HashTable)); + void (*setfn) _((Param, char **)); + char **(*getfn) _((Param)); + void (*unsetfn) _((Param, int)); + Param pm; +}; + +static struct pardef partab[] = { + { "parameters", PM_READONLY, + getpmparameter, scanpmparameters, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "commands", 0, + getpmcommand, scanpmcommands, setpmcommands, + NULL, NULL, stdunsetfn, NULL }, + { "functions", 0, + getpmfunction, scanpmfunctions, setpmfunctions, + NULL, NULL, stdunsetfn, NULL }, + { "dis_functions", 0, + getpmdisfunction, scanpmdisfunctions, setpmdisfunctions, + NULL, NULL, stdunsetfn, NULL }, + { "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY, + NULL, NULL, NULL, + arrsetfn, funcstackgetfn, stdunsetfn, NULL }, + { "builtins", PM_READONLY, + getpmbuiltin, scanpmbuiltins, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "dis_builtins", PM_READONLY, + getpmdisbuiltin, scanpmdisbuiltins, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY, + NULL, NULL, NULL, + arrsetfn, reswordsgetfn, stdunsetfn, NULL }, + { "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY, + NULL, NULL, NULL, + arrsetfn, disreswordsgetfn, stdunsetfn, NULL }, + { "options", 0, + getpmoption, scanpmoptions, setpmoptions, + NULL, NULL, stdunsetfn, NULL }, + { "modules", PM_READONLY, + getpmmodule, scanpmmodules, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE, + NULL, NULL, NULL, + dirssetfn, dirsgetfn, stdunsetfn, NULL }, + { "history", PM_READONLY, + getpmhistory, scanpmhistory, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY, + NULL, NULL, NULL, + arrsetfn, histwgetfn, stdunsetfn, NULL }, + { "jobtexts", PM_READONLY, + getpmjobtext, scanpmjobtexts, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "jobstates", PM_READONLY, + getpmjobstate, scanpmjobstates, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "jobdirs", PM_READONLY, + getpmjobdir, scanpmjobdirs, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "nameddirs", 0, + getpmnameddir, scanpmnameddirs, setpmnameddirs, + NULL, NULL, stdunsetfn, NULL }, + { "userdirs", PM_READONLY, + getpmuserdir, scanpmuserdirs, hashsetfn, + NULL, NULL, stdunsetfn, NULL }, + { "aliases", 0, + getpmralias, scanpmraliases, setpmraliases, + NULL, NULL, stdunsetfn, NULL }, + { "galiases", 0, + getpmgalias, scanpmgaliases, setpmgaliases, + NULL, NULL, stdunsetfn, NULL }, + { "dis_aliases", 0, + getpmdisralias, scanpmdisraliases, setpmdisraliases, + NULL, NULL, stdunsetfn, NULL }, + { "dis_galiases", 0, + getpmdisgalias, scanpmdisgaliases, setpmdisgaliases, + NULL, NULL, stdunsetfn, NULL }, + { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; /**/ int -setup_parameter(Module m) +setup_(Module m) { + incleanup = 0; + return 0; } /**/ int -boot_parameter(Module m) +boot_(Module m) { /* Create the special associative arrays. * As an example for autoloaded parameters, this is probably a bad - * example, because we the zsh core doesn't support creation of + * example, because the zsh core doesn't support creation of * special hashes, yet. */ - unsetparam(PAR_NAM); - if (!(parpm = createspecialhash(PAR_NAM, getpmparameter, - scanpmparameters))) - return 1; - parpm->flags |= PM_READONLY; - unsetparam(CMD_NAM); - if (!(cmdpm = createspecialhash(CMD_NAM, getpmcommand, - scanpmcommands))) - return 1; - cmdpm->sets.hfn = setpmcommands; - unsetparam(FUN_NAM); - if (!(funpm = createspecialhash(FUN_NAM, getpmfunction, - scanpmfunctions))) - return 1; - funpm->sets.hfn = setpmfunctions; - unsetparam(OPT_NAM); - if (!(optpm = createspecialhash(OPT_NAM, getpmoption, - scanpmoptions))) - return 1; - optpm->sets.hfn = setpmoptions; + struct pardef *def; + for (def = partab; def->name; def++) { + unsetparam(def->name); + + if (def->getnfn) { + if (!(def->pm = createspecialhash(def->name, def->getnfn, + def->scantfn))) + return 1; + def->pm->flags |= def->flags; + if (def->hsetfn) + def->pm->sets.hfn = def->hsetfn; + } else { + if (!(def->pm = createparam(def->name, def->flags | PM_HIDE | + PM_REMOVABLE))) + return 1; + def->pm->sets.afn = def->setfn; + def->pm->gets.afn = def->getfn; + def->pm->unsetfn = def->unsetfn; + } + } return 0; } -#ifdef MODULE - /**/ int -cleanup_parameter(Module m) +cleanup_(Module m) { Param pm; + struct pardef *def; - /* Remove the special parameters if they are still the same. */ + incleanup = 1; - if ((pm = (Param) paramtab->getnode(paramtab, PAR_NAM)) && pm == parpm) { - pm->flags &= ~PM_READONLY; - unsetparam_pm(pm, 0, 1); + for (def = partab; def->name; def++) { + if ((pm = (Param) paramtab->getnode(paramtab, def->name)) && + pm == def->pm) { + pm->flags &= ~PM_READONLY; + unsetparam_pm(pm, 0, 1); + } } - if ((pm = (Param) paramtab->getnode(paramtab, CMD_NAM)) && pm == cmdpm) - unsetparam_pm(pm, 0, 1); - if ((pm = (Param) paramtab->getnode(paramtab, FUN_NAM)) && pm == funpm) - unsetparam_pm(pm, 0, 1); - if ((pm = (Param) paramtab->getnode(paramtab, OPT_NAM)) && pm == optpm) - unsetparam_pm(pm, 0, 1); return 0; } /**/ int -finish_parameter(Module m) +finish_(Module m) { return 0; } - -#endif diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index 088979514..26896525c 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -30,6 +30,13 @@ #include "zpty.mdh" #include "zpty.pro" +/* The number of bytes we normally read when given no pattern and the + * upper bound on the number of bytes we read (even if we are give a + * pattern). */ + +#define READ_LEN 1024 +#define READ_MAX (1024 * 1024) + typedef struct ptycmd *Ptycmd; struct ptycmd { @@ -158,7 +165,7 @@ get_pty(int *master, int *slave) #else /* ! __osf__ */ -#if __SVR4 +#if defined(__SVR4) || defined(sinix) #include <sys/stropts.h> @@ -167,11 +174,12 @@ get_pty(int *master, int *slave) { int mfd, sfd; char *name; + int ret; if ((mfd = open("/dev/ptmx", O_RDWR)) < 0) return 1; - if (!(name = ptsname(mfd)) || grantpt(mfd) || unlockpt(mfd)) { + if (grantpt(mfd) || unlockpt(mfd) || !(name = ptsname(mfd))) { close(mfd); return 1; } @@ -179,20 +187,31 @@ get_pty(int *master, int *slave) close(mfd); return 1; } - if (ioctl(sfd, I_PUSH, "ptem") || - ioctl(sfd, I_PUSH, "ldterm") || - ioctl(sfd, I_PUSH, "ttcompat")) { - close(mfd); - close(sfd); - return 1; - } + if ((ret = ioctl(sfd, I_FIND, "ptem")) != 1) + if (ret == -1 || ioctl(sfd, I_PUSH, "ptem") == -1) { + close(mfd); + close(sfd); + return 1; + } + if ((ret = ioctl(sfd, I_FIND, "ldterm")) != 1) + if (ret == -1 || ioctl(sfd, I_PUSH, "ldterm") == -1) { + close(mfd); + close(sfd); + return 1; + } + if ((ret = ioctl(sfd, I_FIND, "ttcompat")) != 1) + if (ret == -1 || ioctl(sfd, I_PUSH, "ttcompat") == -1) { + close(mfd); + close(sfd); + return 1; + } *master = mfd; *slave = sfd; return 0; } -#else /* ! __SVR4 */ +#else /* ! (defined(__SVR4) || defind(sinix)) */ static int get_pty(int *master, int *slave) @@ -242,17 +261,17 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block) char *cmd; if (!(cmd = findcmd(*args, 1))) { - zerrnam(nam, "unknown command: %s", *args, 0); + zwarnnam(nam, "unknown command: %s", *args, 0); return 1; } if (get_pty(&master, &slave)) { - zerrnam(nam, "can't open pseudo terminal", NULL, 0); + zwarnnam(nam, "can't open pseudo terminal", NULL, 0); return 1; } if ((pid = fork()) == -1) { close(master); close(slave); - zerrnam(nam, "couldn't create pty command: %s", pname, 0); + zwarnnam(nam, "couldn't create pty command: %s", pname, 0); return 1; } else if (!pid) { if (!echo) { @@ -298,6 +317,8 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block) close(slave); + setpgrp(0L, getpid()); + execve(cmd, args, environ); exit(0); } @@ -307,9 +328,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block) p = (Ptycmd) zalloc(sizeof(*p)); p->name = ztrdup(pname); - PERMALLOC { - p->args = arrdup(args); - } LASTALLOC; + p->args = zarrdup(args); p->fd = master; p->pid = pid; p->echo = echo; @@ -343,7 +362,9 @@ deleteptycmd(Ptycmd cmd) zsfree(p->name); freearray(p->args); - kill(p->pid, SIGHUP); + /* We kill the process group the command put itself in. */ + + kill(-(p->pid), SIGHUP); zclose(cmd->fd); @@ -375,7 +396,7 @@ checkptycmd(Ptycmd cmd) static int ptyread(char *nam, Ptycmd cmd, char **args) { - int blen = 256, used = 0, ret; + int blen = 256, used = 0, ret = 1; char *buf = (char *) zhalloc(blen + 1); Patprog prog = NULL; @@ -383,57 +404,113 @@ ptyread(char *nam, Ptycmd cmd, char **args) char *p; if (args[2]) { - zerrnam(nam, "too many arguments", NULL, 0); + zwarnnam(nam, "too many arguments", NULL, 0); return 1; } p = dupstring(args[1]); tokenize(p); remnulargs(p); if (!(prog = patcompile(p, PAT_STATIC, NULL))) { - zerrnam(nam, "bad pattern: %s", args[1], 0); + zwarnnam(nam, "bad pattern: %s", args[1], 0); return 1; } } do { - while ((ret = read(cmd->fd, buf + used, 1)) == 1) { + if (!ret) { + checkptycmd(cmd); + if (cmd->fin) + break; + } + if ((ret = read(cmd->fd, buf + used, 1)) == 1) { if (++used == blen) { buf = hrealloc(buf, blen, blen << 1); blen <<= 1; } } buf[used] = '\0'; - } while (prog && !pattry(prog, buf)); - if (*args) - setsparam(*args, ztrdup(buf)); - else - printf("%s", buf); + /**** Hm. If we leave the loop when ret < 0 the user would have + * to make sure that `zpty -r' is tried more than once if + * there will be some output and we only got the ret == -1 + * because the output is not yet available. + * The same for the `write' below. */ + + if (ret < 0 && (cmd->block +#ifdef EWOULDBLOCK + || errno != EWOULDBLOCK +#else +#ifdef EAGAIN + || errno != EAGAIN +#endif +#endif + )) + break; + + if (!prog && !ret) + break; + } while (!errflag && + (prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) : + (used < READ_LEN))); + if (*args) + setsparam(*args, ztrdup(metafy(buf, used, META_HREALLOC))); + else { + fflush(stdout); + write(1, buf, used); + } return !used; } static int +ptywritestr(Ptycmd cmd, char *s, int len) +{ + int written; + + for (; len; len -= written, s += written) { + if ((written = write(cmd->fd, s, len)) < 0 && + (cmd->block +#ifdef EWOULDBLOCK + || errno != EWOULDBLOCK +#else +#ifdef EAGAIN + || errno != EAGAIN +#endif +#endif + )) + return 1; + if (written < 0) { + checkptycmd(cmd); + if (cmd->fin) + break; + written = 0; + } + } + return 0; +} + +static int ptywrite(Ptycmd cmd, char **args, int nonl) { if (*args) { char sp = ' '; - while (*args) { - write(cmd->fd, *args, strlen(*args)); + while (*args) + if (ptywritestr(cmd, *args, strlen(*args)) || + (*++args && ptywritestr(cmd, &sp, 1))) + return 1; - if (*++args) - write(cmd->fd, &sp, 1); - } if (!nonl) { sp = '\n'; - write(cmd->fd, &sp, 1); + if (ptywritestr(cmd, &sp, 1)) + return 1; } } else { int n; char buf[BUFSIZ]; while ((n = read(0, buf, BUFSIZ)) > 0) - write(cmd->fd, buf, n); + if (ptywritestr(cmd, buf, n)) + return 1; } return 0; } @@ -449,17 +526,17 @@ bin_zpty(char *nam, char **args, char *ops, int func) ops['d'] || ops['L'])) || (ops['d'] && (ops['b'] || ops['e'] || ops['L'])) || (ops['L'] && (ops['b'] || ops['e']))) { - zerrnam(nam, "illegal option combination", NULL, 0); + zwarnnam(nam, "illegal option combination", NULL, 0); return 1; } if (ops['r'] || ops['w']) { Ptycmd p; if (!*args) { - zerrnam(nam, "missing pty command name", NULL, 0); + zwarnnam(nam, "missing pty command name", NULL, 0); return 1; } else if (!(p = getptycmd(*args))) { - zerrnam(nam, "no such pty command: %s", *args, 0); + zwarnnam(nam, "no such pty command: %s", *args, 0); return 1; } checkptycmd(p); @@ -486,11 +563,11 @@ bin_zpty(char *nam, char **args, char *ops, int func) return ret; } else if (*args) { if (!args[1]) { - zerrnam(nam, "missing command", NULL, 0); + zwarnnam(nam, "missing command", NULL, 0); return 1; } if (getptycmd(*args)) { - zerrnam(nam, "pty command name already used: %s", *args, 0); + zwarnnam(nam, "pty command name already used: %s", *args, 0); return 1; } return newptycmd(nam, *args, args + 1, ops['e'], ops['b']); |