import winsup-2000-02-17 snapshot

This commit is contained in:
Christopher Faylor 2000-02-17 19:38:33 +00:00
parent 369d8a8fd5
commit 1fd5e000ac
582 changed files with 146593 additions and 0 deletions

46
winsup/CYGWIN_LICENSE Normal file
View File

@ -0,0 +1,46 @@
--------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (GPL) as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--------------------------------------------------------------------------
*** NOTE ***
In accordance with section 10 of the GPL, Cygnus permits programs whose
sources are distributed under a license that complies with the Open
Source definition to be linked with libcygwin.a without libcygwin.a
itself causing the resulting program to be covered by the GNU GPL.
This means that you can port an Open Source(tm) application to cygwin,
and distribute that executable as if it didn't include a copy of
libcygwin.a linked into it. Note that this does not apply to the cygwin
DLL itself. If you distribute a (possibly modified) version of the DLL
you must adhere to the terms of the GPL, i.e., you must provide sources
for the cygwin DLL.
See http://www.opensource.org/osd.html for the precise Open Source
Definition referenced above.
If you have questions about any of the above or would like to arrange
for other licensing terms, please contact Cygnus using the information
given below:
Cygnus Solutions
1325 Chesapeake Terrace
Sunnyvale, CA 94089
USA
+1 408 542 9600
hotline: +1 408 542 9601
email: info@cygnus.com
fax: +1 408 542 9699

36
winsup/ChangeLog Normal file
View File

@ -0,0 +1,36 @@
Sun Feb 6 18:15:44 2000 Christopher Faylor <cgf@cygnus.com>
* configure.in: Do the standard CC/CFLAGS stuff for propagation to
sub-configures.
* configure: Regenerate.
2000-01-26 DJ Delorie <dj@cygnus.com>
* doc/Makefile.in: fix doctool -d options
Fri Jan 21 12:51:32 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.common: No need to rerun Makefile if config.status changes.
That should happen automatically.
* Makefile.in: Ditto.
Sat Jan 8 14:40:01 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.common: Remove cygwin DLL specific stuff. Make Makefile
target PRECIOUS.
* Makefile.in: Make Makefile target PRECIOUS.
Fri Jan 7 21:00:49 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.common: Remove cygwin DLL specific stuff. Correctly deal
with updir stuff when building in the same directory as the source.
Thu Jan 6 19:04:35 2000 Christopher Faylor <cgf@cygnus.com>
Create new directory structure
* Makefile.in: New file.
* configure.in: New file.
* configure: New file.
* Makefile.common: New file.
* cygwin: New directory.
* w32api: New directory.

17
winsup/MAINTAINERS Normal file
View File

@ -0,0 +1,17 @@
The following people are responsible for maintaining various pieces of
the winsup directory. Their approval is required before committing any
changes to the repository.
Makefile.* Chris Faylor <cgf@cygnus.com>
configure.* Chris Faylor <cgf@cygnus.com>
MAINTAINERS Chris Faylor <cgf@cygnus.com>
cygwin/security.cc and
ntsec stuff Corinna Vinschen <corinna@vinschen.de>
cygwin/fhandler_tape.cc Corinna Vinschen <corinna@vinschen.de>
cygwin/{everything else} Chris Faylor <cgf@cygnus.com>,
DJ Delorie <cgf@cygnus.com>
doc/* DJ Delorie <cgf@cygnus.com>
mingw/* Mumit Khan <xraylith.wisc.edu>
utils/* Chris Faylor <cgf@cygnus.com>,
DJ Delorie <dj@cygnus.com>
w32api/* Mumit Khan <xraylith.wisc.edu>

127
winsup/Makefile.common Normal file
View File

@ -0,0 +1,127 @@
# Makefile.common - common definitions for the winsup directory
#
# Copyright 2000 Cygnus Solutions.
#
# This file is part of Cygwin.
#
# This software is a copyrighted work licensed under the terms of the
# Cygwin license. Please consult the file "CYGWIN_LICENSE" for
# details.
# This makefile requires GNU make.
CFLAGS_COMMON:=-Wall -Wwrite-strings # -finline-functions
MALLOC_DEBUG:=#-DMALLOC_DEBUG -I/gotham/src/comp-tools/winsup/dlmalloc
MALLOC_OBJ:=#/gotham/src/comp-tools/winsup/dlmalloc/malloc.o
ifeq (,${findstring /,$(srcdir)})
updir:=$(srcdir)/..
updir1:=$(updir)/..
else
updir:=${patsubst %:::,%,${patsubst %/:::,%,$(dir $(srcdir)):::}}
ifneq (,${findstring /,$(updir)})
updir1:=${patsubst %:::,%,${patsubst %/:::,%,$(dir $(updir)):::}}
else
updir1:=$(updir)/..
endif
endif
pwd:=${shell pwd}
ifeq (,${findstring /,$(pwd)})
bupdir:=..
bupdir1:=../..
else
bupdir:=${patsubst %:::,%,${patsubst %/:::,%,$(dir $(pwd)):::}}
ifneq (,${findstring /,$(bupdir)})
bupdir1:=${patsubst %:::,%,${patsubst %/:::,%,$(dir $(bupdir)):::}}
else
bupdir1:=$(bupdir)/..
endif
endif
w32api_source:=$(updir)/w32api
w32api_build:=$(bupdir)/w32api
w32api_include:=$(w32api_source)/include
w32api_lib:=$(w32api_build)/lib
newlib_source:=$(updir1)/newlib
newlib_build:=$(bupdir1)/newlib
cygwin_build:=$(bupdir)/cygwin
cygwin_source:=$(updir)/cygwin
mingw_build:=$(bupdir)/mingw
mingw_source:=$(updir)/mingw
utils_build:=$(bupdir)/utils
utils_source:=$(updir)/utils
INCLUDES:=-I. -I$(cygwin_source)/include -I$(cygwin_source) -I$(newlib_source)/libc/sys/cygwin -I$(newlib_source)/libc/include -I$(w32api_include)
ifdef CONFIG_DIR
INCLUDES+=-I$(CONFIG_DIR)
endif
MINGW_INCLUDES:=-I$(updir)/mingw/include $(INCLUDES)
GCC_DEFAULT_OPTIONS:=$(CFLAGS_COMMON) $(CFLAGS_CONFIG) $(INCLUDES)
# Link in libc and libm from newlib
LIBC:=$(newlib_build)/libc/libc.a
LIBM:=$(newlib_build)/libm/libm.a
CRT0:=$(newlib_build)/libc/crt0.o
ALL_CFLAGS:=$(DEFS) $(MALLOC_DEBUG) $(CFLAGS) $(GCC_DEFAULT_OPTIONS)
ALL_CXXFLAGS:=$(DEFS) $(MALLOC_DEBUG) $(CXXFLAGS) $(GCC_DEFAULT_OPTIONS)
ifndef PREPROCESS
c=-c
o=.o
else
c=-E
o=.E
endif
LIBGCC:=${subst \,/,${shell $(CC_FOR_TARGET) -print-libgcc-file-name}}
GCC_INCLUDE:=${dir $(LIBGCC)}/include
COMPILE_CXX:=$(CC) $c -nostdinc++ $(ALL_CXXFLAGS) -I$(GCC_INCLUDE) \
-fno-rtti -fno-exceptions
COMPILE_CC:=$(CC) $c -nostdinc $(ALL_CFLAGS) -I$(GCC_INCLUDE)
vpath %.a $(cygwin_build):$(w32api_lib):$(newlib_build)/libc:$(newlib_build)/libm
unexport MAKEOVERRIDES
.PRECIOUS: %.o
%.o: %.cc
ifdef VERBOSE
$(COMPILE_CXX) -o $(@D)/$(*F)$o $<
else
@echo $(CC) $c $(CXXFLAGS) -o $(@D)/$(*F)$o ${subst $(srcdir)/,,$<}; \
$(COMPILE_CXX) -o $(@D)/$(*F)$o $<
endif
%.o: %.c
ifdef VERBOSE
$(COMPILE_CC) -o $(@D)/$(*F)$o $<
else
@echo $(CC) $c $(CFLAGS) -o $(@D)/$(*F)$o ${subst $(srcdir)/,,$<}; \
$(COMPILE_CC) -o $(@D)/$(*F)$o $<
endif
$(bupdir1)/libiberty/%.o: $(updir1)/libiberty/%.c
@$(MAKE) -C $(@D) $(MAKEOVERRIDES) $(@F)
$(w32api_lib)/%.a: $(w32api_lib)/Makefile
@$(MAKE) --no-print-dir -C $(@D) $(MAKEOVERRIDES) $(@F)
all:
# For auto-rebuilding the Makefile
.PRECIOUS: Makefile
Makefile: Makefile.in $(srcdir)/configure.in config.status
$(SHELL) config.status
config.status: configure
$(SHELL) config.status --recheck

71
winsup/Makefile.in Normal file
View File

@ -0,0 +1,71 @@
# Makefile.in for windows stuff
# Copyright 1995, 1996, 1997, 1998, 1999 Cygnus Solutions.
#
# This file is part of Cygwin.
#
# This software is a copyrighted work licensed under the terms of the
# Cygwin license. Please consult the file "CYGWIN_LICENSE" for
# details.
# This makefile requires GNU make.
SHELL:=@SHELL@
VPATH:=@srcdir@
srcdir:=@srcdir@
objdir:=.
target_alias:=@target_alias@
build_alias:=@build_alias@
host_alias:=@host_alias@
prefix:=@prefix@
program_transform_name:=@program_transform_name@
exec_prefix:=@exec_prefix@
bindir:=@bindir@
libdir:=@libdir@
ifeq ($(target_alias),$(host_alias))
ifeq ($(build_alias),$(host_alias))
tooldir:=$(exec_prefix)
else
tooldir:=$(exec_prefix)/$(target_alias)
endif
else
tooldir:=$(exec_prefix)/$(target_alias)
endif
datadir:=@datadir@
infodir:=@infodir@
includedir:=@includedir@
SUBDIRS=@SUBDIRS@
INSTALL_SUBDIRS=${patsubst %,install_%,$(SUBDIRS)}
CLEAN_SUBDIRS=${patsubst %,clean_%,$(SUBDIRS)}
.PHONY: all install clean $(SUBDIRS) $(INSTALL_SUBDIRS) \
$(CLEAN_SUBDIRS)
.SUFFIXES:
unexport MAKEOVERRIDES
all: Makefile $(SUBDIRS)
install: Makefile $(INSTALL_SUBDIRS)
clean: $(CLEAN_SUBDIRS)
$(SUBDIRS):
@$(MAKE) -C $@ $(MAKEOVERRIDES) all
$(INSTALL_SUBDIRS):
@$(MAKE) -C ${patsubst install_%,%,$@} $(MAKEOVERRIDES) install
$(CLEAN_SUBDIRS):
@$(MAKE) -C ${patsubst clean_%,%,$@} $(MAKEOVERRIDES) clean
.PRECIOUS: Makefile
Makefile: Makefile.in $(srcdir)/configure.in config.status
$(SHELL) config.status
config.status: configure
$(SHELL) config.status --recheck

1223
winsup/configure vendored Executable file

File diff suppressed because it is too large Load Diff

65
winsup/configure.in Executable file
View File

@ -0,0 +1,65 @@
dnl Autoconf configure script for Cygwin.
dnl Copyright 1996, 1997, 1998 Cygnus Solutions.
dnl
dnl This file is part of Cygwin.
dnl
dnl This software is a copyrighted work licensed under the terms of the
dnl Cygwin license. Please consult the file "CYGWIN_LICENSE" for
dnl details.
dnl
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.12)dnl
AC_INIT(Makefile.in)
dnl FIXME: We temporarily define our own version of AC_PROG_CC. This is
dnl copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
dnl are probably using a cross compiler, which will not be able to fully
dnl link an executable. This should really be fixed in autoconf
dnl itself.
AC_DEFUN(LIB_AC_PROG_CC,
[AC_BEFORE([$0], [AC_PROG_CPP])dnl
AC_CHECK_TOOL(CC, gcc, gcc)
if test -z "$CC"; then
AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
fi
AC_PROG_CC_GNU
if test $ac_cv_prog_gcc = yes; then
GCC=yes
dnl Check whether -g works, even if CFLAGS is set, in case the package
dnl plays around with CFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
AC_PROG_CC_G
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
if test "$ac_test_CXXFLAGS" != set; then
CXXFLAGS='$(CFLAGS)'
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
])
AC_CANONICAL_SYSTEM
LIB_AC_PROG_CC
SUBDIRS="cygwin w32api mingw utils doc"
AC_CONFIG_SUBDIRS($SUBDIRS)
AC_PROG_MAKE_SET
AC_SUBST(SUBDIRS)
AC_OUTPUT(Makefile)

View File

@ -0,0 +1,46 @@
--------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (GPL) as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--------------------------------------------------------------------------
*** NOTE ***
In accordance with section 10 of the GPL, Cygnus permits programs whose
sources are distributed under a license that complies with the Open
Source definition to be linked with libcygwin.a without libcygwin.a
itself causing the resulting program to be covered by the GNU GPL.
This means that you can port an Open Source(tm) application to cygwin,
and distribute that executable as if it didn't include a copy of
libcygwin.a linked into it. Note that this does not apply to the cygwin
DLL itself. If you distribute a (possibly modified) version of the DLL
you must adhere to the terms of the GPL, i.e., you must provide sources
for the cygwin DLL.
See http://www.opensource.org/osd.html for the precise Open Source
Definition referenced above.
If you have questions about any of the above or would like to arrange
for other licensing terms, please contact Cygnus using the information
given below:
Cygnus Solutions
1325 Chesapeake Terrace
Sunnyvale, CA 94089
USA
+1 408 542 9600
hotline: +1 408 542 9601
email: info@cygnus.com
fax: +1 408 542 9699

229
winsup/cygwin/ChangeLog Normal file
View File

@ -0,0 +1,229 @@
Mon Feb 7 16:50:44 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.in: cygrun needs libshell32.a.
Sun Feb 6 22:17:58 2000 Christopher Faylor <cgf@cygnus.com>
* sigproc.cc (proc_subproc): Simplify case for when a child process is
stopped since new signal handler ensures the desired behavior.
Sun Feb 6 21:52:33 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.in: Fix install target so that directories will be created
when necessary.
Sun Feb 6 18:12:17 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.in: exceptions.cc should depend on autoload.h.
* exceptions.cc: Undef DECLSPEC_IMPORT prior to including imagehlp.h to
avoid defining StackWalk as "import".
(call_handler): Minor optimizations.
(sig_handle_tty_stop): Fix typo in previous checkin.
* sigproc.cc (sigproc_init): Ditto, for signal_arrived initialization.
Sat Feb 5 15:37:37 2000 Christopher Faylor <cgf@cygnus.com>
* dcrt0.cc (isquote): Convert to inline function.
Sat Feb 5 00:26:01 2000 Christopher Faylor <cgf@cygnus.com>
Throughout, rename global_signal_arrived to signal_arrived.
Throughout, eliminate use of arm_signals and __signal_arrived.
Throughout, revert to use of simple call to WaitForSingleObject or
WaitForMultipleObjects.
* debug.h: Eliminate obsolete function declaration.
* exceptions.cc (sigWaitForSingleObject): Eliminate obsolete function
definition.
* fhandler.h: Reflect change to select_stuff wait method.
* fhandler_tape.cc (get_ll): Accomodate new w32api LARGE_INTEGER
definition.
* ntea.c (NTReadEARaw): Ditto.
(NTWriteEA): Ditto.
* security.cc (ReadSD): Ditto.
(WriteSD): Ditto.
* syscalls.cc (_link): Ditto.
* uname.cc (uname): Eliminate PPC switch.
2000-02-01 Salvador Eduardo Tropea <salvador@inti.gov.ar>
* include/io.h: add return type to setmode()
2000-01-27 DJ Delorie <dj@cygnus.com>
* include/netdb.h (h_errno): change __imp_ to dllimport
* cygwin.din (reent_data): add DATA
Thu Jan 27 01:07:14 2000 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (call_handler): Add debugging output.
* select.cc (MAKEready): Arm signals earlier.
* sigproc.cc (__signal_arrived:arm): Move debugging version of this
method here.
(__signal_arrived::release): Ditto.
* sigproc.h: Recognize debugging versions of above two methods.
(arm_signals::WaitForMultipleObjects): Don't release signal lock unless
signal arrived.
(arm_signals::WaitForMultipleSingleObject): Ditto.
(arm_signals::MsgWaitForMultipleObjects): Ditto.
Thu Jan 27 00:19:26 2000 Christopher Faylor <cgf@cygnus.com>
* sync.h (new_muto): Workaround change in gcc behavior.
Wed Jan 26 12:57:13 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.in: Ensure that all required libraries are built prior
to linking cygrun.exe.
Tue Jan 25 21:26:57 2000 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (sig_handle): Crudely work around potential problem
when main thread has a lock but is killed by a fatal signal.
* fhandler_tty.cc (fhandler_pty_master::write): Don't perform line
editing on the pty master (so why do we need the second argument to
line_edit, then?)
* thread.cc: Reformat to GNU standards.
2000-01-11 DJ Delorie <dj@cygnus.com>
* ROADMAP: new
2000-01-11 DJ Delorie <dj@cygnus.com>
* fhandler_zero.cc: new, emulate /dev/zero
* testsuite/winsup.api/devzero.c: new, test /dev/zero
* Makefile.in: build fhandler_zero.o
* fhandler.h: add support for /dev/zero
* hinfo.cc: ditto
* path.cc: ditto
2000-01-11 DJ Delorie <dj@cygnus.com>
* mmap.cc (mmap): MSDN says *one* of FILE_MAP_*, fix flags for
MAP_PRIVATE.
Mon Jan 10 01:11:00 2000 Corinna Vinschen <corinna@vinschen.de>
* security.cc (acl_access): New function.
* syscalls.cc (access): Call acl_access if ntsec is on.
Mon Jan 10 01:11:00 2000 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (get_file_owner): Use of ReadSD() instead of
GetFileSecurity().
(get_file_group): Ditto.
Sun Jan 9 15:43:07 2000 Christopher Faylor <cgf@cygnus.com>
* debug.cc (struct thread_start): Add a flag to determine whether a
field is in use. Eliminate thread_start_ix since it was not
thread-safe.
(thread_stub): Use notavail flag to control whether the entry in
start_buf can be reused.
(makethread): Ditto.
Sun Jan 9 20:18:00 2000 Corinna Vinschen <corinna@vinschen.de>
* security.cc (alloc_sd): Rearrange order of ACE creation.
(setacl): Optimize creation of ACEs related to inheritance. Code
cleanup.
(aclcheck): Disable check for existance of DEF_)CLASS_OBJ.
Sat Jan 8 18:42:32 2000 Christopher Faylor <cgf@cygnus.com>
* mkvers.h: Reorg fix.
Sat Jan 8 20:00:00 2000 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din: Add new acl API calls.
* grp.cc (getgroups): Change to work for any username.
* security.cc (get_id_from_sid): Change to work with acl API.
(is_grp_member): New function.
(get_nt_attribute): Rewritten.
(add_access_allowed_ace): New function.
(add_access_denied_ace): Ditto.
(alloc_sd): Rewritten.
(setacl): New function.
(getace): Ditto.
(searchace): Ditto.
(getacl): Ditto.
(acl): Ditto.
(facl): Ditto.
(aclcheck): Ditto.
(acecmp): Ditto.
(aclsort): Ditto.
(acltomode): Ditto.
(aclfrommode): Ditto.
(acltopbits): Ditto.
(aclfrompbits): Ditto.
(permtostr): Ditto.
(acltotext): Ditto.
(permfromstr): Ditto.
(aclfromtext): Ditto.
* syscalls.cc (access): Set errno again when needed.
* include/cygwin/acl.h: New file.
* include/sys/acl.h: Ditto.
Sat Jan 8 14:46:19 2000 Christopher Faylor <cgf@cygnus.com>
* Makefile.in: Add cygwin DLL specific CFLAGS define.
Fri Jan 7 21:01:57 2000 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (interrupt_on_return): Properly coerce assignment of
sigsave.func.
2000-01-07 Mumit Khan <khan@xraylith.wisc.edu>
* acconfig.h: New file.
* configure.in Add check for memset builtin.
(AC_CONFIG_HEADER): Use.
(STRACE_HHMMSS): Define instead of substituting.
(_MT_SAFE): Likewise.
(_CYG_THREAD_FAILSAFE): Likewise.
(DEBUGGING): Likewise.
(MT_SAFE): Substitute as a yes/no variable.
* Makefile.in: Remove DEBUGGING, STRACE_HHMMSS, and THREAD_FAILSAFE
variables and add DEFS. Update usage of MT_SAFE to reflect yes/no
values. Add config.h to winsup.h dependency.
(CFLAGS_CONFIG): Update.
(INCLUDES): Prepend `-I.'.
* utils/Makefile.in (INCLUDES): Likewise.
* winsup.h: Conditionally include config.h.
* thread.cc: Likewise.
* config.h.in: Generate new file.
* configure: Regenerate.
Fri Jan 7 16:21:01 2000 Christopher Faylor <cgf@cygnus.com>
* dcrt0.cc (dll_crt0): Allow signal handling for dynamically loaded
case.
Thu Jan 6 00:30:12 2000 Corinna Vinschen <corinna@vinschen.de>
* path.cc (symlink_check_one): Initialize local variable `unixattr'
before calling `get_file_attribute'.
* syscalls.cc (chown): Ditto.
* security.cc (get_nt_attribute): Eliminate attribute copying from
world to user/group in case of missing ACEs.
(alloc_sd): Set special rights for administrators group only if it's
neither owner nor group.
* utils/mkpasswd.c: Create entry for local group administrators (SID
544).
Thu Jan 6 00:21:31 2000 Christopher Faylor <cgf@cygnus.com>
Change function calls to __stdcall throughout.
* exceptions.cc (handle_exceptions): Probe stack for return address to
use with new signal method. Fill out sigsave.cx with this information.
(call_handler): Use sigsave.cx if it is available, rather than trying
to find the context of the main thread.
(interrupt_on_return): Use address of context rather than
pass-by-reference.
(interrupt_now): Ditto.
Thu Jan 6 00:21:31 2000 Corinna Vinschen <corinna@vinschen.de>
* grp.cc (getgroups): Return supplementary groups now.
* include/limits.h: Define NGROUP_MAX as 16 now.

View File

@ -0,0 +1,177 @@
Mon Dec 18 16:44:38 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* configure.in (target_cpu): specify valid Intel x86 architectures
explicitly.
Mon Dec 18 15:04:29 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* sysdef/*.def: moved to sysdef/i386/.
Mon Dec 18 15:00:56 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* configure.in: Set DLL_ENTRY and SYSDEF_DIR for i386 and powerpc.
* configure: Regenerated with autoconf 2.7.
* Makefile.in: Use DLL_ENTRY and SYSDEF_DIR.
Sat Dec 16 18:36:44 1995 steve chamberlain <sac@slash.cygnus.com>
Changed the way that file handles are inherited. Now
all files are opened with the inheriting turned on, and they're
closed when necessary.
Changed the way that children are waited for. Now
you can exec a non-gnuwin32 program and wait for its
result.
* Makefile.in: Turn off frame-pointer.
* dcrt0.cc (environ_init): Lint.
* dirsearch.cc (opendir): Use new path_conv mechanism.
* exceptions.cc (ctrl_c_handler): Exit with correct status
* exec.cc (file_exists): Moved to paths.cc
(_execve): Moved most of the work into spawn.cc.
* fhandler.cc (*): Much.
* libccrt0.c (foo): Deleted.
(cygwin_crt0): Lint.
* path.cc (readlink): Initialize the SECURITY_ATTRIBUTES struct.
* pipe.cc (pipe, dup*): Reorganized.
* registry.cc (read_in): Create the key in CURRENT_USER.
* wait.cc, spawn.cc (*): Much.
* sysconf.cc (sysconf): Understand SC_PAGESIZE.
* times.cc (utime): New function.
* uname.cc (uname): Dig out more info.
Wed Dec 13 05:54:55 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* dcrt0.cc (environ_init): Cast alloca return to appropriate type.
* spawn.cc (spawn_guts): Ditto.
* strace.cc (__small_{v,}sprintf): Add appropriate prototypes.
* exceptions.cc (_except_list): Only use segments for 386 systems.
(__stack_trace): Add PowerPC support, and do nothing for systems
that are not supported except print stack tracing is not yet
support.
* sdata.cc (import_term): Only use __attribute__((section)) on 386
systems.
* shared.cc (shared_init): Use MARK macro instead of calling mark
directly with incorrect type arguments.
* fhandler.cc (fhandler_dev_null::{read,write}): Use size_t in
prototype, not unsigned int.
* fork.cc (find_exec): Fix type errors.
* path.cc (path_to_real_path_keep_rel): Ditto.
* syscalls.h (PATH_TO_REAL_PATH): Ditto.
* {longjmp,setjmp}.c: #ifdef i386 code.
* include/wintypes.h (ExitProcess): Add
__attribute__((__noreturn__)) so exit compiles without warnings.
Tue Dec 12 18:25:05 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* include/wintypes.h (WINAPI): Only define WINAPI for x86 systems.
Tue Dec 5 16:00:05 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* Makefile.in (all): Only build documentation for info target.
Expect texi2html to not be found most of the time.
Tue Dec 5 08:08:08 1995 steve chamberlain <sac@slash.cygnus.com>
Release-B10
* cygwin.dll (__assert, wait, spawnv, spawnvp): Deleted.
* dcrt0.c: Quoting rewritten.
* exec.cc (file_exists): Use new path_conv mechanism.
(_execve): Close open child process handles.
* fhandler.cc (fhandler_normal::open): Follow symlinks.
(fhandler_normal::read): Keep track of logical file posision.
(fhandler_normal::lseek): Seek in text files correctly.
(fhandler_normal::fstat): Set IFLNK bit if its a symlink.
(fhandler_normal::init): Maintain is_pipe.
(fhandler_dev_null::fstat): New.
(fhandler_dev_null::get_handle): Return INVALID_HANDLE.
* fork.cc: Use new event mechanism.
* libccrt0.cc: Keep track of _fmode variable.
* misc.c (readlink): Delete.
* path.cc (__path_to_real_path_1): Allow /d<letter> mechanism.
(path_to_real_path_keep_rel): New
(link_cookie:*): Support for symbolic links.
* spawn.cc (spawn_guts): Quoting rewritten.
* times.cc: New.
* syscalls.cc (_stat_worker): New.
(_stat, _lstat): Use _stat_worker.
* sysconf.cc (sysconf): Support _SC_CLK_TCK.
Tue Nov 28 15:29:38 1995 steve chamberlain <sac@slash.cygnus.com>
* loads of stuff. When I make < 100k of diffs in a day,
the ChangeLog will be usefull.
Tue Nov 21 18:01:39 1995 steve chamberlain <sac@slash.cygnus.com>
* Makefile.in: Build the doc.
* exceptions.cc: lint.
* fork.cc: lint.
* shared.cc (shared_init): If MapViewOfFileEx fails, then try
again, but get the OS to select the address (for win95)
* strace.cc (__sysprintf): Print pid and state in hex.
* syscalls.cc (_unlink): Translate path to realpath.
Wed Nov 15 23:47:43 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* spawn.cc (_exit): set return value's lower byte to 0 by default.
Tue Oct 3 10:23:14 1995 Anders Blomdell (anders.blomdell@control.lth.se)
* spawn.cc (spawn_guts): quote doublequotes correctly
Tue Nov 14 15:05:33 1995 Jason Molenda (crash@phydeaux.cygnus.com)
* configure.in: comment out call to cfg-ml-com.in.
Tue Oct 31 11:19:18 1995 steve chamberlain <sac@slash.cygnus.com>
* libcerr.cc: New file.
* dcrt0.cc (environ_init): Initialize PATH and friends nicely.
* exceptions.cc (ctrl_c_handler): Default case is to exit.
* fork.cc (__suffixy, find_exec): translate between paths and
real_paths.
* shared.cc (shared_init): Hard wire shared memory at 0xa0000000.
* syscalls.c (__path_to_real_path, real_path_to_path): Always
translate '/' <> '\'
Mon Oct 30 17:36:10 1995 steve chamberlain <sac@slash.cygnus.com>
* syscalls.cc (_rename): Fix for win95.
Fri Oct 27 20:53:47 1995 steve chamberlain <sac@slash.cygnus.com>
* Everything changed.
Thu Oct 19 10:47:52 1995 steve chamberlain <sac@slash.cygnus.com>
* registry.cc, uinfo.cc: New files.
* crt0.c (*uinfo*, *_exe_suffix*): Delete.
(dll_crt0): Call shared_init.
* getlogin.c: deleted.
* shared.cc: Fill in.
* spawn.c (_spawn): Use __exe_suffix function.
* syscalls.c (getuid, getgid): Moved into uinfo.cc
* syscalls.h (*uinfo, __exe_suffix): Deleted
* Makefile.in: Cope with target configury.
* termios.c: Fix stub prototypes.
* win.h: Deleted.
* include/winadvapi.h: Fill in some REG prototypes.
Thu Oct 19 10:47:52 1995 steve chamberlain <sac@slash.cygnus.com>
* Makefile.in: Cope with target configury.
Wed Oct 18 15:34:49 1995 steve chamberlain <sac@slash.cygnus.com>
* Moved from newlib.

2031
winsup/cygwin/ChangeLog-1996 Normal file

File diff suppressed because it is too large Load Diff

2800
winsup/cygwin/ChangeLog-1997 Normal file

File diff suppressed because it is too large Load Diff

4490
winsup/cygwin/ChangeLog-1998 Normal file

File diff suppressed because it is too large Load Diff

3552
winsup/cygwin/ChangeLog-1999 Normal file

File diff suppressed because it is too large Load Diff

341
winsup/cygwin/Makefile.in Normal file
View File

@ -0,0 +1,341 @@
# Makefile.in for Cygwin.
# Copyright 1995, 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
#
# This file is part of Cygwin.
#
# This software is a copyrighted work licensed under the terms of the
# Cygwin license. Please consult the file "CYGWIN_LICENSE" for
# details.
# This makefile requires GNU make.
CONFIG_DIR:=@srcdir@/config/@CONFIG_DIR@
SHELL:=@SHELL@
VPATH:=@srcdir@:$(CONFIG_DIR):@srcdir@/regexp
srcdir:=@srcdir@
objdir:=.
target_alias:=@target_alias@
build_alias:=@build_alias@
host_alias:=@host_alias@
prefix:=@prefix@
program_transform_name:=@program_transform_name@
exec_prefix:=@exec_prefix@
bindir:=@bindir@
libdir:=@libdir@
ifeq ($(target_alias),$(host_alias))
ifeq ($(build_alias),$(host_alias))
tooldir:=$(exec_prefix)
else
tooldir:=$(exec_prefix)/$(target_alias)
endif
else
tooldir:=$(exec_prefix)/$(target_alias)
endif
datadir:=@datadir@
infodir:=@infodir@
includedir:=@includedir@
INSTALL:=@INSTALL@
INSTALL_PROGRAM:=@INSTALL_PROGRAM@
#
# --enable options from configure
#
MT_SAFE = @MT_SAFE@
DEFS = @DEFS@
CC:=@CC@
# FIXME: Which is it, CC or CC_FOR_TARGET?
CC_FOR_TARGET:=$(CC)
CFLAGS:=@CFLAGS@
CXXFLAGS:=@CXXFLAGS@
# For linking mount, etc. crt0.o isn't accessable in a fresh build.
EXE_LDFLAGS:=@EXE_LDFLAGS@
AR:=@AR@
AR_FLAGS:=qv
RANLIB:=@RANLIB@
LD:=@LD@
DLLTOOL:=@DLLTOOL@
WINDRES:=@WINDRES@
AS:=@AS@
#
# Include common definitions for winsup directory
#
include $(srcdir)/../Makefile.common
INSTALL_DATA:=$(SHELL) $(updir1)/install-sh -c
COMPILE_CC+=-D__INSIDE_CYGWIN__
@SET_MAKE@
# Setup the testing framework, if you have one
EXPECT = `if [ -f $${rootme}/../../expect/expect$(EXEEXT) ] ; then \
echo $${rootme}/../../expect/expect$(EXEEXT) ; \
else echo expect ; fi`
RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
echo $${srcdir}/../dejagnu/runtest ; \
else echo runtest; fi`
RUNTESTFLAGS =
ifdef MT_SAFE
MT_SAFE_HEADERS:=thread.h
MT_SAFE_OBJECTS:=pthread.o thread.o
endif
# Parameters used in building the cygwin.dll.
# We build as new-cygwin.dll and rename at install time to overcome
# native rebuilding issues (we don't want the build tools to see a partially
# built cygwin.dll and attempt to use it instead of the old one).
DLL_NAME:=cygwin1.dll
LIB_NAME:=libcygwin.a
DEF_FILE:=cygwin.def
DLL_ENTRY:=@DLL_ENTRY@
LIBGMON_A:=libgmon.a
GMON_START:=gcrt0.o
# Some things want these from libc, but they have their own static
# data which apps can get to, which is a pain in the dll, so we
# include them directly into the library.
LIBCOS:=libccrt0.o libcmain.o getopt.o dll_entry.o dll_main.o
# Build all source files in the config directory
EXTRA_DLL_OFILES:=${addsuffix .o,${basename ${notdir ${wildcard $(CONFIG_DIR)/*.c}}}}
EXTRA_OFILES=$(bupdir1)/libiberty/random.o $(bupdir1)/libiberty/strsignal.o
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libadvapi32.a
DLL_OFILES:=assert.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o dll_init.o \
environ.o errno.o exceptions.o exec.o external.o fcntl.o fhandler.o \
fhandler_console.o fhandler_serial.o fhandler_termios.o fhandler_tty.o \
fhandler_windows.o fhandler_raw.o fhandler_floppy.o fhandler_tape.o fhandler_zero.o \
fork.o glob.o grp.o heap.o hinfo.o init.o ioctl.o localtime.o malloc.o \
mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o regexp.o regerror.o \
regsub.o registry.o resource.o scandir.o security.o select.o shared.o \
signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o sync.o \
syscalls.o sysconf.o syslog.o termios.o times.o tty.o uinfo.o uname.o \
wait.o window.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS)
GMON_OFILES:= gmon.o mcount.o profil.o
LD_STUFF=--dll $(DLL_OFILES) version.o winver.o $(DLL_IMPORTS) $(LIBM) $(LIBC) $(LIBGCC) -e $(DLL_ENTRY) --image-base=0x61000000
.PHONY: all force dll_ofiles install
.SUFFIXES:
.SUFFIXES: .c .cc .def .a .o
all: new-$(DLL_NAME) $(LIBGMON_A) $(LIB_NAME) cygrun.exe force
force:
install: all
$(INSTALL_DATA) new-$(DLL_NAME) $(bindir)/$(DLL_NAME) ; \
$(INSTALL_DATA) $(LIB_NAME) $(tooldir)/lib/$(LIB_NAME); \
cd $(srcdir); \
for sub in `find include -name '[a-z]*' -type d -print | sort`; do \
for i in $$sub/*.h ; do \
$(INSTALL_DATA) $$i $(tooldir)/$$sub/`basename $$i` ; \
done ; \
done
clean:
-rm -f *.o *.dll *.a *.exp junk *.base version.cc regexp/*.o winver_stamp
maintainer-clean realclean: clean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-rm -fr configure
# Rule to build libcygwin.a
$(LIB_NAME): $(DEF_FILE) $(LIBCOS)
$(DLLTOOL) --as=$(AS) --dllname $(DLL_NAME) --def $(DEF_FILE) --output-lib temp.a
$(AR) rcv temp.a $(LIBCOS)
mv temp.a $(LIB_NAME)
# Rule to make stub library used by "make check"
new-$(LIB_NAME): $(DEF_FILE) $(LIBCOS)
$(DLLTOOL) --as=$(AS) --dllname new-$(DLL_NAME) --def $(DEF_FILE) --output-lib temp.a
$(AR) rcv temp.a $(LIBCOS)
mv temp.a new-$(LIB_NAME)
# Rule to build cygwin.dll
new-$(DLL_NAME): $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
$(LD) -shared -o $@ -e $(DLL_ENTRY) cygwin.def $(DLL_OFILES) version.o \
winver.o $(DLL_IMPORTS) $(LIBM) $(LIBGCC) $(MALLOC_OBJ) $(LIBC) $(LIBGCC)
dll_ofiles: $(DLL_OFILES)
$(LIBGMON_A): $(GMON_OFILES) $(GMON_START)
$(AR) rcv $(LIBGMON_A) $(GMON_OFILES)
version.cc winver.o: winver_stamp
@ :
winver_stamp: mkvers.sh include/cygwin/version.h winver.rc $(DLL_OFILES)
@echo "Making version.o and winver.o";\
$(SHELL) ${word 1,$^} ${word 2,$^} ${word 3,$^} $(WINDRES); \
touch $@; \
$(COMPILE_CXX) -o version.o version.cc
cygrun.exe : $(srcdir)/cygrun.c $(DLL_IMPORTS) $(w32api_lib)/libuser32.a \
$(w32api_lib)/libshell32.a
$(CC) -o $@ $^
#
# These targets are for the dejagnu testsuites. The file site.exp
# contains global variables that all the testsuites will use.
# Set to $(target_alias)/ for cross.
target_subdir = @target_subdir@
site.exp: ./config.status Makefile
@echo "Making a new config file..."
-@rm -f ./tmp?
@touch site.exp
-@mv site.exp site.bak
@echo "## these variables are automatically generated by make ##" > ./tmp0
@echo "# Do not edit here. If you wish to override these values" >> ./tmp0
@echo "# add them to the last section" >> ./tmp0
@echo "set rootme \"`pwd`\"" >> ./tmp0
@echo "set srcdir \"`cd ${srcdir}; pwd`\"" >> ./tmp0
@echo "set host_triplet $(host_canonical)" >> ./tmp0
@echo "set build_triplet $(build_canonical)" >> ./tmp0
@echo "set target_triplet $(target)" >> ./tmp0
@echo "set target_alias $(target_alias)" >> ./tmp0
@echo "set CC \"$(CC)\"" >> ./tmp0
# CFLAGS is set even though it's empty to show we reserve the right to set it.
@echo "set CFLAGS \"\"" >> ./tmp0
echo "set tmpdir $(objdir)/testsuite" >> ./tmp0
@echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./tmp0
@echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0
@cat ./tmp0 > site.exp
@cat site.bak | sed \
-e '1,/^## All variables above are.*##/ d' >> site.exp
-@rm -f ./tmp?
testsuite/site.exp: site.exp
if [ -d testsuite ]; then \
true; \
else \
mkdir testsuite; \
fi
rm -rf testsuite/site.exp
cp site.exp testsuite/site.exp
# Note: we set the PATH so that we can pick up new-cygwin1.dll
check: testsuite/site.exp
-rootme=`pwd`; export rootme; \
srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
export TCL_LIBRARY ; fi ; \
PATH=$${rootme}:$${PATH} ;\
$(RUNTEST) --tool winsup $(RUNTESTFLAGS)
#
Makefile: cygwin.din
# .h file dependencies
# This may be overkill, but it's better than the previous situation.
# As files/dependencies are added and removed from Cygwin, please keep
# this list up to date.
WINSUP_H:=winsup.h fhandler.h path.h shared.h \
sigproc.h include/cygwin/version.h \
$(MT_SAFE_HEADERS)
winsup.h: config.h
assert.o: $(WINSUP_H)
dcrt0.o: $(WINSUP_H) include/exceptions.h include/glob.h dll_init.h autoload.h
debug.o: $(WINSUP_H) debug.h sync.h
delqueue.o: $(WINSUP_H)
dir.o: $(WINSUP_H)
dlfcn.o: $(WINSUP_H) dll_init.h
dll_entry.o: $(WINSUP_H) include/cygwin/cygwin_dll.h
dll_init.o: $(WINSUP_H) include/exceptions.h dll_init.h
dll_main.o:
environ.o: $(WINSUP_H)
errno.o: $(WINSUP_H)
exceptions.o: $(WINSUP_H) include/exceptions.h sync.h autoload.h
exec.o: $(WINSUP_H)
external.o: $(WINSUP_H) external.h
fcntl.o: $(WINSUP_H)
fhandler.o: $(WINSUP_H)
fhandler_console.o: $(WINSUP_H)
fhandler_serial.o: $(WINSUP_H)
fhandler_termios.o: $(WINSUP_H)
fhandler_tty.o: $(WINSUP_H)
fhandler_windows.o: $(WINSUP_H)
fhandler_raw.o: $(WINSUP_H)
fhandler_floppy.o: $(WINSUP_H)
fhandler_tape.o: $(WINSUP_H)
fhandler_zero.o: $(WINSUP_H)
fork.o: $(WINSUP_H) dll_init.h
glob.o: include/glob.h
gmon.o: profil.h gmon.h
grp.o: $(WINSUP_H)
heap.o: $(WINSUP_H)
hinfo.o: $(WINSUP_H)
init.o: $(WINSUP_H)
ioctl.o: $(WINSUP_H)
libccrt0.o: $(WINSUP_H)
libcmain.o: $(WINSUP_H)
localtime.o: tz_posixrules.h
malloc.o: $(WINSUP_H)
mcount.o: gmon.h
mmap.o: $(WINSUP_H)
net.o: $(WINSUP_H) autoload.h
ntea.o:
passwd.o: $(WINSUP_H)
path.o: $(WINSUP_H)
pinfo.o: $(WINSUP_H)
pipe.o: $(WINSUP_H)
profile.o: profil.h
pthread.o: $(WINSUP_H)
registry.o: $(WINSUP_H)
resource.o: $(WINSUP_H)
scandir.o:
security.o: $(WINSUP_H)
select.o: $(WINSUP_H) select.h
shared.o: $(WINSUP_H)
signal.o: $(WINSUP_H)
sigproc.o: $(WINSUP_H) sync.h
smallprint.o: $(WINSUP_H)
spawn.o: $(WINSUP_H)
strace.o: $(WINSUP_H)
strsep.o:
sync.o: $(WINSUP_H) sync.h
syscalls.o: $(WINSUP_H)
sysconf.o: $(WINSUP_H)
syslog.o: $(WINSUP_H)
termios.o: $(WINSUP_H)
test.o: $(WINSUP_H)
times.o: $(WINSUP_H)
tty.o: $(WINSUP_H)
uinfo.o: $(WINSUP_H)
uname.o: $(WINSUP_H)
wait.o: $(WINSUP_H)
window.o: $(WINSUP_H)
thread.o: $(WINSUP_H)

129
winsup/cygwin/ROADMAP Normal file
View File

@ -0,0 +1,129 @@
WINSUP ROADMAP
The purpose of this document is to give the briefest overview of how
the various parts of cygwin work together and where everything can be
found. The intended audience is people developing the cygwin dll
itself. Comments to dj@cygnus.com.
=== cygwin1.dll source files
- overhead
.h winsup autoload debug external shared sync
.cc assert dcrt0 debug external init ntea registry security
shared smallprint strace sync
.din cygwin
.rc winver
.sgml external shared
- processes
.h sigproc
.cc exec fork pinfo resource signal sigproc spawn wait
- signals
.cc exceptions window
- files and I/O
.h delqueue fhandler path select
.cc delqueue dir fhandler* hinfo path pipe select tty
.sgml hinfo path
- common unix functions
.h dll_init tz_posixrules
.cc dlfcn dll_init environ errno fcntl flog grp ioctl localtime
malloc passwd scandir strsep syscalls sysconf syslog termios
.c longjmp setjmp
.sgml dll_init
- unix emulation
.cc heap mmap net times unifo uname
--- if MT_SAFE
.h thread
.cc pthread thread
--- from other places
regex/*
../libiberty/{random,strsignal}
../newlib/* (libc)
=== libcygwin.a source files
libccrt0.cc
libcmain.cc
dll_entry.cc
dll_main.cc
getopt.c
=== gmon (profiling, -pg)
gcrt0.c
gmon.c gmon.h
mcount.c
profil.c profil.h
=== entry points
- normal cygwin program
newlib/libc/sys/cygwin/crt0.c has mainCRTStartup() and calls cygwin_crt0()
libccrt0.cc has cygwin_crt0() and calls dll_crt0()
dcrt0.cc - has dll_crt0()
Note: dll_init.cc has nothing to do with initializing the cygwin dll.
It initializes the dlls you have dl_open'd.
- cygwin-built dll
dll_entry.cc - has a macro for wrapping your dll startup function
(equivalent of DllMain()) in such a way that you get your
cygwin environment set up automatically when your dll is
loaded.
dll_main.cc - has empty DllMain() in case you don't have your own
- manually loading cygwin1.dll
init.cc - has dll_entry() which is called by the OS when the dll is
loaded. It doesn't do much except note if you linked
cygwin1.dll or are manually loading it.
=== About "fhandlers"
An fhandler is a file type handler. This is where the unix device
emulation happens.
hinfo.cc maps posix file descriptors to a table of file handlers (type
fhandler) in the dll. It's mostly concerned with managing the table
of descriptors (open, dup, fork, select). Most of the posix I/O
system calls (syscalls.cc) use the hinfo table to call the right
fhandler directly.
fhandler.cc is the base class; specific types are derived as
appropriate (see fhandler.h). hinfo.cc is in charge of selecting and
creating a suitable fhandler when you open a file. path.cc handles
emulated files in /dev (like /dev/null) by returning an FH_* value
from get_device_number (which hinfo.cc calls in hinfo::build_fhandler).
Note: if you're looking for read() and write(), they call _read() and
_write() in syscalls.cc. The non-underscored ones are in
newlib/libc/syscalls and just call the underscored ones.
=== How "fork" works
It all starts in fork() in fork.cc.
Set up a pid in the shared memory area for the new child. Use
setjmp() to capture state. First time (parent), set up some stuff and
use CreateProcess to run a second copy of the same executable. The
second copy will note in the shared memory area that it's a fork, and
do the longjmp. They sync up and the parent copies all it's program
memory to the child's address space. There's also code to reload
dlls, map shared memory and mmap'd files, etc.
Handling the special startup for the child is done in dcrt0.cc in many
places. This case is triggered by a special StartupInfo structure
that's passed from the parent to the child in CreateProcessA.

15
winsup/cygwin/acconfig.h Normal file
View File

@ -0,0 +1,15 @@
/* Define if DEBUGGING support is requested. */
#undef DEBUGGING
/* Define if building "extra" thread-safe Cygwin DLL. */
#undef _CYG_THREAD_FAILSAFE
/* Define if GCC supports builtin memset. */
#undef HAVE_BUILTIN_MEMSET
/* Define if building thread-safe Cygwin DLL. */
#undef _MT_SAFE
/* Define if strace log output has date/time stamp. */
#undef STRACE_HHMMSS

59
winsup/cygwin/ansi.sgml Normal file
View File

@ -0,0 +1,59 @@
<sect1 id="std-ansi">
<title>Compatibility with ANSI</title>
<para>The following functions are compatible with ANSI:</para>
<sect2><title>stdio</title><para>
clearerr, fclose, feof, ferror, fflush, fgetc, fgetpos, fgets, fopen,
fprintf, fputc, fputs, fread, freopen, fscanf, fseek, fsetpos, ftell,
fwrite, getc, getchar, gets, perror, printf, putc, putchar, puts,
remove, rename, rewind, scanf, setbuf, setvbuf, sprintf, sscanf,
tmpfile, tmpnam, vfprintf, ungetc, vprintf, vsprintf,
</para></sect2>
<sect2><title>string</title><para>
memchr, memcmp, memcpy, memmove, memset, strcat, strchr, strcmp,
strcoll, strcpy, strcspn, strerror, strlen, strncat, strncmp, strncpy,
strpbrk, strrchr, strspn, strstr, strtok, strxfrm
</para></sect2>
<sect2><title>stdlib</title><para>
abort, abs, assert, atexit, atof, atoi, atol, bsearch, calloc, div,
exit, free, getenv, labs, ldiv, longjmp, malloc, mblen, mbstowcs,
mbtowc, qsort, rand, realloc, setjmp, srand, strtod, strtol, strtoul,
system, wcstombs, wctomb
</para></sect2>
<sect2><title>time</title><para>
asctime, gmtime, localtime, time, clock, ctime, difftime, mktime,
strftime
</para></sect2>
<sect2><title>signals</title><para>
raise, signal
</para></sect2>
<sect2><title>ctype</title><para>
isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint,
ispunct, isspace, isupper, isxdigit, tolower, toupper
</para></sect2>
<sect2><title>math</title><para>
acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh
</para></sect2>
<sect2><title>misc</title><para>
localeconv, setlocale, va_arg, va_end, va_start
</para></sect2>
</sect1>

50
winsup/cygwin/assert.cc Normal file
View File

@ -0,0 +1,50 @@
/* assert.cc: Handle the assert macro for WIN32.
Copyright 1997, 1998, 2000 Cygnus Solutions.
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 <assert.h>
#include <stdlib.h>
#include <stdio.h>
/* This function is called when the assert macro fails. This will
override the function of the same name in newlib. */
extern "C" void
__assert (const char *file, int line, const char *failedexpr)
{
HANDLE h;
/* If we don't have a console in a Windows program, then bring up a
message box for the assertion failure. */
h = CreateFileA ("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, &sec_none_nih,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE || h == 0)
{
char *buf;
buf = (char *) alloca (100 + strlen (failedexpr));
siprintf (buf, "Failed assertion\n\t%s\nat line %d of file %s",
failedexpr, line, file);
MessageBox (NULL, buf, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
}
else
{
CloseHandle (h);
(void) fiprintf (stderr,
"assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
}
abort ();
/* NOTREACHED */
}

38
winsup/cygwin/config.h.in Normal file
View File

@ -0,0 +1,38 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if DEBUGGING support is requested. */
#undef DEBUGGING
/* Define if building "extra" thread-safe Cygwin DLL. */
#undef _CYG_THREAD_FAILSAFE
/* Define if GCC supports builtin memset. */
#undef HAVE_BUILTIN_MEMSET
/* Define if building thread-safe Cygwin DLL. */
#undef _MT_SAFE
/* Define if strace log output has date/time stamp. */
#undef STRACE_HHMMSS

View File

@ -0,0 +1,51 @@
/* longjmp.c
Copyright 1996, 1998 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifdef __i386__
#if 1
asm (" .globl _longjmp \n"
"_longjmp: \n"
" pushl %ebp \n"
" movl %esp,%ebp \n"
" movl 8(%ebp),%edi \n"
" movl 12(%ebp),%eax \n"
" testl %eax,%eax \n"
" jne 0f \n"
" incl %eax \n"
"0: \n"
" movl %eax,0(%edi) \n"
" movl 24(%edi),%ebp \n"
" pushfl \n"
" popl %ebx \n"
" movw 42(%edi),%ax \n"
" movw %ax,%ss \n"
" movl 28(%edi),%esp \n"
" pushl 32(%edi) \n"
" pushl %ebx \n"
" movw 36(%edi),%ax \n"
" movw %ax,%es \n"
#if 0
/* fs is a system register in windows; don't muck with it */
" movw 38(%edi),%ax \n"
" movw %ax,%fs \n"
#endif
" movw 40(%edi),%ax \n"
" movw %ax,%gs \n"
" movl 0(%edi),%eax \n"
" movl 4(%edi),%ebx \n"
" movl 8(%edi),%ecx \n"
" movl 12(%edi),%edx \n"
" movl 16(%edi),%esi \n"
" movl 20(%edi),%edi \n"
" popfl \n"
" ret \n");
#endif
#endif /* __i386__ */

View File

@ -0,0 +1,17 @@
# makefrag: included by the main Cygwin Makefile.in
# Copyright 1996, 1998 Cygnus Solutions.
# 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.
EXTRA_DLL_OFILES=setjmp.o longjmp.o
setjmp.o:config/i386/setjmp.c
$(CC) -c $(ALL_CFLAGS) $<
longjmp.o:config/i386/longjmp.c
$(CC) -c $(ALL_CFLAGS) $<

View File

@ -0,0 +1,58 @@
/* $NetBSD: profile.h,v 1.6 1995/03/28 18:17:08 jtc Exp $ */
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)profile.h 8.1 (Berkeley) 6/11/93
*/
#define _MCOUNT_DECL static inline void _mcount
#define MCOUNT \
void \
mcount() \
{ \
int selfpc, frompcindex; \
/* \
* find the return address for mcount, \
* and the return address for mcount's caller. \
* \
* selfpc = pc pushed by mcount call \
*/ \
__asm("movl 4(%%ebp),%0" : "=r" (selfpc)); \
/* \
* frompcindex = pc pushed by call into self. \
*/ \
__asm("movl (%%ebp),%0;movl 4(%0),%0" : "=r" (frompcindex)); \
_mcount(frompcindex, selfpc); \
}

View File

@ -0,0 +1,48 @@
/* setjmp.c
Copyright 1996, 1998 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifdef __i386__
#if 1
asm(" .globl _setjmp \n"
"_setjmp: \n"
" pushl %ebp \n"
" movl %esp,%ebp \n"
" pushl %edi \n"
" movl 8(%ebp),%edi \n"
" movl %eax,0(%edi) \n"
" movl %ebx,4(%edi) \n"
" movl %ecx,8(%edi) \n"
" movl %edx,12(%edi) \n"
" movl %esi,16(%edi) \n"
" movl -4(%ebp),%eax \n"
" movl %eax,20(%edi) \n"
" movl 0(%ebp),%eax \n"
" movl %eax,24(%edi) \n"
" movl %esp,%eax \n"
" addl $12,%eax \n"
" movl %eax,28(%edi) \n"
" movl 4(%ebp),%eax \n"
" movl %eax,32(%edi) \n"
" movw %es, %ax \n"
" movw %ax, 36(%edi) \n"
" movw %fs, %ax \n"
" movw %ax, 38(%edi) \n"
" movw %gs, %ax \n"
" movw %ax, 40(%edi) \n"
" movw %ss, %ax \n"
" movw %ax, 42(%edi) \n"
" popl %edi \n"
" movl $0,%eax \n"
" leave \n"
" ret \n");
#endif
#endif /* __i386__ */

2335
winsup/cygwin/configure vendored Executable file

File diff suppressed because it is too large Load Diff

229
winsup/cygwin/configure.in Normal file
View File

@ -0,0 +1,229 @@
dnl Autoconf configure script for Cygwin.
dnl Copyright 1996, 1997, 1998, 2000 Cygnus Solutions.
dnl
dnl This file is part of Cygwin.
dnl
dnl This software is a copyrighted work licensed under the terms of the
dnl Cygwin license. Please consult the file "CYGWIN_LICENSE" for
dnl details.
dnl
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.12)dnl
AC_INIT(init.cc)
AC_CONFIG_HEADER(config.h)
AC_PROG_INSTALL
dnl FIXME: We temporarily define our own version of AC_PROG_CC. This is
dnl copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
dnl are probably using a cross compiler, which will not be able to fully
dnl link an executable. This should really be fixed in autoconf
dnl itself.
AC_DEFUN(LIB_AC_PROG_CC,
[AC_BEFORE([$0], [AC_PROG_CPP])dnl
AC_CHECK_TOOL(CC, gcc, gcc)
if test -z "$CC"; then
AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
fi
AC_PROG_CC_GNU
if test $ac_cv_prog_gcc = yes; then
GCC=yes
dnl Check whether -g works, even if CFLAGS is set, in case the package
dnl plays around with CFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
AC_PROG_CC_G
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
if test "$ac_test_CXXFLAGS" != set; then
CXXFLAGS='$(CFLAGS)'
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
])
AC_CANONICAL_SYSTEM
LIB_AC_PROG_CC
AC_CHECK_TOOL(AR, ar, ar)
AC_SUBST(AR)
AC_CHECK_TOOL(AS, as, as)
AC_SUBST(AS)
AC_CHECK_TOOL(RANLIB, ranlib, ranlib)
AC_SUBST(RANLIB)
AC_CHECK_TOOL(LD, ld, ld)
AC_SUBST(LD)
AC_CHECK_TOOL(DLLTOOL, dlltool, dlltool)
AC_SUBST(DLLTOOL)
AC_CHECK_TOOL(WINDRES, windres, windres)
AC_SUBST(WINDRES)
AC_ALLOCA
AC_CONFIG_SUBDIRS(utils doc)
AC_PROG_MAKE_SET
dnl check whether gcc supports __builtin_memset.
# Test for builtin mem* functions.
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([
#include <string.h>
void foo(char *s, int c, size_t n)
{
__builtin_memset(s, c, n);
}
], [ ],
use_builtin_memset=yes, use_builtin_memset=no)
if test $use_builtin_memset = "yes"; then
AC_DEFINE(HAVE_BUILTIN_MEMSET)
fi
AC_LANG_RESTORE
AC_ARG_ENABLE(strace-hhmmss,
[ --enable-strace-hhmmss strace log output has date/time stamp],
[case "${enableval}" in
yes)
AC_DEFINE(STRACE_HHMMSS)
;;
no)
;;
*)
AC_MSG_ERROR(bad value ${enableval} given for enable-strace-hhmmss option)
;;
esac
])
dnl set default mt safeness and then process the options.
mt_safe_val=1
MT_SAFE=yes
PTH_ALLOW=''
AC_ARG_ENABLE(threadsafe,
[ --enable-threadsafe=[runtime] Build a cygwin DLL which is thread safe],
[case "${enableval}" in
yes)
dnl default.
;;
runtime)
mt_safe_val=2
MT_SAFE=yes
;;
no)
mt_safe_val=0
MT_SAFE=no
PTH_ALLOW=';'
;;
esac
])
AC_ARG_ENABLE(extra-threadsafe-checking,
[ --enable-extra-threadsafe-checking Build a cygwin DLL which is thread safe with extra consistency checking],
[case "${enableval}" in
yes)
mt_safe_val=1
MT_SAFE=yes
AC_DEFINE(_CYG_THREAD_FAILSAFE)
;;
no)
dnl Don't do anything here to avoid overriding --enable-threadsafe.
;;
esac
])
if test "$MT_SAFE" = "yes"; then
AC_DEFINE_UNQUOTED(_MT_SAFE,$mt_safe_val)
fi
dnl Makefile uses MT_SAFE, so we subst as well as defining it.
AC_SUBST(MT_SAFE)
AC_SUBST(PTH_ALLOW)
AC_ARG_ENABLE(debugging,
[ --enable-debugging Build a cygwin DLL which has more consistency checking for debugging],
[case "${enableval}" in
yes) AC_DEFINE(DEBUGGING) ;;
no) ;;
esac
])
dnl The only time we might want to transform the install names
dnl is for unix x cygwin. Otherwise we don't. For now we don't
dnl transform names.
dnl if test "x$cross_compiling" = "xno" -a ; then
dnl if test "x$program_transform_name" = "xs,x,x,"; then
dnl program_transform_name=""
dnl fi
dnl if test "x$program_transform_name" = "x"; then
dnl program_transform_name="s,^,$target_alias-,"
dnl else
dnl program_transform_name="$program_transform_name -e s,^,$target_alias-,"
dnl fi
dnl fi
dnl
dnl If newlib is part of build tree, always set EXE_LDFLAGS to point to
dnl it; this is important in cases where the installed newlib is perhaps
dnl not compatible. Check and warn for installed newlib only if it's not
dnl part of the build tree.
dnl
AC_MSG_CHECKING([if newlib is part of the build tree])
EXE_LDFLAGS=
if test -d ../newlib
then
AC_MSG_RESULT(yes)
EXE_LDFLAGS="-B../../newlib/ -B../"
else
AC_MSG_RESULT(no)
fi
AC_SUBST(EXE_LDFLAGS)
if test x"$EXE_LDFLAGS" = x
then
AC_MSG_CHECKING([if installed newlib needed])
AC_TRY_LINK(,
[/* main already defined */]
,
AC_MSG_RESULT(no)
,
AC_MSG_RESULT(yes)
AC_MSG_WARN(newlib not found - utility .exe's may not link))
fi
AC_SUBST(EXE_LDFLAGS)
case "$target_cpu" in
i386|i486|i586|i686) DLL_ENTRY="_dll_entry@12"
DEF_DLL_ENTRY="dll_entry@12"
ALLOCA="_alloca"
CONFIG_DIR="i386" ;;
powerpc*) DLL_ENTRY="dll_entry"
DEF_DLL_ENTRY="dll_entry"
ALLOCA=" __allocate_stack"
CONFIG_DIR="ppc" ;;
*) AC_MSG_ERROR(Invalid target processor \"$target_cpu\") ;;
esac
AC_SUBST(DLL_ENTRY)
AC_SUBST(DEF_DLL_ENTRY)
AC_SUBST(ALLOCA)
AC_SUBST(CONFIG_DIR)
AC_OUTPUT(Makefile cygwin.def:cygwin.din)

1051
winsup/cygwin/cygwin.din Normal file

File diff suppressed because it is too large Load Diff

1063
winsup/cygwin/dcrt0.cc Normal file

File diff suppressed because it is too large Load Diff

326
winsup/cygwin/debug.cc Normal file
View File

@ -0,0 +1,326 @@
/* debug.cc
Copyright 1998, 1999, 2000 Cygnus Solutions.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#define NO_DEBUG_DEFINES
#include "winsup.h"
#include "exceptions.h"
static muto NO_COPY *threadname_lock = NULL;
#define lock_threadname() \
do {if (threadname_lock) threadname_lock->acquire (INFINITE); } while (0)
#define unlock_threadname() \
do {if (threadname_lock) threadname_lock->release (); } while (0)
typedef struct
{
DWORD id;
const char *name;
} thread_info;
static NO_COPY thread_info threads[32] = {{0}}; // increase as necessary
#define NTHREADS (sizeof(threads) / sizeof(threads[0]))
void
threadname_init ()
{
threadname_lock = new_muto (FALSE, NULL);
}
void __stdcall
regthread (const char *name, DWORD tid)
{
lock_threadname ();
for (DWORD i = 0; i < NTHREADS; i++)
if (threads[i].name == NULL || strcmp (threads[i].name, name) == 0 ||
threads[i].id == tid)
{
threads[i].name = name;
threads[i].id = tid;
break;
}
unlock_threadname ();
}
struct thread_start
{
LONG notavail;
LPTHREAD_START_ROUTINE func;
VOID *arg;
};
/* A place to store arguments to thread_stub since they can't be
stored on the stack. An available element is !notavail. */
thread_start NO_COPY start_buf[NTHREADS] = {{0, NULL,NULL}};
/* Initial stub called by makethread. Performs initial per-thread
initialization. */
static DWORD WINAPI
thread_stub (VOID *arg)
{
LPTHREAD_START_ROUTINE threadfunc = ((thread_start *) arg)->func;
VOID *threadarg = ((thread_start *) arg)->arg;
exception_list except_entry;
/* Give up our slot in the start_buf array */
InterlockedExchange (&((thread_start *) arg)->notavail, 0);
#ifdef _MT_SAFE
/* marco@ddi.nl: Needed for the reent's of this local dll thread
I assume that the local threads are using the reent structure of
the main thread
*/
if ( !TlsSetValue(user_data->threadinterface->reent_index,
&user_data->threadinterface->reents) )
api_fatal(" Sig proc MT init failed\n");
#endif
/* Initialize this threads ability to respond to things like
SIGSEGV or SIGFPE. */
init_exceptions (&except_entry);
return threadfunc (threadarg);
}
/* Wrapper for CreateThread. Registers the thread name/id and ensures that
cygwin threads are properly initialized. */
HANDLE __stdcall
makethread (LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags,
const char *name)
{
DWORD tid;
HANDLE h;
SECURITY_ATTRIBUTES *sa;
thread_start *info; /* Various information needed by the newly created thread */
for (;;)
{
/* Search the start_buf array for an empty slot to use */
for (info = start_buf; info < start_buf + NTHREADS; info++)
if (!InterlockedExchange (&info->notavail, 1))
goto out;
/* Should never hit here, but be defensive anyway. */
Sleep (0);
}
out:
info->func = start; /* Real function to start */
info->arg = param; /* The single parameter to the thread */
if (*name != '+')
sa = &sec_none_nih; /* The handle should not be inherited by subprocesses. */
else
{
name++;
sa = &sec_none; /* The handle should be inherited by subprocesses. */
}
if ((h = CreateThread (sa, 0, thread_stub, (VOID *) info, flags, &tid)))
regthread (name, tid); /* Register this name/thread id for debugging output. */
return h;
}
/* Return the symbolic name of the current thread for debugging.
*/
const char * __stdcall
threadname (DWORD tid, int lockit)
{
const char *res = NULL;
if (!tid)
tid = GetCurrentThreadId ();
if (lockit)
lock_threadname ();
for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++)
if (threads[i].id == tid)
{
res = threads[i].name;
break;
}
if (lockit)
unlock_threadname ();
if (!res)
{
static char buf[30] NO_COPY = {0};
__small_sprintf (buf, "unknown (%p)", tid);
res = buf;
}
return res;
}
#ifdef DEBUGGING
/* Here lies extra debugging routines which help track down internal
Cygwin problems when compiled with -DDEBUGGING . */
#include <stdlib.h>
typedef struct _h
{
BOOL allocated;
HANDLE h;
const char *name;
const char *func;
int ln;
struct _h *next;
} handle_list;
static NO_COPY handle_list starth = {0};
static NO_COPY handle_list *endh = NULL;
static handle_list NO_COPY freeh[1000] = {{0}};
#define NFREEH (sizeof (freeh) / sizeof (freeh[0]))
static muto NO_COPY *debug_lock = NULL;
#define lock_debug() \
do {if (debug_lock) debug_lock->acquire (INFINITE); } while (0)
#define unlock_debug() \
do {if (debug_lock) debug_lock->release (); } while (0)
void
debug_init ()
{
debug_lock = new_muto (FALSE, NULL);
}
/* Find a registered handle in the linked list of handles. */
static handle_list * __stdcall
find_handle (HANDLE h)
{
handle_list *hl;
for (hl = &starth; hl->next != NULL; hl = hl->next)
if (hl->next->h == h)
goto out;
endh = hl;
hl = NULL;
out:
return hl;
}
/* Create a new handle record */
static handle_list * __stdcall
newh ()
{
handle_list *hl;
lock_debug ();
for (hl = freeh; hl < freeh + NFREEH; hl++)
if (hl->name == NULL)
goto out;
/* All used up??? */
if ((hl = (handle_list *)malloc (sizeof *hl)) != NULL)
{
memset (hl, 0, sizeof (*hl));
hl->allocated = TRUE;
}
out:
unlock_debug ();
return hl;
}
/* Add a handle to the linked list of known handles. */
void __stdcall
add_handle (const char *func, int ln, HANDLE h, const char *name)
{
handle_list *hl;
lock_debug ();
if (find_handle (h))
goto out; /* Already did this once */
if ((hl = newh()) == NULL)
{
unlock_debug ();
system_printf ("couldn't allocate memory for %s(%d): %s(%p)",
func, ln, name, h);
return;
}
hl->h = h;
hl->name = name;
hl->func = func;
hl->ln = ln;
hl->next = NULL;
endh->next = hl;
endh = hl;
out:
unlock_debug ();
}
/* Close a known handle. Complain if !force and closing a known handle or
if the name of the handle being closed does not match the registered name. */
BOOL __stdcall
close_handle (const char *func, int ln, HANDLE h, const char *name, BOOL force)
{
BOOL ret;
handle_list *hl;
lock_debug ();
if ((hl = find_handle (h)) && !force)
{
hl = hl->next;
unlock_debug (); // race here
system_printf ("attempt to close protected handle %s:%d(%s<%p>)",
hl->func, hl->ln, hl->name, hl->h);
system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
return FALSE;
}
handle_list *hln;
if (hl && (hln = hl->next) && strcmp (name, hln->name))
{
system_printf ("closing protected handle %s:%d(%s<%p>)",
hln->func, hln->ln, hln->name, hln->h);
system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
}
ret = CloseHandle (h);
if (hl)
{
handle_list *hnuke = hl->next;
hl->next = hl->next->next;
if (hnuke->allocated)
free (hnuke);
else
memset (hnuke, 0, sizeof (*hnuke));
}
unlock_debug ();
return ret;
}
#endif /*DEBUGGING*/
extern "C" {
/* Provide a stack frame when calling WaitFor* functions */
#undef WaitForSingleObject
DWORD __stdcall
WFSO (HANDLE hHandle, DWORD dwMilliseconds)
{
DWORD ret;
ret = WaitForSingleObject (hHandle, dwMilliseconds);
return ret;
}
#undef WaitForMultipleObjects
DWORD __stdcall
WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
{
DWORD ret;
ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds);
return ret;
}
}

69
winsup/cygwin/debug.h Normal file
View File

@ -0,0 +1,69 @@
/* debug.h
Copyright 1998, 1999, 2000 Cygnus Solutions.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef MALLOC_DEBUG
#define MALLOC_CHECK do {} while (0)
#else
#define MALLOC_CHECK ({\
debug_printf ("checking malloc pool");\
(void)mallinfo ();\
})
#endif
extern "C" {
DWORD __stdcall WFSO (HANDLE, DWORD);
DWORD __stdcall WFMO (DWORD, CONST HANDLE *, BOOL, DWORD);
}
#define WaitForSingleObject WFSO
#define WaitForMultipleObject WFMO
#if !defined(_DEBUG_H_)
#define _DEBUG_H_
void threadname_init ();
HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *);
const char * __stdcall threadname (DWORD, int lockit = TRUE);
void __stdcall regthread (const char *, DWORD);
#ifndef DEBUGGING
# define ForceCloseHandle CloseHandle
# define ForceCloseHandle1(h, n) CloseHandle (h)
# define ForceCloseHandle2(h, n) CloseHandle (h)
# define ProtectHandle(h) do {} while (0)
# define ProtectHandle1(h,n) do {} while (0)
# define ProtectHandle2(h,n) do {} while (0)
# define debug_init() do {} while (0)
#else
# ifdef NO_DEBUG_DEFINES
# undef NO_DEBUG_DEFINES
# else
# define CloseHandle(h) \
close_handle (__PRETTY_FUNCTION__, __LINE__, (h), #h, FALSE)
# define ForceCloseHandle(h) \
close_handle (__PRETTY_FUNCTION__, __LINE__, (h), #h, TRUE)
# define ForceCloseHandle1(h,n) \
close_handle (__PRETTY_FUNCTION__, __LINE__, (h), #n, TRUE)
# define ForceCloseHandle2(h,n) \
close_handle (__PRETTY_FUNCTION__, __LINE__, (h), n, TRUE)
# define lock_pinfo_for_update(n) lpfu(__PRETTY_FUNCTION__, __LINE__, n)
# endif
# define ProtectHandle(h) add_handle (__PRETTY_FUNCTION__, __LINE__, (h), #h)
# define ProtectHandle1(h,n) add_handle (__PRETTY_FUNCTION__, __LINE__, (h), #n)
# define ProtectHandle2(h,n) add_handle (__PRETTY_FUNCTION__, __LINE__, (h), n)
void debug_init ();
void __stdcall add_handle (const char *, int, HANDLE, const char *);
BOOL __stdcall close_handle (const char *, int, HANDLE, const char *, BOOL);
int __stdcall lpfu (const char *, int, DWORD timeout);
#endif /*DEBUGGING*/
#endif /*_DEBUG_H_*/

99
winsup/cygwin/delqueue.cc Normal file
View File

@ -0,0 +1,99 @@
/* delqueue.cc
Copyright 1996, 1998 Cygnus Solutions.
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"
/* FIXME: this delqueue module is very flawed and should be rewritten.
First, having an array of a fixed size for keeping track of the
unlinked but not yet deleted files is bad. Second, some programs
will unlink files and then create a new one in the same location
and this behavior is not supported in the current code. Probably
we should find a move/rename function that will work on open files,
and move delqueue files to some special location or some such
hack... */
void
delqueue_list::init ()
{
empty = 1;
memset(inuse, 0, MAX_DELQUEUES_PENDING);
}
void
delqueue_list::queue_file (const char *dosname)
{
char temp[MAX_PATH], *end;
GetFullPathName (dosname, sizeof (temp), temp, &end);
/* Note about race conditions: The only time we get to this point is
when a delete fails because someone's holding the descriptor open.
In those cases, other programs will be unable to delete the file
also, so any entries referring to that file will not be removed
from the queue while we're here. */
if (!empty)
{
/* check for duplicates */
for (int i=0; i < MAX_DELQUEUES_PENDING; i++)
if (inuse[i] && strcmp(name[i], temp) == 0)
return;
}
for (int i = 0; i < MAX_DELQUEUES_PENDING; i++)
if (!inuse[i])
{
/* set the name first, in case someone else is running the
queue they'll get a valid name */
strcpy(name[i], temp);
inuse[i] = 1;
empty = 0;
return;
}
system_printf ("Out of queue slots");
}
void
delqueue_list::process_queue ()
{
if (empty)
return;
/* We set empty to 1 here, rather than later, to avoid a race
condition - some other program might queue up a file while we're
processing, and it will zero out empty also. */
empty = 1; /* but might get set to zero again, below */
syscall_printf ("Running delqueue");
for (int i = 0; i < MAX_DELQUEUES_PENDING; i++)
if (inuse[i])
{
if (DeleteFileA (name[i]))
{
syscall_printf ("Deleted %s", name[i]);
inuse[i] = 0;
}
else
{
int res = GetLastError ();
empty = 0;
if (res == ERROR_SHARING_VIOLATION)
{
/* File still inuse, that's ok */
syscall_printf ("Still using %s", name[i]);
}
else
{
syscall_printf ("Hmm, don't know what to do with '%s', %E", name[i]);
inuse[i] = 0;
}
}
}
}

340
winsup/cygwin/dir.cc Normal file
View File

@ -0,0 +1,340 @@
/* dir.cc: Posix directory-related routines
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
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 <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include "winsup.h"
#define _COMPILING_NEWLIB
#include "dirent.h"
/* Cygwin internal */
/* Return whether the directory of a file is writable. Return 1 if it
is. Otherwise, return 0, and set errno appropriately. */
int __stdcall
writable_directory (const char *file)
{
char dir[strlen (file) + 1];
strcpy (dir, file);
const char *usedir;
char *slash = strrchr (dir, '\\');
if (slash == NULL)
usedir = ".";
else
{
*slash = '\0';
usedir = dir;
}
int acc = access (usedir, W_OK);
return acc == 0;
}
/* opendir: POSIX 5.1.2.1 */
extern "C" DIR *
opendir (const char *dirname)
{
int len;
DIR *dir;
DIR *res = 0;
struct stat statbuf;
path_conv real_dirname (dirname, SYMLINK_FOLLOW, 1);
if (real_dirname.error)
{
set_errno (real_dirname.error);
goto failed;
}
if (stat (real_dirname.get_win32 (), &statbuf) == -1)
goto failed;
if (!(statbuf.st_mode & S_IFDIR))
{
set_errno (ENOTDIR);
goto failed;
}
len = strlen (real_dirname.get_win32 ());
if (len > MAX_PATH - 3)
{
set_errno (ENAMETOOLONG);
goto failed;
}
if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
{
set_errno (ENOMEM);
goto failed;
}
if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL)
{
free (dir);
set_errno (ENOMEM);
goto failed;
}
if ((dir->__d_dirent =
(struct dirent *) malloc (sizeof (struct dirent))) == NULL)
{
free (dir->__d_dirname);
free (dir);
set_errno (ENOMEM);
goto failed;
}
strcpy (dir->__d_dirname, real_dirname.get_win32 ());
/* 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 = statbuf.st_ino;
res = dir;
failed:
syscall_printf ("%p = opendir (%s)", res, dirname);
return res;
}
/* readdir: POSIX 5.1.2.1 */
extern "C" struct dirent *
readdir (DIR * dir)
{
WIN32_FIND_DATA buf;
HANDLE handle;
struct dirent *res = 0;
int prior_errno;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
}
if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE)
{
if (FindNextFileA (dir->__d_u.__d_data.__handle, &buf) == 0)
{
prior_errno = get_errno();
(void) FindClose (dir->__d_u.__d_data.__handle);
dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
__seterrno ();
/* POSIX says you shouldn't set errno when readdir can't
find any more files; if another error we leave it set. */
if (get_errno () == ENMFILE)
set_errno (prior_errno);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
}
}
else
{
handle = FindFirstFileA (dir->__d_dirname, &buf);
if (handle == INVALID_HANDLE_VALUE)
{
/* It's possible that someone else deleted or emptied the directory
or some such between the opendir () call and here. */
prior_errno = get_errno ();
__seterrno ();
/* POSIX says you shouldn't set errno when readdir can't
find any more files; if another error we leave it set. */
if (get_errno () == ENMFILE)
set_errno (prior_errno);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
}
dir->__d_u.__d_data.__handle = handle;
}
/* We get here if `buf' contains valid data. */
strcpy (dir->__d_dirent->d_name, buf.cFileName);
/* 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;
}
/* telldir */
extern "C" off_t
telldir (DIR * dir)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return 0;
return dir->__d_position;
}
/* seekdir */
extern "C" void
seekdir (DIR * dir, off_t loc)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
rewinddir (dir);
while (loc > dir->__d_position)
if (! readdir (dir))
break;
}
/* rewinddir: POSIX 5.1.2.1 */
extern "C" void
rewinddir (DIR * dir)
{
syscall_printf ("rewinddir (%p)", dir);
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
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;
}
}
/* closedir: POSIX 5.1.2.1 */
extern "C" int
closedir (DIR * dir)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("-1 = closedir (%p)", dir);
return -1;
}
if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE &&
FindClose (dir->__d_u.__d_data.__handle) == 0)
{
__seterrno ();
syscall_printf ("-1 = closedir (%p)", dir);
return -1;
}
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("0 = closedir (%p)", dir);
return 0;
}
/* mkdir: POSIX 5.4.1.1 */
extern "C" int
mkdir (const char *dir, mode_t mode)
{
int res = -1;
path_conv real_dir (dir, SYMLINK_NOFOLLOW);
if (real_dir.error)
{
set_errno (real_dir.error);
goto done;
}
nofinalslash(real_dir.get_win32 (), real_dir.get_win32 ());
if (! writable_directory (real_dir.get_win32 ()))
goto done;
if (CreateDirectoryA (real_dir.get_win32 (), 0))
{
set_file_attribute (real_dir.has_acls (), real_dir.get_win32 (),
(mode & 0777) & ~myself->umask);
res = 0;
}
else
__seterrno ();
done:
syscall_printf ("%d = mkdir (%s, %d)", res, dir, mode);
return res;
}
/* rmdir: POSIX 5.5.2.1 */
extern "C" int
rmdir (const char *dir)
{
int res = -1;
path_conv real_dir (dir, SYMLINK_NOFOLLOW);
if (real_dir.error)
{
set_errno (real_dir.error);
goto done;
}
if (RemoveDirectoryA (real_dir.get_win32 ()))
res = 0;
else if (os_being_run != winNT && GetLastError() == ERROR_ACCESS_DENIED)
{
/* Under Windows 95 & 98, ERROR_ACCESS_DENIED is returned
if you try to remove a file or a non-empty directory. */
if (GetFileAttributes (real_dir.get_win32()) != FILE_ATTRIBUTE_DIRECTORY)
set_errno (ENOTDIR);
else
set_errno (ENOTEMPTY);
}
else if (GetLastError () == ERROR_DIRECTORY)
set_errno (ENOTDIR);
else
__seterrno ();
done:
syscall_printf ("%d = rmdir (%s)", res, dir);
return res;
}

236
winsup/cygwin/dlfcn.cc Normal file
View File

@ -0,0 +1,236 @@
/* dlfcn.cc
Copyright 1998, 2000 Cygnus Solutions
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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "winsup.h"
#include <ctype.h>
#include "dlfcn.h"
#include "dll_init.h"
#ifdef _MT_SAFE
#define _dl_error _reent_winsup()->_dl_error
#define _dl_buffer _reent_winsup()->_dl_buffer
#else
static int _dl_error = 0;
static char _dl_buffer[256];
#endif
static void __stdcall
set_dl_error (const char *str)
{
__small_sprintf (_dl_buffer, "%s: %E", str);
_dl_error = 1;
}
//
// this function checks for existence of a file specified by the
// directory and name components. If successful, return a pointer
// the full pathname (static buffer), or else return 0.
//
static const char * __stdcall
check_access (const char *dir, const char *name)
{
static char buf[MAX_PATH];
const char *ret = 0;
buf[0] = 0;
strcpy (buf, dir);
strcat (buf, "\\");
strcat (buf, name);
if (!access (buf, F_OK))
ret = buf;
return ret;
}
//
// this function looks for an executable file given the name and the
// environment variable to use for searching (eg., PATH); returns
// the full pathname (static buffer) if found or NULL if not.
//
static const char * __stdcall
check_path_access (const char *mywinenv, const char *name)
{
static char buf[MAX_PATH];
return find_exec (name, buf, mywinenv, TRUE);
}
//
// This function simulates the same search as LoadLibary + check
// environment variable LD_LIBRARY_PATH. If found, return the full
// pathname (static buffer); if illegal, return the input string
// unchanged and let the caller deal with it; return NULL otherwise.
//
// Note that this should never be called with a NULL string, since
// that is the introspective case, and the caller should not call
// this function at all.
//
static const char * __stdcall
get_full_path_of_dll (const char* str)
{
int len = (str) ? strlen (str) : 0;
// NULL or empty string or too long to be legal win32 pathname?
if (len == 0 || len >= MAX_PATH - 1)
return str;
char buf[MAX_PATH];
static char name[MAX_PATH];
const char *ret = 0;
strcpy (name, str);
// add extension if necessary, but leave a trailing '.', if any, alone.
// Files with trailing '.'s are handled differently by win32 API.
if (str[len - 1] != '.')
{
// add .dll only if no extension provided. Handle various cases:
//
// ./shlib --> ./shlib.dll
// ./dir/shlib.so --> ./dir/shlib.so
// shlib --> shlib.dll
// shlib.dll --> shlib.dll
// shlib.so --> shlib.so
//
const char *p = strrchr (str, '.');
if (!p || isdirsep (p[1]))
strcat (name, ".dll");
}
// deal with fully qualified filename right away. Do the actual
// conversion to win32 filename just before returning however.
if (isabspath (str))
ret = name;
// current directory
if (!ret)
{
if (GetCurrentDirectory (MAX_PATH, buf) == 0)
small_printf ("WARNING: get_full_path_of_dll can't get current directory win32 %E\n");
else
ret = check_access (buf, name);
}
// LD_LIBRARY_PATH
if (!ret)
ret = check_path_access ("LD_LIBRARY_PATH=", name);
if (!ret)
{
// system directory
if (GetSystemDirectory (buf, MAX_PATH) == 0)
small_printf ("WARNING: get_full_path_of_dll can't get system directory win32 %E\n");
else
ret = check_access (buf, name);
}
// 16 bits system directory
if (!ret && (os_being_run == winNT))
{
// we assume last dir was xxxxx\SYSTEM32, so we remove 32
len = strlen (buf);
buf[len - 2] = 0;
ret = check_access (buf, name);
}
// windows directory
if (!ret)
{
if (GetWindowsDirectory (buf, MAX_PATH) == 0)
small_printf ("WARNING: get_full_path_of_dll can't get Windows directory win32 %E\n");
else
ret = check_access (buf, name);
}
// PATH
if (!ret)
ret = check_path_access ("PATH=", name);
//
// now do a final conversion to win32 pathname. This step is necessary
// to resolve symlinks etc so that win32 API finds the underlying file.
//
if (ret)
{
path_conv real_filename (ret, SYMLINK_FOLLOW, 1);
if (real_filename.error)
ret = 0;
else
{
strcpy (name, real_filename.get_win32 ());
ret = name;
}
}
return ret;
}
void *
dlopen (const char *name, int)
{
SetResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlopen");
void *ret = 0;
if (!name)
{
// handle for the current module
ret = (void *) GetModuleHandle (0);
}
else
{
// handle for the named library
const char *fullpath = get_full_path_of_dll (name);
DllList::the().currentDlOpenedLib (fullpath);
ret = (void *) LoadLibrary (fullpath);
}
if (!ret)
set_dl_error ("dlopen");
debug_printf ("ret %p", ret);
ReleaseResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlopen");
return ret;
}
void *
dlsym (void *handle, const char *name)
{
void *ret = (void *) GetProcAddress ((HMODULE) handle, name);
if (!ret)
set_dl_error ("dlsym");
debug_printf ("ret %p", ret);
return ret;
}
int
dlclose (void *handle)
{
SetResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlclose");
int ret = -1;
if (FreeLibrary ((HMODULE) handle))
ret = 0;
if (ret)
set_dl_error ("dlclose");
ReleaseResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlclose");
return ret;
}
char *
dlerror ()
{
char *ret = 0;
if (_dl_error)
ret = _dl_buffer;
return ret;
}

499
winsup/cygwin/dll_init.cc Normal file
View File

@ -0,0 +1,499 @@
/* dll_init.cc
Copyright 1998, 1999, 2000 Cygnus Solutions.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <stdlib.h>
#include "winsup.h"
#include "exceptions.h"
#include "dll_init.h"
extern void __stdcall check_sanity_and_sync (per_process *);
#ifdef _MT_SAFE
extern ResourceLocks _reslock NO_COPY;
extern MTinterface _mtinterf NO_COPY;
#endif /*_MT_SAFE*/
/* WARNING: debug can't be called before init !!!! */
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// the private structure
typedef enum { NONE, LINK, LOAD } dllType;
struct dll
{
per_process *p;
HMODULE handle;
const char *name;
dllType type;
};
//-----------------------------------------------------------------------------
#define MAX_DLL_BEFORE_INIT 100 // FIXME: enough ???
static dll _list_before_init[MAX_DLL_BEFORE_INIT];
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// local variables
static DllList _the;
static int _last = 0;
static int _max = MAX_DLL_BEFORE_INIT;
static dll *_list = _list_before_init;
static int _initCalled = 0;
static int _numberOfOpenedDlls = 0;
static int _forkeeMustReloadDlls = 0;
static int _in_forkee = 0;
static const char *_dlopenedLib = 0;
static int _dlopenIndex = -1;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
static int __dll_global_dtors_recorded = 0;
static void
__dll_global_dtors()
{
_the.doGlobalDestructorsOfDlls();
}
static void
doGlobalCTORS (per_process *p)
{
void (**pfunc)() = p->ctors;
/* Run ctors backwards, so skip the first entry and find how many
there are, then run them. */
if (pfunc)
{
int i;
for (i = 1; pfunc[i]; i++);
for (int j = i - 1; j > 0; j-- )
(pfunc[j]) ();
}
}
static void
doGlobalDTORS (per_process *p)
{
if (!p)
return;
void (**pfunc)() = p->dtors;
for (int i = 1; pfunc[i]; i++)
(pfunc[i]) ();
}
#define INC 500
static int
add (HMODULE h, char *name, per_process *p, dllType type)
{
int ret = -1;
if (p)
check_sanity_and_sync (p);
if (_last == _max)
{
if (!_initCalled) // we try to load more than MAX_DLL_BEFORE_INIT
{
small_printf ("try to load more dll than max allowed=%d\n",
MAX_DLL_BEFORE_INIT);
ExitProcess (1);
}
dll* newArray = new dll[_max+INC];
if (_list)
{
memcpy (newArray, _list, _max * sizeof (dll));
if (_list != _list_before_init)
delete []_list;
}
_list = newArray;
_max += INC;
}
_list[_last].name = name && type == LOAD ? strdup (name) : NULL;
_list[_last].handle = h;
_list[_last].p = p;
_list[_last].type = type;
ret = _last++;
return ret;
}
static int
initOneDll (per_process *p)
{
/* global variable user_data must be initialized */
if (user_data == NULL)
{
small_printf ("WARNING: process not inited while trying to init a DLL!\n");
return 0;
}
/* init impure_ptr */
*(p->impure_ptr_ptr) = *(user_data->impure_ptr_ptr);
/* FIXME: init environment (useful?) */
*(p->envptr) = *(user_data->envptr);
/* FIXME: need other initializations? */
int ret = 1;
if (!_in_forkee)
{
/* global contructors */
doGlobalCTORS (p);
/* entry point of dll (use main of per_process with null args...) */
if (p->main)
ret = (*(p->main)) (0, 0, 0);
}
return ret;
}
DllList&
DllList::the ()
{
return _the;
}
void
DllList::currentDlOpenedLib (const char *name)
{
if (_dlopenedLib != 0)
small_printf ("WARNING: previous dlopen of %s wasn't correctly performed\n", _dlopenedLib);
_dlopenedLib = name;
_dlopenIndex = -1;
}
int
DllList::recordDll (HMODULE h, per_process *p)
{
int ret = -1;
/* debug_printf ("Record a dll p=%p\n", p); see WARNING */
dllType type = LINK;
if (_initCalled)
{
type = LOAD;
_numberOfOpenedDlls++;
forkeeMustReloadDlls (1);
}
if (_in_forkee)
{
ret = 0; // Just a flag
goto out;
}
char buf[MAX_PATH];
GetModuleFileName (h, buf, MAX_PATH);
if (type == LOAD && _dlopenedLib !=0)
{
// it is not the current dlopened lib
// so we insert one empty lib to preserve place for current dlopened lib
if (!strcasematch (_dlopenedLib, buf))
{
if (_dlopenIndex == -1)
_dlopenIndex = add (0, 0, 0, NONE);
ret = add (h, buf, p, type);
}
else // it is the current dlopened lib
{
if (_dlopenIndex != -1)
{
_list[_dlopenIndex].handle = h;
_list[_dlopenIndex].p = p;
_list[_dlopenIndex].type = type;
ret = _dlopenIndex;
_dlopenIndex = -1;
}
else // it this case the dlopened lib doesn't need other lib
ret = add (h, buf, p, type);
_dlopenedLib = 0;
}
}
else
ret = add (h, buf, p, type);
out:
if (_initCalled) // main module is already initialized
{
if (!initOneDll (p))
ret = -1;
}
return ret;
}
void
DllList::detachDll (int dll_index)
{
if (dll_index != -1)
{
dll *aDll = &(_list[dll_index]);
doGlobalDTORS (aDll->p);
if (aDll->type == LOAD)
_numberOfOpenedDlls--;
aDll->type = NONE;
}
else
small_printf ("WARNING: try to detach an already detached dll ...\n");
}
void
DllList::initAll ()
{
// init for destructors
// because initAll isn't called in forked process, this exit function will
// be recorded only once
if (!__dll_global_dtors_recorded)
{
atexit (__dll_global_dtors);
__dll_global_dtors_recorded = 1;
}
if (!_initCalled)
{
debug_printf ("call to DllList::initAll");
for (int i = 0; i < _last; i++)
{
per_process *p = _list[i].p;
if (p)
initOneDll (p);
}
_initCalled = 1;
}
}
void
DllList::doGlobalDestructorsOfDlls ()
{
// global destructors in reverse order
for (int i = _last - 1; i >= 0; i--)
{
if (_list[i].type != NONE)
{
per_process *p = _list[i].p;
if (p)
doGlobalDTORS (p);
}
}
}
int
DllList::numberOfOpenedDlls ()
{
return _numberOfOpenedDlls;
}
int
DllList::forkeeMustReloadDlls ()
{
return _forkeeMustReloadDlls;
}
void
DllList::forkeeMustReloadDlls (int i)
{
_forkeeMustReloadDlls = i;
}
#define A64K (64 * 1024)
/* Mark every memory address up to "here" as reserved. This may force
Windows NT to load a DLL in the next available, lowest slot. */
void
reserve_upto (const char *name, DWORD here)
{
DWORD size;
MEMORY_BASIC_INFORMATION mb;
for (DWORD start = 0x10000; start < here; start += size)
if (!VirtualQuery ((void *) start, &mb, sizeof (mb)))
size = 64 * 1024;
else
{
size = A64K * ((mb.RegionSize + A64K - 1) / A64K);
start = A64K * (((DWORD) mb.BaseAddress + A64K - 1) / A64K);
if (start + size > here)
size = here - start;
if (mb.State == MEM_FREE &&
!VirtualAlloc ((void *) start, size, MEM_RESERVE, PAGE_NOACCESS))
api_fatal ("couldn't allocate memory %p(%d) for '%s' alignment, %E\n",
start, size, name);
}
}
/* Release all of the memory previously allocated by "upto" above.
Note that this may also free otherwise reserved memory. If that becomes
a problem, we'll have to keep track of the memory that we reserve above. */
void
release_upto (const char *name, DWORD here)
{
DWORD size;
MEMORY_BASIC_INFORMATION mb;
for (DWORD start = 0x10000; start < here; start += size)
if (!VirtualQuery ((void *) start, &mb, sizeof (mb)))
size = 64 * 1024;
else
{
size = mb.RegionSize;
if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS &&
((void *) start < user_data->heapbase || (void *) start > user_data->heaptop)))
continue;
if (!VirtualFree ((void *) start, 0, MEM_RELEASE))
api_fatal ("couldn't release memory %p(%d) for '%s' alignment, %E\n",
start, size, name);
}
}
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded DLLs
and attempts to load them in the same place as they were loaded in the parent. */
void
DllList::forkeeLoadDlls ()
{
_initCalled = 1;
_in_forkee = 1;
int try2 = 0;
for (int i = 0; i < _last; i++)
if (_list[i].type == LOAD)
{
const char *name = _list[i].name;
HMODULE handle = _list[i].handle;
HMODULE h = LoadLibraryEx (name, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (h == handle)
{
FreeLibrary (h);
LoadLibrary (name);
}
else if (try2)
api_fatal ("unable to remap %s to same address as parent -- %p", name, h);
else
{
FreeLibrary (h);
reserve_upto (name, (DWORD) handle);
try2 = 1;
i--;
continue;
}
if (try2)
{
release_upto (name, (DWORD) handle);
try2 = 0;
}
}
_in_forkee = 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// iterators
DllListIterator::DllListIterator (int type) : _type (type), _index (-1)
{
operator++ ();
}
DllListIterator::~DllListIterator ()
{
}
DllListIterator::operator per_process* ()
{
return _list[index ()].p;
}
void
DllListIterator::operator++ ()
{
_index++;
while (_index < _last && (int) (_list[_index].type) != _type)
_index++;
if (_index == _last)
_index = -1;
}
LinkedDllIterator::LinkedDllIterator () : DllListIterator ((int) LINK)
{
}
LinkedDllIterator::~LinkedDllIterator ()
{
}
LoadedDllIterator::LoadedDllIterator () : DllListIterator ((int) LOAD)
{
}
LoadedDllIterator::~LoadedDllIterator ()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// the extern symbols
extern "C"
{
/* This is an exported copy of environ which can be used by DLLs
which use cygwin.dll. */
extern struct _reent reent_data;
};
extern "C"
int
dll_dllcrt0 (HMODULE h, per_process *p)
{
/* Partially initialize Cygwin guts for non-cygwin apps. */
if (dynamically_loaded && (! user_data || user_data->magic_biscuit == 0))
{
dll_crt0 (p);
}
return _the.recordDll (h, p);
}
/* OBSOLETE: This function is obsolescent and will go away in the
future. Cygwin can now handle being loaded from a noncygwin app
using the same entry point. */
extern "C"
int
dll_noncygwin_dllcrt0 (HMODULE h, per_process *p)
{
return dll_dllcrt0 (h, p);
}
extern "C"
void
cygwin_detach_dll (int dll_index)
{
_the.detachDll (dll_index);
}
extern "C"
void
dlfork (int val)
{
_the.forkeeMustReloadDlls (val);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

102
winsup/cygwin/dll_init.h Normal file
View File

@ -0,0 +1,102 @@
/* dll_init.h
Copyright 1998 Cygnus Solutions
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. */
//-----------------------------------------------------------------------------
// list of loaded DLL (used by fork & init)
class DllList
{
public:
static DllList& the ();
// return dll index used for freeDll
int recordDll (HMODULE, per_process*);
void detachDll (int dll_index);
// called after initialization of main module in dll_crt0
void initAll ();
// global destructors of loaded dlls
void doGlobalDestructorsOfDlls ();
// number of dlls dlopened
int numberOfOpenedDlls ();
// boolean to determine if forked process must reload dlls opened with
// LoadLibrary or dlopen ...
// default = 0 (FALSE)
int forkeeMustReloadDlls ();
void forkeeMustReloadDlls (int);
void forkeeLoadDlls ();
// set name of current library opened with dlopen
void currentDlOpenedLib (const char*);
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class DllListIterator
{
int _type;
int _index;
protected:
DllListIterator (int type);
int index () const { return _index; }
public:
virtual ~DllListIterator();
int ok() { return _index!=-1; }
void operator++ ();
void operator++ (int) { operator++ (); }
operator per_process* ();
};
//-----------------------------------------------------------------------------
class LinkedDllIterator : public DllListIterator
{
public:
LinkedDllIterator ();
~LinkedDllIterator ();
};
//-----------------------------------------------------------------------------
class LoadedDllIterator : public DllListIterator
{
public:
LoadedDllIterator ();
~LoadedDllIterator ();
};
//-----------------------------------------------------------------------------
#define DO_LINKED_DLL(var) \
{ \
LinkedDllIterator iterator; \
while (iterator.ok ()) \
{ \
per_process *var = (per_process *) iterator;
#define DO_LOADED_DLL(var) \
{ \
LoadedDllIterator iterator; \
while (iterator.ok ()) \
{ \
per_process *var = (per_process *) iterator;
#define DLL_DONE \
iterator++; \
} \
}

View File

@ -0,0 +1,11 @@
<sect1 id="func-cygwin-detach-dll">
<title>cygwin_detach_dll</title>
<funcsynopsis>
<funcdef>extern "C" void
<function>cygwin_detach_dll</function></funcdef>
<paramdef>int <parameter>dll_index</parameter></paramdef>
</funcsynopsis>
</sect1>

603
winsup/cygwin/dtable.cc Normal file
View File

@ -0,0 +1,603 @@
/* hinfo.cc: file descriptor support.
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#define __INSIDE_CYGWIN_NET__
#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#define Win32_Winsock
#include "winsup.h"
hinfo dtable;
/* Set aside space for the table of fds */
void
dtable_init (void)
{
if (!dtable.size)
dtable.extend(NOFILE_INCR);
}
void __stdcall
set_std_handle (int fd)
{
if (fd == 0)
SetStdHandle (STD_INPUT_HANDLE, dtable[fd]->get_handle ());
else if (fd == 1)
SetStdHandle (STD_OUTPUT_HANDLE, dtable[fd]->get_output_handle ());
else if (fd == 2)
SetStdHandle (STD_ERROR_HANDLE, dtable[fd]->get_output_handle ());
}
int
hinfo::extend (int howmuch)
{
int new_size = size + howmuch;
fhandler_base **newfds;
if (howmuch <= 0)
return 0;
/* Try to allocate more space for fd table. We can't call realloc()
here to preserve old table if memory allocation fails */
debug_printf ("here size %d", size);
if (!(newfds = (fhandler_base **) calloc (new_size, sizeof newfds[0])))
{
debug_printf ("calloc failed");
return 0;
}
if (fds)
{
memcpy (newfds, fds, size * sizeof (fds[0]));
free (fds);
}
size = new_size;
fds = newfds;
debug_printf ("size %d, fds %d", size, fds);
return 1;
}
/* Initialize the file descriptor/handle mapping table.
We only initialize the parent table here. The child table is
initialized at each fork () call. */
void
hinfo_init (void)
{
/* Set these before trying to output anything from strace.
Also, always set them even if we're to pick up our parent's fds
in case they're missed. */
if (!parent_alive && NOTSTATE(myself, PID_CYGPARENT))
{
HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
dtable.init_std_file_from_handle (0, in, GENERIC_READ, "{stdin}");
/* STD_ERROR_HANDLE has been observed to be the same as
STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes
to pass data from child to parent). */
if (out == err)
{
/* Since this code is not invoked for forked tasks, we don't have
to worry about the close-on-exec flag here. */
if (!DuplicateHandle (hMainProc, out, hMainProc, &err, 0,
1, DUPLICATE_SAME_ACCESS))
{
/* If that fails, do this as a fall back. */
err = out;
system_printf ("couldn't make stderr distinct from stdout");
}
}
dtable.init_std_file_from_handle (1, out, GENERIC_WRITE, "{stdout}");
dtable.init_std_file_from_handle (2, err, GENERIC_WRITE, "{stderr}");
}
}
int
hinfo::not_open (int fd)
{
SetResourceLock(LOCK_FD_LIST,READ_LOCK," not_open");
int res = fd < 0 || fd >= (int)size || fds[fd] == NULL;
ReleaseResourceLock(LOCK_FD_LIST,READ_LOCK," not open");
return res;
}
int
hinfo::find_unused_handle (int start)
{
AssertResourceOwner(LOCK_FD_LIST,READ_LOCK);
do
{
for (int i = start; i < (int) size; i++)
if (not_open (i))
return i;
}
while (extend (NOFILE_INCR));
return -1;
}
void
hinfo::release (int fd)
{
if (!not_open (fd))
{
MALLOC_CHECK;
delete (fds[fd]);
MALLOC_CHECK;
fds[fd] = NULL;
}
}
void
hinfo::init_std_file_from_handle (int fd, HANDLE handle,
DWORD myaccess, const char *name)
{
int bin = __fmode;
/* Check to see if we're being redirected - if not then
we open then as consoles */
if (fd == 0 || fd == 1 || fd == 2)
{
first_fd_for_open = 0;
/* See if we can consoleify it - if it is a console,
don't open it in binary. That will screw up our crlfs*/
CONSOLE_SCREEN_BUFFER_INFO buf;
if (GetConsoleScreenBufferInfo (handle, &buf))
{
bin = 0;
if (ISSTATE (myself, PID_USETTY))
name = "/dev/tty";
else
name = "/dev/conout";
}
else if (FlushConsoleInputBuffer (handle))
{
bin = 0;
if (ISSTATE (myself, PID_USETTY))
name = "/dev/tty";
else
name = "/dev/conin";
}
}
build_fhandler (fd, name, handle)->init (handle, myaccess, bin);
set_std_handle (fd);
paranoid_printf ("fd %d, handle %p", fd, handle);
}
extern "C"
int
cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
DWORD myaccess)
{
if (fd == -1)
fd = dtable.find_unused_handle();
fhandler_base *res = dtable.build_fhandler (fd, name, handle);
res->init (handle, myaccess, bin);
return fd;
}
fhandler_base *
hinfo::build_fhandler (int fd, const char *name, HANDLE handle)
{
int unit;
DWORD devn;
if ((devn = get_device_number (name, unit)) == FH_BAD)
{
struct sockaddr sa;
int sal = sizeof (sa);
CONSOLE_SCREEN_BUFFER_INFO cinfo;
DCB dcb;
if (handle == NULL)
devn = FH_DISK;
else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &cinfo))
devn = FH_CONIN;
else if (GetConsoleScreenBufferInfo (handle, &cinfo))
devn= FH_CONOUT;
else if (wsock32_handle && getpeername ((SOCKET) handle, &sa, &sal))
devn = FH_SOCKET;
else if (GetFileType (handle) == FILE_TYPE_PIPE)
devn = FH_PIPE;
else if (GetCommState (handle, &dcb))
devn = FH_SERIAL;
else
devn = FH_DISK;
}
return build_fhandler (fd, devn, name, unit);
}
fhandler_base *
hinfo::build_fhandler (int fd, DWORD dev, const char *name, int unit)
{
fhandler_base *fh;
void *buf = calloc (1, sizeof (fhandler_union) + 100);
switch (dev & FH_DEVMASK)
{
case FH_TTYM:
fh = new (buf) fhandler_tty_master (name, unit);
break;
case FH_CONSOLE:
case FH_CONIN:
case FH_CONOUT:
fh = new (buf) fhandler_console (name);
break;
case FH_PTYM:
fh = new (buf) fhandler_pty_master (name);
break;
case FH_TTYS:
if (unit < 0)
fh = new (buf) fhandler_tty_slave (name);
else
fh = new (buf) fhandler_tty_slave (unit, name);
break;
case FH_WINDOWS:
fh = new (buf) fhandler_windows (name);
break;
case FH_SERIAL:
fh = new (buf) fhandler_serial (name, FH_SERIAL, unit);
break;
case FH_PIPE:
case FH_PIPER:
case FH_PIPEW:
fh = new (buf) fhandler_pipe (name);
break;
case FH_SOCKET:
fh = new (buf) fhandler_socket (name);
break;
case FH_DISK:
fh = new (buf) fhandler_disk_file (NULL);
break;
case FH_FLOPPY:
fh = new (buf) fhandler_dev_floppy (name, unit);
break;
case FH_TAPE:
fh = new (buf) fhandler_dev_tape (name, unit);
break;
case FH_NULL:
fh = new (buf) fhandler_dev_null (name);
break;
case FH_ZERO:
fh = new (buf) fhandler_dev_zero (name);
break;
default:
/* FIXME - this could recurse forever */
return build_fhandler (fd, name, NULL);
}
debug_printf ("%s - cb %d, fd %d, fh %p", fh->get_name () ?: "", fh->cb,
fd, fh);
return fd >= 0 ? (fds[fd] = fh) : fh;
}
fhandler_base *
hinfo::dup_worker (fhandler_base *oldfh)
{
fhandler_base *newfh = build_fhandler (-1, oldfh->get_device (), NULL);
*newfh = *oldfh;
newfh->set_io_handle (NULL);
if (oldfh->dup (newfh))
{
free (newfh);
newfh = NULL;
return NULL;
}
newfh->set_close_on_exec_flag (0);
MALLOC_CHECK;
return newfh;
}
int
hinfo::dup2 (int oldfd, int newfd)
{
int res = -1;
fhandler_base *newfh = NULL; // = NULL to avoid an incorrect warning
MALLOC_CHECK;
debug_printf ("dup2 (%d, %d)", oldfd, newfd);
if (not_open (oldfd))
{
syscall_printf("dup2: fd %d not open", oldfd);
set_errno (EBADF);
goto done;
}
if (newfd == oldfd)
{
res = 0;
goto done;
}
if ((newfh = dup_worker (fds[oldfd])) == NULL)
{
res = -1;
goto done;
}
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
if (!not_open (newfd))
_close (newfd);
fds[newfd] = newfh;
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
MALLOC_CHECK;
if ((res = newfd) <= 2)
set_std_handle (res);
MALLOC_CHECK;
done:
syscall_printf ("%d = dup2 (%d, %d)", res, oldfd, newfd);
return res;
}
select_record *
hinfo::select_read (int fd, select_record *s)
{
if (dtable.not_open (fd))
{
set_errno (EBADF);
return NULL;
}
fhandler_base *fh = dtable[fd];
s = fh->select_read (s);
s->fd = fd;
s->fh = fh;
s->saw_error = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
}
select_record *
hinfo::select_write (int fd, select_record *s)
{
if (dtable.not_open (fd))
{
set_errno (EBADF);
return NULL;
}
fhandler_base *fh = dtable[fd];
s = fh->select_write (s);
s->fd = fd;
s->fh = fh;
s->saw_error = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
}
select_record *
hinfo::select_except (int fd, select_record *s)
{
if (dtable.not_open (fd))
{
set_errno (EBADF);
return NULL;
}
fhandler_base *fh = dtable[fd];
s = fh->select_except (s);
s->fd = fd;
s->fh = fh;
s->saw_error = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
}
/*
* Function to take an existant hinfo array
* and linearize it into a memory buffer.
* If memory buffer is NULL, it returns the size
* of memory buffer needed to do the linearization.
* On error returns -1.
*/
int
hinfo::linearize_fd_array (unsigned char *in_buf, int buflen)
{
/* If buf == NULL, just precalculate length */
if (in_buf == NULL)
{
buflen = sizeof (size_t);
for (int i = 0, max_used_fd = -1; i < (int)size; i++)
if (!not_open (i) && !fds[i]->get_close_on_exec ())
{
buflen += i - (max_used_fd + 1);
buflen += fds[i]->cb + strlen (fds[i]->get_name ()) + 1
+ strlen (fds[i]->get_win32_name ()) + 1;
max_used_fd = i;
}
debug_printf ("needed buflen %d", buflen);
return buflen;
}
debug_printf ("in_buf = %x, buflen = %d", in_buf, buflen);
/*
* Now linearize each open fd (write a 0xff byte for a closed fd).
* Write the name of the open fd first (null terminated). This
* allows the de_linearizeing code to determine what kind of fhandler_xxx
* to create.
*/
size_t i;
int len, total_size;
total_size = sizeof (size_t);
if (total_size > buflen)
{
system_printf ("FATAL: linearize_fd_array exceeded buffer size");
return -1;
}
unsigned char *buf = in_buf;
buf += sizeof (size_t); /* skip over length which is added later */
for (i = 0, total_size = sizeof (size_t); total_size < buflen; i++)
{
if (not_open (i) || fds[i]->get_close_on_exec ())
{
debug_printf ("linearizing closed fd %d",i);
*buf = 0xff; /* place holder */
len = 1;
}
else
{
len = fds[i]->linearize (buf);
debug_printf ("fd %d, len %d, name %s, device %p", i, len, buf,
fds[i]->get_device ());
}
total_size += len;
buf += len;
}
i--;
memcpy (in_buf, &i, sizeof (size_t));
if (total_size != buflen)
system_printf ("out of sync %d != %d", total_size, buflen);
return total_size;
}
/*
* Function to take a linearized hinfo array in a memory buffer and
* re-create the original hinfo array.
*/
LPBYTE
hinfo::de_linearize_fd_array (LPBYTE buf)
{
int len;
size_t max_used_fd, inc_size;
debug_printf ("buf %x", buf);
/* First get the number of fd's - use this to set the dtablesize.
NB. This is the only place in the code this should be done !!
*/
memcpy ((char *) &max_used_fd, buf, sizeof (int));
buf += sizeof (size_t);
inc_size = NOFILE_INCR * ((max_used_fd + NOFILE_INCR - 1) / NOFILE_INCR) -
size;
debug_printf ("max_used_fd %d, inc size %d", max_used_fd, inc_size);
if (inc_size > 0 && !extend (inc_size))
{
system_printf ("out of memory");
return NULL;
}
for (size_t i = 0; i <= max_used_fd; i++)
{
/* 0xFF means closed */
if (*buf == 0xff)
{
fds[i] = NULL;
buf++;
debug_printf ("closed fd %d", i);
continue;
}
/* fd was open - de_linearize it */
/* Get the null-terminated name. It is followed by an image of
the actual fhandler_* structure. Use the status field from
this to build a new fhandler type. */
DWORD status;
LPBYTE obuf = buf;
char *win32;
win32 = strchr ((char *)obuf, '\0') + 1;
buf = (LPBYTE)strchr ((char *)win32, '\0') + 1;
memcpy ((char *)&status, buf + FHSTATOFF, sizeof(DWORD));
debug_printf ("fd %d, name %s, win32 name %s, status %p",
i, obuf, win32, status);
len = build_fhandler (i, status, (const char *) NULL)->
de_linearize ((char *) buf, (char *) obuf, win32);
set_std_handle (i);
buf += len;
debug_printf ("len %d", buf - obuf);
}
first_fd_for_open = 0;
return buf;
}
void
hinfo::fixup_after_fork (HANDLE parent)
{
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
for (size_t i = 0; i < size; i++)
if (!not_open (i))
{
fhandler_base *fh = fds[i];
if (fh->get_close_on_exec () || fh->get_need_fork_fixup ())
{
debug_printf ("fd %d(%s)", i, fh->get_name ());
fh->fixup_after_fork (parent);
}
}
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
}
int
hinfo::vfork_child_dup ()
{
fhandler_base **newtable;
newtable = (fhandler_base **) calloc (size, sizeof(fds[0]));
int res = 1;
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
for (size_t i = 0; i < size; i++)
if (not_open (i))
continue;
else if ((newtable[i] = dup_worker (fds[i])) == NULL)
{
res = 0;
set_errno (EBADF);
goto out;
}
fds_on_hold = fds;
fds = newtable;
out:
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
return 1;
}
void
hinfo::vfork_parent_restore ()
{
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
close_all_files ();
fhandler_base **deleteme = fds;
fds = fds_on_hold;
fds_on_hold = NULL;
free (deleteme);
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
return;
}

20
winsup/cygwin/dtable.sgml Normal file
View File

@ -0,0 +1,20 @@
<sect1 id="func-cygwin-attach-handle-to-fd">
<title>cygwin_attach_handle_to_fd</title>
<funcsynopsis>
<funcdef>extern "C" int
<function>cygwin_attach_handle_to_fd</function></funcdef>
<paramdef>char *<parameter>name</parameter></paramdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>HANDLE <parameter>handle</parameter></paramdef>
<paramdef>int <parameter>bin</parameter></paramdef>
<paramdef>int <parameter>access</parameter></paramdef>
</funcsynopsis>
<para>This function can be used to turn a Win32 "handle" into a
posix-style file handle. <parameter>fd</parameter> may be -1 to
make cygwin allocate a handle; the actual handle is returned
in all cases.</para>
</sect1>

567
winsup/cygwin/environ.cc Normal file
View File

@ -0,0 +1,567 @@
/* environ.cc: Cygwin-adopted functions from newlib to manipulate
process's environment.
Copyright 1997, 1998, 1999, 2000 Cygnus Solutions.
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 <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <fcntl.h>
#define environ (*user_data->envptr)
extern BOOL allow_glob;
extern BOOL allow_ntea;
extern BOOL strip_title_path;
extern DWORD chunksize;
extern BOOL oldstack;
BOOL threadsafe;
BOOL reset_com = TRUE;
static BOOL envcache = TRUE;
/* List of names which are converted from dos to unix
* on the way in and back again on the way out.
*
* PATH needs to be here because CreateProcess uses it and gdb uses
* CreateProcess. HOME is here because most shells use it and would be
* confused by Windows style path names.
*/
static int return_MAX_PATH (const char *) {return MAX_PATH;}
static win_env conv_envvars[] =
{
{"PATH=", 5, NULL, NULL, cygwin_win32_to_posix_path_list,
cygwin_posix_to_win32_path_list,
cygwin_win32_to_posix_path_list_buf_size,
cygwin_posix_to_win32_path_list_buf_size},
{"HOME=", 5, NULL, NULL, cygwin_conv_to_full_posix_path, cygwin_conv_to_full_win32_path,
return_MAX_PATH, return_MAX_PATH},
{"LD_LIBRARY_PATH=", 16, NULL, NULL, cygwin_conv_to_full_posix_path,
cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH},
{NULL}
};
void
win_env::add_cache (const char *in_posix, const char *in_native)
{
posix = (char *) realloc (posix, strlen (in_posix) + 1);
strcpy (posix, in_posix);
if (in_native)
{
native = (char *) realloc (native, namelen + 1 + strlen (in_native));
(void) strcpy (native, name);
(void) strcpy (native + namelen, in_native);
}
else
{
native = (char *) realloc (native, namelen + 1 + win32_len (in_posix));
(void) strcpy (native, name);
towin32 (in_posix, native + namelen);
}
debug_printf ("posix %s", posix);
debug_printf ("native %s", native);
}
/* Check for a "special" environment variable name. *env is the pointer
* to the beginning of the environment variable name. n is the length
* of the name including a mandatory '='. Returns a pointer to the
* appropriate conversion structure.
*/
win_env *
getwinenv (const char *env, const char *in_posix)
{
for (int i = 0; conv_envvars[i].name != NULL; i++)
if (strncasematch (env, conv_envvars[i].name, conv_envvars[i].namelen))
{
win_env *we = conv_envvars + i;
const char *val;
if (!environ || !(val = in_posix ?: getenv(we->name)))
debug_printf ("can't set native for %s since no environ yet",
we->name);
else if (!envcache || !we->posix || strcmp (val, we->posix))
we->add_cache (val);
return we;
}
return NULL;
}
/* Convert windows path specs to POSIX, if appropriate.
*/
static void __stdcall
posify (char **here, const char *value)
{
char *src = *here;
win_env *conv;
int len = strcspn (src, "=") + 1;
if (!(conv = getwinenv (src)))
return;
/* Turn all the items from c:<foo>;<bar> into their
mounted equivalents - if there is one. */
char *outenv = (char *) malloc (1 + len + conv->posix_len (value));
memcpy (outenv, src, len);
conv->toposix (value, outenv + len);
conv->add_cache (outenv + len, value);
debug_printf ("env var converted to %s", outenv);
*here = outenv;
free (src);
}
/*
* my_findenv --
* Returns pointer to value associated with name, if any, else NULL.
* Sets offset to be the offset of the name/value combination in the
* environment array, for use by setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*/
static char * __stdcall
my_findenv (const char *name, int *offset)
{
register int len;
register char **p;
const char *c;
c = name;
len = 0;
while (*c && *c != '=')
{
c++;
len++;
}
for (p = environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
*offset = p - environ;
return (char *) (++c);
}
return NULL;
}
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
extern "C"
char *
getenv (const char *name)
{
int offset;
return my_findenv (name, &offset);
}
/* putenv --
* Sets an environment variable
*/
extern "C"
int
putenv (const char *str)
{
register char *p, *equal;
int rval;
if (!(p = strdup (str)))
return 1;
if (!(equal = index (p, '=')))
{
(void) free (p);
return 1;
}
*equal = '\0';
rval = setenv (p, equal + 1, 1);
(void) free (p);
return rval;
}
/*
* setenv --
* Set the value of the environment variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
extern "C"
int
setenv (const char *name, const char *value, int rewrite)
{
register char *C;
unsigned int l_value;
int offset;
if (*value == '=') /* no `=' in value */
++value;
l_value = strlen (value);
if ((C = my_findenv (name, &offset)))
{ /* find if already exists */
if (!rewrite)
return 0;
if (strlen (C) >= l_value)
{ /* old larger; copy over */
while ((*C++ = *value++));
return 0;
}
}
else
{ /* create new slot */
register int cnt;
register char **P;
for (P = environ, cnt = 0; *P; ++P, ++cnt)
;
__cygwin_environ = environ = (char **) realloc ((char *) environ,
(size_t) (sizeof (char *) * (cnt + 2)));
if (!environ)
return -1;
environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
if (!(environ[offset] = /* name + `=' + value */
(char *) malloc ((size_t) ((int) (C - name) + l_value + 2))))
return -1;
for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
*C++ = '=';
strcpy (C, value);
win_env *spenv;
if ((spenv = getwinenv (environ[offset])))
spenv->add_cache (value);
return 0;
}
/*
* unsetenv(name) --
* Delete environment variable "name".
*/
extern "C"
void
unsetenv (const char *name)
{
register char **P;
int offset;
while (my_findenv (name, &offset)) /* if set multiple times */
for (P = &environ[offset];; ++P)
if (!(*P = *(P + 1)))
break;
}
/* Turn environment variable part of a=b string into uppercase. */
static void __inline
ucenv (char *p, char *eq)
{
/* Amazingly, NT has a case sensitive environment name list,
but only sometimes.
It's normal to have NT set your "Path" to something.
Later, you set "PATH" to something else. This alters "Path".
But if you try and do a naive getenv on "PATH" you'll get nothing.
So we upper case the labels here to prevent confusion later but
we only do it for the first process in a session group. */
for (; p < eq; p++)
if (islower (*p))
*p = toupper (*p);
}
/* Parse CYGWIN options */
static NO_COPY BOOL export_settings = FALSE;
enum settings
{
justset,
isfunc,
setbit,
set_process_state,
};
/* The structure below is used to set up an array which is used to
* parse the CYGWIN environment variable or, if enabled, options from
* the registry.
*/
struct parse_thing
{
const char *name;
union parse_setting
{
BOOL *b;
DWORD *x;
int *i;
void (*func)(const char *);
} setting;
enum settings disposition;
char *remember;
union parse_values
{
DWORD i;
const char *s;
} values[2];
} known[] =
{
{"binmode", {&__fmode}, justset, NULL, {{O_TEXT}, {O_BINARY}}},
{"envcache", {&envcache}, justset, NULL, {{TRUE}, {FALSE}}},
{"error_start", {func: &error_start_init}, isfunc, NULL, {{0}, {0}}},
{"export", {&export_settings}, justset, NULL, {{FALSE}, {TRUE}}},
{"forkchunk", {x: &chunksize}, justset, NULL, {{8192}, {0}}},
{"glob", {&allow_glob}, justset, NULL, {{FALSE}, {TRUE}}},
{"ntea", {&allow_ntea}, justset, NULL, {{FALSE}, {TRUE}}},
{"ntsec", {&allow_ntsec}, justset, NULL, {{FALSE}, {TRUE}}},
{"oldstack", {&oldstack}, justset, NULL, {{FALSE}, {TRUE}}},
{"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
{"threadsafe", {&threadsafe}, justset, NULL, {{TRUE}, {FALSE}}},
{NULL, {0}, justset, 0, {{0}, {0}}}
};
/* Parse a string of the form "something=stuff somethingelse=more-stuff",
* silently ignoring unknown "somethings".
*/
static void __stdcall
parse_options (char *buf)
{
int istrue;
char *p;
parse_thing *k;
if (buf == NULL)
{
char newbuf[MAX_PATH + 7] = "CYGWIN";
for (k = known; k->name != NULL; k++)
if (k->remember)
{
strcat (strcat (newbuf, " "), k->remember);
free (k->remember);
k->remember = NULL;
}
if (!export_settings)
return;
newbuf[sizeof ("CYGWIN") - 1] = '=';
debug_printf ("%s", newbuf);
putenv (newbuf);
return;
}
buf = strcpy ((char *) alloca (strlen (buf) + 1), buf);
for (p = strtok (buf, " \t"); p != NULL; p = strtok (NULL, " \t"))
{
if (!(istrue = !strncasematch (p, "no", 2)))
p += 2;
else if (!(istrue = *p != '-'))
p++;
char ch, *eq;
if ((eq = strchr (p, '=')) != NULL || (eq = strchr (p, ':')) != NULL)
ch = *eq, *eq++ = '\0';
else
ch = 0;
for (parse_thing *k = known; k->name != NULL; k++)
if (strcasematch (p, k->name))
{
switch (k->disposition)
{
case isfunc:
k->setting.func ((!eq || !istrue) ?
k->values[istrue].s : eq);
debug_printf ("%s (called func)", k->name);
break;
case justset:
if (!istrue || !eq)
*k->setting.x = k->values[istrue].i;
else
*k->setting.x = strtol (eq, NULL, 0);
debug_printf ("%s %d", k->name, *k->setting.x);
break;
case set_process_state:
k->setting.x = &myself->process_state;
/* fall through */
case setbit:
*k->setting.x &= ~k->values[istrue].i;
if (istrue || (eq && strtol (eq, NULL, 0)))
*k->setting.x |= k->values[istrue].i;
debug_printf ("%s %x", k->name, *k->setting.x);
break;
}
if (eq)
*--eq = ch;
int n = eq - p;
p = strdup (p);
if (n > 0)
p[n] = ':';
k->remember = p;
break;
}
}
debug_printf ("returning");
return;
}
/* Set options from the registry. */
static void __stdcall
regopt (const char *name)
{
MALLOC_CHECK;
/* FIXME: should not be under mount */
reg_key r (KEY_READ, CYGWIN_INFO_PROGRAM_OPTIONS_NAME, NULL);
char buf[MAX_PATH];
char lname[strlen(name) + 1];
strlwr (strcpy (lname, name));
MALLOC_CHECK;
if (r.get_string (lname, buf, sizeof (buf) - 1, "") == ERROR_SUCCESS)
parse_options (buf);
MALLOC_CHECK;
}
/* Initialize the environ array. Look for the CYGWIN environment
* environment variable and set appropriate options from it.
*/
void
environ_init (void)
{
const char * const rawenv = GetEnvironmentStrings ();
int envsize, i;
char *newp, **envp;
const char *p;
int sawTERM = 0;
/* Allocate space for environment + trailing NULL + CYGWIN env. */
envp = (char **) malloc ((4 + (envsize = 100)) * sizeof (char *));
regopt ("default");
if (myself->progname[0])
regopt (myself->progname);
#ifdef NTSEC_ON_BY_DEFAULT
/* Set ntsec explicit as default, if NT is running */
if (os_being_run == winNT)
allow_ntsec = TRUE;
#endif
/* Current directory information is recorded as variables of the
form "=X:=X:\foo\bar; these must be changed into something legal
(we could just ignore them but maybe an application will
eventually want to use them). */
for (i = 0, p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1, i++)
{
newp = strdup (p);
if (i >= envsize)
envp = (char **) realloc (envp, (4 + (envsize += 100)) *
sizeof (char *));
envp[i] = newp;
if (*newp == '=')
*newp = '!';
char *eq;
if ((eq = strchr (newp, '=')) == NULL)
eq = strchr (newp, '\0');
if (!parent_alive)
ucenv (newp, eq);
if (strncmp (newp, "TERM=", 5) == 0)
sawTERM = 1;
if (strncmp (newp, "CYGWIN=", sizeof("CYGWIN=") - 1) == 0)
parse_options (newp + sizeof("CYGWIN=") - 1);
if (*eq)
posify (envp + i, *++eq ? eq : --eq);
debug_printf ("%s", envp[i]);
}
if (!sawTERM)
envp[i++] = strdup ("TERM=cygwin");
envp[i] = NULL;
__cygwin_environ = *user_data->envptr = envp;
FreeEnvironmentStringsA ((char *) rawenv);
parse_options (NULL);
MALLOC_CHECK;
}
/* Function called by qsort to sort environment strings.
*/
static int
env_sort (const void *a, const void *b)
{
const char **p = (const char **) a;
const char **q = (const char **) b;
return strcmp (*p, *q);
}
/* Create a Windows-style environment block, i.e. a typical character buffer
* filled with null terminated strings, terminated by double null characters.
* Converts environment variables noted in conv_envvars into win32 form
* prior to placing them in the string.
*/
char *
winenv (const char * const *envp)
{
int len, n, tl;
const char * const *srcp;
const char * *dstp;
for (n = 0; envp[n]; n++)
continue;
const char *newenvp[n + 1];
for (tl = 0, srcp = envp, dstp = newenvp; *srcp; srcp++, dstp++)
{
len = strcspn (*srcp, "=") + 1;
win_env *conv;
if ((conv = getwinenv (*srcp, *srcp + len)))
*dstp = conv->native;
else
*dstp = *srcp;
tl += strlen (*dstp) + 1;
if ((*dstp)[0] == '!' && isalpha((*dstp)[1]) && (*dstp)[2] == ':' &&
(*dstp)[3] == '=')
{
char *p = (char *) alloca (strlen (*dstp) + 1);
strcpy (p, *dstp);
*p = '=';
*dstp = p;
}
}
*dstp = NULL; /* Terminate */
int envlen = dstp - newenvp;
debug_printf ("env count %d, bytes %d", envlen, tl);
/* Windows programs expect the environment block to be sorted. */
qsort (newenvp, envlen, sizeof (char *), env_sort);
/* Create an environment block suitable for passing to CreateProcess. */
char *ptr, *envblock;
envblock = (char *) malloc (tl + 2);
for (srcp = newenvp, ptr = envblock; *srcp; srcp++)
{
len = strlen (*srcp);
memcpy (ptr, *srcp, len + 1);
ptr += len + 1;
}
*ptr = '\0'; /* Two null bytes at the end */
return envblock;
}

669
winsup/cygwin/errno.cc Normal file
View File

@ -0,0 +1,669 @@
/* errno.cc: errno-related functions
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#define _REENT_ONLY
#include <stdio.h>
#include "winsup.h"
#include <errno.h>
/* Table to map Windows error codes to Errno values. */
/* FIXME: Doing things this way is a little slow. It's trivial to change
this into a big case statement if necessary. Left as is for now. */
#define X(w, e) {ERROR_##w, #w, e}
static const struct
{
int w; /* windows version of error */
const char *s; /* text of windows version */
int e; /* errno version of error */
}
errmap[] =
{
/* FIXME: Some of these choices are arbitrary! */
X (INVALID_FUNCTION, EBADRQC),
X (FILE_NOT_FOUND, ENOENT),
X (PATH_NOT_FOUND, ENOENT),
X (TOO_MANY_OPEN_FILES, EMFILE),
X (ACCESS_DENIED, EACCES),
X (INVALID_HANDLE, EBADF),
X (NOT_ENOUGH_MEMORY, ENOMEM),
X (INVALID_DATA, EINVAL),
X (OUTOFMEMORY, ENOMEM),
X (INVALID_DRIVE, ENODEV),
X (NOT_SAME_DEVICE, EXDEV),
X (NO_MORE_FILES, ENMFILE),
X (WRITE_PROTECT, EROFS),
X (BAD_UNIT, ENODEV),
X (SHARING_VIOLATION, EACCES),
X (LOCK_VIOLATION, EACCES),
X (SHARING_BUFFER_EXCEEDED, ENOLCK),
X (HANDLE_EOF, ENODATA),
X (HANDLE_DISK_FULL, ENOSPC),
X (NOT_SUPPORTED, ENOSYS),
X (REM_NOT_LIST, ENONET),
X (DUP_NAME, ENOTUNIQ),
X (BAD_NETPATH, ENXIO),
X (FILE_EXISTS, EEXIST),
X (CANNOT_MAKE, EPERM),
X (INVALID_PARAMETER, EINVAL),
X (NO_PROC_SLOTS, EAGAIN),
X (BROKEN_PIPE, EPIPE),
X (OPEN_FAILED, EIO),
X (NO_MORE_SEARCH_HANDLES, ENFILE),
X (CALL_NOT_IMPLEMENTED, ENOSYS),
X (INVALID_NAME, ENOENT),
X (WAIT_NO_CHILDREN, ECHILD),
X (CHILD_NOT_COMPLETE, EBUSY),
X (DIR_NOT_EMPTY, ENOTEMPTY),
X (SIGNAL_REFUSED, EIO),
X (BAD_PATHNAME, EINVAL),
X (SIGNAL_PENDING, EBUSY),
X (MAX_THRDS_REACHED, EAGAIN),
X (BUSY, EBUSY),
X (ALREADY_EXISTS, EEXIST),
X (NO_SIGNAL_SENT, EIO),
X (FILENAME_EXCED_RANGE, EINVAL),
X (META_EXPANSION_TOO_LONG, EINVAL),
X (INVALID_SIGNAL_NUMBER, EINVAL),
X (THREAD_1_INACTIVE, EINVAL),
X (BAD_PIPE, EINVAL),
X (PIPE_BUSY, EBUSY),
X (NO_DATA, EPIPE),
X (PIPE_NOT_CONNECTED, ECOMM),
X (MORE_DATA, EAGAIN),
X (DIRECTORY, EISDIR),
X (PIPE_CONNECTED, EBUSY),
X (PIPE_LISTENING, ECOMM),
X (NO_TOKEN, EINVAL),
X (PROCESS_ABORTED, EFAULT),
X (BAD_DEVICE, ENODEV),
X (BAD_USERNAME, EINVAL),
X (NOT_CONNECTED, ENOLINK),
X (OPEN_FILES, EAGAIN),
X (ACTIVE_CONNECTIONS, EAGAIN),
X (DEVICE_IN_USE, EAGAIN),
X (INVALID_AT_INTERRUPT_TIME, EINTR),
X (IO_DEVICE, EIO),
X (NOT_OWNER, EPERM),
X (END_OF_MEDIA, ENOSPC),
X (EOM_OVERFLOW, ENOSPC),
X (BEGINNING_OF_MEDIA, ESPIPE),
X (SETMARK_DETECTED, ESPIPE),
X (NO_DATA_DETECTED, ENOSPC),
X (POSSIBLE_DEADLOCK, EDEADLOCK),
X (CRC, EIO),
X (NEGATIVE_SEEK, EINVAL),
X (NOT_READY, ENOMEDIUM),
X (DISK_FULL, ENOSPC),
{ 0, NULL, 0}
};
/* seterrno_from_win_error: Given a Windows error code, set errno
as appropriate. */
void
seterrno_from_win_error (const char *file, int line, int code)
{
int i;
for (i = 0; errmap[i].w != 0; ++i)
if (code == errmap[i].w)
break;
if (errmap[i].w != 0)
{
if (strace_active)
strace_printf (_STRACE_SYSCALL, "%s:%d seterrno: %d (%s) -> %d",
file, line, code, errmap[i].s, errmap[i].e);
set_errno (errmap[i].e);
}
else
{
if (strace_active)
strace_printf (_STRACE_SYSCALL, "%s:%d seterrno: unknown error %d", file, line, code);
set_errno (EACCES);
}
}
/* seterrno: Set `errno' based on GetLastError (). */
void
seterrno (const char *file, int line)
{
seterrno_from_win_error (file, line, GetLastError ());
}
extern char *_user_strerror _PARAMS ((int));
extern const char __declspec(dllexport) * const _sys_errlist[]=
{
/* NOERROR 0 */ "No error",
/* EPERM 1 */ "Not super-user",
/* ENOENT 2 */ "No such file or directory",
/* ESRCH 3 */ "No such process",
/* EINTR 4 */ "Interrupted system call",
/* EIO 5 */ "I/O error",
/* ENXIO 6 */ "No such device or address",
/* E2BIG 7 */ "Arg list too long",
/* ENOEXEC 8 */ "Exec format error",
/* EBADF 9 */ "Bad file number",
/* ECHILD 10 */ "No children",
/* EAGAIN 11 */ "Resource temporarily unavailable",
/* ENOMEM 12 */ "Not enough core",
/* EACCES 13 */ "Permission denied",
/* EFAULT 14 */ "Bad address",
/* ENOTBLK 15 */ "Block device required",
/* EBUSY 16 */ "Mount device busy",
/* EEXIST 17 */ "File exists",
/* EXDEV 18 */ "Cross-device link",
/* ENODEV 19 */ "No such device",
/* ENOTDIR 20 */ "Not a directory",
/* EISDIR 21 */ "Is a directory",
/* EINVAL 22 */ "Invalid argument",
/* ENFILE 23 */ "Too many open files in system",
/* EMFILE 24 */ "Too many open files",
/* ENOTTY 25 */ "Not a typewriter",
/* ETXTBSY 26 */ "Text file busy",
/* EFBIG 27 */ "File too large",
/* ENOSPC 28 */ "No space left on device",
/* ESPIPE 29 */ "Illegal seek",
/* EROFS 30 */ "Read only file system",
/* EMLINK 31 */ "Too many links",
/* EPIPE 32 */ "Broken pipe",
/* EDOM 33 */ "Math arg out of domain of func",
/* ERANGE 34 */ "Math result not representable",
/* ENOMSG 35 */ "No message of desired type",
/* EIDRM 36 */ "Identifier removed",
/* ECHRNG 37 */ "Channel number out of range",
/* EL2NSYNC 38 */ "Level 2 not synchronized",
/* EL3HLT 39 */ "Level 3 halted",
/* EL3RST 40 */ "Level 3 reset",
/* ELNRNG 41 */ "Link number out of range",
/* EUNATCH 42 */ "Protocol driver not attached",
/* ENOCSI 43 */ "No CSI structure available",
/* EL2HLT 44 */ "Level 2 halted",
/* EDEADLK 45 */ "Deadlock condition",
/* ENOLCK 46 */ "No record locks available",
"47",
"48",
"49",
/* EBADE 50 */ "Invalid exchange",
/* EBADR 51 */ "Invalid request descriptor",
/* EXFULL 52 */ "Exchange full",
/* ENOANO 53 */ "No anode",
/* EBADRQC 54 */ "Invalid request code",
/* EBADSLT 55 */ "Invalid slot",
/* EDEADLOCK 56 */ "File locking deadlock error",
/* EBFONT 57 */ "Bad font file fmt",
"58",
"59",
/* ENOSTR 60 */ "Device not a stream",
/* ENODATA 61 */ "No data (for no delay io)",
/* ETIME 62 */ "Timer expired",
/* ENOSR 63 */ "Out of streams resources",
/* ENONET 64 */ "Machine is not on the network",
/* ENOPKG 65 */ "Package not installed",
/* EREMOTE 66 */ "The object is remote",
/* ENOLINK 67 */ "The link has been severed",
/* EADV 68 */ "Advertise error",
/* ESRMNT 69 */ "Srmount error",
/* ECOMM 70 */ "Communication error on send",
/* EPROTO 71 */ "Protocol error",
"72",
"73",
/* EMULTIHOP 74 */ "Multihop attempted",
/* ELBIN 75 */ "Inode is remote (not really error)",
/* EDOTDOT 76 */ "Cross mount point (not really error)",
/* EBADMSG 77 */ "Trying to read unreadable message",
"78",
"79",
/* ENOTUNIQ 80 */ "Given log. name not unique",
/* EBADFD 81 */ "f.d. invalid for this operation",
/* EREMCHG 82 */ "Remote address changed",
/* ELIBACC 83 */ "Can't access a needed shared lib",
/* ELIBBAD 84 */ "Accessing a corrupted shared lib",
/* ELIBSCN 85 */ ".lib section in a.out corrupted",
/* ELIBMAX 86 */ "Attempting to link in too many libs",
/* ELIBEXEC 87 */ "Attempting to exec a shared library",
/* ENOSYS 88 */ "Function not implemented",
/* ENMFILE 89 */ "No more files",
/* ENOTEMPTY 90 */ "Directory not empty",
/* ENAMETOOLONG 91 */ "File or path name too long",
/* ELOOP 92 */ "Too many symbolic links",
"93",
"94",
/* EOPNOTSUPP 95 */ "Operation not supported on transport endpoint",
/* EPFNOSUPPORT 96 */ "Protocol family not supported",
"97",
"98",
"99",
"100",
"101",
"102",
"103",
/* ECONNRESET 104 */ "Connection reset by peer",
/* ENOBUFS 105 */ "No buffer space available",
/* EAFNOSUPPORT 106 */ "Address family not supported by protocol",
/* EPROTOTYPE 107 */ "Protocol wrong type for transport endpoint",
/* ENOTSOCK 108 */ "Socket operation on non-socket"
/* ENOPROTOOPT 109 */ "Protocol not available",
/* ESHUTDOWN 110 */ "Cannot send after transport endpoint shutdown",
/* ECONNREFUSED 111 */ "Connection refused",
/* EADDRINUSE 112 */ "Address already in use"
/* ECONNABORTED 113 */ "Connection aborted",
/* ENETUNREACH 114 */ "Network is unreachable",
/* ENETDOWN 115 */ "Network is down",
/* ETIMEDOUT 116 */ "Connection timed out",
/* EHOSTDOWN 117 */ "Host is down",
/* EHOSTUNREACH 118 */ "No route to host",
/* EINPROGRESS 119 */ "Operation now in progress",
/* EALREADY 120 */ "Operation already in progress",
/* EDESTADDRREQ 121 */ "Destination address required",
/* EMSGSIZE 122 */ "Message too long",
/* EPROTONOSUPPORT 123 */ "Protocol not supported",
/* ESOCKTNOSUPPORT 124 */ "Socket type not supported",
/* EADDRNOTAVAIL 125 */ "Cannot assign requested address",
/* ENETRESET 126 */ "Network dropped connection because of reset",
/* EISCONN 127 */ "Transport endpoint is already connected",
/* ENOTCONN 128 */ "Transport endpoint is not connected",
/* ETOOMANYREFS 129 */ "Too many references: cannot splice",
/* EPROCLIM 130 */ "Process limit exceeded",
/* EUSERS 131 */ "Too many users",
/* EDQUOT 132 */ "Quota exceeded",
/* ESTALE 133 */ "Stale NFS file handle",
/* ENOTSUP 134 */ "134",
/* ENOMEDIUM 135 */ "no medium"
};
int __declspec(dllexport) _sys_nerr =
sizeof (_sys_errlist) / sizeof (_sys_errlist[0]);
/* FIXME: Why is strerror() a long switch and not just:
return sys_errlist[errnum];
(or moral equivalent).
Some entries in sys_errlist[] don't match the corresponding
entries in strerror(). This seems odd.
*/
/* CYGWIN internal */
/* strerror: convert from errno values to error strings */
extern "C" char *
strerror (int errnum)
{
const char *error;
switch (errnum)
{
case EPERM:
error = "Not owner";
break;
case ENOENT:
error = "No such file or directory";
break;
case ESRCH:
error = "No such process";
break;
case EINTR:
error = "Interrupted system call";
break;
case EIO:
error = "I/O error";
break;
case ENXIO:
error = "No such device or address";
break;
case E2BIG:
error = "Arg list too long";
break;
case ENOEXEC:
error = "Exec format error";
break;
case EBADF:
error = "Bad file number";
break;
case ECHILD:
error = "No children";
break;
case EAGAIN:
error = "No more processes";
break;
case ENOMEM:
error = "Not enough memory";
break;
case EACCES:
error = "Permission denied";
break;
case EFAULT:
error = "Bad address";
break;
case ENOTBLK:
error = "Block device required";
break;
case EBUSY:
error = "Device or resource busy";
break;
case EEXIST:
error = "File exists";
break;
case EXDEV:
error = "Cross-device link";
break;
case ENODEV:
error = "No such device";
break;
case ENOTDIR:
error = "Not a directory";
break;
case EISDIR:
error = "Is a directory";
break;
case EINVAL:
error = "Invalid argument";
break;
case ENFILE:
error = "Too many open files in system";
break;
case EMFILE:
error = "Too many open files";
break;
case ENOTTY:
error = "Not a character device";
break;
case ETXTBSY:
error = "Text file busy";
break;
case EFBIG:
error = "File too large";
break;
case ENOSPC:
error = "No space left on device";
break;
case ESPIPE:
error = "Illegal seek";
break;
case EROFS:
error = "Read-only file system";
break;
case EMLINK:
error = "Too many links";
break;
case EPIPE:
error = "Broken pipe";
break;
case EDOM:
error = "Math arg out of domain of func";
break;
case ERANGE:
error = "Math result out of range";
break;
case ENOMSG:
error = "No message of desired type";
break;
case EIDRM:
error = "Identifier removed";
break;
case ECHRNG:
error = "Channel number out of range";
break;
case EL2NSYNC:
error = "Level 2 not synchronized";
break;
case EL3HLT:
error = "Level 3 halted";
break;
case EL3RST:
error = "Level 3 reset";
break;
case ELNRNG:
error = "Link number out of range";
break;
case EUNATCH:
error = "Protocol driver not attached";
break;
case ENOCSI:
error = "No CSI structure available";
break;
case EL2HLT:
error = "Level 2 halted";
break;
case EDEADLK:
error = "Deadlock condition";
break;
case ENOLCK:
error = "No lock";
break;
case EBADE:
error = "Invalid exchange";
break;
case EBADR:
error = "Invalid request descriptor";
break;
case EXFULL:
error = "Exchange full";
break;
case ENOANO:
error = "No anode";
break;
case EBADRQC:
error = "Invalid request code";
break;
case EBADSLT:
error = "Invalid slot";
break;
case EDEADLOCK:
error = "File locking deadlock error";
break;
case EBFONT:
error = "Bad font file fmt";
break;
case ENOSTR:
error = "Not a stream";
break;
case ENODATA:
error = "No data (for no delay io)";
break;
case ETIME:
error = "Stream ioctl timeout";
break;
case ENOSR:
error = "No stream resources";
break;
case ENONET:
error = "Machine is not on the network";
break;
case ENOPKG:
error = "No package";
break;
case EREMOTE:
error = "Resource is remote";
break;
case ENOLINK:
error = "Virtual circuit is gone";
break;
case EADV:
error = "Advertise error";
break;
case ESRMNT:
error = "Srmount error";
break;
case ECOMM:
error = "Communication error";
break;
case EPROTO:
error = "Protocol error";
break;
case EMULTIHOP:
error = "Multihop attempted";
break;
case ELBIN:
error = "Inode is remote (not really error)";
break;
case EDOTDOT:
error = "Cross mount point (not really error)";
break;
case EBADMSG:
error = "Bad message";
break;
case ENOTUNIQ:
error = "Given log. name not unique";
break;
case EBADFD:
error = "f.d. invalid for this operation";
break;
case EREMCHG:
error = "Remote address changed";
break;
case ELIBACC:
error = "Cannot access a needed shared library";
break;
case ELIBBAD:
error = "Accessing a corrupted shared library";
break;
case ELIBSCN:
error = ".lib section in a.out corrupted";
break;
case ELIBMAX:
error = "Attempting to link in more shared libraries than system limit";
break;
case ELIBEXEC:
error = "Cannot exec a shared library directly";
break;
case ENOSYS:
error = "Function not implemented";
break;
case ENMFILE:
error = "No more files";
break;
case ENOTEMPTY:
error = "Directory not empty";
break;
case ENAMETOOLONG:
error = "File or path name too long";
break;
case ELOOP:
error = "Too many symbolic links";
break;
case EOPNOTSUPP:
error = "Operation not supported on transport endpoint";
break;
case EPFNOSUPPORT:
error = "Protocol family not supported";
break;
case ECONNRESET:
error = "Connection reset by peer";
break;
case ENOBUFS:
error = "No buffer space available; the socket cannot be connected";
break;
case EAFNOSUPPORT:
error = "Addresses in the specified family cannot be used with this socket";
break;
case EPROTOTYPE:
error = "errno EPROTOTYPE triggered";
break;
case ENOTSOCK:
error = "The descriptor is a file, not a socket";
break;
case ENOPROTOOPT:
error = "This option is unsupported";
break;
case ESHUTDOWN:
error = "errno ESHUTDOWN triggered";
break;
case ECONNREFUSED:
error = "Connection refused";
break;
case EADDRINUSE:
error = "Address already in use";
break;
case ECONNABORTED:
error = "The connection was aborted";
break;
case ENETUNREACH:
error ="The network can't be reached from this host at this time";
break;
case ENETDOWN:
error = "Network failed.";
break;
case ETIMEDOUT:
error = "Attempt to connect timed out without establishing a connection";
break;
case EHOSTDOWN:
error = "errno EHOSTDOWN triggered";
break;
case EHOSTUNREACH:
error = "errno EHOSTUNREACH triggered";
break;
case EINPROGRESS:
error = "errno EINPROGRESS triggered";
break;
case EALREADY:
error = "errno EALREADY triggered";
break;
case EDESTADDRREQ:
error = "errno EDESTADDRREQ triggered";
break;
case EMSGSIZE:
error = "errno EMSGSIZE triggered";
break;
case EPROTONOSUPPORT:
error = "errno EPROTONOSUPPORT triggered";
break;
case ESOCKTNOSUPPORT:
error = "errno ESOCKTNOSUPPORT triggered";
break;
case EADDRNOTAVAIL:
error = "errno EADDRNOTAVAIL triggered";
break;
case ENETRESET:
error = "errno ENETRESET triggered";
break;
case EISCONN:
error = "The socket is already connected";
break;
case ENOTCONN:
error = "The socket is not connected";
break;
case ETOOMANYREFS:
error = "errno ETOOMANYREFS triggered";
break;
case EPROCLIM:
error = "errno EPROCLIM triggered";
break;
case EUSERS:
error = "errno EUSERS triggered";
break;
case EDQUOT:
error = "errno EDQUOT triggered";
break;
case ESTALE:
error = "errno ESTALE triggered";
break;
case ENOTSUP:
error = "errno ENOTSUP triggered";
break;
case ENOMEDIUM:
error = "no medium";
break;
default:
#ifdef _MT_SAFE
char *buf= _reent_winsup()->_strerror_buf;
#else
static NO_COPY char buf[20];
#endif
__small_sprintf (buf, "error %d", errnum);
error = buf;
break;
}
/* FIXME: strerror should really be const in the appropriate newlib
include files. */
return (char *) error;
}

1066
winsup/cygwin/exceptions.cc Normal file

File diff suppressed because it is too large Load Diff

204
winsup/cygwin/exec.cc Normal file
View File

@ -0,0 +1,204 @@
/* exec.cc: exec system call support.
Copyright 1996, 1997, 1998, 2000 Cygnus Solutions.
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 <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <process.h>
#include "winsup.h"
/* This is called _execve and not execve because the real execve is defined
in libc/posix/execve.c. It calls us. */
extern "C"
pid_t
_execve (const char *path, const char *const argv[], const char *const envp[])
{
static char *const empty_env[] = { 0 };
MALLOC_CHECK;
if (!envp)
envp = empty_env;
return _spawnve (NULL, _P_OVERLAY, path, argv, envp);
}
extern "C"
int
execl (const char *path, const char *arg0, ...)
{
int i;
va_list args;
const char *argv[1024];
va_start (args, arg0);
argv[0] = arg0;
i = 1;
do
argv[i] = va_arg (args, const char *);
while (argv[i++] != NULL);
va_end (args);
MALLOC_CHECK;
return _execve (path, (char * const *) argv, *user_data->envptr);
}
extern "C"
int
execv (const char *path, char * const *argv)
{
MALLOC_CHECK;
return _execve (path, (char * const *) argv, *user_data->envptr);
}
/* the same as a standard exec() calls family, but with NT security support */
extern "C"
pid_t
sexecve (HANDLE hToken, const char *path, const char *const argv[],
const char *const envp[])
{
_spawnve (hToken, _P_OVERLAY, path, argv, envp);
return -1;
}
extern "C"
int
sexecl (HANDLE hToken, const char *path, const char *arg0, ...)
{
int i;
va_list args;
const char *argv[1024];
va_start (args, arg0);
argv[0] = arg0;
i = 1;
do
argv[i] = va_arg (args, const char *);
while (argv[i++] != NULL);
va_end (args);
MALLOC_CHECK;
return sexecve (hToken, path, (char * const *) argv, *user_data->envptr);
}
extern "C"
int
sexecle (HANDLE hToken, const char *path, const char *arg0, ...)
{
int i;
va_list args;
const char * const *envp;
const char *argv[1024];
va_start (args, arg0);
argv[0] = arg0;
i = 1;
do
argv[i] = va_arg (args, const char *);
while (argv[i++] != NULL);
envp = va_arg (args, const char * const *);
va_end (args);
MALLOC_CHECK;
return sexecve(hToken, path, (char * const *) argv, (char * const *) envp);
}
extern "C"
int
sexeclp (HANDLE hToken, const char *path, const char *arg0, ...)
{
int i;
va_list args;
const char *argv[1024];
va_start (args, arg0);
argv[0] = arg0;
i = 1;
do
argv[i] = va_arg (args, const char *);
while (argv[i++] != NULL);
va_end (args);
MALLOC_CHECK;
return sexecvpe (hToken, path, (const char * const *) argv,
*user_data->envptr);
}
extern "C"
int
sexeclpe (HANDLE hToken, const char *path, const char *arg0, ...)
{
int i;
va_list args;
const char * const *envp;
const char *argv[1024];
va_start (args, arg0);
argv[0] = arg0;
i = 1;
do
argv[i] = va_arg (args, const char *);
while (argv[i++] != NULL);
envp = va_arg (args, const char * const *);
va_end (args);
MALLOC_CHECK;
return sexecvpe (hToken, path, argv, envp);
}
extern "C"
int
sexecv (HANDLE hToken, const char *path, const char * const *argv)
{
MALLOC_CHECK;
return sexecve (hToken, path, argv, *user_data->envptr);
}
extern "C"
int
sexecp (HANDLE hToken, const char *path, const char * const *argv)
{
MALLOC_CHECK;
return sexecvpe (hToken, path, argv, *user_data->envptr);
}
/*
* Copy string, until c or <nul> is encountered.
* NUL-terminate the destination string (s1).
* Return pointer to terminating byte in dst string.
*/
char * __stdcall
strccpy (char *s1, const char **s2, char c)
{
while (**s2 && **s2 != c)
*s1++ = *((*s2)++);
*s1 = 0;
MALLOC_CHECK;
return s1;
}
extern "C"
int
sexecvpe (HANDLE hToken, const char *file, const char * const *argv,
const char *const *envp)
{
char buf[MAXNAMLEN];
MALLOC_CHECK;
return sexecve (hToken, find_exec (file, buf), argv, envp);
}

107
winsup/cygwin/external.cc Normal file
View File

@ -0,0 +1,107 @@
/* external.cc: Interface to Cygwin internals from external programs.
Copyright 1997, 1998, 1999 Cygnus Solutions.
Written by Christopher Faylor <cgf@cygnus.com>
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include "external.h"
static external_pinfo *
fillout_pinfo (DWORD pid)
{
BOOL nextpid;
pinfo *p = NULL;
int i;
static external_pinfo ep;
if ((nextpid = !!(pid & CW_NEXTPID)))
pid ^= CW_NEXTPID;
for (i = 0; i < cygwin_shared->p.size(); i++, p = NULL)
{
p = cygwin_shared->p.vec + i;
if (!pid || (DWORD) p->pid == pid)
{
if (nextpid && pid)
{
pid = 0;
nextpid = 0;
}
else if (p->pid && NOTSTATE(p, PID_CLEAR))
break;
}
}
if (p == NULL)
return 0;
memset (&ep, 0, sizeof ep);
ep.ctty = tty_attached (p) ? p->ctty : -1;
ep.pid = p->pid;
ep.ppid = p->ppid;
ep.hProcess = p->hProcess;
ep.dwProcessId = p->dwProcessId;
//ep.dwSpawnedProcessId = p->dwSpawnedProcessId;
ep.uid = p->uid;
ep.gid = p->gid;
ep.pgid = p->pgid;
ep.sid = p->sid;
ep.umask = p->umask;
ep.start_time = p->start_time;
ep.rusage_self = p->rusage_self;
ep.rusage_children = p->rusage_children;
strcpy (ep.progname, p->progname);
ep.strace_mask = 0;
ep.strace_file = 0;
ep.process_state = p->process_state;
return &ep;
}
extern "C" DWORD
cygwin_internal (cygwin_getinfo_types t, ...)
{
va_list arg;
va_start (arg, t);
switch (t)
{
case CW_LOCK_PINFO:
return lock_pinfo_for_update (va_arg (arg, DWORD));
break;
case CW_UNLOCK_PINFO:
unlock_pinfo ();
return 1;
case CW_GETTHREADNAME:
return (DWORD) threadname (va_arg (arg, DWORD));
case CW_SETTHREADNAME:
{
char *name = va_arg (arg, char *);
regthread (name, va_arg (arg, DWORD));
return 1;
}
case CW_GETPINFO:
return (DWORD) fillout_pinfo (va_arg (arg, DWORD));
case CW_GETVERSIONINFO:
return (DWORD) cygwin_version_strings;
case CW_READ_V1_MOUNT_TABLES:
/* Upgrade old v1 registry mounts to new location. */
cygwin_shared->mount.import_v1_mounts ();
return 0;
default:
return (DWORD) -1;
}
}

View File

@ -0,0 +1,16 @@
<sect1 id="func-cygwin-internal">
<title>cygwin_internal</title>
<funcsynopsis>
<funcdef>extern "C" DWORD
<function>cygwin_internal</function></funcdef>
<paramdef>cygwin_getinfo_types <parameter>t</parameter></paramdef>
<paramdef><parameter>...</parameter></paramdef>
</funcsynopsis>
<para>This function gives you access to various internal data and functions.
Stay away unless you know what you're doing.</para>
</sect1>

106
winsup/cygwin/fcntl.cc Normal file
View File

@ -0,0 +1,106 @@
/* fcntl.cc: fcntl syscall
Copyright 1996, 1997, 1998 Cygnus Solutions.
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 <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include "winsup.h"
extern "C"
int
_fcntl (int fd, int cmd,...)
{
va_list args;
int arg = 0;
int res;
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK, "_fcntl");
if (dtable.not_open (fd))
{
set_errno (EBADF);
res = -1;
goto done;
}
switch (cmd)
{
case F_DUPFD:
va_start (args, cmd);
arg = va_arg (args,int);
va_end (args);
res = dup2 (fd, dtable.find_unused_handle (arg));
goto done;
case F_GETFD:
res = dtable[fd]->get_close_on_exec () ? FD_CLOEXEC : 0;
goto done;
case F_SETFD:
va_start (args, cmd);
arg = va_arg (args, int);
va_end (args);
dtable[fd]->set_close_on_exec (arg);
res = 0;
goto done;
case F_GETFL:
{
res = dtable[fd]->get_flags ();
goto done;
}
case F_SETFL:
{
int temp = 0;
va_start (args, cmd);
arg = va_arg (args, int);
va_end (args);
if (arg & O_RDONLY)
temp |= GENERIC_READ;
if (arg & O_WRONLY)
temp |= GENERIC_WRITE;
syscall_printf ("fcntl (%d, F_SETFL, %d)", arg);
dtable[fd]->set_access (temp);
dtable[fd]->set_flags (arg);
res = 0;
goto done;
}
case F_GETLK:
case F_SETLK:
case F_SETLKW:
{
struct flock *fl;
va_start (args, cmd);
fl = va_arg (args,struct flock *);
va_end (args);
res = dtable[fd]->lock (cmd, fl);
goto done;
}
default:
set_errno (EINVAL);
res = -1;
goto done;
}
set_errno (ENOSYS);
res = -1;
done:
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"_fcntl");
syscall_printf ("%d = fcntl (%d, %d, %d)", res, fd, cmd, arg);
return res;
}

1501
winsup/cygwin/fhandler.cc Normal file

File diff suppressed because it is too large Load Diff

804
winsup/cygwin/fhandler.h Normal file
View File

@ -0,0 +1,804 @@
/* fhandler.h
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _FHANDLER_H_
#define _FHANDLER_H_
#include <sys/ioctl.h>
/* Classes
Code is located in fhandler.cc unless another file name is given.
fhandler_base normal I/O
fhandler_disk_file
fhandler_serial Adds vmin and vtime.
fhandler_dev_null Not really I/O
fhandler_dev_zero Faked
fhandler_dev_raw (fhandler_raw.cc)
fhandler_dev_floppy (fhandler_floppy.cc)
fhandler_dev_tape (fhandler_tape.cc)
fhandler_pipe
fhandler_socket (net.cc)
fhandler_tty_slave (tty.cc)
fhandler_pty_master (tty.cc)
fhandler_tty_master (tty.cc)
fhandler_console Out with ansi control. (console.cc)
fhandler_windows Windows messages I/O (fhandler_windows.cc)
fhandler_proc Interesting possibility, not implemented yet
*/
enum
{
FH_RBINARY = 0x00001000, /* binary read mode */
FH_WBINARY = 0x00002000, /* binary write mode */
FH_CLOEXEC = 0x00004000, /* close-on-exec */
FH_RBINSET = 0x00008000, /* binary read mode has been explicitly set */
FH_WBINSET = 0x00010000, /* binary write mode has been explicitly set */
FH_APPEND = 0x00020000, /* always append */
FH_ASYNC = 0x00040000, /* async I/O */
FH_HADEOF = 0x00080000, /* EOF seen */
FH_SYMLINK = 0x00100000, /* is a symlink */
FH_EXECABL = 0x00200000, /* file looked like it would run:
* ends in .exe or .bat or begins with #! */
FH_W95LSBUG= 0x00400000, /* set when lseek is called as a flag that
* _write should check if we've moved beyond
* EOF, zero filling if so. */
FH_NOFRNAME= 0x00800000, /* Set if shouldn't free unix_path_name_ and
windows_path_name_ on destruction. */
FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */
FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */
FH_LOCAL = 0x04000000, /* File is unix domain socket */
FH_FIFO = 0x08000000, /* File is FIFO */
FH_HASACLS = 0x40000000, /* True if fs of file has ACLS */
/* Device flags */
/* Slow devices */
FH_CONSOLE = 0x00000001, /* is a console */
FH_CONIN = 0x00000002, /* console input */
FH_CONOUT = 0x00000003, /* console output */
FH_TTYM = 0x00000004, /* is a tty master */
FH_TTYS = 0x00000005, /* is a tty slave */
FH_PTYM = 0x00000006, /* is a pty master */
FH_SERIAL = 0x00000007, /* is a serial port */
FH_PIPE = 0x00000008, /* is a pipe */
FH_PIPER = 0x00000009, /* read end of a pipe */
FH_PIPEW = 0x0000000a, /* write end of a pipe */
FH_SOCKET = 0x0000000b, /* is a socket */
FH_WINDOWS = 0x0000000c, /* is a window */
FH_SLOW = 0x00000010, /* "slow" device if below this */
/* Fast devices */
FH_DISK = 0x00000010, /* is a disk */
FH_FLOPPY = 0x00000011, /* is a floppy */
FH_TAPE = 0x00000012, /* is a tape */
FH_NULL = 0x00000013, /* is the null device */
FH_ZERO = 0x00000014, /* is the zero device */
FH_NDEV = 0x00000015, /* Maximum number of devices */
FH_DEVMASK = 0x00000fff, /* devices live here */
FH_BAD = 0xffffffff
};
#define FHDEVN(n) ((n) & FH_DEVMASK)
#define FHISSETF(x) __ISSETF (this, x, FH)
#define FHSETF(x) __SETF (this, x, FH)
#define FHCLEARF(x) __CLEARF (this, x, FH)
#define FHCONDSETF(n, x) __CONDSETF(n, this, x, FH)
#define FHSTATOFF 0
extern const char *windows_device_names[];
#define __fmode (*(user_data->fmode_ptr))
class select_record;
class path_conv;
class fhandler_disk_file;
class fhandler_base
{
private:
DWORD status;
public:
int cb;
private:
int access_;
HANDLE io_handle;
int rpos_; /* Used in text reading */
int rsize_;
unsigned long namehash_; /* hashed filename, used as inode num */
/* Full unix path name of this file */
/* File open flags from open () and fcntl () calls */
int openflags_;
protected:
char *rabuf; /* used for crlf conversion in text files */
size_t ralen;
size_t raixget;
size_t raixput;
size_t rabuflen;
char *unix_path_name_;
char *win32_path_name_;
public:
void set_name (const char *unix, const char *win32 = NULL, int unit = 0);
virtual fhandler_base& operator =(fhandler_base &x)
{
memcpy (this, &x, sizeof *this);
unix_path_name_ = x.unix_path_name_ ? strdup (x.unix_path_name_) : NULL;
win32_path_name_ = x.win32_path_name_ ? strdup (x.win32_path_name_) : NULL;
return *this;
};
fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
virtual ~fhandler_base ();
/* Non-virtual simple accessor functions. */
void set_io_handle (HANDLE);
void set_cb (size_t size) { cb = size; }
DWORD get_device () { return status & FH_DEVMASK; }
virtual int get_unit () { return 0; }
virtual BOOL is_slow () { return get_device () < FH_SLOW; }
int get_access () { return access_; }
void set_access (int x) { access_ = x; }
int get_async () { return FHISSETF (ASYNC); }
void set_async (int x) { FHCONDSETF (x, ASYNC); }
int get_flags () { return openflags_; }
void set_flags (int x) { openflags_ = x; }
int get_w_binary () { return FHISSETF (WBINARY); }
int get_r_binary () { return FHISSETF (RBINARY); }
int get_w_binset () { return FHISSETF (WBINSET); }
int get_r_binset () { return FHISSETF (RBINSET); }
void set_w_binary (int b) { FHCONDSETF (b, WBINARY); FHSETF (WBINSET); }
void set_r_binary (int b) { FHCONDSETF (b, RBINARY); FHSETF (RBINSET); }
int get_r_no_interrupt () { return FHISSETF (NOEINTR); }
void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); }
int get_close_on_exec () { return FHISSETF (CLOEXEC); }
int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); }
void set_check_win95_lseek_bug (int b = 1) { FHCONDSETF (b, W95LSBUG); }
int get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); }
int get_need_fork_fixup () { return FHISSETF (FFIXUP); }
void set_need_fork_fixup () { FHSETF (FFIXUP); }
virtual void set_close_on_exec (int val);
virtual void fixup_after_fork (HANDLE parent);
int get_symlink_p () { return FHISSETF (SYMLINK); }
void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); }
void set_symlink_p () { FHSETF (SYMLINK); }
int get_socket_p () { return FHISSETF (LOCAL); }
void set_socket_p (int val) { FHCONDSETF (val, LOCAL); }
void set_socket_p () { FHSETF (LOCAL); }
int get_execable_p () { return FHISSETF (EXECABL); }
void set_execable_p (int val) { FHCONDSETF (val, EXECABL); }
void set_execable_p () { FHSETF (EXECABL); }
int get_append_p () { return FHISSETF (APPEND); }
void set_append_p (int val) { FHCONDSETF (val, APPEND); }
void set_append_p () { FHSETF (APPEND); }
int get_readahead_valid () { return raixget < ralen; }
int puts_readahead (const char *s, size_t len = (size_t) -1);
int put_readahead (char value);
int get_readahead ();
int peek_readahead (int queryput = 0);
int eat_readahead (int n);
void set_readahead_valid (int val, int ch = -1);
int has_acls () { return FHISSETF (HASACLS); }
void set_has_acls (int val) { FHCONDSETF (val, HASACLS); }
int no_free_names () { return FHISSETF (NOFRNAME); }
void set_no_free_names (int val) { FHCONDSETF (val, NOFRNAME); }
void set_no_free_names () { FHSETF (NOFRNAME); }
const char *get_name () { return unix_path_name_; }
const char *get_win32_name () { return win32_path_name_; }
unsigned long get_namehash () { return namehash_; }
/* fixup fd possibly non-inherited handles after fork */
void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
/* Potentially overridden virtual functions. */
virtual int open (const char *, int flags, mode_t mode = 0)
{
return open (flags, mode);
}
virtual int open (int flags, mode_t mode = 0);
virtual int close ();
virtual int fstat (struct stat *buf);
virtual int ioctl (unsigned int cmd, void *);
virtual char const * ttyname () { return get_name(); }
virtual int read (void *ptr, size_t len);
virtual int write (const void *ptr, size_t len);
virtual off_t lseek (off_t offset, int whence);
virtual int lock (int, struct flock *);
virtual void dump ();
virtual int dup (fhandler_base *child);
void *operator new (size_t, void *p) {return p;}
virtual void init (HANDLE, DWORD, mode_t);
virtual int tcflush (int);
virtual int tcsendbreak (int);
virtual int tcdrain ();
virtual int tcflow (int);
virtual int tcsetattr (int a, const struct termios *t);
virtual int tcgetattr (struct termios *t);
virtual int tcsetpgrp (const pid_t pid);
virtual int tcgetpgrp ();
virtual int is_tty () { return 0; }
virtual BOOL is_device () { return TRUE; }
virtual char *ptsname () { return NULL;}
virtual class fhandler_socket *is_socket () { return 0; }
virtual class fhandler_console *is_console () { return 0; }
virtual int is_windows () {return 0; }
virtual int raw_read (void *ptr, size_t ulen);
virtual int raw_write (const void *ptr, size_t ulen);
/* Function to save state of a fhandler_base into memory. */
virtual int linearize (unsigned char *);
/* Function to de-linearize into a fd */
virtual int de_linearize (const char *, const char *, const char *);
/* Virtual accessor functions to hide the fact
that some fd's have two handles. */
virtual HANDLE get_handle () const { return io_handle; }
virtual HANDLE get_io_handle () const { return io_handle; }
virtual HANDLE get_output_handle () const { return io_handle; }
virtual BOOL hit_eof () {return FALSE;}
virtual select_record *select_read (select_record *s);
virtual select_record *select_write (select_record *s);
virtual select_record *select_except (select_record *s);
virtual int ready_for_read (int fd, DWORD howlong, int ignra);
virtual const char * get_native_name ()
{
return windows_device_names[FHDEVN (status)];
}
virtual int bg_check (int, int x = 0) {return 1;}
};
class fhandler_socket: public fhandler_base
{
private:
int addr_family;
public:
fhandler_socket (const char *name = 0);
fhandler_socket (unsigned int, const char *name = 0);
~fhandler_socket ();
int get_socket () const { return (int) get_handle(); }
fhandler_socket * is_socket () { return this; }
int write (const void *ptr, size_t len);
int read (void *ptr, size_t len);
int ioctl (unsigned int cmd, void *);
off_t lseek (off_t offset, int whence) { return 0; }
int close ();
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
int get_addr_family () {return addr_family;}
void set_addr_family (int af) {addr_family = af;}
};
class fhandler_pipe: public fhandler_base
{
public:
fhandler_pipe (const char *name = 0);
off_t lseek (off_t offset, int whence);
/* This strange test is due to the fact that we can't rely on
Windows shells to "do the right thing" with pipes. Apparently
the can keep one end of the pipe open when it shouldn't be. */
BOOL is_slow () {return os_being_run == winNT;}
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
};
class fhandler_dev_raw: public fhandler_base
{
protected:
char *devbuf;
size_t devbufsiz;
size_t devbufstart;
size_t devbufend;
int eom_detected : 1;
int eof_detected : 1;
int lastblk_to_read : 1;
int is_writing : 1;
int has_written : 1;
int unit;
virtual void clear (void);
virtual int writebuf (void);
/* returns not null, if `win_error' determines an end of media condition */
virtual int is_eom(int win_error) = 0;
/* returns not null, if `win_error' determines an end of file condition */
virtual int is_eof(int win_error) = 0;
fhandler_dev_raw (DWORD dev, const char *name, int unit);
public:
~fhandler_dev_raw (void);
/* Function to de-linearize into a fd */
int de_linearize (const char *, const char *, const char *);
int open (const char *path, int flags, mode_t mode = 0);
int close (void);
int raw_read (void *ptr, size_t ulen);
int raw_write (const void *ptr, size_t ulen);
int fstat (struct stat *buf);
int dup (fhandler_base *child);
int ioctl (unsigned int cmd, void *buf);
};
class fhandler_dev_floppy: public fhandler_dev_raw
{
protected:
virtual int is_eom (int win_error);
virtual int is_eof (int win_error);
public:
fhandler_dev_floppy (const char *name, int unit);
virtual int open (const char *path, int flags, mode_t mode = 0);
virtual int close (void);
virtual off_t lseek (off_t offset, int whence);
virtual int ioctl (unsigned int cmd, void *buf);
};
class fhandler_dev_tape: public fhandler_dev_raw
{
int norewind;
int lasterr;
protected:
virtual void clear (void);
virtual int is_eom (int win_error);
virtual int is_eof (int win_error);
public:
fhandler_dev_tape (const char *name, int unit);
virtual int open (const char *path, int flags, mode_t mode = 0);
virtual int close (void);
virtual off_t lseek (off_t offset, int whence);
virtual int fstat (struct stat *buf);
virtual int dup (fhandler_base *child);
virtual int ioctl (unsigned int cmd, void *buf);
private:
int tape_write_marks (int marktype, DWORD len);
int tape_get_pos (unsigned long *ret);
int tape_set_pos (int mode, long count, BOOLEAN sfm_func = FALSE);
int tape_erase (int mode);
int tape_prepare (int action);
BOOLEAN tape_get_feature (DWORD parm);
int tape_get_blocksize (long *min, long *def, long *max, long *cur);
int tape_set_blocksize (long count);
int tape_status (struct mtget *get);
int tape_compression (long count);
};
/* Standard disk file */
class fhandler_disk_file: public fhandler_base
{
private:
int check_execable_p (const char *path);
public:
fhandler_disk_file (const char *name);
int open (const char *path, int flags, mode_t mode = 0);
int open (path_conv& real_path, int flags, mode_t mode);
int close ();
int lock (int, struct flock *);
BOOL is_device () { return FALSE; }
int fstat (struct stat *buf);
};
class fhandler_serial: public fhandler_base
{
private:
unsigned int vmin_; /* from termios */
unsigned int vtime_; /* from termios */
pid_t pgrp_;
public:
int overlapped_armed;
OVERLAPPED io_status;
/* Constructor */
fhandler_serial (const char *name, DWORD devtype = FH_SERIAL, int unit = 0);
int open (const char *path, int flags, mode_t mode);
int close ();
void init (HANDLE h, DWORD a, mode_t flags);
void overlapped_setup ();
int dup (fhandler_base *child);
int raw_read (void *ptr, size_t ulen);
int raw_write (const void *ptr, size_t ulen);
int tcsendbreak (int);
int tcdrain ();
int tcflow (int);
int tcsetattr (int a, const struct termios *t);
int tcgetattr (struct termios *t);
off_t lseek (off_t offset, int whence) { return 0; }
int tcflush (int);
void dump ();
int is_tty () { return 1; }
void fixup_after_fork (HANDLE parent);
int de_linearize (const char *, const char *, const char *);
/* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
don't use it for permissions checking. fhandler_tty_slave does
permission checking on pgrps. */
virtual int tcgetpgrp () { return pgrp_; }
virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
};
class fhandler_termios: public fhandler_base
{
protected:
HANDLE output_handle;
virtual void doecho (const void *str, DWORD len) {};
virtual int accept_input () {return 1;};
public:
tty_min *tc;
fhandler_termios (DWORD dev, const char *name = 0, int unit = 0) :
fhandler_base (dev, name, unit)
{
// nothing to do
}
HANDLE restart_output_event;
HANDLE get_output_handle () const { return output_handle; }
int line_edit (const char *rptr, int nread, int always_accept = 0);
void set_output_handle (HANDLE h) { output_handle = h; }
void tcinit (tty_min *this_tc, int force = FALSE);
virtual int is_tty () { return 1; }
int tcgetpgrp ();
int tcsetpgrp (int pid);
void set_ctty (int ttynum, int flags);
int bg_check (int sig, int blocksigs = 1);
};
/* This is a input and output console handle */
class fhandler_console: public fhandler_termios
{
private:
/* Output state */
// enum {normal, gotesc, gotsquare, gotarg1, gotcommand} state;
#define normal 1
#define gotesc 2
#define gotsquare 3
#define gotarg1 4
#define gotrsquare 5
#define gotcommand 6
#define gettitle 7
#define eattitle 8
#define MAXARGS 10
int state_;
int args_[MAXARGS];
int nargs_;
DWORD default_color;
/* Output calls */
BOOL fillin_info ();
void clear_screen (int, int, int, int);
void scroll_screen (int, int, int, int, int, int);
void cursor_set (BOOL, int, int);
void cursor_get (int *, int *);
void cursor_rel (int, int);
const unsigned char * write_normal (unsigned const char*, unsigned const char *);
void char_command (char);
int output_tcsetattr (int a, const struct termios *t);
/* Input calls */
int igncr_enabled ();
int input_tcsetattr (int a, const struct termios *t);
public:
fhandler_console (const char *name);
fhandler_console* is_console () { return this; }
int open (const char *path, int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
void doecho (const void *str, DWORD len) { (void) write (str, len); }
int read (void *ptr, size_t len);
int close ();
int tcflush (int);
int tcsetattr (int a, const struct termios *t);
int tcgetattr (struct termios *t);
int tcsetpgrp (const pid_t pid) { tc->pgid = pid; return 0; }
/* Special dup as we must dup two handles */
int dup (fhandler_base *child);
int ioctl (unsigned int cmd, void *);
void init (HANDLE, DWORD, mode_t);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
int de_linearize (const char *, const char *, const char *);
void set_close_on_exec (int val);
void fixup_after_fork (HANDLE parent);
void set_input_state ()
{
if (TTYISSETF (RSTCONS))
input_tcsetattr (0, &tc->ti);
}
};
class fhandler_tty_common: public fhandler_termios
{
public:
fhandler_tty_common (DWORD dev, const char *name = 0, int unit = 0) :
fhandler_termios (dev, name, unit),
ttynum (unit)
{
// nothing to do
}
HANDLE output_done_event; // Raised by master when tty's output buffer
// written. Write status in tty::write_retval.
HANDLE ioctl_request_event; // Raised by slave to perform ioctl() request.
// Ioctl() request in tty::cmd/arg.
HANDLE ioctl_done_event; // Raised by master on ioctl() completion.
// Ioctl() status in tty::ioctl_retval.
HANDLE output_mutex;
HANDLE inuse; // used to indicate that a tty is in use
DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
void __release_output_mutex (const char *fn, int ln);
int ttynum; // Master tty num.
virtual int dup (fhandler_base *child);
tty *get_ttyp () { return (tty *)tc; }
int get_unit () { return ttynum; }
int close ();
void set_close_on_exec (int val);
void fixup_after_fork (HANDLE parent);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
};
class fhandler_tty_slave: public fhandler_tty_common
{
void send_ioctl_request ();
public:
/* Constructor */
fhandler_tty_slave (const char *name);
fhandler_tty_slave (int, const char *name);
int open (const char *path, int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
int read (void *ptr, size_t len);
void init (HANDLE, DWORD, mode_t);
int tcsetattr (int a, const struct termios *t);
int tcgetattr (struct termios *t);
int tcflush (int);
int ioctl (unsigned int cmd, void *);
off_t lseek (off_t offset, int whence) { return 0; }
};
class fhandler_pty_master: public fhandler_tty_common
{
int pktmode; // non-zero if pty in a packet mode.
public:
int neednl_; // Next read should start with \n
/* Constructor */
fhandler_pty_master (const char *name, DWORD devtype = FH_PTYM, int unit = -1);
int process_slave_output (char *buf, size_t len);
void doecho (const void *str, DWORD len);
int accept_input ();
int open (const char *path, int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
int read (void *ptr, size_t len);
int close ();
int tcsetattr (int a, const struct termios *t);
int tcgetattr (struct termios *t);
int tcflush (int);
int ioctl (unsigned int cmd, void *);
off_t lseek (off_t offset, int whence) { return 0; }
char *ptsname ();
void set_close_on_exec (int val);
void fixup_after_fork (HANDLE parent);
BOOL hit_eof ();
};
class fhandler_tty_master: public fhandler_pty_master
{
public:
/* Constructor */
fhandler_tty_master (const char *name, int unit);
fhandler_console *console; // device handler to perform real i/o.
HANDLE hThread; // process_output thread handle.
int init (int);
int init_console ();
void fixup_after_fork (HANDLE parent);
int de_linearize (const char *, const char *, const char *);
};
class fhandler_dev_null: public fhandler_base
{
public:
fhandler_dev_null (const char *name);
void dump ();
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
};
class fhandler_dev_zero: public fhandler_base
{
public:
fhandler_dev_zero (const char *name);
int open (const char *path, int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
int read (void *ptr, size_t len);
off_t lseek (off_t offset, int whence);
int close (void);
void dump ();
};
class fhandler_windows: public fhandler_base
{
private:
HWND hWnd_; // the window whose messages are to be retrieved by read() call
int method_; // write method (Post or Send)
public:
fhandler_windows (const char *name = 0);
int is_windows (void) { return 1; }
int open (const char *path, int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
int read (void *ptr, size_t len);
int ioctl (unsigned int cmd, void *);
off_t lseek (off_t offset, int whence) { return 0; }
int close (void) { return 0; }
void set_close_on_exec (int val);
void fixup_after_fork (HANDLE parent);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra);
};
#if 0
/* You can't do this */
typedef union
{
fhandler_normal normal;
fhandler_dev_null dev_null;
fhandler bare;
fhandler_serial tty;
} fhandler_union;
#else
#define fhandler_union fhandler_console
#endif
struct select_record
{
int fd;
HANDLE h;
fhandler_base *fh;
BOOL saw_error;
BOOL windows_handle;
BOOL read_ready, write_ready, except_ready;
BOOL read_selected, write_selected, except_selected;
select_record (fhandler_base *in_fh = NULL) {memset (this, 0, sizeof(select_record)); fh = in_fh;}
int (*startup) (select_record *me, class select_stuff *stuff);
int (*poll) (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
void (*cleanup) (select_record *me, class select_stuff *stuff);
struct select_record *next;
};
class select_stuff
{
public:
~select_stuff ();
BOOL always_ready, windows_used;
int total;
select_record start;
void *device_specific[FH_NDEV];
int test_and_set (int i, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
};
uid_t __stdcall get_file_owner (int, const char *);
gid_t __stdcall get_file_group (int, const char *);
void __stdcall set_inheritance (HANDLE &h, int val, const char *name = NULL);
#endif /* _FHANDLER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/* fhandler_floppy.cc. See fhandler.h for a description of the
fhandler classes.
Copyright 1999 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <sys/termios.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "winsup.h"
/**********************************************************************/
/* fhandler_dev_floppy */
int
fhandler_dev_floppy::is_eom (int win_error)
{
int ret = (win_error == ERROR_INVALID_PARAMETER);
if (ret)
debug_printf ("end of medium");
return ret;
}
int
fhandler_dev_floppy::is_eof (int win_error)
{
int ret = 0;
if (ret)
debug_printf ("end of file");
return ret;
}
fhandler_dev_floppy::fhandler_dev_floppy (const char *name, int unit) : fhandler_dev_raw (FH_FLOPPY, name, unit)
{
set_cb (sizeof *this);
}
int
fhandler_dev_floppy::open (const char *path, int flags, mode_t)
{
/* The correct size of the buffer would be 512 bytes,
* which is the atomic size, supported by WinNT.
* Unfortunately, the performance is worse than
* access to file system on same device!
* Setting buffer size to a relatively big value
* increases performance by means.
* The new ioctl call with 'rdevio.h' header file
* supports changing this value.
*
* Let's be smart: Let's take a multiplier of typical tar
* and cpio buffer sizes by default!
*/
devbufsiz = 61440L; /* 512L; */
return fhandler_dev_raw::open (path, flags);
}
int
fhandler_dev_floppy::close (void)
{
int ret;
ret = writebuf ();
if (ret)
{
fhandler_dev_raw::close ();
return ret;
}
return fhandler_dev_raw::close ();
}
off_t
fhandler_dev_floppy::lseek (off_t offset, int whence)
{
/* FIXME: Need to implement better. */
offset = (offset / 512) * 512;
return fhandler_base::lseek (offset, whence);
}
int
fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
{
return fhandler_dev_raw::ioctl (cmd, buf);
}

View File

@ -0,0 +1,495 @@
/* fhandler_raw.cc. See fhandler.h for a description of the fhandler classes.
Copyright 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <sys/termios.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "winsup.h"
#include <cygwin/rdevio.h>
#include <sys/mtio.h>
/**********************************************************************/
/* fhandler_dev_raw */
void
fhandler_dev_raw::clear (void)
{
devbuf = NULL;
devbufsiz = 0;
devbufstart = 0;
devbufend = 0;
eom_detected = 0;
eof_detected = 0;
lastblk_to_read = 0;
unit = 0;
}
int
fhandler_dev_raw::writebuf (void)
{
DWORD written;
int ret = 0;
if (is_writing && devbuf && devbufend)
{
memset (devbuf + devbufend, 0, devbufsiz - devbufend);
DWORD to_write = ((devbufend - 1) / 512 + 1) * 512;
ret = 0;
if (!WriteFile (get_handle (), devbuf, to_write, &written, 0))
{
ret = GetLastError ();
if (is_eom (ret))
eom_detected = 1;
}
if (written)
has_written = 1;
syscall_printf ("%d = WriteFile(%d, %d, write %d, written %d, 0)\n",
ret, get_handle (), devbuf, to_write, written);
devbufstart = devbufend = 0;
}
is_writing = 0;
return ret;
}
fhandler_dev_raw::fhandler_dev_raw (DWORD devtype, const char *name, int unit) : fhandler_base (devtype, name)
{
clear ();
this->unit = unit;
}
fhandler_dev_raw::~fhandler_dev_raw (void)
{
delete[]devbuf;
clear ();
}
int
fhandler_dev_raw::de_linearize (const char *buf, const char *unix_name,
const char *win32_name)
{
int ret = fhandler_base::de_linearize (buf, unix_name, win32_name);
if (devbufsiz > 1L)
{
devbuf = new char[devbufsiz];
devbufstart = devbufend = 0;
}
return ret;
}
int
fhandler_dev_raw::open (const char *path, int flags, mode_t)
{
path_conv real_path (path, SYMLINK_IGNORE);
int ret;
set_name (path, real_path.get_win32 ());
/* Always open a raw device existing */
ret = fhandler_base::open (path, flags & ~(O_CREAT | O_TRUNC));
if (ret)
{
if (devbufsiz > 1L)
{
devbuf = new char[devbufsiz];
}
}
else
{
devbufsiz = 0;
}
return ret;
}
int
fhandler_dev_raw::close (void)
{
return fhandler_base::close ();
}
int
fhandler_dev_raw::fstat (struct stat *buf)
{
if (!buf)
{
set_errno (EINVAL);
return -1;
}
memset (buf, 0, sizeof *buf);
buf->st_mode = S_IFCHR |
S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
buf->st_nlink = 1;
buf->st_blksize = devbuf ? devbufsiz : 1;
buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff);
return 0;
}
int
fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{
DWORD bytes_read = 0;
DWORD read2;
DWORD bytes_to_read;
int ret;
size_t len = ulen;
char *tgt;
/* In mode O_RDWR the buffer has to be written to device first */
ret = writebuf ();
if (ret)
{
set_errno (is_eom (ret) ? ENOSPC : EACCES);
return -1;
}
/* Checking a previous end of file */
if (eof_detected && !lastblk_to_read)
{
eof_detected = 0;
return 0;
}
/* Checking a previous end of media */
if (eom_detected && !lastblk_to_read)
{
set_errno (ENOSPC);
return -1;
}
if (devbuf)
{
while (len > 0)
{
if (devbufstart < devbufend)
{
bytes_to_read = min (len, devbufend - devbufstart);
debug_printf ("read %d bytes from buffer (rest %d)\n",
bytes_to_read, devbufstart - devbufend);
memcpy (ptr, devbuf + devbufstart, bytes_to_read);
len -= bytes_to_read;
ptr = (void *) ((char *) ptr + bytes_to_read);
bytes_read += bytes_to_read;
devbufstart += bytes_to_read;
if (lastblk_to_read)
{
lastblk_to_read = 0;
break;
}
}
if (len > 0)
{
if (len >= devbufsiz)
{
bytes_to_read = (len / 512) * 512;
tgt = (char *) ptr;
debug_printf ("read %d bytes direct from file\n",
bytes_to_read);
}
else
{
bytes_to_read = devbufsiz;
tgt = devbuf;
debug_printf ("read %d bytes from file into buffer\n",
bytes_to_read);
}
if (!ReadFile (get_handle (), tgt, bytes_to_read, &read2, 0))
{
ret = GetLastError ();
syscall_printf ("ReadFile %s failed with error %d\n",
get_name (), ret);
if (!is_eof (ret) && !is_eom (ret))
{
debug_printf ("return -1, set errno to EACCES");
set_errno (EACCES);
return -1;
}
if (is_eof (ret))
eof_detected = 1;
else
eom_detected = 1;
if (!read2)
{
if (!bytes_read && is_eom (ret))
{
debug_printf ("return -1, set errno to ENOSPC");
set_errno (ENOSPC);
return -1;
}
break;
}
lastblk_to_read = 1;
}
if (! read2)
break;
if (tgt == devbuf)
{
devbufstart = 0;
devbufend = read2;
}
else
{
len -= bytes_to_read;
ptr = (void *) ((char *) ptr + bytes_to_read);
bytes_read += bytes_to_read;
}
}
}
}
else if (!ReadFile (get_handle (), ptr, len, &bytes_read, 0))
{
ret = GetLastError ();
syscall_printf ("ReadFile %s failed with error %d\n",
get_name (), ret);
if (!is_eof (ret) && !is_eom (ret))
{
debug_printf ("return -1, set errno to EACCES");
set_errno (EACCES);
return -1;
}
if (bytes_read)
{
if (is_eof (ret))
eof_detected = 1;
else
eom_detected = 1;
}
else if (is_eom (ret))
{
debug_printf ("return -1, set errno to ENOSPC");
set_errno (ENOSPC);
return -1;
}
}
return bytes_read;
}
int
fhandler_dev_raw::raw_write (const void *ptr, size_t len)
{
DWORD bytes_written = 0;
DWORD bytes_to_write;
DWORD written;
char *p = (char *) ptr;
char *tgt;
int ret;
/* Checking a previous end of media on tape */
if (eom_detected)
{
set_errno (ENOSPC);
return -1;
}
if (!is_writing)
devbufstart = devbufend = 0;
is_writing = 1;
if (devbuf)
{
while (len > 0)
{
if ((len < devbufsiz || devbufend > 0) && devbufend < devbufsiz)
{
bytes_to_write = min (len, devbufsiz - devbufend);
memcpy (devbuf + devbufend, p, bytes_to_write);
bytes_written += bytes_to_write;
devbufend += bytes_to_write;
p += bytes_to_write;
len -= bytes_to_write;
}
else
{
if (devbufend == devbufsiz)
{
bytes_to_write = devbufsiz;
tgt = devbuf;
}
else
{
bytes_to_write = (len / devbufsiz) * devbufsiz;
tgt = p;
}
ret = 0;
if (!WriteFile (get_handle (), tgt, bytes_to_write, &written, 0))
ret = GetLastError ();
syscall_printf ("%d = WriteFile(%d, %d, write %d, written %d, 0)\n",
ret, get_handle (), tgt, bytes_to_write, written);
if (written)
has_written = 1;
if (ret)
{
if (!is_eom (ret))
{
__seterrno ();
return -1;
}
eom_detected = 1;
if (!written && !bytes_written)
{
set_errno (ENOSPC);
return -1;
}
if (tgt == p)
bytes_written += written;
break; // from while (len > 0)
}
if (tgt == devbuf)
{
if (written != devbufsiz)
memmove (devbuf, devbuf + written, devbufsiz - written);
devbufend = devbufsiz - written;
}
else
{
len -= written;
p += written;
bytes_written += written;
}
}
}
}
else if (len > 0)
{
if (!WriteFile (get_handle (), ptr, len, &bytes_written, 0))
{
ret = GetLastError ();
syscall_printf ("WriteFile %s failed with error %d\n",
get_name (), ret);
if (bytes_written)
has_written = 1;
if (!is_eom (ret))
{
set_errno (EACCES);
return -1;
}
eom_detected = 1;
if (!bytes_written)
{
set_errno (ENOSPC);
return -1;
}
}
has_written = 1;
}
return bytes_written;
}
int
fhandler_dev_raw::dup (fhandler_base *child)
{
int ret = fhandler_base::dup (child);
if (! ret)
{
fhandler_dev_raw *fhc = (fhandler_dev_raw *) child;
fhc->devbufsiz = devbufsiz;
if (devbufsiz > 1L)
{
fhc->devbuf = new char[devbufsiz];
memcpy (fhc->devbuf, devbuf, devbufend);
}
fhc->devbufstart = devbufstart;
fhc->devbufend = devbufend;
fhc->eom_detected = eom_detected;
fhc->eof_detected = eof_detected;
fhc->lastblk_to_read = lastblk_to_read;
fhc->unit = unit;
}
return ret;
}
int
fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
{
int ret = NO_ERROR;
if (cmd == RDIOCDOP)
{
struct rdop *op = (struct rdop *) buf;
if (!op)
ret = ERROR_INVALID_PARAMETER;
else
switch (op->rd_op)
{
case RDSETBLK:
if (get_device () == FH_TAPE)
{
struct mtop mop;
mop.mt_op = MTSETBLK;
mop.mt_count = op->rd_parm;
ret = ioctl (MTIOCTOP, &mop);
}
else if (op->rd_parm % 512)
ret = ERROR_INVALID_PARAMETER;
else if (devbuf && op->rd_parm < devbufend - devbufstart)
ret = ERROR_INVALID_PARAMETER;
else if (!devbuf || op->rd_parm != devbufsiz)
{
char *buf = new char[op->rd_parm];
if (devbuf)
{
memcpy (buf, devbuf + devbufstart, devbufend - devbufstart);
devbufend -= devbufstart;
delete[]devbuf;
}
else
devbufend = 0;
devbufstart = 0;
devbuf = buf;
devbufsiz = op->rd_parm;
}
break;
default:
break;
}
}
else if (cmd == RDIOCGET)
{
struct rdget *get = (struct rdget *) buf;
if (!get)
ret = ERROR_INVALID_PARAMETER;
else
get->bufsiz = devbufsiz ? devbufsiz : 1L;
}
else
return fhandler_base::ioctl (cmd, buf);
if (ret != NO_ERROR)
{
SetLastError (ret);
__seterrno ();
return -1;
}
return 0;
}

View File

@ -0,0 +1,883 @@
/* fhandler_serial.cc
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
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 <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include "winsup.h"
/**********************************************************************/
/* fhandler_serial */
fhandler_serial::fhandler_serial (const char *name, DWORD devtype, int unit) :
fhandler_base (devtype, name, unit)
{
set_cb (sizeof *this);
vmin_ = 0;
vtime_ = 0;
pgrp_ = myself->pgid;
set_need_fork_fixup ();
}
void
fhandler_serial::overlapped_setup ()
{
memset (&io_status, 0, sizeof (io_status));
io_status.hEvent = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
ProtectHandle (io_status.hEvent);
overlapped_armed = 0;
}
int
fhandler_serial::raw_read (void *ptr, size_t ulen)
{
int tot;
DWORD n;
HANDLE w4[2];
DWORD minchars = vmin_ ?: ulen;
w4[0] = io_status.hEvent;
w4[1] = signal_arrived;
debug_printf ("ulen %d, vmin_ %d, vtime_ %d, hEvent %p", ulen, vmin_, vtime_,
io_status.hEvent);
if (!overlapped_armed)
{
(void) SetCommMask (get_handle (), EV_RXCHAR);
ResetEvent (io_status.hEvent);
}
for (n = 0, tot = 0; ulen; ulen -= n, ptr = (char *)ptr + n)
{
DWORD ev;
COMSTAT st;
DWORD inq = 1;
n = 0;
if (!vtime_ && !vmin_)
inq = ulen;
else if (vtime_)
{
inq = ulen; // non-interruptible -- have to use kernel timeouts
// also note that this is not strictly correct.
// if vmin > ulen then things won't work right.
overlapped_armed = -1;
}
if (!overlapped_armed)
{
if (!ClearCommError (get_handle (), &ev, &st))
goto err;
else if (ev)
termios_printf ("error detected %x", ev);
else if (st.cbInQue)
inq = st.cbInQue;
else if ((size_t)tot >= minchars)
break;
else if (WaitCommEvent (get_handle (), &ev, &io_status))
{
debug_printf ("WaitCommEvent succeeded: ev %x", ev);
if (!ev)
continue;
}
else if (GetLastError () != ERROR_IO_PENDING)
goto err;
else
{
overlapped_armed = 1;
switch (WaitForMultipleObjects (2, w4, FALSE, INFINITE))
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult (get_handle (), &io_status, &n, FALSE))
goto err;
debug_printf ("n %d, ev %x", n, ev);
break;
case WAIT_OBJECT_0 + 1:
tot = -1;
PurgeComm (get_handle (), PURGE_RXABORT);
overlapped_armed = 0;
set_sig_errno (EINTR);
goto out;
default:
goto err;
}
}
}
overlapped_armed = 0;
ResetEvent (io_status.hEvent);
if (inq > ulen)
inq = ulen;
debug_printf ("inq %d", inq);
if (ReadFile (get_handle(), ptr, min (inq, ulen), &n, &io_status))
/* Got something */;
else if (GetLastError () != ERROR_IO_PENDING)
goto err;
else if (!GetOverlappedResult (get_handle (), &io_status, &n, TRUE))
goto err;
tot += n;
debug_printf ("vtime_ %d, vmin_ %d, n %d, tot %d", vtime_, vmin_, n, tot);
if (vtime_ || !vmin_ || !n)
break;
continue;
err:
PurgeComm (get_handle (), PURGE_RXABORT);
debug_printf ("err %E");
if (GetLastError () == ERROR_OPERATION_ABORTED)
n = 0;
else
{
tot = -1;
__seterrno ();
break;
}
}
out:
return tot;
}
/* Cover function to WriteFile to provide Posix interface and semantics
(as much as possible). */
int
fhandler_serial::raw_write (const void *ptr, size_t len)
{
DWORD bytes_written;
if (overlapped_armed)
PurgeComm (get_handle (), PURGE_TXABORT | PURGE_RXABORT);
ResetEvent (io_status.hEvent);
for (;;)
{
overlapped_armed = TRUE;
if (WriteFile (get_handle(), ptr, len, &bytes_written, &io_status))
break;
switch (GetLastError ())
{
case ERROR_OPERATION_ABORTED:
continue;
case ERROR_IO_PENDING:
break;
default:
goto err;
}
if (!GetOverlappedResult (get_handle (), &io_status, &bytes_written, TRUE))
goto err;
break;
}
overlapped_armed = FALSE;
return bytes_written;
err:
__seterrno ();
return -1;
}
void
fhandler_serial::dump (void)
{
paranoid_printf ("here");
}
void
fhandler_serial::init (HANDLE f, DWORD flags, mode_t bin)
{
fhandler_base::init (f, flags, bin);
(void) open (NULL, flags, bin ? O_BINARY : 0);
}
int
fhandler_serial::open (const char *name, int flags, mode_t mode)
{
int res;
COMMTIMEOUTS to;
extern BOOL reset_com;
syscall_printf ("fhandler_serial::open (%s, %p, %p)",
get_name (), flags, mode);
if (name && !(res = this->fhandler_base::open (flags, mode)))
return 0;
else
res = 1;
(void) SetCommMask (get_handle (), EV_RXCHAR);
set_r_no_interrupt (1); // Handled explicitly in read code
overlapped_setup ();
memset (&to, 0, sizeof (to));
(void) SetCommTimeouts (get_handle (), &to);
/* Reset serial port to known state of 9600-8-1-no flow control
on open for better behavior under Win 95.
FIXME: This should only be done when explicitly opening the com
port. It should not be reset if an fd is inherited.
Using __progname in this way, to determine how far along in the
initialization we are, is really a terrible kludge and should
be fixed ASAP.
*/
extern char *__progname;
if (reset_com && __progname)
{
DCB state;
GetCommState (get_handle (), &state);
syscall_printf ("setting initial state on %s (reset_com %d)",
get_name (), reset_com);
state.BaudRate = CBR_9600;
state.ByteSize = 8;
state.StopBits = ONESTOPBIT;
state.Parity = NOPARITY; /* FIXME: correct default? */
state.fBinary = TRUE; /* binary xfer */
state.EofChar = 0; /* no end-of-data in binary mode */
state.fNull = FALSE; /* don't discard nulls in binary mode */
state.fParity = FALSE; /* ignore parity errors */
state.fErrorChar = FALSE;
state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */
state.fOutX = FALSE; /* disable transmission flow control */
state.fInX = FALSE; /* disable reception flow control */
state.XonChar = 0x11;
state.XoffChar = 0x13;
state.fOutxDsrFlow = FALSE; /* disable DSR flow control */
state.fRtsControl = RTS_CONTROL_ENABLE; /* ignore lead control except
DTR */
state.fOutxCtsFlow = FALSE; /* disable output flow control */
state.fDtrControl = DTR_CONTROL_ENABLE; /* assert DTR */
state.fDsrSensitivity = FALSE; /* don't assert DSR */
state.fAbortOnError = TRUE;
if (!SetCommState (get_handle (), &state))
system_printf ("couldn't set initial state for %s, %E", get_name ());
}
SetCommMask (get_handle (), EV_RXCHAR);
syscall_printf ("%p = fhandler_serial::open (%s, %p, %p)",
res, get_name (), flags, mode);
return res;
}
int
fhandler_serial::close ()
{
(void) ForceCloseHandle (io_status.hEvent);
return fhandler_base::close ();
}
/* tcsendbreak: POSIX 7.2.2.1 */
/* Break for 250-500 milliseconds if duration == 0 */
/* Otherwise, units for duration are undefined */
int
fhandler_serial::tcsendbreak (int duration)
{
unsigned int sleeptime = 300;
if (duration > 0)
sleeptime *= duration;
if (SetCommBreak (get_handle ()) == 0)
return -1;
/* FIXME: need to send zero bits during duration */
usleep (sleeptime);
if (ClearCommBreak (get_handle ()) == 0)
return -1;
syscall_printf ("0 = fhandler_serial:tcsendbreak (%d)", duration);
return 0;
}
/* tcdrain: POSIX 7.2.2.1 */
int
fhandler_serial::tcdrain (void)
{
if (FlushFileBuffers (get_handle ()) == 0)
return -1;
return 0;
}
/* tcflow: POSIX 7.2.2.1 */
int
fhandler_serial::tcflow (int action)
{
DWORD win32action = 0;
DCB dcb;
char xchar;
termios_printf ("action %d", action);
switch (action)
{
case TCOOFF:
win32action = SETXOFF;
break;
case TCOON:
win32action = SETXON;
break;
case TCION:
case TCIOFF:
if (GetCommState (get_handle (), &dcb) == 0)
return -1;
if (action == TCION)
xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
else
xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
if (TransmitCommChar (get_handle (), xchar) == 0)
return -1;
return 0;
break;
default:
return -1;
break;
}
if (EscapeCommFunction (get_handle (), win32action) == 0)
return -1;
return 0;
}
/* tcflush: POSIX 7.2.2.1 */
int
fhandler_serial::tcflush (int queue)
{
if (queue == TCOFLUSH || queue == TCIOFLUSH)
PurgeComm (get_handle (), PURGE_TXABORT | PURGE_TXCLEAR);
if (queue == TCIFLUSH | queue == TCIOFLUSH)
/* Input flushing by polling until nothing turns up
(we stop after 1000 chars anyway) */
for (int max = 1000; max > 0; max--)
{
DWORD ev;
COMSTAT st;
if (!PurgeComm (get_handle (), PURGE_RXABORT | PURGE_RXCLEAR))
break;
Sleep (100);
if (!ClearCommError (get_handle (), &ev, &st) || !st.cbInQue)
break;
}
return 0;
}
/* tcsetattr: POSIX 7.2.1.1 */
int
fhandler_serial::tcsetattr (int action, const struct termios *t)
{
/* Possible actions:
TCSANOW: immediately change attributes.
TCSADRAIN: flush output, then change attributes.
TCSAFLUSH: flush output and discard input, then change attributes.
*/
BOOL dropDTR = FALSE;
COMMTIMEOUTS to;
DCB ostate, state;
unsigned int ovtime = vtime_, ovmin = vmin_;
termios_printf ("action %d", action);
if ((action == TCSADRAIN) || (action == TCSAFLUSH))
{
FlushFileBuffers (get_handle ());
termios_printf ("flushed file buffers");
}
if (action == TCSAFLUSH)
PurgeComm (get_handle (), (PURGE_RXABORT | PURGE_RXCLEAR));
/* get default/last comm state */
if (!GetCommState (get_handle (), &ostate))
return -1;
state = ostate;
/* -------------- Set baud rate ------------------ */
/* FIXME: WIN32 also has 14400, 56000, 128000, and 256000.
Unix also has 230400. */
switch (t->c_ospeed)
{
case B0: /* drop DTR */
dropDTR = TRUE;
state.BaudRate = 0;
break;
case B110:
state.BaudRate = CBR_110;
break;
case B300:
state.BaudRate = CBR_300;
break;
case B600:
state.BaudRate = CBR_600;
break;
case B1200:
state.BaudRate = CBR_1200;
break;
case B2400:
state.BaudRate = CBR_2400;
break;
case B4800:
state.BaudRate = CBR_4800;
break;
case B9600:
state.BaudRate = CBR_9600;
break;
case B19200:
state.BaudRate = CBR_19200;
break;
case B38400:
state.BaudRate = CBR_38400;
break;
case B57600:
state.BaudRate = CBR_57600;
break;
case B115200:
state.BaudRate = CBR_115200;
break;
default:
/* Unsupported baud rate! */
termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed);
set_errno (EINVAL);
return -1;
}
/* -------------- Set byte size ------------------ */
switch (t->c_cflag & CSIZE)
{
case CS5:
state.ByteSize = 5;
break;
case CS6:
state.ByteSize = 6;
break;
case CS7:
state.ByteSize = 7;
break;
case CS8:
state.ByteSize = 8;
break;
default:
/* Unsupported byte size! */
termios_printf ("Invalid t->c_cflag byte size %d",
t->c_cflag & CSIZE);
set_errno (EINVAL);
return -1;
}
/* -------------- Set stop bits ------------------ */
if (t->c_cflag & CSTOPB)
state.StopBits = TWOSTOPBITS;
else
state.StopBits = ONESTOPBIT;
/* -------------- Set parity ------------------ */
if (t->c_cflag & PARENB)
state.Parity = (t->c_cflag & PARODD) ? ODDPARITY : EVENPARITY;
else
state.Parity = NOPARITY;
state.fBinary = TRUE; /* Binary transfer */
state.EofChar = 0; /* No end-of-data in binary mode */
state.fNull = FALSE; /* Don't discard nulls in binary mode */
/* -------------- Parity errors ------------------ */
/* fParity combines the function of INPCK and NOT IGNPAR */
if ((t->c_iflag & INPCK) && !(t->c_iflag & IGNPAR))
state.fParity = TRUE; /* detect parity errors */
else
state.fParity = FALSE; /* ignore parity errors */
/* Only present in Win32, Unix has no equivalent */
state.fErrorChar = FALSE;
state.ErrorChar = 0;
/* -------------- Set software flow control ------------------ */
/* Set fTXContinueOnXoff to FALSE. This prevents the triggering of a
premature XON when the remote device interprets a received character
as XON (same as IXANY on the remote side). Otherwise, a TRUE
value separates the TX and RX functions. */
state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */
/* Transmission flow control */
if (t->c_iflag & IXON)
state.fOutX = TRUE; /* enable */
else
state.fOutX = FALSE; /* disable */
/* Reception flow control */
if (t->c_iflag & IXOFF)
state.fInX = TRUE; /* enable */
else
state.fInX = FALSE; /* disable */
/* XoffLim and XonLim are left at default values */
state.XonChar = (t->c_cc[VSTART] ? t->c_cc[VSTART] : 0x11);
state.XoffChar = (t->c_cc[VSTOP] ? t->c_cc[VSTOP] : 0x13);
/* -------------- Set hardware flow control ------------------ */
/* Disable DSR flow control */
state.fOutxDsrFlow = FALSE;
/* Some old flavors of Unix automatically enabled hardware flow
control when software flow control was not enabled. Since newer
Unices tend to require explicit setting of hardware flow-control,
this is what we do. */
/* RTS/CTS flow control */
if (t->c_cflag & CRTSCTS)
{ /* enable */
state.fOutxCtsFlow = TRUE;
state.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
else
{ /* disable */
state.fRtsControl = RTS_CONTROL_ENABLE;
state.fOutxCtsFlow = FALSE;
}
if (t->c_cflag & CRTSXOFF)
state.fRtsControl = RTS_CONTROL_HANDSHAKE;
/* -------------- DTR ------------------ */
/* Assert DTR on device open */
state.fDtrControl = DTR_CONTROL_ENABLE;
/* -------------- DSR ------------------ */
/* Assert DSR at the device? */
if (t->c_cflag & CLOCAL)
state.fDsrSensitivity = FALSE; /* no */
else
state.fDsrSensitivity = TRUE; /* yes */
/* -------------- Error handling ------------------ */
/* Since read/write operations terminate upon error, we
will use ClearCommError() to resume. */
state.fAbortOnError = TRUE;
/* -------------- Set state and exit ------------------ */
if (memcmp (&ostate, &state, sizeof (state)) != 0)
SetCommState (get_handle (), &state);
set_r_binary ((t->c_iflag & IGNCR) ? 0 : 1);
set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1);
if (dropDTR == TRUE)
EscapeCommFunction (get_handle (), CLRDTR);
else
{
/* FIXME: Sometimes when CLRDTR is set, setting
state.fDtrControl = DTR_CONTROL_ENABLE will fail. This
is a problem since a program might want to change some
parameters while DTR is still down. */
EscapeCommFunction (get_handle (), SETDTR);
}
/*
The following documentation on was taken from "Linux Serial Programming
HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME
(t->c_cc[VTIME] || vtime_) is to be used.
In non-canonical input processing mode, input is not assembled into
lines and input processing (erase, kill, delete, etc.) does not
occur. Two parameters control the behavior of this mode: c_cc[VTIME]
sets the character timer, and c_cc[VMIN] sets the minimum number of
characters to receive before satisfying the read.
If MIN > 0 and TIME = 0, MIN sets the number of characters to receive
before the read is satisfied. As TIME is zero, the timer is not used.
If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will
be satisfied if a single character is read, or TIME is exceeded (t =
TIME *0.1 s). If TIME is exceeded, no character will be returned.
If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The
read will be satisfied if MIN characters are received, or the time
between two characters exceeds TIME. The timer is restarted every time
a character is received and only becomes active after the first
character has been received.
If MIN = 0 and TIME = 0, read will be satisfied immediately. The
number of characters currently available, or the number of characters
requested will be returned. According to Antonino (see contributions),
you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get
the same result.
*/
if (t->c_lflag & ICANON)
{
vmin_ = MAXDWORD;
vtime_ = 0;
}
else
{
vtime_ = t->c_cc[VTIME] * 100;
vmin_ = t->c_cc[VMIN];
}
debug_printf ("vtime %d, vmin %d\n", vtime_, vmin_);
if (ovmin == vmin_ && ovtime == vtime_)
return 0;
memset (&to, 0, sizeof (to));
if ((vmin_ > 0) && (vtime_ == 0))
{
/* Returns immediately with whatever is in buffer on a ReadFile();
or blocks if nothing found. We will keep calling ReadFile(); until
vmin_ characters are read */
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
to.ReadTotalTimeoutConstant = MAXDWORD - 1;
}
else if ((vmin_ == 0) && (vtime_ > 0))
{
/* set timeoout constant appropriately and we will only try to
read one character in ReadFile() */
to.ReadTotalTimeoutConstant = vtime_;
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
}
else if ((vmin_ > 0) && (vtime_ > 0))
{
/* time applies to the interval time for this case */
to.ReadIntervalTimeout = vtime_;
}
else if ((vmin_ == 0) && (vtime_ == 0))
{
/* returns immediately with whatever is in buffer as per
Time-Outs docs in Win32 SDK API docs */
to.ReadIntervalTimeout = MAXDWORD;
}
debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d",
to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
int res = SetCommTimeouts (get_handle (), &to);
if (!res)
{
system_printf ("SetCommTimeout failed, %E");
__seterrno ();
return -1;
}
return 0;
}
/* tcgetattr: POSIX 7.2.1.1 */
int
fhandler_serial::tcgetattr (struct termios *t)
{
DCB state;
/* Get current Win32 comm state */
if (GetCommState (get_handle (), &state) == 0)
return -1;
/* for safety */
memset (t, 0, sizeof (*t));
/* -------------- Baud rate ------------------ */
switch (state.BaudRate)
{
case 0:
/* FIXME: need to drop DTR */
t->c_cflag = t->c_ospeed = t->c_ispeed = B0;
break;
case CBR_110:
t->c_cflag = t->c_ospeed = t->c_ispeed = B110;
break;
case CBR_300:
t->c_cflag = t->c_ospeed = t->c_ispeed = B300;
break;
case CBR_600:
t->c_cflag = t->c_ospeed = t->c_ispeed = B600;
break;
case CBR_1200:
t->c_cflag = t->c_ospeed = t->c_ispeed = B1200;
break;
case CBR_2400:
t->c_cflag = t->c_ospeed = t->c_ispeed = B2400;
break;
case CBR_4800:
t->c_cflag = t->c_ospeed = t->c_ispeed = B4800;
break;
case CBR_9600:
t->c_cflag = t->c_ospeed = t->c_ispeed = B9600;
break;
case CBR_19200:
t->c_cflag = t->c_ospeed = t->c_ispeed = B19200;
break;
case CBR_38400:
t->c_cflag = t->c_ospeed = t->c_ispeed = B38400;
break;
case CBR_57600:
t->c_cflag = t->c_ospeed = t->c_ispeed = B57600;
break;
case CBR_115200:
t->c_cflag = t->c_ospeed = t->c_ispeed = B115200;
break;
default:
/* Unsupported baud rate! */
termios_printf ("Invalid baud rate %d", state.BaudRate);
set_errno (EINVAL);
return -1;
}
/* -------------- Byte size ------------------ */
switch (state.ByteSize)
{
case 5:
t->c_cflag |= CS5;
break;
case 6:
t->c_cflag |= CS6;
break;
case 7:
t->c_cflag |= CS7;
break;
case 8:
t->c_cflag |= CS8;
break;
default:
/* Unsupported byte size! */
termios_printf ("Invalid byte size %d", state.ByteSize);
set_errno (EINVAL);
return -1;
}
/* -------------- Stop bits ------------------ */
if (state.StopBits == TWOSTOPBITS)
t->c_cflag |= CSTOPB;
/* -------------- Parity ------------------ */
if (state.Parity == ODDPARITY)
t->c_cflag |= (PARENB | PARODD);
if (state.Parity == EVENPARITY)
t->c_cflag |= PARENB;
/* -------------- Parity errors ------------------ */
/* fParity combines the function of INPCK and NOT IGNPAR */
if (state.fParity == TRUE)
t->c_iflag |= INPCK;
else
t->c_iflag |= IGNPAR; /* not necessarily! */
/* -------------- Software flow control ------------------ */
/* transmission flow control */
if (state.fOutX)
t->c_iflag |= IXON;
/* reception flow control */
if (state.fInX)
t->c_iflag |= IXOFF;
t->c_cc[VSTART] = (state.XonChar ? state.XonChar : 0x11);
t->c_cc[VSTOP] = (state.XoffChar ? state.XoffChar : 0x13);
/* -------------- Hardware flow control ------------------ */
/* Some old flavors of Unix automatically enabled hardware flow
control when software flow control was not enabled. Since newer
Unices tend to require explicit setting of hardware flow-control,
this is what we do. */
/* Input flow-control */
if ((state.fRtsControl == RTS_CONTROL_HANDSHAKE) &&
(state.fOutxCtsFlow == TRUE))
t->c_cflag |= CRTSCTS;
if (state.fRtsControl == RTS_CONTROL_HANDSHAKE)
t->c_cflag |= CRTSXOFF;
/* -------------- CLOCAL --------------- */
/* DSR is only lead toggled only by CLOCAL. Check it to see if
CLOCAL was called. */
/* FIXME: If tcsetattr() hasn't been called previously, this may
give a false CLOCAL. */
if (state.fDsrSensitivity == FALSE)
t->c_cflag |= CLOCAL;
/* FIXME: need to handle IGNCR */
#if 0
if (!get_r_binary ())
t->c_iflag |= IGNCR;
#endif
if (!get_w_binary ())
t->c_oflag |= ONLCR;
debug_printf ("vmin_ %d, vtime_ %d", vmin_, vtime_);
if (vmin_ == MAXDWORD)
{
t->c_lflag |= ICANON;
t->c_cc[VTIME] = t->c_cc[VMIN] = 0;
}
else
{
t->c_cc[VTIME] = vtime_ / 100;
t->c_cc[VMIN] = vmin_;
}
return 0;
}
void
fhandler_serial::fixup_after_fork (HANDLE parent)
{
if (get_close_on_exec ())
this->fhandler_base::fixup_after_fork (parent);
overlapped_setup ();
debug_printf ("io_status.hEvent %p", io_status.hEvent);
}
int
fhandler_serial::de_linearize (const char *buf, const char *unix_name,
const char *win32_name)
{
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
overlapped_setup ();
debug_printf ("io_status.hEvent %p", io_status.hEvent);
return res;
}
int
fhandler_serial::dup (fhandler_base *child)
{
fhandler_serial *fhc = (fhandler_serial *) child;
overlapped_setup ();
fhc->vmin_ = vmin_;
fhc->vtime_ = vtime_;
return fhandler_base::dup (child);
}

View File

@ -0,0 +1,829 @@
/* fhandler_tape.cc. See fhandler.h for a description of the fhandler
classes.
Copyright 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <sys/termios.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "winsup.h"
#include <sys/mtio.h>
/**********************************************************************/
/* fhandler_dev_tape */
void
fhandler_dev_tape::clear (void)
{
norewind = 0;
lasterr = 0;
fhandler_dev_raw::clear ();
}
int
fhandler_dev_tape::is_eom (int win_error)
{
int ret = ((win_error == ERROR_END_OF_MEDIA)
|| (win_error == ERROR_EOM_OVERFLOW)
|| (win_error == ERROR_NO_DATA_DETECTED));
if (ret)
debug_printf ("end of medium");
return ret;
}
int
fhandler_dev_tape::is_eof (int win_error)
{
int ret = ((win_error == ERROR_FILEMARK_DETECTED)
|| (win_error == ERROR_SETMARK_DETECTED));
if (ret)
debug_printf ("end of file");
return ret;
}
fhandler_dev_tape::fhandler_dev_tape (const char *name, int unit) : fhandler_dev_raw (FH_TAPE, name, unit)
{
set_cb (sizeof *this);
}
int
fhandler_dev_tape::open (const char *path, int flags, mode_t)
{
int ret;
int minor;
if (get_device_number (path, minor) != FH_TAPE)
{
set_errno (EINVAL);
return -1;
}
norewind = (minor >= 128);
devbufsiz = 1L;
ret = fhandler_dev_raw::open (path, flags);
if (ret)
{
struct mtget get;
struct mtop op;
struct mtpos pos;
if (! ioctl (MTIOCGET, &get))
{
devbufsiz = get.mt_dsreg;
}
if (devbufsiz > 1L)
{
devbuf = new char [ devbufsiz ];
}
/*
* The following rewind in position 0 solves a problem which appears
* in case of multi volume archives: The last ReadFile on first medium
* returns ERROR_NO_DATA_DETECTED. After media change, all subsequent
* ReadFile calls return ERROR_NO_DATA_DETECTED, too!
* The call to tape_set_pos seems to reset some internal flags!
*/
if ((! ioctl (MTIOCPOS, &pos)) && (! pos.mt_blkno))
{
op.mt_op = MTREW;
ioctl (MTIOCTOP, &op);
}
if (flags & O_APPEND)
{
/* In append mode, seek to beginning of next filemark */
op.mt_op = MTFSFM;
op.mt_count = 1;
ioctl (MTIOCTOP, &op);
}
}
return ret;
}
int
fhandler_dev_tape::close (void)
{
struct mtop op;
int ret = 0;
if (is_writing)
{
ret = writebuf ();
if ((has_written) && (! eom_detected))
{
/* if last operation was writing, write a filemark */
debug_printf ("writing filemark\n");
op.mt_op = MTWEOF;
op.mt_count = 1;
ioctl (MTIOCTOP, &op);
}
}
// To protected reads on signaling (e.g. Ctrl-C)
eof_detected = 1;
if (! norewind)
{
debug_printf ("rewinding\n");
op.mt_op = MTREW;
ioctl (MTIOCTOP, &op);
}
if (ret)
{
fhandler_dev_raw::close ();
return ret;
}
return fhandler_dev_raw::close ();
}
int
fhandler_dev_tape::fstat (struct stat *buf)
{
int ret;
if (! (ret = fhandler_dev_raw::fstat (buf)))
{
struct mtget get;
if (! ioctl (MTIOCGET, &get))
{
buf->st_blocks = get.mt_capacity / buf->st_blksize;
}
}
return ret;
}
off_t
fhandler_dev_tape::lseek (off_t offset, int whence)
{
struct mtop op;
struct mtpos pos;
debug_printf ("lseek (%s, %d, %d)\n", get_name (), offset, whence);
writebuf ();
eom_detected = eof_detected = 0;
lastblk_to_read = 0;
devbufstart = devbufend = 0;
if (ioctl (MTIOCPOS, &pos))
{
return (off_t) -1;
}
switch (whence)
{
case SEEK_END:
op.mt_op = MTFSF;
op.mt_count = 1;
if (ioctl (MTIOCTOP, &op))
return -1;
break;
case SEEK_SET:
if (whence == SEEK_SET && offset < 0)
{
set_errno (EINVAL);
return -1;
}
break;
case SEEK_CUR:
break;
default:
set_errno (EINVAL);
return -1;
}
op.mt_op = MTFSR;
op.mt_count = offset / devbufsiz
- (whence == SEEK_SET ? pos.mt_blkno : 0);
if (op.mt_count < 0)
{
op.mt_op = MTBSR;
op.mt_count = -op.mt_count;
}
if (ioctl (MTIOCTOP, &op) || ioctl (MTIOCPOS, &pos))
return -1;
return (pos.mt_blkno * devbufsiz);
}
int
fhandler_dev_tape::dup (fhandler_base *child)
{
fhandler_dev_tape *fhc = (fhandler_dev_tape *) child;
fhc->norewind = norewind;
fhc->lasterr = lasterr;
return fhandler_dev_raw::dup (child);
}
int
fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
{
int ret = NO_ERROR;
unsigned long block;
if (cmd == MTIOCTOP)
{
struct mtop *op = (struct mtop *) buf;
if (! op)
ret = ERROR_INVALID_PARAMETER;
else
switch (op->mt_op)
{
case MTRESET:
break;
case MTFSF:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, op->mt_count);
break;
case MTBSF:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, -op->mt_count);
break;
case MTFSR:
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, op->mt_count);
break;
case MTBSR:
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -op->mt_count);
break;
case MTWEOF:
ret = tape_write_marks (TAPE_FILEMARKS, op->mt_count);
break;
case MTREW:
ret = tape_set_pos (TAPE_REWIND, 0);
break;
case MTOFFL:
ret = tape_prepare (TAPE_UNLOAD);
break;
case MTNOP:
break;
case MTRETEN:
if (! tape_get_feature (TAPE_DRIVE_END_OF_DATA))
{
ret = ERROR_INVALID_PARAMETER;
break;
}
if (! (ret = tape_set_pos (TAPE_REWIND, 0, FALSE)))
{
ret = tape_prepare (TAPE_TENSION);
}
break;
case MTBSFM:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, -op->mt_count, TRUE);
break;
case MTFSFM:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, op->mt_count, TRUE);
break;
case MTEOM:
if (tape_get_feature (TAPE_DRIVE_END_OF_DATA))
{
ret = tape_set_pos (TAPE_SPACE_END_OF_DATA, 0);
}
else
{
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, 32767);
}
break;
case MTERASE:
ret = tape_erase (TAPE_ERASE_SHORT);
break;
case MTRAS1:
case MTRAS2:
case MTRAS3:
ret = ERROR_INVALID_PARAMETER;
break;
case MTSETBLK:
{
long min, max;
if (! tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
{
ret = ERROR_INVALID_PARAMETER;
break;
}
ret = tape_get_blocksize (&min, NULL, &max, NULL);
if (ret)
{
break;
}
if (op->mt_count < min || op->mt_count > max)
{
ret = ERROR_INVALID_PARAMETER;
break;
}
if (devbuf && (size_t) op->mt_count == devbufsiz)
{
ret = 0;
break;
}
if (devbuf && (size_t) op->mt_count < devbufend - devbufstart)
{
ret = ERROR_INVALID_PARAMETER;
break;
}
if (! (ret = tape_set_blocksize (op->mt_count)))
{
char *buf = new char [ op->mt_count ];
if (devbuf)
{
memcpy(buf,devbuf + devbufstart, devbufend - devbufstart);
devbufend -= devbufstart;
delete [] devbuf;
}
else
{
devbufend = 0;
}
devbufstart = 0;
devbuf = buf;
devbufsiz = op->mt_count;
}
}
break;
case MTSETDENSITY:
ret = ERROR_INVALID_PARAMETER;
break;
case MTSEEK:
if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
{
ret = tape_set_pos (TAPE_ABSOLUTE_BLOCK, op->mt_count);
break;
}
if (! (ret = tape_get_pos (&block)))
{
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS,
op->mt_count - block);
}
break;
case MTTELL:
if (! (ret = tape_get_pos (&block)))
op->mt_count = block;
break;
case MTSETDRVBUFFER:
ret = ERROR_INVALID_PARAMETER;
break;
case MTFSS:
ret = tape_set_pos (TAPE_SPACE_SETMARKS, op->mt_count);
break;
case MTBSS:
ret = tape_set_pos (TAPE_SPACE_SETMARKS, -op->mt_count);
break;
case MTWSM:
ret = tape_write_marks (TAPE_SETMARKS, op->mt_count);
break;
case MTLOCK:
ret = tape_prepare (TAPE_LOCK);
break;
case MTUNLOCK:
ret = tape_prepare (TAPE_UNLOCK);
break;
case MTLOAD:
ret = tape_prepare (TAPE_LOAD);
break;
case MTUNLOAD:
ret = tape_prepare (TAPE_UNLOAD);
break;
case MTCOMPRESSION:
ret = tape_compression (op->mt_count);
break;
case MTSETPART:
case MTMKPART:
default:
ret = ERROR_INVALID_PARAMETER;
break;
}
}
else if (cmd == MTIOCGET)
ret = tape_status ((struct mtget *) buf);
else if (cmd == MTIOCPOS)
{
ret = ERROR_INVALID_PARAMETER;
if (buf && (ret = tape_get_pos (&block)))
((struct mtpos *) buf)->mt_blkno = block;
}
else
return fhandler_dev_raw::ioctl (cmd, buf);
if (ret != NO_ERROR)
{
SetLastError (ret);
__seterrno ();
return -1;
}
return 0;
}
/* ------------------------------------------------------------------ */
/* Private functions used by `ioctl' */
/* ------------------------------------------------------------------ */
static int
tape_error (DWORD lasterr, const char *txt)
{
if (lasterr)
debug_printf ("%s: error: %d\n", txt, lasterr);
return lasterr;
}
int
fhandler_dev_tape::tape_write_marks (int marktype, DWORD len)
{
syscall_printf ("write_tapemark\n");
while (((lasterr = WriteTapemark (get_handle (),
marktype,
len,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
return tape_error (lasterr, "tape_write_marks");
}
int
fhandler_dev_tape::tape_get_pos (unsigned long *ret)
{
DWORD part, low, high;
while (((lasterr = GetTapePosition (get_handle (),
TAPE_ABSOLUTE_POSITION,
&part,
&low,
&high)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (! tape_error (lasterr, "tape_get_pos") && ret)
*ret = low;
return lasterr;
}
static int _tape_set_pos (HANDLE hTape, int mode, long count)
{
int err;
while (((err = SetTapePosition (hTape,
mode,
1,
count,
count < 0 ? -1 : 0,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (err == ERROR_BUS_RESET))
;
return err;
}
int
fhandler_dev_tape::tape_set_pos (int mode, long count, BOOLEAN sfm_func)
{
unsigned long pos, tgtpos;
switch (mode)
{
case TAPE_SPACE_RELATIVE_BLOCKS:
lasterr = tape_get_pos (&pos);
if (lasterr)
return lasterr;
tgtpos = pos + count;
while (((lasterr = _tape_set_pos (get_handle (),
mode,
count)) == ERROR_FILEMARK_DETECTED)
|| (lasterr == ERROR_SETMARK_DETECTED))
{
lasterr = tape_get_pos (&pos);
if (lasterr)
return lasterr;
count = tgtpos - pos;
}
if (lasterr == ERROR_BEGINNING_OF_MEDIA && ! tgtpos)
lasterr = NO_ERROR;
break;
case TAPE_SPACE_FILEMARKS:
if (count < 0)
{
if (pos > 0)
{
if ((! _tape_set_pos (get_handle (),
TAPE_SPACE_RELATIVE_BLOCKS,
-1))
|| (sfm_func))
++count;
_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, 1);
}
while (! (lasterr = _tape_set_pos (get_handle (), mode, -1))
&& count++ < 0)
;
if (lasterr == ERROR_BEGINNING_OF_MEDIA)
{
if (! count)
lasterr = NO_ERROR;
}
else if (! sfm_func)
lasterr = _tape_set_pos (get_handle (), mode, 1);
}
else
{
if (sfm_func)
{
if (_tape_set_pos (get_handle (),
TAPE_SPACE_RELATIVE_BLOCKS,
1) == ERROR_FILEMARK_DETECTED)
++count;
_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, -1);
}
if (! (lasterr = _tape_set_pos (get_handle (), mode, count))
&& sfm_func)
lasterr = _tape_set_pos (get_handle (), mode, -1);
}
break;
case TAPE_SPACE_SETMARKS:
case TAPE_ABSOLUTE_BLOCK:
case TAPE_SPACE_END_OF_DATA:
case TAPE_REWIND:
lasterr = _tape_set_pos (get_handle (), mode, count);
break;
}
return tape_error (lasterr, "tape_set_pos");
}
int
fhandler_dev_tape::tape_erase (int mode)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
switch (mode)
{
case TAPE_ERASE_SHORT:
if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_SHORT))
mode = TAPE_ERASE_LONG;
break;
case TAPE_ERASE_LONG:
if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_LONG))
mode = TAPE_ERASE_SHORT;
break;
}
return tape_error (EraseTape (get_handle (), mode, FALSE), "tape_erase");
}
int
fhandler_dev_tape::tape_prepare (int action)
{
while (((lasterr = PrepareTape (get_handle (),
action,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
return tape_error (lasterr, "tape_prepare");
}
BOOLEAN
fhandler_dev_tape::tape_get_feature (DWORD parm)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return FALSE;
return ((parm & TAPE_DRIVE_HIGH_FEATURES)
? ((dp.FeaturesHigh & parm) != 0)
: ((dp.FeaturesLow & parm) != 0));
}
int
fhandler_dev_tape::tape_get_blocksize (long *min, long *def, long *max, long *cur)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
TAPE_GET_MEDIA_PARAMETERS mp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_get_blocksize");
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_MEDIA_INFORMATION,
(varlen = sizeof mp, &varlen),
&mp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_get_blocksize");
if (min)
*min = (long) dp.MinimumBlockSize;
if (def)
*def = (long) dp.DefaultBlockSize;
if (max)
*max = (long) dp.MaximumBlockSize;
if (cur)
*cur = (long) mp.BlockSize;
return tape_error (lasterr, "tape_get_blocksize");
}
int
fhandler_dev_tape::tape_set_blocksize (long count)
{
long min, max;
TAPE_SET_MEDIA_PARAMETERS mp;
lasterr = tape_get_blocksize (&min, NULL, &max, NULL);
if (lasterr)
return lasterr;
if (count < min || count > max)
return tape_error (ERROR_INVALID_PARAMETER, "tape_set_blocksize");
mp.BlockSize = count;
return tape_error (SetTapeParameters (get_handle (),
SET_TAPE_MEDIA_INFORMATION,
&mp),
"tape_set_blocksize");
}
static long long
get_ll (PLARGE_INTEGER i)
{
long long l = 0;
l = i->HighPart;
l <<= 32;
l |= i->LowPart;
return l;
}
int
fhandler_dev_tape::tape_status (struct mtget *get)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
TAPE_GET_MEDIA_PARAMETERS mp;
int notape = 0;
if (! get)
return ERROR_INVALID_PARAMETER;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if ((lasterr) || (lasterr = GetTapeParameters (get_handle (),
GET_TAPE_MEDIA_INFORMATION,
(varlen = sizeof mp, &varlen),
&mp)))
notape = 1;
memset (get, 0, sizeof *get);
get->mt_type = MT_ISUNKNOWN;
if (! notape && (dp.FeaturesLow & TAPE_DRIVE_TAPE_REMAINING))
{
get->mt_remaining = get_ll (&mp.Remaining);
get->mt_resid = get->mt_remaining >> 10;
}
if ((dp.FeaturesHigh & TAPE_DRIVE_SET_BLOCK_SIZE) && ! notape)
get->mt_dsreg = mp.BlockSize;
else
get->mt_dsreg = dp.DefaultBlockSize;
if (notape)
get->mt_gstat |= GMT_DR_OPEN (-1);
if (! notape)
{
if (dp.FeaturesLow & TAPE_DRIVE_GET_ABSOLUTE_BLK)
tape_get_pos ((unsigned long *) &get->mt_blkno);
if (! get->mt_blkno)
get->mt_gstat |= GMT_BOT (-1);
get->mt_gstat |= GMT_ONLINE (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_WRITE_PROTECT) && mp.WriteProtected)
get->mt_gstat |= GMT_WR_PROT (-1);
if (dp.FeaturesLow & TAPE_DRIVE_TAPE_CAPACITY)
get->mt_capacity = get_ll (&mp.Capacity);
}
if ((dp.FeaturesLow & TAPE_DRIVE_COMPRESSION) && dp.Compression)
get->mt_gstat |= GMT_HW_COMP (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_ECC) && dp.ECC)
get->mt_gstat |= GMT_HW_ECC (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_PADDING) && dp.DataPadding)
get->mt_gstat |= GMT_PADDING (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_REPORT_SMKS) && dp.ReportSetmarks)
get->mt_gstat |= GMT_IM_REP_EN (-1);
get->mt_erreg = lasterr;
get->mt_minblksize = dp.MinimumBlockSize;
get->mt_maxblksize = dp.MaximumBlockSize;
get->mt_defblksize = dp.DefaultBlockSize;
get->mt_featureslow = dp.FeaturesLow;
get->mt_featureshigh = dp.FeaturesHigh;
return 0;
}
int
fhandler_dev_tape::tape_compression (long count)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dpg;
TAPE_SET_DRIVE_PARAMETERS dps;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dpg, &varlen),
&dpg)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_compression");
if (! (dpg.FeaturesLow & TAPE_DRIVE_COMPRESSION))
return ERROR_INVALID_PARAMETER;
if (count)
{
dps.ECC = dpg.ECC;
dps.Compression = count ? TRUE : FALSE;
dps.DataPadding = dpg.DataPadding;
dps.ReportSetmarks = dpg.ReportSetmarks;
dps.EOTWarningZoneSize = dpg.EOTWarningZoneSize;
lasterr = SetTapeParameters (get_handle (),
SET_TAPE_DRIVE_INFORMATION,
&dps);
if (lasterr)
return tape_error (lasterr, "tape_compression");
dpg.Compression = dps.Compression;
}
return 0;
}

View File

@ -0,0 +1,293 @@
/* fhandler_termios.cc
Copyright 1996, 1997, 1998 Cygnus Solutions.
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 <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "winsup.h"
#include <ctype.h>
/* Common functions shared by tty/console */
void
fhandler_termios::tcinit (tty_min *this_tc, int force)
{
/* Initial termios values */
tc = this_tc;
if (force || !TTYISSETF (INITIALIZED))
{
tc->ti.c_iflag = BRKINT | ICRNL | IXON;
tc->ti.c_oflag = OPOST | ONLCR;
tc->ti.c_cflag = B38400 | CS8 | CREAD;
tc->ti.c_lflag = ISIG | ICANON | ECHO | IEXTEN;
tc->ti.c_cc[VDISCARD] = CFLUSH;
tc->ti.c_cc[VEOL] = CEOL;
tc->ti.c_cc[VEOL2] = CEOL2;
tc->ti.c_cc[VEOF] = CEOF;
tc->ti.c_cc[VERASE] = CERASE;
tc->ti.c_cc[VINTR] = CINTR;
tc->ti.c_cc[VKILL] = CKILL;
tc->ti.c_cc[VLNEXT] = CLNEXT;
tc->ti.c_cc[VMIN] = 1;
tc->ti.c_cc[VQUIT] = CQUIT;
tc->ti.c_cc[VREPRINT] = CRPRNT;
tc->ti.c_cc[VSTART] = CSTART;
tc->ti.c_cc[VSTOP] = CSTOP;
tc->ti.c_cc[VSUSP] = CSUSP;
tc->ti.c_cc[VSWTC] = CSWTCH;
tc->ti.c_cc[VTIME] = 0;
tc->ti.c_cc[VWERASE] = CWERASE;
tc->ti.c_ispeed = tc->ti.c_ospeed = B38400;
tc->pgid = myself->pgid;
TTYSETF (INITIALIZED);
}
}
int
fhandler_termios::tcsetpgrp (const pid_t pgid)
{
termios_printf ("pgid %d, sid %d, tsid %d", pgid,
myself->sid, tc->getsid ());
if (myself->sid != tc->getsid ())
{
set_errno (EPERM);
return -1;
}
tc->setpgid (pgid);
return 0;
}
int
fhandler_termios::tcgetpgrp ()
{
return tc->pgid;
}
void
fhandler_termios::set_ctty (int ttynum, int flags)
{
if ((myself->ctty < 0 || myself->ctty == ttynum) && !(flags & O_NOCTTY))
{
myself->ctty = ttynum;
syscall_printf ("attached tty%d sid %d, pid %d, tty->pgid %d, tty->sid %d",
ttynum, myself->sid, myself->pid, tc->pgid, tc->getsid ());
pinfo *p = procinfo (tc->getsid ());
if (myself->sid == myself->pid &&
(p == myself || !proc_exists (p)))
{
paranoid_printf ("resetting tty%d sid. Was %d, now %d. pgid was %d, now %d.",
ttynum, tc->getsid(), myself->sid, tc->getpgid (), myself->pgid);
/* We are the session leader */
tc->setsid (myself->sid);
tc->setpgid (myself->pgid);
}
else
myself->sid = tc->getsid ();
if (tc->getpgid () == 0)
tc->setpgid (myself->pgid);
}
}
int
fhandler_termios::bg_check (int sig, int blocksigs)
{
if (!myself->pgid || tc->getpgid () == myself->pgid ||
myself->ctty != tc->ntty ||
((sig == SIGTTOU) && !(tc->ti.c_lflag & TOSTOP)))
return 1;
if (sig < 0)
sig = -sig;
termios_printf("bg I/O pgid %d, tpgid %d, ctty %d",
myself->pgid, tc->getpgid (), myself->ctty);
if (tc->getsid () == 0)
{
/* The pty has been closed by the master. Return an EOF
indication. FIXME: There is nothing to stop somebody
from reallocating this pty. I think this is the case
which is handled by unlockpt on a Unix system. */
termios_printf ("closed by master");
return 0;
}
/* If the process group is no more or if process is ignoring or blocks 'sig',
return with error */
int pgid_gone = !proc_exists (procinfo (myself->pgid));
int sigs_ignored =
((void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN) ||
(myself->getsigmask () & SIGTOMASK (sig));
if (pgid_gone)
goto setEIO;
else if (!sigs_ignored)
/* nothing */;
else if (sig == SIGTTOU)
return 1; /* Just allow the output */
else
goto setEIO; /* This is an output error */
_raise (sig);
return 1;
setEIO:
set_errno (EIO);
return -1;
}
#define set_input_done(x) input_done = input_done || (x)
int
fhandler_termios::line_edit (const char *rptr, int nread, int always_accept)
{
char c;
int input_done = 0;
int iscanon = tc->ti.c_lflag & ICANON;
while (nread-- > 0)
{
c = *rptr++;
termios_printf ("char %c", c);
/* Check for special chars */
if (c == '\r')
{
if (tc->ti.c_iflag & IGNCR)
continue;
if (tc->ti.c_iflag & ICRNL)
{
c = '\n';
set_input_done (iscanon);
}
}
else if (c == '\n')
{
if (tc->ti.c_iflag & INLCR)
c = '\r';
else
set_input_done (iscanon);
}
if (tc->ti.c_iflag & ISTRIP)
c &= 0x7f;
if (tc->ti.c_lflag & ISIG)
{
int sig;
if (c == tc->ti.c_cc[VINTR])
sig = SIGINT;
else if (c == tc->ti.c_cc[VQUIT])
sig = SIGQUIT;
else if (c == tc->ti.c_cc[VSUSP])
sig = SIGTSTP;
else
goto not_a_sig;
termios_printf ("got interrupt %d, sending signal %d", c, sig);
kill_pgrp (tc->getpgid (), sig);
tc->ti.c_lflag &= ~FLUSHO;
goto restart_output;
}
not_a_sig:
if (tc->ti.c_iflag & IXON)
{
if (c == tc->ti.c_cc[VSTOP])
{
tc->OutputStopped++;
continue;
}
else if (c == tc->ti.c_cc[VSTART])
{
restart_output:
tc->OutputStopped = 0;
SetEvent (restart_output_event);
continue;
}
else if ((tc->ti.c_iflag & IXANY) && tc->OutputStopped)
goto restart_output;
}
if (tc->ti.c_lflag & IEXTEN && c == tc->ti.c_cc[VDISCARD])
{
tc->ti.c_lflag ^= FLUSHO;
continue;
}
if (!iscanon)
/* nothing */;
else if (c == tc->ti.c_cc[VERASE])
{
if (eat_readahead (1))
doecho ("\b \b", 3);
continue;
}
else if (c == tc->ti.c_cc[VWERASE])
{
int ch;
do
if (!eat_readahead (1))
break;
else
doecho ("\b \b", 3);
while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
continue;
}
else if (c == tc->ti.c_cc[VKILL])
{
int nchars = eat_readahead (-1);
while (nchars--)
doecho ("\b \b", 3);
continue;
}
else if (c == tc->ti.c_cc[VREPRINT])
{
doecho ("\n\r", 2);
doecho (rabuf, ralen);
continue;
}
else if (c == tc->ti.c_cc[VEOF])
{
termios_printf ("EOF");
input_done = 1;
continue;
}
else if (c == tc->ti.c_cc[VEOL] ||
c == tc->ti.c_cc[VEOL2] ||
c == '\n')
{
set_input_done (1);
termios_printf ("EOL");
}
if (tc->ti.c_iflag & IUCLC && isupper (c))
c = tolower (c);
if (tc->ti.c_lflag & ECHO)
doecho (&c, 1);
put_readahead (c);
}
if (!iscanon || always_accept)
set_input_done (ralen > 0);
/* FIXME: It's not clear that this code will ever do anything.
Currently, it doesn't look like accept_input will ever return
a negative number. */
if (input_done)
(void) accept_input ();
return input_done;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,145 @@
/* fhandler_windows.cc: code to access windows message queues.
Copyright 1998 Cygnus Solutions.
Written by Sergey S. Okhapkin (sos@prospect.com.ru).
Feedback and testing by Andy Piper (andyp@parallax.co.uk).
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <errno.h>
#include "winsup.h"
/*
The following unix-style calls are supported:
open ("/dev/windows", flags, mode=0)
- create a unix fd for message queue.
O_NONBLOCK flag controls the read() call behavior.
read (fd, buf, len)
- return next message from queue. buf must point to MSG
structure, len must be >= sizeof (MSG). If read is set to
non-blocking and the queue is empty, read call returns -1
immediately with errno set to EAGAIN, otherwise it blocks
untill the message will be received.
write (fd, buf, len)
- send a message pointed by buf. len argument ignored.
ioctl (fd, command, *param)
- control read()/write() behavior.
ioctl (fd, WINDOWS_POST, NULL): write() will PostMessage();
ioctl (fd, WINDOWS_SEND, NULL): write() will SendMessage();
ioctl (fd, WINDOWS_HWND, &hWnd): read() messages for
hWnd window.
select () call marks read fd when any message posted to queue.
*/
fhandler_windows::fhandler_windows (const char *name) :
fhandler_base (FH_WINDOWS, name)
{
set_cb (sizeof *this);
hWnd_ = NULL;
method_ = WINDOWS_POST;
}
int
fhandler_windows::open (const char *, int flags, mode_t)
{
set_flags (flags);
set_close_on_exec_flag (1);
return 1;
}
int
fhandler_windows::write (const void *buf, size_t)
{
MSG *ptr = (MSG *) buf;
if (method_ == WINDOWS_POST)
{
if (!PostMessage (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam))
{
__seterrno ();
return -1;
}
else
return sizeof (MSG);
}
else
return SendMessage (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam);
}
int
fhandler_windows::read (void *buf, size_t len)
{
MSG *ptr = (MSG *) buf;
int ret;
if (len < sizeof (MSG))
{
set_errno (EINVAL);
return -1;
}
ret = GetMessage (ptr, hWnd_, 0, 0);
if (ret == -1)
{
__seterrno ();
}
set_errno (0);
return ret;
}
int
fhandler_windows::ioctl (unsigned int cmd, void *val)
{
switch (cmd)
{
case WINDOWS_POST:
case WINDOWS_SEND:
method_ = cmd;
break;
case WINDOWS_HWND:
if (val == NULL)
{
set_errno (EINVAL);
return -1;
}
hWnd_ = * ((HWND *) val);
break;
default:
set_errno (EINVAL);
return -1;
}
return 0;
}
void
fhandler_windows::set_close_on_exec (int val)
{
if (get_handle ())
this->fhandler_base::set_close_on_exec (val);
else
this->fhandler_base::set_close_on_exec_flag (val);
void *h = hWnd_;
if (h)
set_inheritance (h, val);
}
void
fhandler_windows::fixup_after_fork (HANDLE parent)
{
if (get_handle ())
this->fhandler_base::fixup_after_fork (parent);
void *h = hWnd_;
if (h)
fork_fixup (parent, h, "hWnd_");
}

View File

@ -0,0 +1,58 @@
/* fhandler_dev_zero.cc: code to access /dev/zero
Copyright 2000 Cygnus Solutions.
Written by DJ Delorie (dj@cygnus.com)
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <errno.h>
#include "winsup.h"
fhandler_dev_zero::fhandler_dev_zero (const char *name)
: fhandler_base (FH_ZERO, name)
{
set_cb (sizeof *this);
}
int
fhandler_dev_zero::open (const char *path, int flags, mode_t mode = 0)
{
set_flags (flags);
return 1;
}
int
fhandler_dev_zero::write (const void *ptr, size_t len)
{
return len;
}
int
fhandler_dev_zero::read (void *ptr, size_t len)
{
memset(ptr, 0, len);
return len;
}
off_t
fhandler_dev_zero::lseek (off_t offset, int whence)
{
return 0;
}
int
fhandler_dev_zero::close (void)
{
return 0;
}
void
fhandler_dev_zero::dump ()
{
paranoid_printf("here, fhandler_dev_zero");
}

625
winsup/cygwin/fork.cc Normal file
View File

@ -0,0 +1,625 @@
/* fork.cc
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include "winsup.h"
#include "dll_init.h"
DWORD chunksize = 0;
/* Timeout to wait for child to start, parent to init child, etc. */
/* FIXME: Once things stabilize, bump up to a few minutes. */
#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
#define dll_data_start &_data_start__
#define dll_data_end &_data_end__
#define dll_bss_start &_bss_start__
#define dll_bss_end &_bss_end__
void
per_thread::set (void *s)
{
if (s == PER_THREAD_FORK_CLEAR)
{
tls = TlsAlloc ();
s = NULL;
}
TlsSetValue (get_tls (), s);
}
static void
stack_base (child_info_fork &ch)
{
MEMORY_BASIC_INFORMATION m;
memset (&m, 0, sizeof m);
if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
ch.stacktop = m.AllocationBase;
ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
ch.stackbottom, ch.stacktop, &m, ch.stacksize,
(DWORD) ch.stackbottom - (DWORD) ch.stacktop);
}
/* Copy memory from parent to child.
The result is a boolean indicating success. */
static int
fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
{
va_list args;
char *low;
int pass = 0;
va_start (args, what);
while ((low = va_arg (args, char *)))
{
char *high = va_arg (args, char *);
DWORD todo = chunksize ?: high - low;
char *here;
for (here = low; here < high; here += todo)
{
DWORD done = 0;
if (here + todo > high)
todo = high - here;
int res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
low, high, res);
if (!res || todo != done)
{
if (!res)
__seterrno ();
/* If this happens then there is a bug in our fork
implementation somewhere. */
system_printf ("%s pass %d failed, %p..%p, done %d, %E",
what, pass, low, high, done);
goto err;
}
}
pass++;
}
debug_printf ("done");
return 1;
err:
TerminateProcess (pi.hProcess, 1);
set_errno (EAGAIN);
return 0;
}
/* Wait for child to finish what it's doing and signal us.
We don't want to wait forever here.If there's a problem somewhere
it'll hang the entire system (since all forks are mutex'd). If we
time out, set errno = EAGAIN and hope the app tries again. */
static int
sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
BOOL hang_child, const char *s)
{
/* We also add the child process handle to the wait. If the child fails
to initialize (eg. because of a missing dll). Then this
handle will become signalled. This stops a *looong* timeout wait.
*/
HANDLE w4[2];
debug_printf ("waiting for child. reason: %s", s);
w4[1] = pi.hProcess;
w4[0] = subproc_ready;
DWORD rc = WaitForMultipleObjects (2, w4, FALSE, FORK_WAIT_TIMEOUT);
if (rc == WAIT_OBJECT_0 ||
WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
/* That's ok */;
else if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
{
if (rc != WAIT_FAILED)
system_printf ("WaitForMultipleObjects timed out");
else
system_printf ("WaitForMultipleObjects failed, %E");
set_errno (EAGAIN);
syscall_printf ("-1 = fork(), WaitForMultipleObjects failed");
TerminateProcess (pi.hProcess, 1);
return 0;
}
else
{
/* Child died. Clean up and exit. */
DWORD errcode;
GetExitCodeProcess (pi.hProcess, &errcode);
/* Fix me. This is not enough. The fork should not be considered
* to have failed if the process was essentially killed by a signal.
*/
if (errcode != STATUS_CONTROL_C_EXIT)
{
system_printf ("child %d(%p) died before initialization with status code %p",
pi.dwProcessId, pi.hProcess, errcode);
system_printf ("*** child state %s", s);
#ifdef DEBUGGING
abort ();
#endif
}
set_errno (EAGAIN);
syscall_printf ("Child died before subproc_ready signalled");
return 0;
}
debug_printf ("child signalled me");
if (hang_child)
{
int n = SuspendThread (pi.hThread);
debug_printf ("suspend count %d", n); \
}
return 1;
}
static int
resume_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
HANDLE forker_finished)
{
int rc;
debug_printf ("here");
SetEvent (forker_finished);
rc = ResumeThread (pi.hThread);
debug_printf ("rc %d", rc);
if (rc == 1)
return 1; // Successful resumption
/* Can't resume the thread. Not sure why this would happen unless
there's a bug in the system. Things seem to be working OK now
though, so flag this with EAGAIN, but print a message on the
console. */
small_printf ("fork: ResumeThread failed, rc = %d, %E\n", rc);
set_errno (EAGAIN);
syscall_printf ("-1 = fork(), ResumeThread failed");
TerminateProcess (pi.hProcess, 1);
return 0;
}
/* Notify parent that it is time for the next step.
Note that this has to be a macro since the parent may be messing with
our stack. */
#define sync_with_parent(s, hang_self) \
((void) ({ \
debug_printf ("signalling parent: %s", s); \
/* Tell our parent we're waiting. */ \
if (!SetEvent (child_proc_info->subproc_ready)) \
api_fatal ("fork child - SetEvent failed, %E"); \
if (hang_self) \
{ \
/* Wait for the parent to fill in our stack and heap. \
Don't wait forever here. If our parent dies we don't want to clog \
the system. If the wait fails, we really can't continue so exit. */ \
DWORD psync_rc = WaitForSingleObject (child_proc_info->forker_finished, FORK_WAIT_TIMEOUT); \
switch (psync_rc) \
{ \
case WAIT_TIMEOUT: \
api_fatal ("sync_with_parent - WFSO timed out"); \
break; \
case WAIT_FAILED: \
if (GetLastError () == ERROR_INVALID_HANDLE && \
WaitForSingleObject (child_proc_info->forker_finished, 1) != WAIT_FAILED) \
break; \
api_fatal ("sync_with_parent - WFSO failed, fork_finished %p, %E", child_proc_info->forker_finished); \
break; \
default: \
break; \
} \
debug_printf ("awake"); \
} \
0; \
}))
static volatile void grow_stack_slack();
static void *
stack_dummy (int here)
{
return &here;
}
extern "C" int
fork ()
{
int res;
DWORD rc;
HANDLE hParent;
pinfo *child;
HANDLE subproc_ready, forker_finished;
void *stack_here;
int x;
PROCESS_INFORMATION pi = {0};
MALLOC_CHECK;
/* FIXME: something is broken when copying the stack from the parent
to the child; we try various tricks here to make sure that the
stack is good enough to prevent page faults, but the true cause
is still unknown. DJ */
volatile char dummy[4096];
dummy[0] = dummy[4095] = 0; // Just to leave some slack in the stack
grow_stack_slack ();
debug_printf ("entering");
/* Calculate how much of stack to copy to child */
stack_here = stack_dummy (0);
if (ISSTATE(myself, PID_SPLIT_HEAP))
{
system_printf ("The heap has been split, CYGWIN can't fork this process.");
system_printf ("Increase the heap_chunk_size in the registry and try again.");
set_errno (ENOMEM);
syscall_printf ("-1 = fork (), split heap");
return -1;
}
/* Don't start the fork until we have the lock. */
child = cygwin_shared->p.allocate_pid ();
if (!child)
{
set_errno (EAGAIN);
syscall_printf ("-1 = fork (), process table full");
return -1;
}
static child_info_fork ch;
x = setjmp (ch.jmp);
if (x == 0)
{
/* This will help some of the confusion. */
fflush (stdout);
debug_printf ("parent pid %d, child pid %d", myself->pid, child->pid);
subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
ProtectHandle (subproc_ready);
ProtectHandle (forker_finished);
/* If we didn't obtain all the resources we need to fork, allow the program
to continue, but record the fact that fork won't work. */
if (forker_finished == NULL || subproc_ready == NULL)
{
system_printf ("unable to allocate fork() resources.");
system_printf ("fork() disabled.");
return -1;
}
subproc_init ();
debug_printf ("about to call setjmp");
/* Parent. */
#ifdef DEBUGGING
/* The ProtectHandle call allocates memory so we need to make sure
that enough is set aside here so that the sbrk pointer does not
move when ProtectHandle is called after the child is started.
Otherwise the sbrk pointers in the parent will not agree with
the child and when user_data is (regrettably) copied over,
the user_data->ptr field will not be accurate. */
free (malloc (4096));
#endif
init_child_info (PROC_FORK1, &ch, child->pid, subproc_ready);
ch.forker_finished = forker_finished;
ch.heaptop = user_data->heaptop;
ch.heapbase = user_data->heapbase;
ch.heapptr = user_data->heapptr;
stack_base (ch);
/* Initialize things that are done later in dll_crt0_1 that aren't done
for the forkee. */
strcpy(child->progname, myself->progname);
STARTUPINFO si = {0};
si.cb = sizeof (STARTUPINFO);
si.lpReserved2 = (LPBYTE)&ch;
si.cbReserved2 = sizeof(ch);
int c_flags = GetPriorityClass (hMainProc) /*|
CREATE_NEW_PROCESS_GROUP*/;
/* If we don't have a console, then don't create a console for the
child either. */
HANDLE console_handle = CreateFileA ("CONOUT$", GENERIC_WRITE,
FILE_SHARE_WRITE, &sec_none_nih,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
syscall_printf ("CreateProcessA (%s, %s,0,0,1,%x, 0,0,%p,%p)",
myself->progname, myself->progname, c_flags, &si, &pi);
if (console_handle != INVALID_HANDLE_VALUE && console_handle != 0)
CloseHandle (console_handle);
else
c_flags |= DETACHED_PROCESS;
hParent = NULL;
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
DUPLICATE_SAME_ACCESS))
{
system_printf ("couldn't create handle to myself for child, %E");
goto cleanup;
}
rc = CreateProcessA (myself->progname, /* image to run */
myself->progname, /* what we send in arg0 */
&sec_none_nih, /* process security attrs */
&sec_none_nih, /* thread security attrs */
TRUE, /* inherit handles from parent */
c_flags,
NULL, /* environment filled in later */
0, /* use current drive/directory */
&si,
&pi);
CloseHandle (hParent);
if (!rc)
{
__seterrno ();
syscall_printf ("-1 = fork(), CreateProcessA failed");
child->process_state = PID_NOT_IN_USE;
ForceCloseHandle(subproc_ready);
ForceCloseHandle(forker_finished);
subproc_ready = forker_finished = NULL;
return -1;
}
ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will
be called in subproc handling. */
ProtectHandle1 (pi.hProcess, childhProc);
/* Fill in fields in the child's process table entry. */
child->ppid = myself->pid;
child->hProcess = pi.hProcess;
child->dwProcessId = pi.dwProcessId;
child->uid = myself->uid;
child->gid = myself->gid;
child->pgid = myself->pgid;
child->sid = myself->sid;
child->ctty = myself->ctty;
child->umask = myself->umask;
child->copysigs(myself);
child->process_state |= PID_INITIALIZING |
(myself->process_state & PID_USETTY);
memcpy (child->username, myself->username, MAX_USER_NAME);
child->psid = myself->psid;
memcpy (child->sidbuf, myself->sidbuf, 40);
memcpy (child->logsrv, myself->logsrv, 256);
memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
set_child_mmap_ptr (child);
/* Wait for subproc to initialize itself. */
if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp"))
goto cleanup;
/* CHILD IS STOPPED */
debug_printf ("child is alive (but stopped)");
/* Initialize, in order: data, bss, heap, stack, dll data, dll bss
Note: variables marked as NO_COPY will not be copied
since they are placed in a protected segment. */
MALLOC_CHECK;
rc = fork_copy (pi, "user/cygwin data",
user_data->data_start, user_data->data_end,
user_data->bss_start, user_data->bss_end,
ch.heapbase, ch.heapptr,
stack_here, ch.stackbottom,
dll_data_start, dll_data_end,
dll_bss_start, dll_bss_end, NULL);
MALLOC_CHECK;
if (!rc)
goto cleanup;
/* Now fill data/bss of linked dll */
DO_LINKED_DLL (p)
{
debug_printf ("copying data/bss of a linked dll");
if (!fork_copy (pi, "linked dll data/bss", p->data_start, p->data_end,
p->bss_start, p->bss_end,
NULL))
goto cleanup;
}
DLL_DONE;
proc_register (child);
int load_dll = DllList::the().forkeeMustReloadDlls() &&
DllList::the().numberOfOpenedDlls();
/* Start thread, and wait for it to reload dlls. */
if (!resume_child (pi, subproc_ready, forker_finished) ||
!sync_with_child (pi, subproc_ready, load_dll, "child loading dlls"))
goto cleanup;
/* child reload dlls & then write their data and bss */
if (load_dll)
{
/* CHILD IS STOPPED */
/* write memory of reloaded dlls */
DO_LOADED_DLL (p)
{
debug_printf ("copying data/bss for a loaded dll");
if (!fork_copy (pi, "loaded dll data/bss", p->data_start, p->data_end,
p->bss_start, p->bss_end,
NULL))
goto cleanup;
}
DLL_DONE;
/* Start the child up again. */
(void) resume_child (pi, subproc_ready, forker_finished);
}
ForceCloseHandle (subproc_ready);
ForceCloseHandle (pi.hThread);
ForceCloseHandle (forker_finished);
forker_finished = NULL;
pi.hThread = NULL;
res = child->pid;
}
else
{
/**** Child *****/
/* We arrive here via a longjmp from "crt0". */
(void) stack_dummy (0); // Just to make sure
debug_printf ("child is running %d", x);
debug_printf ("self %p, pid %d, ppid %d",
myself, x, myself ? myself->ppid : -1);
sync_with_parent ("after longjmp.", TRUE);
ProtectHandle (hParent);
#ifdef DEBUGGING
char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
try_to_debug ();
#endif
/* If we've played with the stack, stacksize != 0. That means that
fork() was invoked from other than the main thread. Make sure that
when the "main" thread exits it calls do_exit, like a normal process.
Exit with a status code of 0. */
if (child_proc_info->stacksize)
{
((DWORD *)child_proc_info->stackbottom)[-17] = (DWORD)do_exit;
((DWORD *)child_proc_info->stackbottom)[-15] = (DWORD)0;
}
MALLOC_CHECK;
dtable.fixup_after_fork (hParent);
ForceCloseHandle (hParent);
MALLOC_CHECK;
/* reload dlls if necessary */
if (!DllList::the().forkeeMustReloadDlls() ||
!DllList::the().numberOfOpenedDlls())
sync_with_parent ("performed fork fixup.", FALSE);
else
{
DllList::the().forkeeLoadDlls();
sync_with_parent ("loaded dlls", TRUE);
}
(void) ForceCloseHandle (child_proc_info->subproc_ready);
(void) ForceCloseHandle (child_proc_info->forker_finished);
if (recreate_mmaps_after_fork (myself->mmap_ptr))
api_fatal ("recreate_mmaps_after_fork_failed");
res = 0;
/* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
non-zero, for some reason.
FIXME: There is a memory leak here after a fork. */
for (per_thread **t = threadstuff; *t; t++)
if ((*t)->clear_on_fork ())
(*t)->set ();
/* Initialize signal/process handling */
sigproc_init ();
}
MALLOC_CHECK;
syscall_printf ("%d = fork()", res);
return res;
/* Common cleanup code for failure cases */
cleanup:
/* Remember to de-allocate the fd table. */
child->process_state = PID_NOT_IN_USE;
if (pi.hProcess)
ForceCloseHandle1 (pi.hProcess, childhProc);
if (pi.hThread)
ForceCloseHandle (pi.hThread);
if (subproc_ready)
ForceCloseHandle (subproc_ready);
if (forker_finished)
ForceCloseHandle (forker_finished);
forker_finished = subproc_ready = child->hProcess = NULL;
return -1;
}
static volatile void
grow_stack_slack ()
{
volatile char dummy[16384];
dummy[0] = dummy[16383] = 0; // Just to make some slack in the stack
}
#ifdef NEWVFORK
/* Dummy function to force second assignment below to actually be
carried out */
static vfork_save *
get_vfork_val ()
{
return vfork_storage.val ();
}
#endif
extern "C"
int
vfork ()
{
#ifndef NEWVFORK
return fork ();
#else
vfork_save *vf = get_vfork_val ();
if (vf == NULL)
vf = vfork_storage.create ();
if (!setjmp (vf->j))
{
vf->pid = -1;
__asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
__asm__ volatile ("movl (%%ebp),%0": "=r" (vf->caller_ebp):);
__asm__ volatile ("movl 4(%%ebp),%0": "=r" (vf->retaddr):);
return dtable.vfork_child_dup () ? 0 : -1;
}
dtable.vfork_parent_restore ();
vf = get_vfork_val ();
if (vf->pid < 0)
{
int exitval = -vf->pid;
if ((vf->pid = fork ()) == 0)
exit (exitval);
}
vf->vfork_ebp[0] = vf->caller_ebp;
vf->vfork_ebp[1] = vf->retaddr;
return vf->pid;
#endif
}

41
winsup/cygwin/gcrt0.c Normal file
View File

@ -0,0 +1,41 @@
/* gcrt0.c
Copyright 1998 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <sys/types.h>
#include <stdlib.h>
extern u_char etext asm ("etext");
extern u_char eprol asm ("__eprol");
extern void _mcleanup (void);
extern void monstartup (u_long, u_long);
void _monstartup (void) __attribute__((__constructor__));
/* startup initialization for -pg support */
void
_monstartup (void)
{
static int called;
/* Guard against multiple calls that may happen if DLLs are linked
with profile option set as well. Addede side benefit is that it
makes profiling backward compatible (GCC used to emit a call to
_monstartup when compiling main with profiling enabled). */
if (called++)
return;
monstartup ((u_long) &eprol, (u_long) &etext);
atexit (&_mcleanup);
}
asm (".text");
asm ("__eprol:");

871
winsup/cygwin/glob.c Normal file
View File

@ -0,0 +1,871 @@
/* $NetBSD: __glob13.c,v 1.1.2.1 1997/10/22 06:41:27 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
/*
* glob(3) -- a superset of the one defined in POSIX 1003.2.
*
* The [!...] convention to negate a range is supported (SysV, Posix, ksh).
*
* Optional extra services, controlled by flags not defined by POSIX:
*
* GLOB_QUOTE:
* Escaping convention: \ inhibits any special meaning the following
* character might have (except \ at end of string is retained).
* GLOB_MAGCHAR:
* Set in gl_flags if pattern contained a globbing character.
* GLOB_NOMAGIC:
* Same as GLOB_NOCHECK, but it will only append pattern if it did
* not contain any magic characters. [Used in csh style globbing]
* GLOB_ALTDIRFUNC:
* Use alternately specified directory access functions.
* GLOB_TILDE:
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
* expand {1,2}{a,b} to 1a 1b 2a 2b
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
/* CYGNUS LOCAL: don't include */
/* #include "namespace.h" */
/* end CYGNUS LOCAL */
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <glob.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __weak_alias
#ifdef __LIBC12_SOURCE__
__weak_alias(glob,_glob);
__weak_alias(globfree,_globfree);
#else
#error "XXX THESE ARE NOT RIGHT!"
__weak_alias(__glob13,___glob13);
__weak_alias(__globfree13,___globfree13);
#endif /* __LIBC12_SOURCE__ */
#endif /* __weak_alias */
#ifdef __LIBC12_SOURCE__
#define STAT stat12
#else
#define STAT stat
#endif
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
#define LBRACKET '['
#define NOT '!'
#define QUESTION '?'
#define QUOTE '\\'
#define RANGE '-'
#define RBRACKET ']'
#define SEP '/'
#define STAR '*'
#define TILDE '~'
#define UNDERSCORE '_'
#define LBRACE '{'
#define RBRACE '}'
#define SLASH '/'
#define COMMA ','
#ifndef DEBUG
#define M_QUOTE 0x8000
#define M_PROTECT 0x4000
#define M_MASK 0xffff
#define M_ASCII 0x00ff
typedef u_short Char;
#else
#define M_QUOTE 0x80
#define M_PROTECT 0x40
#define M_MASK 0xff
#define M_ASCII 0x7f
typedef char Char;
#endif
#define CHAR(c) ((Char)((c)&M_ASCII))
#define META(c) ((Char)((c)|M_QUOTE))
#define M_ALL META('*')
#define M_END META(']')
#define M_NOT META('!')
#define M_ONE META('?')
#define M_RNG META('-')
#define M_SET META('[')
#define ismeta(c) (((c)&M_QUOTE) != 0)
static int compare __P((const void *, const void *));
static void g_Ctoc __P((const Char *, char *));
static int g_lstat __P((Char *, struct STAT *, glob_t *));
static DIR *g_opendir __P((Char *, glob_t *));
static Char *g_strchr __P((Char *, int));
#ifdef notdef
static Char *g_strcat __P((Char *, const Char *));
#endif
static int g_stat __P((Char *, struct STAT *, glob_t *));
static int glob0 __P((const Char *, glob_t *));
static int glob1 __P((Char *, glob_t *));
static int glob2 __P((Char *, Char *, Char *, glob_t *));
static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
static int globextend __P((const Char *, glob_t *));
static const Char * globtilde __P((const Char *, Char *, glob_t *));
static int globexp1 __P((const Char *, glob_t *));
static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
static int match __P((Char *, Char *, Char *));
#ifdef DEBUG
static void qprintf __P((const char *, Char *));
#endif
#undef MAXPATHLEN
#define MAXPATHLEN 16384
int
glob(pattern, flags, errfunc, pglob)
const char *pattern;
int flags, (*errfunc) __P((const char *, int));
glob_t *pglob;
{
const u_char *patnext;
int c;
Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
patnext = (u_char *) pattern;
if (!(flags & GLOB_APPEND)) {
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
if (!(flags & GLOB_DOOFFS))
pglob->gl_offs = 0;
}
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
pglob->gl_errfunc = errfunc;
pglob->gl_matchc = 0;
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN;
if (flags & GLOB_QUOTE) {
/* Protect the quoted characters. */
while (bufnext < bufend && (c = *patnext++) != EOS)
if (c == QUOTE) {
if ((c = *patnext++) == EOS) {
c = QUOTE;
--patnext;
}
*bufnext++ = c | M_PROTECT;
}
else
*bufnext++ = c;
}
else
while (bufnext < bufend && (c = *patnext++) != EOS)
*bufnext++ = c;
*bufnext = EOS;
if (flags & GLOB_BRACE)
return globexp1(patbuf, pglob);
else
return glob0(patbuf, pglob);
}
/*
* Expand recursively a glob {} pattern. When there is no more expansion
* invoke the standard globbing routine to glob the rest of the magic
* characters
*/
static int globexp1(pattern, pglob)
const Char *pattern;
glob_t *pglob;
{
const Char* ptr = pattern;
int rv;
/* Protect a single {}, for find(1), like csh */
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
return glob0(pattern, pglob);
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
if (!globexp2(ptr, pattern, pglob, &rv))
return rv;
return glob0(pattern, pglob);
}
/*
* Recursive brace globbing helper. Tries to expand a single brace.
* If it succeeds then it invokes globexp1 with the new pattern.
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int globexp2(ptr, pattern, pglob, rv)
const Char *ptr, *pattern;
glob_t *pglob;
int *rv;
{
int i;
Char *lm, *ls;
const Char *pe, *pm, *pl;
Char patbuf[MAXPATHLEN + 1];
/* copy part up to the brace */
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
continue;
ls = lm;
/* Find the balanced brace */
for (i = 0, pe = ++ptr; *pe; pe++)
if (*pe == LBRACKET) {
/* Ignore everything between [] */
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
continue;
if (*pe == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pe = pm;
}
}
else if (*pe == LBRACE)
i++;
else if (*pe == RBRACE) {
if (i == 0)
break;
i--;
}
/* Non matching braces; just glob the pattern */
if (i != 0 || *pe == EOS) {
*rv = glob0(patbuf, pglob);
return 0;
}
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
switch (*pm) {
case LBRACKET:
/* Ignore everything between [] */
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
continue;
if (*pm == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pm = pl;
}
break;
case LBRACE:
i++;
break;
case RBRACE:
if (i) {
i--;
break;
}
/* FALLTHROUGH */
case COMMA:
if (i && *pm == COMMA)
break;
else {
/* Append the current string */
for (lm = ls; (pl < pm); *lm++ = *pl++)
continue;
/*
* Append the rest of the pattern after the
* closing brace
*/
for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
continue;
/* Expand the current pattern */
#ifdef DEBUG
qprintf("globexp2:", patbuf);
#endif
*rv = globexp1(patbuf, pglob);
/* move after the comma, to the next string */
pl = pm + 1;
}
break;
default:
break;
}
*rv = 0;
return 0;
}
/*
* expand tilde from the passwd file.
*/
static const Char *
globtilde(pattern, patbuf, pglob)
const Char *pattern;
Char *patbuf;
glob_t *pglob;
{
struct passwd *pwd;
char *h;
const Char *p;
Char *b;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
/* Copy up to the end of the string or / */
for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
*h++ = *p++)
continue;
*h = EOS;
if (((char *) patbuf)[0] == EOS) {
/*
* handle a plain ~ or ~/ by expanding $HOME
* first and then trying the password file
*/
if ((h = getenv("HOME")) == NULL) {
if ((pwd = getpwuid(getuid())) == NULL)
return pattern;
else
h = pwd->pw_dir;
}
}
else {
/*
* Expand a ~user
*/
if ((pwd = getpwnam((char*) patbuf)) == NULL)
return pattern;
else
h = pwd->pw_dir;
}
/* Copy the home directory */
for (b = patbuf; *h; *b++ = *h++)
continue;
/* Append the rest of the pattern */
while ((*b++ = *p++) != EOS)
continue;
return patbuf;
}
/*
* The main glob() routine: compiles the pattern (optionally processing
* quotes), calls glob1() to do the real pattern matching, and finally
* sorts the list (unless unsorted operation is requested). Returns 0
* if things went well, nonzero if errors occurred. It is not an error
* to find no matches.
*/
static int
glob0(pattern, pglob)
const Char *pattern;
glob_t *pglob;
{
const Char *qpatnext;
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN+1];
qpatnext = globtilde(pattern, patbuf, pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
/* We don't need to check for buffer overflow any more. */
while ((c = *qpatnext++) != EOS) {
switch (c) {
case LBRACKET:
c = *qpatnext;
if (c == NOT)
++qpatnext;
if (*qpatnext == EOS ||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET;
if (c == NOT)
--qpatnext;
break;
}
*bufnext++ = M_SET;
if (c == NOT)
*bufnext++ = M_NOT;
c = *qpatnext++;
do {
*bufnext++ = CHAR(c);
if (*qpatnext == RANGE &&
(c = qpatnext[1]) != RBRACKET) {
*bufnext++ = M_RNG;
*bufnext++ = CHAR(c);
qpatnext += 2;
}
} while ((c = *qpatnext++) != RBRACKET);
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_END;
break;
case QUESTION:
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_ONE;
break;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
/* collapse adjacent stars to one,
* to avoid exponential behavior
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
*bufnext++ = M_ALL;
break;
default:
*bufnext++ = CHAR(c);
break;
}
}
*bufnext = EOS;
#ifdef DEBUG
qprintf("glob0:", patbuf);
#endif
if ((err = glob1(patbuf, pglob)) != 0)
return(err);
/*
* If there was no match we are going to append the pattern
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
* and the pattern did not contain any magic characters
* GLOB_NOMAGIC is there just for compatibility with csh.
*/
if (pglob->gl_pathc == oldpathc &&
((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR))))
return(globextend(pattern, pglob));
else if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
return(0);
}
static int
compare(p, q)
const void *p, *q;
{
return(strcmp(*(char **)p, *(char **)q));
}
static int
glob1(pattern, pglob)
Char *pattern;
glob_t *pglob;
{
Char pathbuf[MAXPATHLEN+1];
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
return(0);
return(glob2(pathbuf, pathbuf, pattern, pglob));
}
/*
* The functions glob2 and glob3 are mutually recursive; there is one level
* of recursion for each segment in the pattern that contains one or more
* meta characters.
*/
static int
glob2(pathbuf, pathend, pattern, pglob)
Char *pathbuf, *pathend, *pattern;
glob_t *pglob;
{
struct STAT sb;
Char *p, *q;
int anymeta;
/*
* Loop over pattern segments until end of pattern or until
* segment with meta character found.
*/
for (anymeta = 0;;) {
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob))
return(0);
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
|| (S_ISLNK(sb.st_mode) &&
(g_stat(pathbuf, &sb, pglob) == 0) &&
S_ISDIR(sb.st_mode)))) {
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
return(globextend(pathbuf, pglob));
}
/* Find end of next segment, copy tentatively to pathend. */
q = pathend;
p = pattern;
while (*p != EOS && *p != SEP) {
if (ismeta(*p))
anymeta = 1;
*q++ = *p++;
}
if (!anymeta) { /* No expansion, do next segment. */
pathend = q;
pattern = p;
while (*pattern == SEP)
*pathend++ = *pattern++;
} else /* Need expansion, recurse. */
return(glob3(pathbuf, pathend, pattern, p, pglob));
}
/* NOTREACHED */
}
static int
glob3(pathbuf, pathend, pattern, restpattern, pglob)
Char *pathbuf, *pathend, *pattern, *restpattern;
glob_t *pglob;
{
register struct dirent *dp;
DIR *dirp;
int err;
char buf[MAXPATHLEN];
/*
* The readdirfunc declaration can't be prototyped, because it is
* assigned, below, to two functions which are prototyped in glob.h
* and dirent.h as taking pointers to differently typed opaque
* structures.
*/
struct dirent *(*readdirfunc) __P((void *));
*pathend = EOS;
errno = 0;
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
/* TODO: don't call for ENOENT or ENOTDIR? */
if (pglob->gl_errfunc) {
g_Ctoc(pathbuf, buf);
if (pglob->gl_errfunc(buf, errno) ||
pglob->gl_flags & GLOB_ERR)
return (GLOB_ABEND);
}
return(0);
}
err = 0;
/* Search directory for matching names. */
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
readdirfunc = pglob->gl_readdir;
else
readdirfunc = (struct dirent *(*)__P((void *))) readdir;
while ((dp = (*readdirfunc)(dirp))) {
register u_char *sc;
register Char *dc;
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
for (sc = (u_char *) dp->d_name, dc = pathend;
(*dc++ = *sc++) != EOS;)
continue;
if (!match(pathend, pattern, restpattern)) {
*pathend = EOS;
continue;
}
err = glob2(pathbuf, --dc, restpattern, pglob);
if (err)
break;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir)(dirp);
else
closedir(dirp);
return(err);
}
/*
* Extend the gl_pathv member of a glob_t structure to accomodate a new item,
* add the new item, and update gl_pathc.
*
* This assumes the BSD realloc, which only copies the block when its size
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
* behavior.
*
* Return 0 if new item added, error code if memory couldn't be allocated.
*
* Invariant of the glob_t structure:
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
globextend(path, pglob)
const Char *path;
glob_t *pglob;
{
register char **pathv;
register int i;
u_int newsize;
char *copy;
const Char *p;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
pathv = pglob->gl_pathv ?
realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL)
return(GLOB_NOSPACE);
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
for (i = pglob->gl_offs; --i >= 0; )
*--pathv = NULL;
}
pglob->gl_pathv = pathv;
for (p = path; *p++;)
continue;
if ((copy = malloc(p - path)) != NULL) {
g_Ctoc(path, copy);
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
return(copy == NULL ? GLOB_NOSPACE : 0);
}
/*
* pattern matching function for filenames. Each occurrence of the *
* pattern causes a recursion level.
*/
static int
match(name, pat, patend)
register Char *name, *pat, *patend;
{
int ok, negate_range;
Char c, k;
while (pat < patend) {
c = *pat++;
switch (c & M_MASK) {
case M_ALL:
if (pat == patend)
return(1);
do
if (match(name, pat, patend))
return(1);
while (*name++ != EOS);
return(0);
case M_ONE:
if (*name++ == EOS)
return(0);
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
if (c <= k && k <= pat[1])
ok = 1;
pat += 2;
} else if (c == k)
ok = 1;
if (ok == negate_range)
return(0);
break;
default:
if (*name++ != c)
return(0);
break;
}
}
return(*name == EOS);
}
/* Free allocated data belonging to a glob_t structure. */
void
globfree(pglob)
glob_t *pglob;
{
register int i;
register char **pp;
if (pglob->gl_pathv != NULL) {
pp = pglob->gl_pathv + pglob->gl_offs;
for (i = pglob->gl_pathc; i--; ++pp)
if (*pp)
free(*pp);
free(pglob->gl_pathv);
}
}
static DIR *
g_opendir(str, pglob)
register Char *str;
glob_t *pglob;
{
char buf[MAXPATHLEN];
if (!*str)
strcpy(buf, ".");
else
g_Ctoc(str, buf);
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_opendir)(buf));
return(opendir(buf));
}
static int
g_lstat(fn, sb, pglob)
register Char *fn;
struct STAT *sb;
glob_t *pglob;
{
char buf[MAXPATHLEN];
g_Ctoc(fn, buf);
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_lstat)(buf, sb));
return(lstat(buf, sb));
}
static int
g_stat(fn, sb, pglob)
register Char *fn;
struct STAT *sb;
glob_t *pglob;
{
char buf[MAXPATHLEN];
g_Ctoc(fn, buf);
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_stat)(buf, sb));
return(stat(buf, sb));
}
static Char *
g_strchr(str, ch)
Char *str;
int ch;
{
do {
if (*str == ch)
return (str);
} while (*str++);
return (NULL);
}
#ifdef notdef
static Char *
g_strcat(dst, src)
Char *dst;
const Char* src;
{
Char *sdst = dst;
while (*dst++)
continue;
--dst;
while((*dst++ = *src++) != EOS)
continue;
return (sdst);
}
#endif
static void
g_Ctoc(str, buf)
register const Char *str;
char *buf;
{
register char *dc;
for (dc = buf; (*dc++ = *str++) != EOS;)
continue;
}
#ifdef DEBUG
static void
qprintf(str, s)
const char *str;
register Char *s;
{
register Char *p;
(void)printf("%s:\n", str);
for (p = s; *p; p++)
(void)printf("%c", CHAR(*p));
(void)printf("\n");
for (p = s; *p; p++)
(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
(void)printf("\n");
for (p = s; *p; p++)
(void)printf("%c", ismeta(*p) ? '_' : ' ');
(void)printf("\n");
}
#endif

277
winsup/cygwin/gmon.c Normal file
View File

@ -0,0 +1,277 @@
/*-
* Copyright (c) 1983, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char rcsid[] = "$OpenBSD: gmon.c,v 1.8 1997/07/23 21:11:27 kstailey Exp $";
#endif
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <gmon.h>
#include <profil.h>
/* XXX needed? */
//extern char *minbrk __asm ("minbrk");
struct gmonparam _gmonparam = { GMON_PROF_OFF };
static int s_scale;
/* see profil(2) where this is describe (incorrectly) */
#define SCALE_1_TO_1 0x10000L
#define ERR(s) write(2, s, sizeof(s))
void moncontrol __P((int));
static void *
fake_sbrk(int size)
{
return malloc(size);
}
void
monstartup(lowpc, highpc)
u_long lowpc;
u_long highpc;
{
register int o;
char *cp;
struct gmonparam *p = &_gmonparam;
/*
* round lowpc and highpc to multiples of the density we're using
* so the rest of the scaling (here and in gprof) stays in ints.
*/
p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
p->textsize = p->highpc - p->lowpc;
p->kcountsize = p->textsize / HISTFRACTION;
p->hashfraction = HASHFRACTION;
p->fromssize = p->textsize / p->hashfraction;
p->tolimit = p->textsize * ARCDENSITY / 100;
if (p->tolimit < MINARCS)
p->tolimit = MINARCS;
else if (p->tolimit > MAXARCS)
p->tolimit = MAXARCS;
p->tossize = p->tolimit * sizeof(struct tostruct);
cp = fake_sbrk(p->kcountsize + p->fromssize + p->tossize);
if (cp == (char *)-1) {
ERR("monstartup: out of memory\n");
return;
}
#ifdef notdef
bzero(cp, p->kcountsize + p->fromssize + p->tossize);
#endif
p->tos = (struct tostruct *)cp;
cp += p->tossize;
p->kcount = (u_short *)cp;
cp += p->kcountsize;
p->froms = (u_short *)cp;
/* XXX minbrk needed? */
//minbrk = fake_sbrk(0);
p->tos[0].link = 0;
o = p->highpc - p->lowpc;
if (p->kcountsize < o) {
#ifndef notdef
s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
#else /* avoid floating point */
int quot = o / p->kcountsize;
if (quot >= 0x10000)
s_scale = 1;
else if (quot >= 0x100)
s_scale = 0x10000 / quot;
else if (o >= 0x800000)
s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
else
s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
#endif
} else
s_scale = SCALE_1_TO_1;
moncontrol(1);
}
void
_mcleanup()
{
int fd;
int hz;
int fromindex;
int endfrom;
u_long frompc;
int toindex;
struct rawarc rawarc;
struct gmonparam *p = &_gmonparam;
struct gmonhdr gmonhdr, *hdr;
char *proffile;
#ifdef DEBUG
int log, len;
char dbuf[200];
#endif
if (p->state == GMON_PROF_ERROR)
ERR("_mcleanup: tos overflow\n");
hz = PROF_HZ;
moncontrol(0);
#ifdef nope
if ((profdir = getenv("PROFDIR")) != NULL) {
extern char *__progname;
char *s, *t, *limit;
pid_t pid;
long divisor;
/* If PROFDIR contains a null value, no profiling
output is produced */
if (*profdir == '\0') {
return;
}
limit = buf + sizeof buf - 1 - 10 - 1 -
strlen(__progname) - 1;
t = buf;
s = profdir;
while((*t = *s) != '\0' && t < limit) {
t++;
s++;
}
*t++ = '/';
/*
* Copy and convert pid from a pid_t to a string. For
* best performance, divisor should be initialized to
* the largest power of 10 less than PID_MAX.
*/
pid = getpid();
divisor=10000;
while (divisor > pid) divisor /= 10; /* skip leading zeros */
do {
*t++ = (pid/divisor) + '0';
pid %= divisor;
} while (divisor /= 10);
*t++ = '.';
s = __progname;
while ((*t++ = *s++) != '\0')
;
proffile = buf;
} else {
proffile = "gmon.out";
}
#else
proffile = "gmon.out";
#endif
fd = open(proffile , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
if (fd < 0) {
perror( proffile );
return;
}
#ifdef DEBUG
log = open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664);
if (log < 0) {
perror("mcount: gmon.log");
return;
}
len = sprintf(dbuf, "[mcleanup1] kcount 0x%x ssiz %d\n",
p->kcount, p->kcountsize);
write(log, dbuf, len);
#endif
hdr = (struct gmonhdr *)&gmonhdr;
hdr->lpc = p->lowpc;
hdr->hpc = p->highpc;
hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
hdr->version = GMONVERSION;
hdr->profrate = hz;
write(fd, (char *)hdr, sizeof *hdr);
write(fd, p->kcount, p->kcountsize);
endfrom = p->fromssize / sizeof(*p->froms);
for (fromindex = 0; fromindex < endfrom; fromindex++) {
if (p->froms[fromindex] == 0)
continue;
frompc = p->lowpc;
frompc += fromindex * p->hashfraction * sizeof(*p->froms);
for (toindex = p->froms[fromindex]; toindex != 0;
toindex = p->tos[toindex].link) {
#ifdef DEBUG
len = sprintf(dbuf,
"[mcleanup2] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc, p->tos[toindex].selfpc,
p->tos[toindex].count);
write(log, dbuf, len);
#endif
rawarc.raw_frompc = frompc;
rawarc.raw_selfpc = p->tos[toindex].selfpc;
rawarc.raw_count = p->tos[toindex].count;
write(fd, &rawarc, sizeof rawarc);
}
}
close(fd);
}
/*
* Control profiling
* profiling is what mcount checks to see if
* all the data structures are ready.
*/
void
moncontrol(mode)
int mode;
{
struct gmonparam *p = &_gmonparam;
if (mode) {
/* start */
profil((char *)p->kcount, p->kcountsize, p->lowpc,
s_scale);
p->state = GMON_PROF_ON;
} else {
/* stop */
profil((char *)0, 0, 0, 0);
p->state = GMON_PROF_OFF;
}
}

166
winsup/cygwin/gmon.h Normal file
View File

@ -0,0 +1,166 @@
/* $OpenBSD: gmon.h,v 1.3 1996/04/21 22:31:46 deraadt Exp $ */
/* $NetBSD: gmon.h,v 1.5 1996/04/09 20:55:30 cgd Exp $ */
/*-
* Copyright (c) 1982, 1986, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)gmon.h 8.2 (Berkeley) 1/4/94
*/
#ifndef _SYS_GMON_H_
#define _SYS_GMON_H_
#ifndef __P
#define __P(x) x
#endif
#include <profile.h>
/*
* Structure prepended to gmon.out profiling data file.
*/
struct gmonhdr {
u_long lpc; /* base pc address of sample buffer */
u_long hpc; /* max pc address of sampled buffer */
int ncnt; /* size of sample buffer (plus this header) */
int version; /* version number */
int profrate; /* profiling clock rate */
int spare[3]; /* reserved */
};
#define GMONVERSION 0x00051879
/*
* histogram counters are unsigned shorts (according to the kernel).
*/
#define HISTCOUNTER unsigned short
/*
* fraction of text space to allocate for histogram counters here, 1/2
*/
#define HISTFRACTION 2
/*
* Fraction of text space to allocate for from hash buckets.
* The value of HASHFRACTION is based on the minimum number of bytes
* of separation between two subroutine call points in the object code.
* Given MIN_SUBR_SEPARATION bytes of separation the value of
* HASHFRACTION is calculated as:
*
* HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
*
* For example, on the VAX, the shortest two call sequence is:
*
* calls $0,(r0)
* calls $0,(r0)
*
* which is separated by only three bytes, thus HASHFRACTION is
* calculated as:
*
* HASHFRACTION = 3 / (2 * 2 - 1) = 1
*
* Note that the division above rounds down, thus if MIN_SUBR_FRACTION
* is less than three, this algorithm will not work!
*
* In practice, however, call instructions are rarely at a minimal
* distance. Hence, we will define HASHFRACTION to be 2 across all
* architectures. This saves a reasonable amount of space for
* profiling data structures without (in practice) sacrificing
* any granularity.
*/
#define HASHFRACTION 2
/*
* percent of text space to allocate for tostructs with a minimum.
*/
#define ARCDENSITY 2
#define MINARCS 50
#define MAXARCS ((1 << (8 * sizeof(HISTCOUNTER))) - 2)
struct tostruct {
u_long selfpc;
long count;
u_short link;
u_short pad;
};
/*
* a raw arc, with pointers to the calling site and
* the called site and a count.
*/
struct rawarc {
u_long raw_frompc;
u_long raw_selfpc;
long raw_count;
};
/*
* general rounding functions.
*/
#define ROUNDDOWN(x,y) (((x)/(y))*(y))
#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
/*
* The profiling data structures are housed in this structure.
*/
struct gmonparam {
int state;
u_short *kcount;
u_long kcountsize;
u_short *froms;
u_long fromssize;
struct tostruct *tos;
u_long tossize;
long tolimit;
u_long lowpc;
u_long highpc;
u_long textsize;
u_long hashfraction;
};
extern struct gmonparam _gmonparam;
/*
* Possible states of profiling.
*/
#define GMON_PROF_ON 0
#define GMON_PROF_BUSY 1
#define GMON_PROF_ERROR 2
#define GMON_PROF_OFF 3
/*
* Sysctl definitions for extracting profiling information from the kernel.
*/
#define GPROF_STATE 0 /* int: profiling enabling variable */
#define GPROF_COUNT 1 /* struct: profile tick count buffer */
#define GPROF_FROMS 2 /* struct: from location hash bucket */
#define GPROF_TOS 3 /* struct: destination/count structure */
#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */
#endif /* !_SYS_GMONH_ */

283
winsup/cygwin/grp.cc Normal file
View File

@ -0,0 +1,283 @@
/* grp.cc
Copyright 1996, 1997, 1998, 2000 Cygnus Solutions.
Original stubs by Jason Molenda of Cygnus Support, crash@cygnus.com
First implementation by Gunther Ebert, gunther.ebert@ixos-leipzig.de
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include "winsup.h"
/* Read /etc/group only once for better performance. This is done
on the first call that needs information from it. */
#define MAX_DOMAIN_NAME 100
static NO_COPY const char *etc_group = "/etc/group";
static struct group *group_buf = NULL; /* group contents in memory */
static int curr_lines = 0;
static int max_lines = 0;
/* Position in the group cache */
#ifdef _MT_SAFE
#define grp_pos _reent_winsup()->_grp_pos
#else
static int grp_pos = 0;
#endif
/* Set to 1 when /etc/group has been read in by read_etc_group (). */
/* Functions in this file need to check the value of group_in_memory_p
and read in the group file if it isn't set. */
/* FIXME: This should be static but this is called in uinfo_init outside
this file */
int group_in_memory_p = 0;
static int
parse_grp (struct group &grp, const char *line)
{
int len = strlen(line);
char *newline = (char *) malloc (len + 1);
(void) memcpy (newline, line, len + 1);
if (newline[--len] == '\n')
newline[len] = '\0';
char *dp = strchr (newline, ':');
if (!dp)
return 0;
*dp++ = '\0';
grp.gr_name = newline;
grp.gr_passwd = dp;
dp = strchr (grp.gr_passwd, ':');
if (dp)
{
*dp++ = '\0';
if (!strlen (grp.gr_passwd))
grp.gr_passwd = NULL;
grp.gr_gid = atoi (dp);
dp = strchr (dp, ':');
if (dp)
{
if (*++dp)
{
int i = 0;
char *cp;
for (cp = dp; (cp = strchr (cp, ',')) != NULL; ++cp)
++i;
char **namearray = (char **) calloc (i + 2, sizeof (char *));
if (namearray)
{
i = 0;
for (cp = dp; (cp = strchr (dp, ',')) != NULL; dp = cp + 1)
{
*cp = '\0';
namearray[i++] = dp;
}
namearray[i++] = dp;
namearray[i] = NULL;
}
grp.gr_mem = namearray;
}
else
grp.gr_mem = NULL;
return 1;
}
}
return 0;
}
/* Read one line from /etc/group into the group cache */
static void
add_grp_line (const char *line)
{
if (curr_lines == max_lines)
{
max_lines += 10;
group_buf = (struct group *) realloc (group_buf, max_lines * sizeof (struct group));
}
if (parse_grp (group_buf[curr_lines], line))
curr_lines++;
}
extern PSID get_admin_sid ();
/* Cygwin internal */
/* Read in /etc/group and save contents in the group cache */
/* This sets group_in_memory_p to 1 so functions in this file can
tell that /etc/group has been read in */
/* FIXME: should be static but this is called in uinfo_init outside this
file */
void
read_etc_group ()
{
extern int group_sem;
char linebuf [ 200 ];
char group_name [ MAX_USER_NAME ];
DWORD group_name_len = MAX_USER_NAME;
strncpy (group_name, "Administrators", sizeof (group_name));
++group_sem;
FILE *f = fopen (etc_group, "r");
--group_sem;
if (f)
{
while (fgets (linebuf, sizeof (linebuf), f) != NULL)
{
if (strlen (linebuf))
add_grp_line (linebuf);
}
fclose (f);
}
else /* /etc/group doesn't exist -- create default one in memory */
{
char domain_name [ MAX_DOMAIN_NAME ];
DWORD domain_name_len = MAX_DOMAIN_NAME;
SID_NAME_USE acType;
debug_printf ("Emulating /etc/group");
if (! LookupAccountSidA (NULL ,
get_admin_sid () ,
group_name,
&group_name_len,
domain_name,
&domain_name_len,
&acType))
{
strcpy (group_name, "unknown");
debug_printf ("Failed to get local admins group name. %E");
}
snprintf (linebuf, sizeof (linebuf), "%s::%u:\n", group_name, DEFAULT_GID);
add_grp_line (linebuf);
}
group_in_memory_p = 1;
}
extern "C"
struct group *
getgrgid (gid_t gid)
{
struct group * default_grp = NULL;
if (!group_in_memory_p)
read_etc_group();
for (int i = 0; i < curr_lines; i++)
{
if (group_buf[i].gr_gid == DEFAULT_GID)
default_grp = group_buf + i;
if (group_buf[i].gr_gid == gid)
return group_buf + i;
}
return default_grp;
}
extern "C"
struct group *
getgrnam (const char *name)
{
if (!group_in_memory_p)
read_etc_group();
for (int i = 0; i < curr_lines; i++)
if (strcasematch (group_buf[i].gr_name, name))
return group_buf + i;
/* Didn't find requested group */
return NULL;
}
extern "C"
void
endgrent()
{
grp_pos = 0;
}
extern "C"
struct group *
getgrent()
{
if (!group_in_memory_p)
read_etc_group();
if (grp_pos < curr_lines)
return group_buf + grp_pos++;
return NULL;
}
extern "C"
void
setgrent ()
{
grp_pos = 0;
}
int
getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username)
{
if (!group_in_memory_p)
read_etc_group();
int cnt = 0;
for (int i = 0; i < curr_lines; ++i)
if (gid == group_buf[i].gr_gid)
{
if (cnt < gidsetsize)
grouplist[cnt] = group_buf[i].gr_gid;
++cnt;
if (gidsetsize && cnt >= gidsetsize)
goto out;
}
else if (group_buf[i].gr_mem)
for (int gi = 0; group_buf[i].gr_mem[gi]; ++gi)
if (! strcasecmp (username, group_buf[i].gr_mem[gi]))
{
if (cnt < gidsetsize)
grouplist[cnt] = group_buf[i].gr_gid;
++cnt;
if (gidsetsize && cnt >= gidsetsize)
goto out;
}
out:
return cnt;
}
extern "C"
int
getgroups (int gidsetsize, gid_t *grouplist)
{
#if 0
if (gidsetsize <= 0)
return 0;
grouplist[0] = myself->gid;
return 1;
#else
return getgroups (gidsetsize, grouplist, myself->gid, myself->username);
#endif
}
extern "C"
int
initgroups (const char *user, gid_t grp)
{
return 0;
}

140
winsup/cygwin/heap.cc Normal file
View File

@ -0,0 +1,140 @@
/* heap.cc: Cygwin heap manager.
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <errno.h>
#include "winsup.h"
#define brksize ((char *) user_data->heaptop - (char *) user_data->heapbase)
#define brk (user_data->heapptr)
#define brkbase (user_data->heapbase)
#define brktop (user_data->heaptop)
#define brkchunk (cygwin_shared->heap_chunk_size ())
#define assert(x)
static unsigned page_const = 0;
static int __inline
getpagesize(void)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
return (int)si.dwPageSize;
}
/* Initialize the heap at process start up. */
void
heap_init ()
{
/* If we're the forkee, we must allocate the heap at exactly the same place
as our parent. If not, we don't care where it ends up. */
page_const = getpagesize();
if (brkbase)
{
DWORD chunk = brkchunk; /* allocation chunk */
/* total size commited in parent */
DWORD allocsize = (char *) brktop - (char *) brkbase;
/* round up by chunk size */
DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk);
/* Loop until we've managed to reserve an adequate amount of memory. */
char *p;
for (;;)
{
p = (char *) VirtualAlloc (brkbase, reserve_size,
MEM_RESERVE, PAGE_READWRITE);
if (p)
break;
if ((reserve_size -= page_const) <= allocsize)
break;
}
if (p == NULL)
api_fatal ("1. unable to allocate heap, heap_chunk_size %d, pid %d, %E",
brkchunk, myself->pid);
if (p != brkbase)
api_fatal ("heap allocated but not at %p", brkbase);
if (! VirtualAlloc (brkbase, allocsize, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("MEM_COMMIT failed, %E");
}
else
{
/* Initialize page mask and default heap size. Preallocate a heap
* to assure contiguous memory. */
brk = brktop = brkbase = VirtualAlloc(NULL, brkchunk, MEM_RESERVE, PAGE_NOACCESS);
if (brkbase == NULL)
api_fatal ("2. unable to allocate heap, heap_chunk_size %d, %E",
brkchunk);
}
page_const--;
malloc_init ();
}
#define pround(n) (((size_t)(n) + page_const) & ~page_const)
/* FIXME: This function no longer handles "split heaps". */
extern "C" void *
_sbrk(int n)
{
char *newtop, *newbrk;
unsigned commitbytes, newbrksize;
if (n == 0)
return brk; /* Just wanted to find current brk address */
newbrk = (char *) brk + n; /* Where new brk will be */
newtop = (char *) pround (newbrk); /* Actual top of allocated memory -
on page boundary */
if (newtop == brktop)
goto good;
if (n < 0)
{ /* Freeing memory */
assert(newtop < brktop);
n = (char *) brktop - newtop;
if (VirtualFree(newtop, n, MEM_DECOMMIT)) /* Give it back to OS */
goto good; /* Didn't take */
else
goto err;
}
assert(newtop > brktop);
/* Need to grab more pages from the OS. If this fails it may be because
* we have used up previously reserved memory. Or, we're just plumb out
* of memory. */
commitbytes = pround (newtop - (char *) brktop);
if (VirtualAlloc(brktop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)
goto good;
/* Couldn't allocate memory. Maybe we can reserve some more.
Reserve either the maximum of the standard brkchunk or the requested
amount. Then attempt to actually allocate it. */
if ((newbrksize = brkchunk) < commitbytes)
newbrksize = commitbytes;
if ((VirtualAlloc(brktop, newbrksize, MEM_RESERVE, PAGE_NOACCESS) != NULL) &&
(VirtualAlloc(brktop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL))
goto good;
err:
set_errno (ENOMEM);
return (void *) -1;
good:
void *oldbrk = brk;
brk = newbrk;
brktop = newtop;
return oldbrk;
}

View File

@ -0,0 +1,421 @@
#ifndef _A_OUT_H_
#define _A_OUT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define COFF_IMAGE_WITH_PE
#define COFF_LONG_SECTION_NAMES
/*** coff information for Intel 386/486. */
/********************** FILE HEADER **********************/
struct external_filehdr {
short f_magic; /* magic number */
short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
short f_opthdr; /* sizeof(optional hdr) */
short f_flags; /* flags */
};
/* Bits for f_flags:
* F_RELFLG relocation info stripped from file
* F_EXEC file is executable (no unresolved external references)
* F_LNNO line numbers stripped from file
* F_LSYMS local symbols stripped from file
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
*/
#define F_RELFLG (0x0001)
#define F_EXEC (0x0002)
#define F_LNNO (0x0004)
#define F_LSYMS (0x0008)
#define I386MAGIC 0x14c
#define I386PTXMAGIC 0x154
#define I386AIXMAGIC 0x175
/* This is Lynx's all-platform magic number for executables. */
#define LYNXCOFFMAGIC 0415
#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \
&& (x).f_magic != I386AIXMAGIC \
&& (x).f_magic != I386PTXMAGIC \
&& (x).f_magic != LYNXCOFFMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER"=
**********************/
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of data used for this file=
*/
}
AOUTHDR;
#define AOUTSZ 28
#define AOUTHDRSZ 28
#define OMAGIC 0404 /* object files, eg as output */
#define ZMAGIC 0413 /* demand load format, eg normal ld output */
#define STMAGIC 0401 /* target shlib */
#define SHMAGIC 0443 /* host shlib */
/* define some NT default values */
/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
#define NT_SECTION_ALIGNMENT 0x1000
#define NT_FILE_ALIGNMENT 0x200
#define NT_DEF_RESERVE 0x100000
#define NT_DEF_COMMIT 0x1000
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
unsigned long s_paddr; /* physical address, offset
of last addr in scn */
unsigned long s_vaddr; /* virtual address */
unsigned long s_size; /* section size */
unsigned long s_scnptr; /* file ptr to raw data for section */
unsigned long s_relptr; /* file ptr to relocation */
unsigned long s_lnnoptr; /* file ptr to line numbers */
unsigned short s_nreloc; /* number of relocation entries */
unsigned short s_nlnno; /* number of line number entries*/
unsigned long s_flags; /* flags */
};
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _COMMENT ".comment"
#define _LIB ".lib"
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */
unsigned long l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
unsigned long e_zeroes;
unsigned long e_offset;
} e;
} e;
unsigned long e_value;
unsigned short e_scnum;
unsigned short e_type;
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (0xf)
#define N_TMASK (0x30)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
unsigned long x_tagndx; /* str, un, or enum tag indx */
union {
struct {
unsigned short x_lnno; /* declaration line number */
unsigned short x_size; /* str/union/array size */
} x_lnsz;
unsigned long x_fsize; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
unsigned long x_lnnoptr;/* ptr to fcn line # */
unsigned long x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
unsigned short x_tvndx; /* tv index */
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
unsigned long x_zeroes;
unsigned long x_offset;
} x_n;
} x_file;
struct {
unsigned long x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
unsigned long x_checksum; /* section COMDAT checksum */
unsigned short x_associated;/* COMDAT associated section index */
char x_comdat[1]; /* COMDAT selection number */
} x_scn;
struct {
unsigned long x_tvfill; /* tv fill value */
unsigned short x_tvlen; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define _ETEXT "etext"
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_type[2];
};
#define RELOC struct external_reloc
#define RELSZ 10
/* end of coff/i386.h */
/* PE COFF header information */
#ifndef _PE_H
#define _PE_H
/* NT specific file attributes */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
/* additional flags to be set for section headers to allow the NT loader to
read and write to the section data (to replace the addresses of data in
dlls for one thing); also to execute the section in .text's case=
*/
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
/*
* Section characteristics added for ppc-nt
*/
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
/* COMDAT selection codes. */
#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */
#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */
#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */
#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */
/* Magic values that are true for all dos/nt implementations */
#define DOSMAGIC 0x5a4d
#define NT_SIGNATURE 0x00004550
/* NT allows long filenames, we want to accommodate this. This may break
some of the bfd functions */
#undef FILNMLEN
#define FILNMLEN 18 /* # characters in a file name */
#ifdef COFF_IMAGE_WITH_PE
/* The filehdr is only weired in images */
#undef FILHDR
struct external_PE_filehdr
{
/* DOS header fields */
unsigned short e_magic; /* Magic number, 0x5a4d */
unsigned short e_cblp; /* Bytes on last page of file, 0x90 */
unsigned short e_cp; /* Pages in file, 0x3 */
unsigned short e_crlc; /* Relocations, 0x0 */
unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */
unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */
unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */
unsigned short e_ss; /* Initial (relative) SS value, 0x0 */
unsigned short e_sp; /* Initial SP value, 0xb8 */
unsigned short e_csum; /* Checksum, 0x0 */
unsigned short e_ip; /* Initial IP value, 0x0 */
unsigned short e_cs; /* Initial (relative) CS value, 0x0 */
unsigned short e_lfarlc; /* File address of relocation table, 0x40 */
unsigned short e_ovno; /* Overlay number, 0x0 */
char e_res[4][2]; /* Reserved words, all 0x0 */
unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */
unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */
char e_res2[10][2]; /* Reserved words, all 0x0 */
unsigned long e_lfanew; /* File address of new exe header, 0x80 */
char dos_message[16][4]; /* other stuff, always follow DOS header */
unsigned int nt_signature; /* required NT signature, 0x4550 */
/* From standard header */
unsigned short f_magic; /* magic number */
unsigned short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
#define FILHDR struct external_PE_filehdr
#undef FILHSZ
#define FILHSZ 152
#endif
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of all data used for this file */
/* NT extra fields; see internal.h for descriptions */
unsigned long ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
char Reserved1[4];
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
unsigned long SizeOfStackReserve;
unsigned long SizeOfStackCommit;
unsigned long SizeOfHeapReserve;
unsigned long SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEAOUTHDR;
#undef AOUTSZ
#define AOUTSZ (AOUTHDRSZ + 196)
#undef E_FILNMLEN
#define E_FILNMLEN 18 /* # characters in a file name */
#endif
/* end of coff/pe.h */
#define DT_NON (0) /* no derived type */
#define DT_PTR (1) /* pointer */
#define DT_FCN (2) /* function */
#define DT_ARY (3) /* array */
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
#ifdef __cplusplus
}
#endif
#endif /* _A_OUT_H_ */

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ftp.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _ARPA_FTP_H
#define _ARPA_FTP_H
/* Definitions for FTP; see RFC-765. */
/*
* Reply codes.
*/
#define PRELIM 1 /* positive preliminary */
#define COMPLETE 2 /* positive completion */
#define CONTINUE 3 /* positive intermediate */
#define TRANSIENT 4 /* transient negative completion */
#define ERROR 5 /* permanent negative completion */
/*
* Type codes
*/
#define TYPE_A 1 /* ASCII */
#define TYPE_E 2 /* EBCDIC */
#define TYPE_I 3 /* image */
#define TYPE_L 4 /* local byte size */
#ifdef FTP_NAMES
char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" };
#endif
/*
* Form codes
*/
#define FORM_N 1 /* non-print */
#define FORM_T 2 /* telnet format effectors */
#define FORM_C 3 /* carriage control (ASA) */
#ifdef FTP_NAMES
char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" };
#endif
/*
* Structure codes
*/
#define STRU_F 1 /* file (no record structure) */
#define STRU_R 2 /* record structure */
#define STRU_P 3 /* page structure */
#ifdef FTP_NAMES
char *strunames[] = {"0", "File", "Record", "Page" };
#endif
/*
* Mode types
*/
#define MODE_S 1 /* stream */
#define MODE_B 2 /* block */
#define MODE_C 3 /* compressed */
#ifdef FTP_NAMES
char *modenames[] = {"0", "Stream", "Block", "Compressed" };
#endif
/*
* Record Tokens
*/
#define REC_ESC '\377' /* Record-mode Escape */
#define REC_EOR '\001' /* Record-mode End-of-Record */
#define REC_EOF '\002' /* Record-mode End-of-File */
/*
* Block Header
*/
#define BLK_EOR 0x80 /* Block is End-of-Record */
#define BLK_EOF 0x40 /* Block is End-of-File */
#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */
#define BLK_RESTART 0x10 /* Block is Restart Marker */
#define BLK_BYTECOUNT 2 /* Bytes in this block */
#endif /* !_ARPA_FTP_H */

View File

@ -0,0 +1,25 @@
#ifndef _ARPA_INET_H
#define _ARPA_INET_H
#include <netinet/in.h>
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef __INSIDE_CYGWIN_NET__
unsigned long inet_addr (const char *);
int inet_aton (const char *, struct in_addr *);
unsigned long inet_lnaof (struct in_addr);
struct in_addr inet_makeaddr (unsigned long , unsigned long);
unsigned int inet_netof (struct in_addr);
unsigned int inet_network (const char *);
char *inet_ntoa (struct in_addr);
#endif
#ifdef __cplusplus
};
#endif
#endif /* _ARPA_INET_H */

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)telnet.h 8.2 (Berkeley) 12/15/93
*/
#ifndef _ARPA_TELNET_H
#define _ARPA_TELNET_H
/*
* Definitions for the TELNET protocol.
*/
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
#ifdef TELCMDS
char *telcmds[] = {
"EOF", "SUSP", "ABORT", "EOR",
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
};
#else
extern char *telcmds[];
#endif
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
(unsigned int)(x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */
#define TELOPT_ENCRYPT 38 /* Encryption option */
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define TELOPT_ENVIRON TELOPT_OLD_ENVIRON
#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
#ifdef TELOPTS
char *telopts[NTELOPTS+1] = {
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
"TACACS UID", "OUTPUT MARKING", "TTYLOC",
"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
"ENCRYPT", "NEW-ENVIRON",
0,
};
#define TELOPT_FIRST TELOPT_BINARY
#define TELOPT_LAST TELOPT_NEW_ENVIRON
#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
#endif
/* sub-option qualifiers */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
#define LFLOW_OFF 0 /* Disable remote flow control */
#define LFLOW_ON 1 /* Enable remote flow control */
#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
/*
* LINEMODE suboptions
*/
#define LM_MODE 1
#define LM_FORWARDMASK 2
#define LM_SLC 3
#define MODE_EDIT 0x01
#define MODE_TRAPSIG 0x02
#define MODE_ACK 0x04
#define MODE_SOFT_TAB 0x08
#define MODE_LIT_ECHO 0x10
#define MODE_MASK 0x1f
/* Not part of protocol, but needed to simplify things... */
#define MODE_FLOW 0x0100
#define MODE_ECHO 0x0200
#define MODE_INBIN 0x0400
#define MODE_OUTBIN 0x0800
#define MODE_FORCE 0x1000
#define SLC_SYNCH 1
#define SLC_BRK 2
#define SLC_IP 3
#define SLC_AO 4
#define SLC_AYT 5
#define SLC_EOR 6
#define SLC_ABORT 7
#define SLC_EOF 8
#define SLC_SUSP 9
#define SLC_EC 10
#define SLC_EL 11
#define SLC_EW 12
#define SLC_RP 13
#define SLC_LNEXT 14
#define SLC_XON 15
#define SLC_XOFF 16
#define SLC_FORW1 17
#define SLC_FORW2 18
#define NSLC 18
/*
* For backwards compatability, we define SLC_NAMES to be the
* list of names if SLC_NAMES is not defined.
*/
#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
#ifdef SLC_NAMES
char *slc_names[] = {
SLC_NAMELIST
};
#else
extern char *slc_names[];
#define SLC_NAMES SLC_NAMELIST
#endif
#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
#define SLC_NAME(x) slc_names[x]
#define SLC_NOSUPPORT 0
#define SLC_CANTCHANGE 1
#define SLC_VARIABLE 2
#define SLC_DEFAULT 3
#define SLC_LEVELBITS 0x03
#define SLC_FUNC 0
#define SLC_FLAGS 1
#define SLC_VALUE 2
#define SLC_ACK 0x80
#define SLC_FLUSHIN 0x40
#define SLC_FLUSHOUT 0x20
#define OLD_ENV_VAR 1
#define OLD_ENV_VALUE 0
#define NEW_ENV_VAR 0
#define NEW_ENV_VALUE 1
#define ENV_ESC 2
#define ENV_USERVAR 3
#define ENV_VALUE 0
#define ENV_VAR 1
/*
* AUTHENTICATION suboptions
*/
/*
* Who is authenticating who ...
*/
#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
#define AUTH_WHO_SERVER 1 /* Server authenticating client */
#define AUTH_WHO_MASK 1
/*
* amount of authentication done
*/
#define AUTH_HOW_ONE_WAY 0
#define AUTH_HOW_MUTUAL 2
#define AUTH_HOW_MASK 2
#define AUTHTYPE_NULL 0
#define AUTHTYPE_KERBEROS_V4 1
#define AUTHTYPE_KERBEROS_V5 2
#define AUTHTYPE_SPX 3
#define AUTHTYPE_MINK 4
#define AUTHTYPE_CNT 5
#define AUTHTYPE_TEST 99
#ifdef AUTH_NAMES
char *authtype_names[] = {
"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
};
#else
extern char *authtype_names[];
#endif
#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
#define AUTHTYPE_NAME(x) authtype_names[x]
/*
* ENCRYPTion suboptions
*/
#define ENCRYPT_IS 0 /* I pick encryption type ... */
#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
#define ENCRYPT_REPLY 2 /* Initial setup response */
#define ENCRYPT_START 3 /* Am starting to send encrypted */
#define ENCRYPT_END 4 /* Am ending encrypted */
#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
#define ENCRYPT_REQEND 6 /* Request you send encrypting */
#define ENCRYPT_ENC_KEYID 7
#define ENCRYPT_DEC_KEYID 8
#define ENCRYPT_CNT 9
#define ENCTYPE_ANY 0
#define ENCTYPE_DES_CFB64 1
#define ENCTYPE_DES_OFB64 2
#define ENCTYPE_CNT 3
#ifdef ENCRYPT_NAMES
char *encrypt_names[] = {
"IS", "SUPPORT", "REPLY", "START", "END",
"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
0,
};
char *enctype_names[] = {
"ANY", "DES_CFB64", "DES_OFB64", 0,
};
#else
extern char *encrypt_names[];
extern char *enctype_names[];
#endif
#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
#define ENCRYPT_NAME(x) encrypt_names[x]
#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
#define ENCTYPE_NAME(x) enctype_names[x]
#endif /* _ARPA_TELNET_H */

View File

@ -0,0 +1,93 @@
#ifndef _I386_BYTEORDER_H
#define _I386_BYTEORDER_H
#ifdef __cplusplus
extern "C" {
#endif
#if 0
#undef ntohl
#undef ntohs
#undef htonl
#undef htons
#endif
#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN 1234
#endif
#ifndef __LITTLE_ENDIAN_BITFIELD
#define __LITTLE_ENDIAN_BITFIELD
#endif
#if 1
extern unsigned long int ntohl(unsigned long int);
extern unsigned short int ntohs(unsigned short int);
extern unsigned long int htonl(unsigned long int);
extern unsigned short int htons(unsigned short int);
extern __inline__ unsigned long int __ntohl(unsigned long int);
extern __inline__ unsigned short int __ntohs(unsigned short int);
extern __inline__ unsigned long int __constant_ntohl(unsigned long int);
extern __inline__ unsigned short int __constant_ntohs(unsigned short int);
extern __inline__ unsigned long int
__ntohl(unsigned long int x)
{
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (x)
: "0" (x));
return x;
}
#define __constant_ntohl(x) \
((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
(((unsigned long int)(x) & 0x0000ff00U) << 8) | \
(((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned long int)(x) & 0xff000000U) >> 24)))
extern __inline__ unsigned short int
__ntohs(unsigned short int x)
{
__asm__("xchgb %b0,%h0" /* swap bytes */
: "=q" (x)
: "0" (x));
return x;
}
#define __constant_ntohs(x) \
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8))) \
#define __htonl(x) __ntohl(x)
#define __htons(x) __ntohs(x)
#define __constant_htonl(x) __constant_ntohl(x)
#define __constant_htons(x) __constant_ntohs(x)
#ifdef __OPTIMIZE__
# define ntohl(x) \
(__builtin_constant_p((long)(x)) ? \
__constant_ntohl((x)) : \
__ntohl((x)))
# define ntohs(x) \
(__builtin_constant_p((short)(x)) ? \
__constant_ntohs((x)) : \
__ntohs((x)))
# define htonl(x) \
(__builtin_constant_p((long)(x)) ? \
__constant_htonl((x)) : \
__htonl((x)))
# define htons(x) \
(__builtin_constant_p((short)(x)) ? \
__constant_htons((x)) : \
__htons((x)))
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,58 @@
#ifndef _ASM_SOCKET_H
#define _ASM_SOCKET_H
#include <cygwin/if.h>
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
#define _IO(x,y) (IOC_VOID|(x<<8)|y)
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark? */
#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to read */
#define FIONBIO 0x8004667e /* To be compatible with termiost version */
#define REAL_FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */
#define FIOASYNC _IOW('f', 125, u_long) /* set/clear async i/o */
#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */
/* Needed for if queries */
#define SIOCGIFCONF _IOW('s', 100, struct ifconf) /* get if list */
#define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */
#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
#define SIOCGIFBRDADDR _IOW('s', 103, struct ifreq) /* Get if broadcastaddr */
#define SIOCGIFNETMASK _IOW('s', 104, struct ifreq) /* Get if netmask */
#define SOL_SOCKET 0xffff /* options for socket level */
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_DONTLINGER (u_int)(~SO_LINGER)
/*
* Additional options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
#endif /* _ASM_SOCKET_H */

View File

@ -0,0 +1,13 @@
#ifndef _ASM_TYPES_H
#define _ASM_TYPES_H
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#endif /* _ASM_TYPES_H */

View File

@ -0,0 +1,81 @@
/* cygwin/acl.h header file for Cygwin.
Copyright 1999, 2000 Cygnus Solutions.
Written by C. Vinschen.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _CYGWIN_ACL_H
#ifdef __cplusplus
extern "C" {
#endif
#define _CYGWIN_ACL_H
#include <_ansi.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Values for `cmd' in calls to acl(2) and facl(2) */
#define SETACL (0x0)
#define GETACL (0x1)
#define GETACLCNT (0x2)
#define MIN_ACL_ENTRIES (4) // minimal acl entries from GETACLCNT
#define MAX_ACL_ENTRIES (256) // max entries of each type
// Return values of aclcheck(3) in case of error */
#define GRP_ERROR (0x1)
#define USER_ERROR (0x2)
#define CLASS_ERROR (0x3)
#define OTHER_ERROR (0x4)
#define DUPLICATE_ERROR (0x5)
#define ENTRY_ERROR (0x6)
#define MISS_ERROR (0x7) // which = -1
#define MEM_ERROR (0x8) // which = -1
// Values for entry type of struct acl
#define USER_OBJ (0x0001) // owner
#define USER (0x0002) // additional user
#define GROUP_OBJ (0x0004) // owning group
#define GROUP (0x0008) // additional group
#define CLASS_OBJ (0x0010) // mask entry
#define OTHER_OBJ (0x0020) // others
#define ACL_DEFAULT (0x1000) // default flag
#define DEF_USER_OBJ (ACL_DEFAULT|USER_OBJ) // default owner
#define DEF_USER (ACL_DEFAULT|USER) // default additional user
#define DEF_GROUP_OBJ (ACL_DEFAULT|GROUP_OBJ) // default owning group
#define DEF_GROUP (ACL_DEFAULT|GROUP) // default additional group
#define DEF_CLASS_OBJ (ACL_DEFAULT|CLASS_OBJ) // default mask entry
#define DEF_OTHER_OBJ (ACL_DEFAULT|OTHER_OBJ) // default others
// Values with equivalent meanings
#define USER_OWNER USER_OBJ
#define GROUP_OWNER GROUP_OBJ
#define MASK CLASS_OBJ
#define OTHER OTHER_OBJ
typedef struct acl {
int a_type; /* entry type */
uid_t a_id; /* UID | GID */
mode_t a_perm; /* permissions */
} aclent_t;
int _EXFUN(acl,(const char *path, int cmd, int nentries, aclent_t *aclbufp));
int _EXFUN(facl,(int fd, int cmd, int nentries, aclent_t *aclbufp));
int _EXFUN(aclcheck,(aclent_t *aclbufp, int nentries, int *which));
int _EXFUN(aclsort,(int nentries, int calclass, aclent_t *aclbufp));
int _EXFUN(acltomode,(aclent_t *aclbufp, int nentries, mode_t *modep));
int _EXFUN(aclfrommode,(aclent_t *aclbufp, int nentries, mode_t *modep));
int _EXFUN(acltopbits,(aclent_t *aclbufp, int nentries, mode_t *pbitsp));
int _EXFUN(aclfrompbits,(aclent_t *aclbufp, int nentries, mode_t *pbitsp));
char *_EXFUN(acltotext,(aclent_t *aclbufp, int aclcnt));
aclent_t *_EXFUN(aclfromtext,(char *acltextp, int *aclcnt));
#ifdef __cplusplus
}
#endif
#endif /* _CYGWIN_ACL_H */

View File

@ -0,0 +1,96 @@
/* cygwin_dll.h
Copyright 1998 Cygnus Solutions
This file is part of Cygwin32.
This software is a copyrighted work licensed under the terms of the
Cygwin32 license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef __CYGWIN_CYGWIN_DLL_H__
#define __CYGWIN_CYGWIN_DLL_H__
#include <windows.h>
#ifdef __cplusplus
#define CDECL_BEGIN extern "C" {
#define CDECL_END }
#else
#define CDECL_BEGIN
#define CDECL_END
#endif
#define DECLARE_CYGWIN_DLL(Entry) \
\
CDECL_BEGIN \
int WINAPI _cygwin_dll_entry (HANDLE h, DWORD reason, void *ptr); \
int WINAPI _cygwin_noncygwin_dll_entry (HANDLE h, DWORD reason, void *ptr); \
\
int WINAPI Entry (HANDLE h, DWORD reason, void *ptr); \
extern int cygwin_attach_dll (); \
extern void cygwin_detach_dll (); \
CDECL_END \
\
static HANDLE storedHandle; \
static DWORD storedReason; \
static void* storedPtr; \
\
static int __dllMain (int a, char **b, char **c) \
{ \
return Entry (storedHandle, storedReason, storedPtr); \
} \
\
static int dll_index; \
\
int WINAPI _cygwin_dll_entry (HANDLE h, DWORD reason, void *ptr) \
{ \
int ret; \
ret = 1; \
\
switch (reason) \
{ \
case DLL_PROCESS_ATTACH: \
{ \
storedHandle = h; \
storedReason = reason; \
storedPtr = ptr; \
dll_index = cygwin_attach_dll (h, &__dllMain); \
if (dll_index == -1) \
ret = 0; \
} \
break; \
\
case DLL_PROCESS_DETACH: \
{ \
ret = Entry (h, reason, ptr); \
if (ret) \
{ \
cygwin_detach_dll (dll_index); \
dll_index = -1; \
} \
} \
break; \
\
case DLL_THREAD_ATTACH: \
{ \
ret = Entry (h, reason, ptr); \
} \
break; \
\
case DLL_THREAD_DETACH: \
{ \
ret = Entry (h, reason, ptr); \
} \
break; \
} \
return ret; \
} \
\
/* OBSOLETE: This is only provided for source level compatibility. */ \
int WINAPI _cygwin_noncygwin_dll_entry (HANDLE h, DWORD reason, void *ptr) \
{ \
return _cygwin_dll_entry (h, reason, ptr); \
} \
#endif /* __CYGWIN_CYGWIN_DLL_H__ */

View File

@ -0,0 +1 @@
/* icmp.h */

View File

@ -0,0 +1,74 @@
#ifndef _CYGWIN_IF_H_
#define _CYGWIN_IF_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <sys/types.h>
#include <sys/socket.h>
/* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_MULTICAST 0x1000 /* Supports multicast */
/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
* definitions which begin with ifr_name. The
* remainder may be interface specific.
*/
struct ifreq
{
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
short ifru_flags;
int ifru_metric;
int ifru_mtu;
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
/*
* Structure used in SIOCGIFCONF request.
* Used to retrieve interface configuration
* for machine (useful for programs which
* must know all networks accessible).
*/
struct ifconf
{
int ifc_len; /* size of buffer */
union
{
caddr_t ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* _CYGWIN_IF_H_ */

View File

@ -0,0 +1,188 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions of the Internet Protocol.
*
* Version: @(#)in.h 1.0.1 04/21/93
*
* Authors: Original taken from the GNU Project <netinet/in.h> file.
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _CYGWIN_IN_H
#define _CYGWIN_IN_H
#include <cygwin/types.h>
/* Standard well-defined IP protocols. */
enum {
IPPROTO_IP = 0, /* Dummy protocol for TCP */
IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
IPPROTO_IGMP = 2, /* Internet Gateway Management Protocol */
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
IPPROTO_TCP = 6, /* Transmission Control Protocol */
IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
IPPROTO_PUP = 12, /* PUP protocol */
IPPROTO_UDP = 17, /* User Datagram Protocol */
IPPROTO_IDP = 22, /* XNS IDP protocol */
IPPROTO_RAW = 255, /* Raw IP packets */
IPPROTO_MAX
};
/* Standard well-known ports. *//* from winsup/include/netinet/in.h */
enum
{
IPPORT_ECHO = 7, /* Echo service. */
IPPORT_DISCARD = 9, /* Discard transmissions service. */
IPPORT_SYSTAT = 11, /* System status service. */
IPPORT_DAYTIME = 13, /* Time of day service. */
IPPORT_NETSTAT = 15, /* Network status service. */
IPPORT_FTP = 21, /* File Transfer Protocol. */
IPPORT_TELNET = 23, /* Telnet protocol. */
IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */
IPPORT_TIMESERVER = 37, /* Timeserver service. */
IPPORT_NAMESERVER = 42, /* Domain Name Service. */
IPPORT_WHOIS = 43, /* Internet Whois service. */
IPPORT_MTP = 57,
IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */
IPPORT_RJE = 77,
IPPORT_FINGER = 79, /* Finger service. */
IPPORT_TTYLINK = 87,
IPPORT_SUPDUP = 95, /* SUPDUP protocol. */
IPPORT_EXECSERVER = 512, /* execd service. */
IPPORT_LOGINSERVER = 513, /* rlogind service. */
IPPORT_CMDSERVER = 514,
IPPORT_EFSSERVER = 520,
/* UDP ports. */
IPPORT_BIFFUDP = 512,
IPPORT_WHOSERVER = 513,
IPPORT_ROUTESERVER = 520,
/* Ports less than this value are reserved for privileged processes. */
IPPORT_RESERVED = 1024,
/* Ports greater this value are reserved for (non-privileged) servers. */
IPPORT_USERRESERVED = 5000
};
/* Internet address. */
struct in_addr {
unsigned int s_addr;
};
/* Request struct for multicast socket ops */
struct ip_mreq
{
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero __pad /* for BSD UNIX comp. -FvK */
/*
* Definitions of the bits in an Internet address integer.
* On subnets, host and network parts are found according
* to the subnet mask, not these masks.
*/
#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
#define IN_CLASSA_MAX 128
#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(a) IN_CLASSD(a)
#define IN_MULTICAST_NET 0xF0000000
#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) == 0xe0000000)
#define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000)
/* Address to send to all hosts. */
#define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
/* Address indicating an error return. */
#define INADDR_NONE 0xffffffff
/* Network number for local host loopback. */
#define IN_LOOPBACKNET 127
/* Address to loopback in software to local host. */
#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
/* Defines for Multicast INADDR */
#define INADDR_UNSPEC_GROUP 0xe0000000 /* 224.0.0.0 */
#define INADDR_ALLHOSTS_GROUP 0xe0000001 /* 224.0.0.1 */
#define INADDR_MAX_LOCAL_GROUP 0xe00000ff /* 224.0.0.255 */
/* <asm/byteorder.h> contains the htonl type stuff.. */
#include <asm/byteorder.h>
/* Some random defines to make it easier in the kernel.. */
#ifdef __KERNEL__
#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
#endif
/*
* IPv6 definitions as we start to include them. This is just
* a beginning dont get excited 8)
*/
struct in_addr6
{
unsigned char s6_addr[16];
};
struct sockaddr_in6
{
unsigned short sin6_family;
unsigned short sin6_port;
unsigned long sin6_flowinfo;
struct in_addr6 sin6_addr;
};
#endif /* _CYGWIN_IN_H */

View File

@ -0,0 +1,190 @@
/*
* cygwin/mtio.h header file for Cygwin.
*
* Original written by H. Bergman for Linux.
* Changed for Cygwin by C. Vinschen.
*/
#ifndef _CYGWIN_MTIO_H
#define _CYGWIN_MTIO_H
#include <sys/ioctl.h>
#include <asm/socket.h>
/*
* Structures and definitions for mag tape io control commands
*/
/* structure for MTIOCTOP - mag tape op command */
struct mtop {
short mt_op; /* operations defined below */
int mt_count; /* how many of them */
};
/* Magnetic Tape operations [Not all operations supported by all drivers]: */
#define MTRESET 0 /* +reset drive in case of problems */
#define MTFSF 1 /* forward space over FileMark,
* position at first record of next file
*/
#define MTBSF 2 /* backward space FileMark (position before FM) */
#define MTFSR 3 /* forward space record */
#define MTBSR 4 /* backward space record */
#define MTWEOF 5 /* write an end-of-file record (mark) */
#define MTREW 6 /* rewind */
#define MTOFFL 7 /* rewind and put the drive offline (eject?) */
#define MTNOP 8 /* no op, set status only (read with MTIOCGET) */
#define MTRETEN 9 /* retension tape */
#define MTBSFM 10 /* +backward space FileMark, position at FM */
#define MTFSFM 11 /* +forward space FileMark, position at FM */
#define MTEOM 12 /* goto end of recorded media (for appending files).
* MTEOM positions after the last FM, ready for
* appending another file.
*/
#define MTERASE 13 /* erase tape -- be careful! */
#define MTRAS1 14 /* run self test 1 (nondestructive) */
#define MTRAS2 15 /* run self test 2 (destructive) */
#define MTRAS3 16 /* reserved for self test 3 */
#define MTSETBLK 20 /* set block length (SCSI) */
#define MTSETDENSITY 21 /* set tape density (SCSI) */
#define MTSEEK 22 /* seek to block (Tandberg, etc.) */
#define MTTELL 23 /* tell block (Tandberg, etc.) */
#define MTSETDRVBUFFER 24 /* set the drive buffering according to SCSI-2 */
/* ordinary buffered operation with code 1 */
#define MTFSS 25 /* space forward over setmarks */
#define MTBSS 26 /* space backward over setmarks */
#define MTWSM 27 /* write setmarks */
#define MTLOCK 28 /* lock the drive door */
#define MTUNLOCK 29 /* unlock the drive door */
#define MTLOAD 30 /* execute the SCSI load command */
#define MTUNLOAD 31 /* execute the SCSI unload command */
#define MTCOMPRESSION 32/* control compression with SCSI mode page 15 */
#define MTSETPART 33 /* Change the active tape partition */
#define MTMKPART 34 /* Format the tape with one or two partitions */
/* structure for MTIOCGET - mag tape get status command */
struct mtget {
long mt_type; /* type of magtape device
* Cygwin: MT_ISUNKNOWN */
long mt_resid; /* residual count: (not sure)
* number of bytes ignored, or
* number of files not skipped, or
* number of records not skipped.
* Cygwin: remaining KB.
*/
/* the following registers are device dependent */
long mt_dsreg; /* status register */
long mt_gstat; /* generic (device independent) status */
long mt_erreg; /* error register */
/* The next two fields are not always used */
long mt_fileno; /* number of current file on tape */
long mt_blkno; /* current block number */
/* The next are Windows NT specific */
long long mt_capacity; /* Tape capacity in bytes */
long long mt_remaining; /* Remaining bytes */
int mt_minblksize;
int mt_maxblksize;
int mt_defblksize;
unsigned long mt_featureslow;
unsigned long mt_featureshigh;
};
/* structure for MTIOCPOS - mag tape get position command */
struct mtpos {
long mt_blkno; /* current block number */
};
/* mag tape io control commands */
#define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
#define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */
#define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */
/* Generic Mag Tape (device independent) status macros for examining
* mt_gstat -- HP-UX compatible.
* There is room for more generic status bits here, but I don't
* know which of them are reserved. At least three or so should
* be added to make this really useful.
*/
#define GMT_EOF(x) ((x) & 0x80000000)
#define GMT_BOT(x) ((x) & 0x40000000)
#define GMT_EOT(x) ((x) & 0x20000000)
#define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */
#define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */
#define GMT_WR_PROT(x) ((x) & 0x04000000)
/* #define GMT_ ? ((x) & 0x02000000) */
#define GMT_ONLINE(x) ((x) & 0x01000000)
#define GMT_D_6250(x) ((x) & 0x00800000)
#define GMT_D_1600(x) ((x) & 0x00400000)
#define GMT_D_800(x) ((x) & 0x00200000)
#define GMT_PADDING(x) ((x) & 0x00100000) /* data padding */
#define GMT_HW_ECC(x) ((x) & 0x00080000) /* HW error correction */
#define GMT_DR_OPEN(x) ((x) & 0x00040000) /* door open (no tape) */
#define GMT_HW_COMP(x) ((x) & 0x00020000) /* HW compression */
#define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* immediate report mode */
/* 16 generic status bits unused */
/* SCSI-tape specific definitions */
/* Bitfield shifts in the status mt_dsreg */
#define MT_ST_BLKSIZE_SHIFT 0
#define MT_ST_BLKSIZE_MASK 0xffffff
#define MT_ST_DENSITY_SHIFT 24
#define MT_ST_DENSITY_MASK 0xff000000
#define MT_ST_SOFTERR_SHIFT 0
#define MT_ST_SOFTERR_MASK 0xffff
/*
* Constants for mt_type. Not all of these are supported,
* and these are not all of the ones that are supported.
*/
#define MT_ISUNKNOWN 0x01
#define MT_ISQIC02 0x02 /* Generic QIC-02 tape streamer */
#define MT_ISWT5150 0x03 /* Wangtek 5150EQ, QIC-150, QIC-02 */
#define MT_ISARCHIVE_5945L2 0x04 /* Archive 5945L-2, QIC-24, QIC-02? */
#define MT_ISCMSJ500 0x05 /* CMS Jumbo 500 (QIC-02?) */
#define MT_ISTDC3610 0x06 /* Tandberg 6310, QIC-24 */
#define MT_ISARCHIVE_VP60I 0x07 /* Archive VP60i, QIC-02 */
#define MT_ISARCHIVE_2150L 0x08 /* Archive Viper 2150L */
#define MT_ISARCHIVE_2060L 0x09 /* Archive Viper 2060L */
#define MT_ISARCHIVESC499 0x0A /* Archive SC-499 QIC-36 controller */
#define MT_ISQIC02_ALL_FEATURES 0x0F /* Generic QIC-02 with all features */
#define MT_ISWT5099EEN24 0x11 /* Wangtek 5099-een24, 60MB, QIC-24 */
#define MT_ISTEAC_MT2ST 0x12 /* Teac MT-2ST 155mb drive, Teac DC-1 card (Wangtek type) */
#define MT_ISEVEREX_FT40A 0x32 /* Everex FT40A (QIC-40) */
#define MT_ISDDS1 0x51 /* DDS device without partitions */
#define MT_ISDDS2 0x52 /* DDS device with partitions */
#define MT_ISSCSI1 0x71 /* Generic ANSI SCSI-1 tape unit */
#define MT_ISSCSI2 0x72 /* Generic ANSI SCSI-2 tape unit */
struct mt_tape_info {
long t_type; /* device type id (mt_type) */
char *t_name; /* descriptive name */
};
#define MT_TAPE_INFO { \
{MT_ISUNKNOWN, "Unknown type of tape device"}, \
{MT_ISQIC02, "Generic QIC-02 tape streamer"}, \
{MT_ISWT5150, "Wangtek 5150, QIC-150"}, \
{MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \
{MT_ISCMSJ500, "CMS Jumbo 500"}, \
{MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \
{MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \
{MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \
{MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \
{MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \
{MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \
{MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \
{MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \
{MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \
{MT_ISSCSI1, "Generic SCSI-1 tape"}, \
{MT_ISSCSI2, "Generic SCSI-2 tape"}, \
{0, NULL} \
}
#endif /* _CYGWIN_MTIO_H */

View File

@ -0,0 +1,30 @@
/*
* cygwin/rdevio.h header file for Cygwin.
*
* Written by C. Vinschen.
*/
#ifndef _CYGWIN_RDEVIO_H
#define _CYGWIN_RDEVIO_H
/* structure for RDIOCDOP - raw device operation */
struct rdop {
short rd_op;
unsigned long rd_parm;
};
/* Raw device operations */
#define RDSETBLK 1 /* set buffer for driver */
/* structure for RDIOCGET - get raw device */
struct rdget {
unsigned long bufsiz;
};
/*
* ioctl commands
*/
#define RDIOCDOP _IOW('r', 128, struct rdop)
#define RDIOCGET _IOR('r', 129, struct rdget)
#endif /* _CYGWIN_RDEVIO_H */

View File

@ -0,0 +1,152 @@
#ifndef _CYGWIN_SOCKET_H
#define _CYGWIN_SOCKET_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
#include <asm/socket.h> /* arch-dependent defines */
#include <cygwin/sockios.h> /* the SIOCxxx I/O controls */
#include <cygwin/uio.h> /* iovec support */
#include <sys/types.h>
struct linger {
unsigned short l_onoff; /* Linger active */
unsigned short l_linger; /* How long to linger for */
};
struct msghdr
{
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
int msg_iovlen; /* Number of blocks */
void * msg_accrights; /* Per protocol magic (eg BSD file descriptor passing) */
int msg_accrightslen; /* Length of rights list */
};
/* Socket types. */
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
#define SOCK_RAW 3 /* raw socket */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequential packet socket */
#define SOCK_PACKET 10 /* CYGWIN specific way of */
/* getting packets at the dev */
/* level. For writing rarp and */
/* other similar things on the */
/* user level. */
/* Supported address families. */
/*
* Address families.
*/
#define AF_UNSPEC 0 /* unspecified */
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_MAX 18
/*
* Protocol families, same as address families for now.
*/
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_LOCAL AF_LOCAL
#define PF_INET AF_INET
#define PF_IMPLINK AF_IMPLINK
#define PF_PUP AF_PUP
#define PF_CHAOS AF_CHAOS
#define PF_NS AF_NS
#define PF_ISO AF_ISO
#define PF_OSI AF_OSI
#define PF_ECMA AF_ECMA
#define PF_DATAKIT AF_DATAKIT
#define PF_CCITT AF_CCITT
#define PF_SNA AF_SNA
#define PF_DECnet AF_DECnet
#define PF_DLI AF_DLI
#define PF_LAT AF_LAT
#define PF_HYLINK AF_HYLINK
#define PF_APPLETALK AF_APPLETALK
#define PF_NETBIOS AF_NETBIOS
#define PF_MAX AF_MAX
/* Maximum queue length specificable by listen. */
#define SOMAXCONN 5
/* Flags we can use with send/ and recv. */
#define MSG_OOB 0x1 /* process out-of-band data */
#define MSG_PEEK 0x2 /* peek at incoming message */
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
#define SOL_IP 0
#define SOL_IPX 256
#define SOL_AX25 257
#define SOL_ATALK 258
#define SOL_NETROM 259
#define SOL_TCP 6
#define SOL_UDP 17
/* IP options */
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
/* These need to appear somewhere around here */
#define IP_DEFAULT_MULTICAST_TTL 1
#define IP_DEFAULT_MULTICAST_LOOP 1
#define IP_MAX_MEMBERSHIPS 20
/* IP options for use with WinSock */
#define IP_OPTIONS 1
#define IP_MULTICAST_IF 2
#define IP_MULTICAST_TTL 3
#define IP_MULTICAST_LOOP 4
#define IP_ADD_MEMBERSHIP 5
#define IP_DROP_MEMBERSHIP 6
#define IP_TTL 7
#define IP_TOS 8
#define IP_DONTFRAGMENT 9
/* IPX options */
#define IPX_TYPE 1
/* TCP options - this way around because someone left a set in the c library includes */
#define TCP_NODELAY 0x0001
#define TCP_MAXSEG 2
/* The various priorities. */
#define SOPRI_INTERACTIVE 0
#define SOPRI_NORMAL 1
#define SOPRI_BACKGROUND 2
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* _CYGWIN_SOCKET_H */

View File

@ -0,0 +1 @@
/* sockios.h */

View File

@ -0,0 +1 @@
/* types.h */

View File

@ -0,0 +1 @@
/* uio.h */

View File

@ -0,0 +1,159 @@
/* version.h -- Cygwin version numbers and accompanying documentation.
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
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. */
/* Cygwin versioning is relatively complicated because of its status
as a shared library. Let's start with how versioning used to be done.
Historical versioning in Cygwin 16.0 to 19.5:
In the olden days of Cygwin, we had a dll major and minor version
and a registry version. The major number started at 16 because the
"b15" GNU-Win32 release of the compiler tools was out when this
scheme was started. We incremented the DLL name frequently (for
every official release) and towards the end of this period every
release used a different shared memory area to prevent DLLs from
interfering with each other (embedding a build timestamp into the
name of the shared memory area). This turned out to be a Bad Idea
(tm) because people needed to mingle separate releases and have
them work together more than we thought they would. This was
especially problematic when tty info needed to be retained when an
old Cygwin executable executed a newer one.
In the old scheme, we incremented the major number whenever a
change to the dll invalidated existing executables. This can
happen for a number of reasons, including when functions are
removed from the export list of the dll. The minor number was
incremented when a change was made that we wanted to record, but
that didn't invalidate existing executables. Both numbers were
recorded in the executable and in the dll.
In October 1998 (starting with Cygwin 19.6), we started a new
means of Cygwin versioning: */
/* The DLL major and minor numbers correspond to the "version of
the Cygwin library". This version is used to track important
changes to the DLL and is mainly informative in nature. */
/* The current cygwin version is 1.1.0 */
#define CYGWIN_VERSION_DLL_MAJOR 1001
#define CYGWIN_VERSION_DLL_MINOR 0
/* Major numbers before CYGWIN_VERSION_DLL_EPOCH are
incompatible. */
#define CYGWIN_VERSION_DLL_EPOCH 19
/* CYGWIN_VERSION_DLL_COMBINED gives us a single number
representing the combined DLL major and minor numbers. */
#define CYGWIN_VERSION_DLL_MAKE_COMBINED(maj, min) (((maj) * 1000) + min)
#define CYGWIN_VERSION_DLL_COMBINED \
CYGWIN_VERSION_DLL_MAKE_COMBINED (CYGWIN_DLL_VERSION_MAJOR, CYGWIN_DLL_VERSION_MINOR)
/* Every version of cygwin <= this uses an old, incorrect method
to determine signal masks. */
#define CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK 19005
/* API versions <= this had a termios structure whose members were
too small to accomodate modern settings. */
#define CYGWIN_VERSION_DLL_OLD_TERMIOS 00005
#define CYGWIN_VERSION_DLL_IS_OLD_TERMIOS \
(CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) <= \
CYGWIN_VERSION_DLL_OLD_TERMIOS)
/* We used to use the DLL major/minor to track
non-backward-compatible interface changes to the API. Now we
use an API major/minor number for this purpose. */
/* API_MAJOR 0.0: Initial version. API_MINOR changes:
1: Export cygwin32_ calls as cygwin_ as well.
2: Export j1, jn, y1, yn.
3: Export dll_noncygwin_dllcrt0.
4: New socket ioctls, revamped ifconf support.
5: Thread support/exports.
6: Change in termios handling.
7: Export scandir and alphasort.
8: Export _ctype_, _sys_errlist, _sys_nerr.
9: Mount-related changes, new cygwin_umount export.
Raw device support (tape, floppies).
10: Fast math routine support added.
11: Export seekdir, telldir.
12: Export pthread_join, pthread_detach.
13: Export math funcs gamma and friends, also _j0, _j1, etc.
14: Export snprintf and vnsprintf.
15: Export glob
16: Export cygwin_stackdump
*/
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 16
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
changes are made to the shared memory region *or* to any named
shared mutexes, semaphores, etc. The arbitrary starting
version was 0 (cygwin release 98r2). */
#define CYGWIN_VERSION_SHARED_DATA 3
/* An identifier used in the names used to create shared objects.
The full names include the CYGWIN_VERSION_SHARED_DATA version
as well as this identifier. */
#define CYGWIN_VERSION_DLL_IDENTIFIER "cygwin1"
/* The Cygwin mount table interface in the Win32 registry also
has a version number associated with it in case that is
changed in a non-backwards compatible fashion. Increment this
version number whenever incompatible changes in mount table
registry usage are made.
1: Original number version.
2: New mount registry layout, system-wide mount accessibility.
*/
#define CYGWIN_VERSION_MOUNT_REGISTRY 2
/* Identifiers used in the Win32 registry. */
#define CYGWIN_INFO_CYGNUS_REGISTRY_NAME "Cygnus Solutions"
#define CYGWIN_INFO_CYGWIN_REGISTRY_NAME "Cygwin"
#define CYGWIN_INFO_PROGRAM_OPTIONS_NAME "Program Options"
#define CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME "mounts v2"
/* In addition to the above version number strings, the build
process adds some strings that may be useful in
debugging/identifying a particular Cygwin DLL:
The mkvers.sh script at the top level produces a .cc file
which initializes a cygwin_version structure based on the
above version information and creates a string table for
grepping via "fgrep '%%%' cygwinwhatever.dll" if you are
using GNU grep. Otherwise you may want to do a
"strings cygwinwhatever.dll | fgrep '%%%'" instead.
This will produce output such as:
%%% Cygwin dll_identifier: cygwin
%%% Cygwin api_major: 0
%%% Cygwin api_minor: 0
%%% Cygwin dll_major: 19
%%% Cygwin dll_minor: 6
%%% Cygwin shared_data: 1
%%% Cygwin registry: b15
%%% Cygwin build date: Wed Oct 14 16:26:51 EDT 1998
%%% Cygwin shared id: cygwinS1
This information can also be obtained through a call to
cygwin_internal (CW_GETVERSIONINFO).
*/

View File

@ -0,0 +1,41 @@
/* dlfcn.h
Copyright 1998 Cygnus Solutions
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _DLFCN_H
#define _DLFCN_H
#ifdef __cplusplus
extern "C" {
#endif
/* declarations used for dynamic linking support routines */
extern void *dlopen (const char *, int);
extern void *dlsym (void *, const char *);
extern int dlclose (void *);
extern char *dlerror (void);
/* specific to CYGWIN */
#define FORK_RELOAD 1
#define FORK_NO_RELOAD 0
extern void dlfork (int);
/* following doesn't exist in Win32 API .... */
/* valid values for mode argument to dlopen */
#define RTLD_LAZY 1 /* lazy function call binding */
#define RTLD_NOW 2 /* immediate function call binding */
#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */
#ifdef __cplusplus
}
#endif
#endif /* _DLFCN_H */

View File

@ -0,0 +1,120 @@
/* exceptions.h
Copyright 1996, 1997, 1998 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _EXCEPTIONS_H
#define _EXCEPTIONS_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Documentation on the innards of exception handling (i.e. from the
perspective of a compiler implementor) apparently doesn't exist. Sigh.
However, the following came from Onno Hovers <onno@stack.urc.tue.nl>
The first pointer to the chain of handlers is in the thread environment block
at FS:[0]. This chain has the following format:
typedef struct __EXCEPTION_FRAME
{
struct __EXCEPTION_FRAME *Prev; /-* pointer to the previous frame *-/
PEXCEPTION_HANDLER Handler; /-* handler function *-/
}
You register an exception handler in your compiler with this simple ASM
sequence:
PUSH _MyExceptionHandler
PUSH FS:[0]
MOV FS:[0],ESP
An exception frame MUST be on the stack! The frame may have more fields and
both Visual C++ and Borland C++ use more fields for themselves.
When an exception occurs the system calls all handlers starting with the
handler at FS:0, and then the previous etc. until one handler returns
ExceptionContinueExecution, which is 0. If a handler does not want to handle
the exception it should just return ExceptionContinueSearch, which is 1.
The handler has the following parameters:
ehandler (
PEXCEPTION_RECORD erecord,
PEXCEPTION_FRAME myframe,
PCONTEXT context, /-* context before and after *-/
PVOID dispatch ) /-* something *-/
When a handler wants to handle the exception, it has some alternatives:
-one is to do do something about the exception condition, like emulating
an invalid instruction, mapping memory where there was a page fault, etc.
If the handler wants to have the context of the thread that causes the
exception changed, it should make that change in the context passed to the
handler.
-the second alternative is to call all exception handlers again, indicating
that you want them to clean up. This way all the __finally blocks get
executed. After doing that you change the context passed to the handler so
the code starts executing in the except block. For this purpose you could
call RtlUnwind. This (undocumented) function calls all exception handlers
up to but not including the exception frame passed to it. If NULL is passed
as exception frame RtlUnwind calls all exception handlers and then exits the
process. The parameters to RtlUnwind are:
RtlUnwind (
PEXCEPTION_FRAME endframe,
PVOID unusedEip,
PEXCEPTION_RECORD erecord,
DWORD returnEax)
You should set unusedEip to the address where RtlUnwind should return like
this:
PUSH 0
PUSH OFFSET ReturnUnwind
PUSH 0
PUSH 0
CALL RtlUnwind
ReturnUnwind:
.....
If no EXCEPTION_RECORD is passed, RtlUnwind makes a default exception
record. In any case, the ExceptionFlags part of this record has the
EH_UNWINDING (=2), flag set. (and EH_EXIT_UNWIND (=4), when NULL is passed as the end
frame.).
The handler for a exception as well as a for unwinds may be executed in the
thread causing the exception, but may also be executed in another (special
exception) thread. So it is not wise to make any assumptions about that!
As an alternative you may consider the SetUnhandledExceptionFilter API
to install your own exception filter. This one is documented.
*/
/* The January 1994 MSJ has an article entitled "Clearer, More Comprehensive
Error Processing with Win32 Structured Exception Handling". It goes into
a teensy bit of detail of the innards of exception handling (i.e. what we
have to do). */
typedef int (exception_handler)
(EXCEPTION_RECORD *, void *, CONTEXT *, void *);
typedef struct _exception_list
{
struct _exception_list *prev;
exception_handler *handler;
/* We're apparently free to add more stuff here.
At present we don't need any. */
} exception_list;
void init_exceptions (exception_list *);
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* _EXCEPTIONS_H */

View File

@ -0,0 +1,7 @@
#ifndef _FCNTL_H
#define _FCNTL_H
#include <sys/fcntl.h>
#define O_NDELAY _FNDELAY
#endif /* _FCNTL_H */

View File

@ -0,0 +1 @@
/* features.h */

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 1987, 1993, 1994, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __GETOPT_H__
#define __GETOPT_H__
#ifdef __cplusplus
extern "C" {
#endif
struct option {
char * name;
int has_arg;
int * flag;
int val;
};
extern int opterr; /* if error message should be printed */
extern int optind; /* index into parent argv vector */
extern int optopt; /* character checked for validity */
extern int optreset; /* reset getopt */
extern char *optarg; /* argument associated with option */
int getopt (int, char * const *, const char *);
int getopt_long (int, char **, char *, struct option *, int *);
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#ifdef __cplusplus
}
#endif
#endif /* __GETOPT_H__ */

View File

@ -0,0 +1,111 @@
/* $NetBSD: glob.h,v 1.6.2.2 1997/11/04 23:38:33 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)glob.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _GLOB_H_
#define _GLOB_H_
/* CYGNUS LOCAL: end */
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct {
int gl_pathc; /* Count of total paths so far. */
int gl_matchc; /* Count of paths matching pattern. */
int gl_offs; /* Reserved at beginning of gl_pathv. */
int gl_flags; /* Copy of flags parameter to glob. */
char **gl_pathv; /* List of paths matching pattern. */
/* Copy of errfunc parameter to glob. */
int (*gl_errfunc) __P((const char *, int));
/*
* Alternate filesystem access methods for glob; replacement
* versions of closedir(3), readdir(3), opendir(3), stat(2)
* and lstat(2).
*/
void (*gl_closedir) __P((void *));
struct dirent *(*gl_readdir) __P((void *));
void *(*gl_opendir) __P((const char *));
#ifdef __LIBC12_SOURCE__
int (*gl_lstat) __P((const char *, struct stat12 *));
int (*gl_stat) __P((const char *, struct stat12 *));
#else
int (*gl_lstat) __P((const char *, struct stat *));
int (*gl_stat) __P((const char *, struct stat *));
#endif
} glob_t;
#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
#define GLOB_ERR 0x0004 /* Return on error. */
#define GLOB_MARK 0x0008 /* Append / to matching directories. */
#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
#define GLOB_NOSORT 0x0020 /* Don't sort. */
#ifndef _POSIX_SOURCE
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
#endif
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
#define GLOB_ABEND (-2) /* Unignored error. */
__BEGIN_DECLS
/* CYGNUS LOCAL: normal protos */
#undef DLLEXPORT
#ifdef __INSIDE_CYGWIN__
# define DLLEXPORT
#else
# define DLLEXPORT __declspec(dllimport)
#endif
int DLLEXPORT glob(const char *, int, int (*)(const char *, int), glob_t *);
void DLLEXPORT globfree(glob_t *);
#undef DLLEXPORT
/* end CYGNUS LOCAL */
__END_DECLS
#endif /* !_GLOB_H_ */

View File

@ -0,0 +1 @@
/* icmp.h */

View File

@ -0,0 +1,28 @@
/* io.h
Copyright 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _IO_H_
#define _IO_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Function to return a Win32 HANDLE from a fd.
*/
extern long get_osfhandle(int);
extern int setmode (int __fd, int __mode);
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* _IO_H_ */

View File

@ -0,0 +1,12 @@
#ifndef _LASTLOG_H
#define _LASTLOG_H
#include <utmp.h>
struct lastlog {
long ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
#endif

View File

@ -0,0 +1,144 @@
/* limits.h
Copyright 1999, 2000 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _LIMITS_H___
#ifndef _MACH_MACHLIMITS_H_
/* _MACH_MACHLIMITS_H_ is used on OSF/1. */
#define _LIMITS_H___
#define _MACH_MACHLIMITS_H_
/* Number of bits in a `char'. */
#undef CHAR_BIT
#define CHAR_BIT 8
/* Maximum length of a multibyte character. */
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 1
#endif
/* Minimum and maximum values a `signed char' can hold. */
#undef SCHAR_MIN
#define SCHAR_MIN (-128)
#undef SCHAR_MAX
#define SCHAR_MAX 127
/* Maximum value an `unsigned char' can hold. (Minimum is 0). */
#undef UCHAR_MAX
#define UCHAR_MAX 255
/* Minimum and maximum values a `char' can hold. */
#ifdef __CHAR_UNSIGNED__
#undef CHAR_MIN
#define CHAR_MIN 0
#undef CHAR_MAX
#define CHAR_MAX 255
#else
#undef CHAR_MIN
#define CHAR_MIN (-128)
#undef CHAR_MAX
#define CHAR_MAX 127
#endif
/* Minimum and maximum values a `signed short int' can hold. */
#undef SHRT_MIN
#define SHRT_MIN (-32768)
#undef SHRT_MAX
#define SHRT_MAX 32767
/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */
#undef USHRT_MAX
#define USHRT_MAX 65535
/* Minimum and maximum values a `signed int' can hold. */
#ifndef __INT_MAX__
#define __INT_MAX__ 2147483647
#endif
#undef INT_MIN
#define INT_MIN (-INT_MAX-1)
#undef INT_MAX
#define INT_MAX __INT_MAX__
/* Maximum value an `unsigned int' can hold. (Minimum is 0). */
#undef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
/* Minimum and maximum values a `signed long int' can hold.
(Same as `int'). */
#ifndef __LONG_MAX__
#ifndef __alpha__
#define __LONG_MAX__ 2147483647L
#else
#define __LONG_MAX__ 9223372036854775807L
# endif /* __alpha__ */
#endif
#undef LONG_MIN
#define LONG_MIN (-LONG_MAX-1)
#undef LONG_MAX
#define LONG_MAX __LONG_MAX__
/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */
#undef ULONG_MAX
#define ULONG_MAX (LONG_MAX * 2UL + 1)
#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)
/* Minimum and maximum values a `signed long long int' can hold. */
#ifndef __LONG_LONG_MAX__
#define __LONG_LONG_MAX__ 9223372036854775807LL
#endif
#undef LONG_LONG_MIN
#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
#undef LONG_LONG_MAX
#define LONG_LONG_MAX __LONG_LONG_MAX__
/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */
#undef ULONG_LONG_MAX
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
#endif
/* Maximum number of iovcnt in a writev */
#undef IOV_MAX
#define IOV_MAX (__INT_MAX__-1)
/* Maximum size of ssize_t */
#undef SSIZE_MAX
#define SSIZE_MAX (__LONG_MAX__)
/* Maximum length of a path */
#define PATH_MAX (260 - 1 /*NUL*/)
/* Max num groups for a user, value taken from NT documentation */
/* Must match <sys/param.h> NGROUPS */
#define NGROUPS_MAX 16
/* WaitForMultipleObjects can't handle waiting for more than 64 objects.
This limits how many children we can fork/spawn off. */
#define CHILD_MAX 63
/* POSIX values */
/* These should never vary from one system type to another */
/* They represent the minimum values that POSIX systems must support.
POSIX-conforming apps must not require larger values. */
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 6
#define _POSIX_LINK_MAX 8
#define _POSIX_MAX_CANON 255
#define _POSIX_MAX_INPUT 255
#define _POSIX_NAME_MAX 14
#define _POSIX_NGROUPS_MAX 0
#define _POSIX_OPEN_MAX 16
#define _POSIX_PATH_MAX 255
#define _POSIX_PIPE_BUF 512
#define _POSIX_SSIZE_MAX 32767
#define _POSIX_STREAM_MAX 8
#define _POSIX_TZNAME_MAX 3
#endif /* _MACH_MACHLIMITS_H_ */
#endif /* _LIMITS_H___ */

View File

@ -0,0 +1,102 @@
/* mapi.h
Copyright 1997, 1998 Cygnus Solutions.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _MAPI_H
#define _MAPI_H
/* Currently this doesn't include all the definitions. It does cover
the parts of Simple MAPI required to send mail. */
#ifdef __cplusplus
extern "C"
{
#endif
/* FIXME: should this be elsewhere? */
typedef unsigned long FLAGS;
/* FIXME: should this be elsewhere? */
#define SUCCESS_SUCCESS 0
/* FIXME: should this be elsewhere? */
typedef unsigned long LHANDLE, FAR *LPLHANDLE;
#define MAPI_E_AMBIGUOUS_RECIPIENT 0x15
#define MAPI_E_ATTACHMENT_NOT_FOUND 0xb
#define MAPI_E_ATTACHMENT_OPEN_FAILURE 0xc
#define MAPI_E_BAD_RECIPTYPE 0xf
#define MAPI_E_FAILURE 0x2
#define MAPI_E_INSUFFICIENT_MEMORY 0x5
#define MAPI_E_INVALID_RECIPS 0x19
#define MAPI_E_LOGIN_FAILURE 0x3
#define MAPI_E_TEXT_TOO_LARGE 0x12
#define MAPI_E_TOO_MANY_FILES 0x9
#define MAPI_E_TOO_MANY_RECIPIENTS 0xa
#define MAPI_E_UNKNOWN_RECIPIENT 0xe
#define MAPI_E_USER_ABORT 0x1
#define MAPI_E_TEXT_TOO_LARGE 0x12
#define MAPI_DIALOG 0x8
#define MAPI_NEW_SESSION 0x2
#define MAPI_LOGON_UI 0x1
#define MAPI_RECEIPT_REQUESTED 0x2
#define MAPI_SENT 0x4
#define MAPI_UNREAD 0x1
#define MAPI_OLE 0x1
#define MAPI_OLE_STATIC 0x2
#define MAPI_ORIG 0
#define MAPI_TO 1
#define MAPI_CC 2
#define MAPI_BCC 3
typedef struct
{
ULONG ulReserved;
ULONG flFlags;
ULONG nPosition;
LPTSTR lpszPathName;
LPTSTR lpszFileName;
LPVOID lpFileType;
} MapiFileDesc, FAR *lpMapiFileDesc;
typedef struct
{
ULONG ulReserved;
ULONG ulRecipClass;
LPTSTR lpszName;
LPTSTR lpszAddress;
ULONG ulEIDSize;
LPVOID lpEntryID;
} MapiRecipDesc, FAR *lpMapiRecipDesc;
typedef struct
{
ULONG ulReserved;
LPTSTR lpszSubject;
LPTSTR lpszNoteText;
LPTSTR lpszMessageType;
LPTSTR lpszDateReceived;
LPTSTR lpszConversationID;
FLAGS flFlags;
lpMapiRecipDesc lpOriginator;
ULONG nRecipCount;
lpMapiRecipDesc lpRecips;
ULONG nFileCount;
lpMapiFileDesc lpFiles;
} MapiMessage, FAR *lpMapiMessage;
ULONG FAR PASCAL MAPISendMail (LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG);
#ifdef __cplusplus
}
#endif
#endif /* _MAPI_H */

View File

@ -0,0 +1,7 @@
#ifndef _MEMORY_H
#define _MEMORY_H
/* This allows more things to compile. */
#include <string.h>
#endif /* _MEMORY_H */

View File

@ -0,0 +1,35 @@
#ifndef _MNTENT_H
#define _MNTENT_H
#ifdef __cplusplus
extern "C" {
#endif
struct mntent
{
char *mnt_fsname;
char *mnt_dir;
char *mnt_type;
char *mnt_opts;
int mnt_freq;
int mnt_passno;
};
FILE *setmntent (const char *__filep, const char *__type);
struct mntent *getmntent (FILE *__filep);
int addmntent (FILE *__filep, const struct mntent *__mnt);
int endmntent (FILE *__filep);
char *hasmntopt (const struct mntent *__mnt, const char *__opt);
/* This next file doesn't exist, it is in the registry,
however applications need the define to pass to
the above calls.
*/
#ifndef MOUNTED
#define MOUNTED "/etc/mtab"
#endif
#ifdef __cplusplus
};
#endif
#endif /* _MNTENT_H */

View File

@ -0,0 +1,6 @@
#ifndef _NET_IF_H
#define _NET_IF_H
#include <cygwin/if.h>
#endif /* _NET_IF_H */

View File

@ -0,0 +1,167 @@
/* Original linux netdb.h merged with winsock.h types */
/*-
* Copyright (c) 1980, 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)netdb.h 8.1 (Berkeley) 6/2/93
* netdb.h,v 1.1.1.1 1995/02/18 05:34:07 hjl Exp
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#ifndef _NETDB_H_
#define _NETDB_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* Structures returned by network data base library. All addresses are
* supplied in host order, and returned in network order (suitable for
* use in system calls).
*/
/* Different from the linux versions - note the shorts.. */
struct hostent {
const char *h_name; /* official name of host */
char **h_aliases; /* alias list */
short h_addrtype; /* host address type */
short h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
};
/*
* Assumption here is that a network number
* fits in an unsigned long -- probably a poor one.
*/
struct netent {
char *n_name; /* official name of net */
char **n_aliases; /* alias list */
short n_addrtype; /* net address type */
unsigned long n_net; /* network # */
};
struct servent {
char *s_name; /* official service name */
char **s_aliases; /* alias list */
short s_port; /* port # */
char *s_proto; /* protocol to use */
};
struct protoent
{
char *p_name; /* official protocol name */
char **p_aliases; /* alias list */
short p_proto; /* protocol # */
};
struct rpcent {
char *r_name; /* name of server for this rpc program */
char **r_aliases; /* alias list */
int r_number; /* rpc program number */
};
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (left in extern int h_errno).
*/
#ifdef __INSIDE_CYGWIN_NET__
extern int h_errno;
#else
extern __declspec(dllimport) int h_errno;
#endif
#define NETDB_INTERNAL -1 /* see errno */
#define NETDB_SUCCESS 0 /* no problem */
#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define NO_DATA 4 /* Valid name, no data record of requested type */
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
#ifndef __INSIDE_CYGWIN_NET__
void endhostent (void);
void endnetent (void);
void endprotoent (void);
void endservent (void);
void endrpcent (void);
struct hostent *gethostbyaddr (const char *, int, int);
struct hostent *gethostbyname (const char *);
struct hostent *gethostent (void);
struct netent *getnetbyaddr (long, int); /* u_long? */
struct netent *getnetbyname (const char *);
struct netent *getnetent (void);
struct protoent *getprotobyname (const char *);
struct protoent *getprotobynumber (int);
struct protoent *getprotoent (void);
struct servent *getservbyname (const char *, const char *);
struct servent *getservbyport (int, const char *);
struct servent *getservent (void);
struct rpcent *getrpcent (void);
struct rpcent *getrpcbyname (const char *);
struct rpcent *getrpcbynumber (int);
void herror (const char *);
void sethostent (int);
void setnetent (int);
void setprotoent (int);
void setservent (int);
void setrpcent (int);
#endif
#ifdef __cplusplus
};
#endif
#endif /* !_NETDB_H_ */

View File

@ -0,0 +1,6 @@
#ifndef _NETINET_IN_H
#define _NETINET_IN_H
#include <cygwin/in.h>
#endif /* _NETINET_IN_H */

View File

@ -0,0 +1,6 @@
#ifndef _NETINET_IP_H
#define _NETINET_IP_H
#include <cygwin/ip.h>
#endif /* _NETINET_IP_H */

View File

@ -0,0 +1,6 @@
#ifndef _NETINET_IP_ICMP_H
#define _NETINET_IP_ICMP_H
#include <cygwin/icmp.h>
#endif /* _NETINET_IP_ICMP_H */

Some files were not shown because too many files have changed in this diff Show More