14 Commits

Author SHA1 Message Date
Ben Gras
957d948cbd This is the right 3.1.3a. 2007-06-08 11:24:30 +00:00
Ben Gras
b648da01d7 Tag of 3.1.3a, an incremental release of 3.1.3. 2007-06-08 11:21:21 +00:00
Ben Gras
818b1a2741 Disable this test - there's a bug that vfs doesn't know an
updated directory size after new directory entries are added. To
be fixed.
2007-06-07 09:59:44 +00:00
Ben Gras
2862654b07 firstdatazone is prone to overflowing with many inodes. 2007-06-06 15:14:58 +00:00
Ben Gras
26cf8b90ea Not used in vfs. 2007-06-06 14:48:18 +00:00
Ben Gras
1560fc9b94 Bugfix for 'mkdir x; mkdir y; mv x y' 2007-05-31 13:37:38 +00:00
Ben Gras
af78f809ee improve FS process bookkeeping; fixes bug where vfs tries to e.g. send
stime messages to NONE of an unmounted filesystem.
2007-05-31 12:20:09 +00:00
Ben Gras
0e44ca2b61 Hack for dhcp on 3.1.3 branch (not necessary on trunk) 2007-05-30 16:44:43 +00:00
Ben Gras
2db64a7fa5 run is as root so it can retrieve its signal set 2007-05-30 16:41:14 +00:00
Ben Gras
3a3f4496d9 Assume bios parameters are wrong/missing if any of the parameters are 0. 2007-05-30 16:13:36 +00:00
Ben Gras
f73affcfc3 Disable copy diagnostic. 2007-05-30 15:45:47 +00:00
Ben Gras
dc4916c77a include 'printer' 2007-05-30 15:39:27 +00:00
Ben Gras
0a9128303d New small release of 3.1.3 branch in preparation. 2007-05-30 13:40:54 +00:00
Ben Gras
ccd02a6028 Backports and a fix for the 3.1.3 branch.
. backports of various fixes already on the trunk
  . pass label of driver as argv[0], allowing the pci
    driver to free pci resources for it (solved differently
    on the trunk code), allowing pci drivers to be restarted
2007-05-01 13:29:50 +00:00
48814 changed files with 632154 additions and 8958008 deletions

43
.gitignore vendored
View File

@@ -1,43 +0,0 @@
cscope.*
*.swap
.*.sw[po]
.sw[po]
*~
*.orig
*.diff
*.patch
*.rej
*.[1-9].gz
*.o
*.[psS]o
*.pico
lib*.so*
*.a
*.so.*
*.d
.depend
nbsdsrc/*
TAGS
tags
GPATH
GRTAGS
GSYMS
GTAGS
\#*#
CVS
!/.gitignore
.gitignore
.svn
minix-port.patch
*.worldstone.log
.worldstone*
usr.bin/mdocml/man/*.7
etc/passwd
etc/pwd.db
etc/spwd.db
releasetools/image
releasetools/kernel
releasetools/revision
share/zoneinfo/builddir
lib/libc/compat__*
.gdbinit

View File

@@ -1,17 +0,0 @@
# MINIX 3 code review setup.
#
# This gerrit code review configuration is meant for performing per commit
# internal code reviews. If you are an external contributor please read and
# apply http://wiki.minix3.org/en/HowToContribute
#
# Consider reading http://wiki.openstack.org/GerritWorkflow to learn how
# to install git review on a Linux setup. On Minix you can use pkgin to
# install git-review.
#
[gerrit]
# The git-minix host is to be configured in your .ssh/config
#
host=gerrit.minix3.org
port=2222
project=minix
defaultbranch=master

10
LICENSE Normal file → Executable file
View File

@@ -50,13 +50,3 @@ observe the conditions of the GPL with respect to this software. As
clearly stated in Article 2 of the GPL, when GPL and nonGPL software are
distributed together on the same medium, this aggregation does not cause
the license of either part to apply to the other part.
Acknowledgements
This product includes software developed by the University of
California, Berkeley and its contributors.
This product includes software developed by Softweyr LLC, the
University of California, Berkeley, and its contributors.

647
Makefile Normal file → Executable file
View File

@@ -1,576 +1,71 @@
# $NetBSD: Makefile,v 1.303 2013/07/16 09:52:21 joerg Exp $
#
# This is the top-level makefile for building NetBSD. For an outline of
# how to build a snapshot or release, as well as other release engineering
# information, see http://www.NetBSD.org/developers/releng/index.html
#
# Not everything you can set or do is documented in this makefile. In
# particular, you should review the files in /usr/share/mk (especially
# bsd.README) for general information on building programs and writing
# Makefiles within this structure, and see the comments in src/etc/Makefile
# for further information on installation and release set options.
#
# Variables listed below can be set on the make command line (highest
# priority), in /etc/mk.conf (middle priority), or in the environment
# (lowest priority).
#
# Variables:
# DESTDIR is the target directory for installation of the compiled
# software. It defaults to /. Note that programs are built against
# libraries installed in DESTDIR.
# MKMAN, if `no', will prevent building of manual pages.
# MKOBJDIRS, if not `no', will build object directories at
# an appropriate point in a build.
# MKSHARE, if `no', will prevent building and installing
# anything in /usr/share.
# MKUPDATE, if not `no', will avoid a `make cleandir' at the start of
# `make build', as well as having the effects listed in
# /usr/share/mk/bsd.README.
# NOCLEANDIR, if defined, will avoid a `make cleandir' at the start
# of the `make build'.
# NOINCLUDES will avoid the `make includes' usually done by `make build'.
#
# See mk.conf(5) for more details.
#
#
# Targets:
# build:
# Builds a full release of NetBSD in DESTDIR, except for the
# /etc configuration files.
# If BUILD_DONE is set, this is an empty target.
# distribution:
# Builds a full release of NetBSD in DESTDIR, including the /etc
# configuration files.
# buildworld:
# As per `make distribution', except that it ensures that DESTDIR
# is not the root directory.
# installworld:
# Install the distribution from DESTDIR to INSTALLWORLDDIR (which
# defaults to the root directory). Ensures that INSTALLWORLDDIR
# is not the root directory if cross compiling.
# release:
# Does a `make distribution', and then tars up the DESTDIR files
# into ${RELEASEDIR}/${RELEASEMACHINEDIR}, in release(7) format.
# (See etc/Makefile for more information on this.)
# regression-tests:
# Runs the regression tests in "regress" on this host.
# sets:
# Populate ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/sets
# from ${DESTDIR}
# sourcesets:
# Populate ${RELEASEDIR}/source/sets from ${NETBSDSRCDIR}
# syspkgs:
# Populate ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/syspkgs
# from ${DESTDIR}
# iso-image:
# Create CD-ROM image in RELEASEDIR/iso.
# RELEASEDIR must already have been populated by `make release'
# or equivalent.
# iso-image-source:
# Create CD-ROM image with source in RELEASEDIR/iso.
# RELEASEDIR must already have been populated by
# `make release sourcesets' or equivalent.
# live-image:
# Create bootable live image for emulators or USB stick etc.
# in RELEASEDIR/liveimage.
# RELEASEDIR must already have been populated by `make release'
# or equivalent.
# install-image:
# Create bootable installation image for USB stick etc.
# in RELEASEDIR/installimage.
# RELEASEDIR must already have been populated by `make release'
# or equivalent.
#
# Targets invoked by `make build,' in order:
# cleandir: cleans the tree.
# do-top-obj: creates the top level object directory.
# do-tools-obj: creates object directories for the host toolchain.
# do-tools: builds host toolchain.
# params: record the values of variables that might affect the
# build.
# obj: creates object directories.
# do-distrib-dirs: creates the distribution directories.
# includes: installs include files.
# do-lib: builds and installs prerequisites from lib
# if ${MKCOMPAT} != "no".
# do-compat-lib: builds and installs prerequisites from compat/lib
# if ${MKCOMPAT} != "no".
# do-build: builds and installs the entire system.
# do-x11: builds and installs X11 if ${MKX11} != "no"; either
# X11R7 from src/external/mit/xorg if ${X11FLAVOUR} == "Xorg"
# or X11R6 from src/x11
# do-extsrc: builds and installs extsrc if ${MKEXTSRC} != "no".
# do-obsolete: installs the obsolete sets (for the postinstall-* targets).
#
.if ${.MAKEFLAGS:M${.CURDIR}/share/mk} == ""
.MAKEFLAGS: -m ${.CURDIR}/share/mk
.endif
#
# If _SRC_TOP_OBJ_ gets set here, we will end up with a directory that may
# not be the top level objdir, because "make obj" can happen in the *middle*
# of "make build" (long after <bsd.own.mk> is calculated it). So, pre-set
# _SRC_TOP_OBJ_ here so it will not be added to ${.MAKEOVERRIDES}.
#
_SRC_TOP_OBJ_=
.include <bsd.own.mk>
#
# Sanity check: make sure that "make build" is not invoked simultaneously
# with a standard recursive target.
#
.if make(build) || make(release) || make(snapshot)
.for targ in ${TARGETS:Nobj:Ncleandir}
.if make(${targ}) && !target(.BEGIN)
.BEGIN:
@echo 'BUILD ABORTED: "make build" and "make ${targ}" are mutually exclusive.'
@false
.endif
.endfor
.endif
#
# _SUBDIR is used to set SUBDIR, after removing directories that have
# BUILD_${dir}=no, or that have no ${dir}/Makefile.
#
_SUBDIR= tools lib include gnu external crypto/external bin games
_SUBDIR+= libexec sbin usr.bin
_SUBDIR+= usr.sbin share sys etc tests compat
_SUBDIR+= .WAIT rescue .WAIT distrib regress
.if defined(__MINIX)
# the minix subdir depends on some other things (e.g. lib/)
_SUBDIR+= .WAIT minix
.endif # defined(__MINIX)
.for dir in ${_SUBDIR}
.if "${dir}" == ".WAIT" \
|| (${BUILD_${dir}:Uyes} != "no" && exists(${dir}/Makefile))
SUBDIR+= ${dir}
.endif
.endfor
.if exists(regress)
regression-tests: .PHONY .MAKE
@echo Running regression tests...
${MAKEDIRTARGET} regress regress
.endif
.if ${MKUNPRIVED} != "no"
NOPOSTINSTALL= # defined
.endif
afterinstall: .PHONY .MAKE
.if ${MKMAN} != "no"
.if !defined(__MINIX)
${MAKEDIRTARGET} share/man makedb
.else
${MAKEDIRTARGET} minix/man makedb
.endif # !defined(__MINIX)
.endif
.if (${MKUNPRIVED} != "no" && ${MKINFO} != "no")
${MAKEDIRTARGET} gnu/usr.bin/texinfo/install-info infodir-meta
.endif
.if !defined(NOPOSTINSTALL)
${MAKEDIRTARGET} . postinstall-check
.endif
_POSTINSTALL= ${.CURDIR}/usr.sbin/postinstall/postinstall
_POSTINSTALL_ENV= \
AWK=${TOOL_AWK:Q} \
DB=${TOOL_DB:Q} \
HOST_SH=${HOST_SH:Q} \
MAKE=${MAKE:Q} \
PWD_MKDB=${TOOL_PWD_MKDB:Q} \
STAT=${TOOL_STAT:Q}
postinstall-check: .PHONY
@echo " === Post installation checks ==="
${_POSTINSTALL_ENV} ${HOST_SH} ${_POSTINSTALL} -s ${.CURDIR} -d ${DESTDIR}/ check; if [ $$? -gt 1 ]; then exit 1; fi
@echo " ================================"
postinstall-fix: .NOTMAIN .PHONY
@echo " === Post installation fixes ==="
${_POSTINSTALL_ENV} ${HOST_SH} ${_POSTINSTALL} -s ${.CURDIR} -d ${DESTDIR}/ fix
@echo " ==============================="
postinstall-fix-obsolete: .NOTMAIN .PHONY
@echo " === Removing obsolete files ==="
${_POSTINSTALL_ENV} ${HOST_SH} ${_POSTINSTALL} -s ${.CURDIR} -d ${DESTDIR}/ fix obsolete
@echo " ==============================="
#
# Targets (in order!) called by "make build".
#
.if defined(HAVE_GCC)
.if ${HAVE_GCC} == "4"
LIBGCC_EXT=4
BUILD_CC_LIB_BASEDIR= gnu/lib
BUILD_CC_LIB_BASETARGET= gnu-lib
.else
LIBGCC_EXT=
BUILD_CC_LIB_BASEDIR= external/gpl3/gcc/lib
BUILD_CC_LIB_BASETARGET= external-gpl3-gcc-lib
.endif
.endif
BUILDTARGETS+= check-tools
.if ${MKUPDATE} == "no" && !defined(NOCLEANDIR)
BUILDTARGETS+= cleandir
.endif
.if ${MKOBJDIRS} != "no"
BUILDTARGETS+= do-top-obj
.endif
.if ${USETOOLS} == "yes" # {
.if ${MKOBJDIRS} != "no"
BUILDTARGETS+= do-tools-obj
.endif
BUILDTARGETS+= do-tools
.endif # USETOOLS # }
BUILDTARGETS+= params
.if ${MKOBJDIRS} != "no"
BUILDTARGETS+= obj
.endif
BUILDTARGETS+= clean_METALOG
.if !defined(NODISTRIBDIRS)
BUILDTARGETS+= do-distrib-dirs
.endif
.if !defined(NOINCLUDES)
BUILDTARGETS+= includes
.endif
BUILDTARGETS+= do-lib
.if !defined(__MINIX)
# LSC Not used in MINIX3
BUILDTARGETS+= do-compat-lib
.endif # !defined(__MINIX)
BUILDTARGETS+= do-build
.if ${MKX11} != "no"
BUILDTARGETS+= do-x11
.endif
.if ${MKEXTSRC} != "no"
BUILDTARGETS+= do-extsrc
.endif
.if defined(__MINIX) && ${MKSRC} == "yes"
BUILDTARGETS+= do-installsrc
.endif # defined(__MINIX)
BUILDTARGETS+= do-obsolete
#
# Enforce proper ordering of some rules.
#
.ORDER: ${BUILDTARGETS}
includes-lib: .PHONY includes-include includes-sys
includes-gnu: .PHONY includes-lib
#
# Record the values of variables that might affect the build.
# If no values have changed, avoid updating the timestamp
# of the params file.
#
# This is referenced by _NETBSD_VERSION_DEPENDS in <bsd.own.mk>.
#
.include "${NETBSDSRCDIR}/etc/Makefile.params"
CLEANDIRFILES+= params
params: .EXEC
${_MKMSG_CREATE} params
@${PRINT_PARAMS} >${.TARGET}.new
@if cmp -s ${.TARGET}.new ${.TARGET} > /dev/null 2>&1; then \
: "params is unchanged" ; \
rm ${.TARGET}.new ; \
else \
: "params has changed or is new" ; \
mv ${.TARGET}.new ${.TARGET} ; \
fi
#
# Display current make(1) parameters
#
show-params: .PHONY .MAKE
@${PRINT_PARAMS}
#
# Build the system and install into DESTDIR.
#
START_TIME!= date
.if defined(__MINIX)
world: build .PHONY .MAKE
${MAKEDIRTARGET} . etcfiles
@echo "WARNING: "
@echo "WARNING: The 'world' target is obsolete, please use 'build' instead."
@echo "WARNING: "
etcfiles: .PHONY .MAKE
${MAKEDIRTARGET} etc install-etc-files-safe DESTDIR=${DESTDIR:U/}
etcforce: .PHONY .MAKE
${MAKEDIRTARGET} etc install-etc-files DESTDIR=${DESTDIR:U/}
.endif # defined(__MINIX)
build: .PHONY .MAKE
.if defined(BUILD_DONE)
@echo "Build already installed into ${DESTDIR}"
.else
@echo "Build started at: ${START_TIME}"
.for tgt in ${BUILDTARGETS}
${MAKEDIRTARGET} . ${tgt}
.endfor
${MAKEDIRTARGET} etc install-etc-release
.if defined(__MINIX)
${MAKEDIRTARGET} etc install-etc-files-safe DESTDIR=${DESTDIR:U/}
${MAKEDIRTARGET} releasetools do-hdboot
.endif # defined(__MINIX)
@echo "Build started at: ${START_TIME}"
@printf "Build finished at: " && date
.endif
#
# Build a full distribution, but not a release (i.e. no sets into
# ${RELEASEDIR}). "buildworld" enforces a build to ${DESTDIR} != /
#
distribution buildworld: .PHONY .MAKE
.if make(buildworld) && \
(!defined(DESTDIR) || ${DESTDIR} == "" || ${DESTDIR} == "/")
@echo "Won't make ${.TARGET} with DESTDIR=/"
@false
.endif
${MAKEDIRTARGET} . build NOPOSTINSTALL=1
${MAKEDIRTARGET} etc distribution INSTALL_DONE=1
.if defined(DESTDIR) && ${DESTDIR} != "" && ${DESTDIR} != "/"
${MAKEDIRTARGET} . postinstall-fix-obsolete
${MAKEDIRTARGET} distrib/sets checkflist
.endif
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Install the distribution from $DESTDIR to $INSTALLWORLDDIR (defaults to `/')
# If installing to /, ensures that the host's operating system is NetBSD and
# the host's `uname -m` == ${MACHINE}.
#
HOST_UNAME_S!= uname -s
.if ${HOST_OSTYPE:C/\-.*//} != "Minix"
HOST_UNAME_M!= uname -m
.else
HOST_UNAME_M:= ${MACHINE}
.endif
installworld: .PHONY .MAKE
.if (!defined(DESTDIR) || ${DESTDIR} == "" || ${DESTDIR} == "/")
@echo "Can't make ${.TARGET} to DESTDIR=/"
@false
.endif
.if !defined(INSTALLWORLDDIR) || \
${INSTALLWORLDDIR} == "" || ${INSTALLWORLDDIR} == "/"
.if (${HOST_UNAME_S} != "NetBSD") && (${HOST_UNAME_S} != "Minix")
@echo "Won't cross-make ${.TARGET} from ${HOST_UNAME_S} to Minix with INSTALLWORLDDIR=/"
@false
.endif
.if (${HOST_UNAME_M} != ${MACHINE})
@echo "Won't cross-make ${.TARGET} from ${HOST_UNAME_M} to ${MACHINE} with INSTALLWORLDDIR=/"
@false
.endif
.endif
${MAKEDIRTARGET} distrib/sets installsets \
INSTALLDIR=${INSTALLWORLDDIR:U/} INSTALLSETS=${INSTALLSETS:Q}
${MAKEDIRTARGET} . postinstall-check DESTDIR=${INSTALLWORLDDIR}
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Install modules from $DESTDIR to $INSTALLMODULESDIR
#
installmodules: .PHONY .MAKE
.if (!defined(DESTDIR) || ${DESTDIR} == "" || ${DESTDIR} == "/")
@echo "Can't make ${.TARGET} to DESTDIR=/"
@false
.endif
.if !defined(INSTALLMODULESDIR) || \
${INSTALLMODULESDIR} == "" || ${INSTALLMODULESDIR} == "/"
.if (${HOST_UNAME_S} != "NetBSD")
@echo "Won't cross-make ${.TARGET} from ${HOST_UNAME_S} to NetBSD with INSTALLMODULESDIR=/"
@false
.endif
.if (${HOST_UNAME_M} != ${MACHINE})
@echo "Won't cross-make ${.TARGET} from ${HOST_UNAME_M} to ${MACHINE} with INSTALLMODULESDIR=/"
@false
.endif
.endif
${MAKEDIRTARGET} sys/modules install DESTDIR=${INSTALLMODULESDIR:U/}
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Create sets from $DESTDIR or $NETBSDSRCDIR into $RELEASEDIR
#
.for tgt in sets sourcesets syspkgs
${tgt}: .PHONY .MAKE
${MAKEDIRTARGET} distrib/sets ${tgt}
.endfor
#
# Build a release or snapshot (implies "make distribution"). Note that
# in this case, the set lists will be checked before the tar files
# are made.
#
release snapshot: .PHONY .MAKE
${MAKEDIRTARGET} . distribution
${MAKEDIRTARGET} etc release DISTRIBUTION_DONE=1
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Create a CD-ROM image.
#
iso-image: .PHONY
${MAKEDIRTARGET} distrib iso_image
${MAKEDIRTARGET} etc iso-image
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
iso-image-source: .PHONY
${MAKEDIRTARGET} distrib iso_image CDSOURCE=true
${MAKEDIRTARGET} etc iso-image
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Create bootable live images.
#
live-image: .PHONY
${MAKEDIRTARGET} etc live-image
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Create bootable installation images.
#
install-image: .PHONY
${MAKEDIRTARGET} etc install-image
@echo "make ${.TARGET} started at: ${START_TIME}"
@printf "make ${.TARGET} finished at: " && date
#
# Special components of the "make build" process.
#
check-tools: .PHONY
.if ${TOOLCHAIN_MISSING} != "no" && !defined(EXTERNAL_TOOLCHAIN)
@echo '*** WARNING: Building on MACHINE=${MACHINE} with missing toolchain.'
@echo '*** May result in a failed build or corrupt binaries!'
.elif defined(EXTERNAL_TOOLCHAIN)
@echo '*** Using external toolchain rooted at ${EXTERNAL_TOOLCHAIN}.'
.endif
.if defined(NBUILDJOBS)
@echo '*** WARNING: NBUILDJOBS is obsolete; use -j directly instead!'
.endif
# Delete or sanitise a leftover METALOG from a previous build.
clean_METALOG: .PHONY .MAKE
.if ${MKUPDATE} != "no"
${MAKEDIRTARGET} distrib/sets clean_METALOG
.endif
do-distrib-dirs: .PHONY .MAKE
.if !defined(DESTDIR) || ${DESTDIR} == ""
${MAKEDIRTARGET} etc distrib-dirs DESTDIR=/
.else
${MAKEDIRTARGET} etc distrib-dirs DESTDIR=${DESTDIR}
.endif
.for targ in cleandir obj includes
do-${targ}: .PHONY ${targ}
@true
.endfor
do-tools: .PHONY .MAKE
${MAKEDIRTARGET} tools build_install
do-lib: .PHONY .MAKE
${MAKEDIRTARGET} lib build_install
do-compat-lib: .PHONY .MAKE
${MAKEDIRTARGET} compat build_install BOOTSTRAP_SUBDIRS="../../../lib"
do-top-obj: .PHONY .MAKE
${MAKEDIRTARGET} . obj NOSUBDIR=
do-tools-obj: .PHONY .MAKE
${MAKEDIRTARGET} tools obj
do-build: .PHONY .MAKE
.for targ in dependall install
${MAKEDIRTARGET} . ${targ} BUILD_tools=no BUILD_lib=no
.endfor
do-x11: .PHONY .MAKE
.if ${MKX11} != "no"
.if ${X11FLAVOUR} == "Xorg"
${MAKEDIRTARGET} external/mit/xorg build
.else
${MAKEDIRTARGET} x11 build
.endif
.else
@echo "MKX11 is not enabled"
@false
.endif
do-extsrc: .PHONY .MAKE
.if ${MKEXTSRC} != "no"
${MAKEDIRTARGET} extsrc build
.else
@echo "MKEXTSRC is not enabled"
@false
.endif
do-obsolete: .PHONY .MAKE
${MAKEDIRTARGET} etc install-obsolete-lists
#
# Speedup stubs for some subtrees that don't need to run these rules.
# (Tells <bsd.subdir.mk> not to recurse for them.)
#
.for dir in bin etc distrib games libexec regress sbin usr.bin usr.sbin tools
includes-${dir}: .PHONY
@true
.endfor
.for dir in etc distrib regress
install-${dir}: .PHONY
@true
.endfor
.if defined(__MINIX)
SRCTAR=src.tar.gz
do-installsrc:
cd ${.CURDIR} && git ls-tree -r HEAD --name-only | tar czf ${.OBJDIR}/$(SRCTAR) -T -
${INSTALL_FILE} ${.OBJDIR}/$(SRCTAR) ${DESTDIR}/usr/src/
.endif # defined(__MINIX)
#
# XXX this needs to change when distrib Makefiles are recursion compliant
# XXX many distrib subdirs need "cd etc && make snap_pre snap_kern" first...
#
dependall-distrib depend-distrib all-distrib: .PHONY
@true
.include <bsd.sys.mk>
.include <bsd.obj.mk>
.include <bsd.kernobj.mk>
.include <bsd.subdir.mk>
# Master Makefile to compile everything in /usr/src except the system.
MAKE = exec make -$(MAKEFLAGS)
usage:
@echo ""
@echo "Master Makefile for MINIX commands and utilities."
@echo "Root privileges are required for some actions."
@echo ""
@echo "Usage:"
@echo " make world # Compile everything (libraries & commands)"
@echo " make includes # Install include files from src/"
@echo " make libraries # Compile and install libraries"
@echo " make cmds # Compile all, commands, but don't install"
@echo " make install # Compile and install commands"
@echo " make depend # Generate required .depend files"
@echo " make clean # Remove all compiler results"
@echo ""
@echo "Run 'make' in tools/ to create a new MINIX configuration."
@echo ""
# world has to be able to make a new system, even if there
# is no complete old system. it has to install commands, for which
# it has to install libraries, for which it has to install includes,
# for which it has to install /etc (for users and ownerships).
# etcfiles also creates a directory hierarchy in its
# 'make install' target.
#
# etcfiles has to be done first.
world: includes depend libraries cmds install postinstall
includes:
cd include && $(MAKE) install gcc
libraries:
cd lib && $(MAKE) all install
cmds:
if [ -f commands/Makefile ] ; then cd commands && $(MAKE) all; fi
install::
if [ -f commands/Makefile ] ; then cd commands && $(MAKE) install; fi
depend::
mkdep kernel
mkdep servers
mkdep drivers
cd kernel && $(MAKE) $@
cd servers && $(MAKE) $@
cd drivers && $(MAKE) $@
clean::
cd lib && $(MAKE) $@
test ! -f commands/Makefile || { cd commands && $(MAKE) $@; }
etcfiles::
cd etc && $(MAKE) install
clean::
cd test && $(MAKE) $@
all install clean::
cd boot && $(MAKE) $@
cd man && $(MAKE) $@ # First manpages, then commands
test ! -f commands/Makefile || { cd commands && $(MAKE) $@; }
cd tools && $(MAKE) $@
cd servers && $(MAKE) $@
postinstall:
cd etc && $(MAKE) $@

View File

@@ -1,16 +0,0 @@
# $NetBSD: Makefile.inc,v 1.4 2002/04/10 14:53:43 lukem Exp $
.ifndef ABSTOP
ABSTOP!= cd ${.PARSEDIR}; pwd
.if (${.PARSEDIR} == ${.CURDIR})
RELTOP:= .
.else
RELTOP:= ${.PARSEDIR:S,^${.CURDIR},,}
.endif
# you can set BSD{SRC,OBJ}DIR in Makefile.local.inc
.if exists(${ABSTOP}/Makefile.local.inc)
.include "${ABSTOP}/Makefile.local.inc"
.endif
.endif

View File

@@ -1,8 +0,0 @@
# $NetBSD: Makefile,v 1.22 2007/12/31 15:31:24 ad Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
SUBDIR= cat chmod cp csh date dd df domainname echo ed expr hostname \
kill ksh ln ls mkdir mv pax pwd rcp rcmd rm rmdir sh \
sleep stty sync test
.include <bsd.subdir.mk>

View File

@@ -1,11 +0,0 @@
# $NetBSD: Makefile.inc,v 1.17 2012/03/21 05:47:53 matt Exp $
# @(#)Makefile.inc 8.1 (Berkeley) 5/31/93
.include <bsd.own.mk> # for MKDYNAMICROOT definition
WARNS?= 5
BINDIR?= /bin
.if (${MKDYNAMICROOT} == "no")
LDSTATIC?= -static
.endif

View File

@@ -1,6 +0,0 @@
# $NetBSD: Makefile,v 1.12 2003/05/18 07:57:31 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= cat
.include <bsd.prog.mk>

View File

@@ -1,218 +0,0 @@
.\" $NetBSD: cat.1,v 1.36 2012/11/10 18:41:10 wiz Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" 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. 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.
.\"
.\" @(#)cat.1 8.3 (Berkeley) 5/2/95
.\"
.Dd November 10, 2012
.Dt CAT 1
.Os
.Sh NAME
.Nm cat
.Nd concatenate and print files
.Sh SYNOPSIS
.Nm
.Op Fl beflnstuv
.Op Fl B Ar bsize
.Op Fl
.Op Ar
.Sh DESCRIPTION
The
.Nm
utility reads files sequentially, writing them to the standard output.
The
.Ar file
operands are processed in command line order.
A single dash represents the standard input,
and may appear multiple times in the
.Ar file
list.
If no
.Ar file
operands are given, standard input is read.
.Pp
The word
.Dq concatenate
is just a verbose synonym for
.Dq catenate .
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl B Ar bsize
Read with a buffer size of
.Ar bsize
bytes, instead of the default buffer size which is the blocksize of the
output file.
.It Fl b
Implies the
.Fl n
option, but doesn't number blank lines.
.It Fl e
Implies the
.Fl v
option, and displays a dollar sign
.Pq Ql \&$
at the end of each line
as well.
.It Fl f
Only attempt to display regular files.
.It Fl l
Set an exclusive advisory lock on the standard output file descriptor.
This lock is set using
.Xr fcntl 2
with the
.Dv F_SETLKW
command.
If the output file is already locked,
.Nm
will block until the lock is acquired.
.It Fl n
Number the output lines, starting at 1.
.It Fl s
Squeeze multiple adjacent empty lines, causing the output to be
single spaced.
.It Fl t
Implies the
.Fl v
option, and displays tab characters as
.Ql ^I
as well.
.It Fl u
The
.Fl u
option guarantees that the output is unbuffered.
.It Fl v
Displays non-printing characters so they are visible.
Control characters print as
.Ql ^X
for control-X; the delete
character (octal 0177) prints as
.Ql ^? .
Non-ascii characters (with the high bit set) are printed as
.Ql M-
(for meta) followed by the character for the low 7 bits.
.El
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success, and \*[Gt]0 if an error occurs.
.Sh EXAMPLES
The command:
.Bd -literal -offset indent
.Ic cat file1
.Ed
.Pp
will print the contents of
.Ar file1
to the standard output.
.Pp
The command:
.Bd -literal -offset indent
.Ic cat file1 file2 \*[Gt] file3
.Ed
.Pp
will sequentially print the contents of
.Ar file1
and
.Ar file2
to the file
.Ar file3 ,
truncating
.Ar file3
if it already exists.
See the manual page for your shell (e.g.,
.Xr sh 1 )
for more information on redirection.
.Pp
The command:
.Bd -literal -offset indent
.Ic cat file1 - file2 - file3
.Ed
.Pp
will print the contents of
.Ar file1 ,
print data it receives from the standard input until it receives an
.Dv EOF
.Pq Sq ^D
character, print the contents of
.Ar file2 ,
read and output contents of the standard input again, then finally output
the contents of
.Ar file3 .
Note that if the standard input referred to a file, the second dash
on the command-line would have no effect, since the entire contents of the file
would have already been read and printed by
.Nm
when it encountered the first
.Ql \&-
operand.
.Sh SEE ALSO
.Xr head 1 ,
.Xr hexdump 1 ,
.Xr lpr 1 ,
.Xr more 1 ,
.Xr pr 1 ,
.Xr tail 1 ,
.Xr view 1 ,
.Xr vis 1 ,
.Xr fcntl 2
.Rs
.%A Rob Pike
.%T "UNIX Style, or cat -v Considered Harmful"
.%J "USENIX Summer Conference Proceedings"
.%D 1983
.Re
.Sh STANDARDS
The
.Nm
utility is expected to conform to the
.St -p1003.2-92
specification.
.Pp
The flags
.Op Fl belnstv
are extensions to the specification.
.Sh HISTORY
A
.Nm
utility appeared in
.At v1 .
Dennis Ritchie designed and wrote the first man page.
It appears to have been
.Xr cat 1 .
.Sh BUGS
Because of the shell language mechanism used to perform output
redirection, the command
.Dq Li cat file1 file2 \*[Gt] file1
will cause the original data in file1 to be destroyed!
This is performed by the shell before
.Nm
is run.

View File

@@ -1,323 +0,0 @@
/* $NetBSD: cat.c,v 1.52 2012/11/19 19:41:31 christos Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kevin Fall.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if !defined(lint)
__COPYRIGHT(
"@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#if 0
static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
#else
__RCSID("$NetBSD: cat.c,v 1.52 2012/11/19 19:41:31 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag;
static size_t bsize;
static int rval;
static const char *filename;
void cook_args(char *argv[]);
void cook_buf(FILE *);
void raw_args(char *argv[]);
void raw_cat(int);
int
main(int argc, char *argv[])
{
int ch;
struct flock stdout_lock;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "B:beflnstuv")) != -1)
switch (ch) {
case 'B':
bsize = (size_t)strtol(optarg, NULL, 0);
break;
case 'b':
bflag = nflag = 1; /* -b implies -n */
break;
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
case 'f':
fflag = 1;
break;
case 'l':
lflag = 1;
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 't':
tflag = vflag = 1; /* -t implies -v */
break;
case 'u':
setbuf(stdout, NULL);
break;
case 'v':
vflag = 1;
break;
default:
case '?':
(void)fprintf(stderr,
"Usage: %s [-beflnstuv] [-B bsize] [-] "
"[file ...]\n", getprogname());
return EXIT_FAILURE;
}
argv += optind;
if (lflag) {
stdout_lock.l_len = 0;
stdout_lock.l_start = 0;
stdout_lock.l_type = F_WRLCK;
stdout_lock.l_whence = SEEK_SET;
if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
err(EXIT_FAILURE, "stdout");
}
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
else
raw_args(argv);
if (fclose(stdout))
err(EXIT_FAILURE, "stdout");
return rval;
}
void
cook_args(char **argv)
{
FILE *fp;
fp = stdin;
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fp = stdin;
else if ((fp = fopen(*argv,
fflag ? "rf" : "r")) == NULL) {
warn("%s", *argv);
rval = EXIT_FAILURE;
++argv;
continue;
}
filename = *argv++;
}
cook_buf(fp);
if (fp != stdin)
(void)fclose(fp);
else
clearerr(fp);
} while (*argv);
}
void
cook_buf(FILE *fp)
{
int ch, gobble, line, prev;
line = gobble = 0;
for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (ch == '\n') {
if (sflag) {
if (!gobble && nflag && !bflag)
(void)fprintf(stdout,
"%6d\t\n", ++line);
else if (!gobble && putchar(ch) == EOF)
break;
gobble = 1;
continue;
}
if (nflag) {
if (!bflag) {
(void)fprintf(stdout,
"%6d\t", ++line);
if (ferror(stdout))
break;
} else if (eflag) {
(void)fprintf(stdout,
"%6s\t", "");
if (ferror(stdout))
break;
}
}
} else if (nflag) {
(void)fprintf(stdout, "%6d\t", ++line);
if (ferror(stdout))
break;
}
}
gobble = 0;
if (ch == '\n') {
if (eflag)
if (putchar('$') == EOF)
break;
} else if (ch == '\t') {
if (tflag) {
if (putchar('^') == EOF || putchar('I') == EOF)
break;
continue;
}
} else if (vflag) {
if (!isascii(ch)) {
if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}
if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}
}
if (putchar(ch) == EOF)
break;
}
if (ferror(fp)) {
warn("%s", filename);
rval = EXIT_FAILURE;
clearerr(fp);
}
if (ferror(stdout))
err(EXIT_FAILURE, "stdout");
}
void
raw_args(char **argv)
{
int fd;
fd = fileno(stdin);
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fd = fileno(stdin);
else if (fflag) {
struct stat st;
fd = open(*argv, O_RDONLY|O_NONBLOCK, 0);
if (fd < 0)
goto skip;
if (fstat(fd, &st) == -1) {
close(fd);
goto skip;
}
if (!S_ISREG(st.st_mode)) {
close(fd);
warnx("%s: not a regular file", *argv);
goto skipnomsg;
}
}
else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
skip:
warn("%s", *argv);
skipnomsg:
rval = EXIT_FAILURE;
++argv;
continue;
}
filename = *argv++;
}
raw_cat(fd);
if (fd != fileno(stdin))
(void)close(fd);
} while (*argv);
}
void
raw_cat(int rfd)
{
static char *buf;
static char fb_buf[BUFSIZ];
ssize_t nr, nw, off;
int wfd;
wfd = fileno(stdout);
if (buf == NULL) {
struct stat sbuf;
if (bsize == 0) {
if (fstat(wfd, &sbuf) == 0 && sbuf.st_blksize > 0 &&
(size_t)sbuf.st_blksize > sizeof(fb_buf))
bsize = sbuf.st_blksize;
}
if (bsize > sizeof(fb_buf)) {
buf = malloc(bsize);
if (buf == NULL)
warnx("malloc, using %zu buffer", bsize);
}
if (buf == NULL) {
bsize = sizeof(fb_buf);
buf = fb_buf;
}
}
while ((nr = read(rfd, buf, bsize)) > 0)
for (off = 0; nr; nr -= nw, off += nw)
if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
err(EXIT_FAILURE, "stdout");
if (nr < 0) {
warn("%s", filename);
rval = EXIT_FAILURE;
}
}

View File

@@ -1,6 +0,0 @@
# $NetBSD: Makefile,v 1.8 1997/07/20 22:36:34 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= chmod
.include <bsd.prog.mk>

View File

@@ -1,307 +0,0 @@
.\" $NetBSD: chmod.1,v 1.24 2012/10/22 17:47:06 christos Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" 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. 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.
.\"
.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
.\"
.Dd October 22, 2012
.Dt CHMOD 1
.Os
.Sh NAME
.Nm chmod
.Nd change file modes
.Sh SYNOPSIS
.Nm
.Oo
.Fl R
.Op Fl H | Fl L | Fl P
.Oc
.Op Fl fh
.Ar mode
.Ar
.Nm
.Oo
.Fl R
.Op Fl H | Fl L | Fl P
.Oc
.Op Fl fh
.Fl Fl reference=rfile
.Ar
.Sh DESCRIPTION
The
.Nm
utility modifies the file mode bits of the listed files
as specified by the
.Ar mode
operand, or
copied from a reference
.Ar rfile ,
as specified with the
.Fl Fl reference
argument.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl H
If the
.Fl R
option is specified, symbolic links on the command line are followed.
(Symbolic links encountered in the tree traversal are not followed.)
.It Fl L
If the
.Fl R
option is specified, all symbolic links are followed.
.It Fl P
If the
.Fl R
option is specified, no symbolic links are followed.
.It Fl R
Change the modes of the file hierarchies rooted in the files
instead of just the files themselves.
.It Fl f
Do not display a diagnostic message or modify the exit status if
.Nm
fails to change the mode of a file.
.It Fl h
If
.Ar file
is symbolic link, the mode of the link is changed.
.El
.Pp
The
.Fl H ,
.Fl L
and
.Fl P
options are ignored unless the
.Fl R
option is specified.
In addition, these options override each other and the
command's actions are determined by the last one specified.
.Pp
Only the owner of a file or the super-user is permitted to change
the mode of a file.
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success, and \*[Gt]0 if an error occurs.
.Sh MODES
Modes may be absolute or symbolic.
An absolute mode is an octal number constructed by
.Em or Ap ing
the following values:
.Pp
.Bl -tag -width 6n -compact -offset indent
.It Li 4000
set-user-ID-on-execution
.It Li 2000
set-group-ID-on-execution
.It Li 1000
sticky bit, see
.Xr chmod 2
.It Li 0400
read by owner
.It Li 0200
write by owner
.It Li 0100
execute (or search for directories) by owner
.It Li 0070
read, write, execute/search by group
.It Li 0007
read, write, execute/search by others
.El
.Pp
The read, write, and execute/search values for group and others
are encoded as described for owner.
.Pp
The symbolic mode is described by the following grammar:
.Bd -literal -offset indent
mode ::= clause [, clause ...]
clause ::= [who ...] [action ...] last_action
action ::= op [perm ...]
last_action ::= op [perm ...]
who ::= a | u | g | o
op ::= + | \- | =
perm ::= r | s | t | w | x | X | u | g | o
.Ed
.Pp
The
.Ar who
symbols ``u'', ``g'', and ``o'' specify the user, group, and other parts
of the mode bits, respectively.
The
.Ar who
symbol ``a'' is equivalent to ``ugo''.
.Pp
The
.Ar perm
symbols represent the portions of the mode bits as follows:
.Pp
.Bl -tag -width Ds -compact -offset indent
.It r
The read bits.
.It s
The set-user-ID-on-execution and set-group-ID-on-execution bits.
.It t
The sticky bit.
.It w
The write bits.
.It x
The execute/search bits.
.It X
The execute/search bits if the file is a directory or any of the
execute/search bits are set in the original (unmodified) mode.
Operations with the
.Ar perm
symbol ``X'' are only meaningful in conjunction with the
.Ar op
symbol ``+'', and are ignored in all other cases.
.It u
The user permission bits in the mode of the original file.
.It g
The group permission bits in the mode of the original file.
.It o
The other permission bits in the mode of the original file.
.El
.Pp
The
.Ar op
symbols represent the operation performed, as follows:
.Bl -tag -width 4n
.It +
If no value is supplied for
.Ar perm ,
the ``+'' operation has no effect.
If no value is supplied for
.Ar who ,
each permission bit specified in
.Ar perm ,
for which the corresponding bit in the file mode creation mask
is clear, is set.
Otherwise, the mode bits represented by the specified
.Ar who
and
.Ar perm
values are set.
.It \&\-
If no value is supplied for
.Ar perm ,
the ``\-'' operation has no effect.
If no value is supplied for
.Ar who ,
each permission bit specified in
.Ar perm ,
for which the corresponding bit in the file mode creation mask
is clear, is cleared.
Otherwise, the mode bits represented by the specified
.Ar who
and
.Ar perm
values are cleared.
.It =
The mode bits specified by the
.Ar who
value are cleared, or, if no who value is specified, the owner, group
and other mode bits are cleared.
Then, if no value is supplied for
.Ar who ,
each permission bit specified in
.Ar perm ,
for which the corresponding bit in the file mode creation mask
is clear, is set.
Otherwise, the mode bits represented by the specified
.Ar who
and
.Ar perm
values are set.
.El
.Pp
Each
.Ar clause
specifies one or more operations to be performed on the mode
bits, and each operation is applied to the mode bits in the
order specified.
.Pp
Operations upon the other permissions only (specified by the symbol
``o'' by itself), in combination with the
.Ar perm
symbols ``s'' or ``t'', are ignored.
.Sh EXAMPLES
.Bl -tag -width "u=rwx,go=u-w" -compact
.It Li 644
make a file readable by anyone and writable by the owner only.
.Pp
.It Li go-w
deny write permission to group and others.
.Pp
.It Li =rw,+X
set the read and write permissions to the usual defaults, but
retain any execute permissions that are currently set.
.Pp
.It Li +X
make a directory or file searchable/executable by everyone if it is
already searchable/executable by anyone.
.Pp
.It Li 755
.It Li u=rwx,go=rx
.It Li u=rwx,go=u-w
make a file readable/executable by everyone and writable by the owner only.
.Pp
.It Li go=
clear all mode bits for group and others.
.Pp
.It Li g=u-w
set the group bits equal to the user bits, but clear the group write bit.
.El
.Sh SEE ALSO
.Xr chflags 1 ,
.Xr install 1 ,
.Xr chmod 2 ,
.Xr stat 2 ,
.Xr umask 2 ,
.Xr fts 3 ,
.Xr setmode 3 ,
.Xr symlink 7 ,
.Xr chown 8
.Sh STANDARDS
The
.Nm
utility is expected to be
.St -p1003.2-92
compatible with the exception of the
.Ar perm
symbol
.Dq t
which is not included in that standard.
.Sh BUGS
There's no
.Ar perm
option for the naughty bits.

View File

@@ -1,239 +0,0 @@
/* $NetBSD: chmod.c,v 1.38 2012/10/22 18:00:46 christos Exp $ */
/*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1989, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94";
#else
__RCSID("$NetBSD: chmod.c,v 1.38 2012/10/22 18:00:46 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <fts.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
__dead static void usage(void);
struct option chmod_longopts[] = {
{ "reference", required_argument, 0,
1 },
{ NULL, 0, 0,
0 },
};
int
main(int argc, char *argv[])
{
FTS *ftsp;
FTSENT *p;
void *set;
mode_t mval;
int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval;
char *mode, *reference;
int (*change_mode)(const char *, mode_t);
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
Hflag = Lflag = Rflag = fflag = hflag = 0;
reference = NULL;
while ((ch = getopt_long(argc, argv, "HLPRXfghorstuwx",
chmod_longopts, NULL)) != -1)
switch (ch) {
case 1:
reference = optarg;
break;
case 'H':
Hflag = 1;
Lflag = 0;
break;
case 'L':
Lflag = 1;
Hflag = 0;
break;
case 'P':
Hflag = Lflag = 0;
break;
case 'R':
Rflag = 1;
break;
case 'f':
fflag = 1;
break;
case 'h':
/*
* In System V the -h option causes chmod to
* change the mode of the symbolic link.
* 4.4BSD's symbolic links didn't have modes,
* so it was an undocumented noop. In NetBSD
* 1.3, lchmod(2) is introduced and this
* option does real work.
*/
hflag = 1;
break;
/*
* XXX
* "-[rwx]" are valid mode commands. If they are the entire
* argument, getopt has moved past them, so decrement optind.
* Regardless, we're done argument processing.
*/
case 'g': case 'o': case 'r': case 's':
case 't': case 'u': case 'w': case 'X': case 'x':
if (argv[optind - 1][0] == '-' &&
argv[optind - 1][1] == ch &&
argv[optind - 1][2] == '\0')
--optind;
goto done;
case '?':
default:
usage();
}
done: argv += optind;
argc -= optind;
if (argc == 0 || (argc == 1 && reference == NULL))
usage();
fts_options = FTS_PHYSICAL;
if (Rflag) {
if (hflag) {
errx(EXIT_FAILURE,
"the -R and -h options may not be specified together.");
/* NOTREACHED */
}
if (Hflag)
fts_options |= FTS_COMFOLLOW;
if (Lflag) {
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
}
} else if (!hflag)
fts_options |= FTS_COMFOLLOW;
if (hflag)
change_mode = lchmod;
else
change_mode = chmod;
if (reference == NULL) {
mode = *argv++;
if ((set = setmode(mode)) == NULL) {
err(EXIT_FAILURE, "Cannot set file mode `%s'", mode);
/* NOTREACHED */
}
mval = 0;
} else {
struct stat st;
if (stat(reference, &st) == -1)
err(EXIT_FAILURE, "Cannot stat `%s'", reference);
mval = st.st_mode;
set = NULL;
}
if ((ftsp = fts_open(argv, fts_options, 0)) == NULL) {
err(EXIT_FAILURE, "fts_open");
/* NOTREACHED */
}
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
switch (p->fts_info) {
case FTS_D:
if (!Rflag)
(void)fts_set(ftsp, p, FTS_SKIP);
break;
case FTS_DNR: /* Warn, chmod, continue. */
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
rval = 1;
break;
case FTS_DP: /* Already changed at FTS_D. */
continue;
case FTS_ERR: /* Warn, continue. */
case FTS_NS:
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
rval = 1;
continue;
case FTS_SL: /* Ignore. */
case FTS_SLNONE:
/*
* The only symlinks that end up here are ones that
* don't point to anything and ones that we found
* doing a physical walk.
*/
if (!hflag)
continue;
/* else */
/* FALLTHROUGH */
default:
break;
}
if ((*change_mode)(p->fts_accpath,
set ? getmode(set, p->fts_statp->st_mode) : mval)
&& !fflag) {
warn("%s", p->fts_path);
rval = 1;
}
}
if (errno) {
err(EXIT_FAILURE, "fts_read");
/* NOTREACHED */
}
exit(rval);
/* NOTREACHED */
}
static void
usage(void)
{
(void)fprintf(stderr,
"Usage: %s [-R [-H | -L | -P]] [-fh] mode file ...\n"
"\t%s [-R [-H | -L | -P]] [-fh] --reference=rfile file ...\n",
getprogname(), getprogname());
exit(1);
/* NOTREACHED */
}

View File

@@ -1,7 +0,0 @@
# $NetBSD: Makefile,v 1.9 1997/07/20 22:36:37 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= cp
SRCS= cp.c utils.c
.include <bsd.prog.mk>

View File

@@ -1,254 +0,0 @@
.\" $NetBSD: cp.1,v 1.42 2012/03/25 22:37:08 wiz Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" 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. 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.
.\"
.\" @(#)cp.1 8.3 (Berkeley) 4/18/94
.\"
.Dd March 25, 2012
.Dt CP 1
.Os
.Sh NAME
.Nm cp
.Nd copy files
.Sh SYNOPSIS
.Nm
.Oo
.Fl R
.Op Fl H | Fl L | Fl P
.Oc
.Op Fl f | i
.Op Fl alNpv
.Ar source_file target_file
.Nm cp
.Oo
.Fl R
.Op Fl H | Fl L | Fl P
.Oc
.Op Fl f | i
.Op Fl alNpv
.Ar source_file ... target_directory
.Sh DESCRIPTION
In the first synopsis form, the
.Nm
utility copies the contents of the
.Ar source_file
to the
.Ar target_file .
In the second synopsis form,
the contents of each named
.Ar source_file
is copied to the destination
.Ar target_directory .
The names of the files themselves are not changed.
If
.Nm
detects an attempt to copy a file to itself, the copy will fail.
.Pp
The following options are available:
.Bl -tag -width flag
.It Fl a
Archive mode.
Same as
.Fl RpP .
.It Fl f
For each existing destination pathname, attempt to overwrite it.
If permissions do not allow copy to succeed, remove it and create a new
file, without prompting for confirmation.
(The
.Fl i
option is ignored if the
.Fl f
option is specified.)
.It Fl H
If the
.Fl R
option is specified, symbolic links on the command line are followed.
(Symbolic links encountered in the tree traversal are not followed.)
.It Fl i
Causes
.Nm
to write a prompt to the standard error output before copying a file
that would overwrite an existing file.
If the response from the standard input begins with the character
.Sq Li y ,
the file copy is attempted.
.It Fl L
If the
.Fl R
option is specified, all symbolic links are followed.
.It Fl l
Create hard links to regular files in a hierarchy instead of copying.
.It Fl N
When used with
.Fl p ,
don't copy file flags.
.It Fl P
No symbolic links are followed.
This is the default.
.It Fl p
Causes
.Nm
to preserve in the copy as many of the modification time, access time,
file flags, file mode, user ID, group ID, and extended attributes,
as allowed by permissions.
.Pp
If the user ID and group ID cannot be preserved, no error message
is displayed and the exit value is not altered.
.Pp
If the source file has its set user ID bit on and the user ID cannot
be preserved, the set user ID bit is not preserved
in the copy's permissions.
If the source file has its set group ID bit on and the group ID cannot
be preserved, the set group ID bit is not preserved
in the copy's permissions.
If the source file has both its set user ID and set group ID bits on,
and either the user ID or group ID cannot be preserved, neither
the set user ID or set group ID bits are preserved in the copy's
permissions.
.Pp
Extended attributes from all accessible namespaces are copied;
others are ignored.
If an error occurs during this copy, a message is displayed and
.Nm
skips the other extended attributes for that file.
.It Fl R
If
.Ar source_file
designates a directory,
.Nm
copies the directory and the entire subtree connected at that point.
This option also causes symbolic links to be copied, rather than
followed, and for
.Nm
to create special files rather than copying them as normal files.
Created directories have the same mode as the corresponding source
directory, unmodified by the process's umask.
.Pp
Note that
.Nm
copies hard linked files as separate files.
If you need to preserve hard links, consider using a utility like
.Xr pax 1
instead.
.It Fl v
Causes
.Nm
to be verbose, showing files as they are copied.
.El
.Pp
For each destination file that already exists, its contents are
overwritten if permissions allow, but its mode, user ID, and group
ID are unchanged.
.Pp
In the second synopsis form,
.Ar target_directory
must exist unless there is only one named
.Ar source_file
which is a directory and the
.Fl R
flag is specified.
.Pp
If the destination file does not exist, the mode of the source file is
used as modified by the file mode creation mask
.Ic ( umask ,
see
.Xr csh 1 ) .
If the source file has its set user ID bit on, that bit is removed
unless both the source file and the destination file are owned by the
same user.
If the source file has its set group ID bit on, that bit is removed
unless both the source file and the destination file are in the same
group and the user is a member of that group.
If both the set user ID and set group ID bits are set, all of the above
conditions must be fulfilled or both bits are removed.
.Pp
Appropriate permissions are required for file creation or overwriting.
.Pp
Symbolic links are always followed unless the
.Fl R
flag is set, in which case symbolic links are not followed, by default.
The
.Fl H
or
.Fl L
flags (in conjunction with the
.Fl R
flag), as well as the
.Fl P
flag cause symbolic links to be followed as described above.
The
.Fl H
and
.Fl L
options are ignored unless the
.Fl R
option is specified.
In addition, these options override each other and the
command's actions are determined by the last one specified.
.Sh EXIT STATUS
.Ex -std cp
.Sh COMPATIBILITY
Historic versions of the
.Nm
utility had a
.Fl r
option.
This implementation supports that option, however, its use is strongly
discouraged, as it does not correctly copy special files, symbolic links
or fifo's.
.Sh SEE ALSO
.Xr mv 1 ,
.Xr pax 1 ,
.Xr rcp 1 ,
.Xr umask 2 ,
.Xr fts 3 ,
.Xr symlink 7
.Sh STANDARDS
The
.Nm
utility is expected to be
.St -p1003.2
compatible.
.Pp
The
.Fl a
and
.Fl l
flags are non-standard extensions.
They are intended to be compatible with the same options which
other implementations, namely GNU coreutils and
.Fx ,
of this utility have.
.Pp
The
.Fl v
option is an extension to
.St -p1003.2 .

View File

@@ -1,548 +0,0 @@
/* $NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $ */
/*
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* David Hitz of Auspex Systems Inc.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1988, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95";
#else
__RCSID("$NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $");
#endif
#endif /* not lint */
/*
* Cp copies source files to target files.
*
* The global PATH_T structure "to" always contains the path to the
* current target file. Since fts(3) does not change directories,
* this path can be either absolute or dot-relative.
*
* The basic algorithm is to initialize "to" and use fts(3) to traverse
* the file hierarchy rooted in the argument list. A trivial case is the
* case of 'cp file1 file2'. The more interesting case is the case of
* 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
* path (relative to the root of the traversal) is appended to dir (stored
* in "to") to form the final target path.
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fts.h>
#include <locale.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define STRIP_TRAILING_SLASH(p) { \
while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \
*--(p).p_end = '\0'; \
}
static char empty[] = "";
PATH_T to = { .p_end = to.p_path, .target_end = empty };
uid_t myuid;
int Hflag, Lflag, Rflag, Pflag, fflag, iflag, lflag, pflag, rflag, vflag, Nflag;
mode_t myumask;
sig_atomic_t pinfo;
enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
static int copy(char *[], enum op, int);
static void
progress(int sig __unused)
{
pinfo++;
}
int
main(int argc, char *argv[])
{
struct stat to_stat, tmp_stat;
enum op type;
int ch, fts_options, r, have_trailing_slash;
char *target, **src;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
Hflag = Lflag = Pflag = Rflag = 0;
while ((ch = getopt(argc, argv, "HLNPRfailprv")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
Lflag = Pflag = 0;
break;
case 'L':
Lflag = 1;
Hflag = Pflag = 0;
break;
case 'N':
Nflag = 1;
break;
case 'P':
Pflag = 1;
Hflag = Lflag = 0;
break;
case 'R':
Rflag = 1;
break;
case 'a':
Pflag = 1;
pflag = 1;
Rflag = 1;
Hflag = Lflag = 0;
break;
case 'f':
fflag = 1;
iflag = 0;
break;
case 'i':
iflag = isatty(fileno(stdin));
fflag = 0;
break;
case 'l':
lflag = 1;
break;
case 'p':
pflag = 1;
break;
case 'r':
rflag = 1;
break;
case 'v':
vflag = 1;
break;
case '?':
default:
usage();
/* NOTREACHED */
}
argc -= optind;
argv += optind;
if (argc < 2)
usage();
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
if (rflag) {
if (Rflag) {
errx(EXIT_FAILURE,
"the -R and -r options may not be specified together.");
/* NOTREACHED */
}
if (Hflag || Lflag || Pflag) {
errx(EXIT_FAILURE,
"the -H, -L, and -P options may not be specified with the -r option.");
/* NOTREACHED */
}
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
}
if (Rflag) {
if (Hflag)
fts_options |= FTS_COMFOLLOW;
if (Lflag) {
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
}
} else if (!Pflag) {
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
}
myuid = getuid();
/* Copy the umask for explicit mode setting. */
myumask = umask(0);
(void)umask(myumask);
/* Save the target base in "to". */
target = argv[--argc];
if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path))
errx(EXIT_FAILURE, "%s: name too long", target);
to.p_end = to.p_path + strlen(to.p_path);
have_trailing_slash = (to.p_end[-1] == '/');
if (have_trailing_slash)
STRIP_TRAILING_SLASH(to);
to.target_end = to.p_end;
/* Set end of argument list for fts(3). */
argv[argc] = NULL;
(void)signal(SIGINFO, progress);
/*
* Cp has two distinct cases:
*
* cp [-R] source target
* cp [-R] source1 ... sourceN directory
*
* In both cases, source can be either a file or a directory.
*
* In (1), the target becomes a copy of the source. That is, if the
* source is a file, the target will be a file, and likewise for
* directories.
*
* In (2), the real target is not directory, but "directory/source".
*/
if (Pflag)
r = lstat(to.p_path, &to_stat);
else
r = stat(to.p_path, &to_stat);
if (r == -1 && errno != ENOENT) {
err(EXIT_FAILURE, "%s", to.p_path);
/* NOTREACHED */
}
if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
/*
* Case (1). Target is not a directory.
*/
if (argc > 1)
usage();
/*
* Need to detect the case:
* cp -R dir foo
* Where dir is a directory and foo does not exist, where
* we want pathname concatenations turned on but not for
* the initial mkdir().
*/
if (r == -1) {
if (rflag || (Rflag && (Lflag || Hflag)))
r = stat(*argv, &tmp_stat);
else
r = lstat(*argv, &tmp_stat);
if (r == -1) {
err(EXIT_FAILURE, "%s", *argv);
/* NOTREACHED */
}
if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
type = DIR_TO_DNE;
else
type = FILE_TO_FILE;
} else
type = FILE_TO_FILE;
if (have_trailing_slash && type == FILE_TO_FILE) {
if (r == -1)
errx(1, "directory %s does not exist",
to.p_path);
else
errx(1, "%s is not a directory", to.p_path);
}
} else {
/*
* Case (2). Target is a directory.
*/
type = FILE_TO_DIR;
}
/*
* make "cp -rp src/ dst" behave like "cp -rp src dst" not
* like "cp -rp src/. dst"
*/
for (src = argv; *src; src++) {
size_t len = strlen(*src);
while (len-- > 1 && (*src)[len] == '/')
(*src)[len] = '\0';
}
exit(copy(argv, type, fts_options));
/* NOTREACHED */
}
static int dnestack[MAXPATHLEN]; /* unlikely we'll have more nested dirs */
static ssize_t dnesp;
static void
pushdne(int dne)
{
dnestack[dnesp++] = dne;
assert(dnesp < MAXPATHLEN);
}
static int
popdne(void)
{
int rv;
rv = dnestack[--dnesp];
assert(dnesp >= 0);
return rv;
}
static int
copy(char *argv[], enum op type, int fts_options)
{
struct stat to_stat;
FTS *ftsp;
FTSENT *curr;
int base, dne, sval;
int this_failed, any_failed;
size_t nlen;
char *p, *target_mid;
base = 0; /* XXX gcc -Wuninitialized (see comment below) */
if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL)
err(EXIT_FAILURE, "%s", argv[0]);
/* NOTREACHED */
for (any_failed = 0; (curr = fts_read(ftsp)) != NULL;) {
this_failed = 0;
switch (curr->fts_info) {
case FTS_NS:
case FTS_DNR:
case FTS_ERR:
warnx("%s: %s", curr->fts_path,
strerror(curr->fts_errno));
this_failed = any_failed = 1;
continue;
case FTS_DC: /* Warn, continue. */
warnx("%s: directory causes a cycle", curr->fts_path);
this_failed = any_failed = 1;
continue;
}
/*
* If we are in case (2) or (3) above, we need to append the
* source name to the target name.
*/
if (type != FILE_TO_FILE) {
if ((curr->fts_namelen +
to.target_end - to.p_path + 1) > MAXPATHLEN) {
warnx("%s/%s: name too long (not copied)",
to.p_path, curr->fts_name);
this_failed = any_failed = 1;
continue;
}
/*
* Need to remember the roots of traversals to create
* correct pathnames. If there's a directory being
* copied to a non-existent directory, e.g.
* cp -R a/dir noexist
* the resulting path name should be noexist/foo, not
* noexist/dir/foo (where foo is a file in dir), which
* is the case where the target exists.
*
* Also, check for "..". This is for correct path
* concatentation for paths ending in "..", e.g.
* cp -R .. /tmp
* Paths ending in ".." are changed to ".". This is
* tricky, but seems the easiest way to fix the problem.
*
* XXX
* Since the first level MUST be FTS_ROOTLEVEL, base
* is always initialized.
*/
if (curr->fts_level == FTS_ROOTLEVEL) {
if (type != DIR_TO_DNE) {
p = strrchr(curr->fts_path, '/');
base = (p == NULL) ? 0 :
(int)(p - curr->fts_path + 1);
if (!strcmp(&curr->fts_path[base],
".."))
base += 1;
} else
base = curr->fts_pathlen;
}
p = &curr->fts_path[base];
nlen = curr->fts_pathlen - base;
target_mid = to.target_end;
if (*p != '/' && target_mid[-1] != '/')
*target_mid++ = '/';
*target_mid = 0;
if (target_mid - to.p_path + nlen >= PATH_MAX) {
warnx("%s%s: name too long (not copied)",
to.p_path, p);
this_failed = any_failed = 1;
continue;
}
(void)strncat(target_mid, p, nlen);
to.p_end = target_mid + nlen;
*to.p_end = 0;
STRIP_TRAILING_SLASH(to);
}
sval = Pflag ? lstat(to.p_path, &to_stat) : stat(to.p_path, &to_stat);
/* Not an error but need to remember it happened */
if (sval == -1)
dne = 1;
else {
if (to_stat.st_dev == curr->fts_statp->st_dev &&
to_stat.st_ino == curr->fts_statp->st_ino) {
warnx("%s and %s are identical (not copied).",
to.p_path, curr->fts_path);
this_failed = any_failed = 1;
if (S_ISDIR(curr->fts_statp->st_mode))
(void)fts_set(ftsp, curr, FTS_SKIP);
continue;
}
if (!S_ISDIR(curr->fts_statp->st_mode) &&
S_ISDIR(to_stat.st_mode)) {
warnx("cannot overwrite directory %s with non-directory %s",
to.p_path, curr->fts_path);
this_failed = any_failed = 1;
continue;
}
dne = 0;
}
switch (curr->fts_statp->st_mode & S_IFMT) {
case S_IFLNK:
/* Catch special case of a non dangling symlink */
if((fts_options & FTS_LOGICAL) ||
((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) {
if (copy_file(curr, dne))
this_failed = any_failed = 1;
} else {
if (copy_link(curr, !dne))
this_failed = any_failed = 1;
}
break;
case S_IFDIR:
if (!Rflag && !rflag) {
if (curr->fts_info == FTS_D)
warnx("%s is a directory (not copied).",
curr->fts_path);
(void)fts_set(ftsp, curr, FTS_SKIP);
this_failed = any_failed = 1;
break;
}
/*
* Directories get noticed twice:
* In the first pass, create it if needed.
* In the second pass, after the children have been copied, set the permissions.
*/
if (curr->fts_info == FTS_D) /* First pass */
{
/*
* If the directory doesn't exist, create the new
* one with the from file mode plus owner RWX bits,
* modified by the umask. Trade-off between being
* able to write the directory (if from directory is
* 555) and not causing a permissions race. If the
* umask blocks owner writes, we fail..
*/
pushdne(dne);
if (dne) {
if (mkdir(to.p_path,
curr->fts_statp->st_mode | S_IRWXU) < 0)
err(EXIT_FAILURE, "%s",
to.p_path);
/* NOTREACHED */
} else if (!S_ISDIR(to_stat.st_mode)) {
errno = ENOTDIR;
err(EXIT_FAILURE, "%s",
to.p_path);
/* NOTREACHED */
}
}
else if (curr->fts_info == FTS_DP) /* Second pass */
{
/*
* If not -p and directory didn't exist, set it to be
* the same as the from directory, umodified by the
* umask; arguably wrong, but it's been that way
* forever.
*/
if (pflag && setfile(curr->fts_statp, 0))
this_failed = any_failed = 1;
else if ((dne = popdne()))
(void)chmod(to.p_path,
curr->fts_statp->st_mode);
}
else
{
warnx("directory %s encountered when not expected.",
curr->fts_path);
this_failed = any_failed = 1;
break;
}
break;
case S_IFBLK:
case S_IFCHR:
if (Rflag) {
if (copy_special(curr->fts_statp, !dne))
this_failed = any_failed = 1;
} else
if (copy_file(curr, dne))
this_failed = any_failed = 1;
break;
case S_IFIFO:
if (Rflag) {
if (copy_fifo(curr->fts_statp, !dne))
this_failed = any_failed = 1;
} else
if (copy_file(curr, dne))
this_failed = any_failed = 1;
break;
default:
if (copy_file(curr, dne))
this_failed = any_failed = 1;
break;
}
if (vflag && !this_failed)
(void)printf("%s -> %s\n", curr->fts_path, to.p_path);
}
if (errno) {
err(EXIT_FAILURE, "fts_read");
/* NOTREACHED */
}
(void)fts_close(ftsp);
return (any_failed);
}

View File

@@ -1,61 +0,0 @@
/* $NetBSD: extern.h,v 1.17 2012/01/04 15:58:37 christos Exp $ */
/*-
* Copyright (c) 1991, 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. 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.
*
* @(#)extern.h 8.2 (Berkeley) 4/1/94
*/
#ifndef _EXTERN_H_
#define _EXTERN_H_
typedef struct {
char *p_end; /* pointer to NULL at end of path */
char *target_end; /* pointer to end of target base */
char p_path[MAXPATHLEN + 1]; /* pointer to the start of a path */
} PATH_T;
extern PATH_T to;
extern uid_t myuid;
extern int Rflag, rflag, Hflag, Lflag, Pflag, fflag, iflag, lflag, pflag, Nflag;
extern mode_t myumask;
extern sig_atomic_t pinfo;
#include <sys/cdefs.h>
__BEGIN_DECLS
int copy_fifo(struct stat *, int);
int copy_file(FTSENT *, int);
int copy_link(FTSENT *, int);
int copy_special(struct stat *, int);
int set_utimes(const char *, struct stat *);
int setfile(struct stat *, int);
void usage(void) __attribute__((__noreturn__));
__END_DECLS
#endif /* !_EXTERN_H_ */

View File

@@ -1,429 +0,0 @@
/* $NetBSD: utils.c,v 1.41 2012/01/04 15:58:37 christos Exp $ */
/*-
* Copyright (c) 1991, 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
#else
__RCSID("$NetBSD: utils.c,v 1.41 2012/01/04 15:58:37 christos Exp $");
#endif
#endif /* not lint */
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/extattr.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define MMAP_MAX_SIZE (8 * 1048576)
#define MMAP_MAX_WRITE (64 * 1024)
int
set_utimes(const char *file, struct stat *fs)
{
static struct timeval tv[2];
TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
if (lutimes(file, tv)) {
warn("lutimes: %s", file);
return (1);
}
return (0);
}
struct finfo {
const char *from;
const char *to;
size_t size;
};
static void
progress(const struct finfo *fi, size_t written)
{
int pcent = (int)((100.0 * written) / fi->size);
pinfo = 0;
(void)fprintf(stderr, "%s => %s %zu/%zu bytes %d%% written\n",
fi->from, fi->to, written, fi->size, pcent);
}
int
copy_file(FTSENT *entp, int dne)
{
static char buf[MAXBSIZE];
struct stat to_stat, *fs;
int ch, checkch, from_fd, rcount, rval, to_fd, tolnk, wcount;
char *p;
size_t ptotal = 0;
if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
warn("%s", entp->fts_path);
return (1);
}
to_fd = -1;
fs = entp->fts_statp;
tolnk = ((Rflag && !(Lflag || Hflag)) || Pflag);
/*
* If the file exists and we're interactive, verify with the user.
* If the file DNE, set the mode to be the from file, minus setuid
* bits, modified by the umask; arguably wrong, but it makes copying
* executables work right and it's been that way forever. (The
* other choice is 666 or'ed with the execute bits on the from file
* modified by the umask.)
*/
if (!dne) {
struct stat sb;
int sval;
if (iflag) {
(void)fprintf(stderr, "overwrite %s? ", to.p_path);
checkch = ch = getchar();
while (ch != '\n' && ch != EOF)
ch = getchar();
if (checkch != 'y' && checkch != 'Y') {
(void)close(from_fd);
return (0);
}
}
sval = tolnk ?
lstat(to.p_path, &sb) : stat(to.p_path, &sb);
if (sval == -1) {
warn("stat: %s", to.p_path);
(void)close(from_fd);
return (1);
}
if (!(tolnk && S_ISLNK(sb.st_mode)))
to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
} else
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
fs->st_mode & ~(S_ISUID | S_ISGID));
if (to_fd == -1 && (fflag || tolnk)) {
/*
* attempt to remove existing destination file name and
* create a new file
*/
(void)unlink(to.p_path);
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
fs->st_mode & ~(S_ISUID | S_ISGID));
}
if (to_fd == -1) {
warn("%s", to.p_path);
(void)close(from_fd);
return (1);
}
rval = 0;
/* if hard linking then simply close the open fds, link and return */
if (lflag) {
(void)close(from_fd);
(void)close(to_fd);
(void)unlink(to.p_path);
if (link(entp->fts_path, to.p_path)) {
warn("%s", to.p_path);
return (1);
}
return (0);
}
/* NOTREACHED */
/*
* There's no reason to do anything other than close the file
* now if it's empty, so let's not bother.
*/
if (fs->st_size > 0) {
struct finfo fi;
fi.from = entp->fts_path;
fi.to = to.p_path;
fi.size = (size_t)fs->st_size;
/*
* Mmap and write if less than 8M (the limit is so
* we don't totally trash memory on big files).
* This is really a minor hack, but it wins some CPU back.
*/
bool use_read;
use_read = true;
if (fs->st_size <= MMAP_MAX_SIZE) {
size_t fsize = (size_t)fs->st_size;
p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED,
from_fd, (off_t)0);
if (p != MAP_FAILED) {
size_t remainder;
use_read = false;
#if !defined(__minix)
(void) madvise(p, (size_t)fs->st_size,
MADV_SEQUENTIAL);
#endif /* !defined(__minix) */
/*
* Write out the data in small chunks to
* avoid locking the output file for a
* long time if the reading the data from
* the source is slow.
*/
remainder = fsize;
do {
ssize_t chunk;
chunk = (remainder > MMAP_MAX_WRITE) ?
MMAP_MAX_WRITE : remainder;
if (write(to_fd, &p[fsize - remainder],
chunk) != chunk) {
warn("%s", to.p_path);
rval = 1;
break;
}
remainder -= chunk;
ptotal += chunk;
if (pinfo)
progress(&fi, ptotal);
} while (remainder > 0);
if (munmap(p, fsize) < 0) {
warn("%s", entp->fts_path);
rval = 1;
}
}
}
if (use_read) {
while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
wcount = write(to_fd, buf, (size_t)rcount);
if (rcount != wcount || wcount == -1) {
warn("%s", to.p_path);
rval = 1;
break;
}
ptotal += wcount;
if (pinfo)
progress(&fi, ptotal);
}
if (rcount < 0) {
warn("%s", entp->fts_path);
rval = 1;
}
}
}
#if !defined(__minix)
if (pflag && (fcpxattr(from_fd, to_fd) != 0))
warn("%s: error copying extended attributes", to.p_path);
#endif /* !defined(__minix) */
(void)close(from_fd);
if (rval == 1) {
(void)close(to_fd);
return (1);
}
if (pflag && setfile(fs, to_fd))
rval = 1;
/*
* If the source was setuid or setgid, lose the bits unless the
* copy is owned by the same user and group.
*/
#define RETAINBITS \
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
if (!pflag && dne
&& fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
if (fstat(to_fd, &to_stat)) {
warn("%s", to.p_path);
rval = 1;
} else if (fs->st_gid == to_stat.st_gid &&
fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
warn("%s", to.p_path);
rval = 1;
}
}
if (close(to_fd)) {
warn("%s", to.p_path);
rval = 1;
}
/* set the mod/access times now after close of the fd */
if (pflag && set_utimes(to.p_path, fs)) {
rval = 1;
}
return (rval);
}
int
copy_link(FTSENT *p, int exists)
{
int len;
char target[MAXPATHLEN];
if ((len = readlink(p->fts_path, target, sizeof(target)-1)) == -1) {
warn("readlink: %s", p->fts_path);
return (1);
}
target[len] = '\0';
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
}
if (symlink(target, to.p_path)) {
warn("symlink: %s", target);
return (1);
}
return (pflag ? setfile(p->fts_statp, 0) : 0);
}
int
copy_fifo(struct stat *from_stat, int exists)
{
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
}
if (mkfifo(to.p_path, from_stat->st_mode)) {
warn("mkfifo: %s", to.p_path);
return (1);
}
return (pflag ? setfile(from_stat, 0) : 0);
}
int
copy_special(struct stat *from_stat, int exists)
{
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
}
if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
warn("mknod: %s", to.p_path);
return (1);
}
return (pflag ? setfile(from_stat, 0) : 0);
}
/*
* Function: setfile
*
* Purpose:
* Set the owner/group/permissions for the "to" file to the information
* in the stat structure. If fd is zero, also call set_utimes() to set
* the mod/access times. If fd is non-zero, the caller must do a utimes
* itself after close(fd).
*/
int
setfile(struct stat *fs, int fd)
{
int rval, islink;
rval = 0;
islink = S_ISLNK(fs->st_mode);
fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
/*
* Changing the ownership probably won't succeed, unless we're root
* or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
* the mode; current BSD behavior is to remove all setuid bits on
* chown. If chown fails, lose setuid/setgid bits.
*/
if (fd ? fchown(fd, fs->st_uid, fs->st_gid) :
lchown(to.p_path, fs->st_uid, fs->st_gid)) {
if (errno != EPERM) {
warn("chown: %s", to.p_path);
rval = 1;
}
fs->st_mode &= ~(S_ISUID | S_ISGID);
}
if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) {
warn("chmod: %s", to.p_path);
rval = 1;
}
#if !defined(__minix)
if (!islink && !Nflag) {
unsigned long fflags = fs->st_flags;
/*
* XXX
* NFS doesn't support chflags; ignore errors unless
* there's reason to believe we're losing bits.
* (Note, this still won't be right if the server
* supports flags and we were trying to *remove* flags
* on a file that we copied, i.e., that we didn't create.)
*/
errno = 0;
if ((fd ? fchflags(fd, fflags) :
chflags(to.p_path, fflags)) == -1)
if (errno != EOPNOTSUPP || fs->st_flags != 0) {
warn("chflags: %s", to.p_path);
rval = 1;
}
}
#endif /* !defined(__minix) */
/* if fd is non-zero, caller must call set_utimes() after close() */
if (fd == 0 && set_utimes(to.p_path, fs))
rval = 1;
return (rval);
}
void
usage(void)
{
(void)fprintf(stderr,
"usage: %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src target\n"
" %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src1 ... srcN directory\n",
getprogname(), getprogname());
exit(1);
/* NOTREACHED */
}

View File

@@ -1,76 +0,0 @@
# $NetBSD: Makefile,v 1.39 2013/07/16 17:47:43 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
#
# C Shell with process control; VM/UNIX VAX Makefile
# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
#
# To profile, put -DPROF in DFLAGS and -pg in COPTS, and recompile.
.include <bsd.own.mk>
WARNS=6
PROG= csh
DFLAGS=-DBUILTIN -DFILEC -DNLS -DSHORT_STRINGS
# - Editor history not always aligned with shell history,
# should implement internally
# - Does not handle escaped prompts.
# - Does not do completion
.ifndef SMALLPROG
DFLAGS+=-DEDIT
.endif
CPPFLAGS+=-I${.CURDIR} -I. ${DFLAGS}
SRCS= alloc.c char.c const.c csh.c dir.c dol.c err.c exec.c exp.c file.c \
func.c glob.c hist.c init.c lex.c misc.c parse.c printf.c proc.c \
sem.c set.c str.c time.c
.PATH: ${NETBSDSRCDIR}/usr.bin/printf
MLINKS= csh.1 limit.1 csh.1 alias.1 csh.1 bg.1 csh.1 dirs.1 csh.1 fg.1 \
csh.1 foreach.1 csh.1 history.1 csh.1 jobs.1 csh.1 popd.1 \
csh.1 pushd.1 csh.1 rehash.1 csh.1 repeat.1 csh.1 suspend.1 \
csh.1 stop.1 csh.1 source.1
DPSRCS+= errnum.h const.h
CLEANFILES+= errnum.h const.h
errnum.h: err.c
${_MKTARGET_CREATE}
rm -f ${.TARGET}
(\
echo '/* Do not edit this file, make creates it. */' ;\
echo '#ifndef _h_sh_errnum' ;\
echo '#define _h_sh_errnum' ;\
egrep 'ERR_' ${.ALLSRC} | egrep '^#define' ;\
echo '#endif /* _h_sh_errnum */' ;\
) > ${.TARGET}
const.c: errnum.h
const.h: const.c
${_MKTARGET_CREATE}
rm -f ${.TARGET}
echo '/* Do not edit this file, make creates it. */' > ${.TARGET}
${CC} -E ${CPPFLAGS} ${.ALLSRC} | egrep 'Char STR' | \
${TOOL_SED} -e 's/Char \([a-zA-Z0-9_]*\)\(.*\)/extern Char \1[];/' | \
sort >> ${.TARGET}
.if make(install)
SUBDIR+=USD.doc
.endif
# XXX Only GCC 4.1 problem
.if defined(HAVE_GCC) && ${HAVE_GCC} == 4 && ${MACHINE_ARCH} == "vax"
COPTS.parse.c+= -O0
.endif
COPTS.err.c = -Wno-format-nonliteral
COPTS.printf.c = -Wno-format-nonliteral
COPTS.proc.c = -Wno-format-nonliteral
.if !empty(DFLAGS:M*EDIT)
LDADD+=-ledit -lterminfo -lutil
DPADD+=${LIBEDIT} ${LIBUTIL}
.else
LDADD+=-lutil
DPADD+=${LIBUTIL}
.endif
.include <bsd.prog.mk>
.include <bsd.subdir.mk>

View File

@@ -1,12 +0,0 @@
# $NetBSD: Makefile,v 1.7 2007/10/18 18:26:31 tls Exp $
# @(#)Makefile 8.1 (Berkeley) 8/14/93
DIR= usd/04.csh
SRCS= tabs csh.1 csh.2 csh.3 csh.4 csh.ap csh.g
MACROS= -ms
paper.ps: ${SRCS}
${TOOL_SOELIM} -I${.CURDIR} ${.ALLSRC} | \
${TOOL_ROFF_PS} ${MACROS} > ${.TARGET}
.include <bsd.doc.mk>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,648 +0,0 @@
.\" $NetBSD: csh.3,v 1.5 2003/08/07 09:05:08 agc Exp $
.\"
.\" 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. 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.
.\"
.\" @(#)csh.3 8.1 (Berkeley) 6/8/93
.\"
.nr H1 2
.NH
Shell control structures and command scripts
.NH 2
Introduction
.PP
It is possible to place commands in files and to cause shells to be
invoked to read and execute commands from these files,
which are called
.I "shell scripts."
We here detail those features of the shell useful to the writers of such
scripts.
.NH 2
Make
.PP
It is important to first note what shell scripts are
.I not
useful for.
There is a program called
.I make
which is very useful for maintaining a group of related files
or performing sets of operations on related files.
For instance a large program consisting of one or more files
can have its dependencies described in a
.I makefile
which contains definitions of the commands used to create these
different files when changes occur.
Definitions of the means for printing listings, cleaning up the directory
in which the files reside, and installing the resultant programs
are easily, and most appropriately placed in this
.I makefile.
This format is superior and preferable to maintaining a group of shell
procedures to maintain these files.
.PP
Similarly when working on a document a
.I makefile
may be created which defines how different versions of the document
are to be created and which options of
.I nroff
or
.I troff
are appropriate.
.NH 2
Invocation and the argv variable
.PP
A
.I csh
command script may be interpreted by saying
.DS
% csh script ...
.DE
where
.I script
is the name of the file containing a group of
.I csh
commands and
`\&...' is replaced by a sequence of arguments.
The shell places these arguments in the variable
.I argv
and then begins to read commands from the script.
These parameters are then available through the same mechanisms
which are used to reference any other shell variables.
.PP
If you make the file
`script'
executable by doing
.DS
chmod 755 script
.DE
and place a shell comment at the beginning of the shell script
(i.e. begin the file with a `#' character)
then a `/bin/csh' will automatically be invoked to execute `script' when
you type
.DS
script
.DE
If the file does not begin with a `#' then the standard shell
`/bin/sh' will be used to execute it.
This allows you to convert your older shell scripts to use
.I csh
at your convenience.
.NH 2
Variable substitution
.PP
After each input line is broken into words and history substitutions
are done on it, the input line is parsed into distinct commands.
Before each command is executed a mechanism know as
.I "variable substitution"
is done on these words.
Keyed by the character `$' this substitution replaces the names
of variables by their values.
Thus
.DS
echo $argv
.DE
when placed in a command script would cause the current value of the
variable
.I argv
to be echoed to the output of the shell script.
It is an error for
.I argv
to be unset at this point.
.PP
A number of notations are provided for accessing components and attributes
of variables.
The notation
.DS
$?name
.DE
expands to `1' if name is
.I set
or to `0'
if name is not
.I set.
It is the fundamental mechanism used for checking whether particular
variables have been assigned values.
All other forms of reference to undefined variables cause errors.
.PP
The notation
.DS
$#name
.DE
expands to the number of elements in the variable
.I name.
Thus
.DS
% set argv=(a b c)
% echo $?argv
1
% echo $#argv
3
% unset argv
% echo $?argv
0
% echo $argv
Undefined variable: argv.
%
.DE
.PP
It is also possible to access the components of a variable
which has several values.
Thus
.DS
$argv[1]
.DE
gives the first component of
.I argv
or in the example above `a'.
Similarly
.DS
$argv[$#argv]
.DE
would give `c',
and
.DS
$argv[1\-2]
.DE
would give `a b'. Other notations useful in shell scripts are
.DS
$\fIn\fR
.DE
where
.I n
is an integer as a shorthand for
.DS
$argv[\fIn\fR\|]
.DE
the
.I n\|th
parameter and
.DS
$*
.DE
which is a shorthand for
.DS
$argv
.DE
The form
.DS
$$
.DE
expands to the process number of the current shell.
Since this process number is unique in the system it can
be used in generation of unique temporary file names.
The form
.DS
$<
.DE
is quite special and is replaced by the next line of input read from
the shell's standard input (not the script it is reading). This is
useful for writing shell scripts that are interactive, reading
commands from the terminal, or even writing a shell script that
acts as a filter, reading lines from its input file. Thus the sequence
.DS
echo 'yes or no?\ec'
set a=($<)
.DE
would write out the prompt `yes or no?' without a newline and then
read the answer into the variable `a'. In this case `$#a' would be
`0' if either a blank line or end-of-file (^D) was typed.
.PP
One minor difference between `$\fIn\fR\|' and `$argv[\fIn\fR\|]'
should be noted here.
The form
`$argv[\fIn\fR\|]'
will yield an error if
.I n
is not in the range
`1\-$#argv'
while `$n'
will never yield an out of range subscript error.
This is for compatibility with the way older shells handled parameters.
.PP
Another important point is that it is never an error to give a subrange
of the form `n\-'; if there are less than
.I n
components of the given variable then no words are substituted.
A range of the form `m\-n' likewise returns an empty vector without giving
an error when \fIm\fR exceeds the number of elements of the given variable,
provided the subscript \fIn\fR is in range.
.NH 2
Expressions
.PP
In order for interesting shell scripts to be constructed it
must be possible to evaluate expressions in the shell based on the
values of variables.
In fact, all the arithmetic operations of the language C are available
in the shell
with the same precedence that they have in C.
In particular, the operations `==' and `!=' compare strings
and the operators `&&' and `|\|\||' implement the boolean and/or operations.
The special operators `=~' and `!~' are similar to `==' and `!=' except
that the string on the right side can have pattern matching characters
(like *, ? or []) and the test is whether the string on the left matches
the pattern on the right.
.PP
The shell also allows file enquiries of the form
.DS
\-? filename
.DE
where `?' is replace by a number of single characters.
For instance the expression primitive
.DS
\-e filename
.DE
tell whether the file
`filename'
exists.
Other primitives test for read, write and execute access to the file,
whether it is a directory, or has non-zero length.
.PP
It is possible to test whether a command terminates normally,
by a primitive of the
form `{ command }' which returns true, i.e. `1' if the command
succeeds exiting normally with exit status 0, or `0' if the command
terminates abnormally or with exit status non-zero.
If more detailed information about the execution status of a command
is required, it can be executed and the variable `$status' examined
in the next command.
Since `$status' is set by every command, it is very transient.
It can be saved if it is inconvenient to use it only in the single
immediately following command.
.PP
For a full list of expression components available see the manual
section for the shell.
.NH 2
Sample shell script
.PP
A sample shell script which makes use of the expression mechanism
of the shell and some of its control structure follows:
.DS
% cat copyc
#
# Copyc copies those C programs in the specified list
# to the directory ~/backup if they differ from the files
# already in ~/backup
#
set noglob
foreach i ($argv)
if ($i !~ *.c) continue # not a .c file so do nothing
if (! \-r ~/backup/$i:t) then
echo $i:t not in backup... not cp\e\'ed
continue
endif
cmp \-s $i ~/backup/$i:t # to set $status
if ($status != 0) then
echo new backup of $i
cp $i ~/backup/$i:t
endif
end
.DE
.PP
This script makes use of the
.I foreach
command, which causes the shell to execute the commands between the
.I foreach
and the matching
.I end
for each of the values given between `(' and `)' with the named
variable, in this case `i' set to successive values in the list.
Within this loop we may use the command
.I break
to stop executing the loop
and
.I continue
to prematurely terminate one iteration
and begin the next.
After the
.I foreach
loop the iteration variable
(\fIi\fR in this case)
has the value at the last iteration.
.PP
We set the variable
.I noglob
here to prevent filename expansion of the members of
.I argv.
This is a good idea, in general, if the arguments to a shell script
are filenames which have already been expanded or if the arguments
may contain filename expansion metacharacters.
It is also possible to quote each use of a `$' variable expansion,
but this is harder and less reliable.
.PP
The other control construct used here is a statement of the form
.DS
\fBif\fR ( expression ) \fBthen\fR
command
...
\fBendif\fR
.DE
The placement of the keywords here is
.B not
flexible due to the current implementation of the shell.\(dg
.FS
\(dgThe following two formats are not currently acceptable to the shell:
.sp
.in +5
.nf
\fBif\fR ( expression ) # \fBWon't work!\fR
\fBthen\fR
command
...
\fBendif\fR
.fi
.in -5
.sp
and
.sp
.in +5
.nf
\fBif\fR ( expression ) \fBthen\fR command \fBendif\fR # \fBWon't work\fR
.in -5
.fi
.FE
.PP
The shell does have another form of the if statement of the form
.DS
\fBif\fR ( expression ) \fBcommand\fR
.DE
which can be written
.DS
\fBif\fR ( expression ) \e
command
.DE
Here we have escaped the newline for the sake of appearance.
The command must not involve `\||\|', `&' or `;'
and must not be another control command.
The second form requires the final `\e' to
.B immediately
precede the end-of-line.
.PP
The more general
.I if
statements above also admit a sequence of
.I else\-if
pairs followed by a single
.I else
and an
.I endif,
e.g.:
.DS
\fBif\fR ( expression ) \fBthen\fR
commands
\fBelse\fR \fBif\fR (expression ) \fBthen\fR
commands
\&...
\fBelse\fR
commands
\fBendif\fR
.DE
.PP
Another important mechanism used in shell scripts is the `:' modifier.
We can use the modifier `:r' here to extract a root of a filename or
`:e' to extract the
.I extension.
Thus if the variable
.I i
has the value
`/mnt/foo.bar'
then
.sp
.in +5
.nf
% echo $i $i:r $i:e
/mnt/foo.bar /mnt/foo bar
%
.sp
.in -5
.fi
shows how the `:r' modifier strips off the trailing `.bar' and the
the `:e' modifier leaves only the `bar'.
Other modifiers will take off the last component of a pathname leaving
the head `:h' or all but the last component of a pathname leaving the
tail `:t'.
These modifiers are fully described in the
.I csh
manual pages in the User's Reference Manual.
It is also possible to use the
.I "command substitution"
mechanism described in the next major section to perform modifications
on strings to then reenter the shell's environment.
Since each usage of this mechanism involves the creation of a new process,
it is much more expensive to use than the `:' modification mechanism.\(dd
.FS
\(dd It is also important to note that
the current implementation of the shell limits the number of `:' modifiers
on a `$' substitution to 1.
Thus
.sp
.nf
.in +5
% echo $i $i:h:t
/a/b/c /a/b:t
%
.in -5
.fi
.sp
does not do what one would expect.
.FE
Finally, we note that the character `#' lexically introduces a shell
comment in shell scripts (but not from the terminal).
All subsequent characters on the input line after a `#' are discarded
by the shell.
This character can be quoted using `\'' or `\e' to place it in
an argument word.
.NH 2
Other control structures
.PP
The shell also has control structures
.I while
and
.I switch
similar to those of C.
These take the forms
.DS
\fBwhile\fR ( expression )
commands
\fBend\fR
.DE
and
.DS
\fBswitch\fR ( word )
\fBcase\fR str1:
commands
\fBbreaksw\fR
\& ...
\fBcase\fR strn:
commands
\fBbreaksw\fR
\fBdefault:\fR
commands
\fBbreaksw\fR
\fBendsw\fR
.DE
For details see the manual section for
.I csh.
C programmers should note that we use
.I breaksw
to exit from a
.I switch
while
.I break
exits a
.I while
or
.I foreach
loop.
A common mistake to make in
.I csh
scripts is to use
.I break
rather than
.I breaksw
in switches.
.PP
Finally,
.I csh
allows a
.I goto
statement, with labels looking like they do in C, i.e.:
.DS
loop:
commands
\fBgoto\fR loop
.DE
.NH 2
Supplying input to commands
.PP
Commands run from shell scripts receive by default the standard
input of the shell which is running the script.
This is different from previous shells running
under \s-2UNIX\s0. It allows shell scripts to fully participate
in pipelines, but mandates extra notation for commands which are to take
inline data.
.PP
Thus we need a metanotation for supplying inline data to commands in
shell scripts.
As an example, consider this script which runs the editor to
delete leading blanks from the lines in each argument file:
.DS
% cat deblank
# deblank \-\- remove leading blanks
foreach i ($argv)
ed \- $i << \'EOF\'
1,$s/^[ ]*//
w
q
\&\'EOF\'
end
%
.DE
The notation `<< \'EOF\''
means that the standard input for the
.I ed
command is to come from the text in the shell script file
up to the next line consisting of exactly `\'EOF\''.
The fact that the `EOF' is enclosed in `\'' characters, i.e. quoted,
causes the shell to not perform variable substitution on the
intervening lines.
In general, if any part of the word following the `<<' which the
shell uses to terminate the text to be given to the command is quoted
then these substitutions will not be performed.
In this case since we used the form `1,$' in our editor script
we needed to insure that this `$' was not variable substituted.
We could also have insured this by preceding the `$' here with a `\e',
i.e.:
.DS
1,\e$s/^[ ]*//
.DE
but quoting the `EOF' terminator is a more reliable way of achieving the
same thing.
.NH 2
Catching interrupts
.PP
If our shell script creates temporary files, we may wish to catch
interruptions of the shell script so that we can clean up
these files.
We can then do
.DS
onintr label
.DE
where
.I label
is a label in our program.
If an interrupt is received the shell will do a
`goto label'
and we can remove the temporary files and then do an
.I exit
command (which is built in to the shell)
to exit from the shell script.
If we wish to exit with a non-zero status we can do
.DS
exit(1)
.DE
e.g. to exit with status `1'.
.NH 2
What else?
.PP
There are other features of the shell useful to writers of shell
procedures.
The
.I verbose
and
.I echo
options and the related
.I \-v
and
.I \-x
command line options can be used to help trace the actions of the shell.
The
.I \-n
option causes the shell only to read commands and not to execute
them and may sometimes be of use.
.PP
One other thing to note is that
.I csh
will not execute shell scripts which do not begin with the
character `#', that is shell scripts that do not begin with a comment.
Similarly, the `/bin/sh' on your system may well defer to `csh'
to interpret shell scripts which begin with `#'.
This allows shell scripts for both shells to live in harmony.
.PP
There is also another quotation mechanism using `"' which allows
only some of the expansion mechanisms we have so far discussed to occur
on the quoted string and serves to make this string into a single word
as `\'' does.
.bp

View File

@@ -1,176 +0,0 @@
.\" $NetBSD: csh.4,v 1.4 2003/08/07 09:05:08 agc Exp $
.\"
.\" 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. 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.
.\"
.\" @(#)csh.4 8.1 (Berkeley) 6/8/93
.\"
.nr H1 3
.NH
Other, less commonly used, shell features
.NH 2
Loops at the terminal; variables as vectors
.PP
It is occasionally useful to use the
.I foreach
control structure at the terminal to aid in performing a number
of similar commands.
For instance, there were at one point three shells in use on the Cory \s-2UNIX\s0
system at Cory Hall,
`/bin/sh',
`/bin/nsh',
and
`/bin/csh'.
To count the number of persons using each shell one could have issued
the commands
.DS
% grep \-c csh$ /etc/passwd
27
% grep \-c nsh$ /etc/passwd
128
% grep \-c \-v sh$ /etc/passwd
430
%
.DE
Since these commands are very similar we can use
.I foreach
to do this more easily.
.DS
% foreach i (\'sh$\' \'csh$\' \'\-v sh$\')
? grep \-c $i /etc/passwd
? end
27
128
430
%
.DE
Note here that the shell prompts for
input with `? ' when reading the body of the loop.
.PP
Very useful with loops are variables which contain lists of filenames
or other words.
You can, for example, do
.DS
% set a=(\`ls\`)
% echo $a
csh.n csh.rm
% ls
csh.n
csh.rm
% echo $#a
2
%
.DE
The
.I set
command here gave the variable
.I a
a list of all the filenames in the current directory as value.
We can then iterate over these names to perform any chosen function.
.PP
The output of a command within `\`' characters is converted by
the shell to a list of words.
You can also place the `\`' quoted string within `"' characters
to take each (non-empty) line as a component of the variable;
preventing the lines from being split into words at blanks and tabs.
A modifier `:x' exists which can be used later to expand each component
of the variable into another variable splitting it into separate words
at embedded blanks and tabs.
.NH 2
Braces { ... } in argument expansion
.PP
Another form of filename expansion, alluded
to before involves the characters `{' and `}'.
These characters specify that the contained strings, separated by `,'
are to be consecutively substituted into the containing characters
and the results expanded left to right.
Thus
.DS
A{str1,str2,...strn}B
.DE
expands to
.DS
Astr1B Astr2B ... AstrnB
.DE
This expansion occurs before the other filename expansions, and may
be applied recursively (i.e. nested).
The results of each expanded string are sorted separately, left
to right order being preserved.
The resulting filenames are not required to exist if no other expansion
mechanisms are used.
This means that this mechanism can be used to generate arguments which are
not filenames, but which have common parts.
.PP
A typical use of this would be
.DS
mkdir ~/{hdrs,retrofit,csh}
.DE
to make subdirectories `hdrs', `retrofit' and `csh'
in your home directory.
This mechanism is most useful when the common prefix is longer
than in this example, i.e.
.DS
chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
.DE
.NH 2
Command substitution
.PP
A command enclosed in `\`' characters is replaced, just before
filenames are expanded, by the output from that command.
Thus it is possible to do
.DS
set pwd=\`pwd\`
.DE
to save the current directory in the variable
.I pwd
or to do
.DS
ex \`grep \-l TRACE *.c\`
.DE
to run the editor
.I ex
supplying as arguments those files whose names end in `.c'
which have the string `TRACE' in them.*
.FS
*Command expansion also occurs in input redirected with `<<'
and within `"' quotations.
Refer to the shell manual section for full details.
.FE
.NH 2
Other details not covered here
.PP
In particular circumstances it may be necessary to know the exact
nature and order of different substitutions performed by the shell.
The exact meaning of certain combinations of quotations is also
occasionally important.
These are detailed fully in its manual section.
.PP
The shell has a number of command line option flags mostly of use
in writing \s-2UNIX\s0 programs,
and debugging shell scripts.
See the csh(1) manual section for a list of these options.
.bp

View File

@@ -1,93 +0,0 @@
.\" $NetBSD: csh.ap,v 1.1 2007/10/18 18:26:31 tls Exp $
.\"
.\" 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. 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.
.\"
.\" @(#)csh.a 8.1 (Berkeley) 6/8/93
.\"
.SH
Appendix \- Special characters
.LP
The following table lists the special characters of
.I csh
and the \s-2UNIX\s0 system, giving for each the section(s) in which it
is discussed.
A number of these characters also have special meaning in expressions.
See the
.I csh
manual section
for a complete list.
.ta .75i 1.5i 2.25i
.LP
Syntactic metacharacters
.DS
; 2.4 separates commands to be executed sequentially
| 1.5 separates commands in a pipeline
( ) 2.2,3.6 brackets expressions and variable values
& 2.5 follows commands to be executed without waiting for completion
.DE
.LP
Filename metacharacters
.DS
/ 1.6 separates components of a file's pathname
\&. 1.6 separates root parts of a file name from extensions
? 1.6 expansion character matching any single character
* 1.6 expansion character matching any sequence of characters
[ ] 1.6 expansion sequence matching any single character from a set
~ 1.6 used at the beginning of a filename to indicate home directories
{ } 4.2 used to specify groups of arguments with common parts
.DE
.LP
Quotation metacharacters
.DS
\e 1.7 prevents meta-meaning of following single character
\' 1.7 prevents meta-meaning of a group of characters
" 4.3 like \', but allows variable and command expansion
.DE
.LP
Input/output metacharacters
.DS
< 1.5 indicates redirected input
> 1.3 indicates redirected output
.DE
.LP
Expansion/substitution metacharacters
.DS
$ 3.4 indicates variable substitution
! 2.3 indicates history substitution
: 3.6 precedes substitution modifiers
^ 2.3 used in special forms of history substitution
\` 4.3 indicates command substitution
.DE
.LP
Other metacharacters
.DS
# 1.3,3.6 begins scratch file names; indicates shell comments
\- 1.2 prefixes option (flag) arguments to commands
% 2.6 prefixes job name specifications
.DE
.bp

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
.\" $NetBSD: tabs,v 1.4 2003/08/07 09:05:09 agc Exp $
.\"
.\" 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. 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.
.\"
.\" @(#)tabs 8.1 (Berkeley) 6/8/93
.\"
.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n

View File

@@ -1,91 +0,0 @@
/* $NetBSD: alloc.c,v 1.13 2013/01/22 19:28:00 christos Exp $ */
/*-
* Copyright (c) 1983, 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)alloc.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: alloc.c,v 1.13 2013/01/22 19:28:00 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include "csh.h"
#include "extern.h"
ptr_t
Malloc(size_t n)
{
ptr_t ptr;
if ((ptr = malloc(n)) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
return (ptr);
}
ptr_t
Realloc(ptr_t p, size_t n)
{
ptr_t ptr;
if ((ptr = realloc(p, n)) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
return (ptr);
}
ptr_t
Calloc(size_t s, size_t n)
{
ptr_t ptr;
if ((ptr = calloc(s, n)) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
return (ptr);
}
void
Free(ptr_t p)
{
if (p)
free(p);
}

View File

@@ -1,315 +0,0 @@
/* $NetBSD: char.c,v 1.10 2012/01/19 02:42:53 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)char.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: char.c,v 1.10 2012/01/19 02:42:53 christos Exp $");
#endif
#endif /* not lint */
#include "char.h"
/* on default same as original map */
unsigned short _cmap[256] = {
/* 0 nul 1 soh 2 stx 3 etx */
_CTR, _CTR, _CTR, _CTR,
/* 4 eot 5 enq 6 ack 7 bel */
_CTR, _CTR, _CTR, _CTR,
/* 8 bs 9 ht 10 nl 11 vt */
_CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
/* 12 np 13 cr 14 so 15 si */
_CTR, _CTR, _CTR, _CTR,
/* 16 dle 17 dc1 18 dc2 19 dc3 */
_CTR, _CTR, _CTR, _CTR,
/* 20 dc4 21 nak 22 syn 23 etb */
_CTR, _CTR, _CTR, _CTR,
/* 24 can 25 em 26 sub 27 esc */
_CTR, _CTR, _CTR, _CTR,
/* 28 fs 29 gs 30 rs 31 us */
_CTR, _CTR, _CTR, _CTR,
/* 32 sp 33 ! 34 " 35 # */
_SP|_META, _PUN, _QF|_PUN, _META|_PUN,
/* 36 $ 37 % 38 & 39 ' */
_DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN,
/* 40 ( 41 ) 42 * 43 + */
_META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN,
/* 44 , 45 - 46 . 47 / */
_PUN, _PUN, _PUN, _PUN,
/* 48 0 49 1 50 2 51 3 */
_DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
/* 52 4 53 5 54 6 55 7 */
_DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
/* 56 8 57 9 58 : 59 ; */
_DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN,
/* 60 < 61 = 62 > 63 ? */
_META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN,
/* 64 @ 65 A 66 B 67 C */
_PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
/* 68 D 69 E 70 F 71 G */
_LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
/* 72 H 73 I 74 J 75 K */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 76 L 77 M 78 N 79 O */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 80 P 81 Q 82 R 83 S */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 84 T 85 U 86 V 87 W */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 88 X 89 Y 90 Z 91 [ */
_LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN,
/* 92 \ 93 ] 94 ^ 95 _ */
_ESC|_PUN, _PUN, _PUN, _PUN,
/* 96 ` 97 a 98 b 99 c */
_QB|_GLOB|_META|_PUN, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD,
/* 100 d 101 e 102 f 103 g */
_LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW,
/* 104 h 105 i 106 j 107 k */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 108 l 109 m 110 n 111 o */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 112 p 113 q 114 r 115 s */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 116 t 117 u 118 v 119 w */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 120 x 121 y 122 z 123 { */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _GLOB|_PUN,
/* 124 | 125 } 126 ~ 127 del */
_META|_CMD|_PUN,_PUN, _PUN, _CTR,
#ifdef SHORT_STRINGS
/****************************************************************/
/* 128 - 255 The below is supposedly ISO 8859/1 */
/****************************************************************/
/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */
_CTR, _CTR, _CTR, _CTR,
/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */
_PUN, /* XXX */ _PUN, _PUN, _PUN,
/* 164 currency 165 yen 166 brokenbar 167 section */
_PUN, _PUN, _PUN, _PUN,
/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/
_PUN, _PUN, _PUN, _PUN,
/* 172 notsign 173 hyphen 174 registered 175 macron */
_PUN, _PUN, _PUN, _PUN,
/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/
_PUN, _PUN, _PUN, _PUN,
/* 180 acute 181 mu 182 paragraph 183 periodcentered*/
_PUN, _PUN, /*XXX*/ _PUN, _PUN,
/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/
_PUN, _PUN, _PUN, _PUN,
/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/
_PUN, _PUN, _PUN, _PUN,
/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */
_LET|_UP, _LET|_UP, _LET|_UP, _PUN,
/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_LOW,
/* 224 agrave 225 aacute 226 acircumflex 227 atilde */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 240 eth 241 ntilde 242 ograve 243 oacute */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _PUN,
/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
#endif /* SHORT_STRINGS */
};
#ifndef NLS
/* _cmap_lower, _cmap_upper for ISO 8859/1 */
unsigned char _cmap_lower[256] = {
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0327,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
};
unsigned char _cmap_upper[256] = {
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0367,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0377,
};
#endif /* NLS */

View File

@@ -1,100 +0,0 @@
/* $NetBSD: char.h,v 1.9 2012/01/19 02:42:53 christos Exp $ */
/*-
* 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. 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.
*
* @(#)char.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _CHAR_H_
#define _CHAR_H_
#include <ctype.h>
extern unsigned short _cmap[];
#ifndef NLS
extern unsigned char _cmap_lower[], _cmap_upper[];
#endif
#define _QF 0x0001 /* '" (Forward quotes) */
#define _QB 0x0002 /* ` (Backquote) */
#define _SP 0x0004 /* space and tab */
#define _NL 0x0008 /* \n */
#define _META 0x0010 /* lex meta characters, sp #'`";&<>()|\t\n */
#define _GLOB 0x0020 /* glob characters, *?{[` */
#define _ESC 0x0040 /* \ */
#define _DOL 0x0080 /* $ */
#define _DIG 0x0100 /* 0-9 */
#define _LET 0x0200 /* a-z, A-Z, _ */
#define _UP 0x0400 /* A-Z */
#define _LOW 0x0800 /* a-z */
#define _XD 0x1000 /* 0-9, a-f, A-F */
#define _CMD 0x2000 /* lex end of command chars, ;&(|` */
#define _CTR 0x4000 /* control */
#define _PUN 0x8000 /* punctuation */
#define cmap(c, bits) \
(((c) & QUOTE) ? 0 : (_cmap[(unsigned char)(c)] & (bits)))
#define isglob(c) cmap(c, _GLOB)
#define isspc(c) cmap(c, _SP)
#define ismeta(c) cmap(c, _META)
#define iscmdmeta(c) cmap(c, _CMD)
#define letter(c) (((c) & QUOTE) ? 0 : \
(isalpha((unsigned char) (c)) || (c) == '_'))
#define alnum(c) (((c) & QUOTE) ? 0 : \
(isalnum((unsigned char) (c)) || (c) == '_'))
#ifdef NLS
#define Isspace(c) (((c) & QUOTE) ? 0 : isspace((unsigned char) (c)))
#define Isdigit(c) (((c) & QUOTE) ? 0 : isdigit((unsigned char) (c)))
#define Isalpha(c) (((c) & QUOTE) ? 0 : isalpha((unsigned char) (c)))
#define Islower(c) (((c) & QUOTE) ? 0 : islower((unsigned char) (c)))
#define Isupper(c) (((c) & QUOTE) ? 0 : isupper((unsigned char) (c)))
#define Tolower(c) (((c) & QUOTE) ? 0 : tolower((unsigned char) (c)))
#define Toupper(c) (((c) & QUOTE) ? 0 : toupper((unsigned char) (c)))
#define Isxdigit(c) (((c) & QUOTE) ? 0 : isxdigit((unsigned char) (c)))
#define Isalnum(c) (((c) & QUOTE) ? 0 : isalnum((unsigned char) (c)))
#define Iscntrl(c) (((c) & QUOTE) ? 0 : iscntrl((unsigned char) (c)))
#define Isprint(c) (((c) & QUOTE) ? 0 : isprint((unsigned char) (c)))
#else
#define Isspace(c) cmap(c, _SP|_NL)
#define Isdigit(c) cmap(c, _DIG)
#define Isalpha(c) (cmap(c,_LET) && !(((c) & META) && AsciiOnly))
#define Islower(c) (cmap(c,_LOW) && !(((c) & META) && AsciiOnly))
#define Isupper(c) (cmap(c, _UP) && !(((c) & META) && AsciiOnly))
#define Tolower(c) (_cmap_lower[(unsigned char)(c)])
#define Toupper(c) (_cmap_upper[(unsigned char)(c)])
#define Isxdigit(c) cmap(c, _XD)
#define Isalnum(c) (cmap(c, _DIG|_LET) && !(((c) & META) && AsciiOnly))
#define Iscntrl(c) (cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
#define Isprint(c) (!cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
#endif
#endif /* !_CHAR_H_ */

View File

@@ -1,164 +0,0 @@
/* $NetBSD: const.c,v 1.10 2013/01/22 20:35:29 christos Exp $ */
/*-
* Copyright (c) 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)const.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: const.c,v 1.10 2013/01/22 20:35:29 christos Exp $");
#endif
#endif /* not lint */
/*
* tc.const.c: String constants for csh.
*/
#include "csh.h"
Char STR0[] = { '0', '\0' };
Char STR1[] = { '1', '\0' };
Char STRHOME[] = { 'H', 'O', 'M', 'E', '\0' };
Char STRLANG[] = { 'L', 'A', 'N', 'G', '\0' };
Char STRLC_CTYPE[] = { 'L', 'C', '_', 'C', 'T', 'Y', 'P', 'E' ,'\0' };
Char STRLOGNAME[] = { 'L', 'O', 'G', 'N', 'A', 'M', 'E', '\0' };
Char STRLbrace[] = { '{', '\0' };
Char STRLparen[] = { '(', '\0' };
Char STRLparensp[] = { '(', ' ', '\0' };
Char STRNULL[] = { '\0' };
Char STRPATH[] = { 'P', 'A', 'T', 'H', '\0' };
Char STRPWD[] = { 'P', 'W', 'D', '\0' };
Char STRQNULL[] = { '\0' | QUOTE, '\0' };
Char STRRbrace[] = { '}', '\0' };
Char STRspRparen[] = { ' ', ')', '\0' };
Char STRTERM[] = { 'T', 'E', 'R', 'M', '\0' };
Char STRUSER[] = { 'U', 'S', 'E', 'R', '\0' };
Char STRalias[] = { 'a', 'l', 'i', 'a', 's', '\0' };
Char STRand[] = { '&', '\0' };
Char STRand2[] = { '&', '&', '\0' };
Char STRaout[] = { 'a', '.', 'o', 'u', 't', '\0' };
Char STRargv[] = { 'a', 'r', 'g', 'v', '\0' };
Char STRbang[] = { '!', '\0' };
Char STRcaret[] = { '^', '\0' };
Char STRcdpath[] = { 'c', 'd', 'p', 'a', 't', 'h', '\0' };
Char STRcent2[] = { '%', '%', '\0' };
Char STRcenthash[] = { '%', '#', '\0' };
Char STRcentplus[] = { '%', '+', '\0' };
Char STRcentminus[] = { '%', '-', '\0' };
Char STRchase_symlinks[] = { 'c', 'h', 'a', 's', 'e', '_', 's', 'y', 'm', 'l',
'i', 'n', 'k', 's', '\0' };
Char STRchild[] = { 'c', 'h', 'i', 'l', 'd', '\0' };
Char STRcolon[] = { ':', '\0' };
Char STRcwd[] = { 'c', 'w', 'd', '\0' };
Char STRdefault[] = { 'd', 'e', 'f', 'a', 'u', 'l', 't', '\0' };
Char STRdot[] = { '.', '\0' };
Char STRdotdotsl[] = { '.', '.', '/', '\0' };
Char STRdotsl[] = { '.', '/', '\0' };
Char STRecho[] = { 'e', 'c', 'h', 'o', '\0' };
Char STRedit[] = { 'e', 'd', 'i', 't', '\0' };
Char STRequal[] = { '=', '\0' };
Char STRfakecom[] = { '{', ' ', '.', '.', '.', ' ', '}', '\0' };
Char STRfakecom1[] = { '`', ' ', '.', '.', '.', ' ', '`', '\0' };
Char STRfignore[] = { 'f', 'i', 'g', 'n', 'o', 'r', 'e', '\0' };
#ifdef FILEC
Char STRfilec[] = { 'f', 'i', 'l', 'e', 'c', '\0' };
#endif /* FILEC */
Char STRhistchars[] = { 'h', 'i', 's', 't', 'c', 'h', 'a', 'r', 's', '\0' };
Char STRtildothist[] = { '~', '/', '.', 'h', 'i', 's', 't', 'o', 'r',
'y', '\0' };
Char STRhistfile[] = { 'h', 'i', 's', 't', 'f', 'i', 'l', 'e', '\0' };
Char STRhistory[] = { 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' };
Char STRhome[] = { 'h', 'o', 'm', 'e', '\0' };
Char STRignore_symlinks[] = { 'i', 'g', 'n', 'o', 'r', 'e', '_', 's', 'y', 'm',
'l', 'i', 'n', 'k', 's', '\0' };
Char STRignoreeof[] = { 'i', 'g', 'n', 'o', 'r', 'e', 'e', 'o', 'f', '\0' };
Char STRjobs[] = { 'j', 'o', 'b', 's', '\0' };
Char STRlistjobs[] = { 'l', 'i', 's', 't', 'j', 'o', 'b', 's', '\0' };
Char STRlogout[] = { 'l', 'o', 'g', 'o', 'u', 't', '\0' };
Char STRlong[] = { 'l', 'o', 'n', 'g', '\0' };
Char STRmail[] = { 'm', 'a', 'i', 'l', '\0' };
Char STRmh[] = { '-', 'h', '\0' };
Char STRminus[] = { '-', '\0' };
Char STRml[] = { '-', 'l', '\0' };
Char STRmn[] = { '-', 'n', '\0' };
Char STRmquestion[] = { '?' | QUOTE, ' ', '\0' };
Char STRnice[] = { 'n', 'i', 'c', 'e', '\0' };
Char STRnoambiguous[] = { 'n', 'o', 'a', 'm', 'b', 'i', 'g', 'u', 'o', 'u',
's', '\0' };
Char STRnobeep[] = { 'n', 'o', 'b', 'e', 'e', 'p', '\0' };
Char STRnoclobber[] = { 'n', 'o', 'c', 'l', 'o', 'b', 'b', 'e', 'r', '\0' };
Char STRnoglob[] = { 'n', 'o', 'g', 'l', 'o', 'b', '\0' };
Char STRnohup[] = { 'n', 'o', 'h', 'u', 'p', '\0' };
Char STRnonomatch[] = { 'n', 'o', 'n', 'o', 'm', 'a', 't', 'c', 'h', '\0' };
Char STRnormal[] = { 'n', 'o', 'r', 'm', 'a', 'l', '\0' };
Char STRnotify[] = { 'n', 'o', 't', 'i', 'f', 'y', '\0' };
Char STRor[] = { '|', '\0' };
Char STRor2[] = { '|', '|', '\0' };
Char STRpath[] = { 'p', 'a', 't', 'h', '\0' };
Char STRprintexitvalue[] = { 'p', 'r', 'i', 'n', 't', 'e', 'x', 'i', 't', 'v',
'a', 'l', 'u', 'e', '\0' };
Char STRprompt[] = { 'p', 'r', 'o', 'm', 'p', 't', '\0' };
Char STRprompt2[] = { 'p', 'r', 'o', 'm', 'p', 't', '2', '\0' };
Char STRpushdsilent[] = { 'p', 'u', 's', 'h', 'd', 's', 'i', 'l', 'e', 'n',
't', '\0' };
Char STRret[] = { '\n', '\0' };
Char STRsavehist[] = { 's', 'a', 'v', 'e', 'h', 'i', 's', 't', '\0' };
Char STRsemisp[] = { ';', ' ', '\0' };
Char STRshell[] = { 's', 'h', 'e', 'l', 'l', '\0' };
Char STRslash[] = { '/', '\0' };
Char STRsldotcshrc[] = { '/', '.', 'c', 's', 'h', 'r', 'c', '\0' };
Char STRsldotlogin[] = { '/', '.', 'l', 'o', 'g', 'i', 'n', '\0' };
Char STRsldthist[] = { '/', '.', 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' };
Char STRsldtlogout[] = { '/', '.', 'l', 'o', 'g', 'o', 'u', 't', '\0' };
Char STRsource[] = { 's', 'o', 'u', 'r', 'c', 'e', '\0' };
Char STRsp3dots[] = { ' ', '.', '.', '.', '\0' };
Char STRspLarrow2sp[] = { ' ', '<', '<', ' ', '\0' };
Char STRspLarrowsp[] = { ' ', '<', ' ', '\0' };
Char STRspRarrow[] = { ' ', '>', '\0' };
Char STRspRarrow2[] = { ' ', '>', '>', '\0' };
Char STRRparen[] = { ')', '\0' };
Char STRspace[] = { ' ', '\0' };
Char STRspand2sp[] = { ' ', '&', '&', ' ', '\0' };
Char STRspor2sp[] = { ' ', '|', '|', ' ', '\0' };
Char STRsporsp[] = { ' ', '|', ' ', '\0' };
Char STRstar[] = { '*', '\0' };
Char STRstatus[] = { 's', 't', 'a', 't', 'u', 's', '\0' };
Char STRsymcent[] = { '%', ' ', '\0' };
Char STRsymhash[] = { '#', ' ', '\0' };
Char STRterm[] = { 't', 'e', 'r', 'm', '\0' };
Char STRthen[] = { 't', 'h', 'e', 'n', '\0' };
Char STRtilde[] = { '~', '\0' };
Char STRtime[] = { 't', 'i', 'm', 'e', '\0' };
Char STRtmpsh[] = { '/', 't', 'm', 'p', '/', 's', 'h', '\0' };
Char STRunalias[] = { 'u', 'n', 'a', 'l', 'i', 'a', 's', '\0' };
Char STRuser[] = { 'u', 's', 'e', 'r', '\0' };
Char STRverbose[] = { 'v', 'e', 'r', 'b', 'o', 's', 'e', '\0' };
Char STRwordchars[] = { 'w', 'o', 'r', 'd', 'c', 'h', 'a', 'r', 's', '\0' };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,559 +0,0 @@
/* $NetBSD: csh.h,v 1.26 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. 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.
*
* @(#)csh.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _CSH_H_
#define _CSH_H_
/*
* Fundamental definitions which may vary from system to system.
*
* BUFSIZE The i/o buffering size; also limits word size
* MAILINTVL How often to mailcheck; more often is more expensive
*/
#ifndef BUFSIZE
#define BUFSIZE 4096 /* default buffer size */
#endif /* BUFSIZE */
#define FORKSLEEP 10 /* delay loop on non-interactive fork failure */
#define MAILINTVL 600 /* 10 minutes */
/*
* The shell moves std in/out/diag and the old std input away from units
* 0, 1, and 2 so that it is easy to set up these standards for invoked
* commands.
*/
#define FSHTTY 15 /* /dev/tty when manip pgrps */
#define FSHIN 16 /* Preferred desc for shell input */
#define FSHOUT 17 /* ... shell output */
#define FSHERR 18 /* ... shell diagnostics */
#define FOLDSTD 19 /* ... old std input */
#ifdef PROF
#define xexit(n) done(n)
#endif
#ifdef SHORT_STRINGS
typedef short Char;
#define SAVE(a) (Strsave(str2short(a)))
#else
typedef char Char;
#define SAVE(a) (strsave(a))
#endif
/*
* Make sure a variable is not stored in a register by taking its address
* This is used where variables might be clobbered by longjmp.
*/
#define UNREGISTER(a) (void) &a
typedef void *ioctl_t; /* Third arg of ioctl */
typedef void *ptr_t;
#include "const.h"
#include "char.h"
#include "errnum.h"
#define xmalloc(i) Malloc(i)
#define xrealloc(p, i) Realloc(p, i)
#define xcalloc(n, s) Calloc(n, s)
#define xfree(p) Free(p)
#include <stdio.h>
FILE *cshin, *cshout, *csherr;
#define isdir(d) (S_ISDIR(d.st_mode))
#define eq(a, b) (Strcmp(a, b) == 0)
/* globone() flags */
#define G_ERROR 0 /* default action: error if multiple words */
#define G_IGNORE 1 /* ignore the rest of the words */
#define G_APPEND 2 /* make a sentence by cat'ing the words */
/*
* Global flags
*/
int child; /* Child shell ... errors cause exit */
int chkstop; /* Warned of stopped jobs... allow exit */
int didfds; /* Have setup i/o fd's for child */
int doneinp; /* EOF indicator after reset from readc */
int exiterr; /* Exit if error or non-zero exit status */
int haderr; /* Reset was because of an error */
int havhash; /* path hashing is available */
int intact; /* We are interactive... therefore prompt */
int intty; /* Input is a tty */
int justpr; /* Just print because of :p hist mod */
int loginsh; /* We are a loginsh -> .login/.logout */
int neednote; /* Need to pnotify() */
int noexec; /* Don't execute, just syntax check */
int pjobs; /* want to print jobs if interrupted */
int setintr; /* Set interrupts on/off -> Wait intr... */
int timflg; /* Time the next waited for command */
#ifdef FILEC
extern int filec; /* doing filename expansion */
#endif
/*
* Global i/o info
*/
Char *arginp; /* Argument input for sh -c and internal `xx` */
Char *ffile; /* Name of shell file for $0 */
int onelflg; /* 2 -> need line for -t, 1 -> exit on read */
extern char *seterr; /* Error message from scanner/parser */
Char *shtemp; /* Temp name for << shell files in /tmp */
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
struct timespec time0; /* Time at which the shell started */
struct rusage ru0;
/*
* Miscellany
*/
time_t chktim; /* Time mail last checked */
Char *doldol; /* Character pid for $$ */
pid_t backpid; /* Pid of the last background process */
gid_t egid, gid; /* Invokers gid */
uid_t euid, uid; /* Invokers uid */
int shpgrp; /* Pgrp of shell */
int tpgrp; /* Terminal process group */
/* If tpgrp is -1, leave tty alone! */
int opgrp; /* Initial pgrp and tty pgrp */
/*
* To be able to redirect i/o for builtins easily, the shell moves the i/o
* descriptors it uses away from 0,1,2.
* Ideally these should be in units which are closed across exec's
* (this saves work) but for version 6, this is not usually possible.
* The desired initial values for these descriptors are F{SHIN,...}.
*/
int SHIN; /* Current shell input (script) */
int SHOUT; /* Shell output */
int SHERR; /* Diagnostic output... shell errs go here */
int OLDSTD; /* Old standard input (def for cmds) */
/*
* Error control
*
* Errors in scanning and parsing set up an error message to be printed
* at the end and complete. Other errors always cause a reset.
* Because of source commands and .cshrc we need nested error catches.
*/
#include <setjmp.h>
jmp_buf reslab;
#define setexit() (setjmp(reslab))
#define reset() longjmp(reslab, 1)
/* Should use structure assignment here */
#define getexit(a) (void)memcpy((a), reslab, sizeof reslab)
#define resexit(a) (void)memcpy(reslab, (a), sizeof reslab)
Char *gointr; /* Label for an onintr transfer */
#include <signal.h>
sig_t parintr; /* Parents interrupt catch */
sig_t parterm; /* Parents terminate catch */
/*
* Lexical definitions.
*
* All lexical space is allocated dynamically.
* The eighth/sixteenth bit of characters is used to prevent recognition,
* and eventually stripped.
*/
#define META 0x80
#define ASCII 0x7f
#ifdef SHORT_STRINGS
#define CHAR ((Char)0xff)
#define QUOTE ((Char)0x8000) /* 16nth char bit used for 'ing */
#define TRIM ((Char)0x7fff) /* Mask to strip quote bit */
#else
#define CHAR ((Char)0x7f)
#define QUOTE ((Char)0x80) /* Eighth char bit used for 'ing */
#define TRIM ((Char)0x7f) /* Mask to strip quote bit */
#endif
int AsciiOnly; /* If set only 7 bits is expected in characters */
/*
* Each level of input has a buffered input structure.
* There are one or more blocks of buffered input for each level,
* exactly one if the input is seekable and tell is available.
* In other cases, the shell buffers enough blocks to keep all loops
* in the buffer.
*/
struct Bin {
off_t Bfseekp; /* Seek pointer */
off_t Bfbobp; /* Seekp of beginning of buffers */
off_t Bfeobp; /* Seekp of end of buffers */
int Bfblocks; /* Number of buffer blocks */
Char **Bfbuf; /* The array of buffer blocks */
} B;
/*
* This structure allows us to seek inside aliases
*/
struct Ain {
int type;
#define I_SEEK -1 /* Invalid seek */
#define A_SEEK 0 /* Alias seek */
#define F_SEEK 1 /* File seek */
#define E_SEEK 2 /* Eval seek */
union {
off_t _f_seek;
Char* _c_seek;
} fc;
#define f_seek fc._f_seek
#define c_seek fc._c_seek
Char **a_seek;
} ;
extern int aret; /* What was the last character returned */
#define SEEKEQ(a, b) ((a)->type == (b)->type && \
(a)->f_seek == (b)->f_seek && \
(a)->a_seek == (b)->a_seek)
#define fseekp B.Bfseekp
#define fbobp B.Bfbobp
#define feobp B.Bfeobp
#define fblocks B.Bfblocks
#define fbuf B.Bfbuf
/*
* The shell finds commands in loops by reseeking the input
* For whiles, in particular, it reseeks to the beginning of the
* line the while was on; hence the while placement restrictions.
*/
struct Ain lineloc;
int cantell; /* Is current source tellable ? */
/*
* Input lines are parsed into doubly linked circular
* lists of words of the following form.
*/
struct wordent {
Char *word;
struct wordent *prev;
struct wordent *next;
};
/*
* During word building, both in the initial lexical phase and
* when expanding $ variable substitutions, expansion by `!' and `$'
* must be inhibited when reading ahead in routines which are themselves
* processing `!' and `$' expansion or after characters such as `\' or in
* quotations. The following flags are passed to the getC routines
* telling them which of these substitutions are appropriate for the
* next character to be returned.
*/
#define DODOL 1
#define DOEXCL 2
#define DOALL DODOL|DOEXCL
/*
* Labuf implements a general buffer for lookahead during lexical operations.
* Text which is to be placed in the input stream can be stuck here.
* We stick parsed ahead $ constructs during initial input,
* process id's from `$$', and modified variable values (from qualifiers
* during expansion in sh.dol.c) here.
*/
Char *lap;
/*
* Parser structure
*
* Each command is parsed to a tree of command structures and
* flags are set bottom up during this process, to be propagated down
* as needed during the semantics/execution pass (sh.sem.c).
*/
struct command {
int t_dtyp; /* Type of node */
#define NODE_COMMAND 1 /* t_dcom <t_dlef >t_drit */
#define NODE_PAREN 2 /* ( t_dspr ) <t_dlef >t_drit */
#define NODE_PIPE 3 /* t_dlef | t_drit */
#define NODE_LIST 4 /* t_dlef ; t_drit */
#define NODE_OR 5 /* t_dlef || t_drit */
#define NODE_AND 6 /* t_dlef && t_drit */
int t_dflg; /* Flags, e.g. F_AMPERSAND|... */
#define F_SAVE (F_NICE|F_TIME|F_NOHUP) /* save these when re-doing */
#define F_AMPERSAND (1<<0) /* executes in background */
#define F_APPEND (1<<1) /* output is redirected >> */
#define F_PIPEIN (1<<2) /* input is a pipe */
#define F_PIPEOUT (1<<3) /* output is a pipe */
#define F_NOFORK (1<<4) /* don't fork, last ()ized cmd */
#define F_NOINTERRUPT (1<<5) /* should be immune from intr's */
/* spare */
#define F_STDERR (1<<7) /* redirect unit 2 with unit 1 */
#define F_OVERWRITE (1<<8) /* output was ! */
#define F_READ (1<<9) /* input redirection is << */
#define F_REPEAT (1<<10) /* reexec aft if, repeat,... */
#define F_NICE (1<<11) /* t_nice is meaningful */
#define F_NOHUP (1<<12) /* nohup this command */
#define F_TIME (1<<13) /* time this command */
union {
Char *T_dlef; /* Input redirect word */
struct command *T_dcar; /* Left part of list/pipe */
} L;
union {
Char *T_drit; /* Output redirect word */
struct command *T_dcdr; /* Right part of list/pipe */
} R;
#define t_dlef L.T_dlef
#define t_dcar L.T_dcar
#define t_drit R.T_drit
#define t_dcdr R.T_dcdr
Char **t_dcom; /* Command/argument vector */
struct command *t_dspr; /* Pointer to ()'d subtree */
int t_nice;
};
/*
* These are declared here because they want to be
* initialized in sh.init.c (to allow them to be made readonly)
*/
extern struct biltins {
const char *bname;
void (*bfunct)(Char **, struct command *);
short minargs, maxargs;
} bfunc[];
extern int nbfunc;
extern int nsrchn;
extern struct srch {
const char *s_name;
short s_value;
} srchn[];
/*
* The keywords for the parser
*/
#define T_BREAK 0
#define T_BRKSW 1
#define T_CASE 2
#define T_DEFAULT 3
#define T_ELSE 4
#define T_END 5
#define T_ENDIF 6
#define T_ENDSW 7
#define T_EXIT 8
#define T_FOREACH 9
#define T_GOTO 10
#define T_IF 11
#define T_LABEL 12
#define T_LET 13
#define T_SET 14
#define T_SWITCH 15
#define T_TEST 16
#define T_THEN 17
#define T_WHILE 18
/*
* Structure defining the existing while/foreach loops at this
* source level. Loops are implemented by seeking back in the
* input. For foreach (fe), the word list is attached here.
*/
struct whyle {
struct Ain w_start; /* Point to restart loop */
struct Ain w_end; /* End of loop (0 if unknown) */
Char **w_fe, **w_fe0; /* Current/initial wordlist for fe */
Char *w_fename; /* Name for fe */
struct whyle *w_next; /* Next (more outer) loop */
} *whyles;
/*
* Variable structure
*
* Aliases and variables are stored in AVL balanced binary trees.
*/
struct varent {
Char **vec; /* Array of words which is the value */
Char *v_name; /* Name of variable/alias */
struct varent *v_link[3]; /* The links, see below */
int v_bal; /* Balance factor */
} shvhed, aliases;
#define v_left v_link[0]
#define v_right v_link[1]
#define v_parent v_link[2]
#define adrof(v) adrof1(v, &shvhed)
#define value(v) value1(v, &shvhed)
/*
* The following are for interfacing redo substitution in
* aliases to the lexical routines.
*/
struct wordent *alhistp; /* Argument list (first) */
struct wordent *alhistt; /* Node after last in arg list */
extern Char **alvec, *alvecp; /* The (remnants of) alias vector */
/*
* Filename/command name expansion variables
*/
int gflag; /* After tglob -> is globbing needed? */
#define MAXVARLEN 30 /* Maximum number of char in a variable name */
/*
* Variables for filename expansion
*/
extern long gargc; /* Number args in gargv */
extern Char **gargv; /* Pointer to the (stack) arglist */
/*
* Variables for command expansion.
*/
extern Char **pargv; /* Pointer to the argv list space */
extern long pargc; /* Count of arguments in pargv */
long pnleft; /* Number of chars left in pargs */
Char *pargs; /* Pointer to start current word */
Char *pargcp; /* Current index into pargs */
/*
* History list
*
* Each history list entry contains an embedded wordlist
* from the scanner, a number for the event, and a reference count
* to aid in discarding old entries.
*
* Essentially "invisible" entries are put on the history list
* when history substitution includes modifiers, and thrown away
* at the next discarding since their event numbers are very negative.
*/
struct Hist {
struct wordent Hlex;
int Hnum;
int Href;
struct Hist *Hnext;
} Histlist;
struct wordent paraml; /* Current lexical word list */
int eventno; /* Next events number */
int lastev; /* Last event reference (default) */
Char HIST; /* history invocation character */
Char HISTSUB; /* auto-substitute character */
/*
* strings.h:
*/
#ifndef SHORT_STRINGS
#define Strchr(a, b) strchr(a, b)
#define Strrchr(a, b) strrchr(a, b)
#define Strcat(a, b) strcat(a, b)
#define Strncat(a, b, c) strncat(a, b, c)
#define Strcpy(a, b) strcpy(a, b)
#define Strncpy(a, b, c) strncpy(a, b, c)
#define Strlen(a) strlen(a)
#define Strcmp(a, b) strcmp(a, b)
#define Strncmp(a, b, c) strncmp(a, b, c)
#define Strspl(a, b) strspl(a, b)
#define Strsave(a) strsave(a)
#define Strend(a) strend(a)
#define Strstr(a, b) strstr(a, b)
#define str2short(a) (a)
#define blk2short(a) saveblk(a)
#define short2blk(a) saveblk(a)
#define short2str(a) strip(a)
#else
#define Strchr(a, b) s_strchr(a, b)
#define Strrchr(a, b) s_strrchr(a, b)
#define Strcat(a, b) s_strcat(a, b)
#define Strncat(a, b, c) s_strncat(a, b, c)
#define Strcpy(a, b) s_strcpy(a, b)
#define Strncpy(a, b, c) s_strncpy(a, b, c)
#define Strlen(a) s_strlen(a)
#define Strcmp(a, b) s_strcmp(a, b)
#define Strncmp(a, b, c) s_strncmp(a, b, c)
#define Strspl(a, b) s_strspl(a, b)
#define Strsave(a) s_strsave(a)
#define Strend(a) s_strend(a)
#define Strstr(a, b) s_strstr(a, b)
#endif
/*
* setname is a macro to save space (see sh.err.c)
*/
const char *bname;
#define setname(a) (bname = (a))
Char *Vsav;
Char *Vdp;
Char *Vexpath;
char **Vt;
Char **evalvec;
Char *evalp;
/* word_chars is set by default to WORD_CHARS but can be overridden by
the worchars variable--if unset, reverts to WORD_CHARS */
Char *word_chars;
#define WORD_CHARS "*?_-.[]~=" /* default chars besides alnums in words */
Char *STR_SHELLPATH;
#include <paths.h>
#ifdef _PATH_BSHELL
Char *STR_BSHELL;
#endif
Char *STR_WORD_CHARS;
Char **STR_environ;
#ifdef EDIT
#include <histedit.h>
EditLine *el;
History *hi;
#endif
int editing;
#endif /* !_CSH_H_ */

View File

@@ -1,901 +0,0 @@
/* $NetBSD: dir.c,v 1.30 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)dir.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: dir.c,v 1.30 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "csh.h"
#include "dir.h"
#include "extern.h"
/* Directory management. */
static struct directory *dfind(Char *);
static Char *dfollow(Char *);
static void printdirs(void);
static Char *dgoto(Char *);
static void skipargs(Char ***, const char *);
static void dnewcwd(struct directory *);
static void dset(Char *);
struct directory dhead; /* "head" of loop */
int printd; /* force name to be printed */
static int dirflag = 0;
/*
* dinit - initialize current working directory
*/
void
dinit(Char *hp)
{
static const char emsg[] = "csh: Trying to start from \"%s\"\n";
char path[MAXPATHLEN];
struct directory *dp;
const char *ecp;
Char *cp;
/* Don't believe the login shell home, because it may be a symlink */
ecp = getcwd(path, MAXPATHLEN);
if (ecp == NULL || *ecp == '\0') {
(void)fprintf(csherr, "csh: %s\n", strerror(errno));
if (hp && *hp) {
ecp = short2str(hp);
if (chdir(ecp) == -1)
cp = NULL;
else
cp = Strsave(hp);
(void)fprintf(csherr, emsg, vis_str(hp));
}
else
cp = NULL;
if (cp == NULL) {
(void)fprintf(csherr, emsg, "/");
if (chdir("/") == -1) {
/* I am not even try to print an error message! */
xexit(1);
}
cp = SAVE("/");
}
}
else {
struct stat swd, shp;
/*
* See if $HOME is the working directory we got and use that
*/
if (hp && *hp &&
stat(ecp, &swd) != -1 && stat(short2str(hp), &shp) != -1 &&
swd.st_dev == shp.st_dev && swd.st_ino == shp.st_ino)
cp = Strsave(hp);
else {
const char *cwd;
/*
* use PWD if we have it (for subshells)
*/
if ((cwd = getenv("PWD")) != NULL) {
if (stat(cwd, &shp) != -1 && swd.st_dev == shp.st_dev &&
swd.st_ino == shp.st_ino)
ecp = cwd;
}
cp = dcanon(SAVE(ecp), STRNULL);
}
}
dp = (struct directory *)xcalloc(1, sizeof(struct directory));
dp->di_name = cp;
dp->di_count = 0;
dhead.di_next = dhead.di_prev = dp;
dp->di_next = dp->di_prev = &dhead;
printd = 0;
dnewcwd(dp);
}
static void
dset(Char *dp)
{
Char **vec;
/*
* Don't call set() directly cause if the directory contains ` or
* other junk characters glob will fail.
*/
vec = xmalloc((size_t)(2 * sizeof(Char **)));
vec[0] = Strsave(dp);
vec[1] = 0;
setq(STRcwd, vec, &shvhed);
Setenv(STRPWD, dp);
}
#define DIR_LONG 1
#define DIR_VERT 2
#define DIR_LINE 4
static void
skipargs(Char ***v, const char *str)
{
Char **n, *s;
n = *v;
dirflag = 0;
for (n++; *n != NULL && (*n)[0] == '-'; n++)
for (s = &((*n)[1]); *s; s++)
switch (*s) {
case 'l':
dirflag |= DIR_LONG;
break;
case 'n':
dirflag |= DIR_LINE;
break;
case 'v':
dirflag |= DIR_VERT;
break;
default:
stderror(ERR_DIRUS, vis_str(**v), str);
/* NOTREACHED */
}
*v = n;
}
/*
* dodirs - list all directories in directory loop
*/
void
/*ARGSUSED*/
dodirs(Char **v, struct command *t)
{
skipargs(&v, "");
if (*v != NULL)
stderror(ERR_DIRUS, "dirs", "");
printdirs();
}
static void
printdirs(void)
{
struct directory *dp;
Char *hp, *s;
size_t cur, idx, len;
hp = value(STRhome);
if (*hp == '\0')
hp = NULL;
dp = dcwd;
idx = 0;
cur = 0;
do {
if (dp == &dhead)
continue;
if (dirflag & DIR_VERT) {
(void)fprintf(cshout, "%zu\t", idx++);
cur = 0;
}
if (!(dirflag & DIR_LONG) && hp != NULL && !eq(hp, STRslash) &&
(len = Strlen(hp), Strncmp(hp, dp->di_name, len) == 0) &&
(dp->di_name[len] == '\0' || dp->di_name[len] == '/'))
len = Strlen(s = (dp->di_name + len)) + 2;
else
len = Strlen(s = dp->di_name) + 1;
cur += len;
if ((dirflag & DIR_LINE) && cur >= 80 - 1 && len < 80) {
(void)fprintf(cshout, "\n");
cur = len;
}
(void) fprintf(cshout, "%s%s%c", (s != dp->di_name)? "~" : "",
vis_str(s), (dirflag & DIR_VERT) ? '\n' : ' ');
} while ((dp = dp->di_prev) != dcwd);
if (!(dirflag & DIR_VERT))
(void)fprintf(cshout, "\n");
}
void
dtildepr(Char *home, Char *dir)
{
if (!eq(home, STRslash) && prefix(home, dir))
(void)fprintf(cshout, "~%s", vis_str(dir + Strlen(home)));
else
(void)fprintf(cshout, "%s", vis_str(dir));
}
void
dtilde(void)
{
struct directory *d;
d = dcwd;
do {
if (d == &dhead)
continue;
d->di_name = dcanon(d->di_name, STRNULL);
} while ((d = d->di_prev) != dcwd);
dset(dcwd->di_name);
}
/* dnormalize():
* If the name starts with . or .. then we might need to normalize
* it depending on the symbolic link flags
*/
Char *
dnormalize(Char *cp)
{
#define UC (unsigned char)
#define ISDOT(c) (UC(c)[0] == '.' && ((UC(c)[1] == '\0') || (UC(c)[1] == '/')))
#define ISDOTDOT(c) (UC(c)[0] == '.' && ISDOT(&((c)[1])))
if ((unsigned char) cp[0] == '/')
return (Strsave(cp));
if (adrof(STRignore_symlinks)) {
size_t dotdot = 0;
Char *dp, *cwd;
cwd = xmalloc((size_t)((Strlen(dcwd->di_name) + 3) *
sizeof(Char)));
(void)Strcpy(cwd, dcwd->di_name);
/*
* Ignore . and count ..'s
*/
while (*cp) {
if (ISDOT(cp)) {
if (*++cp)
cp++;
}
else if (ISDOTDOT(cp)) {
dotdot++;
cp += 2;
if (*cp)
cp++;
}
else
break;
}
while (dotdot > 0) {
dp = Strrchr(cwd, '/');
if (dp) {
*dp = '\0';
dotdot--;
}
else
break;
}
if (*cp) {
cwd[dotdot = Strlen(cwd)] = '/';
cwd[dotdot + 1] = '\0';
dp = Strspl(cwd, cp);
xfree((ptr_t) cwd);
return dp;
}
else {
if (!*cwd) {
cwd[0] = '/';
cwd[1] = '\0';
}
return cwd;
}
}
return Strsave(cp);
}
/*
* dochngd - implement chdir command.
*/
void
/*ARGSUSED*/
dochngd(Char **v, struct command *t)
{
struct directory *dp;
Char *cp;
skipargs(&v, " [<dir>]");
printd = 0;
if (*v == NULL) {
if ((cp = value(STRhome)) == NULL || *cp == 0)
stderror(ERR_NAME | ERR_NOHOMEDIR);
if (chdir(short2str(cp)) < 0)
stderror(ERR_NAME | ERR_CANTCHANGE);
cp = Strsave(cp);
}
else if (v[1] != NULL)
stderror(ERR_NAME | ERR_TOOMANY);
else if ((dp = dfind(*v)) != 0) {
char *tmp;
printd = 1;
if (chdir(tmp = short2str(dp->di_name)) < 0)
stderror(ERR_SYSTEM, tmp, strerror(errno));
dcwd->di_prev->di_next = dcwd->di_next;
dcwd->di_next->di_prev = dcwd->di_prev;
dfree(dcwd);
dnewcwd(dp);
return;
}
else
cp = dfollow(*v);
dp = (struct directory *)xcalloc(1, sizeof(struct directory));
dp->di_name = cp;
dp->di_count = 0;
dp->di_next = dcwd->di_next;
dp->di_prev = dcwd->di_prev;
dp->di_prev->di_next = dp;
dp->di_next->di_prev = dp;
dfree(dcwd);
dnewcwd(dp);
}
static Char *
dgoto(Char *cp)
{
Char *dp;
if (*cp != '/') {
Char *p, *q;
size_t cwdlen;
for (p = dcwd->di_name; *p++;)
continue;
if ((cwdlen = (size_t)(p - dcwd->di_name - 1)) == 1) /* root */
cwdlen = 0;
for (p = cp; *p++;)
continue;
dp = xmalloc((size_t)(cwdlen + (size_t)(p - cp) + 1) * sizeof(Char));
for (p = dp, q = dcwd->di_name; (*p++ = *q++) != '\0';)
continue;
if (cwdlen)
p[-1] = '/';
else
p--; /* don't add a / after root */
for (q = cp; (*p++ = *q++) != '\0';)
continue;
xfree((ptr_t) cp);
cp = dp;
dp += cwdlen;
}
else
dp = cp;
cp = dcanon(cp, dp);
return cp;
}
/*
* dfollow - change to arg directory; fall back on cdpath if not valid
*/
static Char *
dfollow(Char *cp)
{
char ebuf[MAXPATHLEN];
struct varent *c;
Char *dp;
int serrno;
cp = globone(cp, G_ERROR);
/*
* if we are ignoring symlinks, try to fix relatives now.
*/
dp = dnormalize(cp);
if (chdir(short2str(dp)) >= 0) {
xfree((ptr_t) cp);
return dgoto(dp);
}
else {
xfree((ptr_t) dp);
if (chdir(short2str(cp)) >= 0)
return dgoto(cp);
serrno = errno;
}
if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp)
&& (c = adrof(STRcdpath))) {
Char **cdp;
Char *p;
Char buf[MAXPATHLEN];
for (cdp = c->vec; *cdp; cdp++) {
for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';)
continue;
dp[-1] = '/';
for (p = cp; (*dp++ = *p++) != '\0';)
continue;
if (chdir(short2str(buf)) >= 0) {
printd = 1;
xfree((ptr_t) cp);
cp = Strsave(buf);
return dgoto(cp);
}
}
}
dp = value(cp);
if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) {
xfree((ptr_t) cp);
cp = Strsave(dp);
printd = 1;
return dgoto(cp);
}
(void)strcpy(ebuf, short2str(cp));
xfree((ptr_t) cp);
stderror(ERR_SYSTEM, ebuf, strerror(serrno));
/* NOTREACHED */
}
/*
* dopushd - push new directory onto directory stack.
* with no arguments exchange top and second.
* with numeric argument (+n) bring it to top.
*/
void
/*ARGSUSED*/
dopushd(Char **v, struct command *t)
{
struct directory *dp;
skipargs(&v, " [<dir>|+<n>]");
printd = 1;
if (*v == NULL) {
char *tmp;
if ((dp = dcwd->di_prev) == &dhead)
dp = dhead.di_prev;
if (dp == dcwd)
stderror(ERR_NAME | ERR_NODIR);
if (chdir(tmp = short2str(dp->di_name)) < 0)
stderror(ERR_SYSTEM, tmp, strerror(errno));
dp->di_prev->di_next = dp->di_next;
dp->di_next->di_prev = dp->di_prev;
dp->di_next = dcwd->di_next;
dp->di_prev = dcwd;
dcwd->di_next->di_prev = dp;
dcwd->di_next = dp;
}
else if (v[1] != NULL)
stderror(ERR_NAME | ERR_TOOMANY);
else if ((dp = dfind(*v)) != NULL) {
char *tmp;
if (chdir(tmp = short2str(dp->di_name)) < 0)
stderror(ERR_SYSTEM, tmp, strerror(errno));
}
else {
Char *ccp;
ccp = dfollow(*v);
dp = (struct directory *)xcalloc(1, sizeof(struct directory));
dp->di_name = ccp;
dp->di_count = 0;
dp->di_prev = dcwd;
dp->di_next = dcwd->di_next;
dcwd->di_next = dp;
dp->di_next->di_prev = dp;
}
dnewcwd(dp);
}
/*
* dfind - find a directory if specified by numeric (+n) argument
*/
static struct directory *
dfind(Char *cp)
{
struct directory *dp;
Char *ep;
int i;
if (*cp++ != '+')
return (0);
for (ep = cp; Isdigit(*ep); ep++)
continue;
if (*ep)
return (0);
i = getn(cp);
if (i <= 0)
return (0);
for (dp = dcwd; i != 0; i--) {
if ((dp = dp->di_prev) == &dhead)
dp = dp->di_prev;
if (dp == dcwd)
stderror(ERR_NAME | ERR_DEEP);
}
return (dp);
}
/*
* dopopd - pop a directory out of the directory stack
* with a numeric argument just discard it.
*/
void
/*ARGSUSED*/
dopopd(Char **v, struct command *t)
{
struct directory *dp, *p = NULL;
skipargs(&v, " [+<n>]");
printd = 1;
if (*v == NULL)
dp = dcwd;
else if (v[1] != NULL)
stderror(ERR_NAME | ERR_TOOMANY);
else if ((dp = dfind(*v)) == 0)
stderror(ERR_NAME | ERR_BADDIR);
if (dp->di_prev == &dhead && dp->di_next == &dhead)
stderror(ERR_NAME | ERR_EMPTY);
if (dp == dcwd) {
char *tmp;
if ((p = dp->di_prev) == &dhead)
p = dhead.di_prev;
if (chdir(tmp = short2str(p->di_name)) < 0)
stderror(ERR_SYSTEM, tmp, strerror(errno));
}
dp->di_prev->di_next = dp->di_next;
dp->di_next->di_prev = dp->di_prev;
if (dp == dcwd)
dnewcwd(p);
else {
printdirs();
}
dfree(dp);
}
/*
* dfree - free the directory (or keep it if it still has ref count)
*/
void
dfree(struct directory *dp)
{
if (dp->di_count != 0) {
dp->di_next = dp->di_prev = 0;
}
else {
xfree((char *) dp->di_name);
xfree((ptr_t) dp);
}
}
/*
* dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
* we are of course assuming that the file system is standardly
* constructed (always have ..'s, directories have links)
*/
Char *
dcanon(Char *cp, Char *p)
{
Char slink[MAXPATHLEN];
char tlink[MAXPATHLEN];
Char *newcp, *sp;
Char *p1, *p2; /* general purpose */
ssize_t cc;
size_t len;
int slash;
/*
* christos: if the path given does not start with a slash prepend cwd. If
* cwd does not start with a path or the result would be too long abort().
*/
if (*cp != '/') {
Char tmpdir[MAXPATHLEN];
p1 = value(STRcwd);
if (p1 == NULL || *p1 != '/')
abort();
if (Strlen(p1) + Strlen(cp) + 1 >= MAXPATHLEN)
abort();
(void)Strcpy(tmpdir, p1);
(void)Strcat(tmpdir, STRslash);
(void)Strcat(tmpdir, cp);
xfree((ptr_t) cp);
cp = p = Strsave(tmpdir);
}
while (*p) { /* for each component */
sp = p; /* save slash address */
while (*++p == '/') /* flush extra slashes */
continue;
if (p != ++sp)
for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';)
continue;
p = sp; /* save start of component */
slash = 0;
while (*++p) /* find next slash or end of path */
if (*p == '/') {
slash = 1;
*p = 0;
break;
}
if (*sp == '\0') { /* if component is null */
if (--sp == cp) /* if path is one char (i.e. /) */
break;
else
*sp = '\0';
} else if (sp[0] == '.' && sp[1] == 0) {
if (slash) {
for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';)
continue;
p = --sp;
}
else if (--sp != cp)
*sp = '\0';
}
else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) {
/*
* We have something like "yyy/xxx/..", where "yyy" can be null or
* a path starting at /, and "xxx" is a single component. Before
* compressing "xxx/..", we want to expand "yyy/xxx", if it is a
* symbolic link.
*/
*--sp = 0; /* form the pathname for readlink */
if (sp != cp && !adrof(STRignore_symlinks) &&
(cc = readlink(short2str(cp), tlink,
sizeof(tlink) - 1)) >= 0) {
tlink[cc] = '\0';
(void)Strcpy(slink, str2short(tlink));
if (slash)
*p = '/';
/*
* Point p to the '/' in "/..", and restore the '/'.
*/
*(p = sp) = '/';
/*
* find length of p
*/
for (p1 = p; *p1++;)
continue;
if (*slink != '/') {
/*
* Relative path, expand it between the "yyy/" and the
* "/..". First, back sp up to the character past "yyy/".
*/
while (*--sp != '/')
continue;
sp++;
*sp = 0;
/*
* New length is "yyy/" + slink + "/.." and rest
*/
p1 = newcp = xmalloc(
(size_t)((sp - cp) + cc + (p1 - p)) * sizeof(Char));
/*
* Copy new path into newcp
*/
for (p2 = cp; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = slink; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
continue;
/*
* Restart canonicalization at expanded "/xxx".
*/
p = sp - cp - 1 + newcp;
}
else {
/*
* New length is slink + "/.." and rest
*/
p1 = newcp = xmalloc(
(size_t)(cc + (p1 - p)) * sizeof(Char));
/*
* Copy new path into newcp
*/
for (p2 = slink; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
continue;
/*
* Restart canonicalization at beginning
*/
p = newcp;
}
xfree((ptr_t) cp);
cp = newcp;
continue; /* canonicalize the link */
}
*sp = '/';
if (sp != cp)
while (*--sp != '/')
continue;
if (slash) {
for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';)
continue;
p = sp;
}
else if (cp == sp)
*++sp = '\0';
else
*sp = '\0';
}
else { /* normal dir name (not . or .. or nothing) */
if (sp != cp && adrof(STRchase_symlinks) &&
!adrof(STRignore_symlinks) &&
(cc = readlink(short2str(cp), tlink, sizeof(tlink)-1)) >= 0) {
tlink[cc] = '\0';
(void)Strcpy(slink, str2short(tlink));
/*
* restore the '/'.
*/
if (slash)
*p = '/';
/*
* point sp to p (rather than backing up).
*/
sp = p;
/*
* find length of p
*/
for (p1 = p; *p1++;)
continue;
if (*slink != '/') {
/*
* Relative path, expand it between the "yyy/" and the
* remainder. First, back sp up to the character past
* "yyy/".
*/
while (*--sp != '/')
continue;
sp++;
*sp = 0;
/*
* New length is "yyy/" + slink + "/.." and rest
*/
p1 = newcp = xmalloc(
(size_t)((sp - cp) + cc + (p1 - p)) * sizeof(Char));
/*
* Copy new path into newcp
*/
for (p2 = cp; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = slink; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
continue;
/*
* Restart canonicalization at expanded "/xxx".
*/
p = sp - cp - 1 + newcp;
}
else {
/*
* New length is slink + the rest
*/
p1 = newcp = xmalloc(
(size_t)(cc + (p1 - p)) * sizeof(Char));
/*
* Copy new path into newcp
*/
for (p2 = slink; (*p1++ = *p2++) != '\0';)
continue;
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
continue;
/*
* Restart canonicalization at beginning
*/
p = newcp;
}
xfree((ptr_t) cp);
cp = newcp;
continue; /* canonicalize the link */
}
if (slash)
*p = '/';
}
}
/*
* fix home...
*/
p1 = value(STRhome);
len = Strlen(p1);
/*
* See if we're not in a subdir of STRhome
*/
if (p1 && *p1 == '/' &&
(Strncmp(p1, cp, len) != 0 || (cp[len] != '/' && cp[len] != '\0'))) {
static ino_t home_ino;
static dev_t home_dev = NODEV;
static Char *home_ptr = NULL;
struct stat statbuf;
/*
* Get dev and ino of STRhome
*/
if (home_ptr != p1 &&
stat(short2str(p1), &statbuf) != -1) {
home_dev = statbuf.st_dev;
home_ino = statbuf.st_ino;
home_ptr = p1;
}
/*
* Start comparing dev & ino backwards
*/
p2 = Strcpy(slink, cp);
for (sp = NULL; *p2 && stat(short2str(p2), &statbuf) != -1;) {
if (statbuf.st_dev == home_dev &&
statbuf.st_ino == home_ino) {
sp = (Char *) - 1;
break;
}
if ((sp = Strrchr(p2, '/')) != NULL)
*sp = '\0';
}
/*
* See if we found it
*/
if (*p2 && sp == (Char *) -1) {
/*
* Use STRhome to make '~' work
*/
newcp = Strspl(p1, cp + Strlen(p2));
xfree((ptr_t) cp);
cp = newcp;
}
}
return cp;
}
/*
* dnewcwd - make a new directory in the loop the current one
*/
static void
dnewcwd(struct directory *dp)
{
dcwd = dp;
dset(dcwd->di_name);
if (printd && !(adrof(STRpushdsilent)))
printdirs();
}

View File

@@ -1,48 +0,0 @@
/* $NetBSD: dir.h,v 1.8 2003/08/07 09:05:04 agc Exp $ */
/*-
* 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. 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.
*
* @(#)dir.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _DIR_H_
#define _DIR_H_
/*
* Structure for entries in directory stack.
*/
struct directory {
struct directory *di_next; /* next in loop */
struct directory *di_prev; /* prev in loop */
unsigned short *di_count; /* refcount of processes */
Char *di_name; /* actual name */
};
struct directory *dcwd; /* the one we are in now */
#endif /* !_DIR_H_ */

View File

@@ -1,968 +0,0 @@
/* $NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)dol.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "csh.h"
#include "extern.h"
/*
* These routines perform variable substitution and quoting via ' and ".
* To this point these constructs have been preserved in the divided
* input words. Here we expand variables and turn quoting via ' and " into
* QUOTE bits on characters (which prevent further interpretation).
* If the `:q' modifier was applied during history expansion, then
* some QUOTEing may have occurred already, so we dont "trim()" here.
*/
static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
static Char *Dcp, **Dvp; /* Input vector for Dreadc */
#define DEOF -1
#define unDgetC(c) Dpeekc = c
#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
/*
* The following variables give the information about the current
* $ expansion, recording the current word position, the remaining
* words within this expansion, the count of remaining words, and the
* information about any : modifier which is being applied.
*/
#define MAXWLEN (BUFSIZE - 4)
#define MAXMOD MAXWLEN /* This cannot overflow */
static Char dolmod[MAXMOD]; /* : modifier character */
static Char *dolp; /* Remaining chars from this word */
static Char **dolnxt; /* Further words */
static int dolcnt; /* Count of further words */
static int dolnmod; /* Number of modifiers */
static int dolmcnt; /* :gx -> 10000, else 1 */
static int dolwcnt; /* :wx -> 10000, else 1 */
static void Dfix2(Char **);
static Char *Dpack(Char *, Char *);
static int Dword(void);
__dead static void dolerror(Char *);
static int DgetC(int);
static void Dgetdol(void);
static void fixDolMod(void);
static void setDolp(Char *);
static void unDredc(int);
static int Dredc(void);
static void Dtestq(int);
/*
* Fix up the $ expansions and quotations in the
* argument list to command t.
*/
void
Dfix(struct command *t)
{
Char *p, **pp;
if (noexec)
return;
/* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
for (pp = t->t_dcom; (p = *pp++) != NULL;)
for (; *p; p++) {
if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
Dfix2(t->t_dcom); /* found one */
blkfree(t->t_dcom);
t->t_dcom = gargv;
gargv = 0;
return;
}
}
}
/*
* $ substitute one word, for i/o redirection
*/
Char *
Dfix1(Char *cp)
{
Char *Dv[2];
if (noexec)
return (0);
Dv[0] = cp;
Dv[1] = NULL;
Dfix2(Dv);
if (gargc != 1) {
setname(vis_str(cp));
stderror(ERR_NAME | ERR_AMBIG);
}
cp = Strsave(gargv[0]);
blkfree(gargv), gargv = 0;
return (cp);
}
/*
* Subroutine to do actual fixing after state initialization.
*/
static void
Dfix2(Char **v)
{
ginit(); /* Initialize glob's area pointers */
Dvp = v;
Dcp = STRNULL; /* Setup input vector for Dreadc */
unDgetC(0);
unDredc(0); /* Clear out any old peeks (at error) */
dolp = 0;
dolcnt = 0; /* Clear out residual $ expands (...) */
while (Dword())
continue;
}
/*
* Pack up more characters in this word
*/
static Char *
Dpack(Char *wbuf, Char *wp)
{
int c;
ptrdiff_t i;
i = MAXWLEN - (wp - wbuf);
for (;;) {
c = DgetC(DODOL);
if (c == '\\') {
c = DgetC(0);
if (c == DEOF) {
unDredc(c);
*wp = 0;
Gcat(STRNULL, wbuf);
return (NULL);
}
if (c == '\n')
c = ' ';
else
c |= QUOTE;
}
if (c == DEOF) {
unDredc(c);
*wp = 0;
Gcat(STRNULL, wbuf);
return (NULL);
}
if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
unDgetC(c);
if (cmap(c, QUOTES))
return (wp);
*wp++ = 0;
Gcat(STRNULL, wbuf);
return (NULL);
}
if (--i <= 0)
stderror(ERR_WTOOLONG);
*wp++ = (Char)c;
}
}
/*
* Get a word. This routine is analogous to the routine
* word() in sh.lex.c for the main lexical input. One difference
* here is that we don't get a newline to terminate our expansion.
* Rather, DgetC will return a DEOF when we hit the end-of-input.
*/
static int
Dword(void)
{
Char wbuf[BUFSIZE], *wp;
int c, c1;
ptrdiff_t i;
int dolflg, done, sofar;
done = 0;
i = MAXWLEN;
sofar = 0;
wp = wbuf;
while (!done) {
done = 1;
c = DgetC(DODOL);
switch (c) {
case DEOF:
if (sofar == 0)
return (0);
/* finish this word and catch the code above the next time */
unDredc(c);
/* FALLTHROUGH */
case '\n':
*wp = 0;
Gcat(STRNULL, wbuf);
return (1);
case ' ':
case '\t':
done = 0;
break;
case '`':
/* We preserve ` quotations which are done yet later */
*wp++ = (Char)c, --i;
/* FALLTHROUGH */
case '\'':
case '"':
/*
* Note that DgetC never returns a QUOTES character from an
* expansion, so only true input quotes will get us here or out.
*/
c1 = c;
dolflg = c1 == '"' ? DODOL : 0;
for (;;) {
c = DgetC(dolflg);
if (c == c1)
break;
if (c == '\n' || c == DEOF)
stderror(ERR_UNMATCHED, c1);
if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))
--wp, ++i;
if (--i <= 0)
stderror(ERR_WTOOLONG);
switch (c1) {
case '"':
/*
* Leave any `s alone for later. Other chars are all
* quoted, thus `...` can tell it was within "...".
*/
*wp++ = (Char)(c == '`' ? '`' : (c | QUOTE));
break;
case '\'':
/* Prevent all further interpretation */
*wp++ = (Char)(c | QUOTE);
break;
case '`':
/* Leave all text alone for later */
*wp++ = (Char)c;
break;
default:
break;
}
}
if (c1 == '`')
*wp++ = '`' /* i--; eliminated */;
sofar = 1;
if ((wp = Dpack(wbuf, wp)) == NULL)
return (1);
else {
i = MAXWLEN - (wp - wbuf);
done = 0;
}
break;
case '\\':
c = DgetC(0); /* No $ subst! */
if (c == '\n' || c == DEOF) {
done = 0;
break;
}
c |= QUOTE;
break;
default:
break;
}
if (done) {
unDgetC(c);
sofar = 1;
if ((wp = Dpack(wbuf, wp)) == NULL)
return (1);
else {
i = MAXWLEN - (wp - wbuf);
done = 0;
}
}
}
/* Really NOTREACHED */
return (0);
}
/*
* Get a character, performing $ substitution unless flag is 0.
* Any QUOTES character which is returned from a $ expansion is
* QUOTEd so that it will not be recognized above.
*/
static int
DgetC(int flag)
{
int c;
top:
if ((c = Dpeekc) != '\0') {
Dpeekc = 0;
return (c);
}
if (lap) {
c = *lap++ & (QUOTE | TRIM);
if (c == 0) {
lap = 0;
goto top;
}
quotspec:
if (cmap(c, QUOTES))
return (c | QUOTE);
return (c);
}
if (dolp) {
if ((c = *dolp++ & (QUOTE | TRIM)) != '\0')
goto quotspec;
if (dolcnt > 0) {
setDolp(*dolnxt++);
--dolcnt;
return (' ');
}
dolp = 0;
}
if (dolcnt > 0) {
setDolp(*dolnxt++);
--dolcnt;
goto top;
}
c = Dredc();
if (c == '$' && flag) {
Dgetdol();
goto top;
}
return (c);
}
static Char *nulvec[] = {0};
static struct varent nulargv = {nulvec, STRargv, { NULL, NULL, NULL }, 0};
static void
dolerror(Char *s)
{
setname(vis_str(s));
stderror(ERR_NAME | ERR_RANGE);
/* NOTREACHED */
}
/*
* Handle the multitudinous $ expansion forms.
* Ugh.
*/
static void
Dgetdol(void)
{
static Char *dolbang = NULL;
Char name[4*MAXVARLEN+1];
Char wbuf[BUFSIZE];
struct varent *vp;
Char *np;
int c, lwb, sc, subscr, upb;
int dimen, bitset;
char tnp;
bitset = 0;
dimen = 0;
lwb = 1;
upb = 0;
subscr = 0;
vp = NULL;
dolnmod = dolmcnt = dolwcnt = 0;
c = sc = DgetC(0);
if (c == '{')
c = DgetC(0); /* sc is { to take } later */
if ((c & TRIM) == '#')
dimen++, c = DgetC(0); /* $# takes dimension */
else if (c == '?')
bitset++, c = DgetC(0); /* $? tests existence */
switch (c) {
case '!':
if (dimen || bitset)
stderror(ERR_SYNTAX);
if (backpid != 0) {
if (dolbang)
xfree((ptr_t)dolbang);
setDolp(dolbang = putn(backpid));
}
goto eatbrac;
case '$':
if (dimen || bitset)
stderror(ERR_SYNTAX);
setDolp(doldol);
goto eatbrac;
case '<' | QUOTE:
if (bitset)
stderror(ERR_NOTALLOWED, "$?<");
if (dimen)
stderror(ERR_NOTALLOWED, "$?#");
for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
*np = (unsigned char)tnp;
if (np >= &wbuf[BUFSIZE - 1])
stderror(ERR_LTOOLONG);
if (tnp == '\n')
break;
}
*np = 0;
/*
* KLUDGE: dolmod is set here because it will cause setDolp to call
* domod and thus to copy wbuf. Otherwise setDolp would use it
* directly. If we saved it ourselves, no one would know when to free
* it. The actual function of the 'q' causes filename expansion not to
* be done on the interpolated value.
*/
dolmod[dolnmod++] = 'q';
dolmcnt = 10000;
setDolp(wbuf);
goto eatbrac;
case DEOF:
case '\n':
stderror(ERR_SYNTAX);
/* NOTREACHED */
case '*':
(void) Strcpy(name, STRargv);
vp = adrof(STRargv);
subscr = -1; /* Prevent eating [...] */
break;
default:
np = name;
if (Isdigit(c)) {
if (dimen)
stderror(ERR_NOTALLOWED, "$#<num>");
subscr = 0;
do {
subscr = subscr * 10 + c - '0';
c = DgetC(0);
} while (Isdigit(c));
unDredc(c);
if (subscr < 0)
stderror(ERR_RANGE);
if (subscr == 0) {
if (bitset) {
dolp = ffile ? STR1 : STR0;
goto eatbrac;
}
if (ffile == 0)
stderror(ERR_DOLZERO);
fixDolMod();
setDolp(ffile);
goto eatbrac;
}
if (bitset)
stderror(ERR_DOLQUEST);
vp = adrof(STRargv);
if (vp == 0) {
vp = &nulargv;
goto eatmod;
}
break;
}
if (!alnum(c))
stderror(ERR_VARALNUM);
for (;;) {
*np++ = (Char)c;
c = DgetC(0);
if (!alnum(c))
break;
if (np >= &name[MAXVARLEN])
stderror(ERR_VARTOOLONG);
}
*np++ = 0;
unDredc(c);
vp = adrof(name);
}
if (bitset) {
dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
goto eatbrac;
}
if (vp == 0) {
np = str2short(getenv(short2str(name)));
if (np) {
fixDolMod();
setDolp(np);
goto eatbrac;
}
udvar(name);
}
c = DgetC(0);
upb = blklen(vp->vec);
if (dimen == 0 && subscr == 0 && c == '[') {
np = name;
for (;;) {
c = DgetC(DODOL); /* Allow $ expand within [ ] */
if (c == ']')
break;
if (c == '\n' || c == DEOF)
stderror(ERR_INCBR);
if (np >= &name[sizeof(name) / sizeof(Char) - 2])
stderror(ERR_VARTOOLONG);
*np++ = (Char)c;
}
*np = 0, np = name;
if (dolp || dolcnt) /* $ exp must end before ] */
stderror(ERR_EXPORD);
if (!*np)
stderror(ERR_SYNTAX);
if (Isdigit(*np)) {
int i;
for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
continue;
if ((i < 0 || i > upb) && !any("-*", *np)) {
dolerror(vp->v_name);
return;
}
lwb = i;
if (!*np)
upb = lwb, np = STRstar;
}
if (*np == '*')
np++;
else if (*np != '-')
stderror(ERR_MISSING, '-');
else {
int i = upb;
np++;
if (Isdigit(*np)) {
i = 0;
while (Isdigit(*np))
i = i * 10 + *np++ - '0';
if (i < 0 || i > upb) {
dolerror(vp->v_name);
return;
}
}
if (i < lwb)
upb = lwb - 1;
else
upb = i;
}
if (lwb == 0) {
if (upb != 0) {
dolerror(vp->v_name);
return;
}
upb = -1;
}
if (*np)
stderror(ERR_SYNTAX);
}
else {
if (subscr > 0) {
if (subscr > upb)
lwb = 1, upb = 0;
else
lwb = upb = subscr;
}
unDredc(c);
}
if (dimen) {
Char *cp = putn(upb - lwb + 1);
addla(cp);
xfree((ptr_t) cp);
}
else {
eatmod:
fixDolMod();
dolnxt = &vp->vec[lwb - 1];
dolcnt = upb - lwb + 1;
}
eatbrac:
if (sc == '{') {
c = Dredc();
if (c != '}')
stderror(ERR_MISSING, '}');
}
}
static void
fixDolMod(void)
{
int c;
c = DgetC(0);
if (c == ':') {
do {
c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
if (c == 'g' || c == 'a') {
if (c == 'g')
dolmcnt = 10000;
else
dolwcnt = 10000;
c = DgetC(0);
}
if ((c == 'g' && dolmcnt != 10000) ||
(c == 'a' && dolwcnt != 10000)) {
if (c == 'g')
dolmcnt = 10000;
else
dolwcnt = 10000;
c = DgetC(0);
}
if (c == 's') { /* [eichin:19910926.0755EST] */
int delimcnt = 2;
int delim = DgetC(0);
dolmod[dolnmod++] = (Char)c;
dolmod[dolnmod++] = (Char)delim;
if (!delim || letter(delim)
|| Isdigit(delim) || any(" \t\n", delim)) {
seterror(ERR_BADSUBST);
break;
}
while ((c = DgetC(0)) != (-1)) {
dolmod[dolnmod++] = (Char)c;
if(c == delim) delimcnt--;
if(!delimcnt) break;
}
if(delimcnt) {
seterror(ERR_BADSUBST);
break;
}
continue;
}
if (!any("htrqxes", c))
stderror(ERR_BADMOD, c);
dolmod[dolnmod++] = (Char)c;
if (c == 'q')
dolmcnt = 10000;
}
while ((c = DgetC(0)) == ':');
unDredc(c);
}
else
unDredc(c);
}
static void
setDolp(Char *cp)
{
Char *dp;
int i;
if (dolnmod == 0 || dolmcnt == 0) {
dolp = cp;
return;
}
dp = cp = Strsave(cp);
for (i = 0; i < dolnmod; i++) {
/* handle s// [eichin:19910926.0510EST] */
if(dolmod[i] == 's') {
int delim;
Char *lhsub, *rhsub, *np;
size_t lhlen = 0, rhlen = 0;
int didmod = 0;
delim = dolmod[++i];
if (!delim || letter(delim)
|| Isdigit(delim) || any(" \t\n", delim)) {
seterror(ERR_BADSUBST);
break;
}
lhsub = &dolmod[++i];
while(dolmod[i] != delim && dolmod[++i]) {
lhlen++;
}
dolmod[i] = 0;
rhsub = &dolmod[++i];
while(dolmod[i] != delim && dolmod[++i]) {
rhlen++;
}
dolmod[i] = 0;
do {
dp = Strstr(cp, lhsub);
if (dp) {
np = xmalloc(
(size_t)((Strlen(cp) + 1 - lhlen + rhlen) *
sizeof(*np)));
(void)Strncpy(np, cp, (size_t)(dp - cp));
(void)Strcpy(np + (dp - cp), rhsub);
(void)Strcpy(np + (dp - cp) + rhlen, dp + lhlen);
xfree((ptr_t) cp);
dp = cp = np;
didmod = 1;
} else {
/* should this do a seterror? */
break;
}
}
while (dolwcnt == 10000);
/*
* restore dolmod for additional words
*/
dolmod[i] = rhsub[-1] = (Char)delim;
if (didmod)
dolmcnt--;
else
break;
} else {
int didmod = 0;
do {
if ((dp = domod(cp, dolmod[i]))) {
didmod = 1;
if (Strcmp(cp, dp) == 0) {
xfree((ptr_t) cp);
cp = dp;
break;
}
else {
xfree((ptr_t) cp);
cp = dp;
}
}
else
break;
}
while (dolwcnt == 10000);
dp = cp;
if (didmod)
dolmcnt--;
else
break;
}
}
if (dp) {
addla(dp);
xfree((ptr_t) dp);
}
else {
addla(cp);
xfree((ptr_t) cp);
}
dolp = STRNULL;
if (seterr)
stderror(ERR_OLD);
}
static void
unDredc(int c)
{
Dpeekrd = c;
}
static int
Dredc(void)
{
int c;
if ((c = Dpeekrd) != '\0') {
Dpeekrd = 0;
return (c);
}
if (Dcp && (c = *Dcp++))
return (c & (QUOTE | TRIM));
if (*Dvp == 0) {
Dcp = 0;
return (DEOF);
}
Dcp = *Dvp++;
return (' ');
}
static void
Dtestq(int c)
{
if (cmap(c, QUOTES))
gflag = 1;
}
/*
* Form a shell temporary file (in unit 0) from the words
* of the shell input up to EOF or a line the same as "term".
* Unit 0 should have been closed before this call.
*/
void
/*ARGSUSED*/
heredoc(Char *term)
{
Char obuf[BUFSIZE], lbuf[BUFSIZE], mbuf[BUFSIZE];
struct timespec tv;
Char *Dv[2], *lbp, *obp, *mbp, **vp;
char *tmp;
int c, ocnt, lcnt, mcnt;
int quoted;
again:
tmp = short2str(shtemp);
if (open(tmp, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600) < 0) {
if (errno == EEXIST) {
if (unlink(tmp) == -1) {
(void)clock_gettime(CLOCK_MONOTONIC, &tv);
mbp = putn((((int)tv.tv_sec) ^
((int)tv.tv_nsec) ^ ((int)getpid())) & 0x00ffffff);
shtemp = Strspl(STRtmpsh, mbp);
xfree((ptr_t)mbp);
}
goto again;
}
stderror(ERR_SYSTEM, tmp, strerror(errno));
}
(void)unlink(tmp); /* 0 0 inode! */
Dv[0] = term;
Dv[1] = NULL;
gflag = 0;
trim(Dv);
rscan(Dv, Dtestq);
quoted = gflag;
ocnt = BUFSIZE;
obp = obuf;
for (;;) {
/*
* Read up a line
*/
lbp = lbuf;
lcnt = BUFSIZE - 4;
for (;;) {
c = readc(1); /* 1 -> Want EOF returns */
if (c < 0 || c == '\n')
break;
if ((c &= TRIM) != '\0') {
*lbp++ = (Char)c;
if (--lcnt < 0) {
setname("<<");
stderror(ERR_NAME | ERR_OVERFLOW);
}
}
}
*lbp = 0;
/*
* Check for EOF or compare to terminator -- before expansion
*/
if (c < 0 || eq(lbuf, term)) {
(void)write(0, short2str(obuf), (size_t)(BUFSIZE - ocnt));
(void)lseek(0, (off_t)0, SEEK_SET);
return;
}
/*
* If term was quoted or -n just pass it on
*/
if (quoted || noexec) {
*lbp++ = '\n';
*lbp = 0;
for (lbp = lbuf; (c = *lbp++) != '\0';) {
*obp++ = (Char)c;
if (--ocnt == 0) {
(void) write(0, short2str(obuf), BUFSIZE);
obp = obuf;
ocnt = BUFSIZE;
}
}
continue;
}
/*
* Term wasn't quoted so variable and then command expand the input
* line
*/
Dcp = lbuf;
Dvp = Dv + 1;
mbp = mbuf;
mcnt = BUFSIZE - 4;
for (;;) {
c = DgetC(DODOL);
if (c == DEOF)
break;
if ((c &= TRIM) == 0)
continue;
/* \ quotes \ $ ` here */
if (c == '\\') {
c = DgetC(0);
if (!any("$\\`", c))
unDgetC(c | QUOTE), c = '\\';
else
c |= QUOTE;
}
*mbp++ = (Char)c;
if (--mcnt == 0) {
setname("<<");
stderror(ERR_NAME | ERR_OVERFLOW);
}
}
*mbp++ = 0;
/*
* If any ` in line do command substitution
*/
mbp = mbuf;
if (any(short2str(mbp), '`')) {
/*
* 1 arg to dobackp causes substitution to be literal. Words are
* broken only at newlines so that all blanks and tabs are
* preserved. Blank lines (null words) are not discarded.
*/
vp = dobackp(mbuf, 1);
}
else
/* Setup trivial vector similar to return of dobackp */
Dv[0] = mbp, Dv[1] = NULL, vp = Dv;
/*
* Resurrect the words from the command substitution each separated by
* a newline. Note that the last newline of a command substitution
* will have been discarded, but we put a newline after the last word
* because this represents the newline after the last input line!
*/
for (; *vp; vp++) {
for (mbp = *vp; *mbp; mbp++) {
*obp++ = *mbp & TRIM;
if (--ocnt == 0) {
(void)write(0, short2str(obuf), BUFSIZE);
obp = obuf;
ocnt = BUFSIZE;
}
}
*obp++ = '\n';
if (--ocnt == 0) {
(void)write(0, short2str(obuf), BUFSIZE);
obp = obuf;
ocnt = BUFSIZE;
}
}
if (pargv)
blkfree(pargv), pargv = 0;
}
}

View File

@@ -1,388 +0,0 @@
/* $NetBSD: err.c,v 1.21 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: err.c,v 1.21 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include "csh.h"
#include "extern.h"
char *seterr = NULL; /* Holds last error if there was one */
#define ERR_FLAGS ((int)0xf0000000)
#define ERR_NAME 0x10000000
#define ERR_SILENT 0x20000000
#define ERR_OLD 0x40000000
static const char *errorlist[] =
{
#define ERR_SYNTAX 0
"Syntax Error",
#define ERR_NOTALLOWED 1
"%s is not allowed",
#define ERR_WTOOLONG 2
"Word too long",
#define ERR_LTOOLONG 3
"$< line too long",
#define ERR_DOLZERO 4
"No file for $0",
#define ERR_DOLQUEST 5
"$? not allowed here",
#define ERR_INCBR 6
"Incomplete [] modifier",
#define ERR_EXPORD 7
"$ expansion must end before ]",
#define ERR_BADMOD 8
"Bad : modifier in $ (%c)",
#define ERR_SUBSCRIPT 9
"Subscript error",
#define ERR_BADNUM 10
"Badly formed number",
#define ERR_NOMORE 11
"No more words",
#define ERR_FILENAME 12
"Missing file name",
#define ERR_GLOB 13
"Internal glob error",
#define ERR_COMMAND 14
"Command not found",
#define ERR_TOOFEW 15
"Too few arguments",
#define ERR_TOOMANY 16
"Too many arguments",
#define ERR_DANGER 17
"Too dangerous to alias that",
#define ERR_EMPTYIF 18
"Empty if",
#define ERR_IMPRTHEN 19
"Improper then",
#define ERR_NOPAREN 20
"Words not parenthesized",
#define ERR_NOTFOUND 21
"%s not found",
#define ERR_MASK 22
"Improper mask",
#define ERR_LIMIT 23
"No such limit",
#define ERR_TOOLARGE 24
"Argument too large",
#define ERR_SCALEF 25
"Improper or unknown scale factor",
#define ERR_UNDVAR 26
"Undefined variable",
#define ERR_DEEP 27
"Directory stack not that deep",
#define ERR_BADSIG 28
"Bad signal number",
#define ERR_UNKSIG 29
"Unknown signal; kill -l lists signals",
#define ERR_VARBEGIN 30
"Variable name must begin with a letter",
#define ERR_VARTOOLONG 31
"Variable name too long",
#define ERR_VARALNUM 32
"Variable name must contain alphanumeric characters",
#define ERR_JOBCONTROL 33
"No job control in this shell",
#define ERR_EXPRESSION 34
"Expression Syntax",
#define ERR_NOHOMEDIR 35
"No home directory",
#define ERR_CANTCHANGE 36
"Can't change to home directory",
#define ERR_NULLCOM 37
"Invalid null command",
#define ERR_ASSIGN 38
"Assignment missing expression",
#define ERR_UNKNOWNOP 39
"Unknown operator",
#define ERR_AMBIG 40
"Ambiguous",
#define ERR_EXISTS 41
"%s: File exists",
#define ERR_INTR 42
"Interrupted",
#define ERR_RANGE 43
"Subscript out of range",
#define ERR_OVERFLOW 44
"Line overflow",
#define ERR_VARMOD 45
"Unknown variable modifier",
#define ERR_NOSUCHJOB 46
"No such job",
#define ERR_TERMINAL 47
"Can't from terminal",
#define ERR_NOTWHILE 48
"Not in while/foreach",
#define ERR_NOPROC 49
"No more processes",
#define ERR_NOMATCH 50
"No match",
#define ERR_MISSING 51
"Missing %c",
#define ERR_UNMATCHED 52
"Unmatched %c",
#define ERR_NOMEM 53
"Out of memory",
#define ERR_PIPE 54
"Can't make pipe",
#define ERR_SYSTEM 55
"%s: %s",
#define ERR_STRING 56
"%s",
#define ERR_JOBS 57
"usage: jobs [ -l ]",
#define ERR_JOBARGS 58
"Arguments should be jobs or process id's",
#define ERR_JOBCUR 59
"No current job",
#define ERR_JOBPREV 60
"No previous job",
#define ERR_JOBPAT 61
"No job matches pattern",
#define ERR_NESTING 62
"Fork nesting > %d; maybe `...` loop",
#define ERR_JOBCTRLSUB 63
"No job control in subshells",
#define ERR_BADPLPS 64
"Badly placed ()'s",
#define ERR_STOPPED 65
"%sThere are suspended jobs",
#define ERR_NODIR 66
"No other directory",
#define ERR_EMPTY 67
"Directory stack empty",
#define ERR_BADDIR 68
"Bad directory",
#define ERR_DIRUS 69
"usage: %s [-lvn]%s",
#define ERR_HFLAG 70
"No operand for -h flag",
#define ERR_NOTLOGIN 71
"Not a login shell",
#define ERR_DIV0 72
"Division by 0",
#define ERR_MOD0 73
"Mod by 0",
#define ERR_BADSCALE 74
"Bad scaling; did you mean \"%s\"?",
#define ERR_SUSPLOG 75
"Can't suspend a login shell (yet)",
#define ERR_UNKUSER 76
"Unknown user: %s",
#define ERR_NOHOME 77
"No $home variable set",
#define ERR_HISTUS 78
"usage: history [-rh] [# number of events]",
#define ERR_SPDOLLT 79
"$, ! or < not allowed with $# or $?",
#define ERR_NEWLINE 80
"Newline in variable name",
#define ERR_SPSTAR 81
"* not allowed with $# or $?",
#define ERR_DIGIT 82
"$?<digit> or $#<digit> not allowed",
#define ERR_VARILL 83
"Illegal variable name",
#define ERR_NLINDEX 84
"Newline in variable index",
#define ERR_EXPOVFL 85
"Expansion buffer overflow",
#define ERR_VARSYN 86
"Variable syntax",
#define ERR_BADBANG 87
"Bad ! form",
#define ERR_NOSUBST 88
"No previous substitute",
#define ERR_BADSUBST 89
"Bad substitute",
#define ERR_LHS 90
"No previous left hand side",
#define ERR_RHSLONG 91
"Right hand side too long",
#define ERR_BADBANGMOD 92
"Bad ! modifier: %c",
#define ERR_MODFAIL 93
"Modifier failed",
#define ERR_SUBOVFL 94
"Substitution buffer overflow",
#define ERR_BADBANGARG 95
"Bad ! arg selector",
#define ERR_NOSEARCH 96
"No prev search",
#define ERR_NOEVENT 97
"%s: Event not found",
#define ERR_TOOMANYRP 98
"Too many )'s",
#define ERR_TOOMANYLP 99
"Too many ('s",
#define ERR_BADPLP 100
"Badly placed (",
#define ERR_MISRED 101
"Missing name for redirect",
#define ERR_OUTRED 102
"Ambiguous output redirect",
#define ERR_REDPAR 103
"Can't << within ()'s",
#define ERR_INRED 104
"Ambiguous input redirect",
#define ERR_ALIASLOOP 105
"Alias loop",
#define ERR_HISTLOOP 106
"!# History loop",
#define ERR_ARCH 107
"%s: %s. Wrong Architecture",
#define ERR_FILEINQ 108
"Malformed file inquiry",
#define ERR_SELOVFL 109
"Selector overflow",
#define ERR_INVALID 110
"Invalid Error"
};
/*
* The parser and scanner set up errors for later by calling seterr,
* which sets the variable err as a side effect; later to be tested,
* e.g. in process.
*/
void
seterror(int id, ...)
{
if (seterr == 0) {
char berr[BUFSIZE];
va_list va;
va_start(va, id);
if (id < 0 || id >= (int)(sizeof(errorlist) / sizeof(errorlist[0])) - 1)
id = ERR_INVALID;
(void)vsnprintf(berr, sizeof(berr), errorlist[id], va);
va_end(va);
seterr = strsave(berr);
}
}
/*
* Print the error with the given id.
*
* Special ids:
* ERR_SILENT: Print nothing.
* ERR_OLD: Print the previously set error if one was there.
* otherwise return.
* ERR_NAME: If this bit is set, print the name of the function
* in bname
*
* This routine always resets or exits. The flag haderr
* is set so the routine who catches the unwind can propogate
* it if they want.
*
* Note that any open files at the point of error will eventually
* be closed in the routine process in sh.c which is the only
* place error unwinds are ever caught.
*/
void
stderror(int id, ...)
{
va_list va;
Char **v;
int flags;
flags = id & ERR_FLAGS;
id &= ~ERR_FLAGS;
if ((flags & ERR_OLD) && seterr == NULL)
abort();
if (id < 0 || id > (int)(sizeof(errorlist) / sizeof(errorlist[0])))
id = ERR_INVALID;
(void)fflush(cshout);
(void)fflush(csherr);
haderr = 1; /* Now to diagnostic output */
timflg = 0; /* This isn't otherwise reset */
if (!(flags & ERR_SILENT)) {
if (flags & ERR_NAME)
(void)fprintf(csherr, "%s: ", bname);
if ((flags & ERR_OLD))
/* Old error. */
(void)fprintf(csherr, "%s.\n", seterr);
else {
va_start(va, id);
(void)vfprintf(csherr, errorlist[id], va);
va_end(va);
(void)fprintf(csherr, ".\n");
}
}
if (seterr) {
xfree((ptr_t) seterr);
seterr = NULL;
}
if ((v = pargv) != NULL)
pargv = 0, blkfree(v);
if ((v = gargv) != NULL)
gargv = 0, blkfree(v);
(void)fflush(cshout);
(void)fflush(csherr);
didfds = 0; /* Forget about 0,1,2 */
/*
* Go away if -e or we are a child shell
*/
if (exiterr || child)
xexit(1);
/*
* Reset the state of the input. This buffered seek to end of file will
* also clear the while/foreach stack.
*/
btoeof();
set(STRstatus, Strsave(STR1));
if (tpgrp > 0)
(void)tcsetpgrp(FSHTTY, tpgrp);
reset(); /* Unwind */
}

View File

@@ -1,746 +0,0 @@
/* $NetBSD: exec.c,v 1.29 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)exec.c 8.3 (Berkeley) 5/23/95";
#else
__RCSID("$NetBSD: exec.c,v 1.29 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "csh.h"
#include "extern.h"
/*
* System level search and execute of a command. We look in each directory
* for the specified command name. If the name contains a '/' then we
* execute only the full path name. If there is no search path then we
* execute only full path names.
*/
extern char **environ;
/*
* As we search for the command we note the first non-trivial error
* message for presentation to the user. This allows us often
* to show that a file has the wrong mode/no access when the file
* is not in the last component of the search path, so we must
* go on after first detecting the error.
*/
static const char *exerr; /* Execution error message */
static Char *expath; /* Path for exerr */
/*
* Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
* to hash execs. If it is allocated (havhash true), then to tell
* whether ``name'' is (possibly) present in the i'th component
* of the variable path, you look at the bit in xhash indexed by
* hash(hashname("name"), i). This is setup automatically
* after .login is executed, and recomputed whenever ``path'' is
* changed.
* The two part hash function is designed to let texec() call the
* more expensive hashname() only once and the simple hash() several
* times (once for each path component checked).
* Byte size is assumed to be 8.
*/
#define HSHSIZ 8192 /* 1k bytes */
#define HSHMASK (HSHSIZ - 1)
#define HSHMUL 243
static unsigned char xhash[HSHSIZ / 8];
#define hash(a, b) (((a) * HSHMUL + (b)) & HSHMASK)
#define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
#define bis(h, b) ((h)[(b) >> 3] |= (unsigned char)(1 << ((b) & 7))) /* bit set */
static int hits, misses;
/* Dummy search path for just absolute search when no path */
static Char *justabs[] = {STRNULL, 0};
static void pexerr(void) __dead;
static void texec(Char *, Char **);
static int hashname(Char *);
static int tellmewhat(struct wordent *, Char *);
static int executable(Char *, Char *, int);
static int iscommand(Char *);
void
/*ARGSUSED*/
doexec(Char **v, struct command *t)
{
struct varent *pathv;
Char *blk[2], **av, *dp, **pv, *sav;
int i, hashval, hashval1;
sigset_t nsigset;
int slash;
hashval = 0;
/*
* Glob the command name. We will search $path even if this does something,
* as in sh but not in csh. One special case: if there is no PATH, then we
* execute only commands which start with '/'.
*/
blk[0] = t->t_dcom[0];
blk[1] = 0;
gflag = 0, tglob(blk);
if (gflag) {
pv = globall(blk);
if (pv == 0) {
setname(vis_str(blk[0]));
stderror(ERR_NAME | ERR_NOMATCH);
}
gargv = 0;
}
else
pv = saveblk(blk);
trim(pv);
exerr = 0;
expath = Strsave(pv[0]);
Vexpath = expath;
pathv = adrof(STRpath);
if (pathv == 0 && expath[0] != '/') {
blkfree(pv);
pexerr();
}
slash = any(short2str(expath), '/');
/*
* Glob the argument list, if necessary. Otherwise trim off the quote bits.
*/
gflag = 0;
av = &t->t_dcom[1];
tglob(av);
if (gflag) {
av = globall(av);
if (av == 0) {
blkfree(pv);
setname(vis_str(expath));
stderror(ERR_NAME | ERR_NOMATCH);
}
gargv = 0;
}
else
av = saveblk(av);
blkfree(t->t_dcom);
t->t_dcom = blkspl(pv, av);
xfree((ptr_t) pv);
xfree((ptr_t) av);
av = t->t_dcom;
trim(av);
if (*av == NULL || **av == '\0')
pexerr();
xechoit(av); /* Echo command if -x */
/*
* Since all internal file descriptors are set to close on exec, we don't
* need to close them explicitly here. Just reorient ourselves for error
* messages.
*/
SHIN = 0;
SHOUT = 1;
SHERR = 2;
OLDSTD = 0;
/*
* We must do this AFTER any possible forking (like `foo` in glob) so that
* this shell can still do subprocesses.
*/
sigemptyset(&nsigset);
(void)sigprocmask(SIG_SETMASK, &nsigset, NULL);
/*
* If no path, no words in path, or a / in the filename then restrict the
* command search.
*/
if (pathv == 0 || pathv->vec[0] == 0 || slash)
pv = justabs;
else
pv = pathv->vec;
sav = Strspl(STRslash, *av); /* / command name for postpending */
Vsav = sav;
if (havhash)
hashval = hashname(*av);
i = 0;
hits++;
do {
/*
* Try to save time by looking at the hash table for where this command
* could be. If we are doing delayed hashing, then we put the names in
* one at a time, as the user enters them. This is kinda like Korn
* Shell's "tracked aliases".
*/
if (!slash && pv[0][0] == '/' && havhash) {
hashval1 = hash(hashval, i);
if (!bit(xhash, hashval1))
goto cont;
}
if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
texec(*av, av);
else {
dp = Strspl(*pv, sav);
Vdp = dp;
texec(dp, av);
Vdp = 0;
xfree((ptr_t)dp);
}
misses++;
cont:
pv++;
i++;
} while (*pv);
hits--;
Vsav = 0;
xfree((ptr_t)sav);
pexerr();
/* NOTREACHED */
}
static void
pexerr(void)
{
/* Couldn't find the damn thing */
if (expath) {
setname(vis_str(expath));
Vexpath = 0;
xfree((ptr_t)expath);
expath = 0;
}
else
setname("");
if (exerr)
stderror(ERR_NAME | ERR_STRING, exerr);
else
stderror(ERR_NAME | ERR_COMMAND);
/* NOTREACHED */
}
/*
* Execute command f, arg list t.
* Record error message if not found.
* Also do shell scripts here.
*/
static void
texec(Char *sf, Char **st)
{
struct varent *v;
Char *lastsh[2], **vp, *st0, **ost;
char *f, **t;
int fd;
unsigned char c = '\0';
/* The order for the conversions is significant */
t = short2blk(st);
f = short2str(sf);
Vt = t;
errno = 0; /* don't use a previous error */
(void)execve(f, t, environ);
Vt = 0;
blkfree((Char **)t);
switch (errno) {
case ENOEXEC:
/*
* From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute
* it, don't feed it to the shell if it looks like a binary!
*/
if ((fd = open(f, O_RDONLY)) != -1) {
if (read(fd, (char *)&c, 1) == 1) {
if (!Isprint(c) && (c != '\n' && c != '\t')) {
(void)close(fd);
/*
* We *know* what ENOEXEC means.
*/
stderror(ERR_ARCH, f, strerror(errno));
}
}
#ifdef _PATH_BSHELL
else
c = '#';
#endif
(void)close(fd);
}
/*
* If there is an alias for shell, then put the words of the alias in
* front of the argument list replacing the command name. Note no
* interpretation of the words at this point.
*/
v = adrof1(STRshell, &aliases);
if (v == 0) {
vp = lastsh;
vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH;
vp[1] = NULL;
#ifdef _PATH_BSHELL
if (fd != -1 && c != '#')
vp[0] = STR_BSHELL;
#endif
}
else
vp = v->vec;
st0 = st[0];
st[0] = sf;
ost = st;
st = blkspl(vp, st); /* Splice up the new arglst */
ost[0] = st0;
sf = *st;
/* The order for the conversions is significant */
t = short2blk(st);
f = short2str(sf);
xfree((ptr_t) st);
Vt = t;
(void)execve(f, t, environ);
Vt = 0;
blkfree((Char **) t);
/* FALLTHROUGH */
case ENOMEM:
stderror(ERR_SYSTEM, f, strerror(errno));
/* NOTREACHED */
case ENOENT:
break;
default:
if (exerr == 0) {
exerr = strerror(errno);
if (expath)
xfree((ptr_t) expath);
expath = Strsave(sf);
Vexpath = expath;
}
}
}
/*ARGSUSED*/
void
execash(Char **t, struct command *kp)
{
jmp_buf osetexit;
sig_t osigint, osigquit, osigterm;
int my_reenter, odidfds, oOLDSTD, oSHERR, oSHIN, oSHOUT;
int saveDIAG, saveIN, saveOUT, saveSTD;
if (chkstop == 0 && setintr)
panystop(0);
/*
* Hmm, we don't really want to do that now because we might
* fail, but what is the choice
*/
rechist();
osigint = signal(SIGINT, parintr);
osigquit = signal(SIGQUIT, parintr);
osigterm = signal(SIGTERM, parterm);
odidfds = didfds;
oSHIN = SHIN;
oSHOUT = SHOUT;
oSHERR = SHERR;
oOLDSTD = OLDSTD;
saveIN = dcopy(SHIN, -1);
saveOUT = dcopy(SHOUT, -1);
saveDIAG = dcopy(SHERR, -1);
saveSTD = dcopy(OLDSTD, -1);
lshift(kp->t_dcom, 1);
getexit(osetexit);
if ((my_reenter = setexit()) == 0) {
SHIN = dcopy(0, -1);
SHOUT = dcopy(1, -1);
SHERR = dcopy(2, -1);
didfds = 0;
doexec(t, kp);
}
(void)signal(SIGINT, osigint);
(void)signal(SIGQUIT, osigquit);
(void)signal(SIGTERM, osigterm);
doneinp = 0;
didfds = odidfds;
(void)close(SHIN);
(void)close(SHOUT);
(void)close(SHERR);
(void)close(OLDSTD);
SHIN = dmove(saveIN, oSHIN);
SHOUT = dmove(saveOUT, oSHOUT);
SHERR = dmove(saveDIAG, oSHERR);
OLDSTD = dmove(saveSTD, oOLDSTD);
resexit(osetexit);
if (my_reenter)
stderror(ERR_SILENT);
}
void
xechoit(Char **t)
{
if (adrof(STRecho)) {
int odidfds = didfds;
(void)fflush(csherr);
odidfds = didfds;
didfds = 0;
blkpr(csherr, t);
(void)fputc('\n', csherr);
(void)fflush(csherr);
didfds = odidfds;
}
}
void
/*ARGSUSED*/
dohash(Char **v, struct command *t)
{
struct dirent *dp;
struct varent *pathv;
DIR *dirp;
Char **pv;
size_t cnt;
int hashval, i;
i = 0;
havhash = 1;
pathv = adrof(STRpath);
for (cnt = 0; cnt < sizeof xhash; cnt++)
xhash[cnt] = 0;
if (pathv == 0)
return;
for (pv = pathv->vec; *pv; pv++, i++) {
if (pv[0][0] != '/')
continue;
dirp = opendir(short2str(*pv));
if (dirp == NULL)
continue;
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_ino == 0)
continue;
if (dp->d_name[0] == '.' &&
(dp->d_name[1] == '\0' ||
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
continue;
hashval = hash(hashname(str2short(dp->d_name)), i);
bis(xhash, hashval);
/* tw_add_comm_name (dp->d_name); */
}
(void) closedir(dirp);
}
}
void
/*ARGSUSED*/
dounhash(Char **v, struct command *t)
{
havhash = 0;
}
void
/*ARGSUSED*/
hashstat(Char **v, struct command *t)
{
if (hits + misses)
(void)fprintf(cshout, "%d hits, %d misses, %d%%\n",
hits, misses, 100 * hits / (hits + misses));
}
/*
* Hash a command name.
*/
static int
hashname(Char *cp)
{
long h = 0;
while (*cp)
h = hash(h, *cp++);
return ((int) h);
}
static int
iscommand(Char *name)
{
struct varent *v;
Char **pv, *sav;
int hashval, hashval1, i;
int slash;
hashval = 0;
slash = any(short2str(name), '/');
v = adrof(STRpath);
if (v == 0 || v->vec[0] == 0 || slash)
pv = justabs;
else
pv = v->vec;
sav = Strspl(STRslash, name); /* / command name for postpending */
if (havhash)
hashval = hashname(name);
i = 0;
do {
if (!slash && pv[0][0] == '/' && havhash) {
hashval1 = hash(hashval, i);
if (!bit(xhash, hashval1))
goto cont;
}
if (pv[0][0] == 0 || eq(pv[0], STRdot)) { /* don't make ./xxx */
if (executable(NULL, name, 0)) {
xfree((ptr_t) sav);
return i + 1;
}
}
else {
if (executable(*pv, sav, 0)) {
xfree((ptr_t) sav);
return i + 1;
}
}
cont:
pv++;
i++;
} while (*pv);
xfree((ptr_t) sav);
return 0;
}
/* Also by:
* Andreas Luik <luik@isaak.isa.de>
* I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
* Azenberstr. 35
* D-7000 Stuttgart 1
* West-Germany
* is the executable() routine below and changes to iscommand().
* Thanks again!!
*/
/*
* executable() examines the pathname obtained by concatenating dir and name
* (dir may be NULL), and returns 1 either if it is executable by us, or
* if dir_ok is set and the pathname refers to a directory.
* This is a bit kludgy, but in the name of optimization...
*/
static int
executable(Char *dir, Char *name, int dir_ok)
{
struct stat stbuf;
Char path[MAXPATHLEN + 1], *dp, *sp;
char *strname;
if (dir && *dir) {
for (dp = path, sp = dir; *sp; *dp++ = *sp++)
if (dp == &path[MAXPATHLEN + 1]) {
*--dp = '\0';
break;
}
for (sp = name; *sp; *dp++ = *sp++)
if (dp == &path[MAXPATHLEN + 1]) {
*--dp = '\0';
break;
}
*dp = '\0';
strname = short2str(path);
}
else
strname = short2str(name);
return (stat(strname, &stbuf) != -1 && ((S_ISREG(stbuf.st_mode) &&
/* save time by not calling access() in the hopeless case */
(stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
access(strname, X_OK) == 0) || (dir_ok && S_ISDIR(stbuf.st_mode))));
}
/* The dowhich() is by:
* Andreas Luik <luik@isaak.isa.de>
* I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
* Azenberstr. 35
* D-7000 Stuttgart 1
* West-Germany
* Thanks!!
*/
/*ARGSUSED*/
void
dowhich(Char **v, struct command *c)
{
struct wordent lexw[3];
struct varent *vp;
lexw[0].next = &lexw[1];
lexw[1].next = &lexw[2];
lexw[2].next = &lexw[0];
lexw[0].prev = &lexw[2];
lexw[1].prev = &lexw[0];
lexw[2].prev = &lexw[1];
lexw[0].word = STRNULL;
lexw[2].word = STRret;
while (*++v) {
if ((vp = adrof1(*v, &aliases)) != NULL) {
(void)fprintf(cshout, "%s: \t aliased to ", vis_str(*v));
blkpr(cshout, vp->vec);
(void)fputc('\n', cshout);
set(STRstatus, Strsave(STR0));
}
else {
lexw[1].word = *v;
set(STRstatus, Strsave(tellmewhat(lexw, NULL) ? STR0 : STR1));
}
}
}
static int
tellmewhat(struct wordent *lexp, Char *str)
{
struct biltins *bptr;
struct wordent *sp;
Char *cmd, *s0, *s1, *s2;
int i;
int aliased, found;
Char qc;
aliased = 0;
sp = lexp->next;
if (adrof1(sp->word, &aliases)) {
alias(lexp);
sp = lexp->next;
aliased = 1;
}
s0 = sp->word; /* to get the memory freeing right... */
/* handle quoted alias hack */
if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
(sp->word)++;
/* do quoting, if it hasn't been done */
s1 = s2 = sp->word;
while (*s2)
switch (*s2) {
case '\'':
case '"':
qc = *s2++;
while (*s2 && *s2 != qc)
*s1++ = (Char)(*s2++ | QUOTE);
if (*s2)
s2++;
break;
case '\\':
if (*++s2)
*s1++ = (Char)(*s2++ | QUOTE);
break;
default:
*s1++ = *s2++;
}
*s1 = '\0';
for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
if (eq(sp->word, str2short(bptr->bname))) {
if (str == NULL) {
if (aliased)
prlex(cshout, lexp);
(void)fprintf(cshout, "%s: shell built-in command.\n",
vis_str(sp->word));
}
else
(void)Strcpy(str, sp->word);
sp->word = s0; /* we save and then restore this */
return 1;
}
}
sp->word = cmd = globone(sp->word, G_IGNORE);
if ((i = iscommand(sp->word)) != 0) {
Char **pv;
struct varent *v;
int slash = any(short2str(sp->word), '/');
v = adrof(STRpath);
if (v == 0 || v->vec[0] == 0 || slash)
pv = justabs;
else
pv = v->vec;
while (--i)
pv++;
if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
if (!slash) {
sp->word = Strspl(STRdotsl, sp->word);
prlex(cshout, lexp);
xfree((ptr_t) sp->word);
}
else
prlex(cshout, lexp);
}
else {
s1 = Strspl(*pv, STRslash);
sp->word = Strspl(s1, sp->word);
xfree((ptr_t) s1);
if (str == NULL)
prlex(cshout, lexp);
else
(void)Strcpy(str, sp->word);
xfree((ptr_t) sp->word);
}
found = 1;
}
else {
if (str == NULL) {
if (aliased)
prlex(cshout, lexp);
(void)fprintf(csherr,
"%s: Command not found.\n", vis_str(sp->word));
}
else
(void)Strcpy(str, sp->word);
found = 0;
}
sp->word = s0; /* we save and then restore this */
xfree((ptr_t) cmd);
return found;
}

View File

@@ -1,661 +0,0 @@
/* $NetBSD: exp.c,v 1.20 2009/02/14 07:12:29 lukem Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: exp.c,v 1.20 2009/02/14 07:12:29 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef SHORT_STRINGS
#include <string.h>
#endif /* SHORT_STRINGS */
#include "csh.h"
#include "extern.h"
#define IGNORE 1 /* in ignore, it means to ignore value, just parse */
#define NOGLOB 2 /* in ignore, it means not to globone */
#define ADDOP 1
#define MULOP 2
#define EQOP 4
#define RELOP 8
#define RESTOP 16
#define ANYOP 31
#define EQEQ 1
#define GTR 2
#define LSS 4
#define NOTEQ 6
#define EQMATCH 7
#define NOTEQMATCH 8
static int exp1(Char ***, int);
static int csh_exp2(Char ***, int);
static int exp2a(Char ***, int);
static int exp2b(Char ***, int);
static int exp2c(Char ***, int);
static Char *exp3(Char ***, int);
static Char *exp3a(Char ***, int);
static Char *exp4(Char ***, int);
static Char *exp5(Char ***, int);
static Char *exp6(Char ***, int);
static void evalav(Char **);
static int isa(Char *, int);
static int egetn(Char *);
#ifdef EDEBUG
static void etracc(char *, Char *, Char ***);
static void etraci(char *, int, Char ***);
#endif
int
expr(Char ***vp)
{
return (exp0(vp, 0));
}
int
exp0(Char ***vp, int ignore)
{
int p1;
p1 = exp1(vp, ignore);
#ifdef EDEBUG
etraci("exp0 p1", p1, vp);
#endif
if (**vp && eq(**vp, STRor2)) {
int p2;
(*vp)++;
p2 = exp0(vp, (ignore & IGNORE) || p1);
#ifdef EDEBUG
etraci("exp0 p2", p2, vp);
#endif
return (p1 || p2);
}
return (p1);
}
static int
exp1(Char ***vp, int ignore)
{
int p1;
p1 = csh_exp2(vp, ignore);
#ifdef EDEBUG
etraci("exp1 p1", p1, vp);
#endif
if (**vp && eq(**vp, STRand2)) {
int p2;
(*vp)++;
p2 = exp1(vp, (ignore & IGNORE) || !p1);
#ifdef EDEBUG
etraci("exp1 p2", p2, vp);
#endif
return (p1 && p2);
}
return (p1);
}
static int
csh_exp2(Char ***vp, int ignore)
{
int p1;
p1 = exp2a(vp, ignore);
#ifdef EDEBUG
etraci("exp3 p1", p1, vp);
#endif
if (**vp && eq(**vp, STRor)) {
int p2;
(*vp)++;
p2 = csh_exp2(vp, ignore);
#ifdef EDEBUG
etraci("exp3 p2", p2, vp);
#endif
return (p1 | p2);
}
return (p1);
}
static int
exp2a(Char ***vp, int ignore)
{
int p1;
p1 = exp2b(vp, ignore);
#ifdef EDEBUG
etraci("exp2a p1", p1, vp);
#endif
if (**vp && eq(**vp, STRcaret)) {
int p2;
(*vp)++;
p2 = exp2a(vp, ignore);
#ifdef EDEBUG
etraci("exp2a p2", p2, vp);
#endif
return (p1 ^ p2);
}
return (p1);
}
static int
exp2b(Char ***vp, int ignore)
{
int p1;
p1 = exp2c(vp, ignore);
#ifdef EDEBUG
etraci("exp2b p1", p1, vp);
#endif
if (**vp && eq(**vp, STRand)) {
int p2;
(*vp)++;
p2 = exp2b(vp, ignore);
#ifdef EDEBUG
etraci("exp2b p2", p2, vp);
#endif
return (p1 & p2);
}
return (p1);
}
static int
exp2c(Char ***vp, int ignore)
{
Char *p1, *p2;
int i;
p1 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp2c p1", p1, vp);
#endif
if ((i = isa(**vp, EQOP)) != 0) {
(*vp)++;
if (i == EQMATCH || i == NOTEQMATCH)
ignore |= NOGLOB;
p2 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp2c p2", p2, vp);
#endif
if (!(ignore & IGNORE))
switch (i) {
case EQEQ:
i = eq(p1, p2);
break;
case EQMATCH:
i = Gmatch(p1, p2);
break;
case NOTEQ:
i = !eq(p1, p2);
break;
case NOTEQMATCH:
i = !Gmatch(p1, p2);
break;
}
xfree((ptr_t) p1);
xfree((ptr_t) p2);
return (i);
}
i = egetn(p1);
xfree((ptr_t) p1);
return (i);
}
static Char *
exp3(Char ***vp, int ignore)
{
Char *p1, *p2;
int i;
p1 = exp3a(vp, ignore);
#ifdef EDEBUG
etracc("exp3 p1", p1, vp);
#endif
if ((i = isa(**vp, RELOP)) != 0) {
(*vp)++;
if (**vp && eq(**vp, STRequal))
i |= 1, (*vp)++;
p2 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp3 p2", p2, vp);
#endif
if (!(ignore & IGNORE))
switch (i) {
case GTR:
i = egetn(p1) > egetn(p2);
break;
case GTR | 1:
i = egetn(p1) >= egetn(p2);
break;
case LSS:
i = egetn(p1) < egetn(p2);
break;
case LSS | 1:
i = egetn(p1) <= egetn(p2);
break;
}
xfree((ptr_t) p1);
xfree((ptr_t) p2);
return (putn(i));
}
return (p1);
}
static Char *
exp3a(Char ***vp, int ignore)
{
Char *op, *p1, *p2;
int i;
p1 = exp4(vp, ignore);
#ifdef EDEBUG
etracc("exp3a p1", p1, vp);
#endif
op = **vp;
if (op && any("<>", op[0]) && op[0] == op[1]) {
(*vp)++;
p2 = exp3a(vp, ignore);
#ifdef EDEBUG
etracc("exp3a p2", p2, vp);
#endif
if (op[0] == '<')
i = egetn(p1) << egetn(p2);
else
i = egetn(p1) >> egetn(p2);
xfree((ptr_t) p1);
xfree((ptr_t) p2);
return (putn(i));
}
return (p1);
}
static Char *
exp4(Char ***vp, int ignore)
{
Char *p1, *p2;
int i;
i = 0;
p1 = exp5(vp, ignore);
#ifdef EDEBUG
etracc("exp4 p1", p1, vp);
#endif
if (isa(**vp, ADDOP)) {
Char *op;
op = *(*vp)++;
p2 = exp4(vp, ignore);
#ifdef EDEBUG
etracc("exp4 p2", p2, vp);
#endif
if (!(ignore & IGNORE))
switch (op[0]) {
case '+':
i = egetn(p1) + egetn(p2);
break;
case '-':
i = egetn(p1) - egetn(p2);
break;
}
xfree((ptr_t) p1);
xfree((ptr_t) p2);
return (putn(i));
}
return (p1);
}
static Char *
exp5(Char ***vp, int ignore)
{
Char *p1, *p2;
int i;
i = 0;
p1 = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp5 p1", p1, vp);
#endif
if (isa(**vp, MULOP)) {
Char *op;
op = *(*vp)++;
p2 = exp5(vp, ignore);
#ifdef EDEBUG
etracc("exp5 p2", p2, vp);
#endif
if (!(ignore & IGNORE))
switch (op[0]) {
case '*':
i = egetn(p1) * egetn(p2);
break;
case '/':
i = egetn(p2);
if (i == 0)
stderror(ERR_DIV0);
i = egetn(p1) / i;
break;
case '%':
i = egetn(p2);
if (i == 0)
stderror(ERR_MOD0);
i = egetn(p1) % i;
break;
}
xfree((ptr_t) p1);
xfree((ptr_t) p2);
return (putn(i));
}
return (p1);
}
static Char *
exp6(Char ***vp, int ignore)
{
Char *cp, *dp, *ep;
int ccode, i;
i = 0;
if (**vp == 0)
stderror(ERR_NAME | ERR_EXPRESSION);
if (eq(**vp, STRbang)) {
(*vp)++;
cp = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp6 ! cp", cp, vp);
#endif
i = egetn(cp);
xfree((ptr_t) cp);
return (putn(!i));
}
if (eq(**vp, STRtilde)) {
(*vp)++;
cp = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp6 ~ cp", cp, vp);
#endif
i = egetn(cp);
xfree((ptr_t) cp);
return (putn(~i));
}
if (eq(**vp, STRLparen)) {
(*vp)++;
ccode = exp0(vp, ignore);
#ifdef EDEBUG
etraci("exp6 () ccode", ccode, vp);
#endif
if (**vp == 0 || ***vp != ')')
stderror(ERR_NAME | ERR_EXPRESSION);
(*vp)++;
return (putn(ccode));
}
if (eq(**vp, STRLbrace)) {
struct command faket;
Char *fakecom[2];
Char **v;
faket.t_dtyp = NODE_COMMAND;
faket.t_dflg = 0;
faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
faket.t_dcom = fakecom;
fakecom[0] = STRfakecom;
fakecom[1] = NULL;
(*vp)++;
v = *vp;
for (;;) {
if (!**vp)
stderror(ERR_NAME | ERR_MISSING, '}');
if (eq(*(*vp)++, STRRbrace))
break;
}
if (ignore & IGNORE)
return (Strsave(STRNULL));
psavejob();
if (pfork(&faket, -1) == 0) {
*--(*vp) = 0;
evalav(v);
exitstat();
}
pwait();
prestjob();
#ifdef EDEBUG
etraci("exp6 {} status", egetn(value(STRstatus)), vp);
#endif
return (putn(egetn(value(STRstatus)) == 0));
}
if (isa(**vp, ANYOP))
return (Strsave(STRNULL));
cp = *(*vp)++;
if (*cp == '-' && any("erwxfdzopls", cp[1])) {
struct stat stb;
if (cp[2] != '\0')
stderror(ERR_NAME | ERR_FILEINQ);
/*
* Detect missing file names by checking for operator in the file name
* position. However, if an operator name appears there, we must make
* sure that there's no file by that name (e.g., "/") before announcing
* an error. Even this check isn't quite right, since it doesn't take
* globbing into account.
*/
if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
stderror(ERR_NAME | ERR_FILENAME);
dp = *(*vp)++;
if (ignore & IGNORE)
return (Strsave(STRNULL));
ep = globone(dp, G_ERROR);
switch (cp[1]) {
case 'r':
i = !access(short2str(ep), R_OK);
break;
case 'w':
i = !access(short2str(ep), W_OK);
break;
case 'x':
i = !access(short2str(ep), X_OK);
break;
default:
if (cp[1] == 'l' ?
lstat(short2str(ep), &stb) : stat(short2str(ep), &stb)) {
xfree((ptr_t) ep);
return (Strsave(STR0));
}
switch (cp[1]) {
case 'd':
i = S_ISDIR(stb.st_mode);
break;
case 'e':
i = 1;
break;
case 'f':
i = S_ISREG(stb.st_mode);
break;
case 'l':
#ifdef S_ISLNK
i = S_ISLNK(stb.st_mode);
#else
i = 0;
#endif
break;
case 'o':
i = stb.st_uid == (uid_t)uid;
break;
case 'p':
#ifdef S_ISFIFO
i = S_ISFIFO(stb.st_mode);
#else
i = 0;
#endif
break;
case 's':
#ifdef S_ISSOCK
i = S_ISSOCK(stb.st_mode);
#else
i = 0;
#endif
break;
case 'z':
i = stb.st_size == 0;
break;
}
}
#ifdef EDEBUG
etraci("exp6 -? i", i, vp);
#endif
xfree((ptr_t) ep);
return (putn(i));
}
#ifdef EDEBUG
etracc("exp6 default", cp, vp);
#endif
return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
}
static void
evalav(Char **v)
{
struct wordent *hp, paraml1, *wdp;
struct command *t;
hp = &paraml1;
wdp = hp;
set(STRstatus, Strsave(STR0));
hp->prev = hp->next = hp;
hp->word = STRNULL;
while (*v) {
struct wordent *new;
new = (struct wordent *)xcalloc(1, sizeof *wdp);
new->prev = wdp;
new->next = hp;
wdp->next = new;
wdp = new;
wdp->word = Strsave(*v++);
}
hp->prev = wdp;
alias(&paraml1);
t = syntax(paraml1.next, &paraml1, 0);
if (seterr)
stderror(ERR_OLD);
execute(t, -1, NULL, NULL);
freelex(&paraml1), freesyn(t);
}
static int
isa(Char *cp, int what)
{
if (cp == 0)
return ((what & RESTOP) != 0);
if (cp[1] == 0) {
if (what & ADDOP && (*cp == '+' || *cp == '-'))
return (1);
if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
return (1);
if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
*cp == '~' || *cp == '^' || *cp == '"'))
return (1);
}
else if (cp[2] == 0) {
if (what & RESTOP) {
if (cp[0] == '|' && cp[1] == '&')
return (1);
if (cp[0] == '<' && cp[1] == '<')
return (1);
if (cp[0] == '>' && cp[1] == '>')
return (1);
}
if (what & EQOP) {
if (cp[0] == '=') {
if (cp[1] == '=')
return (EQEQ);
if (cp[1] == '~')
return (EQMATCH);
}
else if (cp[0] == '!') {
if (cp[1] == '=')
return (NOTEQ);
if (cp[1] == '~')
return (NOTEQMATCH);
}
}
}
if (what & RELOP) {
if (*cp == '<')
return (LSS);
if (*cp == '>')
return (GTR);
}
return (0);
}
static int
egetn(Char *cp)
{
if (*cp && *cp != '-' && !Isdigit(*cp))
stderror(ERR_NAME | ERR_EXPRESSION);
return (getn(cp));
}
/* Phew! */
#ifdef EDEBUG
static void
etraci(char *str, int i, Char ***vp)
{
(void)fprintf(csherr, "%s=%d\t", str, i);
blkpr(csherr, *vp);
(void)fprintf(csherr, "\n");
}
static void
etracc(char *str, Char *cp, Char ***vp)
{
(void)fprintf(csherr, "%s=%s\t", str, vis_str(cp));
blkpr(csherr, *vp);
(void)fprintf(csherr, "\n");
}
#endif

View File

@@ -1,341 +0,0 @@
/* $NetBSD: extern.h,v 1.29 2013/07/16 17:47:43 christos Exp $ */
/*-
* Copyright (c) 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. 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.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _EXTERN_H_
#define _EXTERN_H_
#include <sys/cdefs.h>
/*
* csh.c
*/
int gethdir(Char *);
void dosource(Char **, struct command *);
__dead void exitstat(void);
__dead void goodbye(void);
void importpath(Char *);
void initdesc(void);
__dead void pintr(int);
__dead void pintr1(int);
void printprompt(void);
#ifdef EDIT
char *printpromptstr(EditLine *);
#endif
void process(int);
void rechist(void);
void untty(void);
int vis_fputc(int, FILE *);
#ifdef PROF
__dead void done(int);
#else
__dead void xexit(int);
#endif
/*
* dir.c
*/
void dinit(Char *);
void dodirs(Char **, struct command *);
Char *dcanon(Char *, Char *);
void dtildepr(Char *, Char *);
void dtilde(void);
void dochngd(Char **, struct command *);
Char *dnormalize(Char *);
void dopushd(Char **, struct command *);
void dopopd(Char **, struct command *);
struct directory;
void dfree(struct directory *);
/*
* dol.c
*/
void Dfix(struct command *);
Char *Dfix1(Char *);
void heredoc(Char *);
/*
* err.c
*/
void seterror(int, ...);
__dead void stderror(int, ...);
/*
* exec.c
*/
__dead void doexec(Char **, struct command *);
void dohash(Char **, struct command *);
void dounhash(Char **, struct command *);
void dowhich(Char **, struct command *);
void execash(Char **, struct command *);
void hashstat(Char **, struct command *);
void xechoit(Char **);
/*
* exp.c
*/
int expr(Char ***);
int exp0(Char ***, int);
/*
* file.c
*/
#ifdef FILEC
ssize_t tenex(Char *, size_t);
#endif
/*
* func.c
*/
void Setenv(Char *, Char *);
void doalias(Char **, struct command *);
void dobreak(Char **, struct command *);
void docontin(Char **, struct command *);
void doecho(Char **, struct command *);
void doelse(Char **, struct command *);
void doend(Char **, struct command *);
void doeval(Char **, struct command *);
void doexit(Char **, struct command *);
void doforeach(Char **, struct command *);
void doglob(Char **, struct command *);
void dogoto(Char **, struct command *);
void doif(Char **, struct command *);
void dolimit(Char **, struct command *);
__dead void dologin(Char **, struct command *);
__dead void dologout(Char **, struct command *);
void donohup(Char **, struct command *);
void doonintr(Char **, struct command *);
void doprintf(Char **, struct command *);
void dorepeat(Char **, struct command *);
void dosetenv(Char **, struct command *);
void dosuspend(Char **, struct command *);
void doswbrk(Char **, struct command *);
void doswitch(Char **, struct command *);
void doumask(Char **, struct command *);
void dounlimit(Char **, struct command *);
void dounsetenv(Char **, struct command *);
void dowhile(Char **, struct command *);
void dozip(Char **, struct command *);
void func(struct command *, struct biltins *);
struct biltins *isbfunc(struct command *);
void prvars(void);
void gotolab(Char *);
int srchx(Char *);
void unalias(Char **, struct command *);
void wfree(void);
/*
* glob.c
*/
Char **dobackp(Char *, int);
void Gcat(Char *, Char *);
Char *globone(Char *, int);
int Gmatch(Char *, Char *);
void ginit(void);
Char **globall(Char **);
void rscan(Char **, void (*)(int));
void tglob(Char **);
void trim(Char **);
#ifdef FILEC
int sortscmp(const ptr_t, const ptr_t);
#endif /* FILEC */
/*
* hist.c
*/
void dohist(Char **, struct command *);
struct Hist *enthist(int, struct wordent *, int);
#ifdef EDIT
void loadhist(struct Hist *);
#endif
void savehist(struct wordent *);
/*
* lex.c
*/
void addla(Char *);
void bseek(struct Ain *);
void btell(struct Ain *);
void btoeof(void);
void copylex(struct wordent *, struct wordent *);
Char *domod(Char *, int);
void freelex(struct wordent *);
int lex(struct wordent *);
void prlex(FILE *, struct wordent *);
#ifdef EDIT
int sprlex(char **, struct wordent *);
#endif
int readc(int);
void settell(void);
void unreadc(int);
/*
* misc.c
*/
int any(const char *, int);
Char **blkcat(Char **, Char **);
Char **blkcpy(Char **, Char **);
Char **blkend(Char **);
void blkfree(Char **);
int blklen(Char **);
void blkpr(FILE *, Char **);
Char **blkspl(Char **, Char **);
void closem(void);
Char **copyblk(Char **);
int dcopy(int, int);
int dmove(int, int);
void donefds(void);
Char lastchr(Char *);
void lshift(Char **, size_t);
int number(Char *);
int prefix(Char *, Char *);
Char **saveblk(Char **);
Char *strip(Char *);
Char *quote(Char *);
char *strsave(const char *);
char *strspl(char *, char *);
__dead void udvar(Char *);
#ifndef SHORT_STRINGS
# ifdef NOTUSED
char *strstr(const char *, const char *);
# endif /* NOTUSED */
char *strend(char *);
#endif
/*
* parse.c
*/
void alias(struct wordent *);
void freesyn(struct command *);
struct command *syntax(struct wordent *, struct wordent *, int);
/*
* proc.c
*/
void dobg(Char **, struct command *);
void dobg1(Char **, struct command *);
void dofg(Char **, struct command *);
void dofg1(Char **, struct command *);
void dojobs(Char **, struct command *);
void dokill(Char **, struct command *);
void donotify(Char **, struct command *);
void dostop(Char **, struct command *);
void dowait(Char **, struct command *);
void palloc(int, struct command *);
void panystop(int);
void pchild(int);
void pendjob(void);
struct process *pfind(Char *);
int pfork(struct command *, int);
void pgetty(int, int);
void pjwait(struct process *);
void pnote(void);
void prestjob(void);
void psavejob(void);
void pstart(struct process *, int);
void pwait(void);
/*
* sem.c
*/
void execute(struct command *, int, int *, int *);
void mypipe(int *);
/*
* set.c
*/
struct varent*adrof1(Char *, struct varent *);
void doset(Char **, struct command *);
void dolet(Char **, struct command *);
Char *putn(int);
int getn(Char *);
Char *value1(Char *, struct varent *);
void set(Char *, Char *);
void set1(Char *, Char **, struct varent *);
void setq(Char *, Char **, struct varent *);
void unset(Char **, struct command *);
void unset1(Char *[], struct varent *);
void unsetv(Char *);
void setNS(Char *);
void shift(Char **, struct command *);
void plist(struct varent *);
/*
* time.c
*/
void donice(Char **, struct command *);
void dotime(Char **, struct command *);
void prusage(FILE *, struct rusage *, struct rusage *, struct timespec *,
struct timespec *);
void ruadd(struct rusage *, struct rusage *);
void settimes(void);
void psecs(long);
/*
* alloc.c
*/
void Free(ptr_t);
ptr_t Malloc(size_t);
ptr_t Realloc(ptr_t, size_t);
ptr_t Calloc(size_t, size_t);
/*
* str.c:
*/
#ifdef SHORT_STRINGS
Char *s_strchr(const Char *, int);
Char *s_strrchr(const Char *, int);
Char *s_strcat(Char *, const Char *);
#ifdef NOTUSED
Char *s_strncat(Char *, const Char *, size_t);
#endif
Char *s_strcpy(Char *, const Char *);
Char *s_strncpy(Char *, const Char *, size_t);
Char *s_strspl(const Char *, const Char *);
size_t s_strlen(const Char *);
int s_strcmp(const Char *, const Char *);
int s_strncmp(const Char *, const Char *, size_t);
Char *s_strsave(const Char *);
Char *s_strend(const Char *);
Char *s_strstr(const Char *, const Char *);
Char *str2short(const char *);
Char **blk2short(char **);
char *short2str(const Char *);
char **short2blk(Char * const *);
#endif
char *short2qstr(const Char *);
char *vis_str(const Char *);
#endif /* !_EXTERN_H_ */

View File

@@ -1,729 +0,0 @@
/* $NetBSD: file.c,v 1.30 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)file.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: file.c,v 1.30 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#ifdef FILEC
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <dirent.h>
#include <pwd.h>
#include <termios.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef SHORT_STRINGS
#include <string.h>
#endif /* SHORT_STRINGS */
#include "csh.h"
#include "extern.h"
/*
* Tenex style file name recognition, .. and more.
* History:
* Author: Ken Greer, Sept. 1975, CMU.
* Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
*/
#define ON 1
#define OFF 0
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define ESC '\033'
typedef enum {
LIST, RECOGNIZE
} COMMAND;
static void setup_tty(int);
static void back_to_col_1(void);
static int pushback(Char *);
static void catn(Char *, Char *, size_t);
static void copyn(Char *, Char *, size_t);
static Char filetype(Char *, Char *);
static void print_by_column(Char *, Char *[], size_t);
static Char *tilde(Char *, Char *);
static void retype(void);
static void beep(void);
static void print_recognized_stuff(Char *);
static void extract_dir_and_name(Char *, Char *, Char *);
static Char *getentry(DIR *, int);
static void free_items(Char **, size_t);
static size_t tsearch(Char *, COMMAND, size_t);
static int recognize(Char *, Char *, size_t, size_t);
static int is_prefix(Char *, Char *);
static int is_suffix(Char *, Char *);
static int ignored(Char *);
/*
* Put this here so the binary can be patched with adb to enable file
* completion by default. Filec controls completion, nobeep controls
* ringing the terminal bell on incomplete expansions.
*/
int filec = 0;
static void
setup_tty(int on)
{
struct termios tchars;
(void)tcgetattr(SHIN, &tchars);
if (on) {
tchars.c_cc[VEOL] = ESC;
if (tchars.c_lflag & ICANON)
on = TCSADRAIN;
else {
tchars.c_lflag |= ICANON;
on = TCSAFLUSH;
}
}
else {
tchars.c_cc[VEOL] = _POSIX_VDISABLE;
on = TCSADRAIN;
}
(void)tcsetattr(SHIN, on, &tchars);
}
/*
* Move back to beginning of current line
*/
static void
back_to_col_1(void)
{
struct termios tty, tty_normal;
sigset_t nsigset, osigset;
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGINT);
(void)sigprocmask(SIG_BLOCK, &nsigset, &osigset);
(void)tcgetattr(SHOUT, &tty);
tty_normal = tty;
tty.c_iflag &= ~INLCR;
tty.c_oflag &= ~ONLCR;
(void)tcsetattr(SHOUT, TCSADRAIN, &tty);
(void)write(SHOUT, "\r", 1);
(void)tcsetattr(SHOUT, TCSADRAIN, &tty_normal);
(void)sigprocmask(SIG_SETMASK, &osigset, NULL);
}
/*
* Push string contents back into tty queue
*/
static int
pushback(Char *string)
{
struct termios tty, tty_normal;
char buf[64], svchars[sizeof(buf)];
sigset_t nsigset, osigset;
Char *p;
size_t bufidx, i, len_str, nbuf, nsv, onsv, retrycnt;
char c;
nsv = 0;
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGINT);
(void)sigprocmask(SIG_BLOCK, &nsigset, &osigset);
(void)tcgetattr(SHOUT, &tty);
tty_normal = tty;
tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL);
/* FIONREAD works only in noncanonical mode. */
tty.c_lflag &= ~ICANON;
tty.c_cc[VMIN] = 0;
(void)tcsetattr(SHOUT, TCSADRAIN, &tty);
for (retrycnt = 5; ; retrycnt--) {
/*
* Push back characters.
*/
for (p = string; (c = (char)*p) != '\0'; p++)
(void)ioctl(SHOUT, TIOCSTI, (ioctl_t) &c);
for (i = 0; i < nsv; i++)
(void)ioctl(SHOUT, TIOCSTI, (ioctl_t) &svchars[i]);
if (retrycnt == 0)
break; /* give up salvaging characters */
len_str = (size_t)(p - string);
if (ioctl(SHOUT, FIONREAD, (ioctl_t) &nbuf) ||
nbuf <= len_str + nsv || /* The string fit. */
nbuf > sizeof(buf)) /* For future binary compatibility
(and safety). */
break;
/*
* User has typed characters before the pushback finished.
* Salvage the characters.
*/
/* This read() should be in noncanonical mode. */
if (read(SHOUT, &buf, nbuf) != (ssize_t)nbuf)
continue; /* hangup? */
onsv = nsv;
for (bufidx = 0, i = 0; bufidx < nbuf; bufidx++, i++) {
c = buf[bufidx];
if ((i < len_str) ? c != (char)string[i] :
(i < len_str + onsv) ? c != svchars[i - len_str] : 1) {
/* Salvage a character. */
if (nsv < (int)(sizeof svchars / sizeof svchars[0])) {
svchars[nsv++] = c;
i--; /* try this comparison with the next char */
} else
break; /* too many */
}
}
}
#if 1
/*
* XXX Is this a bug or a feature of kernel tty driver?
*
* FIONREAD in canonical mode does not return correct byte count
* in tty input queue, but this is required to avoid unwanted echo.
*/
tty.c_lflag |= ICANON;
(void)tcsetattr(SHOUT, TCSADRAIN, &tty);
(void)ioctl(SHOUT, FIONREAD, (ioctl_t) &i);
#endif
(void)tcsetattr(SHOUT, TCSADRAIN, &tty_normal);
(void)sigprocmask(SIG_SETMASK, &osigset, NULL);
return (int)nsv;
}
/*
* Concatenate src onto tail of des.
* Des is a string whose maximum length is count.
* Always null terminate.
*/
static void
catn(Char *des, Char *src, size_t count)
{
while (count-- > 0 && *des)
des++;
while (count-- > 0)
if ((*des++ = *src++) == 0)
return;
*des = '\0';
}
/*
* Like strncpy but always leave room for trailing \0
* and always null terminate.
*/
static void
copyn(Char *des, Char *src, size_t count)
{
while (count-- > 0)
if ((*des++ = *src++) == 0)
return;
*des = '\0';
}
static Char
filetype(Char *dir, Char *file)
{
struct stat statb;
Char path[MAXPATHLEN];
catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char));
if (lstat(short2str(path), &statb) == 0) {
switch (statb.st_mode & S_IFMT) {
case S_IFDIR:
return ('/');
case S_IFLNK:
if (stat(short2str(path), &statb) == 0 && /* follow it out */
S_ISDIR(statb.st_mode))
return ('>');
else
return ('@');
case S_IFSOCK:
return ('=');
default:
if (statb.st_mode & 0111)
return ('*');
}
}
return (' ');
}
static struct winsize win;
/*
* Print sorted down columns
*/
static void
print_by_column(Char *dir, Char *items[], size_t count)
{
size_t c, columns, i, maxwidth, r, rows;
maxwidth = 0;
if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0)
win.ws_col = 80;
for (i = 0; i < count; i++)
maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r;
maxwidth += 2; /* for the file tag and space */
columns = win.ws_col / maxwidth;
if (columns == 0)
columns = 1;
rows = (count + (columns - 1)) / columns;
for (r = 0; r < rows; r++) {
for (c = 0; c < columns; c++) {
i = c * rows + r;
if (i < count) {
size_t w;
(void)fprintf(cshout, "%s", vis_str(items[i]));
(void)fputc(dir ? filetype(dir, items[i]) : ' ', cshout);
if (c < columns - 1) { /* last column? */
w = Strlen(items[i]) + 1;
for (; w < maxwidth; w++)
(void) fputc(' ', cshout);
}
}
}
(void)fputc('\r', cshout);
(void)fputc('\n', cshout);
}
}
/*
* Expand file name with possible tilde usage
* ~person/mumble
* expands to
* home_directory_of_person/mumble
*/
static Char *
tilde(Char *new, Char *old)
{
static Char person[40];
struct passwd *pw;
Char *o, *p;
if (old[0] != '~')
return (Strcpy(new, old));
for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++)
continue;
*p = '\0';
if (person[0] == '\0')
(void)Strcpy(new, value(STRhome));
else {
pw = getpwnam(short2str(person));
if (pw == NULL)
return (NULL);
(void)Strcpy(new, str2short(pw->pw_dir));
}
(void)Strcat(new, o);
return (new);
}
/*
* Cause pending line to be printed
*/
static void
retype(void)
{
struct termios tty;
(void)tcgetattr(SHOUT, &tty);
tty.c_lflag |= PENDIN;
(void)tcsetattr(SHOUT, TCSADRAIN, &tty);
}
static void
beep(void)
{
if (adrof(STRnobeep) == 0)
(void)write(SHOUT, "\007", 1);
}
/*
* Erase that silly ^[ and
* print the recognized part of the string
*/
static void
print_recognized_stuff(Char *recognized_part)
{
/* An optimized erasing of that silly ^[ */
(void)fputc('\b', cshout);
(void)fputc('\b', cshout);
switch (Strlen(recognized_part)) {
case 0: /* erase two Characters: ^[ */
(void)fputc(' ', cshout);
(void)fputc(' ', cshout);
(void)fputc('\b', cshout);
(void)fputc('\b', cshout);
break;
case 1: /* overstrike the ^, erase the [ */
(void)fprintf(cshout, "%s", vis_str(recognized_part));
(void)fputc(' ', cshout);
(void)fputc('\b', cshout);
break;
default: /* overstrike both Characters ^[ */
(void)fprintf(cshout, "%s", vis_str(recognized_part));
break;
}
(void)fflush(cshout);
}
/*
* Parse full path in file into 2 parts: directory and file names
* Should leave final slash (/) at end of dir.
*/
static void
extract_dir_and_name(Char *path, Char *dir, Char *name)
{
Char *p;
p = Strrchr(path, '/');
if (p == NULL) {
copyn(name, path, MAXNAMLEN);
dir[0] = '\0';
}
else {
copyn(name, ++p, MAXNAMLEN);
copyn(dir, path, (size_t)(p - path));
}
}
static Char *
getentry(DIR *dir_fd, int looking_for_lognames)
{
struct dirent *dirp;
struct passwd *pw;
if (looking_for_lognames) {
if ((pw = getpwent()) == NULL)
return (NULL);
return (str2short(pw->pw_name));
}
if ((dirp = readdir(dir_fd)) != NULL)
return (str2short(dirp->d_name));
return (NULL);
}
static void
free_items(Char **items, size_t numitems)
{
size_t i;
for (i = 0; i < numitems; i++)
xfree((ptr_t) items[i]);
xfree((ptr_t) items);
}
#define FREE_ITEMS(items, numitems) { \
sigset_t nsigset, osigset;\
\
sigemptyset(&nsigset);\
(void) sigaddset(&nsigset, SIGINT);\
(void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);\
free_items(items, numitems);\
(void) sigprocmask(SIG_SETMASK, &osigset, NULL);\
}
/*
* Perform a RECOGNIZE or LIST command on string "word".
*/
static size_t
tsearch(Char *word, COMMAND command, size_t max_word_length)
{
Char dir[MAXPATHLEN + 1], extended_name[MAXNAMLEN + 1];
Char name[MAXNAMLEN + 1], tilded_dir[MAXPATHLEN + 1];
DIR *dir_fd;
Char *entry;
int ignoring, looking_for_lognames;
size_t name_length, nignored, numitems;
Char **items = NULL;
size_t maxitems = 0;
numitems = 0;
ignoring = TRUE;
nignored = 0;
looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL);
if (looking_for_lognames) {
(void)setpwent();
copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
dir_fd = NULL;
}
else {
extract_dir_and_name(word, dir, name);
if (tilde(tilded_dir, dir) == 0)
return (0);
dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : ".");
if (dir_fd == NULL)
return (0);
}
again: /* search for matches */
name_length = Strlen(name);
for (numitems = 0; (entry = getentry(dir_fd, looking_for_lognames)) != NULL;) {
if (!is_prefix(name, entry))
continue;
/* Don't match . files on null prefix match */
if (name_length == 0 && entry[0] == '.' &&
!looking_for_lognames)
continue;
if (command == LIST) {
if ((size_t)numitems >= maxitems) {
maxitems += 1024;
if (items == NULL)
items = xmalloc(sizeof(*items) * maxitems);
else
items = xrealloc((ptr_t) items,
sizeof(*items) * maxitems);
}
items[numitems] = xmalloc((size_t) (Strlen(entry) + 1) *
sizeof(Char));
copyn(items[numitems], entry, MAXNAMLEN);
numitems++;
}
else { /* RECOGNIZE command */
if (ignoring && ignored(entry))
nignored++;
else if (recognize(extended_name,
entry, name_length, ++numitems))
break;
}
}
if (ignoring && numitems == 0 && nignored > 0) {
ignoring = FALSE;
nignored = 0;
if (looking_for_lognames)
(void)setpwent();
else
rewinddir(dir_fd);
goto again;
}
if (looking_for_lognames)
(void)endpwent();
else
(void)closedir(dir_fd);
if (numitems == 0)
return (0);
if (command == RECOGNIZE) {
if (looking_for_lognames)
copyn(word, STRtilde, 1);
else
/* put back dir part */
copyn(word, dir, max_word_length);
/* add extended name */
catn(word, extended_name, max_word_length);
return (numitems);
}
else { /* LIST */
qsort((ptr_t) items, numitems, sizeof(items[0]),
(int (*) (const void *, const void *)) sortscmp);
print_by_column(looking_for_lognames ? NULL : tilded_dir,
items, numitems);
if (items != NULL)
FREE_ITEMS(items, numitems);
}
return (0);
}
/*
* Object: extend what user typed up to an ambiguity.
* Algorithm:
* On first match, copy full entry (assume it'll be the only match)
* On subsequent matches, shorten extended_name to the first
* Character mismatch between extended_name and entry.
* If we shorten it back to the prefix length, stop searching.
*/
static int
recognize(Char *extended_name, Char *entry, size_t name_length, size_t numitems)
{
if (numitems == 1) /* 1st match */
copyn(extended_name, entry, MAXNAMLEN);
else { /* 2nd & subsequent matches */
Char *ent, *x;
size_t len = 0;
x = extended_name;
for (ent = entry; *x && *x == *ent++; x++, len++)
continue;
*x = '\0'; /* Shorten at 1st Char diff */
if (len == name_length) /* Ambiguous to prefix? */
return (-1); /* So stop now and save time */
}
return (0);
}
/*
* Return true if check matches initial Chars in template.
* This differs from PWB imatch in that if check is null
* it matches anything.
*/
static int
is_prefix(Char *check, Char *template)
{
do
if (*check == 0)
return (TRUE);
while (*check++ == *template++);
return (FALSE);
}
/*
* Return true if the Chars in template appear at the
* end of check, I.e., are its suffix.
*/
static int
is_suffix(Char *check, Char *template)
{
Char *c, *t;
for (c = check; *c++;)
continue;
for (t = template; *t++;)
continue;
for (;;) {
if (t == template)
return 1;
if (c == check || *--t != *--c)
return 0;
}
}
ssize_t
tenex(Char *inputline, size_t inputline_size)
{
char tinputline[BUFSIZE];
ssize_t num_read;
size_t numitems;
setup_tty(ON);
while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) {
size_t i, nr = (size_t) num_read;
static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<',
'>', '(', ')', '|', '^', '%', '\0'};
Char *str_end, *word_start, last_Char, should_retype;
size_t space_left;
COMMAND command;
for (i = 0; i < nr; i++)
inputline[i] = (unsigned char) tinputline[i];
last_Char = inputline[nr - 1] & ASCII;
if (last_Char == '\n' || nr == inputline_size)
break;
command = (last_Char == ESC) ? RECOGNIZE : LIST;
if (command == LIST)
(void)fputc('\n', cshout);
str_end = &inputline[nr];
if (last_Char == ESC)
--str_end; /* wipeout trailing cmd Char */
*str_end = '\0';
/*
* Find LAST occurence of a delimiter in the inputline. The word start
* is one Character past it.
*/
for (word_start = str_end; word_start > inputline; --word_start)
if (Strchr(delims, word_start[-1]))
break;
space_left = inputline_size - (size_t)(word_start - inputline) - 1;
numitems = tsearch(word_start, command, space_left);
if (command == RECOGNIZE) {
/* print from str_end on */
print_recognized_stuff(str_end);
if (numitems != 1) /* Beep = No match/ambiguous */
beep();
}
/*
* Tabs in the input line cause trouble after a pushback. tty driver
* won't backspace over them because column positions are now
* incorrect. This is solved by retyping over current line.
*/
should_retype = FALSE;
if (Strchr(inputline, '\t')) { /* tab Char in input line? */
back_to_col_1();
should_retype = TRUE;
}
if (command == LIST) /* Always retype after a LIST */
should_retype = TRUE;
if (pushback(inputline))
should_retype = TRUE;
if (should_retype) {
if (command == RECOGNIZE)
(void) fputc('\n', cshout);
printprompt();
}
if (should_retype)
retype();
}
setup_tty(OFF);
return num_read;
}
static int
ignored(Char *entry)
{
struct varent *vp;
Char **cp;
if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
return (FALSE);
for (; *cp != NULL; cp++)
if (is_suffix(entry, *cp))
return (TRUE);
return (FALSE);
}
#endif /* FILEC */

File diff suppressed because it is too large Load Diff

View File

@@ -1,923 +0,0 @@
/* $NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)glob.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <errno.h>
#include <glob.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "csh.h"
#include "extern.h"
static int noglob;
static int gargsiz, pargsiz;
/*
* Values for gflag
*/
#define G_NONE 0 /* No globbing needed */
#define G_GLOB 1 /* string contains *?[] characters */
#define G_CSH 2 /* string contains ~`{ characters */
#define GLOBSPACE 100 /* Alloc increment */
#define LBRC '{'
#define RBRC '}'
#define LBRK '['
#define RBRK ']'
#define EOS '\0'
Char **gargv = NULL;
Char **pargv = NULL;
long gargc = 0;
long pargc = 0;
/*
* globbing is now done in two stages. In the first pass we expand
* csh globbing idioms ~`{ and then we proceed doing the normal
* globbing if needed ?*[
*
* Csh type globbing is handled in globexpand() and the rest is
* handled in glob() which is part of the 4.4BSD libc.
*
*/
static Char *globtilde(Char **, Char *);
static Char *handleone(Char *, Char **, int);
static Char **libglob(Char **);
static Char **globexpand(Char **);
static int globbrace(Char *, Char *, Char ***);
static void expbrace(Char ***, Char ***, size_t);
static int pmatch(Char *, Char *);
static void pword(void);
static void psave(int);
static void backeval(Char *, int);
static Char *
globtilde(Char **nv, Char *s)
{
Char gbuf[MAXPATHLEN], *b, *e, *gstart, *u;
gstart = gbuf;
*gstart++ = *s++;
u = s;
for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
*s && *s != '/' && *s != ':' && b < e;
*b++ = *s++)
continue;
*b = EOS;
if (gethdir(gstart)) {
blkfree(nv);
if (*gstart)
stderror(ERR_UNKUSER, vis_str(gstart));
else
stderror(ERR_NOHOME);
}
b = &gstart[Strlen(gstart)];
while (*s)
*b++ = *s++;
*b = EOS;
--u;
xfree((ptr_t) u);
return (Strsave(gstart));
}
static int
globbrace(Char *s, Char *p, Char ***bl)
{
Char gbuf[MAXPATHLEN];
Char *lm, *pe, *pl, *pm, **nv, **vl;
int i, len, size;
size = GLOBSPACE;
nv = vl = xmalloc(sizeof(Char *) * (size_t)size);
*vl = NULL;
len = 0;
/* copy part up to the brace */
for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
continue;
/* check for balanced braces */
for (i = 0, pe = ++p; *pe; pe++)
if (*pe == LBRK) {
/* Ignore everything between [] */
for (++pe; *pe != RBRK && *pe != EOS; pe++)
continue;
if (*pe == EOS) {
blkfree(nv);
return (-RBRK);
}
}
else if (*pe == LBRC)
i++;
else if (*pe == RBRC) {
if (i == 0)
break;
i--;
}
if (i != 0 || *pe == '\0') {
blkfree(nv);
return (-RBRC);
}
for (i = 0, pl = pm = p; pm <= pe; pm++)
switch (*pm) {
case LBRK:
for (++pm; *pm != RBRK && *pm != EOS; pm++)
continue;
if (*pm == EOS) {
*vl = NULL;
blkfree(nv);
return (-RBRK);
}
break;
case LBRC:
i++;
break;
case RBRC:
if (i) {
i--;
break;
}
/* FALLTHROUGH */
case ',':
if (i && *pm == ',')
break;
else {
Char savec = *pm;
*pm = EOS;
(void)Strcpy(lm, pl);
(void)Strcat(gbuf, pe + 1);
*pm = savec;
*vl++ = Strsave(gbuf);
len++;
pl = pm + 1;
if (vl == &nv[size]) {
size += GLOBSPACE;
nv = (Char **)xrealloc((ptr_t) nv,
(size_t)size * sizeof(Char *));
vl = &nv[size - GLOBSPACE];
}
}
break;
default:
break;
}
*vl = NULL;
*bl = nv;
return (len);
}
static void
expbrace(Char ***nvp, Char ***elp, size_t size)
{
Char **ex, **nv, *s, **vl;
vl = nv = *nvp;
if (elp != NULL)
ex = *elp;
else
for (ex = vl; *ex; ex++)
continue;
for (s = *vl; s; s = *++vl) {
Char *b, **bp, **vp;
/* leave {} untouched for find */
if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
continue;
if ((b = Strchr(s, '{')) != NULL) {
Char **bl;
int len;
if ((len = globbrace(s, b, &bl)) < 0) {
xfree((ptr_t)nv);
stderror(ERR_MISSING, -len);
}
xfree((ptr_t) s);
if (len == 1) {
*vl-- = *bl;
xfree((ptr_t) bl);
continue;
}
len = blklen(bl);
if (&ex[len] >= &nv[size]) {
ptrdiff_t l, e;
l = &ex[len] - &nv[size];
size += (size_t)(GLOBSPACE > l ? GLOBSPACE : l);
l = vl - nv;
e = ex - nv;
nv = (Char **)xrealloc((ptr_t)nv,
(size_t)size * sizeof(Char *));
vl = nv + l;
ex = nv + e;
}
vp = vl--;
*vp = *bl;
len--;
for (bp = ex; bp != vp; bp--)
bp[len] = *bp;
ex += len;
vp++;
for (bp = bl + 1; *bp; *vp++ = *bp++)
continue;
xfree((ptr_t)bl);
}
}
if (elp != NULL)
*elp = ex;
*nvp = nv;
}
static Char **
globexpand(Char **v)
{
Char **ex, **nv, *s, **vl;
size_t size;
size = GLOBSPACE;
nv = vl = xmalloc(sizeof(Char *) * size);
*vl = NULL;
/*
* Step 1: expand backquotes.
*/
while ((s = *v++) != NULL) {
if (Strchr(s, '`')) {
int i;
(void) dobackp(s, 0);
for (i = 0; i < pargc; i++) {
*vl++ = pargv[i];
if (vl == &nv[size]) {
size += GLOBSPACE;
nv = (Char **)xrealloc((ptr_t) nv,
(size_t)size * sizeof(Char *));
vl = &nv[size - GLOBSPACE];
}
}
xfree((ptr_t)pargv);
pargv = NULL;
}
else {
*vl++ = Strsave(s);
if (vl == &nv[size]) {
size += GLOBSPACE;
nv = (Char **)xrealloc((ptr_t)nv,
size * sizeof(Char *));
vl = &nv[size - GLOBSPACE];
}
}
}
*vl = NULL;
if (noglob)
return (nv);
/*
* Step 2: expand braces
*/
ex = vl;
expbrace(&nv, &ex, size);
/*
* Step 3: expand ~
*/
vl = nv;
for (s = *vl; s; s = *++vl)
if (*s == '~')
*vl = globtilde(nv, s);
vl = nv;
return (vl);
}
static Char *
handleone(Char *str, Char **vl, int action)
{
Char *cp, **vlp;
vlp = vl;
switch (action) {
case G_ERROR:
setname(vis_str(str));
blkfree(vl);
stderror(ERR_NAME | ERR_AMBIG);
/* NOTREACHED */
case G_APPEND:
trim(vlp);
str = Strsave(*vlp++);
do {
cp = Strspl(str, STRspace);
xfree((ptr_t)str);
str = Strspl(cp, *vlp);
xfree((ptr_t)cp);
}
while (*++vlp);
blkfree(vl);
break;
case G_IGNORE:
str = Strsave(strip(*vlp));
blkfree(vl);
break;
default:
break;
}
return (str);
}
static Char **
libglob(Char **vl)
{
glob_t globv;
char *ptr;
int gflgs, magic, match, nonomatch;
gflgs = GLOB_NOMAGIC;
magic = 0;
match = 0;
nonomatch = adrof(STRnonomatch) != 0;
if (!vl || !vl[0])
return (vl);
globv.gl_offs = 0;
globv.gl_pathv = 0;
globv.gl_pathc = 0;
if (nonomatch)
gflgs |= GLOB_NOCHECK;
do {
ptr = short2qstr(*vl);
switch (glob(ptr, gflgs, 0, &globv)) {
case GLOB_ABORTED:
setname(vis_str(*vl));
stderror(ERR_NAME | ERR_GLOB);
/* NOTREACHED */
case GLOB_NOSPACE:
stderror(ERR_NOMEM);
/* NOTREACHED */
default:
break;
}
if (globv.gl_flags & GLOB_MAGCHAR) {
match |= (globv.gl_matchc != 0);
magic = 1;
}
gflgs |= GLOB_APPEND;
}
while (*++vl);
vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
NULL : blk2short(globv.gl_pathv);
globfree(&globv);
return (vl);
}
Char *
globone(Char *str, int action)
{
Char *v[2], **vl, **vo;
int gflg;
noglob = adrof(STRnoglob) != 0;
gflag = 0;
v[0] = str;
v[1] = 0;
tglob(v);
gflg = gflag;
if (gflg == G_NONE)
return (strip(Strsave(str)));
if (gflg & G_CSH) {
/*
* Expand back-quote, tilde and brace
*/
vo = globexpand(v);
if (noglob || (gflg & G_GLOB) == 0) {
if (vo[0] == NULL) {
xfree((ptr_t)vo);
return (Strsave(STRNULL));
}
if (vo[1] != NULL)
return (handleone(str, vo, action));
else {
str = strip(vo[0]);
xfree((ptr_t) vo);
return (str);
}
}
}
else if (noglob || (gflg & G_GLOB) == 0)
return (strip(Strsave(str)));
else
vo = v;
vl = libglob(vo);
if ((gflg & G_CSH) && vl != vo)
blkfree(vo);
if (vl == NULL) {
setname(vis_str(str));
stderror(ERR_NAME | ERR_NOMATCH);
}
if (vl[0] == NULL) {
xfree((ptr_t)vl);
return (Strsave(STRNULL));
}
if (vl[1] != NULL)
return (handleone(str, vl, action));
else {
str = strip(*vl);
xfree((ptr_t)vl);
return (str);
}
}
Char **
globall(Char **v)
{
Char **vl, **vo;
int gflg;
gflg = gflag;
if (!v || !v[0]) {
gargv = saveblk(v);
gargc = blklen(gargv);
return (gargv);
}
noglob = adrof(STRnoglob) != 0;
if (gflg & G_CSH)
/*
* Expand back-quote, tilde and brace
*/
vl = vo = globexpand(v);
else
vl = vo = saveblk(v);
if (!noglob && (gflg & G_GLOB)) {
vl = libglob(vo);
if ((gflg & G_CSH) && vl != vo)
blkfree(vo);
}
else
trim(vl);
gargc = vl ? blklen(vl) : 0;
return (gargv = vl);
}
void
ginit(void)
{
gargsiz = GLOBSPACE;
gargv = xmalloc(sizeof(Char *) * (size_t)gargsiz);
gargv[0] = 0;
gargc = 0;
}
void
rscan(Char **t, void (*f)(int))
{
Char *p;
while ((p = *t++) != NULL)
while (*p)
(*f) (*p++);
}
void
trim(Char **t)
{
Char *p;
while ((p = *t++) != NULL)
while (*p)
*p++ &= TRIM;
}
void
tglob(Char **t)
{
Char *p, c;
while ((p = *t++) != NULL) {
if (*p == '~' || *p == '=')
gflag |= G_CSH;
else if (*p == '{' &&
(p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
continue;
while ((c = *p++) != '\0') {
/*
* eat everything inside the matching backquotes
*/
if (c == '`') {
gflag |= G_CSH;
while (*p && *p != '`')
if (*p++ == '\\') {
if (*p) /* Quoted chars */
p++;
else
break;
}
if (*p) /* The matching ` */
p++;
else
break;
}
else if (c == '{')
gflag |= G_CSH;
else if (isglob(c))
gflag |= G_GLOB;
}
}
}
/*
* Command substitute cp. If literal, then this is a substitution from a
* << redirection, and so we should not crunch blanks and tabs, separating
* words only at newlines.
*/
Char **
dobackp(Char *cp, int literal)
{
Char word[MAXPATHLEN], *ep, *lp, *rp;
if (pargv) {
#ifdef notdef
abort();
#endif
blkfree(pargv);
}
pargsiz = GLOBSPACE;
pargv = xmalloc(sizeof(Char *) * (size_t)pargsiz);
pargv[0] = NULL;
pargcp = pargs = word;
pargc = 0;
pnleft = MAXPATHLEN - 4;
for (;;) {
for (lp = cp; *lp != '`'; lp++) {
if (*lp == 0) {
if (pargcp != pargs)
pword();
return (pargv);
}
psave(*lp);
}
lp++;
for (rp = lp; *rp && *rp != '`'; rp++)
if (*rp == '\\') {
rp++;
if (!*rp)
goto oops;
}
if (!*rp) {
oops:
stderror(ERR_UNMATCHED, '`');
}
ep = Strsave(lp);
ep[rp - lp] = 0;
backeval(ep, literal);
cp = rp + 1;
}
}
static void
backeval(Char *cp, int literal)
{
struct command faket;
char tibuf[BUFSIZE];
Char ibuf[BUFSIZE], *fakecom[2], *ip;
int pvec[2], c, quoted;
ssize_t icnt;
int hadnl;
hadnl = 0;
icnt = 0;
quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
faket.t_dtyp = NODE_COMMAND;
faket.t_dflg = 0;
faket.t_dlef = 0;
faket.t_drit = 0;
faket.t_dspr = 0;
faket.t_dcom = fakecom;
fakecom[0] = STRfakecom1;
fakecom[1] = 0;
/*
* We do the psave job to temporarily change the current job so that the
* following fork is considered a separate job. This is so that when
* backquotes are used in a builtin function that calls glob the "current
* job" is not corrupted. We only need one level of pushed jobs as long as
* we are sure to fork here.
*/
psavejob();
/*
* It would be nicer if we could integrate this redirection more with the
* routines in sh.sem.c by doing a fake execute on a builtin function that
* was piped out.
*/
mypipe(pvec);
if (pfork(&faket, -1) == 0) {
struct wordent fparaml;
struct command *t;
(void)close(pvec[0]);
(void)dmove(pvec[1], 1);
(void)dmove(SHERR, 2);
initdesc();
/*
* Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
* posted to comp.bugs.4bsd 12 Sep. 1989.
*/
if (pargv) /* mg, 21.dec.88 */
blkfree(pargv), pargv = 0, pargsiz = 0;
/* mg, 21.dec.88 */
arginp = cp;
for (arginp = cp; *cp; cp++) {
*cp &= TRIM;
if (*cp == '\n' || *cp == '\r')
*cp = ';';
}
/*
* In the child ``forget'' everything about current aliases or
* eval vectors.
*/
alvec = NULL;
evalvec = NULL;
alvecp = NULL;
evalp = NULL;
(void) lex(&fparaml);
if (seterr)
stderror(ERR_OLD);
alias(&fparaml);
t = syntax(fparaml.next, &fparaml, 0);
if (seterr)
stderror(ERR_OLD);
if (t)
t->t_dflg |= F_NOFORK;
(void)signal(SIGTSTP, SIG_IGN);
(void)signal(SIGTTIN, SIG_IGN);
(void)signal(SIGTTOU, SIG_IGN);
execute(t, -1, NULL, NULL);
exitstat();
}
xfree((ptr_t)cp);
(void)close(pvec[1]);
c = 0;
ip = NULL;
do {
int cnt;
cnt = 0;
for (;;) {
if (icnt == 0) {
int i;
ip = ibuf;
do
icnt = read(pvec[0], tibuf, BUFSIZE);
while (icnt == -1 && errno == EINTR);
if (icnt <= 0) {
c = -1;
break;
}
for (i = 0; i < icnt; i++)
ip[i] = (unsigned char) tibuf[i];
}
if (hadnl)
break;
--icnt;
c = (*ip++ & TRIM);
if (c == 0)
break;
if (c == '\n') {
/*
* Continue around the loop one more time, so that we can eat
* the last newline without terminating this word.
*/
hadnl = 1;
continue;
}
if (!quoted && (c == ' ' || c == '\t'))
break;
cnt++;
psave(c | quoted);
}
/*
* Unless at end-of-file, we will form a new word here if there were
* characters in the word, or in any case when we take text literally.
* If we didn't make empty words here when literal was set then we
* would lose blank lines.
*/
if (c != -1 && (cnt || literal))
pword();
hadnl = 0;
} while (c >= 0);
(void)close(pvec[0]);
pwait();
prestjob();
}
static void
psave(int c)
{
if (--pnleft <= 0)
stderror(ERR_WTOOLONG);
*pargcp++ = (Char)c;
}
static void
pword(void)
{
psave(0);
if (pargc == pargsiz - 1) {
pargsiz += GLOBSPACE;
pargv = (Char **)xrealloc((ptr_t)pargv,
(size_t)pargsiz * sizeof(Char *));
}
pargv[pargc++] = Strsave(pargs);
pargv[pargc] = NULL;
pargcp = pargs;
pnleft = MAXPATHLEN - 4;
}
int
Gmatch(Char *string, Char *pattern)
{
Char **blk, **p;
int gpol, gres;
gpol = 1;
gres = 0;
if (*pattern == '^') {
gpol = 0;
pattern++;
}
blk = xmalloc(GLOBSPACE * sizeof(Char *));
blk[0] = Strsave(pattern);
blk[1] = NULL;
expbrace(&blk, NULL, GLOBSPACE);
for (p = blk; *p; p++)
gres |= pmatch(string, *p);
blkfree(blk);
return(gres == gpol);
}
static int
pmatch(Char *string, Char *pattern)
{
int match, negate_range;
Char patternc, rangec, stringc;
for (;; ++string) {
stringc = *string & TRIM;
patternc = *pattern++;
switch (patternc) {
case 0:
return (stringc == 0);
case '?':
if (stringc == 0)
return (0);
break;
case '*':
if (!*pattern)
return (1);
while (*string)
if (Gmatch(string++, pattern))
return (1);
return (0);
case '[':
match = 0;
if ((negate_range = (*pattern == '^')) != 0)
pattern++;
while ((rangec = *pattern++) != '\0') {
if (rangec == ']')
break;
if (match)
continue;
if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') {
match = (stringc <= (*pattern & TRIM) &&
(*(pattern-2) & TRIM) <= stringc);
pattern++;
}
else
match = (stringc == (rangec & TRIM));
}
if (rangec == 0)
stderror(ERR_NAME | ERR_MISSING, ']');
if (match == negate_range)
return (0);
break;
default:
if ((patternc & TRIM) != stringc)
return (0);
break;
}
}
}
void
Gcat(Char *s1, Char *s2)
{
Char *p, *q;
ptrdiff_t n;
for (p = s1; *p++;)
continue;
for (q = s2; *q++;)
continue;
n = (p - s1) + (q - s2) - 1;
if (++gargc >= gargsiz) {
gargsiz += GLOBSPACE;
gargv = (Char **)xrealloc((ptr_t)gargv,
(size_t)gargsiz * sizeof(Char *));
}
gargv[gargc] = 0;
p = gargv[gargc - 1] = xmalloc((size_t)n * sizeof(Char));
for (q = s1; (*p++ = *q++) != '\0';)
continue;
for (p--, q = s2; (*p++ = *q++) != '\0';)
continue;
}
#ifdef FILEC
int
sortscmp(const ptr_t a, const ptr_t b)
{
#if defined(NLS) && !defined(NOSTRCOLL)
char buf[2048];
#endif
if (!a) /* check for NULL */
return (b ? 1 : 0);
if (!b)
return (-1);
if (!*(Char **)a) /* check for NULL */
return (*(Char **)b ? 1 : 0);
if (!*(Char **)b)
return (-1);
#if defined(NLS) && !defined(NOSTRCOLL)
(void)strcpy(buf, short2str(*(Char **)a));
return ((int)strcoll(buf, short2str(*(Char **)b)));
#else
return ((int)Strcmp(*(Char **)a, *(Char **)b));
#endif
}
#endif /* FILEC */

View File

@@ -1,207 +0,0 @@
/* $NetBSD: hist.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: hist.c,v 1.20 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include "csh.h"
#include "extern.h"
static void hfree(struct Hist *);
static void dohist1(struct Hist *, int *, int, int);
static void phist(struct Hist *, int);
void
savehist(struct wordent *sp)
{
struct Hist *hp, *np;
Char *cp;
int histlen;
histlen = 0;
/* throw away null lines */
if (sp->next->word[0] == '\n')
return;
cp = value(STRhistory);
if (*cp) {
Char *p = cp;
while (*p) {
if (!Isdigit(*p)) {
histlen = 0;
break;
}
histlen = histlen * 10 + *p++ - '0';
}
}
for (hp = &Histlist; (np = hp->Hnext) != NULL;)
if (eventno - np->Href >= histlen || histlen == 0)
hp->Hnext = np->Hnext, hfree(np);
else
hp = np;
(void) enthist(++eventno, sp, 1);
}
#ifdef EDIT
void
loadhist(struct Hist *hp) {
char *h = NULL;
if (hi == NULL || hp == NULL)
return;
loadhist(hp->Hnext);
if (sprlex(&h, &hp->Hlex) != -1) {
HistEvent ev;
history(hi, &ev, H_ENTER, h);
}
}
#endif
struct Hist *
enthist(int event, struct wordent *lp, int docopy)
{
struct Hist *np;
#ifdef EDIT
if (hi) {
char *h = NULL;
if (sprlex(&h, lp) != -1) {
HistEvent ev;
history(hi, &ev, H_ENTER, h);
}
}
#endif
np = xmalloc(sizeof(*np));
np->Hnum = np->Href = event;
if (docopy) {
copylex(&np->Hlex, lp);
}
else {
np->Hlex.next = lp->next;
lp->next->prev = &np->Hlex;
np->Hlex.prev = lp->prev;
lp->prev->next = &np->Hlex;
}
np->Hnext = Histlist.Hnext;
Histlist.Hnext = np;
return (np);
}
static void
hfree(struct Hist *hp)
{
freelex(&hp->Hlex);
xfree((ptr_t) hp);
}
void
/*ARGSUSED*/
dohist(Char **v, struct command *t)
{
sigset_t nsigset;
int hflg, n, rflg;
hflg = 0;
rflg = 0;
if (getn(value(STRhistory)) == 0)
return;
if (setintr) {
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGINT);
(void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL);
}
while (*++v && **v == '-') {
Char *vp = *v;
while (*++vp)
switch (*vp) {
case 'h':
hflg++;
break;
case 'r':
rflg++;
break;
case '-': /* ignore multiple '-'s */
break;
default:
stderror(ERR_HISTUS);
/* NOTREACHED */
}
}
if (*v)
n = getn(*v);
else {
n = getn(value(STRhistory));
}
dohist1(Histlist.Hnext, &n, rflg, hflg);
}
static void
dohist1(struct Hist *hp, int *np, int rflg, int hflg)
{
int print;
print = (*np) > 0;
for (; hp != 0; hp = hp->Hnext) {
(*np)--;
hp->Href++;
if (rflg == 0) {
dohist1(hp->Hnext, np, rflg, hflg);
if (print)
phist(hp, hflg);
return;
}
if (*np >= 0)
phist(hp, hflg);
}
}
static void
phist(struct Hist *hp, int hflg)
{
if (hflg == 0)
(void)fprintf(cshout, "%6d\t", hp->Hnum);
prlex(cshout, &hp->Hlex);
}

View File

@@ -1,131 +0,0 @@
/* $NetBSD: init.c,v 1.11 2013/01/22 19:28:00 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: init.c,v 1.11 2013/01/22 19:28:00 christos Exp $");
#endif
#endif /* not lint */
#include <stdarg.h>
#include "csh.h"
#include "extern.h"
#define INF 1000
struct biltins bfunc[] =
{
{ "@", dolet, 0, INF },
{ "alias", doalias, 0, INF },
{ "bg", dobg, 0, INF },
{ "break", dobreak, 0, 0 },
{ "breaksw", doswbrk, 0, 0 },
{ "case", dozip, 0, 1 },
{ "cd", dochngd, 0, INF },
{ "chdir", dochngd, 0, INF },
{ "continue", docontin, 0, 0 },
{ "default", dozip, 0, 0 },
{ "dirs", dodirs, 0, INF },
{ "echo", doecho, 0, INF },
{ "else", doelse, 0, INF },
{ "end", doend, 0, 0 },
{ "endif", dozip, 0, 0 },
{ "endsw", dozip, 0, 0 },
{ "eval", doeval, 0, INF },
{ "exec", execash, 1, INF },
{ "exit", doexit, 0, INF },
{ "fg", dofg, 0, INF },
{ "foreach", doforeach, 3, INF },
{ "glob", doglob, 0, INF },
{ "goto", dogoto, 1, 1 },
{ "hashstat", hashstat, 0, 0 },
{ "history", dohist, 0, 2 },
{ "if", doif, 1, INF },
{ "jobs", dojobs, 0, 1 },
{ "kill", dokill, 1, INF },
{ "limit", dolimit, 0, 3 },
{ "linedit", doecho, 0, INF },
{ "login", dologin, 0, 1 },
{ "logout", dologout, 0, 0 },
{ "nice", donice, 0, INF },
{ "nohup", donohup, 0, INF },
{ "notify", donotify, 0, INF },
{ "onintr", doonintr, 0, 2 },
{ "popd", dopopd, 0, INF },
{ "printf", doprintf, 1, INF },
{ "pushd", dopushd, 0, INF },
{ "rehash", dohash, 0, 0 },
{ "repeat", dorepeat, 2, INF },
{ "set", doset, 0, INF },
{ "setenv", dosetenv, 0, 2 },
{ "shift", shift, 0, 1 },
{ "source", dosource, 1, 2 },
{ "stop", dostop, 1, INF },
{ "suspend", dosuspend, 0, 0 },
{ "switch", doswitch, 1, INF },
{ "time", dotime, 0, INF },
{ "umask", doumask, 0, 1 },
{ "unalias", unalias, 1, INF },
{ "unhash", dounhash, 0, 0 },
{ "unlimit", dounlimit, 0, INF },
{ "unset", unset, 1, INF },
{ "unsetenv", dounsetenv, 1, INF },
{ "wait", dowait, 0, 0 },
{ "which", dowhich, 1, INF },
{ "while", dowhile, 1, INF }
};
int nbfunc = sizeof(bfunc) / sizeof(*bfunc);
struct srch srchn[] =
{
{ "@", T_LET },
{ "break", T_BREAK },
{ "breaksw", T_BRKSW },
{ "case", T_CASE },
{ "default", T_DEFAULT },
{ "else", T_ELSE },
{ "end", T_END },
{ "endif", T_ENDIF },
{ "endsw", T_ENDSW },
{ "exit", T_EXIT },
{ "foreach", T_FOREACH },
{ "goto", T_GOTO },
{ "if", T_IF },
{ "label", T_LABEL },
{ "set", T_SET },
{ "switch", T_SWITCH },
{ "while", T_WHILE }
};
int nsrchn = sizeof(srchn) / sizeof(*srchn);

File diff suppressed because it is too large Load Diff

View File

@@ -1,407 +0,0 @@
/* $NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "csh.h"
#include "extern.h"
static int renum(int, int);
int
any(const char *s, int c)
{
if (!s)
return (0); /* Check for nil pointer */
while (*s)
if (*s++ == c)
return (1);
return (0);
}
char *
strsave(const char *s)
{
const char *n;
char *p, *r;
if (s == NULL)
s = "";
for (n = s; *n++;)
continue;
r = p = xmalloc((size_t)(n - s) * sizeof(*p));
while ((*p++ = *s++) != '\0')
continue;
return (r);
}
Char **
blkend(Char **up)
{
while (*up)
up++;
return (up);
}
void
blkpr(FILE *fp, Char **av)
{
for (; *av; av++) {
(void)fprintf(fp, "%s", vis_str(*av));
if (av[1])
(void)fprintf(fp, " ");
}
}
int
blklen(Char **av)
{
int i;
i = 0;
while (*av++)
i++;
return (i);
}
Char **
blkcpy(Char **oav, Char **bv)
{
Char **av;
av = oav;
while ((*av++ = *bv++) != NULL)
continue;
return (oav);
}
Char **
blkcat(Char **up, Char **vp)
{
(void)blkcpy(blkend(up), vp);
return (up);
}
void
blkfree(Char **av0)
{
Char **av;
av = av0;
if (!av0)
return;
for (; *av; av++)
xfree((ptr_t) * av);
xfree((ptr_t) av0);
}
Char **
saveblk(Char **v)
{
Char **newv, **onewv;
if (v == NULL)
return NULL;
newv = xcalloc((size_t)(blklen(v) + 1), sizeof(*newv));
onewv = newv;
while (*v)
*newv++ = Strsave(*v++);
return (onewv);
}
#ifdef NOTUSED
char *
strstr(char *s, char *t)
{
do {
char *ss;
char *tt;
ss = s;
tt = t;
do
if (*tt == '\0')
return (s);
while (*ss++ == *tt++);
} while (*s++ != '\0');
return (NULL);
}
#endif /* NOTUSED */
#ifndef SHORT_STRINGS
char *
strspl(char *cp, char *dp)
{
char *ep, *p, *q;
if (!cp)
cp = "";
if (!dp)
dp = "";
for (p = cp; *p++;)
continue;
for (q = dp; *q++;)
continue;
ep = xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(*ep)));
for (p = ep, q = cp; *p++ = *q++;)
continue;
for (p--, q = dp; *p++ = *q++;)
continue;
return (ep);
}
#endif
Char **
blkspl(Char **up, Char **vp)
{
Char **wp;
wp = xcalloc((size_t)(blklen(up) + blklen(vp) + 1), sizeof(*wp));
(void)blkcpy(wp, up);
return (blkcat(wp, vp));
}
Char
lastchr(Char *cp)
{
if (!cp)
return (0);
if (!*cp)
return (0);
while (cp[1])
cp++;
return (*cp);
}
/*
* This routine is called after an error to close up
* any units which may have been left open accidentally.
*/
void
closem(void)
{
int f;
int nofile;
#ifdef F_CLOSEM
nofile = FOLDSTD + 1;
if (fcntl(nofile, F_CLOSEM, 0) == -1)
#endif
nofile = NOFILE;
for (f = 0; f < nofile; f++)
if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
f != FSHTTY)
(void) close(f);
}
void
donefds(void)
{
(void)close(0);
(void)close(1);
(void)close(2);
didfds = 0;
}
/*
* Move descriptor i to j.
* If j is -1 then we just want to get i to a safe place,
* i.e. to a unit > 2. This also happens in dcopy.
*/
int
dmove(int i, int j)
{
if (i == j || i < 0)
return (i);
if (j >= 0) {
(void)dup2(i, j);
if (j != i)
(void)close(i);
return (j);
}
j = dcopy(i, j);
if (j != i)
(void)close(i);
return (j);
}
int
dcopy(int i, int j)
{
if (i == j || i < 0 || (j < 0 && i > 2))
return (i);
if (j >= 0) {
(void)dup2(i, j);
return (j);
}
return (renum(i, j));
}
static int
renum(int i, int j)
{
int k;
k = dup(i);
if (k < 0)
return (-1);
if (j == -1 && k > 2)
return (k);
if (k != j) {
j = renum(k, j);
(void)close(k);
return (j);
}
return (k);
}
/*
* Left shift a command argument list, discarding
* the first c arguments. Used in "shift" commands
* as well as by commands like "repeat".
*/
void
lshift(Char **v, size_t c)
{
Char **u;
for (u = v; *u && c-- > 0; u++)
xfree((ptr_t) *u);
(void)blkcpy(v, u);
}
int
number(Char *cp)
{
if (!cp)
return(0);
if (*cp == '-') {
cp++;
if (!Isdigit(*cp))
return (0);
cp++;
}
while (*cp && Isdigit(*cp))
cp++;
return (*cp == 0);
}
Char **
copyblk(Char **v)
{
Char **nv;
nv = xcalloc((size_t)(blklen(v) + 1), sizeof(*nv));
return (blkcpy(nv, v));
}
#ifndef SHORT_STRINGS
char *
strend(char *cp)
{
if (!cp)
return (cp);
while (*cp)
cp++;
return (cp);
}
#endif /* SHORT_STRINGS */
Char *
strip(Char *cp)
{
Char *dp;
dp = cp;
if (!cp)
return (cp);
while ((*dp++ &= TRIM) != '\0')
continue;
return (cp);
}
Char *
quote(Char *cp)
{
Char *dp;
dp = cp;
if (!cp)
return (cp);
while (*dp != '\0')
*dp++ |= QUOTE;
return (cp);
}
void
udvar(Char *name)
{
setname(vis_str(name));
stderror(ERR_NAME | ERR_UNDVAR);
/* NOTREACHED */
}
int
prefix(Char *sub, Char *str)
{
for (;;) {
if (*sub == 0)
return (1);
if (*str == 0)
return (0);
if (*sub++ != *str++)
return (0);
}
}

View File

@@ -1,640 +0,0 @@
/* $NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "csh.h"
#include "extern.h"
static void asyntax(struct wordent *, struct wordent *);
static void asyn0(struct wordent *, struct wordent *);
static void asyn3(struct wordent *, struct wordent *);
static struct wordent *freenod(struct wordent *, struct wordent *);
static struct command *syn0(struct wordent *, struct wordent *, int);
static struct command *syn1(struct wordent *, struct wordent *, int);
static struct command *syn1a(struct wordent *, struct wordent *, int);
static struct command *syn1b(struct wordent *, struct wordent *, int);
static struct command *syn2(struct wordent *, struct wordent *, int);
static struct command *syn3(struct wordent *, struct wordent *, int);
#define ALEFT 21 /* max of 20 alias expansions */
#define HLEFT 11 /* max of 10 history expansions */
/*
* Perform aliasing on the word list lex
* Do a (very rudimentary) parse to separate into commands.
* If word 0 of a command has an alias, do it.
* Repeat a maximum of 20 times.
*/
static int aleft;
extern int hleft;
void
alias(struct wordent *lexp)
{
jmp_buf osetexit;
aleft = ALEFT;
hleft = HLEFT;
getexit(osetexit);
(void)setexit();
if (haderr) {
resexit(osetexit);
reset();
}
if (--aleft == 0)
stderror(ERR_ALIASLOOP);
asyntax(lexp->next, lexp);
resexit(osetexit);
}
static void
asyntax(struct wordent *p1, struct wordent *p2)
{
while (p1 != p2)
if (any(";&\n", p1->word[0]))
p1 = p1->next;
else {
asyn0(p1, p2);
return;
}
}
static void
asyn0(struct wordent *p1, struct wordent *p2)
{
struct wordent *p;
int l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
if (l < 0)
stderror(ERR_TOOMANYRP);
continue;
case '>':
if (p->next != p2 && eq(p->next->word, STRand))
p = p->next;
continue;
case '&':
case '|':
case ';':
case '\n':
if (l != 0)
continue;
asyn3(p1, p);
asyntax(p->next, p2);
return;
}
if (l == 0)
asyn3(p1, p2);
}
static void
asyn3(struct wordent *p1, struct wordent *p2)
{
struct varent *ap;
struct wordent alout;
int redid;
if (p1 == p2)
return;
if (p1->word[0] == '(') {
for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
if (p2 == p1)
return;
if (p2 == p1->next)
return;
asyn0(p1->next, p2);
return;
}
ap = adrof1(p1->word, &aliases);
if (ap == 0)
return;
alhistp = p1->prev;
alhistt = p2;
alvec = ap->vec;
redid = lex(&alout);
alhistp = alhistt = 0;
alvec = 0;
if (seterr) {
freelex(&alout);
stderror(ERR_OLD);
}
if (p1->word[0] && eq(p1->word, alout.next->word)) {
Char *cp;
cp = alout.next->word;
alout.next->word = Strspl(STRQNULL, cp);
xfree((ptr_t) cp);
}
p1 = freenod(p1, redid ? p2 : p1->next);
if (alout.next != &alout) {
p1->next->prev = alout.prev->prev;
alout.prev->prev->next = p1->next;
alout.next->prev = p1;
p1->next = alout.next;
xfree((ptr_t)alout.prev->word);
xfree((ptr_t)(alout.prev));
}
reset(); /* throw! */
}
static struct wordent *
freenod(struct wordent *p1, struct wordent *p2)
{
struct wordent *retp;
retp = p1->prev;
while (p1 != p2) {
xfree((ptr_t)p1->word);
p1 = p1->next;
xfree((ptr_t) (p1->prev));
}
retp->next = p2;
p2->prev = retp;
return (retp);
}
#define PHERE 1
#define PIN 2
#define POUT 4
#define PERR 8
/*
* syntax
* empty
* syn0
*/
struct command *
syntax(struct wordent *p1, struct wordent *p2, int flags)
{
while (p1 != p2)
if (any(";&\n", p1->word[0]))
p1 = p1->next;
else
return (syn0(p1, p2, flags));
return (0);
}
/*
* syn0
* syn1
* syn1 & syntax
*/
static struct command *
syn0(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *p;
struct command *t, *t1;
int l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
if (l < 0)
seterror(ERR_TOOMANYRP);
continue;
case '|':
if (p->word[1] == '|')
continue;
/* FALLTHROUGH */
case '>':
if (p->next != p2 && eq(p->next->word, STRand))
p = p->next;
continue;
case '&':
if (l != 0)
break;
if (p->word[1] == '&')
continue;
t1 = syn1(p1, p, flags);
if (t1->t_dtyp == NODE_LIST ||
t1->t_dtyp == NODE_AND ||
t1->t_dtyp == NODE_OR) {
t = (struct command *)xcalloc(1, sizeof(*t));
t->t_dtyp = NODE_PAREN;
t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
t->t_dspr = t1;
t1 = t;
}
else
t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
t = (struct command *)xcalloc(1, sizeof(*t));
t->t_dtyp = NODE_LIST;
t->t_dflg = 0;
t->t_dcar = t1;
t->t_dcdr = syntax(p, p2, flags);
return (t);
}
if (l == 0)
return (syn1(p1, p2, flags));
seterror(ERR_TOOMANYLP);
return (0);
}
/*
* syn1
* syn1a
* syn1a ; syntax
*/
static struct command *
syn1(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *p;
struct command *t;
int l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case ';':
case '\n':
if (l != 0)
break;
t = (struct command *) xcalloc(1, sizeof(*t));
t->t_dtyp = NODE_LIST;
t->t_dcar = syn1a(p1, p, flags);
t->t_dcdr = syntax(p->next, p2, flags);
if (t->t_dcdr == 0)
t->t_dcdr = t->t_dcar, t->t_dcar = 0;
return (t);
}
return (syn1a(p1, p2, flags));
}
/*
* syn1a
* syn1b
* syn1b || syn1a
*/
static struct command *
syn1a(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *p;
struct command *t;
int l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case '|':
if (p->word[1] != '|')
continue;
if (l == 0) {
t = (struct command *)xcalloc(1, sizeof(*t));
t->t_dtyp = NODE_OR;
t->t_dcar = syn1b(p1, p, flags);
t->t_dcdr = syn1a(p->next, p2, flags);
t->t_dflg = 0;
return (t);
}
continue;
}
return (syn1b(p1, p2, flags));
}
/*
* syn1b
* syn2
* syn2 && syn1b
*/
static struct command *
syn1b(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *p;
struct command *t;
int l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case '&':
if (p->word[1] == '&' && l == 0) {
t = (struct command *)xcalloc(1, sizeof(*t));
t->t_dtyp = NODE_AND;
t->t_dcar = syn2(p1, p, flags);
t->t_dcdr = syn1b(p->next, p2, flags);
t->t_dflg = 0;
return (t);
}
continue;
}
return (syn2(p1, p2, flags));
}
/*
* syn2
* syn3
* syn3 | syn2
* syn3 |& syn2
*/
static struct command *
syn2(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *p, *pn;
struct command *t;
int f, l;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
l++;
continue;
case ')':
l--;
continue;
case '|':
if (l != 0)
continue;
t = (struct command *)xcalloc(1, sizeof(*t));
f = flags | POUT;
pn = p->next;
if (pn != p2 && pn->word[0] == '&') {
f |= PERR;
t->t_dflg |= F_STDERR;
}
t->t_dtyp = NODE_PIPE;
t->t_dcar = syn3(p1, p, f);
if (pn != p2 && pn->word[0] == '&')
p = pn;
t->t_dcdr = syn2(p->next, p2, flags | PIN);
return (t);
}
return (syn3(p1, p2, flags));
}
static char RELPAR[] = {'<', '>', '(', ')', '\0'};
/*
* syn3
* ( syn0 ) [ < in ] [ > out ]
* word word* [ < in ] [ > out ]
* KEYWORD ( word* ) word* [ < in ] [ > out ]
*
* KEYWORD = (@ exit foreach if set switch test while)
*/
static struct command *
syn3(struct wordent *p1, struct wordent *p2, int flags)
{
struct wordent *lp, *p, *rp;
struct command *t;
Char **av;
int c, l, n;
int specp;
specp = 0;
if (p1 != p2) {
p = p1;
again:
switch (srchx(p->word)) {
case T_ELSE:
p = p->next;
if (p != p2)
goto again;
break;
case T_EXIT:
case T_FOREACH:
case T_IF:
case T_LET:
case T_SET:
case T_SWITCH:
case T_WHILE:
specp = 1;
break;
}
}
n = 0;
l = 0;
for (p = p1; p != p2; p = p->next)
switch (p->word[0]) {
case '(':
if (specp)
n++;
l++;
continue;
case ')':
if (specp)
n++;
l--;
continue;
case '>':
case '<':
if (l != 0) {
if (specp)
n++;
continue;
}
if (p->next == p2)
continue;
if (any(RELPAR, p->next->word[0]))
continue;
n--;
continue;
default:
if (!specp && l != 0)
continue;
n++;
continue;
}
if (n < 0)
n = 0;
t = (struct command *)xcalloc(1, sizeof(*t));
av = (Char **)xcalloc((size_t)(n + 1), sizeof(Char **));
t->t_dcom = av;
n = 0;
if (p2->word[0] == ')')
t->t_dflg = F_NOFORK;
lp = 0;
rp = 0;
l = 0;
for (p = p1; p != p2; p = p->next) {
c = p->word[0];
switch (c) {
case '(':
if (l == 0) {
if (lp != 0 && !specp)
seterror(ERR_BADPLP);
lp = p->next;
}
l++;
goto savep;
case ')':
l--;
if (l == 0)
rp = p;
goto savep;
case '>':
if (l != 0)
goto savep;
if (p->word[1] == '>')
t->t_dflg |= F_APPEND;
if (p->next != p2 && eq(p->next->word, STRand)) {
t->t_dflg |= F_STDERR, p = p->next;
if (flags & (POUT | PERR)) {
seterror(ERR_OUTRED);
continue;
}
}
if (p->next != p2 && eq(p->next->word, STRbang))
t->t_dflg |= F_OVERWRITE, p = p->next;
if (p->next == p2) {
seterror(ERR_MISRED);
continue;
}
p = p->next;
if (any(RELPAR, p->word[0])) {
seterror(ERR_MISRED);
continue;
}
if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
seterror(ERR_OUTRED);
else
t->t_drit = Strsave(p->word);
continue;
case '<':
if (l != 0)
goto savep;
if (p->word[1] == '<')
t->t_dflg |= F_READ;
if (p->next == p2) {
seterror(ERR_MISRED);
continue;
}
p = p->next;
if (any(RELPAR, p->word[0])) {
seterror(ERR_MISRED);
continue;
}
if ((flags & PHERE) && (t->t_dflg & F_READ))
seterror(ERR_REDPAR);
else if ((flags & PIN) || t->t_dlef)
seterror(ERR_INRED);
else
t->t_dlef = Strsave(p->word);
continue;
savep:
if (!specp)
continue;
/* FALLTHROUGH */
default:
if (l != 0 && !specp)
continue;
if (seterr == 0)
av[n] = Strsave(p->word);
n++;
continue;
}
}
if (lp != 0 && !specp) {
if (n != 0)
seterror(ERR_BADPLPS);
t->t_dtyp = NODE_PAREN;
t->t_dspr = syn0(lp, rp, PHERE);
}
else {
if (n == 0)
seterror(ERR_NULLCOM);
t->t_dtyp = NODE_COMMAND;
}
return (t);
}
void
freesyn(struct command *t)
{
Char **v;
if (t == 0)
return;
switch (t->t_dtyp) {
case NODE_COMMAND:
for (v = t->t_dcom; *v; v++)
xfree((ptr_t) * v);
xfree((ptr_t)(t->t_dcom));
xfree((ptr_t)t->t_dlef);
xfree((ptr_t)t->t_drit);
break;
case NODE_PAREN:
freesyn(t->t_dspr);
xfree((ptr_t)t->t_dlef);
xfree((ptr_t)t->t_drit);
break;
case NODE_AND:
case NODE_OR:
case NODE_PIPE:
case NODE_LIST:
freesyn(t->t_dcar), freesyn(t->t_dcdr);
break;
}
xfree((ptr_t)t);
}

View File

@@ -1,44 +0,0 @@
/* $NetBSD: pathnames.h,v 1.8 2003/08/07 09:05:06 agc Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _PATHNAMES_H_
#define _PATHNAMES_H_
#define _PATH_BIN "/bin"
#define _PATH_DOTCSHRC "/etc/csh.cshrc"
#define _PATH_DOTLOGIN "/etc/csh.login"
#define _PATH_DOTLOGOUT "/etc/csh.logout"
#define _PATH_LOGIN "/usr/bin/login"
#define _PATH_USRBIN "/usr/bin"
#endif /* !_PATHNAMES_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +0,0 @@
/* $NetBSD: proc.h,v 1.14 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. 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.
*
* @(#)proc.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _PROC_H_
#define _PROC_H_
/*
* Structure for each process the shell knows about:
* allocated and filled by pcreate.
* flushed by pflush; freeing always happens at top level
* so the interrupt level has less to worry about.
* processes are related to "friends" when in a pipeline;
* p_friends links makes a circular list of such jobs
*/
struct process {
struct process *p_next; /* next in global "proclist" */
struct process *p_friends; /* next in job list (or self) */
struct directory *p_cwd; /* cwd of the job (only in head) */
int p_flags; /* various job status flags */
int p_reason; /* reason for entering this state */
int p_index; /* shorthand job index */
pid_t p_pid;
pid_t p_jobid; /* pid of job leader */
/* if a job is stopped/background p_jobid gives its pgrp */
struct timespec p_btime; /* begin time */
struct timespec p_etime; /* end time */
struct rusage p_rusage;
Char *p_command; /* first PMAXLEN chars of command */
};
/* flag values for p_flags */
#define PRUNNING (1<<0) /* running */
#define PSTOPPED (1<<1) /* stopped */
#define PNEXITED (1<<2) /* normally exited */
#define PAEXITED (1<<3) /* abnormally exited */
#define PSIGNALED (1<<4) /* terminated by a signal != SIGINT */
#define PNOTIFY (1<<5) /* notify async when done */
#define PTIME (1<<6) /* job times should be printed */
#define PAWAITED (1<<7) /* top level is waiting for it */
#define PFOREGND (1<<8) /* started in shells pgrp */
#define PDUMPED (1<<9) /* process dumped core */
#define PERR (1<<10) /* diagnostic output also piped out */
#define PPOU (1<<11) /* piped output */
#define PREPORTED (1<<12) /* status has been reported */
#define PINTERRUPTED (1<<13) /* job stopped via interrupt signal */
#define PPTIME (1<<14) /* time individual process */
#define PNEEDNOTE (1<<15) /* notify as soon as practical */
#define PALLSTATES (PRUNNING|PSTOPPED|PNEXITED|PAEXITED|PSIGNALED|PINTERRUPTED)
#define PMAXLEN 80
/* defines for arguments to pprint */
#define NUMBER 01
#define NAME 02
#define REASON 04
#define AMPERSAND 010
#define FANCY 020
#define SHELLDIR 040 /* print shell's dir if not the same */
#define JOBDIR 0100 /* print job's dir if not the same */
#define AREASON 0200
struct process proclist; /* list head of all processes */
int pnoprocesses; /* pchild found nothing to wait for */
struct process *pholdjob; /* one level stack of current jobs */
struct process *pcurrjob; /* current job */
struct process *pcurrent; /* current job in table */
struct process *pprevious; /* previous job in table */
int pmaxindex; /* current maximum job index */
#endif /* !_PROC_H_ */

View File

@@ -1,646 +0,0 @@
/* $NetBSD: sem.c,v 1.29 2011/08/29 14:51:17 joerg Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)sem.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: sem.c,v 1.29 2011/08/29 14:51:17 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "csh.h"
#include "extern.h"
#include "proc.h"
__dead static void vffree(int);
static Char *splicepipe(struct command *t, Char *);
static void doio(struct command *t, int *, int *);
static void chkclob(char *);
void
execute(struct command *t, int wtty, int *pipein, int *pipeout)
{
static sigset_t csigset, ocsigset;
static int nosigchld = 0, onosigchld = 0;
volatile int wanttty = wtty;
struct biltins * volatile bifunc;
int pv[2], pid;
sigset_t nsigset;
int forked;
UNREGISTER(forked);
UNREGISTER(bifunc);
UNREGISTER(wanttty);
forked = 0;
pid = 0;
if (t == 0)
return;
if (t->t_dflg & F_AMPERSAND)
wanttty = 0;
switch (t->t_dtyp) {
case NODE_COMMAND:
if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
(void)Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
if ((t->t_dflg & F_REPEAT) == 0)
Dfix(t); /* $ " ' \ */
if (t->t_dcom[0] == 0)
return;
/* FALLTHROUGH */
case NODE_PAREN:
if (t->t_dflg & F_PIPEOUT)
mypipe(pipeout);
/*
* Must do << early so parent will know where input pointer should be.
* If noexec then this is all we do.
*/
if (t->t_dflg & F_READ) {
(void)close(0);
heredoc(t->t_dlef);
if (noexec)
(void)close(0);
}
set(STRstatus, Strsave(STR0));
/*
* This mess is the necessary kludge to handle the prefix builtins:
* nice, nohup, time. These commands can also be used by themselves,
* and this is not handled here. This will also work when loops are
* parsed.
*/
while (t->t_dtyp == NODE_COMMAND)
if (eq(t->t_dcom[0], STRnice)) {
if (t->t_dcom[1]) {
if (strchr("+-", t->t_dcom[1][0])) {
if (t->t_dcom[2]) {
setname("nice");
t->t_nice =
getn(t->t_dcom[1]);
lshift(t->t_dcom, 2);
t->t_dflg |= F_NICE;
}
else
break;
} else {
t->t_nice = 4;
lshift(t->t_dcom, 1);
t->t_dflg |= F_NICE;
}
} else
break;
} else if (eq(t->t_dcom[0], STRnohup)) {
if (t->t_dcom[1]) {
t->t_dflg |= F_NOHUP;
lshift(t->t_dcom, 1);
}
else
break;
} else if (eq(t->t_dcom[0], STRtime)) {
if (t->t_dcom[1]) {
t->t_dflg |= F_TIME;
lshift(t->t_dcom, 1);
}
else
break;
} else
break;
/* is it a command */
if (t->t_dtyp == NODE_COMMAND) {
/*
* Check if we have a builtin function and remember which one.
*/
bifunc = isbfunc(t);
if (noexec && bifunc != NULL) {
/*
* Continue for builtins that are part of the scripting language
*/
if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin &&
bifunc->bfunct != doelse && bifunc->bfunct != doend &&
bifunc->bfunct != doforeach && bifunc->bfunct != dogoto &&
bifunc->bfunct != doif && bifunc->bfunct != dorepeat &&
bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch &&
bifunc->bfunct != dowhile && bifunc->bfunct != dozip)
break;
}
}
else { /* not a command */
bifunc = NULL;
if (noexec)
break;
}
/*
* We fork only if we are timed, or are not the end of a parenthesized
* list and not a simple builtin function. Simple meaning one that is
* not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
* fork in some of these cases.
*/
/*
* Prevent forking cd, pushd, popd, chdir cause this will cause the
* shell not to change dir!
*/
if (bifunc && (bifunc->bfunct == dochngd ||
bifunc->bfunct == dopushd ||
bifunc->bfunct == dopopd))
t->t_dflg &= ~(F_NICE);
if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
(!bifunc || t->t_dflg &
(F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
/*
* We have to fork for eval too.
*/
(bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 &&
bifunc->bfunct == doeval)) {
if (t->t_dtyp == NODE_PAREN ||
t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
forked++;
/*
* We need to block SIGCHLD here, so that if the process does
* not die before we can set the process group
*/
if (wanttty >= 0 && !nosigchld) {
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGCHLD);
(void)sigprocmask(SIG_BLOCK, &nsigset, &csigset);
nosigchld = 1;
}
pid = pfork(t, wanttty);
if (pid == 0 && nosigchld) {
(void)sigprocmask(SIG_SETMASK, &csigset, NULL);
nosigchld = 0;
}
else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
backpid = pid;
}
else {
int ochild, osetintr, ohaderr, odidfds;
int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
sigset_t osigset;
/*
* Prepare for the vfork by saving everything that the child
* corrupts before it exec's. Note that in some signal
* implementations which keep the signal info in user space
* (e.g. Sun's) it will also be necessary to save and restore
* the current sigaction's for the signals the child touches
* before it exec's.
*/
if (wanttty >= 0 && !nosigchld && !noexec) {
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGCHLD);
(void)sigprocmask(SIG_BLOCK, &nsigset, &csigset);
nosigchld = 1;
}
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGCHLD);
(void)sigaddset(&nsigset, SIGINT);
(void)sigprocmask(SIG_BLOCK, &nsigset, &osigset);
ochild = child;
osetintr = setintr;
ohaderr = haderr;
odidfds = didfds;
oSHIN = SHIN;
oSHOUT = SHOUT;
oSHERR = SHERR;
oOLDSTD = OLDSTD;
otpgrp = tpgrp;
ocsigset = csigset;
onosigchld = nosigchld;
Vsav = Vdp = 0;
Vexpath = 0;
Vt = 0;
pid = vfork();
if (pid < 0) {
(void)sigprocmask(SIG_SETMASK, &osigset, NULL);
stderror(ERR_NOPROC);
}
forked++;
if (pid) { /* parent */
child = ochild;
setintr = osetintr;
haderr = ohaderr;
didfds = odidfds;
SHIN = oSHIN;
SHOUT = oSHOUT;
SHERR = oSHERR;
OLDSTD = oOLDSTD;
tpgrp = otpgrp;
csigset = ocsigset;
nosigchld = onosigchld;
xfree((ptr_t) Vsav);
Vsav = 0;
xfree((ptr_t) Vdp);
Vdp = 0;
xfree((ptr_t) Vexpath);
Vexpath = 0;
blkfree((Char **) Vt);
Vt = 0;
/* this is from pfork() */
palloc(pid, t);
(void)sigprocmask(SIG_SETMASK, &osigset, NULL);
}
else { /* child */
/* this is from pfork() */
int pgrp;
int ignint = 0;
if (nosigchld) {
(void)sigprocmask(SIG_SETMASK, &csigset, NULL);
nosigchld = 0;
}
if (setintr)
ignint =
(tpgrp == -1 &&
(t->t_dflg & F_NOINTERRUPT))
|| (gointr && eq(gointr, STRminus));
pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
child++;
if (setintr) {
setintr = 0;
if (ignint) {
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
}
else {
(void)signal(SIGINT, vffree);
(void)signal(SIGQUIT, SIG_DFL);
}
if (wanttty >= 0) {
(void)signal(SIGTSTP, SIG_DFL);
(void)signal(SIGTTIN, SIG_DFL);
(void)signal(SIGTTOU, SIG_DFL);
}
(void)signal(SIGTERM, parterm);
}
else if (tpgrp == -1 &&
(t->t_dflg & F_NOINTERRUPT)) {
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
}
pgetty(wanttty, pgrp);
if (t->t_dflg & F_NOHUP)
(void)signal(SIGHUP, SIG_IGN);
if (t->t_dflg & F_NICE)
(void)setpriority(PRIO_PROCESS, 0, t->t_nice);
}
}
}
if (pid != 0) {
/*
* It would be better if we could wait for the whole job when we
* knew the last process had been started. Pwait, in fact, does
* wait for the whole job anyway, but this test doesn't really
* express our intentions.
*/
if (didfds == 0 && t->t_dflg & F_PIPEIN) {
(void)close(pipein[0]);
(void)close(pipein[1]);
}
if ((t->t_dflg & F_PIPEOUT) == 0) {
if (nosigchld) {
(void)sigprocmask(SIG_SETMASK, &csigset, NULL);
nosigchld = 0;
}
if ((t->t_dflg & F_AMPERSAND) == 0)
pwait();
}
break;
}
doio(t, pipein, pipeout);
if (t->t_dflg & F_PIPEOUT) {
(void)close(pipeout[0]);
(void)close(pipeout[1]);
}
/*
* Perform a builtin function. If we are not forked, arrange for
* possible stopping
*/
if (bifunc) {
func(t, bifunc);
if (forked)
exitstat();
break;
}
if (t->t_dtyp != NODE_PAREN)
doexec(NULL, t);
/*
* For () commands must put new 0,1,2 in FSH* and recurse
*/
(void) ioctl(OLDSTD = dcopy(0, FOLDSTD), FIOCLEX, NULL);
(void) ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, NULL);
(void) ioctl(SHERR = dcopy(2, FSHERR), FIOCLEX, NULL);
(void) close(SHIN);
SHIN = -1;
didfds = 0;
wanttty = -1;
t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
execute(t->t_dspr, wanttty, NULL, NULL);
exitstat();
/* NOTREACHED */
case NODE_PIPE:
t->t_dcar->t_dflg |= F_PIPEOUT |
(t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
execute(t->t_dcar, wanttty, pipein, pv);
t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
if (wanttty > 0)
wanttty = 0; /* got tty already */
execute(t->t_dcdr, wanttty, pv, pipeout);
break;
case NODE_LIST:
if (t->t_dcar) {
t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
execute(t->t_dcar, wanttty, NULL, NULL);
/*
* In strange case of A&B make a new job after A
*/
if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
(t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
pendjob();
}
if (t->t_dcdr) {
t->t_dcdr->t_dflg |= t->t_dflg &
(F_NOFORK | F_NOINTERRUPT);
execute(t->t_dcdr, wanttty, NULL, NULL);
}
break;
case NODE_OR:
case NODE_AND:
if (t->t_dcar) {
t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
execute(t->t_dcar, wanttty, NULL, NULL);
if ((getn(value(STRstatus)) == 0) !=
(t->t_dtyp == NODE_AND))
return;
}
if (t->t_dcdr) {
t->t_dcdr->t_dflg |= t->t_dflg &
(F_NOFORK | F_NOINTERRUPT);
execute(t->t_dcdr, wanttty, NULL, NULL);
}
break;
}
/*
* Fall through for all breaks from switch
*
* If there will be no more executions of this command, flush all file
* descriptors. Places that turn on the F_REPEAT bit are responsible for
* doing donefds after the last re-execution
*/
if (didfds && !(t->t_dflg & F_REPEAT))
donefds();
}
static void
vffree(int i)
{
Char **v;
if ((v = gargv) != NULL) {
gargv = 0;
xfree((ptr_t) v);
}
if ((v = pargv) != NULL) {
pargv = 0;
xfree((ptr_t) v);
}
_exit(i);
/* NOTREACHED */
}
/*
* Expand and glob the words after an i/o redirection.
* If more than one word is generated, then update the command vector.
*
* This is done differently in all the shells:
* 1. in the bourne shell and ksh globbing is not performed
* 2. Bash/csh say ambiguous
* 3. zsh does i/o to/from all the files
* 4. itcsh concatenates the words.
*
* I don't know what is best to do. I think that Ambiguous is better
* than restructuring the command vector, because the user can get
* unexpected results. In any case, the command vector restructuring
* code is present and the user can choose it by setting noambiguous
*/
static Char *
splicepipe(struct command *t, Char *cp /* word after < or > */)
{
Char *blk[2];
if (adrof(STRnoambiguous)) {
Char **pv;
blk[0] = Dfix1(cp); /* expand $ */
blk[1] = NULL;
gflag = 0, tglob(blk);
if (gflag) {
pv = globall(blk);
if (pv == NULL) {
setname(vis_str(blk[0]));
xfree((ptr_t) blk[0]);
stderror(ERR_NAME | ERR_NOMATCH);
/* NOTREACHED */
}
gargv = NULL;
if (pv[1] != NULL) { /* we need to fix the command vector */
Char **av = blkspl(t->t_dcom, &pv[1]);
xfree((ptr_t) t->t_dcom);
t->t_dcom = av;
}
xfree((ptr_t) blk[0]);
blk[0] = pv[0];
xfree((ptr_t) pv);
}
}
else {
blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR);
xfree((ptr_t) blk[1]);
}
return(blk[0]);
}
/*
* Perform io redirection.
* We may or maynot be forked here.
*/
static void
doio(struct command *t, int *pipein, int *pipeout)
{
Char *cp;
int fd, flags;
flags = t->t_dflg;
if (didfds || (flags & F_REPEAT))
return;
if ((flags & F_READ) == 0) {/* F_READ already done */
if (t->t_dlef) {
char tmp[MAXPATHLEN+1];
/*
* so < /dev/std{in,out,err} work
*/
(void)dcopy(SHIN, 0);
(void)dcopy(SHOUT, 1);
(void)dcopy(SHERR, 2);
cp = splicepipe(t, t->t_dlef);
(void)strlcpy(tmp, short2str(cp), sizeof(tmp));
xfree((ptr_t) cp);
if ((fd = open(tmp, O_RDONLY)) < 0) {
stderror(ERR_SYSTEM, tmp, strerror(errno));
/* NOTREACHED */
}
(void)dmove(fd, 0);
}
else if (flags & F_PIPEIN) {
(void)close(0);
(void)dup(pipein[0]);
(void)close(pipein[0]);
(void)close(pipein[1]);
}
else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
(void)close(0);
(void)open(_PATH_DEVNULL, O_RDONLY);
}
else {
(void)close(0);
(void)dup(OLDSTD);
(void)ioctl(0, FIONCLEX, NULL);
}
}
if (t->t_drit) {
char tmp[MAXPATHLEN+1];
cp = splicepipe(t, t->t_drit);
(void)strlcpy(tmp, short2str(cp), sizeof(tmp));
xfree((ptr_t) cp);
/*
* so > /dev/std{out,err} work
*/
(void)dcopy(SHOUT, 1);
(void)dcopy(SHERR, 2);
if ((flags & F_APPEND) &&
#ifdef O_APPEND
(fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
#else
(fd = open(tmp, O_WRONLY)) >= 0)
(void)lseek(1, (off_t) 0, SEEK_END);
#endif
else {
if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
if (flags & F_APPEND) {
stderror(ERR_SYSTEM, tmp, strerror(errno));
/* NOTREACHED */
}
chkclob(tmp);
}
if ((fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
stderror(ERR_SYSTEM, tmp, strerror(errno));
/* NOTREACHED */
}
}
(void)dmove(fd, 1);
}
else if (flags & F_PIPEOUT) {
(void)close(1);
(void)dup(pipeout[1]);
}
else {
(void)close(1);
(void)dup(SHOUT);
(void)ioctl(1, FIONCLEX, NULL);
}
(void)close(2);
if (flags & F_STDERR) {
(void)dup(1);
}
else {
(void)dup(SHERR);
(void)ioctl(2, FIONCLEX, NULL);
}
didfds = 1;
}
void
mypipe(int *pv)
{
if (pipe(pv) < 0)
goto oops;
pv[0] = dmove(pv[0], -1);
pv[1] = dmove(pv[1], -1);
if (pv[0] >= 0 && pv[1] >= 0)
return;
oops:
stderror(ERR_PIPE);
/* NOTREACHED */
}
static void
chkclob(char *cp)
{
struct stat stb;
if (stat(cp, &stb) < 0)
return;
if (S_ISCHR(stb.st_mode))
return;
stderror(ERR_EXISTS, cp);
/* NOTREACHED */
}

View File

@@ -1,820 +0,0 @@
/* $NetBSD: set.c,v 1.33 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)set.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: set.c,v 1.33 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef SHORT_STRINGS
#include <string.h>
#endif /* SHORT_STRINGS */
#include "csh.h"
#include "extern.h"
static Char *getinx(Char *, int *);
static void asx(Char *, int, Char *);
static struct varent *getvx(Char *, int);
static Char *xset(Char *, Char ***);
static Char *operate(int, Char *, Char *);
static void putn1(int);
static struct varent *madrof(Char *, struct varent *);
static void unsetv1(struct varent *);
static void exportpath(Char **);
static void balance(struct varent *, int, int);
/*
* C Shell
*/
static void
update_vars(Char *vp)
{
if (eq(vp, STRpath)) {
struct varent *pt = adrof(STRpath);
if (pt == NULL)
stderror(ERR_NAME | ERR_UNDVAR);
else {
exportpath(pt->vec);
dohash(NULL, NULL);
}
}
else if (eq(vp, STRhistchars)) {
Char *pn = value(STRhistchars);
HIST = *pn++;
HISTSUB = *pn;
}
else if (eq(vp, STRuser)) {
Setenv(STRUSER, value(vp));
Setenv(STRLOGNAME, value(vp));
}
else if (eq(vp, STRwordchars)) {
word_chars = value(vp);
}
else if (eq(vp, STRterm))
Setenv(STRTERM, value(vp));
else if (eq(vp, STRhome)) {
Char *cp;
cp = Strsave(value(vp)); /* get the old value back */
/*
* convert to canonical pathname (possibly resolving symlinks)
*/
cp = dcanon(cp, cp);
set(vp, Strsave(cp)); /* have to save the new val */
/* and now mirror home with HOME */
Setenv(STRHOME, cp);
/* fix directory stack for new tilde home */
dtilde();
xfree((ptr_t)cp);
}
#ifdef FILEC
else if (eq(vp, STRfilec))
filec = 1;
#endif
#ifdef EDIT
else if (eq(vp, STRedit)) {
HistEvent ev;
editing = 1;
el = el_init_fd(getprogname(), cshin, cshout, csherr,
SHIN, SHOUT, SHERR);
el_set(el, EL_EDITOR, "emacs");
el_set(el, EL_PROMPT, printpromptstr);
hi = history_init();
history(hi, &ev, H_SETSIZE, getn(value(STRhistory)));
loadhist(Histlist.Hnext);
el_set(el, EL_HIST, history, hi);
}
#endif
}
void
/*ARGSUSED*/
doset(Char **v, struct command *t)
{
Char op, *p, **vecp, *vp;
int subscr = 0; /* XXX: GCC */
int hadsub;
v++;
p = *v++;
if (p == 0) {
prvars();
return;
}
do {
hadsub = 0;
vp = p;
if (letter(*p))
for (; alnum(*p); p++)
continue;
if (vp == p || !letter(*vp))
stderror(ERR_NAME | ERR_VARBEGIN);
if ((p - vp) > MAXVARLEN)
stderror(ERR_NAME | ERR_VARTOOLONG);
if (*p == '[') {
hadsub++;
p = getinx(p, &subscr);
}
if ((op = *p) != '\0') {
*p++ = 0;
if (*p == 0 && *v && **v == '(')
p = *v++;
}
else if (*v && eq(*v, STRequal)) {
op = '=', v++;
if (*v)
p = *v++;
}
if (op && op != '=')
stderror(ERR_NAME | ERR_SYNTAX);
if (eq(p, STRLparen)) {
Char **e = v;
if (hadsub)
stderror(ERR_NAME | ERR_SYNTAX);
for (;;) {
if (!*e)
stderror(ERR_NAME | ERR_MISSING, ')');
if (**e == ')')
break;
e++;
}
p = *e;
*e = 0;
vecp = saveblk(v);
set1(vp, vecp, &shvhed);
*e = p;
v = e + 1;
}
else if (hadsub)
asx(vp, subscr, Strsave(p));
else
set(vp, Strsave(p));
update_vars(vp);
} while ((p = *v++) != NULL);
}
static Char *
getinx(Char *cp, int *ip)
{
*ip = 0;
*cp++ = 0;
while (*cp && Isdigit(*cp))
*ip = *ip * 10 + *cp++ - '0';
if (*cp++ != ']')
stderror(ERR_NAME | ERR_SUBSCRIPT);
return (cp);
}
static void
asx(Char *vp, int subscr, Char *p)
{
struct varent *v;
v = getvx(vp, subscr);
xfree((ptr_t) v->vec[subscr - 1]);
v->vec[subscr - 1] = globone(p, G_APPEND);
}
static struct varent *
getvx(Char *vp, int subscr)
{
struct varent *v;
v = adrof(vp);
if (v == 0)
udvar(vp);
if (subscr < 1 || subscr > blklen(v->vec))
stderror(ERR_NAME | ERR_RANGE);
return (v);
}
void
/*ARGSUSED*/
dolet(Char **v, struct command *t)
{
Char c, op, *p, *vp;
int subscr = 0; /* XXX: GCC */
int hadsub;
v++;
p = *v++;
if (p == 0) {
prvars();
return;
}
do {
hadsub = 0;
vp = p;
if (letter(*p))
for (; alnum(*p); p++)
continue;
if (vp == p || !letter(*vp))
stderror(ERR_NAME | ERR_VARBEGIN);
if ((p - vp) > MAXVARLEN)
stderror(ERR_NAME | ERR_VARTOOLONG);
if (*p == '[') {
hadsub++;
p = getinx(p, &subscr);
}
if (*p == 0 && *v)
p = *v++;
if ((op = *p) != '\0')
*p++ = 0;
else
stderror(ERR_NAME | ERR_ASSIGN);
if (*p == '\0' && *v == NULL)
stderror(ERR_NAME | ERR_ASSIGN);
vp = Strsave(vp);
if (op == '=') {
c = '=';
p = xset(p, &v);
}
else {
c = *p++;
if (any("+-", c)) {
if (c != op || *p)
stderror(ERR_NAME | ERR_UNKNOWNOP);
p = Strsave(STR1);
}
else {
if (any("<>", op)) {
if (c != op)
stderror(ERR_NAME | ERR_UNKNOWNOP);
c = *p++;
stderror(ERR_NAME | ERR_SYNTAX);
}
if (c != '=')
stderror(ERR_NAME | ERR_UNKNOWNOP);
p = xset(p, &v);
}
}
if (op == '=') {
if (hadsub)
asx(vp, subscr, p);
else
set(vp, p);
} else if (hadsub) {
struct varent *gv = getvx(vp, subscr);
asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
}
else
set(vp, operate(op, value(vp), p));
if (eq(vp, STRpath)) {
struct varent *pt = adrof(STRpath);
if (pt == NULL)
stderror(ERR_NAME | ERR_UNDVAR);
else {
exportpath(pt->vec);
dohash(NULL, NULL);
}
}
xfree((ptr_t) vp);
if (c != '=')
xfree((ptr_t) p);
} while ((p = *v++) != NULL);
}
static Char *
xset(Char *cp, Char ***vp)
{
Char *dp;
if (*cp) {
dp = Strsave(cp);
--(*vp);
xfree((ptr_t) ** vp);
**vp = dp;
}
return (putn(expr(vp)));
}
static Char *
operate(int op, Char *vp, Char *p)
{
Char opr[2], **v, *vec[5], **vecp;
int i;
v = vec;
vecp = v;
if (op != '=') {
if (*vp)
*v++ = vp;
opr[0] = (Char)op;
opr[1] = 0;
*v++ = opr;
if (op == '<' || op == '>')
*v++ = opr;
}
*v++ = p;
*v++ = 0;
i = expr(&vecp);
if (*vecp)
stderror(ERR_NAME | ERR_EXPRESSION);
return (putn(i));
}
static Char *putp;
Char *
putn(int n)
{
static Char numbers[15];
putp = numbers;
if (n < 0) {
n = -n;
*putp++ = '-';
}
if ((unsigned int)n == 0x80000000U) {
*putp++ = '2';
n = 147483648;
}
putn1(n);
*putp = 0;
return (Strsave(numbers));
}
static void
putn1(int n)
{
if (n > 9)
putn1(n / 10);
*putp++ = (Char)(n % 10 + '0');
}
int
getn(Char *cp)
{
int n, sign;
sign = 0;
if (cp[0] == '+' && cp[1])
cp++;
if (*cp == '-') {
sign++;
cp++;
if (!Isdigit(*cp))
stderror(ERR_NAME | ERR_BADNUM);
}
n = 0;
while (Isdigit(*cp))
n = n * 10 + *cp++ - '0';
if (*cp)
stderror(ERR_NAME | ERR_BADNUM);
return (sign ? -n : n);
}
Char *
value1(Char *var, struct varent *head)
{
struct varent *vp;
vp = adrof1(var, head);
return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
}
static struct varent *
madrof(Char *pat, struct varent *vp)
{
struct varent *vp1;
for (; vp; vp = vp->v_right) {
if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
return vp1;
if (Gmatch(vp->v_name, pat))
return vp;
}
return vp;
}
struct varent *
adrof1(Char *name, struct varent *v)
{
int cmp;
v = v->v_left;
while (v && ((cmp = *name - *v->v_name) ||
(cmp = Strcmp(name, v->v_name))))
if (cmp < 0)
v = v->v_left;
else
v = v->v_right;
return v;
}
/*
* The caller is responsible for putting value in a safe place
*/
void
set(Char *var, Char *val)
{
Char **vec;
vec = xmalloc(2 * sizeof(*vec));
vec[0] = val;
vec[1] = 0;
set1(var, vec, &shvhed);
}
void
set1(Char *var, Char **vec, struct varent *head)
{
Char **oldv;
oldv = vec;
gflag = 0;
tglob(oldv);
if (gflag) {
vec = globall(oldv);
if (vec == 0) {
blkfree(oldv);
stderror(ERR_NAME | ERR_NOMATCH);
}
blkfree(oldv);
gargv = 0;
}
setq(var, vec, head);
}
void
setq(Char *name, Char **vec, struct varent *p)
{
struct varent *c;
int f;
f = 0; /* tree hangs off the header's left link */
while ((c = p->v_link[f]) != NULL) {
if ((f = *name - *c->v_name) == 0 &&
(f = Strcmp(name, c->v_name)) == 0) {
blkfree(c->vec);
goto found;
}
p = c;
f = f > 0;
}
p->v_link[f] = c = xmalloc(sizeof(*c));
c->v_name = Strsave(name);
c->v_bal = 0;
c->v_left = c->v_right = 0;
c->v_parent = p;
balance(p, f, 0);
found:
trim(c->vec = vec);
}
void
/*ARGSUSED*/
unset(Char **v, struct command *t)
{
unset1(v, &shvhed);
if (adrof(STRhistchars) == 0) {
HIST = '!';
HISTSUB = '^';
}
else if (adrof(STRwordchars) == 0)
word_chars = STR_WORD_CHARS;
#ifdef FILEC
else if (adrof(STRfilec) == 0)
filec = 0;
#endif
#ifdef EDIT
else if (adrof(STRedit) == 0) {
el_end(el);
history_end(hi);
el = NULL;
hi = NULL;
editing = 0;
}
#endif
}
void
unset1(Char *v[], struct varent *head)
{
struct varent *vp;
int cnt;
while (*++v) {
cnt = 0;
while ((vp = madrof(*v, head->v_left)) != NULL)
unsetv1(vp), cnt++;
if (cnt == 0)
setname(vis_str(*v));
}
}
void
unsetv(Char *var)
{
struct varent *vp;
if ((vp = adrof1(var, &shvhed)) == 0)
udvar(var);
unsetv1(vp);
}
static void
unsetv1(struct varent *p)
{
struct varent *c, *pp;
int f;
/*
* Free associated memory first to avoid complications.
*/
blkfree(p->vec);
xfree((ptr_t) p->v_name);
/*
* If p is missing one child, then we can move the other into where p is.
* Otherwise, we find the predecessor of p, which is guaranteed to have no
* right child, copy it into p, and move its left child into it.
*/
if (p->v_right == 0)
c = p->v_left;
else if (p->v_left == 0)
c = p->v_right;
else {
for (c = p->v_left; c->v_right; c = c->v_right)
continue;
p->v_name = c->v_name;
p->vec = c->vec;
p = c;
c = p->v_left;
}
/*
* Move c into where p is.
*/
pp = p->v_parent;
f = pp->v_right == p;
if ((pp->v_link[f] = c) != NULL)
c->v_parent = pp;
/*
* Free the deleted node, and rebalance.
*/
xfree((ptr_t) p);
balance(pp, f, 1);
}
void
setNS(Char *cp)
{
set(cp, Strsave(STRNULL));
}
void
/*ARGSUSED*/
shift(Char **v, struct command *t)
{
struct varent *argv;
Char *name;
v++;
name = *v;
if (name == 0)
name = STRargv;
else
(void) strip(name);
argv = adrof(name);
if (argv == 0)
udvar(name);
if (argv->vec[0] == 0)
stderror(ERR_NAME | ERR_NOMORE);
lshift(argv->vec, 1);
update_vars(name);
}
static void
exportpath(Char **val)
{
Char exppath[BUFSIZE];
exppath[0] = 0;
if (val)
while (*val) {
if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZE) {
(void)fprintf(csherr,
"Warning: ridiculously long PATH truncated\n");
break;
}
(void)Strcat(exppath, *val++);
if (*val == 0 || eq(*val, STRRparen))
break;
(void)Strcat(exppath, STRcolon);
}
Setenv(STRPATH, exppath);
}
#ifndef lint
/*
* Lint thinks these have null effect
*/
/* macros to do single rotations on node p */
#define rright(p) (\
t = (p)->v_left,\
(t)->v_parent = (p)->v_parent,\
((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
(t->v_right = (p))->v_parent = t,\
(p) = t)
#define rleft(p) (\
t = (p)->v_right,\
(t)->v_parent = (p)->v_parent,\
((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
(t->v_left = (p))->v_parent = t,\
(p) = t)
#else
struct varent *
rleft(struct varent *p)
{
return (p);
}
struct varent *
rright(struct varent *p)
{
return (p);
}
#endif /* ! lint */
/*
* Rebalance a tree, starting at p and up.
* F == 0 means we've come from p's left child.
* D == 1 means we've just done a delete, otherwise an insert.
*/
static void
balance(struct varent *p, int f, int d)
{
struct varent *pp;
#ifndef lint
struct varent *t; /* used by the rotate macros */
#endif
int ff;
/*
* Ok, from here on, p is the node we're operating on; pp is its parent; f
* is the branch of p from which we have come; ff is the branch of pp which
* is p.
*/
for (; (pp = p->v_parent) != NULL; p = pp, f = ff) {
ff = pp->v_right == p;
if (f ^ d) { /* right heavy */
switch (p->v_bal) {
case -1: /* was left heavy */
p->v_bal = 0;
break;
case 0: /* was balanced */
p->v_bal = 1;
break;
case 1: /* was already right heavy */
switch (p->v_right->v_bal) {
case 1: /* single rotate */
pp->v_link[ff] = rleft(p);
p->v_left->v_bal = 0;
p->v_bal = 0;
break;
case 0: /* single rotate */
pp->v_link[ff] = rleft(p);
p->v_left->v_bal = 1;
p->v_bal = -1;
break;
case -1: /* double rotate */
(void) rright(p->v_right);
pp->v_link[ff] = rleft(p);
p->v_left->v_bal =
p->v_bal < 1 ? 0 : -1;
p->v_right->v_bal =
p->v_bal > -1 ? 0 : 1;
p->v_bal = 0;
break;
}
break;
}
}
else { /* left heavy */
switch (p->v_bal) {
case 1: /* was right heavy */
p->v_bal = 0;
break;
case 0: /* was balanced */
p->v_bal = -1;
break;
case -1: /* was already left heavy */
switch (p->v_left->v_bal) {
case -1: /* single rotate */
pp->v_link[ff] = rright(p);
p->v_right->v_bal = 0;
p->v_bal = 0;
break;
case 0: /* single rotate */
pp->v_link[ff] = rright(p);
p->v_right->v_bal = -1;
p->v_bal = 1;
break;
case 1: /* double rotate */
(void) rleft(p->v_left);
pp->v_link[ff] = rright(p);
p->v_left->v_bal =
p->v_bal < 1 ? 0 : -1;
p->v_right->v_bal =
p->v_bal > -1 ? 0 : 1;
p->v_bal = 0;
break;
}
break;
}
}
/*
* If from insert, then we terminate when p is balanced. If from
* delete, then we terminate when p is unbalanced.
*/
if ((p->v_bal == 0) ^ d)
break;
}
}
void
plist(struct varent *p)
{
struct varent *c;
sigset_t nsigset;
int len;
if (setintr) {
sigemptyset(&nsigset);
(void)sigaddset(&nsigset, SIGINT);
(void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL);
}
for (;;) {
while (p->v_left)
p = p->v_left;
x:
if (p->v_parent == 0) /* is it the header? */
return;
len = blklen(p->vec);
(void)fprintf(cshout, "%s\t", short2str(p->v_name));
if (len != 1)
(void)fputc('(', cshout);
blkpr(cshout, p->vec);
if (len != 1)
(void)fputc(')', cshout);
(void)fputc('\n', cshout);
if (p->v_right) {
p = p->v_right;
continue;
}
do {
c = p;
p = p->v_parent;
} while (p->v_right == c);
goto x;
}
}

View File

@@ -1,441 +0,0 @@
/* $NetBSD: str.c,v 1.15 2013/07/16 17:47:43 christos Exp $ */
/*-
* Copyright (c) 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: str.c,v 1.15 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#define MALLOC_INCR 128
/*
* tc.str.c: Short string package
* This has been a lesson of how to write buggy code!
*/
#include <sys/types.h>
#include <stdarg.h>
#include <vis.h>
#include "csh.h"
#include "extern.h"
#ifdef SHORT_STRINGS
Char **
blk2short(char **src)
{
Char **dst, **sdst;
size_t n;
/*
* Count
*/
for (n = 0; src[n] != NULL; n++)
continue;
sdst = dst = xmalloc((size_t)((n + 1) * sizeof(*dst)));
for (; *src != NULL; src++)
*dst++ = SAVE(*src);
*dst = NULL;
return (sdst);
}
char **
short2blk(Char *const *src)
{
char **dst, **sdst;
size_t n;
/*
* Count
*/
for (n = 0; src[n] != NULL; n++)
continue;
sdst = dst = xmalloc((size_t)((n + 1) * sizeof(*dst)));
for (; *src != NULL; src++)
*dst++ = strsave(short2str(*src));
*dst = NULL;
return (sdst);
}
Char *
str2short(const char *src)
{
static Char *sdst;
Char *dst, *edst;
static size_t dstsize = 0;
if (src == NULL)
return (NULL);
if (sdst == (NULL)) {
dstsize = MALLOC_INCR;
sdst = xmalloc((size_t)dstsize * sizeof(*sdst));
}
dst = sdst;
edst = &dst[dstsize];
while (*src) {
*dst++ = (Char) ((unsigned char) *src++);
if (dst == edst) {
dstsize += MALLOC_INCR;
sdst = xrealloc((ptr_t)sdst,
(size_t)dstsize * sizeof(*sdst));
edst = &sdst[dstsize];
dst = &edst[-MALLOC_INCR];
}
}
*dst = 0;
return (sdst);
}
char *
short2str(const Char *src)
{
static char *sdst = NULL;
static size_t dstsize = 0;
char *dst, *edst;
if (src == NULL)
return (NULL);
if (sdst == NULL) {
dstsize = MALLOC_INCR;
sdst = xmalloc((size_t)dstsize * sizeof(*sdst));
}
dst = sdst;
edst = &dst[dstsize];
while (*src) {
*dst++ = (char) *src++;
if (dst == edst) {
dstsize += MALLOC_INCR;
sdst = xrealloc((ptr_t)sdst,
(size_t)dstsize * sizeof(*sdst));
edst = &sdst[dstsize];
dst = &edst[-MALLOC_INCR];
}
}
*dst = 0;
return (sdst);
}
Char *
s_strcpy(Char *dst, const Char *src)
{
Char *sdst;
sdst = dst;
while ((*dst++ = *src++) != '\0')
continue;
return (sdst);
}
Char *
s_strncpy(Char *dst, const Char *src, size_t n)
{
Char *sdst;
if (n == 0)
return(dst);
sdst = dst;
do
if ((*dst++ = *src++) == '\0') {
while (--n != 0)
*dst++ = '\0';
return(sdst);
}
while (--n != 0);
return (sdst);
}
Char *
s_strcat(Char *dst, const Char *src)
{
short *sdst;
sdst = dst;
while (*dst++)
continue;
--dst;
while ((*dst++ = *src++) != '\0')
continue;
return (sdst);
}
#ifdef NOTUSED
Char *
s_strncat(Char *dst, Char *src, size_t n)
{
Char *sdst;
if (n == 0)
return (dst);
sdst = dst;
while (*dst++)
continue;
--dst;
do
if ((*dst++ = *src++) == '\0')
return(sdst);
while (--n != 0)
continue;
*dst = '\0';
return (sdst);
}
#endif
Char *
s_strchr(const Char *str, int ch)
{
do
if (*str == ch)
return __UNCONST(str);
while (*str++);
return (NULL);
}
Char *
s_strrchr(const Char *str, int ch)
{
const Char *rstr;
rstr = NULL;
do
if (*str == ch)
rstr = str;
while (*str++);
return __UNCONST(rstr);
}
size_t
s_strlen(const Char *str)
{
size_t n;
for (n = 0; *str++; n++)
continue;
return (n);
}
int
s_strcmp(const Char *str1, const Char *str2)
{
for (; *str1 && *str1 == *str2; str1++, str2++)
continue;
/*
* The following case analysis is necessary so that characters which look
* negative collate low against normal characters but high against the
* end-of-string NUL.
*/
if (*str1 == '\0' && *str2 == '\0')
return (0);
else if (*str1 == '\0')
return (-1);
else if (*str2 == '\0')
return (1);
else
return (*str1 - *str2);
}
int
s_strncmp(const Char *str1, const Char *str2, size_t n)
{
if (n == 0)
return (0);
do {
if (*str1 != *str2) {
/*
* The following case analysis is necessary so that characters
* which look negative collate low against normal characters
* but high against the end-of-string NUL.
*/
if (*str1 == '\0')
return (-1);
else if (*str2 == '\0')
return (1);
else
return (*str1 - *str2);
}
if (*str1 == '\0')
return(0);
str1++, str2++;
} while (--n != 0);
return(0);
}
Char *
s_strsave(const Char *s)
{
const Char *p;
Char *n;
if (s == 0)
s = STRNULL;
for (p = s; *p++;)
continue;
p = n = xmalloc((size_t)(p - s) * sizeof(*n));
while ((*n++ = *s++) != '\0')
continue;
return __UNCONST(p);
}
Char *
s_strspl(const Char *cp, const Char *dp)
{
Char *ep, *d;
const Char *p, *q;
if (!cp)
cp = STRNULL;
if (!dp)
dp = STRNULL;
for (p = cp; *p++;)
continue;
for (q = dp; *q++;)
continue;
ep = xmalloc((size_t)((p - cp) + (q - dp) - 1) * sizeof(*ep));
for (d = ep, q = cp; (*d++ = *q++) != '\0';)
continue;
for (d--, q = dp; (*d++ = *q++) != '\0';)
continue;
return (ep);
}
Char *
s_strend(const Char *cp)
{
if (!cp)
return __UNCONST(cp);
while (*cp)
cp++;
return __UNCONST(cp);
}
Char *
s_strstr(const Char *s, const Char *t)
{
do {
const Char *ss = s;
const Char *tt = t;
do
if (*tt == '\0')
return __UNCONST(s);
while (*ss++ == *tt++);
} while (*s++ != '\0');
return (NULL);
}
#endif /* SHORT_STRINGS */
char *
short2qstr(const Char *src)
{
static char *sdst = NULL;
static size_t dstsize = 0;
char *dst, *edst;
if (src == NULL)
return (NULL);
if (sdst == NULL) {
dstsize = MALLOC_INCR;
sdst = xmalloc((size_t)dstsize * sizeof(*sdst));
}
dst = sdst;
edst = &dst[dstsize];
while (*src) {
if (*src & QUOTE) {
*dst++ = '\\';
if (dst == edst) {
dstsize += MALLOC_INCR;
sdst = xrealloc((ptr_t) sdst,
(size_t)dstsize * sizeof(*sdst));
edst = &sdst[dstsize];
dst = &edst[-MALLOC_INCR];
}
}
*dst++ = (char) *src++;
if (dst == edst) {
dstsize += MALLOC_INCR;
sdst = xrealloc((ptr_t) sdst,
(size_t)dstsize * sizeof(*sdst));
edst = &sdst[dstsize];
dst = &edst[-MALLOC_INCR];
}
}
*dst = 0;
return (sdst);
}
/*
* XXX: Should we worry about QUOTE'd chars?
*/
char *
vis_str(const Char *cp)
{
static char *sdst = NULL;
static size_t dstsize = 0;
const Char *dp;
size_t n;
if (cp == NULL)
return (NULL);
for (dp = cp; *dp++;)
continue;
n = ((size_t)(dp - cp) << 2) + 1; /* 4 times + NULL */
if (dstsize < n) {
sdst = (dstsize ?
xrealloc(sdst, (size_t)n * sizeof(*sdst)) :
xmalloc((size_t)n * sizeof(*sdst)));
dstsize = n;
}
/*
* XXX: When we are in AsciiOnly we want all characters >= 0200 to
* be encoded, but currently there is no way in vis to do that.
*/
(void)strvis(sdst, short2str(cp), VIS_NOSLASH);
return (sdst);
}

View File

@@ -1,285 +0,0 @@
/* $NetBSD: time.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */
/*-
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: time.c,v 1.20 2013/07/16 17:47:43 christos Exp $");
#endif
#endif /* not lint */
#ifndef NOT_CSH
#include <sys/types.h>
#include <stdarg.h>
#include "csh.h"
#include "extern.h"
#endif
#include <util.h>
/*
* C Shell - routines handling process timing and niceing
*/
static void pdeltat(FILE *, struct timeval *, struct timeval *);
static void pcsecs(FILE *, long);
#ifndef NOT_CSH
void
settimes(void)
{
struct rusage ruch;
(void)clock_gettime(CLOCK_MONOTONIC, &time0);
(void)getrusage(RUSAGE_SELF, &ru0);
(void)getrusage(RUSAGE_CHILDREN, &ruch);
ruadd(&ru0, &ruch);
}
/*
* dotime is only called if it is truly a builtin function and not a
* prefix to another command
*/
void
/*ARGSUSED*/
dotime(Char **v, struct command *t)
{
struct rusage ru1, ruch;
struct timespec timedol;
(void)getrusage(RUSAGE_SELF, &ru1);
(void)getrusage(RUSAGE_CHILDREN, &ruch);
ruadd(&ru1, &ruch);
(void)clock_gettime(CLOCK_MONOTONIC, &timedol);
prusage(cshout, &ru0, &ru1, &timedol, &time0);
}
/*
* donice is only called when it on the line by itself or with a +- value
*/
void
/*ARGSUSED*/
donice(Char **v, struct command *t)
{
Char *cp;
int nval;
nval = 0;
v++;
cp = *v++;
if (cp == 0)
nval = 4;
else if (*v == 0 && any("+-", cp[0]))
nval = getn(cp);
(void)setpriority(PRIO_PROCESS, 0, nval);
}
void
ruadd(struct rusage *ru, struct rusage *ru2)
{
timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
if (ru2->ru_maxrss > ru->ru_maxrss)
ru->ru_maxrss = ru2->ru_maxrss;
ru->ru_ixrss += ru2->ru_ixrss;
ru->ru_idrss += ru2->ru_idrss;
ru->ru_isrss += ru2->ru_isrss;
ru->ru_minflt += ru2->ru_minflt;
ru->ru_majflt += ru2->ru_majflt;
ru->ru_nswap += ru2->ru_nswap;
ru->ru_inblock += ru2->ru_inblock;
ru->ru_oublock += ru2->ru_oublock;
ru->ru_msgsnd += ru2->ru_msgsnd;
ru->ru_msgrcv += ru2->ru_msgrcv;
ru->ru_nsignals += ru2->ru_nsignals;
ru->ru_nvcsw += ru2->ru_nvcsw;
ru->ru_nivcsw += ru2->ru_nivcsw;
}
#endif /* NOT_CSH */
void
prusage(FILE *fp, struct rusage *r0, struct rusage *r1, struct timespec *e,
struct timespec *b)
{
#ifndef NOT_CSH
struct varent *vp;
#endif
const char *cp;
long i;
time_t t;
time_t ms;
cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
ms = (e->tv_sec - b->tv_sec) * 100 + (e->tv_nsec - b->tv_nsec) / 10000000;
t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
(r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
(r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
(r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
#ifndef NOT_CSH
vp = adrof(STRtime);
if (vp && vp->vec[0] && vp->vec[1])
cp = short2str(vp->vec[1]);
#endif
for (; *cp; cp++)
if (*cp != '%')
(void) fputc(*cp, fp);
else if (cp[1])
switch (*++cp) {
case 'D': /* (average) unshared data size */
(void)fprintf(fp, "%ld", t == 0 ? 0L :
(long)((r1->ru_idrss + r1->ru_isrss -
(r0->ru_idrss + r0->ru_isrss)) / t));
break;
case 'E': /* elapsed (wall-clock) time */
pcsecs(fp, (long) ms);
break;
case 'F': /* page faults */
(void)fprintf(fp, "%ld", r1->ru_majflt - r0->ru_majflt);
break;
case 'I': /* FS blocks in */
(void)fprintf(fp, "%ld", r1->ru_inblock - r0->ru_inblock);
break;
case 'K': /* (average) total data memory used */
(void)fprintf(fp, "%ld", t == 0 ? 0L :
(long)(((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
(r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t));
break;
case 'M': /* max. Resident Set Size */
(void)fprintf(fp, "%ld", r1->ru_maxrss / 2L);
break;
case 'O': /* FS blocks out */
(void)fprintf(fp, "%ld", r1->ru_oublock - r0->ru_oublock);
break;
case 'P': /* percent time spent running */
/* check if it did not run at all */
if (ms == 0) {
(void)fputs("0.0%", fp);
} else {
char pb[32];
(void)fputs(strpct(pb, sizeof(pb),
(uintmax_t)t, (uintmax_t)ms, 1), fp);
(void)fputc('%', fp);
}
break;
case 'R': /* page reclaims */
(void)fprintf(fp, "%ld", r1->ru_minflt - r0->ru_minflt);
break;
case 'S': /* system CPU time used */
pdeltat(fp, &r1->ru_stime, &r0->ru_stime);
break;
case 'U': /* user CPU time used */
pdeltat(fp, &r1->ru_utime, &r0->ru_utime);
break;
case 'W': /* number of swaps */
i = r1->ru_nswap - r0->ru_nswap;
(void)fprintf(fp, "%ld", i);
break;
case 'X': /* (average) shared text size */
(void)fprintf(fp, "%ld", t == 0 ? 0L :
(long)((r1->ru_ixrss - r0->ru_ixrss) / t));
break;
case 'c': /* num. involuntary context switches */
(void)fprintf(fp, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
break;
case 'k': /* number of signals received */
(void)fprintf(fp, "%ld", r1->ru_nsignals-r0->ru_nsignals);
break;
case 'r': /* socket messages received */
(void)fprintf(fp, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
break;
case 's': /* socket messages sent */
(void)fprintf(fp, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
break;
case 'w': /* num. voluntary context switches (waits) */
(void)fprintf(fp, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
break;
}
(void)fputc('\n', fp);
}
static void
pdeltat(FILE *fp, struct timeval *t1, struct timeval *t0)
{
struct timeval td;
timersub(t1, t0, &td);
(void)fprintf(fp, "%ld.%01ld", (long)td.tv_sec,
(long)(td.tv_usec / 100000));
}
#define P2DIG(fp, i) (void)fprintf(fp, "%ld%ld", (i) / 10, (i) % 10)
#ifndef NOT_CSH
void
psecs(long l)
{
long i;
i = l / 3600;
if (i) {
(void)fprintf(cshout, "%ld:", i);
i = l % 3600;
P2DIG(cshout, i / 60);
goto minsec;
}
i = l;
(void)fprintf(cshout, "%ld", i / 60);
minsec:
i %= 60;
(void)fputc(':', cshout);
P2DIG(cshout, i);
}
#endif
static void
pcsecs(FILE *fp, long l) /* PWP: print mm:ss.dd, l is in sec*100 */
{
long i;
i = l / 360000;
if (i) {
(void)fprintf(fp, "%ld:", i);
i = (l % 360000) / 100;
P2DIG(fp, i / 60);
goto minsec;
}
i = l / 100;
(void)fprintf(fp, "%ld", i / 60);
minsec:
i %= 60;
(void)fputc(':', fp);
P2DIG(fp, i);
(void)fputc('.', fp);
P2DIG(fp, (l % 100));
}

View File

@@ -1,12 +0,0 @@
# $NetBSD: Makefile,v 1.15 2011/08/14 10:53:16 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= date
SRCS= date.c netdate.c
DPADD+= ${LIBUTIL}
LDADD+= -lutil
CPPFLAGS+=-I${.CURDIR}
COPTS.date.c = -Wno-format-nonliteral
.include <bsd.prog.mk>

View File

@@ -1,246 +0,0 @@
.\" $NetBSD: date.1,v 1.42 2012/04/06 11:36:56 wiz Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" 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. 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.
.\"
.\" @(#)date.1 8.3 (Berkeley) 4/28/95
.\"
.Dd November 15, 2006
.Dt DATE 1
.Os
.Sh NAME
.Nm date
.Nd display or set date and time
.Sh SYNOPSIS
.Nm
.Op Fl ajnu
.Op Fl d Ar date
.Op Fl r Ar seconds
.Op Cm + Ns Ar format
.Sm off
.Oo Oo Oo Oo Oo Oo
.Ar CC Oc
.Ar yy Oc
.Ar mm Oc
.Ar dd Oc
.Ar HH Oc Ar MM Oo
.Li \&. Ar SS Oc Oc
.Sm on
.Sh DESCRIPTION
.Nm
displays the current date and time when invoked without arguments.
Providing arguments will format the date and time in a user-defined
way or set the date.
Only the superuser may set the date.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a
Use
.Xr adjtime 2
to change the local system time slowly,
maintaining it as a monotonically increasing function.
.Fl a
implies
.Fl n .
.It Fl d Ar date
Parse the provided human-described date and time and display the result without
actually changing the system clock.
(See
.Xr parsedate 3
for examples.)
.It Fl j
Parse the provided canonical representation of date and time (described below)
and display the result without actually changing the system clock.
.It Fl n
The utility
.Xr timed 8
is used to synchronize the clocks on groups of machines.
By default, if
.Xr timed 8
is running,
.Nm
will set the time on all of the machines in the local group.
The
.Fl n
option stops
.Nm
from setting the time for other than the current machine.
.It Fl r Ar seconds
Print out the date and time that is
.Ar seconds
from the Epoch.
.It Fl u
Display or set the date in
.Tn UTC
(universal) time.
.El
.Pp
An operand with a leading plus
.Pq Cm +
sign signals a user-defined format
string which specifies the format in which to display the date and time.
The format string may contain any of the conversion specifications described
in the
.Xr strftime 3
manual page, as well as any arbitrary text.
A \*[Lt]newline\*[Gt] character is always output after the characters
specified by the format string.
The format string for the default display is:
.Bd -literal -offset indent
%a %b %e %H:%M:%S %Z %Y
.Ed
.Pp
If an operand does not have a leading plus sign, it is interpreted as
a value for setting the system's notion of the current date and time.
The canonical representation for setting the date and time is:
.Pp
.Bl -tag -width Ds -compact -offset indent
.It Ar CC
The first two digits of the year (the century).
.It Ar yy
The second two digits of the year.
If
.Ar yy
is specified, but
.Ar CC
is not, a value for
.Ar yy
between 69 and 99 results in a
.Ar CC
value of 19.
Otherwise, a
.Ar CC
value of 20 is used.
.It Ar mm
The month of the year, from 01 to 12.
.It Ar dd
The day of the month, from 01 to 31.
.It Ar HH
The hour of the day, from 00 to 23.
.It Ar MM
The minute of the hour, from 00 to 59.
.It Ar SS
The second of the minute, from 00 to 61.
.El
.Pp
Everything but the minutes is optional.
.Pp
Time changes for Daylight Saving and Standard Time and leap seconds
and years are handled automatically.
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
.Bl -tag -width iTZ
.It Ev TZ
The timezone to use when displaying dates.
See
.Xr environ 7
for more information.
.El
.Sh FILES
.Bl -tag -width /var/log/messages -compact
.It Pa /etc/localtime
Symlink pointing to system's default timezone information file in
.Pa /usr/share/zoneinfo
directory.
.It Pa /var/log/wtmp
A record of date resets and time changes.
.It Pa /var/log/messages
A record of the user setting the time.
.El
.Sh EXAMPLES
The command:
.Bd -literal -offset indent
date '+DATE: %m/%d/%y%nTIME: %H:%M:%S'
.Ed
.Pp
will display:
.Bd -literal -offset indent
DATE: 11/21/87
TIME: 13:36:16
.Ed
.Pp
The command:
.Bd -literal -offset indent
date 8506131627
.Ed
.Pp
sets the date to
.Dq Li "June 13, 1985, 4:27 PM" .
.Pp
The command:
.Bd -literal -offset indent
date 1432
.Ed
.Pp
sets the time to
.Li "2:32 PM" ,
without modifying the date.
.Sh DIAGNOSTICS
Exit status is 0 on success, 1 if unable to set the date, and 2
if able to set the local date, but unable to set it globally.
.Pp
Occasionally, when
.Xr timed 8
synchronizes the time on many hosts, the setting of a new time value may
require more than a few seconds.
On these occasions,
.Nm
prints:
.Ql Network time being set .
The message
.Ql Communication error with
.Xr timed 8
occurs when the communication
between
.Nm
and
.Xr timed 8
fails.
.Sh SEE ALSO
.Xr adjtime 2 ,
.Xr gettimeofday 2 ,
.Xr settimeofday 2 ,
.Xr parsedate 3 ,
.Xr strftime 3 ,
.Xr utmp 5 ,
.Xr environ 7 ,
.Xr timed 8
.Rs
.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
.%A R. Gusella
.%A S. Zatti
.Re
.Sh STANDARDS
The
.Nm
utility is expected to be compatible with
.St -p1003.2 .

View File

@@ -1,343 +0,0 @@
/* $NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $ */
/*
* Copyright (c) 1985, 1987, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1985, 1987, 1988, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <util.h>
#include "extern.h"
static time_t tval;
static int aflag, jflag, rflag, nflag;
__dead static void badformat(void);
__dead static void badtime(void);
__dead static void badvalue(const char *);
static void setthetime(const char *);
__dead static void usage(void);
int
main(int argc, char *argv[])
{
char *buf;
size_t bufsiz;
const char *format;
int ch;
long long val;
struct tm *tm;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "ad:jnr:u")) != -1) {
switch (ch) {
case 'a': /* adjust time slowly */
aflag = 1;
nflag = 1;
break;
case 'd':
#if !defined(__minix)
rflag = 1;
tval = parsedate(optarg, NULL, NULL);
if (tval == -1)
#endif /* !defined(__minix) */
badarg: errx(EXIT_FAILURE,
"Cannot parse `%s'", optarg);
break;
case 'j': /* don't set time */
jflag = 1;
break;
case 'n': /* don't set network */
nflag = 1;
break;
case 'r': /* user specified seconds */
errno = 0;
val = strtoll(optarg, &buf, 0);
if (optarg[0] == '\0' || *buf != '\0')
goto badarg;
if (errno == ERANGE && (val == LLONG_MAX ||
val == LLONG_MIN))
err(EXIT_FAILURE, "Bad number `%s'", optarg);
rflag = 1;
tval = (time_t)val;
break;
case 'u': /* do everything in UTC */
(void)setenv("TZ", "UTC0", 1);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (!rflag && time(&tval) == -1)
err(EXIT_FAILURE, "time");
/* allow the operands in any order */
if (*argv && **argv == '+') {
format = *argv;
++argv;
} else
format = "+%a %b %e %H:%M:%S %Z %Y";
if (*argv) {
setthetime(*argv);
++argv;
}
if (*argv && **argv == '+')
format = *argv;
if ((buf = malloc(bufsiz = 1024)) == NULL)
goto bad;
if ((tm = localtime(&tval)) == NULL)
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
while (strftime(buf, bufsiz, format, tm) == 0)
if ((buf = realloc(buf, bufsiz <<= 1)) == NULL)
goto bad;
(void)printf("%s\n", buf + 1);
free(buf);
return 0;
bad:
err(EXIT_FAILURE, "Cannot allocate format buffer");
}
static void
badformat(void)
{
warnx("illegal time format");
usage();
}
static void
badtime(void)
{
errx(EXIT_FAILURE, "illegal time");
/* NOTREACHED */
}
static void
badvalue(const char *param)
{
warnx("invalid %s supplied", param);
usage();
}
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
static void
setthetime(const char *p)
{
struct timeval tv;
time_t new_time;
struct tm *lt;
const char *dot, *t;
size_t len;
int yearset;
for (t = p, dot = NULL; *t; ++t) {
if (isdigit((unsigned char)*t))
continue;
if (*t == '.' && dot == NULL) {
dot = t;
continue;
}
badformat();
}
if ((lt = localtime(&tval)) == NULL)
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
lt->tm_isdst = -1; /* Divine correct DST */
if (dot != NULL) { /* .ss */
len = strlen(dot);
if (len != 3)
badformat();
++dot;
lt->tm_sec = ATOI2(dot);
if (lt->tm_sec > 61)
badvalue("seconds");
} else {
len = 0;
lt->tm_sec = 0;
}
yearset = 0;
switch (strlen(p) - len) {
case 12: /* cc */
lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
if (lt->tm_year < 0)
badtime();
yearset = 1;
/* FALLTHROUGH */
case 10: /* yy */
if (yearset) {
lt->tm_year += ATOI2(p);
} else {
yearset = ATOI2(p);
if (yearset < 69)
lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
else
lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
}
/* FALLTHROUGH */
case 8: /* mm */
lt->tm_mon = ATOI2(p);
if (lt->tm_mon > 12 || lt->tm_mon == 0)
badvalue("month");
--lt->tm_mon; /* time struct is 0 - 11 */
/* FALLTHROUGH */
case 6: /* dd */
lt->tm_mday = ATOI2(p);
switch (lt->tm_mon) {
case 0:
case 2:
case 4:
case 6:
case 7:
case 9:
case 11:
if (lt->tm_mday > 31 || lt->tm_mday == 0)
badvalue("day of month");
break;
case 3:
case 5:
case 8:
case 10:
if (lt->tm_mday > 30 || lt->tm_mday == 0)
badvalue("day of month");
break;
case 1:
if (lt->tm_mday > 29 || lt->tm_mday == 0 ||
(lt->tm_mday == 29 &&
!isleap(lt->tm_year + TM_YEAR_BASE)))
badvalue("day of month");
break;
default:
badvalue("month");
break;
}
/* FALLTHROUGH */
case 4: /* hh */
lt->tm_hour = ATOI2(p);
if (lt->tm_hour > 23)
badvalue("hour");
/* FALLTHROUGH */
case 2: /* mm */
lt->tm_min = ATOI2(p);
if (lt->tm_min > 59)
badvalue("minute");
break;
case 0: /* was just .sss */
if (len != 0)
break;
/* FALLTHROUGH */
default:
badformat();
}
/* convert broken-down time to UTC clock time */
if ((new_time = mktime(lt)) == -1)
badtime();
/* if jflag is set, don't actually change the time, just return */
if (jflag) {
tval = new_time;
return;
}
/* set the time */
if (nflag || netsettime(new_time)) {
logwtmp("|", "date", "");
if (aflag) {
tv.tv_sec = new_time - tval;
tv.tv_usec = 0;
if (adjtime(&tv, NULL))
err(EXIT_FAILURE, "adjtime");
} else {
tval = new_time;
tv.tv_sec = tval;
tv.tv_usec = 0;
if (settimeofday(&tv, NULL))
err(EXIT_FAILURE, "settimeofday");
}
logwtmp("{", "date", "");
}
if ((p = getlogin()) == NULL)
p = "???";
syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
}
static void
usage(void)
{
(void)fprintf(stderr,
"Usage: %s [-ajnu] [-d date] [-r seconds] [+format]",
getprogname());
(void)fprintf(stderr, " [[[[[[CC]yy]mm]dd]HH]MM[.SS]]\n");
exit(EXIT_FAILURE);
/* NOTREACHED */
}

View File

@@ -1,39 +0,0 @@
/* $NetBSD: extern.h,v 1.8 2006/11/17 22:11:28 christos Exp $ */
/*-
* Copyright (c) 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. 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.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
#ifndef _EXTERN_H_
#define _EXTERN_H_
int netsettime(time_t);
#endif /* !_EXTERN_H_ */

View File

@@ -1,200 +0,0 @@
/* $NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $ */
/*-
* Copyright (c) 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)netdate.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define TSPTYPES
#include <protocols/timed.h>
#include <err.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define WAITACK 2000 /* milliseconds */
#define WAITDATEACK 5000 /* milliseconds */
static const char *
tsp_type_to_string(const struct tsp *msg)
{
unsigned i;
i = msg->tsp_type;
return i < TSPTYPENUMBER ? tsptype[i] : "unknown";
}
/*
* Set the date in the machines controlled by timedaemons by communicating the
* new date to the local timedaemon. If the timedaemon is in the master state,
* it performs the correction on all slaves. If it is in the slave state, it
* notifies the master that a correction is needed.
* Returns 0 on success. Returns > 0 on failure.
*/
int
netsettime(time_t tval)
{
struct sockaddr_in dest;
struct tsp msg;
char hostname[MAXHOSTNAMELEN];
struct servent *sp;
struct pollfd ready;
int found, s, timed_ack, waittime;
if ((sp = getservbyname("timed", "udp")) == NULL) {
warnx("udp/timed: unknown service");
return 2;
}
(void)memset(&dest, 0, sizeof(dest));
#ifdef BSD4_4
dest.sin_len = sizeof(dest);
#endif
dest.sin_family = AF_INET;
dest.sin_port = sp->s_port;
dest.sin_addr.s_addr = htonl(INADDR_ANY);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
if (errno != EAFNOSUPPORT)
warn("timed");
return 2;
}
#ifdef IP_PORTRANGE
{
static const int on = IP_PORTRANGE_LOW;
if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &on,
sizeof(on)) == -1) {
warn("setsockopt");
goto bad;
}
}
#endif
msg.tsp_type = TSP_SETDATE;
msg.tsp_vers = TSPVERSION;
if (gethostname(hostname, sizeof(hostname)) == -1) {
warn("gethostname");
goto bad;
}
(void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
msg.tsp_seq = htons((in_port_t)0);
msg.tsp_time.tv_sec = htonl((in_addr_t)tval); /* XXX: y2038 */
msg.tsp_time.tv_usec = htonl((in_addr_t)0);
if (connect(s, (const void *)&dest, sizeof(dest)) == -1) {
warn("connect");
goto bad;
}
if (send(s, &msg, sizeof(msg), 0) == -1) {
if (errno != ECONNREFUSED)
warn("send");
goto bad;
}
timed_ack = -1;
waittime = WAITACK;
ready.fd = s;
ready.events = POLLIN;
loop:
found = poll(&ready, 1, waittime);
{
socklen_t len;
int error;
len = sizeof(error);
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
warn("getsockopt");
goto bad;
}
if (error) {
if (error != ECONNREFUSED) {
errno = error;
warn("send (delayed error)");
}
goto bad;
}
}
if (found > 0 && ready.revents & POLLIN) {
ssize_t ret;
if ((ret = recv(s, &msg, sizeof(msg), 0)) == -1) {
if (errno != ECONNREFUSED)
warn("recv");
goto bad;
} else if ((size_t)ret < sizeof(msg)) {
warnx("recv: incomplete packet");
goto bad;
}
msg.tsp_seq = ntohs(msg.tsp_seq);
msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
switch (msg.tsp_type) {
case TSP_ACK:
timed_ack = TSP_ACK;
waittime = WAITDATEACK;
goto loop;
case TSP_DATEACK:
(void)close(s);
return 0;
default:
warnx("wrong ack received from timed: %s",
tsp_type_to_string(&msg));
timed_ack = -1;
break;
}
}
if (timed_ack == -1)
warnx("can't reach time daemon, time set locally");
bad:
(void)close(s);
return 2;
}

View File

@@ -1,21 +0,0 @@
# $NetBSD: Makefile,v 1.17 2012/08/08 14:09:14 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
.include <bsd.own.mk>
RUMPPRG=dd
SRCS= args.c conv.c dd.c misc.c position.c
DPADD+= ${LIBUTIL}
LDADD+= -lutil
.ifdef SMALLPROG
CPPFLAGS+= -DNO_CONV -DNO_MSGFMT -DSMALL
.else
SRCS+= conv_tab.c
.ifdef CRUNCHEDPROG
CPPFLAGS+= -DSMALL
.endif
.endif
.include <bsd.prog.mk>

View File

@@ -1,391 +0,0 @@
/* $NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/time.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dd.h"
#include "extern.h"
static int c_arg(const void *, const void *);
#ifdef NO_MSGFMT
static void f_msgfmt(char *) __dead;
#else
static void f_msgfmt(char *);
#endif /* NO_MSGFMT */
#ifdef NO_CONV
static void f_conv(char *) __dead;
#else
static void f_conv(char *);
static int c_conv(const void *, const void *);
#endif /* NO_CONV */
static void f_bs(char *);
static void f_cbs(char *);
static void f_count(char *);
static void f_files(char *);
static void f_ibs(char *);
static void f_if(char *);
static void f_obs(char *);
static void f_of(char *);
static void f_seek(char *);
static void f_skip(char *);
static void f_progress(char *);
static const struct arg {
const char *name;
void (*f)(char *);
u_int set, noset;
} args[] = {
/* the array needs to be sorted by the first column so
bsearch() can be used to find commands quickly */
{ "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
{ "cbs", f_cbs, C_CBS, C_CBS },
{ "conv", f_conv, 0, 0 },
{ "count", f_count, C_COUNT, C_COUNT },
{ "files", f_files, C_FILES, C_FILES },
{ "ibs", f_ibs, C_IBS, C_BS|C_IBS },
{ "if", f_if, C_IF, C_IF },
{ "iseek", f_skip, C_SKIP, C_SKIP },
{ "msgfmt", f_msgfmt, 0, 0 },
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
{ "of", f_of, C_OF, C_OF },
{ "oseek", f_seek, C_SEEK, C_SEEK },
{ "progress", f_progress, 0, 0 },
{ "seek", f_seek, C_SEEK, C_SEEK },
{ "skip", f_skip, C_SKIP, C_SKIP },
};
/*
* args -- parse JCL syntax of dd.
*/
void
jcl(char **argv)
{
struct arg *ap, tmp;
char *oper, *arg;
in.dbsz = out.dbsz = 512;
while ((oper = *++argv) != NULL) {
if ((oper = strdup(oper)) == NULL) {
errx(EXIT_FAILURE,
"unable to allocate space for the argument %s",
*argv);
/* NOTREACHED */
}
if ((arg = strchr(oper, '=')) == NULL) {
errx(EXIT_FAILURE, "unknown operand %s", oper);
/* NOTREACHED */
}
*arg++ = '\0';
if (!*arg) {
errx(EXIT_FAILURE, "no value specified for %s", oper);
/* NOTREACHED */
}
tmp.name = oper;
if (!(ap = bsearch(&tmp, args,
__arraycount(args), sizeof(*args), c_arg))) {
errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
/* NOTREACHED */
}
if (ddflags & ap->noset) {
errx(EXIT_FAILURE,
"%s: illegal argument combination or already set",
tmp.name);
/* NOTREACHED */
}
ddflags |= ap->set;
ap->f(arg);
}
/* Final sanity checks. */
if (ddflags & C_BS) {
/*
* Bs is turned off by any conversion -- we assume the user
* just wanted to set both the input and output block sizes
* and didn't want the bs semantics, so we don't warn.
*/
if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
C_UNBLOCK | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
ddflags &= ~C_BS;
ddflags |= C_IBS|C_OBS;
}
/* Bs supersedes ibs and obs. */
if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
warnx("bs supersedes ibs and obs");
}
/*
* Ascii/ebcdic and cbs implies block/unblock.
* Block/unblock requires cbs and vice-versa.
*/
if (ddflags & (C_BLOCK|C_UNBLOCK)) {
if (!(ddflags & C_CBS)) {
errx(EXIT_FAILURE, "record operations require cbs");
/* NOTREACHED */
}
cfunc = ddflags & C_BLOCK ? block : unblock;
} else if (ddflags & C_CBS) {
if (ddflags & (C_ASCII|C_EBCDIC)) {
if (ddflags & C_ASCII) {
ddflags |= C_UNBLOCK;
cfunc = unblock;
} else {
ddflags |= C_BLOCK;
cfunc = block;
}
} else {
errx(EXIT_FAILURE,
"cbs meaningless if not doing record operations");
/* NOTREACHED */
}
} else
cfunc = def;
/* Read, write and seek calls take off_t as arguments.
*
* The following check is not done because an off_t is a quad
* for current NetBSD implementations.
*
* if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
* errx(1, "seek offsets cannot be larger than %d", INT_MAX);
*/
}
static int
c_arg(const void *a, const void *b)
{
return (strcmp(((const struct arg *)a)->name,
((const struct arg *)b)->name));
}
static void
f_bs(char *arg)
{
in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
}
static void
f_cbs(char *arg)
{
cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
}
static void
f_count(char *arg)
{
cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
if (!cpy_cnt)
terminate(0);
}
static void
f_files(char *arg)
{
files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
if (!files_cnt)
terminate(0);
}
static void
f_ibs(char *arg)
{
if (!(ddflags & C_BS))
in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
}
static void
f_if(char *arg)
{
in.name = arg;
}
#ifdef NO_MSGFMT
/* Build a small version (i.e. for a ramdisk root) */
static void
f_msgfmt(char *arg)
{
errx(EXIT_FAILURE, "msgfmt option disabled");
/* NOTREACHED */
}
#else /* NO_MSGFMT */
static void
f_msgfmt(char *arg)
{
/*
* If the format string is not valid, dd_write_msg() will print
* an error and exit.
*/
dd_write_msg(arg, 0);
msgfmt = arg;
}
#endif /* NO_MSGFMT */
static void
f_obs(char *arg)
{
if (!(ddflags & C_BS))
out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
}
static void
f_of(char *arg)
{
out.name = arg;
}
static void
f_seek(char *arg)
{
out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
}
static void
f_skip(char *arg)
{
in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
}
static void
f_progress(char *arg)
{
progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
}
#ifdef NO_CONV
/* Build a small version (i.e. for a ramdisk root) */
static void
f_conv(char *arg)
{
errx(EXIT_FAILURE, "conv option disabled");
/* NOTREACHED */
}
#else /* NO_CONV */
static const struct conv {
const char *name;
u_int set, noset;
const u_char *ctab;
} clist[] = {
{ "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
{ "block", C_BLOCK, C_UNBLOCK, NULL },
{ "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
{ "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
{ "lcase", C_LCASE, C_UCASE, NULL },
{ "noerror", C_NOERROR, 0, NULL },
{ "notrunc", C_NOTRUNC, 0, NULL },
{ "oldascii", C_ASCII, C_EBCDIC, e2a_32V },
{ "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V },
{ "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V },
{ "osync", C_OSYNC, C_BS, NULL },
{ "sparse", C_SPARSE, 0, NULL },
{ "swab", C_SWAB, 0, NULL },
{ "sync", C_SYNC, 0, NULL },
{ "ucase", C_UCASE, C_LCASE, NULL },
{ "unblock", C_UNBLOCK, C_BLOCK, NULL },
/* If you add items to this table, be sure to add the
* conversions to the C_BS check in the jcl routine above.
*/
};
static void
f_conv(char *arg)
{
struct conv *cp, tmp;
while (arg != NULL) {
tmp.name = strsep(&arg, ",");
if (!(cp = bsearch(&tmp, clist,
__arraycount(clist), sizeof(*clist), c_conv))) {
errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
/* NOTREACHED */
}
if (ddflags & cp->noset) {
errx(EXIT_FAILURE,
"%s: illegal conversion combination", tmp.name);
/* NOTREACHED */
}
ddflags |= cp->set;
if (cp->ctab)
ctab = cp->ctab;
}
}
static int
c_conv(const void *a, const void *b)
{
return (strcmp(((const struct conv *)a)->name,
((const struct conv *)b)->name));
}
#endif /* NO_CONV */

View File

@@ -1,283 +0,0 @@
/* $NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <err.h>
#include <string.h>
#include <stdlib.h>
#include "dd.h"
#include "extern.h"
/*
* def --
* Copy input to output. Input is buffered until reaches obs, and then
* output until less than obs remains. Only a single buffer is used.
* Worst case buffer calculation is (ibs + obs - 1).
*/
void
def(void)
{
uint64_t cnt;
u_char *inp;
const u_char *t;
if ((t = ctab) != NULL)
for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
*inp = t[*inp];
/* Make the output buffer look right. */
out.dbp = in.dbp;
out.dbcnt = in.dbcnt;
if (in.dbcnt >= out.dbsz) {
/* If the output buffer is full, write it. */
dd_out(0);
/*
* Ddout copies the leftover output to the beginning of
* the buffer and resets the output buffer. Reset the
* input buffer to match it.
*/
in.dbp = out.dbp;
in.dbcnt = out.dbcnt;
}
}
void
def_close(void)
{
/* Just update the count, everything is already in the buffer. */
if (in.dbcnt)
out.dbcnt = in.dbcnt;
}
#ifdef NO_CONV
/* Build a smaller version (i.e. for a miniroot) */
/* These can not be called, but just in case... */
static const char no_block[] = "unblock and -DNO_CONV?";
void block(void) { errx(EXIT_FAILURE, "%s", no_block + 2); }
void block_close(void) { errx(EXIT_FAILURE, "%s", no_block + 2); }
void unblock(void) { errx(EXIT_FAILURE, "%s", no_block); }
void unblock_close(void) { errx(EXIT_FAILURE, "%s", no_block); }
#else /* NO_CONV */
/*
* Copy variable length newline terminated records with a max size cbsz
* bytes to output. Records less than cbs are padded with spaces.
*
* max in buffer: MAX(ibs, cbsz)
* max out buffer: obs + cbsz
*/
void
block(void)
{
static int intrunc;
int ch = 0; /* pacify gcc */
uint64_t cnt, maxlen;
u_char *inp, *outp;
const u_char *t;
/*
* Record truncation can cross block boundaries. If currently in a
* truncation state, keep tossing characters until reach a newline.
* Start at the beginning of the buffer, as the input buffer is always
* left empty.
*/
if (intrunc) {
for (inp = in.db, cnt = in.dbrcnt;
cnt && *inp++ != '\n'; --cnt);
if (!cnt) {
in.dbcnt = 0;
in.dbp = in.db;
return;
}
intrunc = 0;
/* Adjust the input buffer numbers. */
in.dbcnt = cnt - 1;
in.dbp = inp + cnt - 1;
}
/*
* Copy records (max cbsz size chunks) into the output buffer. The
* translation is done as we copy into the output buffer.
*/
for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
maxlen = MIN(cbsz, in.dbcnt);
if ((t = ctab) != NULL)
for (cnt = 0;
cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
*outp++ = t[ch];
else
for (cnt = 0;
cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
*outp++ = ch;
/*
* Check for short record without a newline. Reassemble the
* input block.
*/
if (ch != '\n' && in.dbcnt < cbsz) {
(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
break;
}
/* Adjust the input buffer numbers. */
in.dbcnt -= cnt;
if (ch == '\n')
--in.dbcnt;
/* Pad short records with spaces. */
if (cnt < cbsz)
(void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
else {
/*
* If the next character wouldn't have ended the
* block, it's a truncation.
*/
if (!in.dbcnt || *inp != '\n')
++st.trunc;
/* Toss characters to a newline. */
for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
if (!in.dbcnt)
intrunc = 1;
else
--in.dbcnt;
}
/* Adjust output buffer numbers. */
out.dbp += cbsz;
if ((out.dbcnt += cbsz) >= out.dbsz)
dd_out(0);
outp = out.dbp;
}
in.dbp = in.db + in.dbcnt;
}
void
block_close(void)
{
/*
* Copy any remaining data into the output buffer and pad to a record.
* Don't worry about truncation or translation, the input buffer is
* always empty when truncating, and no characters have been added for
* translation. The bottom line is that anything left in the input
* buffer is a truncated record. Anything left in the output buffer
* just wasn't big enough.
*/
if (in.dbcnt) {
++st.trunc;
(void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
(void)memset(out.dbp + in.dbcnt,
ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
out.dbcnt += cbsz;
}
}
/*
* Convert fixed length (cbsz) records to variable length. Deletes any
* trailing blanks and appends a newline.
*
* max in buffer: MAX(ibs, cbsz) + cbsz
* max out buffer: obs + cbsz
*/
void
unblock(void)
{
uint64_t cnt;
u_char *inp;
const u_char *t;
/* Translation and case conversion. */
if ((t = ctab) != NULL)
for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
*inp = t[*inp];
/*
* Copy records (max cbsz size chunks) into the output buffer. The
* translation has to already be done or we might not recognize the
* spaces.
*/
for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
if (t >= inp) {
cnt = t - inp + 1;
(void)memmove(out.dbp, inp, cnt);
out.dbp += cnt;
out.dbcnt += cnt;
}
++out.dbcnt;
*out.dbp++ = '\n';
if (out.dbcnt >= out.dbsz)
dd_out(0);
}
if (in.dbcnt)
(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
in.dbp = in.db + in.dbcnt;
}
void
unblock_close(void)
{
uint64_t cnt;
u_char *t;
if (in.dbcnt) {
warnx("%s: short input record", in.name);
for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
if (t >= in.db) {
cnt = t - in.db + 1;
(void)memmove(out.dbp, in.db, cnt);
out.dbp += cnt;
out.dbcnt += cnt;
}
++out.dbcnt;
*out.dbp++ = '\n';
}
}
#endif /* NO_CONV */

View File

@@ -1,287 +0,0 @@
/* $NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
/*
* There are currently six tables:
*
* ebcdic -> ascii 32V conv=oldascii
* ascii -> ebcdic 32V conv=oldebcdic
* ascii -> ibm ebcdic 32V conv=oldibm
*
* ebcdic -> ascii POSIX/S5 conv=ascii
* ascii -> ebcdic POSIX/S5 conv=ebcdic
* ascii -> ibm ebcdic POSIX/S5 conv=ibm
*
* Other tables are built from these if multiple conversions are being
* done.
*
* Tables used for conversions to/from IBM and EBCDIC to support an extension
* to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted
* from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were
* constructed by running against a file with all possible byte values.
*
* More information can be obtained in "Correspondences of 8-Bit and Hollerith
* Codes for Computer Environments-A USASI Tutorial", Communications of the
* ACM, Volume 11, Number 11, November 1968, pp. 783-789.
*/
u_char casetab[256];
/* EBCDIC to ASCII -- 32V compatible. */
const u_char e2a_32V[] = {
0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */
0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */
0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */
0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */
0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */
0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};
/* ASCII to EBCDIC -- 32V compatible. */
const u_char a2e_32V[] = {
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};
/* ASCII to IBM EBCDIC -- 32V compatible. */
const u_char a2ibm_32V[] = {
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};
/* EBCDIC to ASCII -- POSIX and System V compatible. */
const u_char e2a_POSIX[] = {
0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */
0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */
0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */
0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */
0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */
0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};
/* ASCII to EBCDIC -- POSIX and System V compatible. */
const u_char a2e_POSIX[] = {
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */
0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};
/* ASCII to IBM EBCDIC -- POSIX and System V compatible. */
const u_char a2ibm_POSIX[] = {
0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
};

View File

@@ -1,477 +0,0 @@
.\" $NetBSD: dd.1,v 1.25 2012/06/20 17:54:16 wiz Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Keith Muller of the University of California, San Diego.
.\"
.\" 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. 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.
.\"
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\"
.Dd November 6, 2011
.Dt DD 1
.Os
.Sh NAME
.Nm dd
.Nd convert and copy a file
.Sh SYNOPSIS
.Nm
.Op operand ...
.Sh DESCRIPTION
The
.Nm
utility copies the standard input to the standard output.
Input data is read and written in 512-byte blocks.
If input reads are short, input from multiple reads are aggregated
to form the output block.
When finished,
.Nm
displays the number of complete and partial input and output blocks
and truncated input records to the standard error output.
.Pp
The following operands are available:
.Bl -tag -width of=file
.It Cm bs= Ns Ar n
Set both input and output block size, superseding the
.Cm ibs
and
.Cm obs
operands.
If no conversion values other than
.Cm noerror ,
.Cm notrunc
or
.Cm sync
are specified, then each input block is copied to the output as a
single block without any aggregation of short blocks.
.It Cm cbs= Ns Ar n
Set the conversion record size to
.Va n
bytes.
The conversion record size is required by the record oriented conversion
values.
.It Cm count= Ns Ar n
Copy only
.Va n
input blocks.
.It Cm files= Ns Ar n
Copy
.Va n
input files before terminating.
This operand is only applicable when the input device is a tape.
.It Cm ibs= Ns Ar n
Set the input block size to
.Va n
bytes instead of the default 512.
.It Cm if= Ns Ar file
Read input from
.Ar file
instead of the standard input.
.It Cm iseek= Ns Ar n
Seek on the input file
.Ar n
blocks.
This is synonymous with
.Cm skip= Ns Ar n .
.It Cm msgfmt= Ns Ar fmt
Specify the message format
.Ar fmt
to be used when writing information to standard output.
Possible values are:
.Bl -tag -width xxxxx -offset indent -compact
.It quiet
turns off information summary report except for errors and
.Cm progress .
.It posix
default information summary report as specified by POSIX.
.It human
default information summary report extended with human-readable
values.
.El
.Pp
When
.Ar fmt
does not correspond to any value given above,
it contains a string that will be used as format specifier
for the information summary output.
Each conversion specification is introduced by the character
.Cm % .
The following ones are available:
.Bl -tag -width xx -offset indent -compact
.It b
total number of bytes transferred
.It B
total number of bytes transferred in
.Xr humanize_number 3
format
.It e
speed transfer
.It E
speed transfer in
.Xr humanize_number 3
format
.It i
number of partial input block(s)
.It I
number of full input block(s)
.It o
number of partial output block(s)
.It O
number of full output block(s)
.It s
time elapsed since the beginning in
.Do seconds.ms Dc
format
.It p
number of sparse output blocks
.It t
number of truncated blocks
.It w
number of odd-length swab blocks
.It P
singular/plural of
.Do block Dc
depending on number of sparse blocks
.It T
singular/plural of
.Do block Dc
depending on number of truncated blocks
.It W
singular/plural of
.Do block Dc
depending on number of swab blocks
.El
.It Cm obs= Ns Ar n
Set the output block size to
.Va n
bytes instead of the default 512.
.It Cm of= Ns Ar file
Write output to
.Ar file
instead of the standard output.
Any regular output file is truncated unless the
.Cm notrunc
conversion value is specified.
If an initial portion of the output file is skipped (see the
.Cm seek
operand)
the output file is truncated at that point.
.It Cm oseek= Ns Ar n
Seek on the output file
.Ar n
blocks.
This is synonymous with
.Cm seek= Ns Ar n .
.It Cm seek= Ns Ar n
Seek
.Va n
blocks from the beginning of the output before copying.
On non-tape devices, an
.Xr lseek 2
operation is used.
Otherwise, existing blocks are read and the data discarded.
If the user does not have read permission for the tape, it is positioned
using the tape
.Xr ioctl 2
function calls.
If the seek operation is past the end of file, space from the current
end of file to the specified offset is filled with blocks of
.Tn NUL
bytes.
.It Cm skip= Ns Ar n
Skip
.Va n
blocks from the beginning of the input before copying.
On input which supports seeks, an
.Xr lseek 2
operation is used.
Otherwise, input data is read and discarded.
For pipes, the correct number of bytes is read.
For all other devices, the correct number of blocks is read without
distinguishing between a partial or complete block being read.
.It Cm progress= Ns Ar n
Switch on display of progress if
.Va n
is set to any non-zero value.
This will cause a
.Dq \&.
to be printed (to the standard error output) for every
.Va n
full or partial blocks written to the output file.
.Sm off
.It Cm conv= Cm value Op \&, Cm value \&...
.Sm on
Where
.Cm value
is one of the symbols from the following list.
.Bl -tag -width unblock
.It Cm ascii , oldascii
The same as the
.Cm unblock
value except that characters are translated from
.Tn EBCDIC
to
.Tn ASCII
before the
records are converted.
(These values imply
.Cm unblock
if the operand
.Cm cbs
is also specified.)
There are two conversion maps for
.Tn ASCII .
The value
.Cm ascii
specifies the recommended one which is compatible with
.At V .
The value
.Cm oldascii
specifies the one used in historic
.Tn AT\*[Am]T
and pre-
.Bx 4.3 Reno
systems.
.It Cm block
Treats the input as a sequence of newline or end-of-file terminated variable
length records independent of input and output block boundaries.
Any trailing newline character is discarded.
Each input record is converted to a fixed length output record where the
length is specified by the
.Cm cbs
operand.
Input records shorter than the conversion record size are padded with spaces.
Input records longer than the conversion record size are truncated.
The number of truncated input records, if any, are reported to the standard
error output at the completion of the copy.
.It Cm ebcdic , ibm , oldebcdic , oldibm
The same as the
.Cm block
value except that characters are translated from
.Tn ASCII
to
.Tn EBCDIC
after the
records are converted.
(These values imply
.Cm block
if the operand
.Cm cbs
is also specified.)
There are four conversion maps for
.Tn EBCDIC .
The value
.Cm ebcdic
specifies the recommended one which is compatible with
.At V .
The value
.Cm ibm
is a slightly different mapping, which is compatible with the
.At V
.Cm ibm
value.
The values
.Cm oldebcdic
and
.Cm oldibm
are maps used in historic
.Tn AT\*[Am]T
and pre
.Bx 4.3 Reno
systems.
.It Cm lcase
Transform uppercase characters into lowercase characters.
.It Cm noerror
Do not stop processing on an input error.
When an input error occurs, a diagnostic message followed by the current
input and output block counts will be written to the standard error output
in the same format as the standard completion message.
If the
.Cm sync
conversion is also specified, any missing input data will be replaced
with
.Tn NUL
bytes (or with spaces if a block oriented conversion value was
specified) and processed as a normal input buffer.
If the
.Cm sync
conversion is not specified, the input block is omitted from the output.
On input files which are not tapes or pipes, the file offset
will be positioned past the block in which the error occurred using
.Xr lseek 2 .
.It Cm notrunc
Do not truncate the output file.
This will preserve any blocks in the output file not explicitly written
by
.Nm .
The
.Cm notrunc
value is not supported for tapes.
.It Cm osync
Pad the final output block to the full output block size.
If the input file is not a multiple of the output block size
after conversion, this conversion forces the final output block
to be the same size as preceding blocks for use on devices that require
regularly sized blocks to be written.
This option is incompatible with use of the
.Cm bs= Ns Ar n
block size specification.
.It Cm sparse
If one or more non-final output blocks would consist solely of
.Dv NUL
bytes, try to seek the output file by the required space instead of
filling them with
.Dv NUL Ns s .
This results in a sparse file on some file systems.
.It Cm swab
Swap every pair of input bytes.
If an input buffer has an odd number of bytes, the last byte will be
ignored during swapping.
.It Cm sync
Pad every input block to the input buffer size.
Spaces are used for pad bytes if a block oriented conversion value is
specified, otherwise
.Tn NUL
bytes are used.
.It Cm ucase
Transform lowercase characters into uppercase characters.
.It Cm unblock
Treats the input as a sequence of fixed length records independent of input
and output block boundaries.
The length of the input records is specified by the
.Cm cbs
operand.
Any trailing space characters are discarded and a newline character is
appended.
.El
.El
.Pp
Where sizes are specified, a decimal number of bytes is expected.
Two or more numbers may be separated by an
.Dq x
to indicate a product.
Each number may have one of the following optional suffixes:
.Bl -tag -width 3n -offset indent -compact
.It b
Block; multiply by 512
.It k
Kibi; multiply by 1024 (1 KiB)
.It m
Mebi; multiply by 1048576 (1 MiB)
.It g
Gibi; multiply by 1073741824 (1 GiB)
.It t
Tebi; multiply by 1099511627776 (1 TiB)
.It w
Word; multiply by the number of bytes in an integer
.El
.Pp
When finished,
.Nm
displays the number of complete and partial input and output blocks,
truncated input records and odd-length byte-swapping blocks to the
standard error output.
A partial input block is one where less than the input block size
was read.
A partial output block is one where less than the output block size
was written.
Partial output blocks to tape devices are considered fatal errors.
Otherwise, the rest of the block will be written.
Partial output blocks to character devices will produce a warning message.
A truncated input block is one where a variable length record oriented
conversion value was specified and the input line was too long to
fit in the conversion record or was not newline terminated.
.Pp
Normally, data resulting from input or conversion or both are aggregated
into output blocks of the specified size.
After the end of input is reached, any remaining output is written as
a block.
This means that the final output block may be shorter than the output
block size.
.Pp
If
.Nm
receives a
.Dv SIGINFO
signal
(see the
.Ic status
argument for
.Xr stty 1 ) ,
the current input and output block counts will
be written to the standard error output
in the same format as the standard completion message.
If
.Nm
receives a
.Dv SIGINT
signal, the current input and output block counts will
be written to the standard error output
in the same format as the standard completion message and
.Nm
will exit.
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success and \*[Gt]0 if an error occurred.
.Sh EXAMPLES
To print summary information in human-readable form:
.Pp
.Dl dd if=/dev/zero of=/dev/null count=1 msgfmt=human
.Pp
To customize the information summary output and print it through
.Xr unvis 3 :
.Pp
.Bd -literal -offset indent
dd if=/dev/zero of=/dev/null count=1 \e
msgfmt='speed:%E, in %s seconds\en' 2\*[Gt]\*[Am]1 | unvis
.Ed
.Sh SEE ALSO
.Xr cp 1 ,
.Xr mt 1 ,
.Xr tr 1
.Sh STANDARDS
The
.Nm
utility is expected to be a superset of the
.St -p1003.2
standard.
The
.Cm files
and
.Cm msgfmt
operands and the
.Cm ascii ,
.Cm ebcdic ,
.Cm ibm ,
.Cm oldascii ,
.Cm oldebcdic
and
.Cm oldibm
values are extensions to the
.Tn POSIX
standard.

View File

@@ -1,598 +0,0 @@
/* $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dd.h"
#include "extern.h"
static void dd_close(void);
static void dd_in(void);
static void getfdtype(IO *);
static void redup_clean_fd(IO *);
static void setup(void);
int main(int, char *[]);
IO in, out; /* input/output state */
STAT st; /* statistics */
void (*cfunc)(void); /* conversion function */
uint64_t cpy_cnt; /* # of blocks to copy */
static off_t pending = 0; /* pending seek if sparse */
u_int ddflags; /* conversion options */
uint64_t cbsz; /* conversion block size */
u_int files_cnt = 1; /* # of files to copy */
uint64_t progress = 0; /* display sign of life */
const u_char *ctab; /* conversion table */
sigset_t infoset; /* a set blocking SIGINFO */
const char *msgfmt = "posix"; /* default summary() message format */
/*
* Ops for stdin/stdout and crunch'd dd. These are always host ops.
*/
static const struct ddfops ddfops_stdfd = {
.op_open = open,
.op_close = close,
.op_fcntl = fcntl,
.op_ioctl = ioctl,
.op_fstat = fstat,
.op_fsync = fsync,
.op_ftruncate = ftruncate,
.op_lseek = lseek,
.op_read = read,
.op_write = write,
};
extern const struct ddfops ddfops_prog;
int
main(int argc, char *argv[])
{
int ch;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "")) != -1) {
switch (ch) {
default:
errx(EXIT_FAILURE, "usage: dd [operand ...]");
/* NOTREACHED */
}
}
argc -= (optind - 1);
argv += (optind - 1);
jcl(argv);
#ifndef CRUNCHOPS
if (ddfops_prog.op_init && ddfops_prog.op_init() == -1)
err(1, "prog init");
#endif
setup();
(void)signal(SIGINFO, summaryx);
(void)signal(SIGINT, terminate);
(void)sigemptyset(&infoset);
(void)sigaddset(&infoset, SIGINFO);
(void)atexit(summary);
while (files_cnt--)
dd_in();
dd_close();
exit(0);
/* NOTREACHED */
}
static void
setup(void)
{
#ifdef CRUNCHOPS
const struct ddfops *prog_ops = &ddfops_stdfd;
#else
const struct ddfops *prog_ops = &ddfops_prog;
#endif
if (in.name == NULL) {
in.name = "stdin";
in.fd = STDIN_FILENO;
in.ops = &ddfops_stdfd;
} else {
in.ops = prog_ops;
in.fd = ddop_open(in, in.name, O_RDONLY, 0);
if (in.fd < 0)
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
/* Ensure in.fd is outside the stdio descriptor range */
redup_clean_fd(&in);
}
getfdtype(&in);
if (files_cnt > 1 && !(in.flags & ISTAPE)) {
errx(EXIT_FAILURE, "files is not supported for non-tape devices");
/* NOTREACHED */
}
if (out.name == NULL) {
/* No way to check for read access here. */
out.fd = STDOUT_FILENO;
out.name = "stdout";
out.ops = &ddfops_stdfd;
} else {
out.ops = prog_ops;
#define OFLAGS \
(O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
/*
* May not have read access, so try again with write only.
* Without read we may have a problem if output also does
* not support seeks.
*/
if (out.fd < 0) {
out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
DEFFILEMODE);
out.flags |= NOREAD;
}
if (out.fd < 0) {
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
}
/* Ensure out.fd is outside the stdio descriptor range */
redup_clean_fd(&out);
}
getfdtype(&out);
/*
* Allocate space for the input and output buffers. If not doing
* record oriented I/O, only need a single buffer.
*/
if (!(ddflags & (C_BLOCK|C_UNBLOCK))) {
size_t dbsz = out.dbsz;
if (!(ddflags & C_BS))
dbsz += in.dbsz - 1;
if ((in.db = malloc(dbsz)) == NULL) {
err(EXIT_FAILURE, NULL);
/* NOTREACHED */
}
out.db = in.db;
} else if ((in.db =
malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
(out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
err(EXIT_FAILURE, NULL);
/* NOTREACHED */
}
in.dbp = in.db;
out.dbp = out.db;
/* Position the input/output streams. */
if (in.offset)
pos_in();
if (out.offset)
pos_out();
/*
* Truncate the output file; ignore errors because it fails on some
* kinds of output files, tapes, for example.
*/
if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
(void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
/*
* If converting case at the same time as another conversion, build a
* table that does both at once. If just converting case, use the
* built-in tables.
*/
if (ddflags & (C_LCASE|C_UCASE)) {
#ifdef NO_CONV
/* Should not get here, but just in case... */
errx(EXIT_FAILURE, "case conv and -DNO_CONV");
/* NOTREACHED */
#else /* NO_CONV */
u_int cnt;
if (ddflags & C_ASCII || ddflags & C_EBCDIC) {
if (ddflags & C_LCASE) {
for (cnt = 0; cnt < 256; ++cnt)
casetab[cnt] = tolower(ctab[cnt]);
} else {
for (cnt = 0; cnt < 256; ++cnt)
casetab[cnt] = toupper(ctab[cnt]);
}
} else {
if (ddflags & C_LCASE) {
for (cnt = 0; cnt < 256; ++cnt)
casetab[cnt] = tolower(cnt);
} else {
for (cnt = 0; cnt < 256; ++cnt)
casetab[cnt] = toupper(cnt);
}
}
ctab = casetab;
#endif /* NO_CONV */
}
(void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */
}
static void
getfdtype(IO *io)
{
struct mtget mt;
struct stat sb;
if (io->ops->op_fstat(io->fd, &sb)) {
err(EXIT_FAILURE, "%s", io->name);
/* NOTREACHED */
}
if (S_ISCHR(sb.st_mode))
io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
? ISCHR : ISTAPE;
else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
&& errno == ESPIPE)
io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */
}
/*
* Move the parameter file descriptor to a descriptor that is outside the
* stdio descriptor range, if necessary. This is required to avoid
* accidentally outputting completion or error messages into the
* output file that were intended for the tty.
*/
static void
redup_clean_fd(IO *io)
{
int fd = io->fd;
int newfd;
if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
fd != STDERR_FILENO)
/* File descriptor is ok, return immediately. */
return;
/*
* 3 is the first descriptor greater than STD*_FILENO. Any
* free descriptor valued 3 or above is acceptable...
*/
newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
if (newfd < 0) {
err(EXIT_FAILURE, "dupfd IO");
/* NOTREACHED */
}
io->ops->op_close(fd);
io->fd = newfd;
}
static void
dd_in(void)
{
int flags;
int64_t n;
for (flags = ddflags;;) {
if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
return;
/*
* Clear the buffer first if doing "sync" on input.
* If doing block operations use spaces. This will
* affect not only the C_NOERROR case, but also the
* last partial input block which should be padded
* with zero and not garbage.
*/
if (flags & C_SYNC) {
if (flags & (C_BLOCK|C_UNBLOCK))
(void)memset(in.dbp, ' ', in.dbsz);
else
(void)memset(in.dbp, 0, in.dbsz);
}
n = ddop_read(in, in.fd, in.dbp, in.dbsz);
if (n == 0) {
in.dbrcnt = 0;
return;
}
/* Read error. */
if (n < 0) {
/*
* If noerror not specified, die. POSIX requires that
* the warning message be followed by an I/O display.
*/
if (!(flags & C_NOERROR)) {
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
}
warn("%s", in.name);
summary();
/*
* If it's not a tape drive or a pipe, seek past the
* error. If your OS doesn't do the right thing for
* raw disks this section should be modified to re-read
* in sector size chunks.
*/
if (!(in.flags & (ISPIPE|ISTAPE)) &&
ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR))
warn("%s", in.name);
/* If sync not specified, omit block and continue. */
if (!(ddflags & C_SYNC))
continue;
/* Read errors count as full blocks. */
in.dbcnt += in.dbrcnt = in.dbsz;
++st.in_full;
/* Handle full input blocks. */
} else if ((uint64_t)n == in.dbsz) {
in.dbcnt += in.dbrcnt = n;
++st.in_full;
/* Handle partial input blocks. */
} else {
/* If sync, use the entire block. */
if (ddflags & C_SYNC)
in.dbcnt += in.dbrcnt = in.dbsz;
else
in.dbcnt += in.dbrcnt = n;
++st.in_part;
}
/*
* POSIX states that if bs is set and no other conversions
* than noerror, notrunc or sync are specified, the block
* is output without buffering as it is read.
*/
if (ddflags & C_BS) {
out.dbcnt = in.dbcnt;
dd_out(1);
in.dbcnt = 0;
continue;
}
if (ddflags & C_SWAB) {
if ((n = in.dbrcnt) & 1) {
++st.swab;
--n;
}
swab(in.dbp, in.dbp, n);
}
in.dbp += in.dbrcnt;
(*cfunc)();
}
}
/*
* Cleanup any remaining I/O and flush output. If necessary, output file
* is truncated.
*/
static void
dd_close(void)
{
if (cfunc == def)
def_close();
else if (cfunc == block)
block_close();
else if (cfunc == unblock)
unblock_close();
if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) {
(void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
out.dbcnt = out.dbsz;
}
/* If there are pending sparse blocks, make sure
* to write out the final block un-sparse
*/
if ((out.dbcnt == 0) && pending) {
memset(out.db, 0, out.dbsz);
out.dbcnt = out.dbsz;
out.dbp = out.db + out.dbcnt;
pending -= out.dbsz;
}
if (out.dbcnt)
dd_out(1);
/*
* Reporting nfs write error may be deferred until next
* write(2) or close(2) system call. So, we need to do an
* extra check. If an output is stdout, the file structure
* may be shared with other processes and close(2) just
* decreases the reference count.
*/
if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
&& errno != EINVAL) {
err(EXIT_FAILURE, "fsync stdout");
/* NOTREACHED */
}
if (ddop_close(out, out.fd) == -1) {
err(EXIT_FAILURE, "close");
/* NOTREACHED */
}
}
void
dd_out(int force)
{
static int warned;
int64_t cnt, n, nw;
u_char *outp;
/*
* Write one or more blocks out. The common case is writing a full
* output block in a single write; increment the full block stats.
* Otherwise, we're into partial block writes. If a partial write,
* and it's a character device, just warn. If a tape device, quit.
*
* The partial writes represent two cases. 1: Where the input block
* was less than expected so the output block was less than expected.
* 2: Where the input block was the right size but we were forced to
* write the block in multiple chunks. The original versions of dd(1)
* never wrote a block in more than a single write, so the latter case
* never happened.
*
* One special case is if we're forced to do the write -- in that case
* we play games with the buffer size, and it's usually a partial write.
*/
outp = out.db;
for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
for (cnt = n;; cnt -= nw) {
if (!force && ddflags & C_SPARSE) {
int sparse, i;
sparse = 1; /* Is buffer sparse? */
for (i = 0; i < cnt; i++)
if (outp[i] != 0) {
sparse = 0;
break;
}
if (sparse) {
pending += cnt;
outp += cnt;
nw = 0;
break;
}
}
if (pending != 0) {
if (ddop_lseek(out,
out.fd, pending, SEEK_CUR) == -1)
err(EXIT_FAILURE, "%s: seek error creating sparse file",
out.name);
}
nw = bwrite(&out, outp, cnt);
if (nw <= 0) {
if (nw == 0)
errx(EXIT_FAILURE,
"%s: end of device", out.name);
/* NOTREACHED */
if (errno != EINTR)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
nw = 0;
}
if (pending) {
st.bytes += pending;
st.sparse += pending/out.dbsz;
st.out_full += pending/out.dbsz;
pending = 0;
}
outp += nw;
st.bytes += nw;
if (nw == n) {
if ((uint64_t)n != out.dbsz)
++st.out_part;
else
++st.out_full;
break;
}
++st.out_part;
if (nw == cnt)
break;
if (out.flags & ISCHR && !warned) {
warned = 1;
warnx("%s: short write on character device", out.name);
}
if (out.flags & ISTAPE)
errx(EXIT_FAILURE,
"%s: short write on tape device", out.name);
/* NOTREACHED */
}
if ((out.dbcnt -= n) < out.dbsz)
break;
}
/* Reassemble the output block. */
if (out.dbcnt)
(void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
out.dbp = out.db + out.dbcnt;
if (progress && (st.out_full + st.out_part) % progress == 0)
(void)write(STDERR_FILENO, ".", 1);
}
/*
* A protected against SIGINFO write
*/
ssize_t
bwrite(IO *io, const void *buf, size_t len)
{
sigset_t oset;
ssize_t rv;
int oerrno;
(void)sigprocmask(SIG_BLOCK, &infoset, &oset);
rv = io->ops->op_write(io->fd, buf, len);
oerrno = errno;
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
errno = oerrno;
return (rv);
}

View File

@@ -1,123 +0,0 @@
/* $NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. 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.
*
* @(#)dd.h 8.3 (Berkeley) 4/2/94
*/
#include <sys/stat.h>
struct ddfops {
int (*op_init)(void);
int (*op_open)(const char *, int, ...);
int (*op_close)(int);
int (*op_fcntl)(int, int, ...);
int (*op_ioctl)(int, unsigned long, ...);
int (*op_fstat)(int, struct stat *);
int (*op_fsync)(int);
int (*op_ftruncate)(int, off_t);
off_t (*op_lseek)(int, off_t, int);
ssize_t (*op_read)(int, void *, size_t);
ssize_t (*op_write)(int, const void *, size_t);
};
#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, __VA_ARGS__)
#define ddop_close(dir, a1) dir.ops->op_close(a1)
#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
#define ddop_fsync(dir, a1) dir.ops->op_fsync(a1)
#define ddop_ftruncate(dir, a1, a2) dir.ops->op_ftruncate(a1, a2)
#define ddop_lseek(dir, a1, a2, a3) dir.ops->op_lseek(a1, a2, a3)
#define ddop_read(dir, a1, a2, a3) dir.ops->op_read(a1, a2, a3)
#define ddop_write(dir, a1, a2, a3) dir.ops->op_write(a1, a2, a3)
/* Input/output stream state. */
typedef struct {
u_char *db; /* buffer address */
u_char *dbp; /* current buffer I/O address */
uint64_t dbcnt; /* current buffer byte count */
int64_t dbrcnt; /* last read byte count */
uint64_t dbsz; /* buffer size */
#define ISCHR 0x01 /* character device (warn on short) */
#define ISPIPE 0x02 /* pipe (not truncatable) */
#define ISTAPE 0x04 /* tape (not seekable) */
#define NOREAD 0x08 /* not readable */
u_int flags;
const char *name; /* name */
int fd; /* file descriptor */
uint64_t offset; /* # of blocks to skip */
struct ddfops const *ops; /* ops to use with fd */
} IO;
typedef struct {
uint64_t in_full; /* # of full input blocks */
uint64_t in_part; /* # of partial input blocks */
uint64_t out_full; /* # of full output blocks */
uint64_t out_part; /* # of partial output blocks */
uint64_t trunc; /* # of truncated records */
uint64_t swab; /* # of odd-length swab blocks */
uint64_t sparse; /* # of sparse output blocks */
uint64_t bytes; /* # of bytes written */
struct timeval start; /* start time of dd */
} STAT;
/* Flags (in ddflags). */
#define C_ASCII 0x00001
#define C_BLOCK 0x00002
#define C_BS 0x00004
#define C_CBS 0x00008
#define C_COUNT 0x00010
#define C_EBCDIC 0x00020
#define C_FILES 0x00040
#define C_IBS 0x00080
#define C_IF 0x00100
#define C_LCASE 0x00200
#define C_NOERROR 0x00400
#define C_NOTRUNC 0x00800
#define C_OBS 0x01000
#define C_OF 0x02000
#define C_SEEK 0x04000
#define C_SKIP 0x08000
#define C_SWAB 0x10000
#define C_SYNC 0x20000
#define C_UCASE 0x40000
#define C_UNBLOCK 0x80000
#define C_OSYNC 0x100000
#define C_SPARSE 0x200000

View File

@@ -1,53 +0,0 @@
/* $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include "dd.h"
const struct ddfops ddfops_prog = {
.op_open = open,
.op_close = close,
.op_fcntl = fcntl,
.op_ioctl = ioctl,
.op_fstat = fstat,
.op_fsync = fsync,
.op_ftruncate = ftruncate,
.op_lseek = lseek,
.op_read = read,
.op_write = write,
};

View File

@@ -1,52 +0,0 @@
/* $NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
#endif /* !lint */
#include <rump/rump_syscalls.h>
#include <rump/rumpclient.h>
#include "dd.h"
const struct ddfops ddfops_prog = {
.op_init = rumpclient_init,
.op_open = rump_sys_open,
.op_close = rump_sys_close,
.op_fcntl = rump_sys_fcntl,
.op_ioctl = rump_sys_ioctl,
.op_fstat = rump_sys_fstat,
.op_fsync = rump_sys_fsync,
.op_ftruncate = rump_sys_ftruncate,
.op_lseek = rump_sys_lseek,
.op_read = rump_sys_read,
.op_write = rump_sys_write,
};

View File

@@ -1,82 +0,0 @@
/* $NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. 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.
*
* @(#)extern.h 8.3 (Berkeley) 4/2/94
*/
#include <sys/cdefs.h>
#ifdef NO_CONV
__dead void block(void);
__dead void block_close(void);
__dead void unblock(void);
__dead void unblock_close(void);
#else
void block(void);
void block_close(void);
void unblock(void);
void unblock_close(void);
#endif
#ifndef NO_MSGFMT
int dd_write_msg(const char *, int);
#endif
void dd_out(int);
void def(void);
void def_close(void);
void jcl(char **);
void pos_in(void);
void pos_out(void);
void summary(void);
void summaryx(int);
__dead void terminate(int);
void unblock(void);
void unblock_close(void);
ssize_t bwrite(IO *, const void *, size_t);
extern IO in, out;
extern STAT st;
extern void (*cfunc)(void);
extern uint64_t cpy_cnt;
extern uint64_t cbsz;
extern u_int ddflags;
extern u_int files_cnt;
extern uint64_t progress;
extern const u_char *ctab;
extern const u_char a2e_32V[], a2e_POSIX[];
extern const u_char e2a_32V[], e2a_POSIX[];
extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];
extern const char *msgfmt;

View File

@@ -1,342 +0,0 @@
/* $NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <inttypes.h>
#include "dd.h"
#include "extern.h"
#define tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
static void posix_summary(void);
#ifndef NO_MSGFMT
static void custom_summary(void);
static void human_summary(void);
static void quiet_summary(void);
static void buffer_write(const char *, size_t, int);
#endif /* NO_MSGFMT */
void
summary(void)
{
if (progress)
(void)write(STDERR_FILENO, "\n", 1);
#ifdef NO_MSGFMT
return posix_summary();
#else /* NO_MSGFMT */
if (strncmp(msgfmt, "human", sizeof("human")) == 0)
return human_summary();
if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
return posix_summary();
if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
return quiet_summary();
return custom_summary();
#endif /* NO_MSGFMT */
}
static void
posix_summary(void)
{
char buf[100];
int64_t mS;
struct timeval tv;
if (progress)
(void)write(STDERR_FILENO, "\n", 1);
(void)gettimeofday(&tv, NULL);
mS = tv2mS(tv) - tv2mS(st.start);
if (mS == 0)
mS = 1;
/* Use snprintf(3) so that we don't reenter stdio(3). */
(void)snprintf(buf, sizeof(buf),
"%llu+%llu records in\n%llu+%llu records out\n",
(unsigned long long)st.in_full, (unsigned long long)st.in_part,
(unsigned long long)st.out_full, (unsigned long long)st.out_part);
(void)write(STDERR_FILENO, buf, strlen(buf));
if (st.swab) {
(void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
(unsigned long long)st.swab,
(st.swab == 1) ? "block" : "blocks");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
if (st.trunc) {
(void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
(unsigned long long)st.trunc,
(st.trunc == 1) ? "block" : "blocks");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
if (st.sparse) {
(void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
(unsigned long long)st.sparse,
(st.sparse == 1) ? "block" : "blocks");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
(void)snprintf(buf, sizeof(buf),
"%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
(unsigned long long) st.bytes,
(long) (mS / 1000),
(int) (mS % 1000),
(unsigned long long) (st.bytes * 1000LL / mS));
(void)write(STDERR_FILENO, buf, strlen(buf));
}
/* ARGSUSED */
void
summaryx(int notused)
{
summary();
}
/* ARGSUSED */
void
terminate(int signo)
{
summary();
(void)raise_default_signal(signo);
_exit(127);
}
#ifndef NO_MSGFMT
/*
* Buffer write(2) calls
*/
static void
buffer_write(const char *str, size_t size, int flush)
{
static char wbuf[128];
static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */
unsigned int i;
for (i = 0; i < size; i++) {
if (str != NULL) {
wbuf[cnt++] = str[i];
}
if (cnt >= sizeof(wbuf)) {
(void)write(STDERR_FILENO, wbuf, cnt);
cnt = 0;
}
}
if (flush != 0) {
(void)write(STDERR_FILENO, wbuf, cnt);
cnt = 0;
}
}
/*
* Write summary to stderr according to format 'fmt'. If 'enable' is 0, it
* will not attempt to write anything. Can be used to validate the
* correctness of the 'fmt' string.
*/
int
dd_write_msg(const char *fmt, int enable)
{
char hbuf[7], nbuf[32];
const char *ptr;
int64_t mS;
struct timeval tv;
(void)gettimeofday(&tv, NULL);
mS = tv2mS(tv) - tv2mS(st.start);
if (mS == 0)
mS = 1;
#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \
while (/*CONSTCOND*/0)
#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \
while (/*CONSTCOND*/0)
for (ptr = fmt; *ptr; ptr++) {
if (*ptr != '%') {
ADDC(*ptr);
continue;
}
switch (*++ptr) {
case 'b':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.bytes);
ADDS(nbuf);
break;
case 'B':
if (humanize_number(hbuf, sizeof(hbuf),
st.bytes, "B",
HN_AUTOSCALE, HN_DECIMAL) == -1)
warnx("humanize_number (bytes transferred)");
ADDS(hbuf);
break;
case 'e':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long) (st.bytes * 1000LL / mS));
ADDS(nbuf);
break;
case 'E':
if (humanize_number(hbuf, sizeof(hbuf),
st.bytes * 1000LL / mS, "B",
HN_AUTOSCALE, HN_DECIMAL) == -1)
warnx("humanize_number (bytes per second)");
ADDS(hbuf); ADDS("/sec");
break;
case 'i':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.in_part);
ADDS(nbuf);
break;
case 'I':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.in_full);
ADDS(nbuf);
break;
case 'o':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.out_part);
ADDS(nbuf);
break;
case 'O':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.out_full);
ADDS(nbuf);
break;
case 's':
(void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
(long) (mS / 1000), (int) (mS % 1000));
ADDS(nbuf);
break;
case 'p':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.sparse);
ADDS(nbuf);
break;
case 't':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.trunc);
ADDS(nbuf);
break;
case 'w':
(void)snprintf(nbuf, sizeof(nbuf), "%llu",
(unsigned long long)st.swab);
ADDS(nbuf);
break;
case 'P':
ADDS("block");
if (st.sparse != 1) ADDS("s");
break;
case 'T':
ADDS("block");
if (st.trunc != 1) ADDS("s");
break;
case 'W':
ADDS("block");
if (st.swab != 1) ADDS("s");
break;
case '%':
ADDC(*ptr);
break;
default:
if (*ptr == '\0')
goto done;
errx(EXIT_FAILURE, "unknown specifier '%c' in "
"msgfmt string", *ptr);
/* NOTREACHED */
}
}
done:
/* flush buffer */
buffer_write(NULL, 0, 1);
return 0;
}
static void
custom_summary(void)
{
dd_write_msg(msgfmt, 1);
}
static void
human_summary(void)
{
(void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1);
if (st.swab) {
(void)dd_write_msg("%w odd length swab %W\n", 1);
}
if (st.trunc) {
(void)dd_write_msg("%t truncated %T\n", 1);
}
if (st.sparse) {
(void)dd_write_msg("%p sparse output %P\n", 1);
}
(void)dd_write_msg("%b bytes (%B) transferred in %s secs "
"(%e bytes/sec - %E)\n", 1);
}
static void
quiet_summary(void)
{
/* stay quiet */
}
#endif /* NO_MSGFMT */

View File

@@ -1,185 +0,0 @@
/* $NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/time.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dd.h"
#include "extern.h"
/*
* Position input/output data streams before starting the copy. Device type
* dependent. Seekable devices use lseek, and the rest position by reading.
* Seeking past the end of file can cause null blocks to be written to the
* output.
*/
void
pos_in(void)
{
int bcnt, cnt, nr, warned;
/* If not a pipe or tape device, try to seek on it. */
if (!(in.flags & (ISPIPE|ISTAPE))) {
if (ddop_lseek(in, in.fd,
(off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
}
return;
/* NOTREACHED */
}
/*
* Read the data. If a pipe, read until satisfy the number of bytes
* being skipped. No differentiation for reading complete and partial
* blocks for other devices.
*/
for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) {
if (in.flags & ISPIPE) {
if (!(bcnt -= nr)) {
bcnt = in.dbsz;
--cnt;
}
} else
--cnt;
continue;
}
if (nr == 0) {
if (files_cnt > 1) {
--files_cnt;
continue;
}
errx(EXIT_FAILURE, "skip reached end of input");
/* NOTREACHED */
}
/*
* Input error -- either EOF with no more files, or I/O error.
* If noerror not set die. POSIX requires that the warning
* message be followed by an I/O display.
*/
if (ddflags & C_NOERROR) {
if (!warned) {
warn("%s", in.name);
warned = 1;
summary();
}
continue;
}
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
}
}
void
pos_out(void)
{
struct mtop t_op;
int n;
uint64_t cnt;
/*
* If not a tape, try seeking on the file. Seeking on a pipe is
* going to fail, but don't protect the user -- they shouldn't
* have specified the seek operand.
*/
if (!(out.flags & ISTAPE)) {
if (ddop_lseek(out, out.fd,
(off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
return;
}
/* If no read access, try using mtio. */
if (out.flags & NOREAD) {
t_op.mt_op = MTFSR;
t_op.mt_count = out.offset;
if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
return;
}
/* Read it. */
for (cnt = 0; cnt < out.offset; ++cnt) {
if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
continue;
if (n < 0)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
/*
* If reach EOF, fill with NUL characters; first, back up over
* the EOF mark. Note, cnt has not yet been incremented, so
* the EOF read does not count as a seek'd block.
*/
t_op.mt_op = MTBSR;
t_op.mt_count = 1;
if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
while (cnt++ < out.offset)
if ((uint64_t)(n = bwrite(&out,
out.db, out.dbsz)) != out.dbsz)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
break;
}
}

View File

@@ -1,11 +0,0 @@
# $NetBSD: Makefile,v 1.19 2011/08/28 08:20:58 christos Exp $
# @(#)Makefile 8.3 (Berkeley) 5/8/95
.include <bsd.own.mk>
PROG= df
LDADD+=-lutil
DPADD+=${LIBUTIL}
.include <bsd.prog.mk>

View File

@@ -1,206 +0,0 @@
.\" $NetBSD: df.1,v 1.44 2010/04/05 21:17:28 joerg Exp $
.\"
.\" 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. 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.
.\"
.\" @(#)df.1 8.2 (Berkeley) 1/13/92
.\"
.Dd March 4, 2008
.Dt DF 1
.Os
.Sh NAME
.Nm df
.Nd display free disk space
.Sh SYNOPSIS
.Nm
.Op Fl agklmn
.Op Fl G | Fl i | Fl P
.Op Fl t Ar type
.Op Ar file | Ar file_system ...
.Sh DESCRIPTION
.Nm
displays statistics about the amount of free disk space on the specified
.Ar file_system
or on the file system of which
.Ar file
is a part.
By default, all sizes are reported in 512-byte block counts.
If neither a file or a
.Ar file_system
operand is specified,
statistics for all mounted file systems are displayed
(subject to the
.Fl l
and
.Fl t
options below).
.Pp
Note that the printed count of available blocks takes
.Va minfree
into account, and thus will be negative when the number of free blocks
on the filesystem is less than
.Va minfree .
.Pp
The following options are available:
.Bl -tag -width Ds
.It Fl a
Show all mount points,
including those that were mounted with the
.Dv MNT_IGNORE
flag.
.It Fl G
Display all the fields of the structure(s) returned by
.Xr statvfs 2 .
This option cannot be used with the
.Fl i
or
.Fl P
options, and it is modelled after the Solaris
.Fl g
option.
This option will override the
.Fl g ,
.Fl h ,
.Fl k ,
and
.Fl m
options, as well as any setting of
.Ev BLOCKSIZE .
.It Fl g
The
.Fl g
option causes the numbers to be reported in gigabytes (1024*1024*1024
bytes).
.It Fl h
"Human-readable" output.
Use unit suffixes: Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte, Petabyte, Exabyte in order to reduce the number of
digits to four or less.
.It Fl i
Include statistics on the number of free inodes.
.It Fl k
By default, all sizes are reported in 512-byte block counts.
The
.Fl k
option causes the numbers to be reported in kilobytes (1024 bytes).
.It Fl l
Display statistics only about mounted file systems with the
.Dv MNT_LOCAL
flag set.
If a non-local file system is given as an argument, a
warning is issued and no information is given on that file system.
.It Fl m
The
.Fl m
option causes the numbers to be reported in megabytes (1024*1024 bytes).
.It Fl n
Print out the previously obtained statistics from the file systems.
This option should be used if it is possible that one or more
file systems are in a state such that they will not be able to provide
statistics without a long delay.
When this option is specified,
.Nm
will not request new statistics from the file systems, but will respond
with the possibly stale statistics that were previously obtained.
.It Fl P
Produce output in the following portable format:
.Pp
If both the
.Fl P
and
.Fl k
option are specified, the output will be preceded by the following header
line, formatted to match the data following it:
.Bd -literal
"Filesystem 1024-blocks Used Available Capacity Mounted on\en"
.Ed
.Pp
If the
.Fl P
option is specified without the
.Fl k
options, the output will be preceded by the following header line,
formatted to match the data following it:
.Bd -literal
"Filesystem \*[Lt]blksize\*[Gt]-blocks Used Available Capacity Mounted on\en"
.Ed
.Pp
The header line is followed by data formatted as follows:
.Bd -literal
"%s %d %d %d %d%% %s\en", \*[Lt]file system name\*[Gt], \*[Lt]total space\*[Gt],
\*[Lt]space used\*[Gt], \*[Lt]space free\*[Gt], \*[Lt]percentage used\*[Gt],
\*[Lt]file system root\*[Gt]
.Ed
.Pp
Note that the
.Fl i
option may not be specified with
.Fl P .
.It Fl t Ar type
Is used to indicate the actions should only be taken on
filesystems of the specified type.
More than one type may be specified in a comma-separated list.
The list of filesystem types can be prefixed with
.Dq no
to specify the filesystem types for which action should
.Em not
be taken.
If a file system is given on the command line that is not of
the specified type, a warning is issued and no information is given on
that file system.
.El
.Sh ENVIRONMENT
.Bl -tag -width BLOCKSIZE
.It Ev BLOCKSIZE
If the environment variable
.Ev BLOCKSIZE
is set, and the
.Fl g ,
.Fl h ,
.Fl k
and
.Fl m
options are not specified, the block counts will be displayed in units of that
size block.
.El
.Sh SEE ALSO
.Xr quota 1 ,
.Xr fstatvfs 2 ,
.Xr getvfsstat 2 ,
.Xr statvfs 2 ,
.Xr getbsize 3 ,
.Xr getmntinfo 3 ,
.Xr fs 5 ,
.Xr fstab 5 ,
.Xr mount 8 ,
.Xr quot 8 ,
.Xr tunefs 8
.Sh HISTORY
A
.Nm
utility appeared in
.At v6 .

View File

@@ -1,520 +0,0 @@
/* $NetBSD: df.c,v 1.90 2012/01/07 18:45:13 christos Exp $ */
/*
* Copyright (c) 1980, 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1980, 1990, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)df.c 8.7 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: df.c,v 1.90 2012/01/07 18:45:13 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <util.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
static char *getmntpt(const char *);
static void prtstat(struct statvfs *, int);
static int selected(const char *, size_t);
static void maketypelist(char *);
static size_t regetmntinfo(struct statvfs **, size_t);
__dead static void usage(void);
static void prthumanval(int64_t, const char *);
static void prthuman(struct statvfs *, int64_t, int64_t);
static int aflag, gflag, hflag, iflag, lflag, nflag, Pflag;
static long usize;
static char **typelist;
int
main(int argc, char *argv[])
{
struct stat stbuf;
struct statvfs *mntbuf;
long mntsize;
int ch, i, maxwidth, width;
char *mntpt;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "aGghiklmnPt:")) != -1)
switch (ch) {
case 'a':
aflag = 1;
break;
case 'g':
hflag = 0;
usize = 1024 * 1024 * 1024;
break;
case 'G':
gflag = 1;
break;
case 'h':
hflag = 1;
usize = 0;
break;
case 'i':
iflag = 1;
break;
case 'k':
hflag = 0;
usize = 1024;
break;
case 'l':
lflag = 1;
break;
case 'm':
hflag = 0;
usize = 1024 * 1024;
break;
case 'n':
nflag = 1;
break;
case 'P':
Pflag = 1;
break;
case 't':
if (typelist != NULL)
errx(EXIT_FAILURE,
"only one -t option may be specified.");
maketypelist(optarg);
break;
case '?':
default:
usage();
}
if (gflag && (Pflag || iflag))
errx(EXIT_FAILURE,
"only one of -G and -P or -i may be specified");
if (Pflag && iflag)
errx(EXIT_FAILURE,
"only one of -P and -i may be specified");
#if 0
/*
* The block size cannot be checked until after getbsize() is called.
*/
if (Pflag && (hflag || (usize != 1024 && usize != 512)))
errx(EXIT_FAILURE,
"non-standard block size incompatible with -P");
#endif
argc -= optind;
argv += optind;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
if (mntsize == 0)
err(EXIT_FAILURE,
"retrieving information on mounted file systems");
if (*argv == NULL) {
mntsize = regetmntinfo(&mntbuf, mntsize);
} else {
if ((mntbuf = malloc(argc * sizeof(*mntbuf))) == NULL)
err(EXIT_FAILURE, "can't allocate statvfs array");
mntsize = 0;
for (/*EMPTY*/; *argv != NULL; argv++) {
if (stat(*argv, &stbuf) < 0) {
if ((mntpt = getmntpt(*argv)) == 0) {
warn("%s", *argv);
continue;
}
} else if (S_ISBLK(stbuf.st_mode)) {
if ((mntpt = getmntpt(*argv)) == 0)
mntpt = *argv;
} else
mntpt = *argv;
/*
* Statfs does not take a `wait' flag, so we cannot
* implement nflag here.
*/
if (!statvfs(mntpt, &mntbuf[mntsize]))
if (lflag &&
(mntbuf[mntsize].f_flag & MNT_LOCAL) == 0)
warnx("Warning: %s is not a local %s",
*argv, "file system");
else if
(!selected(mntbuf[mntsize].f_fstypename,
sizeof(mntbuf[mntsize].f_fstypename)))
warnx("Warning: %s mounted as a %s %s",
*argv,
mntbuf[mntsize].f_fstypename,
"file system");
else
++mntsize;
else
warn("%s", *argv);
}
}
maxwidth = 0;
for (i = 0; i < mntsize; i++) {
width = (int)strlen(mntbuf[i].f_mntfromname);
if (width > maxwidth)
maxwidth = width;
}
for (i = 0; i < mntsize; i++)
prtstat(&mntbuf[i], maxwidth);
return 0;
}
static char *
getmntpt(const char *name)
{
size_t mntsize, i;
struct statvfs *mntbuf;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
if (mntsize == 0)
err(EXIT_FAILURE, "Can't get mount information");
for (i = 0; i < mntsize; i++) {
if (!strcmp(mntbuf[i].f_mntfromname, name))
return mntbuf[i].f_mntonname;
}
return 0;
}
static enum { IN_LIST, NOT_IN_LIST } which;
static int
selected(const char *type, size_t len)
{
char **av;
/* If no type specified, it's always selected. */
if (typelist == NULL)
return 1;
for (av = typelist; *av != NULL; ++av)
if (!strncmp(type, *av, len))
return which == IN_LIST ? 1 : 0;
return which == IN_LIST ? 0 : 1;
}
static void
maketypelist(char *fslist)
{
size_t i;
char *nextcp, **av;
if ((fslist == NULL) || (fslist[0] == '\0'))
errx(EXIT_FAILURE, "empty type list");
/*
* XXX
* Note: the syntax is "noxxx,yyy" for no xxx's and
* no yyy's, not the more intuitive "noyyy,noyyy".
*/
if (fslist[0] == 'n' && fslist[1] == 'o') {
fslist += 2;
which = NOT_IN_LIST;
} else
which = IN_LIST;
/* Count the number of types. */
for (i = 1, nextcp = fslist;
(nextcp = strchr(nextcp, ',')) != NULL; i++)
++nextcp;
/* Build an array of that many types. */
if ((av = typelist = malloc((i + 1) * sizeof(*av))) == NULL)
err(EXIT_FAILURE, "can't allocate type array");
av[0] = fslist;
for (i = 1, nextcp = fslist;
(nextcp = strchr(nextcp, ',')) != NULL; i++) {
*nextcp = '\0';
av[i] = ++nextcp;
}
/* Terminate the array. */
av[i] = NULL;
}
/*
* Make a pass over the filesystem info in ``mntbuf'' filtering out
* filesystem types not in ``fsmask'' and possibly re-stating to get
* current (not cached) info. Returns the new count of valid statvfs bufs.
*/
static size_t
regetmntinfo(struct statvfs **mntbufp, size_t mntsize)
{
size_t i, j;
struct statvfs *mntbuf;
if (!lflag && typelist == NULL && aflag)
return nflag ? mntsize : (size_t)getmntinfo(mntbufp, MNT_WAIT);
mntbuf = *mntbufp;
j = 0;
for (i = 0; i < mntsize; i++) {
if (!aflag && (mntbuf[i].f_flag & MNT_IGNORE) != 0)
continue;
if (lflag && (mntbuf[i].f_flag & MNT_LOCAL) == 0)
continue;
if (!selected(mntbuf[i].f_fstypename,
sizeof(mntbuf[i].f_fstypename)))
continue;
if (nflag)
mntbuf[j] = mntbuf[i];
else {
struct statvfs layerbuf = mntbuf[i];
(void)statvfs(mntbuf[i].f_mntonname, &mntbuf[j]);
/*
* If the FS name changed, then new data is for
* a different layer and we don't want it.
*/
if (memcmp(layerbuf.f_mntfromname,
mntbuf[j].f_mntfromname, MNAMELEN))
mntbuf[j] = layerbuf;
}
j++;
}
return j;
}
static void
prthumanval(int64_t bytes, const char *pad)
{
char buf[6];
(void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
bytes, "", HN_AUTOSCALE,
HN_B | HN_NOSPACE | HN_DECIMAL);
(void)printf("%s %6s", pad, buf);
}
static void
prthuman(struct statvfs *sfsp, int64_t used, int64_t bavail)
{
prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), " ");
prthumanval((int64_t)(used * sfsp->f_frsize), " ");
prthumanval((int64_t)(bavail * sfsp->f_frsize), " ");
}
/*
* Convert statvfs returned filesystem size into BLOCKSIZE units.
* Attempts to avoid overflow for large filesystems.
*/
#define fsbtoblk(num, fsbs, bs) \
(((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ? \
(int64_t)(num) / (int64_t)((bs) / (fsbs)) : \
(int64_t)(num) * (int64_t)((fsbs) / (bs)))
/*
* Print out status about a filesystem.
*/
static void
prtstat(struct statvfs *sfsp, int maxwidth)
{
static long blocksize;
static int headerlen, timesthrough;
static const char *header;
static const char full[] = "100";
static const char empty[] = " 0";
int64_t used, availblks, inodes;
int64_t bavail;
char pb[64];
if (gflag) {
/*
* From SunOS-5.6:
*
* /var (/dev/dsk/c0t0d0s3 ): 8192 block size 1024 frag size
* 984242 total blocks 860692 free blocks 859708 available 249984 total files
* 248691 free files 8388611 filesys id
* ufs fstype 0x00000004 flag 255 filename length
*
*/
(void)printf("%10s (%-12s): %7ld block size %12ld frag size\n",
sfsp->f_mntonname, sfsp->f_mntfromname,
sfsp->f_iosize, /* On UFS/FFS systems this is
* also called the "optimal
* transfer block size" but it
* is of course the file
* system's block size too.
*/
sfsp->f_bsize); /* not so surprisingly the
* "fundamental file system
* block size" is the frag
* size.
*/
(void)printf("%10" PRId64 " total blocks %10" PRId64
" free blocks %10" PRId64 " available\n",
(uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree,
(uint64_t)sfsp->f_bavail);
(void)printf("%10" PRId64 " total files %10" PRId64
" free files %12lx filesys id\n",
(uint64_t)sfsp->f_ffree, (uint64_t)sfsp->f_files,
sfsp->f_fsid);
(void)printf("%10s fstype %#15lx flag %17ld filename "
"length\n", sfsp->f_fstypename, sfsp->f_flag,
sfsp->f_namemax);
(void)printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64
" asyncwrites\n\n", (unsigned long)sfsp->f_owner,
sfsp->f_syncwrites, sfsp->f_asyncwrites);
/*
* a concession by the structured programming police to the
* indentation police....
*/
return;
}
if (maxwidth < 12)
maxwidth = 12;
if (++timesthrough == 1) {
switch (blocksize = usize) {
case 1024:
header = Pflag ? "1024-blocks" : "1K-blocks";
headerlen = (int)strlen(header);
break;
case 1024 * 1024:
header = "1M-blocks";
headerlen = (int)strlen(header);
break;
case 1024 * 1024 * 1024:
header = "1G-blocks";
headerlen = (int)strlen(header);
break;
default:
if (hflag) {
header = "Size";
headerlen = (int)strlen(header);
} else
header = getbsize(&headerlen, &blocksize);
break;
}
if (Pflag) {
/*
* either:
* "Filesystem 1024-blocks Used Available Capacity Mounted on\n"
* or:
* "Filesystem 512-blocks Used Available Capacity Mounted on\n"
*/
if (blocksize != 1024 && blocksize != 512)
errx(EXIT_FAILURE,
"non-standard block size incompatible with -P");
(void)printf("Filesystem %s Used Available Capacity "
"Mounted on\n", header);
} else {
(void)printf("%-*.*s %s Used Avail %%Cap",
maxwidth - (headerlen - 10),
maxwidth - (headerlen - 10),
"Filesystem", header);
if (iflag)
(void)printf(" iUsed iAvail %%iCap");
(void)printf(" Mounted on\n");
}
}
used = sfsp->f_blocks - sfsp->f_bfree;
bavail = sfsp->f_bfree - sfsp->f_bresvd;
availblks = bavail + used;
if (Pflag) {
assert(hflag == 0);
assert(blocksize > 0);
/*
* "%s %d %d %d %s %s\n", <file system name>, <total space>,
* <space used>, <space free>, <percentage used>,
* <file system root>
*/
(void)printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s%% %s\n",
sfsp->f_mntfromname,
fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
fsbtoblk(used, sfsp->f_frsize, blocksize),
fsbtoblk(bavail, sfsp->f_frsize, blocksize),
availblks == 0 ? full : strspct(pb, sizeof(pb), used,
availblks, 0), sfsp->f_mntonname);
/*
* another concession by the structured programming police to
* the indentation police....
*
* Note iflag cannot be set when Pflag is set.
*/
return;
}
(void)printf("%-*.*s ", maxwidth, maxwidth, sfsp->f_mntfromname);
if (hflag)
prthuman(sfsp, used, bavail);
else
(void)printf("%10" PRId64 " %10" PRId64 " %10" PRId64,
fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
fsbtoblk(used, sfsp->f_frsize, blocksize),
fsbtoblk(bavail, sfsp->f_frsize, blocksize));
(void)printf(" %3s%%",
availblks == 0 ? full :
strspct(pb, sizeof(pb), used, availblks, 0));
if (iflag) {
inodes = sfsp->f_files;
used = inodes - sfsp->f_ffree;
(void)printf(" %8jd %8jd %3s%%",
(intmax_t)used, (intmax_t)sfsp->f_ffree,
inodes == 0 ? (used == 0 ? empty : full) :
strspct(pb, sizeof(pb), used, inodes, 0));
}
(void)printf(" %s\n", sfsp->f_mntonname);
}
static void
usage(void)
{
(void)fprintf(stderr,
"Usage: %s [-aGgln] [-hkm|-ihkm|-Pk] [-t type] [file | "
"file_system ...]\n",
getprogname());
exit(1);
/* NOTREACHED */
}

View File

@@ -1,6 +0,0 @@
# $NetBSD: Makefile,v 1.6 1997/07/20 22:36:50 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= domainname
.include <bsd.prog.mk>

View File

@@ -1,65 +0,0 @@
.\" $NetBSD: domainname.1,v 1.15 2004/06/15 14:08:33 jmmv Exp $
.\"
.\" Copyright (c) 1983, 1988, 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. 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.
.\"
.\" @(#)hostname.1 8.1 (Berkeley) 5/31/93
.\"
.Dd May 31, 1993
.Dt DOMAINNAME 1
.Os
.Sh NAME
.Nm domainname
.Nd set or print YP domain of current host system
.Sh SYNOPSIS
.Nm
.Op Ar name-of-domain
.Sh DESCRIPTION
.Nm
prints the
.Tn YP
domain name of the current host.
The super-user can set the domain name by supplying an argument;
this is usually done in the network initialization script
.Pa /etc/rc.d/network ,
normally run at boot
time.
.Sh SEE ALSO
.Xr hostname 1 ,
.Xr getdomainname 3 ,
.Xr setdomainname 3
.Sh HISTORY
The
.Nm
utility is derived from the
.Nm hostname
utility, which appeared in
.Bx 4.2 .
The
.Nm
utility appeared in
.Nx 0.8 .

View File

@@ -1,95 +0,0 @@
/* $NetBSD: domainname.c,v 1.15 2011/08/29 14:51:18 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1988, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)hostname.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: domainname.c,v 1.15 2011/08/29 14:51:18 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__dead static void usage(void);
int
main(int argc, char *argv[])
{
int ch;
char domainname[MAXHOSTNAMELEN];
setprogname(argv[0]);
while ((ch = getopt(argc, argv, "")) != -1) {
switch (ch) {
case '?':
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (argc > 1)
usage();
if (*argv) {
if (setdomainname(*argv, strlen(*argv)))
err(1, "setdomainname");
} else {
if (getdomainname(domainname, sizeof(domainname)))
err(1, "getdomainname");
(void)printf("%s\n", domainname);
}
exit(EXIT_SUCCESS);
/* NOTREACHED */
}
static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [name-of-domain]\n", getprogname());
exit(EXIT_FAILURE);
}

View File

@@ -1,6 +0,0 @@
# $NetBSD: Makefile,v 1.8 1997/07/20 22:36:53 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= echo
.include <bsd.prog.mk>

View File

@@ -1,68 +0,0 @@
.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:12 agc Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" 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. 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.
.\"
.\" @(#)echo.1 8.1 (Berkeley) 7/22/93
.\"
.Dd July 22, 1993
.Dt ECHO 1
.Os
.Sh NAME
.Nm echo
.Nd write arguments to the standard output
.Sh SYNOPSIS
.Nm
.Op Fl n
.Op Ar string ...
.Sh DESCRIPTION
The
.Nm
utility writes any specified operands, separated by single blank (`` '')
characters and followed by a newline (``\en'') character, to the standard
output.
.Pp
The following option is available:
.Bl -tag -width flag
.It Fl n
Do not print the trailing newline character.
.El
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success, and \*[Gt]0 if an error occurs.
.Sh SEE ALSO
.Xr printf 1
.Sh STANDARDS
The
.Nm
utility is expected to be
.St -p1003.2
compatible.

View File

@@ -1,83 +0,0 @@
/* $NetBSD: echo.c,v 1.18 2008/09/18 05:42:08 dholland Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: echo.c,v 1.18 2008/09/18 05:42:08 dholland Exp $");
#endif
#endif /* not lint */
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int, char *[]);
/* ARGSUSED */
int
main(int argc, char *argv[])
{
int nflag;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
/* This utility may NOT do getopt(3) option parsing. */
if (*++argv && !strcmp(*argv, "-n")) {
++argv;
nflag = 1;
}
else
nflag = 0;
while (*argv) {
(void)printf("%s", *argv);
if (*++argv)
(void)putchar(' ');
}
if (nflag == 0)
(void)putchar('\n');
fflush(stdout);
if (ferror(stdout))
exit(1);
exit(0);
/* NOTREACHED */
}

View File

@@ -1,20 +0,0 @@
# $NetBSD: Makefile,v 1.36 2009/07/26 01:58:20 dholland Exp $
.include <bsd.own.mk>
PROG= ed
CPPFLAGS+=-DBACKWARDS
.if (${MKCRYPTO} != "no")
CPPFLAGS+=-DDES
.endif
SRCS= buf.c cbc.c glbl.c io.c main.c re.c sub.c undo.c
LDADD+= -lcrypt
DPADD+= ${LIBCRYPT}
#LINKS= ${BINDIR}/ed ${BINDIR}/red
#MLINKS= ed.1 red.1
.include <bsd.prog.mk>

View File

@@ -1,103 +0,0 @@
$NetBSD: POSIX,v 1.10 1999/11/18 19:16:34 kristerw Exp $
This version of ed(1) is not strictly POSIX compliant, as described in
the POSIX 1003.2 document. The following is a summary of the omissions,
extensions and possible deviations from POSIX 1003.2.
OMISSIONS
---------
1) Locale(3) is not supported yet.
2) For backwards compatibility, the POSIX rule that says a range of
addresses cannot be used where only a single address is expected has
been relaxed.
3) To support the BSD `s' command (see extension [1] below),
substitution patterns cannot be delimited by numbers or the characters
`r', `g' and `p'. In contrast, POSIX specifies any character expect
space or newline can used as a delimiter.
EXTENSIONS
----------
1) BSD commands have been implemented wherever they do not conflict with
the POSIX standard. The BSD-ism's included are:
i) `s' (i.e., s[n][rgp]*) to repeat a previous substitution,
ii) `W' for appending text to an existing file,
iii) `wq' for exiting after a write,
iv) `z' for scrolling through the buffer, and
v) BSD line addressing syntax (i.e., `^' and `%') is recognized.
2) If crypt(3) is available, files can be read and written using DES
encryption. The `x' command prompts the user to enter a key used for
encrypting/ decrypting subsequent reads and writes. If only a newline
is entered as the key, then encryption is disabled. Otherwise, a key
is read in the same manner as a password entry. The key remains in
effect until encryption is disabled. For more information on the
encryption algorithm, see the bdes(1) man page. Encryption/decryption
should be fully compatible with SunOS des(1).
3) The POSIX interactive global commands `G' and `V' are extended to
support multiple commands, including `a', `i' and `c'. The command
format is the same as for the global commands `g' and `v', i.e., one
command per line with each line, except for the last, ending in a
backslash (\).
4) An extension to the POSIX file commands `E', `e', `r', `W' and `w' is
that <file> arguments are processed for backslash escapes, i.e., any
character preceded by a backslash is interpreted literally. If the
first unescaped character of a <file> argument is a bang (!), then the
rest of the line is interpreted as a shell command, and no escape
processing is performed by ed.
5) For SunOS ed(1) compatibility, ed runs in restricted mode if invoked
as red. This limits editing of files in the local directory only and
prohibits shell commands.
DEVIATIONS
----------
1) Though ed is not a stream editor, it can be used to edit binary files.
To assist in binary editing, when a file containing at least one ASCII
NUL character is written, a newline is not appended if it did not
already contain one upon reading. In particular, reading /dev/null
prior to writing prevents appending a newline to a binary file.
For example, to create a file with ed containing a single NUL character:
$ ed file
a
^@
.
r /dev/null
wq
Similarly, to remove a newline from the end of binary `file':
$ ed file
r /dev/null
wq
2) Since the behavior of `u' (undo) within a `g' (global) command list is
not specified by POSIX, it follows the behavior of the SunOS ed:
undo forces a global command list to be executed only once, rather than
for each line matching a global pattern. In addtion, each instance of
`u' within a global command undoes all previous commands (including
undo's) in the command list. This seems the best way, since the
alternatives are either too complicated to implement or too confusing
to use.
The global/undo combination is useful for masking errors that
would otherwise cause a script to fail. For instance, an ed script
to remove any occurrences of either `censor1' or `censor2' might be
written as:
ed - file <<EOF
1g/.*/u\
,s/censor1//g\
,s/censor2//g
...
3) The `m' (move) command within a `g' command list also follows the SunOS
ed implementation: any moved lines are removed from the global command's
`active' list.
4) If ed is invoked with a name argument prefixed by a bang (!), then the
remainder of the argument is interpreted as a shell command. To invoke
ed on a file whose name starts with bang, prefix the name with a
backslash.

View File

@@ -1,24 +0,0 @@
$NetBSD: README,v 1.9 1995/03/21 09:04:33 cgd Exp $
ed is an 8-bit-clean, POSIX-compliant line editor. It should work with
any regular expression package that conforms to the POSIX interface
standard, such as GNU regex(3).
If reliable signals are supported (e.g., POSIX sigaction(2)), it should
compile with little trouble. Otherwise, the macros SPL1() and SPL0()
should be redefined to disable interrupts.
The following compiler directives are recognized:
DES - to add encryption support (requires crypt(3))
NO_REALLOC_NULL - if realloc(3) does not accept a NULL pointer
BACKWARDS - for backwards compatibility
NEED_INSQUE - if insque(3) is missing
The file `POSIX' describes extensions to and deviations from the POSIX
standard.
The ./test directory contains regression tests for ed. The README
file in that directory explains how to run these.
For a description of the ed algorithm, see Kernighan and Plauger's book
"Software Tools in Pascal," Addison-Wesley, 1981.

View File

@@ -1,319 +0,0 @@
/* $NetBSD: buf.c,v 1.26 2006/03/17 14:37:14 rumble Exp $ */
/* buf.c: This file contains the scratch-file buffer routines for the
ed line editor. */
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp";
#else
__RCSID("$NetBSD: buf.c,v 1.26 2006/03/17 14:37:14 rumble Exp $");
#endif
#endif /* not lint */
#include <sys/file.h>
#include <sys/stat.h>
#include <paths.h>
#include <stdio.h>
#include <err.h>
#include "ed.h"
FILE *sfp; /* scratch file pointer */
off_t sfseek; /* scratch file position */
int seek_write; /* seek before writing */
line_t buffer_head; /* incore buffer */
/* get_sbuf_line: get a line of text from the scratch file; return pointer
to the text */
char *
get_sbuf_line(line_t *lp)
{
static char *sfbuf = NULL; /* buffer */
static int sfbufsz = 0; /* buffer size */
int len, ct;
if (lp == &buffer_head)
return NULL;
seek_write = 1; /* force seek on write */
/* out of position */
if (sfseek != lp->seek) {
sfseek = lp->seek;
if (fseek(sfp, sfseek, SEEK_SET) < 0) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot seek temp file");
return NULL;
}
}
len = lp->len;
REALLOC(sfbuf, sfbufsz, len + 1, NULL);
if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot read temp file");
return NULL;
}
sfseek += len; /* update file position */
sfbuf[len] = '\0';
return sfbuf;
}
/* put_sbuf_line: write a line of text to the scratch file and add a line node
to the editor buffer; return a pointer to the end of the text */
char *
put_sbuf_line(char *cs)
{
line_t *lp;
int len, ct;
char *s;
if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "out of memory");
return NULL;
}
/* assert: cs is '\n' terminated */
for (s = cs; *s != '\n'; s++)
;
if (s - cs >= LINECHARS) {
sprintf(errmsg, "line too long");
free(lp);
return NULL;
}
len = s - cs;
/* out of position */
if (seek_write) {
if (fseek(sfp, 0L, SEEK_END) < 0) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot seek temp file");
free(lp);
return NULL;
}
sfseek = ftell(sfp);
seek_write = 0;
}
/* assert: SPL1() */
if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
sfseek = -1;
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot write temp file");
free(lp);
return NULL;
}
lp->len = len;
lp->seek = sfseek;
add_line_node(lp);
sfseek += len; /* update file position */
return ++s;
}
/* add_line_node: add a line node in the editor buffer after the current line */
void
add_line_node(line_t *lp)
{
line_t *cp;
cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */
INSQUE(lp, cp);
addr_last++;
current_addr++;
}
/* get_line_node_addr: return line number of pointer */
long
get_line_node_addr(line_t *lp)
{
line_t *cp = &buffer_head;
long n = 0;
while (cp != lp && (cp = cp->q_forw) != &buffer_head)
n++;
if (n && cp == &buffer_head) {
sprintf(errmsg, "invalid address");
return ERR;
}
return n;
}
/* get_addressed_line_node: return pointer to a line node in the editor buffer */
line_t *
get_addressed_line_node(long n)
{
static line_t *lp = &buffer_head;
static long on = 0;
SPL1();
if (n > on) {
if (n <= (on + addr_last) >> 1) {
for (; on < n; on++)
lp = lp->q_forw;
} else {
lp = buffer_head.q_back;
for (on = addr_last; on > n; on--)
lp = lp->q_back;
}
} else {
if (n >= on >> 1) {
for (; on > n; on--)
lp = lp->q_back;
} else {
lp = &buffer_head;
for (on = 0; on < n; on++)
lp = lp->q_forw;
}
}
SPL0();
return lp;
}
char *sfn = NULL; /* scratch file name */
/* open_sbuf: open scratch file */
int
open_sbuf(void)
{
int u, fd;
const char *tmp;
size_t s;
isbinary = newline_added = 0;
fd = -1;
u = umask(077);
if ((tmp = getenv("TMPDIR")) == NULL)
tmp = _PATH_TMP;
if ((s = strlen(tmp)) == 0 || tmp[s - 1] == '/')
(void)asprintf(&sfn, "%sed.XXXXXX", tmp);
else
(void)asprintf(&sfn, "%s/ed.XXXXXX", tmp);
if (sfn == NULL) {
warn(NULL);
sprintf(errmsg, "could not allocate memory");
umask(u);
return ERR;
}
if ((fd = mkstemp(sfn)) == -1 || (sfp = fdopen(fd, "w+")) == NULL) {
if (fd != -1)
close(fd);
warn("%s", sfn);
sprintf(errmsg, "cannot open temp file");
umask(u);
return ERR;
}
umask(u);
return 0;
}
/* close_sbuf: close scratch file */
int
close_sbuf(void)
{
if (sfp) {
if (fclose(sfp) < 0) {
fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
sprintf(errmsg, "cannot close temp file");
return ERR;
}
sfp = NULL;
if (sfn) {
unlink(sfn);
free(sfn);
sfn = NULL;
}
}
sfseek = seek_write = 0;
return 0;
}
/* quit: remove_lines scratch file and exit */
void
quit(int n)
{
if (sfp) {
fclose(sfp);
if (sfn) {
unlink(sfn);
free(sfn);
sfn = NULL;
}
}
exit(n);
/* NOTREACHED */
}
unsigned char ctab[256]; /* character translation table */
/* init_buffers: open scratch buffer; initialize line queue */
void
init_buffers(void)
{
int i = 0;
/* Read stdin one character at a time to avoid i/o contention
with shell escapes invoked by nonterminal input, e.g.,
ed - <<EOF
!cat
hello, world
EOF */
setbuffer(stdin, stdinbuf, 1);
if (open_sbuf() < 0)
quit(2);
REQUE(&buffer_head, &buffer_head);
for (i = 0; i < 256; i++)
ctab[i] = i;
}
/* translit_text: translate characters in a string */
char *
translit_text(char *s, int len, int from, int to)
{
static int i = 0;
unsigned char *us;
ctab[i] = i; /* restore table to initial state */
ctab[i = from] = to;
for (us = (unsigned char *) s; len-- > 0; us++)
*us = ctab[*us];
return s;
}

View File

@@ -1,460 +0,0 @@
/* $NetBSD: cbc.c,v 1.22 2010/06/09 19:20:18 riz Exp $ */
/* cbc.c: This file contains the encryption routines for the ed line editor */
/*-
* Copyright (c) 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. 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: @(#)bdes.c 5.5 (Berkeley) 6/27/91
*/
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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: @(#)bdes.c 5.5 (Berkeley) 6/27/91
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)cbc.c,v 1.2 1994/02/01 00:34:36 alm Exp";
#else
__RCSID("$NetBSD: cbc.c,v 1.22 2010/06/09 19:20:18 riz Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#ifdef DES
#include <time.h>
#endif
#include "ed.h"
/*
* Define a divisor for rand() that yields a uniform distribution in the
* range 0-255.
*/
#define RAND_DIV (((unsigned) RAND_MAX + 1) >> 8)
/*
* BSD and System V systems offer special library calls that do
* block move_liness and fills, so if possible we take advantage of them
*/
#define MEMCPY(dest,src,len) memcpy((dest),(src),(len))
#define MEMZERO(dest,len) memset((dest), 0, (len))
/* Hide the calls to the primitive encryption routines. */
#define DES_KEY(buf) \
if (des_setkey(buf)) \
des_error("des_setkey");
#define DES_XFORM(buf) \
if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
des_error("des_cipher");
/*
* read/write - no error checking
*/
#define READ(buf, n, fp) fread(buf, sizeof(char), n, fp)
#define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp)
/*
* some things to make references easier
*/
typedef char Desbuf[8];
#define CHAR(x,i) (x[i])
#define UCHAR(x,i) (x[i])
#define BUFFER(x) (x)
#define UBUFFER(x) (x)
#ifdef DES
/*
* global variables and related macros
*/
static Desbuf ivec; /* initialization vector */
static Desbuf pvec; /* padding vector */
static char bits[] = { /* used to extract bits from a char */
'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
};
static int pflag; /* 1 to preserve parity bits */
static char des_buf[8]; /* shared buffer for get_des_char/put_des_char */
static int des_ct = 0; /* count for get_des_char/put_des_char */
static int des_n = 0; /* index for put_des_char/get_des_char */
#endif
#ifdef DES
static void des_error(const char *);
static int hex_to_binary(int, int);
static void expand_des_key(char *, char *);
static void set_des_key(char *);
static int cbc_decode(char *, FILE *);
static int cbc_encode(char *, int, FILE *);
#endif
/* init_des_cipher: initialize DES */
void
init_des_cipher(void)
{
#ifdef DES
int i;
des_ct = des_n = 0;
/* initialize the initialization vector */
MEMZERO(ivec, 8);
/* intialize the padding vector */
srand((unsigned) time((time_t *) 0));
for (i = 0; i < 8; i++)
CHAR(pvec, i) = (char) (rand()/RAND_DIV);
#endif
}
/* get_des_char: return next char in an encrypted file */
int
get_des_char(FILE *fp)
{
#ifdef DES
if (des_n >= des_ct) {
des_n = 0;
des_ct = cbc_decode(des_buf, fp);
}
return (des_ct > 0) ? (unsigned char) des_buf[des_n++] : EOF;
#else
return EOF;
#endif
}
/* put_des_char: write a char to an encrypted file; return char written */
int
put_des_char(int c, FILE *fp)
{
#ifdef DES
if (des_n == sizeof des_buf) {
des_ct = cbc_encode(des_buf, des_n, fp);
des_n = 0;
}
return (des_ct >= 0) ? (unsigned char) (des_buf[des_n++] = c) : EOF;
#else
return EOF;
#endif
}
/* flush_des_file: flush an encrypted file's output; return status */
int
flush_des_file(FILE *fp)
{
#ifdef DES
if (des_n == sizeof des_buf) {
des_ct = cbc_encode(des_buf, des_n, fp);
des_n = 0;
}
return (des_ct >= 0 && cbc_encode(des_buf, des_n, fp) >= 0) ? 0 : EOF;
#else
return EOF;
#endif
}
#ifdef DES
/*
* get keyword from tty or stdin
*/
int
get_keyword(void)
{
char *p; /* used to obtain the key */
Desbuf msgbuf; /* I/O buffer */
/*
* get the key
*/
if (*(p = getpass("Enter key: "))) {
/*
* copy it, nul-padded, into the key area
*/
expand_des_key(BUFFER(msgbuf), p);
MEMZERO(p, _PASSWORD_LEN);
set_des_key(msgbuf);
MEMZERO(msgbuf, sizeof msgbuf);
return 1;
}
return 0;
}
/*
* print a warning message and, possibly, terminate
*/
static void
des_error(const char *s /* the message */)
{
(void)sprintf(errmsg, "%s", s ? s : strerror(errno));
}
/*
* map a hex character to an integer
*/
static int
hex_to_binary(int c /* char to be converted */,
int radix /* base (2 to 16) */)
{
switch(c) {
case '0': return(0x0);
case '1': return(0x1);
case '2': return(radix > 2 ? 0x2 : -1);
case '3': return(radix > 3 ? 0x3 : -1);
case '4': return(radix > 4 ? 0x4 : -1);
case '5': return(radix > 5 ? 0x5 : -1);
case '6': return(radix > 6 ? 0x6 : -1);
case '7': return(radix > 7 ? 0x7 : -1);
case '8': return(radix > 8 ? 0x8 : -1);
case '9': return(radix > 9 ? 0x9 : -1);
case 'A': case 'a': return(radix > 10 ? 0xa : -1);
case 'B': case 'b': return(radix > 11 ? 0xb : -1);
case 'C': case 'c': return(radix > 12 ? 0xc : -1);
case 'D': case 'd': return(radix > 13 ? 0xd : -1);
case 'E': case 'e': return(radix > 14 ? 0xe : -1);
case 'F': case 'f': return(radix > 15 ? 0xf : -1);
}
/*
* invalid character
*/
return(-1);
}
/*
* convert the key to a bit pattern
*/
static void
expand_des_key(char *obuf /* bit pattern */, char *inbuf /* the key itself */)
{
int i, j; /* counter in a for loop */
int nbuf[64]; /* used for hex/key translation */
/*
* leading '0x' or '0X' == hex key
*/
if (inbuf[0] == '0' && (inbuf[1] == 'x' || inbuf[1] == 'X')) {
inbuf = &inbuf[2];
/*
* now translate it, bombing on any illegal hex digit
*/
for (i = 0; inbuf[i] && i < 16; i++)
if ((nbuf[i] = hex_to_binary((int) inbuf[i], 16)) == -1)
des_error("bad hex digit in key");
while (i < 16)
nbuf[i++] = 0;
for (i = 0; i < 8; i++)
obuf[i] =
((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
/* preserve parity bits */
pflag = 1;
return;
}
/*
* leading '0b' or '0B' == binary key
*/
if (inbuf[0] == '0' && (inbuf[1] == 'b' || inbuf[1] == 'B')) {
inbuf = &inbuf[2];
/*
* now translate it, bombing on any illegal binary digit
*/
for (i = 0; inbuf[i] && i < 16; i++)
if ((nbuf[i] = hex_to_binary((int) inbuf[i], 2)) == -1)
des_error("bad binary digit in key");
while (i < 64)
nbuf[i++] = 0;
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
/* preserve parity bits */
pflag = 1;
return;
}
/*
* no special leader -- ASCII
*/
(void)strncpy(obuf, inbuf, 8);
}
/*****************
* DES FUNCTIONS *
*****************/
/*
* This sets the DES key and (if you're using the deszip version)
* the direction of the transformation. This uses the Sun
* to map the 64-bit key onto the 56 bits that the key schedule
* generation routines use: the old way, which just uses the user-
* supplied 64 bits as is, and the new way, which resets the parity
* bit to be the same as the low-order bit in each character. The
* new way generates a greater variety of key schedules, since many
* systems set the parity (high) bit of each character to 0, and the
* DES ignores the low order bit of each character.
*/
static void
set_des_key(Desbuf buf /* key block */)
{
int i, j; /* counter in a for loop */
int par; /* parity counter */
/*
* if the parity is not preserved, flip it
*/
if (!pflag) {
for (i = 0; i < 8; i++) {
par = 0;
for (j = 1; j < 8; j++)
if ((bits[j]&UCHAR(buf, i)) != 0)
par++;
if ((par&01) == 01)
UCHAR(buf, i) = UCHAR(buf, i)&0177;
else
UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
}
}
DES_KEY(UBUFFER(buf));
}
/*
* This encrypts using the Cipher Block Chaining mode of DES
*/
static int
cbc_encode(char *msgbuf, int n, FILE *fp)
{
int inverse = 0; /* 0 to encrypt, 1 to decrypt */
/*
* do the transformation
*/
if (n == 8) {
for (n = 0; n < 8; n++)
CHAR(msgbuf, n) ^= CHAR(ivec, n);
DES_XFORM(UBUFFER(msgbuf));
MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
return WRITE(BUFFER(msgbuf), 8, fp);
}
/*
* at EOF or last block -- in either case, the last byte contains
* the character representation of the number of bytes in it
*/
/*
MEMZERO(msgbuf + n, 8 - n);
*/
/*
* Pad the last block randomly
*/
(void)MEMCPY(BUFFER(msgbuf + n), BUFFER(pvec), 8 - n);
CHAR(msgbuf, 7) = n;
for (n = 0; n < 8; n++)
CHAR(msgbuf, n) ^= CHAR(ivec, n);
DES_XFORM(UBUFFER(msgbuf));
return WRITE(BUFFER(msgbuf), 8, fp);
}
/*
* This decrypts using the Cipher Block Chaining mode of DES
*/
static int
cbc_decode(char *msgbuf /* I/O buffer */,
FILE *fp /* input file descriptor */)
{
Desbuf inbuf; /* temp buffer for initialization vector */
int n; /* number of bytes actually read */
int c; /* used to test for EOF */
int inverse = 1; /* 0 to encrypt, 1 to decrypt */
if ((n = READ(BUFFER(msgbuf), 8, fp)) == 8) {
/*
* do the transformation
*/
MEMCPY(BUFFER(inbuf), BUFFER(msgbuf), 8);
DES_XFORM(UBUFFER(msgbuf));
for (c = 0; c < 8; c++)
UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
MEMCPY(BUFFER(ivec), BUFFER(inbuf), 8);
/*
* if the last one, handle it specially
*/
if ((c = fgetc(fp)) == EOF) {
n = CHAR(msgbuf, 7);
if (n < 0 || n > 7) {
des_error("decryption failed (block corrupted)");
return EOF;
}
} else
(void)ungetc(c, fp);
return n;
}
if (n > 0)
des_error("decryption failed (incomplete block)");
else if (n < 0)
des_error("cannot read file");
return EOF;
}
#endif /* DES */

View File

@@ -1,972 +0,0 @@
.\" $NetBSD: ed.1,v 1.30 2010/05/14 02:09:58 joerg Exp $
.\" $OpenBSD: ed.1,v 1.42 2003/07/27 13:25:43 jmc Exp $
.\"
.\" Copyright (c) 1993 Andrew Moore, Talke Studio.
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
.\"
.Dd January 23, 2002
.Dt ED 1
.Os
.Sh NAME
.Nm ed
.Nd text editor
.Sh SYNOPSIS
.Nm
.Op Fl
.Op Fl Esx
.Op Fl p Ar string
.Op Ar file
.Sh DESCRIPTION
.Nm
is a line-oriented text editor.
It is used to create, display, modify, and otherwise manipulate text files.
If invoked with a
.Ar file
argument, then a copy of
.Ar file
is read into the editor's buffer.
Changes are made to this copy and not directly to
.Ar file
itself.
Upon quitting
.Nm ,
any changes not explicitly saved with a
.Ic w
command are lost.
.Pp
Editing is done in two distinct modes:
.Em command
and
.Em input .
When first invoked,
.Nm
is in command mode.
In this mode, commands are read from the standard input and
executed to manipulate the contents of the editor buffer.
.Pp
A typical command might look like:
.Bd -literal -offset indent
,s/old/new/g
.Ed
.Pp
which replaces all occurrences of the string
.Pa old
with
.Pa new .
.Pp
When an input command, such as
.Ic a
(append),
.Ic i
(insert),
or
.Ic c
(change) is given,
.Nm
enters input mode.
This is the primary means of adding text to a file.
In this mode, no commands are available;
instead, the standard input is written directly to the editor buffer.
Lines consist of text up to and including a newline character.
Input mode is terminated by entering a single period
.Pq Ql \&.
on a line.
.Pp
All
.Nm
commands operate on whole lines or ranges of lines; e.g.,
the
.Ic d
command deletes lines; the
.Ic m
command moves lines, and so on.
It is possible to modify only a portion of a line by means of replacement,
as in the example above.
However, even here, the
.Ic s
command is applied to whole lines at a time.
.Pp
In general,
.Nm
commands consist of zero or more line addresses, followed by a single
character command and possibly additional parameters; i.e.,
commands have the structure:
.Bd -literal -offset indent
[address [,address]]command[parameters]
.Ed
.Pp
The address(es) indicate the line or range of lines to be affected by the
command.
If fewer addresses are given than the command accepts, then
default addresses are supplied.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl
Same as the
.Fl s
option (deprecated).
.It Fl E
Enables the use of extended regular expressions instead of the basic
regular expressions that are normally used.
.It Fl p Ar string
Specifies a command prompt.
This may be toggled on and off with the
.Ic P
command.
.It Fl s
Suppress diagnostics.
This should be used if
.Nm
standard input is from a script.
.It Fl x
Prompt for an encryption key to be used in subsequent reads and writes
(see the
.Ic x
command).
.It Ar file
Specifies the name of a file to read.
If
.Ar file
is prefixed with a
bang
.Pq Ql \&! ,
then it is interpreted as a shell command.
In this case, what is read is the standard output of
.Ar file
executed via
.Xr sh 1 .
To read a file whose name begins with a bang, prefix the
name with a backslash
.Pq Ql \e .
The default filename is set to
.Ar file
only if it is not prefixed with a bang.
.El
.Ss LINE ADDRESSING
An address represents the number of a line in the buffer.
.Nm
maintains a
.Em current address
which is typically supplied to commands as the default address
when none is specified.
When a file is first read, the current address is set to the last line
of the file.
In general, the current address is set to the last line affected by a command.
.Pp
A line address is
constructed from one of the bases in the list below, optionally followed
by a numeric offset.
The offset may include any combination of digits, operators (i.e.,
.Sq + ,
.Sq - ,
and
.Sq ^ ) ,
and whitespace.
Addresses are read from left to right, and their values are computed
relative to the current address.
.Pp
One exception to the rule that addresses represent line numbers is the
address
.Em 0
(zero).
This means
.Dq before the first line ,
and is legal wherever it makes sense.
.Pp
An address range is two addresses separated either by a comma or semi-colon.
The value of the first address in a range cannot exceed the
value of the second.
If only one address is given in a range,
then the second address is set to the given address.
If an
.Em n Ns No -tuple
of addresses is given where
.Em n \*[Gt] 2 ,
then the corresponding range is determined by the last two addresses in the
.Em n Ns No -tuple.
If only one address is expected, then the last address is used.
.Pp
Each address in a comma-delimited range is interpreted relative to the
current address.
In a semi-colon-delimited range, the first address is
used to set the current address, and the second address is interpreted
relative to the first.
.Pp
The following address symbols are recognized:
.Bl -tag -width Ds
.It Em \&.
The current line (address) in the buffer.
.It Em $
The last line in the buffer.
.It Em n
The
.Em n Ns No th
line in the buffer where
.Em n
is a number in the range
.Em [0,$] .
.It Em - No or Em ^
The previous line.
This is equivalent to
.Em -1
and may be repeated with cumulative effect.
.It Em -n No or Em ^n
The
.Em n Ns No th
previous line, where
.Em n
is a non-negative number.
.It Em +
The next line.
This is equivalent to
.Em +1
and may be repeated with cumulative effect.
.It Em +n
The
.Em n Ns No th
next line, where
.Em n
is a non-negative number.
.It Em whitespace Em n
.Em whitespace
followed by a number
.Em n
is interpreted as
.Sq Em +n .
.It Em \&, No or Em %
The first through last lines in the buffer.
This is equivalent to the address range
.Em 1,$ .
.It Em \&;
The current through last lines in the buffer.
This is equivalent to the address range
.Em .,$ .
.It Em / Ns Ar re Ns Em /
The next line containing the regular expression
.Ar re .
The search wraps to the beginning of the buffer and continues down to the
current line, if necessary.
.Em //
repeats the last search.
.It Em \&? Ns Ar re Ns Em \&?
The previous line containing the regular expression
.Ar re .
The search wraps to the end of the buffer and continues up to the
current line, if necessary.
.Em ??
repeats the last search.
.It Em \&\' Ns Ar lc
The line previously marked by a
.Ic k
(mark) command, where
.Ar lc
is a lower case letter.
.El
.Ss REGULAR EXPRESSIONS
Regular expressions are patterns used in selecting text.
For example, the
.Nm
command
.Bd -literal -offset indent
g/string/
.Ed
.Pp
prints all lines containing
.Em string .
Regular expressions are also used by the
.Ic s
command for selecting old text to be replaced with new.
.Pp
In addition to specifying string literals, regular expressions can
represent classes of strings.
Strings thus represented are said to be matched by the
corresponding regular expression.
If it is possible for a regular expression to match several strings in
a line, then the leftmost longest match is the one selected.
.Pp
The following symbols are used in constructing regular expressions:
.Bl -tag -width Dsasdfsd
.It Em c
Any character
.Em c
not listed below, including
.Sq { ,
.Sq } ,
.Sq \&( ,
.Sq \&) ,
.Sq \*[Lt] ,
and
.Sq \*[Gt]
matches itself.
.It Em \ec
Any backslash-escaped character
.Em c ,
except for
.Sq { ,
.Sq } ,
.Sq \&( ,
.Sq \&) ,
.Sq \*[Lt] ,
and
.Sq \*[Gt]
matches itself.
.It Em \&.
Matches any single character.
.It Em [char-class]
Matches any single character in the character class
.Em char-class .
See
.Sx CHARACTER CLASSES
below for further information.
.It Em [^char-class]
Matches any single character, other than newline, not in the
character class
.Em char-class .
.It Em ^
If
.Em ^
is the first character of a regular expression, then it
anchors the regular expression to the beginning of a line.
Otherwise, it matches itself.
.It Em $
If
.Em $
is the last character of a regular expression,
it anchors the regular expression to the end of a line.
Otherwise, it matches itself.
.It Em \e\*[Lt]
Anchors the single character regular expression or subexpression
immediately following it to the beginning of a word.
(This may not be available.)
.It Em \e\*[Gt]
Anchors the single character regular expression or subexpression
immediately following it to the end of a word.
(This may not be available.)
.It Em \e( Ns Ar re Ns Em \e)
Defines a subexpression
.Ar re .
Subexpressions may be nested.
A subsequent backreference of the form
.Em \en ,
where
.Em n
is a number in the range [1,9], expands to the text matched by the
.Em n Ns No th
subexpression.
For example, the regular expression
.Em \e(.*\e)\e1
matches any string consisting of identical adjacent substrings.
Subexpressions are ordered relative to their left delimiter.
.It Em *
Matches the single character regular expression or subexpression
immediately preceding it zero or more times.
If
.Em *
is the first character of a regular expression or subexpression,
then it matches itself.
The
.Em *
operator sometimes yields unexpected results.
For example, the regular expression
.Em b*
matches the beginning of the string
.Em abbb
(as opposed to the substring
.Em bbb ) ,
since a null match is the only leftmost match.
.Sm off
.It Em \e{ No n,m Em \e}\ \e{ No n, Em \e}\ \& Em \e{ No n Em \e}
.Sm on
Matches the single character regular expression or subexpression
immediately preceding it at least
.Em n
and at most
.Em m
times.
If
.Em m
is omitted, then it matches at least
.Em n
times.
If the comma is also omitted, then it matches exactly
.Em n
times.
.El
.Pp
Additional regular expression operators may be defined depending on the
particular
.Xr regex 3
implementation.
.Ss CHARACTER CLASSES
A character class specifies a set of characters. It is written within
square brackets
.Pq []
and in its most basic form contains just the characters in the set.
.Pp
To include a
.Sq \&]
in a character class, it must be the first character.
A range of characters may be specified by separating the end characters
of the range with a
.Sq \&- ,
e.g.,
.Sq a-z
specifies the lower case characters.
.Pp
The following literals can also be used within character classes as
shorthand for particular sets of characters:
.Bl -tag -offset indent -compact -width [:blahblah:]
.It [:alnum:]
Alphanumeric characters.
.It [:cntrl:]
Control characters.
.It [:lower:]
Lowercase alphabetic characters.
.It [:space:]
Whitespace (space, tab, newline, form feed, etc.)
.It [:alpha:]
Alphabetic characters.
.It [:digit:]
Numeric characters (digits).
.It [:print:]
Printable characters.
.It [:upper:]
Uppercase alphabetic characters.
.It [:blank:]
Blank characters (space and tab).
.It [:graph:]
Graphical characters (printing nonblank characters).
.It [:punct:]
Punctuation characters.
.It [:xdigit:]
Hexadecimal digits.
.El
If
.Sq \&-
appears as the first or last character of a character class, then
it matches itself.
All other characters in a character class match themselves.
.Pp
Patterns in
a character class
of the form
.Em [.col-elm.]
or
.Em [=col-elm=]
where
.Em col-elm
is a
.Em collating element
are interpreted according to
.Xr locale 5
(not currently supported).
See
.Xr regex 3
for an explanation of these constructs.
.Ss COMMANDS
All
.Nm
commands are single characters, though some require additional parameters.
If a command's parameters extend over several lines, then
each line except for the last must be terminated with a backslash
.Pq Ql \e .
.Pp
In general, at most one command is allowed per line.
However, most commands accept a print suffix, which is any of
.Ic p
(print),
.Ic l
(list),
or
.Ic n
(enumerate), to print the last line affected by the command.
.Pp
An interrupt (typically ^C) has the effect of aborting the current command
and returning the editor to command mode.
.Pp
.Nm
recognizes the following commands.
The commands are shown together with
the default address or address range supplied if none is
specified (in parentheses), and other possible arguments on the right.
.Bl -tag -width Dxxs
.It (.) Ns Ic a
Appends text to the buffer after the addressed line.
Text is entered in input mode.
The current address is set to last line entered.
.It (.,.) Ns Ic c
Changes lines in the buffer.
The addressed lines are deleted from the buffer,
and text is appended in their place.
Text is entered in input mode.
The current address is set to last line entered.
.It (.,.) Ns Ic d
Deletes the addressed lines from the buffer.
If there is a line after the deleted range, then the current address is set
to this line.
Otherwise the current address is set to the line before the deleted range.
.It Ic e Ar file
Edits
.Ar file ,
and sets the default filename.
If
.Ar file
is not specified, then the default filename is used.
Any lines in the buffer are deleted before the new file is read.
The current address is set to the last line read.
.It Ic e Ar !command
Edits the standard output of
.Ar command ,
(see
.Ic \&! Ar command
below).
The default filename is unchanged.
Any lines in the buffer are deleted before the output of
.Em command
is read.
The current address is set to the last line read.
.It Ic E Ar file
Edits
.Ar file
unconditionally.
This is similar to the
.Ic e
command, except that unwritten changes are discarded without warning.
The current address is set to the last line read.
.It Ic f Ar file
Sets the default filename to
.Ar file .
If
.Ar file
is not specified, then the default unescaped filename is printed.
.It (1,$) Ns Ic g Ns Ar /re/command-list
Applies
.Ar command-list
to each of the addressed lines matching a regular expression
.Ar re .
The current address is set to the line currently matched before
.Ar command-list
is executed.
At the end of the
.Ic g
command, the current address is set to the last line affected by
.Ar command-list .
.Pp
Each command in
.Ar command-list
must be on a separate line,
and every line except for the last must be terminated by a backslash
.Pq Sq \e .
Any commands are allowed, except for
.Ic g ,
.Ic G ,
.Ic v ,
and
.Ic V .
A newline alone in
.Ar command-list
is equivalent to a
.Ic p
command.
.It (1,$) Ns Ic G Ns Ar /re/
Interactively edits the addressed lines matching a regular expression
.Ar re .
For each matching line, the line is printed, the current address is set,
and the user is prompted to enter a
.Ar command-list .
At the end of the
.Ic G
command, the current address is set to the last line affected by (the last)
.Ar command-list .
.Pp
The format of
.Ar command-list
is the same as that of the
.Ic g
command.
A newline alone acts as a null command list.
A single
.Sq \*[Am]
repeats the last non-null command list.
.It Ic H
Toggles the printing of error explanations.
By default, explanations are not printed.
It is recommended that
.Nm
scripts begin with this command to aid in debugging.
.It Ic h
Prints an explanation of the last error.
.It (.) Ns Ic i
Inserts text in the buffer before the current line.
Text is entered in input mode.
The current address is set to the last line entered.
.It (.,.+1) Ns Ic j
Joins the addressed lines.
The addressed lines are deleted from the buffer and replaced by a single
line containing their joined text.
The current address is set to the resultant line.
.It (.) Ns Ic k Ns Ar lc
Marks a line with a lower case letter
.Ar lc .
The line can then be addressed as
.Ar \&'lc
(i.e., a single quote followed by
.Ar lc )
in subsequent commands.
The mark is not cleared until the line is deleted or otherwise modified.
.It (.,.) Ns Ic l
Prints the addressed lines unambiguously.
If a single line fills more than one screen (as might be the case
when viewing a binary file, for instance), a
.Dq --More--
prompt is printed on the last line.
.Nm
waits until the RETURN key is pressed before displaying the next screen.
The current address is set to the last line printed.
.It (.,.) Ns Ic m Ns No (.)
Moves lines in the buffer.
The addressed lines are moved to after the
right-hand destination address, which may be the address
.Em 0
(zero).
The current address is set to the last line moved.
.It (.,.) Ns Ic n
Prints the addressed lines along with their line numbers.
The current address is set to the last line printed.
.It (.,.) Ns Ic p
Prints the addressed lines.
The current address is set to the last line printed.
.It Ic P
Toggles the command prompt on and off.
Unless a prompt was specified with the command-line option
.Fl p Ar string ,
the command prompt is by default turned off.
.It Ic q
Quits
.Nm .
.It Ic Q
Quits
.Nm
unconditionally.
This is similar to the
.Ic q
command, except that unwritten changes are discarded without warning.
.It ($) Ns Ic r Ar file
Reads
.Ar file
to after the addressed line.
If
.Ar file
is not specified, then the default filename is used.
If there was no default filename prior to the command,
then the default filename is set to
.Ar file .
Otherwise, the default filename is unchanged.
The current address is set to the last line read.
.It ($) Ns Ic r Ar !command
Reads to after the addressed line the standard output of
.Ar command ,
(see the
.Ic \&!
command below).
The default filename is unchanged.
The current address is set to the last line read.
.Sm off
.It (.,.) Ic s Ar /re/replacement/ , \ (.,.) \
Ic s Ar /re/replacement/ Em g , Ar \ (.,.) \
Ic s Ar /re/replacement/ Em n
.Sm on
Replaces text in the addressed lines matching a regular expression
.Ar re
with
.Ar replacement .
By default, only the first match in each line is replaced.
If the
.Em g
(global) suffix is given, then every match to be replaced.
The
.Em n
suffix, where
.Em n
is a positive number, causes only the
.Em n Ns No th
match to be replaced.
It is an error if no substitutions are performed on any of the addressed
lines.
The current address is set the last line affected.
.Pp
.Ar re
and
.Ar replacement
may be delimited by any character other than space and newline
(see the
.Ic s
command below).
If one or two of the last delimiters is omitted, then the last line
affected is printed as though the print suffix
.Em p
were specified.
.Pp
An unescaped
.Ql \*[Am]
in
.Ar replacement
is replaced by the currently matched text.
The character sequence
.Em \em ,
where
.Em m
is a number in the range [1,9], is replaced by the
.Em m Ns No th
backreference expression of the matched text.
If
.Ar replacement
consists of a single
.Ql % ,
then
.Ar replacement
from the last substitution is used.
Newlines may be embedded in
.Ar replacement
if they are escaped with a backslash
.Pq Ql \e .
.It (.,.) Ns Ic s
Repeats the last substitution.
This form of the
.Ic s
command accepts a count suffix
.Em n ,
or any combination of the characters
.Em r ,
.Em g ,
and
.Em p .
If a count suffix
.Em n
is given, then only the
.Em n Ns No th
match is replaced.
The
.Em r
suffix causes
the regular expression of the last search to be used instead of
that of the last substitution.
The
.Em g
suffix toggles the global suffix of the last substitution.
The
.Em p
suffix toggles the print suffix of the last substitution.
The current address is set to the last line affected.
.It (.,.) Ns Ic t Ns No (.)
Copies (i.e., transfers) the addressed lines to after the right-hand
destination address, which may be the address
.Em 0
(zero).
The current address is set to the last line copied.
.It Ic u
Undoes the last command and restores the current address
to what it was before the command.
The global commands
.Ic g ,
.Ic G ,
.Ic v ,
and
.Ic V
are treated as a single command by undo.
.Ic u
is its own inverse.
.It (1,$) Ns Ic v Ns Ar /re/command-list
Applies
.Ar command-list
to each of the addressed lines not matching a regular expression
.Ar re .
This is similar to the
.Ic g
command.
.It (1,$) Ns Ic V Ns Ar /re/
Interactively edits the addressed lines not matching a regular expression
.Ar re .
This is similar to the
.Ic G
command.
.It (1,$) Ns Ic w Ar file
Writes the addressed lines to
.Ar file .
Any previous contents of
.Ar file
are lost without warning.
If there is no default filename, then the default filename is set to
.Ar file ,
otherwise it is unchanged.
If no filename is specified, then the default filename is used.
The current address is unchanged.
.It (1,$) Ns Ic wq Ar file
Writes the addressed lines to
.Ar file ,
and then executes a
.Ic q
command.
.It (1,$) Ns Ic w Ar !command
Writes the addressed lines to the standard input of
.Ar command ,
(see the
.Ic \&!
command below).
The default filename and current address are unchanged.
.It (1,$) Ns Ic W Ar file
Appends the addressed lines to the end of
.Ar file .
This is similar to the
.Ic w
command, except that the previous contents of file are not clobbered.
The current address is unchanged.
.It Ic x
Prompts for an encryption key which is used in subsequent reads and writes.
If a newline alone is entered as the key, then encryption is turned off.
Otherwise, echoing is disabled while a key is read.
Encryption/decryption is done using the
.Xr bdes 1
algorithm.
.It (.+1) Ns Ic z Ns Ar n
Scrolls
.Ar n
lines at a time starting at addressed line.
If
.Ar n
is not specified, then the current window size is used.
The current address is set to the last line printed.
.It ($) Ns Ic =
Prints the line number of the addressed line.
.It (.+1) Ns Ic newline
Prints the addressed line, and sets the current address to that line.
.It Ic \&! Ns Ar command
Executes
.Ar command
via
.Xr sh 1 .
If the first character of
.Ar command
is
.Ic \&! ,
then it is replaced by text of the previous
.Ic !command .
.Nm
does not process
.Ar command
for
.Sq \e
(backslash) escapes.
However, an unescaped
.Sq %
is replaced by the default filename.
When the shell returns from execution, a
.Sq \&!
is printed to the standard output.
The current line is unchanged.
.El
.Sh LIMITATIONS
.Nm
processes
.Em file
arguments for backslash escapes, i.e., in a filename,
any characters preceded by a backslash
.Pq Ql \e
are interpreted literally.
.Pp
If a text (non-binary) file is not terminated by a newline character,
then
.Nm
appends one on reading/writing it.
In the case of a binary file,
.Nm
does not append a newline on reading/writing.
.Sh ENVIRONMENT
.Bl -tag -width iTMPDIR
.It Ev TMPDIR
The location used to store temporary files.
.El
.Sh FILES
.Bl -tag -width /tmp/ed.* -compact
.It Pa /tmp/ed.*
buffer file
.It Pa ed.hup
where
.Nm
attempts to write the buffer if the terminal hangs up
.El
.Sh DIAGNOSTICS
When an error occurs,
.Nm
prints a
.Dq \&?
and either returns to command mode or exits if its input is from a script.
An explanation of the last error can be printed with the
.Ic h
(help) command.
.Pp
Since the
.Ic g
(global) command masks any errors from failed searches and substitutions,
it can be used to perform conditional operations in scripts; e.g.,
.Bd -literal -offset indent
g/old/s//new/
.Ed
.Pp
replaces any occurrences of
.Em old
with
.Em new .
.Pp
If the
.Ic u
(undo) command occurs in a global command list, then
the command list is executed only once.
.Pp
If diagnostics are not disabled, attempting to quit
.Nm
or edit another file before writing a modified buffer results in an error.
If the command is entered a second time, it succeeds,
but any changes to the buffer are lost.
.Sh SEE ALSO
.Xr bdes 1 ,
.Xr sed 1 ,
.Xr sh 1 ,
.Xr vi 1 ,
.Xr regex 3
.Pp
USD:09-10
.Rs
.%A B. W. Kernighan
.%A P. J. Plauger
.%B Software Tools in Pascal
.%I Addison-Wesley
.%D 1981
.Re
.Sh HISTORY
An
.Nm
command appeared in
.At v1 .

View File

@@ -1,293 +0,0 @@
/* $NetBSD: ed.h,v 1.35 2011/08/29 14:51:18 joerg Exp $ */
/* ed.h: type and constant definitions for the ed editor. */
/*
* Copyright (c) 1993 Andrew Moore
* 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.
*
* 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.
*
* @(#)ed.h,v 1.5 1994/02/01 00:34:39 alm Exp
*/
#include <sys/types.h>
#if defined(BSD) && BSD >= 199103 || defined(__386BSD__)
# include <sys/param.h> /* for MAXPATHLEN */
#endif
#include <errno.h>
#if defined(sun) || defined(__NetBSD__) || defined(__APPLE__) || \
defined(__minix)
# include <limits.h>
#endif
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define ERR (-2)
#define EMOD (-3)
#define FATAL (-4)
#ifndef MAXPATHLEN
# define MAXPATHLEN 255 /* _POSIX_PATH_MAX */
#endif
#define MINBUFSZ 512 /* minimum buffer size - must be > 0 */
#define SE_MAX 30 /* max subexpressions in a regular expression */
#ifdef INT_MAX
# define LINECHARS INT_MAX /* max chars per line */
#else
# define LINECHARS MAXINT /* max chars per line */
#endif
/* gflags */
#define GLB 001 /* global command */
#define GPR 002 /* print after command */
#define GLS 004 /* list after command */
#define GNP 010 /* enumerate after command */
#define GSG 020 /* global substitute */
typedef regex_t pattern_t;
/* Line node */
typedef struct line {
struct line *q_forw;
struct line *q_back;
off_t seek; /* address of line in scratch buffer */
int len; /* length of line */
} line_t;
typedef struct undo {
/* type of undo nodes */
#define UADD 0
#define UDEL 1
#define UMOV 2
#define VMOV 3
int type; /* command type */
line_t *h; /* head of list */
line_t *t; /* tail of list */
} undo_t;
#ifndef max
# define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#define INC_MOD(l, k) ((l) + 1 > (k) ? 0 : (l) + 1)
#define DEC_MOD(l, k) ((l) - 1 < 0 ? (k) : (l) - 1)
/* SPL1: disable some interrupts (requires reliable signals) */
#define SPL1() mutex++
/* SPL0: enable all interrupts; check sigflags (requires reliable signals) */
#define SPL0() \
if (--mutex == 0) { \
if (sigflags & (1 << (SIGHUP - 1))) handle_hup(SIGHUP); \
if (sigflags & (1 << (SIGINT - 1))) handle_int(SIGINT); \
}
/* STRTOL: convert a string to long */
#define STRTOL(i, p) { \
errno = 0 ; \
if (((i = strtol(p, &p, 10)) == LONG_MIN || i == LONG_MAX) && \
errno == ERANGE) { \
sprintf(errmsg, "number out of range"); \
i = 0; \
return ERR; \
} \
}
#if defined(sun) || defined(NO_REALLOC_NULL)
/* REALLOC: assure at least a minimum size for buffer b */
#define REALLOC(b,n,i,err) \
if ((i) > (n)) { \
int ti = (n); \
char *ts; \
SPL1(); \
if ((b) != NULL) { \
if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \
fprintf(stderr, "%s\n", strerror(errno)); \
sprintf(errmsg, "out of memory"); \
SPL0(); \
return err; \
} \
} else { \
if ((ts = (char *) malloc(ti += max((i), MINBUFSZ))) == NULL) { \
fprintf(stderr, "%s\n", strerror(errno)); \
sprintf(errmsg, "out of memory"); \
SPL0(); \
return err; \
} \
} \
(n) = ti; \
(b) = ts; \
SPL0(); \
}
#else /* NO_REALLOC_NULL */
/* REALLOC: assure at least a minimum size for buffer b */
#define REALLOC(b,n,i,err) \
if ((i) > (n)) { \
int ti = (n); \
char *ts; \
SPL1(); \
if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \
fprintf(stderr, "%s\n", strerror(errno)); \
sprintf(errmsg, "out of memory"); \
SPL0(); \
return err; \
} \
(n) = ti; \
(b) = ts; \
SPL0(); \
}
#endif /* NO_REALLOC_NULL */
/* REQUE: link pred before succ */
#define REQUE(pred, succ) (pred)->q_forw = (succ), (succ)->q_back = (pred)
/* INSQUE: insert elem in circular queue after pred */
#define INSQUE(elem, pred) \
{ \
REQUE((elem), (pred)->q_forw); \
REQUE((pred), elem); \
}
/* remque: remove_lines elem from circular queue */
#define REMQUE(elem) REQUE((elem)->q_back, (elem)->q_forw);
/* NUL_TO_NEWLINE: overwrite ASCII NULs with newlines */
#define NUL_TO_NEWLINE(s, l) translit_text(s, l, '\0', '\n')
/* NEWLINE_TO_NUL: overwrite newlines with ASCII NULs */
#define NEWLINE_TO_NUL(s, l) translit_text(s, l, '\n', '\0')
#if defined(sun) && !defined(__SVR4)
# define strerror(n) sys_errlist[n]
#endif
/* Local Function Declarations */
void add_line_node(line_t *);
int append_lines(long);
int apply_subst_template(char *, regmatch_t *, int, int);
int build_active_list(int);
int check_addr_range(long, long);
void clear_active_list(void);
void clear_undo_stack(void);
int close_sbuf(void);
int copy_lines(long);
int delete_lines(long, long);
int display_lines(long, long, int);
line_t *dup_line_node(line_t *);
int exec_command(void);
long exec_global(int, int);
int extract_addr_range(void);
char *extract_pattern(int);
int extract_subst_tail(int *, long *);
char *extract_subst_template(void);
int filter_lines(long, long, char *);
int flush_des_file(FILE *);
line_t *get_addressed_line_node(long);
pattern_t *get_compiled_pattern(void);
int get_des_char(FILE *);
char *get_extended_line(int *, int);
char *get_filename(void);
int get_keyword(void);
long get_line_node_addr(line_t *);
long get_matching_node_addr(pattern_t *, int);
long get_marked_node_addr(int);
char *get_sbuf_line(line_t *);
int get_shell_command(void);
int get_stream_line(FILE *);
int get_tty_line(void);
__dead void handle_hup(int);
__dead void handle_int(int);
void handle_winch(int);
int has_trailing_escape(char *, char *);
void init_buffers(void);
void init_des_cipher(void);
int is_legal_filename(char *);
int join_lines(long, long);
int mark_line_node(line_t *, int);
int move_lines(long);
line_t *next_active_node(void);
long next_addr(void);
int open_sbuf(void);
char *parse_char_class(char *);
int pop_undo_stack(void);
undo_t *push_undo_stack(int, long, long);
int put_des_char(int, FILE *);
char *put_sbuf_line(char *);
int put_stream_line(FILE *, char *, int);
int put_tty_line(char *, int, long, int);
__dead void quit(int);
long read_file(char *, long);
long read_stream(FILE *, long);
int search_and_replace(pattern_t *, int, int);
int set_active_node(line_t *);
void signal_hup(int);
void signal_int(int);
char *strip_escapes(const char *);
int substitute_matching_text(pattern_t *, line_t *, int, int);
char *translit_text(char *, int, int, int);
void unmark_line_node(line_t *);
void unset_active_nodes(line_t *, line_t *);
long write_file(const char *, const char *, long, long);
long write_stream(FILE *, long, long);
/* global buffers */
extern char stdinbuf[];
extern char *ibuf;
extern char *ibufp;
extern int ibufsz;
/* global flags */
extern int isbinary;
extern int isglobal;
extern int modified;
extern int mutex;
extern int sigflags;
/* global vars */
extern long addr_last;
extern long current_addr;
extern long first_addr;
extern int lineno;
extern long second_addr;
extern long rows;
extern int cols;
extern int scripted;
extern int ere;
extern int des;
extern int newline_added; /* io.c */
extern int patlock;
extern char errmsg[]; /* re.c */
extern long u_current_addr; /* undo.c */
extern long u_addr_last; /* undo.c */
#if defined(sun) && !defined(__SVR4)
extern char *sys_errlist[];
#endif

View File

@@ -1,227 +0,0 @@
/* $NetBSD: glbl.c,v 1.6 2005/06/26 19:10:49 christos Exp $ */
/* glob.c: This file contains the global command routines for the ed line
editor */
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)glob.c,v 1.1 1994/02/01 00:34:40 alm Exp";
#else
__RCSID("$NetBSD: glbl.c,v 1.6 2005/06/26 19:10:49 christos Exp $");
#endif
#endif /* not lint */
#include <sys/ioctl.h>
#include <sys/wait.h>
#include "ed.h"
/* build_active_list: add line matching a pattern to the global-active list */
int
build_active_list(int isgcmd)
{
pattern_t *pat;
line_t *lp;
long n;
char *s;
char delimiter;
if ((delimiter = *ibufp) == ' ' || delimiter == '\n') {
sprintf(errmsg, "invalid pattern delimiter");
return ERR;
} else if ((pat = get_compiled_pattern()) == NULL)
return ERR;
else if (*ibufp == delimiter)
ibufp++;
clear_active_list();
lp = get_addressed_line_node(first_addr);
for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) {
if ((s = get_sbuf_line(lp)) == NULL)
return ERR;
if (isbinary)
NUL_TO_NEWLINE(s, lp->len);
if (!regexec(pat, s, 0, NULL, 0) == isgcmd &&
set_active_node(lp) < 0)
return ERR;
}
return 0;
}
/* exec_global: apply command list in the command buffer to the active
lines in a range; return command status */
long
exec_global(int interact, int gflag)
{
static char *ocmd = NULL;
static int ocmdsz = 0;
line_t *lp = NULL;
int status;
int n;
char *cmd = NULL;
#ifdef BACKWARDS
char cmdp[] = "p\n";
if (!interact) {
if (!strcmp(ibufp, "\n"))
cmd = cmdp; /* null cmd-list == `p' */
else if ((cmd = get_extended_line(&n, 0)) == NULL)
return ERR;
}
#else
if (!interact && (cmd = get_extended_line(&n, 0)) == NULL)
return ERR;
#endif
clear_undo_stack();
while ((lp = next_active_node()) != NULL) {
if ((current_addr = get_line_node_addr(lp)) < 0)
return ERR;
if (interact) {
/* print current_addr; get a command in global syntax */
if (display_lines(current_addr, current_addr, gflag) < 0)
return ERR;
while ((n = get_tty_line()) > 0 &&
ibuf[n - 1] != '\n')
clearerr(stdin);
if (n < 0)
return ERR;
else if (n == 0) {
sprintf(errmsg, "unexpected end-of-file");
return ERR;
} else if (n == 1 && !strcmp(ibuf, "\n"))
continue;
else if (n == 2 && !strcmp(ibuf, "&\n")) {
if (cmd == NULL) {
sprintf(errmsg, "no previous command");
return ERR;
} else cmd = ocmd;
} else if ((cmd = get_extended_line(&n, 0)) == NULL)
return ERR;
else {
REALLOC(ocmd, ocmdsz, n + 1, ERR);
memcpy(ocmd, cmd, n + 1);
cmd = ocmd;
}
}
ibufp = cmd;
for (; *ibufp;)
if ((status = extract_addr_range()) < 0 ||
(status = exec_command()) < 0 ||
(status > 0 && (status = display_lines(
current_addr, current_addr, status))) < 0)
return status;
}
return 0;
}
line_t **active_list; /* list of lines active in a global command */
long active_last; /* index of last active line in active_list */
long active_size; /* size of active_list */
long active_ptr; /* active_list index (non-decreasing) */
long active_ndx; /* active_list index (modulo active_last) */
/* set_active_node: add a line node to the global-active list */
int
set_active_node(line_t *lp)
{
if (active_last + 1 > active_size) {
int ti = active_size;
line_t **ts;
SPL1();
#if defined(sun) || defined(NO_REALLOC_NULL)
if (active_list != NULL) {
#endif
if ((ts = (line_t **) realloc(active_list,
(ti += MINBUFSZ) * sizeof(line_t **))) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "out of memory");
SPL0();
return ERR;
}
#if defined(sun) || defined(NO_REALLOC_NULL)
} else {
if ((ts = (line_t **) malloc((ti += MINBUFSZ) *
sizeof(line_t **))) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "out of memory");
SPL0();
return ERR;
}
}
#endif
active_size = ti;
active_list = ts;
SPL0();
}
active_list[active_last++] = lp;
return 0;
}
/* unset_active_nodes: remove a range of lines from the global-active list */
void
unset_active_nodes(line_t *np, line_t *mp)
{
line_t *lp;
long i;
for (lp = np; lp != mp; lp = lp->q_forw)
for (i = 0; i < active_last; i++)
if (active_list[active_ndx] == lp) {
active_list[active_ndx] = NULL;
active_ndx = INC_MOD(active_ndx, active_last - 1);
break;
} else active_ndx = INC_MOD(active_ndx, active_last - 1);
}
/* next_active_node: return the next global-active line node */
line_t *
next_active_node(void)
{
while (active_ptr < active_last && active_list[active_ptr] == NULL)
active_ptr++;
return (active_ptr < active_last) ? active_list[active_ptr++] : NULL;
}
/* clear_active_list: clear the global-active list */
void
clear_active_list(void)
{
SPL1();
active_size = active_last = active_ptr = active_ndx = 0;
free(active_list);
active_list = NULL;
SPL0();
}

View File

@@ -1,358 +0,0 @@
/* $NetBSD: io.c,v 1.9 2011/05/23 23:13:10 joerg Exp $ */
/* io.c: This file contains the i/o routines for the ed line editor */
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)io.c,v 1.1 1994/02/01 00:34:41 alm Exp";
#else
__RCSID("$NetBSD: io.c,v 1.9 2011/05/23 23:13:10 joerg Exp $");
#endif
#endif /* not lint */
#include "ed.h"
/* read_file: read a named file/pipe into the buffer; return line count */
long
read_file(char *fn, long n)
{
FILE *fp;
long size;
fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r");
if (fp == NULL) {
fprintf(stderr, "%s: %s\n", fn, strerror(errno));
sprintf(errmsg, "cannot open input file");
return ERR;
} else if ((size = read_stream(fp, n)) < 0)
return ERR;
else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) {
fprintf(stderr, "%s: %s\n", fn, strerror(errno));
sprintf(errmsg, "cannot close input file");
return ERR;
}
if (!scripted)
fprintf(stderr, "%lu\n", size);
return current_addr - n;
}
char *sbuf; /* file i/o buffer */
int sbufsz; /* file i/o buffer size */
int newline_added; /* if set, newline appended to input file */
/* read_stream: read a stream into the editor buffer; return status */
long
read_stream(FILE *fp, long n)
{
line_t *lp = get_addressed_line_node(n);
undo_t *up = NULL;
unsigned long size = 0;
int o_newline_added = newline_added;
int o_isbinary = isbinary;
int appended = (n == addr_last);
int len;
isbinary = newline_added = 0;
if (des)
init_des_cipher();
for (current_addr = n; (len = get_stream_line(fp)) > 0; size += len) {
SPL1();
if (put_sbuf_line(sbuf) == NULL) {
SPL0();
return ERR;
}
lp = lp->q_forw;
if (up)
up->t = lp;
else if ((up = push_undo_stack(UADD, current_addr,
current_addr)) == NULL) {
SPL0();
return ERR;
}
SPL0();
}
if (len < 0)
return ERR;
if (appended && size && o_isbinary && o_newline_added)
fputs("newline inserted\n", stderr);
else if (newline_added && (!appended || (!isbinary && !o_isbinary)))
fputs("newline appended\n", stderr);
if (isbinary && newline_added && !appended)
size += 1;
if (!size)
newline_added = 1;
newline_added = appended ? newline_added : o_newline_added;
isbinary = isbinary | o_isbinary;
if (des)
size += 8 - size % 8; /* adjust DES size */
return size;
}
/* get_stream_line: read a line of text from a stream; return line length */
int
get_stream_line(FILE *fp)
{
int c;
int i = 0;
while (((c = des ? get_des_char(fp) : getc(fp)) != EOF || (!feof(fp) &&
!ferror(fp))) && c != '\n') {
REALLOC(sbuf, sbufsz, i + 1, ERR);
if (!(sbuf[i++] = c))
isbinary = 1;
}
REALLOC(sbuf, sbufsz, i + 2, ERR);
if (c == '\n')
sbuf[i++] = c;
else if (ferror(fp)) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot read input file");
return ERR;
} else if (i) {
sbuf[i++] = '\n';
newline_added = 1;
}
sbuf[i] = '\0';
return (isbinary && newline_added && i) ? --i : i;
}
/* write_file: write a range of lines to a named file/pipe; return line count */
long
write_file(const char *fn, const char *mode, long n, long m)
{
FILE *fp;
long size;
fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode);
if (fp == NULL) {
fprintf(stderr, "%s: %s\n", fn, strerror(errno));
sprintf(errmsg, "cannot open output file");
return ERR;
} else if ((size = write_stream(fp, n, m)) < 0)
return ERR;
else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) {
fprintf(stderr, "%s: %s\n", fn, strerror(errno));
sprintf(errmsg, "cannot close output file");
return ERR;
}
if (!scripted)
fprintf(stderr, "%lu\n", size);
return n ? m - n + 1 : 0;
}
/* write_stream: write a range of lines to a stream; return status */
long
write_stream(FILE *fp, long n, long m)
{
line_t *lp = get_addressed_line_node(n);
unsigned long size = 0;
char *s;
int len;
if (des)
init_des_cipher();
for (; n && n <= m; n++, lp = lp->q_forw) {
if ((s = get_sbuf_line(lp)) == NULL)
return ERR;
len = lp->len;
if (n != addr_last || !isbinary || !newline_added)
s[len++] = '\n';
if (put_stream_line(fp, s, len) < 0)
return ERR;
size += len;
}
if (des) {
flush_des_file(fp); /* flush buffer */
size += 8 - size % 8; /* adjust DES size */
}
return size;
}
/* put_stream_line: write a line of text to a stream; return status */
int
put_stream_line(FILE *fp, char *s, int len)
{
while (len--)
if ((des ? put_des_char(*s++, fp) : fputc(*s++, fp)) < 0) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "cannot write file");
return ERR;
}
return 0;
}
/* get_extended_line: get a an extended line from stdin */
char *
get_extended_line(int *sizep, int nonl)
{
static char *cvbuf = NULL; /* buffer */
static int cvbufsz = 0; /* buffer size */
int l, n;
char *t = ibufp;
while (*t++ != '\n')
;
if ((l = t - ibufp) < 2 || !has_trailing_escape(ibufp, ibufp + l - 1)) {
*sizep = l;
return ibufp;
}
*sizep = -1;
REALLOC(cvbuf, cvbufsz, l, NULL);
memcpy(cvbuf, ibufp, l);
*(cvbuf + --l - 1) = '\n'; /* strip trailing esc */
if (nonl) l--; /* strip newline */
for (;;) {
if ((n = get_tty_line()) < 0)
return NULL;
else if (n == 0 || ibuf[n - 1] != '\n') {
sprintf(errmsg, "unexpected end-of-file");
return NULL;
}
REALLOC(cvbuf, cvbufsz, l + n, NULL);
memcpy(cvbuf + l, ibuf, n);
l += n;
if (n < 2 || !has_trailing_escape(cvbuf, cvbuf + l - 1))
break;
*(cvbuf + --l - 1) = '\n'; /* strip trailing esc */
if (nonl) l--; /* strip newline */
}
REALLOC(cvbuf, cvbufsz, l + 1, NULL);
cvbuf[l] = '\0';
*sizep = l;
return cvbuf;
}
/* get_tty_line: read a line of text from stdin; return line length */
int
get_tty_line(void)
{
int oi = 0;
int i = 0;
int c;
for (;;)
switch (c = getchar()) {
default:
oi = 0;
REALLOC(ibuf, ibufsz, i + 2, ERR);
if (!(ibuf[i++] = c)) isbinary = 1;
if (c != '\n')
continue;
lineno++;
ibuf[i] = '\0';
ibufp = ibuf;
return i;
case EOF:
if (ferror(stdin)) {
fprintf(stderr, "stdin: %s\n", strerror(errno));
sprintf(errmsg, "cannot read stdin");
clearerr(stdin);
ibufp = NULL;
return ERR;
} else {
clearerr(stdin);
if (i != oi) {
oi = i;
continue;
} else if (i)
ibuf[i] = '\0';
ibufp = ibuf;
return i;
}
}
}
#define ESCAPES "\a\b\f\n\r\t\v\\"
#define ESCCHARS "abfnrtv\\"
/* put_tty_line: print text to stdout */
int
put_tty_line(char *s, int l, long n, int gflag)
{
int col = 0;
char *cp;
#ifndef BACKWARDS
int lc = 0;
#endif
if (gflag & GNP) {
printf("%ld\t", n);
col = 8;
}
for (; l--; s++) {
if ((gflag & GLS) && ++col > cols) {
fputs("\\\n", stdout);
col = 1;
#ifndef BACKWARDS
if (!scripted && !isglobal && ++lc > rows) {
lc = 0;
fputs("Press <RETURN> to continue... ", stdout);
fflush(stdout);
if (get_tty_line() < 0)
return ERR;
}
#endif
}
if (gflag & GLS) {
if (31 < *s && *s < 127 && *s != '\\')
putchar(*s);
else {
putchar('\\');
col++;
if (*s && (cp = strchr(ESCAPES, *s)) != NULL)
putchar(ESCCHARS[cp - ESCAPES]);
else {
putchar((((unsigned char) *s & 0300) >> 6) + '0');
putchar((((unsigned char) *s & 070) >> 3) + '0');
putchar(((unsigned char) *s & 07) + '0');
col += 2;
}
}
} else
putchar(*s);
}
#ifndef BACKWARDS
if (gflag & GLS)
putchar('$');
#endif
putchar('\n');
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +0,0 @@
/* $NetBSD: re.c,v 1.20 2013/06/28 15:04:35 joerg Exp $ */
/* re.c: This file contains the regular expression interface routines for
the ed line editor. */
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)re.c,v 1.6 1994/02/01 00:34:43 alm Exp";
#else
__RCSID("$NetBSD: re.c,v 1.20 2013/06/28 15:04:35 joerg Exp $");
#endif
#endif /* not lint */
#include "ed.h"
char errmsg[MAXPATHLEN + 40] = "";
/* get_compiled_pattern: return pointer to compiled pattern from command
buffer */
pattern_t *
get_compiled_pattern(void)
{
static pattern_t *expr = NULL;
char *exps;
char delimiter;
int n;
if ((delimiter = *ibufp) == ' ') {
sprintf(errmsg, "invalid pattern delimiter");
return NULL;
} else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) {
if (!expr) sprintf(errmsg, "no previous pattern");
return expr;
} else if ((exps = extract_pattern(delimiter)) == NULL)
return NULL;
/* buffer alloc'd && not reserved */
if (expr && !patlock)
regfree(expr);
else if ((expr = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
sprintf(errmsg, "out of memory");
return NULL;
}
patlock = 0;
if ((n = regcomp(expr, exps, ere)) != 0) {
regerror(n, expr, errmsg, sizeof errmsg);
free(expr);
return expr = NULL;
}
return expr;
}
/* extract_pattern: copy a pattern string from the command buffer; return
pointer to the copy */
char *
extract_pattern(int delimiter)
{
static char *lhbuf = NULL; /* buffer */
static int lhbufsz = 0; /* buffer size */
char *nd;
int len;
for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++)
switch (*nd) {
default:
break;
case '[':
if ((nd = parse_char_class(nd + 1)) == NULL) {
sprintf(errmsg, "unbalanced brackets ([])");
return NULL;
}
break;
case '\\':
if (*++nd == '\n') {
sprintf(errmsg, "trailing backslash (\\)");
return NULL;
}
break;
}
len = nd - ibufp;
REALLOC(lhbuf, lhbufsz, len + 1, NULL);
memcpy(lhbuf, ibufp, len);
lhbuf[len] = '\0';
ibufp = nd;
return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf;
}
/* parse_char_class: expand a POSIX character class */
char *
parse_char_class(char *s)
{
int c, d;
if (*s == '^')
s++;
if (*s == ']')
s++;
for (; *s != ']' && *s != '\n'; s++)
if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '='))
for (s++, c = *++s; *s != ']' || c != d; s++)
if ((c = *s) == '\n')
return NULL;
return (*s == ']') ? s : NULL;
}

View File

@@ -1,260 +0,0 @@
/* $NetBSD: sub.c,v 1.6 2005/02/17 16:29:26 xtraeme Exp $ */
/* sub.c: This file contains the substitution routines for the ed
line editor */
/*-
* Copyright (c) 1993 Andrew Moore, Talke Studio.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "@(#)sub.c,v 1.1 1994/02/01 00:34:44 alm Exp";
#else
__RCSID("$NetBSD: sub.c,v 1.6 2005/02/17 16:29:26 xtraeme Exp $");
#endif
#endif /* not lint */
#include "ed.h"
char *rhbuf; /* rhs substitution buffer */
int rhbufsz; /* rhs substitution buffer size */
int rhbufi; /* rhs substitution buffer index */
/* extract_subst_tail: extract substitution tail from the command buffer */
int
extract_subst_tail(int *flagp, long *np)
{
char delimiter;
*flagp = *np = 0;
if ((delimiter = *ibufp) == '\n') {
rhbufi = 0;
*flagp = GPR;
return 0;
} else if (extract_subst_template() == NULL)
return ERR;
else if (*ibufp == '\n') {
*flagp = GPR;
return 0;
} else if (*ibufp == delimiter)
ibufp++;
if ('1' <= *ibufp && *ibufp <= '9') {
STRTOL(*np, ibufp);
return 0;
} else if (*ibufp == 'g') {
ibufp++;
*flagp = GSG;
return 0;
}
return 0;
}
/* extract_subst_template: return pointer to copy of substitution template
in the command buffer */
char *
extract_subst_template(void)
{
int n = 0;
int i = 0;
char c;
char delimiter = *ibufp++;
if (*ibufp == '%' && *(ibufp + 1) == delimiter) {
ibufp++;
if (!rhbuf) sprintf(errmsg, "no previous substitution");
return rhbuf;
}
while (*ibufp != delimiter) {
REALLOC(rhbuf, rhbufsz, i + 2, NULL);
if ((c = rhbuf[i++] = *ibufp++) == '\n' && *ibufp == '\0') {
i--, ibufp--;
break;
} else if (c != '\\')
;
else if ((rhbuf[i++] = *ibufp++) != '\n')
;
else if (!isglobal) {
while ((n = get_tty_line()) == 0 ||
(n > 0 && ibuf[n - 1] != '\n'))
clearerr(stdin);
if (n < 0)
return NULL;
}
}
REALLOC(rhbuf, rhbufsz, i + 1, NULL);
rhbuf[rhbufi = i] = '\0';
return rhbuf;
}
char *rbuf; /* substitute_matching_text buffer */
int rbufsz; /* substitute_matching_text buffer size */
/* search_and_replace: for each line in a range, change text matching a pattern
according to a substitution template; return status */
int
search_and_replace(pattern_t *pat, int gflag, int kth)
{
undo_t *up;
char *txt;
char *eot;
long lc;
long xa = current_addr;
int nsubs = 0;
line_t *lp;
int len;
current_addr = first_addr - 1;
for (lc = 0; lc <= second_addr - first_addr; lc++) {
lp = get_addressed_line_node(++current_addr);
if ((len = substitute_matching_text(pat, lp, gflag, kth)) < 0)
return ERR;
else if (len) {
up = NULL;
if (delete_lines(current_addr, current_addr) < 0)
return ERR;
txt = rbuf;
eot = rbuf + len;
SPL1();
do {
if ((txt = put_sbuf_line(txt)) == NULL) {
SPL0();
return ERR;
} else if (up)
up->t = get_addressed_line_node(current_addr);
else if ((up = push_undo_stack(UADD,
current_addr, current_addr)) == NULL) {
SPL0();
return ERR;
}
} while (txt != eot);
SPL0();
nsubs++;
xa = current_addr;
}
}
current_addr = xa;
if (nsubs == 0 && !(gflag & GLB)) {
sprintf(errmsg, "no match");
return ERR;
} else if ((gflag & (GPR | GLS | GNP)) &&
display_lines(current_addr, current_addr, gflag) < 0)
return ERR;
return 0;
}
/* substitute_matching_text: replace text matched by a pattern according to
a substitution template; return pointer to the modified text */
int
substitute_matching_text(pattern_t *pat, line_t *lp, int gflag, int kth)
{
int off = 0;
int changed = 0;
int matchno = 0;
int i = 0;
regmatch_t rm[SE_MAX];
char *txt;
char *eot;
if ((txt = get_sbuf_line(lp)) == NULL)
return ERR;
if (isbinary)
NUL_TO_NEWLINE(txt, lp->len);
eot = txt + lp->len;
if (!regexec(pat, txt, SE_MAX, rm, 0)) {
do {
if (!kth || kth == ++matchno) {
changed++;
i = rm[0].rm_so;
REALLOC(rbuf, rbufsz, off + i, ERR);
if (isbinary)
NEWLINE_TO_NUL(txt, rm[0].rm_eo);
memcpy(rbuf + off, txt, i);
off += i;
if ((off = apply_subst_template(txt, rm, off,
pat->re_nsub)) < 0)
return ERR;
} else {
i = rm[0].rm_eo;
REALLOC(rbuf, rbufsz, off + i, ERR);
if (isbinary)
NEWLINE_TO_NUL(txt, i);
memcpy(rbuf + off, txt, i);
off += i;
}
txt += rm[0].rm_eo;
} while (*txt && (!changed || ((gflag & GSG) && rm[0].rm_eo))
&& !regexec(pat, txt, SE_MAX, rm, REG_NOTBOL));
i = eot - txt;
REALLOC(rbuf, rbufsz, off + i + 2, ERR);
if (i > 0 && !rm[0].rm_eo && (gflag & GSG)) {
sprintf(errmsg, "infinite substitution loop");
return ERR;
}
if (isbinary)
NEWLINE_TO_NUL(txt, i);
memcpy(rbuf + off, txt, i);
memcpy(rbuf + off + i, "\n", 2);
}
return changed ? off + i + 1 : 0;
}
/* apply_subst_template: modify text according to a substitution template;
return offset to end of modified text */
int
apply_subst_template(char *boln, regmatch_t *rm, int off, int re_nsub)
{
int j = 0;
int k = 0;
int n;
char *sub = rhbuf;
for (; sub - rhbuf < rhbufi; sub++)
if (*sub == '&') {
j = rm[0].rm_so;
k = rm[0].rm_eo;
REALLOC(rbuf, rbufsz, off + k - j, ERR);
while (j < k)
rbuf[off++] = boln[j++];
} else if (*sub == '\\' && '1' <= *++sub && *sub <= '9' &&
(n = *sub - '0') <= re_nsub) {
j = rm[n].rm_so;
k = rm[n].rm_eo;
REALLOC(rbuf, rbufsz, off + k - j, ERR);
while (j < k)
rbuf[off++] = boln[j++];
} else {
REALLOC(rbuf, rbufsz, off + 1, ERR);
rbuf[off++] = *sub;
}
REALLOC(rbuf, rbufsz, off + 1, ERR);
rbuf[off] = '\0';
return off;
}

View File

@@ -1 +0,0 @@
1,$=

View File

@@ -1,28 +0,0 @@
# $NetBSD: Makefile,v 1.12 2003/10/26 03:50:07 lukem Exp $
.include <bsd.own.mk>
ED?= ../obj/ed
all: check
@:
check: build test
@if grep -h '\*\*\*' errs.o scripts.o; then :; else \
echo "tests completed successfully."; \
fi
build: mkscripts.sh
@if [ -f errs.o ]; then :; else \
echo "building test scripts for $(ED) ..."; \
${HOST_SH} ${.CURDIR}/mkscripts.sh $(ED); \
fi
test: build ckscripts.sh
@echo testing $(ED) ...
@${HOST_SH} ckscripts.sh $(ED)
clean:
rm -f *.ed *.red *.[oz] *~
.include <bsd.prog.mk>

View File

@@ -1,32 +0,0 @@
$NetBSD: README,v 1.8 1995/03/21 09:05:18 cgd Exp $
The files in this directory with suffixes `.t', `.d', `.r' and `.err' are
used for testing ed. To run the tests, set the ED variable in the Makefile
for the path name of the program to be tested (e.g., /bin/ed), and type
`make'. The tests do not exhaustively verify POSIX compliance nor do
they verify correct 8-bit or long line support.
The test file suffixes have the following meanings:
.t Template - a list of ed commands from which an ed script is
constructed
.d Data - read by an ed script
.r Result - the expected output after processing data via an ed
script.
.err Error - invalid ed commands that should generate an error
The output of the tests is written to the two files err.o and scripts.o.
At the end of the tests, these files are grep'ed for error messages,
which look like:
*** The script u.ed exited abnormally ***
or:
*** Output u.o of script u.ed is incorrect ***
The POSIX requirement that an address range not be used where at most
a single address is expected has been relaxed in this version of ed.
Therefore, the following scripts which test for compliance with this
POSIX rule exit abnormally:
=-err.ed
a1-err.ed
i1-err.ed
k1-err.ed
r1-err.ed

View File

@@ -1,17 +0,0 @@
$NetBSD: TODO,v 1.3 1995/03/21 09:05:20 cgd Exp $
Some missing tests:
0) g/./s^@^@ - okay: NULs in commands
1) g/./s/^@/ - okay: NULs in patterns
2) a
hello^V^Jworld
. - okay: embedded newlines in insert mode
3) ed "" - error: invalid filename
4) red .. - error: restricted
5) red / - error: restricted
5) red !xx - error: restricted
6) ed -x - verify: 8-bit clean
7) ed - verify: long-line support
8) ed - verify: interactive/help mode
9) G/pat/ - verify: global interactive command
10) V/pat/ - verify: global interactive command

View File

@@ -1,8 +0,0 @@
hello world
line 1
hello world!
line 2
line 3
line 4
line5
hello world!!

View File

@@ -1,9 +0,0 @@
0a
hello world
.
2a
hello world!
.
$a
hello world!!
.

Some files were not shown because too many files have changed in this diff Show More