summaryrefslogtreecommitdiff
path: root/text-utils
diff options
context:
space:
mode:
Diffstat (limited to 'text-utils')
-rw-r--r--text-utils/LICENSE.pg28
-rw-r--r--text-utils/Makefile.am33
-rw-r--r--text-utils/Makefile.in802
-rw-r--r--text-utils/README.clear7
-rw-r--r--text-utils/README.col48
-rw-r--r--text-utils/README.pg23
-rw-r--r--text-utils/col.1141
-rw-r--r--text-utils/col.c559
-rw-r--r--text-utils/colcrt.1111
-rw-r--r--text-utils/colcrt.c286
-rw-r--r--text-utils/colrm.166
-rw-r--r--text-utils/colrm.c140
-rw-r--r--text-utils/column.1102
-rw-r--r--text-utils/column.c376
-rw-r--r--text-utils/conv.c119
-rw-r--r--text-utils/display.c369
-rw-r--r--text-utils/hexdump.1342
-rw-r--r--text-utils/hexdump.c76
-rw-r--r--text-utils/hexdump.h96
-rw-r--r--text-utils/hexsyntax.c133
-rw-r--r--text-utils/line.117
-rw-r--r--text-utils/line.c38
-rw-r--r--text-utils/more.1205
-rw-r--r--text-utils/more.c2126
-rw-r--r--text-utils/odsyntax.c265
-rw-r--r--text-utils/parse.c504
-rw-r--r--text-utils/pg.1237
-rw-r--r--text-utils/pg.c1768
-rw-r--r--text-utils/rev.153
-rw-r--r--text-utils/rev.c145
-rw-r--r--text-utils/tailf.161
-rw-r--r--text-utils/tailf.c227
-rw-r--r--text-utils/ul.1110
-rw-r--r--text-utils/ul.c603
34 files changed, 10216 insertions, 0 deletions
diff --git a/text-utils/LICENSE.pg b/text-utils/LICENSE.pg
new file mode 100644
index 0000000..e805a31
--- /dev/null
+++ b/text-utils/LICENSE.pg
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2000-2001 Gunnar Ritter. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [deleted]
+ * 4. Neither the name of Gunnar Ritter nor the names of his contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
diff --git a/text-utils/Makefile.am b/text-utils/Makefile.am
new file mode 100644
index 0000000..dec895b
--- /dev/null
+++ b/text-utils/Makefile.am
@@ -0,0 +1,33 @@
+include $(top_srcdir)/config/include-Makefile.am
+
+EXTRA_DIST = README.clear README.col
+
+usrbin_exec_PROGRAMS = col colcrt colrm column hexdump rev line tailf
+
+hexdump_SOURCES = hexdump.c conv.c display.c hexsyntax.c odsyntax.c parse.c \
+ hexdump.h
+
+dist_man_MANS = col.1 colcrt.1 colrm.1 column.1 hexdump.1 rev.1 line.1 tailf.1
+
+if HAVE_NCURSES
+bin_PROGRAMS = more
+usrbin_exec_PROGRAMS += ul pg
+if HAVE_TINFO
+more_LDADD = -ltinfo
+pg_LDADD = -ltinfo @NCURSES_LIBS@
+ul_LDADD = -ltinfo
+else
+more_LDADD = @NCURSES_LIBS@
+pg_LDADD = @NCURSES_LIBS@
+ul_LDADD = @NCURSES_LIBS@
+endif
+dist_man_MANS += ul.1 more.1 pg.1
+else
+if HAVE_TERMCAP
+bin_PROGRAMS = more
+more_LDADD = -ltermcap
+dist_man_MANS += more.1
+endif
+endif
+
+EXTRA_DIST += README.pg LICENSE.pg
diff --git a/text-utils/Makefile.in b/text-utils/Makefile.in
new file mode 100644
index 0000000..892c8d6
--- /dev/null
+++ b/text-utils/Makefile.in
@@ -0,0 +1,802 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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@
+DIST_COMMON = $(am__dist_noinst_DATA_DIST) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/config/include-Makefile.am
+usrbin_exec_PROGRAMS = col$(EXEEXT) colcrt$(EXEEXT) colrm$(EXEEXT) \
+ column$(EXEEXT) hexdump$(EXEEXT) rev$(EXEEXT) line$(EXEEXT) \
+ tailf$(EXEEXT) $(am__EXEEXT_1)
+@HAVE_NCURSES_FALSE@@HAVE_TERMCAP_TRUE@bin_PROGRAMS = more$(EXEEXT)
+@HAVE_NCURSES_TRUE@bin_PROGRAMS = more$(EXEEXT)
+@HAVE_NCURSES_TRUE@am__append_1 = ul pg
+@HAVE_NCURSES_TRUE@am__append_2 = ul.1 more.1 pg.1
+@HAVE_NCURSES_FALSE@@HAVE_TERMCAP_TRUE@am__append_3 = more.1
+subdir = text-utils
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/m4/tls.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(usrbin_execdir)" \
+ "$(DESTDIR)$(man1dir)"
+@HAVE_NCURSES_TRUE@am__EXEEXT_1 = ul$(EXEEXT) pg$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS) $(usrbin_exec_PROGRAMS)
+col_SOURCES = col.c
+col_OBJECTS = col.$(OBJEXT)
+col_LDADD = $(LDADD)
+colcrt_SOURCES = colcrt.c
+colcrt_OBJECTS = colcrt.$(OBJEXT)
+colcrt_LDADD = $(LDADD)
+colrm_SOURCES = colrm.c
+colrm_OBJECTS = colrm.$(OBJEXT)
+colrm_LDADD = $(LDADD)
+column_SOURCES = column.c
+column_OBJECTS = column.$(OBJEXT)
+column_LDADD = $(LDADD)
+am_hexdump_OBJECTS = hexdump.$(OBJEXT) conv.$(OBJEXT) \
+ display.$(OBJEXT) hexsyntax.$(OBJEXT) odsyntax.$(OBJEXT) \
+ parse.$(OBJEXT)
+hexdump_OBJECTS = $(am_hexdump_OBJECTS)
+hexdump_LDADD = $(LDADD)
+line_SOURCES = line.c
+line_OBJECTS = line.$(OBJEXT)
+line_LDADD = $(LDADD)
+more_SOURCES = more.c
+more_OBJECTS = more.$(OBJEXT)
+more_DEPENDENCIES =
+pg_SOURCES = pg.c
+pg_OBJECTS = pg.$(OBJEXT)
+pg_DEPENDENCIES =
+rev_SOURCES = rev.c
+rev_OBJECTS = rev.$(OBJEXT)
+rev_LDADD = $(LDADD)
+tailf_SOURCES = tailf.c
+tailf_OBJECTS = tailf.$(OBJEXT)
+tailf_LDADD = $(LDADD)
+ul_SOURCES = ul.c
+ul_OBJECTS = ul.$(OBJEXT)
+ul_DEPENDENCIES =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = col.c colcrt.c colrm.c column.c $(hexdump_SOURCES) line.c \
+ more.c pg.c rev.c tailf.c ul.c
+DIST_SOURCES = col.c colcrt.c colrm.c column.c $(hexdump_SOURCES) \
+ line.c more.c pg.c rev.c tailf.c ul.c
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+am__dist_noinst_DATA_DIST = col.1 colcrt.1 colrm.1 column.1 hexdump.1 \
+ rev.1 line.1 tailf.1 ul.1 more.1 pg.1
+DATA = $(dist_noinst_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLKID = @BLKID@
+BLKID_CFLAGS = @BLKID_CFLAGS@
+BLKID_LIBS = @BLKID_LIBS@
+BLKID_LIBS_STATIC = @BLKID_LIBS_STATIC@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBBLKID_VERSION = @LIBBLKID_VERSION@
+LIBBLKID_VERSION_INFO = @LIBBLKID_VERSION_INFO@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_VERSION = @LIBUUID_VERSION@
+LIBUUID_VERSION_INFO = @LIBUUID_VERSION_INFO@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+NCURSES_LIBS = @NCURSES_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED = @SED@
+SELINUX_LIBS = @SELINUX_LIBS@
+SELINUX_LIBS_STATIC = @SELINUX_LIBS_STATIC@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUID_CFLAGS = @SUID_CFLAGS@
+SUID_LDFLAGS = @SUID_LDFLAGS@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+VOLID = @VOLID@
+XGETTEXT = @XGETTEXT@
+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@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+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@
+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@
+libdirname = @libdirname@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+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_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+usrbin_execdir = @usrbin_execdir@
+usrlib_execdir = @usrlib_execdir@
+usrsbin_execdir = @usrsbin_execdir@
+AM_CPPFLAGS = -include $(top_builddir)/config.h -I$(top_srcdir)/include \
+ -DLOCALEDIR=\"$(localedir)\"
+
+AM_CFLAGS = -fsigned-char
+AM_LDFLAGS =
+
+# Automake (at least up to 1.10) mishandles dist_man_MANS inside conditionals.
+# Unlike with other dist primaries, the files are not distributed if the
+# conditional is false.
+# Work the bug around until it is fixed:
+dist_noinst_DATA = $(dist_man_MANS)
+
+# Paths to in-tree libraries (use ul_ prefix to avoid possible collisions)
+#
+# blkid
+ul_libblkid_srcdir = $(top_srcdir)/shlibs/blkid/src
+ul_libblkid_builddir = $(top_builddir)/shlibs/blkid/src
+ul_libblkid_la = $(top_builddir)/shlibs/blkid/src/libblkid.la
+
+# uuid
+ul_libuuid_srcdir = $(top_srcdir)/shlibs/uuid/src
+ul_libuuid_builddir = $(top_builddir)/shlibs/uuid/src
+ul_libuuid_la = $(top_builddir)/shlibs/uuid/src/libuuid.la
+EXTRA_DIST = README.clear README.col README.pg LICENSE.pg
+hexdump_SOURCES = hexdump.c conv.c display.c hexsyntax.c odsyntax.c parse.c \
+ hexdump.h
+
+dist_man_MANS = col.1 colcrt.1 colrm.1 column.1 hexdump.1 rev.1 line.1 \
+ tailf.1 $(am__append_2) $(am__append_3)
+@HAVE_NCURSES_FALSE@@HAVE_TERMCAP_TRUE@more_LDADD = -ltermcap
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_FALSE@more_LDADD = @NCURSES_LIBS@
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_TRUE@more_LDADD = -ltinfo
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_FALSE@pg_LDADD = @NCURSES_LIBS@
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_TRUE@pg_LDADD = -ltinfo @NCURSES_LIBS@
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_FALSE@ul_LDADD = @NCURSES_LIBS@
+@HAVE_NCURSES_TRUE@@HAVE_TINFO_TRUE@ul_LDADD = -ltinfo
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/include-Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign text-utils/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign text-utils/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
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+install-usrbin_execPROGRAMS: $(usrbin_exec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(usrbin_execdir)" || $(MKDIR_P) "$(DESTDIR)$(usrbin_execdir)"
+ @list='$(usrbin_exec_PROGRAMS)'; test -n "$(usrbin_execdir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(usrbin_execdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(usrbin_execdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-usrbin_execPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(usrbin_exec_PROGRAMS)'; test -n "$(usrbin_execdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(usrbin_execdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(usrbin_execdir)" && rm -f $$files
+
+clean-usrbin_execPROGRAMS:
+ @list='$(usrbin_exec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+col$(EXEEXT): $(col_OBJECTS) $(col_DEPENDENCIES)
+ @rm -f col$(EXEEXT)
+ $(LINK) $(col_OBJECTS) $(col_LDADD) $(LIBS)
+colcrt$(EXEEXT): $(colcrt_OBJECTS) $(colcrt_DEPENDENCIES)
+ @rm -f colcrt$(EXEEXT)
+ $(LINK) $(colcrt_OBJECTS) $(colcrt_LDADD) $(LIBS)
+colrm$(EXEEXT): $(colrm_OBJECTS) $(colrm_DEPENDENCIES)
+ @rm -f colrm$(EXEEXT)
+ $(LINK) $(colrm_OBJECTS) $(colrm_LDADD) $(LIBS)
+column$(EXEEXT): $(column_OBJECTS) $(column_DEPENDENCIES)
+ @rm -f column$(EXEEXT)
+ $(LINK) $(column_OBJECTS) $(column_LDADD) $(LIBS)
+hexdump$(EXEEXT): $(hexdump_OBJECTS) $(hexdump_DEPENDENCIES)
+ @rm -f hexdump$(EXEEXT)
+ $(LINK) $(hexdump_OBJECTS) $(hexdump_LDADD) $(LIBS)
+line$(EXEEXT): $(line_OBJECTS) $(line_DEPENDENCIES)
+ @rm -f line$(EXEEXT)
+ $(LINK) $(line_OBJECTS) $(line_LDADD) $(LIBS)
+more$(EXEEXT): $(more_OBJECTS) $(more_DEPENDENCIES)
+ @rm -f more$(EXEEXT)
+ $(LINK) $(more_OBJECTS) $(more_LDADD) $(LIBS)
+pg$(EXEEXT): $(pg_OBJECTS) $(pg_DEPENDENCIES)
+ @rm -f pg$(EXEEXT)
+ $(LINK) $(pg_OBJECTS) $(pg_LDADD) $(LIBS)
+rev$(EXEEXT): $(rev_OBJECTS) $(rev_DEPENDENCIES)
+ @rm -f rev$(EXEEXT)
+ $(LINK) $(rev_OBJECTS) $(rev_LDADD) $(LIBS)
+tailf$(EXEEXT): $(tailf_OBJECTS) $(tailf_DEPENDENCIES)
+ @rm -f tailf$(EXEEXT)
+ $(LINK) $(tailf_OBJECTS) $(tailf_LDADD) $(LIBS)
+ul$(EXEEXT): $(ul_OBJECTS) $(ul_DEPENDENCIES)
+ @rm -f ul$(EXEEXT)
+ $(LINK) $(ul_OBJECTS) $(ul_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/col.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colcrt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colrm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/column.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hexdump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hexsyntax.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/line.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/more.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odsyntax.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rev.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tailf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ul.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(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@ $(am__mv) $(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) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+
+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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @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 "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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: check-am
+all-am: Makefile $(PROGRAMS) $(MANS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(usrbin_execdir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: 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:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-usrbin_execPROGRAMS 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
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-usrbin_execPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+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 \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man \
+ uninstall-usrbin_execPROGRAMS
+
+uninstall-man: uninstall-man1
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool clean-usrbin_execPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ 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-man1 \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip install-usrbin_execPROGRAMS installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-man uninstall-man1 uninstall-usrbin_execPROGRAMS
+
+
+$(ul_libblkid_la):
+ $(MAKE) -C $(ul_libblkid_builddir)
+
+$(ul_libuuid_la):
+ $(MAKE) -C $(ul_libuuid_builddir)
+
+# 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/text-utils/README.clear b/text-utils/README.clear
new file mode 100644
index 0000000..7684132
--- /dev/null
+++ b/text-utils/README.clear
@@ -0,0 +1,7 @@
+RedHat and SuSE take the program clear from ncurses.
+ A 20KB program equivalent to "tput clear".
+
+Slackware uses the script.
+
+So, both versions will behave identically, and
+Slackware saves 20 KB.
diff --git a/text-utils/README.col b/text-utils/README.col
new file mode 100644
index 0000000..2a7dd6c
--- /dev/null
+++ b/text-utils/README.col
@@ -0,0 +1,48 @@
+# @(#)README 5.1 (Berkeley) 5/22/90
+
+col - filter out reverse line feeds.
+
+Options are:
+ -b do not print any backspaces (last character written is printed)
+ -f allow half line feeds in output, by default characters between
+ lines are pushed to the line below
+ -x do not compress spaces into tabs.
+ -l num keep (at least) num lines in memory, 128 are kept by default
+
+In the 32V source code to col(1) the default behavior was to NOT compress
+spaces into tabs. There was a -h option which caused it to compress spaces
+into tabs. There was no -x flag.
+
+The 32V documentation, however, was consistent with the SVID (actually, V7
+at the time) and documented a -x flag (as defined above) while making no
+mention of a -h flag. Just before 4.3BSD went out, CSRG updated the manual
+page to reflect the way the code worked. Suspecting that this was probably
+the wrong way to go, this version adopts the SVID defaults, and no longer
+documents the -h option.
+
+The S5 -p flag is not supported because it isn't clear what it does (looks
+like a kludge introduced for a particular printer).
+
+Known differences between AT&T's col and this one (# is delimiter):
+ Input AT&T col this col
+ #\nabc\E7def\n# # def\nabc\r# # def\nabc\n#
+ #a# ## #a\n#
+ - last line always ends with at least one \n (or \E9)
+ #1234567 8\n# #1234567\t8\n# #1234567 8\n#
+ - single space not expanded to tab
+ -f #a\E8b\n# #ab\n# # b\E9\ra\n#
+ - can back up past first line (as far as you want) so you
+ *can* have a super script on the first line
+ #\E9_\ba\E8\nb\n# #\n_\bb\ba\n# #\n_\ba\bb\n#
+ - always print last character written to a position,
+ AT&T col claims to do this but doesn't.
+
+If a character is to be placed on a line that has been flushed, a warning
+is produced (the AT&T col is silent). The -l flag (not in AT&T col) can
+be used to increase the number of lines buffered to avoid the problem.
+
+General algorithm: a limited number of lines are buffered in a linked
+list. When a printable character is read, it is put in the buffer of
+the current line along with the column it's supposed to be in. When
+a line is flushed, the characters in the line are sorted according to
+column and then printed.
diff --git a/text-utils/README.pg b/text-utils/README.pg
new file mode 100644
index 0000000..df92b85
--- /dev/null
+++ b/text-utils/README.pg
@@ -0,0 +1,23 @@
+README for the "pg" utility for Linux.
+
+The "pg" utility is the historic System V equivalent to BSD's "more". This
+is a free clone of it, and it is intended to conform to the SVID 4 as well
+as the SUSv2 specification of this command.
+
+Contrasting to the System V implementation, this one filters backspace
+formatting sequences while searching, so you can comfortably search in nroff
+output like manual pages.
+
+This code uses routines as defined by SUSv2, so a glibc version of 2.1 or
+higher is required on Linux. A curses implementation (like ncurses) must
+be present as well.
+
+If large files > 2GB are supported by the kernel and the C library, pg is
+able to handle them.
+
+Please send comments, bug-reports and especially bug-fixes to
+<g-r@bigfoot.de> .
+
+Gunnar Ritter
+Freiburg i. Br.
+Germany
diff --git a/text-utils/col.1 b/text-utils/col.1
new file mode 100644
index 0000000..86afba3
--- /dev/null
+++ b/text-utils/col.1
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Michael Rendell.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)col.1 6.8 (Berkeley) 6/17/91
+.\"
+.Dd June 17, 1991
+.Dt COL 1
+.Os
+.Sh NAME
+.Nm col
+.Nd filter reverse line feeds from input
+.Sh SYNOPSIS
+.Nm col
+.Op Fl bfpx
+.Op Fl l Ar num
+.Sh DESCRIPTION
+.Nm Col
+filters out reverse (and half reverse) line feeds so the output is
+in the correct order with only forward and half forward line
+feeds, and replaces white-space characters with tabs where possible.
+This can be useful in processing the output of
+.Xr nroff 1
+and
+.Xr tbl 1 .
+.Pp
+.Nm Col
+reads from standard input and writes to standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width "-lnum"
+.It Fl b
+Do not output any backspaces, printing only the last character
+written to each column position.
+.It Fl f
+Forward half line feeds are permitted (``fine'' mode).
+Normally characters printed on a half line boundary are printed
+on the following line.
+.It Fl p
+Force unknown control sequences to be passed through unchanged.
+Normally,
+.Nm col
+will filter out any control sequences from the input other than those
+recognized and interpreted by itself, which are listed below.
+.It Fl x
+Output multiple spaces instead of tabs.
+.It Fl l Ns Ar num
+Buffer at least
+.Ar num
+lines in memory.
+By default, 128 lines are buffered.
+.El
+.Pp
+The control sequences for carriage motion that
+.Nm col
+understands and their decimal values are listed in the following
+table:
+.Pp
+.Bl -tag -width "carriage return" -compact
+.It ESC\-7
+reverse line feed (escape then 7)
+.It ESC\-8
+half reverse line feed (escape then 8)
+.It ESC\-9
+half forward line feed (escape then 9)
+.It backspace
+moves back one column (8); ignored in the first column
+.It carriage return
+(13)
+.It newline
+forward line feed (10); also does carriage return
+.It shift in
+shift to normal character set (15)
+.It shift out
+shift to alternate character set (14)
+.It space
+moves forward one column (32)
+.It tab
+moves forward to next tab stop (9)
+.It vertical tab
+reverse line feed (11)
+.El
+.Pp
+All unrecognized control characters and escape sequences are
+discarded.
+.Pp
+.Nm Col
+keeps track of the character set as characters are read and makes
+sure the character set is correct when they are output.
+.Pp
+If the input attempts to back up to the last flushed line,
+.Nm col
+will display a warning message.
+.Sh SEE ALSO
+.Xr expand 1 ,
+.Xr nroff 1 ,
+.Xr tbl 1
+.Sh STANDARDS
+The
+.Nm col
+utility conforms to the Single UNIX Specification, Version 2. The
+.Fl l
+option is an extension to the standard.
+.Sh HISTORY
+A
+.Nm col
+command
+appeared in Version 6 AT&T UNIX.
+.Sh AVAILABILITY
+The col command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/col.c b/text-utils/col.c
new file mode 100644
index 0000000..3b81a89
--- /dev/null
+++ b/text-utils/col.c
@@ -0,0 +1,559 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Rendell of the Memorial University of Newfoundland.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Wed Jun 22 22:15:41 1994, faith@cs.unc.edu: Added internationalization
+ * patches from Andries.Brouwer@cwi.nl
+ * Wed Sep 14 22:31:17 1994: patches from Carl Christofferson
+ * (cchris@connected.com)
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ *
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "nls.h"
+
+#include "widechar.h"
+
+#define BS '\b' /* backspace */
+#define TAB '\t' /* tab */
+#define SPACE ' ' /* space */
+#define NL '\n' /* newline */
+#define CR '\r' /* carriage return */
+#define ESC '\033' /* escape */
+#define SI '\017' /* shift in to normal character set */
+#define SO '\016' /* shift out to alternate character set */
+#define VT '\013' /* vertical tab (aka reverse line feed) */
+#define RLF '\007' /* ESC-07 reverse line feed */
+#define RHLF '\010' /* ESC-010 reverse half-line feed */
+#define FHLF '\011' /* ESC-011 forward half-line feed */
+
+/* build up at least this many lines before flushing them out */
+#define BUFFER_MARGIN 32
+
+typedef char CSET;
+
+typedef struct char_str {
+#define CS_NORMAL 1
+#define CS_ALTERNATE 2
+ short c_column; /* column character is in */
+ CSET c_set; /* character set (currently only 2) */
+ wchar_t c_char; /* character in question */
+ int c_width; /* character width */
+} CHAR;
+
+typedef struct line_str LINE;
+struct line_str {
+ CHAR *l_line; /* characters on the line */
+ LINE *l_prev; /* previous line */
+ LINE *l_next; /* next line */
+ int l_lsize; /* allocated sizeof l_line */
+ int l_line_len; /* strlen(l_line) */
+ int l_needs_sort; /* set if chars went in out of order */
+ int l_max_col; /* max column in the line */
+};
+
+void usage(void);
+void wrerr(void);
+void warn(int);
+void free_line(LINE *l);
+void flush_line(LINE *l);
+void flush_lines(int);
+void flush_blanks(void);
+void *xmalloc(void *p, size_t size);
+LINE *alloc_line(void);
+
+CSET last_set; /* char_set of last char printed */
+LINE *lines;
+int compress_spaces; /* if doing space -> tab conversion */
+int fine; /* if `fine' resolution (half lines) */
+int max_bufd_lines; /* max # lines to keep in memory */
+int nblank_lines; /* # blanks after last flushed line */
+int no_backspaces; /* if not to output any backspaces */
+int pass_unknown_seqs; /* whether to pass unknown control sequences */
+
+#define PUTC(ch) \
+ if (putwchar(ch) == WEOF) \
+ wrerr();
+
+int main(int argc, char **argv)
+{
+ register wint_t ch;
+ CHAR *c;
+ CSET cur_set; /* current character set */
+ LINE *l; /* current line */
+ int extra_lines; /* # of lines above first line */
+ int cur_col; /* current column */
+ int cur_line; /* line number of current position */
+ int max_line; /* max value of cur_line */
+ int this_line; /* line l points to */
+ int nflushd_lines; /* number of lines that were flushed */
+ int adjust, opt, warned;
+ int ret = 0;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ max_bufd_lines = 128;
+ compress_spaces = 1; /* compress spaces into tabs */
+ pass_unknown_seqs = 0; /* remove unknown escape sequences */
+ while ((opt = getopt(argc, argv, "bfhl:px")) != -1)
+ switch (opt) {
+ case 'b': /* do not output backspaces */
+ no_backspaces = 1;
+ break;
+ case 'f': /* allow half forward line feeds */
+ fine = 1;
+ break;
+ case 'h': /* compress spaces into tabs */
+ compress_spaces = 1;
+ break;
+ case 'l': /* buffered line count */
+ if ((max_bufd_lines = atoi(optarg)) <= 0) {
+ (void)fprintf(stderr,
+ _("col: bad -l argument %s.\n"), optarg);
+ exit(1);
+ }
+ break;
+ case 'p':
+ pass_unknown_seqs = 1;
+ break;
+ case 'x': /* do not compress spaces into tabs */
+ compress_spaces = 0;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (optind != argc)
+ usage();
+
+ /* this value is in half lines */
+ max_bufd_lines *= 2;
+
+ adjust = cur_col = extra_lines = warned = 0;
+ cur_line = max_line = nflushd_lines = this_line = 0;
+ cur_set = last_set = CS_NORMAL;
+ lines = l = alloc_line();
+
+ while (feof(stdin)==0) {
+ errno = 0;
+ if ((ch = getwchar()) == WEOF) {
+ if (errno==EILSEQ) {
+ perror("col");
+ ret = 1;
+ }
+ break;
+ }
+ if (!iswgraph(ch)) {
+ switch (ch) {
+ case BS: /* can't go back further */
+ if (cur_col == 0)
+ continue;
+ --cur_col;
+ continue;
+ case CR:
+ cur_col = 0;
+ continue;
+ case ESC: /* just ignore EOF */
+ switch(getwchar()) {
+ case RLF:
+ cur_line -= 2;
+ break;
+ case RHLF:
+ cur_line--;
+ break;
+ case FHLF:
+ cur_line++;
+ if (cur_line > max_line)
+ max_line = cur_line;
+ }
+ continue;
+ case NL:
+ cur_line += 2;
+ if (cur_line > max_line)
+ max_line = cur_line;
+ cur_col = 0;
+ continue;
+ case SPACE:
+ ++cur_col;
+ continue;
+ case SI:
+ cur_set = CS_NORMAL;
+ continue;
+ case SO:
+ cur_set = CS_ALTERNATE;
+ continue;
+ case TAB: /* adjust column */
+ cur_col |= 7;
+ ++cur_col;
+ continue;
+ case VT:
+ cur_line -= 2;
+ continue;
+ }
+ if (iswspace(ch)) {
+ if (wcwidth(ch) > 0)
+ cur_col += wcwidth(ch);
+ continue;
+ }
+ if (!pass_unknown_seqs)
+ continue;
+ }
+
+ /* Must stuff ch in a line - are we at the right one? */
+ if (cur_line != this_line - adjust) {
+ LINE *lnew;
+ int nmove;
+
+ adjust = 0;
+ nmove = cur_line - this_line;
+ if (!fine) {
+ /* round up to next line */
+ if (cur_line & 1) {
+ adjust = 1;
+ nmove++;
+ }
+ }
+ if (nmove < 0) {
+ for (; nmove < 0 && l->l_prev; nmove++)
+ l = l->l_prev;
+ if (nmove) {
+ if (nflushd_lines == 0) {
+ /*
+ * Allow backup past first
+ * line if nothing has been
+ * flushed yet.
+ */
+ for (; nmove < 0; nmove++) {
+ lnew = alloc_line();
+ l->l_prev = lnew;
+ lnew->l_next = l;
+ l = lines = lnew;
+ extra_lines++;
+ }
+ } else {
+ if (!warned++)
+ warn(cur_line);
+ cur_line -= nmove;
+ }
+ }
+ } else {
+ /* may need to allocate here */
+ for (; nmove > 0 && l->l_next; nmove--)
+ l = l->l_next;
+ for (; nmove > 0; nmove--) {
+ lnew = alloc_line();
+ lnew->l_prev = l;
+ l->l_next = lnew;
+ l = lnew;
+ }
+ }
+ this_line = cur_line + adjust;
+ nmove = this_line - nflushd_lines;
+ if (nmove >= max_bufd_lines + BUFFER_MARGIN) {
+ nflushd_lines += nmove - max_bufd_lines;
+ flush_lines(nmove - max_bufd_lines);
+ }
+ }
+ /* grow line's buffer? */
+ if (l->l_line_len + 1 >= l->l_lsize) {
+ int need;
+
+ need = l->l_lsize ? l->l_lsize * 2 : 90;
+ l->l_line = (CHAR *)xmalloc((void *) l->l_line,
+ (unsigned) need * sizeof(CHAR));
+ l->l_lsize = need;
+ }
+ c = &l->l_line[l->l_line_len++];
+ c->c_char = ch;
+ c->c_set = cur_set;
+ c->c_column = cur_col;
+ c->c_width = wcwidth(ch);
+ /*
+ * If things are put in out of order, they will need sorting
+ * when it is flushed.
+ */
+ if (cur_col < l->l_max_col)
+ l->l_needs_sort = 1;
+ else
+ l->l_max_col = cur_col;
+ if (c->c_width > 0)
+ cur_col += c->c_width;
+ }
+ /* goto the last line that had a character on it */
+ for (; l->l_next; l = l->l_next)
+ this_line++;
+ flush_lines(this_line - nflushd_lines + extra_lines + 1);
+
+ /* make sure we leave things in a sane state */
+ if (last_set != CS_NORMAL)
+ PUTC('\017');
+
+ /* flush out the last few blank lines */
+ nblank_lines = max_line - this_line;
+ if (max_line & 1)
+ nblank_lines++;
+ else if (!nblank_lines)
+ /* missing a \n on the last line? */
+ nblank_lines = 2;
+ flush_blanks();
+ if (ferror(stdout) || fclose(stdout))
+ return 1;
+ return ret;
+}
+
+void flush_lines(int nflush)
+{
+ LINE *l;
+
+ while (--nflush >= 0) {
+ l = lines;
+ lines = l->l_next;
+ if (l->l_line) {
+ flush_blanks();
+ flush_line(l);
+ }
+ nblank_lines++;
+ if (l->l_line)
+ (void)free((void *)l->l_line);
+ free_line(l);
+ }
+ if (lines)
+ lines->l_prev = NULL;
+}
+
+/*
+ * Print a number of newline/half newlines. If fine flag is set, nblank_lines
+ * is the number of half line feeds, otherwise it is the number of whole line
+ * feeds.
+ */
+void flush_blanks()
+{
+ int half, i, nb;
+
+ half = 0;
+ nb = nblank_lines;
+ if (nb & 1) {
+ if (fine)
+ half = 1;
+ else
+ nb++;
+ }
+ nb /= 2;
+ for (i = nb; --i >= 0;)
+ PUTC('\n');
+ if (half) {
+ PUTC('\033');
+ PUTC('9');
+ if (!nb)
+ PUTC('\r');
+ }
+ nblank_lines = 0;
+}
+
+/*
+ * Write a line to stdout taking care of space to tab conversion (-h flag)
+ * and character set shifts.
+ */
+void flush_line(LINE *l)
+{
+ CHAR *c, *endc;
+ int nchars, last_col, this_col;
+
+ last_col = 0;
+ nchars = l->l_line_len;
+
+ if (l->l_needs_sort) {
+ static CHAR *sorted;
+ static int count_size, *count, i, save, sorted_size, tot;
+
+ /*
+ * Do an O(n) sort on l->l_line by column being careful to
+ * preserve the order of characters in the same column.
+ */
+ if (l->l_lsize > sorted_size) {
+ sorted_size = l->l_lsize;
+ sorted = (CHAR *)xmalloc((void *)sorted,
+ (unsigned)sizeof(CHAR) * sorted_size);
+ }
+ if (l->l_max_col >= count_size) {
+ count_size = l->l_max_col + 1;
+ count = (int *)xmalloc((void *)count,
+ (unsigned)sizeof(int) * count_size);
+ }
+ memset(count, 0, sizeof(int) * l->l_max_col + 1);
+ for (i = nchars, c = l->l_line; --i >= 0; c++)
+ count[c->c_column]++;
+
+ /*
+ * calculate running total (shifted down by 1) to use as
+ * indices into new line.
+ */
+ for (tot = 0, i = 0; i <= l->l_max_col; i++) {
+ save = count[i];
+ count[i] = tot;
+ tot += save;
+ }
+
+ for (i = nchars, c = l->l_line; --i >= 0; c++)
+ sorted[count[c->c_column]++] = *c;
+ c = sorted;
+ } else
+ c = l->l_line;
+ while (nchars > 0) {
+ this_col = c->c_column;
+ endc = c;
+ do {
+ ++endc;
+ } while (--nchars > 0 && this_col == endc->c_column);
+
+ /* if -b only print last character */
+ if (no_backspaces) {
+ c = endc - 1;
+ if (nchars > 0 &&
+ this_col + c->c_width > endc->c_column)
+ continue;
+ }
+
+ if (this_col > last_col) {
+ int nspace = this_col - last_col;
+
+ if (compress_spaces && nspace > 1) {
+ int ntabs;
+
+ ntabs = this_col / 8 - last_col / 8;
+ if (ntabs > 0) {
+ nspace = this_col & 7;
+ while (--ntabs >= 0)
+ PUTC('\t');
+ }
+ }
+ while (--nspace >= 0)
+ PUTC(' ');
+ last_col = this_col;
+ }
+
+ for (;;) {
+ if (c->c_set != last_set) {
+ switch (c->c_set) {
+ case CS_NORMAL:
+ PUTC('\017');
+ break;
+ case CS_ALTERNATE:
+ PUTC('\016');
+ }
+ last_set = c->c_set;
+ }
+ PUTC(c->c_char);
+ if ((c+1) < endc) {
+ int i;
+ for (i=0; i < c->c_width; i++)
+ PUTC('\b');
+ }
+ if (++c >= endc)
+ break;
+ }
+ last_col += (c-1)->c_width;
+ }
+}
+
+#define NALLOC 64
+
+static LINE *line_freelist;
+
+LINE *
+alloc_line()
+{
+ LINE *l;
+ int i;
+
+ if (!line_freelist) {
+ l = (LINE *)xmalloc((void *)NULL, sizeof(LINE) * NALLOC);
+ line_freelist = l;
+ for (i = 1; i < NALLOC; i++, l++)
+ l->l_next = l + 1;
+ l->l_next = NULL;
+ }
+ l = line_freelist;
+ line_freelist = l->l_next;
+
+ memset(l, 0, sizeof(LINE));
+ return(l);
+}
+
+void free_line(LINE *l)
+{
+ l->l_next = line_freelist;
+ line_freelist = l;
+}
+
+void *
+xmalloc(void *p, size_t size)
+{
+ if (!(p = (void *)realloc(p, size))) {
+ (void)fprintf(stderr, "col: %s.\n", strerror(ENOMEM));
+ exit(1);
+ }
+ return(p);
+}
+
+void usage()
+{
+ (void)fprintf(stderr, _("usage: col [-bfpx] [-l nline]\n"));
+ exit(1);
+}
+
+void wrerr()
+{
+ (void)fprintf(stderr, _("col: write error.\n"));
+ exit(1);
+}
+
+void warn(int line)
+{
+ (void)fprintf(stderr,
+ _("col: warning: can't back up %s.\n"), line < 0 ?
+ _("past first line") : _("-- line already flushed"));
+}
diff --git a/text-utils/colcrt.1 b/text-utils/colcrt.1
new file mode 100644
index 0000000..f0eceb5
--- /dev/null
+++ b/text-utils/colcrt.1
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1980, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)colcrt.1 8.1 (Berkeley) 6/30/93
+.\"
+.Dd June 30, 1993
+.Dt COLCRT 1
+.Os BSD 3
+.Sh NAME
+.Nm colcrt
+.Nd filter nroff output for CRT previewing
+.Sh SYNOPSIS
+.Nm colcrt
+.Op Fl
+.Op Fl \&2
+.Op Ar
+.Sh DESCRIPTION
+.Nm Colcrt
+provides virtual half-line and reverse line feed sequences
+for terminals without such capability, and on which overstriking
+is destructive.
+Half-line characters and underlining (changed to dashing `\-')
+are placed on new lines in between the normal output lines.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl
+Suppress all underlining.
+This option is especially useful for previewing
+.Em allboxed
+tables from
+.Xr tbl 1 .
+.It Fl 2
+Causes all half-lines to be printed, effectively double spacing the output.
+Normally, a minimal space output format is used which will suppress empty
+lines.
+The program never suppresses two consecutive empty lines, however.
+The
+.Fl 2
+option is useful for sending output to the line printer when the output
+contains superscripts and subscripts which would otherwise be invisible.
+.El
+.Sh EXAMPLES
+A typical use of
+.Nm colcrt
+would be
+.Bd -literal
+tbl exum2.n \&| nroff \-ms \&| colcrt \- \&| more
+.Ed
+.Sh SEE ALSO
+.Xr nroff 1 ,
+.Xr troff 1 ,
+.Xr col 1 ,
+.Xr more 1 ,
+.Xr ul 1
+.Sh BUGS
+Should fold underlines onto blanks even with the
+.Ql Fl
+option so that
+a true underline character would show.
+.Pp
+Can't back up more than 102 lines.
+.Pp
+General overstriking is lost;
+as a special case
+.Ql \&|
+overstruck with
+.Ql \-
+or underline becomes
+.Ql \&+ .
+.Pp
+Lines are trimmed to 132 characters.
+.Pp
+Some provision should be made for processing superscripts and subscripts
+in documents which are already double-spaced.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh AVAILABILITY
+The colcrt command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/colcrt.c b/text-utils/colcrt.c
new file mode 100644
index 0000000..6f79665
--- /dev/null
+++ b/text-utils/colcrt.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close() */
+#include <string.h>
+#include "nls.h"
+
+#include "widechar.h"
+
+int plus(wchar_t c, wchar_t d);
+void move(int l, int m);
+void pflush(int ol);
+
+/*
+ * colcrt - replaces col for crts with new nroff esp. when using tbl.
+ * Bill Joy UCB July 14, 1977
+ *
+ * This filter uses a screen buffer, 267 half-lines by 132 columns.
+ * It interprets the up and down sequences generated by the new
+ * nroff when used with tbl and by \u \d and \r.
+ * General overstriking doesn't work correctly.
+ * Underlining is split onto multiple lines, etc.
+ *
+ * Option - suppresses all underlining.
+ * Option -2 forces printing of all half lines.
+ */
+
+wchar_t page[267][132];
+
+int outline = 1;
+int outcol;
+
+char suppresul;
+char printall;
+
+char *progname;
+void colcrt(FILE *f);
+
+int
+main(int argc, char **argv) {
+ FILE *f;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ argc--;
+ progname = *argv++;
+ while (argc > 0 && argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case 0:
+ suppresul = 1;
+ break;
+ case '2':
+ printall = 1;
+ break;
+ default:
+ printf(_("usage: %s [ - ] [ -2 ] [ file ... ]\n"), progname);
+ fflush(stdout);
+ exit(1);
+ }
+ argc--;
+ argv++;
+ }
+ f = stdin;
+ do {
+ if (argc > 0) {
+ if (!(f = fopen(argv[0], "r"))) {
+ fflush(stdout);
+ perror(argv[0]);
+ exit (1);
+ }
+ argc--;
+ argv++;
+ }
+ colcrt(f);
+ if (f != stdin)
+ fclose(f);
+ } while (argc > 0);
+ fflush(stdout);
+ if (ferror(stdout) || fclose(stdout))
+ return 1;
+ return 0;
+}
+
+void
+colcrt(FILE *f) {
+ wint_t c;
+ wchar_t *cp, *dp;
+ int i, w;
+
+ for (;;) {
+ c = getwc(f);
+ if (c == WEOF) {
+ pflush(outline);
+ fflush(stdout);
+ break;
+ }
+ switch (c) {
+ case '\n':
+ if (outline >= 265)
+ pflush(62);
+ outline += 2;
+ outcol = 0;
+ continue;
+ case '\016':
+ case '\017':
+ continue;
+ case 033:
+ c = getwc(f);
+ switch (c) {
+ case '9':
+ if (outline >= 266)
+ pflush(62);
+ outline++;
+ continue;
+ case '8':
+ if (outline >= 1)
+ outline--;
+ continue;
+ case '7':
+ outline -= 2;
+ if (outline < 0)
+ outline = 0;
+ continue;
+ default:
+ continue;
+ }
+ case '\b':
+ if (outcol)
+ outcol--;
+ continue;
+ case '\t':
+ outcol += 8;
+ outcol &= ~7;
+ outcol--;
+ c = ' ';
+ default:
+ w = wcwidth(c);
+ if (outcol + w > 132) {
+ outcol++;
+ continue;
+ }
+ cp = &page[outline][outcol];
+ outcol += w;
+ if (c == '_') {
+ if (suppresul)
+ continue;
+ cp += 132;
+ c = '-';
+ }
+ if (*cp == 0) {
+ /* trick! */
+ for (i=0; i<w; i++)
+ cp[i] = c;
+ dp = cp - (outcol-w);
+ for (cp--; cp >= dp && *cp == 0; cp--)
+ *cp = ' ';
+ } else {
+ if (plus(c, *cp) || plus(*cp, c))
+ *cp = '+';
+ else if (*cp == ' ' || *cp == 0) {
+ for (i=1; i<w; i++)
+ if (cp[i] != ' ' && cp[i] != 0)
+ continue;
+ for (i=0; i<w; i++)
+ cp[i] = c;
+ }
+ }
+ continue;
+ }
+ }
+}
+
+int plus(wchar_t c, wchar_t d)
+{
+
+ return (c == '|' && (d == '-' || d == '_'));
+}
+
+int first;
+
+void pflush(int ol)
+{
+ register int i;
+ register wchar_t *cp;
+ char lastomit;
+ int l, w;
+
+ l = ol;
+ lastomit = 0;
+ if (l > 266)
+ l = 266;
+ else
+ l |= 1;
+ for (i = first | 1; i < l; i++) {
+ move(i, i - 1);
+ move(i, i + 1);
+ }
+ for (i = first; i < l; i++) {
+ cp = page[i];
+ if (printall == 0 && lastomit == 0 && *cp == 0) {
+ lastomit = 1;
+ continue;
+ }
+ lastomit = 0;
+ while (*cp) {
+ if ((w = wcwidth(*cp)) > 0) {
+ putwchar(*cp);
+ cp += w;
+ } else
+ cp++;
+ }
+ putwchar('\n');
+ }
+ memmove(page, page[ol], (267 - ol) * 132 * sizeof(wchar_t));
+ memset(page[267- ol], '\0', ol * 132 * sizeof(wchar_t));
+ outline -= ol;
+ outcol = 0;
+ first = 1;
+}
+
+void move(int l, int m)
+{
+ register wchar_t *cp, *dp;
+
+ for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
+ switch (*cp) {
+ case '|':
+ if (*dp != ' ' && *dp != '|' && *dp != 0)
+ return;
+ break;
+ case ' ':
+ break;
+ default:
+ return;
+ }
+ }
+ if (*cp == 0) {
+ for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
+ if (*cp == '|')
+ *dp = '|';
+ else if (*dp == 0)
+ *dp = ' ';
+ page[l][0] = 0;
+ }
+}
diff --git a/text-utils/colrm.1 b/text-utils/colrm.1
new file mode 100644
index 0000000..d02167a
--- /dev/null
+++ b/text-utils/colrm.1
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1980, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)colrm.1 6.6 (Berkeley) 3/14/91
+.\"
+.Dd March 14, 1991
+.Dt COLRM 1
+.Os BSD 3
+.Sh NAME
+.Nm colrm
+.Nd remove columns from a file
+.Sh SYNOPSIS
+.Nm colrm
+.Op Ar startcol Op Ar endcol
+.Sh DESCRIPTION
+.Nm Colrm
+removes selected columns from a file. Input is taken from standard input.
+Output is sent to standard output.
+.Pp
+If called with one parameter the columns
+of each line will be removed starting with the specified column.
+If called with two parameters the columns from the first column
+to the last column will be removed.
+.Pp
+Column numbering starts with column 1.
+.Sh SEE ALSO
+.Xr awk 1 ,
+.Xr column 1 ,
+.Xr expand 1 ,
+.Xr paste 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh AVAILABILITY
+The colrm command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/colrm.c b/text-utils/colrm.c
new file mode 100644
index 0000000..e8b1ea4
--- /dev/null
+++ b/text-utils/colrm.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nls.h"
+#include "widechar.h"
+
+/*
+COLRM removes unwanted columns from a file
+ Jeff Schriebman UC Berkeley 11-74
+*/
+
+int
+main(int argc, char **argv)
+{
+ register int ct, first, last;
+ register wint_t c;
+ int i, w;
+ int padding;
+
+ setlocale(LC_ALL, "");
+
+ first = 0;
+ last = 0;
+ if (argc > 1)
+ first = atoi(*++argv);
+ if (argc > 2)
+ last = atoi(*++argv);
+
+start:
+ ct = 0;
+loop1:
+ c = getwc(stdin);
+ if (c == WEOF)
+ goto fin;
+ if (c == '\t')
+ w = ((ct + 8) & ~7) - ct;
+ else if (c == '\b')
+ w = (ct ? ct - 1 : 0) - ct;
+ else {
+ w = wcwidth(c);
+ if (w < 0)
+ w = 0;
+ }
+ ct += w;
+ if (c == '\n') {
+ putwc(c, stdout);
+ goto start;
+ }
+ if (!first || ct < first) {
+ putwc(c, stdout);
+ goto loop1;
+ }
+ for (i = ct-w+1; i < first; i++)
+ putwc(' ', stdout);
+
+/* Loop getting rid of characters */
+ while (!last || ct < last) {
+ c = getwc(stdin);
+ if (c == WEOF)
+ goto fin;
+ if (c == '\n') {
+ putwc(c, stdout);
+ goto start;
+ }
+ if (c == '\t')
+ ct = (ct + 8) & ~7;
+ else if (c == '\b')
+ ct = ct ? ct - 1 : 0;
+ else {
+ w = wcwidth(c);
+ if (w < 0)
+ w = 0;
+ ct += w;
+ }
+ }
+
+ padding = 0;
+
+/* Output last of the line */
+ for (;;) {
+ c = getwc(stdin);
+ if (c == WEOF)
+ break;
+ if (c == '\n') {
+ putwc(c, stdout);
+ goto start;
+ }
+ if (padding == 0 && last < ct) {
+ for (i = last; i <ct; i++)
+ putwc(' ', stdout);
+ padding = 1;
+ }
+ putwc(c, stdout);
+ }
+fin:
+ fflush(stdout);
+ if (ferror(stdout) || fclose(stdout))
+ return 1;
+ return 0;
+}
diff --git a/text-utils/column.1 b/text-utils/column.1
new file mode 100644
index 0000000..1da59cc
--- /dev/null
+++ b/text-utils/column.1
@@ -0,0 +1,102 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)column.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Os
+.Dt COLUMN 1
+.Sh NAME
+.Nm column
+.Nd columnate lists
+.Sh SYNOPSIS
+.Nm column
+.Op Fl tx
+.Op Fl c Ar columns
+.Op Fl s Ar sep
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm column
+utility formats its input into multiple columns.
+Rows are filled before columns.
+Input is taken from
+.Ar file
+operands, or, by default, from the standard input.
+Empty lines are ignored.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Output is formatted for a display
+.Ar columns
+wide.
+.It Fl s
+Specify a set of characters to be used to delimit columns for the
+.Fl t
+option.
+.It Fl t
+Determine the number of columns the input contains and create a table.
+Columns are delimited with whitespace, by default, or with the characters
+supplied using the
+.Fl s
+option.
+Useful for pretty-printing displays.
+.It Fl x
+Fill columns before filling rows.
+.El
+.Pp
+.Nm Column
+exits 0 on success, >0 if an error occurred.
+.Sh ENVIRONMENT
+.Bl -tag -width COLUMNS
+.It Ev COLUMNS
+The environment variable
+.Ev COLUMNS
+is used to determine the size of
+the screen if no other information is available.
+.El
+.Sh EXAMPLES
+.Dl (printf \&"PERM LINKS OWNER GROUP SIZE MONTH DAY HH:MM/YEAR\ NAME\en\&"\ \&\e
+.Dl \&; ls -l \&| sed 1d) \&| column -t
+.Sh SEE ALSO
+.Xr colrm 1 ,
+.Xr ls 1 ,
+.Xr paste 1 ,
+.Xr sort 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 Reno .
+.Sh AVAILABILITY
+The column command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/column.c b/text-utils/column.c
new file mode 100644
index 0000000..f5d41a2
--- /dev/null
+++ b/text-utils/column.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include "nls.h"
+
+#include "widechar.h"
+
+#ifdef HAVE_WIDECHAR
+#define wcs_width(s) wcswidth(s,wcslen(s))
+static wchar_t *mbs_to_wcs(const char *);
+#else
+#define wcs_width(s) strlen(s)
+#define mbs_to_wcs(s) strdup(s)
+static char *mtsafe_strtok(char *, const char *, char **);
+#define wcstok mtsafe_strtok
+#endif
+
+static void c_columnate __P((void));
+static void *emalloc __P((int));
+static void input __P((FILE *));
+static void maketbl __P((void));
+static void print __P((void));
+static void r_columnate __P((void));
+static void usage __P((void));
+
+int termwidth = 80; /* default terminal width */
+
+int entries; /* number of records */
+int eval; /* exit value */
+int maxlength; /* longest record */
+wchar_t **list; /* array of pointers to records */
+wchar_t default_separator[] = { '\t', ' ', 0 };
+wchar_t *separator = default_separator; /* field separator for table option */
+
+int
+main(int argc, char **argv)
+{
+ struct winsize win;
+ FILE *fp;
+ int ch, tflag, xflag;
+ char *p;
+
+ extern char *__progname;
+ __progname = argv[0];
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
+ if ((p = getenv("COLUMNS")) != NULL)
+ termwidth = atoi(p);
+ } else
+ termwidth = win.ws_col;
+
+ tflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "c:s:tx")) != -1)
+ switch(ch) {
+ case 'c':
+ termwidth = atoi(optarg);
+ break;
+ case 's':
+ separator = mbs_to_wcs(optarg);
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!*argv)
+ input(stdin);
+ else for (; *argv; ++argv)
+ if ((fp = fopen(*argv, "r")) != NULL) {
+ input(fp);
+ (void)fclose(fp);
+ } else {
+ warn("%s", *argv);
+ eval = 1;
+ }
+
+ if (!entries)
+ exit(eval);
+
+ if (tflag)
+ maketbl();
+ else if (maxlength >= termwidth)
+ print();
+ else if (xflag)
+ c_columnate();
+ else
+ r_columnate();
+ if (ferror(stdout) || fclose(stdout))
+ eval = 1;
+ exit(eval);
+}
+
+#define TAB 8
+static void
+c_columnate()
+{
+ int chcnt, col, cnt, endcol, numcols;
+ wchar_t **lp;
+
+ maxlength = (maxlength + TAB) & ~(TAB - 1);
+ numcols = termwidth / maxlength;
+ endcol = maxlength;
+ for (chcnt = col = 0, lp = list;; ++lp) {
+ fputws(*lp, stdout);
+ chcnt += wcs_width(*lp);
+ if (!--entries)
+ break;
+ if (++col == numcols) {
+ chcnt = col = 0;
+ endcol = maxlength;
+ putwchar('\n');
+ } else {
+ while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) {
+ putwchar('\t');
+ chcnt = cnt;
+ }
+ endcol += maxlength;
+ }
+ }
+ if (chcnt)
+ putwchar('\n');
+}
+
+static void
+r_columnate()
+{
+ int base, chcnt, cnt, col, endcol, numcols, numrows, row;
+
+ maxlength = (maxlength + TAB) & ~(TAB - 1);
+ numcols = termwidth / maxlength;
+ if (!numcols)
+ numcols = 1;
+ numrows = entries / numcols;
+ if (entries % numcols)
+ ++numrows;
+
+ for (row = 0; row < numrows; ++row) {
+ endcol = maxlength;
+ for (base = row, chcnt = col = 0; col < numcols; ++col) {
+ fputws(list[base], stdout);
+ chcnt += wcs_width(list[base]);
+ if ((base += numrows) >= entries)
+ break;
+ while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) {
+ putwchar('\t');
+ chcnt = cnt;
+ }
+ endcol += maxlength;
+ }
+ putwchar('\n');
+ }
+}
+
+static void
+print()
+{
+ int cnt;
+ wchar_t **lp;
+
+ for (cnt = entries, lp = list; cnt--; ++lp) {
+ fputws(*lp, stdout);
+ putwchar('\n');
+ }
+}
+
+typedef struct _tbl {
+ wchar_t **list;
+ int cols, *len;
+} TBL;
+#define DEFCOLS 25
+
+static void
+maketbl()
+{
+ TBL *t;
+ int coloff, cnt, i;
+ wchar_t *p, **lp;
+ int *lens, maxcols;
+ TBL *tbl;
+ wchar_t **cols;
+ wchar_t *wcstok_state;
+
+ t = tbl = emalloc(entries * sizeof(TBL));
+ cols = emalloc((maxcols = DEFCOLS) * sizeof(wchar_t *));
+ lens = emalloc(maxcols * sizeof(int));
+ for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
+ for (coloff = 0, p = *lp;
+ (cols[coloff] = wcstok(p, separator, &wcstok_state)) != NULL;
+ p = NULL)
+ if (++coloff == maxcols) {
+ if (!(cols = realloc(cols, ((u_int)maxcols + DEFCOLS)
+ * sizeof(wchar_t *))) ||
+ !(lens = realloc(lens, ((u_int)maxcols + DEFCOLS)
+ * sizeof(int))))
+ err(1, NULL);
+ memset((char *)lens + maxcols * sizeof(int),
+ 0, DEFCOLS * sizeof(int));
+ maxcols += DEFCOLS;
+ }
+ t->list = emalloc(coloff * sizeof(wchar_t *));
+ t->len = emalloc(coloff * sizeof(int));
+ for (t->cols = coloff; --coloff >= 0;) {
+ t->list[coloff] = cols[coloff];
+ t->len[coloff] = wcs_width(cols[coloff]);
+ if (t->len[coloff] > lens[coloff])
+ lens[coloff] = t->len[coloff];
+ }
+ }
+ for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
+ for (coloff = 0; coloff < t->cols - 1; ++coloff) {
+ fputws(t->list[coloff], stdout);
+ for (i = lens[coloff] - t->len[coloff] + 2; i > 0; i--)
+ putwchar(' ');
+ }
+ fputws(t->list[coloff], stdout);
+ putwchar('\n');
+ }
+}
+
+#define DEFNUM 1000
+#define MAXLINELEN (LINE_MAX + 1)
+
+static void
+input(fp)
+ FILE *fp;
+{
+ static int maxentry;
+ int len;
+ wchar_t *p, buf[MAXLINELEN];
+
+ if (!list)
+ list = emalloc((maxentry = DEFNUM) * sizeof(wchar_t *));
+ while (fgetws(buf, MAXLINELEN, fp)) {
+ for (p = buf; *p && iswspace(*p); ++p);
+ if (!*p)
+ continue;
+ if (!(p = wcschr(p, '\n'))) {
+ warnx(_("line too long"));
+ eval = 1;
+ continue;
+ }
+ *p = '\0';
+ len = wcs_width(buf); /* len = p - buf; */
+ if (maxlength < len)
+ maxlength = len;
+ if (entries == maxentry) {
+ maxentry += DEFNUM;
+ if (!(list = realloc(list,
+ (u_int)maxentry * sizeof(wchar_t *))))
+ err(1, NULL);
+ }
+ list[entries++] = wcsdup(buf);
+ }
+}
+
+#ifdef HAVE_WIDECHAR
+static wchar_t *mbs_to_wcs(const char *s)
+{
+ size_t n;
+ wchar_t *wcs;
+
+ n = mbstowcs((wchar_t *)0, s, 0);
+ if (n < 0)
+ return NULL;
+ wcs = malloc((n + 1) * sizeof(wchar_t));
+ if (!wcs)
+ return NULL;
+ if (mbstowcs(wcs, s, n + 1) < 0)
+ return NULL;
+ return wcs;
+}
+#endif
+
+#ifndef HAVE_WIDECHAR
+static char *mtsafe_strtok(char *str, const char *delim, char **ptr)
+{
+ if (str == NULL) {
+ str = *ptr;
+ if (str == NULL)
+ return NULL;
+ }
+ str += strspn(str, delim);
+ if (*str == '\0') {
+ *ptr = NULL;
+ return NULL;
+ } else {
+ char *token_end = strpbrk(str, delim);
+ if (token_end) {
+ *token_end = '\0';
+ *ptr = token_end + 1;
+ } else
+ *ptr = NULL;
+ return str;
+ }
+}
+#endif
+
+static void *
+emalloc(size)
+ int size;
+{
+ char *p;
+
+ if (!(p = malloc(size)))
+ err(1, NULL);
+ memset(p, 0, size);
+ return (p);
+}
+
+static void
+usage()
+{
+
+ (void)fprintf(stderr,
+ _("usage: column [-tx] [-c columns] [file ...]\n"));
+ exit(1);
+}
diff --git a/text-utils/conv.c b/text-utils/conv.c
new file mode 100644
index 0000000..8e0efa1
--- /dev/null
+++ b/text-utils/conv.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "hexdump.h"
+
+void
+conv_c(PR *pr, u_char *p)
+{
+ char buf[10];
+ char const *str;
+
+ switch(*p) {
+ case '\0':
+ str = "\\0";
+ goto strpr;
+ /* case '\a': */
+ case '\007':
+ if (deprecated) /* od didn't know about \a */
+ break;
+ str = "\\a";
+ goto strpr;
+ case '\b':
+ str = "\\b";
+ goto strpr;
+ case '\f':
+ str = "\\f";
+ goto strpr;
+ case '\n':
+ str = "\\n";
+ goto strpr;
+ case '\r':
+ str = "\\r";
+ goto strpr;
+ case '\t':
+ str = "\\t";
+ goto strpr;
+ case '\v':
+ if (deprecated)
+ break;
+ str = "\\v";
+ goto strpr;
+ default:
+ break;
+ }
+ if (isprint(*p)) {
+ *pr->cchar = 'c';
+ (void)printf(pr->fmt, *p);
+ } else {
+ (void)sprintf(buf, "%03o", (int)*p);
+ str = buf;
+strpr: *pr->cchar = 's';
+ (void)printf(pr->fmt, str);
+ }
+}
+
+void
+conv_u(PR *pr, u_char *p)
+{
+ static const char *list[] = {
+ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
+ "bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
+ "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
+ "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
+ };
+
+ /* od used nl, not lf */
+ if (*p <= 0x1f) {
+ *pr->cchar = 's';
+ if (deprecated && *p == 0x0a)
+ (void)printf(pr->fmt, "nl");
+ else
+ (void)printf(pr->fmt, list[*p]);
+ } else if (*p == 0x7f) {
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, "del");
+ } else if (deprecated && *p == 0x20) { /* od replaced space with sp */
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, " sp");
+ } else if (isprint(*p)) {
+ *pr->cchar = 'c';
+ (void)printf(pr->fmt, *p);
+ } else {
+ *pr->cchar = 'x';
+ (void)printf(pr->fmt, (int)*p);
+ }
+}
diff --git a/text-utils/display.c b/text-utils/display.c
new file mode 100644
index 0000000..91857c2
--- /dev/null
+++ b/text-utils/display.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hexdump.h"
+
+static void doskip(const char *, int);
+static u_char *get(void);
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+enum _vflag vflag = FIRST;
+
+static off_t address; /* address/offset in stream */
+static off_t eaddress; /* end address */
+
+static inline void
+print(PR *pr, u_char *bp) {
+
+ switch(pr->flags) {
+ case F_ADDRESS:
+ (void)printf(pr->fmt, (quad_t)address);
+ break;
+ case F_BPAD:
+ (void)printf(pr->fmt, "");
+ break;
+ case F_C:
+ conv_c(pr, bp);
+ break;
+ case F_CHAR:
+ (void)printf(pr->fmt, *bp);
+ break;
+ case F_DBL:
+ {
+ double dval;
+ float fval;
+ switch(pr->bcnt) {
+ case 4:
+ memmove(&fval, bp, sizeof(fval));
+ (void)printf(pr->fmt, fval);
+ break;
+ case 8:
+ memmove(&dval, bp, sizeof(dval));
+ (void)printf(pr->fmt, dval);
+ break;
+ }
+ break;
+ }
+ case F_INT:
+ {
+ short sval; /* int16_t */
+ int ival; /* int32_t */
+ long long Lval; /* int64_t, quad_t */
+
+ switch(pr->bcnt) {
+ case 1:
+ (void)printf(pr->fmt, (quad_t)*bp);
+ break;
+ case 2:
+ memmove(&sval, bp, sizeof(sval));
+ (void)printf(pr->fmt, (quad_t)sval);
+ break;
+ case 4:
+ memmove(&ival, bp, sizeof(ival));
+ (void)printf(pr->fmt, (quad_t)ival);
+ break;
+ case 8:
+ memmove(&Lval, bp, sizeof(Lval));
+ (void)printf(pr->fmt, (quad_t)Lval);
+ break;
+ }
+ break;
+ }
+ case F_P:
+ (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
+ break;
+ case F_STR:
+ (void)printf(pr->fmt, (char *)bp);
+ break;
+ case F_TEXT:
+ (void)printf("%s", pr->fmt);
+ break;
+ case F_U:
+ conv_u(pr, bp);
+ break;
+ case F_UINT:
+ {
+ unsigned short sval; /* u_int16_t */
+ unsigned int ival; /* u_int32_t */
+ unsigned long long Lval;/* u_int64_t, u_quad_t */
+
+ switch(pr->bcnt) {
+ case 1:
+ (void)printf(pr->fmt, (u_quad_t)*bp);
+ break;
+ case 2:
+ memmove(&sval, bp, sizeof(sval));
+ (void)printf(pr->fmt, (u_quad_t)sval);
+ break;
+ case 4:
+ memmove(&ival, bp, sizeof(ival));
+ (void)printf(pr->fmt, (u_quad_t)ival);
+ break;
+ case 8:
+ memmove(&Lval, bp, sizeof(Lval));
+ (void)printf(pr->fmt, (u_quad_t)Lval);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static void bpad(PR *pr)
+{
+ static const char *spec = " -0+#";
+ char *p1, *p2;
+
+ /*
+ * remove all conversion flags; '-' is the only one valid
+ * with %s, and it's not useful here.
+ */
+ pr->flags = F_BPAD;
+ pr->cchar[0] = 's';
+ pr->cchar[1] = 0;
+ for (p1 = pr->fmt; *p1 != '%'; ++p1);
+ for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
+ while ((*p2++ = *p1++) != 0) ;
+}
+
+void display(void)
+{
+ register FS *fs;
+ register FU *fu;
+ register PR *pr;
+ register int cnt;
+ register u_char *bp;
+ off_t saveaddress;
+ u_char savech = 0, *savebp;
+
+ while ((bp = get()) != NULL)
+ for (fs = fshead, savebp = bp, saveaddress = address; fs;
+ fs = fs->nextfs, bp = savebp, address = saveaddress)
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (fu->flags&F_IGNORE)
+ break;
+ for (cnt = fu->reps; cnt; --cnt)
+ for (pr = fu->nextpr; pr; address += pr->bcnt,
+ bp += pr->bcnt, pr = pr->nextpr) {
+ if (eaddress && address >= eaddress &&
+ !(pr->flags&(F_TEXT|F_BPAD)))
+ bpad(pr);
+ if (cnt == 1 && pr->nospace) {
+ savech = *pr->nospace;
+ *pr->nospace = '\0';
+ }
+ print(pr, bp);
+ if (cnt == 1 && pr->nospace)
+ *pr->nospace = savech;
+ }
+ }
+ if (endfu) {
+ /*
+ * if eaddress not set, error or file size was multiple of
+ * blocksize, and no partial block ever found.
+ */
+ if (!eaddress) {
+ if (!address)
+ return;
+ eaddress = address;
+ }
+ for (pr = endfu->nextpr; pr; pr = pr->nextpr)
+ switch(pr->flags) {
+ case F_ADDRESS:
+ (void)printf(pr->fmt, (quad_t)eaddress);
+ break;
+ case F_TEXT:
+ (void)printf("%s", pr->fmt);
+ break;
+ }
+ }
+}
+
+static char **_argv;
+
+static u_char *
+get(void)
+{
+ static int ateof = 1;
+ static u_char *curp, *savp;
+ int n;
+ int need, nread;
+ u_char *tmpp;
+
+ if (!curp) {
+ curp = emalloc(blocksize);
+ savp = emalloc(blocksize);
+ } else {
+ tmpp = curp;
+ curp = savp;
+ savp = tmpp;
+ address += blocksize;
+ }
+ for (need = blocksize, nread = 0;;) {
+ /*
+ * if read the right number of bytes, or at EOF for one file,
+ * and no other files are available, zero-pad the rest of the
+ * block and set the end flag.
+ */
+ if (!length || (ateof && !next(NULL))) {
+ if (need == blocksize)
+ return(NULL);
+ if (!need && vflag != ALL &&
+ !memcmp(curp, savp, nread)) {
+ if (vflag != DUP)
+ (void)printf("*\n");
+ return(NULL);
+ }
+ if (need > 0)
+ memset((char *)curp + nread, 0, need);
+ eaddress = address + nread;
+ return(curp);
+ }
+ n = fread((char *)curp + nread, sizeof(u_char),
+ length == -1 ? need : MIN(length, need), stdin);
+ if (!n) {
+ if (ferror(stdin))
+ (void)fprintf(stderr, "hexdump: %s: %s\n",
+ _argv[-1], strerror(errno));
+ ateof = 1;
+ continue;
+ }
+ ateof = 0;
+ if (length != -1)
+ length -= n;
+ if (!(need -= n)) {
+ if (vflag == ALL || vflag == FIRST ||
+ memcmp(curp, savp, blocksize)) {
+ if (vflag == DUP || vflag == FIRST)
+ vflag = WAIT;
+ return(curp);
+ }
+ if (vflag == WAIT)
+ (void)printf("*\n");
+ vflag = DUP;
+ address += blocksize;
+ need = blocksize;
+ nread = 0;
+ }
+ else
+ nread += n;
+ }
+}
+
+int next(char **argv)
+{
+ static int done;
+ int statok;
+
+ if (argv) {
+ _argv = argv;
+ return(1);
+ }
+ for (;;) {
+ if (*_argv) {
+ if (!(freopen(*_argv, "r", stdin))) {
+ (void)fprintf(stderr, "hexdump: %s: %s\n",
+ *_argv, strerror(errno));
+ exitval = 1;
+ ++_argv;
+ continue;
+ }
+ statok = done = 1;
+ } else {
+ if (done++)
+ return(0);
+ statok = 0;
+ }
+ if (skip)
+ doskip(statok ? *_argv : "stdin", statok);
+ if (*_argv)
+ ++_argv;
+ if (!skip)
+ return(1);
+ }
+ /* NOTREACHED */
+}
+
+static void
+doskip(const char *fname, int statok)
+{
+ struct stat sbuf;
+
+ if (statok) {
+ if (fstat(fileno(stdin), &sbuf)) {
+ (void)fprintf(stderr, "hexdump: %s: %s.\n",
+ fname, strerror(errno));
+ exit(1);
+ }
+ if (S_ISREG(sbuf.st_mode) && skip >= sbuf.st_size) {
+ /* If size valid and skip >= size */
+ skip -= sbuf.st_size;
+ address += sbuf.st_size;
+ return;
+ }
+ }
+ /* sbuf may be undefined here - do not test it */
+ if (fseek(stdin, skip, SEEK_SET)) {
+ (void)fprintf(stderr, "hexdump: %s: %s.\n",
+ fname, strerror(errno));
+ exit(1);
+ }
+ address += skip;
+ skip = 0;
+}
+
+void *
+emalloc(int sz) {
+ void *p;
+
+ if (!(p = malloc((u_int)sz)))
+ nomem();
+ memset(p, 0, sz);
+ return(p);
+}
+
+void nomem() {
+ (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));
+ exit(1);
+}
diff --git a/text-utils/hexdump.1 b/text-utils/hexdump.1
new file mode 100644
index 0000000..24cb8c3
--- /dev/null
+++ b/text-utils/hexdump.1
@@ -0,0 +1,342 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)hexdump.1 8.2 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt HEXDUMP 1
+.Os
+.Sh NAME
+.Nm hexdump
+.Nd ascii, decimal, hexadecimal, octal dump
+.Sh SYNOPSIS
+.Nm
+.Op Fl bcCdovx
+.Bk -words
+.Op Fl e Ar format_string
+.Ek
+.Bk -words
+.Op Fl f Ar format_file
+.Ek
+.Bk -words
+.Op Fl n Ar length
+.Ek
+.Bk -words
+.Op Fl s Ar skip
+.Ek
+.Ar file ...
+.Sh DESCRIPTION
+The hexdump utility is a filter which displays the specified files, or
+the standard input, if no files are specified, in a user specified
+format.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl b
+.Em One-byte octal display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, three column, zero-filled, bytes of input data,
+in octal, per line.
+.It Fl c
+.Em One-byte character display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, three column, space-filled, characters of input
+data per line.
+.It Fl C
+.Em Canonical hex+ASCII display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, two column, hexadecimal bytes, followed by the
+same sixteen bytes in %_p format enclosed in ``|'' characters.
+.It Fl d
+.Em Two-byte decimal display .
+Display the input offset in hexadecimal, followed by eight
+space-separated, five column, zero-filled, two-byte units
+of input data, in unsigned decimal, per line.
+.It Fl e Ar format_string
+Specify a format string to be used for displaying data.
+.It Fl f Ar format_file
+Specify a file that contains one or more newline separated format strings.
+Empty lines and lines whose first non-blank character is a hash mark
+.Pf ( Cm \&# )
+are ignored.
+.It Fl n Ar length
+Interpret only
+.Ar length
+bytes of input.
+.It Fl o
+.Em Two-byte octal display .
+Display the input offset in hexadecimal, followed by eight
+space-separated, six column, zero-filled, two byte quantities of
+input data, in octal, per line.
+.It Fl s Ar offset
+Skip
+.Ar offset
+bytes from the beginning of the input.
+By default,
+.Ar offset
+is interpreted as a decimal number.
+With a leading
+.Cm 0x
+or
+.Cm 0X ,
+.Ar offset
+is interpreted as a hexadecimal number,
+otherwise, with a leading
+.Cm 0 ,
+.Ar offset
+is interpreted as an octal number.
+Appending the character
+.Cm b ,
+.Cm k ,
+or
+.Cm m
+to
+.Ar offset
+causes it to be interpreted as a multiple of
+.Li 512 ,
+.Li 1024 ,
+or
+.Li 1048576 ,
+respectively.
+.It Fl v
+The
+.Fl v
+option causes hexdump to display all input data.
+Without the
+.Fl v
+option, any number of groups of output lines, which would be
+identical to the immediately preceding group of output lines (except
+for the input offsets), are replaced with a line comprised of a
+single asterisk.
+.It Fl x
+.Em Two-byte hexadecimal display .
+Display the input offset in hexadecimal, followed by eight, space
+separated, four column, zero-filled, two-byte quantities of input
+data, in hexadecimal, per line.
+.El
+.Pp
+For each input file,
+.Nm
+sequentially copies the input to standard output, transforming the
+data according to the format strings specified by the
+.Fl e
+and
+.Fl f
+options, in the order that they were specified.
+.Ss Formats
+A format string contains any number of format units, separated by
+whitespace.
+A format unit contains up to three items: an iteration count, a byte
+count, and a format.
+.Pp
+The iteration count is an optional positive integer, which defaults to
+one.
+Each format is applied iteration count times.
+.Pp
+The byte count is an optional positive integer.
+If specified it defines the number of bytes to be interpreted by
+each iteration of the format.
+.Pp
+If an iteration count and/or a byte count is specified, a single slash
+must be placed after the iteration count and/or before the byte count
+to disambiguate them.
+Any whitespace before or after the slash is ignored.
+.Pp
+The format is required and must be surrounded by double quote
+(" ") marks.
+It is interpreted as a fprintf-style format string (see
+.Xr fprintf 3 ) ,
+with the
+following exceptions:
+.Bl -bullet -offset indent
+.It
+An asterisk (*) may not be used as a field width or precision.
+.It
+A byte count or field precision
+.Em is
+required for each ``s'' conversion
+character (unlike the
+.Xr fprintf 3
+default which prints the entire string if the precision is unspecified).
+.It
+The conversion characters ``h'', ``l'', ``n'', ``p'' and ``q'' are
+not supported.
+.It
+The single character escape sequences
+described in the C standard are supported:
+.Bd -ragged -offset indent -compact
+.Bl -column <alert_character>
+.It NUL \e0
+.It <alert character> \ea
+.It <backspace> \eb
+.It <form-feed> \ef
+.It <newline> \en
+.It <carriage return> \er
+.It <tab> \et
+.It <vertical tab> \ev
+.El
+.Ed
+.El
+.Pp
+Hexdump also supports the following additional conversion strings:
+.Bl -tag -width Fl
+.It Cm \&_a Ns Op Cm dox
+Display the input offset, cumulative across input files, of the
+next byte to be displayed.
+The appended characters
+.Cm d ,
+.Cm o ,
+and
+.Cm x
+specify the display base
+as decimal, octal or hexadecimal respectively.
+.It Cm \&_A Ns Op Cm dox
+Identical to the
+.Cm \&_a
+conversion string except that it is only performed
+once, when all of the input data has been processed.
+.It Cm \&_c
+Output characters in the default character set.
+Nonprinting characters are displayed in three character, zero-padded
+octal, except for those representable by standard escape notation
+(see above),
+which are displayed as two character strings.
+.It Cm _p
+Output characters in the default character set.
+Nonprinting characters are displayed as a single
+.Dq Cm \&. .
+.It Cm _u
+Output US ASCII characters, with the exception that control characters are
+displayed using the following, lower-case, names.
+Characters greater than 0xff, hexadecimal, are displayed as hexadecimal
+strings.
+.Bl -column \&000_nu \&001_so \&002_st \&003_et \&004_eo
+.It \&000\ nul\t001\ soh\t002\ stx\t003\ etx\t004\ eot\t005\ enq
+.It \&006\ ack\t007\ bel\t008\ bs\t009\ ht\t00A\ lf\t00B\ vt
+.It \&00C\ ff\t00D\ cr\t00E\ so\t00F\ si\t010\ dle\t011\ dc1
+.It \&012\ dc2\t013\ dc3\t014\ dc4\t015\ nak\t016\ syn\t017\ etb
+.It \&018\ can\t019\ em\t01A\ sub\t01B\ esc\t01C\ fs\t01D\ gs
+.It \&01E\ rs\t01F\ us\t0FF\ del
+.El
+.El
+.Pp
+The default and supported byte counts for the conversion characters
+are as follows:
+.Bl -tag -width "Xc,_Xc,_Xc,_Xc,_Xc,_Xc" -offset indent
+.It Li \&%_c , \&%_p , \&%_u , \&%c
+One byte counts only.
+.It Xo
+.Li \&%d , \&%i , \&%o ,
+.Li \&%u , \&%X , \&%x
+.Xc
+Four byte default, one, two and four byte counts supported.
+.It Xo
+.Li \&%E , \&%e , \&%f ,
+.Li \&%G , \&%g
+.Xc
+Eight byte default, four byte counts supported.
+.El
+.Pp
+The amount of data interpreted by each format string is the sum of the
+data required by each format unit, which is the iteration count times the
+byte count, or the iteration count times the number of bytes required by
+the format if the byte count is not specified.
+.Pp
+The input is manipulated in ``blocks'', where a block is defined as the
+largest amount of data specified by any format string.
+Format strings interpreting less than an input block's worth of data,
+whose last format unit both interprets some number of bytes and does
+not have a specified iteration count, have the iteration count
+incremented until the entire input block has been processed or there
+is not enough data remaining in the block to satisfy the format string.
+.Pp
+If, either as a result of user specification or hexdump modifying
+the iteration count as described above, an iteration count is
+greater than one, no trailing whitespace characters are output
+during the last iteration.
+.Pp
+It is an error to specify a byte count as well as multiple conversion
+characters or strings unless all but one of the conversion characters
+or strings is
+.Cm \&_a
+or
+.Cm \&_A .
+.Pp
+If, as a result of the specification of the
+.Fl n
+option or end-of-file being reached, input data only partially
+satisfies a format string, the input block is zero-padded sufficiently
+to display all available data (i.e. any format units overlapping the
+end of data will display some number of the zero bytes).
+.Pp
+Further output by such format strings is replaced by an equivalent
+number of spaces.
+An equivalent number of spaces is defined as the number of spaces
+output by an
+.Cm s
+conversion character with the same field width
+and precision as the original conversion character or conversion
+string but with any
+.Dq Li \&+ ,
+.Dq \&\ \& ,
+.Dq Li \&#
+conversion flag characters
+removed, and referencing a NULL string.
+.Pp
+If no format strings are specified, the default display is equivalent
+to specifying the
+.Fl x
+option.
+.Pp
+.Nm
+exits 0 on success and >0 if an error occurred.
+.Sh EXAMPLES
+Display the input in perusal format:
+.Bd -literal -offset indent
+"%06.6_ao " 12/1 "%3_u "
+"\et\et" "%_p "
+"\en"
+.Ed
+.Pp
+Implement the \-x option:
+.Bd -literal -offset indent
+"%07.7_Ax\en"
+"%07.7_ax " 8/2 "%04x " "\en"
+.Ed
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+.Sh AVAILABILITY
+The hexdump command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/hexdump.c b/text-utils/hexdump.c
new file mode 100644
index 0000000..68bb76e
--- /dev/null
+++ b/text-utils/hexdump.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include "hexdump.h"
+#include "nls.h"
+
+FS *fshead; /* head of format strings */
+int blocksize; /* data block size */
+int exitval; /* final exit value */
+int length = -1; /* max bytes to read */
+
+int main(int argc, char **argv)
+{
+ FS *tfs;
+ char *p;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ if (!(p = strrchr(argv[0], 'o')) || strcmp(p, "od"))
+ newsyntax(argc, &argv);
+ else
+ oldsyntax(argc, &argv);
+
+ /* figure out the data block size */
+ for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
+ tfs->bcnt = size(tfs);
+ if (blocksize < tfs->bcnt)
+ blocksize = tfs->bcnt;
+ }
+ /* rewrite the rules, do syntax checking */
+ for (tfs = fshead; tfs; tfs = tfs->nextfs)
+ rewrite(tfs);
+
+ (void)next(argv);
+ display();
+ return exitval;
+}
diff --git a/text-utils/hexdump.h b/text-utils/hexdump.h
new file mode 100644
index 0000000..f9e963b
--- /dev/null
+++ b/text-utils/hexdump.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)hexdump.h 5.4 (Berkeley) 6/1/90
+ */
+
+typedef struct _pr {
+ struct _pr *nextpr; /* next print unit */
+#define F_ADDRESS 0x001 /* print offset */
+#define F_BPAD 0x002 /* blank pad */
+#define F_C 0x004 /* %_c */
+#define F_CHAR 0x008 /* %c */
+#define F_DBL 0x010 /* %[EefGf] */
+#define F_INT 0x020 /* %[di] */
+#define F_P 0x040 /* %_p */
+#define F_STR 0x080 /* %s */
+#define F_U 0x100 /* %_u */
+#define F_UINT 0x200 /* %[ouXx] */
+#define F_TEXT 0x400 /* no conversions */
+ u_int flags; /* flag values */
+ int bcnt; /* byte count */
+ char *cchar; /* conversion character */
+ char *fmt; /* printf format */
+ char *nospace; /* no whitespace version */
+} PR;
+
+typedef struct _fu {
+ struct _fu *nextfu; /* next format unit */
+ struct _pr *nextpr; /* next print unit */
+#define F_IGNORE 0x01 /* %_A */
+#define F_SETREP 0x02 /* rep count set, not default */
+ u_int flags; /* flag values */
+ int reps; /* repetition count */
+ int bcnt; /* byte count */
+ char *fmt; /* format string */
+} FU;
+
+typedef struct _fs { /* format strings */
+ struct _fs *nextfs; /* linked list of format strings */
+ struct _fu *nextfu; /* linked list of format units */
+ int bcnt;
+} FS;
+
+extern FU *endfu;
+extern FS *fshead; /* head of format strings list */
+extern int blocksize; /* data block size */
+extern int deprecated; /* od compatibility */
+extern int exitval; /* final exit value */
+extern int length; /* max bytes to read */
+extern off_t skip; /* bytes to skip */
+
+enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
+extern enum _vflag vflag;
+
+void *emalloc(int);
+int size(FS *);
+void add(const char *);
+void rewrite(FS *);
+void addfile(char *);
+void display(void);
+void nomem(void);
+void usage(void);
+void conv_c(PR *, u_char *);
+void conv_u(PR *, u_char *);
+int next(char **);
+void oldsyntax(int, char ***);
+void newsyntax(int, char ***);
diff --git a/text-utils/hexsyntax.c b/text-utils/hexsyntax.c
new file mode 100644
index 0000000..f05043c
--- /dev/null
+++ b/text-utils/hexsyntax.c
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "hexdump.h"
+#include "nls.h"
+
+off_t skip; /* bytes to skip */
+
+void
+newsyntax(int argc, char ***argvp)
+{
+ int ch;
+ char *p, **argv;
+
+ argv = *argvp;
+ while ((ch = getopt(argc, argv, "bcCde:f:n:os:vx")) != -1)
+ switch (ch) {
+ case 'b':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
+ break;
+ case 'c':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
+ break;
+ case 'C':
+ add("\"%08.8_Ax\n\"");
+ add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
+ add("\" |\" 16/1 \"%_p\" \"|\\n\"");
+ break;
+ case 'd':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
+ break;
+ case 'e':
+ add(optarg);
+ break;
+ case 'f':
+ addfile(optarg);
+ break;
+ case 'n':
+ if ((length = atoi(optarg)) < 0) {
+ fprintf(stderr,
+ _("hexdump: bad length value.\n"));
+ exit(1);
+ }
+ break;
+ case 'o':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
+ break;
+ case 's':
+ if ((skip = strtol(optarg, &p, 0)) < 0) {
+ fprintf(stderr,
+ _("hexdump: bad skip value.\n"));
+ exit(1);
+ }
+ switch(*p) {
+ case 'b':
+ skip *= 512;
+ break;
+ case 'k':
+ skip *= 1024;
+ break;
+ case 'm':
+ skip *= 1048576;
+ break;
+ }
+ break;
+ case 'v':
+ vflag = ALL;
+ break;
+ case 'x':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
+ break;
+ case '?':
+ usage();
+ }
+
+ if (!fshead) {
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
+ }
+
+ *argvp += optind;
+}
+
+void
+usage()
+{
+ fprintf(stderr,
+_("hexdump: [-bcCdovx] [-e fmt] [-f fmt_file] [-n length] [-s skip] [file ...]\n"));
+ exit(1);
+}
diff --git a/text-utils/line.1 b/text-utils/line.1
new file mode 100644
index 0000000..93081ea
--- /dev/null
+++ b/text-utils/line.1
@@ -0,0 +1,17 @@
+.\" This page is in the public domain
+.TH LINE 1 "2002-07-07" "" "User Commands"
+.SH NAME
+line \- read one line
+.SH SYNOPSIS
+.B line
+.SH DESCRIPTION
+The utility
+.I line
+copies one line (up to a newline) from standard input to standard output.
+It always prints at least a newline and returns an exit status of 1
+on EOF or read error.
+.SH "SEE ALSO"
+.BR read (1)
+.SH AVAILABILITY
+The line command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/line.c b/text-utils/line.c
new file mode 100644
index 0000000..d4bb86d
--- /dev/null
+++ b/text-utils/line.c
@@ -0,0 +1,38 @@
+/*
+ * line - read one line
+ *
+ * Gunnar Ritter, Freiburg i. Br., Germany, December 2000.
+ *
+ * Public Domain.
+ */
+
+#ident "@(#)line.c 1.7 (gritter) 7/5/02"
+
+#include <stdio.h>
+#include <unistd.h>
+
+static int status; /* exit status */
+
+static void
+doline(int fd)
+{
+ char c;
+
+ for (;;) {
+ if (read(fd, &c, 1) <= 0) {
+ status = 1;
+ break;
+ }
+ if (c == '\n')
+ break;
+ putchar(c);
+ }
+ putchar('\n');
+}
+
+int
+main(int argc, char **argv)
+{
+ doline(0);
+ return status;
+}
diff --git a/text-utils/more.1 b/text-utils/more.1
new file mode 100644
index 0000000..a049d13
--- /dev/null
+++ b/text-utils/more.1
@@ -0,0 +1,205 @@
+.\" Copyright (c) 1988, 1990 The Regents of the University of California.
+.\" Copyright (c) 1988 Mark Nudleman
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)more.1 5.15 (Berkeley) 7/29/91
+.\"
+.\" Revised: Fri Dec 25 15:27:27 1992 by root
+.\" 25Dec92: Extensive changes made by Rik Faith (faith@cs.unc.edu) to
+.\" conform with the more 5.19 currently in use by the Linux community.
+.\"
+.\" .Dd July 29, 1991 (Modified December 25, 1992)
+.Dd December 25, 1992
+.Dt MORE 1
+.Os "Linux 0.98"
+.Sh NAME
+.Nm more
+.Nd file perusal filter for crt viewing
+.Sh SYNOPSIS
+.Nm more
+.Op Fl dlfpcsu
+.Op Fl num
+.Op +/\fIpattern\fP
+.Op +\fIlinenum\fP
+.Op Ar
+.Sh DESCRIPTION
+.Nm More
+is a filter for paging through text one screenful at a time. This version
+is especially primitive. Users should realize that
+.Xr less 1
+provides
+.Xr more 1
+emulation and extensive enhancements.
+.Sh OPTIONS
+Command line options are described below.
+Options are also taken from the environment variable
+.Ev MORE
+(make sure to precede them with a dash (``-'')) but command
+line options will override them.
+.Bl -tag -width flag
+.It Fl num
+This option specifies an integer which is the screen size (in lines).
+.It Fl d
+.Nm more
+will prompt the user with the message "[Press space to continue, 'q' to
+quit.]" and will display "[Press 'h' for instructions.]" instead of ringing
+the bell when an illegal key is pressed.
+.It Fl l
+.Nm more
+usually treats
+.Ic \&^L
+(form feed) as a special character, and will pause after any line that
+contains a form feed. The
+.Fl l
+option will prevent this behavior.
+.It Fl f
+Causes
+.Nm more
+to count logical, rather than screen lines (i.e., long lines are not
+folded).
+.It Fl p
+Do not scroll. Instead, clear the whole screen and then display the text.
+.It Fl c
+Do not scroll. Instead, paint each screen from the top, clearing the
+remainder of each line as it is displayed.
+.It Fl s
+Squeeze multiple blank lines into one.
+.It Fl u
+Suppress underlining.
+.It Ic +/
+The
+.Ic +/
+option specifies a string that will be searched for before
+each file is displayed.
+.It Ic +num
+Start at line number
+.Ic num .
+.El
+.Sh COMMANDS
+Interactive commands for
+.Nm more
+are based on
+.Xr vi 1 .
+Some commands may be preceded by a decimal number, called k in the
+descriptions below.
+In the following descriptions, ^X means control-X.
+.Pp
+.Bl -tag -width Ic
+.It Ic h No or Ic ?
+Help: display a summary of these commands.
+If you forget all the other commands, remember this one.
+.It Ic SPACE
+Display next k lines of text. Defaults to current screen size.
+.It Ic z
+Display next k lines of text. Defaults to current screen size. Argument
+becomes new default.
+.It Ic RETURN
+Display next k lines of text. Defaults to 1. Argument becomes new
+default.
+.It Ic d No or Ic \&^D
+Scroll k lines. Default is current scroll size, initially 11. Argument
+becomes new default.
+.It Xo
+.Ic q
+.No or
+.Ic Q
+.No or
+.Ic INTERRUPT
+.Xc
+Exit.
+.It Ic s
+Skip forward k lines of text. Defaults to 1.
+.It Ic f
+Skip forward k screenfuls of text. Defaults to 1.
+.It Ic b No or Ic \&^B
+Skip backwards k screenfuls of text. Defaults to 1.
+Only works with files, not pipes.
+.It Ic '
+Go to place where previous search started.
+.It Ic =
+Display current line number.
+.It Ic \&/ Ns Ar pattern
+Search for kth occurrence of regular expression. Defaults to 1.
+.It Ic n
+Search for kth occurrence of last r.e. Defaults to 1.
+.It Ic !<cmd> No or Ic :!<cmd>
+Execute <cmd> in a subshell
+.It Ic v
+Start up an editor at current line.
+The editor is taken from the environment variable VISUAL if defined,
+or EDITOR if VISUAL is not defined,
+or defaults to "vi" if neither VISUAL nor EDITOR is defined.
+.It Ic \&^L
+Redraw screen
+.It Ic :n
+Go to kth next file. Defaults to 1.
+.It Ic :p
+Go to kth previous file. Defaults to 1.
+.It Ic :f
+Display current file name and line number
+.It Ic \&.
+Repeat previous command
+.El
+.Sh ENVIRONMENT
+.Nm More
+utilizes the following environment variables, if they exist:
+.Bl -tag -width Fl
+.It Ev MORE
+This variable may be set with favored options to
+.Nm more .
+.It Ev SHELL
+Current shell in use (normally set by the shell at login time).
+.It Ev TERM
+Specifies terminal type, used by more to get the terminal
+characteristics necessary to manipulate the screen.
+.El
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr less 1
+.Sh AUTHORS
+Eric Shienbrood, UC Berkeley
+.br
+Modified by Geoff Peck, UCB to add underlining, single spacing
+.br
+Modified by John Foderaro, UCB to add -c and MORE environment variable
+.Sh HISTORY
+The
+.Nm more
+command appeared in
+.Bx 3.0 .
+This man page documents
+.Nm more
+version 5.19 (Berkeley 6/29/88), which is currently in use in the Linux
+community. Documentation was produced using several other versions of the
+man page, and extensive inspection of the source code.
+.Sh AVAILABILITY
+The more command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/more.c b/text-utils/more.c
new file mode 100644
index 0000000..45a58e2
--- /dev/null
+++ b/text-utils/more.c
@@ -0,0 +1,2126 @@
+/*
+ * Copyright (C) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+** more.c - General purpose tty output filter and file perusal program
+**
+** by Eric Shienbrood, UC Berkeley
+**
+** modified by Geoff Peck, UCB to add underlining, single spacing
+** modified by John Foderaro, UCB to add -c and MORE environment variable
+** modified by Erik Troan <ewt@redhat.com> to be more posix and so compile
+** on linux/axp.
+** modified by Kars de Jong <jongk@cs.utwente.nl> to use terminfo instead
+** of termcap.
+ 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ - added Native Language Support
+ 1999-03-19 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ - more nls translatable strings
+ 1999-05-09 aeb - applied a RedHat patch (setjmp->sigsetjmp); without it
+ a second ^Z would fail.
+ 1999-05-09 aeb - undone Kars' work, so that more works without
+ libcurses (and hence can be in /bin with libcurses being in /usr/lib
+ which may not be mounted). However, when termcap is not present curses
+ can still be used.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h> /* for alloca() */
+#include <stdarg.h> /* for va_start() etc */
+#include <sys/param.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <setjmp.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include "xstrncpy.h"
+#include "nls.h"
+#include "widechar.h"
+
+#define _REGEX_RE_COMP
+#include <regex.h>
+#undef _REGEX_RE_COMP
+
+#define VI "vi" /* found on the user's path */
+
+#define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m))
+#define Ftell(f) file_pos
+#define Fseek(f,off) (file_pos=off,fseek(f,off,0))
+#define Getc(f) (++file_pos, getc(f))
+#define Ungetc(c,f) (--file_pos, ungetc(c,f))
+#define putcerr(c) fputc(c, stderr)
+#define putserr(s) fputs(s, stderr)
+#define putsout(s) fputs(s, stdout)
+
+#define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
+
+/* some function declarations */
+void initterm(void);
+void kill_line(void);
+void doclear(void);
+void cleareol(void);
+void clreos(void);
+void home(void);
+void error (char *mess);
+void do_shell (char *filename);
+int colon (char *filename, int cmd, int nlines);
+int expand (char **outbuf, char *inbuf);
+void argscan(char *s,char *argv0);
+void rdline (register FILE *f);
+void copy_file(register FILE *f);
+void search(char buf[], FILE *file, register int n);
+void skipf (register int nskip);
+void skiplns(register int n, register FILE *f);
+void screen (register FILE *f, register int num_lines);
+int command (char *filename, register FILE *f);
+void erasep (register int col);
+void show (register char ch);
+void set_tty(void);
+void reset_tty(void);
+void ttyin (char buf[], register int nmax, char pchar);
+int number(char *cmd);
+int readch (void);
+int get_line(register FILE *f, int *length);
+void prbuf (register char *s, register int n);
+void execute (char *filename, char *cmd, ...);
+FILE *checkf (char *, int *);
+
+#define TBUFSIZ 1024
+#define LINSIZ 256
+#define ctrl(letter) (letter & 077)
+#define RUBOUT '\177'
+#define ESC '\033'
+#define QUIT '\034'
+
+struct termios otty, savetty0;
+long file_pos, file_size;
+int fnum, no_intty, no_tty, slow_tty;
+int dum_opt, dlines;
+void onquit(int), onsusp(int), chgwinsz(int), end_it(int);
+int nscroll = 11; /* Number of lines scrolled by 'd' */
+int fold_opt = 1; /* Fold long lines */
+int stop_opt = 1; /* Stop after form feeds */
+int ssp_opt = 0; /* Suppress white space */
+int ul_opt = 1; /* Underline as best we can */
+int promptlen;
+int Currline; /* Line we are currently at */
+int startup = 1;
+int firstf = 1;
+int notell = 1;
+int docrterase = 0;
+int docrtkill = 0;
+int bad_so; /* True if overwriting does not turn off standout */
+int inwait, Pause, errors;
+int within; /* true if we are within a file,
+ false if we are between files */
+int hard, dumb, noscroll, hardtabs, clreol, eatnl;
+int catch_susp; /* We should catch the SIGTSTP signal */
+char **fnames; /* The list of file names */
+int nfiles; /* Number of files left to process */
+char *shell; /* The name of the shell to use */
+int shellp; /* A previous shell command exists */
+sigjmp_buf restore;
+char Line[LINSIZ+2]; /* Line buffer */
+int Lpp = 24; /* lines per page */
+char *Clear; /* clear screen */
+char *eraseln; /* erase line */
+char *Senter, *Sexit;/* enter and exit standout mode */
+char *ULenter, *ULexit; /* enter and exit underline mode */
+char *chUL; /* underline character */
+char *chBS; /* backspace character */
+char *Home; /* go to home */
+char *cursorm; /* cursor movement */
+char cursorhome[40]; /* contains cursor movement to home */
+char *EodClr; /* clear rest of screen */
+int Mcol = 80; /* number of columns */
+int Wrap = 1; /* set if automargins */
+int soglitch; /* terminal has standout mode glitch */
+int ulglitch; /* terminal has underline mode glitch */
+int pstate = 0; /* current UL state */
+static int magic(FILE *, char *);
+struct {
+ long chrctr, line;
+} context, screen_start;
+extern char PC; /* pad character */
+
+#ifdef HAVE_NCURSES_H
+# include <ncurses.h>
+#elif defined(HAVE_NCURSES_NCURSES_H)
+# include <ncurses/ncurses.h>
+#endif
+
+#if defined(HAVE_NCURSES_H) || defined(HAVE_NCURSES_NCURSES_H)
+# include <term.h> /* include after <curses.h> */
+
+static void
+my_putstring(char *s) {
+ tputs (s, 1, putchar); /* putp(s); */
+}
+
+static void
+my_setupterm(char *term, int fildes, int *errret) {
+ setupterm(term, fildes, errret);
+}
+
+static int
+my_tgetnum(char *s, char *ss) {
+ return tigetnum(ss);
+}
+
+static int
+my_tgetflag(char *s, char *ss) {
+ return tigetflag(ss);
+}
+
+static char *
+my_tgetstr(char *s, char *ss) {
+ return tigetstr(ss);
+}
+
+static char *
+my_tgoto(char *cap, int col, int row) {
+ return tparm(cap, col, row);
+}
+
+#elif defined(HAVE_LIBTERMCAP) /* !ncurses */
+
+#include <termcap.h>
+
+char termbuffer[4096];
+char tcbuffer[4096];
+char *strbuf = termbuffer;
+
+static void
+my_putstring(char *s) {
+ tputs (s, 1, putchar);
+}
+
+static void
+my_setupterm(char *term, int fildes, int *errret) {
+ *errret = tgetent(tcbuffer, term);
+}
+
+static int
+my_tgetnum(char *s, char *ss) {
+ return tgetnum(s);
+}
+
+static int
+my_tgetflag(char *s, char *ss) {
+ return tgetflag(s);
+}
+
+static char *
+my_tgetstr(char *s, char *ss) {
+ return tgetstr(s, &strbuf);
+}
+
+static char *
+my_tgoto(char *cap, int col, int row) {
+ return tgoto(cap, col, row);
+}
+
+#endif /* HAVE_LIBTERMCAP */
+
+static void
+idummy(int *kk) {}
+
+static void
+Fdummy(FILE **ff) {}
+
+static void
+usage(char *s) {
+ char *p = strrchr(s, '/');
+ fprintf(stderr,
+ _("usage: %s [-dflpcsu] [+linenum | +/pattern] name1 name2 ...\n"),
+ p ? p + 1 : s);
+}
+
+int main(int argc, char **argv) {
+ FILE *f;
+ char *s;
+ char *p;
+ int ch;
+ int left;
+ int prnames = 0;
+ int initopt = 0;
+ int srchopt = 0;
+ int clearit = 0;
+ int initline = 0;
+ char initbuf[80];
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ /* avoid gcc complaints about register variables that
+ may be clobbered by a longjmp, by forcing our variables here
+ to be non-register */
+ Fdummy(&f); idummy(&left); idummy(&prnames);
+ idummy(&initopt); idummy(&srchopt); idummy(&initline);
+
+ nfiles = argc;
+ fnames = argv;
+ setlocale(LC_ALL, "");
+ initterm ();
+ nscroll = Lpp/2 - 1;
+ if (nscroll <= 0)
+ nscroll = 1;
+ if((s = getenv("MORE")) != NULL) argscan(s,argv[0]);
+ while (--nfiles > 0) {
+ if ((ch = (*++fnames)[0]) == '-') {
+ argscan(*fnames+1,argv[0]);
+ }
+ else if (ch == '+') {
+ s = *fnames;
+ if (*++s == '/') {
+ srchopt++;
+ for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';)
+ *p++ = *s++;
+ *p = '\0';
+ }
+ else {
+ initopt++;
+ for (initline = 0; *s != '\0'; s++)
+ if (isdigit (*s))
+ initline = initline*10 + *s -'0';
+ --initline;
+ }
+ }
+ else break;
+ }
+ /* allow clreol only if Home and eraseln and EodClr strings are
+ * defined, and in that case, make sure we are in noscroll mode
+ */
+ if (clreol) {
+ if((Home == NULL) || (*Home == '\0') ||
+ (eraseln == NULL) || (*eraseln == '\0') ||
+ (EodClr == NULL) || (*EodClr == '\0') )
+ clreol = 0;
+ else noscroll = 1;
+ }
+ if (dlines == 0)
+ dlines = Lpp - 1; /* was: Lpp - (noscroll ? 1 : 2) */
+ left = dlines;
+ if (nfiles > 1)
+ prnames++;
+ if (!no_intty && nfiles == 0) {
+ usage(argv[0]);
+ exit(1);
+ }
+ else
+ f = stdin;
+ if (!no_tty) {
+ signal(SIGQUIT, onquit);
+ signal(SIGINT, end_it);
+#ifdef SIGWINCH
+ signal(SIGWINCH, chgwinsz);
+#endif
+ if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
+ signal(SIGTSTP, onsusp);
+ catch_susp++;
+ }
+ stty (fileno(stderr), &otty);
+ }
+ if (no_intty) {
+ if (no_tty)
+ copy_file (stdin);
+ else {
+ if ((ch = Getc (f)) == '\f')
+ doclear();
+ else {
+ Ungetc (ch, f);
+ if (noscroll && (ch != EOF)) {
+ if (clreol)
+ home ();
+ else
+ doclear ();
+ }
+ }
+ if (srchopt)
+ {
+ search (initbuf, stdin, 1);
+ if (noscroll)
+ left--;
+ }
+ else if (initopt)
+ skiplns (initline, stdin);
+ screen (stdin, left);
+ }
+ no_intty = 0;
+ prnames++;
+ firstf = 0;
+ }
+
+ while (fnum < nfiles) {
+ if ((f = checkf (fnames[fnum], &clearit)) != NULL) {
+ context.line = context.chrctr = 0;
+ Currline = 0;
+ if (firstf) sigsetjmp (restore, 1);
+ if (firstf) {
+ firstf = 0;
+ if (srchopt) {
+ search (initbuf, f, 1);
+ if (noscroll)
+ left--;
+ }
+ else if (initopt)
+ skiplns (initline, f);
+ }
+ else if (fnum < nfiles && !no_tty) {
+ sigsetjmp (restore, 1);
+ left = command (fnames[fnum], f);
+ }
+ if (left != 0) {
+ if ((noscroll || clearit) && (file_size != LONG_MAX)) {
+ if (clreol)
+ home ();
+ else
+ doclear ();
+ }
+ if (prnames) {
+ if (bad_so)
+ erasep (0);
+ if (clreol)
+ cleareol ();
+ putsout("::::::::::::::");
+ if (promptlen > 14)
+ erasep (14);
+ putchar('\n');
+ if(clreol) cleareol();
+ puts(fnames[fnum]);
+ if(clreol) cleareol();
+ puts("::::::::::::::");
+ if (left > Lpp - 4)
+ left = Lpp - 4;
+ }
+ if (no_tty)
+ copy_file (f);
+ else {
+ within++;
+ screen(f, left);
+ within = 0;
+ }
+ }
+ sigsetjmp (restore, 1);
+ fflush(stdout);
+ fclose(f);
+ screen_start.line = screen_start.chrctr = 0L;
+ context.line = context.chrctr = 0L;
+ }
+ fnum++;
+ firstf = 0;
+ }
+ reset_tty ();
+ exit(0);
+}
+
+void argscan(char *s, char *argv0) {
+ int seen_num = 0;
+
+ while (*s != '\0') {
+ switch (*s) {
+ case '0': case '1': case '2':
+ case '3': case '4': case '5':
+ case '6': case '7': case '8':
+ case '9':
+ if (!seen_num) {
+ dlines = 0;
+ seen_num = 1;
+ }
+ dlines = dlines*10 + *s - '0';
+ break;
+ case 'd':
+ dum_opt = 1;
+ break;
+ case 'l':
+ stop_opt = 0;
+ break;
+ case 'f':
+ fold_opt = 0;
+ break;
+ case 'p':
+ noscroll++;
+ break;
+ case 'c':
+ clreol++;
+ break;
+ case 's':
+ ssp_opt = 1;
+ break;
+ case 'u':
+ ul_opt = 0;
+ break;
+ case '-': case ' ': case '\t':
+ break;
+ default:
+ fprintf(stderr,
+ _("%s: unknown option \"-%c\"\n"), argv0, *s);
+ usage(argv0);
+ exit(1);
+ break;
+ }
+ s++;
+ }
+}
+
+
+/*
+** Check whether the file named by fs is an ASCII file which the user may
+** access. If it is, return the opened file. Otherwise return NULL.
+*/
+
+FILE *
+checkf (fs, clearfirst)
+ register char *fs;
+ int *clearfirst;
+{
+ struct stat stbuf;
+ register FILE *f;
+ int c;
+
+ if (stat (fs, &stbuf) == -1) {
+ (void)fflush(stdout);
+ if (clreol)
+ cleareol ();
+ perror(fs);
+ return((FILE *)NULL);
+ }
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
+ printf(_("\n*** %s: directory ***\n\n"), fs);
+ return((FILE *)NULL);
+ }
+ if ((f = Fopen(fs, "r")) == NULL) {
+ (void)fflush(stdout);
+ perror(fs);
+ return((FILE *)NULL);
+ }
+ if (magic(f, fs))
+ return((FILE *)NULL);
+ fcntl(fileno(f), F_SETFD, FD_CLOEXEC );
+ c = Getc(f);
+ *clearfirst = (c == '\f');
+ Ungetc (c, f);
+ if ((file_size = stbuf.st_size) == 0)
+ file_size = LONG_MAX;
+ return(f);
+}
+
+/*
+ * magic --
+ * check for file magic numbers. This code would best be shared with
+ * the file(1) program or, perhaps, more should not try to be so smart.
+ */
+static int
+magic(f, fs)
+ FILE *f;
+ char *fs;
+{
+ signed char twobytes[2];
+
+ /* don't try to look ahead if the input is unseekable */
+ if (fseek(f, 0L, SEEK_SET))
+ return 0;
+
+ if (fread(twobytes, 2, 1, f) == 1) {
+ switch(twobytes[0] + (twobytes[1]<<8)) {
+ case 0407: /* a.out obj */
+ case 0410: /* a.out exec */
+ case 0413: /* a.out demand exec */
+ case 0405:
+ case 0411:
+ case 0177545:
+ case 0x457f: /* simple ELF detection */
+ printf(_("\n******** %s: Not a text file ********\n\n"), fs);
+ (void)fclose(f);
+ return 1;
+ }
+ }
+ (void)fseek(f, 0L, SEEK_SET); /* rewind() not necessary */
+ return 0;
+}
+
+/*
+** Print out the contents of the file f, one screenful at a time.
+*/
+
+#define STOP -10
+
+void screen (register FILE *f, register int num_lines)
+{
+ register int c;
+ register int nchars;
+ int length; /* length of current line */
+ static int prev_len = 1; /* length of previous line */
+
+ for (;;) {
+ while (num_lines > 0 && !Pause) {
+ if ((nchars = get_line (f, &length)) == EOF)
+ {
+ if (clreol)
+ clreos();
+ return;
+ }
+ if (ssp_opt && length == 0 && prev_len == 0)
+ continue;
+ prev_len = length;
+ if (bad_so || ((Senter && *Senter == ' ') && (promptlen > 0)))
+ erasep (0);
+ /* must clear before drawing line since tabs on some terminals
+ * do not erase what they tab over.
+ */
+ if (clreol)
+ cleareol ();
+ prbuf (Line, length);
+ if (nchars < promptlen)
+ erasep (nchars); /* erasep () sets promptlen to 0 */
+ else promptlen = 0;
+ /* is this needed?
+ * if (clreol)
+ * cleareol(); * must clear again in case we wrapped *
+ */
+ if (nchars < Mcol || !fold_opt)
+ prbuf("\n", 1); /* will turn off UL if necessary */
+ if (nchars == STOP)
+ break;
+ num_lines--;
+ }
+ if (pstate) {
+ my_putstring (ULexit);
+ pstate = 0;
+ }
+ fflush(stdout);
+ if ((c = Getc(f)) == EOF)
+ {
+ if (clreol)
+ clreos ();
+ return;
+ }
+
+ if (Pause && clreol)
+ clreos ();
+ Ungetc (c, f);
+ sigsetjmp (restore, 1);
+ Pause = 0; startup = 0;
+ if ((num_lines = command (NULL, f)) == 0)
+ return;
+ if (hard && promptlen > 0)
+ erasep (0);
+ if (noscroll && num_lines >= dlines)
+ {
+ if (clreol)
+ home();
+ else
+ doclear ();
+ }
+ screen_start.line = Currline;
+ screen_start.chrctr = Ftell (f);
+ }
+}
+
+/*
+** Come here if a quit signal is received
+*/
+
+void onquit(int dummy) {
+ signal(SIGQUIT, SIG_IGN);
+ if (!inwait) {
+ putchar ('\n');
+ if (!startup) {
+ signal(SIGQUIT, onquit);
+ siglongjmp (restore, 1);
+ }
+ else
+ Pause++;
+ }
+ else if (!dum_opt && notell) {
+ promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
+ notell = 0;
+ }
+ signal(SIGQUIT, onquit);
+}
+
+/*
+** Come here if a signal for a window size change is received
+*/
+
+#ifdef SIGWINCH
+void chgwinsz(int dummy) {
+ struct winsize win;
+
+ (void) signal(SIGWINCH, SIG_IGN);
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
+ if (win.ws_row != 0) {
+ Lpp = win.ws_row;
+ nscroll = Lpp/2 - 1;
+ if (nscroll <= 0)
+ nscroll = 1;
+ dlines = Lpp - 1; /* was: Lpp - (noscroll ? 1 : 2) */
+ }
+ if (win.ws_col != 0)
+ Mcol = win.ws_col;
+ }
+ (void) signal(SIGWINCH, chgwinsz);
+}
+#endif
+
+/*
+** Clean up terminal state and exit. Also come here if interrupt signal received
+*/
+
+void end_it (int dummy) {
+ reset_tty ();
+ if (clreol) {
+ putchar ('\r');
+ clreos ();
+ fflush (stdout);
+ }
+ else if (!clreol && (promptlen > 0)) {
+ kill_line ();
+ fflush (stdout);
+ }
+ else
+ putcerr('\n');
+ _exit(0);
+}
+
+void copy_file(register FILE *f) {
+ register int c;
+
+ while ((c = getc(f)) != EOF)
+ putchar(c);
+}
+
+#define ringbell() putcerr('\007')
+
+/* See whether the last component of the path name "path" is equal to the
+** string "string"
+*/
+
+static int tailequ (char *path, register char *string)
+{
+ register char *tail;
+
+ tail = path + strlen(path);
+ while (--tail >= path)
+ if (*tail == '/')
+ break;
+ ++tail;
+ while (*tail++ == *string++)
+ if (*tail == '\0')
+ return(1);
+ return(0);
+}
+
+static void prompt (char *filename)
+{
+ if (clreol)
+ cleareol ();
+ else if (promptlen > 0)
+ kill_line ();
+ if (!hard) {
+ promptlen = 0;
+ if (Senter && Sexit) {
+ my_putstring (Senter);
+ promptlen += (2 * soglitch);
+ }
+ if (clreol)
+ cleareol ();
+ promptlen += printf(_("--More--"));
+ if (filename != NULL) {
+ promptlen += printf(_("(Next file: %s)"), filename);
+ } else if (!no_intty) {
+ promptlen += printf("(%d%%)", (int) ((file_pos * 100) / file_size));
+ }
+ if (dum_opt) {
+ promptlen += printf(_("[Press space to continue, 'q' to quit.]"));
+ }
+ if (Senter && Sexit)
+ my_putstring (Sexit);
+ if (clreol)
+ clreos ();
+ fflush(stdout);
+ }
+ else
+ ringbell();
+ inwait++;
+}
+
+/*
+ * Get a logical line
+ */
+
+int get_line(register FILE *f, int *length)
+{
+ int c;
+ char *p;
+ int column;
+ static int colflg;
+
+#ifdef HAVE_WIDECHAR
+ int i;
+ wchar_t wc;
+ int wc_width;
+ mbstate_t state, state_bak; /* Current status of the stream. */
+ char mbc[MB_LEN_MAX]; /* Buffer for one multibyte char. */
+ size_t mblength; /* Byte length of multibyte char. */
+ size_t mbc_pos = 0; /* Postion of the MBC. */
+ int use_mbc_buffer_flag = 0; /* If 1, mbc has data. */
+ int break_flag = 0; /* If 1, exit while(). */
+ long file_pos_bak = Ftell (f);
+
+ memset (&state, '\0', sizeof (mbstate_t));
+#endif
+
+ p = Line;
+ column = 0;
+ c = Getc (f);
+ if (colflg && c == '\n') {
+ Currline++;
+ c = Getc (f);
+ }
+ while (p < &Line[LINSIZ - 1]) {
+#ifdef HAVE_WIDECHAR
+ if (fold_opt && use_mbc_buffer_flag && MB_CUR_MAX > 1) {
+ use_mbc_buffer_flag = 0;
+ state_bak = state;
+ mbc[mbc_pos++] = c;
+process_mbc:
+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
+
+ switch (mblength) {
+ case (size_t)-2: /* Incomplete multibyte character. */
+ use_mbc_buffer_flag = 1;
+ state = state_bak;
+ break;
+
+ case (size_t)-1: /* Invalid as a multibyte character. */
+ *p++ = mbc[0];
+ state = state_bak;
+ column++;
+ file_pos_bak++;
+
+ if (column >= Mcol) {
+ Fseek (f, file_pos_bak);
+ } else {
+ memmove (mbc, mbc + 1, --mbc_pos);
+ if (mbc_pos > 0) {
+ mbc[mbc_pos] = '\0';
+ goto process_mbc;
+ }
+ }
+ break;
+
+ default:
+ wc_width = wcwidth (wc);
+
+ if (column + wc_width > Mcol) {
+ Fseek (f, file_pos_bak);
+ break_flag = 1;
+ } else {
+ for (i = 0; i < mbc_pos; i++)
+ *p++ = mbc[i];
+ if (wc_width > 0)
+ column += wc_width;
+ }
+ }
+
+ if (break_flag || column >= Mcol)
+ break;
+
+ c = Getc (f);
+ continue;
+ }
+#endif
+ if (c == EOF) {
+ if (p > Line) {
+ *p = '\0';
+ *length = p - Line;
+ return (column);
+ }
+ *length = p - Line;
+ return (EOF);
+ }
+ if (c == '\n') {
+ Currline++;
+ break;
+ }
+
+ *p++ = c;
+#if 0
+ if (c == '\033') { /* ESC */
+ c = Getc(f);
+ while (c > ' ' && c < '0' && p < &Line[LINSIZ - 1]) {
+ *p++ = c;
+ c = Getc(f);
+ }
+ if (c >= '0' && c < '\177' && p < &Line[LINSIZ - 1]) {
+ *p++ = c;
+ c = Getc(f);
+ continue;
+ }
+ }
+#endif
+ if (c == '\t') {
+ if (!hardtabs || (column < promptlen && !hard)) {
+ if (hardtabs && eraseln && !dumb) {
+ column = 1 + (column | 7);
+ my_putstring (eraseln);
+ promptlen = 0;
+ }
+ else {
+ for (--p; p < &Line[LINSIZ - 1];) {
+ *p++ = ' ';
+ if ((++column & 7) == 0)
+ break;
+ }
+ if (column >= promptlen) promptlen = 0;
+ }
+ } else
+ column = 1 + (column | 7);
+ } else if (c == '\b' && column > 0) {
+ column--;
+ } else if (c == '\r') {
+ int next = Getc(f);
+ if (next == '\n') {
+ p--;
+ Currline++;
+ break;
+ }
+ Ungetc(next,f);
+ column = 0;
+ } else if (c == '\f' && stop_opt) {
+ p[-1] = '^';
+ *p++ = 'L';
+ column += 2;
+ Pause++;
+ } else if (c == EOF) {
+ *length = p - Line;
+ return (column);
+ } else {
+#ifdef HAVE_WIDECHAR
+ if (fold_opt && MB_CUR_MAX > 1) {
+ memset (mbc, '\0', MB_LEN_MAX);
+ mbc_pos = 0;
+ mbc[mbc_pos++] = c;
+ state_bak = state;
+
+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
+
+ /* The value of mblength is always less than 2 here. */
+ switch (mblength) {
+ case (size_t)-2:
+ p--;
+ file_pos_bak = Ftell (f) - 1;
+ state = state_bak;
+ use_mbc_buffer_flag = 1;
+ break;
+
+ case (size_t)-1:
+ state = state_bak;
+ column++;
+ break;
+
+ default:
+ wc_width = wcwidth (wc);
+ if (wc_width > 0)
+ column += wc_width;
+ }
+ } else
+#endif
+ {
+ if (isprint(c))
+ column++;
+ }
+ }
+
+ if (column >= Mcol && fold_opt)
+ break;
+ c = Getc (f);
+ }
+ if (column >= Mcol && Mcol > 0) {
+ if (!Wrap) {
+ *p++ = '\n';
+ }
+ }
+ colflg = column == Mcol && fold_opt;
+ if (colflg && eatnl && Wrap) {
+ *p++ = '\n'; /* simulate normal wrap */
+ }
+ *length = p - Line;
+ *p = 0;
+ return (column);
+}
+
+/*
+** Erase the rest of the prompt, assuming we are starting at column col.
+*/
+
+void erasep (register int col)
+{
+
+ if (promptlen == 0)
+ return;
+ if (hard) {
+ putchar ('\n');
+ }
+ else {
+ if (col == 0)
+ putchar ('\r');
+ if (!dumb && eraseln)
+ my_putstring (eraseln);
+ else
+ for (col = promptlen - col; col > 0; col--)
+ putchar (' ');
+ }
+ promptlen = 0;
+}
+
+/*
+** Erase the current line entirely
+*/
+
+void kill_line()
+{
+ erasep(0);
+ if (!eraseln || dumb)
+ putchar('\r');
+}
+
+/*
+ * force clear to end of line
+ */
+void cleareol()
+{
+ my_putstring(eraseln);
+}
+
+void clreos()
+{
+ my_putstring(EodClr);
+}
+
+/* Print a buffer of n characters */
+
+void prbuf (register char *s, register int n)
+{
+ register char c; /* next output character */
+ register int state; /* next output char's UL state */
+#define wouldul(s,n) ((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_')))
+
+ while (--n >= 0)
+ if (!ul_opt)
+ putchar (*s++);
+ else {
+ if (*s == ' ' && pstate == 0 && ulglitch && wouldul(s+1, n-1)) {
+ s++;
+ continue;
+ }
+ if ((state = wouldul(s, n)) != 0) {
+ c = (*s == '_')? s[2] : *s ;
+ n -= 2;
+ s += 3;
+ } else
+ c = *s++;
+ if (state != pstate) {
+ if (c == ' ' && state == 0 && ulglitch && wouldul(s, n-1))
+ state = 1;
+ else
+ my_putstring(state ? ULenter : ULexit);
+ }
+ if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0)
+#ifdef HAVE_WIDECHAR
+ {
+ wchar_t wc;
+ size_t mblength;
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+ s--; n++;
+ mblength = mbrtowc (&wc, s, n, &state);
+ if (mblength == (size_t) -2 || mblength == (size_t) -1)
+ mblength = 1;
+ while (mblength--)
+ putchar (*s++);
+ n += mblength;
+ }
+#else
+ putchar(c);
+#endif /* HAVE_WIDECHAR */
+ if (state && *chUL) {
+ putsout(chBS);
+ my_putstring(chUL);
+ }
+ pstate = state;
+ }
+}
+
+/*
+** Clear the screen
+*/
+void
+doclear()
+{
+ if (Clear && !hard) {
+ my_putstring(Clear);
+
+ /* Put out carriage return so that system doesn't
+ ** get confused by escape sequences when expanding tabs
+ */
+ putchar ('\r');
+ promptlen = 0;
+ }
+}
+
+/*
+ * Go to home position
+ */
+void
+home()
+{
+ my_putstring(Home);
+}
+
+static int lastcmd, lastarg, lastp;
+static int lastcolon;
+char shell_line[1000];
+
+/*
+** Read a command and do it. A command consists of an optional integer
+** argument followed by the command character. Return the number of lines
+** to display in the next screenful. If there is nothing more to display
+** in the current file, zero is returned.
+*/
+
+int command (char *filename, register FILE *f)
+{
+ register int nlines;
+ register int retval = 0;
+ register int c;
+ char colonch;
+ int done;
+ char comchar, cmdbuf[80];
+
+#define ret(val) retval=val;done++;break
+
+ done = 0;
+ if (!errors)
+ prompt (filename);
+ else
+ errors = 0;
+ for (;;) {
+ nlines = number (&comchar);
+ lastp = colonch = 0;
+ if (comchar == '.') { /* Repeat last command */
+ lastp++;
+ comchar = lastcmd;
+ nlines = lastarg;
+ if (lastcmd == ':')
+ colonch = lastcolon;
+ }
+ lastcmd = comchar;
+ lastarg = nlines;
+ if ((cc_t) comchar == otty.c_cc[VERASE]) {
+ kill_line ();
+ prompt (filename);
+ continue;
+ }
+ switch (comchar) {
+ case ':':
+ retval = colon (filename, colonch, nlines);
+ if (retval >= 0)
+ done++;
+ break;
+ case 'b':
+ case ctrl('B'):
+ {
+ register int initline;
+
+ if (no_intty) {
+ ringbell();
+ return (-1);
+ }
+
+ if (nlines == 0) nlines++;
+
+ putchar ('\r');
+ erasep (0);
+ putchar('\n');
+ if (clreol)
+ cleareol ();
+ if (nlines != 1)
+ printf(_("...back %d pages"), nlines);
+ else
+ putsout(_("...back 1 page"));
+ if (clreol)
+ cleareol ();
+ putchar('\n');
+
+ initline = Currline - dlines * (nlines + 1);
+ if (! noscroll)
+ --initline;
+ if (initline < 0) initline = 0;
+ Fseek(f, 0L);
+ Currline = 0; /* skiplns() will make Currline correct */
+ skiplns(initline, f);
+ if (! noscroll) {
+ ret(dlines + 1);
+ }
+ else {
+ ret(dlines);
+ }
+ }
+ case ' ':
+ case 'z':
+ if (nlines == 0) nlines = dlines;
+ else if (comchar == 'z') dlines = nlines;
+ ret (nlines);
+ case 'd':
+ case ctrl('D'):
+ if (nlines != 0) nscroll = nlines;
+ ret (nscroll);
+ case 'q':
+ case 'Q':
+ end_it (0);
+ case 's':
+ case 'f':
+ case ctrl('F'):
+ if (nlines == 0) nlines++;
+ if (comchar == 'f')
+ nlines *= dlines;
+ putchar ('\r');
+ erasep (0);
+ putchar('\n');
+ if (clreol)
+ cleareol ();
+ if (nlines == 1)
+ putsout(_("...skipping one line"));
+ else
+ printf(_("...skipping %d lines"), nlines);
+
+ if (clreol)
+ cleareol ();
+ putchar('\n');
+
+ while (nlines > 0) {
+ while ((c = Getc (f)) != '\n')
+ if (c == EOF) {
+ retval = 0;
+ done++;
+ goto endsw;
+ }
+ Currline++;
+ nlines--;
+ }
+ ret (dlines);
+ case '\n':
+ if (nlines != 0)
+ dlines = nlines;
+ else
+ nlines = 1;
+ ret (nlines);
+ case '\f':
+ if (!no_intty) {
+ doclear ();
+ Fseek (f, screen_start.chrctr);
+ Currline = screen_start.line;
+ ret (dlines);
+ }
+ else {
+ ringbell();
+ break;
+ }
+ case '\'':
+ if (!no_intty) {
+ kill_line ();
+ putsout(_("\n***Back***\n\n"));
+ Fseek (f, context.chrctr);
+ Currline = context.line;
+ ret (dlines);
+ }
+ else {
+ ringbell();
+ break;
+ }
+ case '=':
+ kill_line ();
+ promptlen = printf("%d", Currline);
+ fflush (stdout);
+ break;
+ case 'n':
+ lastp++;
+ case '/':
+ if (nlines == 0) nlines++;
+ kill_line ();
+ putchar('/');
+ promptlen = 1;
+ fflush (stdout);
+ if (lastp) {
+ putcerr('\r');
+ search (NULL, f, nlines); /* Use previous r.e. */
+ }
+ else {
+ ttyin (cmdbuf, sizeof(cmdbuf)-2, '/');
+ putcerr('\r');
+ search (cmdbuf, f, nlines);
+ }
+ ret (dlines-1);
+ case '!':
+ do_shell (filename);
+ break;
+ case '?':
+ case 'h':
+ if (noscroll) doclear();
+ putsout(_("\n"
+"Most commands optionally preceded by integer argument k. "
+"Defaults in brackets.\n"
+"Star (*) indicates argument becomes new default.\n"));
+ puts("---------------------------------------"
+ "----------------------------------------");
+ putsout(_(
+"<space> Display next k lines of text [current screen size]\n"
+"z Display next k lines of text [current screen size]*\n"
+"<return> Display next k lines of text [1]*\n"
+"d or ctrl-D Scroll k lines [current scroll size, initially 11]*\n"
+"q or Q or <interrupt> Exit from more\n"
+"s Skip forward k lines of text [1]\n"
+"f Skip forward k screenfuls of text [1]\n"
+"b or ctrl-B Skip backwards k screenfuls of text [1]\n"
+"' Go to place where previous search started\n"
+"= Display current line number\n"
+"/<regular expression> Search for kth occurrence of regular expression [1]\n"
+"n Search for kth occurrence of last r.e [1]\n"
+"!<cmd> or :!<cmd> Execute <cmd> in a subshell\n"
+"v Start up /usr/bin/vi at current line\n"
+"ctrl-L Redraw screen\n"
+":n Go to kth next file [1]\n"
+":p Go to kth previous file [1]\n"
+":f Display current file name and line number\n"
+". Repeat previous command\n"));
+ puts("---------------------------------------"
+ "----------------------------------------");
+ prompt(filename);
+ break;
+ case 'v': /* This case should go right before default */
+ if (!no_intty) {
+ /*
+ * Earlier: call vi +n file. This also works for emacs.
+ * POSIX: call vi -c n file (when editor is vi or ex).
+ */
+ char *editor, *p;
+ int n = (Currline - dlines <= 0 ? 1 :
+ Currline - (dlines + 1) / 2);
+ int split = 0;
+
+ editor = getenv("VISUAL");
+ if (editor == NULL || *editor == '\0')
+ editor = getenv("EDITOR");
+ if (editor == NULL || *editor == '\0')
+ editor = VI;
+
+ p = strrchr(editor, '/');
+ if (p)
+ p++;
+ else
+ p = editor;
+ if (!strcmp(p, "vi") || !strcmp(p, "ex")) {
+ sprintf(cmdbuf, "-c %d", n);
+ split = 1;
+ } else {
+ sprintf(cmdbuf, "+%d", n);
+ }
+
+ kill_line();
+ printf("%s %s %s", editor, cmdbuf, fnames[fnum]);
+ if (split) {
+ cmdbuf[2] = 0;
+ execute(filename, editor, editor, cmdbuf,
+ cmdbuf+3, fnames[fnum], (char *)0);
+ } else
+ execute(filename, editor, editor,
+ cmdbuf, fnames[fnum], (char *)0);
+ break;
+ }
+ /* fall through */
+ default:
+ if (dum_opt) {
+ kill_line ();
+ if (Senter && Sexit) {
+ my_putstring (Senter);
+ promptlen = printf(_("[Press 'h' for instructions.]"))
+ + 2 * soglitch;
+ my_putstring (Sexit);
+ }
+ else
+ promptlen = printf(_("[Press 'h' for instructions.]"));
+ fflush (stdout);
+ }
+ else
+ ringbell();
+ break;
+ }
+ if (done) break;
+ }
+ putchar ('\r');
+endsw:
+ inwait = 0;
+ notell++;
+ return (retval);
+}
+
+static char ch;
+
+/*
+ * Execute a colon-prefixed command.
+ * Returns <0 if not a command that should cause
+ * more of the file to be printed.
+ */
+
+int colon (char *filename, int cmd, int nlines) {
+ if (cmd == 0)
+ ch = readch ();
+ else
+ ch = cmd;
+ lastcolon = ch;
+ switch (ch) {
+ case 'f':
+ kill_line ();
+ if (!no_intty)
+ promptlen = printf(_("\"%s\" line %d"), fnames[fnum], Currline);
+ else
+ promptlen = printf(_("[Not a file] line %d"), Currline);
+ fflush (stdout);
+ return (-1);
+ case 'n':
+ if (nlines == 0) {
+ if (fnum >= nfiles - 1)
+ end_it (0);
+ nlines++;
+ }
+ putchar ('\r');
+ erasep (0);
+ skipf (nlines);
+ return (0);
+ case 'p':
+ if (no_intty) {
+ ringbell();
+ return (-1);
+ }
+ putchar ('\r');
+ erasep (0);
+ if (nlines == 0)
+ nlines++;
+ skipf (-nlines);
+ return (0);
+ case '!':
+ do_shell (filename);
+ return (-1);
+ case 'q':
+ case 'Q':
+ end_it (0);
+ default:
+ ringbell();
+ return (-1);
+ }
+}
+
+/*
+** Read a decimal number from the terminal. Set cmd to the non-digit which
+** terminates the number.
+*/
+
+int number(char *cmd)
+{
+ register int i;
+
+ i = 0; ch = otty.c_cc[VKILL];
+ for (;;) {
+ ch = readch ();
+ if (isdigit(ch))
+ i = i*10 + ch - '0';
+ else if ((cc_t) ch == otty.c_cc[VKILL])
+ i = 0;
+ else {
+ *cmd = ch;
+ break;
+ }
+ }
+ return (i);
+}
+
+void do_shell (char *filename)
+{
+ char cmdbuf[200];
+ int rc;
+ char *expanded;
+
+ kill_line ();
+ putchar('!');
+ fflush (stdout);
+ promptlen = 1;
+ if (lastp)
+ putsout(shell_line);
+ else {
+ ttyin (cmdbuf, sizeof(cmdbuf)-2, '!');
+ expanded = 0;
+ rc = expand (&expanded, cmdbuf);
+ if (expanded) {
+ if (strlen(expanded) < sizeof(shell_line))
+ strcpy(shell_line, expanded);
+ else
+ rc = -1;
+ free(expanded);
+ }
+ if (rc < 0) {
+ putserr(_(" Overflow\n"));
+ prompt (filename);
+ return;
+ } else if (rc > 0) {
+ kill_line ();
+ promptlen = printf("!%s", shell_line);
+ }
+ }
+ fflush (stdout);
+ putcerr('\n');
+ promptlen = 0;
+ shellp = 1;
+ execute (filename, shell, shell, "-c", shell_line, 0);
+}
+
+/*
+** Search for nth ocurrence of regular expression contained in buf in the file
+*/
+
+void search(char buf[], FILE *file, register int n)
+{
+ long startline = Ftell (file);
+ register long line1 = startline;
+ register long line2 = startline;
+ register long line3 = startline;
+ register int lncount;
+ int saveln, rv;
+ char *s;
+
+ context.line = saveln = Currline;
+ context.chrctr = startline;
+ lncount = 0;
+ if ((s = re_comp (buf)) != 0)
+ error (s);
+ while (!feof (file)) {
+ line3 = line2;
+ line2 = line1;
+ line1 = Ftell (file);
+ rdline (file);
+ lncount++;
+ if ((rv = re_exec (Line)) == 1) {
+ if (--n == 0) {
+ if (lncount > 3 || (lncount > 1 && no_intty))
+ {
+ putchar('\n');
+ if (clreol)
+ cleareol ();
+ putsout(_("...skipping\n"));
+ }
+ if (!no_intty) {
+ Currline -= (lncount >= 3 ? 3 : lncount);
+ Fseek (file, line3);
+ if (noscroll) {
+ if (clreol) {
+ home ();
+ cleareol ();
+ }
+ else
+ doclear ();
+ }
+ }
+ else {
+ kill_line ();
+ if (noscroll) {
+ if (clreol) {
+ home ();
+ cleareol ();
+ }
+ else
+ doclear ();
+ }
+ puts(Line);
+ }
+ break;
+ }
+ } else if (rv == -1)
+ error (_("Regular expression botch"));
+ }
+ if (feof (file)) {
+ if (!no_intty) {
+ Currline = saveln;
+ Fseek (file, startline);
+ }
+ else {
+ putsout(_("\nPattern not found\n"));
+ end_it (0);
+ }
+ error (_("Pattern not found"));
+ }
+}
+
+/*VARARGS2*/
+void execute (char *filename, char *cmd, ...)
+{
+ int id;
+ int n;
+ va_list argp;
+ char * arg;
+ char ** args;
+ int argcount;
+
+ fflush (stdout);
+ reset_tty ();
+ for (n = 10; (id = fork ()) < 0 && n > 0; n--)
+ sleep (5);
+ if (id == 0) {
+ if (!isatty(0)) {
+ close(0);
+ open("/dev/tty", 0);
+ }
+
+ va_start(argp, cmd);
+ arg = va_arg(argp, char *);
+ argcount = 0;
+ while (arg) {
+ argcount++;
+ arg = va_arg(argp, char *);
+ }
+ va_end(argp);
+
+ args = alloca(sizeof(char *) * (argcount + 1));
+ args[argcount] = NULL;
+
+ va_start(argp, cmd);
+ arg = va_arg(argp, char *);
+ argcount = 0;
+ while (arg) {
+ args[argcount] = arg;
+ argcount++;
+ arg = va_arg(argp, char *);
+ }
+ va_end(argp);
+
+ execvp (cmd, args);
+ putserr(_("exec failed\n"));
+ exit (1);
+ }
+ if (id > 0) {
+ signal (SIGINT, SIG_IGN);
+ signal (SIGQUIT, SIG_IGN);
+ if (catch_susp)
+ signal(SIGTSTP, SIG_DFL);
+ while (wait(0) > 0);
+ signal (SIGINT, end_it);
+ signal (SIGQUIT, onquit);
+ if (catch_susp)
+ signal(SIGTSTP, onsusp);
+ } else
+ putserr(_("can't fork\n"));
+ set_tty ();
+ puts("------------------------");
+ prompt (filename);
+}
+/*
+** Skip n lines in the file f
+*/
+
+void skiplns (register int n, register FILE *f)
+{
+ register int c;
+
+ while (n > 0) {
+ while ((c = Getc (f)) != '\n')
+ if (c == EOF)
+ return;
+ n--;
+ Currline++;
+ }
+}
+
+/*
+** Skip nskip files in the file list (from the command line). Nskip may be
+** negative.
+*/
+
+void skipf (register int nskip)
+{
+ if (nskip == 0) return;
+ if (nskip > 0) {
+ if (fnum + nskip > nfiles - 1)
+ nskip = nfiles - fnum - 1;
+ }
+ else if (within)
+ ++fnum;
+ fnum += nskip;
+ if (fnum < 0)
+ fnum = 0;
+ puts(_("\n...Skipping "));
+ if (clreol)
+ cleareol ();
+ if (nskip > 0)
+ putsout(_("...Skipping to file "));
+ else
+ putsout(_("...Skipping back to file "));
+ puts(fnames[fnum]);
+ if (clreol)
+ cleareol ();
+ putchar('\n');
+ --fnum;
+}
+
+/*----------------------------- Terminal I/O -------------------------------*/
+
+void initterm()
+{
+ int ret;
+ char *padstr;
+ char *term;
+ struct winsize win;
+
+#ifdef do_SIGTTOU
+retry:
+#endif
+ no_tty = tcgetattr(fileno(stdout), &otty);
+ if (!no_tty) {
+ docrterase = (otty.c_cc[VERASE] != 255);
+ docrtkill = (otty.c_cc[VKILL] != 255);
+#ifdef do_SIGTTOU
+ {
+ int tgrp;
+ /*
+ * Wait until we're in the foreground before we save the
+ * the terminal modes.
+ */
+ if ((tgrp = tcgetpgrp(fileno(stdout))) < 0) {
+ perror("tcgetpgrp");
+ exit(1);
+ }
+ if (tgrp != getpgrp(0)) {
+ kill(0, SIGTTOU);
+ goto retry;
+ }
+ }
+#endif
+ if ((term = getenv("TERM")) == 0) {
+ dumb++; ul_opt = 0;
+ }
+ my_setupterm(term, 1, &ret);
+ if (ret <= 0) {
+ dumb++; ul_opt = 0;
+ }
+ else {
+#ifdef TIOCGWINSZ
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
+#endif
+ Lpp = my_tgetnum("li","lines");
+ Mcol = my_tgetnum("co","cols");
+#ifdef TIOCGWINSZ
+ } else {
+ if ((Lpp = win.ws_row) == 0)
+ Lpp = my_tgetnum("li","lines");
+ if ((Mcol = win.ws_col) == 0)
+ Mcol = my_tgetnum("co","cols");
+ }
+#endif
+ if ((Lpp <= 0) || my_tgetflag("hc","hc")) {
+ hard++; /* Hard copy terminal */
+ Lpp = 24;
+ }
+
+ if (my_tgetflag("xn","xenl"))
+ eatnl++; /* Eat newline at last column + 1; dec, concept */
+ if (Mcol <= 0)
+ Mcol = 80;
+
+ if (tailequ (fnames[0], "page"))
+ noscroll++;
+ Wrap = my_tgetflag("am","am");
+ bad_so = my_tgetflag ("xs","xhp");
+ eraseln = my_tgetstr("ce","el");
+ Clear = my_tgetstr("cl","clear");
+ Senter = my_tgetstr("so","smso");
+ Sexit = my_tgetstr("se","rmso");
+ if ((soglitch = my_tgetnum("sg","xmc")) < 0)
+ soglitch = 0;
+
+ /*
+ * Set up for underlining: some terminals don't need it;
+ * others have start/stop sequences, still others have an
+ * underline char sequence which is assumed to move the
+ * cursor forward one character. If underline sequence
+ * isn't available, settle for standout sequence.
+ */
+
+ if (my_tgetflag("ul","ul") || my_tgetflag("os","os"))
+ ul_opt = 0;
+ if ((chUL = my_tgetstr("uc","uc")) == NULL )
+ chUL = "";
+ if (((ULenter = my_tgetstr("us","smul")) == NULL ||
+ (ULexit = my_tgetstr("ue","rmul")) == NULL) && !*chUL) {
+ if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) {
+ ULenter = "";
+ ULexit = "";
+ } else
+ ulglitch = soglitch;
+ } else {
+ ulglitch = 0;
+ }
+
+ if ((padstr = my_tgetstr("pc","pad")) != NULL)
+ PC = *padstr;
+ Home = my_tgetstr("ho","home");
+ if (Home == 0 || *Home == '\0') {
+ if ((cursorm = my_tgetstr("cm","cup")) != NULL) {
+ const char *t = (const char *)my_tgoto(cursorm, 0, 0);
+ xstrncpy(cursorhome, t, sizeof(cursorhome));
+ Home = cursorhome;
+ }
+ }
+ EodClr = my_tgetstr("cd","ed");
+ if ((chBS = my_tgetstr("le","cub1")) == NULL)
+ chBS = "\b";
+
+ }
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = "/bin/sh";
+ }
+ no_intty = tcgetattr(fileno(stdin), &otty);
+ tcgetattr(fileno(stderr), &otty);
+ savetty0 = otty;
+ slow_tty = cfgetispeed(&otty) < B1200;
+ hardtabs = (otty.c_oflag & TABDLY) != XTABS;
+ if (!no_tty) {
+ otty.c_lflag &= ~(ICANON|ECHO);
+ otty.c_cc[VMIN] = 1;
+ otty.c_cc[VTIME] = 0;
+ }
+}
+
+int readch () {
+ unsigned char c;
+
+ errno = 0;
+ if (read (fileno(stderr), &c, 1) <= 0) {
+ if (errno != EINTR)
+ end_it(0);
+ else
+ c = otty.c_cc[VKILL];
+ }
+ return (c);
+}
+
+static char *BS = "\b";
+static char *BSB = "\b \b";
+static char *CARAT = "^";
+#define ERASEONECOLUMN \
+ if (docrterase) \
+ putserr(BSB); \
+ else \
+ putserr(BS);
+
+void ttyin (char buf[], register int nmax, char pchar) {
+ char *sp;
+ int c;
+ int slash = 0;
+ int maxlen;
+
+ sp = buf;
+ maxlen = 0;
+ while (sp - buf < nmax) {
+ if (promptlen > maxlen) maxlen = promptlen;
+ c = readch ();
+ if (c == '\\') {
+ slash++;
+ }
+ else if (((cc_t) c == otty.c_cc[VERASE]) && !slash) {
+ if (sp > buf) {
+#ifdef HAVE_WIDECHAR
+ if (MB_CUR_MAX > 1)
+ {
+ wchar_t wc;
+ size_t pos = 0, mblength;
+ mbstate_t state, state_bak;
+
+ memset (&state, '\0', sizeof (mbstate_t));
+
+ while (1) {
+ state_bak = state;
+ mblength = mbrtowc (&wc, buf + pos, sp - buf, &state);
+
+ state = (mblength == (size_t)-2
+ || mblength == (size_t)-1) ? state_bak : state;
+ mblength = (mblength == (size_t)-2
+ || mblength == (size_t)-1
+ || mblength == 0) ? 1 : mblength;
+
+ if (buf + pos + mblength >= sp)
+ break;
+
+ pos += mblength;
+ }
+
+ if (mblength == 1) {
+ ERASEONECOLUMN
+ }
+ else {
+ int wc_width;
+ wc_width = wcwidth (wc);
+ wc_width = (wc_width < 1) ? 1 : wc_width;
+ while (wc_width--) {
+ ERASEONECOLUMN
+ }
+ }
+
+ while (mblength--) {
+ --promptlen;
+ --sp;
+ }
+ }
+ else
+#endif
+ {
+ --promptlen;
+ ERASEONECOLUMN
+ --sp;
+ }
+
+ if ((*sp < ' ' && *sp != '\n') || *sp == RUBOUT) {
+ --promptlen;
+ ERASEONECOLUMN
+ }
+ continue;
+ }
+ else {
+ if (!eraseln) promptlen = maxlen;
+ siglongjmp (restore, 1);
+ }
+ }
+ else if (((cc_t) c == otty.c_cc[VKILL]) && !slash) {
+ if (hard) {
+ show (c);
+ putchar ('\n');
+ putchar (pchar);
+ }
+ else {
+ putchar ('\r');
+ putchar (pchar);
+ if (eraseln)
+ erasep (1);
+ else if (docrtkill)
+ while (promptlen-- > 1)
+ putserr(BSB);
+ promptlen = 1;
+ }
+ sp = buf;
+ fflush (stdout);
+ continue;
+ }
+ if (slash && ((cc_t) c == otty.c_cc[VKILL]
+ || (cc_t) c == otty.c_cc[VERASE])) {
+ ERASEONECOLUMN
+ --sp;
+ }
+ if (c != '\\')
+ slash = 0;
+ *sp++ = c;
+ if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
+ c += (c == RUBOUT) ? -0100 : 0100;
+ putserr(CARAT);
+ promptlen++;
+ }
+ if (c != '\n' && c != ESC) {
+ putcerr(c);
+ promptlen++;
+ }
+ else
+ break;
+ }
+ *--sp = '\0';
+ if (!eraseln) promptlen = maxlen;
+ if (sp - buf >= nmax - 1)
+ error (_("Line too long"));
+}
+
+/* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */
+int expand (char **outbuf, char *inbuf) {
+ char *inpstr;
+ char *outstr;
+ char c;
+ char *temp;
+ int changed = 0;
+ int tempsz, xtra, offset;
+
+ xtra = strlen (fnames[fnum]) + strlen (shell_line) + 1;
+ tempsz = 200 + xtra;
+ temp = malloc(tempsz);
+ if (!temp) {
+ error (_("Out of memory"));
+ return -1;
+ }
+ inpstr = inbuf;
+ outstr = temp;
+ while ((c = *inpstr++) != '\0'){
+ offset = outstr-temp;
+ if (tempsz-offset-1 < xtra) {
+ tempsz += 200 + xtra;
+ temp = realloc(temp, tempsz);
+ if (!temp) {
+ error (_("Out of memory"));
+ return -1;
+ }
+ outstr = temp + offset;
+ }
+ switch (c) {
+ case '%':
+ if (!no_intty) {
+ strcpy (outstr, fnames[fnum]);
+ outstr += strlen (fnames[fnum]);
+ changed++;
+ } else
+ *outstr++ = c;
+ break;
+ case '!':
+ if (!shellp)
+ error (_("No previous command to substitute for"));
+ strcpy (outstr, shell_line);
+ outstr += strlen (shell_line);
+ changed++;
+ break;
+ case '\\':
+ if (*inpstr == '%' || *inpstr == '!') {
+ *outstr++ = *inpstr++;
+ break;
+ }
+ default:
+ *outstr++ = c;
+ }
+ }
+ *outstr++ = '\0';
+ *outbuf = temp;
+ return (changed);
+}
+
+void show (char c) {
+ if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
+ c += (c == RUBOUT) ? -0100 : 0100;
+ putserr(CARAT);
+ promptlen++;
+ }
+ putcerr(c);
+ promptlen++;
+}
+
+void error (char *mess)
+{
+ if (clreol)
+ cleareol ();
+ else
+ kill_line ();
+ promptlen += strlen (mess);
+ if (Senter && Sexit) {
+ my_putstring (Senter);
+ putsout(mess);
+ my_putstring (Sexit);
+ }
+ else
+ putsout(mess);
+ fflush(stdout);
+ errors++;
+ siglongjmp (restore, 1);
+}
+
+
+void set_tty () {
+ otty.c_lflag &= ~(ICANON|ECHO);
+ otty.c_cc[VMIN] = 1; /* read at least 1 char */
+ otty.c_cc[VTIME] = 0; /* no timeout */
+ stty(fileno(stderr), &otty);
+}
+
+static int
+ourputch(int c) {
+ return putc(c, stdout);
+}
+
+void
+reset_tty () {
+ if (no_tty)
+ return;
+ if (pstate) {
+ tputs(ULexit, 1, ourputch); /* putchar - if that isnt a macro */
+ fflush(stdout);
+ pstate = 0;
+ }
+ otty.c_lflag |= ICANON|ECHO;
+ otty.c_cc[VMIN] = savetty0.c_cc[VMIN];
+ otty.c_cc[VTIME] = savetty0.c_cc[VTIME];
+ stty(fileno(stderr), &savetty0);
+}
+
+void rdline (register FILE *f)
+{
+ register int c;
+ register char *p;
+
+ p = Line;
+ while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
+ *p++ = c;
+ if (c == '\n')
+ Currline++;
+ *p = '\0';
+}
+
+/* Come here when we get a suspend signal from the terminal */
+
+void onsusp (int dummy) {
+ sigset_t signals, oldmask;
+
+ /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+ signal(SIGTTOU, SIG_IGN);
+ reset_tty ();
+ fflush (stdout);
+ signal(SIGTTOU, SIG_DFL);
+ /* Send the TSTP signal to suspend our process group */
+ signal(SIGTSTP, SIG_DFL);
+
+ /* unblock SIGTSTP or we won't be able to suspend ourself */
+ sigemptyset(&signals);
+ sigaddset(&signals, SIGTSTP);
+ sigprocmask(SIG_UNBLOCK, &signals, &oldmask);
+
+ kill (0, SIGTSTP);
+ /* Pause for station break */
+
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+
+ /* We're back */
+ signal (SIGTSTP, onsusp);
+ set_tty ();
+ if (inwait)
+ siglongjmp (restore, 1);
+}
diff --git a/text-utils/odsyntax.c b/text-utils/odsyntax.c
new file mode 100644
index 0000000..e7711f9
--- /dev/null
+++ b/text-utils/odsyntax.c
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h> /* for isdigit() */
+#include <unistd.h> /* for getopt() */
+#include "hexdump.h"
+#include "nls.h"
+
+static void odoffset(int, char ***);
+static void odprecede(void);
+
+int deprecated;
+
+void
+oldsyntax(int argc, char ***argvp)
+{
+ int ch;
+ char **argv;
+
+ deprecated = 1;
+ argv = *argvp;
+ while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != -1)
+ switch (ch) {
+ case 'a':
+ odprecede();
+ add("16/1 \"%3_u \" \"\\n\"");
+ break;
+ case 'B':
+ case 'o':
+ odprecede();
+ add("8/2 \" %06o \" \"\\n\"");
+ break;
+ case 'b':
+ odprecede();
+ add("16/1 \"%03o \" \"\\n\"");
+ break;
+ case 'c':
+ odprecede();
+ add("16/1 \"%3_c \" \"\\n\"");
+ break;
+ case 'd':
+ odprecede();
+ add("8/2 \" %05u \" \"\\n\"");
+ break;
+ case 'D':
+ odprecede();
+ add("4/4 \" %010u \" \"\\n\"");
+ break;
+ case 'e': /* undocumented in od */
+ case 'F':
+ odprecede();
+ add("2/8 \" %21.14e \" \"\\n\"");
+ break;
+
+ case 'f':
+ odprecede();
+ add("4/4 \" %14.7e \" \"\\n\"");
+ break;
+ case 'H':
+ case 'X':
+ odprecede();
+ add("4/4 \" %08x \" \"\\n\"");
+ break;
+ case 'h':
+ case 'x':
+ odprecede();
+ add("8/2 \" %04x \" \"\\n\"");
+ break;
+ case 'I':
+ case 'L':
+ case 'l':
+ odprecede();
+ add("4/4 \" %11d \" \"\\n\"");
+ break;
+ case 'i':
+ odprecede();
+ add("8/2 \" %6d \" \"\\n\"");
+ break;
+ case 'O':
+ odprecede();
+ add("4/4 \" %011o \" \"\\n\"");
+ break;
+ case 'v':
+ vflag = ALL;
+ break;
+ case 'P':
+ case 'p':
+ case 's':
+ case 'w':
+ case '?':
+ default:
+ fprintf(stderr,
+ _("od: od(1) has been deprecated for hexdump(1).\n"));
+ if (ch != '?')
+ fprintf(stderr,
+_("od: hexdump(1) compatibility doesn't support the -%c option%s\n"),
+ ch, ch == 's' ? _("; see strings(1).") : ".");
+ usage();
+ }
+
+ if (!fshead) {
+ add("\"%07.7_Ao\n\"");
+ add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\"");
+ }
+
+ argc -= optind;
+ *argvp += optind;
+
+ if (argc)
+ odoffset(argc, argvp);
+}
+
+#define ishexdigit(c) \
+ ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+
+static void
+odoffset(int argc, char ***argvp)
+{
+ char *num, *p;
+ int base;
+ char *end;
+
+ /*
+ * The offset syntax of od(1) was genuinely bizarre. First, if
+ * it started with a plus it had to be an offset. Otherwise, if
+ * there were at least two arguments, a number or lower-case 'x'
+ * followed by a number makes it an offset. By default it was
+ * octal; if it started with 'x' or '0x' it was hex. If it ended
+ * in a '.', it was decimal. If a 'b' or 'B' was appended, it
+ * multiplied the number by 512 or 1024 byte units. There was
+ * no way to assign a block count to a hex offset.
+ *
+ * We assume it's a file if the offset is bad.
+ */
+ p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
+ if (!p)
+ return;
+
+ if (*p != '+' && (argc < 2 ||
+ (!isdigit((unsigned char)p[0]) &&
+ (p[0] != 'x' || !ishexdigit(p[1])))))
+ return;
+
+ base = 0;
+ /*
+ * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
+ * set base.
+ */
+ if (p[0] == '+')
+ ++p;
+ if (p[0] == 'x' && ishexdigit(p[1])) {
+ ++p;
+ base = 16;
+ } else if (p[0] == '0' && p[1] == 'x') {
+ p += 2;
+ base = 16;
+ }
+
+ /* skip over the number */
+ if (base == 16)
+ for (num = p; ishexdigit(*p); ++p);
+ else
+ for (num = p; isdigit((unsigned char)*p); ++p);
+
+ /* check for no number */
+ if (num == p)
+ return;
+
+ /* if terminates with a '.', base is decimal */
+ if (*p == '.') {
+ if (base)
+ return;
+ base = 10;
+ }
+
+ skip = strtol(num, &end, base ? base : 8);
+
+ /* if end isn't the same as p, we got a non-octal digit */
+ if (end != p) {
+ skip = 0;
+ return;
+ }
+
+ if (*p) {
+ if (*p == 'B') {
+ skip *= 1024;
+ p++;
+ } else if (*p == 'b') {
+ skip *= 512;
+ p++;
+ }
+ }
+
+ if (*p) {
+ skip = 0;
+ return;
+ }
+
+ /*
+ * If the offset uses a non-octal base, the base of
+ * the offset is changed as well. This isn't pretty,
+ * but it's easy.
+ */
+#define TYPE_OFFSET 7
+ if (base == 16) {
+ fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
+ fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
+ } else if (base == 10) {
+ fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
+ fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
+ }
+
+ /* Terminate file list. */
+ (*argvp)[1] = NULL;
+}
+
+static void
+odprecede(void)
+{
+ static int first = 1;
+
+ if (first) {
+ first = 0;
+ add("\"%07.7_Ao\n\"");
+ add("\"%07.7_ao \"");
+ } else
+ add("\" \"");
+}
diff --git a/text-utils/parse.c b/text-utils/parse.c
new file mode 100644
index 0000000..8164c60
--- /dev/null
+++ b/text-utils/parse.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "hexdump.h"
+#include "nls.h"
+
+static void escape(char *p1);
+static void badcnt(const char *s);
+static void badsfmt(void);
+static void badfmt(const char *fmt);
+static void badconv(const char *ch);
+
+FU *endfu; /* format at end-of-data */
+
+void addfile(char *name)
+{
+ char *p;
+ FILE *fp;
+ int ch;
+ char buf[2048 + 1];
+
+ if ((fp = fopen(name, "r")) == NULL) {
+ (void)fprintf(stderr, _("hexdump: can't read %s.\n"), name);
+ exit(1);
+ }
+ while (fgets(buf, sizeof(buf), fp)) {
+ if ((p = strchr(buf, '\n')) == NULL) {
+ (void)fprintf(stderr, _("hexdump: line too long.\n"));
+ while ((ch = getchar()) != '\n' && ch != EOF);
+ continue;
+ }
+ *p = '\0';
+ for (p = buf; *p && isspace((unsigned char)*p); ++p);
+ if (!*p || *p == '#')
+ continue;
+ add(p);
+ }
+ (void)fclose(fp);
+}
+
+void add(const char *fmt)
+{
+ const char *p;
+ static FS **nextfs;
+ FS *tfs;
+ FU *tfu, **nextfu;
+ const char *savep;
+
+ /* Start new linked list of format units. */
+ tfs = emalloc(sizeof(FS));
+ if (!fshead)
+ fshead = tfs;
+ else
+ *nextfs = tfs;
+ nextfs = &tfs->nextfs;
+ nextfu = &tfs->nextfu;
+
+ /* Take the format string and break it up into format units. */
+ for (p = fmt;;) {
+ /* Skip leading white space. */
+ for (; isspace((unsigned char)*p); ++p);
+ if (!*p)
+ break;
+
+ /* Allocate a new format unit and link it in. */
+ tfu = emalloc(sizeof(FU));
+ *nextfu = tfu;
+ nextfu = &tfu->nextfu;
+ tfu->reps = 1;
+
+ /* If leading digit, repetition count. */
+ if (isdigit((unsigned char)*p)) {
+ for (savep = p; isdigit((unsigned char)*p); ++p);
+ if (!isspace((unsigned char)*p) && *p != '/')
+ badfmt(fmt);
+ /* may overwrite either white space or slash */
+ tfu->reps = atoi(savep);
+ tfu->flags = F_SETREP;
+ /* skip trailing white space */
+ for (++p; isspace((unsigned char)*p); ++p);
+ }
+
+ /* Skip slash and trailing white space. */
+ if (*p == '/')
+ while (isspace((unsigned char)*++p));
+
+ /* byte count */
+ if (isdigit((unsigned char)*p)) {
+ for (savep = p; isdigit((unsigned char)*p); ++p);
+ if (!isspace((unsigned char)*p))
+ badfmt(fmt);
+ tfu->bcnt = atoi(savep);
+ /* skip trailing white space */
+ for (++p; isspace((unsigned char)*p); ++p);
+ }
+
+ /* format */
+ if (*p != '"')
+ badfmt(fmt);
+ for (savep = ++p; *p != '"';)
+ if (*p++ == 0)
+ badfmt(fmt);
+ if (!(tfu->fmt = malloc(p - savep + 1)))
+ nomem();
+ (void) strncpy(tfu->fmt, savep, p - savep);
+ tfu->fmt[p - savep] = '\0';
+ escape(tfu->fmt);
+ p++;
+ }
+}
+
+static const char *spec = ".#-+ 0123456789";
+
+int size(FS *fs)
+{
+ FU *fu;
+ int bcnt, cursize;
+ char *fmt;
+ int prec;
+
+ /* figure out the data block size needed for each format unit */
+ for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (fu->bcnt) {
+ cursize += fu->bcnt * fu->reps;
+ continue;
+ }
+ for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
+ if (*fmt != '%')
+ continue;
+ /*
+ * skip any special chars -- save precision in
+ * case it's a %s format.
+ */
+ while (strchr(spec + 1, *++fmt));
+ if (*fmt == '.' && isdigit((unsigned char)*++fmt)) {
+ prec = atoi(fmt);
+ while (isdigit((unsigned char)*++fmt));
+ }
+ switch(*fmt) {
+ case 'c':
+ bcnt += 1;
+ break;
+ case 'd': case 'i': case 'o': case 'u':
+ case 'x': case 'X':
+ bcnt += 4;
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ bcnt += 8;
+ break;
+ case 's':
+ bcnt += prec;
+ break;
+ case '_':
+ switch(*++fmt) {
+ case 'c': case 'p': case 'u':
+ bcnt += 1;
+ break;
+ }
+ }
+ }
+ cursize += bcnt * fu->reps;
+ }
+ return(cursize);
+}
+
+void rewrite(FS *fs)
+{
+ enum { NOTOKAY, USEBCNT, USEPREC } sokay;
+ PR *pr, **nextpr;
+ FU *fu;
+ char *p1, *p2;
+ char savech, *fmtp, cs[3];
+ int nconv, prec;
+
+ nextpr = NULL;
+ prec = 0;
+
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ /*
+ * Break each format unit into print units; each
+ * conversion character gets its own.
+ */
+ for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
+ pr = emalloc(sizeof(PR));
+ if (!fu->nextpr)
+ fu->nextpr = pr;
+ else
+ *nextpr = pr;
+
+ /* Skip preceding text and up to the next % sign. */
+ for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
+
+ /* Only text in the string. */
+ if (!*p1) {
+ pr->fmt = fmtp;
+ pr->flags = F_TEXT;
+ break;
+ }
+
+ /*
+ * Get precision for %s -- if have a byte count, don't
+ * need it.
+ */
+ if (fu->bcnt) {
+ sokay = USEBCNT;
+ /* skip to conversion character */
+ for (++p1; strchr(spec, *p1); ++p1);
+ } else {
+ /* skip any special chars, field width */
+ while (strchr(spec + 1, *++p1));
+ if (*p1 == '.' &&
+ isdigit((unsigned char)*++p1)) {
+ sokay = USEPREC;
+ prec = atoi(p1);
+ while (isdigit((unsigned char)*++p1));
+ } else
+ sokay = NOTOKAY;
+ }
+
+ p2 = p1 + 1; /* Set end pointer. */
+ cs[0] = *p1; /* Set conversion string. */
+ cs[1] = 0;
+
+ /*
+ * Figure out the byte count for each conversion;
+ * rewrite the format as necessary, set up blank-
+ * padding for end of data.
+ */
+ switch(cs[0]) {
+ case 'c':
+ pr->flags = F_CHAR;
+ switch(fu->bcnt) {
+ case 0: case 1:
+ pr->bcnt = 1;
+ break;
+ default:
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ break;
+ case 'd': case 'i':
+ pr->flags = F_INT;
+ goto isint;
+ case 'o': case 'u': case 'x': case 'X':
+ pr->flags = F_UINT;
+isint: cs[2] = '\0';
+ cs[1] = cs[0];
+ cs[0] = 'q';
+ switch(fu->bcnt) {
+ case 0: case 4:
+ pr->bcnt = 4;
+ break;
+ case 1:
+ pr->bcnt = 1;
+ break;
+ case 2:
+ pr->bcnt = 2;
+ break;
+ case 8:
+ pr->bcnt = 8;
+ break;
+ default:
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ pr->flags = F_DBL;
+ switch(fu->bcnt) {
+ case 0: case 8:
+ pr->bcnt = 8;
+ break;
+ case 4:
+ pr->bcnt = 4;
+ break;
+ default:
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ break;
+ case 's':
+ pr->flags = F_STR;
+ switch(sokay) {
+ case NOTOKAY:
+ badsfmt();
+ case USEBCNT:
+ pr->bcnt = fu->bcnt;
+ break;
+ case USEPREC:
+ pr->bcnt = prec;
+ break;
+ }
+ break;
+ case '_':
+ ++p2;
+ switch(p1[1]) {
+ case 'A':
+ endfu = fu;
+ fu->flags |= F_IGNORE;
+ /* FALLTHROUGH */
+ case 'a':
+ pr->flags = F_ADDRESS;
+ ++p2;
+ switch(p1[2]) {
+ case 'd': case 'o': case'x':
+ cs[0] = 'q';
+ cs[1] = p1[2];
+ cs[2] = '\0';
+ break;
+ default:
+ p1[3] = '\0';
+ badconv(p1);
+ }
+ break;
+ case 'c':
+ pr->flags = F_C;
+ /* cs[0] = 'c'; set in conv_c */
+ goto isint2;
+ case 'p':
+ pr->flags = F_P;
+ cs[0] = 'c';
+ goto isint2;
+ case 'u':
+ pr->flags = F_U;
+ /* cs[0] = 'c'; set in conv_u */
+isint2: switch(fu->bcnt) {
+ case 0: case 1:
+ pr->bcnt = 1;
+ break;
+ default:
+ p1[2] = '\0';
+ badcnt(p1);
+ }
+ break;
+ default:
+ p1[2] = '\0';
+ badconv(p1);
+ }
+ break;
+ default:
+ p1[1] = '\0';
+ badconv(p1);
+ }
+
+ /*
+ * Copy to PR format string, set conversion character
+ * pointer, update original.
+ */
+ savech = *p2;
+ p1[0] = '\0';
+ pr->fmt = emalloc(strlen(fmtp) + strlen(cs) + 1);
+ (void)strcpy(pr->fmt, fmtp);
+ (void)strcat(pr->fmt, cs);
+ *p2 = savech;
+ pr->cchar = pr->fmt + (p1 - fmtp);
+ fmtp = p2;
+
+ /* Only one conversion character if byte count */
+ if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) {
+ (void)fprintf(stderr,
+ _("hexdump: byte count with multiple conversion characters.\n"));
+ exit(1);
+ }
+ }
+ /*
+ * If format unit byte count not specified, figure it out
+ * so can adjust rep count later.
+ */
+ if (!fu->bcnt)
+ for (pr = fu->nextpr; pr; pr = pr->nextpr)
+ fu->bcnt += pr->bcnt;
+ }
+ /*
+ * If the format string interprets any data at all, and it's
+ * not the same as the blocksize, and its last format unit
+ * interprets any data at all, and has no iteration count,
+ * repeat it as necessary.
+ *
+ * If rep count is greater than 1, no trailing whitespace
+ * gets output from the last iteration of the format unit.
+ */
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (!fu->nextfu && fs->bcnt < blocksize &&
+ !(fu->flags&F_SETREP) && fu->bcnt)
+ fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
+ if (fu->reps > 1) {
+ for (pr = fu->nextpr;; pr = pr->nextpr)
+ if (!pr->nextpr)
+ break;
+ for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
+ p2 = isspace((unsigned char)*p1) ? p1 : NULL;
+ if (p2)
+ pr->nospace = p2;
+ }
+ }
+}
+
+
+static void escape(char *p1)
+{
+ char *p2;
+
+ /* alphabetic escape sequences have to be done in place */
+ for (p2 = p1;; ++p1, ++p2) {
+ if (!*p1) {
+ *p2 = *p1;
+ break;
+ }
+ if (*p1 == '\\')
+ switch(*++p1) {
+ case 'a':
+ /* *p2 = '\a'; */
+ *p2 = '\007';
+ break;
+ case 'b':
+ *p2 = '\b';
+ break;
+ case 'f':
+ *p2 = '\f';
+ break;
+ case 'n':
+ *p2 = '\n';
+ break;
+ case 'r':
+ *p2 = '\r';
+ break;
+ case 't':
+ *p2 = '\t';
+ break;
+ case 'v':
+ *p2 = '\v';
+ break;
+ default:
+ *p2 = *p1;
+ break;
+ }
+ }
+}
+
+static void badcnt(const char *s)
+{
+ (void)fprintf(stderr,
+ _("hexdump: bad byte count for conversion character %s.\n"), s);
+ exit(1);
+}
+
+static void badsfmt(void)
+{
+ (void)fprintf(stderr,
+ _("hexdump: %%s requires a precision or a byte count.\n"));
+ exit(1);
+}
+
+static void badfmt(const char *fmt)
+{
+ (void)fprintf(stderr, _("hexdump: bad format {%s}\n"), fmt);
+ exit(1);
+}
+
+static void badconv(const char *ch)
+{
+ (void)fprintf(stderr, _("hexdump: bad conversion character %%%s.\n"), ch);
+ exit(1);
+}
diff --git a/text-utils/pg.1 b/text-utils/pg.1
new file mode 100644
index 0000000..b1891ca
--- /dev/null
+++ b/text-utils/pg.1
@@ -0,0 +1,237 @@
+.\" @(#)pg.1 1.7 (gritter) 4/25/01
+.TH PG 1 "2001-04-25" "Gunnar Ritter" "User Commands"
+.SH NAME
+pg \- browse pagewise through text files
+.SH SYNOPSIS
+.B pg
+.RB [ \-\fInumber\fP ]
+.RB [ \-p
+.IR string ]
+.RB [ \-cefnrs ]
+.RB [ +\fIline\fP ]
+.RB [ +/\fIpattern\fP/ ]
+.RI [ file ...]
+.SH DESCRIPTION
+.I Pg
+displays a text file on a
+.SM CRT
+one screenful at once.
+After each page, a prompt is displayed. The user may then either press the
+newline key to view the next page or one of the keys described below.
+.PP
+If no filename is given on the command line,
+.I pg
+reads from standard input.
+If the standard output is not a terminal,
+.I pg
+acts like
+.IR cat (1)
+but precedes each file with its name if there is more than one.
+.PP
+If input comes from a pipe,
+.I pg
+stores the data in a buffer file while reading
+to make navigation possible.
+.SH OPTIONS
+.I Pg
+accepts the following options:
+.TP
+.BI \- number
+The number of lines per page. Usually, this is the number of
+.SM CRT
+lines
+minus one.
+.TP
+.B \-c
+Clear the screen before a page is displayed
+if the terminfo entry for the terminal provides this capability.
+.TP
+.B \-e
+.I pg
+will not pause and display
+.SM (EOF)
+at the end of a file.
+.TP
+.B \-f
+.I pg
+does not split long lines.
+.TP
+.B \-n
+Without this option, commands must be terminated by a newline character. With
+this option,
+.I pg
+advances once a command letter is entered.
+.TP
+.BI \-p \ string
+Instead of the prompt
+.I " :"
+,
+.I string
+is displayed.
+If
+.I string
+contains
+.I %d
+, its first occurrence is replaced by the number of the current page.
+.TP
+.B \-r
+Disallow the shell escape.
+.TP
+.B \-s
+Print messages in
+.I standout
+mode
+if the terminfo entry for the terminal provides this capability.
+.TP
+.BI + number
+Start at the given line.
+.TP
+.BI +/ pattern /
+Start at the line containing the Basic Regular Expression
+.I pattern
+given.
+.SH USAGE
+The following commands may be entered at the prompt. Commands preceded by
+.I i
+in this document accept a number as argument, positive or negative.
+If this argument starts with
+.I +
+or
+.I \-,
+it is interpreted relative to the current position in the input file,
+otherwise relative to the beginning.
+.TP
+.IB i <newline>
+Display the next or the indicated page.
+.TP
+\fIi\fR\fBd\fR or \fB^D\fR
+Display the next halfpage. If
+.I i
+is given, it is always interpreted relative to the current position.
+.TP
+.IB i l
+Display the next or the indicated line.
+.TP
+.IB i f
+Skip a page forward.
+.I i
+must be a positive number and is always interpreted relative
+to the current position.
+.TP
+\fIi\fR\fBw\fR or \fIi\fR\fBz\fR
+Behave as
+.I <newline>
+except that
+.I i
+becomes the new page size.
+.TP
+.BR . " or " ^L
+Redraw the screen.
+.TP
+.B $
+Advance to the last line of the input file.
+.TP
+.IB i / pattern /
+Search forward until the first or the \fIi\fR-th
+occurrence of the Basic Regular Expression
+.I pattern
+is found. The search starts
+after the current page and stops at the end of the file. No wrap-around is
+performed.
+.I i
+must be a positive number.
+.TP
+\fIi\fR\fB?\fR\fIpattern\fR\fB?\fR or \fIi\fR\fB^\fR\fIpattern\fR\fB^\fR
+Search backward until the first or the \fIi\fR-th
+occurrence of the Basic Regular Expression
+.I pattern
+is found. The search starts
+before the current page and stops at the beginning of the file.
+No wrap-around is performed.
+.I i
+must be a positive number.
+.PP
+The search commands accept an added letter. If
+.B t
+is given, the line containing the pattern is displayed at the top of the
+screen, which is the default.
+.B m
+selects the middle and
+.B b
+the bottom of the screen.
+The selected position is used in following searches, too.
+.TP
+.IB i n
+Advance to the next file or
+.I i
+files forward.
+.TP
+.IB i p
+Reread the previous file or
+.I i
+files backward.
+.TP
+.BI s \ filename
+Save the current file to the given
+.I filename.
+.TP
+.B h
+Display a command summary.
+.TP
+.BI ! command
+Execute
+.I command
+using the shell.
+.TP
+.BR q " or " Q
+Quit.
+.PP
+If the user presses the interrupt or quit key while
+.I pg
+reads from the
+input file or writes on the terminal,
+.I pg
+will immediately display the prompt.
+In all other situations these keys will terminate
+.I pg.
+.SH "ENVIRONMENT VARIABLES"
+The following environment variables
+affect the behaviour of
+.I pg:
+.TP
+.B COLUMNS
+Overrides the system-supplied number of columns if set.
+.TP
+.BR LANG ,\ LC_ALL ,\ LC_COLLATE ,\ LC_CTYPE ,\ LC_MESSAGES
+See
+.IR locale (7).
+.TP
+.B LINES
+Overrides the system-supplied number of lines if set.
+.TP
+.B SHELL
+Used by the
+.B !
+command.
+.TP
+.B TERM
+Determines the terminal type.
+.SH "SEE ALSO"
+.BR cat (1),
+.BR more (1),
+.BR sh (1),
+.BR terminfo (5),
+.BR locale (7),
+.BR regex (7),
+.BR term (7)
+.SH NOTES
+.I pg
+expects the terminal tabulators to set on eight positions.
+.PP
+Files that include
+.SM NUL
+characters cannot be displayed by
+.IR pg .
+.SH AVAILABILITY
+The pg command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/pg.c b/text-utils/pg.c
new file mode 100644
index 0000000..b2c4d87
--- /dev/null
+++ b/text-utils/pg.c
@@ -0,0 +1,1768 @@
+/*
+ * pg - A clone of the System V CRT paging utility.
+ *
+ * Copyright (c) 2000-2001 Gunnar Ritter. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [deleted]
+ * 4. Neither the name of Gunnar Ritter nor the names of his contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Sccsid @(#)pg.c 1.44 (gritter) 2/8/02 - modified for util-linux */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#ifndef TIOCGWINSZ
+#include <sys/ioctl.h>
+#endif
+#include <sys/termios.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <libgen.h>
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#elif defined(HAVE_NCURSES_NCURSES_H)
+#include <ncurses/ncurses.h>
+#endif
+
+#include <term.h>
+
+#include "nls.h"
+#include "widechar.h"
+
+#define READBUF LINE_MAX /* size of input buffer */
+#define CMDBUF 255 /* size of command buffer */
+#define TABSIZE 8 /* spaces consumed by tab character */
+
+/*
+ * Avoid the message "`var' might be clobbered by `longjmp' or `vfork'"
+ */
+#define CLOBBGRD(a) (void)(&(a));
+
+#define cuc(c) ((c) & 0377)
+
+enum { FORWARD = 1, BACKWARD = 2 }; /* search direction */
+enum { TOP, MIDDLE, BOTTOM }; /* position of matching line */
+
+/*
+ * States for syntax-aware command line editor.
+ */
+enum {
+ COUNT,
+ SIGN,
+ CMD_FIN,
+ SEARCH,
+ SEARCH_FIN,
+ ADDON_FIN,
+ STRING,
+ INVALID
+};
+
+/*
+ * Current command
+ */
+struct {
+ char cmdline[CMDBUF];
+ size_t cmdlen;
+ int count;
+ int key;
+ char pattern[CMDBUF];
+ char addon;
+} cmd;
+
+/*
+ * Position of file arguments on argv[] to main()
+ */
+struct {
+ int first;
+ int current;
+ int last;
+} files;
+
+void (*oldint)(int); /* old SIGINT handler */
+void (*oldquit)(int); /* old SIGQUIT handler */
+void (*oldterm)(int); /* old SIGTERM handler */
+char *tty; /* result of ttyname(1) */
+char *progname; /* program name */
+unsigned ontty; /* whether running on tty device */
+unsigned exitstatus; /* exit status */
+int pagelen = 23; /* lines on a single screen page */
+int ttycols = 79; /* screen columns (starting at 0) */
+struct termios otio; /* old termios settings */
+int tinfostat = -1; /* terminfo routines initialized */
+int searchdisplay = TOP; /* matching line position */
+regex_t re; /* regular expression to search for */
+int remembered; /* have a remembered search string */
+int cflag; /* clear screen before each page */
+int eflag; /* suppress (EOF) */
+int fflag; /* do not split lines */
+int nflag; /* no newline for commands required */
+int rflag; /* "restricted" pg */
+int sflag; /* use standout mode */
+char *pstring = ":"; /* prompt string */
+char *searchfor; /* search pattern from argv[] */
+int havepagelen; /* page length is manually defined */
+long startline; /* start line from argv[] */
+int nextfile = 1; /* files to advance */
+jmp_buf jmpenv; /* jump from signal handlers */
+int canjump; /* jmpenv is valid */
+wchar_t wbuf[READBUF]; /* used in several widechar routines */
+
+const char *copyright =
+"@(#)pg 1.44 2/8/02. Copyright (c) 2000-2001 Gunnar Ritter. ";
+const char *helpscreen = N_("All rights reserved.\n\
+-------------------------------------------------------\n\
+ h this screen\n\
+ q or Q quit program\n\
+ <newline> next page\n\
+ f skip a page forward\n\
+ d or ^D next halfpage\n\
+ l next line\n\
+ $ last page\n\
+ /regex/ search forward for regex\n\
+ ?regex? or ^regex^ search backward for regex\n\
+ . or ^L redraw screen\n\
+ w or z set page size and go to next page\n\
+ s filename save current file to filename\n\
+ !command shell escape\n\
+ p go to previous file\n\
+ n go to next file\n\
+\n\
+Many commands accept preceding numbers, for example:\n\
++1<newline> (next page); -1<newline> (previous page); 1<newline> (first page).\n\
+\n\
+See pg(1) for more information.\n\
+-------------------------------------------------------\n");
+
+#ifndef HAVE_FSEEKO
+ static int fseeko(FILE *f, off_t off, int whence) {
+ return fseek(f, (long) off, whence);
+ }
+ static off_t ftello(FILE *f) {
+ return (off_t) ftell(f);
+ }
+#endif
+
+#ifdef USE_SIGSET /* never defined */
+/* sigset and sigrelse are obsolete - use when POSIX stuff is unavailable */
+#define my_sigset sigset
+#define my_sigrelse sigrelse
+#else
+static int my_sigrelse(int sig) {
+ sigset_t sigs;
+
+ if (sigemptyset(&sigs) || sigaddset(&sigs, sig))
+ return -1;
+ return sigprocmask(SIG_UNBLOCK, &sigs, NULL);
+}
+typedef void (*my_sighandler_t)(int);
+static my_sighandler_t my_sigset(int sig, my_sighandler_t disp) {
+ struct sigaction act, oact;
+
+ act.sa_handler = disp;
+ if (sigemptyset(&act.sa_mask))
+ return SIG_ERR;
+ act.sa_flags = 0;
+ if (sigaction(sig, &act, &oact))
+ return SIG_ERR;
+ if (my_sigrelse(sig))
+ return SIG_ERR;
+ return oact.sa_handler;
+}
+#endif
+
+/*
+ * Quit pg.
+ */
+static void
+quit(int status)
+{
+ exit(status < 0100 ? status : 077);
+}
+
+/*
+ * Memory allocator including check.
+ */
+static char *
+smalloc(size_t s)
+{
+ char *m = (char *)malloc(s);
+ if (m == NULL) {
+ const char *p = _("Out of memory\n");
+ write(2, p, strlen(p));
+ quit(++exitstatus);
+ }
+ return m;
+}
+
+/*
+ * Usage message and similar routines.
+ */
+static void
+usage(void)
+{
+ fprintf(stderr, _("%s: Usage: %s [-number] [-p string] [-cefnrs] "
+ "[+line] [+/pattern/] [files]\n"),
+ progname, progname);
+ quit(2);
+}
+
+static void
+needarg(char *s)
+{
+ fprintf(stderr, _("%s: option requires an argument -- %s\n"),
+ progname, s);
+ usage();
+}
+
+static void
+invopt(char *s)
+{
+ fprintf(stderr, _("%s: illegal option -- %s\n"), progname, s);
+ usage();
+}
+
+#ifdef HAVE_WIDECHAR
+/*
+ * A mbstowcs()-alike function that transparently handles invalid sequences.
+ */
+static size_t
+xmbstowcs(wchar_t *pwcs, const char *s, size_t nwcs)
+{
+ size_t n = nwcs;
+ int c;
+
+ mbtowc(pwcs, NULL, MB_CUR_MAX);
+ while (*s && n) {
+ if ((c = mbtowc(pwcs, s, MB_CUR_MAX)) < 0) {
+ s++;
+ *pwcs = L'?';
+ } else
+ s += c;
+ pwcs++;
+ n--;
+ }
+ if (n)
+ *pwcs = L'\0';
+ mbtowc(pwcs, NULL, MB_CUR_MAX);
+ return nwcs - n;
+}
+#endif
+
+/*
+ * Helper function for tputs().
+ */
+static int
+outcap(int i)
+{
+ char c = i;
+ return write(1, &c, 1);
+}
+
+/*
+ * Write messages to terminal.
+ */
+static void
+mesg(char *message)
+{
+ if (ontty == 0)
+ return;
+ if (*message != '\n' && sflag)
+ vidputs(A_STANDOUT, outcap);
+ write(1, message, strlen(message));
+ if (*message != '\n' && sflag)
+ vidputs(A_NORMAL, outcap);
+}
+
+/*
+ * Get the window size.
+ */
+static void
+getwinsize(void)
+{
+ static int initialized, envlines, envcols, deflines, defcols;
+#ifdef TIOCGWINSZ
+ struct winsize winsz;
+ int badioctl;
+#endif
+ char *p;
+
+ if (initialized == 0) {
+ if ((p = getenv("LINES")) != NULL && *p != '\0')
+ if ((envlines = atoi(p)) < 0)
+ envlines = 0;
+ if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
+ if ((envcols = atoi(p)) < 0)
+ envcols = 0;
+ /* terminfo values. */
+ if (tinfostat != 1 || columns == 0)
+ defcols = 24;
+ else
+ defcols = columns;
+ if (tinfostat != 1 || lines == 0)
+ deflines = 80;
+ else
+ deflines = lines;
+ initialized = 1;
+ }
+#ifdef TIOCGWINSZ
+ badioctl = ioctl(1, TIOCGWINSZ, &winsz);
+#endif
+ if (envcols)
+ ttycols = envcols - 1;
+#ifdef TIOCGWINSZ
+ else if (!badioctl)
+ ttycols = winsz.ws_col - 1;
+#endif
+ else
+ ttycols = defcols - 1;
+ if (havepagelen == 0) {
+ if (envlines)
+ pagelen = envlines - 1;
+#ifdef TIOCGWINSZ
+ else if (!badioctl)
+ pagelen = winsz.ws_row - 1;
+#endif
+ else
+ pagelen = deflines - 1;
+ }
+}
+
+/*
+ * Message if skipping parts of files.
+ */
+static void
+skip(int direction)
+{
+ if (direction > 0)
+ mesg(_("...skipping forward\n"));
+ else
+ mesg(_("...skipping backward\n"));
+}
+
+/*
+ * Signal handler while reading from input file.
+ */
+static void
+sighandler(int signum)
+{
+ if (canjump && (signum == SIGINT || signum == SIGQUIT))
+ longjmp(jmpenv, signum);
+ tcsetattr(1, TCSADRAIN, &otio);
+ quit(exitstatus);
+}
+
+/*
+ * Check whether the requested file was specified on the command line.
+ */
+static int
+checkf(void)
+{
+ if (files.current + nextfile >= files.last) {
+ mesg(_("No next file"));
+ return 1;
+ }
+ if (files.current + nextfile < files.first) {
+ mesg(_("No previous file"));
+ return 1;
+ }
+ return 0;
+}
+
+#ifdef HAVE_WIDECHAR
+/*
+ * Return the last character that will fit on the line at col columns
+ * in case MB_CUR_MAX > 1.
+ */
+static char *
+endline_for_mb(unsigned col, char *s)
+{
+ unsigned pos = 0;
+ wchar_t *p = wbuf;
+ wchar_t *end;
+ size_t wl;
+ char *t = s;
+
+ if ((wl = xmbstowcs(wbuf, t, sizeof wbuf - 1)) == (size_t)-1)
+ return s + 1;
+ wbuf[wl] = L'\0';
+ while (*p != L'\0') {
+ switch (*p) {
+ /*
+ * Cursor left.
+ */
+ case L'\b':
+ if (pos > 0)
+ pos--;
+ break;
+ /*
+ * No cursor movement.
+ */
+ case L'\a':
+ break;
+ /*
+ * Special.
+ */
+ case L'\r':
+ pos = 0;
+ break;
+ case L'\n':
+ end = p + 1;
+ goto ended;
+ /*
+ * Cursor right.
+ */
+ case L'\t':
+ pos += TABSIZE - (pos % TABSIZE);
+ break;
+ default:
+ pos += wcwidth(*p);
+ }
+ if (pos > col) {
+ if (*p == L'\t')
+ p++;
+ else if (pos > col + 1)
+ /*
+ * wcwidth() found a character that
+ * has multiple columns. What happens
+ * now? Assume the terminal will print
+ * the entire character onto the next
+ * row.
+ */
+ p--;
+ if (*++p == L'\n')
+ p++;
+ end = p;
+ goto ended;
+ }
+ p++;
+ }
+ end = p;
+ ended:
+ *end = L'\0';
+ p = wbuf;
+ if ((pos = wcstombs(NULL, p, READBUF)) == -1)
+ return s + 1;
+ return s + pos;
+}
+#endif
+
+/*
+ * Return the last character that will fit on the line at col columns.
+ */
+static char *
+endline(unsigned col, char *s)
+{
+ unsigned pos = 0;
+ char *t = s;
+
+#ifdef HAVE_WIDECHAR
+ if (MB_CUR_MAX > 1)
+ return endline_for_mb(col, s);
+#endif
+
+ while (*s != '\0') {
+ switch (*s) {
+ /*
+ * Cursor left.
+ */
+ case '\b':
+ if (pos > 0)
+ pos--;
+ break;
+ /*
+ * No cursor movement.
+ */
+ case '\a':
+ break;
+ /*
+ * Special.
+ */
+ case '\r':
+ pos = 0;
+ break;
+ case '\n':
+ t = s + 1;
+ goto cend;
+ /*
+ * Cursor right.
+ */
+ case '\t':
+ pos += TABSIZE - (pos % TABSIZE);
+ break;
+ default:
+ pos++;
+ }
+ if (pos > col) {
+ if (*s == '\t')
+ s++;
+ if (*++s == '\n')
+ s++;
+ t = s;
+ goto cend;
+ }
+ s++;
+ }
+ t = s;
+ cend:
+ return t;
+}
+
+/*
+ * Clear the current line on the terminal's screen.
+ */
+static void
+cline(void)
+{
+ char *buf = (char *)smalloc(ttycols + 2);
+ memset(buf, ' ', ttycols + 2);
+ buf[0] = '\r';
+ buf[ttycols + 1] = '\r';
+ write(1, buf, ttycols + 2);
+ free(buf);
+}
+
+/*
+ * Evaluate a command character's semantics.
+ */
+static int
+getstate(int c)
+{
+ switch (c) {
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '0':
+ case '\0':
+ return COUNT;
+ case '-': case '+':
+ return SIGN;
+ case 'l': case 'd': case '\004': case 'f': case 'z':
+ case '.': case '\014': case '$': case 'n': case 'p':
+ case 'w': case 'h': case 'q': case 'Q':
+ return CMD_FIN;
+ case '/': case '?': case '^':
+ return SEARCH;
+ case 's': case '!':
+ return STRING;
+ case 'm': case 'b': case 't':
+ return ADDON_FIN;
+ default:
+#ifdef PG_BELL
+ if (bell)
+ tputs(bell, 1, outcap);
+#endif /* PG_BELL */
+ return INVALID;
+ }
+}
+
+/*
+ * Get the count and ignore last character of string.
+ */
+static int
+getcount(char *cmdstr)
+{
+ char *buf;
+ char *p;
+ int i;
+
+ if (*cmdstr == '\0')
+ return 1;
+ buf = (char *)smalloc(strlen(cmdstr) + 1);
+ strcpy(buf, cmdstr);
+ if (cmd.key != '\0') {
+ if (cmd.key == '/' || cmd.key == '?' || cmd.key == '^') {
+ if ((p = strchr(buf, cmd.key)) != NULL)
+ *p = '\0';
+ } else
+ *(buf + strlen(buf) - 1) = '\0';
+ }
+ if (*buf == '\0')
+ return 1;
+ if (buf[0] == '-' && buf[1] == '\0') {
+ i = -1;
+ } else {
+ if (*buf == '+')
+ i = atoi(buf + 1);
+ else
+ i = atoi(buf);
+ }
+ free(buf);
+ return i;
+}
+
+/*
+ * Read what the user writes at the prompt. This is tricky because
+ * we check for valid input.
+ */
+static void
+prompt(long long pageno)
+{
+ struct termios tio;
+ char key;
+ int state = COUNT;
+ int escape = 0;
+ char b[LINE_MAX], *p;
+
+ if (pageno != -1) {
+ if ((p = strstr(pstring, "%d")) == NULL) {
+ mesg(pstring);
+ } else {
+ strcpy(b, pstring);
+ sprintf(b + (p - pstring), "%lld", pageno);
+ strcat(b, p + 2);
+ mesg(b);
+ }
+ }
+ cmd.key = cmd.addon = cmd.cmdline[0] = '\0';
+ cmd.cmdlen = 0;
+ tcgetattr(1, &tio);
+ tio.c_lflag &= ~(ICANON | ECHO);
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr(1, TCSADRAIN, &tio);
+ tcflush(1, TCIFLUSH);
+ for (;;) {
+ switch (read(1, &key, 1)) {
+ case 0: quit(0);
+ /*NOTREACHED*/
+ case -1: quit(1);
+ }
+ if (key == tio.c_cc[VERASE]) {
+ if (cmd.cmdlen) {
+ write(1, "\b \b", 3);
+ cmd.cmdline[--cmd.cmdlen] = '\0';
+ switch (state) {
+ case ADDON_FIN:
+ state = SEARCH_FIN;
+ cmd.addon = '\0';
+ break;
+ case CMD_FIN:
+ cmd.key = '\0';
+ state = COUNT;
+ break;
+ case SEARCH_FIN:
+ state = SEARCH;
+ /*FALLTHRU*/
+ case SEARCH:
+ if (cmd.cmdline[cmd.cmdlen - 1]
+ == '\\') {
+ escape = 1;
+ while(cmd.cmdline[cmd.cmdlen
+ - escape - 1]
+ == '\\') escape++;
+ escape %= 2;
+ }
+ else {
+ escape = 0;
+ if (strchr(cmd.cmdline, cmd.key)
+ == NULL) {
+ cmd.key = '\0';
+ state = COUNT;
+ }
+ }
+ break;
+ }
+ }
+ if (cmd.cmdlen == 0) {
+ state = COUNT;
+ cmd.key = '\0';
+ }
+ continue;
+ }
+ if (key == tio.c_cc[VKILL]) {
+ cline();
+ cmd.cmdlen = 0;
+ cmd.cmdline[0] = '\0';
+ state = COUNT;
+ cmd.key = '\0';
+ continue;
+ }
+ if (key == '\n' || (nflag && state == COUNT && key == ' '))
+ break;
+ if (cmd.cmdlen >= CMDBUF - 1)
+ continue;
+ switch (state) {
+ case STRING:
+ break;
+ case SEARCH:
+ if (!escape) {
+ if (key == cmd.key)
+ state = SEARCH_FIN;
+ if (key == '\\')
+ escape = 1;
+ } else
+ escape = 0;
+ break;
+ case SEARCH_FIN:
+ if (getstate(key) != ADDON_FIN)
+ continue;
+ state = ADDON_FIN;
+ cmd.addon = key;
+ switch (key) {
+ case 't':
+ searchdisplay = TOP;
+ break;
+ case 'm':
+ searchdisplay = MIDDLE;
+ break;
+ case 'b':
+ searchdisplay = BOTTOM;
+ break;
+ }
+ break;
+ case CMD_FIN:
+ case ADDON_FIN:
+ continue;
+ default:
+ state = getstate(key);
+ switch (state) {
+ case SIGN:
+ if (cmd.cmdlen != 0) {
+ state = INVALID;
+ continue;
+ }
+ state = COUNT;
+ /*FALLTHRU*/
+ case COUNT:
+ break;
+ case ADDON_FIN:
+ case INVALID:
+ continue;
+ default:
+ cmd.key = key;
+ }
+ }
+ write(1, &key, 1);
+ cmd.cmdline[cmd.cmdlen++] = key;
+ cmd.cmdline[cmd.cmdlen] = '\0';
+ if (nflag && state == CMD_FIN)
+ goto endprompt;
+ }
+endprompt:
+ tcsetattr(1, TCSADRAIN, &otio);
+ cline();
+ cmd.count = getcount(cmd.cmdline);
+}
+
+#ifdef HAVE_WIDECHAR
+/*
+ * Remove backspace formatting, for searches
+ * in case MB_CUR_MAX > 1.
+ */
+static char *
+colb_for_mb(char *s)
+{
+ char *p = s;
+ wchar_t *wp, *wq;
+ size_t l = strlen(s), wl;
+ unsigned i;
+
+ if ((wl = xmbstowcs(wbuf, p, sizeof wbuf)) == (size_t)-1)
+ return s;
+ for (wp = wbuf, wq = wbuf, i = 0; *wp != L'\0' && i < wl;
+ wp++, wq++) {
+ if (*wp == L'\b') {
+ if (wq != wbuf)
+ wq -= 2;
+ else
+ wq--;
+ } else
+ *wq = *wp;
+ }
+ *wq = L'\0';
+ wp = wbuf;
+ wcstombs(s, wp, l + 1);
+
+ return s;
+}
+#endif
+
+/*
+ * Remove backspace formatting, for searches.
+ */
+static char *
+colb(char *s)
+{
+ char *p = s, *q;
+
+#ifdef HAVE_WIDECHAR
+ if (MB_CUR_MAX > 1)
+ return colb_for_mb(s);
+#endif
+
+ for (q = s; *p != '\0'; p++, q++) {
+ if (*p == '\b') {
+ if (q != s)
+ q -= 2;
+ else
+ q--;
+ } else
+ *q = *p;
+ }
+ *q = '\0';
+
+ return s;
+}
+
+#ifdef HAVE_WIDECHAR
+/*
+ * Convert nonprintable characters to spaces
+ * in case MB_CUR_MAX > 1.
+ */
+static void
+makeprint_for_mb(char *s, size_t l)
+{
+ char *t = s;
+ wchar_t *wp = wbuf;
+ size_t wl;
+
+ if ((wl = xmbstowcs(wbuf, t, sizeof wbuf)) == (size_t)-1)
+ return;
+ while (wl--) {
+ if (!iswprint(*wp) && *wp != L'\n' && *wp != L'\r'
+ && *wp != L'\b' && *wp != L'\t')
+ *wp = L'?';
+ wp++;
+ }
+ wp = wbuf;
+ wcstombs(s, wp, l);
+}
+#endif
+
+/*
+ * Convert nonprintable characters to spaces.
+ */
+static void
+makeprint(char *s, size_t l)
+{
+#ifdef HAVE_WIDECHAR
+ if (MB_CUR_MAX > 1)
+ return makeprint_for_mb(s, l);
+#endif
+
+ while (l--) {
+ if (!isprint(cuc(*s)) && *s != '\n' && *s != '\r'
+ && *s != '\b' && *s != '\t')
+ *s = '?';
+ s++;
+ }
+}
+
+/*
+ * Strip backslash characters from the given string.
+ */
+static void
+striprs(char *s)
+{
+ char *p = s;
+
+ do {
+ if (*s == '\\') {
+ s++;
+ }
+ *p++ = *s;
+ } while (*s++ != '\0');
+}
+
+/*
+ * Extract the search pattern off the command line.
+ */
+static char *
+makepat(void)
+{
+ char *p;
+
+ if (cmd.addon == '\0')
+ p = cmd.cmdline + strlen(cmd.cmdline) - 1;
+ else
+ p = cmd.cmdline + strlen(cmd.cmdline) - 2;
+ if (*p == cmd.key)
+ *p = '\0';
+ else
+ *(p + 1) = '\0';
+ if ((p = strchr(cmd.cmdline, cmd.key)) != NULL) {
+ p++;
+ striprs(p);
+ }
+ return p;
+}
+
+/*
+ * Process errors that occurred in temporary file operations.
+ */
+static void
+tmperr(FILE *f, char *ftype)
+{
+ if (ferror(f))
+ fprintf(stderr, _("%s: Read error from %s file\n"),
+ progname, ftype);
+ else if (feof(f))
+ /*
+ * Most likely '\0' in input.
+ */
+ fprintf(stderr, _("%s: Unexpected EOF in %s file\n"),
+ progname, ftype);
+ else
+ fprintf(stderr, _("%s: Unknown error in %s file\n"),
+ progname, ftype);
+ quit(++exitstatus);
+}
+
+/*
+ * perror()-like, but showing the program's name.
+ */
+static void
+pgerror(int eno, char *string)
+{
+ fprintf(stderr, "%s: %s: %s\n", progname, string, strerror(eno));
+}
+
+/*
+ * Read the file and respond to user input.
+ * Beware: long and ugly.
+ */
+static void
+pgfile(FILE *f, char *name)
+{
+ off_t pos, oldpos, fpos;
+ off_t line = 0, fline = 0, bline = 0, oldline = 0, eofline = 0;
+ int dline = 0;
+ /*
+ * These are the line counters:
+ * line the line desired to display
+ * fline the current line of the input file
+ * bline the current line of the file buffer
+ * oldline the line before a search was started
+ * eofline the last line of the file if it is already reached
+ * dline the line on the display
+ */
+ int search = 0;
+ unsigned searchcount = 0;
+ /*
+ * Advance to EOF immediately.
+ */
+ int seekeof = 0;
+ /*
+ * EOF has been reached by `line'.
+ */
+ int eof = 0;
+ /*
+ * f and fbuf refer to the same file.
+ */
+ int nobuf = 0;
+ int sig;
+ int rerror;
+ size_t sz;
+ char b[READBUF + 1];
+ char *p;
+ /*
+ * fbuf an exact copy of the input file as it gets read
+ * find index table for input, one entry per line
+ * save for the s command, to save to a file
+ */
+ FILE *fbuf, *find, *save;
+
+ /* silence compiler - it may warn about longjmp() */
+ CLOBBGRD(line);
+ CLOBBGRD(fline);
+ CLOBBGRD(bline);
+ CLOBBGRD(oldline);
+ CLOBBGRD(eofline);
+ CLOBBGRD(dline);
+ CLOBBGRD(ttycols);
+ CLOBBGRD(search);
+ CLOBBGRD(searchcount);
+ CLOBBGRD(seekeof);
+ CLOBBGRD(eof);
+ CLOBBGRD(fpos);
+ CLOBBGRD(nobuf);
+ CLOBBGRD(fbuf);
+
+ if (ontty == 0) {
+ /*
+ * Just copy stdin to stdout.
+ */
+ while ((sz = fread(b, sizeof *b, READBUF, f)) != 0)
+ write(1, b, sz);
+ if (ferror(f)) {
+ pgerror(errno, name);
+ exitstatus++;
+ }
+ return;
+ }
+ if ((fpos = fseeko(f, (off_t)0, SEEK_SET)) == -1)
+ fbuf = tmpfile();
+ else {
+ fbuf = f;
+ nobuf = 1;
+ }
+ find = tmpfile();
+ if (fbuf == NULL || find == NULL) {
+ fprintf(stderr, _("%s: Cannot create tempfile\n"), progname);
+ quit(++exitstatus);
+ }
+ if (searchfor) {
+ search = FORWARD;
+ oldline = 0;
+ searchcount = 1;
+ rerror = regcomp(&re, searchfor, REG_NOSUB | REG_NEWLINE);
+ if (rerror != 0) {
+ mesg(_("RE error: "));
+ regerror(rerror, &re, b, READBUF);
+ mesg(b);
+ goto newcmd;
+ }
+ remembered = 1;
+ }
+
+ for (line = startline; ; ) {
+ /*
+ * Get a line from input file or buffer.
+ */
+ if (line < bline) {
+ fseeko(find, line * sizeof pos, SEEK_SET);
+ if (fread(&pos, sizeof pos, 1, find) == 0)
+ tmperr(find, "index");
+ fseeko(find, (off_t)0, SEEK_END);
+ fseeko(fbuf, pos, SEEK_SET);
+ if (fgets(b, READBUF, fbuf) == NULL)
+ tmperr(fbuf, "buffer");
+ } else if (eofline == 0) {
+ fseeko(find, (off_t)0, SEEK_END);
+ do {
+ if (!nobuf)
+ fseeko(fbuf, (off_t)0, SEEK_END);
+ pos = ftello(fbuf);
+ if ((sig = setjmp(jmpenv)) != 0) {
+ /*
+ * We got a signal.
+ */
+ canjump = 0;
+ my_sigrelse(sig);
+ fseeko(fbuf, pos, SEEK_SET);
+ *b = '\0';
+ dline = pagelen;
+ break;
+ } else {
+ if (nobuf)
+ fseeko(f, fpos, SEEK_SET);
+ canjump = 1;
+ p = fgets(b, READBUF, f);
+ if (nobuf)
+ if ((fpos = ftello(f)) == -1)
+ pgerror(errno, name);
+ canjump = 0;
+ }
+ if (p == NULL || *b == '\0') {
+ if (ferror(f))
+ pgerror(errno, name);
+ eofline = fline;
+ eof = 1;
+ break;
+ } else {
+ if (!nobuf)
+ fputs(b, fbuf);
+ fwrite(&pos, sizeof pos, 1, find);
+ if (!fflag) {
+ oldpos = pos;
+ p = b;
+ while (*(p = endline(ttycols,
+ p))
+ != '\0') {
+ pos = oldpos + (p - b);
+ fwrite(&pos,
+ sizeof pos,
+ 1, find);
+ fline++;
+ bline++;
+ }
+ }
+ fline++;
+ }
+ } while (line > bline++);
+ } else {
+ /*
+ * eofline != 0
+ */
+ eof = 1;
+ }
+ if (search == FORWARD && remembered == 1) {
+ if (eof) {
+ line = oldline;
+ search = searchcount = 0;
+ mesg(_("Pattern not found"));
+ eof = 0;
+ goto newcmd;
+ }
+ line++;
+ colb(b);
+ if (regexec(&re, b, 0, NULL, 0) == 0) {
+ searchcount--;
+ }
+ if (searchcount == 0) {
+ search = dline = 0;
+ switch (searchdisplay) {
+ case TOP:
+ line -= 1;
+ break;
+ case MIDDLE:
+ line -= pagelen / 2 + 1;
+ break;
+ case BOTTOM:
+ line -= pagelen;
+ break;
+ }
+ skip(1);
+ }
+ continue;
+ } else if (eof) { /*
+ * We are not searching.
+ */
+ line = bline;
+ } else if (*b != '\0') {
+ if (cflag && clear_screen) {
+ switch (dline) {
+ case 0:
+ tputs(clear_screen, 1, outcap);
+ dline = 0;
+ }
+ }
+ line++;
+ if (eofline && line == eofline)
+ eof = 1;
+ dline++;
+ if ((sig = setjmp(jmpenv)) != 0) {
+ /*
+ * We got a signal.
+ */
+ canjump = 0;
+ my_sigrelse(sig);
+ dline = pagelen;
+ } else {
+ p = endline(ttycols, b);
+ sz = p - b;
+ makeprint(b, sz);
+ canjump = 1;
+ write(1, b, sz);
+ canjump = 0;
+ }
+ }
+ if (dline >= pagelen || eof) {
+ /*
+ * Time for prompting!
+ */
+ if (eof && seekeof) {
+ eof = seekeof = 0;
+ if (line >= pagelen)
+ line -= pagelen;
+ else
+ line = 0;
+ dline = -1;
+ continue;
+ }
+newcmd:
+ if (eof) {
+ if (fline == 0 || eflag)
+ break;
+ mesg(_("(EOF)"));
+ }
+ prompt((line - 1) / pagelen + 1);
+ switch (cmd.key) {
+ case '/':
+ /*
+ * Search forward.
+ */
+ search = FORWARD;
+ oldline = line;
+ searchcount = cmd.count;
+ p = makepat();
+ if (p != NULL && *p) {
+ if (remembered == 1)
+ regfree(&re);
+ rerror = regcomp(&re, p,
+ REG_NOSUB | REG_NEWLINE);
+ if (rerror != 0) {
+ mesg(_("RE error: "));
+ sz = regerror(rerror, &re,
+ b, READBUF);
+ mesg(b);
+ goto newcmd;
+ }
+ remembered = 1;
+ } else if (remembered == 0) {
+ mesg(_("No remembered search string"));
+ goto newcmd;
+ }
+ continue;
+ case '?':
+ case '^':
+ /*
+ * Search backward.
+ */
+ search = BACKWARD;
+ oldline = line;
+ searchcount = cmd.count;
+ p = makepat();
+ if (p != NULL && *p) {
+ if (remembered == 1)
+ regfree(&re);
+ rerror = regcomp(&re, p,
+ REG_NOSUB | REG_NEWLINE);
+ if (rerror != 0) {
+ mesg(_("RE error: "));
+ regerror(rerror, &re,
+ b, READBUF);
+ mesg(b);
+ goto newcmd;
+ }
+ remembered = 1;
+ } else if (remembered == 0) {
+ mesg(_("No remembered search string"));
+ goto newcmd;
+ }
+ line -= pagelen;
+ if (line <= 0)
+ goto notfound_bw;
+ while (line) {
+ fseeko(find, --line * sizeof pos,
+ SEEK_SET);
+ if(fread(&pos, sizeof pos, 1,find)==0)
+ tmperr(find, "index");
+ fseeko(find, (off_t)0, SEEK_END);
+ fseeko(fbuf, pos, SEEK_SET);
+ if (fgets(b, READBUF, fbuf) == NULL)
+ tmperr(fbuf, "buffer");
+ colb(b);
+ if (regexec(&re, b, 0, NULL, 0) == 0)
+ searchcount--;
+ if (searchcount == 0)
+ goto found_bw;
+ }
+notfound_bw:
+ line = oldline;
+ search = searchcount = 0;
+ mesg(_("Pattern not found"));
+ goto newcmd;
+found_bw:
+ eof = search = dline = 0;
+ skip(-1);
+ switch (searchdisplay) {
+ case TOP:
+ /* line -= 1; */
+ break;
+ case MIDDLE:
+ line -= pagelen / 2;
+ break;
+ case BOTTOM:
+ if (line != 0)
+ dline = -1;
+ line -= pagelen;
+ break;
+ }
+ if (line < 0)
+ line = 0;
+ continue;
+ case 's':
+ /*
+ * Save to file.
+ */
+ p = cmd.cmdline;
+ while (*++p == ' ');
+ if (*p == '\0')
+ goto newcmd;
+ save = fopen(p, "wb");
+ if (save == NULL) {
+ cmd.count = errno;
+ mesg(_("Cannot open "));
+ mesg(p);
+ mesg(": ");
+ mesg(strerror(cmd.count));
+ goto newcmd;
+ }
+ /*
+ * Advance to EOF.
+ */
+ fseeko(find, (off_t)0, SEEK_END);
+ for (;;) {
+ if (!nobuf)
+ fseeko(fbuf,(off_t)0,SEEK_END);
+ pos = ftello(fbuf);
+ if (fgets(b, READBUF, f) == NULL) {
+ eofline = fline;
+ break;
+ }
+ if (!nobuf)
+ fputs(b, fbuf);
+ fwrite(&pos, sizeof pos, 1, find);
+ if (!fflag) {
+ oldpos = pos;
+ p = b;
+ while (*(p = endline(ttycols,
+ p))
+ != '\0') {
+ pos = oldpos + (p - b);
+ fwrite(&pos,
+ sizeof pos,
+ 1, find);
+ fline++;
+ bline++;
+ }
+ }
+ fline++;
+ bline++;
+ }
+ fseeko(fbuf, (off_t)0, SEEK_SET);
+ while ((sz = fread(b, sizeof *b, READBUF,
+ fbuf)) != 0) {
+ /*
+ * No error check for compat.
+ */
+ fwrite(b, sizeof *b, sz, save);
+ }
+ fclose(save);
+ fseeko(fbuf, (off_t)0, SEEK_END);
+ mesg(_("saved"));
+ goto newcmd;
+ case 'l':
+ /*
+ * Next line.
+ */
+ if (*cmd.cmdline != 'l')
+ eof = 0;
+ if (cmd.count == 0)
+ cmd.count = 1; /* compat */
+ if (isdigit(cuc(*cmd.cmdline))) {
+ line = cmd.count - 2;
+ dline = 0;
+ } else {
+ if (cmd.count != 1) {
+ line += cmd.count - 1
+ - pagelen;
+ dline = -1;
+ skip(cmd.count);
+ }
+ /*
+ * Nothing to do if count==1.
+ */
+ }
+ break;
+ case 'd':
+ /*
+ * Half screen forward.
+ */
+ case '\004': /* ^D */
+ if (*cmd.cmdline != cmd.key)
+ eof = 0;
+ if (cmd.count == 0)
+ cmd.count = 1; /* compat */
+ line += (cmd.count * pagelen / 2)
+ - pagelen - 1;
+ dline = -1;
+ skip(cmd.count);
+ break;
+ case 'f':
+ /*
+ * Skip forward.
+ */
+ if (cmd.count <= 0)
+ cmd.count = 1; /* compat */
+ line += cmd.count * pagelen - 2;
+ if (eof)
+ line += 2;
+ if (*cmd.cmdline != 'f')
+ eof = 0;
+ else if (eof)
+ break;
+ if (eofline && line >= eofline)
+ line -= pagelen;
+ dline = -1;
+ skip(cmd.count);
+ break;
+ case '\0':
+ /*
+ * Just a number, or '-', or <newline>.
+ */
+ if (cmd.count == 0)
+ cmd.count = 1; /* compat */
+ if (isdigit(cuc(*cmd.cmdline)))
+ line = (cmd.count - 1) * pagelen - 2;
+ else
+ line += (cmd.count - 1)
+ * (pagelen - 1) - 2;
+ if (*cmd.cmdline != '\0')
+ eof = 0;
+ if (cmd.count != 1) {
+ skip(cmd.count);
+ dline = -1;
+ } else {
+ dline = 1;
+ line += 2;
+ }
+ break;
+ case '$':
+ /*
+ * Advance to EOF.
+ */
+ if (!eof)
+ skip(1);
+ eof = 0;
+ line = LONG_MAX;
+ seekeof = 1;
+ dline = -1;
+ break;
+ case '.':
+ case '\014': /* ^L */
+ /*
+ * Repaint screen.
+ */
+ eof = 0;
+ if (line >= pagelen)
+ line -= pagelen;
+ else
+ line = 0;
+ dline = 0;
+ break;
+ case '!':
+ /*
+ * Shell escape.
+ */
+ if (rflag) {
+ mesg(progname);
+ mesg(_(": !command not allowed in "
+ "rflag mode.\n"));
+ } else {
+ pid_t cpid;
+
+ write(1, cmd.cmdline,
+ strlen(cmd.cmdline));
+ write(1, "\n", 1);
+ my_sigset(SIGINT, SIG_IGN);
+ my_sigset(SIGQUIT, SIG_IGN);
+ switch (cpid = fork()) {
+ case 0:
+ p = getenv("SHELL");
+ if (p == NULL) p = "/bin/sh";
+ if (!nobuf)
+ fclose(fbuf);
+ fclose(find);
+ if (isatty(0) == 0) {
+ close(0);
+ open(tty, O_RDONLY);
+ } else {
+ fclose(f);
+ }
+ my_sigset(SIGINT, oldint);
+ my_sigset(SIGQUIT, oldquit);
+ my_sigset(SIGTERM, oldterm);
+ execl(p, p, "-c",
+ cmd.cmdline + 1, NULL);
+ pgerror(errno, p);
+ _exit(0177);
+ /*NOTREACHED*/
+ case -1:
+ mesg(_("fork() failed, "
+ "try again later\n"));
+ break;
+ default:
+ while (wait(NULL) != cpid);
+ }
+ my_sigset(SIGINT, sighandler);
+ my_sigset(SIGQUIT, sighandler);
+ mesg("!\n");
+ }
+ goto newcmd;
+ case 'h':
+ {
+ /*
+ * Help!
+ */
+ const char *help = _(helpscreen);
+ write(1, copyright + 4, strlen(copyright + 4));
+ write(1, help, strlen(help));
+ goto newcmd;
+ }
+ case 'n':
+ /*
+ * Next file.
+ */
+ if (cmd.count == 0)
+ cmd.count = 1;
+ nextfile = cmd.count;
+ if (checkf()) {
+ nextfile = 1;
+ goto newcmd;
+ }
+ eof = 1;
+ break;
+ case 'p':
+ /*
+ * Previous file.
+ */
+ if (cmd.count == 0)
+ cmd.count = 1;
+ nextfile = 0 - cmd.count;
+ if (checkf()) {
+ nextfile = 1;
+ goto newcmd;
+ }
+ eof = 1;
+ break;
+ case 'q':
+ case 'Q':
+ /*
+ * Exit pg.
+ */
+ quit(exitstatus);
+ /*NOTREACHED*/
+ case 'w':
+ case 'z':
+ /*
+ * Set window size.
+ */
+ if (cmd.count < 0)
+ cmd.count = 0;
+ if (*cmd.cmdline != cmd.key)
+ pagelen = ++cmd.count;
+ dline = 1;
+ break;
+ }
+ if (line <= 0) {
+ line = 0;
+ dline = 0;
+ }
+ if (cflag && dline == 1) {
+ dline = 0;
+ line--;
+ }
+ }
+ if (eof)
+ break;
+ }
+ fclose(find);
+ if (!nobuf)
+ fclose(fbuf);
+}
+
+int
+main(int argc, char **argv)
+{
+ int arg, i;
+ char *p;
+ FILE *input;
+
+ progname = basename(argv[0]);
+
+ setlocale(LC_MESSAGES, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ if (tcgetattr(1, &otio) == 0) {
+ ontty = 1;
+ oldint = my_sigset(SIGINT, sighandler);
+ oldquit = my_sigset(SIGQUIT, sighandler);
+ oldterm = my_sigset(SIGTERM, sighandler);
+ setlocale(LC_CTYPE, "");
+ setlocale(LC_COLLATE, "");
+ tty = ttyname(1);
+ setupterm(NULL, 1, &tinfostat);
+ getwinsize();
+ helpscreen = _(helpscreen);
+ }
+ for (arg = 1; argv[arg]; arg++) {
+ if (*argv[arg] == '+')
+ continue;
+ if (*argv[arg] != '-' || argv[arg][1] == '\0')
+ break;
+ argc--;
+ for (i = 1; argv[arg][i]; i++) {
+ switch (argv[arg][i]) {
+ case '-':
+ if (i != 1 || argv[arg][i + 1])
+ invopt(&argv[arg][i]);
+ goto endargs;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '0':
+ pagelen = atoi(argv[arg] + i);
+ havepagelen = 1;
+ goto nextarg;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'e':
+ eflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'p':
+ if (argv[arg][i + 1]) {
+ pstring = &argv[arg][i + 1];
+ } else if (argv[++arg]) {
+ --argc;
+ pstring = argv[arg];
+ } else
+ needarg("-p");
+ goto nextarg;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ default:
+ invopt(&argv[arg][i]);
+ }
+ }
+nextarg:
+ ;
+ }
+endargs:
+ for (arg = 1; argv[arg]; arg++) {
+ if (*argv[arg] == '-') {
+ if (argv[arg][1] == '-') {
+ arg++;
+ break;
+ }
+ if (argv[arg][1] == '\0')
+ break;
+ if (argv[arg][1] == 'p' && argv[arg][2] == '\0')
+ arg++;
+ continue;
+ }
+ if (*argv[arg] != '+')
+ break;
+ argc--;
+ switch (*(argv[arg] + 1)) {
+ case '\0':
+ needarg("+");
+ /*NOTREACHED*/
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '0':
+ startline = atoi(argv[arg] + 1);
+ break;
+ case '/':
+ searchfor = argv[arg] + 2;
+ if (*searchfor == '\0')
+ needarg("+/");
+ p = searchfor + strlen(searchfor) - 1;
+ if (*p == '/') *p = '\0';
+ if (*searchfor == '\0')
+ needarg("+/");
+ break;
+ default:
+ invopt(argv[arg]);
+ }
+ }
+ if (argc == 1) {
+ pgfile(stdin, "stdin");
+ } else {
+ files.first = arg;
+ files.last = arg + argc - 1;
+ for ( ; argv[arg]; arg += nextfile) {
+ nextfile = 1;
+ files.current = arg;
+ if (argc > 2) {
+ static int firsttime;
+ firsttime++;
+ if (firsttime > 1) {
+ mesg(_("(Next file: "));
+ mesg(argv[arg]);
+ mesg(")");
+newfile:
+ if (ontty) {
+ prompt(-1);
+ switch(cmd.key) {
+ case 'n':
+ /*
+ * Next file.
+ */
+ if (cmd.count == 0)
+ cmd.count = 1;
+ nextfile = cmd.count;
+ if (checkf()) {
+ nextfile = 1;
+ mesg(":");
+ goto newfile;
+ }
+ continue;
+ case 'p':
+ /*
+ * Previous file.
+ */
+ if (cmd.count == 0)
+ cmd.count = 1;
+ nextfile = 0 - cmd.count;
+ if (checkf()) {
+ nextfile = 1;
+ mesg(":");
+ goto newfile;
+ }
+ continue;
+ case 'q':
+ case 'Q':
+ quit(exitstatus);
+ }
+ } else mesg("\n");
+ }
+ }
+ if (strcmp(argv[arg], "-") == 0)
+ input = stdin;
+ else {
+ input = fopen(argv[arg], "r");
+ if (input == NULL) {
+ pgerror(errno, argv[arg]);
+ exitstatus++;
+ continue;
+ }
+ }
+ if (ontty == 0 && argc > 2) {
+ /*
+ * Use the prefix as specified by SUSv2.
+ */
+ write(1, "::::::::::::::\n", 15);
+ write(1, argv[arg], strlen(argv[arg]));
+ write(1, "\n::::::::::::::\n", 16);
+ }
+ pgfile(input, argv[arg]);
+ if (input != stdin)
+ fclose(input);
+ }
+ }
+ quit(exitstatus);
+ /*NOTREACHED*/
+ return 0;
+}
diff --git a/text-utils/rev.1 b/text-utils/rev.1
new file mode 100644
index 0000000..6288616
--- /dev/null
+++ b/text-utils/rev.1
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1985, 1992 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)rev.1 6.3 (Berkeley) 3/21/92
+.\" Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu)
+.\" and Brian Koehmstedt (bpk@gnu.ai.mit.edu)
+.\"
+.Dd March 21, 1992
+.Dt REV 1
+.Os
+.Sh NAME
+.Nm rev
+.Nd reverse lines of a file or files
+.Sh SYNOPSIS
+.Nm rev
+.Op Ar file ...
+.Sh DESCRIPTION
+The
+.Nm rev
+utility copies the specified files to the standard output, reversing the
+order of characters in every line.
+If no files are specified, the standard input is read.
+.Sh AVAILABILITY
+The rev command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/rev.c b/text-utils/rev.c
new file mode 100644
index 0000000..3ae38cf
--- /dev/null
+++ b/text-utils/rev.c
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 1987, 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu)
+ * and Brian Koehmstedt (bpk@gnu.ai.mit.edu)
+ *
+ * Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle
+ * last line that has no newline correctly.
+ * 3-Jun-1998: Patched by Nicolai Langfeldt to work better on Linux:
+ * Handle any-length-lines. Code copied from util-linux' setpwnam.c
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ *
+ */
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "nls.h"
+#include "widechar.h"
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ register char *filename;
+ register wchar_t *t;
+ size_t buflen = 512;
+ wchar_t *p = malloc(buflen*sizeof(wchar_t));
+ size_t len;
+ FILE *fp;
+ int ch, rval;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ fp = stdin;
+ filename = "stdin";
+ rval = 0;
+ do {
+ if (*argv) {
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ warn("cannot open %s", *argv );
+ rval = 1;
+ ++argv;
+ continue;
+ }
+ filename = *argv++;
+ }
+
+ while (fgetws(p, buflen, fp)) {
+
+ len = wcslen(p);
+
+ /* This is my hack from setpwnam.c -janl */
+ while (p[len-1] != '\n' && !feof(fp)) {
+ /* Extend input buffer if it failed getting the whole line */
+
+ /* So now we double the buffer size */
+ buflen *= 2;
+
+ p = realloc(p, buflen*sizeof(wchar_t));
+ if (p == NULL)
+ err(1, _("unable to allocate bufferspace"));
+
+ /* And fill the rest of the buffer */
+ if (fgetws(&p[len], buflen/2, fp) == NULL) break;
+
+ len = wcslen(p);
+
+ /* That was a lot of work for nothing. Gimme perl! */
+ }
+
+ t = p + len - 1 - (*(p+len-1)=='\r' || *(p+len-1)=='\n');
+ for ( ; t >= p; --t)
+ if (*t != 0)
+ putwchar(*t);
+ putwchar('\n');
+ }
+ fflush(fp);
+ if (ferror(fp)) {
+ warn("%s", filename);
+ rval = 1;
+ }
+ if (fclose(fp))
+ rval = 1;
+ } while(*argv);
+ exit(rval);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, _("usage: rev [file ...]\n"));
+ exit(1);
+}
diff --git a/text-utils/tailf.1 b/text-utils/tailf.1
new file mode 100644
index 0000000..294d9d6
--- /dev/null
+++ b/text-utils/tailf.1
@@ -0,0 +1,61 @@
+.\" tailf.1 --
+.\" Created: Thu Jan 11 16:43:10 1996 by faith@acm.org
+.\" Copyright 1996, 2003 Rickard E. Faith (faith@acm.org)
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.TH TAILF 1 "13 February 2003" "" "Linux Programmer's Manual"
+.SH NAME
+tailf \- follow the growth of a log file
+.SH SYNOPSIS
+.B tailf
+[\fIOPTION\fR] \fIfile\fR
+.SH DESCRIPTION
+.B tailf
+will print out the last 10 lines of a file and then wait for the file to
+grow. It is similar to
+.B tail -f
+but does not access the file when it is not growing. This has the side
+effect of not updating the access time for the file, so a filesystem flush
+does not occur periodically when no log activity is happening.
+.PP
+.B tailf
+is extremely useful for monitoring log files on a laptop when logging is
+infrequent and the user desires that the hard disk spin down to conserve
+battery life.
+.PP
+Mandatory arguments to long options are mandatory for short options too.
+.TP
+\fB\-n\fR, \fB\-\-lines\fR=\fIN\fR, \fB\-N\fR
+output the last
+.I N
+lines, instead of the last 10.
+.SH AUTHOR
+This program was originally written by Rik Faith (faith@acm.org) and may be freely
+distributed under the terms of the X11/MIT License. There is ABSOLUTELY
+NO WARRANTY for this program.
+
+The latest inotify based implementation was written by Karel Zak (kzak@redhat.com).
+.SH "SEE ALSO"
+.BR tail "(1), " less "(1)"
+.SH AVAILABILITY
+The tailf command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/tailf.c b/text-utils/tailf.c
new file mode 100644
index 0000000..75998ce
--- /dev/null
+++ b/text-utils/tailf.c
@@ -0,0 +1,227 @@
+/* tailf.c -- tail a log file and then follow it
+ * Created: Tue Jan 9 15:49:21 1996 by faith@acm.org
+ * Copyright 1996, 2003 Rickard E. Faith (faith@acm.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * less -F and tail -f cause a disk access every five seconds. This
+ * program avoids this problem by waiting for the file size to change.
+ * Hence, the file is not accessed, and the access time does not need to be
+ * flushed back to disk. This is sort of a "stealth" tail.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <err.h>
+#ifdef HAVE_INOTIFY_INIT
+#include <sys/inotify.h>
+#endif
+#include "nls.h"
+#include "usleep.h"
+
+#define DEFAULT_LINES 10
+
+static void
+tailf(const char *filename, int lines)
+{
+ char *buf, *p;
+ int head = 0;
+ int tail = 0;
+ FILE *str;
+ int i;
+
+ if (!(str = fopen(filename, "r")))
+ err(EXIT_FAILURE, _("cannot open \"%s\" for read"), filename);
+
+ buf = malloc(lines * BUFSIZ);
+ p = buf;
+ while (fgets(p, BUFSIZ, str)) {
+ if (++tail >= lines) {
+ tail = 0;
+ head = 1;
+ }
+ p = buf + (tail * BUFSIZ);
+ }
+
+ if (head) {
+ for (i = tail; i < lines; i++)
+ fputs(buf + (i * BUFSIZ), stdout);
+ for (i = 0; i < tail; i++)
+ fputs(buf + (i * BUFSIZ), stdout);
+ } else {
+ for (i = head; i < tail; i++)
+ fputs(buf + (i * BUFSIZ), stdout);
+ }
+
+ fflush(stdout);
+ free(buf);
+ fclose(str);
+}
+
+static void
+roll_file(const char *filename, off_t *size)
+{
+ char buf[BUFSIZ];
+ int fd;
+ struct stat st;
+
+ if (!(fd = open(filename, O_RDONLY)))
+ err(EXIT_FAILURE, _("cannot open \"%s\" for read"), filename);
+
+ if (fstat(fd, &st) == -1)
+ err(EXIT_FAILURE, _("cannot stat \"%s\""), filename);
+
+ if (st.st_size == *size) {
+ close(fd);
+ return;
+ }
+
+ if (lseek(fd, *size, SEEK_SET) != (off_t)-1) {
+ ssize_t rc, wc;
+
+ while ((rc = read(fd, buf, sizeof(buf))) > 0) {
+ wc = write(STDOUT_FILENO, buf, rc);
+ if (rc != wc)
+ warnx(_("incomplete write to \"%s\" (written %zd, expected %zd)\n"),
+ filename, wc, rc);
+ }
+ fflush(stdout);
+ }
+ close(fd);
+ *size = st.st_size;
+}
+
+static void
+watch_file(const char *filename, off_t *size)
+{
+ do {
+ roll_file(filename, size);
+ usleep(250000);
+ } while(1);
+}
+
+
+#ifdef HAVE_INOTIFY_INIT
+
+#define EVENTS (IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)
+#define NEVENTS 4
+
+static int
+watch_file_inotify(const char *filename, off_t *size)
+{
+ char buf[ NEVENTS * sizeof(struct inotify_event) ];
+ int fd, ffd, e;
+ ssize_t len;
+
+ fd = inotify_init();
+ if (fd == -1)
+ return 0;
+
+ ffd = inotify_add_watch(fd, filename, EVENTS);
+ if (ffd == -1) {
+ if (errno == ENOSPC)
+ errx(EXIT_FAILURE, _("%s: cannot add inotify watch "
+ "(limit of inotify watches was reached)."),
+ filename);
+
+ err(EXIT_FAILURE, _("%s: cannot add inotify watch."), filename);
+ }
+
+ while (ffd >= 0) {
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0 && (errno == EINTR || errno == EAGAIN))
+ continue;
+ if (len < 0)
+ err(EXIT_FAILURE,
+ _("%s: cannot read inotify events"), filename);
+
+ for (e = 0; e < len; ) {
+ struct inotify_event *ev = (struct inotify_event *) &buf[e];
+
+ if (ev->mask & IN_MODIFY)
+ roll_file(filename, size);
+ else {
+ close(ffd);
+ ffd = -1;
+ break;
+ }
+ e += sizeof(struct inotify_event) + ev->len;
+ }
+ }
+ close(fd);
+ return 1;
+}
+
+#endif /* HAVE_INOTIFY_INIT */
+
+int main(int argc, char **argv)
+{
+ const char *filename;
+ int lines = DEFAULT_LINES;
+ struct stat st;
+ off_t size = 0;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ argc--;
+ argv++;
+
+ for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
+ if (!strcmp(*argv, "-n") || !strcmp(*argv, "--lines")) {
+ argc--; argv++;
+ if (argc > 0 && (lines = atoi(argv[0])) <= 0)
+ errx(EXIT_FAILURE, _("invalid number of lines"));
+ }
+ else if (isdigit(argv[0][1])) {
+ if ((lines = atoi(*argv + 1)) <= 0)
+ errx(EXIT_FAILURE, _("invalid number of lines"));
+ }
+ else
+ errx(EXIT_FAILURE, _("invalid option"));
+ }
+
+ if (argc != 1)
+ errx(EXIT_FAILURE, _("usage: tailf [-n N | -N] logfile"));
+
+ filename = argv[0];
+
+ if (stat(filename, &st) != 0)
+ err(EXIT_FAILURE, _("cannot stat \"%s\""), filename);
+
+ size = st.st_size;;
+ tailf(filename, lines);
+
+#ifdef HAVE_INOTIFY_INIT
+ if (!watch_file_inotify(filename, &size))
+#endif
+ watch_file(filename, &size);
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/text-utils/ul.1 b/text-utils/ul.1
new file mode 100644
index 0000000..cec6940
--- /dev/null
+++ b/text-utils/ul.1
@@ -0,0 +1,110 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ul.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt UL 1
+.Os BSD 4
+.Sh NAME
+.Nm ul
+.Nd do underlining
+.Sh SYNOPSIS
+.Nm ul
+.Op Fl i
+.Op Fl t Ar terminal
+.Op Ar name Ar ...
+.Sh DESCRIPTION
+.Nm Ul
+reads the named files (or standard input if none are given)
+and translates occurrences of underscores to the sequence
+which indicates underlining for the terminal in use, as specified
+by the environment variable
+.Ev TERM .
+The
+.Pa terminfo
+database is read to determine the appropriate sequences for underlining.
+If the terminal is incapable of underlining, but is capable of
+a standout mode then that is used instead.
+If the terminal can overstrike,
+or handles underlining automatically,
+.Nm ul
+degenerates to
+.Xr cat 1 .
+If the terminal cannot underline, underlining is ignored.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl i
+Underlining is indicated by a separate line containing appropriate
+dashes `\-'; this is useful when you want to look at the underlining
+which is present in an
+.Xr nroff
+output stream on a crt-terminal.
+.It Fl t Ar terminal
+Overrides the terminal type specified in the environment with
+.Ar terminal .
+.El
+.Sh ENVIRONMENT
+The following environment variable is used:
+.Bl -tag -width TERM
+.It Ev TERM
+The
+.Ev TERM
+variable is used to relate a tty device
+with its device capability description (see
+.Xr terminfo 5 ) .
+.Ev TERM
+is set at login time, either by the default terminal type
+specified in
+.Pa /etc/ttys
+or as set during the login process by the user in their
+.Pa login
+file (see
+.Xr setenv 1 ) .
+.El
+.Sh SEE ALSO
+.Xr man 1 ,
+.Xr nroff 1 ,
+.Xr colcrt 1
+.Sh BUGS
+.Xr Nroff
+usually outputs a series of backspaces and underlines intermixed
+with the text to indicate underlining. No attempt is made to optimize
+the backward motion.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh AVAILABILITY
+The ul command is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/text-utils/ul.c b/text-utils/ul.c
new file mode 100644
index 0000000..a1491b8
--- /dev/null
+++ b/text-utils/ul.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * modified by Kars de Jong <jongk@cs.utwente.nl>
+ * to use terminfo instead of termcap.
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * added Native Language Support
+ * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
+ * modified to work correctly in multi-byte locales
+ */
+
+#include <stdio.h>
+#include <unistd.h> /* for getopt(), isatty() */
+#include <string.h> /* for memset(), strcpy() */
+#include <term.h> /* for setupterm() */
+#include <stdlib.h> /* for getenv() */
+#include <limits.h> /* for INT_MAX */
+#include "nls.h"
+
+#include "widechar.h"
+
+#ifdef HAVE_WIDECHAR
+static int put1wc(int c) /* Output an ASCII character as a wide character */
+{
+ if (putwchar(c) == WEOF)
+ return EOF;
+ else
+ return c;
+}
+#define putwp(s) tputs(s,1,put1wc)
+#else
+#define putwp(s) putp(s)
+#endif
+
+void filter(FILE *f);
+void flushln(void);
+void overstrike(void);
+void iattr(void);
+void initbuf(void);
+void fwd(void);
+void reverse(void);
+void initinfo(void);
+void outc(wint_t c, int width);
+void setmode(int newmode);
+static void setcol(int newcol);
+static void needcol(int col);
+
+#define IESC '\033'
+#define SO '\016'
+#define SI '\017'
+#define HFWD '9'
+#define HREV '8'
+#define FREV '7'
+
+#define NORMAL 000
+#define ALTSET 001 /* Reverse */
+#define SUPERSC 002 /* Dim */
+#define SUBSC 004 /* Dim | Ul */
+#define UNDERL 010 /* Ul */
+#define BOLD 020 /* Bold */
+#define INITBUF 512
+
+int must_use_uc, must_overstrike;
+char *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
+ *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
+ *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
+
+struct CHAR {
+ char c_mode;
+ wchar_t c_char;
+ int c_width;
+} ;
+
+struct CHAR *obuf;
+int obuflen; /* Tracks number of elements in obuf. */
+int col, maxcol;
+int mode;
+int halfpos;
+int upln;
+int iflag;
+
+#define PRINT(s) if (s == NULL) /* void */; else putwp(s)
+
+int main(int argc, char **argv)
+{
+ int c, ret;
+ char *termtype;
+ FILE *f;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ termtype = getenv("TERM");
+ if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
+ termtype = "lpr";
+ while ((c = getopt(argc, argv, "it:T:")) != -1)
+ switch(c) {
+
+ case 't':
+ case 'T': /* for nroff compatibility */
+ termtype = optarg;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+
+ default:
+ fprintf(stderr,
+ _("usage: %s [ -i ] [ -tTerm ] file...\n"),
+ argv[0]);
+ exit(1);
+ }
+ setupterm(termtype, 1, &ret);
+ switch(ret) {
+
+ case 1:
+ break;
+
+ default:
+ fprintf(stderr,_("trouble reading terminfo"));
+ /* fall through to ... */
+
+ case 0:
+ /* No such terminal type - assume dumb */
+ setupterm("dumb", 1, (int *)0);
+ break;
+ }
+ initinfo();
+ if ( (tigetflag("os") && ENTER_BOLD==NULL ) ||
+ (tigetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
+ must_overstrike = 1;
+ initbuf();
+ if (optind == argc)
+ filter(stdin);
+ else for (; optind<argc; optind++) {
+ f = fopen(argv[optind],"r");
+ if (f == NULL) {
+ perror(argv[optind]);
+ exit(1);
+ } else
+ filter(f);
+ }
+ if (ferror(stdout) || fclose(stdout))
+ return 1;
+ return 0;
+}
+
+void filter(FILE *f)
+{
+ wint_t c;
+ int i, w;
+
+ while ((c = getwc(f)) != WEOF) switch(c) {
+
+ case '\b':
+ setcol(col - 1);
+ continue;
+
+ case '\t':
+ setcol((col+8) & ~07);
+ continue;
+
+ case '\r':
+ setcol(0);
+ continue;
+
+ case SO:
+ mode |= ALTSET;
+ continue;
+
+ case SI:
+ mode &= ~ALTSET;
+ continue;
+
+ case IESC:
+ switch (c = getwc(f)) {
+
+ case HREV:
+ if (halfpos == 0) {
+ mode |= SUPERSC;
+ halfpos--;
+ } else if (halfpos > 0) {
+ mode &= ~SUBSC;
+ halfpos--;
+ } else {
+ halfpos = 0;
+ reverse();
+ }
+ continue;
+
+ case HFWD:
+ if (halfpos == 0) {
+ mode |= SUBSC;
+ halfpos++;
+ } else if (halfpos < 0) {
+ mode &= ~SUPERSC;
+ halfpos++;
+ } else {
+ halfpos = 0;
+ fwd();
+ }
+ continue;
+
+ case FREV:
+ reverse();
+ continue;
+
+ default:
+ fprintf(stderr,
+ _("Unknown escape sequence in input: %o, %o\n"),
+ IESC, c);
+ exit(1);
+ }
+ continue;
+
+ case '_':
+ if (obuf[col].c_char || obuf[col].c_width < 0) {
+ while(col > 0 && obuf[col].c_width < 0)
+ col--;
+ w = obuf[col].c_width;
+ for (i = 0; i < w; i++)
+ obuf[col++].c_mode |= UNDERL | mode;
+ setcol(col);
+ continue;
+ }
+ obuf[col].c_char = '_';
+ obuf[col].c_width = 1;
+ /* fall through */
+ case ' ':
+ setcol(col + 1);
+ continue;
+
+ case '\n':
+ flushln();
+ continue;
+
+ case '\f':
+ flushln();
+ putwchar('\f');
+ continue;
+
+ default:
+ if (!iswprint(c)) /* non printing */
+ continue;
+ w = wcwidth(c);
+ needcol(col + w);
+ if (obuf[col].c_char == '\0') {
+ obuf[col].c_char = c;
+ for (i = 0; i < w; i++)
+ obuf[col+i].c_mode = mode;
+ obuf[col].c_width = w;
+ for (i = 1; i < w; i++)
+ obuf[col+i].c_width = -1;
+ } else if (obuf[col].c_char == '_') {
+ obuf[col].c_char = c;
+ for (i = 0; i < w; i++)
+ obuf[col+i].c_mode |= UNDERL|mode;
+ obuf[col].c_width = w;
+ for (i = 1; i < w; i++)
+ obuf[col+i].c_width = -1;
+ } else if (obuf[col].c_char == c) {
+ for (i = 0; i < w; i++)
+ obuf[col+i].c_mode |= BOLD|mode;
+ } else {
+ w = obuf[col].c_width;
+ for (i = 0; i < w; i++)
+ obuf[col+i].c_mode = mode;
+ }
+ setcol(col + w);
+ continue;
+ }
+ if (maxcol)
+ flushln();
+}
+
+void flushln(void)
+{
+ int lastmode;
+ int i;
+ int hadmodes = 0;
+
+ lastmode = NORMAL;
+ for (i=0; i<maxcol; i++) {
+ if (obuf[i].c_mode != lastmode) {
+ hadmodes++;
+ setmode(obuf[i].c_mode);
+ lastmode = obuf[i].c_mode;
+ }
+ if (obuf[i].c_char == '\0') {
+ if (upln) {
+ PRINT(CURS_RIGHT);
+ } else
+ outc(' ', 1);
+ } else
+ outc(obuf[i].c_char, obuf[i].c_width);
+ if (obuf[i].c_width > 1)
+ i += obuf[i].c_width -1;
+ }
+ if (lastmode != NORMAL) {
+ setmode(0);
+ }
+ if (must_overstrike && hadmodes)
+ overstrike();
+ putwchar('\n');
+ if (iflag && hadmodes)
+ iattr();
+ (void)fflush(stdout);
+ if (upln)
+ upln--;
+ initbuf();
+}
+
+/*
+ * For terminals that can overstrike, overstrike underlines and bolds.
+ * We don't do anything with halfline ups and downs, or Greek.
+ */
+void overstrike(void)
+{
+ register int i;
+#ifdef __GNUC__
+ register wchar_t *lbuf = __builtin_alloca((maxcol+1)*sizeof(wchar_t));
+#else
+ wchar_t lbuf[256];
+#endif
+ register wchar_t *cp = lbuf;
+ int hadbold=0;
+
+ /* Set up overstrike buffer */
+ for (i=0; i<maxcol; i++)
+ switch (obuf[i].c_mode) {
+ case NORMAL:
+ default:
+ *cp++ = ' ';
+ break;
+ case UNDERL:
+ *cp++ = '_';
+ break;
+ case BOLD:
+ *cp++ = obuf[i].c_char;
+ if (obuf[i].c_width > 1)
+ i += obuf[i].c_width - 1;
+ hadbold=1;
+ break;
+ }
+ putwchar('\r');
+ for (*cp=' '; *cp==' '; cp--)
+ *cp = 0;
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp);
+ if (hadbold) {
+ putwchar('\r');
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp=='_' ? ' ' : *cp);
+ putwchar('\r');
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp=='_' ? ' ' : *cp);
+ }
+}
+
+void iattr(void)
+{
+ register int i;
+#ifdef __GNUC__
+ register char *lbuf = __builtin_alloca((maxcol+1)*sizeof(char));
+#else
+ char lbuf[256];
+#endif
+ register char *cp = lbuf;
+
+ for (i=0; i<maxcol; i++)
+ switch (obuf[i].c_mode) {
+ case NORMAL: *cp++ = ' '; break;
+ case ALTSET: *cp++ = 'g'; break;
+ case SUPERSC: *cp++ = '^'; break;
+ case SUBSC: *cp++ = 'v'; break;
+ case UNDERL: *cp++ = '_'; break;
+ case BOLD: *cp++ = '!'; break;
+ default: *cp++ = 'X'; break;
+ }
+ for (*cp=' '; *cp==' '; cp--)
+ *cp = 0;
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp);
+ putwchar('\n');
+}
+
+void initbuf(void)
+{
+ if (obuf == NULL) { /* First time. */
+ obuflen = INITBUF;
+ obuf = malloc(sizeof(struct CHAR) * obuflen);
+ if (obuf == NULL) {
+ fprintf(stderr, _("Unable to allocate buffer.\n"));
+ exit(1);
+ }
+ }
+
+ /* assumes NORMAL == 0 */
+ memset(obuf, 0, sizeof(struct CHAR) * obuflen);
+ setcol(0);
+ maxcol = 0;
+ mode &= ALTSET;
+}
+
+void fwd(void)
+{
+ int oldcol, oldmax;
+
+ oldcol = col;
+ oldmax = maxcol;
+ flushln();
+ setcol(oldcol);
+ maxcol = oldmax;
+}
+
+void reverse(void)
+{
+ upln++;
+ fwd();
+ PRINT(CURS_UP);
+ PRINT(CURS_UP);
+ upln++;
+}
+
+void initinfo(void)
+{
+ CURS_UP = tigetstr("cuu1");
+ CURS_RIGHT = tigetstr("cuf1");
+ CURS_LEFT = tigetstr("cub1");
+ if (CURS_LEFT == NULL)
+ CURS_LEFT = "\b";
+
+ ENTER_STANDOUT = tigetstr("smso");
+ EXIT_STANDOUT = tigetstr("rmso");
+ ENTER_UNDERLINE = tigetstr("smul");
+ EXIT_UNDERLINE = tigetstr("rmul");
+ ENTER_DIM = tigetstr("dim");
+ ENTER_BOLD = tigetstr("bold");
+ ENTER_REVERSE = tigetstr("rev");
+ EXIT_ATTRIBUTES = tigetstr("sgr0");
+
+ if (!ENTER_BOLD && ENTER_REVERSE)
+ ENTER_BOLD = ENTER_REVERSE;
+ if (!ENTER_BOLD && ENTER_STANDOUT)
+ ENTER_BOLD = ENTER_STANDOUT;
+ if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
+ ENTER_UNDERLINE = ENTER_STANDOUT;
+ EXIT_UNDERLINE = EXIT_STANDOUT;
+ }
+ if (!ENTER_DIM && ENTER_STANDOUT)
+ ENTER_DIM = ENTER_STANDOUT;
+ if (!ENTER_REVERSE && ENTER_STANDOUT)
+ ENTER_REVERSE = ENTER_STANDOUT;
+ if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
+ EXIT_ATTRIBUTES = EXIT_STANDOUT;
+
+ /*
+ * Note that we use REVERSE for the alternate character set,
+ * not the as/ae capabilities. This is because we are modelling
+ * the model 37 teletype (since that's what nroff outputs) and
+ * the typical as/ae is more of a graphics set, not the greek
+ * letters the 37 has.
+ */
+
+ UNDER_CHAR = tigetstr("uc");
+ must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
+}
+
+static int curmode = 0;
+
+void
+outc(wint_t c, int width) {
+ int i;
+
+ putwchar(c);
+ if (must_use_uc && (curmode&UNDERL)) {
+ for (i=0; i<width; i++)
+ PRINT(CURS_LEFT);
+ for (i=0; i<width; i++)
+ PRINT(UNDER_CHAR);
+ }
+}
+
+void setmode(int newmode)
+{
+ if (!iflag) {
+ if (curmode != NORMAL && newmode != NORMAL)
+ setmode(NORMAL);
+ switch (newmode) {
+ case NORMAL:
+ switch(curmode) {
+ case NORMAL:
+ break;
+ case UNDERL:
+ PRINT(EXIT_UNDERLINE);
+ break;
+ default:
+ /* This includes standout */
+ PRINT(EXIT_ATTRIBUTES);
+ break;
+ }
+ break;
+ case ALTSET:
+ PRINT(ENTER_REVERSE);
+ break;
+ case SUPERSC:
+ /*
+ * This only works on a few terminals.
+ * It should be fixed.
+ */
+ PRINT(ENTER_UNDERLINE);
+ PRINT(ENTER_DIM);
+ break;
+ case SUBSC:
+ PRINT(ENTER_DIM);
+ break;
+ case UNDERL:
+ PRINT(ENTER_UNDERLINE);
+ break;
+ case BOLD:
+ PRINT(ENTER_BOLD);
+ break;
+ default:
+ /*
+ * We should have some provision here for multiple modes
+ * on at once. This will have to come later.
+ */
+ PRINT(ENTER_STANDOUT);
+ break;
+ }
+ }
+ curmode = newmode;
+}
+
+static void
+setcol(int newcol) {
+ col = newcol;
+
+ if (col < 0)
+ col = 0;
+ else if (col > maxcol)
+ needcol(col);
+}
+
+static void
+needcol(int col) {
+ maxcol = col;
+
+ /* If col >= obuflen, expand obuf until obuflen > col. */
+ while (col >= obuflen) {
+ /* Paranoid check for obuflen == INT_MAX. */
+ if (obuflen == INT_MAX) {
+ fprintf(stderr,
+ _("Input line too long.\n"));
+ exit(1);
+ }
+
+ /* Similar paranoia: double only up to INT_MAX. */
+ obuflen = ((INT_MAX / 2) < obuflen)
+ ? INT_MAX
+ : obuflen * 2;
+
+ /* Now we can try to expand obuf. */
+ obuf = realloc(obuf, sizeof(struct CHAR) * obuflen);
+ if (obuf == NULL) {
+ fprintf(stderr,
+ _("Out of memory when growing buffer.\n"));
+ exit(1);
+ }
+ }
+}