|
|
coherent
/*
* sh/main.c
* The Bourne shell.
* Main program, initialization and miscellaneous routines.
*/
#include <sys/param.h>
#include "sh.h"
main(argc, argv, envp)
char *argv[];
char *envp[];
{
sarg0 = argc>0 ? argv[0] : "";
fakearg(0, argc, argv, envp);
if (argc>0 && argv[0][0]=='-') {
lgnflag = 1;
umask(ufmask=022);
} else if (argc>0 && argv[0][0]=='+') {
dflttrp(IBACK); /* for security, no <Ctrl-C> out of /etc/profile */
lgnflag = 2;
umask(ufmask=022);
} else {
umask(ufmask=umask(ufmask));
}
if (setjmp(restart) != 0) {
/* reentry for shell command file execution */
fakearg(1, nargc, nargv, nenvp);
argc = nargc;
argv = nargv;
envp = nenvp;
cmdflag++;
nllflag = 0;
}
shpid = getpid();
initvar(envp);
cleanup(1, NULL);
if (set(argc, argv, 1))
return(1);
if (cflag) {
if (sargp[0]==NULL) {
printe("No string for -c?");
return(1);
}
--sargc;
session(SARGS, *sargp++);
} else if (!sflag && !iflag && sargc!=0) {
sarg0 = *sargp++;
--sargc;
if (scmdp == NULL)
scmdp = sarg0;
session(SFILE, scmdp);
} else {
session(SSTR, stdin);
}
cleanup(2, NULL);
return (slret);
}
/*
* Make the arg listing of ps come out right.
* f == 0, first entry, determine buffer limits.
* f != 0, later entry, fill buffer with lies.
*/
fakearg(f, argc, argv, envp)
int f, argc;
char **argv, **envp;
{
static char *fbuf;
static int nbuf;
register int n;
if (f == 0) {
fbuf = argv[0];
nbuf = 0;
if (envp != NULL && envp[0] != NULL) {
while (envp[1] != NULL)
envp += 1;
nbuf = envp[0] - fbuf + strlen(envp[0]) - 1;
} else if (argc > 0)
nbuf = argv[argc-1] - fbuf + strlen(argv[argc-1]) - 1;
} else {
if (fbuf == NULL || nbuf == 0)
return;
n = 0;
fbuf[0] = 0;
while (--argc > 0) {
argv += 1;
n += strlen(argv[0]) + 1;
if (n >= nbuf)
break;
strcat(fbuf, argv[0]);
strcat(fbuf, " ");
}
strcat(fbuf, "\1"); /* non-ascii terminator */
}
}
/*
* Loop on input.
*/
session(t, p)
register char *p;
{
SES s;
register int rcode;
s.s_next = sesp;
sesp = &s;
s.s_bpp = savebuf();
switch (s.s_type = t) {
case SARGS:
s.s_strp = p;
s.s_flag = 0;
break;
case SARGV:
s.s_argv = (char **) p;
if ((s.s_strp = s.s_argv[0]) == NULL)
return (0);
s.s_flag = 0;
break;
case SFILE:
s.s_strp = p;
if ((s.s_ifp = fopen(s.s_strp, "r")) == NULL) {
ecantopen(s.s_strp);
return (1);
}
s.s_flag = isatty(fileno(s.s_ifp)) && isatty(2);
break;
case SSTR:
s.s_strp = NULL;
s.s_ifp = (FILE *) p;
s.s_flag = isatty(fileno(s.s_ifp)) && isatty(2);
break;
}
if (s.s_next == NULL) { /* Initial entry */
if (iflag)
s.s_flag = iflag;
else
iflag = s.s_flag;
if (lgnflag != 2)
dflttrp(IRDY); /* allow <Ctrl-C> unless "+sh" */
}
/* Loop on input */
for (;;) {
rcode = setjmp(s.s_envl);
switch (rcode) {
case RSET: /* initial setjmp call */
switch (lgnflag) {
case 1: /* - sign invocation */
lgnflag = 0;
if (ffind("/etc", "profile", 4))
session(SFILE, duplstr(strt, 0));
recover(IPROF);
if (*vhome && ffind(vhome, ".profile", 4))
session(SFILE, duplstr(strt, 0));
break;
case 2: /* + sign invocation */
lgnflag = 0;
if (ffind("/etc", "profile", 4))
session(SFILE, duplstr(strt, 0));
recover(IPROF);
dflttrp(IRDY); /* allow <Ctrl-C> in SHELL */
return exshell( findvar("SHELL") );
}
checkmail();
comflag = 1;
errflag = 0;
recover(IRDY);
freebuf(s.s_bpp);
s.s_bpp = savebuf();
if (yyparse() != 0)
syntax();
case REOF:
recover(IRDY);
break;
case RCMD:
recover(IRDY);
s.s_con = NULL;
command(s.s_node);
if ((tflag && tflag++ >= 2))
break;
continue;
case RERR:
recover(IRDY);
if ( ! errflag)
syntax();
if ( ! iflag || (tflag && tflag++ >= 2))
break;
continue;
case RINT:
if (s.s_next != NULL) {
sesp = s.s_next;
reset(RINT);
NOTREACHED;
}
prpflag = 2;
if ( ! iflag || (tflag && tflag++ >= 2))
break;
continue;
case RUEXITS:
case RUABORT:
if (s.s_next != NULL) {
sesp = s.s_next;
reset(rcode);
NOTREACHED;
}
if (rcode == RUEXITS || !iflag || (tflag && tflag++ >= 2))
break;
continue;
case RNOSBRK:
case RSYSER:
case RBRKCON:
case RNOWAY:
default:
if (s.s_next!=NULL)
break;
if ( ! iflag || (tflag && tflag++ >= 2))
break;
continue;
}
break;
}
freebuf(s.s_bpp);
if (s.s_type == SFILE)
fclose(s.s_ifp);
if (s.s_next == NULL) {
sigintr(0);
recover(IRDY);
}
sesp = s.s_next;
return (slret);
}
reset(f)
{
longjmp(sesp->s_envl, f);
NOTREACHED;
}
/*
* Kludge cleanup.
*/
cleanup(flag, file)
char *file;
{
static char *files[8];
static int nfiles = 0;
register char **pp;
if (flag) {
for (pp=files; pp<files+8; pp+=1)
if (*pp != NULL) {
if (flag==2)
unlink(*pp);
sfree(*pp);
*pp = NULL;
}
nfiles = 0;
} else {
pp = files + nfiles;
if (*pp != NULL) {
unlink(*pp);
sfree(*pp);
}
*pp = duplstr(file, 1);
nfiles = (nfiles + 1) & 7;
}
}
/*
* Make a temp file name.
*/
char *
shtmp()
{
static char tmpfile[] = "/tmp/shXXXXXX";
static int tmpflag = 0;
sprintf(tmpfile+6, "%05d%c", shpid, (tmpflag++%26) + 'a');
return (tmpfile);
}
/*
* Print formatted.
*/
/*
printv(av)
register char **av;
{
while (*av) prints("\t%s\n", *av++);
}
*/
prints(a1)
char *a1;
{
fprintf(stderr, "%r", &a1);
}
/*
* Make a core dump in /tmp and longjmp back to session -
* there's a possibility we'll die horribly.
*/
panic(i) register int i;
{
#ifdef PARANOID
register int f;
if ((f=fork())==0) {
abort();
NOTREACHED;
}
waitc(f);
#endif
printe("Internal shell assertion %d failed", i);
reset(RNOWAY);
NOTREACHED;
}
/*
* Print out an error message.
*/
printe(a1)
char *a1;
{
errflag += 1;
if (! noeflag)
fprintf(stderr, "%r\n", &a1);
}
/*
* Some familiar errors.
*/
ecantopen(s) char *s; { printe("Cannot open %s", s); }
ecantfind(s) char *s; { printe("Cannot find %s", s); }
e2big(s) char *s; { printe("File to big to execute: %s", s); }
ecantmake(s) char *s; { printe("Cannot create %s", s); }
emisschar(c) { printe("Missing `%c'", c); }
ecantfdop() { printe("Fdopen failed"); }
enotdef(s) char *s; { printe("Cannot find variable %s", s); }
eillvar(s) char *s; { printe("Illegal variable name: %s", s); }
eredir() { printe("Illegal redirection"); }
etoolong() { printe("Argument too long: %.*s", STRSIZE, strt); }
/*
* Don't print out an error message.
*/
yyerror()
{
}
/*
* print out the prompt given the prompt to write
*/
prompt(vps)
char *vps;
{
prints("%s", vps);
#if RSX
fflush(stdout);
#endif
}
/*
* Syntax error message - print line number and file if
* not interactive.
*/
syntax()
{
if (sesp->s_type == SFILE) {
if (feof(sesp->s_ifp))
printe("%s: Syntax error at EOF", sesp->s_strp);
else
printe("%s: Syntax error in line %d", sesp->s_strp, yyline);
} else
printe("Syntax error");
}
/* end of sh/main.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.