install-reloc: Support multi-binary installation.
[gnulib.git] / lib / spawni.c
index 0d0d418..17b903f 100644 (file)
@@ -1,5 +1,5 @@
 /* Guts of POSIX spawn interface.  Generic POSIX.1 version.
-   Copyright (C) 2000-2005, 2006, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2000-2006, 2008-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    This program is free software: you can redistribute it and/or modify
    was wanted there is no way to signal an error using one of the
    available methods.  The committee chose to signal an error by a
    normal program exit with the exit code 127.  */
-#define SPAWN_ERROR    127
+#define SPAWN_ERROR     127
+
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* Native Windows API.  */
+int
+__spawni (pid_t *pid, const char *file,
+          const posix_spawn_file_actions_t *file_actions,
+          const posix_spawnattr_t *attrp, char *const argv[],
+          char *const envp[], int use_path)
+{
+  /* Not yet implemented.  */
+  return ENOSYS;
+}
+
+#else
 
 
 /* The file is accessible but it is not an executable file.  Invoke
@@ -107,8 +123,8 @@ script_execute (const char *file, char *const argv[], char *const envp[])
     new_argv[1] = (char *) file;
     while (argc > 1)
       {
-       new_argv[argc] = argv[argc - 1];
-       --argc;
+        new_argv[argc] = argv[argc - 1];
+        --argc;
       }
 
     /* Execute the shell.  */
