USG_PG3/usr/source/cmd5/sh.c
#
/*
11/26/75 mod3.30.04
*/
#define INTR 2
#define QUIT 3
#define LINSIZ 1024
#define ARGSIZ 50
#define STKSIZ 10
#define TRESIZ 128
#define SCCMODE 0100000
#define QUOTE 0200
#define GLOB "/etc/glob"
#define GOTO "/bin/goto"
#define PWD "/bin/pwd"
#define SHELL "/bin/sh"
/*
* node types:
* TCOM: program {syntax type 3.2}
* TPAR: ( stuff ) {syntax type 3.1}
* TFIL: pipe node {syntax type 2.2, 2.3}
* TLST: list node {syntax type 1.2, 1.3}
*/
#define TCOM 1
#define TPAR 2
#define TFIL 3
#define TLST 4
/*
* flags
* FCAT: concatenate to output file.
* FECAT: concatenate to errput file.
* FPIN: input from pipe
* FPOU: output to pipe.
* FPAR: last spinoff from parenthesized expression, don't fork again.
* FAND: no wait for termination of child.
* FINT: clear traps, if set (INTR, QUIT); default input from /dev/null.
* FPRS: print pid of child after forking.
*/
#define FCAT 1
#define FECAT 2
#define FPIN 4
#define FPOU 8
#define FPAR 16
#define FAND 32
#define FINT 64
#define FPRS 128
/*
* node descriptions:
* program: DTYP, DFLG, DIN, DOUT, DERR, DPRG, DCOM, DARG1, DARG2, ...
* paren: DTYP, DFLG, DIN, DOUT, DERR, DSPR
* pipe: DTYP, DFLG, DLEF, DRIT
* list: DTYP, DFLG, DLEF, DRIT
*/
#define DTYP 0
#define DFLG 1
#define DLEF 2
#define DIN 2
#define DRIT 3
#define DOUT 3
#define DERR 4
#define DSPR 5
#define DPRG 5
#define DCOM 6
#define DARG1 7
#define DARG2 8
struct list {
int type;
char flagc;
char cchar;
struct list *left;
struct list *right;
};
struct paren {
int type;
int flag;
char *input;
char *output;
char *errput;
struct list *subpar;
char *args[0];
};
struct progm {
int type;
int flag;
char *input;
char *output;
char *errput;
char *program;
char *pname;
char *arg1;
char *arg2;
};
#define ENOENT 2
#define E2BIG 7
#define ENOEXEC 8
#define ENOMEM 12
#define EACCES 13
#define ENOTDIR 20
#define EDIRECT 13
char *dolp;
#define STKP stk[0]
int stk[STKSIZ+1];
char pidp[6];
char nbuf[6];
int ldivr;
char **dolv;
int dolc;
char *promp "% ";
char *linep;
char line[LINSIZ];
char *elinep line+LINSIZ-30;
char **argp;
char *args[ARGSIZ];
char **eargp args+ARGSIZ-1;
int *treep;
int treecnt;
int trebuf[TRESIZ];
int *treeend trebuf+TRESIZ;
char peekc;
char error;
char uid;
char setintr;
char *arginp;
int acctf;
int readf;
char *intrf;
int prof;
int onelflg;
int exitcod;
int echoflg;
char *seta[26];
char tty[] "/dev/lnXX";
char *qc;
char qlist[] ": \t;&<>%()|^*?[\"'$\\";
char *home;
char *endcore;
char *endptr;
int errno;
int wasintr;
char *gointr;
char *goeof;
/*
char expath[32], *expathp;
*/
char *mesg[] {
0,
"Hangup",
0,
"Quit",
"Illegal instruction",
"Trace/BPT trap",
"IOT trap",
"EMT trap",
"Floating exception",
"Killed",
"Bus error",
"Memory fault",
"Bad system call",
"Broken pipe",
"Alarm timeout",
"Software kill",
"Sig 16",
"Sig 17",
"Sig 18",
"Sig 19",
};
char *acct_name "/usr/adm/sh_acct";
struct stime {
long uproct;
long sproct;
long cputim;
long systim;
} timeb;
main(c, av)
int c;
char **av;
{
register *f;
register char *cptr, **v;
int pv[2];
int stopprof();
int ln;
int pwdstat;
struct{
char lobyte;
char hibyte;
};
endptr = endcore = sbrk(0);
dup(1); /* if error output (2) not open, open it. */
for(cptr=3; cptr<15; close(cptr++));
if(pipe(f=pv)!= -1) {
if(!fork()) {
close(*f++);
close(1);
dup(*f);
close(*f);
write(1, "/", 1);
execl(PWD, PWD+5, 0);
exit(9);
}
close(f[1]);
wait(&pwdstat);
home = rdval(*f, 0, 0);
close(*f);
}
ln = lnxx(0);
if(ln.lobyte == 'x' && ln.hibyte == 'x'){
ln = lnxx(1);
if(ln.lobyte == 'x' && ln.hibyte == 'x')
ln = lnxx(2);
}
tty[7] = ln;
tty[8] = ln>>8;
btoa(getpid(), pidp+5);
f = pidp;
*f++ =| '00';
*f =| '00';
v = av;
cptr = acct_name;
promp = "% ";
if(((uid = getuid())&0377) == 0) {
promp = "# ";
acct_name[10] = 'u';
}
acctf = open(cptr, 1);
f = *v++;
if(c == 1 && *f == '-')
if((prof = open("profile.sh", 0)) == -1)
prof = 0;
while(--c > 0 && promp) {
cptr = *v++;
if(*cptr++ == '-') {
switch(*cptr) {
default:
prs("Bad arg: ");
err(--cptr);
case 'c':
if(--c <= 0)
exit(4);
arginp = *v;
case '\0':
break;
case 'e':
case 'v':
echoflg = 1;
continue;
case 'i':
*f = '-';
continue;
case 't':
onelflg = 2;
*--v =+ 2;
}
*f = '-';
} else {
readf = dup(0);
close(0);
openi(*--v);
intrf = *v;
}
promp = 0;
}
dolv = v;
dolc = c;
*--v = f;
if(*f == '-') {
setintr++;
signal(QUIT, 1);
signal(INTR, 1);
if(prof)setintr = -1;
}
setexit();
for(;;) {
if(wasintr == 1)
wasintr = 0;
if(wasintr > 0) {
wasintr = -1;
if(intrf)
if((prof = open(intrf, 0)) == -1)
prof = 0;
if(xgoto(gointr)) {
if(prof)
close(prof);
prof = 0;
signal(INTR, 0);
wasintr = 0;
}
}
if(promp && !prof)
prs(promp);
echoflg =<<2;
qc = qlist;
if((peekc = getc()) == ':')
while(getc() != '\n');
else {
qc++;
main1();
if(setintr<0) {
signal(INTR, stopprof);
setintr = 1;
}
}
}
}
main1()
{
register char c, *cp;
register *t;
argp = args;
linep = line;
error = 0;
do {
cp = linep;
if(argp == eargp) {
while(getc() != '\n');
err("Too many tokens");
reset();
}
word();
} while(*cp != '\n');
treep = trebuf;
treecnt = 0;
if(error == 0)
t = syntax(args, argp);
if(error != 0)
err("syntax error");
else
execute(t);
}
word()
{
register char c, c1;
register (*qf)();
extern getc(), reade();
*argp++ = linep;
loop:
switch(c = getc()) {
case ' ':
case '\t':
goto loop;
case '\'':
case '"':
c1 = c;
qc = qlist+16;
qf = (c1 == '"')? reade: getc;
while((c=(*qf)()) != c1) {
if(c == '\n') {
error++;
peekc = c;
return;
}
*linep++ = c|QUOTE;
}
qc = qlist+1;
goto pack;
case '&':
case ';':
case '%':
case '<':
case '>':
case '(':
case ')':
case '|':
case '^':
case '\n':
*linep++ = c;
*linep++ = '\0';
return;
default:
peekc = c;
}
pack:
for(;;) {
c = getc();
if(any(c, " '\"\t;&%<>()|^\n")) {
peekc = c;
if(any(c, "\"'"))
goto loop;
*linep++ = '\0';
return;
}
*linep++ = c;
}
}
tree(n)
int n;
{
register *t;
t = treep;
treep =+ n;
treecnt++;
if (treep>treeend) {
prs("Command table overflow\n");
error++;
reset();
}
return(t);
}
reade() {
return(echo(readc()));
}
echo(c) {
switch(echoflg) {
case 0:
return(c);
case 1<<10: /* (1<<2)<<8 only. */
case 1<<2:
write(2, "* ", 2);
case 1<<8:
if(echoflg != 1<<2)
write(2, "\\\n", 1);
c =& 0177;
case 1:
write(2, &c, 1);
break;
case 1<<4:
write(2, "\\\n", 2);
}
echoflg = 1;
return(c);
}
getc()
{
register char c, n, *temp;
if(peekc) {
c = peekc;
peekc = 0;
return(c);
}
for(;;) {
c = readc();
if(c == '$') {
c = readc();
temp = "\\$X";
temp[2] = c;
if((n = c-'0')>=0 && c<='9') {
if(n > dolc)
continue;
else temp = dolv[n];
} else if((n = c-'a')>=0 && c<='z') {
if((temp = seta[n]) == 0)
continue;
} else if(c == '$')
temp = pidp;
else if(c == '.')
temp = home;
else if(c == 'T' || c == '_')
temp = tty;
else if(c == 'E') {
temp = nbuf;
temp[3] = 0;
temp[2] = (exitcod & 7) + '0';
temp[1] = (exitcod>>3 & 7) + '0';
temp[0] = (exitcod>>6 & 3) + '0';
} else if(c == 'N')
temp = btoa(dolc, nbuf+5);
else if(c == 'R')
temp = btoa(exitcod, nbuf+5);
else if(c == 'P')
temp = btoa(prof, nbuf+5);
else if(c == 'F')
temp = btoa(readf, nbuf+5);
else if(c == 'V') {
if(echoflg)
temp = "-v";
else continue;
} else if(c == 'I')
temp = btoa(setintr, nbuf+5);
else if(c=='Z')
temp = btoa(endptr);
if(STKP >= STKSIZ)
err("'$' nesting error");
else {
stk[STKP] = dolp;
STKP++;
dolp = temp;
}
continue;
}
if(c=='\\') {
c=readc();
if(c=='\n') {
echoflg =<<4;
c = ' ';
} else if(any(c, qc)) {
c =| QUOTE;
echoflg =<<8;
} else {
peekc = c;
c = '\\';
}
}
break;
}
echo(c);
if(linep == elinep) {
linep--;
while(getc() != '\n');
linep++;
err("Too many characters");
reset();
}
return(c);
}
readc()
{
char cc;
register c;
while(dolp) {
c = *dolp++;
if(c != '\0')
return(c =& 0177);
else
dolp = stk[--STKP];
}
if (arginp) {
if (arginp == 1)
exit(exitcod);
if ((c = *arginp++) == 0) {
arginp = 1;
c = '\n';
}
return(c);
}
if (onelflg==1)
exit(exitcod);
if(read1(prof, &cc)) {
if(!prof || !setintr)
exit(exitcod);
close(prof);
prof = 0;
if(wasintr<0) {
wasintr = 0;
signal(INTR, 0);
}
cc = '\n';
}
if (cc=='\n' && onelflg)
onelflg--;
return(cc);
}
/*
* syntax
* empty
* syn1
*/
syntax(p1, p2)
char **p1, **p2;
{
while(p1 < p2) {
if(any(**p1, ";&\n"))
p1++; else
return(syn1(p1, p2));
}
return(0);
}
/*
* syn1
* syn2
* syn2 &&C syntax
* syn2 & syntax
* syn2 ; syntax
*/
syn1(p1, p2)
char **p1, **p2;
{
register char **p;
register *t, *t1;
int l;
l = 0;
for(p=p1; p<p2; )
switch(**p++) {
case '(':
l++;
continue;
case ')':
l--;
if(l < 0)
error++;
continue;
case '&':
case ';':
case '\n':
if(l == 0) {
l = **--p;
t = tree(4);
t[DTYP] = TLST;
t[DLEF] = syn2(p1, p);
t[DFLG] = 0;
p++;
if(l == '&') {
t1 = t[DLEF];
t1[DFLG] =| FAND|FPRS|FINT;
if(**p == '&' && ++p<p2 &&
**p >= 'a' && **p <= 'z' && p[0][1] == 0)
t1->cchar = **p++;
}
t[DRIT] = syntax(p, p2);
return(t);
}
}
if(l == 0)
return(syn2(p1, p2));
error++;
}
/*
* syn2
* syn3
* syn3 | syn2
* syn3 ^ syn2
*/
syn2(p1, p2)
char **p1, **p2;
{
register char **p;
register int l, *t;
l = 0;
for(p=p1; p!=p2; )
switch(**p++) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case '|':
case '^':
if(p1 == p) {
error++;
return(0);
}
if(l == 0) {
t = tree(4);
t[DTYP] = TFIL;
t[DLEF] = syn3(p1, p-1);
t[DRIT] = syn2(p, p2);
t[DFLG] = 0;
return(t);
}
}
return(syn3(p1, p2));
}
/*
* syn3
* ( syn1 ) [ < in ] [ > [ > ] out ] [ % [ % ] err ]
* word word* [ < in ] [ > [ > ] out ] [ % [ % ] err ]
*/
syn3(p1, p2)
char **p1, **p2;
{
register char **p;
char **lp, **rp;
register *t, *ioep;
int n, l, ioe[3], flg;
char c;
flg = 0;
if(**p2 == ')')
flg =| FPAR;
lp = 0;
rp = 0;
ioep = ioe+3;
*--ioep = 0;
*--ioep = 0;
*--ioep = 0;
n = 0;
l = 0;
for(p=p1; p!=p2; )
switch(c = **p++) {
case '(':
if(l == 0) {
if(lp != 0)
error++;
lp = p;
}
l++;
continue;
case ')':
l--;
if(l == 0)
rp = p-1;
continue;
case '%':
ioep++;
case '>':
ioep++;
if(l) {
ioep = ioe;
continue;
}
if(p != p2) {
if(**p++ == c)
flg =| (c == '%') ? FECAT : FCAT;
else if(**--p == '%')
**p = 0377;
}
case '<':
if(l) continue;
if(p == p2 || any(**p, "<>%(") || *ioep) {
error++;
continue;
}
*ioep = *p++;
ioep = ioe;
continue;
default:
if(l == 0)
p1[n++] = p[-1];
}
if(lp != 0) {
if(n != 0)
error++;
t = tree(6);
t[DTYP] = TPAR;
t[DSPR] = syn1(lp, rp);
goto out;
}
if(n == 0)
error++;
p1[n++] = 0;
t = tree(n+6);
t[DTYP] = TCOM;
for(l=0; l<n; l++)
t[l+DCOM] = p1[l];
out:
t[DFLG] = flg;
t[DLEF] = *ioep++;
t[DRIT] = *ioep++;
t[DERR] = *ioep;
return(t);
}
scan(at, f)
int *at;
{
register char *p, c;
register *t;
t = at+DCOM;
while(p = *t++)
while(c = *p)
if(f)
*p++ =& 0177;
else
if(any(*p++,"[?*"))
return(1);
return(0);
}
execute(t, pf1, pf2)
int *t, pf1, *pf2;
{
int catchintr();
int i, f, pv[2], wt;
register *t1;
register char *cp1, *cp2;
char *copy();
if((t1 = t) != 0)
switch(t1[DTYP]) {
case TCOM:
exitcod = 0;
cp1 = t1[DCOM];
if(equal(cp1, "chdir") || equal(cp1, "cd")) {
if(t1[DARG1] == 0 || chdir(t1[DARG1]) < 0)
noex();
return;
}
if(equal(cp1, "shift")) {
if(dolc < 1) {
prs("shift: no args\n");
exitcod = 4;
return;
}
if((cp1 = t1[DARG1])==0) {
dolv[1] = dolv[0];
dolv++;
dolc--;
return;
}
if ((*cp1 =^ '0')>9 || *cp1++ >dolc || *cp1) {
prs("shift: argument?\n");
exitcod = 4;
return;
}
t1 = dolv + *--cp1;
for(cp2 = dolc - *cp1 +1; --cp2; *t1++ = t1[1]);
dolc--;
return;
}
if(equal(cp1, "login")) {
if(promp != 0 && prof == 0) {
close(acctf);
if(readf) close(readf);
execv("/bin/login", t1+DCOM);
}
noex();
return;
}
/* newgrp not implemented.
if(equal(cp1, "newgrp")) {
if(promp != 0 && prof == 0) {
close(acctf);
if(readf) close(readf);
execv("/bin/newgrp", t1+DCOM);
}
noex();
return;
}
*/
/* home -- use chdir $.
if(equal(cp1, "home")) {
if(!home || !*home || chdir(home)<0)
noex();
return;
}
*/
if(equal(cp1, "wait")) {
if(t1[DARG1])
cp2 = atob(t1[DARG1]);
else cp2 = -1;
wt = signal(INTR, catchintr);
pwait(cp2, 0);
signal(INTR, wt);
wasintr = 0;
return;
}
if(equal(cp1, ":"))
return;
if((cp2=equal(cp1, "return")) || equal(cp1, "exit")) {
if(t1[DARG1]) exitcod = atob(t1[DARG1]);
if(cp2 && prof) {
close(prof);
prof = 0;
} else if(promp==0 || prof) {
seek(0,0,2);
exit(exitcod);
}
return;
}
if(equal(cp1, "onintr")) {
if(setintr) {
setintr = 1;
if(t1[DARG1])
noex();
else signal(INTR, 1);
return;
}
if(t1[DARG1]==0) {
signal(INTR, 0);
return;
}
gointr = rdval(0, 0, t1[DARG1]);
wasintr = 0;
signal(INTR, catchintr);
return;
}
if(equal(cp1, "onend")) {
if(t1[DARG1])
goeof = rdval(0, 0, t1[DARG1]);
else
goeof = 0;
return;
}
if(equal(cp1, "=")) {
if((cp1 = t1[DARG1]) == 0 ||
(*cp1 =- 'a')<0 || *cp1++ > 25 || *cp1 ||
(seta[*--cp1] = rdval((t1[DFLG]&FPIN?pf1:0),
t1[DLEF], t1[DARG2])) == 0)
err("'=' error");
return;
}
if(equal(cp1, "open")) {
if(readf) close(readf);
if(!t1[DARG1])
if(t1[DFLG]&FPIN) {
readf = dup(pf1);
return;
} else t1[DARG1] = tty;
readf = open(t1[DARG1],0);
return;
}
if(equal(cp1, "read")) {
cp2 = linep;
if(t1[DFLG]&FPOU)
cp1 = pf2[1];
else if(t1->output) {
if((cp1=openo(t1->output,t1[DFLG]&FCAT))&0100000)
return;
} else cp1 = 1;
if(read1(readf, cp2)) {
if(xgoto(goeof))
err("read - EOF");
*cp2 = 0;
}
while(*cp2 && *cp2 != '\n') {
write(cp1, cp2, 1);
if(read1(readf, cp2))
break;
}
write(cp1, "\n", 1);
if(!(t1[DFLG]&FPOU) && t1[DRIT])
close(cp1);
return;
}
case TPAR:
f = t1[DFLG];
i = 0;
if((f&FPAR) == 0)
for(wt=10; ; wt =+ 10) {
if ((i=fork()) != -1) break;
if(promp == 0 && wt<60)
sleep(wt);
else {
err("Cannot fork; try again");
return;
}
}
if(i != 0) {
if((f&FPRS) != 0) {
if(t1->cchar) {
seta[t1->cchar - 'a'] = rdval(0, 0,
btoa(i, nbuf+5));
} else {
prn(i);
prs("\n");
}
}
if((f&FAND) != 0)
return;
if((f&FPOU) == 0)
pwait(i, t);
return;
}
promp = 0; /* show err this is a child */
if(prof) {
close(0);
dup(prof);
close(prof);
}
if(t1[DERR]) {
i = openo(t1->errput, f&FECAT);
close(2);
dup(i);
close(i);
}
if(t1[DLEF]) {
close(0);
openi(t1->input);
}
if(t1[DRIT]) {
close(1);
if(t1->output[0] == -1)
dup(2);
else openo(t1->output, f&FCAT);
}
if((f&FPIN) != 0) {
close(0);
dup(pf1);
close(pf1);
}
if((f&FPOU) != 0) {
close(1);
dup(pf2[1]);
close(pf2[0]);
close(pf2[1]);
}
if((f&FINT)!=0 && t1[DLEF]==0 && (f&FPIN)==0) {
close(0);
open("/dev/null", 0);
}
if((f&FINT) == 0 && setintr) {
signal(INTR, 0);
signal(QUIT, 0);
}
if(t1[DTYP] == TPAR) {
if(t1 = t1[DSPR])
t1[DFLG] =| f&FINT;
execute(t1);
exit(exitcod);
}
close(acctf);
if(readf) close(readf);
if(scan(t1, 0)){
t1[DSPR] = GLOB;
execv(t1[DSPR], t1+DSPR);
t1->pname = GLOB;
noex();
}
scan(t1, 1);
cp1 = *(t1 = t+DCOM);
cp2 = shexec(cp1, t1);
copy(*t1, copy("/usr/bin/", linep));
cp2 =+ shexec(linep+4, t1);
cp2 =+ shexec(linep, t1);
prs(*t1);
err(cp2? ": permission denied!": ": not found");
case TFIL:
f = t[DFLG];
if(pipe(pv)<0)
err("Cannot create pipe");
t1 = t[DLEF];
t1[DFLG] =| FPOU | (f&(FPIN|FINT|FPRS));
execute(t1, pf1, pv);
close(pv[1]);
t1 = t[DRIT];
t1[DFLG] =| FPIN | (f&(FPOU|FINT|FAND|FPRS));
execute(t1, *pv, pf2);
close(pv[0]);
return;
case TLST:
f = t[DFLG]&FINT;
if(t1 = t[DLEF])
t1[DFLG] =| f;
execute(t1);
if(t1 = t[DRIT])
t1[DFLG] =| f;
execute(t1);
return;
}
}
noex() {
register t1;
prs(t1->pname);
err(": cannot execute");
}
openi(ifile) {
register i;
if((i = open(ifile, 0)) < 0) {
prs(ifile);
err(": cannot open");
i=0;
}
return(i);
}
openo(of, flg) {
register i;
if(flg && (i = open(of, 1)) > 0)
seek(i, 0, 2);
else if((i=creat(of, 0666)) < 0) {
prs(of);
err(": cannot create");
}
return(i);
}
err(s)
char *s;
{
prs(s);
prs("\n");
if(promp == 0) {
seek(0, 0, 2);
exit(8);
}
exitcod = 8;
return;
}
any(c, as)
int c;
char *as;
{
register char *s;
s = as;
while(*s)
if(*s++ == c)
return(1);
return(0);
}
equal(as1, as2)
char *as1, *as2;
{
register char *s1, *s2;
s1 = as1;
s2 = as2;
while(*s1++ == *s2)
if(*s2++ == '\0')
return(1);
return(0);
}
pwait(i, t)
int i, *t;
{
register p, e;
int s;
int catchintr();
if(i != 0)
for(;;) {
times(&timeb);
time(&timeb.uproct);
p = wait(&s);
if(wasintr > 0) { /* wait terminated by interrupt */
if(t == 0) /* wait called by wait command, */
break; /* stop waiting. */
p = wait(&s);
}
if(p == -1)
break;
e = s&0177;
if(e == 2 && wasintr > 0) /* process killed by intr */
e = 0;
if(mesg[e] != 0) {
if(p != i) {
prn(p);
prs(": ");
}
prs(mesg[e]);
if(s&0200)
prs(" -- Core dumped");
}
exitcod = s>>8;
if(e != 0)
err("");
if(i == p) {
acct(t);
break;
} else
acct(0);
}
}
acct(t)
int *t;
{
if(t == 0)
enacct("**gok"); else
if(*t == TPAR)
enacct("()"); else
enacct(t[DCOM]);
}
enacct(as)
char *as;
{
struct stime timbuf;
struct {
char cname[14];
char shf;
char uid;
long datet;
long realt;
long bcput;
long bsyst;
} tbuf;
register i;
register char *np, *s;
if(acctf == -1) return;
s = as;
times(&timbuf);
time(&timbuf.uproct);
tbuf.realt = timbuf.uproct - timeb.uproct;
tbuf.bcput = timbuf.cputim - timeb.cputim;
tbuf.bsyst = timbuf.systim - timeb.cputim;
for(np = s; i = *s++; )
if(i=='/')
np=s;
for (i=0; i<14; i++) {
if(tbuf.cname[i] = *np)
np++;
}
tbuf.datet = timbuf.uproct;
tbuf.uid = uid;
tbuf.shf = 0;
if (promp==0)
tbuf.shf = 1;
seek(acctf, 0, 2);
write(acctf, &tbuf, sizeof(tbuf));
}
read1(file, where) {
register i;
while((i = read(file, where, 1)) != 1 && wasintr == 2) wasintr++;
return(--i != 0);
}
catchintr() {
wasintr=2;
signal(INTR, 1);
}
stopprof() {
signal(INTR, 1);
seek(prof, 0, 2);
wasintr=1;
}
char *copy(source,sink) char source[], sink[]; {
/* copy strings */
register char *p1, *p2;
p1 = source;
p2 = sink;
while(*p2++ = *p1++);
return(--p2);
}
rdval(pipef, lef, arg2p) char *arg2p; int *pipef; {
register char c, *st, *endp;
endp = st = endptr;
if(!arg2p && !pipef && lef) {
if((pipef = open(lef, 0)) < 0)
return(0);
} else
lef = 0;
do {
if(endp >= endcore)
if(sbrk(64)<0)
return(0);
else
endcore =+ 64;
if(arg2p == 0) {
if(read1(pipef, endp) || *endp == '\n')
*endp = '\0';
} else
*endp = *arg2p++;
} while(*endp++);
endptr = endp;
if(lef) close(pipef);
return(st);
}
xgoto(where) char *where; {
register i;
int j;
if(!where || !*where)
return(1);
if(!(i = fork())) {
if(prof) {
close(0);
dup(prof);
close(prof);
}
execl(GOTO, GOTO+5, where, 0);
exit(9);
}
if(i == -1)
return(i);
pwait(i, 0);
return(exitcod);
}
atob(ptr)
char *ptr;
{
register char *p;
register n, base;
static char base0;
n = 0;
p = ptr;
base = 10;
if(*p == '-')
p++;
if(*p == '0') {
base = 8;
p++;
}
base0 = base + '0';
while(*p >= '0' && base0 > *p) {
n =* base;
n =+ *p++;
n =- '0';
}
if(*ptr == '-')
n = -n;
return(n);
}
#define ENOENT 2
#define E2BIG 7
#define ENOEXEC 8
#define ENOMEM 12
#define EACCESS 13
#define ENOTDIR 20
#define EDIRECT 13
#define SHELL "/bin/sh"
int ldivr;
char nbuf[6];
shexec(afile, aargp)
char *afile, *aargp[];
{
register char *file, **rargp;
extern errno;
file = afile;
rargp = aargp;
execv(file, rargp);
/* temp */ if(!errno || errno & 0177700) errno = EDIRECT;
if(errno == ENOEXEC) {
*rargp = file;
*--rargp = SHELL+5;
execv(SHELL, rargp);
if(errno == ENOENT || errno == ENOTDIR)
err("No Shell!");
}
switch (errno) {
case E2BIG:
prs(*rargp);
err(": arg list too long");
case ENOMEM:
prs(*rargp);
err(": not enough core");
default:
prs(*rargp);
prs(": unknown error (errno=");
prn(errno);
err(").");
case EACCESS:
return(1);
case ENOENT:
case ENOTDIR:
return(0);
}
}
prs(as)
char *as;
{
register char *s;
s = as;
while(*s)
write(2, s++, 1);
}
prn(n) {
prs(btoa(n, nbuf+5));
}
btoa(n, ptr)
char *ptr;
{
register char *p;
register v;
p = ptr;
*p = 0;
v = n;
do {
v = ldiv(0, v, 10);
*--p = ldivr | '0';
} while(v);
return(p);
}