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 #include "qemu.h"
36
37 static bool is_qemu;
38
39 static int
40 fd_safer (int fd)
41 {
42 if (0 <= fd && fd <= 2)
43 {
44 int f = fd_safer (dup (fd));
45 int e = errno;
46 close (fd);
47 errno = e;
48 fd = f;
49 }
50
51 return fd;
52 }
53
54 static void
55 test (const char *pwd_prog)
56 {
57 char *argv[2] = { (char *) "pwd", NULL };
58 int rootfd;
59 int ifd[2];
60 sigset_t blocked_signals;
61 sigset_t fatal_signal_set;
62 posix_spawn_file_actions_t actions;
63 bool actions_allocated;
64 posix_spawnattr_t attrs;
65 bool attrs_allocated;
66 int err;
67 pid_t child;
68 int fd;
69 FILE *fp;
70 char line[80];
71 int status;
72 int exitstatus;
73
74 rootfd = open ("/", O_RDONLY);
75 if (rootfd < 0)
76 {
77 perror ("cannot open directory");
78 exit (1);
79 }
80 if (pipe (ifd) < 0 || (ifd[0] = fd_safer (ifd[0])) < 0)
81 {
82 perror ("cannot create pipe");
83 exit (1);
84 }
85 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
86 sigemptyset (&fatal_signal_set);
87 sigaddset (&fatal_signal_set, SIGINT);
88 sigaddset (&fatal_signal_set, SIGTERM);
89 #ifdef SIGHUP
90 sigaddset (&fatal_signal_set, SIGHUP);
91 #endif
92 #ifdef SIGPIPE
93 sigaddset (&fatal_signal_set, SIGPIPE);
94 #endif
95 sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
96 actions_allocated = false;
97 attrs_allocated = false;
98 if ((err = posix_spawn_file_actions_init (&actions)) != 0
99 || (actions_allocated = true,
100 (err = posix_spawn_file_actions_adddup2 (&actions, ifd[1], STDOUT_FILENO)) != 0
101 || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
102 || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
103 || (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, "/dev/null", O_RDONLY, 0)) != 0
104 || (err = posix_spawn_file_actions_addfchdir (&actions, rootfd)) != 0
105 || (err = posix_spawnattr_init (&attrs)) != 0
106 || (attrs_allocated = true,
107 #if defined _WIN32 && !defined __CYGWIN__
108 0
109 #else
110 (err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
111 || (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0
112 #endif
113 )
114 || (err = posix_spawnp (&child, pwd_prog, &actions, &attrs, argv, environ)) != 0))
115 {
116 if (actions_allocated)
117 posix_spawn_file_actions_destroy (&actions);
118 if (attrs_allocated)
119 posix_spawnattr_destroy (&attrs);
120 sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
121 errno = err;
122 perror ("subprocess failed");
123 exit (1);
124 }
125 posix_spawn_file_actions_destroy (&actions);
126 posix_spawnattr_destroy (&attrs);
127 sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
128 close (ifd[1]);
129 fd = ifd[0];
130 fp = fdopen (fd, "r");
131 if (fp == NULL)
132 {
133 fprintf (stderr, "fdopen() failed\n");
134 exit (1);
135 }
136 if (fread (line, 1, 80, fp) < 2)
137 {
138 fprintf (stderr, "could not read expected output\n");
139 exit (1);
140 }
141
142
143
144
145 if (!is_qemu)
146 {
147 if (memcmp (line, "/\n", 2) != 0)
148 {
149 fprintf (stderr, "read output is not the expected output\n");
150 exit (1);
151 }
152 }
153 fclose (fp);
154 status = 0;
155 while (waitpid (child, &status, 0) != child)
156 ;
157 if (!WIFEXITED (status))
158 {
159 fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
160 exit (1);
161 }
162 exitstatus = WEXITSTATUS (status);
163 if (exitstatus != 0)
164 {
165 fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
166 exit (1);
167 }
168 }
169
170 int
171 main ()
172 {
173 is_qemu = is_running_under_qemu_user ();
174
175 test ("pwd");
176
177
178
179
180 if (!is_qemu)
181 {
182 const char *abs_pwd_prog = find_in_path ("pwd");
183
184 if (abs_pwd_prog != NULL
185 && abs_pwd_prog[0] == '/'
186 && abs_pwd_prog[1] != '0' && abs_pwd_prog[1] != '/')
187 test (&abs_pwd_prog[1]);
188 }
189
190 return 0;
191 }