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_noerr( enum request req
)
239 /***********************************************************************
242 * Perform a server call, passing a file descriptor.
243 * If *fd is != -1, it will be passed to the server.
244 * If the server passes an fd, it will be stored into *fd.
246 unsigned int server_call_fd( enum request req
, int fd_out
, int *fd_in
)
250 if (fd_out
== -1) send_request( req
);
251 else send_request_fd( req
, fd_out
);
253 if (fd_in
) res
= wait_reply_fd( fd_in
);
254 else res
= wait_reply();
255 if (res
) SetLastError( res
);
256 return res
; /* error code */
260 /***********************************************************************
263 * Start the server and create the initial socket pair.
265 int CLIENT_InitServer(void)
269 extern void create_initial_thread( int fd
);
271 if (socketpair( AF_UNIX
, SOCK_STREAM
, 0, fd
) == -1)
273 perror("socketpair");
283 fcntl( fd
[0], F_SETFD
, 1 ); /* set close on exec flag */
285 default: /* parent */
287 sprintf( buffer
, "%d", fd
[1] );
288 execl( BINDIR
"/wineserver", "wineserver", buffer
, NULL
);
289 execlp( "wineserver", "wineserver", buffer
, NULL
);
290 execl( "./server/wineserver", "wineserver", buffer
, NULL
);
291 create_initial_thread( fd
[1] );
298 /***********************************************************************
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();
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 );
314 if (teb
->buffer
== (void*)-1) server_perror( "mmap" );
316 req
= get_req_buffer();
317 req
->unix_pid
= getpid();
319 if (server_call( REQ_INIT_THREAD
)) return -1;
320 teb
->process
->server_pid
= req
->pid
;
326 /***********************************************************************
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();
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();
347 return server_call( REQ_DEBUGGER
);