v18i088: zsh2.00 - The Z shell, Part05/15
Paul Falstad
pfalstad at phoenix.princeton.edu
Wed Apr 24 13:03:52 AEST 1991
Submitted-by: Paul Falstad <pfalstad at phoenix.princeton.edu>
Posting-number: Volume 18, Issue 88
Archive-name: zsh2.00/part05
#!/bin/sh
# this is zsh2.00.00.shar.05 (part 5 of zsh2.00.00)
# do not concatenate these parts, unpack them in order with /bin/sh
# file zsh2.00/src/cond.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 5; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping zsh2.00/src/cond.c'
else
echo 'x - continuing file zsh2.00/src/cond.c'
sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.00/src/cond.c' &&
X
X cond.c - evaluate conditional expressions
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#include "funcs.h"
X
X#ifndef F_OK
X#define F_OK 00
X#define R_OK 04
X#define W_OK 02
X#define X_OK 01
X#endif
X
Xint evalcond(c) /**/
XCond c;
X{
Xstruct stat *st;
X
X switch (c->type)
X {
X case COND_NOT: return !evalcond(c->left);
X case COND_AND: return evalcond(c->left) && evalcond(c->right);
X case COND_OR: return evalcond(c->left) || evalcond(c->right);
X }
X singsub((char **) &c->left);
X if (c->right)
X singsub((char **) &c->right);
X switch (c->type)
X {
X case COND_STREQ: return matchpat(c->left,c->right);
X case COND_STRNEQ: return !matchpat(c->left,c->right);
X case COND_STRLT: return strcmp(c->left,c->right) < 0;
X case COND_STRGTR: return strcmp(c->left,c->right) > 0;
X case 'a': return(doaccess(c->left,F_OK));
X case 'b': return(S_ISBLK(dostat(c->left)));
X case 'c': return(S_ISCHR(dostat(c->left)));
X case 'd': return(S_ISDIR(dostat(c->left)));
X case 'f': return(S_ISREG(dostat(c->left)));
X case 'g': return(!!(dostat(c->left) & S_ISGID));
X case 'k': return(!!(dostat(c->left) & S_ISVTX));
X case 'n': return(!strlen(c->left));
X case 'o': return(optison(c->left));
X case 'p': return(S_ISFIFO(dostat(c->left)));
X case 'r': return(doaccess(c->left,R_OK));
X case 's': return((st = getstat(c->left)) && !!(st->st_size));
X case 'S': return(S_ISSOCK(dostat(c->left)));
X case 'u': return(!!(dostat(c->left) & S_ISUID));
X case 'w': return(doaccess(c->left,W_OK));
X case 'x': return(doaccess(c->left,X_OK));
X case 'z': return(!!strlen(c->left));
X case 'L': return(S_ISLNK(dostat(c->left)));
X case 'O': return((st = getstat(c->left)) && st->st_uid == geteuid());
X case 'G': return((st = getstat(c->left)) && st->st_gid == getegid());
X case 't': return isatty(matheval(c->left));
X case COND_EQ: return matheval(c->left) == matheval(c->right);
X case COND_NE: return matheval(c->left) != matheval(c->right);
X case COND_LT: return matheval(c->left) < matheval(c->right);
X case COND_GT: return matheval(c->left) > matheval(c->right);
X case COND_LE: return matheval(c->left) <= matheval(c->right);
X case COND_GE: return matheval(c->left) >= matheval(c->right);
X case COND_NT: case COND_OT:
X {
X time_t a;
X if (!(st = getstat(c->left)))
X return 0;
X a = st->st_mtime;
X if (!(st = getstat(c->right)))
X return 0;
X return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
X }
X case COND_EF:
X {
X dev_t d;
X ino_t i;
X
X if (!(st = getstat(c->left)))
X return 0;
X d = st->st_dev;
X i = st->st_ino;
X if (!(st = getstat(c->right)))
X return 0;
X return d == st->st_dev && i == st->st_ino;
X }
X default: zerr("bad cond structure",NULL,0);
X }
X return 0;
X}
X
Xint doaccess(s,c) /**/
Xchar *s;int c;
X{
X return !access(s,c);
X}
X
Xstruct stat *getstat(s) /**/
Xchar *s;
X{
Xstatic struct stat st;
X
X if (!strncmp(s,"/dev/fd/",8))
X {
X if (fstat(atoi(s+8),&st))
X return NULL;
X }
X else if (lstat(s,&st))
X return NULL;
X return &st;
X}
X
Xunsigned short dostat(s) /**/
Xchar *s;
X{
Xstruct stat *st;
X
X if (!(st = getstat(s)))
X return 0;
X return st->st_mode;
X}
X
Xint optison(s) /**/
Xchar *s;
X{
Xint i;
X
X if (strlen(s) == 1)
X return opts[*s];
X if ((i = optlookup(s)) != -1)
X return opts[i];
X zerr("no such option: %s",s,0);
X return 0;
X}
X
SHAR_EOF
echo 'File zsh2.00/src/cond.c is complete' &&
chmod 0644 zsh2.00/src/cond.c ||
echo 'restore of zsh2.00/src/cond.c failed'
Wc_c="`wc -c < 'zsh2.00/src/cond.c'`"
test 4322 -eq "$Wc_c" ||
echo 'zsh2.00/src/cond.c: original size 4322, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/cond.pro ==============
if test -f 'zsh2.00/src/cond.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.00/src/cond.pro (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/cond.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/cond.pro' &&
Xint evalcond DCLPROTO((Cond c));
Xint doaccess DCLPROTO((char *s,int c));
Xstruct stat *getstat DCLPROTO((char *s));
Xunsigned short dostat DCLPROTO((char *s));
Xint optison DCLPROTO((char *s));
SHAR_EOF
chmod 0644 zsh2.00/src/cond.pro ||
echo 'restore of zsh2.00/src/cond.pro failed'
Wc_c="`wc -c < 'zsh2.00/src/cond.pro'`"
test 191 -eq "$Wc_c" ||
echo 'zsh2.00/src/cond.pro: original size 191, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/exec.c ==============
if test -f 'zsh2.00/src/exec.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.00/src/exec.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/exec.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/exec.c' &&
X/*
X
X exec.c - command execution
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#include "funcs.h"
X#include <sys/errno.h>
X#include <sys/dir.h>
X
X#define execerr() { if (forked) exit(1); \
X closemnodes(mfds); errflag = 1; return; }
X
X/* parse list in a string */
X
XList parselstring(s) /**/
Xchar *s;
X{
XList l;
X
X hungets(s);
X strinbeg();
X pushheap();
X if (!(l = parlist()))
X {
X strinend();
X hflush();
X popheap();
X return NULL;
X }
X strinend();
X return l;
X}
X
X/* execute a string */
X
Xvoid execstring(s) /**/
Xchar *s;
X{
XList l;
X
X if (l = parselstring(s))
X {
X execlist(l);
X popheap();
X }
X}
X
X/* duplicate a list and run it */
X
Xvoid newrunlist(l) /**/
XList l;
X{
X List a = dupstruct(l); runlist(a);
X}
X
X/* fork and set limits */
X
Xint phork() /**/
X{
Xint pid = fork(),t0;
X
X if (pid == -1)
X {
X zerr("fork failed: %e",NULL,errno);
X return -1;
X }
X if (!pid)
X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
X setrlimit(t0,limits+t0);
X return pid;
X}
X
X/* execute a current shell command */
X
Xint execcursh(cmd) /**/
XCmd cmd;
X{
X runlist(cmd->u.list);
X cmd->u.list = NULL;
X return lastval;
X}
X
X/* execve after handling $_ and #! */
X
Xvoid zexecve(pth,argv,ee,b1,b2) /**/
Xchar *pth;char **argv;int *ee;char *b1;char *b2;
X{
Xint eno;
Xchar buf[MAXPATHLEN*2];
Xchar **eep;
X
X for (eep = environ; *eep; eep++)
X if (**eep == '_' && (*eep)[1] == '=')
X break;
X buf[0] = '_';
X buf[1] = '=';
X if (*pth == '/')
X strcpy(buf+2,pth);
X else
X sprintf(buf+2,"%s/%s",cwd,pth);
X if (!*eep)
X eep[1] = NULL;
X *eep = buf;
X execve(pth,argv,environ);
X if ((eno = errno) == ENOEXEC)
X {
X char buf[33],*ptr,*ptr2,*argv0;
X int fd,ct,t0;
X
X if ((fd = open(pth,O_RDONLY)) >= 0)
X {
X argv0 = *argv;
X *argv = pth;
X ct = read(fd,buf,32);
X close(fd);
X if (ct > 0)
X {
X if (buf[0] == '#')
X if (buf[1] == '!')
X {
X for (t0 = 0; t0 != ct; t0++)
X if (buf[t0] == '\n')
X buf[t0] = '\0';
X buf[32] = '\0';
X for (ptr = buf+2; *ptr && *ptr == ' '; ptr++);
X for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++);
X if (*ptr)
X {
X *ptr = '\0';
X argv[-2] = ptr2;
X argv[-1] = ptr+1;
X execve(ptr2,argv-2,environ);
X }
X else
X {
X argv[-1] = ptr2;
X execve(ptr2,argv-1,environ);
X }
X }
X else
X {
X argv[-1] = MYSELF;
X execve(MYSELF,argv-1,environ);
X }
X else
X {
X for (t0 = 0; t0 != ct; t0++)
X if (!buf[t0])
X break;
X if (t0 == ct)
X {
X argv[-1] = "/bin/sh";
X execve("/bin/sh",argv-1,environ);
X }
X }
X }
X else
X eno = errno;
X *argv = argv0;
X }
X else
X eno = errno;
X }
X if (ee && eno != ENOENT)
X {
X *ee = eno;
X strcpy(b1,b2);
X }
X}
X
X#define MAXCMDLEN (MAXPATHLEN*4)
X
X/* execute an external command */
X
Xvoid execute(args,dash) /**/
XLklist args;int dash;
X{
Xchar **argv,*arg0;
Xchar *z,*s,buf[MAXCMDLEN],buf2[MAXCMDLEN];
XCmdnam cn;
Xint tl,ee = 0;
X
X cn = gethnode(peekfirst(args),cmdnamtab);
X if (s = zgetenv("STTY"))
X zyztem("stty",s);
X arg0 = peekfirst(args);
X if (z = zgetenv("ARGV0"))
X {
X setdata(firstnode(args),ztrdup(z));
X delenv(z-6);
X }
X else if (dash)
X {
X sprintf(buf2,"-%s",arg0);
X setdata(firstnode(args),ztrdup(buf2));
X }
X argv = makecline(args);
X fixsigs();
X if (cn && (cn->type != BUILTIN && cn->type != SHFUNC))
X {
X if (cn->type == EXCMD_POSTDOT)
X zexecve(arg0,argv,&ee,buf2,buf);
X zexecve(cn->u.nam,argv,&ee,buf2,buf);
X }
X for (s = arg0; *s; s++)
X if (*s == '/')
X {
X zexecve(arg0,argv,NULL,NULL,NULL);
X if (arg0 == s || unset(PATHDIRS))
X {
X zerr("%e: %s",arg0,errno);
X _exit(1);
X }
X break;
X }
X for (; *path; path++)
X if ((*path)[0] == '.' && !(*path)[1])
X zexecve(arg0,argv,&ee,buf2,buf);
X else
X {
X tl = strlen(*path);
X strcpy(buf,*path);
X buf[tl] = '/';
X if (strlen(arg0)+strlen(buf)+1 >= MAXCMDLEN)
X {
X zerr("command too long: %s",arg0,0);
X _exit(1);
X }
X strcpy(buf+tl+1,arg0);
X zexecve(buf,argv,&ee,buf2,buf);
X }
X if (ee)
X {
X zerr("%e: %s",arg0,ee);
X _exit(1);
X }
X zerr("command not found: %s",arg0,0);
X _exit(1);
X}
X
X#define try(X) { if (!access(X,X_OK)) return ztrdup(X); }
X
X/* get the pathname of a command */
X
Xchar *findcmd(arg0) /**/
Xchar *arg0;
X{
Xchar *s,buf[MAXPATHLEN];
Xint tl;
Xstruct cmdnam *cn = gethnode(arg0,cmdnamtab);
Xchar **pp = path;
X
X if (cn && (cn->type == EXCMD_POSTDOT || cn->type == EXCMD_PREDOT))
X {
X if (cn->type == EXCMD_POSTDOT)
X {
X strcpy(buf,"./");
X strcat(buf,arg0);
X try(buf);
X }
X try(cn->u.nam);
X }
X for (s = arg0; *s; s++)
X if (*s == '/')
X {
X try(arg0);
X if (s == arg0 || unset(PATHDIRS))
X goto failed;
X break;
X }
X for (; *pp; pp++)
X if (**pp == '.')
X {
X strcpy(buf,"./");
X strcat(buf,arg0);
X try(buf);
X }
X else
X {
X tl = strlen(*pp);
X strcpy(buf,*pp);
X buf[tl] = '/';
X strcpy(buf+tl+1,arg0);
X try(buf);
X }
Xfailed:
X return NULL;
X}
X
Xvoid execlist(list) /**/
XList list;
X{
X if (breaks)
X return;
X simplifyright(list);
X switch(list->type)
X {
X case SYNC:
X case ASYNC:
X execlist2(list->left,list->type,!list->right);
X if (sigtrapped[SIGDEBUG])
X dotrap(SIGDEBUG);
X if (sigtrapped[SIGERR] && lastval)
X dotrap(SIGERR);
X if (list->right && !retflag)
X execlist(list->right);
X break;
X }
X}
X
Xvoid execlist2(list,type,last1) /**/
XSublist list;int type;int last1;
X{
X switch(list->type)
X {
X case END:
X execpline(list,type,last1);
X break;
X case ORNEXT:
X if (!execpline(list,SYNC,0))
X execlist2(list->right,type,last1);
X break;
X case ANDNEXT:
X if (execpline(list,SYNC,0))
X execlist2(list->right,type,last1);
X break;
X }
X}
X
Xint execpline(l,how,last1) /**/
XSublist l;int how;int last1;
X{
Xint ipipe[2],opipe[2];
X
X ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
X sigblock(sigmask(SIGCHLD));
X if ((thisjob = getfreejob()) == -1)
X return 1;
X initjob();
X if (how == TIMED)
X {
X jobtab[thisjob].stat |= STAT_TIMED;
X how = SYNC;
X }
X if (l->flags & PFLAG_COPROC)
X {
X how = ASYNC;
X mpipe(ipipe);
X mpipe(opipe);
X if (coprocin)
X {
X close(coprocin);
X close(coprocout);
X }
X coprocin = ipipe[0];
X coprocout = opipe[1];
X }
X execpline2(l->left,how,opipe[0],ipipe[1],last1);
X if (how == ASYNC)
X {
X spawnjob();
X sigsetmask(0);
X return 1;
X }
X else
X {
X waitjobs();
X sigsetmask(0);
X if (l->flags & PFLAG_NOT)
X lastval = !lastval;
X return !lastval;
X }
X}
X
Xvoid execpline2(pline,how,input,output,last1) /**/
XPline pline;int how;int input;int output;int last1;
X{
Xint pid;
Xint pipes[2];
X
X if (breaks)
X return;
X if (!pline)
X return;
X if (pline->type == END)
X {
X execcmd(pline->left,input,output,how==ASYNC,last1);
X pline->left = NULL;
X }
X else
X {
X mpipe(pipes);
X
X /* if we are doing "foo | bar" where foo is a current
X shell command, do foo in the current shell and do
X the rest of the pipeline in a subshell. */
X
X if (pline->left->type >= CURSH && how == SYNC)
X {
X if (!(pid = fork()))
X {
X close(pipes[1]);
X entersubsh(1);
X exiting = 1;
X execpline2(pline->right,ASYNC,pipes[0],output,1);
X _exit(lastval);
X }
X else if (pid == -1)
X zerr("fork failed: %e",NULL,errno);
X else
X {
X char *s,*text;
X
X close(pipes[0]);
X text = s = gettext((void *) pline->right,0);
X addproc(pid,text)->lastfg = 1;
X pline->right = NULL;
X }
X }
X
X /* otherwise just do the pipeline normally. */
X
X execcmd(pline->left,input,pipes[1],how==ASYNC,0);
X pline->left = NULL;
X close(pipes[1]);
X if (pline->right)
X {
X execpline2(pline->right,how,pipes[0],output,last1);
X close(pipes[0]);
X }
X }
X}
X
X/* make the argv array */
X
Xchar **makecline(list) /**/
Xstruct lklist *list;
X{
Xint ct = 0;
XLknode node;
Xchar **argv,**ptr;
X
X if (isset(XTRACE))
X {
X fprintf(stderr,"%s",(prompt4) ? prompt4 : "");
X for (node = firstnode(list); node; incnode(node),ct++);
X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
X for (node = firstnode(list); node; incnode(node))
X if (*(char *) getdata(node))
X {
X *ptr++ = getdata(node);
X untokenize(getdata(node));
X fputs(getdata(node),stderr);
X if (nextnode(node))
X fputc(' ',stderr);
X }
X *ptr = NULL;
X fputc('\n',stderr);
X fflush(stderr);
X return(argv);
X }
X else
X {
X for (node = firstnode(list); node; incnode(node),ct++);
X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
X for (node = firstnode(list); node; incnode(node))
X if (*(char *) getdata(node))
X {
X *ptr++ = getdata(node);
X untokenize(getdata(node));
X }
X *ptr = NULL;
X return(argv);
X }
X}
X
X/* untokenize the command line and remove null arguments */
X
Xvoid fixcline(l) /**/
XLklist l;
X{
XLknode node,next;
X
X for (node = firstnode(l); node; node = next)
X {
X next = nextnode(node);
X if (*(char *) getdata(node))
X untokenize(getdata(node));
X else
X uremnode(l,node);
X }
X}
X
Xvoid untokenize(s) /**/
Xchar *s;
X{
X for (; *s; s++)
X if (itok(*s))
X if (*s == Nularg)
X chuck(s--);
X else
X *s = ztokens[*s-Pound];
X}
X
X/* nonzero if we shouldn't clobber a file */
X
Xint dontclob(f) /**/
Xstruct redir *f;
X{
Xstruct stat buf;
X
X if (unset(NOCLOBBER) || f->type & 1)
X return 0;
X if (stat(f->name,&buf) == -1)
X return 1;
X return S_ISREG(buf.st_mode);
X}
X
X/* close an multio (success) */
X
Xvoid closemn(mfds,fd) /**/
Xstruct multio **mfds;int fd;
X{
X if (mfds[fd])
X {
X if (mfds[fd]->ct > 1)
X if (mfds[fd]->rflag == 0)
X catproc(mfds[fd]);
X else
X teeproc(mfds[fd]);
X mfds[fd] = NULL;
X }
X}
X
X/* close all the mnodes (failure) */
X
Xvoid closemnodes(mfds) /**/
Xstruct multio **mfds;
X{
Xint t0,t1;
X
X for (t0 = 0; t0 != 10; t0++)
X if (mfds[t0])
X {
X for (t1 = 0; t1 != mfds[t0]->ct; t1++)
X close(mfds[t0]->fds[t1]);
X mfds[t0] = NULL;
X }
X}
X
X/* add a fd to an multio */
X/* an multio is a list of fds associated with a certain fd.
X thus if you do "foo >bar >ble", the multio for fd 1 will have
X two fds, the result of open("bar",...), and the result of
X open("ble",....). */
X
Xvoid addfd(forked,save,mfds,fd1,fd2,rflag) /**/
Xint forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag;
X{
Xint pipes[2];
X
X if (!mfds[fd1]) /* starting a new multio */
X {
X mfds[fd1] = alloc(sizeof(struct multio));
X if (!forked && fd1 != fd2 && fd1 < 10)
X save[fd1] = movefd(fd1);
X redup(fd2,fd1);
X mfds[fd1]->ct = 1;
X mfds[fd1]->fds[0] = fd1;
X mfds[fd1]->rflag = rflag;
X }
X else
X {
X if (mfds[fd1]->rflag != rflag)
X {
X zerr("file mode mismatch on fd %d",NULL,fd1);
X return;
X }
X if (mfds[fd1]->ct == 1) /* split the stream */
X {
X mfds[fd1]->fds[0] = movefd(fd1);
X mfds[fd1]->fds[1] = movefd(fd2);
X mpipe(pipes);
X mfds[fd1]->pipe = pipes[1-rflag];
X redup(pipes[rflag],fd1);
X mfds[fd1]->ct = 2;
X }
X else /* add another fd to an already split stream */
X mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
X }
X}
X
Xvoid addvars(l,export) /**/
XLklist l;int export;
X{
Xstruct varasg *v;
XLklist vl;
X
X while (full(l))
X {
X char **arr,**ptr;
X
X v = ugetnode(l);
X singsub(&v->name);
X if (errflag)
X return;
X untokenize(v->name);
X if (v->type == PMFLAG_s)
X {
X vl = newlist();
X addnode(vl,v->str);
X }
X else
X vl = v->arr;
X prefork(vl);
X if (errflag)
X return;
X postfork(vl,1);
X if (errflag)
X return;
X if (v->type == PMFLAG_s)
X {
X Param pm;
X char *val;
X
X if (!full(vl))
X pm = setsparam(v->name,val = ztrdup(""));
X else
X {
X untokenize(peekfirst(vl));
X pm = setsparam(v->name,val = ztrdup(ugetnode(vl)));
X }
X if (export && !(pm->flags & PMFLAG_x))
X addenv(v->name,val);
X continue;
X }
X ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(v->arr)+1));
X while (full(v->arr))
X {
X *ptr = ztrdup(ugetnode(v->arr));
X untokenize(*ptr++);
X }
X *ptr = NULL;
X setaparam(v->name,arr);
X }
X}
X
Xvoid execcmd(cmd,input,output,bkg,last1) /**/
XCmd cmd;int input;int output;int bkg;int last1;
X{
Xint type;
Xlong pid = 0;
XLklist args = cmd->args;
Xint save[10],t0;
Xstruct redir *fn;
Xstruct multio *mfds[10];
Xint fil,forked = 0,iscursh = 0,nullexec = 0;
XCmdnam chn = NULL;
Xchar *text;
X
X for (t0 = 0; t0 != 10; t0++)
X {
X save[t0] = 0;
X mfds[t0] = NULL;
X }
X if ((type = cmd->type) == SIMPLE && !full(args))
X if (full(cmd->redir))
X if (cmd->flags & CFLAG_EXEC)
X nullexec = 1;
X else
X addnode(args,strdup("cat"));
X else
X {
X addvars(cmd->vars,0);
X return;
X }
X if (full(args) && *(char *) peekfirst(args) == '%')
X {
X insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg"));
X bkg = 0;
X }
X if (isset(AUTORESUME) && !full(cmd->redir) && full(args) &&
X type == SIMPLE && !nextnode(firstnode(args)) &&
X findjobnam(peekfirst(args)) != -1)
X pushnode(args,strdup("fg"));
X if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) &&
X type == SIMPLE && full(args) && nextnode(firstnode(args)) &&
X !strcmp(peekfirst(args),"rm"))
X {
X char *s = getdata(nextnode(firstnode(args)));
X
X if (s[0] == Star && !s[1])
X checkrmall();
X }
X if (jobbing) /* get the text associated with this command */
X {
X char *s;
X s = text = gettext((void *) cmd,0);
X }
X else
X text = NULL;
X prefork(args); /* do prefork substitutions */
X if (errflag)
X {
X lastval = 1;
X return;
X }
X if (full(args) && !(cmd->flags & CFLAG_COMMAND))
X chn = gethnode(peekfirst(args),cmdnamtab);
X if (!pathsuppress && !chn && isset(AUTOCD) && full(args) &&
X !full(cmd->redir) &&
X !nextnode(firstnode(args)) && cancd(peekfirst(args)))
X {
X pushnode(args,strdup("cd"));
X chn = gethnode("cd",cmdnamtab);
X }
X
X /* this is nonzero if cmd is a current shell procedure */
X
X iscursh = (type >= CURSH) || (type == SIMPLE && chn &&
X (chn->type == BUILTIN || chn->type == SHFUNC));
X
X /* if this command is backgrounded or (this is an external
X command and we are not exec'ing it) or this is a builtin
X with output piped somewhere, then fork. If this is the
X last stage in a subshell pipeline, don't fork, but make
X the rest of the function think we forked. */
X
X if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) ||
X (chn && (chn->type == BUILTIN || chn->type == SHFUNC) && output))
X {
X pid = (last1 && execok()) ? 0 : phork();
X if (pid == -1)
X return;
X if (pid)
X {
X if (pid == -1)
X zerr("%e",NULL,errno);
X else
X ( void ) addproc(pid,text);
X return;
X }
X entersubsh(bkg);
X forked = 1;
X }
X if (bkg && isset(BGNICE)) /* stupid */
X nice(5);
X if (input) /* add pipeline input/output to mnodes */
X addfd(forked,save,mfds,0,input,0);
X if (output)
X addfd(forked,save,mfds,1,output,1);
X spawnpipes(cmd->redir); /* do process substitutions */
X while (full(cmd->redir))
X if ((fn = ugetnode(cmd->redir))->type == INPIPE)
X {
X if (fn->fd2 == -1)
X execerr();
X addfd(forked,save,mfds,fn->fd1,fn->fd2,0);
X }
X else if (fn->type == OUTPIPE)
X {
X if (fn->fd2 == -1)
X execerr();
X addfd(forked,save,mfds,fn->fd1,fn->fd2,1);
X }
X else
X {
X if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type ==
X MERGE || fn->type == MERGEOUT))
X if (xpandredir(fn,cmd->redir))
X continue;
X if (fn->type == HERESTR)
X {
X fil = getherestr(fn);
X if (fil == -1)
X {
X if (errno != EINTR)
X zerr("%e",NULL,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,0);
X }
X else if (fn->type == READ)
X {
X fil = open(fn->name,O_RDONLY);
X if (fil == -1)
X {
X if (errno != EINTR)
X zerr("%e: %s",fn->name,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,0);
X }
X else if (fn->type == CLOSE)
X {
X if (!forked && fn->fd1 < 3)
X {
X zerr("can't close fd %d without forking",NULL,fn->fd1);
X execerr();
X }
X closemn(mfds,fn->fd1);
X close(fn->fd1);
X }
X else if (fn->type == MERGE || fn->type == MERGEOUT)
X {
X fil = dup(fn->fd2);
X if (mfds[fn->fd1])
X redup(fil,fn->fd1);
X else
X addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
X }
X else
X {
X if (fn->type >= APP)
X fil = open(fn->name,isset(NOCLOBBER) ?
X O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
X else
X fil = open(fn->name,dontclob(fn) ?
X O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
X if (fil == -1)
X {
X if (errno != EINTR)
X zerr("%e: %s",fn->name,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,1);
X }
X }
X postfork(args,!(cmd->flags & CFLAG_NOGLOB));
X /* perform postfork substitutions */
X if (errflag)
X {
X lastval = 1;
X goto err;
X }
X
X /* we are done with redirection. close the mnodes, spawning
X tee/cat processes as necessary. */
X for (t0 = 0; t0 != 10; t0++)
X closemn(mfds,t0);
X
X if (nullexec)
X return;
X if (unset(NOEXEC))
X if (type >= CTIME)
X {
X static int (*func[]) DCLPROTO((Cmd)) = {
X exectime,execcursh,execfuncdef,execfor,execwhile,
X execrepeat,execif,execcase,execselect,execcond };
X
X fixcline(args);
X lastval = (func[type-CTIME])(cmd);
X }
X else if (iscursh) /* builtin or shell function */
X {
X if (cmd->vars)
X addvars(cmd->vars,0);
X fixcline(args);
X if (chn && chn->type == SHFUNC)
X execshfunc(cmd,chn);
X else
X {
X lastval = execbin(args,chn);
X if (isset(PRINTEXITVALUE) && lastval)
X zerr("exit %d",NULL,lastval);
X fflush(stdout);
X if (ferror(stdout))
X {
X zerr("write error: %e",NULL,errno);
X clearerr(stdout);
X }
X }
X }
X else
X {
X if (cmd->vars)
X addvars(cmd->vars,1);
X if (type == SIMPLE)
X {
X closem();
X execute(args,cmd->flags & CFLAG_DASH);
X }
X else /* ( ... ) */
X execlist(cmd->u.list);
X }
Xerr:
X if (forked)
X _exit(lastval);
X fixfds(save);
X}
X
X/* restore fds after redirecting a builtin */
X
Xvoid fixfds(save) /**/
Xint *save;
X{
Xint t0;
X
X for (t0 = 0; t0 != 10; t0++)
X if (save[t0])
X redup(save[t0],t0);
X}
X
Xvoid entersubsh(bkg) /**/
Xint bkg;
X{
X if (!jobbing)
X {
X if (bkg && isatty(0))
X {
X close(0);
X if (open("/dev/null",O_RDWR))
X {
X zerr("can't open /dev/null: %e",NULL,errno);
X _exit(1);
X }
X }
X }
X else if (!jobtab[thisjob].gleader)
X {
X setpgrp(0L,jobtab[thisjob].gleader = getpid());
X if (!bkg)
X attachtty(jobtab[thisjob].gleader);
X }
X else
X setpgrp(0L,jobtab[thisjob].gleader);
X subsh = 1;
X if (SHTTY != -1)
X {
X close(SHTTY);
X SHTTY = -1;
X }
X if (jobbing)
X {
X signal(SIGTTOU,SIG_DFL);
X signal(SIGTTIN,SIG_DFL);
X signal(SIGTSTP,SIG_DFL);
X signal(SIGPIPE,SIG_DFL);
X }
X if (interact)
X {
X signal(SIGTERM,SIG_DFL);
X if (sigtrapped[SIGINT])
X signal(SIGINT,SIG_IGN);
X }
X if (!sigtrapped[SIGQUIT])
X signal(SIGQUIT,SIG_DFL);
X opts[MONITOR] = OPT_UNSET;
X clearjobtab();
X}
X
X/* close all internal shell fds */
X
Xvoid closem() /**/
X{
Xint t0;
X
X for (t0 = 10; t0 != NOFILE; t0++)
X close(t0);
X}
X
X/* convert here document into a here string */
X
Xchar *gethere(str) /**/
Xchar *str;
X{
Xchar pbuf[256];
Xint qt = 0,siz = 0,l,strip = 0;
Xchar *s,*t,*bptr;
X
X for (s = str; *s; s++)
X if (*s == Nularg)
X qt = 1;
X untokenize(str);
X if (*str == '-')
X {
X str++;
X strip = 1;
X while (*str == '\t')
X str++;
X }
X t = ztrdup("");
X for(;;)
X {
X char *u,*v;
X
X if (!fgets(pbuf,256,bshin))
X break;
X bptr = pbuf;
X if (strip)
X while (*bptr == '\t')
X bptr++;
X for (u = bptr, v = str; *u != '\n' && *v; u++,v++)
X if (*u != *v)
X break;
X if (!(*u == '\n' && !*v))
X {
X l = strlen(bptr);
X if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\')
X bptr[l -= 2] = '\0';
X t = realloc(t,siz+l+1);
X strncpy(t+siz,bptr,l);
X siz += l;
X }
X else
X break;
X }
X t[siz] = '\0';
X if (siz && t[siz-1] == '\n')
X t[siz-1] = '\0';
X if (!qt)
X for (s = t; *s; s++)
X if (*s == '$')
X *s = Qstring;
X else if (*s == '`')
X *s = Qtick;
X else if (*s == '\\')
X {
X s++;
X if (!*s)
X break;
X }
X s = strdup(t);
X free(t);
X return s;
X}
X
X/* open here string fd */
X
Xint getherestr(fn) /**/
Xstruct redir *fn;
X{
XLklist fake;
Xchar *s = gettemp(),*t;
Xint fd;
X
X fake = newlist();
X addnode(fake,fn->name);
X prefork(fake);
X if (!errflag)
X postfork(fake,1);
X if (errflag)
X return -1;
X if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1)
X return -1;
X while (t = ugetnode(fake))
X {
X untokenize(t);
X write(fd,t,strlen(t));
X if (full(fake))
X write(fd," ",1);
X }
X write(fd,"\n",1);
X close(fd);
X fd = open(s,O_RDONLY);
X unlink(s);
X return fd;
X}
X
Xvoid catproc(mn) /**/
Xstruct multio *mn;
X{
Xint len,t0;
Xchar *buf;
X
X if (phork())
X {
X for (t0 = 0; t0 != mn->ct; t0++)
X close(mn->fds[t0]);
X close(mn->pipe);
X return;
X }
X closeallelse(mn);
X buf = zalloc(4096);
X for (t0 = 0; t0 != mn->ct; t0++)
X while (len = read(mn->fds[t0],buf,4096))
X write(mn->pipe,buf,len);
X _exit(0);
X}
X
Xvoid teeproc(mn) /**/
Xstruct multio *mn;
X{
Xint len,t0;
Xchar *buf;
X
X if (phork())
X {
X for (t0 = 0; t0 != mn->ct; t0++)
X close(mn->fds[t0]);
X close(mn->pipe);
X return;
X }
X buf = zalloc(4096);
X closeallelse(mn);
X while ((len = read(mn->pipe,buf,4096)) > 0)
X for (t0 = 0; t0 != mn->ct; t0++)
X write(mn->fds[t0],buf,len);
X _exit(0);
X}
X
Xvoid closeallelse(mn) /**/
Xstruct multio *mn;
X{
Xint t0,t1;
X
X for (t0 = 0; t0 != NOFILE; t0++)
X if (mn->pipe != t0)
X {
X for (t1 = 0; t1 != mn->ct; t1++)
X if (mn->fds[t1] == t0)
X break;
X if (t1 == mn->ct)
X close(t0);
X }
X}
X
Xlong int zstrtol(s,t,base) /**/
Xchar *s;char **t;int base;
X{
Xint ret = 0;
X
X for (; *s >= '0' && *s < ('0'+base); s++)
X ret = ret*base+*s-'0';
X if (t)
X *t = (char *) s;
X return ret;
X}
X
X/* $(...) */
X
XLklist getoutput(cmd,qt) /**/
Xchar *cmd;int qt;
X{
XList list;
Xint pipes[2];
X
X if (*cmd == '<')
X {
X int stream;
X char *fi;
X
X fi = strdup(cmd+1);
X if (*fi == '~')
X *fi = Tilde;
X else if (*fi == '=')
X *fi = Equals;
X singsub(&fi);
X if (errflag)
X return NULL;
X stream = open(fi,O_RDONLY);
X if (stream == -1)
X {
X zerr("%e: %s",cmd+1,errno);
X return NULL;
X }
X return readoutput(stream,qt);
X }
X if (!(list = parselstring(cmd)))
X return NULL;
X mpipe(pipes);
X if (phork())
X {
X popheap();
X close(pipes[1]);
X return readoutput(pipes[0],qt);
X }
X subsh = 1;
X close(pipes[0]);
X redup(pipes[1],1);
X entersubsh(0);
X signal(SIGTSTP,SIG_IGN);
X exiting = 1;
X execlist(list);
X close(1);
X exit(0); return NULL;
X}
X
X/* read output of command substitution */
X
XLklist readoutput(in,qt) /**/
Xint in;int qt;
X{
XLklist ret;
Xchar *buf,*ptr;
Xint bsiz,c,cnt = 0;
XFILE *fin;
X
X fin = fdopen(in,"r");
X ret = newlist();
X ptr = buf = zalloc(bsiz = 256);
X while ((c = fgetc(fin)) != EOF)
X if (!qt && isep(c))
X {
X if (cnt)
X {
X *ptr = '\0';
X addnode(ret,ztrdup(buf));
X cnt = 0;
X ptr = buf;
X }
X }
X else
X {
X *ptr++ = c;
X if (++cnt == bsiz)
X {
X char *pp = zalloc(bsiz *= 2);
X
X memcpy(pp,buf,cnt);
X free(buf);
X ptr = (buf = pp)+cnt;
X }
X }
X if (qt && ptr != buf && ptr[-1] == '\n')
X ptr[-1] = '\0';
X if (cnt)
X addnode(ret,ztrdup(buf));
X free(buf);
X fclose(fin);
X return ret;
X}
X
X/* =(...) */
X
Xchar *getoutputfile(cmd) /**/
Xchar *cmd;
X{
X#ifdef WAITPID
Xint pid;
X#endif
Xchar *nam = gettemp(),*str;
Xint tfil;
XList list;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X if (!(list = parselstring(cmd)))
X return NULL;
X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(nam));
X heapalloc();
X#ifdef WAITPID
X if (pid = phork())
X {
X popheap();
X waitpid(pid,NULL,WUNTRACED);
X return nam;
X }
X#else
X if (waitfork())
X return nam;
X#endif
X subsh = 1;
X close(1);
X entersubsh(0);
X tfil = creat(nam,0666);
X exiting = 1;
X execlist(list);
X close(1);
X exit(0); return NULL;
X}
X
X/* get a temporary named pipe */
X
Xchar *namedpipe() /**/
X{
Xchar *tnam = gettemp();
X
X mknod(tnam,0010666,0);
X return tnam;
X}
X
X/* <(...) */
X
Xchar *getoutproc(cmd) /**/
Xchar *cmd;
X{
XList list;
Xint fd;
Xchar *pnam,*str;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X pnam = namedpipe();
X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
X heapalloc();
X if (!(list = parselstring(cmd)))
X return NULL;
X if (phork())
X {
X popheap();
X return pnam;
X }
X entersubsh(1);
X fd = open(pnam,O_WRONLY);
X if (fd == -1)
X {
X zerr("can't open %s: %e",pnam,errno);
X _exit(0);
X }
X redup(fd,1);
X fd = open("/dev/null",O_RDONLY);
X redup(fd,0);
X exiting = 1;
X execlist(list);
X close(1);
X _exit(0); return NULL;
X}
X
X/* >(...) */
X
Xchar *getinproc(cmd) /**/
Xchar *cmd;
X{
XList list;
Xint pid,fd;
Xchar *pnam,*str;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X pnam = namedpipe();
X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
X heapalloc();
X if (!(list = parselstring(cmd)))
X return NULL;
X if (pid = phork())
X {
X popheap();
X return pnam;
X }
X entersubsh(1);
X fd = open(pnam,O_RDONLY);
X redup(fd,0);
X exiting = 1;
X execlist(list);
X _exit(0); return NULL;
X}
X
X/* > >(...) (does not use named pipes) */
X
Xint getinpipe(cmd) /**/
Xchar *cmd;
X{
XList list;
Xint pipes[2];
Xchar *str = cmd;
X
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X if (!(list = parselstring(cmd+2)))
X return -1;
X mpipe(pipes);
X if (phork())
X {
X popheap();
X close(pipes[1]);
X return pipes[0];
X }
X close(pipes[0]);
X entersubsh(1);
X redup(pipes[1],1);
X exiting = 1;
X execlist(list);
X _exit(0); return 0;
X}
X
X/* < <(...) */
X
Xint getoutpipe(cmd) /**/
Xchar *cmd;
X{
XList list;
Xint pipes[2];
Xchar *str;
X
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X if (!(list = parselstring(cmd+2)))
X return -1;
X strinend();
X mpipe(pipes);
X if (phork())
X {
X popheap();
X close(pipes[0]);
X return pipes[1];
X }
X close(pipes[1]);
X entersubsh(1);
X redup(pipes[0],0);
X exiting = 1;
X execlist(list);
X _exit(0); return 0;
X}
X
X/* run a list, saving the current job num */
X
Xvoid runlist(l) /**/
XList l;
X{
Xint cj = thisjob;
X
X execlist(l);
X thisjob = cj;
X}
X
Xchar *gettemp() /**/
X{
X return mktemp(strdup("/tmp/zshXXXXXX"));
X}
X
X/* my getwd; all the other ones I tried confused the SIGCHLD handler */
X
Xchar *zgetwd() /**/
X{
Xstatic char buf0[MAXPATHLEN];
Xchar buf3[MAXPATHLEN],*buf2 = buf0+1;
Xstruct stat sbuf;
Xstruct direct *de;
XDIR *dir;
Xino_t ino = -1;
Xdev_t dev = -1;
X
X holdintr();
X buf2[0] = '\0';
X buf0[0] = '/';
X for(;;)
X {
X if (stat(".",&sbuf) < 0)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X ino = sbuf.st_ino;
X dev = sbuf.st_dev;
X if (stat("..",&sbuf) < 0)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X if (sbuf.st_ino == ino && sbuf.st_dev == dev)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(buf0);
X }
X dir = opendir("..");
X if (!dir)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X chdir("..");
X readdir(dir); readdir(dir);
X while (de = readdir(dir))
X if (de->d_ino == ino)
X {
X lstat(de->d_name,&sbuf);
X if (sbuf.st_dev == dev)
X goto match;
X }
X rewinddir(dir);
X readdir(dir); readdir(dir);
X while (de = readdir(dir))
X {
X lstat(de->d_name,&sbuf);
X if (sbuf.st_dev == dev)
X goto match;
X }
X noholdintr();
X closedir(dir);
X return ztrdup(".");
Xmatch:
X strcpy(buf3,de->d_name);
X if (*buf2)
X strcat(buf3,"/");
X strcat(buf3,buf2);
X strcpy(buf2,buf3);
X closedir(dir);
X }
X}
X
X/* open pipes with fds >= 10 */
X
Xvoid mpipe(pp) /**/
Xint *pp;
X{
X pipe(pp);
X pp[0] = movefd(pp[0]);
X pp[1] = movefd(pp[1]);
X}
X
X/* do process substitution with redirection */
X
Xvoid spawnpipes(l) /**/
XLklist l;
X{
XLknode n = firstnode(l);
Xstruct redir *f;
X
X for (; n; incnode(n))
X {
X f = getdata(n);
X if (f->type == OUTPIPE)
X {
X char *str = f->name;
X f->fd2 = getoutpipe(str);
X }
X if (f->type == INPIPE)
X {
X char *str = f->name;
X f->fd2 = getinpipe(str);
X }
X }
X}
X
X/* perform time ... command */
X
Xint exectime(cmd) /**/
XCmd cmd;
X{
Xint jb = thisjob;
X
X execpline(cmd->u.pline,TIMED,0);
X thisjob = jb;
X return lastval;
X}
X
X/* define a function */
X
Xint execfuncdef(cmd) /**/
XCmd cmd;
X{
XCmdnam cc;
Xchar *s;
X
X permalloc();
X while (s = ugetnode(cmd->args))
X {
X cc = zalloc(sizeof *cc);
X cc->type = SHFUNC;
X cc->flags = 0;
X cc->u.list = dupstruct(cmd->u.list);
X addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam);
X if (!strncmp(s,"TRAP",4))
X {
X int t0 = getsignum(s+4);
X
X if (t0 != -1)
X settrap(t0,cmd->u.list);
X }
X }
X heapalloc();
X return 0;
X}
X
X/* evaluate a [[ ... ]] */
X
Xint execcond(cmd) /**/
XCmd cmd;
X{
X return !evalcond(cmd->u.cond);
X}
X
Xvoid execshfunc(cmd,cn) /**/
XCmd cmd;Cmdnam cn;
X{
Xchar **tab,**x,*oargv0;
Xint oxtr = opts[XTRACE],flags,xexittr;
XList l;
XLklist olist;
Xchar *s;
XList xexitfn;
X
X if (errflag)
X return;
X l = cn->u.list;
X if (!l)
X {
X char *nam;
X
X if (!(l = getfpfunc(nam = peekfirst(cmd->args))))
X {
X zerr("function not found: %s",nam,0);
X lastval = 1;
X return;
X }
X cn->flags &= ~PMFLAG_u;
X permalloc();
X cn->u.list = dupstruct(l);
X heapalloc();
X }
X flags = cn->flags;
X xexittr = sigtrapped[SIGEXIT];
X xexitfn = sigfuncs[SIGEXIT];
X tab = pparams;
X oargv0 = argzero;
X if (flags & PMFLAG_t)
X opts[XTRACE] = OPT_SET;
X pparams = x = zcalloc(((sizeof *x)*(1+countnodes(cmd->args))));
X argzero = ztrdup(ugetnode(cmd->args));
X while (*x = ugetnode(cmd->args))
X *x = ztrdup(*x), x++;
X permalloc();
X olist = locallist;
X locallist = newlist();
X heapalloc();
X newrunlist(l);
X while (s = getnode(locallist))
X unsetparam(s);
X free(locallist);
X locallist = olist;
X retflag = 0;
X cmd->u.list = NULL;
X freearray(pparams);
X free(argzero);
X argzero = oargv0;
X pparams = tab;
X if (sigtrapped[SIGEXIT])
X dotrap(SIGEXIT);
X if (sigfuncs[SIGEXIT])
X freestruct(sigfuncs[SIGEXIT]);
X sigtrapped[SIGEXIT] = xexittr;
X sigfuncs[SIGEXIT] = xexitfn;
X opts[XTRACE] = oxtr;
X}
X
X/* search fpath for an undefined function */
X
XList getfpfunc(s) /**/
Xchar *s;
X{
Xchar **pp = fpath,buf[MAXPATHLEN];
Xint fd;
X
X for (; *pp; pp++)
X {
X sprintf(buf,"%s/%s",*pp,s);
X if (!access(buf,X_OK) && (fd = open(buf,O_RDONLY)) != -1)
X {
X int len = lseek(fd,0,2);
X
X if (len == -1)
X close(fd);
X else
X {
X char *d;
X
X lseek(fd,0,0);
X d = zcalloc(len+1);
X if (read(fd,d,len) != len)
X {
X free(d);
X close(fd);
X }
X else
X {
X close(fd);
X return parselstring(d);
X }
X }
X }
X }
X return NULL;
X}
X
X/* check to see if AUTOCD applies here */
X
Xint cancd(s)
Xchar *s;
X{
Xchar *t;
X
X for (t = s; *t; t++)
X if (*t == '/')
X break;
X if (!*t)
X {
X char sbuf[MAXPATHLEN],**cp;
X
X if (cancd2(s))
X return 1;
X for (cp = cdpath; *cp; cp++)
X {
X sprintf(sbuf,"%s/%s",*cp,s);
X if (cancd2(sbuf))
X return 1;
X }
X return 0;
X }
X return cancd2(s);
X}
X
Xint cancd2(s)
Xchar *s;
X{
Xstruct stat buf;
X
X return !(access(s,X_OK) || lstat(s,&buf) || !S_ISDIR(buf.st_mode));
X}
X
SHAR_EOF
chmod 0644 zsh2.00/src/exec.c ||
echo 'restore of zsh2.00/src/exec.c failed'
Wc_c="`wc -c < 'zsh2.00/src/exec.c'`"
test 31640 -eq "$Wc_c" ||
echo 'zsh2.00/src/exec.c: original size 31640, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/exec.pro ==============
if test -f 'zsh2.00/src/exec.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.00/src/exec.pro (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/exec.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/exec.pro' &&
XList parselstring DCLPROTO((char *s));
Xvoid execstring DCLPROTO((char *s));
Xvoid newrunlist DCLPROTO((List l));
Xint phork DCLPROTO((void));
Xint execcursh DCLPROTO((Cmd cmd));
Xvoid zexecve DCLPROTO((char *pth,char **argv,int *ee,char *b1,char *b2));
Xvoid execute DCLPROTO((Lklist args,int dash));
Xchar *findcmd DCLPROTO((char *arg0));
Xvoid execlist DCLPROTO((List list));
Xvoid execlist2 DCLPROTO((Sublist list,int type,int last1));
Xint execpline DCLPROTO((Sublist l,int how,int last1));
Xvoid execpline2 DCLPROTO((Pline pline,int how,int input,int output,int last1));
Xchar **makecline DCLPROTO((struct lklist *list));
Xvoid fixcline DCLPROTO((Lklist l));
Xvoid untokenize DCLPROTO((char *s));
Xint dontclob DCLPROTO((struct redir *f));
Xvoid closemn DCLPROTO((struct multio **mfds,int fd));
Xvoid closemnodes DCLPROTO((struct multio **mfds));
Xvoid addfd DCLPROTO((int forked,int *save,struct multio **mfds,int fd1,int fd2,int rflag));
Xvoid addvars DCLPROTO((Lklist l,int export));
Xvoid execcmd DCLPROTO((Cmd cmd,int input,int output,int bkg,int last1));
Xvoid fixfds DCLPROTO((int *save));
Xvoid entersubsh DCLPROTO((int bkg));
Xvoid closem DCLPROTO((void));
Xchar *gethere DCLPROTO((char *str));
Xint getherestr DCLPROTO((struct redir *fn));
Xvoid catproc DCLPROTO((struct multio *mn));
Xvoid teeproc DCLPROTO((struct multio *mn));
Xvoid closeallelse DCLPROTO((struct multio *mn));
Xlong int zstrtol DCLPROTO((char *s,char **t,int base));
XLklist getoutput DCLPROTO((char *cmd,int qt));
XLklist readoutput DCLPROTO((int in,int qt));
Xchar *getoutputfile DCLPROTO((char *cmd));
Xchar *namedpipe DCLPROTO((void));
Xchar *getoutproc DCLPROTO((char *cmd));
Xchar *getinproc DCLPROTO((char *cmd));
Xint getinpipe DCLPROTO((char *cmd));
Xint getoutpipe DCLPROTO((char *cmd));
Xvoid runlist DCLPROTO((List l));
Xchar *gettemp DCLPROTO((void));
Xchar *zgetwd DCLPROTO((void));
Xvoid mpipe DCLPROTO((int *pp));
Xvoid spawnpipes DCLPROTO((Lklist l));
Xint exectime DCLPROTO((Cmd cmd));
Xint execfuncdef DCLPROTO((Cmd cmd));
Xint execcond DCLPROTO((Cmd cmd));
Xvoid execshfunc DCLPROTO((Cmd cmd,Cmdnam cn));
XList getfpfunc DCLPROTO((char *s));
SHAR_EOF
chmod 0644 zsh2.00/src/exec.pro ||
echo 'restore of zsh2.00/src/exec.pro failed'
Wc_c="`wc -c < 'zsh2.00/src/exec.pro'`"
test 2101 -eq "$Wc_c" ||
echo 'zsh2.00/src/exec.pro: original size 2101, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/funcs.h ==============
if test -f 'zsh2.00/src/funcs.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.00/src/funcs.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/funcs.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/funcs.h' &&
X#include "glob.pro"
X#include "hist.pro"
X#include "table.pro"
X#include "subst.pro"
X#include "params.pro"
X#include "builtin.pro"
X#include "loop.pro"
X#include "jobs.pro"
X#include "exec.pro"
X#include "init.pro"
X#include "lex.pro"
X#include "parse.pro"
X#include "utils.pro"
X#include "cond.pro"
X#include "mem.pro"
X#include "text.pro"
X#include "watch.pro"
X
X#include "zle_emacs.pro"
X#include "zle_utils.pro"
X#include "zle_main.pro"
X#include "zle_refresh.pro"
X#include "zle_tricky.pro"
X#include "zle_vi.pro"
X
Xchar *mktemp DCLPROTO((char *));
Xchar *malloc DCLPROTO((int));
Xchar *realloc DCLPROTO((char *,int));
Xchar *calloc DCLPROTO((int,int));
Xchar *ttyname DCLPROTO((int));
Xchar *tgetstr();
SHAR_EOF
chmod 0644 zsh2.00/src/funcs.h ||
echo 'restore of zsh2.00/src/funcs.h failed'
Wc_c="`wc -c < 'zsh2.00/src/funcs.h'`"
test 682 -eq "$Wc_c" ||
echo 'zsh2.00/src/funcs.h: original size 682, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.00/src/glob.c ==============
if test -f 'zsh2.00/src/glob.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.00/src/glob.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.00/src/glob.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.00/src/glob.c' &&
X/*
X
X glob.c - filename generation
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#include "funcs.h"
X#ifndef INT_MAX
X#include <limits.h>
X#endif
X#include <sys/dir.h>
X#include <sys/errno.h>
X
X#define exists(X) (access(X,0) == 0)
X
Xstatic int mode; /* != 0 if we are parsing glob patterns */
Xstatic int pathpos; /* position in pathbuf */
Xstatic int matchsz; /* size of matchbuf */
Xstatic int matchct; /* number of matches found */
Xstatic char pathbuf[MAXPATHLEN]; /* pathname buffer */
Xstatic char **matchbuf; /* array of matches */
Xstatic char **matchptr; /* &matchbuf[matchct] */
X
X/* max # of qualifiers */
X
X#define QUALCT 16
X
Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
Xstatic long qualdata[QUALCT];
Xstatic int qualsense[QUALCT];
Xstatic int qualct;
X
X/* pathname component in filename patterns */
X
Xstruct complist {
X Complist next;
X Comp comp;
X int closure; /* 1 if this is a (foo/)# */
X };
Xstruct comp {
X Comp left,right,next;
X char *str;
X int closure,last;
X };
X
Xvoid glob(list,np) /**/
XLklist list;Lknode *np;
X{
XLknode node = prevnode(*np);
XLknode next = nextnode(*np);
Xint sl; /* length of the pattern */
Xchar *ostr; /* the pattern before the parser chops it up */
XComplist q; /* pattern after parsing */
Xchar *str = getdata(*np); /* the pattern */
X
X sl = strlen(str);
X ostr = strdup(str);
X uremnode(list,*np);
X qualct = 0;
X if (str[sl-1] == Outpar) /* check for qualifiers */
X {
X char *s;
X int sense = 0;
X long data;
X int (*func) DCLPROTO((struct stat *,long));
X
X for (s = str+sl-2; s != str; s--)
X if (*s == Bar || *s == Outpar || *s == Inpar)
X break;
X if (*s == Inpar)
X {
X *s++ = '\0';
X func = NULL;
X while (*s != Outpar)
X {
X func = NULL;
X if (idigit(*s))
X {
X func = qualflags;
X data = 0;
X while (idigit(*s))
X data = data*010+(*s-'0');
X }
X else switch (*s++)
X {
X case Hat: sense = 1-sense; break;
X case '@': func = qualmode; data = S_IFLNK; break;
X case '=': func = qualmode; data = S_IFSOCK; break;
X case 'p': func = qualmode; data = S_IFIFO; break;
X case '/': func = qualmode; data = S_IFDIR; break;
X case '.': func = qualmode; data = S_IFREG; break;
X case '%': func = qualisdev; break;
X case Star: func = qualflags; data = 0100; break;
X case 'R': func = qualflags; data = 0004; break;
X case 'W': func = qualflags; data = 0002; break;
X case 'X': func = qualflags; data = 0001; break;
X case 'r': func = qualflags; data = 0400; break;
X case 'w': func = qualflags; data = 0200; break;
X case 'x': func = qualflags; data = 0100; break;
X case 's': func = qualflags; data = 04000; break;
X case 'S': func = qualflags; data = 02000; break;
X case 'd': func = qualdev; data = qgetnum(&s); break;
X case 'l': func = qualnlink; data = qgetnum(&s); break;
X case 'U': func = qualuid; data = geteuid(); break;
X case 'G': func = qualgid; data = getegid(); break;
X case 'u': func = qualuid; data = qgetnum(&s); break;
X case 'g': func = qualgid; data = qgetnum(&s); break;
X default: zerr("unknown file attribute",NULL,0); return;
X }
X if (func)
X {
X if (qualct == 15)
X {
X zerr("too many qualifiers",NULL,0);
X return;
X }
X qualfuncs[qualct] = func;
X qualsense[qualct] = sense;
X qualdata[qualct] = data;
X qualct++;
X }
X if (errflag)
X return;
X }
X }
X }
X else if (str[sl-1] == '/') /* foo/ == foo(/) */
X {
X str[sl-1] = '\0';
X qualfuncs[0] = qualmode;
X qualdata[0] = S_IFDIR;
X qualsense[0] = 0;
X qualct = 1;
X }
X if (*str == '/') /* pattern has absolute path */
X {
X str++;
X pathbuf[0] = '/';
X pathbuf[pathpos = 1] = '\0';
X }
X else /* pattern is relative to cwd */
X pathbuf[pathpos = 0] = '\0';
X q = parsepat(str);
X if (!q || errflag) /* if parsing failed */
X {
X if (isset(NOBADPATTERN))
X {
X insnode(list,node,ostr);
X return;
X }
X errflag = 0;
X zerr("bad pattern: %s",ostr,0);
X return;
X }
X matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
X matchct = 0;
X scanner(q); /* do the globbing */
X if (!matchct && unset(NULLGLOB))
X if (unset(NONOMATCH))
X {
X zerr("no matches found: %s",ostr,0);
X free(matchbuf);
X return;
X }
X else
X {
X *matchptr++ = strdup(ostr);
X matchct = 1;
X }
X qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
X matchptr = matchbuf;
X while (matchct--) /* insert matches in the arg list */
X insnode(list,node,*matchptr++);
X free(matchbuf);
X *np = (next) ? prevnode(next) : lastnode(list);
X}
X
X/* get number after qualifier */
X
Xlong qgetnum(s) /**/
Xchar **s;
X{
Xlong v = 0;
X
X if (!idigit(**s))
X {
X zerr("number expected",NULL,0);
X return 0;
X }
X while (idigit(**s))
X v = v*10+*(*s)++-'0';
X return v;
X}
X
Xint notstrcmp(a,b) /**/
Xchar **a;char **b;
X{
Xchar *c = *b,*d = *a;
SHAR_EOF
true || echo 'restore of zsh2.00/src/glob.c failed'
fi
echo 'End of zsh2.00.00 part 5'
echo 'File zsh2.00/src/glob.c is continued in part 6'
echo 6 > _shar_seq_.tmp
exit 0
--
Paul Falstad pfalstad at phoenix.princeton.edu
And on the roads, too, vicious gangs of KEEP LEFT signs!
If Princeton knew my opinions, they'd have expelled me long ago.
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list