Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Scott <conrad.scott@dsl.pipex.com>2002-06-18 01:35:37 +0400
committerConrad Scott <conrad.scott@dsl.pipex.com>2002-06-18 01:35:37 +0400
commitc84589dfeacc877975ab35b5a3c86815887cd237 (patch)
tree15d448a388a3e60e91a4da0fd6100960649659b1 /winsup/cygwin
parent061625829e483cba153df9dbc5670d027b501b1e (diff)
* include/cygwin/cygserver.h: Change the client_request classes to
give greater encapsulation and to allow variable length requests and replies. (enum cygserver_request_code): Now client_request::request_code_t. (class request_header): Now client_request::header_t. Make a union of the request_code and the error_code. The `cb' field, which was the buffer length, is now the `size_t msglen' field. (struct request_get_version): Now client_request_get_version::request_get_version. (struct request_shutdown): Remove unused type. (struct request_attach_tty): Now client_request_attach_tty::request_attach_tty. (client_request::_buf): Make field const. (client_request::_buflen): New const private field. (client_request::request_code): New accessor. (client_request::error_code): Ditto. (client_request::msglen): Ditto. (client_request::handle_request): New static method. (client_request::make_request): New virtual method. (client_request::handle): New method. (client_request::send): Make private. (client_request_get_version::check_version): New method. (client_request_get_version::serve): Make private. (client_request_get_version::version): Ditto. (client_request_shutdown::serve): Ditto. (client_request_attach_tty::req): Ditto. (client_request_attach_tty::serve): Ditto. (client_request_attach_tty::from_master): Make method const. (client_request_attach_tty::from_master): Ditto. * cygserver_client.cc (client_request_get_version::client_request_get_version): Track changes to the client_request classes. (client_request_attach_tty::client_request_attach_tty): Ditto. (client_request_get_version::check_version): New method to encapsulate code from cygserver_init(). (client_request_shutdown::client_request_shutdown): Move into "cygserver.cc". (client_request::send): Track changes to the client_request classes. Add more error checking. (client_request::handle_request): New static method containing the first half of the old server_request::process() code. (client_request::make_request): New method to replace the old cygserver_request() function. (client_request::handle): New method containing the second half of the old server_request::process() code. (cygserver_init): Track changes to the client_request classes. In particular, some code moved into the client_request_get_version::check_version() method. * cygserver.cc (client_request_attach_tty::serve): Track changes to the client_request classes. In particular, only return a reply body if some handles are successfully duplicated for the client. And remove goto's. (client_request_get_version::serve): Track changes to the client_request classes. (client_request_shutdown::serve): Ditto. (class client_request_invalid): Dead, and so young too. (server_request::request_buffer): Remove unnecessary field. (client_request_shutdown::client_request_shutdown): Moved here from "cygserver_client.cc". (server_request::process): Implementation moved into the new client_request::handle_request() and client_request::handle() methods. * cygserver_shm.h (class client_request_shm): Put client- and server-specific interfaces inside #ifdef/#ifndef __INSIDE_CYGWIN__ guards. (client_request_shm::serve): Make private. * cygserver_shm.cc (client_request_shm::client_request_shm): Track changes to the client_request classes. (client_request_shm::serve): Ditto * shm.cc (client_request_shm::client_request_shm): Ditto. Use alloc_sd() rather than set_security_attribute() to get access to the SECURITY_DESCRIPTOR length, so that we can use it to set the request body length. (shmat): Track changes to the client_request classes. In particular, allocate client_request objects on the stack rather than on the heap, and use the client_request::make_request() method rather than the old cygserver_request() function. (shmdt): Ditto. (shmctl): Ditto. (shmget): Ditto. * fhandler_tty.cc (fhandler_tty_slave::cygserver_attach_tty): Ditto.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog85
-rwxr-xr-xwinsup/cygwin/cygserver.cc296
-rwxr-xr-xwinsup/cygwin/cygserver_client.cc415
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc117
-rw-r--r--winsup/cygwin/cygserver_shm.h37
-rw-r--r--winsup/cygwin/fhandler_tty.cc28
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver.h187
-rw-r--r--winsup/cygwin/shm.cc121
8 files changed, 825 insertions, 461 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ffb8e4d0f..4860a810c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,90 @@
2002-06-17 Conrad Scott <conrad.scott@dsl.pipex.com>
+ * include/cygwin/cygserver.h: Change the client_request classes to
+ give greater encapsulation and to allow variable length requests
+ and replies.
+ (enum cygserver_request_code): Now client_request::request_code_t.
+ (class request_header): Now client_request::header_t. Make a
+ union of the request_code and the error_code. The `cb' field,
+ which was the buffer length, is now the `size_t msglen' field.
+ (struct request_get_version): Now
+ client_request_get_version::request_get_version.
+ (struct request_shutdown): Remove unused type.
+ (struct request_attach_tty): Now
+ client_request_attach_tty::request_attach_tty.
+ (client_request::_buf): Make field const.
+ (client_request::_buflen): New const private field.
+ (client_request::request_code): New accessor.
+ (client_request::error_code): Ditto.
+ (client_request::msglen): Ditto.
+ (client_request::handle_request): New static method.
+ (client_request::make_request): New virtual method.
+ (client_request::handle): New method.
+ (client_request::send): Make private.
+ (client_request_get_version::check_version): New method.
+ (client_request_get_version::serve): Make private.
+ (client_request_get_version::version): Ditto.
+ (client_request_shutdown::serve): Ditto.
+ (client_request_attach_tty::req): Ditto.
+ (client_request_attach_tty::serve): Ditto.
+ (client_request_attach_tty::from_master): Make method const.
+ (client_request_attach_tty::from_master): Ditto.
+ * cygserver_client.cc
+ (client_request_get_version::client_request_get_version): Track
+ changes to the client_request classes.
+ (client_request_attach_tty::client_request_attach_tty): Ditto.
+ (client_request_get_version::check_version): New method to
+ encapsulate code from cygserver_init().
+ (client_request_shutdown::client_request_shutdown): Move into
+ "cygserver.cc".
+ (client_request::send): Track changes to the client_request
+ classes. Add more error checking.
+ (client_request::handle_request): New static method containing the
+ first half of the old server_request::process() code.
+ (client_request::make_request): New method to replace the old
+ cygserver_request() function.
+ (client_request::handle): New method containing the second half of
+ the old server_request::process() code.
+ (cygserver_init): Track changes to the client_request classes. In
+ particular, some code moved into the
+ client_request_get_version::check_version() method.
+ * cygserver.cc (client_request_attach_tty::serve): Track changes
+ to the client_request classes. In particular, only return a reply
+ body if some handles are successfully duplicated for the client.
+ And remove goto's.
+ (client_request_get_version::serve): Track changes to the
+ client_request classes.
+ (client_request_shutdown::serve): Ditto.
+ (class client_request_invalid): Dead, and so young too.
+ (server_request::request_buffer): Remove unnecessary field.
+ (client_request_shutdown::client_request_shutdown): Moved here
+ from "cygserver_client.cc".
+ (server_request::process): Implementation moved into the new
+ client_request::handle_request() and client_request::handle()
+ methods.
+ * cygserver_shm.h (class client_request_shm): Put client- and
+ server-specific interfaces inside #ifdef/#ifndef __INSIDE_CYGWIN__
+ guards.
+ (client_request_shm::serve): Make private.
+ * cygserver_shm.cc
+ (client_request_shm::client_request_shm): Track changes to the
+ client_request classes.
+ (client_request_shm::serve): Ditto
+ * shm.cc (client_request_shm::client_request_shm): Ditto. Use
+ alloc_sd() rather than set_security_attribute() to get access to
+ the SECURITY_DESCRIPTOR length, so that we can use it to set the
+ request body length.
+ (shmat): Track changes to the client_request classes. In
+ particular, allocate client_request objects on the stack rather
+ than on the heap, and use the client_request::make_request()
+ method rather than the old cygserver_request() function.
+ (shmdt): Ditto.
+ (shmctl): Ditto.
+ (shmget): Ditto.
+ * fhandler_tty.cc (fhandler_tty_slave::cygserver_attach_tty): Ditto.
+
+2002-06-17 Conrad Scott <conrad.scott@dsl.pipex.com>
+
* include/cygwin/cygserver_transport.h
(cygserver_transport::read): Change buffer type to void *.
(cygserver_transport::write): Ditto.
diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc
index 836117e3f..d74ee1342 100755
--- a/winsup/cygwin/cygserver.cc
+++ b/winsup/cygwin/cygserver.cc
@@ -244,146 +244,153 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process,
return (ret_val);
}
+/*
+ * client_request_attach_tty::serve ()
+ */
+
void
-client_request_attach_tty::serve(transport_layer_base *conn, class process_cache *cache)
+client_request_attach_tty::serve (transport_layer_base * const conn,
+ process_cache *)
{
- HANDLE from_process_handle = NULL;
- HANDLE to_process_handle = NULL;
- HANDLE token_handle = NULL;
- DWORD rc;
+ assert (conn);
+
+ assert (!error_code ());
if (!wincap.has_security ())
{
- system_printf ("this should not be called in a system without security");
- header.error_code = EINVAL;
+ syscall_printf ("operation only supported on systems with security");
+ error_code (EINVAL);
+ msglen (0);
return;
}
- if (header.cb != sizeof (req))
+ if (msglen () != sizeof (req))
{
- header.error_code = EINVAL;
+ syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
+ sizeof (req), msglen ());
+ error_code (EINVAL);
+ msglen (0);
return;
}
- const HANDLE from_master_orig = req.from_master;
- const HANDLE to_master_orig = req.to_master;
+ msglen (0); // Until we fill in some fields.
// verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld", req.master_pid,
- // req.from_master, req.to_master,
+ // from_master, to_master,
// req.pid);
// verbose: debug_printf ("opening process %ld", req.master_pid);
- from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
+
+ const HANDLE from_process_handle =
+ OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
+
+ if (!from_process_handle)
+ {
+ system_printf ("error opening `from' process, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ return;
+ }
+
// verbose: debug_printf ("opening process %ld", req.pid);
- to_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
- if (!from_process_handle || !to_process_handle)
+
+ const HANDLE to_process_handle =
+ OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
+
+ if (!to_process_handle)
{
- system_printf ("error opening process (%lu)", GetLastError ());
- header.error_code = EACCES;
- goto out;
+ system_printf ("error opening `to' process, error = %lu",
+ GetLastError ());
+ CloseHandle (from_process_handle);
+ error_code (EACCES);
+ return;
}
// verbose: debug_printf ("Impersonating client");
conn->impersonate_client ();
+ HANDLE token_handle = NULL;
+
// verbose: debug_printf ("about to open thread token");
- rc = OpenThreadToken (GetCurrentThread (),
- TOKEN_QUERY,
- TRUE,
- &token_handle);
+ const DWORD rc = OpenThreadToken (GetCurrentThread (),
+ TOKEN_QUERY,
+ TRUE,
+ &token_handle);
// verbose: debug_printf ("opened thread token, rc=%lu", rc);
conn->revert_to_self ();
if (!rc)
{
- system_printf ("error opening thread token (%lu)", GetLastError ());
- header.error_code = EACCES;
- goto out;
- }
-
- if (check_and_dup_handle (from_process_handle, to_process_handle,
- token_handle,
- GENERIC_READ,
- req.from_master,
- &req.from_master, TRUE) != 0)
- {
- system_printf ("error duplicating from_master handle (%lu)",
+ system_printf ("error opening thread token, error = %lu",
GetLastError ());
- header.error_code = EACCES;
- goto out;
+ CloseHandle (from_process_handle);
+ CloseHandle (to_process_handle);
+ error_code (EACCES);
+ return;
}
- if (req.to_master)
- {
- if (check_and_dup_handle (from_process_handle, to_process_handle,
- token_handle,
- GENERIC_WRITE,
- req.to_master,
- &req.to_master, TRUE) != 0)
- {
- system_printf ("error duplicating to_master handle (%lu)",
- GetLastError ());
- header.error_code = EACCES;
- goto out;
- }
- }
+ // From this point on, a reply body is returned to the client.
+
+ const HANDLE from_master = req.from_master;
+ const HANDLE to_master = req.to_master;
+
+ req.from_master = NULL;
+ req.to_master = NULL;
+
+ msglen (sizeof (req));
+
+ if (from_master)
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_READ,
+ from_master,
+ &req.from_master, TRUE) != 0)
+ {
+ system_printf ("error duplicating from_master handle, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ }
+
+ if (to_master)
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_WRITE,
+ to_master,
+ &req.to_master, TRUE) != 0)
+ {
+ system_printf ("error duplicating to_master handle, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ }
+
+ CloseHandle (from_process_handle);
+ CloseHandle (to_process_handle);
+ CloseHandle (token_handle);
debug_printf ("%lu(%lu, %lu) -> %lu(%lu,%lu)",
- req.master_pid, from_master_orig, to_master_orig,
+ req.master_pid, from_master, to_master,
req.pid, req.from_master, req.to_master);
- header.error_code = 0;
-
-out:
- if (from_process_handle)
- CloseHandle (from_process_handle);
- if (to_process_handle)
- CloseHandle (to_process_handle);
- if (token_handle)
- CloseHandle (token_handle);
+ return;
}
void
-client_request_get_version::serve(transport_layer_base *conn, class process_cache *cache)
+client_request_get_version::serve(transport_layer_base *, process_cache *)
{
- if (header.cb != sizeof (version))
- {
- header.error_code = EINVAL;
- return;
- }
- header.error_code = 0;
+ assert (!error_code ());
+
+ if (msglen ())
+ syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
+
+ msglen (sizeof (version));
+
version.major = CYGWIN_SERVER_VERSION_MAJOR;
version.api = CYGWIN_SERVER_VERSION_API;
version.minor = CYGWIN_SERVER_VERSION_MINOR;
version.patch = CYGWIN_SERVER_VERSION_PATCH;
}
-/*
- * class client_request_invalid
- *
- * Used by server_request::process() to handle unrecognised client
- * requests. Apart from error reporting (to the log and to the
- * client), its main purpose is to provide an implementation of the
- * (pure virtual) serve() method that server_request::process() can
- * call.
- */
-
-class client_request_invalid : public client_request
-{
-public:
- client_request_invalid (const request_header * const hdr)
- : client_request (CYGSERVER_REQUEST_INVALID, 0)
- {
- header.error_code = ENOSYS;
- system_printf ("invalid request [type = %d]: returning ENOSYS",
- hdr->req_id);
- };
-
- virtual void serve (transport_layer_base *, class process_cache *)
- {};
-};
-
class server_request : public queue_request
{
public:
@@ -392,7 +399,6 @@ class server_request : public queue_request
virtual ~server_request();
virtual void process ();
private:
- char request_buffer [MAX_REQUEST_SIZE];
transport_layer_base *conn;
class process_cache *cache;
};
@@ -411,6 +417,7 @@ class server_request_queue : public threaded_queue
void process_requests (transport_layer_base *transport);
void add_connection (transport_layer_base *conn);
};
+
class server_request_queue request_queue;
static DWORD WINAPI
@@ -442,14 +449,27 @@ server_request_queue::process_requests (transport_layer_base *transport)
threaded_queue::process_requests (params, request_loop);
}
+client_request_shutdown::client_request_shutdown ()
+ : client_request (CYGSERVER_REQUEST_SHUTDOWN)
+{
+ syscall_printf ("created");
+}
+
void
-client_request_shutdown::serve (transport_layer_base *conn, class process_cache *cache)
+client_request_shutdown::serve (transport_layer_base *, process_cache *)
{
+ assert (!error_code ());
+
+ if (msglen ())
+ syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
+
/* FIXME: link upwards, and then this becomes a trivial method call to
* only shutdown _this queue_
*/
/* tell the main thread to shutdown */
- request_queue.active=false;
+ request_queue.active = false;
+
+ msglen (0);
}
server_request::server_request (transport_layer_base *newconn,
@@ -465,71 +485,7 @@ server_request::~server_request ()
void
server_request::process ()
{
- ssize_t bytes_read, bytes_written;
- struct request_header* req_ptr = (struct request_header*) &request_buffer;
- client_request *req = NULL;
- // verbose: debug_printf ("about to read");
-
- bytes_read = conn->read (request_buffer, sizeof (struct request_header));
- if (bytes_read != sizeof (struct request_header))
- {
- system_printf ("error reading from connection (%lu)", GetLastError ());
- return;
- }
- // verbose: debug_printf ("got header (%ld)", bytes_read);
-
- switch (req_ptr->req_id)
- {
- case CYGSERVER_REQUEST_GET_VERSION:
- req = new client_request_get_version (); break;
- case CYGSERVER_REQUEST_ATTACH_TTY:
- req = new client_request_attach_tty (); break;
- case CYGSERVER_REQUEST_SHUTDOWN:
- req = new client_request_shutdown (); break;
- case CYGSERVER_REQUEST_SHM_GET:
- req = new client_request_shm (); break;
- default:
- req = new client_request_invalid (req_ptr); break;
- }
-
- assert (req);
-
- if (req->header.cb != req_ptr->cb)
- {
- system_printf ("Mismatch in request buffer sizes");
- delete req;
- return;
- }
-
- if (req->header.cb)
- {
- bytes_read = conn->read (req->buffer, req->header.cb);
- if (bytes_read != req->header.cb)
- {
- system_printf ("error reading from connection (%lu)", GetLastError ());
- delete req;
- return;
- }
- // verbose: debug_printf ("got body (%ld)",bytes_read);
- }
-
- /* this is not allowed to fail. We must return ENOSYS at a minimum to the client */
- req->serve (conn, cache);
-
- if ((bytes_written = conn->write ((char *)&req->header, sizeof (req->header)))
- != sizeof(req->header) || (req->header.cb &&
- (bytes_written = conn->write (req->buffer, req->header.cb)) != req->header.cb))
- {
- req->header.error_code = -1;
- system_printf ("error writing to connection (%lu)", GetLastError ());
- delete req;
- return;
- }
-
- // verbose: debug_printf("Sent reply, size (%ld)",bytes_written);
- printf (".");
-
- delete (req);
+ client_request::handle_request (conn, cache);
}
void
@@ -680,24 +636,20 @@ main (const int argc, char *argv[])
return 1;
}
- transport_layer_base * const transport = create_server_transport ();
-
- assert (transport);
-
if (shutdown)
{
- if (!transport->connect())
- {
- system_printf ("couldn't establish connection with server");
- return 1;
- }
+ client_request_shutdown req;
+
+ if (req.make_request () == -1 || req.error_code ())
+ return 1;
- client_request_shutdown request;
- request.send (transport);
- transport->close();
return 0;
}
+ transport_layer_base * const transport = create_server_transport ();
+
+ assert (transport);
+
setbuf (stdout, NULL);
printf ("daemon starting up");
print_version (pgm);
diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc
index d50e7d9a8..25bb10390 100755
--- a/winsup/cygwin/cygserver_client.cc
+++ b/winsup/cygwin/cygserver_client.cc
@@ -4,11 +4,11 @@
Written by Egor Duda <deo@logos-m.ru>
- This file is part of Cygwin.
+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. */
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
/* to allow this to link into cygwin and the .dll, a little magic is needed. */
#ifdef __OUTSIDE_CYGWIN__
@@ -18,108 +18,283 @@
#endif
#include <sys/socket.h>
+
+#include <assert.h>
#include <errno.h>
+#include <stdio.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"
+#include "cygserver_shm.h"
+
+int cygserver_running = CYGSERVER_UNKNOWN;
-/* 0 = untested, 1 = running, 2 = dead */
-int cygserver_running=CYGSERVER_UNKNOWN;
-/* on by default during development. For release, we probably want off by default */
+/* 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))
+client_request_get_version::client_request_get_version ()
+ : client_request (CYGSERVER_REQUEST_GET_VERSION, &version, sizeof (version))
{
- buffer = (char *)&version;
-}
+ msglen (0); // No parameters for request.
-#ifndef __INSIDE_CYGWIN__
+ syscall_printf ("created");
+}
-client_request_attach_tty::client_request_attach_tty () : client_request (CYGSERVER_REQUEST_ATTACH_TTY, sizeof (req))
+void
+client_request_get_version::check_version () const
{
- buffer = (char *)&req;
- req.pid = 0;
- req.master_pid = 0;
- req.from_master = NULL;
- req.to_master = NULL;
+ if (version.major != CYGWIN_SERVER_VERSION_MAJOR ||
+ version.api != CYGWIN_SERVER_VERSION_API ||
+ 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,
+ version.major,
+ version.api,
+ version.minor,
+ version.patch);
}
-#else /* __INSIDE_CYGWIN__ */
+#ifdef __INSIDE_CYGWIN__
-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))
+client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid,
+ HANDLE nfrom_master,
+ HANDLE nto_master)
+ : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
{
- buffer = (char *)&req;
- req.pid = npid;
+ req.pid = GetCurrentProcessId ();
req.master_pid = nmaster_pid;
req.from_master = nfrom_master;
req.to_master = nto_master;
+
+ syscall_printf (("created: pid = %lu, master_pid = %lu, "
+ "from_master = %lu, to_master = %lu"),
+ req.pid, req.master_pid, req.from_master, req.to_master);
}
-#endif /* __INSIDE_CYGWIN__ */
+#else /* !__INSIDE_CYGWIN__ */
-client_request_shutdown::client_request_shutdown () : client_request (CYGSERVER_REQUEST_SHUTDOWN, 0)
+client_request_attach_tty::client_request_attach_tty ()
+ : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
{
- buffer = NULL;
+ syscall_printf ("created");
}
-client_request::client_request (cygserver_request_code id, ssize_t buffer_size) : header (id, buffer_size)
-{
-}
+#endif /* __INSIDE_CYGWIN__ */
-client_request::~client_request ()
+client_request::header_t::header_t (const request_code_t request_code,
+ const size_t msglen)
+ : msglen (msglen),
+ request_code (request_code)
{
+ assert (request_code >= 0 && request_code < CYGSERVER_REQUEST_LAST);
}
+// FIXME: also check write and read result for -1.
+
void
-client_request::send (transport_layer_base *conn)
+client_request::send (transport_layer_base * const conn)
{
- if (!conn)
- return;
- debug_printf("this=%p, conn=%p",this, conn);
- ssize_t bytes_written, bytes_read;
- debug_printf("header.cb = %ld",header.cb);
- if ((bytes_written = conn->write ((char *)&header, sizeof (header)))
- != sizeof(header) || (header.cb &&
- (bytes_written = conn->write (buffer, header.cb)) != header.cb))
+ assert (conn);
+ assert (!(_header.msglen && !_buf)); // i.e., _header.msglen implies _buf
+ assert (_header.msglen <= _buflen);
+
+ {
+ const ssize_t count = conn->write (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ error_code(errno);
+ syscall_printf (("request header write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (_header.msglen)
{
- header.error_code = -1;
- debug_printf ("bytes written != request size");
+ const ssize_t count = conn->write (_buf, _header.msglen);
+
+ if (count == -1 || (size_t) count != _header.msglen)
+ {
+ error_code(errno);
+ syscall_printf (("request body write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, _header.msglen,
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ syscall_printf ("request sent (%ld + %ld bytes)",
+ sizeof (_header), _header.msglen);
+
+ {
+ const ssize_t count = conn->read (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ error_code(errno);
+ syscall_printf (("reply header read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (_header.msglen && !_buf)
+ {
+ system_printf ("no client buffer for reply body: %ld bytes needed",
+ _header.msglen);
+ error_code(EINVAL);
return;
}
- debug_printf("Sent request, size (%ld)",bytes_written);
+ if (_header.msglen > _buflen)
+ {
+ system_printf (("client buffer too small for reply body: "
+ "have %ld bytes and need %ld"),
+ _buflen, _header.msglen);
+ error_code(EINVAL);
+ return;
+ }
- if ((bytes_read = conn->read ((char *)&header, sizeof (header)))
- != sizeof (header) || (header.cb &&
- (bytes_read = conn->read (buffer, header.cb)) != header.cb))
+ if (_header.msglen)
{
- header.error_code = -1;
- debug_printf("failed reading response ");
+ const ssize_t count = conn->read (_buf, _header.msglen);
+
+ if (count == -1 || (size_t) count != _header.msglen)
+ {
+ error_code(errno);
+ syscall_printf (("reply body read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, _header.msglen,
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ syscall_printf ("reply received (%ld + %ld bytes)",
+ sizeof (_header), _header.msglen);
+}
+
+#ifndef __INSIDE_CYGWIN__
+
+/*
+ * client_request::handle_request ()
+ *
+ * A server-side method.
+ *
+ * This is a factory method for the client_request subclasses. It
+ * reads the incoming request header and, based on its request code,
+ * creates an instance of the appropriate class.
+ *
+ * FIXME: If the incoming packet is malformed, the server drops it on
+ * the floor. Should it try and generate some sort of reply for the
+ * client? As it is, the client will simply get a broken connection.
+ *
+ * FIXME: also check write and read result for -1.
+ */
+
+/* static */ void
+client_request::handle_request (transport_layer_base *conn,
+ class process_cache *cache)
+{
+ // verbose: debug_printf ("about to read");
+
+ header_t header;
+
+ {
+ const ssize_t count = conn->read (&header, sizeof (header));
+
+ if (count != sizeof (header))
+ {
+ syscall_printf (("request header read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ // verbose: debug_printf ("got header (%ld)", bytes_read);
+
+ client_request *req = NULL;
+
+ switch (header.request_code)
+ {
+ case CYGSERVER_REQUEST_GET_VERSION:
+ req = new client_request_get_version ();
+ break;
+ case CYGSERVER_REQUEST_SHUTDOWN:
+ req = new client_request_shutdown ();
+ break;
+ case CYGSERVER_REQUEST_ATTACH_TTY:
+ req = new client_request_attach_tty ();
+ break;
+ case CYGSERVER_REQUEST_SHM:
+ req = new client_request_shm ();
+ break;
+ default:
+ syscall_printf ("unknown request code %d received: request ignored",
+ header.request_code);
return;
}
- debug_printf ("completed ok");
+
+ assert (req);
+
+ req->msglen (header.msglen);
+ req->handle (conn, cache);
+
+ delete (req);
+ printf (".");
}
-#ifdef __INSIDE_CYGWIN__
+#endif /* !__INSIDE_CYGWIN__ */
-/* Oh, BTW: Fix the procedural basis and make this more intuitive. */
+client_request::client_request (request_code_t const id,
+ void * const buf,
+ size_t const buflen)
+ : _header (id, buflen),
+ _buf (buf),
+ _buflen (buflen)
+{
+ assert ((!_buf && !_buflen) || (_buf && _buflen));
+}
+
+client_request::~client_request ()
+{}
int
-cygserver_request (client_request * req)
+client_request::make_request ()
{
- class transport_layer_base *transport;
-
- if (!req || allow_daemon != TRUE)
+ if (!allow_daemon)
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)
+ /* Don't retry every request if the server's not there */
+ if (cygserver_running == CYGSERVER_DEAD
+ && request_code() != CYGSERVER_REQUEST_GET_VERSION)
return -1;
- transport = create_server_transport ();
+ class transport_layer_base * const transport = create_server_transport ();
+
+ assert (transport);
/* FIXME: have at most one connection per thread. use TLS to store the details */
/* logic is:
@@ -134,7 +309,7 @@ cygserver_request (client_request * req)
debug_printf ("connected to server %p", transport);
- req->send(transport);
+ send (transport);
transport->close ();
@@ -143,6 +318,112 @@ cygserver_request (client_request * req)
return 0;
}
+#ifndef __INSIDE_CYGWIN__
+
+/*
+ * client_request::handle ()
+ *
+ * A server-side method.
+ *
+ * At this point, the header of an incoming request has been read and
+ * an appropriate client_request object constructed. This method has
+ * to read the request body into its buffer, if there is such a body,
+ * then perform the request and send back the results to the client.
+ *
+ * FIXME: If the incoming packet is malformed, the server drops it on
+ * the floor. Should it try and generate some sort of reply for the
+ * client? As it is, the client will simply get a broken connection.
+ *
+ * FIXME: also check write and read result for -1.
+ */
+
+void
+client_request::handle (transport_layer_base * const conn,
+ class process_cache * const cache)
+{
+ if (_header.msglen && !_buf)
+ {
+ system_printf ("no buffer for request body: %ld bytes needed",
+ _header.msglen);
+ error_code(EINVAL);
+ return;
+ }
+
+ if (_header.msglen > _buflen)
+ {
+ system_printf (("buffer too small for request body: "
+ "have %ld bytes and need %ld"),
+ _buflen, _header.msglen);
+ error_code(EINVAL);
+ return;
+ }
+
+ if (_header.msglen)
+ {
+ const ssize_t count = conn->read (_buf, _header.msglen);
+
+ if (count == -1 || (size_t) count != _header.msglen)
+ {
+ error_code(errno);
+ syscall_printf (("request body read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, _header.msglen,
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ syscall_printf ("request received (%ld + %ld bytes)",
+ sizeof (_header), _header.msglen);
+
+ error_code (0); // Overwrites the _header.request_code field.
+
+ /*
+ * This is not allowed to fail. We must return ENOSYS at a minimum
+ * to the client.
+ */
+ serve (conn, cache);
+
+ {
+ const ssize_t count = conn->write (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ error_code(errno);
+ syscall_printf (("reply header write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (_header.msglen)
+ {
+ const ssize_t count = conn->write (_buf, _header.msglen);
+
+ if (count == -1 || (size_t) count != _header.msglen)
+ {
+ error_code(errno);
+ syscall_printf (("reply body write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, _header.msglen,
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ syscall_printf ("reply sent (%ld + %ld bytes)",
+ sizeof (_header), _header.msglen);
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+#ifdef __INSIDE_CYGWIN__
+
#if 0
BOOL
check_cygserver_available ()
@@ -181,7 +462,7 @@ cygserver_init ()
// This indicates that we failed to connect to cygserver at all but
// that's fine as cygwin doesn't need it to be running.
- if (cygserver_request (&req) == -1)
+ if (req.make_request () == -1)
{
cygserver_running = CYGSERVER_DEAD;
return;
@@ -189,28 +470,16 @@ cygserver_init ()
// We connected to the server but something went wrong after that
// (sending the message, cygserver itself, or receiving the reply).
- if (req.header.error_code != 0)
+ if (req.error_code () != 0)
{
cygserver_running = CYGSERVER_DEAD;
debug_printf ("failure in cygserver version request: %d",
- req.header.error_code);
+ req.error_code ());
debug_printf ("process will continue without cygserver support");
return;
}
- 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);
+ req.check_version (); // Dies if bad . . .
cygserver_running = CYGSERVER_OK;
}
diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc
index 49e86a3fe..90473032c 100755
--- a/winsup/cygwin/cygserver_shm.cc
+++ b/winsup/cygwin/cygserver_shm.cc
@@ -12,22 +12,20 @@
#include "woutsup.h"
-// #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+
+#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>
-#include "cygerrno.h"
#include <unistd.h>
-#include "security.h"
-//#include "fhandler.h"
-//#include "dtable.h"
-//#include "cygheap.h"
-//#include "thread.h"
-#include <sys/shm.h>
-//#include "perprocess.h"
-#include <threaded_queue.h>
-#include <cygwin/cygserver_process.h>
+
+#include "cygerrno.h"
#include "cygserver_shm.h"
+#include "cygwin/cygserver_process.h"
+#include "security.h"
+#include "threaded_queue.h"
// FIXME IS THIS CORRECT
/* Implementation notes: We use two shared memory regions per key:
@@ -50,11 +48,10 @@ getsystemallocgranularity ()
return buffer_offset;
}
-
-client_request_shm::client_request_shm ():client_request (CYGSERVER_REQUEST_SHM_GET,
- sizeof (parameters))
+client_request_shm::client_request_shm ()
+ : client_request (CYGSERVER_REQUEST_SHM, &parameters, sizeof (parameters))
{
- buffer = (char *) &parameters;
+ syscall_printf ("created");
}
/* FIXME: evaluate getuid() and getgid() against the requested mode. Then
@@ -127,8 +124,33 @@ delete_shmnode (shmnode **nodeptr)
}
void
-client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
+client_request_shm::serve (transport_layer_base * const conn,
+ process_cache * const cache)
{
+ assert (conn);
+ assert (cache);
+
+ assert (!error_code ());
+
+ // The minimum possible request length. SHM_CREATE requests should
+ // be longer than this.
+ const size_t min_req_msglen =
+ (sizeof (parameters.in) - sizeof (parameters.in.sd_buf));
+
+ if (msglen () < min_req_msglen)
+ {
+ syscall_printf (("bad request body length: "
+ "expecting at least %lu bytes, got %lu"),
+ min_req_msglen, msglen ());
+ error_code (EINVAL);
+ msglen (0);
+ return;
+ }
+
+ // FIXME: check length of sd_buf contents for SHM_CREATE?
+
+ msglen (sizeof (parameters.out));
+
HANDLE from_process_handle = NULL;
HANDLE token_handle = NULL;
DWORD rc;
@@ -142,7 +164,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (!from_process_handle)
{
system_printf ("error opening process (%lu)", GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
return;
}
@@ -158,7 +180,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (!rc)
{
system_printf ("error opening thread token (%lu)", GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
CloseHandle (from_process_handle);
return;
}
@@ -185,7 +207,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating filemap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
}
if (check_and_dup_handle
(GetCurrentProcess (), from_process_handle, token_handle,
@@ -194,14 +216,14 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating attachmap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
}
CloseHandle (token_handle);
return;
}
tempnode = tempnode->next;
}
- header.error_code = EINVAL;
+ error_code (EINVAL);
CloseHandle (token_handle);
return;
}
@@ -220,13 +242,12 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (tempnode->shm_id == parameters.in.shm_id)
{
InterlockedIncrement (&tempnode->shmds->ds.shm_nattch);
- header.error_code = 0;
CloseHandle (token_handle);
return;
}
tempnode = tempnode->next;
}
- header.error_code = EINVAL;
+ error_code (EINVAL);
CloseHandle (token_handle);
return;
}
@@ -240,13 +261,12 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (tempnode->shm_id == parameters.in.shm_id)
{
InterlockedDecrement (&tempnode->shmds->ds.shm_nattch);
- header.error_code = 0;
CloseHandle (token_handle);
return;
}
tempnode = tempnode->next;
}
- header.error_code = EINVAL;
+ error_code (EINVAL);
CloseHandle (token_handle);
return;
}
@@ -256,7 +276,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
shmnode **tempnode = &shm_head;
while (*tempnode)
- {
+ {
if ((*tempnode)->shm_id == parameters.in.shm_id)
{
// unlink from the accessible node list
@@ -276,13 +296,12 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
delete_shmnode (&temp2);
}
- header.error_code = 0;
CloseHandle (token_handle);
return;
}
tempnode = &(*tempnode)->next;
}
- header.error_code = EINVAL;
+ error_code (EINVAL);
CloseHandle (token_handle);
return;
}
@@ -325,8 +344,6 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
* with the same key and size. Different modes is a ?.
*/
-
-
/* walk the list of known keys and return the id if found. remember, we are
* authoritative...
*/
@@ -341,7 +358,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (parameters.in.size
&& tempnode->shmds->ds.shm_segsz < parameters.in.size)
{
- header.error_code = EINVAL;
+ error_code (EINVAL);
CloseHandle (token_handle);
return;
}
@@ -351,7 +368,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if ((parameters.in.shmflg & IPC_CREAT)
&& (parameters.in.shmflg & IPC_EXCL))
{
- header.error_code = EEXIST;
+ error_code (EEXIST);
debug_printf
("attempt to exclusively create already created shm_area with key 0x%0qx",
parameters.in.key);
@@ -376,8 +393,8 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating filemap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
-/*mutex*/
+ error_code (EACCES);
+ /*mutex*/
CloseHandle (token_handle);
return;
}
@@ -388,8 +405,8 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating attachmap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
-/*mutex*/
+ error_code (EACCES);
+ /*mutex*/
CloseHandle (token_handle);
return;
}
@@ -432,7 +449,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
GetLastError ());
// free the mutex
// we can assume that it exists, and that it was an access problem.
- header.error_code = EACCES;
+ error_code (EACCES);
CloseHandle (token_handle);
return;
}
@@ -450,7 +467,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
/* FIXME free mutex */
CloseHandle (filemap);
- header.error_code = EEXIST;
+ error_code (EEXIST);
CloseHandle (token_handle);
return;
}
@@ -462,7 +479,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
CloseHandle (filemap);
/* FIXME free mutex */
- header.error_code = ENOENT;
+ error_code (ENOENT);
CloseHandle (token_handle);
return;
}
@@ -476,7 +493,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
CloseHandle (filemap);
//FIXME: close filemap and free the mutex
/* we couldn't access the mapped area with the requested permissions */
- header.error_code = EACCES;
+ error_code (EACCES);
CloseHandle (token_handle);
return;
}
@@ -491,13 +508,13 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
parameters.in.size %
getsystemallocgranularity (),
shmaname // object name
- );
+ );
conn->revert_to_self ();
if (attachmap == NULL)
{
system_printf ("failed to get shm attachmap");
- header.error_code = ENOMEM;
+ error_code (ENOMEM);
UnmapViewOfFile (mapptr);
CloseHandle (filemap);
/* FIXME exit the mutex */
@@ -509,7 +526,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
if (!shmtemp)
{
system_printf ("failed to malloc shm node");
- header.error_code = ENOMEM;
+ error_code (ENOMEM);
UnmapViewOfFile (mapptr);
CloseHandle (filemap);
CloseHandle (attachmap);
@@ -545,7 +562,7 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
/* we now have the area in the daemon list, opened.
- FIXME: leave the system wide shm mutex */
+ FIXME: leave the system wide shm mutex */
parameters.out.shm_id = tempnode->shm_id;
if (check_and_dup_handle (GetCurrentProcess (), from_process_handle,
@@ -556,9 +573,9 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating filemap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
CloseHandle (token_handle);
-/* mutex et al */
+ /* mutex et al */
return;
}
if (check_and_dup_handle (GetCurrentProcess (), from_process_handle,
@@ -569,20 +586,18 @@ client_request_shm::serve (transport_layer_base * conn, process_cache * cache)
{
system_printf ("error duplicating attachmap handle (%lu)",
GetLastError ());
- header.error_code = EACCES;
+ error_code (EACCES);
CloseHandle (from_process_handle);
CloseHandle (token_handle);
-/* more cleanup... yay! */
+ /* more cleanup... yay! */
return;
}
CloseHandle (token_handle);
-
return;
}
- header.error_code = ENOSYS;
+ error_code (ENOSYS);
CloseHandle (token_handle);
-
return;
}
diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h
index bc389c28a..a8b7dd2a6 100644
--- a/winsup/cygwin/cygserver_shm.h
+++ b/winsup/cygwin/cygserver_shm.h
@@ -51,14 +51,37 @@ struct shmnode
class client_request_shm : public client_request
{
public:
-#ifndef __INSIDE_CYGWIN__
- virtual void serve (transport_layer_base *conn, process_cache *cache);
-#endif
+#ifdef __INSIDE_CYGWIN__
client_request_shm (key_t ntype, size_t nsize, int shmflg);
- client_request_shm ();
client_request_shm (int ntype, int nshmid);
- union {
- struct {int type; pid_t cygpid; DWORD winpid; int shm_id; key_t key; size_t size; int shmflg; char sd_buf[4096];} in;
- struct {int shm_id; HANDLE filemap; HANDLE attachmap; key_t key;} out;
+#else
+ client_request_shm ();
+#endif
+
+ union
+ {
+ struct
+ {
+ int type;
+ pid_t cygpid;
+ DWORD winpid;
+ int shm_id;
+ key_t key;
+ size_t size;
+ int shmflg;
+ char sd_buf[4096]; // Must be the last item (variable length).
+ } in;
+ struct
+ {
+ int shm_id;
+ HANDLE filemap;
+ HANDLE attachmap;
+ key_t key;
+ } out;
} parameters;
+
+private:
+#ifndef __INSIDE_CYGWIN__
+ virtual void serve (transport_layer_base *, process_cache *);
+#endif
};
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 758d6eaec..fe4ea6911 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -572,29 +572,15 @@ fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
if (!from_master_ptr || !to_master_ptr)
return 0;
- client_request_attach_tty *request =
- new client_request_attach_tty ((DWORD) GetCurrentProcessId (),
- (DWORD) get_ttyp ()->master_pid,
- (HANDLE) get_ttyp ()->from_master,
- (HANDLE) get_ttyp ()->to_master);
-
- if (cygserver_request (request) != 0 ||
- request->header.error_code != 0)
- return 0;
+ client_request_attach_tty req ((DWORD) get_ttyp ()->master_pid,
+ (HANDLE) get_ttyp ()->from_master,
+ (HANDLE) get_ttyp ()->to_master);
-/*
- struct request_attach_tty req;
- INIT_REQUEST (req, CYGSERVER_REQUEST_ATTACH_TTY);
- req.pid = GetCurrentProcessId ();
- req.master_pid = get_ttyp ()->master_pid;
- req.from_master = get_ttyp ()->from_master;
- req.to_master = get_ttyp ()->to_master;
- if (cygserver_request ((struct request_header*) &req) != 0)
+ if (req.make_request () != 0 || req.error_code () != 0)
return 0;
-*/
- *from_master_ptr = request->from_master ();
- *to_master_ptr = request->to_master ();
- delete request;
+
+ *from_master_ptr = req.from_master ();
+ *to_master_ptr = req.to_master ();
return 1;
}
diff --git a/winsup/cygwin/include/cygwin/cygserver.h b/winsup/cygwin/include/cygwin/cygserver.h
index 8c9c0a93b..5873e2424 100755
--- a/winsup/cygwin/include/cygwin/cygserver.h
+++ b/winsup/cygwin/include/cygwin/cygserver.h
@@ -13,123 +13,162 @@ details. */
#ifndef _CYGSERVER_H_
#define _CYGSERVER_H_
-#define MAX_REQUEST_SIZE 128
+#ifdef __GNUC__
+#define CYGSERVER_PACKED __attribute__ ((packed))
+#else
+#define CYGSERVER_PACKED
+#endif
#define CYGWIN_SERVER_VERSION_MAJOR 1
#define CYGWIN_SERVER_VERSION_API 1
#define CYGWIN_SERVER_VERSION_MINOR 0
#define CYGWIN_SERVER_VERSION_PATCH 0
-
typedef enum {
- CYGSERVER_UNKNOWN=0,
- CYGSERVER_OK=1,
- CYGSERVER_DEAD=2
+ CYGSERVER_UNKNOWN = 0,
+ CYGSERVER_OK,
+ CYGSERVER_DEAD
} cygserver_states;
-typedef enum {
- CYGSERVER_REQUEST_INVALID = 0,
- CYGSERVER_REQUEST_GET_VERSION,
- CYGSERVER_REQUEST_ATTACH_TTY,
- CYGSERVER_REQUEST_SHUTDOWN,
- CYGSERVER_REQUEST_SHM_GET,
- CYGSERVER_REQUEST_LAST
-} cygserver_request_code;
-
-class request_header
+/*---------------------------------------------------------------------------*
+ * class client_request
+ *---------------------------------------------------------------------------*/
+
+class client_request
{
+protected:
+ typedef enum {
+ CYGSERVER_REQUEST_INVALID,
+ CYGSERVER_REQUEST_GET_VERSION,
+ CYGSERVER_REQUEST_SHUTDOWN,
+ CYGSERVER_REQUEST_ATTACH_TTY,
+ CYGSERVER_REQUEST_SHM,
+ CYGSERVER_REQUEST_LAST
+ } request_code_t;
+
+ struct header_t
+ {
+ size_t msglen;
+ union
+ {
+ request_code_t request_code;
+ ssize_t error_code;
+ };
+
+ header_t () {};
+ header_t (request_code_t, size_t);
+ } CYGSERVER_PACKED;
+
public:
- ssize_t cb;
- cygserver_request_code req_id;
- ssize_t error_code;
- request_header (cygserver_request_code id, ssize_t ncb) : cb (ncb), req_id (id), error_code (0) {} ;
-}
-#ifdef __GNUC__
- __attribute__ ((packed))
+#ifndef __INSIDE_CYGWIN__
+ static void handle_request (transport_layer_base *, class process_cache *);
#endif
-;
-extern void cygserver_init ();
+ client_request (request_code_t request_code,
+ void *buf = NULL,
+ size_t bufsiz = 0);
+ virtual ~client_request();
-#define INIT_REQUEST(req,id) \
- (req).header.cb = sizeof (req); \
- (req).header.req_id = id;
+ request_code_t request_code () const { return _header.request_code; }
-struct request_get_version
-{
- DWORD major, api, minor, patch;
-}
-#ifdef __GNUC__
- __attribute__ ((packed))
-#endif
-;
+ ssize_t error_code () const { return _header.error_code; };
+ void error_code (ssize_t error_code) { _header.error_code = error_code; };
-struct request_shutdown
-{
- int foo;
-}
-#ifdef __GNUC__
- __attribute__ ((packed))
-#endif
-;
+ size_t msglen () const { return _header.msglen; };
+ void msglen (size_t len) { _header.msglen = len; };
-struct request_attach_tty
-{
- DWORD pid, master_pid;
- HANDLE from_master, to_master;
-}
-#ifdef __GNUC__
- __attribute__ ((packed))
-#endif
-;
+ virtual int make_request ();
+
+private:
+ header_t _header;
+ void * const _buf;
+ const size_t _buflen;
-class client_request
-{
-public:
- client_request (cygserver_request_code id, ssize_t data_size);
- void send (transport_layer_base *conn);
#ifndef __INSIDE_CYGWIN__
+ void handle (transport_layer_base *, class process_cache *);
virtual void serve (transport_layer_base *, class process_cache *) = 0;
#endif
- cygserver_request_code req_id () {return header.req_id;};
- virtual ~client_request();
- request_header header;
- char *buffer;
+
+ void send (transport_layer_base *);
};
+/*---------------------------------------------------------------------------*
+ * class client_request_get_version
+ *---------------------------------------------------------------------------*/
+
class client_request_get_version : public client_request
{
+private:
+ struct request_get_version
+ {
+ DWORD major, api, minor, patch;
+ } CYGSERVER_PACKED;
+
public:
+ client_request_get_version ();
+
+ void check_version () const;
+
+private:
+ struct request_get_version version;
+
#ifndef __INSIDE_CYGWIN__
- virtual void serve (transport_layer_base *conn, class process_cache *cache);
+ virtual void serve (transport_layer_base *, class process_cache *);
#endif
- client_request_get_version::client_request_get_version();
- struct request_get_version version;
};
+/*---------------------------------------------------------------------------*
+ * class client_request_shutdown
+ *
+ * Nb. This whole class is only !__INSIDE_CYGWIN__ since it is used
+ * solely by cygserver itself.
+ *---------------------------------------------------------------------------*/
+
+#ifndef __INSIDE_CYGWIN__
+
class client_request_shutdown : public client_request
{
public:
-#ifndef __INSIDE_CYGWIN__
- virtual void serve (transport_layer_base *conn, class process_cache *cache);
-#endif
client_request_shutdown ();
+
+private:
+ virtual void serve (transport_layer_base *, class process_cache *);
};
+#endif /* !__INSIDE_CYGWIN__ */
+
+/*---------------------------------------------------------------------------*
+ * class client_request_attach_tty
+ *---------------------------------------------------------------------------*/
+
class client_request_attach_tty : public client_request
{
+private:
+ struct request_attach_tty
+ {
+ DWORD pid, master_pid;
+ HANDLE from_master, to_master;
+ } CYGSERVER_PACKED;
+
public:
-#ifndef __INSIDE_CYGWIN__
- virtual void serve (transport_layer_base *conn, class process_cache *cache);
- client_request_attach_tty ();
+#ifdef __INSIDE_CYGWIN__
+ client_request_attach_tty (DWORD nmaster_pid,
+ HANDLE nfrom_master, HANDLE nto_master);
#else
- client_request_attach_tty (DWORD npid, DWORD nmaster_pid, HANDLE nfrom_master, HANDLE nto_master);
+ client_request_attach_tty ();
#endif
- HANDLE from_master () {return req.from_master;};
- HANDLE to_master () {return req.to_master;};
+
+ HANDLE from_master () const { return req.from_master; };
+ HANDLE to_master () const { return req.to_master; };
+
+private:
struct request_attach_tty req;
+
+#ifndef __INSIDE_CYGWIN__
+ virtual void serve (transport_layer_base *, class process_cache *);
+#endif
};
-extern int cygserver_request (client_request *);
+extern void cygserver_init ();
#endif /* _CYGSERVER_H_ */
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
index d22217f72..7d52fa3b8 100644
--- a/winsup/cygwin/shm.cc
+++ b/winsup/cygwin/shm.cc
@@ -69,15 +69,13 @@ getsystemallocgranularity ()
* Used for: SHM_ATTACH, SHM_DETACH, SHM_REATTACH, and SHM_DEL.
*/
client_request_shm::client_request_shm (int ntype, int nshmid)
- : client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
+ : client_request (CYGSERVER_REQUEST_SHM, &parameters, sizeof (parameters))
{
assert (ntype == SHM_REATTACH \
|| ntype == SHM_ATTACH \
|| ntype == SHM_DETACH \
|| ntype == SHM_DEL);
- buffer = (char *) &parameters;
-
parameters.in.type = ntype;
parameters.in.cygpid = getpid ();
parameters.in.winpid = GetCurrentProcessId ();
@@ -86,20 +84,21 @@ client_request_shm::client_request_shm (int ntype, int nshmid)
assert (parameters.in.cygpid > 0);
assert (parameters.in.winpid != 0);
- debug_printf ("created: ntype = %d, shmid = %d", ntype, nshmid);
+ msglen (sizeof (parameters.in) - sizeof (parameters.in.sd_buf));
+
+ syscall_printf ("created: type = %d, shmid = %d",
+ parameters.in.type, parameters.in.shm_id);
}
/*
* Used for: SHM_CREATE.
*/
client_request_shm::client_request_shm (key_t nkey, size_t nsize, int nshmflg)
- : client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
+ : client_request (CYGSERVER_REQUEST_SHM, &parameters, sizeof (parameters))
{
assert (nkey != (key_t) -1);
assert (nsize >= 0);
- buffer = (char *) &parameters;
-
parameters.in.type = SHM_CREATE;
parameters.in.cygpid = getpid ();
parameters.in.winpid = GetCurrentProcessId ();
@@ -110,16 +109,29 @@ client_request_shm::client_request_shm (key_t nkey, size_t nsize, int nshmflg)
assert (parameters.in.cygpid > 0);
assert (parameters.in.winpid != 0);
+ DWORD sd_buf_size = 0;
+
if (wincap.has_security ())
{
SECURITY_ATTRIBUTES sa = sec_none;
- set_security_attribute (nshmflg & 0777, &sa,
- parameters.in.sd_buf,
- sizeof (parameters.in.sd_buf));
+ sd_buf_size = sizeof (parameters.in.sd_buf);
+
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) parameters.in.sd_buf;
+
+ InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION);
+
+ alloc_sd (geteuid32 (), getegid32 (), parameters.in.shmflg & 0777,
+ psd, &sd_buf_size);
}
- debug_printf ("created: key = 0x%x%08x, size = %ld, shmflg = %o",
- hi_ulong(nkey), lo_ulong(nkey), nsize, nshmflg);
+ msglen (sizeof (parameters.in) - sizeof (parameters.in.sd_buf)
+ + sd_buf_size);
+
+ syscall_printf (("created: type = %d, "
+ "key = 0x%x%08x, size = %ld, shmflg = %o"),
+ parameters.in.type,
+ hi_ulong(parameters.in.key), lo_ulong(parameters.in.key),
+ parameters.in.size, parameters.in.shmflg);
}
static shmnode *shm_head = NULL;
@@ -268,20 +280,17 @@ shmat (int shmid, const void *shmaddr, int shmflg)
/* couldn't find a currently open shm control area for the key - probably because
* shmget hasn't been called.
* Allocate a new control block - this has to be handled by the daemon */
- client_request_shm *req = new client_request_shm (SHM_REATTACH, shmid);
+ client_request_shm req (SHM_REATTACH, shmid);
- int rc;
- if ((rc = cygserver_request (req)))
+ if (req.make_request () == -1)
{
- delete req;
set_errno (ENOSYS); /* daemon communication failed */
return (void *) -1;
}
- if (req->header.error_code) /* shm_get failed in the daemon */
+ if (req.error_code ()) /* shm_get failed in the daemon */
{
- set_errno (req->header.error_code);
- delete req;
+ set_errno (req.error_code ());
return (void *) -1;
}
@@ -290,11 +299,10 @@ shmat (int shmid, const void *shmaddr, int shmflg)
* FIXME: make this a method of shmnode ?
*/
tempnode =
- build_inprocess_shmds (req->parameters.out.filemap,
- req->parameters.out.attachmap,
- req->parameters.out.key,
- req->parameters.out.shm_id);
- delete req;
+ build_inprocess_shmds (req.parameters.out.filemap,
+ req.parameters.out.attachmap,
+ req.parameters.out.key,
+ req.parameters.out.shm_id);
if (!tempnode)
return (void *) -1;
@@ -320,13 +328,12 @@ shmat (int shmid, const void *shmaddr, int shmflg)
return (void *) -1;
}
/* tell the daemon we have attached */
- client_request_shm *req = new client_request_shm (SHM_ATTACH, shmid);
- int rc;
- if ((rc = cygserver_request (req)))
+ client_request_shm req (SHM_ATTACH, shmid);
+
+ if (req.make_request () == -1)
{
debug_printf ("failed to tell daemon that we have attached");
}
- delete req;
_shmattach *attachnode = new _shmattach;
attachnode->data = rv;
@@ -368,14 +375,12 @@ shmdt (const void *shmaddr)
UnmapViewOfFile (attachnode->data);
/* tell the daemon we have attached */
- client_request_shm *req =
- new client_request_shm (SHM_DETACH, tempnode->shm_id);
- int rc;
- if ((rc = cygserver_request (req)))
+ client_request_shm req (SHM_DETACH, tempnode->shm_id);
+
+ if (req.make_request () == -1)
{
debug_printf ("failed to tell daemon that we have detached");
}
- delete req;
return 0;
}
@@ -392,20 +397,17 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
/* couldn't find a currently open shm control area for the key - probably because
* shmget hasn't been called.
* Allocate a new control block - this has to be handled by the daemon */
- client_request_shm *req = new client_request_shm (SHM_REATTACH, shmid);
+ client_request_shm req (SHM_REATTACH, shmid);
- int rc;
- if ((rc = cygserver_request (req)))
+ if (req.make_request () == -1)
{
- delete req;
set_errno (ENOSYS); /* daemon communication failed */
return -1;
}
- if (req->header.error_code) /* shm_get failed in the daemon */
+ if (req.error_code ()) /* shm_get failed in the daemon */
{
- set_errno (req->header.error_code);
- delete req;
+ set_errno (req.error_code ());
return -1;
}
@@ -414,11 +416,10 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
* FIXME: make this a method of shmnode ?
*/
tempnode =
- build_inprocess_shmds (req->parameters.out.filemap,
- req->parameters.out.attachmap,
- req->parameters.out.key,
- req->parameters.out.shm_id);
- delete req;
+ build_inprocess_shmds (req.parameters.out.filemap,
+ req.parameters.out.attachmap,
+ req.parameters.out.key,
+ req.parameters.out.shm_id);
if (!tempnode)
return -1;
}
@@ -444,19 +445,17 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
* daemon has an attach. The daemon gets asked to detach immediately.
*/
//waiting for the daemon to handle terminating process's
- client_request_shm *req = new client_request_shm (SHM_DEL, shmid);
- int rc;
- if ((rc = cygserver_request (req)))
+ client_request_shm req (SHM_DEL, shmid);
+
+ if (req.make_request () == -1)
{
- delete req;
set_errno (ENOSYS); /* daemon communication failed */
return -1;
}
- if (req->header.error_code) /* shm_del failed in the daemon */
+ if (req.error_code ()) /* shm_del failed in the daemon */
{
- set_errno (req->header.error_code);
- delete req;
+ set_errno (req.error_code ());
return -1;
}
@@ -528,20 +527,17 @@ shmget (key_t key, size_t size, int shmflg)
}
/* couldn't find a currently open shm control area for the key.
* Allocate a new control block - this has to be handled by the daemon */
- client_request_shm *req = new client_request_shm (key, size, shmflg);
+ client_request_shm req (key, size, shmflg);
- int rc;
- if ((rc = cygserver_request (req)))
+ if (req.make_request () == -1)
{
- delete req;
set_errno (ENOSYS); /* daemon communication failed */
return -1;
}
- if (req->header.error_code) /* shm_get failed in the daemon */
+ if (req.error_code ()) /* shm_get failed in the daemon */
{
- set_errno (req->header.error_code);
- delete req;
+ set_errno (req.error_code ());
return -1;
}
@@ -549,11 +545,10 @@ shmget (key_t key, size_t size, int shmflg)
* This tests security automagically
* FIXME: make this a method of shmnode ?
*/
- shmnode *shmtemp = build_inprocess_shmds (req->parameters.out.filemap,
- req->parameters.out.attachmap,
+ shmnode *shmtemp = build_inprocess_shmds (req.parameters.out.filemap,
+ req.parameters.out.attachmap,
key,
- req->parameters.out.shm_id);
- delete req;
+ req.parameters.out.shm_id);
if (shmtemp)
return shmtemp->shm_id;
return -1;