diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-02-22 22:25:21 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-02-22 22:25:21 +0100 |
commit | 258fe87faf0a64947bb91c8ed93f8ea378a36f83 (patch) | |
tree | c0e683a2e9f080ac67f7fd6947483cde52deb4bd /sys/src/cmd | |
parent | a9639c68947a9872cacd8a9629df097fe009503b (diff) |
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.
Diffstat (limited to 'sys/src/cmd')
-rw-r--r-- | sys/src/cmd/rc/glob.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/rc/haventfork.c | 29 | ||||
-rw-r--r-- | sys/src/cmd/rc/plan9.c | 74 | ||||
-rw-r--r-- | sys/src/cmd/rc/simple.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/rc/subr.c | 6 | ||||
-rw-r--r-- | sys/src/cmd/rc/unix.c | 3 | ||||
-rw-r--r-- | sys/src/cmd/rc/win32.c | 3 |
7 files changed, 40 insertions, 79 deletions
diff --git a/sys/src/cmd/rc/glob.c b/sys/src/cmd/rc/glob.c index 295d7b6a6..90513243d 100644 --- a/sys/src/cmd/rc/glob.c +++ b/sys/src/cmd/rc/glob.c @@ -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){ diff --git a/sys/src/cmd/rc/haventfork.c b/sys/src/cmd/rc/haventfork.c index aa97f5c58..1e5aa0dc9 100644 --- a/sys/src/cmd/rc/haventfork.c +++ b/sys/src/cmd/rc/haventfork.c @@ -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); diff --git a/sys/src/cmd/rc/plan9.c b/sys/src/cmd/rc/plan9.c index 6ad3ba3bd..61ddfaba7 100644 --- a/sys/src/cmd/rc/plan9.c +++ b/sys/src/cmd/rc/plan9.c @@ -305,72 +305,36 @@ Updenv(void) /* not used on plan 9 */ int -ForkExecute(char *file, char **argv, int sin, int sout, int serr) -{ - 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; +ForkExecute(char *, char **, int, int, int) +{ + 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; } diff --git a/sys/src/cmd/rc/simple.c b/sys/src/cmd/rc/simple.c index fb50ce31d..59e8483e6 100644 --- a/sys/src/cmd/rc/simple.c +++ b/sys/src/cmd/rc/simple.c @@ -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 diff --git a/sys/src/cmd/rc/subr.c b/sys/src/cmd/rc/subr.c index ee5550a8d..0bdf99742 100644 --- a/sys/src/cmd/rc/subr.c +++ b/sys/src/cmd/rc/subr.c @@ -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"); diff --git a/sys/src/cmd/rc/unix.c b/sys/src/cmd/rc/unix.c index 31c6e2145..8eaaa09f8 100644 --- a/sys/src/cmd/rc/unix.c +++ b/sys/src/cmd/rc/unix.c @@ -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){ diff --git a/sys/src/cmd/rc/win32.c b/sys/src/cmd/rc/win32.c index d19629644..9b3cc5749 100644 --- a/sys/src/cmd/rc/win32.c +++ b/sys/src/cmd/rc/win32.c @@ -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; } |