zsh - ksh/tcsh-like shell (part 5 of 8)
Paul John Falstad
pfalstad at phoenix.Princeton.EDU
Sat Dec 15 10:32:05 AEST 1990
---cut here---cut here---cut here---
-{
-list2 l2 = (list2) alloc(sizeof *l2);
-int iter = 0;
-
- for (;;)
- {
- if (peek == BANG)
- {
- l2->flags |= PFLAG_NOT;
- matchit();
- }
- else if (peek == TIME)
- {
- l2->flags |= PFLAG_TIMED;
- matchit();
- }
- else if (peek == COPROC)
- {
- l2->flags |= PFLAG_COPROC;
- matchit();
- }
- else
- break;
- iter = 1;
- }
- if (!(l2->left = parpline()))
- {
- free(l2);
- if (!errflag && iter)
- {
- zerr("parse error: pipeline expected");
- errflag = 1;
- }
- return NULL;
- }
- if (peek == DAMPER || peek == DBAR)
- {
- l2->type = (peek == DAMPER) ? ANDNEXT : ORNEXT;
- matchit();
- while (peek == NEWLIN)
- matchit();
- if (!(l2->right = parlist2()))
- {
- if (!errflag)
- {
- zerr("invalid null command");
- errflag = 1;
- }
- freepline(l2->left);
- free(l2);
- return NULL;
- }
- }
- else
- {
- l2->type = END;
- l2->right = NULL;
- }
- return l2;
-}
-
-/* parse a pipeline */
-
-pline parpline(void)
-{
-pline p = (pline) alloc(sizeof *p);
-
- if (!(p->left = parcmd()))
- {
- free(p);
- return NULL;
- }
- if (peek == HERR)
- {
- freecmd(p->left);
- free(p);
- return NULL;
- }
- if (peek == BAR || peek == BARAMP)
- {
- if (peek == BARAMP)
- {
- struct fnode *f;
-
- f = alloc(sizeof *f);
- f->type = MERGEOUT;
- f->fd1 = 2;
- f->u.fd2 = 1;
- addnode(p->left->redir,f);
- }
- matchit();
- while (peek == NEWLIN)
- matchit();
- p->type = PIPE;
- if (!(p->right = parpline()))
- {
- if (!errflag)
- {
- zerr("invalid null command");
- errflag = 1;
- }
- freecmd(p->left);
- free(p);
- return NULL;
- }
- }
- else
- {
- p->type = END;
- p->right = NULL;
- }
- return p;
-}
-
-/* parse a command */
-
-comm parcmd(void)
-{
-comm c = (comm) alloc(sizeof *c);
-list l;
-char *str;
-int flag,iter = 0;
-
- incmd = 0;
- c->left = NULL;
- c->cmd = NULL;
- c->args = newtable();
- c->redir = newtable();
- c->type = SIMPLE;
- c->vars = NULL;
- if (peek == EOF)
- return NULL;
-foo:
- switch (peek)
- {
- case HERR:
- return NULL;
- case ENVSTRING:
- if (!c->vars)
- c->vars = newtable(); /* FIX */
- for (str = tstr; *str != '='; str++);
- *str++ = '\0';
- addnode(c->vars,tstr);
- addnode(c->vars,strdup(str));
- matchit();
- goto foo;
- case FOR:
- incmd = 1;
- matchit();
- if (parfor(c,1))
- return NULL;
- break;
- case SELECT:
- incmd = 1;
- matchit();
- if (parfor(c,0))
- return NULL;
- break;
- case CASE:
- incmd = 1;
- matchit();
- if (parcase(c))
- return NULL;
- break;
- case IF:
- matchit();
- if (parif(c))
- return NULL;
- break;
- case WHILE:
- matchit();
- if (parwhile(c,0))
- return NULL;
- break;
- case UNTIL:
- matchit();
- if (parwhile(c,1))
- return NULL;
- break;
- case REPEAT:
- incmd = 1;
- matchit();
- if (parrepeat(c))
- return NULL;
- break;
- case INPAR:
- matchit();
- c->type = SUBSH;
- if (!(c->left = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTPAR)
- {
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- break;
- case INBRACE:
- matchit();
- c->type = CURSH;
- if (!(c->left = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- break;
- case FUNC:
- matchit();
- str = tstr;
- if (peek != STRING && peek != ENVSTRING)
- {
- c->cmd = strdup("function");
- incmd = 1;
- if (isredir())
- goto jump1;
- else
- goto jump2;
- }
- do
- matchit();
- while (peek == NEWLIN);
- if (peek != INBRACE)
- {
- freecmd(c);
- zerr("parse error: '{' expected");
- return NULL;
- }
- matchit();
- flag = peek == OUTBRACE;
- if (!(l = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freelist(l);
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- settrap(str,flag);
- addhnode(str,l,shfunchtab,freeshfunc);
- c->cmd = strdup("");
- c->type = SIMPLE;
- break;
- case EXEC:
- c->flags |= CFLAG_EXEC;
- matchit();
- iter = 1;
- goto foo;
- case COMMAND:
- c->flags |= CFLAG_COMMAND;
- matchit();
- iter = 1;
- goto foo;
- default:
-jump1:
- if (isredir())
- {
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- goto foo;
- }
- if (!(peek == STRING || peek == ENVSTRING))
- {
- if (full(c->redir))
- {
- c->cmd = strdup("cat");
- return c;
- }
- if (c->vars)
- {
- c->cmd = strdup("");
- return c;
- }
- free(c->args);
- free(c->redir);
- free(c);
- if (iter && !errflag)
- {
- errflag = 1;
- zerr("parse error: command expected");
- }
- return NULL;
- }
-jump2:
- while (peek == STRING || peek == ENVSTRING || isredir())
- if (isredir())
- {
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- }
- else
- {
- if (tstr[0] == Inpar && tstr[1] == Outpar && !tstr[2])
- {
- free(tstr);
- incmd = 0;
- matchit();
- if (full(c->args))
- {
- zerr("illegal function definition");
- freecmd(c);
- return NULL;
- }
- while (peek == NEWLIN)
- matchit();
- if (peek != INBRACE)
- {
- freecmd(c);
- zerr("parse error: '{' expected");
- return NULL;
- }
- matchit();
- flag = peek == OUTBRACE;
- if (!(l = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freelist(l);
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- settrap(c->cmd,flag);
- addhnode(c->cmd,l,shfunchtab,freeshfunc);
- c->cmd = strdup("");
- c->type = SIMPLE;
- incmd = 0;
- return c;
- }
- if (peek == ENVSTRING && (!incmd || opts[KEYWORD] == OPT_SET))
- {
- if (!c->vars)
- c->vars = newtable(); /* FIX */
- for (str = tstr; *str != '='; str++);
- *str++ = '\0';
- addnode(c->vars,tstr);
- addnode(c->vars,strdup(str));
- }
- else if (c->cmd)
- addnode(c->args,tstr);
- else
- {
- c->cmd = tstr;
- incmd = 1;
- }
- matchit();
- }
- break;
- }
- while (isredir())
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- incmd = 0;
- if (peek == HERR)
- {
- freecmd(c);
- return NULL;
- }
- return c;
-}
-
-/* != 0 if peek is a redirection operator */
-
-int isredir(void)
-{
- return (peek >= OUTANG && peek <= DOUTANGAMPBANG);
-}
-
-/* get fd associated with str */
-
-int getfdstr(char *s)
-{
- if (s[1])
- return -1;
- if (isdigit(*s))
- return *s-'0';
- if (*s == 'p')
- return -2;
- return -1;
-}
-
-int parredir(comm c)
-{
-struct fnode *fn = (struct fnode *) alloc(sizeof *fn);
-int pk = peek,ic = incmd,mrg2 = 0;
-
- fn->type = peek-OUTANG+WRITE;
- if (peek == OUTANGAMP)
- fn->type = MERGEOUT;
- if (peekfd != -1)
- fn->fd1 = peekfd;
- else if (peek <= DOUTANGBANG || peek >= OUTANGAMP)
- fn->fd1 = 1;
- else
- fn->fd1 = 0;
- incmd = 1;
- matchit();
- incmd = ic;
- if (peek != STRING)
- {
- zerr("parse error: filename expected");
- return 1;
- }
-
- if ((*tstr == Inang || *tstr == Outang) && tstr[1] == Inpar)
- {
- if (fn->type == WRITE)
- fn->type = OUTPIPE;
- else if (fn->type == READ)
- fn->type = INPIPE;
- else
- {
- zerr("parse error: bad process redirection");
- return 1;
- }
- fn->u.name = tstr;
- }
- else if (fn->type == HEREDOC)
- fn->u.fd2 = gethere(tstr);
- else if (pk >= OUTANGAMP && getfdstr(tstr) == -1)
- {
- mrg2 = 1;
- fn->u.name = tstr;
- fn->type = pk-OUTANGAMP;
- }
- else if (pk > OUTANGAMPBANG)
- {
- zerr("parse error: filename expected");
- return 1;
- }
- else if (pk == OUTANGAMPBANG)
- {
- struct fnode *fe = alloc(sizeof *fe);
-
- fe->fd1 = fn->fd1;
- fe->type = CLOSE;
- addnode(c->redir,fe);
- fn->u.fd2 = getfdstr(tstr);
- if (fn->u.fd2 == -2)
- fn->u.fd2 = spout;
- fn->type = MERGEOUT;
- }
- else if (fn->type == MERGE || fn->type == MERGEOUT)
- {
- if (*tstr == '-')
- fn->type = CLOSE;
- else
- {
- fn->u.fd2 = getfdstr(tstr);
- if (fn->u.fd2 == -2)
- fn->u.fd2 = (pk == OUTANGAMP) ? spout : spin;
- }
- }
- else
- fn->u.name = tstr;
- addnode(c->redir,fn);
- if (mrg2)
- {
- struct fnode *fe = alloc(sizeof *fe);
-
- fe->fd1 = 2;
- fe->u.fd2 = fn->fd1;
- fe->type = MERGEOUT;
- addnode(c->redir,fe);
- }
- matchit();
- return 0;
-}
-
End of parse.c
echo parse.pro 1>&2
sed 's/^-//' >parse.pro <<'End of parse.pro'
-list parlist(int nest);
-list parlist1(int nest);
-list2 parlist2(void);
-pline parpline(void);
-comm parcmd(void);
-int isredir(void);
-int getfdstr(char *s);
-int parredir(comm c);
End of parse.pro
echo subst.c 1>&2
sed 's/^-//' >subst.c <<'End of subst.c'
-/*
-
- subst.c - various substitution
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <pwd.h>
-#define MAXPATHLEN 1024
-
-#define magicerr() { if (magic) putc('\n',stderr); }
-
-/* do substitutions before fork */
-
-void prefork(table list)
-{
-Node node = list->first;
-
- while (node)
- {
- char *str,*str3;
-
- str = str3 = node->dat;
- if (!magic && str[1] == Inpar && (*str == Inang ||
- *str == Outang || *str == Equals))
- {
- if (*str == Inang)
- node->dat = getoutproc(str+2); /* <(...) */
- else if (*str == Equals)
- node->dat = getoutputfile(str+2); /* =(...) */
- else
- node->dat = getinproc(str+2); /* >(...) */
- free(str);
- if (!node->dat)
- {
- zerr("parse error in process substitution");
- errflag = 1;
- return;
- }
- }
- else while (*str)
- {
- if (*str == String || *str == Qstring)
- if (str[1] != Inpar)
- if (str[1] == '*' || str[1] == Star)
- parminsall(list,&node,&str,&str3); /* $* */
- else if (str[1] == Inbrack)
- {
- arithsuber((void **) &str,&str3); /* $[...] */
- if (magic)
- magic = 2;
- node->dat = str3;
- }
- else
- {
- parmsuber(str,&str3); /* $foo */
- node->dat = str = str3;
- if (errflag)
- return;
- continue;
- }
- str++;
- if (errflag)
- return;
- }
- node = node->next;
- }
-}
-
-void postfork(table list,int globstat)
-{
-Node node = list->first;
-int glb = 1;
-
- if (isset(NOGLOBOPT) || globstat != GLOB)
- glb = 0;
- while (node)
- {
- char *str,*str3;
-
- str = str3 = node->dat;
- while (*str)
- {
- if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
- *str == Tick || *str == Qtick)
- comminsall(list,&node,&str,&str3); /* `...`,$(...) */
- str++;
- if (errflag)
- return;
- }
-
- /* now we remove the Nulargs tokens if this is not a null
- arguments. The lexical analyzer throws these in so that
- zsh will not look at this:
-
- $PA"TH"
-
- and expand it to $PATH. But after parameter substitution
- these are only a nuisance, so we remove them. */
-
- if (*(char *) node->dat)
- remnulargs(node->dat);
-
- if (unset(IGNOREBRACES))
- while (hasbraces(node->dat))
- xpandbraces(list,&node);
- filesub(&node->dat);
- if (errflag)
- return;
- if (glb)
- {
- if (haswilds(node->dat))
- glob(list,&node);
- if (errflag)
- return;
- }
- else if (globstat == MOSTGLOB && *(char *) node->dat != '-')
- glb = 1;
- node = node->next;
- }
-}
-
-/* strdup, but returns "Nularg" if this is a null string */
-
-void *nstrdup(void *s)
-{
-char *t = s,u[] = {Nularg,'\0'};
-
- if (!*t)
- return strdup(u);
- return strdup(t);
-}
-
-/* $* */
-
-void parminsall(table l,Node *nn,char **aptr,char **bptr)
-{
-char *str3 = *aptr,*str = *bptr;
-Node n = *nn,where = n->last;
-table pl;
-
- if (magic)
- magic = 2;
- *str3 = '\0';
- str3 += 2;
- remnode(l,n);
- pl = duptable(pparms,nstrdup);
- free(getnode(pl));
- if (pl->first) /* if $# > 1 */
- {
- char *ptr;
- Node tmp;
-
- ptr = pl->first->dat;
- pl->first->dat = dyncat(str,ptr);
- free(ptr);
- ptr = pl->last->dat;
- *bptr = pl->last->dat = dyncat(ptr,str3);
- *aptr = *bptr+strlen(str)+strlen(ptr)-1;
- free(ptr);
- tmp = where->next;
- where->next = pl->first;
- pl->last->next = tmp;
- pl->first->last = where;
- if (tmp)
- tmp->last = pl->last;
- else
- l->last = pl->last;
- *nn = pl->last;
- }
- else /* just remove the $* */
- {
- insnode(l,where,*bptr = dyncat(str,str3));
- *nn = where->next;
- *aptr = *bptr+strlen(str)-1;
- }
-}
-
-char *dynread(char stop)
-{
-int bsiz = 256,ct = 0,c;
-char *buf = zalloc(bsiz),*ptr;
-
- ptr = buf;
- while ((c = hgetc()) != stop)
- {
- *ptr++ = c;
- if (++ct == bsiz)
- {
- buf = realloc(buf,bsiz *= 2);
- ptr = buf+ct;
- }
- }
- *ptr = 0;
- return buf;
-}
-
-int filesub(void **namptr)
-{
-char *str = *namptr,*cnam;
-
- if (*str == Tilde && str[1] != '=')
- {
- if (str[1] == '+')
- {
- char *foo = strdup(cwd),*t = str; /* ~+ */
-
- str+=2;
- modify((void **) &foo,&str);
- *namptr = dyncat(cwd,str);
- free(foo);
- free(t);
- return 1;
- }
- else if (str[1] == '-') /* ~- */
- {
- char *foo,*t = str;
-
- if (cnam = getparm("OLDPWD"))
- foo = cnam;
- else
- foo = cwd;
- str += 2;
- foo = strdup(foo);
- modify((void **) &foo,&str);
- *namptr = dyncat(foo,str);
- free(t);
- free(foo);
- return 1;
- }
- if (isalpha(str[1])) /* ~foo */
- {
- char *ptr,*home;
-
- for (ptr = ++str; *ptr && !istok(*ptr) && (isalnum(*ptr) || *ptr == '-'); ptr++)
- if (*ptr == '-')
- *ptr = '-';
- if (!(home = gethome(str,ptr-str)))
- {
- if (magic)
- home = completehome(str,ptr-str);
- if (!home)
- {
- magicerr();
- zerr("user not found: %l",ptr-str,str);
- errflag = 1;
- return 0;
- }
- }
- modify((void **) &home,&ptr);
- *namptr = dyncat(home,ptr);
- free(home);
- free(str-1);
- return 1;
- }
- else if (str[1] == '/') /* ~/foo */
- {
- *namptr = dyncat(home,str+1);
- free(str);
- return 1;
- }
- else if (!str[1]) /* ~ by itself */
- {
- free(str);
- *namptr = strdup(home);
- return 1;
- }
- }
- if (*str == Equals && !istok(str[1]) && (isalnum(str[1]) || str[1] == '-'))
- {
- char *ptr,*s,*ds;
- int val;
-
- untokenize(str);
- if (isalpha(str[1])) /* =foo */
- {
- struct chnode *chn;
- struct anode *t;
- char sav,*pp;
-
- for (pp = str+1; *pp && *pp != ':'; pp++);
- sav = *pp;
- *pp = '\0';
- if ((t = gethnode(str+1,alhtab)) && t->cmd)
- if (t->cmd >= 0)
- cnam = strdup(t->text);
- else
- {
- magicerr();
- zerr("%s: shell reserved word",str+1);
- errflag = 1;
- return 0;
- }
- else if (chn = gethnode(str+1,chtab))
- if (chn->type != BUILTIN)
- cnam = strdup(chn->u.nam);
- else
- {
- magicerr();
- zerr("%s: shell built-in command",str+1);
- errflag = 1;
- return 0;
- }
- else if (!(cnam = findcmd(str+1)))
- {
- magicerr();
- zerr("%s not found",str+1);
- errflag = 1;
- return 0;
- }
- *namptr = cnam;
- if ((*pp = sav) == ':')
- {
- modify(namptr,&pp);
- s = *namptr;
- *namptr = dyncat(*namptr,pp);
- free(s);
- }
- free(str);
- return 1;
- }
- if (str[1] == '-') /* =- */
- {
- val = -1;
- ptr = str+2;
- }
- else
- val = strtol(str+1,&ptr,10); /* =# */
- ds = dstackent(val);
- if (!ds)
- return 1;
- s = strdup(ds);
- modify((void **) &s,&ptr);
- *namptr = dyncat(s,ptr);
- free(s);
- free(str);
- return 1;
- }
- return 0;
-}
-
-/* get a user's directory */
-
-char *gethome(char *user,int len)
-{
-char sav,*str;
-struct passwd *pw;
-
- sav = user[len];
- user[len] = '\0';
- if (!(pw = getpwnam(user)))
- {
- user[len] = sav;
- return NULL;
- }
- str = xsymlink(pw->pw_dir);
- user[len] = sav;
- return str;
-}
-
-/* complete a user and try to get his home directory */
-
-char *completehome(char *user,int len)
-{
-FILE *in;
-char buf[MAXPATHLEN],*str;
-
- sprintf(buf,"%s/.zfriends",getparm("HOME"));
- if (!(in = fopen(buf,"r")))
- return NULL;
- while (fgetline(buf,MAXPATHLEN,in))
- if (!strncmp(user,buf,len))
- if (str = gethome(buf,strlen(buf)))
- {
- fclose(in);
- return str;
- }
- fclose(in);
- return NULL;
-}
-
-/* get the value of the parameter specified by the first len
- characters of s */
-
-char *getsparmval(char *s,int len)
-{
-char sav = s[len];
-char *val;
-char buf[50];
-int t0;
-
- if (len == 1 && (istok(*s) || !isalnum(*s)))
- switch(*s)
- {
- case Pound:
- case '#':
- sprintf(buf,"%d",ppcount());
- return strdup(buf);
- case '-':
- for (val = buf, t0 = ' '; t0 <= 'z'; t0++)
- if (opts[t0] == OPT_SET)
- *val++ = t0;
- *val = '\0';
- return strdup(buf);
- case '?':
- case Quest:
- sprintf(buf,"%d",lastval);
- return strdup(buf);
- case '$':
- case String:
- sprintf(buf,"%d",procnum);
- return strdup(buf);
- case '!':
- sprintf(buf,"%d",proclast);
- return strdup(buf);
- default:
- return NULL;
- }
- s[len] = '\0';
- if (isdigit(*s))
- {
- int num;
- Node node;
-
- num = atoi(s);
- s[len] = sav;
- for (node = pparms->first; node && num; num--,node = node->next);
- return (node) ? strdup(node->dat) : NULL;
- }
- val = getparm(s);
- s[len] = sav;
- return (val) ? strdup(val) : NULL;
-}
-
-/* set the parameter associated with the first len characters of s
- to v. */
-
-void setparml(char *s,int len,char *v)
-{
-char c;
-
- c = s[len];
- s[len] = 0;
- if (isdigit(*s))
- {
- int num;
- Node node;
-
- num = atoi(s);
- for (node = pparms->first; node && num; num--,node = node->next);
- if (node)
- {
- free(node->dat);
- node->dat = v;
- }
- else
- {
- while (num--)
- addnode(pparms,strdup(""));
- addnode(pparms,v);
- }
- }
- else
- setparm(strdup(s),v,0,0);
- s[len] = c;
-}
-
-/* `...`, $(...) */
-
-void comminsall(table l,Node *nn,char **aptr,char **bptr)
-{
-char *str3 = *aptr,*str = *bptr,*str2;
-Node n = *nn,where = n->last;
-table pl;
-int s31 = (*str3 == Qtick || *str3 == Qstring);
-
- if (magic) magic = 2;
- if (*str3 == Tick || *str3 == Qtick)
- {
- *str3 = '\0';
- for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
- *str3++ = '\0';
- }
- else
- {
- *str3++ = '\0';
- for (str2 = ++str3; *str3 != Outpar; str3++);
- *str3++ = '\0';
- }
- remnode(l,n);
- if (!(pl = getoutput(str2,s31)))
- {
- magicerr();
- zerr("parse error in command substitution");
- errflag = 1;
- return;
- }
- if (pl->first)
- {
- char *ptr;
- Node tmp;
-
- ptr = pl->first->dat;
- pl->first->dat = dyncat(str,ptr);
- free(ptr);
- ptr = pl->last->dat;
- *bptr = pl->last->dat = dyncat(ptr,str3);
- *aptr = *bptr+strlen(str)+strlen(ptr)-1;
- free(ptr);
- tmp = where->next;
- where->next = pl->first;
- pl->last->next = tmp;
- pl->first->last = where;
- if (tmp)
- tmp->last = pl->last;
- else
- l->last = pl->last;
- /* free(tmp); */
- *nn = pl->last;
- free(pl);
- }
- else
- {
- insnode(l,where,*bptr = dyncat(str,str3));
- *nn = where->next;
- *aptr = *bptr+strlen(str)-1;
- }
-}
-
-/* do simple parameter substitution */
-
-/*
- consider an argument like this:
-
- abcde${fgh:-ijk}lmnop
-
- aptr will point to the $.
- *bptr,ostr will point to the a.
- t will point to the f.
- u will point to the i.
- s will point to the l (eventually).
-*/
-
-void parmsuber(char *aptr,char **bptr)
-{
-char *s = aptr,*t,*u,*val,*ostr = *bptr;
-int brs; /* != 0 means ${...}, otherwise $... */
-int vlen; /* the length of the name of the parameter */
-int colf; /* != 0 means we found a colon after the name */
-int doub = 0; /* != 0 means we have %%, not %, or ##, not # */
-
- /* first, remove the $ so *bptr is pointing to a null-terminated
- string containing the stuff before the $. Then check for braces,
- and get the parameter name and value, if any. */
-
- *s++ = '\0';
- if (brs = (*s == '{' || *s == Inbrace))
- s++;
- t = s;
- if (istok(*s) || !isalnum(*s))
- {
- val = getsparmval(t,vlen = 1);
- if (!val)
- {
- *(char *) aptr = '$';
- if (brs)
- s[-1] = '{';
- return;
- }
- s++;
- }
- else
- {
- while (!istok(*s) && (isalnum(*s) || *s == '_'))
- s++;
- val = getsparmval(t,vlen = s-t);
- }
-
- /* val can still be NULL at this point. */
-
- if (colf = *s == ':')
- s++;
-
- /* check for ${..?...} or ${..=..} or one of those. Only works
- if the name is in braces. */
-
- if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
- *s == '%' || *s == Quest || *s == Pound))
- {
- if (*s == s[1])
- {
- s++;
- doub = 1;
- }
- u = ++s;
- if (brs)
- while (*s != '}' && *s != Outbrace)
- s++;
- else
- {
- while (*s++);
- s--;
- }
- *s = '\0';
- switch (u[-1])
- {
- case '-':
- if (!val || (colf && !*val))
- val = strdup(u);
- break;
- case '=':
- if (!val || (colf && !*val))
- setparml(t,vlen,val = strdup(u));
- break;
- case '?':
- case Quest:
- if (!val || (colf && !*val))
- {
- magicerr();
- zerr("%s",(*u) ? u : "parameter not set");
- if (!interact)
- exit(1);
- else
- errflag = 1;
- return;
- }
- break;
- case '+':
- if (!val || (colf && !*val))
- val = strdup("");
- else
- val = strdup(u);
- break;
- case '#':
- case Pound:
- if (!val)
- val = strdup("");
- getmatch(&val,u,doub);
- break;
- case '%':
- if (!val)
- val = strdup("");
- getmatch(&val,u,doub+2);
- break;
- }
- }
- else /* no ${...=...} or anything, but possible modifiers. */
- {
- if (!val)
- {
- if (isset(NOUNSET))
- {
- zerr("parameter not set: %l",vlen,t);
- errflag = 1;
- return;
- }
- val = strdup("");
- }
- if (colf)
- {
- s--;
- modify((void **) &val,&s); /* do modifiers */
- }
- if (brs)
- {
- if (*s != '}' && *s != Outbrace)
- {
- zerr("closing brace expected");
- errflag = 1;
- return;
- }
- s++;
- }
- }
- if (errflag)
- {
- free(ostr);
- return;
- }
- *bptr = zalloc((char *) aptr-(*bptr)+strlen(val)+strlen(s)+1);
- strcpy(*bptr,ostr);
- strcat(*bptr,val);
- strcat(*bptr,s);
- free(ostr);
- if (magic)
- magic = 2;
-}
-
-/* arithmetic substitution */
-
-void arithsuber(void **aptr,char **bptr)
-{
-char *s = *aptr,*t,buf[16];
-long v;
-
- *s = '\0';
- for (; *s != Outbrack; s++);
- *s++ = '\0';
- v = matheval(*aptr+2);
- sprintf(buf,"%ld",v);
- t = zalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
- strcpy(t,*bptr);
- strcat(t,buf);
- strcat(t,s);
- free(*bptr);
- *bptr = t;
-}
-
-void modify(void **str,char **ptr)
-{
-char *ptr1,*ptr2,*ptr3,del,*lptr;
-int gbal;
-
- while (**ptr == ':')
- {
- lptr = *ptr;
- (*ptr)++;
- gbal = 0;
-here:
- switch(*(*ptr)++)
- {
- case 'h':
- while (remtpath(str) && gbal);
- break;
- case 'r':
- while (remtext(str) && gbal);
- break;
- case 'e':
- while (rembutext(str) && gbal);
- break;
- case 't':
- while (remlpaths(str) && gbal);
- break;
- case 's':
- if (last)
- free(last);
- if (rast)
- free(rast);
- ptr1 = *ptr;
- del = *ptr1++;
- for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
- if (!*ptr2)
- {
- magicerr();
- zerr("bad subtitution");
- errflag = 1;
- return;
- }
- *ptr2++ = '\0';
- for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
- if (*ptr3)
- *ptr3++ = '\0';
- last = strdup(ptr1);
- rast = strdup(ptr2);
- *ptr = ptr3;
- case '&':
- if (last && rast)
- subststr(str,last,rast,gbal);
- break;
- case 'g':
- gbal = 1;
- goto here;
- default:
- *ptr = lptr;
- return;
- }
- }
-}
-
-/* get a directory stack entry */
-
-char *dstackent(int val)
-{
-Node node;
-
- if ((val < 0 && !dirstack->first) || !val--)
- return cwd;
- if (val < 0)
- node = dirstack->last;
- else
- for (node = dirstack->first; node && val; val--,node = node->next);
- if (!node)
- {
- magicerr();
- zerr("not enough dir stack entries.");
- errflag = 1;
- return NULL;
- }
- return node->dat;
-}
-
-void execshfunc(comm comm)
-{
-table tab,oldlocals;
-Node n;
-char *s;
-
- tab = pparms;
- oldlocals = locallist;
- locallist = newtable();
- for (n = tab->first; n; n = n->next);
- pparms = comm->args;
- runlist(comm->left);
- retflag = 0;
- comm->left = NULL;
- pparms = tab;
- while (s = getnode(locallist))
- {
- void *z = remhnode(s,parmhtab);
- if (z)
- freepm(z);
- }
- free(locallist);
- locallist = oldlocals;
-}
-
-/* make an alias hash table node */
-
-struct anode *mkanode(char *txt,int cmflag)
-{
-struct anode *ptr = (void *) alloc(sizeof(struct anode));
-
- ptr->text = txt;
- ptr->cmd = cmflag;
- ptr->inuse = 0;
- return ptr;
-}
-
-/* perform TAB substitution */
-
-char *docompsubs(char *str,int *i)
-{
-table fake,curt = curtab;
-char *s,*t;
-int ct = 0;
-
- for (s = str; *s; s++)
- for (t = tokens; *t; t++)
- if (*s == *t)
- {
- *s = (t-tokens)+Pound;
- break;
- }
- curtab = NULL;
- magic = 1;
- fake = newtable();
- addnode(fake,str);
- prefork(fake);
- if (!errflag)
- postfork(fake,GLOB);
- if (fake->first && fake->first->next)
- ct = 1;
- t = s = buildline(fake);
- free(fake);
- rl_prep_terminal();
- if (errflag)
- {
- rl_on_new_line();
- rl_redisplay();
- errflag = 0;
- magic = 0;
- curtab = curt;
- *i = 0;
- return NULL;
- }
- *i = (magic == 2) + ct;
- magic = 0;
- curtab = curt;
- untokenize(s);
- return s;
-}
-
-/* perform substitution on the command name */
-
-void docmdsubs(char **str)
-{
-table fake;
-char *s = strdup(*str);
-
- fake = newtable();
- addnode(fake,*str);
- prefork(fake);
- if (!errflag) postfork(fake,GLOB);
- if (errflag)
- {
- free(fake);
- free(s);
- return;
- }
- if (fake->first && fake->first->next)
- {
- zerr("%s: ambiguous",s);
- errflag = 1;
- free(fake);
- free(s);
- return;
- }
- *str = getnode(fake);
- free(s);
- free(fake);
-}
-
-/* perform substitution on the variables */
-
-void dovarsubs(char **str)
-{
-table fake;
-char *s;
-
- fake = newtable();
- addnode(fake,*str);
- prefork(fake);
- if (!errflag) postfork(fake,GLOB);
- if (errflag)
- return;
- s = buildline(fake);
- untokenize(s);
- *str = s;
- free(fake);
-}
-
End of subst.c
echo subst.pro 1>&2
sed 's/^-//' >subst.pro <<'End of subst.pro'
-void prefork(table list);
-void postfork(table list,int globstat);
-void *nstrdup(void *s);
-void parminsall(table l,Node *nn,char **aptr,char **bptr);
-char *dynread(char stop);
-int filesub(void **namptr);
-char *gethome(char *user,int len);
-char *completehome(char *user,int len);
-char *getsparmval(char *s,int len);
-void setparml(char *s,int len,char *v);
-void comminsall(table l,Node *nn,char **aptr,char **bptr);
-void parmsuber(char *aptr,char **bptr);
-void arithsuber(void **aptr,char **bptr);
-void modify(void **str,char **ptr);
-char *dstackent(int val);
-void execshfunc(comm comm);
-struct anode *mkanode(char *txt,int cmflag);
-char *docompsubs(char *str,int *i);
-void docmdsubs(char **str);
-void dovarsubs(char **str);
End of subst.pro
echo table.c 1>&2
sed 's/^-//' >table.c <<'End of table.c'
-/*
-
- table.c - linked list and hash table management
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-
-/* get an empty linked list header */
-
-table newtable()
-{
-table list;
-
- list = alloc(sizeof(*list));
- list->first = 0;
- list->last = (Node) list;
- return list;
-}
-
-/* get an empty hash table */
-
-htable newhtable(int size)
-{
-htable ret;
-
- ret = alloc(sizeof(struct xhtab));
- ret->hsize = size;
- ret->nodes = alloc(size*sizeof(struct hnode *));
- return ret;
-}
-
-/* Peter Weinberger's hash function */
-
-int hasher(char *s)
-{
-unsigned hash = 0,g;
-
- for (; *s; s++)
- {
- hash = (hash << 4) + *s;
- if (g = hash & 0xf0000000)
- {
- hash ^= g;
- hash ^= g >> 24;
- }
- }
- return hash;
-}
-
-/* add a node to a hash table */
-
-void addhnode(char *nam,void *dat,htable ht,void (*freefunc)(void *))
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hp = ht->nodes[hval],*hn;
-
- for (; hp; hp = hp->hchain)
- if (!strcmp(hp->nam,nam))
- {
- freefunc(hp->dat);
- hp->dat = dat;
- free(nam);
- return;
- }
- hn = (void *) alloc(sizeof(struct hnode));
- hn->nam = nam;
- hn->dat = dat;
- hn->hchain = ht->nodes[hval];
- ht->nodes[hval] = hn;
- if (++ht->ct == ht->hsize*4)
- expandhtab(ht);
-}
-
-/* expand hash tables when they get too many entries */
-
-void expandhtab(htable ht)
-{
-struct hnode *hp,**arr,**ha,*hn;
-int osize = ht->hsize,nsize = osize*8;
-
- ht->hsize = nsize;
- arr = ht->nodes;
- ht->nodes = alloc(nsize*sizeof(struct hnode *));
- for (ha = arr; osize; osize--,ha++)
- for (hn = *ha; hn; )
- {
- addhnode(hn->nam,hn->dat,ht,NULL);
- hp = hn->hchain;
- free(hn);
- hn = hp;
- }
- free(arr);
-}
-
-/* get an entry in a hash table */
-
-void *gethnode(char *nam,htable ht)
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hn = ht->nodes[hval];
-
- for (; hn; hn = hn->hchain)
- if (!strcmp(hn->nam,nam))
- return hn->dat;
- return NULL;
-}
-
-void freehtab(htable ht,void (*freefunc)(void *))
-{
-int val;
-struct hnode *hn,**hptr = &ht->nodes[0],*next;
-
- for (val = ht->hsize; val; val--,hptr++)
- for (hn = *hptr; hn; )
- {
- next = hn->hchain;
- freefunc(hn);
- hn = next;
- }
-}
-
-/* remove a hash table entry and return a pointer to it */
-
-void *remhnode(char *nam,htable ht)
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hn = ht->nodes[hval],*hp;
-void *dat;
-
- if (!hn)
- return NULL;
- if (!strcmp(hn->nam,nam))
- {
- ht->nodes[hval] = hn->hchain;
- dat = hn->dat;
- free(hn->nam);
- free(hn);
- ht->ct--;
- return dat;
- }
- for (hp = hn, hn = hn->hchain; hn; hn = (hp = hn)->hchain)
- if (!strcmp(hn->nam,nam))
- {
- hp->hchain = hn->hchain;
- dat = hn->dat;
- free(hn->nam);
- free(hn);
- ht->ct--;
- return dat;
- }
- return NULL;
-}
-
-void *zalloc(int l)
-{
-void *z;
-
- if (!(z = malloc(l)))
- {
- zerr("fatal error: out of memory: restarting");
- execl(MYSELF,"zsh","-f",(void *) 0);
- exit(1);
- }
- return z;
-}
-
-void *alloc(int l)
-{
-void *z;
-
- if (!(z = calloc(l,1)))
- {
- zerr("fatal error: out of memory: restarting");
- execl(MYSELF,"zsh","-f",(void *) 0);
- exit(1);
- }
- return z;
-}
-
-/* add a node to the end of a linked list */
-
-void addnode(table list,void *str)
-{
- insnode(list,list->last,str);
-}
-
-/* insert a node in a linked list after 'last' */
-
-void insnode(table list,Node last,void *dat)
-{
-Node tmp;
-
- tmp = last->next;
- last->next = alloc(sizeof(*tmp));
- last->next->last = last;
- last->next->dat = dat;
- last->next->next = tmp;
- if (tmp)
- tmp->last = last->next;
- else
- list->last = last->next;
-}
-
-/* remove a node from a linked list */
-
-void *remnode(table list,Node nd)
-{
-void *dat;
-
- nd->last->next = nd->next;
- if (nd->next)
- nd->next->last = nd->last;
- else
- list->last = nd->last;
- free(nd);
- dat = nd->dat;
- return dat;
-}
-
-/* delete a character in a string */
-
-void chuck(char *str)
-{
- while (str[0] = str[1])
- str++;
-}
-
-/* get a node in a linked list */
-
-void *getnode(table list)
-{
-void *dat;
-Node node = list->first;
-
- if (!node)
- return NULL;
- dat = node->dat;
- list->first = node->next;
- if (node->next)
- node->next->last = (Node) list;
- else
- list->last = (Node) list;
- free(node);
- return dat;
-}
-
-/* != 0 if the linked list has at least one entry */
-
-int full(table list)
-{
- return list->first != NULL;
-}
-
-void freetable(table tab,void (*freefunc)(void *))
-{
-Node node = tab->first,next;
-
- while (node)
- {
- next = node->next;
- freefunc(node);
- node = next;
- }
- free(tab);
-}
-
-char *strdup(char *str)
-{
-char *ret = zalloc(strlen(str)+1);
-
- strcpy(ret,str);
- return ret;
-}
-
-#ifndef STRSTR
-const char *strstr(const char *s,const char *t)
-{
-const char *p1,*p2;
-
- for (; *s; s++)
- {
- for (p1 = s, p2 = t; *p2; p1++,p2++)
- if (*p1 != *p2)
- break;
- if (!*p2)
- return (char *) s;
- }
- return NULL;
-}
-#endif
-
End of table.c
echo table.pro 1>&2
sed 's/^-//' >table.pro <<'End of table.pro'
-table newtable();
-htable newhtable(int size);
-int hasher(char *s) /* copied from Programming in C++, p14 */;
-void addhnode(char *nam,void *dat,htable ht,void (*freefunc)(void *));
-void expandhtab(htable ht);
-void *gethnode(char *nam,htable ht);
-void freehtab(htable ht,void (*freefunc)(void *));
-void *remhnode(char *nam,htable ht);
-void *zalloc(int l);
-void *alloc(int l);
-void addnode(table list,void *str);
-void insnode(table list,Node last,void *dat);
-void *remnode(table list,Node nd);
-void chuck(char *str);
-void *getnode(table list);
-int full(table list);
-void freetable(table tab,void (*freefunc)(void *));
-char *strdup(char *str);
-/*const char *strstr(const char *s,const char *t); */
End of table.pro
echo test.c 1>&2
sed 's/^-//' >test.c <<'End of test.c'
-/*
-
- test.c - the test builtin
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-
-#ifndef F_OK
-#define F_OK 00
-#define R_OK 04
-#define W_OK 02
-#define X_OK 01
-#endif
-
-#include "test.pro"
-#include "table.pro"
-
-static char **arg;
-static int efg;
-
-void die(char *str)
-{
- if (!efg)
- zerrnam("test",str);
- efg = 1;
-}
-
-int test(comm comm)
-{
-Node n;
-int t0;
-char **av,**ap;
-
- for (n = comm->args->first, t0 = 0; n; n = n->next,t0++);
- ap = av = (char **) zalloc((sizeof(char *))*(t0+1));
- for (n = comm->args->first; n; n = n->next)
- *ap++ = n->dat;
- *ap = NULL;
- t0 = testmain(av);
- free(av);
- return t0;
-}
-
-int testmain(char **argv)
-{
-int ret,isbrack;
-
- efg = 0;
- arg = argv+1;
- ret = testexpr();
- if (efg)
- return 1;
- isbrack = !strcmp(*argv,"[");
- if (isbrack)
- {
- if (*arg && !strcmp(*arg,"]") && !arg[1])
- return !ret;
- }
- else
- if (!*arg)
- return !ret;
- die("bad test format");
- return 1;
-}
-
-int testexpr(void)
-{
-int ret = testexpr2(),ret2;
-
- if (*arg && !strcmp(*arg,"-o"))
- {
- arg++;
- ret2 = testexpr2();
- if (efg)
- return 0;
- ret = ret || ret2;
- }
- return ret;
-}
-
-int testexpr2(void)
-{
-int ret = testexpr3(),ret2;
-
- if (*arg && !strcmp(*arg,"-a"))
- {
- arg++;
- ret2 = testexpr2();
- if (efg)
- return 0;
- ret = ret && ret2;
- }
- return ret;
-}
-
-int testexpr3(void)
-{
- if (*arg && !strcmp(*arg,"!"))
- {
- arg++;
- return !testexpr3();
- }
- return testexpr4();
-}
-
-int testexpr4(void)
-{
-int ret,t0,t1;
-struct stat *st;
-char buf[16],*op;
-
- if (!*arg)
- {
- die("expression expected");
- return 0;
- }
- if (!strcmp(*arg,"("))
- {
- arg++;
- ret = testexpr();
- if (!*arg || strcmp(*arg,")"))
- {
- die("')' expected");
- return 0;
- }
- arg++;
- return ret;
- }
- if (**arg == '-' && !(*arg)[2])
- {
- switch((*arg++)[1])
- {
- case 'a': return(doaccess(F_OK));
- case 'b': return(S_ISBLK(dostat()));
- case 'c': return(S_ISCHR(dostat()));
- case 'd': return(S_ISDIR(dostat()));
- case 'f': return(S_ISREG(dostat()));
- case 'g': return(!!(dostat() & S_ISGID));
- case 'k': return(!!(dostat() & S_ISVTX));
- case 'L': return(S_ISLNK(dostat()));
- case 'p': return(S_ISFIFO(dostat()));
- case 'r': return(doaccess(R_OK));
- case 's': return((st = getstat()) && !!(st->st_size));
- case 'S': return(S_ISSOCK(dostat()));
- case 'u': return(!!(dostat() & S_ISUID));
- case 'w': return(doaccess(W_OK));
- case 'x': return(doaccess(X_OK));
- case 'O': return((st = getstat()) && st->st_uid == geteuid());
- case 'G': return((st = getstat()) && st->st_gid == getegid());
- case 't': {
- int t0 = 1;
-
- if (*arg && isdigit(**arg))
- t0 = atoi(*arg++);
- return isatty(t0);
- }
- case 'z':
- if (!*arg)
- {
- die("string expected");
- return 0;
- }
- return !strlen(*arg++);
- case 'n':
- if (!*arg)
- {
- die("string expected");
- return 0;
- }
- return !!strlen(*arg++);
- case 'l':
- sprintf(buf,"%d",strlen(*arg));
- *arg = buf;
- break;
- }
- }
- if (!arg[1] || !strcmp(arg[1],"-o") || !strcmp(arg[1],"-a") ||
- !strcmp(arg[1],"]") || !strcmp(arg[1],")"))
- return(!!strlen(*arg++));
- if (!arg[2])
- {
- die("bad expression");
- return 0;
- }
- if (!strcmp(arg[1],"-nt"))
- {
- time_t a;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- a = st->st_mtime;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return a > st->st_mtime;
- }
- if (!strcmp(arg[1],"-ot"))
- {
- time_t a;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- a = st->st_mtime;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return a < st->st_mtime;
- }
- if (!strcmp(arg[1],"-ef"))
- {
- dev_t d;
- ino_t i;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- d = st->st_dev;
- i = st->st_ino;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return d == st->st_dev && i == st->st_ino;
- }
- if (!strcmp(arg[1],"~="))
- {
- arg += 3;
- return patmatch(arg[-3],arg[-1]);
- }
- if (!strcmp(arg[1],"="))
- {
- arg += 3;
- return !strcmp(arg[-3],arg[-1]);
- }
- if (!strcmp(arg[1],"!="))
- {
- arg += 3;
- return !!strcmp(arg[-3],arg[-1]);
- }
- t0 = atoi(arg[0]);
- op = arg[1];
- arg += 2;
- if (!strcmp(*arg,"-l"))
- {
- if (!arg[1])
- {
- die("string expected");
- return 0;
- }
- t1 = strlen(arg[1]);
- arg += 2;
- }
- else
- t1 = atoi(*arg++);
- if (!strcmp(op,"-eq"))
- return t0 == t1;
- if (!strcmp(op,"-ne"))
- return t0 != t1;
- if (!strcmp(op,"-lt"))
- return t0 < t1;
- if (!strcmp(op,"-le"))
- return t0 <= t1;
- if (!strcmp(op,"-gt"))
- return t0 > t1;
- if (!strcmp(op,"-ge"))
- return t0 >= t1;
- if (!efg)
- zerrnam("test","unrecognized operator: %s",op);
- efg = 1;
- return 0;
-}
-
-int doaccess(int c)
-{
- if (!*arg)
- {
- die("filename expected");
- return 0;
- }
- return !access(*arg++,c);
-}
-
-struct stat *getstat(void)
-{
-static struct stat st;
-
- if (!*arg)
- {
- die("filename expected");
- return NULL;
- }
- if (!strncmp(*arg,"/dev/fd/",8))
- {
- if (fstat(atoi((*arg++)+8),&st))
- return NULL;
- }
- else if (lstat(*arg++,&st))
- return NULL;
- return &st;
-}
-
-unsigned short dostat(void)
-{
-struct stat *st;
-
- if (!(st = getstat()))
- return 0;
- return st->st_mode;
-}
-
End of test.c
echo test.pro 1>&2
sed 's/^-//' >test.pro <<'End of test.pro'
-void die(char *str);
-int test(comm comm);
-int testmain(char **argv);
-int testexpr(void);
-int testexpr2(void);
-int testexpr3(void);
-int testexpr4(void);
-int doaccess(int c);
-struct stat *getstat(void);
-unsigned short dostat(void);
End of test.pro
echo utils.c 1>&2
sed 's/^-//' >utils.c <<'End of utils.c'
-/*
-
- utils.c - miscellaneous utilities
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <pwd.h>
-#include <stdarg.h> /* had to change this to stdarg.h.old on one machine */
-#include <errno.h>
-#include <sys/dir.h>
-#include <fcntl.h>
-
-/* add vars to the parm hash table */
-
-void addvars(table vars)
-{
-char *s1,*s2;
-Node node;
-
- for (node = vars->first; node; node = node->next)
- {
- s1 = node->dat;
- untokenize(s1);
- node = node->next;
- s2 = node->dat;
- dovarsubs(&s2);
- if (errflag)
- break;
- untokenize(s2);
- setparm(s1,s2,0,0);
- }
- free(vars);
-}
-
-/* set a parameter to an integer value */
-
-void setiparm(char *s,long v,int isint)
-{
-struct pmnode *pmn,*pmo;
-
- if (!strcmp(s,"RANDOM"))
- {
- srand((unsigned long) v);
- return;
- }
- if (!strcmp(s,"SECONDS"))
- {
- shtimer = v+time(NULL);
- return;
- }
- if (pmo = gethnode(s,parmhtab))
- {
- char buf[12];
-
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = pmo->isint | isint)
- pmn->u.val = v;
- else
- {
- sprintf(buf,"%ld",v);
- pmn->u.str = strdup(buf);
- }
- addhnode(s,pmn,parmhtab,freepm);
- }
- else if (getenv(s) || (opts[ALLEXPORT] == OPT_SET))
- {
- char buf[12];
-
- sprintf(buf,"%ld",v);
- putenv(tricat(s,"=",buf));
- }
- else
- {
- char buf[12];
-
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = isint)
- pmn->u.val = v;
- else
- {
- sprintf(buf,"%ld",v);
- pmn->u.str = strdup(buf);
- }
- addhnode(s,pmn,parmhtab,freepm);
- addlocal(s);
- }
- if (!strcmp(s,"PERIOD"))
- {
- period = v*60;
- lastperiod = time(NULL)+period;
- }
- if (!strcmp(s,"HISTSIZE"))
- {
- tevs = v;
- if (tevs <= 2)
- tevs = 2;
- }
-}
-
-/* set a parameter to a string value */
-
-void setparm(char *s,char *t,int ex,int isint)
-{
-struct pmnode *pmn,*pmo;
-
- if (!strcmp(s,"RANDOM"))
- {
- srand((unsigned long) atol(t));
- return;
- }
- if (!strcmp(s,"SECONDS"))
- {
- shtimer = atol(t)+time(NULL);
- return;
- }
- if (ex && gethnode(s,parmhtab))
- freepm(remhnode(s,parmhtab));
- if (pmo = gethnode(s,parmhtab))
- {
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = pmo->isint | isint)
- {
- pmn->u.val = matheval(t);
- free(t);
- t = NULL;
- }
- else
- pmn->u.str = t;
- addhnode(s,pmn,parmhtab,freepm);
- }
- else if (ex || getenv(s) || (opts[ALLEXPORT] == OPT_SET))
- putenv(tricat(s,"=",t));
- else
- {
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = isint)
- {
- pmn->u.val = matheval(t);
- free(t);
- t = NULL;
- }
- else
- pmn->u.str = t;
- addhnode(s,pmn,parmhtab,freepm);
-#if 0
- addlocal(s);
-#endif
- }
- if (!t)
- return;
- if (!strcmp(s,"PATH"))
- parsepath();
- if (!strcmp(s,"CDPATH"))
- parsecdpath();
- if (!strcmp(s,"IFS"))
- {
- free(ifs);
- ifs = strdup(t);
- }
- if (!strcmp(s,"PERIOD"))
- {
- period = atoi(t)*60;
- lastperiod = time(NULL)+period;
- }
- if (!strcmp(s,"HISTSIZE"))
- {
- tevs = atoi(t);
- if (tevs <= 2)
- tevs = 2;
- }
- if (!strcmp(s,"HOME"))
- {
- free(home);
- home = xsymlink(t);
- }
- if (!strcmp(s,"MAIL") || !strcmp(s,"MAILCHECK") || !strcmp(s,"MAILPATH"))
- lastmailcheck = 0;
-}
-
-void unsetparm(char *s)
-{
-char **pp;
-
- if (!strcmp(s,"HOME"))
- return;
- if (!strcmp(s,"PERIOD"))
- period = 0;
- if (!strcmp(s,"HISTSIZE"))
- tevs = 1;
- if (gethnode(s,parmhtab))
- {
- freepm(remhnode(s,parmhtab));
- return;
- }
- for (pp = environ; *pp; pp++)
- if (!strncmp(*pp,s,strlen(s)) && (*pp)[strlen(s)] == '=')
- {
- while (pp[0] = pp[1])
- pp++;
- return;
- }
-}
-
-/* get the integer value of a parameter */
-
-long getiparm(char *s)
-{
-struct pmnode *pmn;
-char *t;
-
- if (!isalpha(*s) && !s[1])
- {
- t = getsparmval(s,1);
- return (t) ? atoi(t) : 0;
- }
- if (s[0] == 'T' && s[1] == 'C' && !s[4]) /* TCxx */
- return tgetnum(s+2);
- if (!strcmp(s,"RANDOM"))
- return rand() & 0x7fff;
- if (!strcmp(s,"LINENO"))
- return lineno;
- if (!strcmp(s,"SECONDS"))
- return time(NULL)-shtimer;
- if (pmn = gethnode(s,parmhtab))
- {
- if (pmn->isint)
- return pmn->u.val;
- return atol(pmn->u.str);
- }
- return atol(getenv(s));
-}
-
-/* get the string value of a parameter */
-
-char *getparm(char *s)
-{
-struct pmnode *pmn;
-
- if (!isalpha(*s) && !s[1])
- return getsparmval(s,1);
- if (s[0] == 'T' && s[1] == 'C' && !s[4]) /* TCxx */
- {
- static char buf[1024];
- char *ss = buf;
- int t0;
-
- if (tgetstr(s+2,&ss))
- return buf;
- if ((t0 = tgetnum(s+2)) != -1)
- {
- sprintf(buf,"%d",t0);
- return buf;
- }
- return NULL;
- }
- if (!strcmp(s,"LINENO"))
- {
- static char buf[8];
-
- sprintf(buf,"%d",lineno);
- return buf;
- }
- if (!strcmp(s,"RANDOM"))
- {
- static char buf[8];
-
- sprintf(buf,"%d",rand() & 0x7fff);
- return buf;
- }
- if (!strcmp(s,"SECONDS"))
- {
- static char buf[12];
-
- sprintf(buf,"%ld",time(NULL)-shtimer);
- return buf;
- }
- if (pmn = gethnode(s,parmhtab))
- {
- static char buf[12];
-
- if (pmn->isint)
- {
- sprintf(buf,"%ld",pmn->u.val);
- return buf;
- }
- return pmn->u.str;
- }
- return getenv(s);
-}
-
-/* parse the PATH parameter into directory names in a array of
- strings and create the command hash table */
-
-void parsepath(void)
-{
-char *pptr = getparm("PATH"),*ptr;
-
- if (path)
- {
- while(pathct)
- free(path[--pathct]);
- free(path);
- }
- for (pathct = 1, ptr = pptr; *ptr; ptr++)
- if (*ptr == ':')
- pathct++;
- path = (char **) zalloc(pathct*sizeof(char *));
- pathct = 0;
- ptr = pptr;
- while(pptr)
- {
- ptr = strchr(pptr,':');
- if (ptr)
- *ptr = '\0';
- path[pathct] = strdup(pptr);
- if (ptr)
- {
- *ptr = ':';
- pptr = ptr+1;
- }
- else
- pptr = NULL;
- if (!*path[pathct])
- {
- free(path[pathct]);
- path[pathct] = strdup(".");
- }
- pathsub(&path[pathct]);
- if (*path[pathct] != '/' && strcmp(path[pathct],"."))
- {
-#ifdef PATH_WARNINGS
- zerr("PATH component not absolute pathname: %s",path[pathct]);
-#endif
- free(path[pathct--]);
- }
- pathct++;
- }
- createchtab();
-}
-
-void parsecdpath(void)
-{
-char *pptr = getparm("CDPATH"),*ptr;
-
- if (cdpath)
- {
- while(cdpathct)
- free(cdpath[--cdpathct]);
- free(cdpath);
- }
- if (pptr == NULL)
- {
- cdpath = (char **) zalloc(sizeof(char *));
- cdpath[0] = strdup(".");
- cdpathct = 1;
- return;
- }
- for (cdpathct = 2, ptr = pptr; *ptr; ptr++)
- if (*ptr == ':')
- cdpathct++;
- cdpath = (char **) zalloc(cdpathct*sizeof(char *));
- cdpath[0] = strdup(".");
- cdpathct = 1;
- ptr = pptr;
- while (pptr)
- {
- ptr = strchr(pptr,':');
- if (ptr)
- *ptr = '\0';
- cdpath[cdpathct] = strdup(pptr);
- if (ptr)
- {
- *ptr = ':';
- pptr = ptr+1;
- }
- else
- pptr = NULL;
- pathsub(&cdpath[cdpathct]);
- if (*cdpath[cdpathct] != '/')
- {
-#ifdef PATH_WARNINGS
- zerr("CDPATH component not absolute pathname: %s",cdpath[cdpathct]);
-#endif
- free(cdpath[cdpathct--]);
- }
- cdpathct++;
- }
-}
-
-/* source a file */
-
-int source(char *s)
-{
-int fd,cj = curjob,iact = opts[INTERACTIVE];
-FILE *obshin = bshin;
-
- fd = SHIN;
- opts[INTERACTIVE] = OPT_UNSET;
- if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
- {
- SHIN = fd;
- curjob = cj;
- opts[INTERACTIVE] = iact;
- return 1;
- }
- bshin = fdopen(SHIN,"r");
- loop();
- fclose(bshin);
- opts[INTERACTIVE] = iact;
- bshin = obshin;
- SHIN = fd;
- peek = EMPTY;
- curjob = cj;
- errflag = 0;
- retflag = 0;
- return 0;
-}
-
-/* try to source a file in our home directory */
-
-void sourcehome(char *s)
-{
-char buf[MAXPATHLEN];
-
- sprintf(buf,"%s/%s",getparm("HOME"),s);
- (void) source(buf);
-}
-
-/* print an error */
-
-void zerrnam(char *cmd, char *fmt, ...)
-{
-va_list ap;
-char *str;
-int num;
-
- va_start(ap,fmt);
- fputs(cmd,stderr);
- putc(':',stderr);
- putc(' ',stderr);
- while (*fmt)
- if (*fmt == '%')
- {
- fmt++;
- switch(*fmt++)
- {
- case 's': /* string */
- str = va_arg(ap,char *);
- while (*str)
- niceputc(*str++,stderr);
- break;
- case 'l': /* string with a length */
- num = va_arg(ap,int);
- str = va_arg(ap,char *);
- while (num--)
- niceputc(*str++,stderr);
- break;
- case 'd': /* number */
- num = va_arg(ap,int);
- fprintf(stderr,"%d",num);
- break;
- case '%':
- putc('%',stderr);
- break;
- case 'c': /* char */
- num = va_arg(ap,int);
- niceputc(num,stderr);
- break;
- case 'e': /* system error */
- num = va_arg(ap,int);
- if (num == EINTR)
- {
- fputs("interrupt\n",stderr);
- errflag = 1;
- return;
- }
- fputc(tolower(sys_errlist[num][0]),stderr);
- fputs(sys_errlist[num]+1,stderr);
- break;
- }
- }
- else
- putc(*fmt++,stderr);
- putc('\n',stderr);
- va_end(ap);
-}
-
-void zerr(char *fmt,...)
-{
-va_list ap;
-char *str;
-int num;
-
- va_start(ap,fmt);
- fputs("zsh: ",stderr);
- while (*fmt)
- if (*fmt == '%')
- {
- fmt++;
- switch(*fmt++)
- {
- case 's':
- str = va_arg(ap,char *);
- while (*str)
- niceputc(*str++,stderr);
- break;
- case 'l':
- num = va_arg(ap,int);
- str = va_arg(ap,char *);
- while (num--)
- niceputc(*str++,stderr);
- break;
- case 'd':
- num = va_arg(ap,int);
- fprintf(stderr,"%d",num);
- break;
- case '%':
- putc('%',stderr);
- break;
- case 'c':
- num = va_arg(ap,int);
- niceputc(num,stderr);
- break;
- case 'e':
- num = va_arg(ap,int);
- if (num == EINTR)
- {
- fputs("interrupt\n",stderr);
- errflag = 1;
- return;
- }
- fputc(tolower(sys_errlist[num][0]),stderr);
- fputs(sys_errlist[num]+1,stderr);
- break;
- }
- }
- else
- putc(*fmt++,stderr);
- putc('\n',stderr);
- va_end(ap);
-}
-
-void niceputc(int c,FILE *f)
-{
- if (istok(c))
- {
- if (c >= Pound && c <= Qtick)
- putc(tokens[c-Pound],f);
- return;
- }
- c &= 0x7f;
- if (c >= ' ' && c < '\x7f')
- putc(c,f);
- else if (c == '\n')
- {
- putc('\\',f);
- putc('n',f);
- }
- else
- {
- putc('^',f);
- putc(c|'A',f);
- }
-}
-
-/* enable ^C interrupts */
-
-void intr(void)
-{
-struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
-
- if (interact)
- sigvec(SIGINT,&vec,NULL);
- sigsetmask(0);
-}
-
-void noholdintr(void)
-{
- intr();
-}
-
-void holdintr(void)
-{
-struct sigvec vec = { handler,sigmask(SIGINT),0 };
-
- if (interact)
- {
- sigvec(SIGINT,&vec,NULL);
- sigsetmask(0);
- }
-}
-
-char *fgetline(char *buf,int len,FILE *in)
-{
- if (!fgets(buf,len,in))
- return NULL;
- buf[len] = '\0';
- buf[strlen(buf)-1] = '\0';
- return buf;
-}
-
-/* get a symlink-free pathname for s relative to PWD */
-
-char *findcwd(char *s)
-{
-char *t;
-
- if (*s == '/')
- return xsymlink(s);
- s = tricat((cwd[1]) ? cwd : "","/",s);
- t = xsymlink(s);
- free(s);
- return t;
-}
-
-static char xbuf[MAXPATHLEN];
-
-/* expand symlinks in s, and remove other weird things */
-
-char *xsymlink(char *s)
-{
- if (*s != '/')
- return NULL;
- strcpy(xbuf,"");
- if (xsymlinks(s+1))
- return strdup(s);
- if (!*xbuf)
- return strdup("/");
- return strdup(xbuf);
-}
-
-char **slashsplit(char *s)
-{
-char *t,**r,**q;
-int t0;
-
- if (!*s)
- return (char **) calloc(sizeof(char **),1);
- for (t = s, t0 = 0; *t; t++)
- if (*t == '/')
- t0++;
- q = r = (char **) zalloc(sizeof(char **)*(t0+2));
- while (t = strchr(s,'/'))
- {
- *t = '\0';
- *q++ = strdup(s);
- *t = '/';
- while (*t == '/')
- t++;
- if (!*t)
- {
- *q = NULL;
- return r;
- }
- s = t;
- }
- *q++ = strdup(s);
- *q = NULL;
- return r;
-}
-
-int islink(char *s)
-{
-char xbuf[MAXPATHLEN];
-
- if (readlink(s,xbuf,1) == -1 && errno == EINVAL)
- return 0;
- return 1;
-}
-
-int xsymlinks(char *s)
-{
-char **pp,**opp;
-char xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
-int t0;
-
- opp = pp = slashsplit(s);
- for (; *pp; pp++)
- {
- if (!strcmp(*pp,"."))
- {
- free(*pp);
- continue;
- }
- if (!strcmp(*pp,".."))
- {
- char *p;
-
- free(*pp);
- if (!strcmp(xbuf,"/"))
- continue;
- p = xbuf+strlen(xbuf);
- while (*--p != '/');
- *p = '\0';
- continue;
- }
- sprintf(xbuf2,"%s/%s",xbuf,*pp);
- t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
- if (t0 == -1)
- {
- if (errno != EINVAL)
- {
- while (*pp)
- free(*pp++);
- free(opp);
- return 1;
- }
- strcat(xbuf,"/");
- strcat(xbuf,*pp);
- free(*pp);
- }
- else
- {
- xbuf3[t0] = '\0'; /* STUPID */
- if (*xbuf3 == '/')
- {
- strcpy(xbuf,"");
- if (xsymlinks(xbuf3+1))
- return 1;
- }
- else
- if (xsymlinks(xbuf3))
- return 1;
- free(*pp);
- }
- }
- free(opp);
- return 0;
-}
-
-void printdir(char *s)
-{
-int t0;
-
- if (!strncmp(s,home,t0 = strlen(home)))
- {
- putchar('~');
- fputs(s+t0,stdout);
- }
- else
- fputs(s,stdout);
-}
-
-
-int ddifftime(time_t t1,time_t t2)
-{
- return ((long) t2-(long) t1);
-}
-
-/* see if jobs need printing */
-
-void scanjobs(void)
-{
-int t0;
-
- for (t0 = 1; t0 != MAXJOB; t0++)
- if (jobtab[t0].stat & STAT_CHANGED)
- printjob(jobtab+t0,0);
-}
-
-/* do pre-prompt stuff */
-
-void preprompt(void)
-{
-int diff;
-list list;
-char *mc = getparm("MAILCHECK"),*wc = getparm("LOGCHECK");
-struct schnode *sch,*schl;
-
- if (unset(NOTIFY))
- scanjobs();
- if (errflag)
- return;
- if (list = gethnode("precmd",shfunchtab))
- newrunlist(list);
- if (errflag)
- return;
- if (period && (time(NULL) > lastperiod+period) &&
- (list = gethnode("periodic",shfunchtab)))
- {
- newrunlist(list);
- lastperiod = time(NULL);
- }
- if (errflag)
- return;
- if (getparm("WATCH"))
- {
- diff = (int) ddifftime(lastwatch,time(NULL));
- if (diff > ((wc) ? atoi(wc)*60 : 300))
- {
- lastwatch = time(NULL);
- watch();
- }
- }
- if (errflag)
- return;
- diff = (int) ddifftime(lastmailcheck,time(NULL));
- if (diff > ((mc) ? atoi(mc) : 60))
- {
- lastmailcheck = time(NULL);
- if (getparm("MAILPATH"))
- checkmailpath();
- else
- checkmail();
- }
- for (schl = (struct schnode *) &scheds, sch = scheds; sch;
- sch = (schl = sch)->next)
- {
- if (sch->time < time(NULL))
- {
- execstring(sch->cmd);
- schl->next = sch->next;
- free(sch);
- }
- if (errflag)
- return;
- }
-}
-
-void checkmail(void)
-{
-struct stat st;
-char *s;
-
- if (!(s = getparm("MAIL")))
- return;
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- lastmailval = 0;
- lastmailsize = 0;
- return;
- }
- else
- if (lastmailval != -1 && lastmailval < st.st_mtime &&
- lastmailsize < st.st_size)
- zerr("you have new mail.");
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
-}
-
-void checkfirstmail(void)
-{
-struct stat st;
-char *s;
-
- if (!(s = getparm("MAIL")))
- return;
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- lastmailval = 0;
- lastmailsize = 0;
- return;
- }
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
- zerr("you have mail.");
-}
-
-void checkmailpath(void)
-{
-struct stat st;
-char *s = getparm("MAILPATH"),*v,*u,c,d;
-
- for (;;)
- {
- for (v = s; *v && *v != '?' && *v != ':'; v++);
- c = *v;
- *v = '\0';
- if (c != '?')
- u = NULL;
- else
- {
- for (u = v+1; *u && *u != ':'; u++);
- d = *u;
- *u = '\0';
- }
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- }
- else
- if (lastmailval != -1 && lastmailval < st.st_mtime &&
- lastmailsize < st.st_size)
- if (!u)
- fprintf(stderr,"You have new mail.\n");
- else
- {
- char *z = u;
-
- while (*z)
- if (*z == '$' && z[1] == '_')
- {
- fprintf(stderr,"%s",s);
- z += 2;
- }
- else
- fputc(*z++,stderr);
- fputc('\n',stderr);
- }
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
- *v = c;
- if (u)
- *u = d;
- if (!c || (u && !d))
- break;
- v = (u) ? u+1 : v+1;
- }
-}
-
-/* create command hash table */
-
-void createchtab(void)
-{
-int t0,dot = 0;
-struct direct *de;
-DIR *dir;
-struct chnode *cc;
-
- holdintr();
- if (chtab)
- freehtab(chtab,freechnode);
- chtab = newhtable(101);
- for (t0 = 0; t0 != pathct; t0++)
- if (!strcmp(".",path[t0]))
- {
- dot = 1;
- break;
- }
- for (t0 = pathct-1; t0 >= 0; t0--)
- if (!strcmp(".",path[t0]))
- dot = 0;
- else
- {
- dir = opendir(path[t0]);
- if (!dir)
- {
- zerr("%e: %s",errno,path[t0]);
- continue;
- }
- readdir(dir); readdir(dir);
- while (de = readdir(dir))
- {
- cc = alloc(sizeof(struct chnode));
- cc->type = (dot) ? EXCMD_POSTDOT : EXCMD_PREDOT;
- cc->globstat = GLOB;
- cc->u.nam = tricat(path[t0],"/",de->d_name);
- addhnode(strdup(de->d_name),cc,chtab,freechnode);
- }
- closedir(dir);
- }
- addintern(chtab);
- noholdintr();
-}
-
-void freechnode(void *a)
-{
-struct chnode *c = (struct chnode *) a;
-
- if (c->type != BUILTIN)
- free(c->u.nam);
- free(c);
-}
-
-void freestr(void *a)
-{
- free(a);
-}
-
-void freeanode(void *a)
-{
-struct anode *c = (struct anode *) a;
-
- free(c->text);
- free(c);
-}
-
-void freeredir(void *a)
-{
-struct fnode *f = (struct fnode *) a;
-
- if (f)
- {
- if (f->type == HEREDOC)
- close(f->u.fd2);
- else
- free(f->u.name);
- free(f);
- }
-}
-
-void freeshfunc(void *a)
-{
- freelist((list) a);
-}
-
-void freepm(void *a)
-{
-struct pmnode *pm = a;
-
- if (!pm->isint)
- free(pm->u.str);
- free(pm);
-}
-
-void restoretty(void)
-{
- settyinfo(&shttyinfo);
-}
-
-void gettyinfo(struct ttyinfo *ti)
-{
- if (jobbing)
- {
-#ifndef BUGGY_GCC
-#ifdef TERMIOS
- ioctl(SHTTY,TCGETS,&ti->termios);
-#else
- ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
- ioctl(SHTTY,TIOCGETC,&ti->tchars);
- ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
-#endif
- ioctl(SHTTY,TIOCGWINSZ,&ti->winsize);
-#else
-#ifdef TERMIOS
- ioctl(SHTTY, ( 0x40000000 |((sizeof( struct termios)&0xff )<<16)|('T'<<8)| 8) ,&ti->termios);
-#else
- ioctl(SHTTY,(0x40000000|((sizeof(struct sgttyb)&0x1fff)<<16)|
- ('t'<<8)|8),&ti->sgttyb);
- ioctl(SHTTY,(0x40000000|((sizeof(struct tchars)&0x1fff)<<16)|
- ('t'<<8)|18),&ti->tchars);
- ioctl(SHTTY,(0x40000000|((sizeof(struct ltchars)&0x1fff)<<16)|
- ('t'<<8)|116),&ti->ltchars);
-#endif
- ioctl(SHTTY,( 0x40000000 |((sizeof( struct winsize)&0xff )<<16)|('t'<<8)| 104) ,&ti->winsize);
-#endif
- }
-}
-
-void settyinfo(struct ttyinfo *ti)
-{
- if (jobbing)
- {
-#ifndef BUGGY_GCC
-#ifdef TERMIOS
- ioctl(SHTTY,TCSETS,&ti->termios);
-#else
- ioctl(SHTTY,TIOCSETP,&ti->sgttyb);
- ioctl(SHTTY,TIOCSETC,&ti->tchars);
- ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
-#endif
- ioctl(SHTTY,TIOCSWINSZ,&ti->winsize);
-#else
-#ifdef TERMIOS
- ioctl(SHTTY, ( 0x80000000 |((sizeof( struct termios)&0xff )<<16)|('T'<<8)| 9) ,&ti->termios);
-#else
- ioctl(SHTTY,(0x80000000|((sizeof( struct sgttyb)&0x1fff)<<16)|
- ('t'<<8)|9),&ti->sgttyb);
- ioctl(SHTTY,(0x80000000|((sizeof(struct tchars)&0x1fff)<<16)|
- ('t'<<8)|17),&ti->tchars);
- ioctl(SHTTY,(0x80000000|((sizeof(struct ltchars)&0x1fff)<<16)|
- ('t'<<8)|117),&ti->ltchars);
-#endif
- ioctl(SHTTY,( 0x80000000 |((sizeof( struct winsize)&0xff )<<16)|('t'<<8)| 103) ,&ti->winsize);
-#endif
- }
-}
-
-int zyztem(char *s,char *t)
-{
-#ifdef WAITPID
-int pid,statusp;
-
- if (!(pid = fork()))
- {
- s = tricat(s," ",t);
- execl("/bin/sh","sh","-c",s,(char *) 0);
- _exit(1);
- }
- waitpid(pid,&statusp,WUNTRACED);
- if (WIFEXITED(SP(statusp)))
- return WEXITSTATUS(SP(statusp));
- return 1;
-#else
- if (!waitfork())
- {
- s = tricat(s," ",t);
- execl("/bin/sh","sh","-c",s,(char *) 0);
- _exit(1);
- }
- return 0;
-#endif
-}
-
-#ifndef WAITPID
-
-/* fork a process and wait for it to complete without confusing
- the SIGCHLD handler */
-
-int waitfork(void)
-{
-int pipes[2];
-char x;
-
- pipe(pipes);
- if (!fork())
- {
- close(pipes[0]);
- signal(SIGCHLD,SIG_DFL);
- if (!fork())
- return 0;
- wait(NULL);
- _exit(0);
- }
- close(pipes[1]);
- read(pipes[0],&x,1);
- close(pipes[0]);
- return 1;
-}
-
-#endif
-
-/* move a fd to a place >= 10 */
-
-int movefd(int fd)
-{
-int fe;
-
- if (fd == -1)
- return fd;
- if ((fe = dup(fd)) < 10)
- fe = movefd(fe);
- close(fd);
- return fe;
-}
-
-/* move fd x to y */
-
-void redup(int x,int y)
-{
- if (x != y)
- {
- dup2(x,y);
- close(x);
- }
-}
-
-void settrap(char *s,int empty)
-{
-int t0;
-
- if (strncmp(s,"TRAP",4))
- return;
- for (t0 = 0; t0 != SIGCOUNT+2; t0++)
- if (!strcmp(s+4,sigs[t0]))
- {
- if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
- || t0 == SIGPIPE))
- {
- zerr("can't trap SIG%s in interactive shells",s);
- return;
- }
- if (empty)
- {
- sigtrapped[t0] = 2;
- if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
- {
- signal(t0,SIG_IGN);
- sigtrapped[t0] = 2;
- }
- }
- else
- {
- if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
- signal(t0,handler);
- sigtrapped[t0] = 1;
- }
- return;
---cut here---cut here---cut here---
More information about the Alt.sources
mailing list