summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-07-06 05:10:42 +0000
committerChristopher Faylor <cgf@redhat.com>2003-07-06 05:10:42 +0000
commit61845845988c077545effa69e36fefe40c2f5a18 (patch)
treed728c7cf589c5dad057c817f6f945b0106617867
parent09edab1c1dcc6c47daef3d4ac3f277116cf88912 (diff)
downloadgdb-61845845988c077545effa69e36fefe40c2f5a18.tar.gz
merge from trunk
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/Makefile.in37
-rw-r--r--winsup/cygwin/acconfig.h20
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/config.h.in41
-rwxr-xr-xwinsup/cygwin/configure48
-rw-r--r--winsup/cygwin/configure.in38
-rw-r--r--winsup/cygwin/cygerrno.h41
-rw-r--r--winsup/cygwin/cygheap.cc1
-rw-r--r--winsup/cygwin/cygheap.h48
-rwxr-xr-xwinsup/cygwin/cygserver.cc773
-rwxr-xr-xwinsup/cygwin/cygserver_client.cc528
-rwxr-xr-xwinsup/cygwin/cygserver_process.cc431
-rwxr-xr-xwinsup/cygwin/cygserver_transport_pipes.cc362
-rw-r--r--winsup/cygwin/cygthread.cc1
-rw-r--r--winsup/cygwin/cygwin.din2
-rw-r--r--winsup/cygwin/dcrt0.cc7
-rw-r--r--winsup/cygwin/debug.cc3
-rw-r--r--winsup/cygwin/dir.cc1
-rw-r--r--winsup/cygwin/dll_init.cc1
-rw-r--r--winsup/cygwin/dtable.cc7
-rw-r--r--winsup/cygwin/environ.cc57
-rw-r--r--winsup/cygwin/errno.cc93
-rw-r--r--winsup/cygwin/exceptions.cc9
-rw-r--r--winsup/cygwin/exec.cc1
-rw-r--r--winsup/cygwin/external.cc1
-rw-r--r--winsup/cygwin/fcntl.cc1
-rw-r--r--winsup/cygwin/fhandler.cc3
-rw-r--r--winsup/cygwin/fhandler.h7
-rw-r--r--winsup/cygwin/fhandler_clipboard.cc1
-rw-r--r--winsup/cygwin/fhandler_console.cc1
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc12
-rw-r--r--winsup/cygwin/fhandler_dsp.cc1
-rw-r--r--winsup/cygwin/fhandler_floppy.cc1
-rw-r--r--winsup/cygwin/fhandler_mem.cc1
-rw-r--r--winsup/cygwin/fhandler_proc.cc1
-rw-r--r--winsup/cygwin/fhandler_process.cc1
-rw-r--r--winsup/cygwin/fhandler_random.cc1
-rw-r--r--winsup/cygwin/fhandler_raw.cc1
-rw-r--r--winsup/cygwin/fhandler_registry.cc1
-rw-r--r--winsup/cygwin/fhandler_serial.cc1
-rw-r--r--winsup/cygwin/fhandler_socket.cc22
-rw-r--r--winsup/cygwin/fhandler_tape.cc1
-rw-r--r--winsup/cygwin/fhandler_termios.cc1
-rw-r--r--winsup/cygwin/fhandler_tty.cc17
-rw-r--r--winsup/cygwin/fhandler_virtual.cc1
-rw-r--r--winsup/cygwin/fhandler_windows.cc1
-rw-r--r--winsup/cygwin/fork.cc21
-rw-r--r--winsup/cygwin/grp.cc7
-rw-r--r--winsup/cygwin/heap.cc1
-rw-r--r--winsup/cygwin/include/cygwin/config.h1
-rw-r--r--winsup/cygwin/include/cygwin/version.h5
-rw-r--r--winsup/cygwin/include/sys/syslog.h86
-rw-r--r--winsup/cygwin/ioctl.cc1
-rw-r--r--winsup/cygwin/malloc_wrapper.cc1
-rw-r--r--winsup/cygwin/mmap.cc91
-rw-r--r--winsup/cygwin/msg.cc47
-rw-r--r--winsup/cygwin/net.cc54
-rw-r--r--winsup/cygwin/ntea.cc2
-rw-r--r--winsup/cygwin/passwd.cc1
-rw-r--r--winsup/cygwin/path.cc154
-rw-r--r--winsup/cygwin/path.h4
-rw-r--r--winsup/cygwin/pinfo.cc3
-rw-r--r--winsup/cygwin/pipe.cc1
-rw-r--r--winsup/cygwin/poll.cc2
-rw-r--r--winsup/cygwin/resource.cc188
-rw-r--r--winsup/cygwin/scandir.cc99
-rw-r--r--winsup/cygwin/sched.cc443
-rw-r--r--winsup/cygwin/sec_acl.cc1
-rw-r--r--winsup/cygwin/sec_helper.cc1
-rw-r--r--winsup/cygwin/security.cc24
-rw-r--r--winsup/cygwin/security.h6
-rw-r--r--winsup/cygwin/select.cc1
-rw-r--r--winsup/cygwin/sem.cc40
-rw-r--r--winsup/cygwin/shared.cc1
-rw-r--r--winsup/cygwin/shm.cc4
-rw-r--r--winsup/cygwin/signal.cc5
-rw-r--r--winsup/cygwin/sigproc.cc1
-rw-r--r--winsup/cygwin/spawn.cc24
-rw-r--r--winsup/cygwin/strace.cc1
-rw-r--r--winsup/cygwin/syscalls.cc125
-rw-r--r--winsup/cygwin/sysconf.cc1
-rw-r--r--winsup/cygwin/syslog.cc16
-rw-r--r--winsup/cygwin/termios.cc1
-rw-r--r--winsup/cygwin/thread.cc108
-rw-r--r--winsup/cygwin/thread.h13
-rw-r--r--winsup/cygwin/times.cc1
-rw-r--r--winsup/cygwin/tty.cc10
-rw-r--r--winsup/cygwin/uinfo.cc27
-rw-r--r--winsup/cygwin/wait.cc1
-rw-r--r--winsup/cygwin/window.cc249
-rw-r--r--winsup/cygwin/winsup.h5
92 files changed, 4033 insertions, 496 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a4182314605..352df7b9dd6 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,18 +1,32 @@
+2003-07-04 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (fhandler_disk_file::mmap): Fix address test.
+
+2003-07-03 Christopher Faylor <cgf@redhat.com>
+
+ * path.cc (fillout_mntent): Change "posix" to "managed".
+
2003-07-02 Christopher Faylor <cgf@redhat.com>
* fhandler.h (FH_ENC): New enum.
(fhandler_base::get_encoded): New function.
(fhandler_base::set_encoded): Ditto.
- * fhandler_disk_file.cc (fhandler_disk_file::readdir): Unmunge filename
- as appropriate based on new encoding flag.
- * path.cc (normalize_posix_path): Change drive check short-circuit.
+ * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set encoded flag
+ in fhandler, as appropriate.
+ (fhandler_disk_file::readdir): Unmunge filename as appropriate based on
+ new encoding flag.
+ * path.cc (normalize_posix_path): Don't punt on files with colons.
(special_char): New function.
(mount_item::fnmunge): Ditto.
(fnunmunge): Ditto.
(special_name): Ditto.
+ (mount_item::build_win32): Avoid drive considerations when file is
+ encoded.
(mount_info::conv_to_win32_path): Handle encoded filenames.
+ (mount_info::conv_to_posix_path): Ditto.
(fillout_mntent): Add posix string when directory is encoded.
* path.h (fnunmunge): Declare.
+ (path_conv::is_encoded): Declare.
2003-07-03 Christopher Faylor <cgf@redhat.com>
@@ -386,7 +400,7 @@
2003-05-27 Bill C. Riemers <cygwin@docbill.net>
* fhandler_disk_file.cc (fhandler_disk_file::fstat_helper): Filter
- permissions throug umask on FAT or if ntsec is off.
+ permissions through umask on FAT or if ntsec is off.
2003-05-26 Pierre Humblet <pierre.humblet@ieee.org>
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index b892b37c7c2..53422ac9bcd 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -146,9 +146,7 @@ DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
MT_SAFE_OBJECTS:=
# Please maintain this list in sorted order, with maximum files per 80 col line
-DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygserver_client.o \
- cygserver_transport.o cygserver_transport_pipes.o \
- cygserver_transport_sockets.o cygthread.o dcrt0.o debug.o \
+DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygthread.o dcrt0.o debug.o \
delqueue.o devices.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o \
exceptions.o exec.o external.o fcntl.o fhandler.o \
fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \
@@ -252,7 +250,7 @@ install_host=@install_host@
all: all_target $(all_host)
-all_target: $(TARGET_LIBS) cygserver.exe
+all_target: $(TARGET_LIBS)
all_host: $(TEST_LIB_NAME)
@@ -264,7 +262,7 @@ install: install-libs install-headers install-man install_target \
uninstall: uninstall-libs uninstall-headers uninstall-man
install-libs: $(TARGET_LIBS)
- $(INSTALL_DATA) $(TEST_DLL_NAME) $(bindir)/$(DLL_NAME); \
+ $(INSTALL_PROGRAM) $(TEST_DLL_NAME) $(bindir)/$(DLL_NAME); \
for i in $^; do \
$(INSTALL_DATA) $$i $(tooldir)/lib/`basename $$i` ; \
done
@@ -293,8 +291,7 @@ install-man:
$(INSTALL_DATA) $$i $(tooldir)/man/man7/`basename $$i` ; \
done
-install_target: cygserver.exe
- $(INSTALL_PROGRAM) cygserver.exe $(bindir)/cygserver.exe
+install_target:
install_host:
@@ -399,32 +396,6 @@ winver_stamp: mkvers.sh include/cygwin/version.h winver.rc $(DLL_OFILES)
$(COMPILE_CXX) -o version.o version.cc && \
touch $@
-cygserver_transport_outside.o: cygserver_transport.cc
- $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
-
-cygserver_transport_pipes_outside.o: cygserver_transport_pipes.cc
- $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
-
-cygserver_transport_sockets_outside.o: cygserver_transport_sockets.cc
- $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
-
-cygserver_client_outside.o: cygserver_client.cc
- $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
-
-# gperf -c --key-positions='1-126' -r -t -C -E -L 'ANSI-C' -Hdevhash -N'device::lookup' -Z devstring -7 $? |\
-
-$(srcdir)/devices.cc: cygwin-gperf devices.gperf devices.h
- perl $^ > $@
-
-cygserver.exe: cygserver.o cygserver_shm.o cygserver_transport_outside.o cygserver_transport_pipes_outside.o cygserver_transport_sockets_outside.o cygserver_client_outside.o cygserver_process.o threaded_queue.o wincap.o version.o smallprint.o
- $(CXX) -o $@ $^ -lstdc++
-#ifdef VERBOSE
-# $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
-#else
-# @echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)};\
-# $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
-#endif
-
-lgcc:
:
diff --git a/winsup/cygwin/acconfig.h b/winsup/cygwin/acconfig.h
new file mode 100644
index 00000000000..79e2651d38d
--- /dev/null
+++ b/winsup/cygwin/acconfig.h
@@ -0,0 +1,20 @@
+/* Define if DEBUGGING support is requested. */
+#undef DEBUGGING
+
+/* Define if building "extra" thread-safe Cygwin DLL. */
+#undef _CYG_THREAD_FAILSAFE
+
+/* Define if GCC supports builtin memset. */
+#undef HAVE_BUILTIN_MEMSET
+
+/* Define if MALLOC_DEBUGGING support is requested. */
+#undef MALLOC_DEBUG
+
+/* Define if building thread-safe Cygwin DLL. */
+#undef _MT_SAFE
+
+/* Define if using new vfork functionality. */
+#undef NEWVFORK
+
+/* Define if using cygserver */
+#undef USE_CYGSERVER
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 71e7f9ead90..f5cc250fa0e 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -492,6 +492,7 @@ LoadDLLfuncEx (WSAEnumNetworkEvents, 12, ws2_32, 1)
LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
LoadDLLfuncEx (GetIfEntry, 4, iphlpapi, 1)
LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
+LoadDLLfuncEx (GetNetworkParams, 8, iphlpapi, 1)
LoadDLLfunc (CoInitialize, 4, ole32)
LoadDLLfunc (CoUninitialize, 0, ole32)
diff --git a/winsup/cygwin/config.h.in b/winsup/cygwin/config.h.in
new file mode 100644
index 00000000000..d4f6269e0d6
--- /dev/null
+++ b/winsup/cygwin/config.h.in
@@ -0,0 +1,41 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if DEBUGGING support is requested. */
+#undef DEBUGGING
+
+/* Define if building "extra" thread-safe Cygwin DLL. */
+#undef _CYG_THREAD_FAILSAFE
+
+/* Define if GCC supports builtin memset. */
+#undef HAVE_BUILTIN_MEMSET
+
+/* Define if MALLOC_DEBUGGING support is requested. */
+#undef MALLOC_DEBUG
+
+/* Define if using new vfork functionality. */
+#undef NEWVFORK
+
+/* Define if using cygserver */
+#undef USE_CYGSERVER
diff --git a/winsup/cygwin/configure b/winsup/cygwin/configure
index f5c8a7d4be6..af5f3cab0fe 100755
--- a/winsup/cygwin/configure
+++ b/winsup/cygwin/configure
@@ -12,12 +12,12 @@ ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
- --enable-threadsafe=[runtime] Build a cygwin DLL which is thread safe"
-ac_help="$ac_help
--enable-extra-threadsafe-checking Build a cygwin DLL which is thread safe with extra consistency checking"
ac_help="$ac_help
--enable-debugging Build a cygwin DLL which has more consistency checking for debugging"
ac_help="$ac_help
+ --enable-server Build a cygwin DLL which can communicate with cygserver"
+ac_help="$ac_help
--enable-malloc-debugging Build a cygwin DLL with heap sanity checking (this is very slow, use only if you have heap corruption problems)"
ac_help="$ac_help
--enable-vfork Build a cygwin DLL which uses experimental vfork code"
@@ -1865,28 +1865,6 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
-mt_safe_val=1
-MT_SAFE=yes
-
-# Check whether --enable-threadsafe or --disable-threadsafe was given.
-if test "${enable_threadsafe+set}" = set; then
- enableval="$enable_threadsafe"
- case "${enableval}" in
-yes)
- ;;
-runtime)
- mt_safe_val=2
- MT_SAFE=yes
- ;;
-no)
- mt_safe_val=0
- MT_SAFE=no
- ;;
-esac
-
-fi
-
-
# Check whether --enable-extra-threadsafe-checking or --disable-extra-threadsafe-checking was given.
if test "${enable_extra_threadsafe_checking+set}" = set; then
enableval="$enable_extra_threadsafe_checking"
@@ -1906,21 +1884,26 @@ esac
fi
-if test "$MT_SAFE" = "yes"; then
- cat >> confdefs.h <<EOF
-#define _MT_SAFE $mt_safe_val
+# Check whether --enable-debugging or --disable-debugging was given.
+if test "${enable_debugging+set}" = set; then
+ enableval="$enable_debugging"
+ case "${enableval}" in
+yes) cat >> confdefs.h <<\EOF
+#define DEBUGGING 1
EOF
+ ;;
+no) ;;
+esac
fi
-
-# Check whether --enable-debugging or --disable-debugging was given.
-if test "${enable_debugging+set}" = set; then
- enableval="$enable_debugging"
+# Check whether --enable-server or --disable-server was given.
+if test "${enable_server+set}" = set; then
+ enableval="$enable_server"
case "${enableval}" in
yes) cat >> confdefs.h <<\EOF
-#define DEBUGGING 1
+#define USE_CYGSERVER 1
EOF
;;
no) ;;
@@ -2146,7 +2129,6 @@ s%@WINDRES@%$WINDRES%g
s%@CPP@%$CPP%g
s%@ALLOCA@%$ALLOCA%g
s%@SET_MAKE@%$SET_MAKE%g
-s%@MT_SAFE@%$MT_SAFE%g
s%@MALLOC_OFILES@%$MALLOC_OFILES%g
s%@DLL_ENTRY@%$DLL_ENTRY%g
s%@DEF_DLL_ENTRY@%$DEF_DLL_ENTRY%g
diff --git a/winsup/cygwin/configure.in b/winsup/cygwin/configure.in
index 48ffe7dbb48..c192221ab99 100644
--- a/winsup/cygwin/configure.in
+++ b/winsup/cygwin/configure.in
@@ -1,5 +1,5 @@
dnl Autoconf configure script for Cygwin.
-dnl Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc.
+dnl Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003 Red Hat, Inc.
dnl
dnl This file is part of Cygwin.
dnl
@@ -111,27 +111,6 @@ if test $use_builtin_memset = "yes"; then
fi
AC_LANG_RESTORE
-dnl set default mt safeness and then process the options.
-mt_safe_val=1
-MT_SAFE=yes
-
-AC_ARG_ENABLE(threadsafe,
-[ --enable-threadsafe=[runtime] Build a cygwin DLL which is thread safe],
-[case "${enableval}" in
-yes)
- dnl default.
- ;;
-runtime)
- mt_safe_val=2
- MT_SAFE=yes
- ;;
-no)
- mt_safe_val=0
- MT_SAFE=no
- ;;
-esac
-])
-
AC_ARG_ENABLE(extra-threadsafe-checking,
[ --enable-extra-threadsafe-checking Build a cygwin DLL which is thread safe with extra consistency checking],
[case "${enableval}" in
@@ -146,13 +125,6 @@ no)
esac
])
-if test "$MT_SAFE" = "yes"; then
- AC_DEFINE_UNQUOTED(_MT_SAFE,$mt_safe_val)
-fi
-
-dnl Makefile uses MT_SAFE, so we subst as well as defining it.
-AC_SUBST(MT_SAFE)
-
AC_ARG_ENABLE(debugging,
[ --enable-debugging Build a cygwin DLL which has more consistency checking for debugging],
[case "${enableval}" in
@@ -161,6 +133,14 @@ no) ;;
esac
])
+AC_ARG_ENABLE(server,
+[ --enable-server Build a cygwin DLL which can communicate with cygserver],
+[case "${enableval}" in
+yes) AC_DEFINE(USE_CYGSERVER) ;;
+no) ;;
+esac
+])
+
MALLOC_OFILES=
AC_ARG_ENABLE(malloc-debugging,
[ --enable-malloc-debugging Build a cygwin DLL with heap sanity checking (this is very slow, use only if you have heap corruption problems)],
diff --git a/winsup/cygwin/cygerrno.h b/winsup/cygwin/cygerrno.h
new file mode 100644
index 00000000000..fb00f3f1d2a
--- /dev/null
+++ b/winsup/cygwin/cygerrno.h
@@ -0,0 +1,41 @@
+/* cygerrno.h: main Cygwin header file.
+
+ Copyright 2000, 2001, 2002, 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. */
+
+#include <errno.h>
+
+void __stdcall seterrno_from_win_error (const char *file, int line, DWORD code) __attribute__ ((regparm(3)));
+void __stdcall seterrno (const char *, int line) __attribute__ ((regparm(2)));
+int __stdcall geterrno_from_win_error (DWORD code, int deferrno) __attribute__ ((regparm(2)));
+
+#define __seterrno() seterrno (__FILE__, __LINE__)
+#define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
+
+#ifndef DEBUGGING
+#define set_errno(val) (errno = (val))
+#else
+int __stdcall __set_errno (const char *ln, int ln, int val) __attribute ((regparm(3)));
+#define set_errno(val) __set_errno (__PRETTY_FUNCTION__, __LINE__, (val))
+#endif
+#define get_errno() (errno)
+extern "C" void __stdcall set_sig_errno (int e);
+
+class save_errno
+ {
+ int saved;
+ public:
+ save_errno () {saved = get_errno ();}
+ save_errno (int what) {saved = get_errno (); set_errno (what); }
+ void set (int what) {set_errno (what); saved = what;}
+ void reset () {saved = get_errno ();}
+ ~save_errno () {set_errno (saved);}
+ };
+
+extern const char *__sp_fn;
+extern int __sp_ln;
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index 1d3e4fb84c6..1ee1f2d7192 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -10,7 +10,6 @@
#include "winsup.h"
#include <string.h>
-#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include "security.h"
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 281f9b4b7eb..215d202b51b 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -92,7 +92,13 @@ enum homebodies
CH_HOME
};
-struct passwd;
+enum impersonation
+{
+ IMP_BAD = -1,
+ IMP_NONE = 0,
+ IMP_EXTERNAL,
+ IMP_INTERNAL
+};
class cygheap_user
{
@@ -117,8 +123,9 @@ public:
/* token is needed if set(e)uid should be called. It can be set by a call
to `set_impersonation_token()'. */
- HANDLE token;
- BOOL impersonated;
+ HANDLE external_token;
+ HANDLE internal_token;
+ enum impersonation impersonation_state;
/* CGF 2002-06-27. I removed the initializaton from this constructor
since this class is always allocated statically. That means that everything
@@ -165,7 +172,40 @@ public:
const char *ontherange (homebodies what, struct passwd * = NULL);
bool issetuid () const
{
- return impersonated && token != INVALID_HANDLE_VALUE;
+ return impersonation_state > IMP_NONE;
+ }
+ HANDLE token ()
+ {
+ if (impersonation_state == IMP_EXTERNAL)
+ return external_token;
+ if (impersonation_state == IMP_INTERNAL)
+ return internal_token;
+ return INVALID_HANDLE_VALUE;
+ }
+ void deimpersonate ()
+ {
+ if (impersonation_state > IMP_NONE)
+ RevertToSelf ();
+ }
+ void reimpersonate ()
+ {
+ if (impersonation_state > IMP_NONE
+ && !ImpersonateLoggedOnUser (token ()))
+ system_printf ("ImpersonateLoggedOnUser: %E");
+ }
+ bool has_impersonation_tokens () { return external_token || internal_token; }
+ void close_impersonation_tokens ()
+ {
+ if (external_token)
+ {
+ CloseHandle (external_token);
+ external_token = 0;
+ }
+ if (internal_token)
+ {
+ CloseHandle (internal_token);
+ internal_token = 0;
+ }
}
const char *cygheap_user::test_uid (char *&, const char *, size_t)
__attribute__ ((regparm (3)));
diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc
new file mode 100755
index 00000000000..137730f9ef7
--- /dev/null
+++ b/winsup/cygwin/cygserver.cc
@@ -0,0 +1,773 @@
+/* cygserver.cc
+
+ Copyright 2001, 2002 Red Hat Inc.
+
+ Written by Egor Duda <deo@logos-m.ru>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "woutsup.h"
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "cygerrno.h"
+#include "cygwin_version.h"
+
+#include "cygwin/cygserver.h"
+#include "cygwin/cygserver_process.h"
+#include "cygwin/cygserver_transport.h"
+
+// Version string.
+static const char version[] = "$Revision$";
+
+/*
+ * Support function for the XXX_printf () macros in "woutsup.h".
+ * Copied verbatim from "strace.cc".
+ */
+static int
+getfunc (char *in_dst, const char *func)
+{
+ const char *p;
+ const char *pe;
+ char *dst = in_dst;
+ for (p = func; (pe = strchr (p, '(')); p = pe + 1)
+ if (isalnum ((int)pe[-1]) || pe[-1] == '_')
+ break;
+ else if (isspace ((int)pe[-1]))
+ {
+ pe--;
+ break;
+ }
+ if (!pe)
+ pe = strchr (func, '\0');
+ for (p = pe; p > func; p--)
+ if (p != pe && *p == ' ')
+ {
+ p++;
+ break;
+ }
+ if (*p == '*')
+ p++;
+ while (p < pe)
+ *dst++ = *p++;
+
+ *dst++ = ':';
+ *dst++ = ' ';
+ *dst = '\0';
+
+ return dst - in_dst;
+}
+
+/*
+ * Support function for the XXX_printf () macros in "woutsup.h".
+ */
+extern "C" void
+__cygserver__printf (const char *const function, const char *const fmt, ...)
+{
+ const DWORD lasterror = GetLastError ();
+ const int lasterrno = errno;
+
+ va_list ap;
+
+ char *const buf = (char *) alloca (BUFSIZ);
+
+ assert (buf);
+
+ int len = 0;
+
+ if (function)
+ len += getfunc (buf, function);
+
+ va_start (ap, fmt);
+ len += vsnprintf (buf + len, BUFSIZ - len, fmt, ap);
+ va_end (ap);
+
+ len += snprintf (buf + len, BUFSIZ - len, "\n");
+
+ const int actual = (len > BUFSIZ ? BUFSIZ : len);
+
+ write (2, buf, actual);
+
+ errno = lasterrno;
+ SetLastError (lasterror);
+
+ return;
+}
+
+#ifdef DEBUGGING
+
+int __stdcall
+__set_errno (const char *func, int ln, int val)
+{
+ debug_printf ("%s:%d val %d", func, ln, val);
+ return _impure_ptr->_errno = val;
+}
+
+#endif /* DEBUGGING */
+
+GENERIC_MAPPING access_mapping;
+
+static BOOL
+setup_privileges ()
+{
+ BOOL rc, ret_val;
+ HANDLE hToken = NULL;
+ TOKEN_PRIVILEGES sPrivileges;
+
+ rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ;
+ if (!rc)
+ {
+ system_printf ("error opening process token (%lu)", GetLastError ());
+ ret_val = FALSE;
+ goto out;
+ }
+ rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid);
+ if (!rc)
+ {
+ system_printf ("error getting privilege luid (%lu)", GetLastError ());
+ ret_val = FALSE;
+ goto out;
+ }
+ sPrivileges.PrivilegeCount = 1 ;
+ sPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
+ rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ;
+ if (!rc)
+ {
+ system_printf ("error adjusting privilege level. (%lu)",
+ GetLastError ());
+ ret_val = FALSE;
+ goto out;
+ }
+
+ access_mapping.GenericRead = FILE_READ_DATA;
+ access_mapping.GenericWrite = FILE_WRITE_DATA;
+ access_mapping.GenericExecute = 0;
+ access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA;
+
+ ret_val = TRUE;
+
+out:
+ CloseHandle (hToken);
+ return ret_val;
+}
+
+int
+check_and_dup_handle (HANDLE from_process, HANDLE to_process,
+ HANDLE from_process_token,
+ DWORD access,
+ HANDLE from_handle,
+ HANDLE *to_handle_ptr, BOOL bInheritHandle = FALSE)
+{
+ HANDLE local_handle = NULL;
+ int ret_val = EACCES;
+
+ if (from_process != GetCurrentProcess ())
+ {
+ if (!DuplicateHandle (from_process, from_handle,
+ GetCurrentProcess (), &local_handle,
+ 0, bInheritHandle,
+ DUPLICATE_SAME_ACCESS))
+ {
+ system_printf ("error getting handle(%u) to server (%lu)",
+ (unsigned int)from_handle, GetLastError ());
+ goto out;
+ }
+ } else
+ local_handle = from_handle;
+
+ if (!wincap.has_security ())
+ assert (!from_process_token);
+ else
+ {
+ char sd_buf [1024];
+ PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) &sd_buf;
+ DWORD bytes_needed;
+ PRIVILEGE_SET ps;
+ DWORD ps_len = sizeof (ps);
+ BOOL status;
+
+ if (!GetKernelObjectSecurity (local_handle,
+ (OWNER_SECURITY_INFORMATION
+ | GROUP_SECURITY_INFORMATION
+ | DACL_SECURITY_INFORMATION),
+ sd, sizeof (sd_buf), &bytes_needed))
+ {
+ system_printf ("error getting handle SD (%lu)", GetLastError ());
+ goto out;
+ }
+
+ MapGenericMask (&access, &access_mapping);
+
+ if (!AccessCheck (sd, from_process_token, access, &access_mapping,
+ &ps, &ps_len, &access, &status))
+ {
+ system_printf ("error checking access rights (%lu)",
+ GetLastError ());
+ goto out;
+ }
+
+ if (!status)
+ {
+ system_printf ("access to object denied");
+ goto out;
+ }
+ }
+
+ if (!DuplicateHandle (from_process, from_handle,
+ to_process, to_handle_ptr,
+ access, bInheritHandle, 0))
+ {
+ system_printf ("error getting handle to client (%lu)", GetLastError ());
+ goto out;
+ }
+
+ // verbose: debug_printf ("Duplicated %p to %p", from_handle, *to_handle_ptr);
+
+ ret_val = 0;
+
+ out:
+ if (local_handle && from_process != GetCurrentProcess ())
+ CloseHandle (local_handle);
+
+ return (ret_val);
+}
+
+/*
+ * client_request_attach_tty::serve ()
+ */
+
+void
+client_request_attach_tty::serve (transport_layer_base *const conn,
+ process_cache *)
+{
+ assert (conn);
+
+ assert (!error_code ());
+
+ if (!wincap.has_security ())
+ {
+ syscall_printf ("operation only supported on systems with security");
+ error_code (EINVAL);
+ msglen (0);
+ return;
+ }
+
+ if (msglen () != sizeof (req))
+ {
+ syscall_printf ("bad request body length: expecting %lu bytes, got %lu",
+ sizeof (req), msglen ());
+ error_code (EINVAL);
+ msglen (0);
+ return;
+ }
+
+ msglen (0); // Until we fill in some fields.
+
+ // verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld",
+ // req.master_pid, req.from_master, req.to_master,
+ // req.pid);
+
+ // verbose: debug_printf ("opening process %ld", req.master_pid);
+
+ const HANDLE from_process_handle =
+ OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
+
+ if (!from_process_handle)
+ {
+ system_printf ("error opening `from' process, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ return;
+ }
+
+ // verbose: debug_printf ("opening process %ld", req.pid);
+
+ const HANDLE to_process_handle =
+ OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
+
+ if (!to_process_handle)
+ {
+ system_printf ("error opening `to' process, error = %lu",
+ GetLastError ());
+ CloseHandle (from_process_handle);
+ error_code (EACCES);
+ return;
+ }
+
+ // verbose: debug_printf ("Impersonating client");
+ conn->impersonate_client ();
+
+ HANDLE token_handle = NULL;
+
+ // verbose: debug_printf ("about to open thread token");
+ const DWORD rc = OpenThreadToken (GetCurrentThread (),
+ TOKEN_QUERY,
+ TRUE,
+ &token_handle);
+
+ // verbose: debug_printf ("opened thread token, rc=%lu", rc);
+ conn->revert_to_self ();
+
+ if (!rc)
+ {
+ system_printf ("error opening thread token, error = %lu",
+ GetLastError ());
+ CloseHandle (from_process_handle);
+ CloseHandle (to_process_handle);
+ error_code (EACCES);
+ return;
+ }
+
+ // From this point on, a reply body is returned to the client.
+
+ const HANDLE from_master = req.from_master;
+ const HANDLE to_master = req.to_master;
+
+ req.from_master = NULL;
+ req.to_master = NULL;
+
+ msglen (sizeof (req));
+
+ if (from_master)
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_READ,
+ from_master,
+ &req.from_master, TRUE) != 0)
+ {
+ system_printf ("error duplicating from_master handle, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ }
+
+ if (to_master)
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_WRITE,
+ to_master,
+ &req.to_master, TRUE) != 0)
+ {
+ system_printf ("error duplicating to_master handle, error = %lu",
+ GetLastError ());
+ error_code (EACCES);
+ }
+
+ CloseHandle (from_process_handle);
+ CloseHandle (to_process_handle);
+ CloseHandle (token_handle);
+
+ debug_printf ("%lu(%lu, %lu) -> %lu(%lu,%lu)",
+ req.master_pid, from_master, to_master,
+ req.pid, req.from_master, req.to_master);
+
+ return;
+}
+
+void
+client_request_get_version::serve (transport_layer_base *, process_cache *)
+{
+ assert (!error_code ());
+
+ if (msglen ())
+ syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
+
+ msglen (sizeof (version));
+
+ version.major = CYGWIN_SERVER_VERSION_MAJOR;
+ version.api = CYGWIN_SERVER_VERSION_API;
+ version.minor = CYGWIN_SERVER_VERSION_MINOR;
+ version.patch = CYGWIN_SERVER_VERSION_PATCH;
+}
+
+class server_request : public queue_request
+{
+public:
+ server_request (transport_layer_base *const conn, process_cache *const cache)
+ : _conn (conn), _cache (cache)
+ {}
+
+ virtual ~server_request ()
+ {
+ safe_delete (_conn);
+ }
+
+ virtual void process ()
+ {
+ client_request::handle_request (_conn, _cache);
+ }
+
+private:
+ transport_layer_base *const _conn;
+ process_cache *const _cache;
+};
+
+class server_submission_loop : public queue_submission_loop
+{
+public:
+ server_submission_loop (threaded_queue *const queue,
+ transport_layer_base *const transport,
+ process_cache *const cache)
+ : queue_submission_loop (queue, false),
+ _transport (transport),
+ _cache (cache)
+ {
+ assert (_transport);
+ assert (_cache);
+ }
+
+private:
+ transport_layer_base *const _transport;
+ process_cache *const _cache;
+
+ virtual void request_loop ();
+};
+
+/* FIXME: this is a little ugly. What we really want is to wait on
+ * two objects: one for the pipe/socket, and one for being told to
+ * shutdown. Otherwise this will stay a problem (we won't actually
+ * shutdown until the request _AFTER_ the shutdown request. And
+ * sending ourselves a request is ugly
+ */
+void
+server_submission_loop::request_loop ()
+{
+ /* I'd like the accepting thread's priority to be above any "normal"
+ * thread in the system to avoid overflowing the listen queue (for
+ * sockets; similar issues exist for named pipes); but, for example,
+ * a normal priority thread in a foregrounded process is boosted to
+ * THREAD_PRIORITY_HIGHEST (AFAICT). Thus try to set the current
+ * thread's priority to a level one above that. This fails on
+ * win9x/ME so assume any failure in that call is due to that and
+ * simply call again at one priority level lower.
+ */
+ if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1))
+ if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST))
+ debug_printf ("failed to raise accept thread priority, error = %lu",
+ GetLastError ());
+
+ while (_running)
+ {
+ bool recoverable = false;
+ transport_layer_base *const conn = _transport->accept (&recoverable);
+ if (!conn && !recoverable)
+ {
+ system_printf ("fatal error on IPC transport: closing down");
+ return;
+ }
+ // EINTR probably implies a shutdown request; so back off for a
+ // moment to let the main thread take control, otherwise the
+ // server spins here receiving EINTR repeatedly since the signal
+ // handler in the main thread doesn't get a chance to be called.
+ if (!conn && errno == EINTR)
+ {
+ if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL))
+ debug_printf ("failed to reset thread priority, error = %lu",
+ GetLastError ());
+
+ Sleep (0);
+ if (!SetThreadPriority (GetCurrentThread (),
+ THREAD_PRIORITY_HIGHEST + 1))
+ if (!SetThreadPriority (GetCurrentThread (),
+ THREAD_PRIORITY_HIGHEST))
+ debug_printf ("failed to raise thread priority, error = %lu",
+ GetLastError ());
+ }
+ if (conn)
+ _queue->add (safe_new (server_request, conn, _cache));
+ }
+}
+
+client_request_shutdown::client_request_shutdown ()
+ : client_request (CYGSERVER_REQUEST_SHUTDOWN)
+{
+ // verbose: syscall_printf ("created");
+}
+
+void
+client_request_shutdown::serve (transport_layer_base *, process_cache *)
+{
+ assert (!error_code ());
+
+ if (msglen ())
+ syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());
+
+ /* FIXME: link upwards, and then this becomes a trivial method call to
+ * only shutdown _this queue_
+ */
+
+ kill (getpid (), SIGINT);
+
+ msglen (0);
+}
+
+static sig_atomic_t shutdown_server = false;
+
+static void
+handle_signal (const int signum)
+{
+ /* any signal makes us die :} */
+
+ shutdown_server = true;
+}
+
+/*
+ * print_usage ()
+ */
+
+static void
+print_usage (const char *const pgm)
+{
+ printf ("Usage: %s [OPTIONS]\n", pgm);
+ printf (" -c, --cleanup-threads number of cleanup threads to use\n");
+ printf (" -h, --help output usage information and exit\n");
+ printf (" -r, --request-threads number of request threads to use\n");
+ printf (" -s, --shutdown shutdown the daemon\n");
+ printf (" -v, --version output version information and exit\n");
+}
+
+/*
+ * print_version ()
+ */
+
+static void
+print_version (const char *const pgm)
+{
+ char *vn = NULL;
+
+ const char *const colon = strchr (version, ':');
+
+ if (!colon)
+ {
+ vn = strdup ("?");
+ }
+ else
+ {
+ vn = strdup (colon + 2); // Skip ": "
+
+ char *const spc = strchr (vn, ' ');
+
+ if (spc)
+ *spc = '\0';
+ }
+
+ char buf[200];
+ snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s",
+ cygwin_version.dll_major / 1000,
+ cygwin_version.dll_major % 1000,
+ cygwin_version.dll_minor,
+ cygwin_version.api_major,
+ cygwin_version.api_minor,
+ cygwin_version.shared_data,
+ CYGWIN_SERVER_VERSION_MAJOR,
+ CYGWIN_SERVER_VERSION_API,
+ CYGWIN_SERVER_VERSION_MINOR,
+ CYGWIN_SERVER_VERSION_PATCH,
+ cygwin_version.mount_registry,
+ cygwin_version.dll_build_date);
+
+ printf ("%s (cygwin) %s\n", pgm, vn);
+ printf ("API version %s\n", buf);
+ printf ("Copyright 2001, 2002 Red Hat, Inc.\n");
+ printf ("Compiled on %s\n", __DATE__);
+
+ free (vn);
+}
+
+/*
+ * main ()
+ */
+
+int
+main (const int argc, char *argv[])
+{
+ const struct option longopts[] = {
+ {"cleanup-threads", required_argument, NULL, 'c'},
+ {"help", no_argument, NULL, 'h'},
+ {"request-threads", required_argument, NULL, 'r'},
+ {"shutdown", no_argument, NULL, 's'},
+ {"version", no_argument, NULL, 'v'},
+ {0, no_argument, NULL, 0}
+ };
+
+ const char opts[] = "c:hr:sv";
+
+ int cleanup_threads = 2;
+ int request_threads = 10;
+ bool shutdown = false;
+
+ const char *pgm = NULL;
+
+ if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/')))
+ pgm = *argv;
+ else
+ pgm++;
+
+ wincap.init ();
+ if (wincap.has_security ())
+ setup_privileges ();
+
+ int opt;
+
+ while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
+ switch (opt)
+ {
+ case 'c':
+ cleanup_threads = atoi (optarg);
+ if (cleanup_threads <= 0)
+ {
+ fprintf (stderr,
+ "%s: number of cleanup threads must be positive\n",
+ pgm);
+ exit (1);
+ }
+ break;
+
+ case 'h':
+ print_usage (pgm);
+ return 0;
+
+ case 'r':
+ request_threads = atoi (optarg);
+ if (request_threads <= 0)
+ {
+ fprintf (stderr,
+ "%s: number of request threads must be positive\n",
+ pgm);
+ exit (1);
+ }
+ break;
+
+ case 's':
+ shutdown = true;
+ break;
+
+ case 'v':
+ print_version (pgm);
+ return 0;
+
+ case '?':
+ fprintf (stderr, "Try `%s --help' for more information.\n", pgm);
+ exit (1);
+ }
+
+ if (optind != argc)
+ {
+ fprintf (stderr, "%s: too many arguments\n", pgm);
+ exit (1);
+ }
+
+ if (shutdown)
+ {
+ /* Setting `cygserver_running' stops the request code making a
+ * version request, which is not much to the point.
+ */
+ cygserver_running = CYGSERVER_OK;
+
+ client_request_shutdown req;
+
+ if (req.make_request () == -1 || req.error_code ())
+ {
+ fprintf (stderr, "%s: shutdown request failed: %s\n",
+ pgm, strerror (req.error_code ()));
+ exit (1);
+ }
+
+ // FIXME: It would be nice to wait here for the daemon to exit.
+
+ return 0;
+ }
+
+#define SIGHANDLE(SIG) \
+ do \
+ { \
+ struct sigaction act; \
+ \
+ act.sa_handler = &handle_signal; \
+ act.sa_mask = 0; \
+ act.sa_flags = 0; \
+ \
+ if (sigaction (SIG, &act, NULL) == -1) \
+ { \
+ system_printf ("failed to install handler for " #SIG ": %s", \
+ strerror (errno)); \
+ exit (1); \
+ } \
+ } while (false)
+
+ SIGHANDLE (SIGHUP);
+ SIGHANDLE (SIGINT);
+ SIGHANDLE (SIGTERM);
+
+ print_version (pgm);
+ setbuf (stdout, NULL);
+ printf ("daemon starting up");
+
+ threaded_queue request_queue (request_threads);
+ printf (".");
+
+ transport_layer_base *const transport = create_server_transport ();
+ assert (transport);
+ printf (".");
+
+ process_cache cache (cleanup_threads);
+ printf (".");
+
+ server_submission_loop submission_loop (&request_queue, transport, &cache);
+ printf (".");
+
+ request_queue.add_submission_loop (&submission_loop);
+ printf (".");
+
+ if (transport->listen () == -1)
+ {
+ exit (1);
+ }
+ printf (".");
+
+ cache.start ();
+ printf (".");
+
+ request_queue.start ();
+ printf (".");
+
+ printf ("complete\n");
+
+ /* TODO: wait on multiple objects - the thread handle for each
+ * request loop + all the process handles. This should be done by
+ * querying the request_queue and the process cache for all their
+ * handles, and then waiting for (say) 30 seconds. after that we
+ * recreate the list of handles to wait on, and wait again. the
+ * point of all this abstraction is that we can trivially server
+ * both sockets and pipes simply by making a new transport, and then
+ * calling request_queue.process_requests (transport2);
+ */
+ /* WaitForMultipleObjects abort && request_queue && process_queue && signal
+ -- if signal event then retrigger it
+ */
+ while (!shutdown_server && request_queue.running () && cache.running ())
+ pause ();
+
+ printf ("\nShutdown request received - new requests will be denied\n");
+ request_queue.stop ();
+ printf ("All pending requests processed\n");
+ safe_delete (transport);
+ printf ("No longer accepting requests - cygwin will operate in daemonless mode\n");
+ cache.stop ();
+ printf ("All outstanding process-cache activities completed\n");
+ printf ("daemon shutdown\n");
+
+ return 0;
+}
diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc
new file mode 100755
index 00000000000..f6683182d72
--- /dev/null
+++ b/winsup/cygwin/cygserver_client.cc
@@ -0,0 +1,528 @@
+/* cygserver_client.cc
+
+ Copyright 2001, 2002 Red Hat Inc.
+
+ Written by Egor Duda <deo@logos-m.ru>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* to allow this to link into cygwin and the .dll, a little magic is needed. */
+#ifdef __OUTSIDE_CYGWIN__
+#include "woutsup.h"
+#else
+#include "winsup.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "cygerrno.h"
+#include "cygserver_shm.h"
+#include "safe_memory.h"
+
+#include "cygwin/cygserver.h"
+#include "cygwin/cygserver_transport.h"
+
+int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children.
+
+/* On by default during development. For release, we probably want off
+ * by default.
+ */
+bool allow_daemon = true; // Nb: inherited by children.
+
+client_request_get_version::client_request_get_version ()
+ : client_request (CYGSERVER_REQUEST_GET_VERSION, &version, sizeof (version))
+{
+ msglen (0); // No parameters for request.
+
+ // verbose: syscall_printf ("created");
+}
+
+/*
+ * client_request_get_version::check_version ()
+ *
+ * The major version and API version numbers must match exactly. An
+ * older than expected minor version number is accepted (as long as
+ * the first numbers match, that is).
+ */
+
+bool
+client_request_get_version::check_version () const
+{
+ const bool ok = (version.major == CYGWIN_SERVER_VERSION_MAJOR
+ && version.api == CYGWIN_SERVER_VERSION_API
+ && version.minor <= CYGWIN_SERVER_VERSION_MINOR);
+
+ if (!ok)
+ syscall_printf (("incompatible version of cygwin server: "
+ "client version %d.%d.%d.%d, "
+ "server version %ld.%ld.%ld.%ld"),
+ CYGWIN_SERVER_VERSION_MAJOR,
+ CYGWIN_SERVER_VERSION_API,
+ CYGWIN_SERVER_VERSION_MINOR,
+ CYGWIN_SERVER_VERSION_PATCH,
+ version.major,
+ version.api,
+ version.minor,
+ version.patch);
+
+ return ok;
+}
+
+#ifdef __INSIDE_CYGWIN__
+
+client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid,
+ HANDLE nfrom_master,
+ HANDLE nto_master)
+ : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
+{
+ req.pid = GetCurrentProcessId ();
+ req.master_pid = nmaster_pid;
+ req.from_master = nfrom_master;
+ req.to_master = nto_master;
+
+ syscall_printf (("created: pid = %lu, master_pid = %lu, "
+ "from_master = %lu, to_master = %lu"),
+ req.pid, req.master_pid, req.from_master, req.to_master);
+}
+
+#else /* !__INSIDE_CYGWIN__ */
+
+client_request_attach_tty::client_request_attach_tty ()
+ : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req))
+{
+ // verbose: syscall_printf ("created");
+}
+
+#endif /* __INSIDE_CYGWIN__ */
+
+/*
+ * client_request_attach_tty::send ()
+ *
+ * Wraps the base method to provide error handling support. If the
+ * reply contains a body but is flagged as an error, close any handles
+ * that have been returned by cygserver and then discard the message
+ * body, i.e. the client either sees a successful result with handles
+ * or an unsuccessful result with no handles.
+ */
+
+void
+client_request_attach_tty::send (transport_layer_base * const conn)
+{
+ client_request::send (conn);
+
+ if (msglen () && error_code ())
+ {
+ if (from_master ())
+ CloseHandle (from_master ());
+ if (to_master ())
+ CloseHandle (to_master ());
+ msglen (0);
+ }
+}
+
+client_request::header_t::header_t (const request_code_t request_code,
+ const size_t msglen)
+ : msglen (msglen),
+ request_code (request_code)
+{
+ assert (request_code >= 0 && request_code < CYGSERVER_REQUEST_LAST);
+}
+
+// FIXME: also check write and read result for -1.
+
+void
+client_request::send (transport_layer_base * const conn)
+{
+ assert (conn);
+ assert (!(msglen () && !_buf)); // i.e., msglen () implies _buf
+ assert (msglen () <= _buflen);
+
+ {
+ const ssize_t count = conn->write (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("request header write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (msglen ())
+ {
+ const ssize_t count = conn->write (_buf, msglen ());
+
+ if (count == -1 || (size_t) count != msglen ())
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("request body write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, msglen (),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ // verbose: syscall_printf ("request sent (%ld + %ld bytes)",
+ // sizeof (_header), msglen ());
+
+ {
+ const ssize_t count = conn->read (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("reply header read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (msglen () && !_buf)
+ {
+ system_printf ("no client buffer for reply body: %ld bytes needed",
+ msglen ());
+ error_code (EINVAL);
+ return;
+ }
+
+ if (msglen () > _buflen)
+ {
+ system_printf (("client buffer too small for reply body: "
+ "have %ld bytes and need %ld"),
+ _buflen, msglen ());
+ error_code (EINVAL);
+ return;
+ }
+
+ if (msglen ())
+ {
+ const ssize_t count = conn->read (_buf, msglen ());
+
+ if (count == -1 || (size_t) count != msglen ())
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("reply body read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, msglen (),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ // verbose: syscall_printf ("reply received (%ld + %ld bytes)",
+ // sizeof (_header), msglen ());
+}
+
+#ifndef __INSIDE_CYGWIN__
+
+/*
+ * client_request::handle_request ()
+ *
+ * A server-side method.
+ *
+ * This is a factory method for the client_request subclasses. It
+ * reads the incoming request header and, based on its request code,
+ * creates an instance of the appropriate class.
+ *
+ * FIXME: If the incoming packet is malformed, the server drops it on
+ * the floor. Should it try and generate some sort of reply for the
+ * client? As it is, the client will simply get a broken connection.
+ *
+ * FIXME: also check write and read result for -1.
+ */
+
+/* static */ void
+client_request::handle_request (transport_layer_base *const conn,
+ process_cache *const cache)
+{
+ // verbose: debug_printf ("about to read");
+
+ header_t header;
+
+ {
+ const ssize_t count = conn->read (&header, sizeof (header));
+
+ if (count != sizeof (header))
+ {
+ syscall_printf (("request header read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (header),
+ errno, GetLastError ());
+ return;
+ }
+
+ // verbose: debug_printf ("got header (%ld)", count);
+ }
+
+ client_request *req = NULL;
+
+ switch (header.request_code)
+ {
+ case CYGSERVER_REQUEST_GET_VERSION:
+ req = safe_new0 (client_request_get_version);
+ break;
+ case CYGSERVER_REQUEST_SHUTDOWN:
+ req = safe_new0 (client_request_shutdown);
+ break;
+ case CYGSERVER_REQUEST_ATTACH_TTY:
+ req = safe_new0 (client_request_attach_tty);
+ break;
+ case CYGSERVER_REQUEST_SHM:
+ req = safe_new0 (client_request_shm);
+ break;
+ default:
+ syscall_printf ("unknown request code %d received: request ignored",
+ header.request_code);
+ return;
+ }
+
+ assert (req);
+
+ req->msglen (header.msglen);
+ req->handle (conn, cache);
+
+ safe_delete (req);
+
+#ifndef DEBUGGING
+ printf ("."); // A little noise when we're being quiet.
+#endif
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+client_request::client_request (request_code_t const id,
+ void * const buf,
+ size_t const buflen)
+ : _header (id, buflen),
+ _buf (buf),
+ _buflen (buflen)
+{
+ assert ((!_buf && !_buflen) || (_buf && _buflen));
+}
+
+client_request::~client_request ()
+{}
+
+int
+client_request::make_request ()
+{
+ assert (cygserver_running == CYGSERVER_UNKNOWN \
+ || cygserver_running == CYGSERVER_OK \
+ || cygserver_running == CYGSERVER_UNAVAIL);
+
+ if (cygserver_running == CYGSERVER_UNKNOWN)
+ cygserver_init ();
+
+ assert (cygserver_running == CYGSERVER_OK \
+ || cygserver_running == CYGSERVER_UNAVAIL);
+
+ /* Don't retry every request if the server's not there */
+ if (cygserver_running == CYGSERVER_UNAVAIL)
+ {
+ syscall_printf ("cygserver un-available");
+ error_code (ENOSYS);
+ return -1;
+ }
+
+ transport_layer_base *const transport = create_server_transport ();
+
+ assert (transport);
+
+ if (transport->connect () == -1)
+ {
+ if (errno)
+ error_code (errno);
+ else
+ error_code (ENOSYS);
+ safe_delete (transport);
+ return -1;
+ }
+
+ // verbose: debug_printf ("connected to server %p", transport);
+
+ send (transport);
+
+ safe_delete (transport);
+
+ return 0;
+}
+
+#ifndef __INSIDE_CYGWIN__
+
+/*
+ * client_request::handle ()
+ *
+ * A server-side method.
+ *
+ * At this point, the header of an incoming request has been read and
+ * an appropriate client_request object constructed. This method has
+ * to read the request body into its buffer, if there is such a body,
+ * then perform the request and send back the results to the client.
+ *
+ * FIXME: If the incoming packet is malformed, the server drops it on
+ * the floor. Should it try and generate some sort of reply for the
+ * client? As it is, the client will simply get a broken connection.
+ *
+ * FIXME: also check write and read result for -1.
+ */
+
+void
+client_request::handle (transport_layer_base *const conn,
+ process_cache *const cache)
+{
+ if (msglen () && !_buf)
+ {
+ system_printf ("no buffer for request body: %ld bytes needed",
+ msglen ());
+ error_code (EINVAL);
+ return;
+ }
+
+ if (msglen () > _buflen)
+ {
+ system_printf (("buffer too small for request body: "
+ "have %ld bytes and need %ld"),
+ _buflen, msglen ());
+ error_code (EINVAL);
+ return;
+ }
+
+ if (msglen ())
+ {
+ const ssize_t count = conn->read (_buf, msglen ());
+
+ if (count == -1 || (size_t) count != msglen ())
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("request body read failure: "
+ "only %ld bytes received of %ld, "
+ "error = %d(%lu)"),
+ count, msglen (),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ // verbose: syscall_printf ("request received (%ld + %ld bytes)",
+ // sizeof (_header), msglen ());
+
+ error_code (0); // Overwrites the _header.request_code field.
+
+ /*
+ * This is not allowed to fail. We must return ENOSYS at a minimum
+ * to the client.
+ */
+ serve (conn, cache);
+
+ {
+ const ssize_t count = conn->write (&_header, sizeof (_header));
+
+ if (count != sizeof (_header))
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("reply header write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, sizeof (_header),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ if (msglen ())
+ {
+ const ssize_t count = conn->write (_buf, msglen ());
+
+ if (count == -1 || (size_t) count != msglen ())
+ {
+ assert (errno);
+ error_code (errno);
+ syscall_printf (("reply body write failure: "
+ "only %ld bytes sent of %ld, "
+ "error = %d(%lu)"),
+ count, msglen (),
+ errno, GetLastError ());
+ return;
+ }
+ }
+
+ // verbose: syscall_printf ("reply sent (%ld + %ld bytes)",
+ // sizeof (_header), msglen ());
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+bool
+check_cygserver_available ()
+{
+ assert (cygserver_running == CYGSERVER_UNKNOWN \
+ || cygserver_running == CYGSERVER_UNAVAIL);
+
+ cygserver_running = CYGSERVER_OK; // For make_request ().
+
+ client_request_get_version req;
+
+ /* This indicates that we failed to connect to cygserver at all but
+ * that's fine as cygwin doesn't need it to be running.
+ */
+ if (req.make_request () == -1)
+ return false;
+
+ /* We connected to the server but something went wrong after that
+ * (in sending the message, in cygserver itself, or in receiving the
+ * reply).
+ */
+ if (req.error_code ())
+ {
+ syscall_printf ("failure in cygserver version request: %d",
+ req.error_code ());
+ syscall_printf ("process will continue without cygserver support");
+ return false;
+ }
+
+ return req.check_version ();
+}
+
+void
+cygserver_init ()
+{
+ if (!allow_daemon)
+ {
+ syscall_printf ("cygserver use disabled in client");
+ cygserver_running = CYGSERVER_UNAVAIL;
+ return;
+ }
+
+ assert (cygserver_running == CYGSERVER_UNKNOWN \
+ || cygserver_running == CYGSERVER_OK \
+ || cygserver_running == CYGSERVER_UNAVAIL);
+
+ if (cygserver_running == CYGSERVER_OK)
+ return;
+
+ if (!check_cygserver_available ())
+ cygserver_running = CYGSERVER_UNAVAIL;
+}
diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc
new file mode 100755
index 00000000000..2cc7be19c92
--- /dev/null
+++ b/winsup/cygwin/cygserver_process.cc
@@ -0,0 +1,431 @@
+/* cygserver_process.cc
+
+ Copyright 2001, 2002 Red Hat Inc.
+
+ Written by Robert Collins <rbtcollins@hotmail.com>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "woutsup.h"
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "cygerrno.h"
+
+#include "cygwin/cygserver_process.h"
+
+/*****************************************************************************/
+
+#define elements(ARRAY) (sizeof (ARRAY) / sizeof (*ARRAY))
+
+/*****************************************************************************/
+
+process_cleanup::~process_cleanup ()
+{
+ safe_delete (_process);
+}
+
+void
+process_cleanup::process ()
+{
+ _process->cleanup ();
+}
+
+/*****************************************************************************/
+
+/* cleanup_routine */
+cleanup_routine::~cleanup_routine ()
+{
+}
+
+/*****************************************************************************/
+
+process::process (const pid_t cygpid, const DWORD winpid)
+ : _cygpid (cygpid),
+ _winpid (winpid),
+ _hProcess (NULL),
+ _cleaning_up (false),
+ _exit_status (STILL_ACTIVE),
+ _routines_head (NULL),
+ _next (NULL)
+{
+ _hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid);
+ if (!_hProcess)
+ {
+ system_printf ("unable to obtain handle for new cache process %d(%lu)",
+ _cygpid, _winpid);
+ _hProcess = INVALID_HANDLE_VALUE;
+ _exit_status = 0;
+ }
+ else
+ debug_printf ("got handle %p for new cache process %d(%lu)",
+ _hProcess, _cygpid, _winpid);
+ InitializeCriticalSection (&_access);
+}
+
+process::~process ()
+{
+ DeleteCriticalSection (&_access);
+ (void) CloseHandle (_hProcess);
+}
+
+/* No need to be thread-safe as this is only ever called by
+ * process_cache::remove_process (). If it has to be made thread-safe
+ * later on, it should not use the `access' critical section as that
+ * is held by the client request handlers for an arbitrary length of
+ * time, i.e. while they do whatever processing is required for a
+ * client request.
+ */
+DWORD
+process::check_exit_code ()
+{
+ if (_hProcess && _hProcess != INVALID_HANDLE_VALUE
+ && _exit_status == STILL_ACTIVE
+ && !GetExitCodeProcess (_hProcess, &_exit_status))
+ {
+ system_printf ("failed to retrieve exit code for %d(%lu), error = %lu",
+ _cygpid, _winpid, GetLastError ());
+ _hProcess = INVALID_HANDLE_VALUE;
+ }
+ return _exit_status;
+}
+
+bool
+process::add (cleanup_routine *const entry)
+{
+ assert (entry);
+
+ bool res = false;
+ EnterCriticalSection (&_access);
+
+ if (!_cleaning_up)
+ {
+ entry->_next = _routines_head;
+ _routines_head = entry;
+ res = true;
+ }
+
+ LeaveCriticalSection (&_access);
+ return res;
+}
+
+bool
+process::remove (const cleanup_routine *const entry)
+{
+ assert (entry);
+
+ bool res = false;
+ EnterCriticalSection (&_access);
+
+ if (!_cleaning_up)
+ {
+ cleanup_routine *previous = NULL;
+
+ for (cleanup_routine *ptr = _routines_head;
+ ptr;
+ previous = ptr, ptr = ptr->_next)
+ {
+ if (*ptr == *entry)
+ {
+ if (previous)
+ previous->_next = ptr->_next;
+ else
+ _routines_head = ptr->_next;
+
+ safe_delete (ptr);
+ res = true;
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection (&_access);
+ return res;
+}
+
+/* This is single threaded. It's called after the process is removed
+ * from the cache, but inserts may be attemped by worker threads that
+ * have a pointer to it.
+ */
+void
+process::cleanup ()
+{
+ EnterCriticalSection (&_access);
+ assert (!is_active ());
+ assert (!_cleaning_up);
+ InterlockedExchange (&_cleaning_up, true);
+ cleanup_routine *entry = _routines_head;
+ _routines_head = NULL;
+ LeaveCriticalSection (&_access);
+
+ while (entry)
+ {
+ cleanup_routine *const ptr = entry;
+ entry = entry->_next;
+ ptr->cleanup (this);
+ safe_delete (ptr);
+ }
+}
+
+/*****************************************************************************/
+
+void
+process_cache::submission_loop::request_loop ()
+{
+ assert (this);
+ assert (_cache);
+ assert (_interrupt_event);
+
+ while (_running)
+ _cache->wait_for_processes (_interrupt_event);
+}
+
+/*****************************************************************************/
+
+process_cache::process_cache (const unsigned int initial_workers)
+ : _queue (initial_workers),
+ _submitter (this, &_queue), // true == interruptible
+ _processes_count (0),
+ _processes_head (NULL),
+ _cache_add_trigger (NULL)
+{
+ /* there can only be one */
+ InitializeCriticalSection (&_cache_write_access);
+
+ _cache_add_trigger = CreateEvent (NULL, // SECURITY_ATTRIBUTES
+ FALSE, // Auto-reset
+ FALSE, // Initially non-signalled
+ NULL); // Anonymous
+
+ if (!_cache_add_trigger)
+ {
+ system_printf ("failed to create cache add trigger, error = %lu",
+ GetLastError ());
+ abort ();
+ }
+
+ _queue.add_submission_loop (&_submitter);
+}
+
+process_cache::~process_cache ()
+{
+ (void) CloseHandle (_cache_add_trigger);
+ DeleteCriticalSection (&_cache_write_access);
+}
+
+/* This returns the process object to the caller already locked, that
+ * is, with the object's `access' critical region entered. Thus the
+ * caller must unlock the object when it's finished with it (via
+ * process::release ()). It must then not try to access the object
+ * afterwards, except by going through this routine again, as it may
+ * have been deleted once it has been unlocked.
+ */
+class process *
+process_cache::process (const pid_t cygpid, const DWORD winpid)
+{
+ /* TODO: make this more granular, so a search doesn't involve the
+ * write lock.
+ */
+ EnterCriticalSection (&_cache_write_access);
+ class process *previous = NULL;
+ class process *entry = find (winpid, &previous);
+
+ if (!entry)
+ {
+ if (_processes_count + SPECIALS_COUNT >= MAXIMUM_WAIT_OBJECTS)
+ {
+ LeaveCriticalSection (&_cache_write_access);
+ system_printf (("process limit (%d processes) reached; "
+ "new connection refused for %d(%lu)"),
+ MAXIMUM_WAIT_OBJECTS - SPECIALS_COUNT,
+ cygpid, winpid);
+ set_errno (EAGAIN);
+ return NULL;
+ }
+
+ entry = safe_new (class process, cygpid, winpid);
+ if (!entry->is_active ())
+ {
+ LeaveCriticalSection (&_cache_write_access);
+ safe_delete (entry);
+ set_errno (ESRCH);
+ return NULL;
+ }
+
+ if (previous)
+ {
+ entry->_next = previous->_next;
+ previous->_next = entry;
+ }
+ else
+ {
+ entry->_next = _processes_head;
+ _processes_head = entry;
+ }
+
+ _processes_count += 1;
+ SetEvent (_cache_add_trigger);
+ }
+
+ EnterCriticalSection (&entry->_access); // To be released by the caller.
+ LeaveCriticalSection (&_cache_write_access);
+ assert (entry);
+ assert (entry->_winpid == winpid);
+ return entry;
+}
+
+void
+process_cache::wait_for_processes (const HANDLE interrupt_event)
+{
+ // Update `_wait_array' with handles of all current processes.
+ const size_t count = sync_wait_array (interrupt_event);
+
+ debug_printf ("waiting on %u objects in total (%u processes)",
+ count, _processes_count);
+
+ const DWORD rc = WaitForMultipleObjects (count, _wait_array,
+ FALSE, INFINITE);
+
+ if (rc == WAIT_FAILED)
+ {
+ system_printf ("could not wait on the process handles, error = %lu",
+ GetLastError ());
+ abort ();
+ }
+
+ const size_t start = rc - WAIT_OBJECT_0;
+
+ if (rc < WAIT_OBJECT_0 || start > count)
+ {
+ system_printf (("unexpected return code %rc "
+ "from WaitForMultipleObjects: "
+ "expected [%u .. %u)"),
+ rc, WAIT_OBJECT_0, WAIT_OBJECT_0 + count);
+ abort ();
+ }
+
+ // Tell all the processes, from the signalled point up, the bad news.
+ for (size_t index = start; index != count; index++)
+ if (_process_array[index])
+ check_and_remove_process (index);
+}
+
+/*
+ * process_cache::sync_wait_array ()
+ *
+ * Fill-in the wait array with the handles that the cache needs to wait on.
+ * These handles are:
+ * - the process_process_param's interrupt event
+ * - the process_cache's cache_add_trigger event
+ * - the handle for each live process in the cache.
+ *
+ * Return value: the number of live handles in the array.
+ */
+
+size_t
+process_cache::sync_wait_array (const HANDLE interrupt_event)
+{
+ assert (this);
+ assert (_cache_add_trigger && _cache_add_trigger != INVALID_HANDLE_VALUE);
+ assert (interrupt_event && interrupt_event != INVALID_HANDLE_VALUE);
+
+ EnterCriticalSection (&_cache_write_access);
+
+ assert (_processes_count + SPECIALS_COUNT <= elements (_wait_array));
+
+ size_t index = 0;
+
+ for (class process *ptr = _processes_head; ptr; ptr = ptr->_next)
+ {
+ assert (ptr->_hProcess && ptr->_hProcess != INVALID_HANDLE_VALUE);
+ assert (ptr->is_active ());
+
+ _wait_array[index] = ptr->handle ();
+ _process_array[index++] = ptr;
+
+ assert (index <= elements (_wait_array));
+ }
+
+ /* Sorry for shouting, but THESE MUST BE ADDED AT THE END! */
+ /* Well, not strictly `must', but it's more efficient if they are :-) */
+
+ _wait_array[index] = interrupt_event;
+ _process_array[index++] = NULL;
+
+ _wait_array[index] = _cache_add_trigger;
+ _process_array[index++] = NULL;
+
+ /* Phew, back to normal volume now. */
+
+ assert (index <= elements (_wait_array));
+
+ LeaveCriticalSection (&_cache_write_access);
+
+ return index;
+}
+
+void
+process_cache::check_and_remove_process (const size_t index)
+{
+ assert (this);
+ assert (index < elements (_wait_array) - SPECIALS_COUNT);
+
+ class process *const process = _process_array[index];
+
+ assert (process);
+ assert (process->handle () == _wait_array[index]);
+
+ if (process->check_exit_code () == STILL_ACTIVE)
+ return;
+
+ debug_printf ("process %d(%lu) has left the building ($? = %lu)",
+ process->_cygpid, process->_winpid, process->_exit_status);
+
+ /* Unlink the process object from the process list. */
+
+ EnterCriticalSection (&_cache_write_access);
+
+ class process *previous = NULL;
+
+ const class process *const tmp = find (process->_winpid, &previous);
+
+ assert (tmp == process);
+ assert (previous ? previous->_next == process : _processes_head == process);
+
+ if (previous)
+ previous->_next = process->_next;
+ else
+ _processes_head = process->_next;
+
+ _processes_count -= 1;
+ LeaveCriticalSection (&_cache_write_access);
+
+ /* Schedule any cleanup tasks for this process. */
+ _queue.add (safe_new (process_cleanup, process));
+}
+
+class process *
+process_cache::find (const DWORD winpid, class process **previous)
+{
+ if (previous)
+ *previous = NULL;
+
+ for (class process *ptr = _processes_head; ptr; ptr = ptr->_next)
+ if (ptr->_winpid == winpid)
+ return ptr;
+ else if (ptr->_winpid > winpid) // The list is sorted by winpid.
+ return NULL;
+ else if (previous)
+ *previous = ptr;
+
+ return NULL;
+}
+
+/*****************************************************************************/
diff --git a/winsup/cygwin/cygserver_transport_pipes.cc b/winsup/cygwin/cygserver_transport_pipes.cc
new file mode 100755
index 00000000000..6d80defd4ed
--- /dev/null
+++ b/winsup/cygwin/cygserver_transport_pipes.cc
@@ -0,0 +1,362 @@
+/* cygserver_transport_pipes.cc
+
+ Copyright 2001, 2002 Red Hat Inc.
+
+ Written by Robert Collins <rbtcollins@hotmail.com>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* to allow this to link into cygwin and the .dll, a little magic is needed. */
+#ifdef __OUTSIDE_CYGWIN__
+#include "woutsup.h"
+#else
+#include "winsup.h"
+#endif
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "cygerrno.h"
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver_transport_pipes.h"
+
+#ifndef __INSIDE_CYGWIN__
+#include "cygwin/cygserver.h"
+#endif
+
+enum
+ {
+ MAX_WAIT_NAMED_PIPE_RETRY = 64,
+ WAIT_NAMED_PIPE_TIMEOUT = 10 // milliseconds
+ };
+
+#ifndef __INSIDE_CYGWIN__
+
+static pthread_once_t pipe_instance_lock_once = PTHREAD_ONCE_INIT;
+static CRITICAL_SECTION pipe_instance_lock;
+static long pipe_instance = 0;
+
+static void
+initialise_pipe_instance_lock ()
+{
+ assert (pipe_instance == 0);
+ InitializeCriticalSection (&pipe_instance_lock);
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+#ifndef __INSIDE_CYGWIN__
+
+transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe)
+ : _pipe_name (""),
+ _hPipe (hPipe),
+ _is_accepted_endpoint (true),
+ _is_listening_endpoint (false)
+{
+ assert (_hPipe);
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+
+ init_security ();
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+transport_layer_pipes::transport_layer_pipes ()
+ : _pipe_name ("\\\\.\\pipe\\cygwin_lpc"),
+ _hPipe (NULL),
+ _is_accepted_endpoint (false),
+ _is_listening_endpoint (false)
+{
+ init_security ();
+}
+
+void
+transport_layer_pipes::init_security ()
+{
+ assert (wincap.has_security ());
+
+ /* FIXME: pthread_once or equivalent needed */
+
+ InitializeSecurityDescriptor (&_sd, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl (&_sd, TRUE, NULL, FALSE);
+
+ _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
+ _sec_all_nih.lpSecurityDescriptor = &_sd;
+ _sec_all_nih.bInheritHandle = FALSE;
+}
+
+transport_layer_pipes::~transport_layer_pipes ()
+{
+ close ();
+}
+
+#ifndef __INSIDE_CYGWIN__
+
+int
+transport_layer_pipes::listen ()
+{
+ assert (!_hPipe);
+ assert (!_is_accepted_endpoint);
+ assert (!_is_listening_endpoint);
+
+ _is_listening_endpoint = true;
+
+ /* no-op */
+ return 0;
+}
+
+class transport_layer_pipes *
+transport_layer_pipes::accept (bool *const recoverable)
+{
+ assert (!_hPipe);
+ assert (!_is_accepted_endpoint);
+ assert (_is_listening_endpoint);
+
+ pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock);
+
+ EnterCriticalSection (&pipe_instance_lock);
+
+ // Read: http://www.securityinternals.com/research/papers/namedpipe.php
+ // See also the Microsoft security bulletins MS00-053 and MS01-031.
+
+ // FIXME: Remove FILE_CREATE_PIPE_INSTANCE.
+
+ const bool first_instance = (pipe_instance == 0);
+
+ const HANDLE accept_pipe =
+ CreateNamedPipe (_pipe_name,
+ (PIPE_ACCESS_DUPLEX
+ | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0)),
+ (PIPE_TYPE_BYTE | PIPE_WAIT),
+ PIPE_UNLIMITED_INSTANCES,
+ 0, 0, 1000,
+ &_sec_all_nih);
+
+ const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE
+ && pipe_instance == 0
+ && GetLastError () == ERROR_ACCESS_DENIED);
+
+ if (accept_pipe != INVALID_HANDLE_VALUE)
+ InterlockedIncrement (&pipe_instance);
+
+ LeaveCriticalSection (&pipe_instance_lock);
+
+ if (duplicate)
+ {
+ *recoverable = false;
+ system_printf ("failed to create named pipe: "
+ "is the daemon already running?");
+ return NULL;
+ }
+
+ if (accept_pipe == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("error creating pipe (%lu).", GetLastError ());
+ *recoverable = true; // FIXME: case analysis?
+ return NULL;
+ }
+
+ assert (accept_pipe);
+
+ if (!ConnectNamedPipe (accept_pipe, NULL)
+ && GetLastError () != ERROR_PIPE_CONNECTED)
+ {
+ debug_printf ("error connecting to pipe (%lu)", GetLastError ());
+ (void) CloseHandle (accept_pipe);
+ *recoverable = true; // FIXME: case analysis?
+ return NULL;
+ }
+
+ return safe_new (transport_layer_pipes, accept_pipe);
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
+
+void
+transport_layer_pipes::close ()
+{
+ // verbose: debug_printf ("closing pipe %p", _hPipe);
+
+ if (_hPipe)
+ {
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+
+#ifndef __INSIDE_CYGWIN__
+
+ if (_is_accepted_endpoint)
+ {
+ (void) FlushFileBuffers (_hPipe); // Blocks until client reads.
+ (void) DisconnectNamedPipe (_hPipe);
+ EnterCriticalSection (&pipe_instance_lock);
+ (void) CloseHandle (_hPipe);
+ assert (pipe_instance > 0);
+ InterlockedDecrement (&pipe_instance);
+ LeaveCriticalSection (&pipe_instance_lock);
+ }
+ else
+ (void) CloseHandle (_hPipe);
+
+#else /* __INSIDE_CYGWIN__ */
+
+ assert (!_is_accepted_endpoint);
+ (void) ForceCloseHandle (_hPipe);
+
+#endif /* __INSIDE_CYGWIN__ */
+
+ _hPipe = NULL;
+ }
+}
+
+ssize_t
+transport_layer_pipes::read (void *const buf, const size_t len)
+{
+ // verbose: debug_printf ("reading from pipe %p", _hPipe);
+
+ assert (_hPipe);
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+ assert (!_is_listening_endpoint);
+
+ DWORD count;
+ if (!ReadFile (_hPipe, buf, len, &count, NULL))
+ {
+ debug_printf ("error reading from pipe (%lu)", GetLastError ());
+ set_errno (EINVAL); // FIXME?
+ return -1;
+ }
+
+ return count;
+}
+
+ssize_t
+transport_layer_pipes::write (void *const buf, const size_t len)
+{
+ // verbose: debug_printf ("writing to pipe %p", _hPipe);
+
+ assert (_hPipe);
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+ assert (!_is_listening_endpoint);
+
+ DWORD count;
+ if (!WriteFile (_hPipe, buf, len, &count, NULL))
+ {
+ debug_printf ("error writing to pipe, error = %lu", GetLastError ());
+ set_errno (EINVAL); // FIXME?
+ return -1;
+ }
+
+ return count;
+}
+
+/*
+ * This routine holds a static variable, assume_cygserver, that is set
+ * if the transport has good reason to think that cygserver is
+ * running, i.e. if if successfully connected to it with the previous
+ * attempt. If this is set, the code tries a lot harder to get a
+ * connection, making the assumption that any failures are just
+ * congestion and overloading problems.
+ */
+
+int
+transport_layer_pipes::connect ()
+{
+ assert (!_hPipe);
+ assert (!_is_accepted_endpoint);
+ assert (!_is_listening_endpoint);
+
+ static bool assume_cygserver = false;
+
+ BOOL rc = TRUE;
+ int retries = 0;
+
+ while (rc)
+ {
+ _hPipe = CreateFile (_pipe_name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &_sec_all_nih,
+ OPEN_EXISTING,
+ SECURITY_IMPERSONATION,
+ NULL);
+
+ if (_hPipe != INVALID_HANDLE_VALUE)
+ {
+ assert (_hPipe);
+#ifdef __INSIDE_CYGWIN__
+ ProtectHandle (_hPipe);
+#endif
+ assume_cygserver = true;
+ return 0;
+ }
+
+ _hPipe = NULL;
+
+ if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY)
+ {
+ debug_printf ("Error opening the pipe (%lu)", GetLastError ());
+ return -1;
+ }
+
+ /* Note: `If no instances of the specified named pipe exist, the
+ * WaitNamedPipe function returns immediately, regardless of the
+ * time-out value.' Thus the explicit Sleep if the call fails
+ * with ERROR_FILE_NOT_FOUND.
+ */
+ while (retries != MAX_WAIT_NAMED_PIPE_RETRY
+ && !(rc = WaitNamedPipe (_pipe_name, WAIT_NAMED_PIPE_TIMEOUT)))
+ {
+ if (GetLastError () == ERROR_FILE_NOT_FOUND)
+ Sleep (0); // Give the server a chance.
+
+ retries += 1;
+ }
+ }
+
+ assert (retries == MAX_WAIT_NAMED_PIPE_RETRY);
+
+ system_printf ("lost connection to cygserver, error = %lu",
+ GetLastError ());
+
+ assume_cygserver = false;
+
+ return -1;
+}
+
+#ifndef __INSIDE_CYGWIN__
+
+void
+transport_layer_pipes::impersonate_client ()
+{
+ assert (_hPipe);
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+ assert (_is_accepted_endpoint);
+
+ // verbose: debug_printf ("impersonating pipe %p", _hPipe);
+ if (_hPipe)
+ {
+ assert (_hPipe != INVALID_HANDLE_VALUE);
+
+ if (!ImpersonateNamedPipeClient (_hPipe))
+ debug_printf ("Failed to Impersonate the client, (%lu)",
+ GetLastError ());
+ }
+ // verbose: debug_printf ("I am who you are");
+}
+
+void
+transport_layer_pipes::revert_to_self ()
+{
+ assert (_is_accepted_endpoint);
+
+ RevertToSelf ();
+ // verbose: debug_printf ("I am who I yam");
+}
+
+#endif /* !__INSIDE_CYGWIN__ */
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index 2d45f2917f5..c4c871cf754 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -9,7 +9,6 @@ details. */
#include "winsup.h"
#include <windows.h>
#include <stdlib.h>
-#include <errno.h>
#include "exceptions.h"
#include "security.h"
#include "cygthread.h"
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 5dda7eadcb4..107dc00f3e2 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -26,6 +26,7 @@ __eprintf
__errno
__fpclassifyd
__fpclassifyf
+__getreent
__infinity
__main
__signbitd
@@ -1299,6 +1300,7 @@ sysconf
_sysconf = sysconf
syslog
_syslog = syslog
+vsyslog
system
_system = system
tan
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 09fbf58ee0f..04449b2f6ff 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -17,7 +17,6 @@ details. */
#include <limits.h>
#include <wingdi.h>
#include <winuser.h>
-#include <errno.h>
#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
@@ -54,9 +53,9 @@ per_thread NO_COPY *threadstuff[] = {&waitq_storage,
&signal_dispatch_storage,
NULL};
-BOOL display_title;
-BOOL strip_title_path;
-BOOL allow_glob = TRUE;
+bool display_title;
+bool strip_title_path;
+bool allow_glob = TRUE;
codepage_type current_codepage = ansi_cp;
int cygwin_finished_initializing;
diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc
index e85717bcac9..2f0471a1a6d 100644
--- a/winsup/cygwin/debug.cc
+++ b/winsup/cygwin/debug.cc
@@ -15,7 +15,6 @@ details. */
#include "security.h"
#include "cygerrno.h"
#ifdef DEBUGGING
-#include <errno.h>
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
@@ -222,6 +221,6 @@ 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;
+ return errno = val;
}
#endif /*DEBUGGING*/
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 4ed076e2f35..88a1689e6fd 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -12,7 +12,6 @@ details. */
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
-#include <errno.h>
#define _COMPILING_NEWLIB
#include <dirent.h>
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 4e5491947d2..38af9aa4cea 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -8,7 +8,6 @@ details. */
#include "winsup.h"
#include <stdlib.h>
-#include <errno.h>
#include "cygerrno.h"
#include "perprocess.h"
#include "dll_init.h"
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 40c37caacea..6ff8121c72a 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -11,7 +11,6 @@ details. */
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
-#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
@@ -676,8 +675,7 @@ dtable::vfork_child_dup ()
int res = 1;
/* Remove impersonation */
- if (cygheap->user.issetuid ())
- RevertToSelf ();
+ cygheap->user.deimpersonate ();
for (size_t i = 0; i < size; i++)
if (not_open (i))
@@ -696,8 +694,7 @@ dtable::vfork_child_dup ()
out:
/* Restore impersonation */
- if (cygheap->user.issetuid ())
- ImpersonateLoggedOnUser (cygheap->user.token);
+ cygheap->user.reimpersonate ();
ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
return 1;
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 6a112518ee7..6c75f987dac 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -1,14 +1,13 @@
/* environ.cc: Cygwin-adopted functions from newlib to manipulate
process's environment.
- Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+ Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
@@ -27,17 +26,17 @@ details. */
#include "environ.h"
#include "child_info.h"
-extern BOOL allow_daemon;
-extern BOOL allow_glob;
+extern bool allow_glob;
extern bool ignore_case_with_glob;
-extern BOOL allow_ntea;
-extern BOOL allow_smbntsec;
-extern BOOL allow_winsymlinks;
-extern BOOL strip_title_path;
+extern bool allow_ntea;
+extern bool allow_smbntsec;
+extern bool allow_winsymlinks;
+extern bool strip_title_path;
extern int pcheck_case;
extern int subauth_id;
-BOOL reset_com = FALSE;
-static BOOL envcache = TRUE;
+bool reset_com = false;
+bool allow_daemon = false;
+static bool envcache = true;
static char **lastenviron;
@@ -366,7 +365,7 @@ ucenv (char *p, char *eq)
/* Parse CYGWIN options */
-static NO_COPY BOOL export_settings = false;
+static NO_COPY bool export_settings = false;
enum settings
{
@@ -385,18 +384,18 @@ glob_init (const char *buf)
{
if (!buf || !*buf)
{
- allow_glob = FALSE;
- ignore_case_with_glob = FALSE;
+ allow_glob = false;
+ ignore_case_with_glob = false;
}
else if (strncasematch (buf, "ignorecase", 10))
{
- allow_glob = TRUE;
- ignore_case_with_glob = TRUE;
+ allow_glob = true;
+ ignore_case_with_glob = true;
}
else
{
- allow_glob = TRUE;
- ignore_case_with_glob = FALSE;
+ allow_glob = true;
+ ignore_case_with_glob = false;
}
}
@@ -489,7 +488,7 @@ static struct parse_thing
const char *name;
union parse_setting
{
- BOOL *b;
+ bool *b;
DWORD *x;
int *i;
void (*func)(const char *);
@@ -507,21 +506,21 @@ static struct parse_thing
{"binmode", {x: &binmode}, justset, NULL, {{O_TEXT}, {O_BINARY}}},
{"check_case", {func: &check_case_init}, isfunc, NULL, {{0}, {0}}},
{"codepage", {func: &codepage_init}, isfunc, NULL, {{0}, {0}}},
- {"daemon", {&allow_daemon}, justset, NULL, {{FALSE}, {TRUE}}},
- {"envcache", {&envcache}, justset, NULL, {{TRUE}, {FALSE}}},
+ {"daemon", {&allow_daemon}, justset, NULL, {{false}, {true}}},
+ {"envcache", {&envcache}, justset, NULL, {{true}, {false}}},
{"error_start", {func: &error_start_init}, isfunc, NULL, {{0}, {0}}},
- {"export", {&export_settings}, justset, NULL, {{FALSE}, {TRUE}}},
+ {"export", {&export_settings}, justset, NULL, {{false}, {true}}},
{"forkchunk", {func: set_chunksize}, isfunc, NULL, {{0}, {0}}},
{"glob", {func: &glob_init}, isfunc, NULL, {{0}, {s: "normal"}}},
- {"ntea", {&allow_ntea}, justset, NULL, {{FALSE}, {TRUE}}},
- {"ntsec", {&allow_ntsec}, justset, NULL, {{FALSE}, {TRUE}}},
- {"smbntsec", {&allow_smbntsec}, justset, NULL, {{FALSE}, {TRUE}}},
- {"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
- {"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
+ {"ntea", {&allow_ntea}, justset, NULL, {{false}, {true}}},
+ {"ntsec", {&allow_ntsec}, justset, NULL, {{false}, {true}}},
+ {"smbntsec", {&allow_smbntsec}, justset, NULL, {{false}, {true}}},
+ {"reset_com", {&reset_com}, justset, NULL, {{false}, {true}}},
+ {"strip_title", {&strip_title_path}, justset, NULL, {{false}, {true}}},
{"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}},
- {"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
+ {"title", {&display_title}, justset, NULL, {{false}, {true}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
- {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
+ {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
{NULL, {0}, justset, 0, {{0}, {0}}}
};
@@ -677,7 +676,7 @@ environ_init (char **envp, int envc)
/* Set ntsec explicit as default, if NT is running */
if (wincap.has_security ())
- allow_ntsec = TRUE;
+ allow_ntsec = true;
if (!envp)
envp_passed_in = 0;
diff --git a/winsup/cygwin/errno.cc b/winsup/cygwin/errno.cc
index a922d5280dd..127eff9d353 100644
--- a/winsup/cygwin/errno.cc
+++ b/winsup/cygwin/errno.cc
@@ -10,14 +10,14 @@ details. */
#define _sys_nerr FOO_sys_nerr
#define sys_nerr FOOsys_nerr
+#define _sys_errlist FOO_sys_errlist
#include "winsup.h"
-#define _REENT_ONLY
#include <stdio.h>
-#include <errno.h>
#include "cygerrno.h"
#include "thread.h"
#undef _sys_nerr
#undef sys_nerr
+#undef _sys_errlist
/* Table to map Windows error codes to Errno values. */
/* FIXME: Doing things this way is a little slow. It's trivial to change
@@ -25,13 +25,12 @@ details. */
#define X(w, e) {ERROR_##w, #w, e}
-static const NO_COPY struct
- {
- DWORD w; /* windows version of error */
- const char *s; /* text of windows version */
- int e; /* errno version of error */
- }
-errmap[] =
+static NO_COPY struct
+{
+ DWORD w; /* windows version of error */
+ const char *s; /* text of windows version */
+ int e; /* errno version of error */
+} errmap[] =
{
/* FIXME: Some of these choices are arbitrary! */
X (INVALID_FUNCTION, EBADRQC),
@@ -116,42 +115,8 @@ errmap[] =
{ 0, NULL, 0}
};
-int __stdcall
-geterrno_from_win_error (DWORD code, int deferrno)
-{
- for (int i = 0; errmap[i].w != 0; ++i)
- if (code == errmap[i].w)
- {
- syscall_printf ("windows error %u == errno %d", code, errmap[i].e);
- return errmap[i].e;
- }
-
- syscall_printf ("unknown windows error %u, setting errno to %d", code,
- deferrno);
- return deferrno; /* FIXME: what's so special about EACCESS? */
-}
-
-/* seterrno_from_win_error: Given a Windows error code, set errno
- as appropriate. */
-void __stdcall
-seterrno_from_win_error (const char *file, int line, DWORD code)
-{
- syscall_printf ("%s:%d windows error %d", file, line, code);
- set_errno (geterrno_from_win_error (code, EACCES));
- return;
-}
-
-/* seterrno: Set `errno' based on GetLastError (). */
-void __stdcall
-seterrno (const char *file, int line)
-{
- seterrno_from_win_error (file, line, GetLastError ());
-}
-
-extern char *_user_strerror _PARAMS ((int));
-
extern "C" {
-const NO_COPY char __declspec(dllexport) * const _sys_errlist[]=
+const char __declspec(dllexport) * _sys_errlist[] NO_COPY_INIT =
{
/* NOERROR 0 */ "No error",
/* EPERM 1 */ "Operation not permitted",
@@ -295,9 +260,43 @@ const NO_COPY char __declspec(dllexport) * const _sys_errlist[]=
/* EOVERFLOW 139 */ "Value too large for defined data type"
};
-extern const int NO_COPY __declspec(dllexport) _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]);
+int NO_COPY_INIT _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]);
};
+int __stdcall
+geterrno_from_win_error (DWORD code, int deferrno)
+{
+ for (int i = 0; errmap[i].w != 0; ++i)
+ if (code == errmap[i].w)
+ {
+ syscall_printf ("windows error %u == errno %d", code, errmap[i].e);
+ return errmap[i].e;
+ }
+
+ syscall_printf ("unknown windows error %u, setting errno to %d", code,
+ deferrno);
+ return deferrno; /* FIXME: what's so special about EACCESS? */
+}
+
+/* seterrno_from_win_error: Given a Windows error code, set errno
+ as appropriate. */
+void __stdcall
+seterrno_from_win_error (const char *file, int line, DWORD code)
+{
+ syscall_printf ("%s:%d windows error %d", file, line, code);
+ set_errno (geterrno_from_win_error (code, EACCES));
+ return;
+}
+
+/* seterrno: Set `errno' based on GetLastError (). */
+void __stdcall
+seterrno (const char *file, int line)
+{
+ seterrno_from_win_error (file, line, GetLastError ());
+}
+
+extern char *_user_strerror _PARAMS ((int));
+
/* FIXME: Why is strerror() a long switch and not just:
return sys_errlist[errnum];
(or moral equivalent).
@@ -681,7 +680,11 @@ strerror (int errnum)
error = "Value too large for defined data type";
break;
default:
+#ifdef _MT_SAFE
char *buf= _reent_winsup ()->_strerror_buf;
+#else
+ static NO_COPY char buf[20];
+#endif
__small_sprintf (buf, "error %d", errnum);
error = buf;
break;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 4a38a8e4c3a..3c8bf39c99f 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -10,7 +10,6 @@ details. */
#include "winsup.h"
#include <imagehlp.h>
-#include <errno.h>
#include <stdlib.h>
#include "exceptions.h"
@@ -154,7 +153,7 @@ error_start_init (const char *buf)
for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))
*p = '/';
- __small_sprintf (debugger_command, "%s %s", buf, pgm);
+ __small_sprintf (debugger_command, "%s \"%s\"", buf, pgm);
}
static void
@@ -932,7 +931,13 @@ ctrl_c_handler (DWORD type)
is shut down or console window is closed. */
if (type == CTRL_SHUTDOWN_EVENT)
{
+#if 0
+ /* Don't send a signal. Only NT service applications and their child
+ processes will receive this event and the services typically already
+ handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
+ control message. */
sig_send (NULL, SIGTERM);
+#endif
return FALSE;
}
if (type == CTRL_CLOSE_EVENT)
diff --git a/winsup/cygwin/exec.cc b/winsup/cygwin/exec.cc
index af345be99fe..d7c2ee1c271 100644
--- a/winsup/cygwin/exec.cc
+++ b/winsup/cygwin/exec.cc
@@ -12,7 +12,6 @@ details. */
#include "winsup.h"
#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <process.h>
#include "perprocess.h"
#include "security.h"
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
index c1a829adcc3..49e430518b6 100644
--- a/winsup/cygwin/external.cc
+++ b/winsup/cygwin/external.cc
@@ -11,7 +11,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include "security.h"
#include "sigproc.h"
#include "pinfo.h"
diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc
index f99dd2d2b7c..b1afb57d38e 100644
--- a/winsup/cygwin/fcntl.cc
+++ b/winsup/cygwin/fcntl.cc
@@ -10,7 +10,6 @@ details. */
#include "winsup.h"
#include <stdarg.h>
-#include <errno.h>
#include <unistd.h>
#include "security.h"
#include "path.h"
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index ab5e4b8f62e..253fca6fc47 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
@@ -600,7 +599,7 @@ fhandler_base::write (const void *ptr, size_t len)
if (current_position > actual_length)
{
if ((get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
- && current_position >= actual_length + (64 * 1024))
+ && current_position >= actual_length + (128 * 1024))
{
/* If the file systemn supports sparse files and the application
is writing after a long seek beyond EOF, convert the file to
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index d3b0f5dec61..2ee82fcf95a 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -20,8 +20,7 @@ enum
FH_WBINSET = 0x00010000, /* binary write mode has been explicitly set */
FH_APPEND = 0x00020000, /* always append */
FH_ASYNC = 0x00040000, /* async I/O */
- FH_SIGCLOSE = 0x00080000, /* signal handler should close fd on interrupt */
-
+ FH_ENC = 0x00080000, /* native path is encoded */
FH_SYMLINK = 0x00100000, /* is a symlink */
FH_EXECABL = 0x00200000, /* file looked like it would run:
* ends in .exe or .bat or begins with #! */
@@ -200,6 +199,9 @@ class fhandler_base
bool get_need_fork_fixup () { return FHISSETF (FFIXUP); }
void set_need_fork_fixup () { FHSETF (FFIXUP); }
+ bool get_encoded () { return FHISSETF (ENC);}
+ void set_encoded () { FHSETF (ENC);}
+
virtual void set_close_on_exec (int val);
virtual void fixup_before_fork_exec (DWORD) {}
@@ -387,6 +389,7 @@ class fhandler_socket: public fhandler_base
bool is_connect_pending () const {return had_connect_or_listen == CONNECT_PENDING;}
bool is_connected () const {return had_connect_or_listen == CONNECTED;}
void set_connect_state (int newstate) { had_connect_or_listen = newstate; }
+ int get_connect_state () const { return had_connect_or_listen; }
int bind (const struct sockaddr *name, int namelen);
int connect (const struct sockaddr *name, int namelen);
diff --git a/winsup/cygwin/fhandler_clipboard.cc b/winsup/cygwin/fhandler_clipboard.cc
index 3f72703b32c..3f24094024e 100644
--- a/winsup/cygwin/fhandler_clipboard.cc
+++ b/winsup/cygwin/fhandler_clipboard.cc
@@ -13,7 +13,6 @@ details. */
#include "winsup.h"
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include <unistd.h>
#include <windows.h>
#include <wingdi.h>
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index a76cfb0cdc5..9409cddd4ee 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -12,7 +12,6 @@ details. */
#include <sys/termios.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include <unistd.h>
#include <wingdi.h>
#include <winuser.h>
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 7e6d033757f..d97b5dc63eb 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
@@ -627,6 +626,8 @@ fhandler_disk_file::opendir ()
res = dir;
}
+ if (real_name.isencoded ())
+ set_encoded ();
}
syscall_printf ("%p = opendir (%s)", res, get_name ());
@@ -653,9 +654,7 @@ fhandler_disk_file::readdir (DIR *dir)
}
}
else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
- {
- return res;
- }
+ return res;
else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
{
DWORD lasterr = GetLastError ();
@@ -670,7 +669,10 @@ fhandler_disk_file::readdir (DIR *dir)
}
/* We get here if `buf' contains valid data. */
- strcpy (dir->__d_dirent->d_name, buf.cFileName);
+ if (get_encoded ())
+ (void) fnunmunge (dir->__d_dirent->d_name, buf.cFileName);
+ else
+ strcpy (dir->__d_dirent->d_name, buf.cFileName);
/* Check for Windows shortcut. If it's a Cygwin or U/WIN
symlink, drop the .lnk suffix. */
diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc
index f961ec99bdf..3c577a89e34 100644
--- a/winsup/cygwin/fhandler_dsp.cc
+++ b/winsup/cygwin/fhandler_dsp.cc
@@ -12,7 +12,6 @@ details. */
#include "winsup.h"
#include <stdio.h>
-#include <errno.h>
#include <windows.h>
#include <sys/soundcard.h>
#include <mmsystem.h>
diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc
index dbf603c9f2d..1b8cccf7e9a 100644
--- a/winsup/cygwin/fhandler_floppy.cc
+++ b/winsup/cygwin/fhandler_floppy.cc
@@ -11,7 +11,6 @@ details. */
#include "winsup.h"
#include <sys/termios.h>
-#include <errno.h>
#include <unistd.h>
#include <winioctl.h>
#include <asm/socket.h>
diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc
index 243986e4be7..883412f2f7f 100644
--- a/winsup/cygwin/fhandler_mem.cc
+++ b/winsup/cygwin/fhandler_mem.cc
@@ -9,7 +9,6 @@
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <ntdef.h>
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 2ab9fad26bc..081fcf53771 100644
--- a/winsup/cygwin/fhandler_proc.cc
+++ b/winsup/cygwin/fhandler_proc.cc
@@ -11,7 +11,6 @@ details. */
#define _WIN32_WINNT 0x0501
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index 1c46f6f49db..ca48352cd5c 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
diff --git a/winsup/cygwin/fhandler_random.cc b/winsup/cygwin/fhandler_random.cc
index 257228a9513..55953348f6e 100644
--- a/winsup/cygwin/fhandler_random.cc
+++ b/winsup/cygwin/fhandler_random.cc
@@ -11,7 +11,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <limits.h>
#include "cygerrno.h"
#include "security.h"
diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc
index 302af884717..9266290a668 100644
--- a/winsup/cygwin/fhandler_raw.cc
+++ b/winsup/cygwin/fhandler_raw.cc
@@ -10,7 +10,6 @@
#include "winsup.h"
#include <sys/termios.h>
-#include <errno.h>
#include <unistd.h>
#include <cygwin/rdevio.h>
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index ea193b836e0..91370147670 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -11,7 +11,6 @@ details. */
/* FIXME: Access permissions are ignored at the moment. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
index eec4735e1ec..45c3cc1bff3 100644
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include "cygerrno.h"
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 6a163b6644c..3dc16902598 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -13,7 +13,6 @@
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
-#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
@@ -328,6 +327,7 @@ fhandler_socket::dup (fhandler_base *child)
if (get_addr_family () == AF_LOCAL)
fhs->set_sun_path (get_sun_path ());
fhs->set_socket_type (get_socket_type ());
+ fhs->set_connect_state (get_connect_state ());
if (winsock2_active)
{
@@ -338,12 +338,10 @@ fhandler_socket::dup (fhandler_base *child)
If WSADuplicateSocket() still fails for some reason, we fall back
to DuplicateHandle(). */
WSASetLastError (0);
- if (cygheap->user.issetuid ())
- RevertToSelf ();
+ cygheap->user.deimpersonate ();
fhs->set_io_handle (get_io_handle ());
fhs->fixup_before_fork_exec (GetCurrentProcessId ());
- if (cygheap->user.issetuid ())
- ImpersonateLoggedOnUser (cygheap->user.token);
+ cygheap->user.reimpersonate ();
if (!WSAGetLastError ())
{
fhs->fixup_after_fork (hMainProc);
@@ -492,6 +490,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
BOOL in_progress = FALSE;
sockaddr_in sin;
int secret [4];
+ DWORD err;
if (!get_inet_addr (name, namelen, &sin, &namelen, secret))
return -1;
@@ -504,12 +503,12 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
when called on a non-blocking socket. */
if (is_nonblocking () || is_connect_pending ())
{
- DWORD err = WSAGetLastError ();
+ err = WSAGetLastError ();
if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
- {
- WSASetLastError (WSAEINPROGRESS);
- in_progress = TRUE;
- }
+ in_progress = TRUE;
+
+ if (err == WSAEWOULDBLOCK)
+ WSASetLastError (WSAEINPROGRESS);
else if (err == WSAEINVAL)
WSASetLastError (WSAEISCONN);
}
@@ -546,7 +545,8 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
}
}
- if (WSAGetLastError () == WSAEINPROGRESS)
+ err = WSAGetLastError ();
+ if (err == WSAEINPROGRESS || err == WSAEALREADY)
set_connect_state (CONNECT_PENDING);
else
set_connect_state (CONNECTED);
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index 4cbf868c2c9..e3efcd1f9f5 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -11,7 +11,6 @@ details. */
#include "winsup.h"
#include <sys/termios.h>
-#include <errno.h>
#include <unistd.h>
#include <sys/mtio.h>
#include "cygerrno.h"
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index cd4fafff0e7..89d883c681c 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -12,7 +12,6 @@ details. */
#include <sys/termios.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
#include <ctype.h>
#include "cygerrno.h"
#include "security.h"
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 322b80a256b..3c88fcc97b5 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -14,7 +14,6 @@ details. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include "cygerrno.h"
@@ -508,9 +507,11 @@ fhandler_tty_slave::open (int flags, mode_t)
HANDLE from_master_local, to_master_local;
- if (!wincap.has_security () ||
- cygserver_running == CYGSERVER_UNAVAIL ||
- !cygserver_attach_tty (&from_master_local, &to_master_local))
+#ifdef USE_CYGSERVER
+ if (!wincap.has_security ()
+ || cygserver_running == CYGSERVER_UNAVAIL
+ || !cygserver_attach_tty (&from_master_local, &to_master_local))
+#endif
{
termios_printf ("cannot dup handles via server. using old method.");
@@ -583,7 +584,8 @@ fhandler_tty_slave::close ()
{
if (!output_done_event)
{
- fhandler_console::open_fhs--;
+ if (!--fhandler_console::open_fhs && myself->ctty == -1)
+ FreeConsole ();
termios_printf ("decremented open_fhs %d", fhandler_console::open_fhs);
}
return fhandler_tty_common::close ();
@@ -593,6 +595,9 @@ int
fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
LPHANDLE to_master_ptr)
{
+#ifndef USE_CYGSERVER
+ return 0;
+#else
if (!from_master_ptr || !to_master_ptr)
return 0;
@@ -605,7 +610,9 @@ fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
*from_master_ptr = req.from_master ();
*to_master_ptr = req.to_master ();
+
return 1;
+#endif
}
void
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index baf8e79989a..aedaf018726 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
diff --git a/winsup/cygwin/fhandler_windows.cc b/winsup/cygwin/fhandler_windows.cc
index 81972bf132b..4affbc6faf4 100644
--- a/winsup/cygwin/fhandler_windows.cc
+++ b/winsup/cygwin/fhandler_windows.cc
@@ -12,7 +12,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <wingdi.h>
#include <winuser.h>
#include "cygerrno.h"
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index ac1708a6ea6..859bb64e342 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -13,7 +13,6 @@ details. */
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <errno.h>
#include "security.h"
#include "path.h"
#include "fhandler.h"
@@ -237,14 +236,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
/* Restore the inheritance state as in parent
Don't call setuid here! The flags are already set. */
- if (cygheap->user.impersonated)
- {
- debug_printf ("Impersonation of child, token: %d", cygheap->user.token);
- if (cygheap->user.token == INVALID_HANDLE_VALUE)
- RevertToSelf (); // probably not needed
- else if (!ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonate for forked child failed: %E");
- }
+ cygheap->user.reimpersonate ();
sync_with_parent ("after longjmp.", TRUE);
sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
@@ -306,8 +298,10 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
(void) ForceCloseHandle1 (fork_info->subproc_ready, subproc_ready);
(void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
+#ifdef USE_CYGSERVER
if (fixup_shms_after_fork ())
api_fatal ("recreate_shm areas after fork failed");
+#endif
pinfo_fixup_after_fork ();
signal_fixup_after_fork ();
@@ -437,8 +431,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
si.cbReserved2 = sizeof (ch);
/* Remove impersonation */
- if (cygheap->user.issetuid ())
- RevertToSelf ();
+ cygheap->user.deimpersonate ();
ch.parent = hParent;
#ifdef DEBUGGING
@@ -486,8 +479,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
ForceCloseHandle (subproc_ready);
ForceCloseHandle (forker_finished);
/* Restore impersonation */
- if (cygheap->user.issetuid ())
- ImpersonateLoggedOnUser (cygheap->user.token);
+ cygheap->user.reimpersonate ();
cygheap_setup_for_child_cleanup (newheap, &ch, 0);
return -1;
}
@@ -514,8 +506,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
strcpy (forked->progname, myself->progname);
/* Restore impersonation */
- if (cygheap->user.issetuid ())
- ImpersonateLoggedOnUser (cygheap->user.token);
+ cygheap->user.reimpersonate ();
ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index f4df7580d73..6e34a3a19bf 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -16,7 +16,6 @@ details. */
#include <wininet.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include "pinfo.h"
#include "security.h"
#include "path.h"
@@ -262,7 +261,7 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
{
/* If impersonated, use impersonation token. */
if (cygheap->user.issetuid ())
- hToken = cygheap->user.token;
+ hToken = cygheap->user.token ();
else if (!OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken))
hToken = NULL;
}
@@ -296,7 +295,7 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
++cnt;
if (gidsetsize && cnt > gidsetsize)
{
- if (hToken != cygheap->user.token)
+ if (!cygheap->user.issetuid ())
CloseHandle (hToken);
goto error;
}
@@ -306,7 +305,7 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
}
else
debug_printf ("%d = GetTokenInformation(NULL) %E", size);
- if (hToken != cygheap->user.token)
+ if (!cygheap->user.issetuid ())
CloseHandle (hToken);
return cnt;
}
diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc
index ae8a9d0a7b2..d6f0452e2c6 100644
--- a/winsup/cygwin/heap.cc
+++ b/winsup/cygwin/heap.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include "cygerrno.h"
#include "sigproc.h"
#include "pinfo.h"
diff --git a/winsup/cygwin/include/cygwin/config.h b/winsup/cygwin/include/cygwin/config.h
index 77815a071ff..e3e09f051ae 100644
--- a/winsup/cygwin/include/cygwin/config.h
+++ b/winsup/cygwin/include/cygwin/config.h
@@ -19,6 +19,7 @@ extern "C" {
#endif
#define _CYGWIN_CONFIG_H
+#define __DYNAMIC_REENT__
#define __FILENAME_MAX__ (260 - 1 /* NUL */)
#define _READ_WRITE_RETURN_TYPE _ssize_t
#define __LARGE64_FILES 1
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index cd49fa58952..13657a078f3 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -205,12 +205,15 @@ details. */
underscore. No problems with backward compatibility since no
official release has been made so far. This change removes
exported symbols like fopen64, which might confuse configure.
+ 86: Export ftok
+ 87: Export vsyslog
+ 88: Export _getreent
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 85
+#define CYGWIN_VERSION_API_MINOR 88
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/sys/syslog.h b/winsup/cygwin/include/sys/syslog.h
new file mode 100644
index 00000000000..a37b042d722
--- /dev/null
+++ b/winsup/cygwin/include/sys/syslog.h
@@ -0,0 +1,86 @@
+/* sys/syslog.h
+
+ Copyright 1996, 1998, 2001 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 _SYS_LOG_H
+#define _SYS_LOG_H
+
+#include <sys/cdefs.h>
+#include <stdarg.h>
+
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+#define LOG_PRIMASK 0x07
+
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+
+#define LOG_KERN (0<<3)
+#define LOG_USER (1<<3)
+#define LOG_MAIL (2<<3)
+#define LOG_DAEMON (3<<3)
+#define LOG_AUTH (4<<3)
+#define LOG_SYSLOG (5<<3)
+#define LOG_LPR (6<<3)
+#define LOG_NEWS (7<<3)
+#define LOG_UUCP (8<<3)
+#define LOG_CRON (9<<3)
+#define LOG_AUTHPRIV (10<<3)
+#define LOG_FTP (11<<3)
+
+/* Codes through 15 are reserved for system use */
+#define LOG_LOCAL0 (16<<3)
+#define LOG_LOCAL1 (17<<3)
+#define LOG_LOCAL2 (18<<3)
+#define LOG_LOCAL3 (19<<3)
+#define LOG_LOCAL4 (20<<3)
+#define LOG_LOCAL5 (21<<3)
+#define LOG_LOCAL6 (22<<3)
+#define LOG_LOCAL7 (23<<3)
+
+#define LOG_NFACILITIES 24
+#define LOG_FACMASK 0x03f8
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+
+#define LOG_MASK(pri) (1 << (pri))
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1)
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
+#define LOG_PERROR 0x20 /* log to stderr as well */
+
+__BEGIN_DECLS
+
+
+void closelog (void);
+void openlog (const char *, int, int);
+int setlogmask (int);
+void syslog (int, const char *, ...);
+void vsyslog (int, const char *, va_list ap);
+
+__END_DECLS
+
+
+#endif /* _SYS_LOG_H */
diff --git a/winsup/cygwin/ioctl.cc b/winsup/cygwin/ioctl.cc
index 5d9ec87d0cb..39917902d83 100644
--- a/winsup/cygwin/ioctl.cc
+++ b/winsup/cygwin/ioctl.cc
@@ -13,7 +13,6 @@ details. */
#include "winsup.h"
#include <sys/ioctl.h>
-#include <errno.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc
index 9841cd528b6..5798cf41742 100644
--- a/winsup/cygwin/malloc_wrapper.cc
+++ b/winsup/cygwin/malloc_wrapper.cc
@@ -18,7 +18,6 @@ details. */
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
-#include <errno.h>
#include "cygerrno.h"
#include "cygheap.h"
#include "heap.h"
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index 6cf8cc7df8f..08f89c84f4c 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -13,7 +13,6 @@ details. */
#include <stdlib.h>
#include <stddef.h>
#include <sys/mman.h>
-#include <errno.h>
#include "security.h"
#include "path.h"
#include "fhandler.h"
@@ -272,7 +271,8 @@ public:
void erase (int i);
void erase ();
mmap_record *match (_off64_t off, DWORD len);
- long match (caddr_t addr, DWORD len, long start);
+ long match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
+ long start);
};
list::list ()
@@ -325,13 +325,24 @@ list::match (_off64_t off, DWORD len)
/* Used in munmap() */
long
-list::match (caddr_t addr, DWORD len, _off_t start)
+list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
+ _off_t start)
{
+ caddr_t low, high;
+
for (int i = start + 1; i < nrecs; ++i)
- if (addr >= recs[i].get_address ()
- && addr + len <= recs[i].get_address ()
- + (PAGE_CNT (recs[i].get_size ()) * getpagesize ()))
- return i;
+ {
+ low = (addr >= recs[i].get_address ()) ? addr : recs[i].get_address ();
+ high = recs[i].get_address ()
+ + (PAGE_CNT (recs[i].get_size ()) * getpagesize ());
+ high = (addr + len < high) ? addr + len : high;
+ if (low < high)
+ {
+ m_addr = low;
+ m_len = high - low;
+ return i;
+ }
+ }
return -1;
}
@@ -440,7 +451,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
if (off % getpagesize ()
|| (!(flags & MAP_SHARED) && !(flags & MAP_PRIVATE))
|| ((flags & MAP_SHARED) && (flags & MAP_PRIVATE))
- || ((flags & MAP_FIXED) && ((DWORD)addr % granularity))
+ || ((flags & MAP_FIXED) && ((DWORD)addr % getpagesize ()))
|| !len)
{
set_errno (EINVAL);
@@ -471,8 +482,6 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
DWORD gran_len = howmany (off + len, granularity) * granularity - gran_off;
fhandler_base *fh;
- caddr_t base = addr;
- HANDLE h;
if (fd != -1)
{
@@ -490,6 +499,16 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
DWORD high;
DWORD low = GetFileSize (fh->get_handle (), &high);
_off64_t fsiz = ((_off64_t)high << 32) + low;
+ /* Don't allow mappings beginning beyond EOF since Windows can't
+ handle that POSIX like. FIXME: Still looking for a good idea
+ to allow that nevertheless. */
+ if (gran_off >= fsiz)
+ {
+ set_errno (ENXIO);
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
+ "mmap");
+ return MAP_FAILED;
+ }
fsiz -= gran_off;
if (gran_len > fsiz)
gran_len = fsiz;
@@ -542,7 +561,13 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
&& (wincap.has_working_copy_on_write () || fd != -1))
access = FILE_MAP_COPY;
- h = fh->mmap (&base, gran_len, access, flags, gran_off);
+ caddr_t base = addr;
+ /* This shifts the base address to the next lower 64K boundary.
+ The offset is re-added when evaluating the return value. */
+ if (base)
+ base -= off - gran_off;
+
+ HANDLE h = fh->mmap (&base, gran_len, access, flags, gran_off);
if (h == INVALID_HANDLE_VALUE)
{
@@ -589,16 +614,16 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, _off_t off)
return mmap64 (addr, len, prot, flags, fd, (_off64_t)off);
}
-/* munmap () removes an mmapped area. It insists that base area
- requested is the same as that mmapped, error if not. */
+/* munmap () removes all mmapped pages between addr and addr+len. */
extern "C" int
munmap (caddr_t addr, size_t len)
{
syscall_printf ("munmap (addr %x, len %d)", addr, len);
- /* Error conditions according to SUSv2 */
- if (((DWORD)addr % getpagesize ()) || !len)
+ /* Error conditions according to SUSv3 */
+ if (!addr || ((DWORD)addr % getpagesize ()) || !len
+ || IsBadReadPtr (addr, len))
{
set_errno (EINVAL);
syscall_printf ("-1 = munmap(): Invalid parameters");
@@ -606,17 +631,15 @@ munmap (caddr_t addr, size_t len)
}
SetResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
- /* Check if a mmap'ed area was ever created */
if (mmapped_areas == NULL)
{
syscall_printf ("-1 = munmap(): mmapped_areas == NULL");
- set_errno (EINVAL);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
- return -1;
+ return 0;
}
- /* Iterate through the map, looking for the mmapped area.
- Error if not found. */
+ /* Iterate through the map, unmap pages between addr and addr+len
+ in all maps. */
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
@@ -624,10 +647,13 @@ munmap (caddr_t addr, size_t len)
if (map_list)
{
long li = -1;
- if ((li = map_list->match(addr, len, li)) >= 0)
+ caddr_t u_addr;
+ DWORD u_len;
+
+ while ((li = map_list->match(addr, len, u_addr, u_len, li)) >= 0)
{
mmap_record *rec = map_list->recs + li;
- if (rec->unmap_map (addr, len))
+ if (rec->unmap_map (u_addr, u_len))
{
fhandler_base *fh = rec->alloc_fh ();
fh->munmap (rec->get_handle (), addr, len);
@@ -636,18 +662,13 @@ munmap (caddr_t addr, size_t len)
/* Delete the entry. */
map_list->erase (li);
}
- syscall_printf ("0 = munmap(): %x", addr);
- ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
- return 0;
}
}
}
- set_errno (EINVAL);
- syscall_printf ("-1 = munmap(): EINVAL");
-
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
- return -1;
+ syscall_printf ("0 = munmap(): %x", addr);
+ return 0;
}
/* Sync file with memory. Ignore flags for now. */
@@ -815,9 +836,15 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, DWORD access,
}
DWORD high = off >> 32, low = off & 0xffffffff;
- void *base = MapViewOfFileEx (h, access, high, low, len,
- (flags & MAP_FIXED) ? *addr : NULL);
- debug_printf ("%x = MapViewOfFileEx (h:%x, access:%x, 0, off:%D, len:%d, addr:%x)", base, h, access, off, len, (flags & MAP_FIXED) ? *addr : NULL);
+ void *base = NULL;
+ /* If a non-zero address is given, try mapping using the given address first.
+ If it fails and flags is not MAP_FIXED, try again with NULL address. */
+ if (*addr)
+ base = MapViewOfFileEx (h, access, high, low, len, *addr);
+ if (!base && !(flags & MAP_FIXED))
+ base = MapViewOfFileEx (h, access, high, low, len, NULL);
+ debug_printf ("%x = MapViewOfFileEx (h:%x, access:%x, 0, off:%D, "
+ "len:%d, addr:%x)", base, h, access, off, len, *addr);
if (!base || ((flags & MAP_FIXED) && base != *addr))
{
if (!base)
diff --git a/winsup/cygwin/msg.cc b/winsup/cygwin/msg.cc
new file mode 100644
index 00000000000..fecaa068a62
--- /dev/null
+++ b/winsup/cygwin/msg.cc
@@ -0,0 +1,47 @@
+/* msg.cc: Single unix specification IPC interface for Cygwin.
+
+ Copyright 2002 Red Hat, Inc.
+
+ Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+
+#include <sys/types.h>
+#include <cygwin/msg.h>
+
+
+#include "cygerrno.h"
+
+extern "C" int
+msgctl (int msqid, int cmd, struct msqid_ds *buf)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" int
+msgget (key_t key, int msgflg)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" ssize_t
+msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" int
+msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index fc4f5482c66..1d1abab7659 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -13,7 +13,6 @@ details. */
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
-#include <errno.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -1288,20 +1287,39 @@ getdomainname (char *domain, size_t len)
if (__check_null_invalid_struct_errno (domain, len))
return -1;
+ PFIXED_INFO info = NULL;
+ ULONG size = 0;
+
+ if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
+ && (info = (PFIXED_INFO) alloca(size))
+ && GetNetworkParams(info, &size) == ERROR_SUCCESS)
+ {
+ strncpy(domain, info->DomainName, len);
+ return 0;
+ }
+
+ /* This is only used by Win95 and NT <= 4.0.
+ The registry names are language independent.
+ FIXME: Handle DHCP on Win95. The DhcpDomain(s) may be available
+ in ..VxD\DHCP\DhcpInfoXX\OptionInfo, RFC 1533 format */
+
reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
(!wincap.is_winnt ()) ? "System" : "SYSTEM",
"CurrentControlSet", "Services",
(!wincap.is_winnt ()) ? "VxD" : "Tcpip",
(!wincap.is_winnt ()) ? "MSTCP" : "Parameters", NULL);
- /* FIXME: Are registry keys case sensitive? */
- if (r.error () || r.get_string ("Domain", domain, len, "") != ERROR_SUCCESS)
+ if (!r.error ())
{
- __seterrno ();
- return -1;
+ int res1, res2 = 0; /* Suppress compiler warning */
+ res1 = r.get_string ("Domain", domain, len, "");
+ if (res1 != ERROR_SUCCESS || !domain[0])
+ res2 = r.get_string ("DhcpDomain", domain, len, "");
+ if (res1 == ERROR_SUCCESS || res2 == ERROR_SUCCESS)
+ return 0;
}
-
- return 0;
+ __seterrno ();
+ return -1;
}
/* Fill out an ifconf struct. */
@@ -1972,7 +1990,10 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
cygheap_fdnew res_fd;
if (res_fd >= 0 && fdsock (res_fd, tcp_dev, res))
- res = res_fd;
+ {
+ ((fhandler_socket *) res_fd)->set_connect_state (CONNECTED);
+ res = res_fd;
+ }
else
{
closesocket (res);
@@ -1985,7 +2006,10 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
cygheap_fdget fd (*fd2p);
if (newfd >= 0 && fdsock (newfd, tcp_dev, fd2s))
- *fd2p = newfd;
+ {
+ *fd2p = newfd;
+ ((fhandler_socket *) fd2p)->set_connect_state (CONNECTED);
+ }
else
{
closesocket (res);
@@ -2048,7 +2072,10 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
cygheap_fdnew res_fd;
if (res_fd >= 0 && fdsock (res_fd, tcp_dev, res))
- res = res_fd;
+ {
+ ((fhandler_socket *) res_fd)->set_connect_state (CONNECTED);
+ res = res_fd;
+ }
else
{
closesocket (res);
@@ -2061,7 +2088,10 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
cygheap_fdget fd (*fd2p);
if (newfd >= 0 && fdsock (newfd, tcp_dev, fd2s))
- *fd2p = newfd;
+ {
+ ((fhandler_socket *) fd2p)->set_connect_state (CONNECTED);
+ *fd2p = newfd;
+ }
else
{
closesocket (res);
@@ -2234,6 +2264,7 @@ socketpair (int family, int type, int protocol, int *sb)
((fhandler_socket *) sb0)->set_sun_path ("");
((fhandler_socket *) sb0)->set_addr_family (family);
((fhandler_socket *) sb0)->set_socket_type (type);
+ ((fhandler_socket *) sb0)->set_connect_state (CONNECTED);
cygheap_fdnew sb1 (sb0, false);
@@ -2242,6 +2273,7 @@ socketpair (int family, int type, int protocol, int *sb)
((fhandler_socket *) sb1)->set_sun_path ("");
((fhandler_socket *) sb1)->set_addr_family (family);
((fhandler_socket *) sb1)->set_socket_type (type);
+ ((fhandler_socket *) sb1)->set_connect_state (CONNECTED);
sb[0] = sb0;
sb[1] = sb1;
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
index 7ddff77707c..4841a4c9345 100644
--- a/winsup/cygwin/ntea.cc
+++ b/winsup/cygwin/ntea.cc
@@ -16,7 +16,7 @@ details. */
#include "security.h"
/* Default to not using NTEA information */
-BOOL allow_ntea;
+bool allow_ntea;
/*
From Windows NT DDK:
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
index 38876d21710..01e9a6ba163 100644
--- a/winsup/cygwin/passwd.cc
+++ b/winsup/cygwin/passwd.cc
@@ -12,7 +12,6 @@ details. */
#include <stdlib.h>
#include <pwd.h>
#include <stdio.h>
-#include <errno.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 60856f2e110..8947be723f1 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -53,7 +53,6 @@ details. */
#include <sys/mount.h>
#include <mntent.h>
#include <unistd.h>
-#include <errno.h>
#include <ctype.h>
#include <winioctl.h>
#include <wingdi.h>
@@ -208,7 +207,7 @@ normalize_posix_path (const char *src, char *dst)
syscall_printf ("src %s", src);
- if (isdrive (src) || strpbrk (src, "\\:"))
+ if (isdrive (src))
{
int err = normalize_win32_path (src, dst);
if (!err && isdrive (dst))
@@ -513,7 +512,7 @@ path_conv::check (const char *src, unsigned opt,
/* Scan path_copy from right to left looking either for a symlink
or an actual existing file. If an existing file is found, just
- return. If a symlink is found exit the for loop.
+ return. If a symlink is found, exit the for loop.
Also: be careful to preserve the errno returned from
symlink.check as the caller may need it. */
/* FIXME: Do we have to worry about multiple \'s here? */
@@ -1151,10 +1150,99 @@ set_flags (unsigned *flags, unsigned val)
}
}
+char special_chars[] =
+ "\001" "\002" "\003" "\004" "\005" "\006" "\007" "\010"
+ "\011" "\012" "\013" "\014" "\015" "\016" "\017" "\020"
+ "\021" "\022" "\023" "\024" "\025" "\026" "\027" "\030"
+ "\031" "\032" "\033" "\034" "\035" "\036" "\037"
+ ":" "\\" "*" "?" "%"
+ "A" "B" "C" "D" "E" "F" "G" "H"
+ "I" "J" "K" "L" "M" "N" "O" "P"
+ "Q" "R" "S" "T" "U" "V" "W" "X"
+ "Y" "Z";
+
+static inline char
+special_char (const char *s)
+{
+ char *p = strechr (special_chars, *s);
+ if (*p == '%' && strlen (p) >= 3)
+ {
+ char hex[] = {s[1], s[2], '\0'};
+ unsigned char c = strtoul (hex, &p, 16);
+ p = strechr (special_chars, c);
+ }
+ return *p;
+}
+
+bool
+fnunmunge (char *dst, const char *src)
+{
+ bool converted = false;
+ char c;
+
+ while (*src)
+ if (*src != '%' || !(c = special_char (src)))
+ *dst++ = *src++;
+ else
+ {
+ converted = true;
+ *dst++ = c;
+ src += 3;
+ }
+
+ *dst = *src;
+ return converted;
+}
+
+/* Determines if name is "special". Assumes that name is empty or "absolute" */
+static int
+special_name (const char *s)
+{
+ if (!*s)
+ return false;
+
+ if (strpbrk (++s, special_chars))
+ return !strncasematch (s, "%2f", 3);
+
+ if (strcasematch (s, "nul")
+ || strcasematch (s, "aux")
+ || strcasematch (s, "prn"))
+ return -1;
+ if (!strncasematch (s, "com", 3)
+ && !strncasematch (s, "lpt", 3))
+ return false;
+ char *p;
+ (void) strtol (s, &p, 10);
+ return -(*p == '\0');
+}
+
void
mount_item::fnmunge (char *dst, const char *src)
{
- strcpy (dst, src);
+ int name_type;
+ if (!(flags & MOUNT_ENC) || !(name_type = special_name (src)))
+ strcpy (dst, src);
+ else
+ {
+ char *d = dst;
+ *d++ = *src++;
+ if (name_type < 0)
+ {
+ __small_sprintf (d, "%%%02x", (unsigned char) *src++);
+ d += 3;
+ }
+
+ while (*src)
+ if (!special_char (src))
+ *d++ = *src++;
+ else
+ {
+ __small_sprintf (d, "%%%02x", (unsigned char) *src++);
+ d += 3;
+ }
+ *d = *src;
+ }
+
backslashify (dst, dst, 0);
}
@@ -1181,7 +1269,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
const char *p = src + real_posix_pathlen;
if (*p == '/')
/* nothing */;
- else if ((isdrive (dst) && !dst[2]) || *p)
+ else if ((!(flags & MOUNT_ENC) && isdrive (dst) && !dst[2]) || *p)
dst[n++] = '\\';
fnmunge (dst + n, p);
}
@@ -1234,22 +1322,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
if (dst == NULL)
goto out; /* Sanity check. */
- /* An MS-DOS spec has either a : or a \. If this is found, short
- circuit most of the rest of this function. */
- if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
- {
- debug_printf ("%s already win32", src_path);
- rc = normalize_win32_path (src_path, dst);
- if (rc)
- {
- debug_printf ("normalize_win32_path failed, rc %d", rc);
- return rc;
- }
-
- set_flags (flags, (unsigned) set_flags_from_win32_path (dst));
- goto out;
- }
-
/* Normalize the path, taking out ../../ stuff, we need to do this
so that we can move from one mounted directory to another with relative
stuff.
@@ -1349,16 +1421,21 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
break;
}
- if (i >= nmounts)
+ if (i < nmounts)
{
- backslashify (pathbuf, dst, 0); /* just convert */
- set_flags (flags, PATH_BINARY);
- chroot_ok = !cygheap->root.exists ();
+ mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
+ chroot_ok = true;
}
else
{
- mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
- chroot_ok = true;
+ if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
+ rc = normalize_win32_path (src_path, dst);
+ else
+ {
+ backslashify (pathbuf, dst, 0); /* just convert */
+ set_flags (flags, PATH_BINARY);
+ }
+ chroot_ok = !cygheap->root.exists ();
}
if (!isvirtual_dev (dev.devn))
@@ -1522,6 +1599,12 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
const char *p = cygheap->root.unchroot (posix_path);
memmove (posix_path, p, strlen (p) + 1);
}
+ if (mi.flags & MOUNT_ENC)
+ {
+ char tmpbuf[MAX_PATH + 1];
+ if (fnunmunge (tmpbuf, posix_path))
+ strcpy (posix_path, tmpbuf);
+ }
goto out;
}
@@ -1656,10 +1739,16 @@ mount_info::from_registry ()
/* FIXME: Need a mutex to avoid collisions with other tasks. */
int
-mount_info::add_reg_mount (const char * native_path, const char * posix_path, unsigned mountflags)
+mount_info::add_reg_mount (const char *native_path, const char *posix_path, unsigned mountflags)
{
int res = 0;
+ if (strchr (posix_path, '\\'))
+ {
+ set_errno (EINVAL);
+ goto err1;
+ }
+
/* Add the mount to the right registry location, depending on
whether MOUNT_SYSTEM is set in the mount flags. */
if (!(mountflags & MOUNT_SYSTEM)) /* current_user mount */
@@ -1710,6 +1799,7 @@ mount_info::add_reg_mount (const char * native_path, const char * posix_path, un
return 0; /* Success */
err:
__seterrno_from_win_error (res);
+ err1:
return -1;
}
@@ -2175,6 +2265,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
strcat (_reent_winsup ()->mnt_opts, (char *) ",exec");
else if (flags & MOUNT_NOTEXEC)
strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec");
+ if (flags & MOUNT_ENC)
+ strcat (_reent_winsup ()->mnt_opts, ",managed");
if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */
strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount");
@@ -2259,7 +2351,9 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
{
int res = -1;
- if (flags & MOUNT_CYGDRIVE) /* normal mount */
+ if (strpbrk (posix_path, "\\:"))
+ set_errno (EINVAL);
+ else if (flags & MOUNT_CYGDRIVE) /* normal mount */
{
/* When flags include MOUNT_CYGDRIVE, take this to mean that
we actually want to change the cygdrive prefix and flags
@@ -3162,7 +3256,7 @@ chdir (const char *in_dir)
return -1;
}
- const char *native_dir = path.get_win32 ();
+ const char *native_dir = path;
/* Check to see if path translates to something like C:.
If it does, append a \ to the native directory specification to
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 9275bef066f..3f4fe34a949 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -59,6 +59,7 @@ enum path_types
PATH_EXEC = MOUNT_EXEC,
PATH_NOTEXEC = MOUNT_NOTEXEC,
PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC,
+ PATH_ENC = MOUNT_ENC,
PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC),
PATH_LNK = 0x01000000,
PATH_TEXT = 0x02000000,
@@ -108,6 +109,7 @@ class path_conv
int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
int hasgood_inode () const {return path_flags & PATH_HASACLS;} // Not strictly correct
int has_buggy_open () const {return path_flags & PATH_HASBUGGYOPEN;}
+ bool isencoded () {return path_flags & PATH_ENC;}
int binmode () const
{
if (path_flags & PATH_BINARY)
@@ -242,6 +244,8 @@ has_exec_chars (const char *buf, int len)
int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2)));
int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2)));
+bool fnunmunge (char *, const char *) __attribute__ ((regparm (2)));
+
int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3)));
/* FIXME: Move to own include file eventually */
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index bd07e48a65e..e7eeb43c9fb 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -11,7 +11,6 @@ details. */
#include "winsup.h"
#include <stdlib.h>
#include <time.h>
-#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include "security.h"
@@ -361,7 +360,7 @@ _pinfo::commune_send (DWORD code, ...)
res.s = NULL;
res.n = 0;
- if (!pid || !this)
+ if (!pid || !this || (dwProcessId != (DWORD) pid && !pinfo (myself->dwProcessId)))
{
set_errno (ESRCH);
goto err;
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 50f5a4dcb48..a1e99b27e25 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -12,7 +12,6 @@ details. */
#include "winsup.h"
#include <unistd.h>
-#include <errno.h>
#include <sys/socket.h>
#include "cygerrno.h"
#include "security.h"
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index 35d02a83da0..da650ff61cb 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -10,11 +10,11 @@
#define __INSIDE_CYGWIN_NET__
+#define FD_SETSIZE 16384 // lots of fds
#include "winsup.h"
#include <sys/time.h>
#include <sys/poll.h>
#include <sys/socket.h>
-#include <errno.h>
#include <stdlib.h>
#define USE_SYS_TYPES_FD_SET
#include <winsock2.h>
diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc
new file mode 100644
index 00000000000..e87702babfa
--- /dev/null
+++ b/winsup/cygwin/resource.cc
@@ -0,0 +1,188 @@
+/* resource.cc: getrusage () and friends.
+
+ Copyright 1996, 1997, 1998, 2000, 2001, 2002 Red Hat, Inc.
+
+ Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com),
+ Geoffrey Noer (noer@cygnus.com) of Cygnus Support.
+ Rewritten by Sergey S. Okhapkin (sos@prospect.com.ru)
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <unistd.h>
+#include <limits.h>
+#include "cygerrno.h"
+#include "pinfo.h"
+#include "psapi.h"
+
+/* add timeval values */
+static void
+add_timeval (struct timeval *tv1, struct timeval *tv2)
+{
+ tv1->tv_sec += tv2->tv_sec;
+ tv1->tv_usec += tv2->tv_usec;
+ if (tv1->tv_usec >= 1000000)
+ {
+ tv1->tv_usec -= 1000000;
+ tv1->tv_sec++;
+ }
+}
+
+/* add rusage values of r2 to r1 */
+void __stdcall
+add_rusage (struct rusage *r1, struct rusage *r2)
+{
+ add_timeval (&r1->ru_utime, &r2->ru_utime);
+ add_timeval (&r1->ru_stime, &r2->ru_stime);
+ r1->ru_maxrss += r2->ru_maxrss;
+ r1->ru_ixrss += r2->ru_ixrss;
+ r1->ru_idrss += r2->ru_idrss;
+ r1->ru_isrss += r2->ru_isrss;
+ r1->ru_minflt += r2->ru_minflt;
+ r1->ru_majflt += r2->ru_majflt;
+ r1->ru_nswap += r2->ru_nswap;
+ r1->ru_inblock += r2->ru_inblock;
+ r1->ru_oublock += r2->ru_oublock;
+ r1->ru_msgsnd += r2->ru_msgsnd;
+ r1->ru_msgrcv += r2->ru_msgrcv;
+ r1->ru_nsignals += r2->ru_nsignals;
+ r1->ru_nvcsw += r2->ru_nvcsw;
+ r1->ru_nivcsw += r2->ru_nivcsw;
+}
+
+/* FIXME: what about other fields? */
+void __stdcall
+fill_rusage (struct rusage *r, HANDLE h)
+{
+ FILETIME creation_time = {0,0};
+ FILETIME exit_time = {0,0};
+ FILETIME kernel_time = {0,0};
+ FILETIME user_time = {0,0};
+
+ struct timeval tv;
+
+ memset (r, 0, sizeof (*r));
+ GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time);
+ totimeval (&tv, &kernel_time, 0, 0);
+ add_timeval (&r->ru_stime, &tv);
+ totimeval (&tv, &user_time, 0, 0);
+ add_timeval (&r->ru_utime, &tv);
+
+ PROCESS_MEMORY_COUNTERS pmc;
+
+ memset (&pmc, 0, sizeof (pmc));
+ if (GetProcessMemoryInfo (h, &pmc, sizeof (pmc)))
+ {
+ r->ru_maxrss += (long) (pmc.WorkingSetSize /1024);
+ r->ru_majflt += pmc.PageFaultCount;
+ }
+}
+
+extern "C" int
+getrusage (int intwho, struct rusage *rusage_in)
+{
+ int res = 0;
+ struct rusage r;
+
+ if (intwho == RUSAGE_SELF)
+ {
+ memset (&r, 0, sizeof (r));
+ fill_rusage (&r, hMainProc);
+ *rusage_in = r;
+ }
+ else if (intwho == RUSAGE_CHILDREN)
+ *rusage_in = myself->rusage_children;
+ else
+ {
+ set_errno (EINVAL);
+ res = -1;
+ }
+
+ syscall_printf ("%d = getrusage (%d, %p)", res, intwho, rusage_in);
+ return res;
+}
+
+unsigned long rlim_core = RLIM_INFINITY;
+
+extern "C" int
+getrlimit (int resource, struct rlimit *rlp)
+{
+ MEMORY_BASIC_INFORMATION m;
+
+ if (check_null_invalid_struct_errno (rlp))
+ return -1;
+
+ rlp->rlim_cur = RLIM_INFINITY;
+ rlp->rlim_max = RLIM_INFINITY;
+
+ switch (resource)
+ {
+ case RLIMIT_CPU:
+ case RLIMIT_FSIZE:
+ case RLIMIT_DATA:
+ break;
+ case RLIMIT_STACK:
+ if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
+ debug_printf ("couldn't get stack info, returning def.values. %E");
+ else
+ {
+ rlp->rlim_cur = (DWORD) &m - (DWORD) m.AllocationBase;
+ rlp->rlim_max = (DWORD) m.BaseAddress + m.RegionSize
+ - (DWORD) m.AllocationBase;
+ }
+ break;
+ case RLIMIT_NOFILE:
+ rlp->rlim_cur = getdtablesize ();
+ break;
+ case RLIMIT_CORE:
+ rlp->rlim_cur = rlim_core;
+ break;
+ case RLIMIT_AS:
+ rlp->rlim_cur = 0x80000000UL;
+ rlp->rlim_max = 0x80000000UL;
+ break;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 0;
+}
+
+extern "C" int
+setrlimit (int resource, const struct rlimit *rlp)
+{
+ if (__check_invalid_read_ptr_errno (rlp, sizeof (*rlp)))
+ return -1;
+
+ struct rlimit oldlimits;
+
+ // Check if the request is to actually change the resource settings.
+ // If it does not result in a change, take no action and do not
+ // fail.
+ if (getrlimit (resource, &oldlimits) < 0)
+ return -1;
+
+ if (oldlimits.rlim_cur == rlp->rlim_cur &&
+ oldlimits.rlim_max == rlp->rlim_max)
+ // No change in resource requirements, succeed immediately
+ return 0;
+
+ switch (resource)
+ {
+ case RLIMIT_CORE:
+ rlim_core = rlp->rlim_cur;
+ break;
+ case RLIMIT_NOFILE:
+ if (rlp->rlim_cur != RLIM_INFINITY)
+ return setdtablesize (rlp->rlim_cur);
+ break;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 0;
+}
diff --git a/winsup/cygwin/scandir.cc b/winsup/cygwin/scandir.cc
new file mode 100644
index 00000000000..a2f682a50c5
--- /dev/null
+++ b/winsup/cygwin/scandir.cc
@@ -0,0 +1,99 @@
+/* scandir.cc
+
+ Copyright 1998, 1999, 2000, 2001 Red Hat, Inc.
+
+ Written by Corinna Vinschen <corinna.vinschen@cityweb.de>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#include "winsup.h"
+#include <dirent.h>
+#include <stdlib.h>
+#include "cygerrno.h"
+
+extern "C" int
+alphasort (const struct dirent **a, const struct dirent **b)
+{
+ return strcoll ((*a)->d_name, (*b)->d_name);
+}
+
+extern "C" int
+scandir (const char *dir,
+ struct dirent ***namelist,
+ int (*select) (const struct dirent *),
+ int (*compar) (const struct dirent **, const struct dirent **))
+{
+ DIR *dirp;
+ struct dirent *ent, *etmp, **nl = NULL, **ntmp;
+ int count = 0;
+ int allocated = 0;
+
+ if (!(dirp = opendir (dir)))
+ return -1;
+
+ int prior_errno = get_errno ();
+ set_errno (0);
+ if (!compar)
+ compar = alphasort;
+
+ while ((ent = readdir (dirp)))
+ {
+ if (!select || select (ent))
+ {
+
+ /* Ignore error from readdir/select. See POSIX specs. */
+ set_errno (0);
+
+ if (count == allocated)
+ {
+
+ if (allocated == 0)
+ allocated = 10;
+ else
+ allocated *= 2;
+
+ ntmp = (struct dirent **) realloc (nl, allocated * sizeof *nl);
+ if (!ntmp)
+ {
+ set_errno (ENOMEM);
+ break;
+ }
+ nl = ntmp;
+ }
+
+ if (!(etmp = (struct dirent *) malloc (sizeof *ent)))
+ {
+ set_errno (ENOMEM);
+ break;
+ }
+ *etmp = *ent;
+ nl[count++] = etmp;
+ }
+ }
+
+ if ((prior_errno = get_errno ()) != 0)
+ {
+ closedir (dirp);
+ if (nl)
+ {
+ while (count > 0)
+ free (nl[--count]);
+ free (nl);
+ }
+ /* Ignore errors from closedir() and what not else. */
+ set_errno (prior_errno);
+ return -1;
+ }
+
+ closedir (dirp);
+ set_errno (prior_errno);
+
+ qsort (nl, count, sizeof *nl, (int (*)(const void *, const void *)) compar);
+ if (namelist)
+ *namelist = nl;
+ return count;
+}
diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc
new file mode 100644
index 00000000000..b29d7a49e4e
--- /dev/null
+++ b/winsup/cygwin/sched.cc
@@ -0,0 +1,443 @@
+/* sched.cc: scheduler interface for Cygwin
+
+ Copyright 2001, 2002 Red Hat, Inc.
+
+ Written by Robert Collins <rbtcollins@hotmail.com>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "winsup.h"
+#include <limits.h>
+#include "cygerrno.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sched.h>
+#include "pinfo.h"
+/* for getpid */
+#include <unistd.h>
+
+/* Win32 priority to UNIX priority Mapping.
+ For now, I'm just following the spec: any range of priorities is ok.
+ There are probably many many issues with this...
+
+ We don't want process's going realtime. Well, they probably could, but the issues
+ with avoiding the priority values 17-22 and 27-30 (not supported before win2k)
+ make that inefficient.
+ However to complicate things most unixes use lower is better priorities.
+
+ So we map -14 to 15, and 15 to 1 via (16- ((n+16) >> 1))
+ we then map 1 to 15 to various process class and thread priority combinations
+
+ Then we need to look at the threads vi process priority. As win95 98 and NT 4
+ Don't support opening threads cross-process (unless a thread HANDLE is passed around)
+ for now, we'll just use the priority class.
+
+ The code and logic are present to calculate the priority for thread
+ , if a thread handle can be obtained. Alternatively, if the symbols wouldn't be
+ resolved until they are used
+ we could support this on windows 2000 and ME now, and just fall back to the
+ class only on pre win2000 machines.
+
+ Lastly, because we can't assume that the pid we're given are Windows pids, we can't
+ alter non-cygwin started programs.
+*/
+
+extern "C"
+{
+
+/* max priority for policy */
+int
+sched_get_priority_max (int policy)
+{
+ if (policy < 1 || policy > 3)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ return -14;
+}
+
+/* min priority for policy */
+int
+sched_get_priority_min (int policy)
+{
+ if (policy < 1 || policy > 3)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 15;
+}
+
+/* Check a scheduler parameter struct for valid settings */
+int
+valid_sched_parameters (const struct sched_param *param)
+{
+ if (param->sched_priority < -14 || param->sched_priority > 15)
+ {
+ return 0;
+ }
+ return -1;
+
+}
+
+/* get sched params for process
+
+ Note, I'm never returning EPERM,
+ Always ESRCH. This is by design (If cygwin ever looks at paranoid security
+ Walking the pid values is a known hole in some os's)
+*/
+int
+sched_getparam (pid_t pid, struct sched_param *param)
+{
+ pid_t localpid;
+ int winpri;
+ if (!param || pid < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ localpid = pid ? pid : getpid ();
+
+ DWORD Class;
+ int ThreadPriority;
+ HANDLE process;
+ pinfo p (localpid);
+
+ /* get the class */
+
+ if (!p)
+ {
+ set_errno (ESRCH);
+ return -1;
+ }
+ process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, p->dwProcessId);
+ if (!process)
+ {
+ set_errno (ESRCH);
+ return -1;
+ }
+ Class = GetPriorityClass (process);
+ CloseHandle (process);
+ if (!Class)
+ {
+ set_errno (ESRCH);
+ return -1;
+ }
+ ThreadPriority = THREAD_PRIORITY_NORMAL;
+
+ /* calculate the unix priority.
+
+ FIXME: windows 2000 supports ABOVE_NORMAL and BELOW_NORMAL class's
+ So this logic just defaults those class factors to NORMAL in the calculations */
+
+ switch (Class)
+ {
+ case IDLE_PRIORITY_CLASS:
+ switch (ThreadPriority)
+ {
+ case THREAD_PRIORITY_IDLE:
+ winpri = 1;
+ break;
+ case THREAD_PRIORITY_LOWEST:
+ winpri = 2;
+ break;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ winpri = 3;
+ break;
+ case THREAD_PRIORITY_NORMAL:
+ winpri = 4;
+ break;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ winpri = 5;
+ break;
+ case THREAD_PRIORITY_HIGHEST:
+ default:
+ winpri = 6;
+ break;
+ }
+ break;
+ case HIGH_PRIORITY_CLASS:
+ switch (ThreadPriority)
+ {
+ case THREAD_PRIORITY_IDLE:
+ winpri = 1;
+ break;
+ case THREAD_PRIORITY_LOWEST:
+ winpri = 11;
+ break;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ winpri = 12;
+ break;
+ case THREAD_PRIORITY_NORMAL:
+ winpri = 13;
+ break;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ winpri = 14;
+ break;
+ case THREAD_PRIORITY_HIGHEST:
+ default:
+ winpri = 15;
+ break;
+ }
+ break;
+ case NORMAL_PRIORITY_CLASS:
+ default:
+ switch (ThreadPriority)
+ {
+ case THREAD_PRIORITY_IDLE:
+ winpri = 1;
+ break;
+ case THREAD_PRIORITY_LOWEST:
+ winpri = 7;
+ break;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ winpri = 8;
+ break;
+ case THREAD_PRIORITY_NORMAL:
+ winpri = 9;
+ break;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ winpri = 10;
+ break;
+ case THREAD_PRIORITY_HIGHEST:
+ default:
+ winpri = 11;
+ break;
+ }
+ break;
+ }
+
+ /* reverse out winpri = (16- ((unixpri+16) >> 1)) */
+ /*
+ winpri-16 = - (unixpri +16 ) >> 1
+
+ -(winpri-16) = unixpri +16 >> 1
+ (-(winpri-16)) << 1 = unixpri+16
+ ((-(winpri - 16)) << 1) - 16 = unixpri
+ */
+
+ param->sched_priority = ((-(winpri - 16)) << 1) - 16;
+
+ return 0;
+}
+
+/* get the scheduler for pid
+
+ All process's on WIN32 run with SCHED_FIFO.
+ So we just give an answer.
+ (WIN32 uses a multi queue FIFO).
+*/
+int
+sched_getscheduler (pid_t pid)
+{
+ if (pid < 0)
+ return ESRCH;
+ else
+ return SCHED_FIFO;
+}
+
+/* get the time quantum for pid
+
+ We can't return -11, errno ENOSYS, because that implies that
+ sched_get_priority_max & min are also not supported (according to the spec)
+ so some spec-driven autoconf tests will likely assume they aren't present either
+
+ returning ESRCH might confuse some applications (if they assumed that when
+ rr_get_interval is called on pid 0 it always works).
+
+ If someone knows the time quanta for the various win32 platforms, then a
+ simple check for the os we're running on will finish this function
+*/
+int
+sched_rr_get_interval (pid_t pid, struct timespec *interval)
+{
+ set_errno (ESRCH);
+ return -1;
+}
+
+/* set the scheduling parameters */
+int
+sched_setparam (pid_t pid, const struct sched_param *param)
+{
+ pid_t localpid;
+ int winpri;
+ DWORD Class;
+ int ThreadPriority;
+ HANDLE process;
+
+ if (!param || pid < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ if (!valid_sched_parameters (param))
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ /* winpri = (16- ((unixpri+16) >> 1)) */
+ winpri = 16 - ((param->sched_priority + 16) >> 1);
+
+ /* calculate our desired priority class and thread priority */
+
+ if (winpri < 7)
+ Class = IDLE_PRIORITY_CLASS;
+ else if (winpri > 10)
+ Class = HIGH_PRIORITY_CLASS;
+ else
+ Class = NORMAL_PRIORITY_CLASS;
+
+ switch (Class)
+ {
+ case IDLE_PRIORITY_CLASS:
+ switch (winpri)
+ {
+ case 1:
+ ThreadPriority = THREAD_PRIORITY_IDLE;
+ break;
+ case 2:
+ ThreadPriority = THREAD_PRIORITY_LOWEST;
+ break;
+ case 3:
+ ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case 4:
+ ThreadPriority = THREAD_PRIORITY_NORMAL;
+ break;
+ case 5:
+ ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case 6:
+ ThreadPriority = THREAD_PRIORITY_HIGHEST;
+ break;
+ }
+ break;
+ case NORMAL_PRIORITY_CLASS:
+ switch (winpri)
+ {
+ case 7:
+ ThreadPriority = THREAD_PRIORITY_LOWEST;
+ break;
+ case 8:
+ ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case 9:
+ ThreadPriority = THREAD_PRIORITY_NORMAL;
+ break;
+ case 10:
+ ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case 11:
+ ThreadPriority = THREAD_PRIORITY_HIGHEST;
+ break;
+ }
+ break;
+ case HIGH_PRIORITY_CLASS:
+ switch (winpri)
+ {
+ case 12:
+ ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case 13:
+ ThreadPriority = THREAD_PRIORITY_NORMAL;
+ break;
+ case 14:
+ ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case 15:
+ ThreadPriority = THREAD_PRIORITY_HIGHEST;
+ break;
+ }
+ break;
+ }
+
+ localpid = pid ? pid : getpid ();
+
+ pinfo p (localpid);
+
+ /* set the class */
+
+ if (!p)
+ {
+ set_errno (1); //ESRCH);
+ return -1;
+ }
+ process =
+ OpenProcess (PROCESS_SET_INFORMATION, FALSE, (DWORD) p->dwProcessId);
+ if (!process)
+ {
+ set_errno (2); //ESRCH);
+ return -1;
+ }
+ if (!SetPriorityClass (process, Class))
+ {
+ CloseHandle (process);
+ set_errno (EPERM);
+ return -1;
+ }
+ CloseHandle (process);
+
+ return 0;
+}
+
+/* we map -14 to 15, and 15 to 1 via (16- ((n+16) >> 1)). This lines up with the allowed
+ * valueswe return elsewhere in the sched* functions. We then map in groups of three to
+ * allowed thread priority's. The reason for dropping accuracy while still returning
+ * a wide range of values is to allow more flexible code in the future.
+ */
+int
+sched_set_thread_priority (HANDLE thread, int priority)
+{
+ int real_pri;
+ real_pri = 16 - ((priority + 16) >> 1);
+ if (real_pri <1 || real_pri > 15)
+ return EINVAL;
+
+ if (real_pri < 4)
+ real_pri = THREAD_PRIORITY_LOWEST;
+ else if (real_pri < 7)
+ real_pri = THREAD_PRIORITY_BELOW_NORMAL;
+ else if (real_pri < 10)
+ real_pri = THREAD_PRIORITY_NORMAL;
+ else if (real_pri < 13)
+ real_pri = THREAD_PRIORITY_ABOVE_NORMAL;
+ else
+ real_pri = THREAD_PRIORITY_HIGHEST;
+
+ if (!SetThreadPriority (thread, real_pri))
+ /* invalid handle, no access are the only expected errors. */
+ return EPERM;
+ return 0;
+}
+
+/* set the scheduler */
+int
+sched_setscheduler (pid_t pid, int policy,
+ const struct sched_param *param)
+{
+ /* on win32, you can't change the scheduler. Doh! */
+ set_errno (ENOSYS);
+ return -1;
+}
+
+/* yield the cpu */
+int
+sched_yield (void)
+{
+ low_priority_sleep (0);
+ return 0;
+}
+}
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index f71236152c5..c35891016ac 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -15,7 +15,6 @@ details. */
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index b50a4c8c51a..3869a60da44 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -15,7 +15,6 @@ details. */
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 98cb37666b1..47f7c335469 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -16,7 +16,6 @@ details. */
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -41,12 +40,11 @@ details. */
#include "lm.h"
#include "pwdgrp.h"
-extern BOOL allow_ntea;
-BOOL allow_ntsec;
+bool allow_ntsec;
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
It's defined here because of it's strong relationship to allow_ntsec.
The default is TRUE to reflect the old behaviour. */
-BOOL allow_smbntsec;
+bool allow_smbntsec;
cygsid *
cygsidlist::alloc_sids (int n)
@@ -71,10 +69,16 @@ extern "C" void
cygwin_set_impersonation_token (const HANDLE hToken)
{
debug_printf ("set_impersonation_token (%d)", hToken);
- if (cygheap->user.token != hToken)
+ if (cygheap->user.impersonation_state == IMP_EXTERNAL
+ && cygheap->user.external_token != hToken)
{
- cygheap->user.token = hToken;
- cygheap->user.impersonated = FALSE;
+ set_errno (EPERM);
+ return;
+ }
+ else
+ {
+ cygheap->user.external_token = hToken;
+ return;
}
}
@@ -718,7 +722,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, BOOL *pintern)
if (pintern)
{
TOKEN_SOURCE ts;
- if (!GetTokenInformation (cygheap->user.token, TokenSource,
+ if (!GetTokenInformation (token, TokenSource,
&ts, sizeof ts, &size))
debug_printf ("GetTokenInformation(): %E");
else
@@ -1907,7 +1911,7 @@ check_file_access (const char *fn, int flags)
goto done;
if (cygheap->user.issetuid ())
- hToken = cygheap->user.token;
+ hToken = cygheap->user.token ();
else if (!OpenProcessToken (hMainProc, TOKEN_DUPLICATE, &hToken))
{
__seterrno ();
@@ -1915,7 +1919,7 @@ check_file_access (const char *fn, int flags)
}
if (!(status = DuplicateToken (hToken, SecurityIdentification, &hIToken)))
__seterrno ();
- if (hToken != cygheap->user.token)
+ if (!cygheap->user.issetuid ())
CloseHandle (hToken);
if (!status)
goto done;
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 2965b1dec59..71ffe4cecaa 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -209,9 +209,9 @@ legal_sid_type (SID_NAME_USE type)
|| type == SidTypeAlias || type == SidTypeWellKnownGroup;
}
-extern BOOL allow_ntea;
-extern BOOL allow_ntsec;
-extern BOOL allow_smbntsec;
+extern bool allow_ntea;
+extern bool allow_ntsec;
+extern bool allow_smbntsec;
/* File manipulation */
int __stdcall set_process_privileges ();
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 6c8a5b4a75a..48cb56c9674 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -20,7 +20,6 @@ details. */
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
-#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/time.h>
diff --git a/winsup/cygwin/sem.cc b/winsup/cygwin/sem.cc
new file mode 100644
index 00000000000..97d91a3546d
--- /dev/null
+++ b/winsup/cygwin/sem.cc
@@ -0,0 +1,40 @@
+/* sem.cc: Single unix specification IPC interface for Cygwin.
+
+ Copyright 2002 Red Hat, Inc.
+
+ Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+
+#include <sys/types.h>
+#include <cygwin/sem.h>
+
+
+#include "cygerrno.h"
+
+extern "C" int
+semctl (int semid, int semnum, int cmd, ...)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" int
+semget (key_t key, int nsems, int semflg)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" int
+semop (int semid, struct sembuf *sops, size_t nsops)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index c91e380b6eb..1f1145840fa 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -14,7 +14,6 @@ details. */
#include <stdlib.h>
#include <grp.h>
#include <pwd.h>
-#include <errno.h>
#include "pinfo.h"
#include "security.h"
#include "path.h"
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
index 618cac1823f..1221298d2b5 100644
--- a/winsup/cygwin/shm.cc
+++ b/winsup/cygwin/shm.cc
@@ -12,11 +12,10 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-
+#ifdef USE_CYGSERVER
#include <sys/types.h>
#include <assert.h>
-#include <errno.h>
#include <stdio.h>
#include <unistd.h>
@@ -691,3 +690,4 @@ client_request_shm::client_request_shm (const key_t key,
msglen (sizeof (_parameters.in));
}
+#endif /* USE_CYGSERVER */
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 547a1285d0c..0530fcf476b 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -12,7 +12,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <stdlib.h>
#include "cygerrno.h"
#include <sys/cygwin.h>
@@ -297,8 +296,8 @@ abort (void)
be flushed.
However this is the way FreeBSD does it, and it is much easier to
do things this way, so... */
- if (_reent_clib ()->__cleanup)
- _reent_clib ()->__cleanup (_reent_clib ());
+ if (_REENT->__cleanup)
+ _REENT->__cleanup (_REENT);
/* Ensure that SIGABRT can be caught regardless of blockage. */
sigset_t sig_mask;
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index dafaad84faf..3237accba5d 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -14,7 +14,6 @@ details. */
#include <stdlib.h>
#include <time.h>
#include <sys/wait.h>
-#include <errno.h>
#include <stdlib.h>
#include <sys/cygwin.h>
#include <assert.h>
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 850536c9de7..fe4efbad0e5 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -14,7 +14,6 @@ details. */
#include <unistd.h>
#include <process.h>
#include <sys/wait.h>
-#include <errno.h>
#include <limits.h>
#include <wingdi.h>
#include <winuser.h>
@@ -622,7 +621,16 @@ spawn_guts (const char * prog_arg, const char *const *argv,
cygbench ("spawn-guts");
cygheap->fdtab.set_file_pointers_for_exec ();
- if (!cygheap->user.issetuid ())
+ cygheap->user.deimpersonate ();
+ /* When ruid != euid we create the new process under the current original
+ account and impersonate in child, this way maintaining the different
+ effective vs. real ids.
+ FIXME: If ruid != euid and ruid != orig_uid we currently give
+ up on ruid. The new process will have ruid == euid. */
+ if (!cygheap->user.issetuid ()
+ || (cygheap->user.orig_uid == cygheap->user.real_uid
+ && cygheap->user.orig_gid == cygheap->user.real_gid
+ && !cygheap->user.groups.issetgroups ()))
{
PSECURITY_ATTRIBUTES sec_attribs = sec_user_nih (sa_buf);
ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
@@ -646,8 +654,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
/* Set security attributes with sid */
PSECURITY_ATTRIBUTES sec_attribs = sec_user_nih (sa_buf, sid);
- RevertToSelf ();
-
/* Load users registry hive. */
load_registry_hive (sid);
@@ -671,7 +677,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
real_path.iscygexec ());
newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
- rc = CreateProcessAsUser (cygheap->user.token,
+ rc = CreateProcessAsUser (cygheap->user.token (),
runpath, /* image name - with full path */
one_line.buf, /* what was passed to exec */
sec_attribs, /* process security attrs */
@@ -682,11 +688,11 @@ spawn_guts (const char * prog_arg, const char *const *argv,
0, /* use current drive/directory */
&si,
&pi);
- /* Restore impersonation. In case of _P_OVERLAY this isn't
- allowed since it would overwrite child data. */
- if (mode != _P_OVERLAY)
- ImpersonateLoggedOnUser (cygheap->user.token);
}
+ /* Restore impersonation. In case of _P_OVERLAY this isn't
+ allowed since it would overwrite child data. */
+ if (mode != _P_OVERLAY)
+ cygheap->user.reimpersonate ();
MALLOC_CHECK;
if (envblock)
diff --git a/winsup/cygwin/strace.cc b/winsup/cygwin/strace.cc
index 283f019141f..57ad3ba0668 100644
--- a/winsup/cygwin/strace.cc
+++ b/winsup/cygwin/strace.cc
@@ -14,7 +14,6 @@ details. */
#include <wingdi.h>
#include <winuser.h>
#include <ctype.h>
-#include <errno.h>
#include "pinfo.h"
#include "perprocess.h"
#include "cygwin_version.h"
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 5625f1a1eb8..91b533f19c4 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -29,7 +29,6 @@ details. */
#include <process.h>
#include <utmp.h>
#include <sys/uio.h>
-#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <setjmp.h>
@@ -1539,8 +1538,6 @@ getpagesize ()
static int
check_posix_perm (const char *fname, int v)
{
- extern int allow_ntea, allow_ntsec, allow_smbntsec;
-
/* Windows 95/98/ME don't support file system security at all. */
if (!wincap.has_security ())
return 0;
@@ -2123,66 +2120,52 @@ seteuid32 (__uid32_t uid)
sigframe thisframe (mainthread);
cygsid usersid;
user_groups &groups = cygheap->user.groups;
- HANDLE ptok, sav_token;
- BOOL sav_impersonated, sav_token_is_internal_token;
- BOOL process_ok, explicitly_created_token = FALSE;
+ HANDLE ptok, new_token = INVALID_HANDLE_VALUE;
struct passwd * pw_new;
PSID origpsid, psid2 = NO_SID;
+ enum impersonation new_state = IMP_BAD;
+ BOOL token_is_internal;
pw_new = internal_getpwuid (uid);
if (!wincap.has_security () && pw_new)
- goto success;
+ goto success_9x;
if (!usersid.getfrompw (pw_new))
{
set_errno (EINVAL);
return -1;
}
- /* Save current information */
- sav_token = cygheap->user.token;
- sav_impersonated = cygheap->user.impersonated;
RevertToSelf ();
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok))
{
__seterrno ();
- goto failed;
+ goto failed_ptok;;
}
- /* Verify if the process token is suitable.
- Currently we do not try to differentiate between
- internal tokens and others */
- process_ok = verify_token (ptok, usersid, groups);
- debug_printf ("Process token %sverified", process_ok ? "" : "not ");
- if (process_ok)
+
+ /* Verify if the process token is suitable. */
+ if (verify_token (ptok, usersid, groups))
+ new_state = IMP_NONE;
+ /* Verify if a current token is suitable */
+ else if (cygheap->user.external_token
+ && verify_token (cygheap->user.external_token, usersid, groups))
{
- if (cygheap->user.issetuid ())
- cygheap->user.impersonated = FALSE;
- else
- {
- CloseHandle (ptok);
- goto success; /* No change */
- }
+ new_token = cygheap->user.external_token;
+ new_state = IMP_EXTERNAL;
+ }
+ else if (cygheap->user.internal_token
+ && verify_token (cygheap->user.internal_token, usersid, groups,
+ &token_is_internal))
+ {
+ new_token = cygheap->user.internal_token;
+ new_state = IMP_INTERNAL;
}
- if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE)
+ debug_printf ("New token %d, state %d", new_token, new_state);
+ /* Return if current token is valid */
+ if (cygheap->user.impersonation_state == new_state)
{
- /* Verify if the current tokem is suitable */
- BOOL token_ok = verify_token (cygheap->user.token, usersid, groups,
- &sav_token_is_internal_token);
- debug_printf ("Thread token %d %sverified",
- cygheap->user.token, token_ok?"":"not ");
- if (!token_ok)
- cygheap->user.token = INVALID_HANDLE_VALUE;
- else
- {
- /* Return if current token is valid */
- if (cygheap->user.impersonated)
- {
- CloseHandle (ptok);
- if (!ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonating in seteuid failed: %E");
- goto success; /* No change */
- }
- }
+ cygheap->user.reimpersonate ();
+ goto success; /* No change */
}
/* Set process def dacl to allow access to impersonated token */
@@ -2198,72 +2181,72 @@ seteuid32 (__uid32_t uid)
debug_printf ("SetTokenInformation"
"(TokenDefaultDacl): %E");
}
- CloseHandle (ptok);
- if (!process_ok && cygheap->user.token == INVALID_HANDLE_VALUE)
+ if (new_state == IMP_BAD)
{
/* If no impersonation token is available, try to
authenticate using NtCreateToken () or subauthentication. */
- cygheap->user.token = create_token (usersid, groups, pw_new);
- if (cygheap->user.token != INVALID_HANDLE_VALUE)
- explicitly_created_token = TRUE;
- else
+ new_token = create_token (usersid, groups, pw_new);
+ if (new_token == INVALID_HANDLE_VALUE)
{
/* create_token failed. Try subauthentication. */
debug_printf ("create token failed, try subauthentication.");
- cygheap->user.token = subauth (pw_new);
- if (cygheap->user.token == INVALID_HANDLE_VALUE)
+ new_token = subauth (pw_new);
+ if (new_token == INVALID_HANDLE_VALUE)
goto failed;
}
+ new_state = IMP_INTERNAL;
}
/* If using the token, set info and impersonate */
- if (!process_ok)
+ if (new_state != IMP_NONE)
{
/* If the token was explicitly created, all information has
already been set correctly. */
- if (!explicitly_created_token)
+ if (new_state == IMP_EXTERNAL)
{
/* Try setting owner to same value as user. */
- if (!SetTokenInformation (cygheap->user.token, TokenOwner,
+ if (!SetTokenInformation (new_token, TokenOwner,
&usersid, sizeof usersid))
debug_printf ("SetTokenInformation(user.token, "
"TokenOwner): %E");
/* Try setting primary group in token to current group */
- if (!SetTokenInformation (cygheap->user.token,
+ if (!SetTokenInformation (new_token,
TokenPrimaryGroup,
&groups.pgsid, sizeof (cygsid)))
debug_printf ("SetTokenInformation(user.token, "
"TokenPrimaryGroup): %E");
}
- /* Now try to impersonate. */
- if (!ImpersonateLoggedOnUser (cygheap->user.token))
+ /* Try to impersonate. */
+ if (!ImpersonateLoggedOnUser (new_token))
{
debug_printf ("ImpersonateLoggedOnUser %E");
__seterrno ();
goto failed;
}
- cygheap->user.impersonated = TRUE;
+ /* Keep at most one internal token */
+ if (new_state == IMP_INTERNAL)
+ {
+ if (cygheap->user.internal_token)
+ CloseHandle (cygheap->user.internal_token);
+ cygheap->user.internal_token = new_token;
+ }
}
-
- /* If sav_token was internally created and is replaced, destroy it. */
- if (sav_token != INVALID_HANDLE_VALUE &&
- sav_token != cygheap->user.token &&
- sav_token_is_internal_token)
- CloseHandle (sav_token);
cygheap->user.set_sid (usersid);
+
success:
+ CloseHandle (ptok);
+ cygheap->user.impersonation_state = new_state;
+success_9x:
cygheap->user.set_name (pw_new->pw_name);
myself->uid = uid;
groups.ischanged = FALSE;
return 0;
failed:
- cygheap->user.token = sav_token;
- cygheap->user.impersonated = sav_impersonated;
- if (cygheap->user.issetuid ()
- && !ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonating in seteuid failed: %E");
+ CloseHandle (ptok);
+failed_ptok:
+ cygheap->user.reimpersonate ();
return -1;
}
@@ -2344,7 +2327,7 @@ setegid32 (__gid32_t gid)
/* If impersonated, update primary group and revert */
if (cygheap->user.issetuid ())
{
- if (!SetTokenInformation (cygheap->user.token,
+ if (!SetTokenInformation (cygheap->user.token (),
TokenPrimaryGroup,
&gsid, sizeof gsid))
debug_printf ("SetTokenInformation(thread, "
@@ -2362,7 +2345,7 @@ setegid32 (__gid32_t gid)
CloseHandle (ptok);
}
if (cygheap->user.issetuid ()
- && !ImpersonateLoggedOnUser (cygheap->user.token))
+ && !ImpersonateLoggedOnUser (cygheap->user.token ()))
system_printf ("Impersonating in setegid failed: %E");
return 0;
}
diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc
index 608f1877671..55eaa8cee93 100644
--- a/winsup/cygwin/sysconf.cc
+++ b/winsup/cygwin/sysconf.cc
@@ -10,7 +10,6 @@ details. */
#include "winsup.h"
#include <unistd.h>
-#include <errno.h>
#include <time.h>
#include <limits.h>
#include <ntdef.h>
diff --git a/winsup/cygwin/syslog.cc b/winsup/cygwin/syslog.cc
index cf3931ffe76..f8b17149c8d 100644
--- a/winsup/cygwin/syslog.cc
+++ b/winsup/cygwin/syslog.cc
@@ -14,7 +14,6 @@ details. */
#include <syslog.h>
#include <stdarg.h>
#include <unistd.h>
-#include <errno.h>
#include "security.h"
#include "path.h"
#include "fhandler.h"
@@ -208,7 +207,7 @@ pass_handler::print_va (const char *fmt, va_list list)
*/
extern "C" void
-syslog (int priority, const char *message, ...)
+vsyslog (int priority, const char *message, va_list ap)
{
debug_printf ("%x %s", priority, message);
/* If the priority fails the current mask, reject */
@@ -281,8 +280,6 @@ syslog (int priority, const char *message, ...)
output, then do it again to a malloc'ed string. This
is ugly, slow, but prevents core dumps :-).
*/
- va_list ap;
-
pass_handler pass;
for (int pass_number = 0; pass_number < 2; ++pass_number)
{
@@ -341,10 +338,8 @@ syslog (int priority, const char *message, ...)
}
/* Print out the variable part */
- va_start (ap, message);
if (pass.print_va (message, ap) == -1)
return;
- va_end (ap);
}
const char *msg_strings[1];
@@ -409,6 +404,15 @@ syslog (int priority, const char *message, ...)
}
extern "C" void
+syslog (int priority, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ vsyslog (priority, message, ap);
+ va_end (ap);
+}
+
+extern "C" void
closelog (void)
{
;
diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc
index 99019b84b75..ebc06573f01 100644
--- a/winsup/cygwin/termios.cc
+++ b/winsup/cygwin/termios.cc
@@ -12,7 +12,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include "cygerrno.h"
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 0321ea47b9d..b42bb140bdc 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -29,7 +29,6 @@ details. */
# include "config.h"
#endif
-#ifdef _MT_SAFE
#include "winsup.h"
#include <limits.h>
#include "cygerrno.h"
@@ -45,16 +44,21 @@ details. */
extern int threadsafe;
-struct _reent *
-_reent_clib ()
+extern "C" struct _reent *
+__getreent ()
{
struct __reent_t *_r =
(struct __reent_t *) MT_INTERFACE->reent_key.get ();
-#ifdef _CYG_THREAD_FAILSAFE
if (_r == 0)
- system_printf ("local thread storage not inited");
+ {
+#ifdef _CYG_THREAD_FAILSAFE
+ system_printf ("local thread storage not inited");
#endif
+ /* Return _impure_ptr as long as MTinterface is not initialized */
+ return _impure_ptr;
+ }
+
return _r->_clib;
}
@@ -64,10 +68,14 @@ _reent_winsup ()
struct __reent_t *_r =
(struct __reent_t *) MT_INTERFACE->reent_key.get ();
-#ifdef _CYG_THREAD_FAILSAFE
if (_r == 0)
- system_printf ("local thread storage not inited");
+ {
+#ifdef _CYG_THREAD_FAILSAFE
+ system_printf ("local thread storage not inited");
#endif
+ return NULL;
+ }
+
return _r->_winsup;
}
@@ -212,9 +220,24 @@ MTinterface::fixup_after_fork (void)
{
pthread_key::fixup_after_fork ();
+#ifndef __SIGNALS_ARE_MULTITHREADED__
+ /* As long as the signal handling not multithreaded
+ switch reents storage back to _impure_ptr for the mainthread
+ to support fork from threads other than the mainthread */
+ struct _reent *reent_old = __getreent ();
+
+ if (reent_old && _impure_ptr != reent_old)
+ *_impure_ptr = *reent_old;
+ reents._clib = _impure_ptr;
+ reents._winsup = &winsup_reent;
+ winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);
+ reent_key.set (&reents);
+#endif
+
threadcount = 1;
pthread::init_mainthread ();
+ pthread::fixup_after_fork ();
pthread_mutex::fixup_after_fork ();
pthread_cond::fixup_after_fork ();
pthread_rwlock::fixup_after_fork ();
@@ -261,11 +284,16 @@ pthread::get_tls_self_pointer ()
+List<pthread> pthread::threads;
+
/* member methods */
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
+ running (false), suspended (false),
cancelstate (0), canceltype (0), cancel_event (0),
- joiner (NULL), cleanup_stack (NULL)
+ joiner (NULL), next (NULL), cleanup_stack (NULL)
{
+ if (this != pthread_null::get_null_pthread ())
+ threads.insert (this);
}
pthread::~pthread ()
@@ -274,6 +302,9 @@ pthread::~pthread ()
CloseHandle (win32_obj_id);
if (cancel_event)
CloseHandle (cancel_event);
+
+ if (this != pthread_null::get_null_pthread ())
+ threads.remove (this);
}
void
@@ -347,13 +378,15 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
void
pthread::postcreate ()
{
- InterlockedIncrement (&MT_INTERFACE->threadcount);
- /* FIXME: set the priority appropriately for system contention scope */
- if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
- {
- /* FIXME: set the scheduling settings for the new thread */
- /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
- }
+ running = true;
+
+ InterlockedIncrement (&MT_INTERFACE->threadcount);
+ /* FIXME: set the priority appropriately for system contention scope */
+ if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
+ {
+ /* FIXME: set the scheduling settings for the new thread */
+ /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
+ }
}
void
@@ -372,6 +405,7 @@ pthread::exit (void *value_ptr)
delete this;
else
{
+ running = false;
return_ptr = value_ptr;
mutex.unlock ();
}
@@ -390,6 +424,12 @@ pthread::cancel (void)
mutex.lock ();
+ if (!running)
+ {
+ mutex.unlock ();
+ return 0;
+ }
+
if (canceltype == PTHREAD_CANCEL_DEFERRED ||
cancelstate == PTHREAD_CANCEL_DISABLE)
{
@@ -739,6 +779,19 @@ pthread::init_current_thread ()
set_tls_self_pointer (this);
}
+void
+pthread::_fixup_after_fork ()
+{
+ /* set thread to not running if it is not the forking thread */
+ if (this != pthread::self ())
+ {
+ magic = 0;
+ running = false;
+ win32_obj_id = NULL;
+ cancel_event = NULL;
+ }
+}
+
/* static members */
bool
pthread_attr::is_good_object (pthread_attr_t const *attr)
@@ -1964,14 +2017,15 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
extern "C" int
pthread_attr_init (pthread_attr_t *attr)
{
- if (check_valid_pointer (attr))
- return EINVAL;
+ if (pthread_attr::is_good_object (attr))
+ return EBUSY;
+
*attr = new pthread_attr;
if (!pthread_attr::is_good_object (attr))
{
delete (*attr);
*attr = NULL;
- return EAGAIN;
+ return ENOMEM;
}
return 0;
}
@@ -2187,7 +2241,7 @@ pthread::detach (pthread_t *thread)
}
// check if thread is still alive
- if (WaitForSingleObject ((*thread)->win32_obj_id, 0) == WAIT_TIMEOUT)
+ if ((*thread)->running && WaitForSingleObject ((*thread)->win32_obj_id, 0) == WAIT_TIMEOUT)
{
// force cleanup on exit
(*thread)->joiner = *thread;
@@ -2488,14 +2542,15 @@ pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
extern "C" int
pthread_condattr_init (pthread_condattr_t *condattr)
{
- if (check_valid_pointer (condattr))
- return EINVAL;
+ if (pthread_condattr::is_good_object (condattr))
+ return EBUSY;
+
*condattr = new pthread_condattr;
if (!pthread_condattr::is_good_object (condattr))
{
delete (*condattr);
*condattr = NULL;
- return EAGAIN;
+ return ENOMEM;
}
return 0;
}
@@ -2673,14 +2728,15 @@ pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
extern "C" int
pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
{
- if (check_valid_pointer (rwlockattr))
- return EINVAL;
+ if (pthread_rwlockattr::is_good_object (rwlockattr))
+ return EBUSY;
+
*rwlockattr = new pthread_rwlockattr;
if (!pthread_rwlockattr::is_good_object (rwlockattr))
{
delete (*rwlockattr);
*rwlockattr = NULL;
- return EAGAIN;
+ return ENOMEM;
}
return 0;
}
@@ -3172,5 +3228,3 @@ pthread_null::getsequence_np ()
}
pthread_null pthread_null::_instance;
-
-#endif // MT_SAFE
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 55d94157b0f..ea1f13f44a2 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -110,7 +110,6 @@ struct __reent_t
struct _winsup_t *_winsup;
};
-_reent *_reent_clib ();
_winsup_t *_reent_winsup ();
void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3)));
void ReleaseResourceLock (int, int, const char *)
@@ -386,11 +385,11 @@ public:
void *(*function) (void *);
void *arg;
void *return_ptr;
+ bool running;
bool suspended;
int cancelstate, canceltype;
HANDLE cancel_event;
pthread_t joiner;
- // int joinable;
/* signal handling */
struct sigaction *sigs;
@@ -443,11 +442,21 @@ public:
return t1 == t2;
}
+ /* List support calls */
+ class pthread *next;
+ static void fixup_after_fork ()
+ {
+ threads.for_each (&pthread::_fixup_after_fork);
+ }
+
private:
+ static List<pthread> threads;
DWORD thread_id;
__pthread_cleanup_handler *cleanup_stack;
pthread_mutex mutex;
+ void _fixup_after_fork ();
+
void pop_all_cleanup_handlers (void);
void precreate (pthread_attr *);
void postcreate ();
diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc
index 87b8c858981..44a08831a9a 100644
--- a/winsup/cygwin/times.cc
+++ b/winsup/cygwin/times.cc
@@ -15,7 +15,6 @@ details. */
#include <utime.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 01d3f5250ec..f13a96f29cd 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -9,7 +9,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <errno.h>
#include <unistd.h>
#include <utmp.h>
#include <wingdi.h>
@@ -409,11 +408,16 @@ tty::common_init (fhandler_pty_master *ptym)
*/
if (wincap.has_security ())
{
+#ifdef USE_CYGSERVER
if (cygserver_running == CYGSERVER_UNKNOWN)
cygserver_init ();
+#endif
- if (cygserver_running != CYGSERVER_OK
- && !SetKernelObjectSecurity (hMainProc,
+ if (
+#ifdef USE_CYGSERVER
+ cygserver_running != CYGSERVER_OK &&
+#endif
+ !SetKernelObjectSecurity (hMainProc,
DACL_SECURITY_INFORMATION,
get_null_sd ()))
system_printf ("Can't set process security, %E");
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index b74cd165b2c..8c16ac64952 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -17,7 +17,6 @@ details. */
#include <limits.h>
#include <stdlib.h>
#include <lm.h>
-#include <errno.h>
#include <sys/cygwin.h>
#include "pinfo.h"
#include "security.h"
@@ -103,18 +102,28 @@ internal_getlogin (cygheap_user &user)
void
uinfo_init ()
{
- if (!child_proc_info || cygheap->user.token != INVALID_HANDLE_VALUE)
+ if (child_proc_info && !cygheap->user.has_impersonation_tokens ())
+ return;
+
+ if (!child_proc_info)
+ internal_getlogin (cygheap->user); /* Set the cygheap->user. */
+ /* Conditions must match those in spawn to allow starting child
+ processes with ruid != euid and rgid != egid. */
+ else if (cygheap->user.issetuid ()
+ && cygheap->user.orig_uid == cygheap->user.real_uid
+ && cygheap->user.orig_gid == cygheap->user.real_gid
+ && !cygheap->user.groups.issetgroups ())
{
- if (!child_proc_info)
- internal_getlogin (cygheap->user); /* Set the cygheap->user. */
- else
- CloseHandle (cygheap->user.token);
- cygheap->user.set_orig_sid (); /* Update the original sid */
- cygheap->user.token = INVALID_HANDLE_VALUE; /* No token present */
+ cygheap->user.reimpersonate ();
+ return;
}
- /* Real and effective uid/gid are identical on process start up. */
+ else
+ cygheap->user.close_impersonation_tokens ();
+
cygheap->user.orig_uid = cygheap->user.real_uid = myself->uid;
cygheap->user.orig_gid = cygheap->user.real_gid = myself->gid;
+ cygheap->user.impersonation_state = IMP_NONE;
+ cygheap->user.set_orig_sid (); /* Update the original sid */
}
extern "C" char *
diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc
index 3b6427ad927..fd782783e33 100644
--- a/winsup/cygwin/wait.cc
+++ b/winsup/cygwin/wait.cc
@@ -11,7 +11,6 @@ details. */
#include "winsup.h"
#include <sys/wait.h>
#include <stdlib.h>
-#include <errno.h>
#include "cygerrno.h"
#include "sigproc.h"
#include "perthread.h"
diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc
new file mode 100644
index 00000000000..ea9ed6e04bb
--- /dev/null
+++ b/winsup/cygwin/window.cc
@@ -0,0 +1,249 @@
+/* window.cc: hidden windows for signals/itimer support
+
+ Copyright 1997, 1998, 2000, 2001, 2002, 2003 Red Hat, Inc.
+
+ Written by Sergey Okhapkin <sos@prospect.com.ru>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <sys/time.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <limits.h>
+#include <wingdi.h>
+#include <winuser.h>
+#define USE_SYS_TYPES_FD_SET
+#include <winsock2.h>
+#include <unistd.h>
+#include "cygerrno.h"
+#include "perprocess.h"
+#include "security.h"
+#include "cygthread.h"
+
+static NO_COPY UINT timer_active = 0;
+static NO_COPY struct itimerval itv;
+static NO_COPY DWORD start_time;
+static NO_COPY HWND ourhwnd = NULL;
+
+static LRESULT CALLBACK
+WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+#ifndef NOSTRACE
+ strace.wm (uMsg, wParam, lParam);
+#endif
+ switch (uMsg)
+ {
+ case WM_PAINT:
+ return 0;
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ return 0;
+ case WM_TIMER:
+ if (wParam == timer_active)
+ {
+ UINT elapse = itv.it_interval.tv_sec * 1000 +
+ itv.it_interval.tv_usec / 1000;
+ KillTimer (hwnd, timer_active);
+ if (!elapse)
+ {
+ timer_active = 0;
+ }
+ else
+ {
+ timer_active = SetTimer (hwnd, 1, elapse, NULL);
+ start_time = GetTickCount ();
+ itv.it_value = itv.it_interval;
+ }
+ raise (SIGALRM);
+ }
+ return 0;
+ case WM_ASYNCIO:
+ if (WSAGETSELECTEVENT (lParam) == FD_OOB)
+ raise (SIGURG);
+ else
+ raise (SIGIO);
+ return 0;
+ default:
+ return DefWindowProc (hwnd, uMsg, wParam, lParam);
+ }
+}
+
+static HANDLE window_started;
+
+static DWORD WINAPI
+Winmain (VOID *)
+{
+ MSG msg;
+ WNDCLASS wc;
+ static NO_COPY char classname[] = "CygwinWndClass";
+
+ /* Register the window class for the main window. */
+
+ wc.style = 0;
+ wc.lpfnWndProc = (WNDPROC) WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = user_data->hmodule;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = classname;
+
+ if (!RegisterClass (&wc))
+ {
+ system_printf ("Cannot register window class");
+ return FALSE;
+ }
+
+ /* Create hidden window. */
+ ourhwnd = CreateWindow (classname, classname, WS_POPUP, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ (HWND) NULL, (HMENU) NULL, user_data->hmodule,
+ (LPVOID) NULL);
+
+ SetEvent (window_started);
+
+ if (!ourhwnd)
+ {
+ system_printf ("Cannot create window");
+ return FALSE;
+ }
+
+ /* Start the message loop. */
+
+ while (GetMessage (&msg, ourhwnd, 0, 0) == TRUE)
+ DispatchMessage (&msg);
+
+ ExitThread (0);
+}
+
+HWND __stdcall
+gethwnd ()
+{
+ if (ourhwnd != NULL)
+ return ourhwnd;
+
+ cygthread *h;
+
+ window_started = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+ h = new cygthread (Winmain, NULL, "win");
+ h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
+ WaitForSingleObject (window_started, INFINITE);
+ CloseHandle (window_started);
+ h->zap_h ();
+ return ourhwnd;
+}
+
+extern "C" int
+setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue)
+{
+ UINT elapse;
+
+ if (which != ITIMER_REAL)
+ {
+ set_errno (ENOSYS);
+ return -1;
+ }
+ /* Check if we will wrap */
+ if (itv.it_value.tv_sec >= (long) (UINT_MAX / 1000))
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (timer_active)
+ {
+ KillTimer (gethwnd (), timer_active);
+ timer_active = 0;
+ }
+ if (oldvalue)
+ *oldvalue = itv;
+ if (value == NULL)
+ {
+ set_errno (EFAULT);
+ return -1;
+ }
+ itv = *value;
+ elapse = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000;
+ if (elapse == 0)
+ if (itv.it_value.tv_usec)
+ elapse = 1;
+ else
+ return 0;
+ if (!(timer_active = SetTimer (gethwnd (), 1, elapse, NULL)))
+ {
+ __seterrno ();
+ return -1;
+ }
+ start_time = GetTickCount ();
+ return 0;
+}
+
+extern "C" int
+getitimer (int which, struct itimerval *value)
+{
+ UINT elapse, val;
+
+ if (which != ITIMER_REAL)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (value == NULL)
+ {
+ set_errno (EFAULT);
+ return -1;
+ }
+ *value = itv;
+ if (!timer_active)
+ {
+ value->it_value.tv_sec = 0;
+ value->it_value.tv_usec = 0;
+ return 0;
+ }
+ elapse = GetTickCount () - start_time;
+ val = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000;
+ val -= elapse;
+ value->it_value.tv_sec = val / 1000;
+ value->it_value.tv_usec = val % 1000;
+ return 0;
+}
+
+extern "C" unsigned int
+alarm (unsigned int seconds)
+{
+ int ret;
+ struct itimerval newt, oldt;
+
+ newt.it_value.tv_sec = seconds;
+ newt.it_value.tv_usec = 0;
+ newt.it_interval.tv_sec = 0;
+ newt.it_interval.tv_usec = 0;
+ setitimer (ITIMER_REAL, &newt, &oldt);
+ ret = oldt.it_value.tv_sec;
+ if (ret == 0 && oldt.it_value.tv_usec)
+ ret = 1;
+ return ret;
+}
+
+extern "C" useconds_t
+ualarm (useconds_t value, useconds_t interval)
+{
+ struct itimerval timer, otimer;
+
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = value;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = interval;
+
+ if (setitimer (ITIMER_REAL, &timer, &otimer) < 0)
+ return (u_int)-1;
+
+ return (otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec;
+}
+
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 092f502fc9b..fc9de77a25c 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -98,6 +98,8 @@ extern int dynamically_loaded;
extern int cygserver_running;
+#define _MT_SAFE // DELTEME someday
+
#define TITLESIZE 1024
/* status bit manipulation */
@@ -197,7 +199,6 @@ extern int cygwin_finished_initializing;
void __stdcall set_std_handle (int);
int __stdcall writable_directory (const char *file);
int __stdcall stat_dev (DWORD, int, unsigned long, struct __stat64 *);
-extern BOOL allow_ntsec;
__ino64_t __stdcall hash_path_name (__ino64_t hash, const char *name) __attribute__ ((regparm(2)));
void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2)));
@@ -292,7 +293,7 @@ extern SYSTEM_INFO system_info;
/* The title on program start. */
extern char *old_title;
-extern BOOL display_title;
+extern bool display_title;
extern HANDLE hMainThread;
extern HANDLE hMainProc;