This source file includes following definitions.
- fd_safer
 
- test
 
- main
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 #include <config.h>
  20 
  21 #include <spawn.h>
  22 
  23 #include <errno.h>
  24 #include <fcntl.h>
  25 #include <signal.h>
  26 #include <stdbool.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include <string.h>
  30 #include <unistd.h>
  31 #include <sys/types.h>
  32 #include <sys/wait.h>
  33 
  34 #include "findprog.h"
  35 
  36 static int
  37 fd_safer (int fd)
     
  38 {
  39   if (0 <= fd && fd <= 2)
  40     {
  41       int f = fd_safer (dup (fd));
  42       int e = errno;
  43       close (fd);
  44       errno = e;
  45       fd = f;
  46     }
  47 
  48   return fd;
  49 }
  50 
  51 static void
  52 test (const char *pwd_prog)
     
  53 {
  54   char *argv[2] = { (char *) "pwd", NULL };
  55   int ifd[2];
  56   sigset_t blocked_signals;
  57   sigset_t fatal_signal_set;
  58   posix_spawn_file_actions_t actions;
  59   bool actions_allocated;
  60   posix_spawnattr_t attrs;
  61   bool attrs_allocated;
  62   int err;
  63   pid_t child;
  64   int fd;
  65   FILE *fp;
  66   char line[80];
  67   int line_len;
  68   int status;
  69   int exitstatus;
  70 
  71   if (pipe (ifd) < 0 || (ifd[0] = fd_safer (ifd[0])) < 0)
  72     {
  73       perror ("cannot create pipe");
  74       exit (1);
  75     }
  76   sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
  77   sigemptyset (&fatal_signal_set);
  78   sigaddset (&fatal_signal_set, SIGINT);
  79   sigaddset (&fatal_signal_set, SIGTERM);
  80   #ifdef SIGHUP
  81   sigaddset (&fatal_signal_set, SIGHUP);
  82   #endif
  83   #ifdef SIGPIPE
  84   sigaddset (&fatal_signal_set, SIGPIPE);
  85   #endif
  86   sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
  87   actions_allocated = false;
  88   attrs_allocated = false;
  89   if ((err = posix_spawn_file_actions_init (&actions)) != 0
  90       || (actions_allocated = true,
  91           (err = posix_spawn_file_actions_adddup2 (&actions, ifd[1], STDOUT_FILENO)) != 0
  92           || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
  93           || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
  94           || (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, "/dev/null", O_RDONLY, 0)) != 0
  95           || (err = posix_spawn_file_actions_addchdir (&actions, "/")) != 0
  96           || (err = posix_spawnattr_init (&attrs)) != 0
  97           || (attrs_allocated = true,
  98               #if defined _WIN32 && !defined __CYGWIN__
  99               0
 100               #else
 101               (err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
 102               || (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0
 103               #endif
 104              )
 105           || (err = posix_spawnp (&child, pwd_prog, &actions, &attrs, argv, environ)) != 0))
 106     {
 107       if (actions_allocated)
 108         posix_spawn_file_actions_destroy (&actions);
 109       if (attrs_allocated)
 110         posix_spawnattr_destroy (&attrs);
 111       sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 112       errno = err;
 113       perror ("subprocess failed");
 114       exit (1);
 115     }
 116   posix_spawn_file_actions_destroy (&actions);
 117   posix_spawnattr_destroy (&attrs);
 118   sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 119   close (ifd[1]);
 120   fd = ifd[0];
 121   fp = fdopen (fd, "rb");
 122   if (fp == NULL)
 123     {
 124       fprintf (stderr, "fdopen() failed\n");
 125       exit (1);
 126     }
 127   line_len = fread (line, 1, 80, fp);
 128   if (line_len < 2)
 129     {
 130       fprintf (stderr, "could not read expected output\n");
 131       exit (1);
 132     }
 133   if (!(line_len == 2 && memcmp (line, "/\n", 2) == 0))
 134 #if defined _WIN32 && !defined __CYGWIN__
 135     
 136 
 137     if (!(line_len > 11
 138           && memcmp (line, "/cygdrive/", 10) == 0
 139           && line[10] >= 'a' && line[10] <= 'z'
 140           && ((line_len == 12 && line[11] == '\n')
 141               || (line_len == 13 && line[11] == '\r' && line[12] == '\n'))))
 142 #endif
 143       {
 144         fprintf (stderr, "read output is not the expected output\n");
 145         exit (1);
 146       }
 147   fclose (fp);
 148   status = 0;
 149   while (waitpid (child, &status, 0) != child)
 150     ;
 151   if (!WIFEXITED (status))
 152     {
 153       fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
 154       exit (1);
 155     }
 156   exitstatus = WEXITSTATUS (status);
 157   if (exitstatus != 0)
 158     {
 159       fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
 160       exit (1);
 161     }
 162 }
 163 
 164 int
 165 main ()
     
 166 {
 167   test ("pwd");
 168 
 169   
 170 
 171 
 172   {
 173     const char *abs_pwd_prog = find_in_path ("pwd");
 174 
 175     if (abs_pwd_prog != NULL
 176         && abs_pwd_prog[0] == '/'
 177         && abs_pwd_prog[1] != '0' && abs_pwd_prog[1] != '/')
 178       test (&abs_pwd_prog[1]);
 179   }
 180 
 181   return 0;
 182 }