1
0
Fork 0

Adding upstream version 5.2.37.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
Daniel Baumann 2025-06-21 06:49:21 +02:00
parent cf91100bce
commit fa1b3d3922
Signed by: daniel.baumann
GPG key ID: BCC918A2ABD66424
1435 changed files with 757174 additions and 0 deletions

657
lib/sh/Makefile.in Normal file
View file

@ -0,0 +1,657 @@
#
# Makefile for the Bash library
#
#
# Copyright (C) 1998-2022 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PACKAGE = @PACKAGE_NAME@
VERSION = @PACKAGE_VERSION@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_VERSION = @PACKAGE_VERSION@
srcdir = @srcdir@
VPATH = @srcdir@
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
LIBBUILD = ${BUILD_DIR}/lib
BASHINCDIR = ${topdir}/include
INTL_LIBSRC = ${topdir}/lib/intl
INTL_BUILDDIR = ${LIBBUILD}/intl
INTL_INC = @INTL_INC@
LIBINTL_H = @LIBINTL_H@
datarootdir = @datarootdir@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CC = @CC@
RANLIB = @RANLIB@
AR = @AR@
ARFLAGS = @ARFLAGS@
RM = rm -f
CP = cp
MV = mv
SHELL = @MAKE_SHELL@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
STYLE_CFLAGS = @STYLE_CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
PROFILE_FLAGS = @PROFILE_FLAGS@
DEFS = @DEFS@
LOCAL_DEFS = @LOCAL_DEFS@
INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) $(INTL_INC)
CCFLAGS = ${ADDON_CFLAGS} ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) \
$(LOCAL_CFLAGS) $(STYLE_CFLAGS) $(CFLAGS) $(CPPFLAGS)
GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
-Wcast-align -Wstrict-prototypes -Wconversion \
-Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
.c.o:
$(CC) -c $(CCFLAGS) $<
# The name of the library target.
LIBRARY_NAME = libsh.a
# The C code source files for this library.
CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
shquote.c strtrans.c strcasestr.c snprintf.c mailstat.c \
fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c \
strvis.c utf8.c random.c gettimeofday.c timers.c
# The header files for this library.
HSOURCES =
# The object files contained in $(LIBRARY_NAME)
LIBOBJS = @LIBOBJS@
OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
itos.o zread.o zwrite.o shtty.o shmatch.o eaccess.o \
netconn.o netopen.o timeval.o makepath.o pathcanon.o \
pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o strvis.o \
utf8.o random.o gettimeofday.o timers.o wcsnwidth.o ${LIBOBJS}
SUPPORT = Makefile
all: $(LIBRARY_NAME)
$(LIBRARY_NAME): $(OBJECTS)
$(RM) $@
$(AR) $(ARFLAGS) $@ $(OBJECTS)
-test -n "$(RANLIB)" && $(RANLIB) $@
force:
# The rule for 'includes' is written funny so that the if statement
# always returns TRUE unless there really was an error installing the
# include files.
install:
clean:
$(RM) $(OBJECTS) $(LIBRARY_NAME)
realclean distclean maintainer-clean: clean
$(RM) Makefile
mostlyclean: clean
# Dependencies
${BUILD_DIR}/version.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
${BUILD_DIR}/pathnames.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} pathnames.h )
# rules for losing makes, like SunOS
casemod.o: casemod.c
clktck.o: clktck.c
clock.o: clock.c
eaccess.o: eaccess.c
dprintf.o: dprintf.c
fmtullong.o: fmtullong.c
fmtulong.o: fmtulong.c
fmtumax.o: fmtumax.c
fnxform.o: fnxform.c
fpurge.o: fpurge.c
getcwd.o: getcwd.c
getenv.o: getenv.c
gettimeofday.o: gettimeofday.c
inet_aton.o: inet_aton.c
input_avail.o: input_avail.c
itos.o: itos.c
mailstat.o: mailstat.c
makepath.o: makepath.c
mbscasecmp.o: mbscasecmp.c
mbschr.o: mbschr.c
mbscmp.o: mbscmp.c
memset.o: memset.c
mktime.o: mktime.c
netconn.o: netconn.c
netopen.o: netopen.c
oslib.o: oslib.c
pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
random.o: random.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shmatch.o: shmatch.c
shmbchar.o: shmbchar.c
shquote.o: shquote.c
shtty.o: shtty.c
snprintf.o: snprintf.c
spell.o: spell.c
strcasecmp.o: strcasecmp.c
strchrnul.o: strchrnul.c
strerror.o: strerror.c
strftime.o: strftime.c
strcasestr.o: strcasestr.c
stringlist.o: stringlist.c
stringvec.o: stringvec.c
strnlen.o: strnlen.c
strpbrk.o: strpbrk.c
strtod.o: strtod.c
strtoimax.o: strtoimax.c
strtol.o: strtol.c
strtoll.o: strtoll.c
strtoul.o: strtoul.c
strtoull.o: strtoull.c
strtoumax.o: strtoumax.c
strtrans.o: strtrans.c
strvis.o: strvis.c
timers.o: timers.c
times.o: times.c
timeval.o: timeval.c
tmpfile.o: tmpfile.c
uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
unicode.o: unicode.c
utf8.o: utf8.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
wcsnwidth.o: wcsnwidth.c
wcswidth.o: wcswidth.c
winsize.o: winsize.c
zcatfd.o: zcatfd.c
zmapfd.o: zmapfd.c
zgetline.o: zgetline.c
zread.o: zread.c
zwrite.o: zwrite.c
# dependencies for c files that include other c files
fmtullong.o: fmtulong.c
fmtumax.o: fmtulong.c
strtoll.o: strtol.c
strtoul.o: strtol.c
strtoull.o: strtol.c
# all files in the library depend on config.h
casemod.o: ${BUILD_DIR}/config.h
clktck.o: ${BUILD_DIR}/config.h
clock.o: ${BUILD_DIR}/config.h
eaccess.o: ${BUILD_DIR}/config.h
dprintf.o: ${BUILD_DIR}/config.h
fmtullong.o: ${BUILD_DIR}/config.h
fmtulong.o: ${BUILD_DIR}/config.h
fmtumax.o: ${BUILD_DIR}/config.h
fnxform.o: ${BUILD_DIR}/config.h
fpurge.o: ${BUILD_DIR}/config.h
getcwd.o: ${BUILD_DIR}/config.h
getenv.o: ${BUILD_DIR}/config.h
gettimeofday.o: ${BUILD_DIR}/config.h
inet_aton.o: ${BUILD_DIR}/config.h
input_avail.o: ${BUILD_DIR}/config.h
itos.o: ${BUILD_DIR}/config.h
mailstat.o: ${BUILD_DIR}/config.h
makepath.o: ${BUILD_DIR}/config.h
mbscasecmp.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
mbscmp.o: ${BUILD_DIR}/config.h
memset.o: ${BUILD_DIR}/config.h
mktime.o: ${BUILD_DIR}/config.h
netconn.o: ${BUILD_DIR}/config.h
netopen.o: ${BUILD_DIR}/config.h
oslib.o: ${BUILD_DIR}/config.h
pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
random.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shmatch.o: ${BUILD_DIR}/config.h
shmbchar.o: ${BUILD_DIR}/config.h
shquote.o: ${BUILD_DIR}/config.h
shtty.o: ${BUILD_DIR}/config.h
snprintf.o: ${BUILD_DIR}/config.h
spell.o: ${BUILD_DIR}/config.h
strcasecmp.o: ${BUILD_DIR}/config.h
strchrnul.o: ${BUILD_DIR}/config.h
strerror.o: ${BUILD_DIR}/config.h
strftime.o: ${BUILD_DIR}/config.h
strcasestr.o: ${BUILD_DIR}/config.h
stringlist.o: ${BUILD_DIR}/config.h
stringvec.o: ${BUILD_DIR}/config.h
strnlen.o: ${BUILD_DIR}/config.h
strpbrk.o: ${BUILD_DIR}/config.h
strtod.o: ${BUILD_DIR}/config.h
strtoimax.o: ${BUILD_DIR}/config.h
strtol.o: ${BUILD_DIR}/config.h
strtoll.o: ${BUILD_DIR}/config.h
strtoul.o: ${BUILD_DIR}/config.h
strtoull.o: ${BUILD_DIR}/config.h
strtoumax.o: ${BUILD_DIR}/config.h
strtrans.o: ${BUILD_DIR}/config.h
strvis.o: ${BUILD_DIR}/config.h
timers.o: ${BUILD_DIR}/config.h
times.o: ${BUILD_DIR}/config.h
timeval.o: ${BUILD_DIR}/config.h
tmpfile.o: ${BUILD_DIR}/config.h ${topdir}/config-top.h
uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
unicode.o: ${BUILD_DIR}/config.h
utf8.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
wcsnwidth.o: ${BUILD_DIR}/config.h
wcswidth.o: ${BUILD_DIR}/config.h
winsize.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
zgetline.o: ${BUILD_DIR}/config.h
zmapfd.o: ${BUILD_DIR}/config.h
zread.o: ${BUILD_DIR}/config.h
zwrite.o: ${BUILD_DIR}/config.h
clktck.o: ${topdir}/bashtypes.h
getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
getcwd.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
getcwd.o: ${BASHINCDIR}/memalloc.h ${BASHINCDIR}/ansi_stdlib.h
getenv.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
getenv.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
getenv.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#getenv.o: ${BUILD_DIR}/version.h
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
inet_aton.o: ${BASHINCDIR}/stdc.h
itos.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
itos.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
itos.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#itos.o: ${BUILD_DIR}/version.h
makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
makepath.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#makepath.o: ${BUILD_DIR}/version.h
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
netconn.o: ${topdir}/bashtypes.h
netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
#netopen.o: ${BUILD_DIR}/version.h
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#oslib.o: ${BUILD_DIR}/version.h
pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
pathcanon.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#pathcanon.o: ${BUILD_DIR}/version.h
pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
pathphys.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#pathphys.o: ${BUILD_DIR}/version.h
random.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
random.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
random.o: ${BASHINCDIR}/filecntl.h
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
rename.o: ${BASHINCDIR}/posixstat.h
setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h
setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h
eaccess.o: ${topdir}/bashtypes.h
eaccess.o: ${BASHINCDIR}/posixstat.h
eaccess.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
eaccess.o: ${BASHINCDIR}/filecntl.h
eaccess.o: ${BASHINCDIR}/stdc.h
eaccess.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
eaccess.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#eaccess.o: ${BUILD_DIR}/version.h
shmatch.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
shmatch.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
shmatch.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
shmatch.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
shmatch.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
shmatch.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
shmatch.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
shmatch.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
shmatch.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
shquote.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
shtty.o: ${BASHINCDIR}/shtty.h
shtty.o: ${BASHINCDIR}/stdc.h
snprintf.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h ${topdir}/xmalloc.h
snprintf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
snprintf.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
snprintf.o: ${BASHINCDIR}/typemax.h
spell.o: ${topdir}/bashtypes.h
spell.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
spell.o: ${BASHINCDIR}/ansi_stdlib.h
strcasecmp.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strerror.o: ${topdir}/bashtypes.h
strerror.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
strerror.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#strerror.o: ${BUILD_DIR}/version.h
strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
stringlist.o: ${topdir}/bashansi.h
stringlist.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
stringlist.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#stringlist.o: ${BUILD_DIR}/version.h
stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
stringvec.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#stringvec.o: ${BUILD_DIR}/version.h
strnlen.o: ${BASHINCDIR}/stdc.h
strpbrk.o: ${BASHINCDIR}/stdc.h
strtod.o: ${topdir}/bashansi.h
strtod.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoimax.o: ${BASHINCDIR}/stdc.h
strtol.o: ${topdir}/bashansi.h
strtol.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtol.o: ${BASHINCDIR}/typemax.h
strtoll.o: ${topdir}/bashansi.h
strtoll.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoll.o: ${BASHINCDIR}/typemax.h
strtoul.o: ${topdir}/bashansi.h
strtoul.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoul.o: ${BASHINCDIR}/typemax.h
strtoull.o: ${topdir}/bashansi.h
strtoull.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoull.o: ${BASHINCDIR}/typemax.h
strtoumax.o: ${BASHINCDIR}/stdc.h
strtrans.o: ${topdir}/bashansi.h
strtrans.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtrans.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
strtrans.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
strtrans.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
#strtrans.o: ${BUILD_DIR}/version.h
strvis.o: ${topdir}/bashansi.h
strvis.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strvis.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
strvis.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
times.o: ${BASHINCDIR}/systimes.h
times.o: ${BASHINCDIR}/posixtime.h
timeval.o: ${BASHINCDIR}/posixtime.h
gettimeofday.o: ${BASHINCDIR}/posixtime.h
tmpfile.o: ${topdir}/bashtypes.h
tmpfile.o: ${BASHINCDIR}/chartypes.h
tmpfile.o: ${BASHINCDIR}/posixstat.h
tmpfile.o: ${BASHINCDIR}/filecntl.h
tmpfile.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
tmpfile.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
tmpfile.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
tmpfile.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
tmpfile.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
tmpfile.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
tmpfile.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
uconvert.o: ${topdir}/bashtypes.h
uconvert.o: ${BASHINCDIR}/chartypes.h
uconvert.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
uconvert.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
uconvert.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
uconvert.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
uconvert.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
uconvert.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
uconvert.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
ufuncs.o: ${topdir}/bashtypes.h
clock.o: ${BASHINCDIR}/posixtime.h
mailstat.o: ${topdir}/bashansi.h
mailstat.o: ${topdir}/bashtypes.h
mailstat.o: ${BASHINCDIR}/ansi_stdlib.h
mailstat.o: ${BASHINCDIR}/posixstat.h
mailstat.o: ${BASHINCDIR}/posixdir.h
mailstat.o: ${BASHINCDIR}/maxpath.h
fmtulong.o: ${topdir}/bashansi.h
fmtulong.o: ${BASHINCDIR}/ansi_stdlib.h
fmtulong.o: ${BASHINCDIR}/chartypes.h
fmtulong.o: ${BASHINCDIR}/stdc.h
fmtulong.o: ${BASHINCDIR}/typemax.h
fmtulong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fmtullong.o: ${topdir}/bashansi.h
fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h
fmtullong.o: ${BASHINCDIR}/chartypes.h
fmtullong.o: ${BASHINCDIR}/stdc.h
fmtullong.o: ${BASHINCDIR}/typemax.h
fmtullong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fmtumax.o: ${topdir}/bashansi.h
fmtumax.o: ${BASHINCDIR}/ansi_stdlib.h
fmtumax.o: ${BASHINCDIR}/chartypes.h
fmtumax.o: ${BASHINCDIR}/stdc.h
fmtumax.o: ${BASHINCDIR}/typemax.h
fmtumax.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
wcsnwidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsnwidth.o: ${BASHINCDIR}/stdc.h
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcswidth.o: ${BASHINCDIR}/stdc.h
mbschr.o: ${topdir}/bashansi.h
mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
mbschr.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zgetline.o: ${BASHINCDIR}/stdc.h
zgetline.o: ${topdir}/xmalloc.h
zgetline.o: ${topdir}/bashtypes.h
mbscasecmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mbscasecmp.o: ${BASHINCDIR}/stdc.h
mbscasecmp.o: ${topdir}/xmalloc.h
mbscmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mbscmp.o: ${BASHINCDIR}/stdc.h
mbscmp.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
casemod.o: ${BASHINCDIR}/stdc.h
casemod.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
dprintf.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
input_avail.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/xmalloc.h ${BASHINCDIR}/posixselect.h
mktime.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mktime.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
fnxform.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashtypes.h
fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
shmbchar.o: ${BASHINCDIR}/shmbchar.h
shmbchar.o: ${BASHINCDIR}/shmbutil.h
timers.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
timers.o: ${BASHINCDIR}/stdc.h
timers.o: ${topdir}/xmalloc.h ${topdir}/sig.h
timers.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/stat-time.h
timers.o: ${BASHINCDIR}/posixselect.h
timers.o: ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
timers.o: ${BASHINCDIR}/timer.h
unicode.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
unicode.o: ${BASHINCDIR}/stdc.h
unicode.o: ${topdir}/xmalloc.h
utf8.o: ${topdir}/bashansi.h
utf8.o: ${BASHINCDIR}/ansi_stdlib.h
utf8.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
winsize.o: ${BASHINCDIR}/stdc.h
winsize.o: ${topdir}/xmalloc.h
winsize.o: ${topdir}/bashtypes.h
zmapfd.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zmapfd.o: ${BASHINCDIR}/stdc.h
zmapfd.o: ${topdir}/command.h
zmapfd.o: ${topdir}/general.h
zmapfd.o: ${topdir}/bashtypes.h ${BASHINCDIR}/chartypes.h ${topdir}/xmalloc.h

271
lib/sh/casemod.c Normal file
View file

@ -0,0 +1,271 @@
/* casemod.c -- functions to change case of strings */
/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdc.h>
#include <bashansi.h>
#include <bashintl.h>
#include <bashtypes.h>
#include <stdio.h>
#include <ctype.h>
#include <xmalloc.h>
#include <shmbchar.h>
#include <shmbutil.h>
#include <chartypes.h>
#include <typemax.h>
#include <glob/strmatch.h>
#define _to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc))
#define _to_wlower(wc) (iswupper (wc) ? towlower (wc) : (wc))
#if !defined (HANDLE_MULTIBYTE)
# define cval(s, i, l) ((s)[(i)])
# define iswalnum(c) (isalnum(c))
# define TOGGLE(x) (ISUPPER (x) ? tolower ((unsigned char)x) : (TOUPPER (x)))
#else
# define TOGGLE(x) (iswupper (x) ? towlower (x) : (_to_wupper(x)))
#endif
/* These must agree with the defines in externs.h */
#define CASE_NOOP 0x0000
#define CASE_LOWER 0x0001
#define CASE_UPPER 0x0002
#define CASE_CAPITALIZE 0x0004
#define CASE_UNCAP 0x0008
#define CASE_TOGGLE 0x0010
#define CASE_TOGGLEALL 0x0020
#define CASE_UPFIRST 0x0040
#define CASE_LOWFIRST 0x0080
#define CASE_USEWORDS 0x1000 /* modify behavior to act on words in passed string */
extern char *substring PARAMS((char *, int, int));
#ifndef UCHAR_MAX
# define UCHAR_MAX TYPE_MAXIMUM(unsigned char)
#endif
#if defined (HANDLE_MULTIBYTE)
static wchar_t
cval (s, i, l)
char *s;
int i, l;
{
size_t tmp;
wchar_t wc;
mbstate_t mps;
if (MB_CUR_MAX == 1 || is_basic (s[i]))
return ((wchar_t)s[i]);
if (i >= (l - 1))
return ((wchar_t)s[i]);
memset (&mps, 0, sizeof (mbstate_t));
tmp = mbrtowc (&wc, s + i, l - i, &mps);
if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))
return ((wchar_t)s[i]);
return wc;
}
#endif
/* Modify the case of characters in STRING matching PAT based on the value of
FLAGS. If PAT is null, modify the case of each character */
char *
sh_modcase (string, pat, flags)
const char *string;
char *pat;
int flags;
{
int start, next, end, retind;
int inword, c, nc, nop, match, usewords;
char *ret, *s;
wchar_t wc;
int mb_cur_max;
#if defined (HANDLE_MULTIBYTE)
wchar_t nwc;
char mb[MB_LEN_MAX+1];
int mlen;
size_t m;
mbstate_t state;
#endif
if (string == 0 || *string == 0)
{
ret = (char *)xmalloc (1);
ret[0] = '\0';
return ret;
}
#if defined (HANDLE_MULTIBYTE)
memset (&state, 0, sizeof (mbstate_t));
#endif
start = 0;
end = strlen (string);
mb_cur_max = MB_CUR_MAX;
ret = (char *)xmalloc (2*end + 1);
retind = 0;
/* See if we are supposed to split on alphanumerics and operate on each word */
usewords = (flags & CASE_USEWORDS);
flags &= ~CASE_USEWORDS;
inword = 0;
while (start < end)
{
wc = cval ((char *)string, start, end);
if (iswalnum (wc) == 0)
inword = 0;
if (pat)
{
next = start;
ADVANCE_CHAR (string, end, next);
s = substring ((char *)string, start, next);
match = strmatch (pat, s, FNM_EXTMATCH) != FNM_NOMATCH;
free (s);
if (match == 0)
{
/* copy unmatched portion */
memcpy (ret + retind, string + start, next - start);
retind += next - start;
start = next;
inword = 1;
continue;
}
}
/* XXX - for now, the toggling operators work on the individual
words in the string, breaking on alphanumerics. Should I
leave the capitalization operators to do that also? */
if (flags == CASE_CAPITALIZE)
{
if (usewords)
nop = inword ? CASE_LOWER : CASE_UPPER;
else
nop = (start > 0) ? CASE_LOWER : CASE_UPPER;
inword = 1;
}
else if (flags == CASE_UNCAP)
{
if (usewords)
nop = inword ? CASE_UPPER : CASE_LOWER;
else
nop = (start > 0) ? CASE_UPPER : CASE_LOWER;
inword = 1;
}
else if (flags == CASE_UPFIRST)
{
if (usewords)
nop = inword ? CASE_NOOP : CASE_UPPER;
else
nop = (start > 0) ? CASE_NOOP : CASE_UPPER;
inword = 1;
}
else if (flags == CASE_LOWFIRST)
{
if (usewords)
nop = inword ? CASE_NOOP : CASE_LOWER;
else
nop = (start > 0) ? CASE_NOOP : CASE_LOWER;
inword = 1;
}
else if (flags == CASE_TOGGLE)
{
nop = inword ? CASE_NOOP : CASE_TOGGLE;
inword = 1;
}
else
nop = flags;
/* Can't short-circuit, some locales have multibyte upper and lower
case equivalents of single-byte ascii characters (e.g., Turkish) */
if (mb_cur_max == 1)
{
singlebyte:
switch (nop)
{
default:
case CASE_NOOP: nc = wc; break;
case CASE_UPPER: nc = TOUPPER (wc); break;
case CASE_LOWER: nc = TOLOWER (wc); break;
case CASE_TOGGLEALL:
case CASE_TOGGLE: nc = TOGGLE (wc); break;
}
ret[retind++] = nc;
}
#if defined (HANDLE_MULTIBYTE)
else
{
m = mbrtowc (&wc, string + start, end - start, &state);
/* Have to go through wide case conversion even for single-byte
chars, to accommodate single-byte characters where the
corresponding upper or lower case equivalent is multibyte. */
if (MB_INVALIDCH (m))
{
wc = (unsigned char)string[start];
goto singlebyte;
}
else if (MB_NULLWCH (m))
wc = L'\0';
switch (nop)
{
default:
case CASE_NOOP: nwc = wc; break;
case CASE_UPPER: nwc = _to_wupper (wc); break;
case CASE_LOWER: nwc = _to_wlower (wc); break;
case CASE_TOGGLEALL:
case CASE_TOGGLE: nwc = TOGGLE (wc); break;
}
/* We don't have to convert `wide' characters that are in the
unsigned char range back to single-byte `multibyte' characters. */
if ((int)nwc <= UCHAR_MAX && is_basic ((int)nwc))
ret[retind++] = nwc;
else
{
mlen = wcrtomb (mb, nwc, &state);
if (mlen > 0)
mb[mlen] = '\0';
/* Don't assume the same width */
strncpy (ret + retind, mb, mlen);
retind += mlen;
}
}
#endif
ADVANCE_CHAR (string, end, start);
}
ret[retind] = '\0';
return ret;
}

61
lib/sh/clktck.c Normal file
View file

@ -0,0 +1,61 @@
/* clktck.c - get the value of CLK_TCK. */
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK)
# if !defined (CLK_TCK)
# if defined (HZ)
# define CLK_TCK HZ
# else
# define CLK_TCK 60
# endif
# endif /* !CLK_TCK */
#endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */
long
get_clk_tck ()
{
static long retval = 0;
if (retval != 0)
return (retval);
#if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK)
retval = sysconf (_SC_CLK_TCK);
#else /* !SYSCONF || !_SC_CLK_TCK */
retval = CLK_TCK;
#endif /* !SYSCONF || !_SC_CLK_TCK */
return (retval);
}

87
lib/sh/clock.c Normal file
View file

@ -0,0 +1,87 @@
/* clock.c - operations on struct tms and clock_t's */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_TIMES)
#include <sys/types.h>
#include <posixtime.h>
#if defined (HAVE_SYS_TIMES_H)
# include <sys/times.h>
#endif
#include <stdio.h>
#include <stdc.h>
#include <bashintl.h>
#ifndef locale_decpoint
extern int locale_decpoint PARAMS((void));
#endif
extern long get_clk_tck PARAMS((void));
void
clock_t_to_secs (t, sp, sfp)
clock_t t;
time_t *sp;
int *sfp;
{
static long clk_tck = -1;
if (clk_tck == -1)
clk_tck = get_clk_tck ();
*sfp = t % clk_tck;
*sfp = (*sfp * 1000) / clk_tck;
*sp = t / clk_tck;
/* Sanity check */
if (*sfp >= 1000)
{
*sp += 1;
*sfp -= 1000;
}
}
/* Print the time defined by a clock_t (returned by the `times' and `time'
system calls) in a standard way to stdio stream FP. This is scaled in
terms of the value of CLK_TCK, which is what is returned by the
`times' call. */
void
print_clock_t (fp, t)
FILE *fp;
clock_t t;
{
time_t timestamp;
long minutes;
int seconds, seconds_fraction;
clock_t_to_secs (t, &timestamp, &seconds_fraction);
minutes = timestamp / 60;
seconds = timestamp % 60;
fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint(), seconds_fraction);
}
#endif /* HAVE_TIMES */

70
lib/sh/dprintf.c Normal file
View file

@ -0,0 +1,70 @@
/* dprintf -- printf to a file descriptor */
/* Copyright (C) 2008-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdc.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <stdio.h>
int
#if defined (PREFER_STDARG)
dprintf(int fd, const char *format, ...)
#else
dprintf(fd, format, va_alist)
int fd;
const char *format;
va_dcl
#endif
{
FILE *fp;
int fd2, rc, r2;
va_list args;
if ((fd2 = dup(fd)) < 0)
return -1;
fp = fdopen (fd2, "w");
if (fp == 0)
{
close (fd2);
return -1;
}
SH_VA_START (args, format);
rc = vfprintf (fp, format, args);
fflush (fp);
va_end (args);
r2 = fclose (fp); /* check here */
return rc;
}

244
lib/sh/eaccess.c Normal file
View file

