about summary refs log tree commit diff
path: root/posix/execvp.c
diff options
context:
space:
mode:
Diffstat (limited to 'posix/execvp.c')
-rw-r--r--posix/execvp.c83
1 files changed, 41 insertions, 42 deletions
diff --git a/posix/execvp.c b/posix/execvp.c
index 7afb01d11f..3f93357af8 100644
--- a/posix/execvp.c
+++ b/posix/execvp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 95, 96, 97, 98, 99 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
@@ -24,37 +24,31 @@
 #include <paths.h>
 
 
+/* The file is accessible but it is not an executable file.  Invoke
+   the shell to interpret it as a script.  */
 static void
 internal_function
-execute (const char *file, char *const argv[])
+script_execute (const char *file, char *const argv[])
 {
-  execv (file, argv);
-
-  if (errno == ENOEXEC)
-    {
-      /* The file is accessible but it is not an executable file.
-	 Invoke the shell to interpret it as a script.  */
-
-      /* Count the arguments.  */
-      int argc = 0;
-      while (argv[argc++])
-	;
-
-      /* Construct an argument list for the shell.  */
+  /* Count the arguments.  */
+  int argc = 0;
+  while (argv[argc++])
+    ;
+
+  /* Construct an argument list for the shell.  */
+  {
+    char *new_argv[argc + 1];
+    new_argv[0] = (char *) _PATH_BSHELL;
+    new_argv[1] = (char *) file;
+    while (argc > 1)
       {
-	char *new_argv[argc + 1];
-	new_argv[0] = (char *) _PATH_BSHELL;
-	new_argv[1] = (char *) file;
-	while (argc > 1)
-	  {
-	    new_argv[argc] = argv[argc - 1];
-	    --argc;
-	  }
-
-	/* Execute the shell.  */
-	execv (new_argv[0], new_argv);
+	new_argv[argc] = argv[argc - 1];
+	--argc;
       }
-    }
+
+    /* Execute the shell.  */
+    execv (new_argv[0], new_argv);
+  }
 }
 
 
@@ -65,8 +59,6 @@ execvp (file, argv)
      const char *file;
      char *const argv[];
 {
-  int got_eacces = 0;
-
   if (*file == '\0')
     {
       /* We check the simple case first. */
@@ -75,10 +67,16 @@ execvp (file, argv)
     }
 
   if (strchr (file, '/') != NULL)
-    /* Don't search when it contains a slash.  */
-    execute (file, argv);
+    {
+      /* Don't search when it contains a slash.  */
+      execv (file, argv);
+
+      if (errno == ENOEXEC)
+	script_execute (file, argv);
+    }
   else
     {
+      int got_eacces = 0;
       char *path, *p, *name;
       size_t len;
 
@@ -100,9 +98,7 @@ execvp (file, argv)
       do
 	{
 	  path = p;
-	  p = strchr (path, ':');
-	  if (p == NULL)
-	    p = strchr (path, '\0');
+	  p = __strchrnul (path, ':');
 
 	  if (p == path)
 	    /* Two adjacent colons, or a colon at the beginning or the end
@@ -113,11 +109,14 @@ execvp (file, argv)
 	      /* Construct the pathname to try.  */
 	      char *tmp = __mempcpy (name, path, p - path);
 	      *tmp++ = '/';
-	      (void) __mempcpy (tmp, file, len);
+	      memcpy (tmp, file, len);
 	    }
 
 	  /* Try to execute this name.  If it works, execv will not return.  */
-	  execute (name, argv);
+	  execv (name, argv);
+
+	  if (errno == ENOEXEC)
+	    script_execute (name, argv);
 
 	  switch (errno)
 	    {
@@ -142,13 +141,13 @@ execvp (file, argv)
 	    }
 	}
       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);
+      /* 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 the error from the last attempt (probably ENOENT).  */
   return -1;