Improved GetRandomRegion().
[wine.git] / scheduler / client.c
blobbc62f539de19ef837bacb957879ebea6c8130eae
1 /*
2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/mman.h>
15 #include <sys/uio.h>
16 #include <unistd.h>
17 #include <stdarg.h>
19 #include "process.h"
20 #include "thread.h"
21 #include "server.h"
22 #include "winerror.h"
24 /* Some versions of glibc don't define this */
25 #ifndef SCM_RIGHTS
26 #define SCM_RIGHTS 1
27 #endif
29 /* data structure used to pass an fd with sendmsg/recvmsg */
30 struct cmsg_fd
32 int len; /* sizeof structure */
33 int level; /* SOL_SOCKET */
34 int type; /* SCM_RIGHTS */
35 int fd; /* fd to pass */
38 /***********************************************************************
39 * CLIENT_Die
41 * Die on protocol errors or socket close
43 static void CLIENT_Die(void)
45 close( NtCurrentTeb()->socket );
46 SYSDEPS_ExitThread();
49 /***********************************************************************
50 * server_protocol_error
52 void server_protocol_error( const char *err, ... )
54 va_list args;
56 va_start( args, err );
57 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
58 vfprintf( stderr, err, args );
59 va_end( args );
60 CLIENT_Die();
64 /***********************************************************************
65 * server_perror
67 static void server_perror( const char *err )
69 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
70 perror( err );
71 CLIENT_Die();
75 /***********************************************************************
76 * send_request
78 * Send a request to the server.
80 static void send_request( enum request req )
82 int ret;
83 if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
84 return;
85 if (ret == -1)
87 if (errno == EPIPE) CLIENT_Die();
88 server_perror( "sendmsg" );
90 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
93 /***********************************************************************
94 * send_request_fd
96 * Send a request to the server, passing a file descriptor.
98 static void send_request_fd( enum request req, int fd )
100 int ret;
101 #ifndef HAVE_MSGHDR_ACCRIGHTS
102 struct cmsg_fd cmsg;
103 #endif
104 struct msghdr msghdr;
105 struct iovec vec;
107 vec.iov_base = &req;
108 vec.iov_len = sizeof(req);
110 msghdr.msg_name = NULL;
111 msghdr.msg_namelen = 0;
112 msghdr.msg_iov = &vec;
113 msghdr.msg_iovlen = 1;
115 #ifdef HAVE_MSGHDR_ACCRIGHTS
116 msghdr.msg_accrights = (void *)&fd;
117 msghdr.msg_accrightslen = sizeof(fd);
118 #else /* HAVE_MSGHDR_ACCRIGHTS */
119 cmsg.len = sizeof(cmsg);
120 cmsg.level = SOL_SOCKET;
121 cmsg.type = SCM_RIGHTS;
122 cmsg.fd = fd;
123 msghdr.msg_control = &cmsg;
124 msghdr.msg_controllen = sizeof(cmsg);
125 msghdr.msg_flags = 0;
126 #endif /* HAVE_MSGHDR_ACCRIGHTS */
128 if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
129 if (ret == -1)
131 if (errno == EPIPE) CLIENT_Die();
132 server_perror( "sendmsg" );
134 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
137 /***********************************************************************
138 * wait_reply
140 * Wait for a reply from the server.
142 static unsigned int wait_reply(void)
144 int ret;
145 unsigned int res;
147 for (;;)
149 if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
150 return res;
151 if (ret == -1)
153 if (errno == EINTR) continue;
154 if (errno == EPIPE) CLIENT_Die();
155 server_perror("read");
157 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
158 server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
163 /***********************************************************************
164 * wait_reply_fd
166 * Wait for a reply from the server, when a file descriptor is passed.
168 static unsigned int wait_reply_fd( int *fd )
170 struct iovec vec;
171 int ret;
172 unsigned int res;
174 #ifdef HAVE_MSGHDR_ACCRIGHTS
175 struct msghdr msghdr;
177 *fd = -1;
178 msghdr.msg_accrights = (void *)fd;
179 msghdr.msg_accrightslen = sizeof(*fd);
180 #else /* HAVE_MSGHDR_ACCRIGHTS */
181 struct msghdr msghdr;
182 struct cmsg_fd cmsg;
184 cmsg.len = sizeof(cmsg);
185 cmsg.level = SOL_SOCKET;
186 cmsg.type = SCM_RIGHTS;
187 cmsg.fd = -1;
188 msghdr.msg_control = &cmsg;
189 msghdr.msg_controllen = sizeof(cmsg);
190 msghdr.msg_flags = 0;
191 #endif /* HAVE_MSGHDR_ACCRIGHTS */
193 msghdr.msg_name = NULL;
194 msghdr.msg_namelen = 0;
195 msghdr.msg_iov = &vec;
196 msghdr.msg_iovlen = 1;
197 vec.iov_base = &res;
198 vec.iov_len = sizeof(res);
200 for (;;)
202 if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
204 #ifndef HAVE_MSGHDR_ACCRIGHTS
205 *fd = cmsg.fd;
206 #endif
207 return res;
209 if (ret == -1)
211 if (errno == EINTR) continue;
212 if (errno == EPIPE) CLIENT_Die();
213 server_perror("recvmsg");
215 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
216 server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
221 /***********************************************************************
222 * server_call
224 * Perform a server call.
226 unsigned int server_call( enum request req )
228 unsigned int res;
230 send_request( req );
231 res = wait_reply();
232 if (res) SetLastError( res );
233 return res; /* error code */
237 /***********************************************************************
238 * server_call_fd
240 * Perform a server call, passing a file descriptor.
241 * If *fd is != -1, it will be passed to the server.
242 * If the server passes an fd, it will be stored into *fd.
244 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
246 unsigned int res;
248 if (fd_out == -1) send_request( req );
249 else send_request_fd( req, fd_out );
251 if (fd_in) res = wait_reply_fd( fd_in );
252 else res = wait_reply();
253 if (res) SetLastError( res );
254 return res; /* error code */
258 /***********************************************************************
259 * CLIENT_InitServer
261 * Start the server and create the initial socket pair.
263 int CLIENT_InitServer(void)
265 int fd[2];
266 char buffer[16];
267 extern void create_initial_thread( int fd );
269 if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
271 perror("socketpair");
272 exit(1);
274 switch(fork())
276 case -1: /* error */
277 perror("fork");
278 exit(1);
279 case 0: /* child */
280 close( fd[1] );
281 break;
282 default: /* parent */
283 close( fd[0] );
284 sprintf( buffer, "%d", fd[1] );
285 /*#define EXEC_SERVER*/
286 #ifdef EXEC_SERVER
287 execlp( "wineserver", "wineserver", buffer, NULL );
288 execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
289 execl( "./server/wineserver", "wineserver", buffer, NULL );
290 #endif
291 create_initial_thread( fd[1] );
292 exit(0);
294 return fd[0];
298 /***********************************************************************
299 * CLIENT_InitThread
301 * Send an init thread request. Return 0 if OK.
303 int CLIENT_InitThread(void)
305 struct init_thread_request *req;
306 TEB *teb = NtCurrentTeb();
307 int fd;
309 if (wait_reply_fd( &fd ) || (fd == -1))
310 server_protocol_error( "no fd passed on first request\n" );
311 if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
312 teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
313 close( fd );
314 if (teb->buffer == (void*)-1) server_perror( "mmap" );
316 req = get_req_buffer();
317 req->unix_pid = getpid();
318 req->teb = teb;
319 if (server_call( REQ_INIT_THREAD )) return -1;
320 teb->process->server_pid = req->pid;
321 teb->tid = req->tid;
322 return 0;
326 /***********************************************************************
327 * CLIENT_SetDebug
329 * Send a set debug level request. Return 0 if OK.
331 int CLIENT_SetDebug( int level )
333 struct set_debug_request *req = get_req_buffer();
334 req->level = level;
335 return server_call( REQ_SET_DEBUG );
338 /***********************************************************************
339 * CLIENT_DebuggerRequest
341 * Send a debugger support request. Return 0 if OK.
343 int CLIENT_DebuggerRequest( int op )
345 struct debugger_request *req = get_req_buffer();
346 req->op = op;
347 return server_call( REQ_DEBUGGER );