@ -0,0 +1,244 @@
/* eaccess.c - eaccess replacement for the shell, plus other access functions. */
/* Copyright (C) 2006-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdio.h>
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif /* !_POSIX_VERSION */
#include "posixstat.h"
#include "filecntl.h"
#include "shell.h"
#if !defined (R_OK)
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif /* R_OK */
static int path_is_devfd PARAMS((const char *));
static int sh_stataccess PARAMS((const char *, int));
#if HAVE_DECL_SETREGID
static int sh_euidaccess PARAMS((const char *, int));
#endif
static int
path_is_devfd (path)
const char *path;
{
if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
return 1;
else if (STREQN (path, "/dev/std", 8))
{
if (STREQ (path+8, "in") || STREQ (path+8, "out") || STREQ (path+8, "err"))
return 1;
else
return 0;
}
else
return 0;
}
/* A wrapper for stat () which disallows pathnames that are empty strings
and handles /dev/fd emulation on systems that don't have it. */
int
sh_stat (path, finfo)
const char *path;
struct stat *finfo;
{
static char *pbuf = 0;
if (*path == '\0')
{
errno = ENOENT;
return (-1);
}
if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
{
/* If stating /dev/fd/n doesn't produce the same results as fstat of
FD N, then define DEV_FD_STAT_BROKEN */
#if !defined (HAVE_DEV_FD) || defined (DEV_FD_STAT_BROKEN)
intmax_t fd;
int r;
if (legal_number (path + 8, &fd) && fd == (int)fd)
{
r = fstat ((int)fd, finfo);
if (r == 0 || errno != EBADF)
return (r);
}
errno = ENOENT;
return (-1);
#else
/* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
On most systems, with the notable exception of linux, this is
effectively a no-op. */
pbuf = xrealloc (pbuf, sizeof (DEV_FD_PREFIX) + strlen (path + 8));
strcpy (pbuf, DEV_FD_PREFIX);
strcat (pbuf, path + 8);
return (stat (pbuf, finfo));
#endif /* !HAVE_DEV_FD */
}
#if !defined (HAVE_DEV_STDIN)
else if (STREQN (path, "/dev/std", 8))
{
if (STREQ (path+8, "in"))
return (fstat (0, finfo));
else if (STREQ (path+8, "out"))
return (fstat (1, finfo));
else if (STREQ (path+8, "err"))
return (fstat (2, finfo));
else
return (stat (path, finfo));
}
#endif /* !HAVE_DEV_STDIN */
return (stat (path, finfo));
}
/* Do the same thing access(2) does, but use the effective uid and gid,
and don't make the mistake of telling root that any file is
executable. This version uses stat(2). */
static int
sh_stataccess (path, mode)
const char *path;
int mode;
{
struct stat st;
if (sh_stat (path, &st) < 0)
return (-1);
if (current_user.euid == 0)
{
/* Root can read or write any file. */
if ((mode & X_OK) == 0)
return (0);
/* Root can execute any file that has any one of the execute
bits set. */
if (st.st_mode & S_IXUGO)
return (0);
}
if (st.st_uid == current_user.euid) /* owner */
mode <<= 6;
else if (group_member (st.st_gid))
mode <<= 3;
if (st.st_mode & mode)
return (0);
errno = EACCES;
return (-1);
}
#if HAVE_DECL_SETREGID
/* Version to call when uid != euid or gid != egid. We temporarily swap
the effective and real uid and gid as appropriate. */
static int
sh_euidaccess (path, mode)
const char *path;
int mode;
{
int r, e;
if (current_user.uid != current_user.euid)
setreuid (current_user.euid, current_user.uid);
if (current_user.gid != current_user.egid)
setregid (current_user.egid, current_user.gid);
r = access (path, mode);
e = errno;
if (current_user.uid != current_user.euid)
setreuid (current_user.uid, current_user.euid);
if (current_user.gid != current_user.egid)
setregid (current_user.gid, current_user.egid);
errno = e;
return r;
}
#endif
int
sh_eaccess (path, mode)
const char *path;
int mode;
{
int ret;
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
#if (defined (HAVE_FACCESSAT) && defined (AT_EACCESS)) || defined (HAVE_EACCESS)
# if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
ret = faccessat (AT_FDCWD, path, mode, AT_EACCESS);
# else /* HAVE_EACCESS */ /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
# endif /* HAVE_EACCESS */
# if defined (__FreeBSD__) || defined (SOLARIS) || defined (_AIX)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
# endif /* __FreeBSD__ || SOLARIS || _AIX */
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
#else
if (mode == F_OK)
return (sh_stataccess (path, mode));
# if HAVE_DECL_SETREGID
if (current_user.uid != current_user.euid || current_user.gid != current_user.egid)
return (sh_euidaccess (path, mode));
# endif
if (current_user.uid == current_user.euid && current_user.gid == current_user.egid)
{
ret = access (path, mode);
#if defined (__FreeBSD__) || defined (SOLARIS)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
#endif
return ret;
}
return (sh_stataccess (path, mode));
#endif
}

31
lib/sh/fmtullong.c Normal file
View file

@ -0,0 +1,31 @@
/* fmtullong.c - convert `long long int' to string */
/* Copyright (C) 2001-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifdef HAVE_LONG_LONG_INT
#define LONG long long
#define UNSIGNED_LONG unsigned long long
#define fmtulong fmtullong
#include "fmtulong.c"
#endif

191
lib/sh/fmtulong.c Normal file
View file

@ -0,0 +1,191 @@
/* fmtulong.c -- Convert unsigned long int to string. */
/* Copyright (C) 1998-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#include <bashansi.h>
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <chartypes.h>
#include <errno.h>
#include <bashintl.h>
#include "stdc.h"
#include <typemax.h>
#ifndef errno
extern int errno;
#endif
#define x_digs "0123456789abcdef"
#define X_digs "0123456789ABCDEF"
/* XXX -- assumes uppercase letters, lowercase letters, and digits are
contiguous */
#define FMTCHAR(x) \
((x) < 10) ? (x) + '0' \
: (((x) < 36) ? (x) - 10 + 'a' \
: (((x) < 62) ? (x) - 36 + 'A' \
: (((x) == 62) ? '@' : '_')))
#ifndef FL_PREFIX
# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
# define FL_ADDBASE 0x02 /* add base# prefix to converted value */
# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
# define FL_UNSIGNED 0x08 /* don't add any sign */
#endif
#ifndef LONG
# define LONG long
# define UNSIGNED_LONG unsigned long
#endif
/* `unsigned long' (or unsigned long long) to string conversion for a given
base. The caller passes the output buffer and the size. This should
check for buffer underflow, but currently does not. */
char *
fmtulong (ui, base, buf, len, flags)
UNSIGNED_LONG ui;
int base;
char *buf;
size_t len;
int flags;
{
char *p;
int sign;
LONG si;
if (base == 0)
base = 10;
if (base < 2 || base > 64)
{
#if 1
/* XXX - truncation possible with long translation */
strncpy (buf, _("invalid base"), len - 1);
buf[len-1] = '\0';
errno = EINVAL;
return (p = buf);
#else
base = 10;
#endif
}
sign = 0;
if ((flags & FL_UNSIGNED) == 0 && (LONG)ui < 0)
{
ui = -ui;
sign = '-';
}
p = buf + len - 2;
p[1] = '\0';
/* handle common cases explicitly */
switch (base)
{
case 10:
if (ui < 10)
{
*p-- = TOCHAR (ui);
break;
}
/* Favor signed arithmetic over unsigned arithmetic; it is faster on
many machines. */
if ((LONG)ui < 0)
{
*p-- = TOCHAR (ui % 10);
si = ui / 10;
}
else
si = ui;
do
*p-- = TOCHAR (si % 10);
while (si /= 10);
break;
case 8:
do
*p-- = TOCHAR (ui & 7);
while (ui >>= 3);
break;
case 16:
do
*p-- = (flags & FL_HEXUPPER) ? X_digs[ui & 15] : x_digs[ui & 15];
while (ui >>= 4);
break;
case 2:
do
*p-- = TOCHAR (ui & 1);
while (ui >>= 1);
break;
default:
do
*p-- = FMTCHAR (ui % base);
while (ui /= base);
break;
}
if ((flags & FL_PREFIX) && (base == 8 || base == 16))
{
if (base == 16)
{
*p-- = (flags & FL_HEXUPPER) ? 'X' : 'x';
*p-- = '0';
}
else if (p[1] != '0')
*p-- = '0';
}
else if ((flags & FL_ADDBASE) && base != 10)
{
*p-- = '#';
*p-- = TOCHAR (base % 10);
if (base > 10)
*p-- = TOCHAR (base / 10);
}
if (sign)
*p-- = '-';
return (p + 1);
}

27
lib/sh/fmtumax.c Normal file
View file

@ -0,0 +1,27 @@
/* fmtumax.c -- Convert uintmax_t to string. */
/* Copyright (C) 2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#define LONG intmax_t
#define UNSIGNED_LONG uintmax_t
#define fmtulong fmtumax
#include "fmtulong.c"

199
lib/sh/fnxform.c Normal file
View file

@ -0,0 +1,199 @@
/* fnxform - use iconv(3) to transform strings to and from "filename" format */
/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include "bashtypes.h"
#include "stdc.h"
#include "bashintl.h"
#include <xmalloc.h>
#if defined (HAVE_ICONV)
# include <iconv.h>
#endif
#if defined (HAVE_LOCALE_CHARSET)
extern const char *locale_charset PARAMS((void));
#else
extern char *get_locale_var PARAMS((char *));
#endif
#if defined (HAVE_ICONV)
static iconv_t conv_fromfs = (iconv_t)-1;
static iconv_t conv_tofs = (iconv_t)-1;
#define OUTLEN_MAX 4096
static char *outbuf = 0;
static size_t outlen = 0;
static char *curencoding PARAMS((void));
static void init_tofs PARAMS((void));
static void init_fromfs PARAMS((void));
static char *
curencoding ()
{
char *loc;
#if defined (HAVE_LOCALE_CHARSET)
loc = (char *)locale_charset ();
return loc;
#else
char *dot, *mod;
loc = get_locale_var ("LC_CTYPE");
if (loc == 0 || *loc == 0)
return "";
dot = strchr (loc, '.');
if (dot == 0)
return loc;
mod = strchr (dot, '@');
if (mod)
*mod = '\0';
return ++dot;
#endif
}
static void
init_tofs ()
{
char *cur;
cur = curencoding ();
conv_tofs = iconv_open ("UTF-8-MAC", cur);
}
static void
init_fromfs ()
{
char *cur;
cur = curencoding ();
conv_fromfs = iconv_open (cur, "UTF-8-MAC");
}
char *
fnx_tofs (string, len)
char *string;
size_t len;
{
#ifdef MACOSX
ICONV_CONST char *inbuf;
char *tempbuf;
size_t templen;
if (conv_tofs == (iconv_t)-1)
init_tofs ();
if (conv_tofs == (iconv_t)-1)
return string;
/* Free and reallocate outbuf if it's *too* big */
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
{
free (outbuf);
outbuf = 0;
outlen = 0;
}
inbuf = string;
if (outbuf == 0 || outlen < len + 8)
{
outlen = len + 8;
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
}
tempbuf = outbuf;
templen = outlen;
iconv (conv_tofs, NULL, NULL, NULL, NULL);
if (iconv (conv_tofs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
return string;
*tempbuf = '\0';
return outbuf;
#else
return string;
#endif
}
char *
fnx_fromfs (string, len)
char *string;
size_t len;
{
#ifdef MACOSX
ICONV_CONST char *inbuf;
char *tempbuf;
size_t templen;
if (conv_fromfs == (iconv_t)-1)
init_fromfs ();
if (conv_fromfs == (iconv_t)-1)
return string;
/* Free and reallocate outbuf if it's *too* big */
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
{
free (outbuf);
outbuf = 0;
outlen = 0;
}
inbuf = string;
if (outbuf == 0 || outlen < (len + 8))
{
outlen = len + 8;
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
}
tempbuf = outbuf;
templen = outlen;
iconv (conv_fromfs, NULL, NULL, NULL, NULL);
if (iconv (conv_fromfs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
return string;
*tempbuf = '\0';
return outbuf;
#else
return string;
#endif
}
#else
char *
fnx_tofs (string)
char *string;
{
return string;
}
char *
fnx_fromfs (string)
char *string;
{
return string;
}
#endif

232
lib/sh/fpurge.c Normal file
View file

@ -0,0 +1,232 @@
/* fpurge - Flushing buffers of a FILE stream. */
/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "stdc.h"
#include <stdio.h>
/* Specification. Same as in ../../externs.h. */
#define NEED_FPURGE_DECL
#if HAVE_FPURGE
# define fpurge _bash_fpurge
#endif
extern int fpurge PARAMS((FILE *stream));
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
# include <stdio_ext.h>
#endif
#include <stdlib.h>
/* Inline contents of gnulib:stdio-impl.h */
/* Many stdio implementations have the same logic and therefore can share
the same implementation of stdio extension API, except that some fields
have different naming conventions, or their access requires some casts. */
/* BSD stdio derived implementations. */
#if defined __NetBSD__ /* NetBSD */
/* Get __NetBSD_Version__. */
# include <sys/param.h>
#endif
#if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
# if defined __DragonFly__ /* DragonFly */
/* See <http://www.dragonflybsd.org/cvsweb/src/lib/libc/stdio/priv_stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
# define fp_ ((struct { struct __FILE_public pub; \
struct { unsigned char *_base; int _size; } _bf; \
void *cookie; \
void *_close; \
void *_read; \
void *_seek; \
void *_write; \
struct { unsigned char *_base; int _size; } _ub; \
int _ur; \
unsigned char _ubuf[3]; \
unsigned char _nbuf[1]; \
struct { unsigned char *_base; int _size; } _lb; \
int _blksize; \
fpos_t _offset; \
/* More fields, not relevant here. */ \
} *) fp)
/* See <http://www.dragonflybsd.org/cvsweb/src/include/stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
# define _p pub._p
# define _flags pub._flags
# define _r pub._r
# define _w pub._w
# else
# define fp_ fp
# endif
# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ /* NetBSD >= 1.5ZA, OpenBSD */
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
struct __sfileext
{
struct __sbuf _ub; /* ungetc buffer */
/* More fields, not relevant here. */
};
# define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub
# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, MacOS X, Cygwin */
# define fp_ub fp_->_ub
# endif
# define HASUB(fp) (fp_ub._base != NULL)
#endif
/* SystemV derived implementations. */
#if defined _IOERR
# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
# define fp_ ((struct { unsigned char *_ptr; \
unsigned char *_base; \
unsigned char *_end; \
long _cnt; \
int _file; \
unsigned int _flag; \
} *) fp)
# else
# define fp_ fp
# endif
# if defined _SCO_DS /* OpenServer */
# define _cnt __cnt
# define _ptr __ptr
# define _base __base
# define _flag __flag
# endif
#endif
int
fpurge (FILE *fp)
{
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
__fpurge (fp);
/* The __fpurge function does not have a return value. */
return 0;
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin 1.7 */
/* Call the system's fpurge function. */
# undef fpurge
# if !HAVE_DECL_FPURGE
extern int fpurge (FILE *);
# endif
int result = fpurge (fp);
# if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
if (result == 0)
/* Correct the invariants that fpurge broke.
<stdio.h> on BSD systems says:
"The following always hold: if _flags & __SRD, _w is 0."
If this invariant is not fulfilled and the stream is read-write but
currently reading, subsequent putc or fputc calls will write directly
into the buffer, although they shouldn't be allowed to. */
if ((fp_->_flags & __SRD) != 0)
fp_->_w = 0;
# endif
return result;
#else
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
fp->_IO_read_end = fp->_IO_read_ptr;
fp->_IO_write_ptr = fp->_IO_write_base;
/* Avoid memory leak when there is an active ungetc buffer. */
if (fp->_IO_save_base != NULL)
{
free (fp->_IO_save_base);
fp->_IO_save_base = NULL;
}
return 0;
# elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
fp_->_p = fp_->_bf._base;
fp_->_r = 0;
fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
? fp_->_bf._size
: 0);
/* Avoid memory leak when there is an active ungetc buffer. */
if (fp_ub._base != NULL)
{
if (fp_ub._base != fp_->_ubuf)
free (fp_ub._base);
fp_ub._base = NULL;
}
return 0;
# elif defined __EMX__ /* emx+gcc */
fp->_ptr = fp->_buffer;
fp->_rcount = 0;
fp->_wcount = 0;
fp->_ungetc_count = 0;
return 0;
# elif defined _IOERR || defined __TANDEM /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
fp->_ptr = fp->_base;
if (fp->_ptr != NULL)
fp->_cnt = 0;
return 0;
# elif defined __UCLIBC__ /* uClibc */
# ifdef __STDIO_BUFFERS
if (fp->__modeflags & __FLAG_WRITING)
fp->__bufpos = fp->__bufstart;
else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
fp->__bufpos = fp->__bufread;
# endif
return 0;
# elif defined __QNX__ /* QNX */
fp->_Rback = fp->_Back + sizeof (fp->_Back);
fp->_Rsave = NULL;
if (fp->_Mode & 0x2000 /* _MWRITE */)
/* fp->_Buf <= fp->_Next <= fp->_Wend */
fp->_Next = fp->_Buf;
else
/* fp->_Buf <= fp->_Next <= fp->_Rend */
fp->_Rend = fp->_Next;
return 0;
# elif defined __MINT__ /* Atari FreeMiNT */
if (fp->__pushed_back)
{
fp->__bufp = fp->__pushback_bufp;
fp->__pushed_back = 0;
}
/* Preserve the current file position. */
if (fp->__target != -1)
fp->__target += fp->__bufp - fp->__buffer;
fp->__bufp = fp->__buffer;
/* Nothing in the buffer, next getc is nontrivial. */
fp->__get_limit = fp->__bufp;
/* Nothing in the buffer, next putc is nontrivial. */
fp->__put_limit = fp->__buffer;
return 0;
# else
# warning "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
return 0;
# endif
#endif
}

356
lib/sh/getcwd.c Normal file
View file

@ -0,0 +1,356 @@
/* getcwd.c -- get pathname of current directory */
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_GETCWD)
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
#pragma alloca
#endif /* _AIX && RISC6000 && !__GNUC__ */
#if defined (__QNX__)
# undef HAVE_LSTAT
#endif
#include <bashtypes.h>
#include <errno.h>
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <posixdir.h>
#include <posixstat.h>
#include <maxpath.h>
#include <memalloc.h>
#include <bashansi.h>
#if !defined (D_FILENO_AVAILABLE)
# include "command.h"
# include "general.h"
# include "externs.h"
#endif
#include <xmalloc.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if !defined (HAVE_LSTAT)
# define lstat stat
#endif
#if !defined (NULL)
# define NULL 0
#endif
/* If the d_fileno member of a struct dirent doesn't return anything useful,
we need to check inode number equivalence the hard way. Return 1 if
the inode corresponding to PATH/DIR is identical to THISINO. */
#if !defined (D_FILENO_AVAILABLE)
static int
_path_checkino (dotp, name, thisino)
char *dotp;
char *name;
ino_t thisino;
{
char *fullpath;
int r, e;
struct stat st;
e = errno;
fullpath = sh_makepath (dotp, name, MP_RMDOT);
if (stat (fullpath, &st) < 0)
{
errno = e;
return 0;
}
free (fullpath);
errno = e;
return (st.st_ino == thisino);
}
#endif
/* Get the pathname of the current working directory,
and put it in SIZE bytes of BUF. Returns NULL if the
directory couldn't be determined or SIZE was too small.
If successful, returns BUF. In GNU, if BUF is NULL,
an array is allocated with `malloc'; the array is SIZE
bytes long, unless SIZE <= 0, in which case it is as
big as necessary. */
#if defined (__STDC__)
char *
getcwd (char *buf, size_t size)
#else /* !__STDC__ */
char *
getcwd (buf, size)
char *buf;
size_t size;
#endif /* !__STDC__ */
{
static const char dots[]
= "../../../../../../../../../../../../../../../../../../../../../../../\
../../../../../../../../../../../../../../../../../../../../../../../../../../\
../../../../../../../../../../../../../../../../../../../../../../../../../..";
const char *dotp, *dotlist;
size_t dotsize;
dev_t rootdev, thisdev;
ino_t rootino, thisino;
char path[PATH_MAX + 1];
register char *pathp;
char *pathbuf;
size_t pathsize;
struct stat st;
int saved_errno;
if (buf != NULL && size == 0)
{
errno = EINVAL;
return ((char *)NULL);
}
pathsize = sizeof (path);
pathp = &path[pathsize];
*--pathp = '\0';
pathbuf = path;
if (stat (".", &st) < 0)
return ((char *)NULL);
thisdev = st.st_dev;
thisino = st.st_ino;
if (stat ("/", &st) < 0)
return ((char *)NULL);
rootdev = st.st_dev;
rootino = st.st_ino;
saved_errno = 0;
dotsize = sizeof (dots) - 1;
dotp = &dots[sizeof (dots)];
dotlist = dots;
while (!(thisdev == rootdev && thisino == rootino))
{
register DIR *dirstream;
register struct dirent *d;
dev_t dotdev;
ino_t dotino;
char mount_point;
int namlen;
/* Look at the parent directory. */
if (dotp == dotlist)
{
/* My, what a deep directory tree you have, Grandma. */
char *new;
if (dotlist == dots)
{
new = (char *)malloc (dotsize * 2 + 1);
if (new == NULL)
goto lose;
memcpy (new, dots, dotsize);
}
else
{
new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
if (new == NULL)
goto lose;
}
memcpy (&new[dotsize], new, dotsize);
dotp = &new[dotsize];
dotsize *= 2;
new[dotsize] = '\0';
dotlist = new;
}
dotp -= 3;
/* Figure out if this directory is a mount point. */
if (stat (dotp, &st) < 0)
goto lose;
dotdev = st.st_dev;
dotino = st.st_ino;
mount_point = dotdev != thisdev;
/* Search for the last directory. */
dirstream = opendir (dotp);
if (dirstream == NULL)
goto lose;
while ((d = readdir (dirstream)) != NULL)
{
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
#if defined (D_FILENO_AVAILABLE)
if (mount_point || d->d_fileno == thisino)
#else
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
#endif
{
char *name;
namlen = D_NAMLEN(d);
name = (char *)
alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
memcpy (name, dotp, dotlist + dotsize - dotp);
name[dotlist + dotsize - dotp] = '/';
memcpy (&name[dotlist + dotsize - dotp + 1],
d->d_name, namlen + 1);
if (lstat (name, &st) < 0)
{
#if 0
int save = errno;
(void) closedir (dirstream);
errno = save;
goto lose;
#else
saved_errno = errno;
#endif
}
if (st.st_dev == thisdev && st.st_ino == thisino)
break;
}
}
if (d == NULL)
{
#if 0
int save = errno;
#else
int save = errno ? errno : saved_errno;
#endif
(void) closedir (dirstream);
errno = save;
goto lose;
}
else
{
size_t space;
while ((space = pathp - pathbuf) <= namlen)
{
char *new;
if (pathbuf == path)
{
new = (char *)malloc (pathsize * 2);
if (!new)
goto lose;
}
else
{
new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
if (!new)
goto lose;
pathp = new + space;
}
(void) memcpy (new + pathsize + space, pathp, pathsize - space);
pathp = new + pathsize + space;
pathbuf = new;
pathsize *= 2;
}
pathp -= namlen;
(void) memcpy (pathp, d->d_name, namlen);
*--pathp = '/';
(void) closedir (dirstream);
}
thisdev = dotdev;
thisino = dotino;
}
if (pathp == &path[sizeof(path) - 1])
*--pathp = '/';
if (dotlist != dots)
free ((PTR_T) dotlist);
{
size_t len = pathbuf + pathsize - pathp;
if (buf == NULL && size <= 0)
size = len;
if ((size_t) size < len)
{
errno = ERANGE;
goto lose2;
}
if (buf == NULL)
{
buf = (char *) malloc (size);
if (buf == NULL)
goto lose2;
}
(void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
}
if (pathbuf != path)
free (pathbuf);
return (buf);
lose:
if ((dotlist != dots) && dotlist)
{
int e = errno;
free ((PTR_T) dotlist);
errno = e;
}
lose2:
if ((pathbuf != path) && pathbuf)
{
int e = errno;
free ((PTR_T) pathbuf);
errno = e;
}
return ((char *)NULL);
}
#if defined (TEST)
# include <stdio.h>
main (argc, argv)
int argc;
char **argv;
{
char b[PATH_MAX];
if (getcwd(b, sizeof(b)))
{
printf ("%s\n", b);
exit (0);
}
else
{
perror ("cwd: getcwd");
exit (1);
}
}
#endif /* TEST */
#endif /* !HAVE_GETCWD */

233
lib/sh/getenv.c Normal file
View file

@ -0,0 +1,233 @@
/* getenv.c - get environment variable value from the shell's variable
list. */
/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (CAN_REDEFINE_GETENV)
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <bashansi.h>
#include <errno.h>
#include <shell.h>
#ifndef errno
extern int errno;
#endif
extern char **environ;
/* We supply our own version of getenv () because we want library
routines to get the changed values of exported variables. */
/* The NeXT C library has getenv () defined and used in the same file.
This screws our scheme. However, Bash will run on the NeXT using
the C library getenv (), since right now the only environment variable
that we care about is HOME, and that is already defined. */
static char *last_tempenv_value = (char *)NULL;
char *
getenv (name)
const char *name;
{
SHELL_VAR *var;
if (name == 0 || *name == '\0')
return ((char *)NULL);
var = find_tempenv_variable ((char *)name);
if (var)
{
FREE (last_tempenv_value);
last_tempenv_value = value_cell (var) ? savestring (value_cell (var)) : (char *)NULL;
return (last_tempenv_value);
}
else if (shell_variables)
{
var = find_variable ((char *)name);
if (var && exported_p (var))
return (value_cell (var));
}
else if (environ)
{
register int i, len;
/* In some cases, s5r3 invokes getenv() before main(); BSD systems
using gprof also exhibit this behavior. This means that
shell_variables will be 0 when this is invoked. We look up the
variable in the real environment in that case. */
for (i = 0, len = strlen (name); environ[i]; i++)
{
if ((STREQN (environ[i], name, len)) && (environ[i][len] == '='))
return (environ[i] + len + 1);
}
}
return ((char *)NULL);
}
/* Some versions of Unix use _getenv instead. */
char *
_getenv (name)
const char *name;
{
return (getenv (name));
}
/* SUSv3 says argument is a `char *'; BSD implementations disagree */
int
putenv (str)
#ifndef HAVE_STD_PUTENV
const char *str;
#else
char *str;
#endif
{
SHELL_VAR *var;
char *name, *value;
int offset;
if (str == 0 || *str == '\0')
{
errno = EINVAL;
return -1;
}
offset = assignment (str, 0);
if (str[offset] != '=')
{
errno = EINVAL;
return -1;
}
name = savestring (str);
name[offset] = 0;
value = name + offset + 1;
/* XXX - should we worry about readonly here? */
var = bind_variable (name, value, 0);
if (var == 0)
{
errno = EINVAL;
return -1;
}
VUNSETATTR (var, att_invisible);
VSETATTR (var, att_exported);
return 0;
}
#if 0
int
_putenv (name)
#ifndef HAVE_STD_PUTENV
const char *name;
#else
char *name;
#endif
{
return putenv (name);
}
#endif
int
setenv (name, value, rewrite)
const char *name;
const char *value;
int rewrite;
{
SHELL_VAR *var;
char *v;
if (name == 0 || *name == '\0' || strchr (name, '=') != 0)
{
errno = EINVAL;
return -1;
}
var = 0;
v = (char *)value; /* some compilers need explicit cast */
/* XXX - should we worry about readonly here? */
if (rewrite == 0)
var = find_variable (name);
if (var == 0)
var = bind_variable (name, v, 0);
if (var == 0)
return -1;
VUNSETATTR (var, att_invisible);
VSETATTR (var, att_exported);
return 0;
}
#if 0
int
_setenv (name, value, rewrite)
const char *name;
const char *value;
int rewrite;
{
return setenv (name, value, rewrite);
}
#endif
/* SUSv3 says unsetenv returns int; existing implementations (BSD) disagree. */
#ifdef HAVE_STD_UNSETENV
#define UNSETENV_RETURN(N) return(N)
#define UNSETENV_RETTYPE int
#else
#define UNSETENV_RETURN(N) return
#define UNSETENV_RETTYPE void
#endif
UNSETENV_RETTYPE
unsetenv (name)
const char *name;
{
if (name == 0 || *name == '\0' || strchr (name, '=') != 0)
{
errno = EINVAL;
UNSETENV_RETURN(-1);
}
/* XXX - should we just remove the export attribute here? */
#if 1
unbind_variable (name);
#else
SHELL_VAR *v;
v = find_variable (name);
if (v)
VUNSETATTR (v, att_exported);
#endif
UNSETENV_RETURN(0);
}
#endif /* CAN_REDEFINE_GETENV */

35
lib/sh/gettimeofday.c Normal file
View file

@ -0,0 +1,35 @@
/* gettimeofday.c - gettimeofday replacement using time() */
/* Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#if !defined (HAVE_GETTIMEOFDAY)
#include "posixtime.h"
/* A version of gettimeofday that just sets tv_sec from time(3) */
int
gettimeofday (struct timeval *tv, void *tz)
{
tv->tv_sec = (time_t) time ((time_t *)0);
tv->tv_usec = 0;
return 0;
}
#endif

214
lib/sh/inet_aton.c Normal file
View file

@ -0,0 +1,214 @@
/* inet_aton - convert string to numeric IP address */
/* Snagged from GNU C library, version 2.0.3. */
/*
* ++Copyright++ 1983, 1990, 1993
* -
* Copyright (c) 1983, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $";
#endif /* LIBC_SCCS and not lint */
#include <config.h>
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
#include <sys/types.h>
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <bashansi.h>
#include <ctype.h>
#include <stdc.h>
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
#endif
/* these are compatibility routines, not needed on recent BSD releases */
#if 0
/* Not used, not needed. */
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
u_long
inet_addr(cp)
register const char *cp;
{
struct in_addr val;
if (inet_aton(cp, &val))
return (val.s_addr);
return (INADDR_NONE);
}
#endif
/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*/
int
inet_aton(cp, addr)
register const char *cp;
struct in_addr *addr;
{
register u_bits32_t val;
register int base, n;
register unsigned char c;
u_int parts[4];
register u_int *pp = parts;
c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, isdigit=decimal.
*/
#if 0
if (!isdigit(c))
#else
if (c != '0' && c != '1' && c != '2' && c != '3' && c != '4' &&
c != '5' && c != '6' && c != '7' && c != '8' && c != '9')
#endif
return (0);
val = 0; base = 10;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X')
base = 16, c = *++cp;
else
base = 8;
}
for (;;) {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
c = *++cp;
} else if (base == 16 && isascii(c) && isxdigit(c)) {
val = (val << 4) |
(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3)
return (0);
*pp++ = val;
c = *++cp;
} else
break;
}
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 0:
return (0); /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
addr->s_addr = htonl(val);
return (1);
}
#endif /* !HAVE_INET_ATON */

