/*
* sh.c - original source code for the Sixth Edition (V6) UNIX Thompson shell
*
* From: Sixth Edition (V6) UNIX /usr/source/s2/sh.c
*
* NOTE: The first 43 lines of this file have been added by
* Jeffrey Allen Neitzel <jan (at) v6shell (dot) org>
* in order to comply with the license. The file is
* otherwise unmodified.
*/
/*-
* Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code and documentation must retain the above
* copyright notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* 4. Neither the name of Caldera International, Inc. nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
* INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#
/*
*/
#define INTR 2
#define QUIT 3
#define LINSIZ 1000
#define ARGSIZ 50
#define TRESIZ 100
#define QUOTE 0200
#define FAND 1
#define FCAT 2
#define FPIN 4
#define FPOU 8
#define FPAR 16
#define FINT 32
#define FPRS 64
#define TCOM 1
#define TPAR 2
#define TFIL 3
#define TLST 4
#define DTYP 0
#define DLEF 1
#define DRIT 2
#define DFLG 3
#define DSPR 4
#define DCOM 5
#define ENOMEM 12
#define ENOEXEC 8
char *dolp;
char pidp[6];
int ldivr;
char **dolv;
int dolc;
char *promp;
char *linep;
char *elinep;
char **argp;
char **eargp;
int *treep;
int *treeend;
char peekc;
char gflg;
char error;
char acctf;
char uid;
char setintr;
char *arginp;
int onelflg;
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",
0,
"Sig 14",
"Sig 15",
"Sig 16",
"Sig 17",
"Sig 18",
"Sig 19",
};
struct stime {
int proct[2];
int cputim[2];
int systim[2];
} timeb;
char line[LINSIZ];
char *args[ARGSIZ];
int trebuf[TRESIZ];
main(c, av)
int c;
char **av;
{
register f;
register char *acname, **v;
for(f=2; f<15; f++)
close(f);
if((f=dup(1)) != 2)
close(f);
dolc = getpid();
for(f=4; f>=0; f--) {
dolc = ldiv(0, dolc, 10);
pidp[f] = ldivr+'0';
}
v = av;
acname = "/usr/adm/sha";
promp = "% ";
if(((uid = getuid())&0377) == 0)
promp = "# ";
acctf = open(acname, 1);
if(c > 1) {
promp = 0;
if (*v[1]=='-') {
**v = '-';
if (v[1][1]=='c' && c>2)
arginp = v[2];
else if (v[1][1]=='t')
onelflg = 2;
} else {
close(0);
f = open(v[1], 0);
if(f < 0) {
prs(v[1]);
err(": cannot open");
}
}
}
if(**v == '-') {
setintr++;
signal(QUIT, 1);
signal(INTR, 1);
}
dolv = v+1;
dolc = c-1;
loop:
if(promp != 0)
prs(promp);
peekc = getc();
main1();
goto loop;
}
main1()
{
register char c, *cp;
register *t;
argp = args;
eargp = args+ARGSIZ-5;
linep = line;
elinep = line+LINSIZ-5;
error = 0;
gflg = 0;
do {
cp = linep;
word();
} while(*cp != '\n');
treep = trebuf;
treeend = &trebuf[TRESIZ];
if(gflg == 0) {
if(error == 0) {
setexit();
if (error)
return;
t = syntax(args, argp);
}
if(error != 0)
err("syntax error"); else
execute(t);
}
}
word()
{
register char c, c1;
*argp++ = linep;
loop:
switch(c = getc()) {
case ' ':
case '\t':
goto loop;
case '\'':
case '"':
c1 = c;
while((c=readc()) != c1) {
if(c == '\n') {
error++;
peekc = c;
return;
}
*linep++ = c|QUOTE;
}
goto pack;
case '&':
case ';':
case '<':
case '>':
case '(':
case ')':
case '|':
case '^':
case '\n':
*linep++ = c;
*linep++ = '\0';
return;
}
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;
if (treep>treeend) {
prs("Command line overflow\n");
error++;
reset();
}
return(t);
}
getc()
{
register char c;
if(peekc) {
c = peekc;
peekc = 0;
return(c);
}
if(argp > eargp) {
argp =- 10;
while((c=getc()) != '\n');
argp =+ 10;
err("Too many args");
gflg++;
return(c);
}
if(linep > elinep) {
linep =- 10;
while((c=getc()) != '\n');
linep =+ 10;
err("Too many characters");
gflg++;
return(c);
}
getd:
if(dolp) {
c = *dolp++;
if(c != '\0')
return(c);
dolp = 0;
}
c = readc();
if(c == '\\') {
c = readc();
if(c == '\n')
return(' ');
return(c|QUOTE);
}
if(c == '$') {
c = readc();
if(c>='0' && c<='9') {
if(c-'0' < dolc)
dolp = dolv[c-'0'];
goto getd;
}
if(c == '$') {
dolp = pidp;
goto getd;
}
}
return(c&0177);
}
readc()
{
char cc;
register c;
if (arginp) {
if (arginp == 1)
exit();
if ((c = *arginp++) == 0) {
arginp = 1;
c = '\n';
}
return(c);
}
if (onelflg==1)
exit();
if(read(0, &cc, 1) != 1)
exit();
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 & syntax
* syn2 ; syntax
*/
syn1(p1, p2)
char **p1, **p2;
{
register char **p;
register *t, *t1;
int l;
l = 0;
for(p=p1; p!=p2; p++)
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;
if(l == '&') {
t1 = t[DLEF];
t1[DFLG] =| FAND|FPRS|FINT;
}
t[DRIT] = syntax(p+1, p2);
return(t);
}
}
if(l == 0)
return(syn2(p1, p2));
error++;
}
/*
* syn2
* syn3
* syn3 | syn2
*/
syn2(p1, p2)
char **p1, **p2;
{
register char **p;
register int l, *t;
l = 0;
for(p=p1; p!=p2; p++)
switch(**p) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case '|':
case '^':
if(l == 0) {
t = tree(4);
t[DTYP] = TFIL;
t[DLEF] = syn3(p1, p);
t[DRIT] = syn2(p+1, p2);
t[DFLG] = 0;
return(t);
}
}
return(syn3(p1, p2));
}
/*
* syn3
* ( syn1 ) [ < in ] [ > out ]
* word word* [ < in ] [ > out ]
*/