import winsup-2000-02-17 snapshot
This commit is contained in:
46
winsup/CYGWIN_LICENSE
Normal file
46
winsup/CYGWIN_LICENSE
Normal 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
36
winsup/ChangeLog
Normal 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
17
winsup/MAINTAINERS
Normal 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
127
winsup/Makefile.common
Normal 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
71
winsup/Makefile.in
Normal 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
1223
winsup/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
65
winsup/configure.in
Executable file
65
winsup/configure.in
Executable 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)
|
46
winsup/cygwin/CYGWIN_LICENSE
Normal file
46
winsup/cygwin/CYGWIN_LICENSE
Normal 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
229
winsup/cygwin/ChangeLog
Normal 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.
|
177
winsup/cygwin/ChangeLog-1995
Normal file
177
winsup/cygwin/ChangeLog-1995
Normal 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
2031
winsup/cygwin/ChangeLog-1996
Normal file
File diff suppressed because it is too large
Load Diff
2800
winsup/cygwin/ChangeLog-1997
Normal file
2800
winsup/cygwin/ChangeLog-1997
Normal file
File diff suppressed because it is too large
Load Diff
4490
winsup/cygwin/ChangeLog-1998
Normal file
4490
winsup/cygwin/ChangeLog-1998
Normal file
File diff suppressed because it is too large
Load Diff
3552
winsup/cygwin/ChangeLog-1999
Normal file
3552
winsup/cygwin/ChangeLog-1999
Normal file
File diff suppressed because it is too large
Load Diff
341
winsup/cygwin/Makefile.in
Normal file
341
winsup/cygwin/Makefile.in
Normal 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
129
winsup/cygwin/ROADMAP
Normal 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
15
winsup/cygwin/acconfig.h
Normal 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
59
winsup/cygwin/ansi.sgml
Normal 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
50
winsup/cygwin/assert.cc
Normal 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
38
winsup/cygwin/config.h.in
Normal 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
|
51
winsup/cygwin/config/i386/longjmp.c
Normal file
51
winsup/cygwin/config/i386/longjmp.c
Normal 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__ */
|
17
winsup/cygwin/config/i386/makefrag
Normal file
17
winsup/cygwin/config/i386/makefrag
Normal 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) $<
|
58
winsup/cygwin/config/i386/profile.h
Normal file
58
winsup/cygwin/config/i386/profile.h
Normal 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); \
|
||||
}
|
||||
|
48
winsup/cygwin/config/i386/setjmp.c
Normal file
48
winsup/cygwin/config/i386/setjmp.c
Normal 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
2335
winsup/cygwin/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
229
winsup/cygwin/configure.in
Normal file
229
winsup/cygwin/configure.in
Normal 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
1051
winsup/cygwin/cygwin.din
Normal file
File diff suppressed because it is too large
Load Diff
1063
winsup/cygwin/dcrt0.cc
Normal file
1063
winsup/cygwin/dcrt0.cc
Normal file
File diff suppressed because it is too large
Load Diff
326
winsup/cygwin/debug.cc
Normal file
326
winsup/cygwin/debug.cc
Normal 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
69
winsup/cygwin/debug.h
Normal 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
99
winsup/cygwin/delqueue.cc
Normal 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
340
winsup/cygwin/dir.cc
Normal 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
236
winsup/cygwin/dlfcn.cc
Normal 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
499
winsup/cygwin/dll_init.cc
Normal 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
102
winsup/cygwin/dll_init.h
Normal 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++; \
|
||||
} \
|
||||
}
|
||||
|
11
winsup/cygwin/dll_init.sgml
Normal file
11
winsup/cygwin/dll_init.sgml
Normal 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
603
winsup/cygwin/dtable.cc
Normal 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
20
winsup/cygwin/dtable.sgml
Normal 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
567
winsup/cygwin/environ.cc
Normal 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
669
winsup/cygwin/errno.cc
Normal 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
1066
winsup/cygwin/exceptions.cc
Normal file
File diff suppressed because it is too large
Load Diff
204
winsup/cygwin/exec.cc
Normal file
204
winsup/cygwin/exec.cc
Normal 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
107
winsup/cygwin/external.cc
Normal 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;
|
||||
}
|
||||
}
|
16
winsup/cygwin/external.sgml
Normal file
16
winsup/cygwin/external.sgml
Normal 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
106
winsup/cygwin/fcntl.cc
Normal 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
1501
winsup/cygwin/fhandler.cc
Normal file
File diff suppressed because it is too large
Load Diff
804
winsup/cygwin/fhandler.h
Normal file
804
winsup/cygwin/fhandler.h
Normal 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_ */
|
1387
winsup/cygwin/fhandler_console.cc
Normal file
1387
winsup/cygwin/fhandler_console.cc
Normal file
File diff suppressed because it is too large
Load Diff
90
winsup/cygwin/fhandler_floppy.cc
Normal file
90
winsup/cygwin/fhandler_floppy.cc
Normal 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);
|
||||
}
|
||||
|
495
winsup/cygwin/fhandler_raw.cc
Normal file
495
winsup/cygwin/fhandler_raw.cc
Normal 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;
|
||||
}
|
883
winsup/cygwin/fhandler_serial.cc
Normal file
883
winsup/cygwin/fhandler_serial.cc
Normal 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);
|
||||
}
|
829
winsup/cygwin/fhandler_tape.cc
Normal file
829
winsup/cygwin/fhandler_tape.cc
Normal 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;
|
||||
}
|
||||
|
293
winsup/cygwin/fhandler_termios.cc
Normal file
293
winsup/cygwin/fhandler_termios.cc
Normal 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;
|
||||
}
|
1070
winsup/cygwin/fhandler_tty.cc
Normal file
1070
winsup/cygwin/fhandler_tty.cc
Normal file
File diff suppressed because it is too large
Load Diff
145
winsup/cygwin/fhandler_windows.cc
Normal file
145
winsup/cygwin/fhandler_windows.cc
Normal 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_");
|
||||
}
|
58
winsup/cygwin/fhandler_zero.cc
Normal file
58
winsup/cygwin/fhandler_zero.cc
Normal 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
625
winsup/cygwin/fork.cc
Normal 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
41
winsup/cygwin/gcrt0.c
Normal 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
871
winsup/cygwin/glob.c
Normal 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
277
winsup/cygwin/gmon.c
Normal 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
166
winsup/cygwin/gmon.h
Normal 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
283
winsup/cygwin/grp.cc
Normal 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
140
winsup/cygwin/heap.cc
Normal 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;
|
||||
}
|
421
winsup/cygwin/include/a.out.h
Normal file
421
winsup/cygwin/include/a.out.h
Normal 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_ */
|
||||
|
109
winsup/cygwin/include/arpa/ftp.h
Normal file
109
winsup/cygwin/include/arpa/ftp.h
Normal 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 */
|
25
winsup/cygwin/include/arpa/inet.h
Normal file
25
winsup/cygwin/include/arpa/inet.h
Normal 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 */
|
322
winsup/cygwin/include/arpa/telnet.h
Normal file
322
winsup/cygwin/include/arpa/telnet.h
Normal 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 */
|
93
winsup/cygwin/include/asm/byteorder.h
Normal file
93
winsup/cygwin/include/asm/byteorder.h
Normal 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
|
58
winsup/cygwin/include/asm/socket.h
Normal file
58
winsup/cygwin/include/asm/socket.h
Normal 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 */
|
||||
|
13
winsup/cygwin/include/asm/types.h
Normal file
13
winsup/cygwin/include/asm/types.h
Normal 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 */
|
81
winsup/cygwin/include/cygwin/acl.h
Normal file
81
winsup/cygwin/include/cygwin/acl.h
Normal 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 */
|
96
winsup/cygwin/include/cygwin/cygwin_dll.h
Normal file
96
winsup/cygwin/include/cygwin/cygwin_dll.h
Normal 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__ */
|
1
winsup/cygwin/include/cygwin/icmp.h
Normal file
1
winsup/cygwin/include/cygwin/icmp.h
Normal file
@ -0,0 +1 @@
|
||||
/* icmp.h */
|
74
winsup/cygwin/include/cygwin/if.h
Normal file
74
winsup/cygwin/include/cygwin/if.h
Normal 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_ */
|
188
winsup/cygwin/include/cygwin/in.h
Normal file
188
winsup/cygwin/include/cygwin/in.h
Normal 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 */
|
190
winsup/cygwin/include/cygwin/mtio.h
Normal file
190
winsup/cygwin/include/cygwin/mtio.h
Normal 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 */
|
30
winsup/cygwin/include/cygwin/rdevio.h
Normal file
30
winsup/cygwin/include/cygwin/rdevio.h
Normal 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 */
|
152
winsup/cygwin/include/cygwin/socket.h
Normal file
152
winsup/cygwin/include/cygwin/socket.h
Normal 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 */
|
1
winsup/cygwin/include/cygwin/sockios.h
Normal file
1
winsup/cygwin/include/cygwin/sockios.h
Normal file
@ -0,0 +1 @@
|
||||
/* sockios.h */
|
1
winsup/cygwin/include/cygwin/types.h
Normal file
1
winsup/cygwin/include/cygwin/types.h
Normal file
@ -0,0 +1 @@
|
||||
/* types.h */
|
1
winsup/cygwin/include/cygwin/uio.h
Normal file
1
winsup/cygwin/include/cygwin/uio.h
Normal file
@ -0,0 +1 @@
|
||||
/* uio.h */
|
159
winsup/cygwin/include/cygwin/version.h
Normal file
159
winsup/cygwin/include/cygwin/version.h
Normal 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).
|
||||
*/
|
||||
|
41
winsup/cygwin/include/dlfcn.h
Normal file
41
winsup/cygwin/include/dlfcn.h
Normal 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 */
|
120
winsup/cygwin/include/exceptions.h
Normal file
120
winsup/cygwin/include/exceptions.h
Normal 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 */
|
7
winsup/cygwin/include/fcntl.h
Normal file
7
winsup/cygwin/include/fcntl.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _FCNTL_H
|
||||
#define _FCNTL_H
|
||||
|
||||
#include <sys/fcntl.h>
|
||||
#define O_NDELAY _FNDELAY
|
||||
|
||||
#endif /* _FCNTL_H */
|
1
winsup/cygwin/include/features.h
Normal file
1
winsup/cygwin/include/features.h
Normal file
@ -0,0 +1 @@
|
||||
/* features.h */
|
66
winsup/cygwin/include/getopt.h
Normal file
66
winsup/cygwin/include/getopt.h
Normal 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__ */
|
111
winsup/cygwin/include/glob.h
Normal file
111
winsup/cygwin/include/glob.h
Normal 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_ */
|
1
winsup/cygwin/include/icmp.h
Normal file
1
winsup/cygwin/include/icmp.h
Normal file
@ -0,0 +1 @@
|
||||
/* icmp.h */
|
28
winsup/cygwin/include/io.h
Normal file
28
winsup/cygwin/include/io.h
Normal 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_ */
|
12
winsup/cygwin/include/lastlog.h
Normal file
12
winsup/cygwin/include/lastlog.h
Normal 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
|
144
winsup/cygwin/include/limits.h
Normal file
144
winsup/cygwin/include/limits.h
Normal 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___ */
|
102
winsup/cygwin/include/mapi.h
Normal file
102
winsup/cygwin/include/mapi.h
Normal 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 */
|
7
winsup/cygwin/include/memory.h
Normal file
7
winsup/cygwin/include/memory.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H
|
||||
|
||||
/* This allows more things to compile. */
|
||||
#include <string.h>
|
||||
|
||||
#endif /* _MEMORY_H */
|
35
winsup/cygwin/include/mntent.h
Normal file
35
winsup/cygwin/include/mntent.h
Normal 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 */
|
6
winsup/cygwin/include/net/if.h
Normal file
6
winsup/cygwin/include/net/if.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _NET_IF_H
|
||||
#define _NET_IF_H
|
||||
|
||||
#include <cygwin/if.h>
|
||||
|
||||
#endif /* _NET_IF_H */
|
167
winsup/cygwin/include/netdb.h
Normal file
167
winsup/cygwin/include/netdb.h
Normal 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_ */
|
||||
|
6
winsup/cygwin/include/netinet/in.h
Normal file
6
winsup/cygwin/include/netinet/in.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _NETINET_IN_H
|
||||
#define _NETINET_IN_H
|
||||
|
||||
#include <cygwin/in.h>
|
||||
|
||||
#endif /* _NETINET_IN_H */
|
6
winsup/cygwin/include/netinet/ip.h
Normal file
6
winsup/cygwin/include/netinet/ip.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _NETINET_IP_H
|
||||
#define _NETINET_IP_H
|
||||
|
||||
#include <cygwin/ip.h>
|
||||
|
||||
#endif /* _NETINET_IP_H */
|
6
winsup/cygwin/include/netinet/ip_icmp.h
Normal file
6
winsup/cygwin/include/netinet/ip_icmp.h
Normal 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
Reference in New Issue
Block a user