159
lib/sh/input_avail.c Normal file
View file

@ -0,0 +1,159 @@
/* input_avail.c -- check whether or not data is available for reading on a
specified file descriptor. */
/* Copyright (C) 2008,2009-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined (__TANDEM)
# include <floss.h>
#endif
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif /* HAVE_SYS_FILE_H */
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include "bashansi.h"
#include "posixselect.h"
#if defined (FIONREAD_IN_SYS_IOCTL)
# include <sys/ioctl.h>
#endif
#include <stdio.h>
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if !defined (O_NDELAY) && defined (O_NONBLOCK)
# define O_NDELAY O_NONBLOCK /* Posix style */
#endif
/* Return >= 1 if select/FIONREAD indicates data available for reading on
file descriptor FD; 0 if no data available. Return -1 on error. */
int
input_avail (fd)
int fd;
{
int result, chars_avail;
#if defined(HAVE_SELECT)
fd_set readfds, exceptfds;
struct timeval timeout;
#endif
if (fd < 0)
return -1;
chars_avail = 0;
#if defined (HAVE_SELECT)
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (fd, &readfds);
FD_SET (fd, &exceptfds);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
return ((result <= 0) ? 0 : 1);
#endif
#if defined (FIONREAD)
errno = 0;
result = ioctl (fd, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
return (chars_avail);
#endif
return 0;
}
/* Wait until NCHARS are available for reading on file descriptor FD.
This can wait indefinitely. Return -1 on error. */
int
nchars_avail (fd, nchars)
int fd;
int nchars;
{
int result, chars_avail;
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
fd_set readfds, exceptfds;
sigset_t set, oset;
#endif
if (fd < 0 || nchars < 0)
return -1;
if (nchars == 0)
return (input_avail (fd));
chars_avail = 0;
#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (fd, &readfds);
FD_SET (fd, &exceptfds);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
# ifdef SIGCHLD
sigaddset (&set, SIGCHLD);
# endif
sigemptyset (&oset);
#endif
while (1)
{
result = 0;
#if defined (HAVE_PSELECT)
/* XXX - use pselect(2) to block SIGCHLD atomically */
result = pselect (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timespec *)NULL, &set);
#elif defined (HAVE_SELECT)
sigprocmask (SIG_BLOCK, &set, &oset);
result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timeval *)NULL);
sigprocmask (SIG_BLOCK, &oset, (sigset_t *)NULL);
#endif
if (result < 0)
return -1;
#if defined (FIONREAD)
errno = 0;
result = ioctl (fd, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
if (chars_avail >= nchars)
break;
#else
break;
#endif
}
return 0;
}

84
lib/sh/itos.c Normal file
View file

@ -0,0 +1,84 @@
/* itos.c -- Convert integer to string. */
/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <bashansi.h>
#include "shell.h"
char *
inttostr (i, buf, len)
intmax_t i;
char *buf;
size_t len;
{
return (fmtumax (i, 10, buf, len, 0));
}
/* Integer to string conversion. This conses the string; the
caller should free it. */
char *
itos (i)
intmax_t i;
{
char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
return (savestring (p));
}
/* Integer to string conversion. This conses the string using strdup;
caller should free it and be prepared to deal with NULL return. */
char *
mitos (i)
intmax_t i;
{
char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
return (strdup (p));
}
char *
uinttostr (i, buf, len)
uintmax_t i;
char *buf;
size_t len;
{
return (fmtumax (i, 10, buf, len, FL_UNSIGNED));
}
/* Integer to string conversion. This conses the string; the
caller should free it. */
char *
uitos (i)
uintmax_t i;
{
char *p, lbuf[INT_STRLEN_BOUND(uintmax_t) + 1];
p = fmtumax (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED);
return (savestring (p));
}

159
lib/sh/mailstat.c Normal file
View file

@ -0,0 +1,159 @@
/* mailstat.c -- stat a mailbox file, handling maildir-type mail directories */
/* Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <errno.h>
#include <bashtypes.h>
#include <posixstat.h>
#include <posixdir.h>
#include <bashansi.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <maxpath.h>
/*
* Stat a file. If it's a maildir, check all messages
* in the maildir and present the grand total as a file.
* The fields in the 'struct stat' are from the mail directory.
* The following fields are emulated:
*
* st_nlink always 1, unless st_blocks is not present, in which case it's
* the total number of messages
* st_size total number of bytes in all files
* st_blocks total number of messages, if present in struct stat
* st_atime access time of newest file in maildir
* st_mtime modify time of newest file in maildir
* st_mode S_IFDIR changed to S_IFREG
*
* This is good enough for most mail-checking applications.
*/
int
mailstat(path, st)
const char *path;
struct stat *st;
{
static struct stat st_new_last, st_ret_last;
struct stat st_ret, st_tmp;
DIR *dd;
struct dirent *fn;
char dir[PATH_MAX * 2], file[PATH_MAX * 2 + 1];
int i, l;
time_t atime, mtime;
atime = mtime = 0;
/* First see if it's a directory. */
if ((i = stat(path, st)) != 0 || S_ISDIR(st->st_mode) == 0)
return i;
if (strlen(path) > sizeof(dir) - 5)
{
#ifdef ENAMETOOLONG
errno = ENAMETOOLONG;
#else
errno = EINVAL;
#endif
return -1;
}
st_ret = *st;
st_ret.st_nlink = 1;
st_ret.st_size = 0;
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
st_ret.st_blocks = 0;
#else
st_ret.st_nlink = 0;
#endif
st_ret.st_mode &= ~S_IFDIR;
st_ret.st_mode |= S_IFREG;
/* See if cur/ is present */
sprintf(dir, "%s/cur", path);
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
return 0;
st_ret.st_atime = st_tmp.st_atime;
/* See if tmp/ is present */
sprintf(dir, "%s/tmp", path);
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
return 0;
st_ret.st_mtime = st_tmp.st_mtime;
/* And new/ */
sprintf(dir, "%s/new", path);
if (stat(dir, &st_tmp) || S_ISDIR(st_tmp.st_mode) == 0)
return 0;
st_ret.st_mtime = st_tmp.st_mtime;
/* Optimization - if new/ didn't change, nothing else did. */
if (st_tmp.st_dev == st_new_last.st_dev &&
st_tmp.st_ino == st_new_last.st_ino &&
st_tmp.st_atime == st_new_last.st_atime &&
st_tmp.st_mtime == st_new_last.st_mtime)
{
*st = st_ret_last;
return 0;
}
st_new_last = st_tmp;
/* Loop over new/ and cur/ */
for (i = 0; i < 2; i++)
{
sprintf(dir, "%s/%s", path, i ? "cur" : "new");
sprintf(file, "%s/", dir);
l = strlen(file);
if ((dd = opendir(dir)) == NULL)
return 0;
while ((fn = readdir(dd)) != NULL)
{
if (fn->d_name[0] == '.' || strlen(fn->d_name) + l >= sizeof(file))
continue;
strcpy(file + l, fn->d_name);
if (stat(file, &st_tmp) != 0)
continue;
st_ret.st_size += st_tmp.st_size;
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
st_ret.st_blocks++;
#else
st_ret.st_nlink++;
#endif
if (st_tmp.st_atime != st_tmp.st_mtime && st_tmp.st_atime > atime)
atime = st_tmp.st_atime;
if (st_tmp.st_mtime > mtime)
mtime = st_tmp.st_mtime;
}
closedir(dd);
}
/* if (atime) */ /* Set atime even if cur/ is empty */
st_ret.st_atime = atime;
if (mtime)
st_ret.st_mtime = mtime;
*st = st_ret_last = st_ret;
return 0;
}

128
lib/sh/makepath.c Normal file
View file

@ -0,0 +1,128 @@
/* makepath.c - glue PATH and DIR together into a full pathname. */
/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <bashansi.h>
#include "shell.h"
#include <tilde/tilde.h>
#ifndef NULL
# define NULL 0
#endif
/* MAKE SURE THESE AGREE WITH ../../externs.h. */
#ifndef MP_DOTILDE
# define MP_DOTILDE 0x01
# define MP_DOCWD 0x02
# define MP_RMDOT 0x04
# define MP_IGNDOT 0x08
#endif
extern char *get_working_directory PARAMS((char *));
static char *nullpath = "";
/* Take PATH, an element from, e.g., $CDPATH, and DIR, a directory name,
and paste them together into PATH/DIR. Tilde expansion is performed on
PATH if (flags & MP_DOTILDE) is non-zero. If PATH is NULL or the empty
string, it is converted to the current directory. A full pathname is
used if (flags & MP_DOCWD) is non-zero, otherwise `./' is used. If
(flags & MP_RMDOT) is non-zero, any `./' is removed from the beginning
of DIR. If (flags & MP_IGNDOT) is non-zero, a PATH that is "." or "./"
is ignored. */
#define MAKEDOT() \
do { \
xpath = (char *)xmalloc (2); \
xpath[0] = '.'; \
xpath[1] = '\0'; \
pathlen = 1; \
} while (0)
char *
sh_makepath (path, dir, flags)
const char *path, *dir;
int flags;
{
int dirlen, pathlen;
char *ret, *xpath, *xdir, *r, *s;
if (path == 0 || *path == '\0')
{
if (flags & MP_DOCWD)
{
xpath = get_working_directory ("sh_makepath");
if (xpath == 0)
{
ret = get_string_value ("PWD");
if (ret)
xpath = savestring (ret);
}
if (xpath == 0)
MAKEDOT();
else
pathlen = strlen (xpath);
}
else
MAKEDOT();
}
else if ((flags & MP_IGNDOT) && path[0] == '.' && (path[1] == '\0' ||
(path[1] == '/' && path[2] == '\0')))
{
xpath = nullpath;
pathlen = 0;
}
else
{
xpath = ((flags & MP_DOTILDE) && *path == '~') ? bash_tilde_expand (path, 0) : (char *)path;
pathlen = strlen (xpath);
}
xdir = (char *)dir;
dirlen = strlen (xdir);
if ((flags & MP_RMDOT) && dir[0] == '.' && dir[1] == '/')
{
xdir += 2;
dirlen -= 2;
}
r = ret = (char *)xmalloc (2 + dirlen + pathlen);
s = xpath;
while (*s)
*r++ = *s++;
if (s > xpath && s[-1] != '/')
*r++ = '/';
s = xdir;
while (*r++ = *s++)
;
if (xpath != path && xpath != nullpath)
free (xpath);
return (ret);
}

79
lib/sh/mbscasecmp.c Normal file
View file

@ -0,0 +1,79 @@
/* mbscasecmp - case-insensitive multibyte string comparison. */
/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_MBSCASECMP) && defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
/* Compare MBS1 and MBS2 without regard to case. */
int
mbscasecmp (mbs1, mbs2)
const char *mbs1;
const char *mbs2;
{
int len1, len2, mb_cur_max;
wchar_t c1, c2, l1, l2;
len1 = len2 = 0;
/* Reset multibyte characters to their initial state. */
(void) mblen ((char *) NULL, 0);
mb_cur_max = MB_CUR_MAX;
do
{
len1 = mbtowc (&c1, mbs1, mb_cur_max);
len2 = mbtowc (&c2, mbs2, mb_cur_max);
if (len1 == 0)
return len2 == 0 ? 0 : -1;
else if (len2 == 0)
return 1;
else if (len1 > 0 && len2 < 0)
return -1;
else if (len1 < 0 && len2 > 0)
return 1;
else if (len1 < 0 && len2 < 0)
{
len1 = strlen (mbs1);
len2 = strlen (mbs2);
return (len1 == len2 ? memcmp (mbs1, mbs2, len1)
: ((len1 < len2) ? (memcmp (mbs1, mbs2, len1) > 0 ? 1 : -1)
: (memcmp (mbs1, mbs2, len2) >= 0 ? 1 : -1)));
}
l1 = towlower (c1);
l2 = towlower (c2);
mbs1 += len1;
mbs2 += len2;
}
while (l1 == l2);
return l1 - l2;
}
#endif

91
lib/sh/mbschr.c Normal file
View file

@ -0,0 +1,91 @@
/* mbschr.c - strchr(3) that handles multibyte characters. */
/* Copyright (C) 2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "bashansi.h"
#include "shmbutil.h"
extern int locale_mb_cur_max;
extern int locale_utf8locale;
#undef mbschr
extern char *utf8_mbschr (const char *, int); /* XXX */
/* In some locales, the non-first byte of some multibyte characters have
the same value as some ascii character. Faced with these strings, a
legacy strchr() might return the wrong value. */
char *
#if defined (PROTOTYPES)
mbschr (const char *s, int c)
#else
mbschr (s, c)
const char *s;
int c;
#endif
{
#if HANDLE_MULTIBYTE
char *pos;
mbstate_t state;
size_t strlength, mblength;
if (locale_utf8locale && c < 0x80)
return (utf8_mbschr (s, c)); /* XXX */
/* The locale encodings with said weird property are BIG5, BIG5-HKSCS,
GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only
when c >= 0x30. We can therefore use the faster bytewise search if
c <= 0x30. */
if ((unsigned char)c >= '0' && locale_mb_cur_max > 1)
{
pos = (char *)s;
memset (&state, '\0', sizeof(mbstate_t));
strlength = strlen (s);
while (strlength > 0)
{
if (is_basic (*pos))
mblength = 1;
else
{
mblength = mbrlen (pos, strlength, &state);
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
mblength = 1;
}
if (mblength == 1 && c == (unsigned char)*pos)
return pos;
strlength -= mblength;
pos += mblength;
}
return ((char *)NULL);
}
else
#endif
return (strchr (s, c));
}

77
lib/sh/mbscmp.c Normal file
View file

@ -0,0 +1,77 @@
/* mbscmp - multibyte string comparison. */
/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_MBSCMP) && defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
extern int locale_utf8locale;
extern int utf8_mbscmp (const char *, const char *);
/* Compare MBS1 and MBS2. */
int
mbscmp (mbs1, mbs2)
const char *mbs1;
const char *mbs2;
{
int len1, len2, mb_cur_max;
wchar_t c1, c2;
len1 = len2 = 0;
/* Reset multibyte characters to their initial state. */
(void) mblen ((char *) NULL, 0);
mb_cur_max = MB_CUR_MAX;
do
{
len1 = mbtowc (&c1, mbs1, mb_cur_max);
len2 = mbtowc (&c2, mbs2, mb_cur_max);
if (len1 == 0)
return len2 == 0 ? 0 : -1;
else if (len2 == 0)
return 1;
else if (len1 > 0 && len2 < 0)
return -1;
else if (len1 < 0 && len2 > 0)
return 1;
else if (len1 < 0 && len2 < 0)
{
len1 = strlen (mbs1);
len2 = strlen (mbs2);
return (len1 == len2 ? memcmp (mbs1, mbs2, len1)
: ((len1 < len2) ? (memcmp (mbs1, mbs2, len1) > 0 ? 1 : -1)
: (memcmp (mbs1, mbs2, len2) >= 0 ? 1 : -1)));
}
mbs1 += len1;
mbs2 += len2;
}
while (c1 == c2);
return c1 - c2;
}
#endif

29
lib/sh/memset.c Normal file
View file

