OSDN Git Service

2002-03-01 David O'Brien <obrien@FreeBSD.org>
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / cygserver_transport_pipes.cc
1 /* cygserver_transport_pipes.cc
2
3    Copyright 2001 Red Hat Inc.
4
5    Written by Robert Collins <rbtcollins@hotmail.com>
6
7    This file is part of Cygwin.
8
9    This software is a copyrighted work licensed under the terms of the
10    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
11    details. */
12
13 #include <errno.h>
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <windows.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netdb.h>
20 #include "wincap.h"
21 #include "cygwin/cygserver_transport.h"
22 #include "cygwin/cygserver_transport_pipes.h"
23
24 /* to allow this to link into cygwin and the .dll, a little magic is needed. */
25 #ifndef __OUTSIDE_CYGWIN__
26 #include "winsup.h"
27 #else
28 #define DEBUG 0
29 #define debug_printf if (DEBUG) printf
30 #endif
31
32 transport_layer_pipes::transport_layer_pipes (HANDLE new_pipe)
33 {
34   pipe = new_pipe;
35   if (inited != true)
36     init_security();
37 };
38
39 transport_layer_pipes::transport_layer_pipes () 
40 {
41   pipe = NULL;
42   strcpy(pipe_name, "\\\\.\\pipe\\cygwin_lpc");
43   if (inited != true)
44     init_security();
45 }
46
47
48 void
49 transport_layer_pipes::init_security()
50 {
51   /* FIXME: pthread_once or equivalent needed */
52   InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
53   SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);
54
55   sec_none_nih.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
56   sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
57   sec_none_nih.lpSecurityDescriptor = NULL;
58   sec_all_nih.lpSecurityDescriptor = &sd;
59   inited = true;
60 }
61
62 void
63 transport_layer_pipes::listen ()
64 {
65   /* no-op */
66 }
67
68 class transport_layer_pipes *
69 transport_layer_pipes::accept ()
70 {
71   if (pipe)
72     {
73       debug_printf ("Already have a pipe in this %p\n",this);
74       return NULL;
75     }
76
77   pipe = CreateNamedPipe (pipe_name,
78                           PIPE_ACCESS_DUPLEX,
79                           PIPE_TYPE_BYTE | PIPE_WAIT,
80                           PIPE_UNLIMITED_INSTANCES,
81                           0, 0, 1000,
82                           &sec_all_nih );
83   if (pipe == INVALID_HANDLE_VALUE)
84     {
85       debug_printf ("error creating pipe (%lu)\n.", GetLastError ());
86       return NULL;
87     }
88
89   if ( !ConnectNamedPipe ( pipe, NULL ) &&
90      GetLastError () != ERROR_PIPE_CONNECTED)
91     {
92       printf ("error connecting to pipe (%lu)\n.", GetLastError ());
93       CloseHandle (pipe);
94       pipe = NULL;
95       return NULL;
96     }
97   
98   transport_layer_pipes *new_conn = new transport_layer_pipes (pipe);
99   pipe = NULL;
100
101   return new_conn;  
102 }
103
104 void
105 transport_layer_pipes::close()
106 {
107   debug_printf ("closing pipe %p\n", pipe);
108   if (pipe && pipe != INVALID_HANDLE_VALUE)
109     {
110       FlushFileBuffers (pipe);
111       DisconnectNamedPipe (pipe);
112       CloseHandle (pipe);
113     }
114 }
115
116 ssize_t
117 transport_layer_pipes::read (char *buf, size_t len)
118 {
119   debug_printf ("reading from pipe %p\n", pipe);
120   if (!pipe || pipe == INVALID_HANDLE_VALUE)
121     return -1;
122
123   DWORD bytes_read;
124   DWORD rc = ReadFile (pipe, buf, len, &bytes_read, NULL);
125   if (!rc)
126     {
127       debug_printf ("error reading from pipe (%lu)\n", GetLastError ());
128       return -1;
129     }
130   return bytes_read;
131 }
132
133 ssize_t
134 transport_layer_pipes::write (char *buf, size_t len)
135 {
136   debug_printf ("writing to pipe %p\n", pipe);
137   DWORD bytes_written, rc;
138   if (!pipe || pipe == INVALID_HANDLE_VALUE)
139     return -1;
140
141   rc = WriteFile (pipe, buf, len, &bytes_written, NULL);
142   if (!rc)
143     {
144       debug_printf ("error writing to pipe (%lu)\n", GetLastError ());
145       return -1;
146     }
147   return bytes_written;
148 }
149
150 bool
151 transport_layer_pipes::connect ()
152 {
153   if (pipe && pipe != INVALID_HANDLE_VALUE)
154     {
155       debug_printf ("Already have a pipe in this %p\n",this);
156       return false;
157     }
158
159   while (1)
160     {
161       pipe = CreateFile (pipe_name,
162                          GENERIC_READ | GENERIC_WRITE,
163                          FILE_SHARE_READ | FILE_SHARE_WRITE,
164                          &sec_all_nih,
165                          OPEN_EXISTING,
166                          0, NULL);
167
168       if (pipe != INVALID_HANDLE_VALUE)
169         /* got the pipe */
170         return true;
171
172       if (GetLastError () != ERROR_PIPE_BUSY)
173         {
174           debug_printf ("Error opening the pipe (%lu)\n", GetLastError ());
175           pipe = NULL;
176           return false;
177         }
178       if (!WaitNamedPipe (pipe_name, 20000))
179         debug_printf ( "error connecting to server pipe after 20 seconds (%lu)\n", GetLastError () );
180       /* We loop here, because the pipe exists but is busy. If it doesn't exist
181        * the != ERROR_PIPE_BUSY will catch it.
182        */ 
183     }
184 }
185
186 void
187 transport_layer_pipes::impersonate_client ()
188 {
189   debug_printf ("impersonating pipe %p\n", pipe);
190   if (pipe && pipe != INVALID_HANDLE_VALUE)
191     {
192       BOOL rv = ImpersonateNamedPipeClient (pipe);
193       if (!rv)
194         debug_printf ("Failed to Impersonate the client, (%lu)\n", GetLastError ());
195     }
196   debug_printf("I am who you are\n");
197 }
198
199 void
200 transport_layer_pipes::revert_to_self ()
201 {
202   RevertToSelf (); 
203   debug_printf("I am who I yam\n");
204 }
205