diff options
Diffstat (limited to 'winsup/cygserver/client.cc')
-rw-r--r-- | winsup/cygserver/client.cc | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/winsup/cygserver/client.cc b/winsup/cygserver/client.cc new file mode 100644 index 000000000..8a1eeafef --- /dev/null +++ b/winsup/cygserver/client.cc @@ -0,0 +1,207 @@ +/* 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; +} |