@ -0,0 +1,29 @@
/* memset.c -- set an area of memory to a given value */
/* Copyright (C) 1991-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
char *
memset (char *str, int c, unsigned int len)
{
register char *st = str;
while (len-- > 0)
*st++ = c;
return str;
}

438
lib/sh/mktime.c Normal file
View file

@ -0,0 +1,438 @@
/* mktime - convert struct tm to a time_t value */
/* Copyright (C) 1993-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Contributed by Paul Eggert (eggert@twinsun.com).
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Define this to have a standalone program to test this implementation of
mktime. */
/* #define DEBUG 1 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef _LIBC
# define HAVE_LIMITS_H 1
# define HAVE_LOCALTIME_R 1
# define STDC_HEADERS 1
#endif
/* Assume that leap seconds are possible, unless told otherwise.
If the host has a `zic' command with a `-L leapsecondfilename' option,
then it supports leap seconds; otherwise it probably doesn't. */
#ifndef LEAP_SECONDS_POSSIBLE
#define LEAP_SECONDS_POSSIBLE 1
#endif
#ifndef VMS
#include <sys/types.h> /* Some systems define `time_t' here. */
#endif
#include <time.h>
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#include "bashansi.h"
#if DEBUG_MKTIME
#include <stdio.h>
/* Make it work even if the system's libc has its own mktime routine. */
#define mktime my_mktime
#endif /* DEBUG_MKTIME */
#ifndef PARAMS
#if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
#define PARAMS(args) args
#else
#define PARAMS(args) ()
#endif /* GCC. */
#endif /* Not PARAMS. */
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef INT_MIN
#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
#endif
#ifndef INT_MAX
#define INT_MAX (~0 - INT_MIN)
#endif
/* True if the arithmetic type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* The maximum and minimum values for the integer type T. These
macros have undefined behavior if T is signed and has padding bits.
If this is a problem for you, please let us know how to fix it for
your host. */
#define TYPE_MINIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) 0 \
: ~ TYPE_MAXIMUM (t)))
#define TYPE_MAXIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) -1 \
: ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
#ifndef TIME_T_MIN
# define TIME_T_MIN TYPE_MINIMUM (time_t)
#endif
#ifndef TIME_T_MAX
# define TIME_T_MAX TYPE_MAXIMUM (time_t)
#endif
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#ifndef __isleap
/* Nonzero if YEAR is a leap year (every 4 years,
except every 100th isn't, and every 400th is). */
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
#endif
/* How many days come before each month (0-12). */
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
static time_t ydhms_tm_diff PARAMS ((int, int, int, int, int, const struct tm *));
time_t __mktime_internal PARAMS ((struct tm *,
struct tm *(*) (const time_t *, struct tm *),
time_t *));
static struct tm *my_localtime_r PARAMS ((const time_t *, struct tm *));
static struct tm *
my_localtime_r (t, tp)
const time_t *t;
struct tm *tp;
{
struct tm *l = localtime (t);
if (! l)
return 0;
*tp = *l;
return tp;
}
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
measured in seconds, ignoring leap seconds.
YEAR uses the same numbering as TM->tm_year.
All values are in range, except possibly YEAR.
If overflow occurs, yield the low order bits of the correct answer. */
static time_t
ydhms_tm_diff (year, yday, hour, min, sec, tp)
int year, yday, hour, min, sec;
const struct tm *tp;
{
/* Compute intervening leap days correctly even if year is negative.
Take care to avoid int overflow. time_t overflow is OK, since
only the low order bits of the correct time_t answer are needed.
Don't convert to time_t until after all divisions are done, since
time_t might be unsigned. */
int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
int a100 = a4 / 25 - (a4 % 25 < 0);
int b100 = b4 / 25 - (b4 % 25 < 0);
int a400 = a100 >> 2;
int b400 = b100 >> 2;
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
time_t years = year - (time_t) tp->tm_year;
time_t days = (365 * years + intervening_leap_days
+ (yday - tp->tm_yday));
return (60 * (60 * (24 * days + (hour - tp->tm_hour))
+ (min - tp->tm_min))
+ (sec - tp->tm_sec));
}
static time_t localtime_offset;
/* Convert *TP to a time_t value. */
time_t
mktime (tp)
struct tm *tp;
{
#ifdef _LIBC
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
time zone names contained in the external variable `tzname' shall
be set as if the tzset() function had been called. */
__tzset ();
#endif
return __mktime_internal (tp, my_localtime_r, &localtime_offset);
}
/* Convert *TP to a time_t value, inverting
the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed. */
time_t
__mktime_internal (tp, convert, offset)
struct tm *tp;
struct tm *(*convert) PARAMS ((const time_t *, struct tm *));
time_t *offset;
{
time_t t, dt, t0;
struct tm tm;
/* The maximum number of probes (calls to CONVERT) should be enough
to handle any combinations of time zone rule changes, solar time,
and leap seconds. Posix.1 prohibits leap seconds, but some hosts
have them anyway. */
int remaining_probes = 4;
/* Time requested. Copy it in case CONVERT modifies *TP; this can
occur if TP is localtime's returned value and CONVERT is localtime. */
int sec = tp->tm_sec;
int min = tp->tm_min;
int hour = tp->tm_hour;
int mday = tp->tm_mday;
int mon = tp->tm_mon;
int year_requested = tp->tm_year;
int isdst = tp->tm_isdst;
/* Ensure that mon is in range, and set year accordingly. */
int mon_remainder = mon % 12;
int negative_mon_remainder = mon_remainder < 0;
int mon_years = mon / 12 - negative_mon_remainder;
int year = year_requested + mon_years;
/* The other values need not be in range:
the remaining code handles minor overflows correctly,
assuming int and time_t arithmetic wraps around.
Major overflows are caught at the end. */
/* Calculate day of year from year, month, and day of month.
The result need not be in range. */
int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
[mon_remainder + 12 * negative_mon_remainder])
+ mday - 1);
#if LEAP_SECONDS_POSSIBLE
/* Handle out-of-range seconds specially,
since ydhms_tm_diff assumes every minute has 60 seconds. */
int sec_requested = sec;
if (sec < 0)
sec = 0;
if (59 < sec)
sec = 59;
#endif
/* Invert CONVERT by probing. First assume the same offset as last time.
Then repeatedly use the error to improve the guess. */
tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
for (t = t0 + *offset;
(dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
t += dt)
if (--remaining_probes == 0)
return -1;
/* Check whether tm.tm_isdst has the requested value, if any. */
if (0 <= isdst && 0 <= tm.tm_isdst)
{
int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
if (dst_diff)
{
/* Move two hours in the direction indicated by the disagreement,
probe some more, and switch to a new time if found.
The largest known fallback due to daylight savings is two hours:
once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
time_t ot = t - 2 * 60 * 60 * dst_diff;
while (--remaining_probes != 0)
{
struct tm otm;
if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
(*convert) (&ot, &otm))))
{
t = ot;
tm = otm;
break;
}
if ((ot += dt) == t)
break; /* Avoid a redundant probe. */
}
}
}
*offset = t - t0;
#if LEAP_SECONDS_POSSIBLE
if (sec_requested != tm.tm_sec)
{
/* Adjust time to reflect the tm_sec requested, not the normalized value.
Also, repair any damage from a false match due to a leap second. */
t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
(*convert) (&t, &tm);
}
#endif
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
{
/* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
so check for major overflows. A gross check suffices,
since if t has overflowed, it is off by a multiple of
TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
the difference that is bounded by a small value. */
double dyear = (double) year_requested + mon_years - tm.tm_year;
double dday = 366 * dyear + mday;
double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
return -1;
}
*tp = tm;
return t;
}
#ifdef weak_alias
weak_alias (mktime, timelocal)
#endif
#if DEBUG_MKTIME
static int
not_equal_tm (a, b)
struct tm *a;
struct tm *b;
{
return ((a->tm_sec ^ b->tm_sec)
| (a->tm_min ^ b->tm_min)
| (a->tm_hour ^ b->tm_hour)
| (a->tm_mday ^ b->tm_mday)
| (a->tm_mon ^ b->tm_mon)
| (a->tm_year ^ b->tm_year)
| (a->tm_mday ^ b->tm_mday)
| (a->tm_yday ^ b->tm_yday)
| (a->tm_isdst ^ b->tm_isdst));
}
static void
print_tm (tp)
struct tm *tp;
{
printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec,
tp->tm_yday, tp->tm_wday, tp->tm_isdst);
}
static int
check_result (tk, tmk, tl, tml)
time_t tk;
struct tm tmk;
time_t tl;
struct tm tml;
{
if (tk != tl || not_equal_tm (&tmk, &tml))
{
printf ("mktime (");
print_tm (&tmk);
printf (")\nyields (");
print_tm (&tml);
printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
return 1;
}
return 0;
}
int
main (argc, argv)
int argc;
char **argv;
{
int status = 0;
struct tm tm, tmk, tml;
time_t tk, tl;
char trailer;
if ((argc == 3 || argc == 4)
&& (sscanf (argv[1], "%d-%d-%d%c",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
== 3)
&& (sscanf (argv[2], "%d:%d:%d%c",
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
== 3))
{
tm.tm_year -= TM_YEAR_BASE;
tm.tm_mon--;
tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
tmk = tm;
tl = mktime (&tmk);
tml = *localtime (&tl);
printf ("mktime returns %ld == ", (long) tl);
print_tm (&tmk);
printf ("\n");
status = check_result (tl, tmk, tl, tml);
}
else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
{
time_t from = atol (argv[1]);
time_t by = atol (argv[2]);
time_t to = atol (argv[3]);
if (argc == 4)
for (tl = from; tl <= to; tl += by)
{
tml = *localtime (&tl);
tmk = tml;
tk = mktime (&tmk);
status |= check_result (tk, tmk, tl, tml);
}
else
for (tl = from; tl <= to; tl += by)
{
/* Null benchmark. */
tml = *localtime (&tl);
tmk = tml;
tk = tl;
status |= check_result (tk, tmk, tl, tml);
}
}
else
printf ("Usage:\
\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
argv[0], argv[0], argv[0]);
return status;
}
#endif /* DEBUG_MKTIME */
/*
Local Variables:
compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"
End:
*/

82
lib/sh/netconn.c Normal file
View file

@ -0,0 +1,82 @@
/* netconn.c -- is a particular file descriptor a network connection?. */
/* Copyright (C) 2002-2005 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#include <posixstat.h>
#include <filecntl.h>
#include <errno.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
/* The second and subsequent conditions must match those used to decide
whether or not to call getpeername() in isnetconn(). */
#if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2)
# include <sys/socket.h>
#endif
/* Is FD a socket or network connection? */
int
isnetconn (fd)
int fd;
{
#if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2) && !defined (__BEOS__)
int rv;
socklen_t l;
struct sockaddr sa;
l = sizeof(sa);
rv = getpeername(fd, &sa, &l);
/* Posix.2 says getpeername can return these errors. */
return ((rv < 0 && (errno == ENOTSOCK || errno == ENOTCONN || errno == EINVAL || errno == EBADF)) ? 0 : 1);
#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
# if defined (SVR4) || defined (SVR4_2)
/* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
struct stat sb;
if (isatty (fd))
return (0);
if (fstat (fd, &sb) < 0)
return (0);
# if defined (S_ISFIFO)
if (S_ISFIFO (sb.st_mode))
return (0);
# endif /* S_ISFIFO */
return (S_ISCHR (sb.st_mode));
# else /* !SVR4 && !SVR4_2 */
# if defined (S_ISSOCK) && !defined (__BEOS__)
struct stat sb;
if (fstat (fd, &sb) < 0)
return (0);
return (S_ISSOCK (sb.st_mode));
# else /* !S_ISSOCK || __BEOS__ */
return (0);
# endif /* !S_ISSOCK || __BEOS__ */
# endif /* !SVR4 && !SVR4_2 */
#endif /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
}

351
lib/sh/netopen.c Normal file
View file

@ -0,0 +1,351 @@
/*
* netopen.c -- functions to make tcp/udp connections
*
* Chet Ramey
* chet@ins.CWRU.Edu
*/
/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_NETWORK)
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#if defined (HAVE_SYS_SOCKET_H)
# include <sys/socket.h>
#endif
#if defined (HAVE_NETINET_IN_H)
# include <netinet/in.h>
#endif
#if defined (HAVE_NETDB_H)
# include <netdb.h>
#endif
#if defined (HAVE_ARPA_INET_H)
# include <arpa/inet.h>
#endif
#include <bashansi.h>
#include <bashintl.h>
#include <errno.h>
#include <shell.h>
#include <xmalloc.h>
#ifndef errno
extern int errno;
#endif
#if !defined (HAVE_INET_ATON)
extern int inet_aton PARAMS((const char *, struct in_addr *));
#endif
#ifndef HAVE_GETADDRINFO
static int _getaddr PARAMS((char *, struct in_addr *));
static int _getserv PARAMS((char *, int, unsigned short *));
static int _netopen4 PARAMS((char *, char *, int));
#else /* HAVE_GETADDRINFO */
static int _netopen6 PARAMS((char *, char *, int));
#endif
static int _netopen PARAMS((char *, char *, int));
#ifndef HAVE_GETADDRINFO
/* Stuff the internet address corresponding to HOST into AP, in network
byte order. Return 1 on success, 0 on failure. */
static int
_getaddr (host, ap)
char *host;
struct in_addr *ap;
{
struct hostent *h;
int r;
r = 0;
if (host[0] >= '0' && host[0] <= '9')
{
/* If the first character is a digit, guess that it's an
Internet address and return immediately if inet_aton succeeds. */
r = inet_aton (host, ap);
if (r)
return r;
}
#if !defined (HAVE_GETHOSTBYNAME)
return 0;
#else
h = gethostbyname (host);
if (h && h->h_addr)
{
bcopy(h->h_addr, (char *)ap, h->h_length);
return 1;
}
#endif
return 0;
}
/* Return 1 if SERV is a valid port number and stuff the converted value into
PP in network byte order. */
static int
_getserv (serv, proto, pp)
char *serv;
int proto;
unsigned short *pp;
{
intmax_t l;
unsigned short s;
if (legal_number (serv, &l))
{
s = (unsigned short)(l & 0xFFFF);
if (s != l)
return (0);
s = htons (s);
if (pp)
*pp = s;
return 1;
}
else
#if defined (HAVE_GETSERVBYNAME)
{
struct servent *se;
se = getservbyname (serv, (proto == 't') ? "tcp" : "udp");
if (se == 0)
return 0;
if (pp)
*pp = se->s_port; /* ports returned in network byte order */
return 1;
}
#else /* !HAVE_GETSERVBYNAME */
return 0;
#endif /* !HAVE_GETSERVBYNAME */
}
/*
* Open a TCP or UDP connection to HOST on port SERV. Uses the
* traditional BSD mechanisms. Returns the connected socket or -1 on error.
*/
static int
_netopen4(host, serv, typ)
char *host, *serv;
int typ;
{
struct in_addr ina;
struct sockaddr_in sin;
unsigned short p;
int s, e;
if (_getaddr(host, &ina) == 0)
{
internal_error (_("%s: host unknown"), host);
errno = EINVAL;
return -1;
}
if (_getserv(serv, typ, &p) == 0)
{
internal_error(_("%s: invalid service"), serv);
errno = EINVAL;
return -1;
}
memset ((char *)&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = p;
sin.sin_addr = ina;
s = socket(AF_INET, (typ == 't') ? SOCK_STREAM : SOCK_DGRAM, 0);
if (s < 0)
{
sys_error ("socket");
return (-1);
}
if (connect (s, (struct sockaddr *)&sin, sizeof (sin)) < 0)
{
e = errno;
sys_error("connect");
close(s);
errno = e;
return (-1);
}
return(s);
}
#endif /* ! HAVE_GETADDRINFO */
#ifdef HAVE_GETADDRINFO
/*
* Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3)
* which provides support for IPv6. Returns the connected socket or -1
* on error.
*/
static int
_netopen6 (host, serv, typ)
char *host, *serv;
int typ;
{
int s, e;
struct addrinfo hints, *res, *res0;
int gerr;
memset ((char *)&hints, 0, sizeof (hints));
/* XXX -- if problems with IPv6, set to PF_INET for IPv4 only */
#ifdef DEBUG /* PF_INET is the one that works for me */
hints.ai_family = PF_INET;
#else
hints.ai_family = PF_UNSPEC;
#endif
hints.ai_socktype = (typ == 't') ? SOCK_STREAM : SOCK_DGRAM;
gerr = getaddrinfo (host, serv, &hints, &res0);
if (gerr)
{
if (gerr == EAI_SERVICE)
internal_error ("%s: %s", serv, gai_strerror (gerr));
else
internal_error ("%s: %s", host, gai_strerror (gerr));
errno = EINVAL;
return -1;
}
for (res = res0; res; res = res->ai_next)
{
if ((s = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
{
if (res->ai_next)
continue;
sys_error ("socket");
freeaddrinfo (res0);
return -1;
}
if (connect (s, res->ai_addr, res->ai_addrlen) < 0)
{
if (res->ai_next)
{
close (s);
continue;
}
e = errno;
sys_error ("connect");
close (s);
freeaddrinfo (res0);
errno = e;
return -1;
}
freeaddrinfo (res0);
break;
}
return s;
}
#endif /* HAVE_GETADDRINFO */
/*
* Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3)
* if available, falling back to the traditional BSD mechanisms otherwise.
* Returns the connected socket or -1 on error.
*/
static int
_netopen(host, serv, typ)
char *host, *serv;
int typ;
{
#ifdef HAVE_GETADDRINFO
return (_netopen6 (host, serv, typ));
#else
return (_netopen4 (host, serv, typ));
#endif
}
/*
* Open a TCP or UDP connection given a path like `/dev/tcp/host/port' to
* host `host' on port `port' and return the connected socket.
*/
int
netopen (path)
char *path;
{
char *np, *s, *t;
int fd;
np = (char *)xmalloc (strlen (path) + 1);
strcpy (np, path);
s = np + 9;
t = strchr (s, '/');
if (t == 0)
{
internal_error (_("%s: bad network path specification"), path);
free (np);
return -1;
}
*t++ = '\0';
fd = _netopen (s, t, path[5]);
free (np);
return fd;
}
#if 0
/*
* Open a TCP connection to host `host' on the port defined for service
* `serv' and return the connected socket.
*/
int
tcpopen (host, serv)
char *host, *serv;
{
return (_netopen (host, serv, 't'));
}
/*
* Open a UDP connection to host `host' on the port defined for service
* `serv' and return the connected socket.
*/
int
udpopen (host, serv)
char *host, *serv;
{
return _netopen (host, serv, 'u');
}
#endif
#else /* !HAVE_NETWORK */
int
netopen (path)
char *path;
{
internal_error (_("network operations not supported"));
return -1;
}
#endif /* !HAVE_NETWORK */

301
lib/sh/oslib.c Normal file
View file

@ -0,0 +1,301 @@
/* oslib.c - functions present only in some unix versions. */
/* Copyright (C) 1995,2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
#include <posixstat.h>
#include <filecntl.h>
#include <bashansi.h>
#if !defined (HAVE_KILLPG)
# include <signal.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <chartypes.h>
#include <shell.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
/* Make the functions strchr and strrchr if they do not exist. */
#if !defined (HAVE_STRCHR)
char *
strchr (string, c)
char *string;
int c;
{
register char *s;
for (s = string; s && *s; s++)
if (*s == c)
return (s);
return ((char *) NULL);
}
char *
strrchr (string, c)
char *string;
int c;
{
register char *s, *t;
for (s = string, t = (char *)NULL; s && *s; s++)
if (*s == c)
t = s;
return (t);
}
#endif /* !HAVE_STRCHR */
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
/* Replacement for dup2 (), for those systems which either don't have it,
or supply one with broken behaviour. */
int
dup2 (fd1, fd2)
int fd1, fd2;
{
int saved_errno, r;
/* If FD1 is not a valid file descriptor, then return immediately with
an error. */
if (fcntl (fd1, F_GETFL, 0) == -1)
return (-1);
if (fd2 < 0 || fd2 >= getdtablesize ())
{
errno = EBADF;
return (-1);
}
if (fd1 == fd2)
return (0);
saved_errno = errno;
(void) close (fd2);
r = fcntl (fd1, F_DUPFD, fd2);
if (r >= 0)
errno = saved_errno;
else
if (errno == EINVAL)
errno = EBADF;
/* Force the new file descriptor to remain open across exec () calls. */
SET_OPEN_ON_EXEC (fd2);
return (r);
}
#endif /* !HAVE_DUP2 */
/*
* Return the total number of available file descriptors.
*
* On some systems, like 4.2BSD and its descendants, there is a system call
* that returns the size of the descriptor table: getdtablesize(). There are
* lots of ways to emulate this on non-BSD systems.
*
* On System V.3, this can be obtained via a call to ulimit:
* return (ulimit(4, 0L));
*
* On other System V systems, NOFILE is defined in /usr/include/sys/param.h
* (this is what we assume below), so we can simply use it:
* return (NOFILE);
*
* On POSIX systems, there are specific functions for retrieving various
* configuration parameters:
* return (sysconf(_SC_OPEN_MAX));
*
*/
#if !defined (HAVE_GETDTABLESIZE)
int
getdtablesize ()
{
# if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
return (sysconf(_SC_OPEN_MAX)); /* Posix systems use sysconf */
# else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */
# if defined (ULIMIT_MAXFDS)
return (ulimit (4, 0L)); /* System V.3 systems use ulimit(4, 0L) */
# else /* !ULIMIT_MAXFDS */
# if defined (NOFILE) /* Other systems use NOFILE */
return (NOFILE);
# else /* !NOFILE */
return (20); /* XXX - traditional value is 20 */
# endif /* !NOFILE */
# endif /* !ULIMIT_MAXFDS */
# endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
}
#endif /* !HAVE_GETDTABLESIZE */
#if !defined (HAVE_BCOPY)
# if defined (bcopy)
# undef bcopy
# endif
void
bcopy (s,d,n)
void *d, *s;
size_t n;
{
FASTCOPY (s, d, n);
}
#endif /* !HAVE_BCOPY */
#if !defined (HAVE_BZERO)
# if defined (bzero)
# undef bzero
# endif
void
bzero (s, n)
void *s;
size_t n;
{
register int i;
register char *r;
for (i = 0, r = s; i < n; i++)
*r++ = '\0';
}
#endif
#if !defined (HAVE_GETHOSTNAME)
# if defined (HAVE_UNAME)
# include <sys/utsname.h>
int
gethostname (name, namelen)
char *name;
size_t namelen;
{
int i;
struct utsname ut;
--namelen;
uname (&ut);
i = strlen (ut.nodename) + 1;
strncpy (name, ut.nodename, i < namelen ? i : namelen);
name[namelen] = '\0';
return (0);
}
# else /* !HAVE_UNAME */
int
gethostname (name, namelen)
char *name;
size_t namelen;
{
strncpy (name, "unknown", namelen);
name[namelen] = '\0';
return 0;
}
# endif /* !HAVE_UNAME */
#endif /* !HAVE_GETHOSTNAME */
#if !defined (HAVE_KILLPG)
int
killpg (pgrp, sig)
pid_t pgrp;
int sig;
{
return (kill (-pgrp, sig));
}
#endif /* !HAVE_KILLPG */
#if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION)
int
mkfifo (path, mode)
char *path;
mode_t mode;
{
#if defined (S_IFIFO)
return (mknod (path, (mode | S_IFIFO), 0));
#else /* !S_IFIFO */
return (-1);
#endif /* !S_IFIFO */
}
#endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */
#define DEFAULT_MAXGROUPS 64
int
getmaxgroups ()
{
static int maxgroups = -1;
if (maxgroups > 0)
return maxgroups;
#if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
maxgroups = sysconf (_SC_NGROUPS_MAX);
#else
# if defined (NGROUPS_MAX)
maxgroups = NGROUPS_MAX;
# else /* !NGROUPS_MAX */
# if defined (NGROUPS)
maxgroups = NGROUPS;
# else /* !NGROUPS */
maxgroups = DEFAULT_MAXGROUPS;
# endif /* !NGROUPS */
# endif /* !NGROUPS_MAX */
#endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
if (maxgroups <= 0)
maxgroups = DEFAULT_MAXGROUPS;
return maxgroups;
}
long
getmaxchild ()
{
static long maxchild = -1L;
if (maxchild > 0)
return maxchild;
#if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
maxchild = sysconf (_SC_CHILD_MAX);
#else
# if defined (CHILD_MAX)
maxchild = CHILD_MAX;
# else
# if defined (MAXUPRC)
maxchild = MAXUPRC;
# endif /* MAXUPRC */
# endif /* CHILD_MAX */
#endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
return (maxchild);
}

234
lib/sh/pathcanon.c Normal file
View file

@ -0,0 +1,234 @@
/* pathcanon.c -- canonicalize and manipulate pathnames. */
/* Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <filecntl.h>
#include <bashansi.h>
#include <stdio.h>
#include <chartypes.h>
#include <errno.h>
#include "shell.h"
#if !defined (errno)
extern int errno;
#endif
#if defined (__CYGWIN__)
#include <sys/cygwin.h>
static int
_is_cygdrive (path)
char *path;
{
static char user[MAXPATHLEN];
static char system[MAXPATHLEN];
static int first_time = 1;
/* If the path is the first part of a network path, treat it as
existing. */
if (path[0] == '/' && path[1] == '/' && !strchr (path + 2, '/'))
return 1;
/* Otherwise check for /cygdrive prefix. */
if (first_time)
{
char user_flags[MAXPATHLEN];
char system_flags[MAXPATHLEN];
/* Get the cygdrive info */
cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags, system_flags);
first_time = 0;
}
return !strcasecmp (path, user) || !strcasecmp (path, system);
}
#endif /* __CYGWIN__ */
/* Return 1 if PATH corresponds to a directory. A function for debugging. */
static int
_path_isdir (path)
char *path;
{
int l;
struct stat sb;
/* This should leave errno set to the correct value. */
errno = 0;
l = stat (path, &sb) == 0 && S_ISDIR (sb.st_mode);
#if defined (__CYGWIN__)
if (l == 0)
l = _is_cygdrive (path);
#endif
return l;
}
/* Canonicalize PATH, and return a new path. The new path differs from PATH
in that:
Multiple `/'s are collapsed to a single `/'.
Leading `./'s and trailing `/.'s are removed.
Trailing `/'s are removed.
Non-leading `../'s and trailing `..'s are handled by removing
portions of the path. */
/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */
#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')
char *
sh_canonpath (path, flags)
char *path;
int flags;
{
char stub_char;
char *result, *p, *q, *base, *dotdot;
int rooted, double_slash_path;
/* The result cannot be larger than the input PATH. */
result = (flags & PATH_NOALLOC) ? path : savestring (path);
/* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any
leading `x:' (dos drive name). */
if (rooted = ROOTEDPATH(path))
{
stub_char = DIRSEP;
#if defined (__CYGWIN__)
base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 3 : result + 1;
#else
base = result + 1;
#endif
double_slash_path = DOUBLE_SLASH (path);
base += double_slash_path;
}
else
{
stub_char = '.';
#if defined (__CYGWIN__)
base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 2 : result;
#else
base = result;
#endif
double_slash_path = 0;
}
/*
* invariants:
* base points to the portion of the path we want to modify
* p points at beginning of path element we're considering.
* q points just past the last path element we wrote (no slash).
* dotdot points just past the point where .. cannot backtrack
* any further (no slash).
*/
p = q = dotdot = base;
while (*p)
{
if (ISDIRSEP(p[0])) /* null element */
p++;
else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
p += 1; /* don't count the separator in case it is nul */
else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
{
p += 2; /* skip `..' */
if (q > dotdot) /* can backtrack */
{
if (flags & PATH_CHECKDOTDOT)
{
char c;
/* Make sure what we have so far corresponds to a valid
path before we chop some of it off. */
c = *q;
*q = '\0';
if (_path_isdir (result) == 0)
{
if ((flags & PATH_NOALLOC) == 0)
free (result);
return ((char *)NULL);
}
*q = c;
}
while (--q > dotdot && ISDIRSEP(*q) == 0)
;
}
else if (rooted == 0)
{
/* /.. is / but ./../ is .. */
if (q != base)
*q++ = DIRSEP;
*q++ = '.';
*q++ = '.';
dotdot = q;
}
}
else /* real path element */
{
/* add separator if not at start of work portion of result */
if (q != base)
*q++ = DIRSEP;
while (*p && (ISDIRSEP(*p) == 0))
*q++ = *p++;
/* Check here for a valid directory with _path_isdir. */
if (flags & PATH_CHECKEXISTS)
{
char c;
/* Make sure what we have so far corresponds to a valid
path before we chop some of it off. */
c = *q;
*q = '\0';
if (_path_isdir (result) == 0)
{
if ((flags & PATH_NOALLOC) == 0)
free (result);
return ((char *)NULL);
}
*q = c;
}
}
}
/* Empty string is really ``.'' or `/', depending on what we started with. */
if (q == result)
*q++ = stub_char;
*q = '\0';
/* If the result starts with `//', but the original path does not, we
can turn the // into /. Because of how we set `base', this should never
be true, but it's a sanity check. */
if (DOUBLE_SLASH(result) && double_slash_path == 0)
{
if (result[2] == '\0') /* short-circuit for bare `//' */
result[1] = '\0';
else
memmove (result, result + 1, strlen (result + 1) + 1);
}
return (result);
}

296
lib/sh/pathphys.c Normal file
View file

@ -0,0 +1,296 @@
/* pathphys.c -- return pathname with all symlinks expanded. */
/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <filecntl.h>
#include <bashansi.h>
#include <stdio.h>
#include <chartypes.h>
#include <errno.h>
#include "shell.h"
#if !defined (MAXSYMLINKS)
# define MAXSYMLINKS 32
#endif
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern char *get_working_directory PARAMS((char *));
static int
_path_readlink (path, buf, bufsiz)
char *path;
char *buf;
int bufsiz;
{
#ifdef HAVE_READLINK
return readlink (path, buf, bufsiz);
#else
errno = EINVAL;
return -1;
#endif
}
/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */
#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')
/*
* Return PATH with all symlinks expanded in newly-allocated memory.
* This always gets an absolute pathname.
*/
char *
sh_physpath (path, flags)
char *path;
int flags;
{
char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1];
char *result, *p, *q, *qsave, *qbase, *workpath;
int double_slash_path, linklen, nlink;
linklen = strlen (path);
#if 0
/* First sanity check -- punt immediately if the name is too long. */
if (linklen >= PATH_MAX)
return (savestring (path));
#endif
nlink = 0;
q = result = (char *)xmalloc (PATH_MAX + 1);
/* Even if we get something longer than PATH_MAX, we might be able to
shorten it, so we try. */
if (linklen >= PATH_MAX)
workpath = savestring (path);
else
{
workpath = (char *)xmalloc (PATH_MAX + 1);
strcpy (workpath, path);
}
/* This always gets an absolute pathname. */
/* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any
leading `x:' (dos drive name). */
#if defined (__CYGWIN__)
qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
#else
qbase = workpath + 1;
#endif
double_slash_path = DOUBLE_SLASH (workpath);
qbase += double_slash_path;
for (p = workpath; p < qbase; )
*q++ = *p++;
qbase = q;
/*
* invariants:
* qbase points to the portion of the result path we want to modify
* p points at beginning of path element we're considering.
* q points just past the last path element we wrote (no slash).
*
* XXX -- need to fix error checking for too-long pathnames
*/
while (*p)
{
if (ISDIRSEP(p[0])) /* null element */
p++;
else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
p += 1; /* don't count the separator in case it is nul */
else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
{
p += 2; /* skip `..' */
if (q > qbase)
{
while (--q > qbase && ISDIRSEP(*q) == 0)
;
}
}
else /* real path element */
{
/* add separator if not at start of work portion of result */
qsave = q;
if (q != qbase)
*q++ = DIRSEP;
while (*p && (ISDIRSEP(*p) == 0))
{
if (q - result >= PATH_MAX)
{
#ifdef ENAMETOOLONG
errno = ENAMETOOLONG;
#else
errno = EINVAL;
#endif
goto error;
}
*q++ = *p++;
}
*q = '\0';
linklen = _path_readlink (result, linkbuf, PATH_MAX);
if (linklen < 0) /* if errno == EINVAL, it's not a symlink */
{
if (errno != EINVAL)
goto error;
continue;
}
/* It's a symlink, and the value is in LINKBUF. */
nlink++;
if (nlink > MAXSYMLINKS)
{
#ifdef ELOOP
errno = ELOOP;
#else
errno = EINVAL;
#endif
error:
free (result);
free (workpath);
return ((char *)NULL);
}
linkbuf[linklen] = '\0';
/* If the new path length would overrun PATH_MAX, punt now. */
if ((strlen (p) + linklen + 2) >= PATH_MAX)
{
#ifdef ENAMETOOLONG
errno = ENAMETOOLONG;
#else
errno = EINVAL;
#endif
goto error;
}
/* Form the new pathname by copying the link value to a temporary
buffer and appending the rest of `workpath'. Reset p to point
to the start of the rest of the path. If the link value is an
absolute pathname, reset p, q, and qbase. If not, reset p
and q. */
strcpy (tbuf, linkbuf);
tbuf[linklen] = '/';
strcpy (tbuf + linklen, p);
strcpy (workpath, tbuf);
if (ABSPATH(linkbuf))
{
q = result;
/* Duplicating some code here... */
#if defined (__CYGWIN__)
qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
#else
qbase = workpath + 1;
#endif
double_slash_path = DOUBLE_SLASH (workpath);
qbase += double_slash_path;
for (p = workpath; p < qbase; )
*q++ = *p++;
qbase = q;
}
else
{
p = workpath;
q = qsave;
}
}
}
*q = '\0';
free (workpath);
/* If the result starts with `//', but the original path does not, we
can turn the // into /. Because of how we set `qbase', this should never
be true, but it's a sanity check. */
if (DOUBLE_SLASH(result) && double_slash_path == 0)
{
if (result[2] == '\0') /* short-circuit for bare `//' */
result[1] = '\0';
else
memmove (result, result + 1, strlen (result + 1) + 1);
}
return (result);
}
char *
sh_realpath (pathname, resolved)
const char *pathname;
char *resolved;
{
char *tdir, *wd;
if (pathname == 0 || *pathname == '\0')
{
errno = (pathname == 0) ? EINVAL : ENOENT;
return ((char *)NULL);
}
if (ABSPATH (pathname) == 0)
{
wd = get_working_directory ("sh_realpath");
if (wd == 0)
return ((char *)NULL);
tdir = sh_makepath (wd, (char *)pathname, 0);
free (wd);
}
else
tdir = savestring (pathname);
wd = sh_physpath (tdir, 0);
free (tdir);
if (resolved == 0)
return (wd);
if (wd)
{
strncpy (resolved, wd, PATH_MAX - 1);
resolved[PATH_MAX - 1] = '\0';
free (wd);
return resolved;
}
else
{
resolved[0] = '\0';
return wd;
}
}

240
lib/sh/random.c Normal file
View file

@ -0,0 +1,240 @@
/* random.c -- Functions for managing 16-bit and 32-bit random numbers. */
/* Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "bashtypes.h"
#if defined (HAVE_SYS_RANDOM_H)
# include <sys/random.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "filecntl.h"
#include <stdio.h>
#include "bashansi.h"
#include "shell.h"
extern time_t shell_start_time;
extern int last_random_value;
static u_bits32_t intrand32 PARAMS((u_bits32_t));
static u_bits32_t genseed PARAMS((void));
static u_bits32_t brand32 PARAMS((void));
static void sbrand32 PARAMS((u_bits32_t));
static void perturb_rand32 PARAMS((void));
/* The random number seed. You can change this by setting RANDOM. */
static u_bits32_t rseed = 1;
/* Returns a 32-bit pseudo-random number. */
static u_bits32_t
intrand32 (last)
u_bits32_t last;
{
/* Minimal Standard generator from
"Random number generators: good ones are hard to find",
Park and Miller, Communications of the ACM, vol. 31, no. 10,
October 1988, p. 1195. Filtered through FreeBSD.
x(n+1) = 16807 * x(n) mod (m).
We split up the calculations to avoid overflow.
h = last / q; l = x - h * q; t = a * l - h * r
m = 2147483647, a = 16807, q = 127773, r = 2836
There are lots of other combinations of constants to use; look at
https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */
bits32_t h, l, t;
u_bits32_t ret;
/* Can't seed with 0. */
ret = (last == 0) ? 123459876 : last;
h = ret / 127773;
l = ret - (127773 * h);
t = 16807 * l - 2836 * h;
ret = (t < 0) ? t + 0x7fffffff : t;
return (ret);
}
static u_bits32_t
genseed ()
{
struct timeval tv;
u_bits32_t iv;
gettimeofday (&tv, NULL);
iv = (u_bits32_t)seedrand; /* let the compiler truncate */
iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv;
return (iv);
}
#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */
/* Returns a pseudo-random number between 0 and 32767. */
int
brand ()
{
unsigned int ret;
rseed = intrand32 (rseed);
if (shell_compatibility_level > 50)
ret = (rseed >> 16) ^ (rseed & 65535);
else
ret = rseed;
return (ret & BASH_RAND_MAX);
}
/* Set the random number generator seed to SEED. */
void
sbrand (seed)
unsigned long seed;
{
rseed = seed;
last_random_value = 0;
}
void
seedrand ()
{
u_bits32_t iv;
iv = genseed ();
sbrand (iv);
}
static u_bits32_t rseed32 = 1073741823;
static int last_rand32;
static int urandfd = -1;
#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */
/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */
static u_bits32_t
brand32 ()
{
u_bits32_t ret;
rseed32 = intrand32 (rseed32);
return (rseed32 & BASH_RAND32_MAX);
}
static void
sbrand32 (seed)
u_bits32_t seed;
{
last_rand32 = rseed32 = seed;
}
void
seedrand32 ()
{
u_bits32_t iv;
iv = genseed ();
sbrand32 (iv);
}
static void
perturb_rand32 ()
{
rseed32 ^= genseed ();
}
/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */
void
urandom_close ()
{
if (urandfd >= 0)
close (urandfd);
urandfd = -1;
}
#if !defined (HAVE_GETRANDOM)
/* Imperfect emulation of getrandom(2). */
#ifndef GRND_NONBLOCK
# define GRND_NONBLOCK 1
# define GRND_RANDOM 2
#endif
static ssize_t
getrandom (buf, len, flags)
void *buf;
size_t len;
unsigned int flags;
{
int oflags;
ssize_t r;
static int urand_unavail = 0;
#if HAVE_GETENTROPY
r = getentropy (buf, len);
return (r == 0) ? len : -1;
#endif
if (urandfd == -1 && urand_unavail == 0)
{
oflags = O_RDONLY;
if (flags & GRND_NONBLOCK)
oflags |= O_NONBLOCK;
urandfd = open ("/dev/urandom", oflags, 0);
if (urandfd >= 0)
SET_CLOSE_ON_EXEC (urandfd);
else
{
urand_unavail = 1;
return -1;
}
}
if (urandfd >= 0 && (r = read (urandfd, buf, len)) == len)
return (r);
return -1;
}
#endif
u_bits32_t
get_urandom32 ()
{
u_bits32_t ret;
if (getrandom ((void *)&ret, sizeof (ret), GRND_NONBLOCK) == sizeof (ret))
return (last_rand32 = ret);
#if defined (HAVE_ARC4RANDOM)
ret = arc4random ();
#else
if (subshell_environment)
perturb_rand32 ();
do
ret = brand32 ();
while (ret == last_rand32);
#endif
return (last_rand32 = ret);
}

76
lib/sh/rename.c Normal file
View file

@ -0,0 +1,76 @@
/*
* rename - rename a file
*/
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_RENAME)
#include <bashtypes.h>
#include <posixstat.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#include <stdc.h>
#ifndef errno
extern int errno;
#endif
int
rename (from, to)
const char *from, *to;
{
struct stat fb, tb;
if (stat (from, &fb) < 0)
return -1;
if (stat (to, &tb) < 0)
{
if (errno != ENOENT)
return -1;
}
else
{
if (fb.st_dev == tb.st_dev && fb.st_ino == tb.st_ino)
return 0; /* same file */
if (unlink (to) < 0 && errno != ENOENT)
return -1;
}
if (link (from, to) < 0)
return (-1);
if (unlink (from) < 0 && errno != ENOENT)
{
int e = errno;
unlink (to);
errno = e;
return (-1);
}
return (0);
}
#endif /* !HAVE_RENAME */

66
lib/sh/setlinebuf.c Normal file
View file

@ -0,0 +1,66 @@
/* setlinebuf.c - line-buffer a stdio stream. */
/* Copyright (C) 1997,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <xmalloc.h>
#if defined (USING_BASH_MALLOC)
# define LBUF_BUFSIZE 2016
#else
# define LBUF_BUFSIZE BUFSIZ
#endif
static char *stdoutbuf = 0;
static char *stderrbuf = 0;
/* Cause STREAM to buffer lines as opposed to characters or blocks. */
int
sh_setlinebuf (stream)
FILE *stream;
{
#if !defined (HAVE_SETLINEBUF) && !defined (HAVE_SETVBUF)
return (0);
#endif
#if defined (HAVE_SETVBUF)
char *local_linebuf;
#if defined (USING_BASH_MALLOC)
if (stream == stdout && stdoutbuf == 0)
local_linebuf = stdoutbuf = (char *)xmalloc (LBUF_BUFSIZE);
else if (stream == stderr && stderrbuf == 0)
local_linebuf = stderrbuf = (char *)xmalloc (LBUF_BUFSIZE);
else
local_linebuf = (char *)NULL; /* let stdio handle it */
#else
local_linebuf = (char *)NULL;
#endif
return (setvbuf (stream, local_linebuf, _IOLBF, LBUF_BUFSIZE));
#else /* !HAVE_SETVBUF */
setlinebuf (stream);
return (0);
#endif /* !HAVE_SETVBUF */
}

132
lib/sh/shmatch.c Normal file
View file

