208 lines
5.1 KiB
C++
208 lines
5.1 KiB
C++
/* cygserver_client.cc
|
|
|
|
Copyright 2001 Red Hat Inc.
|
|
|
|
Written by Egor Duda <deo@logos-m.ru>
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#ifdef __OUTSIDE_CYGWIN__
|
|
#undef __INSIDE_CYGWIN__
|
|
#else
|
|
#include "winsup.h"
|
|
#endif
|
|
|
|
#ifndef __INSIDE_CYGWIN__
|
|
#define debug_printf printf
|
|
#define api_fatal printf
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#endif
|
|
#include <sys/socket.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
//#include "security.h"
|
|
#include "cygwin/cygserver_transport.h"
|
|
#include "cygwin/cygserver_transport_pipes.h"
|
|
#include "cygwin/cygserver_transport_sockets.h"
|
|
#include "cygwin/cygserver.h"
|
|
|
|
/* 0 = untested, 1 = running, 2 = dead */
|
|
int cygserver_running=CYGSERVER_UNKNOWN;
|
|
/* on by default during development. For release, we probably want off by default */
|
|
int allow_daemon = TRUE;
|
|
|
|
client_request_get_version::client_request_get_version () : client_request (CYGSERVER_REQUEST_GET_VERSION, sizeof (version))
|
|
{
|
|
buffer = (char *)&version;
|
|
}
|
|
|
|
client_request_attach_tty::client_request_attach_tty () : client_request (CYGSERVER_REQUEST_ATTACH_TTY, sizeof (req))
|
|
{
|
|
buffer = (char *)&req;
|
|
req.pid = 0;
|
|
req.master_pid = 0;
|
|
req.from_master = NULL;
|
|
req.to_master = NULL;
|
|
}
|
|
|
|
client_request_attach_tty::client_request_attach_tty (DWORD npid, DWORD nmaster_pid, HANDLE nfrom_master, HANDLE nto_master) : client_request (CYGSERVER_REQUEST_ATTACH_TTY, sizeof (req))
|
|
{
|
|
buffer = (char *)&req;
|
|
req.pid = npid;
|
|
req.master_pid = nmaster_pid;
|
|
req.from_master = nfrom_master;
|
|
req.to_master = nto_master;
|
|
}
|
|
|
|
client_request_shutdown::client_request_shutdown () : client_request (CYGSERVER_REQUEST_SHUTDOWN, 0)
|
|
{
|
|
buffer = NULL;
|
|
}
|
|
|
|
client_request::client_request (cygserver_request_code id, ssize_t buffer_size) : header (id, buffer_size)
|
|
{
|
|
}
|
|
|
|
client_request::~client_request ()
|
|
{
|
|
}
|
|
|
|
client_request::operator class request_header ()
|
|
{
|
|
return header;
|
|
}
|
|
|
|
void
|
|
client_request::send (transport_layer_base *conn)
|
|
{
|
|
if (!conn)
|
|
return;
|
|
debug_printf("this=%p, conn=%p\n",this, conn);
|
|
ssize_t bytes_written, bytes_read;
|
|
debug_printf("header.cb = %ld\n",header.cb);
|
|
if ((bytes_written = conn->write ((char *)&header, sizeof (header)))
|
|
!= sizeof(header) || (header.cb &&
|
|
(bytes_written = conn->write (buffer, header.cb)) != header.cb))
|
|
{
|
|
header.error_code = -1;
|
|
debug_printf ("bytes written != request size\n");
|
|
return;
|
|
}
|
|
|
|
debug_printf("Sent request, size (%ld)\n",bytes_written);
|
|
|
|
if ((bytes_read = conn->read ((char *)&header, sizeof (header)))
|
|
!= sizeof (header) || (header.cb &&
|
|
(bytes_read = conn->read (buffer, header.cb) ) != header.cb))
|
|
{
|
|
header.error_code = -1;
|
|
debug_printf("failed reading response \n");
|
|
return;
|
|
}
|
|
debug_printf ("completed ok\n");
|
|
}
|
|
|
|
/* Oh, BTW: Fix the procedural basis and make this more intuitive. */
|
|
|
|
int
|
|
cygserver_request (client_request * req)
|
|
{
|
|
class transport_layer_base *transport;
|
|
|
|
if (!req || allow_daemon != TRUE)
|
|
return -1;
|
|
|
|
/* dont' retry every request if the server's not there */
|
|
if (cygserver_running==CYGSERVER_DEAD && req->header.req_id != CYGSERVER_REQUEST_GET_VERSION)
|
|
return -1;
|
|
|
|
transport = create_server_transport ();
|
|
|
|
/* FIXME: have at most one connection per thread. use TLS to store the details */
|
|
/* logic is:
|
|
* if not tlskey->conn, new conn,
|
|
* then; transport=conn;
|
|
*/
|
|
if (!transport->connect ())
|
|
{
|
|
delete transport;
|
|
return -1;
|
|
}
|
|
|
|
debug_printf ("connected to server %p\n", transport);
|
|
|
|
req->send(transport);
|
|
|
|
transport->close ();
|
|
|
|
delete transport;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
BOOL
|
|
check_cygserver_available ()
|
|
{
|
|
BOOL ret_val = FALSE;
|
|
HANDLE pipe = CreateFile (pipe_name,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
&sec_all_nih,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (pipe != INVALID_HANDLE_VALUE || GetLastError () != ERROR_PIPE_BUSY)
|
|
ret_val = TRUE;
|
|
|
|
if (pipe && pipe != INVALID_HANDLE_VALUE)
|
|
CloseHandle (pipe);
|
|
|
|
return (ret_val);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
cygserver_init ()
|
|
{
|
|
int rc;
|
|
if (allow_daemon != TRUE)
|
|
{
|
|
cygserver_running = CYGSERVER_DEAD;
|
|
return;
|
|
}
|
|
|
|
if (cygserver_running==CYGSERVER_OK)
|
|
return;
|
|
|
|
client_request_get_version *req =
|
|
new client_request_get_version ();
|
|
|
|
rc = cygserver_request (req);
|
|
delete req;
|
|
if (rc < 0)
|
|
cygserver_running = CYGSERVER_DEAD;
|
|
else if (rc > 0)
|
|
api_fatal ( "error connecting to cygwin server. error: %d", rc );
|
|
else if (req->version.major != CYGWIN_SERVER_VERSION_MAJOR ||
|
|
req->version.api != CYGWIN_SERVER_VERSION_API ||
|
|
req->version.minor > CYGWIN_SERVER_VERSION_MINOR)
|
|
api_fatal ( "incompatible version of cygwin server.\n\
|
|
client version %d.%d.%d.%d, server version%ld.%ld.%ld.%ld",
|
|
CYGWIN_SERVER_VERSION_MAJOR,
|
|
CYGWIN_SERVER_VERSION_API,
|
|
CYGWIN_SERVER_VERSION_MINOR,
|
|
CYGWIN_SERVER_VERSION_PATCH,
|
|
req->version.major,
|
|
req->version.api,
|
|
req->version.minor,
|
|
req->version.patch );
|
|
else
|
|
cygserver_running = CYGSERVER_OK;
|
|
}
|