rc: terminate rc when exec fails, cleanup
The execexec() function should never return, as it irreversably changes the filedescriptor table for the new program. This means rc's internal filedesciptors for reading the script get implicitely closed and we cannot continue the rc interpreter when Execute() fails. So Execute() now sets the error status, and execexec() runs Xexit() in case Execute() returns.
This commit is contained in:
parent
a9639c6894
commit
258fe87faf
7 changed files with 39 additions and 78 deletions
|
@ -101,7 +101,7 @@ glob(void *ap)
|
|||
return;
|
||||
}
|
||||
globname = emalloc(globlen);
|
||||
globname[0]='\0';
|
||||
memset(globname, 0, globlen);
|
||||
globdir(p, (uchar *)globname);
|
||||
efree(globname);
|
||||
if(svglobv==globv){
|
||||
|
|
|
@ -189,30 +189,27 @@ execforkexec(void)
|
|||
{
|
||||
char **argv;
|
||||
char file[1024];
|
||||
int nc;
|
||||
int nc, mc;
|
||||
word *path;
|
||||
int pid;
|
||||
|
||||
if(runq->argv->words==0)
|
||||
return -1;
|
||||
argv = mkargv(runq->argv->words);
|
||||
|
||||
mc = strlen(argv[1])+1;
|
||||
for(path = searchpath(runq->argv->words->word);path;path = path->next){
|
||||
nc = strlen(path->word);
|
||||
if(nc < sizeof file - 1){ /* 1 for / */
|
||||
strcpy(file, path->word);
|
||||
if(file[0]){
|
||||
strcat(file, "/");
|
||||
nc++;
|
||||
}
|
||||
if(nc+strlen(argv[1])<sizeof(file)){
|
||||
strcat(file, argv[1]);
|
||||
pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
|
||||
if(pid >= 0){
|
||||
free(argv);
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
if(nc + mc >= sizeof file - 1) /* 1 for / */
|
||||
continue;
|
||||
if(nc > 0){
|
||||
memmove(file, path->word, nc);
|
||||
file[nc++] = '/';
|
||||
}
|
||||
memmove(file+nc, argv[1], mc);
|
||||
pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
|
||||
if(pid >= 0){
|
||||
free(argv);
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
free(argv);
|
||||
|
|
|
@ -305,72 +305,36 @@ Updenv(void)
|
|||
|
||||
/* not used on plan 9 */
|
||||
int
|
||||
ForkExecute(char *file, char **argv, int sin, int sout, int serr)
|
||||
ForkExecute(char *, char **, int, int, int)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if(access(file, 1) != 0)
|
||||
return -1;
|
||||
switch(pid = fork()){
|
||||
case -1:
|
||||
return -1;
|
||||
case 0:
|
||||
if(sin >= 0)
|
||||
dup(sin, 0);
|
||||
else
|
||||
close(0);
|
||||
if(sout >= 0)
|
||||
dup(sout, 1);
|
||||
else
|
||||
close(1);
|
||||
if(serr >= 0)
|
||||
dup(serr, 2);
|
||||
else
|
||||
close(2);
|
||||
exec(file, argv);
|
||||
exits(file);
|
||||
}
|
||||
return pid;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Execute(word *args, word *path)
|
||||
{
|
||||
char **argv = mkargv(args);
|
||||
char file[1024], errstr[1024];
|
||||
int nc;
|
||||
char file[1024];
|
||||
int nc, mc;
|
||||
|
||||
Updenv();
|
||||
errstr[0] = '\0';
|
||||
mc = strlen(argv[1])+1;
|
||||
for(;path;path = path->next){
|
||||
nc = strlen(path->word);
|
||||
if(nc < sizeof file - 1){ /* 1 for / */
|
||||
strcpy(file, path->word);
|
||||
if(file[0]){
|
||||
strcat(file, "/");
|
||||
nc++;
|
||||
}
|
||||
if(nc + strlen(argv[1]) < sizeof file){
|
||||
strcat(file, argv[1]);
|
||||
exec(file, argv+1);
|
||||
rerrstr(errstr, sizeof errstr);
|
||||
/*
|
||||
* if file exists and is executable, exec should
|
||||
* have worked, unless it's a directory or an
|
||||
* executable for another architecture. in
|
||||
* particular, if it failed due to lack of
|
||||
* swap/vm (e.g., arg. list too long) or other
|
||||
* allocation failure, stop searching and print
|
||||
* the reason for failure.
|
||||
*/
|
||||
if (strstr(errstr, " allocat") != nil ||
|
||||
strstr(errstr, " full") != nil)
|
||||
break;
|
||||
}
|
||||
else werrstr("command name too long");
|
||||
if(nc + mc >= sizeof file - 1){ /* 1 for / */
|
||||
werrstr("command path name too long");
|
||||
continue;
|
||||
}
|
||||
if(nc > 0){
|
||||
memmove(file, path->word, nc);
|
||||
file[nc++] = '/';
|
||||
}
|
||||
memmove(file+nc, argv[1], mc);
|
||||
exec(file, argv+1);
|
||||
}
|
||||
pfmt(err, "%s: %s\n", argv[1], errstr);
|
||||
rerrstr(file, sizeof file);
|
||||
setstatus(file);
|
||||
pfmt(err, "%s: %s\n", argv[1], file);
|
||||
efree((char *)argv);
|
||||
}
|
||||
#define NDIR 256 /* shoud be a better way */
|
||||
|
@ -464,7 +428,7 @@ Again:
|
|||
}
|
||||
if(dir[f].i == dir[f].n)
|
||||
return 0;
|
||||
strcpy(p, dir[f].dbuf[dir[f].i].name);
|
||||
strncpy((char*)p, dir[f].dbuf[dir[f].i].name, NDIR);
|
||||
dir[f].i++;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ Xsimple(void)
|
|||
/* fork and wait is redundant */
|
||||
pushword("exec");
|
||||
execexec();
|
||||
Xexit();
|
||||
}
|
||||
else{
|
||||
flush(err);
|
||||
|
@ -120,6 +119,7 @@ execexec(void)
|
|||
doredir(runq->redir);
|
||||
Execute(runq->argv->words, searchpath(runq->argv->words->word));
|
||||
poplist();
|
||||
Xexit();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -9,15 +9,14 @@ emalloc(long n)
|
|||
void *p = Malloc(n);
|
||||
if(p==0)
|
||||
panic("Can't malloc %d bytes", n);
|
||||
/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } /**/
|
||||
return p;
|
||||
}
|
||||
|
||||
void*
|
||||
erealloc(void *p, long n)
|
||||
{
|
||||
p = Realloc(p, n); /* botch, should be Realloc */
|
||||
if(p==0)
|
||||
p = Realloc(p, n);
|
||||
if(p==0 && n!=0)
|
||||
panic("Can't realloc %d bytes\n", n);
|
||||
return p;
|
||||
}
|
||||
|
@ -25,7 +24,6 @@ erealloc(void *p, long n)
|
|||
void
|
||||
efree(void *p)
|
||||
{
|
||||
/* pfmt(err, "free %p\n", p); flush(err); /**/
|
||||
if(p)
|
||||
free(p);
|
||||
else pfmt(err, "free 0\n");
|
||||
|
|
|
@ -275,6 +275,7 @@ register struct word *args, *path;
|
|||
}
|
||||
}
|
||||
Bad:
|
||||
setstatus(msg);
|
||||
pfmt(err, "%s: %s\n", argv[1], msg);
|
||||
efree((char *)env);
|
||||
efree((char *)argv);
|
||||
|
@ -319,7 +320,7 @@ int onlydirs; /* ignored, just advisory */
|
|||
struct direct *dp = readdir(dirlist[f]);
|
||||
if(dp==0)
|
||||
return 0;
|
||||
strcpy(p, dp->d_name);
|
||||
strncpy(p, dp->d_name, NDIR);
|
||||
return 1;
|
||||
}
|
||||
Closedir(f){
|
||||
|
|
|
@ -299,6 +299,7 @@ Execute(word *args, word *path)
|
|||
}
|
||||
}
|
||||
rerrstr(file, sizeof file);
|
||||
setstatus(file);
|
||||
pfmt(err, "%s: %s\n", argv[1], file);
|
||||
efree((char *)argv);
|
||||
}
|
||||
|
@ -393,7 +394,7 @@ Again:
|
|||
}
|
||||
if(dir[f].i == dir[f].n)
|
||||
return 0;
|
||||
strcpy(p, dir[f].dbuf[dir[f].i].name);
|
||||
strncpy(p, dir[f].dbuf[dir[f].i].name, NDIR);
|
||||
dir[f].i++;
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue