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:
Diffstat (limited to 'winsup/cygserver')
-rw-r--r--winsup/cygserver/client.cc529
-rw-r--r--winsup/cygserver/cygserver.cc774
-rw-r--r--winsup/cygserver/ipc.h84
-rw-r--r--winsup/cygserver/process.cc432
-rw-r--r--winsup/cygserver/shm.cc896
-rwxr-xr-xwinsup/cygserver/shm.h147
-rw-r--r--winsup/cygserver/threaded_queue.cc408
-rw-r--r--winsup/cygserver/transport.cc51
-rw-r--r--winsup/cygserver/transport_pipes.cc363
-rw-r--r--winsup/cygserver/transport_sockets.cc387
-rw-r--r--winsup/cygserver/woutsup.h110
11 files changed, 0 insertions, 4181 deletions
diff --git a/winsup/cygserver/client.cc b/winsup/cygserver/client.cc
deleted file mode 100644
index 138c9ddc0..000000000
--- a/winsup/cygserver/client.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-/* cygserver_client.cc
-
- Copyright 2001, 2002 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. */
-
-/* to allow this to link into cygwin and the .dll, a little magic is needed. */
-#ifdef __OUTSIDE_CYGWIN__
-#include "woutsup.h"
-#else
-#include "winsup.h"
-#endif
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "cygerrno.h"
-#include "cygserver_shm.h"
-#include "safe_memory.h"
-
-#include "cygwin/cygserver.h"
-#include "cygwin/cygserver_transport.h"
-
-int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children.
-
-/* On by default during development. For release, we probably want off
- * by default.
- */
-bool allow_daemon = true; // Nb: inherited by children.
-
-client_request_get_version::client_request_get_version ()
- : client_request (CYGSERVER_REQUEST_GET_VERSION, &version, sizeof (version))
-{
- msglen (0); // No parameters for request.
-
- // verbose: syscall_printf ("created");
-}
-
-/*
- * client_request_get_version::check_version ()
- *
- * The major version and API version numbers must match exactly. An
- * older than expected minor version number is accepted (as long as
- * the first numbers match, that is).
- */
-
-bool
-client_request_get_version::check_version () const
-{
- const bool ok = (version.major == CYGWIN_SERVER_VERSION_MAJOR
- && version.api == CYGWIN_SERVER_VERSION_API
- && version.minor <= CYGWIN_SERVER_VERSION_MINOR);
-
- if (!ok)
- syscall_printf (("incompatible version of cygwin server: "
- "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);
-
- return ok;
-}
-
-#ifdef __INSIDE_CYGWIN__
-
-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))
-{
- 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);
-}
-
-#else /* !__INSIDE_CYGWIN__ */
-
-client_request_attach_tty::client_request_attach_tty ()
- : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
-{
- // verbose: syscall_printf ("created");
-}
-
-#endif /* __INSIDE_CYGWIN__ */
-
-/*
- * client_request_attach_tty::send ()
- *
- * Wraps the base method to provide error handling support. If the
- * reply contains a body but is flagged as an error, close any handles
- * that have been returned by cygserver and then discard the message
- * body, i.e. the client either sees a successful result with handles
- * or an unsuccessful result with no handles.
- */
-
-void
-client_request_attach_tty::send (transport_layer_base * const conn)
-{
- client_request::send (conn);
-
- if (msglen () && error_code ())
- {
- if (from_master ())
- CloseHandle (from_master ());
- if (to_master ())
- CloseHandle (to_master ());
- msglen (0);
- }
-}
-
-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 * const conn)
-{
- assert (conn);
- assert (!(msglen () && !_buf)); // i.e., msglen () implies _buf
- assert (msglen () <= _buflen);
-
- {
- const ssize_t count = conn->write (&_header, sizeof (_header));
-
- if (count != sizeof (_header))
- {
- assert (errno);
- 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 (msglen ())
- {
- const ssize_t count = conn->write (_buf, msglen ());
-
- if (count == -1 || (size_t) count != msglen ())
- {
- assert (errno);
- error_code (errno);
- syscall_printf (("request body write failure: "
- "only %ld bytes sent of %ld, "
- "error = %d(%lu)"),
- count, msglen (),
- errno, GetLastError ());
- return;
- }
- }
-
- // verbose: syscall_printf ("request sent (%ld + %ld bytes)",
- // sizeof (_header), msglen ());
-
- {
- const ssize_t count = conn->read (&_header, sizeof (_header));
-
- if (count != sizeof (_header))
- {
- assert (errno);
- 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 (msglen () && !_buf)
- {
- system_printf ("no client buffer for reply body: %ld bytes needed",
- msglen ());
- error_code (EINVAL);
- return;
- }
-
- if (msglen () > _buflen)
- {
- system_printf (("client buffer too small for reply body: "
- "have %ld bytes and need %ld"),
- _buflen, msglen ());
- error_code (EINVAL);
- return;
- }
-
- if (msglen ())
- {
- const ssize_t count = conn->read (_buf, msglen ());
-
- if (count == -1 || (size_t) count != msglen ())
- {
- assert (errno);
- error_code (errno);
- syscall_printf (("reply body read failure: "
- "only %ld bytes received of %ld, "
- "error = %d(%lu)"),
- count, msglen (),
- errno, GetLastError ());
- return;
- }
- }
-
- // verbose: syscall_printf ("reply received (%ld + %ld bytes)",
- // sizeof (_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 *const conn,
- process_cache *const 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)", count);
- }
-
- client_request *req = NULL;
-
- switch (header.request_code)
- {
- case CYGSERVER_REQUEST_GET_VERSION:
- req = safe_new0 (client_request_get_version);
- break;
- case CYGSERVER_REQUEST_SHUTDOWN:
- req = safe_new0 (client_request_shutdown);
- break;
- case CYGSERVER_REQUEST_ATTACH_TTY:
- req = safe_new0 (client_request_attach_tty);
- break;
- case CYGSERVER_REQUEST_SHM:
- req = safe_new0 (client_request_shm);
- break;
- default:
- syscall_printf ("unknown request code %d received: request ignored",
- header.request_code);
- return;
- }
-
- assert (req);
-
- req->msglen (header.msglen);
- req->handle (conn, cache);
-
- safe_delete (req);
-
-#ifndef DEBUGGING
- printf ("."); // A little noise when we're being quiet.
-#endif
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-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
-client_request::make_request ()
-{
- assert (cygserver_running == CYGSERVER_UNKNOWN \
- || cygserver_running == CYGSERVER_OK \
- || cygserver_running == CYGSERVER_UNAVAIL);
-
- if (cygserver_running == CYGSERVER_UNKNOWN)
- cygserver_init ();
-
- assert (cygserver_running == CYGSERVER_OK \
- || cygserver_running == CYGSERVER_UNAVAIL);
-
- /* Don't retry every request if the server's not there */
- if (cygserver_running == CYGSERVER_UNAVAIL)
- {
- syscall_printf ("cygserver un-available");
- error_code (ENOSYS);
- return -1;
- }
-
- transport_layer_base *const transport = create_server_transport ();
-
- assert (transport);
-
- if (transport->connect () == -1)
- {
- if (errno)
- error_code (errno);
- else
- error_code (ENOSYS);
- safe_delete (transport);
- return -1;
- }
-
- // verbose: debug_printf ("connected to server %p", transport);
-
- send (transport);
-
- safe_delete (transport);
-
- 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,
- process_cache *const cache)
-{
- if (msglen () && !_buf)
- {
- system_printf ("no buffer for request body: %ld bytes needed",
- msglen ());
- error_code (EINVAL);
- return;
- }
-
- if (msglen () > _buflen)
- {
- system_printf (("buffer too small for request body: "
- "have %ld bytes and need %ld"),
- _buflen, msglen ());
- error_code (EINVAL);
- return;
- }
-
- if (msglen ())
- {
- const ssize_t count = conn->read (_buf, msglen ());
-
- if (count == -1 || (size_t) count != msglen ())
- {
- assert (errno);
- error_code (errno);
- syscall_printf (("request body read failure: "
- "only %ld bytes received of %ld, "
- "error = %d(%lu)"),
- count, msglen (),
- errno, GetLastError ());
- return;
- }
- }
-
- // verbose: syscall_printf ("request received (%ld + %ld bytes)",
- // sizeof (_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))
- {
- assert (errno);
- 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 (msglen ())
- {
- const ssize_t count = conn->write (_buf, msglen ());
-
- if (count == -1 || (size_t) count != msglen ())
- {
- assert (errno);
- error_code (errno);
- syscall_printf (("reply body write failure: "
- "only %ld bytes sent of %ld, "
- "error = %d(%lu)"),
- count, msglen (),
- errno, GetLastError ());
- return;
- }
- }
-
- // verbose: syscall_printf ("reply sent (%ld + %ld bytes)",
- // sizeof (_header), msglen ());
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-bool
-check_cygserver_available ()
-{
- assert (cygserver_running == CYGSERVER_UNKNOWN \
- || cygserver_running == CYGSERVER_UNAVAIL);
-
- cygserver_running = CYGSERVER_OK; // For make_request ().
-
- client_request_get_version req;
-
- /* 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 (req.make_request () == -1)
- return false;
-
- /* We connected to the server but something went wrong after that
- * (in sending the message, in cygserver itself, or in receiving the
- * reply).
- */
- if (req.error_code ())
- {
- syscall_printf ("failure in cygserver version request: %d",
- req.error_code ());
- syscall_printf ("process will continue without cygserver support");
- return false;
- }
-
- return req.check_version ();
-}
-
-void
-cygserver_init ()
-{
- if (!allow_daemon)
- {
- syscall_printf ("cygserver use disabled in client");
- cygserver_running = CYGSERVER_UNAVAIL;
- return;
- }
-
- assert (cygserver_running == CYGSERVER_UNKNOWN \
- || cygserver_running == CYGSERVER_OK \
- || cygserver_running == CYGSERVER_UNAVAIL);
-
- if (cygserver_running == CYGSERVER_OK)
- return;
-
- if (!check_cygserver_available ())
- cygserver_running = CYGSERVER_UNAVAIL;
-}
diff --git a/winsup/cygserver/cygserver.cc b/winsup/cygserver/cygserver.cc
deleted file mode 100644
index 0c0740379..000000000
--- a/winsup/cygserver/cygserver.cc
+++ /dev/null
@@ -1,774 +0,0 @@
-/* cygserver.cc
-
- Copyright 2001, 2002 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. */
-
-#include "woutsup.h"
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <getopt.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "cygerrno.h"
-#include "cygwin_version.h"
-
-#include "cygwin/cygserver.h"
-#include "cygwin/cygserver_process.h"
-#include "cygwin/cygserver_transport.h"
-
-// Version string.
-static const char version[] = "$Revision$";
-
-/*
- * Support function for the XXX_printf () macros in "woutsup.h".
- * Copied verbatim from "strace.cc".
- */
-static int
-getfunc (char *in_dst, const char *func)
-{
- const char *p;
- const char *pe;
- char *dst = in_dst;
- for (p = func; (pe = strchr (p, '(')); p = pe + 1)
- if (isalnum ((int)pe[-1]) || pe[-1] == '_')
- break;
- else if (isspace ((int)pe[-1]))
- {
- pe--;
- break;
- }
- if (!pe)
- pe = strchr (func, '\0');
- for (p = pe; p > func; p--)
- if (p != pe && *p == ' ')
- {
- p++;
- break;
- }
- if (*p == '*')
- p++;
- while (p < pe)
- *dst++ = *p++;
-
- *dst++ = ':';
- *dst++ = ' ';
- *dst = '\0';
-
- return dst - in_dst;
-}
-
-/*
- * Support function for the XXX_printf () macros in "woutsup.h".
- */
-extern "C" void
-__cygserver__printf (const char *const function, const char *const fmt, ...)
-{
- const DWORD lasterror = GetLastError ();
- const int lasterrno = errno;
-
- va_list ap;
-
- char *const buf = (char *) alloca (BUFSIZ);
-
- assert (buf);
-
- int len = 0;
-
- if (function)
- len += getfunc (buf, function);
-
- va_start (ap, fmt);
- len += vsnprintf (buf + len, BUFSIZ - len, fmt, ap);
- va_end (ap);
-
- len += snprintf (buf + len, BUFSIZ - len, "\n");
-
- const int actual = (len > BUFSIZ ? BUFSIZ : len);
-
- write (2, buf, actual);
-
- errno = lasterrno;
- SetLastError (lasterror);
-
- return;
-}
-
-#ifdef DEBUGGING
-
-int __stdcall
-__set_errno (const char *func, int ln, int val)
-{
- debug_printf ("%s:%d val %d", func, ln, val);
- return _impure_ptr->_errno = val;
-}
-
-#endif /* DEBUGGING */
-
-GENERIC_MAPPING access_mapping;
-
-static BOOL
-setup_privileges ()
-{
- BOOL rc, ret_val;
- HANDLE hToken = NULL;
- TOKEN_PRIVILEGES sPrivileges;
-
- rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ;
- if (!rc)
- {
- system_printf ("error opening process token (%lu)", GetLastError ());
- ret_val = FALSE;
- goto out;
- }
- rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid);
- if (!rc)
- {
- system_printf ("error getting privilege luid (%lu)", GetLastError ());
- ret_val = FALSE;
- goto out;
- }
- sPrivileges.PrivilegeCount = 1 ;
- sPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
- rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ;
- if (!rc)
- {
- system_printf ("error adjusting privilege level. (%lu)",
- GetLastError ());
- ret_val = FALSE;
- goto out;
- }
-
- access_mapping.GenericRead = FILE_READ_DATA;
- access_mapping.GenericWrite = FILE_WRITE_DATA;
- access_mapping.GenericExecute = 0;
- access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA;
-
- ret_val = TRUE;
-
-out:
- CloseHandle (hToken);
- return ret_val;
-}
-
-int
-check_and_dup_handle (HANDLE from_process, HANDLE to_process,
- HANDLE from_process_token,
- DWORD access,
- HANDLE from_handle,
- HANDLE *to_handle_ptr, BOOL bInheritHandle = FALSE)
-{
- HANDLE local_handle = NULL;
- int ret_val = EACCES;
-
- if (from_process != GetCurrentProcess ())
- {
- if (!DuplicateHandle (from_process, from_handle,
- GetCurrentProcess (), &local_handle,
- 0, bInheritHandle,
- DUPLICATE_SAME_ACCESS))
- {
- system_printf ("error getting handle(%u) to server (%lu)",
- (unsigned int)from_handle, GetLastError ());
- goto out;
- }
- } else
- local_handle = from_handle;
-
- if (!wincap.has_security ())
- assert (!from_process_token);
- else
- {
- char sd_buf [1024];
- PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) &sd_buf;
- DWORD bytes_needed;
- PRIVILEGE_SET ps;
- DWORD ps_len = sizeof (ps);
- BOOL status;
-
- if (!GetKernelObjectSecurity (local_handle,
- (OWNER_SECURITY_INFORMATION
- | GROUP_SECURITY_INFORMATION
- | DACL_SECURITY_INFORMATION),
- sd, sizeof (sd_buf), &bytes_needed))
- {
- system_printf ("error getting handle SD (%lu)", GetLastError ());
- goto out;
- }
-
- MapGenericMask (&access, &access_mapping);
-
- if (!AccessCheck (sd, from_process_token, access, &access_mapping,
- &ps, &ps_len, &access, &status))
- {
- system_printf ("error checking access rights (%lu)",
- GetLastError ());
- goto out;
- }
-
- if (!status)
- {
- system_printf ("access to object denied");
- goto out;
- }
- }
-
- if (!DuplicateHandle (from_process, from_handle,
- to_process, to_handle_ptr,
- access, bInheritHandle, 0))
- {
- system_printf ("error getting handle to client (%lu)", GetLastError ());
- goto out;
- }
-
- // verbose: debug_printf ("Duplicated %p to %p", from_handle, *to_handle_ptr);
-
- ret_val = 0;
-
- out:
- if (local_handle && from_process != GetCurrentProcess ())
- CloseHandle (local_handle);
-
- return (ret_val);
-}
-
-/*
- * client_request_attach_tty::serve ()
- */
-
-void
-client_request_attach_tty::serve (transport_layer_base *const conn,
- process_cache *)
-{
- assert (conn);
-
- assert (!error_code ());
-
- if (!wincap.has_security ())
- {
- syscall_printf ("operation only supported on systems with security");
- error_code (EINVAL);
- msglen (0);
- return;
- }
-
- if (msglen () != sizeof (req))
- {
- syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
- sizeof (req), msglen ());
- error_code (EINVAL);
- msglen (0);
- return;
- }
-
- 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,
- // req.pid);
-
- // verbose: debug_printf ("opening process %ld", 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);
-
- const HANDLE to_process_handle =
- OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
-
- if (!to_process_handle)
- {
- 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");
- 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, error = %lu",
- GetLastError ());
- CloseHandle (from_process_handle);
- CloseHandle (to_process_handle);
- error_code (EACCES);
- return;
- }
-
- // 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, to_master,
- req.pid, req.from_master, req.to_master);
-
- return;
-}
-
-void
-client_request_get_version::serve (transport_layer_base *, process_cache *)
-{
- 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 server_request : public queue_request
-{
-public:
- server_request (transport_layer_base *const conn, process_cache *const cache)
- : _conn (conn), _cache (cache)
- {}
-
- virtual ~server_request ()
- {
- safe_delete (_conn);
- }
-
- virtual void process ()
- {
- client_request::handle_request (_conn, _cache);
- }
-
-private:
- transport_layer_base *const _conn;
- process_cache *const _cache;
-};
-
-class server_submission_loop : public queue_submission_loop
-{
-public:
- server_submission_loop (threaded_queue *const queue,
- transport_layer_base *const transport,
- process_cache *const cache)
- : queue_submission_loop (queue, false),
- _transport (transport),
- _cache (cache)
- {
- assert (_transport);
- assert (_cache);
- }
-
-private:
- transport_layer_base *const _transport;
- process_cache *const _cache;
-
- virtual void request_loop ();
-};
-
-/* FIXME: this is a little ugly. What we really want is to wait on
- * two objects: one for the pipe/socket, and one for being told to
- * shutdown. Otherwise this will stay a problem (we won't actually
- * shutdown until the request _AFTER_ the shutdown request. And
- * sending ourselves a request is ugly
- */
-void
-server_submission_loop::request_loop ()
-{
- /* I'd like the accepting thread's priority to be above any "normal"
- * thread in the system to avoid overflowing the listen queue (for
- * sockets; similar issues exist for named pipes); but, for example,
- * a normal priority thread in a foregrounded process is boosted to
- * THREAD_PRIORITY_HIGHEST (AFAICT). Thus try to set the current
- * thread's priority to a level one above that. This fails on
- * win9x/ME so assume any failure in that call is due to that and
- * simply call again at one priority level lower.
- */
- if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1))
- if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST))
- debug_printf ("failed to raise accept thread priority, error = %lu",
- GetLastError ());
-
- while (_running)
- {
- bool recoverable = false;
- transport_layer_base *const conn = _transport->accept (&recoverable);
- if (!conn && !recoverable)
- {
- system_printf ("fatal error on IPC transport: closing down");
- return;
- }
- // EINTR probably implies a shutdown request; so back off for a
- // moment to let the main thread take control, otherwise the
- // server spins here receiving EINTR repeatedly since the signal
- // handler in the main thread doesn't get a chance to be called.
- if (!conn && errno == EINTR)
- {
- if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL))
- debug_printf ("failed to reset thread priority, error = %lu",
- GetLastError ());
-
- Sleep (0);
- if (!SetThreadPriority (GetCurrentThread (),
- THREAD_PRIORITY_HIGHEST + 1))
- if (!SetThreadPriority (GetCurrentThread (),
- THREAD_PRIORITY_HIGHEST))
- debug_printf ("failed to raise thread priority, error = %lu",
- GetLastError ());
- }
- if (conn)
- _queue->add (safe_new (server_request, conn, _cache));
- }
-}
-
-client_request_shutdown::client_request_shutdown ()
- : client_request (CYGSERVER_REQUEST_SHUTDOWN)
-{
- // verbose: syscall_printf ("created");
-}
-
-void
-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_
- */
-
- kill (getpid (), SIGINT);
-
- msglen (0);
-}
-
-static sig_atomic_t shutdown_server = false;
-
-static void
-handle_signal (const int signum)
-{
- /* any signal makes us die :} */
-
- shutdown_server = true;
-}
-
-/*
- * print_usage ()
- */
-
-static void
-print_usage (const char *const pgm)
-{
- printf ("Usage: %s [OPTIONS]\n", pgm);
- printf (" -c, --cleanup-threads number of cleanup threads to use\n");
- printf (" -h, --help output usage information and exit\n");
- printf (" -r, --request-threads number of request threads to use\n");
- printf (" -s, --shutdown shutdown the daemon\n");
- printf (" -v, --version output version information and exit\n");
-}
-
-/*
- * print_version ()
- */
-
-static void
-print_version (const char *const pgm)
-{
- char *vn = NULL;
-
- const char *const colon = strchr (version, ':');
-
- if (!colon)
- {
- vn = strdup ("?");
- }
- else
- {
- vn = strdup (colon + 2); // Skip ": "
-
- char *const spc = strchr (vn, ' ');
-
- if (spc)
- *spc = '\0';
- }
-
- char buf[200];
- snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s",
- cygwin_version.dll_major / 1000,
- cygwin_version.dll_major % 1000,
- cygwin_version.dll_minor,
- cygwin_version.api_major,
- cygwin_version.api_minor,
- cygwin_version.shared_data,
- CYGWIN_SERVER_VERSION_MAJOR,
- CYGWIN_SERVER_VERSION_API,
- CYGWIN_SERVER_VERSION_MINOR,
- CYGWIN_SERVER_VERSION_PATCH,
- cygwin_version.mount_registry,
- cygwin_version.dll_build_date);
-
- printf ("%s (cygwin) %s\n", pgm, vn);
- printf ("API version %s\n", buf);
- printf ("Copyright 2001, 2002 Red Hat, Inc.\n");
- printf ("Compiled on %s\n", __DATE__);
-
- free (vn);
-}
-
-/*
- * main ()
- */
-
-int
-main (const int argc, char *argv[])
-{
- const struct option longopts[] = {
- {"cleanup-threads", required_argument, NULL, 'c'},
- {"help", no_argument, NULL, 'h'},
- {"request-threads", required_argument, NULL, 'r'},
- {"shutdown", no_argument, NULL, 's'},
- {"version", no_argument, NULL, 'v'},
- {0, no_argument, NULL, 0}
- };
-
- const char opts[] = "c:hr:sv";
-
- int cleanup_threads = 2;
- int request_threads = 10;
- bool shutdown = false;
-
- const char *pgm = NULL;
-
- if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/')))
- pgm = *argv;
- else
- pgm++;
-
- wincap.init ();
- if (wincap.has_security ())
- setup_privileges ();
-
- int opt;
-
- while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
- switch (opt)
- {
- case 'c':
- cleanup_threads = atoi (optarg);
- if (cleanup_threads <= 0)
- {
- fprintf (stderr,
- "%s: number of cleanup threads must be positive\n",
- pgm);
- exit (1);
- }
- break;
-
- case 'h':
- print_usage (pgm);
- return 0;
-
- case 'r':
- request_threads = atoi (optarg);
- if (request_threads <= 0)
- {
- fprintf (stderr,
- "%s: number of request threads must be positive\n",
- pgm);
- exit (1);
- }
- break;
-
- case 's':
- shutdown = true;
- break;
-
- case 'v':
- print_version (pgm);
- return 0;
-
- case '?':
- fprintf (stderr, "Try `%s --help' for more information.\n", pgm);
- exit (1);
- }
-
- if (optind != argc)
- {
- fprintf (stderr, "%s: too many arguments\n", pgm);
- exit (1);
- }
-
- if (shutdown)
- {
- /* Setting `cygserver_running' stops the request code making a
- * version request, which is not much to the point.
- */
- cygserver_running = CYGSERVER_OK;
-
- client_request_shutdown req;
-
- if (req.make_request () == -1 || req.error_code ())
- {
- fprintf (stderr, "%s: shutdown request failed: %s\n",
- pgm, strerror (req.error_code ()));
- exit (1);
- }
-
- // FIXME: It would be nice to wait here for the daemon to exit.
-
- return 0;
- }
-
-#define SIGHANDLE(SIG) \
- do \
- { \
- struct sigaction act; \
- \
- act.sa_handler = &handle_signal; \
- act.sa_mask = 0; \
- act.sa_flags = 0; \
- \
- if (sigaction (SIG, &act, NULL) == -1) \
- { \
- system_printf ("failed to install handler for " #SIG ": %s", \
- strerror (errno)); \
- exit (1); \
- } \
- } while (false)
-
- SIGHANDLE (SIGHUP);
- SIGHANDLE (SIGINT);
- SIGHANDLE (SIGTERM);
-
- print_version (pgm);
- setbuf (stdout, NULL);
- printf ("daemon starting up");
-
- threaded_queue request_queue (request_threads);
- printf (".");
-
- transport_layer_base *const transport = create_server_transport ();
- assert (transport);
- printf (".");
-
- process_cache cache (cleanup_threads);
- printf (".");
-
- server_submission_loop submission_loop (&request_queue, transport, &cache);
- printf (".");
-
- request_queue.add_submission_loop (&submission_loop);
- printf (".");
-
- if (transport->listen () == -1)
- {
- exit (1);
- }
- printf (".");
-
- cache.start ();
- printf (".");
-
- request_queue.start ();
- printf (".");
-
- printf ("complete\n");
-
- /* TODO: wait on multiple objects - the thread handle for each
- * request loop + all the process handles. This should be done by
- * querying the request_queue and the process cache for all their
- * handles, and then waiting for (say) 30 seconds. after that we
- * recreate the list of handles to wait on, and wait again. the
- * point of all this abstraction is that we can trivially server
- * both sockets and pipes simply by making a new transport, and then
- * calling request_queue.process_requests (transport2);
- */
- /* WaitForMultipleObjects abort && request_queue && process_queue && signal
- -- if signal event then retrigger it
- */
- while (!shutdown_server && request_queue.running () && cache.running ())
- pause ();
-
- printf ("\nShutdown request received - new requests will be denied\n");
- request_queue.stop ();
- printf ("All pending requests processed\n");
- safe_delete (transport);
- printf ("No longer accepting requests - cygwin will operate in daemonless mode\n");
- cache.stop ();
- printf ("All outstanding process-cache activities completed\n");
- printf ("daemon shutdown\n");
-
- return 0;
-}
diff --git a/winsup/cygserver/ipc.h b/winsup/cygserver/ipc.h
deleted file mode 100644
index 0d0ebbc76..000000000
--- a/winsup/cygserver/ipc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* cygserver_ipc.h
-
- Copyright 2002 Red Hat, Inc.
-
- Originally written by Conrad Scott <conrad.scott@dsl.pipex.com>
-
-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. */
-
-#ifndef __CYGSERVER_IPC_H__
-#define __CYGSERVER_IPC_H__
-
-#include <assert.h>
-#include <limits.h> /* For OPEN_MAX. */
-
-/*
- * The sysv ipc id's (msgid, semid, shmid) are integers arranged such
- * that they no subsystem will generate the same id as some other
- * subsystem; nor do these ids overlap file descriptors (the other
- * common integer ids). Since Cygwin can allocate more than OPEN_MAX
- * file descriptors, it can't be guaranteed not to overlap, but it
- * should help catch some errors.
- *
- * msgid's: OPEN_MAX, OPEN_MAX + 3, OPEN_MAX + 6, . . .
- * semid's: OPEN_MAX + 1, OPEN_MAX + 4, OPEN_MAX + 7, . . .
- * shmid's: OPEN_MAX + 2, OPEN_MAX + 5, OPEN_MAX + 8, . . .
- *
- * To further ensure that ids are unique, if ipc objects are created
- * and destroyed and then re-created, they are given new ids by
- * munging the basic id (as above) with a sequence number.
- *
- * Internal ipc id's, which are 0, 1, ... within each subsystem (and
- * not munged with a sequence number), are used solely by the ipcs(8)
- * interface.
- */
-
-enum ipc_subsys_t
- {
- IPC_MSGOP = 0,
- IPC_SEMOP = 1,
- IPC_SHMOP = 2,
- IPC_SUBSYS_COUNT
- };
-
-/*
- * IPCMNI - The absolute maximum number of simultaneous ipc ids for
- * any one subsystem.
- */
-
-enum
- {
- IPCMNI = 0x10000 // Must be a power of two.
- };
-
-inline int
-ipc_int2ext (const int intid, const ipc_subsys_t subsys, long & sequence)
-{
- assert (0 <= intid && intid < IPCMNI);
-
- const long tmp = InterlockedIncrement (&sequence);
-
- return (((tmp & 0x7fff) << 16)
- | (OPEN_MAX + (intid * IPC_SUBSYS_COUNT) + subsys));
-}
-
-inline int
-ipc_ext2int_subsys (const int extid)
-{
- return ((extid & (IPCMNI - 1)) - OPEN_MAX) % IPC_SUBSYS_COUNT;
-}
-
-inline int
-ipc_ext2int (const int extid, const ipc_subsys_t subsys)
-{
- if (ipc_ext2int_subsys (extid) != subsys)
- return -1;
- else
- return ((extid & (IPCMNI - 1)) - OPEN_MAX) / IPC_SUBSYS_COUNT;
-}
-
-#endif /* __CYGSERVER_IPC_H__ */
diff --git a/winsup/cygserver/process.cc b/winsup/cygserver/process.cc
deleted file mode 100644
index 7118bbcd9..000000000
--- a/winsup/cygserver/process.cc
+++ /dev/null
@@ -1,432 +0,0 @@
-/* cygserver_process.cc
-
- Copyright 2001, 2002 Red Hat Inc.
-
- Written by Robert Collins <rbtcollins@hotmail.com>
-
-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. */
-
-#include "woutsup.h"
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "cygerrno.h"
-
-#include "cygwin/cygserver_process.h"
-
-/*****************************************************************************/
-
-#define elements(ARRAY) (sizeof (ARRAY) / sizeof (*ARRAY))
-
-/*****************************************************************************/
-
-process_cleanup::~process_cleanup ()
-{
- safe_delete (_process);
-}
-
-void
-process_cleanup::process ()
-{
- _process->cleanup ();
-}
-
-/*****************************************************************************/
-
-/* cleanup_routine */
-cleanup_routine::~cleanup_routine ()
-{
-}
-
-/*****************************************************************************/
-
-process::process (const pid_t cygpid, const DWORD winpid)
- : _cygpid (cygpid),
- _winpid (winpid),
- _hProcess (NULL),
- _cleaning_up (false),
- _exit_status (STILL_ACTIVE),
- _routines_head (NULL),
- _next (NULL)
-{
- _hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid);
- if (!_hProcess)
- {
- system_printf ("unable to obtain handle for new cache process %d(%lu)",
- _cygpid, _winpid);
- _hProcess = INVALID_HANDLE_VALUE;
- _exit_status = 0;
- }
- else
- debug_printf ("got handle %p for new cache process %d(%lu)",
- _hProcess, _cygpid, _winpid);
- InitializeCriticalSection (&_access);
-}
-
-process::~process ()
-{
- DeleteCriticalSection (&_access);
- (void) CloseHandle (_hProcess);
-}
-
-/* No need to be thread-safe as this is only ever called by
- * process_cache::remove_process (). If it has to be made thread-safe
- * later on, it should not use the `access' critical section as that
- * is held by the client request handlers for an arbitrary length of
- * time, i.e. while they do whatever processing is required for a
- * client request.
- */
-DWORD
-process::check_exit_code ()
-{
- if (_hProcess && _hProcess != INVALID_HANDLE_VALUE
- && _exit_status == STILL_ACTIVE
- && !GetExitCodeProcess (_hProcess, &_exit_status))
- {
- system_printf ("failed to retrieve exit code for %d(%lu), error = %lu",
- _cygpid, _winpid, GetLastError ());
- _hProcess = INVALID_HANDLE_VALUE;
- }
- return _exit_status;
-}
-
-bool
-process::add (cleanup_routine *const entry)
-{
- assert (entry);
-
- bool res = false;
- EnterCriticalSection (&_access);
-
- if (!_cleaning_up)
- {
- entry->_next = _routines_head;
- _routines_head = entry;
- res = true;
- }
-
- LeaveCriticalSection (&_access);
- return res;
-}
-
-bool
-process::remove (const cleanup_routine *const entry)
-{
- assert (entry);
-
- bool res = false;
- EnterCriticalSection (&_access);
-
- if (!_cleaning_up)
- {
- cleanup_routine *previous = NULL;
-
- for (cleanup_routine *ptr = _routines_head;
- ptr;
- previous = ptr, ptr = ptr->_next)
- {
- if (*ptr == *entry)
- {
- if (previous)
- previous->_next = ptr->_next;
- else
- _routines_head = ptr->_next;
-
- safe_delete (ptr);
- res = true;
- break;
- }
- }
- }
-
- LeaveCriticalSection (&_access);
- return res;
-}
-
-/* This is single threaded. It's called after the process is removed
- * from the cache, but inserts may be attemped by worker threads that
- * have a pointer to it.
- */
-void
-process::cleanup ()
-{
- EnterCriticalSection (&_access);
- assert (!is_active ());
- assert (!_cleaning_up);
- InterlockedExchange (&_cleaning_up, true);
- cleanup_routine *entry = _routines_head;
- _routines_head = NULL;
- LeaveCriticalSection (&_access);
-
- while (entry)
- {
- cleanup_routine *const ptr = entry;
- entry = entry->_next;
- ptr->cleanup (this);
- safe_delete (ptr);
- }
-}
-
-/*****************************************************************************/
-
-void
-process_cache::submission_loop::request_loop ()
-{
- assert (this);
- assert (_cache);
- assert (_interrupt_event);
-
- while (_running)
- _cache->wait_for_processes (_interrupt_event);
-}
-
-/*****************************************************************************/
-
-process_cache::process_cache (const unsigned int initial_workers)
- : _queue (initial_workers),
- _submitter (this, &_queue), // true == interruptible
- _processes_count (0),
- _processes_head (NULL),
- _cache_add_trigger (NULL)
-{
- /* there can only be one */
- InitializeCriticalSection (&_cache_write_access);
-
- _cache_add_trigger = CreateEvent (NULL, // SECURITY_ATTRIBUTES
- FALSE, // Auto-reset
- FALSE, // Initially non-signalled
- NULL); // Anonymous
-
- if (!_cache_add_trigger)
- {
- system_printf ("failed to create cache add trigger, error = %lu",
- GetLastError ());
- abort ();
- }
-
- _queue.add_submission_loop (&_submitter);
-}
-
-process_cache::~process_cache ()
-{
- (void) CloseHandle (_cache_add_trigger);
- DeleteCriticalSection (&_cache_write_access);
-}
-
-/* This returns the process object to the caller already locked, that
- * is, with the object's `access' critical region entered. Thus the
- * caller must unlock the object when it's finished with it (via
- * process::release ()). It must then not try to access the object
- * afterwards, except by going through this routine again, as it may
- * have been deleted once it has been unlocked.
- */
-class process *
-process_cache::process (const pid_t cygpid, const DWORD winpid)
-{
- /* TODO: make this more granular, so a search doesn't involve the
- * write lock.
- */
- EnterCriticalSection (&_cache_write_access);
- class process *previous = NULL;
- class process *entry = find (winpid, &previous);
-
- if (!entry)
- {
- if (_processes_count + SPECIALS_COUNT >= MAXIMUM_WAIT_OBJECTS)
- {
- LeaveCriticalSection (&_cache_write_access);
- system_printf (("process limit (%d processes) reached; "
- "new connection refused for %d(%lu)"),
- MAXIMUM_WAIT_OBJECTS - SPECIALS_COUNT,
- cygpid, winpid);
- set_errno (EAGAIN);
- return NULL;
- }
-
- entry = safe_new (class process, cygpid, winpid);
- if (!entry->is_active ())
- {
- LeaveCriticalSection (&_cache_write_access);
- safe_delete (entry);
- set_errno (ESRCH);
- return NULL;
- }
-
- if (previous)
- {
- entry->_next = previous->_next;
- previous->_next = entry;
- }
- else
- {
- entry->_next = _processes_head;
- _processes_head = entry;
- }
-
- _processes_count += 1;
- SetEvent (_cache_add_trigger);
- }
-
- EnterCriticalSection (&entry->_access); // To be released by the caller.
- LeaveCriticalSection (&_cache_write_access);
- assert (entry);
- assert (entry->_winpid == winpid);
- return entry;
-}
-
-void
-process_cache::wait_for_processes (const HANDLE interrupt_event)
-{
- // Update `_wait_array' with handles of all current processes.
- const size_t count = sync_wait_array (interrupt_event);
-
- debug_printf ("waiting on %u objects in total (%u processes)",
- count, _processes_count);
-
- const DWORD rc = WaitForMultipleObjects (count, _wait_array,
- FALSE, INFINITE);
-
- if (rc == WAIT_FAILED)
- {
- system_printf ("could not wait on the process handles, error = %lu",
- GetLastError ());
- abort ();
- }
-
- const size_t start = rc - WAIT_OBJECT_0;
-
- if (rc < WAIT_OBJECT_0 || start > count)
- {
- system_printf (("unexpected return code %rc "
- "from WaitForMultipleObjects: "
- "expected [%u .. %u)"),
- rc, WAIT_OBJECT_0, WAIT_OBJECT_0 + count);
- abort ();
- }
-
- // Tell all the processes, from the signalled point up, the bad news.
- for (size_t index = start; index != count; index++)
- if (_process_array[index])
- check_and_remove_process (index);
-}
-
-/*
- * process_cache::sync_wait_array ()
- *
- * Fill-in the wait array with the handles that the cache needs to wait on.
- * These handles are:
- * - the process_process_param's interrupt event
- * - the process_cache's cache_add_trigger event
- * - the handle for each live process in the cache.
- *
- * Return value: the number of live handles in the array.
- */
-
-size_t
-process_cache::sync_wait_array (const HANDLE interrupt_event)
-{
- assert (this);
- assert (_cache_add_trigger && _cache_add_trigger != INVALID_HANDLE_VALUE);
- assert (interrupt_event && interrupt_event != INVALID_HANDLE_VALUE);
-
- EnterCriticalSection (&_cache_write_access);
-
- assert (_processes_count + SPECIALS_COUNT <= elements (_wait_array));
-
- size_t index = 0;
-
- for (class process *ptr = _processes_head; ptr; ptr = ptr->_next)
- {
- assert (ptr->_hProcess && ptr->_hProcess != INVALID_HANDLE_VALUE);
- assert (ptr->is_active ());
-
- _wait_array[index] = ptr->handle ();
- _process_array[index++] = ptr;
-
- assert (index <= elements (_wait_array));
- }
-
- /* Sorry for shouting, but THESE MUST BE ADDED AT THE END! */
- /* Well, not strictly `must', but it's more efficient if they are :-) */
-
- _wait_array[index] = interrupt_event;
- _process_array[index++] = NULL;
-
- _wait_array[index] = _cache_add_trigger;
- _process_array[index++] = NULL;
-
- /* Phew, back to normal volume now. */
-
- assert (index <= elements (_wait_array));
-
- LeaveCriticalSection (&_cache_write_access);
-
- return index;
-}
-
-void
-process_cache::check_and_remove_process (const size_t index)
-{
- assert (this);
- assert (index < elements (_wait_array) - SPECIALS_COUNT);
-
- class process *const process = _process_array[index];
-
- assert (process);
- assert (process->handle () == _wait_array[index]);
-
- if (process->check_exit_code () == STILL_ACTIVE)
- return;
-
- debug_printf ("process %d(%lu) has left the building ($? = %lu)",
- process->_cygpid, process->_winpid, process->_exit_status);
-
- /* Unlink the process object from the process list. */
-
- EnterCriticalSection (&_cache_write_access);
-
- class process *previous = NULL;
-
- const class process *const tmp = find (process->_winpid, &previous);
-
- assert (tmp == process);
- assert (previous ? previous->_next == process : _processes_head == process);
-
- if (previous)
- previous->_next = process->_next;
- else
- _processes_head = process->_next;
-
- _processes_count -= 1;
- LeaveCriticalSection (&_cache_write_access);
-
- /* Schedule any cleanup tasks for this process. */
- _queue.add (safe_new (process_cleanup, process));
-}
-
-class process *
-process_cache::find (const DWORD winpid, class process **previous)
-{
- if (previous)
- *previous = NULL;
-
- for (class process *ptr = _processes_head; ptr; ptr = ptr->_next)
- if (ptr->_winpid == winpid)
- return ptr;
- else if (ptr->_winpid > winpid) // The list is sorted by winpid.
- return NULL;
- else if (previous)
- *previous = ptr;
-
- return NULL;
-}
-
-/*****************************************************************************/
diff --git a/winsup/cygserver/shm.cc b/winsup/cygserver/shm.cc
deleted file mode 100644
index 18b1c3d83..000000000
--- a/winsup/cygserver/shm.cc
+++ /dev/null
@@ -1,896 +0,0 @@
-/* cygserver_shm.cc: Single unix specification IPC interface for Cygwin.
-
- Copyright 2002 Red Hat, Inc.
-
- Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
- Based on code by Robert Collins <robert.collins@hotmail.com>.
-
-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. */
-
-#include "woutsup.h"
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "cygserver_ipc.h"
-#include "cygserver_shm.h"
-#include "security.h"
-
-#include "cygwin/cygserver.h"
-#include "cygwin/cygserver_process.h"
-#include "cygwin/cygserver_transport.h"
-
-/*---------------------------------------------------------------------------*
- * class server_shmmgr
- *
- * A singleton class.
- *---------------------------------------------------------------------------*/
-
-#define shmmgr (server_shmmgr::instance ())
-
-class server_shmmgr
-{
-private:
- class attach_t
- {
- public:
- class process *const _client;
- unsigned int _refcnt;
-
- attach_t *_next;
-
- attach_t (class process *const client)
- : _client (client),
- _refcnt (0),
- _next (NULL)
- {}
- };
-
- class segment_t
- {
- private:
- // Bits for the _flg field.
- enum { IS_DELETED = 0x01 };
-
- public:
- const int _intid;
- const int _shmid;
- struct shmid_ds _ds;
-
- segment_t *_next;
-
- segment_t (const key_t key, const int intid, const HANDLE hFileMap);
- ~segment_t ();
-
- bool is_deleted () const
- {
- return _flg & IS_DELETED;
- }
-
- bool is_pending_delete () const
- {
- return !_ds.shm_nattch && is_deleted ();
- }
-
- void mark_deleted ()
- {
- assert (!is_deleted ());
-
- _flg |= IS_DELETED;
- }
-
- int attach (class process *, HANDLE & hFileMap);
- int detach (class process *);
-
- private:
- static long _sequence;
-
- int _flg;
- const HANDLE _hFileMap;
- attach_t *_attach_head; // A list sorted by winpid;
-
- attach_t *find (const class process *, attach_t **previous = NULL);
- };
-
- class cleanup_t : public cleanup_routine
- {
- public:
- cleanup_t (const segment_t *const segptr)
- : cleanup_routine (reinterpret_cast<void *> (segptr->_shmid))
- {
- assert (key ());
- }
-
- int shmid () const { return reinterpret_cast<int> (key ()); }
-
- virtual void cleanup (class process *const client)
- {
- const int res = shmmgr.shmdt (shmid (), client);
-
- if (res != 0)
- debug_printf ("process cleanup failed [shmid = %d]: %s",
- shmid (), strerror (-res));
- }
- };
-
-public:
- static server_shmmgr & instance ();
-
- int shmat (HANDLE & hFileMap,
- int shmid, int shmflg, class process *);
- int shmctl (int & out_shmid, struct shmid_ds & out_ds,
- struct shminfo & out_shminfo, struct shm_info & out_shm_info,
- const int shmid, int cmd, const struct shmid_ds &,
- class process *);
- int shmdt (int shmid, class process *);
- int shmget (int & out_shmid, key_t, size_t, int shmflg, uid_t, gid_t,
- class process *);
-
-private:
- static server_shmmgr *_instance;
- static pthread_once_t _instance_once;
-
- static void initialise_instance ();
-
- CRITICAL_SECTION _segments_lock;
- segment_t *_segments_head; // A list sorted by int_id.
-
- int _shm_ids; // Number of shm segments (for ipcs(8)).
- int _shm_tot; // Total bytes of shm segments (for ipcs(8)).
- int _shm_atts; // Number of attached segments (for ipcs(8)).
- int _intid_max; // Highest intid yet allocated (for ipcs(8)).
-
- server_shmmgr ();
- ~server_shmmgr ();
-
- // Undefined (as this class is a singleton):
- server_shmmgr (const server_shmmgr &);
- server_shmmgr & operator= (const server_shmmgr &);
-
- segment_t *find_by_key (key_t);
- segment_t *find (int intid, segment_t **previous = NULL);
-
- int new_segment (key_t, size_t, int shmflg, pid_t, uid_t, gid_t);
-
- segment_t *new_segment (key_t, size_t, HANDLE);
- void delete_segment (segment_t *);
-};
-
-/* static */ long server_shmmgr::segment_t::_sequence = 0;
-
-/* static */ server_shmmgr *server_shmmgr::_instance = NULL;
-/* static */ pthread_once_t server_shmmgr::_instance_once = PTHREAD_ONCE_INIT;
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::segment_t::segment_t ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::segment_t::segment_t (const key_t key,
- const int intid,
- const HANDLE hFileMap)
- : _intid (intid),
- _shmid (ipc_int2ext (intid, IPC_SHMOP, _sequence)),
- _next (NULL),
- _flg (0),
- _hFileMap (hFileMap),
- _attach_head (NULL)
-{
- assert (0 <= _intid && _intid < SHMMNI);
-
- memset (&_ds, '\0', sizeof (_ds));
- _ds.shm_perm.key = key;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::segment_t::~segment_t ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::segment_t::~segment_t ()
-{
- assert (!_attach_head);
-
- if (!CloseHandle (_hFileMap))
- syscall_printf ("failed to close file map [handle = 0x%x]: %E", _hFileMap);
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::segment_t::attach ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::segment_t::attach (class process *const client,
- HANDLE & hFileMap)
-{
- assert (client);
-
- if (!DuplicateHandle (GetCurrentProcess (),
- _hFileMap,
- client->handle (),
- &hFileMap,
- 0,
- FALSE, // bInheritHandle
- DUPLICATE_SAME_ACCESS))
- {
- syscall_printf (("failed to duplicate handle for client "
- "[key = 0x%016llx, shmid = %d, handle = 0x%x]: %E"),
- _ds.shm_perm.key, _shmid, _hFileMap);
-
- return -EACCES; // FIXME: Case analysis?
- }
-
- _ds.shm_lpid = client->cygpid ();
- _ds.shm_nattch += 1;
- _ds.shm_atime = time (NULL); // FIXME: sub-second times.
-
- attach_t *previous = NULL;
- attach_t *attptr = find (client, &previous);
-
- if (!attptr)
- {
- attptr = safe_new (attach_t, client);
-
- if (previous)
- {
- attptr->_next = previous->_next;
- previous->_next = attptr;
- }
- else
- {
- attptr->_next = _attach_head;
- _attach_head = attptr;
- }
- }
-
- attptr->_refcnt += 1;
-
- cleanup_t *const cleanup = safe_new (cleanup_t, this);
-
- // FIXME: ::add should only fail if the process object is already
- // cleaning up; but it can't be doing that since this thread has it
- // locked.
-
- const bool result = client->add (cleanup);
-
- assert (result);
-
- return 0;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::segment_t::detach ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::segment_t::detach (class process *const client)
-{
- attach_t *previous = NULL;
- attach_t *const attptr = find (client, &previous);
-
- if (!attptr)
- return -EINVAL;
-
- if (client->is_active ())
- {
- const cleanup_t key (this);
-
- if (!client->remove (&key))
- syscall_printf (("failed to remove cleanup routine for %d(%lu) "
- "[shmid = %d]"),
- client->cygpid (), client->winpid (),
- _shmid);
- }
-
- attptr->_refcnt -= 1;
-
- if (!attptr->_refcnt)
- {
- assert (previous ? previous->_next == attptr : _attach_head == attptr);
-
- if (previous)
- previous->_next = attptr->_next;
- else
- _attach_head = attptr->_next;
-
- safe_delete (attptr);
- }
-
- assert (_ds.shm_nattch > 0);
-
- _ds.shm_lpid = client->cygpid ();
- _ds.shm_nattch -= 1;
- _ds.shm_dtime = time (NULL); // FIXME: sub-second times.
-
- return 0;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::segment_t::find ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::attach_t *
-server_shmmgr::segment_t::find (const class process *const client,
- attach_t **previous)
-{
- if (previous)
- *previous = NULL;
-
- // Nb. The _attach_head list is sorted by winpid.
-
- for (attach_t *attptr = _attach_head; attptr; attptr = attptr->_next)
- if (attptr->_client == client)
- return attptr;
- else if (attptr->_client->winpid () > client->winpid ())
- return NULL;
- else if (previous)
- *previous = attptr;
-
- return NULL;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::instance ()
- *---------------------------------------------------------------------------*/
-
-/* static */ server_shmmgr &
-server_shmmgr::instance ()
-{
- pthread_once (&_instance_once, &initialise_instance);
-
- assert (_instance);
-
- return *_instance;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::shmat ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::shmat (HANDLE & hFileMap,
- const int shmid, const int shmflg,
- class process *const client)
-{
- syscall_printf ("shmat (shmid = %d, shmflg = 0%o) for %d(%lu)",
- shmid, shmflg, client->cygpid (), client->winpid ());
-
- int result = 0;
- EnterCriticalSection (&_segments_lock);
-
- segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP));
-
- if (!segptr)
- result = -EINVAL;
- else
- result = segptr->attach (client, hFileMap);
-
- if (!result)
- _shm_atts += 1;
-
- LeaveCriticalSection (&_segments_lock);
-
- if (result < 0)
- syscall_printf (("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) "
- "for %d(%lu)"),
- -result, shmid, shmflg,
- client->cygpid (), client->winpid ());
- else
- syscall_printf (("0x%x = shmat (shmid = %d, shmflg = 0%o) "
- "for %d(%lu)"),
- hFileMap, shmid, shmflg,
- client->cygpid (), client->winpid ());
-
- return result;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::shmctl ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::shmctl (int & out_shmid,
- struct shmid_ds & out_ds,
- struct shminfo & out_shminfo,
- struct shm_info & out_shm_info,
- const int shmid, const int cmd,
- const struct shmid_ds & ds,
- class process *const client)
-{
- syscall_printf ("shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)",
- shmid, cmd, client->cygpid (), client->winpid ());
-
- int result = 0;
- EnterCriticalSection (&_segments_lock);
-
- switch (cmd)
- {
- case IPC_STAT:
- case SHM_STAT: // Uses intids rather than shmids.
- case IPC_SET:
- case IPC_RMID:
- {
- int intid;
-
- if (cmd == SHM_STAT)
- intid = shmid;
- else
- intid = ipc_ext2int (shmid, IPC_SHMOP);
-
- segment_t *const segptr = find (intid);
-
- if (!segptr)
- result = -EINVAL;
- else
- switch (cmd)
- {
- case IPC_STAT:
- out_ds = segptr->_ds;
- break;
-
- case IPC_SET:
- segptr->_ds.shm_perm.uid = ds.shm_perm.uid;
- segptr->_ds.shm_perm.gid = ds.shm_perm.gid;
- segptr->_ds.shm_perm.mode = ds.shm_perm.mode & 0777;
- segptr->_ds.shm_lpid = client->cygpid ();
- segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times.
- break;
-
- case IPC_RMID:
- if (segptr->is_deleted ())
- result = -EIDRM;
- else
- {
- segptr->mark_deleted ();
- if (segptr->is_pending_delete ())
- delete_segment (segptr);
- }
- break;
-
- case SHM_STAT: // ipcs(8) i'face.
- out_ds = segptr->_ds;
- out_shmid = segptr->_shmid;
- break;
- }
- }
- break;
-
- case IPC_INFO:
- out_shminfo.shmmax = SHMMAX;
- out_shminfo.shmmin = SHMMIN;
- out_shminfo.shmmni = SHMMNI;
- out_shminfo.shmseg = SHMSEG;
- out_shminfo.shmall = SHMALL;
- break;
-
- case SHM_INFO: // ipcs(8) i'face.
- out_shmid = _intid_max;
- out_shm_info.shm_ids = _shm_ids;
- out_shm_info.shm_tot = _shm_tot;
- out_shm_info.shm_atts = _shm_atts;
- break;
-
- default:
- result = -EINVAL;
- break;
- }
-
- LeaveCriticalSection (&_segments_lock);
-
- if (result < 0)
- syscall_printf (("-1 [%d] = "
- "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"),
- -result,
- shmid, cmd, client->cygpid (), client->winpid ());
- else
- syscall_printf (("%d = "
- "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"),
- ((cmd == SHM_STAT || cmd == SHM_INFO)
- ? out_shmid
- : result),
- shmid, cmd, client->cygpid (), client->winpid ());
-
- return result;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::shmdt ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::shmdt (const int shmid, class process *const client)
-{
- syscall_printf ("shmdt (shmid = %d) for %d(%lu)",
- shmid, client->cygpid (), client->winpid ());
-
- int result = 0;
- EnterCriticalSection (&_segments_lock);
-
- segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP));
-
- if (!segptr)
- result = -EINVAL;
- else
- result = segptr->detach (client);
-
- if (!result)
- _shm_atts -= 1;
-
- if (!result && segptr->is_pending_delete ())
- delete_segment (segptr);
-
- LeaveCriticalSection (&_segments_lock);
-
- if (result < 0)
- syscall_printf ("-1 [%d] = shmdt (shmid = %d) for %d(%lu)",
- -result, shmid, client->cygpid (), client->winpid ());
- else
- syscall_printf ("%d = shmdt (shmid = %d) for %d(%lu)",
- result, shmid, client->cygpid (), client->winpid ());
-
- return result;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::shmget ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::shmget (int & out_shmid,
- const key_t key, const size_t size, const int shmflg,
- const uid_t uid, const gid_t gid,
- class process *const client)
-{
- syscall_printf (("shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "
- "for %d(%lu)"),
- key, size, shmflg,
- client->cygpid (), client->winpid ());
-
- int result = 0;
- EnterCriticalSection (&_segments_lock);
-
- if (key == IPC_PRIVATE)
- result = new_segment (key, size, shmflg,
- client->cygpid (), uid, gid);
- else
- {
- segment_t *const segptr = find_by_key (key);
-
- if (!segptr)
- if (shmflg & IPC_CREAT)
- result = new_segment (key, size, shmflg,
- client->cygpid (), uid, gid);
- else
- result = -ENOENT;
- else if (segptr->is_deleted ())
- result = -EIDRM;
- else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL))
- result = -EEXIST;
- else if ((shmflg & ~(segptr->_ds.shm_perm.mode)) & 0777)
- result = -EACCES;
- else if (size && segptr->_ds.shm_segsz < size)
- result = -EINVAL;
- else
- result = segptr->_shmid;
- }
-
- LeaveCriticalSection (&_segments_lock);
-
- if (result >= 0)
- {
- out_shmid = result;
- result = 0;
- }
-
- if (result < 0)
- syscall_printf (("-1 [%d] = "
- "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "
- "for %d(%lu)"),
- -result,
- key, size, shmflg,
- client->cygpid (), client->winpid ());
- else
- syscall_printf (("%d = "
- "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "
- "for %d(%lu)"),
- out_shmid,
- key, size, shmflg,
- client->cygpid (), client->winpid ());
-
- return result;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::initialise_instance ()
- *---------------------------------------------------------------------------*/
-
-/* static */ void
-server_shmmgr::initialise_instance ()
-{
- assert (!_instance);
-
- _instance = safe_new0 (server_shmmgr);
-
- assert (_instance);
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::server_shmmgr ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::server_shmmgr ()
- : _segments_head (NULL),
- _shm_ids (0),
- _shm_tot (0),
- _shm_atts (0),
- _intid_max (0)
-{
- InitializeCriticalSection (&_segments_lock);
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::~server_shmmgr ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::~server_shmmgr ()
-{
- DeleteCriticalSection (&_segments_lock);
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::find_by_key ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::segment_t *
-server_shmmgr::find_by_key (const key_t key)
-{
- for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next)
- if (segptr->_ds.shm_perm.key == key)
- return segptr;
-
- return NULL;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::find ()
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::segment_t *
-server_shmmgr::find (const int intid, segment_t **previous)
-{
- if (previous)
- *previous = NULL;
-
- for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next)
- if (segptr->_intid == intid)
- return segptr;
- else if (segptr->_intid > intid) // The list is sorted by intid.
- return NULL;
- else if (previous)
- *previous = segptr;
-
- return NULL;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::new_segment ()
- *---------------------------------------------------------------------------*/
-
-int
-server_shmmgr::new_segment (const key_t key,
- const size_t size,
- const int shmflg,
- const pid_t cygpid,
- const uid_t uid,
- const gid_t gid)
-{
- if (size < SHMMIN || size > SHMMAX)
- return -EINVAL;
-
- const HANDLE hFileMap = CreateFileMapping (INVALID_HANDLE_VALUE,
- NULL, PAGE_READWRITE,
- 0, size,
- NULL);
-
- if (!hFileMap)
- {
- syscall_printf ("failed to create file mapping [size = %lu]: %E", size);
- return -ENOMEM; // FIXME
- }
-
- segment_t *const segptr = new_segment (key, size, hFileMap);
-
- if (!segptr)
- {
- (void) CloseHandle (hFileMap);
- return -ENOSPC;
- }
-
- segptr->_ds.shm_perm.cuid = segptr->_ds.shm_perm.uid = uid;
- segptr->_ds.shm_perm.cgid = segptr->_ds.shm_perm.gid = gid;
- segptr->_ds.shm_perm.mode = shmflg & 0777;
- segptr->_ds.shm_segsz = size;
- segptr->_ds.shm_cpid = cygpid;
- segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times.
-
- return segptr->_shmid;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::new_segment ()
- *
- * Allocate a new segment for the given key and file map with the
- * lowest available intid and insert into the segment map.
- *---------------------------------------------------------------------------*/
-
-server_shmmgr::segment_t *
-server_shmmgr::new_segment (const key_t key, const size_t size,
- const HANDLE hFileMap)
-{
- // FIXME: Overflow risk.
- if (_shm_tot + size > SHMALL)
- return NULL;
-
- int intid = 0; // Next expected intid value.
- segment_t *previous = NULL; // Insert pointer.
-
- // Find first unallocated intid.
- for (segment_t *segptr = _segments_head;
- segptr && segptr->_intid == intid;
- segptr = segptr->_next, intid++)
- {
- previous = segptr;
- }
-
- /* By the time this condition is reached (given the default value of
- * SHMMNI), the linear searches should all replaced by something
- * just a *little* cleverer . . .
- */
- if (intid >= SHMMNI)
- return NULL;
-
- segment_t *const segptr = safe_new (segment_t, key, intid, hFileMap);
-
- assert (segptr);
-
- if (previous)
- {
- segptr->_next = previous->_next;
- previous->_next = segptr;
- }
- else
- {
- segptr->_next = _segments_head;
- _segments_head = segptr;
- }
-
- _shm_ids += 1;
- _shm_tot += size;
- if (intid > _intid_max)
- _intid_max = intid;
-
- return segptr;
-}
-
-/*---------------------------------------------------------------------------*
- * server_shmmgr::delete_segment ()
- *---------------------------------------------------------------------------*/
-
-void
-server_shmmgr::delete_segment (segment_t *const segptr)
-{
- assert (segptr);
- assert (segptr->is_pending_delete ());
-
- segment_t *previous = NULL;
-
- const segment_t *const tmp = find (segptr->_intid, &previous);
-
- assert (tmp == segptr);
- assert (previous ? previous->_next == segptr : _segments_head == segptr);
-
- if (previous)
- previous->_next = segptr->_next;
- else
- _segments_head = segptr->_next;
-
- assert (_shm_ids > 0);
- _shm_ids -= 1;
- _shm_tot -= segptr->_ds.shm_segsz;
-
- safe_delete (segptr);
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::client_request_shm ()
- *---------------------------------------------------------------------------*/
-
-client_request_shm::client_request_shm ()
- : client_request (CYGSERVER_REQUEST_SHM,
- &_parameters, sizeof (_parameters))
-{
- // verbose: syscall_printf ("created");
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::serve ()
- *---------------------------------------------------------------------------*/
-
-void
-client_request_shm::serve (transport_layer_base *const conn,
- process_cache *const cache)
-{
- assert (conn);
-
- assert (!error_code ());
-
- if (msglen () != sizeof (_parameters.in))
- {
- syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
- sizeof (_parameters), msglen ());
- error_code (EINVAL);
- msglen (0);
- return;
- }
-
- // FIXME: Get a return code out of this and don't continue on error.
- conn->impersonate_client ();
-
- class process *const client = cache->process (_parameters.in.cygpid,
- _parameters.in.winpid);
-
- if (!client)
- {
- error_code (EAGAIN);
- msglen (0);
- return;
- }
-
- int result = -EINVAL;
-
- switch (_parameters.in.shmop)
- {
- case SHMOP_shmget:
- result = shmmgr.shmget (_parameters.out.shmid,
- _parameters.in.key, _parameters.in.size,
- _parameters.in.shmflg,
- _parameters.in.uid, _parameters.in.gid,
- client);
- break;
-
- case SHMOP_shmat:
- result = shmmgr.shmat (_parameters.out.hFileMap,
- _parameters.in.shmid, _parameters.in.shmflg,
- client);
- break;
-
- case SHMOP_shmdt:
- result = shmmgr.shmdt (_parameters.in.shmid, client);
- break;
-
- case SHMOP_shmctl:
- result = shmmgr.shmctl (_parameters.out.shmid,
- _parameters.out.ds, _parameters.out.shminfo,
- _parameters.out.shm_info,
- _parameters.in.shmid, _parameters.in.cmd,
- _parameters.in.ds,
- client);
- break;
- }
-
- client->release ();
- conn->revert_to_self ();
-
- if (result < 0)
- {
- error_code (-result);
- msglen (0);
- }
- else
- msglen (sizeof (_parameters.out));
-}
diff --git a/winsup/cygserver/shm.h b/winsup/cygserver/shm.h
deleted file mode 100755
index b1ff353da..000000000
--- a/winsup/cygserver/shm.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* cygserver_shm.h: Single unix specification IPC interface for Cygwin.
-
- Copyright 2002 Red Hat, Inc.
-
- Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
- Based on code by Robert Collins <robert.collins@hotmail.com>.
-
-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. */
-
-#ifndef __CYGSERVER_SHM_H__
-#define __CYGSERVER_SHM_H__
-
-#include <sys/types.h>
-#include <cygwin/shm.h>
-
-#include <assert.h>
-#include <limits.h>
-
-#include "cygserver_ipc.h"
-
-#include "cygwin/cygserver.h"
-
-/*---------------------------------------------------------------------------*
- * Values for the shminfo entries.
- *
- * Nb. The values are segregated between two enums so that the `small'
- * values aren't promoted to `unsigned long' equivalents.
- *---------------------------------------------------------------------------*/
-
-enum
- {
- SHMMAX = ULONG_MAX,
- SHMSEG = ULONG_MAX,
- SHMALL = ULONG_MAX
- };
-
-enum
- {
- SHMMIN = 1,
- SHMMNI = IPCMNI // Must be <= IPCMNI.
- };
-
-/*---------------------------------------------------------------------------*
- * class client_request_shm
- *---------------------------------------------------------------------------*/
-
-#ifndef __INSIDE_CYGWIN__
-class transport_layer_base;
-class process_cache;
-#endif
-
-class client_request_shm : public client_request
-{
- friend class client_request;
-
-public:
- enum shmop_t
- {
- SHMOP_shmat,
- SHMOP_shmctl,
- SHMOP_shmdt,
- SHMOP_shmget
- };
-
-#ifdef __INSIDE_CYGWIN__
- client_request_shm (int shmid, int shmflg); // shmat
- client_request_shm (int shmid, int cmd, const struct shmid_ds *); // shmctl
- client_request_shm (int shmid); // shmdt
- client_request_shm (key_t, size_t, int shmflg); // shmget
-#endif
-
- // Accessors for out parameters.
-
- int shmid () const
- {
- assert (!error_code ());
- return _parameters.out.shmid;
- }
-
- HANDLE hFileMap () const
- {
- assert (!error_code ());
- return _parameters.out.hFileMap;
- }
-
- const struct shmid_ds & ds () const
- {
- assert (!error_code ());
- return _parameters.out.ds;
- }
-
- const struct shminfo & shminfo () const
- {
- assert (!error_code ());
- return _parameters.out.shminfo;
- }
-
- const struct shm_info & shm_info () const
- {
- assert (!error_code ());
- return _parameters.out.shm_info;
- }
-
-private:
- union
- {
- struct
- {
- shmop_t shmop;
- key_t key;
- size_t size;
- int shmflg;
- int shmid;
- int cmd;
- pid_t cygpid;
- DWORD winpid;
- uid_t uid;
- gid_t gid;
- struct shmid_ds ds;
- } in;
-
- struct {
- int shmid;
- union
- {
- HANDLE hFileMap;
- struct shmid_ds ds;
- struct shminfo shminfo;
- struct shm_info shm_info;
- };
- } out;
- } _parameters;
-
-#ifndef __INSIDE_CYGWIN__
- client_request_shm ();
-#endif
-
-#ifndef __INSIDE_CYGWIN__
- virtual void serve (transport_layer_base *, process_cache *);
-#endif
-};
-
-#endif /* __CYGSERVER_SHM_H__ */
diff --git a/winsup/cygserver/threaded_queue.cc b/winsup/cygserver/threaded_queue.cc
deleted file mode 100644
index ba0fe4178..000000000
--- a/winsup/cygserver/threaded_queue.cc
+++ /dev/null
@@ -1,408 +0,0 @@
-/* threaded_queue.cc
-
- Copyright 2001, 2002 Red Hat Inc.
-
- Written by Robert Collins <rbtcollins@hotmail.com>
-
-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. */
-
-#include "woutsup.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include "threaded_queue.h"
-
-/*****************************************************************************/
-
-/* queue_request */
-
-queue_request::~queue_request ()
-{}
-
-/*****************************************************************************/
-
-/* threaded_queue */
-
-threaded_queue::threaded_queue (const size_t initial_workers)
- : _workers_count (0),
- _running (false),
- _submitters_head (NULL),
- _requests_count (0),
- _requests_head (NULL),
- _requests_sem (NULL)
-{
- InitializeCriticalSection (&_queue_lock);
-
- // This semaphore's count is the number of requests on the queue.
- // The maximum count (129792) is calculated as MAXIMUM_WAIT_OBJECTS
- // multiplied by max. threads per process (2028?), which is (a few)
- // more requests than could ever be pending with the current design.
-
- _requests_sem = CreateSemaphore (NULL, // SECURITY_ATTRIBUTES
- 0, // Initial count
- 129792, // Maximum count
- NULL); // Anonymous
-
- if (!_requests_sem)
- {
- system_printf (("failed to create the request queue semaphore, "
- "error = %lu"),
- GetLastError ());
- abort ();
- }
-
- create_workers (initial_workers);
-}
-
-threaded_queue::~threaded_queue ()
-{
- if (_running)
- stop ();
-
- debug_printf ("deleting all pending queue requests");
- queue_request *reqptr = _requests_head;
- while (reqptr)
- {
- queue_request *const ptr = reqptr;
- reqptr = reqptr->_next;
- safe_delete (ptr);
- }
-
- DeleteCriticalSection (&_queue_lock);
- if (_requests_sem)
- (void) CloseHandle (_requests_sem);
-}
-
-/* FIXME: return success or failure rather than quitting */
-void
-threaded_queue::add_submission_loop (queue_submission_loop *const submitter)
-{
- assert (this);
- assert (submitter);
- assert (submitter->_queue == this);
- assert (!submitter->_next);
-
- submitter->_next =
- TInterlockedExchangePointer (&_submitters_head, submitter);
-
- if (_running)
- submitter->start ();
-}
-
-bool
-threaded_queue::start ()
-{
- EnterCriticalSection (&_queue_lock);
- const bool was_running = _running;
- _running = true;
- queue_submission_loop *loopptr = _submitters_head;
- LeaveCriticalSection (&_queue_lock);
-
- if (!was_running)
- {
- debug_printf ("starting all queue submission loops");
-
- while (loopptr)
- {
- queue_submission_loop *const ptr = loopptr;
- loopptr = loopptr->_next;
- ptr->start ();
- }
- }
-
- return was_running;
-}
-
-bool
-threaded_queue::stop ()
-{
- EnterCriticalSection (&_queue_lock);
- const bool was_running = _running;
- _running = false;
- queue_submission_loop *loopptr = _submitters_head;
- LeaveCriticalSection (&_queue_lock);
-
- if (was_running)
- {
- debug_printf ("stopping all queue submission loops");
- while (loopptr)
- {
- queue_submission_loop *const ptr = loopptr;
- loopptr = loopptr->_next;
- ptr->stop ();
- }
-
- ReleaseSemaphore (_requests_sem, _workers_count, NULL);
- while (_workers_count)
- {
- debug_printf (("waiting for worker threads to terminate: "
- "%lu still running"),
- _workers_count);
- Sleep (1000);
- }
- debug_printf ("all worker threads have terminated");
- }
-
- return was_running;
-}
-
-/* FIXME: return success or failure */
-void
-threaded_queue::add (queue_request *const therequest)
-{
- assert (this);
- assert (therequest);
- assert (!therequest->_next);
-
- if (!_workers_count)
- {
- system_printf ("warning: no worker threads to handle request!");
- // FIXME: And then what?
- }
-
- EnterCriticalSection (&_queue_lock);
- if (!_requests_head)
- _requests_head = therequest;
- else
- {
- /* Add to the queue end. */
- queue_request *reqptr = _requests_head;
- for (; reqptr->_next; reqptr = reqptr->_next)
- {}
- assert (reqptr);
- assert (!reqptr->_next);
- reqptr->_next = therequest;
- }
-
- _requests_count += 1;
- assert (_requests_count > 0);
- LeaveCriticalSection (&_queue_lock);
-
- (void) ReleaseSemaphore (_requests_sem, 1, NULL);
-}
-
-/*static*/ DWORD WINAPI
-threaded_queue::start_routine (const LPVOID lpParam)
-{
- class threaded_queue *const queue = (class threaded_queue *) lpParam;
- assert (queue);
-
- queue->worker_loop ();
-
- const long count = InterlockedDecrement (&queue->_workers_count);
- assert (count >= 0);
-
- if (queue->_running)
- debug_printf ("worker loop has exited; thread about to terminate");
-
- return 0;
-}
-
-/* Called from the constructor: so no need to be thread-safe until the
- * worker threads start to be created; thus the interlocked increment
- * of the `_workers_count' field.
- */
-
-void
-threaded_queue::create_workers (const size_t initial_workers)
-{
- assert (initial_workers > 0);
-
- for (unsigned int i = 0; i != initial_workers; i++)
- {
- const long count = InterlockedIncrement (&_workers_count);
- assert (count > 0);
-
- DWORD tid;
- const HANDLE hThread =
- CreateThread (NULL, 0, start_routine, this, 0, &tid);
-
- if (!hThread)
- {
- system_printf ("failed to create thread, error = %lu",
- GetLastError ());
- abort ();
- }
-
- (void) CloseHandle (hThread);
- }
-}
-
-void
-threaded_queue::worker_loop ()
-{
- while (true)
- {
- const DWORD rc = WaitForSingleObject (_requests_sem, INFINITE);
- if (rc == WAIT_FAILED)
- {
- system_printf ("wait for request semaphore failed, error = %lu",
- GetLastError ());
- return;
- }
- assert (rc == WAIT_OBJECT_0);
-
- EnterCriticalSection (&_queue_lock);
- if (!_running)
- {
- LeaveCriticalSection (&_queue_lock);
- return;
- }
-
- assert (_requests_head);
- queue_request *const reqptr = _requests_head;
- _requests_head = reqptr->_next;
-
- _requests_count -= 1;
- assert (_requests_count >= 0);
- LeaveCriticalSection (&_queue_lock);
-
- assert (reqptr);
- reqptr->process ();
- safe_delete (reqptr);
- }
-}
-
-/*****************************************************************************/
-
-/* queue_submission_loop */
-
-queue_submission_loop::queue_submission_loop (threaded_queue *const queue,
- const bool ninterruptible)
- : _running (false),
- _interrupt_event (NULL),
- _queue (queue),
- _interruptible (ninterruptible),
- _hThread (NULL),
- _tid (0),
- _next (NULL)
-{
- if (_interruptible)
- {
- // verbose: debug_printf ("creating an interruptible processing thread");
-
- _interrupt_event = CreateEvent (NULL, // SECURITY_ATTRIBUTES
- FALSE, // Auto-reset
- FALSE, // Initially non-signalled
- NULL); // Anonymous
-
- if (!_interrupt_event)
- {
- system_printf ("failed to create interrupt event, error = %lu",
- GetLastError ());
- abort ();
- }
- }
-}
-
-queue_submission_loop::~queue_submission_loop ()
-{
- if (_running)
- stop ();
- if (_interrupt_event)
- (void) CloseHandle (_interrupt_event);
- if (_hThread)
- (void) CloseHandle (_hThread);
-}
-
-bool
-queue_submission_loop::start ()
-{
- assert (this);
- assert (!_hThread);
-
- const bool was_running = _running;
-
- if (!was_running)
- {
- _running = true;
-
- _hThread = CreateThread (NULL, 0, start_routine, this, 0, &_tid);
- if (!_hThread)
- {
- system_printf ("failed to create thread, error = %lu",
- GetLastError ());
- abort ();
- }
- }
-
- return was_running;
-}
-
-bool
-queue_submission_loop::stop ()
-{
- assert (this);
- assert (_hThread && _hThread != INVALID_HANDLE_VALUE);
-
- const bool was_running = _running;
-
- if (_running)
- {
- _running = false;
-
- if (_interruptible)
- {
- assert (_interrupt_event
- && _interrupt_event != INVALID_HANDLE_VALUE);
-
- SetEvent (_interrupt_event);
-
- if (WaitForSingleObject (_hThread, 1000) == WAIT_TIMEOUT)
- {
- system_printf (("request loop thread %lu failed to shutdown "
- "when asked politely: about to get heavy"),
- _tid);
-
- if (!TerminateThread (_hThread, 0))
- {
- system_printf (("failed to kill request loop thread %lu"
- ", error = %lu"),
- _tid, GetLastError ());
- abort ();
- }
- }
- }
- else
- {
- // FIXME: could wait to see if the request loop notices that
- // the submission loop is no longer running and shuts down
- // voluntarily.
-
- debug_printf ("killing request loop thread %lu", _tid);
-
- if (!TerminateThread (_hThread, 0))
- system_printf (("failed to kill request loop thread %lu"
- ", error = %lu"),
- _tid, GetLastError ());
- }
- }
-
- return was_running;
-}
-
-/*static*/ DWORD WINAPI
-queue_submission_loop::start_routine (const LPVOID lpParam)
-{
- class queue_submission_loop *const submission_loop =
- (class queue_submission_loop *) lpParam;
- assert (submission_loop);
-
- submission_loop->request_loop ();
-
- debug_printf ("submission loop has exited; thread about to terminate");
-
- submission_loop->stop ();
-
- return 0;
-}
-
-/*****************************************************************************/
diff --git a/winsup/cygserver/transport.cc b/winsup/cygserver/transport.cc
deleted file mode 100644
index 8684a6148..000000000
--- a/winsup/cygserver/transport.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/* cygserver_transport.cc
-
- Copyright 2001, 2002 Red Hat Inc.
-
- Written by Robert Collins <rbtcollins@hotmail.com>
-
-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. */
-
-/* to allow this to link into cygwin and the .dll, a little magic is needed. */
-#ifdef __OUTSIDE_CYGWIN__
-#include "woutsup.h"
-#else
-#include "winsup.h"
-#endif
-
-#include <sys/socket.h>
-
-#include "safe_memory.h"
-
-#include "cygwin/cygserver_transport.h"
-#include "cygwin/cygserver_transport_pipes.h"
-#include "cygwin/cygserver_transport_sockets.h"
-
-/* The factory */
-transport_layer_base *
-create_server_transport ()
-{
- if (wincap.is_winnt ())
- return safe_new0 (transport_layer_pipes);
- else
- return safe_new0 (transport_layer_sockets);
-}
-
-#ifndef __INSIDE_CYGWIN__
-
-void
-transport_layer_base::impersonate_client ()
-{}
-
-void
-transport_layer_base::revert_to_self ()
-{}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-transport_layer_base::~transport_layer_base ()
-{}
diff --git a/winsup/cygserver/transport_pipes.cc b/winsup/cygserver/transport_pipes.cc
deleted file mode 100644
index f318a7592..000000000
--- a/winsup/cygserver/transport_pipes.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-/* cygserver_transport_pipes.cc
-
- Copyright 2001, 2002 Red Hat Inc.
-
- Written by Robert Collins <rbtcollins@hotmail.com>
-
-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. */
-
-/* to allow this to link into cygwin and the .dll, a little magic is needed. */
-#ifdef __OUTSIDE_CYGWIN__
-#include "woutsup.h"
-#else
-#include "winsup.h"
-#endif
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <netdb.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#include "cygerrno.h"
-#include "cygwin/cygserver_transport.h"
-#include "cygwin/cygserver_transport_pipes.h"
-
-#ifndef __INSIDE_CYGWIN__
-#include "cygwin/cygserver.h"
-#endif
-
-enum
- {
- MAX_WAIT_NAMED_PIPE_RETRY = 64,
- WAIT_NAMED_PIPE_TIMEOUT = 10 // milliseconds
- };
-
-#ifndef __INSIDE_CYGWIN__
-
-static pthread_once_t pipe_instance_lock_once = PTHREAD_ONCE_INIT;
-static CRITICAL_SECTION pipe_instance_lock;
-static long pipe_instance = 0;
-
-static void
-initialise_pipe_instance_lock ()
-{
- assert (pipe_instance == 0);
- InitializeCriticalSection (&pipe_instance_lock);
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-#ifndef __INSIDE_CYGWIN__
-
-transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe)
- : _pipe_name (""),
- _hPipe (hPipe),
- _is_accepted_endpoint (true),
- _is_listening_endpoint (false)
-{
- assert (_hPipe);
- assert (_hPipe != INVALID_HANDLE_VALUE);
-
- init_security ();
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-transport_layer_pipes::transport_layer_pipes ()
- : _pipe_name ("\\\\.\\pipe\\cygwin_lpc"),
- _hPipe (NULL),
- _is_accepted_endpoint (false),
- _is_listening_endpoint (false)
-{
- init_security ();
-}
-
-void
-transport_layer_pipes::init_security ()
-{
- assert (wincap.has_security ());
-
- /* FIXME: pthread_once or equivalent needed */
-
- InitializeSecurityDescriptor (&_sd, SECURITY_DESCRIPTOR_REVISION);
- SetSecurityDescriptorDacl (&_sd, TRUE, NULL, FALSE);
-
- _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
- _sec_all_nih.lpSecurityDescriptor = &_sd;
- _sec_all_nih.bInheritHandle = FALSE;
-}
-
-transport_layer_pipes::~transport_layer_pipes ()
-{
- close ();
-}
-
-#ifndef __INSIDE_CYGWIN__
-
-int
-transport_layer_pipes::listen ()
-{
- assert (!_hPipe);
- assert (!_is_accepted_endpoint);
- assert (!_is_listening_endpoint);
-
- _is_listening_endpoint = true;
-
- /* no-op */
- return 0;
-}
-
-class transport_layer_pipes *
-transport_layer_pipes::accept (bool *const recoverable)
-{
- assert (!_hPipe);
- assert (!_is_accepted_endpoint);
- assert (_is_listening_endpoint);
-
- pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock);
-
- EnterCriticalSection (&pipe_instance_lock);
-
- // Read: http://www.securityinternals.com/research/papers/namedpipe.php
- // See also the Microsoft security bulletins MS00-053 and MS01-031.
-
- // FIXME: Remove FILE_CREATE_PIPE_INSTANCE.
-
- const bool first_instance = (pipe_instance == 0);
-
- const HANDLE accept_pipe =
- CreateNamedPipe (_pipe_name,
- (PIPE_ACCESS_DUPLEX
- | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0)),
- (PIPE_TYPE_BYTE | PIPE_WAIT),
- PIPE_UNLIMITED_INSTANCES,
- 0, 0, 1000,
- &_sec_all_nih);
-
- const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE
- && pipe_instance == 0
- && GetLastError () == ERROR_ACCESS_DENIED);
-
- if (accept_pipe != INVALID_HANDLE_VALUE)
- InterlockedIncrement (&pipe_instance);
-
- LeaveCriticalSection (&pipe_instance_lock);
-
- if (duplicate)
- {
- *recoverable = false;
- system_printf ("failed to create named pipe: "
- "is the daemon already running?");
- return NULL;
- }
-
- if (accept_pipe == INVALID_HANDLE_VALUE)
- {
- debug_printf ("error creating pipe (%lu).", GetLastError ());
- *recoverable = true; // FIXME: case analysis?
- return NULL;
- }
-
- assert (accept_pipe);
-
- if (!ConnectNamedPipe (accept_pipe, NULL)
- && GetLastError () != ERROR_PIPE_CONNECTED)
- {
- debug_printf ("error connecting to pipe (%lu)\n.", GetLastError ());
- (void) CloseHandle (accept_pipe);
- *recoverable = true; // FIXME: case analysis?
- return NULL;
- }
-
- return safe_new (transport_layer_pipes, accept_pipe);
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-void
-transport_layer_pipes::close ()
-{
- // verbose: debug_printf ("closing pipe %p", _hPipe);
-
- if (_hPipe)
- {
- assert (_hPipe != INVALID_HANDLE_VALUE);
-
-#ifndef __INSIDE_CYGWIN__
-
- if (_is_accepted_endpoint)
- {
- (void) FlushFileBuffers (_hPipe); // Blocks until client reads.
- (void) DisconnectNamedPipe (_hPipe);
- EnterCriticalSection (&pipe_instance_lock);
- (void) CloseHandle (_hPipe);
- assert (pipe_instance > 0);
- InterlockedDecrement (&pipe_instance);
- LeaveCriticalSection (&pipe_instance_lock);
- }
- else
- (void) CloseHandle (_hPipe);
-
-#else /* __INSIDE_CYGWIN__ */
-
- assert (!_is_accepted_endpoint);
- (void) ForceCloseHandle (_hPipe);
-
-#endif /* __INSIDE_CYGWIN__ */
-
- _hPipe = NULL;
- }
-}
-
-ssize_t
-transport_layer_pipes::read (void *const buf, const size_t len)
-{
- // verbose: debug_printf ("reading from pipe %p", _hPipe);
-
- assert (_hPipe);
- assert (_hPipe != INVALID_HANDLE_VALUE);
- assert (!_is_listening_endpoint);
-
- DWORD count;
- if (!ReadFile (_hPipe, buf, len, &count, NULL))
- {
- debug_printf ("error reading from pipe (%lu)", GetLastError ());
- set_errno (EINVAL); // FIXME?
- return -1;
- }
-
- return count;
-}
-
-ssize_t
-transport_layer_pipes::write (void *const buf, const size_t len)
-{
- // verbose: debug_printf ("writing to pipe %p", _hPipe);
-
- assert (_hPipe);
- assert (_hPipe != INVALID_HANDLE_VALUE);
- assert (!_is_listening_endpoint);
-
- DWORD count;
- if (!WriteFile (_hPipe, buf, len, &count, NULL))
- {
- debug_printf ("error writing to pipe, error = %lu", GetLastError ());
- set_errno (EINVAL); // FIXME?
- return -1;
- }
-
- return count;
-}
-
-/*
- * This routine holds a static variable, assume_cygserver, that is set
- * if the transport has good reason to think that cygserver is
- * running, i.e. if if successfully connected to it with the previous
- * attempt. If this is set, the code tries a lot harder to get a
- * connection, making the assumption that any failures are just
- * congestion and overloading problems.
- */
-
-int
-transport_layer_pipes::connect ()
-{
- assert (!_hPipe);
- assert (!_is_accepted_endpoint);
- assert (!_is_listening_endpoint);
-
- static bool assume_cygserver = false;
-
- BOOL rc = TRUE;
- int retries = 0;
-
- while (rc)
- {
- _hPipe = CreateFile (_pipe_name,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- &_sec_all_nih,
- OPEN_EXISTING,
- SECURITY_IMPERSONATION,
- NULL);
-
- if (_hPipe != INVALID_HANDLE_VALUE)
- {
- assert (_hPipe);
-#ifdef __INSIDE_CYGWIN__
- ProtectHandle (_hPipe);
-#endif
- assume_cygserver = true;
- return 0;
- }
-
- _hPipe = NULL;
-
- if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY)
- {
- debug_printf ("Error opening the pipe (%lu)", GetLastError ());
- return -1;
- }
-
- /* Note: `If no instances of the specified named pipe exist, the
- * WaitNamedPipe function returns immediately, regardless of the
- * time-out value.' Thus the explicit Sleep if the call fails
- * with ERROR_FILE_NOT_FOUND.
- */
- while (retries != MAX_WAIT_NAMED_PIPE_RETRY
- && !(rc = WaitNamedPipe (_pipe_name, WAIT_NAMED_PIPE_TIMEOUT)))
- {
- if (GetLastError () == ERROR_FILE_NOT_FOUND)
- Sleep (0); // Give the server a chance.
-
- retries += 1;
- }
- }
-
- assert (retries == MAX_WAIT_NAMED_PIPE_RETRY);
-
- system_printf ("lost connection to cygserver, error = %lu",
- GetLastError ());
-
- assume_cygserver = false;
-
- return -1;
-}
-
-#ifndef __INSIDE_CYGWIN__
-
-void
-transport_layer_pipes::impersonate_client ()
-{
- assert (_hPipe);
- assert (_hPipe != INVALID_HANDLE_VALUE);
- assert (_is_accepted_endpoint);
-
- // verbose: debug_printf ("impersonating pipe %p", _hPipe);
- if (_hPipe)
- {
- assert (_hPipe != INVALID_HANDLE_VALUE);
-
- if (!ImpersonateNamedPipeClient (_hPipe))
- debug_printf ("Failed to Impersonate the client, (%lu)",
- GetLastError ());
- }
- // verbose: debug_printf ("I am who you are");
-}
-
-void
-transport_layer_pipes::revert_to_self ()
-{
- assert (_is_accepted_endpoint);
-
- RevertToSelf ();
- // verbose: debug_printf ("I am who I yam");
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
diff --git a/winsup/cygserver/transport_sockets.cc b/winsup/cygserver/transport_sockets.cc
deleted file mode 100644
index 6ade14bff..000000000
--- a/winsup/cygserver/transport_sockets.cc
+++ /dev/null
@@ -1,387 +0,0 @@
-/* cygserver_transport_sockets.cc
-
- Copyright 2001, 2002 Red Hat Inc.
-
- Written by Robert Collins <rbtcollins@hotmail.com>
-
-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. */
-
-/* to allow this to link into cygwin and the .dll, a little magic is needed. */
-#ifdef __OUTSIDE_CYGWIN__
-#include "woutsup.h"
-#else
-#include "winsup.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "cygwin/cygserver_transport.h"
-#include "cygwin/cygserver_transport_sockets.h"
-
-/* to allow this to link into cygwin and the .dll, a little magic is needed. */
-#ifndef __OUTSIDE_CYGWIN__
-
-extern "C" int cygwin_accept (int fd, struct sockaddr *, int *len);
-extern "C" int cygwin_bind (int fd, const struct sockaddr *, int len);
-extern "C" int cygwin_connect (int fd, const struct sockaddr *, int len);
-extern "C" int cygwin_listen (int fd, int backlog);
-extern "C" int cygwin_shutdown (int fd, int how);
-extern "C" int cygwin_socket (int af, int type, int protocol);
-
-#else /* __OUTSIDE_CYGWIN__ */
-
-#define cygwin_accept(A,B,C) ::accept (A,B,C)
-#define cygwin_bind(A,B,C) ::bind (A,B,C)
-#define cygwin_connect(A,B,C) ::connect (A,B,C)
-#define cygwin_listen(A,B) ::listen (A,B)
-#define cygwin_shutdown(A,B) ::shutdown (A,B)
-#define cygwin_socket(A,B,C) ::socket (A,B,C)
-
-#endif /* __OUTSIDE_CYGWIN__ */
-
-enum
- {
- MAX_CONNECT_RETRY = 64
- };
-
-transport_layer_sockets::transport_layer_sockets (const int fd)
- : _fd (fd),
- _addr_len (0),
- _is_accepted_endpoint (true),
- _is_listening_endpoint (false)
-{
- assert (_fd != -1);
-
- memset (&_addr, '\0', sizeof (_addr));
-}
-
-transport_layer_sockets::transport_layer_sockets ()
- : _fd (-1),
- _addr_len (0),
- _is_accepted_endpoint (false),
- _is_listening_endpoint (false)
-{
- memset (&_addr, '\0', sizeof (_addr));
-
- _addr.sun_family = AF_UNIX;
- strcpy (_addr.sun_path, "/tmp/cygdaemo"); // FIXME: $TMP?
- _addr_len = SUN_LEN (&_addr);
-}
-
-transport_layer_sockets::~transport_layer_sockets ()
-{
- close ();
-}
-
-#ifndef __INSIDE_CYGWIN__
-
-int
-transport_layer_sockets::listen ()
-{
- assert (_fd == -1);
- assert (!_is_accepted_endpoint);
- assert (!_is_listening_endpoint);
-
- debug_printf ("listen () [this = %p]", this);
-
- struct stat sbuf;
-
- if (stat (_addr.sun_path, &sbuf) == -1)
- {
- if (errno != ENOENT)
- {
- system_printf ("cannot access socket file `%s': %s",
- _addr.sun_path, strerror (errno));
- return -1;
- }
- }
- else if (S_ISSOCK (sbuf.st_mode))
- {
- // The socket already exists: is a duplicate cygserver running?
-
- const int newfd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
-
- if (newfd == -1)
- {
- system_printf ("failed to create UNIX domain socket: %s",
- strerror (errno));
- return -1;
- }
-
- if (cygwin_connect (newfd, (struct sockaddr *) &_addr, _addr_len) == 0)
- {
- system_printf ("the daemon is already running");
- (void) cygwin_shutdown (newfd, SHUT_WR);
- char buf[BUFSIZ];
- while (::read (newfd, buf, sizeof (buf)) > 0)
- {}
- (void) ::close (newfd);
- return -1;
- }
-
- if (unlink (_addr.sun_path) == -1)
- {
- system_printf ("failed to remove `%s': %s",
- _addr.sun_path, strerror (errno));
- (void) ::close (newfd);
- return -1;
- }
- }
- else
- {
- system_printf ("cannot create socket `%s': File already exists",
- _addr.sun_path);
- return -1;
- }
-
- _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
-
- if (_fd == -1)
- {
- system_printf ("failed to create UNIX domain socket: %s",
- strerror (errno));
- return -1;
- }
-
- if (cygwin_bind (_fd, (struct sockaddr *) &_addr, _addr_len) == -1)
- {
- const int saved_errno = errno;
- close ();
- errno = saved_errno;
- system_printf ("failed to bind UNIX domain socket `%s': %s",
- _addr.sun_path, strerror (errno));
- return -1;
- }
-
- _is_listening_endpoint = true; // i.e. this really means "have bound".
-
- if (cygwin_listen (_fd, SOMAXCONN) == -1)
- {
- const int saved_errno = errno;
- close ();
- errno = saved_errno;
- system_printf ("failed to listen on UNIX domain socket `%s': %s",
- _addr.sun_path, strerror (errno));
- return -1;
- }
-
- debug_printf ("0 = listen () [this = %p, fd = %d]", this, _fd);
-
- return 0;
-}
-
-class transport_layer_sockets *
-transport_layer_sockets::accept (bool *const recoverable)
-{
- assert (_fd != -1);
- assert (!_is_accepted_endpoint);
- assert (_is_listening_endpoint);
-
- debug_printf ("accept () [this = %p, fd = %d]", this, _fd);
-
- struct sockaddr_un client_addr;
- socklen_t client_addr_len = sizeof (client_addr);
-
- const int accept_fd =
- cygwin_accept (_fd, (struct sockaddr *) &client_addr, &client_addr_len);
-
- if (accept_fd == -1)
- {
- system_printf ("failed to accept connection: %s", strerror (errno));
- switch (errno)
- {
- case ECONNABORTED:
- case EINTR:
- case EMFILE:
- case ENFILE:
- case ENOBUFS:
- case ENOMEM:
- *recoverable = true;
- break;
-
- default:
- *recoverable = false;
- break;
- }
- return NULL;
- }
-
- debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd);
-
- return safe_new (transport_layer_sockets, accept_fd);
-}
-
-#endif /* !__INSIDE_CYGWIN__ */
-
-void
-transport_layer_sockets::close ()
-{
- debug_printf ("close () [this = %p, fd = %d]", this, _fd);
-
- if (_is_listening_endpoint)
- (void) unlink (_addr.sun_path);
-
- if (_fd != -1)
- {
- (void) cygwin_shutdown (_fd, SHUT_WR);
- if (!_is_listening_endpoint)
- {
- char buf[BUFSIZ];
- while (::read (_fd, buf, sizeof (buf)) > 0)
- {}
- }
- (void) ::close (_fd);
- _fd = -1;
- }
-
- _is_listening_endpoint = false;
-}
-
-ssize_t
-transport_layer_sockets::read (void *const buf, const size_t buf_len)
-{
- assert (_fd != -1);
- assert (!_is_listening_endpoint);
-
- assert (buf);
- assert (buf_len > 0);
-
- // verbose: debug_printf ("read (buf = %p, len = %u) [this = %p, fd = %d]",
- // buf, buf_len, this, _fd);
-
- char *read_buf = static_cast<char *> (buf);
- size_t read_buf_len = buf_len;
- ssize_t res = 0;
-
- while (read_buf_len != 0
- && (res = ::read (_fd, read_buf, read_buf_len)) > 0)
- {
- read_buf += res;
- read_buf_len -= res;
-
- assert (read_buf_len >= 0);
- }
-
- if (res != -1)
- {
- if (res == 0)
- errno = EIO; // FIXME?
-
- res = buf_len - read_buf_len;
- }
-
- if (res != static_cast<ssize_t> (buf_len))
- debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]: %s",
- res, buf, buf_len, this, _fd,
- (res == -1 ? strerror (errno) : "EOF"));
- else
- {
- // verbose: debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]",
- // res, buf, buf_len, this, _fd);
- }
-
- return res;
-}
-
-ssize_t
-transport_layer_sockets::write (void *const buf, const size_t buf_len)
-{
- assert (_fd != -1);
- assert (!_is_listening_endpoint);
-
- assert (buf);
- assert (buf_len > 0);
-
- // verbose: debug_printf ("write (buf = %p, len = %u) [this = %p, fd = %d]",
- // buf, buf_len, this, _fd);
-
- char *write_buf = static_cast<char *> (buf);
- size_t write_buf_len = buf_len;
- ssize_t res = 0;
-
- while (write_buf_len != 0
- && (res = ::write (_fd, write_buf, write_buf_len)) > 0)
- {
- write_buf += res;
- write_buf_len -= res;
-
- assert (write_buf_len >= 0);
- }
-
- if (res != -1)
- {
- if (res == 0)
- errno = EIO; // FIXME?
-
- res = buf_len - write_buf_len;
- }
-
- if (res != static_cast<ssize_t> (buf_len))
- debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]: %s",
- res, buf, buf_len, this, _fd,
- (res == -1 ? strerror (errno) : "EOF"));
- else
- {
- // verbose: debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]",
- // res, buf, buf_len, this, _fd);
- }
-
- return res;
-}
-
-int
-transport_layer_sockets::connect ()
-{
- assert (_fd == -1);
- assert (!_is_accepted_endpoint);
- assert (!_is_listening_endpoint);
-
- static bool assume_cygserver = false;
-
- debug_printf ("connect () [this = %p]", this);
-
- for (int retries = 0; retries != MAX_CONNECT_RETRY; retries++)
- {
- _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
-
- if (_fd == -1)
- {
- system_printf ("failed to create UNIX domain socket: %s",
- strerror (errno));
- return -1;
- }
-
- if (cygwin_connect (_fd, (struct sockaddr *) &_addr, _addr_len) == 0)
- {
- assume_cygserver = true;
- debug_printf ("0 = connect () [this = %p, fd = %d]", this, _fd);
- return 0;
- }
-
- if (!assume_cygserver || errno != ECONNREFUSED)
- {
- debug_printf ("failed to connect to server: %s", strerror (errno));
- (void) ::close (_fd);
- _fd = -1;
- return -1;
- }
-
- (void) ::close (_fd);
- _fd = -1;
- Sleep (0); // Give the server a chance.
- }
-
- debug_printf ("failed to connect to server: %s", strerror (errno));
- return -1;
-}
diff --git a/winsup/cygserver/woutsup.h b/winsup/cygserver/woutsup.h
deleted file mode 100644
index c048f1c19..000000000
--- a/winsup/cygserver/woutsup.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* woutsup.h: for Cygwin code compiled outside the DLL (i.e. cygserver).
-
- Copyright 2002 Red Hat, Inc.
-
-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 HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#ifdef __INSIDE_CYGWIN__
-#error "woutsup.h is not for code being compiled inside the dll"
-#endif
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0500
-#endif
-
-#if _WIN32_WINNT < 0x0500
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0500
-#endif
-
-#define WIN32_LEAN_AND_MEAN 1
-#define _WINGDI_H
-#define _WINUSER_H
-#define _WINNLS_H
-#define _WINVER_H
-#define _WINNETWK_H
-#define _WINSVC_H
-#include <windows.h>
-#include <wincrypt.h>
-#include <lmcons.h>
-#undef _WINGDI_H
-#undef _WINUSER_H
-#undef _WINNLS_H
-#undef _WINVER_H
-#undef _WINNETWK_H
-#undef _WINSVC_H
-
-#include "wincap.h"
-
-/* The one function we use from winuser.h most of the time */
-extern "C" DWORD WINAPI GetLastError (void);
-
-extern int cygserver_running;
-
-#if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L
-#define NEW_MACRO_VARARGS
-#endif
-
-/*
- * A reproduction of the <sys/strace.h> macros. This allows code that
- * runs both inside and outside the Cygwin DLL to use the same macros
- * for logging messages.
- */
-
-extern "C" void __cygserver__printf (const char *, const char *, ...);
-
-#ifdef NEW_MACRO_VARARGS
-
-#define system_printf(...) \
- do \
- { \
- __cygserver__printf (__PRETTY_FUNCTION__, __VA_ARGS__); \
- } while (false)
-
-#define __noop_printf(...) do {;} while (false)
-
-#else /* !NEW_MACRO_VARARGS */
-
-#define system_printf(args...) \
- do \
- { \
- __cygserver__printf (__PRETTY_FUNCTION__, ## args); \
- } while (false)
-
-#define __noop_printf(args...) do {;} while (false)
-
-#endif /* !NEW_MACRO_VARARGS */
-
-#ifdef DEBUGGING
-#define debug_printf system_printf
-#define paranoid_printf system_printf
-#define select_printf system_printf
-#define sigproc_printf system_printf
-#define syscall_printf system_printf
-#define termios_printf system_printf
-#define wm_printf system_printf
-#define minimal_printf system_printf
-#define malloc_printf system_printf
-#define thread_printf system_printf
-#else
-#define debug_printf __noop_printf
-#define paranoid_printf __noop_printf
-#define select_printf __noop_printf
-#define sigproc_printf __noop_printf
-#define syscall_printf __noop_printf
-#define termios_printf __noop_printf
-#define wm_printf __noop_printf
-#define minimal_printf __noop_printf
-#define malloc_printf __noop_printf
-#define thread_printf __noop_printf
-#endif
-
-#include "safe_memory.h"