@ -0,0 +1,132 @@
/*
* shmatch.c -- shell interface to posix regular expression matching.
*/
/* Copyright (C) 2003-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined (HAVE_POSIX_REGEXP)
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include <regex.h>
#include "shell.h"
#include "variables.h"
#include "externs.h"
extern int glob_ignore_case, match_ignore_case;
#if defined (ARRAY_VARS)
extern SHELL_VAR *builtin_find_indexed_array (char *, int);
#endif
int
sh_regmatch (string, pattern, flags)
const char *string;
const char *pattern;
int flags;
{
regex_t regex = { 0 };
regmatch_t *matches;
int rflags;
#if defined (ARRAY_VARS)
SHELL_VAR *rematch;
ARRAY *amatch;
int subexp_ind;
char *subexp_str;
int subexp_len;
#endif
int result;
#if defined (ARRAY_VARS)
rematch = (SHELL_VAR *)NULL;
#endif
rflags = REG_EXTENDED;
if (match_ignore_case)
rflags |= REG_ICASE;
#if !defined (ARRAY_VARS)
rflags |= REG_NOSUB;
#endif
if (regcomp (&regex, pattern, rflags))
return 2; /* flag for printing a warning here. */
#if defined (ARRAY_VARS)
matches = (regmatch_t *)malloc (sizeof (regmatch_t) * (regex.re_nsub + 1));
#else
matches = NULL;
#endif
/* man regexec: NULL PMATCH ignored if NMATCH == 0 */
if (regexec (&regex, string, matches ? regex.re_nsub + 1 : 0, matches, 0))
result = EXECUTION_FAILURE;
else
result = EXECUTION_SUCCESS; /* match */
#if defined (ARRAY_VARS)
subexp_len = strlen (string) + 10;
subexp_str = malloc (subexp_len + 1);
/* Store the parenthesized subexpressions in the array BASH_REMATCH.
Element 0 is the portion that matched the entire regexp. Element 1
is the part that matched the first subexpression, and so on. */
#if 1
unbind_global_variable_noref ("BASH_REMATCH");
rematch = make_new_array_variable ("BASH_REMATCH");
#else
/* TAG:bash-5.3 */
rematch = builtin_find_indexed_array ("BASH_REMATCH", 1);
#endif
amatch = rematch ? array_cell (rematch) : (ARRAY *)0;
if (matches && amatch && (flags & SHMAT_SUBEXP) && result == EXECUTION_SUCCESS && subexp_str)
{
for (subexp_ind = 0; subexp_ind <= regex.re_nsub; subexp_ind++)
{
memset (subexp_str, 0, subexp_len);
strncpy (subexp_str, string + matches[subexp_ind].rm_so,
matches[subexp_ind].rm_eo - matches[subexp_ind].rm_so);
array_insert (amatch, subexp_ind, subexp_str);
}
}
#if 0
VSETATTR (rematch, att_readonly);
#endif
free (subexp_str);
free (matches);
#endif /* ARRAY_VARS */
regfree (&regex);
return result;
}
#endif /* HAVE_POSIX_REGEXP */

137
lib/sh/shmbchar.c Normal file
View file

@ -0,0 +1,137 @@
/* Copyright (C) 2001, 2006, 2009, 2010, 2012, 2015-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <shmbutil.h>
#include <shmbchar.h>
#ifndef errno
extern int errno;
#endif
#if IS_BASIC_ASCII
/* Bit table of characters in the ISO C "basic character set". */
const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
{
0x00001a00, /* '\t' '\v' '\f' */
0xffffffef, /* ' '...'#' '%'...'?' */
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
/* The remaining bits are 0. */
};
#endif /* IS_BASIC_ASCII */
extern int locale_utf8locale;
extern char *utf8_mbsmbchar (const char *);
extern int utf8_mblen (const char *, size_t);
/* Count the number of characters in S, counting multi-byte characters as a
single character. */
size_t
mbstrlen (s)
const char *s;
{
size_t clen, nc;
mbstate_t mbs = { 0 }, mbsbak = { 0 };
int f, mb_cur_max;
nc = 0;
mb_cur_max = MB_CUR_MAX;
while (*s && (clen = (f = is_basic (*s)) ? 1 : mbrlen(s, mb_cur_max, &mbs)) != 0)
{
if (MB_INVALIDCH(clen))
{
clen = 1; /* assume single byte */
mbs = mbsbak;
}
if (f == 0)
mbsbak = mbs;
s += clen;
nc++;
}
return nc;
}
/* Return pointer to first multibyte char in S, or NULL if none. */
/* XXX - if we know that the locale is UTF-8, we can just check whether or
not any byte has the eighth bit turned on */
char *
mbsmbchar (s)
const char *s;
{
char *t;
size_t clen;
mbstate_t mbs = { 0 };
int mb_cur_max;
if (locale_utf8locale)
return (utf8_mbsmbchar (s)); /* XXX */
mb_cur_max = MB_CUR_MAX;
for (t = (char *)s; *t; t++)
{
if (is_basic (*t))
continue;
if (locale_utf8locale) /* not used if above code active */
clen = utf8_mblen (t, mb_cur_max);
else
clen = mbrlen (t, mb_cur_max, &mbs);
if (clen == 0)
return 0;
if (MB_INVALIDCH(clen))
continue;
if (clen > 1)
return t;
}
return 0;
}
int
sh_mbsnlen(src, srclen, maxlen)
const char *src;
size_t srclen;
int maxlen;
{
int count;
int sind;
DECLARE_MBSTATE;
for (sind = count = 0; src[sind]; )
{
count++; /* number of multibyte characters */
ADVANCE_CHAR (src, srclen, sind);
if (sind > maxlen)
break;
}
return count;
}
#endif

432
lib/sh/shquote.c Normal file
View file

