Don't use safe_new but new throughout. Fix copyright dates
throughout. * Makefile.in: Accomodate all new files and name changes. Add a *.d dependency. (sbindir): Add. (etcdir): Drop in favor of more appropriate sysconfdir definition. (sysconfdir): Add. (CXXFLAGS): Add -MMD flag. Add SYSCONFDIR definition. (.SUFFIXES): Add. (install): Add action items. (libclean): New target. (fullclean): Ditto. * bsd_helper.cc: New file. * bsd_helper.h: Ditto. * bsd_log.cc: Ditto. * bsd_log.h: Ditto. * bsd_mutex.cc: Ditto. * bsd_mutex.h: Ditto. * client.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. (client_request::handle_request): Add Message Queue and Semaphore handling. * cygserver.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. Use new debug/log/panic logging functions. (DEF_CONFIG_FILE): New definition for configuration file. Use throughout. (getfunc): Remove. (__cygserver__printf): Remove. (client_request_attach_tty::serve): Return error if impersonation fails. (print_usage): Pump up help message. (print_version): Add output of default configuration file. (main): Accommodate new options. Allow overwrite of threading options from config file. Call several new initialization functions. Drop printing dots. Don't define SIGHANDLE inline. * cygserver.conf: New file. * cygserver_process.h: Rename to process.h. * cygserver_transport.h: Rename to transport.h. * cygserver_transport_pipes.h: Rename to transport_pipes.h. * cygserver_transport_sockets.h: Rename to transport_sockets.h. * msg.cc: Rewrite. * sem.cc: Rewrite. * shm.cc: Rewrite. * sysv_msg.cc: New file, derived from FreeBSD version 1.52. * sysv_sem.cc: New file, derived from FreeBSD version 1.66. * sysv_shm.cc: New file, derived from FreeBSD version 1.89. * threaded_queue.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. * transport.cc (transport_layer_base::impersonate_client): Define bool. (transport_layer_base::revert_to_self): Ditto. * transport.h (transport_layer_base::impersonate_client): Declare bool. (transport_layer_base::revert_to_self): Ditto. * transport_pipes.cc (transport_layer_pipes::transport_layer_pipes): Don't call init_security. (init_security): Remove. (transport_layer_pipes::accept): Use global sec_all_nih. (transport_layer_pipes::connect): Ditto. (transport_layer_pipes::impersonate_client): Define bool. (transport_layer_pipes::revert_to_self): Ditt. * transport_pipes.h (transport_layer_pipes::impersonate_client): Declare bool. (transport_layer_pipes::revert_to_self): Ditto. * woutsup.h: Include bsd compatibility headers. (SIGHANDLE): Add definition. (__cygserver__printf): Remove definition. (__noop_printf): Ditto. (debug_printf): Define using debug. (syscall_printf): Define using log. (system_printf): Ditto. Drop all other _printf definitions.
This commit is contained in:
parent
64cfc6f213
commit
282113ba89
|
@ -1,3 +1,76 @@
|
||||||
|
2003-11-19 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
Don't use safe_new but new throughout. Fix copyright dates
|
||||||
|
throughout.
|
||||||
|
* Makefile.in: Accomodate all new files and name changes.
|
||||||
|
Add a *.d dependency.
|
||||||
|
(sbindir): Add.
|
||||||
|
(etcdir): Drop in favor of more appropriate sysconfdir definition.
|
||||||
|
(sysconfdir): Add.
|
||||||
|
(CXXFLAGS): Add -MMD flag. Add SYSCONFDIR definition.
|
||||||
|
(.SUFFIXES): Add.
|
||||||
|
(install): Add action items.
|
||||||
|
(libclean): New target.
|
||||||
|
(fullclean): Ditto.
|
||||||
|
* bsd_helper.cc: New file.
|
||||||
|
* bsd_helper.h: Ditto.
|
||||||
|
* bsd_log.cc: Ditto.
|
||||||
|
* bsd_log.h: Ditto.
|
||||||
|
* bsd_mutex.cc: Ditto.
|
||||||
|
* bsd_mutex.h: Ditto.
|
||||||
|
* client.cc: Rearrange to build as less as possible if
|
||||||
|
__INSIDE_CYGWIN__.
|
||||||
|
(client_request::handle_request): Add Message Queue and Semaphore
|
||||||
|
handling.
|
||||||
|
* cygserver.cc: Rearrange to build as less as possible if
|
||||||
|
__INSIDE_CYGWIN__. Use new debug/log/panic logging functions.
|
||||||
|
(DEF_CONFIG_FILE): New definition for configuration file. Use
|
||||||
|
throughout.
|
||||||
|
(getfunc): Remove.
|
||||||
|
(__cygserver__printf): Remove.
|
||||||
|
(client_request_attach_tty::serve): Return error if impersonation
|
||||||
|
fails.
|
||||||
|
(print_usage): Pump up help message.
|
||||||
|
(print_version): Add output of default configuration file.
|
||||||
|
(main): Accommodate new options. Allow overwrite of threading options
|
||||||
|
from config file. Call several new initialization functions. Drop
|
||||||
|
printing dots. Don't define SIGHANDLE inline.
|
||||||
|
* cygserver.conf: New file.
|
||||||
|
* cygserver_process.h: Rename to process.h.
|
||||||
|
* cygserver_transport.h: Rename to transport.h.
|
||||||
|
* cygserver_transport_pipes.h: Rename to transport_pipes.h.
|
||||||
|
* cygserver_transport_sockets.h: Rename to transport_sockets.h.
|
||||||
|
* msg.cc: Rewrite.
|
||||||
|
* sem.cc: Rewrite.
|
||||||
|
* shm.cc: Rewrite.
|
||||||
|
* sysv_msg.cc: New file, derived from FreeBSD version 1.52.
|
||||||
|
* sysv_sem.cc: New file, derived from FreeBSD version 1.66.
|
||||||
|
* sysv_shm.cc: New file, derived from FreeBSD version 1.89.
|
||||||
|
* threaded_queue.cc: Rearrange to build as less as possible if
|
||||||
|
__INSIDE_CYGWIN__.
|
||||||
|
* transport.cc (transport_layer_base::impersonate_client): Define bool.
|
||||||
|
(transport_layer_base::revert_to_self): Ditto.
|
||||||
|
* transport.h (transport_layer_base::impersonate_client): Declare bool.
|
||||||
|
(transport_layer_base::revert_to_self): Ditto.
|
||||||
|
* transport_pipes.cc (transport_layer_pipes::transport_layer_pipes):
|
||||||
|
Don't call init_security.
|
||||||
|
(init_security): Remove.
|
||||||
|
(transport_layer_pipes::accept): Use global sec_all_nih.
|
||||||
|
(transport_layer_pipes::connect): Ditto.
|
||||||
|
(transport_layer_pipes::impersonate_client): Define bool.
|
||||||
|
(transport_layer_pipes::revert_to_self): Ditt.
|
||||||
|
* transport_pipes.h (transport_layer_pipes::impersonate_client): Declare
|
||||||
|
bool.
|
||||||
|
(transport_layer_pipes::revert_to_self): Ditto.
|
||||||
|
* woutsup.h: Include bsd compatibility headers.
|
||||||
|
(SIGHANDLE): Add definition.
|
||||||
|
(__cygserver__printf): Remove definition.
|
||||||
|
(__noop_printf): Ditto.
|
||||||
|
(debug_printf): Define using debug.
|
||||||
|
(syscall_printf): Define using log.
|
||||||
|
(system_printf): Ditto.
|
||||||
|
Drop all other _printf definitions.
|
||||||
|
|
||||||
2003-10-22 Corinna Vinschen <corinna@vinschen.de>
|
2003-10-22 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
Accomodate moving cygserver header files from cygwin/include/cygwin
|
Accomodate moving cygserver header files from cygwin/include/cygwin
|
||||||
|
|
|
@ -15,7 +15,8 @@ prefix:=@prefix@
|
||||||
exec_prefix:=@exec_prefix@
|
exec_prefix:=@exec_prefix@
|
||||||
|
|
||||||
bindir:=@bindir@
|
bindir:=@bindir@
|
||||||
etcdir:=$(exec_prefix)/etc
|
sbindir:=@sbindir@
|
||||||
|
sysconfdir:=@sysconfdir@
|
||||||
program_transform_name:=@program_transform_name@
|
program_transform_name:=@program_transform_name@
|
||||||
|
|
||||||
INSTALL:=@INSTALL@
|
INSTALL:=@INSTALL@
|
||||||
|
@ -28,14 +29,18 @@ CXX:=@CXX@
|
||||||
CXX_FOR_TARGET:=$(CXX)
|
CXX_FOR_TARGET:=$(CXX)
|
||||||
AR:=@AR@
|
AR:=@AR@
|
||||||
|
|
||||||
CFLAGS:=@CFLAGS@ -I$(cygwin_source)
|
|
||||||
CXXFLAGS:=@CXXFLAGS@ -I$(cygwin_source)
|
|
||||||
override CXXFLAGS+=-fno-exceptions -fno-rtti -DHAVE_DECL_GETOPT=0 -D__OUTSIDE_CYGWIN__
|
|
||||||
|
|
||||||
include $(srcdir)/../Makefile.common
|
include $(srcdir)/../Makefile.common
|
||||||
|
|
||||||
|
CFLAGS:=@CFLAGS@ -I$(cygwin_source)
|
||||||
|
CXXFLAGS:=@CXXFLAGS@ -I$(cygwin_source)
|
||||||
|
override CXXFLAGS+=-MMD -fno-exceptions -fno-rtti -DHAVE_DECL_GETOPT=0 -D__OUTSIDE_CYGWIN__ -DSYSCONFDIR="\"$(sysconfdir)\""
|
||||||
|
|
||||||
|
.SUFFIXES: .c .cc .a .o .d
|
||||||
|
|
||||||
OBJS:= cygserver.o client.o process.o msg.o sem.o shm.o threaded_queue.o \
|
OBJS:= cygserver.o client.o process.o msg.o sem.o shm.o threaded_queue.o \
|
||||||
transport.o transport_pipes.o transport_sockets.o
|
transport.o transport_pipes.o transport_sockets.o \
|
||||||
|
bsd_helper.o bsd_log.o bsd_mutex.o \
|
||||||
|
sysv_msg.o sysv_sem.o sysv_shm.o
|
||||||
LIBOBJS:=${patsubst %.o,lib%.o,$(OBJS)}
|
LIBOBJS:=${patsubst %.o,lib%.o,$(OBJS)}
|
||||||
|
|
||||||
CYGWIN_OBJS:=$(cygwin_build)/smallprint.o $(cygwin_build)/version.o \
|
CYGWIN_OBJS:=$(cygwin_build)/smallprint.o $(cygwin_build)/version.o \
|
||||||
|
@ -43,10 +48,17 @@ CYGWIN_OBJS:=$(cygwin_build)/smallprint.o $(cygwin_build)/version.o \
|
||||||
|
|
||||||
all: cygserver.exe
|
all: cygserver.exe
|
||||||
|
|
||||||
install: all
|
install: all cygserver.conf
|
||||||
|
$(INSTALL_PROGRAM) cygserver.exe $(sbindir)/cygserver.exe
|
||||||
|
$(INSTALL_DATA) $(srcdir)/cygserver.conf $(sysconfdir)/cygserver.conf
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS)
|
rm -f $(OBJS) ${patsubst %.o,%.d,$(OBJS)} cygserver.exe
|
||||||
|
|
||||||
|
libclean:
|
||||||
|
rm -f $(LIBOBJS) ${patsubst %.o,%.d,$(LIBOBJS)} libcygserver.a
|
||||||
|
|
||||||
|
fullclean: clean libclean
|
||||||
|
|
||||||
cygserver.exe: $(OBJS) $(CYGWIN_OBJS)
|
cygserver.exe: $(OBJS) $(CYGWIN_OBJS)
|
||||||
$(CXX) -o $@ $^
|
$(CXX) -o $@ $^
|
||||||
|
@ -64,3 +76,8 @@ lib%.o: %.cc
|
||||||
|
|
||||||
libcygserver.a: $(LIBOBJS)
|
libcygserver.a: $(LIBOBJS)
|
||||||
$(AR) crus $@ $?
|
$(AR) crus $@ $?
|
||||||
|
|
||||||
|
deps:=${wildcard *.d}
|
||||||
|
ifneq (,$(deps))
|
||||||
|
include $(deps)
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,694 @@
|
||||||
|
/* bsd_helper.cc
|
||||||
|
|
||||||
|
Copyright 2003 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 __OUTSIDE_CYGWIN__
|
||||||
|
#include "woutsup.h"
|
||||||
|
#include "cygerrno.h"
|
||||||
|
#define _KERNEL 1
|
||||||
|
#define __BSD_VISIBLE 1
|
||||||
|
#include <sys/smallprint.h>
|
||||||
|
#include <sys/cygwin.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/msg.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "security.h"
|
||||||
|
#include "cygserver.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "cygserver_ipc.h"
|
||||||
|
#include "cygserver_msg.h"
|
||||||
|
#include "cygserver_sem.h"
|
||||||
|
#include "cygserver_shm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy a piece of memory from the client process into the server process.
|
||||||
|
* Returns an error code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
win_copyin (struct thread *td, const void *client_src,
|
||||||
|
void *server_tgt, size_t len)
|
||||||
|
{
|
||||||
|
if (!ReadProcessMemory (td->client->handle (), client_src, server_tgt,
|
||||||
|
len, NULL))
|
||||||
|
return cygwin_internal (CW_GET_ERRNO_FROM_WINERROR,
|
||||||
|
GetLastError (), EINVAL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy a piece of memory from the server process into the client process.
|
||||||
|
* Returns an error code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
win_copyout (struct thread *td, const void *server_src,
|
||||||
|
void *client_tgt, size_t len)
|
||||||
|
{
|
||||||
|
if (!WriteProcessMemory (td->client->handle (), client_tgt, server_src,
|
||||||
|
len, NULL))
|
||||||
|
return cygwin_internal (CW_GET_ERRNO_FROM_WINERROR,
|
||||||
|
GetLastError (), EINVAL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define enter_critical_section(c) _enter_critical_section((c),__FILE__,__LINE__)
|
||||||
|
static void
|
||||||
|
_enter_critical_section (LPCRITICAL_SECTION pcs, const char *file, int line)
|
||||||
|
{
|
||||||
|
_log (file, line, LOG_DEBUG, "Try enter critical section(%p)", pcs);
|
||||||
|
EnterCriticalSection (pcs);
|
||||||
|
_log (file, line, LOG_DEBUG, "Entered critical section(%p)", pcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define leave_critical_section(c) _leave_critical_section((c),__FILE__,__LINE__)
|
||||||
|
static void
|
||||||
|
_leave_critical_section (LPCRITICAL_SECTION pcs, const char *file, int line)
|
||||||
|
{
|
||||||
|
LeaveCriticalSection (pcs);
|
||||||
|
_log (file, line, LOG_DEBUG, "Left critical section(%p)", pcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
CRITICAL_SECTION ipcht_cs;
|
||||||
|
|
||||||
|
struct ipc_hookthread_storage {
|
||||||
|
HANDLE process_hdl;
|
||||||
|
proc ipcblk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipc_hookthread {
|
||||||
|
SLIST_ENTRY(ipc_hookthread) sht_next;
|
||||||
|
HANDLE thread;
|
||||||
|
DWORD winpid;
|
||||||
|
struct vmspace vmspace;
|
||||||
|
};
|
||||||
|
static SLIST_HEAD(, ipc_hookthread) ipcht_list; /* list of hook threads */
|
||||||
|
|
||||||
|
static HANDLE ipcexit_event;
|
||||||
|
|
||||||
|
struct vmspace *
|
||||||
|
ipc_p_vmspace (struct proc *proc)
|
||||||
|
{
|
||||||
|
struct vmspace *ret = NULL;
|
||||||
|
ipc_hookthread *ipcht_entry;
|
||||||
|
enter_critical_section (&ipcht_cs);
|
||||||
|
SLIST_FOREACH (ipcht_entry, &ipcht_list, sht_next)
|
||||||
|
{
|
||||||
|
if (ipcht_entry->winpid == proc->winpid)
|
||||||
|
{
|
||||||
|
ret = proc->p_vmspace = &ipcht_entry->vmspace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave_critical_section (&ipcht_cs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI
|
||||||
|
ipcexit_hookthread(const LPVOID param)
|
||||||
|
{
|
||||||
|
ipc_hookthread_storage *shs = (ipc_hookthread_storage *) param;
|
||||||
|
HANDLE obj[2] = { ipcexit_event, shs->process_hdl };
|
||||||
|
switch (WaitForMultipleObjects (2, obj, FALSE, INFINITE))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
/* Cygserver shutdown. */
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
/* Process exited. Call semexit_myhook to handle SEM_UNDOs for the
|
||||||
|
exiting process and shmexit_myhook to keep track of shared
|
||||||
|
memory. */
|
||||||
|
if (Giant.owner == shs->ipcblk.winpid)
|
||||||
|
mtx_unlock (&Giant);
|
||||||
|
if (support_semaphores == TUN_TRUE)
|
||||||
|
semexit_myhook (NULL, &shs->ipcblk);
|
||||||
|
if (support_sharedmem == TUN_TRUE)
|
||||||
|
{
|
||||||
|
_mtx_lock (&Giant, shs->ipcblk.winpid, __FILE__, __LINE__);
|
||||||
|
ipc_p_vmspace (&shs->ipcblk);
|
||||||
|
shmexit_myhook (shs->ipcblk.p_vmspace);
|
||||||
|
mtx_unlock (&Giant);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* FIXME: Panic? */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CloseHandle (shs->process_hdl);
|
||||||
|
ipc_hookthread *ipcht_entry, *sav_entry;
|
||||||
|
enter_critical_section (&ipcht_cs);
|
||||||
|
SLIST_FOREACH_SAFE (ipcht_entry, &ipcht_list, sht_next, sav_entry)
|
||||||
|
{
|
||||||
|
if (ipcht_entry->winpid == shs->ipcblk.winpid)
|
||||||
|
{
|
||||||
|
SLIST_REMOVE (&ipcht_list, ipcht_entry, ipc_hookthread, sht_next);
|
||||||
|
delete ipcht_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave_critical_section (&ipcht_cs);
|
||||||
|
delete shs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deletes all pending hook threads. Called by ipcunload() which in turn
|
||||||
|
is called by the cygserver main routine. */
|
||||||
|
static void
|
||||||
|
ipcexit_dispose_hookthreads(void)
|
||||||
|
{
|
||||||
|
SetEvent (ipcexit_event);
|
||||||
|
ipc_hookthread *ipcht_entry;
|
||||||
|
enter_critical_section (&ipcht_cs);
|
||||||
|
SLIST_FOREACH (ipcht_entry, &ipcht_list, sht_next)
|
||||||
|
{
|
||||||
|
WaitForSingleObject (ipcht_entry->thread, 1000);
|
||||||
|
/* Don't bother removing the linked list on cygserver shutdown. */
|
||||||
|
/* FIXME: Error handling? */
|
||||||
|
}
|
||||||
|
leave_critical_section (&ipcht_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates the per process wait thread. Called by semget() under locked
|
||||||
|
Giant mutex condition. */
|
||||||
|
int
|
||||||
|
ipcexit_creat_hookthread(struct thread *td)
|
||||||
|
{
|
||||||
|
ipc_hookthread *ipcht_entry;
|
||||||
|
int ret = -1;
|
||||||
|
enter_critical_section (&ipcht_cs);
|
||||||
|
SLIST_FOREACH (ipcht_entry, &ipcht_list, sht_next)
|
||||||
|
{
|
||||||
|
if (ipcht_entry->winpid == td->ipcblk->winpid)
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
leave_critical_section (&ipcht_cs);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DWORD tid;
|
||||||
|
ipc_hookthread_storage *shs = new ipc_hookthread_storage;
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), td->client->handle (),
|
||||||
|
GetCurrentProcess (), &shs->process_hdl,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
log (LOG_CRIT, "failed to duplicate process handle, error = %lu",
|
||||||
|
GetLastError ());
|
||||||
|
return cygwin_internal (CW_GET_ERRNO_FROM_WINERROR,
|
||||||
|
GetLastError (), ENOMEM);
|
||||||
|
}
|
||||||
|
shs->ipcblk = *td->ipcblk;
|
||||||
|
HANDLE thread = CreateThread (NULL, 0, ipcexit_hookthread, shs, 0, &tid);
|
||||||
|
if (!thread)
|
||||||
|
{
|
||||||
|
log (LOG_CRIT, "failed to create thread, error = %lu", GetLastError ());
|
||||||
|
return cygwin_internal (CW_GET_ERRNO_FROM_WINERROR,
|
||||||
|
GetLastError (), ENOMEM);
|
||||||
|
}
|
||||||
|
ipcht_entry = new ipc_hookthread;
|
||||||
|
ipcht_entry->thread = thread;
|
||||||
|
ipcht_entry->winpid = td->ipcblk->winpid;
|
||||||
|
ipcht_entry->vmspace.vm_map = NULL;
|
||||||
|
ipcht_entry->vmspace.vm_shm = NULL;
|
||||||
|
enter_critical_section (&ipcht_cs);
|
||||||
|
SLIST_INSERT_HEAD (&ipcht_list, ipcht_entry, sht_next);
|
||||||
|
leave_critical_section (&ipcht_cs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need the admins group SID to compare with groups in client token.
|
||||||
|
*/
|
||||||
|
PSID admininstrator_group_sid;
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_admin_sid (void)
|
||||||
|
{
|
||||||
|
if (wincap.has_security ())
|
||||||
|
{
|
||||||
|
SID_IDENTIFIER_AUTHORITY nt_auth = {SECURITY_NT_AUTHORITY};
|
||||||
|
if (! AllocateAndInitializeSid (&nt_auth, 2, 32, 544, 0, 0, 0, 0, 0, 0,
|
||||||
|
&admininstrator_group_sid))
|
||||||
|
panic ("failed to create well known sids, error = %lu",
|
||||||
|
GetLastError ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECURITY_DESCRIPTOR sec_all_nih_sd;
|
||||||
|
SECURITY_ATTRIBUTES sec_all_nih = { sizeof (SECURITY_ATTRIBUTES),
|
||||||
|
&sec_all_nih_sd,
|
||||||
|
FALSE };
|
||||||
|
|
||||||
|
/* Global vars, determining whether the IPC stuff should be started or not. */
|
||||||
|
tun_bool_t support_sharedmem = TUN_UNDEF;
|
||||||
|
tun_bool_t support_msgqueues = TUN_UNDEF;
|
||||||
|
tun_bool_t support_semaphores = TUN_UNDEF;
|
||||||
|
|
||||||
|
void
|
||||||
|
ipcinit ()
|
||||||
|
{
|
||||||
|
InitializeSecurityDescriptor (&sec_all_nih_sd, SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
SetSecurityDescriptorDacl (&sec_all_nih_sd, TRUE, 0, FALSE);
|
||||||
|
|
||||||
|
init_admin_sid ();
|
||||||
|
mtx_init(&Giant, "Giant", NULL, MTX_DEF);
|
||||||
|
msleep_init ();
|
||||||
|
ipcexit_event = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
|
if (!ipcexit_event)
|
||||||
|
panic ("Failed to create ipcexit event object");
|
||||||
|
InitializeCriticalSection (&ipcht_cs);
|
||||||
|
if (support_msgqueues == TUN_TRUE)
|
||||||
|
msginit ();
|
||||||
|
if (support_semaphores == TUN_TRUE)
|
||||||
|
seminit ();
|
||||||
|
if (support_sharedmem == TUN_TRUE)
|
||||||
|
shminit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipcunload ()
|
||||||
|
{
|
||||||
|
ipcexit_dispose_hookthreads();
|
||||||
|
CloseHandle (ipcexit_event);
|
||||||
|
wakeup_all ();
|
||||||
|
if (support_semaphores == TUN_TRUE)
|
||||||
|
semunload ();
|
||||||
|
if (support_sharedmem == TUN_TRUE)
|
||||||
|
shmunload ();
|
||||||
|
if (support_msgqueues == TUN_TRUE)
|
||||||
|
msgunload();
|
||||||
|
mtx_destroy(&Giant);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to find a gid in a list of gids.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
is_grp_member (gid_t grp, gid_t *grplist, int listsize)
|
||||||
|
{
|
||||||
|
if (grplist)
|
||||||
|
for (; listsize > 0; --listsize)
|
||||||
|
if (grp == grplist[listsize - 1])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to get a specific token information from a token.
|
||||||
|
* This function mallocs the necessary buffer spcae by itself. It
|
||||||
|
* must be free'd by the calling function.
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
get_token_info (HANDLE tok, TOKEN_INFORMATION_CLASS tic)
|
||||||
|
{
|
||||||
|
void *buf;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
if (!GetTokenInformation (tok, tic, NULL, 0, &size)
|
||||||
|
&& GetLastError () != ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
return NULL;
|
||||||
|
if (!(buf = malloc (size)))
|
||||||
|
return NULL;
|
||||||
|
if (!GetTokenInformation (tok, tic, buf, size, &size))
|
||||||
|
{
|
||||||
|
free (buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if client user helds "mode" permission when accessing object
|
||||||
|
* associated with "perm" permission record.
|
||||||
|
* Returns an error code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ipcperm (struct thread *td, ipc_perm *perm, unsigned int mode)
|
||||||
|
{
|
||||||
|
proc *p = td->ipcblk;
|
||||||
|
|
||||||
|
if (!suser (td))
|
||||||
|
return 0;
|
||||||
|
if (mode & IPC_M)
|
||||||
|
{
|
||||||
|
return (p->uid != perm->cuid && p->uid != perm->uid)
|
||||||
|
? EACCES : 0;
|
||||||
|
}
|
||||||
|
if (p->uid != perm->cuid && p->uid != perm->uid)
|
||||||
|
{
|
||||||
|
/* If the user is a member of the creator or owner group, test
|
||||||
|
against group bits, otherwise against other bits. */
|
||||||
|
mode >>= p->gid != perm->gid && p->gid != perm->cgid
|
||||||
|
&& !is_grp_member (perm->gid, p->gidlist, p->gidcnt)
|
||||||
|
&& !is_grp_member (perm->cgid, p->gidlist, p->gidcnt)
|
||||||
|
? 6 : 3;
|
||||||
|
}
|
||||||
|
return (mode & perm->mode) != mode ? EACCES : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for client user being superuser.
|
||||||
|
* Returns an error code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
suser (struct thread *td)
|
||||||
|
{
|
||||||
|
/* Always superuser on 9x. */
|
||||||
|
if (!wincap.has_security ())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* This value has been set at ImpersonateNamedPipeClient() time
|
||||||
|
using the token information. See adjust_identity_info() below. */
|
||||||
|
return td->ipcblk->is_admin ? 0 : EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieves user and group info from impersonated token and creates the
|
||||||
|
* correct uid, gid, gidlist and is_admin entries in p from that.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
adjust_identity_info (struct proc *p)
|
||||||
|
{
|
||||||
|
HANDLE tok;
|
||||||
|
|
||||||
|
/* No access tokens on 9x. */
|
||||||
|
if (!wincap.has_security ())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!OpenThreadToken (GetCurrentThread (), TOKEN_READ, TRUE, &tok))
|
||||||
|
{
|
||||||
|
debug ("Failed to open worker thread access token for pid %d, winpid %d",
|
||||||
|
p->cygpid, p->winpid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get uid from user SID in token. */
|
||||||
|
PTOKEN_USER user;
|
||||||
|
if (!(user = (PTOKEN_USER)get_token_info (tok, TokenUser)))
|
||||||
|
goto faulty;
|
||||||
|
p->uid = cygwin_internal (CW_GET_UID_FROM_SID, user->User.Sid);
|
||||||
|
free (user);
|
||||||
|
if (p->uid == (uid_t)-1)
|
||||||
|
log (LOG_WARNING, "WARNING: User not found in /etc/passwd! Using uid -1!");
|
||||||
|
|
||||||
|
/* Get gid from primary group SID in token. */
|
||||||
|
PTOKEN_PRIMARY_GROUP pgrp;
|
||||||
|
if (!(pgrp = (PTOKEN_PRIMARY_GROUP)get_token_info (tok, TokenPrimaryGroup)))
|
||||||
|
goto faulty;
|
||||||
|
p->gid = cygwin_internal (CW_GET_GID_FROM_SID, pgrp->PrimaryGroup);
|
||||||
|
free (pgrp);
|
||||||
|
if (p->gid == (gid_t)-1)
|
||||||
|
log (LOG_WARNING,"WARNING: Group not found in /etc/passwd! Using gid -1!");
|
||||||
|
|
||||||
|
/* Generate gid list from token group's SID list. Also look if the token
|
||||||
|
has an enabled admin group SID. That means, the process has admin
|
||||||
|
privileges. That knowledge is used in suser(). */
|
||||||
|
PTOKEN_GROUPS gsids;
|
||||||
|
if (!(gsids = (PTOKEN_GROUPS)get_token_info (tok, TokenGroups)))
|
||||||
|
goto faulty;
|
||||||
|
if (gsids->GroupCount)
|
||||||
|
{
|
||||||
|
p->gidlist = (gid_t *) calloc (gsids->GroupCount, sizeof (gid_t));
|
||||||
|
if (p->gidlist)
|
||||||
|
p->gidcnt = gsids->GroupCount;
|
||||||
|
}
|
||||||
|
for (DWORD i = 0; i < gsids->GroupCount; ++i)
|
||||||
|
{
|
||||||
|
if (p->gidlist)
|
||||||
|
p->gidlist[i] = cygwin_internal (CW_GET_GID_FROM_SID,
|
||||||
|
gsids->Groups[i].Sid);
|
||||||
|
if (EqualSid (gsids->Groups[i].Sid, admininstrator_group_sid)
|
||||||
|
&& (gsids->Groups[i].Attributes & SE_GROUP_ENABLED))
|
||||||
|
p->is_admin = true;
|
||||||
|
}
|
||||||
|
free (gsids);
|
||||||
|
|
||||||
|
CloseHandle (tok);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
faulty:
|
||||||
|
CloseHandle (tok);
|
||||||
|
log (LOG_CRIT, "Failed to get token information for pid %d, winpid %d",
|
||||||
|
p->cygpid, p->winpid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows wrapper implementation of the VM functions called by sysv_shm.cc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
vm_object_t
|
||||||
|
_vm_pager_allocate (int size, int shmflg)
|
||||||
|
{
|
||||||
|
/* Create the file mapping object with full access for everyone. This is
|
||||||
|
necessary to allow later calls to shmctl(..., IPC_SET,...) to
|
||||||
|
change the access rights and ownership of a shared memory region.
|
||||||
|
The access rights are tested at the beginning of every shm... function.
|
||||||
|
Note that this does not influence the actual read or write access
|
||||||
|
defined in a call to shmat. */
|
||||||
|
vm_object_t object = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_all_nih,
|
||||||
|
PAGE_READWRITE, 0, size, NULL);
|
||||||
|
if (!object)
|
||||||
|
panic ("CreateFileMapping in _vm_pager_allocate failed, %E");
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_object_t
|
||||||
|
vm_object_duplicate (struct thread *td, vm_object_t object)
|
||||||
|
{
|
||||||
|
vm_object_t dup_object;
|
||||||
|
if (!DuplicateHandle(GetCurrentProcess (), object,
|
||||||
|
td->client->handle (), &dup_object,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
panic ("!DuplicateHandle in vm_object_duplicate failed, %E");
|
||||||
|
return dup_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vm_object_deallocate (vm_object_t object)
|
||||||
|
{
|
||||||
|
if (object)
|
||||||
|
CloseHandle (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tunable parameters are read from a system wide cygserver.conf file.
|
||||||
|
* On the first call to tunable_int_fetch, the file is read and the
|
||||||
|
* parameters are set accordingly. Each parameter has default, max and
|
||||||
|
* min settings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum tun_params_type {
|
||||||
|
TUN_NULL,
|
||||||
|
TUN_INT,
|
||||||
|
TUN_BOOL
|
||||||
|
};
|
||||||
|
|
||||||
|
union tun_value {
|
||||||
|
long ival;
|
||||||
|
tun_bool_t bval;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tun_struct {
|
||||||
|
const char *name;
|
||||||
|
tun_params_type type;
|
||||||
|
union tun_value value;
|
||||||
|
union tun_value min;
|
||||||
|
union tun_value max;
|
||||||
|
void (*check_func)(tun_struct *, char *, const char *);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_tun_check (tun_struct *that, char *value, const char *fname)
|
||||||
|
{
|
||||||
|
char *c = NULL;
|
||||||
|
tun_value val;
|
||||||
|
switch (that->type)
|
||||||
|
{
|
||||||
|
case TUN_INT:
|
||||||
|
val.ival = strtoul (value, &c, 10);
|
||||||
|
if (!val.ival || (c && *c))
|
||||||
|
panic ("Error in config file %s: Value of parameter %s malformed",
|
||||||
|
fname, that->name);
|
||||||
|
if (val.ival < that->min.ival || val.ival > that->max.ival)
|
||||||
|
panic ("Error in config file %s: Value of parameter %s must be "
|
||||||
|
"between %lu and %lu",
|
||||||
|
fname, that->name, that->min.ival, that->max.ival);
|
||||||
|
if (that->value.ival)
|
||||||
|
panic ("Error in config file %s: Parameter %s set twice.\n",
|
||||||
|
fname, that->name);
|
||||||
|
that->value.ival = val.ival;
|
||||||
|
break;
|
||||||
|
case TUN_BOOL:
|
||||||
|
if (!strcasecmp (value, "no") || !strcasecmp (value, "n")
|
||||||
|
|| !strcasecmp (value, "false") || !strcasecmp (value, "f")
|
||||||
|
|| !strcasecmp (value, "0"))
|
||||||
|
val.bval = TUN_FALSE;
|
||||||
|
else if (!strcasecmp (value, "yes") || !strcasecmp (value, "y")
|
||||||
|
|| !strcasecmp (value, "true") || !strcasecmp (value, "t")
|
||||||
|
|| !strcasecmp (value, "1"))
|
||||||
|
val.bval = TUN_TRUE;
|
||||||
|
else
|
||||||
|
panic ("Error in config file %s: Value of parameter %s malformed\n"
|
||||||
|
"Allowed values: \"yes\", \"no\", \"y\", \"n\", \"true\", \"false\", \"t\", \"f\", \"1\" and \"0\"", fname, that->name);
|
||||||
|
that->value.bval = val.bval;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Shouldn't happen. */
|
||||||
|
panic ("Internal error: Wrong type of tunable parameter");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static tun_struct tunable_params[] =
|
||||||
|
{
|
||||||
|
/* SRV */
|
||||||
|
{ "kern.srv.cleanup_threads", TUN_INT, {0}, {1}, {16}, default_tun_check},
|
||||||
|
{ "kern.srv.request_threads", TUN_INT, {0}, {1}, {64}, default_tun_check},
|
||||||
|
{ "kern.srv.sharedmem", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
{ "kern.srv.msgqueues", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
{ "kern.srv.semaphores", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
|
||||||
|
/* LOG */
|
||||||
|
{ "kern.log.syslog", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
{ "kern.log.stderr", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
{ "kern.log.debug", TUN_BOOL, {TUN_UNDEF}, {TUN_FALSE}, {TUN_TRUE}, default_tun_check},
|
||||||
|
{ "kern.log.level", TUN_INT, {0}, {1}, {7}, default_tun_check},
|
||||||
|
|
||||||
|
/* MSG */
|
||||||
|
{ "kern.ipc.msgseg", TUN_INT, {0}, {256}, {32767}, default_tun_check},
|
||||||
|
{ "kern.ipc.msgssz", TUN_INT, {0}, {8}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.msgmni", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
|
||||||
|
/* SEM */
|
||||||
|
//{ "kern.ipc.semmap", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semmni", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semmns", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semmnu", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semmsl", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semopm", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semume", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
//{ "kern.ipc.semusz", TUN_INT, {0}, {1}, {1024}, default_tun_check},
|
||||||
|
{ "kern.ipc.semvmx", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
{ "kern.ipc.semaem", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
|
||||||
|
/* SHM */
|
||||||
|
{ "kern.ipc.shmmaxpgs", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
//{ "kern.ipc.shmmin", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
{ "kern.ipc.shmmni", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
{ "kern.ipc.shmseg", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
//{ "kern.ipc.shm_use_phys", TUN_INT, {0}, {1}, {32767}, default_tun_check},
|
||||||
|
{ NULL, TUN_NULL, {0}, {0}, {0}, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define skip_whitespace(c) while (*(c) && isspace (*(c))) ++(c)
|
||||||
|
#define skip_nonwhitespace(c) while (*(c) && !isspace (*(c)) && *(c) != '#') ++(c)
|
||||||
|
#define end_of_content(c) (!*(c) || *(c) == '#')
|
||||||
|
|
||||||
|
void
|
||||||
|
tunable_param_init (const char *config_file, bool force)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen (config_file, "rt");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
if (force)
|
||||||
|
panic ("can't open config file %s\n", config_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char line[1024];
|
||||||
|
while (fgets (line, 1024, fp))
|
||||||
|
{
|
||||||
|
char *c = strrchr (line, '\n');
|
||||||
|
if (!c)
|
||||||
|
panic ("Line too long in confg file %s\n", config_file);
|
||||||
|
/* Overwrite trailing NL. */
|
||||||
|
*c = '\0';
|
||||||
|
c = line;
|
||||||
|
skip_whitespace (c);
|
||||||
|
if (end_of_content (c))
|
||||||
|
continue;
|
||||||
|
/* So we are on the first character of a parameter name. */
|
||||||
|
char *name = c;
|
||||||
|
/* Find end of name. */
|
||||||
|
skip_nonwhitespace (c);
|
||||||
|
if (end_of_content (c))
|
||||||
|
{
|
||||||
|
*c++ = '\0';
|
||||||
|
panic ("Error in config file %s: Parameter %s has no value.\n",
|
||||||
|
config_file, name);
|
||||||
|
}
|
||||||
|
/* Mark end of name. */
|
||||||
|
*c++ = '\0';
|
||||||
|
skip_whitespace (c);
|
||||||
|
if (end_of_content (c))
|
||||||
|
panic ("Error in config file %s: Parameter %s has no value.\n",
|
||||||
|
config_file, name);
|
||||||
|
/* Now we are on the first character of a parameter's value. */
|
||||||
|
char *value = c;
|
||||||
|
/* This only works for simple parameters. If complex string parameters
|
||||||
|
are added at one point, the scanning routine must be changed here. */
|
||||||
|
/* Find end of value. */
|
||||||
|
skip_nonwhitespace (c);
|
||||||
|
/* Mark end of value. */
|
||||||
|
*c++ = '\0';
|
||||||
|
/* Now look if name is one from our list. */
|
||||||
|
tun_struct *s;
|
||||||
|
for (s = &tunable_params[0]; s->name; ++s)
|
||||||
|
if (!strcmp (name, s->name))
|
||||||
|
{
|
||||||
|
/* Now read value and check for validity. check_func doesn't
|
||||||
|
return on error. */
|
||||||
|
s->check_func (s, value, config_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!s->name)
|
||||||
|
panic ("Error in config file %s: Unknown parameter %s.\n",
|
||||||
|
config_file, name);
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tunable_int_fetch (const char *name, long *tunable_target)
|
||||||
|
{
|
||||||
|
tun_struct *s;
|
||||||
|
for (s = &tunable_params[0]; s->name; ++s)
|
||||||
|
if (!strcmp (name, s->name))
|
||||||
|
break;
|
||||||
|
if (!s) /* Not found */
|
||||||
|
return;
|
||||||
|
if (s->type != TUN_INT) /* Wrong type */
|
||||||
|
return;
|
||||||
|
if (!s->value.ival) /* Not set in config file */
|
||||||
|
return;
|
||||||
|
*tunable_target = s->value.ival;
|
||||||
|
debug ("\nSet %s to %lu\n", name, *tunable_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tunable_bool_fetch (const char *name, tun_bool_t *tunable_target)
|
||||||
|
{
|
||||||
|
tun_struct *s;
|
||||||
|
const char *tun_bool_val_string[] = { "undefined", "no", "yes" };
|
||||||
|
for (s = &tunable_params[0]; s->name; ++s)
|
||||||
|
if (!strcmp (name, s->name))
|
||||||
|
break;
|
||||||
|
if (!s) /* Not found */
|
||||||
|
return;
|
||||||
|
if (s->type != TUN_BOOL) /* Wrong type */
|
||||||
|
return;
|
||||||
|
if (!s->value.ival) /* Not set in config file */
|
||||||
|
return;
|
||||||
|
*tunable_target = s->value.bval;
|
||||||
|
debug ("\nSet %s to %s\n", name, tun_bool_val_string[*tunable_target]);
|
||||||
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* bsd_helper.h: Helps integrating BSD kernel code
|
||||||
|
|
||||||
|
Copyright 2003 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. */
|
||||||
|
#ifndef _BSD_HELPER_H
|
||||||
|
#define _BSD_HELPER_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/syslog.h>
|
||||||
|
|
||||||
|
enum tun_bool_t {
|
||||||
|
TUN_UNDEF = 0,
|
||||||
|
TUN_FALSE = 1,
|
||||||
|
TUN_TRUE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TUNABLE_INT_FETCH(a,b) tunable_int_fetch((a),(b))
|
||||||
|
#define TUNABLE_BOOL_FETCH(a,b) tunable_bool_fetch((a),(b))
|
||||||
|
|
||||||
|
#define sys_malloc(a,b,c) (malloc(a)?:(panic("malloc failed in %s, line %d"),(void*)NULL))
|
||||||
|
#define sys_free(a,b) free(a)
|
||||||
|
|
||||||
|
#define jail_sysvipc_allowed true
|
||||||
|
#define jailed(a) false
|
||||||
|
|
||||||
|
extern const char *__progname;
|
||||||
|
|
||||||
|
/* Global vars, determining whether the IPC stuff should be started or not. */
|
||||||
|
extern tun_bool_t support_sharedmem;
|
||||||
|
extern tun_bool_t support_msgqueues;
|
||||||
|
extern tun_bool_t support_semaphores;
|
||||||
|
|
||||||
|
extern SECURITY_ATTRIBUTES sec_all_nih;
|
||||||
|
|
||||||
|
int win_copyin (struct thread *, const void *, void *, size_t);
|
||||||
|
int win_copyout (struct thread *, const void *, void *, size_t);
|
||||||
|
#define copyin(a,b,c) win_copyin((td),(a),(b),(c))
|
||||||
|
#define copyout(a,b,c) win_copyout((td),(a),(b),(c))
|
||||||
|
|
||||||
|
int ipcperm (struct thread *, struct ipc_perm *, unsigned int);
|
||||||
|
int suser (struct thread *);
|
||||||
|
bool adjust_identity_info (struct proc *p);
|
||||||
|
|
||||||
|
struct vmspace *ipc_p_vmspace (struct proc *);
|
||||||
|
int ipcexit_creat_hookthread(struct thread *);
|
||||||
|
void ipcinit (void);
|
||||||
|
int ipcunload (void);
|
||||||
|
|
||||||
|
vm_object_t _vm_pager_allocate (int, int);
|
||||||
|
#define vm_pager_allocate(a,b,s,c,d) _vm_pager_allocate((s),(mode))
|
||||||
|
vm_object_t vm_object_duplicate (struct thread *td, vm_object_t object);
|
||||||
|
void vm_object_deallocate (vm_object_t object);
|
||||||
|
|
||||||
|
void tunable_param_init (const char *, bool);
|
||||||
|
void tunable_int_fetch (const char *, long *);
|
||||||
|
void tunable_bool_fetch (const char *, tun_bool_t *);
|
||||||
|
|
||||||
|
#endif /* _BSD_HELPER_H */
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* bsd_log.cc
|
||||||
|
|
||||||
|
Copyright 2003 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 __OUTSIDE_CYGWIN__
|
||||||
|
#include "woutsup.h"
|
||||||
|
#define _KERNEL 1
|
||||||
|
#define __BSD_VISIBLE 1
|
||||||
|
#include <sys/smallprint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
long log_level = 8; /* Illegal value. Don't change! */
|
||||||
|
tun_bool_t log_debug = TUN_UNDEF;
|
||||||
|
tun_bool_t log_syslog = TUN_UNDEF;
|
||||||
|
tun_bool_t log_stderr = TUN_UNDEF;
|
||||||
|
|
||||||
|
void
|
||||||
|
loginit (tun_bool_t opt_stderr, tun_bool_t opt_syslog)
|
||||||
|
{
|
||||||
|
if (log_debug == TUN_UNDEF)
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.log.debug", &log_debug);
|
||||||
|
if (log_debug == TUN_UNDEF)
|
||||||
|
log_debug = TUN_FALSE;
|
||||||
|
|
||||||
|
if (opt_stderr != TUN_UNDEF)
|
||||||
|
log_stderr = opt_stderr;
|
||||||
|
else
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.log.stderr", &log_stderr);
|
||||||
|
if (log_stderr == TUN_UNDEF)
|
||||||
|
log_stderr = TUN_FALSE;
|
||||||
|
|
||||||
|
if (opt_syslog != TUN_UNDEF)
|
||||||
|
log_syslog = opt_syslog;
|
||||||
|
else
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.log.syslog", &log_syslog);
|
||||||
|
if (log_syslog == TUN_UNDEF)
|
||||||
|
log_syslog = TUN_FALSE;
|
||||||
|
|
||||||
|
if (log_level == 8)
|
||||||
|
TUNABLE_INT_FETCH ("kern.log.level", &log_level);
|
||||||
|
if (log_level == 8)
|
||||||
|
log_level = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_vlog (const char *file, int line, int level,
|
||||||
|
const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[16384];
|
||||||
|
|
||||||
|
if ((level == LOG_DEBUG && log_debug != TUN_TRUE)
|
||||||
|
|| (level != LOG_DEBUG && level >= log_level))
|
||||||
|
return;
|
||||||
|
strcpy (buf, "cygserver: ");
|
||||||
|
if (file && log_debug == TUN_TRUE)
|
||||||
|
__small_sprintf (strchr (buf, '\0'), "%s, line %d: ", file, line);
|
||||||
|
__small_vsprintf (strchr (buf, '\0'), fmt, ap);
|
||||||
|
if (log_syslog == TUN_TRUE && level != LOG_DEBUG)
|
||||||
|
syslog (level, buf);
|
||||||
|
if (log_stderr == TUN_TRUE || level == LOG_DEBUG)
|
||||||
|
{
|
||||||
|
fputs (buf, stderr);
|
||||||
|
fputc ('\n', stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_log (const char *file, int line, int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, fmt);
|
||||||
|
_vlog (file, line, level, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_vpanic (const char *file, int line, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
_vlog (file, line, LOG_EMERG, fmt, ap);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_panic (const char *file, int line, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, fmt);
|
||||||
|
_vpanic (file, line, fmt, ap);
|
||||||
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
|
@ -0,0 +1,33 @@
|
||||||
|
/* bsd_log.h: Helps integrating BSD kernel code
|
||||||
|
|
||||||
|
Copyright 2003 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. */
|
||||||
|
#ifndef _BSD_LOG_H
|
||||||
|
#define _BSD_LOG_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/syslog.h>
|
||||||
|
|
||||||
|
extern long log_level;
|
||||||
|
extern tun_bool_t log_debug;
|
||||||
|
extern tun_bool_t log_syslog;
|
||||||
|
extern tun_bool_t log_stderr;
|
||||||
|
|
||||||
|
void loginit (tun_bool_t, tun_bool_t);
|
||||||
|
void _vlog (const char *, int, int, const char *, va_list);
|
||||||
|
void _log (const char *, int, int, const char *, ...);
|
||||||
|
void _vpanic (const char *, int, const char *, va_list) __attribute__ ((noreturn));
|
||||||
|
void _panic (const char *, int, const char *, ...) __attribute__ ((noreturn));
|
||||||
|
#define vlog(l,f,a) _vlog(NULL,0,(l),(f),(a))
|
||||||
|
#define log(l,f,...) _log(NULL,0,(l),(f),##__VA_ARGS__)
|
||||||
|
#define vdebug(f,a) _vlog(__FILE__,__LINE__,LOG_DEBUG,(f),(a))
|
||||||
|
#define debug(f,...) _log(__FILE__,__LINE__,LOG_DEBUG,(f),##__VA_ARGS__)
|
||||||
|
#define vpanic(f,a) _vpanic(__FILE__,__LINE__,(f),(a))
|
||||||
|
#define panic(f,...) _panic(__FILE__,__LINE__,(f),##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif /* _BSD_LOG_H */
|
|
@ -0,0 +1,253 @@
|
||||||
|
/* bsd_mutex.cc
|
||||||
|
|
||||||
|
Copyright 2003 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 __OUTSIDE_CYGWIN__
|
||||||
|
#include "woutsup.h"
|
||||||
|
#include "cygerrno.h"
|
||||||
|
#define _KERNEL 1
|
||||||
|
#define __BSD_VISIBLE 1
|
||||||
|
#include <sys/smallprint.h>
|
||||||
|
|
||||||
|
#include "process.h"
|
||||||
|
#include "cygserver_ipc.h"
|
||||||
|
|
||||||
|
/* A BSD kernel global mutex. */
|
||||||
|
struct mtx Giant;
|
||||||
|
|
||||||
|
void
|
||||||
|
mtx_init (mtx *m, const char *name, const void *, int)
|
||||||
|
{
|
||||||
|
m->name = name;
|
||||||
|
m->owner = 0;
|
||||||
|
/* Can't use Windows Mutexes here since Windows Mutexes are only
|
||||||
|
unlockable by the lock owner. */
|
||||||
|
m->h = CreateSemaphore (NULL, 1, 1, NULL);
|
||||||
|
if (!m->h)
|
||||||
|
panic ("couldn't allocate %s mutex, %E\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_mtx_lock (mtx *m, DWORD winpid, const char *file, int line)
|
||||||
|
{
|
||||||
|
_log (file, line, LOG_DEBUG, "Try locking mutex %s", m->name);
|
||||||
|
if (WaitForSingleObject (m->h, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
_panic (file, line, "wait for %s in %d failed, %E", m->name, winpid);
|
||||||
|
m->owner = winpid;
|
||||||
|
_log (file, line, LOG_DEBUG, "Locked mutex %s", m->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mtx_owned (mtx *m)
|
||||||
|
{
|
||||||
|
return m->owner > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_mtx_assert(mtx *m, int what, const char *file, int line)
|
||||||
|
{
|
||||||
|
switch (what)
|
||||||
|
{
|
||||||
|
case MA_OWNED:
|
||||||
|
if (!mtx_owned (m))
|
||||||
|
_panic(file, line, "Mutex %s not owned", m->name);
|
||||||
|
break;
|
||||||
|
case MA_NOTOWNED:
|
||||||
|
if (mtx_owned (m))
|
||||||
|
_panic(file, line, "Mutex %s is owned", m->name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_mtx_unlock (mtx *m, const char *file, int line)
|
||||||
|
{
|
||||||
|
m->owner = 0;
|
||||||
|
/* Cautiously check if mtx_destroy has been called (shutdown).
|
||||||
|
In that case, m->h is NULL. */
|
||||||
|
if (m->h && !ReleaseSemaphore (m->h, 1, NULL))
|
||||||
|
{
|
||||||
|
/* Check if the semaphore was already on it's max value. In this case,
|
||||||
|
ReleaseSemaphore returns FALSE with an error code which *sic* depends
|
||||||
|
on the OS. */
|
||||||
|
if ( (!wincap.is_winnt () && GetLastError () != ERROR_INVALID_PARAMETER)
|
||||||
|
|| (wincap.is_winnt () && GetLastError () != ERROR_TOO_MANY_POSTS))
|
||||||
|
_panic (file, line, "release of mutex %s failed, %E", m->name);
|
||||||
|
}
|
||||||
|
_log (file, line, LOG_DEBUG, "Unlocked mutex %s", m->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mtx_destroy (mtx *m)
|
||||||
|
{
|
||||||
|
HANDLE tmp = m->h;
|
||||||
|
m->h = NULL;
|
||||||
|
if (tmp)
|
||||||
|
CloseHandle (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions for msleep/wakeup.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
msleep_event_name (void *ident, char *name)
|
||||||
|
{
|
||||||
|
if (wincap.has_terminal_services ())
|
||||||
|
__small_sprintf (name, "Global\\cygserver.msleep.evt.%08x", ident);
|
||||||
|
else
|
||||||
|
__small_sprintf (name, "cygserver.msleep.evt.%08x", ident);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Original description from BSD code:
|
||||||
|
*
|
||||||
|
* General sleep call. Suspends the current process until a wakeup is
|
||||||
|
* performed on the specified identifier. The process will then be made
|
||||||
|
* runnable with the specified priority. Sleeps at most timo/hz seconds
|
||||||
|
* (0 means no timeout). If pri includes PCATCH flag, signals are checked
|
||||||
|
* before and after sleeping, else signals are not checked. Returns 0 if
|
||||||
|
* awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
|
||||||
|
* signal needs to be delivered, ERESTART is returned if the current system
|
||||||
|
* call should be restarted if possible, and EINTR is returned if the system
|
||||||
|
* call should be interrupted by the signal (return EINTR).
|
||||||
|
*
|
||||||
|
* The mutex argument is exited before the caller is suspended, and
|
||||||
|
* entered before msleep returns. If priority includes the PDROP
|
||||||
|
* flag the mutex is not entered before returning.
|
||||||
|
*/
|
||||||
|
static HANDLE msleep_glob_evt;
|
||||||
|
|
||||||
|
void
|
||||||
|
msleep_init (void)
|
||||||
|
{
|
||||||
|
msleep_glob_evt = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
|
if (!msleep_glob_evt)
|
||||||
|
panic ("CreateEvent in msleep_init failed: %E");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
win_priority (int priority)
|
||||||
|
{
|
||||||
|
int p = (int)((p) & PRIO_MASK) - PZERO;
|
||||||
|
/* Generating a valid priority value is a bit tricky. The only valid
|
||||||
|
values on 9x and NT4 are -15, -2, -1, 0, 1, 2, 15. */
|
||||||
|
switch (p)
|
||||||
|
{
|
||||||
|
case -15: case -14: case -13: case -12: case -11:
|
||||||
|
return THREAD_PRIORITY_IDLE;
|
||||||
|
case -10: case -9: case -8: case -7: case -6:
|
||||||
|
return THREAD_PRIORITY_LOWEST;
|
||||||
|
case -5: case -4: case -3: case -2: case -1:
|
||||||
|
return THREAD_PRIORITY_BELOW_NORMAL;
|
||||||
|
case 0:
|
||||||
|
return THREAD_PRIORITY_NORMAL;
|
||||||
|
case 1: case 2: case 3: case 4: case 5:
|
||||||
|
return THREAD_PRIORITY_ABOVE_NORMAL;
|
||||||
|
case 6: case 7: case 8: case 9: case 10:
|
||||||
|
return THREAD_PRIORITY_HIGHEST;
|
||||||
|
case 11: case 12: case 13: case 14: case 15:
|
||||||
|
return THREAD_PRIORITY_TIME_CRITICAL;
|
||||||
|
}
|
||||||
|
return THREAD_PRIORITY_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the thread priority, returns the old priority.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
set_priority (int priority)
|
||||||
|
{
|
||||||
|
int old_prio = GetThreadPriority (GetCurrentThread ());
|
||||||
|
if (!SetThreadPriority (GetCurrentThread (), win_priority(priority)))
|
||||||
|
log (LOG_WARNING,
|
||||||
|
"Warning: Setting thread priority to %d failed with error %lu\n",
|
||||||
|
win_priority(priority), GetLastError ());
|
||||||
|
return old_prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_msleep (void *ident, struct mtx *mtx, int priority,
|
||||||
|
const char *wmesg, int timo, struct thread *td)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
char name[64];
|
||||||
|
msleep_event_name (ident, name);
|
||||||
|
HANDLE evt = OpenEvent (EVENT_ALL_ACCESS, FALSE, name);
|
||||||
|
if (!evt)
|
||||||
|
evt = CreateEvent (NULL, TRUE, FALSE, name);
|
||||||
|
if (!evt)
|
||||||
|
panic ("CreateEvent in msleep (%s) failed: %E", wmesg);
|
||||||
|
if (mtx)
|
||||||
|
mtx_unlock (mtx);
|
||||||
|
int old_priority = set_priority (priority);
|
||||||
|
/* PCATCH can't be handled here. */
|
||||||
|
HANDLE obj[3] = { evt, td->client->handle (), msleep_glob_evt };
|
||||||
|
switch (WaitForMultipleObjects (3, obj, FALSE, timo ?: INFINITE))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0: /* wakeup() has been called. */
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case WAIT_OBJECT_0 + 2: /* Shutdown event (triggered by wakeup_all). */
|
||||||
|
priority |= PDROP;
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case WAIT_OBJECT_0 + 1: /* The dependent process has exited. */
|
||||||
|
ret = EIDRM;
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
ret = EWOULDBLOCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic ("wait in msleep (%s) failed, %E", wmesg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_priority (old_priority);
|
||||||
|
if (!(priority & PDROP) && mtx)
|
||||||
|
mtx_lock (mtx);
|
||||||
|
CloseHandle (evt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make all threads sleeping on the specified identifier runnable.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
wakeup (void *ident)
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
msleep_event_name (ident, name);
|
||||||
|
HANDLE evt = OpenEvent (EVENT_MODIFY_STATE, FALSE, name);
|
||||||
|
if (!evt)
|
||||||
|
{
|
||||||
|
/* Another round of different error codes returned by 9x and NT
|
||||||
|
systems. Oh boy... */
|
||||||
|
if ( (!wincap.is_winnt () && GetLastError () != ERROR_INVALID_NAME)
|
||||||
|
|| (wincap.is_winnt () && GetLastError () != ERROR_FILE_NOT_FOUND))
|
||||||
|
panic ("OpenEvent (%s) in wakeup failed: %E", name);
|
||||||
|
}
|
||||||
|
if (evt)
|
||||||
|
{
|
||||||
|
if (!SetEvent (evt))
|
||||||
|
panic ("SetEvent (%s) in wakeup failed, %E", name);
|
||||||
|
CloseHandle (evt);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wakeup all sleeping threads. Only called in the context of cygserver
|
||||||
|
* shutdown.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wakeup_all (void)
|
||||||
|
{
|
||||||
|
SetEvent (msleep_glob_evt);
|
||||||
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* bsd_mutex.h: BSD Mutex helper
|
||||||
|
|
||||||
|
Copyright 2003 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. */
|
||||||
|
#ifndef _BSD_MUTEX_H
|
||||||
|
#define _BSD_MUTEX_H
|
||||||
|
|
||||||
|
#define MTX_DEF 0
|
||||||
|
|
||||||
|
#define MA_OWNED 1
|
||||||
|
#define MA_NOTOWNED 2
|
||||||
|
|
||||||
|
#define PZERO (0x20)
|
||||||
|
#define PRIO_MASK (0x1f)
|
||||||
|
#define PDROP 0x1000
|
||||||
|
#define PCATCH 0x2000
|
||||||
|
#define PLOCK 0x3000
|
||||||
|
|
||||||
|
struct mtx {
|
||||||
|
HANDLE h;
|
||||||
|
const char *name;
|
||||||
|
DWORD owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Some BSD kernel global mutex. */
|
||||||
|
extern struct mtx Giant;
|
||||||
|
|
||||||
|
void mtx_init (mtx *, const char *, const void *, int);
|
||||||
|
void _mtx_lock (mtx *, DWORD winpid, const char *, int);
|
||||||
|
#define mtx_lock(m) _mtx_lock((m), (td->ipcblk->winpid), __FILE__, __LINE__)
|
||||||
|
int mtx_owned (mtx *);
|
||||||
|
void _mtx_assert(mtx *, int, const char *, int);
|
||||||
|
#define mtx_assert(m,w) _mtx_assert((m),(w),__FILE__,__LINE__)
|
||||||
|
void _mtx_unlock (mtx *, const char *, int);
|
||||||
|
#define mtx_unlock(m) _mtx_unlock((m),__FILE__,__LINE__)
|
||||||
|
|
||||||
|
void mtx_destroy (mtx *);
|
||||||
|
|
||||||
|
void msleep_init (void);
|
||||||
|
int _msleep (void *, struct mtx *, int, const char *, int, struct thread *);
|
||||||
|
#define msleep(i,m,p,w,t) _msleep((i),(m),(p),(w),(t),(td))
|
||||||
|
#define tsleep(i,p,w,t) _msleep((i),NULL,(p),(w),(t),(td))
|
||||||
|
int wakeup (void *);
|
||||||
|
void wakeup_all (void);
|
||||||
|
|
||||||
|
#endif /* _BSD_MUTEX_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver_client.cc
|
/* client.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Egor Duda <deo@logos-m.ru>
|
Written by Egor Duda <deo@logos-m.ru>
|
||||||
|
|
||||||
|
@ -22,11 +22,12 @@ details. */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
|
#include "cygserver_msg.h"
|
||||||
|
#include "cygserver_sem.h"
|
||||||
#include "cygserver_shm.h"
|
#include "cygserver_shm.h"
|
||||||
#include "safe_memory.h"
|
|
||||||
|
|
||||||
#include "cygserver.h"
|
#include "cygserver.h"
|
||||||
#include "cygserver_transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children.
|
int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children.
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ client_request_get_version::client_request_get_version ()
|
||||||
* the first numbers match, that is).
|
* the first numbers match, that is).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __INSIDE_CYGWIN__
|
||||||
|
|
||||||
bool
|
bool
|
||||||
client_request_get_version::check_version () const
|
client_request_get_version::check_version () const
|
||||||
{
|
{
|
||||||
|
@ -71,8 +74,6 @@ client_request_get_version::check_version () const
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __INSIDE_CYGWIN__
|
|
||||||
|
|
||||||
client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid,
|
client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid,
|
||||||
HANDLE nfrom_master,
|
HANDLE nfrom_master,
|
||||||
HANDLE nto_master)
|
HANDLE nto_master)
|
||||||
|
@ -87,15 +88,6 @@ client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid,
|
||||||
"from_master = %lu, to_master = %lu"),
|
"from_master = %lu, to_master = %lu"),
|
||||||
req.pid, req.master_pid, req.from_master, req.to_master);
|
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__ */
|
#endif /* __INSIDE_CYGWIN__ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -230,7 +222,12 @@ client_request::send (transport_layer_base * const conn)
|
||||||
// sizeof (_header), msglen ());
|
// sizeof (_header), msglen ());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
|
|
||||||
|
client_request_attach_tty::client_request_attach_tty ()
|
||||||
|
: client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* client_request::handle_request ()
|
* client_request::handle_request ()
|
||||||
|
@ -277,16 +274,22 @@ client_request::handle_request (transport_layer_base *const conn,
|
||||||
switch (header.request_code)
|
switch (header.request_code)
|
||||||
{
|
{
|
||||||
case CYGSERVER_REQUEST_GET_VERSION:
|
case CYGSERVER_REQUEST_GET_VERSION:
|
||||||
req = safe_new0 (client_request_get_version);
|
req = new client_request_get_version;
|
||||||
break;
|
break;
|
||||||
case CYGSERVER_REQUEST_SHUTDOWN:
|
case CYGSERVER_REQUEST_SHUTDOWN:
|
||||||
req = safe_new0 (client_request_shutdown);
|
req = new client_request_shutdown;
|
||||||
break;
|
break;
|
||||||
case CYGSERVER_REQUEST_ATTACH_TTY:
|
case CYGSERVER_REQUEST_ATTACH_TTY:
|
||||||
req = safe_new0 (client_request_attach_tty);
|
req = new client_request_attach_tty;
|
||||||
|
break;
|
||||||
|
case CYGSERVER_REQUEST_MSG:
|
||||||
|
req = new client_request_msg;
|
||||||
|
break;
|
||||||
|
case CYGSERVER_REQUEST_SEM:
|
||||||
|
req = new client_request_sem;
|
||||||
break;
|
break;
|
||||||
case CYGSERVER_REQUEST_SHM:
|
case CYGSERVER_REQUEST_SHM:
|
||||||
req = safe_new0 (client_request_shm);
|
req = new client_request_shm;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syscall_printf ("unknown request code %d received: request ignored",
|
syscall_printf ("unknown request code %d received: request ignored",
|
||||||
|
@ -299,74 +302,9 @@ client_request::handle_request (transport_layer_base *const conn,
|
||||||
req->msglen (header.msglen);
|
req->msglen (header.msglen);
|
||||||
req->handle (conn, cache);
|
req->handle (conn, cache);
|
||||||
|
|
||||||
safe_delete (req);
|
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 ()
|
* client_request::handle ()
|
||||||
*
|
*
|
||||||
|
@ -470,7 +408,84 @@ client_request::handle (transport_layer_base *const conn,
|
||||||
// sizeof (_header), msglen ());
|
// sizeof (_header), msglen ());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
/* The server side implementation of make_request. Very simple. */
|
||||||
|
int
|
||||||
|
client_request::make_request ()
|
||||||
|
{
|
||||||
|
transport_layer_base *const transport = create_server_transport ();
|
||||||
|
assert (transport);
|
||||||
|
if (transport->connect () == -1)
|
||||||
|
{
|
||||||
|
if (errno)
|
||||||
|
error_code (errno);
|
||||||
|
else
|
||||||
|
error_code (ENOSYS);
|
||||||
|
delete transport;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
send (transport);
|
||||||
|
delete transport;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* __OUTSIDE_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 ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
#ifdef __INSIDE_CYGWIN__
|
||||||
|
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);
|
||||||
|
delete transport;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verbose: debug_printf ("connected to server %p", transport);
|
||||||
|
|
||||||
|
send (transport);
|
||||||
|
|
||||||
|
delete transport;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_cygserver_available ()
|
check_cygserver_available ()
|
||||||
|
@ -523,3 +538,4 @@ cygserver_init ()
|
||||||
if (!check_cygserver_available ())
|
if (!check_cygserver_available ())
|
||||||
cygserver_running = CYGSERVER_UNAVAIL;
|
cygserver_running = CYGSERVER_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
#endif /* __INSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver.cc
|
/* cygserver.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Egor Duda <deo@logos-m.ru>
|
Written by Egor Duda <deo@logos-m.ru>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
#include "woutsup.h"
|
#include "woutsup.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -27,100 +28,21 @@ details. */
|
||||||
#include "cygwin_version.h"
|
#include "cygwin_version.h"
|
||||||
|
|
||||||
#include "cygserver.h"
|
#include "cygserver.h"
|
||||||
#include "cygserver_process.h"
|
#include "process.h"
|
||||||
#include "cygserver_transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
|
#include "cygserver_ipc.h"
|
||||||
|
#include "cygserver_msg.h"
|
||||||
|
#include "cygserver_sem.h"
|
||||||
|
|
||||||
|
#define DEF_CONFIG_FILE "" SYSCONFDIR "/cygserver.conf"
|
||||||
|
|
||||||
// Version string.
|
// Version string.
|
||||||
static const char version[] = "$Revision$";
|
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;
|
GENERIC_MAPPING access_mapping;
|
||||||
|
|
||||||
static BOOL
|
static bool
|
||||||
setup_privileges ()
|
setup_privileges ()
|
||||||
{
|
{
|
||||||
BOOL rc, ret_val;
|
BOOL rc, ret_val;
|
||||||
|
@ -130,15 +52,14 @@ setup_privileges ()
|
||||||
rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ;
|
rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ;
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
system_printf ("error opening process token (%lu)", GetLastError ());
|
debug ("error opening process token (%lu)", GetLastError ());
|
||||||
ret_val = FALSE;
|
return false;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid);
|
rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
system_printf ("error getting privilege luid (%lu)", GetLastError ());
|
debug ("error getting privilege luid (%lu)", GetLastError ());
|
||||||
ret_val = FALSE;
|
ret_val = false;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sPrivileges.PrivilegeCount = 1 ;
|
sPrivileges.PrivilegeCount = 1 ;
|
||||||
|
@ -146,9 +67,8 @@ setup_privileges ()
|
||||||
rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ;
|
rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ;
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
system_printf ("error adjusting privilege level. (%lu)",
|
debug ("error adjusting privilege level. (%lu)", GetLastError ());
|
||||||
GetLastError ());
|
ret_val = false;
|
||||||
ret_val = FALSE;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +77,7 @@ setup_privileges ()
|
||||||
access_mapping.GenericExecute = 0;
|
access_mapping.GenericExecute = 0;
|
||||||
access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA;
|
access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA;
|
||||||
|
|
||||||
ret_val = TRUE;
|
ret_val = true;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
CloseHandle (hToken);
|
CloseHandle (hToken);
|
||||||
|
@ -181,7 +101,7 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process,
|
||||||
0, bInheritHandle,
|
0, bInheritHandle,
|
||||||
DUPLICATE_SAME_ACCESS))
|
DUPLICATE_SAME_ACCESS))
|
||||||
{
|
{
|
||||||
system_printf ("error getting handle(%u) to server (%lu)",
|
log (LOG_ERR, "error getting handle(%u) to server (%lu)",
|
||||||
(unsigned int)from_handle, GetLastError ());
|
(unsigned int)from_handle, GetLastError ());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +125,7 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process,
|
||||||
| DACL_SECURITY_INFORMATION),
|
| DACL_SECURITY_INFORMATION),
|
||||||
sd, sizeof (sd_buf), &bytes_needed))
|
sd, sizeof (sd_buf), &bytes_needed))
|
||||||
{
|
{
|
||||||
system_printf ("error getting handle SD (%lu)", GetLastError ());
|
log (LOG_ERR, "error getting handle SD (%lu)", GetLastError ());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,14 +134,14 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process,
|
||||||
if (!AccessCheck (sd, from_process_token, access, &access_mapping,
|
if (!AccessCheck (sd, from_process_token, access, &access_mapping,
|
||||||
&ps, &ps_len, &access, &status))
|
&ps, &ps_len, &access, &status))
|
||||||
{
|
{
|
||||||
system_printf ("error checking access rights (%lu)",
|
log (LOG_ERR, "error checking access rights (%lu)",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
system_printf ("access to object denied");
|
log (LOG_ERR, "access to object denied");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,11 +150,11 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process,
|
||||||
to_process, to_handle_ptr,
|
to_process, to_handle_ptr,
|
||||||
access, bInheritHandle, 0))
|
access, bInheritHandle, 0))
|
||||||
{
|
{
|
||||||
system_printf ("error getting handle to client (%lu)", GetLastError ());
|
log (LOG_ERR, "error getting handle to client (%lu)", GetLastError ());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verbose: debug_printf ("Duplicated %p to %p", from_handle, *to_handle_ptr);
|
debug ("Duplicated %p to %p", from_handle, *to_handle_ptr);
|
||||||
|
|
||||||
ret_val = 0;
|
ret_val = 0;
|
||||||
|
|
||||||
|
@ -259,7 +179,7 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
|
|
||||||
if (!wincap.has_security ())
|
if (!wincap.has_security ())
|
||||||
{
|
{
|
||||||
syscall_printf ("operation only supported on systems with security");
|
log (LOG_NOTICE, "operation only supported on systems with security");
|
||||||
error_code (EINVAL);
|
error_code (EINVAL);
|
||||||
msglen (0);
|
msglen (0);
|
||||||
return;
|
return;
|
||||||
|
@ -267,7 +187,7 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
|
|
||||||
if (msglen () != sizeof (req))
|
if (msglen () != sizeof (req))
|
||||||
{
|
{
|
||||||
syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
|
log (LOG_ERR, "bad request body length: expecting %lu bytes, got %lu",
|
||||||
sizeof (req), msglen ());
|
sizeof (req), msglen ());
|
||||||
error_code (EINVAL);
|
error_code (EINVAL);
|
||||||
msglen (0);
|
msglen (0);
|
||||||
|
@ -276,54 +196,65 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
|
|
||||||
msglen (0); // Until we fill in some fields.
|
msglen (0); // Until we fill in some fields.
|
||||||
|
|
||||||
// verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld",
|
debug ("pid %ld:(%p,%p) -> pid %ld", req.master_pid, req.from_master,
|
||||||
// req.master_pid, req.from_master, req.to_master,
|
req.to_master, req.pid);
|
||||||
// req.pid);
|
|
||||||
|
|
||||||
// verbose: debug_printf ("opening process %ld", req.master_pid);
|
debug ("opening process %ld", req.master_pid);
|
||||||
|
|
||||||
const HANDLE from_process_handle =
|
const HANDLE from_process_handle =
|
||||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
|
OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
|
||||||
|
|
||||||
if (!from_process_handle)
|
if (!from_process_handle)
|
||||||
{
|
{
|
||||||
system_printf ("error opening `from' process, error = %lu",
|
log (LOG_ERR, "error opening `from' process, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
error_code (EACCES);
|
error_code (EACCES);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verbose: debug_printf ("opening process %ld", req.pid);
|
debug ("opening process %ld", req.pid);
|
||||||
|
|
||||||
const HANDLE to_process_handle =
|
const HANDLE to_process_handle =
|
||||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
|
OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
|
||||||
|
|
||||||
if (!to_process_handle)
|
if (!to_process_handle)
|
||||||
{
|
{
|
||||||
system_printf ("error opening `to' process, error = %lu",
|
log (LOG_ERR, "error opening `to' process, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
CloseHandle (from_process_handle);
|
CloseHandle (from_process_handle);
|
||||||
error_code (EACCES);
|
error_code (EACCES);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verbose: debug_printf ("Impersonating client");
|
debug ("Impersonating client");
|
||||||
conn->impersonate_client ();
|
if (!conn->impersonate_client ())
|
||||||
|
{
|
||||||
|
CloseHandle (from_process_handle);
|
||||||
|
CloseHandle (to_process_handle);
|
||||||
|
error_code (EACCES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE token_handle = NULL;
|
HANDLE token_handle = NULL;
|
||||||
|
|
||||||
// verbose: debug_printf ("about to open thread token");
|
debug ("about to open thread token");
|
||||||
const DWORD rc = OpenThreadToken (GetCurrentThread (),
|
const DWORD rc = OpenThreadToken (GetCurrentThread (),
|
||||||
TOKEN_QUERY,
|
TOKEN_QUERY,
|
||||||
TRUE,
|
TRUE,
|
||||||
&token_handle);
|
&token_handle);
|
||||||
|
|
||||||
// verbose: debug_printf ("opened thread token, rc=%lu", rc);
|
debug ("opened thread token, rc=%lu", rc);
|
||||||
conn->revert_to_self ();
|
if (!conn->revert_to_self ())
|
||||||
|
{
|
||||||
|
CloseHandle (from_process_handle);
|
||||||
|
CloseHandle (to_process_handle);
|
||||||
|
error_code (EACCES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
system_printf ("error opening thread token, error = %lu",
|
log (LOG_ERR, "error opening thread token, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
CloseHandle (from_process_handle);
|
CloseHandle (from_process_handle);
|
||||||
CloseHandle (to_process_handle);
|
CloseHandle (to_process_handle);
|
||||||
|
@ -348,7 +279,7 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
from_master,
|
from_master,
|
||||||
&req.from_master, TRUE) != 0)
|
&req.from_master, TRUE) != 0)
|
||||||
{
|
{
|
||||||
system_printf ("error duplicating from_master handle, error = %lu",
|
log (LOG_ERR, "error duplicating from_master handle, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
error_code (EACCES);
|
error_code (EACCES);
|
||||||
}
|
}
|
||||||
|
@ -360,7 +291,7 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
to_master,
|
to_master,
|
||||||
&req.to_master, TRUE) != 0)
|
&req.to_master, TRUE) != 0)
|
||||||
{
|
{
|
||||||
system_printf ("error duplicating to_master handle, error = %lu",
|
log (LOG_ERR, "error duplicating to_master handle, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
error_code (EACCES);
|
error_code (EACCES);
|
||||||
}
|
}
|
||||||
|
@ -369,7 +300,7 @@ client_request_attach_tty::serve (transport_layer_base *const conn,
|
||||||
CloseHandle (to_process_handle);
|
CloseHandle (to_process_handle);
|
||||||
CloseHandle (token_handle);
|
CloseHandle (token_handle);
|
||||||
|
|
||||||
debug_printf ("%lu(%lu, %lu) -> %lu(%lu,%lu)",
|
debug ("%lu(%lu, %lu) -> %lu(%lu,%lu)",
|
||||||
req.master_pid, from_master, to_master,
|
req.master_pid, from_master, to_master,
|
||||||
req.pid, req.from_master, req.to_master);
|
req.pid, req.from_master, req.to_master);
|
||||||
|
|
||||||
|
@ -382,7 +313,7 @@ client_request_get_version::serve (transport_layer_base *, process_cache *)
|
||||||
assert (!error_code ());
|
assert (!error_code ());
|
||||||
|
|
||||||
if (msglen ())
|
if (msglen ())
|
||||||
syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
|
log (LOG_ERR, "unexpected request body ignored: %lu bytes", msglen ());
|
||||||
|
|
||||||
msglen (sizeof (version));
|
msglen (sizeof (version));
|
||||||
|
|
||||||
|
@ -401,7 +332,7 @@ public:
|
||||||
|
|
||||||
virtual ~server_request ()
|
virtual ~server_request ()
|
||||||
{
|
{
|
||||||
safe_delete (_conn);
|
delete _conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void process ()
|
virtual void process ()
|
||||||
|
@ -455,8 +386,8 @@ server_submission_loop::request_loop ()
|
||||||
*/
|
*/
|
||||||
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1))
|
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1))
|
||||||
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST))
|
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST))
|
||||||
debug_printf ("failed to raise accept thread priority, error = %lu",
|
debug ("failed to raise accept thread priority, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
|
|
||||||
while (_running)
|
while (_running)
|
||||||
{
|
{
|
||||||
|
@ -464,7 +395,7 @@ server_submission_loop::request_loop ()
|
||||||
transport_layer_base *const conn = _transport->accept (&recoverable);
|
transport_layer_base *const conn = _transport->accept (&recoverable);
|
||||||
if (!conn && !recoverable)
|
if (!conn && !recoverable)
|
||||||
{
|
{
|
||||||
system_printf ("fatal error on IPC transport: closing down");
|
log (LOG_ERR, "fatal error on IPC transport: closing down");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// EINTR probably implies a shutdown request; so back off for a
|
// EINTR probably implies a shutdown request; so back off for a
|
||||||
|
@ -474,26 +405,25 @@ server_submission_loop::request_loop ()
|
||||||
if (!conn && errno == EINTR)
|
if (!conn && errno == EINTR)
|
||||||
{
|
{
|
||||||
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL))
|
if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL))
|
||||||
debug_printf ("failed to reset thread priority, error = %lu",
|
debug ("failed to reset thread priority, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
|
|
||||||
Sleep (0);
|
Sleep (0);
|
||||||
if (!SetThreadPriority (GetCurrentThread (),
|
if (!SetThreadPriority (GetCurrentThread (),
|
||||||
THREAD_PRIORITY_HIGHEST + 1))
|
THREAD_PRIORITY_HIGHEST + 1))
|
||||||
if (!SetThreadPriority (GetCurrentThread (),
|
if (!SetThreadPriority (GetCurrentThread (),
|
||||||
THREAD_PRIORITY_HIGHEST))
|
THREAD_PRIORITY_HIGHEST))
|
||||||
debug_printf ("failed to raise thread priority, error = %lu",
|
debug ("failed to raise thread priority, error = %lu",
|
||||||
GetLastError ());
|
GetLastError ());
|
||||||
}
|
}
|
||||||
if (conn)
|
if (conn)
|
||||||
_queue->add (safe_new (server_request, conn, _cache));
|
_queue->add (new server_request (conn, _cache));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client_request_shutdown::client_request_shutdown ()
|
client_request_shutdown::client_request_shutdown ()
|
||||||
: client_request (CYGSERVER_REQUEST_SHUTDOWN)
|
: client_request (CYGSERVER_REQUEST_SHUTDOWN)
|
||||||
{
|
{
|
||||||
// verbose: syscall_printf ("created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -502,7 +432,7 @@ client_request_shutdown::serve (transport_layer_base *, process_cache *)
|
||||||
assert (!error_code ());
|
assert (!error_code ());
|
||||||
|
|
||||||
if (msglen ())
|
if (msglen ())
|
||||||
syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
|
log (LOG_ERR, "unexpected request body ignored: %lu bytes", msglen ());
|
||||||
|
|
||||||
/* FIXME: link upwards, and then this becomes a trivial method call to
|
/* FIXME: link upwards, and then this becomes a trivial method call to
|
||||||
* only shutdown _this queue_
|
* only shutdown _this queue_
|
||||||
|
@ -530,12 +460,33 @@ handle_signal (const int signum)
|
||||||
static void
|
static void
|
||||||
print_usage (const char *const pgm)
|
print_usage (const char *const pgm)
|
||||||
{
|
{
|
||||||
printf ("Usage: %s [OPTIONS]\n", pgm);
|
log (LOG_NOTICE, "Usage: %s [OPTIONS]\n"
|
||||||
printf (" -c, --cleanup-threads number of cleanup threads to use\n");
|
"Configuration option:\n"
|
||||||
printf (" -h, --help output usage information and exit\n");
|
" -f, --config-file <file> Use <file> as config file. Default is\n"
|
||||||
printf (" -r, --request-threads number of request threads to use\n");
|
"\n"
|
||||||
printf (" -s, --shutdown shutdown the daemon\n");
|
"Performance options:\n"
|
||||||
printf (" -v, --version output version information and exit\n");
|
" -c, --cleanup-threads <num> Number of cleanup threads to use.\n"
|
||||||
|
" -r, --request-threads <num> Number of request threads to use.\n"
|
||||||
|
"\n"
|
||||||
|
"Logging options:\n"
|
||||||
|
" -d, --debug Log debug messages to stderr.\n"
|
||||||
|
" -e, --stderr Log to stderr (default if stderr is a tty).\n"
|
||||||
|
" -E, --no-stderr Don't log to stderr (see -y, -Y options).\n"
|
||||||
|
" " DEF_CONFIG_FILE "\n"
|
||||||
|
" -l, --log-level <level> Verbosity of logging (1..7). Default: 6\n"
|
||||||
|
" -y, --syslog Log to syslog (default if stderr is no tty).\n"
|
||||||
|
" -Y, --no-syslog Don't log to syslog (See -e, -E options).\n"
|
||||||
|
"\n"
|
||||||
|
"Support options:\n"
|
||||||
|
" -m, --no-sharedmem Don't start XSI Shared Memory support.\n"
|
||||||
|
" -q, --no-msgqueues Don't start XSI Message Queue support.\n"
|
||||||
|
" -s, --no-semaphores Don't start XSI Semaphore support.\n"
|
||||||
|
"\n"
|
||||||
|
"Miscellaneous:\n"
|
||||||
|
" -S, --shutdown Shutdown the daemon.\n"
|
||||||
|
" -h, --help Output usage information and exit.\n"
|
||||||
|
" -v, --version Output version information and exit."
|
||||||
|
, pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -543,7 +494,7 @@ print_usage (const char *const pgm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_version (const char *const pgm)
|
print_version ()
|
||||||
{
|
{
|
||||||
char *vn = NULL;
|
char *vn = NULL;
|
||||||
|
|
||||||
|
@ -578,10 +529,12 @@ print_version (const char *const pgm)
|
||||||
cygwin_version.mount_registry,
|
cygwin_version.mount_registry,
|
||||||
cygwin_version.dll_build_date);
|
cygwin_version.dll_build_date);
|
||||||
|
|
||||||
printf ("%s (cygwin) %s\n", pgm, vn);
|
log (LOG_INFO, "(cygwin) %s\n"
|
||||||
printf ("API version %s\n", buf);
|
"API version %s\n"
|
||||||
printf ("Copyright 2001, 2002 Red Hat, Inc.\n");
|
"Copyright 2001, 2002, 2003 Red Hat, Inc.\n"
|
||||||
printf ("Compiled on %s\n", __DATE__);
|
"Compiled on %s\n"
|
||||||
|
"Default configuration file is %s",
|
||||||
|
vn, buf, __DATE__, DEF_CONFIG_FILE);
|
||||||
|
|
||||||
free (vn);
|
free (vn);
|
||||||
}
|
}
|
||||||
|
@ -595,79 +548,127 @@ main (const int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
{"cleanup-threads", required_argument, NULL, 'c'},
|
{"cleanup-threads", required_argument, NULL, 'c'},
|
||||||
|
{"debug", no_argument, NULL, 'd'},
|
||||||
|
{"stderr", no_argument, NULL, 'e'},
|
||||||
|
{"no-stderr", no_argument, NULL, 'E'},
|
||||||
|
{"config-file", required_argument, NULL, 'f'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"log-level", required_argument, NULL, 'l'},
|
||||||
|
{"no-sharedmem", no_argument, NULL, 'm'},
|
||||||
|
{"no-msgqueues", no_argument, NULL, 'q'},
|
||||||
{"request-threads", required_argument, NULL, 'r'},
|
{"request-threads", required_argument, NULL, 'r'},
|
||||||
{"shutdown", no_argument, NULL, 's'},
|
{"no-semaphores", no_argument, NULL, 's'},
|
||||||
|
{"shutdown", no_argument, NULL, 'S'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
|
{"syslog", no_argument, NULL, 'y'},
|
||||||
|
{"no-syslog", no_argument, NULL, 'Y'},
|
||||||
{0, no_argument, NULL, 0}
|
{0, no_argument, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char opts[] = "c:hr:sv";
|
const char opts[] = "c:deEf:hl:mqr:sSvyY";
|
||||||
|
|
||||||
int cleanup_threads = 2;
|
long cleanup_threads = 0;
|
||||||
int request_threads = 10;
|
long request_threads = 0;
|
||||||
bool shutdown = false;
|
bool shutdown = false;
|
||||||
|
const char *config_file = DEF_CONFIG_FILE;
|
||||||
|
bool force_config_file = false;
|
||||||
|
tun_bool_t option_log_stderr = TUN_UNDEF;
|
||||||
|
tun_bool_t option_log_syslog = TUN_UNDEF;
|
||||||
|
|
||||||
const char *pgm = NULL;
|
char *c = NULL;
|
||||||
|
|
||||||
if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/')))
|
/* Check if we have a terminal. If so, default to stderr logging,
|
||||||
pgm = *argv;
|
otherwise default to syslog logging. This must be done early
|
||||||
|
to allow default logging already in option processing state. */
|
||||||
|
openlog ("cygserver", LOG_PID, LOG_KERN);
|
||||||
|
if (isatty (2))
|
||||||
|
log_stderr = TUN_TRUE;
|
||||||
else
|
else
|
||||||
pgm++;
|
log_syslog = TUN_TRUE;
|
||||||
|
|
||||||
wincap.init ();
|
|
||||||
if (wincap.has_security ())
|
|
||||||
setup_privileges ();
|
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
|
opterr = 0;
|
||||||
while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
|
while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'c':
|
||||||
cleanup_threads = atoi (optarg);
|
c = NULL;
|
||||||
if (cleanup_threads <= 0)
|
cleanup_threads = strtol (optarg, &c, 10);
|
||||||
{
|
if (cleanup_threads <= 0 || cleanup_threads > 16 || (c && *c))
|
||||||
fprintf (stderr,
|
panic ("Number of cleanup threads must be between 1 and 16");
|
||||||
"%s: number of cleanup threads must be positive\n",
|
|
||||||
pgm);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
log_debug = TUN_TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
option_log_stderr = TUN_TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
option_log_stderr = TUN_FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
config_file = optarg;
|
||||||
|
force_config_file = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage (pgm);
|
print_usage (getprogname ());
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
c = NULL;
|
||||||
|
log_level = strtoul (optarg, &c, 10);
|
||||||
|
if (!log_level || log_level > 7 || (c && *c))
|
||||||
|
panic ("Log level must be between 1 and 7");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
support_sharedmem = TUN_FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
support_msgqueues = TUN_FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
request_threads = atoi (optarg);
|
c = NULL;
|
||||||
if (request_threads <= 0)
|
request_threads = strtol (optarg, &c, 10);
|
||||||
{
|
if (request_threads <= 0 || request_threads > 64 || (c && *c))
|
||||||
fprintf (stderr,
|
panic ("Number of request threads must be between 1 and 64");
|
||||||
"%s: number of request threads must be positive\n",
|
|
||||||
pgm);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
|
support_semaphores = TUN_FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
shutdown = true;
|
shutdown = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
print_version (pgm);
|
print_version ();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
option_log_syslog = TUN_TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Y':
|
||||||
|
option_log_syslog = TUN_FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
fprintf (stderr, "Try `%s --help' for more information.\n", pgm);
|
panic ("unknown option -- %c\n"
|
||||||
exit (1);
|
"Try `%s --help' for more information.", optopt, getprogname ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind != argc)
|
if (optind != argc)
|
||||||
{
|
panic ("Too many arguments");
|
||||||
fprintf (stderr, "%s: too many arguments\n", pgm);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shutdown)
|
if (shutdown)
|
||||||
{
|
{
|
||||||
|
@ -679,71 +680,76 @@ main (const int argc, char *argv[])
|
||||||
client_request_shutdown req;
|
client_request_shutdown req;
|
||||||
|
|
||||||
if (req.make_request () == -1 || req.error_code ())
|
if (req.make_request () == -1 || req.error_code ())
|
||||||
{
|
panic("Shutdown request failed: %s", strerror (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.
|
// FIXME: It would be nice to wait here for the daemon to exit.
|
||||||
|
|
||||||
return 0;
|
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 (SIGHUP);
|
||||||
SIGHANDLE (SIGINT);
|
SIGHANDLE (SIGINT);
|
||||||
SIGHANDLE (SIGTERM);
|
SIGHANDLE (SIGTERM);
|
||||||
|
|
||||||
print_version (pgm);
|
tunable_param_init (config_file, force_config_file);
|
||||||
setbuf (stdout, NULL);
|
|
||||||
printf ("daemon starting up");
|
|
||||||
|
|
||||||
|
loginit (option_log_stderr, option_log_syslog);
|
||||||
|
|
||||||
|
log (LOG_INFO, "daemon starting up");
|
||||||
|
|
||||||
|
if (!cleanup_threads)
|
||||||
|
TUNABLE_INT_FETCH ("kern.srv.cleanup_threads", &cleanup_threads);
|
||||||
|
if (!cleanup_threads)
|
||||||
|
cleanup_threads = 2;
|
||||||
|
|
||||||
|
if (!request_threads)
|
||||||
|
TUNABLE_INT_FETCH ("kern.srv.request_threads", &request_threads);
|
||||||
|
if (!request_threads)
|
||||||
|
request_threads = 10;
|
||||||
|
|
||||||
|
if (support_sharedmem == TUN_UNDEF)
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.srv.sharedmem", &support_sharedmem);
|
||||||
|
if (support_sharedmem == TUN_UNDEF)
|
||||||
|
support_sharedmem = TUN_TRUE;
|
||||||
|
|
||||||
|
if (support_msgqueues == TUN_UNDEF)
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.srv.msgqueues", &support_msgqueues);
|
||||||
|
if (support_msgqueues == TUN_UNDEF)
|
||||||
|
support_msgqueues = TUN_TRUE;
|
||||||
|
|
||||||
|
if (support_semaphores == TUN_UNDEF)
|
||||||
|
TUNABLE_BOOL_FETCH ("kern.srv.semaphores", &support_semaphores);
|
||||||
|
if (support_semaphores == TUN_UNDEF)
|
||||||
|
support_semaphores = TUN_TRUE;
|
||||||
|
|
||||||
|
wincap.init ();
|
||||||
|
if (wincap.has_security () && !setup_privileges ())
|
||||||
|
panic ("Setting process privileges failed.");
|
||||||
|
|
||||||
|
/*XXXXX*/
|
||||||
threaded_queue request_queue (request_threads);
|
threaded_queue request_queue (request_threads);
|
||||||
printf (".");
|
|
||||||
|
|
||||||
transport_layer_base *const transport = create_server_transport ();
|
transport_layer_base *const transport = create_server_transport ();
|
||||||
assert (transport);
|
assert (transport);
|
||||||
printf (".");
|
|
||||||
|
|
||||||
process_cache cache (cleanup_threads);
|
process_cache cache (cleanup_threads);
|
||||||
printf (".");
|
|
||||||
|
|
||||||
server_submission_loop submission_loop (&request_queue, transport, &cache);
|
server_submission_loop submission_loop (&request_queue, transport, &cache);
|
||||||
printf (".");
|
|
||||||
|
|
||||||
request_queue.add_submission_loop (&submission_loop);
|
request_queue.add_submission_loop (&submission_loop);
|
||||||
printf (".");
|
|
||||||
|
|
||||||
if (transport->listen () == -1)
|
if (transport->listen () == -1)
|
||||||
{
|
{
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
printf (".");
|
|
||||||
|
ipcinit ();
|
||||||
|
|
||||||
cache.start ();
|
cache.start ();
|
||||||
printf (".");
|
|
||||||
|
|
||||||
request_queue.start ();
|
request_queue.start ();
|
||||||
printf (".");
|
|
||||||
|
|
||||||
printf ("complete\n");
|
log (LOG_NOTICE, "Initialization complete. Waiting for requests.");
|
||||||
|
|
||||||
/* TODO: wait on multiple objects - the thread handle for each
|
/* TODO: wait on multiple objects - the thread handle for each
|
||||||
* request loop + all the process handles. This should be done by
|
* request loop + all the process handles. This should be done by
|
||||||
|
@ -758,16 +764,25 @@ main (const int argc, char *argv[])
|
||||||
-- if signal event then retrigger it
|
-- if signal event then retrigger it
|
||||||
*/
|
*/
|
||||||
while (!shutdown_server && request_queue.running () && cache.running ())
|
while (!shutdown_server && request_queue.running () && cache.running ())
|
||||||
pause ();
|
{
|
||||||
|
pause ();
|
||||||
|
if (ipcunload ())
|
||||||
|
{
|
||||||
|
shutdown_server = false;
|
||||||
|
log (LOG_WARNING, "Shutdown request received but ignored. "
|
||||||
|
"Dependent processes still running.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
printf ("\nShutdown request received - new requests will be denied\n");
|
log (LOG_INFO, "Shutdown request received - new requests will be denied");
|
||||||
request_queue.stop ();
|
request_queue.stop ();
|
||||||
printf ("All pending requests processed\n");
|
log (LOG_INFO, "All pending requests processed");
|
||||||
safe_delete (transport);
|
delete transport;
|
||||||
printf ("No longer accepting requests - cygwin will operate in daemonless mode\n");
|
log (LOG_INFO, "No longer accepting requests - cygwin will operate in daemonless mode");
|
||||||
cache.stop ();
|
cache.stop ();
|
||||||
printf ("All outstanding process-cache activities completed\n");
|
log (LOG_INFO, "All outstanding process-cache activities completed");
|
||||||
printf ("daemon shutdown\n");
|
log (LOG_NOTICE, "Shutdown finished.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
# cygserver.conf, Copyright(C) 2003 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Contains configurable parameters for the cygserver.
|
||||||
|
#
|
||||||
|
# The format of this file is easy. Lines beginning with a hash `#' are
|
||||||
|
# comments and ignored. Lines consisting of only whitespaces are ignored.
|
||||||
|
# Any other line is a setting for cygserver.
|
||||||
|
# A setting consists of a name/value pair, separated by whitespace.
|
||||||
|
# Each line must only consist of one name/value pair.
|
||||||
|
# Lines must not be longer than 1023 characters.
|
||||||
|
#
|
||||||
|
# Some settings can be overridden by a command line switch. If so, it's
|
||||||
|
# mentioned below.
|
||||||
|
#
|
||||||
|
# Settings which are commented out will use the default values. These are
|
||||||
|
# mentioned below, too.
|
||||||
|
|
||||||
|
# kern.srv.cleanup_threads: No. of cygserver threads used for cleanup tasks.
|
||||||
|
# Default: 2, Min: 1, Max: 16, command line option -c, --cleanup-threads
|
||||||
|
#kern.srv.cleanup_threads 2
|
||||||
|
|
||||||
|
# kern.srv.request_threads: No. of cygserver threads used to serve
|
||||||
|
# application requests.
|
||||||
|
# Default: 10, Min: 1, Max: 64, command line option -r, --request-threads
|
||||||
|
#kern.srv.request_threads 10
|
||||||
|
|
||||||
|
# kern.srv.msgqueues: Determines whether XSI Message Queue support should be
|
||||||
|
# started, "yes" (or "true", "y", "t", "1") or "no" (or "false", "n", "f", "0").
|
||||||
|
# These values are valid for all binary type options.
|
||||||
|
# Default is "yes". Command line option -q, --no-msgqueues
|
||||||
|
#kern.srv.msgqueues yes
|
||||||
|
|
||||||
|
# kern.srv.semaphores: Determines whether XSI Semaphore support should be
|
||||||
|
# started. Default is "yes". Command line option -s, --no-semaphores
|
||||||
|
#kern.srv.semaphores yes
|
||||||
|
|
||||||
|
# kern.srv.sharedmem: Determines whether XSI Shared Memory support should be
|
||||||
|
# started. Default is "yes". Command line option -m, --no-sharedmem
|
||||||
|
#kern.srv.sharedmem yes
|
||||||
|
|
||||||
|
# LOGGING
|
||||||
|
|
||||||
|
# kern.log.syslog: Determines whether logging should go to the syslog,
|
||||||
|
# Default is "yes", if stderr is no tty, "no" otherwise.
|
||||||
|
# Command line option -y, --syslog or -Y, --no-syslog.
|
||||||
|
#kern.log.syslog no
|
||||||
|
|
||||||
|
# kern.log.stderr: Determines whether logging should go to stderr,
|
||||||
|
# Default is "yes", if stderr is a tty, "no" otherwise.
|
||||||
|
# Command line option -e, --stderr or -E, --no-stderr.
|
||||||
|
#kern.log.stderr no
|
||||||
|
|
||||||
|
# kern.log.level: Logging level. Valid values are 1 to 7 with a bigger
|
||||||
|
# value emitting more logging output. Default level is 6.
|
||||||
|
# Command line option -l, --log-level.
|
||||||
|
#kern.log.level 6
|
||||||
|
|
||||||
|
# kern.log.debug: Determines whether debug output should be printed to stderr.
|
||||||
|
# Default is "no". Command line option -d, --debug
|
||||||
|
#kern.log.debug no
|
||||||
|
|
||||||
|
# XSI message queue parameters.
|
||||||
|
#
|
||||||
|
# Each message is broken up and stored in segments that are msgssz bytes
|
||||||
|
# long. For efficiency reasons, this should be a power of two. Also,
|
||||||
|
# it doesn't make sense if it is less than 8 or greater than about 256.
|
||||||
|
|
||||||
|
# kern.ipc.msgseg: Maximum no. of message queue segments hold concurrently.
|
||||||
|
# Default: 2048, Min: 256, Max: 32767
|
||||||
|
#kern.ipc.msgseg 2048
|
||||||
|
|
||||||
|
# kern.ipc.msgssz: Size of segment in bytes. Must be a power of 2 value.
|
||||||
|
# Default: 8, Min: 8, Max: 1024
|
||||||
|
#kern.ipc.msgssz 8
|
||||||
|
|
||||||
|
# kern.ipc.msgmni: Maximum no. of message queue identifiers hold concurrently.
|
||||||
|
# Default: 40, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.msgmni 40
|
||||||
|
|
||||||
|
# XSI semaphore parameters
|
||||||
|
|
||||||
|
# kern.ipc.semmni: Maximum no. of semaphore identifiers hold concurrently.
|
||||||
|
# Default: 10, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semmni 10
|
||||||
|
|
||||||
|
# kern.ipc.semmns: Maximum no. of semaphores hold concurrently.
|
||||||
|
# Default: 60, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semmns 60
|
||||||
|
|
||||||
|
# kern.ipc.semmnu: Total no. of undo structures hold by server.
|
||||||
|
# Default: 30, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semmnu 30
|
||||||
|
|
||||||
|
# kern.ipc.semmsl: Maximum no. of semaphores per semaphore id.
|
||||||
|
# Default: 60, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semmsl 60
|
||||||
|
|
||||||
|
# kern.ipc.semopm: Maximum no. of operations per semop call.
|
||||||
|
# Default: 100, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semopm 100
|
||||||
|
|
||||||
|
# kern.ipc.semume: Maximum no. of undo entries per process.
|
||||||
|
# Default: 10, Min: 1, Max: 1024
|
||||||
|
#kern.ipc.semume 10
|
||||||
|
|
||||||
|
# kern.ipc.semvmx: Maximum value of a semaphore.
|
||||||
|
# Default: 32767, Min: 1, Max: 32767
|
||||||
|
#kern.ipc.semvmx 32767
|
||||||
|
|
||||||
|
# kern.ipc.semaem: Maximum value to adjust on process exit.
|
||||||
|
# Default: 16384, Min: 1, Max: 32767
|
||||||
|
#kern.ipc.semaem 16384
|
||||||
|
|
||||||
|
# XSI shared memory parameters
|
||||||
|
|
||||||
|
# kern.ipc.shmmaxpgs: Maximum pages available for XSI shared memory.
|
||||||
|
# Default: 8192, Min: 1, Max: 32767
|
||||||
|
#kern.ipc.shmmaxpgs 8192
|
||||||
|
|
||||||
|
# kern.ipc.shmmni: Maximum number of shared memory segments, system wide.
|
||||||
|
# Default: 192, Min: 1, Max: 32767
|
||||||
|
#kern.ipc.shmmni 192
|
||||||
|
|
||||||
|
# kern.ipc.shmseg: Maximum number of shared memory segments per process.
|
||||||
|
# Default: 128, Min: 1, Max: 32767
|
||||||
|
#kern.ipc.shmseg 128
|
|
@ -1,8 +1,6 @@
|
||||||
/* msg.cc: Single unix specification IPC interface for Cygwin.
|
/* msg.cc: Single unix specification IPC interface for Cygwin.
|
||||||
|
|
||||||
Copyright 2002 Red Hat, Inc.
|
Copyright 2003 Red Hat, Inc.
|
||||||
|
|
||||||
Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
|
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -10,38 +8,103 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
|
#include "woutsup.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <errno.h>
|
||||||
#include <cygwin/msg.h>
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "cygserver.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
#include "cygerrno.h"
|
#include "cygserver_ipc.h"
|
||||||
|
#include "cygserver_msg.h"
|
||||||
|
|
||||||
extern "C" int
|
client_request_msg::client_request_msg ()
|
||||||
msgctl (int msqid, int cmd, struct msqid_ds *buf)
|
: client_request (CYGSERVER_REQUEST_MSG,
|
||||||
{
|
&_parameters, sizeof (_parameters))
|
||||||
set_errno (ENOSYS);
|
{
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
void
|
||||||
msgget (key_t key, int msgflg)
|
client_request_msg::serve (transport_layer_base *const conn,
|
||||||
|
process_cache *const cache)
|
||||||
{
|
{
|
||||||
set_errno (ENOSYS);
|
if (msglen () != sizeof (_parameters.in))
|
||||||
return -1;
|
{
|
||||||
}
|
syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
|
||||||
|
sizeof (_parameters), msglen ());
|
||||||
extern "C" ssize_t
|
error_code (EINVAL);
|
||||||
msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
|
msglen (0);
|
||||||
{
|
return;
|
||||||
set_errno (ENOSYS);
|
}
|
||||||
return -1;
|
if (support_msgqueues == TUN_FALSE)
|
||||||
}
|
{
|
||||||
|
syscall_printf ("Message queue support not started");
|
||||||
extern "C" int
|
error_code (ENOSYS);
|
||||||
msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
|
if (_parameters.in.msgop == MSGOP_msgrcv)
|
||||||
{
|
_parameters.out.rcv = -1;
|
||||||
set_errno (ENOSYS);
|
else
|
||||||
return -1;
|
_parameters.out.ret = -1;
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
process *const client = cache->process (_parameters.in.ipcblk.cygpid,
|
||||||
|
_parameters.in.ipcblk.winpid);
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
|
error_code (EAGAIN);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!conn->impersonate_client ())
|
||||||
|
{
|
||||||
|
client->release ();
|
||||||
|
error_code (EACCES);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!adjust_identity_info (&_parameters.in.ipcblk))
|
||||||
|
{
|
||||||
|
conn->revert_to_self ();
|
||||||
|
error_code (EACCES);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Early revert_to_self since IPC code runs in kernel mode. */
|
||||||
|
conn->revert_to_self ();
|
||||||
|
thread td = { client, &_parameters.in.ipcblk, {-1, -1} };
|
||||||
|
int res;
|
||||||
|
msgop_t msgop = _parameters.in.msgop; /* Get's overwritten otherwise. */
|
||||||
|
switch (msgop)
|
||||||
|
{
|
||||||
|
case MSGOP_msgctl:
|
||||||
|
res = msgctl (&td, &_parameters.in.ctlargs);
|
||||||
|
break;
|
||||||
|
case MSGOP_msgget:
|
||||||
|
res = msgget (&td, &_parameters.in.getargs);
|
||||||
|
break;
|
||||||
|
case MSGOP_msgrcv:
|
||||||
|
res = msgrcv (&td, &_parameters.in.rcvargs);
|
||||||
|
break;
|
||||||
|
case MSGOP_msgsnd:
|
||||||
|
res = msgsnd (&td, &_parameters.in.sndargs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Allocated by the call to adjust_identity_info(). */
|
||||||
|
if (_parameters.in.ipcblk.gidlist)
|
||||||
|
free (_parameters.in.ipcblk.gidlist);
|
||||||
|
client->release ();
|
||||||
|
error_code (res);
|
||||||
|
if (msgop == MSGOP_msgrcv)
|
||||||
|
_parameters.out.rcv = td.td_retval[0];
|
||||||
|
else
|
||||||
|
_parameters.out.ret = td.td_retval[0];
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
}
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* cygserver_process.cc
|
/* process.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002 Red Hat Inc.
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ details. */
|
||||||
|
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
|
|
||||||
#include "cygserver_process.h"
|
#include "process.h"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ details. */
|
||||||
|
|
||||||
process_cleanup::~process_cleanup ()
|
process_cleanup::~process_cleanup ()
|
||||||
{
|
{
|
||||||
safe_delete (_process);
|
delete _process;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -139,7 +139,7 @@ process::remove (const cleanup_routine *const entry)
|
||||||
else
|
else
|
||||||
_routines_head = ptr->_next;
|
_routines_head = ptr->_next;
|
||||||
|
|
||||||
safe_delete (ptr);
|
delete ptr;
|
||||||
res = true;
|
res = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ process::cleanup ()
|
||||||
cleanup_routine *const ptr = entry;
|
cleanup_routine *const ptr = entry;
|
||||||
entry = entry->_next;
|
entry = entry->_next;
|
||||||
ptr->cleanup (this);
|
ptr->cleanup (this);
|
||||||
safe_delete (ptr);
|
delete ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,11 +250,11 @@ process_cache::process (const pid_t cygpid, const DWORD winpid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = safe_new (class process, cygpid, winpid);
|
entry = new class process (cygpid, winpid);
|
||||||
if (!entry->is_active ())
|
if (!entry->is_active ())
|
||||||
{
|
{
|
||||||
LeaveCriticalSection (&_cache_write_access);
|
LeaveCriticalSection (&_cache_write_access);
|
||||||
safe_delete (entry);
|
delete entry;
|
||||||
set_errno (ESRCH);
|
set_errno (ESRCH);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ process_cache::check_and_remove_process (const size_t index)
|
||||||
LeaveCriticalSection (&_cache_write_access);
|
LeaveCriticalSection (&_cache_write_access);
|
||||||
|
|
||||||
/* Schedule any cleanup tasks for this process. */
|
/* Schedule any cleanup tasks for this process. */
|
||||||
_queue.add (safe_new (process_cleanup, process));
|
_queue.add (new process_cleanup (process));
|
||||||
}
|
}
|
||||||
|
|
||||||
class process *
|
class process *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* cygserver_process.h
|
/* process.h
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002 Red Hat Inc.
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef _CYGSERVER_PROCESS_
|
#ifndef _PROCESS_H
|
||||||
#define _CYGSERVER_PROCESS_
|
#define _PROCESS_H
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -161,4 +161,4 @@ private:
|
||||||
class process *find (DWORD winpid, class process **previous = NULL);
|
class process *find (DWORD winpid, class process **previous = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _CYGSERVER_PROCESS_ */
|
#endif /* _PROCESS_H */
|
|
@ -1,8 +1,6 @@
|
||||||
/* sem.cc: Single unix specification IPC interface for Cygwin.
|
/* sem.cc: Single unix specification IPC interface for Cygwin.
|
||||||
|
|
||||||
Copyright 2002 Red Hat, Inc.
|
Copyright 2003 Red Hat, Inc.
|
||||||
|
|
||||||
Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
|
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -10,31 +8,94 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
|
#include "woutsup.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <errno.h>
|
||||||
#include <cygwin/sem.h>
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "cygserver.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
#include "cygerrno.h"
|
#include "cygserver_ipc.h"
|
||||||
|
#include "cygserver_sem.h"
|
||||||
|
|
||||||
extern "C" int
|
client_request_sem::client_request_sem ()
|
||||||
semctl (int semid, int semnum, int cmd, ...)
|
: client_request (CYGSERVER_REQUEST_SEM,
|
||||||
{
|
&_parameters, sizeof (_parameters))
|
||||||
set_errno (ENOSYS);
|
{
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
void
|
||||||
semget (key_t key, int nsems, int semflg)
|
client_request_sem::serve (transport_layer_base *const conn,
|
||||||
|
process_cache *const cache)
|
||||||
{
|
{
|
||||||
set_errno (ENOSYS);
|
if (msglen () != sizeof (_parameters.in))
|
||||||
return -1;
|
{
|
||||||
}
|
syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
|
||||||
|
sizeof (_parameters), msglen ());
|
||||||
extern "C" int
|
error_code (EINVAL);
|
||||||
semop (int semid, struct sembuf *sops, size_t nsops)
|
msglen (0);
|
||||||
{
|
return;
|
||||||
set_errno (ENOSYS);
|
}
|
||||||
return -1;
|
if (support_semaphores == TUN_FALSE)
|
||||||
|
{
|
||||||
|
syscall_printf ("Semaphore support not started");
|
||||||
|
error_code (ENOSYS);
|
||||||
|
_parameters.out.ret = -1;
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
process *const client = cache->process (_parameters.in.ipcblk.cygpid,
|
||||||
|
_parameters.in.ipcblk.winpid);
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
|
error_code (EAGAIN);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!conn->impersonate_client ())
|
||||||
|
{
|
||||||
|
client->release ();
|
||||||
|
error_code (EACCES);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!adjust_identity_info (&_parameters.in.ipcblk))
|
||||||
|
{
|
||||||
|
client->release ();
|
||||||
|
conn->revert_to_self ();
|
||||||
|
error_code (EACCES);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Early revert_to_self since IPC code runs in kernel mode. */
|
||||||
|
conn->revert_to_self ();
|
||||||
|
thread td = { client, &_parameters.in.ipcblk, {-1, -1} };
|
||||||
|
int res;
|
||||||
|
switch (_parameters.in.semop)
|
||||||
|
{
|
||||||
|
case SEMOP_semctl:
|
||||||
|
res = semctl (&td, &_parameters.in.ctlargs);
|
||||||
|
break;
|
||||||
|
case SEMOP_semget:
|
||||||
|
res = semget (&td, &_parameters.in.getargs);
|
||||||
|
break;
|
||||||
|
case SEMOP_semop:
|
||||||
|
res = semop (&td, &_parameters.in.opargs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Allocated by the call to adjust_identity_info(). */
|
||||||
|
if (_parameters.in.ipcblk.gidlist)
|
||||||
|
free (_parameters.in.ipcblk.gidlist);
|
||||||
|
client->release ();
|
||||||
|
error_code (res);
|
||||||
|
_parameters.out.ret = td.td_retval[0];
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
}
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
/* cygserver_shm.cc: Single unix specification IPC interface for Cygwin.
|
/* shm.cc: Single unix specification IPC interface for Cygwin.
|
||||||
|
|
||||||
Copyright 2002 Red Hat, Inc.
|
Copyright 2003 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 file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -11,824 +8,33 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
#include "woutsup.h"
|
#include "woutsup.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "cygserver.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
#include "cygserver_ipc.h"
|
#include "cygserver_ipc.h"
|
||||||
#include "cygserver_shm.h"
|
#include "cygserver_shm.h"
|
||||||
#include "security.h"
|
|
||||||
|
|
||||||
#include "cygserver.h"
|
|
||||||
#include "cygserver_process.h"
|
|
||||||
#include "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_shm::client_request_shm ()
|
||||||
: client_request (CYGSERVER_REQUEST_SHM,
|
: client_request (CYGSERVER_REQUEST_SHM,
|
||||||
&_parameters, sizeof (_parameters))
|
&_parameters, sizeof (_parameters))
|
||||||
{
|
{
|
||||||
// verbose: syscall_printf ("created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*
|
|
||||||
* client_request_shm::serve ()
|
|
||||||
*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void
|
void
|
||||||
client_request_shm::serve (transport_layer_base *const conn,
|
client_request_shm::serve (transport_layer_base *const conn,
|
||||||
process_cache *const cache)
|
process_cache *const cache)
|
||||||
{
|
{
|
||||||
assert (conn);
|
|
||||||
|
|
||||||
assert (!error_code ());
|
|
||||||
|
|
||||||
if (msglen () != sizeof (_parameters.in))
|
if (msglen () != sizeof (_parameters.in))
|
||||||
{
|
{
|
||||||
syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
|
syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
|
||||||
|
@ -837,60 +43,76 @@ client_request_shm::serve (transport_layer_base *const conn,
|
||||||
msglen (0);
|
msglen (0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (support_sharedmem == TUN_FALSE)
|
||||||
// FIXME: Get a return code out of this and don't continue on error.
|
{
|
||||||
conn->impersonate_client ();
|
syscall_printf ("Shared memory support not started");
|
||||||
|
error_code (ENOSYS);
|
||||||
class process *const client = cache->process (_parameters.in.cygpid,
|
if (_parameters.in.shmop == SHMOP_shmat)
|
||||||
_parameters.in.winpid);
|
_parameters.out.ptr = (vm_offset_t)0;
|
||||||
|
else
|
||||||
|
_parameters.out.ret = -1;
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
process *const client = cache->process (_parameters.in.ipcblk.cygpid,
|
||||||
|
_parameters.in.ipcblk.winpid);
|
||||||
if (!client)
|
if (!client)
|
||||||
{
|
{
|
||||||
error_code (EAGAIN);
|
error_code (EAGAIN);
|
||||||
msglen (0);
|
msglen (0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!conn->impersonate_client ())
|
||||||
int result = -EINVAL;
|
|
||||||
|
|
||||||
switch (_parameters.in.shmop)
|
|
||||||
{
|
{
|
||||||
case SHMOP_shmget:
|
client->release ();
|
||||||
result = shmmgr.shmget (_parameters.out.shmid,
|
error_code (EACCES);
|
||||||
_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);
|
msglen (0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (!adjust_identity_info (&_parameters.in.ipcblk))
|
||||||
|
{
|
||||||
|
client->release ();
|
||||||
|
conn->revert_to_self ();
|
||||||
|
error_code (EACCES);
|
||||||
|
msglen (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Early revert_to_self since IPC code runs in kernel mode. */
|
||||||
|
conn->revert_to_self ();
|
||||||
|
thread td = { client, &_parameters.in.ipcblk, {0, 0} };
|
||||||
|
int res;
|
||||||
|
shmop_t shmop = _parameters.in.shmop; /* Get's overwritten otherwise. */
|
||||||
|
switch (shmop)
|
||||||
|
{
|
||||||
|
case SHMOP_shmat:
|
||||||
|
ipc_p_vmspace (td.ipcblk);
|
||||||
|
res = shmat (&td, &_parameters.in.atargs);
|
||||||
|
break;
|
||||||
|
case SHMOP_shmctl:
|
||||||
|
res = shmctl (&td, &_parameters.in.ctlargs);
|
||||||
|
break;
|
||||||
|
case SHMOP_shmdt:
|
||||||
|
ipc_p_vmspace (td.ipcblk);
|
||||||
|
res = shmdt (&td, &_parameters.in.dtargs);
|
||||||
|
break;
|
||||||
|
case SHMOP_shmget:
|
||||||
|
res = shmget (&td, &_parameters.in.getargs);
|
||||||
|
break;
|
||||||
|
case SHMOP_shmfork:
|
||||||
|
res = cygwin_shmfork_myhook (&td, &_parameters.in.forkargs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Allocated by the call to adjust_identity_info(). */
|
||||||
|
if (_parameters.in.ipcblk.gidlist)
|
||||||
|
free (_parameters.in.ipcblk.gidlist);
|
||||||
|
client->release ();
|
||||||
|
error_code (res);
|
||||||
|
if (shmop == SHMOP_shmat)
|
||||||
|
_parameters.out.ptr = td.td_retval[0];
|
||||||
else
|
else
|
||||||
msglen (sizeof (_parameters.out));
|
_parameters.out.ret = td.td_retval[0];
|
||||||
|
if (shmop == SHMOP_shmget)
|
||||||
|
_parameters.out.obj = td.td_retval[1];
|
||||||
|
msglen (sizeof (_parameters.out));
|
||||||
}
|
}
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
/* threaded_queue.cc
|
/* threaded_queue.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Robert Collins <rbtcollins@hotmail.com>
|
Written by Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
|
#ifdef __OUTSIDE_CYGWIN__
|
||||||
#include "woutsup.h"
|
#include "woutsup.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -73,7 +74,7 @@ threaded_queue::~threaded_queue ()
|
||||||
{
|
{
|
||||||
queue_request *const ptr = reqptr;
|
queue_request *const ptr = reqptr;
|
||||||
reqptr = reqptr->_next;
|
reqptr = reqptr->_next;
|
||||||
safe_delete (ptr);
|
delete ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteCriticalSection (&_queue_lock);
|
DeleteCriticalSection (&_queue_lock);
|
||||||
|
@ -267,7 +268,7 @@ threaded_queue::worker_loop ()
|
||||||
|
|
||||||
assert (reqptr);
|
assert (reqptr);
|
||||||
reqptr->process ();
|
reqptr->process ();
|
||||||
safe_delete (reqptr);
|
delete reqptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,3 +407,4 @@ queue_submission_loop::start_routine (const LPVOID lpParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
#endif /* __OUTSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver_transport.cc
|
/* transport.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Robert Collins <rbtcollins@hotmail.com>
|
Written by Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
@ -19,31 +19,33 @@ details. */
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include "safe_memory.h"
|
#include "transport.h"
|
||||||
|
#include "transport_pipes.h"
|
||||||
#include "cygserver_transport.h"
|
#include "transport_sockets.h"
|
||||||
#include "cygserver_transport_pipes.h"
|
|
||||||
#include "cygserver_transport_sockets.h"
|
|
||||||
|
|
||||||
/* The factory */
|
/* The factory */
|
||||||
transport_layer_base *
|
transport_layer_base *
|
||||||
create_server_transport ()
|
create_server_transport ()
|
||||||
{
|
{
|
||||||
if (wincap.is_winnt ())
|
if (wincap.is_winnt ())
|
||||||
return safe_new0 (transport_layer_pipes);
|
return new transport_layer_pipes;
|
||||||
else
|
else
|
||||||
return safe_new0 (transport_layer_sockets);
|
return new transport_layer_sockets;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifndef __INSIDE_CYGWIN__
|
||||||
|
|
||||||
void
|
bool
|
||||||
transport_layer_base::impersonate_client ()
|
transport_layer_base::impersonate_client ()
|
||||||
{}
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
transport_layer_base::revert_to_self ()
|
transport_layer_base::revert_to_self ()
|
||||||
{}
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
#endif /* !__INSIDE_CYGWIN__ */
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver_transport.h
|
/* transport.h
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Robert Collins <rbtcollins@hotmail.com>
|
Written by Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef _CYGSERVER_TRANSPORT_
|
#ifndef _TRANSPORT_H
|
||||||
#define _CYGSERVER_TRANSPORT_
|
#define _TRANSPORT_H
|
||||||
|
|
||||||
class transport_layer_base *create_server_transport ();
|
class transport_layer_base *create_server_transport ();
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ public:
|
||||||
virtual int connect () = 0;
|
virtual int connect () = 0;
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifndef __INSIDE_CYGWIN__
|
||||||
virtual void impersonate_client ();
|
virtual bool impersonate_client ();
|
||||||
virtual void revert_to_self ();
|
virtual bool revert_to_self ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual ~transport_layer_base ();
|
virtual ~transport_layer_base ();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _CYGSERVER_TRANSPORT_ */
|
#endif /* _TRANSPORT_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver_transport_pipes.cc
|
/* transport_pipes.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Robert Collins <rbtcollins@hotmail.com>
|
Written by Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
@ -25,11 +25,14 @@ details. */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
#include "cygserver_transport.h"
|
#include "transport.h"
|
||||||
#include "cygserver_transport_pipes.h"
|
#include "transport_pipes.h"
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifndef __INSIDE_CYGWIN__
|
||||||
#include "cygserver.h"
|
#include "cygserver.h"
|
||||||
|
#include "cygserver_ipc.h"
|
||||||
|
#else
|
||||||
|
#include "security.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -64,7 +67,6 @@ transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe)
|
||||||
assert (_hPipe);
|
assert (_hPipe);
|
||||||
assert (_hPipe != INVALID_HANDLE_VALUE);
|
assert (_hPipe != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
init_security ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
#endif /* !__INSIDE_CYGWIN__ */
|
||||||
|
@ -75,22 +77,6 @@ transport_layer_pipes::transport_layer_pipes ()
|
||||||
_is_accepted_endpoint (false),
|
_is_accepted_endpoint (false),
|
||||||
_is_listening_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 ()
|
transport_layer_pipes::~transport_layer_pipes ()
|
||||||
|
@ -138,7 +124,7 @@ transport_layer_pipes::accept (bool *const recoverable)
|
||||||
(PIPE_TYPE_BYTE | PIPE_WAIT),
|
(PIPE_TYPE_BYTE | PIPE_WAIT),
|
||||||
PIPE_UNLIMITED_INSTANCES,
|
PIPE_UNLIMITED_INSTANCES,
|
||||||
0, 0, 1000,
|
0, 0, 1000,
|
||||||
&_sec_all_nih);
|
&sec_all_nih);
|
||||||
|
|
||||||
const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE
|
const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE
|
||||||
&& pipe_instance == 0
|
&& pipe_instance == 0
|
||||||
|
@ -175,7 +161,7 @@ transport_layer_pipes::accept (bool *const recoverable)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return safe_new (transport_layer_pipes, accept_pipe);
|
return new transport_layer_pipes (accept_pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
#endif /* !__INSIDE_CYGWIN__ */
|
||||||
|
@ -281,7 +267,7 @@ transport_layer_pipes::connect ()
|
||||||
_hPipe = CreateFile (_pipe_name,
|
_hPipe = CreateFile (_pipe_name,
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
&_sec_all_nih,
|
&sec_all_nih,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
SECURITY_IMPERSONATION,
|
SECURITY_IMPERSONATION,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -331,32 +317,33 @@ transport_layer_pipes::connect ()
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifndef __INSIDE_CYGWIN__
|
||||||
|
|
||||||
void
|
bool
|
||||||
transport_layer_pipes::impersonate_client ()
|
transport_layer_pipes::impersonate_client ()
|
||||||
{
|
{
|
||||||
assert (_hPipe);
|
assert (_hPipe);
|
||||||
assert (_hPipe != INVALID_HANDLE_VALUE);
|
assert (_hPipe != INVALID_HANDLE_VALUE);
|
||||||
assert (_is_accepted_endpoint);
|
assert (_is_accepted_endpoint);
|
||||||
|
|
||||||
// verbose: debug_printf ("impersonating pipe %p", _hPipe);
|
if (_hPipe && !ImpersonateNamedPipeClient (_hPipe))
|
||||||
if (_hPipe)
|
|
||||||
{
|
{
|
||||||
assert (_hPipe != INVALID_HANDLE_VALUE);
|
debug_printf ("Failed to Impersonate client, (%lu)", GetLastError ());
|
||||||
|
return false;
|
||||||
if (!ImpersonateNamedPipeClient (_hPipe))
|
|
||||||
debug_printf ("Failed to Impersonate the client, (%lu)",
|
|
||||||
GetLastError ());
|
|
||||||
}
|
}
|
||||||
// verbose: debug_printf ("I am who you are");
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
transport_layer_pipes::revert_to_self ()
|
transport_layer_pipes::revert_to_self ()
|
||||||
{
|
{
|
||||||
assert (_is_accepted_endpoint);
|
assert (_is_accepted_endpoint);
|
||||||
|
|
||||||
RevertToSelf ();
|
if (!RevertToSelf ())
|
||||||
// verbose: debug_printf ("I am who I yam");
|
{
|
||||||
|
debug_printf ("Failed to RevertToSelf, (%lu)", GetLastError ());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
#endif /* !__INSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* cygserver_transport_pipes.h
|
/* transport_pipes.h
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002, 2003 Red Hat Inc.
|
||||||
|
|
||||||
Written by Robert Collins <rbtcollins@hotmail.com>
|
Written by Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef _CYGSERVER_TRANSPORT_PIPES_
|
#ifndef _TRANSPORT_PIPES_H
|
||||||
#define _CYGSERVER_TRANSPORT_PIPES_
|
#define _TRANSPORT_PIPES_H
|
||||||
|
|
||||||
/* Named pipes based transport, for security on NT */
|
/* Named pipes based transport, for security on NT */
|
||||||
class transport_layer_pipes : public transport_layer_base
|
class transport_layer_pipes : public transport_layer_base
|
||||||
|
@ -28,20 +28,14 @@ public:
|
||||||
virtual int connect ();
|
virtual int connect ();
|
||||||
|
|
||||||
#ifndef __INSIDE_CYGWIN__
|
#ifndef __INSIDE_CYGWIN__
|
||||||
virtual void impersonate_client ();
|
virtual bool impersonate_client ();
|
||||||
virtual void revert_to_self ();
|
virtual bool revert_to_self ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
transport_layer_pipes ();
|
transport_layer_pipes ();
|
||||||
virtual ~transport_layer_pipes ();
|
virtual ~transport_layer_pipes ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* for pipe based communications */
|
|
||||||
void init_security ();
|
|
||||||
|
|
||||||
//FIXME: allow inited, sd, all_nih_.. to be static members
|
|
||||||
SECURITY_DESCRIPTOR _sd;
|
|
||||||
SECURITY_ATTRIBUTES _sec_all_nih;
|
|
||||||
const char *const _pipe_name;
|
const char *const _pipe_name;
|
||||||
HANDLE _hPipe;
|
HANDLE _hPipe;
|
||||||
const bool _is_accepted_endpoint;
|
const bool _is_accepted_endpoint;
|
||||||
|
@ -50,4 +44,4 @@ private:
|
||||||
transport_layer_pipes (HANDLE hPipe);
|
transport_layer_pipes (HANDLE hPipe);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _CYGSERVER_TRANSPORT_PIPES_ */
|
#endif /* _TRANSPORT_PIPES_H */
|
|
@ -1,4 +1,4 @@
|
||||||
/* cygserver_transport_sockets.cc
|
/* transport_sockets.cc
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002 Red Hat Inc.
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ details. */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cygserver_transport.h"
|
#include "transport.h"
|
||||||
#include "cygserver_transport_sockets.h"
|
#include "transport_sockets.h"
|
||||||
|
|
||||||
/* to allow this to link into cygwin and the .dll, a little magic is needed. */
|
/* to allow this to link into cygwin and the .dll, a little magic is needed. */
|
||||||
#ifndef __OUTSIDE_CYGWIN__
|
#ifndef __OUTSIDE_CYGWIN__
|
||||||
|
@ -219,7 +219,7 @@ transport_layer_sockets::accept (bool *const recoverable)
|
||||||
|
|
||||||
debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd);
|
debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd);
|
||||||
|
|
||||||
return safe_new (transport_layer_sockets, accept_fd);
|
return new transport_layer_sockets (accept_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__INSIDE_CYGWIN__ */
|
#endif /* !__INSIDE_CYGWIN__ */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* cygserver_transport_sockets.h
|
/* transport_sockets.h
|
||||||
|
|
||||||
Copyright 2001, 2002 Red Hat Inc.
|
Copyright 2001, 2002 Red Hat Inc.
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#ifndef _CYGSERVER_TRANSPORT_SOCKETS_
|
#ifndef _TRANSPORT_SOCKETS_H
|
||||||
#define _CYGSERVER_TRANSPORT_SOCKETS_
|
#define _TRANSPORT_SOCKETS_H
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
@ -43,4 +43,4 @@ private:
|
||||||
transport_layer_sockets (int fd);
|
transport_layer_sockets (int fd);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _CYGSERVER_TRANSPORT_SOCKETS_ */
|
#endif /* _TRANSPORT_SOCKETS_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* woutsup.h: for Cygwin code compiled outside the DLL (i.e. cygserver).
|
/* woutsup.h: for Cygwin code compiled outside the DLL (i.e. cygserver).
|
||||||
|
|
||||||
Copyright 2002 Red Hat, Inc.
|
Copyright 2002, 2003 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -42,67 +42,32 @@ details. */
|
||||||
|
|
||||||
#include "wincap.h"
|
#include "wincap.h"
|
||||||
|
|
||||||
|
#include "bsd_helper.h"
|
||||||
|
#include "bsd_log.h"
|
||||||
|
#include "bsd_mutex.h"
|
||||||
|
|
||||||
/* The one function we use from winuser.h most of the time */
|
/* The one function we use from winuser.h most of the time */
|
||||||
extern "C" DWORD WINAPI GetLastError (void);
|
extern "C" DWORD WINAPI GetLastError (void);
|
||||||
|
|
||||||
extern int cygserver_running;
|
extern int cygserver_running;
|
||||||
|
|
||||||
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L
|
#define SIGHANDLE(SIG) \
|
||||||
#define NEW_MACRO_VARARGS
|
do \
|
||||||
#endif
|
{ \
|
||||||
|
struct sigaction act; \
|
||||||
/*
|
\
|
||||||
* A reproduction of the <sys/strace.h> macros. This allows code that
|
act.sa_handler = &handle_signal; \
|
||||||
* runs both inside and outside the Cygwin DLL to use the same macros
|
act.sa_mask = 0; \
|
||||||
* for logging messages.
|
act.sa_flags = 0; \
|
||||||
*/
|
\
|
||||||
|
if (sigaction (SIG, &act, NULL) == -1) \
|
||||||
extern "C" void __cygserver__printf (const char *, const char *, ...);
|
{ \
|
||||||
|
panic ("failed to install handler for " #SIG ": %s", \
|
||||||
#ifdef NEW_MACRO_VARARGS
|
strerror (errno)); \
|
||||||
|
exit (1); \
|
||||||
#define system_printf(...) \
|
} \
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
__cygserver__printf (__PRETTY_FUNCTION__, __VA_ARGS__); \
|
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
#define __noop_printf(...) do {;} while (false)
|
#define debug_printf(f,...) debug((f),##__VA_ARGS__)
|
||||||
|
#define syscall_printf(f,...) log(LOG_ERR,(f),##__VA_ARGS__)
|
||||||
#else /* !NEW_MACRO_VARARGS */
|
#define system_printf(f,...) log(LOG_ERR,(f),##__VA_ARGS__)
|
||||||
|
|
||||||
#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"
|
|
||||||
|
|
Loading…
Reference in New Issue