Added LGPL standard comment, and copyright notices where necessary.
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #ifdef HAVE_SYS_ERRNO_H
29 #include <sys/errno.h>
30 #endif
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <time.h>
34 #include <unistd.h>
35
36 #include "winbase.h"
37
38 #include "handle.h"
39 #include "thread.h"
40 #include "request.h"
41
42 enum side { READ_SIDE, WRITE_SIDE };
43
44 struct pipe
45 {
46     struct object       obj;         /* object header */
47     struct pipe        *other;       /* the pipe other end */
48     enum side           side;        /* which side of the pipe is this */
49 };
50
51 static void pipe_dump( struct object *obj, int verbose );
52 static int pipe_get_poll_events( struct object *obj );
53 static int pipe_get_fd( struct object *obj );
54 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
55 static void pipe_destroy( struct object *obj );
56
57 static const struct object_ops pipe_ops =
58 {
59     sizeof(struct pipe),          /* size */
60     pipe_dump,                    /* dump */
61     default_poll_add_queue,       /* add_queue */
62     default_poll_remove_queue,    /* remove_queue */
63     default_poll_signaled,        /* signaled */
64     no_satisfied,                 /* satisfied */
65     pipe_get_poll_events,         /* get_poll_events */
66     default_poll_event,           /* poll_event */
67     pipe_get_fd,                  /* get_fd */
68     no_flush,                     /* flush */
69     pipe_get_info,                /* get_file_info */
70     NULL,                         /* queue_async */
71     pipe_destroy                  /* destroy */
72 };
73
74
75 static struct pipe *create_pipe_side( int fd, int side )
76 {
77     struct pipe *pipe;
78
79     if ((pipe = alloc_object( &pipe_ops, fd )))
80     {
81         pipe->other  = NULL;
82         pipe->side   = side;
83     }
84     return pipe;
85 }
86
87 static int create_pipe( struct object *obj[2] )
88 {
89     struct pipe *read_pipe;
90     struct pipe *write_pipe;
91     int fd[2];
92
93     if (pipe( fd ) == -1)
94     {
95         file_set_error();
96         return 0;
97     }
98     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
99     {
100         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
101         {
102             write_pipe->other = read_pipe;
103             read_pipe->other  = write_pipe;
104             obj[0] = &read_pipe->obj;
105             obj[1] = &write_pipe->obj;
106             return 1;
107         }
108         release_object( read_pipe );
109     }
110     else close( fd[1] );
111     return 0;
112 }
113
114 static void pipe_dump( struct object *obj, int verbose )
115 {
116     struct pipe *pipe = (struct pipe *)obj;
117     assert( obj->ops == &pipe_ops );
118     fprintf( stderr, "Pipe %s-side fd=%d\n",
119              (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
120 }
121
122 static int pipe_get_poll_events( struct object *obj )
123 {
124     struct pipe *pipe = (struct pipe *)obj;
125     assert( obj->ops == &pipe_ops );
126     return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
127 }
128
129 static int pipe_get_fd( struct object *obj )
130 {
131     struct pipe *pipe = (struct pipe *)obj;
132     assert( obj->ops == &pipe_ops );
133
134     if (!pipe->other)
135     {
136         set_error( STATUS_PIPE_BROKEN );
137         return -1;
138     }
139     return pipe->obj.fd;
140 }
141
142 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
143 {
144     if (reply)
145     {
146         reply->type        = FILE_TYPE_PIPE;
147         reply->attr        = 0;
148         reply->access_time = 0;
149         reply->write_time  = 0;
150         reply->size_high   = 0;
151         reply->size_low    = 0;
152         reply->links       = 0;
153         reply->index_high  = 0;
154         reply->index_low   = 0;
155         reply->serial      = 0;
156     }
157     *flags = 0;
158     return FD_TYPE_DEFAULT;
159 }
160
161 static void pipe_destroy( struct object *obj )
162 {
163     struct pipe *pipe = (struct pipe *)obj;
164     assert( obj->ops == &pipe_ops );
165
166     if (pipe->other) pipe->other->other = NULL;
167 }
168
169 /* create an anonymous pipe */
170 DECL_HANDLER(create_pipe)
171 {
172     struct object *obj[2];
173     handle_t hread = 0, hwrite = 0;
174
175     if (create_pipe( obj ))
176     {
177         hread = alloc_handle( current->process, obj[0],
178                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
179                               req->inherit );
180         if (hread)
181         {
182             hwrite = alloc_handle( current->process, obj[1],
183                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
184                                    req->inherit );
185             if (!hwrite) close_handle( current->process, hread, NULL );
186         }
187         release_object( obj[0] );
188         release_object( obj[1] );
189     }
190     reply->handle_read  = hread;
191     reply->handle_write = hwrite;
192 }