@ -0,0 +1,432 @@
/* shquote - functions to quote and dequote strings */
/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdc.h>
#include "syntax.h"
#include <xmalloc.h>
#include "shmbchar.h"
#include "shmbutil.h"
extern char *ansic_quote PARAMS((char *, int, int *));
extern int ansic_shouldquote PARAMS((const char *));
/* Default set of characters that should be backslash-quoted in strings */
static const char bstab[256] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
/* **************************************************************** */
/* */
/* Functions for quoting strings to be re-read as input */
/* */
/* **************************************************************** */
/* Return a new string which is the single-quoted version of STRING.
Used by alias and trap, among others. */
char *
sh_single_quote (string)
const char *string;
{
register int c;
char *result, *r;
const char *s;
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
if (string[0] == '\'' && string[1] == 0)
{
*r++ = '\\';
*r++ = '\'';
*r++ = 0;
return result;
}
*r++ = '\'';
for (s = string; s && (c = *s); s++)
{
*r++ = c;
if (c == '\'')
{
*r++ = '\\'; /* insert escaped single quote */
*r++ = '\'';
*r++ = '\''; /* start new quoted string */
}
}
*r++ = '\'';
*r = '\0';
return (result);
}
/* Quote STRING using double quotes. Return a new string. */
char *
sh_double_quote (string)
const char *string;
{
register unsigned char c;
int mb_cur_max;
char *result, *r;
size_t slen;
const char *s, *send;
DECLARE_MBSTATE;
slen = strlen (string);
send = string + slen;
mb_cur_max = MB_CUR_MAX;
result = (char *)xmalloc (3 + (2 * strlen (string)));
r = result;
*r++ = '"';
for (s = string; s && (c = *s); s++)
{
/* Backslash-newline disappears within double quotes, so don't add one. */
if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
*r++ = '\\';
#if defined (HANDLE_MULTIBYTE)
if ((locale_utf8locale && (c & 0x80)) ||
(locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
{
COPY_CHAR_P (r, s, send);
s--; /* compensate for auto-increment in loop above */
continue;
}
#endif
/* Assume that the string will not be further expanded, so no need to
add CTLESC to protect CTLESC or CTLNUL. */
*r++ = c;
}
*r++ = '"';
*r = '\0';
return (result);
}
/* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote
double quote characters in S with backslashes. */
char *
sh_mkdoublequoted (s, slen, flags)
const char *s;
int slen, flags;
{
char *r, *ret;
const char *send;
int rlen, mb_cur_max;
DECLARE_MBSTATE;
send = s + slen;
mb_cur_max = flags ? MB_CUR_MAX : 1;
rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
ret = r = (char *)xmalloc (rlen);
*r++ = '"';
while (*s)
{
if (flags && *s == '"')
*r++ = '\\';
#if defined (HANDLE_MULTIBYTE)
if (flags && ((locale_utf8locale && (*s & 0x80)) ||
(locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (*s) == 0)))
{
COPY_CHAR_P (r, s, send);
continue;
}
#endif
*r++ = *s++;
}
*r++ = '"';
*r = '\0';
return ret;
}
/* Remove backslashes that are quoting characters that are special between
double quotes. Return a new string. XXX - should this handle CTLESC
and CTLNUL? */
char *
sh_un_double_quote (string)
char *string;
{
register int c, pass_next;
char *result, *r, *s;
r = result = (char *)xmalloc (strlen (string) + 1);
for (pass_next = 0, s = string; s && (c = *s); s++)
{
if (pass_next)
{
*r++ = c;
pass_next = 0;
continue;
}
if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
{
pass_next = 1;
continue;
}
*r++ = c;
}
*r = '\0';
return result;
}
/* Quote special characters in STRING using backslashes. Return a new
string. NOTE: if the string is to be further expanded, we need a
way to protect the CTLESC and CTLNUL characters. As I write this,
the current callers will never cause the string to be expanded without
going through the shell parser, which will protect the internal
quoting characters. TABLE, if set, points to a map of the ascii code
set with char needing to be backslash-quoted if table[char]==1. FLAGS,
if 1, causes tildes to be quoted as well. If FLAGS&2, backslash-quote
other shell blank characters. */
char *
sh_backslash_quote (string, table, flags)
char *string;
char *table;
int flags;
{
int c, mb_cur_max;
size_t slen;
char *result, *r, *s, *backslash_table, *send;
DECLARE_MBSTATE;
slen = strlen (string);
send = string + slen;
result = (char *)xmalloc (2 * slen + 1);
backslash_table = table ? table : (char *)bstab;
mb_cur_max = MB_CUR_MAX;
for (r = result, s = string; s && (c = *s); s++)
{
#if defined (HANDLE_MULTIBYTE)
/* XXX - isascii, even if is_basic(c) == 0 - works in most cases. */
if (c >= 0 && c <= 127 && backslash_table[(unsigned char)c] == 1)
{
*r++ = '\\';
*r++ = c;
continue;
}
if ((locale_utf8locale && (c & 0x80)) ||
(locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
{
COPY_CHAR_P (r, s, send);
s--; /* compensate for auto-increment in loop above */
continue;
}
#endif
if (backslash_table[(unsigned char)c] == 1)
*r++ = '\\';
else if (c == '#' && s == string) /* comment char */
*r++ = '\\';
else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
/* Tildes are special at the start of a word or after a `:' or `='
(technically unquoted, but it doesn't make a difference in practice) */
*r++ = '\\';
else if ((flags&2) && shellblank((unsigned char)c))
*r++ = '\\';
*r++ = c;
}
*r = '\0';
return (result);
}
#if defined (PROMPT_STRING_DECODE) || defined (TRANSLATABLE_STRINGS)
/* Quote characters that get special treatment when in double quotes in STRING
using backslashes. FLAGS is reserved for future use. Return a new string. */
char *
sh_backslash_quote_for_double_quotes (string, flags)
char *string;
int flags;
{
unsigned char c;
char *result, *r, *s, *send;
size_t slen;
int mb_cur_max;
DECLARE_MBSTATE;
slen = strlen (string);
send = string + slen;
mb_cur_max = MB_CUR_MAX;
result = (char *)xmalloc (2 * slen + 1);
for (r = result, s = string; s && (c = *s); s++)
{
/* Backslash-newline disappears within double quotes, so don't add one. */
if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
*r++ = '\\';
/* I should probably use the CSPECL flag for these in sh_syntaxtab[] */
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
#if defined (HANDLE_MULTIBYTE)
if ((locale_utf8locale && (c & 0x80)) ||
(locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
{
COPY_CHAR_P (r, s, send);
s--; /* compensate for auto-increment in loop above */
continue;
}
#endif
*r++ = c;
}
*r = '\0';
return (result);
}
#endif /* PROMPT_STRING_DECODE */
char *
sh_quote_reusable (s, flags)
char *s;
int flags;
{
char *ret;
if (s == 0)
return s;
else if (*s == 0)
{
ret = (char *)xmalloc (3);
ret[0] = ret[1] = '\'';
ret[2] = '\0';
}
else if (ansic_shouldquote (s))
ret = ansic_quote (s, 0, (int *)0);
else if (flags)
ret = sh_backslash_quote (s, 0, 1);
else
ret = sh_single_quote (s);
return ret;
}
int
sh_contains_shell_metas (string)
const char *string;
{
const char *s;
for (s = string; s && *s; s++)
{
switch (*s)
{
case ' ': case '\t': case '\n': /* IFS white space */
case '\'': case '"': case '\\': /* quoting chars */
case '|': case '&': case ';': /* shell metacharacters */
case '(': case ')': case '<': case '>':
case '!': case '{': case '}': /* reserved words */
case '*': case '[': case '?': case ']': /* globbing chars */
case '^':
case '$': case '`': /* expansion chars */
return (1);
case '~': /* tilde expansion */
if (s == string || s[-1] == '=' || s[-1] == ':')
return (1);
break;
case '#':
if (s == string) /* comment char */
return (1);
/* FALLTHROUGH */
default:
break;
}
}
return (0);
}
int
sh_contains_quotes (string)
const char *string;
{
const char *s;
for (s = string; s && *s; s++)
{
if (*s == '\'' || *s == '"' || *s == '\\')
return 1;
}
return 0;
}

330
lib/sh/shtty.c Normal file
View file

@ -0,0 +1,330 @@
/*
* shtty.c -- abstract interface to the terminal, focusing on capabilities.
*/
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <shtty.h>
static TTYSTRUCT ttin, ttout;
static int ttsaved = 0;
int
ttgetattr(fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
#ifdef TERMIOS_TTY_DRIVER
return tcgetattr(fd, ttp);
#else
# ifdef TERMIO_TTY_DRIVER
return ioctl(fd, TCGETA, ttp);
# else
return ioctl(fd, TIOCGETP, ttp);
# endif
#endif
}
int
ttsetattr(fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
#ifdef TERMIOS_TTY_DRIVER
return tcsetattr(fd, TCSADRAIN, ttp);
#else
# ifdef TERMIO_TTY_DRIVER
return ioctl(fd, TCSETAW, ttp);
# else
return ioctl(fd, TIOCSETN, ttp);
# endif
#endif
}
void
ttsave()
{
if (ttsaved)
return;
ttgetattr (0, &ttin);
ttgetattr (1, &ttout);
ttsaved = 1;
}
void
ttrestore()
{
if (ttsaved == 0)
return;
ttsetattr (0, &ttin);
ttsetattr (1, &ttout);
ttsaved = 0;
}
/* Retrieve the internally-saved attributes associated with tty fd FD. */
TTYSTRUCT *
ttattr (fd)
int fd;
{
if (ttsaved == 0)
return ((TTYSTRUCT *)0);
if (fd == 0)
return &ttin;
else if (fd == 1)
return &ttout;
else
return ((TTYSTRUCT *)0);
}
/*
* Change attributes in ttp so that when it is installed using
* ttsetattr, the terminal will be in one-char-at-a-time mode.
*/
int
tt_setonechar(ttp)
TTYSTRUCT *ttp;
{
#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
/* XXX - might not want this -- it disables erase and kill processing. */
ttp->c_lflag &= ~ICANON;
ttp->c_lflag |= ISIG;
# ifdef IEXTEN
ttp->c_lflag |= IEXTEN;
# endif
ttp->c_iflag |= ICRNL; /* make sure we get CR->NL on input */
ttp->c_iflag &= ~INLCR; /* but no NL->CR */
# ifdef OPOST
ttp->c_oflag |= OPOST;
# endif
# ifdef ONLCR
ttp->c_oflag |= ONLCR;
# endif
# ifdef OCRNL
ttp->c_oflag &= ~OCRNL;
# endif
# ifdef ONOCR
ttp->c_oflag &= ~ONOCR;
# endif
# ifdef ONLRET
ttp->c_oflag &= ~ONLRET;
# endif
ttp->c_cc[VMIN] = 1;
ttp->c_cc[VTIME] = 0;
#else
ttp->sg_flags |= CBREAK;
#endif
return 0;
}
/* Set the tty associated with FD and TTP into one-character-at-a-time mode */
int
ttfd_onechar (fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
if (tt_setonechar(ttp) < 0)
return -1;
return (ttsetattr (fd, ttp));
}
/* Set the terminal into one-character-at-a-time mode */
int
ttonechar ()
{
TTYSTRUCT tt;
if (ttsaved == 0)
return -1;
tt = ttin;
return (ttfd_onechar (0, &tt));
}
/*
* Change attributes in ttp so that when it is installed using
* ttsetattr, the terminal will be in no-echo mode.
*/
int
tt_setnoecho(ttp)
TTYSTRUCT *ttp;
{
#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
ttp->c_lflag &= ~(ECHO|ECHOK|ECHONL);
#else
ttp->sg_flags &= ~ECHO;
#endif
return 0;
}
/* Set the tty associated with FD and TTP into no-echo mode */
int
ttfd_noecho (fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
if (tt_setnoecho (ttp) < 0)
return -1;
return (ttsetattr (fd, ttp));
}
/* Set the terminal into no-echo mode */
int
ttnoecho ()
{
TTYSTRUCT tt;
if (ttsaved == 0)
return -1;
tt = ttin;
return (ttfd_noecho (0, &tt));
}
/*
* Change attributes in ttp so that when it is installed using
* ttsetattr, the terminal will be in eight-bit mode (pass8).
*/
int
tt_seteightbit (ttp)
TTYSTRUCT *ttp;
{
#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
ttp->c_iflag &= ~ISTRIP;
ttp->c_cflag |= CS8;
ttp->c_cflag &= ~PARENB;
#else
ttp->sg_flags |= ANYP;
#endif
return 0;
}
/* Set the tty associated with FD and TTP into eight-bit mode */
int
ttfd_eightbit (fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
if (tt_seteightbit (ttp) < 0)
return -1;
return (ttsetattr (fd, ttp));
}
/* Set the terminal into eight-bit mode */
int
tteightbit ()
{
TTYSTRUCT tt;
if (ttsaved == 0)
return -1;
tt = ttin;
return (ttfd_eightbit (0, &tt));
}
/*
* Change attributes in ttp so that when it is installed using
* ttsetattr, the terminal will be in non-canonical input mode.
*/
int
tt_setnocanon (ttp)
TTYSTRUCT *ttp;
{
#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
ttp->c_lflag &= ~ICANON;
#endif
return 0;
}
/* Set the tty associated with FD and TTP into non-canonical mode */
int
ttfd_nocanon (fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
if (tt_setnocanon (ttp) < 0)
return -1;
return (ttsetattr (fd, ttp));
}
/* Set the terminal into non-canonical mode */
int
ttnocanon ()
{
TTYSTRUCT tt;
if (ttsaved == 0)
return -1;
tt = ttin;
return (ttfd_nocanon (0, &tt));
}
/*
* Change attributes in ttp so that when it is installed using
* ttsetattr, the terminal will be in cbreak, no-echo mode.
*/
int
tt_setcbreak(ttp)
TTYSTRUCT *ttp;
{
if (tt_setonechar (ttp) < 0)
return -1;
return (tt_setnoecho (ttp));
}
/* Set the tty associated with FD and TTP into cbreak (no-echo,
one-character-at-a-time) mode */
int
ttfd_cbreak (fd, ttp)
int fd;
TTYSTRUCT *ttp;
{
if (tt_setcbreak (ttp) < 0)
return -1;
return (ttsetattr (fd, ttp));
}
/* Set the terminal into cbreak (no-echo, one-character-at-a-time) mode */
int
ttcbreak ()
{
TTYSTRUCT tt;
if (ttsaved == 0)
return -1;
tt = ttin;
return (ttfd_cbreak (0, &tt));
}

2221
lib/sh/snprintf.c Normal file

File diff suppressed because it is too large Load diff

212
lib/sh/spell.c Normal file
View file

@ -0,0 +1,212 @@
/* spell.c -- spelling correction for pathnames. */
/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <bashtypes.h>
#include <posixdir.h>
#include <posixstat.h>
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
#include <stdio.h>
#include <bashansi.h>
#include <maxpath.h>
#include <stdc.h>
static int mindist PARAMS((char *, char *, char *));
static int spdist PARAMS((char *, char *));
/*
* `spname' and its helpers are inspired by the code in "The UNIX
* Programming Environment", Kernighan & Pike, Prentice-Hall 1984,
* pages 209 - 213.
*/
/*
* `spname' -- return a correctly spelled filename
*
* int spname(char * oldname, char * newname)
* Returns: -1 if no reasonable match found
* 0 if exact match found
* 1 if corrected
* Stores corrected name in `newname'.
*/
int
spname(oldname, newname)
char *oldname;
char *newname;
{
char *op, *np, *p;
char guess[PATH_MAX + 1], best[PATH_MAX + 1];
op = oldname;
np = newname;
for (;;)
{
while (*op == '/') /* Skip slashes */
*np++ = *op++;
*np = '\0';
if (*op == '\0') /* Exact or corrected */
{
/* `.' is rarely the right thing. */
if (oldname[1] == '\0' && newname[1] == '\0' &&
oldname[0] != '.' && newname[0] == '.')
return -1;
return strcmp(oldname, newname) != 0;
}
/* Copy next component into guess */
for (p = guess; *op != '/' && *op != '\0'; op++)
if (p < guess + PATH_MAX)
*p++ = *op;
*p = '\0';
if (mindist(newname, guess, best) >= 3)
return -1; /* Hopeless */
/*
* Add to end of newname
*/
for (p = best; *np = *p++; np++)
;
}
}
/*
* Search directory for a guess
*/
static int
mindist(dir, guess, best)
char *dir;
char *guess;
char *best;
{
DIR *fd;
struct dirent *dp;
int dist, x;
dist = 3; /* Worst distance */
if (*dir == '\0')
dir = ".";
if ((fd = opendir(dir)) == NULL)
return dist;
while ((dp = readdir(fd)) != NULL)
{
/*
* Look for a better guess. If the new guess is as
* good as the current one, we take it. This way,
* any single character match will be a better match
* than ".".
*/
x = spdist(dp->d_name, guess);
if (x <= dist && x != 3)
{
strcpy(best, dp->d_name);
dist = x;
if (dist == 0) /* Exact match */
break;
}
}
(void)closedir(fd);
/* Don't return `.' */
if (best[0] == '.' && best[1] == '\0')
dist = 3;
return dist;
}
/*
* `spdist' -- return the "distance" between two names.
*
* int spname(char * oldname, char * newname)
* Returns: 0 if strings are identical
* 1 if two characters are transposed
* 2 if one character is wrong, added or deleted
* 3 otherwise
*/
static int
spdist(cur, new)
char *cur, *new;
{
while (*cur == *new)
{
if (*cur == '\0')
return 0; /* Exact match */
cur++;
new++;
}
if (*cur)
{
if (*new)
{
if (cur[1] && new[1] && cur[0] == new[1] && cur[1] == new[0] && strcmp (cur + 2, new + 2) == 0)
return 1; /* Transposition */
if (strcmp (cur + 1, new + 1) == 0)
return 2; /* One character mismatch */
}
if (strcmp(&cur[1], &new[0]) == 0)
return 2; /* Extra character */
}
if (*new && strcmp(cur, new + 1) == 0)
return 2; /* Missing character */
return 3;
}
char *
dirspell (dirname)
char *dirname;
{
int n;
char *guess;
n = (strlen (dirname) * 3 + 1) / 2 + 1;
guess = (char *)malloc (n);
if (guess == 0)
return 0;
switch (spname (dirname, guess))
{
case -1:
default:
free (guess);
return (char *)NULL;
case 0:
case 1:
return guess;
}
}

84
lib/sh/strcasecmp.c Normal file
View file

@ -0,0 +1,84 @@
/* strcasecmp.c - functions for case-insensitive string comparison. */
/* Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_STRCASECMP)
#include <stdc.h>
#include <bashansi.h>
#include <chartypes.h>
/* Compare at most COUNT characters from string1 to string2. Case
doesn't matter. */
int
strncasecmp (string1, string2, count)
const char *string1;
const char *string2;
size_t count;
{
register const char *s1;
register const char *s2;
register int r;
if (count <= 0 || (string1 == string2))
return 0;
s1 = string1;
s2 = string2;
do
{
if ((r = TOLOWER ((unsigned char) *s1) - TOLOWER ((unsigned char) *s2)) != 0)
return r;
if (*s1++ == '\0')
break;
s2++;
}
while (--count != 0);
return (0);
}
/* strcmp (), but caseless. */
int
strcasecmp (string1, string2)
const char *string1;
const char *string2;
{
register const char *s1;
register const char *s2;
register int r;
s1 = string1;
s2 = string2;
if (s1 == s2)
return (0);
while ((r = TOLOWER ((unsigned char)*s1) - TOLOWER ((unsigned char)*s2)) == 0)
{
if (*s1++ == '\0')
return 0;
s2++;
}
return (r);
}
#endif /* !HAVE_STRCASECMP */

46
lib/sh/strcasestr.c Normal file
View file

@ -0,0 +1,46 @@
/* strcasestr.c - Find if one string appears as a substring of another string,
without regard to case. */
/* Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashansi.h>
#include <chartypes.h>
#include <stdc.h>
/* Determine if s2 occurs in s1. If so, return a pointer to the
match in s1. The compare is case insensitive. This is a
case-insensitive strstr(3). */
char *
strcasestr (s1, s2)
const char *s1;
const char *s2;
{
register int i, l, len, c;
c = TOLOWER ((unsigned char)s2[0]);
len = strlen (s1);
l = strlen (s2);
for (i = 0; (len - i) >= l; i++)
if ((TOLOWER ((unsigned char)s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0))
return ((char *)s1 + i);
return ((char *)0);
}

35
lib/sh/strchrnul.c Normal file
View file

@ -0,0 +1,35 @@
/* Searching in a string.
Copyright (C) 2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
/* Specification. */
#include <string.h>
/* Find the first occurrence of C in S or the final NUL byte. */
char *
strchrnul (s, c_in)
const char *s;
int c_in;
{
char c;
register char *s1;
for (c = c_in, s1 = (char *)s; s1 && *s1 && *s1 != c; s1++)
;
return (s1);
}

41
lib/sh/strdup.c Normal file
View file

@ -0,0 +1,41 @@
/* strdup - return a copy of a string in newly-allocated memory. */
/* Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
/* Get specification. */
#include <string.h>
#include <stdlib.h>
/* Duplicate S, returning an identical malloc'd string. */
char *
strdup (s)
const char *s;
{
size_t len;
void *new;
len = strlen (s) + 1;
if ((new = malloc (len)) == NULL)
return NULL;
memcpy (new, s, len);
return ((char *)new);
}

74
lib/sh/strerror.c Normal file
View file

@ -0,0 +1,74 @@
/* strerror.c - string corresponding to a particular value of errno. */
/* Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_STRERROR)
#include <bashtypes.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <shell.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
/* Return a string corresponding to the error number E. From
the ANSI C spec. */
#if defined (strerror)
# undef strerror
#endif
static char *errbase = "Unknown system error ";
char *
strerror (e)
int e;
{
static char emsg[40];
#if defined (HAVE_SYS_ERRLIST)
extern int sys_nerr;
extern char *sys_errlist[];
if (e > 0 && e < sys_nerr)
return (sys_errlist[e]);
else
#endif /* HAVE_SYS_ERRLIST */
{
char *z;
z = itos (e);
strcpy (emsg, errbase);
strcat (emsg, z);
free (z);
return (&emsg[0]);
}
}
#endif /* HAVE_STRERROR */

1012
lib/sh/strftime.c Normal file

File diff suppressed because it is too large Load diff

297
lib/sh/stringlist.c Normal file
View file

@ -0,0 +1,297 @@
/* stringlist.c - functions to handle a generic `list of strings' structure */
/* Copyright (C) 2000-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <bashansi.h>
#include "shell.h"
#ifdef STRDUP
# undef STRDUP
#endif
#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
/* Allocate a new STRINGLIST, with room for N strings. */
STRINGLIST *
strlist_create (n)
int n;
{
STRINGLIST *ret;
register int i;
ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
if (n)
{
ret->list = strvec_create (n+1);
ret->list_size = n;
for (i = 0; i < n; i++)
ret->list[i] = (char *)NULL;
}
else
{
ret->list = (char **)NULL;
ret->list_size = 0;
}
ret->list_len = 0;
return ret;
}
STRINGLIST *
strlist_resize (sl, n)
STRINGLIST *sl;
int n;
{
register int i;
if (sl == 0)
return (sl = strlist_create (n));
if (n > sl->list_size)
{
sl->list = strvec_resize (sl->list, n + 1);
for (i = sl->list_size; i <= n; i++)
sl->list[i] = (char *)NULL;
sl->list_size = n;
}
return sl;
}
void
strlist_flush (sl)
STRINGLIST *sl;
{
if (sl == 0 || sl->list == 0)
return;
strvec_flush (sl->list);
sl->list_len = 0;
}
void
strlist_dispose (sl)
STRINGLIST *sl;
{
if (sl == 0)
return;
if (sl->list)
strvec_dispose (sl->list);
free (sl);
}
int
strlist_remove (sl, s)
STRINGLIST *sl;
char *s;
{
int r;
if (sl == 0 || sl->list == 0 || sl->list_len == 0)
return 0;
r = strvec_remove (sl->list, s);
if (r)
sl->list_len--;
return r;
}
STRINGLIST *
strlist_copy (sl)
STRINGLIST *sl;
{
STRINGLIST *new;
register int i;
if (sl == 0)
return ((STRINGLIST *)0);
new = strlist_create (sl->list_size);
/* I'd like to use strvec_copy, but that doesn't copy everything. */
if (sl->list)
{
for (i = 0; i < sl->list_size; i++)
new->list[i] = STRDUP (sl->list[i]);
}
new->list_size = sl->list_size;
new->list_len = sl->list_len;
/* just being careful */
if (new->list)
new->list[new->list_len] = (char *)NULL;
return new;
}
/* Return a new STRINGLIST with everything from M1 and M2. */
STRINGLIST *
strlist_merge (m1, m2)
STRINGLIST *m1, *m2;
{
STRINGLIST *sl;
int i, n, l1, l2;
l1 = m1 ? m1->list_len : 0;
l2 = m2 ? m2->list_len : 0;
sl = strlist_create (l1 + l2 + 1);
for (i = n = 0; i < l1; i++, n++)
sl->list[n] = STRDUP (m1->list[i]);
for (i = 0; i < l2; i++, n++)
sl->list[n] = STRDUP (m2->list[i]);
sl->list_len = n;
sl->list[n] = (char *)NULL;
return (sl);
}
/* Make STRINGLIST M1 contain everything in M1 and M2. */
STRINGLIST *
strlist_append (m1, m2)
STRINGLIST *m1, *m2;
{
register int i, n, len1, len2;
if (m1 == 0)
return (m2 ? strlist_copy (m2) : (STRINGLIST *)0);
len1 = m1->list_len;
len2 = m2 ? m2->list_len : 0;
if (len2)
{
m1 = strlist_resize (m1, len1 + len2 + 1);
for (i = 0, n = len1; i < len2; i++, n++)
m1->list[n] = STRDUP (m2->list[i]);
m1->list[n] = (char *)NULL;
m1->list_len = n;
}
return m1;
}
STRINGLIST *
strlist_prefix_suffix (sl, prefix, suffix)
STRINGLIST *sl;
char *prefix, *suffix;
{
int plen, slen, tlen, llen, i;
char *t;
if (sl == 0 || sl->list == 0 || sl->list_len == 0)
return sl;
plen = STRLEN (prefix);
slen = STRLEN (suffix);
if (plen == 0 && slen == 0)
return (sl);
for (i = 0; i < sl->list_len; i++)
{
llen = STRLEN (sl->list[i]);
tlen = plen + llen + slen + 1;
t = (char *)xmalloc (tlen + 1);
if (plen)
strcpy (t, prefix);
strcpy (t + plen, sl->list[i]);
if (slen)
strcpy (t + plen + llen, suffix);
free (sl->list[i]);
sl->list[i] = t;
}
return (sl);
}
void
strlist_print (sl, prefix)
STRINGLIST *sl;
char *prefix;
{
register int i;
if (sl == 0)
return;
for (i = 0; i < sl->list_len; i++)
printf ("%s%s\n", prefix ? prefix : "", sl->list[i]);
}
void
strlist_walk (sl, func)
STRINGLIST *sl;
sh_strlist_map_func_t *func;
{
register int i;
if (sl == 0)
return;
for (i = 0; i < sl->list_len; i++)
if ((*func)(sl->list[i]) < 0)
break;
}
void
strlist_sort (sl)
STRINGLIST *sl;
{
if (sl == 0 || sl->list_len == 0 || sl->list == 0)
return;
strvec_sort (sl->list, 0);
}
STRINGLIST *
strlist_from_word_list (list, alloc, starting_index, ip)
WORD_LIST *list;
int alloc, starting_index, *ip;
{
STRINGLIST *ret;
int slen, len;
if (list == 0)
{
if (ip)
*ip = 0;
return ((STRINGLIST *)0);
}
slen = list_length (list);
ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
ret->list = strvec_from_word_list (list, alloc, starting_index, &len);
ret->list_size = slen + starting_index;
ret->list_len = len;
if (ip)
*ip = len;
return ret;
}
WORD_LIST *
strlist_to_word_list (sl, alloc, starting_index)
STRINGLIST *sl;
int alloc, starting_index;
{
WORD_LIST *list;
if (sl == 0 || sl->list == 0)
return ((WORD_LIST *)NULL);
list = strvec_to_word_list (sl->list, alloc, starting_index);
return list;
}

272
lib/sh/stringvec.c Normal file
View file

@ -0,0 +1,272 @@
/* stringvec.c - functions for managing arrays of strings. */
/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <bashansi.h>
#include <stdio.h>
#include <chartypes.h>
#include "shell.h"
/* Allocate an array of strings with room for N members. */
char **
strvec_create (n)
int n;
{
return ((char **)xmalloc ((n) * sizeof (char *)));
}
/* Allocate an array of strings with room for N members. */
char **
strvec_mcreate (n)
int n;
{
return ((char **)malloc ((n) * sizeof (char *)));
}
char **
strvec_resize (array, nsize)
char **array;
int nsize;
{
return ((char **)xrealloc (array, nsize * sizeof (char *)));
}
char **
strvec_mresize (array, nsize)
char **array;
int nsize;
{
return ((char **)realloc (array, nsize * sizeof (char *)));
}
/* Return the length of ARRAY, a NULL terminated array of char *. */
int
strvec_len (array)
char **array;
{
register int i;
for (i = 0; array[i]; i++);
return (i);
}
/* Free the contents of ARRAY, a NULL terminated array of char *. */
void
strvec_flush (array)
char **array;
{
register int i;
if (array == 0)
return;
for (i = 0; array[i]; i++)
free (array[i]);
}
void
strvec_dispose (array)
char **array;
{
if (array == 0)
return;
strvec_flush (array);
free (array);
}
int
strvec_remove (array, name)
char **array, *name;
{
register int i, j;
char *x;
if (array == 0)
return 0;
for (i = 0; array[i]; i++)
if (STREQ (name, array[i]))
{
x = array[i];
for (j = i; array[j]; j++)
array[j] = array[j + 1];
free (x);
return 1;
}
return 0;
}
/* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
ARRAY should be NULL terminated. */
int
strvec_search (array, name)
char **array, *name;
{
int i;
for (i = 0; array[i]; i++)
if (STREQ (name, array[i]))
return (i);
return (-1);
}
/* Allocate and return a new copy of ARRAY and its contents. */
char **
strvec_copy (array)
char **array;
{
register int i;
int len;
char **ret;
len = strvec_len (array);
ret = (char **)xmalloc ((len + 1) * sizeof (char *));
for (i = 0; array[i]; i++)
ret[i] = savestring (array[i]);
ret[i] = (char *)NULL;
return (ret);
}
/* Comparison routine for use by qsort that conforms to the new Posix
requirements (http://austingroupbugs.net/view.php?id=1070).
Perform a bytewise comparison if *S1 and *S2 collate equally. */
int
strvec_posixcmp (s1, s2)
register char **s1, **s2;
{
int result;
#if defined (HAVE_STRCOLL)
result = strcoll (*s1, *s2);
if (result != 0)
return result;
#endif
if ((result = **s1 - **s2) == 0)
result = strcmp (*s1, *s2);
return (result);
}
/* Comparison routine for use with qsort() on arrays of strings. Uses
strcoll(3) if available, otherwise it uses strcmp(3). */
int
strvec_strcmp (s1, s2)
register char **s1, **s2;
{
#if defined (HAVE_STRCOLL)
return (strcoll (*s1, *s2));
#else /* !HAVE_STRCOLL */
int result;
if ((result = **s1 - **s2) == 0)
result = strcmp (*s1, *s2);
return (result);
#endif /* !HAVE_STRCOLL */
}
/* Sort ARRAY, a null terminated array of pointers to strings. */
void
strvec_sort (array, posix)
char **array;
int posix;
{
if (posix)
qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_posixcmp);
else
qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp);
}
/* Cons up a new array of words. The words are taken from LIST,
which is a WORD_LIST *. If ALLOC is true, everything is malloc'ed,
so you should free everything in this array when you are done.
The array is NULL terminated. If IP is non-null, it gets the
number of words in the returned array. STARTING_INDEX says where
to start filling in the returned array; it can be used to reserve
space at the beginning of the array. */
char **
strvec_from_word_list (list, alloc, starting_index, ip)
WORD_LIST *list;
int alloc, starting_index, *ip;
{
int count;
char **array;
count = list_length (list);
array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
for (count = 0; count < starting_index; count++)
array[count] = (char *)NULL;
for (count = starting_index; list; count++, list = list->next)
array[count] = alloc ? savestring (list->word->word) : list->word->word;
array[count] = (char *)NULL;
if (ip)
*ip = count;
return (array);
}
/* Convert an array of strings into the form used internally by the shell.
ALLOC means to allocate new storage for each WORD_DESC in the returned
list rather than copy the values in ARRAY. STARTING_INDEX says where
in ARRAY to begin. */
WORD_LIST *
strvec_to_word_list (array, alloc, starting_index)
char **array;
int alloc, starting_index;
{
WORD_LIST *list;
WORD_DESC *w;
int i, count;
if (array == 0 || array[0] == 0)
return (WORD_LIST *)NULL;
for (count = 0; array[count]; count++)
;
for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
{
w = make_bare_word (alloc ? array[i] : "");
if (alloc == 0)
{
free (w->word);
w->word = array[i];
}
list = make_word_list (w, list);
}
return (REVERSE_LIST (list, WORD_LIST *));
}

49
lib/sh/strnlen.c Normal file
View file

@ -0,0 +1,49 @@
/* strnlen - return length of passed string, with length limit */
/* Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if !defined (HAVE_STRNLEN)
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdc.h>
/* Find the length of S, but scan at most MAXLEN characters. If no '\0'
terminator is found within the first MAXLEN characters, return MAXLEN. */
size_t
strnlen (s, maxlen)
register const char *s;
size_t maxlen;
{
register const char *e;
size_t n;
for (e = s, n = 0; *e && n < maxlen; e++, n++)
;
return n;
}
#endif

49
lib/sh/strpbrk.c Normal file
View file

@ -0,0 +1,49 @@
/* strpbrk.c - locate multiple characters in a string */
/* Copyright (C) 1991, 1994 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if !defined (HAVE_STRPBRK)
#include <stdc.h>
/* Find the first occurrence in S of any character in ACCEPT. */
char *
strpbrk (s, accept)
register const char *s;
register const char *accept;
{
while (*s != '\0')
{
const char *a = accept;
while (*a != '\0')
if (*a++ == *s)
return (char *) s;
++s;
}
return 0;
}
#endif

125
lib/sh/strstr.c Normal file
View file

@ -0,0 +1,125 @@
/* strstr - find a substring within a string */
/* Copyright (C) 1994, 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* My personal strstr() implementation that beats most other algorithms.
* Until someone tells me otherwise, I assume that this is the
* fastest implementation of strstr() in C.
* I deliberately chose not to comment it. You should have at least
* as much fun trying to understand it, as I had to write it :-).
*
* Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if defined _LIBC || defined HAVE_STRING_H
# include <string.h>
#endif
#include <sys/types.h>
typedef unsigned chartype;
#undef strstr
char *
strstr (const char *phaystack, const char *pneedle)
{
register const unsigned char *haystack, *needle;
register chartype b, c;
haystack = (const unsigned char *) phaystack;
needle = (const unsigned char *) pneedle;
b = *needle;
if (b != '\0')
{
haystack--; /* possible ANSI violation */
do
{
c = *++haystack;
if (c == '\0')
goto ret0;
}
while (c != b);
c = *++needle;
if (c == '\0')
goto foundneedle;
++needle;
goto jin;
for (;;)
{
register chartype a;
register const unsigned char *rhaystack, *rneedle;
do
{
a = *++haystack;
if (a == '\0')
goto ret0;
if (a == b)
break;
a = *++haystack;
if (a == '\0')
goto ret0;
shloop:; }
while (a != b);
jin: a = *++haystack;
if (a == '\0')
goto ret0;
if (a != c)
goto shloop;
rhaystack = haystack-- + 1;
rneedle = needle;
a = *rneedle;
if (*rhaystack == a)
do
{
if (a == '\0')
goto foundneedle;
++rhaystack;
a = *++needle;
if (*rhaystack != a)
break;
if (a == '\0')
goto foundneedle;
++rhaystack;
a = *++needle;
}
while (*rhaystack == a);
needle = rneedle; /* took the register-poor approach */
if (a == '\0')
break;
}
}
foundneedle:
return (char*) haystack;
ret0:
return 0;
}

207
lib/sh/strtod.c Normal file
View file

@ -0,0 +1,207 @@
/* strtod.c - convert string to double-precision floating-point value. */
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef HAVE_STRTOD
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#include <chartypes.h>
#include <math.h>
#if HAVE_FLOAT_H
# include <float.h>
#else
# define DBL_MAX 1.7976931348623159e+308
# define DBL_MIN 2.2250738585072010e-308
#endif
#include <bashansi.h>
#ifndef NULL
# define NULL 0
#endif
#ifndef HUGE_VAL
# define HUGE_VAL HUGE
#endif
#ifndef locale_decpoint
extern int locale_decpoint PARAMS((void));
#endif
/* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the
character after the last one used in the number is put in *ENDPTR. */
double
strtod (nptr, endptr)
const char *nptr;
char **endptr;
{
register const char *s;
short sign;
/* The number so far. */
double num;
int radixchar;
int got_dot; /* Found a decimal point. */
int got_digit; /* Seen any digits. */
/* The exponent of the number. */
long int exponent;
if (nptr == NULL)
{
errno = EINVAL;
goto noconv;
}
s = nptr;
/* Eat whitespace. */
while (ISSPACE ((unsigned char)*s))
++s;
/* Get the sign. */
sign = *s == '-' ? -1 : 1;
if (*s == '-' || *s == '+')
++s;
radixchar = locale_decpoint ();
num = 0.0;
got_dot = 0;
got_digit = 0;
exponent = 0;
for (;; ++s)
{
if (DIGIT (*s))
{
got_digit = 1;
/* Make sure that multiplication by 10 will not overflow. */
if (num > DBL_MAX * 0.1)
/* The value of the digit doesn't matter, since we have already
gotten as many digits as can be represented in a `double'.
This doesn't necessarily mean the result will overflow.
The exponent may reduce it to within range.
We just need to record that there was another
digit so that we can multiply by 10 later. */
++exponent;
else
num = (num * 10.0) + (*s - '0');
/* Keep track of the number of digits after the decimal point.
If we just divided by 10 here, we would lose precision. */
if (got_dot)
--exponent;
}
else if (!got_dot && *s == radixchar)
/* Record that we have found the decimal point. */
got_dot = 1;
else
/* Any other character terminates the number. */
break;
}
if (!got_digit)
goto noconv;
if (TOLOWER ((unsigned char)*s) == 'e')
{
/* Get the exponent specified after the `e' or `E'. */
int save = errno;
char *end;
long int exp;
errno = 0;
++s;
exp = strtol (s, &end, 10);
if (errno == ERANGE)
{
/* The exponent overflowed a `long int'. It is probably a safe
assumption that an exponent that cannot be represented by
a `long int' exceeds the limits of a `double'. */
if (endptr != NULL)
*endptr = end;
if (exp < 0)
goto underflow;
else
goto overflow;
}
else if (end == s)
/* There was no exponent. Reset END to point to
the 'e' or 'E', so *ENDPTR will be set there. */
end = (char *) s - 1;
errno = save;
s = end;
exponent += exp;
}
if (endptr != NULL)
*endptr = (char *) s;
if (num == 0.0)
return 0.0;
/* Multiply NUM by 10 to the EXPONENT power,
checking for overflow and underflow. */
if (exponent < 0)
{
if (num < DBL_MIN * pow (10.0, (double) -exponent))
goto underflow;
}
else if (exponent > 0)
{
if (num > DBL_MAX * pow (10.0, (double) -exponent))
goto overflow;
}
num *= pow (10.0, (double) exponent);
return num * sign;
overflow:
/* Return an overflow error. */
errno = ERANGE;
return HUGE_VAL * sign;
underflow:
/* Return an underflow error. */
if (endptr != NULL)
*endptr = (char *) nptr;
errno = ERANGE;
return 0.0;
noconv:
/* There was no number. */
if (endptr != NULL)
*endptr = (char *) nptr;
return 0.0;
}
#endif /* !HAVE_STRTOD */

113
lib/sh/strtoimax.c Normal file
View file

@ -0,0 +1,113 @@
/* strtoimax - convert string representation of a number into an intmax_t value. */
/* Copyright 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Written by Paul Eggert. Modified by Chet Ramey for Bash. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <stdc.h>
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
#ifndef HAVE_DECL_STRTOL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOL
extern long strtol PARAMS((const char *, char **, int));
#endif
#ifndef HAVE_DECL_STRTOLL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG_INT
extern long long strtoll PARAMS((const char *, char **, int));
#endif
#ifdef strtoimax
#undef strtoimax
#endif
intmax_t
strtoimax (ptr, endptr, base)
const char *ptr;
char **endptr;
int base;
{
#if HAVE_LONG_LONG_INT
verify(size_is_that_of_long_or_long_long,
(sizeof (intmax_t) == sizeof (long) ||
sizeof (intmax_t) == sizeof (long long)));
if (sizeof (intmax_t) != sizeof (long))
return (strtoll (ptr, endptr, base));
#else
verify (size_is_that_of_long, sizeof (intmax_t) == sizeof (long));
#endif
return (strtol (ptr, endptr, base));
}
#ifdef TESTING
# include <stdio.h>
int
main ()
{
char *p, *endptr;
intmax_t x;
#if HAVE_LONG_LONG_INT
long long y;
#endif
long z;
printf ("sizeof intmax_t: %d\n", sizeof (intmax_t));
#if HAVE_LONG_LONG_INT
printf ("sizeof long long: %d\n", sizeof (long long));
#endif
printf ("sizeof long: %d\n", sizeof (long));
x = strtoimax("42", &endptr, 10);
#if HAVE_LONG_LONG_INT
y = strtoll("42", &endptr, 10);
#else
y = -1;
#endif
z = strtol("42", &endptr, 10);
printf ("%lld %lld %ld\n", x, y, z);
exit (0);
}
#endif

259
lib/sh/strtol.c Normal file
View file

@ -0,0 +1,259 @@
/* strtol - convert string representation of a number into a long integer value. */
/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !HAVE_STRTOL
#include <chartypes.h>
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#ifndef __set_errno
# define __set_errno(Val) errno = (Val)
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#include <typemax.h>
#include <stdc.h>
#include <bashansi.h>
#ifndef NULL
# define NULL 0
#endif
/* Nonzero if we are defining `strtoul' or `strtoull', operating on
unsigned integers. */
#ifndef UNSIGNED
# define UNSIGNED 0
# define INT LONG int
#else
# define INT unsigned LONG int
#endif
#if UNSIGNED
# ifdef QUAD
# define strtol strtoull
# else
# define strtol strtoul
# endif
#else
# ifdef QUAD
# define strtol strtoll
# endif
#endif
/* If QUAD is defined, we are defining `strtoll' or `strtoull',
operating on `long long ints. */
#ifdef QUAD
# define LONG long long
# define STRTOL_LONG_MIN LLONG_MIN
# define STRTOL_LONG_MAX LLONG_MAX
# define STRTOL_ULONG_MAX ULLONG_MAX
#else /* !QUAD */
# define LONG long
# define STRTOL_LONG_MIN LONG_MIN
# define STRTOL_LONG_MAX LONG_MAX
# define STRTOL_ULONG_MAX ULONG_MAX
#endif
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
If BASE is 0 the base is determined by the presence of a leading
zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
If BASE is < 2 or > 36, it is no longer reset to 10; EINVAL is returned.
If ENDPTR is not NULL, a pointer to the character after the last
one converted is stored in *ENDPTR. */
INT
strtol (nptr, endptr, base)
const char *nptr;
char **endptr;
int base;
{
int negative;
register unsigned LONG int cutoff;
register unsigned int cutlim;
register unsigned LONG int i;
register const char *s;
register unsigned char c;
const char *save, *end;
int overflow;
if (base < 0 || base == 1 || base > 36)
{
__set_errno (EINVAL);
return 0;
}
save = s = nptr;
/* Skip white space. */
while (ISSPACE ((unsigned char)*s))
++s;
if (*s == '\0')
goto noconv;
/* Check for a sign. */
if (*s == '-' || *s == '+')
{
negative = (*s == '-');
++s;
}
else
negative = 0;
/* Recognize number prefix and if BASE is zero, figure it out ourselves. */
if (*s == '0')
{
if ((base == 0 || base == 16) && TOUPPER ((unsigned char) s[1]) == 'X')
{
s += 2;
base = 16;
}
else if (base == 0)
base = 8;
}
else if (base == 0)
base = 10;
/* Save the pointer so we can check later if anything happened. */
save = s;
end = NULL;
cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
overflow = 0;
i = 0;
c = *s;
if (sizeof (long int) != sizeof (LONG int))
{
unsigned long int j = 0;
unsigned long int jmax = ULONG_MAX / base;
for (;c != '\0'; c = *++s)
{
if (s == end)
break;
if (DIGIT (c))
c -= '0';
else if (ISALPHA (c))
c = TOUPPER (c) - 'A' + 10;
else
break;
if ((int) c >= base)
break;
/* Note that we never can have an overflow. */
else if (j >= jmax)
{
/* We have an overflow. Now use the long representation. */
i = (unsigned LONG int) j;
goto use_long;
}
else
j = j * (unsigned long int) base + c;
}
i = (unsigned LONG int) j;
}
else
for (;c != '\0'; c = *++s)
{
if (s == end)
break;
if (DIGIT (c))
c -= '0';
else if (ISALPHA (c))
c = TOUPPER (c) - 'A' + 10;
else
break;
if ((int) c >= base)
break;
/* Check for overflow. */
if (i > cutoff || (i == cutoff && c > cutlim))
overflow = 1;
else
{
use_long:
i *= (unsigned LONG int) base;
i += c;
}
}
/* Check if anything actually happened. */
if (s == save)
goto noconv;
/* Store in ENDPTR the address of one character
past the last character we converted. */
if (endptr != NULL)
*endptr = (char *) s;
#if !UNSIGNED
/* Check for a value that is within the range of
`unsigned LONG int', but outside the range of `LONG int'. */
if (overflow == 0
&& i > (negative
? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
: (unsigned LONG int) STRTOL_LONG_MAX))
overflow = 1;
#endif
if (overflow)
{
__set_errno (ERANGE);
#if UNSIGNED
return STRTOL_ULONG_MAX;
#else
return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
#endif
}
/* Return the result of the appropriate sign. */
return negative ? -i : i;
noconv:
/* We must handle a special case here: the base is 0 or 16 and the
first two characters are '0' and 'x', but the rest are no
hexadecimal digits. This is no error case. We return 0 and
ENDPTR points to the `x`. */
if (endptr != NULL)
{
if (save - nptr >= 2 && TOUPPER ((unsigned char) save[-1]) == 'X' && save[-2] == '0')
*endptr = (char *) &save[-1];
else
/* There was no number to convert. */
*endptr = (char *) nptr;
}
return 0L;
}
#endif /* !HAVE_STRTOL */

30
lib/sh/strtoll.c Normal file
View file

@ -0,0 +1,30 @@
/* strtoll - convert string representation of a number into a long long value. */
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_LONG_LONG_INT) && !HAVE_STRTOLL
#define QUAD 1
#undef HAVE_STRTOL
#include "strtol.c"
#endif /* HAVE_LONG_LONG_INT && !HAVE_STRTOLL */

30
lib/sh/strtoul.c Normal file
View file

@ -0,0 +1,30 @@
/* strtoul - convert string representation of a number into an unsigned long value. */
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifndef HAVE_STRTOUL
#define UNSIGNED 1
#undef HAVE_STRTOL
#include <strtol.c>
#endif /* !HAVE_STRTOUL */

31
lib/sh/strtoull.c Normal file
View file

@ -0,0 +1,31 @@
/* strtoull - convert string representation of a number into an unsigned long long value. */
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNSIGNED_LONG_LONG_INT) && !HAVE_STRTOULL
#define QUAD 1
#define UNSIGNED 1
#undef HAVE_STRTOL
#include "strtol.c"
#endif /* HAVE_UNSIGNED_LONG_LONG_INT && !HAVE_STRTOULL */

113
lib/sh/strtoumax.c Normal file
View file

@ -0,0 +1,113 @@
/* strtoumax - convert string representation of a number into an uintmax_t value. */
/* Copyright 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Written by Paul Eggert. Modified by Chet Ramey for Bash. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <stdc.h>
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
#ifndef HAVE_DECL_STRTOUL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOUL
extern unsigned long strtoul PARAMS((const char *, char **, int));
#endif
#ifndef HAVE_DECL_STRTOULL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG_INT
extern unsigned long long strtoull PARAMS((const char *, char **, int));
#endif
#ifdef strtoumax
#undef strtoumax
#endif
uintmax_t
strtoumax (ptr, endptr, base)
const char *ptr;
char **endptr;
int base;
{
#if HAVE_UNSIGNED_LONG_LONG_INT
verify (size_is_that_of_unsigned_long_or_unsigned_long_long,
(sizeof (uintmax_t) == sizeof (unsigned long) ||
sizeof (uintmax_t) == sizeof (unsigned long long)));
if (sizeof (uintmax_t) != sizeof (unsigned long))
return (strtoull (ptr, endptr, base));
#else
verify (size_is_that_of_unsigned_long, sizeof (uintmax_t) == sizeof (unsigned long));
#endif
return (strtoul (ptr, endptr, base));
}
#ifdef TESTING
# include <stdio.h>
int
main ()
{
char *p, *endptr;
uintmax_t x;
#if HAVE_UNSIGNED_LONG_LONG_INT
unsigned long long y;
#endif
unsigned long z;
printf ("sizeof uintmax_t: %d\n", sizeof (uintmax_t));
#if HAVE_UNSIGNED_LONG_LONG_INT
printf ("sizeof unsigned long long: %d\n", sizeof (unsigned long long));
#endif
printf ("sizeof unsigned long: %d\n", sizeof (unsigned long));
x = strtoumax("42", &endptr, 10);
#if HAVE_LONG_LONG_INT
y = strtoull("42", &endptr, 10);
#else
y = 0;
#endif
z = strtoul("42", &endptr, 10);
printf ("%llu %llu %lu\n", x, y, z);
exit (0);
}
#endif

400
lib/sh/strtrans.c Normal file
View file

@ -0,0 +1,400 @@
/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <bashansi.h>
#include <stdio.h>
#include <chartypes.h>
#include "shell.h"
#include "shmbchar.h"
#include "shmbutil.h"
#ifdef ESC
#undef ESC
#endif
#define ESC '\033' /* ASCII */
/* Convert STRING by expanding the escape sequences specified by the
ANSI C standard. If SAWC is non-null, recognize `\c' and use that
as a string terminator. If we see \c, set *SAWC to 1 before
returning. LEN is the length of STRING. If (FLAGS&1) is non-zero,
that we're translating a string for `echo -e', and therefore should not
treat a single quote as a character that may be escaped with a backslash.
If (FLAGS&2) is non-zero, we're expanding for the parser and want to
quote CTLESC and CTLNUL with CTLESC. If (flags&4) is non-zero, we want
to remove the backslash before any unrecognized escape sequence. */
char *
ansicstr (string, len, flags, sawc, rlen)
char *string;
int len, flags, *sawc, *rlen;
{
int c, temp;
char *ret, *r, *s;
unsigned long v;
size_t clen;
int b, mb_cur_max;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
#endif
if (string == 0 || *string == '\0')
return ((char *)NULL);
mb_cur_max = MB_CUR_MAX;
#if defined (HANDLE_MULTIBYTE)
temp = 4*len + 4;
if (temp < 12)
temp = 12; /* ensure enough for eventual u32cesc */
ret = (char *)xmalloc (temp);
#else
ret = (char *)xmalloc (2*len + 1); /* 2*len for possible CTLESC */
#endif
for (r = ret, s = string; s && *s; )
{
c = *s++;
if (c != '\\' || *s == '\0')
{
clen = 1;
#if defined (HANDLE_MULTIBYTE)
if ((locale_utf8locale && (c & 0x80)) ||
(locale_utf8locale == 0 && mb_cur_max > 0 && is_basic (c) == 0))
{
clen = mbrtowc (&wc, s - 1, mb_cur_max, 0);
if (MB_INVALIDCH (clen))
clen = 1;
}
#endif
*r++ = c;
for (--clen; clen > 0; clen--)
*r++ = *s++;
}
else
{
switch (c = *s++)
{
#if defined (__STDC__)
case 'a': c = '\a'; break;
case 'v': c = '\v'; break;
#else
case 'a': c = (int) 0x07; break;
case 'v': c = (int) 0x0B; break;
#endif
case 'b': c = '\b'; break;
case 'e': case 'E': /* ESC -- non-ANSI */
c = ESC; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7':
#if 1
if (flags & 1)
{
*r++ = '\\';
break;
}
/*FALLTHROUGH*/
#endif
case '0':
/* If (FLAGS & 1), we're translating a string for echo -e (or
the equivalent xpg_echo option), so we obey the SUSv3/
POSIX-2001 requirement and accept 0-3 octal digits after
a leading `0'. */
temp = 2 + ((flags & 1) && (c == '0'));
for (c -= '0'; ISOCTAL (*s) && temp--; s++)
c = (c * 8) + OCTVALUE (*s);
c &= 0xFF;
break;
case 'x': /* Hex digit -- non-ANSI */
if ((flags & 2) && *s == '{')
{
flags |= 16; /* internal flag value */
s++;
}
/* Consume at least two hex characters */
for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
c = (c * 16) + HEXVALUE (*s);
/* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
until a non-xdigit or `}', so potentially more than two
chars are consumed. */
if (flags & 16)
{
for ( ; ISXDIGIT ((unsigned char)*s); s++)
c = (c * 16) + HEXVALUE (*s);
flags &= ~16;
if (*s == '}')
s++;
}
/* \x followed by non-hex digits is passed through unchanged */
else if (temp == 2)
{
*r++ = '\\';
c = 'x';
}
c &= 0xFF;
break;
#if defined (HANDLE_MULTIBYTE)
case 'u':
case 'U':
temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
for (v = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
v = (v * 16) + HEXVALUE (*s);
if (temp == ((c == 'u') ? 4 : 8))
{
*r++ = '\\'; /* c remains unchanged */
break;
}
else if (v <= 0x7f) /* <= 0x7f translates directly */
{
c = v;
break;
}
else
{
temp = u32cconv (v, r);
r += temp;
continue;
}
#endif
case '\\':
break;
case '\'': case '"': case '?':
if (flags & 1)
*r++ = '\\';
break;
case 'c':
if (sawc)
{
*sawc = 1;
*r = '\0';
if (rlen)
*rlen = r - ret;
return ret;
}
else if ((flags & 1) == 0 && *s == 0)
; /* pass \c through */
else if ((flags & 1) == 0 && (c = *s))
{
s++;
if ((flags & 2) && c == '\\' && c == *s)
s++; /* Posix requires $'\c\\' do backslash escaping */
c = TOCTRL(c);
break;
}
/*FALLTHROUGH*/
default:
if ((flags & 4) == 0)
*r++ = '\\';
break;
}
if ((flags & 2) && (c == CTLESC || c == CTLNUL))
*r++ = CTLESC;
*r++ = c;
}
}
*r = '\0';
if (rlen)
*rlen = r - ret;
return ret;
}
/* Take a string STR, possibly containing non-printing characters, and turn it
into a $'...' ANSI-C style quoted string. Returns a new string. */
char *
ansic_quote (str, flags, rlen)
char *str;
int flags, *rlen;
{
char *r, *ret, *s;
int l, rsize;
unsigned char c;
size_t clen;
int b;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
#endif
if (str == 0 || *str == 0)
return ((char *)0);
l = strlen (str);
rsize = 4 * l + 4;
r = ret = (char *)xmalloc (rsize);
*r++ = '$';
*r++ = '\'';
for (s = str; c = *s; s++)
{
b = l = 1; /* 1 == add backslash; 0 == no backslash */
clen = 1;
switch (c)
{
case ESC: c = 'E'; break;
#ifdef __STDC__
case '\a': c = 'a'; break;
case '\v': c = 'v'; break;
#else
case 0x07: c = 'a'; break;
case 0x0b: c = 'v'; break;
#endif
case '\b': c = 'b'; break;
case '\f': c = 'f'; break;
case '\n': c = 'n'; break;
case '\r': c = 'r'; break;
case '\t': c = 't'; break;
case '\\':
case '\'':
break;
default:
#if defined (HANDLE_MULTIBYTE)
b = is_basic (c);
/* XXX - clen comparison to 0 is dicey */
if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) ||
(b == 1 && ISPRINT (c) == 0))
#else
if (ISPRINT (c) == 0)
#endif
{
*r++ = '\\';
*r++ = TOCHAR ((c >> 6) & 07);
*r++ = TOCHAR ((c >> 3) & 07);
*r++ = TOCHAR (c & 07);
continue;
}
l = 0;
break;
}
if (b == 0 && clen == 0)
break;
if (l)
*r++ = '\\';
if (clen == 1)
*r++ = c;
else
{
for (b = 0; b < (int)clen; b++)
*r++ = (unsigned char)s[b];
s += clen - 1; /* -1 because of the increment above */
}
}
*r++ = '\'';
*r = '\0';
if (rlen)
*rlen = r - ret;
return ret;
}
#if defined (HANDLE_MULTIBYTE)
int
ansic_wshouldquote (string)
const char *string;
{
const wchar_t *wcs;
wchar_t wcc;
wchar_t *wcstr = NULL;
size_t slen;
slen = mbstowcs (wcstr, string, 0);
if (slen == (size_t)-1)
return 1;
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
mbstowcs (wcstr, string, slen + 1);
for (wcs = wcstr; wcc = *wcs; wcs++)
if (iswprint(wcc) == 0)
{
free (wcstr);
return 1;
}
free (wcstr);
return 0;
}
#endif
/* return 1 if we need to quote with $'...' because of non-printing chars. */
int
ansic_shouldquote (string)
const char *string;
{
const char *s;
unsigned char c;
if (string == 0)
return 0;
for (s = string; c = *s; s++)
{
#if defined (HANDLE_MULTIBYTE)
if (is_basic (c) == 0)
return (ansic_wshouldquote (s));
#endif
if (ISPRINT (c) == 0)
return 1;
}
return 0;
}
/* $'...' ANSI-C expand the portion of STRING between START and END and
return the result. The result cannot be longer than the input string. */
char *
ansiexpand (string, start, end, lenp)
char *string;
int start, end, *lenp;
{
char *temp, *t;
int len, tlen;
temp = (char *)xmalloc (end - start + 1);
for (tlen = 0, len = start; len < end; )
temp[tlen++] = string[len++];
temp[tlen] = '\0';
if (*temp)
{
t = ansicstr (temp, tlen, 2, (int *)NULL, lenp);
free (temp);
return (t);
}
else
{
if (lenp)
*lenp = 0;
return (temp);
}
}

