2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
14 #include <sys/types.h>
15 #ifdef HAVE_SYS_SOCKET_H
16 # include <sys/socket.h>
18 #ifdef HAVE_SYS_MMAN_H
30 /* Some versions of glibc don't define this */
35 /* data structure used to pass an fd with sendmsg/recvmsg */
38 int len; /* sizeof structure */
39 int level; /* SOL_SOCKET */
40 int type; /* SCM_RIGHTS */
41 int fd; /* fd to pass */
44 /***********************************************************************
47 * Die on protocol errors or socket close
49 static void CLIENT_Die(void)
51 close( NtCurrentTeb()->socket );
55 /***********************************************************************
56 * server_protocol_error
58 void server_protocol_error( const char *err, ... )
62 va_start( args, err );
63 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
64 vfprintf( stderr, err, args );
70 /***********************************************************************
73 static void server_perror( const char *err )
75 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
81 /***********************************************************************
84 * Send a request to the server.
86 static void send_request( enum request req )
89 if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
93 if (errno == EPIPE) CLIENT_Die();
94 server_perror( "sendmsg" );
96 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
99 /***********************************************************************
102 * Send a request to the server, passing a file descriptor.
104 static void send_request_fd( enum request req, int fd )
107 #ifndef HAVE_MSGHDR_ACCRIGHTS
110 struct msghdr msghdr;
113 vec.iov_base = (void *)&req;
114 vec.iov_len = sizeof(req);
116 msghdr.msg_name = NULL;
117 msghdr.msg_namelen = 0;
118 msghdr.msg_iov = &vec;
119 msghdr.msg_iovlen = 1;
121 #ifdef HAVE_MSGHDR_ACCRIGHTS
122 msghdr.msg_accrights = (void *)&fd;
123 msghdr.msg_accrightslen = sizeof(fd);
124 #else /* HAVE_MSGHDR_ACCRIGHTS */
125 cmsg.len = sizeof(cmsg);
126 cmsg.level = SOL_SOCKET;
127 cmsg.type = SCM_RIGHTS;
129 msghdr.msg_control = &cmsg;
130 msghdr.msg_controllen = sizeof(cmsg);
131 msghdr.msg_flags = 0;
132 #endif /* HAVE_MSGHDR_ACCRIGHTS */
134 if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
137 if (errno == EPIPE) CLIENT_Die();
138 server_perror( "sendmsg" );
140 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
143 /***********************************************************************
146 * Wait for a reply from the server.
148 static unsigned int wait_reply(void)
155 if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
159 if (errno == EINTR) continue;
160 if (errno == EPIPE) CLIENT_Die();
161 server_perror("read");
163 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
164 server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
169 /***********************************************************************
172 * Wait for a reply from the server, when a file descriptor is passed.
174 static unsigned int wait_reply_fd( int *fd )
180 #ifdef HAVE_MSGHDR_ACCRIGHTS
181 struct msghdr msghdr;
184 msghdr.msg_accrights = (void *)fd;
185 msghdr.msg_accrightslen = sizeof(*fd);
186 #else /* HAVE_MSGHDR_ACCRIGHTS */
187 struct msghdr msghdr;
190 cmsg.len = sizeof(cmsg);
191 cmsg.level = SOL_SOCKET;
192 cmsg.type = SCM_RIGHTS;
194 msghdr.msg_control = &cmsg;
195 msghdr.msg_controllen = sizeof(cmsg);
196 msghdr.msg_flags = 0;
197 #endif /* HAVE_MSGHDR_ACCRIGHTS */
199 msghdr.msg_name = NULL;
200 msghdr.msg_namelen = 0;
201 msghdr.msg_iov = &vec;
202 msghdr.msg_iovlen = 1;
203 vec.iov_base = (void *)&res;
204 vec.iov_len = sizeof(res);
208 if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
210 #ifndef HAVE_MSGHDR_ACCRIGHTS
217 if (errno == EINTR) continue;
218 if (errno == EPIPE) CLIENT_Die();
219 server_perror("recvmsg");
221 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
222 server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
227 /***********************************************************************
230 * Perform a server call.
232 unsigned int server_call( enum request req )
238 if (res) SetLastError( res );
239 return res; /* error code */
243 /***********************************************************************
246 * Perform a server call, passing a file descriptor.
247 * If *fd is != -1, it will be passed to the server.
248 * If the server passes an fd, it will be stored into *fd.
250 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
254 if (fd_out == -1) send_request( req );
255 else send_request_fd( req, fd_out );
257 if (fd_in) res = wait_reply_fd( fd_in );
258 else res = wait_reply();
259 if (res) SetLastError( res );
260 return res; /* error code */
264 /***********************************************************************
267 * Start the server and create the initial socket pair.
269 int CLIENT_InitServer(void)
273 extern void create_initial_thread( int fd );
275 if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
277 perror("socketpair");
287 fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */
289 default: /* parent */
291 sprintf( buffer, "%d", fd[1] );
292 execl( BINDIR "/wineserver", "wineserver", buffer, NULL );
293 execlp( "wineserver", "wineserver", buffer, NULL );
294 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 );