From owner-freebsd-bugs Tue Sep 2 23:25:08 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id XAA21776 for bugs-outgoing; Tue, 2 Sep 1997 23:25:08 -0700 (PDT) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id XAA21770 for ; Tue, 2 Sep 1997 23:25:04 -0700 (PDT) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.5/8.6.9) id QAA01087 for bugs@freebsd.org; Wed, 3 Sep 1997 16:20:12 +1000 Date: Wed, 3 Sep 1997 16:20:12 +1000 From: Bruce Evans Message-Id: <199709030620.QAA01087@godzilla.zeta.org.au> To: bugs@freebsd.org Subject: fixes for execlp() and execvp() Sender: owner-freebsd-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk 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; } }