6389e154ee8c0dee743b091e6bf27251f94b38de
[gnulib.git] / tests / test-passfd.c
1 /* Test of passing file descriptors.
2    Copyright (C) 2011-2013 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 #include "passfd.h"
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/wait.h>
31
32 #include "macros.h"
33
34 int
35 main ()
36 {
37 #if HAVE_SOCKETPAIR
38   int pair[2];
39   int ret;
40   pid_t pid;
41   int status;
42   int fdnull;
43   int fd;
44   struct stat st;
45
46 # if HAVE_DECL_ALARM
47   /* Avoid hanging on failure.  */
48   int alarm_value = 5;
49   signal (SIGALRM, SIG_DFL);
50   alarm (alarm_value);
51 # endif
52
53   fdnull = open ("/dev/null", O_RDWR);
54   if (fdnull < 0)
55     {
56       perror ("Could not open /dev/null");
57       return 1;
58     }
59
60   ret = socketpair (AF_UNIX, SOCK_STREAM, 0, pair);
61   if (ret < 0)
62     {
63       perror ("socket pair failed");
64       return 2;
65     }
66
67   pid = fork ();
68   if (pid == -1)
69     {
70       perror ("fork");
71       return 3;
72     }
73   if (pid == 0)
74     {
75       ret = sendfd (pair[1], fdnull);
76       if (ret == -1)
77         {
78           perror ("sendfd");
79           return 64;
80         }
81       return 0;
82     }
83   /* father */
84   else
85     {
86       fd = recvfd (pair[0], 0);
87       if (fd == -1)
88         {
89           perror ("recvfd");
90           return 16;
91         }
92       ret = waitpid (pid, &status, 0);
93       if (ret == -1)
94         {
95           perror ("waitpid");
96           return 17;
97         }
98       ASSERT (ret == pid);
99
100       if (!WIFEXITED (status))
101         {
102           fprintf (stderr, "Child does not normally exit\n");
103           return 65;
104         }
105       ret = WEXITSTATUS (status);
106       if (ret != 0)
107         {
108           fprintf (stderr, "Send fd fail\n");
109           return ret;
110         }
111
112       /* try to stat new fd */
113       ret = fstat (fd, &st);
114       if (ret < 0)
115         {
116           perror ("fstat");
117           return 80;
118         }
119       return 0;
120     }
121 #else
122   errno = 0;
123   ASSERT(sendfd (0, 0) == -1);
124   ASSERT(errno == ENOSYS);
125
126   errno = 0;
127   ASSERT(recvfd (0, 0) == -1);
128   ASSERT(errno == ENOSYS);
129
130   fputs ("skipping test: socketpair not supported on this system\n",
131          stderr);
132   return 77;
133 #endif
134 }