Set close-on-exec flag on server socket.
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #ifdef HAVE_SYS_ERRNO_H
15 #include <sys/errno.h>
16 #endif
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <time.h>
21 #include <unistd.h>
22
23 #include "winerror.h"
24 #include "winbase.h"
25
26 #include "handle.h"
27 #include "thread.h"
28 #include "request.h"
29
30 enum side { READ_SIDE, WRITE_SIDE };
31
32 struct pipe
33 {
34     struct object       obj;         /* object header */
35     struct pipe        *other;       /* the pipe other end */
36     struct select_user  select;      /* select user */
37     enum side           side;        /* which side of the pipe is this */
38 };
39
40 static void pipe_dump( struct object *obj, int verbose );
41 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
42 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
43 static int pipe_signaled( struct object *obj, struct thread *thread );
44 static int pipe_get_read_fd( struct object *obj );
45 static int pipe_get_write_fd( struct object *obj );
46 static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
47 static void pipe_destroy( struct object *obj );
48
49 static const struct object_ops pipe_ops =
50 {
51     sizeof(struct pipe),
52     pipe_dump,
53     pipe_add_queue,
54     pipe_remove_queue,
55     pipe_signaled,
56     no_satisfied,
57     pipe_get_read_fd,
58     pipe_get_write_fd,
59     no_flush,
60     pipe_get_info,
61     pipe_destroy
62 };
63
64
65 static struct pipe *create_pipe_side( int fd, int side )
66 {
67     struct pipe *pipe;
68
69     if ((pipe = alloc_object( &pipe_ops )))
70     {
71         pipe->select.fd      = fd;
72         pipe->select.func    = default_select_event;
73         pipe->select.private = pipe;
74         pipe->other          = NULL;
75         pipe->side           = side;
76         register_select_user( &pipe->select );
77     }
78     return pipe;
79 }
80
81 static int create_pipe( struct object *obj[2] )
82 {
83     struct pipe *read_pipe;
84     struct pipe *write_pipe;
85     int fd[2];
86
87     if (pipe( fd ) == -1)
88     {
89         file_set_error();
90         return 0;
91     }
92     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
93     {
94         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
95         {
96             write_pipe->other = read_pipe;
97             read_pipe->other  = write_pipe;
98             obj[0] = &read_pipe->obj;
99             obj[1] = &write_pipe->obj;
100             return 1;
101         }
102         release_object( read_pipe );
103     }
104     close( fd[0] );
105     close( fd[1] );
106     return 0;
107 }
108
109 static void pipe_dump( struct object *obj, int verbose )
110 {
111     struct pipe *pipe = (struct pipe *)obj;
112     assert( obj->ops == &pipe_ops );
113     fprintf( stderr, "Pipe %s-side fd=%d\n",
114              (pipe->side == READ_SIDE) ? "read" : "write", pipe->select.fd );
115 }
116
117 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
118 {
119     struct pipe *pipe = (struct pipe *)obj;
120     assert( obj->ops == &pipe_ops );
121     if (!obj->head)  /* first on the queue */
122         set_select_events( &pipe->select,
123                            (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT );
124     add_queue( obj, entry );
125     return 1;
126 }
127
128 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
129 {
130     struct pipe *pipe = (struct pipe *)grab_object(obj);
131     assert( obj->ops == &pipe_ops );
132
133     remove_queue( obj, entry );
134     if (!obj->head)  /* last on the queue is gone */
135         set_select_events( &pipe->select, 0 );
136     release_object( obj );
137 }
138
139 static int pipe_signaled( struct object *obj, struct thread *thread )
140 {
141     int event;
142     struct pipe *pipe = (struct pipe *)obj;
143     assert( obj->ops == &pipe_ops );
144
145     event = (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT;
146     if (check_select_events( &pipe->select, event ))
147     {
148         /* stop waiting on select() if we are signaled */
149         set_select_events( &pipe->select, 0 );
150         return 1;
151     }
152     else
153     {
154         /* restart waiting on select() if we are no longer signaled */
155         if (obj->head) set_select_events( &pipe->select, event );
156         return 0;
157     }
158 }
159
160 static int pipe_get_read_fd( struct object *obj )
161 {
162     struct pipe *pipe = (struct pipe *)obj;
163     assert( obj->ops == &pipe_ops );
164
165     if (!pipe->other)
166     {
167         set_error( ERROR_BROKEN_PIPE );
168         return -1;
169     }
170     if (pipe->side != READ_SIDE)  /* FIXME: should not be necessary */
171     {
172         set_error( ERROR_ACCESS_DENIED );
173         return -1;
174     }
175     return dup( pipe->select.fd );
176 }
177
178 static int pipe_get_write_fd( struct object *obj )
179 {
180     struct pipe *pipe = (struct pipe *)obj;
181     assert( obj->ops == &pipe_ops );
182
183     if (!pipe->other)
184     {
185         set_error( ERROR_BROKEN_PIPE );
186         return -1;
187     }
188     if (pipe->side != WRITE_SIDE)  /* FIXME: should not be necessary */
189     {
190         set_error( ERROR_ACCESS_DENIED );
191         return -1;
192     }
193     return dup( pipe->select.fd );
194 }
195
196 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
197 {
198     req->type        = FILE_TYPE_PIPE;
199     req->attr        = 0;
200     req->access_time = 0;
201     req->write_time  = 0;
202     req->size_high   = 0;
203     req->size_low    = 0;
204     req->links       = 0;
205     req->index_high  = 0;
206     req->index_low   = 0;
207     req->serial      = 0;
208     return 1;
209 }
210
211 static void pipe_destroy( struct object *obj )
212 {
213     struct pipe *pipe = (struct pipe *)obj;
214     assert( obj->ops == &pipe_ops );
215
216     if (pipe->other) pipe->other->other = NULL;
217     unregister_select_user( &pipe->select );
218     close( pipe->select.fd );
219 }
220
221 /* create an anonymous pipe */
222 DECL_HANDLER(create_pipe)
223 {
224     struct object *obj[2];
225     int hread = -1, hwrite = -1;
226
227     if (create_pipe( obj ))
228     {
229         hread = alloc_handle( current->process, obj[0],
230                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
231                               req->inherit );
232         if (hread != -1)
233         {
234             hwrite = alloc_handle( current->process, obj[1],
235                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
236                                    req->inherit );
237             if (hwrite == -1)
238                 close_handle( current->process, hread );
239         }
240         release_object( obj[0] );
241         release_object( obj[1] );
242     }
243     req->handle_read  = hread;
244     req->handle_write = hwrite;
245 }