154
lib/sh/strvis.c Normal file
View file

@ -0,0 +1,154 @@
/* strvis.c - make unsafe graphical characters in a string visible. */
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* This is a stripped-down version suitable for the shell's use. */
#include <config.h>
#include <unistd.h>
#include "bashansi.h"
#include <stdio.h>
#include "chartypes.h"
#include "bashintl.h"
#include "shmbutil.h"
#define SAFECHAR(c) ((c) == ' ' || (c) == '\t')
#ifndef RUBOUT
#define RUBOUT 0x7f
#endif
#ifndef CTRL_CHAR
#define CTRL_CHAR(c) ((c) < 0x20)
#endif
#ifndef META_CHAR
#define META_CHAR(c) ((c) > 0x7f && (c) <= UCHAR_MAX)
#endif
#ifndef UNCTRL
#define UNCTRL(c) (TOUPPER ((c) | 0x40))
#endif
#ifndef UNMETA
#define UNMETA(c) ((c) & 0x7f)
#endif
int
sh_charvis (s, sindp, slen, ret, rindp)
const char *s;
size_t *sindp;
size_t slen;
char *ret;
size_t *rindp;
{
unsigned char c;
size_t si, ri;
const char *send;
DECLARE_MBSTATE;
si = *sindp;
ri = *rindp;
c = s[*sindp];
#if defined (HANDLE_MULTIBYTE)
send = (locale_mb_cur_max > 1) ? s + slen : 0;
#else
send = 0;
#endif
if (SAFECHAR (c))
{
ret[ri++] = c;
si++;
}
else if (c == RUBOUT)
{
ret[ri++] = '^';
ret[ri++] = '?';
si++;
}
else if (CTRL_CHAR (c))
{
ret[ri++] = '^';
ret[ri++] = UNCTRL (c);
si++;
}
#if defined (HANDLE_MULTIBYTE)
else if (locale_utf8locale && (c & 0x80))
COPY_CHAR_I (ret, ri, s, send, si);
else if (locale_mb_cur_max > 1 && is_basic (c) == 0)
COPY_CHAR_I (ret, ri, s, send, si);
#endif
else if (META_CHAR (c))
{
ret[ri++] = 'M';
ret[ri++] = '-';
ret[ri++] = UNMETA (c);
si++;
}
else
ret[ri++] = s[si++];
*sindp = si;
*rindp = ri;
return si;
}
/* Return a new string with `unsafe' non-graphical characters in S rendered
in a visible way. */
char *
sh_strvis (string)
const char *string;
{
size_t slen, sind;
char *ret;
size_t retind, retsize;
unsigned char c;
DECLARE_MBSTATE;
if (string == 0)
return 0;
if (*string == '\0')
{
if ((ret = (char *)malloc (1)) == 0)
return 0;
ret[0] = '\0';
return ret;
}
slen = strlen (string);
retsize = 3 * slen + 1;
ret = (char *)malloc (retsize);
if (ret == 0)
return 0;
retind = 0;
sind = 0;
while (string[sind])
sind = sh_charvis (string, &sind, slen, ret, &retind);
ret[retind] = '\0';
return ret;
}

262
lib/sh/timers.c Normal file
View file

@ -0,0 +1,262 @@
/* timers - functions to manage shell timers */
/* Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "bashtypes.h"
#include "posixtime.h"
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#if defined (HAVE_SELECT)
# include "posixselect.h"
# include "stat-time.h"
#endif
#include "sig.h"
#include "bashjmp.h"
#include "xmalloc.h"
#include "timer.h"
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#ifndef FREE
#define FREE(s) do { if (s) free (s); } while (0)
#endif
extern unsigned int falarm (unsigned int, unsigned int);
static void shtimer_zero (sh_timer *);
static void
shtimer_zero (sh_timer *t)
{
t->tmout.tv_sec = 0;
t->tmout.tv_usec = 0;
t->fd = -1;
t->flags = t->alrmflag = 0;
t->alrm_handler = t->old_handler = 0;
memset (t->jmpenv, '\0', sizeof (t->jmpenv));
t->tm_handler = 0;
t->data = 0;
}
sh_timer *
shtimer_alloc (void)
{
sh_timer *t;
t = (sh_timer *)xmalloc (sizeof (sh_timer));
shtimer_zero (t);
return t;
}
void
shtimer_flush (sh_timer *t)
{
/* The caller can manage t->data arbitrarily as long as it frees and sets
t->data to 0 before calling this function. Otherwise, we do what we can
to avoid memleaks. */
FREE (t->data);
shtimer_zero (t);
}
void
shtimer_dispose (sh_timer *t)
{
free (t);
}
/* We keep the timer as an offset into the future from the time it's set. */
void
shtimer_set (sh_timer *t, time_t sec, long usec)
{
struct timeval now;
if (t->flags & SHTIMER_ALARM)
{
t->alrmflag = 0; /* just paranoia */
t->old_handler = set_signal_handler (SIGALRM, t->alrm_handler);
t->flags |= SHTIMER_SIGSET;
falarm (t->tmout.tv_sec = sec, t->tmout.tv_usec = usec);
t->flags |= SHTIMER_ALRMSET;
return;
}
if (gettimeofday (&now, 0) < 0)
timerclear (&now);
t->tmout.tv_sec = now.tv_sec + sec;
t->tmout.tv_usec = now.tv_usec + usec;
if (t->tmout.tv_usec > USEC_PER_SEC)
{
t->tmout.tv_sec++;
t->tmout.tv_usec -= USEC_PER_SEC;
}
}
void
shtimer_unset (sh_timer *t)
{
t->tmout.tv_sec = 0;
t->tmout.tv_usec = 0;
if (t->flags & SHTIMER_ALARM)
{
t->alrmflag = 0;
if (t->flags & SHTIMER_ALRMSET)
falarm (0, 0);
if (t->old_handler && (t->flags & SHTIMER_SIGSET))
{
set_signal_handler (SIGALRM, t->old_handler);
t->flags &= ~SHTIMER_SIGSET;
t->old_handler = 0;
}
}
}
void
shtimer_cleanup (sh_timer *t)
{
shtimer_unset (t);
}
void
shtimer_clear (sh_timer *t)
{
shtimer_unset (t);
shtimer_dispose (t);
}
int
shtimer_chktimeout (sh_timer *t)
{
struct timeval now;
int r;
/* Use the flag to avoid returning sigalrm_seen here */
if (t->flags & SHTIMER_ALARM)
return t->alrmflag;
/* Could check a flag for this */
if (t->tmout.tv_sec == 0 && t->tmout.tv_usec == 0)
return 0;
if (gettimeofday (&now, 0) < 0)
return 0;
r = ((now.tv_sec > t->tmout.tv_sec) ||
(now.tv_sec == t->tmout.tv_sec && now.tv_usec >= t->tmout.tv_usec));
return r;
}
#if defined (HAVE_SELECT) || defined (HAVE_PSELECT)
int
shtimer_select (sh_timer *t)
{
int r, nfd;
sigset_t blocked_sigs, prevmask;
struct timeval now, tv;
fd_set readfds;
#if defined (HAVE_PSELECT)
struct timespec ts;
#endif
/* We don't want a SIGCHLD to interrupt this */
sigemptyset (&blocked_sigs);
# if defined (SIGCHLD)
sigaddset (&blocked_sigs, SIGCHLD);
# endif
if (gettimeofday (&now, 0) < 0)
{
if (t->flags & SHTIMER_LONGJMP)
sh_longjmp (t->jmpenv, 1);
else
return -1;
}
/* If the timer has already expired, return immediately */
if ((now.tv_sec > t->tmout.tv_sec) ||
(now.tv_sec == t->tmout.tv_sec && now.tv_usec >= t->tmout.tv_usec))
{
if (t->flags & SHTIMER_LONGJMP)
sh_longjmp (t->jmpenv, 1);
else if (t->tm_handler)
return ((*t->tm_handler) (t));
else
return 0;
}
/* compute timeout */
tv.tv_sec = t->tmout.tv_sec - now.tv_sec;
tv.tv_usec = t->tmout.tv_usec - now.tv_usec;
if (tv.tv_usec < 0)
{
tv.tv_sec--;
tv.tv_usec += USEC_PER_SEC;
}
#if defined (HAVE_PSELECT)
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#else
sigemptyset (&prevmask);
#endif /* !HAVE_PSELECT */
nfd = (t->fd >= 0) ? t->fd + 1 : 0;
FD_ZERO (&readfds);
if (t->fd >= 0)
FD_SET (t->fd, &readfds);
#if defined (HAVE_PSELECT)
r = pselect(nfd, &readfds, (fd_set *)0, (fd_set *)0, &ts, &blocked_sigs);
#else
sigprocmask (SIG_SETMASK, &blocked_sigs, &prevmask);
r = select(nfd, &readfds, (fd_set *)0, (fd_set *)0, &tv);
sigprocmask (SIG_SETMASK, &prevmask, NULL);
#endif
if (r < 0)
return r; /* caller will handle */
else if (r == 0 && (t->flags & SHTIMER_LONGJMP))
sh_longjmp (t->jmpenv, 1);
else if (r == 0 && t->tm_handler)
return ((*t->tm_handler) (t));
else
return r;
}
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
int
shtimer_alrm (sh_timer *t)
{
return 0;
}

77
lib/sh/times.c Normal file
View file

@ -0,0 +1,77 @@
/* times.c - times(3) library function */
/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_TIMES)
#include <sys/types.h>
#include <posixtime.h>
#include <systimes.h>
#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_GETRUSAGE)
# include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H && HAVE_GETRUSAGE */
extern long get_clk_tck PARAMS((void));
#define CONVTCK(r) (r.tv_sec * clk_tck + r.tv_usec / (1000000 / clk_tck))
clock_t
times(tms)
struct tms *tms;
{
clock_t rv;
static long clk_tck = -1;
#if defined (HAVE_GETRUSAGE)
struct timeval tv;
struct rusage ru;
if (clk_tck == -1)
clk_tck = get_clk_tck();
if (getrusage(RUSAGE_SELF, &ru) < 0)
return ((clock_t)-1);
tms->tms_utime = CONVTCK(ru.ru_utime);
tms->tms_stime = CONVTCK(ru.ru_stime);
if (getrusage(RUSAGE_CHILDREN, &ru) < 0)
return ((clock_t)-1);
tms->tms_cutime = CONVTCK(ru.ru_utime);
tms->tms_cstime = CONVTCK(ru.ru_stime);
if (gettimeofday(&tv, NULL) < 0)
return ((clock_t)-1);
rv = (clock_t)(CONVTCK(tv));
#else /* !HAVE_GETRUSAGE */
if (clk_tck == -1)
clk_tck = get_clk_tck();
/* We can't do anything. */
tms->tms_utime = tms->tms_stime = (clock_t)0;
tms->tms_cutime = tms->tms_cstime = (clock_t)0;
rv = (clock_t)time((time_t *)0) * clk_tck;
# endif /* HAVE_GETRUSAGE */
return rv;
}
#endif /* !HAVE_TIMES */

179
lib/sh/timeval.c Normal file
View file

@ -0,0 +1,179 @@
/* timeval.c - functions to perform operations on struct timevals */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_TIMEVAL)
#include <sys/types.h>
#include <posixtime.h>
#include <bashintl.h>
#include <stdc.h>
#ifndef locale_decpoint
extern int locale_decpoint PARAMS((void));
#endif
#include <stdio.h>
struct timeval *
difftimeval (d, t1, t2)
struct timeval *d, *t1, *t2;
{
d->tv_sec = t2->tv_sec - t1->tv_sec;
d->tv_usec = t2->tv_usec - t1->tv_usec;
if (d->tv_usec < 0)
{
d->tv_usec += 1000000;
d->tv_sec -= 1;
if (d->tv_sec < 0) /* ??? -- BSD/OS does this */
{
d->tv_sec = 0;
d->tv_usec = 0;
}
}
return d;
}
struct timeval *
addtimeval (d, t1, t2)
struct timeval *d, *t1, *t2;
{
d->tv_sec = t1->tv_sec + t2->tv_sec;
d->tv_usec = t1->tv_usec + t2->tv_usec;
if (d->tv_usec >= 1000000)
{
d->tv_usec -= 1000000;
d->tv_sec += 1;
}
return d;
}
struct timeval *
multimeval (d, m)
struct timeval *d;
int m;
{
time_t t;
t = d->tv_usec * m;
d->tv_sec = d->tv_sec * m + t / 1000000;
d->tv_usec = t % 1000000;
return d;
}
struct timeval *
divtimeval (d, m)
struct timeval *d;
int m;
{
time_t t;
t = d->tv_sec;
d->tv_sec = t / m;
d->tv_usec = (d->tv_usec + 1000000 * (t % m)) / m;
return d;
}
/* Do "cpu = ((user + sys) * 10000) / real;" with timevals.
Barely-tested code from Deven T. Corzine <deven@ties.org>. */
int
timeval_to_cpu (rt, ut, st)
struct timeval *rt, *ut, *st; /* real, user, sys */
{
struct timeval t1, t2;
register int i;
addtimeval (&t1, ut, st);
t2.tv_sec = rt->tv_sec;
t2.tv_usec = rt->tv_usec;
for (i = 0; i < 6; i++)
{
if ((t1.tv_sec > 99999999) || (t2.tv_sec > 99999999))
break;
t1.tv_sec *= 10;
t1.tv_sec += t1.tv_usec / 100000;
t1.tv_usec *= 10;
t1.tv_usec %= 1000000;
t2.tv_sec *= 10;
t2.tv_sec += t2.tv_usec / 100000;
t2.tv_usec *= 10;
t2.tv_usec %= 1000000;
}
for (i = 0; i < 4; i++)
{
if (t1.tv_sec < 100000000)
t1.tv_sec *= 10;
else
t2.tv_sec /= 10;
}
return ((t2.tv_sec == 0) ? 0 : t1.tv_sec / t2.tv_sec);
}
/* Convert a pointer to a struct timeval to seconds and thousandths of a
second, returning the values in *SP and *SFP, respectively. This does
rounding on the fractional part, not just truncation to three places. */
void
timeval_to_secs (tvp, sp, sfp)
struct timeval *tvp;
time_t *sp;
int *sfp;
{
int rest;
*sp = tvp->tv_sec;
*sfp = tvp->tv_usec % 1000000; /* pretty much a no-op */
rest = *sfp % 1000;
*sfp = (*sfp * 1000) / 1000000;
if (rest >= 500)
*sfp += 1;
/* Sanity check */
if (*sfp >= 1000)
{
*sp += 1;
*sfp -= 1000;
}
}
/* Print the contents of a struct timeval * in a standard way to stdio
stream FP. */
void
print_timeval (fp, tvp)
FILE *fp;
struct timeval *tvp;
{
time_t timestamp;
long minutes;
int seconds, seconds_fraction;
timeval_to_secs (tvp, &timestamp, &seconds_fraction);
minutes = timestamp / 60;
seconds = timestamp % 60;
fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint (), seconds_fraction);
}
#endif /* HAVE_TIMEVAL */

311
lib/sh/tmpfile.c Normal file
View file

@ -0,0 +1,311 @@
/*
* tmpfile.c - functions to create and safely open temp files for the shell.
*/
/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <bashtypes.h>
#include <posixstat.h>
#include <posixtime.h>
#include <filecntl.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <bashansi.h>
#include <stdio.h>
#include <errno.h>
#include <shell.h>
#ifndef errno
extern int errno;
#endif
#define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL | O_BINARY)
#define DEFAULT_TMPDIR "." /* bogus default, should be changed */
#define DEFAULT_NAMEROOT "shtmp"
/* Use ANSI-C rand() interface if random(3) is not available */
#if !HAVE_RANDOM
#define random() rand()
#endif
extern pid_t dollar_dollar_pid;
static char *get_sys_tmpdir PARAMS((void));
static char *get_tmpdir PARAMS((int));
static char *sys_tmpdir = (char *)NULL;
static int ntmpfiles;
static int tmpnamelen = -1;
static unsigned long filenum = 1L;
static char *
get_sys_tmpdir ()
{
if (sys_tmpdir)
return sys_tmpdir;
#ifdef P_tmpdir
sys_tmpdir = P_tmpdir;
if (file_iswdir (sys_tmpdir))
return sys_tmpdir;
#endif
sys_tmpdir = "/tmp";
if (file_iswdir (sys_tmpdir))
return sys_tmpdir;
sys_tmpdir = "/var/tmp";
if (file_iswdir (sys_tmpdir))
return sys_tmpdir;
sys_tmpdir = "/usr/tmp";
if (file_iswdir (sys_tmpdir))
return sys_tmpdir;
sys_tmpdir = DEFAULT_TMPDIR;
return sys_tmpdir;
}
static char *
get_tmpdir (flags)
int flags;
{
char *tdir;
tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL;
if (tdir && (file_iswdir (tdir) == 0 || strlen (tdir) > PATH_MAX))
tdir = 0;
if (tdir == 0)
tdir = get_sys_tmpdir ();
#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
if (tmpnamelen == -1)
tmpnamelen = pathconf (tdir, _PC_NAME_MAX);
#else
tmpnamelen = 0;
#endif
return tdir;
}
static void
sh_seedrand ()
{
#if HAVE_RANDOM
int d;
static int seeded = 0;
if (seeded == 0)
{
struct timeval tv;
gettimeofday (&tv, NULL);
srandom (tv.tv_sec ^ tv.tv_usec ^ (getpid () << 16) ^ (uintptr_t)&d);
seeded = 1;
}
#endif
}
char *
sh_mktmpname (nameroot, flags)
char *nameroot;
int flags;
{
char *filename, *tdir, *lroot;
struct stat sb;
int r, tdlen;
static int seeded = 0;
filename = (char *)xmalloc (PATH_MAX + 1);
tdir = get_tmpdir (flags);
tdlen = strlen (tdir);
lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
if (nameroot == 0)
flags &= ~MT_TEMPLATE;
if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
flags &= ~MT_TEMPLATE;
#ifdef USE_MKTEMP
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
if (mktemp (filename) == 0)
{
free (filename);
filename = NULL;
}
#else /* !USE_MKTEMP */
sh_seedrand ();
while (1)
{
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';
# ifdef HAVE_LSTAT
r = lstat (filename, &sb);
# else
r = stat (filename, &sb);
# endif
if (r < 0 && errno == ENOENT)
break;
}
#endif /* !USE_MKTEMP */
return filename;
}
int
sh_mktmpfd (nameroot, flags, namep)
char *nameroot;
int flags;
char **namep;
{
char *filename, *tdir, *lroot;
int fd, tdlen;
filename = (char *)xmalloc (PATH_MAX + 1);
tdir = get_tmpdir (flags);
tdlen = strlen (tdir);
lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
if (nameroot == 0)
flags &= ~MT_TEMPLATE;
if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
flags &= ~MT_TEMPLATE;
#ifdef USE_MKSTEMP
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
fd = mkstemp (filename);
if (fd < 0 || namep == 0)
{
free (filename);
filename = NULL;
}
if (namep)
*namep = filename;
return fd;
#else /* !USE_MKSTEMP */
sh_seedrand ();
do
{
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';
fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600);
}
while (fd < 0 && errno == EEXIST);
if (namep)
*namep = filename;
else
free (filename);
return fd;
#endif /* !USE_MKSTEMP */
}
FILE *
sh_mktmpfp (nameroot, flags, namep)
char *nameroot;
int flags;
char **namep;
{
int fd;
FILE *fp;
fd = sh_mktmpfd (nameroot, flags, namep);
if (fd < 0)
return ((FILE *)NULL);
fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w");
if (fp == 0)
close (fd);
return fp;
}
char *
sh_mktmpdir (nameroot, flags)
char *nameroot;
int flags;
{
char *filename, *tdir, *lroot, *dirname;
int fd, tdlen;
#ifdef USE_MKDTEMP
filename = (char *)xmalloc (PATH_MAX + 1);
tdir = get_tmpdir (flags);
tdlen = strlen (tdir);
lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
if (nameroot == 0)
flags &= ~MT_TEMPLATE;
if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
flags &= ~MT_TEMPLATE;
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
dirname = mkdtemp (filename);
if (dirname == 0)
{
free (filename);
filename = NULL;
}
return dirname;
#else /* !USE_MKDTEMP */
filename = (char *)NULL;
do
{
filename = sh_mktmpname (nameroot, flags);
fd = mkdir (filename, 0700);
if (fd == 0)
break;
free (filename);
filename = (char *)NULL;
}
while (fd < 0 && errno == EEXIST);
return (filename);
#endif /* !USE_MKDTEMP */
}

124
lib/sh/uconvert.c Normal file
View file

@ -0,0 +1,124 @@
/* uconvert - convert string representations of decimal numbers into whole
number/fractional value pairs. */
/* Copyright (C) 2008,2009,2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "bashtypes.h"
#include "posixtime.h"
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include "chartypes.h"
#include "shell.h"
#include "builtins.h"
#define DECIMAL '.' /* XXX - should use locale */
#define RETURN(x) \
do { \
if (ip) *ip = ipart * mult; \
if (up) *up = upart; \
if (ep) *ep = p; \
return (x); \
} while (0)
/*
* An incredibly simplistic floating point converter.
*/
static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
/* Take a decimal number int-part[.[micro-part]] and convert it to the whole
and fractional portions. The fractional portion is returned in
millionths (micro); callers are responsible for multiplying appropriately.
EP, if non-null, gets the address of the character where conversion stops.
Return 1 if value converted; 0 if invalid integer for either whole or
fractional parts. */
int
uconvert(s, ip, up, ep)
char *s;
long *ip, *up;
char **ep;
{
int n, mult;
long ipart, upart;
char *p;
ipart = upart = 0;
mult = 1;
if (s && (*s == '-' || *s == '+'))
{
mult = (*s == '-') ? -1 : 1;
p = s + 1;
}
else
p = s;
for ( ; p && *p; p++)
{
if (*p == DECIMAL) /* decimal point */
break;
if (DIGIT(*p) == 0)
RETURN(0);
ipart = (ipart * 10) + (*p - '0');
}
if (p == 0 || *p == 0) /* callers ensure p can never be 0; this is to shut up clang */
RETURN(1);
if (*p == DECIMAL)
p++;
/* Look for up to six digits past a decimal point. */
for (n = 0; n < 6 && p[n]; n++)
{
if (DIGIT(p[n]) == 0)
{
if (ep)
{
upart *= multiplier[n];
p += n; /* To set EP */
}
RETURN(0);
}
upart = (upart * 10) + (p[n] - '0');
}
/* Now convert to millionths */
upart *= multiplier[n];
if (n == 6 && p[6] >= '5' && p[6] <= '9')
upart++; /* round up 1 */
if (ep)
{
p += n;
while (DIGIT(*p))
p++;
}
RETURN(1);
}

