2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #ifdef HAVE_SYS_MMAN_H
28 /* Some versions of glibc don't define this */
33 /* data structure used to pass an fd with sendmsg/recvmsg */
36 int len; /* sizeof structure */
37 int level; /* SOL_SOCKET */
38 int type; /* SCM_RIGHTS */
39 int fd; /* fd to pass */
42 /***********************************************************************
45 * Die on protocol errors or socket close
47 static void CLIENT_Die(void)
49 close( NtCurrentTeb()->socket );
53 /***********************************************************************
54 * server_protocol_error
56 void server_protocol_error( const char *err, ... )
60 va_start( args, err );
61 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
62 vfprintf( stderr, err, args );
68 /***********************************************************************
71 static void server_perror( const char *err )
73 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
79 /***********************************************************************
82 * Send a request to the server.
84 static void send_request( enum request req )
87 if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
91 if (errno == EPIPE) CLIENT_Die();
92 server_perror( "sendmsg" );
94 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
97 /***********************************************************************
100 * Send a request to the server, passing a file descriptor.
102 static void send_request_fd( enum request req, int fd )
105 #ifndef HAVE_MSGHDR_ACCRIGHTS
108 struct msghdr msghdr;
111 vec.iov_base = (void *)&req;
112 vec.iov_len = sizeof(req);
114 msghdr.msg_name = NULL;
115 msghdr.msg_namelen = 0;
116 msghdr.msg_iov = &vec;
117 msghdr.msg_iovlen = 1;
119 #ifdef HAVE_MSGHDR_ACCRIGHTS
120 msghdr.msg_accrights = (void *)&fd;
121 msghdr.msg_accrightslen = sizeof(fd);
122 #else /* HAVE_MSGHDR_ACCRIGHTS */
123 cmsg.len = sizeof(cmsg);
124 cmsg.level = SOL_SOCKET;
125 cmsg.type = SCM_RIGHTS;
127 msghdr.msg_control = &cmsg;
128 msghdr.msg_controllen = sizeof(cmsg);
129 msghdr.msg_flags = 0;
130 #endif /* HAVE_MSGHDR_ACCRIGHTS */
132 if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
135 if (errno == EPIPE) CLIENT_Die();
136 server_perror( "sendmsg" );
138 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
141 /***********************************************************************
144 * Wait for a reply from the server.
146 static unsigned int wait_reply(void)
153 if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
157 if (errno == EINTR) continue;
158 if (errno == EPIPE) CLIENT_Die();
159 server_perror("read");
161 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
162 server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
167 /***********************************************************************
170 * Wait for a reply from the server, when a file descriptor is passed.
172 static unsigned int wait_reply_fd( int *fd )
178 #ifdef HAVE_MSGHDR_ACCRIGHTS
179 struct msghdr msghdr;
182 msghdr.msg_accrights = (void *)fd;
183 msghdr.msg_accrightslen = sizeof(*fd);
184 #else /* HAVE_MSGHDR_ACCRIGHTS */
185 struct msghdr msghdr;
188 cmsg.len = sizeof(cmsg);
189 cmsg.level = SOL_SOCKET;
190 cmsg.type = SCM_RIGHTS;
192 msghdr.msg_control = &cmsg;
193 msghdr.msg_controllen = sizeof(cmsg);
194 msghdr.msg_flags = 0;
195 #endif /* HAVE_MSGHDR_ACCRIGHTS */
197 msghdr.msg_name = NULL;
198 msghdr.msg_namelen = 0;
199 msghdr.msg_iov = &vec;
200 msghdr.msg_iovlen = 1;
201 vec.iov_base = (void *)&res;
202 vec.iov_len = sizeof(res);
206 if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
208 #ifndef HAVE_MSGHDR_ACCRIGHTS
215 if (errno == EINTR) continue;
216 if (errno == EPIPE) CLIENT_Die();
217 server_perror("recvmsg");
219 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
220 server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
225 /***********************************************************************
228 * Perform a server call.
230 unsigned int server_call( enum request req )
236 if (res) SetLastError( res );
237 return res; /* error code */
241 /***********************************************************************
244 * Perform a server call, passing a file descriptor.
245 * If *fd is != -1, it will be passed to the server.
246 * If the server passes an fd, it will be stored into *fd.
248 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
252 if (fd_out == -1) send_request( req );
253 else send_request_fd( req, fd_out );
255 if (fd_in) res = wait_reply_fd( fd_in );
256 else res = wait_reply();
257 if (res) SetLastError( res );
258 return res; /* error code */
262 /***********************************************************************
265 * Start the server and create the initial socket pair.
267 int CLIENT_InitServer(void)
271 extern void create_initial_thread( int fd );
273 if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
275 perror("socketpair");
286 default: /* parent */
288 sprintf( buffer, "%d", fd[1] );
289 /*#define EXEC_SERVER*/
291 execlp( "wineserver", "wineserver", buffer, NULL );
292 execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
293 execl( "./server/wineserver", "wineserver", buffer, NULL );
295 create_initial_thread( fd[1] );
302 /***********************************************************************
305 * Send an init thread request. Return 0 if OK.
307 int CLIENT_InitThread(void)
309 struct init_thread_request *req;
310 TEB *teb = NtCurrentTeb();
313 if (wait_reply_fd( &fd ) || (fd == -1))
314 server_protocol_error( "no fd passed on first request\n" );
315 if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
316 teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
318 if (teb->buffer == (void*)-1) server_perror( "mmap" );
320 req = get_req_buffer();
321 req->unix_pid = getpid();
323 if (server_call( REQ_INIT_THREAD )) return -1;
324 teb->process->server_pid = req->pid;
330 /***********************************************************************
333 * Send a set debug level request. Return 0 if OK.
335 int CLIENT_SetDebug( int level )
337 struct set_debug_request *req = get_req_buffer();
339 return server_call( REQ_SET_DEBUG );
342 /***********************************************************************
343 * CLIENT_DebuggerRequest
345 * Send a debugger support request. Return 0 if OK.
347 int CLIENT_DebuggerRequest( int op )
349 struct debugger_request *req = get_req_buffer();
351 return server_call( REQ_DEBUGGER );