Date: Wed, 3 Sep 1997 16:20:12 +1000 From: Bruce Evans <bde@zeta.org.au> To: bugs@freebsd.org Subject: fixes for execlp() and execvp() Message-ID: <199709030620.QAA01087@godzilla.zeta.org.au>
index | next in thread | raw e-mail
Please review these changes. I tested a version that only continued the
search after EISDIR, ELOOP, ENAMETOOLONG and ESTALE (and of course ENOENT),
but then found that POSIX.2 specified most of the braindamage in sh(1).
I think its more important to be compatible with sh(1) than "right".
Bruce
Log:
Handle execve() failure in execlp() and execvp() the same (*) as in sh(1):
- don't retry for ETXTBSY.
- continue with the next component of the search path after most errors.
Previously we returned after most errors. This change is significant
for at least the following errors:
- E2BIG - accessible executable found, but too many args.
- EIO - i/o error somewhere, most likely for loading an accessible
executable.
- EISDIR - the file being searched for is found as a directory (PR 1487).
- ELOOP - too many symlinks in the path component or file.
- ENAMETOOLONG - too-long name in the path component or file, or too-long
path.
- ENOMEM - executable found, but too big. FreeBSD returns this error for
more cases than are documented in execve(2), and it can be returned for
inaccessible files.
- ENOTDIR - non-directory in path component.
- ESTALE - stale nfs handle for path component or file (not documented in
execve(2).
- ETXTBSY - accessible executable found, but busy.
It is bogus to keep searching after finding an accessible executable, but
that's what sh(1) does and what POSIX.2 seems to require.
(*) sh(1) currently sets $? wrong after finding an inaccessible executable.
EACCES should be sticky like it already was for execlp().
PR: 1487
diff -c2 exec.3~ exec.3
*** exec.3~ Thu May 23 17:07:33 1996
--- exec.3 Wed Sep 3 15:09:03 1997
***************
*** 146,150 ****
is
used.
! In addition, certain errors are treated specially.
.Pp
If permission is denied for a file (the attempted
--- 146,150 ----
is
used.
! In addition, errors are treated specially.
.Pp
If permission is denied for a file (the attempted
***************
*** 159,162 ****
--- 159,170 ----
.Er EACCES .
.Pp
+ If the attempted
+ .Fn execve
+ returns any other error,
+ these functions will behave as if
+ .Fn execve
+ returned
+ .Er ENOENT .
+ .Pp
If the header of a file isn't recognized (the attempted
.Fn execve
***************
*** 167,177 ****
(If this attempt fails, no further searching is done.)
.Pp
- If the file is currently busy (the attempted
- .Fn execve
- returned
- .Er ETXTBUSY ) ,
- these functions will sleep for several seconds,
- periodically re-attempting to execute the file.
- .Pp
The function
.Fn exect
--- 175,178 ----
***************
*** 231,236 ****
and
.Fn execvp
! when errors occur while attempting to execute the file is historic
! practice, but has not traditionally been documented and is not specified
by the
.Tn POSIX
--- 232,237 ----
and
.Fn execvp
! when errors occur while attempting to execute the file is not historic
! practice, and has not traditionally been documented and is not specified
by the
.Tn POSIX
***************
*** 242,250 ****
.Fn execvp
ignored all errors except for the ones described above and
.Er ENOMEM
and
.Er E2BIG ,
upon which they returned.
! They now return if any error other than the ones described above occurs.
.Sh STANDARDS
.Fn Execl ,
--- 243,266 ----
.Fn execvp
ignored all errors except for the ones described above and
+ .Er ETXTBSY ,
+ upon which they retried after sleeping for several seconds, and
.Er ENOMEM
and
.Er E2BIG ,
upon which they returned.
! They now ignore all errors except
! .Er EACCES
! and
! .Er ENOEXEC .
! In
! .Bx 4.4 ,
! they returned upon all errors except
! .Er EACCES ,
! .Er ENOEXEC ,
! .Er ENOENT ,
! and
! .Er ETXTBSY .
! This was changed to match the behaviour of
! .Xr sh 1 .
.Sh STANDARDS
.Fn Execl ,
diff -c2 exec.c~ exec.c
*** exec.c~ Wed Nov 20 02:07:18 1996
--- exec.c Wed Sep 3 14:35:40 1997
***************
*** 188,195 ****
register int cnt, lp, ln;
register char *p;
! int eacces, etxtbsy;
char *bp, *cur, *path, buf[MAXPATHLEN];
! eacces = etxtbsy = 0;
/* If it's an absolute or relative path name, it's easy. */
--- 188,195 ----
register int cnt, lp, ln;
register char *p;
! int eacces;
char *bp, *cur, *path, buf[MAXPATHLEN];
! eacces = 0;
/* If it's an absolute or relative path name, it's easy. */
***************
*** 245,250 ****
eacces = 1;
break;
- case ENOENT:
- break;
case ENOEXEC:
for (cnt = 0; argv[cnt]; ++cnt)
--- 245,248 ----
***************
*** 259,268 ****
free(memp);
goto done;
- case ETXTBSY:
- if (etxtbsy < 3)
- (void)sleep(++etxtbsy);
- goto retry;
default:
! goto done;
}
}
--- 257,262 ----
free(memp);
goto done;
default:
! break;
}
}
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709030620.QAA01087>