140
lib/sh/ufuncs.c Normal file
View file

@ -0,0 +1,140 @@
/* ufuncs - sleep and alarm functions that understand fractional values */
/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "bashtypes.h"
#include "posixtime.h"
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if defined (HAVE_SELECT)
# include "posixselect.h"
# include "quit.h"
# include "trap.h"
# include "stat-time.h"
#endif
/* A version of `alarm' using setitimer if it's available. */
#if defined (HAVE_SETITIMER)
unsigned int
falarm(secs, usecs)
unsigned int secs, usecs;
{
struct itimerval it, oit;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
it.it_value.tv_sec = secs;
it.it_value.tv_usec = usecs;
if (setitimer(ITIMER_REAL, &it, &oit) < 0)
return (-1); /* XXX will be converted to unsigned */
/* Backwards compatibility with alarm(3) */
if (oit.it_value.tv_usec)
oit.it_value.tv_sec++;
return (oit.it_value.tv_sec);
}
#else
int
falarm (secs, usecs)
unsigned int secs, usecs;
{
if (secs == 0 && usecs == 0)
return (alarm (0));
if (secs == 0 || usecs >= 500000)
{
secs++;
usecs = 0;
}
return (alarm (secs));
}
#endif /* !HAVE_SETITIMER */
/* A version of sleep using fractional seconds and select. I'd like to use
`usleep', but it's already taken */
#if defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT))
int
fsleep(sec, usec)
unsigned int sec, usec;
{
int e, r;
sigset_t blocked_sigs, prevmask;
#if defined (HAVE_PSELECT)
struct timespec ts;
#else
struct timeval tv;
#endif
sigemptyset (&blocked_sigs);
# if defined (SIGCHLD)
sigaddset (&blocked_sigs, SIGCHLD);
# endif
#if defined (HAVE_PSELECT)
ts.tv_sec = sec;
ts.tv_nsec = usec * 1000;
#else
sigemptyset (&prevmask);
tv.tv_sec = sec;
tv.tv_usec = usec;
#endif /* !HAVE_PSELECT */
do
{
#if defined (HAVE_PSELECT)
r = pselect(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &ts, &blocked_sigs);
#else
sigprocmask (SIG_SETMASK, &blocked_sigs, &prevmask);
r = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
sigprocmask (SIG_SETMASK, &prevmask, NULL);
#endif
e = errno;
if (r < 0 && errno == EINTR)
return -1; /* caller will handle */
errno = e;
}
while (r < 0 && errno == EINTR);
return r;
}
#else /* !HAVE_TIMEVAL || !HAVE_SELECT */
int
fsleep(sec, usec)
long sec, usec;
{
if (usec >= 500000) /* round */
sec++;
return (sleep(sec));
}
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */

339
lib/sh/unicode.c Normal file
View file

@ -0,0 +1,339 @@
/* unicode.c - functions to convert unicode characters */
/* Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <limits.h>
#if HAVE_ICONV
# include <iconv.h>
#endif
#include <xmalloc.h>
#ifndef USHORT_MAX
# ifdef USHRT_MAX
# define USHORT_MAX USHRT_MAX
# else
# define USHORT_MAX ((unsigned short) ~(unsigned short)0)
# endif
#endif
#if !defined (STREQ)
# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
#endif /* !STREQ */
#if defined (HAVE_LOCALE_CHARSET)
extern const char *locale_charset PARAMS((void));
#else
extern char *get_locale_var PARAMS((char *));
#endif
extern int locale_utf8locale;
static int u32init = 0;
static int utf8locale = 0;
#if defined (HAVE_ICONV)
static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
static char charsetbuf[40];
static char *
stub_charset ()
{
char *locale, *s, *t;
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
{
strcpy (charsetbuf, "ASCII");
return charsetbuf;
}
s = strrchr (locale, '.');
if (s)
{
strncpy (charsetbuf, s+1, sizeof (charsetbuf) - 1);
charsetbuf[sizeof (charsetbuf) - 1] = '\0';
t = strchr (charsetbuf, '@');
if (t)
*t = 0;
return charsetbuf;
}
strncpy (charsetbuf, locale, sizeof (charsetbuf) - 1);
charsetbuf[sizeof (charsetbuf) - 1] = '\0';
return charsetbuf;
}
#endif
void
u32reset ()
{
#if defined (HAVE_ICONV)
if (u32init && localconv != (iconv_t)-1)
{
iconv_close (localconv);
localconv = (iconv_t)-1;
}
#endif
u32init = 0;
utf8locale = 0;
}
/* u32toascii ? */
int
u32tochar (x, s)
unsigned long x;
char *s;
{
int l;
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
if (x <= UCHAR_MAX)
s[0] = x & 0xFF;
else if (x <= USHORT_MAX) /* assume unsigned short = 16 bits */
{
s[0] = (x >> 8) & 0xFF;
s[1] = x & 0xFF;
}
else
{
s[0] = (x >> 24) & 0xFF;
s[1] = (x >> 16) & 0xFF;
s[2] = (x >> 8) & 0xFF;
s[3] = x & 0xFF;
}
s[l] = '\0';
return l;
}
int
u32tocesc (wc, s)
u_bits32_t wc;
char *s;
{
int l;
if (wc < 0x10000)
l = sprintf (s, "\\u%04X", wc);
else
l = sprintf (s, "\\U%08X", wc);
return l;
}
/* Convert unsigned 32-bit int to utf-8 character string */
int
u32toutf8 (wc, s)
u_bits32_t wc;
char *s;
{
int l;
if (wc < 0x0080)
{
s[0] = (char)wc;
l = 1;
}
else if (wc < 0x0800)
{
s[0] = (wc >> 6) | 0xc0;
s[1] = (wc & 0x3f) | 0x80;
l = 2;
}
else if (wc < 0x10000)
{
/* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
s[0] = (wc >> 12) | 0xe0;
s[1] = ((wc >> 6) & 0x3f) | 0x80;
s[2] = (wc & 0x3f) | 0x80;
l = 3;
}
else if (wc < 0x200000)
{
s[0] = (wc >> 18) | 0xf0;
s[1] = ((wc >> 12) & 0x3f) | 0x80;
s[2] = ((wc >> 6) & 0x3f) | 0x80;
s[3] = (wc & 0x3f) | 0x80;
l = 4;
}
/* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
else if (wc < 0x04000000)
{
s[0] = (wc >> 24) | 0xf8;
s[1] = ((wc >> 18) & 0x3f) | 0x80;
s[2] = ((wc >> 12) & 0x3f) | 0x80;
s[3] = ((wc >> 6) & 0x3f) | 0x80;
s[4] = (wc & 0x3f) | 0x80;
l = 5;
}
else if (wc < 0x080000000)
{
s[0] = (wc >> 30) | 0xfc;
s[1] = ((wc >> 24) & 0x3f) | 0x80;
s[2] = ((wc >> 18) & 0x3f) | 0x80;
s[3] = ((wc >> 12) & 0x3f) | 0x80;
s[4] = ((wc >> 6) & 0x3f) | 0x80;
s[5] = (wc & 0x3f) | 0x80;
l = 6;
}
else
l = 0;
s[l] = '\0';
return l;
}
/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
only if sizeof(wchar_t) == 2. */
int
u32toutf16 (c, s)
u_bits32_t c;
wchar_t *s;
{
int l;
l = 0;
if (c < 0x0d800 || (c >= 0x0e000 && c <= 0x0ffff))
{
s[0] = (wchar_t) (c & 0xFFFF);
l = 1;
}
else if (c >= 0x10000 && c <= 0x010ffff)
{
c -= 0x010000;
s[0] = (wchar_t)((c >> 10) + 0xd800);
s[1] = (wchar_t)((c & 0x3ff) + 0xdc00);
l = 2;
}
s[l] = 0;
return l;
}
/* convert a single unicode-32 character into a multibyte string and put the
result in S, which must be large enough (at least max(10,MB_LEN_MAX) bytes) */
int
u32cconv (c, s)
unsigned long c;
char *s;
{
wchar_t wc;
wchar_t ws[3];
int n;
#if HAVE_ICONV
const char *charset;
char obuf[25], *optr;
size_t obytesleft;
const char *iptr;
size_t sn;
#endif
#if __STDC_ISO_10646__
wc = c;
if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
n = wctomb (s, wc);
else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
n = wcstombs (s, ws, MB_LEN_MAX);
else
n = -1;
if (n != -1)
return n;
#endif
#if HAVE_ICONV
/* this is mostly from coreutils-8.5/lib/unicodeio.c */
if (u32init == 0)
{
utf8locale = locale_utf8locale;
localconv = (iconv_t)-1;
if (utf8locale == 0)
{
#if HAVE_LOCALE_CHARSET
charset = locale_charset ();
#elif HAVE_NL_LANGINFO
charset = nl_langinfo (CODESET);
#else
charset = stub_charset ();
#endif
localconv = iconv_open (charset, "UTF-8");
if (localconv == (iconv_t)-1)
/* We assume ASCII when presented with an unknown encoding. */
localconv = iconv_open ("ASCII", "UTF-8");
}
u32init = 1;
}
/* NL_LANGINFO and locale_charset used when setting locale_utf8locale */
/* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */
n = u32toutf8 (c, s);
if (utf8locale)
return n;
/* If the conversion is not supported, even the ASCII requested above, we
bail now. Currently we return the UTF-8 conversion. We could return
u32tocesc(). */
if (localconv == (iconv_t)-1)
return n;
optr = obuf;
obytesleft = sizeof (obuf);
iptr = s;
sn = n;
iconv (localconv, NULL, NULL, NULL, NULL);
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
{
/* You get ISO C99 escape sequences if iconv fails */
n = u32tocesc (c, s);
return n;
}
*optr = '\0';
/* number of chars to be copied is optr - obuf if we want to do bounds
checking */
strcpy (s, obuf);
return (optr - obuf);
#endif /* HAVE_ICONV */
if (locale_utf8locale)
n = u32toutf8 (c, s);
else
n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */
return n;
}
#else
void
u32reset ()
{
}
#endif /* HANDLE_MULTIBYTE */

196
lib/sh/utf8.c Normal file
View file

@ -0,0 +1,196 @@
/* utf8.c - UTF-8 character handling functions */
/* Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "bashansi.h"
#include "shmbutil.h"
extern int locale_mb_cur_max;
extern int locale_utf8locale;
#if defined (HANDLE_MULTIBYTE)
char *
utf8_mbschr (s, c)
const char *s;
int c;
{
return strchr (s, c); /* for now */
}
int
utf8_mbscmp (s1, s2)
const char *s1, *s2;
{
/* Use the fact that the UTF-8 encoding preserves lexicographic order. */
return strcmp (s1, s2);
}
char *
utf8_mbsmbchar (str)
const char *str;
{
register char *s;
for (s = (char *)str; *s; s++)
if ((*s & 0xc0) == 0x80)
return s;
return (0);
}
int
utf8_mbsnlen(src, srclen, maxlen)
const char *src;
size_t srclen;
int maxlen;
{
register int sind, count;
for (sind = count = 0; src[sind] && sind <= maxlen; sind++)
{
if ((src[sind] & 0xc0) != 0x80)
count++;
}
return (count);
}
/* Adapted from GNU gnulib. Handles UTF-8 characters up to 4 bytes long */
int
utf8_mblen (s, n)
const char *s;
size_t n;
{
unsigned char c, c1, c2, c3;
if (s == 0)
return (0); /* no shift states */
if (n <= 0)
return (-1);
c = (unsigned char)*s;
if (c < 0x80)
return (c != 0);
if (c >= 0xc2)
{
c1 = (unsigned char)s[1];
if (c < 0xe0)
{
if (n == 1)
return -2;
/*
* c c1
*
* U+0080..U+07FF C2..DF 80..BF
*/
if (n >= 2 && (c1 ^ 0x80) < 0x40) /* 0x80..0xbf */
return 2;
}
else if (c < 0xf0)
{
if (n == 1)
return -2;
/*
* c c1 c2
*
* U+0800..U+0FFF E0 A0..BF 80..BF
* U+1000..U+CFFF E1..EC 80..BF 80..BF
* U+D000..U+D7FF ED 80..9F 80..BF
* U+E000..U+FFFF EE..EF 80..BF 80..BF
*/
if ((c1 ^ 0x80) < 0x40
&& (c >= 0xe1 || c1 >= 0xa0)
&& (c != 0xed || c1 < 0xa0))
{
if (n == 2)
return -2; /* incomplete */
c2 = (unsigned char)s[2];
if ((c2 ^ 0x80) < 0x40)
return 3;
}
}
else if (c <= 0xf4)
{
if (n == 1)
return -2;
/*
* c c1 c2 c3
*
* U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
* U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
* U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
*/
if (((c1 ^ 0x80) < 0x40)
&& (c >= 0xf1 || c1 >= 0x90)
&& (c < 0xf4 || (c == 0xf4 && c1 < 0x90)))
{
if (n == 2)
return -2; /* incomplete */
c2 = (unsigned char)s[2];
if ((c2 ^ 0x80) < 0x40)
{
if (n == 3)
return -2;
c3 = (unsigned char)s[3];
if ((c3 ^ 0x80) < 0x40)
return 4;
}
}
}
}
/* invalid or incomplete multibyte character */
return -1;
}
/* We can optimize this if we know the locale is UTF-8, but needs to handle
malformed byte sequences. */
size_t
utf8_mbstrlen(s)
const char *s;
{
size_t clen, nc;
int mb_cur_max;
nc = 0;
mb_cur_max = MB_CUR_MAX;
while (*s && (clen = (size_t)utf8_mblen(s, mb_cur_max)) != 0)
{
if (MB_INVALIDCH(clen))
clen = 1; /* assume single byte */
s += clen;
nc++;
}
return nc;
}
#endif

85
lib/sh/vprint.c Normal file
View file

@ -0,0 +1,85 @@
/* vprint.c -- v[fs]printf() for 4.[23] BSD systems. */
/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (USE_VFPRINTF_EMULATION)
#include <stdio.h>
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *)0)
# else
# define NULL 0x0
# endif /* __STDC__ */
#endif /* !NULL */
/*
* Beware! Don't trust the value returned by either of these functions; it
* seems that pre-4.3-tahoe implementations of _doprnt () return the first
* argument, i.e. a char *.
*/
#include <varargs.h>
int
vfprintf (iop, fmt, ap)
FILE *iop;
char *fmt;
va_list ap;
{
int len;
char localbuf[BUFSIZ];
if (iop->_flag & _IONBF)
{
iop->_flag &= ~_IONBF;
iop->_ptr = iop->_base = localbuf;
len = _doprnt (fmt, ap, iop);
(void) fflush (iop);
iop->_flag |= _IONBF;
iop->_base = NULL;
iop->_bufsiz = 0;
iop->_cnt = 0;
}
else
len = _doprnt (fmt, ap, iop);
return (ferror (iop) ? EOF : len);
}
/*
* Ditto for vsprintf
*/
int
vsprintf (str, fmt, ap)
char *str, *fmt;
va_list ap;
{
FILE f;
int len;
f._flag = _IOWRT|_IOSTRG;
f._ptr = str;
f._cnt = 32767;
len = _doprnt (fmt, ap, &f);
*f._ptr = 0;
return (len);
}
#endif /* USE_VFPRINTF_EMULATION */

44
lib/sh/wcsdup.c Normal file
View file

@ -0,0 +1,44 @@
/* wcsdup.c - duplicate wide character string */
/* Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
#include <xmalloc.h>
wchar_t *
wcsdup (ws)
const wchar_t *ws;
{
wchar_t *ret;
size_t len;
len = wcslen (ws);
ret = xmalloc ((len + 1) * sizeof (wchar_t));
if (ret == 0)
return ret;
return (wcscpy (ret, ws));
}
#endif /* !HAVE_WCSDUP && HANDLE_MULTIBYTE */

56
lib/sh/wcsnwidth.c Normal file
View file

@ -0,0 +1,56 @@
/* wcsnwidth.c - compute display width of wide character string, up to max
specified width, return length. */
/* Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HANDLE_MULTIBYTE)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
/* Return the number of wide characters that will be displayed from wide string
PWCS. If the display width exceeds MAX, return the number of wide chars
from PWCS required to display MAX characters on the screen. */
int
wcsnwidth(pwcs, n, max)
const wchar_t *pwcs;
size_t n, max;
{
wchar_t wc, *ws;
int len, l;
len = 0;
ws = (wchar_t *)pwcs;
while (n-- > 0 && (wc = *ws++) != L'\0')
{
l = wcwidth (wc);
if (l < 0)
return (-1);
else if (l == max - len)
return (ws - pwcs);
else if (l > max - len)
return (--ws - pwcs);
len += l;
}
return (ws - pwcs);
}
#endif

46
lib/sh/wcswidth.c Normal file
View file

@ -0,0 +1,46 @@
/* wcswidth.c - compute display width of wide character string */
/* Copyright (C) 2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HANDLE_MULTIBYTE) && !defined (HAVE_WCSWIDTH)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
int
wcswidth(pwcs, n)
const wchar_t *pwcs;
size_t n;
{
wchar_t wc;
int len, l;
len = 0;
while (n-- > 0 && (wc = *pwcs++) != L'\0')
{
if ((l = wcwidth(wc)) < 0)
return (-1);
len += l;
}
return (len);
}
#endif

104
lib/sh/winsize.c Normal file
View file

@ -0,0 +1,104 @@
/* winsize.c - handle window size changes and information. */
/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdc.h>
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <sys/ioctl.h>
/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
#if 0
#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
#endif
#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
# include <termios.h>
#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
/* Not in either of the standard places, look around. */
#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
# if defined (HAVE_SYS_STREAM_H)
# include <sys/stream.h>
# endif /* HAVE_SYS_STREAM_H */
# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
# include <sys/ptem.h>
# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
# endif /* HAVE_SYS_PTEM_H */
# if defined (HAVE_SYS_PTE_H) /* ??? */
# include <sys/pte.h>
# endif /* HAVE_SYS_PTE_H */
#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
#include <stdio.h>
/* Return the fd from which we are actually getting input. */
#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int shell_tty;
#if defined (READLINE)
/* Let's not call readline, forcing readline to initialize the termcap/terminfo
variables it needs, unless we have to. */
extern int interactive_shell;
extern int no_line_editing;
extern int bash_readline_initialized;
extern void rl_set_screen_size PARAMS((int, int));
#endif
extern void sh_set_lines_and_columns PARAMS((int, int));
void
get_new_window_size (from_sig, rp, cp)
int from_sig;
int *rp, *cp;
{
#if defined (TIOCGWINSZ)
struct winsize win;
int tty;
tty = input_tty ();
if (tty >= 0 && (ioctl (tty, TIOCGWINSZ, &win) == 0) &&
win.ws_row > 0 && win.ws_col > 0)
{
sh_set_lines_and_columns (win.ws_row, win.ws_col);
#if defined (READLINE)
if ((interactive_shell && no_line_editing == 0) || bash_readline_initialized)
rl_set_screen_size (win.ws_row, win.ws_col);
#endif
if (rp)
*rp = win.ws_row;
if (cp)
*cp = win.ws_col;
}
#endif
}

74
lib/sh/zcatfd.c Normal file
View file

@ -0,0 +1,74 @@
/* zcatfd - copy contents of file descriptor to another */
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#include <stdc.h>
#if !defined (errno)
extern int errno;
#endif
#ifndef ZBUFSIZ
# define ZBUFSIZ 4096
#endif
extern ssize_t zread PARAMS((int, char *, size_t));
extern int zwrite PARAMS((int, char *, ssize_t));
/* Dump contents of file descriptor FD to OFD. FN is the filename for
error messages (not used right now). */
int
zcatfd (fd, ofd, fn)
int fd, ofd;
char *fn;
{
ssize_t nr;
int rval;
char lbuf[ZBUFSIZ];
rval = 0;
while (1)
{
nr = zread (fd, lbuf, sizeof (lbuf));
if (nr == 0)
break;
else if (nr < 0)
{
rval = -1;
break;
}
else if (zwrite (ofd, lbuf, nr) < 0)
{
rval = -1;
break;
}
}
return rval;
}

126
lib/sh/zgetline.c Normal file
View file

@ -0,0 +1,126 @@
/* zgetline - read a line of input from a specified file descriptor and return
a pointer to a newly-allocated buffer containing the data. */
/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#include "xmalloc.h"
#if !defined (errno)
extern int errno;
#endif
extern ssize_t zread PARAMS((int, char *, size_t));
extern ssize_t zreadc PARAMS((int, char *));
extern ssize_t zreadintr PARAMS((int, char *, size_t));
extern ssize_t zreadcintr PARAMS((int, char *));
typedef ssize_t breadfunc_t PARAMS((int, char *, size_t));
typedef ssize_t creadfunc_t PARAMS((int, char *));
/* Initial memory allocation for automatic growing buffer in zreadlinec */
#define GET_LINE_INITIAL_ALLOCATION 16
/* Derived from GNU libc's getline.
The behavior is almost the same as getline. See man getline.
The differences are
(1) using file descriptor instead of FILE *;
(2) the order of arguments: the file descriptor comes first;
(3) the addition of a fourth argument, DELIM; sets the delimiter to
be something other than newline if desired. If setting DELIM,
the next argument should be 1; and
(4) the addition of a fifth argument, UNBUFFERED_READ; this argument
controls whether get_line uses buffering or not to get a byte data
from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and
uses zread if UNBUFFERED_READ is non-zero.
Returns number of bytes read or -1 on error. */
ssize_t
zgetline (fd, lineptr, n, delim, unbuffered_read)
int fd;
char **lineptr;
size_t *n;
int delim;
int unbuffered_read;
{
int retval;
size_t nr;
char *line, c;
if (lineptr == 0 || n == 0 || (*lineptr == 0 && *n != 0))
return -1;
nr = 0;
line = *lineptr;
while (1)
{
retval = unbuffered_read ? zread (fd, &c, 1) : zreadc(fd, &c);
if (retval <= 0)
{
if (line && nr > 0)
line[nr] = '\0';
break;
}
if (nr + 2 >= *n)
{
size_t new_size;
new_size = (*n == 0) ? GET_LINE_INITIAL_ALLOCATION : *n * 2;
line = (*n >= new_size) ? NULL : xrealloc (*lineptr, new_size);
if (line)
{
*lineptr = line;
*n = new_size;
}
else
{
if (*n > 0)
{
(*lineptr)[*n - 1] = '\0';
nr = *n - 2;
}
break;
}
}
line[nr] = c;
nr++;
if (c == delim)
{
line[nr] = '\0';
break;
}
}
return nr - 1;
}

93
lib/sh/zmapfd.c Normal file
View file

@ -0,0 +1,93 @@
/* zmapfd - read contents of file descriptor into a newly-allocated buffer */
/* Copyright (C) 2006-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#include "bashansi.h"
#include "command.h"
#include "general.h"
#if !defined (errno)
extern int errno;
#endif
#ifndef ZBUFSIZ
# define ZBUFSIZ 4096
#endif
extern ssize_t zread PARAMS((int, char *, size_t));
/* Dump contents of file descriptor FD to *OSTR. FN is the filename for
error messages (not used right now). */
int
zmapfd (fd, ostr, fn)
int fd;
char **ostr;
char *fn;
{
ssize_t nr;
int rval;
char lbuf[ZBUFSIZ];
char *result;
size_t rsize, rind;
rval = 0;
result = (char *)xmalloc (rsize = ZBUFSIZ);
rind = 0;
while (1)
{
nr = zread (fd, lbuf, sizeof (lbuf));
if (nr == 0)
{
rval = rind;
break;
}
else if (nr < 0)
{
free (result);
if (ostr)
*ostr = (char *)NULL;
return -1;
}
RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, ZBUFSIZ);
memcpy (result+rind, lbuf, nr);
rind += nr;
}
RESIZE_MALLOCED_BUFFER (result, rind, 1, rsize, 128);
result[rind] = '\0';
if (ostr)
*ostr = result;
else
free (result);
return rval;
}

228
lib/sh/zread.c Normal file
View file

@ -0,0 +1,228 @@
/* zread - read data from file descriptor into buffer with retries */
/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <signal.h>
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif
#ifndef SEEK_CUR
# define SEEK_CUR 1
#endif
#ifndef ZBUFSIZ
# define ZBUFSIZ 4096
#endif
extern int executing_builtin;
extern void check_signals_and_traps (void);
extern void check_signals (void);
extern int signal_is_trapped (int);
extern int read_builtin_timeout (int);
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
error causes the loop to break. */
ssize_t
zread (fd, buf, len)
int fd;
char *buf;
size_t len;
{
ssize_t r;
check_signals (); /* check for signals before a blocking read */
/* should generalize into a mechanism where different parts of the shell can
`register' timeouts and have them checked here. */
while (((r = read_builtin_timeout (fd)) < 0 || (r = read (fd, buf, len)) < 0) &&
errno == EINTR)
{
int t;
t = errno;
/* XXX - bash-5.0 */
/* We check executing_builtin and run traps here for backwards compatibility */
if (executing_builtin)
check_signals_and_traps (); /* XXX - should it be check_signals()? */
else
check_signals ();
errno = t;
}
return r;
}
/* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three
interrupts. Any other error causes the loop to break. */
#ifdef NUM_INTR
# undef NUM_INTR
#endif
#define NUM_INTR 3
ssize_t
zreadretry (fd, buf, len)
int fd;
char *buf;
size_t len;
{
ssize_t r;
int nintr;
for (nintr = 0; ; )
{
r = read (fd, buf, len);
if (r >= 0)
return r;
if (r == -1 && errno == EINTR)
{
if (++nintr >= NUM_INTR)
return -1;
continue;
}
return r;
}
}
/* Call read(2) and allow it to be interrupted. Just a stub for now. */
ssize_t
zreadintr (fd, buf, len)
int fd;
char *buf;
size_t len;
{
check_signals ();
return (read (fd, buf, len));
}
/* Read one character from FD and return it in CP. Return values are as
in read(2). This does some local buffering to avoid many one-character
calls to read(2), like those the `read' builtin performs. */
static char lbuf[ZBUFSIZ];
static size_t lind, lused;
ssize_t
zreadc (fd, cp)
int fd;
char *cp;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
nr = zread (fd, lbuf, sizeof (lbuf));
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
/* Don't mix calls to zreadc and zreadcintr in the same function, since they
use the same local buffer. */
ssize_t
zreadcintr (fd, cp)
int fd;
char *cp;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
nr = zreadintr (fd, lbuf, sizeof (lbuf));
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
/* Like zreadc, but read a specified number of characters at a time. Used
for `read -N'. */
ssize_t
zreadn (fd, cp, len)
int fd;
char *cp;
size_t len;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
if (len > sizeof (lbuf))
len = sizeof (lbuf);
nr = zread (fd, lbuf, len);
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
void
zreset ()
{
lind = lused = 0;
}
/* Sync the seek pointer for FD so that the kernel's idea of the last char
read is the last char returned by zreadc. */
void
zsyncfd (fd)
int fd;
{
off_t off, r;
off = lused - lind;
r = 0;
if (off > 0)
r = lseek (fd, -off, SEEK_CUR);
if (r != -1)
lused = lind = 0;
}

64
lib/sh/zwrite.c Normal file
View file

@ -0,0 +1,64 @@
/* zwrite - write contents of buffer to file descriptor, retrying on error */
/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif
/* Write NB bytes from BUF to file descriptor FD, retrying the write if
it is interrupted. We retry three times if we get a zero-length
write. Any other signal causes this function to return prematurely. */
int
zwrite (fd, buf, nb)
int fd;
char *buf;
size_t nb;
{
int n, i, nt;
for (n = nb, nt = 0;;)
{
i = write (fd, buf, n);
if (i > 0)
{
n -= i;
if (n <= 0)
return nb;
buf += i;
}
else if (i == 0)
{
if (++nt > 3)
return (nb - n);
}
else if (errno != EINTR)
return -1;
}
}