summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/cygserver_client.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/cygserver_client.cc')
-rwxr-xr-xwinsup/cygwin/cygserver_client.cc207
1 files changed, 207 insertions, 0 deletions
diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc
new file mode 100755
index 000000000..8a1eeafef
--- /dev/null
+++ b/winsup/cygwin/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;
+}