diff options
Diffstat (limited to 'winsup/utils')
-rw-r--r-- | winsup/utils/ChangeLog | 21 | ||||
-rw-r--r-- | winsup/utils/Makefile.in | 109 | ||||
-rw-r--r-- | winsup/utils/aclocal.m4 | 78 | ||||
-rwxr-xr-x | winsup/utils/configure | 1246 | ||||
-rw-r--r-- | winsup/utils/configure.in | 75 | ||||
-rw-r--r-- | winsup/utils/cygcheck.cc | 922 | ||||
-rw-r--r-- | winsup/utils/cygpath.cc | 154 | ||||
-rw-r--r-- | winsup/utils/getfacl.c | 124 | ||||
-rw-r--r-- | winsup/utils/kill.cc | 85 | ||||
-rw-r--r-- | winsup/utils/mkgroup.c | 410 | ||||
-rw-r--r-- | winsup/utils/mkpasswd.c | 438 | ||||
-rw-r--r-- | winsup/utils/mount.cc | 240 | ||||
-rw-r--r-- | winsup/utils/passwd.c | 352 | ||||
-rw-r--r-- | winsup/utils/ps.cc | 150 | ||||
-rw-r--r-- | winsup/utils/regtool.cc | 524 | ||||
-rw-r--r-- | winsup/utils/setfacl.c | 377 | ||||
-rw-r--r-- | winsup/utils/strace.cc | 481 | ||||
-rw-r--r-- | winsup/utils/umount.cc | 173 | ||||
-rw-r--r-- | winsup/utils/utils.sgml | 657 |
19 files changed, 6616 insertions, 0 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog new file mode 100644 index 000000000..62a442509 --- /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 000000000..11871d17f --- /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 000000000..754f640bb --- /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 000000000..2f3a2d15a --- /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 000000000..a38e00807 --- /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 000000000..59bf00a97 --- /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 000000000..653d41cec --- /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 000000000..9bf7122db --- /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 000000000..611887896 --- /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 000000000..0c322bbc6 --- /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 000000000..649320c50 --- /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 000000000..2c348703a --- /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 000000000..700ea4d43 --- /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 000000000..4767a6ae0 --- /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 000000000..1e79e3a69 --- /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 000000000..87c96aeac --- /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 000000000..e8d22f673 --- /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 000000000..c37e57ad0 --- /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 000000000..e045e6abb --- /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></prompt> <userinput>cygcheck -s -v -r -h > 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><sys/signal.h></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->t_local&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 <options> [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 > /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 > /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] <win32path> <posixpath> + mount [-bs] --change-cygdrive-prefix<posixpath> + 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\></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\></prompt> <userinput>ls /bin /data</userinput> +ls: /data: No such file or directory +<prompt>c:\cygnus\></prompt> <userinput>mount C:\cygnus\cygwin-b20\H-i586-cygwin32\bin /bin</userinput> +<prompt>c:\cygnus\></prompt> <userinput>mount \\pollux\home\joe\data /data</userinput> +Warning: /data does not exist! +<prompt>c:\cygnus\></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\></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\></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] <posixpath> +-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> + |