/* cygserver_client.cc Copyright 2001, 2002 Red Hat Inc. Written by Egor Duda 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 #include #endif #include #include #include //#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; }