/*********************************************************************** * send_request * * Send a request to the server. */ static unsigned int send_request( const struct __server_request_info *req ) { unsigned int i; int ret; if (!req->u.req.request_header.request_size) { if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req, sizeof(req->u.req) )) == sizeof(req->u.req)) return STATUS_SUCCESS; } else { struct iovec vec[__SERVER_MAX_DATA+1]; vec[0].iov_base = (void *)&req->u.req; vec[0].iov_len = sizeof(req->u.req); for (i = 0; i < req->data_count; i++) { vec[i+1].iov_base = (void *)req->data[i].ptr; vec[i+1].iov_len = req->data[i].size; } if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) == req->u.req.request_header.request_size + sizeof(req->u.req)) return STATUS_SUCCESS; } if (ret >= 0) server_protocol_error( "partial write %d\n", ret ); if (errno == EPIPE) server_abort_thread(0); if (errno == EFAULT) return STATUS_ACCESS_VIOLATION; server_protocol_perror( "write" ); }
/*********************************************************************** * server_protocol_error */ void server_protocol_error( const char *err, ... ) { va_list args; va_start( args, err ); fprintf( stderr, "wine client error:%x: ", GetCurrentThreadId() ); vfprintf( stderr, err, args ); va_end( args ); server_abort_thread(1); }
/*********************************************************************** * receive_fd * * Receive a file descriptor passed from the server. */ static int receive_fd( obj_handle_t *handle ) { struct iovec vec; int ret, fd; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS struct msghdr msghdr; fd = -1; msghdr.msg_accrights = (void *)&fd; msghdr.msg_accrightslen = sizeof(fd); #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ struct msghdr msghdr; struct cmsg_fd cmsg; cmsg.header.len = sizeof(cmsg.header) + sizeof(fd); cmsg.header.level = SOL_SOCKET; cmsg.header.type = SCM_RIGHTS; cmsg.fd = -1; msghdr.msg_control = &cmsg; msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); msghdr.msg_flags = 0; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; vec.iov_base = (void *)handle; vec.iov_len = sizeof(*handle); for (;;) { if ((ret = recvmsg( fd_socket, &msghdr, 0 )) > 0) { #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS fd = cmsg.fd; #endif if (fd != -1) fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */ return fd; } if (!ret) break; if (errno == EINTR) continue; if (errno == EPIPE) break; server_protocol_perror("recvmsg"); } /* the server closed the connection; time to die... */ server_abort_thread(0); }
/*********************************************************************** * wine_server_send_fd (NTDLL.@) * * Send a file descriptor to the server. * * PARAMS * fd [I] file descriptor to send * * RETURNS * nothing */ void CDECL wine_server_send_fd( int fd ) { #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS struct cmsg_fd cmsg; #endif struct send_fd data; struct msghdr msghdr; struct iovec vec; int ret; vec.iov_base = (void *)&data; vec.iov_len = sizeof(data); msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS msghdr.msg_accrights = (void *)&fd; msghdr.msg_accrightslen = sizeof(fd); #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ cmsg.header.len = sizeof(cmsg.header) + sizeof(fd); cmsg.header.level = SOL_SOCKET; cmsg.header.type = SCM_RIGHTS; cmsg.fd = fd; msghdr.msg_control = &cmsg; msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); msghdr.msg_flags = 0; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ data.tid = GetCurrentThreadId(); data.fd = fd; for (;;) { if ((ret = sendmsg( fd_socket, &msghdr, 0 )) == sizeof(data)) return; if (ret >= 0) server_protocol_error( "partial write %d\n", ret ); if (errno == EINTR) continue; if (errno == EPIPE) server_abort_thread(0); server_protocol_perror( "sendmsg" ); } }
/*********************************************************************** * read_reply_data * * Read data from the reply buffer; helper for wait_reply. */ static void read_reply_data( void *buffer, size_t size ) { int ret; for (;;) { if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0) { if (!(size -= ret)) return; buffer = (char *)buffer + ret; continue; } if (!ret) break; if (errno == EINTR) continue; if (errno == EPIPE) break; server_protocol_perror("read"); } /* the server closed the connection; time to die... */ server_abort_thread(0); }
/*********************************************************************** * server_protocol_perror */ void server_protocol_perror( const char *err ) { fprintf( stderr, "wine client error:%x: ", GetCurrentThreadId() ); perror( err ); server_abort_thread(1); }
/********************************************************************** * quit_handler * * Handler for SIGQUIT. */ static HANDLER_DEF(quit_handler) { server_abort_thread(0); }