diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 44 | ||||
-rw-r--r-- | lib/Makefile.in | 717 | ||||
-rw-r--r-- | lib/buildcmd.c | 515 | ||||
-rw-r--r-- | lib/buildcmd.h | 131 | ||||
-rw-r--r-- | lib/extendbuf.c | 105 | ||||
-rw-r--r-- | lib/extendbuf.h | 27 | ||||
-rw-r--r-- | lib/forcefindlib.c | 50 | ||||
-rw-r--r-- | lib/gnulib-version.c | 2 | ||||
-rw-r--r-- | lib/gnulib-version.h | 21 | ||||
-rw-r--r-- | lib/gnulib-version.sh | 50 | ||||
-rw-r--r-- | lib/listfile.c | 395 | ||||
-rw-r--r-- | lib/listfile.h | 28 | ||||
-rw-r--r-- | lib/modetype.h | 95 | ||||
-rw-r--r-- | lib/nextelem.c | 110 | ||||
-rw-r--r-- | lib/nextelem.h | 28 | ||||
-rw-r--r-- | lib/printquoted.c | 87 | ||||
-rw-r--r-- | lib/printquoted.h | 35 | ||||
-rw-r--r-- | lib/qmark.c | 239 | ||||
-rw-r--r-- | lib/regexprops.c | 505 | ||||
-rw-r--r-- | lib/regextype.c | 158 | ||||
-rw-r--r-- | lib/regextype.h | 28 | ||||
-rw-r--r-- | lib/savedirinfo.c | 387 | ||||
-rw-r--r-- | lib/savedirinfo.h | 73 | ||||
-rw-r--r-- | lib/wait.h | 41 | ||||
-rw-r--r-- | lib/waitpid.c | 81 |
25 files changed, 3952 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..3f6b1fe --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,44 @@ +## Process this file with automake to produce Makefile.in. + +AUTOMAKE_OPTIONS = 1.5 gnits +# no-dependencies + +noinst_LIBRARIES = libfind.a + +if CROSS_COMPILING +# The regexprops program needs to be a native executable, so we +# can't build it with a cross-compiler. +else +noinst_PROGRAMS = regexprops +regexprops_SOURCES = regexprops.c regextype.c +endif + +libfind_a_SOURCES = gnulib-version.c +EXTRA_DIST = modetype.h wait.h extendbuf.h savedirinfo.h buildcmd.h \ + gnulib-version.h gnulib-version.sh gnulib-version.c +BUILT_SOURCES = gnulib-version.c +SUFFIXES = +MOSTLYCLEANFILES = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +IMPORT_GNULIB_CONFIG = $(top_srcdir)/import-gnulib.config + +INCLUDES = -I../gnulib/lib -I$(top_srcdir)/gnulib/lib +LDADD = ../gnulib/lib/libgnulib.a @INTLLIBS@ + +libfind_a_SOURCES += modetype.h nextelem.h printquoted.h listfile.h regextype.h +libfind_a_SOURCES += listfile.c nextelem.c extendbuf.c buildcmd.c savedirinfo.c forcefindlib.c qmark.c printquoted.c regextype.c + +EXTRA_DIST += waitpid.c forcefindlib.c + + +libfind_a_LIBADD = @FINDLIBOBJS@ +libfind_a_DEPENDENCIES = @FINDLIBOBJS@ +# libfind_la_LIBADD = @LTFINDLIBOBJS@ + +# libfind_a_OBJECTS += @FINDLIBOBJS@ +# libfind_la_OBJECTS += @LTFINDLIBOBJS@ + +$(srcdir)/gnulib-version.c: $(srcdir)/gnulib-version.sh $(IMPORT_GNULIB_CONFIG) + sh $(srcdir)/gnulib-version.sh $(top_srcdir) $(srcdir) $(IMPORT_GNULIB_CONFIG)
\ No newline at end of file diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..5a1f252 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,717 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@CROSS_COMPILING_FALSE@noinst_PROGRAMS = regexprops$(EXEEXT) +subdir = lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/gnulib/m4/absolute-header.m4 \ + $(top_srcdir)/gnulib/m4/alloca.m4 \ + $(top_srcdir)/gnulib/m4/argmatch.m4 \ + $(top_srcdir)/gnulib/m4/canonicalize.m4 \ + $(top_srcdir)/gnulib/m4/chdir-long.m4 \ + $(top_srcdir)/gnulib/m4/chown.m4 \ + $(top_srcdir)/gnulib/m4/close-stream.m4 \ + $(top_srcdir)/gnulib/m4/closeout.m4 \ + $(top_srcdir)/gnulib/m4/codeset.m4 \ + $(top_srcdir)/gnulib/m4/cycle-check.m4 \ + $(top_srcdir)/gnulib/m4/d-ino.m4 \ + $(top_srcdir)/gnulib/m4/dirfd.m4 \ + $(top_srcdir)/gnulib/m4/dirname.m4 \ + $(top_srcdir)/gnulib/m4/dos.m4 \ + $(top_srcdir)/gnulib/m4/double-slash-root.m4 \ + $(top_srcdir)/gnulib/m4/error.m4 \ + $(top_srcdir)/gnulib/m4/exitfail.m4 \ + $(top_srcdir)/gnulib/m4/extensions.m4 \ + $(top_srcdir)/gnulib/m4/fcntl-safer.m4 \ + $(top_srcdir)/gnulib/m4/fcntl_h.m4 \ + $(top_srcdir)/gnulib/m4/fileblocks.m4 \ + $(top_srcdir)/gnulib/m4/filemode.m4 \ + $(top_srcdir)/gnulib/m4/filenamecat.m4 \ + $(top_srcdir)/gnulib/m4/flexmember.m4 \ + $(top_srcdir)/gnulib/m4/fnmatch.m4 \ + $(top_srcdir)/gnulib/m4/fpending.m4 \ + $(top_srcdir)/gnulib/m4/fstypename.m4 \ + $(top_srcdir)/gnulib/m4/getcwd-abort-bug.m4 \ + $(top_srcdir)/gnulib/m4/getcwd-path-max.m4 \ + $(top_srcdir)/gnulib/m4/getcwd.m4 \ + $(top_srcdir)/gnulib/m4/getdelim.m4 \ + $(top_srcdir)/gnulib/m4/getline.m4 \ + $(top_srcdir)/gnulib/m4/getopt.m4 \ + $(top_srcdir)/gnulib/m4/gettext.m4 \ + $(top_srcdir)/gnulib/m4/glibc21.m4 \ + $(top_srcdir)/gnulib/m4/gnulib-common.m4 \ + $(top_srcdir)/gnulib/m4/gnulib-comp.m4 \ + $(top_srcdir)/gnulib/m4/human.m4 \ + $(top_srcdir)/gnulib/m4/iconv.m4 \ + $(top_srcdir)/gnulib/m4/idcache.m4 \ + $(top_srcdir)/gnulib/m4/inline.m4 \ + $(top_srcdir)/gnulib/m4/inttypes-pri.m4 \ + $(top_srcdir)/gnulib/m4/inttypes.m4 \ + $(top_srcdir)/gnulib/m4/lchown.m4 \ + $(top_srcdir)/gnulib/m4/lib-ld.m4 \ + $(top_srcdir)/gnulib/m4/lib-link.m4 \ + $(top_srcdir)/gnulib/m4/lib-prefix.m4 \ + $(top_srcdir)/gnulib/m4/localcharset.m4 \ + $(top_srcdir)/gnulib/m4/longlong.m4 \ + $(top_srcdir)/gnulib/m4/ls-mntd-fs.m4 \ + $(top_srcdir)/gnulib/m4/lstat.m4 \ + $(top_srcdir)/gnulib/m4/mbrtowc.m4 \ + $(top_srcdir)/gnulib/m4/mbstate_t.m4 \ + $(top_srcdir)/gnulib/m4/memcmp.m4 \ + $(top_srcdir)/gnulib/m4/mempcpy.m4 \ + $(top_srcdir)/gnulib/m4/memrchr.m4 \ + $(top_srcdir)/gnulib/m4/memset.m4 \ + $(top_srcdir)/gnulib/m4/mktime.m4 \ + $(top_srcdir)/gnulib/m4/modechange.m4 \ + $(top_srcdir)/gnulib/m4/mountlist.m4 \ + $(top_srcdir)/gnulib/m4/nls.m4 \ + $(top_srcdir)/gnulib/m4/onceonly_2_57.m4 \ + $(top_srcdir)/gnulib/m4/openat.m4 \ + $(top_srcdir)/gnulib/m4/pathmax.m4 \ + $(top_srcdir)/gnulib/m4/po.m4 \ + $(top_srcdir)/gnulib/m4/progtest.m4 \ + $(top_srcdir)/gnulib/m4/quote.m4 \ + $(top_srcdir)/gnulib/m4/quotearg.m4 \ + $(top_srcdir)/gnulib/m4/readlink.m4 \ + $(top_srcdir)/gnulib/m4/regex.m4 \ + $(top_srcdir)/gnulib/m4/rpmatch.m4 \ + $(top_srcdir)/gnulib/m4/save-cwd.m4 \ + $(top_srcdir)/gnulib/m4/savedir.m4 \ + $(top_srcdir)/gnulib/m4/ssize_t.m4 \ + $(top_srcdir)/gnulib/m4/st_dm_mode.m4 \ + $(top_srcdir)/gnulib/m4/stdbool.m4 \ + $(top_srcdir)/gnulib/m4/stdint.m4 \ + $(top_srcdir)/gnulib/m4/stdio-safer.m4 \ + $(top_srcdir)/gnulib/m4/stdlib_h.m4 \ + $(top_srcdir)/gnulib/m4/stpcpy.m4 \ + $(top_srcdir)/gnulib/m4/strdup.m4 \ + $(top_srcdir)/gnulib/m4/strftime.m4 \ + $(top_srcdir)/gnulib/m4/string_h.m4 \ + $(top_srcdir)/gnulib/m4/strndup.m4 \ + $(top_srcdir)/gnulib/m4/strnlen.m4 \ + $(top_srcdir)/gnulib/m4/strtoimax.m4 \ + $(top_srcdir)/gnulib/m4/strtol.m4 \ + $(top_srcdir)/gnulib/m4/strtoll.m4 \ + $(top_srcdir)/gnulib/m4/strtoul.m4 \ + $(top_srcdir)/gnulib/m4/strtoull.m4 \ + $(top_srcdir)/gnulib/m4/strtoumax.m4 \ + $(top_srcdir)/gnulib/m4/sys_stat_h.m4 \ + $(top_srcdir)/gnulib/m4/time_h.m4 \ + $(top_srcdir)/gnulib/m4/time_r.m4 \ + $(top_srcdir)/gnulib/m4/tm_gmtoff.m4 \ + $(top_srcdir)/gnulib/m4/ulonglong.m4 \ + $(top_srcdir)/gnulib/m4/unistd-safer.m4 \ + $(top_srcdir)/gnulib/m4/unistd_h.m4 \ + $(top_srcdir)/gnulib/m4/wchar.m4 \ + $(top_srcdir)/gnulib/m4/wchar_t.m4 \ + $(top_srcdir)/gnulib/m4/wctype.m4 \ + $(top_srcdir)/gnulib/m4/wint_t.m4 \ + $(top_srcdir)/gnulib/m4/xalloc.m4 \ + $(top_srcdir)/gnulib/m4/xgetcwd.m4 \ + $(top_srcdir)/gnulib/m4/xreadlink.m4 \ + $(top_srcdir)/gnulib/m4/xstrndup.m4 \ + $(top_srcdir)/gnulib/m4/xstrtol.m4 \ + $(top_srcdir)/gnulib/m4/yesno.m4 $(top_srcdir)/m4/findlib.m4 \ + $(top_srcdir)/m4/mkinstalldirs.m4 $(top_srcdir)/m4/nullsort.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libfind_a_AR = $(AR) $(ARFLAGS) +am_libfind_a_OBJECTS = gnulib-version.$(OBJEXT) listfile.$(OBJEXT) \ + nextelem.$(OBJEXT) extendbuf.$(OBJEXT) buildcmd.$(OBJEXT) \ + savedirinfo.$(OBJEXT) forcefindlib.$(OBJEXT) qmark.$(OBJEXT) \ + printquoted.$(OBJEXT) regextype.$(OBJEXT) +libfind_a_OBJECTS = $(am_libfind_a_OBJECTS) +PROGRAMS = $(noinst_PROGRAMS) +am__regexprops_SOURCES_DIST = regexprops.c regextype.c +@CROSS_COMPILING_FALSE@am_regexprops_OBJECTS = regexprops.$(OBJEXT) \ +@CROSS_COMPILING_FALSE@ regextype.$(OBJEXT) +regexprops_OBJECTS = $(am_regexprops_OBJECTS) +regexprops_LDADD = $(LDADD) +regexprops_DEPENDENCIES = ../gnulib/lib/libgnulib.a +DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libfind_a_SOURCES) $(regexprops_SOURCES) +DIST_SOURCES = $(libfind_a_SOURCES) $(am__regexprops_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ABSOLUTE_FCNTL_H = @ABSOLUTE_FCNTL_H@ +ABSOLUTE_INTTYPES_H = @ABSOLUTE_INTTYPES_H@ +ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@ +ABSOLUTE_STDLIB_H = @ABSOLUTE_STDLIB_H@ +ABSOLUTE_STRING_H = @ABSOLUTE_STRING_H@ +ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@ +ABSOLUTE_TIME_H = @ABSOLUTE_TIME_H@ +ABSOLUTE_UNISTD_H = @ABSOLUTE_UNISTD_H@ +ABSOLUTE_WCHAR_H = @ABSOLUTE_WCHAR_H@ +ABSOLUTE_WCTYPE_H = @ABSOLUTE_WCTYPE_H@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FCNTL_H = @FCNTL_H@ +FINDLIBOBJS = @FINDLIBOBJS@ +FNMATCH_H = @FNMATCH_H@ +GETOPT_H = @GETOPT_H@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_IMAXABS = @GNULIB_IMAXABS@ +GNULIB_IMAXDIV = @GNULIB_IMAXDIV@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@ +GREP = @GREP@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRNDUP = @HAVE_STRNDUP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE__BOOL = @HAVE__BOOL@ +INCLUDES = -I../gnulib/lib -I$(top_srcdir)/gnulib/lib +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTTYPES_H = @INTTYPES_H@ +LDFLAGS = @LDFLAGS@ +LIBGNULIB_LIBDEPS = @LIBGNULIB_LIBDEPS@ +LIBGNULIB_LTLIBDEPS = @LIBGNULIB_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_FCHDIR = @REPLACE_FCHDIR@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_STRPTIME = @REPLACE_STRPTIME@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SORT = @SORT@ +SORT_SUPPORTS_Z = @SORT_SUPPORTS_Z@ +STDBOOL_H = @STDBOOL_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_STAT_H = @SYS_STAT_H@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +U = @U@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WCHAR_H = @WCHAR_H@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WCTYPE_H = @WCTYPE_H@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = 1.5 gnits +# no-dependencies +noinst_LIBRARIES = libfind.a +@CROSS_COMPILING_FALSE@regexprops_SOURCES = regexprops.c regextype.c +libfind_a_SOURCES = gnulib-version.c modetype.h nextelem.h \ + printquoted.h listfile.h regextype.h listfile.c nextelem.c \ + extendbuf.c buildcmd.c savedirinfo.c forcefindlib.c qmark.c \ + printquoted.c regextype.c +EXTRA_DIST = modetype.h wait.h extendbuf.h savedirinfo.h buildcmd.h \ + gnulib-version.h gnulib-version.sh gnulib-version.c waitpid.c \ + forcefindlib.c +BUILT_SOURCES = gnulib-version.c +SUFFIXES = +MOSTLYCLEANFILES = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +IMPORT_GNULIB_CONFIG = $(top_srcdir)/import-gnulib.config +LDADD = ../gnulib/lib/libgnulib.a @INTLLIBS@ +libfind_a_LIBADD = @FINDLIBOBJS@ +libfind_a_DEPENDENCIES = @FINDLIBOBJS@ +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits lib/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libfind.a: $(libfind_a_OBJECTS) $(libfind_a_DEPENDENCIES) + -rm -f libfind.a + $(libfind_a_AR) libfind.a $(libfind_a_OBJECTS) $(libfind_a_LIBADD) + $(RANLIB) libfind.a + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +regexprops$(EXEEXT): $(regexprops_OBJECTS) $(regexprops_DEPENDENCIES) + @rm -f regexprops$(EXEEXT) + $(LINK) $(regexprops_OBJECTS) $(regexprops_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buildcmd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extendbuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forcefindlib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnulib-version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listfile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nextelem.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printquoted.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qmark.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexprops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regextype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/savedirinfo.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + +# libfind_la_LIBADD = @LTFINDLIBOBJS@ + +# libfind_a_OBJECTS += @FINDLIBOBJS@ +# libfind_la_OBJECTS += @LTFINDLIBOBJS@ + +$(srcdir)/gnulib-version.c: $(srcdir)/gnulib-version.sh $(IMPORT_GNULIB_CONFIG) + sh $(srcdir)/gnulib-version.sh $(top_srcdir) $(srcdir) $(IMPORT_GNULIB_CONFIG) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/buildcmd.c b/lib/buildcmd.c new file mode 100644 index 0000000..efe1fbf --- /dev/null +++ b/lib/buildcmd.c @@ -0,0 +1,515 @@ +/* buildcmd.c -- build command lines from a list of arguments. + Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#include <config.h> + +# ifndef PARAMS +# if defined PROTOTYPES || (defined __STDC__ && __STDC__) +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +# endif + +#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) +#include <string.h> +#endif + + +#if DO_MULTIBYTE +# if HAVE_MBRLEN +# include <wchar.h> +# else + /* Simulate mbrlen with mblen as best we can. */ +# define mbstate_t int +# define mbrlen(s, n, ps) mblen (s, n) +# endif +#endif + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#if ENABLE_NLS +# include <libintl.h> +# define _(Text) gettext (Text) +#else +# define _(Text) Text +#define textdomain(Domain) +#define bindtextdomain(Package, Directory) +#endif +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +/* See locate.c for explanation as to why not use (String) */ +# define N_(String) String +#endif + +#ifndef _POSIX_SOURCE +#include <sys/param.h> +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +/* The presence of unistd.h is assumed by gnulib these days, so we + * might as well assume it too. + */ +/* for sysconf() */ +#include <unistd.h> + +#include <assert.h> + +/* COMPAT: SYSV version defaults size (and has a max value of) to 470. + We try to make it as large as possible. */ +#if !defined(ARG_MAX) && defined(_SC_ARG_MAX) +#define ARG_MAX sysconf (_SC_ARG_MAX) +#endif +#ifndef ARG_MAX +#define ARG_MAX NCARGS +#endif + + + +#include <xalloc.h> +#include <error.h> + +#include "buildcmd.h" + + +extern char **environ; + + +static char *mbstrstr PARAMS ((const char *haystack, const char *needle)); + +/* Replace all instances of `replace_pat' in ARG with `linebuf', + and add the resulting string to the list of arguments for the command + to execute. + ARGLEN is the length of ARG, not including the null. + LBLEN is the length of LINEBUF, not including the null. + PFXLEN is the length of PREFIX. Substitution is not performed on + the prefix. The prefix is used if the argument contains replace_pat. + + COMPAT: insertions on the SYSV version are limited to 255 chars per line, + and a max of 5 occurrences of replace_pat in the initial-arguments. + Those restrictions do not exist here. */ + +void +bc_do_insert (const struct buildcmd_control *ctl, + struct buildcmd_state *state, + char *arg, size_t arglen, + const char *prefix, size_t pfxlen, + const char *linebuf, size_t lblen, + int initial_args) +{ + /* Temporary copy of each arg with the replace pattern replaced by the + real arg. */ + static char *insertbuf; + char *p; + size_t bytes_left = ctl->arg_max - 1; /* Bytes left on the command line. */ + int need_prefix; + + /* XXX: on systems lacking an upper limit for exec args, ctl->arg_max + * may have been set to LONG_MAX (see bc_get_arg_max()). Hence + * this xmalloc call may be a bad idea, especially since we are + * adding 1 to it... + */ + if (!insertbuf) + insertbuf = (char *) xmalloc (ctl->arg_max + 1); + p = insertbuf; + + do + { + size_t len; /* Length in ARG before `replace_pat'. */ + char *s = mbstrstr (arg, ctl->replace_pat); + if (s) + { + len = s - arg; + } + else + { + len = arglen; + } + + if (bytes_left <= len) + break; + else + bytes_left -= len; + + strncpy (p, arg, len); + p += len; + arg += len; + arglen -= len; + + if (s) + { + if (bytes_left <= (lblen + pfxlen)) + break; + else + bytes_left -= (lblen + pfxlen); + + if (prefix) + { + strcpy (p, prefix); + p += pfxlen; + } + strcpy (p, linebuf); + p += lblen; + + arg += ctl->rplen; + arglen -= ctl->rplen; + } + } + while (*arg); + if (*arg) + error (1, 0, _("command too long")); + *p++ = '\0'; + + bc_push_arg (ctl, state, + insertbuf, p - insertbuf, + NULL, 0, + initial_args); +} + +static +void do_exec(const struct buildcmd_control *ctl, + struct buildcmd_state *state) +{ + (ctl->exec_callback)(ctl, state); +} + + +/* Return nonzero if there would not be enough room for an additional + * argument. We check the total number of arguments only, not the space + * occupied by those arguments. + * + * If we return zero, there still may not be enough room for the next + * argument, depending on its length. + */ +static int +bc_argc_limit_reached(int initial_args, + const struct buildcmd_control *ctl, + struct buildcmd_state *state) +{ + /* Check to see if we about to exceed a limit set by xargs' -n option */ + if (!initial_args && ctl->args_per_exec && + ( (state->cmd_argc - ctl->initial_argc) == ctl->args_per_exec)) + return 1; + + /* We deliberately use an equality test here rather than >= in order + * to force a software failure if the code is modified in such a way + * that it fails to call this function for every new argument. + */ + return state->cmd_argc == ctl->max_arg_count; +} + + +/* Add ARG to the end of the list of arguments `cmd_argv' to pass + to the command. + LEN is the length of ARG, including the terminating null. + If this brings the list up to its maximum size, execute the command. */ + +void +bc_push_arg (const struct buildcmd_control *ctl, + struct buildcmd_state *state, + const char *arg, size_t len, + const char *prefix, size_t pfxlen, + int initial_args) +{ + if (!initial_args) + state->todo = 1; + + if (arg) + { + if (state->cmd_argv_chars + len > ctl->arg_max) + { + if (initial_args || state->cmd_argc == ctl->initial_argc) + error (1, 0, _("can not fit single argument within argument list size limit")); + /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */ + if (ctl->replace_pat + || (ctl->exit_if_size_exceeded && + (ctl->lines_per_exec || ctl->args_per_exec))) + error (1, 0, _("argument list too long")); + do_exec (ctl, state); + } + + if (bc_argc_limit_reached(initial_args, ctl, state)) + do_exec (ctl, state); + } + + if (state->cmd_argc >= state->cmd_argv_alloc) + { + if (!state->cmd_argv) + { + state->cmd_argv_alloc = 64; + state->cmd_argv = (char **) xmalloc (sizeof (char *) * state->cmd_argv_alloc); + } + else + { + state->cmd_argv_alloc *= 2; + state->cmd_argv = (char **) xrealloc (state->cmd_argv, + sizeof (char *) * state->cmd_argv_alloc); + } + } + + if (!arg) + state->cmd_argv[state->cmd_argc++] = NULL; + else + { + state->cmd_argv[state->cmd_argc++] = state->argbuf + state->cmd_argv_chars; + if (prefix) + { + strcpy (state->argbuf + state->cmd_argv_chars, prefix); + state->cmd_argv_chars += pfxlen; + } + + strcpy (state->argbuf + state->cmd_argv_chars, arg); + state->cmd_argv_chars += len; + + /* If we have now collected enough arguments, + * do the exec immediately. This must be + * conditional on arg!=NULL, since do_exec() + * actually calls bc_push_arg(ctl, state, NULL, 0, false). + */ + if (bc_argc_limit_reached(initial_args, ctl, state)) + do_exec (ctl, state); + } + + /* If this is an initial argument, set the high-water mark. */ + if (initial_args) + { + state->cmd_initial_argv_chars = state->cmd_argv_chars; + } +} + + +/* Finds the first occurrence of the substring NEEDLE in the string + HAYSTACK. Both strings can be multibyte strings. */ + +static char * +mbstrstr (const char *haystack, const char *needle) +{ +#if DO_MULTIBYTE + if (MB_CUR_MAX > 1) + { + size_t hlen = strlen (haystack); + size_t nlen = strlen (needle); + mbstate_t mbstate; + size_t step; + + memset (&mbstate, 0, sizeof (mbstate_t)); + while (hlen >= nlen) + { + if (memcmp (haystack, needle, nlen) == 0) + return (char *) haystack; + step = mbrlen (haystack, hlen, &mbstate); + if (step <= 0) + break; + haystack += step; + hlen -= step; + } + return NULL; + } +#endif + return strstr (haystack, needle); +} + +static size_t +get_line_max(void) +{ + long val; +#ifdef _SC_LINE_MAX + val = sysconf(_SC_LINE_MAX); +#else + val = -1; +#endif + + if (val > 0) + return val; + + /* either _SC_LINE_MAX was not available or + * there is no particular limit. + */ +#ifdef LINE_MAX + val = LINE_MAX; +#endif + + if (val > 0) + return val; + + return 2048L; /* a reasonable guess. */ +} + + +size_t +bc_get_arg_max(void) +{ + long val; + + /* We may resort to using LONG_MAX, so check it fits. */ + /* XXX: better to do a compile-time check */ + assert( (~(size_t)0) >= LONG_MAX); + +#ifdef _SC_ARG_MAX + val = sysconf(_SC_ARG_MAX); +#else + val = -1; +#endif + + if (val > 0) + return val; + + /* either _SC_ARG_MAX was not available or + * there is no particular limit. + */ +#ifdef ARG_MAX + val = ARG_MAX; +#endif + + if (val > 0) + return val; + + /* The value returned by this function bounds the + * value applied as the ceiling for the -s option. + * Hence it the system won't tell us what its limit + * is, we allow the user to specify more or less + * whatever value they like. + */ + return LONG_MAX; +} + + +static int cb_exec_noop(const struct buildcmd_control *ctl, + struct buildcmd_state *state) +{ + /* does nothing. */ + (void) ctl; + (void) state; + + return 0; +} + + +/* Return how much of ARG_MAX is used by the environment. */ +size_t +bc_size_of_environment (void) +{ + size_t len = 0u; + char **envp = environ; + + while (*envp) + len += strlen (*envp++) + 1; + + return len; +} + + +enum BC_INIT_STATUS +bc_init_controlinfo(struct buildcmd_control *ctl) +{ + size_t size_of_environment = bc_size_of_environment(); + size_t arg_max; + + ctl->posix_arg_size_min = get_line_max(); + arg_max = bc_get_arg_max(); + + /* POSIX.2 requires subtracting 2048. */ + assert(arg_max > 2048u); /* XXX: this is an external condition, should not check it with assert. */ + ctl->posix_arg_size_max = (arg_max - 2048); + + ctl->exit_if_size_exceeded = 0; + + /* Take the size of the environment into account. */ + if (size_of_environment > ctl->posix_arg_size_max) + { + return BC_INIT_ENV_TOO_BIG; + } + else + { + ctl->posix_arg_size_max - size_of_environment; + } + + /* need to subtract 2 on the following line - for Linux/PPC */ + ctl->max_arg_count = (ctl->posix_arg_size_max / sizeof(char*)) - 2u; + assert(ctl->max_arg_count > 0); + ctl->rplen = 0u; + ctl->replace_pat = NULL; + ctl->initial_argc = 0; + ctl->exec_callback = cb_exec_noop; + ctl->lines_per_exec = 0; + ctl->args_per_exec = 0; + + /* Set the initial value of arg_max to the largest value we can + * tolerate. + */ + ctl->arg_max = ctl->posix_arg_size_max; + + return BC_INIT_OK; +} + +void +bc_use_sensible_arg_max(struct buildcmd_control *ctl) +{ + size_t env_size = bc_size_of_environment(); + const size_t arg_size = (128u * 1024u) + env_size; + + /* Check against the upper and lower limits. */ + if (arg_size > ctl->posix_arg_size_max) + ctl->arg_max = ctl->posix_arg_size_max - env_size; + else if (arg_size < ctl->posix_arg_size_min) + ctl->arg_max = ctl->posix_arg_size_min; + else + ctl->arg_max = arg_size; +} + + + + +void +bc_init_state(const struct buildcmd_control *ctl, + struct buildcmd_state *state, + void *context) +{ + state->cmd_argc = 0; + state->cmd_argv_chars = 0; + state->cmd_argv = NULL; + state->cmd_argv_alloc = 0; + + /* XXX: the following memory allocation is inadvisable on systems + * with no ARG_MAX, because ctl->arg_max may actually be close to + * LONG_MAX. Adding one to it is safe though because earlier we + * subtracted 2048. + */ + assert(ctl->arg_max <= (LONG_MAX - 2048L)); + state->argbuf = (char *) xmalloc (ctl->arg_max + 1u); + + state->cmd_argv_chars = state->cmd_initial_argv_chars = 0; + state->todo = 0; + state->usercontext = context; +} + +void +bc_clear_args(const struct buildcmd_control *ctl, + struct buildcmd_state *state) +{ + state->cmd_argc = ctl->initial_argc; + state->cmd_argv_chars = state->cmd_initial_argv_chars; + state->todo = 0; +} + diff --git a/lib/buildcmd.h b/lib/buildcmd.h new file mode 100644 index 0000000..b8fa896 --- /dev/null +++ b/lib/buildcmd.h @@ -0,0 +1,131 @@ +/* buildcmd.h -- build command lines from a stream of arguments + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ +/* + * Written by James Youngman. + */ +#ifndef INC_BUILDCMD_H +#define INC_BUILDCMD_H 1 + +struct buildcmd_state +{ + /* Number of valid elements in `cmd_argv'. */ + int cmd_argc; /* 0 */ + + /* The list of args being built. */ + char **cmd_argv; /* NULL */ + + /* Number of elements allocated for `cmd_argv'. */ + int cmd_argv_alloc; + + /* Storage for elements of `cmd_argv'. */ + char *argbuf; + + /* Number of chars being used in `cmd_argv'. */ + size_t cmd_argv_chars; + + /* Number of chars being used in `cmd_argv' for the initial args.. */ + size_t cmd_initial_argv_chars; + + /* User context information. */ + void *usercontext; + + /* to-do flag. */ + int todo; +}; + +struct buildcmd_control +{ + /* If true, exit if lines_per_exec or args_per_exec is exceeded. */ + int exit_if_size_exceeded; /* false */ + + /* POSIX limits on the argument length. */ + size_t posix_arg_size_max; + size_t posix_arg_size_min; + + /* The maximum number of characters that can be used per command line. */ + size_t arg_max; + + /* max_arg_count: the maximum number of arguments that can be used. + * + * Many systems include the size of the pointers in ARG_MAX. + * Linux on PPC fails if we just subtract 1 here. + * + * However, not all systems define ARG_MAX. Our bc_get_arg_max() + * function returns a useful value even if ARG_MAX is not defined. + * However, sometimes, max_arg_count is LONG_MAX! + */ + long max_arg_count; + + + /* The length of `replace_pat'. */ + size_t rplen; + + /* If nonzero, then instead of putting the args from stdin at + the end of the command argument list, they are each stuck into the + initial args, replacing each occurrence of the `replace_pat' in the + initial args. */ + char *replace_pat; + + /* Number of initial arguments given on the command line. */ + int initial_argc; /* 0 */ + + /* exec callback. */ + int (*exec_callback)(const struct buildcmd_control *, struct buildcmd_state *); + + /* If nonzero, the maximum number of nonblank lines from stdin to use + per command line. */ + long lines_per_exec; /* 0 */ + + /* The maximum number of arguments to use per command line. */ + long args_per_exec; +}; + +enum BC_INIT_STATUS + { + BC_INIT_OK = 0, + BC_INIT_ENV_TOO_BIG + }; + +extern size_t bc_size_of_environment (void); + + +extern void bc_do_insert (const struct buildcmd_control *ctl, + struct buildcmd_state *state, + char *arg, size_t arglen, + const char *prefix, size_t pfxlen, + const char *linebuf, size_t lblen, + int initial_args); + +extern void bc_push_arg (const struct buildcmd_control *ctl, + struct buildcmd_state *state, + const char *arg, size_t len, + const char *prefix, size_t pfxlen, + int initial_args); + +extern void bc_init_state(const struct buildcmd_control *ctl, + struct buildcmd_state *state, + void *usercontext); +extern enum BC_INIT_STATUS bc_init_controlinfo(struct buildcmd_control *ctl); +extern size_t bc_get_arg_max(void); +extern void bc_use_sensible_arg_max(struct buildcmd_control *ctl); +extern void bc_clear_args(const struct buildcmd_control *ctl, + struct buildcmd_state *state); + + +#endif diff --git a/lib/extendbuf.c b/lib/extendbuf.c new file mode 100644 index 0000000..b1a322f --- /dev/null +++ b/lib/extendbuf.c @@ -0,0 +1,105 @@ +/* extendbuf.c -- manage a dynamically-allocated buffer + + Copyright 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Yougnman <jay@gnu.org>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +#include "xalloc.h" +#include "extendbuf.h" + + +/* We initially use a small default size to ensure that this code + * gets exercised. + */ +#ifndef SIZE_DEFAULT +# define SIZE_DEFAULT 16 +#endif + +static size_t +decide_size(size_t current, size_t wanted) +{ + size_t newsize; + + if (0 == current) + newsize = SIZE_DEFAULT; + else + newsize = current; + + while (newsize < wanted) + { + if (2 * newsize < newsize) + xalloc_die (); + newsize *= 2; + } + return newsize; +} + + +void * +extendbuf(void* existing, size_t wanted, size_t *allocated) +{ + int saved_errno; + size_t newsize; + void *result; /* leave uninitialised to allow static code checkers to identify bugs */ + + saved_errno = errno; + + assert(wanted > 0u); + newsize = decide_size(*allocated, wanted); + + if ( (*allocated) == 0 ) + { + /* Sanity check: If there is no existing allocation size, there + * must be no existing allocated buffer. + */ + assert(NULL == existing); + + (*allocated) = newsize; + result = xmalloc(newsize); + } + else + { + if (newsize != (*allocated) ) + { + (*allocated) = newsize; + result = xrealloc (existing, newsize); + + } + else + { + result = existing; + } + } + + if (result) + { + /* xmalloc() or xrealloc() may have changed errno, but in the + success case we want to preserve the previous value. + */ + errno = saved_errno; + } + return result; +} diff --git a/lib/extendbuf.h b/lib/extendbuf.h new file mode 100644 index 0000000..987152e --- /dev/null +++ b/lib/extendbuf.h @@ -0,0 +1,27 @@ +/* extendbuf.h -- Manage a dynamically-alloicated buffer + + Copyright (C) 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#ifndef INC_EXTENDBUF_H +#define INC_EXTENDBUF_H 1 + +void *extendbuf(void* existing, size_t wanted, size_t *allocated); + + +#endif diff --git a/lib/forcefindlib.c b/lib/forcefindlib.c new file mode 100644 index 0000000..6ee12c1 --- /dev/null +++ b/lib/forcefindlib.c @@ -0,0 +1,50 @@ +/* Ensures that the FINDLIB_REPLACE_FUNCS macro in configure.in works + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +/* Written by James Youngman. */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +extern void forcefindlib(void); /* prevent GCC warning... */ + + + +/* forcefindlib + * + * This function exists only to be pulled into libfind.a by the + * FINDLIB_REPLACE_FUNCS macro in configure.in. We already have + * AC_REPLACE_FUNCS, but that adds to LIBOBJS, and that's a gnulib thing + * in the case of findutils. Hence we have out own library of replacement + * functions which aren't in gnulib (or aren't in it any more). An example + * of this is waitpid(). I develop on a system that doesn't + * lack waitpid, for example. Therefore FINDLIB_REPLACE_FUNCS(waitpid) + * never puts waitpid.o into FINDLIBOBJS. Hence, to ensure that these + * macros are tested every time, we use FINDLIB_REPLACE_FUNCS on a function + * that never exists anywhere, so always needs to be pulled in. That function + * is forcefindlib(). + */ +void +forcefindlib(void) +{ + /* does nothing, exists only to ensure that FINDLIB_REPLACE_FUNCS works. */ +} diff --git a/lib/gnulib-version.c b/lib/gnulib-version.c new file mode 100644 index 0000000..708eec1 --- /dev/null +++ b/lib/gnulib-version.c @@ -0,0 +1,2 @@ +/* This file is automatically generated by import-gnulib.sh and simply records which version of gnulib we used. */ +const char * const gnulib_version = "2007-02-24"; diff --git a/lib/gnulib-version.h b/lib/gnulib-version.h new file mode 100644 index 0000000..eadd5be --- /dev/null +++ b/lib/gnulib-version.h @@ -0,0 +1,21 @@ +/* gnulib-version.h + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +extern const char * const gnulib_version; + diff --git a/lib/gnulib-version.sh b/lib/gnulib-version.sh new file mode 100644 index 0000000..b9494b9 --- /dev/null +++ b/lib/gnulib-version.sh @@ -0,0 +1,50 @@ +#! /bin/sh +# +# gnulib-version.sh -- creates gnulib-version.c (from ../import-gnulib.config) +# Copyright (C) 2007 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# + +topsrcdir="$1" +srcdir="$2" +configfile="$3" + +outfile="${srcdir}"/gnulib-version.c + +source $configfile + +if [ -z "$gnulib_version" ] +then + echo "Error: There should be a gnulib_version setting in $configfile, but there is not." >&2 + exit 1 +fi + + +cat > "${outfile}".new <<EOF +/* This file is automatically generated by $0 and simply records which version of gnulib we used. */ +const char * const gnulib_version = "$gnulib_version"; +EOF + +if test -f "$outfile" ; then + if diff "${outfile}".new "${outfile}" > /dev/null + then + # nothing to do + rm "${outfile}".new + exit 0 + fi +fi +mv "${outfile}".new "${outfile}" diff --git a/lib/listfile.c b/lib/listfile.c new file mode 100644 index 0000000..d60f465 --- /dev/null +++ b/lib/listfile.c @@ -0,0 +1,395 @@ +/* listfile.c -- display a long listing of a file + Copyright (C) 1991, 1993, 2000, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef __GNUC__ +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + # pragma alloca +# else +# ifdef _WIN32 +# include <malloc.h> +# include <io.h> +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <pwd.h> +#include <grp.h> +#include <time.h> +#include <errno.h> +#include "human.h" +#include "xalloc.h" +#include "pathmax.h" +#include "error.h" +#include "filemode.h" + +#include "listfile.h" + +#if HAVE_STRING_H || STDC_HEADERS +#include <string.h> +#else +#include <strings.h> +#endif + + +/* The presence of unistd.h is assumed by gnulib these days, so we + * might as well assume it too. + */ +#include <unistd.h> /* for readlink() */ + + +#if STDC_HEADERS +# include <stdlib.h> +#else +char *getenv (); +extern int errno; +#endif + +/* Since major is a function on SVR4, we can't use `ifndef major'. */ +#ifdef MAJOR_IN_MKDEV +#include <sys/mkdev.h> +#define HAVE_MAJOR +#endif +#ifdef MAJOR_IN_SYSMACROS +#include <sys/sysmacros.h> +#define HAVE_MAJOR +#endif + +#ifdef STAT_MACROS_BROKEN +#undef S_ISCHR +#undef S_ISBLK +#undef S_ISLNK +#endif + +#ifndef S_ISCHR +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif +#ifndef S_ISBLK +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#endif +#if defined(S_IFLNK) && !defined(S_ISLNK) +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif + +/* Get or fake the disk device blocksize. + Usually defined by sys/param.h (if at all). */ +#ifndef DEV_BSIZE +# ifdef BSIZE +# define DEV_BSIZE BSIZE +# else /* !BSIZE */ +# define DEV_BSIZE 4096 +# endif /* !BSIZE */ +#endif /* !DEV_BSIZE */ + +/* Extract or fake data from a `struct stat'. + ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes. + ST_NBLOCKS: Number of blocks in the file, including indirect blocks. + ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */ +#ifndef HAVE_STRUCT_STAT_ST_BLOCKS +# define ST_BLKSIZE(statbuf) DEV_BSIZE +# if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */ +# define ST_NBLOCKS(statbuf) \ + (S_ISREG ((statbuf).st_mode) \ + || S_ISDIR ((statbuf).st_mode) \ + ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0) +# else /* !_POSIX_SOURCE && BSIZE */ +# define ST_NBLOCKS(statbuf) \ + (S_ISREG ((statbuf).st_mode) \ + || S_ISDIR ((statbuf).st_mode) \ + ? st_blocks ((statbuf).st_size) : 0) +# endif /* !_POSIX_SOURCE && BSIZE */ +#else /* HAVE_STRUCT_STAT_ST_BLOCKS */ +/* Some systems, like Sequents, return st_blksize of 0 on pipes. */ +# define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \ + ? (statbuf).st_blksize : DEV_BSIZE) +# if defined(hpux) || defined(__hpux__) || defined(__hpux) +/* HP-UX counts st_blocks in 1024-byte units. + This loses when mixing HP-UX and BSD filesystems with NFS. */ +# define ST_NBLOCKSIZE 1024 +# else /* !hpux */ +# if defined(_AIX) && defined(_I386) +/* AIX PS/2 counts st_blocks in 4K units. */ +# define ST_NBLOCKSIZE (4 * 1024) +# else /* not AIX PS/2 */ +# if defined(_CRAY) +# define ST_NBLOCKS(statbuf) \ + (S_ISREG ((statbuf).st_mode) \ + || S_ISDIR ((statbuf).st_mode) \ + ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0) +# endif /* _CRAY */ +# endif /* not AIX PS/2 */ +# endif /* !hpux */ +#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */ + +#ifndef ST_NBLOCKS +# define ST_NBLOCKS(statbuf) \ + (S_ISREG ((statbuf).st_mode) \ + || S_ISDIR ((statbuf).st_mode) \ + ? (statbuf).st_blocks : 0) +#endif + +#ifndef ST_NBLOCKSIZE +# define ST_NBLOCKSIZE 512 +#endif + +#ifndef _POSIX_VERSION +struct passwd *getpwuid (); +struct group *getgrgid (); +#endif + +#ifdef major /* Might be defined in sys/types.h. */ +#define HAVE_MAJOR +#endif +#ifndef HAVE_MAJOR +#define major(dev) (((dev) >> 8) & 0xff) +#define minor(dev) ((dev) & 0xff) +#endif +#undef HAVE_MAJOR + + +char * get_link_name (char *name, char *relname); +static void print_name_with_quoting (register char *p, FILE *stream); + +extern char * getgroup (gid_t gid); +extern char * getuser (uid_t uid); + + +/* NAME is the name to print. + RELNAME is the path to access it from the current directory. + STATP is the results of stat or lstat on it. + Use CURRENT_TIME to decide whether to print yyyy or hh:mm. + Use OUTPUT_BLOCK_SIZE to determine how to print file block counts + and sizes. + STREAM is the stdio stream to print on. */ + +void +list_file (char *name, + char *relname, + struct stat *statp, + time_t current_time, + int output_block_size, + FILE *stream) +{ + char modebuf[11]; + struct tm const *when_local; + char const *user_name; + char const *group_name; + char hbuf[LONGEST_HUMAN_READABLE + 1]; + +#if HAVE_ST_DM_MODE + /* Cray DMF: look at the file's migrated, not real, status */ + strmode (statp->st_dm_mode, modebuf); +#else + strmode (statp->st_mode, modebuf); +#endif + modebuf[10] = '\0'; + + fprintf (stream, "%6s ", + human_readable ((uintmax_t) statp->st_ino, hbuf, + human_ceiling, + 1, 1)); + + fprintf (stream, "%4s ", + human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf, + human_ceiling, + ST_NBLOCKSIZE, output_block_size)); + + + /* The space between the mode and the number of links is the POSIX + "optional alternate access method flag". */ + fprintf (stream, "%s %3lu ", modebuf, (unsigned long) statp->st_nlink); + + user_name = getuser (statp->st_uid); + if (user_name) + fprintf (stream, "%-8s ", user_name); + else + fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid); + + group_name = getgroup (statp->st_gid); + if (group_name) + fprintf (stream, "%-8s ", group_name); + else + fprintf (stream, "%-8lu ", (unsigned long) statp->st_gid); + + if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode)) +#ifdef HAVE_ST_RDEV + fprintf (stream, "%3lu, %3lu ", + (unsigned long) major (statp->st_rdev), + (unsigned long) minor (statp->st_rdev)); +#else + fprintf (stream, " "); +#endif + else + fprintf (stream, "%8s ", + human_readable ((uintmax_t) statp->st_size, hbuf, + human_ceiling, + 1, + output_block_size < 0 ? output_block_size : 1)); + + if ((when_local = localtime (&statp->st_mtime))) + { + char init_bigbuf[256]; + char *buf = init_bigbuf; + size_t bufsize = sizeof init_bigbuf; + + /* Use strftime rather than ctime, because the former can produce + locale-dependent names for the month (%b). + + Output the year if the file is fairly old or in the future. + POSIX says the cutoff is 6 months old; + approximate this by 6*30 days. + Allow a 1 hour slop factor for what is considered "the future", + to allow for NFS server/client clock disagreement. */ + char const *fmt = + ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime + && statp->st_mtime <= current_time + 60 * 60) + ? "%b %e %H:%M" + : "%b %e %Y"); + + while (!strftime (buf, bufsize, fmt, when_local)) + buf = (char *) alloca (bufsize *= 2); + + fprintf (stream, "%s ", buf); + } + else + { + /* The time cannot be represented as a local time; + print it as a huge integer number of seconds. */ + int width = 12; + + if (statp->st_mtime < 0) + { + char const *num = human_readable (- (uintmax_t) statp->st_mtime, + hbuf, human_ceiling, 1, 1); + int sign_width = width - strlen (num); + fprintf (stream, "%*s%s ", + sign_width < 0 ? 0 : sign_width, "-", num); + } + else + fprintf (stream, "%*s ", width, + human_readable ((uintmax_t) statp->st_mtime, hbuf, + human_ceiling, + 1, 1)); + } + + print_name_with_quoting (name, stream); + +#ifdef S_ISLNK + if (S_ISLNK (statp->st_mode)) + { + char *linkname = get_link_name (name, relname); + + if (linkname) + { + fputs (" -> ", stream); + print_name_with_quoting (linkname, stream); + free (linkname); + } + } +#endif + putc ('\n', stream); +} + +static void +print_name_with_quoting (register char *p, FILE *stream) +{ + register unsigned char c; + + while ((c = *p++) != '\0') + { + switch (c) + { + case '\\': + fprintf (stream, "\\\\"); + break; + + case '\n': + fprintf (stream, "\\n"); + break; + + case '\b': + fprintf (stream, "\\b"); + break; + + case '\r': + fprintf (stream, "\\r"); + break; + + case '\t': + fprintf (stream, "\\t"); + break; + + case '\f': + fprintf (stream, "\\f"); + break; + + case ' ': + fprintf (stream, "\\ "); + break; + + case '"': + fprintf (stream, "\\\""); + break; + + default: + if (c > 040 && c < 0177) + putc (c, stream); + else + fprintf (stream, "\\%03o", (unsigned int) c); + } + } +} + +#ifdef S_ISLNK +char * +get_link_name (char *name, char *relname) +{ + register char *linkname; + register int linklen; + + /* st_size is wrong for symlinks on AIX, and on + mount points with some automounters. + So allocate a pessimistic PATH_MAX + 1 bytes. */ +#define LINK_BUF PATH_MAX + linkname = (char *) xmalloc (LINK_BUF + 1); + linklen = readlink (relname, linkname, LINK_BUF); + if (linklen < 0) + { + error (0, errno, "%s", name); + free (linkname); + return 0; + } + linkname[linklen] = '\0'; + return linkname; +} +#endif diff --git a/lib/listfile.h b/lib/listfile.h new file mode 100644 index 0000000..64d86c5 --- /dev/null +++ b/lib/listfile.h @@ -0,0 +1,28 @@ +/* listfile.h -- display a long listing of a file + Copyright (C) 1991, 1993, 2000 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + + +#if !defined LISTFILE_H +# define LISTFILE_H + +void list_file (char *name, char *relname, struct stat *statp, time_t current_time, int output_block_size, FILE *stream); + + + +#endif diff --git a/lib/modetype.h b/lib/modetype.h new file mode 100644 index 0000000..fb0fc78 --- /dev/null +++ b/lib/modetype.h @@ -0,0 +1,95 @@ +/* modetype.h -- file type bits definitions for POSIX systems + Requires sys/types.h sys/stat.h. + Copyright (C) 1990, 2001, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +/* POSIX.1 doesn't mention the S_IFMT bits; instead, it uses S_IStype + test macros. To make storing file types more convenient, define + them; the values don't need to correspond to what the kernel uses, + because of the way we use them. */ +#ifndef INC_MODETYPE_H +#define INC_MODETYPE_H 1 + +#ifndef S_IFMT /* Doesn't have traditional Unix macros. */ +#define S_IFBLK 1 +#define S_IFCHR 2 +#define S_IFDIR 4 +#define S_IFREG 8 +#ifdef S_ISLNK +#define S_IFLNK 16 +#endif +#ifdef S_ISFIFO +#define S_IFIFO 32 +#endif +#ifdef S_ISSOCK +#define S_IFSOCK 64 +#endif +#ifdef S_ISDOOR +#define S_IFDOOR 128 +#endif +#endif /* !S_IFMT */ + +#ifdef STAT_MACROS_BROKEN +#undef S_ISBLK +#undef S_ISCHR +#undef S_ISDIR +#undef S_ISREG +#undef S_ISFIFO +#undef S_ISLNK +#undef S_ISSOCK +#undef S_ISDOOR +#undef S_ISMPB +#undef S_ISMPC +#undef S_ISNWK +#endif + +/* Do the reverse: define the POSIX.1 macros for traditional Unix systems + that don't have them. */ +#if !defined(S_ISBLK) && defined(S_IFBLK) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#endif +#if !defined(S_ISCHR) && defined(S_IFCHR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISDIR) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISFIFO) && defined(S_IFIFO) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISLNK) && defined(S_IFLNK) +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) && defined(S_IFSOCK) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISDOOR) && defined(S_IFDOOR) +#define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) +#endif +#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ +#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +#endif +#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ +#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +#endif + +#endif diff --git a/lib/nextelem.c b/lib/nextelem.c new file mode 100644 index 0000000..951b634 --- /dev/null +++ b/lib/nextelem.c @@ -0,0 +1,110 @@ +/* Return the next element of a path. + Copyright (C) 1992, 2003, 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +/* Written by David MacKenzie <djm@gnu.org>, + inspired by John P. Rouillard <rouilj@cs.umb.edu>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) +#include <string.h> +#else +#include <strings.h> +#ifndef strchr +#define strchr index +#endif +#endif +#if defined(STDC_HEADERS) +#include <stdlib.h> +#endif + +#include "nextelem.h" + + +/* Return the next element of a colon-separated path. + A null entry in the path is equivalent to "." (the current directory). + + If NEW_PATH is non-NULL, set the path and return NULL. + If NEW_PATH is NULL, return the next item in the string, or + return NULL if there are no more elements. */ + +char * +next_element (const char *new_path, int curdir_ok) +{ + static char *path = NULL; /* Freshly allocated copy of NEW_PATH. */ + static char *end; /* Start of next element to return. */ + static int final_colon; /* If zero, path didn't end with a colon. */ + char *start; /* Start of path element to return. */ + + if (new_path) + { + if (path) + free (path); + end = path = strdup (new_path); + final_colon = 0; + return NULL; + } + + if (*end == '\0') + { + if (final_colon) + { + final_colon = 0; + return curdir_ok ? "." : ""; + } + return NULL; + } + + start = end; + final_colon = 1; /* Maybe there will be one. */ + + end = strchr (start, ':'); + if (end == start) + { + /* An empty path element. */ + *end++ = '\0'; + return curdir_ok ? "." : ""; + } + else if (end == NULL) + { + /* The last path element. */ + end = strchr (start, '\0'); + final_colon = 0; + } + else + *end++ = '\0'; + + return start; +} + +#ifdef TEST +int +main () +{ + char *p; + + next_element (getenv ("PATH")); + while (p = next_element (NULL)) + puts (p); + exit (0); +} +#endif /* TEST */ diff --git a/lib/nextelem.h b/lib/nextelem.h new file mode 100644 index 0000000..afd36fd --- /dev/null +++ b/lib/nextelem.h @@ -0,0 +1,28 @@ +/* Return the next element of a path. + Copyright (C) 1992, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +/* Written by David MacKenzie <djm@gnu.org>, + inspired by John P. Rouillard <rouilj@cs.umb.edu>. */ + +#ifndef INC_NEXTELEM_H +#define INC_NEXTELEM_H 1 + +char *next_element (const char *path, int curdir_ok); + +#endif diff --git a/lib/printquoted.c b/lib/printquoted.c new file mode 100644 index 0000000..a054825 --- /dev/null +++ b/lib/printquoted.c @@ -0,0 +1,87 @@ +/* printquoted.c -- print a specified string with any necessary quoting. + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, + 2003, 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#if HAVE_WCHAR_H +# include <wchar.h> +#endif + + + +#include "xalloc.h" +#include "printquoted.h" + + +/* + * Print S according to the format FORMAT, but if the destination is a tty, + * convert any potentially-dangerous characters. The logic in this function + * was taken from ls.c in coreutils (at Sun Jun 5 20:42:51 2005 UTC). + */ +void +print_quoted (FILE *fp, + const struct quoting_options *qopts, + bool dest_is_tty, + const char *format, + const char *s) +{ + if (dest_is_tty) + { + char smallbuf[BUFSIZ]; + size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, s, -1, qopts); + char *buf; + if (len < sizeof smallbuf) + buf = smallbuf; + else + { + /* The original coreutils code uses alloca(), but I don't + * want to take on the anguish of introducing alloca() to + * 'find'. + */ + buf = xmalloc (len + 1); + quotearg_buffer (buf, len + 1, s, -1, qopts); + } + + /* Replace any remaining funny characters with '?'. */ + len = qmark_chars(buf, len); + + fprintf(fp, format, buf); /* Print the quoted version */ + if (buf != smallbuf) + { + free(buf); + buf = NULL; + } + } + else + { + /* no need to quote things. */ + fprintf(fp, format, s); + } + +} + diff --git a/lib/printquoted.h b/lib/printquoted.h new file mode 100644 index 0000000..7381aa0 --- /dev/null +++ b/lib/printquoted.h @@ -0,0 +1,35 @@ +/* Print a string, appropriately quoted. + + Copyright 1997, 1999, 2001, 2003, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if !defined PRINTQUOTED_H +# define PRINTQUOTED_H + +#include "quote.h" +#include "quotearg.h" + + +#include <stdbool.h> +#include <stdio.h> + + +size_t qmark_chars(char *buf, size_t len); +void print_quoted (FILE *fp, const struct quoting_options *qopts, bool dest_is_tty, const char *format, const char *s); + + +#endif diff --git a/lib/qmark.c b/lib/qmark.c new file mode 100644 index 0000000..dbc9dcb --- /dev/null +++ b/lib/qmark.c @@ -0,0 +1,239 @@ +/* pred.c -- execute the expression tree. + Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, + 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +# include <stddef.h> +# include <stdlib.h> +#include <ctype.h> + +#if HAVE_STRING_H || STDC_HEADERS +#include <string.h> +#else +#include <strings.h> +#endif + + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#if HAVE_WCHAR_H +# include <wchar.h> +#endif + +#include "printquoted.h" + + +/* + This comment, IN_CTYPE_DOMAIN and ISPRINT were borrowed from + coreutils at Sun Jun 5 21:17:40 2005 UTC. + + Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." + + Bruno Haible adds: + + "... Furthermore, isupper(c) etc. have an undefined result if c is + outside the range -1 <= c <= 255. One is tempted to write isupper(c) + with c being of type `char', but this is wrong if c is an 8-bit + character >= 128 which gets sign-extended to a negative value. + The macro ISUPPER protects against this as well." */ + + + + +/* ISPRINT is defined in <sys/euc.h> on at least Solaris2.6 systems. */ +#undef ISPRINT +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) + +#if STDC_HEADERS || (!defined (isascii) && !HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif + + + + + +/* Convert a possibly-signed character to an unsigned character. This is + * a bit safer than casting to unsigned char, since it catches some type + * errors that the cast doesn't. + * + * This code taken from coreutils' system.h header at + * Sun Jun 5 21:05:21 2005 UTC. + */ +static inline unsigned char to_uchar (char ch) +{ + return ch; +} + + + +static size_t +unibyte_qmark_chars(char *buf, size_t len) +{ + char *p = buf; + char const *plimit = buf + len; + + while (p < plimit) + { + if (! ISPRINT (to_uchar (*p))) + *p = '?'; + p++; + } + return len; +} + + +#if HAVE_MBRTOWC +static size_t +multibyte_qmark_chars(char *buf, size_t len) +{ + if (MB_CUR_MAX <= 1) + { + return unibyte_qmark_chars(buf, len); + } + else + { + char const *p = buf; + char const *plimit = buf + len; + char *q = buf; + + while (p < plimit) + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + *q++ = *p++; + break; + default: + /* If we have a multibyte sequence, copy it until we + reach its end, replacing each non-printable multibyte + character with a single question mark. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + { + /* An invalid multibyte sequence was + encountered. Skip one input byte, and + put a question mark. */ + p++; + *q++ = '?'; + break; + } + + if (bytes == (size_t) -2) + { + /* An incomplete multibyte character + at the end. Replace it entirely with + a question mark. */ + p = plimit; + *q++ = '?'; + break; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + { + /* A printable multibyte character. + Keep it. */ + for (; bytes > 0; --bytes) + *q++ = *p++; + } + else + { + /* An unprintable multibyte character. + Replace it entirely with a question + mark. */ + p += bytes; + *q++ = '?'; + } + } + while (! mbsinit (&mbstate)); + } + break; + } + + /* The buffer may have shrunk. */ + len = q - buf; + return len; + } +} +#endif + + +/* Scan BUF, replacing any dangerous-looking characters with question + * marks. This code is taken from the ls.c file in coreutils as at + * Sun Jun 5 20:51:54 2005 UTC. + * + * This function may shrink the buffer. Either way, the new length + * is returned. + */ +size_t +qmark_chars(char *buf, size_t len) +{ +#if HAVE_MBRTOWC + return multibyte_qmark_chars(buf, len); +#else + return unibyte_qmark_chars(buf, len); +#endif +} + diff --git a/lib/regexprops.c b/lib/regexprops.c new file mode 100644 index 0000000..74f49b1 --- /dev/null +++ b/lib/regexprops.c @@ -0,0 +1,505 @@ +/* regexprops.c -- document the properties of the regular expressions + understood by gnulib. + + Copyright 2005, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Youngman, <jay@gnu.org>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "regex.h" +#include "regextype.h" + + +/* Name this program was run with. */ +char *program_name; + +static void output(const char *s, int escape) +{ + fputs(s, stdout); +} + + +static void newline(void) +{ + output("\n", 0); +} + +static void content(const char *s) +{ + output(s, 1); +} + +static void literal(const char *s) +{ + output(s, 0); +} + +static void directive(const char *s) +{ + output(s, 0); +} + +static void enum_item(const char *s) +{ + newline(); + directive("@item "); + literal(s); + newline(); +} +static void table_item(const char *s) +{ + directive("@item"); + newline(); + content(s); + newline(); +} + +static void code(const char *s) +{ + directive("@code{"); + content(s); + directive("}"); +} + +static void begin_subsection(const char *name, + const char *next, + const char *prev, + const char *up) +{ + newline(); + + directive("@node "); + content(name); + content(" regular expression syntax"); + newline(); + + directive("@subsection "); + output("@samp{", 0); + content(name); + output("}", 0); + content(" regular expression syntax"); + newline(); +} + +static void begintable_asis() +{ + newline(); + directive("@table @asis"); + newline(); +} + +static void begintable_markup(char const *markup) +{ + newline(); + directive("@table "); + literal(markup); + newline(); +} + +static void endtable() +{ + newline(); + directive("@end table"); + newline(); +} + +static void beginenum() +{ + newline(); + directive("@enumerate"); + newline(); +} + +static void endenum() +{ + newline(); + directive("@end enumerate"); + newline(); +} + +static void newpara() +{ + content("\n\n"); +} + + +static int describe_regex_syntax(int options) +{ + newpara(); + content("The character @samp{.} matches any single character"); + if ( (options & RE_DOT_NEWLINE) == 0 ) + { + content(" except newline"); + } + if (options & RE_DOT_NOT_NULL) + { + if ( (options & RE_DOT_NEWLINE) == 0 ) + content(" and"); + else + content(" except"); + + content(" the null character"); + } + content(". "); + newpara(); + + if (!(options & RE_LIMITED_OPS)) + { + begintable_markup("@samp"); + if (options & RE_BK_PLUS_QM) + { + enum_item("\\+"); + content("indicates that the regular expression should match one" + " or more occurrences of the previous atom or regexp. "); + enum_item("\\?"); + content("indicates that the regular expression should match zero" + " or one occurrence of the previous atom or regexp. "); + enum_item("+ and ? "); + content("match themselves. "); + } + else + { + enum_item("+"); + content("indicates that the regular expression should match one" + " or more occurrences of the previous atom or regexp. "); + enum_item("?"); + content("indicates that the regular expression should match zero" + " or one occurrence of the previous atom or regexp. "); + enum_item("\\+"); + literal("matches a @samp{+}"); + enum_item("\\?"); + literal("matches a @samp{?}. "); + } + endtable(); + } + + newpara(); + + content("Bracket expressions are used to match ranges of characters. "); + literal("Bracket expressions where the range is backward, for example @samp{[z-a]}, are "); + if (options & RE_NO_EMPTY_RANGES) + content("invalid"); + else + content("ignored"); + content(". "); + + if (options & RE_BACKSLASH_ESCAPE_IN_LISTS) + literal("Within square brackets, @samp{\\} can be used to quote " + "the following character. "); + else + literal("Within square brackets, @samp{\\} is taken literally. "); + + if (options & RE_CHAR_CLASSES) + content("Character classes are supported; for example " + "@samp{[[:digit:]]} will match a single decimal digit. "); + else + literal("Character classes are not supported, so for example " + "you would need to use @samp{[0-9]} " + "instead of @samp{[[:digit:]]}. "); + + if (options & RE_HAT_LISTS_NOT_NEWLINE) + { + literal("Non-matching lists @samp{[^@dots{}]} do not ever match newline. "); + } + newpara(); + if (options & RE_NO_GNU_OPS) + { + content("GNU extensions are not supported and so " + "@samp{\\w}, @samp{\\W}, @samp{\\<}, @samp{\\>}, @samp{\\b}, @samp{\\B}, @samp{\\`}, and @samp{\\'} " + "match " + "@samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively. "); + } + else + { + content("GNU extensions are supported:"); + beginenum(); + enum_item("@samp{\\w} matches a character within a word"); + enum_item("@samp{\\W} matches a character which is not within a word"); + enum_item("@samp{\\<} matches the beginning of a word"); + enum_item("@samp{\\>} matches the end of a word"); + enum_item("@samp{\\b} matches a word boundary"); + enum_item("@samp{\\B} matches characters which are not a word boundary"); + enum_item("@samp{\\`} matches the beginning of the whole input"); + enum_item("@samp{\\'} matches the end of the whole input"); + endenum(); + } + + newpara(); + + + if (options & RE_NO_BK_PARENS) + { + literal("Grouping is performed with parentheses @samp{()}. "); + + if (options & RE_UNMATCHED_RIGHT_PAREN_ORD) + literal("An unmatched @samp{)} matches just itself. "); + } + else + { + literal("Grouping is performed with backslashes followed by parentheses @samp{\\(}, @samp{\\)}. "); + } + + if (options & RE_NO_BK_REFS) + { + content("A backslash followed by a digit matches that digit. "); + } + else + { + literal("A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis "); + if (options & RE_NO_BK_PARENS) + literal("@samp{(}"); + else + literal("@samp{\\(}"); + content(". "); + } + + + newpara(); + if (!(options & RE_LIMITED_OPS)) + { + if (options & RE_NO_BK_VBAR) + literal("The alternation operator is @samp{|}. "); + else + literal("The alternation operator is @samp{\\|}. "); + } + newpara(); + + if (options & RE_CONTEXT_INDEP_ANCHORS) + { + literal("The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. "); + } + else + { + literal("The character @samp{^} only represents the beginning of a string when it appears:"); + beginenum(); + enum_item("\nAt the beginning of a regular expression"); + enum_item("After an open-group, signified by "); + if (options & RE_NO_BK_PARENS) + { + literal("@samp{(}"); + } + else + { + literal("@samp{\\(}"); + } + newline(); + if (!(options & RE_LIMITED_OPS)) + { + if (options & RE_NEWLINE_ALT) + enum_item("After a newline"); + + if (options & RE_NO_BK_VBAR ) + enum_item("After the alternation operator @samp{|}"); + else + enum_item("After the alternation operator @samp{\\|}"); + } + endenum(); + + newpara(); + literal("The character @samp{$} only represents the end of a string when it appears:"); + beginenum(); + enum_item("At the end of a regular expression"); + enum_item("Before a close-group, signified by "); + if (options & RE_NO_BK_PARENS) + { + literal("@samp{)}"); + } + else + { + literal("@samp{\\)}"); + } + if (!(options & RE_LIMITED_OPS)) + { + if (options & RE_NEWLINE_ALT) + enum_item("Before a newline"); + + if (options & RE_NO_BK_VBAR) + enum_item("Before the alternation operator @samp{|}"); + else + enum_item("Before the alternation operator @samp{\\|}"); + } + endenum(); + } + newpara(); + if (!(options & RE_LIMITED_OPS) ) + { + if ((options & RE_CONTEXT_INDEP_OPS) + && !(options & RE_CONTEXT_INVALID_OPS)) + { + literal("The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression. "); + } + else + { + if (options & RE_BK_PLUS_QM) + literal("@samp{\\*}, @samp{\\+} and @samp{\\?} "); + else + literal("@samp{*}, @samp{+} and @samp{?} "); + + if (options & RE_CONTEXT_INVALID_OPS) + { + content("are special at any point in a regular expression except the following places, where they are not allowed:"); + } + else + { + content("are special at any point in a regular expression except:"); + } + + beginenum(); + enum_item("At the beginning of a regular expression"); + enum_item("After an open-group, signified by "); + if (options & RE_NO_BK_PARENS) + { + literal("@samp{(}"); + } + else + { + literal("@samp{\\(}"); + } + if (!(options & RE_LIMITED_OPS)) + { + if (options & RE_NEWLINE_ALT) + enum_item("After a newline"); + + if (options & RE_NO_BK_VBAR) + enum_item("After the alternation operator @samp{|}"); + else + enum_item("After the alternation operator @samp{\\|}"); + } + endenum(); + } + } + + + newpara(); + if (options & RE_INTERVALS) + { + if (options & RE_NO_BK_BRACES) + { + literal("Intervals are specified by @samp{@{} and @samp{@}}. "); + if (options & RE_INVALID_INTERVAL_ORD) + { + literal("Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\\@{1}"); + } + else + { + literal("Invalid intervals such as @samp{a@{1z} are not accepted. "); + } + } + else + { + literal("Intervals are specified by @samp{\\@{} and @samp{\\@}}. "); + if (options & RE_INVALID_INTERVAL_ORD) + { + literal("Invalid intervals are treated as literals, for example @samp{a\\@{1} is treated as @samp{a@{1}"); + } + else + { + literal("Invalid intervals such as @samp{a\\@{1z} are not accepted. "); + } + } + + } + + newpara(); + if (options & RE_NO_POSIX_BACKTRACKING) + { + content("Matching succeeds as soon as the whole pattern is matched, meaning that the result may not be the longest possible match. "); + } + else + { + content("The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. "); + } + newpara(); +} + + + +static int menu() +{ + int i, options; + const char *name; + + output("@menu\n", 0); + for (i=0; + options = get_regex_type_flags(i), + name=get_regex_type_name(i); + ++i) + { + output("* ", 0); + output(name, 0); + content(" regular expression syntax"); + output("::", 0); + newline(); + } + output("@end menu\n", 0); +} + + +static int describe_all(const char *up) +{ + const char *name, *next, *previous; + int options; + int i, parent; + + menu(); + + previous = ""; + + for (i=0; + options = get_regex_type_flags(i), + name=get_regex_type_name(i); + ++i) + { + next = get_regex_type_name(i+1); + if (NULL == next) + next = ""; + begin_subsection(name, next, previous, up); + parent = get_regex_type_synonym(i); + if (parent >= 0) + { + content("This is a synonym for "); + content(get_regex_type_name(parent)); + content("."); + } + else + { + describe_regex_syntax(options); + } + previous = name; + } +} + + + +int main (int argc, char *argv[]) +{ + const char *up = ""; + program_name = argv[0]; + + if (argc > 1) + up = argv[1]; + + describe_all(up); + return 0; +} diff --git a/lib/regextype.c b/lib/regextype.c new file mode 100644 index 0000000..9aaa6c6 --- /dev/null +++ b/lib/regextype.c @@ -0,0 +1,158 @@ + +/* regextype.c -- Decode the name of a regular expression syntax into am + option name. + + Copyright 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Youngman, <jay@gnu.org>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include <stdio.h> + +#include "regextype.h" +#include "regex.h" +#include "quote.h" +#include "quotearg.h" +#include "xalloc.h" +#include "error.h" + + +#if ENABLE_NLS +# include <libintl.h> +# define _(Text) gettext (Text) +#else +# define _(Text) Text +#endif +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +/* See locate.c for explanation as to why not use (String) */ +# define N_(String) String +#endif + + + +struct tagRegexTypeMap +{ + char *name; + int option_val; +}; + +struct tagRegexTypeMap regex_map[] = + { +#ifdef FINDUTILS + { "findutils-default", RE_SYNTAX_EMACS|RE_DOT_NEWLINE }, +#endif + { "awk", RE_SYNTAX_AWK }, + { "egrep", RE_SYNTAX_EGREP }, +#ifndef FINDUTILS + { "ed", RE_SYNTAX_ED }, +#endif + { "emacs", RE_SYNTAX_EMACS }, + { "gnu-awk", RE_SYNTAX_GNU_AWK }, + { "grep", RE_SYNTAX_GREP }, + { "posix-awk", RE_SYNTAX_POSIX_AWK }, + { "posix-basic", RE_SYNTAX_POSIX_BASIC }, + { "posix-egrep", RE_SYNTAX_POSIX_EGREP }, + { "posix-extended", RE_SYNTAX_POSIX_EXTENDED }, +#ifndef FINDUTILS + { "posix-minimal-basic", RE_SYNTAX_POSIX_MINIMAL_BASIC }, + { "sed", RE_SYNTAX_SED }, + /* ,{ "posix-common", _RE_SYNTAX_POSIX_COMMON } */ +#endif + }; +enum { N_REGEX_MAP_ENTRIES = sizeof(regex_map)/sizeof(regex_map[0]) }; + +int +get_regex_type(const char *s) +{ + unsigned i; + size_t msglen; + char *buf, *p; + + msglen = 0u; + for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i) + { + if (0 == strcmp(regex_map[i].name, s)) + return regex_map[i].option_val; + else + msglen += strlen(quote(regex_map[i].name)) + 2u; + } + + /* We didn't find a match for the type of regular expression that the + * user indicated they wanted. Tell them what the options are. + */ + p = buf = xmalloc(1u + msglen); + for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i) + { + if (i > 0u) + { + strcpy(p, ", "); + p += 2; + } + p += sprintf(p, "%s", quote(regex_map[i].name)); + } + + error(1, 0, _("Unknown regular expression type %s; valid types are %s."), + quote(s), + buf); + /*NOTREACHED*/ + return -1; +} + + +const char * +get_regex_type_name(int ix) +{ + if (ix < N_REGEX_MAP_ENTRIES) + return regex_map[ix].name; + else + return NULL; +} + +int +get_regex_type_flags(int ix) +{ + if (ix < N_REGEX_MAP_ENTRIES) + return regex_map[ix].option_val; + else + return -1; +} + + +int get_regex_type_synonym(int ix) +{ + unsigned i; + int flags; + + if (ix >= N_REGEX_MAP_ENTRIES) + return -1; + + flags = regex_map[ix].option_val; + for (i=0u; i<ix; ++i) + { + if (flags == regex_map[i].option_val) + { + return i; + } + } + return -1; +} diff --git a/lib/regextype.h b/lib/regextype.h new file mode 100644 index 0000000..e28815f --- /dev/null +++ b/lib/regextype.h @@ -0,0 +1,28 @@ +/* regextype.h -- Decode the name of a regular expression syntax into am + option name. + + Copyright 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Youngman <jay@gnu.org>. + */ + +int get_regex_type(const char *s); + + +const char * get_regex_type_name(int ix); +int get_regex_type_flags(int ix); +int get_regex_type_synonym(int ix); diff --git a/lib/savedirinfo.c b/lib/savedirinfo.c new file mode 100644 index 0000000..92d0639 --- /dev/null +++ b/lib/savedirinfo.c @@ -0,0 +1,387 @@ +/* savedirinfo.c -- Save the list of files in a directory, with additional information. + + Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Youngman, <jay@gnu.org>. */ +/* Derived from savedir.c, written by David MacKenzie <djm@gnu.org>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif + +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +/* The presence of unistd.h is assumed by gnulib these days, so we + * might as well assume it too. + */ +#include <unistd.h> + +#include <errno.h> + +#if HAVE_DIRENT_H +# include <dirent.h> +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#ifdef CLOSEDIR_VOID +/* Fake a return value. */ +# define CLOSEDIR(d) (closedir (d), 0) +#else +# define CLOSEDIR(d) closedir (d) +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "xalloc.h" +#include "extendbuf.h" +#include "savedirinfo.h" + +/* In order to use struct dirent.d_type, it has to be enabled on the + * configure command line, and we have to have a d_type member in + * 'struct dirent'. + */ +#if !defined(USE_STRUCT_DIRENT_D_TYPE) +/* Not enabled, hence pretend it is absent. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE +#endif +#if !defined(HAVE_STRUCT_DIRENT_D_TYPE) +/* Not present, so cannot use it. */ +#undef USE_STRUCT_DIRENT_D_TYPE +#endif + + +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) +/* Convert the value of struct dirent.d_type into a value for + * struct stat.st_mode (at least the file type bits), or zero + * if the type is DT_UNKNOWN or is a value we don't know about. + */ +static mode_t +type_to_mode(unsigned type) +{ + switch (type) + { +#ifdef DT_FIFO + case DT_FIFO: return S_IFIFO; +#endif +#ifdef DT_CHR + case DT_CHR: return S_IFCHR; +#endif +#ifdef DT_DIR + case DT_DIR: return S_IFDIR; +#endif +#ifdef DT_BLK + case DT_BLK: return S_IFBLK; +#endif +#ifdef DT_REG + case DT_REG: return S_IFREG; +#endif +#ifdef DT_LNK + case DT_LNK: return S_IFLNK; +#endif +#ifdef DT_SOCK + case DT_SOCK: return S_IFSOCK; +#endif + default: + return 0; /* Unknown. */ + } +} + +#endif + +struct new_savedir_direntry_internal +{ + int flags; /* from SaveDirDataFlags */ + mode_t type_info; + size_t buffer_offset; +}; + + + +static int +savedir_cmp(const void *p1, const void *p2) +{ + const struct savedir_direntry *de1, *de2; + de1 = p1; + de2 = p2; + return strcmp(de1->name, de2->name); /* POSIX order, not locale order. */ +} + + +static struct savedir_direntry* +convertentries(const struct savedir_dirinfo *info, + struct new_savedir_direntry_internal *internal) +{ + char *p = info->buffer; + struct savedir_direntry *result; + int n =info->size; + int i; + + + result = xmalloc(sizeof(*result) * info->size); + + for (i=0; i<n; ++i) + { + result[i].flags = internal[i].flags; + result[i].type_info = internal[i].type_info; + result[i].name = &p[internal[i].buffer_offset]; + } + return result; +} + + +struct savedir_dirinfo * +xsavedir(const char *dir, int flags) +{ + DIR *dirp; + struct dirent *dp; + struct savedir_dirinfo *result = NULL; + struct new_savedir_direntry_internal *internal; + + size_t namebuf_allocated = 0u, namebuf_used = 0u; + size_t entrybuf_allocated = 0u; + int save_errno; + + dirp = opendir (dir); + if (dirp == NULL) + return NULL; + + errno = 0; + result = xmalloc(sizeof(*result)); + result->buffer = NULL; + result->size = 0u; + result->entries = NULL; + internal = NULL; + + while ((dp = readdir (dirp)) != NULL) + { + /* Skip "", ".", and "..". "" is returned by at least one buggy + implementation: Solaris 2.4 readdir on NFS file systems. */ + char const *entry = dp->d_name; + if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') + { + /* Remember the name. */ + size_t entry_size = strlen (entry) + 1; + result->buffer = extendbuf(result->buffer, namebuf_used+entry_size, &namebuf_allocated); + memcpy ((result->buffer) + namebuf_used, entry, entry_size); + + /* Remember the other stuff. */ + internal = extendbuf(internal, (1+result->size)*sizeof(*internal), &entrybuf_allocated); + internal[result->size].flags = 0; + +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) + internal[result->size].type_info = type_to_mode(dp->d_type); + if (dp->d_type != DT_UNKNOWN) + internal[result->size].flags |= SavedirHaveFileType; +#else + internal[result->size].type_info = 0; +#endif + internal[result->size].buffer_offset = namebuf_used; + + /* Prepare for the next iteration */ + ++(result->size); + namebuf_used += entry_size; + } + } + + result->buffer = extendbuf(result->buffer, namebuf_used+1, &namebuf_allocated); + result->buffer[namebuf_used] = '\0'; + + /* convert the result to its externally-usable form. */ + result->entries = convertentries(result, internal); + free(internal); + internal = NULL; + + + if (flags & SavedirSort) + { + qsort(result->entries, + result->size, sizeof(*result->entries), + savedir_cmp); + } + + + save_errno = errno; + if (CLOSEDIR (dirp) != 0) + save_errno = errno; + if (save_errno != 0) + { + free (result->buffer); + free (result); + errno = save_errno; + return NULL; + } + + return result; +} + +void free_dirinfo(struct savedir_dirinfo *p) +{ + free(p->entries); + p->entries = NULL; + free(p->buffer); + p->buffer = NULL; + free(p); +} + + + +static char * +new_savedirinfo (const char *dir, struct savedir_extrainfo **extra) +{ + struct savedir_dirinfo *p = xsavedir(dir, SavedirSort); + char *buf, *s; + size_t bufbytes = 0; + int i; + + if (p) + { + struct savedir_extrainfo *pex = xmalloc(p->size * sizeof(*extra)); + for (i=0; i<p->size; ++i) + { + bufbytes += strlen(p->entries[i].name); + ++bufbytes; /* the \0 */ + + pex[i].type_info = p->entries[i].type_info; + } + + s = buf = xmalloc(bufbytes+1); + for (i=0; i<p->size; ++i) + { + size_t len = strlen(p->entries[i].name); + memcpy(s, p->entries[i].name, len); + s += len; + *s = 0; /* Place a NUL */ + ++s; /* Skip the NUL. */ + } + *s = 0; /* final (doubled) terminating NUL */ + + if (extra) + *extra = pex; + else + free (pex); + return buf; + } + else + { + return NULL; + } +} + + +#if 0 +/* Return a freshly allocated string containing the filenames + in directory DIR, separated by '\0' characters; + the end is marked by two '\0' characters in a row. + Return NULL (setting errno) if DIR cannot be opened, read, or closed. */ + +static char * +old_savedirinfo (const char *dir, struct savedir_extrainfo **extra) +{ + DIR *dirp; + struct dirent *dp; + char *name_space; + size_t namebuf_allocated = 0u, namebuf_used = 0u; +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) + size_t extra_allocated = 0u, extra_used = 0u; + struct savedir_extrainfo *info = NULL; +#endif + int save_errno; + + if (extra) + *extra = NULL; + + dirp = opendir (dir); + if (dirp == NULL) + return NULL; + + errno = 0; + name_space = NULL; + while ((dp = readdir (dirp)) != NULL) + { + /* Skip "", ".", and "..". "" is returned by at least one buggy + implementation: Solaris 2.4 readdir on NFS file systems. */ + char const *entry = dp->d_name; + if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') + { + /* Remember the name. */ + size_t entry_size = strlen (entry) + 1; + name_space = extendbuf(name_space, namebuf_used+entry_size, &namebuf_allocated); + memcpy (name_space + namebuf_used, entry, entry_size); + namebuf_used += entry_size; + + +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) + /* Remember the type. */ + if (extra) + { + info = extendbuf(info, + (extra_used+1) * sizeof(struct savedir_dirinfo), + &extra_allocated); + info[extra_used].type_info = type_to_mode(dp->d_type); + ++extra_used; + } +#endif + } + } + + name_space = extendbuf(name_space, namebuf_used+1, &namebuf_allocated); + name_space[namebuf_used] = '\0'; + + save_errno = errno; + if (CLOSEDIR (dirp) != 0) + save_errno = errno; + if (save_errno != 0) + { + free (name_space); + errno = save_errno; + return NULL; + } + +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) + if (extra && info) + *extra = info; +#endif + + return name_space; +} +#endif + + +char * +savedirinfo (const char *dir, struct savedir_extrainfo **extra) +{ + return new_savedirinfo(dir, extra); +} diff --git a/lib/savedirinfo.h b/lib/savedirinfo.h new file mode 100644 index 0000000..365f144 --- /dev/null +++ b/lib/savedirinfo.h @@ -0,0 +1,73 @@ +/* Save the list of files in a directory, with additional information. + + Copyright 1997, 1999, 2001, 2003, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by James Youngman <jay@gnu.org>. + * Based on savedir.h by David MacKenzie <djm@gnu.org>. + */ + +#if !defined SAVEDIRINFO_H_ +# define SAVEDIRINFO_H_ + + +typedef enum tagSaveDirControlFlags + { + SavedirSort = 1 + } +SaveDirControlFlags; + + +typedef enum tagSaveDirDataFlags + { + SavedirHaveFileType = 1 + } +SaveDirDataFlags; + + +/* We keep the name and the type in a structure together + * to allow us to sort them together. + */ +struct savedir_direntry +{ + int flags; /* from SaveDirDataFlags */ + char *name; /* the name of the directory entry */ + mode_t type_info; /* the type (or zero if unknown) */ +}; + +struct savedir_dirinfo +{ + char *buffer; /* The names are stored here. */ + size_t size; /* The total number of results. */ + struct savedir_direntry *entries; /* The results themselves */ +}; + + +struct savedir_extrainfo +{ + mode_t type_info; +}; + +/* savedirinfo() is the old interface. */ +char *savedirinfo (const char *dir, struct savedir_extrainfo **extra); + +/* savedir() is the 'new' interface, but the function has the same name + * as the function from findutils 4.1.7 and 4.1.20. + */ +struct savedir_dirinfo * xsavedir(const char *dir, int flags); +void free_dirinfo(struct savedir_dirinfo *p); + +#endif diff --git a/lib/wait.h b/lib/wait.h new file mode 100644 index 0000000..a7b0803 --- /dev/null +++ b/lib/wait.h @@ -0,0 +1,41 @@ +/* wait.h -- POSIX macros for evaluating exit statuses + Copyright (C) 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include <sys/types.h> /* For pid_t. */ +#if HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifndef WIFSTOPPED +#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0) +#endif +#ifndef WIFEXITED +#define WIFEXITED(w) (((w) & 0xff) == 0) +#endif + +#ifndef WSTOPSIG +#define WSTOPSIG(w) (((w) >> 8) & 0xff) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0x7f) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) >> 8) & 0xff) +#endif diff --git a/lib/waitpid.c b/lib/waitpid.c new file mode 100644 index 0000000..b7984c0 --- /dev/null +++ b/lib/waitpid.c @@ -0,0 +1,81 @@ +/* Emulate waitpid on systems that just have wait. + Copyright 1994, 1995, 1998, 1999, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#ifndef errno +extern int errno; +#endif + + +#if defined _MSC_VER || defined __MINGW32__ +/* Native Woe32 API. */ +#include <process.h> +#else +/* Unix API. */ +#include "wait.h" +#endif + +#define WAITPID_CHILDREN 8 +static pid_t waited_pid[WAITPID_CHILDREN]; +static int waited_status[WAITPID_CHILDREN]; + +pid_t +waitpid (pid_t pid, int *stat_loc, int options) +{ + int i; + pid_t p; + + if (!options && (pid == -1 || 0 < pid)) + { + /* If we have already waited for this child, return it immediately. */ + for (i = 0; i < WAITPID_CHILDREN; i++) + { + p = waited_pid[i]; + if (p && (p == pid || pid == -1)) + { + waited_pid[i] = 0; + goto success; + } + } + + /* The child has not returned yet; wait for it, accumulating status. */ + for (i = 0; i < WAITPID_CHILDREN; i++) + if (! waited_pid[i]) + { + p = wait (&waited_status[i]); + if (p < 0) + return p; + if (p == pid || pid == -1) + goto success; + waited_pid[i] = p; + } + } + + /* We cannot emulate this wait call, e.g. because of too many children. */ + errno = EINVAL; + return -1; + +success: + if (stat_loc) + *stat_loc = waited_status[i]; + return p; +} |