aboutsummaryrefslogtreecommitdiff
path: root/winsup/utils
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/utils')
-rw-r--r--winsup/utils/ChangeLog21
-rw-r--r--winsup/utils/Makefile.in109
-rw-r--r--winsup/utils/aclocal.m478
-rwxr-xr-xwinsup/utils/configure1246
-rw-r--r--winsup/utils/configure.in75
-rw-r--r--winsup/utils/cygcheck.cc922
-rw-r--r--winsup/utils/cygpath.cc154
-rw-r--r--winsup/utils/getfacl.c124
-rw-r--r--winsup/utils/kill.cc85
-rw-r--r--winsup/utils/mkgroup.c410
-rw-r--r--winsup/utils/mkpasswd.c438
-rw-r--r--winsup/utils/mount.cc240
-rw-r--r--winsup/utils/passwd.c352
-rw-r--r--winsup/utils/ps.cc150
-rw-r--r--winsup/utils/regtool.cc524
-rw-r--r--winsup/utils/setfacl.c377
-rw-r--r--winsup/utils/strace.cc481
-rw-r--r--winsup/utils/umount.cc173
-rw-r--r--winsup/utils/utils.sgml657
19 files changed, 6616 insertions, 0 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
new file mode 100644
index 0000000..62a4425
--- /dev/null
+++ b/winsup/utils/ChangeLog
@@ -0,0 +1,21 @@
+Fri Jan 21 02:10:26 Corinna Vinschen <corinna@vinschen.de>
+
+ * utils/regtool.cc (translate): Added unix like backslash
+ processing.
+
+2000-01-20 Corinna Vinschen <corinna@vinschen.de>
+
+ * regtool.cc: allow forward slashes as key separators
+
+2000-01-19 DJ Delorie <dj@redhat.com>
+
+ * regtool.cc: New file.
+ * Makefile.in: add regtool
+ * utils.sgml: add regtool
+
+Sat Jan 8 17:13:51 2000 Christopher Faylor <cgf@cygnus.com>
+
+ * getfacl.c: New file.
+ * setfacl.c: New file.
+ * Makefile.in: Add getfacl.exe and setfacl.exe to list of PROGS.
+ Fix link flags in MINGW case.
diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
new file mode 100644
index 0000000..11871d1
--- /dev/null
+++ b/winsup/utils/Makefile.in
@@ -0,0 +1,109 @@
+# Makefile for Cygwin utilities
+# 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.
+
+SHELL:=@SHELL@
+
+srcdir:=@srcdir@
+VPATH:=@srcdir@
+prefix:=@prefix@
+exec_prefix:=@exec_prefix@
+
+bindir:=@bindir@
+etcdir:=$(exec_prefix)/etc
+program_transform_name:=@program_transform_name@
+
+INSTALL:=@INSTALL@
+INSTALL_PROGRAM:=@INSTALL_PROGRAM@
+INSTALL_DATA:=@INSTALL_DATA@
+
+EXEEXT:=@EXEEXT@
+EXEEXT_FOR_BUILD:=@EXEEXT_FOR_BUILD@
+
+CC:=@CC@
+CC_FOR_TARGET:=$(CC)
+
+CFLAGS:=@CFLAGS@
+CXXFLAGS:=@CXXFLAGS@
+
+include $(srcdir)/../Makefile.common
+
+MINGW_INCLUDES:=-I$(updir)/mingw/include
+
+MINGW_CXXFLAGS:=-mno-cygwin $(CXXFLAGS) $(MINGW_INCLUDES)
+MINGW_CFLAGS:=-mno-cygwin $(CFLAGS) $(MINGW_INCLUDES)
+
+libcygwin:=$(cygwin_build)/libcygwin.a
+libuser32:=$(w32api_lib)/libuser32.a
+libkernel32:=$(w32api_lib)/libkernel32.a
+ALL_DEP_LDLIBS:=$(libcygwin) $(w32api_lib)/libnetapi32.a \
+ $(w32api_lib)/libadvapi32.a $(w32api_lib)/libkernel32.a \
+ $(w32api_lib)/libuser32.a
+
+ALL_LDLIBS:=${patsubst $(w32api_lib)/lib%.a,-l%,\
+ ${filter-out $(libuser32),\
+ ${filter-out $(libkernel32),\
+ ${filter-out $(libcygwin), $(ALL_DEP_LDLIBS)}}}}
+
+MINGW_LIB:=$(mingw_build)/libmingw32.a
+MINGW_LDLIBS:=$(ALL_LDLIBS) $(MINGW_LIB)
+ALL_LDFLAGS:=-B$(newlib_build)/libc/ -B$(newlib_build)/libm/ -B$(w32api_lib)/ \
+ $(LDFLAGS) $(ALL_LDLIBS)
+MINGW_LDFLAGS:=$(ALL_LDFLAGS) $(MINGW_LIB)
+
+PROGS:=mount$(EXEEXT) umount$(EXEEXT) ps$(EXEEXT) kill$(EXEEXT) \
+ mkpasswd$(EXEEXT) mkgroup$(EXEEXT) cygpath$(EXEEXT) cygcheck$(EXEEXT) \
+ passwd$(EXEEXT) getfacl$(EXEEXT) setfacl$(EXEEXT) strace$(EXEEXT) \
+ regtool$(EXEEXT)
+
+WINSUP_DEPS:=$(cygwin_source)/winsup.h
+
+.SUFFIXES:
+.NOEXPORT:
+
+.PHONY: all install clean realclean
+
+all: Makefile $(PROGS)
+
+strace.exe: strace.cc mingw_getopt.o $(MINGW_LDLIBS)
+ifdef VERBOSE
+ $(CC) $(MINGW_CFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+else
+ @echo $(CC) -mno-cygwin -o $@ ${wordlist 1,2,$^} ${filter-out -B%, $(MINGW_LDFLAGS)};\
+ $(CC) $(MINGW_CFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+endif
+
+mingw_getopt.o: $(cygwin_source)/getopt.c
+ $(CC) -c -o $@ $(MINGW_CFLAGS) $^
+
+clean:
+ rm -f *.o $(PROGS)
+
+realclean: clean
+ rm -f Makefile config.cache
+
+install: all
+ $(SHELL) $(updir1)/mkinstalldirs $(bindir) $(etcdir)
+ for i in $(PROGS) ; do \
+ n=`echo $$i | sed '$(program_transform_name)'`; \
+ $(INSTALL_PROGRAM) $$i $(bindir)/$$n; \
+ done
+
+$(cygwin_build)/libcygwin.a: $(cygwin_build)/Makefile
+ @$(MAKE) -C $(@D) $(@F)
+
+$(mingw_build)/libmingw32.a: $(mingw_build)/Makefile
+ @$(MAKE) -C $(@D) $(@F)
+
+%.exe: %.o $(ALL_DEP_LDLIBS)
+ifdef VERBOSE
+ $(CC) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS)
+else
+ @echo $(CC) -o $@ ${firstword $^} ${filter-out -B%, $(ALL_LDFLAGS)};\
+ $(CC) -o $@ ${firstword $^} -B$(cygwin_build)/ $(ALL_LDFLAGS)
+endif
diff --git a/winsup/utils/aclocal.m4 b/winsup/utils/aclocal.m4
new file mode 100644
index 0000000..754f640
--- /dev/null
+++ b/winsup/utils/aclocal.m4
@@ -0,0 +1,78 @@
+dnl aclocal.m4 generated automatically by aclocal 1.3b
+
+dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Check to see if we're running under Win32, without using
+# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe".
+# Otherwise set it to "".
+
+dnl AM_EXEEXT()
+dnl This knows we add .exe if we're building in the Cygwin
+dnl environment. But if we're not, then it compiles a test program
+dnl to see if there is a suffix for executables.
+AC_DEFUN(AM_EXEEXT,
+[AC_REQUIRE([AM_CYGWIN])
+AC_REQUIRE([AM_MINGW32])
+AC_MSG_CHECKING([for executable suffix])
+AC_CACHE_VAL(am_cv_exeext,
+[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+am_cv_exeext=.exe
+else
+cat > am_c_test.c << 'EOF'
+int main() {
+/* Nothing needed here */
+}
+EOF
+${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5
+am_cv_exeext=
+for file in am_c_test.*; do
+ case $file in
+ *.c) ;;
+ *.o) ;;
+ *) am_cv_exeext=`echo $file | sed -e s/am_c_test//` ;;
+ esac
+done
+rm -f am_c_test*])
+test x"${am_cv_exeext}" = x && am_cv_exeext=no
+fi
+EXEEXT=""
+test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext}
+AC_MSG_RESULT(${am_cv_exeext})
+AC_SUBST(EXEEXT)])
+
+# Check to see if we're running under Cygwin, without using
+# AC_CANONICAL_*. If so, set output variable CYGWIN to "yes".
+# Otherwise set it to "no".
+
+dnl AM_CYGWIN()
+AC_DEFUN(AM_CYGWIN,
+[AC_CACHE_CHECK(for Cygwin environment, am_cv_cygwin,
+[AC_TRY_COMPILE(,[return __CYGWIN32__;],
+am_cv_cygwin=yes, am_cv_cygwin=no)
+rm -f conftest*])
+CYGWIN=
+test "$am_cv_cygwin" = yes && CYGWIN=yes])
+
+
+
+# Check to see if we're running under Mingw, without using
+# AC_CANONICAL_*. If so, set output variable MINGW32 to "yes".
+# Otherwise set it to "no".
+
+dnl AM_MINGW32()
+AC_DEFUN(AM_MINGW32,
+[AC_CACHE_CHECK(for Mingw32 environment, am_cv_mingw32,
+[AC_TRY_COMPILE(,[return __MINGW32__;],
+am_cv_mingw32=yes, am_cv_mingw32=no)
+rm -f conftest*])
+MINGW32=
+test "$am_cv_mingw32" = yes && MINGW32=yes])
+
diff --git a/winsup/utils/configure b/winsup/utils/configure
new file mode 100755
index 0000000..2f3a2d1
--- /dev/null
+++ b/winsup/utils/configure
@@ -0,0 +1,1246 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+sitefile=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --site-file=FILE use FILE as the site file
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -site-file | --site-file | --site-fil | --site-fi | --site-f)
+ ac_prev=sitefile ;;
+ -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
+ sitefile="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=mount.cc
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$sitefile"; then
+ if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+ fi
+else
+ CONFIG_SITE="$sitefile"
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:543: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:573: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:622: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:646: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ 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
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:721: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:742: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:760: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+if test "x$cross_compiling" = "xyes"; then
+ if test "x$program_transform_name" = "xs,x,x,"; then
+ program_transform_name=""
+ fi
+ if test "x$program_transform_name" = "x"; then
+ program_transform_name="s,^,$host-,"
+ else
+ program_transform_name="$program_transform_name -e s,^,$host-,"
+ fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:825: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:879: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'am_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 884 "configure"
+#include "confdefs.h"
+
+int main() {
+return __CYGWIN32__;
+; return 0; }
+EOF
+if { (eval echo configure:891: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_cygwin" 1>&6
+CYGWIN=
+test "$am_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for Mingw32 environment""... $ac_c" 1>&6
+echo "configure:908: checking for Mingw32 environment" >&5
+if eval "test \"`echo '$''{'am_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 913 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:920: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_mingw32" 1>&6
+MINGW32=
+test "$am_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:939: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+am_cv_exeext=.exe
+else
+cat > am_c_test.c << 'EOF'
+int main() {
+/* Nothing needed here */
+}
+EOF
+${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5
+am_cv_exeext=
+for file in am_c_test.*; do
+ case $file in
+ *.c) ;;
+ *.o) ;;
+ *) am_cv_exeext=`echo $file | sed -e s/am_c_test//` ;;
+ esac
+done
+rm -f am_c_test*
+fi
+
+test x"${am_cv_exeext}" = x && am_cv_exeext=no
+fi
+EXEEXT=""
+test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext}
+echo "$ac_t""${am_cv_exeext}" 1>&6
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@EXEEXT@%$EXEEXT%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
diff --git a/winsup/utils/configure.in b/winsup/utils/configure.in
new file mode 100644
index 0000000..a38e008
--- /dev/null
+++ b/winsup/utils/configure.in
@@ -0,0 +1,75 @@
+dnl Autoconf configure script for Cygwin utilities.
+dnl Copyright 1996, 1997 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 Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.12)
+
+AC_INIT(mount.cc)
+
+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_PROG(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
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+])
+
+LIB_AC_PROG_CC
+
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+if test "x$cross_compiling" = "xyes"; then
+ if test "x$program_transform_name" = "xs,x,x,"; then
+ program_transform_name=""
+ fi
+ if test "x$program_transform_name" = "x"; then
+ program_transform_name="s,^,$host-,"
+ else
+ program_transform_name="$program_transform_name -e s,^,$host-,"
+ fi
+fi
+
+AC_PROG_INSTALL
+
+AM_EXEEXT
+
+AC_OUTPUT(Makefile)
+
diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc
new file mode 100644
index 0000000..59bf00a
--- /dev/null
+++ b/winsup/utils/cygcheck.cc
@@ -0,0 +1,922 @@
+/* cygcheck.cc
+
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <sys/cygwin.h>
+#include <mntent.h>
+#include <time.h>
+
+int verbose = 0;
+int registry = 0;
+int sysinfo = 0;
+int givehelp = 0;
+
+#ifdef __GNUC__
+typedef long long longlong;
+#else
+typedef __int64 longlong;
+#endif
+
+const char *known_env_vars[] =
+{
+ "c_include_path",
+ "compiler_path",
+ "cxx_include_path",
+ "cygwin",
+ "cygwin32",
+ "dejagnu",
+ "expect",
+ "gcc_default_options",
+ "gcc_exec_prefix",
+ "home",
+ "ld_library_path",
+ "library_path",
+ "login",
+ "lpath",
+ "make_mode",
+ "makeflags",
+ "path",
+ "pwd",
+ "strace",
+ "tcl_library",
+ "user",
+ 0
+};
+
+struct {
+ const char *name;
+ int missing_is_good;
+} common_apps[] = {
+ { "bash", 0 },
+ { "cat", 0 },
+ { "cpp", 1 },
+ { "find", 0 },
+ { "gcc", 0 },
+ { "gdb", 0 },
+ { "ld", 0 },
+ { "ls", 0 },
+ { "make", 0 },
+ { "sh", 0 },
+ { 0, 0 }
+};
+
+int num_paths = 0, max_paths = 0;
+char **paths = 0;
+
+void
+add_path (char *s, int maxlen)
+{
+ if (num_paths >= max_paths)
+ {
+ max_paths += 10;
+ if (paths)
+ paths = (char **) realloc (paths, max_paths * sizeof (char *));
+ else
+ paths = (char **) malloc (max_paths * sizeof (char *));
+ }
+ paths[num_paths] = (char *) malloc (maxlen + 1);
+ memcpy (paths[num_paths], s, maxlen);
+ paths[num_paths][maxlen] = 0;
+ char *e = paths[num_paths] + strlen (paths[num_paths]);
+ if (e[-1] == '\\' && e[-2] != ':')
+ *--e = 0;
+ for (int i = 1; i < num_paths; i++)
+ if (strcasecmp (paths[num_paths], paths[i]) == 0)
+ return;
+ num_paths++;
+}
+
+void
+init_paths ()
+{
+ char tmp[4000], *sl;
+ add_path ((char *) ".", 1); /* to be replaced later */
+ add_path ((char *) ".", 1); /* the current directory */
+ GetSystemDirectory (tmp, 4000);
+ add_path (tmp, strlen (tmp));
+ sl = strrchr (tmp, '\\');
+ if (sl)
+ {
+ strcpy (sl, "\\SYSTEM");
+ add_path (tmp, strlen (tmp));
+ }
+ GetWindowsDirectory (tmp, 4000);
+ add_path (tmp, strlen (tmp));
+
+ char *path = getenv ("PATH");
+ if (path)
+ {
+ char wpath[4000];
+ cygwin_posix_to_win32_path_list (path, wpath);
+ char *b, *e, sep = ':';
+ if (strchr (wpath, ';'))
+ sep = ';';
+ b = wpath;
+ while (1)
+ {
+ for (e = b; *e && *e != sep; e++);
+ add_path (b, e - b);
+ if (!*e)
+ break;
+ b = e + 1;
+ }
+ }
+ else
+ printf ("WARNING: PATH is not set at all!\n");
+}
+
+char *
+find_on_path (char *file, char *default_extension,
+ int showall = 0, int search_sysdirs = 0)
+{
+ static char rv[4000];
+ char tmp[4000], *ptr = rv;
+
+ if (strchr (file, ':') || strchr (file, '\\') || strchr (file, '/'))
+ return file;
+
+ if (strchr (file, '.'))
+ default_extension = (char *)"";
+
+ for (int i = 0; i < num_paths; i++)
+ {
+ if (!search_sysdirs && (i == 0 || i == 2 || i == 3))
+ continue;
+ if (i == 0 || !search_sysdirs || strcasecmp (paths[i], paths[0]))
+ {
+ sprintf (ptr, "%s\\%s%s", paths[i], file, default_extension);
+ if (GetFileAttributes (ptr) != (DWORD) -1)
+ {
+ if (showall)
+ printf ("Found: %s\n", ptr);
+ if (ptr == tmp && verbose)
+ printf ("Warning: %s hides %s\n", rv, ptr);
+ ptr = tmp;
+ }
+ }
+ }
+
+ if (ptr == tmp)
+ return rv;
+
+ return 0;
+}
+
+#define DID_NEW 1
+#define DID_ACTIVE 2
+#define DID_INACTIVE 3
+
+struct Did
+{
+ Did *next;
+ char *file;
+ int state;
+};
+Did *did = 0;
+
+Did *
+already_did (char *file)
+{
+ Did *d;
+ for (d = did; d; d = d->next)
+ if (strcasecmp (d->file, file) == 0)
+ return d;
+ d = new Did;
+ d->file = strdup (file);
+ d->next = did;
+ d->state = DID_NEW;
+ did = d;
+ return d;
+}
+
+int
+get_word (HANDLE fh, int offset)
+{
+ short rv;
+ unsigned r;
+ SetFilePointer (fh, offset, 0, FILE_BEGIN);
+ ReadFile (fh, &rv, 2, (DWORD *) &r, 0);
+ return rv;
+}
+
+int
+get_dword (HANDLE fh, int offset)
+{
+ int rv;
+ unsigned r;
+ SetFilePointer (fh, offset, 0, FILE_BEGIN);
+ ReadFile (fh, &rv, 4, (DWORD *) &r, 0);
+ return rv;
+}
+
+struct Section
+{
+ char name[8];
+ int virtual_size;
+ int virtual_address;
+ int size_of_raw_data;
+ int pointer_to_raw_data;
+};
+
+int
+rva_to_offset (int rva, char *sections, int nsections, int *sz)
+{
+ int i;
+ for (i = 0; i < nsections; i++)
+ {
+ Section *s = (Section *) (sections + i * 40);
+#if 0
+ printf ("%08x < %08x < %08x ? %08x\n",
+ s->virtual_address, rva,
+ s->virtual_address + s->virtual_size, s->pointer_to_raw_data);
+#endif
+ if (rva >= s->virtual_address
+ && rva < s->virtual_address + s->virtual_size)
+ {
+ if (sz)
+ *sz = s->virtual_address + s->virtual_size - rva;
+ return rva - s->virtual_address + s->pointer_to_raw_data;
+ }
+ }
+ return 0; /* punt */
+}
+
+struct ExpDirectory
+{
+ int flags;
+ int timestamp;
+ short major_ver;
+ short minor_ver;
+ int name_rva;
+};
+
+struct ImpDirectory
+ {
+ unsigned characteristics;
+ unsigned timestamp;
+ unsigned forwarder_chain;
+ unsigned name_rva;
+ unsigned iat_rva;
+ };
+
+
+void track_down (char *file, char *suffix, int lvl);
+
+void
+dll_info (HANDLE fh, int lvl, int recurse)
+{
+ DWORD junk;
+ int i;
+ int pe_header_offset = get_dword (fh, 0x3c);
+ int opthdr_ofs = pe_header_offset + 4 + 20;
+ unsigned short v[6];
+ SetFilePointer (fh, opthdr_ofs + 40, 0, FILE_BEGIN);
+ ReadFile (fh, &v, sizeof (v), &junk, 0);
+ if (verbose)
+ printf (" - os=%d.%d img=%d.%d sys=%d.%d\n",
+ v[0], v[1], v[2], v[3], v[4], v[5]);
+ else
+ printf ("\n");
+ int num_entries = get_dword (fh, opthdr_ofs + 92);
+ int export_rva = get_dword (fh, opthdr_ofs + 96);
+ int export_size = get_dword (fh, opthdr_ofs + 100);
+ int import_rva = get_dword (fh, opthdr_ofs + 104);
+ int import_size = get_dword (fh, opthdr_ofs + 108);
+
+ int nsections = get_word (fh, pe_header_offset + 4 + 2);
+ char *sections = (char *) malloc (nsections * 40);
+ SetFilePointer (fh, pe_header_offset + 4 + 20 + get_word (fh, pe_header_offset + 4 + 16),
+ 0, FILE_BEGIN);
+ ReadFile (fh, sections, nsections * 40, &junk, 0);
+
+ if (verbose && num_entries >= 1 && export_size > 0)
+ {
+ int expsz;
+ int expbase = rva_to_offset (export_rva, sections, nsections, &expsz);
+ if (expbase)
+ {
+ SetFilePointer (fh, expbase, 0, FILE_BEGIN);
+ unsigned char *exp = (unsigned char *) malloc (expsz);
+ ReadFile (fh, exp, expsz, &junk, 0);
+ ExpDirectory *ed = (ExpDirectory *) exp;
+ int ofs = ed->name_rva - export_rva;
+ struct tm *tm = localtime ((const time_t *) &(ed->timestamp));
+ if (tm->tm_year < 60)
+ tm->tm_year += 2000;
+ if (tm->tm_year < 200)
+ tm->tm_year += 1900;
+ printf ("%*c", lvl + 2, ' ');
+ printf ("\"%s\" v%d.%d ts=", exp + ofs,
+ ed->major_ver, ed->minor_ver);
+ printf ("%d/%d/%d %d:%02d\n",
+ tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min);
+ }
+ }
+
+ if (num_entries >= 2 && import_size > 0 && recurse)
+ {
+ int impsz;
+ int impbase = rva_to_offset (import_rva, sections, nsections, &impsz);
+ if (impbase)
+ {
+ SetFilePointer (fh, impbase, 0, FILE_BEGIN);
+ unsigned char *imp = (unsigned char *) malloc (impsz);
+ ReadFile (fh, imp, impsz, &junk, 0);
+ ImpDirectory *id = (ImpDirectory *) imp;
+ for (i = 0; id[i].name_rva; i++)
+ {
+ /* int ofs = id[i].name_rva - import_rva; */
+ track_down ((char *) imp + id[i].name_rva - import_rva,
+ (char *) ".dll", lvl + 2);
+ }
+ }
+ }
+}
+
+void
+track_down (char *file, char *suffix, int lvl)
+{
+ char *path = find_on_path (file, suffix, 0, 1);
+ if (!path)
+ {
+ printf ("Error: could not find %s\n", file);
+ return;
+ }
+
+ Did *d = already_did (file);
+ switch (d->state)
+ {
+ case DID_NEW:
+ break;
+ case DID_ACTIVE:
+ if (verbose)
+ {
+ if (lvl)
+ printf ("%*c", lvl, ' ');
+ printf ("%s", path);
+ printf (" (recursive)\n");
+ }
+ return;
+ case DID_INACTIVE:
+ if (verbose)
+ {
+ if (lvl)
+ printf ("%*c", lvl, ' ');
+ printf ("%s", path);
+ printf (" (already done)\n");
+ }
+ return;
+ }
+
+ if (lvl)
+ printf ("%*c", lvl, ' ');
+
+ if (!path)
+ {
+ printf ("%s not found\n", file);
+ return;
+ }
+
+ printf ("%s", path);
+
+ HANDLE fh = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fh == INVALID_HANDLE_VALUE)
+ {
+ printf (" - Cannot open\n");
+ return;
+ }
+
+ d->state = DID_ACTIVE;
+
+ dll_info (fh, lvl, 1);
+ d->state = DID_INACTIVE;
+ CloseHandle (fh);
+}
+
+void
+ls (char *f)
+{
+ HANDLE h = CreateFile (f, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ BY_HANDLE_FILE_INFORMATION info;
+ GetFileInformationByHandle (h, &info);
+ SYSTEMTIME systime;
+ FileTimeToSystemTime (&info.ftLastWriteTime, &systime);
+ printf ("%5dk %04d/%02d/%02d %s",
+ (((int) info.nFileSizeLow) + 512) / 1024,
+ systime.wYear, systime.wMonth, systime.wDay,
+ f);
+ dll_info (h, 16, 0);
+ CloseHandle (h);
+
+}
+
+void
+cygcheck (char *app)
+{
+ char *papp = find_on_path (app, (char *) ".exe", 1, 0);
+ if (!papp)
+ {
+ printf ("Error: could not find %s\n", app);
+ return;
+ }
+ char *s = strdup (papp);
+ char *sl = 0, *t;
+ for (t = s; *t; t++)
+ if (*t == '/' || *t == '\\' || *t == ':')
+ sl = t;
+ if (sl == 0)
+ paths[0] = (char *) ".";
+ else
+ {
+ *sl = 0;
+ paths[0] = s;
+ }
+ did = 0;
+ track_down (papp, (char *) ".exe", 0);
+}
+
+
+extern char **environ;
+
+struct RegInfo
+ {
+ RegInfo *prev;
+ char *name;
+ HKEY key;
+ };
+
+void
+show_reg (RegInfo * ri, int nest)
+{
+ if (!ri)
+ return;
+ show_reg (ri->prev, 1);
+ if (nest)
+ printf ("%s\\", ri->name);
+ else
+ printf ("%s\n", ri->name);
+}
+
+void
+scan_registry (RegInfo * prev, HKEY hKey, char *name, int cygnus)
+{
+ RegInfo ri;
+ ri.prev = prev;
+ ri.name = name;
+ ri.key = hKey;
+
+ char *cp;
+ for (cp = name; *cp; cp++)
+ if (strncasecmp (cp, "cygnus", 6) == 0)
+ cygnus = 1;
+
+ DWORD num_subkeys, max_subkey_len, num_values;
+ DWORD max_value_len, max_valdata_len, i;
+ if (RegQueryInfoKey (hKey, 0, 0, 0, &num_subkeys, &max_subkey_len, 0,
+ &num_values, &max_value_len, &max_valdata_len, 0, 0)
+ != ERROR_SUCCESS)
+ {
+#if 0
+ char tmp[400];
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (),
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tmp,
+ 400, 0);
+ printf ("RegQueryInfoKey: %s\n", tmp);
+#endif
+ return;
+ }
+
+ if (cygnus)
+ {
+ show_reg (&ri, 0);
+ char *value_name = (char *) malloc (max_value_len + 1);
+ char *value_data = (char *) malloc (max_valdata_len + 1);
+
+ for (i = 0; i < num_values; i++)
+ {
+ DWORD dlen = max_valdata_len + 1;
+ DWORD nlen = max_value_len + 1;
+ DWORD type;
+ RegEnumValue (hKey, i, value_name, &nlen, 0,
+ &type, (BYTE *) value_data, &dlen);
+ {
+ printf (" %s = ", i ? value_name : "(default)");
+ switch (type)
+ {
+ case REG_DWORD:
+ printf ("0x%08x\n", *(unsigned *) value_data);
+ break;
+ case REG_EXPAND_SZ:
+ case REG_SZ:
+ printf ("`%s'\n", value_data);
+ break;
+ default:
+ printf ("(unsupported type)\n");
+ break;
+ }
+ }
+#if 0
+ else
+ {
+ char tmp[400];
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (),
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tmp,
+ 400, 0);
+ printf ("RegEnumValue: %s\n", tmp);
+ }
+#endif
+ }
+ free (value_name);
+ free (value_data);
+ }
+
+ char *subkey_name = (char *) malloc (max_subkey_len + 1);
+ for (i = 0; i < num_subkeys; i++)
+ {
+ if (RegEnumKey (hKey, i, subkey_name, max_subkey_len + 1) == ERROR_SUCCESS)
+ {
+ HKEY sKey;
+ if (RegOpenKeyEx (hKey, subkey_name, 0, KEY_ALL_ACCESS, &sKey)
+ == ERROR_SUCCESS)
+ {
+ scan_registry (&ri, sKey, subkey_name, cygnus);
+ RegCloseKey (sKey);
+ }
+ }
+ }
+ free (subkey_name);
+}
+
+void
+dump_sysinfo ()
+{
+ int i, j;
+ char tmp[4000];
+ time_t now;
+
+ printf ("\nCygnus Win95/NT Configuration Diagnostics\n");
+ time (&now);
+ printf ("Current System Time: %s\n", ctime (&now));
+
+ OSVERSIONINFO osversion;
+ osversion.dwOSVersionInfoSize = sizeof (osversion);
+ GetVersionEx (&osversion);
+ char *osname = (char *) "unknown OS";
+ switch (osversion.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32s:
+ osname = (char *) "win32s";
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ switch (osversion.dwMinorVersion)
+ {
+ case 0:
+ osname = (char *) "Win95";
+ break;
+ case 1:
+ osname = (char *) "Win98";
+ break;
+ default:
+ osname = (char *) "Win9X";
+ break;
+ }
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ osname = (char *) "WinNT";
+ break;
+ default:
+ osname = (char *) "uknown-os";
+ break;
+ }
+ printf ("%s Ver %d.%d build %d %s\n\n", osname,
+ (int) osversion.dwMajorVersion, (int) osversion.dwMinorVersion,
+ (int) osversion.dwBuildNumber, osversion.szCSDVersion);
+
+ printf ("Path:");
+ char *s = getenv ("PATH"), *e;
+ char sep = strchr (s, ';') ? ';' : ':';
+ int count_path_items = 0;
+ while (1)
+ {
+ for (e = s; *e && *e != sep; e++);
+ printf ("\t%.*s\n", e - s, s);
+ count_path_items++;
+ if (!*e)
+ break;
+ s = e + 1;
+ }
+
+ GetSystemDirectory (tmp, 4000);
+ printf ("\nSysDir: %s\n", tmp);
+ GetWindowsDirectory (tmp, 4000);
+ printf ("WinDir: %s\n\n", tmp);
+
+
+ if (givehelp)
+ printf ("Here's some environment variables that may affect cygwin:\n");
+ for (i = 0; environ[i]; i++)
+ {
+ char *eq = strchr (environ[i], '=');
+ if (!eq)
+ continue;
+ /* int len = eq - environ[i]; */
+ for (j = 0; known_env_vars[j]; j++)
+ {
+ *eq = 0;
+ if (strcmp (environ[i], "PATH") == 0)
+ continue; /* we handle this one specially */
+ if (strcasecmp (environ[i], known_env_vars[j]) == 0)
+ printf ("%s = `%s'\n", environ[i], eq + 1);
+ *eq = '=';
+ }
+ }
+ printf ("\n");
+
+ if (verbose)
+ {
+ if (givehelp)
+ printf ("Here's the rest of your environment variables:\n");
+ for (i = 0; environ[i]; i++)
+ {
+ int found = 0;
+ char *eq = strchr (environ[i], '=');
+ if (!eq)
+ continue;
+ /* int len = eq - environ[i]; */
+ for (j = 0; known_env_vars[j]; j++)
+ {
+ *eq = 0;
+ if (strcasecmp (environ[i], known_env_vars[j]) == 0)
+ found = 1;
+ *eq = '=';
+ }
+ if (!found)
+ {
+ *eq = 0;
+ printf ("%s = `%s'\n", environ[i], eq + 1);
+ *eq = '=';
+ }
+ }
+ printf ("\n");
+ }
+
+ if (registry)
+ {
+ if (givehelp)
+ printf ("Scanning registry for keys with `Cygnus' in them...\n");
+#if 0
+ /* big and not generally useful */
+ scan_registry (0, HKEY_CLASSES_ROOT, (char *) "HKEY_CLASSES_ROOT", 0);
+#endif
+ scan_registry (0, HKEY_CURRENT_CONFIG,
+ (char *) "HKEY_CURRENT_CONFIG", 0);
+ scan_registry (0, HKEY_CURRENT_USER, (char *) "HKEY_CURRENT_USER", 0);
+ scan_registry (0, HKEY_LOCAL_MACHINE, (char *) "HKEY_LOCAL_MACHINE", 0);
+#if 0
+ /* the parts we need are duplicated in HKEY_CURRENT_USER anyway */
+ scan_registry (0, HKEY_USERS, (char *) "HKEY_USERS", 0);
+#endif
+ printf ("\n");
+ }
+ else
+ printf ("Use `-r' to scan registry\n\n");
+
+ if (givehelp)
+ {
+ printf ("Listing available drives...\n");
+ printf ("Drv Type Size Free Flags Name\n");
+ }
+ int prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ int drivemask = GetLogicalDrives ();
+
+ HINSTANCE k32 = LoadLibrary ("kernel32.dll");
+ BOOL (WINAPI *gdfse) (LPCSTR, long long *, long long *, long long *) =
+ (BOOL (WINAPI *) (LPCSTR, long long *, long long *, long long *))
+ GetProcAddress (k32, "GetDiskFreeSpaceExA");
+
+ for (i = 0; i < 26; i++)
+ {
+ if (!(drivemask & (1 << i)))
+ continue;
+ char drive[4], name[200], fsname[200];
+ DWORD serno = 0, maxnamelen = 0, flags = 0;
+ name[0] = name[0] = fsname[0] = 0;
+ sprintf (drive, "%c:\\", i + 'a');
+ GetVolumeInformation (drive, name, sizeof (name), &serno, &maxnamelen,
+ &flags, fsname, sizeof (fsname));
+
+ int dtype = GetDriveType (drive);
+ char drive_type[4] = "unk";
+ switch (dtype)
+ {
+ case DRIVE_REMOVABLE:
+ strcpy (drive_type, "fd ");
+ break;
+ case DRIVE_FIXED:
+ strcpy (drive_type, "hd ");
+ break;
+ case DRIVE_REMOTE:
+ strcpy (drive_type, "net");
+ break;
+ case DRIVE_CDROM:
+ strcpy (drive_type, "cd ");
+ break;
+ case DRIVE_RAMDISK:
+ strcpy (drive_type, "ram");
+ break;
+ }
+
+ long capacity_mb = -1;
+ int percent_full = -1;
+
+ long long free_me = 0ULL, free_bytes = 0ULL, total_bytes = 1ULL;
+ if (gdfse != NULL
+ && gdfse (drive, & free_me, & total_bytes, & free_bytes))
+ {
+ capacity_mb = total_bytes / (1024L * 1024L);
+ percent_full = 100 - (int) ((100.0 * free_me) / total_bytes);
+ }
+ else
+ {
+ DWORD spc = 0, bps = 0, fc = 0, tc = 1;
+ if (GetDiskFreeSpace (drive, &spc, &bps, &fc, &tc))
+ {
+ capacity_mb = (spc * bps * tc) / (1024 * 1024);
+ percent_full = 100 - (int) ((100.0 * fc) / tc);
+ }
+ }
+
+ printf ("%.2s %s %-6s ", drive, drive_type, fsname);
+ if (capacity_mb >= 0)
+ printf ("%5dMb %3d%% ", (int) capacity_mb, (int) percent_full);
+ else
+ printf (" N/A N/A ");
+ printf ("%s %s %s %s %s %s %s\n",
+ flags & FS_CASE_IS_PRESERVED ? "CP" : " ",
+ flags & FS_CASE_SENSITIVE ? "CS" : " ",
+ flags & FS_UNICODE_STORED_ON_DISK ? "UN" : " ",
+ flags & FS_PERSISTENT_ACLS ? "PA" : " ",
+ flags & FS_FILE_COMPRESSION ? "FC" : " ",
+ flags & FS_VOL_IS_COMPRESSED ? "VC" : " ",
+#if 0
+ flags & FILE_SUPPORTS_ENCRYPTION ? "EN" : " ",
+ flags & FILE_SUPPORTS_OBJECT_IDS ? "OI" : " ",
+ flags & FILE_SUPPORTS_REPARSE_POINTS ? "RP" : " ",
+ flags & FILE_SUPPORTS_SPARSE_FILES ? "SP" : " ",
+ flags & FILE_VOLUME_QUOTAS ? "QU" : " ",
+#endif
+ name);
+ }
+
+ FreeLibrary (k32);
+ SetErrorMode (prev_mode);
+ if (givehelp)
+ {
+ printf ("fd=floppy, hd=hard drive, cd=CD-ROM, net=Network Share\n");
+ printf ("CP=Case Preserving, CS=Case Sensitive, UN=Unicode\n");
+ printf ("PA=Persistent ACLS, FC=File Compression, VC=Volume Compression\n");
+ }
+ printf ("\n");
+
+ unsigned int ml_fsname = 4, ml_dir = 7, ml_type = 6;
+
+ if (givehelp)
+ {
+ printf ("Mount entries: these map POSIX directories to your NT drives.\n");
+ printf ("%-*s %-*s %-*s %s\n",
+ ml_fsname, "-NT-",
+ ml_dir, "-POSIX-",
+ ml_type, "-Type-", "-Flags-");
+ }
+
+ struct mntent *mnt;
+ setmntent (0, 0);
+
+ while ((mnt = getmntent (0)))
+ {
+ printf ("%-*s %-*s %-*s %s\n",
+ ml_fsname, mnt->mnt_fsname,
+ ml_dir, mnt->mnt_dir,
+ ml_type, mnt->mnt_type,
+ mnt->mnt_opts);
+ }
+ printf ("\n");
+
+ add_path ((char *) "\\bin", 4); /* just in case */
+
+ if (givehelp)
+ printf ("Looking to see where common programs can be found, if at all...\n");
+ for (i = 0; common_apps[i].name; i++)
+ if (!find_on_path ((char *) common_apps[i].name, (char *) ".exe", 1, 0))
+ {
+ if (common_apps[i].missing_is_good)
+ printf ("Not Found: %s (good!)\n", common_apps[i].name);
+ else
+ printf ("Not Found: %s\n", common_apps[i].name);
+ }
+ printf ("\n");
+
+ if (givehelp)
+ printf ("Looking for various Cygnus DLLs... (-v gives version info)\n");
+ for (i = 0; i < num_paths; i++)
+ {
+ WIN32_FIND_DATA ffinfo;
+ sprintf (tmp, "%s/*.*", paths[i]);
+ HANDLE ff = FindFirstFile (tmp, &ffinfo);
+ int found = (ff != INVALID_HANDLE_VALUE);
+ while (found)
+ {
+ char *f = ffinfo.cFileName;
+ if (strcasecmp (f + strlen (f) - 4, ".dll") == 0)
+ {
+ if (strncasecmp (f, "cyg", 3) == 0)
+ {
+ sprintf (tmp, "%s\\%s", paths[i], f);
+ ls (tmp);
+ }
+ }
+ found = FindNextFile (ff, &ffinfo);
+ }
+ FindClose (ff);
+ }
+}
+
+void
+usage ()
+{
+ fprintf (stderr, "Usage: cygcheck [-s] [-v] [-r] [-h] [program ...]\n");
+ fprintf (stderr, " -s = system information\n");
+ fprintf (stderr, " -v = verbose output (indented) (for -s or programs)\n");
+ fprintf (stderr, " -r = registry search (requires -s)\n");
+ fprintf (stderr, " -h = give help about the info\n");
+ fprintf (stderr, "You must at least give either -s or a program name\n");
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ while (argc > 1 && argv[1][0] == '-')
+ {
+ if (strcmp (argv[1], "-v") == 0)
+ verbose = 1;
+ if (strcmp (argv[1], "-r") == 0)
+ registry = 1;
+ if (strcmp (argv[1], "-s") == 0)
+ sysinfo = 1;
+ if (strcmp (argv[1], "-h") == 0)
+ givehelp = 1;
+ argc--;
+ argv++;
+ }
+
+ if (argc == 1 && !sysinfo)
+ usage ();
+
+ init_paths ();
+
+ if (argc > 1 && givehelp)
+ {
+ if (argc == 2)
+ {
+ printf ("Here is where the OS will find your program, and which dlls\n");
+ printf ("will be used for it. Use -v to see DLL version info\n");
+ }
+ else
+ {
+ printf ("Here is where the OS will find your programs, and which dlls\n");
+ printf ("will be used for them. Use -v to see DLL version info\n");
+ }
+
+ if (!sysinfo)
+ printf ("\n");
+ }
+
+ for (i = 1; i < argc; i++)
+ {
+ cygcheck (argv[i]);
+ printf ("\n");
+ }
+
+ if (sysinfo)
+ dump_sysinfo ();
+
+ if (!givehelp)
+ printf ("Use -h to see help about each section\n");
+
+ return 0;
+}
diff --git a/winsup/utils/cygpath.cc b/winsup/utils/cygpath.cc
new file mode 100644
index 0000000..653d41c
--- /dev/null
+++ b/winsup/utils/cygpath.cc
@@ -0,0 +1,154 @@
+/* pathconv.cc -- convert pathnames between Windows and Unix format
+ Copyright 1998 Cygnus Solutions.
+ Written by Ian Lance Taylor <ian@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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <getopt.h>
+#include <sys/cygwin.h>
+
+static char *prog_name;
+
+static struct option long_options[] =
+{
+ { (char *) "help", no_argument, NULL, 'h' },
+ { (char *) "path", no_argument, NULL, 'p' },
+ { (char *) "unix", no_argument, NULL, 'u' },
+ { (char *) "version", no_argument, NULL, 'v' },
+ { (char *) "windows", no_argument, NULL, 'w' },
+ { 0, no_argument, 0, 0 }
+};
+
+static void
+usage (FILE *stream, int status)
+{
+ fprintf (stream, "\
+Usage: %s [-p|--path] (-u|--unix)|(-w|--windows) filename\n\
+ -u|--unix print Unix form of filename\n\
+ -w|--windows print Windows form of filename\n\
+ -p|--path filename argument is a path\n",
+ prog_name);
+ exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+ int path_flag, unix_flag, windows_flag;
+ int c;
+ char *filename;
+ size_t len;
+ char *buf;
+
+ prog_name = strrchr (argv[0], '/');
+ if (prog_name == NULL)
+ prog_name = strrchr (argv[0], '\\');
+ if (prog_name == NULL)
+ prog_name = argv[0];
+
+ path_flag = 0;
+ unix_flag = 0;
+ windows_flag = 0;
+ while ((c = getopt_long (argc, argv, (char *) "hpuvw", long_options, (int *) NULL))
+ != EOF)
+ {
+ switch (c)
+ {
+ case 'p':
+ path_flag = 1;
+ break;
+
+ case 'u':
+ if (unix_flag || windows_flag)
+ usage (stderr, 1);
+ unix_flag = 1;
+ break;
+
+ case 'w':
+ if (unix_flag || windows_flag)
+ usage (stderr, 1);
+ windows_flag = 1;
+ break;
+
+ case 'h':
+ usage (stdout, 0);
+ break;
+
+ case 'v':
+ printf ("Cygwin pathconv version 1.0\n");
+ printf ("Copyright 1998 Cygnus Solutions\n");
+ exit (0);
+
+ default:
+ usage (stderr, 1);
+ break;
+ }
+ }
+
+ if (optind != argc - 1)
+ usage (stderr, 1);
+
+ if (! unix_flag && ! windows_flag)
+ usage (stderr, 1);
+
+ filename = argv[optind];
+
+ if (path_flag)
+ {
+ if (cygwin_posix_path_list_p (filename)
+ ? unix_flag
+ : windows_flag)
+ {
+ /* The path is already in the right format. */
+ puts (filename);
+ exit (0);
+ }
+ }
+
+ if (! path_flag)
+ len = strlen (filename) + 100;
+ else
+ {
+ if (unix_flag)
+ len = cygwin_win32_to_posix_path_list_buf_size (filename);
+ else
+ len = cygwin_posix_to_win32_path_list_buf_size (filename);
+ }
+
+ if (len < PATH_MAX)
+ len = PATH_MAX;
+
+ buf = (char *) malloc (len);
+ if (buf == NULL)
+ {
+ fprintf (stderr, "%s: out of memory\n", prog_name);
+ exit (1);
+ }
+
+ if (path_flag)
+ {
+ if (unix_flag)
+ cygwin_win32_to_posix_path_list (filename, buf);
+ else
+ cygwin_posix_to_win32_path_list (filename, buf);
+ }
+ else
+ {
+ if (unix_flag)
+ cygwin_conv_to_posix_path (filename, buf);
+ else
+ cygwin_conv_to_win32_path (filename, buf);
+ }
+
+ puts (buf);
+
+ exit (0);
+}
diff --git a/winsup/utils/getfacl.c b/winsup/utils/getfacl.c
new file mode 100644
index 0000000..9bf7122
--- /dev/null
+++ b/winsup/utils/getfacl.c
@@ -0,0 +1,124 @@
+
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+char *permstr (mode_t perm)
+{
+ static char pbuf[4];
+
+ pbuf[0] = (perm & S_IREAD) ? 'r' : '-';
+ pbuf[1] = (perm & S_IWRITE) ? 'w' : '-';
+ pbuf[2] = (perm & S_IEXEC) ? 'x' : '-';
+ pbuf[3] = '\0';
+ return pbuf;
+}
+
+#if 0
+char *username (uid_t uid)
+{
+ static char ubuf[256];
+ struct passwd *pw;
+
+ if (pw = getpwuid (uid))
+ strcpy (ubuf, pw->pw_name);
+ else
+ strcpy (ubuf, "<unknown>");
+}
+
+char *groupname (gid_t gid)
+{
+ static char gbuf[256];
+ struct group *gr;
+
+ if (gr = getgruid (gid))
+ strcpy (gbuf, gr->gr_name);
+ else
+ strcpy (gbuf, "<unknown>");
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+ extern int optind;
+ int c, i;
+ int aopt = 0;
+ int dopt = 0;
+ int first = 1;
+ struct stat st;
+ aclent_t acls[MAX_ACL_ENTRIES];
+
+ while ((c = getopt (argc, argv, "ad")) != EOF)
+ switch (c)
+ {
+ case 'a':
+ aopt = 1;
+ break;
+ case 'd':
+ dopt = 1;
+ break;
+ default:
+ fprintf (stderr, "usage: %s [-ad] file...\n", argv[0]);
+ return 1;
+ }
+ while ((c = optind++) < argc)
+ {
+ if (stat (argv[c], &st))
+ {
+ perror (argv[0]);
+ continue;
+ }
+ if (! first)
+ putchar ('\n');
+ first = 0;
+ printf ("# file: %s\n", argv[c]);
+ printf ("# owner: %d\n", st.st_uid);
+ printf ("# group: %d\n", st.st_gid);
+ if ((c = acl (argv[c], GETACL, MAX_ACL_ENTRIES, acls)) < 0)
+ {
+ perror (argv[0]);
+ continue;
+ }
+ for (i = 0; i < c; ++i)
+ {
+ if (acls[i].a_type & ACL_DEFAULT)
+ {
+ if (aopt)
+ continue;
+ printf ("default:");
+ }
+ else if (dopt)
+ continue;
+ switch (acls[i].a_type & ~ACL_DEFAULT)
+ {
+ case USER_OBJ:
+ printf ("user::");
+ break;
+ case USER:
+ printf ("user:%d:", acls[i].a_id);
+ break;
+ case GROUP_OBJ:
+ printf ("group::");
+ break;
+ case GROUP:
+ printf ("group:%d:", acls[i].a_id);
+ break;
+ case CLASS_OBJ:
+ printf ("mask::");
+ break;
+ case OTHER_OBJ:
+ printf ("other::");
+ break;
+ }
+ printf ("%s\n", permstr (acls[i].a_perm));
+ }
+ }
+ return 0;
+}
+
diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc
new file mode 100644
index 0000000..6118878
--- /dev/null
+++ b/winsup/utils/kill.cc
@@ -0,0 +1,85 @@
+/* kill.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 <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+static void usage (void);
+static int getsig (char *);
+int a = _timezone;
+
+int
+main (int ac, char **av)
+{
+ int sig = SIGTERM;
+
+ if (ac == 1)
+ usage ();
+
+ if (*(++av)[0] == '-')
+ if (strcmp(*av + 1, "0") != 0)
+ sig = getsig (*av++ + 1);
+ else
+ {
+ av++;
+ sig = 0;
+ goto sig0;
+ }
+
+ if (sig <= 0 || sig > NSIG)
+ {
+ fprintf (stderr, "kill: unknown signal: %s\n", av[-1]);
+ exit (1);
+ }
+
+sig0:
+ while (*av != NULL)
+ {
+ char *p;
+ int pid = strtol (*av, &p, 10);
+ if (*p != '\0')
+ fprintf (stderr, "kill: illegal pid: %s\n", *av);
+ else
+ {
+ printf ("Sending %s(%d) signal to pid %d\n",
+ strsignal (sig), sig, pid);
+ if (kill (pid, sig))
+ perror ("kill");
+ }
+ av++;
+ }
+ return 0;
+}
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage: kill [-sigN] pid1 [pid2 ...]\n");
+ exit (1);
+}
+
+static int
+getsig (char *in_sig)
+{
+ char *sig;
+ char buf[80];
+
+ if (strncmp (in_sig, "SIG", 3) == 0)
+ sig = in_sig;
+ else
+ {
+ sprintf (buf, "SIG%s", in_sig);
+ sig = buf;
+ }
+ return (strtosigno (sig) ?: atoi (in_sig));
+}
diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c
new file mode 100644
index 0000000..0c322bb
--- /dev/null
+++ b/winsup/utils/mkgroup.c
@@ -0,0 +1,410 @@
+/* mkgroup.c:
+
+ 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. */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <sys/cygwin.h>
+#include <windows.h>
+#include <lmaccess.h>
+#include <lmapibuf.h>
+
+SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+char *
+put_sid (PSID sid)
+{
+ static char s[512];
+ char t[32];
+ DWORD i;
+
+ strcpy (s, "S-1-");
+ sprintf(t, "%u", GetSidIdentifierAuthority (sid)->Value[5]);
+ strcat (s, t);
+ for (i = 0; i < *GetSidSubAuthorityCount (sid); ++i)
+ {
+ sprintf(t, "-%lu", *GetSidSubAuthority (sid, i));
+ strcat (s, t);
+ }
+ return s;
+}
+
+void
+psx_dir (char *in, char *out)
+{
+ if (isalpha (in[0]) && in[1] == ':')
+ {
+ sprintf (out, "/cygdrive/%c", in[0]);
+ in += 2;
+ out += strlen (out);
+ }
+
+ while (*in)
+ {
+ if (*in == '\\')
+ *out = '/';
+ else
+ *out = *in;
+ in++;
+ out++;
+ }
+
+ *out = '\0';
+}
+
+void
+uni2ansi (LPWSTR wcs, char *mbs)
+{
+ if (wcs)
+ wcstombs (mbs, wcs, (wcslen (wcs) + 1) * sizeof (WCHAR));
+
+ else
+ *mbs = '\0';
+}
+
+int
+enum_local_groups (int print_sids)
+{
+ LOCALGROUP_INFO_0 *buffer;
+ DWORD entriesread = 0;
+ DWORD totalentries = 0;
+ DWORD resume_handle = 0;
+
+ do
+ {
+ DWORD i;
+ DWORD rc = NetLocalGroupEnum (NULL, 0, (LPBYTE *) & buffer, 1024,
+ &entriesread, &totalentries, &resume_handle);
+
+ switch (rc)
+ {
+ case ERROR_ACCESS_DENIED:
+ fprintf (stderr, "Access denied\n");
+ exit (1);
+
+ case ERROR_MORE_DATA:
+ case ERROR_SUCCESS:
+ break;
+
+ default:
+ fprintf (stderr, "NetUserEnum() failed with %ld\n", rc);
+ exit (1);
+ }
+
+ for (i = 0; i < entriesread; i++)
+ {
+ char localgroup_name[100];
+ char domain_name[100];
+ DWORD domname_len = 100;
+ char psid_buffer[1024];
+ PSID psid = (PSID) psid_buffer;
+ DWORD sid_length = 1024;
+ DWORD gid;
+ SID_NAME_USE acc_type;
+ uni2ansi (buffer[i].lgrpi0_name, localgroup_name);
+
+ if (!LookupAccountName (NULL, localgroup_name, psid,
+ &sid_length, domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr, "LookupAccountName(%s) failed with %ld\n",
+ localgroup_name, GetLastError ());
+ continue;
+ }
+ else if (acc_type == SidTypeDomain)
+ {
+ char domname[356];
+
+ strcpy (domname, domain_name);
+ strcat (domname, "\\");
+ strcat (domname, localgroup_name);
+ sid_length = 1024;
+ domname_len = 100;
+ if (!LookupAccountName (NULL, domname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName(%s) failed with error %ld\n",
+ localgroup_name, GetLastError ());
+ continue;
+ }
+ }
+
+ gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1);
+
+ printf ("%s:%s:%ld:\n", localgroup_name,
+ print_sids ? put_sid (psid) : "",
+ gid);
+ }
+
+ NetApiBufferFree (buffer);
+
+ }
+ while (entriesread < totalentries);
+
+ return 0;
+}
+
+void
+enum_groups (LPWSTR servername, int print_sids)
+{
+ GROUP_INFO_2 *buffer;
+ DWORD entriesread = 0;
+ DWORD totalentries = 0;
+ DWORD resume_handle = 0;
+ char ansi_srvname[256];
+
+ if (servername)
+ uni2ansi (servername, ansi_srvname);
+
+ do
+ {
+ DWORD i;
+ DWORD rc = NetGroupEnum (servername, 2, (LPBYTE *) & buffer, 1024,
+ &entriesread, &totalentries, &resume_handle);
+
+ switch (rc)
+ {
+ case ERROR_ACCESS_DENIED:
+ fprintf (stderr, "Access denied\n");
+ exit (1);
+
+ case ERROR_MORE_DATA:
+ case ERROR_SUCCESS:
+ break;
+
+ default:
+ fprintf (stderr, "NetUserEnum() failed with %ld\n", rc);
+ exit (1);
+ }
+
+ for (i = 0; i < entriesread; i++)
+ {
+ char groupname[100];
+ char domain_name[100];
+ DWORD domname_len = 100;
+ char psid_buffer[1024];
+ PSID psid = (PSID) psid_buffer;
+ DWORD sid_length = 1024;
+ SID_NAME_USE acc_type;
+
+ int gid = buffer[i].grpi2_group_id;
+ uni2ansi (buffer[i].grpi2_name, groupname);
+ if (print_sids)
+ {
+ if (!LookupAccountName (servername ? ansi_srvname : NULL,
+ groupname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName (%s, %s) failed with error %ld\n",
+ servername ? ansi_srvname : "NULL",
+ groupname,
+ GetLastError ());
+ continue;
+ }
+ else if (acc_type == SidTypeDomain)
+ {
+ char domname[356];
+
+ strcpy (domname, domain_name);
+ strcat (domname, "\\");
+ strcat (domname, groupname);
+ sid_length = 1024;
+ domname_len = 100;
+ if (!LookupAccountName (servername ? ansi_srvname : NULL,
+ domname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName(%s,%s) failed with error %ld\n",
+ servername ? ansi_srvname : "NULL",
+ domname,
+ GetLastError ());
+ continue;
+ }
+ }
+ }
+ printf ("%s:%s:%d:\n", groupname,
+ print_sids ? put_sid (psid) : "",
+ gid);
+ }
+
+ NetApiBufferFree (buffer);
+
+ }
+ while (entriesread < totalentries);
+
+ if (servername)
+ NetApiBufferFree (servername);
+}
+
+void
+usage ()
+{
+ fprintf (stderr, "\n");
+ fprintf (stderr, "usage: mkgroup <options> [domain]\n\n");
+ fprintf (stderr, "This program prints group information to stdout\n\n");
+ fprintf (stderr, "Options:\n");
+ fprintf (stderr, " -l,--local print pseudo group information if there is\n");
+ fprintf (stderr, " no domain\n");
+ fprintf (stderr, " -d,--domain print global group information from the domain\n");
+ fprintf (stderr, " specified (or from the current domain if there is\n");
+ fprintf (stderr, " no domain specified)\n");
+ fprintf (stderr, " -s,--no-sids don't print SIDs in pwd field\n");
+ fprintf (stderr, " (this affects NT security)\n");
+ fprintf (stderr, " -?,--help print this message\n\n");
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ LPWSTR servername;
+ DWORD rc = ERROR_SUCCESS;
+ WCHAR domain_name[100];
+ int print_local = 0;
+ int print_domain = 0;
+ int print_sids = 1;
+ int domain_specified = 0;
+ int i;
+
+ char name[256], dom[256];
+ DWORD len, len2;
+ PSID sid, csid;
+ SID_NAME_USE use;
+
+ if (argc == 1)
+ usage ();
+
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp (argv[i], "-l") || !strcmp (argv[i], "--local"))
+ print_local = 1;
+
+ else if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "--domain"))
+ print_domain = 1;
+
+ else if (!strcmp (argv[i], "-s") || !strcmp (argv[i], "--no-sids"))
+ print_sids = 0;
+
+ else if (!strcmp (argv[i], "-?") || !strcmp (argv[i], "--help"))
+ usage ();
+
+ else
+ {
+ mbstowcs (domain_name, argv[i], strlen (argv[i]) + 1);
+ domain_specified = 1;
+ }
+ }
+ }
+
+ /*
+ * Get `Everyone' group
+ */
+ if (AllocateAndInitializeSid (&sid_world_auth, 1, SECURITY_WORLD_RID,
+ 0, 0, 0, 0, 0, 0, 0, &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:%s:%ld:\n", name,
+ print_sids ? put_sid (sid) : "",
+ SECURITY_WORLD_RID);
+ FreeSid (sid);
+ }
+
+ /*
+ * Get `system' group
+ */
+ if (AllocateAndInitializeSid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0, &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:%s:%ld:\n", name,
+ print_sids ? put_sid (sid) : "",
+ SECURITY_LOCAL_SYSTEM_RID);
+ FreeSid (sid);
+ }
+
+ if (print_local)
+ {
+ /*
+ * Get `None' group
+ */
+ GetComputerName (name, (len = 256, &len));
+ csid = (PSID) malloc (1024);
+ LookupAccountName (NULL, name,
+ csid, (len = 1024, &len),
+ dom, (len2 = 256, &len),
+ &use);
+ if (AllocateAndInitializeSid (GetSidIdentifierAuthority (csid),
+ 5,
+ *GetSidSubAuthority (csid, 0),
+ *GetSidSubAuthority (csid, 1),
+ *GetSidSubAuthority (csid, 2),
+ *GetSidSubAuthority (csid, 3),
+ 513,
+ 0,
+ 0,
+ 0,
+ &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:%s:513:\n", name,
+ print_sids ? put_sid (sid) : "");
+ FreeSid (sid);
+ }
+ free (csid);
+ }
+
+ if (print_domain)
+ {
+ if (domain_specified)
+ rc = NetGetDCName (NULL, domain_name, (LPBYTE *) & servername);
+
+ else
+ rc = NetGetDCName (NULL, NULL, (LPBYTE *) & servername);
+
+ if (rc != ERROR_SUCCESS)
+ {
+ fprintf (stderr, "Cannot get PDC, code = %ld\n", rc);
+ exit (1);
+ }
+
+ enum_groups (servername, print_sids);
+ }
+
+ if (print_local)
+ enum_local_groups (print_sids);
+
+ return 0;
+}
diff --git a/winsup/utils/mkpasswd.c b/winsup/utils/mkpasswd.c
new file mode 100644
index 0000000..649320c
--- /dev/null
+++ b/winsup/utils/mkpasswd.c
@@ -0,0 +1,438 @@
+/* mkpasswd.c:
+
+ Copyright 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 <ctype.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <sys/cygwin.h>
+#include <windows.h>
+#include <lmaccess.h>
+#include <lmapibuf.h>
+
+SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+char *
+put_sid (PSID sid)
+{
+ static char s[512];
+ char t[32];
+ DWORD i;
+
+ strcpy (s, "S-1-");
+ sprintf(t, "%u", GetSidIdentifierAuthority (sid)->Value[5]);
+ strcat (s, t);
+ for (i = 0; i < *GetSidSubAuthorityCount (sid); ++i)
+ {
+ sprintf(t, "-%lu", *GetSidSubAuthority (sid, i));
+ strcat (s, t);
+ }
+ return s;
+}
+
+void
+psx_dir (char *in, char *out)
+{
+ if (isalpha (in[0]) && in[1] == ':')
+ {
+ sprintf (out, "/cygdrive/%c", in[0]);
+ in += 2;
+ out += strlen (out);
+ }
+
+ while (*in)
+ {
+ if (*in == '\\')
+ *out = '/';
+ else
+ *out = *in;
+ in++;
+ out++;
+ }
+
+ *out = '\0';
+}
+
+void
+uni2ansi (LPWSTR wcs, char *mbs)
+{
+ if (wcs)
+ wcstombs (mbs, wcs, (wcslen (wcs) + 1) * sizeof (WCHAR));
+
+ else
+ *mbs = '\0';
+}
+
+int
+enum_users (LPWSTR servername, int print_sids, int print_cygpath)
+{
+ USER_INFO_3 *buffer;
+ DWORD entriesread = 0;
+ DWORD totalentries = 0;
+ DWORD resume_handle = 0;
+ char ansi_srvname[256];
+
+ if (servername)
+ uni2ansi (servername, ansi_srvname);
+
+ do
+ {
+ DWORD i;
+ DWORD rc = NetUserEnum (servername, 3, FILTER_NORMAL_ACCOUNT,
+ (LPBYTE *) & buffer, 1024,
+ &entriesread, &totalentries, &resume_handle);
+
+ switch (rc)
+ {
+ case ERROR_ACCESS_DENIED:
+ fprintf (stderr, "Access denied\n");
+ exit (1);
+
+ case ERROR_MORE_DATA:
+ case ERROR_SUCCESS:
+ break;
+
+ default:
+ fprintf (stderr, "NetUserEnum() failed with %ld\n", rc);
+ exit (1);
+ }
+
+ for (i = 0; i < entriesread; i++)
+ {
+ char username[100];
+ char fullname[100];
+ char homedir_psx[MAX_PATH];
+ char homedir_w32[MAX_PATH];
+ char domain_name[100];
+ DWORD domname_len = 100;
+ char psid_buffer[1024];
+ PSID psid = (PSID) psid_buffer;
+ DWORD sid_length = 1024;
+ SID_NAME_USE acc_type;
+
+ int uid = buffer[i].usri3_user_id;
+ int gid = buffer[i].usri3_primary_group_id;
+ uni2ansi (buffer[i].usri3_name, username);
+ uni2ansi (buffer[i].usri3_full_name, fullname);
+ homedir_w32[0] = homedir_psx[0] = '\0';
+ uni2ansi (buffer[i].usri3_home_dir, homedir_w32);
+ if (print_cygpath)
+ cygwin_conv_to_posix_path (homedir_w32, homedir_psx);
+ else
+ psx_dir (homedir_w32, homedir_psx);
+
+ if (print_sids)
+ {
+ if (!LookupAccountName (servername ? ansi_srvname : NULL,
+ username,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName(%s,%s) failed with error %ld\n",
+ servername ? ansi_srvname : "NULL",
+ username,
+ GetLastError ());
+ continue;
+ }
+ else if (acc_type == SidTypeDomain)
+ {
+ char domname[356];
+
+ strcpy (domname, domain_name);
+ strcat (domname, "\\");
+ strcat (domname, username);
+ sid_length = 1024;
+ domname_len = 100;
+ if (!LookupAccountName (servername ? ansi_srvname : NULL,
+ domname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName(%s,%s) failed with error %ld\n",
+ servername ? ansi_srvname : "NULL",
+ domname,
+ GetLastError ());
+ continue;
+ }
+ }
+ }
+ printf ("%s::%d:%d:%s%s%s:%s:/bin/sh\n", username, uid, gid,
+ fullname,
+ print_sids ? "," : "",
+ print_sids ? put_sid (psid) : "",
+ homedir_psx);
+ }
+
+ NetApiBufferFree (buffer);
+
+ }
+ while (entriesread < totalentries);
+
+ if (servername)
+ NetApiBufferFree (servername);
+
+ return 0;
+}
+
+int
+enum_local_groups (int print_sids)
+{
+ LOCALGROUP_INFO_0 *buffer;
+ DWORD entriesread = 0;
+ DWORD totalentries = 0;
+ DWORD resume_handle = 0;
+
+ do
+ {
+ DWORD i;
+ DWORD rc = NetLocalGroupEnum (NULL, 0, (LPBYTE *) & buffer, 1024,
+ &entriesread, &totalentries, &resume_handle);
+
+ switch (rc)
+ {
+ case ERROR_ACCESS_DENIED:
+ fprintf (stderr, "Access denied\n");
+ exit (1);
+
+ case ERROR_MORE_DATA:
+ case ERROR_SUCCESS:
+ break;
+
+ default:
+ fprintf (stderr, "NetUserEnum() failed with %ld\n", rc);
+ exit (1);
+ }
+
+ for (i = 0; i < entriesread; i++)
+ {
+ char localgroup_name[100];
+ char domain_name[100];
+ DWORD domname_len = 100;
+ char psid_buffer[1024];
+ PSID psid = (PSID) psid_buffer;
+ DWORD sid_length = 1024;
+ DWORD gid;
+ SID_NAME_USE acc_type;
+ uni2ansi (buffer[i].lgrpi0_name, localgroup_name);
+
+ if (!LookupAccountName (NULL, localgroup_name, psid,
+ &sid_length, domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr, "LookupAccountName(%s) failed with %ld\n",
+ localgroup_name, GetLastError ());
+ continue;
+ }
+ else if (acc_type == SidTypeDomain)
+ {
+ char domname[356];
+
+ strcpy (domname, domain_name);
+ strcat (domname, "\\");
+ strcat (domname, localgroup_name);
+ sid_length = 1024;
+ domname_len = 100;
+ if (!LookupAccountName (NULL, domname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
+ {
+ fprintf (stderr,
+ "LookupAccountName(%s) failed with error %ld\n",
+ localgroup_name, GetLastError ());
+ continue;
+ }
+ }
+
+ gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1);
+
+ printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name, gid, gid,
+ print_sids ? "," : "",
+ print_sids ? put_sid (psid) : "");
+ }
+
+ NetApiBufferFree (buffer);
+
+ }
+ while (entriesread < totalentries);
+
+ return 0;
+}
+
+void
+usage ()
+{
+ fprintf (stderr, "\n");
+ fprintf (stderr, "usage: mkpasswd [options] [domain]\n\n");
+ fprintf (stderr, "This program prints a /etc/passwd file to stdout\n\n");
+ fprintf (stderr, "Options are\n");
+ fprintf (stderr, " -l,--local print local accounts\n");
+ fprintf (stderr, " -d,--domain print domain accounts (from current domain\n");
+ fprintf (stderr, " if no domain specified\n");
+ fprintf (stderr, " -g,--local-groups print local group information too\n");
+ fprintf (stderr, " -m,--no-mount don't use mount points for home dir\n");
+ fprintf (stderr, " -s,--no-sids don't print SIDs in GCOS field\n");
+ fprintf (stderr, " (this affects NT security)\n");
+ fprintf (stderr, " -?,--help displays this message\n\n");
+ fprintf (stderr, "This program does only work on Windows NT\n\n");
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ LPWSTR servername = NULL;
+ DWORD rc = ERROR_SUCCESS;
+ WCHAR domain_name[200];
+ int print_local = 0;
+ int print_domain = 0;
+ int print_local_groups = 0;
+ int domain_name_specified = 0;
+ int print_sids = 1;
+ int print_cygpath = 1;
+ int i;
+
+ char name[256], dom[256];
+ DWORD len, len2;
+ PSID sid;
+ SID_NAME_USE use;
+
+ if (argc == 1)
+ usage ();
+
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp (argv[i], "-l") || !strcmp (argv[i], "--local"))
+ print_local = 1;
+
+ else if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "--domain"))
+ print_domain = 1;
+
+ else if (!strcmp (argv[i], "-g") || !strcmp (argv[i], "--local-groups"))
+ print_local_groups = 1;
+
+ else if (!strcmp (argv[i], "-s") || !strcmp (argv[i], "--no-sids"))
+ print_sids = 0;
+
+ else if (!strcmp (argv[i], "-m") || !strcmp (argv[i], "--no-mount"))
+ print_cygpath = 0;
+
+ else if (!strcmp (argv[i], "-?") || !strcmp (argv[i], "--help"))
+ usage ();
+
+ else
+ {
+ mbstowcs (domain_name, argv[i], (strlen (argv[i]) + 1));
+ domain_name_specified = 1;
+ }
+ }
+ }
+
+ /* FIXME: this needs to take Windows 98 into account. */
+ if (GetVersion () >= 0x80000000)
+ {
+ fprintf (stderr, "The required functionality is not supported by Windows 95. Sorry.\n");
+ exit (1);
+ }
+
+ /*
+ * Get `Everyone' group
+ */
+ if (AllocateAndInitializeSid (&sid_world_auth, 1, SECURITY_WORLD_RID,
+ 0, 0, 0, 0, 0, 0, 0, &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:*:%ld:%ld:%s%s::\n", name,
+ SECURITY_WORLD_RID,
+ SECURITY_WORLD_RID,
+ print_sids ? "," : "",
+ print_sids ? put_sid (sid) : "");
+ FreeSid (sid);
+ }
+
+ /*
+ * Get `system' group
+ */
+ if (AllocateAndInitializeSid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0, &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:*:%ld:%ld:%s%s::\n", name,
+ SECURITY_LOCAL_SYSTEM_RID,
+ SECURITY_LOCAL_SYSTEM_RID,
+ print_sids ? "," : "",
+ print_sids ? put_sid (sid) : "");
+ FreeSid (sid);
+ }
+
+ /*
+ * Get `administrators' group
+ */
+ if (AllocateAndInitializeSid (&sid_nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0, &sid))
+ {
+ if (LookupAccountSid (NULL, sid,
+ name, (len = 256, &len),
+ dom, (len2 = 256, &len),
+ &use))
+ printf ("%s:*:%ld:%ld:%s%s::\n", name,
+ DOMAIN_ALIAS_RID_ADMINS,
+ DOMAIN_ALIAS_RID_ADMINS,
+ print_sids ? "," : "",
+ print_sids ? put_sid (sid) : "");
+ FreeSid (sid);
+ }
+
+ if (print_local_groups)
+ enum_local_groups (print_sids);
+
+ if (print_domain)
+ {
+ if (domain_name_specified)
+ rc = NetGetAnyDCName (NULL, domain_name, (LPBYTE *) & servername);
+
+ else
+ rc = NetGetAnyDCName (NULL, NULL, (LPBYTE *) & servername);
+
+ if (rc != ERROR_SUCCESS)
+ {
+ fprintf (stderr, "Cannot get DC, code = %ld\n", rc);
+ exit (1);
+ }
+
+ enum_users (servername, print_sids, print_cygpath);
+ }
+
+ if (print_local)
+ enum_users (NULL, print_sids, print_cygpath);
+
+ if (servername)
+ NetApiBufferFree (servername);
+
+ return 0;
+}
diff --git a/winsup/utils/mount.cc b/winsup/utils/mount.cc
new file mode 100644
index 0000000..2c34870
--- /dev/null
+++ b/winsup/utils/mount.cc
@@ -0,0 +1,240 @@
+/* mount.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 <sys/mount.h>
+#include <sys/stat.h>
+#include <mntent.h>
+#include <windows.h>
+#include <sys/cygwin.h>
+#include "winsup.h"
+#include "external.h"
+
+#ifdef errno
+#undef errno
+#endif
+#include <errno.h>
+
+static void show_mounts (void);
+static void change_cygdrive_prefix (const char *new_prefix, int flags);
+static int mount_already_exists (const char *posix_path, int flags);
+
+// static short create_missing_dirs = FALSE;
+static short force = FALSE;
+
+static const char *progname;
+
+/* FIXME: do_mount should also print a warning message if the dev arg
+ is a non-existent Win32 path. */
+
+static void
+do_mount (const char *dev, const char *where, int flags)
+{
+ struct stat statbuf;
+ char win32_path[MAX_PATH];
+ int statres;
+
+ cygwin_conv_to_win32_path (where, win32_path);
+
+ statres = stat (win32_path, &statbuf);
+
+#if 0
+ if (statres == -1)
+ {
+ /* FIXME: this'll fail if mount dir is missing any parent dirs */
+ if (create_missing_dirs == TRUE)
+ {
+ if (mkdir (where, 0755) == -1)
+ fprintf (stderr, "Warning: unable to create %s!\n", where);
+ else
+ statres = 0; /* Pretend stat succeeded if we could mkdir. */
+ }
+ }
+#endif
+
+ if (mount (dev, where, flags))
+ {
+ perror ("mount failed");
+ exit (1);
+ }
+
+ if (statres == -1)
+ {
+ if (force == FALSE)
+ fprintf (stderr, "%s: warning - %s does not exist.\n", progname, where);
+ }
+ else if (!(statbuf.st_mode & S_IFDIR))
+ {
+ if (force == FALSE)
+ fprintf (stderr, "%s: warning: %s is not a directory!\n", progname, where);
+ }
+
+ exit (0);
+}
+
+static void
+usage (void)
+{
+ fprintf (stderr, "usage %s [-bfstux] <win32path> <posixpath>
+-b text files are equivalent to binary files (newline = \\n)
+-f force mount, don't warn about missing mount point directories
+-s add mount point to system-wide registry location
+-t text files get \\r\\n line endings (default)
+-u add mount point to user registry location (default)
+-x treat all files under mount point as executables
+
+[-bs] --change-cygdrive-prefix <posixpath>
+ change the cygdrive path prefix to <posixpath>
+--import-old-mounts
+ copy old registry mount table mounts into the current mount areas
+", progname);
+ exit (1);
+}
+
+int
+main (int argc, const char **argv)
+{
+ int i;
+ int flags = 0;
+
+ progname = argv[0];
+
+ if (argc == 1)
+ {
+ show_mounts ();
+ exit (0);
+ }
+
+ for (i = 1; i < argc; ++i)
+ {
+ if (argv[i][0] != '-')
+ break;
+
+ if (strcmp (argv[i], "--change-cygdrive-prefix") == 0)
+ {
+ if ((i + 2) != argc)
+ usage ();
+
+ change_cygdrive_prefix (argv[i+1], flags);
+ }
+ else if (strcmp (argv[i], "--import-old-mounts") == 0)
+ {
+ if ((i + 1) != argc)
+ usage ();
+
+ cygwin_internal (CW_READ_V1_MOUNT_TABLES);
+ exit (0);
+ }
+ else if (strcmp (argv[i], "-b") == 0)
+ flags |= MOUNT_BINARY;
+ else if (strcmp (argv[i], "-t") == 0)
+ flags &= ~MOUNT_BINARY;
+#if 0
+ else if (strcmp (argv[i], "-c") == 0)
+ create_missing_dirs = TRUE;
+#endif
+ else if (strcmp (argv[i], "-s") == 0)
+ flags |= MOUNT_SYSTEM;
+ else if (strcmp (argv[i], "-u") == 0)
+ flags &= ~MOUNT_SYSTEM;
+ else if (strcmp (argv[i], "-x") == 0)
+ flags |= MOUNT_EXEC;
+ else if (strcmp (argv[i], "-f") == 0)
+ force = TRUE;
+ else
+ usage ();
+ }
+
+ if ((i + 2) != argc)
+ usage ();
+
+ if ((force == FALSE) && (mount_already_exists (argv[i + 1], flags)))
+ {
+ errno = EBUSY;
+ perror ("mount failed");
+ exit (1);
+ }
+ else
+ do_mount (argv[i], argv[i + 1], flags);
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static void
+show_mounts (void)
+{
+ FILE *m = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+ const char *format = "%-18s %-18s %-11s %s\n";
+
+ printf (format, "Device", "Directory", "Type", "Flags");
+ while ((p = getmntent (m)) != NULL)
+ {
+ printf (format,
+ p->mnt_fsname,
+ p->mnt_dir,
+ p->mnt_type,
+ p->mnt_opts);
+ }
+ endmntent (m);
+}
+
+/* Return 1 if mountpoint from the same registry area is already in
+ mount table. Otherwise return 0. */
+static int
+mount_already_exists (const char *posix_path, int flags)
+{
+ int found_matching = 0;
+
+ FILE *m = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+
+ while ((p = getmntent (m)) != NULL)
+ {
+ /* if the paths match, and they're both the same type of mount. */
+ if (strcmp (p->mnt_dir, posix_path) == 0)
+ {
+ if (p->mnt_type[0] == 'u' && !(flags & MOUNT_SYSTEM)) /* both current_user */
+ {
+ found_matching = 1;
+ break;
+ }
+ else if (p->mnt_type[0] == 's' && (flags & MOUNT_SYSTEM)) /* both system */
+ {
+ found_matching = 1;
+ break;
+ }
+ else
+ {
+ fprintf (stderr, "%s: warning -- couldn't determine mount type.\n", progname);
+ break;
+ }
+ }
+ }
+ endmntent (m);
+
+ return found_matching;
+}
+
+/* change_cygdrive_prefix: Change the cygdrive prefix */
+static void
+change_cygdrive_prefix (const char *new_prefix, int flags)
+{
+ flags |= MOUNT_AUTO;
+
+ if (mount (NULL, new_prefix, flags))
+ {
+ perror ("mount failed");
+ exit (1);
+ }
+
+ exit (0);
+}
diff --git a/winsup/utils/passwd.c b/winsup/utils/passwd.c
new file mode 100644
index 0000000..700ea4d
--- /dev/null
+++ b/winsup/utils/passwd.c
@@ -0,0 +1,352 @@
+/* passwd.c: Changing passwords and managing account information
+
+ Copyright 1999 Cygnus Solutions.
+
+ Written by Corinna Vinschen <corinna.vinschen@cityweb.de>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <windows.h>
+#include <lmaccess.h>
+#include <lmerr.h>
+#include <lmcons.h>
+#include <lmapibuf.h>
+
+#define USER_PRIV_ADMIN 2
+
+#define UF_LOCKOUT 0x00010
+
+char *myname;
+
+int
+eprint (int with_name, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (with_name)
+ fprintf(stderr, "%s: ", myname);
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf(stderr, "\n");
+ return 1;
+}
+
+int
+EvalRet (int ret, const char *user)
+{
+ switch (ret)
+ {
+ case NERR_Success:
+ return 0;
+
+ case ERROR_ACCESS_DENIED:
+ if (! user)
+ eprint (0, "You may not change password expiry information.");
+ else
+ eprint (0, "You may not change the password for %s.", user);
+ break;
+
+ eprint (0, "Bad password: Invalid.");
+ break;
+
+ case NERR_PasswordTooShort:
+ eprint (0, "Bad password: Too short.");
+ break;
+
+ case NERR_UserNotFound:
+ eprint (1, "unknown user %s", user);
+ break;
+
+ case ERROR_INVALID_PASSWORD:
+ case NERR_BadPassword:
+ eprint (0, "Incorrect password for %s.", user);
+ eprint (0, "The password for %s is unchanged.", user);
+ break;
+
+ default:
+ eprint (1, "unrecoverable error %d", ret);
+ break;
+ }
+ return 1;
+}
+
+PUSER_INFO_3
+GetPW (const char *user)
+{
+ WCHAR name[512];
+ DWORD ret;
+ PUSER_INFO_3 ui;
+
+ MultiByteToWideChar (CP_ACP, 0, user, -1, name, 512);
+ ret = NetUserGetInfo (NULL, name, 3, (LPBYTE *) &ui);
+ return EvalRet (ret, user) ? NULL : ui;
+}
+
+int
+ChangePW (const char *user, const char *oldpwd, const char *pwd)
+{
+ WCHAR name[512], oldpass[512], pass[512];
+ DWORD ret;
+
+ MultiByteToWideChar (CP_ACP, 0, user, -1, name, 512);
+ MultiByteToWideChar (CP_ACP, 0, pwd, -1, pass, 512);
+ if (! oldpwd)
+ {
+ USER_INFO_1003 ui;
+
+ ui.usri1003_password = pass;
+ ret = NetUserSetInfo (NULL, name, 1003, (LPBYTE) &ui, NULL);
+ }
+ else
+ {
+ MultiByteToWideChar (CP_ACP, 0, oldpwd, -1, oldpass, 512);
+ ret = NetUserChangePassword (NULL, name, oldpass, pass);
+ }
+ if (! EvalRet (ret, user))
+ {
+ eprint (0, "Password changed.");
+ }
+ return ret;
+}
+
+void
+PrintPW (PUSER_INFO_3 ui)
+{
+ time_t t = time (NULL) - ui->usri3_password_age;
+ int ret;
+ PUSER_MODALS_INFO_0 mi;
+
+ printf ("Account disabled : %s", (ui->usri3_flags & UF_ACCOUNTDISABLE)
+ ? "yes\n" : "no\n");
+ printf ("Password required: %s", (ui->usri3_flags & UF_PASSWD_NOTREQD)
+ ? "no\n" : "yes\n");
+ printf ("Password expired : %s", (ui->usri3_password_expired)
+ ? "yes\n" : "no\n");
+ printf ("Password changed : %s", ctime(&t));
+ ret = NetUserModalsGet (NULL, 0, (LPBYTE *) &mi);
+ if (! ret)
+ {
+ if (mi->usrmod0_max_passwd_age == TIMEQ_FOREVER
+ || ui->usri3_priv == USER_PRIV_ADMIN)
+ mi->usrmod0_max_passwd_age = 0;
+ if (mi->usrmod0_min_passwd_age == TIMEQ_FOREVER
+ || ui->usri3_priv == USER_PRIV_ADMIN)
+ mi->usrmod0_min_passwd_age = 0;
+ if (mi->usrmod0_force_logoff == TIMEQ_FOREVER
+ || ui->usri3_priv == USER_PRIV_ADMIN)
+ mi->usrmod0_force_logoff = 0;
+ if (ui->usri3_priv == USER_PRIV_ADMIN)
+ mi->usrmod0_min_passwd_len = 0;
+ printf ("Max. password age %ld days\n",
+ mi->usrmod0_max_passwd_age / ONE_DAY);
+ printf ("Min. password age %ld days\n",
+ mi->usrmod0_min_passwd_age / ONE_DAY);
+ printf ("Force logout after %ld days\n",
+ mi->usrmod0_force_logoff / ONE_DAY);
+ printf ("Min. password length: %ld\n",
+ mi->usrmod0_min_passwd_len);
+ }
+}
+
+int
+SetModals (int xarg, int narg, int iarg, int Larg)
+{
+ int ret;
+ PUSER_MODALS_INFO_0 mi;
+
+ ret = NetUserModalsGet (NULL, 0, (LPBYTE *) &mi);
+ if (! ret)
+ {
+ if (xarg == 0)
+ mi->usrmod0_max_passwd_age = TIMEQ_FOREVER;
+ else if (xarg > 0)
+ mi->usrmod0_max_passwd_age = xarg * ONE_DAY;
+
+ if (narg == 0)
+ {
+ mi->usrmod0_min_passwd_age = TIMEQ_FOREVER;
+ mi->usrmod0_password_hist_len = 0;
+ }
+ else if (narg > 0)
+ mi->usrmod0_min_passwd_age = narg * ONE_DAY;
+
+ if (iarg == 0)
+ mi->usrmod0_force_logoff = TIMEQ_FOREVER;
+ else if (iarg > 0)
+ mi->usrmod0_force_logoff = iarg * ONE_DAY;
+
+ if (Larg >= 0)
+ mi->usrmod0_min_passwd_len = Larg;
+
+ ret = NetUserModalsSet (NULL, 0, (LPBYTE) mi, NULL);
+ NetApiBufferFree (mi);
+ }
+ return EvalRet (ret, NULL);
+}
+
+int
+usage ()
+{
+ fprintf (stderr, "usage: %s [name]\n", myname);
+ fprintf (stderr, " %s [-L maxlen] [-x max] [-n min] [-i inact]\n",
+ myname);
+ fprintf (stderr, " %s {-l|-u|-S} name\n", myname);
+ return 2;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *c;
+ char user[64], oldpwd[64], newpwd[64];
+ int ret = 0;
+ int cnt = 0;
+ int opt;
+ int Larg = -1;
+ int xarg = -1;
+ int narg = -1;
+ int iarg = -1;
+ int lopt = 0;
+ int uopt = 0;
+ int Sopt = 0;
+ PUSER_INFO_3 ui, li;
+
+ if ((myname = strrchr (argv[0], '/'))
+ || (myname = strrchr (argv[0], '\\')))
+ ++myname;
+ else
+ myname = argv[0];
+ c = strrchr (myname, '.');
+ if (c)
+ *c = '\0';
+
+ while ((opt = getopt (argc, argv, "L:x:n:i:luS")) != EOF)
+ switch (opt)
+ {
+ case 'x':
+ if ((xarg = atoi (optarg)) < 0 || xarg > 999)
+ return eprint (1, "Maximum password age must be between 0 and 999.");
+ if (narg >= 0 && xarg < narg)
+ return eprint (1, "Maximum password age must be greater than "
+ "minimum password age.");
+ break;
+
+ case 'n':
+ if ((narg = atoi (optarg)) < 0 || narg > 999)
+ return eprint (1, "Minimum password age must be between 0 and 999.");
+ if (xarg >= 0 && narg > xarg)
+ return eprint (1, "Minimum password age must be less than "
+ "maximum password age.");
+ break;
+
+ case 'i':
+ if ((iarg = atoi (optarg)) < 0 || iarg > 999)
+ return eprint (1, "Force logout time must be between 0 and 999.");
+ break;
+
+ case 'L':
+ if ((Larg = atoi (optarg)) < 0 || Larg > LM20_PWLEN)
+ return eprint (1, "Minimum password length must be between "
+ "0 and %d.", LM20_PWLEN);
+ break;
+
+ case 'l':
+ if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || uopt || Sopt)
+ return usage ();
+ lopt = 1;
+ break;
+
+ case 'u':
+ if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || Sopt)
+ return usage ();
+ uopt = 1;
+ break;
+
+ case 'S':
+ if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt)
+ return usage ();
+ Sopt = 1;
+ break;
+
+ default:
+ return usage ();
+ }
+ if (Larg >= 0 || xarg >= 0 || narg >= 0 || iarg >= 0)
+ {
+ if (optind < argc)
+ return usage ();
+ return SetModals (xarg, narg, iarg, Larg);
+ }
+
+ strcpy (user, optind >= argc ? getlogin () : argv[optind]);
+
+ li = GetPW (getlogin ());
+ if (! li)
+ return 1;
+
+ ui = GetPW (user);
+ if (! ui)
+ return 1;
+
+ if (lopt || uopt || Sopt)
+ {
+ if (li->usri3_priv != USER_PRIV_ADMIN)
+ return eprint (0, "You have no maintenance privileges.");
+ if (lopt)
+ {
+ if (ui->usri3_priv == USER_PRIV_ADMIN)
+ return eprint (0, "You may not lock an administrators account.");
+ ui->usri3_flags |= UF_ACCOUNTDISABLE;
+ }
+ if (uopt)
+ ui->usri3_flags &= ~UF_ACCOUNTDISABLE;
+ if (lopt || uopt)
+ {
+ ret = NetUserSetInfo (NULL, ui->usri3_name, 3, (LPBYTE) ui, NULL);
+ return EvalRet (ret, NULL);
+ }
+ // Sopt
+ PrintPW (ui);
+ return 0;
+ }
+
+ if (li->usri3_priv != USER_PRIV_ADMIN && strcmp (getlogin (), user))
+ return eprint (0, "You may not change the password for %s.", user);
+
+ eprint (0, "Enter the new password (minimum of 5, maximum of 8 characters).");
+ eprint (0, "Please use a combination of upper and lower case letters and numbers.");
+
+ if (li->usri3_priv != USER_PRIV_ADMIN)
+ {
+ strcpy (oldpwd, getpass ("Old password: "));
+ if (ChangePW (user, oldpwd, oldpwd))
+ return 1;
+ }
+
+ do
+ {
+ strcpy (newpwd, getpass ("New password: "));
+ if (strcmp (newpwd, getpass ("Re-enter new password: ")))
+ eprint (0, "Password is not identical.");
+ else if (! ChangePW (user, *oldpwd ? oldpwd : NULL, newpwd))
+ ret = 1;
+ if (! ret && cnt < 2)
+ eprint (0, "Try again.");
+ }
+ while (! ret && ++cnt < 3);
+ return ! ret;
+}
diff --git a/winsup/utils/ps.cc b/winsup/utils/ps.cc
new file mode 100644
index 0000000..4767a6a
--- /dev/null
+++ b/winsup/utils/ps.cc
@@ -0,0 +1,150 @@
+/* ps.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 <stdio.h>
+#include <time.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <sys/cygwin.h>
+#include "winsup.h"
+#include "external.h"
+
+static char *
+start_time (external_pinfo *child)
+{
+ time_t st = child->start_time;
+ time_t t = time (NULL);
+ static char stime[40] = {'\0'};
+ char now[40];
+
+ strncpy (stime, ctime (&st) + 4, 15);
+ strcpy (now, ctime (&t) + 4);
+
+ if ((t - st) < (24 * 3600))
+ return (stime + 7);
+
+ stime[6] = '\0';
+
+ return stime;
+}
+
+int
+main (int argc, char *argv[])
+{
+ external_pinfo *p;
+ int aflag, lflag, fflag, uid;
+ const char *dtitle = " PID TTY STIME COMMAND\n";
+ const char *dfmt = "%5d%4d%10s %s\n";
+ const char *ftitle = " UID PID PPID TTY STIME COMMAND\n";
+ const char *ffmt = "%8.8s%6d%6d%4d%10s %s\n";
+ const char *ltitle = " PID PPID PGID WINPID UID TTY STIME COMMAND\n";
+ const char *lfmt = "%c %5d %5d %5d %8u %4d %3d %8s %s\n";
+ char ch;
+
+ aflag = lflag = fflag = 0;
+ uid = getuid ();
+
+ while ((ch = getopt (argc, argv, "aelfu:")) != -1)
+ switch (ch)
+ {
+ case 'a':
+ case 'e':
+ aflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'u':
+ uid = atoi (optarg);
+ if (uid == 0)
+ {
+ struct passwd *pw;
+
+ if ((pw = getpwnam (optarg)))
+ uid = pw->pw_uid;
+ else
+ {
+ fprintf (stderr, "user %s unknown\n", optarg);
+ exit (1);
+ }
+ }
+ break;
+ default:
+ fprintf (stderr, "Usage %s [-aefl] [-u uid]\n", argv[0]);
+ fprintf (stderr, "-f = show process uids, ppids\n");
+ fprintf (stderr, "-l = show process uids, ppids, pgids, winpids\n");
+ fprintf (stderr, "-u uid = list processes owned by uid\n");
+ fprintf (stderr, "-a, -e = show processes of all users\n");
+ exit (1);
+ }
+
+ if (lflag)
+ printf (ltitle);
+ else if (fflag)
+ printf (ftitle);
+ else
+ printf (dtitle);
+
+ (void) cygwin_internal (CW_LOCK_PINFO, 1000);
+
+ for (int pid = 0;
+ (p = (external_pinfo *) cygwin_internal (CW_GETPINFO,
+ pid | CW_NEXTPID));
+ pid = p->pid)
+ {
+ if (p->process_state == PID_NOT_IN_USE)
+ continue;
+ if (!aflag && p->uid != uid)
+ continue;
+ char status = ' ';
+ if (p->process_state & PID_STOPPED)
+ status = 'S';
+ else if (p->process_state & PID_TTYIN)
+ status = 'I';
+ else if (p->process_state & PID_TTYOU)
+ status = 'O';
+
+ char pname[MAX_PATH];
+ if (p->process_state & PID_ZOMBIE)
+ strcpy (pname, "<defunct>");
+ else
+ cygwin_conv_to_posix_path (p->progname, pname);
+
+ char uname[128];
+
+ if (fflag)
+ {
+ struct passwd *pw;
+
+ if ((pw = getpwuid (p->uid)))
+ strcpy (uname, pw->pw_name);
+ else
+ sprintf (uname, "%d", p->uid);
+ }
+
+ if (lflag)
+ printf (lfmt, status, p->pid, p->ppid, p->pgid,
+ p->dwProcessId, p->uid, p->ctty, start_time (p), pname);
+ else if (fflag)
+ printf (ffmt, uname, p->pid, p->ppid, p->ctty, start_time (p), pname);
+ else
+ printf (dfmt, p->pid, p->ctty, start_time (p), pname);
+
+ }
+ (void) cygwin_internal (CW_UNLOCK_PINFO);
+
+ return 0;
+}
+
diff --git a/winsup/utils/regtool.cc b/winsup/utils/regtool.cc
new file mode 100644
index 0000000..1e79e3a
--- /dev/null
+++ b/winsup/utils/regtool.cc
@@ -0,0 +1,524 @@
+/* regtool.cc
+
+ Copyright 2000 Red Hat Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <windows.h>
+
+enum {
+ KT_AUTO, KT_INT, KT_STRING, KT_EXPAND, KT_MULTI
+} key_type = KT_AUTO;
+
+int verbose = 0;
+int quiet = 0;
+char **argv;
+
+HKEY key;
+char *value;
+
+const char *usage_msg[] =
+{
+ "Regtool Copyright (c) 2000 Red Hat Inc",
+ " regtool -h - print this message",
+ " regtool [-v] list [key] - list subkeys and values",
+ " regtool [-v] add [key\\subkey] - add new subkey",
+ " regtool [-v] remove [key] - remove key",
+ " regtool [-v|-q] check [key] - exit 0 if key exists, 1 if not",
+ " regtool [-i|-s|-e|-m] set [key\\value] [data ...] - set value",
+ " -i=integer -s=string -e=expand-string -m=multi-string",
+ " regtool [-v] unset [key\\value] - removes value from key",
+ " regtool [-q] get [key\\value] - prints value to stdout",
+ " -q=quiet, no error msg, just return nonzero exit if key/value missing",
+ " keys are like \\prefix\\key\\key\\key\\value, where prefix is any of:",
+ " root HKCR HKEY_CLASSES_ROOT",
+ " config HKCC HKEY_CURRENT_CONFIG",
+ " user HKCU HKEY_CURRENT_USER",
+ " machine HKLM HKEY_LOCAL_MACHINE",
+ " users HKU HKEY_USERS",
+ " example: \\user\\software\\Microsoft\\Clock\\iFormat",
+ 0
+};
+
+void
+usage(void)
+{
+ int i;
+ for (i=0; usage_msg[i]; i++)
+ fprintf(stderr, "%s\n", usage_msg[i]);
+ exit(1);
+}
+
+void
+Fail(DWORD rv)
+{
+ char *buf;
+ if (!quiet)
+ {
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, rv, 0, (CHAR *)&buf, 0, 0);
+ fprintf(stderr, "Error: %s\n", buf);
+ }
+ exit(1);
+}
+
+struct {
+ const char *string;
+ HKEY key;
+} wkprefixes[] = {
+ { "root", HKEY_CLASSES_ROOT },
+ { "HKCR", HKEY_CLASSES_ROOT },
+ { "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
+ { "config", HKEY_CURRENT_CONFIG },
+ { "HKCC", HKEY_CURRENT_CONFIG },
+ { "HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG },
+ { "user", HKEY_CURRENT_USER },
+ { "HKCU", HKEY_CURRENT_USER },
+ { "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
+ { "machine", HKEY_LOCAL_MACHINE },
+ { "HKLM", HKEY_LOCAL_MACHINE },
+ { "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
+ { "users", HKEY_USERS },
+ { "HKU", HKEY_USERS },
+ { "HKEY_USERS", HKEY_USERS },
+ { 0, 0 }
+};
+
+void translate(char *key)
+{
+#define isodigit(c) (strchr("01234567", c))
+#define tooct(c) ((c)-'0')
+#define tohex(c) (strchr(_hs,tolower(c))-_hs)
+ static char _hs[] = "0123456789abcdef";
+
+ char *d = key;
+ char *s = key;
+ char c;
+
+ while (*s)
+ {
+ if (*s == '\\')
+ switch (*++s)
+ {
+ case 'a':
+ *d++ = '\007';
+ break;
+ case 'b':
+ *d++ = '\b';
+ break;
+ case 'e':
+ *d++ = '\033';
+ break;
+ case 'f':
+ *d++ = '\f';
+ break;
+ case 'n':
+ *d++ = '\n';
+ break;
+ case 'r':
+ *d++ = '\r';
+ break;
+ case 't':
+ *d++ = '\t';
+ break;
+ case 'v':
+ *d++ = '\v';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = tooct(*s);
+ if (isodigit(s[1]))
+ {
+ c = (c << 3) | tooct(*++s);
+ if (isodigit(s[1]))
+ c = (c << 3) | tooct(*++s);
+ }
+ *d++ = c;
+ break;
+ case 'x':
+ if (isxdigit(s[1]))
+ {
+ c = tohex(*++s);
+ if (isxdigit(s[1]))
+ c = (c << 4) | tohex(*++s);
+ }
+ *d++ = c;
+ break;
+ default: /* before non-special char: just add the char */
+ *d++ = *s;
+ break;
+ }
+ else if (*s == '/')
+ *d++ = '\\';
+ else
+ *d++ = *s;
+ ++s;
+ }
+ *d = '\0';
+}
+
+void
+find_key(int howmanyparts)
+{
+ char *n = argv[0], *e, c;
+ int i;
+ if (*n == '/')
+ translate(n);
+ while (*n == '\\')
+ n++;
+ for (e=n; *e && *e != '\\'; e++);
+ c = *e;
+ *e = 0;
+ for (i=0; wkprefixes[i].string; i++)
+ if (strcmp(wkprefixes[i].string, n) == 0)
+ break;
+ if (!wkprefixes[i].string)
+ {
+ fprintf(stderr, "Unknown key prefix. Valid prefixes are:\n");
+ for (i=0; wkprefixes[i].string; i++)
+ fprintf(stderr, "\t%s\n", wkprefixes[i].string);
+ exit(1);
+ }
+
+ n = e;
+ *e = c;
+ while (*n && *n == '\\')
+ n++;
+ e = n+strlen(n);
+ if (howmanyparts > 1)
+ {
+ while (n < e && *e != '\\')
+ e--;
+ if (*e != '\\')
+ {
+ fprintf(stderr, "Invalid key\n");
+ exit(1);
+ }
+ *e = 0;
+ value = e+1;
+ }
+ if (n[0] == 0)
+ {
+ key = wkprefixes[i].key;
+ return;
+ }
+ int rv = RegOpenKeyEx(wkprefixes[i].key, n, 0, KEY_ALL_ACCESS, &key);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+ //printf("key `%s' value `%s'\n", n, value);
+}
+
+
+int
+cmd_list()
+{
+ DWORD num_subkeys, maxsubkeylen, num_values, maxvalnamelen, maxvaluelen;
+ DWORD maxclasslen;
+ char *subkey_name, *value_name, *class_name;
+ unsigned char *value_data, *vd;
+ DWORD i, j, m, n, t;
+ int v;
+
+ find_key(1);
+ RegQueryInfoKey(key, 0, 0, 0, &num_subkeys, &maxsubkeylen, &maxclasslen,
+ &num_values, &maxvalnamelen, &maxvaluelen, 0, 0);
+
+ subkey_name = (char *)malloc(maxsubkeylen+1);
+ class_name = (char *)malloc(maxclasslen+1);
+ value_name = (char *)malloc(maxvalnamelen+1);
+ value_data = (unsigned char *)malloc(maxvaluelen+1);
+
+ for (i=0; i<num_subkeys; i++)
+ {
+ m = maxsubkeylen+1;
+ n = maxclasslen+1;
+ RegEnumKeyEx(key, i, subkey_name, &m, 0, class_name, &n, 0);
+ if (verbose)
+ printf("%s\\ (%s)\n", subkey_name, class_name);
+ else
+ printf("%s\n", subkey_name);
+ }
+
+ for (i=0; i<num_values; i++)
+ {
+ m = maxvalnamelen+1;
+ n = maxvaluelen+1;
+ RegEnumValue(key, i, value_name, &m, 0, &t, (BYTE *)value_data, &n);
+ if (!verbose)
+ printf("%s\n", value_name);
+ else
+ {
+ printf("%s = ", value_name);
+ switch (t)
+ {
+ case REG_BINARY:
+ for (j=0; j<8 && j<n; j++)
+ printf("%02x ", value_data[j]);
+ printf("\n");
+ break;
+ case REG_DWORD:
+ printf("0x%08lx (%lu)\n", *(DWORD *)value_data,
+ *(DWORD *)value_data);
+ break;
+ case REG_DWORD_BIG_ENDIAN:
+ v = ((value_data[0] << 24)
+ | (value_data[1] << 16)
+ | (value_data[2] << 8)
+ | (value_data[3]));
+ printf("0x%08x (%d)\n", v, v);
+ break;
+ case REG_EXPAND_SZ:
+ case REG_SZ:
+ printf("\"%s\"\n", value_data);
+ break;
+ case REG_MULTI_SZ:
+ vd = value_data;
+ while (vd && *vd)
+ {
+ printf("\"%s\"", vd);
+ vd = vd+strlen((const char *)vd) + 1;
+ if (*vd)
+ printf(", ");
+ }
+ printf("\n");
+ break;
+ default:
+ printf("? (type %d)\n", (int)t);
+ }
+ }
+ }
+ return 0;
+}
+
+int
+cmd_add()
+{
+ find_key(2);
+ HKEY newkey;
+ DWORD newtype;
+ int rv = RegCreateKeyEx(key, value, 0, (char *)"", REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS, 0, &newkey, &newtype);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+
+ if (verbose)
+ {
+ if (newtype == REG_OPENED_EXISTING_KEY)
+ printf("Key %s already exists\n", value);
+ else
+ printf("Key %s created\n", value);
+ }
+ return 0;
+}
+
+int
+cmd_remove()
+{
+ find_key(2);
+ DWORD rv = RegDeleteKey(key, value);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+ if (verbose)
+ printf("subkey %s deleted\n", value);
+ return 0;
+}
+
+int
+cmd_check()
+{
+ find_key(1);
+ if (verbose)
+ printf("key %s exists\n", argv[0]);
+ return 0;
+}
+
+int
+cmd_set()
+{
+ int i, n;
+ DWORD v, rv;
+ char *a = argv[1], *data;
+ find_key(2);
+
+ if (key_type == KT_AUTO)
+ {
+ char *e;
+ strtoul(a, &e, 0);
+ if (a[0] == '%')
+ key_type = KT_EXPAND;
+ else if (a[0] && !*e)
+ key_type = KT_INT;
+ else if (argv[2])
+ key_type = KT_MULTI;
+ else
+ key_type = KT_STRING;
+ }
+
+ switch (key_type)
+ {
+ case KT_INT:
+ v = strtoul(a, 0, 0);
+ rv = RegSetValueEx(key, value, 0, REG_DWORD, (const BYTE *)&v, sizeof(v));
+ break;
+ case KT_STRING:
+ rv = RegSetValueEx(key, value, 0, REG_SZ, (const BYTE *)a, strlen(a));
+ break;
+ case KT_EXPAND:
+ rv = RegSetValueEx(key, value, 0, REG_EXPAND_SZ, (const BYTE *)a, strlen(a));
+ break;
+ case KT_MULTI:
+ for (i=1, n=1; argv[i]; i++)
+ n += strlen(argv[i])+1;
+ data = (char *)malloc(n);
+ for (i=1, n=0; argv[i]; i++)
+ {
+ strcpy(data+n, argv[i]);
+ n += strlen(argv[i])+1;
+ }
+ data[n] = 0;
+ rv = RegSetValueEx(key, value, 0, REG_MULTI_SZ, (const BYTE *)data, n+1);
+ break;
+ case KT_AUTO:
+ break;
+ }
+
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+
+ return 0;
+}
+
+int
+cmd_unset()
+{
+ find_key(2);
+ DWORD rv = RegDeleteValue(key, value);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+ if (verbose)
+ printf("value %s deleted\n", value);
+ return 0;
+}
+
+int
+cmd_get()
+{
+ find_key(2);
+ DWORD vtype, dsize, rv;
+ char *data, *vd;
+ rv = RegQueryValueEx(key, value, 0, &vtype, 0, &dsize);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+ dsize++;
+ data = (char *)malloc(dsize);
+ rv = RegQueryValueEx(key, value, 0, &vtype, (BYTE *)data, &dsize);
+ if (rv != ERROR_SUCCESS)
+ Fail(rv);
+ switch (vtype)
+ {
+ case REG_BINARY:
+ fwrite(data, dsize, 0, stdout);
+ break;
+ case REG_DWORD:
+ printf("%lu\n", *(DWORD *)data);
+ break;
+ case REG_SZ:
+ printf("%s\n", data);
+ break;
+ case REG_EXPAND_SZ:
+ if (key_type == KT_EXPAND) // hack
+ {
+ char *buf;
+ DWORD bufsize;
+ bufsize = ExpandEnvironmentStrings(data, 0, 0);
+ buf = (char *)malloc(bufsize+1);
+ ExpandEnvironmentStrings(data, buf, bufsize+1);
+ data = buf;
+ }
+ printf("%s\n", data);
+ break;
+ case REG_MULTI_SZ:
+ vd = data;
+ while (vd && *vd)
+ {
+ printf("%s\n", vd);
+ vd = vd+strlen((const char *)vd) + 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+struct {
+ const char *name;
+ int (*func)();
+} commands[] = {
+ { "list", cmd_list },
+ { "add", cmd_add },
+ { "remove", cmd_remove },
+ { "check", cmd_check },
+ { "set", cmd_set },
+ { "unset", cmd_unset },
+ { "get", cmd_get },
+ { 0, 0 }
+};
+
+int
+main(int argc, char **_argv)
+{
+ while (1)
+ {
+ int g = getopt (argc, _argv, "hvqisem");
+ if (g == -1)
+ break;
+ switch (g)
+ {
+ case 'v':
+ verbose ++;
+ break;
+ case 'q':
+ quiet ++;
+ break;
+
+ case 'i':
+ key_type = KT_INT;
+ break;
+ case 's':
+ key_type = KT_STRING;
+ break;
+ case 'e':
+ key_type = KT_EXPAND;
+ break;
+ case 'm':
+ key_type = KT_MULTI;
+ break;
+
+ case '?':
+ case 'h':
+ usage();
+ }
+ }
+ if (_argv[optind] == NULL)
+ usage();
+
+ argv = _argv+optind;
+ int i;
+ for (i=0; commands[i].name; i++)
+ if (strcmp(commands[i].name, argv[0]) == 0)
+ {
+ argv++;
+ return commands[i].func();
+ }
+ usage();
+
+ return 0;
+}
diff --git a/winsup/utils/setfacl.c b/winsup/utils/setfacl.c
new file mode 100644
index 0000000..87c96ae
--- /dev/null
+++ b/winsup/utils/setfacl.c
@@ -0,0 +1,377 @@
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef ILLEGAL_MODE
+#define ILLEGAL_MODE ((mode_t)0xffffffff)
+#endif
+
+typedef enum {
+ NoAction,
+ Set,
+ Modify,
+ Delete,
+ ModNDel,
+ SetFromFile
+} action_t;
+
+char *myname;
+
+int usage ()
+{
+ fprintf(stderr, "usage: %s [-r] -s acl_entries file...\n", myname);
+ fprintf(stderr, " %s [-r] -md acl_entries file...\n", myname);
+ fprintf(stderr, " %s [-r] -f acl_file file...\n", myname);
+ return 1;
+}
+
+mode_t getperm (char *in)
+{
+ if (isdigit (*in) && !in[1])
+ {
+ int i = atoi (in);
+ if (i < 0 || i > 7)
+ return ILLEGAL_MODE;
+ return i << 6 | i << 3 | i;
+ }
+ if (strlen (in) != 3)
+ return ILLEGAL_MODE;
+ if (!strchr ("r-", in[0])
+ || !strchr ("w-", in[1])
+ || !strchr ("x-", in[2]))
+ return ILLEGAL_MODE;
+ return (in[0] == 'r' ? S_IRUSR | S_IRGRP | S_IROTH : 0)
+ | (in[1] == 'w' ? S_IWUSR | S_IWGRP | S_IWOTH : 0)
+ | (in[2] == 'x' ? S_IXUSR | S_IXGRP | S_IXOTH : 0);
+}
+
+BOOL
+getaclentry (action_t action, char *c, aclent_t *ace)
+{
+ char *c2;
+
+ ace->a_type = 0;
+ ace->a_id = 0;
+ ace->a_perm = 0;
+
+ if (!strncmp (c, "default:", 8)
+ || !strncmp (c, "d:", 2))
+ {
+ ace->a_type = ACL_DEFAULT;
+ c = strchr (c, ':') + 1;
+ }
+ if (!strncmp (c, "user:", 5)
+ || !strncmp (c, "u:", 2))
+ {
+ ace->a_type |= USER_OBJ;
+ c = strchr (c, ':') + 1;
+ }
+ else if (!strncmp (c, "group:", 6)
+ || !strncmp (c, "g:", 2))
+ {
+ ace->a_type |= GROUP_OBJ;
+ c = strchr (c, ':') + 1;
+ }
+ else if (!strncmp (c, "mask:", 5)
+ || !strncmp (c, "m:", 2))
+ {
+ if (!(ace->a_type & ACL_DEFAULT))
+ return FALSE;
+ ace->a_type |= CLASS_OBJ;
+ c = strchr (c, ':') + 1;
+ }
+ else if (!strncmp (c, "other:", 6)
+ || !strncmp (c, "o:", 2))
+ {
+ if (!(ace->a_type & ACL_DEFAULT))
+ return FALSE;
+ ace->a_type |= OTHER_OBJ;
+ c = strchr (c, ':') + 1;
+ }
+ else
+ return FALSE;
+ if (ace->a_type & (USER_OBJ | GROUP_OBJ))
+ {
+ if (c2 = strchr (c, ':'))
+ {
+ if (action == Delete)
+ return FALSE;
+ *c2 = '\0';
+ }
+ else if (action != Delete)
+ return FALSE;
+ if (c2 == c)
+ {
+ if (action == Delete)
+ return FALSE;
+ }
+ else if (isdigit (*c))
+ {
+ char *c3;
+
+ ace->a_id = strtol (c, &c3, 10);
+ if (*c3)
+ return FALSE;
+ }
+ else if (ace->a_type & USER_OBJ)
+ {
+ struct passwd *pw = getpwnam (c);
+ if (!pw)
+ return FALSE;
+ ace->a_id = pw->pw_uid;
+ }
+ else
+ {
+ struct group *gr = getgrnam (c);
+ if (!gr)
+ return FALSE;
+ ace->a_id = gr->gr_gid;
+ }
+ if (ace->a_type & USER_OBJ)
+ {
+ ace->a_type &= ~USER_OBJ;
+ ace->a_type |= USER;
+ }
+ else
+ {
+ ace->a_type &= ~GROUP_OBJ;
+ ace->a_type |= GROUP;
+ }
+ if (c2)
+ c = c2 + 1;
+ }
+ if (action == Delete)
+ {
+ if ((ace->a_type & (CLASS_OBJ | OTHER_OBJ))
+ && *c)
+ return FALSE;
+ ace->a_perm = ILLEGAL_MODE;
+ return TRUE;
+ }
+ if ((ace->a_perm = getperm (c)) == ILLEGAL_MODE)
+ return FALSE;
+ return TRUE;
+}
+
+BOOL
+getaclentries (action_t action, char *buf, aclent_t *acls, int *idx)
+{
+ char *c;
+
+ if (action == SetFromFile)
+ {
+ FILE *fp;
+ char fbuf[256];
+
+ if (! (fp = fopen (buf, "r")))
+ return FALSE;
+ while (fgets (fbuf, 256, fp))
+ {
+ if (!getaclentry (action, fbuf, acls + (*idx)++))
+ {
+ fclose (fp);
+ return FALSE;
+ }
+ }
+ fclose (fp);
+ }
+ else
+ for (c = strtok (buf, ","); c; c = strtok (NULL, ","))
+ if (!getaclentry (action, c, acls + (*idx)++))
+ return FALSE;
+ return TRUE;
+}
+
+int
+searchace (aclent_t *aclp, int nentries, int type, int id)
+{
+ int i;
+
+ for (i = 0; i < nentries; ++i)
+ if ((aclp[i].a_type == type && (id < 0 || aclp[i].a_id == id))
+ || !aclp[i].a_type)
+ return i;
+ return -1;
+}
+
+int
+modacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt)
+{
+ int t, s, i;
+
+ for (s = 0; s < scnt; ++s)
+ {
+ t = searchace (tgt, MAX_ACL_ENTRIES, src[s].a_type,
+ (src[s].a_type & (USER | GROUP)) ? src[s].a_id : -1);
+ if (t < 0)
+ return -1;
+ if (src[s].a_perm == ILLEGAL_MODE)
+ {
+ if (t < tcnt)
+ {
+ for (i = t + 1; i < tcnt; ++i)
+ tgt[i - 1] = tgt[i];
+ --tcnt;
+ }
+ }
+ else
+ {
+ tgt[t] = src[s];
+ if (t >= tcnt)
+ ++tcnt;
+ }
+ }
+ return tcnt;
+}
+
+void
+setfacl (action_t action, char *path, aclent_t *acls, int cnt)
+{
+ aclent_t lacl[MAX_ACL_ENTRIES];
+ int lcnt;
+
+ memset (lacl, 0, sizeof lacl);
+ if (action == Set)
+ {
+ if (acl (path, SETACL, cnt, acls))
+ perror (myname);
+ return;
+ }
+ if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0
+ || (lcnt = modacl (lacl, lcnt, acls, cnt)) < 0
+ || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0)
+ perror (myname);
+}
+
+int
+main (int argc, char **argv)
+{
+ extern char *optarg;
+ extern int optind;
+ int c;
+ action_t action = NoAction;
+ int ropt = 0;
+ aclent_t acls[MAX_ACL_ENTRIES];
+ int aclidx = 0;
+
+ myname = argv[0];
+ memset (acls, 0, sizeof acls);
+ while ((c = getopt (argc, argv, "d:f:m:rs:")) != EOF)
+ switch (c)
+ {
+ case 'd':
+ if (action == NoAction)
+ action = Delete;
+ else if (action == Modify)
+ action = ModNDel;
+ else
+ return usage ();
+ if (! getaclentries (Delete, optarg, acls, &aclidx))
+ {
+ fprintf (stderr, "%s: illegal acl entries\n", myname);
+ return 2;
+ }
+ break;
+ case 'f':
+ if (action == NoAction)
+ action = Set;
+ else
+ return usage ();
+ if (! getaclentries (SetFromFile, optarg, acls, &aclidx))
+ {
+ fprintf (stderr, "%s: illegal acl entries\n", myname);
+ return 2;
+ }
+ break;
+ case 'm':
+ if (action == NoAction)
+ action = Modify;
+ else if (action == Delete)
+ action = ModNDel;
+ else
+ return usage ();
+ if (! getaclentries (Modify, optarg, acls, &aclidx))
+ {
+ fprintf (stderr, "%s: illegal acl entries\n", myname);
+ return 2;
+ }
+ break;
+ case 'r':
+ if (!ropt)
+ ropt = 1;
+ else
+ return usage ();
+ break;
+ case 's':
+ if (action == NoAction)
+ action = Set;
+ else
+ return usage ();
+ break;
+ if (! getaclentries (Set, optarg, acls, &aclidx))
+ {
+ fprintf (stderr, "%s: illegal acl entries\n", myname);
+ return 2;
+ }
+ default:
+ return usage ();
+ }
+ if (action == NoAction)
+ return usage ();
+ if (optind > argc - 1)
+ return usage ();
+ if (action == Set)
+ switch (aclcheck (acls, aclidx, NULL))
+ {
+ case GRP_ERROR:
+ fprintf (stderr, "%s: more than one group entry.\n", myname);
+ return 2;
+ case USER_ERROR:
+ fprintf (stderr, "%s: more than one user entry.\n", myname);
+ return 2;
+ case CLASS_ERROR:
+ fprintf (stderr, "%s: more than one mask entry.\n", myname);
+ return 2;
+ case OTHER_ERROR:
+ fprintf (stderr, "%s: more than one other entry.\n", myname);
+ return 2;
+ case DUPLICATE_ERROR:
+ fprintf (stderr, "%s: duplicate additional user or group.\n", myname);
+ return 2;
+ case ENTRY_ERROR:
+ fprintf (stderr, "%s: invalid entry type.\n", myname);
+ return 2;
+ case MISS_ERROR:
+ fprintf (stderr, "%s: missing entries.\n", myname);
+ return 2;
+ case MEM_ERROR:
+ fprintf (stderr, "%s: out of memory.\n", myname);
+ return 2;
+ default:
+ break;
+ }
+ for (c = optind; c < argc; ++c)
+ setfacl (action, argv[c], acls, aclidx);
+ return 0;
+}
+
diff --git a/winsup/utils/strace.cc b/winsup/utils/strace.cc
new file mode 100644
index 0000000..e8d22f6
--- /dev/null
+++ b/winsup/utils/strace.cc
@@ -0,0 +1,481 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <signal.h>
+#include "sys/strace.h"
+
+static const char *pgm;
+static int forkdebug = 0;
+static int texterror = 0;
+
+static BOOL close_handle (HANDLE h, DWORD ok);
+
+#define CloseHandle(h) close_handle(h, 0)
+
+struct child_list
+ {
+ DWORD id;
+ HANDLE hproc;
+ struct child_list *next;
+ };
+
+child_list children = {0};
+
+static void
+warn (int geterrno, const char *fmt, ...)
+{
+ va_list args;
+ char buf[4096];
+
+ va_start (args, fmt);
+ sprintf (buf, "%s: ", pgm);
+ vsprintf (strchr (buf, '\0'), fmt, args);
+ if (geterrno)
+ perror (buf);
+ else
+ {
+ fputs (buf, stderr);
+ fputs ("\n", stderr);
+ }
+}
+
+static void __attribute__ ((noreturn))
+error (int geterrno, const char *fmt, ...)
+{
+ va_list args;
+ char buf[4096];
+
+ va_start (args, fmt);
+ sprintf (buf, "%s: ", pgm);
+ vsprintf (strchr (buf, '\0'), fmt, args);
+ if (geterrno)
+ perror (buf);
+ else
+ {
+ fputs (buf, stderr);
+ fputs ("\n", stderr);
+ }
+ ExitProcess (1);
+}
+
+DWORD lastid = 0;
+HANDLE lasth;
+
+#define PROCFLAGS \
+ PROCESS_ALL_ACCESS /*(PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_VM_WRITE)*/
+static void
+add_child (DWORD id, HANDLE hproc)
+{
+ child_list *c = children.next;
+ children.next = new (child_list);
+ children.next->next = c;
+ lastid = children.next->id = id;
+ HANDLE me = GetCurrentProcess ();
+ if (!DuplicateHandle (me, hproc, me, &children.next->hproc, PROCFLAGS,
+ FALSE, DUPLICATE_CLOSE_SOURCE))
+ error (0, "couldn't duplicate %p,%p", me, hproc);
+ lasth = children.next->hproc;
+}
+
+static HANDLE
+get_child_handle (DWORD id)
+{
+ child_list *c;
+ for (c = &children; (c = c->next) != NULL; )
+ if (c->id == id)
+ return c->hproc;
+
+ error (0, "no process id %d found", id);
+}
+
+static void
+remove_child (DWORD id)
+{
+ child_list *c;
+ if (id == lastid)
+ lastid = 0;
+ for (c = &children; c->next != NULL; c = c->next)
+ if (c->next->id == id)
+ {
+ child_list *c1 = c->next;
+ close_handle (c1->hproc, id);
+ c->next = c1->next;
+ delete c1;
+ return;
+ }
+
+ error (0, "no process id %d found", id);
+}
+
+#define LINE_BUF_CHUNK 128
+
+class linebuf
+{
+ size_t alloc;
+public:
+ size_t ix;
+ char *buf;
+ linebuf ()
+ {
+ ix = 0;
+ alloc = 0;
+ buf = NULL;
+ }
+ ~linebuf () {if (buf) free (buf);}
+ void add (const char *what, int len);
+ void add (const char *what) {add (what, strlen (what));}
+ void prepend (const char *what, int len);
+};
+
+void
+linebuf::add (const char *what, int len)
+{
+ size_t newix;
+ if ((newix = ix + len) >= alloc)
+ {
+ alloc += LINE_BUF_CHUNK + len;
+ buf = (char *) realloc (buf, alloc + 1);
+ }
+ memcpy (buf + ix, what, len);
+ ix = newix;
+ buf[ix] = '\0';
+}
+
+void
+linebuf::prepend (const char *what, int len)
+{
+ int buflen;
+ size_t newix;
+ if ((newix = ix + len) >= alloc)
+ {
+ alloc += LINE_BUF_CHUNK + len;
+ buf = (char *) realloc (buf, alloc + 1);
+ buf[ix] = '\0';
+ }
+ if ((buflen = strlen (buf)))
+ memmove (buf + len, buf, buflen + 1);
+ else
+ buf[newix] = '\0';
+ memcpy (buf, what, len);
+ ix = newix;
+}
+
+static void
+make_command_line (linebuf& one_line, char **argv)
+{
+ for (; *argv; argv++)
+ {
+ char *p = NULL;
+ const char *a = *argv;
+
+ int len = strlen (a);
+ if (len != 0 && !(p = strpbrk (a, " \t\n\r\"")))
+ one_line.add (a, len);
+ else
+ {
+ one_line.add ("\"", 1);
+ for (; p; a = p, p = strchr (p, '"'))
+ {
+ one_line.add (a, ++p - a);
+ if (p[-1] == '"')
+ one_line.add ("\"", 1);
+ }
+ if (*a)
+ one_line.add (a);
+ one_line.add ("\"", 1);
+ }
+ one_line.add (" ", 1);
+ }
+
+ if (one_line.ix)
+ one_line.buf[one_line.ix - 1] = '\0';
+ else
+ one_line.add ("", 1);
+}
+
+static DWORD child_pid;
+
+static BOOL WINAPI
+ctrl_c (DWORD type)
+{
+ static int tic = 1;
+ if ((tic ^= 1) && !GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0))
+ error (0, "couldn't send CTRL-C to child, win32 error %d\n",
+ GetLastError ());
+ return TRUE;
+}
+
+static void
+create_child (char **argv)
+{
+ linebuf one_line;
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ BOOL ret;
+ DWORD flags;
+
+ if (!*argv)
+ error (0, "no program argument specified");
+
+ memset (&si, 0, sizeof (si));
+ si.cb = sizeof (si);
+
+ /* cygwin32_conv_to_win32_path (exec_file, real_path);*/
+
+ flags = forkdebug ? 0 : DEBUG_ONLY_THIS_PROCESS;
+ flags |= /*CREATE_NEW_PROCESS_GROUP | */CREATE_DEFAULT_ERROR_MODE | DEBUG_PROCESS;
+
+ make_command_line (one_line, argv);
+
+ SetConsoleCtrlHandler (NULL, 0);
+ ret = CreateProcess (0,
+ one_line.buf,/* command line */
+ NULL, /* Security */
+ NULL, /* thread */
+ TRUE, /* inherit handles */
+ flags, /* start flags */
+ NULL,
+ NULL, /* current directory */
+ &si,
+ &pi);
+ if (!ret)
+ error (0, "error creating process %s, (error %d)", *argv, GetLastError());
+
+ CloseHandle (pi.hThread);
+ CloseHandle (pi.hProcess);
+ child_pid = pi.dwProcessId;
+ SetConsoleCtrlHandler (ctrl_c, 1);
+}
+
+static int
+output_winerror (FILE *ofile, char *s)
+{
+ char *winerr = strstr (s, "Win32 error ");
+ if (!winerr)
+ return 0;
+
+ DWORD errnum = atoi (winerr + sizeof ("Win32 error ") - 1);
+ if (!errnum)
+ return 0;
+
+ /*
+ * NOTE: Currently there is no policy for how long the
+ * the buffers are, and looks like 256 is a smallest one
+ * (dlfcn.cc). Other than error 1395 (length 213) and
+ * error 1015 (length 249), the rest are all under 188
+ * characters, and so I'll use 189 as the buffer length.
+ * For those longer error messages, FormatMessage will
+ * return FALSE, and we'll get the old behaviour such as
+ * ``Win32 error 1395'' etc.
+ */
+ char buf[4096];
+ if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ errnum,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) buf,
+ sizeof (buf),
+ NULL))
+ return 0;
+
+ /* Get rid the trailing CR/NL pair. */
+ char *p = strchr (buf, '\0');
+ p[-2] = '\n';
+ p[-1] = '\0';
+
+ *winerr = '\0';
+ fputs (s, ofile);
+ fputs (buf, ofile);
+ return 1;
+}
+
+static void __stdcall
+handle_output_debug_string (DWORD id, LPVOID p, unsigned mask, FILE *ofile)
+{
+ int len;
+ int special;
+ char alen[3 + 8 + 1];
+ DWORD nbytes;
+ HANDLE hchild = get_child_handle (id);
+ #define INTROLEN (sizeof (alen) - 1)
+
+ if (id == lastid && hchild != lasth)
+ warn (0, "%p != %p", hchild, lasth);
+
+ alen[INTROLEN] = '\0';
+ if (!ReadProcessMemory (hchild, p, alen, INTROLEN, &nbytes))
+#ifndef DEBUGGING
+ return;
+#else
+ error (0, "couldn't get message length from subprocess %d<%p>, windows error %d",
+ id, hchild, GetLastError ());
+#endif
+
+ if (strncmp (alen, "cYg", 3))
+ return;
+ len = (int) strtoul (alen + 3, NULL, 16);
+ if (!len)
+ return;
+
+ if (len > 0)
+ special = 0;
+ else
+ {
+ special = len;
+ if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
+ len = 17;
+ }
+
+ char *buf = (char *) alloca (len + 1);
+
+ if (!ReadProcessMemory (hchild, ((char *) p) + INTROLEN, buf, len, &nbytes))
+ error (0, "couldn't get message from subprocess, windows error %d",
+ GetLastError ());
+
+ buf[len] = '\0';
+ char *s = strtok (buf, " ");
+
+ unsigned n = strtoul (s, NULL, 16);
+
+ s = strchr (s, '\0') + 1;
+
+ if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
+ {
+ DWORD new_flag = 1;
+ if (!WriteProcessMemory (hchild, (LPVOID) n, &new_flag,
+ sizeof (new_flag), &nbytes))
+ error (0, "couldn't write strace flag to subprocess, windows error %d",
+ GetLastError ());
+ return;
+ }
+
+ if (mask & n)
+ /* got it */;
+ else if (!(mask & _STRACE_ALL) || (n & _STRACE_NOTALL))
+ return; /* This should not be included in "all" output */
+
+ if (!texterror || !output_winerror (ofile, s))
+ fputs (s, ofile);
+ fflush (ofile);
+}
+
+static void
+proc_child (unsigned mask, FILE *ofile)
+{
+ DEBUG_EVENT ev;
+ int processes = 0;
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
+ while (1)
+ {
+ BOOL debug_event = WaitForDebugEvent (&ev, 1000);
+ if (!debug_event)
+ continue;
+
+ switch (ev.dwDebugEventCode)
+ {
+ case CREATE_PROCESS_DEBUG_EVENT:
+ if (ev.u.CreateProcessInfo.hFile)
+ CloseHandle (ev.u.CreateProcessInfo.hFile);
+ if (ev.u.CreateProcessInfo.hThread)
+ CloseHandle (ev.u.CreateProcessInfo.hThread);
+ add_child (ev.dwProcessId, ev.u.CreateProcessInfo.hProcess);
+ processes++;
+ break;
+
+ case CREATE_THREAD_DEBUG_EVENT:
+ if (ev.u.CreateThread.hThread)
+ CloseHandle (ev.u.CreateThread.hThread);
+ break;
+
+ case LOAD_DLL_DEBUG_EVENT:
+ if (ev.u.LoadDll.hFile)
+ CloseHandle (ev.u.LoadDll.hFile);
+ break;
+
+ case OUTPUT_DEBUG_STRING_EVENT:
+ handle_output_debug_string (ev.dwProcessId,
+ ev.u.DebugString.lpDebugStringData,
+ mask, ofile);
+ break;
+
+ case EXIT_PROCESS_DEBUG_EVENT:
+ remove_child (ev.dwProcessId);
+ break;
+ }
+ if (!ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId,
+ DBG_CONTINUE))
+ error (0, "couldn't continue debug event, windows error %d",
+ GetLastError ());
+ if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT && --processes == 0)
+ break;
+ }
+}
+
+static void
+dostrace (unsigned mask, FILE *ofile, char **argv)
+{
+ create_child (argv);
+ proc_child (mask, ofile);
+
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ unsigned mask = 0;
+ FILE *ofile = NULL;
+ int opt;
+
+ if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/')))
+ pgm = *argv;
+ else
+ pgm++;
+
+ while ((opt = getopt (argc, argv, "m:o:ft")) != EOF)
+ switch (opt)
+ {
+ case 'f':
+ forkdebug ^= 1;
+ break;
+ case 'm':
+ mask = strtoul (optarg, NULL, 16);
+ break;
+ case 'o':
+ if ((ofile = fopen (optarg, "w")) == NULL)
+ error (1, "can't open %s", optarg);
+#ifdef F_SETFD
+ (void) fcntl (fileno (ofile), F_SETFD, 0);
+#endif
+ break;
+ case 't':
+ texterror ^= 1;
+ break;
+ }
+
+ if (!mask)
+ mask = 1;
+
+ if (!ofile)
+ ofile = stdout;
+
+ dostrace (mask, ofile, argv + optind);
+}
+
+#undef CloseHandle
+
+static BOOL
+close_handle (HANDLE h, DWORD ok)
+{
+ child_list *c;
+ for (c = &children; (c = c->next) != NULL; )
+ if (c->hproc == h && c->id != ok)
+ error (0, "Closing child handle %p", h);
+ return CloseHandle (h);
+}
diff --git a/winsup/utils/umount.cc b/winsup/utils/umount.cc
new file mode 100644
index 0000000..c37e57a
--- /dev/null
+++ b/winsup/utils/umount.cc
@@ -0,0 +1,173 @@
+/* umount.cc
+
+ Copyright 1996, 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 <string.h>
+#include <sys/mount.h>
+#include <mntent.h>
+
+static void remove_all_mounts ();
+static void remove_all_automounts ();
+static void remove_all_user_mounts ();
+static void remove_all_system_mounts ();
+
+static const char *progname;
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage %s [-s] <posixpath>\n", progname);
+ fprintf (stderr, "-s = remove mount point from system-wide registry location\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "--remove-all-mounts = remove all mounts\n");
+ fprintf (stderr, "--remove-auto-mounts = remove all automatically mounted mounts\n");
+ fprintf (stderr, "--remove-user-mounts = remove all mounts in the current user mount registry area, including auto mounts\n");
+ fprintf (stderr, "--remove-system-mounts = Remove all mounts in the system-wide mount registry area\n");
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ int flags = 0;
+ progname = argv[0];
+
+ if (argc == 1)
+ usage ();
+
+ for (i = 1; i < argc; ++i)
+ {
+ if (argv[i][0] != '-')
+ break;
+
+ if (strcmp (argv[i], "-s") == 0)
+ {
+ flags |= MOUNT_SYSTEM;
+ }
+ else if (strcmp (argv[i], "--remove-all-mounts") == 0)
+ {
+ remove_all_mounts ();
+ exit (0);
+ }
+ else if (strcmp (argv[i], "--remove-user-mounts") == 0)
+ {
+ remove_all_user_mounts ();
+ exit (0);
+ }
+ else if (strcmp (argv[i], "--remove-system-mounts") == 0)
+ {
+ remove_all_system_mounts ();
+ exit (0);
+ }
+ else if (strcmp (argv[i], "--remove-auto-mounts") == 0)
+ {
+ remove_all_automounts ();
+ exit (0);
+ }
+ else
+ usage ();
+ }
+
+ if ((i + 1) != argc)
+ usage ();
+
+ if (cygwin_umount (argv[i], flags) != 0)
+ {
+ perror ("umount");
+ exit (1);
+ }
+
+ return 0;
+}
+
+/* remove_all_mounts: Unmount all mounts. */
+static void
+remove_all_mounts ()
+{
+ remove_all_user_mounts ();
+ remove_all_system_mounts ();
+}
+
+/* remove_all_automounts: Unmount all automounts. */
+static void
+remove_all_automounts ()
+{
+ FILE *m = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+
+ while ((p = getmntent (m)) != NULL)
+ {
+ /* Remove the mount if it's an automount. */
+ if (strcmp (p->mnt_type, "user,auto") == 0)
+ {
+ cygwin_umount (p->mnt_dir, 0);
+ /* We've modified the table so we need to start over. */
+ endmntent (m);
+ m = setmntent ("/-not-used-", "r");
+ }
+ else if (strcmp (p->mnt_type, "system,auto") == 0)
+ {
+ cygwin_umount (p->mnt_dir, MOUNT_SYSTEM);
+ /* We've modified the table so we need to start over. */
+ endmntent (m);
+ m = setmntent ("/-not-used-", "r");
+ }
+ }
+
+ endmntent (m);
+}
+
+/* remove_all_user_mounts: Unmount all user mounts. */
+static void
+remove_all_user_mounts ()
+{
+ FILE *m = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+ int err;
+
+ while ((p = getmntent (m)) != NULL)
+ {
+ /* Remove the mount if it's a user mount. */
+ if (strncmp (p->mnt_type, "user", 4) == 0)
+ {
+ err = cygwin_umount (p->mnt_dir, 0);
+
+ /* We've modified the table so we need to start over. */
+ endmntent (m);
+ m = setmntent ("/-not-used-", "r");
+ }
+ }
+
+ endmntent (m);
+}
+
+/* remove_all_system_mounts: Unmount all system mounts. */
+static void
+remove_all_system_mounts ()
+{
+ FILE *m = setmntent ("/-not-used-", "r");
+ struct mntent *p;
+
+ while ((p = getmntent (m)) != NULL)
+ {
+ /* Remove the mount if it's a system mount. */
+ if (strncmp (p->mnt_type, "system", 6) == 0)
+ {
+ cygwin_umount (p->mnt_dir, MOUNT_SYSTEM);
+
+ /* We've modified the table so we need to start over. */
+ endmntent (m);
+ m = setmntent ("/-not-used-", "r");
+ }
+ }
+
+ endmntent (m);
+}
diff --git a/winsup/utils/utils.sgml b/winsup/utils/utils.sgml
new file mode 100644
index 0000000..e045e6a
--- /dev/null
+++ b/winsup/utils/utils.sgml
@@ -0,0 +1,657 @@
+<sect1 id="using-utils"><title>Cygwin Utilities</title>
+
+<para>Cygwin comes with a number of command-line utilities that are
+used to manage the UNIX emulation portion of the Cygwin environment.
+While many of these reflect their UNIX counterparts, each was written
+specifically for Cygwin.</para>
+
+<sect2 id="cygcheck"><title>cygcheck</title>
+
+<screen>
+Usage: cygcheck [-s] [-v] [-r] [-h] [program ...]
+ -s = system information
+ -v = verbose output (indented) (for -s or programs)
+ -r = registry search (requires -s)
+ -h = give help about the info
+You must at least give either -s or a program name
+</screen>
+
+<para>The <command>cygcheck</command> program is a diagnostic utility
+that examines your system and reports the information that is
+significant to the proper operation of Cygwin programs. It can give
+information about a specific program (or program) you are trying to
+run, general system information, or both. If you list one or more
+programs on the command line, it will diagnose the runtime environment
+of that program or programs. If you specify the <literal>-s</literal>
+option, it will give general system information. If you specify
+<literal>-s</literal> and list one or more programs on the command line,
+it reports on both.</para>
+
+<para>The <command>cygcheck</command> program should be used to send
+information about your system to Cygnus for troubleshooting (if your
+support representative requests it). When asked to run this command,
+include all the options plus any commands you are having trouble with,
+and save the output so that you can mail it to Cygnus, like
+this:</para>
+
+<screen>
+<prompt>C:\Cygnus&gt;</prompt> <userinput>cygcheck -s -v -r -h &gt; tocygnus.txt</userinput>
+</screen>
+
+<para>The <literal>-v</literal> option causes the output to be more
+verbose. What this means is that additional information will be
+reported which is usually not interesting, such as the internal
+version numbers of DLLs, additional information about recursive DLL
+usage, and if a file in one directory in the PATH also occurs in other
+directories on the PATH. </para>
+
+<para>The <literal>-r</literal> option causes
+<command>cygcheck</command> to search your registry for information
+that is relevent to Cygnus programs. These registry entries are the
+ones that have "Cygnus" in the name. If you are paranoid about
+privacy, you may remove information from this report, but please keep
+in mind that doing so makes it harder for Cygnus to diagnose your
+problems.</para>
+
+<para>The <literal>-h</literal> option prints additional helpful
+messages in the report, at the beginning of each section. It also
+adds table column headings. While this is useful information, it also
+adds some to the size of the report, so if you want a compact report
+or if you know what everything is already, just leave this out.</para>
+
+</sect2>
+
+<sect2 id="cygpath"><title>cygpath</title>
+
+<screen>
+Usage: cygpath [-p|--path] (-u|--unix)|(-w|--windows) filename
+ cygpath [-v|--version]
+ -u|--unix print UNIX form of filename
+ -w|--windows print Windows form of filename
+ -p|--path filename argument is a path
+ -v|--version print program version
+</screen>
+
+<para>The <command>cygpath</command> program is a utility that
+converts Windows native filenames to Cygwin POSIX-style pathnames and
+back. It can be used when a Cygwin program needs to pass a file name
+to a native Windows program, or expects to get a file name from a
+native Windows program. You may use the long or short option names
+interchangeably, even though only the short ones are described
+here.</para>
+
+<para>The <literal>-u</literal> and <literal>-w</literal> options
+indicate whether you want a conversion from Windows to UNIX (POSIX)
+format (<literal>-u</literal>) or a conversion from UNIX (POSIX) to
+Windows format (<literal>-w</literal>). You must give exactly
+one of these. To give neither or both is an error.</para>
+
+<para>The <literal>-p</literal> option means that you want to convert
+a path-style string rather than a single filename. For example, the
+PATH environment variable is semicolon-delimited in Windows, but
+colon-delimited in UNIX. By giving <literal>-p</literal> you are
+instructing <command>cygpath</command> to convert between these
+formats.</para>
+
+<example><title>Example cygpath usage</title>
+<screen>
+#!/bin/sh
+for i in `echo *.exe | sed 's/\.exe/cc/'`
+do
+ notepad `cygpath -w $i`
+done
+</screen>
+</example>
+
+</sect2>
+
+<sect2 id="kill"><title>kill</title>
+
+<screen>
+Usage: kill [-sigN] pid1 [pid2 ...]
+</screen>
+
+<para>The <command>kill</command> program allows you to send arbitrary
+signals to other Cygwin programs. The usual purpose is to end a
+running program from some other window when ^C won't work, but you can
+also send program-specified signals such as SIGUSR1 to trigger actions
+within the program, like enabling debugging or re-opening log files.
+Each program defines the signals they understand.</para>
+
+<para>Note that the "pid" values are the Cygwin pids, not the Windows
+pids. To get a list of running programs and their Cygwin pids, use
+the Cygwin <command>ps</command> program.</para>
+
+<para>To send a specific signal, use the
+<literal>-signN</literal> option, either
+with a signal number or a signal name (minus the "SIG" part), like
+these examples:</para>
+
+<example><title>Specifying signals with the kill command</title>
+<screen>
+<prompt>$</prompt> <userinput>kill 123</userinput>
+<prompt>$</prompt> <userinput>kill -1 123</userinput>
+<prompt>$</prompt> <userinput>kill -HUP 123</userinput>
+</screen>
+</example>
+
+<para>Here is a list of available signals, their numbers, and some
+commentary on them, from the file
+<literal>&lt;sys/signal.h&gt;</literal>, which should be considered
+the official source of this information.</para>
+
+<screen>
+SIGHUP 1 hangup
+SIGINT 2 interrupt
+SIGQUIT 3 quit
+SIGILL 4 illegal instruction (not reset when caught)
+SIGTRAP 5 trace trap (not reset when caught)
+SIGABRT 6 used by abort
+SIGEMT 7 EMT instruction
+SIGFPE 8 floating point exception
+SIGKILL 9 kill (cannot be caught or ignored)
+SIGBUS 10 bus error
+SIGSEGV 11 segmentation violation
+SIGSYS 12 bad argument to system call
+SIGPIPE 13 write on a pipe with no one to read it
+SIGALRM 14 alarm clock
+SIGTERM 15 software termination signal from kill
+SIGURG 16 urgent condition on IO channel
+SIGSTOP 17 sendable stop signal not from tty
+SIGTSTP 18 stop signal from tty
+SIGCONT 19 continue a stopped process
+SIGCHLD 20 to parent on child stop or exit
+SIGCLD 20 System V name for SIGCHLD
+SIGTTIN 21 to readers pgrp upon background tty read
+SIGTTOU 22 like TTIN for output if (tp-&gt;t_local&amp;LTOSTOP)
+SIGIO 23 input/output possible signal
+SIGPOLL 23 System V name for SIGIO
+SIGXCPU 24 exceeded CPU time limit
+SIGXFSZ 25 exceeded file size limit
+SIGVTALRM 26 virtual time alarm
+SIGPROF 27 profiling time alarm
+SIGWINCH 28 window changed
+SIGLOST 29 resource lost (eg, record-lock lost)
+SIGUSR1 30 user defined signal 1
+SIGUSR2 31 user defined signal 2
+</screen>
+
+</sect2>
+
+<sect2 id="mkgroup"><title>mkgroup</title>
+
+<screen>
+usage: mkgroup &lt;options&gt; [domain]
+This program prints group information to stdout
+Options:\n");
+ -l,--local print pseudo group information if there is
+ no domain
+ -d,--domain print global group information from the domain
+ specified (or from the current domain if there is
+ no domain specified)
+ -?,--help print this message
+</screen>
+
+<para>The <command>mkgroup</command> program can be used to help
+configure your Windows system to be more UNIX-like by creating an
+initial <filename>/etc/group</filename> substitute (some commands need this
+file) from your system information. It only works on NT.
+To initially set up your machine,
+you'd do something like this:</para>
+
+<example><title>Setting up the groups file</title>
+<screen>
+<prompt>$</prompt> <userinput>mkdir /etc</userinput>
+<prompt>$</prompt> <userinput>mkgroup -l &gt; /etc/group</userinput>
+</screen>
+</example>
+
+<para>Note that this information is static. If you change the group
+information in your system, you'll need to regenerate the group file
+for it to have the new information.</para>
+
+<para>The <literal>-d</literal> and <literal>-l</literal> options
+allow you to specify where the information comes from, either the
+local machine or the default (or given) domain.</para>
+
+</sect2>
+
+<sect2 id="mkpasswd"><title>mkpasswd</title>
+
+<screen>
+Usage: mkpasswd [options] [domain]
+This program prints a /etc/passwd file to stdout
+Options are
+ -l,--local print local accounts
+ -d,--domain print domain accounts (from current domain
+ if no domain specified
+ -g,--local-groups print local group information too
+ -?,--help displays this message
+This program does only work on Windows NT
+</screen>
+
+<para>The <command>mkpasswd</command> program can be used to help
+configure your Windows system to be more UNIX-like by creating an
+initial <filename>/etc/passwd</filename> substitute (some commands
+need this file) from your system information. It only works on NT.
+To initially set up your machine, you'd do something like this:</para>
+
+<example><title>Setting up the passwd file</title>
+<screen>
+<prompt>$</prompt> <userinput>mkdir /etc</userinput>
+<prompt>$</prompt> <userinput>mkpasswd -l &gt; /etc/passwd</userinput>
+</screen>
+</example>
+
+<para>Note that this information is static. If you change the user
+information in your system, you'll need to regenerate the passwd file
+for it to have the new information.</para>
+
+<para>The <literal>-d</literal> and <literal>-l</literal> options
+allow you to specify where the information comes from, either the
+local machine or the default (or given) domain.</para>
+
+</sect2>
+
+<sect2 id="passwd"><title>passwd</title>
+
+<screen>
+Usage passwd [name]
+ passwd [-x max] [-n min] [-i inact] [-L len]
+ passwd {-l|-u|-S} name
+ -x max set max age of passwords
+ -n min set min age of passwords
+ -i inact disables account after inact days of expiry
+ -L len set min password length
+ -l lock an account
+ -u unlock an account
+ -S show account information
+</screen>
+
+<para> <command>passwd</command> changes passwords for user accounts.
+A normal user may only change the password for their own account,
+the administrators may change the password for any account.
+<command>passwd</command> also changes account information, such as
+password expiry dates and intervals.</para>
+
+<para>Password changes: The user is first prompted for their old
+password, if one is present. This password is then encrypted and
+compared against the stored password. The user has only one chance to
+enter the correct password. The administrators are permitted to
+bypass this step so that forgotten passwords may be changed.</para>
+
+<para>The user is then prompted for a replacement password.
+<command>passwd</command> will prompt again and compare the second entry
+against the first. Both entries are require to match in order for the
+password to be changed.</para>
+
+<para>After the password has been entered, password aging information
+is checked to see if the user is permitted to change their password
+at this time. If not, <command>passwd</command> refuses to change the
+password and exits.</para>
+
+<para>Password expiry and length: The password aging information may be
+changed by the administrators with the <literal>-x</literal>,
+<literal>-n</literal> and <literal>-i</literal> options. The
+<literal>-x</literal> option is used to set the maximum number of days
+a password remains valid. After <emphasis>max</emphasis> days, the
+password is required to be changed. The <literal>-n</literal> option is
+used to set the minimum number of days before a password may be changed.
+The user will not be permitted to change the password until
+<emphasis>min</emphasis> days have elapsed. The <literal>-i</literal>
+option is used to disable an account after the password has been expired
+for a number of days. After a user account has had an expired password
+for <emphasis>inact</emphasis> days, the user may no longer sign on to
+the account. Allowed values for the above options are 0 to 999. The
+<literal>-L</literal> option sets the minimum length of allowed passwords
+for users, which doesn't belong to the administrators group, to
+<emphasis>len</emphasis> characters. Allowed values for the minimum
+password length are 0 to 14. In any of the above cases, a value of 0
+means `no restrictions'.</para>
+
+<para>Account maintenance: User accounts may be locked and unlocked with the
+<literal>-l</literal> and <literal>-u</literal> flags. The
+<literal>-l</literal> option disables an account. The <literal>-u</literal>
+option re-enables an account.</para>
+
+<para>The account status may be given with the <literal>-S</literal>
+option. The status information is self explanatory.</para>
+
+<para>Limitations: Users may not be able to change their password on
+some systems.</para>
+
+</sect2>
+
+<sect2 id="mount"><title>mount</title>
+
+<screen>
+Usage mount
+ mount [-bfs] &lt;win32path&gt; &lt;posixpath&gt;
+ mount [-bs] --change-cygdrive-prefix&lt;posixpath&gt;
+ mount --import-old-mounts
+
+ -b = text files are equivalent to binary files (newline = \n)
+ -x = files in the mounted directory are automatically given execute permission.
+ -f = force mount, don't warn about missing mount point directories
+ -s = add mount point to system-wide registry location
+ --change-automount-prefix = change path prefix used for automatic mount points
+ --import-old-mounts = copy old registry mount table mounts into the current mount areas
+
+ When invoked without any arguments, mount displays the current mount table.
+</screen>
+
+<para>The <command>mount</command> program is used to map your drives
+and shares onto Cygwin's simulated POSIX directory tree, much like as is
+done by mount commands on typical UNIX systems. Please see
+<Xref Linkend="mount-table"> for more information on the concepts
+behind the Cygwin POSIX file system and strategies for using
+mounts.</para>
+
+<sect3><title>Using mount</title>
+
+<para>If you just type <command>mount</command> with no parameters, it
+will display the current mount table for you.</para>
+
+<example>
+<title>Displaying the current set of mount points</title>
+<screen>
+<prompt>c:\cygnus\&gt;</prompt> <userinput>mount</userinput>
+Device Directory Type Flags
+D: /d user textmode
+C: / system textmode
+</screen>
+</example>
+
+<para>In this example, the C
+drive is the POSIX root and D drive is mapped to
+<filename>/d</filename>. Note that in this case, the root mount is a
+system-wide mount point that is visible to all users running Cygwin
+programs, whereas the <filename>/d</filename> mount is only visible
+to the current user.</para>
+
+<para>The <command>mount</command> utility is also the mechanism for
+adding new mounts to the mount table. The following example
+demonstrates how to mount the directory
+<filename>C:\cygnus\cygwin-b20\H-i586-cygwin32\bin</filename>
+to <filename>/bin</filename> and the network directory
+<filename>\\pollux\home\joe\data</filename> to <filename>/data</filename>.
+<filename>/bin</filename> is assumed to already exist.</para>
+
+<example>
+<title>Adding mount points</title>
+<screen>
+<prompt>c:\cygnus\&gt;</prompt> <userinput>ls /bin /data</userinput>
+ls: /data: No such file or directory
+<prompt>c:\cygnus\&gt;</prompt> <userinput>mount C:\cygnus\cygwin-b20\H-i586-cygwin32\bin /bin</userinput>
+<prompt>c:\cygnus\&gt;</prompt> <userinput>mount \\pollux\home\joe\data /data</userinput>
+Warning: /data does not exist!
+<prompt>c:\cygnus\&gt;</prompt> <userinput>mount</userinput>
+Device Directory Type Flags
+\\pollux\home\joe\data /data user textmode
+C:\cygnus\cygwin-b20\H-i586-cygwin32\bin /bin user textmode
+D: /d user textmode
+\\.\tape1: /dev/st1 user textmode
+\\.\tape0: /dev/st0 user textmode
+\\.\b: /dev/fd1 user textmode
+\\.\a: /dev/fd0 user textmode
+C: / system textmode
+<prompt>c:\cygnus\&gt;</prompt> <userinput>ls /bin/sh</userinput>
+/bin/sh
+</screen>
+</example>
+
+<para>Note that <command>mount</command> was invoked from the Windows
+command shell in the previous example. In many Unix shells, including
+bash, it is legal and convenient to use the forward "/" in Win32
+pathnames since the "\" is the shell's escape character. </para>
+
+<para>The "-s" flag to <command>mount</command> is used to add a mount
+in the system-wide mount table used by all Cygwin users on the system,
+instead of the user-specific one. System-wide mounts are displayed
+by <command>mount</command> as being of the "system" type, as is the
+case for the <filename>/</filename> partition in the last example.
+Under Windows NT, only those users with Administrator priviledges are
+permitted to modify the system-wide mount table.</para>
+
+<para>Note that a given POSIX path may only exist once in the user
+table and once in the global, system-wide table. Attempts to replace
+the mount will fail with a busy error. The "-f" (force) flag causes
+the old mount to be silently replaced with the new one. It will also
+silence warnings about the non-existence of directories at the Win32
+path location.</para>
+
+<para>The "-b" flag is used to instruct Cygwin to treat binary and
+text files in the same manner by default. Binary mode mounts are
+marked as "binmode" in the Flags column of <command>mount</command>
+output. By default, mounts are in text mode ("textmode" in the Flags
+column).
+
+<para>The "-x" flag is used to instruct Cygwin that the mounted file
+is "executable". If the "-x" flag is used with a directory then
+all files in the directory are executable. Files ending in certain
+extensions (.exe, .com, .bat, .cmd) are assumed to be executable
+by default. Files whose first two characters begin with '#!' are
+also considered to be executable. This option allows other files
+to be marked as executable and avoids the overhead of opening each
+file to check for a '#!'.
+
+</sect3>
+
+<sect3><title>Cygdrive mount points</title>
+
+<para>Whenever Cygwin cannot use any of the existing mounts to convert
+from a particular Win32 path to a POSIX one, Cygwin will, instead,
+convert to a POSIX path using a default mount point:
+<filename>/cygdrive</filename>. For example, if Cygwin accesses
+<filename>Z:\foo</filename> and the Z drive is not currently in the
+mount table, then <filename>Z:\</filename> will be accessible as
+<filename>/cygdrive/Z</filename>. The default prefix of
+<filename>/cygdrive</filename> may be changed via the
+<Xref Linkend="mount"> command.</para>
+
+<para>The <command>mount</command> utility can be used to change this
+default automount prefix through the use of the
+"--change-cygdrive-prefix" flag. In the following example, we will
+set the automount prefix to <filename>/</filename>:</para>
+
+<example>
+<title>Changing the default prefix</title>
+<screen>
+<prompt>c:\cygnus\&gt;</prompt> <userinput>mount --change-cygdrive-prefix /</userinput>
+</screen>
+</example>
+
+<para>Note that you if you set a new prefix in this manner, you can
+specify the "-s" flag to make this the system-wide default prefix. By
+default, the cygdrive-prefix applies only to the current user. In the
+same way, you can specify the "-b" flag such that all new automounted
+filesystems default to binary mode file accesses.</para>
+
+<sect3><title>Limitations</title>
+
+<para>Limitations: there is a hard-coded limit of 30 mount
+points. Also, although you can mount to pathnames that do not start
+with "/", there is no way to make use of such mount points.</para>
+
+<para>Normally the POSIX mount point in Cygwin is an existing empty
+directory, as in standard UNIX. If this is the case, or if there is a
+place-holder for the mount point (such as a file, a symbolic link
+pointing anywhere, or a non-empty directory), you will get the expected
+behavior. Files present in a mount point directory before the mount
+become invisible to Cygwin programs.
+</para>
+
+<para>It is sometimes desirable to mount to a non-existent directory,
+for example to avoid cluttering the root directory with names
+such as
+<filename>a</filename>, <filename>b</filename>, <filename>c</filename>
+pointing to disks.
+Although <command>mount</command> will give you a warning, most
+everything will work properly when you refer to the mount point
+explicitly. Some strange effects can occur however.
+For example if your current working directory is
+<filename>/dir</filename>,
+say, and <filename>/dir/mtpt</filename> is a mount point, then
+<filename>mtpt</filename> will not show up in an <command>ls</command>
+or
+<command>echo *</command> command and <command>find .</command> will
+not
+find <filename>mtpt</filename>.
+</para>
+
+</sect3>
+
+</sect2>
+
+<sect2 id="ps"><title>ps</title>
+
+<screen>
+Usage ps [-aefl] [-u uid]
+ -f show process uids, ppids
+ -l show process uids, ppids, pgids, winpids
+ -u uid list processes owned by uid
+ -a, -e show processes of all users
+</screen>
+
+<para>The <command>ps</command> program gives the status of all the
+Cygwin processes running on the system (ps = "process status"). Due
+to the limitations of simulating a POSIX environment under Windows,
+there is little information to give. The PID column is the process ID
+you need to give to the <command>kill</command> command. The WINPID
+column is the process ID that's displayed by NT's Task Manager
+program.</para>
+
+</sect2>
+
+<sect2 id="umount"><title>umount</title>
+
+<screen>
+Usage umount [-s] &lt;posixpath&gt;
+-s = remove mount point from system-wide registry location
+
+--remove-all-mounts = remove all mounts
+--remove-auto-mounts = remove all automatically mounted mounts
+--remove-user-mounts = remove all mounts in the current user mount registry area, including auto mounts
+--remove-system-mounts = Remove all mounts in the system-wide mount registry area
+</screen>
+
+<para>The <command>umount</command> program removes mounts from the
+mount table. If you specify a POSIX path that corresponds to a
+current mount point, <command>umount</command> will remove it from the
+user-specific registry area. The -s flag may be used to specify
+removing the mount from the system-wide registry area instead
+(Administrator priviledges are required).</para>
+
+<para>The <command>umount</command> utility may also be used to remove
+all mounts of a particular type. With the extended options it is
+possible to remove all mounts, all automatically-mounted mounts, all
+mounts in the current user's registry area, or all mounts in the
+system-wide registry area (with Administrator priviledges).</para>
+
+<para>See <Xref Linkend="mount">) for more information on the mount
+table.</para>
+</sect2>
+
+<sect2 id="strace"><title>strace</title>
+
+<screen>
+Usage strace [-m mask] [-o output-file] [ft] program [args...]
+
+-m mask mask for reporting cygwin events (default 1)
+-o output-file output file to hold strace events (default stderr)
+-f follow forked subprocesses
+-t convert Win32 error messages to text
+-s remove mount point from system-wide registry location
+</screen>
+
+<para>The <command>strace</command> program executes a program, and
+optionally the children of the program, reporting any Cygwin DLL output
+from the program(s) to file. This program is mainly useful for debugging
+the Cygwin DLL itself.
+
+The mask argument is a hexadecimal string signifying which events should be
+reported. The valid bits to set are as follows:
+</para>
+
+<screen>
+ Bit Explanation
+0x00000001 All strace output is collected
+0x00000002 Unusual or weird phenomenon
+0x00000010 System calls
+0x00000020 argv/envp printout at startup
+0x00000040 Information useful for DLL debugging
+0x00000080 Paranoid information
+0x00000100 Termios debbugging
+0x00000200 Select() function debugging
+0x00000400 Window message debugging
+0x00000800 Signal and process handling
+0x00001000 Very minimal strace output
+0x00020000 Malloc calls
+0x00040000 Thread locking calls
+</screen>
+</sect2>
+
+<sect2 id="regtool"><title>regtool</title>
+
+<screen>
+regtool -h - print this message
+regtool [-v] list [key] - list subkeys and values
+regtool [-v] add [key\subkey] - add new subkey
+regtool [-v] remove [key] - remove key
+regtool [-v|-q] check [key] - exit 0 if key exists, 1 if not
+regtool [-i|-s|-e|-m] set [key\value] [data ...] - set value
+ -i=integer -s=string -e=expand-string -m=multi-string
+regtool [-v] unset [key\value] - removes value from key
+regtool [-q] get [key\value] - prints value to stdout
+ -q=quiet, no error msg, just return nonzero exit if key/value missing
+keys are like \prefix\key\key\key\value, where prefix is any of:
+ root HKCR HKEY_CLASSES_ROOT
+ config HKCC HKEY_CURRENT_CONFIG
+ user HKCU HKEY_CURRENT_USER
+ machine HKLM HKEY_LOCAL_MACHINE
+ users HKU HKEY_USERS
+example: \user\software\Microsoft\Clock\iFormat
+</screen>
+
+<para>The <command>regtool</command> program allows shell scripts
+to access and modify the Windows registry. Note that modifying the
+Windows registry is dangerous, and carelessness here can result
+in an unusable system. Be careful.</para>
+
+<para>The <literal>-v</literal> option means "verbose". For most
+commands, this causes additional or lengthier messages to be printed.
+Conversely, the <literal>-q</literal> option supresses error messages,
+so you can use the exit status of the program to detect if a key
+exists or not (for example).</para>
+
+<para>The <literal>list</literal> command lists the subkeys and values
+belonging to the given key. The <literal>add</literal> command adds a
+new key. The <literal>remove</literal> command removes a key. Note
+that you may need to remove everything in the key before you may
+remove it, but don't rely on this stopping you from accidentally
+removing too much. The <literal>check</literal> command checks to see
+if a key exists (the exit code of the program is zero if it does,
+nonzero if it does not).</para>
+
+<para>The <literal>set</literal> command sets a value within a key.
+<literal>-i</literal> means the value is an integer (DWORD).
+<literal>-s</literal> means the value is a string.
+<literal>-e</literal> means it's an expanding string (it contains
+embedded environment variables). <literal>-m</literal> means it's a
+multi-string (list). If you don't specify one of these, it tries to
+guess the type based on the value you give. If it looks like a
+number, it's a number. If it starts with a percent, it's an expanding
+string. If you give multiple values, it's a multi-string. Else, it's
+a regular string.</para>
+
+<para>The <literal>unset</literal> command removes a value from a key.
+The <literal>get</literal> command gets the value of a value of a key,
+and prints it (and nothing else) to stdout. Note: if the value
+doesn't exist, an error message is printed and the program returns a
+non-zero exit code. If you give <literal>-q</literal>, it doesn't
+print the message but does return the non-zero exit code.</para>
+
+</sect2>
+
+</sect1>
+