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
);