home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- * UNIX shell
- *
- * S. R. Bourne
- * Bell Telephone Laboratories
- *
- */
-
- #include "defs.h"
-
-
- PROC VOID gsort();
-
- #define ARGMK 01
-
- INT errno;
- STRING sysmsg[];
-
- /* fault handling */
- #define ENOMEM 12
- #define ENOEXEC 8
- #define E2BIG 7
- #define ENOENT 2
- #define ETXTBSY 26
-
-
-
- /* service routines for `execute' */
-
- VOID initio(iop)
- IOPTR iop;
- {
- REG STRING ion;
- REG INT iof, fd;
-
- IF iop
- THEN iof=iop->iofile;
- ion=mactrim(iop->ioname);
- IF *ion ANDF (flags&noexec)==0
- THEN IF iof&IODOC
- THEN subst(chkopen(ion),(fd=tmpfil()));
- close(fd); fd=chkopen(tmpout); unlink(tmpout);
- ELIF iof&IOMOV
- THEN IF eq(minus,ion)
- THEN fd = -1;
- close(iof&IOUFD);
- ELIF (fd=stoi(ion))>=USERIO
- THEN failed(ion,badfile);
- ELSE fd=dup(fd);
- FI
- ELIF (iof&IOPUT)==0
- THEN fd=chkopen(ion);
- ELIF flags&rshflg
- THEN failed(ion,restricted);
- ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0
- THEN lseek(fd, 0L, 2);
- ELSE fd=create(ion);
- FI
- IF fd>=0
- THEN rename(fd,iof&IOUFD);
- FI
- FI
- initio(iop->ionxt);
- FI
- }
-
- STRING getpath(s)
- STRING s;
- {
- REG STRING path;
- IF any('/',s)
- THEN IF flags&rshflg
- THEN failed(s, restricted);
- ELSE return(nullstr);
- FI
- ELIF (path = pathnod.namval)==0
- THEN return(defpath);
- ELSE return(cpystak(path));
- FI
- }
-
- INT pathopen(path, name)
- REG STRING path, name;
- {
- REG UFD f;
-
- REP path=catpath(path,name);
- PER (f=open(curstak(),0))<0 ANDF path DONE
- return(f);
- }
-
- STRING catpath(path,name)
- REG STRING path;
- STRING name;
- {
- /* leaves result on top of stack */
- REG STRING scanp = path,
- argp = locstak();
-
- WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD
- IF scanp!=path THEN *argp++='/' FI
- IF *scanp==COLON THEN scanp++ FI
- path=(*scanp ? scanp : 0); scanp=name;
- WHILE (*argp++ = *scanp++) DONE
- return(path);
- }
-
- LOCAL STRING xecmsg;
- LOCAL STRING *xecenv;
-
- VOID execa(at)
- STRING at[];
- {
- REG STRING path;
- REG STRING *t = at;
-
- IF (flags&noexec)==0
- THEN xecmsg=notfound; path=getpath(*t);
- namscan(exname);
- xecenv=setenv();
- WHILE path=execs(path,t) DONE
- failed(*t,xecmsg);
- FI
- }
-
- LOCAL STRING execs(ap,t)
- STRING ap;
- REG STRING t[];
- {
- REG STRING p, prefix;
-
- prefix=catpath(ap,t[0]);
- trim(p=curstak());
-
- sigchk();
- execve(p, &t[0] ,xecenv);
- SWITCH errno IN
-
- case ENOEXEC:
- flags=0;
- comdiv=0; ioset=0;
- clearup(); /* remove open files and for loop junk */
- IF input THEN close(input) FI
- close(output); output=2;
- input=chkopen(p);
-
- /* set up new args */
- setargs(t);
- longjmp(subshell,1);
-
- case ENOMEM:
- failed(p,toobig);
-
- case E2BIG:
- failed(p,arglist);
-
- case ETXTBSY:
- failed(p,txtbsy);
-
- default:
- xecmsg=badexec;
- case ENOENT:
- return(prefix);
- ENDSW
- }
-
- /* for processes to be waited for */
- #define MAXP 20
- LOCAL INT pwlist[MAXP];
- LOCAL INT pwc;
-
- postclr()
- {
- REG INT *pw = pwlist;
-
- WHILE pw <= &pwlist[pwc]
- DO *pw++ = 0 OD
- pwc=0;
- }
-
- VOID post(pcsid)
- INT pcsid;
- {
- REG INT *pw = pwlist;
-
- IF pcsid
- THEN WHILE *pw DO pw++ OD
- IF pwc >= MAXP-1
- THEN pw--;
- ELSE pwc++;
- FI
- *pw = pcsid;
- FI
- }
-
- VOID await(i)
- INT i;
- {
- INT rc=0, wx=0;
- INT w;
- INT ipwc = pwc;
-
- post(i);
- WHILE pwc
- DO REG INT p;
- REG INT sig;
- INT w_hi;
-
- BEGIN
- REG INT *pw=pwlist;
- p=wait(&w);
- WHILE pw <= &pwlist[ipwc]
- DO IF *pw==p
- THEN *pw=0; pwc--;
- ELSE pw++;
- FI
- OD
- END
-
- IF p == -1 THEN continue FI
-
- w_hi = (w>>8)&LOBYTE;
-
- IF sig = w&0177
- THEN IF sig == 0177 /* ptrace! return */
- THEN prs("ptrace: ");
- sig = w_hi;
- FI
- IF sysmsg[sig]
- THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
- prs(sysmsg[sig]);
- IF w&0200 THEN prs(coredump) FI
- FI
- newline();
- FI
-
- IF rc==0
- THEN rc = (sig ? sig|SIGFLG : w_hi);
- FI
- wx |= w;
- OD
-
- IF wx ANDF flags&errflg
- THEN exitsh(rc);
- FI
- exitval=rc; exitset();
- }
-
- BOOL nosubst;
-
- trim(at)
- STRING at;
- {
- REG STRING p;
- REG CHAR c;
- REG CHAR q=0;
-
- IF p=at
- THEN WHILE c = *p
- DO *p++=c&STRIP; q |= c OD
- FI
- nosubst=q"E;
- }
-
- STRING mactrim(s)
- STRING s;
- {
- REG STRING t=macro(s);
- trim(t);
- return(t);
- }
-
- STRING *scan(argn)
- INT argn;
- {
- REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
- REG STRING *comargn, *comargm;
-
- comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
-
- WHILE argp
- DO *--comargn = argp->argval;
- IF argp = argp->argnxt
- THEN trim(*comargn);
- FI
- IF argp==0 ORF Rcheat(argp)&ARGMK
- THEN gsort(comargn,comargm);
- comargm = comargn;
- FI
- /* Lcheat(argp) &= ~ARGMK; */
- argp = Rcheat(argp)&~ARGMK;
- OD
- return(comargn);
- }
-
- LOCAL VOID gsort(from,to)
- STRING from[], to[];
- {
- INT k, m, n;
- REG INT i, j;
-
- IF (n=to-from)<=1 THEN return FI
-
- FOR j=1; j<=n; j*=2 DONE
-
- FOR m=2*j-1; m/=2;
- DO k=n-m;
- FOR j=0; j<k; j++
- DO FOR i=j; i>=0; i-=m
- DO REG STRING *fromi; fromi = &from[i];
- IF cf(fromi[m],fromi[0])>0
- THEN break;
- ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
- FI
- OD
- OD
- OD
- }
-
- /* Argument list generation */
-
- INT getarg(ac)
- COMPTR ac;
- {
- REG ARGPTR argp;
- REG INT count=0;
- REG COMPTR c;
-
- IF c=ac
- THEN argp=c->comarg;
- WHILE argp
- DO count += split(macro(argp->argval));
- argp=argp->argnxt;
- OD
- FI
- return(count);
- }
-
- LOCAL INT split(s)
- REG STRING s;
- {
- REG STRING argp;
- REG INT c;
- INT count=0;
-
- LOOP sigchk(); argp=locstak()+BYTESPERWORD;
- WHILE (c = *s++, !any(c,ifsnod.namval) && c)
- DO *argp++ = c OD
- IF argp==staktop+BYTESPERWORD
- THEN IF c
- THEN continue;
- ELSE return(count);
- FI
- ELIF c==0
- THEN s--;
- FI
- IF c=expand((argp=endstak(argp))->argval,0)
- THEN count += c;
- ELSE /* assign(&fngnod, argp->argval); */
- makearg(argp); count++;
- FI
- Lcheat(gchain) |= ARGMK;
- POOL
- }
-