Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help
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;
  		}
  	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709030620.QAA01087>