summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog3816
-rw-r--r--winsup/cygwin/Makefile.in259
-rw-r--r--winsup/cygwin/autoload.cc494
-rwxr-xr-xwinsup/cygwin/cygserver.cc546
-rwxr-xr-xwinsup/cygwin/cygserver_client.cc225
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc530
-rw-r--r--winsup/cygwin/cygserver_shm.h80
-rwxr-xr-xwinsup/cygwin/cygserver_transport.cc154
-rwxr-xr-xwinsup/cygwin/cygserver_transport_pipes.cc195
-rw-r--r--winsup/cygwin/cygwin.din1226
-rw-r--r--winsup/cygwin/dcrt0.cc1023
-rw-r--r--winsup/cygwin/fhandler.h1091
-rw-r--r--winsup/cygwin/fhandler_tty.cc1254
-rw-r--r--winsup/cygwin/fork.cc751
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver.h126
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver_transport.h53
-rw-r--r--winsup/cygwin/include/sys/ipc.h52
-rw-r--r--winsup/cygwin/include/sys/shm.h89
-rw-r--r--winsup/cygwin/ipc.cc39
-rw-r--r--winsup/cygwin/pinfo.h208
-rw-r--r--winsup/cygwin/security.h208
-rw-r--r--winsup/cygwin/shm.cc446
-rw-r--r--winsup/cygwin/tty.cc447
-rw-r--r--winsup/cygwin/winsup.h261
24 files changed, 13573 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
new file mode 100644
index 00000000000..a669828e7b0
--- /dev/null
+++ b/winsup/cygwin/ChangeLog
@@ -0,0 +1,3816 @@
+Tue Sep 25 16:22:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * autoload.cc: Add dynamic load statement for 'ImpersonateNamedPipeClient'.
+ * Makefile.in: Add new object files, and build instructions for cygserver.exe.
+ * cygwin.din: Export ftok, shmat, shmctl and shmget.
+ * dcrt0.cc: Additional includes for cygserver support.
+ (dll_crt0_1): Initialise the cygserver client.
+ * fhandler.h (fhandler_tty): New method cygserver_attach_tty.
+ * fhandler_tty.cc: Additional includes for cygserver support.
+ (fhandler_tty_slave::open): Attempt to use the cygserver when obtaining
+ handles from the parent process. On failure or 9x use the current method.
+ (fhandler_tty_slave::cygserver_attach_tty): New function.
+ * fork.cc (fork_child): Fixup shm memory mapped areas.
+ * pinfo.h: Declare fixup_shms_after_fork().
+ * security.h: Declare alloc_sd().
+ * tty.cc: Additonal includes to support cygserver.
+ (tty::common_init): Don't allow others to open us if the cygserver is running.
+ * winsup.h: Declare cygserver_running.
+
+Mon Sep 24 18:46:39 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * select.cc (peek_pipe): Only grab mutex when we actually got something
+ from the pipe.
+
+Mon Sep 24 17:41:03 2001 Christopher Faylor <cgf@redhat.com>
+
+ * fhandler.h (fhandler_pipe::hit_eof): New method.
+ (writepipe_exists): New class element.
+ (orig_pid): Ditto.
+ (id): Ditto.
+ (is_slow): Eliminate.
+ * pipe.cc (fhandler_pipe::set_close_on_exec): Set inheritance on
+ writepipe_exists, if it exists.
+ (fhandler_pipe::hit_eof): New method, modelled after tty.
+ (fhandler_pipe::dup): Duplicate writepipe_exists, if it exists.
+ (make_pipe): Set up a dummy event for pipes on windows 9x. The
+ nonexistence of this event means that the write side of the
+ pipe has closed.
+ (_dup): Move to syscalls.cc
+ (_dup2): Ditto.
+
+ * dtable.cc (dtable::build_fhandler): Fill out set_names here, if
+ appropriate.
+ * syscalls.cc (_open): Call set_names in build_fhandler.
+
+
+Sun Sep 23 16:55:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (_open): Set name in fhandler object after successful
+ creation.
+ (stat_dev): Set device type to block device in FH_FLOPPY case.
+
+Sun Sep 23 11:15:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dtable.cc (dtable::build_fhandler): Initialize unit when using
+ optional path_conv argument.
+
+Sat Sep 22 17:33:45 2001 Christopher Faylor <cgf@cygnus.com>
+ Corinna Vinschen <corinna@vinschen.de>
+
+ * dtable.cc (dtable::build_fhandler): Accept an optional path_conv
+ argument. If available, use this to calculate path name and device
+ number.
+ * dtable.h (dtable): Reflect above change.
+ * fhandler.h (fhandler_base): Declare virtual method which accepts
+ path_conv rather than path string as first argument.
+ * fhandler.cc (fhandler_base::open): Define above new method.
+ * syscalls.cc (_open): Set aside a path_conv variable for use in
+ build_fhandler and subsequent call to open.
+
+Sat Sep 22 12:44:57 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (setup_handler): Always relinquish lock after we've
+ interrupted.
+ * fhandler.cc: Move pipe methods to pipe.cc.
+ * fhandler.h (fhandler_pipe): Add new methods.
+ * fork.cc (sync_with_parent): Make error messages more informative.
+ * pipe.cc (fhandler_pipe::fhandler_pipe): Move here from fhandler.cc.
+ (fhandler_pipe::lseek): Ditto.
+ (fhandler_pipe::set_close_on_exec): New method.
+ (fhandler_pipe::read): Ditto.
+ (fhandler_pipe::close): Ditto.
+ (fhandler_pipe::dup): Ditto.
+ (make_pipe): Create the guard mutex on the read side of the pipe.
+ * select.cc (peek_pipe): Use guard_mutex to discover if we have the
+ right to read on this pipe.
+ (fhandler_pipe::readh_for_read): Pass the read pipe guard mutex to
+ peek_pipe.
+ * syscalls.cc (_read): Always detect signal catchers, for now.
+
+ * debug.cc (makethread): Eliminate hack to make thread inheritable.
+ * sigproc.cc (subproc_init): Don't use hack to make thread inheritable.
+
+Thu Sep 20 16:48:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_base::set_inheritance): Just use
+ DUPLICATE_CLOSE_SOURCE to change inheritance. Eliminate all other
+ logic dealing with closed handles.
+ * fhandler.h (fhandler_base::set_inheritance): Reflect above change.
+ * fhandler_tty.cc (fhandler_tty_common::set_close_on_exec): Ditto.
+
+Thu Sep 20 13:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_socket.cc (fhandler_socket::fixup_after_exec): Close
+ socket only when not using Winsock2.
+
+Thu Sep 20 13:20:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (fhandler_socket::fixup_after_exec): Remove inline
+ implementation.
+ (fhandler_dev_raw::fixup_after_exec): Ditto.
+ * fhandler_raw.cc (fhandler_dev_raw::fixup_after_fork): Don't
+ duplicate buffer on fork to avoid memory leak.
+ (fhandler_dev_raw::fixup_after_exec): New implementation equal to
+ former fixup_after_fork() implementation.
+ * fhandler_socket.cc (fhandler_socket::fixup_after_fork): Do
+ nothing when not using Winsock2.
+ (fhandler_socket::fixup_after_exec): New implementation.
+ (fhandler_socket::set_close_on_exec): Never call set_inheritance().
+
+Thu Sep 20 9:55:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_base::set_inheritance): If available,
+ use SetHandleInformation() to set inheritance.
+ * wincap.cc: Set flag has_set_handle_information_on_console_handles
+ appropriately.
+ * wincap.h: Add flag has_set_handle_information_on_console_handles.
+
+Wed Sep 19 12:24:09 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * lib/getopt.c (__progname): Don't declare if not compiling for cygwin.
+
+Wed Sep 19 18:07:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * lib/getopt.c (getopt_long): Avoid compiler warning.
+
+Wed Sep 19 11:52:42 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * lib/getopt.c: Use __progname==__argv[0] when not compiling for cygwin.
+
+ * scandir.cc (scandir): Use correct default when compar == NULL.
+
+Wed Sep 19 17:49:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_socket.cc (fhandler_socket::fhandler_socket): Revert
+ memory allocation to use cmalloc again.
+
+Tue Sep 18 21:04:26 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din (__argv): Export.
+ (__argc): Ditto.
+ (__progname): Ditto.
+ * include/getopt.h (getopt_long): constify arguments.
+ * lib/getopt.c: Import new file from NetBSD.
+
+Tue Sep 18 18:21:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Don't reuse anonymous memory in MAP_FIXED case.
+
+Mon Sep 17 17:29:25 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/io.h: Add access declaration.
+
+Mon Sep 17 14:04:27 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (rmdir): Set cwd to some other location if attempting to
+ rmdir current working directory.
+
+Sun Sep 16 23:04:31 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dtable.h (not_open): Assure inline.
+ * fhandler.h (operator []): Make const.
+
+Sun Sep 16 23:02:57 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * sync.cc (muto::~muto): Fix typo which stopped muto event handle from
+ ever being closed.
+
+2001-09-16 Egor Duda <deo@logos-m.ru>
+
+ * path.cc (symlink): Check arguments for validity.
+ (getcwd): Ditto.
+ * syscalls.cc (ftruncate): Ditto.
+ * times.cc (times): Ditto.
+ * uname.cc (uname): Ditto.
+
+Sat Sep 15 22:54:49 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * net.cc (dup_servent_ptr): Detect old Windows 95 misaligned structure
+ and realign appropriately.
+
+Sat Sep 15 00:28:40 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * Makefile.in: Generate libcygwin.a during the link pass rather than as
+ a separate dlltool step.
+ * dcrt0.cc (_dll_crt0): pppid_handle could be NULL. Don't close it if
+ so.
+
+Fri Sep 14 20:48:18 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dcrt0.cc (dll_crt0_1): Create vfork main storage here so that it can
+ be queried in waitsig later.
+ * sigproc.cc (wait_sig): Don't deliver a signal if in a vfork.
+ * sigproc.h (sigframe::init): New method.
+ (sigframe): Use init.
+ * perthread.h: Declare main_vfork.
+ * fork.cc (vfork): Deliver all signals on parent return from vfork.
+
+Fri Sep 14 10:21:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dcrt0.cc (_dll_crt0()): Don't call wincap.init() here.
+
+Fri Sep 14 00:37:54 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fork.cc (vfork): Avoid recursive vforks.
+
+Fri Sep 14 00:18:52 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.h (fhandler_pipe::is_slow): Return true only if pipes are
+ reliable (i.e., not Win9x).
+ * wincap.cc: Make statics NO_COPY to avoid fork overhead.
+
+Thu Sep 13 23:01:00 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * grp.cc (read_etc_group): Just reuse group_buf storage for subsequent
+ reread of /etc/group.
+ * passwd.cc (read_etc_passwd): Just reuse passwd_buf storage for
+ subsequent reread of /etc/passwd.
+
+Thu Sep 13 20:46:05 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (dup_now): New function.
+ (cygheap_setup_for_child): Accept new argument controlling whether to
+ delay copying of cygheap to shared memory region.
+ (cygheap_setup_for_child_cleanup): Accept new arguments controlling
+ whether to copy cygheap at this point.
+ * cygheap.h: Reflect above changes.
+ * fork.cc (fork_parent): Break copying of cygheap into two parts when
+ fork_fixup is required so that the child can see the parent's changes.
+ (vfork): Do stack cleanup prior to forcing a fork error.
+ * spawn.cc (spawn_guts): Ditto.
+
+Thu Sep 13 17:14:59 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (ccalloc): Pass correct length to creturn so that
+ cygheap_max is correctly calculated.
+
+Wed Sep 12 21:06:38 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sync.cc (muto::acquire): Fix while/if typo.
+
+Wed Sep 12 23:06:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * wincap.cc (wincapc::init): Simplify W2K/XP case.
+
+Wed Sep 12 23:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * wincap.cc (wincapc::init): Set os name to "NT" on XP, too.
+
+Wed Sep 12 19:00:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in: Build wincap.o.
+ * wincap.cc: New file.
+ * wincap.h: Ditto.
+ * autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
+ * dcrt0.cc (os_being_run): Eliminated.
+ (osname): Ditto.
+ (iswinnt): Ditto.
+ (set_os_type): Ditto.
+ (dll_crt0_1): Call wincap.init() instead of set_os_type().
+ (_dll_crt0): Ditto.
+ * environ.cc (set_chunksize): New function.
+ (parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
+ * fork.cc (chunksize): Eliminated. Moved to be member of wincap.
+ * host_dependent.h: Removed.
+ * syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
+ * cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
+ environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
+ fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
+ security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
+ times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
+ capability check throughout.
+ * winsup.h: Include wincap.h. Eliminate extern declarations of
+ `os_being_run' and `iswinnt'. Eliminate `os_type" definition.
+ * include/cygwin/version.h: Bump version to 1.3.4.
+
+Wed Sep 12 01:03:36 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (call_signal_handler_now): Add additional guard against
+ inappropriately calling signal handler.
+ * syscalls.cc (_read): Reset errno if not exiting due to signal.
+
+Wed Sep 12 13:03:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * autoload.cc (LoadDLLfuncEx): Auto load TryEnterCriticalSection - it's
+ an NT only call.
+ * thread.cc (pthread_cond::TimedWait): Use critical sections for NT.
+ (pthread_cond::fixup_after_fork): Don't detect bad apps.
+ (pthread_mutex::pthread_mutex): Use critical sections for NT.
+ (pthread_mutex::~pthread_mutex): Ditto.
+ (pthread_mutex::Lock): Ditto.
+ (pthread_mutex::TryLock): Ditto.
+ (pthread_mutex::UnLock): Ditto.
+ (pthread_mutex::fixup_after_fork): Ditto. Also do not detect bad apps.
+ (__pthread_mutex_trylock): Move WIN32 specific test into the class
+ method.
+ (__pthread_mutex_destroy): Prevent dereferencing passed pointer without
+ valid address.
+ * thread.h (pthread_mutex): Use critical sections for NT.
+
+Tue Sep 11 21:55:37 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.h (sigframe::unregister): Return true/false whether this
+ frame is capable of responding to signals.
+ * exceptions.cc (sigframe::call_signal_handler): Don't call signal
+ handler if it is not armed for this thread.
+
+Tue Sep 11 11:23:10 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din: Remove cygwin_getshared.
+ * shared.cc: Ditto.
+ * include/cygwin/version.h: Bump API minor number.
+
+Tue Sep 11 11:14:11 2001 Dmitry Timoshkov <dmitry@baikal.ru>
+
+ * dtable.cc (dtable::build_fhandler): Fix incorrect test for socket.
+
+Tue Sep 11 21:22:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc (pthread_cond::~pthread_cond): Fix incorrect use of
+ InterlockExchangePointer.
+ (pthread_mutex::~pthread_mutex): Ditto.
+ (semaphore::~semaphore): Ditto.
+
+Tue Sep 11 18:15:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * dcrt0.cc (cygwin_finished_initializing): Copy _mtinterf on fork.
+ * fork.cc (fork_child): Fixup thread-related structures after fork.
+ * thread.cc (MTinterface::Init): Initialise the new mutex, condition
+ and semaphore lists.
+ (MTinterface::fixup_after_fork): Iterate through each list and fixup
+ the objects.
+ (pthread_cond::pthread_cond): Add this to the condition list.
+ (pthread_cond::~pthread_cond): Remove this from the condition list.
+ (pthread_cond::fixup_after_fork): Recreate as best we can the pre-fork
+ state.
+ (pthread_mutex::pthread_mutex): Add this to the mutex list.
+ (pthread_mutex::~pthread_mutex): Remove this from the mutex list.
+ (pthread_mutex::fixup_after_fork): Recreate as best we can the pre-fork
+ state.
+ (semaphore::semaphore): Store the initial value, and add this to the
+ semaphore list.
+ (semaphore::~semaphore): Remove this from the semaphore list.
+ (semaphore::Post): Increment the current semaphore value.
+ (semaphore::TryWait): Decrement the current semaphore value.
+ (semaphore::Wait): Ditto.
+ (semaphore::fixup_after_fork): Recreate the pre-fork state as best we
+ can.
+ * thread.h (pthread_mutex): New members to allow fixup_after_fork.
+ (pthread_cond): Ditto.
+ (semaphore): Ditto.
+ (MTinterface): New list heads for tracking conds and semaphores.
+
+Sun Sep 9 22:11:27 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dtable.cc (dtable::fixup_after_fork): Use SetStdHandle appropriately
+ on inherited fds.
+
+Sun Sep 9 20:09:11 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.cc (NZOMBIES): Reduce substantially to minimize memory use.
+
+Mon Sep 10 08:28:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.h (MT_Interface): Remove pshared mutex array. Add a
+ threadsafe list for mutex tracking (for fixup after fork).
+ * thread.cc (MTInterface::Init): Remove pshared mutex array.
+ (pthread_mutex::pthread_mutex): Remove pshared mutex functionality.
+ Fail with EINVAL on attempts to use pshared functionality.
+ (__pthread_mutex_getpshared): Remove.
+ (__pthread_cond_timedwait): Remove pshared mutex functionality.
+ (__pthread_cond_wait): Ditto.
+ (__pthread_mutex_init): Ditto.
+ (__pthread_mutex_getprioceiling): Ditto.
+ (__pthread_mutex_lock): Ditto.
+ (__pthread_mutex_trylock): Ditto.
+ (__pthread_mutex_unlock): Ditto.
+ (__pthread_mutex_destroy): Ditto.
+ (__pthread_mutex_setprioceiling): Ditto.
+ (__pthread_mutexattr_setpshared): Ditto.
+
+Sun Sep 9 23:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * pwdgrp.h (pwdgrp_check::set_last_modified): Call GetFileTime()
+ instead of GetFileInformationByHandle().
+
+Sun Sep 9 15:59:53 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * heap.h (inheap): Rewrite macro to accomodate removal of brk macros
+ below.
+
+Sun Sep 9 15:02:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (cygheap_fixup_in_child): Clear cygheap->base so that heap
+ is not forced to start at the same place in execed process.
+ * heap.cc: Remove brk* macros for clarity throughout.
+ * heap.h: Ditto.
+ * shared.cc (shared_info::initialize): Move heap_chunk test into
+ heap_chunk_size().
+ (heap_chunk_size): Check for chunk size here. Don't go to registry if
+ heap_chunk_in_mb is already set.
+
+ * smallprint.c (console_printf): Add Windows 95 concessions.
+
+Sun Sep 9 13:01:06 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * child_info.h (PROC_MAGIC): Bump magic number.
+
+Sun Sep 9 18:36:00 2001 Corinna Vinschen <corinna@vinschen.de>
+ Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (init_cygheap::etc_changed): New method to signal
+ a change in /etc.
+ * cygheap.h (struct init_cygheap): Add member `etc_changed_h'
+ and method `etc_changed'.
+ * grp.cc (enum grp_state): Eliminate.
+ (class grp_check): Ditto.
+ (group_state): Define as `class pwdgrp_check'.
+ (parse_grp): Remeber path and modification time of /etc/group file.
+ * passwd.cc (enum_pwd_state): Eliminate.
+ (class pwd_check): Ditto.
+ (passwd_state): Define as `class pwdgrp_check'.
+ (read_etc_passwd): Remember path and modification time of /etc/passwd
+ file.
+ * pwdgrp.h: New file.
+ (enum pwdgrp_state): Substitutes `pwd_state' and `grp_state'.
+ (class pwdgrp_check): Substitutes `pwd_check' and `grp_check'.
+
+Sun Sep 9 14:31:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * include/cygwin/version.h: Bump API minor version to 45 according
+ to adding the gamm*_r functions.
+
+Sat Sep 8 23:32:18 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fork.cc (fork_parent): Stop malloc activity while fork is in control
+ of the heap.
+ * sigproc.cc (NZOMBIES): Rename from ZOMBIEMAX for clarity.
+ (zombies): Revert to original behavior. Allocating zombie array
+ resulted in performance hit.
+ * winsup.h: Declare malloc lock routines.
+
+Fri Sep 7 21:35:35 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din: Add gamm*_r function exports.
+
+Fri Sep 7 17:11:11 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.h (init_cygheap): Move heap pointers here.
+ * include/sys/cygwin.h (perprocess): Remove heap pointers.
+ * dcrt0.cc (__cygwin_user_data): Reflect obsolete perprocess stuff.
+ (_dll_crt0): Don't initialize heap pointers.
+ (cygwin_dll_init): Ditto.
+ (release_upto): Use heap pointers from cygheap.
+ * heap.h: Ditto.
+ * fork.cc (fork_parent): Ditto. Don't set heap pointers in ch.
+ (fork_child): Remove obsolete sigproc_fixup_after_fork.
+ * shared.cc (memory_init): Reorganize so that cygheap initialization is
+ called prior to regular heap since regular heap uses cygheap now.
+ * sigproc.cc (proc_subproc): Eliminate zombies allocation.
+ (sigproc_init): Move zombies alloation here. Don't free up array on
+ fork, just reuse it.
+ (sigproc_fixup_after_fork): Eliminate.
+ * sigproc.h: Ditto.
+ * include/cygwin/version.h: Reflect change to perprocess structure.
+
+Fri Sep 7 10:53:34 2001 Jason Tishler <jason@tishler.net>
+
+ * poll.cc (poll): Change implementation to only call select() when no
+ invalid file descriptors are specified.
+
+Fri Sep 7 10:27:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * include/limits.h: Define PIPE_BUF.
+ * syscalls.cc (fpathconf): Use PIPE_BUF instead of numerical constant.
+ (pathconf): Ditto.
+
+Thu Sep 6 20:04:05 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_socket.cc (fhandler_socket::fhandler_socket): Ensure that
+ prot_info_ptr is zeroed for later use.
+
+Thu Sep 6 14:03:49 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (cygheap_fixup_in_child): Don't consider a NULL bucket as
+ a candidate for deletion. It is actually the end of a linked list
+ chain.
+
+ * exceptions.cc (open_stackdumpfile): Default to "unknown" program name
+ if myself->progname hasn't been filled out yet.
+
+Thu Sep 6 01:16:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Move appropriate variables to NO_COPY segment, throughout.
+
+Thu Sep 6 00:40:35 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Remove initialization of static or global values to zero, throughout.
+ This just needlessly grows the size of the DLL.
+ * tty.cc (tty::alive): Make inuse handle non-inheriting on open, just
+ for thread safety.
+
+Wed Sep 5 23:36:03 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.h (init_cygheap): Move bucket array here from cygheap.cc.
+ * cygheap.cc: Throughout use bucket array from cygheap.
+
+ * sigproc.cc (proc_subproc): Dynamically allocate zombie buffer to save
+ DLL space.
+ (sigproc_fixup_after_fork): Free zombie array after a fork.
+ * sigproc.h (sigproc_fixup_after_fork): Declare.
+
+2001-09-06 Egor Duda <deo@logos-m.ru>
+
+ * dir.cc (mkdir): Expand buffer for security descriptor to 4K to avoid
+ stack corruption.
+ * fhandler.cc (fhandler_base::open): Ditto.
+ * path.cc (symlink): Ditto.
+
+Wed Sep 5 21:35:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * winver.rc: Change copyright to include 2001.
+
+Wed Sep 5 12:12:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_floppy.cc (fhandler_floppy::lseek): Remove iswinnt check.
+
+Wed Sep 5 11:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_socket.cc (fhandler_socket::close): Change 2MSL value
+ according to MSDN.
+
+Wed Sep 5 10:14:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (cygwin_connect): Add WSAEALREADY and WSAEINVAL handling
+ for non-blocking sockets.
+
+Tue Sep 4 22:42:13 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (ctrl_c_handler): Only send SIGINT when we have a
+ controlling terminal and we are the head of the process group.
+
+Tue Sep 4 16:48:14 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * thread.cc (InterlockedExchangePointer): Don't define if it already
+ exists.
+
+Tue Sep 4 22:14:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * uname.cc (uname): Eliminate os specific retrieving of x86
+ processor type.
+
+2001-09-04 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * fhandler_console.cc (fhandler_console::char_command): Save the cursor
+ position relative to the top of the window.
+ * fhandler_cc (fhandler_console::write): Ditto.
+
+Mon Sep 3 21:06:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (opendir): Write version information to __d_dirent->d_version.
+
+Mon Sep 3 18:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygwin.din: Add `dirfd'.
+ * dir.cc (dirfd): New function.
+ (opendir): Open a directory file descriptor and save it in
+ __d_dirent->d_fd.
+ (closedir): Close directory file descriptor.
+ * include/cygwin/version.h: Bump API minor version to 44.
+
+Sun Sep 2 22:09:31 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * child_info.h: Modify magic number.
+ * dcrt0.cc (_cygwin_testing): Define.
+ (_dll_crt0): Set _cygwin_testing if CYGWIN_TESTING environment variable
+ exists. Don't issue "conflicting versions" error if _cygwin_testing is
+ true.
+ * shared.cc (shared_name): Use _cygwin_testing global rather than
+ testing the environment.
+ * syscalls.cc (_write): Remove debugging info.
+
+Sat Sep 1 01:37:13 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * tty.cc (tty::create_inuse): Eliminate unneeded argument.
+ * tty.h: Reflect above change.
+ * fhandler_tty.cc: Reflect argument reduction in tty::create_inuse,
+ throughout. Always make inuse inheritable.
+
+Sat Sep 1 01:10:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * debug.cc (mark_closed): Rename from debug_mark_closed and make
+ static.
+ (setclexec_pid): New function for marking saved handle as
+ close-on-exec.
+ (delete_handle): New function.
+ (debug_fixup_after_fork): New function.
+ * debug.h: Declare new functions, remove obsolete ones.
+ * fork.cc (debug_fixup_after_fork): Call to cleanup close-on-exec
+ handles.
+
+ * fhandler.cc (fhandler_disk_file::close): Minor reorg.
+ (fhandler_base::set_inheritance): Set flag appropriately for debugging
+ when close-on-exec so forked process can delete closed handles.
+ * tty.h (open_output_mutex): Eliminate unneeded argument.
+ (open_input_mutex): Ditto.
+ * fhandler_tty.cc (fhandler_tty_slave::open): reflect open_*_mutex
+ argument changes.
+ * fhandler.h (fhandler_socket): Make saw_shutdown_* functions type
+ bool.
+ * tty.cc (tty::get_event): Eliminate unneeded argument.
+ (tty::common_init): Reflect change to get_event. Events should always
+ be inherited.
+
+Fri Aug 31 21:39:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (create_token): Change initialization of `exp' to comply
+ with new LARGE_INTEGER definition in winnt.h.
+
+Fri Aug 31 13:58:51 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.sc: Revert to previous NO_COPY behavior.
+ * winsup.h: Ditto.
+ * sigproc.cc: Ditto.
+ * autoload.cc: Ditto.
+
+Fri Aug 31 00:56:26 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.sc: New file -- linker script for building cygwin DLL.
+ * Makefile.in: Use linker script to control location of cygheap.
+ * cygheap.cc (buckets): Make static.
+ (init_cheap): Remove special iswinnt handling. Allocate cygheap at a
+ fixed location. Display more info when allocation fails.
+ (cygheap_fixup_in_child): Try harder to move cygheap to correct
+ location. Display more info when allocation fails.
+ * fhandler.h (fhandler_socket): Add macros for tracking socket shutdown
+ state.
+ * net.cc (cygwin_shutdown): Set appropriate shutdown value for future
+ use.
+ * select.cc (select_stuff::cleanup): New method.
+ (cygwin_select): Call cleanup explicitly to avoid a race.
+ (select_stuff:~select_stuff): Call cleanup chain via cleanup method.
+ (fhandler_socket::select_read): Set *_ready when shutdown has been
+ called on the socket.
+ (fhandler_socket::select_write): Ditto.
+ (fhandler_socket::select_except): Ditto.
+
+ * winsup.h: Move NO_COPY to "COMMON" section.
+ * autoload.cc (wsock_started): Avoid initializing NO_COPY value.
+ * sigproc.cc: Remove initialization from NO_COPY variables.
+ (sigproc_init): Initialize sig_loop_wait here, rather than via
+ initialization.
+ (subproc_init): Initialize proc_loop_wait here, rather than via
+ initialization.
+
+Thu Aug 30 10:19:00 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * select.cc (select_read): Add setting read_ready flag.
+ (select_write): Add setting write_ready flag.
+
+Wed Aug 29 00:40:42 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Avoid splitting off leading '/' in path
+ component when building a symlink.
+
+Wed Aug 29 0:45:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * resource.cc (getrlimit): Return actual values on RLIMIT_STACK.
+
+Tue Aug 28 16:37:17 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dir.cc (rmdir): Report ENOENT when file doesn't exist rather than
+ ENOTDIR.
+
+Mon Aug 27 11:58:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * select.cc (cygwin_select): Ensure that arguments are zeroed on
+ timeout.
+ (select_stuff::wait): Ditto.
+
+2001-08-24 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * syscalls.cc (check_tty_fds): New function. Check whether there is a
+ fd referring to pty slave.
+ (setsid): Don't detach console if the process has a pty slave.
+
+Fri Aug 24 8:54:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (free_addr_list): Add define for symmetry.
+ (free_hostent_ptr): Use free_addr_list to free h_addr_list element.
+
+Thu Aug 23 16:00:09 2001 Jason Tishler <jason@tishler.net>
+
+ * net.cc (dup_addr_list): New static function.
+ (dup_hostent_ptr): Use dup_addr_list instead of dup_char_list in order
+ to handle embedded null characters.
+
+Wed Aug 22 22:23:14 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dtable.cc (dtable::dup2): Allow extension of fd table by dup2.
+ * syscalls.cc: Minor code cleanup.
+ (fpathconf): Check for bad fd before doing anything else.
+ * termios.cc (tcsetattr): Don't convert to new termios if bad fd.
+ (tcgetattr): Minor debugging tweak.
+
+Wed Aug 22 23:41:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (cygwin_inet_ntoa): Rearrange previous patch to use
+ thread local buffer space when compiled thread safe.
+ (cygwin_getprotobyname): Ditto.
+ (cygwin_getprotobynumber): Ditto.
+ (cygwin_getservbyname): Ditto.
+ (cygwin_getservbyport): Ditto.
+ (cygwin_gethostbyname): Ditto.
+ (cygwin_gethostbyaddr): Ditto. Move near to cygwin_gethostbyname.
+ * thread.h (struct _winsup_t): Add pointers for above used buffer space.
+ * passwd.cc (getpwduid): Remove initializing passwd.
+ (setpwent): Ditto.
+ (endpwent): Ditto.
+ (setpassent): Ditto.
+
+Wed Aug 22 13:41:09 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * smallprint.c (console_printf): New function.
+ * dcrt0.cc (dll_crt0_1): Use console_printf for debugging output.
+ * debug.cc (debug_mark_closed): New function.
+ (close_handle): Use debug_mark_closed.
+ * debug.h: Declare new functions.
+ * dtable.cc (dtable::build_fhandler): Remove unneeded extern.
+ * spawn.cc: Cosmetic changes.
+ * winsup.h: Define NO_COPY for C files, too. Declare a global.
+
+Wed Aug 22 17:31:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (free_char_list): New static function.
+ (dup_char_list): Ditto.
+ (free_protoent_ptr): Ditto.
+ (dup_protoent_ptr): Ditto.
+ (free_servent_ptr): Ditto.
+ (dup_servent_ptr): Ditto.
+ (free_hostent_ptr): Ditto.
+ (dup_hostent_ptr): Ditto.
+ (cygwin_inet_ntoa): Use local static buffer to allow propagating of
+ the result to child processes.
+ (cygwin_getprotobyname): Ditto.
+ (cygwin_getprotobynumber): Ditto.
+ (cygwin_getservbyname): Ditto.
+ (cygwin_getservbyport): Ditto.
+ (cygwin_gethostbyname): Ditto.
+ (cygwin_gethostbyaddr): Ditto.
+
+Mon Aug 20 11:56:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (init_cheap): Allocate cygheap in shared memory for Windows NT.
+
+Thu Aug 16 09:38:59 2001 Jason Tishler <jason@tishler.net>
+
+ * fhandler_socket.cc (fhandler_socket::create_secret_event): Relax
+ security of secret_event so AF_UNIX socket clients can connect to
+ servers even if running under a different user account.
+ (fhandler_socket::check_peer_secret_event): Ditto.
+
+Thu Aug 16 16:26:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * resource.cc (getrlimit): Return getdtablesize () as current limit
+ on RLIMIT_NOFILE.
+ * syscalls.cc (getdtablesize): Return OPEN_MAX if current dtable size
+ is less than OPEN_MAX, the current dtable size otherwise.
+ * sysconf.cc (sysconf): Return getdtablesize () on _SC_OPEN_MAX.
+
+Thu Aug 16 16:17:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * resource.cc (getrlimit): Return OPEN_MAX as current limit
+ on RLIMIT_NOFILE.
+ * syscalls.cc (getdtablesize): Return OPEN_MAX.
+ * sysconf.cc (sysconf): Return OPEN_MAX on _SC_OPEN_MAX.
+ * include/limits.h (OPEN_MAX): Define as 256.
+
+Wed Aug 15 12:43:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * times.cc (utimes): Revert previous change. Just open the
+ file using FILE_WRITE_ATTRIBUTES instead of GENERIC_WRITE
+ on NT/W2K.
+
+Wed Aug 15 12:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (set_nt_attribute): Return always -1 in case of
+ a failure.
+ * times.cc (utimes): On NTFS with ntsec ON, change the file's
+ security descriptor temporarily to acquire write access if
+ opening the file failed.
+
+Wed Aug 15 9:42:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_base::is_nonblocking): New method.
+ (fhandler_base::set_nonblocking): Ditto.
+ * fhandler.h (fhandler_base): Declare new methods `is_nonblocking' and
+ `set_nonblocking'.
+ * fhandler_socket.cc (fhandler_socket::ioctl): Use `set_nonblocking'.
+ * fhandler_tty.cc (fhandler_pty_master::process_slave_output):
+ Use `is_nonblocking'.
+ (fhandler_tty_slave::read): Ditto.
+ (fhandler_tty_slave::ioctl): Use `set_nonblocking'.
+ (fhandler_pty_master::ioctl): Ditto.
+ * net.cc (cygwin_sendto): Fallback to winsock 1 functionality
+ in case of nonblocking IO.
+ (cygwin_recvfrom): Ditto.
+ (cygwin_recv): Ditto.
+ (cygwin_send): Ditto.
+ * syscalls.cc (_read): Use `is_nonblocking'.
+
+Tue Aug 14 11:05:26 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump API version.
+
+2001-08-14 Egor Duda <deo@logos-m.ru>
+
+ * spawn.cc (spawn_guts): Enable appropriate privilege before
+ loading user's registry hive.
+
+Mon Aug 13 22:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_base::fcntl): Use new O_NONBLOCK_MASK define.
+ * fhandler.h: Move definitions of O_NOSYMLINK, O_DIROPEN and
+ OLD_O_NDELAY from winsup.h to here. Add O_NONBLOCK_MASK define.
+ * fhandler_socket.cc (fhandler_socket::close): Add hack to allow
+ a graceful shutdown even if shutdown() hasn't been called by the
+ application. Add debug output.
+ (fhandler_socket::ioctl): Set fhandler's NONBLOCK flag according
+ to FIONBIO setting.
+ (fhandler_socket::fcntl): Use new O_NONBLOCK_MASK define. Actually
+ set `request' before using it.
+ * fhandler_tty.cc: Use new O_NONBLOCK_MASK define throughout.
+ (fhandler_tty_slave::ioctl): Set fhandler's NONBLOCK flag according
+ to FIONBIO setting.
+ (fhandler_pty_master::ioctl): Ditto.
+ * net.cc (wsock_event::prepare): Compare WSACreateEvent return code
+ with `WSA_INVALID_EVENT' according to MSDN.
+ * syscalls.cc (_read): Use new O_NONBLOCK_MASK define.
+
+Wed Aug 8 15:24:59 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/wchar.h: Define __need_wint_t.
+
+Wed Aug 8 11:46:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (alloc_sd): Revert to setting inheritance attribute for
+ permissions given to directories. Never set inheritance on NULL ACE.
+
+Tue Aug 7 18:11:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (alloc_sd): Don't set FILE_DELETE_CHILD for group
+ if S_ISVTX attribute is given.
+ * dir.cc (mkdir): Allow immediate setting of S_ISUID, S_ISGID and
+ S_ISVTX attribute.
+ * syscalls.cc (_open): Ditto.
+
+Tue Aug 7 16:24:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (mkdir): Set security attributes correctly for
+ CreateDirectoryA () call if ntsec is on. Don't call
+ set_file_attributes () then.
+ * fhandler.cc (fhandler_base::open): Ditto for CreateFileA () call.
+ * path.cc (symlink): Ditto.
+ * security.cc (set_security_attribute): New function.
+ * security.h: Add declaration for `allow_ntea' and
+ `set_security_attribute'.
+
+Tue Aug 7 10:54:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc (class grp_check): New class. Make `group_state'
+ a member of class grp_check.
+ (read_etc_group): Free former allocated memory on reread.
+ * passwd.cc (class pwd_check): New class Make `passwd_state'
+ a member of class pwd_check.
+ (read_etc_passwd): Free former allocated memory on reread.
+
+Tue Aug 7 01:13:58 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_console.cc (get_tty_stuff): Don't initialize shared memory
+ console area if it is already initialized.
+
+ * fhandler_termios.cc (fhandler_termios::tcsetpgrp): Augment debugging
+ info.
+
+Mon Aug 6 19:58:43 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (cygheap_root::set): Avoid treating '/' specially.
+
+ * fhandler.cc (fhandler_base::fcntl): Only set specific O_NDELAY style
+ flag passed in from application.
+ * fhandler_socket.cc (fhandler_socket::fcntl): Ditto.
+ * fhandler.h: Set constant for future use.
+ * winsup.h: Define OLD_O_NDELAY only for old programs.
+ * include/cygwin/version.h: Define
+ CYGWIN_VERSION_CHECK_FOR_OLD_O_NONBLOCK.
+
+Sat Aug 4 16:52:03 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Throughout, change check for running under Windows NT to 'iswinnt'.
+ * dcrt0.cc (set_os_type): Set 'iswinnt' appropriately.
+ * cygheap.cc (init_cheap): Revert to using VirtualAlloc for allocating
+ cygheap.
+ (cygheap_setup_for_child_cleanup): New function. Standard function to
+ call after calling CreateProcess to cleanup cygheap info passed to
+ child.
+ (cygheap_fixup_in_child): Copy cygheap from shared memory into
+ allocated space under Windows 9x or if can't relocate shared space
+ under NT.
+ * cygheap.h: Declare new function.
+ * spawn.cc (spawn_guts): Use cygheap_fixup_in_child.
+ * fork.cc (fork_parent): Ditto.
+ * winsup.h: Declare iswinnt.
+
+2001-08-04 Egor Duda <deo@logos-m.ru>
+
+ * dtable.cc (dtable::release): Avoid messing with console when
+ closing socket.
+
+Fri Aug 3 14:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (cygwin_accept): Allow NULL peer and len parameters.
+ * include/cygwin/socket.h: Define socklen_t as int.
+
+Fri Aug 3 13:04:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (fchdir): Set the fhandler's path to absolute value to ensure
+ changing to the correct directory even if the fhandler originally
+ points to a relative path.
+
+Thu Aug 2 17:59:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (set_file_attribute): Clean up. Don't call
+ `set_nt_attribute' when ntsec isn't set.
+
+Sat Jul 28 22:30:55 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dcrt0.cc (alloc_stack_hard_way): Make half-hearted attempt to deal
+ with growing stack under Windows 95.
+
+Fri Jul 27 12:36:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * Makefile.in: Add install-lib and install-headers.
+
+Fri Jul 27 12:28:12 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din: Export sys_errlist, sys_nerr.
+ * include/cygwin/version.h: Bump minor version number.
+
+Fri 27 Jul 2001 10:29:00 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (get_user_primary_group): Fix compiler warning.
+ (alloc_sd): Add DELETE permission for user when S_IWUSR is given.
+
+Thu Jul 26 16:43:39 2001 Pieter de Visser <pieterdv@knoware.nl>
+
+ * thread.cc (__pthread_equal): Invert return value so that true is
+ returned when threads are equal.
+
+Thu Jul 26 15:50:38 2001 Charles Wilson <cwilson@ece.gatech.edu>
+ Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din: Export __signgam.
+ * include/cygwin/version.h: Bump minor version number.
+
+Thu Jul 26 15:19:50 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Throughout, reorganize header file inclusion to put security.h prior to
+ fhandler.h.
+ * fhandler.h (fhandler_base::get_inheritance): New method.
+ * fhandler_socket.cc (fhandler_socket::create_secret_event): Use proper
+ close-on-exec inheritance when creating.
+ (fhandler_socket::check_peer_secret_event): Create handle as
+ non-inheritable.
+
+2001-07-25 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * syscalls.cc (setsid): Detach process from its console if the current
+ controlling tty is the console and already closed.
+ * dtable.h (class dtable): Add members to count descriptors referring
+ to the console.
+ * dtable.cc (dtable::dec_console_fds): New function to detach process
+ from its console.
+ (dtable::release): Decrement the counter of console descriptors.
+ (dtable::build_fhandler): Increment it.
+ * exception.cc (ctrl_c_handler): Send SIGTERM to myself when catch
+ CTRL_SHUTDOWN_EVENT.
+
+Tue 24 Jul 2001 02:28:00 PM Trevor Forbes <t4bs@hotmail.com>
+
+ * thread.cc (verifyable_object_isvalid): Don't validate
+ PTHREAD_MUTEX_INITIALIZER pointer as it will cause an exception
+ in IsBadWritePtr() when running GDB.
+
+Wed 25 Jul 2001 23:46:00 Corinna Vinschen <corinna@vinschen.de>
+
+ * localtime.c: Changed whole file to become C++ clean. Rename to
+ localtime.cc.
+ * localtime.cc (tzload): Preserve errno.
+
+Fri 20 Jul 2001 11:15:50 PM EDT Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (cygheap_fixup_in_child): Attempt Win95 workaround.
+ * dtable.cc (dtable::dup_worker): Add debugging output.
+ (dtable::vfork_child_dup): Correctly set close_on_exec.
+ * fhandler.cc (fhandler_base::fork_fixup): Don't mess with handle if
+ there is no need to get it from the parent.
+ * fhandler_tty.cc (fhandler_tty_common::close): Add debugging output.
+
+Fri 20 Jul 2001 09:15:00 Mark Bradshaw <bradshaw@staff.crosswalk.com>
+
+ * dir.cc (readdir): Protect FindNextFileA against INVALID_HANDLE_VALUE.
+
+Wed 18 Jul 2001 01:00:47 PM EDT Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (_cmalloc): Use correct constants for size calculation.
+ * dcrt0.cc (dll_crt0_1): Move uid initialization earlier.
+ * fork.cc (fork_parent): Move cygheap_setup_in_child to just prior to
+ CreateProcess so that all contents of cygheap are copied.
+ * spawn.cc (spawn_guts): Ditto.
+
+Wed 18 Jul 2001 12:54:17 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (get_user_groups): Call Net function with NULL server
+ name under specific error conditions.
+ (is_group_member): Ditto.
+ (get_user_local_groups): Ditto.
+ (get_user_primary_group): Ditto.
+
+Wed 18 Jul 2001 11:56:00 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (_unlink): Explicitly check for non-existant file.
+
+Tue 17 Jul 2001 10:19:00 Corinna Vinschen <corinna@vinschen.de>
+
+ * delqueue.h: Remove obsolete file.
+
+Mon 16 Jul 2001 10:47:17 PM EDT Christopher Faylor <cgf@cygnus.com>
+
+ * child_info.h: Bump magic number.
+ (class child_info): Add an element.
+ * cygheap.cc (init_cheap): Allocate cygwin heap in shared memory area.
+ (cygheap_fixup_in_child): Map cygwin heap, passed from parent via
+ shared memory into correct address.
+ (cygheap_setup_for_child): New function.
+ * cygheap.h: Declare new functions.
+ * dcrt0.cc (dll_crt0_1): Accomodate new cygheap_fixup_in_child
+ arguments. Avoid protecting subproc_ready unless it is spawn/nowait.
+ * fork.cc (fork_parent): Use new cygheap_setup_for_child function to
+ setup cygwin heap info. Close passed cygheap shared memory handle.
+ * spawn.cc (spawn_guts): Ditto. Also, reorganize to avoid
+ synchronization between parent and child in non-P_OVERLAY case.
+ * sigproc.cc (wait_sig): Only signal subproc_ready when execing.
+
+Mon 16 Jul 2001 15:21:00 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc: Add missing Copyright date 2001.
+
+Mon 16 Jul 2001 00:11:00 Corinna Vinschen <corinna@vinschen.de>
+
+ Change well_known_admin_sid to well_known_admins_sid throughout.
+ * sec_acl.cc (setacl): Never set DELETE permission. Set
+ FILE_DELETE_CHILD only on readable and executable directories.
+ * sec_helper.cc: Add constructor for `well_known_null_sid'.
+ * security.cc (get_nt_attribute): Set S_ISVTX for directories if
+ FILE_WRITE_DATA and FILE_EXECUTE but not FILE_DELETE_CHILD is set.
+ Add evaluation of S_ISVTX, S_ISGID and S_ISUID from NULL ACE.
+ (alloc_sd): Never set DELETE permission. Set FILE_DELETE_CHILD
+ only on readable and executable directories.
+ Add creation of NULL ACE for S_ISVTX, S_ISGID and S_ISUID permissions.
+ * security.h: Add extern declaration for `well_known_null_sid'.
+
+Fri 13 Jul 2001 08:08:49 PM EDT Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (stat_worker): Simplify previous change.
+
+Fri Jul 13 13:13:09 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_unlink): Correct (?) logic which determines when
+ to report an access violation and when to queue file for eventual
+ deletion.
+ (stat_worker): Check for invalid buf argument.
+
+Tue Jul 10 23:01:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (fhandler_disk_file::mmap): Try to open file mappings
+ by a unified name when running under 9x/ME. If that failes, create
+ the file mapping using the unified name.
+
+Mon Jul 9 10:43:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * uinfo.cc (internal_getlogin): Add pointer check.
+
+Mon Jul 9 10:05:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (alloc_sd): Don't set inheritance attribute for
+ permissions given to directories.
+
+Thu Jun 28 22:19:08 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_dsp.cc (fhandler_dev_dsp::ioctl): Return 0 for success.
+
+Wed Jun 27 22:19:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Add signal protection here since
+ retrieving info about remote shares can take some time.
+
+Wed Jun 27 23:30:00 2001 Robert Collins <rbtcollins@hotmail.com>
+ Christopher Faylor <cgf@cygnus.com>
+
+ Change check_null_empty_path* to check_null_empty_str* throughout.
+ * path.h (check_null_empty_str_errno): Convert to a function prototype.
+ * path.cc (check_null_empty_str): Move to miscfuncs.cc.
+ * miscfuncs.cc (check_null_empty_str_errno): New function.
+ (__check_null_invalid_struct): Ditto.
+ (__check_null_invalid_struct_errno): Ditto.
+ (check_null_empty_str): Change from VirtualQuery to IsBadWritePtr.
+ * thread.cc (check_valid_pointer): Ditto.
+ * resource.cc (getrlimit): Use check_null_invalid_struct macro for
+ checking validity of pointer.
+ (setrlimit): Ditto.
+
+Tue Jun 26 16:59:16 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_disk_file::fstat): Don't rely on exactly 3
+ characters being read for executable test since we could be checking
+ for less than that.
+ * syscalls.cc (stat_worker): Try opening the file the "correct" way
+ first so that #! processing can potentially happen. If that fails,
+ then use "query open" method.
+
+ * spawn.cc (spawn_guts): Delay processing of signal until after we've
+ notified parent about reparenting.
+
+Tue Jun 26 10:47:24 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * mmap.cc: Clean up *ResourceLock calls throughout.
+
+Tue Jun 26 22:10:00 2001 Robert Collins rbtcollins@hotmail.com
+
+ * thread.cc (pthread_cond::TimedWait): Check for WAIT_TIMEOUT as well
+ as WAIT_ABANDONED.
+ (__pthread_cond_timedwait): Calculate a relative wait from the abstime
+ parameter.
+
+Sun Jun 24 17:38:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (interrupt_setup): Move actions from setup_handler to
+ here.
+ (setup_handler): Move actions after a successful interrupt to
+ interrupt_setup.
+ * fork.cc (vfork): Augment debugging output.
+ * sigproc.cc (proc_subproc): Ditto.
+ * spawn.cc (spawn_guts): Ditto. Correctly fill out progname when spawn
+ NO_WAIT. Call signal handler when a signal arrives.
+ * sigproc.h: Declare a function.
+
+Fri Jun 22 16:50:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h class fhandler_socket): Declare new method
+ `set_close_on_exec'.
+ * fhandler_socket.cc (fhandler_socket::set_close_on_exec):
+ New method.
+
+Fri Jun 22 16:12:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_tape.cc (fhandler_dev_tape::tape_erase): Set size
+ parameter to value expected by GetTapeParameters().
+
+Thu Jun 21 22:01:39 2001 Marius Gedminas <mgedmin@delfi.lt>
+
+ * fhandler_console.cc (fhandler_console::read): Detect AltGr more
+ robustly on WinNT.
+
+2001-06-22 Robert Collins <rbbtcollins@hotmail.com>
+
+ * thread.cc (__pthread_cond_timedwait): Lock the waiting mutex before
+ the condition protect mutex to avoid deadlocking. (Found by Greg Smith).
+ (__pthread_cond_wait): Ditto.
+
+2001-06-30 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.cc (fhandler_base::open): Work around windows bug when
+ CreateFile() with dwDesiredAccess == 0 called on remote share returns
+ valid handle even if file doesn't exist.
+
+2001-06-20 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_socket.cc (fhandler_socket::signal_secret_event): New
+ function.
+ * fhandler.h: Declare it.
+ * fhandler_socket.cc (fhandler_socket::create_secret_event): Don't
+ signal secret event immediately.
+ (fhandler_socket::check_peer_secret_event): Do it after peer event
+ was opened.
+ * net.cc (cygwin_connect): Or if socket is non-blocking.
+ (cygwin_accept): Ditto.
+
+Mon Jun 18 17:09:25 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_tty.cc (fhandler_tty_slave::init): Revert 2001-06-16 change.
+
+ * fork.cc (fork_copy): Print more debugging info.
+ (fork_parent): Change order of arguments to accomdate buggy gcc.
+ (fork): Ditto.
+
+Sun Jun 17 18:54:46 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_unlink): Reorganize to try harder to delete file with
+ DeleteFile and to recover more gracefully if FILE_FLAG_DELETE_ON_CLOSE
+ doesn't work properly.
+
+Sat Jun 16 13:06:49 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (sig_handle_tty_stop): Reset PID_STOPPED if not
+ actually stopping.
+ * fhandler_console.cc (fhandler_console::fixup_after_fork): Don't set
+ controlling terminal if just inheriting a handle.
+ (fhandler_console::fixup_after_exec): Ditto.
+ * fhandler_tty.cc (fhandler_tty_slave::init): Ditto.
+ * signal.cc (kill_worker): Set appropriate errno if proc_exists
+ determines that process does not really exist.
+
+Fri Jun 15 14:34:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Deal more robustly with foo/ behavior.
+
+Fri Jun 15 11:15:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_tape.cc (fhandler_dev_tape::tape_status): Set size
+ parameter to value expected by GetTapeParameters().
+
+Thu Jun 14 20:19:46 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_disk_file::fstat): Properly set executable bits
+ for directory when !ntsec && !ntea. Also move common code prior to
+ call to get_attributes.
+
+Fri June 15 09:25:00 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc (pthread_cond::Signal): Release the condition access
+ variable correctly.
+
+2001-06-14 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.cc (fhandler_base::open): Set win32 access flags to 0, when
+ requested.
+ * fhandler.h: New status flag FH_QUERYOPEN.
+ (fhandler::get_query_open): New function.
+ (fhandler::set_query_open): Ditto.
+ * syscalls.cc (stat_worker): Request query-only open mode.
+
+2001-06-12 Egor Duda <deo@logos-m.ru>
+
+ * environ.cc (set_file_api_mode): New function. Move setting
+ of file APIs mode (OEM/ANSI) here.
+ (codepage_init): From here.
+ * winsup.h (set_file_api_mode): Declare it.
+ * fork.cc (fork_child): Set file APIs mode in forkee.
+
+Mon Jun 11 14:19:49 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * pinfo.cc: Use autoloaded ToolHelp functions throughout for Win9x.
+ * autoload.cc: Autoload ToolHelp functions.
+
+ * sigproc.cc (proc_subproc): Incorporate SIGCHLD == SIG_IGN special
+ handling of zombie processes. Ensure that zombie processes which are
+ at the end of the zombie array are properly cleaned up.
+
+Mon Jun 11 11:18:56 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (chdir): Fix call to path_conv constructor so that it REALLY
+ doesn't check for the null/non-empty path.
+
+Sun Jun 10 23:34:09 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::update_fs_info): Don't consider remote drives to
+ be NTFS. Set root_dir before invoking GetDriveType (from Kazuhiro
+ Fujieda <fujieda@jaist.ac.jp>). Eliminate extra checks for rootdir.
+
+Sun Jun 10 20:19:47 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (chdir): Pre-check path for validity before eating trailing
+ space. Then, ensure that path_conv doesn't check the path for validity
+ again.
+
+Sun Jun 10 12:56:00 2001 Christopher Faylor <cgf@redhat.com>
+
+ * exceptions.cc (sigdelayed): Ensure that signal is cleared as
+ the last operation or suffer races.
+ * sigproc.cc (proc_subproc): Deal with zombie array overflow.
+
+Sun Jun 10 11:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygwin.din: Add fchdir symbols.
+ * path.cc (chdir): Guard against invalid parameter.
+ (fchdir): New function.
+ * include/cygwin/version.h: Bump API minor version to 40.
+ * uinfo.cc (internal_getlogin): Remove unused variable.
+
+Sat Jun 9 23:20:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (seteuid): Set environment variables USERNAME and
+ USERDOMAIN before impersonation to workaround a LookupAccountSid()
+ misbehaviour.
+ * uinfo.cc (internal_getlogin): Revert most of the previous change.
+ Don't set environment variables USERNAME and USERDOMAIN. That's
+ the job of seteuid() now. Try to get logon server from Lsa
+ only if logon server isn't already known.
+
+Thu Jun 7 15:54:32 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc (pthread_cond::Broadcast): Don't print error messages on
+ invalid mutexs - user programs are allowed to call
+ pthread_cond_broadcast like that.
+ (__pthread_cond_timedwait): Initialise themutex properly.
+ (__pthread_cond_wait): Initialise themutex properly.
+
+Tue Jun 5 19:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_console.cc (fhandler_console::dup): Allocate space for
+ savebuf on Cygwin heap.
+ (fhandler_console::char_command): Ditto. Use correct values for size.
+
+2001-06-05 Egor Duda <deo@logos-m.ru>
+
+ * security.h (NTWriteEA): Change prototype.
+ * ntea.cc (NTReadEA): Don't check for global ntea setting, now
+ it's caller responsibility.
+ (NTWriteEA): Ditto.
+ * security.cc (get_file_attribute): Read attribute from EA only
+ if 'ntea' is enabled.
+ (set_file_attribute): Ditto.
+ * path.h: (class path_conv): Add members to store file system
+ information.
+ (path_conv::get_drive_type): New function.
+ * syscalls.cc (stat_worker): Use it.
+ * path.cc (path_conv::update_fs_info): New functions.
+ (path_conv::check): Get file system information from device where
+ file resides. On NTFS, try to read symlink contents from EA.
+ (get_symlink_ea): New function.
+ (set_symlink_ea): Ditto.
+ (symlink): Store symlink in extended attribute, if possible.
+
+Tue Jun 5 11:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_disk_file::fstat): Always reset file position
+ to original value after checking for executable magic.
+
+Mon Jun 4 16:21:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygheap.h (cygheap_user::cygheap_user): Initialize token to
+ INVALID_HANDLE_VALUE.
+ * uinfo.cc (uinfo_init): Close token handle if needed.
+
+Sun Jun 3 20:52:13 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (normalize_posix_path): Revert .. check removed by previous
+ changes.
+ * cygheap.h: Temporarily declare path_prefix_p here.
+
+Mon Jun 4 0:14:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (wsock_event): Add destructor.
+
+Sun Jun 3 09:49:55 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * dlfcn.cc (dlclose): Do not call FreeLibrary if the symbol to close
+ was obtained by dlopen(NULL,...).
+
+Sat Jun 2 23:11:52 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (sleep): Try to be a little more accomodating of signal
+ arrival. Ensure that the signal handler is called.
+
+Sat Jun 2 14:07:28 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (cygheap_root::cygheap_root): Remove constructor.
+ (cygheap_root::~cygheap_root): Remove destructor.
+ (cygheap_root::operator =): Remove.
+ (cygheap_root::set): New method.
+ * cygheap.h (cygheap_root): Reflect above changes. Store root info in
+ mount-like structure.
+ (cygheap_root:posix_ok): New method.
+ (cygheap_root::ischroot_native): Ditto.
+ (cygheap_root::unchroot): Ditto.
+ (cygheap_root::exists): Ditto.
+ (cygheap_root::posix_length): Ditto.
+ (cygheap_root::posix_path): Ditto.
+ (cygheap_root::native_length): Ditto.
+ (cygheap_root::native_path): Ditto.
+ * dir.cc (opendir): Remove special chroot test.
+ * path.cc (path_prefix_p): Remove front end.
+ (normalize_posix_path): Reorganize chroot tests to accomodate new
+ convention of allowing paths using posix chroot prefix.
+ (path_conv::check): Pass a "already ran normalize" option to
+ conv_to_win32_path. Return if there is an error from this function.
+ (mount_info::conv_to_win32_path): Add extra argument. Don't call
+ normalize_posix_path if caller has already done so. Substitute chroot
+ setting, if any, for root translation. Add chroot checking to final
+ output step.
+ * shared_info (mount_info): Accomodate additional argument to
+ conv_to_win32_path.
+ * syscalls.cc (chroot): Store both normalized posix path and native
+ path in chroot.
+
+Fri Jun 1 10:57:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (chdir): Really make sure that isspace gets only an unsigned
+ char.
+
+Fri Jun 1 13:45:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (_rename): Handle the case that `foo' is renamed to
+ `bar' while `bar.lnk' is an existing shortcut-symlink.
+
+Thu May 31 15:57:57 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_disk_file::fstat): Avoid clearing S_IFMT bits
+ since we've already pre-cleared everything anyway.
+
+Wed May 30 23:51:32 2001 Earnie Boyd <earnie_boyd@yahoo.com>
+
+ * path.cc (chdir): Always send unsigned chars to isspace since newlib's
+ isspace doesn't deal well with "negative" chars.
+
+Wed May 30 23:51:32 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_disk_file::open): Propagate remote status of
+ file garnered from path_conv. Move #! checking to fstat.
+ (fhandler_disk_file::fstat): Reorganize st_mode setting to eliminate
+ duplication. Move check for #! here from fhandler::open.
+
+ * fhandler.h (fhandler_base::isremote): New method.
+ (fhandler_base::set_isremote): Ditto.
+ (fhandler_base::set_execable_p): Also record "don't care if executable
+ state".
+ (fhandler_base::dont_care_if_execable): New method.
+ * path.cc (path_conv::check): Clear new flags. Appropriately set
+ vol_flags, drive_type, and is_remote_drive.
+ * path.h: Add new flags and methods for manipulating them.
+ * syscalls.cc (_unlink): Use isremote() to determine if a path is
+ remote rather than calling GetDriveType.
+ (stat_worker): Ditto.
+ * security.cc (get_file_attribute): Or attribute with result of
+ NTReadEA to be consistent with get_nt_attribute.
+
+Tue May 29 19:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * sec_helper.cc (cygsid::getfrompw): Change parameter to `const'.
+ (cygsid::getfromgr): Ditto.
+ * security.cc: Use `sys_mbstowcs' and `sys_wcstombs' throughout.
+ (extract_nt_dom_user): Try to get user and domain from SID in
+ pw->pw_gecos first.
+ * security.h (class cygsid): Change parameter of getfrompw() and
+ getfromgr() to `const'.
+ * uinfo.cc (internal_getlogin): Change order for evaluating user
+ information in winNT case. Drop usage of NetWkstaUserGetInfo().
+
+Mon May 28 21:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * shortcut.c (check_shortcut): Treat only Cygwin shortcuts as symlinks.
+
+Fri May 25 11:07:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (symlink_info::check): Correctly set 'ext_tacked_on'. Use
+ this to determine if user specified 'foo.lnk' explicitly. Reorganize
+ slightly to get rid of one goto.
+
+Fri May 25 10:15:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (symlink_info::check): Add a check to return correctly
+ if incoming `*.lnk' file is not a symlink.
+
+Thu May 24 15:46:50 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (slash_drive_prefix_p): Remove.
+ (mount_info::slash_drive_to_win32_path): Ditto.
+ (mount_info::conv_to_win32_path): Remove slash drive prefix check.
+ (mount_info::add_item): Ditto.
+ (mount_info::del_item): Ditto.
+ * shared_info.h (mount_info): Remove slash_drive_to_win32_path
+ declaration.
+
+Thu May 24 01:17:33 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (handle_exceptions): Bump repeat count for debugging
+ kick out.
+
+ * fhandler.h (fhandler_dev_dsp): Add a fixup_after_exec.
+ * fhandler_dsp.cc (class Audio): Add TOT_BLOCK_SIZE to enum.
+ (operator new): New.
+ (bigwavebuffer): Declare using TOT_BLOCK_SIZE to avoid buffer overruns.
+ (Audio::Audio): Optimize slightly.
+ (fhandler_dev_dsp::open): Allocate s_audio using static buffer.
+ (fhandler_dev_dsp::fixup_after_exec): New function. Ditto.
+
+Wed May 23 17:45:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (seteuid): Restrict overriding external provided
+ user tokens to ntsec. Don't test external tokens for primary
+ group to evaluate if it should be overridden. Restrict creating
+ internal tokens to ntsec.
+
+Wed May 23 10:11:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (chown_worker): Don't check for ENOSYS.
+
+Tue May 22 12:20:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * signal.cc (sleep): Protect with sigframe.
+
+Tue May 22 17:58:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (get_file_attribute): Don't set errno.
+
+Mon May 21 15:08:00 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * configure.in: Allow --enable-newvfork to turn NEWVFORK on and off.
+ * configure: Regenerate.
+
+Mon May 21 11:46:01 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump minor version number.
+
+Sun May 20 13:26:25 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_dsp.cc: Reformat to GNU standards.
+ (s_audio): Change to a pointer throughout.
+ (fhandler_dev_dsp::open): Initialize s_audio, if required.
+
+Sat May 19 23:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add load statements for `LookupAccountNameW',
+ `LsaClose', `LsaEnumerateAccountRights', `LsaFreeMemory',
+ `LsaOpenPolicy', `LsaQueryInformationPolicy', `NetLocalGroupEnum',
+ `NetLocalGroupGetMembers', `NetServerEnum', `NetUserGetGroups' and
+ `NtCreateToken'.
+ * ntdll.h: Add declaration for `NtCreateToken'.
+ * sec_helper.cc: Add `well_known_local_sid', `well_known_dialup_sid',
+ `well_known_network_sid', `well_known_batch_sid',
+ `well_known_interactive_sid', `well_known_service_sid' and
+ `well_known_authenticated_users_sid'.
+ (cygsid::string): Define as const method.
+ (cygsid::get_sid): Set psid to NO_SID on error.
+ (cygsid::getfromstr): Ditto.
+ (cygsid::getfrompw): Simplify.
+ (cygsid::getfromgr): Check for gr == NULL.
+ (legal_sid_type): Move to security.h.
+ (set_process_privilege): Return -1 on error, otherwise 0 or 1 related
+ to previous privilege setting.
+ * security.cc (extract_nt_dom_user): Remove `static'.
+ (lsa2wchar): New function.
+ (open_local_policy): Ditto.
+ (close_local_policy): Ditto.
+ (get_lsa_srv_inf): Ditto.
+ (get_logon_server): Ditto.
+ (get_logon_server_and_user_domain): Ditto.
+ (get_user_groups): Ditto.
+ (is_group_member): Ditto.
+ (get_user_local_groups): Ditto.
+ (sid_in_token_groups): Ditto.
+ (get_user_primary_group): Ditto.
+ (get_group_sidlist): Ditto.
+ (get_system_priv_list): Ditto.
+ (get_priv_list): Ditto.
+ (get_dacl): Ditto.
+ (create_token): Ditto.
+ (subauth): Return immediately if SE_TCB_NAME can't be assigned.
+ Change all return statements in case of error to jumps to `out'
+ label. Add `out' label to support cleanup.
+ * security.h: Add extern declarations for `well_known_local_sid',
+ `well_known_dialup_sid', `well_known_network_sid',
+ `well_known_batch_sid', `well_known_interactive_sid',
+ `well_known_service_sid' and `well_known_authenticated_users_sid'.
+ Add extern declarations for functions `create_token',
+ `extract_nt_dom_user' and `get_logon_server_and_user_domain'.
+ (class cygsid): Add method `assign'. Change operator= to call new
+ `assign' method. Add `debug_print' method.
+ (class cygsidlist): New class.
+ (legal_sid_type): Moved from sec_helper.cc to here.
+ * spawn.cc (spawn_guts) Revert reversion of previous patch.
+ Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'
+ again.
+ * syscalls.cc (seteuid): Rearranged. Call `create_token' now when
+ needed. Call `subauth' if `create_token' fails. Try setting token
+ owner and primary group only if token was not explicitely created
+ by `create_token'.
+ * uinfo.cc (internal_getlogin): Try harder to generate correct user
+ information. Especially don't trust return value of `GetUserName'.
+
+Sat May 19 21:16:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fork.cc (fork_parent): Move atforkprepare call here.
+ (fork): From here.
+
+Sat May 19 18:35:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add missing load statement for `CancelIo'.
+
+Sat May 19 01:22:43 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * grp.cc (read_etc_group): Don't copy mutex on fork.
+ * pwd.cc (read_etc_passwd): Ditto.
+ * autoload.cc (LoadDLLfuncEx): Use LoadDLLprime to initialize DLL
+ specific area.
+
+Fri May 18 10:31:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (wsock_event::wait): Explicitely cancel IO when a signal
+ arrived to avoid data loss. Fallback to blocking IO when canceling
+ fails.
+
+Thu May 17 15:29:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (cygwin_set_impersonation_token): Never destroy
+ previous token object.
+ (subauth): Create token source with well defined identifier.
+
+Wed May 16 23:27:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * uinfo.cc (uinfo_init): Just set user token to INVALID_HANDLE_VALUE.
+ Token value is already invalid at that point.
+
+Wed May 16 21:34:00 2001 Fred Yankowski <fred@ontosys.com>
+
+ * net.cc (errmap): Add missing mapping from WSAEINTR to EINTR.
+
+Wed May 16 09:20:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * sec_helper.cc (legal_sid_type): Fix conditional. Change to
+ inline function.
+
+Wed May 16 01:01:48 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * autoload.h: Eliminate.
+ * autoload.cc: Pull in autoload.h. Eliminate many macros. Rewrite to
+ avoid necessity of initialization routines. Just use a standard one.
+ (wsock_init): New function. Moved from net.cc.
+ * net.cc (wsock_init): Move to autoload.cc.
+ (wsadata): Make global.
+ * dtable.cc (dtable::build_fhandler): Use more reliable method for
+ checking if net stuff has been loaded.
+
+Tue May 15 19:52:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fork.cc (fork): Eliminate superfluous call to getuid().
+ * security.h: New define `NO_SID'. Remove declarations of functions
+ moved to methods into class cygsid.
+ (class cygsid): Declare new methods `getfromstr', `get_sid',
+ `getfrompw', `getfromgr', `get_rid', `get_uid', `get_gid', `string'
+ and new constructors and operators =, == and !=.
+ Declare new global cygsids `well_known_XXX_sid' substituting the
+ corresponding `get_XXX_sid' functions. Remove declarations of
+ these functions.
+ * sec_helper.cc (well_known_admin_sid): New global variable.
+ (well_known_system_sid): Ditto
+ (well_known_creator_owner_sid): Ditto
+ (well_known_world_sid): Ditto
+ (cygsid::string): New method, substituting `convert_sid_to_string_sid'.
+ (cygsid::get_sid): New method, substituting `get_sid'.
+ (cygsid::getfromstr): New method, substituting
+ `convert_string_sid_to_sid'.
+ (cygsid::getfrompw): New method, substituting `get_pw_sid'.
+ (cygsid::getfromgr): New method, substituting `get_gr_sid'.
+ (cygsid::get_id): New method, substituting `get_id_from_sid'.
+ (get_admin_sid): Eliminated.
+ (get_system_sid): Ditto.
+ (get_creator_owner_sid): Ditto.
+ (get_world_sid): Ditto.
+ * grp.cc: Use new cygsid methods and well known sids throughout.
+ * registry.cc: Ditto.
+ * sec_acl.cc: Ditto.
+ * security.cc: Ditto.
+ * shared.cc: Ditto.
+ * syscalls.cc (seteuid): Ditto. Eliminate redundant conditional.
+ * uinfo.cc (internal_getlogin): Ditto.
+ * spawn.cc (spawn_guts) Revert previous patch.
+
+Tue May 15 10:20:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_socket.cc (fhandler_socket::ioctl): Convert s_addr
+ field to host byte order before comparing with INADDR_LOOPBACK.
+
+Tue May 15 9:03:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add autoload statements for ws2_32 functions
+ `WSACloseEvent', `WSACreateEvent', `WSAGetOverlappedResult',
+ `WSARecv', `WSARecvFrom', `WSASend', `WSASendTo' and `WSASetEvent',
+ `WSAWaitForMultipleEvents'.
+ * net.cc: Define wsock_evt.
+ (wsock_event): New class.
+ (cygwin_sendto): Use overlapped socket io if available.
+ (cygwin_recvfrom): Ditto.
+ (cygwin_recv): Ditto.
+ (cygwin_send): Ditto.
+ * security.cc (subauth): Set Win32 error to 0 to safely ask for the
+ error code of dynamically loaded function `LsaRegisterLogonProcess'.
+
+Mon May 14 15:37:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * errno.cc (_sys_errlist): Add missing commas.
+
+Mon May 14 16:13:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (subauth): Check if Secur32.dll could be loaded.
+
+Sun May 13 22:49:04 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Revert allow_ntsec check so that volume
+ info is always retrieved and isdisk setting is properly set.
+
+Sun May 13 14:02:36 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_tty.cc (fhandler_tty_common::dup): Preserve O_NOCTTY when
+ duping a filehandle.
+
+Sat May 12 18:19:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (rmdir): Rearrange slightly to allow removing directories
+ even when R/O attribute is set.
+
+Fri May 11 16:53:38 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * external.cc (fillout_pinfo): Use correct pids.
+ * path.cc (mount_info::conv_to_win32_path): Correct test for whether to
+ include a slash.
+
+Fri May 11 01:04:17 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (handle_exceptions): Don't print message when executing
+ from a cygwin program.
+
+2001-05-10 Egor Duda <deo@logos-m.ru>
+ Christopher Faylor <cgf@redhat.com>
+
+ * environ.cc (winenv): Always add SYSTEMDRIVE and SYSYEMROOT to
+ win32-style environment if they don't already exist.
+
+2001-05-10 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * path.cc (mount_info::conv_to_win32_path): Treat UNC paths the same as
+ paths including `:' or `\'.
+
+Wed May 9 14:46:32 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.h (fhandler_termios::echo_erase): Declare new method.
+ * fhandler_termios.cc (fhandler_termios::echo_erase): New method for
+ echoing erase characters.
+ (fhandler_termios::line_edit): Check the echo flag before echoing
+ control characters (from Kazuhiro Fujieda <fujieda@jaist.ac.jp>).
+
+Wed May 9 10:43:30 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/pthread.h: Remove C++ comment.
+
+Tue May 8 11:09:59 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (_cfree): Add regparm attribute.
+ (_crealloc): Ditto.
+
+ * dcrt0.cc (dll_crt0_1): Default to always checking for executable for now.
+
+ * dtable.cc (dtable::not_open): Move method.
+ * dtable.h (dtable): Here.
+
+ * exceptions.cc (ctrl_c_handler): Don't expect process group leader to
+ handle a signal if it doesn't exist.
+
+ * fhandler.h (fhandler_base): Make openflags protected.
+
+ * localtime.c (tzsetwall): Check for __CYGWIN__ as well as __WIN32__.
+
+ * path.cc (path_conv::check): Add some comments. Change strcat to assignment.
+
+ * lib/_cygwin_S_IEXEC.cc (_cygwin_bob__): Eliminate.
+
+ * fhandler_tty.cc (fhandler_console::dup): Set controlling terminal if necessary.
+ * fhandler_tty.cc (fhandler_tty_slave::dup): Ditto.
+
+Mon May 7 21:33:17 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/sys/file.h: Revert special X_OK usage. Just make it a
+ constant.
+
+Sun May 6 17:05:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.h (pthread_cond): New element cond_access to allow atomic
+ broadcasts.
+ * thread.cc (pthread_cond::pthread_cond): Initialise cond_access.
+ (pthread_cond::~pthread_cond): Destroy cond_access.
+ (pthread_cond::Broadcast): Use cond_access.
+ (pthread_cond::Signal): Use cond_access.
+ (pthread_cond_wait): Use cond_access.
+ (pthread_cond_timedwait): Use cond_access.
+
+Sun May 6 11:55:40 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * string.h (cygwin_strchr): Make 'static inline' so that things will
+ still work when optimized.
+
+Sat May 5 01:04:11 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (handle_exceptions): Vastly increase test for exception
+ loop guard variable.
+
+Fri May 4 22:23:33 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (stack_info): Add some controls.
+ (stack_info::init): Add extra arguments to control method of
+ initialization.. If we have a known good frame, set things up so that
+ this frame is not skipped the first time through. Record whether
+ caller cares about arguments or not.
+ (stack_info::walk): Don't store arguments if they're unwanted.
+ (stackdump): Add isexception parameter for use when called by exception
+ handler.
+ (cygwin_stackdump): Accomodate extra argument to stackdump.
+ (handle_exceptions): Ditto.
+ (sig_handle): Ditto.
+ (interrupt_on_return): Accomodate extra arguments to stack walk
+ initialization.
+
+Fri May 4 21:05:20 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * localtime.c: Revert exclusion of windows.h.
+
+Fri May 4 17:03:16 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * string.h: Fix last-minute typo.
+
+Fri May 4 16:49:34 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * pinfo.h: Correctly set __SIGOFFSET.
+
+ * path.cc (hash_path_name): Avoid calling library functions for simple
+ copying of characters.
+
+ * shortcut.c: Use WIN32_LEAN_AND_MEAN.
+ * smallprint.c: Ditto.
+
+ * environ.cc (getwinenv): Minor clarity fix.
+
+ * localtime.c: No need to include windows.h
+
+ * string.h: New file.
+
+Fri May 4 16:37:30 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (ctrl_c_handler): Always send signal to process if it
+ has no tty.
+
+2001-05-04 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_socket.cc (set_connect_secret): Use /dev/urandom to
+ generate secret cookie.
+
+Thu May 3 16:37:55 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/pthread.h (pthread_cleanup_push): Eliminate space preceding
+ arguments.
+ (pthread_cleanup_pop): Ditto.
+
+Thu May 3 18:16:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (wsock_init): Rename `was_in_progress' to `wsock_started'
+ for clearness.
+
+Thu May 3 10:44:16 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (handle_exceptions): Break out of "loop" if the
+ debugger doesn't seem to be attaching to our process.
+
+Wed May 2 20:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Use new definition of LoadDLLinitfunc throughout.
+ Redefine wrapper for wsock32.dll and ws2_32.dll.
+ (std_dll_init): New function.
+ * autoload.h: Rename LoadDLLinitfunc to LoadDLLinitfuncdef.
+ Add new defines LoadDLLinitfunc and LoadDLLstdfunc.
+ * net.cc (wsock_init): Add guard variable handling. Take care
+ to call WSAStartup only once. Load WSAStartup without using
+ autoload wrapper to eliminate recursion. Eliminate FIONBIO
+ and srandom stuff.
+
+Tue May 1 01:26:15 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (mount_info::conv_to_win32_path): More path tweaking.
+
+Tue May 1 00:34:46 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (mount_info::conv_to_win32_path): Fix debugging output to
+ avoid a SIGSEGV. Avoid double backslashes in middle of filename.
+
+Mon Apr 30 21:51:14 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (mkrelpath): New function.
+ (mount_info::conv_to_win32_path): Eliminate now-unneeded relative path
+ name arg and processing.
+ (path_conv::check): Accomodate relative path names again. Accomodate
+ one extra argument in mount_info::conv_to_win32_path. Tack trailing
+ slash on end of relative path as a side effect, like before.
+ * shared_info.h (mount_info::conv_to_win32_path): Reflect new argument
+ ordering.
+
+Mon Apr 30 22:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add LoadDLLinitfunc for secur32.dll.
+ Add LoadDLLfuncEx statements for AllocateLocallyUniqueId@4,
+ DuplicateTokenEx@24, LsaNtStatusToWinError@4,
+ LsaDeregisterLogonProcess@4, LsaFreeReturnBuffer@4,
+ LsaLogonUser@56, LsaLookupAuthenticationPackage@12,
+ LsaRegisterLogonProcess@12,
+ * environ.cc: Add extern declaration for `subauth_id'.
+ (subauth_id_init): New function for setting `subauth_id'.
+ (struct parse_thing): Add entry for `subauth_id'.
+ * fork.cc (fork_parent): Call `RevertToSelf' and
+ `ImpersonateLoggedOnUser' instead of `seteuid'.
+ * security.cc: Define global variable `subauth_id'.
+ (extract_nt_dom_user): New function.
+ (cygwin_logon_user): Call `extract_nt_dom_user' now.
+ (str2lsa): New static function.
+ (str2buf2lsa): Ditto.
+ (str2buf2uni): Ditto.
+ (subauth): Ditto.
+ * security.h: Add prototype for `subauth'.
+ * spawn.cc (spawn_guts): Use cygheap->user.token only if impersonated.
+ Use `cygsid' type. Remove impersonation before allowing access to
+ workstation/desktop to everyone. Call `RevertToSelf' and
+ `ImpersonateLoggedOnUser' instead of `seteuid'.
+ * syscalls.cc (seteuid): Rearranged to allow using subauthentication
+ to retrieve user tokens when needed.
+
+Mon Apr 30 20:26:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * uinfo.cc (internal_getlogin): Formatting change.
+
+Mon Apr 30 19:58:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc: Eliminate MAX_DOMAIN_NAME define.
+ (read_etc_group): Substitute MAX_DOMAIN_NAME by
+ INTERNET_MAX_HOST_NAME_LENGTH.
+ * passwd.cc (parse_pwd): Don't force pw_name to be lower case.
+ * sec_helper.cc: Substitute MAX_USER_NAME by UNLEN,
+ MAX_COMPUTERNAME_LENGTH by INTERNET_MAX_HOST_NAME_LENGTH throughout.
+ (lookup_name): Slight cleanup.
+ * security.cc (alloc_sd): Substitute MAX_USER_NAME by UNLEN.
+ * security.h: Define DEFAULT_UID as DOMAIN_USER_RID_ADMIN and
+ DEFAULT_GID as DOMAIN_ALIAS_RID_ADMINS.
+ * shared.cc (memory_init): Substitute MAX_USER_NAME by UNLEN.
+ * thread.h: Ditto.
+ * uinfo.cc (internal_getlogin): Substitute MAX_USER_NAME by UNLEN.
+ Substitute MAX_COMPUTERNAME_LENGTH and MAX_HOST_NAME by
+ INTERNET_MAX_HOST_NAME_LENGTH.
+ * winsup.h: Include lmcons.h. Eliminate MAX_USER_NAME and
+ MAX_HOST_NAME. Move DEFAULT_UID and DEFAULT_GID to security.h.
+
+Mon Apr 30 12:35:40 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Don't use path_flags when converting to
+ MS-DOS syntax unless parsing tail of path component. Stop parsing path
+ when we reach the 'root' of the path. Correctly copy tail to path
+ component.
+
+Sun Apr 29 22:28:06 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (INIT_EXCEPTION_HANDLER): Eliminate.
+ (init_exceptions): Just use init_exception_handler.
+ (open_stackdumpfile): New function.
+ (stack_info::first_time): Eliminate.
+ (stack_info::init): Set up fields to avoid "first_time" consideration.
+ (stack_info::walk): Remove "first_time" consideration.
+ (stackdump): Change arguments to accept initial frame pointer and open
+ stack file flag.
+ (stack): Eliminate.
+ (cygwin_stackdump): Use stackdump() rather than stack().
+ (try_to_debug): Remove all synchronization logic. Just keep looping in
+ exception handler until debugger notices us. Return 1 if successfully
+ started debugger.
+ (handle_exceptions): Just return if we know that we're debugging.
+ Reorganize to avoid creating a stackdump file if we are starting a
+ debugger. Return from exception handler if debugger started
+ successfully.
+ (sig_handle): Create a stackdump only if debugger wasn't started.
+ * winsup.h (try_to_debug): Add an argument.
+
+Sun Apr 29 21:41:25 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (symlink_info::check): Remove extra arguments, move
+ functionality back to path_conv::check. Clear symlink bit from pflags
+ argument before detecting if this is a symlink.
+ (path_conv::check): Convert posix path here instead of
+ symlink_info::check. Only grab volflags when using ntsec.
+ (symlink_info::check_case): Just replace appropriate part of input
+ path.
+
+Sat Apr 28 19:36:13 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Throughout, change 'tty_attached' to 'real_tty_attached', for clarity.
+ Throughout, change 'OutputStopped' to 'output_stopped', for
+ consistency.
+ * dtable.cc (stdio_init): Set controlling tty if not set by stdio
+ opens.
+ * exceptions.cc (ctrl_c_handler): Avoid special pgid checking if no tty
+ is associated with the process.
+ (Suggested by Tim Baker <dbaker@direct.ca>)
+ * external.cc (fillout_pinfo): Return actual tty number for ctty.
+ * fhandler_console.cc (get_tty_stuff): Set ctty when shared memory is
+ allocated. Accept flags input from open().
+ (set_console_ctty): New function.
+ (fhandler_console::open): Pass flags to get_tty_stuff and rely on this
+ function to set the ctty, if appropriate.
+ * fhandler_termios.cc (fhandler_termios::set_ctty): Move to tty_min
+ class.
+ * fhandler_tty.cc (fhandler_tty_slave::open): Use tc field to access
+ set_ctty().
+ * tty.h (TTY_CONSOLE): Move to include/sys/cygwin.h.
+ (tty_min): Add set_ctty class here.
+ * include/sys/cygwin.h (TTY_CONSOLE): New home here.
+
+ * path.cc (symlink_info): Make contents an actual buffer. Pass more
+ flags to case_check.
+ (path_conv::check): Reorganize to do parsing based on posix path rather
+ than native path.
+ (symlink_info::check): Expect posix path as input. Translate to native
+ path here. Accept path_conv flags. Stop parsing if not a symlink
+ regardless of whether previous path was a symlink.
+
+2001-04-27 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * thread.cc (thread_init_wrapper): Use _REENT_INIT to initialize the
+ reent structure of newlib.
+
+Fri Apr 27 14:02:24 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.h (sig_send): Add exception parameter to sig_send.
+ * sigproc.cc (sig_send): Ditto. Use it when setting frame info.
+ * exceptions.cc (handle_exceptions): Use exception flag when calling
+ sig_send.
+
+2001-04-27 Egor Duda <deo@logos-m.ru>
+
+ * tty.cc (tty::make_pipes): Set to_slave pipe mode to nonblocking.
+ * fhandler_tty.cc (fhandler_pty_master::accept_input): If pipe buffer
+ is full, give slave a chance to read data.
+
+2001-04-26 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * security.cc (alloc_sd): Add unrelated ACCESS_ALLOWED_ACE behind
+ the `everyone' ACE.
+
+Wed Apr 25 15:07:37 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.h [sigthread]: Add exception field.
+ [sigframe::~sigframe]: Clear exception field.
+ [sigframe::set]: Set exception field from caller.
+ * sigproc.cc (sig_send): Set exception field when frame pointer is
+ passed in.
+ * exceptions.cc (interrupt_on_return): Always treat exception as
+ interruptible.
+
+2001-04-25 Egor Duda <deo@logos-m.ru>
+
+ * cygwin.din: Export asctime_r, ctime_r, gmtime_r, localtime_r
+ * include/cygwin/version.h: Bump CYGWIN_VERSION_API_MINOR to 39
+
+Wed Apr 25 10:57:36 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump minor version number.
+ * childinfo.h: Bump child structure magic number.
+
+2001-04-25 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * uinfo.cc (internal_getlogin): Return pointer to struct passwd.
+ (uinfo_init): Accommodate the above change.
+ * syscalls.cc (seteuid): Ditto.
+
+Tue Apr 25 11:08:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add LoadDLLfunc statements for SetTokenInformation@16.
+ * cygheap.cc: Include security.h.
+ * grp.cc (internal_getgrent): New function.
+ (getgroups): Rearranged using `internal_getgrent' and the new
+ `cygsid' class.
+ * passwd.cc (internal_getpwent): New function.
+ * sec_acl.cc: Use new `cygsid' class throughout.
+ (acl_access): Use `internal_getgrent' instead of `getgrent'.
+ * sec_helper.cc: Use new `cygsid' class throughout.
+ (get_id_from_sid): Use `internal_getgrent' instead of `getgrent'.
+ Use `internal_getpwent' instead of `getpwent'.
+ * security.cc: Use new `cygsid' class throughout.
+ * security.h: Move `MAX_SID_LEN' from winsup.h to here.
+ Add extern declarations for `internal_getgrent' and `internal_getpwent'.
+ (class cygsid): New class.
+ * shared.cc (sec_user): Use new `cygsid' class.
+ * syscalls.cc (seteuid): Try to set owner to user and primary group to
+ current group in impersonation token before performing impersonation.
+ (setegid): Try to set primary group in process token to the new group
+ if ntsec is on.
+ * uinfo.cc (internal_getlogin): Use new `cygsid' class.
+ Try to set owner to user and primary group to current group in process
+ token if the process has been started from a non cygwin process.
+ (uinfo_init): Set primary group only if the process has been started
+ from a non cygwin process.
+ * winsup.h: Move define for `MAX_SID_LEN' to security.h.
+
+Mon Apr 16 23:20:00 2001 Andy Younger <andylyounger@hotmail.com>
+
+ * fhandler_dsp.cc: Improved handling of 8 bit playback modes.
+ Put in mock support for SNDCTL_DSP_SETFRAGMENT.
+
+Tue Apr 24 23:51:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * passwd.cc (getpwnam_r): Add pw_passwd handling as well.
+ (getpwuid_r): Ditto.
+
+Tue Apr 24 23:43:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * passwd.cc (getpwnam_r): Use correct offsets into buffer.
+ Copy pw_gecos field as well.
+ (getpwuid_r): Ditto.
+
+2001-04-24 Egor Duda <deo@logos-m.ru>
+
+ * dlmalloc.c: New file. Port of Doug Lea's malloc
+ * dlmalloc.h: Ditto.
+ * Makefile.in: Add support for MALLOC_DEBUG
+ * config.h.in: Ditto.
+ * winsup.h: Ditto.
+ * configure.in: Add --enable-malloc-debugging option.
+ * configure: Regenerate.
+ * debug.h: Include declarations for debugging malloc.
+ * tty.cc (grantpt): Fix definition.
+ (unlockpt): Ditto.
+
+Mon Apr 23 22:00:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Remove trailing underscore from fhandler_base and friends, throughout.
+ * fhandler.h (fhandler_base::set_open_status): New method. Stores
+ original open status.
+ (fhandler_base::get_open_status): New method. Retrieves original open
+ status.
+ (fhandler_base::reset_to_open_binmode): New method.
+ * fhandler.cc (fhandler_base::open): Save open status.
+ (fhandler_base::init): Ditto.
+ * fhandler_clipboard.cc (fhandler_clipboard::open): Ditto.
+ * fhandler_console.cc (fhandler_console::open): Ditto.
+ * fhandler_dsp.cc (fhandler_dsp::open): Ditto.
+ * fhandler_dev_mem.cc (fhandler_dev_mem::open): Ditto.
+ * fhandler_dev_random.cc (fhandler_dev_random::open): Ditto.
+ * fhandler_serial.cc (fhandler_serial::open): Ditto.
+ * fhandler_tty_slave.cc (fhandler_tty_slave::open): Ditto.
+ * fhandler_tty_master.cc (fhandler_tty_master::open): Ditto.
+ * fhandler_dev_zero.cc (fhandler_dev_zero::open): Ditto.
+ * syscalls.cc (setmode): Rework so that 0 mode value causes reversion
+ to open state.
+
+ * fhandler_tty_slave.cc (fhandler_tty_slave::read): Use correct
+ multiplier when converting from deciseconds to milliseconds.
+
+Mon Apr 23 13:28:35 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.h (fhandler_base::clear_r_binary): New method.
+ (fhandler_base::clear_w_binary): New method.
+ * syscalls.cc (setmode): Accept 0 as mode value. Resets text/binary
+ behavior for fd to default.
+
+Mon Apr 23 12:46:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * net.cc [errmap]: Add '0' condition.
+ (find_winsock_errno): Don't translate no error to EPERM.
+
+Sun Apr 22 20:48:24 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump Cygwin version and API version.
+
+Mon Apr 23 9:27:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc (MTinterface::Init): Always initialise per process variables.
+
+Sun Apr 22 19:18:18 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * features.h: Reinstate as wrapper for sys/features.h.
+
+Mon Apr 23 0:10:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (alloc_sd): Reformat comment.
+ * shared.cc: Drop function declarations already in security.h.
+
+Sun Apr 22 12:17:57 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * shortcut.c (check_shortcut): Close input file handle before
+ returning.
+ * path.cc (check_sysfile): Ditto.
+ (symlink_info::check): Rely on opened file handle being closed by
+ symlink checking routines. Set ext_tacked_on when .lnk is detected.
+
+Sat Apr 21 19:26:05 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * thread.cc (MTinterface::Init): Remove accidentally checked in code.
+
+Sun Apr 22 00:22:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * passwd.cc (getpwuid): Check for thread cancellation.
+ (getpwuid_r): Ditto.
+ (getpwname): Ditto.
+ (getpwnam_r): Ditto.
+ * thread.h (pthread_mutex): New constructors for pshared operation.
+ (MTinterface): Associative array for pshared mutex's.
+ * thread.cc (MTinterface::Init): Initailize pshared mutex array.
+ (pthread_cond::BroadCast): Implementation notes.
+ (pthread_cond::TimedWait): Remove use of SignalObjectAndWait on non-NT systems.
+ (pthread_mutex::pthread_mutex(unsigned short)): New function.
+ (pthread_mutex::pthread_mutex (pthread_mutex_t *, pthread_mutexattr *)):New function.
+ (pthread_mutex::pthread_mutex(pthread_mutexattr *)): Fail on pshared mutex's.
+ (__pthread_mutex_getpshared): New function.
+ (__pthread_join): Check for thread cancellation.
+ (__pthread_cond_timedwait): Support pshared mutex's.
+ (__pthread_cond_wait): Ditto.
+ (__pthread_condattr_setpshared): Error on PROCESS_SHARED requests.
+ (__pthread_mutex_init): Support pshared mutex's.
+ (__pthread_mutex_getprioceiling): Ditto.
+ (__pthread_mutex_lock): Ditto.
+ (__pthread_mutex_trylock): Ditto.
+ (__pthread_mutex_unlock): Ditto.
+ (__pthread_mutex_destroy): Ditto.
+ (__pthread_mutex_setprioceiling): Ditto.
+ (__pthread_mutexattr_setpshared): Support PTHREAD_PROCESS_PSHARED requests.
+
+Fri Apr 20 19:38:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygwin.din: Add *scanf and *scan_r functions.
+
+Fri Apr 20 22:25:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * security.cc (set_process_privileges): Swap out.
+ * sec_helper.cc (set_process_privilege): Rename from
+ `set_process_privileges'. Takes the privilege to enable or disable
+ as parameter now.
+ * security.h: Add prototype for `set_process_privileges'.
+
+2001-04-19 Egor Duda <deo@logos-m.ru>
+
+ * path.cc (path_conv::check): Always initialize member variables.
+
+Fri Apr 20 12:27:49 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/sys/file.h: More cleanup for X_OK.
+
+Fri Apr 20 11:48:45 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/sys/file.h: Move X_OK protection earlier.
+
+ * dtable.cc (dtable::vfork_child_fixup): Avoid closing already closed
+ handles.
+
+Fri Apr 20 16:29:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc (getgroups): Change so that SIDs get compared instead
+ of strings to SIDs.
+
+Fri Apr 20 14:50:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in: Add object files `sec_helper.cc' and `sec_acl.cc'.
+ * security.cc: Swap out several functions.
+ * sec_acl.cc: New file. Move Sun compatibel ACL functions from
+ `security.cc' to here.
+ * sec_helper.cc: New file. Move security helper functions from
+ `security.cc' to here.
+ * security.h: Changed to accomodate the above changes.
+
+Fri Apr 20 14:12:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc: Replace `group_in_memory_p' by `group_state'.
+ Eliminate group_sem throughout.
+ (enum grp_state): New enumeration type.
+ (read_etc_group): Make race safe.
+ * security.cc: Eliminate group_sem throughout.
+
+Thu Apr 19 9:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Drop usage of the same memory area if the same
+ region of the same file is mapped twice.
+
+Wed Apr 18 16:53:54 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Throughout, change fdtab references to cygheap->fdtab.
+ * child_info.h (cygheap_exec_info): Eliminate special fdtab stuff.
+ * spawn.cc (spawn_guts): Ditto.
+ * cygheap.cc (cygheap_init): Initialize fdtab, if appropriate.
+ * cygheap.h (CYGHEAPSIZE): Include size of init_cygheap.
+ (_cmalloc_entry): Include fdtab here.
+ * dtable.h (dtable): Declare/define new methods.
+ * dtable.cc (dtable::vfork_child_fixup): New method.
+ (dtable::fixup_after_exec): Remove unneeded extra arguments.
+ * dcrt0.cc (dll_crt0_1): Ditto.
+
+ * environ.cc (getwinenv): Use case sensitive comparison.
+ (winenv): Make a copy of environment cache to avoid realloc problems
+ when duplicate environment variables exist in the environment. (From
+ Egor Duda)
+
+ * net.cc (cygwin_socket): Revert Apr 14 change.
+
+ * include/sys/file.h: Protect against previous X_OK definition.
+
+Tue Apr 17 12:18:28 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * passwd.cc: Eliminate passwd_sem throughout.
+ * security.cc: Ditto.
+
+Tue Apr 17 12:18:28 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * cygwin.din: Export New functions.
+ * passwd.cc (read_etc_passwd): Make race safe.
+ (getpwuid_r): New function.
+ (getpwnam_r): New function.
+
+2001-04-18 Egor Duda <deo@logos-m.ru>
+
+ * grp.cc (getgroups): Avoid crash if passwd field if /etc/group is
+ empty.
+
+Tue Apr 17 19:05:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.h (path_conv::add_ext_from_sym): Declare.
+ * path.cc (path_conv::add_ext_from_sym): Convert to pure inline method.
+
+Tue Apr 17 18:50:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (windows_device_names): Add missing NULL element.
+
+Tue Apr 17 12:14:54 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (windows_device_names): Move dsp to proper location.
+
+Tue Apr 17 13:44:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (path_conv::check): Set case_clash even if pcheck_case
+ is set to PCHECK_ADJUST when a case clash is given for the last
+ component in path.
+ (symlink_info::case_check): Ditto.
+ * syscalls.cc (_rename): Avoid overwriting an already existing file
+ if a case clash is given even if pcheck_case is set to PCHECK_ADJUST.
+
+Tue Apr 17 2:07:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * config.h.in: Turn off VFORK again.
+
+Mon Apr 16 23:45:24 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.h (cwdstuff): Move class.
+ * cygheap.h (cwdstuff): To here.
+ (init_cygheap): Add cwd field.
+ * child_info.h (cygheap_exec_info): Eliminate cwd stuff.
+ (child_info_spawn): Ditto.
+ * dcrt0.cc (dll_crt0_1): Remove cygcwd.fixup_after_exec call. Convert
+ cygcwd reference to cygheap->cwd.
+ * path.cc: Ditto, throughout.
+ (cwdstuff::copy): Eliminate.
+ (cwdstuff::fixup_after_exec): Ditto.
+ * spawn.cc (spawn_guts): Eliminate call to cygcwd.copy.
+
+ * fhandler.h (FH_OSS_DSP): Move into "fast" device category.
+
+Mon Apr 16 19:19:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc: Move fh_paging_file from some functions to be
+ a global static variable.
+ (class mmap_record): Add `devtype_' member to remember
+ the device type of the file. Add declaration for methods
+ `get_device', `alloc_fh' and `free_fh'.
+ (mmap_record::mmap_record): Initialize `devtype_' correctly.
+ (mmap_record::alloc_fh): New method.
+ (mmap_record::free_fh): Ditto.
+ (munmap): Use new mmap_record::alloc_fh and mmap_record::free_fh
+ methods to create a correct fhandler.
+ (msync): Ditto.
+ (fixup_mmaps_after_fork): Ditto.
+
+Mon Apr 16 16:01:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc (getgroups): If `allow_ntsec' is set, use the process token
+ information to evaluate the groups list.
+
+Mon Apr 16 00:08:02 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * features.h: Remove this file as it is now being supplied by newlib.
+
+Sun Apr 15 23:23:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * autoload.cc: Add winmm functions needed by fhandler_dsp.cc.
+
+Sun Apr 15 22:53:52 2001 Andy Younger <andylyounger@hotmail.com>
+
+ * fhandler_dsp.cc: New file. Implements OSS like /dev/dsp.
+ * include/sys/soundcard.h: New file. User land includes for OSS
+ /dev/dsp.
+ * fhandler.h: Add new class fhandler_dev_dsp and a FH_OSS_DSP
+ definition.
+ * dtable.cc (dtable::build_fhandler): Allow creation of the /dev/dsp
+ device.
+ * path.cc (windows_device_names): Add /dev/dsp into list of device
+ names.
+ * Makefile.in (DLL_OFILES): Add fhandler_dsp.o.
+
+Sun Apr 15 16:36:27 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * uname.c (uname): Default n in in86 to 6 if Windows returns > 6.
+
+Sun Apr 15 15:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (add_ext_from_sym): Redefine to call `add_ext_from_sym_'.
+ (add_ext_from_sym_): New inline function.
+
+Sat Apr 14 19:23:52 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * config.h.in: Turn on VFORK by default.
+
+Sat Apr 14 18:04:35 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * net.cc (cygwin_socket): Set SO_LINGER to small value so closed UNIX
+ domain sockets will not stay around.
+
+Sat Apr 14 18:01:43 2001 Pierre A. Humblet <Pierre.Humblet@ieee.org>
+
+ * select.cc (socket_cleanup): Set SO_LINGER to small value so closed
+ dummy sockets do not stay around. Use correct value for second argument
+ to shutdown.
+
+Sat Apr 14 17:04:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.h (MTinterface): Add threadcount.
+ * thread.cc (MTinterface::Init): Set threadcount to 1.
+ (__pthread_create): Increment threadcount.
+ (__pthread_exit): Decrement threadcount and call exit() from the last thread.
+
+Fri Apr 13 11:34:24 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * fork.cc (fork_child): Call the __pthread_atforkchild function.
+ (fork_parent): Call the __pthread_atforkparent function.
+ * cygwin.din: Export pthread_atfork.
+ * thread.h (callback): New class.
+ (MTinterface): Use it.
+ * thread.cc (__pthread_atforkprepare): New function.
+ (__pthread_atforkparent): New function.
+ (__pthread_atforkchild): New function.
+ (__pthread_atfork): New function.
+ * pthread.cc (pthread_atfork): New function.
+
+Fri Apr 13 9:52:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (add_ext_from_sym): New define evaluating `known'suffix'.
+ (path_conv::check): Use add_ext_from_sym throughout.
+
+Thu Apr 12 23:19:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (mkdir): Check for case clash.
+ * environ.cc: Add extern declaration for `pcheck_case'.
+ (check_case_init): New function.
+ (struct parse_thing): Add "check_case" option.
+ * errno.cc (_sys_nerrlist): Add text for ECASECLASH.
+ (strerror): Add case branch for ECASECLASH.
+ * fhandler.cc (fhandler_disk_file::open): Check for case clash.
+ * path.cc: Add global variable `pcheck_case'.
+ (struct symlink_info): Add member `case_clash' and method `case_check'.
+ (path_prefix_p_): Call `pathnmatch' instead of `strncasematch'.
+ (pathnmatch): New funtion.
+ (pathmatch): Ditto.
+ (path_conv::check): Add handling for case checking.
+ (symlink): Check for case clash.
+ (symlink_info::check): Add parameter for case checking.
+ Handle case checking.
+ (symlink_info::case_check): New method.
+ (chdir): Don't use unconverted path if pcheck_case==PCHECK_STRICT.
+ * path.h: Add extern declarations for `pathmatch' and
+ `pathnmatch'.
+ (enum case_checking): New enumeration type describing
+ the case checking behaviour of path conversion routines.
+ (class path_conv): Add member `case_clash'.
+ * syscalls.cc (_link): Check for case clash.
+
+Thu Apr 12 12:49:53 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (mkfifo): New function stub.
+
+2001-04-12 Robert Collins <rbtcollins@hotmail.com>
+
+ * configure.in: Remove PTH_ALLOW.
+ * cygwin.din: Remove @PTH_ALLOW@ prefixes to pthread functions. Add
+ new pthread exports.
+ * pthread.cc: New wrapper functions for the above new exports.
+ * sched.cc (valid_sched_parameters): New function.
+ (sched_setparam): Use it.
+ (sched_set_thread_priority): New function. Used by pthread_sched*.
+ * thread.cc (pthread_key_destructor::InsertAfter): New function.
+ (pthread_key_destructor::UnlinkNext): New function.
+ (pthread_key_destructor::Next): New function.
+ (pthread_key_destructor_list::Insert): New function.
+ (pthread_key_destructor_list::Remove): New function.
+ (pthread_key_destructor_list::Pop): New function.
+ (pthread_key_destructor::pthread_key_destructor): New function.
+ (pthread_key_destructor_list::IterateNull): New function.
+ (MTinterface::Init): Initialise new member.
+ (pthread::pthread): Initialise new members.
+ (pthread::create): Copy new attributes. Set the new thread priority.
+ (pthread_attr::pthread_attr): Initialise new members.
+ (pthread_key::pthread_key): Setup destructor function.
+ (pthread_key::~pthread_key): Remove destructor function.
+ (pthread_mutexattr::pthread_mutexattr): New function.
+ (pthread_mutexattr::~pthread_mutexattr): New function.
+ (__pthread_once): New function.
+ (__pthread_cleanup): New function.
+ (__pthread_cancel): New function.
+ (__pthread_setcancelstate): New function.
+ (__pthread_setcanceltype): New function.
+ (__pthread_testcancel): New function.
+ (__pthread_attr_getinheritsched): New function.
+ (__pthread_attr_getschedparam): New function.
+ (__pthread_attr_getschedpolicy): New function.
+ (__pthread_attr_getscope): New function.
+ (__pthread_attr_setinheritsched): New function.
+ (__pthread_attr_setschedparam): New function.
+ (__pthread_attr_setschedpolicy): New function.
+ (__pthread_attr_setscope): New function.
+ (__pthread_exit): Call any key destructors on thread exit.
+ (__pthread_join): Use the embedded attr values.
+ (__pthread_detach): Use the embedded attr values.
+ (__pthread_getconcurrency): New function.
+ (__pthread_getschedparam): New function.
+ (__pthread_key_create): Pass the destructor on object creation.
+ (__pthread_key_delete): Correct incorrect prototype.
+ (__pthread_setconcurrency): New function.
+ (__pthread_setschedparam): New function.
+ (__pthread_cond_timedwait): Support static mutex initialisers.
+ (__pthread_cond_wait): Ditto.
+ (__pthread_mutex_getprioceiling): New function.
+ (__pthread_mutex_lock): Support static mutex initialisers.
+ (__pthread_mutex_trylock): Ditto.
+ (__pthread_mutex_unlock): Ditto.
+ (__pthread_mutex_destroy): Ditto.
+ (__pthread_mutex_setprioceiling): New function.
+ (__pthread_mutexattr_getprotocol): New function.
+ (__pthread_mutexattr_getpshared): New function.
+ (__pthread_mutexattr_gettype): New function.
+ (__pthread_mutexattr_init): New function.
+ (__pthread_mutexattr_destroy): New function.
+ (__pthread_mutexattr_setprotocol): New function.
+ (__pthread_mutexattr_setprioceiling): New function.
+ (__pthread_mutexattr_getprioceiling): New function.
+ (__pthread_mutexattr_setpshared): New function.
+ (__pthread_mutexattr_settype): New function. Remove stubs for non
+ MT_SAFE compilation.
+ * thread.h: Remove duplicate #defines. Add prototypes for new
+ functions in thread.cc.
+ (pthread_key_destructor): New class.
+ (pthread_key_destructor_list): New class.
+ (pthread_attr): Add new members.
+ (pthread): Remove members that are duplicated in the pthread_attr
+ class.
+ (pthread_mutex_attr): Add new members.
+ (pthread_once): New class.
+ * include/pthread.h: Add prototypes for new functions exported from
+ cygwin1.dll. Remove typedefs.
+ * include/sched.h: Add prototypes for new functions in sched.cc.
+ * include/cygwin/types.h: Add typedefs from pthread.h
+
+Tue Apr 10 22:02:53 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (struct symlink_info): Add extn and ext_tacked_on fields.
+ (path_conv::check): Only tack on extension if a known one didn't
+ already exist.
+ (suffix_scan::has): Return pointer to known extension.
+ (symlink_info::check): Record location of extension, if any.
+
+2001-04-09 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (class fhandler_socket): Add members and methods to
+ support secure connections on AF_UNIX sockets.
+ * fhandler_socket.cc (fhandler_socket::set_connect_secret): New method.
+ (fhandler_socket::get_connect_secret): Ditto.
+ (fhandler_socket::create_secret_event): Ditto.
+ (fhandler_socket::close_secret_event): Ditto.
+ (fhandler_socket::check_peer_secret_event): Ditto.
+ (fhandler_socket::fixup_after_fork): Duplicate secret event to child.
+ (fhandler_socket::dup): Copy address family.
+ (fhandler_socket::close): Close secret event.
+ * net.cc (get_inet_addr): Read secret cookie.
+ (cygwin_connect): Check if peer knows secret cookie value.
+ (cygwin_accept): Ditto. Copy address family to newly created socket.
+ (cygwin_bind): Generate and write secret cookie.
+ (wsock_init): Initialize random number generator.
+
+Sun Apr 8 20:40:58 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * Makefile.in: Put -lgcc last in list of libraries, since stdc++
+ library needs it.
+ * cygwin.din: Remove obsolete "__empty" export.
+ * exceptions.cc (call_signal_handler_now): Force inclusion of function
+ even when -finline-functions is specified.
+ * sigproc.h: Remove obsolete call_signal_handler declaration.
+
+Sun Apr 8 20:36:55 2001 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+
+ * fhandler_console.cc (cp_get_internal): New function.
+ (cp_convert): New function.
+ (con_to_str): New function.
+ (str_to_con): New function.
+ (fhandler_console::read): Replace OemToCharBuff with con_to_str.
+ (fhandler_console::write_normal): Replace CharToOemBuff with str_to_con.
+
+Thu Apr 5 22:41:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (stat_worker): Fix conditional which still allowed
+ successful stat'ing of non-existant files.
+
+Wed Apr 4 10:37:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * child_info.h: Bump magic number for fork/exec/spawn.
+
+Tue Apr 3 20:06:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * errno.cc (errmap): Map ERROR_FILE_INVALID to ENXIO.
+
+Mon Apr 2 22:48:58 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygrun.c (main): Fix compiler warning.
+ * gmon.c (_mcleanup): Ditto.
+ * profil.c (profile_off): Ditto.
+
+ * net.cc (find_winsock_errno): New function.
+ (__set_winsock_errno): Use find_winsock_errno.
+ (cygwin_setsockopt): Detect SO_ERROR for debugging.
+ (cygwin_getsockopt): Ditto. Translate error when getsockopt returns
+ SO_ERROR.
+ * winsup.h: regparmize __set_winsock_errno.
+ * include/sys/strace.h: Document that strace functions can't use
+ regparm.
+
+2001-04-02 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * fhandler.cc (fhandler_disk_file::open): Avoid checking a magic
+ number of a directory.
+
+Mon Apr 2 00:24:08 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * shared_info.h (mount_info): Remove mnt_ elements.
+ * thread.h (struct _winsup_t): Add mnt_ elements.
+ * path.cc (fillout_mntent): Use mnt_ elements from reent_winsup ().
+
+Sun Apr 1 20:10:34 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (sigframe::call_signal_handler): Return value of
+ call_signal_handler_now.
+ * sigproc.h (sigframe): Use constructor.
+ * syscalls.cc (_read): Correct errno test prior to calling signal
+ handler.
+
+Sun Apr 1 00:38:06 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (sigframe::call_signal_handler): Move outside of "C"
+ block or some compilers will complain.
+
+Sun Apr 1 00:24:14 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (call_signal_handler_now): Rename from
+ call_signal_handler to avoid C++ confusion.
+
+Sun Apr 1 00:08:15 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (fillout_mntent): Always remove drive root directories from
+ future consideration by "/cygdrive" reporting.
+ (cygdrive_getmnt): Avoid reporting removable drives or drives with no
+ media mounted.
+
+Sat Mar 31 21:56:19 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * thread.h (struct _winsup_t): Remove obsolete elements. Add
+ available_drives element.
+ * path.cc (mount_info::getmntent): Report "/cygdrive" drives when
+ mounted drives are exhausted.
+ (fillout_mntent): New function.
+ (mount_item::getmntent): Use fillout_mntent.
+ (cygdrives_mntent): New function. Returns next available "/cygdrive".
+ (setmntent): Initialize available "/cygdrives".
+ * syscalls.cc: Remove some if 0'ed code.
+ * times.cc (timezone): Use more descriptive variable name.
+
+Sat Mar 31 18:59:52 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.h (class sigframe): Implement 'unregister()' method.
+ (sigframe::~sigframe): Use unregister method.
+ (sigframe::call_signal_handler): Declare new method.
+ * exceptions.cc (sigframe::call_signal_handler): New method.
+ Unregisters current sigframe before calling signal handler.
+ (setup_handler): Clear waiting threads prior to arming signal_arrived.
+ * syscalls.cc (_read): Change goto to loop. Recalculate sigframe
+ inside of loop so that constructor is called when appropriate.
+ * wait.cc (wait4): Ditto.
+
+ * signal.cc: Change "sig" to "signal" in debugging messages throughout.
+ * sigproc.cc: Ditto.
+
+Sat Mar 31 17:12:08 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_serial.cc (fhandler_serial::raw_write): Close protected
+ handles with ForceCloseHandle or suffer spurious warnings.
+
+Sat Mar 31 16:23:32 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler.cc (fhandler_base::read): Remove special handling of CTRL-Z.
+
+Sat Mar 31 11:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (class fhandler_console): Add members `insert_mode'.
+ * fhandler_console.cc (fhandler_console::dup): Duplicate `insert_mode'.
+ (fhandler_console::fhandler_console): Initialize `insert_mode'.
+ (fhandler_console::char_command): Add terminal capabilities
+ "enter insert mode" = \E[4h and "exit insert mode" = \E[4l.
+ Care for insert mode on terminal capability "repeat char" = \E[x;yb.
+ (fhandler_console::write_normal): Care for insert mode before writing
+ to the console.
+ (array keytable): Add keymapping for modified cursor and control
+ block keys (xterm like).
+
+Fri Mar 30 13:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (class fhandler_console): Add members `savebufsiz' and
+ `savebuf' to allow save/restore of screen.
+ * fhandler_console.cc (fhandler_console::dup): Duplicate `savebufsiz'
+ and `savebuf'.
+ (fhandler_console::fhandler_console): Initialize `savebufsiz' and
+ `savebuf'.
+ (fhandler_console::char_command): Add terminal capabilities
+ "save screen content" = \E[?47h and "restore screen content" = \E[?47l.
+
+Wed Mar 28 19:28:50 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (chdir): Eat trailing whitespace on input path.
+
+Tue Mar 27 22:38:42 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * lib/_cygwin_S_IEXEC.c: Remove "const" from globals or they never seem
+ to be defined. Wrap definitions in extern "C". Include winsup.h to
+ assure proper definitions.
+
+ * dcrt0.cc (dll_crt0_1): Call stdio_init after premain run so that
+ binmode.o, etc., will control default stdio settings.
+ * dtable.cc (dtable::init_std_file_from_handle): Allow __fmode to force
+ binmode/textmode settings. Default pipes to binmode.
+
+Tue Mar 27 11:31:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Fix conditional for previous patch.
+
+Mon Mar 26 18:48:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Outflank copy-on-write problem on 9x by
+ setting access mode to FILE_MAP_READ when read access is requested.
+
+Sun Mar 25 20:12:21 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dlfcn.cc (check_access): Eliminate.
+ (check_path_access): Use passed in path_conv buf.
+ (get_full_path_of_dll): Use passed in name buf to avoid a static. Rip
+ out most of the path checking since LoadLibrary will do all of this
+ automatically.
+ (dlopen): Set errno when appropriate (may not be compliant?).
+ * environ.cc (posify): Don't pass in "native" path if it seems to
+ actually be posix.
+
+Thursday Mar 22 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * fhandler.h (fhandler_dev_clipboard): Extend to support writing.
+ * fhandler_clipboard.cc (fhandler_dev_clipboard::fhandler_dev_clipboard):
+ Initialize new fields. Open clipboard here.
+ (fhandler_dev_clipboard::dup): New method.
+ (fhandler_dev_clipboard::open): Accomodate new fields. Register
+ clipboard here, if appropriate.
+ (set_clipboard): New function. Moves buffer to clipboard.
+ (fhandler_dev_clipboard::write): Truly implement clipboard writing.
+ (fhandler_dev_clipboard::read): Reimplement to allow successive reads.
+ (fhandler_dev_clipboard::lseek): Truly implement seeks in clipboard.
+ (fhandler_dev_clipboard::close): Clear out new fields. Support
+ sequential reads and sequential writes. Support for binary data via a
+ native clipboard format.
+
+2001-03-22 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_console.cc (fhandler_console::set_default_attr): Update
+ console color attributes on tty reset.
+
+Wed Mar 21 22:12:36 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * autoload.cc (kernel32_init): New function for kernel32 autoload
+ initialization.
+ (SignalObjectAndWait): Add conditional load of this function when it is
+ available.
+
+2001-03-21 Robert Collins <rbtcollins@hotmail.com>
+
+ * sched.cc: New file. Implement sched*.
+ * include/sched.h: New file. User land includes for sched*.
+ * Makefile.in: Add sched.o
+ * cygwin.din: Add exports for sched*.
+
+Tue Mar 20 14:48:46 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dtable.cc: Guard against new winsock.h/winsock2.h warnings when
+ mixing winsock*.h and sys/types.h.
+ * fhandler_socket.cc: Ditto.
+ * net.cc: Ditto.
+ * select.cc: Ditto.
+ * exceptions.cc: Remove unneeded define.
+
+Mon Mar 19 17:43:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (interruptible): Update debugging output.
+ (setup_handler): Ensure that wait_sig loop wakes up when we punt on
+ sending a signal.
+ * poll.cc (poll): Add signal guard here.
+
+2001-03-19 Egor Duda <deo@logos-m.ru>
+
+ * tty.h (tty::create_inuse): Add new parameter to allow non-
+ inheritable 'inuse' events.
+ * tty.cc (tty::create_inuse): Use new parameter.
+ * fhandler_tty.cc (fhandler_tty_master::init): Ditto.
+ * fhandler_tty.cc (fhandler_pty_master::open): Ditto.
+ * fhandler_tty.cc (fhandler_tty_master::init): Create master_alive
+ event.
+ * tty.cc (tty_list::terminate): Close master_alive event.
+ * fhandler_tty.cc (fhandler_tty_common::close): Send EOF to slaves
+ when master side is closed.
+
+Mon Mar 19 14:32:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (map::get_list_by_fd): Avoid calling `get_namehash' when
+ file descriptor is -1.
+
+Sat Mar 17 18:30:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (check_posix_perm): New static function.
+ (fpathconf): Add _PC_POSIX_PERMISSIONS and _PC_POSIX_SECURITY
+ support.
+ (pathconf): Ditto.
+ * include/cygwin/version.h: Bump API minor number to 37.
+
+2001-03-18 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (fhandler_tty_slave): Declare new methods.
+ * select.cc (fhandler_tty_slave::select_read): New method.
+ * select.cc (fhandler_tty_slave::ready_for_read): Ditto.
+ * select.cc (verify_tty_slave): New function.
+ * fhandler_termios.cc (fhandler_termios::line_edit): Empty input
+ buffer on signal.
+ * fhandler_tty.cc (fhandler_tty_slave::read): Check for input data
+ after reading from pipe. Reset event if input pipe is empty.
+ * tty.h (class tty): Allow creating events with manual reset.
+ * tty.cc (tty::get_event): Use manual_reset flag.
+ * tty.cc (tty::common_init): Create input_available_event with
+ manual reset.
+
+Sat Mar 17 21:48:03 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * external.cc (fillout_pinfo): Match windows pid, as well as cygwin pid
+ when passed in pid. Don't prematurely break when searching for a pid.
+
+ * thread.h (_winsup_t): Eliminate unneeded field.
+
+Sat Mar 17 20:46:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (get_95_ifconf): Use strcasematch instead of strcasecmp.
+ * syscalls.cc (_unlink): Ditto.
+ (_rename): Ditto.
+
+Sat Mar 17 12:43:15 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (suffix_scan::next): Avoid searching for foo.lnk twice when
+ input is "foo".
+
+Sat Mar 17 18:10:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * net.cc (cygwin_socket): Set protocol to 0 when address family is
+ AF_UNIX to avoid WSAEPROTONOSUPPORT error.
+
+Sat Mar 17 09:51:32 2001 Mathew Brozowski <brozow@tavve.com>
+
+ * net.cc (cygwin_socket): Pass protocol parameter to socket call.
+
+Sat Mar 17 02:05:38 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dir.cc (readdir): Use strcasematch for consistency.
+ * path.cc (symlink_info): Eliminate known_suffix.
+ (path_conv::check): Always copy ext_here to end of buffer, if found.
+ (suffix_scan): Eliminate ext_here, add suffixes_start.
+ (suffix_scan::has): Eliminate an argument. Reorganize. Always return
+ pointer to end of input path.
+ (suffix_scan::next): Take a second pass through the suffix list looking
+ for .lnk.
+ (symlink_info::check): Eliminate known_suffix usage.
+
+Sat Mar 17 00:10:52 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (stat_dev): Give devices full read/write by default.
+
+Saturday Mar 17 3:45 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc (MTinterface::CreateCond): Check for null attr pointer.
+
+Fri Mar 16 21:13:23 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_termios.cc (fhandler_termios::line_edit): Don't accept input
+ when a signal is sent or we'll end up in an EOF/signal race.
+
+Fri Mar 16 20:25:40 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc: Translate scan states from defines to enums.
+ (suffix_scan): Rename state to nextstate for clarity.
+ (lnk_match): Change to allow multiple states to indicate that a .lnk
+ has been matched.
+ (suffix_scan::has): Eliminate a goto. Handle .lnk as a special case,
+ since a .lnk may also need to be tacked on the end of a .lnk.
+ (suffix_scan::next): Don't increment next state. Set it specifically.
+ Recognize new .lnk states.
+
+Saturday Mar 17 01:19 2001 Robert Collins rbtcollins@hotmail.com
+
+ * cygwin.din: Export the new functions.
+ * pthread.cc (pthread_cond_*): Add wrapper functions that call
+ __pthread_cond* functions.
+ * thread.cc (__pthread_cond_*): Implement the pthread_cond* functions.
+ * thread.h: Add new class entries and prototypes for __pthread_cond*
+ functions.
+ * include/pthread.h: user land header prototypes for pthread_cond*
+ functions and related defines.
+
+Wed Mar 14 16:30:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * environ.cc (parse_options): Use strtok_r instead of strtok.
+ * security.cc (convert_string_sid_to_sid): Ditto.
+ (aclfromtext): Ditto. Fix buffer usage.
+
+Wed Mar 14 10:11:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (lnk_suffixes): Remove.
+ (class suffix_scan): Add `lnk_state' flag.
+ (suffix_scan::lnk_match): Return state of `lnk_state' now.
+ (suffix_scan::has): Changed behaviour if file has `.lnk' suffix.
+ (suffix_scan::next): Set `lnk_state' where appropriate.
+ (symlink_info::check): Fix a wrong `break'.
+ * syscalls.cc (chown_worker): Change debug statement to reflect
+ lchown fix.
+ (lchown): Call chown_worker with `PC_SYM_NOFOLLOW' instead of
+ `PC_SYM_IGNORE'.
+
+Tue Mar 13 13:52:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_disk_file::fstat): Add correct modes to
+ symlinks when stat'ing on FAT or FAT32 file systems.
+
+2001-03-12 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (fhandler_termios::fixup_after_exec): New function.
+ * fhandler_termios.cc (fhandler_termios::fixup_after_fork): New
+ function. Fixup output handle.
+ * fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Output
+ handle is now fixed up in fhandler_termios::fixup_after_fork().
+
+2001-03-12 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (fhandler_termios::fhandler_termios): Enable fixup
+ after fork.
+ * fhandler_console.cc (fhandler_console::fhandler_console): Fixup
+ after fork is now enabled in the base class constructor.
+
+Mon Mar 12 11:19:41 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * mkvers.sh: Include config.h so that DEBUGGING is correctly defined.
+
+Mon Mar 12 09:47:55 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * spawn.cc (spawn_guts): Don't set EXIT_REPARENTING if parent process
+ is not a cygwin process (suggested by Jason Gouger
+ <cygwin@jason-gouger.com>).
+
+Sun Mar 11 16:00:58 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * child_info.h: Bump magic number for fork/exec/spawn.
+
+Sat Mar 10 20:54:47 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * autoload.cc (noload): Use proper method for multiline strings or
+ newer gcc's complain.
+ * exceptions.cc (unused_sig_wrapper): Ditto.
+ * fhandler.h (fhandler_base): Make get_io_handle and friends return
+ self.
+ * fhandler_tty.cc (fhandler_pty_common::close_on_exec): Accomodate
+ DEBUGGING flag to avoid spurious warnings when inheritance is set.
+
+Sat Mar 10 16:52:12 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * shortcut.c (PATH_ALL_EXEC): Add parentheses to avoid a compiler
+ warning.
+
+ * exceptions.cc (setup_handler): Clarify debugging message.
+ * sigproc.cc (proc_subproc): Remove PROC_CHILDSTOPPED test. It is
+ handled by normal PROC_CLEARWAIT case.
+ (wait_sig): Eliminate "dispatched" tracking. Remove __SIGCHILDSTOPPED
+ test. Decrement counter again before jumping out of
+ InterlockedDecrement loop so that subsequent InterlockedIncrement will
+ keep the counter at the correctly decremented value and also detect
+ when there are pending signals.
+ * sigproc.h: Remove __SIGCHILDSTOPPED element.
+ (procstuff): Remove PROC_CHILDSTOPPED element.
+
+Sat Mar 10 15:22:44 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_rename): Set errno to ENOENT when an old path doesn't
+ exist (from Kazuhiro Fujieda <fujieda@jaist.ac.jp>). Also set EACCES
+ when directory is not writable.
+
+Wed Mar 7 15:49:47 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_read): Change definition to return ssize_t to be
+ consistent with read.
+ (_write): Change definition to return ssize_t to be consistent with
+ write.
+
+Wed Mar 7 01:08:21 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * sigproc.h (sigthread): Declare new methods. Create new winapi_lock
+ field.
+ (sigframe:;set): Call get_winapi_lock after frame is set so that signal
+ handler thread knows not to call SuspendThread.
+ (sigframe::~sigframe): Release winapi_lock.
+ * exceptions.cc (sigthread::get_winapi_lock): New method.
+ (sigthread::release_winapi_lock): New method.
+ (setup_handler): Use get_winapi_lock to ensure that signalled thread is
+ not blocked in a Windows API.
+
+ * path.h (path_types): Avoid broken GCC warning.
+
+Tue Mar 6 14:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (suffix_scan::has): Change order of conditionals
+ to allow checking for .lnk suffixes even if in_suffixes is empty.
+
+Tue Mar 6 13:02:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.c (cygwin_premain0): Add missing parameter.
+ * binmode.c (cygwin_premain0): Ditto.
+ * textmode.c (cygwin_premain0): Ditto.
+
+Tue Mar 6 12:04:00 2001 Jason Tiller <jtiller@sjm.com>
+
+ * auto_load.cc: Add "GetKeyboardLayout" entry in the list of
+ Win32 User32.DLL exports to provide.
+ * fhandler.h (class fhandler_console): Add meta_mask private
+ member to remember which keystroke modifiers should generate
+ META.
+ * fhandler_console.cc (fhandler_console::read): Modify code that
+ tests a keystroke for a META-escaped key to use the 'meta_mask'
+ variable.
+ (fhandler_console::fhandler_console): Add definition for
+ variable "meta_mask" used to determine if a keystroke should be
+ preceded by META in the client console stream. Set meta_mask
+ based on whether or not user's keyboard language is English -
+ non-English keyboards pass AltGr (right <ALT>) unmolested,
+ whereas English keyboards now interpret left- and right-<ALT>
+ as META.
+
+Mon Mar 5 20:15:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * include/a.out.h: Add copyright hint.
+ * include/fcntl.h: Ditto.
+ * include/lastlog.h: Ditto.
+ * include/memory.h: Ditto.
+ * include/mntent.h: Ditto.
+ * include/paths.h: Ditto.
+ * include/poll.h: Ditto.
+ * include/syslog.h: Ditto.
+ * include/termio.h: Ditto.
+ * include/tzfile.h: Ditto.
+ * include/arpa/inet.h: Ditto.
+ * include/asm/byteorder.h: Ditto.
+ * include/asm/socket.h: Ditto.
+ * include/asm/types.h: Ditto.
+ * include/cygwin/if.h: Ditto.
+ * include/cygwin/mtio.h: Ditto.
+ * include/cygwin/rdevio.h: Ditto.
+ * include/cygwin/socket.h: Ditto.
+ * include/net/if.h: Ditto.
+ * include/netinet/in.h: Ditto.
+ * include/netinet/in_systm.h: Ditto.
+ * include/netinet/ip.h: Ditto.
+ * include/netinet/ip_icmp.h: Ditto.
+ * include/netinet/tcp.h: Ditto.
+ * include/sys/cdefs.h: Ditto.
+ * include/sys/cygwin.h: Ditto.
+ * include/sys/ioctl.h: Ditto.
+ * include/sys/mman.h: Ditto.
+ * include/sys/mount.h: Ditto.
+ * include/sys/mtio.h: Ditto.
+ * include/sys/procfs.h: Ditto.
+ * include/sys/resource.h: Ditto.
+ * include/sys/smallprint.h: Ditto.
+ * include/sys/socket.h: Ditto.
+ * include/sys/strace.h: Ditto.
+ * include/sys/syslog.h: Ditto.
+ * include/sys/sysmacros.h: Ditto.
+ * include/sys/termio.h: Ditto.
+ * include/sys/termios.h: Ditto.
+ * include/sys/uio.h: Ditto.
+ * include/sys/un.h: Ditto.
+ * include/sys/utsname.h: Ditto.
+ * include/sys/vfs.h: Ditto.
+ * include/sys/wait.h: Ditto.
+ * regexp/regerror.c: Ditto.
+ * regexp/regexp.h: Ditto.
+ * regexp/regmagic.h: Ditto.
+
+Mon Mar 5 01:25:03 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dlopen.c (dlopen): Return NULL when name is NULL (suggested by
+ chrisiasci@aol.com).
+
+ * cygwin.din: Add a new, internally used export -
+ _check_for_executable.
+ * dcrt0.cc (dll_crt0_1): Set _check_for_executable for older binaries.
+ Pass user_data to premain functions.
+ * fhandler.cc (fhandler_disk_file::open): Only check for executable if
+ the linked program is interested in the executable bit.
+ (fhandler_disk_file::check_execable_p): Delete.
+ * fhandler.h (executable_states): New enumeration of various states of
+ executable bit caring.
+ (fhandler_base::set_execable_p): New method.
+
+ * fhandler_termios.cc (fhandler_termios::line_edit): Flag when a signal
+ has been sent to the tty. Return -1 when this is so.
+ * fhandler_console.cc (fhandler_console::read): Return -1 when signal
+ sending character encountered.
+
+ * path.cc (path_conv::check): Record when path refers to a disk device.
+ Move executable extension check here.
+ (check_sysfile): Accomodate new EXEC path states.
+ (has_suffix): Remove.
+ (next_suffix): Remove.
+ (class suffix_scan): New clas.
+ (suffix_scan::has): New method.
+ (suffix_scan:next): New method.
+ (symlink_info::check): Use suffix_scan method to control for scanning
+ for suffixes.
+ * path.h (path_conv::exec_state): New method.
+ * perprocess.h: Make "C" friendly.
+ * include/cygwin/version.h: Define CYGWIN_VERSION_CHECK_FOR_S_IEXEC.
+ Bump CYGWIN_VERSION_API_MINOR.
+ * include/sys/cygwin.h: Change premain declarations.
+
+ * winsup.h: Move __cplusplus test to after builtin defines.
+
+2001-03-04 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (class fhandler_tty_common): New mutex and event to
+ syncronize input on master tty with slave tty.
+ * fhandler_tty.cc (fhandler_pty_master::accept_input): Use them to
+ syncronize with slave.
+ * fhandler_tty.cc (fhandler_tty_slave::read): Use input mutex and
+ event to syncronize with master. Do not limit amount of data read
+ from master to vmin value. Interrupt on signal and return already
+ read data, if any.
+ * fhandler_tty.cc (fhandler_tty_slave::open): Handle input mutex and
+ event.
+ * fhandler_tty.cc (fhandler_tty_common::close): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::set_close_on_exec): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::dup): Ditto.
+ * tty.h (tty::open_input_mutex): New function.
+ * tty.cc (tty::common_init): Create input mutex and event.
+
+Fri Mar 2 13:32:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (readdir): Fix creating path in symlink check.
+
+Fri Mar 2 12:33:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (readdir): Fix shortcut==symlink condition.
+ * environ.cc: Add extern decl for `allow_winsymlinks'.
+ (struct parse_thing): Add entry for `[no]winsymlinks'.
+ * path.cc (symlink): Change to be able to create both,
+ symlink==shortcut and symlink==systemfile, dependent of
+ the setting of `allow_winsymlinks'.
+ * security.cc (cygwin_logon_user): Add debug output.
+ * shortcut.c: Add defines from path.h.
+ (has_exec_chars): Copy from path.h.
+ (check_shortcut): Check for executable file condition if not a
+ shortcut.
+
+Thu Mar 1 21:06:07 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (sig_handle_tty_stop): Ignore attempts to suspend a
+ process if started by non-cygwin parent.
+
+Thu Mar 1 20:48:11 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * select.cc (peek_console): Don't report read_ready on mouse events
+ unless we are looking for mouse events.
+ * fhandler.h (fhandler_console::mouse_aware): New method.
+
+Wed Feb 28 15:10:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * uinfo.cc: Eliminate `#include <wchar.h>'.
+
+2001-02-28 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_floppy.cc (fhandler_dev_floppy::lseek): Determine
+ drive geometry or partition size to allow seeking from the end of
+ raw floppy device. Don't allow positioning past the end of media or
+ to offsets bigger then max off_t.
+
+2001-02-27 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (class fhandler_console): Make all variables that
+ describe "state" of console to be members of fhandler_console.
+ default_color is now the color which is set when console recieves
+ reset command.
+ * fhandler_console.cc (fhandler_console::fhandler_console): Turn
+ mouse handling and raw keyboard mode off by default. Initialize
+ state information.
+ * fhandler.cc (fhandler_console::set_raw_win32_keyboard_mode): New
+ function.
+ * fhandler_console.cc (fhandler_console::set_default_attr): New
+ function. Reset console attributes to default values.
+ * fhandler_console.cc (fhandler_console::open): Reset attributes.
+ * fhandler_console.cc (fhandler_console::get_win32_attr): New function.
+ Calculate win32-style console attribute based on terminal attributes.
+ * fhandler_console.cc (fhandler_console::set_cursor_maybe): Use
+ member variable.
+ * fhandler_console.cc (fhandler_console::read): If in raw-win32
+ keyboard mode, encode win32 keyboard events in \033{x;y;z;t;u;wK
+ sequences.
+ * fhandler_console.cc (fhandler_console::dup): Copy all state
+ information to the dup()ed handle.
+ * fhandler_console.cc (fhandler_console::scroll_screen): Use current
+ fill-in attribute.
+ * fhandler_console.cc (fhandler_console::clear_screen): Ditto.
+ * fhandler_console.cc (fhandler_console::char_command): Check if we
+ saw '?' symbol by member variable. Set terminal attributes on \033[Xm
+ commands. \033[24m - turn off underline mode, \033[27m - turn off
+ reverse mode, \033[39m - restore default foreground color.
+ \033[49m - restore default background color. \033[2000h - turn on raw
+ keyboard mode, \033[2000l - turn off raw keyboard mode.
+ * fhandler_console.cc (fhandler_console::write): Set attribues to
+ default values on reset command.
+
+2001-02-26 Mike Simons <msimons@moria.simons-clan.com>
+
+ * times.cc (settimeofday): Replace function stub with working code.
+
+Mon Feb 26 10:42:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * strace.cc (strace::vprntf): Move prntf functionality to this function
+ adding an va_list interface to strace.
+ (strace::printf): Calls strace::vprntf now.
+ (strace_printf): New function providing an extern "C" interface to
+ trace output.
+ * include/sys/strace.h: Make plain C clean.
+ (class strace): Add `vprntf' method.
+
+Mon Feb 26 0:10:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * shortcut.c: Remove #include <sys/strace.h>.
+
+Sun Feb 25 10:32:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (symlink): Add a ".lnk" suffix regardless. Add a comment.
+
+Sun Feb 25 10:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * shortcut.c (check_shortcut): Change symlink condition.
+
+Fri Feb 23 10:42:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (fhandler_disk_file::mmap): Use `addr' correctly.
+ * fhandler_mem.cc (fhandler_dev_mem::mmap): Ditto.
+
+Thu Feb 22 17:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (symlink): Keep relative paths relative in the DOS
+ path inside of a shortcut. If that's impossible or the target
+ path is already absolute save an absolute path.
+
+Thu Feb 22 15:33:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygerrno.h: Revert previous patch.
+ * errno.cc: Ditto.
+ * dir.cc: Eliminate `dir_suffixes'.
+ (opendir): Remove usage of `dir_suffixes'.
+ (rmdir): Ditto.
+ * fhandler.cc (fhandler_disk_file::open): Remove usage of
+ `inner_suffixes'.
+ * path.cc: Rename `inner_suffixes' to `lnk_suffixes'.
+ (path_conv::check): Remove usage of `inner_suffixes'.
+ (symlink): Ditto.
+ (symlink_info::check): Handle checking for `.lnk' in path_conv
+ exclusively here.
+ (chdir): Remove usage of `dir_suffixes'.
+ * shortcut.c: Eliminate debug_printf lines.
+ (check_shortcut): Don't set error except on failing ReadFile.
+ * spawn.cc: Remove ".lnk" from `std_suffixes'.
+ * syscalls.cc (_unlink): Remove usage of `inner_suffixes'.
+ Remove ".lnk" from `stat_suffixes'.
+ (_rename): Add check for renaming a symlink to keep the ".lnk"
+ suffix after renaming.
+
+Thu Feb 22 13:38:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * shortcut.c: New file. Provides a C interface to reading of
+ Windows shortcuts to avoid compiler flag `-fvtable-thunks'.
+ * shortcut.h: Ditto.
+ * Makefile.in: Add shortcut.o to DLL_OFILES.
+ * cygerrno.h: Provide a C interface to `geterrno_from_win_error' for
+ using in shortcut.c.
+ * errno.cc (geterrno_from_win_error): Define as extern "C".
+ * path.cc (struct symlink_info): Remove methods `check_shortcut' and
+ `check_sysfile'.
+ (shortcut_header): Move to shortcut.c.
+ (shortcut_initalized): Ditto.
+ (create_shortcut_header): Ditto.
+ (cmp_shortcut_header): Ditto.
+ (symlink_info::check_shortcut): Ditto. Reorganize as a plain C function.
+ (symlink_info::check_sysfile): Redefine as a global function using the
+ same parameter list as `check_shortcut' for clearness.
+ (symlink_info::check): Change parameter list for calls to
+ `check_shortcut' and `check_sysfile'.
+
+Thu Feb 22 12:04:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_disk_file::open): Use `inner_suffixes' when
+ resolving real_path.
+ * path.cc (symlink): Ditto for win32_topath.
+
+Wed Feb 21 22:41:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll.
+ * autoload.cc: Add LoadDLLinitfunc for ole32.dll.
+ Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0
+ and CoCreateInstance@20.
+ * dir.cc (dir_suffixes): New datastructure.
+ (readdir): Check for R/O *.lnk files to hide the suffix.
+ (opendir): Use `dir_suffixes' in path conversion.
+ (rmdir): Ditto.
+ * fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag
+ before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY
+ into account only if the file is no symlink.
+ * path.cc (inner_suffixes): New datastructure.
+ (SYMLINKATTR): Eliminated.
+ (path_conv::check): Use `inner_suffixes' on inner path components.
+ (shortcut_header): New global static variable.
+ (shortcut_initalized): Ditto.
+ (create_shortcut_header): New function.
+ (cmp_shortcut_header): Ditto.
+ (symlink): Create symlinks by creating windows shortcuts. Preserve
+ the old code.
+ (symlink_info::check_shortcut): New method.
+ (symlink_info::check_sysfile): Ditto.
+ (symlink_info::check): Check for shortcuts. Move code reading
+ old system attribute symlinks into symlink_info::check_sysfile().
+ (chdir): Use `dir_suffixes' in path conversion.
+ * security.cc (get_file_attribute): Check for S_IFLNK flag.
+ Force 0777 permissions then.
+ * spawn.cc (std_suffixes): Add ".lnk" suffix.
+ * syscalls.cc (_unlink): Use `inner_suffixes' in path conversion.
+ Check for shortcut symlinks to eliminate R/O attribute before
+ calling DeleteFile().
+ (stat_suffixes): Add ".lnk" suffix.
+ (stat_worker): Force 0777 permissions if file is a symlink.
+
+2001-02-21 Egor Duda <deo@logos-m.ru>
+
+ * sigproc.cc (getsem): Make semaphore always non-inheritable.
+
+Mon Feb 19 22:25:53 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * dcrt0.cc (locale_init): Remove.
+
+2001-02-15 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * cygwin.din: Export rand48 functions.
+ * thread.cc (MTinterface::Init): Remove the initialization of
+ `reent_data'.
+ * dcrt0.cc: Add the initalizer to the declaration of `reent_data'.
+ * include/cygwin/version.h: Bump CYGWIN_VERSION_API_MINOR to 35.
+
+2001-02-16 Egor Duda <deo@logos-m.ru>
+
+ * signal.cc (signal): Prohibit setting handlers for SIGKILL and
+ SIGSTOP
+ * signal.cc (sigaction): Ditto
+ * syscalls.cc (_lseek): Return EINVAL on invalid input
+
+Wed Feb 14 14:54:40 2001 Christophe Iasci <chrisiasci@aol.com>
+
+ * dlfcn.cc (dlopen): Do not call LoadLibrary with a NULL pointer, when
+ the library is not found
+
+2001-02-14 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_console.cc (fhandler_console::char_command): Ignore unknown
+ rendition codes in \033[xx;yym control sequences
+
+Fri Feb 9 23:19:01 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fork.cc (fork_parent): Return EAGAIN when can't record pid.
+ * pinfo.h (pinfo::remember): Return value of call to proc_subproc.
+ * sigproc.cc (proc_subproc): Return error if can't record pid.
+
+Fri Feb 9 12:17:27 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (mknod): Add valid parameters.
+
+Thu Feb 8 22:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Check for reusing a mapping only on MAP_SHARED
+ and on MAP_PRIVATE|MAP_ANON in the special case of offset 0.
+
+Thu Feb 8 21:57:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (class list): Add member `hash'.
+ (list::list): Initialize `hash'.
+ (list::get_list_by_fd): Use filepath hash value to get the correct
+ mapping list if it's not an anonymous mapping.
+ (map::add_list): Initialize `hash' with filepath hash value.
+ (mmap): Check for reusing a mapping only on MAP_SHARED.
+
+Wed Feb 7 18:47:36 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * signal.cc (killpg): Correct first argument.
+
+Wed Feb 7 22:22:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add LoadDLLinitfunc for iphlpapi.dll.
+ Add LoadDLLfuncEx statements for GetIfTable@12 and GetIpAddrTable@12.
+ * fhandler_socket.cc (fhandler_socket::ioctl): Move variable
+ definitions to the beginning of the function to allow better debugging.
+ Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU.
+ * net.cc: Include iphlpapi.h.
+ (get_2k_ifconf): Rewritten. Uses IP Helper API now.
+ (get_nt_ifconf): Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC
+ and SIOCGIFMTU.
+ (get_95_ifconf): Ditto. Renamed from `get_9x_ifconf'.
+ (get_ifconf): Name loopback `lo' instead of `lo0' as in Linux.
+ Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU.
+ Call `get_95_ifconf' only on Windows 95, `get_nt_ifconf' only
+ on Windows NT < Service Pack 3, `get_2k_ifconf otherwise.
+ * include/asm/socket.h: Add defines for SIOCGIFHWADDR, SIOCGIFMETRIC
+ and SIOCGIFMTU.
+ * include/cygwin/if.h: Add `ifr_hwaddr', `ifr_metric' and `ifr_mtu'.
+ (struct ifreq): Add `ifru_hwaddr'.
+
+Tue Feb 6 15:04:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (stat_worker): Add a check for the special case when
+ a process creates a file using mode 000 using ntsec.
+
+Mon Feb 5 17:00:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_base::open): Always add GENERIC_READ access
+ when opening raw disk devices.
+ * fhandler_floppy.cc (fhandler_dev_floppy::lseek): Implement bytewise
+ access.
+ * fhandler_raw.cc (fhandler_dev_raw::open): Always open raw disk device
+ binary.
+ (fhandler_dev_raw::raw_write): Don't drop read buffer content when
+ writing after read.
+
+Mon Feb 5 13:30:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap_record::fixup_map): New method to duplicate
+ the memory protection in a just forked child.
+ (mmap): Realign gran_len to page boundary only on anonymous
+ mapping before saving in the mmap_record.
+ (munmap): Cleanup code.
+ (msync): Ditto.
+ (fixup_mmaps_after_fork): Ditto. Call mmap_record::fixup_map now.
+
+Thu Feb 1 23:08:29 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (creturn): Correctly calculate cygheap_max.
+
+Wed Jan 31 10:04:58 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * shared.cc (shared_info::initialize): Reduce size of heap.
+
+Wed Jan 31 13:22:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * include/sys/resource.h: Fix typo.
+
+Wed Jan 31 13:20:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * include/sys/resource.h: Add RLIMIT_NLIMITS and RLIM_NLIMITS.
+
+Tue Jan 30 18:15:23 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump version to 1.3.0.
+
+Tue Jan 30 8:55:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * pinfo.cc (pinfo::init): Use INVALID_HANDLE_VALUE instead of
+ explicit cast (HANDLE) 0xffffffff.
+ * shared.cc (open_shared): Ditto.
+
+Mon Jan 29 17:15:22 2001 Bill Hegardt <bill@troyxcd.com>
+
+ * fhandler_serial.cc (raw_write): Use local copy of OVERLAPPED
+ structure instead of shared structure to fix a race condition between
+ read/write.
+
+Mon Jan 29 14:30:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Remove obsolete check for MAP_SHARED|MAP_ANON as
+ being invalid.
+
+Mon Jan 29 10:23:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap_record::find_empty): Fix loop condition.
+
+Sun Jan 28 19:40:40 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_link): Make sure that newpath does not exist. Set
+ errno if it does.
+
+Sun Jan 28 19:29:08 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (init_cheap): Don't specify a load address for the heap.
+ It doesn't work on #!*& Windows 9x.
+ (cygheap_init): Move GetUserName to memory_init.
+ * dcrt0.cc (dll_crt0_1): Call new memory_init functin, eliminate call
+ to heap_init.
+ * heap.cc (heap_init): Improve error output.
+ * heap.h: Correct some declarations.
+ * shared.cc (mount_table_init): Remove.
+ (memory_init): Renamed from shared_init. Reorganize to accomodate
+ strange Windows 9x problems with cygheap/heap interaction.
+ * shared_info.h: Rename shared_init to memory_init.
+
+Sun Jan 28 01:25:33 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump API version.
+
+Sun Jan 28 01:18:22 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * cygheap.cc (init_cheap): Move username initialization.
+ (cygheap_init): Here.
+ * shared_info.h (mount_info): Add a sys_mount_table_counter field.
+ (shared_info): Ditto.
+ * path.cc (mount_info::conv_to_win32_path): Check that our mount table
+ is in sync with the system mount table and reinitialize it if not.
+ (mount_info::add_reg_mount): Bump sys_mount_table counters if the
+ system mount table changes.
+ (mount_info::del_reg_mount): Ditto.
+ (mount_info::write_cygdrive_info_to_registry): Ditto.
+ (mount_info::remove_cygdrive_info_from_registry): Ditto.
+
+Sun Jan 28 00:28:30 2001 Christopher Faylor <cgf@cygnus.com>
+
+ Throughout, change 'cygwin_shared.mount' to 'mount_table'.
+ * child_info.h (child_info): Move shared_h, console_h to cygheap. Add
+ mount_h.
+ * cygheap.h (init_cygheap): Add shared_h, console_h.
+ * cygheap.cc (init_cheap): Initialize heap at a fixed location after
+ the shared memory regions. Initialize cygheap->user name here.
+ * dcrt0.cc (dll_crt0_1): Call getpagesize () to initialize constants.
+ Remove cygheap_init since it is done in shared_init now.
+ (_dll_crt0): Initialize mount_h, remove shared_h and console_h
+ initialization.
+ * fhandler_console.cc (console_shared_h): Eliminate.
+ (get_tty_stuff): Use cygheap->console_h rather than console_shared_h.
+ * heap.cc (heap_init): Use page size constant calculated earlier in
+ initialization.
+ * shared.cc: Eliminate cygwin_shared_h. Add cygwin_mount_h.
+ (mount_table_init): New function for initializing a user mount table.
+ (open_shared_file_map): Use constant for shared memory region.
+ Initialize cygheap and mount table here.
+ (open_shared): Improve debugging output.
+ (shared_info::initialize): Eliminate call to mount.init.
+ (shared_terminate): Use cygheap->shared_h. Close cygwin_mount_h.
+ (open_shared_file_map): Eliminate.
+ * shared_info.h (mount_info): Add a version field.
+ (shared_align_past): New macro for calculating location for shared
+ memory regions.
+ * sigproc.cc (init_child_info): Eliminate shared_h, console_h.
+ * spawn.cc (spawn_guts): Pass on cygwin_mount_h iff not a different
+ user.
+ * syscalls.cc (system_info): New global holding system memory defaults.
+ (getpagesize): Use system_info.
+ * uinfo.cc (internal_getlogin): Only fill in user name if nonexistent.
+ * winsup.h: Declare system_info.
+
+ * passwd.cc (read_etc_passwd): Use cygheap->user.name () rather than
+ retrieving the name again.
+
+Sat Jan 27 10:18:02 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.cc (path_conv::check): Detect when path has symlinks.
+ (symlink_info::check): Remove debugging stuff.
+ (chdir): Use posix'ized win32 path if cd'ed to a path using symlinks.
+
+Fri Jan 26 21:20:28 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * exceptions.cc (sigreturn): Call any pending signals prior to
+ resetting the signal mask so that stacked signals behave correctly.
+ (sigdelayed): Avoid a race where a signal could end up calling an
+ incorrect signal handler if two signals come in close together.
+
+Tue Jan 23 21:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (fhandler_disk_file::mmap): Call CreateFileMapping with
+ len != 0 only when performing an anonymous mapping.
+
+Mon Jan 22 15:35:28 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * path.h: Add a new constant.
+ * syscalls.cc (_read): Oscillate errno check.
+
+Mon Jan 22 15:27:12 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * include/cygwin/version.h: Bump API to reflect setlogmask.
+
+Sun Jan 21 22:40:25 2001 Jason Tishler <jt@dothill.com>
+
+ * cygwin.din: Add export for setlogmask().
+ * syslog.cc (setlogmask): New function.
+
+Thu Jan 18 10:27:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * resource.cc (setrlimit): Support RLIMIT_NOFILE.
+
+Wed Jan 17 23:23:12 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (setdtablesize): Call with amount to increment not total
+ amount. Return success or failure error code.
+
+Wed Jan 17 09:47:13 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * autoload.cc (LoadDLLinitfunc): Remove debugging statement.
+
+ * exceptions.cc (sig_handle_tty_stop): Move setting of PID_STOPPED to
+ earlier in interrupt.
+ (interrupt_setup): i.e., here.
+ (sig_handle): Don't queue multiple SIGSTOPS.
+ * fhandler.h (bg_check_types): Enumerate return value of bg_check for
+ clarity.
+ * signal.cc (kill_pgrp): Minor cleanup.
+ * fhandler_termios.cc (fhandler_termios::bg_check): Use enumerated type
+ for function return. Don't raise signal if a signal is already queued.
+ * fhandler_console.cc (fhandler_console::read): Use enumerated return
+ type for bg_check.
+ * select.cc: Ditto, throughout.
+ * read.cc: Ditto, throughout.
+ * termios.cc: Ditto, throughout.
+ (_read): YA interrupt detect simplification.
+ * wait.cc (wait4): Ditto.
+
+Wed Jan 17 10:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygheap.cc (cygheap_user::~cygheap_user): Temporarily
+ disable free'ing memory.
+
+Tue Jan 16 18:01:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Initialize fh to avoid compiler warnings.
+
+Mon Jan 15 21:07:00 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * wait.cc (wait4): Rename variable for consistency. Allow restartable
+ signal behavior.
+
+Mon Jan 15 23:15:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc (mmap): Add more parameter checking. Change error output
+ in case of EINVAL. Treat mmapping /dev/zero like MAP_ANONYMOUS.
+
+Mon Jan 15 20:34:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * mmap.cc: include <unistd.h>. Define some bit operations for
+ the new page map.
+ (mmap_record): Change type of base_address_ to caddr_t.
+ Add map_map_ member. Add several methods to manipulate map_map_.
+ (mmap_record::alloc_map): New method.
+ (mmap_record::free_map): Ditto.
+ (mmap_record::find_empty): Ditto.
+ (mmap_record::map_map): Ditto.
+ (mmap_record::unmap_map): Ditto.
+ (list::add_record): Change return type to `mmap_record *'.
+ Allocate page map.
+ (list::match): New method.
+ (mmap): Partly rewritten to take care for the new page map. Add some
+ parameter checking.
+ (munmap): Ditto.
+
+Mon Jan 15 13:50:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * heap.cc (heap_init): Fix extern declaration of getpagesize.
+ * syscalls.cc (getpagesize): Fix another typo.
+
+Mon Jan 15 12:48:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (getpagesize): Save pagesize in global variable to
+ avoid calling GetSystemInfo too often.
+ * heap.cc (getpagesize): Eliminate.
+ (heap_init): Use getpagesize function from syscalls.cc.
+
+Mon Jan 15 11:56:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * sysconf.cc (sysconf): return `getpagesize ()' on _SC_PAGESIZE
+ request to avoid implementing the same twice.
+
+Sun Jan 14 14:07:50 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * syscalls.cc (_read): Use more lightweight method for determining if
+ read has been interrupted by a signal.
+
+Fri Jan 12 00:35:15 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * debug.h: Add regparm attributes to some functions.
+
+ * signal.cc (sigaction): Don't treat SIGCONT specially.
+
+ * exceptions.cc (interrupt_setup): Save sa_flags of interrupted signal
+ for later use.
+ (sig_handler): Default any stopping signal to SIGSTOP.
+ (call_signal_handler): New function.
+ (sigdelayed0): New function.
+ * sigproc.cc (sigproc_init): Initialize SIGSTOP sigaction for special
+ behavior.
+ * sigproc.h: Define call_signal_handler.
+ * syscalls.cc (_read): Allow restartable signal behavior.
+
+Thu Jan 11 13:17:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (fhandler_base): New method `fixup_mmap_after_fork'.
+ (fhandler_disk_file: Ditto.
+ (fhandler_dev_mem): Ditto.
+ * fhandler_mem.cc (fhandler_dev_mem::open): Set OBJ_INHERIT attribute
+ for device\physicalmemory handle.
+ (fhandler_dev_mem::mmap): Ditto.
+ * fhandler_mem.cc (fhandler_dev_mem::fixup_mmap_after_fork): New
+ method.
+ * mmap.cc (mmap_record): Add private `fdesc_' member. Change
+ constructor accordingly.
+ (get_fd): New method.
+ (mmap): Use new mmap_record constructor.
+ (fhandler_base::fixup_mmap_after_fork): New method.
+ (fhandler_disk_file::fixup_mmap_after_fork): Ditto.
+ (fixup_mmaps_after_fork): Call `fixup_mmap_after_fork' of appropriate
+ fhandler class.
+
+Wed Jan 10 22:08:30 2001 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
+
+ * sigproc.cc (wait_sig): Allow SIGCONT when stopped.
+
+Tue Jan 9 16:55:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ Patch suggested by René Møller Fonseca <fonseca@mip.sdu.dk>
+ * include/sys/socket.h: Change prototype to have 2nd parameter `const'.
+ * net.cc (cygwin_bind): Change 2nd parameter to `const'.
+
+Sun Jan 7 22:59:37 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * pinfo.cc (codepage_init): Move function.
+ * environ.cc (codepage_init): To here.
+ * exceptoins.cc (SIG_NONMASKABLE): Remove SIGCONT from consideration
+ since it is supposed to be maskable.
+ * signal.cc (sigaction): Ditto.
+ * sigproc.cc (wait_sig): Ditto.
+ * winsup.h: Eliminate global declaration of codepage_init.
+
+Thu Jan 5 9:33:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * resource.cc (getrlimit): Set errno on EFAULT instead of returning
+ it.
+ (setrlimit): Ditto.
+
+Thu Jan 5 3:38:00 2001 David Sainty <David.Sainty@optimation.co.nz>
+
+ * resource.cc (setrlimit): Prevent failing with an error when the
+ operation would not have changed anything.
+
+Thu Jan 4 10:29:54 2001 Earnie Boyd <earnie_boyd@yahoo.com>
+
+ * thread.cc: Need LONG_MAX definition.
+
+Wed Jan 3 13:47:23 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * thread.cc (MTinterface::CreateSemaphore): Correctly set semaphore
+ max.
+
+Wed Jan 3 09:44:51 2001 Christopher Faylor <cgf@cygnus.com>
+
+ * fhandler_console.cc (fhandler_console::read): Restore missing test
+ for code page before doing OemToCharBuff.
+
+Wed Jan 3 09:20:20 2001 Jason Tishler <jt@dothill.com>
+
+ * include/cygwin/version.h: Fix typo in CYGWIN_VERSION_DLL_COMBINED
+ macro.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
new file mode 100644
index 00000000000..edcf6de1559
--- /dev/null
+++ b/winsup/cygwin/Makefile.in
@@ -0,0 +1,259 @@
+# Makefile.in for Cygwin.
+# Copyright 1995, 1996, 1997, 1998, 1999, 2000, 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.
+
+# This makefile requires GNU make.
+
+SHELL:=@SHELL@
+srcdir:=@srcdir@
+objdir:=.
+
+CONFIG_DIR:=$(srcdir)/config/@CONFIG_DIR@
+VPATH:=$(srcdir):$(CONFIG_DIR):$(srcdir)/regexp:$(srcdir)/lib
+
+target_alias:=@target_alias@
+build_alias:=@build_alias@
+host_alias:=@host_alias@
+prefix:=@prefix@
+
+program_transform_name:=@program_transform_name@
+exec_prefix:=@exec_prefix@
+bindir:=@bindir@
+libdir:=@libdir@
+ifeq ($(target_alias),$(host_alias))
+ifeq ($(build_alias),$(host_alias))
+tooldir:=$(exec_prefix)
+else
+tooldir:=$(exec_prefix)/$(target_alias)
+endif
+else
+tooldir:=$(exec_prefix)/$(target_alias)
+endif
+datadir:=@datadir@
+infodir:=@infodir@
+includedir:=@includedir@
+
+INSTALL:=@INSTALL@
+INSTALL_PROGRAM:=@INSTALL_PROGRAM@
+
+#
+# --enable options from configure
+#
+MT_SAFE = @MT_SAFE@
+DEFS = @DEFS@
+
+CC:=@CC@
+# FIXME: Which is it, CC or CC_FOR_TARGET?
+CC_FOR_TARGET:=$(CC)
+CFLAGS:=@CFLAGS@
+CFLAGS+=-MD -fbuiltin
+CXX:=@CXX@
+CXXFLAGS:=@CXXFLAGS@
+
+# For linking mount, etc. crt0.o isn't accessable in a fresh build.
+EXE_LDFLAGS:=@EXE_LDFLAGS@
+
+AR:=@AR@
+AR_FLAGS:=qv
+RANLIB:=@RANLIB@
+LD:=@LD@
+DLLTOOL:=@DLLTOOL@
+WINDRES:=@WINDRES@
+AS:=@AS@
+LDSCRIPT=cygwin.sc
+
+#
+# Include common definitions for winsup directory
+#
+include $(srcdir)/../Makefile.common
+
+INSTALL_DATA:=$(SHELL) $(updir1)/install-sh -c
+
+@SET_MAKE@
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $${rootme}/../../expect/expect$(EXEEXT) ] ; then \
+ echo $${rootme}/../../expect/expect$(EXEEXT) ; \
+ else echo expect ; fi`
+
+RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
+ echo $${srcdir}/../dejagnu/runtest ; \
+ else echo runtest; fi`
+RUNTESTFLAGS =
+
+# Parameters used in building the cygwin.dll.
+# We build as new-cygwin.dll and rename at install time to overcome
+# native rebuilding issues (we don't want the build tools to see a partially
+# built cygwin.dll and attempt to use it instead of the old one).
+
+DLL_NAME:=cygwin1.dll
+LIB_NAME:=libcygwin.a
+DEF_FILE:=cygwin.def
+DLL_ENTRY:=@DLL_ENTRY@
+
+LIBGMON_A:=libgmon.a
+GMON_START:=gcrt0.o
+
+# Some things want these from libc, but they have their own static
+# data which apps can get to, which is a pain in the dll, so we
+# include them directly into the library.
+
+LIBCOS:=${sort ${addsuffix .o,${basename ${notdir ${wildcard $(srcdir)/lib/*.c}}}} \
+ ${addsuffix .o,${basename ${notdir ${wildcard $(srcdir)/lib/*.cc}}}}}
+
+# Build all source files in the config directory
+
+EXTRA_DLL_OFILES:=${addsuffix .o,${basename ${notdir ${wildcard $(CONFIG_DIR)/*.c}}}}
+
+EXTRA_OFILES=$(bupdir1)/libiberty/random.o $(bupdir1)/libiberty/strsignal.o
+
+MALLOC_OFILES=@MALLOC_OFILES@
+
+DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
+
+DLL_OFILES:=assert.o autoload.o cygheap.o cygserver_client.o cygserver_shm.o \
+ cygserver_transport.o cygserver_transport_pipes.o dcrt0.o debug.o \
+ delqueue.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_dsp.o fhandler_floppy.o fhandler_mem.o fhandler_random.o \
+ fhandler_raw.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \
+ fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \
+ fork.o glob.o grp.o heap.o init.o ioctl.o ipc.o localtime.o malloc.o \
+ miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \
+ pthread.o regexp.o regerror.o regsub.o registry.o resource.o scandir.o \
+ sched.o sec_acl.o sec_helper.o security.o select.o shared.o shm.o \
+ shortcut.o signal.o sigproc.o \
+ smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o \
+ syslog.o termios.o thread.o times.o tty.o uinfo.o uname.o wait.o \
+ wincap.o window.o \
+ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
+
+GMON_OFILES:= gmon.o mcount.o profil.o
+
+.PHONY: all force dll_ofiles install all_target install_target all_host install_host \
+ install install_target install-libs install-headers
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .def .a .o .d
+
+all_host=@all_host@
+install_host=@install_host@
+
+all: all_target $(all_host)
+
+all_target: $(LIB_NAME) automode.o binmode.o textmode.o $(LIBGMON_A) cygserver.exe
+
+all_host: new-$(LIB_NAME) cygrun.exe
+
+force:
+
+install: install-bin install-libs install-headers $(install_host) $(install_target)
+
+install-bin: cygserver.exe
+ $(INSTALL_PROGRAM) cygserver.exe $(bindir)/cygserver.exe
+
+install-libs: $(LIB_NAME)
+ $(INSTALL_DATA) new-$(DLL_NAME) $(bindir)/$(DLL_NAME); \
+ for i in $(LIB_NAME) $(GMON_START) $(LIBGMON_A) automode.o binmode.o textmode.o ; do \
+ $(INSTALL_DATA) $$i $(tooldir)/lib/$$i ; \
+ done
+
+install-headers:
+ cd $(srcdir); \
+ for sub in `find include -name '[a-z]*' -type d -print | sort`; do \
+ for i in $$sub/*.h ; do \
+ $(INSTALL_DATA) $$i $(tooldir)/$$sub/`basename $$i` ; \
+ done ; \
+ done ; \
+ $(INSTALL_DATA) regexp/regexp.h $(tooldir)/include/regexp.h
+
+install_host:
+
+clean:
+ -rm -f *.o *.dll *.a *.exp junk *.base version.cc regexp/*.o winver_stamp *.exe *.d
+
+maintainer-clean realclean: clean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -fr configure
+
+# Rule to build libcygwin.a
+
+# Rule to make stub library used by testsuite
+
+# dependency set to $(LIB_NAME) to accomodate make -j2.
+# Otherwise dlltool gets confused. cgf (11-16-2000)
+new-$(LIB_NAME): $(LIB_NAME)
+ $(DLLTOOL) --as=$(AS) --dllname new-$(DLL_NAME) --def $(DEF_FILE) --output-lib new-templib.a
+ $(AR) rcv new-templib.a $(LIBCOS)
+ mv new-templib.a new-$(LIB_NAME)
+
+# Rule to build cygwin.dll
+
+new-$(DLL_NAME): $(LDSCRIPT) $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
+ $(CXX) $(CXXFLAGS) -nostdlib -Wl,-T$(firstword $^) -Wl,--out-implib,$(LIB_NAME) -shared -o $@ \
+ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o winver.o \
+ $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) \
+ -lstdc++ -lgcc -lshell32 -luuid
+
+$(LIB_NAME): new-$(DLL_NAME) $(LIBCOS)
+ $(AR) rcv $(LIB_NAME) $(LIBCOS)
+
+dll_ofiles: $(DLL_OFILES)
+
+$(LIBGMON_A): $(GMON_OFILES) $(GMON_START)
+ $(AR) rcv $(LIBGMON_A) $(GMON_OFILES)
+
+version.cc winver.o: winver_stamp
+ @ :
+
+winver_stamp: mkvers.sh include/cygwin/version.h winver.rc $(DLL_OFILES)
+ @echo "Making version.o and winver.o";\
+ $(SHELL) ${word 1,$^} ${word 2,$^} ${word 3,$^} $(WINDRES) && \
+ $(CXX) -c -o version.o version.cc &&\
+ touch $@
+
+cygrun.exe : cygrun.o $(LIB_NAME) $(w32api_lib)/libuser32.a \
+ $(w32api_lib)/libshell32.a $(w32api_lib)/libkernel32.a
+ $(CC) -nodefaultlibs -o $@ $^
+
+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_client_outside.o: cygserver_client.cc
+ $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
+
+cygserver_shm_outside.o: cygserver_shm.cc
+ $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $<
+
+cygserver.exe: cygserver.o cygserver_shm_outside.o cygserver_transport_outside.o cygserver_transport_pipes_outside.o cygserver_client_outside.o wincap.o smallprint.o
+ $(CXX) -o $@ $^
+#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
+
+#
+
+Makefile: cygwin.din
+
+$(DEF_FILE): cygwin.din config.status
+ $(SHELL) config.status
+
+winsup.h: config.h
+
+deps:=${wildcard *.d}
+ifneq (,$(deps))
+include $(deps)
+endif
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
new file mode 100644
index 00000000000..ffd9f0078a7
--- /dev/null
+++ b/winsup/cygwin/autoload.cc
@@ -0,0 +1,494 @@
+/* autoload.cc: all dynamic load stuff.
+
+ Copyright 2000, 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. */
+
+#include "winsup.h"
+#define USE_SYS_TYPES_FD_SET
+#include <winsock2.h>
+
+/* Macro for defining "auto-load" functions.
+ * Note that this is self-modifying code *gasp*.
+ * The first invocation of a routine will trigger the loading of
+ * the DLL. This will then be followed by the discovery of
+ * the procedure's entry point, which is placed into the location
+ * pointed to by the stack pointer. This code then changes
+ * the "call" operand which invoked it to a "jmp" which will
+ * transfer directly to the DLL function on the next invocation.
+ *
+ * Subsequent calls to routines whose transfer address has not been
+ * determined will skip the "load the dll" step, starting at the
+ * "discovery of the entry point" step.
+ *
+ * So, immediately following the the call to one of the above routines
+ * we have:
+ * DLL info (4 bytes) Pointer to a block of information concerning
+ * the DLL (see below).
+ * DLL args (4 bytes) The number of arguments pushed on the stack by
+ * the call. If this is an odd value then this
+ * is a flag that non-existence of this function
+ * is not a fatal error
+ * func name (n bytes) asciz string containing the name of the function
+ * to be loaded.
+ *
+ * The DLL info block consists of the following
+ * load_state (4 bytes) Pointer to a word containing the routine used
+ * to eventually invoke the function. Initially
+ * points to an init function which loads the
+ * DLL, gets the process's load address,
+ * changes the contents here to point to the
+ * function address, and changes the call *(%eax)
+ * to a jmp func. If the initialization has been
+ * done, only the load part is done.
+ * DLL handle (4 bytes) The handle to use when loading the DLL.
+ * DLL locker (4 bytes) Word to use to avoid multi-thread access during
+ * initialization.
+ * extra init (4 bytes) Extra initialization function.
+ * DLL name (n bytes) asciz string containing the name of the DLL.
+ */
+
+/* LoadDLLprime is used to prime the DLL info information, providing an
+ additional initialization routine to call prior to calling the first
+ function. */
+#define LoadDLLprime(dllname, init_also) __asm__ (" \n\
+ .section ." #dllname "_info,\"w\" \n\
+ .linkonce \n\
+ .long std_dll_init \n\
+ .long 0 \n\
+ .long -1 \n\
+ .long " #init_also " \n\
+ .asciz \"" #dllname "\" \n\
+ .text \n\
+");
+
+/* Create a "decorated" name */
+#define mangle(name, n) #name "@" #n
+
+/* Standard DLL load macro. Invokes a fatal warning if the function isn't
+ found. */
+#define LoadDLLfunc(name, n, dllname) LoadDLLfuncEx (name, n, dllname, 0)
+
+/* Main DLL setup stuff. */
+#define LoadDLLfuncEx(name, n, dllname, notimp) \
+ LoadDLLprime (dllname, dll_func_load) \
+ __asm__ (" \n\
+ .section ." #dllname "_text,\"wx\" \n\
+ .global _" mangle (name, n) " \n\
+ .global _win32_" mangle (name, n) " \n\
+ .align 8 \n\
+_" mangle (name, n) ": \n\
+_win32_" mangle (name, n) ": \n\
+ movl (1f),%eax \n\
+ call *(%eax) \n\
+1:.long ." #dllname "_info \n\
+ .long " #n "+" #notimp " \n\
+ .asciz \"" #name "\" \n\
+ .text \n\
+");
+
+/* DLL loader helper functions used during initialization. */
+
+/* The function which finds the address, given the name and overwrites
+ the call so that future invocations go straight to the function in
+ the DLL. */
+extern "C" void dll_func_load () __asm__ ("dll_func_load");
+
+/* Called by the primary initialization function "init_std_dll" to
+ setup the stack and eliminate future calls to init_std_dll for other
+ functions from this DLL. */
+extern "C" void dll_chain () __asm__ ("dll_chain");
+
+/* called by the secondary initialization function to call dll_func_load. */
+extern "C" void dll_chain1 () __asm__ ("dll_chain1");
+
+extern "C" {
+
+/* FIXME: This is not thread-safe? */
+__asm__ (" \n\
+msg1: \n\
+ .ascii \"couldn't dynamically determine load address for '%s' (handle %p), %E\\0\"\n\
+ \n\
+ .align 32 \n\
+noload: \n\
+ popl %edx # Get the address of the information block\n\
+ movl 4(%edx),%eax # Should we 'ignore' the lack \n\
+ test $1,%eax # of this function? \n\
+ jz 1f # Nope. \n\
+ decl %eax # Yes. This is the # of bytes + 1 \n\
+ popl %edx # Caller's caller \n\
+ addl %eax,%esp # Pop off bytes \n\
+ movl $127,%eax # ERROR_PROC_NOT_FOUND \n\
+ pushl %eax # First argument \n\
+ call _SetLastError@4 # Set it \n\
+ xor %eax,%eax # Zero functional return \n\
+ jmp *%edx # Return \n\
+1: \n\
+ movl (%edx),%eax # Handle value \n\
+ pushl 4(%eax) \n\
+ leal 8(%edx),%eax # Location of name of function \n\
+ push %eax \n\
+ push $msg1 # The message \n\
+ call ___api_fatal # Print message. Never returns \n\
+ \n\
+ .globl dll_func_load \n\
+dll_func_load: \n\
+ movl (%esp),%eax # 'Return address' contains load info \n\
+ addl $8,%eax # Address of name of function to load \n\
+ pushl %eax # Second argument \n\
+ movl -8(%eax),%eax # Where handle lives \n\
+ movl 4(%eax),%eax # Address of Handle to DLL \n\
+ pushl %eax # Handle to DLL \n\
+ call _GetProcAddress@8# Load it \n\
+ test %eax,%eax # Success? \n\
+ jne gotit # Yes \n\
+ jmp noload # Issue an error or return \n\
+gotit: \n\
+ popl %ecx # Pointer to 'return address' \n\
+ movb $0xe9,-7(%ecx) # Turn preceding call to a jmp *%eax \n\
+ movl %eax,%edx # Save \n\
+ subl %ecx,%eax # Make it relative \n\
+ addl $2,%eax # Tweak \n\
+ movl %eax,-6(%ecx) # Move relative address after jump \n\
+ jmp *%edx # Jump to actual function \n\
+ \n\
+ .global dll_chain \n\
+dll_chain: \n\
+ pushl %eax # Restore 'return address' \n\
+ movl (%eax),%eax # Get address of DLL info block \n\
+ movl $dll_func_load,(%eax) # Just load func now \n\
+ jmp *%edx # Jump to next init function \n\
+ \n\
+dll_chain1: \n\
+ pushl %eax # Restore 'return address' \n\
+ jmp *%edx # Jump to next init function \n\
+");
+
+/* C representations of the two info blocks described above.
+ FIXME: These structures confuse gdb for some reason. GDB can print
+ the whole structure but has problems with the name field? */
+struct dll_info
+{
+ DWORD load_state;
+ HANDLE handle;
+ LONG here;
+ void (*init) ();
+ char name[];
+};
+
+struct func_info
+{
+ struct dll_info *dll;
+ LONG decoration;
+ char name[];
+};
+
+/* Mechanism for setting up info for passing to dll_chain routines. */
+union retchain
+{
+ struct {long high; long low;};
+ long long ll;
+};
+
+/* The standard DLL initialization routine. */
+static long long std_dll_init () __asm__ ("std_dll_init") __attribute__ ((unused));
+static long long
+std_dll_init ()
+{
+ HANDLE h;
+ struct func_info *func = (struct func_info *) __builtin_return_address (0);
+ struct dll_info *dll = func->dll;
+ retchain ret;
+
+ if (InterlockedIncrement (&dll->here))
+ do
+ {
+ InterlockedDecrement (&dll->here);
+ Sleep (0);
+ }
+ while (InterlockedIncrement (&dll->here));
+ else if (!dll->handle)
+ {
+ if ((h = LoadLibrary (dll->name)) != NULL)
+ dll->handle = h;
+ else if (!(func->decoration & 1))
+ api_fatal ("could not load %s, %E", dll->name);
+ else
+ dll->handle = INVALID_HANDLE_VALUE;
+ }
+
+ InterlockedDecrement (&dll->here);
+
+ /* Kludge alert. Redirects the return address to dll_chain. */
+ __asm__ __volatile__ (" \n\
+ movl $dll_chain,4(%ebp) \n\
+ ");
+
+ /* Set "arguments for dll_chain. */
+ ret.low = (long) dll->init;
+ ret.high = (long) func;
+ return ret.ll;
+}
+
+/* Initialization function for winsock stuff. */
+static long long wsock_init () __asm__ ("wsock_init") __attribute__ ((unused, regparm(1)));
+bool NO_COPY wsock_started = 0;
+static long long
+wsock_init ()
+{
+ static LONG NO_COPY here = -1L;
+ extern WSADATA wsadata;
+ struct func_info *func = (struct func_info *) __builtin_return_address (0);
+ struct dll_info *dll = func->dll;
+ retchain ret;
+
+ __asm__ (" \n\
+ .section .ws2_32_info \n\
+ .equ _ws2_32_handle,.ws2_32_info + 4 \n\
+ .global _ws2_32_handle \n\
+ .section .wsock32_info \n\
+ .equ _wsock32_handle,.wsock32_info + 4 \n\
+ .global _wsock32_handle \n\
+ .text \n\
+ ");
+
+ while (InterlockedIncrement (&here))
+ {
+ InterlockedDecrement (&here);
+ Sleep (0);
+ }
+
+ if (!wsock_started && (wsock32_handle || ws2_32_handle))
+ {
+ /* Don't use autoload to load WSAStartup to eliminate recursion. */
+ int (*wsastartup) (int, WSADATA *);
+
+ wsastartup = (int (*)(int, WSADATA *))
+ GetProcAddress ((HMODULE) (dll->handle), "WSAStartup");
+ if (wsastartup)
+ {
+ int res = wsastartup ((2<<8) | 2, &wsadata);
+
+ debug_printf ("res %d", res);
+ debug_printf ("wVersion %d", wsadata.wVersion);
+ debug_printf ("wHighVersion %d", wsadata.wHighVersion);
+ debug_printf ("szDescription %s", wsadata.szDescription);
+ debug_printf ("szSystemStatus %s", wsadata.szSystemStatus);
+ debug_printf ("iMaxSockets %d", wsadata.iMaxSockets);
+ debug_printf ("iMaxUdpDg %d", wsadata.iMaxUdpDg);
+ debug_printf ("lpVendorInfo %d", wsadata.lpVendorInfo);
+
+ wsock_started = 1;
+ }
+ }
+
+ InterlockedDecrement (&here);
+
+ /* Kludge alert. Redirects the return address to dll_chain1. */
+ __asm__ __volatile__ (" \n\
+ movl $dll_chain1,4(%ebp) \n\
+ ");
+
+ /* Set "arguments for dll_chain1. */
+ ret.low = (long) dll_func_load;
+ ret.high = (long) func;
+ return ret.ll;
+}
+
+LoadDLLprime (wsock32, wsock_init)
+LoadDLLprime (ws2_32, wsock_init)
+
+LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
+LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
+LoadDLLfunc (AddAce, 20, advapi32)
+LoadDLLfunc (AdjustTokenPrivileges, 24, advapi32)
+LoadDLLfuncEx (AllocateLocallyUniqueId, 4, advapi32, 1)
+LoadDLLfunc (CopySid, 12, advapi32)
+LoadDLLfunc (CreateProcessAsUserA, 44, advapi32)
+LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
+LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
+LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
+LoadDLLfunc (DeregisterEventSource, 4, advapi32)
+LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
+LoadDLLfunc (EqualSid, 8, advapi32)
+LoadDLLfunc (GetAce, 12, advapi32)
+LoadDLLfunc (GetFileSecurityA, 20, advapi32)
+LoadDLLfunc (GetLengthSid, 4, advapi32)
+LoadDLLfunc (GetSecurityDescriptorDacl, 16, advapi32)
+LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32)
+LoadDLLfunc (GetSecurityDescriptorOwner, 12, advapi32)
+LoadDLLfunc (GetSidIdentifierAuthority, 4, advapi32)
+LoadDLLfunc (GetSidSubAuthority, 8, advapi32)
+LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32)
+LoadDLLfunc (GetTokenInformation, 20, advapi32)
+LoadDLLfunc (GetUserNameA, 8, advapi32)
+LoadDLLfunc (ImpersonateLoggedOnUser, 4, advapi32)
+LoadDLLfunc (ImpersonateNamedPipeClient, 4, advapi32)
+LoadDLLfunc (InitializeAcl, 12, advapi32)
+LoadDLLfunc (InitializeSecurityDescriptor, 8, advapi32)
+LoadDLLfunc (InitializeSid, 12, advapi32)
+LoadDLLfunc (IsValidSid, 4, advapi32)
+LoadDLLfunc (LogonUserA, 24, advapi32)
+LoadDLLfunc (LookupAccountNameA, 28, advapi32)
+LoadDLLfunc (LookupAccountNameW, 28, advapi32)
+LoadDLLfunc (LookupAccountSidA, 28, advapi32)
+LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
+LoadDLLfunc (LsaClose, 4, advapi32)
+LoadDLLfunc (LsaEnumerateAccountRights, 16, advapi32)
+LoadDLLfunc (LsaFreeMemory, 4, advapi32)
+LoadDLLfunc (LsaNtStatusToWinError, 4, advapi32)
+LoadDLLfunc (LsaOpenPolicy, 16, advapi32)
+LoadDLLfunc (LsaQueryInformationPolicy, 12, advapi32)
+LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
+LoadDLLfunc (OpenProcessToken, 12, advapi32)
+LoadDLLfunc (RegCloseKey, 4, advapi32)
+LoadDLLfunc (RegCreateKeyExA, 36, advapi32)
+LoadDLLfunc (RegDeleteKeyA, 8, advapi32)
+LoadDLLfunc (RegDeleteValueA, 8, advapi32)
+LoadDLLfunc (RegLoadKeyA, 12, advapi32)
+LoadDLLfunc (RegEnumKeyExA, 32, advapi32)
+LoadDLLfunc (RegEnumValueA, 32, advapi32)
+LoadDLLfunc (RegOpenKeyExA, 20, advapi32)
+LoadDLLfunc (RegQueryValueExA, 24, advapi32)
+LoadDLLfunc (RegSetValueExA, 24, advapi32)
+LoadDLLfunc (RegisterEventSourceA, 8, advapi32)
+LoadDLLfunc (ReportEventA, 36, advapi32)
+LoadDLLfunc (RevertToSelf, 0, advapi32)
+LoadDLLfunc (SetKernelObjectSecurity, 12, advapi32)
+LoadDLLfunc (SetSecurityDescriptorControl, 12, advapi32)
+LoadDLLfunc (SetSecurityDescriptorDacl, 16, advapi32)
+LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32)
+LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32)
+LoadDLLfunc (SetTokenInformation, 16, advapi32)
+
+LoadDLLfunc (NetApiBufferFree, 4, netapi32)
+LoadDLLfunc (NetLocalGroupEnum, 28, netapi32)
+LoadDLLfunc (NetLocalGroupGetMembers, 32, netapi32)
+LoadDLLfunc (NetServerEnum, 36, netapi32)
+LoadDLLfunc (NetUserGetGroups, 28, netapi32)
+LoadDLLfunc (NetUserGetInfo, 16, netapi32)
+LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
+
+LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1)
+LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
+LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
+LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
+LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
+LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
+LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
+LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
+
+LoadDLLfuncEx (LsaDeregisterLogonProcess, 4, secur32, 1)
+LoadDLLfuncEx (LsaFreeReturnBuffer, 4, secur32, 1)
+LoadDLLfuncEx (LsaLogonUser, 56, secur32, 1)
+LoadDLLfuncEx (LsaLookupAuthenticationPackage, 12, secur32, 1)
+LoadDLLfuncEx (LsaRegisterLogonProcess, 12, secur32, 1)
+
+LoadDLLfunc (CharToOemA, 8, user32)
+LoadDLLfunc (CharToOemBuffA, 12, user32)
+LoadDLLfunc (CloseClipboard, 0, user32)
+LoadDLLfunc (CreateWindowExA, 48, user32)
+LoadDLLfunc (DefWindowProcA, 16, user32)
+LoadDLLfunc (DispatchMessageA, 4, user32)
+LoadDLLfunc (EmptyClipboard, 0, user32)
+LoadDLLfunc (FindWindowA, 8, user32)
+LoadDLLfunc (GetClipboardData, 4, user32)
+LoadDLLfunc (GetKeyboardLayout, 4, user32)
+LoadDLLfunc (GetMessageA, 16, user32)
+LoadDLLfunc (GetPriorityClipboardFormat, 8, user32)
+LoadDLLfunc (GetProcessWindowStation, 0, user32)
+LoadDLLfunc (GetThreadDesktop, 4, user32)
+LoadDLLfunc (GetUserObjectInformationA, 20, user32)
+LoadDLLfunc (KillTimer, 8, user32)
+LoadDLLfunc (MessageBoxA, 16, user32)
+LoadDLLfunc (MsgWaitForMultipleObjects, 20, user32)
+LoadDLLfunc (OemToCharBuffA, 12, user32)
+LoadDLLfunc (OpenClipboard, 4, user32)
+LoadDLLfunc (PeekMessageA, 20, user32)
+LoadDLLfunc (PostMessageA, 16, user32)
+LoadDLLfunc (PostQuitMessage, 4, user32)
+LoadDLLfunc (RegisterClassA, 4, user32)
+LoadDLLfunc (RegisterClipboardFormatA, 4, user32)
+LoadDLLfunc (SendMessageA, 16, user32)
+LoadDLLfunc (SetClipboardData, 8, user32)
+LoadDLLfunc (SetTimer, 16, user32)
+LoadDLLfunc (SetUserObjectSecurity, 12, user32)
+
+LoadDLLfunc (WSAAsyncSelect, 16, wsock32)
+LoadDLLfunc (WSACleanup, 0, wsock32)
+LoadDLLfunc (WSAGetLastError, 0, wsock32)
+LoadDLLfunc (WSASetLastError, 4, wsock32)
+LoadDLLfunc (WSAStartup, 8, wsock32)
+LoadDLLfunc (__WSAFDIsSet, 8, wsock32)
+LoadDLLfunc (accept, 12, wsock32)
+LoadDLLfunc (bind, 12, wsock32)
+LoadDLLfunc (closesocket, 4, wsock32)
+LoadDLLfunc (connect, 12, wsock32)
+LoadDLLfunc (gethostbyaddr, 12, wsock32)
+LoadDLLfunc (gethostbyname, 4, wsock32)
+LoadDLLfunc (gethostname, 8, wsock32)
+LoadDLLfunc (getpeername, 12, wsock32)
+LoadDLLfunc (getprotobyname, 4, wsock32)
+LoadDLLfunc (getprotobynumber, 4, wsock32)
+LoadDLLfunc (getservbyname, 8, wsock32)
+LoadDLLfunc (getservbyport, 8, wsock32)
+LoadDLLfunc (getsockname, 12, wsock32)
+LoadDLLfunc (getsockopt, 20, wsock32)
+LoadDLLfunc (inet_addr, 4, wsock32)
+LoadDLLfunc (inet_network, 4, wsock32)
+LoadDLLfunc (inet_ntoa, 4, wsock32)
+LoadDLLfunc (ioctlsocket, 12, wsock32)
+LoadDLLfunc (listen, 8, wsock32)
+LoadDLLfunc (rcmd, 24, wsock32)
+LoadDLLfunc (recv, 16, wsock32)
+LoadDLLfunc (recvfrom, 24, wsock32)
+LoadDLLfunc (rexec, 24, wsock32)
+LoadDLLfunc (rresvport, 4, wsock32)
+LoadDLLfunc (select, 20, wsock32)
+LoadDLLfunc (send, 16, wsock32)
+LoadDLLfunc (sendto, 24, wsock32)
+LoadDLLfunc (setsockopt, 20, wsock32)
+LoadDLLfunc (shutdown, 8, wsock32)
+LoadDLLfunc (socket, 12, wsock32)
+
+LoadDLLfuncEx (WSACloseEvent, 4, ws2_32, 1)
+LoadDLLfuncEx (WSACreateEvent, 0, ws2_32, 1)
+LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1)
+LoadDLLfuncEx (WSAGetOverlappedResult, 20, ws2_32, 1)
+LoadDLLfuncEx (WSARecv, 28, ws2_32, 1)
+LoadDLLfuncEx (WSARecvFrom, 36, ws2_32, 1)
+LoadDLLfuncEx (WSASend, 28, ws2_32, 1)
+LoadDLLfuncEx (WSASendTo, 36, ws2_32, 1)
+LoadDLLfuncEx (WSASetEvent, 4, ws2_32, 1)
+LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
+LoadDLLfuncEx (WSAWaitForMultipleEvents, 20, ws2_32, 1)
+
+LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
+LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
+
+LoadDLLfunc (CoInitialize, 4, ole32)
+LoadDLLfunc (CoUninitialize, 0, ole32)
+LoadDLLfunc (CoCreateInstance, 20, ole32)
+
+LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1)
+LoadDLLfuncEx (CancelIo, 4, kernel32, 1)
+LoadDLLfuncEx (Process32First, 8, kernel32, 1)
+LoadDLLfuncEx (Process32Next, 8, kernel32, 1)
+LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1)
+LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1)
+LoadDLLfunc (TryEnterCriticalSection, 4, kernel32)
+
+LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1)
+LoadDLLfuncEx (waveOutOpen, 24, winmm, 1)
+LoadDLLfuncEx (waveOutReset, 4, winmm, 1)
+LoadDLLfuncEx (waveOutClose, 4, winmm, 1)
+LoadDLLfuncEx (waveOutGetVolume, 8, winmm, 1)
+LoadDLLfuncEx (waveOutSetVolume, 8, winmm, 1)
+LoadDLLfuncEx (waveOutUnprepareHeader, 12, winmm, 1)
+LoadDLLfuncEx (waveOutPrepareHeader, 12, winmm, 1)
+LoadDLLfuncEx (waveOutWrite, 12, winmm, 1)
+}
diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc
new file mode 100755
index 00000000000..34141d3bfa7
--- /dev/null
+++ b/winsup/cygwin/cygserver.cc
@@ -0,0 +1,546 @@
+/* cygserver.cc
+
+ Copyright 2001 Red Hat Inc.
+
+ Written by Egor Duda <deo@logos-m.ru>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include "wincap.h"
+
+#include "getopt.h"
+
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+#include "cygserver_shm.h"
+
+
+GENERIC_MAPPING access_mapping;
+class transport_layer_base *transport;
+
+DWORD request_count = 0;
+
+BOOL
+setup_privileges ()
+{
+ BOOL rc, ret_val;
+ HANDLE hToken = NULL;
+ TOKEN_PRIVILEGES sPrivileges;
+
+ rc = OpenProcessToken ( GetCurrentProcess() , TOKEN_ALL_ACCESS , &hToken ) ;
+ if ( !rc )
+ {
+ printf ( "error opening process token (%lu)\n", GetLastError () );
+ ret_val = FALSE;
+ goto out;
+ }
+ rc = LookupPrivilegeValue ( NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid );
+ if ( !rc )
+ {
+ printf ( "error getting prigilege luid (%lu)\n", 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 )
+ {
+ printf ( "error adjusting prigilege level. (%lu)\n", 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)
+{
+ HANDLE local_handle = NULL;
+ int ret_val = EACCES;
+ 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 (from_process != GetCurrentProcess ())
+{
+
+ if (!DuplicateHandle (from_process, from_handle,
+ GetCurrentProcess (), &local_handle,
+ 0, bInheritHandle,
+ DUPLICATE_SAME_ACCESS))
+ {
+ printf ( "error getting handle(%u) to server (%lu)\n", (unsigned int)from_handle, GetLastError ());
+ goto out;
+ }
+} else
+ local_handle = from_handle;
+
+ if (!GetKernelObjectSecurity (local_handle,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ sd, sizeof (sd_buf), &bytes_needed))
+ {
+ printf ( "error getting handle SD (%lu)\n", GetLastError ());
+ goto out;
+ }
+
+ MapGenericMask (&access, &access_mapping);
+
+ if (!AccessCheck (sd, from_process_token, access, &access_mapping,
+ &ps, &ps_len, &access, &status))
+ {
+ printf ( "error checking access rights (%lu)\n", GetLastError ());
+ goto out;
+ }
+
+ if (!status)
+ {
+ printf ( "access to object denied\n");
+ goto out;
+ }
+
+ if (!DuplicateHandle (from_process, from_handle,
+ to_process, to_handle_ptr,
+ access, bInheritHandle, 0))
+ {
+ printf ( "error getting handle to client (%lu)\n", GetLastError ());
+ goto out;
+ }
+
+ ret_val = 0;
+
+out:
+ if (local_handle && from_process != GetCurrentProcess ())
+ CloseHandle (local_handle);
+
+ 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)
+{
+ return check_and_dup_handle(from_process,to_process,from_process_token,access,from_handle,to_handle_ptr,FALSE);
+}
+
+void
+client_request_attach_tty::serve(transport_layer_base *conn)
+{
+ HANDLE from_process_handle = NULL;
+ HANDLE to_process_handle = NULL;
+ HANDLE token_handle = NULL;
+ DWORD rc;
+
+ if (header.cb != sizeof (req))
+ {
+ header.error_code = EINVAL;
+ return;
+ }
+
+#ifdef DEBUG
+ printf ("%d:(%d,%d) -> %d\n", req.master_pid,
+ req.from_master, req.to_master,
+ req.pid);
+#endif
+
+ from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid);
+ to_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid);
+ if (!from_process_handle || !to_process_handle)
+ {
+ printf ("error opening process (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ goto out;
+ }
+
+ transport->impersonate_client ();
+
+ rc = OpenThreadToken (GetCurrentThread (),
+ TOKEN_QUERY,
+ TRUE,
+ &token_handle);
+
+ transport->revert_to_self ();
+
+ if (!rc)
+ {
+ printf ("error opening thread token (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ goto out;
+ }
+
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_READ,
+ req.from_master,
+ &req.from_master) != 0)
+ {
+ printf ("error duplicating from_master handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ goto out;
+ }
+
+ if (req.to_master)
+ {
+ if (check_and_dup_handle (from_process_handle, to_process_handle,
+ token_handle,
+ GENERIC_WRITE,
+ req.to_master,
+ &req.to_master) != 0)
+ {
+ printf ("error duplicating to_master handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ goto out;
+ }
+ }
+
+#ifdef DEBUG
+ printf ("%d -> %d(%d,%d)\n", req.master_pid, req.pid,
+ req.from_master, req.to_master);
+#endif
+
+ header.error_code = 0;
+
+out:
+ if (from_process_handle)
+ CloseHandle (from_process_handle);
+ if (to_process_handle)
+ CloseHandle (to_process_handle);
+ if (token_handle)
+ CloseHandle (token_handle);
+}
+
+void
+client_request_get_version::serve(transport_layer_base *conn)
+{
+ if (header.cb != sizeof (version))
+ {
+ header.error_code = EINVAL;
+ return;
+ }
+ header.error_code = 0;
+ 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:
+ class server_request *next;
+ server_request (transport_layer_base *newconn);
+ void process ();
+ private:
+ char request_buffer [MAX_REQUEST_SIZE];
+ transport_layer_base *conn;
+};
+
+class server_request_queue
+{
+ public:
+ CRITICAL_SECTION queuelock;
+ HANDLE event;
+ server_request * request;
+ bool active;
+ unsigned int initial_workers;
+ unsigned int running;
+ void create_workers ();
+ void cleanup ();
+ void add (transport_layer_base *conn);
+};
+class server_request_queue request_queue;
+
+void
+client_request_shutdown::serve (transport_layer_base *conn)
+{
+ /* FIXME: link upwards, and then this becomes a trivial method call to
+ * only shutdown _this queue_
+ */
+ /* tell the main thread to shutdown */
+ request_queue.active=false;
+}
+
+server_request::server_request (transport_layer_base *newconn)
+{
+ conn = newconn;
+ next = NULL;
+}
+
+void
+server_request::process ()
+{
+ ssize_t bytes_read, bytes_written;
+ struct request_header* req_ptr = (struct request_header*) &request_buffer;
+ client_request *req = NULL;
+ printf ("about to read\n");
+
+ bytes_read = conn->read (request_buffer, sizeof (struct request_header));
+ if (bytes_read != sizeof (struct request_header))
+ {
+ printf ("error reading from connection (%lu)\n", GetLastError ());
+ goto out;
+ }
+ printf ("got header (%ld)\n", bytes_read);
+
+ switch (req_ptr->req_id)
+ {
+ case CYGSERVER_REQUEST_GET_VERSION:
+ req = new client_request_get_version (); break;
+ case CYGSERVER_REQUEST_ATTACH_TTY:
+ req = new client_request_attach_tty (); break;
+ case CYGSERVER_REQUEST_SHUTDOWN:
+ req = new client_request_shutdown (); break;
+ case CYGSERVER_REQUEST_SHM_GET:
+ req = new client_request_shm_get (); break;
+ default:
+ req = new client_request (CYGSERVER_REQUEST_INVALID);
+ req->header.error_code = ENOSYS;
+ printf ("Bad client request - returning ENOSYS\n");
+ }
+
+ if (req->header.cb != req_ptr->cb)
+ {
+ printf ("Mismatch in request buffer sizes\n");
+ goto out;
+ }
+
+ if (req->header.cb)
+ {
+
+ bytes_read = conn->read (req->buffer, req->header.cb);
+ if (bytes_read != req->header.cb)
+ {
+ printf ("error reading from connection (%lu)\n", GetLastError ());
+ goto out;
+ }
+ printf ("got body (%ld)\n",bytes_read);
+ }
+
+ /* this is not allowed to fail. We must return ENOSYS at a minimum to the client */
+ req->serve (conn);
+
+ if ((bytes_written = conn->write ((char *)&req->header, sizeof (req->header)))
+ != sizeof(req->header) ||
+ (bytes_written = conn->write (req->buffer, req->header.cb)) != req->header.cb)
+ {
+ req->header.error_code = -1;
+ printf ("error writing to connection (%lu)\n", GetLastError ());
+ goto out;
+ }
+
+ printf("Sent reply, size (%ld)\n",bytes_written);
+
+out:
+ conn->close ();
+ delete conn;
+ if (req)
+ delete (req);
+}
+
+DWORD WINAPI
+worker_function( LPVOID LpParam )
+{
+ class server_request_queue *queue = (class server_request_queue *) LpParam;
+ class server_request *request;
+ /* FIXME use a threadsafe pop instead for speed? */
+ while (queue->active)
+ {
+ EnterCriticalSection (&queue->queuelock);
+ while (!queue->request && queue->active)
+ {
+ LeaveCriticalSection (&queue->queuelock);
+ DWORD rc = WaitForSingleObject (queue->event,INFINITE);
+ if (rc == WAIT_FAILED)
+ {
+ printf("Wait for event failed\n");
+ queue->running--;
+ ExitThread (0);
+ }
+ EnterCriticalSection (&queue->queuelock);
+ }
+ if (!queue->active)
+ {
+ queue->running--;
+ LeaveCriticalSection (&queue->queuelock);
+ ExitThread (0);
+ }
+ /* not needed, but it is efficient */
+ request = (class server_request *)InterlockedExchangePointer (&queue->request, queue->request->next);
+ LeaveCriticalSection (&queue->queuelock);
+ request->process ();
+ delete request;
+ }
+ queue->running--;
+ ExitThread (0);
+}
+
+void
+server_request_queue::create_workers()
+{
+ InitializeCriticalSection (&queuelock);
+ if ((event = CreateEvent (NULL, FALSE, FALSE, NULL)) == NULL)
+ {
+ printf ("Failed to create event queue (%lu), terminating\n", GetLastError ());
+ exit (1);
+ }
+ active = true;
+
+ /* FIXME: Use a stack pair and create threads on the fly whenever
+ * we have to to service a request.
+ */
+ for (unsigned int i=0; i<initial_workers; i++)
+ {
+ HANDLE hThread;
+ DWORD tid;
+ hThread = CreateThread (NULL, 0, worker_function, this, 0, &tid);
+ if (hThread == NULL)
+ {
+ printf ("Failed to create thread (%lu), terminating\n", GetLastError ());
+ exit (1);
+ }
+ CloseHandle (hThread);
+ running++;
+ }
+}
+
+void
+server_request_queue::cleanup ()
+{
+ /* harvest the threads */
+ active = false;
+ if (!running)
+ return;
+ printf ("Waiting for current connections to terminate\n");
+ for (int n=running; n; n--)
+ PulseEvent (event);
+ while (running)
+ sleep (1);
+ DeleteCriticalSection (&queuelock);
+ CloseHandle (event);
+}
+
+void
+server_request_queue::add (transport_layer_base *conn)
+{
+ /* safe to not "Try" because workers don't hog this, they wait on the event
+ */
+ EnterCriticalSection (&queuelock);
+ if (!running)
+ {
+ printf ("No worker threads to handle request!\n");
+ conn->close ();
+ delete conn;
+ }
+ server_request * listrequest;
+ if (!request)
+ {
+ request = new server_request (conn);
+ listrequest = request;
+ }
+ else
+ {
+ /* add to the queue end. */
+ listrequest = request;
+ while (listrequest->next)
+ listrequest = listrequest->next;
+ listrequest->next = new server_request (conn);
+ listrequest = listrequest->next;
+ }
+ PulseEvent (event);
+ LeaveCriticalSection (&queuelock);
+}
+
+struct option longopts[] = {
+ {"shutdown", no_argument, NULL, 's'},
+ {0, no_argument, NULL, 0}
+};
+
+char opts[] = "s";
+
+int
+main (int argc, char **argv)
+{
+ int shutdown=0;
+ char i;
+
+ while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
+ switch (i)
+ {
+ case 's':
+ shutdown = 1;
+ break;
+ default:
+ break;
+ /*NOTREACHED*/
+ }
+
+ wincap.init();
+ if (wincap.has_security ())
+ setup_privileges ();
+ transport = create_server_transport ();
+
+ if (shutdown)
+ {
+ if (!transport->connect())
+ {
+ printf ("couldn't establish connection with server\n");
+ exit (1);
+ }
+ client_request_shutdown *request =
+ new client_request_shutdown ();
+ request->send (transport);
+ transport->close();
+ delete transport;
+ delete request;
+ exit(0);
+ }
+
+ transport->listen ();
+ request_queue.initial_workers = 10;
+ request_queue.create_workers();
+ while (request_queue.active)
+ {
+ transport_layer_base * new_conn = transport->accept ();
+ /* 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
+ */
+ if (new_conn && request_queue.active)
+ request_queue.add (new_conn);
+ }
+ printf ("No longer accepting requests.\n");
+ request_queue.cleanup ();
+ transport->close ();
+}
diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc
new file mode 100755
index 00000000000..1dc8f2d6e89
--- /dev/null
+++ b/winsup/cygwin/cygserver_client.cc
@@ -0,0 +1,225 @@
+/* cygserver_client.cc
+
+ Copyright 2001 Red Hat Inc.
+
+ Written by Egor Duda <deo@logos-m.ru>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#ifdef __OUTSIDE_CYGWIN__
+#undef __INSIDE_CYGWIN__
+#else
+#include "winsup.h"
+#endif
+
+#ifndef __INSIDE_CYGWIN__
+#define debug_printf printf
+#define api_fatal printf
+#include <stdio.h>
+#include <windows.h>
+#endif
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+//#include "security.h"
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+
+/* 0 = untested, 1 = running, 2 = dead */
+int cygserver_running=CYGSERVER_UNKNOWN;
+
+client_request_get_version::client_request_get_version () : client_request (CYGSERVER_REQUEST_GET_VERSION)
+{
+ header.cb = sizeof (version);
+ buffer = (char *)&version;
+}
+
+#ifdef __INSIDE_CYGWIN__
+void
+client_request_get_version::serve (transport_layer_base *conn)
+{
+}
+#endif
+
+client_request_attach_tty::client_request_attach_tty () : client_request (CYGSERVER_REQUEST_ATTACH_TTY)
+{
+ header.cb = sizeof (req);
+ buffer = (char *)&req;
+ req.pid = 0;
+ req.master_pid = 0;
+ req.from_master = NULL;
+ req.to_master = NULL;
+}
+
+client_request_attach_tty::client_request_attach_tty (DWORD npid, DWORD nmaster_pid, HANDLE nfrom_master, HANDLE nto_master) : client_request (CYGSERVER_REQUEST_ATTACH_TTY)
+{
+ header.cb = sizeof (req);
+ buffer = (char *)&req;
+ req.pid = npid;
+ req.master_pid = nmaster_pid;
+ req.from_master = nfrom_master;
+ req.to_master = nto_master;
+}
+
+#ifdef __INSIDE_CYGWIN__
+void
+client_request_attach_tty::serve (transport_layer_base *conn)
+{
+}
+#endif
+
+client_request_shutdown::client_request_shutdown () : client_request (CYGSERVER_REQUEST_SHUTDOWN)
+{
+ header.cb = 0;
+ buffer = NULL;
+}
+
+#ifdef __INSIDE_CYGWIN__
+void
+client_request_shutdown::serve (transport_layer_base *conn)
+{
+}
+#endif
+
+client_request::client_request (cygserver_request_code id)
+{
+ header.req_id = id;
+ header.error_code = 0;
+}
+
+client_request::~client_request ()
+{
+}
+
+client_request::operator class request_header ()
+{
+ return header;
+}
+
+void
+client_request::send (transport_layer_base *conn)
+{
+ if (!conn)
+ return;
+ debug_printf("this=%p, conn=%p\n",this, conn);
+ ssize_t bytes_written, bytes_read;
+ debug_printf("header.cb = %ld\n",header.cb);
+ if ((bytes_written = conn->write ((char *)&header, sizeof (header)))
+ != sizeof(header) || (header.cb &&
+ (bytes_written = conn->write (buffer, header.cb)) != header.cb))
+ {
+ header.error_code = -1;
+ debug_printf ("bytes written != request size\n");
+ return;
+ }
+
+ debug_printf("Sent request, size (%ld)\n",bytes_written);
+
+ if ((bytes_read = conn->read ((char *)&header, sizeof (header)))
+ != sizeof (header) || (header.cb &&
+ (bytes_read = conn->read (buffer, header.cb) ) != header.cb))
+ {
+ header.error_code = -1;
+ debug_printf("failed reading response \n");
+ return;
+ }
+ debug_printf ("completed ok\n");
+}
+
+/* Oh, BTW: Fix the procedural basis and make this more intuitive. */
+
+int
+cygserver_request (client_request * req)
+{
+ class transport_layer_base *transport;
+
+ if (!req)
+ return -1;
+
+ /* dont' retry every request if the server's not there */
+ if (cygserver_running==CYGSERVER_DEAD && req->header.req_id != CYGSERVER_REQUEST_GET_VERSION)
+ return -1;
+
+ transport = create_server_transport ();
+
+ /* FIXME: have at most one connection per thread. use TLS to store the details */
+ /* logic is:
+ * if not tlskey->conn, new conn,
+ * then; transport=conn;
+ */
+ if (!transport->connect ())
+ {
+ delete transport;
+ return -1;
+ }
+
+ debug_printf ("connected to server %p\n", transport);
+
+ req->send(transport);
+
+ transport->close ();
+
+ delete transport;
+
+ return 0;
+}
+
+#if 0
+BOOL
+check_cygserver_available ()
+{
+ BOOL ret_val = FALSE;
+ HANDLE pipe = CreateFile (pipe_name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sec_all_nih,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (pipe != INVALID_HANDLE_VALUE || GetLastError () != ERROR_PIPE_BUSY)
+ ret_val = TRUE;
+
+ if (pipe && pipe != INVALID_HANDLE_VALUE)
+ CloseHandle (pipe);
+
+ return (ret_val);
+}
+#endif
+
+void
+cygserver_init ()
+{
+ int rc;
+
+ if (cygserver_running==CYGSERVER_OK)
+ return;
+
+ client_request_get_version *req =
+ new client_request_get_version ();
+
+ rc = cygserver_request (req);
+ delete req;
+ if (rc < 0)
+ cygserver_running = CYGSERVER_DEAD;
+ else if (rc > 0)
+ api_fatal ( "error connecting to cygwin server. error: %d", rc );
+ else if (req->version.major != CYGWIN_SERVER_VERSION_MAJOR ||
+ req->version.api != CYGWIN_SERVER_VERSION_API ||
+ req->version.minor > CYGWIN_SERVER_VERSION_MINOR)
+ api_fatal ( "incompatible version of cygwin server.\n\
+ client version %d.%d.%d.%d, server version%ld.%ld.%ld.%ld",
+ CYGWIN_SERVER_VERSION_MAJOR,
+ CYGWIN_SERVER_VERSION_API,
+ CYGWIN_SERVER_VERSION_MINOR,
+ CYGWIN_SERVER_VERSION_PATCH,
+ req->version.major,
+ req->version.api,
+ req->version.minor,
+ req->version.patch );
+ else
+ cygserver_running = CYGSERVER_OK;
+}
diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc
new file mode 100755
index 00000000000..97246f0e389
--- /dev/null
+++ b/winsup/cygwin/cygserver_shm.cc
@@ -0,0 +1,530 @@
+/* shm.cc: Single unix specification IPC interface for Cygwin
+
+ Copyright 2001 Red Hat, Inc.
+
+ Originally written by Robert Collins <robert.collins@hotmail.com>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+
+#ifdef __OUTSIDE_CYGWIN__
+#undef __INSIDE_CYGWIN__
+#else
+#include "winsup.h"
+#endif
+
+#ifndef __INSIDE_CYGWIN__
+#define system_printf printf
+#define debug_printf printf
+#define api_fatal printf
+#include <stdio.h>
+#include <windows.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+#include "cygerrno.h"
+#include <unistd.h>
+#include "security.h"
+//#include "fhandler.h"
+//#include "dtable.h"
+//#include "cygheap.h"
+#include <stdio.h>
+//#include "thread.h"
+#ifndef __INSIDE_CYGWIN__
+#define __INSIDE_CYGWIN__
+#include <sys/shm.h>
+#undef __INSIDE_CYGWIN__
+#else
+#include <sys/shm.h>
+#endif
+//#include "perprocess.h"
+#include "cygserver_shm.h"
+
+// FIXME IS THIS CORRECT
+/* Implementation notes: We use two shared memory regions per key:
+ * One for the control structure, and one for the shared memory.
+ * While this has a higher overhead tham a single shared area,
+ * It allows more flexability. As the entire code is transparent to the user
+ * We can merge these in the future should it be needed.
+ * Also, IPC_PRIVATE keys create unique mappings each time. The shm_ids just
+ * keep monotonically incrementing - system wide.
+ */
+size_t getsystemallocgranularity ()
+{
+ SYSTEM_INFO sysinfo;
+ static size_t buffer_offset = 0;
+ if (buffer_offset)
+ return buffer_offset;
+ GetSystemInfo (&sysinfo);
+ buffer_offset = sysinfo.dwAllocationGranularity;
+ return buffer_offset;
+}
+
+client_request_shm_get::client_request_shm_get () : client_request (CYGSERVER_REQUEST_SHM_GET)
+{
+ header.cb = sizeof (parameters);
+ buffer = (char *) &parameters;
+ header.error_code = 0;
+}
+
+client_request_shm_get::client_request_shm_get (int nshm_id, pid_t npid) : client_request (CYGSERVER_REQUEST_SHM_GET)
+{
+ header.cb = sizeof (parameters);
+ buffer = (char *) &parameters;
+ header.error_code = 0;
+ parameters.in.shm_id = nshm_id;
+ parameters.in.type = SHM_REATTACH;
+ parameters.in.pid = npid;
+}
+
+client_request_shm_get::client_request_shm_get (key_t nkey, size_t nsize,
+ int nshmflg, char psdbuf[4096], pid_t npid): client_request (CYGSERVER_REQUEST_SHM_GET)
+{
+ header.cb = sizeof (parameters);
+ buffer = (char *) &parameters;
+ parameters.in.key = nkey;
+ parameters.in.size = nsize;
+ parameters.in.shmflg = nshmflg;
+ parameters.in.type = SHM_CREATE;
+ parameters.in.pid = npid;
+ memcpy (parameters.in.sd_buf, psdbuf, 4096);
+}
+
+/* FIXME: If building on a 64-bit compiler, the address->int typecast will fail.
+ * Solution: manually calculate the next id value
+ */
+
+#if 0
+extern "C" void *
+shmat (int shmid, const void *shmaddr, int parameters.in.shmflg)
+{
+ class shmid_ds *shm = (class shmid_ds *) shmid; //FIXME: verifyable object test
+
+ if (shmaddr)
+ {
+ //FIXME: requested base address ?!
+ set_errno (EINVAL);
+ return (void *) -1;
+ }
+
+ void *rv = MapViewOfFile (shm->attachmap,
+
+
+ (parameters.in.
+ shmflg & SHM_RDONLY) ? FILE_MAP_READ :
+ FILE_MAP_WRITE, 0,
+ 0, 0);
+
+ if (!rv)
+ {
+ //FIXME: translate GetLastError()
+ set_errno (EACCES);
+ return (void *) -1;
+ }
+
+/* FIXME: this needs to be globally protected to prevent a mismatch betwen
+ * attach count and attachees list
+ */
+
+ InterlockedIncrement (&shm->shm_nattch);
+ _shmattach *attachnode = new _shmattach;
+
+ attachnode->data = rv;
+ attachnode->next =
+ (_shmattach *) InterlockedExchangePointer ((LONG *) & shm->attachhead,
+ (long int) attachnode);
+ return rv;
+}
+#endif
+
+/* FIXME: evaluate getuid() and getgid() against the requested mode. Then
+ * choose PAGE_READWRITE | PAGE_READONLY and FILE_MAP_WRITE | FILE_MAP_READ
+ * appropriately
+ */
+
+/* Test result from openbsd: shm ids are persistent cross process if a handle is left
+ * open. This could lead to resource starvation: we're not copying that behaviour
+ * unless we have to. (It will involve acygwin1.dll gloal shared list :[ ).
+ */
+/* FIXME: shmid should be a verifyable object
+ */
+
+/* FIXME: on NT we should check everything against the SD. On 95 we just emulate.
+ */
+
+/* for dll size */
+#ifdef __INSIDE_CYGWIN__
+void
+client_request_shm_get::serve (transport_layer_base * conn)
+{
+}
+#else
+
+extern GENERIC_MAPPING access_mapping;
+
+extern 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);
+
+//FIXME: where should this live
+static shmnode *shm_head = NULL;
+/* must be long for InterlockedIncrement */
+static long new_id = 0;
+static long new_private_key = 0;
+
+void
+client_request_shm_get::serve (transport_layer_base * conn)
+{
+// DWORD sd_size = 4096;
+// char sd_buf[4096];
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) parameters.in.sd_buf;
+// /* create a sd for our open requests based on shmflag & 0x01ff */
+// psd = alloc_sd (getuid (), getgid (), cygheap->user.logsrv (),
+// parameters.in.shmflg & 0x01ff, psd, &sd_size);
+
+ HANDLE from_process_handle = NULL;
+ HANDLE token_handle = NULL;
+ DWORD rc;
+
+ from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, parameters.in.pid);
+ if (!from_process_handle)
+ {
+ printf ("error opening process (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ return;
+ }
+
+ conn->impersonate_client ();
+
+ rc = OpenThreadToken (GetCurrentThread (),
+ TOKEN_QUERY,
+ TRUE,
+ &token_handle);
+
+ conn->revert_to_self ();
+
+ if (!rc)
+ {
+ printf ("error opening thread token (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ CloseHandle (from_process_handle);
+ return;
+ }
+
+
+ /* we trust the clients request - we will be doing it as them, and
+ * the worst they can do is open their own permissions
+ */
+
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof (sa);
+ sa.lpSecurityDescriptor = psd;
+ sa.bInheritHandle = TRUE; /* the memory structures inherit ok */
+
+ char *shmname = NULL, *shmaname = NULL;
+ char stringbuf[29], stringbuf1[29];
+
+ if (parameters.in.type == SHM_REATTACH)
+ {
+ /* just find and fill out the existing shm_id */
+ shmnode *tempnode = shm_head;
+ while (tempnode)
+ {
+ if (tempnode->shm_id == parameters.in.shm_id)
+ {
+ parameters.out.shm_id = tempnode->shm_id;
+ parameters.out.key = tempnode->key;
+ if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->filemap, &parameters.out.filemap, TRUE) != 0)
+ {
+ printf ("error duplicating filemap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ CloseHandle (from_process_handle);
+ }
+ if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->attachmap, &parameters.out.attachmap, TRUE) != 0)
+ {
+ printf ("error duplicating attachmap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ CloseHandle (from_process_handle);
+ }
+ return;
+ }
+ tempnode = tempnode->next;
+ }
+ header.error_code = EINVAL;
+ return;
+ }
+ /* it's a original request from the users */
+
+ /* FIXME: enter the checking for existing keys mutex. This mutex _must_ be system wide
+ * to prevent races on shmget.
+ */
+
+ if (parameters.in.key == IPC_PRIVATE)
+ {
+ /* create the mapping name (CYGWINSHMKPRIVATE_0x01234567 */
+ /* The K refers to Key, the actual mapped area has D */
+ long private_key = (int) InterlockedIncrement (&new_private_key);
+ snprintf (stringbuf , 29, "CYGWINSHMKPRIVATE_0x%0x", private_key);
+ shmname = stringbuf;
+ snprintf (stringbuf1, 29, "CYGWINSHMDPRIVATE_0x%0x", private_key);
+ shmaname = stringbuf1;
+ }
+ else
+ {
+ /* create the mapping name (CYGWINSHMK0x0123456789abcdef */
+ /* The K refers to Key, the actual mapped area has D */
+
+ snprintf (stringbuf , 29, "CYGWINSHMK0x%0qx", parameters.in.key);
+ shmname = stringbuf;
+ snprintf (stringbuf1, 29, "CYGWINSHMD0x%0qx", parameters.in.key);
+ shmaname = stringbuf1;
+debug_printf ("system id strings are \n%s\n%s\n",shmname,shmaname);
+debug_printf ("key input value is 0x%0qx\n", parameters.in.key);
+ }
+
+ /* attempt to open the key */
+
+ /* get an existing key */
+ /* On unix the same shmid identifier is returned on multiple calls to shm_get
+ * with the same key and size. Different modes is a ?.
+ */
+
+
+
+ /* walk the list of known keys and return the id if found. remember, we are
+ * authoritative...
+ */
+
+ shmnode *tempnode = shm_head;
+ while (tempnode)
+ {
+ if (tempnode->key == parameters.in.key
+ && parameters.in.key != IPC_PRIVATE)
+ {
+ // FIXME: free the mutex
+ if (parameters.in.size
+ && tempnode->shmds->shm_segsz < parameters.in.size)
+ {
+ header.error_code = EINVAL;
+ return;
+ }
+ /* FIXME: can the same process call this twice without error ? test
+ * on unix
+ */
+ if ((parameters.in.shmflg & IPC_CREAT)
+ && (parameters.in.shmflg & IPC_EXCL))
+ {
+ header.error_code = EEXIST;
+ debug_printf ("attempt to exclusively create already created shm_area with key 0x%0qx\n",parameters.in.key);
+ // FIXME: free the mutex
+ return;
+ }
+ // FIXME: do we need to other tests of the requested mode with the
+ // tempnode->shm_id mode ? testcase on unix needed.
+ // FIXME how do we do the security test? or
+ // do we wait for shmat to bother with that?
+ /* One possibly solution: impersonate the client, and then test we can
+ * reopen the area. In fact we'll probably have to do that to get
+ * handles back to them, alternatively just tell them the id, and then
+ * let them attempt the open.
+ */
+ parameters.out.shm_id = tempnode->shm_id;
+if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->filemap, &parameters.out.filemap,TRUE) != 0)
+ {
+ printf ("error duplicating filemap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+/*mutex*/
+ CloseHandle (from_process_handle);
+ return;
+ }
+if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->attachmap, &parameters.out.attachmap, TRUE) != 0)
+ {
+ printf ("error duplicating attachmap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+/*mutex*/
+ CloseHandle (from_process_handle);
+return;
+ }
+
+ return;
+ }
+ tempnode = tempnode->next;
+ }
+ /* couldn't find a currently open shm area. */
+
+ /* create one */
+ /* do this as the client */
+ conn->impersonate_client ();
+ /* This may need sh_none... it's only a control structure */
+ HANDLE filemap = CreateFileMapping (INVALID_HANDLE_VALUE, // system pagefile.
+ &sa,
+ PAGE_READWRITE, // protection
+ 0x00000000,
+ getsystemallocgranularity (),
+ shmname // object name
+ );
+ int lasterr = GetLastError ();
+ conn->revert_to_self ();
+
+ if (filemap == NULL)
+ {
+ /* We failed to open the filemapping ? */
+ system_printf ("failed to open file mapping: %lu\n", GetLastError ());
+ // free the mutex
+ // we can assume that it exists, and that it was an access problem.
+ header.error_code = EACCES;
+ return;
+ }
+
+ /* successfully opened the control region mapping */
+ /* did we create it ? */
+ int oldmapping = lasterr == ERROR_ALREADY_EXISTS;
+ if (oldmapping)
+ {
+ /* should never happen - we are the global daemon! */
+#if 0
+ if ((parameters.in.shmflg & IPC_CREAT)
+ && (parameters.in.shmflg & IPC_EXCL))
+#endif
+ {
+ /* FIXME free mutex */
+ CloseHandle (filemap);
+ header.error_code = EEXIST;
+ return;
+ }
+ }
+
+ /* we created a new mapping */
+ if (parameters.in.key != IPC_PRIVATE &&
+ (parameters.in.shmflg & IPC_CREAT) == 0)
+ {
+ CloseHandle (filemap);
+ /* FIXME free mutex */
+ header.error_code = ENOENT;
+ return;
+ }
+
+ conn->impersonate_client ();
+ void *mapptr = MapViewOfFile (filemap, FILE_MAP_WRITE, 0, 0, 0);
+ conn->revert_to_self ();
+
+ if (!mapptr)
+ {
+ CloseHandle (filemap);
+ //FIXME: close filemap and free the mutex
+ /* we couldn't access the mapped area with the requested permissions */
+ header.error_code = EACCES;
+ return;
+ }
+
+ conn->impersonate_client ();
+ /* Now get the user data */
+ HANDLE attachmap = CreateFileMapping (INVALID_HANDLE_VALUE, // system pagefile
+ &sa,
+ PAGE_READWRITE, // protection (FIXME)
+ 0x00000000,
+ parameters.in.size +
+ parameters.in.size %
+ getsystemallocgranularity (),
+ shmaname // object name
+ );
+ conn->revert_to_self ();
+
+ if (attachmap == NULL)
+ {
+ system_printf ("failed to get shm attachmap\n");
+ header.error_code = ENOMEM;
+ UnmapViewOfFile (mapptr);
+ CloseHandle (filemap);
+ /* FIXME exit the mutex */
+ return;
+ }
+
+ shmid_ds *shmtemp = new shmid_ds;
+ if (!shmtemp)
+ {
+ system_printf ("failed to malloc shm node\n");
+ header.error_code = ENOMEM;
+ UnmapViewOfFile (mapptr);
+ CloseHandle (filemap);
+ CloseHandle (attachmap);
+ /* FIXME exit mutex */
+ return;
+ }
+
+ /* fill out the node data */
+ shmtemp->shm_perm.cuid = getuid ();
+ shmtemp->shm_perm.uid = shmtemp->shm_perm.cuid;
+ shmtemp->shm_perm.cgid = getgid ();
+ shmtemp->shm_perm.gid = shmtemp->shm_perm.cgid;
+ shmtemp->shm_perm.mode = parameters.in.shmflg & 0x01ff;
+ shmtemp->shm_lpid = 0;
+ shmtemp->shm_nattch = 0;
+ shmtemp->shm_atime = 0;
+ shmtemp->shm_dtime = 0;
+ shmtemp->shm_ctime = time (NULL);
+ shmtemp->shm_segsz = parameters.in.size;
+ *(shmid_ds *) mapptr = *shmtemp;
+ shmtemp->mapptr = mapptr;
+
+ /* no need for InterlockedExchange here, we're serialised by the global mutex */
+ tempnode = new shmnode;
+ tempnode->shmds = shmtemp;
+ tempnode->shm_id = (int) InterlockedIncrement (&new_id);
+ tempnode->key = parameters.in.key;
+ tempnode->filemap = filemap;
+ tempnode->attachmap = attachmap;
+ tempnode->next = shm_head;
+ shm_head = tempnode;
+
+ /* we now have the area in the daemon list, opened.
+
+ FIXME: leave the system wide shm mutex */
+
+ parameters.out.shm_id = tempnode->shm_id;
+if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->filemap, &parameters.out.filemap, TRUE) != 0)
+ {
+ printf ("error duplicating filemap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ CloseHandle (from_process_handle);
+/* mutex et al */
+return;
+ }
+if (check_and_dup_handle (GetCurrentProcess (),from_process_handle,
+ token_handle,
+ DUPLICATE_SAME_ACCESS,
+ tempnode->attachmap, &parameters.out.attachmap, TRUE) != 0)
+ {
+ printf ("error duplicating attachmap handle (%lu)\n", GetLastError ());
+ header.error_code = EACCES;
+ CloseHandle (from_process_handle);
+/* more cleanup... yay! */
+return;
+ }
+ return;
+}
+#endif
diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h
new file mode 100644
index 00000000000..fe4018d32df
--- /dev/null
+++ b/winsup/cygwin/cygserver_shm.h
@@ -0,0 +1,80 @@
+/* cygserver_shm.h
+
+ Copyright 2001 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 <sys/types.h>
+#include <sys/socket.h>
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+
+#define SHM_CREATE 0
+#define SHM_REATTACH 1
+
+
+class client_request_shm_get : public client_request
+{
+ public:
+ virtual void serve (transport_layer_base *conn);
+ client_request_shm_get::client_request_shm_get(key_t, size_t, int, char psdbuf[4096], pid_t);
+ client_request_shm_get::client_request_shm_get();
+ client_request_shm_get::client_request_shm_get(int,pid_t);
+ union {
+ struct {int type; pid_t pid; int shm_id; key_t key; size_t size; int shmflg; char sd_buf[4096];} in;
+ struct {int shm_id; HANDLE filemap; HANDLE attachmap; key_t key;} out;
+ } parameters;
+};
+
+#if 0
+class _shmattach {
+public:
+ void *data;
+ class _shmattach *next;
+};
+
+class shmid_ds {
+public:
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ shmatt_t shm_nattch;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+ HANDLE filemap;
+ HANDLE attachmap;
+ void *mapptr;
+ class _shmattach *attachhead;
+};
+
+class shmnode {
+public:
+ class shmid_ds * shmid;
+ class shmnode *next;
+ key_t key;
+};
+//....
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ shmatt_t shm_nattch;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+};
+
+void *shmat(int, const void *, int);
+int shmctl(int, int, struct shmid_ds *);
+int shmdt(const void *);
+int shmget(key_t, size_t, int);
+
+#endif
diff --git a/winsup/cygwin/cygserver_transport.cc b/winsup/cygwin/cygserver_transport.cc
new file mode 100755
index 00000000000..d18e0436a0e
--- /dev/null
+++ b/winsup/cygwin/cygserver_transport.cc
@@ -0,0 +1,154 @@
+/* cygserver_transport.cc
+
+ Copyright 2001 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include "wincap.h"
+#include "cygwin/cygserver_transport.h"
+
+/* to allow this to link into cygwin and the .dll, a little magic is needed. */
+#ifndef __OUTSIDE_CYGWIN__
+#include "winsup.h"
+extern "C" int
+cygwin_socket (int af, int type, int protocol);
+extern "C" int
+cygwin_connect (int fd,
+ const struct sockaddr *name,
+ int namelen);
+extern "C" int
+cygwin_accept (int fd, struct sockaddr *peer, int *len);
+extern "C" int
+cygwin_listen (int fd, int backlog);
+extern "C" int
+cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen);
+
+#else
+#define cygwin_accept(A,B,C) ::accept(A,B,C)
+#define cygwin_socket(A,B,C) ::socket(A,B,C)
+#define cygwin_listen(A,B) ::listen(A,B)
+#define cygwin_bind(A,B,C) ::bind(A,B,C)
+#define cygwin_connect(A,B,C) ::connect(A,B,C)
+#define debug_printf printf
+#endif
+
+/* The factory */
+class transport_layer_base *create_server_transport()
+{
+ transport_layer_base *temp;
+ /* currently there is only the base class! */
+ if (wincap.is_winnt ())
+ temp = new transport_layer_pipes ();
+ else
+ temp = new transport_layer_base ();
+ return temp;
+}
+
+
+transport_layer_base::transport_layer_base (int newfd): fd(newfd)
+{
+ /* This may not be needed in this constructor - it's only used
+ * when creating a connection via bind or connect
+ */
+ sockdetails.sa_family = AF_UNIX;
+ strcpy (sockdetails.sa_data, "/tmp/cygdaemo");
+ sdlen = strlen(sockdetails.sa_data) + sizeof(sockdetails.sa_family);
+};
+
+transport_layer_base::transport_layer_base (): fd (-1)
+{
+ sockdetails.sa_family = AF_UNIX;
+ strcpy (sockdetails.sa_data, "/tmp/cygdaemo");
+ sdlen = strlen(sockdetails.sa_data) + sizeof(sockdetails.sa_family);
+}
+
+void
+transport_layer_base::listen ()
+{
+ /* we want a thread pool based approach. */
+ if ((fd = cygwin_socket (AF_UNIX, SOCK_STREAM,0)) < 0)
+ printf ("Socket not created error %d\n", errno);
+ if (cygwin_bind(fd, &sockdetails, sdlen))
+ printf ("Bind doesn't like you. Tsk Tsk. Bind said %d\n", errno);
+ if (cygwin_listen(fd, 5) < 0)
+ printf ("And the OS just isn't listening, all it says is %d\n", errno);
+}
+
+class transport_layer_base *
+transport_layer_base::accept ()
+{
+ /* FIXME: check we have listened */
+ int new_fd;
+
+ if ((new_fd = cygwin_accept(fd, &sockdetails, &sdlen)) < 0)
+ {
+ printf ("Nup, could' accept. %d\n",errno);
+ return NULL;
+ }
+
+ transport_layer_base *new_conn = new transport_layer_base (new_fd);
+
+ return new_conn;
+
+}
+
+void
+transport_layer_base::close()
+{
+ /* FIXME - are we open? */
+ ::close (fd);
+}
+
+ssize_t
+transport_layer_base::read (char *buf, size_t len)
+{
+ /* FIXME: are we open? */
+ return ::read (fd, buf, len);
+}
+
+ssize_t
+transport_layer_base::write (char *buf, size_t len)
+{
+ /* FIXME: are we open? */
+ return ::write (fd, buf, len);
+}
+
+bool
+transport_layer_base::connect ()
+{
+ /* are we already connected? */
+ if (fd != -1)
+ return false;
+ fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
+ if (cygwin_connect (fd, &sockdetails, sdlen) < 0)
+ {
+ debug_printf("client connect failure %d\n", errno);
+ ::close (fd);
+ return false;
+ }
+ return true;
+}
+
+void
+transport_layer_base::impersonate_client ()
+{
+}
+
+void
+transport_layer_base::revert_to_self ()
+{
+}
+
diff --git a/winsup/cygwin/cygserver_transport_pipes.cc b/winsup/cygwin/cygserver_transport_pipes.cc
new file mode 100755
index 00000000000..77eede49221
--- /dev/null
+++ b/winsup/cygwin/cygserver_transport_pipes.cc
@@ -0,0 +1,195 @@
+/* cygserver_transport_pipes.cc
+
+ Copyright 2001 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include "wincap.h"
+#include "cygwin/cygserver_transport.h"
+
+/* to allow this to link into cygwin and the .dll, a little magic is needed. */
+#ifndef __OUTSIDE_CYGWIN__
+#include "winsup.h"
+#else
+#define debug_printf printf
+#endif
+
+transport_layer_pipes::transport_layer_pipes (HANDLE new_pipe)
+{
+ pipe = new_pipe;
+ if (inited != true)
+ init_security();
+};
+
+transport_layer_pipes::transport_layer_pipes ()
+{
+ pipe = NULL;
+ strcpy(pipe_name, "\\\\.\\pipe\\cygwin_lpc");
+ if (inited != true)
+ init_security();
+}
+
+
+void
+transport_layer_pipes::init_security()
+{
+ /* FIXME: pthread_once or equivalent needed */
+ InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);
+
+ sec_none_nih.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
+ sec_none_nih.lpSecurityDescriptor = NULL;
+ sec_all_nih.lpSecurityDescriptor = &sd;
+ inited = true;
+}
+
+void
+transport_layer_pipes::listen ()
+{
+ /* no-op */
+}
+
+class transport_layer_pipes *
+transport_layer_pipes::accept ()
+{
+ if (pipe)
+ {
+ debug_printf ("Already have a pipe in this %p\n",this);
+ return NULL;
+ }
+
+ pipe = CreateNamedPipe (pipe_name,
+ PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_BYTE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ 0, 0, 1000,
+ &sec_all_nih );
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("error creating pipe (%lu)\n.", GetLastError ());
+ return NULL;
+ }
+
+ if ( !ConnectNamedPipe ( pipe, NULL ) &&
+ GetLastError () != ERROR_PIPE_CONNECTED)
+ {
+ printf ("error connecting to pipe (%lu)\n.", GetLastError ());
+ CloseHandle (pipe);
+ pipe = NULL;
+ return NULL;
+ }
+
+ transport_layer_pipes *new_conn = new transport_layer_pipes (pipe);
+ pipe = NULL;
+
+ return new_conn;
+}
+
+void
+transport_layer_pipes::close()
+{
+ if (pipe && pipe != INVALID_HANDLE_VALUE)
+ {
+ FlushFileBuffers (pipe);
+ DisconnectNamedPipe (pipe);
+ CloseHandle (pipe);
+ }
+}
+
+ssize_t
+transport_layer_pipes::read (char *buf, size_t len)
+{
+ DWORD bytes_read, rc;
+ if (!pipe || pipe == INVALID_HANDLE_VALUE)
+ return -1;
+
+ rc = ReadFile (pipe, buf, len, &bytes_read, NULL);
+ if (!rc)
+ {
+ debug_printf ("error reading from pipe (%lu)\n", GetLastError ());
+ return -1;
+ }
+ return bytes_read;
+}
+
+ssize_t
+transport_layer_pipes::write (char *buf, size_t len)
+{
+ DWORD bytes_written, rc;
+ if (!pipe || pipe == INVALID_HANDLE_VALUE)
+ return -1;
+
+ rc = WriteFile (pipe, buf, len, &bytes_written, NULL);
+ if (!rc)
+ {
+ debug_printf ("error writing to pipe (%lu)\n", GetLastError ());
+ return -1;
+ }
+ return bytes_written;
+}
+
+bool
+transport_layer_pipes::connect ()
+{
+ if (pipe && pipe != INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("Already have a pipe in this %p\n",this);
+ return false;
+ }
+
+ while (1)
+ {
+ pipe = CreateFile (pipe_name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sec_all_nih,
+ OPEN_EXISTING,
+ 0, NULL);
+
+ if (pipe != INVALID_HANDLE_VALUE)
+ /* got the pipe */
+ return true;
+
+ if (GetLastError () != ERROR_PIPE_BUSY)
+ {
+ debug_printf ("Error opening the pipe (%lu)\n", GetLastError ());
+ pipe = NULL;
+ return false;
+ }
+ if (!WaitNamedPipe (pipe_name, 20000))
+ debug_printf ( "error connecting to server pipe after 20 seconds (%lu)\n", GetLastError () );
+ /* We loop here, because the pipe exists but is busy. If it doesn't exist
+ * the != ERROR_PIPE_BUSY will catch it.
+ */
+ }
+}
+
+void
+transport_layer_pipes::impersonate_client ()
+{
+ if (pipe && pipe != INVALID_HANDLE_VALUE)
+ ImpersonateNamedPipeClient (pipe);
+ debug_printf("I am who you are\n");
+}
+
+void
+transport_layer_pipes::revert_to_self ()
+{
+ RevertToSelf ();
+ debug_printf("I am who I yam\n");
+}
+
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
new file mode 100644
index 00000000000..09f39f83f60
--- /dev/null
+++ b/winsup/cygwin/cygwin.din
@@ -0,0 +1,1226 @@
+LIBRARY "cygwin1.dll" BASE=0x61000000
+
+EXPORTS
+__assert
+__eprintf
+__errno
+__infinity
+__main
+__signgam
+__srget
+__swbuf
+__argv DATA
+__argc DATA
+__progname DATA
+_check_for_executable DATA
+; __vc__10pinfo_listi
+@ALLOCA@
+cygwin_stackdump
+abort
+_abort = abort
+abs
+_abs = abs
+access
+_access = access
+acos
+_acos = acos
+acosf
+_acosf = acosf
+acosh
+_acosh = acosh
+acoshf
+_acoshf = acoshf
+alarm
+_alarm = alarm
+alphasort
+_alphasort = alphasort
+asctime
+_asctime = asctime
+asctime_r
+_asctime_r = asctime_r
+asin
+_asin = asin
+asinf
+_asinf = asinf
+asinh
+_asinh = asinh
+asinhf
+_asinhf = asinhf
+atan
+_atan = atan
+atan2
+_atan2 = atan2
+atan2f
+_atan2f = atan2f
+atanf
+_atanf = atanf
+atanh
+_atanh = atanh
+atanhf
+_atanhf = atanhf
+atexit
+_atexit = atexit
+atof
+_atof = atof
+atoff
+_atoff = atoff
+atoi
+_atoi = atoi
+atol
+_atol = atol
+bcmp
+_bcmp = bcmp
+bcopy
+_bcopy = bcopy
+bsearch
+_bsearch = bsearch
+bzero
+_bzero = bzero
+cabs
+_cabs = cabs
+cabsf
+_cabsf = cabsf
+calloc = export_calloc
+_calloc = export_calloc
+cbrt
+_cbrt = cbrt
+cbrtf
+_cbrtf = cbrtf
+ceil
+_ceil = ceil
+ceilf
+_ceilf = ceilf
+cfgetospeed
+cfgetispeed
+cfsetospeed
+cfsetispeed
+chdir
+_chdir = chdir
+chmod
+_chmod = chmod
+chown
+_chown = chown
+cleanup_glue
+clearerr
+_clearerr = clearerr
+clock
+_clock = clock
+close
+_close = close
+closedir
+_closedir = closedir
+copysign
+_copysign = copysign
+copysignf
+_copysignf = copysignf
+cos
+_cos = cos
+cosf
+_cosf = cosf
+cosh
+_cosh = cosh
+coshf
+_coshf = coshf
+creat
+_creat = creat
+ctime
+_ctime = ctime
+ctime_r
+_ctime_r = ctime_r
+cwait
+_cwait = cwait
+difftime
+_difftime = difftime
+div
+_div = div
+dirfd
+_dirfd = dirfd
+_dll_crt0@0
+dll_crt0__FP11per_process
+cygwin_dll_init
+dll_dllcrt0
+dll_noncygwin_dllcrt0
+cygwin_detach_dll
+cygwin32_detach_dll = cygwin_detach_dll
+@DEF_DLL_ENTRY@
+drem
+_drem = drem
+dremf
+_dremf = dremf
+dup
+_dup = dup
+dup2
+_dup2 = dup2
+ecvt
+_ecvt = ecvt
+ecvtbuf
+_ecvtbuf = ecvtbuf
+ecvtf
+_ecvtf = ecvtf
+endgrent
+_endgrent = endgrent
+erf
+_erf = erf
+erfc
+_erfc = erfc
+erfcf
+_erfcf = erfcf
+erff
+_erff = erff
+execl
+_execl = execl
+execle
+_execle = execle
+execlp
+_execlp = execlp
+execv
+_execv = execv
+execve
+_execve = execve
+execvp
+_execvp = execvp
+exit
+_exit
+exp
+_exp = exp
+expf
+_expf = expf
+expm1
+_expm1 = expm1
+expm1f
+_expm1f = expm1f
+fabs
+_fabs = fabs
+fabsf
+_fabsf = fabsf
+_f_atan2
+__f_atan2 = _f_atan2
+_f_atan2f
+__f_atan2f = _f_atan2f
+fchdir
+_fchdir = fchdir
+fchmod
+_fchmod = fchmod
+fchown
+_fchown = fchown
+fclose
+_fclose = fclose
+fcntl
+_fcntl = fcntl
+fcvt
+_fcvt = fcvt
+fcvtbuf
+_fcvtbuf = fcvtbuf
+fcvtf
+_fcvtf = fcvtf
+fdopen
+_fdopen = fdopen
+feof
+_feof = feof
+ferror
+_ferror = ferror
+_f_exp
+__f_exp = _f_exp
+_f_expf
+__f_expf = _f_expf
+fflush
+_fflush = fflush
+_f_frexp
+__f_frexp = _f_frexp
+_f_frexpf
+__f_frexpf = _f_frexpf
+fgetc
+_fgetc = fgetc
+fgetpos
+_fgetpos = fgetpos
+fgets
+_fgets = fgets
+ffs
+_ffs = ffs
+fileno
+_fileno = fileno
+finite
+_finite = finite
+finitef
+_finitef = finitef
+fiprintf
+_fiprintf = fiprintf
+_f_ldexp
+__f_ldexp = _f_ldexp
+_f_ldexpf
+__f_ldexpf = _f_ldexpf
+_f_log
+__f_log = _f_log
+_f_logf
+__f_logf = _f_logf
+_f_log10
+__f_log10 = _f_log10
+_f_log10f
+__f_log10f = _f_log10f
+floor
+_floor = floor
+floorf
+_floorf = floorf
+fmod
+_fmod = fmod
+fmodf
+_fmodf = fmodf
+fopen
+_fopen = fopen
+fork
+_fork = fork
+fpathconf
+_f_pow
+__f_pow = _f_pow
+_f_powf
+__f_powf = _f_powf
+fprintf
+_fprintf = fprintf
+fputc
+_fputc = fputc
+fputs
+_fputs = fputs
+fread
+_fread = fread
+free = export_free
+_free = export_free
+freopen
+_freopen = freopen
+frexp
+_frexp = frexp
+frexpf
+_frexpf = frexpf
+fscanf
+_fscanf = fscanf
+_fscanf_r
+fscanf_r = _fscanf_r
+fseek
+_fseek = fseek
+fsetpos
+_fsetpos = fsetpos
+fstat
+_fstat = fstat
+fstatfs
+_fstatfs = fstatfs
+fsync
+_fsync = fsync
+_f_tan
+__f_tan = _f_tan
+_f_tanf
+__f_tanf = _f_tanf
+ftell
+_ftell = ftell
+ftime
+_ftime = ftime
+ftruncate
+_ftruncate = ftruncate
+fwrite
+_fwrite = fwrite
+gamma
+_gamma = gamma
+gamma_r
+_gamma_r = gamma_r
+gammaf
+_gammaf = gammaf
+gammaf_r
+_gammaf_r = gammaf_r
+gcvt
+_gcvt = gcvt
+gcvtf
+_gcvtf = gcvtf
+getc
+_getc = getc
+getchar
+_getchar = getchar
+getcwd
+_getcwd = getcwd
+getdtablesize
+_getdtablesize = getdtablesize
+getegid
+_getegid = getegid
+geteuid
+_geteuid = geteuid
+getgid
+_getgid = getgid
+getgrgid
+_getgrgid = getgrgid
+getgrnam
+_getgrnam = getgrnam
+getgroups
+_getgroups = getgroups
+gethostname = cygwin_gethostname
+_gethostname = cygwin_gethostname
+getlogin
+_getlogin = getlogin
+getmntent
+_getmntent = getmntent
+getmode
+_getmode = getmode
+get_osfhandle
+_get_osfhandle = get_osfhandle
+getpagesize
+_getpagesize = getpagesize
+getpass
+_getpass = getpass
+getpid
+_getpid = getpid
+getppid
+_getppid = getppid
+getrlimit
+_getrlimit = getrlimit
+getrusage
+_getrusage = getrusage
+gets
+_gets = gets
+gettimeofday
+_gettimeofday = gettimeofday
+getuid
+_getuid = getuid
+glob
+_glob = glob
+globfree
+_globfree = globfree
+gmtime
+_gmtime = gmtime
+gmtime_r
+_gmtime_r = gmtime_r
+h_errno DATA
+hypot
+_hypot = hypot
+hypotf
+_hypotf = hypotf
+ilogb
+_ilogb = ilogb
+ilogbf
+_ilogbf = ilogbf
+index
+_index = index
+infinity
+_infinity = infinity
+infinityf
+_infinityf = infinityf
+initgroups
+ioctl
+_ioctl = ioctl
+iprintf
+_iprintf = iprintf
+isalnum
+_isalnum = isalnum
+isalpha
+_isalpha = isalpha
+isascii
+_isascii = isascii
+isatty
+_isatty = isatty
+iscntrl
+_iscntrl = iscntrl
+isdigit
+_isdigit = isdigit
+isgraph
+_isgraph = isgraph
+isinf
+_isinf = isinf
+isinff
+_isinff = isinff
+islower
+_islower = islower
+isnan
+_isnan = isnan
+isnanf
+_isnanf = isnanf
+isprint
+_isprint = isprint
+ispunct
+_ispunct = ispunct
+isspace
+_isspace = isspace
+isupper
+_isupper = isupper
+isxdigit
+_isxdigit = isxdigit
+j0
+_j0 = j0
+j0f
+_j0f = j0f
+j1
+_j1 = j1
+j1f
+_j1f = j1f
+jn
+_jn = jn
+jnf
+_jnf = jnf
+kill
+_kill = kill
+labs
+_labs = labs
+lchown
+_lchown = lchown
+ldexp
+_ldexp = ldexp
+ldexpf
+_ldexpf = ldexpf
+ldiv
+_ldiv = ldiv
+lgamma
+_lgamma = lgamma
+lgamma_r
+_lgamma_r = lgamma_r
+lgammaf
+_lgammaf = lgammaf
+lgammaf_r
+_lgammaf_r = lgammaf_r
+link
+_link = link
+localeconv
+_localeconv = localeconv
+localtime
+_localtime = localtime
+localtime_r
+_localtime_r = localtime_r
+log
+_log = log
+log10
+_log10 = log10
+log10f
+_log10f = log10f
+log1p
+_log1p = log1p
+log1pf
+_log1pf = log1pf
+logb
+_logb = logb
+logbf
+_logbf = logbf
+logf
+_logf = logf
+login
+logout
+longjmp
+_longjmp = longjmp
+lseek
+_lseek = lseek
+lstat
+_lstat = lstat
+malloc = export_malloc
+_malloc = export_malloc
+matherr
+_matherr = matherr
+mblen
+_mblen = mblen
+mbstowcs
+_mbstowcs = mbstowcs
+mbtowc
+_mbtowc = mbtowc
+memchr
+_memchr = memchr
+memcmp
+_memcmp = memcmp
+memcpy
+_memcpy = memcpy
+memmove
+_memmove = memmove
+memset
+_memset = memset
+mkdir
+_mkdir = mkdir
+mkfifo
+mknod
+_mknod = mknod
+mkstemp
+_mkstemp = mkstemp
+mktemp
+_mktemp = mktemp
+mktime
+_mktime = mktime
+mmap
+mprotect
+msync
+munmap
+modf
+_modf = modf
+modff
+_modff = modff
+nan
+_nan = nan
+nanf
+_nanf = nanf
+nextafter
+_nextafter = nextafter
+nextafterf
+_nextafterf = nextafterf
+open
+_open = open
+opendir
+_opendir = opendir
+pathconf
+_pathconf = pathconf
+perror
+_perror = perror
+pipe
+_pipe
+poll
+_poll = poll
+pow
+_pow = pow
+powf
+_powf = powf
+printf
+_printf = printf
+putc
+_putc = putc
+putchar
+_putchar = putchar
+puts
+_puts = puts
+putw
+_putw = putw
+qsort
+_qsort = qsort
+raise
+_raise = raise
+rand
+_rand = rand
+random
+initstate
+setstate
+read
+_read = read
+readdir
+_readdir = readdir
+readlink
+_readlink = readlink
+readv
+_readv = readv
+realloc = export_realloc
+_realloc = export_realloc
+regcomp
+_regcomp = regcomp
+regexec
+_regexec = regexec
+regerror
+_regerror = regerror
+regfree
+_regfree = regfree
+regsub
+_regsub = regsub
+remainder
+_remainder = remainder
+remainderf
+_remainderf = remainderf
+remove
+_remove = remove
+rename
+_rename = rename
+rewind
+_rewind = rewind
+rewinddir
+_rewinddir = rewinddir
+rindex
+_rindex = rindex
+rint
+_rint = rint
+rintf
+_rintf = rintf
+rmdir
+_rmdir = rmdir
+sbrk
+_sbrk = sbrk
+scalb
+_scalb = scalb
+scalbf
+_scalbf = scalbf
+scalbn
+_scalbn = scalbn
+scalbnf
+_scalbnf = scalbnf
+scandir
+_scandir = scandir
+scanf
+_scanf = scanf
+_scanf_r
+scanf_r = _scanf_r
+seekdir
+_seekdir = seekdir
+setbuf
+_setbuf = setbuf
+setdtablesize
+_setdtablesize = setdtablesize
+setgid
+_setgid = setgid
+setjmp
+_setjmp = setjmp
+setlocale
+_setlocale = setlocale
+setpgid
+_setpgid = setpgid
+setrlimit
+_setrlimit = setrlimit
+setsid
+_setsid = setsid
+settimeofday
+_settimeofday = settimeofday
+seteuid
+_seteuid = seteuid
+setegid
+_setegid = setegid
+setuid
+_setuid = setuid
+chroot
+_chroot = chroot
+setvbuf
+_setvbuf = setvbuf
+sigaction
+_sigaction = sigaction
+sigaddset
+_sigaddset = sigaddset
+sigdelset
+_sigdelset = sigdelset
+sigismember
+_sigismember = sigismember
+sigemptyset
+_sigemptyset = sigemptyset
+sigfillset
+_sigfillset = sigfillset
+signal
+_signal = signal
+significand
+_significand = significand
+significandf
+_significandf = significandf
+sigpending
+_sigpending = sigpending
+sigprocmask
+_sigprocmask = sigprocmask
+sigsuspend
+_sigsuspend = sigsuspend
+sin
+_sin = sin
+sinf
+_sinf = sinf
+sinh
+_sinh = sinh
+sinhf
+_sinhf = sinhf
+siprintf
+_siprintf = siprintf
+sleep
+_sleep = sleep
+spawnl
+_spawnl = spawnl
+spawnle
+_spawnle = spawnle
+spawnlp
+_spawnlp = spawnlp
+spawnlpe
+_spawnlpe = spawnlpe
+spawnv
+_spawnv = spawnv
+spawnve
+_spawnve = spawnve
+spawnvp
+_spawnvp = spawnvp
+spawnvpe
+_spawnvpe = spawnvpe
+sprintf
+_sprintf = sprintf
+snprintf
+_snprintf = snprintf
+sqrt
+_sqrt = sqrt
+sqrtf
+_sqrtf = sqrtf
+srand
+_srand = srand
+srandom
+sscanf
+_sscanf = sscanf
+_sscanf_r
+sscanf_r = _sscanf_r
+stat
+_stat = stat
+statfs
+_statfs = statfs
+strcasecmp
+_strcasecmp = strcasecmp
+strcat
+_strcat = strcat
+strchr
+_strchr = strchr
+strcmp
+_strcmp = strcmp
+strcoll
+_strcoll = strcoll
+strcpy
+_strcpy = strcpy
+strcspn
+_strcspn = strcspn
+strdup
+_strdup = strdup
+strerror
+_strerror = strerror
+strlen
+_strlen = strlen
+strlwr
+_strlwr = strlwr
+strncasecmp
+_strncasecmp = strncasecmp
+strncat
+_strncat = strncat
+strncmp
+_strncmp = strncmp
+strncpy
+_strncpy = strncpy
+strpbrk
+_strpbrk = strpbrk
+strrchr
+_strrchr = strrchr
+strspn
+_strspn = strspn
+strstr
+_strstr = strstr
+strtod
+_strtod = strtod
+strtodf
+_strtodf = strtodf
+strtok
+_strtok = strtok
+strtok_r
+_strtok_r = strtok_r
+strtol
+_strtol = strtol
+strtoul
+_strtoul = strtoul
+strupr
+_strupr = strupr
+strxfrm
+_strxfrm = strxfrm
+swab
+_swab = swab
+symlink
+_symlink = symlink
+sync
+_sync = sync
+sysconf
+_sysconf = sysconf
+system
+_system = system
+tan
+_tan = tan
+tanf
+_tanf = tanf
+tanh
+_tanh = tanh
+tanhf
+_tanhf = tanhf
+tcdrain
+_tcdrain = tcdrain
+tcflow
+_tcflow = tcflow
+tcflush
+_tcflush = tcflush
+tcgetattr
+_tcgetattr = tcgetattr
+tcgetpgrp
+_tcgetpgrp = tcgetpgrp
+tcsendbreak
+_tcsendbreak = tcsendbreak
+tcsetattr
+_tcsetattr = tcsetattr
+tcsetpgrp
+_tcsetpgrp = tcsetpgrp
+telldir
+_telldir = telldir
+tempnam
+_tempnam = tempnam
+time
+_time = time
+times
+_times = times
+timezone
+tmpfile
+_tmpfile = tmpfile
+tmpnam
+_tmpnam = tmpnam
+toascii
+_toascii = toascii
+tolower
+_tolower = tolower
+toupper
+_toupper = toupper
+truncate
+_truncate = truncate
+ttyname
+_ttyname = ttyname
+tzset
+_tzset = tzset
+umask
+_umask = umask
+uname
+_uname = uname
+ungetc
+_ungetc = ungetc
+unlink
+_unlink = unlink
+utime
+_utime = utime
+utimes
+_utimes = utimes
+vfiprintf
+_vfiprintf = vfiprintf
+vfork
+_vfork = vfork
+vfprintf
+_vfprintf = vfprintf
+vfscanf
+_vfscanf = vfscanf
+_vfscanf_r
+vfscanf_r = _vfscanf_r
+vprintf
+_vprintf = vprintf
+vscanf
+_vscanf = vscanf
+_vscanf_r
+vscanf_r = _vscanf_r
+vsprintf
+_vsprintf = vsprintf
+vsnprintf
+_vsnprintf = vsnprintf
+vsscanf
+_vsscanf = vsscanf
+_vsscanf_r
+vsscanf_r = _vsscanf_r
+wait
+_wait = wait
+waitpid
+_waitpid = waitpid
+wait3
+wait4
+wcstombs
+_wcstombs = wcstombs
+wctomb
+_wctomb = wctomb
+write
+_write = write
+writev
+_writev = writev
+y0
+y0f
+y1
+y1f
+yn
+ynf
+drand48
+_drand48 = drand48
+erand48
+_erand48 = erand48
+jrand48
+_jrand48 = jrand48
+lcong48
+_lcong48 = lcong48
+lrand48
+_lrand48 = lrand48
+mrand48
+_lrand48 = lrand48
+nrand48
+_nrand48 = nrand48
+seed48
+_seed48 = seed48
+srand48
+_srand48 = srand48
+setmode
+_setmode = setmode
+__assertfail
+getw
+_getw = getw
+getwd
+_getwd = getwd
+popen
+_popen = popen
+pclose
+_pclose = pclose
+strftime
+_strftime = strftime
+setgrent
+_setgrent = setgrent
+cuserid
+_cuserid = cuserid
+setpgrp
+_setpgrp = setpgrp
+mount
+_mount = mount
+setmntent
+_setmntent = setmntent
+endmntent
+_endmntent = endmntent
+umount
+_umount = umount
+wcscmp
+_wcscmp = wcscmp
+wcslen
+_wcslen = wcslen
+usleep
+_usleep = usleep
+wprintf
+_wprintf = wprintf
+memccpy
+_memccpy = memccpy
+getpwent
+_getpwent = getpwent
+endpwent
+_endpwent = endpwent
+setpwent
+_setpwent = setpwent
+getpwduid
+_getpwduid = getpwduid
+getpwnam
+_getpwnam = getpwnam
+getpwnam_r
+getpwuid
+_getpwuid = getpwuid
+getpwuid_r
+getpgrp
+_getpgrp = getpgrp
+getgrent
+_getgrent = getgrent
+ntohl
+_ntohl = ntohl
+htonl
+_htonl = htonl
+htons
+_htons = htons
+ntohs
+_ntohs = ntohs
+accept = cygwin_accept
+bind = cygwin_bind
+connect = cygwin_connect
+hstrerror = cygwin_hstrerror
+herror = cygwin_herror
+inet_addr = cygwin_inet_addr
+inet_network = cygwin_inet_network
+inet_netof
+inet_makeaddr
+listen = cygwin_listen
+getdomainname
+_getdomainname = getdomainname
+gethostbyaddr = cygwin_gethostbyaddr
+gethostbyname = cygwin_gethostbyname
+getpeername = cygwin_getpeername
+getprotobyname = cygwin_getprotobyname
+getprotobynumber = cygwin_getprotobynumber
+getservbyname = cygwin_getservbyname
+getservbyport = cygwin_getservbyport
+getsockname = cygwin_getsockname
+getsockopt = cygwin_getsockopt
+recv = cygwin_recv
+select = cygwin_select
+_select = cygwin_select
+send = cygwin_send
+socket = cygwin_socket
+setsockopt = cygwin_setsockopt
+inet_aton = cygwin_inet_aton
+inet_ntoa = cygwin_inet_ntoa
+recvfrom = cygwin_recvfrom
+sendto = cygwin_sendto
+shutdown = cygwin_shutdown
+sethostent
+endhostent
+setpassent
+_setpassent = setpassent
+strsep
+_strsep = strsep
+syslog
+_syslog = syslog
+closelog
+_closelog = closelog
+openlog
+_openlog = openlog
+setlogmask
+vhangup
+_vhangup = vhangup
+nice
+_nice = nice
+cygwin_conv_to_win32_path
+cygwin_conv_to_full_win32_path
+cygwin_conv_to_posix_path
+cygwin_conv_to_full_posix_path
+cygwin_posix_path_list_p
+cygwin_win32_to_posix_path_list_buf_size
+cygwin_posix_to_win32_path_list_buf_size
+cygwin_win32_to_posix_path_list
+cygwin_posix_to_win32_path_list
+cygwin_split_path
+cygwin_umount
+cygwin32_conv_to_win32_path = cygwin_conv_to_win32_path
+cygwin32_conv_to_full_win32_path = cygwin_conv_to_full_win32_path
+cygwin32_conv_to_posix_path = cygwin_conv_to_posix_path
+cygwin32_conv_to_full_posix_path = cygwin_conv_to_full_posix_path
+cygwin32_posix_path_list_p = cygwin_posix_path_list_p
+cygwin32_win32_to_posix_path_list_buf_size = cygwin_win32_to_posix_path_list_buf_size
+cygwin32_posix_to_win32_path_list_buf_size = cygwin_posix_to_win32_path_list_buf_size
+cygwin32_win32_to_posix_path_list = cygwin_win32_to_posix_path_list
+cygwin32_posix_to_win32_path_list = cygwin_posix_to_win32_path_list
+cygwin32_split_path = cygwin_split_path
+cygwin_winpid_to_pid
+cygwin32_winpid_to_pid = cygwin_winpid_to_pid
+cygwin_logon_user
+cygwin_set_impersonation_token
+realpath
+reent_data DATA
+getenv
+_getenv = getenv
+putenv
+_putenv = putenv
+setenv
+_setenv = setenv
+unsetenv
+_unsetenv = unsetenv
+setitimer
+getitimer
+getpgid
+killpg
+pause
+__cygwin_environ DATA
+__cygwin_user_data DATA
+_ctype_ DATA
+_sys_errlist DATA
+sys_errlist = _sys_errlist DATA
+_sys_nerr DATA
+sys_nerr = _sys_nerr DATA
+__mb_cur_max DATA
+_timezone DATA
+_daylight DATA
+_tzname DATA
+ptsname
+grantpt
+unlockpt
+sexecve
+sexecl
+sexecle
+sexeclp
+sexeclpe
+sexecv
+sexecp
+sexecvpe
+ttyslot
+rcmd = cygwin_rcmd
+rresvport = cygwin_rresvport
+rexec = cygwin_rexec
+socketpair
+strsignal
+strtosigno
+ctermid
+dlopen
+dlclose
+dlsym
+dlerror
+dlfork
+sigpause
+cygwin_attach_handle_to_fd
+cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd
+cygwin_internal
+cygwin32_internal = cygwin_internal
+pthread_atfork
+pthread_attr_destroy
+pthread_attr_getdetachstate
+pthread_attr_getinheritsched
+pthread_attr_getschedparam
+pthread_attr_getschedpolicy
+pthread_attr_getscope
+pthread_attr_getstacksize
+pthread_attr_init
+pthread_attr_setdetachstate
+pthread_attr_setinheritsched
+pthread_attr_setschedparam
+pthread_attr_setschedpolicy
+pthread_attr_setscope
+pthread_attr_setstacksize
+pthread_cancel
+pthread_cond_broadcast
+pthread_cond_destroy
+pthread_cond_init
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_condattr_destroy
+pthread_condattr_getpshared
+pthread_condattr_init
+pthread_condattr_setpshared
+pthread_create
+pthread_detach
+pthread_equal
+pthread_exit
+pthread_getconcurrency
+pthread_getschedparam
+pthread_getspecific
+pthread_join
+pthread_key_create
+pthread_key_delete
+pthread_mutex_destroy
+pthread_mutex_getprioceiling
+pthread_mutex_init
+pthread_mutex_lock
+pthread_mutex_setprioceiling
+pthread_mutex_trylock
+pthread_mutex_unlock
+pthread_mutexattr_destroy
+pthread_mutexattr_getprioceiling
+pthread_mutexattr_getprotocol
+pthread_mutexattr_getpshared
+pthread_mutexattr_gettype
+pthread_mutexattr_init
+pthread_mutexattr_setprioceiling
+pthread_mutexattr_setprotocol
+pthread_mutexattr_setpshared
+pthread_mutexattr_settype
+pthread_once
+pthread_self
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setconcurrency
+pthread_setschedparam
+pthread_setspecific
+pthread_testcancel
+pthread_suspend
+pthread_continue
+pthread_kill
+pthread_sigmask
+sem_init
+sem_destroy
+sem_wait
+sem_trywait
+sem_post
+sched_get_priority_max
+sched_get_priority_min
+sched_getparam
+sched_getscheduler
+sched_rr_get_interval
+sched_setparam
+sched_setscheduler
+sched_yield
+acl
+_acl = acl
+facl
+_facl = facl
+lacl
+_lacl = lacl
+aclcheck
+_aclcheck = aclcheck
+aclsort
+_aclsort = aclsort
+acltomode
+_acltomode = acltomode
+aclfrommode
+_aclfrommode = aclfrommode
+acltopbits
+_acltopbits = acltopbits
+aclfrompbits
+_aclfrompbits = aclfrompbits
+acltotext
+_acltotext = acltotext
+aclfromtext
+_aclfromtext = aclfromtext
+ftok
+shmat
+shmctl
+shmget
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
new file mode 100644
index 00000000000..00059f2725e
--- /dev/null
+++ b/winsup/cygwin/dcrt0.cc
@@ -0,0 +1,1023 @@
+/* dcrt0.cc -- essentially the main() for the Cygwin dll
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 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. */
+
+#include "winsup.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include "glob.h"
+#include "exceptions.h"
+#include <ctype.h>
+#include <limits.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "heap.h"
+#include "cygerrno.h"
+#define NEED_VFORK
+#include "perprocess.h"
+#include "security.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "path.h"
+#include "cygheap.h"
+#include "child_info.h"
+#include "perthread.h"
+#include "shared_info.h"
+#include "cygwin_version.h"
+#include "dll_init.h"
+#include <sys/socket.h>
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+
+#define MAX_AT_FILE_LEVEL 10
+
+#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
+
+HANDLE NO_COPY hMainProc = NULL;
+HANDLE NO_COPY hMainThread = NULL;
+
+sigthread NO_COPY mainthread; // ID of the main thread
+
+per_thread_waitq NO_COPY waitq_storage;
+per_thread_vfork NO_COPY vfork_storage;
+per_thread_signal_dispatch NO_COPY signal_dispatch_storage;
+
+per_thread NO_COPY *threadstuff[] = {&waitq_storage,
+ &vfork_storage,
+ &signal_dispatch_storage,
+ NULL};
+
+BOOL display_title;
+BOOL strip_title_path;
+BOOL allow_glob = TRUE;
+codepage_type current_codepage = ansi_cp;
+
+int cygwin_finished_initializing;
+
+/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
+ This is subtracted from the signal number prior to shifting the bit.
+ In older versions of cygwin, the signal was used as-is to shift the
+ bit for masking. So, we'll temporarily detect this and set it to zero
+ for programs that are linked using older cygwins. This is just a stopgap
+ measure to allow an orderly transfer to the new, correct sigmask method. */
+unsigned NO_COPY int signal_shift_subtract = 1;
+
+ResourceLocks _reslock NO_COPY;
+MTinterface _mtinterf;
+
+bool NO_COPY _cygwin_testing;
+
+extern "C"
+{
+ void *export_malloc (unsigned int);
+ void export_free (void *);
+ void *export_realloc (void *, unsigned int);
+ void *export_calloc (unsigned int, unsigned int);
+
+ /* This is an exported copy of environ which can be used by DLLs
+ which use cygwin.dll. */
+ char **__cygwin_environ;
+ char ***main_environ;
+ /* __progname used in getopt error message */
+ char *__progname;
+ struct _reent reent_data = _REENT_INIT(reent_data);
+ struct per_process __cygwin_user_data =
+ {/* initial_sp */ 0, /* magic_biscuit */ 0,
+ /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
+ /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
+ /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
+ /* malloc */ export_malloc, /* free */ export_free,
+ /* realloc */ export_realloc,
+ /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
+ /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
+ /* bss_start */ NULL, /* bss_end */ NULL,
+ /* calloc */ export_calloc,
+ /* premain */ {NULL, NULL, NULL, NULL},
+ /* run_ctors_p */ 0,
+ /* unused */ {0, 0, 0, 0, 0, 0, 0},
+ /* forkee */ 0,
+ /* hmodule */ NULL,
+ /* api_major */ CYGWIN_VERSION_API_MAJOR,
+ /* api_minor */ CYGWIN_VERSION_API_MINOR,
+ /* unused2 */ {0, 0, 0, 0, 0},
+ /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
+ /* impure_ptr */ &reent_data,
+ };
+ bool ignore_case_with_glob;
+ int __declspec (dllexport) _check_for_executable = TRUE;
+#ifdef DEBUGGING
+ int pinger;
+#endif
+};
+
+char *old_title;
+char title_buf[TITLESIZE + 1];
+
+static void
+do_global_dtors (void)
+{
+ if (user_data->dtors)
+ {
+ void (**pfunc)() = user_data->dtors;
+ while (*++pfunc)
+ (*pfunc) ();
+ }
+}
+
+static void __stdcall
+do_global_ctors (void (**in_pfunc)(), int force)
+{
+ if (!force)
+ {
+ if (user_data->forkee || user_data->run_ctors_p)
+ return; // inherit constructed stuff from parent pid
+ user_data->run_ctors_p = 1;
+ }
+
+ /* Run ctors backwards, so skip the first entry and find how many
+ there are, then run them. */
+
+ void (**pfunc)() = in_pfunc;
+
+ while (*++pfunc)
+ ;
+ while (--pfunc > in_pfunc)
+ (*pfunc) ();
+
+ if (user_data->magic_biscuit == SIZEOF_PER_PROCESS)
+ atexit (do_global_dtors);
+}
+
+/*
+ * Replaces -@file in the command line with the contents of the file.
+ * There may be multiple -@file's in a single command line
+ * A \-@file is replaced with -@file so that echo \-@foo would print
+ * -@foo and not the contents of foo.
+ */
+static int __stdcall
+insert_file (char *name, char *&cmd)
+{
+ HANDLE f;
+ DWORD size;
+
+ f = CreateFile (name + 1,
+ GENERIC_READ, /* open for reading */
+ FILE_SHARE_READ, /* share for reading */
+ &sec_none_nih, /* no security */
+ OPEN_EXISTING, /* existing file only */
+ FILE_ATTRIBUTE_NORMAL, /* normal file */
+ NULL); /* no attr. template */
+
+ if (f == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("couldn't open file '%s', %E", name);
+ return FALSE;
+ }
+
+ /* This only supports files up to about 4 billion bytes in
+ size. I am making the bold assumption that this is big
+ enough for this feature */
+ size = GetFileSize (f, NULL);
+ if (size == 0xFFFFFFFF)
+ {
+ debug_printf ("couldn't get file size for '%s', %E", name);
+ return FALSE;
+ }
+
+ int new_size = strlen (cmd) + size + 2;
+ char *tmp = (char *) malloc (new_size);
+ if (!tmp)
+ {
+ debug_printf ("malloc failed, %E");
+ return FALSE;
+ }
+
+ /* realloc passed as it should */
+ DWORD rf_read;
+ BOOL rf_result;
+ rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
+ CloseHandle (f);
+ if (!rf_result || (rf_read != size))
+ {
+ debug_printf ("ReadFile failed, %E");
+ return FALSE;
+ }
+
+ tmp[size++] = ' ';
+ strcpy (tmp + size, cmd);
+ cmd = tmp;
+ return TRUE;
+}
+
+static inline int
+isquote (char c)
+{
+ char ch = c;
+ return ch == '"' || ch == '\'';
+}
+
+/* Step over a run of characters delimited by quotes */
+static /*__inline*/ char *
+quoted (char *cmd, int winshell)
+{
+ char *p;
+ char quote = *cmd;
+
+ if (!winshell)
+ {
+ char *p;
+ strcpy (cmd, cmd + 1);
+ if ((p = strchr (cmd, quote)) != NULL)
+ strcpy (p, p + 1);
+ else
+ p = strchr (cmd, '\0');
+ return p;
+ }
+
+ const char *s = quote == '\'' ? "'" : "\\\"";
+ /* This must have been run from a Windows shell, so preserve
+ quotes for globify to play with later. */
+ while (*cmd && *++cmd)
+ if ((p = strpbrk (cmd, s)) == NULL)
+ {
+ cmd = strchr (cmd, '\0'); // no closing quote
+ break;
+ }
+ else if (*p == '\\')
+ cmd = ++p;
+ else if (quote == '"' && p[1] == '"')
+ {
+ *p = '\\';
+ cmd = ++p; // a quoted quote
+ }
+ else
+ {
+ cmd = p + 1; // point to after end
+ break;
+ }
+ return cmd;
+}
+
+/* Perform a glob on word if it contains wildcard characters.
+ Also quote every character between quotes to force glob to
+ treat the characters literally. */
+static int __stdcall
+globify (char *word, char **&argv, int &argc, int &argvlen)
+{
+ if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
+ return 0;
+
+ int n = 0;
+ char *p, *s;
+ int dos_spec = isdrive (word);
+ if (!dos_spec && isquote (*word) && word[1] && word[2])
+ dos_spec = isdrive (word + 1);
+
+ /* We'll need more space if there are quoting characters in
+ word. If that is the case, doubling the size of the
+ string should provide more than enough space. */
+ if (strpbrk (word, "'\""))
+ n = strlen (word);
+ char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
+
+ /* Fill pattern with characters from word, quoting any
+ characters found within quotes. */
+ for (p = pattern, s = word; *s != '\000'; s++, p++)
+ if (!isquote (*s))
+ {
+ if (dos_spec && *s == '\\')
+ *p++ = '\\';
+ *p = *s;
+ }
+ else
+ {
+ char quote = *s;
+ while (*++s && *s != quote)
+ {
+ if (dos_spec || *s != '\\')
+ /* nothing */;
+ else if (s[1] == quote || s[1] == '\\')
+ s++;
+ *p++ = '\\';
+ *p++ = *s;
+ }
+ if (*s == quote)
+ p--;
+ if (*s == '\0')
+ break;
+ }
+
+ *p = '\0';
+
+ glob_t gl;
+ gl.gl_offs = 0;
+
+ /* Attempt to match the argument. Return just word (minus quoting) if no match. */
+ if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
+ return 0;
+
+ /* Allocate enough space in argv for the matched filenames. */
+ n = argc;
+ if ((argc += gl.gl_pathc) > argvlen)
+ {
+ argvlen = argc + 10;
+ argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
+ }
+
+ /* Copy the matched filenames to argv. */
+ char **gv = gl.gl_pathv;
+ char **av = argv + n;
+ while (*gv)
+ {
+ debug_printf ("argv[%d] = '%s'\n", n++, *gv);
+ *av++ = *gv++;
+ }
+
+ /* Clean up after glob. */
+ free (gl.gl_pathv);
+ return 1;
+}
+
+/* Build argv, argc from string passed from Windows. */
+
+static void __stdcall
+build_argv (char *cmd, char **&argv, int &argc, int winshell)
+{
+ int argvlen = 0;
+ int nesting = 0; // monitor "nesting" from insert_file
+
+ argc = 0;
+ argvlen = 0;
+ argv = NULL;
+
+ /* Scan command line until there is nothing left. */
+ while (*cmd)
+ {
+ /* Ignore spaces */
+ if (issep (*cmd))
+ {
+ cmd++;
+ continue;
+ }
+
+ /* Found the beginning of an argument. */
+ char *word = cmd;
+ char *sawquote = NULL;
+ while (*cmd)
+ {
+ if (*cmd != '"' && (!winshell || *cmd != '\''))
+ cmd++; // Skip over this character
+ else
+ /* Skip over characters until the closing quote */
+ {
+ sawquote = cmd;
+ cmd = quoted (cmd, winshell && argc > 0);
+ }
+ if (issep (*cmd)) // End of argument if space
+ break;
+ }
+ if (*cmd)
+ *cmd++ = '\0'; // Terminate `word'
+
+ /* Possibly look for @file construction assuming that this isn't
+ the very first argument and the @ wasn't quoted */
+ if (argc && sawquote != word && *word == '@')
+ {
+ if (++nesting > MAX_AT_FILE_LEVEL)
+ api_fatal ("Too many levels of nesting for %s", word);
+ if (insert_file (word, cmd))
+ continue; // There's new stuff in cmd now
+ }
+
+ /* See if we need to allocate more space for argv */
+ if (argc >= argvlen)
+ {
+ argvlen = argc + 10;
+ argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
+ }
+
+ /* Add word to argv file after (optional) wildcard expansion. */
+ if (!winshell || !argc || !globify (word, argv, argc, argvlen))
+ {
+ debug_printf ("argv[%d] = '%s'\n", argc, word);
+ argv[argc++] = word;
+ }
+ }
+
+ argv[argc] = NULL;
+
+ debug_printf ("argc %d", argc);
+}
+
+/* sanity and sync check */
+void __stdcall
+check_sanity_and_sync (per_process *p)
+{
+ /* Sanity check to make sure developers didn't change the per_process */
+ /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
+ /* about changing it]. */
+ if (sizeof (per_process) != SIZEOF_PER_PROCESS)
+ {
+ api_fatal ("per_process sanity check failed");
+ }
+
+ /* Make sure that the app and the dll are in sync. */
+
+ /* Complain if older than last incompatible change */
+ if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
+ api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
+ p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
+
+ /* magic_biscuit != 0 if using the old style version numbering scheme. */
+ if (p->magic_biscuit != SIZEOF_PER_PROCESS)
+ api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
+ p->magic_biscuit, SIZEOF_PER_PROCESS);
+
+ /* Complain if incompatible API changes made */
+ if (p->api_major != cygwin_version.api_major)
+ api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d < %d",
+ p->api_major, cygwin_version.api_major);
+
+ if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
+ CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
+ signal_shift_subtract = 0;
+}
+
+static NO_COPY STARTUPINFO si;
+# define fork_info ((struct child_info_fork *)(si.lpReserved2))
+# define spawn_info ((struct child_info_spawn *)(si.lpReserved2))
+child_info_fork NO_COPY *child_proc_info = NULL;
+static MEMORY_BASIC_INFORMATION sm;
+
+#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? PAGE_GUARD : PAGE_NOACCESS)
+
+// __inline__ void
+extern void
+alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
+{
+ void *new_stack_pointer;
+ MEMORY_BASIC_INFORMATION m;
+ void *newbase;
+ int newlen;
+ LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
+ bool noguard;
+
+ if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
+ {
+ newbase = curbot;
+ newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
+ noguard = 1;
+ }
+ else
+ {
+ newbase = ci->stacktop;
+ newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
+ noguard = 0;
+ }
+ if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
+ api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
+ ci->stacktop, ci->stackbottom);
+
+ new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
+
+ if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE))
+ api_fatal ("fork: can't commit memory for stack %p(%d), %E",
+ new_stack_pointer, ci->stacksize);
+ if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
+ api_fatal ("fork: couldn't get new stack info, %E");
+ if (!noguard)
+ {
+ m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
+ if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE|CYGWIN_GUARD))
+ api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
+ m.BaseAddress);
+ }
+ if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
+ api_fatal ("fork: couldn't get new stack info, %E");
+ ci->stacktop = m.BaseAddress;
+ *b = 0;
+}
+
+/* extend the stack prior to fork longjmp */
+
+static void
+alloc_stack (child_info_fork *ci)
+{
+ /* FIXME: adding 16384 seems to avoid a stack copy problem during
+ fork on Win95, but I don't know exactly why yet. DJ */
+ volatile char b[ci->stacksize + 16384];
+
+ if (ci->type == PROC_FORK)
+ ci->stacksize = 0; // flag to fork not to do any funny business
+ else
+ {
+ if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
+ api_fatal ("fork: couldn't get stack info, %E");
+
+ if (sm.AllocationBase != ci->stacktop)
+ alloc_stack_hard_way (ci, b + sizeof (b) - 1);
+ else
+ ci->stacksize = 0;
+ }
+
+ return;
+}
+
+static NO_COPY int mypid = 0;
+int _declspec(dllexport) __argc;
+char _declspec(dllexport) **__argv;
+vfork_save NO_COPY *main_vfork = NULL;
+
+void
+sigthread::init (const char *s)
+{
+ InitializeCriticalSection (&lock);
+ id = GetCurrentThreadId ();
+}
+
+/* Take over from libc's crt0.o and start the application. Note the
+ various special cases when Cygwin DLL is being runtime loaded (as
+ opposed to being link-time loaded by Cygwin apps) from a non
+ cygwin app via LoadLibrary. */
+static void
+dll_crt0_1 ()
+{
+ /* According to onno@stack.urc.tue.nl, the exception handler record must
+ be on the stack. */
+ /* FIXME: Verify forked children get their exception handler set up ok. */
+ exception_list cygwin_except_entry;
+
+ /* Initialize SIGSEGV handling, etc. */
+ init_exceptions (&cygwin_except_entry);
+
+ do_global_ctors (&__CTOR_LIST__, 1);
+
+ /* Set the os_being_run global. */
+ wincap.init ();
+ check_sanity_and_sync (user_data);
+
+ /* Nasty static stuff needed by newlib -- point to a local copy of
+ the reent stuff.
+ Note: this MUST be done here (before the forkee code) as the
+ fork copy code doesn't copy the data in libccrt0.cc (that's why we
+ pass in the per_process struct into the .dll from libccrt0). */
+
+ _impure_ptr = &reent_data;
+
+ user_data->resourcelocks->Init ();
+ user_data->threadinterface->Init (user_data->forkee);
+
+ threadname_init ();
+ debug_init ();
+ (void) getpagesize (); /* initialize page size constant */
+
+ regthread ("main", GetCurrentThreadId ());
+ mainthread.init ("mainthread"); // For use in determining if signals
+ // should be blocked.
+
+ int envc = 0;
+ char **envp = NULL;
+
+ if (child_proc_info)
+ {
+ switch (child_proc_info->type)
+ {
+ case PROC_FORK:
+ case PROC_FORK1:
+ cygheap_fixup_in_child (child_proc_info, 0);
+ alloc_stack (fork_info);
+ set_myself (mypid);
+ ProtectHandle (child_proc_info->forker_finished);
+ break;
+ case PROC_SPAWN:
+ CloseHandle (spawn_info->hexec_proc);
+ goto around;
+ case PROC_EXEC:
+ hexec_proc = spawn_info->hexec_proc;
+ around:
+ HANDLE h;
+ cygheap_fixup_in_child (spawn_info, 1);
+ if (!spawn_info->moreinfo->myself_pinfo ||
+ !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
+ hMainProc, &h, 0, 0,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+ h = NULL;
+ set_myself (mypid, h);
+ myself->uid = spawn_info->moreinfo->uid;
+ __argc = spawn_info->moreinfo->argc;
+ __argv = spawn_info->moreinfo->argv;
+ envp = spawn_info->moreinfo->envp;
+ envc = spawn_info->moreinfo->envc;
+ cygheap->fdtab.fixup_after_exec (spawn_info->parent);
+ signal_fixup_after_exec (child_proc_info->type == PROC_SPAWN);
+ CloseHandle (spawn_info->parent);
+ if (spawn_info->moreinfo->old_title)
+ {
+ old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
+ cfree (spawn_info->moreinfo->old_title);
+ }
+ if (child_proc_info->subproc_ready)
+ ProtectHandle (child_proc_info->subproc_ready);
+ if (myself->uid == USHRT_MAX)
+ cygheap->user.set_sid (NULL);
+ break;
+ }
+ }
+ ProtectHandle (hMainProc);
+ ProtectHandle (hMainThread);
+
+ /* Initialize the cygwin subsystem if this is the first process,
+ or attach to shared data structures if it's already running. */
+ memory_init ();
+ cygheap->fdtab.vfork_child_fixup ();
+
+ (void) SetErrorMode (SEM_FAILCRITICALERRORS);
+
+ /* Initialize events. */
+ events_init ();
+
+ cygheap->cwd.init ();
+ main_vfork = vfork_storage.create ();
+
+ cygbench ("pre-forkee");
+ if (user_data->forkee)
+ {
+ /* If we've played with the stack, stacksize != 0. That means that
+ fork() was invoked from other than the main thread. Make sure that
+ frame pointer is referencing the new stack so that the OS knows what
+ to do when it needs to increase the size of the stack.
+
+ NOTE: Don't do anything that involves the stack until you've completed
+ this step. */
+ if (fork_info->stacksize)
+ {
+ asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom));
+ asm ("movl %0,%%fs:8" : : "r" (fork_info->stacktop));
+ }
+
+ longjmp (fork_info->jmp, fork_info->cygpid);
+ }
+
+#ifdef DEBUGGING
+ {
+ extern void fork_init ();
+ fork_init ();
+ }
+#endif
+
+ /* Initialize our process table entry. */
+ pinfo_init (envp, envc);
+
+ if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
+ old_title = title_buf;
+
+ /* Allocate cygheap->fdtab */
+ dtable_init ();
+
+/* Initialize uid, gid. */
+ uinfo_init ();
+
+ /* Initialize signal/subprocess handling. */
+ sigproc_init ();
+
+ cygserver_init ();
+
+ /* Connect to tty. */
+ tty_init ();
+
+ if (!__argc)
+ {
+ char *line = GetCommandLineA ();
+ line = strcpy ((char *) alloca (strlen (line) + 1), line);
+
+ if (current_codepage == oem_cp)
+ CharToOemA (line, line);
+
+ /* Scan the command line and build argv. Expand wildcards if not
+ called from another cygwin process. */
+ build_argv (line, __argv, __argc,
+ NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
+
+ /* Convert argv[0] to posix rules if it's currently blatantly
+ win32 style. */
+ if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
+ {
+ char *new_argv0 = (char *) alloca (MAX_PATH);
+ cygwin_conv_to_posix_path (__argv[0], new_argv0);
+ char *p = strchr (new_argv0, '\0') - 4;
+ if (p > new_argv0 && strcasematch (p, ".exe"))
+ *p = '\0';
+ __argv[0] = new_argv0;
+ }
+ }
+
+ if (user_data->premain[0])
+ for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
+ user_data->premain[i] (__argc, __argv, user_data);
+
+ /* Set up standard fds in file descriptor table. */
+ stdio_init ();
+
+ /* Set up __progname for getopt error call. */
+ __progname = __argv[0];
+
+ /* Set new console title if appropriate. */
+
+ if (display_title && !dynamically_loaded)
+ {
+ char *cp = __progname;
+ if (strip_title_path)
+ for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
+ if (isdirsep (*ptr))
+ cp = ptr + 1;
+ set_console_title (cp);
+ }
+
+ cygwin_finished_initializing = 1;
+ /* Call init of loaded dlls. */
+ dlls.init ();
+
+ /* Execute any specified "premain" functions */
+ if (user_data->premain[PREMAIN_LEN / 2])
+ for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
+ user_data->premain[i] (__argc, __argv, user_data);
+
+ debug_printf ("user_data->main %p", user_data->main);
+
+ if (dynamically_loaded)
+ {
+ set_errno (0);
+ return;
+ }
+
+ /* Disable case-insensitive globbing */
+ ignore_case_with_glob = FALSE;
+
+ /* Flush signals and ensure that signal thread is up and running. Can't
+ do this for noncygwin case since the signal thread is blocked due to
+ LoadLibrary serialization. */
+ sig_send (NULL, __SIGFLUSH);
+
+ set_errno (0);
+
+ MALLOC_CHECK;
+ cygbench (__progname);
+ if (user_data->main)
+ exit (user_data->main (__argc, __argv, *user_data->envptr));
+}
+
+/* Wrap the real one, otherwise gdb gets confused about
+ two symbols with the same name, but different addresses.
+
+ UPTR is a pointer to global data that lives on the libc side of the
+ line [if one distinguishes the application from the dll]. */
+
+extern "C" void __stdcall
+_dll_crt0 ()
+{
+ char envbuf[8];
+#ifdef DEBUGGING
+ if (GetEnvironmentVariable ("CYGWIN_SLEEP", envbuf, sizeof (envbuf) - 1))
+ {
+ console_printf ("Sleeping %d, pid %u\n", atoi (envbuf), GetCurrentProcessId ());
+ Sleep (atoi (envbuf));
+ }
+#endif
+
+ if (GetEnvironmentVariable ("CYGWIN_TESTING", envbuf, sizeof (envbuf) - 1))
+ _cygwin_testing = 1;
+
+ char zeros[sizeof (fork_info->zero)] = {0};
+#ifdef DEBUGGING
+ strace.microseconds ();
+#endif
+
+ main_environ = user_data->envptr;
+ *main_environ = NULL;
+
+ set_console_handler ();
+ if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
+ GetCurrentProcess (), &hMainProc, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ hMainProc = GetCurrentProcess ();
+
+ DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
+ &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
+
+ GetStartupInfo (&si);
+ if (si.cbReserved2 >= EXEC_MAGIC_SIZE &&
+ memcmp (fork_info->zero, zeros, sizeof (zeros)) == 0)
+ {
+ switch (fork_info->type)
+ {
+ case PROC_FORK:
+ case PROC_FORK1:
+ user_data->forkee = fork_info->cygpid;
+ case PROC_SPAWN:
+ if (fork_info->pppid_handle)
+ CloseHandle (fork_info->pppid_handle);
+ case PROC_EXEC:
+ {
+ child_proc_info = fork_info;
+ cygwin_mount_h = child_proc_info->mount_h;
+ mypid = child_proc_info->cygpid;
+ break;
+ }
+ default:
+ if (_cygwin_testing)
+ fork_info = NULL;
+ else if ((fork_info->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
+ api_fatal ("conflicting versions of cygwin1.dll detected. Use only the most recent version.\n");
+ break;
+ }
+ }
+ dll_crt0_1 ();
+}
+
+void
+dll_crt0 (per_process *uptr)
+{
+ /* Set the local copy of the pointer into the user space. */
+ if (uptr && uptr != user_data)
+ {
+ memcpy (user_data, uptr, per_process_overwrite);
+ *(user_data->impure_ptr_ptr) = &reent_data;
+ }
+ _dll_crt0 ();
+}
+
+/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
+extern "C" void
+cygwin_dll_init ()
+{
+ static char **envp;
+ static int _fmode;
+
+ if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
+ GetCurrentProcess (), &hMainProc, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ hMainProc = GetCurrentProcess ();
+
+ DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
+ &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ user_data->magic_biscuit = sizeof (per_process);
+
+ user_data->envptr = &envp;
+ user_data->fmode_ptr = &_fmode;
+
+ dll_crt0_1 ();
+}
+
+extern "C" void
+__main (void)
+{
+ do_global_ctors (user_data->ctors, FALSE);
+}
+
+enum
+ {
+ ES_SIGNAL = 1,
+ ES_CLOSEALL = 2,
+ ES_SIGPROCTERMINATE = 3
+ };
+
+extern "C" void __stdcall
+do_exit (int status)
+{
+ UINT n = (UINT) status;
+ static int NO_COPY exit_state = 0;
+
+ syscall_printf ("do_exit (%d)", n);
+
+ vfork_save *vf = vfork_storage.val ();
+ if (vf != NULL && vf->pid < 0)
+ {
+ vf->pid = status < 0 ? status : -status;
+ longjmp (vf->j, 1);
+ }
+
+ if (exit_state < ES_SIGNAL)
+ {
+ exit_state = ES_SIGNAL;
+ if (!(n & EXIT_REPARENTING))
+ {
+ signal (SIGCHLD, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGQUIT, SIG_IGN);
+ }
+ }
+
+ if (exit_state < ES_CLOSEALL)
+ {
+ exit_state = ES_CLOSEALL;
+ close_all_files ();
+ }
+
+ if (exit_state < ES_SIGPROCTERMINATE)
+ {
+ exit_state = ES_SIGPROCTERMINATE;
+ sigproc_terminate ();
+ }
+
+ if (n & EXIT_REPARENTING)
+ n &= ~EXIT_REPARENTING;
+ else
+ {
+ myself->stopsig = 0;
+
+ /* restore console title */
+ if (old_title && display_title)
+ set_console_title (old_title);
+
+ /* Kill orphaned children on group leader exit */
+ if (myself->has_pgid_children && myself->pid == myself->pgid)
+ {
+ sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
+ myself->pid, myself->pgid);
+ kill_pgrp (myself->pgid, -SIGHUP);
+ }
+
+ /* Kill the foreground process group on session leader exit */
+ if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
+ {
+ tty *tp = cygwin_shared->tty[myself->ctty];
+ sigproc_printf ("%d == sid %d, send SIGHUP to children",
+ myself->pid, myself->sid);
+
+ /* CGF FIXME: This can't be right. */
+ if (tp->getsid () == myself->sid)
+ kill_pgrp (tp->getpgid (), SIGHUP);
+ }
+
+ tty_terminate ();
+ }
+
+ window_terminate ();
+ events_terminate ();
+ shared_terminate ();
+
+ minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
+ myself->exit (n);
+}
+
+extern "C" void
+_exit (int n)
+{
+ do_exit ((DWORD) n & 0xffff);
+}
+
+extern "C" void
+__api_fatal (const char *fmt, ...)
+{
+ char buf[4096];
+ va_list ap;
+
+ va_start (ap, fmt);
+ __small_vsprintf (buf, fmt, ap);
+ va_end (ap);
+ strcat (buf, "\n");
+ int len = strlen (buf);
+ DWORD done;
+ (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
+
+ /* Make sure that the message shows up on the screen, too, since this is
+ a serious error. */
+ if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
+ {
+ HANDLE h = CreateFileA ("CONOUT$", GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_WRITE, &sec_none,
+ OPEN_EXISTING, 0, 0);
+ if (h)
+ (void) WriteFile (h, buf, len, &done, 0);
+ }
+
+ /* We are going down without mercy. Make sure we reset
+ our process_state. */
+ sigproc_terminate ();
+#ifdef DEBUGGING
+ (void) try_to_debug ();
+#endif
+ myself->exit (1);
+}
+
+#ifdef DEBUGGING
+void __stdcall
+cygbench (const char *s)
+{
+ char buf[1024];
+ if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
+ small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
+}
+#endif
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
new file mode 100644
index 00000000000..72c80c392cd
--- /dev/null
+++ b/winsup/cygwin/fhandler.h
@@ -0,0 +1,1091 @@
+/* fhandler.h
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 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 _FHANDLER_H_
+#define _FHANDLER_H_
+
+#include <sys/ioctl.h>
+
+/* Classes
+
+ Code is located in fhandler.cc unless another file name is given.
+
+ fhandler_base normal I/O
+
+ fhandler_disk_file
+ fhandler_serial Adds vmin and vtime.
+ fhandler_dev_null Not really I/O
+ fhandler_dev_zero Faked
+
+ fhandler_dev_raw (fhandler_raw.cc)
+ fhandler_dev_floppy (fhandler_floppy.cc)
+ fhandler_dev_tape (fhandler_tape.cc)
+
+ fhandler_pipe
+ fhandler_socket (fhandler_socket.cc)
+
+ fhandler_tty_slave (tty.cc)
+ fhandler_pty_master (tty.cc)
+ fhandler_tty_master (tty.cc)
+
+ fhandler_console Out with ansi control. (console.cc)
+
+ fhandler_windows Windows messages I/O (fhandler_windows.cc)
+
+ fhandler_dev_random /dev/[u]random implementation (fhandler_random.cc)
+
+ fhandler_dev_mem /dev/mem implementation (fhandler_mem.cc)
+
+ fhandler_dev_clipboard /dev/clipboard implementation (fhandler_clipboard.cc)
+
+ fhandler_proc Interesting possibility, not implemented yet
+*/
+
+enum
+{
+ FH_RBINARY = 0x00001000, /* binary read mode */
+ FH_WBINARY = 0x00002000, /* binary write mode */
+ FH_CLOEXEC = 0x00004000, /* close-on-exec */
+ FH_RBINSET = 0x00008000, /* binary read mode has been explicitly set */
+ 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_SYMLINK = 0x00100000, /* is a symlink */
+ FH_EXECABL = 0x00200000, /* file looked like it would run:
+ * ends in .exe or .bat or begins with #! */
+ FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that
+ * _write should check if we've moved beyond
+ * EOF, zero filling if so. */
+ FH_NOFRNAME = 0x00800000, /* Set if shouldn't free unix_path_name and
+ windows_path_name_ on destruction. */
+ FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */
+ FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */
+ FH_LOCAL = 0x04000000, /* File is unix domain socket */
+ FH_SHUTRD = 0x08000000, /* Socket saw a SHUT_RD */
+ FH_SHUTWR = 0x10000000, /* Socket saw a SHUT_WR */
+ FH_ISREMOTE = 0x10000000, /* File is on a remote drive */
+ FH_DCEXEC = 0x20000000, /* Don't care if this is executable */
+ FH_HASACLS = 0x40000000, /* True if fs of file has ACLS */
+ FH_QUERYOPEN = 0x80000000, /* open file without requesting either read
+ or write access */
+
+ /* Device flags */
+
+ /* Slow devices */
+ FH_CONSOLE = 0x00000001, /* is a console */
+ FH_CONIN = 0x00000002, /* console input */
+ FH_CONOUT = 0x00000003, /* console output */
+ FH_TTYM = 0x00000004, /* is a tty master */
+ FH_TTYS = 0x00000005, /* is a tty slave */
+ FH_PTYM = 0x00000006, /* is a pty master */
+ FH_SERIAL = 0x00000007, /* is a serial port */
+ FH_PIPE = 0x00000008, /* is a pipe */
+ FH_PIPER = 0x00000009, /* read end of a pipe */
+ FH_PIPEW = 0x0000000a, /* write end of a pipe */
+ FH_SOCKET = 0x0000000b, /* is a socket */
+ FH_WINDOWS = 0x0000000c, /* is a window */
+ FH_SLOW = 0x00000010, /* "slow" device if below this */
+
+ /* Fast devices */
+ FH_DISK = 0x00000010, /* is a disk */
+ FH_FLOPPY = 0x00000011, /* is a floppy */
+ FH_TAPE = 0x00000012, /* is a tape */
+ FH_NULL = 0x00000013, /* is the null device */
+ FH_ZERO = 0x00000014, /* is the zero device */
+ FH_RANDOM = 0x00000015, /* is a random device */
+ FH_MEM = 0x00000016, /* is a mem device */
+ FH_CLIPBOARD = 0x00000017, /* is a clipbaord device */
+ FH_OSS_DSP = 0x00000018, /* is a dsp audio device */
+
+ FH_NDEV = 0x00000019, /* Maximum number of devices */
+ FH_DEVMASK = 0x00000fff, /* devices live here */
+ FH_BAD = 0xffffffff
+};
+
+#define FHDEVN(n) ((n) & FH_DEVMASK)
+#define FHISSETF(x) __ISSETF (this, x, FH)
+#define FHSETF(x) __SETF (this, x, FH)
+#define FHCLEARF(x) __CLEARF (this, x, FH)
+#define FHCONDSETF(n, x) __CONDSETF(n, this, x, FH)
+
+#define FHSTATOFF 0
+
+/* fcntl flags used only internaly. */
+#define O_NOSYMLINK 0x080000
+#define O_DIROPEN 0x100000
+
+/* newlib used to define O_NDELAY differently from O_NONBLOCK. Now it
+ properly defines both to be the same. Unfortunately, we have to
+ behave properly the old version, too, to accomodate older executables. */
+#define OLD_O_NDELAY (CYGWIN_VERSION_CHECK_FOR_OLD_O_NONBLOCK ? 4 : 0)
+
+/* Care for the old O_NDELAY flag. If one of the flags is set,
+ both flags are set. */
+#define O_NONBLOCK_MASK (O_NONBLOCK | OLD_O_NDELAY)
+
+extern const char *windows_device_names[];
+extern struct __cygwin_perfile *perfile_table;
+#define __fmode (*(user_data->fmode_ptr))
+
+class select_record;
+class path_conv;
+class fhandler_disk_file;
+
+enum bg_check_types
+{
+ bg_error = -1,
+ bg_eof = 0,
+ bg_ok = 1,
+ bg_signalled = 2
+};
+
+enum executable_states
+{
+ is_executable,
+ not_executable,
+ dont_care_if_executable,
+ dont_know_if_executable
+};
+
+class fhandler_base
+{
+protected:
+ DWORD status;
+public:
+ int cb;
+private:
+ int access;
+ HANDLE io_handle;
+
+ unsigned long namehash; /* hashed filename, used as inode num */
+
+protected:
+ /* Full unix path name of this file */
+ /* File open flags from open () and fcntl () calls */
+ int openflags;
+
+ char *rabuf; /* used for crlf conversion in text files */
+ size_t ralen;
+ size_t raixget;
+ size_t raixput;
+ size_t rabuflen;
+
+ char *unix_path_name;
+ char *win32_path_name;
+ DWORD open_status;
+
+public:
+ void set_name (const char * unix_path, const char * win32_path = NULL,
+ int unit = 0);
+
+ virtual fhandler_base& operator =(fhandler_base &x);
+ fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
+ virtual ~fhandler_base ();
+
+ /* Non-virtual simple accessor functions. */
+ void set_io_handle (HANDLE x) { io_handle = x; }
+
+ void set_cb (size_t size) { cb = size; }
+ DWORD get_device () { return status & FH_DEVMASK; }
+ virtual int get_unit () { return 0; }
+ virtual BOOL is_slow () { return get_device () < FH_SLOW; }
+
+ int get_access () { return access; }
+ void set_access (int x) { access = x; }
+
+ int get_async () { return FHISSETF (ASYNC); }
+ void set_async (int x) { FHCONDSETF (x, ASYNC); }
+
+ int get_flags () { return openflags; }
+ void set_flags (int x) { openflags = x; }
+
+ int is_nonblocking ();
+ void set_nonblocking (int yes);
+
+ int get_w_binary () { return FHISSETF (WBINARY); }
+ int get_r_binary () { return FHISSETF (RBINARY); }
+
+ int get_w_binset () { return FHISSETF (WBINSET); }
+ int get_r_binset () { return FHISSETF (RBINSET); }
+
+ void set_w_binary (int b) { FHCONDSETF (b, WBINARY); FHSETF (WBINSET); }
+ void set_r_binary (int b) { FHCONDSETF (b, RBINARY); FHSETF (RBINSET); }
+ void clear_w_binary () {FHCLEARF (WBINARY); FHCLEARF (WBINSET); }
+ void clear_r_binary () {FHCLEARF (RBINARY); FHCLEARF (RBINSET); }
+ void set_open_status () {open_status = status;}
+ DWORD get_open_status () {return open_status;}
+ void reset_to_open_binmode ()
+ {
+ status = status & ~(FH_WBINARY | FH_WBINSET | FH_RBINARY | FH_RBINSET);
+ status = status | ((FH_WBINARY | FH_WBINSET | FH_RBINARY | FH_RBINSET)
+ & open_status);
+ }
+
+ int get_default_fmode (int flags);
+
+ int get_r_no_interrupt () { return FHISSETF (NOEINTR); }
+ void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); }
+
+ int get_close_on_exec () { return FHISSETF (CLOEXEC); }
+ int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); }
+
+ LPSECURITY_ATTRIBUTES get_inheritance (bool all = 0)
+ {
+ if (all)
+ return get_close_on_exec () ? &sec_all_nih : &sec_all;
+ else
+ return get_close_on_exec () ? &sec_none_nih : &sec_none;
+ }
+
+ void set_check_win95_lseek_bug (int b = 1) { FHCONDSETF (b, W95LSBUG); }
+ int get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); }
+
+ int get_need_fork_fixup () { return FHISSETF (FFIXUP); }
+ void set_need_fork_fixup () { FHSETF (FFIXUP); }
+
+ virtual void set_close_on_exec (int val);
+
+ virtual void fixup_before_fork_exec (DWORD) {}
+ virtual void fixup_after_fork (HANDLE);
+ virtual void fixup_after_exec (HANDLE) {}
+
+ int get_symlink_p () { return FHISSETF (SYMLINK); }
+ void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); }
+ void set_symlink_p () { FHSETF (SYMLINK); }
+
+ int get_socket_p () { return FHISSETF (LOCAL); }
+ void set_socket_p (int val) { FHCONDSETF (val, LOCAL); }
+ void set_socket_p () { FHSETF (LOCAL); }
+
+ int get_execable_p () { return FHISSETF (EXECABL); }
+ void set_execable_p (executable_states val)
+ {
+ FHCONDSETF (val == is_executable, EXECABL);
+ FHCONDSETF (val == dont_care_if_executable, DCEXEC);
+ }
+ void set_execable_p () { FHSETF (EXECABL); }
+ int dont_care_if_execable () { return FHISSETF (DCEXEC); }
+
+ int get_append_p () { return FHISSETF (APPEND); }
+ void set_append_p (int val) { FHCONDSETF (val, APPEND); }
+ void set_append_p () { FHSETF (APPEND); }
+
+ int get_query_open () { return FHISSETF (QUERYOPEN); }
+ void set_query_open (int val) { FHCONDSETF (val, QUERYOPEN); }
+
+ int get_readahead_valid () { return raixget < ralen; }
+ int puts_readahead (const char *s, size_t len = (size_t) -1);
+ int put_readahead (char value);
+
+ int get_readahead ();
+ int peek_readahead (int queryput = 0);
+
+ int eat_readahead (int n);
+
+ void set_readahead_valid (int val, int ch = -1);
+
+ int get_readahead_into_buffer (char *buf, size_t buflen);
+
+ int has_acls () { return FHISSETF (HASACLS); }
+ void set_has_acls (int val) { FHCONDSETF (val, HASACLS); }
+
+ int isremote () { return FHISSETF (ISREMOTE); }
+ void set_isremote (int val) { FHCONDSETF (val, ISREMOTE); }
+
+ int no_free_names () { return FHISSETF (NOFRNAME); }
+ void set_no_free_names (int val) { FHCONDSETF (val, NOFRNAME); }
+ void set_no_free_names () { FHSETF (NOFRNAME); }
+
+ const char *get_name () { return unix_path_name; }
+ const char *get_win32_name () { return win32_path_name; }
+ unsigned long get_namehash () { return namehash; }
+
+ virtual void hclose (HANDLE h) {CloseHandle (h);}
+ virtual void set_inheritance (HANDLE &h, int not_inheriting);
+
+ /* fixup fd possibly non-inherited handles after fork */
+ void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
+
+ /* Potentially overridden virtual functions. */
+ virtual int open (const char *, int flags, mode_t mode = 0)
+ {
+ return open (flags, mode);
+ }
+ virtual int open (path_conv& real_path, int flags, mode_t mode);
+ virtual int open (int flags, mode_t mode = 0);
+ virtual int close ();
+ virtual int fstat (struct stat *buf) { return stat_dev (get_device (), get_unit (), get_namehash (), buf); }
+ virtual int ioctl (unsigned int cmd, void *);
+ virtual int fcntl (int cmd, void *);
+ virtual char const * ttyname () { return get_name(); }
+ virtual int read (void *ptr, size_t len);
+ virtual int write (const void *ptr, size_t len);
+ virtual off_t lseek (off_t offset, int whence);
+ virtual int lock (int, struct flock *);
+ virtual void dump ();
+ virtual int dup (fhandler_base *child);
+
+ virtual HANDLE mmap (caddr_t *addr, size_t len, DWORD access,
+ int flags, off_t off);
+ virtual int munmap (HANDLE h, caddr_t addr, size_t len);
+ virtual int msync (HANDLE h, caddr_t addr, size_t len, int flags);
+ virtual BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,
+ DWORD size, void *address);
+
+ void *operator new (size_t, void *p) {return p;}
+
+ virtual void init (HANDLE, DWORD, mode_t);
+
+ virtual int tcflush (int);
+ virtual int tcsendbreak (int);
+ virtual int tcdrain ();
+ virtual int tcflow (int);
+ virtual int tcsetattr (int a, const struct termios *t);
+ virtual int tcgetattr (struct termios *t);
+ virtual int tcsetpgrp (const pid_t pid);
+ virtual int tcgetpgrp ();
+ virtual int is_tty () { return 0; }
+ virtual BOOL is_device () { return TRUE; }
+ virtual char *ptsname () { return NULL;}
+ virtual class fhandler_socket *is_socket () { return 0; }
+ virtual class fhandler_console *is_console () { return 0; }
+ virtual int is_windows () {return 0; }
+
+ virtual int raw_read (void *ptr, size_t ulen);
+ virtual int raw_write (const void *ptr, size_t ulen);
+
+ /* Virtual accessor functions to hide the fact
+ that some fd's have two handles. */
+ virtual HANDLE& get_handle () { return io_handle; }
+ virtual HANDLE& get_io_handle () { return io_handle; }
+ virtual HANDLE& get_output_handle () { return io_handle; }
+ virtual bool hit_eof () {return FALSE;}
+ virtual select_record *select_read (select_record *s);
+ virtual select_record *select_write (select_record *s);
+ virtual select_record *select_except (select_record *s);
+ virtual int ready_for_read (int fd, DWORD howlong, int ignra);
+ virtual const char * get_native_name ()
+ {
+ return windows_device_names[FHDEVN (status)];
+ }
+ virtual bg_check_types bg_check (int) {return bg_ok;}
+ void clear_readahead ()
+ {
+ raixput = raixget = ralen = rabuflen = 0;
+ rabuf = NULL;
+ }
+ void operator delete (void *);
+};
+
+class fhandler_socket: public fhandler_base
+{
+private:
+ int addr_family;
+ int connect_secret [4];
+ HANDLE secret_event;
+ struct _WSAPROTOCOL_INFOA *prot_info_ptr;
+
+public:
+ fhandler_socket (const char *name = 0);
+ ~fhandler_socket ();
+ int get_socket () { return (int) get_handle(); }
+ fhandler_socket * is_socket () { return this; }
+
+ bool saw_shutdown_read () const {return FHISSETF (SHUTRD);}
+ bool saw_shutdown_write () const {return FHISSETF (SHUTWR);}
+
+ void set_shutdown_read () {FHSETF (SHUTRD);}
+ void set_shutdown_write () {FHSETF (SHUTWR);}
+
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ int ioctl (unsigned int cmd, void *);
+ int fcntl (int cmd, void *);
+ off_t lseek (off_t, int) { return 0; }
+ int close ();
+ void hclose (HANDLE) {close ();}
+ int dup (fhandler_base *child);
+
+ void set_close_on_exec (int val);
+ virtual void fixup_before_fork_exec (DWORD);
+ void fixup_after_fork (HANDLE);
+ void fixup_after_exec (HANDLE);
+
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+ int get_addr_family () {return addr_family;}
+ void set_addr_family (int af) {addr_family = af;}
+ void set_connect_secret ();
+ void get_connect_secret (char*);
+ HANDLE create_secret_event (int *secret = NULL);
+ int check_peer_secret_event (struct sockaddr_in *peer, int *secret = NULL);
+ void signal_secret_event ();
+ void close_secret_event ();
+};
+
+class fhandler_pipe: public fhandler_base
+{
+ HANDLE guard;
+ HANDLE writepipe_exists;
+ DWORD orig_pid;
+ unsigned id;
+public:
+ fhandler_pipe (const char *name = 0, DWORD devtype = FH_PIPE);
+ off_t lseek (off_t offset, int whence);
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+ void set_close_on_exec (int val);
+ int read (void *ptr, size_t len);
+ int close ();
+ void create_guard (SECURITY_ATTRIBUTES *sa) {guard = CreateMutex (sa, FALSE, NULL);}
+ int dup (fhandler_base *child);
+ bool hit_eof ();
+ friend int make_pipe (int fildes[2], unsigned int psize, int mode);
+};
+
+class fhandler_dev_raw: public fhandler_base
+{
+protected:
+ char *devbuf;
+ size_t devbufsiz;
+ size_t devbufstart;
+ size_t devbufend;
+ int eom_detected : 1;
+ int eof_detected : 1;
+ int lastblk_to_read : 1;
+ int is_writing : 1;
+ int has_written : 1;
+ int varblkop : 1;
+ int unit;
+
+ virtual void clear (void);
+ virtual int writebuf (void);
+
+ /* returns not null, if `win_error' determines an end of media condition */
+ virtual int is_eom(int win_error) = 0;
+ /* returns not null, if `win_error' determines an end of file condition */
+ virtual int is_eof(int win_error) = 0;
+
+ fhandler_dev_raw (DWORD dev, const char *name, int unit);
+
+public:
+ ~fhandler_dev_raw (void);
+
+ int open (const char *path, int flags, mode_t mode = 0);
+ int close (void);
+
+ int raw_read (void *ptr, size_t ulen);
+ int raw_write (const void *ptr, size_t ulen);
+
+ int fstat (struct stat *buf);
+
+ int dup (fhandler_base *child);
+
+ int ioctl (unsigned int cmd, void *buf);
+
+ void fixup_after_fork (HANDLE);
+ void fixup_after_exec (HANDLE);
+};
+
+class fhandler_dev_floppy: public fhandler_dev_raw
+{
+protected:
+ virtual int is_eom (int win_error);
+ virtual int is_eof (int win_error);
+
+public:
+ fhandler_dev_floppy (const char *name, int unit);
+
+ virtual int open (const char *path, int flags, mode_t mode = 0);
+ virtual int close (void);
+
+ virtual off_t lseek (off_t offset, int whence);
+
+ virtual int ioctl (unsigned int cmd, void *buf);
+};
+
+class fhandler_dev_tape: public fhandler_dev_raw
+{
+ int norewind;
+ int lasterr;
+
+protected:
+ virtual void clear (void);
+
+ virtual int is_eom (int win_error);
+ virtual int is_eof (int win_error);
+
+public:
+ fhandler_dev_tape (const char *name, int unit);
+
+ virtual int open (const char *path, int flags, mode_t mode = 0);
+ virtual int close (void);
+
+ virtual off_t lseek (off_t offset, int whence);
+
+ virtual int fstat (struct stat *buf);
+
+ virtual int dup (fhandler_base *child);
+
+ virtual int ioctl (unsigned int cmd, void *buf);
+
+private:
+ int tape_write_marks (int marktype, DWORD len);
+ int tape_get_pos (unsigned long *ret);
+ int tape_set_pos (int mode, long count, BOOLEAN sfm_func = FALSE);
+ int tape_erase (int mode);
+ int tape_prepare (int action);
+ BOOLEAN tape_get_feature (DWORD parm);
+ int tape_get_blocksize (long *min, long *def, long *max, long *cur);
+ int tape_set_blocksize (long count);
+ int tape_status (struct mtget *get);
+ int tape_compression (long count);
+};
+
+/* Standard disk file */
+
+class fhandler_disk_file: public fhandler_base
+{
+public:
+ fhandler_disk_file (const char *name);
+
+ int open (const char *path, int flags, mode_t mode = 0);
+ int open (path_conv& real_path, int flags, mode_t mode);
+ int close ();
+ int lock (int, struct flock *);
+ BOOL is_device () { return FALSE; }
+ int fstat (struct stat *buf);
+
+ HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
+ int munmap (HANDLE h, caddr_t addr, size_t len);
+ int msync (HANDLE h, caddr_t addr, size_t len, int flags);
+ BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,
+ DWORD size, void *address);
+};
+
+class fhandler_serial: public fhandler_base
+{
+private:
+ unsigned int vmin_; /* from termios */
+ unsigned int vtime_; /* from termios */
+ pid_t pgrp_;
+
+public:
+ int overlapped_armed;
+ OVERLAPPED io_status;
+
+ /* Constructor */
+ fhandler_serial (const char *name, DWORD devtype = FH_SERIAL, int unit = 0);
+
+ int open (const char *path, int flags, mode_t mode);
+ int close ();
+ void init (HANDLE h, DWORD a, mode_t flags);
+ void overlapped_setup ();
+ int dup (fhandler_base *child);
+ int raw_read (void *ptr, size_t ulen);
+ int raw_write (const void *ptr, size_t ulen);
+ int tcsendbreak (int);
+ int tcdrain ();
+ int tcflow (int);
+ int tcsetattr (int a, const struct termios *t);
+ int tcgetattr (struct termios *t);
+ off_t lseek (off_t, int) { return 0; }
+ int tcflush (int);
+ void dump ();
+ int is_tty () { return 1; }
+ void fixup_after_fork (HANDLE parent);
+ void fixup_after_exec (HANDLE);
+
+ /* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
+ don't use it for permissions checking. fhandler_tty_slave does
+ permission checking on pgrps. */
+ virtual int tcgetpgrp () { return pgrp_; }
+ virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+};
+
+#define acquire_output_mutex(ms) \
+ __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms);
+
+#define release_output_mutex() \
+ __release_output_mutex (__PRETTY_FUNCTION__, __LINE__);
+
+class tty;
+class tty_min;
+class fhandler_termios: public fhandler_base
+{
+protected:
+ HANDLE output_handle;
+ virtual void doecho (const void *, DWORD) {};
+ virtual int accept_input () {return 1;};
+public:
+ tty_min *tc;
+ fhandler_termios (DWORD dev, const char *name = 0, int unit = 0) :
+ fhandler_base (dev, name, unit)
+ {
+ set_need_fork_fixup ();
+ }
+ HANDLE& get_output_handle () { return output_handle; }
+ int line_edit (const char *rptr, int nread, int always_accept = 0);
+ void set_output_handle (HANDLE h) { output_handle = h; }
+ void tcinit (tty_min *this_tc, int force = FALSE);
+ virtual int is_tty () { return 1; }
+ int tcgetpgrp ();
+ int tcsetpgrp (int pid);
+ bg_check_types bg_check (int sig);
+ virtual DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms) {return 1;}
+ virtual void __release_output_mutex (const char *fn, int ln) {}
+ void fixup_after_fork (HANDLE);
+ void fixup_after_exec (HANDLE parent) { fixup_after_fork (parent); }
+ void echo_erase (int force = 0);
+};
+
+enum ansi_intensity
+{
+ INTENSITY_INVISIBLE,
+ INTENSITY_DIM,
+ INTENSITY_NORMAL,
+ INTENSITY_BOLD
+};
+
+#define normal 1
+#define gotesc 2
+#define gotsquare 3
+#define gotarg1 4
+#define gotrsquare 5
+#define gotcommand 6
+#define gettitle 7
+#define eattitle 8
+#define MAXARGS 10
+
+/* This is a input and output console handle */
+class fhandler_console: public fhandler_termios
+{
+private:
+
+ WORD default_color, underline_color, dim_color;
+
+ /* Used to determine if an input keystroke should be modified with META. */
+ int meta_mask;
+
+/* Output state */
+ int state_;
+ int args_[MAXARGS];
+ int nargs_;
+ unsigned rarg;
+ BOOL saw_question_mark;
+
+ char my_title_buf [TITLESIZE + 1];
+
+ WORD current_win32_attr;
+ ansi_intensity intensity;
+ BOOL underline, blink, reverse;
+ WORD fg, bg;
+
+ /* saved cursor coordinates */
+ int savex, savey;
+
+ /* saved screen */
+ COORD savebufsiz;
+ PCHAR_INFO savebuf;
+
+ struct
+ {
+ short Top, Bottom;
+ } scroll_region;
+ struct
+ {
+ SHORT winTop;
+ SHORT winBottom;
+ COORD dwWinSize;
+ COORD dwBufferSize;
+ COORD dwCursorPosition;
+ WORD wAttributes;
+ } info;
+
+ COORD dwLastCursorPosition;
+ DWORD dwLastButtonState;
+ int nModifiers;
+
+ BOOL insert_mode;
+ BOOL use_mouse;
+ BOOL raw_win32_keyboard_mode;
+
+/* Output calls */
+ void set_default_attr ();
+ WORD get_win32_attr ();
+
+ BOOL fillin_info ();
+ void clear_screen (int, int, int, int);
+ void scroll_screen (int, int, int, int, int, int);
+ void cursor_set (BOOL, int, int);
+ void cursor_get (int *, int *);
+ void cursor_rel (int, int);
+ const unsigned char * write_normal (unsigned const char*, unsigned const char *);
+ void char_command (char);
+ BOOL set_raw_win32_keyboard_mode (BOOL);
+ int output_tcsetattr (int a, const struct termios *t);
+
+/* Input calls */
+ int igncr_enabled ();
+ int input_tcsetattr (int a, const struct termios *t);
+ void set_cursor_maybe ();
+
+public:
+
+ fhandler_console (const char *name);
+
+ fhandler_console* is_console () { return this; }
+
+ int open (const char *path, int flags, mode_t mode = 0);
+
+ int write (const void *ptr, size_t len);
+ void doecho (const void *str, DWORD len) { (void) write (str, len); }
+ int read (void *ptr, size_t len);
+ int close ();
+
+ int tcflush (int);
+ int tcsetattr (int a, const struct termios *t);
+ int tcgetattr (struct termios *t);
+
+ /* Special dup as we must dup two handles */
+ int dup (fhandler_base *child);
+
+ int ioctl (unsigned int cmd, void *);
+ void init (HANDLE, DWORD, mode_t);
+ bool mouse_aware () {return use_mouse;}
+
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+ void fixup_after_exec (HANDLE);
+ void set_close_on_exec (int val);
+ void fixup_after_fork (HANDLE parent);
+ void set_input_state ();
+};
+
+class fhandler_tty_common: public fhandler_termios
+{
+public:
+ fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
+ fhandler_termios (dev, name, unit),
+ ttynum (unit)
+ {
+ // nothing to do
+ }
+ HANDLE output_done_event; // Raised by master when tty's output buffer
+ // written. Write status in tty::write_retval.
+ HANDLE ioctl_request_event; // Raised by slave to perform ioctl() request.
+ // Ioctl() request in tty::cmd/arg.
+ HANDLE ioctl_done_event; // Raised by master on ioctl() completion.
+ // Ioctl() status in tty::ioctl_retval.
+ HANDLE output_mutex, input_mutex;
+ HANDLE input_available_event;
+ HANDLE inuse; // used to indicate that a tty is in use
+
+
+ DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
+ void __release_output_mutex (const char *fn, int ln);
+
+ int ttynum; // Master tty num.
+ virtual int dup (fhandler_base *child);
+
+ tty *get_ttyp () { return (tty *)tc; }
+ int get_unit () { return ttynum; }
+
+ int close ();
+ void set_close_on_exec (int val);
+ void fixup_after_fork (HANDLE parent);
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+};
+
+class fhandler_tty_slave: public fhandler_tty_common
+{
+public:
+ /* Constructor */
+ fhandler_tty_slave (const char *name);
+ fhandler_tty_slave (int, const char *name);
+
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ void init (HANDLE, DWORD, mode_t);
+
+ int tcsetattr (int a, const struct termios *t);
+ int tcgetattr (struct termios *t);
+ int tcflush (int);
+ int ioctl (unsigned int cmd, void *);
+
+ off_t lseek (off_t, int) { return 0; }
+ select_record *select_read (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+
+ int cygserver_attach_tty (HANDLE*, HANDLE*);
+};
+
+class fhandler_pty_master: public fhandler_tty_common
+{
+ int pktmode; // non-zero if pty in a packet mode.
+public:
+ int need_nl; // Next read should start with \n
+
+ /* Constructor */
+ fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
+
+ int process_slave_output (char *buf, size_t len, int pktmode_on);
+ void doecho (const void *str, DWORD len);
+ int accept_input ();
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ int close ();
+
+ int tcsetattr (int a, const struct termios *t);
+ int tcgetattr (struct termios *t);
+ int tcflush (int);
+ int ioctl (unsigned int cmd, void *);
+
+ off_t lseek (off_t, int) { return 0; }
+ char *ptsname ();
+
+ void set_close_on_exec (int val);
+ bool hit_eof ();
+};
+
+class fhandler_tty_master: public fhandler_pty_master
+{
+public:
+ /* Constructor */
+ fhandler_tty_master (const char *name, int unit);
+ fhandler_console *console; // device handler to perform real i/o.
+ HANDLE hThread; // process_output thread handle.
+
+ int init (int);
+ int init_console ();
+ void fixup_after_fork (HANDLE parent);
+ void fixup_after_exec (HANDLE);
+};
+
+class fhandler_dev_null: public fhandler_base
+{
+public:
+ fhandler_dev_null (const char *name);
+
+ void dump ();
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+};
+
+class fhandler_dev_zero: public fhandler_base
+{
+public:
+ fhandler_dev_zero (const char *name);
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ off_t lseek (off_t offset, int whence);
+ int close (void);
+
+ void dump ();
+};
+
+class fhandler_dev_random: public fhandler_base
+{
+protected:
+ int unit;
+ HCRYPTPROV crypt_prov;
+ long pseudo;
+
+ BOOL crypt_gen_random (void *ptr, size_t len);
+ int pseudo_write (const void *ptr, size_t len);
+ int pseudo_read (void *ptr, size_t len);
+
+public:
+ fhandler_dev_random (const char *name, int unit);
+ int get_unit () { return unit; }
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ off_t lseek (off_t offset, int whence);
+ int close (void);
+ int dup (fhandler_base *child);
+
+ void dump ();
+};
+
+class fhandler_dev_mem: public fhandler_base
+{
+protected:
+ int unit;
+ DWORD mem_size;
+ DWORD pos;
+
+public:
+ fhandler_dev_mem (const char *name, int unit);
+ ~fhandler_dev_mem (void);
+
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t ulen);
+ int read (void *ptr, size_t ulen);
+ off_t lseek (off_t offset, int whence);
+ int close (void);
+ int fstat (struct stat *buf);
+ int dup (fhandler_base *child);
+
+ HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, off_t off);
+ int munmap (HANDLE h, caddr_t addr, size_t len);
+ int msync (HANDLE h, caddr_t addr, size_t len, int flags);
+ BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,
+ DWORD size, void *address);
+
+ void dump ();
+} ;
+
+class fhandler_dev_clipboard: public fhandler_base
+{
+public:
+ fhandler_dev_clipboard (const char *name);
+ int is_windows (void) { return 1; }
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ off_t lseek (off_t offset, int whence);
+ int close (void);
+
+ int dup (fhandler_base *child);
+
+ void dump ();
+
+private:
+ off_t pos;
+ void *membuffer;
+ size_t msize;
+ BOOL eof;
+};
+
+class fhandler_windows: public fhandler_base
+{
+private:
+ HWND hWnd_; // the window whose messages are to be retrieved by read() call
+ int method_; // write method (Post or Send)
+public:
+ fhandler_windows (const char *name = 0);
+ int is_windows (void) { return 1; }
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ int ioctl (unsigned int cmd, void *);
+ off_t lseek (off_t, int) { return 0; }
+ int close (void) { return 0; }
+
+ void set_close_on_exec (int val);
+ void fixup_after_fork (HANDLE parent);
+ select_record *select_read (select_record *s);
+ select_record *select_write (select_record *s);
+ select_record *select_except (select_record *s);
+ int ready_for_read (int fd, DWORD howlong, int ignra);
+};
+
+class fhandler_dev_dsp : public fhandler_base
+{
+private:
+ int audioformat_;
+ int audiofreq_;
+ int audiobits_;
+ int audiochannels_;
+ bool setupwav(const char *pData, int nBytes);
+public:
+ fhandler_dev_dsp (const char *name = 0);
+ ~fhandler_dev_dsp();
+
+ int open (const char *path, int flags, mode_t mode = 0);
+ int write (const void *ptr, size_t len);
+ int read (void *ptr, size_t len);
+ int ioctl (unsigned int cmd, void *);
+ off_t lseek (off_t, int);
+ int close (void);
+ int dup (fhandler_base * child);
+ void dump (void);
+ void fixup_after_exec (HANDLE);
+};
+
+#if 0
+/* You can't do this */
+typedef union
+{
+ fhandler_normal normal;
+ fhandler_dev_null dev_null;
+ fhandler bare;
+ fhandler_serial tty;
+} fhandler_union;
+#else
+#define fhandler_union fhandler_console
+#endif
+struct select_record
+{
+ int fd;
+ HANDLE h;
+ fhandler_base *fh;
+ BOOL saw_error;
+ BOOL windows_handle;
+ BOOL read_ready, write_ready, except_ready;
+ BOOL read_selected, write_selected, except_selected;
+ int (*startup) (select_record *me, class select_stuff *stuff);
+ int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds);
+ int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds);
+ void (*cleanup) (select_record *me, class select_stuff *stuff);
+ struct select_record *next;
+
+ select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
+ fh (in_fh), saw_error (0), windows_handle (0),
+ read_ready (0), write_ready (0), except_ready (0),
+ read_selected (0), write_selected (0), except_selected (0),
+ startup (NULL), poll (NULL), verify (NULL), cleanup (NULL),
+ next (NULL) {}
+};
+
+class select_stuff
+{
+public:
+ ~select_stuff ();
+ select_stuff (): always_ready (0), windows_used (0), start (0)
+ {
+ memset (device_specific, 0, sizeof (device_specific));
+ }
+ BOOL always_ready, windows_used;
+ select_record start;
+ void *device_specific[FH_NDEV];
+
+ int test_and_set (int i, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds);
+ int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
+ int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
+ void cleanup ();
+};
+
+int __stdcall set_console_state_for_spawn ();
+
+#endif /* _FHANDLER_H_ */
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
new file mode 100644
index 00000000000..8a2abb77a42
--- /dev/null
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -0,0 +1,1254 @@
+/* fhandler_tty.cc
+
+ Copyright 1997, 1998, 2000, 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. */
+
+#include "winsup.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "cygheap.h"
+#include "shared_info.h"
+#include <sys/socket.h>
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+
+/* Tty master stuff */
+
+fhandler_tty_master NO_COPY *tty_master;
+
+static DWORD WINAPI process_input (void *); // Input queue thread
+static DWORD WINAPI process_output (void *); // Output queue thread
+static DWORD WINAPI process_ioctl (void *); // Ioctl requests thread
+
+fhandler_tty_master::fhandler_tty_master (const char *name, int unit) :
+ fhandler_pty_master (name, FH_TTYM, unit)
+{
+ set_cb (sizeof *this);
+ console = NULL;
+ hThread = NULL;
+}
+
+int
+fhandler_tty_master::init (int ntty)
+{
+ HANDLE h;
+ termios_printf ("Creating master for tty%d", ntty);
+
+ if (init_console ())
+ {
+ termios_printf ("can't create fhandler");
+ return -1;
+ }
+
+ termios ti;
+ memset (&ti, 0, sizeof (ti));
+ console->tcsetattr (0, &ti);
+
+ ttynum = ntty;
+
+ cygwin_shared->tty[ttynum]->common_init (this);
+
+ inuse = get_ttyp ()->create_inuse (TTY_MASTER_ALIVE);
+
+ h = makethread (process_input, NULL, 0, "ttyin");
+ if (h == NULL)
+ {
+ termios_printf ("can't create input thread");
+ return -1;
+ }
+ else
+ {
+ SetThreadPriority (h, THREAD_PRIORITY_HIGHEST);
+ CloseHandle (h);
+ }
+
+ h = makethread (process_ioctl, NULL, 0, "ttyioctl");
+ if (h == NULL)
+ {
+ termios_printf ("can't create ioctl thread");
+ return -1;
+ }
+ else
+ {
+ SetThreadPriority (h, THREAD_PRIORITY_HIGHEST);
+ CloseHandle (h);
+ }
+
+ hThread = makethread (process_output, NULL, 0, "ttyout");
+ if (hThread != NULL)
+ SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
+ else
+ {
+ termios_printf ("can't create output thread");
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef DEBUGGING
+static class mutex_stack
+{
+public:
+ const char *fn;
+ int ln;
+ const char *tname;
+} ostack[100];
+
+static int osi;
+#endif /*DEBUGGING*/
+
+DWORD
+fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
+ DWORD ms)
+{
+ if (strace.active)
+ strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms);
+ DWORD res = WaitForSingleObject (output_mutex, ms);
+ if (res == WAIT_OBJECT_0)
+ {
+#ifndef DEBUGGING
+ if (strace.active)
+ strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: acquired", ln, res);
+#else
+ ostack[osi].fn = fn;
+ ostack[osi].ln = ln;
+ ostack[osi].tname = threadname (0, 0);
+ termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
+ osi++;
+#endif
+ }
+ return res;
+}
+
+void
+fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
+{
+ if (ReleaseMutex (output_mutex))
+ {
+#ifndef DEBUGGING
+ if (strace.active)
+ strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln);
+#else
+ if (osi > 0)
+ osi--;
+ termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
+ termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
+ ostack[osi].ln = -ln;
+#endif
+ }
+}
+
+/* Process tty input. */
+
+void
+fhandler_pty_master::doecho (const void *str, DWORD len)
+{
+ acquire_output_mutex (INFINITE);
+ if (!WriteFile (get_ttyp ()->to_master, str, len, &len, NULL))
+ termios_printf ("Write to %p failed, %E", get_ttyp ()->to_master);
+// WaitForSingleObject (output_done_event, INFINITE);
+ release_output_mutex ();
+}
+
+int
+fhandler_pty_master::accept_input ()
+{
+ DWORD bytes_left, written;
+ DWORD n;
+ DWORD rc;
+ char* p;
+
+ rc = WaitForSingleObject (input_mutex, INFINITE);
+
+ bytes_left = n = eat_readahead (-1);
+ get_ttyp ()->read_retval = 0;
+ p = rabuf;
+
+ if (n != 0)
+ {
+ while (bytes_left > 0)
+ {
+ termios_printf ("about to write %d chars to slave", bytes_left);
+ rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
+ if (!rc)
+ {
+ debug_printf ("error writing to pipe %E");
+ break;
+ }
+ get_ttyp ()->read_retval += written;
+ p += written;
+ bytes_left -= written;
+ if (bytes_left > 0)
+ {
+ debug_printf ("to_slave pipe is full");
+ SetEvent (input_available_event);
+ ReleaseMutex (input_mutex);
+ Sleep (10);
+ rc = WaitForSingleObject (input_mutex, INFINITE);
+ }
+ }
+ }
+ else
+ termios_printf ("sending EOF to slave");
+ SetEvent (input_available_event);
+ ReleaseMutex (input_mutex);
+ return get_ttyp ()->read_retval;
+}
+
+static DWORD WINAPI
+process_input (void *)
+{
+ char rawbuf[INP_BUFFER_SIZE];
+
+ while (1)
+ {
+ int nraw = tty_master->console->read ((void *) rawbuf,
+ (size_t) INP_BUFFER_SIZE);
+ (void) tty_master->line_edit (rawbuf, nraw);
+ }
+}
+
+bool
+fhandler_pty_master::hit_eof ()
+{
+ if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
+ {
+ /* We have the only remaining open handle to this pty, and
+ the slave pty has been opened at least once. We treat
+ this as EOF. */
+ termios_printf ("all other handles closed");
+ return 1;
+ }
+ return 0;
+}
+
+/* Process tty output requests */
+
+int
+fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
+{
+ size_t rlen;
+ char outbuf[OUT_BUFFER_SIZE + 1];
+ DWORD n;
+ int column = 0;
+ int rc = 0;
+
+ if (len == 0)
+ goto out;
+
+ if (need_nl)
+ {
+ /* We need to return a left over \n character, resulting from
+ \r\n conversion. Note that we already checked for FLUSHO and
+ output_stopped at the time that we read the character, so we
+ don't check again here. */
+ buf[0] = '\n';
+ need_nl = 0;
+ rc = 1;
+ goto out;
+ }
+
+
+ for (;;)
+ {
+ /* Set RLEN to the number of bytes to read from the pipe. */
+ rlen = len;
+ if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
+ {
+ /* We are going to expand \n to \r\n, so don't read more than
+ half of the number of bytes requested. */
+ rlen /= 2;
+ if (rlen == 0)
+ rlen = 1;
+ }
+ if (rlen > sizeof outbuf)
+ rlen = sizeof outbuf;
+
+ HANDLE handle = get_io_handle ();
+
+ n = 0; // get_readahead_into_buffer (outbuf, len);
+ if (!n)
+ {
+ /* Doing a busy wait like this is quite inefficient, but nothing
+ else seems to work completely. Windows should provide some sort
+ of overlapped I/O for pipes, or something, but it doesn't. */
+ while (1)
+ {
+ if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
+ goto err;
+ if (n > 0)
+ break;
+ if (hit_eof ())
+ goto out;
+ if (n == 0 && is_nonblocking ())
+ {
+ set_errno (EAGAIN);
+ rc = -1;
+ break;
+ }
+
+ Sleep (10);
+ }
+
+ if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE)
+ goto err;
+ }
+
+ termios_printf ("bytes read %u", n);
+ get_ttyp ()->write_error = 0;
+ if (output_done_event != NULL)
+ SetEvent (output_done_event);
+
+ if (get_ttyp ()->ti.c_lflag & FLUSHO)
+ continue;
+
+ char *optr;
+ optr = buf;
+ if (pktmode_on)
+ *optr++ = TIOCPKT_DATA;
+
+ if (!(get_ttyp ()->ti.c_oflag & OPOST)) // post-process output
+ {
+ memcpy (optr, outbuf, n);
+ optr += n;
+ }
+ else // raw output mode
+ {
+ char *iptr = outbuf;
+
+ while (n--)
+ {
+ switch (*iptr)
+ {
+ case '\r':
+ if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
+ {
+ iptr++;
+ continue;
+ }
+ if (get_ttyp ()->ti.c_oflag & OCRNL)
+ *iptr = '\n';
+ else
+ column = 0;
+ break;
+ case '\n':
+ if (get_ttyp ()->ti.c_oflag & ONLCR)
+ {
+ *optr++ = '\r';
+ column = 0;
+ }
+ if (get_ttyp ()->ti.c_oflag & ONLRET)
+ column = 0;
+ break;
+ default:
+ column++;
+ break;
+ }
+
+ /* Don't store data past the end of the user's buffer. This
+ can happen if the user requests a read of 1 byte when
+ doing \r\n expansion. */
+ if (optr - buf >= (int) len)
+ {
+ if (*iptr != '\n' || n != 0)
+ system_printf ("internal error: %d unexpected characters", n);
+ need_nl = 1;
+ break;
+ }
+
+ *optr++ = *iptr++;
+ }
+ }
+ rc = optr - buf;
+ break;
+
+ err:
+ if (GetLastError () == ERROR_BROKEN_PIPE)
+ rc = 0;
+ else
+ {
+ __seterrno ();
+ rc = -1;
+ }
+ break;
+ }
+
+out:
+ termios_printf ("returning %d", rc);
+ return rc;
+}
+
+static DWORD WINAPI
+process_output (void *)
+{
+ char buf[OUT_BUFFER_SIZE*2];
+
+ for (;;)
+ {
+ int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
+ if (n < 0)
+ {
+ termios_printf ("ReadFile %E");
+ ExitThread (0);
+ }
+ if (n == 0)
+ {
+ /* End of file. */
+ ExitThread (0);
+ }
+ n = tty_master->console->write ((void *) buf, (size_t) n);
+ tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
+ }
+}
+
+
+/* Process tty ioctl requests */
+
+static DWORD WINAPI
+process_ioctl (void *)
+{
+ while (1)
+ {
+ WaitForSingleObject (tty_master->ioctl_request_event, INFINITE);
+ termios_printf ("ioctl() request");
+ tty_master->get_ttyp ()->ioctl_retval =
+ tty_master->console->ioctl (tty_master->get_ttyp ()->cmd,
+ (void *) &tty_master->get_ttyp ()->arg);
+ SetEvent (tty_master->ioctl_done_event);
+ }
+}
+
+/**********************************************************************/
+/* Tty slave stuff */
+
+fhandler_tty_slave::fhandler_tty_slave (int num, const char *name) :
+ fhandler_tty_common (FH_TTYS, name, num)
+{
+ set_cb (sizeof *this);
+ ttynum = num;
+ /* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the
+ need for double allocates. */
+ unix_path_name = (char *) crealloc (unix_path_name, strlen (win32_path_name) + 1);
+ strcpy (unix_path_name, win32_path_name);
+ unix_path_name[0] = unix_path_name[4] = '/';
+ debug_printf ("unix '%s', win32 '%s'", unix_path_name, win32_path_name);
+ inuse = NULL;
+}
+
+fhandler_tty_slave::fhandler_tty_slave (const char *name) :
+ fhandler_tty_common (FH_TTYS, name, 0)
+{
+ set_cb (sizeof *this);
+ inuse = NULL;
+}
+
+/* FIXME: This function needs to close handles when it has
+ a failing condition. */
+int
+fhandler_tty_slave::open (const char *, int flags, mode_t)
+{
+ tcinit (cygwin_shared->tty[ttynum]);
+
+ attach_tty (ttynum);
+ tc->set_ctty (ttynum, flags);
+
+ set_flags (flags);
+ /* Create synchronisation events */
+ char buf[40];
+
+ /* output_done_event may or may not exist. It will exist if the tty
+ was opened by fhandler_tty_master::init, normally called at
+ startup if use_tty is non-zero. It will not exist if this is a
+ pty opened by fhandler_pty_master::open. In the former case, tty
+ output is handled by a separate thread which controls output. */
+ __small_sprintf (buf, OUTPUT_DONE_EVENT, ttynum);
+ output_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+
+ if (!(output_mutex = get_ttyp ()->open_output_mutex ()))
+ {
+ termios_printf ("open output mutex failed, %E");
+ __seterrno ();
+ return 0;
+ }
+ if (!(input_mutex = get_ttyp ()->open_input_mutex ()))
+ {
+ termios_printf ("open input mutex failed, %E");
+ __seterrno ();
+ return 0;
+ }
+ __small_sprintf (buf, INPUT_AVAILABLE_EVENT, ttynum);
+ if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf)))
+ {
+ termios_printf ("open input event failed, %E");
+ __seterrno ();
+ return 0;
+ }
+
+ /* The ioctl events may or may not exist. See output_done_event,
+ above. */
+ __small_sprintf (buf, IOCTL_REQUEST_EVENT, ttynum);
+ ioctl_request_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+ __small_sprintf (buf, IOCTL_DONE_EVENT, ttynum);
+ ioctl_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+
+ /* FIXME: Needs a method to eliminate tty races */
+ {
+ acquire_output_mutex (500);
+ inuse = get_ttyp ()->create_inuse (TTY_SLAVE_ALIVE);
+ get_ttyp ()->was_opened = TRUE;
+ release_output_mutex ();
+ }
+
+ /* Duplicate tty handles. */
+
+ if (!get_ttyp ()->from_slave || !get_ttyp ()->to_slave)
+ {
+ termios_printf ("tty handles have been closed");
+ set_errno (EACCES);
+ return 0;
+ }
+
+ HANDLE from_master_local, to_master_local;
+
+ if (!wincap.has_security () ||
+ cygserver_running!=CYGSERVER_OK ||
+ !cygserver_attach_tty ( &from_master_local, &to_master_local))
+ {
+ termios_printf ("cannot dup handles via server. using old method.");
+
+ HANDLE tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+ get_ttyp ()->master_pid);
+ if (tty_owner == NULL)
+ {
+ termios_printf ("can't open tty (%d) handle process %d",
+ ttynum, get_ttyp ()->master_pid);
+ __seterrno ();
+ return 0;
+ }
+
+ if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
+ hMainProc, &from_master_local, 0, TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("can't duplicate input, %E");
+ __seterrno ();
+ return 0;
+ }
+ termios_printf ("duplicated from_master %p->%p from tty_owner %p",
+ get_ttyp ()->from_master, from_master_local, tty_owner);
+
+ if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
+ hMainProc, &to_master_local, 0, TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("can't duplicate output, %E");
+ __seterrno ();
+ return 0;
+ }
+ termios_printf ("duplicated to_master %p->%p from tty_owner %p",
+ get_ttyp ()->to_master, to_master_local, tty_owner);
+ CloseHandle (tty_owner);
+ }
+
+ set_io_handle (from_master_local);
+ ProtectHandle1 (from_master_local, from_pty);
+ set_output_handle (to_master_local);
+ ProtectHandle1 (to_master_local, to_pty);
+
+ set_open_status ();
+ termios_printf ("tty%d opened", ttynum);
+
+ return 1;
+}
+
+int
+fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
+ LPHANDLE to_master_ptr)
+{
+ if (!from_master_ptr || !to_master_ptr)
+ return 0;
+
+ client_request_attach_tty *request =
+ new client_request_attach_tty ((DWORD) GetCurrentProcessId (),
+ (DWORD) get_ttyp ()->master_pid,
+ (HANDLE) get_ttyp ()->from_master,
+ (HANDLE) get_ttyp ()->to_master);
+
+ if (cygserver_request (request) != 0 ||
+ request->header.error_code != 0)
+ return 0;
+
+/*
+ struct request_attach_tty req;
+ INIT_REQUEST (req, CYGSERVER_REQUEST_ATTACH_TTY);
+ req.pid = GetCurrentProcessId ();
+ req.master_pid = get_ttyp ()->master_pid;
+ req.from_master = get_ttyp ()->from_master;
+ req.to_master = get_ttyp ()->to_master;
+ if (cygserver_request ((struct request_header*) &req) != 0)
+ return 0;
+*/
+ *from_master_ptr = request->from_master ();
+ *to_master_ptr = request->to_master ();
+ delete request;
+ return 1;
+}
+
+void
+fhandler_tty_slave::init (HANDLE, DWORD a, mode_t)
+{
+ int mode = 0;
+
+ a &= GENERIC_READ | GENERIC_WRITE;
+ if (a == GENERIC_READ)
+ mode = O_RDONLY;
+ if (a == GENERIC_WRITE)
+ mode = O_WRONLY;
+ if (a == (GENERIC_READ | GENERIC_WRITE))
+ mode = O_RDWR;
+
+ open (0, mode);
+}
+
+int
+fhandler_tty_slave::write (const void *ptr, size_t len)
+{
+ DWORD n, towrite = len;
+
+ termios_printf ("tty%d, write(%x, %d)", ttynum, ptr, len);
+
+ acquire_output_mutex (INFINITE);
+
+ while (len)
+ {
+ n = min (OUT_BUFFER_SIZE, len);
+ char *buf = (char *)ptr;
+ ptr = (char *) ptr + n;
+ len -= n;
+
+ /* Previous write may have set write_error to != 0. Check it here.
+ This is less than optimal, but the alternative slows down tty
+ writes enormously. */
+ if (get_ttyp ()->write_error)
+ {
+ set_errno (get_ttyp ()->write_error);
+ towrite = (DWORD) -1;
+ break;
+ }
+
+ if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
+ {
+ DWORD err = GetLastError ();
+ termios_printf ("WriteFile failed, %E");
+ switch (err)
+ {
+ case ERROR_NO_DATA:
+ err = ERROR_IO_DEVICE;
+ default:
+ __seterrno_from_win_error (err);
+ }
+ _raise (SIGHUP); /* FIXME: Should this be SIGTTOU? */
+ towrite = (DWORD) -1;
+ break;
+ }
+
+ if (output_done_event != NULL)
+ {
+ DWORD rc;
+ DWORD x = n * 1000;
+ rc = WaitForSingleObject (output_done_event, x);
+ termios_printf ("waited %d ms for output_done_event, WFSO %d", x, rc);
+ }
+ }
+ release_output_mutex ();
+ return towrite;
+}
+
+int
+fhandler_tty_slave::read (void *ptr, size_t len)
+{
+ DWORD n;
+ int totalread = 0;
+ int vmin = INT_MAX;
+ int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
+ size_t readlen;
+ DWORD bytes_in_pipe;
+ char buf[INP_BUFFER_SIZE];
+ char peek_buf[INP_BUFFER_SIZE];
+ DWORD time_to_wait;
+ DWORD rc;
+ HANDLE w4[2];
+
+ termios_printf ("read(%x, %d) handle %d", ptr, len, get_handle ());
+
+ if (!(get_ttyp ()->ti.c_lflag & ICANON))
+ {
+ vmin = min (INP_BUFFER_SIZE, get_ttyp ()->ti.c_cc[VMIN]);
+ vtime = get_ttyp ()->ti.c_cc[VTIME];
+ if (vmin < 0) vmin = 0;
+ if (vtime < 0) vtime = 0;
+ if (vmin == 0)
+ time_to_wait = INFINITE;
+ else
+ time_to_wait = (vtime == 0 ? INFINITE : 100 * vtime);
+ }
+ else
+ time_to_wait = INFINITE;
+
+ w4[0] = signal_arrived;
+ w4[1] = input_available_event;
+
+ while (len)
+ {
+ rc = WaitForMultipleObjects (2, w4, FALSE, time_to_wait);
+ if (rc == WAIT_OBJECT_0)
+ {
+ /* if we've received signal after successfully reading some data,
+ just return all data successfully read */
+ if (totalread > 0)
+ break;
+ set_sig_errno (EINTR);
+ return -1;
+ }
+ else if (rc == WAIT_FAILED)
+ {
+ termios_printf ("wait for input event failed, %E");
+ break;
+ }
+ else if (rc == WAIT_TIMEOUT)
+ break;
+ rc = WaitForSingleObject (input_mutex, 1000);
+ if (rc == WAIT_FAILED)
+ {
+ termios_printf ("wait for input mutex failed, %E");
+ break;
+ }
+ else if (rc == WAIT_TIMEOUT)
+ {
+ termios_printf ("failed to acquire input mutex after input event arrived");
+ break;
+ }
+ if (!PeekNamedPipe (get_handle (), peek_buf, sizeof(peek_buf), &bytes_in_pipe, NULL, NULL))
+ {
+ termios_printf ("PeekNamedPipe failed, %E");
+ _raise (SIGHUP);
+ bytes_in_pipe = 0;
+ }
+ readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
+ if (readlen)
+ {
+ termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
+ if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
+ {
+ termios_printf ("read failed, %E");
+ _raise (SIGHUP);
+ }
+ /* MSDN states that 5th prameter can be used to determine total
+ number of bytes in pipe, but for some reason this number doesn't
+ change after successful read. So we have to peek into the pipe
+ again to see if input is still available */
+ if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
+ {
+ termios_printf ("PeekNamedPipe failed, %E");
+ _raise (SIGHUP);
+ bytes_in_pipe = 0;
+ }
+ if (n)
+ {
+ len -= n;
+ totalread += n;
+ memcpy (ptr, buf, n);
+ ptr = (char *) ptr + n;
+ }
+ }
+
+ if (!bytes_in_pipe)
+ ResetEvent (input_available_event);
+
+ ReleaseMutex (input_mutex);
+
+ if (get_ttyp ()->read_retval < 0) // read error
+ {
+ set_errno (-get_ttyp ()->read_retval);
+ totalread = -1;
+ break;
+ }
+ if (get_ttyp ()->read_retval == 0) //EOF
+ {
+ termios_printf ("saw EOF");
+ break;
+ }
+ if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
+ break;
+ if (totalread >= vmin && (vmin > 0 || totalread > 0))
+ break;
+
+ /* vmin == 0 && vtime == 0:
+ * we've already read all input, if any, so return immediately
+ * vmin == 0 && vtime > 0:
+ * we've waited for input 10*vtime ms in WFSO(input_available_event),
+ * no matter whether any input arrived, we shouldn't wait any longer,
+ * so return immediately
+ * vmin > 0 && vtime == 0:
+ * here, totalread < vmin, so continue waiting until more data
+ * arrive
+ * vmin > 0 && vtime > 0:
+ * similar to the previous here, totalread < vmin, and timer
+ * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
+ * so "restart timer" and wait until more data arrive
+ */
+
+ if (vmin == 0)
+ break;
+ }
+ termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
+ return totalread;
+}
+
+int
+fhandler_tty_common::dup (fhandler_base *child)
+{
+ fhandler_tty_slave *fts = (fhandler_tty_slave *) child;
+ int errind;
+
+ fts->ttynum = ttynum;
+ fts->tcinit (get_ttyp ());
+
+ attach_tty (ttynum);
+ tc->set_ctty (ttynum, openflags);
+
+ HANDLE nh;
+
+ if (output_done_event == NULL)
+ fts->output_done_event = NULL;
+ else if (!DuplicateHandle (hMainProc, output_done_event, hMainProc,
+ &fts->output_done_event, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 1;
+ goto err;
+ }
+ if (ioctl_request_event == NULL)
+ fts->ioctl_request_event = NULL;
+ else if (!DuplicateHandle (hMainProc, ioctl_request_event, hMainProc,
+ &fts->ioctl_request_event, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 2;
+ goto err;
+ }
+ if (ioctl_done_event == NULL)
+ fts->ioctl_done_event = NULL;
+ else if (!DuplicateHandle (hMainProc, ioctl_done_event, hMainProc,
+ &fts->ioctl_done_event, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 3;
+ goto err;
+ }
+ if (!DuplicateHandle (hMainProc, input_available_event, hMainProc,
+ &fts->input_available_event, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 4;
+ goto err;
+ }
+ if (!DuplicateHandle (hMainProc, output_mutex, hMainProc,
+ &fts->output_mutex, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 5;
+ goto err;
+ }
+ if (!DuplicateHandle (hMainProc, input_mutex, hMainProc,
+ &fts->input_mutex, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 6;
+ goto err;
+ }
+ if (!DuplicateHandle (hMainProc, get_handle (), hMainProc,
+ &nh, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 7;
+ goto err;
+ }
+ fts->set_io_handle (nh);
+
+ if (!DuplicateHandle (hMainProc, get_output_handle (), hMainProc,
+ &nh, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 8;
+ goto err;
+ }
+ fts->set_output_handle (nh);
+
+ if (inuse == NULL)
+ fts->inuse = NULL;
+ else if (!DuplicateHandle (hMainProc, inuse, hMainProc,
+ &fts->inuse, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 9;
+ goto err;
+ }
+ return 0;
+
+err:
+ __seterrno ();
+ termios_printf ("dup %d failed in DuplicateHandle, %E", errind);
+ return -1;
+}
+
+int
+fhandler_tty_slave::tcgetattr (struct termios *t)
+{
+ *t = get_ttyp ()->ti;
+ return 0;
+}
+
+int
+fhandler_tty_slave::tcsetattr (int, const struct termios *t)
+{
+ acquire_output_mutex (INFINITE);
+ get_ttyp ()->ti = *t;
+ release_output_mutex ();
+ return 0;
+}
+
+int
+fhandler_tty_slave::tcflush (int)
+{
+ return 0;
+}
+
+int
+fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
+{
+ termios_printf ("ioctl (%x)", cmd);
+
+ if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid &&
+ myself->ctty == ttynum && (get_ttyp ()->ti.c_lflag & TOSTOP))
+ {
+ /* background process */
+ termios_printf ("bg ioctl pgid %d, tpgid %d, ctty %d",
+ myself->pgid, get_ttyp ()->getpgid (), myself->ctty);
+ _raise (SIGTTOU);
+ }
+
+ switch (cmd)
+ {
+ case TIOCGWINSZ:
+ case TIOCSWINSZ:
+ break;
+ case FIONBIO:
+ set_nonblocking (*(int *) arg);
+ goto out;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ acquire_output_mutex (INFINITE);
+
+ get_ttyp ()->cmd = cmd;
+ get_ttyp ()->ioctl_retval = 0;
+ switch (cmd)
+ {
+ case TIOCGWINSZ:
+ get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
+ if (ioctl_request_event)
+ SetEvent (ioctl_request_event);
+ * (struct winsize *) arg = get_ttyp ()->arg.winsize;
+ if (ioctl_done_event)
+ WaitForSingleObject (ioctl_done_event, INFINITE);
+ get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
+ break;
+ case TIOCSWINSZ:
+ get_ttyp ()->ioctl_retval = -1;
+ get_ttyp ()->arg.winsize = * (struct winsize *) arg;
+ if (ioctl_request_event)
+ SetEvent (ioctl_request_event);
+ if (ioctl_done_event)
+ WaitForSingleObject (ioctl_done_event, INFINITE);
+ break;
+ }
+
+ release_output_mutex ();
+
+out:
+ termios_printf ("%d = ioctl (%x)", get_ttyp ()->ioctl_retval, cmd);
+ return get_ttyp ()->ioctl_retval;
+}
+
+/*******************************************************
+ fhandler_pty_master
+*/
+fhandler_pty_master::fhandler_pty_master (const char *name, DWORD devtype, int unit) :
+ fhandler_tty_common (devtype, name, unit)
+{
+ set_cb (sizeof *this);
+ ioctl_request_event = NULL;
+ ioctl_done_event = NULL;
+ pktmode = need_nl = 0;
+ inuse = NULL;
+}
+
+int
+fhandler_pty_master::open (const char *, int flags, mode_t)
+{
+ ttynum = cygwin_shared->tty.allocate_tty (0);
+ if (ttynum < 0)
+ return 0;
+
+ cygwin_shared->tty[ttynum]->common_init (this);
+ inuse = get_ttyp ()->create_inuse (TTY_MASTER_ALIVE);
+ set_flags (flags);
+ set_open_status ();
+
+ termios_printf ("opened pty master tty%d<%p>", ttynum, this);
+ return 1;
+}
+
+int
+fhandler_tty_common::close ()
+{
+ if (output_done_event && !CloseHandle (output_done_event))
+ termios_printf ("CloseHandle (output_done_event), %E");
+ if (ioctl_done_event && !CloseHandle (ioctl_done_event))
+ termios_printf ("CloseHandle (ioctl_done_event), %E");
+ if (ioctl_request_event && !CloseHandle (ioctl_request_event))
+ termios_printf ("CloseHandle (ioctl_request_event), %E");
+ if (inuse && !CloseHandle (inuse))
+ termios_printf ("CloseHandle (inuse), %E");
+ if (!ForceCloseHandle (output_mutex))
+ termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
+ if (!ForceCloseHandle (input_mutex))
+ termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
+
+ /* Send EOF to slaves if master side is closed */
+ if (!get_ttyp ()->master_alive ())
+ {
+ termios_printf ("no more masters left. sending EOF" );
+ SetEvent (input_available_event);
+ }
+
+ if (!ForceCloseHandle (input_available_event))
+ termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
+ if (!ForceCloseHandle1 (get_handle (), from_pty))
+ termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
+ if (!ForceCloseHandle1 (get_output_handle (), to_pty))
+ termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
+
+ inuse = NULL;
+ termios_printf ("tty%d <%p,%p> closed", ttynum, get_handle (), get_output_handle ());
+ return 0;
+}
+
+int
+fhandler_pty_master::close ()
+{
+#if 0
+ while (accept_input () > 0)
+ continue;
+#endif
+ this->fhandler_tty_common::close ();
+
+ if (!get_ttyp ()->master_alive ())
+ {
+ termios_printf ("freeing tty%d (%d)", ttynum, get_ttyp ()->ntty);
+#if 0
+ if (get_ttyp ()->to_slave)
+ ForceCloseHandle1 (get_ttyp ()->to_slave, to_slave);
+ if (get_ttyp ()->from_slave)
+ ForceCloseHandle1 (get_ttyp ()->from_slave, from_slave);
+#endif
+ if (get_ttyp ()->from_master)
+ CloseHandle (get_ttyp ()->from_master);
+ if (get_ttyp ()->to_master)
+ CloseHandle (get_ttyp ()->to_master);
+ get_ttyp ()->init ();
+ }
+
+ return 0;
+}
+
+int
+fhandler_pty_master::write (const void *ptr, size_t len)
+{
+ (void) line_edit ((char *) ptr, len);
+ return len;
+}
+
+int
+fhandler_pty_master::read (void *ptr, size_t len)
+{
+ return process_slave_output ((char *) ptr, len, pktmode);
+}
+
+int
+fhandler_pty_master::tcgetattr (struct termios *t)
+{
+ *t = cygwin_shared->tty[ttynum]->ti;
+ return 0;
+}
+
+int
+fhandler_pty_master::tcsetattr (int, const struct termios *t)
+{
+ cygwin_shared->tty[ttynum]->ti = *t;
+ return 0;
+}
+
+int
+fhandler_pty_master::tcflush (int)
+{
+ return 0;
+}
+
+int
+fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
+{
+ switch (cmd)
+ {
+ case TIOCPKT:
+ pktmode = * (int *) arg;
+ break;
+ case TIOCGWINSZ:
+ * (struct winsize *) arg = get_ttyp ()->winsize;
+ break;
+ case TIOCSWINSZ:
+ get_ttyp ()->winsize = * (struct winsize *) arg;
+ _kill (-get_ttyp ()->getpgid (), SIGWINCH);
+ break;
+ case FIONBIO:
+ set_nonblocking (*(int *) arg);
+ break;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 0;
+}
+
+char *
+fhandler_pty_master::ptsname (void)
+{
+ static char buf[32];
+
+ __small_sprintf (buf, "/dev/tty%d", ttynum);
+ return buf;
+}
+
+void
+fhandler_tty_common::set_close_on_exec (int val)
+{
+#ifndef DEBUGGING
+ this->fhandler_base::set_close_on_exec (val);
+#else
+ /* FIXME: This is a duplication from fhandler_base::set_close_on_exec.
+ It is here because we need to specify the "from_pty" stuff here or
+ we'll get warnings from ForceCloseHandle when debugging. */
+ set_inheritance (get_io_handle (), val);
+ set_close_on_exec_flag (val);
+#endif
+ if (output_done_event)
+ set_inheritance (output_done_event, val);
+ if (ioctl_request_event)
+ set_inheritance (ioctl_request_event, val);
+ if (ioctl_done_event)
+ set_inheritance (ioctl_done_event, val);
+ if (inuse)
+ set_inheritance (inuse, val);
+ set_inheritance (output_mutex, val);
+ set_inheritance (input_mutex, val);
+ set_inheritance (input_available_event, val);
+ set_inheritance (output_handle, val);
+}
+
+void
+fhandler_tty_common::fixup_after_fork (HANDLE parent)
+{
+ this->fhandler_termios::fixup_after_fork (parent);
+ if (output_done_event)
+ fork_fixup (parent, output_done_event, "output_done_event");
+ if (ioctl_request_event)
+ fork_fixup (parent, ioctl_request_event, "ioctl_request_event");
+ if (ioctl_done_event)
+ fork_fixup (parent, ioctl_done_event, "ioctl_done_event");
+ if (output_mutex)
+ {
+ fork_fixup (parent, output_mutex, "output_mutex");
+ ProtectHandle (output_mutex);
+ }
+ if (input_mutex)
+ {
+ fork_fixup (parent, input_mutex, "input_mutex");
+ ProtectHandle (input_mutex);
+ }
+ if (input_available_event)
+ fork_fixup (parent, input_available_event, "input_available_event");
+ fork_fixup (parent, inuse, "inuse");
+}
+
+void
+fhandler_pty_master::set_close_on_exec (int val)
+{
+ this->fhandler_tty_common::set_close_on_exec (val);
+
+ /* FIXME: There is a console handle leak here. */
+ if (get_ttyp ()->master_pid == GetCurrentProcessId ())
+ {
+ get_ttyp ()->from_slave = get_handle ();
+ get_ttyp ()->to_slave = get_output_handle ();
+ termios_printf ("from_slave %p, to_slave %p", get_handle (),
+ get_output_handle ());
+ }
+}
+
+void
+fhandler_tty_master::fixup_after_fork (HANDLE child)
+{
+ this->fhandler_pty_master::fixup_after_fork (child);
+ console->fixup_after_fork (child);
+}
+
+void
+fhandler_tty_master::fixup_after_exec (HANDLE)
+{
+ console->close ();
+ init_console ();
+ return;
+}
+
+int
+fhandler_tty_master::init_console ()
+{
+ console = (fhandler_console *) cygheap->fdtab.build_fhandler (-1, FH_CONSOLE, "/dev/ttym");
+ if (console == NULL)
+ return -1;
+
+ console->init (INVALID_HANDLE_VALUE, GENERIC_READ | GENERIC_WRITE, O_BINARY);
+ console->set_r_no_interrupt (1);
+ return 0;
+}
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
new file mode 100644
index 00000000000..0903ae9a532
--- /dev/null
+++ b/winsup/cygwin/fork.cc
@@ -0,0 +1,751 @@
+/* fork.cc
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 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. */
+
+#include "winsup.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include "security.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygerrno.h"
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "cygheap.h"
+#include "child_info.h"
+#define NEED_VFORK
+#include "perthread.h"
+#include "perprocess.h"
+#include "dll_init.h"
+
+#ifdef DEBUGGING
+static int npid;
+static int npid_max;
+static pid_t fork_pids[100];
+#endif
+
+/* Timeout to wait for child to start, parent to init child, etc. */
+/* FIXME: Once things stabilize, bump up to a few minutes. */
+#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
+
+#define dll_data_start &_data_start__
+#define dll_data_end &_data_end__
+#define dll_bss_start &_bss_start__
+#define dll_bss_end &_bss_end__
+
+void
+per_thread::set (void *s)
+{
+ if (s == PER_THREAD_FORK_CLEAR)
+ {
+ tls = TlsAlloc ();
+ s = NULL;
+ }
+ TlsSetValue (get_tls (), s);
+}
+
+static void
+stack_base (child_info_fork &ch)
+{
+ MEMORY_BASIC_INFORMATION m;
+ memset (&m, 0, sizeof m);
+ if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
+ system_printf ("couldn't get memory info, %E");
+
+ ch.stacktop = m.AllocationBase;
+ ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
+ ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
+ debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
+ ch.stackbottom, ch.stacktop, &m, ch.stacksize,
+ (DWORD) ch.stackbottom - (DWORD) ch.stacktop);
+}
+
+/* Copy memory from parent to child.
+ The result is a boolean indicating success. */
+
+static int
+fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
+{
+ va_list args;
+ char *low;
+ int pass = 0;
+
+ va_start (args, what);
+
+ while ((low = va_arg (args, char *)))
+ {
+ char *high = va_arg (args, char *);
+ DWORD todo = wincap.chunksize () ?: high - low;
+ char *here;
+
+ for (here = low; here < high; here += todo)
+ {
+ DWORD done = 0;
+ if (here + todo > high)
+ todo = high - here;
+ int res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
+ debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
+ low, high, res);
+ if (!res || todo != done)
+ {
+ if (!res)
+ __seterrno ();
+ /* If this happens then there is a bug in our fork
+ implementation somewhere. */
+ system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E",
+ what, pass, low, high, done, pi.dwProcessId);
+ goto err;
+ }
+ }
+
+ pass++;
+ }
+
+ debug_printf ("done");
+ return 1;
+
+ err:
+ TerminateProcess (pi.hProcess, 1);
+ set_errno (EAGAIN);
+ return 0;
+}
+
+/* Wait for child to finish what it's doing and signal us.
+ We don't want to wait forever here.If there's a problem somewhere
+ it'll hang the entire system (since all forks are mutex'd). If we
+ time out, set errno = EAGAIN and hope the app tries again. */
+static int
+sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
+ BOOL hang_child, const char *s)
+{
+ /* We also add the child process handle to the wait. If the child fails
+ to initialize (eg. because of a missing dll). Then this
+ handle will become signalled. This stops a *looong* timeout wait.
+ */
+ HANDLE w4[2];
+
+ debug_printf ("waiting for child. reason: %s, hang_child %d", s,
+ hang_child);
+ w4[1] = pi.hProcess;
+ w4[0] = subproc_ready;
+ DWORD rc = WaitForMultipleObjects (2, w4, FALSE, FORK_WAIT_TIMEOUT);
+
+ if (rc == WAIT_OBJECT_0 ||
+ WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
+ /* That's ok */;
+ else if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
+ {
+ if (rc != WAIT_FAILED)
+ system_printf ("WaitForMultipleObjects timed out");
+ else
+ system_printf ("WaitForMultipleObjects failed, %E");
+ set_errno (EAGAIN);
+ syscall_printf ("-1 = fork(), WaitForMultipleObjects failed");
+ TerminateProcess (pi.hProcess, 1);
+ return 0;
+ }
+ else
+ {
+ /* Child died. Clean up and exit. */
+ DWORD errcode;
+ GetExitCodeProcess (pi.hProcess, &errcode);
+ /* Fix me. This is not enough. The fork should not be considered
+ * to have failed if the process was essentially killed by a signal.
+ */
+ if (errcode != STATUS_CONTROL_C_EXIT)
+ {
+ system_printf ("child %d(%p) died before initialization with status code %p",
+ pi.dwProcessId, pi.hProcess, errcode);
+ system_printf ("*** child state %s", s);
+#ifdef DEBUGGING
+ abort ();
+#endif
+ }
+ set_errno (EAGAIN);
+ syscall_printf ("Child died before subproc_ready signalled");
+ return 0;
+ }
+
+ debug_printf ("child signalled me");
+ return 1;
+}
+
+static int
+resume_child (PROCESS_INFORMATION &pi, HANDLE forker_finished)
+{
+ SetEvent (forker_finished);
+ debug_printf ("signalled child");
+ return 1;
+}
+
+/* Notify parent that it is time for the next step.
+ Note that this has to be a macro since the parent may be messing with
+ our stack. */
+static void __stdcall
+sync_with_parent(const char *s, bool hang_self)
+{
+ debug_printf ("signalling parent: %s", s);
+ /* Tell our parent we're waiting. */
+ if (!SetEvent (child_proc_info->subproc_ready))
+ api_fatal ("fork child - SetEvent for %s failed, %E", s);
+ if (hang_self)
+ {
+ HANDLE h = child_proc_info->forker_finished;
+ /* Wait for the parent to fill in our stack and heap.
+ Don't wait forever here. If our parent dies we don't want to clog
+ the system. If the wait fails, we really can't continue so exit. */
+ DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
+ debug_printf ("awake");
+ switch (psync_rc)
+ {
+ case WAIT_TIMEOUT:
+ api_fatal ("WFSO timed out for %s", s);
+ break;
+ case WAIT_FAILED:
+ if (GetLastError () == ERROR_INVALID_HANDLE &&
+ WaitForSingleObject (child_proc_info->forker_finished, 1) != WAIT_FAILED)
+ break;
+ api_fatal ("WFSO failed for %s, fork_finished %p, %E", s,
+ child_proc_info->forker_finished);
+ break;
+ default:
+ debug_printf ("no problems");
+ break;
+ }
+ }
+}
+
+static int __stdcall
+fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
+{
+ debug_printf ("child is running. pid %d, ppid %d, stack here %p",
+ myself->pid, myself->ppid, __builtin_frame_address (0));
+
+ /* 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");
+ }
+
+ sync_with_parent ("after longjmp.", TRUE);
+ ProtectHandle (hParent);
+ sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d\n", hParent,
+ first_dll, load_dlls);
+
+#ifdef DEBUGGING
+ char c;
+ if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
+ try_to_debug ();
+ char buf[80];
+ /* This is useful for debugging fork problems. Use gdb to attach to
+ the pid reported here. */
+ if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
+ {
+ small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
+ Sleep (atoi(buf));
+ }
+#endif
+
+ /* If we've played with the stack, stacksize != 0. That means that
+ fork() was invoked from other than the main thread. Make sure that
+ when the "main" thread exits it calls do_exit, like a normal process.
+ Exit with a status code of 0. */
+ if (child_proc_info->stacksize)
+ {
+ ((DWORD *)child_proc_info->stackbottom)[-17] = (DWORD)do_exit;
+ ((DWORD *)child_proc_info->stackbottom)[-15] = (DWORD)0;
+ }
+
+ set_file_api_mode (current_codepage);
+
+ MALLOC_CHECK;
+
+ debug_fixup_after_fork ();
+ pinfo_fixup_after_fork ();
+ cygheap->fdtab.fixup_after_fork (hParent);
+ signal_fixup_after_fork ();
+
+ MALLOC_CHECK;
+
+ /* If we haven't dynamically loaded any dlls, just signal
+ the parent. Otherwise, load all the dlls, tell the parent
+ that we're done, and wait for the parent to fill in the.
+ loaded dlls' data/bss. */
+ if (!load_dlls)
+ sync_with_parent ("performed fork fixup.", FALSE);
+ else
+ {
+ dlls.load_after_fork (hParent, first_dll);
+ sync_with_parent ("loaded dlls", TRUE);
+ }
+
+ ForceCloseHandle (hParent);
+ (void) ForceCloseHandle (child_proc_info->subproc_ready);
+ (void) ForceCloseHandle (child_proc_info->forker_finished);
+
+ if (fixup_mmaps_after_fork ())
+ api_fatal ("recreate_mmaps_after_fork_failed");
+
+ if (fixup_shms_after_fork ())
+ api_fatal ("recreate_shm areas after fork failed");
+
+ /* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
+ non-zero, for some reason.
+ FIXME: There is a memory leak here after a fork. */
+ for (per_thread **t = threadstuff; *t; t++)
+ if ((*t)->clear_on_fork ())
+ (*t)->set ();
+
+ user_data->threadinterface->fixup_after_fork ();
+
+ /* Initialize signal/process handling */
+ sigproc_init ();
+ __pthread_atforkchild ();
+ cygbench ("fork-child");
+ return 0;
+}
+
+static void
+slow_pid_reuse (HANDLE h)
+{
+ static NO_COPY HANDLE last_fork_procs[8] = {0};
+ static NO_COPY unsigned nfork_procs = 0;
+
+ if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
+ nfork_procs = 0;
+ /* Keep a list of handles to forked processes sitting around to prevent
+ Windows from reusing the same pid n times in a row. Having the same pids
+ close in succesion confuses bash. Keeping a handle open will stop
+ windows from reusing the same pid. */
+ if (last_fork_procs[nfork_procs])
+ ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
+ if (DuplicateHandle (hMainProc, h, hMainProc, &last_fork_procs[nfork_procs],
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
+ else
+ {
+ last_fork_procs[nfork_procs] = NULL;
+ system_printf ("couldn't create last_fork_proc, %E");
+ }
+ nfork_procs++;
+}
+
+static int __stdcall
+fork_parent (HANDLE& hParent, dll *&first_dll,
+ bool& load_dlls, void *stack_here, child_info_fork &ch)
+{
+ HANDLE subproc_ready, forker_finished;
+ DWORD rc;
+ PROCESS_INFORMATION pi = {0, NULL, 0, 0};
+
+ /* call the pthread_atfork prepare functions */
+ __pthread_atforkprepare ();
+
+ subproc_init ();
+
+#ifdef DEBUGGING_NOTNEEDED
+ /* The ProtectHandle call allocates memory so we need to make sure
+ that enough is set aside here so that the sbrk pointer does not
+ move when ProtectHandle is called after the child is started.
+ Otherwise the sbrk pointers in the parent will not agree with
+ the child and when user_data is (regrettably) copied over,
+ the user_data->ptr field will not be accurate. */
+ free (malloc (4096));
+#endif
+
+ int c_flags = GetPriorityClass (hMainProc) /*|
+ CREATE_NEW_PROCESS_GROUP*/;
+ STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
+
+ /* If we don't have a console, then don't create a console for the
+ child either. */
+ HANDLE console_handle = CreateFileA ("CONOUT$", GENERIC_WRITE,
+ FILE_SHARE_WRITE, &sec_none_nih,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (console_handle != INVALID_HANDLE_VALUE && console_handle != 0)
+ CloseHandle (console_handle);
+ else
+ c_flags |= DETACHED_PROCESS;
+
+ /* Some file types (currently only sockets) need extra effort in the
+ parent after CreateProcess and before copying the datastructures
+ to the child. So we have to start the child in suspend state,
+ unfortunately, to avoid a race condition. */
+ if (cygheap->fdtab.need_fixup_before ())
+ c_flags |= CREATE_SUSPENDED;
+
+ /* Create an inheritable handle to pass to the child process. This will
+ allow the child to duplicate handles from the parent to itself. */
+ hParent = NULL;
+ if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ system_printf ("couldn't create handle to myself for child, %E");
+ return -1;
+ }
+
+ /* Remember the address of the first loaded dll and decide
+ if we need to load dlls. We do this here so that this
+ information will be available in the parent and, when
+ the stack is copied, in the child. */
+ first_dll = dlls.start.next;
+ load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
+
+ /* This will help some of the confusion. */
+ fflush (stdout);
+
+ subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
+ if (subproc_ready == NULL)
+ {
+ CloseHandle (hParent);
+ system_printf ("unable to allocate subproc_ready event, %E");
+ return -1;
+ }
+ forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
+ if (forker_finished == NULL)
+ {
+ CloseHandle (hParent);
+ CloseHandle (subproc_ready);
+ system_printf ("unable to allocate subproc_ready event, %E");
+ return -1;
+ }
+
+ ProtectHandle (subproc_ready);
+ ProtectHandle (forker_finished);
+
+ init_child_info (PROC_FORK1, &ch, 1, subproc_ready);
+
+ ch.forker_finished = forker_finished;
+
+ stack_base (ch);
+
+ si.cb = sizeof (STARTUPINFO);
+ si.lpReserved2 = (LPBYTE)&ch;
+ si.cbReserved2 = sizeof(ch);
+
+ /* Remove impersonation */
+ if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
+ RevertToSelf ();
+
+ ch.parent = hParent;
+#ifdef DEBUGGING
+ if (npid_max)
+ {
+ for (int pass = 0; pass < 2; pass++)
+ {
+ pid_t pid;
+ while ((pid = fork_pids[npid++]))
+ if (!pinfo (pid))
+ {
+ ch.cygpid = pid;
+ goto out;
+ }
+ npid = 0;
+ }
+ }
+ out:
+#endif
+
+ char sa_buf[1024];
+ syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
+ myself->progname, myself->progname, c_flags, &si, &pi);
+ __malloc_lock (_reent_clib ());
+ void *newheap;
+ newheap = cygheap_setup_for_child (&ch,cygheap->fdtab.need_fixup_before ());
+ rc = CreateProcess (myself->progname, /* image to run */
+ myself->progname, /* what we send in arg0 */
+ allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
+ allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
+ TRUE, /* inherit handles from parent */
+ c_flags,
+ NULL, /* environment filled in later */
+ 0, /* use current drive/directory */
+ &si,
+ &pi);
+
+ CloseHandle (hParent);
+
+ if (!rc)
+ {
+ __seterrno ();
+ syscall_printf ("CreateProcessA failed, %E");
+ ForceCloseHandle(subproc_ready);
+ ForceCloseHandle(forker_finished);
+ /* Restore impersonation */
+ if (cygheap->user.impersonated
+ && cygheap->user.token != INVALID_HANDLE_VALUE)
+ ImpersonateLoggedOnUser (cygheap->user.token);
+ cygheap_setup_for_child_cleanup (newheap, &ch, 0);
+ return -1;
+ }
+
+ /* Fixup the parent datastructure if needed and resume the child's
+ main thread. */
+ if (!cygheap->fdtab.need_fixup_before ())
+ cygheap_setup_for_child_cleanup (newheap, &ch, 0);
+ else
+ {
+ cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
+ cygheap_setup_for_child_cleanup (newheap, &ch, 1);
+ ResumeThread (pi.hThread);
+ }
+
+#ifdef DEBUGGING
+ pinfo forked ((ch.cygpid != 1 ? ch.cygpid : cygwin_pid (pi.dwProcessId)), 1);
+#else
+ pinfo forked (cygwin_pid (pi.dwProcessId), 1);
+#endif
+
+ /* Initialize things that are done later in dll_crt0_1 that aren't done
+ for the forkee. */
+ strcpy(forked->progname, myself->progname);
+
+ /* Restore impersonation */
+ if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
+ ImpersonateLoggedOnUser (cygheap->user.token);
+
+ ProtectHandle (pi.hThread);
+ /* Protect the handle but name it similarly to the way it will
+ be called in subproc handling. */
+ ProtectHandle1 (pi.hProcess, childhProc);
+
+ /* Fill in fields in the child's process table entry. */
+ forked->hProcess = pi.hProcess;
+ forked->dwProcessId = pi.dwProcessId;
+ forked->copysigs(myself);
+
+ /* Hopefully, this will succeed. The alternative to doing things this
+ way is to reserve space prior to calling CreateProcess and then fill
+ it in afterwards. This requires more bookkeeping than I like, though,
+ so we'll just do it the easy way. So, terminate any child process if
+ we can't actually record the pid in the internal table. */
+ if (!forked.remember ())
+ {
+ TerminateProcess (pi.hProcess, 1);
+ set_errno (EAGAIN);
+ goto cleanup;
+ }
+
+ slow_pid_reuse (pi.hProcess);
+
+ /* Wait for subproc to initialize itself. */
+ if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp"))
+ goto cleanup;
+
+ /* CHILD IS STOPPED */
+ debug_printf ("child is alive (but stopped)");
+
+ /* Initialize, in order: data, bss, heap, stack, dll data, dll bss
+ Note: variables marked as NO_COPY will not be copied
+ since they are placed in a protected segment. */
+
+
+ MALLOC_CHECK;
+ rc = fork_copy (pi, "user/cygwin data",
+ user_data->data_start, user_data->data_end,
+ user_data->bss_start, user_data->bss_end,
+ cygheap->heapbase, cygheap->heapptr,
+ stack_here, ch.stackbottom,
+ dll_data_start, dll_data_end,
+ dll_bss_start, dll_bss_end, NULL);
+
+ __malloc_unlock (_reent_clib ());
+ MALLOC_CHECK;
+ if (!rc)
+ goto cleanup;
+
+ /* Now fill data/bss of any DLLs that were linked into the program. */
+ for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
+ {
+ debug_printf ("copying data/bss of a linked dll");
+ if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
+ d->p.bss_start, d->p.bss_end,
+ NULL))
+ goto cleanup;
+ }
+
+ /* Start thread, and wait for it to reload dlls. */
+ if (!resume_child (pi, forker_finished) ||
+ !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))
+ goto cleanup;
+
+ /* If DLLs were loaded in the parent, then the child has reloaded all
+ of them and is now waiting to have all of the individual data and
+ bss sections filled in. */
+ if (load_dlls)
+ {
+ /* CHILD IS STOPPED */
+ /* write memory of reloaded dlls */
+ for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
+ {
+ debug_printf ("copying data/bss for a loaded dll");
+ if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
+ d->p.bss_start, d->p.bss_end,
+ NULL))
+ goto cleanup;
+ }
+ /* Start the child up again. */
+ (void) resume_child (pi, forker_finished);
+ }
+
+ ForceCloseHandle (subproc_ready);
+ ForceCloseHandle (pi.hThread);
+ ForceCloseHandle (forker_finished);
+ forker_finished = NULL;
+ pi.hThread = NULL;
+ __pthread_atforkparent ();
+
+ return forked->pid;
+
+/* Common cleanup code for failure cases */
+ cleanup:
+ /* Remember to de-allocate the fd table. */
+ if (pi.hProcess)
+ ForceCloseHandle1 (pi.hProcess, childhProc);
+ if (pi.hThread)
+ ForceCloseHandle (pi.hThread);
+ if (subproc_ready)
+ ForceCloseHandle (subproc_ready);
+ if (forker_finished)
+ ForceCloseHandle (forker_finished);
+ return -1;
+}
+
+extern "C" int
+fork ()
+{
+ struct
+ {
+ HANDLE hParent;
+ dll *first_dll;
+ bool load_dlls;
+ } grouped;
+
+ MALLOC_CHECK;
+ sigframe thisframe (mainthread);
+
+ debug_printf ("entering");
+ grouped.hParent = grouped.first_dll = NULL;
+ grouped.load_dlls = 0;
+
+ if (ISSTATE(myself, PID_SPLIT_HEAP))
+ {
+ system_printf ("The heap has been split, CYGWIN can't fork this process.");
+ system_printf ("Increase the heap_chunk_size in the registry and try again.");
+ set_errno (ENOMEM);
+ syscall_printf ("-1 = fork (), split heap");
+ return -1;
+ }
+
+ void *esp;
+ __asm__ volatile ("movl %%esp,%0": "=r" (esp));
+
+ myself->set_has_pgid_children ();
+
+ child_info_fork ch;
+
+ int res = setjmp (ch.jmp);
+
+ if (res)
+ res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);
+ else
+ res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, esp, ch);
+
+ MALLOC_CHECK;
+ syscall_printf ("%d = fork()", res);
+ return res;
+}
+#ifdef DEBUGGING
+void
+fork_init ()
+{
+ char buf[1024];
+ if (!GetEnvironmentVariable ("CYGWIN_FORK_PIDS", buf, 1024))
+ return;
+ pid_t pid;
+ char *p, *pe;
+ for (p = buf; (pid = strtol (p, &pe, 10)); p = pe)
+ fork_pids[npid_max++] = pid;
+}
+#endif /*DEBUGGING*/
+
+#ifdef NEWVFORK
+/* Dummy function to force second assignment below to actually be
+ carried out */
+static vfork_save *
+get_vfork_val ()
+{
+ return vfork_storage.val ();
+}
+#endif
+
+extern "C"
+int
+vfork ()
+{
+#ifndef NEWVFORK
+ return fork ();
+#else
+ sigframe thisframe;
+ vfork_save *vf = get_vfork_val ();
+ char **esp, **pp;
+
+ if (vf == NULL)
+ vf = vfork_storage.create ();
+ else if (vf->pid)
+ return fork ();
+
+ if (!setjmp (vf->j))
+ {
+ vf->pid = -1;
+ __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
+ __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
+ for (pp = (char **)vf->frame, esp = vf->vfork_esp;
+ esp <= vf->vfork_ebp + 2; pp++, esp++)
+ *pp = *esp;
+ int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
+ debug_printf ("%d = vfork()", res);
+ return res;
+ }
+
+ vf = get_vfork_val ();
+
+ for (pp = (char **)vf->frame, esp = vf->vfork_esp;
+ esp <= vf->vfork_ebp + 2; pp++, esp++)
+ *esp = *pp;
+
+ thisframe.init (mainthread);
+ cygheap->fdtab.vfork_parent_restore ();
+
+ if (vf->pid < 0)
+ {
+ int exitval = -vf->pid;
+ vf->pid = 0;
+ if ((vf->pid = fork ()) == 0)
+ exit (exitval);
+ }
+
+ int pid = vf->pid;
+ vf->pid = 0;
+ sig_dispatch_pending ();
+ return pid;
+#endif
+}
diff --git a/winsup/cygwin/include/cygwin/cygserver.h b/winsup/cygwin/include/cygwin/cygserver.h
new file mode 100755
index 00000000000..bf21e990464
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/cygserver.h
@@ -0,0 +1,126 @@
+/* cygserver.h
+
+ Copyright 2001 Red Hat Inc.
+
+ Written by Egor Duda <deo@logos-m.ru>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef _CYGSERVER_H_
+#define _CYGSERVER_H_
+
+#define MAX_REQUEST_SIZE 128
+
+#define CYGWIN_SERVER_VERSION_MAJOR 1
+#define CYGWIN_SERVER_VERSION_API 1
+#define CYGWIN_SERVER_VERSION_MINOR 0
+#define CYGWIN_SERVER_VERSION_PATCH 0
+
+
+typedef enum {
+ CYGSERVER_UNKNOWN=0,
+ CYGSERVER_OK=1,
+ CYGSERVER_DEAD=2
+} cygserver_states;
+
+typedef enum {
+ CYGSERVER_REQUEST_INVALID = 0,
+ CYGSERVER_REQUEST_GET_VERSION,
+ CYGSERVER_REQUEST_ATTACH_TTY,
+ CYGSERVER_REQUEST_SHUTDOWN,
+ CYGSERVER_REQUEST_SHM_GET,
+ CYGSERVER_REQUEST_LAST
+} cygserver_request_code;
+
+class request_header
+{
+ public:
+ ssize_t cb;
+ cygserver_request_code req_id;
+ ssize_t error_code;
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+;
+
+extern void cygserver_init ();
+
+#define INIT_REQUEST(req,id) \
+ (req).header.cb = sizeof (req); \
+ (req).header.req_id = id;
+
+struct request_get_version
+{
+ DWORD major, api, minor, patch;
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+;
+
+struct request_shutdown
+{
+ int foo;
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+;
+
+struct request_attach_tty
+{
+ DWORD pid, master_pid;
+ HANDLE from_master, to_master;
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+;
+
+class client_request
+{
+ public:
+ client_request (cygserver_request_code id);
+ virtual void send (transport_layer_base *conn);
+ virtual void serve (transport_layer_base *conn) {};
+ virtual operator struct request_header ();
+ cygserver_request_code req_id () {return header.req_id;};
+ virtual ~client_request();
+ request_header header;
+ char *buffer;
+};
+
+class client_request_get_version : public client_request
+{
+ public:
+ virtual void serve (transport_layer_base *conn);
+ client_request_get_version::client_request_get_version();
+ struct request_get_version version;
+};
+
+class client_request_shutdown : public client_request
+{
+ public:
+ virtual void serve (transport_layer_base *conn);
+ client_request_shutdown ();
+};
+
+class client_request_attach_tty : public client_request
+{
+ public:
+ virtual void serve (transport_layer_base *conn);
+ client_request_attach_tty ();
+ client_request_attach_tty (DWORD npid, DWORD nmaster_pid, HANDLE nfrom_master, HANDLE nto_master);
+ HANDLE from_master () {return req.from_master;};
+ HANDLE to_master () {return req.to_master;};
+ struct request_attach_tty req;
+};
+
+extern int cygserver_request (client_request *);
+
+#endif /* _CYGSERVER+H+ */
diff --git a/winsup/cygwin/include/cygwin/cygserver_transport.h b/winsup/cygwin/include/cygwin/cygserver_transport.h
new file mode 100755
index 00000000000..e4405d2d41f
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/cygserver_transport.h
@@ -0,0 +1,53 @@
+
+#ifndef _CYGSERVER_SHM_
+#define _CYGSERVER_SHM_
+class transport_layer_base *create_server_transport();
+
+/* the base class uses AF_UNIX sockets,but other classes are possible. */
+class transport_layer_base
+{
+ public:
+ virtual void listen ();
+ virtual class transport_layer_base * accept ();
+ virtual void close ();
+ virtual ssize_t read (char *buf, size_t len);
+ virtual ssize_t write (char *buf, size_t len);
+ virtual bool connect();
+ virtual void impersonate_client ();
+ virtual void revert_to_self ();
+ transport_layer_base ();
+
+ private:
+ /* for socket based communications */
+ int fd;
+ struct sockaddr sockdetails;
+ int sdlen;
+ transport_layer_base (int newfd);
+};
+
+/* Named pipes based transport, for security on NT */
+class transport_layer_pipes : public transport_layer_base
+{
+ public:
+ virtual void listen ();
+ virtual class transport_layer_pipes * accept ();
+ virtual void close ();
+ virtual ssize_t read (char *buf, size_t len);
+ virtual ssize_t write (char *buf, size_t len);
+ virtual bool connect();
+ virtual void impersonate_client ();
+ virtual void revert_to_self ();
+ transport_layer_pipes ();
+
+ private:
+ /* for pipe based communications */
+ void init_security ();
+ SECURITY_DESCRIPTOR sd;
+ SECURITY_ATTRIBUTES sec_none_nih, sec_all_nih;
+ char pipe_name [MAX_PATH];
+ HANDLE pipe;
+ bool inited;
+ transport_layer_pipes (HANDLE new_pipe);
+};
+
+#endif /* _CYGSERVER_SHM_ */
diff --git a/winsup/cygwin/include/sys/ipc.h b/winsup/cygwin/include/sys/ipc.h
new file mode 100644
index 00000000000..8ddec6d500d
--- /dev/null
+++ b/winsup/cygwin/include/sys/ipc.h
@@ -0,0 +1,52 @@
+/* sys/ipc.h
+
+ Copyright 2001 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 __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef _SYS_IPC_H
+#define _SYS_IPC_H
+
+/* sys/types must be included before sys/ipc.h. We aren't meant to automatically
+ * include it however
+ */
+
+struct ipc_perm {
+ uid_t uid;
+ gid_t gid;
+ uid_t cuid;
+ gid_t cgid;
+ mode_t mode;
+};
+
+/* the mode flags used with the _get functions use the low order 9 bits for a mode
+ * request
+ */
+#define IPC_CREAT 0x0200
+#define IPC_EXCL 0x0400
+#define IPC_NOWAIT 0x0800
+
+/* this is a value that will _never_ be a valid key from ftok */
+#define IPC_PRIVATE -2
+
+#define IPC_RMID 0x0003
+#define IPC_SET 0x0002
+#define IPC_STAT 0x0001
+
+key_t ftok(const char *, int);
+
+#endif /* _SYS_IPC_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/winsup/cygwin/include/sys/shm.h b/winsup/cygwin/include/sys/shm.h
new file mode 100644
index 00000000000..208c5f29f30
--- /dev/null
+++ b/winsup/cygwin/include/sys/shm.h
@@ -0,0 +1,89 @@
+/* sys/shm.h
+
+ Copyright 2001 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 __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef _SYS_SHM_H
+#define _SYS_SHM_H
+
+#include <sys/ipc.h>
+
+#define SHM_RDONLY 1
+/* 64 Kb was hardcoded for x86. MS states this may change, but we need it in the header
+ * file.
+ */
+#define SHMLBA 65536
+#define SHM_RND 1
+
+typedef long int shmatt_t;
+
+#if defined(__INSIDE_CYGWIN__) && defined(__cplusplus)
+
+class _shmattach {
+public:
+ void *data;
+ int shmflg;
+ class _shmattach *next;
+};
+
+class shmid_ds {
+public:
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ shmatt_t shm_nattch;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+ void *mapptr;
+};
+
+class shmnode {
+public:
+ class shmid_ds * shmds;
+ int shm_id;
+ class shmnode *next;
+ key_t key;
+ HANDLE filemap;
+ HANDLE attachmap;
+ class _shmattach *attachhead;
+};
+
+#else
+/* this is what we return when queried. It has no bitwise correspondence
+ * the internal structures
+ */
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ shmatt_t shm_nattch;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+};
+#endif /* __INSIDE_CYGWIN__ */
+
+void *shmat(int, const void *, int);
+int shmctl(int, int, struct shmid_ds *);
+int shmdt(const void *);
+int shmget(key_t, size_t, int);
+
+#endif /* _SYS_SHM_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/winsup/cygwin/ipc.cc b/winsup/cygwin/ipc.cc
new file mode 100644
index 00000000000..192a124d52f
--- /dev/null
+++ b/winsup/cygwin/ipc.cc
@@ -0,0 +1,39 @@
+/* ipc.cc: Single unix specification IPC interface for Cygwin
+
+ Copyright 2001 Red Hat, Inc.
+
+ Originally written by Robert Collins <robert.collins@hotmail.com>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#include "winsup.h"
+#include <sys/ipc.h>
+#include <sys/stat.h>
+
+extern "C"
+{
+
+/* Notes: we return a valid key even if id's low order 8 bits are 0. */
+key_t
+ftok(const char *path, int id)
+{
+ struct stat statbuf;
+ if (stat(path, &statbuf))
+ {
+ /* stat set the appropriate errno for us */
+ return (key_t) -1;
+ }
+
+ /* dev_t is short for cygwin
+ * ino_t is long for cygwin
+ * and we need 8 bits for the id.
+ * thus key_t is long long.
+ */
+ return ((long long) statbuf.st_dev << (5*8)) | (statbuf.st_ino << (8) ) | (id & 0x00ff);
+}
+
+}
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
new file mode 100644
index 00000000000..f62614d58f1
--- /dev/null
+++ b/winsup/cygwin/pinfo.h
@@ -0,0 +1,208 @@
+/* pinfo.h: process table info
+
+ Copyright 2000, 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. */
+
+/* Signal constants (have to define them here, unfortunately) */
+
+enum
+{
+ __SIGFLUSH = -2,
+ __SIGSTRACE = -1,
+ __SIGUNUSED = 0,
+ __SIGOFFSET = 2
+};
+
+#define PSIZE 63
+
+#include <sys/resource.h>
+#include "thread.h"
+
+class _pinfo
+{
+public:
+ /* Cygwin pid */
+ pid_t pid;
+
+ /* Various flags indicating the state of the process. See PID_
+ constants below. */
+ DWORD process_state;
+
+ /* If hProcess is set, it's because it came from a
+ CreateProcess call. This means it's process relative
+ to the thing which created the process. That's ok because
+ we only use this handle from the parent. */
+ HANDLE hProcess;
+
+#define PINFO_REDIR_SIZE ((DWORD) &(((_pinfo *)NULL)->hProcess) + sizeof (DWORD))
+
+ /* Handle associated with initial Windows pid which started it all. */
+ HANDLE pid_handle;
+
+ /* Handle to the logical parent of this pid. */
+ HANDLE ppid_handle;
+
+ /* Parent process id. */
+ pid_t ppid;
+
+ /* dwProcessId contains the processid used for sending signals. It
+ * will be reset in a child process when it is capable of receiving
+ * signals.
+ */
+ DWORD dwProcessId;
+
+ /* Used to spawn a child for fork(), among other things. */
+ char progname[MAX_PATH];
+
+ /* User information.
+ The information is derived from the GetUserName system call,
+ with the name looked up in /etc/passwd and assigned a default value
+ if not found. This data resides in the shared data area (allowing
+ tasks to store whatever they want here) so it's for informational
+ purposes only. */
+ uid_t uid; /* User ID */
+ gid_t gid; /* Group ID */
+ pid_t pgid; /* Process group ID */
+ pid_t sid; /* Session ID */
+ int ctty; /* Control tty */
+ bool has_pgid_children;/* True if we've forked or spawned children with our GID. */
+
+ /* Resources used by process. */
+ long start_time;
+ struct rusage rusage_self;
+ struct rusage rusage_children;
+
+ /* Non-zero if process was stopped by a signal. */
+ char stopsig;
+
+ void exit (UINT n, bool norecord = 0) __attribute__ ((noreturn, regparm(2)));
+
+ inline void set_has_pgid_children ()
+ {
+ if (pgid == pid)
+ has_pgid_children = 1;
+ }
+
+ inline void set_has_pgid_children (bool val) {has_pgid_children = val;}
+
+ inline struct sigaction& getsig (int sig)
+ {
+ return thread2signal ? thread2signal->sigs[sig] : sigs[sig];
+ }
+
+ inline void copysigs (_pinfo *p) {sigs = p->sigs;}
+
+ inline sigset_t& getsigmask ()
+ {
+ return thread2signal ? *thread2signal->sigmask : sig_mask;
+ }
+
+ inline void setsigmask (sigset_t mask)
+ {
+ if (thread2signal)
+ *(thread2signal->sigmask) = mask;
+ sig_mask = mask;
+ }
+
+ inline LONG* getsigtodo (int sig) {return _sigtodo + __SIGOFFSET + sig;}
+
+ inline HANDLE getthread2signal ()
+ {
+ return thread2signal ? thread2signal->win32_obj_id : hMainThread;
+ }
+
+ inline void setthread2signal (void *thr) {thread2signal = (pthread *) thr;}
+
+private:
+ struct sigaction sigs[NSIG];
+ sigset_t sig_mask; /* one set for everything to ignore. */
+ LONG _sigtodo[NSIG + __SIGOFFSET];
+ pthread *thread2signal; // NULL means means thread any other means a pthread
+};
+
+class pinfo
+{
+ HANDLE h;
+ _pinfo *procinfo;
+ int destroy;
+public:
+ void init (pid_t n, DWORD create = 0, HANDLE h = NULL) __attribute__ ((regparm(3)));
+ pinfo () {}
+ pinfo (_pinfo *x): procinfo (x) {}
+ pinfo (pid_t n) {init (n);}
+ pinfo (pid_t n, int create) {init (n, create);}
+ void release ();
+ ~pinfo ()
+ {
+ if (destroy && procinfo)
+ release ();
+ }
+
+ _pinfo *operator -> () const {return procinfo;}
+ int operator == (pinfo *x) const {return x->procinfo == procinfo;}
+ int operator == (pinfo &x) const {return x.procinfo == procinfo;}
+ int operator == (void *x) const {return procinfo == x;}
+ int operator == (int x) const {return (int) procinfo == (int) x;}
+ int operator == (char *x) const {return (char *) procinfo == x;}
+ _pinfo *operator * () const {return procinfo;}
+ operator _pinfo * () const {return procinfo;}
+ // operator bool () const {return (int) h;}
+ int remember () {destroy = 0; return proc_subproc (PROC_ADDCHILD, (DWORD) this);}
+ HANDLE shared_handle () {return h;}
+};
+
+#define ISSTATE(p, f) (!!((p)->process_state & f))
+#define NOTSTATE(p, f) (!((p)->process_state & f))
+
+class winpids
+{
+ DWORD *pidlist;
+ DWORD npidlist;
+ pinfo *pinfolist;
+ DWORD (winpids::* enum_processes) (bool winpid);
+ DWORD enum_init (bool winpid);
+ DWORD enumNT (bool winpid);
+ DWORD enum9x (bool winpid);
+ void add (DWORD& nelem, bool, DWORD pid);
+public:
+ DWORD npids;
+ inline void reset () { npids = 0; release (); }
+ void init (bool winpid);
+ winpids (int): enum_processes (&winpids::enum_init) { reset (); }
+ winpids (): pidlist (NULL), npidlist (0), pinfolist (NULL),
+ enum_processes (&winpids::enum_init), npids (0) { init (0); }
+ inline DWORD& winpid (int i) const {return pidlist[i];}
+ inline _pinfo *operator [] (int i) const {return (_pinfo *) pinfolist[i];}
+ ~winpids ();
+ void release ();
+};
+
+extern __inline pid_t
+cygwin_pid (pid_t pid)
+{
+ return (pid_t) (wincap.has_negative_pids ()) ? -(int) pid : pid;
+}
+
+void __stdcall pinfo_init (char **, int);
+void __stdcall set_myself (pid_t pid, HANDLE h = NULL);
+extern pinfo myself;
+
+#define _P_VFORK 0
+extern "C" int _spawnve (HANDLE hToken, int mode, const char *path,
+ const char *const *argv, const char *const *envp);
+
+extern void __stdcall pinfo_fixup_after_fork ();
+extern HANDLE hexec_proc;
+
+/* For mmaps across fork(). */
+int __stdcall fixup_mmaps_after_fork ();
+/* for shm areas across fork (). */
+int __stdcall fixup_shms_after_fork ();
+
+void __stdcall fill_rusage (struct rusage *, HANDLE);
+void __stdcall add_rusage (struct rusage *, struct rusage *);
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
new file mode 100644
index 00000000000..8555fe461e0
--- /dev/null
+++ b/winsup/cygwin/security.h
@@ -0,0 +1,208 @@
+/* security.h: security declarations
+
+ Copyright 2000, 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. */
+
+#define DONT_INHERIT (0)
+#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
+#define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
+
+#define DEFAULT_UID DOMAIN_USER_RID_ADMIN
+#define DEFAULT_GID DOMAIN_ALIAS_RID_ADMINS
+
+#define MAX_SID_LEN 40
+
+#define NO_SID ((PSID)NULL)
+
+class cygsid {
+ PSID psid;
+ char sbuf[MAX_SID_LEN];
+
+ const PSID getfromstr (const char *nsidstr);
+ PSID get_sid (DWORD s, DWORD cnt, DWORD *r);
+
+ inline const PSID assign (const PSID nsid)
+ {
+ if (!nsid)
+ psid = NO_SID;
+ else
+ {
+ psid = (PSID) sbuf;
+ CopySid (MAX_SID_LEN, psid, nsid);
+ }
+ return psid;
+ }
+
+public:
+ inline cygsid () : psid ((PSID) sbuf) {}
+ inline cygsid (const PSID nsid) { *this = nsid; }
+ inline cygsid (const char *nstrsid) { *this = nstrsid; }
+
+ inline PSID set () { return psid = (PSID) sbuf; }
+
+ BOOL getfrompw (const struct passwd *pw);
+ BOOL getfromgr (const struct group *gr);
+
+ int get_id (BOOL search_grp, int *type = NULL);
+ inline int get_uid () { return get_id (FALSE); }
+ inline int get_gid () { return get_id (TRUE); }
+
+ char *string (char *nsidstr) const;
+
+ inline const PSID operator= (cygsid &nsid)
+ { return assign (nsid); }
+ inline const PSID operator= (const PSID nsid)
+ { return assign (nsid); }
+ inline const PSID operator= (const char *nsidstr)
+ { return getfromstr (nsidstr); }
+
+ inline BOOL operator== (const PSID nsid) const
+ {
+ if (!psid || !nsid)
+ return nsid == psid;
+ return EqualSid (psid, nsid);
+ }
+ inline BOOL operator== (const char *nsidstr) const
+ {
+ cygsid nsid (nsidstr);
+ return *this == nsid;
+ }
+ inline BOOL operator!= (const PSID nsid) const
+ { return !(*this == nsid); }
+ inline BOOL operator!= (const char *nsidstr) const
+ { return !(*this == nsidstr); }
+
+ inline operator const PSID () { return psid; }
+
+ void debug_print (const char *prefix = NULL) const
+ {
+ char buf[256];
+ debug_printf ("%s %s", prefix ?: "", string (buf) ?: "NULL");
+ }
+};
+
+class cygsidlist {
+public:
+ int count;
+ cygsid *sids;
+
+ cygsidlist () : count (0), sids (NULL) {}
+ ~cygsidlist () { delete [] sids; }
+
+ BOOL add (cygsid &nsi)
+ {
+ cygsid *tmp = new cygsid [count + 1];
+ if (!tmp)
+ return FALSE;
+ for (int i = 0; i < count; ++i)
+ tmp[i] = sids[i];
+ delete [] sids;
+ sids = tmp;
+ sids[count++] = nsi;
+ return TRUE;
+ }
+ BOOL add (const PSID nsid) { return add (nsid); }
+ BOOL add (const char *sidstr)
+ { cygsid nsi (sidstr); return add (nsi); }
+
+ BOOL operator+= (cygsid &si) { return add (si); }
+ BOOL operator+= (const char *sidstr) { return add (sidstr); }
+
+ BOOL contains (cygsid &sid) const
+ {
+ for (int i = 0; i < count; ++i)
+ if (sids[i] == sid)
+ return TRUE;
+ return FALSE;
+ }
+ void debug_print (const char *prefix = NULL) const
+ {
+ debug_printf ("-- begin sidlist ---");
+ if (!count)
+ debug_printf ("No elements");
+ for (int i = 0; i < count; ++i)
+ sids[i].debug_print (prefix);
+ debug_printf ("-- ende sidlist ---");
+ }
+};
+
+extern cygsid well_known_null_sid;
+extern cygsid well_known_world_sid;
+extern cygsid well_known_local_sid;
+extern cygsid well_known_creator_owner_sid;
+extern cygsid well_known_dialup_sid;
+extern cygsid well_known_network_sid;
+extern cygsid well_known_batch_sid;
+extern cygsid well_known_interactive_sid;
+extern cygsid well_known_service_sid;
+extern cygsid well_known_authenticated_users_sid;
+extern cygsid well_known_system_sid;
+extern cygsid well_known_admins_sid;
+
+inline BOOL
+legal_sid_type (SID_NAME_USE type)
+{
+ return type == SidTypeUser || type == SidTypeGroup
+ || type == SidTypeAlias || type == SidTypeWellKnownGroup;
+}
+
+extern BOOL allow_ntea;
+extern BOOL allow_ntsec;
+extern BOOL allow_smbntsec;
+
+/* These both functions are needed to allow walking through the passwd
+ and group lists so they are somehow security related. Besides that
+ I didn't find a better place to declare them. */
+extern struct passwd *internal_getpwent (int);
+extern struct group *internal_getgrent (int);
+
+/* File manipulation */
+int __stdcall set_process_privileges ();
+int __stdcall get_file_attribute (int, const char *, int *,
+ uid_t * = NULL, gid_t * = NULL);
+int __stdcall set_file_attribute (int, const char *, int);
+int __stdcall set_file_attribute (int, const char *, uid_t, gid_t, int, const char *);
+LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size);
+LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size);
+BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+
+void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
+ void *sd_buf, DWORD sd_buf_size);
+
+/* Try a subauthentication. */
+HANDLE subauth (struct passwd *pw);
+/* Try creating a token directly. */
+HANDLE create_token (cygsid &usersid, cygsid &pgrpsid);
+
+/* Extract U-domain\user field from passwd entry. */
+void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
+/* Get default logonserver and domain for this box. */
+BOOL get_logon_server_and_user_domain (char *logonserver, char *domain);
+
+/* sec_helper.cc: Security helper functions. */
+BOOL __stdcall is_grp_member (uid_t uid, gid_t gid);
+/* `lookup_name' should be called instead of LookupAccountName.
+ * logsrv may be NULL, in this case only the local system is used for lookup.
+ * The buffer for ret_sid (40 Bytes) has to be allocated by the caller! */
+BOOL __stdcall lookup_name (const char *, const char *, PSID);
+int set_process_privilege (const char *privilege, BOOL enable = TRUE);
+
+/* shared.cc: */
+/* Retrieve a security descriptor that allows all access */
+SECURITY_DESCRIPTOR *__stdcall get_null_sd (void);
+
+/* Various types of security attributes for use in Create* functions. */
+extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih;
+extern SECURITY_ATTRIBUTES *__stdcall sec_user (PVOID sa_buf, PSID sid2 = NULL, BOOL inherit = TRUE);
+extern SECURITY_ATTRIBUTES *__stdcall sec_user_nih (PVOID sa_buf, PSID sid2 = NULL);
+
+int __stdcall NTReadEA (const char *file, const char *attrname, char *buf, int len);
+BOOL __stdcall NTWriteEA (const char *file, const char *attrname, const char *buf, int len);
+PSECURITY_DESCRIPTOR alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute,
+ PSECURITY_DESCRIPTOR sd_ret, DWORD *sd_size_ret);
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
new file mode 100644
index 00000000000..840c0f23ac7
--- /dev/null
+++ b/winsup/cygwin/shm.cc
@@ -0,0 +1,446 @@
+/* shm.cc: Single unix specification IPC interface for Cygwin
+
+ Copyright 2001 Red Hat, Inc.
+
+ Originally written by Robert Collins <robert.collins@hotmail.com>
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+#include "winsup.h"
+#include <sys/stat.h>
+#include <errno.h>
+#include "cygerrno.h"
+#include <unistd.h>
+#include "security.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include <stdio.h>
+#include "thread.h"
+#include <sys/shm.h>
+#include "perprocess.h"
+#include "cygserver_shm.h"
+
+// FIXME IS THIS CORRECT
+/* Implementation notes: We use two shared memory regions per key:
+ * One for the control structure, and one for the shared memory.
+ * While this has a higher overhead tham a single shared area,
+ * It allows more flexability. As the entire code is transparent to the user
+ * We can merge these in the future should it be needed.
+ */
+extern "C" size_t
+getsystemallocgranularity ()
+{
+ SYSTEM_INFO sysinfo;
+ static size_t buffer_offset = 0;
+ if (buffer_offset)
+ return buffer_offset;
+ GetSystemInfo (&sysinfo);
+ buffer_offset = sysinfo.dwAllocationGranularity;
+ return buffer_offset;
+}
+
+static shmnode *shm_head = NULL;
+
+static shmnode *
+build_inprocess_shmds (HANDLE hfilemap, HANDLE hattachmap, key_t key,
+ int shm_id)
+{
+ HANDLE filemap = hfilemap;
+ void *mapptr = MapViewOfFile (filemap, FILE_MAP_WRITE, 0, 0, 0);
+
+ if (!mapptr)
+ {
+ CloseHandle (hfilemap);
+ CloseHandle (hattachmap);
+ //FIXME: close filemap and free the mutex
+ /* we couldn't access the mapped area with the requested permissions */
+ set_errno (EACCES);
+ return NULL;
+ }
+
+ /* Now get the user data */
+ HANDLE attachmap = hattachmap;
+ shmid_ds *shmtemp = new shmid_ds;
+ if (!shmtemp)
+ {
+ system_printf ("failed to malloc shm node\n");
+ set_errno (ENOMEM);
+ UnmapViewOfFile (mapptr);
+ CloseHandle (filemap);
+ CloseHandle (attachmap);
+ /* exit mutex */
+ return NULL;
+ }
+
+ /* get the system node data */
+ *shmtemp = *(shmid_ds *) mapptr;
+
+ /* process local data */
+ shmnode *tempnode = new shmnode;
+
+ tempnode->filemap = filemap;
+ tempnode->attachmap = attachmap;
+ shmtemp->mapptr = mapptr;
+
+ /* no need for InterlockedExchange here, we're serialised by the global mutex */
+ tempnode->shmds = shmtemp;
+ tempnode->shm_id = shm_id;
+ tempnode->key = key;
+ tempnode->next = shm_head;
+ tempnode->attachhead = NULL;
+ shm_head = tempnode;
+
+ /* FIXME: leave the system wide shm mutex */
+
+ return tempnode;
+}
+
+int __stdcall
+fixup_shms_after_fork ()
+{
+ shmnode *tempnode = shm_head;
+ while (tempnode)
+ {
+ void *newshmds =
+ MapViewOfFile (tempnode->filemap, FILE_MAP_WRITE, 0, 0, 0);
+ if (!newshmds)
+ {
+ /* don't worry about handle cleanup, we're dying! */
+ system_printf("failed to reattach to shm control file view %x\n",tempnode);
+ return 1;
+ }
+ tempnode->shmds = (class shmid_ds *) newshmds;
+ tempnode->shmds->mapptr = newshmds;
+ _shmattach *attachnode = tempnode->attachhead;
+ while (attachnode)
+ {
+ void *newdata = MapViewOfFileEx (tempnode->attachmap,
+ (attachnode->shmflg & SHM_RDONLY) ?
+ FILE_MAP_READ : FILE_MAP_WRITE, 0,
+ 0, 0, attachnode->data);
+ if (newdata != attachnode->data)
+ {
+ /* don't worry about handle cleanup, we're dying! */
+ system_printf("failed to reattach to mapped file view %x\n",attachnode->data);
+ return 1;
+ }
+ attachnode = attachnode->next;
+ }
+ tempnode = tempnode->next;
+ }
+ return 0;
+}
+
+/* this is ugly. Yes, I know that.
+ * FIXME: abstract the lookup functionality,
+ * So that it can be an array, list, whatever without us being worried
+ */
+
+/* FIXME: after fork, every memory area needs to have the attach count
+ * incremented and the mappings potentially reestablished, perhaps allowing
+ * inherit will work?!?
+ */
+
+/* FIXME: are inherited mapped IPC_PRIVATE id's shared between process's
+ * YES from linux.
+ */
+
+extern "C" void *
+shmat (int shmid, const void *shmaddr, int shmflg)
+{
+ shmnode *tempnode = shm_head;
+ while (tempnode && tempnode->shm_id != shmid)
+ tempnode = tempnode->next;
+
+ if (!tempnode)
+ {
+ /* couldn't find a currently open shm control area for the key - probably because
+ * shmget hasn't been called.
+ * Allocate a new control block - this has to be handled by the daemon */
+ client_request_shm_get *req =
+ new client_request_shm_get (shmid, GetCurrentProcessId ());
+
+ int rc;
+ if ((rc = cygserver_request (req)))
+ {
+ delete req;
+ set_errno (ENOSYS); /* daemon communication failed */
+ return (void *) -1;
+ }
+
+ if (req->header.error_code) /* shm_get failed in the daemon */
+ {
+ set_errno (req->header.error_code);
+ delete req;
+ return (void *) -1;
+ }
+
+ /* we've got the id, now we open the memory area ourselves.
+ * This tests security automagically
+ * FIXME: make this a method of shmnode ?
+ */
+ tempnode =
+ build_inprocess_shmds (req->parameters.out.filemap,
+ req->parameters.out.attachmap,
+ req->parameters.out.key,
+ req->parameters.out.shm_id);
+ delete req;
+ if (!tempnode)
+ return (void *) -1;
+
+ }
+
+ class shmid_ds *shm = tempnode->shmds;
+
+ if (shmaddr)
+ {
+ //FIXME: requested base address ?! (Don't forget to fix the fixup_after_fork too)
+ set_errno (EINVAL);
+ return (void *) -1;
+ }
+
+ void *rv = MapViewOfFile (tempnode->attachmap,
+ (shmflg & SHM_RDONLY) ? FILE_MAP_READ :
+ FILE_MAP_WRITE, 0, 0, 0);
+
+ if (!rv)
+ {
+ //FIXME: translate GetLastError()
+ set_errno (EACCES);
+ return (void *) -1;
+ }
+
+ InterlockedIncrement (&shm->shm_nattch);
+ _shmattach *attachnode = new _shmattach;
+
+ attachnode->data = rv;
+ attachnode->shmflg = shmflg;
+ attachnode->next =
+ (_shmattach *) InterlockedExchangePointer (&tempnode->attachhead, attachnode);
+
+
+ return rv;
+}
+
+//FIXME: who is allowed to perform STAT?
+extern "C" int
+shmctl (int shmid, int cmd, struct shmid_ds *buf)
+{
+ shmnode *tempnode = shm_head;
+ while (tempnode && tempnode->shm_id != shmid)
+ tempnode = tempnode->next;
+ if (!tempnode)
+ {
+ /* couldn't find a currently open shm control area for the key - probably because
+ * shmget hasn't been called.
+ * Allocate a new control block - this has to be handled by the daemon */
+ client_request_shm_get *req =
+ new client_request_shm_get (shmid, GetCurrentProcessId ());
+
+ int rc;
+ if ((rc = cygserver_request (req)))
+ {
+ delete req;
+ set_errno (ENOSYS); /* daemon communication failed */
+ return -1;
+ }
+
+ if (req->header.error_code) /* shm_get failed in the daemon */
+ {
+ set_errno (req->header.error_code);
+ delete req;
+ return -1;
+ }
+
+ /* we've got the id, now we open the memory area ourselves.
+ * This tests security automagically
+ * FIXME: make this a method of shmnode ?
+ */
+ tempnode =
+ build_inprocess_shmds (req->parameters.out.filemap,
+ req->parameters.out.attachmap,
+ req->parameters.out.key,
+ req->parameters.out.shm_id);
+ delete req;
+ if (!tempnode)
+ return -1;
+ }
+
+ switch (cmd)
+ {
+ case IPC_STAT:
+ buf->shm_perm = tempnode->shmds->shm_perm;
+ buf->shm_segsz = tempnode->shmds->shm_segsz;
+ buf->shm_lpid = tempnode->shmds->shm_lpid;
+ buf->shm_cpid = tempnode->shmds->shm_cpid;
+ buf->shm_nattch = tempnode->shmds->shm_nattch;
+ buf->shm_atime = tempnode->shmds->shm_atime;
+ buf->shm_dtime = tempnode->shmds->shm_dtime;
+ buf->shm_ctime = tempnode->shmds->shm_ctime;
+ break;
+ case IPC_RMID:
+ {
+ /* TODO: check permissions. Or possibly, the daemon gets to be the only
+ * one with write access to the memory area?
+ */
+ if (tempnode->shmds->shm_nattch)
+ system_printf ("call to shmctl with cmd= IPC_RMID when memory area still has"
+ " attachees\n");
+ /* how does this work?
+ * we mark the ds area as "deleted", and the at and get calls all fail from now on
+ * on, when nattch becomes 0, the mapped data area is destroyed.
+ * and each process, as they touch this area detaches. eventually only the
+ * daemon has an attach. The daemon gets asked to detach immediately.
+ */
+#if 0
+ client_request_shm_get *req =
+ new client_request_shm_get (SHM_DEL, shmid, GetCurrentProcessId ());
+ int rc;
+ if ((rc = cygserver_request (req)))
+ {
+ delete req;
+ set_errno (ENOSYS); /* daemon communication failed */
+ return -1;
+ }
+
+ if (req->header.error_code) /* shm_del failed in the daemon */
+ {
+ set_errno (req->header.error_code);
+ delete req;
+ return -1;
+ }
+
+ /* the daemon has deleted it's references */
+ /* now for us */
+#endif
+}
+ break;
+ case IPC_SET:
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+ return 0;
+}
+
+/* FIXME: evaluate getuid() and getgid() against the requested mode. Then
+ * choose PAGE_READWRITE | PAGE_READONLY and FILE_MAP_WRITE | FILE_MAP_READ
+ * appropriately
+ */
+
+/* Test result from openbsd: shm ids are persistent cross process if a handle is left
+ * open. This could lead to resource starvation: we're not copying that behaviour
+ * unless we have to. (It will involve acygwin1.dll gloal shared list :[ ).
+ */
+/* FIXME: shmid should be a verifyable object
+ */
+
+/* FIXME: on NT we should check everything against the SD. On 95 we just emulate.
+ */
+extern "C" int
+shmget (key_t key, size_t size, int shmflg)
+{
+ DWORD sd_size = 4096;
+ char sd_buf[4096];
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
+ /* create a sd for our open requests based on shmflag & 0x01ff */
+ psd = alloc_sd (getuid (), getgid (), cygheap->user.logsrv (),
+ shmflg & 0x01ff, psd, &sd_size);
+
+ if (key == (key_t) - 1)
+ {
+ set_errno (ENOENT);
+ return -1;
+ }
+
+ /* FIXME: enter the checking for existing keys mutex. This mutex _must_ be system wide
+ * to prevent races on shmget.
+ */
+
+ /* walk the list of currently open keys and return the id if found
+ */
+ shmnode *tempnode = shm_head;
+ while (tempnode)
+ {
+ if (tempnode->key == key && key != IPC_PRIVATE)
+ {
+ // FIXME: free the mutex
+ if (size && tempnode->shmds->shm_segsz < size)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL))
+ {
+ set_errno (EEXIST);
+ // FIXME: free the mutex
+ return -1;
+ }
+ // FIXME: do we need to other tests of the requested mode with the
+ // tempnode->shmid mode ? testcase on unix needed.
+ // FIXME do we need a security test? We are only examining the keys we already have open.
+ // FIXME: what are the sec implications for fork () if we don't check here?
+ return tempnode->shm_id;
+ }
+ tempnode = tempnode->next;
+ }
+ /* couldn't find a currently open shm control area for the key.
+ * Allocate a new control block - this has to be handled by the daemon */
+ client_request_shm_get *req =
+ new client_request_shm_get (key, size, shmflg, sd_buf,
+ GetCurrentProcessId ());
+
+ int rc;
+ if ((rc = cygserver_request (req)))
+ {
+ delete req;
+ set_errno (ENOSYS); /* daemon communication failed */
+ return -1;
+ }
+
+ if (req->header.error_code) /* shm_get failed in the daemon */
+ {
+ set_errno (req->header.error_code);
+ delete req;
+ return -1;
+ }
+
+ /* we've got the id, now we open the memory area ourselves.
+ * This tests security automagically
+ * FIXME: make this a method of shmnode ?
+ */
+ shmnode *shmtemp = build_inprocess_shmds (req->parameters.out.filemap,
+ req->parameters.out.attachmap,
+ key,
+ req->parameters.out.shm_id);
+ delete req;
+ if (shmtemp)
+ return shmtemp->shm_id;
+ return -1;
+
+
+#if 0
+ /* fill out the node data */
+ shmtemp->shm_perm.cuid = getuid ();
+ shmtemp->shm_perm.uid = shmtemp->shm_perm.cuid;
+ shmtemp->shm_perm.cgid = getgid ();
+ shmtemp->shm_perm.gid = shmtemp->shm_perm.cgid;
+ shmtemp->shm_perm.mode = shmflg & 0x01ff;
+ shmtemp->shm_lpid = 0;
+ shmtemp->shm_nattch = 0;
+ shmtemp->shm_atime = 0;
+ shmtemp->shm_dtime = 0;
+ shmtemp->shm_ctime = time (NULL);
+ shmtemp->shm_segsz = size;
+ *(shmid_ds *) mapptr = *shmtemp;
+ shmtemp->filemap = filemap;
+ shmtemp->attachmap = attachmap;
+ shmtemp->mapptr = mapptr;
+
+#endif
+}
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
new file mode 100644
index 00000000000..baa05cd6212
--- /dev/null
+++ b/winsup/cygwin/tty.cc
@@ -0,0 +1,447 @@
+/* tty.cc
+
+ Copyright 1997, 1998, 2000, 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. */
+
+#include "winsup.h"
+#include <errno.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include <sys/cygwin.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include <sys/socket.h>
+#include "cygwin/cygserver_transport.h"
+#include "cygwin/cygserver.h"
+#include "shared_info.h"
+
+extern fhandler_tty_master *tty_master;
+
+extern "C"
+int
+grantpt (int fd)
+{
+ return 0;
+}
+
+extern "C"
+int
+unlockpt (int fd)
+{
+ return 0;
+}
+
+extern "C"
+int
+ttyslot (void)
+{
+ if (NOTSTATE (myself, PID_USETTY))
+ return -1;
+ return myself->ctty;
+}
+
+void __stdcall
+tty_init (void)
+{
+ if (NOTSTATE (myself, PID_USETTY))
+ return;
+ if (myself->ctty == -1)
+ if (NOTSTATE (myself, PID_CYGPARENT))
+ myself->ctty = attach_tty (myself->ctty);
+ else
+ return;
+ if (myself->ctty == -1)
+ termios_printf ("Can't attach to tty");
+}
+
+/* Create session's master tty */
+
+void __stdcall
+create_tty_master (int ttynum)
+{
+ tty_master = (fhandler_tty_master *) cygheap->fdtab.build_fhandler (-1, FH_TTYM,
+ "/dev/ttym", ttynum);
+ if (tty_master->init (ttynum))
+ api_fatal ("Can't create master tty");
+ else
+ {
+ /* Log utmp entry */
+ struct utmp our_utmp;
+
+ bzero ((char *) &our_utmp, sizeof (utmp));
+ (void) time (&our_utmp.ut_time);
+ strncpy (our_utmp.ut_name, getlogin (), sizeof (our_utmp.ut_name));
+ cygwin_gethostname (our_utmp.ut_host, sizeof (our_utmp.ut_host));
+ __small_sprintf (our_utmp.ut_line, "tty%d", ttynum);
+ our_utmp.ut_type = USER_PROCESS;
+ myself->ctty = ttynum;
+ login (&our_utmp);
+ }
+}
+
+void __stdcall
+tty_terminate (void)
+{
+ if (NOTSTATE (myself, PID_USETTY))
+ return;
+ cygwin_shared->tty.terminate ();
+}
+
+int __stdcall
+attach_tty (int num)
+{
+ if (num != -1)
+ {
+ return cygwin_shared->tty.connect_tty (num);
+ }
+ if (NOTSTATE (myself, PID_USETTY))
+ return -1;
+ return cygwin_shared->tty.allocate_tty (1);
+}
+
+void
+tty_list::terminate (void)
+{
+ int ttynum = myself->ctty;
+
+ /* Keep master running till there are connected clients */
+ if (ttynum != -1 && ttys[ttynum].master_pid == GetCurrentProcessId ())
+ {
+ tty *t = ttys + ttynum;
+ CloseHandle (t->from_master);
+ CloseHandle (t->to_master);
+ /* Wait for children which rely on tty handling in this process to
+ go away */
+ for (int i = 0; ; i++)
+ {
+ if (!t->slave_alive ())
+ break;
+ if (i >= 100)
+ {
+ small_printf ("waiting for children using tty%d to terminate\n",
+ ttynum);
+ i = 0;
+ }
+
+ Sleep (200);
+ }
+
+ termios_printf ("tty %d master about to finish", ttynum);
+ ForceCloseHandle1 (t->to_slave, to_pty);
+ ForceCloseHandle1 (t->from_slave, from_pty);
+ CloseHandle (tty_master->inuse);
+ WaitForSingleObject (tty_master->hThread, INFINITE);
+ t->init ();
+
+ char buf[20];
+ __small_sprintf (buf, "tty%d", ttynum);
+ logout (buf);
+ }
+}
+
+int
+tty_list::connect_tty (int ttynum)
+{
+ if (ttynum < 0 || ttynum >= NTTYS)
+ {
+ termios_printf ("ttynum (%d) out of range", ttynum);
+ return -1;
+ }
+ if (!ttys[ttynum].exists ())
+ {
+ termios_printf ("tty %d was not allocated", ttynum);
+ return -1;
+ }
+
+ return ttynum;
+}
+
+void
+tty_list::init (void)
+{
+ for (int i = 0; i < NTTYS; i++)
+ {
+ ttys[i].init ();
+ ttys[i].setntty (i);
+ }
+}
+
+/* Search for tty class for our console. Allocate new tty if our process is
+ the only cygwin process in the current console.
+ Return tty number or -1 if error.
+ If flag == 0, just find a free tty.
+ */
+int
+tty_list::allocate_tty (int with_console)
+{
+ HWND console;
+
+ /* FIXME: This whole function needs a protective mutex. */
+
+ if (!with_console)
+ console = NULL;
+ else
+ {
+ char *oldtitle = new char [TITLESIZE];
+
+ if (!oldtitle)
+ {
+ termios_printf ("Can't *allocate console title buffer");
+ return -1;
+ }
+ if (!GetConsoleTitle (oldtitle, TITLESIZE))
+ {
+ termios_printf ("Can't read console title");
+ return -1;
+ }
+
+ if (WaitForSingleObject (title_mutex, INFINITE) == WAIT_FAILED)
+ termios_printf ("WFSO for title_mutext %p failed, %E", title_mutex);
+
+ char buf[40];
+
+ __small_sprintf (buf, "cygwin.find.console.%d", myself->pid);
+ SetConsoleTitle (buf);
+ Sleep (40);
+ console = FindWindow (NULL, buf);
+ SetConsoleTitle (oldtitle);
+ Sleep (40);
+ ReleaseMutex (title_mutex);
+ if (console == NULL)
+ {
+ termios_printf ("Can't find console window");
+ return -1;
+ }
+ }
+ /* Is a tty allocated for console? */
+
+ int freetty = -1;
+ for (int i = 0; i < NTTYS; i++)
+ {
+ if (!ttys[i].exists ())
+ {
+ if (freetty < 0) /* Scanning? */
+ freetty = i; /* Yes. */
+ if (!with_console) /* Do we want to attach this to a console? */
+ break; /* No. We've got one. */
+ }
+
+ if (with_console && ttys[i].gethwnd () == console)
+ {
+ termios_printf ("console %x already associated with tty%d",
+ console, i);
+ /* Is the master alive? */
+ HANDLE hMaster;
+ hMaster = OpenProcess (PROCESS_DUP_HANDLE, FALSE, ttys[i].master_pid);
+ if (hMaster)
+ {
+ CloseHandle (hMaster);
+ return i;
+ }
+ /* Master is dead */
+ freetty = i;
+ break;
+ }
+ }
+
+ /* There is no tty allocated to console, allocate the first free found */
+ if (freetty == -1)
+ {
+ system_printf ("No free ttys available");
+ return -1;
+ }
+ tty *t = ttys + freetty;
+ t->init ();
+ t->setsid (-1);
+ t->setpgid (myself->pgid);
+ t->sethwnd (console);
+
+ if (with_console)
+ {
+ termios_printf ("console %x associated with tty%d", console, freetty);
+ create_tty_master (freetty);
+ }
+ else
+ termios_printf ("tty%d allocated", freetty);
+ return freetty;
+}
+
+BOOL
+tty::slave_alive ()
+{
+ return alive (TTY_SLAVE_ALIVE);
+}
+
+BOOL
+tty::master_alive ()
+{
+ return alive (TTY_MASTER_ALIVE);
+}
+
+BOOL
+tty::alive (const char *fmt)
+{
+ HANDLE ev;
+ char buf[sizeof (TTY_MASTER_ALIVE) + 16];
+
+ __small_sprintf (buf, fmt, ntty);
+ if ((ev = OpenEvent (EVENT_ALL_ACCESS, FALSE, buf)))
+ CloseHandle (ev);
+ return ev != NULL;
+}
+
+HANDLE
+tty::create_inuse (const char *fmt)
+{
+ HANDLE h;
+ char buf[sizeof (TTY_MASTER_ALIVE) + 16];
+
+ __small_sprintf (buf, fmt, ntty);
+ h = CreateEvent (&sec_all, TRUE, FALSE, buf);
+ termios_printf ("%s = %p", buf, h);
+ if (!h)
+ termios_printf ("couldn't open inuse event, %E", buf);
+ return h;
+}
+
+void
+tty::init (void)
+{
+ output_stopped = 0;
+ setsid (0);
+ pgid = 0;
+ hwnd = NULL;
+ to_slave = NULL;
+ from_slave = NULL;
+ was_opened = 0;
+}
+
+HANDLE
+tty::get_event (const char *fmt, BOOL manual_reset)
+{
+ HANDLE hev;
+ char buf[40];
+
+ __small_sprintf (buf, fmt, ntty);
+ if (!(hev = CreateEvent (&sec_all, manual_reset, FALSE, buf)))
+ {
+ termios_printf ("couldn't create %s", buf);
+ set_errno (ENOENT); /* FIXME this can't be the right errno */
+ return NULL;
+ }
+
+ termios_printf ("created event %s", buf);
+ return hev;
+}
+
+int
+tty::make_pipes (fhandler_pty_master *ptym)
+{
+ /* Create communication pipes */
+
+ /* FIXME: should this be sec_none_nih? */
+ if (CreatePipe (&from_master, &to_slave, &sec_all, 0) == FALSE)
+ {
+ termios_printf ("can't create input pipe");
+ set_errno (ENOENT);
+ return FALSE;
+ }
+
+ ProtectHandle1 (to_slave, to_pty);
+ if (CreatePipe (&from_slave, &to_master, &sec_all, 0) == FALSE)
+ {
+ termios_printf ("can't create output pipe");
+ set_errno (ENOENT);
+ return FALSE;
+ }
+ ProtectHandle1 (from_slave, from_pty);
+ termios_printf ("tty%d from_slave %p, to_slave %p", ntty, from_slave,
+ to_slave);
+
+ DWORD pipe_mode = PIPE_NOWAIT;
+ if (!SetNamedPipeHandleState (to_slave, &pipe_mode, NULL, NULL))
+ termios_printf ("can't set to_slave to non-blocking mode");
+ ptym->set_io_handle (from_slave);
+ ptym->set_output_handle (to_slave);
+ return TRUE;
+}
+
+BOOL
+tty::common_init (fhandler_pty_master *ptym)
+{
+ /* Set termios information. Force initialization. */
+ ptym->tcinit (this, TRUE);
+
+ if (!make_pipes (ptym))
+ return FALSE;
+ ptym->need_nl = 0;
+
+ /* Save our pid */
+
+ master_pid = GetCurrentProcessId ();
+
+ /* Allow the others to open us (for handle duplication) */
+
+ if (wincap.has_security () && cygserver_running==CYGSERVER_OK &&
+ (SetKernelObjectSecurity (hMainProc, DACL_SECURITY_INFORMATION,
+ get_null_sd ()) == FALSE))
+ small_printf ("Can't set process security, %E");
+
+ /* Create synchronisation events */
+
+ if (ptym->get_device () != FH_TTYM)
+ {
+ ptym->output_done_event = ptym->ioctl_done_event =
+ ptym->ioctl_request_event = NULL;
+ }
+ else
+ {
+ if (!(ptym->output_done_event = get_event (OUTPUT_DONE_EVENT)))
+ return FALSE;
+ if (!(ptym->ioctl_done_event = get_event (IOCTL_DONE_EVENT)))
+ return FALSE;
+ if (!(ptym->ioctl_request_event = get_event (IOCTL_REQUEST_EVENT)))
+ return FALSE;
+ }
+
+ if (!(ptym->input_available_event = get_event (INPUT_AVAILABLE_EVENT, TRUE)))
+ return FALSE;
+
+ char buf[40];
+ __small_sprintf (buf, OUTPUT_MUTEX, ntty);
+ if (!(ptym->output_mutex = CreateMutex (&sec_all, FALSE, buf)))
+ {
+ termios_printf ("can't create %s", buf);
+ set_errno (ENOENT);
+ return FALSE;
+ }
+
+ __small_sprintf (buf, INPUT_MUTEX, ntty);
+ if (!(ptym->input_mutex = CreateMutex (&sec_all, FALSE, buf)))
+ {
+ termios_printf ("can't create %s", buf);
+ set_errno (ENOENT);
+ return FALSE;
+ }
+
+ ProtectHandle1 (ptym->output_mutex, output_mutex);
+ ProtectHandle1 (ptym->input_mutex, input_mutex);
+ winsize.ws_col = 80;
+ winsize.ws_row = 25;
+
+ termios_printf ("tty%d opened", ntty);
+ return TRUE;
+}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
new file mode 100644
index 00000000000..e40dfb68a20
--- /dev/null
+++ b/winsup/cygwin/winsup.h
@@ -0,0 +1,261 @@
+/* winsup.h: main Cygwin header file.
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 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. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define __INSIDE_CYGWIN__
+
+#define alloca __builtin_alloca
+#define strlen __builtin_strlen
+#define strcmp __builtin_strcmp
+#define strcpy __builtin_strcpy
+#define memcpy __builtin_memcpy
+#define memcmp __builtin_memcmp
+#ifdef HAVE_BUILTIN_MEMSET
+# define memset __builtin_memset
+#endif
+
+#define NO_COPY __attribute__((section(".data_cygwin_nocopy")))
+
+#ifdef __cplusplus
+
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L
+#define NEW_MACRO_VARARGS
+#endif
+
+#include <sys/types.h>
+#include <sys/strace.h>
+
+extern const char case_folded_lower[];
+#define cyg_tolower(c) (case_folded_lower[(unsigned char)(c)])
+extern const char case_folded_upper[];
+#define cyg_toupper(c) (case_folded_upper[(unsigned char)(c)])
+
+#ifndef MALLOC_DEBUG
+#define cfree newlib_cfree_dont_use
+#endif
+
+#define WIN32_LEAN_AND_MEAN 1
+#define _WINGDI_H
+#define _WINUSER_H
+#define _WINNLS_H
+#define _WINVER_H
+#define _WINNETWK_H
+#define _WINSVC_H
+#include <windows.h>
+#include <wincrypt.h>
+#include <lmcons.h>
+#undef _WINGDI_H
+#undef _WINUSER_H
+#undef _WINNLS_H
+#undef _WINVER_H
+#undef _WINNETWK_H
+#undef _WINSVC_H
+
+#include "wincap.h"
+
+/* The one function we use from winuser.h most of the time */
+extern "C" DWORD WINAPI GetLastError (void);
+
+enum codepage_type {ansi_cp, oem_cp};
+extern codepage_type current_codepage;
+
+extern int cygserver_running;
+
+/* Used to check if Cygwin DLL is dynamically loaded. */
+extern int dynamically_loaded;
+
+#define sys_wcstombs(tgt,src,len) \
+ WideCharToMultiByte((current_codepage==ansi_cp?CP_ACP:CP_OEMCP),0,(src),-1,(tgt),(len),NULL,NULL)
+#define sys_mbstowcs(tgt,src,len) \
+ MultiByteToWideChar((current_codepage==ansi_cp?CP_ACP:CP_OEMCP),0,(src),-1,(tgt),(len))
+
+#define TITLESIZE 1024
+
+/* status bit manipulation */
+#define __ISSETF(what, x, prefix) \
+ ((what)->status & prefix##_##x)
+#define __SETF(what, x, prefix) \
+ ((what)->status |= prefix##_##x)
+#define __CLEARF(what, x, prefix) \
+ ((what)->status &= ~prefix##_##x)
+#define __CONDSETF(n, what, x, prefix) \
+ ((n) ? __SETF (what, x, prefix) : __CLEARF (what, x, prefix))
+
+#include "debug.h"
+
+/* Events/mutexes */
+extern HANDLE title_mutex;
+
+/**************************** Convenience ******************************/
+
+/* Used when treating / and \ as equivalent. */
+#define SLASH_P(ch) \
+ ({ \
+ char __c = (ch); \
+ ((__c) == '/' || (__c) == '\\'); \
+ })
+
+/* Convert a signal to a signal mask */
+#define SIGTOMASK(sig) (1<<((sig) - signal_shift_subtract))
+extern unsigned int signal_shift_subtract;
+
+#ifdef NEW_MACRO_VARARGS
+# define api_fatal(...) __api_fatal ("%P: *** " __VA_ARGS__)
+#else
+# define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args)
+#endif
+
+#undef issep
+#define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
+
+#define isdirsep SLASH_P
+#define isabspath(p) \
+ (isdirsep (*(p)) || (isalpha (*(p)) && (p)[1] == ':' && (!(p)[2] || isdirsep ((p)[2]))))
+
+/******************** Initialization/Termination **********************/
+
+class per_process;
+/* cygwin .dll initialization */
+void dll_crt0 (per_process *) __asm__ ("_dll_crt0__FP11per_process");
+extern "C" void __stdcall _dll_crt0 ();
+
+/* dynamically loaded dll initialization */
+extern "C" int dll_dllcrt0 (HMODULE, per_process *);
+
+/* dynamically loaded dll initialization for non-cygwin apps */
+extern "C" int dll_noncygwin_dllcrt0 (HMODULE, per_process *);
+
+/* exit the program */
+extern "C" void __stdcall do_exit (int) __attribute__ ((noreturn));
+
+/* UID/GID */
+void uinfo_init (void);
+
+/* various events */
+void events_init (void);
+void events_terminate (void);
+
+void __stdcall close_all_files (void);
+
+/* Invisible window initialization/termination. */
+HWND __stdcall gethwnd (void);
+void __stdcall window_terminate (void);
+
+/* Globals that handle initialization of winsock in a child process. */
+extern HANDLE wsock32_handle;
+extern HANDLE ws2_32_handle;
+
+/* Globals that handle initialization of netapi in a child process. */
+extern HANDLE netapi32_handle;
+
+/* debug_on_trap support. see exceptions.cc:try_to_debug() */
+extern "C" void error_start_init (const char*);
+extern "C" int try_to_debug (bool waitloop = 1);
+
+void set_file_api_mode (codepage_type);
+
+extern int cygwin_finished_initializing;
+
+/**************************** Miscellaneous ******************************/
+
+void __stdcall set_std_handle (int);
+int __stdcall writable_directory (const char *file);
+int __stdcall stat_dev (DWORD, int, unsigned long, struct stat *);
+extern BOOL allow_ntsec;
+
+unsigned long __stdcall hash_path_name (unsigned long hash, const char *name) __attribute__ ((regparm(2)));
+void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2)));
+extern "C" char *__stdcall rootdir (char *full_path) __attribute__ ((regparm(1)));
+
+/* String manipulation */
+extern "C" char *__stdcall strccpy (char *s1, const char **s2, char c);
+extern "C" int __stdcall strcasematch (const char *s1, const char *s2) __attribute__ ((regparm(2)));
+extern "C" int __stdcall strncasematch (const char *s1, const char *s2, size_t n) __attribute__ ((regparm(3)));
+extern "C" char *__stdcall strcasestr (const char *searchee, const char *lookfor) __attribute__ ((regparm(2)));
+
+/* Time related */
+void __stdcall totimeval (struct timeval *dst, FILETIME * src, int sub, int flag);
+long __stdcall to_time_t (FILETIME * ptr);
+
+void __stdcall set_console_title (char *);
+void set_console_handler ();
+
+int __stdcall check_null_empty_str (const char *name) __attribute__ ((regparm(1)));
+int __stdcall check_null_empty_str_errno (const char *name) __attribute__ ((regparm(1)));
+int __stdcall __check_null_invalid_struct (const void *s, unsigned sz) __attribute__ ((regparm(1)));
+int __stdcall __check_null_invalid_struct_errno (const void *s, unsigned sz) __attribute__ ((regparm(1)));
+
+#define check_null_invalid_struct(s) \
+ __check_null_invalid ((s), sizeof (*(s)))
+#define check_null_invalid_struct_errno(s) \
+ __check_null_invalid_struct_errno ((s), sizeof (*(s)))
+
+#define set_winsock_errno() __set_winsock_errno (__FUNCTION__, __LINE__)
+void __set_winsock_errno (const char *fn, int ln) __attribute__ ((regparm(2)));
+
+extern bool wsock_started;
+
+/* Printf type functions */
+extern "C" void __api_fatal (const char *, ...) __attribute__ ((noreturn));
+extern "C" int __small_sprintf (char *dst, const char *fmt, ...) /*__attribute__ ((regparm (2)))*/;
+extern "C" int __small_vsprintf (char *dst, const char *fmt, va_list ap) /*__attribute__ ((regparm (3)))*/;
+
+extern "C" void __malloc_lock (struct _reent *);
+extern "C" void __malloc_unlock (struct _reent *);
+
+extern "C" void __malloc_lock (struct _reent *);
+extern "C" void __malloc_unlock (struct _reent *);
+
+/**************************** Exports ******************************/
+
+extern "C" {
+int cygwin_select (int , fd_set *, fd_set *, fd_set *,
+ struct timeval *to);
+int cygwin_gethostname (char *__name, size_t __len);
+
+int kill_pgrp (pid_t, int);
+int _kill (int, int);
+int _raise (int sig);
+
+extern DWORD binmode;
+extern char _data_start__, _data_end__, _bss_start__, _bss_end__;
+extern void (*__CTOR_LIST__) (void);
+extern void (*__DTOR_LIST__) (void);
+extern SYSTEM_INFO system_info;
+};
+
+/*************************** Unsorted ******************************/
+
+#define WM_ASYNCIO 0x8000 // WM_APP
+
+/* Note that MAX_PATH is defined in the windows headers */
+/* There is also PATH_MAX and MAXPATHLEN.
+ PATH_MAX is from Posix and does *not* include the trailing NUL.
+ MAXPATHLEN is from Unix.
+
+ Thou shalt use MAX_PATH throughout. It avoids the NUL vs no-NUL
+ issue and is neither of the Unixy ones [so we can punt on which
+ one is the right one to use]. */
+
+#define STD_RBITS (S_IRUSR | S_IRGRP | S_IROTH)
+#define STD_WBITS (S_IWUSR)
+#define STD_XBITS (S_IXUSR | S_IXGRP | S_IXOTH)
+
+/* The title on program start. */
+extern char *old_title;
+extern BOOL display_title;
+
+extern HANDLE hMainThread;
+extern HANDLE hMainProc;
+
+#endif /* defined __cplusplus */