@@ -121,9 +137,9 @@ script_execute (const char *file, char *const argv[], char *const envp[])
    Before running the process perform the actions described in FILE-ACTIONS. */
 int
 __spawni (pid_t *pid, const char *file,
-         const posix_spawn_file_actions_t *file_actions,
-         const posix_spawnattr_t *attrp, char *const argv[],
-         char *const envp[], int use_path)
+          const posix_spawn_file_actions_t *file_actions,
+          const posix_spawnattr_t *attrp, char *const argv[],
+          char *const envp[], int use_path)
 {
   pid_t new_pid;
   char *path, *p, *name;
@@ -133,17 +149,21 @@ __spawni (pid_t *pid, const char *file,
   /* Do this once.  */
   short int flags = attrp == NULL ? 0 : attrp->_flags;
 
+  /* Avoid gcc warning
+       "variable 'flags' might be clobbered by 'longjmp' or 'vfork'"  */
+  (void) &flags;
+
   /* Generate the new process.  */
 #if HAVE_VFORK
   if ((flags & POSIX_SPAWN_USEVFORK) != 0
       /* If no major work is done, allow using vfork.  Note that we
-        might perform the path searching.  But this would be done by
-        a call to execvp(), too, and such a call must be OK according
-        to POSIX.  */
+         might perform the path searching.  But this would be done by
+         a call to execvp(), too, and such a call must be OK according
+         to POSIX.  */
       || ((flags & (POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF
-                   | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER
-                   | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0
-         && file_actions == NULL))
+                    | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER
+                    | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0
+          && file_actions == NULL))
     new_pid = vfork ();
   else
 #endif
@@ -152,11 +172,11 @@ __spawni (pid_t *pid, const char *file,
   if (new_pid != 0)
     {
       if (new_pid < 0)
-       return errno;
+        return errno;
 
       /* The call was successful.  Store the PID if necessary.  */
       if (pid != NULL)
-       *pid = new_pid;
+        *pid = new_pid;
 
       return 0;
     }
@@ -170,9 +190,9 @@ __spawni (pid_t *pid, const char *file,
   if ((flags & POSIX_SPAWN_SETSIGDEF) != 0)
     {
       /* We have to iterate over all signals.  This could possibly be
-        done better but it requires system specific solutions since
-        the sigset_t data type can be very different on different
-        architectures.  */
+         done better but it requires system specific solutions since
+         the sigset_t data type can be very different on different
+         architectures.  */
       int sig;
       struct sigaction sa;
 
@@ -180,9 +200,9 @@ __spawni (pid_t *pid, const char *file,
       sa.sa_handler = SIG_DFL;
 
       for (sig = 1; sig <= NSIG; ++sig)
-       if (sigismember (&attrp->_sd, sig) != 0
-           && sigaction (sig, &sa, NULL) != 0)
-         _exit (SPAWN_ERROR);
+        if (sigismember (&attrp->_sd, sig) != 0
+            && sigaction (sig, &sa, NULL) != 0)
+          _exit (SPAWN_ERROR);
 
     }
 
@@ -192,14 +212,14 @@ __spawni (pid_t *pid, const char *file,
       == POSIX_SPAWN_SETSCHEDPARAM)
     {
       if (sched_setparam (0, &attrp->_sp) == -1)
-       _exit (SPAWN_ERROR);
+        _exit (SPAWN_ERROR);
     }
   else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0)
     {
       if (sched_setscheduler (0, attrp->_policy,
-                             (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0
-                             ? &attrp->_sp : NULL) == -1)
-       _exit (SPAWN_ERROR);
+                              (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0
+                              ? &attrp->_sp : NULL) == -1)
+        _exit (SPAWN_ERROR);
     }
 #endif
 
@@ -211,7 +231,7 @@ __spawni (pid_t *pid, const char *file,
   /* Set the effective user and group IDs.  */
   if ((flags & POSIX_SPAWN_RESETIDS) != 0
       && (local_seteuid (getuid ()) != 0
-         || local_setegid (getgid ()) != 0))
+          || local_setegid (getgid ()) != 0))
     _exit (SPAWN_ERROR);
 
   /* Execute the file actions.  */
@@ -220,52 +240,52 @@ __spawni (pid_t *pid, const char *file,
       int cnt;
 
       for (cnt = 0; cnt < file_actions->_used; ++cnt)
-       {
-         struct __spawn_action *action = &file_actions->_actions[cnt];
-
-         switch (action->tag)
-           {
-           case spawn_do_close:
-             if (close_not_cancel (action->action.close_action.fd) != 0)
-               /* Signal the error.  */
-               _exit (SPAWN_ERROR);
-             break;
-
-           case spawn_do_open:
-             {
-               int new_fd = open_not_cancel (action->action.open_action.path,
-                                             action->action.open_action.oflag
-                                             | O_LARGEFILE,
-                                             action->action.open_action.mode);
-
-               if (new_fd == -1)
-                 /* The `open' call failed.  */
-                 _exit (SPAWN_ERROR);
-
-               /* Make sure the desired file descriptor is used.  */
-               if (new_fd != action->action.open_action.fd)
-                 {
-                   if (dup2 (new_fd, action->action.open_action.fd)
-                       != action->action.open_action.fd)
-                     /* The `dup2' call failed.  */
-                     _exit (SPAWN_ERROR);
-
-                   if (close_not_cancel (new_fd) != 0)
-                     /* The `close' call failed.  */
-                     _exit (SPAWN_ERROR);
-                 }
-             }
-             break;
-
-           case spawn_do_dup2:
-             if (dup2 (action->action.dup2_action.fd,
-                       action->action.dup2_action.newfd)
-                 != action->action.dup2_action.newfd)
-               /* The `dup2' call failed.  */
-               _exit (SPAWN_ERROR);
-             break;
-           }
-       }
+        {
+          struct __spawn_action *action = &file_actions->_actions[cnt];
+
+          switch (action->tag)
+            {
+            case spawn_do_close:
+              if (close_not_cancel (action->action.close_action.fd) != 0)
+                /* Signal the error.  */
+                _exit (SPAWN_ERROR);
+              break;
+
+            case spawn_do_open:
+              {
+                int new_fd = open_not_cancel (action->action.open_action.path,
+                                              action->action.open_action.oflag
+                                              | O_LARGEFILE,
+                                              action->action.open_action.mode);
+
+                if (new_fd == -1)
+                  /* The 'open' call failed.  */
+                  _exit (SPAWN_ERROR);
+
+                /* Make sure the desired file descriptor is used.  */
+                if (new_fd != action->action.open_action.fd)
+                  {
+                    if (dup2 (new_fd, action->action.open_action.fd)
+                        != action->action.open_action.fd)
+                      /* The 'dup2' call failed.  */
+                      _exit (SPAWN_ERROR);
+
+                    if (close_not_cancel (new_fd) != 0)
+                      /* The 'close' call failed.  */
+                      _exit (SPAWN_ERROR);
+                  }
+              }
+              break;
+
+            case spawn_do_dup2:
+              if (dup2 (action->action.dup2_action.fd,
+                        action->action.dup2_action.newfd)
+                  != action->action.dup2_action.newfd)
+                /* The 'dup2' call failed.  */
+                _exit (SPAWN_ERROR);
+              break;
+            }
+        }
     }
 
   if (! use_path || strchr (file, '/') != NULL)
@@ -274,9 +294,9 @@ __spawni (pid_t *pid, const char *file,
       execve (file, argv, envp);
 
       if (errno == ENOEXEC)
-       script_execute (file, argv, envp);
+        script_execute (file, argv, envp);
 
-      /* Oh, oh.  `execve' returns.  This is bad.  */
+      /* Oh, oh.  'execve' returns.  This is bad.  */
       _exit (SPAWN_ERROR);
     }
 
@@ -285,9 +305,9 @@ __spawni (pid_t *pid, const char *file,
   if (path == NULL)
     {
 #if HAVE_CONFSTR
-      /* There is no `PATH' in the environment.
-        The default search path is the current directory
-        followed by the path `confstr' returns for `_CS_PATH'.  */
+      /* There is no 'PATH' in the environment.
+         The default search path is the current directory
+         followed by the path 'confstr' returns for '_CS_PATH'.  */
       len = confstr (_CS_PATH, (char *) NULL, 0);
       path = (char *) alloca (1 + len);
       path[0] = ':';
@@ -315,38 +335,40 @@ __spawni (pid_t *pid, const char *file,
       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;
+        /* 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);
+        startp = (char *) memcpy (name - (p - path), path, p - path);
 
       /* Try to execute this name.  If it works, execv will not return.  */
       execve (startp, argv, envp);
 
       if (errno == ENOEXEC)
-       script_execute (startp, argv, envp);
+        script_execute (startp, argv, envp);
 
       switch (errno)
-       {
-       case EACCES:
-       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.  */
-         break;
-
-       default:
-         /* Some other error means we found an executable file, but
-            something went wrong executing it; return the error to our
-            caller.  */
-         _exit (SPAWN_ERROR);
-       }
+        {
+        case EACCES:
+        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.  */
+          break;
+
+        default:
+          /* Some other error means we found an executable file, but
+             something went wrong executing it; return the error to our
+             caller.  */
+          _exit (SPAWN_ERROR);
+        }
     }
   while (*p++ != '\0');
 
   /* Return with an error.  */
   _exit (SPAWN_ERROR);
 }
+
+#endif