diff --git a/ChangeLog b/ChangeLog
index 9bdcb51..892062c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2016-01-25  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+	* posix/execvpe.c (__execvpe): Remove dynamic allocation.
+	* posix/Makefile (tests): Add tst-execvpe{1,2,3,4,5,6}.
+	* posix/tst-execvp1.c (do_test): Use a macro to call execvp.
+	* posix/tst-execvp2.c (do_test): Likewise.
+	* posix/tst-execvp3.c (do_test): Likewise.
+	* posix/tst-execvp4.c (do_test): Likewise.
+	* posix/tst-execvpe1.c: New file.
+	* posix/tst-execvpe2.c: Likewise.
+	* posix/tst-execvpe3.c: Likewise.
+	* posix/tst-execvpe4.c: Likewise.
+	* posix/tst-execvpe5.c: Likewise.
+	* posix/tst-execvpe6.c: Likewise.
+
 2016-01-22  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
 	* string/tst-endian.c: Include <libc-internal.h>.
diff --git a/posix/Makefile b/posix/Makefile
index f94e023..e251363 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -82,6 +82,8 @@ tests		:= tstgetopt testfnm runtests runptests	     \
 		   tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
 		   tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
 		   tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
+		   tst-execvpe1 tst-execvpe2 tst-execvpe3 tst-execvpe4 \
+		   tst-execvpe5 tst-execvpe6 \
 		   tst-rfc3484-3 \
 		   tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
 		   bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
@@ -228,6 +230,7 @@ tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
 
 tst-exec-ARGS = -- $(host-test-program-cmd)
 tst-exec-static-ARGS = $(tst-exec-ARGS)
+tst-execvpe5-ARGS = -- $(host-test-program-cmd)
 tst-spawn-ARGS = -- $(host-test-program-cmd)
 tst-spawn-static-ARGS = $(tst-spawn-ARGS)
 tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
diff --git a/posix/execvpe.c b/posix/execvpe.c
index 61697a7..a774d85 100644
--- a/posix/execvpe.c
+++ b/posix/execvpe.c
@@ -15,7 +15,6 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -23,15 +22,36 @@
 #include <string.h>
 #include <errno.h>
 #include <paths.h>
+#include <confstr.h>
+#include <sys/param.h>
 
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+#  define PATH_MAX MAXPATHLEN
+# else
+#  define PATH_MAX 1024
+# endif
+#endif
 
 /* The file is accessible but it is not an executable file.  Invoke
    the shell to interpret it as a script.  */
 static void
-internal_function
-scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
+maybe_script_execute (const char *file, char *const argv[], char *const envp[])
 {
+  /* Linux accepts a very large argument number (INT_MAX to fit on a signed
+     32-bit integer).  To limit stack allocation we set it to a lower
+     bound.  */
+  int argc = 0;
+  int limit = MIN (NCARGS, __MAX_ALLOCA_CUTOFF / sizeof (char *));
+  while (argv[argc++] != NULL)
+    if (argc >= limit)
+      {
+	errno = E2BIG;
+	return;
+      }
+
   /* Construct an argument list for the shell.  */
+  char *new_argv[argc];
   new_argv[0] = (char *) _PATH_BSHELL;
   new_argv[1] = (char *) file;
   while (argc > 1)
@@ -39,6 +59,9 @@ scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
       new_argv[argc] = argv[argc - 1];
       --argc;
     }
+
+  /* Execute the shell.  */
+  __execve (new_argv[0], new_argv, envp);
 }
 
 
