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