2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
11 #include <sys/types.h>
12 #include <sys/socket.h>
21 /* Some versions of glibc don't define this */
26 /***********************************************************************
27 * CLIENT_SendRequest_v
29 * Send a request to the server.
31 static void CLIENT_SendRequest_v( enum request req
, int pass_fd
,
32 struct iovec
*vec
, int veclen
)
34 THDB
*thdb
= THREAD_Current();
35 #ifndef HAVE_MSGHDR_ACCRIGHTS
36 struct cmsg_fd cmsg
= { sizeof(cmsg
), SOL_SOCKET
, SCM_RIGHTS
, pass_fd
};
38 struct msghdr msghdr
= { NULL
, 0, vec
, veclen
, };
43 vec
[0].iov_base
= &head
;
44 vec
[0].iov_len
= sizeof(head
);
45 for (i
= len
= 0; i
< veclen
; i
++) len
+= vec
[i
].iov_len
;
47 assert( len
<= MAX_MSG_LENGTH
);
50 head
.seq
= thdb
->seq
++;
52 if (pass_fd
!= -1) /* we have an fd to send */
54 #ifdef HAVE_MSGHDR_ACCRIGHTS
55 msghdr
.msg_accrights
= (void *)&pass_fd
;
56 msghdr
.msg_accrightslen
= sizeof(pass_fd
);
58 msghdr
.msg_control
= &cmsg
;
59 msghdr
.msg_controllen
= sizeof(cmsg
);
63 if ((ret
= sendmsg( thdb
->socket
, &msghdr
, 0 )) < len
)
65 fprintf( stderr
, "Fatal protocol error: " );
66 if (ret
== -1) perror( "sendmsg" );
67 else fprintf( stderr
, "partial msg sent %d/%d\n", ret
, len
);
70 /* we passed the fd now we can close it */
71 if (pass_fd
!= -1) close( pass_fd
);
75 /***********************************************************************
78 * Send a request to the server.
80 static void CLIENT_SendRequest( enum request req
, int pass_fd
,
81 int n
, ... /* arg_1, len_1, etc. */ )
90 for (i
= 1; i
< n
; i
++)
92 vec
[i
].iov_base
= va_arg( args
, void * );
93 vec
[i
].iov_len
= va_arg( args
, int );
96 return CLIENT_SendRequest_v( req
, pass_fd
, vec
, n
);
100 /***********************************************************************
103 * Wait for a reply from the server.
104 * Returns the error code (or 0 if OK).
106 static unsigned int CLIENT_WaitReply_v( int *len
, int *passed_fd
,
107 struct iovec
*vec
, int veclen
)
109 THDB
*thdb
= THREAD_Current();
111 #ifdef HAVE_MSGHDR_ACCRIGHTS
112 struct msghdr msghdr
= { NULL
, 0, vec
, veclen
, (void*)&pass_fd
, sizeof(int) };
114 struct cmsg_fd cmsg
= { sizeof(cmsg
), SOL_SOCKET
, SCM_RIGHTS
, -1 };
115 struct msghdr msghdr
= { NULL
, 0, vec
, veclen
, &cmsg
, sizeof(cmsg
), 0 };
120 assert( veclen
> 0 );
121 vec
[0].iov_base
= &head
;
122 vec
[0].iov_len
= sizeof(head
);
124 if ((ret
= recvmsg( thdb
->socket
, &msghdr
, 0 )) == -1)
126 fprintf( stderr
, "Fatal protocol error: " );
130 if (ret
< sizeof(head
))
133 "Fatal protocol error: partial header received %d/%d\n",
137 if ((head
.len
< sizeof(head
)) || (head
.len
> MAX_MSG_LENGTH
))
139 fprintf( stderr
, "Fatal protocol error: header length %d\n",
143 if (head
.seq
!= thdb
->seq
++)
146 "Fatal protocol error: sequence %08x instead of %08x\n",
147 head
.seq
, thdb
->seq
- 1 );
151 #ifndef HAVE_MSGHDR_ACCRIGHTS
155 if (head
.type
!= ERROR_SUCCESS
)
157 SetLastError( head
.type
);
161 *passed_fd
= pass_fd
;
165 if (len
) *len
= ret
- sizeof(head
);
166 if (pass_fd
!= -1) close( pass_fd
);
167 remaining
= head
.len
- ret
;
168 while (remaining
> 0) /* drop remaining data */
171 int len
= remaining
< sizeof(buffer
) ? remaining
: sizeof(buffer
);
172 if ((len
= recv( thdb
->socket
, buffer
, len
, 0 )) == -1)
174 fprintf( stderr
, "Fatal protocol error: " );
181 return head
.type
; /* error code */
185 /***********************************************************************
188 * Wait for a reply from the server.
190 static unsigned int CLIENT_WaitReply( int *len
, int *passed_fd
,
191 int n
, ... /* arg_1, len_1, etc. */ )
193 struct iovec vec
[16];
197 n
++; /* for vec[0] */
200 for (i
= 1; i
< n
; i
++)
202 vec
[i
].iov_base
= va_arg( args
, void * );
203 vec
[i
].iov_len
= va_arg( args
, int );
206 return CLIENT_WaitReply_v( len
, passed_fd
, vec
, n
);
210 /***********************************************************************
213 * Send a new thread request. Helper function for CLIENT_NewThread.
215 static int send_new_thread( THDB
*thdb
)
217 struct new_thread_request request
;
218 struct new_thread_reply reply
;
221 if (socketpair( AF_UNIX
, SOCK_STREAM
, 0, fd
) == -1)
223 SetLastError( ERROR_TOO_MANY_OPEN_FILES
); /* FIXME */
227 request
.pid
= thdb
->process
->server_pid
;
228 CLIENT_SendRequest( REQ_NEW_THREAD
, fd
[1], 1, &request
, sizeof(request
) );
230 if (CLIENT_WaitReply( &len
, NULL
, 1, &reply
, sizeof(reply
) )) goto error
;
231 if (len
< sizeof(reply
)) goto error
;
232 thdb
->server_tid
= reply
.tid
;
233 thdb
->process
->server_pid
= reply
.pid
;
234 if (thdb
->socket
!= -1) close( thdb
->socket
);
235 thdb
->socket
= fd
[0];
236 thdb
->seq
= 0; /* reset the sequence number for the new fd */
245 /***********************************************************************
248 * Send a new thread request.
250 int CLIENT_NewThread( THDB
*thdb
)
252 extern BOOL32 THREAD_InitDone
;
254 if (!THREAD_InitDone
) /* first thread -> start the server */
259 if (socketpair( AF_UNIX
, SOCK_STREAM
, 0, tmpfd
) == -1)
261 perror("socketpair");
271 sprintf( buffer
, "%d", tmpfd
[1] );
273 execlp( "wineserver", "wineserver", buffer
, NULL
);
274 execl( "/usr/local/bin/wineserver", "wineserver", buffer
, NULL
);
275 execl( "./server/wineserver", "wineserver", buffer
, NULL
);
277 server_main_loop( tmpfd
[1] );
279 default: /* parent */
281 SET_CUR_THREAD( thdb
);
282 THREAD_InitDone
= TRUE
;
283 thdb
->socket
= tmpfd
[0];
288 return send_new_thread( thdb
);
292 /***********************************************************************
295 * Send an init thread request. Return 0 if OK.
297 int CLIENT_InitThread(void)
299 THDB
*thdb
= THREAD_Current();
300 struct init_thread_request init
;
301 int len
= strlen( thdb
->process
->env_db
->cmd_line
);
304 len
= MIN( len
, MAX_MSG_LENGTH
- sizeof(init
) );
306 CLIENT_SendRequest( REQ_INIT_THREAD
, -1, 2,
308 thdb
->process
->env_db
->cmd_line
, len
);
309 return CLIENT_WaitReply( NULL
, NULL
, NULL
, 0 );