2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
12 #include <sys/types.h>
13 #include <sys/socket.h>
24 /* Some versions of glibc don't define this */
29 /* data structure used to pass an fd with sendmsg/recvmsg */
32 int len
; /* sizeof structure */
33 int level
; /* SOL_SOCKET */
34 int type
; /* SCM_RIGHTS */
35 int fd
; /* fd to pass */
38 /***********************************************************************
41 * Die on protocol errors or socket close
43 static void CLIENT_Die(void)
45 close( NtCurrentTeb()->socket
);
49 /***********************************************************************
50 * server_protocol_error
52 void server_protocol_error( const char *err
, ... )
56 va_start( args
, err
);
57 fprintf( stderr
, "Client protocol error:%p: ", NtCurrentTeb()->tid
);
58 vfprintf( stderr
, err
, args
);
64 /***********************************************************************
67 static void server_perror( const char *err
)
69 fprintf( stderr
, "Client protocol error:%p: ", NtCurrentTeb()->tid
);
75 /***********************************************************************
78 * Send a request to the server.
80 static void send_request( enum request req
)
83 if ((ret
= write( NtCurrentTeb()->socket
, &req
, sizeof(req
) )) == sizeof(req
))
87 if (errno
== EPIPE
) CLIENT_Die();
88 server_perror( "sendmsg" );
90 server_protocol_error( "partial msg sent %d/%d\n", ret
, sizeof(req
) );
93 /***********************************************************************
96 * Send a request to the server, passing a file descriptor.
98 static void send_request_fd( enum request req
, int fd
)
101 #ifndef HAVE_MSGHDR_ACCRIGHTS
104 struct msghdr msghdr
;
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
;
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;
131 if (errno
== EPIPE
) CLIENT_Die();
132 server_perror( "sendmsg" );
134 server_protocol_error( "partial msg sent %d/%d\n", ret
, sizeof(req
) );
137 /***********************************************************************
140 * Wait for a reply from the server.
142 static unsigned int wait_reply(void)
149 if ((ret
= read( NtCurrentTeb()->socket
, &res
, sizeof(res
) )) == sizeof(res
))
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 /***********************************************************************
166 * Wait for a reply from the server, when a file descriptor is passed.
168 static unsigned int wait_reply_fd( int *fd
)
174 #ifdef HAVE_MSGHDR_ACCRIGHTS
175 struct msghdr msghdr
;
178 msghdr
.msg_accrights
= (void *)fd
;
179 msghdr
.msg_accrightslen
= sizeof(*fd
);
180 #else /* HAVE_MSGHDR_ACCRIGHTS */
181 struct msghdr msghdr
;
184 cmsg
.len
= sizeof(cmsg
);
185 cmsg
.level
= SOL_SOCKET
;
186 cmsg
.type
= SCM_RIGHTS
;
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;
198 vec
.iov_len
= sizeof(res
);
202 if ((ret
= recvmsg( NtCurrentTeb()->socket
, &msghdr
, 0 )) == sizeof(res
))
204 #ifndef HAVE_MSGHDR_ACCRIGHTS
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 /***********************************************************************
224 * Perform a server call.
226 unsigned int server_call( enum request req
)
232 if (res
) SetLastError( res
);
233 return res
; /* error code */
237 /***********************************************************************
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
)
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 /***********************************************************************
261 * Start the server and create the initial socket pair.
263 int CLIENT_InitServer(void)
267 extern void create_initial_thread( int fd
);
269 if (socketpair( AF_UNIX
, SOCK_STREAM
, 0, fd
) == -1)
271 perror("socketpair");
282 default: /* parent */
284 sprintf( buffer
, "%d", fd
[1] );
285 /*#define EXEC_SERVER*/
287 execlp( "wineserver", "wineserver", buffer
, NULL
);
288 execl( "/usr/local/bin/wineserver", "wineserver", buffer
, NULL
);
289 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
);