@@ -47,170 +70,109 @@ scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
 int
 __execvpe (const char *file, char *const argv[], char *const envp[])
 {
+  /* We check the simple case first. */
   if (*file == '\0')
     {
-      /* We check the simple case first. */
       __set_errno (ENOENT);
       return -1;
     }
 
+  /* Don't search when it contains a slash.  */
   if (strchr (file, '/') != NULL)
     {
-      /* Don't search when it contains a slash.  */
       __execve (file, argv, envp);
 
       if (errno == ENOEXEC)
-	{
-	  /* Count the arguments.  */
-	  int argc = 0;
-	  while (argv[argc++])
-	    ;
-	  size_t len = (argc + 1) * sizeof (char *);
-	  char **script_argv;
-	  void *ptr = NULL;
-	  if (__libc_use_alloca (len))
-	    script_argv = alloca (len);
-	  else
-	    script_argv = ptr = malloc (len);
-
-	  if (script_argv != NULL)
-	    {
-	      scripts_argv (file, argv, argc, script_argv);
-	      __execve (script_argv[0], script_argv, envp);
-
-	      free (ptr);
-	    }
-	}
+        maybe_script_execute (file, argv, envp);
+
+      return -1;
     }
-  else
+
+  const char *path = getenv ("PATH");
+  if (!path)
+    path = CS_PATH;
+  /* Although GLIBC does not enforce NAME_MAX, we set it as the maximum
+     size to avoid unbounded stack allocation.  Same applies for
+     PATH_MAX.  */
+  size_t file_len = __strnlen (file, NAME_MAX + 1);
+  size_t path_len = __strnlen (path, PATH_MAX - 1) + 1;
+
+  if ((file_len > NAME_MAX)
+      || !__libc_alloca_cutoff (path_len + file_len + 1))
     {
-      size_t pathlen;
-      size_t alloclen = 0;
-      char *path = getenv ("PATH");
-      if (path == NULL)
-	{
-	  pathlen = confstr (_CS_PATH, (char *) NULL, 0);
-	  alloclen = pathlen + 1;
-	}
-      else
-	pathlen = strlen (path);
+      errno = ENAMETOOLONG;
+      return -1;
+    }
 
-      size_t len = strlen (file) + 1;
-      alloclen += pathlen + len + 1;
+  const char *subp;
+  bool got_eacces = false;
+  for (const char *p = path; ; p = subp)
+    {
+      char buffer[path_len + file_len + 1];
 
-      char *name;
-      char *path_malloc = NULL;
-      if (__libc_use_alloca (alloclen))
-	name = alloca (alloclen);
-      else
-	{
-	  path_malloc = name = malloc (alloclen);
-	  if (name == NULL)
-	    return -1;
-	}
+      subp = __strchrnul (p, ':');
 
-      if (path == NULL)
+      /* PATH is larger than PATH_MAX and thus potentially larger than
+	 the stack allocation.  */
+      if (subp - p >= path_len)
 	{
-	  /* There is no `PATH' in the environment.
-	     The default search path is the current directory
-	     followed by the path `confstr' returns for `_CS_PATH'.  */
-	  path = name + pathlen + len + 1;
-	  path[0] = ':';
-	  (void) confstr (_CS_PATH, path + 1, pathlen);
+          /* If there is only one path, bail out.  */
+	  if (!*subp)
+	    break;
+	  /* Otherwise skip to next one.  */
+	  continue;
 	}
 
-      /* Copy the file name at the top.  */
-      name = (char *) memcpy (name + pathlen + 1, file, len);
-      /* And add the slash.  */
-      *--name = '/';
+      /* Set current path considered plus a '/'.  */
+      memcpy (buffer, p, subp - p);
+      buffer[subp - p] = '/';
+      /* And the file to execute.  */
+      memcpy (buffer + (subp - p) + (subp > p), file, file_len + 1);
+
+      __execve (buffer, argv, envp);
+
+      if (errno == ENOEXEC)
+        maybe_script_execute (buffer, argv, envp);
 
-      char **script_argv = NULL;
-      void *script_argv_malloc = NULL;
-      bool got_eacces = false;
-      char *p = path;
-      do
+      switch (errno)
 	{
-	  char *startp;
-
-	  path = p;
-	  p = __strchrnul (path, ':');
-
-	  if (p == path)
-	    /* Two adjacent colons, or a colon at the beginning or the end
-	       of `PATH' means to search the current directory.  */
-	    startp = name + 1;
-	  else
-	    startp = (char *) memcpy (name - (p - path), path, p - path);
-
-	  /* Try to execute this name.  If it works, execve will not return. */
-	  __execve (startp, argv, envp);
-
-	  if (errno == ENOEXEC)
-	    {
-	      if (script_argv == NULL)
-		{
-		  /* Count the arguments.  */
-		  int argc = 0;
-		  while (argv[argc++])
-		    ;
-		  size_t arglen = (argc + 1) * sizeof (char *);
-		  if (__libc_use_alloca (alloclen + arglen))
-		    script_argv = alloca (arglen);
-		  else
-		    script_argv = script_argv_malloc = malloc (arglen);
-		  if (script_argv == NULL)
-		    {
-		      /* A possible EACCES error is not as important as
-			 the ENOMEM.  */
-		      got_eacces = false;
-		      break;
-		    }
-		  scripts_argv (startp, argv, argc, script_argv);
-		}
-
-	      __execve (script_argv[0], script_argv, envp);
-	    }
-
-	  switch (errno)
-	    {
-	    case EACCES:
-	      /* Record the we got a `Permission denied' error.  If we end
-		 up finding no executable we can use, we want to diagnose
-		 that we did find one but were denied access.  */
-	      got_eacces = true;
-	    case ENOENT:
-	    case ESTALE:
-	    case ENOTDIR:
-	      /* Those errors indicate the file is missing or not executable
-		 by us, in which case we want to just try the next path
-		 directory.  */
-	    case ENODEV:
-	    case ETIMEDOUT:
-	      /* Some strange filesystems like AFS return even
-		 stranger error numbers.  They cannot reasonably mean
-		 anything else so ignore those, too.  */
-	      break;
-
-	    default:
-	      /* Some other error means we found an executable file, but
-		 something went wrong executing it; return the error to our
-		 caller.  */
-	      return -1;
-	    }
+	  case EACCES:
+	  /* Record the we got a 'Permission denied' error.  If we end
+             up finding no executable we can use, we want to diagnose
+             that we did find one but were denied access.  */
+	    got_eacces = true;
+	  case ENOENT:
+	  case ESTALE:
+	  case ENOTDIR:
+	  /* Those errors indicate the file is missing or not executable
+	     by us, in which case we want to just try the next path
+	     directory.  */
+	  case ENODEV:
+	  case ETIMEDOUT:
+          /* Some strange filesystems like AFS return even
+             stranger error numbers.  They cannot reasonably mean
+             anything else so ignore those, too.  */
+	    break;
+
+          default:
+	  /* Some other error means we found an executable file, but
+	     something went wrong executing it; return the error to our
+	     caller.  */
+	    return -1;
 	}
-      while (*p++ != '\0');
-
-      /* We tried every element and none of them worked.  */
-      if (got_eacces)
-	/* At least one failure was due to permissions, so report that
-	   error.  */
-	__set_errno (EACCES);
 
-      free (script_argv_malloc);
-      free (path_malloc);
+      if (*subp++ == '\0')
+	break;
     }
 
-  /* Return the error from the last attempt (probably ENOENT).  */
+  /* We tried every element and none of them worked.  */
+  if (got_eacces)
+    /* At least one failure was due to permissions, so report that
+       error.  */
+    __set_errno (EACCES);
+
   return -1;
+
 }
