zsh - a ksh/tcsh-like shell (part 3 of 8)
Paul John Falstad
pfalstad at phoenix.Princeton.EDU
Sat Dec 15 10:30:38 AEST 1990
---cut here---cut here---cut here---
- close(pipes[1]);
- entersubsh(1);
- exiting = 1;
- execpline2(pline->right,ASYNC,pipes[0],output,1);
- _exit(lastval);
- }
- else if (pid == -1)
- {
- zerr("fork failed: %e",errno);
- errflag = 1;
- }
- else
- {
- char *s,*text;
-
- close(pipes[0]);
- text = s = getptext(pline->right);
- for (;*s;s++)
- if (*s == '\n')
- *s = ';';
- untokenize(text);
- addproc(pid,text)->lastfg = 1;
- freepline(pline->right);
- pline->right = NULL;
- }
- }
-
- /* otherwise just do the pipeline normally. */
-
- execcomm(pline->left,input,pipes[1],how==ASYNC,0);
- pline->left = NULL;
- close(pipes[1]);
- if (pline->right)
- {
- execpline2(pline->right,how,pipes[0],output,last1);
- close(pipes[0]);
- }
- }
-}
-
-/* make the argv array */
-
-char **makecline(char *nam,struct xlist *list)
-{
-int ct = 0;
-Node node;
-char **argv,**ptr;
-
- if (isset(XTRACE))
- {
- for (node = list->first; node; node = node->next,ct++);
- ptr = argv = (char **) zalloc((ct+2)*sizeof(char *));
- *ptr++ = nam;
- fprintf(stderr,"+ %s",nam);
- if (list->first)
- fputc(' ',stderr);
- for (node = list->first; node; node = node->next)
- if (*(char *) node->dat)
- {
- *ptr++ = node->dat;
- untokenize(node->dat);
- fputs(node->dat,stderr);
- if (node->next)
- fputc(' ',stderr);
- }
- *ptr = NULL;
- fputc('\n',stderr);
- return(argv);
- }
- else
- {
- for (node = list->first; node; node = node->next,ct++);
- ptr = argv = (char **) zalloc((ct+2)*sizeof(char *));
- *ptr++ = nam;
- for (node = list->first; node; node = node->next)
- if (*(char *) node->dat)
- {
- *ptr++ = node->dat;
- untokenize(node->dat);
- }
- *ptr = NULL;
- return(argv);
- }
-}
-
-/* untokenize the command line and remove null arguments */
-
-void fixcline(table l)
-{
-Node node,next;
-
- for (node = l->first; node; node = next)
- {
- next = node->next;
- if (*(char *) node->dat)
- untokenize(node->dat);
- else
- remnode(l,node);
- }
-}
-
-void untokenize(char *s)
-{
- for (; *s; s++)
- if (istok(*s))
- if (*s == HQUOT || *s == Nularg)
- chuck(s--);
- else
- *s = tokens[*s-Pound];
-}
-
-/* add vars to the environment */
-
-void addenv(table list)
-{
-char *s,*t;
-
- while (s = getnode(list))
- {
- dovarsubs(&s);
- if (errflag)
- break;
- untokenize(s);
- t = getnode(list);
- dovarsubs(&t);
- if (errflag)
- break;
- untokenize(t);
- setparm(s,t,1,0);
- }
-}
-
-/* nonzero if we shouldn't clobber a file */
-
-int dontclob(struct fnode *f)
-{
-struct stat buf;
-
- if (isset(CLOBBER) || f->type & 1)
- return 0;
- if (stat(f->u.name,&buf) == -1)
- return 1;
- return S_ISREG(buf.st_mode);
-}
-
-/* close an mnode (success) */
-
-void closemn(struct mnode *mfds[10],int fd)
-{
- if (mfds[fd])
- {
- if (mfds[fd]->ct > 1)
- if (mfds[fd]->rflag == 0)
- catproc(mfds[fd]);
- else
- teeproc(mfds[fd]);
- free(mfds[fd]);
- mfds[fd] = NULL;
- }
-}
-
-/* close all the mnodes (failure) */
-
-void closemnodes(struct mnode *mfds[10])
-{
-int t0,t1;
-
- for (t0 = 0; t0 != 10; t0++)
- if (mfds[t0])
- {
- for (t1 = 0; t1 != mfds[t0]->ct; t1++)
- close(mfds[t0]->fds[t1]);
- free(mfds[t0]);
- mfds[t0] = NULL;
- }
-}
-
-/* add a fd to an mnode */
-/* an mnode is a list of fds associated with a certain fd.
- thus if you do "foo >bar >ble", the mnode for fd 1 will have
- two fds, the result of open("bar",...), and the result of
- open("ble",....). */
-
-void addfd(int forked,int save[10],struct mnode *mfds[10],int fd1,int fd2,int rflag)
-{
-int pipes[2];
-
- if (!mfds[fd1]) /* starting a new mnode */
- {
- mfds[fd1] = alloc(sizeof(struct mnode));
- if (!forked && fd1 != fd2 && fd1 < 10)
- save[fd1] = movefd(fd1);
- redup(fd2,fd1);
- mfds[fd1]->ct = 1;
- mfds[fd1]->fds[0] = fd1;
- mfds[fd1]->rflag = rflag;
- }
- else
- {
- if (mfds[fd1]->rflag != rflag)
- {
- zerr("file mode mismatch on fd %d",fd1);
- errflag = 1;
- return;
- }
- if (mfds[fd1]->ct == 1) /* split the stream */
- {
- mfds[fd1]->fds[0] = movefd(fd1);
- mfds[fd1]->fds[1] = movefd(fd2);
- mpipe(pipes);
- mfds[fd1]->pipe = pipes[1-rflag];
- redup(pipes[rflag],fd1);
- mfds[fd1]->ct = 2;
- }
- else /* add another fd to an already split stream */
- mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
- }
-}
-
-void execcomm(comm comm,int input,int output,int bkg,int last1)
-{
-int type;
-long pid = 0;
-table args = comm->args;
-int save[10] = {0,0,0,0,0,0,0,0,0,0},gstat;
-struct fnode *fn;
-struct mnode *mfds[10] = {0,0,0,0,0,0,0,0,0,0};
-int fil,forked = 0,iscursh = 0,t0;
-struct chnode *chn = NULL;
-char *text;
-list l;
-
- if ((type = comm->type) == SIMPLE && !*comm->cmd)
- {
- if (comm->vars)
- addvars(comm->vars);
- return;
- }
- if (comm->cmd)
- {
- if (*comm->cmd == '%')
- {
- if (full(args))
- {
- zerrnam(comm->cmd,"too many arguments");
- return;
- }
- addnode(args,comm->cmd);
- comm->cmd = strdup((bkg) ? "bg" : "fg");
- bkg = 0;
- }
- docmdsubs(&comm->cmd);
- if (errflag)
- {
- freecmd(comm);
- lastval = 1;
- return;
- }
- untokenize(comm->cmd);
- }
- if (jobbing) /* get the text associated with this command */
- {
- char *s;
- s = text = gettext(comm);
- for (;*s;s++)
- if (*s == '\n')
- *s = ';';
- untokenize(text);
- }
- else
- text = NULL;
- prefork(comm->args); /* do prefork substitutions */
- if (comm->cmd && !(comm->flags & CFLAG_COMMAND))
- {
- if (isset(CORRECT) && jobbing)
- spckcmd(&comm->cmd);
- if ((l = gethnode(comm->cmd,shfunchtab)) &&
- !(comm->flags & CFLAG_COMMAND))
- {
- insnode(comm->args,(Node) comm->args,comm->cmd);
- comm->cmd = NULL;
- comm->left = duplist(l);
- type = comm->type = SHFUNC;
- }
- else
- chn = gethnode(comm->cmd,chtab);
- }
- if (unset(RMSTARSILENT) && jobbing && chn && chn->type != BUILTIN &&
- !strcmp(comm->cmd,"rm") && full(comm->args) &&
- ((char *) comm->args->first->dat)[0] == Star &&
- ((char *) comm->args->first->dat)[1] == '\0')
- checkrmall();
- if (errflag)
- {
- freecmd(comm);
- lastval = 1;
- return;
- }
-
- /* this is nonzero if comm is a current shell procedure */
-
- iscursh = (type >= CURSH) || (type == SIMPLE && chn &&
- chn->type == BUILTIN);
-
- gstat = (chn) ? chn->globstat : GLOB;
-
- /* if this command is backgrounded or (this is an external
- command and we are not exec'ing it) or this is a builtin
- with output piped somewhere, then fork. If this is the
- last stage in a subshell pipeline, don't fork, but make
- the rest of the function think we forked. */
-
- if (bkg || !(iscursh || (comm->flags & CFLAG_EXEC)) ||
- (chn && chn->type == BUILTIN && output))
- {
- pid = (last1 && execok()) ? 0 : phork();
- if (pid == -1)
- return;
- if (pid)
- {
- if (pid == -1)
- zerr("%e",errno);
- else
- (void) addproc(pid,text);
- return;
- }
- entersubsh(bkg);
- forked = 1;
- }
- if (bkg && isset(BGNICE)) /* stupid */
- nice(5);
- if (input) /* add pipeline input/output to mnodes */
- addfd(forked,save,mfds,0,input,0);
- if (output)
- addfd(forked,save,mfds,1,output,1);
- spawnpipes(comm->redir); /* do process substitutions */
- while (full(comm->redir))
- if ((fn = getnode(comm->redir))->type == INPIPE)
- {
- if (fn->u.fd2 == -1)
- execerr();
- addfd(forked,save,mfds,fn->fd1,fn->u.fd2,0);
- free(fn);
- }
- else if (fn->type == OUTPIPE)
- {
- if (fn->u.fd2 == -1)
- execerr();
- addfd(forked,save,mfds,fn->fd1,fn->u.fd2,1);
- free(fn);
- }
- else
- {
- if (!(fn->type == HEREDOC || fn->type == CLOSE || fn->type ==
- MERGE || fn->type == MERGEOUT))
- if (xpandredir(fn,comm->redir))
- continue;
- if (fn->type == READ || fn->type == HEREDOC)
- {
- fil = (fn->type == READ) ? open(fn->u.name,O_RDONLY) : fn->u.fd2;
- if (fil == -1)
- {
- if (errno != EINTR)
- zerr("%e: %s",errno,fn->u.name);
- execerr();
- }
- addfd(forked,save,mfds,fn->fd1,fil,0);
- if (fn->type == READ)
- free(fn->u.name);
- }
- else if (fn->type == CLOSE)
- {
- if (!forked && fn->fd1 < 3)
- {
- zerr("can't close fd %d without forking",fn->fd1);
- execerr();
- }
- closemn(mfds,fn->fd1);
- close(fn->fd1);
- }
- else if (fn->type == MERGE || fn->type == MERGEOUT)
- {
- fil = dup(fn->u.fd2);
- if (mfds[fn->fd1])
- redup(fil,fn->fd1);
- else
- addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
- }
- else
- {
- if (fn->type >= APP)
- fil = open(fn->u.name,dontclob(fn) ?
- O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
- else
- fil = open(fn->u.name,dontclob(fn) ?
- O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
- if (fil == -1)
- {
- if (errno != EINTR)
- zerr("%e: %s",errno,fn->u.name);
- execerr();
- }
- addfd(forked,save,mfds,fn->fd1,fil,1);
- free(fn->u.name);
- }
- free(fn);
- }
- postfork(comm->args,gstat); /* perform postfork substitutions */
- if (errflag)
- {
- lastval = 1;
- goto err;
- }
-
- /* we are done with redirection. close the mnodes, spawning
- tee/cat processes as necessary. */
- for (t0 = 0; t0 != 10; t0++)
- closemn(mfds,t0);
-
- if (unset(NOEXEC))
- if (type >= CURSH) /* current shell proc */
- {
- void (*func[])(struct cnode *) = {execcursh,execshfunc,
- execfor,execwhile,execrepeat,execif,execcase,execselect};
-
- fixcline(comm->args);
- (func[type-CURSH])(comm);
- fflush(stdout);
- if (ferror(stdout))
- {
- zerr("write error: %e",errno);
- clearerr(stdout);
- }
- }
- else if (iscursh) /* builtin */
- {
- int (*func)() = chn->u.func;
-
- if (comm->vars)
- {
- addvars(comm->vars);
- comm->vars = NULL;
- }
- fixcline(comm->args);
- if (func == test) /* let test know if it is test or [ */
- insnode(comm->args,(Node) comm->args,strdup(comm->cmd));
- lastval = func(comm);
- if (isset(PRINTEXITVALUE) && lastval)
- zerr("exit %d",lastval);
- }
- else
- {
- if (comm->vars)
- addenv(comm->vars);
- if (type == SIMPLE)
- {
- closem();
- execute(comm->cmd,args);
- }
- else /* ( ... ) */
- execlist(comm->left);
- }
-err:
- if (forked)
- _exit(lastval);
- fixfds(save);
- freecmd(comm);
-}
-
-/* restore fds after redirecting a builtin */
-
-void fixfds(int save[10])
-{
-int t0;
-
- for (t0 = 0; t0 != 10; t0++)
- if (save[t0])
- redup(save[t0],t0);
-}
-
-void entersubsh(int bkg)
-{
- if (!jobbing)
- {
- if (bkg && isatty(0))
- {
- close(0);
- if (open("/dev/null",O_RDWR))
- {
- zerr("can't open /dev/null: %e",errno);
- _exit(1);
- }
- }
- }
- else if (!jobtab[curjob].gleader)
- {
- setpgrp(0L,jobtab[curjob].gleader = getpid());
- if (!bkg)
- attachtty(jobtab[curjob].gleader);
- }
- else
- setpgrp(0L,jobtab[curjob].gleader);
- subsh = 1;
- if (SHTTY != -1)
- {
- close(SHTTY);
- SHTTY = -1;
- }
- if (jobbing)
- {
- signal(SIGTTOU,SIG_DFL);
- signal(SIGTTIN,SIG_DFL);
- signal(SIGTSTP,SIG_DFL);
- signal(SIGPIPE,SIG_DFL);
- }
- if (interact)
- {
- signal(SIGTERM,SIG_DFL);
- if (sigtrapped[SIGINT])
- signal(SIGINT,SIG_IGN);
- }
- if (!sigtrapped[SIGQUIT])
- signal(SIGQUIT,SIG_DFL);
- opts[MONITOR] = OPT_UNSET;
- clearjobtab();
-}
-
-/* close all shell files */
-
-void closem(void)
-{
-int t0;
-
- for (t0 = 10; t0 != NOFILE; t0++)
- close(t0);
-}
-
-/* get here document */
-
-int gethere(char *str)
-{
-char pbuf[256],*nam = gettemp();
-int tfil = creat(nam,0666);
-FILE *in = fdopen(SHIN,"r");
-
- FOREVER
- {
- fgetline(pbuf,256,in);
- if (strcmp(str,pbuf))
- {
- pbuf[strlen(pbuf)] = '\n';
- write(tfil,pbuf,strlen(pbuf));
- }
- else
- break;
- }
- close(tfil);
- tfil = open(nam,O_RDONLY);
- unlink(nam);
- free(nam);
- return(tfil);
-}
-
-void catproc(struct mnode *mn)
-{
-int len,t0;
-char *buf;
-
- if (phork())
- {
- for (t0 = 0; t0 != mn->ct; t0++)
- close(mn->fds[t0]);
- close(mn->pipe);
- return;
- }
- closeallelse(mn);
- buf = zalloc(4096);
- for (t0 = 0; t0 != mn->ct; t0++)
- while (len = read(mn->fds[t0],buf,4096))
- write(mn->pipe,buf,len);
- _exit(0);
-}
-
-void teeproc(struct mnode *mn)
-{
-int len,t0;
-char *buf;
-
- if (phork())
- {
- for (t0 = 0; t0 != mn->ct; t0++)
- close(mn->fds[t0]);
- close(mn->pipe);
- return;
- }
- buf = zalloc(4096);
- closeallelse(mn);
- while ((len = read(mn->pipe,buf,4096)) > 0)
- for (t0 = 0; t0 != mn->ct; t0++)
- write(mn->fds[t0],buf,len);
- _exit(0);
-}
-
-void closeallelse(struct mnode *mn)
-{
-int t0,t1;
-
- for (t0 = 0; t0 != NOFILE; t0++)
- if (mn->pipe != t0)
- {
- for (t1 = 0; t1 != mn->ct; t1++)
- if (mn->fds[t1] == t0)
- break;
- if (t1 == mn->ct)
- close(t0);
- }
-}
-
-/* strtol() doesn't work right on my system */
-
-long int zstrtol(const char *s,char **t,int base)
-{
-int ret = 0;
-
- for (; *s >= '0' && *s < ('0'+base); s++)
- ret = ret*base+*s-'0';
- if (t)
- *t = (char *) s;
- return ret;
-}
-
-/* $(...) */
-
-table getoutput(char *cmd,int qt)
-{
-list list;
-int pipes[2];
-
- if (*cmd == '<')
- {
- int stream;
- char *fi;
-
- fi = strdup(cmd+1);
- if (*fi == '~')
- *fi = Tilde;
- else if (*fi == '=')
- *fi = Equals;
- filesub((void **) &fi);
- if (errflag)
- return NULL;
- stream = open(fi,O_RDONLY);
- if (stream == -1)
- {
- magicerr();
- zerr("%e: %s",errno,cmd+1);
- return NULL;
- }
- return readoutput(stream,qt);
- }
- hungets(strdup(cmd));
- strinbeg();
- if (!(list = parlist(1)))
- {
- strinend();
- hflush();
- return NULL;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- mpipe(pipes);
- if (phork())
- {
- close(pipes[1]);
- return readoutput(pipes[0],qt);
- }
- subsh = 1;
- close(pipes[0]);
- redup(pipes[1],1);
- entersubsh(0);
- signal(SIGTSTP,SIG_IGN);
- exiting = 1;
- execlist(list);
- close(1);
- exit(0); return NULL;
-}
-
-/* read output of command substitution */
-
-table readoutput(int in,int qt)
-{
-table ret;
-char *buf,*ptr;
-int bsiz,c,cnt = 0;
-FILE *fin;
-
- fin = fdopen(in,"r");
- ret = newtable();
- ptr = buf = zalloc(bsiz = 256);
- while ((c = fgetc(fin)) != EOF)
- if (!qt && znspace(c))
- {
- if (cnt)
- {
- *ptr = '\0';
- addnode(ret,strdup(buf));
- cnt = 0;
- ptr = buf;
- }
- }
- else
- {
- *ptr++ = c;
- if (++cnt == bsiz)
- {
- char *pp = zalloc(bsiz *= 2);
-
- memcpy(pp,buf,cnt);
- free(buf);
- ptr = (buf = pp)+cnt;
- }
- }
- if (qt && ptr != buf && ptr[-1] == '\n')
- ptr[-1] = '\0';
- if (cnt)
- addnode(ret,strdup(buf));
- free(buf);
- fclose(fin);
- return ret;
-}
-
-/* =(...) */
-
-char *getoutputfile(char *cmd)
-{
-#ifdef WAITPID
-int pid;
-#endif
-char *nam = gettemp(),*str;
-int tfil;
-list list;
-
- for (str = cmd; *str && *str != Outpar; str++);
- if (!*str)
- zerr("oops.");
- *str = '\0';
- hungets(strdup(cmd));
- strinbeg();
- if (!(list = parlist(1)))
- {
- hflush();
- strinend();
- return NULL;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- if (!jobtab[curjob].filelist)
- jobtab[curjob].filelist = newtable();
- addnode(jobtab[curjob].filelist,strdup(nam));
-#ifdef WAITPID
- if (pid = phork())
- {
- waitpid(pid,NULL,WUNTRACED);
- return nam;
- }
-#else
- if (waitfork())
- return nam;
-#endif
- subsh = 1;
- close(1);
- entersubsh(0);
- tfil = creat(nam,0666);
- exiting = 1;
- execlist(list);
- close(1);
- exit(0); return NULL;
-}
-
-/* get a temporary named pipe */
-
-char *namedpipe(void)
-{
-char *tnam = gettemp();
-
- mknod(tnam,0010666,0);
- return tnam;
-}
-
-/* <(...) */
-
-char *getoutproc(char *cmd)
-{
-list list;
-int fd;
-char *pnam,*str;
-
- for (str = cmd; *str && *str != Outpar; str++);
- if (!*str)
- zerr("oops.");
- *str = '\0';
- hungets(strdup(cmd));
- strinbeg();
- if (!(list = parlist(1)))
- {
- strinend();
- hflush();
- return NULL;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- pnam = namedpipe();
- if (!jobtab[curjob].filelist)
- jobtab[curjob].filelist = newtable();
- addnode(jobtab[curjob].filelist,strdup(pnam));
- if (phork())
- return pnam;
- entersubsh(1);
- fd = open(pnam,O_WRONLY);
- if (fd == -1)
- {
- zerr("can't open %s: %e",pnam,errno);
- _exit(0);
- }
- redup(fd,1);
- fd = open("/dev/null",O_RDONLY);
- redup(fd,0);
- exiting = 1;
- execlist(list);
- close(1);
- _exit(0); return NULL;
-}
-
-/* >(...) */
-
-char *getinproc(char *cmd)
-{
-list list;
-int pid,fd;
-char *pnam,*str;
-
- for (str = cmd; *str && *str != Outpar; str++);
- if (!*str)
- zerr("oops.");
- *str = '\0';
- hungets(strdup(cmd));
- strinbeg();
- if (!(list = parlist(1)))
- {
- strinend();
- hflush();
- return NULL;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- pnam = namedpipe();
- if (!jobtab[curjob].filelist)
- jobtab[curjob].filelist = newtable();
- addnode(jobtab[curjob].filelist,strdup(pnam));
- if (pid = phork())
- return pnam;
- entersubsh(1);
- fd = open(pnam,O_RDONLY);
- redup(fd,0);
- exiting = 1;
- execlist(list);
- _exit(0); return NULL;
-}
-
-/* > >(...) (does not use named pipes) */
-
-int getinpipe(char *cmd)
-{
-list list;
-int pipes[2];
-char *str = cmd;
-
- for (str = cmd; *str && *str != Outpar; str++);
- if (!*str)
- zerr("oops.");
- *str = '\0';
- hungets(strdup(cmd+2));
- strinbeg();
- if (!(list = parlist(1)))
- {
- strinend();
- hflush();
- return -1;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- mpipe(pipes);
- if (phork())
- {
- close(pipes[1]);
- return pipes[0];
- }
- close(pipes[0]);
- entersubsh(1);
- redup(pipes[1],1);
- exiting = 1;
- execlist(list);
- _exit(0); return 0;
-}
-
-/* < <(...) */
-
-int getoutpipe(char *cmd)
-{
-list list;
-int pipes[2];
-char *str;
-
- for (str = cmd; *str && *str != Outpar; str++);
- if (!*str)
- zerr("oops.");
- *str = '\0';
- hungets(strdup(cmd+2));
- strinbeg();
- if (!(list = parlist(1)))
- {
- strinend();
- hflush();
- return -1;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return NULL;
- }
- strinend();
- mpipe(pipes);
- if (phork())
- {
- close(pipes[0]);
- return pipes[1];
- }
- close(pipes[1]);
- entersubsh(1);
- redup(pipes[0],0);
- exiting = 1;
- execlist(list);
- _exit(0); return 0;
-}
-
-/* run a list, saving the current job num */
-
-void runlist(list l)
-{
-int cj = curjob;
-
- execlist(l);
- curjob = cj;
-}
-
-char *gettemp(void)
-{
- return mktemp(strdup("/tmp/zshXXXXXX"));
-}
-
-/* my getwd; all the other ones I tried confused the SIGCHLD handler */
-
-char *zgetwd(void)
-{
-static char buf0[MAXPATHLEN];
-char buf3[MAXPATHLEN],*buf2 = buf0+1;
-struct stat sbuf;
-struct direct *de;
-DIR *dir;
-ino_t ino = -1;
-dev_t dev = -1;
-
- holdintr();
- buf2[0] = '\0';
- buf0[0] = '/';
- for(;;)
- {
- if (stat(".",&sbuf) < 0)
- {
- chdir(buf0);
- noholdintr();
- return strdup(".");
- }
- ino = sbuf.st_ino;
- dev = sbuf.st_dev;
- if (stat("..",&sbuf) < 0)
- {
- chdir(buf0);
- noholdintr();
- return strdup(".");
- }
- if (sbuf.st_ino == ino && sbuf.st_dev == dev)
- {
- chdir(buf0);
- noholdintr();
- return strdup(buf0);
- }
- dir = opendir("..");
- if (!dir)
- {
- chdir(buf0);
- noholdintr();
- return strdup(".");
- }
- chdir("..");
- readdir(dir); readdir(dir);
- while (de = readdir(dir))
- if (de->d_fileno == ino)
- {
- lstat(de->d_name,&sbuf);
- if (sbuf.st_dev == dev)
- goto match;
- }
- rewinddir(dir);
- readdir(dir); readdir(dir);
- while (de = readdir(dir))
- {
- lstat(de->d_name,&sbuf);
- if (sbuf.st_dev == dev)
- goto match;
- }
- noholdintr();
- closedir(dir);
- return strdup(".");
-match:
- strcpy(buf3,de->d_name);
- if (*buf2)
- strcat(buf3,"/");
- strcat(buf3,buf2);
- strcpy(buf2,buf3);
- closedir(dir);
- }
-}
-
-/* open pipes with fds >= 10 */
-
-void mpipe(int pp[2])
-{
- pipe(pp);
- pp[0] = movefd(pp[0]);
- pp[1] = movefd(pp[1]);
-}
-
-/* do process substitution with redirection */
-
-void spawnpipes(table l)
-{
-Node n = l->first;
-struct fnode *f;
-
- for (; n; n = n->next)
- {
- f = n->dat;
- if (f->type == OUTPIPE)
- {
- char *str = f->u.name;
- f->u.fd2 = getoutpipe(str);
- free(str);
- }
- if (f->type == INPIPE)
- {
- char *str = f->u.name;
- f->u.fd2 = getinpipe(str);
- free(str);
- }
- }
-}
-
End of exec.c
echo exec.pro 1>&2
sed 's/^-//' >exec.pro <<'End of exec.pro'
-void execstring(char *s);
-void newrunlist(list l);
-int phork(void);
-void execcursh(comm comm);
-void execute(char *arg0,table args);
-char *findcmd(char *arg0);
-void execlist(list list);
-void execlist1(list list);
-void execlist2(list2 list,int type,int last1);
-int execpline(list2 l,int how,int last1);
-void execpline2(pline pline,int how,int input,int output,int last1);
-char **makecline(char *nam,struct xlist *list);
-void fixcline(table l);
-void untokenize(char *s);
-void addenv(table list);
-int dontclob(struct fnode *f);
-void closemn(struct mnode *mfds[10],int fd);
-void closemnodes(struct mnode *mfds[10]);
-void addfd(int forked,int save[10],struct mnode *mfds[10],int fd1,int fd2,int rflag);
-void execcomm(comm comm,int input,int output,int bkg,int last1);
-void fixfds(int save[10]);
-void entersubsh(int bkg);
-void closem(void);
-int gethere(char *str);
-void catproc(struct mnode *mn);
-void teeproc(struct mnode *mn);
-void closeallelse(struct mnode *mn);
-long int zstrtol(const char *s,char **t,int base);
-table getoutput(char *cmd,int qt);
-table readoutput(int in,int qt);
-char *getoutputfile(char *cmd);
-char *namedpipe(void);
-char *getoutproc(char *cmd);
-char *getinproc(char *cmd);
-int getinpipe(char *cmd);
-int getoutpipe(char *cmd);
-void runlist(list l);
-char *gettemp(void);
-char *zgetwd(void);
-void mpipe(int pp[2]);
-void spawnpipes(table l);
End of exec.pro
echo funcs.h 1>&2
sed 's/^-//' >funcs.h <<'End of funcs.h'
-/*
-
- funcs.h - includes for all prototype files
-
- 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 "glob.pro"
-#include "hist.pro"
-#include "table.pro"
-#include "subst.pro"
-#include "builtin.pro"
-#include "loop.pro"
-#include "jobs.pro"
-#include "exec.pro"
-#include "init.pro"
-#include "lex.pro"
-#include "parse.pro"
-#include "utils.pro"
-#include "test.pro"
-char *readline(char *);
-char *mktemp(char *);
End of funcs.h
echo glob.c 1>&2
sed 's/^-//' >glob.c <<'End of glob.c'
-/*
-
- glob.c - filename generation and brace expansion
-
- 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"
-#ifndef INT_MAX
-#include <limits.h>
-#endif
-#include <sys/dir.h>
-#include <sys/errno.h>
-
-#define exists(X) (access(X,0) == 0)
-#define magicerr() { if (magic) putc('\n',stderr); errflag = 1; }
-
-static int gtype; /* file type for (X) */
-static int mode; /* != 0 if we are parsing glob patterns */
-static int sense; /* (X) or (^X) */
-static int pathpos; /* position in pathbuf */
-static int matchsz; /* size of matchbuf */
-static int matchct; /* number of matches found */
-static char pathbuf[MAXPATHLEN]; /* pathname buffer */
-static char **matchbuf; /* array of matches */
-static char **matchptr; /* &matchbuf[matchct] */
-
-/* pathname component in filename patterns */
-
-/* qath is a struct xpath * */
-
-struct xpath {
- qath next;
- comp comp;
- int closure; /* 1 if this is a (foo/)# */
- };
-struct xcomp {
- comp nx1,nx2;
- char *str;
- };
-
-void glob(table list,Node *np)
-{
-Node node = (*np)->last; /* the node before this one */
-Node next = (*np)->next; /* the node after this one */
-int sl; /* length of the pattern */
-char *ostr; /* the pattern before the parser chops it up */
-char *wd; /* the cwd */
-qath q; /* pattern after parsing */
-char *str = (*np)->dat; /* the pattern */
-
- sl = strlen(str);
- ostr = strdup(str);
- remnode(list,*np);
- gtype = 0;
- if (str[sl-1] == Outpar) /* check for (X) or (^X) */
- {
- if (sl > 4 && str[sl-4] == Inpar && str[sl-3] == Hat)
- sense = 1;
- else if (sl > 3 && str[sl-3] == Inpar)
- sense = 0;
- else
- sense = 2;
- if (sense != 2)
- {
- str[sl-3-sense] = '\0';
- switch (str[sl-2])
- {
- case '@': gtype = S_IFLNK; break;
- case '=': gtype = S_IFSOCK; break;
- case Inang: gtype = S_IFIFO; break;
- case '/': gtype = S_IFDIR; break;
- case '.': gtype = S_IFREG; break;
- case Star: gtype = 0100; break;
- case '%': gtype = S_IFCHR; break;
- case 'R': gtype = 0004; break;
- case 'W': gtype = 0002; break;
- case 'X': gtype = 0001; break;
- case 'r': gtype = 0400; break;
- case 'w': gtype = 0200; break;
- case 'x': gtype = 0100; break;
- default:
- magicerr();
- zerr("unknown file attribute");
- return;
- };
- }
- }
- else if (str[sl-1] == '/') /* foo/ == foo(/) */
- {
- gtype = S_IFDIR;
- sense = 0;
- }
- if (*str == '/') /* pattern has absolute path */
- {
- wd = zgetwd();
- str++;
- chdir("/");
- pathbuf[0] = '/';
- pathbuf[pathpos = 1] = '\0';
- }
- else /* pattern is relative to cwd */
- {
- wd = NULL;
- pathbuf[pathpos = 0] = '\0';
- }
- q = parsepat(str);
- if (!q || errflag) /* if parsing failed */
- {
- if (isset(NOBADPATTERN))
- {
- insnode(list,node,ostr);
- return;
- }
- magicerr();
- zerr("bad pattern: %s",ostr);
- free(ostr);
- return;
- }
- matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
- matchct = 0;
- scanner(q); /* do the globbing */
- freepath(q);
- if (wd) /* reset cwd */
- {
- chdir(wd);
- free(wd);
- }
- if (!matchct && unset(NULLGLOB))
- if (unset(NONOMATCH))
- {
- if (!errflag)
- {
- magicerr();
- zerr("no matches found: %s",ostr);
- }
- free(matchbuf);
- free(ostr);
- errflag = 1;
- return;
- }
- else
- {
- *matchptr++ = strdup(ostr);
- matchct = 1;
- }
- qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
- matchptr = matchbuf;
- while (matchct--) /* insert matches in the arg list */
- insnode(list,node,*matchptr++);
- free(matchbuf);
- free(ostr);
- if (magic)
- magic = 2; /* tell readline we did something */
- *np = (next) ? next->last : list->last;
-}
-
-int notstrcmp(char **a,char **b)
-{
-char *c = *b,*d = *a;
-
- for (; *c == *d && *c; c++,d++);
- return ((int) (unsigned char) *c-(int) (unsigned char) *d);
-}
-
-/* add a match to the list */
-
-void insert(char *s)
-{
-struct stat buf;
-
- if (isset(MARKDIRS) && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) /* grrr */
- {
- char *t;
- int ll = strlen(s);
-
- t = zalloc(ll+2);
- strcpy(t,s);
- t[ll] = '/';
- t[ll+1] = '\0';
- free(s);
- s = t;
- }
- *matchptr++ = s;
- if (++matchct == matchsz)
- {
- matchbuf = (char **) realloc(matchbuf,sizeof(char **)*(matchsz *= 2));
- matchptr = matchbuf+matchct;
- }
-}
-
-/* check to see if str is eligible for filename generation */
-
-int haswilds(char *str)
-{
- if (!str[1] && (*str == Inbrack || *str == Outbrack))
- return 0;
- if (str[0] == '%')
- return 0;
- for (; *str; str++)
- if (!strncmp(str,"..../",5))
- return 1;
- else if (*str == Pound || *str == Hat || *str == Star ||
- *str == Bar || *str == Inbrack || *str == Inang ||
- *str == Quest)
- return 1;
- return 0;
-}
-
-/* check to see if str is eligible for brace expansion */
-
-int hasbraces(char *str)
-{
-int mb,bc,cmct1,cmct2;
-char *lbr = NULL;
-
- if (str[0] == Inbrace && str[1] == Outbrace)
- return 0;
- for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
- {
- if (*str == Inbrace)
- {
- if (!bc)
- lbr = str;
- bc++;
- if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
- {
- cmct1++;
- if (bc == 1)
- cmct2++;
- }
- }
- else if (*str == Outbrace)
- {
- bc--;
- if (!bc && !cmct2)
- {
- *lbr = '{';
- *str = '}';
- }
- cmct2 = 0;
- }
- else if (*str == Comma && bc)
- {
- cmct1++;
- if (bc == 1)
- cmct2++;
- }
- if (bc > mb)
- mb = bc;
- if (bc < 0)
- return 0;
- }
- return (mb && bc == 0 && cmct1);
-}
-
-/* expand stuff like >>*.c */
-
-int xpandredir(struct fnode *fn,table tab)
-{
-table fake;
-char *nam;
-struct fnode *ff;
-int ret = 0;
-
- fake = newtable();
- addnode(fake,fn->u.name);
- prefork(fake);
- if (!errflag)
- postfork(fake,GLOB);
- if (errflag)
- {
- freetable(fake,freestr);
- return 0;
- }
- if (fake->first && !fake->first->next)
- {
- fn->u.name = fake->first->dat;
- untokenize(fn->u.name);
- }
- else
- while (nam = getnode(fake))
- {
- ff = alloc(sizeof(struct fnode));
- ff->u.name = nam;
- ff->type = fn->type;
- addnode(tab,ff);
- ret = 1;
- }
- free(fake);
- return ret;
-}
-
-/* concatenate s1 and s2 in dynamically allocated buffer */
-
-char *dyncat(char *s1,char *s2)
-{
-char *ptr;
-
- ptr = zalloc(strlen(s1)+strlen(s2)+1);
- strcpy(ptr,s1);
- strcat(ptr,s2);
- return ptr;
-}
-
-/* concatenate s1, s2, and s3 in dynamically allocated buffer */
-
-char *tricat(char *s1,char *s2,char *s3)
-{
-char *ptr;
-
- ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
- strcpy(ptr,s1);
- strcat(ptr,s2);
- strcat(ptr,s3);
- return ptr;
-}
-
-/* brace expansion */
-
-void xpandbraces(table list,Node *np)
-{
-Node node = (*np),last = node->last;
-char *str = node->dat,*str3 = str,*str2;
-int prev;
-
- if (magic)
- magic = 2;
- for (; *str != Inbrace; str++);
- if (str[2] == '-' && str[4] == Outbrace) /* {a-z} */
- {
- char c1,c2;
-
- remnode(list,node);
- chuck(str);
- c1 = *str;
- chuck(str);
- chuck(str);
- c2 = *str;
- chuck(str);
- if (istok(c1))
- c1 = tokens[c1-Pound];
- if (istok(c2))
- c2 = tokens[c2-Pound];
- if (c1 < c2)
- for (; c2 >= c1; c2--) /* {a-z} */
- {
- *str = c2;
- insnode(list,last,strdup(str3));
- }
- else
- for (; c2 <= c1; c2++) /* {z-a} */
- {
- *str = c2;
- insnode(list,last,strdup(str3));
- }
- free(str3);
- *np = last->next;
- return;
- }
- prev = str-str3;
- str2 = getparen(str++);
- if (!str2)
- {
- errflag = 1;
- zerr("how did you get this error?");
- return;
- }
- remnode(list,node);
- node = last;
- FOREVER
- {
- char *zz,*str4;
- int cnt;
-
- for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
- Outbrace; str++)
- if (*str == Inbrace)
- cnt++;
- else if (*str == Outbrace)
- cnt--;
- else if (!*str)
- exit(10);
- zz = zalloc(prev+(str-str4)+strlen(str2)+1);
- strncpy(zz,str3,prev);
- zz[prev] = '\0';
- strncat(zz,str4,str-str4);
- strcat(zz,str2);
- insnode(list,node,zz);
- node = node->next;
- if (*str != Outbrace)
- str++;
- else
- break;
- }
- free(str3);
- *np = last->next;
-}
-
-/* get closing paren, given pointer to opening paren */
-
-char *getparen(char *str)
-{
-int cnt = 1;
-char typein = *str++,typeout = typein+1;
-
- for (; *str && cnt; str++)
- if (*str == typein)
- cnt++;
- else if (*str == typeout)
- cnt--;
- if (!str && cnt)
- return NULL;
- return str;
-}
-
-/* check to see if a matches b (b is not a filename pattern) */
-
-int matchpat(char *a,char *b)
-{
-comp c;
-int val;
-
- c = parsereg(b);
- if (!c)
- {
- zerr("bad pattern: %s");
- errflag = 1;
- return NULL;
- }
- val = doesmatch(a,c,0);
- freecomp(c);
- return val;
-}
-
-/* do the ${foo%%bar}, ${foo#bar} stuff */
-/* please do not laugh at this code. */
-
-void getmatch(char **sp,char *pat,int dd)
-{
-comp c;
-char *t,*lng = NULL,cc,*s = *sp;
-
- c = parsereg(pat);
- if (!c)
- {
- magicerr();
- zerr("bad pattern: %s",pat);
- return;
- }
- if (!(dd & 2))
- {
- for (t = s; t==s || t[-1]; t++)
- {
- cc = *t;
- *t = '\0';
- if (doesmatch(s,c,0))
- {
- if (!(dd & 1))
- {
- *t = cc;
- t = strdup(t);
- free(s);
- freecomp(c);
- *sp = t;
- return;
- }
- lng = t;
- }
- *t = cc;
- }
- if (lng)
- {
- t = strdup(lng);
- free(s);
- freecomp(c);
- *sp = t;
- return;
- }
- }
- else
- {
- for (t = s+strlen(s); t >= s; t--)
- {
- if (doesmatch(t,c,0))
- {
- if (!(dd & 1))
- {
- *t = '\0';
- freecomp(c);
- return;
- }
- lng = t;
- }
- }
- if (lng)
- {
- *lng = '\0';
- freecomp(c);
- return;
- }
- }
- freecomp(c);
-}
-
-/* add a component to pathbuf */
-
-void addpath(char *s)
-{
- while (pathbuf[pathpos++] = *s++);
- pathbuf[pathpos-1] = '/';
- pathbuf[pathpos] = '\0';
-}
-
-/* do the globbing */
-
-void scanner(qath q)
-{
-comp c;
-
- if (q->closure) /* (foo/)# */
- if (q->closure == 2) /* (foo/)## */
- q->closure = 1;
- else
- scanner(q->next);
- if (c = q->comp)
- {
- if (!(c->nx1 || c->nx2) && !haswilds(c->str))
- if (q->next)
- {
- char *wd = NULL;
-
- if (errflag)
- return;
- if (islink(c->str) || !strcmp(c->str,".."))
- wd = zgetwd();
- if (!chdir(c->str))
- {
- int oppos = pathpos;
-
- addpath(c->str);
- scanner((q->closure) ? q : q->next);
- if (wd)
- chdir(wd);
- else if (strcmp(c->str,"."))
- chdir("..");
- pathbuf[pathpos = oppos] = '\0';
- }
- else
- {
- magicerr();
- zerr("%e: %s",errno,c->str);
- if (wd)
- chdir(wd);
- else if (strcmp(c->str,"."))
- chdir("..");
- return;
- }
- }
- else
- {
- if (exists(c->str))
- insert(dyncat(pathbuf,c->str));
- }
- else
- {
- char *fn;
- int type,type3,dirs = !!q->next;
- struct direct *de;
- DIR *lock = opendir(".");
- static struct stat buf;
-
- if (lock == NULL)
- {
- magicerr();
- if (errno != EINTR)
- zerr("%e: %s",errno,pathbuf);
- return;
- }
- readdir(lock); readdir(lock); /* skip . and .. */
- while (de = readdir(lock))
- {
- if (errflag)
- break;
- fn = &de->d_name[0];
- if (dirs)
- {
- if (lstat(fn,&buf) == -1)
- {
- magicerr();
- zerr("%e: %s",errno,fn);
- }
- type3 = buf.st_mode & S_IFMT;
- if (type3 != S_IFDIR)
- continue;
- }
- else
- if (gtype) /* do the (X) (^X) stuff */
- {
- if (lstat(fn,&buf) == -1)
- {
- if (errno != ENOENT)
- {
- magicerr();
- zerr("%e: %s",errno,fn);
- }
- continue;
- }
- type3 = (type = buf.st_mode) & S_IFMT;
- if (gtype & 0777)
- {
- if ((!(type & gtype) ^ sense) || type3 == S_IFLNK)
- continue;
- }
- else if (gtype == S_IFCHR)
- {
- if ((type3 != S_IFCHR && type3 != S_IFBLK) ^ sense)
- continue;
- }
- else if ((gtype != type3) ^ sense)
- continue;
- }
- if (doesmatch(fn,c,unset(GLOBDOTS)))
- if (dirs)
- {
- if (!chdir(fn))
- {
- int oppos = pathpos;
-
- addpath(fn);
- scanner((q->closure) ? q : q->next); /* scan next level */
- chdir("..");
- pathbuf[pathpos = oppos] = '\0';
- }
- }
- else
- insert(dyncat(pathbuf,fn));
- }
- closedir(lock);
- }
- }
- else
- {
- zerr("no idea how you got this error message.");
- errflag = 1;
- }
-}
-
-/* do the [..(foo)..] business */
-
-int minimatch(char **pat,char **str)
-{
-char *pt = *pat+1,*s = *str;
-
- for (; *pt != Outpar; s++,pt++)
- if ((*pt != Quest || !*s) && *pt != *s)
- {
- *pat = getparen(*pat)-1;
- return 0;
- }
- *str = s-1;
- return 1;
-}
-
-/* see if str matches c; first means worry about matching . explicitly */
-
-int doesmatch(char *str,comp c,int first)
-{
-char *pat = c->str;
-
- FOREVER
- {
- if (!*pat)
- {
- if (errflag)
- return 0;
- if (!(*str || c->nx1 || c->nx2))
- return 1;
- return (c->nx1 && doesmatch(str,c->nx1,first)) ||
- (c->nx2 && doesmatch(str,c->nx2,first));
- }
- if (first && *str == '.' && *pat != '.')
- return 0;
- if (*pat == Star) /* final * is not expanded to ?#; returns success */
- return 1;
- first = 0;
- if (*pat == Quest && *str)
- {
- str++;
- pat++;
- continue;
- }
- if (*pat == Hat)
- return 1-doesmatch(str,c->nx1,first);
- if (*pat == Inbrack)
- if (pat[1] == Hat)
- {
- for (pat += 2; *pat != Outbrack && *pat; pat++)
- if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack)
- {
- if (pat[-1] <= *str && pat[1] >= *str)
- break;
- }
- else if (*str == *pat)
- break;
- if (!*pat)
- {
- zerr("something is very wrong.");
- return 0;
- }
- if (*pat != Outbrack)
- break;
- pat++;
- str++;
- continue;
- }
- else
- {
- for (pat++; *pat != Outbrack && *pat; pat++)
- if (*pat == Inpar)
- {
- if (minimatch(&pat,&str))
- break;
- }
- else if (*pat == '-' && pat[-1] != Inbrack && pat[1] != Outbrack)
- {
- if (pat[-1] <= *str && pat[1] >= *str)
- break;
- }
- else if (*str == *pat)
- break;
- if (!pat || !*pat)
- {
- zerr("oh dear. that CAN'T be right.");
- return 0;
- }
- if (*pat == Outbrack)
- break;
- for (str++; *pat != Outbrack; pat++);
- pat++;
- continue;
- }
- if (*pat == Inang)
- {
- int t1,t2,t3;
- char *ptr;
-
- if (*++pat == Outang) /* handle <> case */
- {
- (void) zstrtol(str,&ptr,10);
- if (ptr == str)
- break;
- str = ptr;
- pat++;
- }
- else
- {
- t1 = zstrtol(str,&ptr,10);
- if (ptr == str)
- break;
- str = ptr;
- t2 = zstrtol(pat,&ptr,10);
- if (*ptr != '-')
- exit(31);
- t3 = zstrtol(ptr+1,&pat,10);
- if (!t3)
- t3 = INT_MAX;
- if (*pat++ != Outang)
- exit(21);
- if (t1 < t2 || t1 > t3)
- break;
- }
- continue;
- }
- if (*str == *pat)
- {
- str++;
- pat++;
- continue;
- }
- break;
- }
- return 0;
-}
-
-static char *pptr;
-
-qath parsepat(char *str)
-{
- mode = 0;
- pptr = str;
- return parseqath();
-}
-
-comp parsereg(char *str)
-{
- mode = 1;
- pptr = str;
- return parsecompsw();
-}
-
-qath parseqath(void)
-{
-comp c1;
-qath p1;
-
- if (pptr[0] == '.' && pptr[1] == '.' && pptr[2] == '.' && pptr[3] ==
- '.' && pptr[4] == '/')
- {
- pptr[0] = Inpar;
- pptr[1] = Star;
- pptr[2] = '/';
- pptr[3] = Outpar;
- pptr[4] = Pound; /* "..../" -> "( * /)#" */
- }
- if (*pptr == Inpar)
- {
- char *str;
- int pars = 1;
-
- for (str = pptr+1; *str && pars; str++)
- if (*str == Inpar)
- pars++;
- else if (*str == Outpar)
- pars--;
- if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/')
- goto kludge;
- pptr++;
- if (!(c1 = parsecompsw()))
- return NULL;
- if (pptr[0] == '/' && pptr[1] == Outpar && pptr[2] == Pound)
- {
- int pdflag = 0;
-
- pptr += 3;
- if (*pptr == Pound)
- {
- pdflag = 1;
- pptr++;
- }
- p1 = (qath) alloc(sizeof(struct xpath));
- p1->comp = c1;
- p1->closure = 1+pdflag;
- p1->next = parseqath();
- return (p1->comp) ? p1 : NULL;
- }
- }
- else
- {
-kludge:
- if (!(c1 = parsecompsw()))
- return NULL;
- if (*pptr == '/' || !*pptr)
- {
- int ef = *pptr == '/';
-
- p1 = (qath) alloc(sizeof(struct xpath));
- p1->comp = c1;
- p1->closure = 0;
- p1->next = (*pptr == '/') ? (pptr++,parseqath()) : NULL;
- return (ef && !p1->next) ? NULL : p1;
- }
- }
- magicerr();
- errflag = 1;
- return NULL;
-}
-
-comp parsecomp(void)
-{
-comp c = (comp) alloc(sizeof(struct xcomp)),c1,c2;
-char *s = c->str = alloc(MAXPATHLEN*2),*ls = NULL;
-
- c->nx2 = NULL;
- while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
- *pptr != Outpar)
- {
- if (*pptr == Hat)
- {
- *s++ = Hat;
- *s++ = '\0';
- pptr++;
- if (!(c->nx1 = parsecomp()))
- {
- free(c->str);
- free(c);
- return NULL;
- }
- return c;
- }
- if (*pptr == Star && pptr[1] && (mode || pptr[1] != '/'))
- {
- *s++ = '\0';
- pptr++;
- c->nx1 = c1 = (comp) alloc(sizeof(struct xcomp));
- *((c1->nx1 = c1)->str = strdup("?")) = Quest;
- c->nx2 = c1->nx2 = parsecomp();
- return (c->nx2) ? c : NULL;
- }
- if (*pptr == Inpar)
- {
- *s++ = '\0';
- pptr++;
- c->nx1 = c1 = parsecompsw();
- if (*pptr != Outpar)
- {
- errflag = 1;
- free(c);
- free(c->str);
- return NULL;
- }
- pptr++;
- if (*pptr == Pound)
- {
- int dpnd = 0;
-
- pptr++;
- if (*pptr == Pound)
- {
- pptr++;
- dpnd = 1;
- }
- c2 = parsecomp();
- if (dpnd)
- c->nx2 = NULL;
- else
- c->nx2 = c2;
- if (!c2)
- {
- free(c);
- free(c->str);
- return NULL;
- }
- adjustcomp(c1,c2,c1);
- return c;
- }
- c2 = parsecomp();
- if (!c2)
- {
- free(c);
- free(c->str);
- return NULL;
- }
- adjustcomp(c1,c2,NULL);
- return c;
- }
- if (*pptr == Pound)
- {
- int dpnd = 0;
-
- *s = '\0';
- pptr++;
- if (*pptr == Pound)
- {
- pptr++;
- dpnd = 1;
- }
- if (!ls)
- return NULL;
- c->nx1 = c1 = (comp) alloc(sizeof(struct xcomp));
- (c1->nx2 = c1)->str = strdup(ls);
- c->nx2 = c1->nx1 = parsecomp();
- if (!c->nx2)
- {
- free(c);
- free(c->str);
- return NULL;
- }
- if (dpnd)
- c->nx2 = NULL;
- *ls++ = '\0';
- return c;
- }
- ls = s;
- if (*pptr == Inang)
- {
- int dshct;
-
- dshct = (pptr[1] == Outang);
- *s++ = *pptr++;
- while (*pptr && (*s++ = *pptr++) != Outang)
- if (s[-1] == '-')
- dshct++;
- else if (!isdigit(s[-1]))
- break;
- if (s[-1] != Outang || dshct != 1)
- {
- free(c);
- free(c->str);
- return NULL;
- }
- }
- else if (*pptr == Inbrack)
- {
- while (*pptr && (*s++ = *pptr++) != Outbrack);
- if (s[-1] != Outbrack)
- {
- free(c);
- free(c->str);
- return NULL;
- }
- }
- else if (istok(*pptr) && *pptr != Star && *pptr != Quest)
- *s++ = tokens[*pptr++-Pound];
- else
- *s++ = *pptr++;
- }
- *s++ = '\0';
- c->nx1 = NULL;
- return c;
-}
-
-comp parsecompsw(void)
-{
-comp c1,c2,c3;
-
- c1 = parsecomp();
- if (!c1)
- return NULL;
- if (*pptr == Bar)
- {
- c2 = (comp) alloc(sizeof(struct xcomp));
- pptr++;
- c3 = parsecompsw();
- if (!c3)
- return NULL;
- c2->str = strdup("");
- c2->nx1 = c1;
- c2->nx2 = c3;
- return c2;
- }
- return c1;
-}
-
-#define MARKER ((void *) 1L)
-
-void adjustcomp(comp c1,comp c2,comp c3)
-{
-comp z;
-
- if (c1->nx1 == c2 && c1->nx2 == c3)
- return;
- if (c1->nx1)
- {
- if ((z = c1->nx1) == MARKER)
- return;
- c1->nx1 = MARKER;
- adjustcomp(z,c2,c3);
- c1->nx1 = z;
- }
- if (c1->nx2)
- adjustcomp(c1->nx2,c2,c3);
- if (!(c1->nx1 || c1->nx2))
- {
- c1->nx1 = c2;
- c1->nx2 = c3;
- }
-}
-
-void freepath(qath p)
-{
- if (p)
- {
- freepath(p->next);
- freecomp(p->comp);
- free(p);
- }
-}
-
-void freecomp(comp c)
-{
- if (c && c->str)
- {
- free(c->str);
- c->str = NULL;
- freecomp(c->nx1);
- freecomp(c->nx2);
- free(c);
- }
-}
-
-/* tokenize and see if ss matches tt */
-
-int patmatch(char *ss,char *tt)
-{
-char *s = ss,*t;
-
- for (; *s; s++)
- if (*s == '\\')
- chuck(s);
- else
- for (t = tokens; *t; t++)
- if (*t == *s)
- {
- *s = (t-tokens)+Pound;
- break;
- }
- return matchpat(ss,tt);
-}
-
-/* remove unnecessary Nulargs */
-
-void remnulargs(char *s)
-{
-int nl = *s;
-char *t = s;
-
- while (*s)
- if (*s == Nularg)
- chuck(s);
- else
- s++;
- if (!*t && nl)
- {
- t[0] = Nularg;
- t[1] = '\0';
- }
-}
-
End of glob.c
echo glob.pro 1>&2
sed 's/^-//' >glob.pro <<'End of glob.pro'
-void glob(table list,Node *np);
-int notstrcmp(char **a,char **b);
-void insert(char *s);
-int haswilds(char *str);
-int hasbraces(char *str);
-int xpandredir(struct fnode *fn,table tab);
-char *dyncat(char *s1,char *s2);
-char *tricat(char *s1,char *s2,char *s3);
-void xpandbraces(table list,Node *np);
-char *getparen(char *str);
-int matchpat(char *a,char *b);
-void getmatch(char **sp,char *pat,int dd);
-void addpath(char *s);
-void scanner(qath q);
-int minimatch(char **pat,char **str);
-int doesmatch(char *str,comp c,int first);
-qath parsepat(char *str);
-comp parsereg(char *str);
-qath parseqath(void);
-comp parsecomp(void);
-comp parsecompsw(void);
-void adjustcomp(comp c1,comp c2,comp c3);
-void freepath(qath p);
-void freecomp(comp c);
-int patmatch(char *ss,char *tt);
-void remnulargs(char *s);
End of glob.pro
echo hist.c 1>&2
sed 's/^-//' >hist.c <<'End of hist.c'
-/*
-
- hist.c - ! history
-
- 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"
-
-int lastc;
-
-/* add a character to the current history word */
-
-void hwaddc(int c)
-{
- if (hlastw)
- {
- if (c == EOF || c == HERR)
- return;
- *hlastp++ = c;
- if (hlastp-hlastw == hlastsz)
- {
- hlastw = realloc(hlastw,hlastsz *= 2);
- hlastp = hlastw+(hlastsz/2);
- }
- }
-}
-
-#define habort() { errflag = 1; return HERR; }
-
-/* get a character after performing history substitution */
-
-int hgetc(void)
-{
-int c,ev,farg,larg,argc,marg = -1,cflag = 0,bflag = 0;
-char buf[256],*ptr;
-table slist,elist;
-
-tailrec:
- c = hgetch();
- if (stophist)
- {
- hwaddc(c);
- return c;
- }
- if (firstch && c == '^' && !(ungots && !magic))
- {
- firstch = 0;
- hungets(strdup(":s^"));
- c = '!';
- goto hatskip;
- }
- if (c != ' ')
- firstch = 0;
- if (c == '\\')
- {
- int g = hgetch();
-
- if (g != '!')
- hungetch(g);
- else
- {
- hwaddc('!');
- return '!';
- }
- }
- if (c != '!' || (ungots && !magic))
- {
- hwaddc(c);
- return c;
- }
-hatskip:
- if ((c = hgetch()) == '{')
- {
- bflag = cflag = 1;
- c = hgetch();
- }
- if (c == '\"')
- {
- stophist = 1;
- goto tailrec;
- }
- if (!cflag && znspace(c) || c == '=' || c == '(')
- {
- hungetch(c);
- hwaddc('!');
- return '!';
- }
- cflag = 0;
- ptr = buf;
-
- /* get event number */
-
- if (c == '?')
- {
- FOREVER
- {
- c = hgetch();
- if (c == '?' || c == '\n')
- break;
- else
- *ptr++ = c;
- }
- if (c != '\n')
- c = hgetch();
- *ptr = NULL;
- ev = hconsearch(last = strdup(buf),&marg);
- if (ev == -1)
- {
- herrflush();
- zerr("no such event: %s",buf);
- habort();
- }
- }
- else
- {
- int t0;
-
- FOREVER
- {
- if (znspace(c) || c == ':' || c == '^' || c == '$' || c == '*'
- || c == '%' || c == '}')
- break;
- if (ptr != buf && c == '-')
- break;
- *ptr++ = c;
- if (c == '#' || c == '!')
- {
- c = hgetch();
- break;
- }
- c = hgetch();
- }
- *ptr = 0;
- if (!*buf)
- ev = dev;
- else if (t0 = atoi(buf))
- ev = (t0 < 0) ? cev+t0 : t0;
- else if (*buf == '!')
- ev = cev-1;
- else if (*buf == '#')
- ev = cev;
- else if ((ev = hcomsearch(buf)) == -1)
- {
- zerr("event not found: %s",buf);
- while (c != '\n')
- c = hgetch();
- habort();
- }
- }
-
- /* get the event */
-
- if (!(elist = getevent(dev = ev)))
- habort();
-
- /* extract the relevant arguments */
-
- argc = getargc(elist)-1;
- if (c == ':')
- {
- cflag = 1;
- c = hgetch();
- }
- if (c == '*')
- {
- farg = 1;
- larg = argc;
- cflag = 0;
- }
- else
- {
- hungetch(c);
- larg = farg = getargspec(argc,marg);
- if (larg == -2)
- habort();
- if (farg != -1)
- cflag = 0;
- c = hgetch();
- if (c == '*')
- {
- cflag = 0;
- larg = argc;
- }
- else if (c == '-')
- {
- cflag = 0;
- larg = getargspec(argc,marg);
- if (larg == -2)
- habort();
- if (larg == -1)
- larg = argc-1;
- }
- else
- hungetch(c);
- }
- if (farg == -1)
- farg = 0;
- if (larg == -1)
- larg = argc;
- if (!(slist = getargs(elist,farg,larg)))
- habort();
-
- /* do the modifiers */
-
- FOREVER
- {
- c = (cflag) ? ':' : hgetch();
- cflag = 0;
- if (c == ':')
- {
- int gbal = 0;
-
- if ((c = hgetch()) == 'g')
- {
- gbal = 1;
- c = hgetch();
- }
- switch(c)
- {
- case 'p':
- hflag = 2;
- break;
- case 'h':
- if (!apply1(gbal,remtpath,slist))
- {
- herrflush();
- zerr("modifier failed: h");
- habort();
- }
- break;
- case 'e':
- if (!apply1(gbal,rembutext,slist))
- {
- herrflush();
- zerr("modifier failed: e");
- habort();
- }
- break;
- case 'r':
- if (!apply1(gbal,remtext,slist))
- {
- herrflush();
- zerr("modifier failed: r");
- habort();
- }
- break;
- case 't':
- if (!apply1(gbal,remlpaths,slist))
- {
- herrflush();
- zerr("modifier failed: t");
- habort();
- }
- break;
- case 's':
- {
- int del;
- char *ptr1,*ptr2;
-
- del = hgetch();
- ptr1 = hdynread(del);
- if (!ptr1)
- habort();
- ptr2 = hdynread2(del);
- if (strlen(ptr1))
- {
- if (last)
- free(last);
- last = ptr1;
- }
- if (rast)
- free(rast);
- rast = ptr2;
- }
- case '&':
- if (last && rast)
- {
- if (subst(gbal,slist,last,rast))
- habort();
- }
- else
- {
- herrflush();
- zerr("no previous substitution with &");
- habort();
- }
- break;
- case 'q':
- apply1(0,quote,slist);
- break;
- case 'x':
- apply1(0,quotebreak,slist);
- break;
- default:
- herrflush();
- zerr("illegal modifier: %c",c);
- habort();
- break;
- }
- }
- else
- {
- if (c != '}' || !bflag)
- hungetch(c);
- if (c != '}' && bflag)
- {
- zerr("'}' expected");
- habort();
- }
- break;
- }
- }
-
- /* stuff the resulting string in the input queue and start over */
-
- hungets(makehlist(slist,1));
- hflag |= 1;
- goto tailrec;
-}
-
-/* begin reading a string */
-
-void strinbeg(void)
-{
- strin = 1;
-}
-
-/* done reading a string */
-
-void strinend(void)
-{
- strin = 0;
- firstch = 1;
- hflag = 0;
- free(ungots);
- ungotptr = ungots = NULL;
- peek = EMPTY;
-}
-
-static char *line = NULL,*oline = NULL;
-
-/* stuff a whole FILE into the input queue */
-
-int stuff(char *fn)
-{
-FILE *in;
-char *buf;
-int len;
-
- if (!(in = fopen(fn,"r")))
- {
- zerr("can't open %s",fn);
- return 1;
- }
- fseek(in,0,2);
- len = ftell(in);
- fseek(in,0,0);
- buf = alloc(len+1);
- if (!(fread(buf,len,1,in)))
- {
- zerr("read error on %s",fn);
- fclose(fn);
- free(buf);
- return 1;
- }
- fclose(in);
- if (!line)
- line = oline = buf;
- else
- {
- line = dyncat(line,buf);
- free(oline);
- oline = line;
- }
- return 0;
-}
-
-/* get a char without history */
-
-int hgetch(void)
-{
-char *pmpt = NULL,*s;
-
- if (ungots)
- {
- if (*ungotptr)
- {
- if (*ungotptr == ALPOP) /* done expanding an alias,
- pop the alias stack */
- {
- if (!alix)
- {
- ungotptr++;
- return lastc = HERR;
- }
- alstack[--alix]->inuse = 0;
- s = alstack[alix]->text;
- if (*s && s[strlen(s)-1] == ' ')
- alstat = ALSTAT_MORE;
- else
- alstat = ALSTAT_JUNK;
- ungotptr++;
- return lastc = hgetch();
- }
- return lastc = *ungotptr++;
- }
- if (strin)
- return lastc = EOF;
- ungotptr = 0;
- free(ungots);
- ungots = NULL;
- }
-kludge:
- if (errflag)
- {
- if (oline)
- free(oline);
- oline = line = NULL;
- return lastc = HERR;
- }
- if (line && *line)
- return lastc = (*line++);
- if (line)
- free(oline);
- if (interact)
- if (!firstln)
- pmpt = putprompt("PROMPT2");
- else
- pmpt = putprompt("PROMPT");
- if (interact && SHTTY == -1)
- write(2,pmpt,strlen(pmpt));
- oline = line = (interact && SHTTY != -1) ? readline(pmpt) :
- fgets(zalloc(256),256,bshin);
- if (isset(VERBOSE) && line)
- fputs(line,stderr);
- if (!line)
- return lastc = EOF;
- if (line[strlen(line)-1] == '\n')
- lineno++;
- firstch = 1;
- firstln = 0;
- goto kludge;
-}
-
-/* unget a character */
-
-void hungetch(int c)
-{
-static char ubuf2[] = {'x',0};
-
- if (c == EOF)
- return;
- ubuf2[0] = c;
- hungets(strdup(ubuf2));
-}
-
-/* unget a character and remove it from the history word */
-
-void hungetc(int c)
-{
- if (hlastw)
- {
- if (hlastw == hlastp)
- zerr("hungetc attempted at buffer start");
- else
- hlastp--;
- }
- hungetch(c);
-}
-
-void hflush(void)
-{
- if (ungots)
- free(ungots);
- ungots = ungotptr = NULL;
-}
-
-/* unget a string into the input queue */
-
-void hungets(char *str)
-{
- if (ungots && !*ungotptr)
- {
- free(ungots);
- ungots = NULL;
- }
- if (ungots)
- {
- char *ptr;
-
- ptr = dyncat(str,ungotptr);
- free(ungots);
- free(str);
- ungotptr = ungots = ptr;
- }
- else
- ungots = ungotptr = str;
-}
-
-/* initialize the history mechanism */
-
-void hbegin(void)
-{
- firstln = firstch = 1;
- histremmed = errflag = hflag = 0;
- stophist = isset(NOBANGHIST);
- if (interact)
- {
- inittty();
- dev = cev++;
- while (cev-tfev >= tevs)
- {
- freetable(getnode(histlist),freestr);
- tfev++;
- }
- addnode(histlist,curtab = newtable());
- }
-}
-
-void inittty(void)
-{
- attachtty(shpgrp);
- settyinfo(&shttyinfo);
-}
-
-/* say we're done using the history mechanism */
-
-int hend(void)
-{
-char *ptr;
-int flag;
-
- if (!interact)
- return 1;
- if (!curtab)
- return 0;
- flag = hflag;
- hflag = 0;
- if (curtab->first && (*(char *) curtab->last->dat == '\n'))
- free(remnode(curtab,curtab->last));
- if (!curtab->first)
- {
- freetable(remnode(histlist,histlist->last),freestr);
- cev--;
- flag = 0;
- }
- if (flag)
- {
- fprintf(stderr,"%s\n",ptr = makehlist(curtab,0));
- free(ptr);
- }
- curtab = NULL;
- return !(flag & 2 || errflag);
-}
-
-/* remove the current line from the history list */
-
-void remhist(void)
-{
- if (!interact)
- return;
- if (!histremmed)
- {
- histremmed = 1;
- freetable(remnode(histlist,histlist->last),freestr);
- cev--;
- }
-}
-
-/* begin a word */
-
-void hwbegin(void)
-{
- if (hlastw)
- free(hlastw);
- hlastw = hlastp = zalloc(hlastsz = 32);
-}
-
-/* add a word to the history list */
-
-char *hwadd(void)
-{
-char *ret = hlastw;
-
- if (hlastw)
- *hlastp = '\0';
- if (hlastw && lastc != EOF && !errflag)
- if (curtab && !alix/* && alstat != ALSTAT_JUNK*/)
- {
- addnode(curtab,hlastw);
- hlastw = NULL;
- }
- if (alstat == ALSTAT_JUNK)
- alstat = 0;
- return ret;
-}
-
-/* get an argument specification */
-
-int getargspec(int argc,int marg)
-{
-int c,ret = -1;
-
- if ((c = hgetch()) == '0')
- return 0;
- if (isdigit(c))
- {
- ret = 0;
- while (isdigit(c))
- {
- ret = ret*10+c-'0';
- c = hgetch();
- }
- hungetch(c);
- }
- else if (c == '^')
- ret = 1;
- else if (c == '$')
- ret = argc;
- else if (c == '%')
- {
- if (marg == -1)
- {
- herrflush();
- zerr("%% with no previous word matched");
- return -2;
- }
- ret = marg;
- }
- else
- hungetch(c);
- return ret;
-}
-
-/* do ?foo? search */
-
-int hconsearch(char *str,int *marg)
-{
-int t0,t1;
-Node node,node2;
-
- if (cev-tfev < 1)
- return -1;
- for (t0 = cev-1,node = histlist->last->last;
- t0 >= tfev; t0--,node = node->last)
- for (t1 = 0,node2 = ((table) node->dat)->first; node2; t1++,node2 =
- node2->next)
- if (strstr(node2->dat,str))
- {
- *marg = t1;
- return t0;
- }
- return -1;
-}
-
-/* do !foo search */
-
-int hcomsearch(char *str)
-{
-int t0;
-Node node,node2;
-
- if (cev-tfev < 1)
- return -1;
- for (t0 = cev-1,node = histlist->last->last; t0 >= tfev;
- t0--,node = node->last)
- if ((node2 = ((table) node->dat)->first)->dat &&
- strstr(node2->dat,str))
- return t0;
- return -1;
-}
-
-/* apply func to a list */
-
-int apply1(int gflag,int (*func)(void **),table list)
-{
-Node node;
-int flag = 0;
-
- for (node = list->first; node; node = node->next)
- if ((flag |= func(&node->dat)) && !gflag)
- return 1;
- return flag;
-}
-
-/* various utilities for : modifiers */
-
-int remtpath(void **junkptr)
-{
-char *str = *junkptr,*cut;
-
- if (cut = strrchr(str,'/'))
- {
- *cut = NULL;
- return 1;
- }
- return 0;
-}
-
-int remtext(void **junkptr)
-{
-char *str = *junkptr,*cut;
-
- if ((cut = strrchr(str,'.')) && cut != str)
- {
- *cut = NULL;
- return 1;
- }
- return 0;
-}
-
-int rembutext(void **junkptr)
-{
-char *str = *junkptr,*cut;
-
- if ((cut = strrchr(str,'.')) && cut != str)
- {
- *junkptr = strdup(cut+1); /* .xx or xx? */
- free(str);
- return 1;
- }
- return 0;
-}
-
-int remlpaths(void **junkptr)
-{
-char *str = *junkptr,*cut;
-
- if (cut = strrchr(str,'/'))
- {
- *cut = NULL;
- *junkptr = strdup(cut+1);
- free(str);
- return 1;
- }
- return 0;
-}
-
-int subst(int gbal,table slist,char *ptr1,char *ptr2)
-{
-Node node;
-int iflag = 0;
-
- for (node = slist->first; node; )
- if (subststr(&node->dat,ptr1,ptr2,gbal))
- {
- iflag = 1;
- if (!gbal)
- return 0;
- }
- else
- node = node->next;
- if (!iflag)
- {
- herrflush();
- zerr("string not found: %s",ptr1);
- return 1;
- }
- return 0;
-}
-
-int subststr(void **strptr,char *in,char *out,int gbal)
-{
-char *str = *strptr,*cut,*sptr,*ss;
-int ret = 0;
-
-maze:
- if (cut = (char *) strstr(str,in))
- {
- char *incop;
-
- incop = strdup(in);
- *cut = '\0';
- cut += strlen(in);
- ss = *strptr;
- *strptr = tricat(*strptr,sptr = convamps(out,incop),cut);
- free(ss);
- free(sptr);
- free(incop);
- if (gbal)
- {
- str = (char *) *strptr+(cut-str)+strlen(in);
- ret = 1;
- goto maze;
- }
- return 1;
- }
- return ret;
-}
-
-char *convamps(char *out,char *in)
-{
-char *ptr,*ret,*pp;
-int slen,inlen = strlen(in);
-
- for (ptr = out, slen = 0; *ptr; ptr++,slen++)
- if (*ptr == '\\')
- ptr++;
- else if (*ptr == '&')
- slen += inlen-1;
- ret = pp = zalloc(slen+1);
- for (ptr = out; *ptr; ptr++)
- if (*ptr == '\\')
- *pp++ = *++ptr;
- else if (*ptr == '&')
- {
- strcpy(pp,in);
- pp += inlen;
- }
- else
- *pp++ = *ptr;
- *pp = '\0';
- return ret;
-}
-
-/* make a string out of a history list */
-
-char *makehlist(table tab,int freeit)
-{
-int ccnt;
-Node node;
-char *ret,*ptr;
-char sep = *ifs;
-
- for (ccnt = 0, node = (freeit == 2) ? tab->first->next : tab->first;
- node; node = node->next)
- ccnt += strlen(node->dat)+1;
- if (!ccnt)
- return strdup("");
- ptr = ret = zalloc(ccnt);
- for (node = (freeit == 2) ? tab->first->next : tab->first;
- node; node = node->next)
- {
- strcpy(ptr,node->dat);
- ptr += strlen(node->dat);
- if (freeit == 1)
- free(node->dat);
- *ptr++ = sep;
- }
- *--ptr = '\0';
- return ret;
-}
-
-table quietgetevent(int ev)
-{
-Node node;
-
- ev -= tfev;
- for (node = histlist->first; ev && node; node = node->next, ev--);
- if (ev)
- return NULL;
- return node->dat;
-}
-
-table getevent(int ev)
-{
-Node node;
-int oev = ev;
-
- ev -= tfev;
- for (node = histlist->first; ev && node; node = node->next, ev--);
- if (ev || !node)
- {
- herrflush();
- zerr("no such event: %d",oev);
- return NULL;
- }
- return node->dat;
-}
-
-int getargc(table tab)
-{
-int argc;
-Node node;
-
- for (argc = 0, node = tab->first; node; node = node->next, argc++);
- return argc;
-}
-
-table getargs(table elist,int arg1,int arg2)
-{
-table ret = newtable();
-Node node;
-int oarg1 = arg1,oarg2 = arg2;
-
- for (node = elist->first; arg1 && node; node = node->next, arg1--,arg2--);
- if (!node)
- {
- herrflush();
- zerr("no such word in event: %d",oarg1);
- return NULL;
- }
- for (arg2++; arg2 && node; node = node->next, arg2--)
- addnode(ret,strdup(node->dat));
- if (arg2 && !node)
- {
- herrflush();
- zerr("no such word in event: %d",oarg2);
- return NULL;
- }
- return ret;
-}
-
-int quote(void **tr)
-{
-char *ptr,*rptr,**str = (char **) tr;
-int len = 1;
-
- for (ptr = *str; *ptr; ptr++,len++)
- if (*ptr == '\'')
- len += 3;
- ptr = *str;
- *str = rptr = alloc(len);
- for (ptr = *str; *ptr; )
- if (*ptr == '\'')
- {
- *rptr++ = '\'';
- *rptr++ = '\\';
- *rptr++ = '\'';
- *rptr++ = '\'';
- ptr++;
- }
- else
- *rptr++ = *ptr++;
- return 0;
-}
-
-int quotebreak(void **tr)
-{
-char *ptr,*rptr,**str = (char **) tr;
-int len = 1;
-
- for (ptr = *str; *ptr; ptr++,len++)
- if (*ptr == '\'')
- len += 3;
- else if (znspace(*ptr))
- len += 2;
- ptr = *str;
- *str = rptr = alloc(len);
- for (ptr = *str; *ptr; )
- if (*ptr == '\'')
- {
- *rptr++ = '\'';
- *rptr++ = '\\';
- *rptr++ = '\'';
- *rptr++ = '\'';
- ptr++;
- }
- else if (znspace(*ptr))
- {
- *rptr++ = '\'';
- *rptr++ = *ptr++;
- *rptr++ = '\'';
- }
- else
- *rptr++ = *ptr++;
- return 0;
-}
-
-void stradd(char **p,char *d)
-{
-char *s = *p;
-
- while (*s++ = *d++);
- *p = s-1;
-}
-
-/* get a prompt string */
-
-char *putprompt(char *fm)
-{
-char *ss,*ttyname(int);
-static char buf[256];
-char *bp = buf;
-int t0;
-struct tm *tm = NULL;
-time_t timet;
-
- clearerr(stdin);
- fm = getparm(fm);
- for(;*fm;fm++)
- {
- if (bp-buf >= 220)
- break;
- if (*fm == '%')
- switch (*++fm)
- {
- case '~':
- if (!strncmp(cwd,home,t0 = strlen(home)))
- {
- *bp++ = '~';
- stradd(&bp,cwd+t0);
- break;
- }
- case 'd':
- case '/':
- stradd(&bp,cwd);
- break;
- case 'c':
- case '.':
- for (ss = cwd+strlen(cwd); ss > cwd; ss--)
- if (*ss == '/')
- {
- ss++;
- break;
- }
- stradd(&bp,ss);
- break;
- case 'h':
- case '!':
- sprintf(bp,"%d",cev);
- bp += strlen(bp);
- break;
---cut here---cut here---cut here---
More information about the Alt.sources
mailing list