@@ -18,6 +18,7 @@
#include <unistd.h>
#include <stdarg.h>
#include "bltin.h"
+#include "../exec.h"
/* test(1) accepts the following grammar:
oexpr ::= aexpr | aexpr "-o" oexpr ;
@@ -148,11 +149,6 @@ static int isoperand(char **);
static int newerf(const char *, const char *);
static int olderf(const char *, const char *);
static int equalf(const char *, const char *);
-#ifdef HAVE_FACCESSAT
-static int test_file_access(const char *, int);
-#else
-static int test_access(const struct stat64 *, int);
-#endif
#ifdef HAVE_FACCESSAT
# ifdef HAVE_TRADITIONAL_FACCESSAT
@@ -527,7 +523,7 @@ static int has_exec_bit_set(const char *path)
return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
}
-static int test_file_access(const char *path, int mode)
+int test_file_access(const char *path, int mode)
{
if (faccessat_confused_about_superuser() &&
mode == X_OK && geteuid() == 0 && !has_exec_bit_set(path))
@@ -657,7 +653,7 @@ static int test_file_access(const char *path, int mode)
* (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root.
* i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b).
*/
-static int test_access(const struct stat64 *sp, int stmode)
+int test_access(const struct stat64 *sp, int stmode)
{
gid_t *groups;
register int n;
@@ -325,7 +325,22 @@ printentry(struct tblentry *cmdp)
out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr);
}
+static int test_exec(const char *fullname, struct stat64 *statb)
+{
+ if (!S_ISREG(statb->st_mode))
+ return 0;
+ if ((statb->st_mode & 0111) != 0111 &&
+#ifdef HAVE_FACCESSAT
+ !test_file_access(fullname, X_OK)
+#else
+ !test_access(statb, X_OK)
+#endif
+ )
+ return 0;
+
+ return 1;
+}
/*
* Resolve a command name. If you change this routine, you may have to
@@ -354,9 +369,12 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
if (errno == EINTR)
continue;
#endif
+absfail:
entry->cmdtype = CMDUNKNOWN;
return;
}
+ if (!test_exec(name, &statb))
+ goto absfail;
}
entry->cmdtype = CMDNORMAL;
return;
@@ -451,9 +469,6 @@ loop:
e = errno;
goto loop;
}
- e = EACCES; /* if we fail, this will be the error */
- if (!S_ISREG(statb.st_mode))
- continue;
if (lpathopt) { /* this is a %func directory */
stalloc(len);
readcmdfile(fullname);
@@ -464,20 +479,9 @@ loop:
stunalloc(fullname);
goto success;
}
-#ifdef notdef
- /* XXX this code stops root executing stuff, and is buggy
- if you need a group from the group list. */
- if (statb.st_uid == geteuid()) {
- if ((statb.st_mode & 0100) == 0)
- goto loop;
- } else if (statb.st_gid == getegid()) {
- if ((statb.st_mode & 010) == 0)
- goto loop;
- } else {
- if ((statb.st_mode & 01) == 0)
- goto loop;
- }
-#endif
+ e = EACCES; /* if we fail, this will be the error */
+ if (!test_exec(fullname, &statb))
+ continue;
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
if (!updatetbl) {
entry->cmdtype = CMDNORMAL;
@@ -62,6 +62,8 @@ union node;
extern const char *pathopt; /* set by padvance */
+struct stat64;
+
void shellexec(char **, const char *, int)
__attribute__((__noreturn__));
int padvance_magic(const char **path, const char *name, int magic);
@@ -78,6 +80,9 @@ void unsetfunc(const char *);
int typecmd(int, char **);
int commandcmd(int, char **);
+int test_file_access(const char *path, int mode);
+int test_access(const struct stat64 *sp, int stmode);
+
static inline int padvance(const char **path, const char *name)
{
return padvance_magic(path, name, 1);