diff options
author | cvs2svn <> | 2002-01-02 03:06:36 +0300 |
---|---|---|
committer | cvs2svn <> | 2002-01-02 03:06:36 +0300 |
commit | 9783ce28caf426c5ab39d1d6aefa31cfdb1b8234 (patch) | |
tree | 4bac6085e7b0a39a0eb017a135fee30dadc49b16 | |
parent | 10caff1aadd69ebe7fbfba162dd23f6b2dc8b5a4 (diff) |
This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.
Cherrypick from master 2002-01-02 00:06:35 UTC Christopher Faylor <me@cgf.cx> '* speclib: Remove temp files automatically.':
winsup/cygwin/ChangeLog-2001
winsup/cygwin/cygmagic
winsup/cygwin/fhandler_disk_file.cc
winsup/cygwin/how-fhandlers-work.txt
winsup/cygwin/newsym
winsup/cygwin/regex/COPYRIGHT
winsup/cygwin/regex/cclass.h
winsup/cygwin/regex/cname.h
winsup/cygwin/regex/engine.c
winsup/cygwin/regex/engine.ih
winsup/cygwin/regex/mkh
winsup/cygwin/regex/regcomp.c
winsup/cygwin/regex/regcomp.ih
winsup/cygwin/regex/regerror.c
winsup/cygwin/regex/regerror.ih
winsup/cygwin/regex/regex.3
winsup/cygwin/regex/regex.7
winsup/cygwin/regex/regex.h
winsup/cygwin/regex/regex2.h
winsup/cygwin/regex/regexec.c
winsup/cygwin/regex/regfree.c
winsup/cygwin/regex/tests
winsup/cygwin/regex/utils.h
winsup/cygwin/regexp/v8_regerror.c
winsup/cygwin/regexp/v8_regexp.c
winsup/cygwin/regexp/v8_regsub.c
winsup/cygwin/rmsym
winsup/cygwin/speclib
winsup/cygwin/winbase.h
29 files changed, 12501 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog-2001 b/winsup/cygwin/ChangeLog-2001 new file mode 100644 index 000000000..140b2a9e9 --- /dev/null +++ b/winsup/cygwin/ChangeLog-2001 @@ -0,0 +1,5337 @@ +2001-12-31 Christopher Faylor <cgf@redhat.com> + + * Makefile.in: Strip path when installing library. + +2001-12-30 Christopher Faylor <cgf@redhat.com> + + * include/getopt.h: Fix define. + +2001-12-30 Christopher Faylor <cgf@redhat.com> + Ralf Habacker <Ralf.Habacker@freenet.de> + + * speclib: New file. + * Makefile.in: Create library versions of automode.o, textmode.o, and + binmode.o for easier use on command line. Create libpthread.a, libm.a, + and libc.a with subsets of exports found in libcygwin.a. + +2001-12-30 Ralf Habacker <Ralf.Habacker@freenet.de> + + * cygmagic: Eliminate unneeded use of 'tr' and 'bc'. + +2001-12-30 Corinna Vinschen <corinna@vinschen.de> + + * security.cc (open_local_policy): Use POLICY_EXECUTE instead of + enumerating user rights. + +2001-12-29 Corinna Vinschen <corinna@vinschen.de> + + * security.cc (open_local_policy): Initialize lsa handle to NULL. + Request only needed access rights in call to LsaOpenPolicy(). + (create_token): Check for NULL lsa pointer. + +2001-12-28 Corinna Vinschen <corinna@vinschen.de> + + * cygwin.din: Add symbols for endutent(), getutent(), getutid(), + getutline(), setutent() and utmpname(). + * syscalls.cc (setutent): New function. + (endutent): Ditto. + (utmpname): Ditto. + (getutent): Ditto. + (getutid): Ditto. + (getutline): Ditto. + * include/cygwin/version.h: Bump API minor version. + +2001-12-26 Christopher Faylor <cgf@redhat.com> + + * cygmagic: Add define name to warning. + * dcrt0.cc (_dll_crt0): Check for changes in child_info size. + (multiple_cygwin_problem): Avoid "proc" errors when testing. Just + assume new cygwin proc. + * shared_info.h (mount_info): Add 'cb' element for sanity checks. + (shared_info): Ditto. + * child_info.h (child_info): Add fhandler_union_size element for sanity + checking. + * shared.cc (open_shared): Detect shared region size mismatch between + parent and child. + (shared_info::initialize): Detect shared region size mismatch with + expectation. + (memory_Init): Ditto. + * sigproc.cc (init_child_info): Correctly set cb in passed structure. + * shared.cc (open_shared): + +2001-12-26 Christopher Faylor <cgf@redhat.com> + + * include/getopt.h: Protect a declaratin. + +2001-12-26 Robert Collins <rbtcollins@hotmail.com> + + * thread.cc (pthread_cond::Signal): Use a separate flag for signal + detection and broadcast semantics. + (__pthread_cond_dowait): Ditto. + * thread.h (pthread_cond): New flag for testing when a waiter has + woken. + +2001-12-26 Christopher Faylor <cgf@redhat.com> + + * Makefile.in: Quote arguments to shell scripts. + (clean): Remove new *_magic.h autogenerated files. + +2001-12-25 Christopher Faylor <cgf@redhat.com> + + * Makefile.in: Autogenerate some header files which provide magic + numbers. Force dependencies for files which depend on autogenerated + headers to ensure that they are always built. + * child_info.h (child_info): Add new fields to accommodate new magic + number header stuff. + * dcrt0.cc: Rely on "child_info_magic.h" to ensure that correct + child_info magic numbers are used. + (dll_crt0_1): Temporarily remove _cygwin_testing_magic test. + (_dll_crt0): Do more testing on magic numbers from fork_info structure. + Call "multiple_cygwin_problem" where appropriate. + (multiple_cygwin_problem): Rename from multiple_cygwin_die. Issue a + warning or die, as appropriate based on cygwin version/magic number + mismatch. + * pinfo.cc (pinfo::exit): Don't attempt to dereference `this' if it + doesn't exist. This can happen when a fatal error occurs early in + process initialization. + * shared.cc: Rely on "shared_info_magic.h" to accommodate that new + magic number header stuff. + (shared_info::initialize): Use new magic number stuff, for shared + region. + (memory_init): Ditto, for mount table. + * shared_info.h: Accomodate new magic number stuff for shared region + and mount table. + * sigproc.cc: Rely on "child_info_magic.h" to accommodate new magic + number header stuff. + (init_child_info): Initialize new fields in child_info) to accomodate + magic numbers. + * winsup.h: Rename multiple_cygwin_die to multiple_cygwin_problem. + * include/cygwin/version.h: Define macros for manipulating version + magic. + * cygmagic: New shell script for generating magic numbers. + +2001-12-20 Christopher Faylor <cgf@redhat.com> + + * include/cygwin/version.h: Bump API minor version for below changes. + +2001-12-19 Christopher Faylor <cgf@redhat.com> + + * Makefile.in (VPATH): Add regex directory. + (NM): new variable. + (OBSOLETE_FUNCTIONS): Ditto. + (NEW_FUNCTIONS): Ditto. + (install-headers): Install regex.h. + (install-man): New target. + (install): Use new target. + (DLL_OFILES): Add v8_reg* stuff. + (new-cygwin1.dll): Eliminate stamp-cygwin-lib creation. + (libcygwin.a): Remove obsolete functions from import lib. Add new functions. + * configure.in: Detect 'nm' tool. + * configure: Regenerate. + * cygwin.din: Export posix_reg* functions. Eliminate export of v8 reg* functions. + This is now handled in object files themselves. + * regex/*: New files. + * regexp/v8_*.c: New files, renamed from non v8_ equivalents. + +2001-12-17 Corinna Vinschen <corinna@vinschen.de> + + * include/getopt.h: Don't define getopt_long() and friends when + included through unistd.h. + +2001-12-17 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::init_std_file_from_handle): Avoid initializing + using an invalid handle. + +2001-12-16 David Billinghurst <David.Billinghurst@riotinto.com> + + * include/limits.h: Define LLONG_MIN, LLONG_MAX, ULLONG_MAX. + +2001-12-11 Christopher Faylor <cgf@redhat.com> + + * include/getopt.h: Add HAVE_DECL_GETOPT to save pain elsewhere. + +2001-12-10 Christopher Faylor <cgf@redhat.com> + + * fhandler.h (fhandler_serial::ev): New class member. + * fhandler_serial.cc (fhandler_serial::raw_read): Use class member for + event status. + * select.cc (peek_serial): Ditto. + +2001-12-07 Christopher Faylor <cgf@redhat.com> + + * path.cc (path_conv::check): Use full path name for determining + attributes when /cygdrive/x/foo. + +2001-12-06 Christopher Faylor <cgf@redhat.com> + + * path.cc (path_conv::check): Reset FH_CYGDRIVE if iterating through + path. + +2001-12-06 Christopher Faylor <cgf@redhat.com> + + * path.cc (path_conv::check): Don't complain if /dev/x/foo when x + doesn't exist. + (mount_info::conv_to_win32_path): Keep translating when a /cygdrive is + found. Don't attempt to translate to a device name when devn == + FH_CYGDRIVE. + (cygwin_conv_to_win32_path): Set buffer to empty on error. + (cygwin_conv_to_full_win32_path): Ditto. + + * window.cc: Include unistd.h to verify definitions. + +2001-12-05 Christopher Faylor <cgf@redhat.com> + + * dir.cc (opendir): Detect error return from build_fhandler_from_name. + +2001-12-04 David Rothenberger <daveroth@acm.org> + + * net.cc (cygwin_getsockopt): Dereference optlen pointer when passing + to __check_null_invalid_struct_errno. + +2001-12-03 Christopher Faylor <cgf@redhat.com> + + * net.cc (cygwin_getsockopt): Allow NULL optval. + (cygwin_setsockopt): Ditto. + (cygwin_recvfrom): Allow NULL from. + + * path.cc (mount_info::read_cygdrive_info_from_registry): Don't write + cygdrive to registry if it doesn't exist. + +2001-12-03 Christopher Faylor <cgf@redhat.com> + + * path.cc (mount_info::conv_to_win32_path): Avoid returning error if + cygdrive == '/'. + (mount_info::cygdrive_win32_path): Return 0 if invalid cygdrive path. + +2001-11-30 Christopher Faylor <cgf@redhat.com> + + * debug.cc (makethread): Eliminate unneeded function call. + * miscfuncs.cc (tls_ix): Predefine. + * perthread.h (set_reent): Eliminate. + (get_reent): Ditto. + * winbase.h (my_tlsalloc): Use global stack base pointer. Set newly + allocated location to NULL. + (my_tlssetvalue): Use global stack base pointer. + (my_tlsgetvalue): Ditto. + +2001-11-27 Christopher Faylor <cgf@redhat.com> + + * winsup.h: Reorganize to avoid use of experimental stuff. + * shortcut.cc: Move winsup.h first in include order. + +2001-11-27 Christopher Faylor <cgf@redhat.com> + + * cygwin.din (ualarm): New export. + * dcrt0.cc (_dll_crt0): Add experimental tls storage declaration. + (dll_crt0): Ditto. + * debug.cc (thread_stub): Ditto. + * thread.cc: Minor cleanup. + (__pthread_create): Add experimental tls storage declaration. + * miscfuncs.cc: Define tls index. + * winsup.h: Declare experimental tls storage. + + * window.cc (alarm): Use old timer return from setitimer. + (ualarm): New function. From Alexandr V. Shutko. + +2001-11-26 Christopher Faylor <cgf@redhat.com> + + * Makefile.in (libcygwin.a): Use ar commands to build libcygwin.a since + adding an archive doesn't work the way we want it to. + +2001-11-24 Christopher Faylor <cgf@redhat.com> + + * fhandler_disk_file.cc (fhandler_cygdrive::readdir): Avoid reporting + inaccessible drives. + +2001-11-24 Corinna Vinschen <corinna@vinschen.de> + + * net.cc (cygwin_hstrerror): Allow s == NULL. + (cygwin_rcmd): Add parameter checking. + (cygwin_rexec): Ditto. + +2001-11-24 Corinna Vinschen <corinna@vinschen.de> + + * net.cc (cygwin_inet_ntoa): Add parameter checking. + (cygwin_inet_network): Return INADDR_NONE instead of 0 in case of + EFAULT. + (cygwin_hstrerror): Add parameter checking. + (cygwin_rresvport): Ditto. + (socketpair): Ditto. + * winsup.h (check_null_str): Add extern declaration. + +2001-11-24 Christopher Faylor <cgf@redhat.com> + + * path.cc (path_conv::check): Tighten FH_CYGDRIVE check to avoid + matching trailing component, like other devices. + +2001-11-24 Christopher Faylor <cgf@redhat.com> + + * autoload.cc (IsDebuggerPresent): Make conditional load since it is + not available everywhere. + + * path.cc (mount_info::conv_to_win32_path): Only consider /cygdrive to + be FH_CYGDRIVE, not /cygdrive/x. + +2001-11-24 Christopher Faylor <cgf@redhat.com> + + * net.cc (inet_makeaddr): Revert previous change. + +2001-11-23 Christopher Faylor <cgf@redhat.com> + + * path.cc (chdir): Allow 'cd /cygdrive'. + +2001-11-23 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::vfork_parent_restore): Add debugging statement. + + * exceptions.cc (try_to_debug): Spin only as long as we don't have a + debugger attached. + + * fhandler.h (fhandler_base::set_nohandle): New method. + (fhandler_base::get_nohandle): New method. + * fhandler.cc (fhandler_base::dup): Avoid duplicating handle if there + is no handle. + * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set nohandle + flag on dummy fd. + +2001-11-23 Christopher Faylor <cgf@redhat.com> + + * Makefile.in: Make intermediate library for eventual inclusion in + libcygwin.a + + * fhandler.h (fhandler_pipe::fhandler_pipe): Remove default argument + setting since it is no longer used. + + * miscfuncs.cc (check_null_str): New function. + (check_null_str_errno): Ditto. + * net.cc: Add defensive buffer checking throughout. + (cygwin_sendto): Protect against invalid fd. + (cygwin_recvfrom): Ditto. + (cygwin_getpeername): Ditto. + (cygwin_recv): Ditto. + (cygwin_send): Ditto. + * winsup.h: Declare a new function. + +2001-11-23 Corinna Vinschen <corinna@vinschen.de> + + * select.cc (set_bits): Fix conditional for setting fd in exceptfds. + * dtable.cc (dtable::build_fhandler): Create fhandler_pipe using + correct device type. + * path.cc (get_devn): Set correct pipe device type from device name. + +2001-11-22 Christopher Faylor <cgf@redhat.com> + + * path.cc (conv_path_list): Fix wild indexing into path due to + conflicting methods for setting src pointer. + + * dir.cc (opendir): Only pass path_conv argument to opendir, since name + is already part of the fhandler. + * dtable.cc (dtable::build_fhandler): Accomodate new FH_CYGDRIVE type. + * fhandler.cc (fhandler_base::opendir): Nuke name argument. + * fhandler.h: Add FH_CYGDRIVE to "device" enum. + (fhandler_base::opendir): Nuke name argument. + (fhandler_disk_file::opendir): Ditto. + (fhandler_disk_file::fhandler_disk_file): Declare new method which + passes devtype through. + (fhandler_cygdrive): Add elements for tracking drives. + (fhandler_cygdrive::set_drives): Declare new method. + (fhandler_cygdrive::iscygdrive_root): Declare new method. + (fhandler_cygdrive::opendir): Declare new method. + (fhandler_cygdrive::readdir): Declare new method. + (fhandler_cygdrive::telldir): Declare new method. + (fhandler_cygdrive::seekdir): Declare new method. + (fhandler_cygdrive::rewinddir): Declare new method. + (fhandler_cygdrive::closedir): Declare new method. + (fhandler_cygdrive::fstat): Declare new method. + * fhandler_disk_file.cc (fhandler_disk_file::fhandler_disk_file): + Define new method which passes devtype through. + (fhandler_disk_file::open): Tweak debug output. + (fhandler_disk_file::opendir): Nuke first argument. Use info from + path_conv and class rather than calling fstat. + (fhandler_cygdrive::set_drives): New method. + (fhandler_cygdrive::iscygdrive_root): New method. + (fhandler_cygdrive::opendir): New method. + (fhandler_cygdrive::readdir): New method. + (fhandler_cygdrive::telldir): New method. + (fhandler_cygdrive::seekdir): New method. + (fhandler_cygdrive::rewinddir): New method. + (fhandler_cygdrive::closedir): New method. + (fhandler_cygdrive::fstat): New method. + * path.cc (iscygdrive_device): Assume cygdriveness is already verified. + (path_conv::check): Treat FH_CYGDRIVE "method" as a special case, + setting file attributes as needed. + (mount_info::conv_to_win32_path): Allow stand-alone /cygdrive, meaning + "the directory which contains all of the drives on the system". + (fillout_mntent): Use cyg_tolower for conversions. + (mount_info::cygdrive_win32_path): Replace unused argument with unit + number. + * shared_info.h (mount_info::cygdrive_win32_path): Reflect argument + change. + +2001-11-21 Christopher Faylor <cgf@redhat.com> + + * Makefile.in (DLL_OFILES): Add fhandler_disk_file.o. + * cygheap.h (cygheap_fdnew::operator =): New operator. + * dir.cc: Add invalid struct checking throughout. Use methods for all + directory manipulation throughout. + * fhandler.cc: Move fhandler_disk_file stuff to own file. + (fhandler_base::opendir): New method. + (fhandler_base::readdir): New method. + (fhandler_base::telldir): New method. + (fhandler_base::seekdir): New method. + (fhandler_base::rewinddir): New method. + (fhandler_base::closedir): New method. + * fhandler_disk_file.cc: New file. + * fhandler.h (fhandler_base): Declare new virtual methods. + (fhandler_disk_file): Ditto. + (fhandler_cygdrive): New class. + + * path.cc (conv_path_list): Use strccpy to break apart path. + +2001-11-17 Nick Duffek <nick@duffek.com> + + * path.cc (conv_path_list): Copy source paths before modifying them. + +2001-11-17 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_raw.cc (fhandler_dev_raw::clear): Don't reset unit. + * fhandler_tape.cc (fhandler_dev_tape::fhandler_dev_tape): Add debug + output. + +2001-11-15 Egor Duda <deo@logos-m.ru> + + * include/pthread.h (PTHREAD_COND_INITIALIZER): Define. + * thread.cc (__pthread_cond_destroy): Add support for + PTHREAD_COND_INITIALIZER. + (__pthread_cond_init): Ditto. + (__pthread_cond_broadcast): Ditto. + (__pthread_cond_signal): Ditto. + (__pthread_cond_dowait): Ditto. + (__pthread_mutex_init): Handle PTHREAD_MUTEX_INITIALIZER correctly, + don't return error when it's passed as parameter. + * winsup.h (check_null_invalid_struct): Call correct function. + +2001-11-14 Christopher Faylor <cgf@redhat.com> + + * exceptions.cc: Add stdlib.h include for alloca declaration. + * poll.cc: Ditto. + * termios.cc: Ditto. + +2001-11-14 Christopher Faylor <cgf@redhat.com> + + * syscalls.cc (_write): Only allow zero length when fd is valid. + +2001-11-14 Corinna Vinschen <corinna@vinschen.de> + + * fhandler.cc (fhandler_disk_file::fstat): Add setting access time + and creation time to last modification time for files on filesystems + not supporting multiple timestamps. + (fhandler_disk_file::fstat_helper): Set access time and creation + time in incoming Windows structure instead of in stat buf to avoid + incorrectly overwriting Epoch timestamp. + +2001-11-14 Corinna Vinschen <corinna@vinschen.de> + + * winsup.h: Remove alloca definition since it's now defined through + inclusion of stdlib.h. + * lib/cygwin_crt0.c: Ditto. + +2001-11-13 Christopher Faylor <cgf@redhat.com> + + * syscalls.cc (_write): Allow zero length as per SUSv2. + +2001-11-13 Corinna Vinschen <corinna@vinschen.de> + + * dir.cc (mkdir): Add HIDDEN file attribute if file has leading dot + and HIDDEN_DOT_FILES is defined. + * fhandler.cc (fhandler_base::open): Ditto. + * path.cc (symlink): Ditto. + * syscalls.cc (_rename): Ditto and remove HIDDEN file attribute if + new filename does not begin with a dot. + +2001-11-12 Christopher Faylor <cgf@redhat.com> + + * fhandler_console.cc (fhandler_console::read): Revert 2001-10-23 + change to only honor keydown events. + +2001-11-11 Christopher Faylor <cgf@redhat.com> + + * include/cygwin/version.h: Bump version to 1.3.6. + +2001-11-10 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::build_fhandler): Don't increment console fd count + if new operation fails. Increment fork_fixup field here. + (dtable::dup2): Don't increment fork_fixup field here. + * net.cc (fdsock): Ditto. + +2001-11-08 Corinna Vinschen <corinna@vinschen.de> + + * select.cc: Set errno using set_sig_errno() throughout. + * signal.cc (signal): Always set SA_RESTART flag. + * syscalls.cc (_read): Revert previous patch. + +2001-11-08 Corinna Vinschen <corinna@vinschen.de> + + * select.cc (fhandler_tty_slave::ready_for_read): Return 0 on EBADF. + * syscalls.cc (_read): If ready_for_read() failed, save errno from + being overwritten by signal handler call. + +2001-11-07 Corinna Vinschen <corinna@vinschen.de> + + * lib/getopt.c (getopt_internal): Reset optind to 1 only if optreset + is not set. + +2001-11-06 Christopher Faylor <cgf@redhat.com> + + * select.cc (fhandler_tty_slave::ready_for_read): Correct inverted + not_open test. + +2001-11-05 Christopher Faylor <cgf@redhat.com> + + * include/cygwin/version.h: Bump version to 1.3.5. + +2001-11-05 Corinna Vinschen <corinna@vinschen.de> + + * mmap.cc (mmap_record::find_empty): Add input parameter check. + +2001-11-04 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::build_fhandler): Fix debug_printf to avoid SEGV + due to incorrect parameter placement. + +2001-11-04 Christopher Faylor <cgf@redhat.com> + + * fhandler.h (fhandler_pipe::broken_pipe): Renamed from saweof. + (fhandler_pipe::set_eof): Reflect above change. + * pipe.cc (fhandler_pipe::fhandler_pipe): Ditto. + (fhandler_pipe::read): Ditto. + (fhandler_pipe::hiteof): Ditto. + +2001-11-04 Christopher Faylor <cgf@redhat.com> + + * pipe.cc (fhandler_pipe::read): Narrow eof return to just the "broken + pipe" test. + +2001-11-04 Christopher Faylor <cgf@redhat.com> + + * select.cc: Add more comments throughout. Use bool 'true' where + appropriate throughout. + (fhandler_socket::select_read): Remove duplicate setting for *_ready + which inadvertently overrode previous, correct setting. + (fhandler_socket::select_write): Ditto. + +2001-11-03 Christopher Faylor <cgf@redhat.com> + + * select.cc (verify_console): New function. + (verify_windows): Ditto. + (fhandler_console::select_read): Really do need to verify that there is + something to read. + (fhandler_console::select_windows): Ditto. + +2001-11-03 Christopher Faylor <cgf@redhat.com> + + * fhandler.h (fhandler_base::ready_for_read): Remove unused argument. + (fhandler_tty_slave::ready_for_read): Ditto. + (select_record): Remove poll, initialize peek. + * select.cc: Remove all poll functions, throughout. Change second + argument of peek_* functions to 'bool' throughout. Specifically + initialize *_ready variables throughout. + (select_stuff::poll): Subsume previous poll functionality. + (peek_pipe): Don't grab guard mutex when in select loop. + select()/read() is racy by design so there is no need to worry about a + race in select(). + (fhandler_base::ready_for_read): Remove unused argument. + (fhandler_tty_slave::ready_for_read): Ditto. + * syscalls.cc (_read): Eliminate third argument in ready_for_read call. + +2001-11-03 Corinna Vinschen <corinna@vinschen.de> + + * security.cc (get_supplementary_group_sidlist): New function. + (get_group_sidlist): Call get_supplementary_group_sidlist() to + retrieve list of supplementary groups SIDs from /etc/group and + add them to the user's group list. + +2001-11-03 Christopher Faylor <cgf@redhat.com> + + * fhandler.cc (fhandler_base::read): Return just read ahead characters + if slow device. + * fhandler.h (fhandler_base::set_eof): New virtual method. + (fhandler_pipe::set_eof): New method. + * pipe.cc (fhandler_pipe::fhandler_pipe): Clear saweof flag. + (fhandler_pipe::read): Return immediately if hit eof. + (fhandler_pipe::hit_eof): Return true if saweof flag is set. + * select.cc (peek_pipe): Don't call PeekNamedPipe if we couldn't grab + the guard mutex. + +2001-11-02 Egor Duda <deo@logos-m.ru> + + * dll_init.h (class dll_list): Reorder functions to avoid compiler + "can't inline" warnings. + * security.h (class cygsid): Ditto. + * sigproc.cc (get_proc_lock): Ditto. + * sigproc.h (class sigframe): Ditto. + * sync.h (class muto): Ditto. + +2001-11-02 Christopher Faylor <cgf@redhat.com> + + * fhandler.h (fhandler_base::get_guard): Actually MAKE virtual as + previously indicated. + * pipe.cc (make_pipe): Remove extraneous set_errno. + * syscalls.cc (_open): Ditto. + * select.cc (peek_pipe): Need to check that there is still something to + read from the pipe after acquiring the mutex since another + process/thread could have eaten the input before we got to acquiring + the lock. (Thanks to Nick Duffek for this inspiration.) + +2001-11-01 Christopher Faylor <cgf@redhat.com> + + * fhandler.h: Change Windows 'BOOL's to c++ 'bool's for all variables. + * select.cc (fhandler_base::ready_for_read): Set read_ready to zero + prior to testing it or it will be uninitialized. + + * Makefile.in (CFLAGS): Move setting to Makefile.common. + +2001-11-01 Christopher Faylor <cgf@redhat.com> + + * cygheap.h (cygheap_fdmanip::isopen): Set appropriate errno if fd not + open. + * select.cc (fhandler_base::ready_for_read): Release an open guard + mutex when exiting with an error condition. + * syscalls.cc (_read): Check frequently for closed fd as a kludge until + something better is invented. + +2001-11-01 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::build_fhandler): Issue internal error on unknown + device. + * fhandler.cc (fhandler_base::close): Show both name and handle in + debugging output. + + * fhandler.h (fhandler_base::get_guard): New virtual method. + (fhandler_pipe::get_guard): New method. + (fhandler_socket::ready_for_read): Delete declaration. + (fhandler_pipe::ready_for_read): Ditto. + (fhandler_serial::ready_for_read): Ditto. + (fhandler_console::ready_for_read): Ditto. + (fhandler_tty_common::ready_for_read): Ditto. + (fhandler_windows::ready_for_read): Ditto. + (struct select_record::peek): Declare new method. + * select.cc (MAKEready): Delete. + (peek_pipe): Use get_guard method to retrieve potential guard mutex + handle. + (fhandler_base::ready_for_read): Rewrite as generic ready-for-read + handler. Should only be called for "slow" devices. + (fhandler_socket::ready_for_read): Delete definition. + (fhandler_pipe::ready_for_read): Ditto. + (fhandler_serial::ready_for_read): Ditto. + (fhandler_console::ready_for_read): Ditto. + (fhandler_tty_common::ready_for_read): Ditto. + (fhandler_windows::ready_for_read): Ditto. + (fhandler_pipe::select_read): Fill in new peek record in select_record + structure. + (fhandler_console::select_read): Ditto. + (fhandler_tty_common::select_read): Ditto. + (fhandler_serial::select_read): Ditto. + (fhandler_socket::select_read): Ditto. + (fhandler_socket::select_read): Ditto. + (fhandler_tty_slave::ready_for_read): Check for tty not open. Set + errnos appropriately. + * syscalls.cc (_read): Allow ready_for_read to set errno. + + * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it + is initializing. + * sigproc.cc (getsem): Adjust wait for process to initialize downward + to avoid huge waits. + +2001-10-31 Christopher Faylor <cgf@redhat.com> + + * environ.cc: Set reset_com to false to mimic linux behavior more + closely. + +2001-10-31 Corinna Vinschen <corinna@vinschen.de> + + * dtable.cc (dtable::vfork_child_dup): Revert impersonation + before duplicating fhandler. + +2001-10-30 Christopher Faylor <cgf@redhat.com> + + * exceptions.cc (signal_exit): Weight the odds against the main thread + running when signal thread is exiting. + +2001-10-30 Christopher Faylor <cgf@redhat.com> + + * sigproc.cc (sigproc_terminate): Don't signal main thread when exiting. + * sigproc.h (sigframe): Decorate some methods with `inline'. + (new_muto): Coerce pointer to new to void *. + +2001-10-30 Christopher Faylor <cgf@redhat.com> + + * fhandler.cc (fhandler_base::fork_fixup): Pass old handle to + setclexec_pid. + +2001-10-30 Christopher Faylor <cgf@redhat.com> + + * cygheap.h (cygheap_fdmanip::cygheap_fdmanip): Clear fh. + (cygheap_fdmanip::isopen): New method. + * syscalls.cc (_read): Avoid accessing closed fd. + + * path.h (fe_types): New enum. + (path_conv::set_path): New method. + (find_exec): Change null_if_not_found argument to something more + generic. + * spawn.cc (find_exec): Default to returning the POSIX path rather than + the windows path, unless instructed otherwise. + (spawn_guts): Force call to find_exec to use native paths. + * dlfcn.cc (check_path_access): Accommodate new find_exec arguments. + * environ.h (win_env::get_posix): New method. + +2001-10-30 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_socket.cc (fhandler_socket::close): Add error handling. + +2001-10-30 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_socket.cc (fhandler_socket::dup): Revert previous change. + +2001-10-30 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::dup2): Add some debugging. Use methods from + passed in class rather than cygheap->fdtab. + * fhandler_socket.cc (fhandler_socket::fixup_before_fork_exec): Add + more debugging output. + (fhandler_socket::dup): Allocate new space for prot_info_ptr for + duplicated entry. + (fhandler_socket::close): Loop closesocket() as long as WSAEWOULDBLOCK + is returned. + * syscalls.cc (stat_worker): Always delete fh if it has been created. + +2001-10-29 Corinna Vinschen <corinna@vinschen.de> + + * security.cc (is_group_member): Call NetLocalGroupGetMembers() for + local machine only. + (get_user_local_groups): Ditto for NetLocalGroupEnum(). + +2001-10-29 Christopher Faylor <cgf@redhat.com> + + * fhandler.cc (fhandler_base::set_name): Set namehash here to catch + name changes. + (fhandler_base::open): Remove namehash setting. + (fhandler_base::fstat): Subtract 1 from arbitrary time setting to avoid + strange ls -l granularity problem. + +2001-10-29 Christopher Faylor <cgf@redhat.com> + + * select.cc (MAKEready): Remove extraneous select_read. + +2001-10-29 Corinna Vinschen <corinna@vinschen.de> + + * uinfo.cc (internal_getlogin): Set environment variable $HOME + from either /etc/passwd or $HOMEDRIVE/$HOMEPATH if necessary. + +2001-10-29 Christopher Faylor <cgf@redhat.com> + + * fhandler.h (fhandler_serial::fhandler_serial): Change to only accept + unit argument. + * fhandler_serial.cc (fhandler_serial::fhandler_serial): Ditto. + (fhandler_serial::open): Avoid else when previous clause is a return(). + * path.cc (get_devn): Alias /dev/ttyS0 -> /dev/com1, etc. + (get_device_number): Reallow standalone "com1" as a valid name for + /dev/com1. + +2001-10-26 Christopher Faylor <cgf@redhat.com> + + * select.cc (MAKEready): Check for read_ready in loop since select_read + could set it. + (peek_socket): Check ready/write/except specifically since they could + have been set even prior to peek_socket call. + +2001-10-24 Christopher Faylor <cgf@redhat.com> + + * shared_info.h (MOUNT_VERSION): Change to a smaller, still arbitrary + number. + * shared.cc (open_shared): Accept a number to denote the shared memory + region. + (memory_init): Use shared memory version as part of the object name of + the shared region. Ditto for the mount table. + * path.cc (CYGWIN_REGNAME): New define used in place of + CYGWIN_INFO_CYGWIN_REGISTRY_NAME throughout. + * external.cc (cygwin_internal): Implement CW_[GS]ET_CYGWIN_REGISTRY_NAME. + * cygheap.h (init_cygheap::cygwin_regname): New element. + +2001-10-23 Christopher Faylor <cgf@redhat.com> + + Ensure that all fhandler_*::read definitions are __stdcall throughout. + * fhandler.cc (fhandler_base::set_inheritance): Be more defensive in + debugging code. + * fhandler.h: Adjust regparms throughout to reflect passing 'this' + parameter. + * fhandler_console.cc (fhandler_console::read): Remove unneeded test. + Only honor "key down" events. + * miscfuncs.cc (strcasestr): Reorganize for efficient code use. + (check_null_empty_str_errno): Ditto. + (__check_null_invalid_struct_errno): Ditto. + (__check_invalid_read_ptr_errno): Ditto. + * syscalls.cc (_read): Return 0 when length == 0, as per Single UNIX + Specification. + +2001-10-22 Christopher Faylor <cgf@redhat.com> + + * debug.cc (set_errno): Return value of errno that was set, just like + the macro. + (setclexec_pid): Replace old handle with new handle. + * debug.h: Reflect change in arguments for setclexec_pid. + * fhandler.cc (fhandler_base::set_inheritance): Ditto. + (fhandler_base::fork_fixup): Ditto. + * cygerrno.h: Reflect return value change for set_errno. + +2001-10-22 Christopher Faylor <cgf@redhat.com> + + Remove 'cb' parameter and modify fhandler_* constructors throughout. + * dtable.cc (dtable::build_fhandler): Remove debugging output which + uses 'cb'. + * exec.cc (execvp): New function. + (execvpe): Ditto. + * fhandler.cc (fhandler_base::fhandler_base): Use constructor + initialization. + * fhandler.h (fhandler_tty_common::fhandler_tty_common): Ditto. + * fhandler_clipboard.cc (fhandler_dev_clipboard::fhandler_dev_clipboard): + Ditto. + * fhandler_console.cc (fhandler_console::fhandler_console): Ditto. + * fhandler_raw.cc (fhandler_dev_raw::fhandler_dev_raw): Ditto. + * fhandler_serial.cc (fhandler_serial::fhandler_serial): Ditto. + * fhandler_tty.cc (fhandler_tty_master::fhandler_tty_master): Ditto. + (fhandler_tty_slave::fhandler_tty_slave): Ditto. + (fhandler_pty_master::fhandler_pty_master): Ditto. + * fhandler_windows.cc (fhandler_windows::fhandler_windows): Ditto. + +2001-10-22 Corinna Vinschen <corinna@vinschen.de> + + Patch suggested by Ian Ray <ian.ray@nokia.com>: + * syscalls.cc (seteuid): Unset environment variables HOMEDRIVE and + HOMEPATH before calling internal_getlogin(). + * uinfo.cc (internal_getlogin): Use default HOMEPATH and HOMEDRIVE + from environment if both are present, else query NetUserGetInfo(). + +2001-10-22 Corinna Vinschen <corinna@vinschen.de> + + * net.cc (get_2k_ifconf): Change multiple IP address naming scheme + to Linux style. + +Sun Oct 21 19:04:37 2001 Alexander Gottwald <ago@informatik.tu-chemnitz.de> + + * net.cc (get_2k_ifconf): Added support for multiple IP addresses on + one interface. + +2001-10-22 Corinna Vinschen <corinna@vinschen.de> + + * miscfuncs.cc (__check_invalid_read_ptr_errno): Return error, if any. + +2001-10-21 Christopher Faylor <cgf@redhat.com> + + * resource.cc (fill_rusage): Perform paranoid zero structure passed to + GetProcessMemoryInfo. + +2001-10-22 Robert Collins <rbtcollins@hotmail.com> + + * autoload.cc: Autoload GetProcessMemoryInfo. + * resource.cc (fill_rusage): Calculate ru_maxrss and ru_majflt entries. + (Bug report on this from Guido Serassio in the squid project). + This requires including psapi.h. + +2001-10-20 Christopher Faylor <cgf@redhat.com> + + * dll_init.cc (dll_list::alloc): Increase retry count to 1000. + +2001-10-20 Christopher Faylor <cgf@redhat.com> + + * miscfuncs.cc (__check_invalid_read_ptr_errno): New function. + * syscalls.c (_write): Validate that write buffer is accessible for + reading, not writing. + * winsup.h: Declare new function, increase regparmization of check_* + functions. + +2001-10-19 Corinna Vinschen <corinna@vinschen.de> + + * path.cc (getcwd): Allow len == 0 when buf == NULL. + +2001-10-18 Christopher Faylor <cgf@redhat.com> + + * syscalls.cc (_read): Validate input pointer. + (_write): Ditto. + (system): Ditto. + +2001-10-16 Frederic Devernay <Frederic.Devernay@sophia.inria.fr> + + * poll.cc (poll): Call cygwin_select() if any fd is valid. + +2001-10-16 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_raw.cc (fhandler_dev_raw::open): Eliminate compatibility + code since no Win32 device names are used anymore. + * fhandler_tape.cc (fhandler_dev_tape::tape_set_blocksize): Allow + 0 as blocksize to indicate variable blocksize. + * path.cc (win32_device_name): Generate NT internal device names + using upper/lower case names for readability. + Generate \DosDevices\<letter>: device name for mount table + compatibility devices. + +2001-10-16 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_tape.cc (fhandler_dev_tape::tape_status): Report + EOTWarningZoneSize in get->mt_eotwarningzonesize. + * include/cygwin/mtio.h: Define DEFTAPE. + (struct mtget): Add member `mt_eotwarningzonesize'. Add a comment. + * include/cygwin/version.h: Bump API minor version to 47. + +2001-10-16 Christopher Faylor <cgf@redhat.com> + + * fhandler.cc (fhandler_base::fork_fixup): Guard against compiler + warning. + +2001-10-16 Corinna Vinschen <corinna@vinschen.de> + + * autoload.cc: Add load statement for `NtOpenFile'. + * fhandler.h (fhandler_dev_raw::get_unit): New method. + (fhandler_dev_tape::norewind): Eliminate. + (fhandler_dev_tape::is_rewind_device): New method. + * fhandler_raw.cc (fhandler_dev_raw::open): Open new + fixed device name devices using NT internal method. + Keep calling fhandler_base::open() for old mount table + device mapping compatibility devices. + (fhandler_dev_raw::fstat): Eliminate. Settings are done + by fhandler_base::fstat() already. + * fhandler_tape.cc: Remove `norewind' usage throughout. + * ntdll.h: Define FILE_SYNCHRONOUS_IO_NONALERT. + Define struct _IO_STATUS_BLOCK. + Declare NtOpenFile(). + * path.cc (get_raw_device_number): Add new approach for + using fixed device names. + (win32_device_name): Ditto. + (get_device_number): Ditto. Require POSIX path to begin + with "/dev/". + (mount_info::conv_to_win32_path): Call win32_device_name() + instead of get_device_number() after evaluating mount points + to allow changing the win32 destination path again. + * security.cc (str2buf2uni): Remove `static' to be able to + call function from fhandler_dev_raw::open(). + * wincap.cc: Set flag has_raw_devices appropriately. + * wincap.h: Add flag has_raw_devices. + +2001-10-16 Christopher Faylor <cgf@redhat.com> + + * cygheap.h (cygheap_fdget::cygheap_fdget): Remove debugging operation + from set_errno. + +2001-10-16 Christopher Faylor <cgf@redhat.com> + + * mmap.cc (mmap): Assign 'fh' from cygheap_fdget. Use 'fh' everywhere. + +2001-10-15 Christopher Faylor <cgf@redhat.com> + + * cygerrno.h (set_errno): Define more informative version of this + function for debugging. + (__set_errno): Declare when DEBUGGING. + * cygheap.h (cygheap_fdget::cygheap_fdget): Add a flag to control when + errno is set. + * debug.cc (__set_errno): New function. + * fcntl.cc (_fcntl): Fix so that correct fd is used for second argument + to dup2. + * syscalls.cc (_cygwin_istext_for_stdio): Don't set errno here when + using cygheap_fdget. + +2001-10-15 Christopher Faylor <cgf@redhat.com> + + * fhandler.cc (fhandler_base::fork_fixup): Don't protect handle. + + * dlfcn.cc: Fix to confirm to coding standards. + + Reorganize includes throughout to accommodate new cygheap.h usage. + * cygheap.h (cygheap_fdmanip): New class: simplifies locking and + retrieval of fds from cygheap->fdtab. + (cygheap_fdget): Ditto. + (cygheap_fdnew): Ditto. + * fcntl.cc (_fcntl): Use new method to lock fdtab and retrieve info. + * ioctl.cc (ioctl): Ditto. + * mmap.cc (mmap): Ditto. + * net.cc: Ditto, throughout. + * passwd.cc (getpass): Ditto. + * path.cc (fchdir): Ditto. + * pipe.cc (make_pipe): Ditto. + * sec_acl.cc (facl): Ditto. + * syscalls.cc: Ditto, throughout. + * termios.cc: Ditto, throughout. + +2001-10-15 Corinna Vinschen <corinna@vinschen.de> + + * uname.cc (uname): Use `wProcessorLevel' unless OS sets it wrong. + Use `dwProcessorType' then instead. + * wincap.cc: Set flag has_valid_processorlevel appropriately. + * wincap.h: Add flag has_valid_processorlevel. + +2001-10-14 Christopher Faylor <cgf@redhat.com> + + * dtable.cc (dtable::build_fhandler_from_name): Use PC_FULL to + determine path name. + * path.cc (fchdir): Remove rel -> abs path conversion. + +Sun Oct 14 08:10:12 2001 Gary R. Van Sickle + + * fork.cc (fork_parent): Correct the "unable to allocate + forker_finished event" error message. It named the wrong event before. + +2001-10-13 Christopher Faylor <cgf@redhat.com> + + * autoload.cc (load_wsock32): Declare dummy function to force loading + of winsock. + * fhandler.cc (fhandler_base::set_inheritance): Make debugging output + more verbose. + * fhandler_socket.cc (fhandler_socket::fixup_after_fork): Force loading + of winsock32 if winsock2 not available. + * net.cc (set_socket_inheritance): Use DuplicateHandle in all cases to + set inheritance correctly. + (fdsock): Use winsock2_active macro to determine when to set socket + inheritance. Remove fdtab resource locking since this function should + already be protected. + (cygwin_accept): Simplify logic. Ensure that fdtab unlock is not + called inappropriately. + (cygwin_rcmd): Use fdtab locking. + (cygwin_rresvport): Ditto. + (cygwin_rexec): Ditto. + * select.cc (peek_socket): Set errno appropriately if winsock select + fails. + +2001-10-13 Kazuhiro Fujieda <fujieda@jaist.ac.jp> + + * winsup.h: Declare check_pty_fds. + * syscalls.cc (check_pty_fds): Rename from check_ttys_fds. Also check + pty master. + (setsid): Use check_pty_fds. + * dtable.cc (dtable::dec_console_fds): Add check on pty fds. + +2001-10-13 Ralf Habacker <Ralf.Habacker@freenet.de> + + * fhandler_dsp.cc (fhandler_dsp::ioctl): Return 0 for successful + SNDCTL_DSP_GETBLKSIZE operation. + +2001-10-13 Christopher Faylor <cgf@redhat.com> + + Remove obsolete 'name' arg from fhandler_* constructors throughout. + * winsup.h (winsock_active): New macro. + (winsock2_active): Ditto. + * autoload.cc (wsock_init): Use new macros to decide if winsock or + winsock2 is loaded. + (nonexist_wsock32): Dummy function to force winsock load. + (nonexist_ws2_32): Dummy function to force winsock2 load. + * fhandler.h (fhandler_socket::fstat): Declare new method. Currently + unused. + * fhandler_socket.cc (fhandler_socket::fixup_before_fork_exec): Check + that winsock2 is active before trying WSADuplicateSocketA. + (fhandler_socket::fixup_after_fork): Add extra check for + winsock2_active. Otherwise use iffy procedures for Windows 95. + (fhandler_socket::fixup_after_exec): Add debugging. + (fhandler_socket::dup): Add debugging. + (fhandler_socket::fstat): New method. + (fhandler_socket::set_close_on_exec): Attempt to perform iffy stuff on + Windows 95. + + * errno.cc (_sys_nerr): Work around compiler strangeness. + + * pinfo.cc (winpids::add): Add extra element at end of allocated array + for setting to NULL. + (winpids::enumNT): Ditto. + (winpids::init): Don't modify pidlist if it hasn't been allocated + (possibly due to malloc problem). + +2001-10-12 Christopher Faylor <cgf@redhat.com> + + * autoload.cc (wsock_init): Reorganize slightly to accommodate a new + compiler. + +2001-10-11 Egor Duda <deo@logos-m.ru> + + * net.cc (cygwin_sendto): Use correct socket address when sending + data to AF_UNIX socket. + +Wed Oct 10 16:10:41 2001 Alexander Gottwald <ago@informatik.tu-chemnitz.de> + + * net.cc (get_95_ifconf): Using other registry values pointing to + correct networkdevice identification for Windows95. + +Tue Oct 9 22:22:45 2001 Christopher Faylor <cgf@cygnus.com> + + Throughout, rename PROC_FORK1 to PROC_FORK. + * child_info.h: Rename PROC_* to _PROC_*. Define PROC_* with + additional testing magic. Eliminate old PROC_FORK and rename + PROC_FORK1 to PROC_FORK. + * dcrt0.cc (_cygwin_testing_magic): New variable. Added to magic + number in proc_info. + (alloc_stack): Eliminate old PROC_FORK test. + (dll_crt0_1): Ditto. Use _PROC_* enums for test. Subtract + _cygwin_testing_magic from child_proc_info->type so that normal cygwin + programs invoked by test suite programs do not consider themselves to + be in a cygwin environment. + (_dll_crt0): Ditto. Move environment checks to initial_env function to + conserve on stack space. + (initial_env): New function. Checks for testing and debugging + environment variables. + * init.cc (cygwin_hmodule): Move declaration. + * winsup.h: Declare variables used for cygwin testing. + +Tue Oct 9 19:17:53 2001 Christopher Faylor <cgf@cygnus.com> + + * uinfo.cc (internal_getlogin): Reorganize slightly to minimize work in + default condition. + +Tue Oct 9 18:53:00 2001 Corinna Vinschen <corinna@vinschen.de> + + * fhandler.cc (fhandler_disk_file::open): Add missing case clash check. + +Mon Oct 8 01:47:27 2001 Christopher Faylor <cgf@cygnus.com> + + * dtable.cc (dtable::build_fhandler): Allocate correct amount for given + fhandler class. + * fhandler.h (fhandler_union): Properly define rather than relying on + fhandler_console being "big enough". + +Mon Oct 8 00:25:18 2001 Christopher Faylor <cgf@cygnus.com> + + * external.cc (fillout_pinfo): Reset counter whenever we initialize the + pid list. + +Sun Oct 7 17:16:05 2001 Christopher Faylor <cgf@cygnus.com> + + * path.cc (normalize_posix_path): Don't eat a '.' after a '\\' since it + has special meaning on NT. + + * syscalls.cc (access): Use stat_worker. + +Fri Oct 5 21:01:14 2001 Christopher Faylor <cgf@cygnus.com> + + * fhandler.cc (fhandler_base::fork_fixup): Protect dup'ed handle and + record it as non-inheritable for debugging purposes in case there is a + subsequent fork or exec. + * fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Allow + fork_fixup to call ProtectHandle. + +Fri Oct 5 14:22:47 2001 Christopher Faylor <cgf@cygnus.com> + + * path.cc (get_raw_device_number): Correct length arguments for + wdeveqn. + +Fri Oct 5 11:05:32 2001 Christopher Faylor <cgf@cygnus.com> + + * path.cc (getcwd): Allow NULL first argument. + +Fri Oct 5 00:31:35 2001 Christopher Faylor <cgf@cygnus.com> + + * heap.h (inheap): Check for NULL. + +Thu Oct 4 23:17:49 2001 Christopher Faylor <cgf@cygnus.com> + + Add second path_conv * argument to fstat()s throughout. + * fhandler.h: Change read and fstat to regparm/stdcall throughout. + (fhandler_base::fstat): Just declare. Don't define. + (fhandler_disk_file::fstat_helper): Declare. + * fhandler.cc (fhandler_base::fstat): Move here from fhandler.h, adapt + from former stat_dev(). + (fhandler_disk_file::fstat): Move most of the disk-file-specific logic + from stat_worker to here. Use fstat_helper to derive final fstat + output. + (fhandler_disk_file::fstat_helper): New method, renamed from former + fstat method. + (num_entries): Moved here from syscalls.cc. + * fhandler_mem.cc (fhandler_dev_mem::fstat): Use base class to + initialize most stuff. Invert has_physical_mem_access test for + establishing permissions. + * fhandler_raw.cc (fhandler_dev_raw::fstat): Eliminate unneed test and + memory clearing. Use base class to initialize most stuff. + * syscalls.cc (stat_dev): Eliminate. + (stat_worker): Simply call fstat method to generate fstat output. Move + all device specific code to appropriate fstats. + + * dir.cc (opendir): Pass correct arg to stat_worker to allow following + symlinks. + +Thu Oct 4 21:37:57 2001 Christopher Faylor <cgf@cygnus.com> + + * spawn.cc (perhaps_suffix): Return NULL on non-existence of file as + well as "directoryness". Previous code modified on 2001/09/30 actually + had an arguable bug which was unmasked by the change on that day. + +Thu Oct 4 20:52:42 2001 Christopher Faylor <cgf@cygnus.com> + + * path.cc (path_conv::check): Return ENOTDIR when leading device and + trailing component. + +Thu Oct 4 18:49:23 2001 Christopher Faylor <cgf@cygnus.com> + + * syscalls.cc (stat_worker): Make global. Accept path_conv parameter + for passing information back to caller. + * winsup.h: Declare stat_worker. + * dir.cc (opendir): Use stat_worker rather than stat and pass path_conv + parameter to stat_worker for later inspection. + +2001-10-04 Karellen (karellen@boreworms.com) + + * syslog.cc (syslog): Teach syslog about syslog priorities other than + LOG_ERR, LOG_WARNING and LOG_INFO + +Thu Oct 4 15:50:03 2001 Christopher Faylor <cgf@cygnus.com> + + * path.cc (path_conv::check): Don't perform file system or rootdir + checks on devices. + +Wed Oct 3 19:40:36 2001 Christopher Faylor <cgf@cygnus.com> + + * dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. + + * fork.cc (vfork): Add debugging statements. + + * path.cc (get_device_number): Make static. Rewrite to inspect both unix + and windows paths. + (get_raw_device_number): Just check for parts of raw device that we + care about. + (get_devn): New function, pulled from get_device_number. + (win32_device_name): Accommodate arg changes to get_device_number. + (mount_info::get_device_number): Call get_device_number on translated + Windows path. + + * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. + Add handle to child's shared region to child so that it will be + preserved if the parent goes away. + * fhandler.h: Throughout, simplify to one open method for all fhandler + classes, requiring a path_conv first element. + * fhandler.cc (fhandler_base::open): Remove obsolete method. + Generalize to require path_conv * as first argument. + (fhandler_disk_file::open): Remove obsolete method. + (fhandler_disk_file::open): Use path_conv pointer rather than + reference. + * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open + method. + (fhandler_dev_clipboard::open): Accommodate new argument for open + methods. + * fhandler_console.cc (fhandler_console::open): Ditto. + (fhandler_console::dup): Use new open method. + (fhandler_console::fixup_after_fork): Ditto. + (fhandler_console::fixup_after_exec): Ditto. + * fhandler_dsp.cc (fhandler_dev_dsp::open): Accommodate new argument for + open methods. + * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. + * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. + * fhandler_random (fhandler_dev_random::open): Ditto. + * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. + * fhandler_serial.cc (fhandler_serial::open): Ditto. + * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. + * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. + (fhandler_pty_master::open): Ditto. + * fhandler_windows.cc (fhandler_windows::open): Ditto. + * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. + * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accommodate + new argument for open methods. + * syscalls.cc (_open): Ditto. + (stat_worker): Ditto. + +Tue Oct 2 23:49:18 2001 Christopher Faylor <cgf@cygnus.com> + + * cygheap.cc (cfree): Remove malloc debugging probe. + * dlmalloc.c (errprint): Remove abort() call which causes interesting + error message printing to abort prematurely. + * environ.cc: Sprinkle MALLOC_CHECKs liberally throughout. + (_addenv): Allocate two empty elements at end of environ to + (apparently) work around problems with some buggy applications. + (winenv): Avoid calling alloca if no forced environment variable is + present. + + * exceptions.cc (open_stackdumpfile): Don't print "Dumping stack trace + to..." when running in a cygwin environment (i.e., the parent is a + cygwin process). + + * dtable.cc (dtable::init_std_file_from_handle): Move device type + detection code from build_fhandler here since it is only used by this + function. + (dtable::build_fhandler_from_name): New method. Renamed from + dtable::build_fhandler. + (dtable::build_fhandler): Use build_fhandler_from_name. + (cygwin_attach_handle_to_fd): Ditto. + * syscalls.cc (_open): Ditto. + (stat_worker): Ditto. + * dtable.h (dtable::build_fhandler_from_name): Rename declaration from + dtable::build_fhandler. + +Mon Oct 1 16:52:23 2001 Christopher Faylor <cgf@cygnus.com> + + * dtable.h (dtable::build_fhandler): Make path_conv parameter + non-optional. + (dtable::init_std_file_from_handle): Eliminate name parameter. + * dtable.cc (stdio_init): Don't pass bogus name to + init_std_file_from_handle. The function will figure out the name + itself. + (dtable::init_std_file_from_handle): Eliminate name parameter. Assume + that we're always called with an appropriate fd. Pass name as NULL if + we can't simply figure it out from context. + (cygwin_attach_handle_to_fd): Pass path_conv argument to + build_fhandler. + (dtable::build_fhandler): Make path_conv argument mandatory. Eliminate + specific call to get_device_number. With unknown device names, set + name from handle context for parsing by path_conv. + (dtable::build_fhandler): Pass path_conv argument to build_fhandler. + * path.h (path_conv::set_isdisk): Set disk device type. + (path_conv::is_device): Don't consider FH_DISK a "device". + * syscalls.cc (_open): Pass path_conv argument by reference. + (stat_worker): Ditto. + (_rename): Use path_conv operators. Add bounds to DeleteFile/MoveFile + for loop. + +Mon Oct 1 14:25:00 2001 Charles Wilson <cwilson@ece.gatech.edu> + + * cygwin.din: export strtoll and strtoull + +Sun Sep 30 22:51:41 2001 Christopher Faylor <cgf@cygnus.com> + + Add "path.h" include throughout, where needed. Use new path_conv + methods and operators to simplify testing for directory and attributes, + throughout. + * path.h (path_conv::exists): New method. + (path_conv::has_attribute): Ditto. + (path_conv::isdir): Ditto. + (path_conv::DWORD &): New operator. + (path_conv::int &): Ditto. + * dir.cc (rmdir): Eliminate a goto. + * dtable.cc (dtable::build_fhandler): Accept opt and suffix info for + path_conv.check. Return fh == NULL on path_conv error. Pass unit to + set_name as appropriate. + (dtable::reset_unix_path_name): New method. + * dtable.h (dtable): Declare new method. Reflect arg changes to + build_fhandler. + * fhandler.cc (fhandler_disk_dummy_name): Eliminate. + (fhandler_base::set_name): Expect paths to be NULL. Build + unix_path_name from win32_path_name when it is a device. + (fhandler_base::reset_unix_path_name): New method. + (fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION + or ERROR_INVALID_PARAMETER and reading a directory. + (fhandler_disk_file::fstat): Don't call stat_dev since we should now + never be calling fhandler_disk_file methods with devices. + (fhandler_base::fhandler_base): Clear {unix,win32}_path_name. + (fhandler_base::~fhandler_base): Always free {unix,win32}_path_name. + (fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names + kludge. + (fhandler_disk_file::open): Ditto. + * fhandler.h (fhandler_base::no_free_names): Eliminate. + (fhandler_base::set_no_free_names): Ditto. + * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set + unix_path_name here. + * path.cc (fchdir): Lock fd table throughout. Use new + dtable::reset_unix_path_name method to reset path. + * syscalls.cc (stat_worker): Reorganize to always call fstat method. + Pass path_conv method to fhandler_*::open. + (chroot): Elminate a goto. + +Sun Sep 30 17:37:43 2001 Christopher Faylor <cgf@cygnus.com> + + * environ.cc (winenv): Allocate exact amount of space needed for forced + windows environment variable rather than just using MAX_PATH. + +Sun Sep 30 17:10:18 2001 Christopher Faylor <cgf@cygnus.com> + + * Makefile.in: Depend on stamp to ensure rebuilding. Remove stamp file + when we've just built the DLL. + +Mon Oct 1 00:34:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * thread.cc (pthread_cond_dowait): Hopefully eliminate a race on multiple thread + wakeups. + +Sat Sep 29 18:26:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * pthread.cc (pthread_cond_timedwait): Deleted - exported from thread.cc. + (pthread_cond_wait): Deleted - exported from thread.cc. + * thread.cc (pthread_cond::BroadCast): Update to use the new syntax for + verifyable_object_isvalid (). + (pthread_cond::Signal): Ditto. Also attempt to fix the lost signal race + with pthread_cond::TimedWait(). + (check_valid_pointer): Change definiton to void const *. + (verifyable_object_isvalid): Add new parameter to allow identification of + static initializers, and return a enum rather than magic numbers. + (__pthread_create): Ditto. + (__pthread_cleanup): Ditto. + (__pthread_attr_init): Ditto. + (__pthread_attr_getinheritsched): Ditto. + (__pthread_attr_getschedparam): Ditto. + (__pthread_attr_getschedpolicy): Ditto. + (__pthread_attr_getscope): Ditto. + (__pthread_attr_setdetachstate): Ditto. + (__pthread_attr_getdetachstate): Ditto. + (__pthread_attr_setinheritsched): Ditto. + (__pthread_attr_setschedparam): Ditto. + (__pthread_attr_setschedpolicy): Ditto. + (__pthread_attr_setscope): Ditto. + (__pthread_attr_setstacksize): Ditto. + (__pthread_attr_getstacksize): Ditto. + (__pthread_attr_destroy): Ditto. + (__pthread_join): Ditto. + (__pthread_detach): Ditto. + (__pthread_suspend): Ditto. + (__pthread_continue): Ditto. + (__pthread_getschedparam): Ditto. + (__pthread_getsequence_np): Ditto. + (__pthread_key_create): Ditto. + (__pthread_key_delete): Ditto. + (__pthread_setschedparam): Ditto. + (__pthread_setspecific): Ditto. + (__pthread_getspecific): Ditto. + (__pthread_cond_destroy): Ditto. + (__pthread_cond_init): Ditto. + (__pthread_cond_broadcast): Ditto. + (__pthread_cond_signal): Ditto. + (__pthread_condattr_init): Ditto. + (__pthread_condattr_getpshared): Ditto. + (__pthread_condattr_setpshared): Ditto. + (__pthread_condattr_destroy): Ditto. + (__pthread_kill): 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_getprotocol): Ditto. + (__pthread_mutexattr_getpshared): Ditto. + (__pthread_mutexattr_gettype): Ditto. + (__pthread_mutexattr_init): Ditto. + (__pthread_mutexattr_destroy): Ditto. + (__pthread_mutexattr_setprotocol): Ditto. + (__pthread_mutexattr_setprioceiling): Ditto. + (__pthread_mutexattr_getprioceiling): Ditto. + (__pthread_mutexattr_setpshared): Ditto. + (__pthread_mutexattr_settype): Ditto. + (__sem_init): Ditto. + (__sem_destroy): Ditto. + (__sem_wait): Ditto. + (__sem_trywait): Ditto. + (__sem_post): Ditto. + (__pthread_cond_dowait): New function, contains core logic from + __pthread_cond_wait and __pthread_cond_timedwait. Decrement (*cond)->waiting + before reentering the cond access mutex to allow detection of lost signals. + (__pthread_cond_timedwait): Rename to pthread_cond_timedwait, and call + __pthread_cond_dowait after calculating the wait length. + (__pthread_cond_wait): Rename to pthread_cond_wait, and call + __pthread_cond_dowait. + * thread.h: New enum for use with verifyable_object_isvalid. + Remove the extern exporting of __pthread_cond_timedwait and __pthread_cond_wait. + +Fri Sep 28 21:18:50 2001 Christopher Faylor <cgf@cygnus.com> + + * pipe.cc (fhandler_pipe::fixup_after_fork): New method. + * fhandler.h (fhandler_pipe::fixup_after_fork): Declare new method. + +Fri Sep 28 03:23:04 2001 Christopher Faylor <cgf@cygnus.com> + + * passwd.cc (read_etc_passwd): Bother with unlocking when not + in cygwin initialization. + * grp.cc (read_etc_group): Ditto. + +Fri Sep 28 02:57:03 2001 Christopher Faylor <cgf@cygnus.com> + + * passwd.cc (read_etc_passwd): Don't bother with locking when + in cygwin initialization since there is only one thread. + * grp.cc (read_etc_group): Ditto. + +Fri Sep 28 01:50:09 2001 Christopher Faylor <cgf@cygnus.com> + + * pipe.cc (fhandler_pipe::hit_eof): Return correct value when there is + no EOF event available. + +Sat Sep 28 00:34:00 2001 Corinna Vinschen <corinna@vinschen.de> + + * mmap.cc (mmap): Move setting the access after evaluating fd. + Remove useless comment. Explain copy-on-write problem of 9x + more detailed. Don't set access to FILE_MAP_COPY on 9x only + when anonymous mapping is requested. + (fhandler_disk_file::mmap): Remove useless device check. + Add debug output. + +Fri Sep 27 07:35:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * Makefile.in: Only stamp winver_stamp on success. + +Wed Sep 26 16:02:35 2001 Christopher Faylor <cgf@cygnus.com> + + * select.cc (peek_pipe): REALLY only grab mutex when we actually got + something from the pipe. + +Tue Sep 25 21:25:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * thread.cc (pthread_cond::BroadCast): Use address with verifyable_object_isvalid(). + (pthread_cond::Signal): Ditto. + (__pthread_create): Ditto. + (__pthread_cleanup): Ditto. + (__pthread_attr_init): Ditto. + (__pthread_attr_getinheritsched): Ditto. + (__pthread_attr_getschedparam): Ditto. + (__pthread_attr_getschedpolicy): Ditto. + (__pthread_attr_getscope): Ditto. + (__pthread_attr_setdetachstate): Ditto. + (__pthread_attr_getdetachstate): Ditto. + (__pthread_attr_setinheritsched): Ditto. + (__pthread_attr_setschedparam): Ditto. + (__pthread_attr_setschedpolicy): Ditto. + (__pthread_attr_setscope): Ditto. + (__pthread_attr_setstacksize): Ditto. + (__pthread_attr_getstacksize): Ditto. + (__pthread_attr_destroy): Ditto. + (__pthread_join): Ditto. + (__pthread_detach): Ditto. + (__pthread_suspend): Ditto. + (__pthread_continue): Ditto. + (__pthread_getschedparam): Ditto. + (__pthread_getsequence_np): Ditto. + (__pthread_key_create): Ditto. + (__pthread_key_delete): Ditto. + (__pthread_setschedparam): Ditto. + (__pthread_setspecific): Ditto. + (__pthread_getspecific): Ditto. + (__pthread_cond_destroy): Ditto. + (__pthread_cond_init): Ditto. + (__pthread_cond_broadcast): Ditto. + (__pthread_cond_signal): Ditto. + (__pthread_cond_timedwait): Ditto. + (__pthread_cond_wait): Ditto. + (__pthread_condattr_init): Ditto. + (__pthread_condattr_getpshared): Ditto. + (__pthread_condattr_setpshared): Ditto. + (__pthread_condattr_destroy): Ditto. + (__pthread_kill): 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_getprotocol): Ditto. + (__pthread_mutexattr_getpshared): Ditto. + (__pthread_mutexattr_gettype): Ditto. + (__pthread_mutexattr_init): Ditto. + (__pthread_mutexattr_destroy): Ditto. + (__pthread_mutexattr_setprotocol): Ditto. + (__pthread_mutexattr_setprioceiling): Ditto. + (__pthread_mutexattr_getprioceiling): Ditto. + (__pthread_mutexattr_setpshared): Ditto. + (__pthread_mutexattr_settype): Ditto. + (__sem_init): Ditto. + (__sem_destroy): Ditto. + (__sem_wait): Ditto. + (__sem_trywait): Ditto. + (__sem_post): Ditto. + (verifyable_object_isvalid): Recieve a pointer to a pointer for verification. + (__pthread_mutexattr_getprotocol): Fix typo in magic number. + (__pthread_mutexattr_getpshared): Ditto. + (__pthread_mutexattr_gettype): Ditto. + * thread.h (verifyable_object_isvalid): Change prototype to recieve a pointer to a + pointer for verification. + * include/pthread.h: Fix typo for __cleanup_routine_type typedef. (Contrib from Net). + +Tue Sep 25 02:09:42 2001 Christopher Faylor <cgf@redhat.com> + + * select.cc (fhandler_tty_common::ready_for_read): Rewrite to correctly + call peek_pipe. + +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 accommodate 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): Accommodate 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 accommodate 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): Accommodate 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): Accommodate extra argument to stackdump. + (handle_exceptions): Ditto. + (sig_handle): Ditto. + (interrupt_on_return): Accommodate 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): Accommodate relative path names again. Accommodate + 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 accommodate 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): Accommodate 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): Accommodate + 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): Accommodate 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 accommodate + 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/cygmagic b/winsup/cygwin/cygmagic new file mode 100755 index 000000000..5589b26f6 --- /dev/null +++ b/winsup/cygwin/cygmagic @@ -0,0 +1,20 @@ +#!/bin/sh +file_magic=$1; shift +gcc=$1; shift +file=$1; shift +trap "rm -f /tmp/$$.magic" 0 1 2 15 +cat <<EOF > $file_magic +/* autogenerated - do not edit */ +#include "$file" +EOF +while [ -n "$1" ]; do + define=$1; shift + struct=$1; shift + sum=`$gcc -E $file | sed -n "/^$struct/,/^};/p" | sed -e 's/[ ]//g' -e '/^$/d' | sum | awk '{printf "0x%x", $1}'` + echo "#define $define $sum" + curr=`sed -n "s/^#[ ]*define CURR_$define[ ][ ]*\([^ ][^ ]*\)/\1/p" $file` + [ "$curr" == "$sum" ] || echo "*** WARNING WARNING WARNING WARNING WARNING *** +*** $file: magic number for $define changed old $curr != new $sum +*** WARNING WARNING WARNING WARNING WARNING ***" 1>&2 +done >> $file_magic +exit 0 diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc new file mode 100644 index 000000000..1ce4893d2 --- /dev/null +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -0,0 +1,857 @@ +/* fhandler_disk_file.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 <sys/fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/cygwin.h> +#include <signal.h> +#include "cygerrno.h" +#include "perprocess.h" +#include "security.h" +#include "cygwin/version.h" +#include "fhandler.h" +#include "path.h" +#include "dtable.h" +#include "cygheap.h" +#include "shared_info.h" +#include "sigproc.h" +#include "pinfo.h" +#include <assert.h> + +#define _COMPILING_NEWLIB +#include <dirent.h> + +static int +num_entries (const char *win32_name) +{ + WIN32_FIND_DATA buf; + HANDLE handle; + char buf1[MAX_PATH]; + int count = 0; + + strcpy (buf1, win32_name); + int len = strlen (buf1); + if (len == 0 || isdirsep (buf1[len - 1])) + strcat (buf1, "*"); + else + strcat (buf1, "/*"); /* */ + + handle = FindFirstFileA (buf1, &buf); + + if (handle == INVALID_HANDLE_VALUE) + return 0; + count ++; + while (FindNextFileA (handle, &buf)) + { + if ((buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + count ++; + } + FindClose (handle); + return count; +} + +int +fhandler_disk_file::fstat (struct stat *buf, path_conv *pc) +{ + int res = -1; + int oret; + uid_t uid; + gid_t gid; + int open_flags = O_RDONLY | O_BINARY | O_DIROPEN; + + if (!pc) + return fstat_helper (buf); + + if ((oret = open (pc, open_flags, 0))) + /* ok */; + else + { + int ntsec_atts = 0; + /* If we couldn't open the file, try a "query open" with no permissions. + This will allow us to determine *some* things about the file, at least. */ + set_query_open (TRUE); + if ((oret = open (pc, open_flags, 0))) + /* ok */; + else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES + && !get_file_attribute (TRUE, get_win32_name (), &ntsec_atts, &uid, &gid) + && !ntsec_atts && uid == myself->uid && gid == myself->gid) + { + /* Check a special case here. If ntsec is ON it happens + that a process creates a file using mode 000 to disallow + other processes access. In contrast to UNIX, this results + in a failing open call in the same process. Check that + case. */ + set_file_attribute (TRUE, get_win32_name (), 0400); + oret = open (pc, open_flags, 0); + set_file_attribute (TRUE, get_win32_name (), ntsec_atts); + } + } + if (oret) + { + res = fstat_helper (buf); + /* The number of links to a directory includes the + number of subdirectories in the directory, since all + those subdirectories point to it. + This is too slow on remote drives, so we do without it and + set the number of links to 2. */ + /* Unfortunately the count of 2 confuses `find (1)' command. So + let's try it with `1' as link count. */ + if (pc->isdir ()) + buf->st_nlink = (pc->isremote () + ? 1 : num_entries (pc->get_win32 ())); + close (); + } + else if (pc->exists ()) + { + /* Unfortunately, the above open may fail if the file exists, though. + So we have to care for this case here, too. */ + WIN32_FIND_DATA wfd; + HANDLE handle; + buf->st_nlink = 1; + if (pc->isdir () && pc->isremote ()) + buf->st_nlink = num_entries (pc->get_win32 ()); + buf->st_dev = FHDEVN (FH_DISK) << 8; + buf->st_ino = hash_path_name (0, pc->get_win32 ()); + if (pc->isdir ()) + buf->st_mode = S_IFDIR; + else if (pc->issymlink ()) + buf->st_mode = S_IFLNK; + else if (pc->issocket ()) + buf->st_mode = S_IFSOCK; + else + buf->st_mode = S_IFREG; + if (!pc->has_acls () + || get_file_attribute (TRUE, pc->get_win32 (), + &buf->st_mode, + &buf->st_uid, &buf->st_gid)) + { + buf->st_mode |= STD_RBITS | STD_XBITS; + if (!(pc->has_attribute (FILE_ATTRIBUTE_READONLY))) + buf->st_mode |= STD_WBITS; + if (pc->issymlink ()) + buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; + get_file_attribute (FALSE, pc->get_win32 (), + NULL, &buf->st_uid, &buf->st_gid); + } + if ((handle = FindFirstFile (pc->get_win32 (), &wfd)) + != INVALID_HANDLE_VALUE) + { + /* This is for FAT filesystems, which don't support atime/ctime */ + if (wfd.ftLastAccessTime.dwLowDateTime == 0 + && wfd.ftLastAccessTime.dwHighDateTime == 0) + wfd.ftLastAccessTime = wfd.ftLastWriteTime; + if (wfd.ftCreationTime.dwLowDateTime == 0 + && wfd.ftCreationTime.dwHighDateTime == 0) + wfd.ftCreationTime = wfd.ftLastWriteTime; + + buf->st_atime = to_time_t (&wfd.ftLastAccessTime); + buf->st_mtime = to_time_t (&wfd.ftLastWriteTime); + buf->st_ctime = to_time_t (&wfd.ftCreationTime); + buf->st_size = wfd.nFileSizeLow; + buf->st_blksize = S_BLKSIZE; + buf->st_blocks = ((unsigned long) buf->st_size + + S_BLKSIZE-1) / S_BLKSIZE; + FindClose (handle); + } + res = 0; + } + + return res; +} + +int +fhandler_disk_file::fstat_helper (struct stat *buf) +{ + int res = 0; // avoid a compiler warning + BY_HANDLE_FILE_INFORMATION local; + save_errno saved_errno; + + /* NT 3.51 seems to have a bug when attempting to get vol serial + numbers. This loop gets around this. */ + for (int i = 0; i < 2; i++) + { + if (!(res = GetFileInformationByHandle (get_handle (), &local))) + break; + if (local.dwVolumeSerialNumber && (long) local.dwVolumeSerialNumber != -1) + break; + } + debug_printf ("%d = GetFileInformationByHandle (%s, %d)", + res, get_win32_name (), get_handle ()); + if (res == 0) + { + /* GetFileInformationByHandle will fail if it's given stdin/out/err + or a pipe*/ + DWORD lsize, hsize; + + if (GetFileType (get_handle ()) != FILE_TYPE_DISK) + buf->st_mode = S_IFCHR; + + lsize = GetFileSize (get_handle (), &hsize); + if (lsize == 0xffffffff && GetLastError () != NO_ERROR) + buf->st_mode = S_IFCHR; + else + buf->st_size = lsize; + /* We expect these to fail! */ + buf->st_mode |= STD_RBITS | STD_WBITS; + buf->st_blksize = S_BLKSIZE; + buf->st_ino = get_namehash (); + syscall_printf ("0 = fstat (, %p)", buf); + return 0; + } + + if (!get_win32_name ()) + { + saved_errno.set (ENOENT); + return -1; + } + + /* This is for FAT filesystems, which don't support atime/ctime */ + if (local.ftLastAccessTime.dwLowDateTime == 0 + && local.ftLastAccessTime.dwHighDateTime == 0) + local.ftLastAccessTime = local.ftLastWriteTime; + if (local.ftCreationTime.dwLowDateTime == 0 + && local.ftCreationTime.dwHighDateTime == 0) + local.ftCreationTime = local.ftLastWriteTime; + + buf->st_atime = to_time_t (&local.ftLastAccessTime); + buf->st_mtime = to_time_t (&local.ftLastWriteTime); + buf->st_ctime = to_time_t (&local.ftCreationTime); + buf->st_nlink = local.nNumberOfLinks; + buf->st_dev = local.dwVolumeSerialNumber; + buf->st_size = local.nFileSizeLow; + + /* Allocate some place to determine the root directory. Need to allocate + enough so that rootdir can add a trailing slash if path starts with \\. */ + char root[strlen (get_win32_name ()) + 3]; + strcpy (root, get_win32_name ()); + + /* Assume that if a drive has ACL support it MAY have valid "inodes". + It definitely does not have valid inodes if it does not have ACL + support. */ + switch (has_acls () ? GetDriveType (rootdir (root)) : DRIVE_UNKNOWN) + { + case DRIVE_FIXED: + case DRIVE_REMOVABLE: + case DRIVE_CDROM: + case DRIVE_RAMDISK: + /* Although the documentation indicates otherwise, it seems like + "inodes" on these devices are persistent, at least across reboots. */ + buf->st_ino = local.nFileIndexHigh | local.nFileIndexLow; + break; + default: + /* Either the nFileIndex* fields are unreliable or unavailable. Use the + next best alternative. */ + buf->st_ino = get_namehash (); + break; + } + + buf->st_blksize = S_BLKSIZE; + buf->st_blocks = ((unsigned long) buf->st_size + S_BLKSIZE-1) / S_BLKSIZE; + + buf->st_mode = 0; + /* Using a side effect: get_file_attibutes checks for + directory. This is used, to set S_ISVTX, if needed. */ + if (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buf->st_mode = S_IFDIR; + else if (get_symlink_p ()) + buf->st_mode = S_IFLNK; + else if (get_socket_p ()) + buf->st_mode = S_IFSOCK; + if (get_file_attribute (has_acls (), get_win32_name (), &buf->st_mode, + &buf->st_uid, &buf->st_gid) == 0) + { + /* If read-only attribute is set, modify ntsec return value */ + if ((local.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + && !get_symlink_p ()) + buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + + if (!(buf->st_mode & S_IFMT)) + buf->st_mode |= S_IFREG; + } + else + { + buf->st_mode |= STD_RBITS; + + if (!(local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buf->st_mode |= STD_WBITS; + /* | S_IWGRP | S_IWOTH; we don't give write to group etc */ + + if (buf->st_mode & S_IFDIR) + buf->st_mode |= S_IFDIR | STD_XBITS; + else if (buf->st_mode & S_IFMT) + /* nothing */; + else if (get_socket_p ()) + buf->st_mode |= S_IFSOCK; + else + switch (GetFileType (get_handle ())) + { + case FILE_TYPE_CHAR: + case FILE_TYPE_UNKNOWN: + buf->st_mode |= S_IFCHR; + break; + case FILE_TYPE_DISK: + buf->st_mode |= S_IFREG; + if (!dont_care_if_execable () && !get_execable_p ()) + { + DWORD cur, done; + char magic[3]; + + /* First retrieve current position, set to beginning + of file if not already there. */ + cur = SetFilePointer (get_handle(), 0, NULL, FILE_CURRENT); + if (cur != INVALID_SET_FILE_POINTER && + (!cur || + SetFilePointer (get_handle(), 0, NULL, FILE_BEGIN) + != INVALID_SET_FILE_POINTER)) + { + /* FIXME should we use /etc/magic ? */ + magic[0] = magic[1] = magic[2] = '\0'; + if (ReadFile (get_handle (), magic, 3, &done, NULL) && + has_exec_chars (magic, done)) + set_execable_p (); + SetFilePointer (get_handle(), cur, NULL, FILE_BEGIN); + } + } + if (get_execable_p ()) + buf->st_mode |= STD_XBITS; + break; + case FILE_TYPE_PIPE: + buf->st_mode |= S_IFSOCK; + break; + } + } + + syscall_printf ("0 = fstat (, %p) st_atime=%x st_size=%d, st_mode=%p, st_ino=%d, sizeof=%d", + buf, buf->st_atime, buf->st_size, buf->st_mode, + (int) buf->st_ino, sizeof (*buf)); + + return 0; +} + +fhandler_disk_file::fhandler_disk_file (DWORD devtype) : + fhandler_base (devtype) +{ +} + +fhandler_disk_file::fhandler_disk_file () : + fhandler_base (FH_DISK) +{ +} + +int +fhandler_disk_file::open (path_conv *real_path, int flags, mode_t mode) +{ + if (real_path->case_clash && flags & O_CREAT) + { + debug_printf ("case clash detected"); + set_errno (ECASECLASH); + return 0; + } + + if (real_path->isbinary ()) + { + set_r_binary (1); + set_w_binary (1); + } + + set_has_acls (real_path->has_acls ()); + set_isremote (real_path->isremote ()); + + if (real_path->isdir ()) + flags |= O_DIROPEN; + + int res = this->fhandler_base::open (real_path, flags, mode); + + if (!res) + goto out; + + /* This is for file systems known for having a buggy CreateFile call + which might return a valid HANDLE without having actually opened + the file. + The only known file system to date is the SUN NFS Solstice Client 3.1 + which returns a valid handle when trying to open a file in a nonexistent + directory. */ + if (real_path->has_buggy_open () + && GetFileAttributes (win32_path_name) == (DWORD) -1) + { + debug_printf ("Buggy open detected."); + close (); + set_errno (ENOENT); + return 0; + } + + if (flags & O_APPEND) + SetFilePointer (get_handle(), 0, 0, FILE_END); + + set_symlink_p (real_path->issymlink ()); + set_execable_p (real_path->exec_state ()); + set_socket_p (real_path->issocket ()); + +out: + syscall_printf ("%d = fhandler_disk_file::open (%s, %p)", res, + get_win32_name (), flags); + return res; +} + +int +fhandler_disk_file::close () +{ + int res = this->fhandler_base::close (); + if (!res) + cygwin_shared->delqueue.process_queue (); + return res; +} + +/* + * FIXME !!! + * The correct way to do this to get POSIX locking + * semantics is to keep a linked list of posix lock + * requests and map them into Win32 locks. The problem + * is that Win32 does not deal correctly with overlapping + * lock requests. Also another pain is that Win95 doesn't do + * non-blocking or non exclusive locks at all. For '95 just + * convert all lock requests into blocking,exclusive locks. + * This shouldn't break many apps but denying all locking + * would. + * For now just convert to Win32 locks and hope for the best. + */ + +int +fhandler_disk_file::lock (int cmd, struct flock *fl) +{ + int win32_start; + int win32_len; + DWORD win32_upper; + DWORD startpos; + + /* + * We don't do getlck calls yet. + */ + + if (cmd == F_GETLK) + { + set_errno (ENOSYS); + return -1; + } + + /* + * Calculate where in the file to start from, + * then adjust this by fl->l_start. + */ + + switch (fl->l_whence) + { + case SEEK_SET: + startpos = 0; + break; + case SEEK_CUR: + if ((off_t) (startpos = lseek (0, SEEK_CUR)) == (off_t)-1) + return -1; + break; + case SEEK_END: + { + BY_HANDLE_FILE_INFORMATION finfo; + if (GetFileInformationByHandle (get_handle(), &finfo) == 0) + { + __seterrno (); + return -1; + } + startpos = finfo.nFileSizeLow; /* Nowhere to keep high word */ + break; + } + default: + set_errno (EINVAL); + return -1; + } + + /* + * Now the fun starts. Adjust the start and length + * fields until they make sense. + */ + + win32_start = startpos + fl->l_start; + if (fl->l_len < 0) + { + win32_start -= fl->l_len; + win32_len = -fl->l_len; + } + else + win32_len = fl->l_len; + + if (win32_start < 0) + { + /* watch the signs! */ + win32_len -= -win32_start; + if (win32_len <= 0) + { + /* Failure ! */ + set_errno (EINVAL); + return -1; + } + win32_start = 0; + } + + /* + * Special case if len == 0 for POSIX means lock + * to the end of the entire file (and all future extensions). + */ + if (win32_len == 0) + { + win32_len = 0xffffffff; + win32_upper = wincap.lock_file_highword (); + } + else + win32_upper = 0; + + BOOL res; + + if (wincap.has_lock_file_ex ()) + { + DWORD lock_flags = (cmd == F_SETLK) ? LOCKFILE_FAIL_IMMEDIATELY : 0; + lock_flags |= (fl->l_type == F_WRLCK) ? LOCKFILE_EXCLUSIVE_LOCK : 0; + + OVERLAPPED ov; + + ov.Internal = 0; + ov.InternalHigh = 0; + ov.Offset = (DWORD)win32_start; + ov.OffsetHigh = 0; + ov.hEvent = (HANDLE) 0; + + if (fl->l_type == F_UNLCK) + { + res = UnlockFileEx (get_handle (), 0, (DWORD)win32_len, win32_upper, &ov); + } + else + { + res = LockFileEx (get_handle (), lock_flags, 0, (DWORD)win32_len, + win32_upper, &ov); + /* Deal with the fail immediately case. */ + /* + * FIXME !! I think this is the right error to check for + * but I must admit I haven't checked.... + */ + if ((res == 0) && (lock_flags & LOCKFILE_FAIL_IMMEDIATELY) && + (GetLastError () == ERROR_LOCK_FAILED)) + { + set_errno (EAGAIN); + return -1; + } + } + } + else + { + /* Windows 95 -- use primitive lock call */ + if (fl->l_type == F_UNLCK) + res = UnlockFile (get_handle (), (DWORD)win32_start, 0, (DWORD)win32_len, + win32_upper); + else + res = LockFile (get_handle (), (DWORD)win32_start, 0, (DWORD)win32_len, win32_upper); + } + + if (res == 0) + { + __seterrno (); + return -1; + } + + return 0; +} + +DIR * +fhandler_disk_file::opendir (path_conv& real_name) +{ + DIR *dir; + DIR *res = NULL; + size_t len; + + if (!real_name.isdir ()) + set_errno (ENOTDIR); + else if ((len = strlen (real_name))> MAX_PATH - 3) + set_errno (ENAMETOOLONG); + else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL) + set_errno (ENOMEM); + else if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL) + { + free (dir); + set_errno (ENOMEM); + } + else if ((dir->__d_dirent = + (struct dirent *) malloc (sizeof (struct dirent))) == NULL) + { + free (dir->__d_dirname); + free (dir); + set_errno (ENOMEM); + } + else + { + strcpy (dir->__d_dirname, real_name.get_win32 ()); + dir->__d_dirent->d_version = __DIRENT_VERSION; + cygheap_fdnew fd; + fd = this; + fd->set_nohandle (true); + dir->__d_dirent->d_fd = fd; + dir->__d_u.__d_data.__fh = this; + /* FindFirstFile doesn't seem to like duplicate /'s. */ + len = strlen (dir->__d_dirname); + if (len == 0 || SLASH_P (dir->__d_dirname[len - 1])) + strcat (dir->__d_dirname, "*"); + else + strcat (dir->__d_dirname, "\\*"); /**/ + dir->__d_cookie = __DIRENT_COOKIE; + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + dir->__d_position = 0; + dir->__d_dirhash = get_namehash (); + + res = dir; + } + + syscall_printf ("%p = opendir (%s)", res, get_name ()); + return res; +} + +struct dirent * +fhandler_disk_file::readdir (DIR *dir) +{ + WIN32_FIND_DATA buf; + HANDLE handle; + struct dirent *res = NULL; + + if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE + && dir->__d_position == 0) + { + handle = FindFirstFileA (dir->__d_dirname, &buf); + DWORD lasterr = GetLastError (); + dir->__d_u.__d_data.__handle = handle; + if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) + { + seterrno_from_win_error (__FILE__, __LINE__, lasterr); + return res; + } + } + else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE) + { + return res; + } + else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf)) + { + DWORD lasterr = GetLastError (); + (void) FindClose (dir->__d_u.__d_data.__handle); + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + /* POSIX says you shouldn't set errno when readdir can't + find any more files; so, if another error we leave it set. */ + if (lasterr != ERROR_NO_MORE_FILES) + seterrno_from_win_error (__FILE__, __LINE__, lasterr); + syscall_printf ("%p = readdir (%p)", res, dir); + return res; + } + + /* We get here if `buf' contains valid data. */ + strcpy (dir->__d_dirent->d_name, buf.cFileName); + + /* Check for Windows shortcut. If it's a Cygwin or U/WIN + symlink, drop the .lnk suffix. */ + if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + { + char *c = dir->__d_dirent->d_name; + int len = strlen (c); + if (strcasematch (c + len - 4, ".lnk")) + { + char fbuf[MAX_PATH + 1]; + strcpy (fbuf, dir->__d_dirname); + strcpy (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name); + path_conv fpath (fbuf, PC_SYM_NOFOLLOW); + if (fpath.issymlink ()) + c[len - 4] = '\0'; + } + } + + /* Compute d_ino by combining filename hash with the directory hash + (which was stored in dir->__d_dirhash when opendir was called). */ + if (buf.cFileName[0] == '.') + { + if (buf.cFileName[1] == '\0') + dir->__d_dirent->d_ino = dir->__d_dirhash; + else if (buf.cFileName[1] != '.' || buf.cFileName[2] != '\0') + goto hashit; + else + { + char *p, up[strlen (dir->__d_dirname) + 1]; + strcpy (up, dir->__d_dirname); + if (!(p = strrchr (up, '\\'))) + goto hashit; + *p = '\0'; + if (!(p = strrchr (up, '\\'))) + dir->__d_dirent->d_ino = hash_path_name (0, "."); + else + { + *p = '\0'; + dir->__d_dirent->d_ino = hash_path_name (0, up); + } + } + } + else + { + hashit: + ino_t dino = hash_path_name (dir->__d_dirhash, "\\"); + dir->__d_dirent->d_ino = hash_path_name (dino, buf.cFileName); + } + + dir->__d_position++; + res = dir->__d_dirent; + syscall_printf ("%p = readdir (%p) (%s)", + &dir->__d_dirent, dir, buf.cFileName); + return res; +} + +off_t +fhandler_disk_file::telldir (DIR *dir) +{ + return dir->__d_position; +} + +void +fhandler_disk_file::seekdir (DIR *dir, off_t loc) +{ + rewinddir (dir); + while (loc > dir->__d_position) + if (!readdir (dir)) + break; +} + +void +fhandler_disk_file::rewinddir (DIR *dir) +{ + if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE) + { + (void) FindClose (dir->__d_u.__d_data.__handle); + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + } + dir->__d_position = 0; +} + +int +fhandler_disk_file::closedir (DIR *dir) +{ + int res = 0; + if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE && + FindClose (dir->__d_u.__d_data.__handle) == 0) + { + __seterrno (); + res = -1; + } + syscall_printf ("%d = closedir (%p)", res, dir); + return 0; +} + +fhandler_cygdrive::fhandler_cygdrive (int unit) : + fhandler_disk_file (FH_CYGDRIVE), unit (unit), ndrives (0), pdrive (NULL) +{ +} + +#define DRVSZ sizeof ("x:\\") +void +fhandler_cygdrive::set_drives () +{ + const int len = 1 + 26 * DRVSZ; + win32_path_name = (char *) crealloc (win32_path_name, len); + + ndrives = GetLogicalDriveStrings (len, win32_path_name) / DRVSZ; + pdrive = win32_path_name; +} + +int +fhandler_cygdrive::fstat (struct stat *buf, path_conv *pc) +{ + if (!iscygdrive_root ()) + return fhandler_disk_file::fstat (buf, pc); + buf->st_mode = S_IFDIR | 0555; + if (!ndrives) + set_drives (); + buf->st_nlink = ndrives; + return 0; +} + +DIR * +fhandler_cygdrive::opendir (path_conv& real_name) +{ + DIR *dir; + + dir = fhandler_disk_file::opendir (real_name); + if (dir && iscygdrive_root () && !ndrives) + set_drives (); + + return dir; +} + +struct dirent * +fhandler_cygdrive::readdir (DIR *dir) +{ + if (!iscygdrive_root ()) + return fhandler_disk_file::readdir (dir); + if (!pdrive || !*pdrive) + { + set_errno (ENMFILE); + return NULL; + } + if (GetFileAttributes (pdrive) == (DWORD) -1) + { + pdrive += DRVSZ; + return readdir (dir); + } + *dir->__d_dirent->d_name = cyg_tolower (*pdrive); + dir->__d_dirent->d_name[1] = '\0'; + dir->__d_position++; + pdrive += DRVSZ; + syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir, + dir->__d_dirent->d_name); + return dir->__d_dirent; +} + +off_t +fhandler_cygdrive::telldir (DIR *dir) +{ + return fhandler_disk_file::telldir (dir); +} + +void +fhandler_cygdrive::seekdir (DIR *dir, off_t loc) +{ + if (!iscygdrive_root ()) + return fhandler_disk_file::seekdir (dir, loc); + + for (pdrive = win32_path_name, dir->__d_position = -1; *pdrive; pdrive += DRVSZ) + if (++dir->__d_position >= loc) + break; + + return; +} + +void +fhandler_cygdrive::rewinddir (DIR *dir) +{ + if (!iscygdrive_root ()) + return fhandler_disk_file::rewinddir (dir); + pdrive = win32_path_name; + dir->__d_position = 0; + return; +} + +int +fhandler_cygdrive::closedir (DIR *dir) +{ + if (!iscygdrive_root ()) + return fhandler_disk_file::closedir (dir); + pdrive = win32_path_name; + return -1; +} diff --git a/winsup/cygwin/how-fhandlers-work.txt b/winsup/cygwin/how-fhandlers-work.txt new file mode 100644 index 000000000..5e810a780 --- /dev/null +++ b/winsup/cygwin/how-fhandlers-work.txt @@ -0,0 +1,65 @@ +Copyright 2001 Red Hat Inc., Robert Collins + +fhandlers are the core mechanism by which cygwin provides a file descripter (fd) +interface to things such as a random number generated, winsock sockets, raw disk +devices, the clipboard, the console and so on. Under unix access to all such +devices is via a combination of IOCTL's and open/close/read/write calls. Some +special functions do exist - such as bind () and listen () for sockets, but +these consistently operate on fd's. Under Win32 there are disparate interfaces +that have little in common with each other. See for example Direct Sound and +the Clipboard. + +The fhandler class provides all open,read,write,close, ioctl and fork()/exec() +functionality for the fd interface. The base class operates on win32 backed +files. The various derived classes utilise win32 primitives to provide their +specific functionality. + +When a file is opened - not necesarily via open() a fd is assigned to it. The fd +includes a pointer to the actual fhandler that operates this specific file. All +file-oriented system calls then operate off this basic structure. + +For example, lets examine lseek (). + +extern "C" off_t +_lseek (int fd, off_t pos, int dir) +{ + off_t res; + sigframe thisframe (mainthread); + + if (dir != SEEK_SET && dir != SEEK_CUR && dir != SEEK_END) + { + set_errno (EINVAL); + res = -1; + } + else if (cygheap->fdtab.not_open (fd)) + { + set_errno (EBADF); + res = -1; + } + else + { + res = cygheap->fdtab[fd]->lseek (pos, dir); + } + syscall_printf ("%d = lseek (%d, %d, %d)", res, fd, pos, dir); + + return res; +} + +The sigframe thisframe (mainthread); is signal related - see +"how_signals_work.txt". + +The if, else if, else tests (in order) +* the validity of the dir parameter, +* is the fd being passed actually open? (cannot seek on a closed fd) +* call the lseek virtual function in the associated fhandler. + +So as you can see, there is no code that attempts to understand the nature of +the fhandler. + +fhandlers that make cross-function-call use of win32 objects that are not +inheritable cross-process need to implement fixup-after-fork and recreate those +objects. HANDLES can be inherited, but memory mapped regions (for example) +cannot. + +For an example step-by-step to create a new fhandler, see +../doc/fhandler-tut.txt diff --git a/winsup/cygwin/newsym b/winsup/cygwin/newsym new file mode 100755 index 000000000..688a8c6f8 --- /dev/null +++ b/winsup/cygwin/newsym @@ -0,0 +1,24 @@ +#!/bin/sh -x +lib=$1; shift +as=$1; shift +ar=$1; shift +ranlib=$1; shift +rm -rf newsym.dir +trap "rm -rf newsym.dir" 0 1 2 15 +mkdir newsym.dir +while [ -n "$1" ]; do + newsym=$1; shift + oldsym=$1; shift + cat <<EOF > newsym.dir/$newsym.s + .section .idata$6 + .extern __imp__$oldsym + .extern __head_cygwin1_dll + .section .text + .global _$newsym +_$newsym: + jmp *__imp__$oldsym +EOF + $as -o newsym.dir/$newsym.o newsym.dir/$newsym.s +done +$ar cru $lib newsym.dir/*.o +$ranlib $lib diff --git a/winsup/cygwin/regex/COPYRIGHT b/winsup/cygwin/regex/COPYRIGHT new file mode 100644 index 000000000..30c1f7a48 --- /dev/null +++ b/winsup/cygwin/regex/COPYRIGHT @@ -0,0 +1,20 @@ +Copyright 1992, 1993, 1994, 1997 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. diff --git a/winsup/cygwin/regex/cclass.h b/winsup/cygwin/regex/cclass.h new file mode 100644 index 000000000..7ddb44afb --- /dev/null +++ b/winsup/cygwin/regex/cclass.h @@ -0,0 +1,31 @@ +/* character-class table */ +static struct cclass { + const char *name; + const char *chars; + const char *multis; +} cclasses[] = { + {"alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789", ""}, + {"alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + ""}, + {"blank", " \t", ""}, + {"cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ + \25\26\27\30\31\32\33\34\35\36\37\177", ""}, + {"digit", "0123456789", ""}, + {"graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ + 0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""}, + {"lower", "abcdefghijklmnopqrstuvwxyz", + ""}, + {"print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ + 0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", + ""}, + {"punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""}, + {"space", "\t\n\v\f\r ", ""}, + {"upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + ""}, + {"xdigit", "0123456789ABCDEFabcdef", + ""}, + {NULL, 0, ""} +}; diff --git a/winsup/cygwin/regex/cname.h b/winsup/cygwin/regex/cname.h new file mode 100644 index 000000000..1000f603e --- /dev/null +++ b/winsup/cygwin/regex/cname.h @@ -0,0 +1,102 @@ +/* character-name table */ +static struct cname { + const char *name; + char code; +} cnames[] = { + {"NUL", '\0'}, + {"SOH", '\001'}, + {"STX", '\002'}, + {"ETX", '\003'}, + {"EOT", '\004'}, + {"ENQ", '\005'}, + {"ACK", '\006'}, + {"BEL", '\007'}, + {"alert", '\007'}, + {"BS", '\010'}, + {"backspace", '\b'}, + {"HT", '\011'}, + {"tab", '\t'}, + {"LF", '\012'}, + {"newline", '\n'}, + {"VT", '\013'}, + {"vertical-tab", '\v'}, + {"FF", '\014'}, + {"form-feed", '\f'}, + {"CR", '\015'}, + {"carriage-return", '\r'}, + {"SO", '\016'}, + {"SI", '\017'}, + {"DLE", '\020'}, + {"DC1", '\021'}, + {"DC2", '\022'}, + {"DC3", '\023'}, + {"DC4", '\024'}, + {"NAK", '\025'}, + {"SYN", '\026'}, + {"ETB", '\027'}, + {"CAN", '\030'}, + {"EM", '\031'}, + {"SUB", '\032'}, + {"ESC", '\033'}, + {"IS4", '\034'}, + {"FS", '\034'}, + {"IS3", '\035'}, + {"GS", '\035'}, + {"IS2", '\036'}, + {"RS", '\036'}, + {"IS1", '\037'}, + {"US", '\037'}, + {"space", ' '}, + {"exclamation-mark", '!'}, + {"quotation-mark", '"'}, + {"number-sign", '#'}, + {"dollar-sign", '$'}, + {"percent-sign", '%'}, + {"ampersand", '&'}, + {"apostrophe", '\''}, + {"left-parenthesis", '('}, + {"right-parenthesis", ')'}, + {"asterisk", '*'}, + {"plus-sign", '+'}, + {"comma", ','}, + {"hyphen", '-'}, + {"hyphen-minus", '-'}, + {"period", '.'}, + {"full-stop", '.'}, + {"slash", '/'}, + {"solidus", '/'}, + {"zero", '0'}, + {"one", '1'}, + {"two", '2'}, + {"three", '3'}, + {"four", '4'}, + {"five", '5'}, + {"six", '6'}, + {"seven", '7'}, + {"eight", '8'}, + {"nine", '9'}, + {"colon", ':'}, + {"semicolon", ';'}, + {"less-than-sign", '<'}, + {"equals-sign", '='}, + {"greater-than-sign", '>'}, + {"question-mark", '?'}, + {"commercial-at", '@'}, + {"left-square-bracket", '['}, + {"backslash", '\\'}, + {"reverse-solidus", '\\'}, + {"right-square-bracket", ']'}, + {"circumflex", '^'}, + {"circumflex-accent", '^'}, + {"underscore", '_'}, + {"low-line", '_'}, + {"grave-accent", '`'}, + {"left-brace", '{'}, + {"left-curly-bracket", '{'}, + {"vertical-line", '|'}, + {"right-brace", '}'}, + {"right-curly-bracket", '}'}, + {"tilde", '~'}, + {"DEL", '\177'}, + {NULL, 0} +}; diff --git a/winsup/cygwin/regex/engine.c b/winsup/cygwin/regex/engine.c new file mode 100644 index 000000000..919fe3f64 --- /dev/null +++ b/winsup/cygwin/regex/engine.c @@ -0,0 +1,1019 @@ +/* + * The matching engine and friends. This file is #included by regexec.c + * after suitable #defines of a variety of macros used herein, so that + * different state representations can be used without duplicating masses + * of code. + */ + +#ifdef SNAMES +#define matcher smatcher +#define fast sfast +#define slow sslow +#define dissect sdissect +#define backref sbackref +#define step sstep +#define print sprint +#define at sat +#define match smat +#endif +#ifdef LNAMES +#define matcher lmatcher +#define fast lfast +#define slow lslow +#define dissect ldissect +#define backref lbackref +#define step lstep +#define print lprint +#define at lat +#define match lmat +#endif + +/* another structure passed up and down to avoid zillions of parameters */ +struct match { + struct re_guts *g; + int eflags; + regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ + char *offp; /* offsets work from here */ + char *beginp; /* start of string -- virtual NUL precedes */ + char *endp; /* end of string -- virtual NUL here */ + char *coldp; /* can be no match starting before here */ + char **lastpos; /* [nplus+1] */ + STATEVARS; + states st; /* current states */ + states fresh; /* states for a fresh start */ + states tmp; /* temporary */ + states empty; /* empty set of states */ +}; + +#include "engine.ih" + +#ifdef REDEBUG +#define SP(t, s, c) print(m, t, s, c, stdout) +#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) +#define NOTE(str) { if (m->eflags®_TRACE) printf("=%s\n", (str)); } +#else +#define SP(t, s, c) /* nothing */ +#define AT(t, p1, p2, s1, s2) /* nothing */ +#define NOTE(s) /* nothing */ +#endif + +/* + - matcher - the actual matching engine + == static int matcher(register struct re_guts *g, char *string, \ + == size_t nmatch, regmatch_t pmatch[], int eflags); + */ +static int /* 0 success, REG_NOMATCH failure */ +matcher(g, string, nmatch, pmatch, eflags) +register struct re_guts *g; +char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register char *endp; + register int i; + struct match mv; + register struct match *m = &mv; + register char *dp; + const register sopno gf = g->firststate+1; /* +1 for OEND */ + const register sopno gl = g->laststate; + char *start; + char *stop; + + /* simplify the situation where possible */ + if (g->cflags®_NOSUB) + nmatch = 0; + if (eflags®_STARTEND) { + start = string + pmatch[0].rm_so; + stop = string + pmatch[0].rm_eo; + } else { + start = string; + stop = start + strlen(start); + } + if (stop < start) + return(REG_INVARG); + + /* prescreening; this does wonders for this rather slow code */ + if (g->must != NULL) { + for (dp = start; dp < stop; dp++) + if (*dp == g->must[0] && stop - dp >= g->mlen && + memcmp(dp, g->must, (size_t)g->mlen) == 0) + break; + if (dp == stop) /* we didn't find g->must */ + return(REG_NOMATCH); + } + + /* match struct setup */ + m->g = g; + m->eflags = eflags; + m->pmatch = NULL; + m->lastpos = NULL; + m->offp = string; + m->beginp = start; + m->endp = stop; + STATESETUP(m, 4); + SETUP(m->st); + SETUP(m->fresh); + SETUP(m->tmp); + SETUP(m->empty); + CLEAR(m->empty); + + /* this loop does only one repetition except for backrefs */ + for (;;) { + endp = fast(m, start, stop, gf, gl); + if (endp == NULL) { /* a miss */ + STATETEARDOWN(m); + return(REG_NOMATCH); + } + if (nmatch == 0 && !g->backrefs) + break; /* no further info needed */ + + /* where? */ + assert(m->coldp != NULL); + for (;;) { + NOTE("finding start"); + endp = slow(m, m->coldp, stop, gf, gl); + if (endp != NULL) + break; + assert(m->coldp < m->endp); + m->coldp++; + } + if (nmatch == 1 && !g->backrefs) + break; /* no further info needed */ + + /* oh my, he wants the subexpressions... */ + if (m->pmatch == NULL) + m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) * + sizeof(regmatch_t)); + if (m->pmatch == NULL) { + STATETEARDOWN(m); + return(REG_ESPACE); + } + for (i = 1; i <= m->g->nsub; i++) + m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; + if (!g->backrefs && !(m->eflags®_BACKR)) { + NOTE("dissecting"); + dp = dissect(m, m->coldp, endp, gf, gl); + } else { + if (g->nplus > 0 && m->lastpos == NULL) + m->lastpos = (char **)malloc((g->nplus+1) * + sizeof(char *)); + if (g->nplus > 0 && m->lastpos == NULL) { + free(m->pmatch); + STATETEARDOWN(m); + return(REG_ESPACE); + } + NOTE("backref dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + if (dp != NULL) + break; + + /* uh-oh... we couldn't find a subexpression-level match */ + assert(g->backrefs); /* must be back references doing it */ + assert(g->nplus == 0 || m->lastpos != NULL); + for (;;) { + if (dp != NULL || endp <= m->coldp) + break; /* defeat */ + NOTE("backoff"); + endp = slow(m, m->coldp, endp-1, gf, gl); + if (endp == NULL) + break; /* defeat */ + /* try it on a shorter possibility */ +#ifndef NDEBUG + for (i = 1; i <= m->g->nsub; i++) { + assert(m->pmatch[i].rm_so == -1); + assert(m->pmatch[i].rm_eo == -1); + } +#endif + NOTE("backoff dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + assert(dp == NULL || dp == endp); + if (dp != NULL) /* found a shorter one */ + break; + + /* despite initial appearances, there is no match here */ + NOTE("false alarm"); + start = m->coldp + 1; /* recycle starting later */ + assert(start <= stop); + } + + /* fill in the details if requested */ + if (nmatch > 0) { + pmatch[0].rm_so = m->coldp - m->offp; + pmatch[0].rm_eo = endp - m->offp; + } + if (nmatch > 1) { + assert(m->pmatch != NULL); + for (i = 1; i < nmatch; i++) + if (i <= m->g->nsub) + pmatch[i] = m->pmatch[i]; + else { + pmatch[i].rm_so = -1; + pmatch[i].rm_eo = -1; + } + } + + if (m->pmatch != NULL) + free((char *)m->pmatch); + if (m->lastpos != NULL) + free((char *)m->lastpos); + STATETEARDOWN(m); + return(0); +} + +/* + - dissect - figure out what matched what, no back references + == static char *dissect(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* == stop (success) always */ +dissect(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register sopno es; /* end sop of current subRE */ + register char *sp; /* start of string matched by it */ + register char *stp; /* string matched by it cannot pass here */ + register char *rest; /* start of rest of string */ + register char *tail; /* string unmatched by rest of RE */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *sep; /* end of string matched by subsubRE */ + register char *oldssp; /* previous ssp */ + register char *dp; + + AT("diss", start, stop, startst, stopst); + sp = start; + for (ss = startst; ss < stopst; ss = es) { + /* identify end of subRE */ + es = ss; + switch (OP(m->g->strip[es])) { + case OPLUS_: + case OQUEST_: + es += OPND(m->g->strip[es]); + break; + case OCH_: + while (OP(m->g->strip[es]) != O_CH) + es += OPND(m->g->strip[es]); + break; + } + es++; + + /* figure out what it matched */ + switch (OP(m->g->strip[ss])) { + case OEND: + assert(nope); + break; + case OCHAR: + sp++; + break; + case OBOL: + case OEOL: + case OBOW: + case OEOW: + break; + case OANY: + case OANYOF: + sp++; + break; + case OBACK_: + case O_BACK: + assert(nope); + break; + /* cases where length of match is hard to find */ + case OQUEST_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + /* did innards match? */ + if (slow(m, sp, rest, ssub, esub) != NULL) { + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + } else /* no */ + assert(sp == rest); + sp = rest; + break; + case OPLUS_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + ssp = sp; + oldssp = ssp; + for (;;) { /* find last match of innards */ + sep = slow(m, ssp, rest, ssub, esub); + if (sep == NULL || sep == ssp) + break; /* failed or matched null */ + oldssp = ssp; /* on to next try */ + ssp = sep; + } + if (sep == NULL) { + /* last successful match */ + sep = ssp; + ssp = oldssp; + } + assert(sep == rest); /* must exhaust substring */ + assert(slow(m, ssp, sep, ssub, esub) == rest); + dp = dissect(m, ssp, sep, ssub, esub); + assert(dp == sep); + sp = rest; + break; + case OCH_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = ss + OPND(m->g->strip[ss]) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + if (slow(m, sp, rest, ssub, esub) == rest) + break; /* it matched all of it */ + /* that one missed, try next one */ + assert(OP(m->g->strip[esub]) == OOR1); + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + sp = rest; + break; + case O_PLUS: + case O_QUEST: + case OOR1: + case OOR2: + case O_CH: + assert(nope); + break; + case OLPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_so = sp - m->offp; + break; + case ORPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_eo = sp - m->offp; + break; + default: /* uh oh */ + assert(nope); + break; + } + } + + assert(sp == stop); + return(sp); +} + +/* + - backref - figure out what matched what, figuring in back references + == static char *backref(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst, sopno lev); + */ +static char * /* == stop (success) or NULL (failure) */ +backref(m, start, stop, startst, stopst, lev) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +sopno lev; /* PLUS nesting level */ +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register char *sp; /* start of string matched by it */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *dp; + register size_t len; + register int hard; + register sop s; + register regoff_t offsave; + register cset *cs; + + AT("back", start, stop, startst, stopst); + sp = start; + + /* get as far as we can with easy stuff */ + hard = 0; + for (ss = startst; !hard && ss < stopst; ss++) + switch (OP(s = m->g->strip[ss])) { + case OCHAR: + if (sp == stop || *sp++ != (char)OPND(s)) + return(NULL); + break; + case OANY: + if (sp == stop) + return(NULL); + sp++; + break; + case OANYOF: + cs = &m->g->sets[OPND(s)]; + if (sp == stop || !CHIN(cs, *sp++)) + return(NULL); + break; + case OBOL: + if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp > m->beginp && + !ISWORD(*(sp-1))) ) && + (sp < m->endp && ISWORD(*sp)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOW: + if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp < m->endp && !ISWORD(*sp)) ) && + (sp > m->beginp && ISWORD(*(sp-1))) ) + { /* yes */ } + else + return(NULL); + break; + case O_QUEST: + break; + case OOR1: /* matches null but needs to skip */ + ss++; + s = m->g->strip[ss]; + do { + assert(OP(s) == OOR2); + ss += OPND(s); + } while (OP(s = m->g->strip[ss]) != O_CH); + /* note that the ss++ gets us past the O_CH */ + break; + default: /* have to make a choice */ + hard = 1; + break; + } + if (!hard) { /* that was it! */ + if (sp != stop) + return(NULL); + return(sp); + } + ss--; /* adjust for the for's final increment */ + + /* the hard stuff */ + AT("hard", sp, stop, ss, stopst); + s = m->g->strip[ss]; + switch (OP(s)) { + case OBACK_: /* the vilest depths */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + if (m->pmatch[i].rm_eo == -1) + return(NULL); + assert(m->pmatch[i].rm_so != -1); + len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; + assert(stop - m->beginp >= len); + if (sp > stop - len) + return(NULL); /* not enough left to match */ + ssp = m->offp + m->pmatch[i].rm_so; + if (memcmp(sp, ssp, len) != 0) + return(NULL); + while (m->g->strip[ss] != SOP(O_BACK, i)) + ss++; + return(backref(m, sp+len, stop, ss+1, stopst, lev)); + break; + case OQUEST_: /* to null or not */ + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); /* not */ + return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev)); + break; + case OPLUS_: + assert(m->lastpos != NULL); + assert(lev+1 <= m->g->nplus); + m->lastpos[lev+1] = sp; + return(backref(m, sp, stop, ss+1, stopst, lev+1)); + break; + case O_PLUS: + if (sp == m->lastpos[lev]) /* last pass matched null */ + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + /* try another pass */ + m->lastpos[lev] = sp; + dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev); + if (dp == NULL) + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + else + return(dp); + break; + case OCH_: /* find the right one, if any */ + ssub = ss + 1; + esub = ss + OPND(s) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + dp = backref(m, sp, stop, ssub, esub, lev); + if (dp != NULL) + return(dp); + /* that one missed, try next one */ + if (OP(m->g->strip[esub]) == O_CH) + return(NULL); /* there is none */ + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + break; + case OLPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_so; + m->pmatch[i].rm_so = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_so = offsave; + return(NULL); + break; + case ORPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_eo; + m->pmatch[i].rm_eo = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_eo = offsave; + return(NULL); + break; + default: /* uh oh */ + assert(nope); + break; + } + + /* "can't happen" */ + assert(nope); + /* NOTREACHED */ + return((char *)NULL); /* dummy */ +} + +/* + - fast - step through the string at top speed + == static char *fast(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where tentative match ended, or NULL */ +fast(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states fresh = m->fresh; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *coldp; /* last p after which no match was underway */ + + CLEAR(st); + SET1(st, startst); + st = step(m->g, startst, stopst, st, NOTHING, st); + ASSIGN(fresh, st); + SP("start", st, *p); + coldp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + if (EQ(st, fresh)) + coldp = p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("boleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("boweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, fresh); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("aft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + assert(coldp != NULL); + m->coldp = coldp; + if (ISSET(st, stopst)) + return(p+1); + else + return(NULL); +} + +/* + - slow - step through the string more deliberately + == static char *slow(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where it ended */ +slow(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states empty = m->empty; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *matchp; /* last p at which a match ended */ + + AT("slow", start, stop, startst, stopst); + CLEAR(st); + SET1(st, startst); + SP("sstart", st, *p); + st = step(m->g, startst, stopst, st, NOTHING, st); + matchp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst)) + matchp = p; + if (EQ(st, empty) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, empty); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("saft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + return(matchp); +} + + +/* + - step - map set of states reachable before char to set reachable after + == static states step(register struct re_guts *g, sopno start, sopno stop, \ + == register states bef, int ch, register states aft); + == #define BOL (OUT+1) + == #define EOL (BOL+1) + == #define BOLEOL (BOL+2) + == #define NOTHING (BOL+3) + == #define BOW (BOL+4) + == #define EOW (BOL+5) + == #define CODEMAX (BOL+5) // highest code used + == #define NONCHAR(c) ((c) > CHAR_MAX) + == #define NNONCHAR (CODEMAX-CHAR_MAX) + */ +static states +step(g, start, stop, bef, ch, aft) +register struct re_guts *g; +sopno start; /* start state within strip */ +sopno stop; /* state after stop state within strip */ +register states bef; /* states reachable before */ +int ch; /* character or NONCHAR code */ +register states aft; /* states already known reachable after */ +{ + register cset *cs; + register sop s; + register sopno pc; + register onestate here; /* note, macros know this name */ + register sopno look; + register long i; + + for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { + s = g->strip[pc]; + switch (OP(s)) { + case OEND: + assert(pc == stop-1); + break; + case OCHAR: + /* only characters can match */ + assert(!NONCHAR(ch) || ch != (char)OPND(s)); + if (ch == (char)OPND(s)) + FWD(aft, bef, 1); + break; + case OBOL: + if (ch == BOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OEOL: + if (ch == EOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OBOW: + if (ch == BOW) + FWD(aft, bef, 1); + break; + case OEOW: + if (ch == EOW) + FWD(aft, bef, 1); + break; + case OANY: + if (!NONCHAR(ch)) + FWD(aft, bef, 1); + break; + case OANYOF: + cs = &g->sets[OPND(s)]; + if (!NONCHAR(ch) && CHIN(cs, ch)) + FWD(aft, bef, 1); + break; + case OBACK_: /* ignored here */ + case O_BACK: + FWD(aft, aft, 1); + break; + case OPLUS_: /* forward, this is just an empty */ + FWD(aft, aft, 1); + break; + case O_PLUS: /* both forward and back */ + FWD(aft, aft, 1); + i = ISSETBACK(aft, OPND(s)); + BACK(aft, aft, OPND(s)); + if (!i && ISSETBACK(aft, OPND(s))) { + /* oho, must reconsider loop body */ + pc -= OPND(s) + 1; + INIT(here, pc); + } + break; + case OQUEST_: /* two branches, both forward */ + FWD(aft, aft, 1); + FWD(aft, aft, OPND(s)); + break; + case O_QUEST: /* just an empty */ + FWD(aft, aft, 1); + break; + case OLPAREN: /* not significant here */ + case ORPAREN: + FWD(aft, aft, 1); + break; + case OCH_: /* mark the first two branches */ + FWD(aft, aft, 1); + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + break; + case OOR1: /* done a branch, find the O_CH */ + if (ISSTATEIN(aft, here)) { + for (look = 1; + OP(s = g->strip[pc+look]) != O_CH; + look += OPND(s)) + assert(OP(s) == OOR2); + FWD(aft, aft, look); + } + break; + case OOR2: /* propagate OCH_'s marking */ + FWD(aft, aft, 1); + if (OP(g->strip[pc+OPND(s)]) != O_CH) { + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + } + break; + case O_CH: /* just empty */ + FWD(aft, aft, 1); + break; + default: /* ooooops... */ + assert(nope); + break; + } + } + + return(aft); +} + +#ifdef REDEBUG +/* + - print - print a set of states + == #ifdef REDEBUG + == static void print(struct match *m, char *caption, states st, \ + == int ch, FILE *d); + == #endif + */ +static void +print(m, caption, st, ch, d) +struct match *m; +char *caption; +states st; +int ch; +FILE *d; +{ + register struct re_guts *g = m->g; + register int i; + register int first = 1; + + if (!(m->eflags®_TRACE)) + return; + + fprintf(d, "%s", caption); + if (ch != '\0') + fprintf(d, " %s", pchar(ch)); + for (i = 0; i < g->nstates; i++) + if (ISSET(st, i)) { + fprintf(d, "%s%d", (first) ? "\t" : ", ", i); + first = 0; + } + fprintf(d, "\n"); +} + +/* + - at - print current situation + == #ifdef REDEBUG + == static void at(struct match *m, char *title, char *start, char *stop, \ + == sopno startst, sopno stopst); + == #endif + */ +static void +at(m, title, start, stop, startst, stopst) +struct match *m; +char *title; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + if (!(m->eflags®_TRACE)) + return; + + printf("%s %s-", title, pchar(*start)); + printf("%s ", pchar(*stop)); + printf("%ld-%ld\n", (long)startst, (long)stopst); +} + +#ifndef PCHARDONE +#define PCHARDONE /* never again */ +/* + - pchar - make a character printable + == #ifdef REDEBUG + == static char *pchar(int ch); + == #endif + * + * Is this identical to regchar() over in debug.c? Well, yes. But a + * duplicate here avoids having a debugging-capable regexec.o tied to + * a matching debug.o, and this is convenient. It all disappears in + * the non-debug compilation anyway, so it doesn't matter much. + */ +static char * /* -> representation */ +pchar(ch) +int ch; +{ + static char pbuf[10]; + + if (isprint(ch) || ch == ' ') + sprintf(pbuf, "%c", ch); + else + sprintf(pbuf, "\\%o", ch); + return(pbuf); +} +#endif +#endif + +#undef matcher +#undef fast +#undef slow +#undef dissect +#undef backref +#undef step +#undef print +#undef at +#undef match diff --git a/winsup/cygwin/regex/engine.ih b/winsup/cygwin/regex/engine.ih new file mode 100644 index 000000000..cc98334e7 --- /dev/null +++ b/winsup/cygwin/regex/engine.ih @@ -0,0 +1,35 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === engine.c === */ +static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev); +static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft); +#define BOL (OUT+1) +#define EOL (BOL+1) +#define BOLEOL (BOL+2) +#define NOTHING (BOL+3) +#define BOW (BOL+4) +#define EOW (BOL+5) +#define CODEMAX (BOL+5) /* highest code used */ +#define NONCHAR(c) ((c) > CHAR_MAX) +#define NNONCHAR (CODEMAX-CHAR_MAX) +#ifdef REDEBUG +static void print(struct match *m, char *caption, states st, int ch, FILE *d); +#endif +#ifdef REDEBUG +static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst); +#endif +#ifdef REDEBUG +static char *pchar(int ch); +#endif + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/winsup/cygwin/regex/mkh b/winsup/cygwin/regex/mkh new file mode 100755 index 000000000..252b246c7 --- /dev/null +++ b/winsup/cygwin/regex/mkh @@ -0,0 +1,76 @@ +#! /bin/sh +# mkh - pull headers out of C source +PATH=/bin:/usr/bin ; export PATH + +# egrep pattern to pick out marked lines +egrep='^ =([ ]|$)' + +# Sed program to process marked lines into lines for the header file. +# The markers have already been removed. Two things are done here: removal +# of backslashed newlines, and some fudging of comments. The first is done +# because -o needs to have prototypes on one line to strip them down. +# Getting comments into the output is tricky; we turn C++-style // comments +# into /* */ comments, after altering any existing */'s to avoid trouble. +peel=' /\\$/N + /\\\n[ ]*/s///g + /\/\//s;\*/;* /;g + /\/\//s;//\(.*\);/*\1 */;' + +for a +do + case "$a" in + -o) # old (pre-function-prototype) compiler + # add code to comment out argument lists + peel="$peel + "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);' + shift + ;; + -b) # funny Berkeley __P macro + peel="$peel + "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));' + shift + ;; + -s) # compiler doesn't like `static foo();' + # add code to get rid of the `static' + peel="$peel + "'/^static[ ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;' + shift + ;; + -p) # private declarations + egrep='^ ==([ ]|$)' + shift + ;; + -i) # wrap in #ifndef, argument is name + ifndef="$2" + shift ; shift + ;; + *) break + ;; + esac +done + +if test " $ifndef" != " " +then + echo "#ifndef $ifndef" + echo "#define $ifndef /* never again */" +fi +echo "/* ========= begin header generated by $0 ========= */" +echo '#ifdef __cplusplus' +echo 'extern "C" {' +echo '#endif' +for f +do + echo + echo "/* === $f === */" + egrep "$egrep" $f | sed 's/^ ==*[ ]//;s/^ ==*$//' | sed "$peel" + echo +done +echo '#ifdef __cplusplus' +echo '}' +echo '#endif' +echo "/* ========= end header generated by $0 ========= */" +if test " $ifndef" != " " +then + echo "#endif" +fi +exit 0 diff --git a/winsup/cygwin/regex/regcomp.c b/winsup/cygwin/regex/regcomp.c new file mode 100644 index 000000000..34c1f2e5c --- /dev/null +++ b/winsup/cygwin/regex/regcomp.c @@ -0,0 +1,1546 @@ +#include "winsup.h" +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <stdlib.h> +#include "regex.h" + +#include "utils.h" +#include "regex2.h" + +#include "cclass.h" +#include "cname.h" + +/* + * parse structure, passed up and down to avoid global variables and + * other clumsinesses + */ +struct parse { + char *next; /* next character in RE */ + char *end; /* end of string (-> NUL normally) */ + int error; /* has an error been seen? */ + sop *strip; /* malloced strip */ + sopno ssize; /* malloced strip size (allocated) */ + sopno slen; /* malloced strip length (used) */ + int ncsalloc; /* number of csets allocated */ + struct re_guts *g; +# define NPAREN 10 /* we need to remember () 1-9 for back refs */ + sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ + sopno pend[NPAREN]; /* -> ) ([0] unused) */ +}; + +#include "regcomp.ih" + +static char nuls[10]; /* place to point scanner in event of error */ + +/* + * macros for use with parse structure + * BEWARE: these know that the parse structure is named `p' !!! + */ +#define PEEK() (*p->next) +#define PEEK2() (*(p->next+1)) +#define MORE() (p->next < p->end) +#define MORE2() (p->next+1 < p->end) +#define SEE(c) (MORE() && PEEK() == (c)) +#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) +#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) +#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) +#define NEXT() (p->next++) +#define NEXT2() (p->next += 2) +#define NEXTn(n) (p->next += (n)) +#define GETNEXT() (*p->next++) +#define SETERROR(e) seterr(p, (e)) +#define REQUIRE(co, e) ((co) || SETERROR(e)) +#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) +#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) +#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) +#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) +#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) +#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) +#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) +#define HERE() (p->slen) +#define THERE() (p->slen - 1) +#define THERETHERE() (p->slen - 2) +#define DROP(n) (p->slen -= (n)) + +#ifndef NDEBUG +static int never = 0; /* for use in asserts; shuts lint up */ +#else +#define never 0 /* some <assert.h>s have bugs too */ +#endif + +/* + - regcomp - interface for parser and compilation + = extern int regcomp(regex_t *, const char *, int); + = #define REG_BASIC 0000 + = #define REG_EXTENDED 0001 + = #define REG_ICASE 0002 + = #define REG_NOSUB 0004 + = #define REG_NEWLINE 0010 + = #define REG_NOSPEC 0020 + = #define REG_PEND 0040 + = #define REG_DUMP 0200 + */ +int /* 0 success, otherwise REG_something */ +regcomp(preg, pattern, cflags) +regex_t *preg; +const char *pattern; +int cflags; +{ + struct parse pa; + register struct re_guts *g; + register struct parse *p = &pa; + register int i; + register size_t len; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&~REG_DUMP) +#endif + + cflags = GOODFLAGS(cflags); + if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_PEND) { + if (preg->re_endp < pattern) + return(REG_INVARG); + len = preg->re_endp - pattern; + } else + len = strlen((char *)pattern); + + /* do the mallocs early so failure handling is easy */ + g = (struct re_guts *)malloc(sizeof(struct re_guts) + + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); + p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ + p->strip = (sop *)malloc(p->ssize * sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { + free((char *)g); + return(REG_ESPACE); + } + + /* set things up */ + p->g = g; + p->next = (char *)pattern; /* convenience; we do not modify it */ + p->end = p->next + len; + p->error = 0; + p->ncsalloc = 0; + for (i = 0; i < NPAREN; i++) { + p->pbegin[i] = 0; + p->pend[i] = 0; + } + g->csetsize = NC; + g->sets = NULL; + g->setbits = NULL; + g->ncsets = 0; + g->cflags = cflags; + g->iflags = 0; + g->nbol = 0; + g->neol = 0; + g->must = NULL; + g->mlen = 0; + g->nsub = 0; + g->ncategories = 1; /* category 0 is "everything else" */ + g->categories = &g->catspace[-(CHAR_MIN)]; + (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); + g->backrefs = 0; + + /* do it */ + EMIT(OEND, 0); + g->firststate = THERE(); + if (cflags®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_NOSPEC) + p_str(p); + else + p_bre(p, OUT, OUT); + EMIT(OEND, 0); + g->laststate = THERE(); + + /* tidy up loose ends and fill things in */ + categorize(p, g); + stripsnug(p, g); + findmust(p, g); + g->nplus = pluscount(p, g); + g->magic = MAGIC2; + preg->re_nsub = g->nsub; + preg->re_g = g; + preg->re_magic = MAGIC1; +#ifndef REDEBUG + /* not debugging, so can't rely on the assert() in regexec() */ + if (g->iflags&BAD) + SETERROR(REG_ASSERT); +#endif + + /* win or lose, we're done */ + if (p->error != 0) /* lose */ + regfree(preg); + return(p->error); +} + +/* + - p_ere - ERE parser top level, concatenation and alternation + == static void p_ere(register struct parse *p, int stop); + */ +static void +p_ere(p, stop) +register struct parse *p; +int stop; /* character this ERE should end at */ +{ + register char c; + register sopno prevback = 0; + register sopno prevfwd = 0; + register sopno conc = 0; + register int first = 1; /* is this the first alternative? */ + + for (;;) { + /* do a bunch of concatenated expressions */ + conc = HERE(); + while (MORE() && (c = PEEK()) != '|' && c != stop) + p_ere_exp(p); + REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + + if (!EAT('|')) + break; /* NOTE BREAK OUT */ + + if (first) { + INSERT(OCH_, conc); /* offset is wrong */ + prevfwd = conc; + prevback = conc; + first = 0; + } + ASTERN(OOR1, prevback); + prevback = THERE(); + AHEAD(prevfwd); /* fix previous offset */ + prevfwd = HERE(); + EMIT(OOR2, 0); /* offset is very wrong */ + } + + if (!first) { /* tail-end fixups */ + AHEAD(prevfwd); + ASTERN(O_CH, prevback); + } + + assert(!MORE() || SEE(stop)); +} + +/* + - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op + == static void p_ere_exp(register struct parse *p); + */ +static void +p_ere_exp(p) +register struct parse *p; +{ + register char c; + register sopno pos; + register int count; + register int count2; + register sopno subno; + int wascaret = 0; + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + + pos = HERE(); + switch (c) { + case '(': + REQUIRE(MORE(), REG_EPAREN); + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + if (!SEE(')')) + p_ere(p, ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + MUSTEAT(')', REG_EPAREN); + break; +#ifndef POSIX_MISTAKE + case ')': /* happens only if no current unmatched ( */ + /* + * You may ask, why the ifndef? Because I didn't notice + * this until slightly too late for 1003.2, and none of the + * other 1003.2 regular-expression reviewers noticed it at + * all. So an unmatched ) is legal POSIX, at least until + * we can get it fixed. + */ + SETERROR(REG_EPAREN); + break; +#endif + case '^': + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + wascaret = 1; + break; + case '$': + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + break; + case '|': + SETERROR(REG_EMPTY); + break; + case '*': + case '+': + case '?': + SETERROR(REG_BADRPT); + break; + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case '\\': + REQUIRE(MORE(), REG_EESCAPE); + c = GETNEXT(); + ordinary(p, c); + break; + case '{': /* okay as ordinary except if digit follows */ + REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c); + break; + } + + if (!MORE()) + return; + c = PEEK(); + /* we call { a repetition if followed by a digit */ + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) )) + return; /* no repetition, we're done */ + NEXT(); + + REQUIRE(!wascaret, REG_BADRPT); + switch (c) { + case '*': /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + break; + case '+': + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + break; + case '?': + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, pos); /* offset slightly wrong */ + ASTERN(OOR1, pos); /* this one's right */ + AHEAD(pos); /* fix the OCH_ */ + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + break; + case '{': + count = p_count(p); + if (EAT(',')) { + if (isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EAT('}')) { /* error heuristics */ + while (MORE() && PEEK() != '}') + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + break; + } + + if (!MORE()) + return; + c = PEEK(); + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) ) ) + return; + SETERROR(REG_BADRPT); +} + +/* + - p_str - string (no metacharacters) "parser" + == static void p_str(register struct parse *p); + */ +static void +p_str(p) +register struct parse *p; +{ + REQUIRE(MORE(), REG_EMPTY); + while (MORE()) + ordinary(p, GETNEXT()); +} + +/* + - p_bre - BRE parser top level, anchoring and concatenation + == static void p_bre(register struct parse *p, register int end1, \ + == register int end2); + * Giving end1 as OUT essentially eliminates the end1/end2 check. + * + * This implementation is a bit of a kludge, in that a trailing $ is first + * taken as an ordinary character and then revised to be an anchor. The + * only undesirable side effect is that '$' gets included as a character + * category in such cases. This is fairly harmless; not worth fixing. + * The amount of lookahead needed to avoid this kludge is excessive. + */ +static void +p_bre(p, end1, end2) +register struct parse *p; +register int end1; /* first terminating character */ +register int end2; /* second terminating character */ +{ + register sopno start = HERE(); + register int first = 1; /* first subexpression? */ + register int wasdollar = 0; + + if (EAT('^')) { + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + } + while (MORE() && !SEETWO(end1, end2)) { + wasdollar = p_simp_re(p, first); + first = 0; + } + if (wasdollar) { /* oops, that was a trailing anchor */ + DROP(1); + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + } + + REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ +} + +/* + - p_simp_re - parse a simple RE, an atom possibly followed by a repetition + == static int p_simp_re(register struct parse *p, int starordinary); + */ +static int /* was the simple RE an unbackslashed $? */ +p_simp_re(p, starordinary) +register struct parse *p; +int starordinary; /* is a leading * an ordinary character? */ +{ + register int c; + register int count; + register int count2; + register sopno pos; + register int i; + register sopno subno; +# define BACKSL (1<<CHAR_BIT) + + pos = HERE(); /* repetion op, if any, covers from here */ + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + if (c == '\\') { + REQUIRE(MORE(), REG_EESCAPE); + c = BACKSL | (unsigned char)GETNEXT(); + } + switch (c) { + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case BACKSL|'{': + SETERROR(REG_BADRPT); + break; + case BACKSL|'(': + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + /* the MORE here is an error heuristic */ + if (MORE() && !SEETWO('\\', ')')) + p_bre(p, '\\', ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + break; + case BACKSL|')': /* should not get here -- must be user */ + case BACKSL|'}': + SETERROR(REG_EPAREN); + break; + case BACKSL|'1': + case BACKSL|'2': + case BACKSL|'3': + case BACKSL|'4': + case BACKSL|'5': + case BACKSL|'6': + case BACKSL|'7': + case BACKSL|'8': + case BACKSL|'9': + i = (c&~BACKSL) - '0'; + assert(i < NPAREN); + if (p->pend[i] != 0) { + assert(i <= p->g->nsub); + EMIT(OBACK_, i); + assert(p->pbegin[i] != 0); + assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); + assert(OP(p->strip[p->pend[i]]) == ORPAREN); + (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + EMIT(O_BACK, i); + } else + SETERROR(REG_ESUBREG); + p->g->backrefs = 1; + break; + case '*': + REQUIRE(starordinary, REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, (char)c); /* takes off BACKSL, if any */ + break; + } + + if (EAT('*')) { /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + } else if (EATTWO('\\', '{')) { + count = p_count(p); + if (EAT(',')) { + if (MORE() && isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EATTWO('\\', '}')) { /* error heuristics */ + while (MORE() && !SEETWO('\\', '}')) + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ + return(1); + + return(0); +} + +/* + - p_count - parse a repetition count + == static int p_count(register struct parse *p); + */ +static int /* the value */ +p_count(p) +register struct parse *p; +{ + register int count = 0; + register int ndigits = 0; + + while (MORE() && isdigit(PEEK()) && count <= DUPMAX) { + count = count*10 + (GETNEXT() - '0'); + ndigits++; + } + + REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + return(count); +} + +/* + - p_bracket - parse a bracketed character list + == static void p_bracket(register struct parse *p); + * + * Note a significant property of this code: if the allocset() did SETERROR, + * no set operations are done. + */ +static void +p_bracket(p) +register struct parse *p; +{ + register cset *cs = allocset(p); + register int invert = 0; + + /* Dept of Truly Sickening Special-Case Kludges */ + if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { + EMIT(OBOW, 0); + NEXTn(6); + return; + } + if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { + EMIT(OEOW, 0); + NEXTn(6); + return; + } + + if (EAT('^')) + invert++; /* make note to invert set at end */ + if (EAT(']')) + CHadd(cs, ']'); + else if (EAT('-')) + CHadd(cs, '-'); + while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) + p_b_term(p, cs); + if (EAT('-')) + CHadd(cs, '-'); + MUSTEAT(']', REG_EBRACK); + + if (p->error != 0) /* don't mess things up further */ + return; + + if (p->g->cflags®_ICASE) { + register int i; + register int ci; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i) && isalpha(i)) { + ci = othercase(i); + if (ci != i) + CHadd(cs, ci); + } + if (cs->multis != NULL) + mccase(p, cs); + } + if (invert) { + register int i; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i)) + CHsub(cs, i); + else + CHadd(cs, i); + if (p->g->cflags®_NEWLINE) + CHsub(cs, '\n'); + if (cs->multis != NULL) + mcinvert(p, cs); + } + + assert(cs->multis == NULL); /* xxx */ + + if (nch(p, cs) == 1) { /* optimize singleton sets */ + ordinary(p, firstch(p, cs)); + freeset(p, cs); + } else + EMIT(OANYOF, freezeset(p, cs)); +} + +/* + - p_b_term - parse one term of a bracketed character list + == static void p_b_term(register struct parse *p, register cset *cs); + */ +static void +p_b_term(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + register char start, finish; + register int i; + + /* classify what we've got */ + switch ((MORE()) ? PEEK() : '\0') { + case '[': + c = (MORE2()) ? PEEK2() : '\0'; + break; + case '-': + SETERROR(REG_ERANGE); + return; /* NOTE RETURN */ + break; + default: + c = '\0'; + break; + } + + switch (c) { + case ':': /* character class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECTYPE); + p_b_cclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + break; + case '=': /* equivalence class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + p_b_eclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + break; + default: /* symbol, ordinary character, or range */ +/* xxx revision needed for multichar stuff */ + start = p_b_symbol(p); + if (SEE('-') && MORE2() && PEEK2() != ']') { + /* range */ + NEXT(); + if (EAT('-')) + finish = '-'; + else + finish = p_b_symbol(p); + } else + finish = start; +/* xxx what about signed chars here... */ + REQUIRE(start <= finish, REG_ERANGE); + for (i = start; i <= finish; i++) + CHadd(cs, i); + break; + } +} + +/* + - p_b_cclass - parse a character-class name and deal with it + == static void p_b_cclass(register struct parse *p, register cset *cs); + */ +static void +p_b_cclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char *sp = p->next; + register struct cclass *cp; + register size_t len; + register const char *u; + register char c; + + while (MORE() && isalpha(PEEK())) + NEXT(); + len = p->next - sp; + for (cp = cclasses; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + break; + if (cp->name == NULL) { + /* oops, didn't find it */ + SETERROR(REG_ECTYPE); + return; + } + + u = cp->chars; + while ((c = *u++) != '\0') + CHadd(cs, c); + for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) + MCadd(p, cs, u); +} + +/* + - p_b_eclass - parse an equivalence-class name and deal with it + == static void p_b_eclass(register struct parse *p, register cset *cs); + * + * This implementation is incomplete. xxx + */ +static void +p_b_eclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + + c = p_b_coll_elem(p, '='); + CHadd(cs, c); +} + +/* + - p_b_symbol - parse a character or [..]ed multicharacter collating symbol + == static char p_b_symbol(register struct parse *p); + */ +static char /* value of symbol */ +p_b_symbol(p) +register struct parse *p; +{ + register char value; + + REQUIRE(MORE(), REG_EBRACK); + if (!EATTWO('[', '.')) + return(GETNEXT()); + + /* collating symbol */ + value = p_b_coll_elem(p, '.'); + REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + return(value); +} + +/* + - p_b_coll_elem - parse a collating-element name and look it up + == static char p_b_coll_elem(register struct parse *p, int endc); + */ +static char /* value of collating element */ +p_b_coll_elem(p, endc) +register struct parse *p; +int endc; /* name ended by endc,']' */ +{ + register char *sp = p->next; + register struct cname *cp; + register int len; + + while (MORE() && !SEETWO(endc, ']')) + NEXT(); + if (!MORE()) { + SETERROR(REG_EBRACK); + return(0); + } + len = p->next - sp; + for (cp = cnames; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + return(cp->code); /* known name */ + if (len == 1) + return(*sp); /* single character */ + SETERROR(REG_ECOLLATE); /* neither */ + return(0); +} + +/* + - othercase - return the case counterpart of an alphabetic + == static char othercase(int ch); + */ +static char /* if no counterpart, return ch */ +othercase(ch) +int ch; +{ + assert(isalpha(ch)); + if (isupper(ch)) + return(tolower(ch)); + else if (islower(ch)) + return(toupper(ch)); + else /* peculiar, but could happen */ + return(ch); +} + +/* + - bothcases - emit a dualcase version of a two-case character + == static void bothcases(register struct parse *p, int ch); + * + * Boy, is this implementation ever a kludge... + */ +static void +bothcases(p, ch) +register struct parse *p; +int ch; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[3]; + + assert(othercase(ch) != ch); /* p_bracket() would recurse */ + p->next = bracket; + p->end = bracket+2; + bracket[0] = ch; + bracket[1] = ']'; + bracket[2] = '\0'; + p_bracket(p); + assert(p->next == bracket+2); + p->next = oldnext; + p->end = oldend; +} + +/* + - ordinary - emit an ordinary character + == static void ordinary(register struct parse *p, register int ch); + */ +static void +ordinary(p, ch) +register struct parse *p; +register int ch; +{ + register cat_t *cap = p->g->categories; + + if ((p->g->cflags®_ICASE) && isalpha(ch) && othercase(ch) != ch) + bothcases(p, ch); + else { + EMIT(OCHAR, (unsigned char)ch); + if (cap[ch] == 0) + cap[ch] = p->g->ncategories++; + } +} + +/* + - nonnewline - emit REG_NEWLINE version of OANY + == static void nonnewline(register struct parse *p); + * + * Boy, is this implementation ever a kludge... + */ +static void +nonnewline(p) +register struct parse *p; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[4]; + + p->next = bracket; + p->end = bracket+3; + bracket[0] = '^'; + bracket[1] = '\n'; + bracket[2] = ']'; + bracket[3] = '\0'; + p_bracket(p); + assert(p->next == bracket+3); + p->next = oldnext; + p->end = oldend; +} + +/* + - repeat - generate code for a bounded repetition, recursively if needed + == static void repeat(register struct parse *p, sopno start, int from, int to); + */ +static void +repeat(p, start, from, to) +register struct parse *p; +sopno start; /* operand from here to end of strip */ +int from; /* repeated from this number */ +int to; /* to this number of times (maybe INFINITY) */ +{ + register sopno finish = HERE(); +# define N 2 +# define INF 3 +# define REP(f, t) ((f)*8 + (t)) +# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) + register sopno copy; + + if (p->error != 0) /* head off possible runaway recursion */ + return; + + assert(from <= to); + + switch (REP(MAP(from), MAP(to))) { + case REP(0, 0): /* must be user doing this */ + DROP(finish-start); /* drop the operand */ + break; + case REP(0, 1): /* as x{1,1}? */ + case REP(0, N): /* as x{1,n}? */ + case REP(0, INF): /* as x{1,}? */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); /* offset is wrong... */ + repeat(p, start+1, 1, to); + ASTERN(OOR1, start); + AHEAD(start); /* ... fix it */ + EMIT(OOR2, 0); + AHEAD(THERE()); + ASTERN(O_CH, THERETHERE()); + break; + case REP(1, 1): /* trivial case */ + /* done */ + break; + case REP(1, N): /* as x?x{1,n-1} */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); + ASTERN(OOR1, start); + AHEAD(start); + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + copy = dupl(p, start+1, finish+1); + assert(copy == finish+4); + repeat(p, copy, 1, to-1); + break; + case REP(1, INF): /* as x+ */ + INSERT(OPLUS_, start); + ASTERN(O_PLUS, start); + break; + case REP(N, N): /* as xx{m-1,n-1} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to-1); + break; + case REP(N, INF): /* as xx{n-1,INF} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to); + break; + default: /* "can't happen" */ + SETERROR(REG_ASSERT); /* just in case */ + break; + } +} + +/* + - seterr - set an error condition + == static int seterr(register struct parse *p, int e); + */ +static int /* useless but makes type checking happy */ +seterr(p, e) +register struct parse *p; +int e; +{ + if (p->error == 0) /* keep earliest error condition */ + p->error = e; + p->next = nuls; /* try to bring things to a halt */ + p->end = nuls; + return(0); /* make the return value well-defined */ +} + +/* + - allocset - allocate a set of characters for [] + == static cset *allocset(register struct parse *p); + */ +static cset * +allocset(p) +register struct parse *p; +{ + register int no = p->g->ncsets++; + register size_t nc; + register size_t nbytes; + register cset *cs; + register size_t css = (size_t)p->g->csetsize; + register int i; + + if (no >= p->ncsalloc) { /* need another column of space */ + p->ncsalloc += CHAR_BIT; + nc = p->ncsalloc; + assert(nc % CHAR_BIT == 0); + nbytes = nc / CHAR_BIT * css; + if (p->g->sets == NULL) + p->g->sets = (cset *)malloc(nc * sizeof(cset)); + else + p->g->sets = (cset *)realloc((char *)p->g->sets, + nc * sizeof(cset)); + if (p->g->setbits == NULL) + p->g->setbits = (uch *)malloc(nbytes); + else { + p->g->setbits = (uch *)realloc((char *)p->g->setbits, + nbytes); + /* xxx this isn't right if setbits is now NULL */ + for (i = 0; i < no; i++) + p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); + } + if (p->g->sets != NULL && p->g->setbits != NULL) + (void) memset((char *)p->g->setbits + (nbytes - css), + 0, css); + else { + no = 0; + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + } + } + + assert(p->g->sets != NULL); /* xxx */ + cs = &p->g->sets[no]; + cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); + cs->mask = 1 << ((no) % CHAR_BIT); + cs->hash = 0; + cs->smultis = 0; + cs->multis = NULL; + + return(cs); +} + +/* + - freeset - free a now-unused set + == static void freeset(register struct parse *p, register cset *cs); + */ +static void +freeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + CHsub(cs, i); + if (cs == top-1) /* recover only the easy case */ + p->g->ncsets--; +} + +/* + - freezeset - final processing on a set of characters + == static int freezeset(register struct parse *p, register cset *cs); + * + * The main task here is merging identical sets. This is usually a waste + * of time (although the hash code minimizes the overhead), but can win + * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash + * is done using addition rather than xor -- all ASCII [aA] sets xor to + * the same value! + */ +static int /* set number */ +freezeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register uch h = cs->hash; + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register cset *cs2; + register size_t css = (size_t)p->g->csetsize; + + /* look for an earlier one which is the same */ + for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) + if (cs2->hash == h && cs2 != cs) { + /* maybe */ + for (i = 0; i < css; i++) + if (!!CHIN(cs2, i) != !!CHIN(cs, i)) + break; /* no */ + if (i == css) + break; /* yes */ + } + + if (cs2 < top) { /* found one */ + freeset(p, cs); + cs = cs2; + } + + return((int)(cs - p->g->sets)); +} + +/* + - firstch - return first character in a set (which must have at least one) + == static int firstch(register struct parse *p, register cset *cs); + */ +static int /* character; there is no "none" value */ +firstch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + return((char)i); + assert(never); + return(0); /* arbitrary */ +} + +/* + - nch - number of characters in a set + == static int nch(register struct parse *p, register cset *cs); + */ +static int +nch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + register int n = 0; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + n++; + return(n); +} + +/* + - mcadd - add a collating element to a cset + == static void mcadd(register struct parse *p, register cset *cs, \ + == register char *cp); + */ +static void +mcadd(p, cs, cp) +register struct parse *p; +register cset *cs; +register const char *cp; +{ + register size_t oldend = cs->smultis; + + cs->smultis += strlen(cp) + 1; + if (cs->multis == NULL) + cs->multis = malloc(cs->smultis); + else + cs->multis = realloc(cs->multis, cs->smultis); + if (cs->multis == NULL) { + SETERROR(REG_ESPACE); + return; + } + + (void) strcpy(cs->multis + oldend - 1, cp); + cs->multis[cs->smultis - 1] = '\0'; +} + +/* + - mcinvert - invert the list of collating elements in a cset + == static void mcinvert(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mcinvert(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - mccase - add case counterparts of the list of collating elements in a cset + == static void mccase(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mccase(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - isinsets - is this character in any sets? + == static int isinsets(register struct re_guts *g, int c); + */ +static int /* predicate */ +isinsets(g, c) +register struct re_guts *g; +int c; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc = (unsigned char)c; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc] != 0) + return(1); + return(0); +} + +/* + - samesets - are these two characters in exactly the same sets? + == static int samesets(register struct re_guts *g, int c1, int c2); + */ +static int /* predicate */ +samesets(g, c1, c2) +register struct re_guts *g; +int c1; +int c2; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc1 = (unsigned char)c1; + register unsigned uc2 = (unsigned char)c2; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc1] != col[uc2]) + return(0); + return(1); +} + +/* + - categorize - sort out character categories + == static void categorize(struct parse *p, register struct re_guts *g); + */ +static void +categorize(p, g) +struct parse *p; +register struct re_guts *g; +{ + register cat_t *cats = g->categories; + register int c; + register int c2; + register cat_t cat; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (cats[c] == 0 && isinsets(g, c)) { + cat = g->ncategories++; + cats[c] = cat; + for (c2 = c+1; c2 <= CHAR_MAX; c2++) + if (cats[c2] == 0 && samesets(g, c, c2)) + cats[c2] = cat; + } +} + +/* + - dupl - emit a duplicate of a bunch of sops + == static sopno dupl(register struct parse *p, sopno start, sopno finish); + */ +static sopno /* start of duplicate */ +dupl(p, start, finish) +register struct parse *p; +sopno start; /* from here */ +sopno finish; /* to this less one */ +{ + register sopno ret = HERE(); + register sopno len = finish - start; + + assert(finish >= start); + if (len == 0) + return(ret); + enlarge(p, p->ssize + len); /* this many unexpected additions */ + assert(p->ssize >= p->slen + len); + (void) memcpy((char *)(p->strip + p->slen), + (char *)(p->strip + start), (size_t)len*sizeof(sop)); + p->slen += len; + return(ret); +} + +/* + - doemit - emit a strip operator + == static void doemit(register struct parse *p, sop op, size_t opnd); + * + * It might seem better to implement this as a macro with a function as + * hard-case backup, but it's just too big and messy unless there are + * some changes to the data structures. Maybe later. + */ +static void +doemit(p, op, opnd) +register struct parse *p; +sop op; +size_t opnd; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* deal with oversize operands ("can't happen", more or less) */ + assert(opnd < 1<<OPSHIFT); + + /* deal with undersized strip */ + if (p->slen >= p->ssize) + enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ + assert(p->slen < p->ssize); + + /* finally, it's all reduced to the easy case */ + p->strip[p->slen++] = SOP(op, opnd); +} + +/* + - doinsert - insert a sop into the strip + == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); + */ +static void +doinsert(p, op, opnd, pos) +register struct parse *p; +sop op; +size_t opnd; +sopno pos; +{ + register sopno sn; + register sop s; + register int i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + sn = HERE(); + EMIT(op, opnd); /* do checks, ensure space */ + assert(HERE() == sn+1); + s = p->strip[sn]; + + /* adjust paren pointers */ + assert(pos > 0); + for (i = 1; i < NPAREN; i++) { + if (p->pbegin[i] >= pos) { + p->pbegin[i]++; + } + if (p->pend[i] >= pos) { + p->pend[i]++; + } + } + + memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], + (HERE()-pos-1)*sizeof(sop)); + p->strip[pos] = s; +} + +/* + - dofwd - complete a forward reference + == static void dofwd(register struct parse *p, sopno pos, sop value); + */ +static void +dofwd(p, pos, value) +register struct parse *p; +register sopno pos; +sop value; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + assert(value < 1<<OPSHIFT); + p->strip[pos] = OP(p->strip[pos]) | value; +} + +/* + - enlarge - enlarge the strip + == static void enlarge(register struct parse *p, sopno size); + */ +static void +enlarge(p, size) +register struct parse *p; +register sopno size; +{ + register sop *sp; + + if (p->ssize >= size) + return; + + sp = (sop *)realloc(p->strip, size*sizeof(sop)); + if (sp == NULL) { + SETERROR(REG_ESPACE); + return; + } + p->strip = sp; + p->ssize = size; +} + +/* + - stripsnug - compact the strip + == static void stripsnug(register struct parse *p, register struct re_guts *g); + */ +static void +stripsnug(p, g) +register struct parse *p; +register struct re_guts *g; +{ + g->nstates = p->slen; + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); + if (g->strip == NULL) { + SETERROR(REG_ESPACE); + g->strip = p->strip; + } +} + +/* + - findmust - fill in must and mlen with longest mandatory literal string + == static void findmust(register struct parse *p, register struct re_guts *g); + * + * This algorithm could do fancy things like analyzing the operands of | + * for common subsequences. Someday. This code is simple and finds most + * of the interesting cases. + * + * Note that must and mlen got initialized during setup. + */ +static void +findmust(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + sop *start = NULL; + register sop *newstart = NULL; + register sopno newlen; + register sop s; + register char *cp; + register sopno i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* find the longest OCHAR sequence in strip */ + newlen = 0; + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OCHAR: /* sequence member */ + if (newlen == 0) /* new sequence */ + newstart = scan - 1; + newlen++; + break; + case OPLUS_: /* things that don't break one */ + case OLPAREN: + case ORPAREN: + break; + case OQUEST_: /* things that must be skipped */ + case OCH_: + scan--; + do { + scan += OPND(s); + s = *scan; + /* assert() interferes w debug printouts */ + if (OP(s) != O_QUEST && OP(s) != O_CH && + OP(s) != OOR2) { + g->iflags |= BAD; + return; + } + } while (OP(s) != O_QUEST && OP(s) != O_CH); + /* fallthrough */ + default: /* things that break a sequence */ + if (newlen > g->mlen) { /* ends one */ + start = newstart; + g->mlen = newlen; + } + newlen = 0; + break; + } + } while (OP(s) != OEND); + + if (g->mlen == 0) /* there isn't one */ + return; + + /* turn it into a character string */ + g->must = malloc((size_t)g->mlen + 1); + if (g->must == NULL) { /* argh; just forget it */ + g->mlen = 0; + return; + } + cp = g->must; + scan = start; + for (i = g->mlen; i > 0; i--) { + while (OP(s = *scan++) != OCHAR) + continue; + assert(cp < g->must + g->mlen); + *cp++ = (char)OPND(s); + } + assert(cp == g->must + g->mlen); + *cp++ = '\0'; /* just on general principles */ +} + +/* + - pluscount - count + nesting + == static sopno pluscount(register struct parse *p, register struct re_guts *g); + */ +static sopno /* nesting depth */ +pluscount(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + register sop s; + register sopno plusnest = 0; + register sopno maxnest = 0; + + if (p->error != 0) + return(0); /* there may not be an OEND */ + + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OPLUS_: + plusnest++; + break; + case O_PLUS: + if (plusnest > maxnest) + maxnest = plusnest; + plusnest--; + break; + } + } while (OP(s) != OEND); + if (plusnest != 0) + g->iflags |= BAD; + return(maxnest); +} diff --git a/winsup/cygwin/regex/regcomp.ih b/winsup/cygwin/regex/regcomp.ih new file mode 100644 index 000000000..e16d5ab2f --- /dev/null +++ b/winsup/cygwin/regex/regcomp.ih @@ -0,0 +1,48 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regcomp.c === */ +static void p_ere(register struct parse *p, int stop); +static void p_ere_exp(register struct parse *p); +static void p_str(register struct parse *p); +static void p_bre(register struct parse *p, register int end1, register int end2); +static int p_simp_re(register struct parse *p, int starordinary); +static int p_count(register struct parse *p); +static void p_bracket(register struct parse *p); +static void p_b_term(register struct parse *p, register cset *cs); +static void p_b_cclass(register struct parse *p, register cset *cs); +static void p_b_eclass(register struct parse *p, register cset *cs); +static char p_b_symbol(register struct parse *p); +static char p_b_coll_elem(register struct parse *p, int endc); +static char othercase(int ch); +static void bothcases(register struct parse *p, int ch); +static void ordinary(register struct parse *p, register int ch); +static void nonnewline(register struct parse *p); +static void repeat(register struct parse *p, sopno start, int from, int to); +static int seterr(register struct parse *p, int e); +static cset *allocset(register struct parse *p); +static void freeset(register struct parse *p, register cset *cs); +static int freezeset(register struct parse *p, register cset *cs); +static int firstch(register struct parse *p, register cset *cs); +static int nch(register struct parse *p, register cset *cs); +static void mcadd(register struct parse *p, register cset *cs, register const char *cp); +static void mcinvert(register struct parse *p, register cset *cs); +static void mccase(register struct parse *p, register cset *cs); +static int isinsets(register struct re_guts *g, int c); +static int samesets(register struct re_guts *g, int c1, int c2); +static void categorize(struct parse *p, register struct re_guts *g); +static sopno dupl(register struct parse *p, sopno start, sopno finish); +static void doemit(register struct parse *p, sop op, size_t opnd); +static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); +static void dofwd(register struct parse *p, sopno pos, sop value); +static void enlarge(register struct parse *p, sopno size); +static void stripsnug(register struct parse *p, register struct re_guts *g); +static void findmust(register struct parse *p, register struct re_guts *g); +static sopno pluscount(register struct parse *p, register struct re_guts *g); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/winsup/cygwin/regex/regerror.c b/winsup/cygwin/regex/regerror.c new file mode 100644 index 000000000..4d14ab231 --- /dev/null +++ b/winsup/cygwin/regex/regerror.c @@ -0,0 +1,127 @@ +#include "winsup.h" +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <stdlib.h> +#include "regex.h" + +#include "utils.h" +#include "regerror.ih" + +/* + = #define REG_OKAY 0 + = #define REG_NOMATCH 1 + = #define REG_BADPAT 2 + = #define REG_ECOLLATE 3 + = #define REG_ECTYPE 4 + = #define REG_EESCAPE 5 + = #define REG_ESUBREG 6 + = #define REG_EBRACK 7 + = #define REG_EPAREN 8 + = #define REG_EBRACE 9 + = #define REG_BADBR 10 + = #define REG_ERANGE 11 + = #define REG_ESPACE 12 + = #define REG_BADRPT 13 + = #define REG_EMPTY 14 + = #define REG_ASSERT 15 + = #define REG_INVARG 16 + = #define REG_ATOI 255 // convert name to number (!) + = #define REG_ITOA 0400 // convert number to name (!) + */ +static struct rerr { + int code; + const char *name; + const char *explain; +} rerrs[] = { + {REG_OKAY, "REG_OKAY", "no errors detected"}, + {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"}, + {REG_BADPAT, "REG_BADPAT", "invalid regular expression"}, + {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"}, + {REG_ECTYPE, "REG_ECTYPE", "invalid character class"}, + {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"}, + {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"}, + {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"}, + {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"}, + {REG_EBRACE, "REG_EBRACE", "braces not balanced"}, + {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"}, + {REG_ERANGE, "REG_ERANGE", "invalid character range"}, + {REG_ESPACE, "REG_ESPACE", "out of memory"}, + {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"}, + {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"}, + {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"}, + {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"}, + {-1, "", "*** unknown regexp error code ***"}, +}; + +/* + - regerror - the interface to error numbers + = extern size_t regerror(int, const regex_t *, char *, size_t); + */ +/* ARGSUSED */ +size_t +regerror(errcode, preg, errbuf, errbuf_size) +int errcode; +const regex_t *preg; +char *errbuf; +size_t errbuf_size; +{ + register struct rerr *r; + register size_t len; + register int target = errcode &~ REG_ITOA; + register const char *s; + char convbuf[50]; + + if (errcode == REG_ATOI) + s = regatoi(preg, convbuf); + else { + for (r = rerrs; r->code >= 0; r++) + if (r->code == target) + break; + + if (errcode®_ITOA) { + if (r->code >= 0) + (void) strcpy(convbuf, r->name); + else + sprintf(convbuf, "REG_0x%x", target); + assert(strlen(convbuf) < sizeof(convbuf)); + s = convbuf; + } else + s = r->explain; + } + + len = strlen(s) + 1; + if (errbuf_size > 0) { + if (errbuf_size > len) + (void) strcpy(errbuf, s); + else { + (void) strncpy(errbuf, s, errbuf_size-1); + errbuf[errbuf_size-1] = '\0'; + } + } + + return(len); +} + +/* + - regatoi - internal routine to implement REG_ATOI + == static char *regatoi(const regex_t *preg, char *localbuf); + */ +static const char * +regatoi(preg, localbuf) +const regex_t *preg; +char *localbuf; +{ + register struct rerr *r; + + for (r = rerrs; r->code >= 0; r++) + if (strcmp(r->name, preg->re_endp) == 0) + break; + if (r->code < 0) + return("0"); + + sprintf(localbuf, "%d", r->code); + return(localbuf); +} diff --git a/winsup/cygwin/regex/regerror.ih b/winsup/cygwin/regex/regerror.ih new file mode 100644 index 000000000..d428544e3 --- /dev/null +++ b/winsup/cygwin/regex/regerror.ih @@ -0,0 +1,12 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regerror.c === */ +static const char *regatoi(const regex_t *preg, char *localbuf); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/winsup/cygwin/regex/regex.3 b/winsup/cygwin/regex/regex.3 new file mode 100644 index 000000000..bc747096d --- /dev/null +++ b/winsup/cygwin/regex/regex.3 @@ -0,0 +1,509 @@ +.TH REGEX 3 "25 Sept 1997" +.BY "Henry Spencer" +.de ZR +.\" one other place knows this name: the SEE ALSO section +.IR regex (7) \\$1 +.. +.SH NAME +regcomp, regexec, regerror, regfree \- regular-expression library +.SH SYNOPSIS +.ft B +.\".na +#include <sys/types.h> +.br +#include <regex.h> +.HP 10 +int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags); +.HP +int\ regexec(const\ regex_t\ *preg, const\ char\ *string, +size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags); +.HP +size_t\ regerror(int\ errcode, const\ regex_t\ *preg, +char\ *errbuf, size_t\ errbuf_size); +.HP +void\ regfree(regex_t\ *preg); +.\".ad +.ft +.SH DESCRIPTION +These routines implement POSIX 1003.2 regular expressions (``RE''s); +see +.ZR . +.I Regcomp +compiles an RE written as a string into an internal form, +.I regexec +matches that internal form against a string and reports results, +.I regerror +transforms error codes from either into human-readable messages, +and +.I regfree +frees any dynamically-allocated storage used by the internal form +of an RE. +.PP +The header +.I <regex.h> +declares two structure types, +.I regex_t +and +.IR regmatch_t , +the former for compiled internal forms and the latter for match reporting. +It also declares the four functions, +a type +.IR regoff_t , +and a number of constants with names starting with ``REG_''. +.PP +.I Regcomp +compiles the regular expression contained in the +.I pattern +string, +subject to the flags in +.IR cflags , +and places the results in the +.I regex_t +structure pointed to by +.IR preg . +.I Cflags +is the bitwise OR of zero or more of the following flags: +.IP REG_EXTENDED \w'REG_EXTENDED'u+2n +Compile modern (``extended'') REs, +rather than the obsolete (``basic'') REs that +are the default. +.IP REG_BASIC +This is a synonym for 0, +provided as a counterpart to REG_EXTENDED to improve readability. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +.IP REG_NOSPEC +Compile with recognition of all special characters turned off. +All characters are thus considered ordinary, +so the ``RE'' is a literal string. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +REG_EXTENDED and REG_NOSPEC may not be used +in the same call to +.IR regcomp . +.IP REG_ICASE +Compile for matching that ignores upper/lower case distinctions. +See +.ZR . +.IP REG_NOSUB +Compile for matching that need only report success or failure, +not what was matched. +.IP REG_NEWLINE +Compile for newline-sensitive matching. +By default, newline is a completely ordinary character with no special +meaning in either REs or strings. +With this flag, +`[^' bracket expressions and `.' never match newline, +a `^' anchor matches the null string after any newline in the string +in addition to its normal function, +and the `$' anchor matches the null string before any newline in the +string in addition to its normal function. +.IP REG_PEND +The regular expression ends, +not at the first NUL, +but just before the character pointed to by the +.I re_endp +member of the structure pointed to by +.IR preg . +The +.I re_endp +member is of type +.IR const\ char\ * . +This flag permits inclusion of NULs in the RE; +they are considered ordinary characters. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +.PP +When successful, +.I regcomp +returns 0 and fills in the structure pointed to by +.IR preg . +One member of that structure +(other than +.IR re_endp ) +is publicized: +.IR re_nsub , +of type +.IR size_t , +contains the number of parenthesized subexpressions within the RE +(except that the value of this member is undefined if the +REG_NOSUB flag was used). +If +.I regcomp +fails, it returns a non-zero error code; +see DIAGNOSTICS. +.PP +.I Regexec +matches the compiled RE pointed to by +.I preg +against the +.IR string , +subject to the flags in +.IR eflags , +and reports results using +.IR nmatch , +.IR pmatch , +and the returned value. +The RE must have been compiled by a previous invocation of +.IR regcomp . +The compiled form is not altered during execution of +.IR regexec , +so a single compiled RE can be used simultaneously by multiple threads. +.PP +By default, +the NUL-terminated string pointed to by +.I string +is considered to be the text of an entire line, +with the NUL indicating the end of the line. +(That is, +any other end-of-line marker is considered to have been removed +and replaced by the NUL.) +The +.I eflags +argument is the bitwise OR of zero or more of the following flags: +.IP REG_NOTBOL \w'REG_STARTEND'u+2n +The first character of +the string +is not the beginning of a line, so the `^' anchor should not match before it. +This does not affect the behavior of newlines under REG_NEWLINE. +.IP REG_NOTEOL +The NUL terminating +the string +does not end a line, so the `$' anchor should not match before it. +This does not affect the behavior of newlines under REG_NEWLINE. +.IP REG_STARTEND +The string is considered to start at +\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR +and to have a terminating NUL located at +\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR +(there need not actually be a NUL at that location), +regardless of the value of +.IR nmatch . +See below for the definition of +.IR pmatch +and +.IR nmatch . +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL; +REG_STARTEND affects only the location of the string, +not how it is matched. +.PP +See +.ZR +for a discussion of what is matched in situations where an RE or a +portion thereof could match any of several substrings of +.IR string . +.PP +Normally, +.I regexec +returns 0 for success and the non-zero code REG_NOMATCH for failure. +Other non-zero error codes may be returned in exceptional situations; +see DIAGNOSTICS. +.PP +If REG_NOSUB was specified in the compilation of the RE, +or if +.I nmatch +is 0, +.I regexec +ignores the +.I pmatch +argument (but see below for the case where REG_STARTEND is specified). +Otherwise, +.I pmatch +points to an array of +.I nmatch +structures of type +.IR regmatch_t . +Such a structure has at least the members +.I rm_so +and +.IR rm_eo , +both of type +.I regoff_t +(a signed arithmetic type at least as large as an +.I off_t +and a +.IR ssize_t ), +containing respectively the offset of the first character of a substring +and the offset of the first character after the end of the substring. +Offsets are measured from the beginning of the +.I string +argument given to +.IR regexec . +An empty substring is denoted by equal offsets, +both indicating the character following the empty substring. +.PP +The 0th member of the +.I pmatch +array is filled in to indicate what substring of +.I string +was matched by the entire RE. +Remaining members report what substring was matched by parenthesized +subexpressions within the RE; +member +.I i +reports subexpression +.IR i , +with subexpressions counted (starting at 1) by the order of their opening +parentheses in the RE, left to right. +Unused entries in the array\(emcorresponding either to subexpressions that +did not participate in the match at all, or to subexpressions that do not +exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both +.I rm_so +and +.I rm_eo +set to \-1. +If a subexpression participated in the match several times, +the reported substring is the last one it matched. +(Note, as an example in particular, that when the RE `(b*)+' matches `bbb', +the parenthesized subexpression matches the three `b's and then +an infinite number of empty strings following the last `b', +so the reported substring is one of the empties.) +.PP +If REG_STARTEND is specified, +.I pmatch +must point to at least one +.I regmatch_t +(even if +.I nmatch +is 0 or REG_NOSUB was specified), +to hold the input offsets for REG_STARTEND. +Use for output is still entirely controlled by +.IR nmatch ; +if +.I nmatch +is 0 or REG_NOSUB was specified, +the value of +.IR pmatch [0] +will not be changed by a successful +.IR regexec . +.PP +.I Regerror +maps a non-zero +.I errcode +from either +.I regcomp +or +.I regexec +to a human-readable, printable message. +If +.I preg +is non-NULL, +the error code should have arisen from use of +the +.I regex_t +pointed to by +.IR preg , +and if the error code came from +.IR regcomp , +it should have been the result from the most recent +.I regcomp +using that +.IR regex_t . +.RI ( Regerror +may be able to supply a more detailed message using information +from the +.IR regex_t .) +.I Regerror +places the NUL-terminated message into the buffer pointed to by +.IR errbuf , +limiting the length (including the NUL) to at most +.I errbuf_size +bytes. +If the whole message won't fit, +as much of it as will fit before the terminating NUL is supplied. +In any case, +the returned value is the size of buffer needed to hold the whole +message (including terminating NUL). +If +.I errbuf_size +is 0, +.I errbuf +is ignored but the return value is still correct. +.PP +If the +.I errcode +given to +.I regerror +is first ORed with REG_ITOA, +the ``message'' that results is the printable name of the error code, +e.g. ``REG_NOMATCH'', +rather than an explanation thereof. +If +.I errcode +is REG_ATOI, +then +.I preg +shall be non-NULL and the +.I re_endp +member of the structure it points to +must point to the printable name of an error code; +in this case, the result in +.I errbuf +is the decimal digits of +the numeric value of the error code +(0 if the name is not recognized). +REG_ITOA and REG_ATOI are intended primarily as debugging facilities; +they are extensions, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +Be warned also that they are considered experimental and changes are possible. +.PP +.I Regfree +frees any dynamically-allocated storage associated with the compiled RE +pointed to by +.IR preg . +The remaining +.I regex_t +is no longer a valid compiled RE +and the effect of supplying it to +.I regexec +or +.I regerror +is undefined. +.PP +None of these functions references global variables except for tables +of constants; +all are safe for use from multiple threads if the arguments are safe. +.SH IMPLEMENTATION CHOICES +There are a number of decisions that 1003.2 leaves up to the implementor, +either by explicitly saying ``undefined'' or by virtue of them being +forbidden by the RE grammar. +This implementation treats them as follows. +.PP +See +.ZR +for a discussion of the definition of case-independent matching. +.PP +There is no particular limit on the length of REs, +except insofar as memory is limited. +Memory usage is approximately linear in RE size, and largely insensitive +to RE complexity, except for bounded repetitions. +See BUGS for one short RE using them +that will run almost any system out of memory. +.PP +A backslashed character other than one specifically given a magic meaning +by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs) +is taken as an ordinary character. +.PP +Any unmatched [ is a REG_EBRACK error. +.PP +Equivalence classes cannot begin or end bracket-expression ranges. +The endpoint of one range cannot begin another. +.PP +RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255. +.PP +A repetition operator (?, *, +, or bounds) cannot follow another +repetition operator. +A repetition operator cannot begin an expression or subexpression +or follow `^' or `|'. +.PP +`|' cannot appear first or last in a (sub)expression or after another `|', +i.e. an operand of `|' cannot be an empty subexpression. +An empty parenthesized subexpression, `()', is legal and matches an +empty (sub)string. +An empty string is not a legal RE. +.PP +A `{' followed by a digit is considered the beginning of bounds for a +bounded repetition, which must then follow the syntax for bounds. +A `{' \fInot\fR followed by a digit is considered an ordinary character. +.PP +`^' and `$' beginning and ending subexpressions in obsolete (``basic'') +REs are anchors, not ordinary characters. +.SH SEE ALSO +grep(1), regex(7) +.PP +POSIX 1003.2, sections 2.8 (Regular Expression Notation) +and +B.5 (C Binding for Regular Expression Matching). +.SH DIAGNOSTICS +Non-zero error codes from +.I regcomp +and +.I regexec +include the following: +.PP +.nf +.ta \w'REG_ECOLLATE'u+3n +REG_NOMATCH regexec() failed to match +REG_BADPAT invalid regular expression +REG_ECOLLATE invalid collating element +REG_ECTYPE invalid character class +REG_EESCAPE \e applied to unescapable character +REG_ESUBREG invalid backreference number +REG_EBRACK brackets [ ] not balanced +REG_EPAREN parentheses ( ) not balanced +REG_EBRACE braces { } not balanced +REG_BADBR invalid repetition count(s) in { } +REG_ERANGE invalid character range in [ ] +REG_ESPACE ran out of memory +REG_BADRPT ?, *, or + operand invalid +REG_EMPTY empty (sub)expression +REG_ASSERT ``can't happen''\(emyou found a bug +REG_INVARG invalid argument, e.g. negative-length string +.fi +.SH HISTORY +Written by Henry Spencer, +henry@zoo.toronto.edu. +.SH BUGS +This is an alpha release with known defects. +Please report problems. +.PP +There is one known functionality bug. +The implementation of internationalization is incomplete: +the locale is always assumed to be the default one of 1003.2, +and only the collating elements etc. of that locale are available. +.PP +The back-reference code is subtle and doubts linger about its correctness +in complex cases. +.PP +.I Regexec +performance is poor. +This will improve with later releases. +.I Nmatch +exceeding 0 is expensive; +.I nmatch +exceeding 1 is worse. +.I Regexec +is largely insensitive to RE complexity \fIexcept\fR that back +references are massively expensive. +RE length does matter; in particular, there is a strong speed bonus +for keeping RE length under about 30 characters, +with most special characters counting roughly double. +.PP +.I Regcomp +implements bounded repetitions by macro expansion, +which is costly in time and space if counts are large +or bounded repetitions are nested. +An RE like, say, +`((((a{1,100}){1,100}){1,100}){1,100}){1,100}' +will (eventually) run almost any existing machine out of swap space. +.PP +There are suspected problems with response to obscure error conditions. +Notably, +certain kinds of internal overflow, +produced only by truly enormous REs or by multiply nested bounded repetitions, +are probably not handled well. +.PP +Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is +a special character only in the presence of a previous unmatched `('. +This can't be fixed until the spec is fixed. +.PP +The standard's definition of back references is vague. +For example, does +`a\e(\e(b\e)*\e2\e)*d' match `abbbd'? +Until the standard is clarified, +behavior in such cases should not be relied on. +.PP +The implementation of word-boundary matching is a bit of a kludge, +and bugs may lurk in combinations of word-boundary matching and anchoring. diff --git a/winsup/cygwin/regex/regex.7 b/winsup/cygwin/regex/regex.7 new file mode 100644 index 000000000..0fa180269 --- /dev/null +++ b/winsup/cygwin/regex/regex.7 @@ -0,0 +1,235 @@ +.TH REGEX 7 "25 Oct 1995" +.BY "Henry Spencer" +.SH NAME +regex \- POSIX 1003.2 regular expressions +.SH DESCRIPTION +Regular expressions (``RE''s), +as defined in POSIX 1003.2, come in two forms: +modern REs (roughly those of +.IR egrep ; +1003.2 calls these ``extended'' REs) +and obsolete REs (roughly those of +.IR ed ; +1003.2 ``basic'' REs). +Obsolete REs mostly exist for backward compatibility in some old programs; +they will be discussed at the end. +1003.2 leaves some aspects of RE syntax and semantics open; +`\(dg' marks decisions on these aspects that +may not be fully portable to other 1003.2 implementations. +.PP +A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR, +separated by `|'. +It matches anything that matches one of the branches. +.PP +A branch is one\(dg or more \fIpieces\fR, concatenated. +It matches a match for the first, followed by a match for the second, etc. +.PP +A piece is an \fIatom\fR possibly followed +by a single\(dg `*', `+', `?', or \fIbound\fR. +An atom followed by `*' matches a sequence of 0 or more matches of the atom. +An atom followed by `+' matches a sequence of 1 or more matches of the atom. +An atom followed by `?' matches a sequence of 0 or 1 matches of the atom. +.PP +A \fIbound\fR is `{' followed by an unsigned decimal integer, +possibly followed by `,' +possibly followed by another unsigned decimal integer, +always followed by `}'. +The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive, +and if there are two of them, the first may not exceed the second. +An atom followed by a bound containing one integer \fIi\fR +and no comma matches +a sequence of exactly \fIi\fR matches of the atom. +An atom followed by a bound +containing one integer \fIi\fR and a comma matches +a sequence of \fIi\fR or more matches of the atom. +An atom followed by a bound +containing two integers \fIi\fR and \fIj\fR matches +a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom. +.PP +An atom is a regular expression enclosed in `()' (matching a match for the +regular expression), +an empty set of `()' (matching the null string)\(dg, +a \fIbracket expression\fR (see below), `.' +(matching any single character), `^' (matching the null string at the +beginning of a line), `$' (matching the null string at the +end of a line), a `\e' followed by one of the characters +`^.[$()|*+?{\e' +(matching that character taken as an ordinary character), +a `\e' followed by any other character\(dg +(matching that character taken as an ordinary character, +as if the `\e' had not been present\(dg), +or a single character with no other significance (matching that character). +A `{' followed by a character other than a digit is an ordinary +character, not the beginning of a bound\(dg. +It is illegal to end an RE with `\e'. +.PP +A \fIbracket expression\fR is a list of characters enclosed in `[]'. +It normally matches any single character from the list (but see below). +If the list begins with `^', +it matches any single character +(but see below) \fInot\fR from the rest of the list. +If two characters in the list are separated by `\-', this is shorthand +for the full \fIrange\fR of characters between those two (inclusive) in the +collating sequence, +e.g. `[0\-9]' in ASCII matches any decimal digit. +It is illegal\(dg for two ranges to share an +endpoint, e.g. `a\-c\-e'. +Ranges are very collating-sequence-dependent, +and portable programs should avoid relying on them. +.PP +To include a literal `]' in the list, make it the first character +(following a possible `^'). +To include a literal `\-', make it the first or last character, +or the second endpoint of a range. +To use a literal `\-' as the first endpoint of a range, +enclose it in `[.' and `.]' to make it a collating element (see below). +With the exception of these and some combinations using `[' (see next +paragraphs), all other special characters, including `\e', lose their +special significance within a bracket expression. +.PP +Within a bracket expression, a collating element (a character, +a multi-character sequence that collates as if it were a single character, +or a collating-sequence name for either) +enclosed in `[.' and `.]' stands for the +sequence of characters of that collating element. +The sequence is a single element of the bracket expression's list. +A bracket expression containing a multi-character collating element +can thus match more than one character, +e.g. if the collating sequence includes a `ch' collating element, +then the RE `[[.ch.]]*c' matches the first five characters +of `chchcc'. +.PP +Within a bracket expression, a collating element enclosed in `[=' and +`=]' is an equivalence class, standing for the sequences of characters +of all collating elements equivalent to that one, including itself. +(If there are no other equivalent collating elements, +the treatment is as if the enclosing delimiters were `[.' and `.]'.) +For example, if o and \o'o^' are the members of an equivalence class, +then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous. +An equivalence class may not\(dg be an endpoint +of a range. +.PP +Within a bracket expression, the name of a \fIcharacter class\fR enclosed +in `[:' and `:]' stands for the list of all characters belonging to that +class. +Standard character class names are: +.PP +.RS +.nf +.ta 3c 6c 9c +alnum digit punct +alpha graph space +blank lower upper +cntrl print xdigit +.fi +.RE +.PP +These stand for the character classes defined in +.IR ctype (3). +A locale may provide others. +A character class may not be used as an endpoint of a range. +.PP +There are two special cases\(dg of bracket expressions: +the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at +the beginning and end of a word respectively. +A word is defined as a sequence of +word characters +which is neither preceded nor followed by +word characters. +A word character is an +.I alnum +character (as defined by +.IR ctype (3)) +or an underscore. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +.PP +In the event that an RE could match more than one substring of a given +string, +the RE matches the one starting earliest in the string. +If the RE could match more than one substring starting at that point, +it matches the longest. +Subexpressions also match the longest possible substrings, subject to +the constraint that the whole match be as long as possible, +with subexpressions starting earlier in the RE taking priority over +ones starting later. +Note that higher-level subexpressions thus take priority over +their lower-level component subexpressions. +.PP +Match lengths are measured in characters, not collating elements. +A null string is considered longer than no match at all. +For example, +`bb*' matches the three middle characters of `abbbc', +`(wee|week)(knights|nights)' matches all ten characters of `weeknights', +when `(.*).*' is matched against `abc' the parenthesized subexpression +matches all three characters, and +when `(a*)*' is matched against `bc' both the whole RE and the parenthesized +subexpression match the null string. +.PP +If case-independent matching is specified, +the effect is much as if all case distinctions had vanished from the +alphabet. +When an alphabetic that exists in multiple cases appears as an +ordinary character outside a bracket expression, it is effectively +transformed into a bracket expression containing both cases, +e.g. `x' becomes `[xX]'. +When it appears inside a bracket expression, all case counterparts +of it are added to the bracket expression, so that (e.g.) `[x]' +becomes `[xX]' and `[^x]' becomes `[^xX]'. +.PP +No particular limit is imposed on the length of REs\(dg. +Programs intended to be portable should not employ REs longer +than 256 bytes, +as an implementation can refuse to accept such REs and remain +POSIX-compliant. +.PP +Obsolete (``basic'') regular expressions differ in several respects. +`|', `+', and `?' are ordinary characters and there is no equivalent +for their functionality. +The delimiters for bounds are `\e{' and `\e}', +with `{' and `}' by themselves ordinary characters. +The parentheses for nested subexpressions are `\e(' and `\e)', +with `(' and `)' by themselves ordinary characters. +`^' is an ordinary character except at the beginning of the +RE or\(dg the beginning of a parenthesized subexpression, +`$' is an ordinary character except at the end of the +RE or\(dg the end of a parenthesized subexpression, +and `*' is an ordinary character if it appears at the beginning of the +RE or the beginning of a parenthesized subexpression +(after a possible leading `^'). +Finally, there is one new type of atom, a \fIback reference\fR: +`\e' followed by a non-zero decimal digit \fId\fR +matches the same sequence of characters +matched by the \fId\fRth parenthesized subexpression +(numbering subexpressions by the positions of their opening parentheses, +left to right), +so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'. +.SH SEE ALSO +regex(3) +.PP +POSIX 1003.2, section 2.8 (Regular Expression Notation). +.SH HISTORY +Written by Henry Spencer, based on the 1003.2 spec. +.SH BUGS +Having two kinds of REs is a botch. +.PP +The current 1003.2 spec says that `)' is an ordinary character in +the absence of an unmatched `('; +this was an unintentional result of a wording error, +and change is likely. +Avoid relying on it. +.PP +Back references are a dreadful botch, +posing major problems for efficient implementations. +They are also somewhat vaguely defined +(does +`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?). +Avoid using them. +.PP +1003.2's specification of case-independent matching is vague. +The ``one case implies all cases'' definition given above +is current consensus among implementors as to the right interpretation. +.PP +The syntax for word boundaries is incredibly ugly. diff --git a/winsup/cygwin/regex/regex.h b/winsup/cygwin/regex/regex.h new file mode 100644 index 000000000..0ef0ace36 --- /dev/null +++ b/winsup/cygwin/regex/regex.h @@ -0,0 +1,83 @@ +#ifndef _REGEX_H_ +#define _REGEX_H_ /* never again */ +#include <sys/types.h> +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __INSIDE_CYGWIN__ +#define regcomp posix_regcomp +#define regerror posix_regerror +#define regexec posix_regexec +#define regfree posix_regfree +#endif + +/* === regex2.h === */ +typedef off_t regoff_t; +typedef struct { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} regex_t; +typedef struct { + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + + +/* === regcomp.c === */ +extern int regcomp(regex_t *, const char *, int); +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + + +/* === regerror.c === */ +#define REG_OKAY 0 +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ +extern size_t regerror(int, const regex_t *, char *, size_t); + + +/* === regexec.c === */ +extern int regexec(const regex_t *, const char *, size_t, regmatch_t [], int); +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + + +/* === regfree.c === */ +extern void regfree(regex_t *); + + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ +#endif diff --git a/winsup/cygwin/regex/regex2.h b/winsup/cygwin/regex/regex2.h new file mode 100644 index 000000000..58fd8d8a4 --- /dev/null +++ b/winsup/cygwin/regex/regex2.h @@ -0,0 +1,134 @@ +/* + * First, the stuff that ends up in the outside-world include file + = typedef off_t regoff_t; + = typedef struct { + = int re_magic; + = size_t re_nsub; // number of parenthesized subexpressions + = const char *re_endp; // end pointer for REG_PEND + = struct re_guts *re_g; // none of your business :-) + = } regex_t; + = typedef struct { + = regoff_t rm_so; // start of match + = regoff_t rm_eo; // end of match + = } regmatch_t; + */ +/* + * internals of regex_t + */ +#define MAGIC1 ((('r'^0200)<<8) | 'e') + +/* + * The internal representation is a *strip*, a sequence of + * operators ending with an endmarker. (Some terminology etc. is a + * historical relic of earlier versions which used multiple strips.) + * Certain oddities in the representation are there to permit running + * the machinery backwards; in particular, any deviation from sequential + * flow must be marked at both its source and its destination. Some + * fine points: + * + * - OPLUS_ and O_PLUS are *inside* the loop they create. + * - OQUEST_ and O_QUEST are *outside* the bypass they create. + * - OCH_ and O_CH are *outside* the multi-way branch they create, while + * OOR1 and OOR2 are respectively the end and the beginning of one of + * the branches. Note that there is an implicit OOR2 following OCH_ + * and an implicit OOR1 preceding O_CH. + * + * In state representations, an operator's bit is on to signify a state + * immediately *preceding* "execution" of that operator. + */ +typedef long sop; /* strip operator */ +typedef long sopno; +#define OPRMASK 0x7c000000 +#define OPDMASK 0x03ffffff +#define OPSHIFT (26) +#define OP(n) ((n)&OPRMASK) +#define OPND(n) ((n)&OPDMASK) +#define SOP(op, opnd) ((op)|(opnd)) +/* operators meaning operand */ +/* (back, fwd are offsets) */ +#define OEND (1<<OPSHIFT) /* endmarker - */ +#define OCHAR (2<<OPSHIFT) /* character unsigned char */ +#define OBOL (3<<OPSHIFT) /* left anchor - */ +#define OEOL (4<<OPSHIFT) /* right anchor - */ +#define OANY (5<<OPSHIFT) /* . - */ +#define OANYOF (6<<OPSHIFT) /* [...] set number */ +#define OBACK_ (7<<OPSHIFT) /* begin \d paren number */ +#define O_BACK (8<<OPSHIFT) /* end \d paren number */ +#define OPLUS_ (9<<OPSHIFT) /* + prefix fwd to suffix */ +#define O_PLUS (10<<OPSHIFT) /* + suffix back to prefix */ +#define OQUEST_ (11<<OPSHIFT) /* ? prefix fwd to suffix */ +#define O_QUEST (12<<OPSHIFT) /* ? suffix back to prefix */ +#define OLPAREN (13<<OPSHIFT) /* ( fwd to ) */ +#define ORPAREN (14<<OPSHIFT) /* ) back to ( */ +#define OCH_ (15<<OPSHIFT) /* begin choice fwd to OOR2 */ +#define OOR1 (16<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */ +#define OOR2 (17<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */ +#define O_CH (18<<OPSHIFT) /* end choice back to OOR1 */ +#define OBOW (19<<OPSHIFT) /* begin word - */ +#define OEOW (20<<OPSHIFT) /* end word - */ + +/* + * Structure for [] character-set representation. Character sets are + * done as bit vectors, grouped 8 to a byte vector for compactness. + * The individual set therefore has both a pointer to the byte vector + * and a mask to pick out the relevant bit of each byte. A hash code + * simplifies testing whether two sets could be identical. + * + * This will get trickier for multicharacter collating elements. As + * preliminary hooks for dealing with such things, we also carry along + * a string of multi-character elements, and decide the size of the + * vectors at run time. + */ +typedef struct { + uch *ptr; /* -> uch [csetsize] */ + uch mask; /* bit within array */ + uch hash; /* hash code */ + size_t smultis; + char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ +} cset; +/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ +#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) +#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) +#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) +#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ +#define MCsub(p, cs, cp) mcsub(p, cs, cp) +#define MCin(p, cs, cp) mcin(p, cs, cp) + +/* stuff for character categories */ +typedef unsigned char cat_t; + +/* + * main compiled-expression structure + */ +struct re_guts { + int magic; +# define MAGIC2 ((('R'^0200)<<8)|'E') + sop *strip; /* malloced area for strip */ + int csetsize; /* number of bits in a cset vector */ + int ncsets; /* number of csets in use */ + cset *sets; /* -> cset [ncsets] */ + uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ + int cflags; /* copy of regcomp() cflags argument */ + sopno nstates; /* = number of sops */ + sopno firststate; /* the initial OEND (normally 0) */ + sopno laststate; /* the final OEND */ + int iflags; /* internal flags */ +# define USEBOL 01 /* used ^ */ +# define USEEOL 02 /* used $ */ +# define BAD 04 /* something wrong */ + int nbol; /* number of ^ used */ + int neol; /* number of $ used */ + int ncategories; /* how many character categories */ + cat_t *categories; /* ->catspace[-CHAR_MIN] */ + char *must; /* match must contain this string */ + int mlen; /* length of must */ + size_t nsub; /* copy of re_nsub */ + int backrefs; /* does it use back references? */ + sopno nplus; /* how deep does it nest +s? */ + /* catspace must be last */ + cat_t catspace[1]; /* actually [NC] */ +}; + +/* misc utilities */ +#define OUT (CHAR_MAX+1) /* a non-character value */ +#define ISWORD(c) (isalnum(c) || (c) == '_') diff --git a/winsup/cygwin/regex/regexec.c b/winsup/cygwin/regex/regexec.c new file mode 100644 index 000000000..5ab72e00e --- /dev/null +++ b/winsup/cygwin/regex/regexec.c @@ -0,0 +1,141 @@ +/* + * the outer shell of regexec() + * + * This file includes engine.c *twice*, after muchos fiddling with the + * macros that code uses. This lets the same code operate on two different + * representations for state sets. + */ +#include "winsup.h" +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include "regex.h" + +#include "utils.h" +#include "regex2.h" + +#ifdef lint +static int nope = 0; /* for use in asserts; shuts lint up */ +#endif + +/* macros for manipulating states, small version */ +#define states unsigned +#define states1 unsigned /* for later use in regexec() decision */ +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~((unsigned)1 << (n))) +#define SET1(v, n) ((v) |= (unsigned)1 << (n)) +#define ISSET(v, n) ((v) & ((unsigned)1 << (n))) +#define ASSIGN(d, s) ((d) = (s)) +#define EQ(a, b) ((a) == (b)) +#define STATEVARS int dummy /* dummy version */ +#define STATESETUP(m, n) /* nothing */ +#define STATETEARDOWN(m) /* nothing */ +#define SETUP(v) ((v) = 0) +#define onestate unsigned +#define INIT(o, n) ((o) = (unsigned)1 << (n)) +#define INC(o) ((o) <<= 1) +#define ISSTATEIN(v, o) ((v) & (o)) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) ((v) & ((unsigned)here >> (n))) +/* function names */ +#define SNAMES /* engine.c looks after details */ + +#include "engine.c" + +/* now undo things */ +#undef states +#undef CLEAR +#undef SET0 +#undef SET1 +#undef ISSET +#undef ASSIGN +#undef EQ +#undef STATEVARS +#undef STATESETUP +#undef STATETEARDOWN +#undef SETUP +#undef onestate +#undef INIT +#undef INC +#undef ISSTATEIN +#undef FWD +#undef BACK +#undef ISSETBACK +#undef SNAMES + +/* macros for manipulating states, large version */ +#define states char * +#define CLEAR(v) memset(v, 0, m->g->nstates) +#define SET0(v, n) ((v)[n] = 0) +#define SET1(v, n) ((v)[n] = 1) +#define ISSET(v, n) ((v)[n]) +#define ASSIGN(d, s) memcpy(d, s, m->g->nstates) +#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) +#define STATEVARS int vn; char *space +#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ + if ((m)->space == NULL) return(REG_ESPACE); \ + (m)->vn = 0; } +#define STATETEARDOWN(m) { free((m)->space); } +#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) +#define onestate int +#define INIT(o, n) ((o) = (n)) +#define INC(o) ((o)++) +#define ISSTATEIN(v, o) ((v)[o]) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) +#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) +#define ISSETBACK(v, n) ((v)[here - (n)]) +/* function names */ +#define LNAMES /* flag */ + +#include "engine.c" + +/* + - regexec - interface for matching + = extern int regexec(const regex_t *, const char *, size_t, \ + = regmatch_t [], int); + = #define REG_NOTBOL 00001 + = #define REG_NOTEOL 00002 + = #define REG_STARTEND 00004 + = #define REG_TRACE 00400 // tracing of execution + = #define REG_LARGE 01000 // force large representation + = #define REG_BACKR 02000 // force use of backref code + * + * We put this here so we can exploit knowledge of the state representation + * when choosing which matcher to call. Also, by this point the matchers + * have been prototyped. + */ +int /* 0 success, REG_NOMATCH failure */ +regexec(preg, string, nmatch, pmatch, eflags) +const regex_t *preg; +const char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register struct re_guts *g = preg->re_g; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) +#endif + + if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) + return(REG_BADPAT); + assert(!(g->iflags&BAD)); + if (g->iflags&BAD) /* backstop for no-debug case */ + return(REG_BADPAT); + eflags = GOODFLAGS(eflags); + + if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) + return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); +} diff --git a/winsup/cygwin/regex/regfree.c b/winsup/cygwin/regex/regfree.c new file mode 100644 index 000000000..b8be143d8 --- /dev/null +++ b/winsup/cygwin/regex/regfree.c @@ -0,0 +1,38 @@ +#include "winsup.h" +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include "regex.h" + +#include "utils.h" +#include "regex2.h" + +/* + - regfree - free everything + = extern void regfree(regex_t *); + */ +void +regfree(preg) +regex_t *preg; +{ + register struct re_guts *g; + + if (preg->re_magic != MAGIC1) /* oops */ + return; /* nice to complain, but hard */ + + g = preg->re_g; + if (g == NULL || g->magic != MAGIC2) /* oops again */ + return; + preg->re_magic = 0; /* mark it invalid */ + g->magic = 0; /* mark it invalid */ + + if (g->strip != NULL) + free((char *)g->strip); + if (g->sets != NULL) + free((char *)g->sets); + if (g->setbits != NULL) + free((char *)g->setbits); + if (g->must != NULL) + free(g->must); + free((char *)g); +} diff --git a/winsup/cygwin/regex/tests b/winsup/cygwin/regex/tests new file mode 100644 index 000000000..e4d928dad --- /dev/null +++ b/winsup/cygwin/regex/tests @@ -0,0 +1,477 @@ +# regular expression test set +# Lines are at least three fields, separated by one or more tabs. "" stands +# for an empty field. First field is an RE. Second field is flags. If +# C flag given, regcomp() is expected to fail, and the third field is the +# error name (minus the leading REG_). +# +# Otherwise it is expected to succeed, and the third field is the string to +# try matching it against. If there is no fourth field, the match is +# expected to fail. If there is a fourth field, it is the substring that +# the RE is expected to match. If there is a fifth field, it is a comma- +# separated list of what the subexpressions should match, with - indicating +# no match for that one. In both the fourth and fifth fields, a (sub)field +# starting with @ indicates that the (sub)expression is expected to match +# a null string followed by the stuff after the @; this provides a way to +# test where null strings match. The character `N' in REs and strings +# is newline, `S' is space, `T' is tab, `Z' is NUL. +# +# The full list of flags: +# - placeholder, does nothing +# b RE is a BRE, not an ERE +# & try it as both an ERE and a BRE +# C regcomp() error expected, third field is error name +# i REG_ICASE +# m ("mundane") REG_NOSPEC +# s REG_NOSUB (not really testable) +# n REG_NEWLINE +# ^ REG_NOTBOL +# $ REG_NOTEOL +# # REG_STARTEND (see below) +# p REG_PEND +# +# For REG_STARTEND, the start/end offsets are those of the substring +# enclosed in (). + +# basics +a & a a +abc & abc abc +abc|de - abc abc +a|b|c - abc a + +# parentheses and perversions thereof +a(b)c - abc abc +a\(b\)c b abc abc +a( C EPAREN +a( b a( a( +a\( - a( a( +a\( bC EPAREN +a\(b bC EPAREN +a(b C EPAREN +a(b b a(b a(b +# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly) +a) - a) a) +) - ) ) +# end gagging (in a just world, those *should* give EPAREN) +a) b a) a) +a\) bC EPAREN +\) bC EPAREN +a()b - ab ab +a\(\)b b ab ab + +# anchoring and REG_NEWLINE +^abc$ & abc abc +a^b - a^b +a^b b a^b a^b +a$b - a$b +a$b b a$b a$b +^ & abc @abc +$ & abc @ +^$ & "" @ +$^ - "" @ +\($\)\(^\) b "" @ +# stop retching, those are legitimate (although disgusting) +^^ - "" @ +$$ - "" @ +b$ & abNc +b$ &n abNc b +^b$ & aNbNc +^b$ &n aNbNc b +^$ &n aNNb @Nb +^$ n abc +^$ n abcN @ +$^ n aNNb @Nb +\($\)\(^\) bn aNNb @Nb +^^ n^ aNNb @Nb +$$ n aNNb @NN +^a ^ a +a$ $ a +^a ^n aNb +^b ^n aNb b +a$ $n bNa +b$ $n bNa b +a*(^b$)c* - b b +a*\(^b$\)c* b b b + +# certain syntax errors and non-errors +| C EMPTY +| b | | +* C BADRPT +* b * * ++ C BADRPT +? C BADRPT +"" &C EMPTY +() - abc @abc +\(\) b abc @abc +a||b C EMPTY +|ab C EMPTY +ab| C EMPTY +(|a)b C EMPTY +(a|)b C EMPTY +(*a) C BADRPT +(+a) C BADRPT +(?a) C BADRPT +({1}a) C BADRPT +\(\{1\}a\) bC BADRPT +(a|*b) C BADRPT +(a|+b) C BADRPT +(a|?b) C BADRPT +(a|{1}b) C BADRPT +^* C BADRPT +^* b * * +^+ C BADRPT +^? C BADRPT +^{1} C BADRPT +^\{1\} bC BADRPT + +# metacharacters, backslashes +a.c & abc abc +a[bc]d & abd abd +a\*c & a*c a*c +a\\b & a\b a\b +a\\\*b & a\*b a\*b +a\bc & abc abc +a\ &C EESCAPE +a\\bc & a\bc a\bc +\{ bC BADRPT +a\[b & a[b a[b +a[b &C EBRACK +# trailing $ is a peculiar special case for the BRE code +a$ & a a +a$ & a$ +a\$ & a +a\$ & a$ a$ +a\\$ & a +a\\$ & a$ +a\\$ & a\$ +a\\$ & a\ a\ + +# back references, ugh +a\(b\)\2c bC ESUBREG +a\(b\1\)c bC ESUBREG +a\(b*\)c\1d b abbcbbd abbcbbd bb +a\(b*\)c\1d b abbcbd +a\(b*\)c\1d b abbcbbbd +^\(.\)\1 b abc +a\([bc]\)\1d b abcdabbd abbd b +a\(\([bc]\)\2\)*d b abbccd abbccd +a\(\([bc]\)\2\)*d b abbcbd +# actually, this next one probably ought to fail, but the spec is unclear +a\(\(b\)*\2\)*d b abbbd abbbd +# here is a case that no NFA implementation does right +\(ab*\)[ab]*\1 b ababaaa ababaaa a +# check out normal matching in the presence of back refs +\(a\)\1bcd b aabcd aabcd +\(a\)\1bc*d b aabcd aabcd +\(a\)\1bc*d b aabd aabd +\(a\)\1bc*d b aabcccd aabcccd +\(a\)\1bc*[ce]d b aabcccd aabcccd +^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd + +# ordinary repetitions +ab*c & abc abc +ab+c - abc abc +ab?c - abc abc +a\(*\)b b a*b a*b +a\(**\)b b ab ab +a\(***\)b bC BADRPT +*a b *a *a +**a b a a +***a bC BADRPT + +# the dreaded bounded repetitions +{ & { { +{abc & {abc {abc +{1 C BADRPT +{1} C BADRPT +a{b & a{b a{b +a{1}b - ab ab +a\{1\}b b ab ab +a{1,}b - ab ab +a\{1,\}b b ab ab +a{1,2}b - aab aab +a\{1,2\}b b aab aab +a{1 C EBRACE +a\{1 bC EBRACE +a{1a C EBRACE +a\{1a bC EBRACE +a{1a} C BADBR +a\{1a\} bC BADBR +a{,2} - a{,2} a{,2} +a\{,2\} bC BADBR +a{,} - a{,} a{,} +a\{,\} bC BADBR +a{1,x} C BADBR +a\{1,x\} bC BADBR +a{1,x C EBRACE +a\{1,x bC EBRACE +a{300} C BADBR +a\{300\} bC BADBR +a{1,0} C BADBR +a\{1,0\} bC BADBR +ab{0,0}c - abcac ac +ab\{0,0\}c b abcac ac +ab{0,1}c - abcac abc +ab\{0,1\}c b abcac abc +ab{0,3}c - abbcac abbc +ab\{0,3\}c b abbcac abbc +ab{1,1}c - acabc abc +ab\{1,1\}c b acabc abc +ab{1,3}c - acabc abc +ab\{1,3\}c b acabc abc +ab{2,2}c - abcabbc abbc +ab\{2,2\}c b abcabbc abbc +ab{2,4}c - abcabbc abbc +ab\{2,4\}c b abcabbc abbc +((a{1,10}){1,10}){1,10} - a a a,a + +# multiple repetitions +a** &C BADRPT +a++ C BADRPT +a?? C BADRPT +a*+ C BADRPT +a*? C BADRPT +a+* C BADRPT +a+? C BADRPT +a?* C BADRPT +a?+ C BADRPT +a{1}{1} C BADRPT +a*{1} C BADRPT +a+{1} C BADRPT +a?{1} C BADRPT +a{1}* C BADRPT +a{1}+ C BADRPT +a{1}? C BADRPT +a*{b} - a{b} a{b} +a\{1\}\{1\} bC BADRPT +a*\{1\} bC BADRPT +a\{1\}* bC BADRPT + +# brackets, and numerous perversions thereof +a[b]c & abc abc +a[ab]c & abc abc +a[^ab]c & adc adc +a[]b]c & a]c a]c +a[[b]c & a[c a[c +a[-b]c & a-c a-c +a[^]b]c & adc adc +a[^-b]c & adc adc +a[b-]c & a-c a-c +a[b &C EBRACK +a[] &C EBRACK +a[1-3]c & a2c a2c +a[3-1]c &C ERANGE +a[1-3-5]c &C ERANGE +a[[.-.]--]c & a-c a-c +a[1- &C ERANGE +a[[. &C EBRACK +a[[.x &C EBRACK +a[[.x. &C EBRACK +a[[.x.] &C EBRACK +a[[.x.]] & ax ax +a[[.x,.]] &C ECOLLATE +a[[.one.]]b & a1b a1b +a[[.notdef.]]b &C ECOLLATE +a[[.].]]b & a]b a]b +a[[:alpha:]]c & abc abc +a[[:notdef:]]c &C ECTYPE +a[[: &C EBRACK +a[[:alpha &C EBRACK +a[[:alpha:] &C EBRACK +a[[:alpha,:] &C ECTYPE +a[[:]:]]b &C ECTYPE +a[[:-:]]b &C ECTYPE +a[[:alph:]] &C ECTYPE +a[[:alphabet:]] &C ECTYPE +[[:alnum:]]+ - -%@a0X- a0X +[[:alpha:]]+ - -%@aX0- aX +[[:blank:]]+ - aSSTb SST +[[:cntrl:]]+ - aNTb NT +[[:digit:]]+ - a019b 019 +[[:graph:]]+ - Sa%bS a%b +[[:lower:]]+ - AabC ab +[[:print:]]+ - NaSbN aSb +[[:punct:]]+ - S%-&T %-& +[[:space:]]+ - aSNTb SNT +[[:upper:]]+ - aBCd BC +[[:xdigit:]]+ - p0f3Cq 0f3C +a[[=b=]]c & abc abc +a[[= &C EBRACK +a[[=b &C EBRACK +a[[=b= &C EBRACK +a[[=b=] &C EBRACK +a[[=b,=]] &C ECOLLATE +a[[=one=]]b & a1b a1b + +# complexities +a(((b)))c - abc abc +a(b|(c))d - abd abd +a(b*|c)d - abbd abbd +# just gotta have one DFA-buster, of course +a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and an inline expansion in case somebody gets tricky +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and in case somebody just slips in an NFA... +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights +# fish for anomalies as the number of states passes 32 +12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789 +123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890 +1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901 +12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012 +123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123 +# and one really big one, beyond any plausible word width +1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890 +# fish for problems as brackets go past 8 +[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm +[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo +[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq +[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq + +# subtleties of matching +abc & xabcy abc +a\(b\)?c\1d b acd +aBc i Abc Abc +a[Bc]*d i abBCcd abBCcd +0[[:upper:]]1 &i 0a1 0a1 +0[[:lower:]]1 &i 0A1 0A1 +a[^b]c &i abc +a[^b]c &i aBc +a[^b]c &i adc adc +[a]b[c] - abc abc +[a]b[a] - aba aba +[abc]b[abc] - abc abc +[abc]b[abd] - abd abd +a(b?c)+d - accd accd +(wee|week)(knights|night) - weeknights weeknights +(we|wee|week|frob)(knights|night|day) - weeknights weeknights +a[bc]d - xyzaaabcaababdacd abd +a[ab]c - aaabc abc +abc s abc abc +a* & b @b + +# Let's have some fun -- try to match a C comment. +# first the obvious, which looks okay at first glance... +/\*.*\*/ - /*x*/ /*x*/ +# but... +/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/ +# okay, we must not match */ inside; try to do that... +/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/ +/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/ +# but... +/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/ +# and a still fancier version, which does it right (I think)... +/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/ +/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/ + +# subexpressions +.* - abc abc - +a(b)(c)d - abcd abcd b,c +a(((b)))c - abc abc b,b,b +a(b|(c))d - abd abd b,- +a(b*|c|e)d - abbd abbd bb +a(b*|c|e)d - acd acd c +a(b*|c|e)d - ad ad @d +a(b?)c - abc abc b +a(b?)c - ac ac @c +a(b+)c - abc abc b +a(b+)c - abbbc abbbc bbb +a(b*)c - ac ac @c +(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de +# the regression tester only asks for 9 subexpressions +a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j +a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k +a([bc]?)c - abc abc b +a([bc]?)c - ac ac @c +a([bc]+)c - abc abc b +a([bc]+)c - abcc abcc bc +a([bc]+)bc - abcbc abcbc bc +a(bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abbb abbb bb +a(bbb+|bb+|b)bb - abbb abbb b +(.*).* - abcdef abcdef abcdef +(a*)* - bc @b @b + +# do we get the right subexpression when it is used more than once? +a(b|c)*d - ad ad - +a(b|c)*d - abcd abcd c +a(b|c)+d - abd abd b +a(b|c)+d - abcd abcd c +a(b|c?)+d - ad ad @d +a(b|c?)+d - abcd abcd @d +a(b|c){0,0}d - ad ad - +a(b|c){0,1}d - ad ad - +a(b|c){0,1}d - abd abd b +a(b|c){0,2}d - ad ad - +a(b|c){0,2}d - abcd abcd c +a(b|c){0,}d - ad ad - +a(b|c){0,}d - abcd abcd c +a(b|c){1,1}d - abd abd b +a(b|c){1,1}d - acd acd c +a(b|c){1,2}d - abd abd b +a(b|c){1,2}d - abcd abcd c +a(b|c){1,}d - abd abd b +a(b|c){1,}d - abcd abcd c +a(b|c){2,2}d - acbd acbd b +a(b|c){2,2}d - abcd abcd c +a(b|c){2,4}d - abcd abcd c +a(b|c){2,4}d - abcbd abcbd b +a(b|c){2,4}d - abcbcd abcbcd c +a(b|c){2,}d - abcd abcd c +a(b|c){2,}d - abcbd abcbd b +a(b+|((c)*))+d - abd abd @d,@d,- +a(b+|((c)*))+d - abcd abcd @d,@d,- + +# check out the STARTEND option +[abc] &# a(b)c b +[abc] &# a(d)c +[abc] &# a(bc)d b +[abc] &# a(dc)d c +. &# a()c +b.*c &# b(bc)c bc +b.* &# b(bc)c bc +.*c &# b(bc)c bc + +# plain strings, with the NOSPEC flag +abc m abc abc +abc m xabcy abc +abc m xyz +a*b m aba*b a*b +a*b m ab +"" mC EMPTY + +# cases involving NULs +aZb & a a +aZb &p a +aZb &p# (aZb) aZb +aZ*b &p# (ab) ab +a.b &# (aZb) aZb +a.* &# (aZb)c aZb + +# word boundaries (ick) +[[:<:]]a & a a +[[:<:]]a & ba +[[:<:]]a & -a a +a[[:>:]] & a a +a[[:>:]] & ab +a[[:>:]] & a- a +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc +[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc +[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc +[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_ +[[:<:]]a_b[[:>:]] & x_a_b + +# past problems, and suspected problems +(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1 +abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop +abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv +(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11 +CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11 +Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz +a?b - ab ab +-\{0,1\}[0-9]*$ b -5 -5 +a*a*a*a*a*a*a* & aaaaaa aaaaaa diff --git a/winsup/cygwin/regex/utils.h b/winsup/cygwin/regex/utils.h new file mode 100644 index 000000000..1a997ac8f --- /dev/null +++ b/winsup/cygwin/regex/utils.h @@ -0,0 +1,22 @@ +/* utility definitions */ +#ifdef _POSIX2_RE_DUP_MAX +#define DUPMAX _POSIX2_RE_DUP_MAX +#else +#define DUPMAX 255 +#endif +#define INFINITY (DUPMAX + 1) +#define NC (CHAR_MAX - CHAR_MIN + 1) +typedef unsigned char uch; + +/* switch off assertions (if not already off) if no REDEBUG */ +#ifndef REDEBUG +#ifndef NDEBUG +#define NDEBUG /* no assertions please */ +#endif +#endif +#include <assert.h> + +/* for old systems with bcopy() but no memmove() */ +#ifdef USEBCOPY +#define memmove(d, s, c) bcopy(s, d, c) +#endif diff --git a/winsup/cygwin/regexp/v8_regerror.c b/winsup/cygwin/regexp/v8_regerror.c new file mode 100644 index 000000000..56d63ff2f --- /dev/null +++ b/winsup/cygwin/regexp/v8_regerror.c @@ -0,0 +1,28 @@ +/* regerror.c + + Copyright 1996, 1998, 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include "regexp.h" +#include <stdio.h> + +void __declspec(dllexport) +regerror(const char *s __attribute__ ((unused))) +{ +#ifdef ERRAVAIL + error("regexp: %s", s); +#else +/* + fprintf(stderr, "regexp(3): %s\n", s); + exit(1); +*/ + return; /* let std. egrep handle errors */ +#endif + /* NOTREACHED */ +} diff --git a/winsup/cygwin/regexp/v8_regexp.c b/winsup/cygwin/regexp/v8_regexp.c new file mode 100644 index 000000000..fef1267a0 --- /dev/null +++ b/winsup/cygwin/regexp/v8_regexp.c @@ -0,0 +1,1321 @@ +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to | + *** to assist in implementing egrep. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching + *** as in BSD grep and ex. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \. + *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods, + *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy. + *** THIS IS AN ALTERED VERSION. It was altered by Geoffrey Noer, + *** noer@cygnus.com, on 6 Oct 1997, to change the prototype format + *** for inclusion in the Cygwin32 library. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ + +#include "winsup.h" +#include "regexp.h" +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include "regmagic.h" + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define WORDA 12 /* no Match "" at wordchar, where prev is nonword */ +#define WORDZ 13 /* no Match "" at nonwordchar, where prev is word */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE 30 /* no Analogous to OPEN. */ + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +/* + * Global work variables for regcomp(). + */ +static char *regparse; /* Input-scan pointer. */ +static int regnpar; /* () count. */ +static char regdummy; +static char *regcode; /* Code-emit pointer; ®dummy = don't. */ +static long regsize; /* Code size. */ + +/* + * Forward declarations for regcomp()'s friends. + */ +#ifndef STATIC +#define STATIC static +#endif +STATIC char *reg (int, int *); +STATIC char *regbranch (int *); +STATIC char *regpiece (int *); +STATIC char *regatom (int *); +STATIC char *regnode (char); +STATIC char *regnext (char *); +STATIC void regc (char); +STATIC void reginsert (char, char *); +STATIC void regtail (char *, char *); +STATIC void regoptail (char *, char *); +#ifdef STRCSPN +STATIC int strcspn (char *, char *); +#endif + +/* + - regcomp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ +regexp * __declspec(dllexport) +regcomp(exp) +const char *exp; +{ + register regexp *r; + register char *scan; + register char *longest; + register int len; + int flags; + + if (exp == NULL) + FAIL("NULL argument"); + + /* First pass: determine size, legality. */ +#ifdef notdef + if (exp[0] == '.' && exp[1] == '*') exp += 2; /* aid grep */ +#endif + regparse = (char *)exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Small enough for pointer-storage convention? */ + if (regsize >= 32767L) /* Probably could be 65535L. */ + FAIL("regexp too big"); + + /* Allocate space. */ + r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); + if (r == NULL) + FAIL("out of space"); + + /* Second pass: emit code. */ + regparse = (char *)exp; + regnpar = 1; + regcode = r->program; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Dig out information for optimizations. */ + r->regstart = '\0'; /* Worst-case defaults. */ + r->reganch = 0; + r->regmust = NULL; + r->regmlen = 0; + scan = r->program+1; /* First BRANCH. */ + if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(scan) == EXACTLY) + r->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + r->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && (int) strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + r->regmust = longest; + r->regmlen = len; + } + } + + return(r); +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static char * +reg(paren, flagp) +int paren; /* Parenthesized? */ +int *flagp; +{ + register char *ret; + register char *br; + register char *ender; + register int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = regnpar; + regnpar++; + ret = regnode(OPEN+parno); + } else + ret = NULL; + + /* Pick up the branches, linking them together. */ + br = regbranch(&flags); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*regparse == '|' || *regparse == '\n') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END); + regtail(ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + /* Check for proper termination. */ + if (paren && *regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char * +regbranch(flagp) +int *flagp; +{ + register char *ret; + register char *chain; + register char *latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != ')' && + *regparse != '\n' && *regparse != '|') { + latest = regpiece(&flags); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static char * +regpiece(flagp) +int *flagp; +{ + register char *ret; + register char op; + register char *next; + int flags; + + ret = regatom(&flags); + if (ret == NULL) + return(NULL); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret); /* Either x */ + regoptail(ret, regnode(BACK)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH); /* Either */ + regtail(ret, next); + regtail(regnode(BACK), ret); /* loop back */ + regtail(next, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret); /* Either x */ + regtail(ret, regnode(BRANCH)); /* or */ + next = regnode(NOTHING); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) + FAIL("nested *?+"); + + return(ret); +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static char * +regatom(flagp) +int *flagp; +{ + register char *ret; + int flags; + + *flagp = WORST; /* Tentatively. */ + + switch (*regparse++) { + /* FIXME: these chars only have meaning at beg/end of pat? */ + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int class; + register int classend; + + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); + regparse++; + } else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + class = UCHARAT(regparse-2)+1; + classend = UCHARAT(regparse); + if (class > classend+1) + FAIL("invalid [] range"); + for (; class <= classend; class++) + regc(class); + regparse++; + } + } else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case '\n': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + break; + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + break; + case '\\': + switch (*regparse++) { + case '\0': + FAIL("trailing \\"); + break; + case '<': + ret = regnode(WORDA); + break; + case '>': + ret = regnode(WORDZ); + break; + /* FIXME: Someday handle \1, \2, ... */ + default: + /* Handle general quoted chars in exact-match routine */ + goto de_fault; + } + break; + de_fault: + default: + /* + * Encode a string of characters to be matched exactly. + * + * This is a bit tricky due to quoted chars and due to + * '*', '+', and '?' taking the SINGLE char previous + * as their operand. + * + * On entry, the char at regparse[-1] is going to go + * into the string, no matter what it is. (It could be + * following a \ if we are entered from the '\' case.) + * + * Basic idea is to pick up a good char in ch and + * examine the next char. If it's *+? then we twiddle. + * If it's \ then we frozzle. If it's other magic char + * we push ch and terminate the string. If none of the + * above, we push ch on the string and go around again. + * + * regprev is used to remember where "the current char" + * starts in the string, if due to a *+? we need to back + * up and put the current char in a separate, 1-char, string. + * When regprev is NULL, ch is the only char in the + * string; this is used in *+? handling, and in setting + * flags |= SIMPLE at the end. + */ + { + char *regprev; + register char ch = 0; + + regparse--; /* Look at cur char */ + ret = regnode(EXACTLY); + for ( regprev = 0 ; ; ) { + ch = *regparse++; /* Get current char */ + switch (*regparse) { /* look at next one */ + + default: + regc(ch); /* Add cur to string */ + break; + + case '.': case '[': case '(': + case ')': case '|': case '\n': + case '$': case '^': + case '\0': + /* FIXME, $ and ^ should not always be magic */ + magic: + regc(ch); /* dump cur char */ + goto done; /* and we are done */ + + case '?': case '+': case '*': + if (!regprev) /* If just ch in str, */ + goto magic; /* use it */ + /* End mult-char string one early */ + regparse = regprev; /* Back up parse */ + goto done; + + case '\\': + regc(ch); /* Cur char OK */ + switch (regparse[1]){ /* Look after \ */ + case '\0': + case '<': + case '>': + /* FIXME: Someday handle \1, \2, ... */ + goto done; /* Not quoted */ + default: + /* Backup point is \, scan * point is after it. */ + regprev = regparse; + regparse++; + continue; /* NOT break; */ + } + } + regprev = regparse; /* Set backup point */ + } + done: + regc('\0'); + *flagp |= HASWIDTH; + if (!regprev) /* One char? */ + *flagp |= SIMPLE; + } + break; + } + + return(ret); +} + +/* + - regnode - emit a node + */ +static char * /* Location. */ +regnode(op) +char op; +{ + register char *ret; + register char *ptr; + + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return(ret); + } + + ptr = ret; + *ptr++ = op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + regcode = ptr; + + return(ret); +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void +regc(b) +char b; +{ + if (regcode != ®dummy) + *regcode++ = b; + else + regsize++; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +static void +reginsert(op, opnd) +char op; +char *opnd; +{ + register char *src; + register char *dst; + register char *place; + + if (regcode == ®dummy) { + regsize += 3; + return; + } + + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; /* Op node, where operand used to be. */ + *place++ = op; + *place++ = '\0'; + *place++ = '\0'; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void +regtail(p, val) +char *p; +char *val; +{ + register char *scan; + register char *temp; + register int offset; + + if (p == ®dummy) + return; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (offset>>8)&0377; + *(scan+2) = offset&0377; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void +regoptail(p, val) +char *p; +char *val; +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + +/* + * regexec and friends + */ + +/* + * Global work variables for regexec(). + */ +static char *reginput; /* String-input pointer. */ +static char *regbol; /* Beginning of input, for ^ check. */ +static char **regstartp; /* Pointer to startp array. */ +static char **regendp; /* Ditto for endp. */ + +/* + * Forwards. + */ +STATIC int regtry (const regexp *, const char *); +STATIC int regmatch (char *); +STATIC int regrepeat (char *); + +#ifdef DEBUG +int regnarrate = 0; +void regdump __P((regexp *)); +STATIC char *regprop __P((char *)); +#endif + +/* + - regexec - match a regexp against a string + */ +int __declspec(dllexport) +regexec(prog, string) +register const regexp *prog; +register const char *string; +{ + register char *s; + + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + regerror("NULL parameter"); + return(0); + } + + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + regerror("corrupted program"); + return(0); + } + + /* If there is a "must appear" string, look for it. */ + if (prog->regmust != NULL) { + s = (char *)string; + while ((s = strchr(s, prog->regmust[0])) != NULL) { + if (strncmp(s, prog->regmust, prog->regmlen) == 0) + break; /* Found it. */ + s++; + } + if (s == NULL) /* Not present. */ + return(0); + } + + /* Mark beginning of line for ^ . */ + regbol = (char *)string; + + /* Simplest case: anchored match need be tried only once. */ + if (prog->reganch) + return(regtry(prog, string)); + + /* Messy cases: unanchored match. */ + s = (char *)string; + if (prog->regstart != '\0') + /* We know what char it must start with. */ + while ((s = strchr(s, prog->regstart)) != NULL) { + if (regtry(prog, s)) + return(1); + s++; + } + else + /* We don't -- general case. */ + do { + if (regtry(prog, s)) + return(1); + } while (*s++ != '\0'); + + /* Failure. */ + return(0); +} + +/* + - regtry - try match at specific point + */ +static int /* 0 failure, 1 success */ +regtry(prog, string) +const regexp *prog; +const char *string; +{ + register int i; + register char **sp; + register char **ep; + + reginput = (char *)string; /* XXX */ + regstartp = (char **)prog->startp; /* XXX */ + regendp = (char **)prog->endp; /* XXX */ + + sp = (char **)prog->startp; /* XXX */ + ep = (char **)prog->endp; /* XXX */ + for (i = NSUBEXP; i > 0; i--) { + *sp++ = NULL; + *ep++ = NULL; + } + if (regmatch((char *)prog->program + 1)) { /* XXX */ + ((regexp *)prog)->startp[0] = (char *)string; /* XXX */ + ((regexp *)prog)->endp[0] = reginput; /* XXX */ + return(1); + } else + return(0); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +static int /* 0 failure, 1 success */ +regmatch(prog) +char *prog; +{ + register char *scan; /* Current node. */ + char *next; /* Next node. */ + + scan = prog; +#ifdef DEBUG + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != NULL) { +#ifdef DEBUG + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); +#endif + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (reginput != regbol) + return(0); + break; + case EOL: + if (*reginput != '\0') + return(0); + break; + case WORDA: + /* Must be looking at a letter, digit, or _ */ + if ((!isalnum(*reginput)) && *reginput != '_') + return(0); + /* Prev must be BOL or nonword */ + if (reginput > regbol && + (isalnum(reginput[-1]) || reginput[-1] == '_')) + return(0); + break; + case WORDZ: + /* Must be looking at non letter, digit, or _ */ + if (isalnum(*reginput) || *reginput == '_') + return(0); + /* We don't care what the previous char was */ + break; + case ANY: + if (*reginput == '\0') + return(0); + reginput++; + break; + case EXACTLY: { + register int len; + register char *opnd; + + opnd = OPERAND(scan); + /* Inline the first character, for speed. */ + if (*opnd != *reginput) + return(0); + len = strlen(opnd); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return(0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) + return(0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) + return(0); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; + + no = OP(scan) - OPEN; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (regstartp[no] == NULL) + regstartp[no] = save; + return(1); + } else + return(0); + } + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; + + no = OP(scan) - CLOSE; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (regendp[no] == NULL) + regendp[no] = save; + return(1); + } else + return(0); + } + break; + case BRANCH: { + register char *save; + + if (OP(next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = reginput; + if (regmatch(OPERAND(scan))) + return(1); + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min) { + /* If it could work, try it. */ + if (nextch == '\0' || *reginput == nextch) + if (regmatch(next)) + return(1); + /* Couldn't or didn't -- back up. */ + no--; + reginput = save + no; + } + return(0); + } + break; + case END: + return(1); /* Success! */ + break; + default: + regerror("memory corruption"); + return(0); + break; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + regerror("corrupted pointers"); + return(0); +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int +regrepeat(p) +char *p; +{ + register int count = 0; + register char *scan; + register char *opnd; + + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + regerror("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static char * +regnext(p) +register char *p; +{ + register int offset; + + if (p == ®dummy) + return(NULL); + + offset = NEXT(p); + if (offset == 0) + return(NULL); + + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#ifdef DEBUG + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +void +regdump(r) +regexp *r; +{ + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; + extern char *strchr(); + + + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } + + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static char * +regprop(op) +char *op; +{ + register char *p; + static char buf[50]; + + (void) strcpy(buf, ":"); + + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + case WORDA: + p = "WORDA"; + break; + case WORDZ: + p = "WORDZ"; + break; + default: + regerror("corrupted opcode"); + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); +} +#endif + +/* + * The following is provided for those people who do not have strcspn() in + * their C libraries. They should get off their butts and do something + * about it; at least one public-domain implementation of those (highly + * useful) string routines has been published on Usenet. + */ +#ifdef STRCSPN +/* + * strcspn - find length of initial segment of s1 consisting entirely + * of characters not from s2 + */ + +static int +strcspn(s1, s2) +char *s1; +char *s2; +{ + register char *scan1; + register char *scan2; + register int count; + + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); +} +#endif diff --git a/winsup/cygwin/regexp/v8_regsub.c b/winsup/cygwin/regexp/v8_regsub.c new file mode 100644 index 000000000..aa95b876a --- /dev/null +++ b/winsup/cygwin/regexp/v8_regsub.c @@ -0,0 +1,88 @@ +/* + * regsub + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + */ + +#if 0 +#ifndef lint +static char *rcsid = "$Id$"; +#endif /* not lint */ +#endif + +#include "winsup.h" +#include "regexp.h" +#include <stdio.h> +#include <string.h> +#include "regmagic.h" + +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +/* + - regsub - perform substitutions after a regexp match + */ +void __declspec(dllexport) +regsub(prog, source, dest) +const regexp *prog; +const char *source; +char *dest; +{ + register char *src; + register char *dst; + register char c; + register int no; + register int len; + + if (prog == NULL || source == NULL || dest == NULL) { + regerror("NULL parm to regsub"); + return; + } + if (UCHARAT(prog->program) != MAGIC) { + regerror("damaged regexp fed to regsub"); + return; + } + + src = (char *)source; + dst = dest; + while ((c = *src++) != '\0') { + if (c == '&') + no = 0; + else if (c == '\\' && '0' <= *src && *src <= '9') + no = *src++ - '0'; + else + no = -1; + if (no < 0) { /* Ordinary character. */ + if (c == '\\' && (*src == '\\' || *src == '&')) + c = *src++; + *dst++ = c; + } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { + len = prog->endp[no] - prog->startp[no]; + (void) strncpy(dst, prog->startp[no], len); + dst += len; + if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ + regerror("damaged match string"); + return; + } + } + } + *dst++ = '\0'; +} diff --git a/winsup/cygwin/rmsym b/winsup/cygwin/rmsym new file mode 100755 index 000000000..685802684 --- /dev/null +++ b/winsup/cygwin/rmsym @@ -0,0 +1,11 @@ +#!/bin/sh +lib=$1; shift +nm=$1; shift +ar=$1; shift +ranlib=$1; shift +grepit=`echo $* | sed 's/ /|__imp__/g'` +[ -n "$grepit" ] && grepit="__imp__$grepit" +objs=`$nm $lib | awk -F: '/^d[0-9]*.o:/ {obj=$1} '"/$grepit/"'{print obj}'` +[ -n "$objs" ] || exit 1 +$ar d $lib $objs +$ranlib $lib diff --git a/winsup/cygwin/speclib b/winsup/cygwin/speclib new file mode 100755 index 000000000..f9c467685 --- /dev/null +++ b/winsup/cygwin/speclib @@ -0,0 +1,12 @@ +#!/bin/sh +case "$1" in + -v) v="-v"; shift +esac +lib=$1; shift +nm=$1; shift +dlltool=$1; shift +def=$1; shift +trap "rm /tmp/$$.def" 0 1 2 15 +(echo "LIBRARY cygwin1.dll +EXPORTS"; $nm --extern-only --defined-only $* | sed -e '/^[ ]*$/d' -e '/:$/d' -e 's/^.* _\(.*\)/\1/' | grep $v -f - -w $def |egrep -vi '^library|exports|^$' | sort) > /tmp/$$.def +exec $dlltool -d /tmp/$$.def -l "$lib" -D /dev/null diff --git a/winsup/cygwin/winbase.h b/winsup/cygwin/winbase.h new file mode 100644 index 000000000..d72bb0893 --- /dev/null +++ b/winsup/cygwin/winbase.h @@ -0,0 +1,83 @@ +#include_next "winbase.h" + +#ifndef _WINBASE2_H +#define _WINBASE2_H + +extern __inline__ long ilockincr (long *m) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl $1,%0\n\ + lock xadd %0,(%1)\n\ + inc %0\n\ + ": "=a" (__res), "=r" (m): "1" (m)); + return __res; +} +extern __inline__ long ilockdecr (long *m) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl $0xffffffff,%0\n\ + lock xadd %0,(%1)\n\ + dec %0\n\ + ": "=a" (__res), "=r" (m): "1" (m)); + return __res; +} +extern __inline__ long ilockexch (long *t, long v) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl (%2),%0\n\ +1: lock cmpxchgl %3,(%1)\n\ + jne 1b\n\ + ": "=a" (__res), "=c" (t): "1" (t), "d" (v)); + return __res; +} + +#undef InterlockedIncrement +#define InterlockedIncrement ilockincr +#undef InterlockedDecrement +#define InterlockedDecrement ilockdecr +#undef InterlockedExchange +#define InterlockedExchange ilockexch + +extern long tls_ix; +extern char * volatile *__stackbase __asm__ ("%fs:4"); + +extern __inline__ DWORD +my_tlsalloc () +{ + DWORD n = ilockdecr (&tls_ix); + __stackbase[tls_ix] = NULL; + return n; +} + +extern __inline__ BOOL +my_tlssetvalue (DWORD ix, void *val) +{ + __stackbase[ix] = (char *) val; + return 1; +} + +extern __inline__ void * +my_tlsgetvalue (DWORD ix) +{ + return __stackbase[ix]; +} + +extern __inline__ BOOL +my_tlsfree (DWORD ix) +{ + /* nothing for now */ + return 1; +} + +#undef TlsAlloc +#define TlsAlloc my_tlsalloc +#undef TlsGetValue +#define TlsGetValue my_tlsgetvalue +#undef TlsSetValue +#define TlsSetValue my_tlssetvalue +#undef TlsFree +#define TlsFree my_tlsfree +#endif /*_WINBASE2_H*/ |