+
 weak_alias (__execvpe, execvpe)
diff --git a/posix/tst-execvp1.c b/posix/tst-execvp1.c
index ecc673d..fe98ce5 100644
--- a/posix/tst-execvp1.c
+++ b/posix/tst-execvp1.c
@@ -3,6 +3,10 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#ifndef EXECVP
+# define EXECVP(__file, __argv) execvp (__file, __argv)
+#endif
+
 static int
 do_test (void)
 {
@@ -19,7 +23,7 @@ do_test (void)
 
   char *argv[] = { (char *) "does-not-exist", NULL };
   errno = 0;
-  execvp (argv[0], argv);
+  EXECVP (argv[0], argv);
 
   if (errno != ENOENT)
     {
diff --git a/posix/tst-execvp2.c b/posix/tst-execvp2.c
index 7e0f5d8..9be8733 100644
--- a/posix/tst-execvp2.c
+++ b/posix/tst-execvp2.c
@@ -14,6 +14,9 @@ static int do_test (void);
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
 
+#ifndef EXECVP
+# define EXECVP(__file, __argv)  execvp (__file, __argv)
+#endif
 
 static char *copy;
 
@@ -70,7 +73,7 @@ do_test (void)
 
   char *argv[] = { basename (copy), NULL };
   errno = 0;
-  execvp (argv[0], argv);
+  EXECVP (argv[0], argv);
 
   if (errno != EACCES)
     {
diff --git a/posix/tst-execvp3.c b/posix/tst-execvp3.c
index 5ebc879..43f7c34 100644
--- a/posix/tst-execvp3.c
+++ b/posix/tst-execvp3.c
@@ -12,6 +12,9 @@ static int do_test (void);
 
 #include "../test-skeleton.c"
 
+#ifndef EXECVP
+# define EXECVP(__file, __argv)  execvp (__file, __argv)
+#endif
 
 static char *fname;
 
@@ -35,7 +38,7 @@ do_test (void)
     }
 
   char *argv[] = { fname, NULL };
-  execvp (basename (fname), argv);
+  EXECVP (basename (fname), argv);
 
   /* If we come here, the execvp call failed.  */
   return 1;
diff --git a/posix/tst-execvp4.c b/posix/tst-execvp4.c
index 531fab2..116624f 100644
--- a/posix/tst-execvp4.c
+++ b/posix/tst-execvp4.c
@@ -5,6 +5,10 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
+#ifndef EXECVP
+# define EXECVP(__file, __argv)  execvp (__file, __argv)
+#endif
+
 static int
 do_test (void)
 {
@@ -27,7 +31,7 @@ do_test (void)
 
   unsetenv ("PATH");
   char *argv[] = { buf + 9, NULL };
-  execvp (argv[0], argv);
+  EXECVP (argv[0], argv);
   return 0;
 }
 
diff --git a/posix/tst-execvpe1.c b/posix/tst-execvpe1.c
new file mode 100644
index 0000000..7b386c8
--- /dev/null
+++ b/posix/tst-execvpe1.c
@@ -0,0 +1,20 @@
+/* Check ENOENT failure for execvpe.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define EXECVP(__file, __argv) execvpe (__file, __argv, NULL)
+#include <posix/tst-execvp1.c>
diff --git a/posix/tst-execvpe2.c b/posix/tst-execvpe2.c
new file mode 100644
index 0000000..3c99fb1
--- /dev/null
+++ b/posix/tst-execvpe2.c
@@ -0,0 +1,20 @@
+/* Check EACCES for execvpe.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define EXECVP(__file, __argv) execvpe (__file, __argv, NULL)
+#include <posix/tst-execvp2.c>
diff --git a/posix/tst-execvpe3.c b/posix/tst-execvpe3.c
new file mode 100644
index 0000000..8380fd3
--- /dev/null
+++ b/posix/tst-execvpe3.c
@@ -0,0 +1,20 @@
+/* Check script execution without shebang for execvpe.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define EXECVP(__file, __argv) execvpe (__file, __argv, NULL)
+#include <posix/tst-execvp3.c>
diff --git a/posix/tst-execvpe4.c b/posix/tst-execvpe4.c
new file mode 100644
index 0000000..08fdaf0
--- /dev/null
+++ b/posix/tst-execvpe4.c
@@ -0,0 +1,20 @@
+/* Check unexistent binary for execvpe.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define EXECVP(__file, __argv) execvpe (__file, __argv, NULL)
+#include <posix/tst-execvp4.c>
diff --git a/posix/tst-execvpe5.c b/posix/tst-execvpe5.c
new file mode 100644
index 0000000..09f0fb0
--- /dev/null
+++ b/posix/tst-execvpe5.c
@@ -0,0 +1,130 @@
+/* General tests for execpve.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wait.h>
+
+
+/* Nonzero if the program gets called via `exec'.  */
+static int restart;
+
+
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+/* Prototype for our test function.  */
+extern void do_prepare (int argc, char *argv[]);
+extern int do_test (int argc, char *argv[]);
+
+#include "../test-skeleton.c"
+
+#define EXECVPE_KEY    "EXECVPE_ENV"
+#define EXECVPE_VALUE  "execvpe_test"
+
+
+static int
+handle_restart (void)
+{
+  /* First check if only one variable is passed on execvpe.  */
+  int env_count = 0;
+  for (char **e = environ; *e != NULL; ++e)
+    if (++env_count == INT_MAX)
+      error (EXIT_FAILURE, 0, "environment variable number overflow");
+  if (env_count != 1)
+    error (EXIT_FAILURE, 0, "wrong number of environment variables");
+
+  /* Check if the combinarion os "EXECVPE_ENV=execvpe_test"  */
+  const char *env = getenv (EXECVPE_KEY);
+  if (env == NULL)
+    error (EXIT_FAILURE, 0, "test environment variable not found");
+
+  if (strncmp (env, EXECVPE_VALUE, sizeof (EXECVPE_VALUE)))
+    error (EXIT_FAILURE, 0, "test environment variable with wrong value");
+
+  return 0;
+}
+
+
+int
+do_test (int argc, char *argv[])
+{
+  pid_t pid;
+  int status;
+
+  /* We must have
+     - one or four parameters left if called initially
+       + path for ld.so		optional
+       + "--library-path"	optional
+       + the library path	optional
+       + the application name
+  */
+
+  if (restart)
+    {
+      if (argc != 1)
+	error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc);
+
+      return handle_restart ();
+    }
+
+  if (argc != 2 && argc != 5)
+    error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc);
+
+  /* We want to test the `execvpe' function.  To do this we restart the
+     program with an additional parameter.  */
+  pid = fork ();
+  if (pid == 0)
+    {
+      /* This is the child.  Construct the command line.  */
+
+      /* We cast here to char* because the test itself does not modify neither
+	 the argument nor the environment list.  */
+      char *envs[] = { (char*)(EXECVPE_KEY "=" EXECVPE_VALUE), NULL };
+      if (argc == 5)
+	{
+	  char *args[] = { argv[1], argv[2], argv[3], argv[4],
+			   (char*)"--direct", (char*)"--restart", NULL };
+	  execvpe (args[0], args, envs);
+	}
+      else
+	{
+	  char *args[] = { argv[1], argv[1],
+			   (char*)"--direct", (char*)"--restart", NULL };
+	  execvpe (args[0], args, envs);
+	}
+
+      error (EXIT_FAILURE, errno, "cannot exec");
+    }
+  else if (pid == (pid_t) -1)
+    error (EXIT_FAILURE, errno, "cannot fork");
+
+  /* Wait for the child.  */
+  if (waitpid (pid, &status, 0) != pid)
+    error (EXIT_FAILURE, errno, "wrong child");
+
+  if (WTERMSIG (status) != 0)
+    error (EXIT_FAILURE, 0, "Child terminated incorrectly");
+  status = WEXITSTATUS (status);
+
+  return status;
+}
diff --git a/posix/tst-execvpe6.c b/posix/tst-execvpe6.c
new file mode 100644
index 0000000..e099a2f
--- /dev/null
+++ b/posix/tst-execvpe6.c
@@ -0,0 +1,82 @@
+/* Check execvpe script argument handling.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+static char *fname;
+
+static void do_prepare (void);
+#define PREPARE(argc, argv) do_prepare ()
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+static void
+do_prepare (void)
+{
+  int fd = create_temp_file ("testscript", &fname);
+  dprintf (fd, "echo foo\n");
+  fchmod (fd, 0700);
+  close (fd);
+}
+
+static int
+do_test (void)
+{
+  if  (setenv ("PATH", test_dir, 1) != 0)
+    {
+      puts ("setenv failed");
+      return 1;
+    }
+
+  /* To limit stack allocation for argument construction in case of
+     script without shebang execvpe limits total number of argument
+     to NCARGS.  */
+  const size_t max_args = NCARGS + 1;
+  char **args = malloc ((NCARGS + 1) * sizeof (char*));
+  if (args == NULL)
+    {
+      puts ("malloc failed");
+      return 1;
+    }
+
+  args[0] = fname;
+  for (int i=1; i < max_args; ++i)
+    args[i] = strdup ("a");
+  args[max_args] = NULL;
+
+  execvpe (basename (fname), args, NULL);
+
+  for (int i=1; i < max_args; ++i)
+    free (args[i]);
+  free (args);
+
+  if (errno != E2BIG)
+    {
+      printf ("errno = %d (%m), expected E2BIG\n", errno);
+      return 1;
+    }
+
+  return 0;
+}
