Imported from ../bash-2.0.tar.gz.

This commit is contained in:
Jari Aalto 1996-12-23 17:02:34 +00:00
commit ccc6cda312
502 changed files with 91988 additions and 69123 deletions

View file

@ -1,267 +0,0 @@
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
#
MKBUILTINS = mkbuiltins
RANLIB = /usr/bin/ranlib
CFLAGS = -g -I.. -I.
SHELL = /bin/sh
# CC = cc
AR = ar
RM = rm -f
CP = cp
srcdir = .
VPATH = .:$(srcdir)
.SUFFIXES:
.SUFFIXES: .def .c .o
# How to make a .o file from a .def file.
.def.o:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
$(CC) -c $(CFLAGS) $(CPPFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
$(RM) $*.c
# How to make a .c file from a .def file.
.def.c:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
# Here is a rule for making .o files from .c files that does not
# force the type of the machine (like -M_MACHINE) into the flags.
.c.o:
$(RM) $@
$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
DEFS = $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
$(srcdir)/builtin.def $(srcdir)/cd.def $(srcdir)/colon.def \
$(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
$(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
$(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
$(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
$(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
$(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
$(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
$(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
$(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
$(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
$(srcdir)/reserved.def
STATIC_SOURCE = common.c getopt.c bashgetopt.c getopt.h
OFILES = builtins.o \
alias.o bind.o break.o builtin.o cd.o colon.o command.o \
common.o declare.o echo.o enable.o eval.o exec.o exit.o \
fc.o fg_bg.o hash.o help.o history.o jobs.o kill.o \
let.o read.o return.o set.o setattr.o shift.o source.o \
suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
wait.o getopts.o getopt.o bashgetopt.o
THINGS_TO_TAR = $(DEFS) $(STATIC_SOURCE) Makefile ChangeLog
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h
all: $(MKBUILTINS) libbuiltins.a
libbuiltins.a: $(MKBUILTINS) $(OFILES)
$(RM) $@
$(AR) cq $@ $(OFILES)
-$(RANLIB) $@
builtext.h builtins.c: $(MKBUILTINS) $(DEFS)
$(RM) builtext.h builtins.c
./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
-noproduction $(DIRECTDEFINE) $(DEFS)
mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h
$(CC) $(CFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c
ulimit.o: ulimit.def pipesize.h
pipesize.h: psize.aux
$(SHELL) $(srcdir)/psize.sh > pipesize.h
psize.aux: psize.c
$(CC) $(CFLAGS) -o $@ $(srcdir)/psize.c
documentation: builtins.texi
$(OFILES): $(MKBUILTINS) ../config.h
builtins.texi: $(MKBUILTINS)
./$(MKBUILTINS) -documentonly $(DEFS)
clean:
$(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS)
mostlyclean:
$(RM) $(OFILES) libbuiltins.a
distclean realclean maintainer-clean: clean
$(RM) libbuiltins.a
alias.o: alias.def
bind.o: bind.def
break.o: break.def
builtin.o: builtin.def
cd.o: cd.def
colon.o: colon.def
command.o: command.def
declare.o: declare.def
echo.o: echo.def
enable.o: enable.def
eval.o: eval.def
exec.o: exec.def
exit.o: exit.def
fc.o: fc.def
fg_bg.o: fg_bg.def
hash.o: hash.def
help.o: help.def
history.o: history.def
jobs.o: jobs.def
kill.o: kill.def
let.o: let.def
read.o: read.def
return.o: return.def
set.o: set.def
setattr.o: setattr.def
shift.o: shift.def
source.o: source.def
suspend.o: suspend.def
test.o: test.def
times.o: times.def
trap.o: trap.def
type.o: type.def
umask.o: umask.def
wait.o: wait.def
getopts.o: getopts.def
reserved.o: reserved.def
common.o: ../shell.h ../command.h ../config.h ../memalloc.h ../general.h
common.o: ../variables.h ../input.h hashcom.h ../bashhist.h
common.o: ../quit.h ../unwind_prot.h ../maxpath.h ../jobs.h ../builtins.h
common.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
common.o: ../execute_cmd.h ../error.h
alias.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
alias.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
alias.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
bind.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
bind.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
bind.o: ../maxpath.h
bind.o: ../shell.h ../unwind_prot.h ../variables.h bashgetopt.h
break.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
break.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
break.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
builtin.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
builtin.o: ../quit.h common.h ../maxpath.h
builtin.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
builtin.o: ../shell.h ../unwind_prot.h ../variables.h
cd.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
cd.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
cd.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
command.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
command.o: ../quit.h bashgetopt.h ../maxpath.h
command.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
command.o: ../shell.h ../unwind_prot.h ../variables.h
declare.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
declare.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
declare.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
echo.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
echo.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
echo.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
enable.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
enable.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
enable.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
eval.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
eval.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
eval.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
exec.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
exec.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
exec.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../execute_cmd.h
exec.o: ../maxpath.h ../flags.h
exit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
exit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
exit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
fc.o: ../builtins.h ../command.h bashgetopt.h ../bashhist.h
fc.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
fc.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
fc.o: ../flags.h ../unwind_prot.h ../variables.h ../shell.h ../maxpath.h
fg_bg.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
fg_bg.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
fg_bg.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
getopts.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
getopts.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
getopts.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
hash.o: ../builtins.h ../command.h ../quit.h ../execute_cmd.h
hash.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
hash.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
help.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
help.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
help.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
history.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
history.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
history.o: ../filecntl.h ../shell.h ../unwind_prot.h ../variables.h
history.o: ../bashhist.h ../maxpath.h
inlib.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
inlib.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
inlib.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
jobs.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
jobs.o: ../quit.h bashgetopt.h ../maxpath.h
jobs.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
jobs.o: ../shell.h ../unwind_prot.h ../variables.h
kill.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
kill.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
kill.o: ../shell.h ../trap.h ../unwind_prot.h ../variables.h ../maxpath.h
let.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
let.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
let.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
read.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
read.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
read.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
return.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
return.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
return.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
set.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
set.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
set.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
setattr.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
setattr.o: ../quit.h common.h bashgetopt.h ../maxpath.h
setattr.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
setattr.o: ../shell.h ../unwind_prot.h ../variables.h
shift.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
shift.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
shift.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
source.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
source.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
source.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
suspend.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
suspend.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
suspend.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
test.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
test.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
test.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
times.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
times.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
times.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
trap.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
trap.o: ../quit.h common.h ../maxpath.h
trap.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
trap.o: ../shell.h ../unwind_prot.h ../variables.h ../execute_cmd.h
type.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
type.o: ../quit.h common.h ../maxpath.h
type.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
type.o: ../shell.h ../unwind_prot.h ../variables.h
ulimit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
ulimit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
ulimit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
umask.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
umask.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
umask.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
wait.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
wait.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
wait.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
bashgetopt.o: ../bashansi.h ../ansi_stdlib.h
mkbuiltins.o: ../bashansi.h ../ansi_stdlib.h
fc.o: ../bashansi.h ../ansi_stdlib.h
#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h

375
builtins/Makefile.in Normal file
View file

@ -0,0 +1,375 @@
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
#
MKBUILTINS = mkbuiltins
RANLIB = @RANLIB@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
CPPFLAGS = @CPPFLAGS@
SHELL = /bin/sh
CC = @CC@
AR = @AR@
RM = rm -f
CP = cp
LIBS = @LIBS@
srcdir = @srcdir@
VPATH = .:@srcdir@
topdir = @top_srcdir@
includedir = @includedir@
DEFS = @DEFS@
INCLUDES = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(srcdir)
CCFLAGS = $(DEFS) $(SYSTEM_FLAGS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
DIRECTDEFINE = -D $(srcdir)
# xxx this is bad style
RL_LIBSRC = $(topdir)/lib/readline
.SUFFIXES:
.SUFFIXES: .def .c .o
# How to make a .o file from a .def file.
.def.o:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
$(CC) -c $(CCFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
$(RM) $*.c
# How to make a .c file from a .def file.
.def.c:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
# default rule for making a .o file from a .c file
.c.o:
$(RM) $@
$(CC) -c $(CCFLAGS) $<
DEFSRC = $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
$(srcdir)/builtin.def $(srcdir)/cd.def $(srcdir)/colon.def \
$(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
$(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
$(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
$(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
$(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
$(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
$(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
$(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
$(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
$(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
$(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def
STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
getopt.h
OFILES = builtins.o \
alias.o bind.o break.o builtin.o cd.o colon.o command.o \
common.o declare.o echo.o enable.o eval.o evalfile.o \
evalstring.o exec.o \
exit.o fc.o fg_bg.o hash.o help.o history.o jobs.o kill.o let.o \
pushd.o read.o return.o set.o setattr.o shift.o source.o \
suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
wait.o getopts.o shopt.o getopt.o bashgetopt.o
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h
all: $(MKBUILTINS) libbuiltins.a
libbuiltins.a: $(MKBUILTINS) $(OFILES)
$(RM) $@
$(AR) cr $@ $(OFILES)
-$(RANLIB) $@
builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
$(RM) builtext.h builtins.c
./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
-noproduction $(DIRECTDEFINE) $(DEFSRC)
mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h
$(CC) $(CCFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c $(LIBS)
# rules for deficient makes, like SunOS
common.o: common.c
bashgetopt.o: bashgetopt.c
getopt.o: getopt.c
ulimit.o: ulimit.def pipesize.h
pipesize.h: psize.aux
$(SHELL) $(srcdir)/psize.sh > pipesize.h
psize.aux: psize.c
$(CC) $(CCFLAGS) -o $@ $(srcdir)/psize.c
documentation: builtins.texi
$(OFILES): $(MKBUILTINS) ../config.h
builtins.texi: $(MKBUILTINS)
./$(MKBUILTINS) -documentonly $(DEFSRC)
clean:
$(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS) libbuiltins.a
mostlyclean:
$(RM) $(OFILES) libbuiltins.a
distclean maintainer-clean: clean
$(RM) Makefile
alias.o: alias.def
bind.o: bind.def
break.o: break.def
builtin.o: builtin.def
cd.o: cd.def
colon.o: colon.def
command.o: command.def
declare.o: declare.def
echo.o: echo.def
enable.o: enable.def
eval.o: eval.def
exec.o: exec.def
exit.o: exit.def
fc.o: fc.def
fg_bg.o: fg_bg.def
hash.o: hash.def
help.o: help.def
history.o: history.def
jobs.o: jobs.def
kill.o: kill.def
let.o: let.def
pushd.o: pushd.def
read.o: read.def
return.o: return.def
set.o: set.def
setattr.o: setattr.def
shift.o: shift.def
source.o: source.def
suspend.o: suspend.def
test.o: test.def
times.o: times.def
trap.o: trap.def
type.o: type.def
umask.o: umask.def
wait.o: wait.def
getopts.o: getopts.def
reserved.o: reserved.def
common.o: $(topdir)/shell.h $(topdir)/command.h ../config.h
common.o: $(topdir)/memalloc.h $(topdir)/general.h
common.o: $(topdir)/variables.h $(topdir)/input.h $(srcdir)/hashcom.h
common.o: $(topdir)/bashhist.h $(topdir)/quit.h $(topdir)/unwind_prot.h
common.o: $(topdir)/maxpath.h $(topdir)/jobs.h $(topdir)/builtins.h
common.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
common.o: $(topdir)/execute_cmd.h $(topdir)/error.h $(topdir)/externs.h
alias.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
alias.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/maxpath.h
alias.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
alias.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/common.h
alias.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
bind.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
bind.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
bind.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/bashgetopt.h
bind.o: $(topdir)/general.h $(topdir)/maxpath.h $(topdir)/bashline.h
bind.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
break.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
break.o: $(topdir)/error.h $(topdir)/general.h
break.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
break.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
break.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
builtin.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
builtin.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/externs.h
builtin.o: $(topdir)/quit.h $(srcdir)/common.h $(topdir)/maxpath.h
builtin.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
builtin.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
cd.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
cd.o: $(topdir)/general.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
cd.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
cd.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
cd.o: $(srcdir)/common.h $(topdir)/maxpath.h
command.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
command.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/externs.h
command.o: $(topdir)/quit.h $(srcdir)/bashgetopt.h $(topdir)/maxpath.h
command.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
command.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
declare.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
declare.o: $(topdir)/error.h $(topdir)/general.h
declare.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
declare.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
declare.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
echo.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
echo.o: $(topdir)/general.h $(topdir)/subst.h $(topdir)/externs.h
echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
echo.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
echo.o: $(topdir)/maxpath.h
enable.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
enable.o: $(topdir)/error.h $(topdir)/general.h
enable.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
enable.o: $(topdir)/subst.h $(topdir)/externs.h
enable.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
enable.o: $(topdir)/maxpath.h
eval.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
eval.o: $(topdir)/error.h $(topdir)/general.h
eval.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
eval.o: $(topdir)/subst.h $(topdir)/externs.h
eval.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
eval.o: $(topdir)/maxpath.h
exec.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
exec.o: $(topdir)/error.h $(topdir)/general.h
exec.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
exec.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/flags.h
exec.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(topdir)/maxpath.h
exit.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
exit.o: $(topdir)/error.h $(topdir)/general.h
exit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
exit.o: $(topdir)/subst.h $(topdir)/externs.h
exit.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
exit.o: $(topdir)/maxpath.h
fc.o: $(topdir)/builtins.h $(topdir)/command.h $(srcdir)/bashgetopt.h
fc.o: $(topdir)/bashhist.h
fc.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
fc.o: $(topdir)/general.h $(topdir)/maxpath.h
fc.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h
fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h
fg_bg.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
fg_bg.o: $(topdir)/error.h $(topdir)/general.h
fg_bg.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
fg_bg.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
fg_bg.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
getopts.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
getopts.o: $(topdir)/error.h $(topdir)/general.h
getopts.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
getopts.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
getopts.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h
hash.o: $(topdir)/execute_cmd.h $(topdir)/hashlib.h
hash.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
hash.o: $(topdir)/error.h $(topdir)/general.h
hash.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
hash.o: $(srcdir)/common.h $(topdir)/maxpath.h
help.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
help.o: $(topdir)/error.h $(topdir)/general.h
help.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
help.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
help.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
history.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
history.o: $(topdir)/error.h $(topdir)/general.h
history.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
history.o: $(topdir)/subst.h $(topdir)/externs.h
history.o: $(topdir)/filecntl.h $(topdir)/shell.h $(topdir)/unwind_prot.h
history.o: $(topdir)/variables.h $(topdir)/bashhist.h $(topdir)/maxpath.h
inlib.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
inlib.o: $(topdir)/error.h $(topdir)/general.h
inlib.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
inlib.o: $(topdir)/maxpath.h $(topdir)/subst.h $(topdir)/externs.h
inlib.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
jobs.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
jobs.o: $(topdir)/general.h $(topdir)/quit.h $(srcdir)/bashgetopt.h
jobs.o: $(topdir)/maxpath.h $(topdir)/externs.h
jobs.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
jobs.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
kill.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h $(topdir)/error.h
kill.o: $(topdir)/general.h $(topdir)/subst.h $(topdir)/externs.h
kill.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
kill.o: $(topdir)/shell.h $(topdir)/trap.h $(topdir)/unwind_prot.h
kill.o: $(topdir)/variables.h $(topdir)/maxpath.h
let.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
let.o: $(topdir)/error.h $(topdir)/general.h
let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
let.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
let.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
pushd.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
pushd.o: $(topdir)/error.h $(topdir)/general.h
pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
pushd.o: $(topdir)/subst.h $(topdir)/externs.h
pushd.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
pushd.o: $(topdir)/maxpath.h $(srcdir)/common.h
read.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
read.o: $(topdir)/error.h $(topdir)/general.h
read.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
read.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
read.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
return.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
return.o: $(topdir)/error.h $(topdir)/general.h
return.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
return.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
return.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
set.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
set.o: $(topdir)/general.h $(topdir)/subst.h $(topdir)/externs.h
set.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
set.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
set.o: $(topdir)/maxpath.h $(topdir)/error.h
setattr.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
setattr.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/maxpath.h
setattr.o: $(topdir)/quit.h $(srcdir)/common.h $(srcdir)/bashgetopt.h
setattr.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
setattr.o: $(topdir)/externs.h
setattr.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
shift.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
shift.o: $(topdir)/error.h $(topdir)/general.h
shift.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
shift.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
shift.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
source.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
source.o: $(topdir)/error.h $(topdir)/general.h
source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
source.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
source.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
suspend.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
suspend.o: $(topdir)/error.h $(topdir)/general.h
suspend.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
suspend.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
suspend.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
test.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
test.o: $(topdir)/error.h $(topdir)/general.h
test.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
test.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
test.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
times.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
times.o: $(topdir)/error.h $(topdir)/general.h
times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
times.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
times.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
trap.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/externs.h
trap.o: $(topdir)/quit.h $(srcdir)/common.h $(topdir)/maxpath.h
trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
trap.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
trap.o: $(topdir)/execute_cmd.h
type.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
type.o: $(topdir)/error.h $(topdir)/general.h
type.o: $(topdir)/quit.h $(srcdir)/common.h $(topdir)/maxpath.h
type.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
type.o: $(topdir)/externs.h
type.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
ulimit.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
ulimit.o: $(topdir)/error.h $(topdir)/general.h
ulimit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
ulimit.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
ulimit.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
umask.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
umask.o: $(topdir)/error.h $(topdir)/general.h
umask.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
umask.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
umask.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
wait.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
wait.o: $(topdir)/error.h $(topdir)/general.h
wait.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
wait.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
wait.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
shopt.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h
shopt.o: $(topdir)/error.h $(topdir)/general.h
shopt.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
shopt.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h
shopt.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h
shopt.o: $(srcdir)/common.h $(srcdir)/bashgetopt.h
bashgetopt.o: $(topdir)/bashansi.h $(topdir)/ansi_stdlib.h
mkbuiltins.o: $(topdir)/bashansi.h $(topdir)/ansi_stdlib.h
fc.o: $(topdir)/bashansi.h $(topdir)/ansi_stdlib.h
#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h

View file

@ -23,85 +23,108 @@ $BUILTIN alias
$FUNCTION alias_builtin
$DEPENDS_ON ALIAS
$PRODUCES alias.c
$SHORT_DOC alias [ name[=value] ... ]
`alias' with no arguments prints the list of aliases in the form
NAME=VALUE on standard output. An alias is defined for each NAME
whose VALUE is given. A trailing space in VALUE causes the next
word to be checked for alias substitution. Alias returns true
unless a NAME is given for which no alias has been defined.
$SHORT_DOC alias [-p] [name[=value] ... ]
`alias' with no arguments or with the -p option prints the list
of aliases in the form alias NAME=VALUE on standard output.
Otherwise, an alias is defined for each NAME whose VALUE is given.
A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded. Alias returns
true unless a NAME is given for which no alias has been defined.
$END
#include "../config.h"
#include <config.h>
#if defined (ALIAS)
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
# include <stdio.h>
# include "../shell.h"
# include "../alias.h"
# include "common.h"
# include "bashgetopt.h"
extern int interactive;
static void print_alias ();
/* Hack the alias command in a Korn shell way. */
int
alias_builtin (list)
WORD_LIST *list;
{
int any_failed = 0;
int any_failed, offset, pflag;
alias_t **alias_list, *t;
char *name, *value;
if (!list)
pflag = 0;
reset_internal_getopt ();
while ((offset = internal_getopt (list, "p")) != -1)
{
register int i;
ASSOC **alias_list;
switch (offset)
{
case 'p':
pflag = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
if (!aliases)
list = loptend;
if (list == 0 || pflag)
{
if (aliases == 0)
return (EXECUTION_FAILURE);
alias_list = all_aliases ();
if (!alias_list)
if (alias_list == 0)
return (EXECUTION_FAILURE);
for (i = 0; alias_list[i]; i++)
print_alias (alias_list[i]);
for (offset = 0; alias_list[offset]; offset++)
print_alias (alias_list[offset]);
free (alias_list); /* XXX - Do not free the strings. */
if (list == 0)
return (EXECUTION_SUCCESS);
}
else
any_failed = 0;
while (list)
{
while (list)
name = list->word->word;
for (offset = 0; name[offset] && name[offset] != '='; offset++)
;
if (offset && name[offset] == '=')
{
register char *value, *name = list->word->word;
register int offset;
name[offset] = '\0';
value = name + offset + 1;
for (offset = 0; name[offset] && name[offset] != '='; offset++)
;
if (offset && name[offset] == '=')
{
name[offset] = '\0';
value = name + offset + 1;
add_alias (name, value);
}
add_alias (name, value);
}
else
{
t = find_alias (name);
if (t)
print_alias (t);
else
{
ASSOC *t = find_alias (name);
if (t)
print_alias (t);
else
{
if (interactive)
builtin_error ("`%s' not found", name);
any_failed++;
}
if (interactive)
builtin_error ("`%s' not found", name);
any_failed++;
}
list = list->next;
}
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
#endif /* ALIAS */
@ -115,33 +138,37 @@ $END
#if defined (ALIAS)
/* Remove aliases named in LIST from the aliases database. */
int
unalias_builtin (list)
register WORD_LIST *list;
{
register ASSOC *alias;
int any_failed = 0;
register alias_t *alias;
int opt, aflag;
while (list && *list->word->word == '-')
aflag = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "a")) != -1)
{
register char *word = list->word->word;
if (ISOPTION (word, 'a'))
switch (opt)
{
delete_all_aliases ();
list = list->next;
}
else if (ISOPTION (word, '-'))
{
list = list->next;
case 'a':
aflag = 1;
break;
}
else
{
bad_option (word);
return (EXECUTION_FAILURE);
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (aflag)
{
delete_all_aliases ();
return (EXECUTION_SUCCESS);
}
aflag = 0;
while (list)
{
alias = find_alias (list->word->word);
@ -151,27 +178,25 @@ unalias_builtin (list)
else
{
if (interactive)
builtin_error ("`%s' not an alias", list->word->word);
builtin_error ("`%s': not an alias", list->word->word);
any_failed++;
aflag++;
}
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
return (aflag ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
/* Output ALIAS in such a way as to allow it to be read back in. */
static void
print_alias (alias)
ASSOC *alias;
alias_t *alias;
{
char *value = single_quote (alias->value);
char *value;
value = single_quote (alias->value);
printf ("alias %s=%s\n", alias->name, value);
free (value);

View file

@ -18,10 +18,17 @@ You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <errno.h>
#include "shell.h"
#include <config.h>
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include <errno.h>
#include "../shell.h"
#include "common.h"
#define ERR(S, C) builtin_error("%s%c", (S), (C))
@ -41,14 +48,21 @@ char *opts;
{
register int c;
register char *cp;
int plus; /* nonzero means to handle +option */
if (!list) {
if (*opts == '+') {
plus = 1;
opts++;
} else
plus = 0;
if (list == 0) {
list_optarg = (char *)NULL;
loptend = (WORD_LIST *)NULL; /* No non-option arguments */
return -1;
}
if (list != lhead || !lhead) {
if (list != lhead || lhead == 0) {
/* Hmmm.... called with a different word list. Reset. */
sp = 1;
lcurrent = lhead = list;
@ -56,7 +70,7 @@ char *opts;
}
if (sp == 1) {
if (!lcurrent ||
if (lcurrent == 0 ||
(lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) {
lhead = (WORD_LIST *)NULL;
loptend = lcurrent;
@ -84,23 +98,46 @@ char *opts;
return('?');
}
if (*++cp == ':') {
/* Option requires an argument. */
if (*++cp == ':' || *cp == ';') {
/* `:': Option requires an argument. */
/* `;': option argument may be missing */
/* We allow -l2 as equivalent to -l 2 */
if (lcurrent->word->word[sp+1] != '\0') {
list_optarg = &(lcurrent->word->word[sp+1]);
if (lcurrent->word->word[sp+1]) {
list_optarg = lcurrent->word->word + sp + 1;
lcurrent = lcurrent->next;
} else if (lcurrent->next == NULL) {
/* If the specifier is `;', don't set optarg if the next
argument looks like another option. */
} else if (lcurrent->next && (*cp == ':' || lcurrent->next->word->word[0] != '-')) {
lcurrent = lcurrent->next;
list_optarg = lcurrent->word->word;
lcurrent = lcurrent->next;
} else if (*cp == ';') {
list_optarg = (char *)NULL;
lcurrent = lcurrent->next;
} else { /* lcurrent->next == NULL */
ERR("option requires an argument: -", c);
sp = 1;
list_optarg = (char *)NULL;
return('?');
} else {
lcurrent = lcurrent->next;
list_optarg = lcurrent->word->word;
lcurrent = lcurrent->next;
}
sp = 1;
} else if (*cp == '#') {
/* optional numeric argument */
if (lcurrent->word->word[sp+1]) {
if (digit(lcurrent->word->word[sp+1])) {
list_optarg = lcurrent->word->word + sp + 1;
lcurrent = lcurrent->next;
} else
list_optarg = (char *)NULL;
} else {
if (lcurrent->next && legal_number(lcurrent->next->word->word, (long *)0)) {
lcurrent = lcurrent->next;
list_optarg = lcurrent->word->word;
lcurrent = lcurrent->next;
} else
list_optarg = (char *)NULL;
}
} else {
/* No argument, just return the option. */
if (lcurrent->word->word[++sp] == '\0') {

View file

@ -21,10 +21,12 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES bind.c
#include <config.h>
$BUILTIN bind
$DEPENDS_ON READLINE
$FUNCTION bind_builtin
$SHORT_DOC bind [-lvd] [-m keymap] [-f filename] [-q name] [keyseq:readline-function]
$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-r keyseq] [keyseq:readline-function]
Bind a key sequence to a Readline function, or to a macro. The
syntax is equivalent to that found in ~/.inputrc, but must be
passed as a single argument: bind '"\C-x\C-r": re-read-init-file'.
@ -34,49 +36,75 @@ Arguments we accept:
emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
vi-command, and vi-insert.
-l List names of functions.
-v List function names and bindings.
-d Dump functions and bindings such that they
can be read back in.
-P List function names and bindings.
-p List functions and bindings in a form that can be
reused as input.
-r keyseq Remove the binding for KEYSEQ.
-f filename Read key bindings from FILENAME.
-q function-name Query about which keys invoke the named function.
-V List variable names and values
-v List variable names and values in a form that can
be reused as input.
-S List key sequences that invoke macros and their values
-s List key sequences that invoke macros and their values in
a form that can be reused as input.
$END
#include <stdio.h>
#include "../shell.h"
#if defined (READLINE)
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include <readline/readline.h>
#include <readline/history.h>
#include "../shell.h"
#include "../bashline.h"
#include "bashgetopt.h"
#include "common.h"
static int query_bindings ();
extern int bash_readline_initialized;
extern int no_line_editing;
#define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0)
#define USAGE "usage: bind [-lvd] [-m keymap] [-f filename] [-q name] [keyseq:readline_func]"
#define LFLAG 0x01
#define PFLAG 0x02
#define FFLAG 0x04
#define VFLAG 0x08
#define QFLAG 0x10
#define MFLAG 0x20
#define RFLAG 0x40
#define PPFLAG 0x80
#define VVFLAG 0x100
#define SFLAG 0x200
#define SSFLAG 0x400
int
bind_builtin (list)
WORD_LIST *list;
{
int return_code = EXECUTION_SUCCESS;
int return_code;
FILE *old_rl_outstream;
Keymap kmap, saved_keymap;
int lflag, dflag, fflag, vflag, qflag, mflag, opt;
char *initfile, *map_name, *fun_name;
int flags, opt;
char *initfile, *map_name, *fun_name, *remove_seq;
if (no_line_editing)
return (EXECUTION_FAILURE);
kmap = saved_keymap = (Keymap) NULL;
lflag = dflag = vflag = fflag = qflag = mflag = 0;
initfile = map_name = fun_name = (char *)NULL;
flags = 0;
initfile = map_name = fun_name = remove_seq = (char *)NULL;
return_code = EXECUTION_SUCCESS;
if (!bash_readline_initialized)
initialize_readline ();
@ -88,39 +116,49 @@ bind_builtin (list)
rl_outstream = stdout;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lvdf:q:m:")) != EOF)
while ((opt = internal_getopt (list, "lvpVPsSf:q:m:r:")) != EOF)
{
switch (opt)
{
case 'l':
lflag++;
flags |= LFLAG;
break;
case 'v':
vflag++;
flags |= VFLAG;
break;
case 'd':
dflag++;
case 'p':
flags |= PFLAG;
break;
case 'f':
fflag++;
flags |= FFLAG;
initfile = list_optarg;
break;
case 'm':
mflag++;
flags |= MFLAG;
map_name = list_optarg;
break;
case 'q':
qflag++;
flags |= QFLAG;
fun_name = list_optarg;
break;
case 'r':
flags |= RFLAG;
remove_seq = list_optarg;
break;
case 'V':
flags |= VVFLAG;
break;
case 'P':
flags |= PPFLAG;
break;
case 's':
flags |= SFLAG;
break;
case 'S':
flags |= SSFLAG;
break;
default:
builtin_error (USAGE);
builtin_usage ();
BIND_RETURN (EX_USAGE);
}
}
@ -130,12 +168,12 @@ bind_builtin (list)
/* First, see if we need to install a special keymap for this
command. Then start on the arguments. */
if (mflag && map_name)
if ((flags & MFLAG) && map_name)
{
kmap = rl_get_keymap_by_name (map_name);
if (!kmap)
{
builtin_error ("`%s': illegal keymap name", map_name);
builtin_error ("`%s': invalid keymap name", map_name);
BIND_RETURN (EXECUTION_FAILURE);
}
}
@ -149,16 +187,28 @@ bind_builtin (list)
/* XXX - we need to add exclusive use tests here. It doesn't make sense
to use some of these options together. */
/* Now hack the option arguments */
if (lflag)
rl_list_funmap_names (0);
if (flags & LFLAG)
rl_list_funmap_names ();
if (vflag)
rl_function_dumper (0);
if (dflag)
if (flags & PFLAG)
rl_function_dumper (1);
if (fflag && initfile)
if (flags & PPFLAG)
rl_function_dumper (0);
if (flags & SFLAG)
rl_macro_dumper (1);
if (flags & SSFLAG)
rl_macro_dumper (0);
if (flags & VFLAG)
rl_variable_dumper (1);
if (flags & VVFLAG)
rl_variable_dumper (0);
if ((flags & FFLAG) && initfile)
{
if (rl_read_init_file (initfile) != 0)
{
@ -167,9 +217,18 @@ bind_builtin (list)
}
}
if (qflag && fun_name)
if ((flags & QFLAG) && fun_name)
return_code = query_bindings (fun_name);
if ((flags & RFLAG) && remove_seq)
{
if (rl_set_key (remove_seq, (Function *)NULL, rl_get_keymap ()) != 0)
{
builtin_error ("cannot unbind %s", remove_seq);
BIND_RETURN (EXECUTION_FAILURE);
}
}
/* Process the rest of the arguments as binding specifications. */
while (list)
{

View file

@ -27,8 +27,14 @@ $SHORT_DOC break [n]
Exit from within a FOR, WHILE or UNTIL loop. If N is specified,
break N levels.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include "../shell.h"
#include "common.h"
extern char *this_command_name;
@ -45,6 +51,7 @@ int continuing = 0;
/* Set up to break x levels, where x defaults to 1, but can be specified
as the first argument. */
int
break_builtin (list)
WORD_LIST *list;
{
@ -75,6 +82,7 @@ $END
/* Set up to continue x levels, where x defaults to 1, but can be specified
as the first argument. */
int
continue_builtin (list)
WORD_LIST *list;
{
@ -103,7 +111,7 @@ check_loop_level ()
{
#if defined (BREAK_COMPLAINS)
if (!loop_level)
builtin_error ("Only meaningful in a `for', `while', or `until' loop");
builtin_error ("only meaningful in a `for', `while', or `until' loop");
#endif /* BREAK_COMPLAINS */
return (loop_level);

View file

@ -28,15 +28,20 @@ Run a shell builtin. This is useful when you wish to rename a
shell builtin to be a function, but need the functionality of the
builtin within the function itself.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "common.h"
extern char *this_command_name;
/* Run the command mentioned in list directly, without going through the
normal alias/function/builtin/filename lookup process. */
int
builtin_builtin (list)
WORD_LIST *list;
{

File diff suppressed because it is too large Load diff

View file

@ -28,10 +28,32 @@ $SHORT_DOC :
No effect; the command does nothing. A zero exit code is returned.
$END
/* Do nothing. This command is a no-op. */
$BUILTIN true
$DOCNAME true_builtin
$FUNCTION colon_builtin
$SHORT_DOC true
Return a successful result.
$END
$BUILTIN false
$DOCNAME false_builtin
$FUNCTION false_builtin
$SHORT_DOC false
Return an unsuccessful result.
$END
/* Return a successful result. */
int
colon_builtin (ignore)
char *ignore;
{
return (0);
}
/* Return an unsuccessful result. */
int
false_builtin (ignore)
char *ignore;
{
return (1);
}

View file

@ -23,7 +23,7 @@ $PRODUCES command.c
$BUILTIN command
$FUNCTION command_builtin
$SHORT_DOC command [-pVv] [command [arg ...]]
$SHORT_DOC command [-pVv] command [arg ...]
Runs COMMAND with ARGS ignoring shell functions. If you have a shell
function called `ls', and you wish to call the command `ls', you can
say "command ls". If the -p option is given, a default value is used
@ -32,14 +32,19 @@ the -V or -v option is given, a string is printed describing COMMAND.
The -V option produces a more verbose description.
$END
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../execute_cmd.h"
#include "../flags.h"
#include "bashgetopt.h"
#include "common.h"
extern int subshell_environment;
@ -52,9 +57,11 @@ int
command_builtin (list)
WORD_LIST *list;
{
int result, verbose = 0, use_standard_path = 0, opt;
char *old_path;
int result, verbose, use_standard_path, opt;
char *old_path, *standard_path;
COMMAND *command;
verbose = use_standard_path = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "pvV")) != -1)
{
@ -69,73 +76,80 @@ command_builtin (list)
case 'v':
verbose = 4;
break;
default:
report_bad_option ();
builtin_error ("usage: command [-pvV] [command [arg...]]");
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (!list)
if (list == 0)
return (EXECUTION_SUCCESS);
if (verbose)
{
int found, any_found = 0;
int found, any_found;
while (list)
for (any_found = 0; list; list = list->next)
{
found = describe_command (list->word->word, verbose, 0);
if (!found)
if (found == 0)
builtin_error ("%s: not found", list->word->word);
any_found += found;
list = list->next;
}
return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
#if defined (RESTRICTED_SHELL)
if (use_standard_path && restricted)
{
builtin_error ("restricted: cannot use -p");
return (EXECUTION_FAILURE);
}
#endif
begin_unwind_frame ("command_builtin");
/* We don't want this to be reparsed (consider command echo 'foo &'), so
just make a simple_command structure and call execute_command with it. */
{
COMMAND *command;
if (use_standard_path)
{
old_path = get_string_value ("PATH");
if (old_path)
old_path = savestring (old_path);
else
{
old_path = xmalloc (1);
old_path[0] = '\0';
}
add_unwind_protect ((Function *)restore_path, old_path);
if (use_standard_path)
{
char *standard_path;
standard_path = get_standard_path ();
bind_variable ("PATH", standard_path ? standard_path : "");
FREE (standard_path);
}
old_path = get_string_value ("PATH");
if (old_path)
old_path = savestring (old_path);
else
old_path = savestring ("");
add_unwind_protect ((Function *)restore_path, old_path);
standard_path = get_standard_path ();
bind_variable ("PATH", standard_path);
free (standard_path);
}
command = make_bare_simple_command ();
command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
command->value.Simple->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
/* If we're in a subshell, see if we can get away without forking
again, since we've already forked to run this builtin. */
if (subshell_environment)
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
add_unwind_protect ((char *)dispose_command, command);
result = execute_command (command);
}
command = make_bare_simple_command ();
command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
command->value.Simple->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
#if 0
/* This breaks for things like ( cd /tmp ; command z ababa ; echo next )
or $(command echo a ; command echo b;) or even
{ command echo a; command echo b; } & */
/* If we're in a subshell, see if we can get away without forking
again, since we've already forked to run this builtin. */
if (subshell_environment)
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
#endif
add_unwind_protect ((char *)dispose_command, command);
result = execute_command (command);
run_unwind_frame ("command_builtin");
@ -158,7 +172,7 @@ restore_path (var)
static char *
get_standard_path ()
{
#if defined (_CS_PATH) && !defined (hpux_7) && !defined (NetBSD)
#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
char *p;
size_t len;
@ -167,11 +181,11 @@ get_standard_path ()
*p = '\0';
confstr (_CS_PATH, p, len);
return (p);
#else /* !_CSPATH || hpux_7 || NetBSD */
#else /* !_CSPATH || !HAVE_CONFSTR */
# if defined (CS_PATH)
return (savestring (CS_PATH));
# else
return (savestring (STANDARD_UTILS_PATH));
# endif /* !CS_PATH */
#endif /* !_CS_PATH || hpux_7 */
#endif /* !_CS_PATH || !HAVE_CONFSTR */
}

File diff suppressed because it is too large Load diff

View file

@ -21,23 +21,23 @@
#if !defined (__COMMON_H)
# define __COMMON_H
#include "../stdc.h"
#define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
extern void builtin_error ();
extern void builtin_error __P((const char *, ...));
extern void builtin_usage ();
extern void bad_option ();
extern char **make_builtin_argv ();
extern int get_numeric_arg ();
extern void remember_args ();
extern void no_args ();
extern int no_options ();
extern int read_octal ();
extern char *find_hashed_filename ();
extern void remove_hashed_filename ();
extern void remember_filename ();
extern void push_context (), pop_context ();
extern void push_dollar_vars (), pop_dollar_vars ();
extern void dispose_saved_dollar_vars ();
@ -53,17 +53,55 @@ extern void set_working_directory ();
extern int get_job_spec ();
#endif
extern int parse_and_execute ();
extern void parse_and_execute_cleanup ();
extern void initialize_shell_builtins ();
extern int display_signal_list ();
/* It's OK to declare a function as returning a Function * without
providing a definition of what a `Function' is. */
extern struct builtin *builtin_address_internal ();
extern Function *find_shell_builtin ();
extern Function *builtin_address ();
extern Function *find_special_builtin ();
extern void initialize_shell_builtins ();
extern char *single_quote ();
extern char *double_quote ();
extern char *backslash_quote ();
extern int contains_shell_metas ();
/* Functions from hash.def */
extern void initialize_filename_hashing ();
extern void flush_hashed_filenames ();
extern char *find_hashed_filename ();
extern void remove_hashed_filename ();
extern void remember_filename ();
/* Functions from set.def */
extern void initialize_shell_options ();
extern void list_minus_o_opts ();
extern int set_minus_o_option ();
extern int minus_o_option_value ();
/* Functions from type.def */
extern int describe_command ();
/* Functions from setattr.def */
extern int set_or_show_attributes ();
extern int show_var_attributes ();
extern int show_name_attributes ();
extern void set_var_attribute ();
/* Functions from pushd.def */
extern char *get_dirstack_element ();
extern void set_dirstack_element ();
extern WORD_LIST *get_directory_stack ();
/* Functions from evalstring.c */
extern int parse_and_execute ();
extern void parse_and_execute_cleanup ();
/* Functions from evalfile.c */
extern int maybe_execute_file __P((char *, int));
extern int source_file __P((char *));
#endif /* !__COMMON_H */

View file

@ -23,39 +23,50 @@ $PRODUCES declare.c
$BUILTIN declare
$FUNCTION declare_builtin
$SHORT_DOC declare [-[frxi]] name[=value] ...
$SHORT_DOC declare [-afFrxi] [-p] name[=value] ...
Declare variables and/or give them attributes. If no NAMEs are
given, then display the values of variables instead.
given, then display the values of variables instead. The -p option
will display the attributes and values of each NAME.
The flags are:
-f to select from among function names only,
-r to make NAMEs readonly,
-x to make NAMEs export,
-i to make NAMEs have the `integer' attribute set.
-a to make NAMEs arrays (if supported)
-f to select from among function names only
-F to display function names without definitions
-r to make NAMEs readonly
-x to make NAMEs export
-i to make NAMEs have the `integer' attribute set
Variables with the integer attribute have arithmetic evaluation (see
`let') done when the variable is assigned to.
When displaying values of variables, -f displays a function's name
and definition. The -F option restricts the display to function
name only.
Using `+' instead of `-' turns off the given attribute instead. When
used in a function, makes NAMEs local, as with the `local' command.
$END
$BUILTIN typeset
$FUNCTION declare_builtin
$SHORT_DOC typeset [-[frxi]] name[=value] ...
$SHORT_DOC typeset [-afFrxi] [-p] name[=value] ...
Obsolete. See `declare'.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../bashansi.h"
#include "../shell.h"
#include "common.h"
#include "builtext.h"
extern int variable_context, array_needs_making;
@ -84,7 +95,7 @@ local_builtin (list)
return (declare_internal (list, 1));
else
{
builtin_error ("Can only be used in a function");
builtin_error ("can only be used in a function");
return (EXECUTION_FAILURE);
}
}
@ -95,14 +106,14 @@ declare_internal (list, local_var)
register WORD_LIST *list;
int local_var;
{
int flags_on = 0, flags_off = 0;
int any_failed = 0;
int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs;
char *t;
SHELL_VAR *var;
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
while (list)
{
register char *t = list->word->word;
int *flags;
t = list->word->word;
if (t[0] == '-' && t[1] == '-' && t[2] == '\0')
{
list = list->next;
@ -112,16 +123,18 @@ declare_internal (list, local_var)
if (*t != '+' && *t != '-')
break;
if (*t == '+')
flags = &flags_off;
else
flags = &flags_on;
t++;
flags = (*t++ == '+') ? &flags_off : &flags_on;
while (*t)
{
if (*t == 'f')
if (*t == 'p' && local_var == 0)
pflag++, t++;
else if (*t == 'F')
{
nodefs++;
*flags |= att_function; t++;
}
else if (*t == 'f')
*flags |= att_function, t++;
else if (*t == 'x')
*flags |= att_exported, t++, array_needs_making = 1;
@ -129,9 +142,14 @@ declare_internal (list, local_var)
*flags |= att_readonly, t++;
else if (*t == 'i')
*flags |= att_integer, t++;
#if defined (ARRAY_VARS)
else if (*t == 'a')
*flags |= att_array, t++;
#endif
else
{
builtin_error ("unknown option: `-%c'", *t);
builtin_usage ();
return (EX_USAGE);
}
}
@ -141,7 +159,7 @@ declare_internal (list, local_var)
/* If there are no more arguments left, then we just want to show
some variables. */
if (!list)
if (list == 0) /* declare -[afFirx] */
{
/* Show local variables defined at this context level if this is
the `local' builtin. */
@ -162,25 +180,45 @@ declare_internal (list, local_var)
}
else
{
if (!flags_on)
if (flags_on == 0)
set_builtin ((WORD_LIST *)NULL);
else
set_or_show_attributes ((WORD_LIST *)NULL, flags_on);
set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}
if (pflag) /* declare -p [-afFirx] name [name...] */
{
for (any_failed = 0; list; list = list->next)
{
pflag = show_name_attributes (list->word->word, nodefs);
if (pflag)
{
builtin_error ("%s: not found", list->word->word);
any_failed++;
}
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
while (list)
while (list) /* declare [-afFirx] name [name ...] */
{
char *value, *name = savestring (list->word->word);
int offset = assignment (name);
char *value, *name;
int offset;
#if defined (ARRAY_VARS)
int making_array_special, assigning_array_special;
#endif
if (offset)
name = savestring (list->word->word);
offset = assignment (name);
if (offset) /* declare [-afFirx] name=value */
{
name[offset] = '\0';
value = name + offset + 1;
@ -188,10 +226,21 @@ declare_internal (list, local_var)
else
value = "";
#if defined (ARRAY_VARS)
assigning_array_special = 0;
if (t = strchr (name, '['))
{
*t = '\0';
making_array_special = 1;
}
else
making_array_special = 0;
#endif
if (legal_identifier (name) == 0)
{
builtin_error ("%s: not a legal variable name", name);
any_failed++;
builtin_error ("`%s': not a valid identifier", name);
assign_error++;
NEXT_VARIABLE ();
}
@ -200,7 +249,14 @@ declare_internal (list, local_var)
not global ones. */
if (variable_context)
make_local_variable (name);
{
#if defined (ARRAY_VARS)
if ((flags_on & att_array) || making_array_special)
make_local_array_variable (name);
else
#endif
make_local_variable (name);
}
/* If we are declaring a function, then complain about it in some way.
We don't let people make functions by saying `typeset -f foo=bar'. */
@ -210,36 +266,35 @@ declare_internal (list, local_var)
if (flags_on & att_function)
{
if (offset)
if (offset) /* declare -f [-rix] foo=bar */
{
builtin_error ("Can't use `-f' to make functions");
return (EXECUTION_FAILURE);
}
else
else /* declare -f [-rx] name [name...] */
{
SHELL_VAR *find_function (), *funvar;
var = find_function (name);
funvar = find_function (name);
if (funvar)
if (var)
{
if (readonly_p (funvar) && (flags_off & att_readonly))
if (readonly_p (var) && (flags_off & att_readonly))
{
builtin_error ("%s: readonly function", name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -[Ff] name [name...] */
if (flags_on == att_function && flags_off == 0)
{
char *result = named_function_string
(name, (COMMAND *)function_cell (funvar), 1);
printf ("%s\n", result);
t = nodefs ? var->name
: named_function_string (name, function_cell (var), 1);
printf ("%s\n", t);
}
else
else /* declare -[fF] -[rx] name [name...] */
{
funvar->attributes |= flags_on;
funvar->attributes &= ~flags_off;
var->attributes |= flags_on;
var->attributes &= ~flags_off;
}
}
else
@ -247,15 +302,21 @@ declare_internal (list, local_var)
NEXT_VARIABLE ();
}
}
else
else /* declare -[airx] name [name...] */
{
SHELL_VAR *var;
var = find_variable (name);
if (!var)
var = bind_variable (name, "");
if (var == 0)
{
#if defined (ARRAY_VARS)
if ((flags_on & att_array) || making_array_special)
var = make_new_array_variable (name);
else
#endif
var = bind_variable (name, "");
}
/* Cannot use declare +r to turn off readonly attribute. */
if (readonly_p (var) && (flags_off & att_readonly))
{
builtin_error ("%s: readonly variable", name);
@ -263,22 +324,55 @@ declare_internal (list, local_var)
NEXT_VARIABLE ();
}
/* Cannot use declare to assign value to readonly variable. */
if (readonly_p (var) && offset)
{
builtin_error ("%s: readonly variable", name);
assign_error++;
NEXT_VARIABLE ();
}
#if defined (ARRAY_VARS)
/* declare -a name=value does not work; declare name=value when
name is already an array does not work. */
if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset)
{
if (value[0] == '(' && strchr (value, ')'))
assigning_array_special = 1;
else
{
builtin_error ("%s: cannot assign to array variables in this way", name);
assign_error++;
NEXT_VARIABLE ();
}
}
/* Cannot use declare +a name to remove an array variable. */
if ((flags_off & att_array) && array_p (var))
{
builtin_error ("%s: cannot destroy array variables in this way", name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -a name makes name an array variable. */
if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
var = convert_var_to_array (var);
#endif /* ARRAY_VARS */
var->attributes |= flags_on;
var->attributes &= ~flags_off;
#if defined (ARRAY_VARS)
if (offset && assigning_array_special)
assign_array_var_from_string (var, value);
else
#endif
if (offset)
{
free (var->value);
if (integer_p (var))
{
long val, evalexp ();
char *itos ();
val = evalexp (value);
var->value = itos ((int)val);
}
else
var->value = savestring (value);
t = make_variable_value (var, value);
FREE (var->value);
var->value = t;
}
}
@ -286,5 +380,8 @@ declare_internal (list, local_var)
NEXT_VARIABLE ();
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}

View file

@ -20,6 +20,12 @@ with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES echo.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../shell.h"
@ -33,6 +39,7 @@ following backslash-escaped characters is turned on:
\a alert (bell)
\b backspace
\c suppress trailing newline
\E escape character
\f form feed
\n new line
\r carriage return
@ -60,109 +67,91 @@ $END
/* Print the words in LIST to standard output. If the first word is
`-n', then don't print a trailing newline. We also support the
echo syntax from Version 9 unix systems. */
echo syntax from Version 9 Unix systems. */
int
echo_builtin (list)
WORD_LIST *list;
{
int display_return = 1, do_v9 = 0;
int display_return, do_v9, i;
char *temp;
#if defined (DEFAULT_ECHO_TO_USG)
/* System V machines already have a /bin/sh with a v9 behaviour. We
give Bash the identical behaviour for these machines so that the
existing system shells won't barf. */
do_v9 = 1;
#else
do_v9 = 0;
#endif /* DEFAULT_ECHO_TO_USG */
while (list && list->word->word[0] == '-')
{
register char *temp;
register int i;
display_return = 1;
for (; list && (temp = list->word->word) && *temp == '-'; list = list->next)
{
/* If it appears that we are handling options, then make sure that
all of the options specified are actually valid. Otherwise, the
string should just be echoed. */
temp = &(list->word->word[1]);
temp++;
for (i = 0; temp[i]; i++)
{
if (strchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
goto just_echo;
break;
}
if (!*temp)
goto just_echo;
/* echo - and echo -<nonopt> both mean to just echo the arguments. */
if (*temp == 0 || temp[i])
break;
/* All of the options in TEMP are valid options to ECHO.
Handle them. */
while (*temp)
while (i = *temp++)
{
if (*temp == 'n')
display_return = 0;
switch (i)
{
case 'n':
display_return = 0;
break;
#if defined (V9_ECHO)
else if (*temp == 'e')
do_v9 = 1;
else if (*temp == 'E')
do_v9 = 0;
case 'e':
do_v9 = 1;
break;
case 'E':
do_v9 = 0;
break;
#endif /* V9_ECHO */
else
goto just_echo;
temp++;
default:
goto just_echo; /* XXX */
}
}
list = list->next;
}
just_echo:
if (list)
while (list)
{
#if defined (V9_ECHO)
if (do_v9)
i = 0;
temp = do_v9 ? ansicstr (list->word->word, STRLEN (list->word->word), &i)
: list->word->word;
if (temp)
{
while (list)
{
register char *s = list->word->word;
register int c;
while (c = *s++)
{
if (c == '\\' && *s)
{
switch (c = *s++)
{
case 'a': c = '\007'; break;
case 'b': c = '\b'; break;
case 'c': display_return = 0; continue;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = (int) 0x0B; break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c -= '0';
if (*s >= '0' && *s <= '7')
c = c * 8 + (*s++ - '0');
if (*s >= '0' && *s <= '7')
c = c * 8 + (*s++ - '0');
break;
case '\\': break;
default: putchar ('\\'); break;
}
}
putchar(c);
}
list = list->next;
if (list)
putchar(' ');
}
printf ("%s", temp);
fflush (stdout); /* Fix for bug in SunOS 5.5 printf(3) */
}
else
#endif /* V9_ECHO */
print_word_list (list, " ");
if (do_v9 && temp)
free (temp);
list = list->next;
if (i)
{
display_return = 0;
break;
}
if (list)
putchar(' ');
}
if (display_return)
printf ("\n");
putchar ('\n');
fflush (stdout);
return (EXECUTION_SUCCESS);
}

View file

@ -23,20 +23,54 @@ $PRODUCES enable.c
$BUILTIN enable
$FUNCTION enable_builtin
$SHORT_DOC enable [-n] [name ...]
$SHORT_DOC enable [-pnds] [-a] [-f filename] [name ...]
Enable and disable builtin shell commands. This allows
you to use a disk command which has the same name as a shell
builtin. If -n is used, the NAMEs become disabled. Otherwise
builtin. If -n is used, the NAMEs become disabled; otherwise
NAMEs are enabled. For example, to use the `test' found on your
path instead of the shell builtin version, you type `enable -n test'.
path instead of the shell builtin version, type `enable -n test'.
On systems supporting dynamic loading, the -f option may be used
to load new builtins from the shared object FILENAME. The -d
option will delete a builtin previously loaded with -f. If no
non-option names are given, or the -p option is supplied, a list
of builtins is printed. The -a option means to print every builtin
with an indication of whether or not it is enabled. The -s option
restricts the output to the Posix.2 `special' builtins. The -n
option displays a list of all disabled builtins.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../builtins.h"
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
static int dyn_load_builtin ();
#endif
#if defined (HAVE_DLCLOSE)
static int dyn_unload_builtin ();
#endif
#define ENABLED 1
#define DISABLED 2
#define SPECIAL 4
#define AFLAG 0x01
#define DFLAG 0x02
#define FFLAG 0x04
#define NFLAG 0x08
#define PFLAG 0x10
#define SFLAG 0x20
static int enable_shell_command ();
static void list_some_builtins ();
@ -44,61 +78,117 @@ static void list_some_builtins ();
/* Enable/disable shell commands present in LIST. If list is not specified,
then print out a list of shell commands showing which are enabled and
which are disabled. */
int
enable_builtin (list)
WORD_LIST *list;
{
int result = 0, any_failed = 0;
int disable_p, all_p;
int result, flags;
int opt, filter;
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
char *filename;
#endif
disable_p = all_p = 0;
result = EXECUTION_SUCCESS;
flags = 0;
while (list && list->word->word && list->word->word[0] == '-')
reset_internal_getopt ();
while ((opt = internal_getopt (list, "adnpsf:")) != -1)
{
char *arg = list->word->word;
list = list->next;
if (ISOPTION (arg, 'n'))
disable_p = 1;
else if (arg[1] == 'a' && (arg[2] == 0 || strcmp (arg + 2, "ll") == 0))
all_p = 1;
else if (ISOPTION (arg, '-'))
break;
else
switch (opt)
{
bad_option (arg);
return (EXECUTION_FAILURE);
case 'a':
flags |= AFLAG;
break;
case 'n':
flags |= NFLAG;
break;
case 'p':
flags |= PFLAG;
break;
case 's':
flags |= SFLAG;
break;
case 'f':
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
flags |= FFLAG;
filename = list_optarg;
break;
#else
builtin_error ("dynamic loading not available");
return (EX_USAGE);
#endif
#if defined (HAVE_DLCLOSE)
case 'd':
flags |= DFLAG;
break;
#else
builtin_error ("dynamic loading not available");
return (EX_USAGE);
#endif /* HAVE_DLCLOSE */
default:
builtin_usage ();
return (EX_USAGE);
}
}
if (!list)
{
int filter;
list = loptend;
if (all_p)
filter = ENABLED | DISABLED;
else if (disable_p)
filter = DISABLED;
else
filter = ENABLED;
#if defined (RESTRICTED_SHELL)
/* Restricted shells cannot load new builtins. */
if (restricted && (flags & (FFLAG|DFLAG)))
{
builtin_error ("restricted");
return (EXECUTION_FAILURE);
}
#endif
if (list == 0 || (flags & PFLAG))
{
filter = (flags & AFLAG) ? (ENABLED | DISABLED)
: (flags & NFLAG) ? DISABLED : ENABLED;
if (flags & SFLAG)
filter |= SPECIAL;
list_some_builtins (filter);
}
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
else if (flags & FFLAG)
{
filter = (flags & NFLAG) ? DISABLED : ENABLED;
if (flags & SFLAG)
filter |= SPECIAL;
result = dyn_load_builtin (list, filter, filename);
}
#endif
#if defined (HAVE_DLCLOSE)
else if (flags & DFLAG)
{
while (list)
{
opt = dyn_unload_builtin (list->word->word);
if (opt == EXECUTION_FAILURE)
result = EXECUTION_FAILURE;
list = list->next;
}
}
#endif
else
{
while (list)
{
result = enable_shell_command (list->word->word, disable_p);
opt = enable_shell_command (list->word->word, flags & NFLAG);
if (!result)
if (opt == EXECUTION_FAILURE)
{
builtin_error ("%s: not a shell builtin", list->word->word);
any_failed++;
result = EXECUTION_FAILURE;
}
list = list->next;
}
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
return (result);
}
/* List some builtins.
@ -111,19 +201,18 @@ list_some_builtins (filter)
for (i = 0; i < num_shell_builtins; i++)
{
if (!shell_builtins[i].function)
if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
continue;
if ((filter & ENABLED) &&
(shell_builtins[i].flags & BUILTIN_ENABLED))
{
printf ("enable %s\n", shell_builtins[i].name);
}
if ((filter & SPECIAL) &&
(shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
continue;
if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
printf ("enable %s\n", shell_builtins[i].name);
else if ((filter & DISABLED) &&
((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
{
printf ("enable -n %s\n", shell_builtins[i].name);
}
printf ("enable -n %s\n", shell_builtins[i].name);
}
}
@ -134,23 +223,202 @@ enable_shell_command (name, disable_p)
char *name;
int disable_p;
{
register int i;
int found = 0;
struct builtin *b;
for (i = 0; i < num_shell_builtins; i++)
{
if (!shell_builtins[i].function)
continue;
b = builtin_address_internal (name, 1);
if (b == 0)
return (EXECUTION_FAILURE);
if (STREQ (name, shell_builtins[i].name))
{
found++;
if (disable_p)
b->flags &= ~BUILTIN_ENABLED;
else
b->flags |= BUILTIN_ENABLED;
if (disable_p)
shell_builtins[i].flags &= ~BUILTIN_ENABLED;
else
shell_builtins[i].flags |= BUILTIN_ENABLED;
}
}
return (found);
return (EXECUTION_SUCCESS);
}
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
#include <dlfcn.h>
static int
dyn_load_builtin (list, flags, filename)
WORD_LIST *list;
int flags;
char *filename;
{
WORD_LIST *l;
void *handle;
int total, size, new, replaced;
char *struct_name, *name;
struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
if (list == 0)
return (EXECUTION_FAILURE);
#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif
#if defined (_AIX)
handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
#else
handle = dlopen (filename, RTLD_LAZY);
#endif /* !_AIX */
if (handle == 0)
{
builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
return (EXECUTION_FAILURE);
}
for (new = 0, l = list; l; l = l->next, new++)
;
new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
/* For each new builtin in the shared object, find it and its describing
structure. If this is overwriting an existing builtin, do so, otherwise
save the loaded struct for creating the new list of builtins. */
for (replaced = new = 0; list; list = list->next)
{
name = list->word->word;
size = strlen (name);
struct_name = xmalloc (size + 8);
strcpy (struct_name, name);
strcpy (struct_name + size, "_struct");
b = (struct builtin *)dlsym (handle, struct_name);
if (b == 0)
{
builtin_error ("cannot find %s in shared object %s: %s", struct_name,
filename, dlerror ());
free (struct_name);
continue;
}
free (struct_name);
b->flags &= ~STATIC_BUILTIN;
if (flags & SPECIAL)
b->flags |= SPECIAL_BUILTIN;
b->handle = handle;
if (old_builtin = builtin_address_internal (name, 1))
{
replaced++;
FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
}
else
new_builtins[new++] = b;
}
if (replaced == 0 && new == 0)
{
free (new_builtins);
dlclose (handle);
return (EXECUTION_FAILURE);
}
if (new)
{
total = num_shell_builtins + new;
size = (total + 1) * sizeof (struct builtin);
new_shell_builtins = (struct builtin *)xmalloc (size);
FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
num_shell_builtins * sizeof (struct builtin));
for (replaced = 0; replaced < new; replaced++)
FASTCOPY ((char *)new_builtins[replaced],
(char *)&new_shell_builtins[num_shell_builtins + replaced],
sizeof (struct builtin));
new_shell_builtins[total].name = (char *)0;
new_shell_builtins[total].function = (Function *)0;
new_shell_builtins[total].flags = 0;
if (shell_builtins != static_shell_builtins)
free (shell_builtins);
shell_builtins = new_shell_builtins;
num_shell_builtins = total;
initialize_shell_builtins ();
}
free (new_builtins);
return (EXECUTION_SUCCESS);
}
#endif
#if defined (HAVE_DLCLOSE)
static void
delete_builtin (b)
struct builtin *b;
{
int ind, size;
struct builtin *new_shell_builtins;
/* XXX - funky pointer arithmetic - XXX */
ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
size = num_shell_builtins * sizeof (struct builtin);
new_shell_builtins = (struct builtin *)xmalloc (size);
/* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
if (ind)
FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
ind * sizeof (struct builtin));
/* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
new_shell_builtins, starting at ind. */
FASTCOPY ((char *)(&shell_builtins[ind+1]),
(char *)(&new_shell_builtins[ind]),
(num_shell_builtins - ind) * sizeof (struct builtin));
if (shell_builtins != static_shell_builtins)
free (shell_builtins);
/* The result is still sorted. */
num_shell_builtins--;
shell_builtins = new_shell_builtins;
}
static int
dyn_unload_builtin (name)
char *name;
{
struct builtin *b;
void *handle;
int ref, i;
b = builtin_address_internal (name, 1);
if (b == 0)
{
builtin_error ("%s: not a shell builtin", name);
return (EXECUTION_FAILURE);
}
if (b->flags & STATIC_BUILTIN)
{
builtin_error ("%s: not dynamically loaded", name);
return (EXECUTION_FAILURE);
}
handle = (void *)b->handle;
for (ref = i = 0; i < num_shell_builtins; i++)
{
if (shell_builtins[i].handle == b->handle)
ref++;
}
/* Don't remove the shared object unless the reference count of builtins
using it drops to zero. */
if (ref == 1 && dlclose (handle) != 0)
{
builtin_error ("cannot delete %s: %s", name, dlerror ());
return (EXECUTION_FAILURE);
}
/* Now remove this entry from the builtin table and reinitialize. */
delete_builtin (b);
return (EXECUTION_SUCCESS);
}
#endif

View file

@ -27,19 +27,24 @@ $SHORT_DOC eval [arg ...]
Read ARGs as input to the shell and execute the resulting command(s).
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include "../shell.h"
#include "bashgetopt.h"
extern int parse_and_execute ();
/* Parse the string that these words make, and execute the command found. */
int
eval_builtin (list)
WORD_LIST *list;
{
int result;
if (no_options (list))
return (EX_USAGE);
/* Note that parse_and_execute () frees the string it is passed. */
if (list)
result = parse_and_execute (string_list (list), "eval", -1);
else
result = EXECUTION_SUCCESS;
return (result);
return (list ? parse_and_execute (string_list (list), "eval", -1) : EXECUTION_SUCCESS);
}

211
builtins/evalfile.c Normal file
View file

@ -0,0 +1,211 @@
/* Copyright (C) 1996 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 1, 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; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <sys/types.h>
#include "../posixstat.h"
#include "../filecntl.h"
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
/* Flags for _evalfile() */
#define FEVAL_ENOENTOK 0x001
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
#define FEVAL_LONGJMP 0x010
extern int interactive, interactive_shell, posixly_correct;
extern int indirection_level, startup_state, subshell_environment;
extern int return_catch_flag, return_catch_value;
extern int last_command_exit_value;
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
static int
_evalfile (filename, flags)
char *filename;
int flags;
{
volatile int old_interactive;
procenv_t old_return_catch;
int return_val, fd, result;
char *string;
struct stat finfo;
VFunction *errfunc;
fd = open (filename, O_RDONLY);
if (fd < 0 || (fstat (fd, &finfo) == -1))
{
file_error_and_exit:
if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
file_error (filename);
if (flags & FEVAL_LONGJMP)
{
last_command_exit_value = 1;
jump_to_top_level (EXITPROG);
}
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
: ((errno == ENOENT) ? 0 : -1));
}
errfunc = (VFunction *)((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
if (S_ISDIR (finfo.st_mode))
{
(*errfunc) ("%s: is a directory", filename);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
else if (S_ISREG (finfo.st_mode) == 0)
{
(*errfunc) ("%s: not a regular file", filename);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
string = xmalloc (1 + (int)finfo.st_size);
result = read (fd, string, finfo.st_size);
string[result] = '\0';
return_val = errno;
close (fd);
errno = return_val;
if (result != (int)finfo.st_size)
{
free (string);
goto file_error_and_exit;
}
if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result))
{
free (string);
(*errfunc) ("%s: cannot execute binary file", filename);
return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
}
if (flags & FEVAL_UNWINDPROT)
{
begin_unwind_frame ("_evalfile");
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
if (flags & FEVAL_NONINT)
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
}
else
{
COPY_PROCENV (return_catch, old_return_catch);
if (flags & FEVAL_NONINT)
old_interactive = interactive;
}
if (flags & FEVAL_NONINT)
interactive = 0;
return_catch_flag++;
sourcelevel++;
if (flags & FEVAL_BUILTIN)
result = EXECUTION_SUCCESS;
return_val = setjmp (return_catch);
/* If `return' was seen outside of a function, but in the script, then
force parse_and_execute () to clean up. */
if (return_val)
{
parse_and_execute_cleanup ();
result = return_catch_value;
}
else
result = parse_and_execute (string, filename, -1);
if (flags & FEVAL_UNWINDPROT)
run_unwind_frame ("_evalfile");
else
{
if (flags & FEVAL_NONINT)
interactive = old_interactive;
return_catch_flag--;
sourcelevel--;
COPY_PROCENV (old_return_catch, return_catch);
}
return ((flags & FEVAL_BUILTIN) ? result : 1);
}
int
maybe_execute_file (fname, force_noninteractive)
char *fname;
int force_noninteractive;
{
char *filename;
int result, flags;
filename = bash_tilde_expand (fname);
flags = FEVAL_ENOENTOK;
if (force_noninteractive)
flags |= FEVAL_NONINT;
result = _evalfile (filename, flags);
free (filename);
return result;
}
int
source_file (filename)
char *filename;
{
int flags;
flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
/* POSIX shells exit if non-interactive and file error. */
if (posixly_correct && !interactive_shell)
flags |= FEVAL_LONGJMP;
return (_evalfile (filename, flags));
}

228
builtins/evalstring.c Normal file
View file

@ -0,0 +1,228 @@
/* Copyright (C) 1996 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 1, 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; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <signal.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include "common.h"
extern int interactive, interactive_shell;
extern int indirection_level, startup_state, subshell_environment;
extern int line_number;
extern int last_command_exit_value;
extern int running_trap;
extern COMMAND *global_command;
int parse_and_execute_level = 0;
/* How to force parse_and_execute () to clean up after itself. */
void
parse_and_execute_cleanup ()
{
if (running_trap)
{
run_trap_cleanup (running_trap - 1);
unfreeze_jobs_list ();
}
run_unwind_frame ("parse_and_execute_top");
}
/* Parse and execute the commands in STRING. Returns whatever
execute_command () returns. This frees STRING. INTERACT is
the new value for `interactive' while the commands are being
executed. A value of -1 means don't change it. */
int
parse_and_execute (string, from_file, interact)
char *string;
char *from_file;
int interact;
{
int code;
volatile int should_jump_to_top_level, last_result;
char *orig_string;
COMMAND *volatile command;
orig_string = string;
/* Unwind protect this invocation of parse_and_execute (). */
begin_unwind_frame ("parse_and_execute_top");
unwind_protect_int (parse_and_execute_level);
unwind_protect_jmp_buf (top_level);
unwind_protect_int (indirection_level);
unwind_protect_int (line_number);
if (interact != -1 && interactive != interact)
unwind_protect_int (interactive);
#if defined (HISTORY)
if (interactive_shell)
{
unwind_protect_int (remember_on_history);
# if defined (BANG_HISTORY)
unwind_protect_int (history_expansion_inhibited);
# endif /* BANG_HISTORY */
}
#endif /* HISTORY */
add_unwind_protect (pop_stream, (char *)NULL);
if (orig_string)
add_unwind_protect (xfree, orig_string);
end_unwind_frame ();
parse_and_execute_level++;
push_stream (1); /* reset the line number */
indirection_level++;
if (interact != -1)
interactive = interact;
#if defined (HISTORY)
bash_history_disable ();
#endif /* HISTORY */
code = should_jump_to_top_level = 0;
last_result = EXECUTION_SUCCESS;
command = (COMMAND *)NULL;
with_input_from_string (string, from_file);
while (*(bash_input.location.string))
{
if (interrupt_state)
{
last_result = EXECUTION_FAILURE;
break;
}
/* Provide a location for functions which `longjmp (top_level)' to
jump to. This prevents errors in substitution from restarting
the reader loop directly, for example. */
code = setjmp (top_level);
if (code)
{
should_jump_to_top_level = 0;
switch (code)
{
case FORCE_EOF:
case EXITPROG:
run_unwind_frame ("pe_dispose");
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
should_jump_to_top_level = 1;
goto out;
case DISCARD:
run_unwind_frame ("pe_dispose");
last_command_exit_value = 1; /* XXX */
if (subshell_environment)
{
should_jump_to_top_level = 1;
goto out;
}
else
{
dispose_command (command); /* XXX */
continue;
}
default:
programming_error ("parse_and_execute: bad jump: code %d", code);
break;
}
}
if (parse_command () == 0)
{
if (interactive_shell == 0 && read_but_dont_execute)
{
last_result = EXECUTION_SUCCESS;
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else if (command = global_command)
{
struct fd_bitmap *bitmap;
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
global_command = (COMMAND *)NULL;
#if defined (ONESHOT)
if (startup_state == 2 && *bash_input.location.string == '\0' &&
command->type == cm_simple && !command->redirects &&
!command->value.Simple->redirects)
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
#endif /* ONESHOT */
last_result = execute_command_internal
(command, 0, NO_PIPE, NO_PIPE, bitmap);
dispose_command (command);
dispose_fd_bitmap (bitmap);
discard_unwind_frame ("pe_dispose");
}
}
else
{
last_result = EXECUTION_FAILURE;
/* Since we are shell compatible, syntax errors in a script
abort the execution of the script. Right? */
break;
}
}
out:
run_unwind_frame ("parse_and_execute_top");
if (interrupt_state && parse_and_execute_level == 0)
{
/* An interrupt during non-interactive execution in an
interactive shell (e.g. via $PROMPT_COMMAND) should
not cause the shell to exit. */
interactive = interactive_shell;
throw_to_top_level ();
}
if (should_jump_to_top_level)
jump_to_top_level (code);
return (last_result);
}

View file

@ -23,141 +23,190 @@ $PRODUCES exec.c
$BUILTIN exec
$FUNCTION exec_builtin
$SHORT_DOC exec [ [-] file [redirection ...]]
$SHORT_DOC exec [-cl] [-a name] file [redirection ...]
Exec FILE, replacing this shell with the specified program.
If FILE is not specified, the redirections take effect in this
shell. If the first argument is `-', then place a dash in the
zeroth arg passed to FILE. If the file cannot be exec'ed and
the shell is not interactive, then the shell exits, unless the
shell variable "no_exit_on_failed_exec" exists.
shell. If the first argument is `-l', then place a dash in the
zeroth arg passed to FILE, as login does. If the `-c' option
is supplied, FILE is executed with a null environment. The `-a'
option means to make set argv[0] of the executed process to NAME.
If the file cannot be executed and the shell is not interactive,
then the shell exits, unless the shell option `execfail' is set.
$END
#include "../shell.h"
#include <config.h>
#include <sys/types.h>
#include "../posixstat.h"
#include <signal.h>
#include <errno.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../execute_cmd.h"
#include "common.h"
#if defined (JOB_CONTROL)
# include "../jobs.h"
#endif
#include "../flags.h"
#include "../trap.h"
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include "common.h"
#include "bashgetopt.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int interactive, subshell_environment;
extern REDIRECT *redirection_undo_list;
int no_exit_on_failed_exec;
/* If the user wants this to look like a login shell, then
prepend a `-' onto NAME and return the new name. */
static char *
mkdashname (name)
char *name;
{
char *ret;
ret = xmalloc (2 + strlen (name));
ret[0] = '-';
strcpy (ret + 1, name);
return ret;
}
int
exec_builtin (list)
WORD_LIST *list;
{
int exit_value = EXECUTION_FAILURE;
int cleanenv, login, opt;
char *argv0, *command, **args, **env, *newname;
maybe_make_export_env ();
cleanenv = login = 0;
argv0 = (char *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "cla:")) != -1)
{
switch (opt)
{
case 'c':
cleanenv = 1;
break;
case 'l':
login = 1;
break;
case 'a':
argv0 = list_optarg;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* First, let the redirections remain. */
dispose_redirects (redirection_undo_list);
redirection_undo_list = (REDIRECT *)NULL;
if (!list)
if (list == 0)
return (EXECUTION_SUCCESS);
else
{
/* Otherwise, execve the new command with args. */
char *command, **args;
int dash_name = 0;
if (list->word->word[0] == '-' && !list->word->word[1])
{
/* The user would like to exec this command as if it was a
login command. Do so. */
list = list->next;
dash_name++;
}
if (!list)
return (EXECUTION_SUCCESS);
#if defined (RESTRICTED_SHELL)
if (restricted)
{
builtin_error ("restricted");
return (EXECUTION_FAILURE);
}
if (restricted)
{
builtin_error ("restricted");
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
args = make_word_array (list);
args = word_list_to_argv (list, 1, 0, (int *)NULL);
/* A command with a slash anywhere in its name is not looked up in
the search path. */
if (absolute_program (args[0]))
command = args[0];
else
command = find_user_command (args[0]);
if (!command)
{
builtin_error ("%s: not found", args[0]);
exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
goto failed_exec;
}
/* A command with a slash anywhere in its name is not looked up in $PATH. */
command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
command = full_pathname (command);
/* If the user wants this to look like a login shell, then
prepend a `-' onto the first argument (argv[0]). */
if (dash_name)
{
char *new_name = xmalloc (2 + strlen (args[0]));
new_name[0] = '-';
strcpy (new_name + 1, args[0]);
free (args[0]);
args[0] = new_name;
}
if (command == 0)
{
builtin_error ("%s: not found", args[0]);
exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
goto failed_exec;
}
/* Decrement SHLVL by 1 so a new shell started here has the same value,
preserving the appearance. After we do that, we need to change the
exported environment to include the new value. */
adjust_shell_level (-1);
command = full_pathname (command);
if (argv0)
{
free (args[0]);
args[0] = login ? mkdashname (argv0) : savestring (argv0);
}
else if (login)
{
newname = mkdashname (args[0]);
free (args[0]);
args[0] = newname;
}
/* Decrement SHLVL by 1 so a new shell started here has the same value,
preserving the appearance. After we do that, we need to change the
exported environment to include the new value. */
if (cleanenv == 0)
adjust_shell_level (-1);
if (cleanenv)
env = (char **)NULL;
else
{
maybe_make_export_env ();
env = export_env;
}
#if defined (HISTORY)
maybe_save_shell_history ();
maybe_save_shell_history ();
#endif /* HISTORY */
restore_original_signals ();
restore_original_signals ();
#if defined (JOB_CONTROL)
if (subshell_environment == 0)
end_job_control ();
if (subshell_environment == 0)
end_job_control ();
#endif /* JOB_CONTROL */
shell_execve (command, args, export_env);
shell_execve (command, args, env);
if (cleanenv == 0)
adjust_shell_level (1);
adjust_shell_level (1);
if (!executable_file (command))
{
builtin_error ("%s: cannot execute: %s", command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
}
else
file_error (command);
failed_exec:
if (command)
free (command);
if (subshell_environment ||
(!interactive && !find_variable ("no_exit_on_failed_exec")))
exit (exit_value);
initialize_traps ();
reinitialize_signals ();
#if defined (JOB_CONTROL)
restart_job_control ();
#endif /* JOB_CONTROL */
return (exit_value);
if (executable_file (command) == 0)
{
builtin_error ("%s: cannot execute: %s", command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
}
else
file_error (command);
failed_exec:
if (command)
free (command);
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
exit_shell (exit_value);
initialize_traps ();
reinitialize_signals ();
#if defined (JOB_CONTROL)
restart_job_control ();
#endif /* JOB_CONTROL */
return (exit_value);
}

View file

@ -1,5 +1,5 @@
This file is exit.def, from which is created exit.c.
It implements the builtins "exit" and "logout" in Bash.
It implements the builtins "exit", and "logout" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
@ -28,18 +28,26 @@ Exit the shell with a status of N. If N is omitted, the exit status
is that of the last command executed.
$END
#include <stdio.h>
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "../jobs.h"
#include "common.h"
#include "builtext.h" /* for jobs_builtin */
extern int interactive, login_shell;
extern int last_command_exit_value;
static int exit_or_logout ();
static int sourced_logout = 0;
static int sourced_logout;
int
exit_builtin (list)
@ -65,9 +73,9 @@ int
logout_builtin (list)
WORD_LIST *list;
{
if (!login_shell && interactive)
if (login_shell == 0 && interactive)
{
builtin_error ("Not login shell: use `exit'");
builtin_error ("not login shell: use `exit'");
return (EXECUTION_FAILURE);
}
else
@ -87,7 +95,7 @@ exit_or_logout (list)
#if defined (JOB_CONTROL)
int exit_immediate_okay;
exit_immediate_okay = (!interactive ||
exit_immediate_okay = (interactive == 0 ||
last_shell_builtin == exit_builtin ||
last_shell_builtin == logout_builtin ||
last_shell_builtin == jobs_builtin);
@ -97,7 +105,7 @@ exit_or_logout (list)
{
register int i;
for (i = 0; i < job_slots; i++)
if (jobs[i] && (jobs[i]->state == JSTOPPED))
if (jobs[i] && STOPPED (i))
{
fprintf (stderr, "There are stopped jobs.\n");
@ -113,17 +121,20 @@ exit_or_logout (list)
/* Get return value if present. This means that you can type
`logout 5' to a shell, and it returns 5. */
if (list)
exit_value = get_numeric_arg (list);
else
exit_value = last_command_exit_value;
exit_value = list ? get_numeric_arg (list) : last_command_exit_value;
/* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
if (login_shell && sourced_logout++ == 0)
maybe_execute_file ("~/.bash_logout", 1);
{
maybe_execute_file ("~/.bash_logout", 1);
#ifdef SYS_BASH_LOGOUT
maybe_execute_file (SYS_BASH_LOGOUT, 1);
#endif
}
last_command_exit_value = exit_value;
/* Exit the program. */
longjmp (top_level, EXITPROG);
jump_to_top_level (EXITPROG);
/*NOTREACHED*/
}

View file

@ -46,23 +46,32 @@ runs the last command beginning with `cc' and typing `r' re-executes
the last command.
$END
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include <config.h>
#if defined (HISTORY)
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "bashtypes.h"
#include "posixstat.h"
#include <sys/file.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include <errno.h>
#include "../shell.h"
#include "../builtins.h"
#include "../flags.h"
#include "../maxpath.h"
#include "../bashhist.h"
#include <readline/history.h>
#include "bashgetopt.h"
#include "common.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
@ -100,8 +109,8 @@ extern int unlink ();
Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
*/
static char *fc_dosubs (), *fc_replace (), *fc_gethist (), *fc_readline ();
static int fc_gethnum ();
static char *fc_dosubs (), *fc_gethist (), *fc_readline ();
static int fc_gethnum (), fc_number ();
static void fc_replhist (), fc_addhist ();
/* Data structure describing a list of global replacements to perform. */
@ -111,8 +120,6 @@ typedef struct repl {
char *rep;
} REPL;
#define USAGE "usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [command]"
/* Accessors for HIST_ENTRY lists that are called HLIST. */
#define histline(i) (hlist[(i)]->line)
#define histdata(i) (hlist[(i)]->data)
@ -143,61 +150,51 @@ fc_builtin (list)
int numbering, reverse, listing, execute;
int histbeg, histend, last_hist, retval, first, opt;
FILE *stream;
REPL *rlist = (REPL *) NULL, *rl;
char *ename = NULL, *command, *newcom, *line;
REPL *rlist, *rl;
char *ename, *command, *newcom, *line;
HIST_ENTRY **hlist;
char fn[MAXPATHLEN];
char fn[64];
numbering = 1;
reverse = listing = execute = 0;
ename = (char *)NULL;
/* Parse out the options and set which of the two forms we're in. */
while (list && *list->word->word == '-')
reset_internal_getopt ();
lcurrent = list; /* XXX */
while (fc_number (loptend = lcurrent) == 0 &&
(opt = internal_getopt (list, ":e:lnrs")) != -1)
{
register char *s = &((list->word->word)[1]);
if (!isletter (*s))
break;
while (opt = *s++)
switch (opt)
{
switch (opt)
{
case 'n':
numbering = 0;
break;
case 'n':
numbering = 0;
break;
case 'l':
listing = 1;
break;
case 'l':
listing = 1;
break;
case 'r':
reverse = 1;
break;
case 'r':
reverse = 1;
break;
case 's':
execute = 1;
break;
case 's':
execute = 1;
break;
case 'e':
list = list->next;
if (list == NULL)
{
builtin_error (USAGE);
return (EX_USAGE);
}
ename = list->word->word;
break;
case 'e':
ename = list_optarg;
break;
default:
builtin_error (USAGE);
return (EX_USAGE);
}
default:
builtin_usage ();
return (EX_USAGE);
}
list = list->next;
}
list = loptend;
if (ename && (*ename == '-') && (ename[1] == '\0'))
execute = 1;
@ -205,6 +202,7 @@ fc_builtin (list)
substitutions). */
if (execute)
{
rlist = (REPL *)NULL;
while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
{
*sep++ = '\0';
@ -227,16 +225,13 @@ fc_builtin (list)
to get the replacements in the proper order. */
if (rlist && rlist->next)
rlist = (REPL *) reverse_list ((GENERIC_LIST *) rlist);
rlist = (REPL *)reverse_list ((GENERIC_LIST *) rlist);
hlist = history_list ();
/* If we still have something in list, it is a command spec.
Otherwise, we use the most recent command in time. */
if (list)
command = fc_gethist (list->word->word, hlist);
else
command = fc_gethist ((char *) NULL, hlist);
command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
if (command == NULL)
{
@ -255,8 +250,8 @@ fc_builtin (list)
command = newcom;
}
printf ("%s\n", command);
fc_replhist (command); /* replace `fc -e -' with command */
fprintf (stderr, "%s\n", command);
fc_replhist (command); /* replace `fc -s' with command */
return (parse_and_execute (command, "fc", -1));
}
@ -283,12 +278,7 @@ fc_builtin (list)
if (list)
histend = fc_gethnum (list->word->word, hlist);
else
{
if (listing)
histend = last_hist;
else
histend = histbeg;
}
histend = listing ? last_hist : histbeg;
}
else
{
@ -301,10 +291,8 @@ fc_builtin (list)
histbeg = 0;
}
else
{
/* For editing, it is the last history command. */
histbeg = histend = last_hist;
}
/* For editing, it is the last history command. */
histbeg = histend = last_hist;
}
/* We print error messages for line specifications out of range. */
@ -317,10 +305,10 @@ fc_builtin (list)
if (histend < histbeg)
{
int t = histend;
i = histend;
histend = histbeg;
histbeg = t;
histbeg = i;
reverse = 1;
}
@ -329,40 +317,25 @@ fc_builtin (list)
else
{
numbering = 0;
sprintf (fn, "/tmp/bash%d", (int)time ((long *) 0) + (int)getpid ());
sprintf (fn, "/tmp/bash%d", (int)time ((time_t *) 0) + (int)getpid ());
stream = fopen (fn, "w");
if (!stream)
if (stream == 0)
{
builtin_error ("cannot open temp file %s", fn);
return (EXECUTION_FAILURE);
}
}
if (!reverse)
for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
{
for (i = histbeg; i <= histend; i++)
{
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
fprintf (stream, "%s\n", histline (i));
}
}
else
{
for (i = histend; i >= histbeg; i--)
{
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
fprintf (stream, "%s\n", histline (i));
}
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
fprintf (stream, "%s\n", histline (i));
}
if (listing)
@ -381,7 +354,12 @@ fc_builtin (list)
command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
}
parse_and_execute (command, "fc", -1);
retval = parse_and_execute (command, "fc", -1);
if (retval != EXECUTION_SUCCESS)
{
unlink (fn);
return (EXECUTION_FAILURE);
}
/* Now reopen the file and execute the edited commands. */
@ -435,6 +413,21 @@ fc_builtin (list)
return (retval);
}
/* Return 1 if LIST->word->word is a legal number for fc's use. */
static int
fc_number (list)
WORD_LIST *list;
{
char *s;
if (list == 0)
return 0;
s = list->word->word;
if (*s == '-')
s++;
return (legal_number (s, (long *)NULL));
}
/* Return an absolute index into HLIST which corresponds to COMMAND. If
COMMAND is a number, then it was specified in relative terms. If it
is a string, then it is the start of a command line present in HLIST. */
@ -572,58 +565,18 @@ fc_dosubs (command, subs)
char *command;
REPL *subs;
{
register char *new = savestring (command);
register char *new, *t;
register REPL *r;
for (r = subs; r; r = r->next)
for (new = savestring (command), r = subs; r; r = r->next)
{
register char *t;
t = fc_replace (r->pat, r->rep, new);
t = strsub (new, r->pat, r->rep, 1);
free (new);
new = t;
}
return (new);
}
/* Replace the occurrences of PAT with REP in COMMAND.
This returns a new string; the caller should free it. */
static char *
fc_replace (pat, rep, command)
char *pat, *rep, *command;
{
register int i;
int patlen, replen, templen;
char *new, *temp;
patlen = strlen (pat);
replen = strlen (rep);
temp = savestring (command);
templen = strlen (temp);
i = 0;
for (; (i + patlen) <= templen; i++)
{
if (STREQN (temp + i, pat, patlen))
{
new = (char *) xmalloc (1 + (replen - patlen) + templen);
strncpy (new, temp, i);
strncpy (new + i, rep, replen);
strncpy (new + i + replen,
temp + i + patlen, templen - (i + patlen));
new[templen + (replen - patlen)] = '\0'; /* just in case */
free (temp);
temp = new;
i += replen;
templen = strlen (temp);
}
}
return (temp);
}
/* Use `command' to replace the last entry in the history list, which,
by this time, is `fc blah...'. The intent is that the new command
become the history entry, and that `fc' should never appear in the
@ -634,10 +587,9 @@ fc_replhist (command)
{
register int i;
HIST_ENTRY **hlist, *histent, *discard;
char *data;
int n;
if (!command || !*command)
if (command == 0 || *command == '\0')
return;
hlist = history_list ();
@ -665,8 +617,7 @@ fc_replhist (command)
discard = remove_history (i);
if (discard)
{
if (discard->line)
free (discard->line);
FREE (discard->line);
free ((char *) discard);
}
maybe_add_history (command); /* Obeys HISTCONTROL setting. */

View file

@ -30,10 +30,18 @@ JOB_SPEC is not present, the shell's notion of the current job is
used.
$END
#include <config.h>
#include <sys/types.h>
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "../jobs.h"
#include "common.h"
#if defined (JOB_CONTROL)
extern char *this_command_name;
@ -45,23 +53,23 @@ int
fg_builtin (list)
WORD_LIST *list;
{
int fg_bit = 1;
register WORD_LIST *t = list;
int fg_bit;
register WORD_LIST *t;
if (!job_control)
if (job_control == 0)
{
builtin_error ("no job control");
return (EXECUTION_FAILURE);
}
if (no_options (list))
return (EX_USAGE);
/* If the last arg on the line is '&', then start this job in the
background. Else, fg the job. */
while (t && t->next)
t = t->next;
if (t && t->word->word[0] == '&' && !t->word->word[1])
fg_bit = 0;
for (t = list; t && t->next; t = t->next)
;
fg_bit = (t && t->word->word[0] == '&' && t->word->word[1] == '\0') == 0;
return (fg_bg (list, fg_bit));
}
@ -82,12 +90,15 @@ int
bg_builtin (list)
WORD_LIST *list;
{
if (!job_control)
if (job_control == 0)
{
builtin_error ("no job control");
return (EXECUTION_FAILURE);
}
if (no_options (list))
return (EX_USAGE);
return (fg_bg (list, 0));
}
@ -98,27 +109,27 @@ fg_bg (list, foreground)
int foreground;
{
sigset_t set, oset;
int job, status = EXECUTION_SUCCESS, old_async_pid;
int job, status, old_async_pid;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if (job < 0 || job >= job_slots || !jobs[job])
if (job < 0 || job >= job_slots || jobs[job] == 0)
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list ? list->word->word : "");
builtin_error ("%s: no such job", list ? list->word->word : "current");
goto failure;
}
/* Or if jobs[job]->pgrp == shell_pgrp. */
if (!(jobs[job]->flags & J_JOBCONTROL))
if (IS_JOBCONTROL (job) == 0)
{
builtin_error ("job %%%d started without job control", job + 1);
goto failure;
}
if (!foreground)
if (foreground == 0)
{
old_async_pid = last_asynchronous_pid;
last_asynchronous_pid = jobs[job]->pgrp; /* As per Posix.2 5.4.2 */
@ -134,7 +145,7 @@ fg_bg (list, foreground)
}
else
{
if (!foreground)
if (foreground == 0)
last_asynchronous_pid = old_async_pid;
failure:

View file

@ -17,6 +17,12 @@
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../memalloc.h"
#include "../shell.h"
@ -66,6 +72,9 @@ int sh_opterr = 1;
int sh_optopt = '?';
/* Set to 1 when we see an illegal option; public so getopts can reset it. */
int sh_badopt = 0;
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
@ -102,7 +111,6 @@ sh_getopt (argc, argv, optstring)
char *const *argv;
const char *optstring;
{
int option_index;
char c, *temp;
sh_optarg = 0;
@ -124,10 +132,18 @@ sh_getopt (argc, argv, optstring)
nextchar = (char *)NULL;
}
/* Do the increment of `sh_optind' we deferred because the last option
was illegal. */
if (sh_badopt && (nextchar == 0 || *nextchar == '\0'))
{
sh_badopt = 0;
sh_optind++;
nextchar = (char *)NULL;
}
if (nextchar == 0 || *nextchar == '\0')
{
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
/* If we have done all the ARGV-elements, stop the scan. */
if (sh_optind == argc)
return EOF;
@ -158,16 +174,11 @@ sh_getopt (argc, argv, optstring)
c = *nextchar++; sh_charindex++;
temp = strchr (optstring, c);
/* Increment `sh_optind' when we start to process its last character. */
if (nextchar == 0 || *nextchar == '\0')
{
sh_optind++;
nextchar = (char *)NULL;
}
sh_optopt = c;
if (temp == NULL || c == ':')
/* If the option is illegal, return an error, but defer updating sh_optind
until the next call so $OPTIND is correct. */
if (sh_badopt = (temp == NULL || c == ':'))
{
if (sh_opterr)
BADOPT (c);
@ -175,6 +186,13 @@ sh_getopt (argc, argv, optstring)
return '?';
}
/* Increment `sh_optind' when we start to process its last character. */
if (nextchar == 0 || *nextchar == '\0')
{
sh_optind++;
nextchar = (char *)NULL;
}
if (temp[1] == ':')
{
if (nextchar && *nextchar)
@ -191,6 +209,7 @@ sh_getopt (argc, argv, optstring)
NEEDARG (c);
sh_optopt = c;
sh_optarg = ""; /* Needed by getopts. */
c = (optstring[0] == ':') ? ':' : '?';
}
else

View file

@ -51,6 +51,9 @@ extern int sh_opterr;
extern int sh_optopt;
/* Set to 1 when an unrecognized option is encountered. */
extern int sh_badopt;
extern int sh_getopt ();
extern void sh_getopt_restore_state ();

View file

@ -22,7 +22,6 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES getopts.c
$BUILTIN getopts
$DEPENDS_ON GETOPTS_BUILTIN
$FUNCTION getopts_builtin
$SHORT_DOC getopts optstring name [arg]
Getopts is used by shell procedures to parse positional parameters.
@ -57,22 +56,24 @@ Getopts normally parses the positional parameters ($0 - $9), but if
more arguments are given, they are parsed instead.
$END
#include <config.h>
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#if defined (GETOPTS_BUILTIN)
#include "common.h"
#include "bashgetopt.h"
#include "getopt.h"
#define G_EOF (-1)
#define G_ILLEGAL_OPT (-2)
#define G_ARG_MISSING (-3)
#define G_EOF -1
#define G_ILLEGAL_OPT -2
#define G_ARG_MISSING -3
extern char *this_command_name;
extern WORD_LIST *rest_of_args;
@ -84,6 +85,25 @@ getopts_reset (newind)
int newind;
{
sh_optind = newind;
sh_badopt = 0;
}
static int
getopts_bind_variable (name, value)
char *name, *value;
{
SHELL_VAR *v;
if (legal_identifier (name))
{
v = bind_variable (name, value);
return (v && (readonly_p (v) == 0)) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
}
else
{
builtin_error ("`%s': not a valid identifier", name);
return (EXECUTION_FAILURE);
}
}
/* Error handling is now performed as specified by Posix.2, draft 11
@ -118,7 +138,7 @@ dogetopts (argc, argv)
int argc;
char **argv;
{
int ret, special_error, old_opterr = 0, i, n;
int ret, special_error, old_opterr, i, n;
char strval[2], numval[16];
char *optstr; /* list of options */
char *name; /* variable to get flag val */
@ -126,7 +146,7 @@ dogetopts (argc, argv)
if (argc < 3)
{
builtin_error("usage: getopts optstring name [arg]");
builtin_usage ();
return (EX_USAGE);
}
@ -156,19 +176,19 @@ dogetopts (argc, argv)
}
else if (rest_of_args == (WORD_LIST *)NULL)
{
register int i;
for (i = 0; i < 10 && dollar_vars[i]; i++);
for (i = 0; i < 10 && dollar_vars[i]; i++)
;
ret = sh_getopt (i, dollar_vars, optstr);
}
else
{
register int i;
register WORD_LIST *words;
char **v;
for (i = 0; i < 10 && dollar_vars[i]; i++);
for (words = rest_of_args; words; words = words->next, i++);
for (i = 0; i < 10 && dollar_vars[i]; i++)
;
for (words = rest_of_args; words; words = words->next, i++)
;
v = (char **)xmalloc ((i + 1) * sizeof (char *));
for (i = 0; i < 10 && dollar_vars[i]; i++)
v[i] = dollar_vars[i];
@ -203,9 +223,9 @@ dogetopts (argc, argv)
/* If an error occurred, decide which one it is and set the return
code appropriately. In all cases, the option character in error
is in SH_OPTOPT. If an illegal option was encountered, OPTARG is
is in OPTOPT. If an illegal option was encountered, OPTARG is
NULL. If a required option argument was missing, OPTARG points
to a NULL string (that is, optarg[0] == 0). */
to a NULL string (that is, sh_optarg[0] == 0). */
if (ret == '?')
{
if (sh_optarg == NULL)
@ -216,26 +236,25 @@ dogetopts (argc, argv)
if (ret == G_EOF)
{
bind_variable (name, "?");
getopts_bind_variable (name, "?");
return (EXECUTION_FAILURE);
}
if (ret == G_ILLEGAL_OPT)
{
/* Illegal option encountered. */
strval[0] = '?';
strval[1] = '\0';
bind_variable (name, strval);
ret = getopts_bind_variable (name, "?");
if (special_error)
{
strval[0] = (char) sh_optopt;
strval[0] = (char)sh_optopt;
strval[1] = '\0';
bind_variable ("OPTARG", strval);
}
else
makunbound ("OPTARG", shell_variables);
return (EXECUTION_SUCCESS);
return (ret);
}
if (ret == G_ARG_MISSING)
@ -243,31 +262,25 @@ dogetopts (argc, argv)
/* Required argument missing. */
if (special_error)
{
strval[0] = ':';
strval[1] = '\0';
bind_variable (name, strval);
ret = getopts_bind_variable (name, ":");
strval[0] = (char) sh_optopt;
strval[0] = (char)sh_optopt;
strval[1] = '\0';
bind_variable ("OPTARG", strval);
}
else
{
strval[0] = '?';
strval[1] = '\0';
bind_variable (name, strval);
ret = getopts_bind_variable (name, "?");
makunbound ("OPTARG", shell_variables);
}
return (EXECUTION_SUCCESS);
return (ret);
}
bind_variable ("OPTARG", sh_optarg);
strval[0] = (char) ret;
strval[1] = '\0';
bind_variable (name, strval);
return (EXECUTION_SUCCESS);
return (getopts_bind_variable (name, strval));
}
/* The getopts builtin. Build an argv, and call dogetopts with it. */
@ -275,26 +288,27 @@ int
getopts_builtin (list)
WORD_LIST *list;
{
register int i;
char **av;
int ac, ret;
WORD_LIST *t;
if (list == 0)
return EXECUTION_FAILURE;
for (t = list, ac = 0; t; t = t->next, ac++);
ac++;
av = (char **)xmalloc ((1 + ac) * sizeof (char *));
av[ac] = (char *) NULL;
av[0] = this_command_name;
for (t = list, i = 1; t; t = t->next, i++)
av[i] = t->word->word;
reset_internal_getopt ();
while ((ret = internal_getopt (list, "")) != -1)
{
switch (ret)
{
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
av = make_builtin_argv (list, &ac);
ret = dogetopts (ac, av);
free ((char *)av);
return (ret);
}
#endif /* GETOPTS_BUILTIN */

View file

@ -23,182 +23,167 @@ $PRODUCES hash.c
$BUILTIN hash
$FUNCTION hash_builtin
$SHORT_DOC hash [-r] [name ...]
$SHORT_DOC hash [-r] [-p pathname] [name ...]
For each NAME, the full pathname of the command is determined and
remembered. The -r option causes the shell to forget all remembered
locations. If no arguments are given, information about remembered
commands is presented.
remembered. If the -p option is supplied, PATHNAME is used as the
full pathname of NAME, and no path search is performed. The -r
option causes the shell to forget all remembered locations. If no
arguments are given, information about remembered commands is displayed.
$END
#include <config.h>
#include <sys/types.h>
#include "../posixstat.h"
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../builtins.h"
#include "../flags.h"
#include "../execute_cmd.h"
#include "hashcom.h"
#include "common.h"
#include "../execute_cmd.h"
#include "bashgetopt.h"
extern int dot_found_in_search;
extern char *this_command_name;
static int add_hashed_command ();
static int print_hashed_commands ();
static int hashing_initialized = 0;
HASH_TABLE *hashed_filenames;
void
initialize_filename_hashing ()
{
hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
if (hashing_initialized == 0)
{
hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
hashing_initialized = 1;
}
}
static void
free_filename_data (data)
char *data;
{
free (((PATH_DATA *)data)->path);
free (data);
}
void
flush_hashed_filenames ()
{
flush_hash_table (hashed_filenames, free_filename_data);
}
/* Remove FILENAME from the table of hashed commands. */
void
remove_hashed_filename (filename)
char *filename;
{
register BUCKET_CONTENTS *item;
if (hashing_enabled == 0)
return;
item = remove_hash_item (filename, hashed_filenames);
if (item)
{
if (item->data)
free_filename_data (item->data);
free (item->key);
free (item);
}
}
/* Print statistics on the current state of hashed commands. If LIST is
not empty, then rehash (or hash in the first place) the specified
commands. */
int
hash_builtin (list)
WORD_LIST *list;
{
int expunge_hash_table = 0;
int any_failed = 0;
int expunge_hash_table, opt;
char *word, *pathname;
if (hashing_disabled)
if (hashing_enabled == 0)
{
builtin_error ("hashing disabled");
return (EXECUTION_FAILURE);
}
while (list)
expunge_hash_table = 0;
pathname = (char *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "rp:")) != -1)
{
char *arg = list->word->word;
if (ISOPTION (arg, 'r'))
switch (opt)
{
case 'r':
expunge_hash_table = 1;
list = list->next;
}
else if (ISOPTION (arg, '-'))
{
list = list->next;
break;
}
else if (*arg == '-')
{
bad_option (list->word->word);
builtin_error ("usage: hash [-r] [command ...]");
case 'p':
pathname = list_optarg;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
else
break;
}
list = loptend;
/* We want hash -r to be silent, but hash -- to print hashing info. That
is the reason for the !expunge_hash_table. */
if (!list && !expunge_hash_table)
is the reason for the test of expunge_hash_table. */
if (list == 0 && expunge_hash_table == 0)
{
/* Print information about current hashed info. */
int any_printed = 0;
int bucket = 0;
register BUCKET_CONTENTS *item_list;
while (bucket < hashed_filenames->nbuckets)
{
item_list = get_hash_bucket (bucket, hashed_filenames);
if (item_list)
{
if (!any_printed)
{
printf ("hits\tcommand\n");
any_printed++;
}
while (item_list)
{
printf ("%4d\t%s\n",
item_list->times_found, pathdata(item_list)->path);
item_list = item_list->next;
}
}
bucket++;
}
if (!any_printed)
printf ("No commands in hash table.\n");
if (print_hashed_commands () == 0)
printf ("%s: hash table empty\n", this_command_name);
return (EXECUTION_SUCCESS);
}
if (expunge_hash_table)
{
int bucket = 0;
register BUCKET_CONTENTS *item_list, *prev;
flush_hashed_filenames ();
while (bucket < hashed_filenames->nbuckets)
{
item_list = get_hash_bucket (bucket, hashed_filenames);
if (item_list)
{
while (item_list)
{
prev = item_list;
free (item_list->key);
free (pathdata(item_list)->path);
free (item_list->data);
item_list = item_list->next;
free (prev);
}
hashed_filenames->bucket_array[bucket] = (BUCKET_CONTENTS *)NULL;
}
bucket++;
}
}
while (list)
for (opt = EXECUTION_SUCCESS; list; list = list->next)
{
/* Add or rehash the specified commands. */
char *word;
char *full_path;
SHELL_VAR *var;
word = list->word->word;
if (absolute_program (word))
if (pathname)
remember_filename (word, pathname, 0, 0);
else
{
list = list->next;
continue;
}
full_path = find_user_command (word);
var = find_function (word);
if (!find_shell_builtin (word) && (!var))
{
if (full_path && executable_file (full_path))
remember_filename (word, full_path, dot_found_in_search, 0);
else
if (absolute_program (word))
{
builtin_error ("%s: not found", word);
any_failed++;
list = list->next;
continue;
}
}
if (full_path)
free (full_path);
list = list->next;
if (add_hashed_command (word))
opt = EXECUTION_FAILURE;
}
}
fflush (stdout);
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
return (opt);
}
/* Place FILENAME (key) and FULL_PATHNAME (data->path) into the
hash table. CHECK_DOT if non-null is for future calls to
find_hashed_filename (). FOUND is the initial value for
times_found. */
find_hashed_filename (); it means that this file was found
in a directory in $PATH that is not an absolute pathname.
FOUND is the initial value for times_found. */
void
remember_filename (filename, full_pathname, check_dot, found)
char *filename, *full_pathname;
@ -206,17 +191,74 @@ remember_filename (filename, full_pathname, check_dot, found)
{
register BUCKET_CONTENTS *item;
if (hashing_disabled)
if (hashing_enabled == 0)
return;
item = add_hash_item (filename, hashed_filenames);
if (item->data)
free (pathdata(item)->path);
else
{
item->key = savestring (filename);
item->data = (char *)xmalloc (sizeof (PATH_DATA));
item->data = xmalloc (sizeof (PATH_DATA));
}
pathdata(item)->path = savestring (full_pathname);
pathdata(item)->check_dot = check_dot;
pathdata(item)->flags = 0;
if (check_dot)
pathdata(item)->flags |= HASH_CHKDOT;
if (*full_pathname != '/')
pathdata(item)->flags |= HASH_RELPATH;
item->times_found = found;
}
static int
add_hashed_command (word, quiet)
char *word;
int quiet;
{
int rv;
char *full_path;
rv = 0;
if (find_function (word) == 0 && find_shell_builtin (word) == 0)
{
full_path = find_user_command (word);
if (full_path && executable_file (full_path))
remember_filename (word, full_path, dot_found_in_search, 0);
else
{
if (quiet == 0)
builtin_error ("%s: not found", word);
rv++;
}
if (full_path)
free (full_path);
}
return (rv);
}
/* Print information about current hashed info. */
static int
print_hashed_commands ()
{
BUCKET_CONTENTS *item_list;
int bucket, any_printed;
for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++)
{
item_list = get_hash_bucket (bucket, hashed_filenames);
if (item_list == 0)
continue;
if (any_printed == 0)
{
printf ("hits\tcommand\n");
any_printed++;
}
for ( ; item_list; item_list = item_list->next)
printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path);
}
return (any_printed);
}

View file

@ -18,7 +18,7 @@
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "../hash.h"
#include "../hashlib.h"
#define FILENAME_HASH_BUCKETS 631
@ -26,7 +26,10 @@ extern HASH_TABLE *hashed_filenames;
typedef struct {
char *path; /* The full pathname of the file. */
int check_dot; /* Whether `.' appeared before this one in $PATH. */
int flags;
} PATH_DATA;
#define HASH_RELPATH 0x01 /* this filename is a relative pathname. */
#define HASH_CHKDOT 0x02 /* check `.' since it was earlier in $PATH */
#define pathdata(x) ((PATH_DATA *)(x)->data)

View file

@ -23,112 +23,131 @@ $PRODUCES help.c
$BUILTIN help
$FUNCTION help_builtin
$DEPENDS_ON HELP_BUILTIN
$SHORT_DOC help [pattern ...]
Display helpful information about builtin commands. If PATTERN is
specified, gives detailed help on all commands matching PATTERN,
otherwise a list of the builtins is printed.
$END
#include <config.h>
#if defined (HELP_BUILTIN)
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "../builtins.h"
#include "bashgetopt.h"
#if defined (USE_GLOB_LIBRARY)
# include <glob/glob.h>
#else
# define FNM_NOMATCH 1
#endif /* USE_GLOB_LIBRARY */
#include <glob/fnmatch.h>
#include <glob/glob.h>
static void show_builtin_command_help ();
/* Print out a list of the known functions in the shell, and what they do.
If LIST is supplied, print out the list which matches for each pattern
specified. */
int
help_builtin (list)
WORD_LIST *list;
{
if (!list)
{
register int i, j;
char blurb[256];
register int i, j;
char *pattern, *name;
int plen, match_found;
show_shell_version ();
printf (
"Shell commands that are defined internally. Type `help' to see this list.\n\
if (list == 0)
{
show_shell_version (0);
show_builtin_command_help ();
return (EXECUTION_SUCCESS);
}
/* Placeholder for future options. */
reset_internal_getopt ();
while ((i = internal_getopt (list, "")) != -1)
{
switch (i)
{
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* We should consider making `help bash' do something. */
if (glob_pattern_p (list->word->word))
{
printf ("Shell commands matching keyword%s `", list->next ? "s" : "");
print_word_list (list, ", ");
printf ("'\n\n");
}
for (match_found = 0, pattern = ""; list; list = list->next)
{
pattern = list->word->word;
plen = strlen (pattern);
for (i = 0; name = shell_builtins[i].name; i++)
{
QUIT;
if ((strncmp (pattern, name, plen) == 0) ||
(fnmatch (pattern, name, 0) != FNM_NOMATCH))
{
printf ("%s: %s\n", name, shell_builtins[i].short_doc);
for (j = 0; shell_builtins[i].long_doc[j]; j++)
printf (" %s\n", shell_builtins[i].long_doc[j]);
match_found++;
}
}
}
if (match_found == 0)
{
builtin_error ("no help topics match `%s'. Try `help help'.", pattern);
return (EXECUTION_FAILURE);
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}
static void
show_builtin_command_help ()
{
int i, j;
char blurb[36];
printf (
"These shell commands are defined internally. Type `help' to see this list.\n\
Type `help name' to find out more about the function `name'.\n\
Use `info bash' to find out more about the shell in general.\n\
\n\
A star (*) next to a name means that the command is disabled.\n\
\n");
for (i = 0; i < num_shell_builtins; i++)
{
QUIT;
sprintf (blurb, "%c%s",
(shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*',
shell_builtins[i].short_doc);
for (i = 0; i < num_shell_builtins; i++)
{
QUIT;
blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
strncpy (blurb + 1, shell_builtins[i].short_doc, 34);
blurb[35] = '\0';
printf ("%s", blurb);
blurb[35] = '\0';
printf ("%s", blurb);
if (i % 2)
printf ("\n");
else
for (j = strlen (blurb); j < 35; j++)
putc (' ', stdout);
}
if (i % 2)
printf ("\n");
else
for (j = strlen (blurb); j < 35; j++)
putc (' ', stdout);
}
else
{
int match_found = 0;
char *pattern = "";
if (glob_pattern_p (list->word->word))
{
printf ("Shell commands matching keyword%s `",
list->next ? "s" : "");
print_word_list (list, ", ");
printf ("'\n\n");
}
while (list)
{
register int i = 0, plen;
char *name;
pattern = list->word->word;
plen = strlen (pattern);
while (name = shell_builtins[i].name)
{
int doc_index;
QUIT;
if ((strncmp (pattern, name, plen) == 0) ||
(fnmatch (pattern, name, 0) != FNM_NOMATCH))
{
printf ("%s: %s\n", name, shell_builtins[i].short_doc);
for (doc_index = 0;
shell_builtins[i].long_doc[doc_index]; doc_index++)
printf (" %s\n", shell_builtins[i].long_doc[doc_index]);
match_found++;
}
i++;
}
list = list->next;
}
if (!match_found)
{
fprintf (stderr, "No help topics match `%s'. Try `help help'.\n",
pattern);
fflush (stderr);
return (EXECUTION_FAILURE);
}
}
fflush (stdout);
return (EXECUTION_SUCCESS);
if (i % 2)
printf ("\n");
}
#endif /* HELP_BUILTIN */

View file

@ -24,156 +24,277 @@ $PRODUCES history.c
$BUILTIN history
$FUNCTION history_builtin
$DEPENDS_ON HISTORY
$SHORT_DOC history [n] [ [-awrn] [filename]]
$SHORT_DOC history [-c] [n] or history -awrn [filename] or history -ps arg [arg...]
Display the history list with line numbers. Lines listed with
with a `*' have been modified. Argument of N says to list only
the last N lines. Argument `-w' means to write out the current
history file; `-r' means to read it instead. Argument `-a' means
the last N lines. The -c option causes the history list to be
cleared by deleting all of the entries. The `-w' option writes out the
current history to the history file; `-r' means to read the file and
append the contents to the history list instead. `-a' means
to append history lines from this session to the history file.
Argument `-n' means to read all history lines not already read
from the history file. If FILENAME is given, then use that file,
else if $HISTFILE has a value, use that, else use ~/.bash_history.
from the history file and append them to the history list. If
FILENAME is given, then that is used as the history file else
if $HISTFILE has a value, that is used, else ~/.bash_history.
If the -s option is supplied, the non-option ARGs are appended to
the history list as a single entry. The -p option means to perform
history expansion on each ARG and display the result, without storing
anything in the history list.
$END
#include "../shell.h"
#include <config.h>
#if defined (HISTORY)
#include <sys/types.h>
#include <sys/file.h>
#include "../filecntl.h"
#include "../posixstat.h"
#include "../filecntl.h"
#include <errno.h>
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../bashhist.h"
#include <readline/history.h>
#include "bashgetopt.h"
#include "common.h"
/* History. Arg of -w FILENAME means write file, arg of -r FILENAME
means read file. Arg of N means only display that many items. */
#if !defined (errno)
extern int errno;
#endif
static void display_history ();
static void push_history ();
static int expand_and_print_history ();
#define AFLAG 0x01
#define RFLAG 0x02
#define WFLAG 0x04
#define NFLAG 0x08
#define SFLAG 0x10
#define PFLAG 0x20
#define CFLAG 0x40
int
history_builtin (list)
WORD_LIST *list;
{
register int i;
int limited = 0, limit = 0;
HIST_ENTRY **hlist;
int flags, opt, result;
char *filename;
while (list)
flags = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "acnpsrw")) != -1)
{
char *arg = list->word->word;
if ((arg[0] == '-') &&
(strlen (arg) == 2) &&
(member (arg[1], "rwan")))
switch (opt)
{
char *file;
int result = EXECUTION_SUCCESS;
if (list->next)
file = list->next->word->word;
else
file = get_string_value ("HISTFILE");
switch (arg[1])
{
case 'a': /* Append `new' lines to file. */
{
if (history_lines_this_session)
{
void using_history ();
if (history_lines_this_session < where_history ())
{
/* If the filename was supplied, then create it
if it doesn't already exist. */
if (file)
{
struct stat buf;
if (stat (file, &buf) == -1)
{
int tem;
tem = open (file, O_CREAT, 0666);
close (tem);
}
}
result =
append_history (history_lines_this_session, file);
history_lines_in_file += history_lines_this_session;
history_lines_this_session = 0;
}
}
break;
}
case 'w': /* Write entire history. */
{
result = write_history (file);
break;
}
case 'r': /* Read entire file. */
{
result = read_history (file);
break;
}
case 'n': /* Read `new' history from file. */
{
/* Read all of the lines in the file that we haven't
already read. */
using_history ();
result = read_history_range (file, history_lines_in_file, -1);
using_history ();
history_lines_in_file = where_history ();
break;
}
}
return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
else if (strcmp (list->word->word, "--") == 0)
{
list = list->next;
case 'a':
flags |= AFLAG;
break;
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_error ("usage: history [n] [-rwan [filename]]");
case 'c':
flags |= CFLAG;
break;
case 'n':
flags |= NFLAG;
break;
case 'r':
flags |= RFLAG;
break;
case 'w':
flags |= WFLAG;
break;
case 's':
flags |= SFLAG;
break;
case 'p':
#if defined (BANG_HISTORY)
flags |= PFLAG;
#endif
break;
default:
builtin_usage ();
return (EX_USAGE);
}
else
break;
}
list = loptend;
opt = flags & (AFLAG|RFLAG|WFLAG|NFLAG);
if (opt && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG)
{
builtin_error ("cannot use more than one of -anrw");
return (EXECUTION_FAILURE);
}
/* clear the history, but allow other arguments to add to it again. */
if (flags & CFLAG)
{
clear_history ();
if (list == 0)
return (EXECUTION_SUCCESS);
}
if (flags & SFLAG)
{
if (list)
push_history (list);
return (EXECUTION_SUCCESS);
}
#if defined (BANG_HISTORY)
else if (flags & PFLAG)
{
if (list)
return (expand_and_print_history (list));
return (EXECUTION_SUCCESS);
}
#endif
else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
{
display_history (list);
return (EXECUTION_SUCCESS);
}
filename = list ? list->word->word : get_string_value ("HISTFILE");
result = EXECUTION_SUCCESS;
if (flags & AFLAG) /* Append session's history to file. */
result = maybe_append_history (filename);
else if (flags & WFLAG) /* Write entire history. */
result = write_history (filename);
else if (flags & RFLAG) /* Read entire file. */
result = read_history (filename);
else if (flags & NFLAG) /* Read `new' history from file. */
{
/* Read all of the lines in the file that we haven't already read. */
using_history ();
result = read_history_range (filename, history_lines_in_file, -1);
using_history ();
history_lines_in_file = where_history ();
}
return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
/* Accessors for HIST_ENTRY lists that are called HLIST. */
#define histline(i) (hlist[(i)]->line)
#define histdata(i) (hlist[(i)]->data)
static void
display_history (list)
WORD_LIST *list;
{
register int i;
int limited, limit;
HIST_ENTRY **hlist;
if (list)
{
limited = 1;
limit = get_numeric_arg (list);
}
else
limited = limit = 0;
hlist = history_list ();
if (hlist)
{
for (i = 0; hlist[i]; i++);
for (i = 0; hlist[i]; i++)
;
if (limit < 0)
limit = -limit;
if (!limited)
if ((limited == 0) || ((i -= limit) < 0))
i = 0;
else
if ((i -= limit) < 0)
i = 0;
while (hlist[i])
{
QUIT;
printf ("%5d%c %s\n", i + history_base,
hlist[i]->data ? '*' : ' ', hlist[i]->line);
histdata(i) ? '*' : ' ',
histline(i));
i++;
}
}
return (EXECUTION_SUCCESS);
}
static int
delete_last_history ()
{
register int i;
HIST_ENTRY **hlist, *histent, *discard;
hlist = history_list ();
if (hlist == NULL)
return 0;
for (i = 0; hlist[i]; i++)
;
i--;
/* History_get () takes a parameter that must be offset by history_base. */
histent = history_get (history_base + i); /* Don't free this */
if (histent == NULL)
return 0;
discard = remove_history (i);
if (discard)
{
if (discard->line)
free (discard->line);
free ((char *) discard);
}
return (1);
}
/* Remove the last entry in the history list and add each argument in
LIST to the history. */
static void
push_history (list)
WORD_LIST *list;
{
char *s;
if (delete_last_history () == 0)
return;
s = string_list (list);
maybe_add_history (s); /* Obeys HISTCONTROL setting. */
free (s);
}
#if defined (BANG_HISTORY)
static int
expand_and_print_history (list)
WORD_LIST *list;
{
char *s;
int r, result;
if (delete_last_history () == 0)
return EXECUTION_FAILURE;
result = EXECUTION_SUCCESS;
while (list)
{
r = history_expand (list->word->word, &s);
if (r < 0)
{
builtin_error ("%s: history expansion failed", list->word->word);
result = EXECUTION_FAILURE;
}
else
{
fputs (s, stdout);
putchar ('\n');
}
FREE (s);
list = list->next;
}
fflush (stdout);
return result;
}
#endif /* BANG_HISTORY */
#endif /* HISTORY */

View file

@ -20,6 +20,8 @@ with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES inlib.c
#include <config.h>
#include <stdio.h>
#include "../shell.h"

View file

@ -1,5 +1,5 @@
This file is jobs.def, from which is created jobs.c.
It implements the builtin "jobs" in Bash.
It implements the builtins "jobs" and "disown" in Bash.
Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
@ -24,24 +24,38 @@ $PRODUCES jobs.c
$BUILTIN jobs
$FUNCTION jobs_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC jobs [-lnp] [jobspec ...] | jobs -x command [args]
$SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args]
Lists the active jobs. The -l option lists process id's in addition
to the normal information; the -p option lists process id's only.
If -n is given, only processes that have changed status since the last
notification are printed. JOBSPEC restricts output to that job.
If -x is given, COMMAND is run after all job specifications that appear
in ARGS have been replaced with the process ID of that job's process group
leader.
notification are printed. JOBSPEC restricts output to that job. The
-r and -s options restrict output to running and stopped jobs only,
respectively. Without options, the status of all active jobs is
printed. If -x is given, COMMAND is run after all job specifications
that appear in ARGS have been replaced with the process ID of that job's
process group leader.
$END
#include "../shell.h"
#include <config.h>
#if defined (JOB_CONTROL)
#include <sys/types.h>
#include "../bashtypes.h"
#include <signal.h>
#include "../jobs.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../jobs.h"
#include "../execute_cmd.h"
#include "bashgetopt.h"
#include "common.h"
#define JSTATE_ANY 0x0
#define JSTATE_RUNNING 0x1
#define JSTATE_STOPPED 0x2
extern int job_control, interactive_shell;
static int execute_list_with_replacements ();
@ -52,20 +66,24 @@ static int execute_list_with_replacements ();
pid only. If `-n' is given, only processes that have changed
status since the last notification are printed. If -x is given,
replace all job specs with the pid of the appropriate process
group leader and execute the command. */
group leader and execute the command. The -r and -s options mean
to print info about running and stopped jobs only, respectively. */
int
jobs_builtin (list)
WORD_LIST *list;
{
int form = JLIST_STANDARD, execute = 0;
int opt;
int any_failed = 0;
int form, execute, state, opt, any_failed, job;
sigset_t set, oset;
if (!job_control && !interactive_shell)
if (job_control == 0 && interactive_shell == 0)
return (EXECUTION_SUCCESS);
execute = any_failed = 0;
form = JLIST_STANDARD;
state = JSTATE_ANY;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lpnx")) != -1)
while ((opt = internal_getopt (list, "lpnxrs")) != -1)
{
switch (opt)
{
@ -86,9 +104,15 @@ jobs_builtin (list)
}
execute++;
break;
case 'r':
state = JSTATE_RUNNING;
break;
case 's':
state = JSTATE_STOPPED;
break;
default:
builtin_error ("usage: jobs [-lpn [jobspec]] [-x command [args]]");
builtin_usage ();
return (EX_USAGE);
}
}
@ -100,21 +124,29 @@ jobs_builtin (list)
if (!list)
{
list_jobs (form);
switch (state)
{
case JSTATE_ANY:
list_all_jobs (form);
break;
case JSTATE_RUNNING:
list_running_jobs (form);
break;
case JSTATE_STOPPED:
list_stopped_jobs (form);
break;
}
return (EXECUTION_SUCCESS);
}
while (list)
{
int job;
sigset_t set, oset;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if ((job == NO_JOB) || !jobs || !jobs[job])
{
builtin_error ("No such job %s", list->word->word);
builtin_error ("no such job %s", list->word->word);
any_failed++;
}
else if (job != DUP_JOB)
@ -169,3 +201,62 @@ execute_list_with_replacements (list)
return (result);
}
#endif /* JOB_CONTROL */
$BUILTIN disown
$FUNCTION disown_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC disown [-h] [jobspec ...]
By default, removes each JOBSPEC argument from the table of active jobs.
If the -h option is given, the job is not removed from the table, but is
marked so that SIGHUP is not sent to the job if the shell receives a
SIGHUP.
$END
#if defined (JOB_CONTROL)
int
disown_builtin (list)
WORD_LIST *list;
{
int opt, job, retval, nohup_only;
sigset_t set, oset;
nohup_only = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "h")) != -1)
{
switch (opt)
{
case 'h':
nohup_only = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
retval = EXECUTION_SUCCESS;
do
{
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if (job == NO_JOB || jobs == 0 || jobs[job] == 0)
{
builtin_error ("no such job %s", list->word->word);
retval = EXECUTION_FAILURE;
}
else if (nohup_only)
nohup_job (job);
else
delete_job (job);
UNBLOCK_CHILD (oset);
if (list)
list = list->next;
}
while (list);
return (retval);
}
#endif /* JOB_CONTROL */

View file

@ -24,7 +24,7 @@ $PRODUCES kill.c
$BUILTIN kill
$FUNCTION kill_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC kill [-s sigspec | -sigspec] [pid | job]... | -l [signum]
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
Send the processes named by PID (or JOB) the signal SIGSPEC. If
SIGSPEC is not present, then SIGTERM is assumed. An argument of `-l'
lists the signal names; if arguments follow `-l' they are assumed to
@ -34,17 +34,25 @@ process IDs, and, if you have reached the limit on processes that
you can create, you don't have to start a process to kill another one.
$END
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include <config.h>
#include <stdio.h>
#include <errno.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../bashtypes.h"
#include "../shell.h"
#include "../trap.h"
#include "../jobs.h"
#include "common.h"
#include <errno.h>
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if defined (JOB_CONTROL)
extern int interactive;
@ -63,14 +71,17 @@ int
kill_builtin (list)
WORD_LIST *list;
{
int signal = SIGTERM;
int any_succeeded = 0, listing = 0, saw_signal = 0;
char *sigspec = "TERM", *word;
int signal, any_succeeded, listing, saw_signal;
char *sigspec, *word;
pid_t pid;
if (!list)
if (list == 0)
return (EXECUTION_SUCCESS);
any_succeeded = listing = saw_signal = 0;
signal = SIGTERM;
sigspec = "TERM";
/* Process options. */
while (list)
{
@ -81,13 +92,13 @@ kill_builtin (list)
listing++;
list = list->next;
}
else if (ISOPTION (word, 's'))
else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
{
list = list->next;
if (list)
{
sigspec = list->word->word;
if (sigspec[0] == '0' && !sigspec[1])
if (sigspec[0] == '0' && sigspec[1] == '\0')
signal = 0;
else
signal = decode_signal (sigspec);
@ -95,7 +106,7 @@ kill_builtin (list)
}
else
{
builtin_error ("-s requires an argument");
builtin_error ("%s requires an argument", word);
return (EXECUTION_FAILURE);
}
}
@ -104,6 +115,11 @@ kill_builtin (list)
list = list->next;
break;
}
else if (ISOPTION (word, '?'))
{
builtin_usage ();
return (EXECUTION_SUCCESS);
}
/* If this is a signal specification then process it. We only process
the first one seen; other arguments may signify process groups (e.g,
-num == process group num). */
@ -119,75 +135,7 @@ kill_builtin (list)
}
if (listing)
{
if (!list)
{
register int i;
register int column = 0;
char *name;
for (i = 1; i < NSIG; i++)
{
name = signal_name (i);
if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
continue;
if (posixly_correct)
printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
else
{
printf ("%2d) %s", i, name);
if (++column < 4)
printf ("\t");
else
{
printf ("\n");
column = 0;
}
}
}
if (posixly_correct || column != 0)
printf ("\n");
}
else
{
/* List individual signal names. */
while (list)
{
int signum;
char *name;
if ((sscanf (list->word->word, "%d", &signum) != 1) ||
(signum <= 0))
{
list_error:
builtin_error ("bad signal number: %s", list->word->word);
list = list->next;
continue;
}
/* This is specified by Posix.2 so that exit statuses can be
mapped into signal numbers. */
if (signum > 128)
signum -= 128;
if (signum >= NSIG)
goto list_error;
name = signal_name (signum);
if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
{
list = list->next;
continue;
}
printf ("%s\n", name);
list = list->next;
}
}
return (EXECUTION_SUCCESS);
}
return (display_signal_list (list, 0));
/* OK, we are killing processes. */
if (signal == NO_SIG)
@ -215,15 +163,11 @@ kill_builtin (list)
}
else if (*list->word->word != '%')
{
builtin_error ("No such pid %s", list->word->word);
builtin_error ("%s: no such pid", list->word->word);
CONTINUE_OR_FAIL;
}
#if 1
else if (interactive)
/* Posix.2 says you can kill without job control active (4.32.4) */
#else
else if (job_control) /* can't kill jobs if not using job control */
#endif
{ /* Must be a job spec. Check it out. */
int job;
sigset_t set, oset;
@ -234,7 +178,7 @@ kill_builtin (list)
if (job < 0 || job >= job_slots || !jobs[job])
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list->word->word);
builtin_error ("%s: no such job", list->word->word);
UNBLOCK_CHILD (oset);
CONTINUE_OR_FAIL;
}
@ -243,10 +187,7 @@ kill_builtin (list)
without job control, then its pgrp == shell_pgrp, so we have
to be careful. We take the pid of the first job in the pipeline
in that case. */
if (jobs[job]->flags & J_JOBCONTROL)
pid = jobs[job]->pgrp;
else
pid = jobs[job]->pipe->pid;
pid = IS_JOBCONTROL (job) ? jobs[job]->pgrp : jobs[job]->pipe->pid;
UNBLOCK_CHILD (oset);
@ -266,16 +207,13 @@ kill_builtin (list)
}
else
{
builtin_error ("bad process specification `%s'", list->word->word);
builtin_error ("`%s' is not a pid or valid job spec", list->word->word);
CONTINUE_OR_FAIL;
}
continue_killing:
list = list->next;
}
if (any_succeeded)
return (EXECUTION_SUCCESS);
else
return (EXECUTION_FAILURE);
return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
#endif /* JOB_CONTROL */

View file

@ -29,13 +29,23 @@ by 0 is trapped and flagged as an error. The following list of
operators is grouped into levels of equal-precedence operators.
The levels are listed in order of decreasing precedence.
- unary minus
! logical NOT
* / % multiplication, division, remainder
+ - addition, subtraction
<= >= < > comparison
== != equality inequality
= assignment
-, + unary minus, plus
!, ~ logical and bitwise negation
*, /, % multiplication, division, remainder
+, - addition, subtraction
<<, >> left and right bitwise shifts
<=, >=, <, > comparison
==, != equality, inequality
& bitwise AND
^ bitwise XOR
| bitwise OR
&& logical AND
|| logical OR
expr ? expr : expr
conditional expression
=, *=, /=, %=,
+=, -=, <<=, >>=,
&=, ^=, |= assignment
Shell variables are allowed as operands. The name of the variable
is replaced by its value (coerced to a long integer) within
@ -50,28 +60,49 @@ If the last ARG evaluates to 0, let returns 1; 0 is returned
otherwise.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "common.h"
/* Arithmetic LET function. */
int
let_builtin (list)
WORD_LIST *list;
{
long ret = 0L;
long ret;
if (!list)
if (list == 0)
{
builtin_error ("argument (expression) expected");
builtin_error ("expression expected");
return (EXECUTION_FAILURE);
}
while (list)
for (; list; list = list->next)
ret = evalexp (list->word->word);
return ((ret == 0L) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
int
exp_builtin (list)
WORD_LIST *list;
{
char *exp;
int ret;
if (list == 0)
{
ret = evalexp (list->word->word);
list = list->next;
builtin_error ("expression expected");
return (EXECUTION_FAILURE);
}
if (ret == 0L)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
exp = string_list (list);
ret = evalexp (exp);
free (exp);
return ((ret == 0L) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}

View file

@ -19,6 +19,12 @@ You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../config.h"
#include <stdio.h>
@ -50,6 +56,7 @@ extern char *strcpy ();
/* Flag values that builtins can have. */
#define BUILTIN_FLAG_SPECIAL 0x01
#define BUILTIN_FLAG_ASSIGNMENT 0x02
/* If this stream descriptor is non-zero, then write
texinfo documentation to it. */
@ -115,12 +122,41 @@ char *special_builtins[] =
"export", "readonly", "return", "set", "shift", "trap", "unset",
(char *)NULL
};
static int is_special_builtin ();
/* The builtin commands that take assignment statements as arguments. */
char *assignment_builtins[] =
{
"alias", "declare", "export", "local", "readonly", "typeset",
(char *)NULL
};
/* Forward declarations. */
static int is_special_builtin ();
static int is_assignment_builtin ();
void extract_info ();
void file_error ();
void line_error ();
void write_file_headers ();
void write_file_footers ();
void write_ifdefs ();
void write_endifs ();
void write_documentation ();
void write_longdocs ();
void write_builtins ();
void free_defs ();
void add_documentation ();
void must_be_building ();
void remove_trailing_whitespace ();
/* For each file mentioned on the command line, process it and
write the information to STRUCTFILE and EXTERNFILE, while
creating the production file if neccessary. */
int
main (argc, argv)
int argc;
char **argv;
@ -305,6 +341,7 @@ copy_string_array (array)
}
/* Add ELEMENT to ARRAY, growing the array if neccessary. */
void
array_add (element, array)
char *element;
ARRAY *array;
@ -324,6 +361,7 @@ array_add (element, array)
}
/* Free an allocated array and data pointer. */
void
array_free (array)
ARRAY *array;
{
@ -397,6 +435,7 @@ int output_cpp_line_info = 0;
target. After the file has been processed, write out the names of
builtins found in each $BUILTIN. Plain text found before the $PRODUCES
is ignored, as is "$$ comment text". */
void
extract_info (filename, structfile, externfile)
char *filename;
FILE *structfile, *externfile;
@ -548,6 +587,7 @@ free_builtin (builtin)
}
/* Free all of the memory allocated to a DEF_FILE. */
void
free_defs (defs)
DEF_FILE *defs;
{
@ -592,6 +632,7 @@ strip_whitespace (string)
}
/* Remove only the trailing whitespace from STRING. */
void
remove_trailing_whitespace (string)
char *string;
{
@ -625,6 +666,7 @@ get_arg (for_whom, defs, string)
}
/* Error if not building a builtin. */
void
must_be_building (directive, defs)
char *directive;
DEF_FILE *defs;
@ -645,6 +687,7 @@ current_builtin (directive, defs)
/* Add LINE to the long documentation for the current builtin.
Ignore blank lines until the first non-blank line has been seen. */
void
add_documentation (defs, line)
DEF_FILE *defs;
char *line;
@ -670,38 +713,42 @@ builtin_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
{
BUILTIN_DESC *new;
char *name;
/* If we are already building a builtin, we cannot start a new one. */
if (building_builtin)
return (line_error (defs, "%s found before $END", self));
{
line_error (defs, "%s found before $END", self);
return (-1);
}
output_cpp_line_info++;
/* Get the name of this builtin, and stick it in the array. */
{
BUILTIN_DESC *new;
char *name;
name = get_arg (self, defs, arg);
name = get_arg (self, defs, arg);
/* If this is the first builtin, create the array to hold them. */
if (!defs->builtins)
defs->builtins = array_create (sizeof (BUILTIN_DESC *));
/* If this is the first builtin, create the array to hold them. */
if (!defs->builtins)
defs->builtins = array_create (sizeof (BUILTIN_DESC *));
new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
new->name = name;
new->function = (char *)NULL;
new->shortdoc = (char *)NULL;
new->docname = (char *)NULL;
new->longdoc = (ARRAY *)NULL;
new->dependencies = (ARRAY *)NULL;
new->flags = 0;
new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
new->name = name;
new->function = (char *)NULL;
new->shortdoc = (char *)NULL;
new->docname = (char *)NULL;
new->longdoc = (ARRAY *)NULL;
new->dependencies = (ARRAY *)NULL;
new->flags = 0;
if (is_special_builtin (name))
new->flags |= BUILTIN_FLAG_SPECIAL;
if (is_assignment_builtin (name))
new->flags |= BUILTIN_FLAG_ASSIGNMENT;
if (is_special_builtin (name))
new->flags |= BUILTIN_FLAG_SPECIAL;
array_add ((char *)new, defs->builtins);
building_builtin = 1;
array_add ((char *)new, defs->builtins);
building_builtin = 1;
}
return (0);
}
@ -744,6 +791,7 @@ docname_handler (self, defs, arg)
}
/* How to handle the $SHORT_DOC directive. */
int
short_doc_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
@ -762,13 +810,16 @@ short_doc_handler (self, defs, arg)
}
/* How to handle the $COMMENT directive. */
int
comment_handler (self, defs)
char *self;
DEF_FILE *defs;
{
return (0);
}
/* How to handle the $DEPENDS_ON directive. */
int
depends_on_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
@ -788,6 +839,7 @@ depends_on_handler (self, defs, arg)
}
/* How to handle the $PRODUCES directive. */
int
produces_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
@ -820,12 +872,14 @@ produces_handler (self, defs, arg)
}
/* How to handle the $END directive. */
int
end_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
{
must_be_building (self, defs);
building_builtin = 0;
return (0);
}
/* **************************************************************** */
@ -835,6 +889,7 @@ end_handler (self, defs, arg)
/* **************************************************************** */
/* Produce an error for DEFS with FORMAT and ARGS. */
void
line_error (defs, format, arg1, arg2)
DEF_FILE *defs;
char *format, *arg1, *arg2;
@ -848,6 +903,7 @@ line_error (defs, format, arg1, arg2)
}
/* Print error message for FILENAME. */
void
file_error (filename)
char *filename;
{
@ -895,7 +951,7 @@ xrealloc (pointer, bytes)
static void
memory_error_and_abort ()
{
fprintf (stderr, "mkbuiltins: Out of virtual memory!\n");
fprintf (stderr, "mkbuiltins: out of virtual memory\n");
abort ();
}
@ -929,6 +985,7 @@ copy_builtin (builtin)
}
/* How to save away a builtin. */
void
save_builtin (builtin)
BUILTIN_DESC *builtin;
{
@ -972,7 +1029,7 @@ char *structfile_header[] = {
" along with Bash; see the file COPYING. If not, write to the Free",
" Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
"",
"/* The list of shell builtins. Each element is name, function, enabled-p,",
"/* The list of shell builtins. Each element is name, function, flags,",
" long-doc, short-doc. The long-doc field contains a pointer to an array",
" of help lines. The function takes a WORD_LIST *; the first word in the",
" list is the first arg to the command. The list has already had word",
@ -992,13 +1049,17 @@ char *structfile_footer[] = {
" { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
"};",
"",
"struct builtin *shell_builtins = static_shell_builtins;",
"struct builtin *current_builtin;",
"",
"int num_shell_builtins =",
"\tsizeof (shell_builtins) / sizeof (struct builtin) - 1;",
"\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
(char *)NULL
};
/* Write out any neccessary opening information for
STRUCTFILE and EXTERNFILE. */
void
write_file_headers (structfile, externfile)
FILE *structfile, *externfile;
{
@ -1011,7 +1072,7 @@ write_file_headers (structfile, externfile)
fprintf (structfile, "#include \"%s\"\n",
extern_filename ? extern_filename : "builtext.h");
fprintf (structfile, "\nstruct builtin shell_builtins[] = {\n");
fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
}
if (externfile)
@ -1022,6 +1083,7 @@ write_file_headers (structfile, externfile)
/* Write out any necessary closing information for
STRUCTFILE and EXTERNFILE. */
void
write_file_footers (structfile, externfile)
FILE *structfile, *externfile;
{
@ -1037,6 +1099,7 @@ write_file_footers (structfile, externfile)
/* Write out the information accumulated in DEFS to
STRUCTFILE and EXTERNFILE. */
void
write_builtins (defs, structfile, externfile)
DEF_FILE *defs;
FILE *structfile, *externfile;
@ -1057,8 +1120,7 @@ write_builtins (defs, structfile, externfile)
{
if (builtin->dependencies)
{
if (builtin->function)
write_ifdefs (externfile, builtin->dependencies->array);
write_ifdefs (externfile, builtin->dependencies->array);
write_ifdefs (structfile, builtin->dependencies->array);
}
@ -1083,20 +1145,14 @@ write_builtins (defs, structfile, externfile)
else
fprintf (structfile, "(Function *)0x0, ");
#define SPECIAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN | SPECIAL_BUILTIN"
#define NORMAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN"
fprintf (structfile, "%s, %s_doc,\n",
(builtin->flags & BUILTIN_FLAG_SPECIAL) ?
SPECIAL_FLAG_STRING :
NORMAL_FLAG_STRING,
fprintf (structfile, "%s%s%s, %s_doc,\n",
"BUILTIN_ENABLED | STATIC_BUILTIN",
(builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
(builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
builtin->docname ? builtin->docname : builtin->name);
#undef SPECIAL_FLAG_STRING
#undef NORMAL_FLAG_STRING
fprintf
(structfile, " \"%s\" },\n",
(structfile, " \"%s\", (char *)NULL },\n",
builtin->shortdoc ? builtin->shortdoc : builtin->name);
/* Save away this builtin for later writing of the
@ -1126,6 +1182,7 @@ write_builtins (defs, structfile, externfile)
}
/* Write out the long documentation strings in BUILTINS to STREAM. */
void
write_longdocs (stream, builtins)
FILE *stream;
ARRAY *builtins;
@ -1157,6 +1214,7 @@ write_longdocs (stream, builtins)
DEFINES is a null terminated array of define names.
If a define is preceded by an `!', then the sense of the test is
reversed. */
void
write_ifdefs (stream, defines)
FILE *stream;
char **defines;
@ -1187,6 +1245,7 @@ write_ifdefs (stream, defines)
of the immediately preceding code.
STREAM is the stream to write the information to.
DEFINES is a null terminated array of define names. */
void
write_endifs (stream, defines)
FILE *stream;
char **defines;
@ -1211,6 +1270,7 @@ write_endifs (stream, defines)
/* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
and quoting special characters in the string. */
void
write_documentation (stream, documentation, indentation, flags)
FILE *stream;
char **documentation;
@ -1218,14 +1278,14 @@ write_documentation (stream, documentation, indentation, flags)
{
register int i, j;
register char *line;
int string_array = (flags & STRING_ARRAY); /* Mutually exclusive. */
int texinfo = (flags & TEXINFO);
int string_array, texinfo;
if (!stream)
return;
string_array = flags & STRING_ARRAY;
if (string_array)
fprintf (stream, " {\n");
fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
#if !defined (OLDCODE)
/* XXX -- clean me up; for experiment only */
@ -1233,7 +1293,7 @@ write_documentation (stream, documentation, indentation, flags)
goto end_of_document;
#endif /* !OLDCODE */
for (i = 0; line = documentation[i]; i++)
for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
{
/* Allow #ifdef's to be written out verbatim. */
if (*line == '#')
@ -1295,17 +1355,31 @@ end_of_document:
#endif /* !OLDCODE */
if (string_array)
fprintf (stream, " (char *)NULL\n};\n");
fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
}
static int
_find_in_table (name, name_table)
char *name, *name_table[];
{
register int i;
for (i = 0; name_table[i]; i++)
if (strcmp (name, name_table[i]) == 0)
return 1;
return 0;
}
static int
is_special_builtin (name)
char *name;
{
register int i;
for (i = 0; special_builtins[i]; i++)
if (strcmp (name, special_builtins[i]) == 0)
return 1;
return 0;
return (_find_in_table (name, special_builtins));
}
static int
is_assignment_builtin (name)
char *name;
{
return (_find_in_table (name, assignment_builtins));
}

View file

@ -21,6 +21,11 @@
/* Write output in 128-byte chunks until we get a sigpipe or write gets an
EPIPE. Then report how many bytes we wrote. We assume that this is the
pipe size. */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
@ -29,6 +34,7 @@
#include "../command.h"
#include "../general.h"
#include "../sig.h"
extern int errno;
int nw;

604
builtins/pushd.def Normal file
View file

@ -0,0 +1,604 @@
This file is pushd.def, from which is created pushd.c. It implements the
builtins "pushd", "popd", and "dirs" in Bash.
Copyright (C) 1987, 1989, 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 1, 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; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES pushd.c
$BUILTIN pushd
$FUNCTION pushd_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC pushd [dir | +N | -N] [-n]
Adds a directory to the top of the directory stack, or rotates
the stack, making the new top of the stack the current working
directory. With no arguments, exchanges the top two directories.
+N Rotates the stack so that the Nth directory (counting
from the left of the list shown by `dirs') is at the top.
-N Rotates the stack so that the Nth directory (counting
from the right) is at the top.
-n suppress the normal change of directory when adding directories
to the stack, so only the stack is manipulated.
dir adds DIR to the directory stack at the top, making it the
new current working directory.
You can see the directory stack with the `dirs' command.
$END
$BUILTIN popd
$FUNCTION popd_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC popd [+N | -N] [-n]
Removes entries from the directory stack. With no arguments,
removes the top directory from the stack, and cd's to the new
top directory.
+N removes the Nth entry counting from the left of the list
shown by `dirs', starting with zero. For example: `popd +0'
removes the first directory, `popd +1' the second.
-N removes the Nth entry counting from the right of the list
shown by `dirs', starting with zero. For example: `popd -0'
removes the last directory, `popd -1' the next to last.
-n suppress the normal change of directory when removing directories
from the stack, so only the stack is manipulated.
You can see the directory stack with the `dirs' command.
$END
$BUILTIN dirs
$FUNCTION dirs_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC dirs [-clpv] [+N] [-N]
Display the list of currently remembered directories. Directories
find their way onto the list with the `pushd' command; you can get
back up through the list with the `popd' command.
The -l flag specifies that `dirs' should not print shorthand versions
of directories which are relative to your home directory. This means
that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag
causes `dirs' to print the directory stack with one entry per line,
prepending the directory name with its position in the stack. The -p
flag does the same thing, but the stack position is not prepended.
The -c flag clears the directory stack by deleting all of the elements.
+N displays the Nth entry counting from the left of the list shown by
dirs when invoked without options, starting with zero.
-N displays the Nth entry counting from the right of the list shown by
dirs when invoked without options, starting with zero.
$END
#include <config.h>
#if defined (PUSHD_AND_POPD)
#include <stdio.h>
#include <sys/param.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include <errno.h>
#include <tilde/tilde.h>
#include "../shell.h"
#include "../maxpath.h"
#include "common.h"
#include "builtext.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
static char *m_badarg = "%s: bad argument";
/* The list of remembered directories. */
static char **pushd_directory_list = (char **)NULL;
/* Number of existing slots in this list. */
static int directory_list_size;
/* Offset to the end of the list. */
static int directory_list_offset;
static void pushd_error ();
static void clear_directory_stack ();
static int cd_to_string ();
static int change_to_temp ();
static int get_dirstack_index ();
static void add_dirstack_element ();
#define NOCD 0x01
#define ROTATE 0x02
#define LONGFORM 0x04
#define CLEARSTAK 0x08
int
pushd_builtin (list)
WORD_LIST *list;
{
char *temp, *current_directory, *top;
int j, flags;
long num;
char direction;
/* If there is no argument list then switch current and
top of list. */
if (list == 0)
{
if (directory_list_offset == 0)
{
builtin_error ("no other directory");
return (EXECUTION_FAILURE);
}
current_directory = get_working_directory ("pushd");
if (current_directory == 0)
return (EXECUTION_FAILURE);
j = directory_list_offset - 1;
temp = pushd_directory_list[j];
pushd_directory_list[j] = current_directory;
j = change_to_temp (temp);
free (temp);
return j;
}
for (flags = 0; list; list = list->next)
{
if (ISOPTION (list->word->word, 'n'))
{
flags |= NOCD;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
/* Let `pushd -' work like it used to. */
break;
else if (((direction = list->word->word[0]) == '+') || direction == '-')
{
if (legal_number (list->word->word + 1, &num) == 0)
{
builtin_error (m_badarg, list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
if (direction == '-')
num = directory_list_offset - num;
if (num > directory_list_offset || num < 0)
{
pushd_error (directory_list_offset, list->word->word);
return (EXECUTION_FAILURE);
}
flags |= ROTATE;
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
else
break;
}
if (flags & ROTATE)
{
/* Rotate the stack num times. Remember, the current
directory acts like it is part of the stack. */
temp = get_working_directory ("pushd");
if (num == 0)
{
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
free (temp);
return j;
}
do
{
top = pushd_directory_list[directory_list_offset - 1];
for (j = directory_list_offset - 2; j > -1; j--)
pushd_directory_list[j + 1] = pushd_directory_list[j];
pushd_directory_list[j + 1] = temp;
temp = top;
num--;
}
while (num);
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
free (temp);
return j;
}
if (list == 0)
return (EXECUTION_SUCCESS);
/* Change to the directory in list->word->word. Save the current
directory on the top of the stack. */
current_directory = get_working_directory ("pushd");
if (current_directory == 0)
return (EXECUTION_FAILURE);
j = ((flags & NOCD) == 0) ? cd_builtin (list) : EXECUTION_SUCCESS;
if (j == EXECUTION_SUCCESS)
{
add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory);
dirs_builtin ((WORD_LIST *)NULL);
return (EXECUTION_SUCCESS);
}
else
{
free (current_directory);
return (EXECUTION_FAILURE);
}
}
/* Pop the directory stack, and then change to the new top of the stack.
If LIST is non-null it should consist of a word +N or -N, which says
what element to delete from the stack. The default is the top one. */
int
popd_builtin (list)
WORD_LIST *list;
{
register int i;
long which;
int flags;
char direction;
for (flags = 0, which = 0L, direction = '+'; list; list = list->next)
{
if (ISOPTION (list->word->word, 'n'))
{
flags |= NOCD;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (((direction = list->word->word[0]) == '+') || direction == '-')
{
if (legal_number (list->word->word + 1, &which) == 0)
{
builtin_error (m_badarg, list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
else
break;
}
if (which > directory_list_offset || (directory_list_offset == 0 && which == 0))
{
pushd_error (directory_list_offset, list ? list->word->word : "");
return (EXECUTION_FAILURE);
}
/* Handle case of no specification, or top of stack specification. */
if ((direction == '+' && which == 0) ||
(direction == '-' && which == directory_list_offset))
{
i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1])
: EXECUTION_SUCCESS;
if (i != EXECUTION_SUCCESS)
return (i);
free (pushd_directory_list[--directory_list_offset]);
}
else
{
/* Since an offset other than the top directory was specified,
remove that directory from the list and shift the remainder
of the list into place. */
i = (direction == '+') ? directory_list_offset - which : which;
free (pushd_directory_list[i]);
directory_list_offset--;
/* Shift the remainder of the list into place. */
for (; i < directory_list_offset; i++)
pushd_directory_list[i] = pushd_directory_list[i + 1];
}
dirs_builtin ((WORD_LIST *)NULL);
return (EXECUTION_SUCCESS);
}
/* Print the current list of directories on the directory stack. */
int
dirs_builtin (list)
WORD_LIST *list;
{
int flags, desired_index, index_flag, vflag;
long i;
char *temp, *w;
for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next)
{
if (ISOPTION (list->word->word, 'l'))
{
flags |= LONGFORM;
}
else if (ISOPTION (list->word->word, 'c'))
{
flags |= CLEARSTAK;
}
else if (ISOPTION (list->word->word, 'v'))
{
vflag |= 2;
}
else if (ISOPTION (list->word->word, 'p'))
{
vflag |= 1;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (*list->word->word == '+' || *list->word->word == '-')
{
int sign;
if (legal_number (w = list->word->word + 1, &i) == 0)
{
builtin_error (m_badarg, list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
sign = (*list->word->word == '+') ? 1 : -1;
desired_index = get_dirstack_index (i, sign, &index_flag);
}
else
{
bad_option (list->word->word);
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
if (flags & CLEARSTAK)
{
clear_directory_stack ();
return (EXECUTION_SUCCESS);
}
if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
{
pushd_error (directory_list_offset, w);
return (EXECUTION_FAILURE);
}
#define DIRSTACK_FORMAT(temp) \
(flags & LONGFORM) ? temp : polite_directory_format (temp)
/* The first directory printed is always the current working directory. */
if (index_flag == 0 || (index_flag == 1 && desired_index == 0))
{
temp = get_working_directory ("dirs");
if (temp == 0)
temp = savestring ("<no current directory>");
if (vflag & 2)
printf ("%2d %s", 0, DIRSTACK_FORMAT (temp));
else
printf ("%s", DIRSTACK_FORMAT (temp));
free (temp);
if (index_flag)
{
putchar ('\n');
return EXECUTION_SUCCESS;
}
}
#define DIRSTACK_ENTRY(i) \
(flags & LONGFORM) ? pushd_directory_list[i] \
: polite_directory_format (pushd_directory_list[i])
/* Now print the requested directory stack entries. */
if (index_flag)
{
if (vflag & 2)
printf ("%2d %s", directory_list_offset - desired_index,
DIRSTACK_ENTRY (desired_index));
else
printf ("%s", DIRSTACK_ENTRY (desired_index));
}
else
for (i = directory_list_offset - 1; i >= 0; i--)
if (vflag >= 2)
printf ("\n%2d %s", directory_list_offset - (int)i, DIRSTACK_ENTRY (i));
else
printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i));
putchar ('\n');
fflush (stdout);
return (EXECUTION_SUCCESS);
}
static void
pushd_error (offset, arg)
int offset;
char *arg;
{
if (offset == 0)
builtin_error ("directory stack empty");
else if (arg)
builtin_error ("%s: bad directory stack index", arg);
else
builtin_error ("bad directory stack index");
}
static void
clear_directory_stack ()
{
register int i;
for (i = 0; i < directory_list_offset; i++)
free (pushd_directory_list[i]);
directory_list_offset = 0;
}
/* Switch to the directory in NAME. This uses the cd_builtin to do the work,
so if the result is EXECUTION_FAILURE then an error message has already
been printed. */
static int
cd_to_string (name)
char *name;
{
WORD_LIST *tlist;
int result;
tlist = make_word_list (make_word (name), NULL);
result = cd_builtin (tlist);
dispose_words (tlist);
return (result);
}
static int
change_to_temp (temp)
char *temp;
{
int tt;
tt = temp ? cd_to_string (temp) : EXECUTION_FAILURE;
if (tt == EXECUTION_SUCCESS)
dirs_builtin ((WORD_LIST *)NULL);
return (tt);
}
static void
add_dirstack_element (dir)
char *dir;
{
int j;
if (directory_list_offset == directory_list_size)
{
j = (directory_list_size += 10) * sizeof (char *);
pushd_directory_list = (char **)xrealloc (pushd_directory_list, j);
}
pushd_directory_list[directory_list_offset++] = dir;
}
static int
get_dirstack_index (ind, sign, indexp)
int ind, sign, *indexp;
{
if (indexp)
*indexp = sign > 0 ? 1 : 2;
/* dirs +0 prints the current working directory. */
/* dirs -0 prints last element in directory stack */
if (ind == 0 && sign > 0)
return 0;
else if (ind == directory_list_offset)
{
if (indexp)
*indexp = sign > 0 ? 2 : 1;
return 0;
}
else
return (sign > 0 ? directory_list_offset - ind : ind);
}
char *
get_dirstack_element (ind, sign)
int ind, sign;
{
int i;
i = get_dirstack_index (ind, sign, (int *)NULL);
return (i < 0 || i > directory_list_offset) ? (char *)NULL
: pushd_directory_list[i];
}
void
set_dirstack_element (ind, sign, value)
int ind, sign;
char *value;
{
int i;
i = get_dirstack_index (ind, sign, (int *)NULL);
if (ind == 0 || i < 0 || i > directory_list_offset)
return;
free (pushd_directory_list[i]);
pushd_directory_list[i] = savestring (value);
}
WORD_LIST *
get_directory_stack ()
{
register int i;
WORD_LIST *ret;
char *d, *t;
for (ret = (WORD_LIST *)NULL, i = 0; i < directory_list_offset; i++)
{
d = polite_directory_format (pushd_directory_list[i]);
ret = make_word_list (make_word (d), ret);
}
/* Now the current directory. */
d = get_working_directory ("dirstack");
i = 0; /* sentinel to decide whether or not to free d */
if (d == 0)
d = ".";
else
{
t = polite_directory_format (d);
/* polite_directory_format sometimes returns its argument unchanged.
If it does not, we can free d right away. If it does, we need to
mark d to be deleted later. */
if (t != d)
{
free (d);
d = t;
}
else /* t == d, so d is what we want */
i = 1;
}
ret = make_word_list (make_word (d), ret);
if (i)
free (d);
return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */
}
#endif /* PUSHD_AND_POPD */

View file

@ -23,101 +23,170 @@ $PRODUCES read.c
$BUILTIN read
$FUNCTION read_builtin
$SHORT_DOC read [-r] [name ...]
$SHORT_DOC read [-r] [-p prompt] [-a array] [-e] [name ...]
One line is read from the standard input, and the first word is
assigned to the first NAME, the second word to the second NAME, etc.
with leftover words assigned to the last NAME. Only the characters
assigned to the first NAME, the second word to the second NAME, and so
on, with leftover words assigned to the last NAME. Only the characters
found in $IFS are recognized as word delimiters. The return code is
zero, unless end-of-file is encountered. If the -r option is given,
this signifies `raw' input, and backslash processing is disabled.
zero, unless end-of-file is encountered. If no NAMEs are supplied, the
line read is stored in the REPLY variable. If the -r option is given,
this signifies `raw' input, and backslash escaping is disabled. If
the `-p' option is supplied, the string supplied as an argument is
output without a trailing newline before attempting to read. If -a is
supplied, the words read are assigned to sequential indices of ARRAY,
starting at zero. If -e is supplied and the shell is interactive,
readline is used to obtain the line.
$END
#include <config.h>
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
#define issep(c) (strchr (ifs_chars, (c)) != (char *)0)
#if defined (READLINE)
#include "../bashline.h"
#include <readline/readline.h>
#endif
static int stream_close ();
#define issep(c) (strchr (ifs_chars, (c)))
extern int interrupt_immediately;
#if defined (READLINE)
static char *edit_line ();
#endif
static SHELL_VAR *bind_read_variable ();
/* Read the value of the shell variables whose names follow.
The reading is done from the current input stream, whatever
that may be. Successive words of the input line are assigned
to the variables mentioned in LIST. The last variable in LIST
gets the remainder of the words on the line. If no variables
are mentioned in LIST, then the default variable is $REPLY.
S. R. Bourne's shell complains if you don't name a variable
to receive the stuff that is read. GNU's shell doesn't. This
allows you to let the user type random things. */
are mentioned in LIST, then the default variable is $REPLY. */
int
read_builtin (list)
WORD_LIST *list;
{
register char *varname;
int size, c, i, fildes, raw_mode, pass_next, saw_escape, retval;
char *input_string, *orig_input_string, *ifs_chars, *t;
FILE *input_stream;
int size, i, raw, pass_next, saw_escape, eof, opt, retval, edit;
char c;
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
char *e, *t, *t1;
SHELL_VAR *var;
#if defined (ARRAY_VARS)
WORD_LIST *alist;
#endif
#if defined (READLINE)
char *rlbuf;
int rlind;
#endif
i = 0; /* Index into the string that we are reading. */
raw_mode = 0; /* Not reading raw input be default. */
raw = edit = 0; /* Not reading raw input by default. */
arrayname = prompt = (char *)NULL;
while (list)
#if defined (READLINE)
rlbuf = (char *)0;
rlind = 0;
#endif
reset_internal_getopt ();
while ((opt = internal_getopt (list, "erp:a:")) != -1)
{
if (ISOPTION (list->word->word, 'r'))
{
raw_mode = 1;
list = list->next;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
switch (opt)
{
case 'r':
raw = 1;
break;
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_error ("usage: read [-r] [name ...]");
case 'p':
prompt = list_optarg;
break;
case 'e':
#if defined (READLINE)
edit = 1;
#endif
break;
#if defined (ARRAY_VARS)
case 'a':
arrayname = list_optarg;
break;
#endif
default:
builtin_usage ();
return (EX_USAGE);
}
else
break;
}
/* We need unbuffered input from stdin. So we make a new stream with
the same file descriptor as stdin, then unbuffer it. */
fildes = dup (fileno (stdin));
if (fildes == -1)
return (EXECUTION_FAILURE);
input_stream = fdopen (fildes, "r");
if (!input_stream)
{
close (fildes);
return (EXECUTION_FAILURE);
}
list = loptend;
/* IF IFS is unset, we use the default of " \t\n". */
var = find_variable ("IFS");
ifs_chars = var ? value_cell (var) : " \t\n";
input_string = xmalloc (size = 128);
if (ifs_chars == 0) /* XXX */
ifs_chars = ""; /* XXX */
setbuf (input_stream, (char *)NULL);
input_string = xmalloc (size = 128);
begin_unwind_frame ("read_builtin");
add_unwind_protect (xfree, input_string);
add_unwind_protect (stream_close, input_stream);
#if defined (READLINE)
add_unwind_protect (xfree, rlbuf);
#endif
interrupt_immediately++;
/* If the -p or -e flags were given, but input is not coming from the
terminal, turn them off. */
if ((prompt || edit) && (isatty (0) == 0))
{
prompt = (char *)NULL;
edit = 0;
}
if (prompt && edit == 0)
{
fprintf (stderr, "%s", prompt);
fflush (stderr);
}
pass_next = 0; /* Non-zero signifies last char was backslash. */
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
while ((c = getc (input_stream)) != EOF)
for (eof = 0;;)
{
#if defined (READLINE)
if (edit)
{
if (rlbuf && rlbuf[rlind] == '\0')
{
free (rlbuf);
rlbuf = (char *)0;
}
if (rlbuf == 0)
{
rlbuf = edit_line (prompt ? prompt : "");
rlind = 0;
}
if (rlbuf == 0)
{
eof = 1;
break;
}
c = rlbuf[rlind++];
}
else
#endif
if (read (0, &c, 1) != 1)
{
eof = 1;
break;
}
if (i + 2 >= size)
input_string = xrealloc (input_string, size += 128);
@ -133,7 +202,7 @@ read_builtin (list)
continue;
}
if (c == '\\' && !raw_mode)
if (c == '\\' && raw == 0)
{
pass_next++;
saw_escape++;
@ -157,15 +226,31 @@ read_builtin (list)
interrupt_immediately--;
discard_unwind_frame ("read_builtin");
fclose (input_stream);
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
if (c == EOF)
#if defined (ARRAY_VARS)
/* If -a was given, take the string read, break it into a list of words,
an assign them to `arrayname' in turn. */
if (arrayname)
{
retval = EXECUTION_FAILURE;
/* input_string[0] = '\0'; */
var = find_variable (arrayname);
if (var == 0)
var = make_new_array_variable (arrayname);
else if (array_p (var) == 0)
var = convert_var_to_array (var);
empty_array (array_cell (var));
alist = list_string (input_string, ifs_chars, 0);
if (alist)
{
assign_array_var_from_word_list (var, alist);
dispose_words (alist);
}
free (input_string);
return (retval);
}
else
retval = EXECUTION_SUCCESS;
#endif /* ARRAY_VARS */
if (!list)
{
@ -179,98 +264,140 @@ read_builtin (list)
var = bind_variable ("REPLY", input_string);
var->attributes &= ~att_invisible;
free (input_string);
return (retval);
}
else
/* This code implements the Posix.2 spec for splitting the words
read and assigning them to variables. */
orig_input_string = input_string;
/* Remove IFS white space at the beginning of the input string. If
$IFS is null, no field splitting is performed. */
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
;
input_string = t;
for (; list->next; list = list->next)
{
/* This code implements the Posix.2 spec for splitting the words
read and assigning them to variables. If $IFS is unset, we
use the default value of " \t\n". */
orig_input_string = input_string;
/* Remove IFS white space at the beginning of the input string. If
$IFS is null, no field splitting is performed. */
for (t = input_string; *ifs_chars && spctabnl (*t) && issep (*t); t++)
;
input_string = t;
for (; list->next; list = list->next)
varname = list->word->word;
#if defined (ARRAY_VARS)
if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
#else
if (legal_identifier (varname) == 0)
#endif
{
char *e, *t1;
varname = list->word->word;
if (legal_identifier (varname) == 0)
{
builtin_error ("%s: not a legal variable name", varname);
free (orig_input_string);
return (EXECUTION_FAILURE);
}
/* If there are more variables than words read from the input,
the remaining variables are set to the empty string. */
if (*input_string)
{
/* This call updates INPUT_STRING. */
t = get_word_from_string (&input_string, ifs_chars, &e);
if (t)
*e = '\0';
/* Don't bother to remove the CTLESC unless we added one
somewhere while reading the string. */
if (t && saw_escape)
{
t1 = dequote_string (t);
var = bind_variable (varname, t1);
free (t1);
}
else
var = bind_variable (varname, t);
}
else
{
t = (char *)0;
var = bind_variable (varname, "");
}
stupidly_hack_special_variables (varname);
var->attributes &= ~att_invisible;
if (t)
free (t);
}
if (legal_identifier (list->word->word) == 0)
{
builtin_error ("%s: not a legal variable name", list->word->word);
builtin_error ("`%s': not a valid identifier", varname);
free (orig_input_string);
return (EXECUTION_FAILURE);
}
/* This has to be done this way rather than using string_list
and list_string because Posix.2 says that the last variable gets the
remaining words and their intervening separators. */
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars,
saw_escape);
if (saw_escape)
/* If there are more variables than words read from the input,
the remaining variables are set to the empty string. */
if (*input_string)
{
t = dequote_string (input_string);
var = bind_variable (list->word->word, t);
free (t);
/* This call updates INPUT_STRING. */
t = get_word_from_string (&input_string, ifs_chars, &e);
if (t)
*e = '\0';
/* Don't bother to remove the CTLESC unless we added one
somewhere while reading the string. */
if (t && saw_escape)
{
t1 = dequote_string (t);
var = bind_read_variable (varname, t1);
free (t1);
}
else
var = bind_read_variable (varname, t);
}
else
var = bind_variable (list->word->word, input_string);
stupidly_hack_special_variables (list->word->word);
{
t = (char *)0;
var = bind_read_variable (varname, "");
}
FREE (t);
if (var == 0)
{
free (orig_input_string);
return (EXECUTION_FAILURE);
}
stupidly_hack_special_variables (varname);
var->attributes &= ~att_invisible;
free (orig_input_string);
}
/* Now assign the rest of the line to the last variable argument. */
#if defined (ARRAY_VARS)
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
#else
if (legal_identifier (list->word->word) == 0)
#endif
{
builtin_error ("`%s': not a valid identifier", list->word->word);
free (orig_input_string);
return (EXECUTION_FAILURE);
}
/* This has to be done this way rather than using string_list
and list_string because Posix.2 says that the last variable gets the
remaining words and their intervening separators. */
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
if (saw_escape)
{
t = dequote_string (input_string);
var = bind_read_variable (list->word->word, t);
free (t);
}
else
var = bind_read_variable (list->word->word, input_string);
stupidly_hack_special_variables (list->word->word);
if (var)
var->attributes &= ~att_invisible;
free (orig_input_string);
return (retval);
}
/* This way I don't have to know whether fclose () is a
function or a macro. */
static int
stream_close (file)
FILE *file;
static SHELL_VAR *
bind_read_variable (name, value)
char *name, *value;
{
return (fclose (file));
#if defined (ARRAY_VARS)
if (valid_array_reference (name) == 0)
{
if (legal_identifier (name) == 0)
{
builtin_error ("`%s': not a valid identifier", name);
return ((SHELL_VAR *)NULL);
}
return (bind_variable (name, value));
}
else
return (do_array_element_assignment (name, value));
#else
return bind_variable (name, value);
#endif
}
#if defined (READLINE)
static char *
edit_line (p)
char *p;
{
char *ret;
int len;
if (!bash_readline_initialized)
initialize_readline ();
ret = readline (p);
if (ret == 0)
return ret;
len = strlen (ret);
ret = xrealloc (ret, len + 2);
ret[len++] = '\n';
ret[len] = '\0';
return ret;
}
#endif

View file

@ -43,6 +43,15 @@ in the variable REPLY. COMMANDS are executed after each selection
until a break or return command is executed.
$END
$BUILTIN time
$SHORT_DOC time [-p] PIPELINE
Execute PIPELINE and print a summary of the real time, user CPU time,
and system CPU time spent executing PIPELINE when it terminates.
The return status is the return status of PIPELINE. The `-p' option
prints the timing summary in a slightly different format. This uses
the value of the TIMEFORMAT variable as the output format.
$END
$BUILTIN case
$SHORT_DOC case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
Selectively execute COMMANDS based upon WORD matching PATTERN. The
@ -97,10 +106,12 @@ $END
$BUILTIN variables
$DOCNAME variable_help
$SHORT_DOC variables - Some variable names and meanings
BASH_VERSION The version numbers of this Bash.
BASH_VERSION Version information for this Bash.
CDPATH A colon separated list of directories to search
when the argument to `cd' is not found in the current
directory.
GLOBIGNORE A colon-separated list of patterns describing filenames to
be ignored by pathname expansion.
#if defined (HISTORY)
HISTFILE The name of the file where your command history is stored.
HISTFILESIZE The maximum number of lines this file can contain.
@ -108,22 +119,29 @@ HISTSIZE The maximum number of history lines that a running
shell can access.
#endif /* HISTORY */
HOME The complete pathname to your login directory.
HOSTNAME The name of the current host.
HOSTTYPE The type of CPU this version of Bash is running under.
IGNOREEOF Controls the action of the shell on receipt of an EOF
character as the sole input. If set, then the value
of it is the number of EOF characters that can be seen
in a row on an empty line before the shell will exit
(default 10). When unset, EOF signifies the end of input.
MACHTYPE A string describing the current system Bash is running on.
MAILCHECK How often, in seconds, Bash checks for new mail.
MAILPATH A colon-separated list of filenames which Bash checks
for new mail.
OSTYPE The version of Unix this version of Bash is running on.
PATH A colon-separated list of directories to search when
looking for commands.
PROMPT_COMMAND A command to be executed before the printing of each
primary prompt.
PS1 The primary prompt string.
PS2 The secondary prompt string.
PWD The full pathname of the current directory.
SHELLOPTS A colon-separated list of enabled shell options.
TERM The name of the current terminal type.
TIMEFORMAT The output format for timing statistics displayed by the
`time' reserved word.
auto_resume Non-null means a command word appearing on a line by
itself is first looked for in the list of currently
stopped jobs. If found there, that job is foregrounded.
@ -133,9 +151,6 @@ auto_resume Non-null means a command word appearing on a line by
match a substring of the job. Any other value means that
the command must be a prefix of a stopped job.
#if defined (HISTORY)
command_oriented_history
Non-null means to save multiple-line commands together on
a single history line.
# if defined (BANG_HISTORY)
histchars Characters controlling history expansion and quick
substitution. The first character is the history
@ -143,12 +158,7 @@ histchars Characters controlling history expansion and quick
the `quick substitution' character, usually `^'. The
third is the `history comment' character, usually `#'.
# endif /* BANG_HISTORY */
HISTCONTROL Set to a value of `ignorespace', it means don't enter
lines which begin with a space or tab on the history
list. Set to a value of `ignoredups', it means don't
enter lines which match the last entered line. Set to
`ignoreboth' means to combine the two options. Unset,
or set to any other value than those above means to save
all lines on the history list.
HISTIGNORE A colon-separated list of patterns used to decide which
command should be saved on the history list.
#endif /* HISTORY */
$END

View file

@ -29,11 +29,17 @@ Causes a function to exit with the return value specified by N. If N
is omitted, the return status is that of the last command.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "common.h"
extern int last_command_exit_value;
extern int return_catch_flag, return_catch_value;
extern jmp_buf return_catch;
/* If we are executing a user-defined function then exit with the value
specified as an argument. if no argument is given, then the last
@ -42,16 +48,13 @@ int
return_builtin (list)
WORD_LIST *list;
{
return_catch_value = get_numeric_arg (list);
if (!list)
return_catch_value = last_command_exit_value;
return_catch_value = list ? get_numeric_arg (list) : last_command_exit_value;
if (return_catch_flag)
longjmp (return_catch, 1);
else
{
builtin_error ("Can only `return' from a function");
builtin_error ("can only `return' from a function or sourced script");
return (EXECUTION_FAILURE);
}
}

View file

@ -21,62 +21,79 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES set.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
#if defined (READLINE)
# include "../input.h"
# include "../bashline.h"
# include <readline/readline.h>
#endif
#if defined (HISTORY)
# include "../bashhist.h"
#endif
extern int interactive;
extern int noclobber, no_brace_expansion, posixly_correct;
extern int noclobber, posixly_correct, ignoreeof, eof_encountered_limit;
#if defined (READLINE)
extern int rl_editing_mode, no_line_editing;
#endif /* READLINE */
#define USAGE_STRING "set [--abefhknotuvxldHCP] [-o option] [arg ...]"
$BUILTIN set
$FUNCTION set_builtin
$SHORT_DOC set [--abefhknotuvxldHCP] [-o option] [arg ...]
$SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
-a Mark variables which are modified or created for export.
-b Notify of job termination immediately.
-e Exit immediately if a command exits with a non-zero status.
-f Disable file name generation (globbing).
-h Locate and remember function commands as functions are
defined. Function commands are normally looked up when
the function is executed.
-h Remember the location of commands as they are looked up.
-i Force the shell to be an "interactive" one. Interactive shells
always read `~/.bashrc' on startup.
-k All keyword arguments are placed in the environment for a
-k All assignment arguments are placed in the environment for a
command, not just those that precede the command name.
-m Job control is enabled.
-n Read commands but do not execute them.
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand the shell will perform brace expansion
braceexpand same as -B
#if defined (READLINE)
emacs use an emacs-style line editing interface
#endif /* READLINE */
errexit same as -e
hashall same as -h
#if defined (BANG_HISTORY)
histexpand same as -H
#endif /* BANG_HISTORY */
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
keyword same as -k
monitor same as -m
noclobber disallow redirection to existing files
noclobber same as -C
noexec same as -n
noglob same as -f
nohash same as -d
notify save as -b
nounset same as -u
physical same as -P
posix change the behavior of bash where the default
operation differs from the 1003.2 standard to
match the standard
privileged same as -p
onecmd same as -t
physical same as -P
posix change the behavior of bash where the default
operation differs from the 1003.2 standard to
match the standard
privileged same as -p
verbose same as -v
#if defined (READLINE)
vi use a vi-style line editing interface
@ -85,15 +102,14 @@ $SHORT_DOC set [--abefhknotuvxldHCP] [-o option] [arg ...]
-p Turned on whenever the real and effective user ids do not match.
Disables processing of the $ENV file and importing of shell
functions. Turning this option off causes the effective uid and
gid to be set to the real uid and gid.
gid to be set to the real uid and gid.
-t Exit after reading and executing one command.
-u Treat unset variables as an error when substituting.
-v Print shell input lines as they are read.
-x Print commands and their arguments as they are executed.
-l Save and restore the binding of the NAME in a FOR command.
-d Disable the hashing of commands that are looked up for execution.
Normally, commands are remembered in a hash table, and once
found, do not have to be looked up again.
#if defined (BRACE_EXPANSION)
-B the shell will perform brace expansion
#endif /* BRACE_EXPANSION */
#if defined (BANG_HISTORY)
-H Enable ! style history substitution. This flag is on
by default.
@ -110,6 +126,20 @@ parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
$END
static int set_ignoreeof ();
#if defined (READLINE)
static int set_edit_mode ();
static int get_edit_mode ();
#endif
#if defined (HISTORY)
static int bash_set_history ();
#endif
static char *on = "on";
static char *off = "off";
/* An a-list used to match long options for set -o to the corresponding
option letter. */
struct {
@ -117,201 +147,354 @@ struct {
int letter;
} o_options[] = {
{ "allexport", 'a' },
#if defined (BRACE_EXPANSION)
{ "braceexpand",'B' },
#endif
{ "errexit", 'e' },
{ "hashall", 'h' },
#if defined (BANG_HISTORY)
{ "histexpand", 'H' },
#endif /* BANG_HISTORY */
{ "keyword", 'k' },
{ "monitor", 'm' },
{ "noclobber", 'C' },
{ "noexec", 'n' },
{ "noglob", 'f' },
{ "nohash", 'd' },
#if defined (JOB_CONTROL)
{ "notify", 'b' },
#endif /* JOB_CONTROL */
{"nounset", 'u' },
{"physical", 'P' },
{"privileged", 'p' },
{"verbose", 'v' },
{"xtrace", 'x' },
{(char *)NULL, 0},
{ "nounset", 'u' },
{ "onecmd", 't' },
{ "physical", 'P' },
{ "privileged", 'p' },
{ "verbose", 'v' },
{ "xtrace", 'x' },
{(char *)NULL, 0 },
};
struct {
char *name;
int *variable;
Function *set_func;
Function *get_func;
} binary_o_options[] = {
#if defined (HISTORY)
{ "history", &remember_on_history, bash_set_history, (Function *)NULL },
#endif
{ "ignoreeof", &ignoreeof, set_ignoreeof, (Function *)NULL },
{ "interactive-comments", &interactive_comments, (Function *)NULL, (Function *)NULL },
{ "posix", &posixly_correct, (Function *)NULL, (Function *)NULL },
#if defined (READLINE)
{ "emacs", (int *)NULL, set_edit_mode, get_edit_mode },
{ "vi", (int *)NULL, set_edit_mode, get_edit_mode },
#endif
{ (char *)NULL, (int *)NULL }
};
#define GET_BINARY_O_OPTION_VALUE(i, name) \
((binary_o_options[i].get_func) ? (*binary_o_options[i].get_func) (name) \
: (*binary_o_options[i].variable))
#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
((binary_o_options[i].set_func) ? (*binary_o_options[i].set_func) (onoff, name) \
: (*binary_o_options[i].variable = (onoff == FLAG_ON)))
int
minus_o_option_value (name)
char *name;
{
register int i;
int *on_or_off;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (name, o_options[i].name))
{
on_or_off = find_flag (o_options[i].letter);
return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
}
}
for (i = 0; binary_o_options[i].name; i++)
{
if (STREQ (name, binary_o_options[i].name))
return (GET_BINARY_O_OPTION_VALUE (i, name));
}
return (-1);
}
#define MINUS_O_FORMAT "%-15s\t%s\n"
void
list_minus_o_opts ()
list_minus_o_opts (mode)
int mode;
{
register int i;
char *on = "on", *off = "off";
int *on_or_off, value;
printf (MINUS_O_FORMAT, "braceexpand", (no_brace_expansion == 0) ? on : off);
printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
printf (MINUS_O_FORMAT, "ignoreeof", on);
else
printf (MINUS_O_FORMAT, "ignoreeof", off);
printf (MINUS_O_FORMAT, "interactive-comments",
interactive_comments ? on : off);
printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
#if defined (READLINE)
if (no_line_editing)
for (value = i = 0; o_options[i].name; i++)
{
printf (MINUS_O_FORMAT, "emacs", off);
printf (MINUS_O_FORMAT, "vi", off);
}
else
{
/* Magic. This code `knows' how readline handles rl_editing_mode. */
printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
}
#endif /* READLINE */
for (i = 0; o_options[i].name; i++)
{
int *on_or_off, zero = 0;
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &zero;
printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
on_or_off = &value;
if (mode == -1 || mode == *on_or_off)
printf (MINUS_O_FORMAT, o_options[i].name, *on_or_off ? on : off);
}
for (i = 0; binary_o_options[i].name; i++)
{
value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name);
if (mode == -1 || mode == value)
printf (MINUS_O_FORMAT, binary_o_options[i].name, value ? on : off);
}
}
static void
minus_o_option_commands ()
{
register int i;
int *on_or_off, value;
for (value = i = 0; o_options[i].name; i++)
{
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &value;
printf ("set %co %s\n", *on_or_off ? '-' : '+', o_options[i].name);
}
for (i = 0; binary_o_options[i].name; i++)
{
value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name);
printf ("set %co %s\n", value ? '-' : '+', binary_o_options[i].name);
}
}
static int
set_ignoreeof (on_or_off, option_name)
int on_or_off;
char *option_name;
{
ignoreeof = on_or_off == FLAG_ON;
unbind_variable ("ignoreeof");
if (ignoreeof)
bind_variable ("IGNOREEOF", "10");
else
unbind_variable ("IGNOREEOF");
sv_ignoreeof ("IGNOREEOF");
return 0;
}
#if defined (READLINE)
/* Magic. This code `knows' how readline handles rl_editing_mode. */
static int
set_edit_mode (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int isemacs;
if (on_or_off == FLAG_ON)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
isemacs = rl_editing_mode == 1;
if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
}
return 1-no_line_editing;
}
static int
get_edit_mode (name)
char *name;
{
return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
: no_line_editing == 0 && rl_editing_mode == 0);
}
#endif /* READLINE */
#if defined (HISTORY)
static int
bash_set_history (on_or_off, option_name)
int on_or_off;
char *option_name;
{
if (on_or_off == FLAG_ON)
{
bash_history_enable ();
if (history_lines_this_session == 0)
load_history ();
}
else
bash_history_disable ();
return (1 - remember_on_history);
}
#endif
int
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int option_char = -1;
int option_char;
VFunction *set_func;
register int i;
if (STREQ (option_name, "braceexpand"))
for (i = 0; binary_o_options[i].name; i++)
{
if (on_or_off == FLAG_ON)
no_brace_expansion = 0;
else
no_brace_expansion = 1;
}
else if (STREQ (option_name, "noclobber"))
{
if (on_or_off == FLAG_ON)
bind_variable ("noclobber", "");
else
unbind_variable ("noclobber");
stupidly_hack_special_variables ("noclobber");
}
else if (STREQ (option_name, "ignoreeof"))
{
unbind_variable ("ignoreeof");
unbind_variable ("IGNOREEOF");
if (on_or_off == FLAG_ON)
bind_variable ("IGNOREEOF", "10");
stupidly_hack_special_variables ("IGNOREEOF");
}
#if defined (READLINE)
else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
{
if (on_or_off == FLAG_ON)
if (STREQ (option_name, binary_o_options[i].name))
{
rl_variable_bind ("editing-mode", option_name);
SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
return (EXECUTION_SUCCESS);
}
}
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
int isemacs = (rl_editing_mode == 1);
if ((isemacs && STREQ (option_name, "emacs")) ||
(!isemacs && STREQ (option_name, "vi")))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
else
builtin_error ("not in %s editing mode", option_name);
}
}
#endif /* READLINE */
else if (STREQ (option_name, "interactive-comments"))
interactive_comments = (on_or_off == FLAG_ON);
else if (STREQ (option_name, "posix"))
for (i = 0, option_char = -1, set_func = 0; o_options[i].name; i++)
{
posixly_correct = (on_or_off == FLAG_ON);
unbind_variable ("POSIXLY_CORRECT");
unbind_variable ("POSIX_PEDANTIC");
if (on_or_off == FLAG_ON)
{
bind_variable ("POSIXLY_CORRECT", "");
stupidly_hack_special_variables ("POSIXLY_CORRECT");
}
if (STREQ (option_name, o_options[i].name))
{
option_char = o_options[i].letter;
break;
}
}
else
if (option_char == -1)
{
register int i;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (option_name, o_options[i].name))
{
option_char = o_options[i].letter;
break;
}
}
if (option_char == -1)
{
builtin_error ("%s: unknown option name", option_name);
return (EXECUTION_FAILURE);
}
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
{
bad_option (option_name);
return (EXECUTION_FAILURE);
}
builtin_error ("%s: unknown option name", option_name);
return (EXECUTION_FAILURE);
}
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
{
bad_option (option_name);
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
static void
print_all_shell_variables ()
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
vars = all_shell_functions ();
if (vars)
{
print_var_list (vars);
free (vars);
}
}
void
set_shellopts ()
{
char *value;
int vsize, i, vptr, *ip;
SHELL_VAR *v;
for (vsize = i = 0; o_options[i].name; i++)
{
ip = find_flag (o_options[i].letter);
if (ip && *ip)
vsize += strlen (o_options[i].name) + 1;
}
for (i = 0; binary_o_options[i].name; i++)
if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
vsize += strlen (binary_o_options[i].name) + 1;
value = xmalloc (vsize + 1);
for (i = vptr = 0; o_options[i].name; i++)
{
ip = find_flag (o_options[i].letter);
if (ip && *ip)
{
strcpy (value + vptr, o_options[i].name);
vptr += strlen (o_options[i].name);
value[vptr++] = ':';
}
}
for (i = 0; binary_o_options[i].name; i++)
if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
{
strcpy (value + vptr, binary_o_options[i].name);
vptr += strlen (binary_o_options[i].name);
value[vptr++] = ':';
}
value[--vptr] = '\0'; /* cut off trailing colon */
v = find_variable ("SHELLOPTS");
if (v)
v->attributes &= ~att_readonly;
v = bind_variable ("SHELLOPTS", value);
v->attributes |= att_readonly;
free (value);
}
void
parse_shellopts (value)
char *value;
{
char *vname;
int vptr;
vptr = 0;
while (vname = extract_colon_unit (value, &vptr))
{
set_minus_o_option (FLAG_ON, vname);
free (vname);
}
}
void
initialize_shell_options ()
{
char *temp;
/* set up any shell options we may have inherited. */
if (temp = get_string_value ("SHELLOPTS"))
parse_shellopts (temp);
/* Set up the $SHELLOPTS variable. */
set_shellopts ();
}
/* Set some flags from the word values in the input list. If LIST is empty,
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
int
set_builtin (list)
WORD_LIST *list;
{
int on_or_off, flag_name, force_assignment = 0;
int on_or_off, flag_name, force_assignment, opts_changed;
WORD_LIST *l;
register char *arg;
if (!list)
if (list == 0)
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
vars = all_shell_functions ();
if (vars)
{
print_var_list (vars);
free (vars);
}
print_all_shell_variables ();
return (EXECUTION_SUCCESS);
}
/* Check validity of flag arguments. */
if (*list->word->word == '-' || *list->word->word == '+')
{
register char *arg;
WORD_LIST *save_list = list;
while (list && (arg = list->word->word))
for (l = list; l && (arg = l->word->word); l = l->next)
{
char c;
@ -319,8 +502,7 @@ set_builtin (list)
break;
/* `-' or `--' signifies end of flag arguments. */
if (arg[0] == '-' &&
(!arg[1] || (arg[1] == '-' && !arg[2])))
if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
break;
while (c = *++arg)
@ -331,30 +513,28 @@ set_builtin (list)
s[0] = c; s[1] = '\0';
bad_option (s);
if (c == '?')
printf ("usage: %s\n", USAGE_STRING);
builtin_usage ();
return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
}
list = list->next;
}
list = save_list;
}
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
while (list)
for (force_assignment = opts_changed = 0; list; )
{
char *string = list->word->word;
arg = list->word->word;
/* If the argument is `--' or `-' then signal the end of the list
and remember the remaining arguments. */
if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
{
list = list->next;
/* `set --' unsets the positional parameters. */
if (string[1] == '-')
if (arg[1] == '-')
force_assignment = 1;
/* Until told differently, the old shell behaviour of
@ -364,20 +544,19 @@ set_builtin (list)
{
change_flag ('x', '+');
change_flag ('v', '+');
opts_changed = 1;
}
break;
}
if ((on_or_off = *string) &&
(on_or_off == '-' || on_or_off == '+'))
if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
{
int i = 1;
while (flag_name = string[i++])
while (flag_name = *++arg)
{
if (flag_name == '?')
{
printf ("usage: %s\n", USAGE_STRING);
builtin_usage ();
return (EXECUTION_SUCCESS);
}
else if (flag_name == 'o') /* -+o option-name */
@ -387,36 +566,47 @@ set_builtin (list)
opt = list->next;
if (!opt)
if (opt == 0)
{
list_minus_o_opts ();
if (on_or_off == '-')
list_minus_o_opts (-1);
else
minus_o_option_commands ();
continue;
}
option_name = opt->word->word;
if (!option_name || !*option_name || (*option_name == '-'))
if (option_name == 0 || *option_name == '\0' ||
*option_name == '-' || *option_name == '+')
{
list_minus_o_opts ();
if (on_or_off == '-')
list_minus_o_opts (-1);
else
minus_o_option_commands ();
continue;
}
list = list->next; /* Skip over option name. */
opts_changed = 1;
if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
return (EXECUTION_FAILURE);
}
else
{
if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
char opt[3];
opt[0] = on_or_off;
opt[1] = flag_name;
opt[2] = '\0';
bad_option (opt);
set_shellopts ();
return (EXECUTION_FAILURE);
}
}
else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
char opt[3];
opt[0] = on_or_off;
opt[1] = flag_name;
opt[2] = '\0';
bad_option (opt);
builtin_usage ();
set_shellopts ();
return (EXECUTION_FAILURE);
}
opts_changed = 1;
}
}
else
@ -429,6 +619,9 @@ set_builtin (list)
/* Assigning $1 ... $n */
if (list || force_assignment)
remember_args (list, 1);
/* Set up new value of $SHELLOPTS */
if (opts_changed)
set_shellopts ();
return (EXECUTION_SUCCESS);
}
@ -443,13 +636,17 @@ function. Some variables (such as PATH and IFS) cannot be unset; also
see readonly.
$END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
int
unset_builtin (list)
WORD_LIST *list;
{
int unset_function = 0, unset_variable = 0, opt;
int any_failed = 0;
int unset_function, unset_variable, unset_array, opt, any_failed;
char *name;
unset_function = unset_variable = unset_array = any_failed = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fv")) != -1)
{
@ -462,7 +659,8 @@ unset_builtin (list)
unset_variable = 1;
break;
default:
return (EXECUTION_FAILURE);
builtin_usage ();
return (EX_USAGE);
}
}
@ -476,53 +674,69 @@ unset_builtin (list)
while (list)
{
SHELL_VAR *var;
int tem;
#if defined (ARRAY_VARS)
char *t;
#endif
name = list->word->word;
if (!unset_function &&
find_name_in_list (name, non_unsettable_vars) > -1)
#if defined (ARRAY_VARS)
if (!unset_function && valid_array_reference (name))
{
t = strchr (name, '[');
*t++ = '\0';
unset_array++;
}
#endif
var = unset_function ? find_function (name) : find_variable (name);
if (var && !unset_function && non_unsettable_p (var))
{
builtin_error ("%s: cannot unset", name);
any_failed++;
NEXT_VARIABLE ();
}
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error ("%s: cannot unset: readonly %s",
name, unset_function ? "function" : "variable");
NEXT_VARIABLE ();
}
/* Unless the -f option is supplied, the name refers to a variable. */
#if defined (ARRAY_VARS)
if (var && unset_array)
{
if (array_p (var) == 0)
{
builtin_error ("%s: not an array variable", name);
NEXT_VARIABLE ();
}
else
tem = unbind_array_element (var, t);
}
else
{
SHELL_VAR *var;
int tem;
#endif /* ARRAY_VARS */
tem = makunbound (name, unset_function ? shell_functions : shell_variables);
var = unset_function ? find_function (name) : find_variable (name);
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if (tem == -1 && !unset_function && !unset_variable)
tem = makunbound (name, shell_functions);
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error ("%s: cannot unset: readonly %s",
name, unset_function ? "function" : "variable");
any_failed++;
list = list->next;
continue;
}
if (tem == -1)
any_failed++;
else if (!unset_function)
stupidly_hack_special_variables (name);
/* Unless the -f option is supplied, the name refers to a
variable. */
tem = makunbound
(name, unset_function ? shell_functions : shell_variables);
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if ((tem == -1) && !unset_function && !unset_variable)
tem = makunbound (name, shell_functions);
if (tem == -1)
any_failed++;
else if (!unset_function)
stupidly_hack_special_variables (name);
}
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}

View file

@ -21,6 +21,15 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES setattr.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
@ -30,7 +39,7 @@ extern char *this_command_name;
$BUILTIN export
$FUNCTION export_builtin
$SHORT_DOC export [-n] [-f] [name ...] or export -p
$SHORT_DOC export [-nf] [name ...] or export -p
NAMEs are marked for automatic export to the environment of
subsequently executed commands. If the -f option is given,
the NAMEs refer to functions. If no NAMEs are given, or if `-p'
@ -45,46 +54,51 @@ $END
print all such variables. An argument of `-n' says to remove the
exported attribute from variables named in LIST. An argument of
-f indicates that the names present in LIST refer to functions. */
int
export_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_exported));
return (set_or_show_attributes (list, att_exported, 0));
}
$BUILTIN readonly
$FUNCTION readonly_builtin
$SHORT_DOC readonly [-n] [-f] [name ...] or readonly -p
$SHORT_DOC readonly [-anf] [name ...] or readonly -p
The given NAMEs are marked readonly and the values of these NAMEs may
not be changed by subsequent assignment. If the -f option is given,
then functions corresponding to the NAMEs are so marked. If no
arguments are given, or if `-p' is given, a list of all readonly names
is printed. An argument of `-n' says to remove the readonly property
from subsequent NAMEs. An argument of `--' disables further option
from subsequent NAMEs. The `-a' option means to treat each NAME as
an array variable. An argument of `--' disables further option
processing.
$END
/* For each variable name in LIST, make that variable readonly. Given an
empty LIST, print out all existing readonly variables. */
int
readonly_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_readonly));
return (set_or_show_attributes (list, att_readonly, 0));
}
/* For each variable name in LIST, make that variable have the specified
ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
remaining names in LIST. */
int
set_or_show_attributes (list, attribute)
set_or_show_attributes (list, attribute, nodefs)
register WORD_LIST *list;
int attribute;
int attribute, nodefs;
{
register SHELL_VAR *var;
int assign, undo = 0, functions_only = 0, any_failed = 0, opt;
int assign, undo, functions_only, arrays_only, any_failed, assign_error, opt;
char *name;
undo = functions_only = arrays_only = any_failed = assign_error = 0;
/* Read arguments from the front of the list. */
reset_internal_getopt ();
while ((opt = internal_getopt (list, "nfp")) != -1)
while ((opt = internal_getopt (list, "anfp")) != -1)
{
switch (opt)
{
@ -94,10 +108,15 @@ set_or_show_attributes (list, attribute)
case 'f':
functions_only = 1;
break;
#if defined (ARRAY_VARS)
case 'a':
arrays_only = 1;
break;
#endif
case 'p':
break;
default:
builtin_error ("usage: %s [-nfp] [varname]", this_command_name);
builtin_usage ();
return (EX_USAGE);
}
}
@ -108,85 +127,56 @@ set_or_show_attributes (list, attribute)
if (attribute & att_exported)
array_needs_making = 1;
/* Cannot undo readonly status. */
/* Cannot undo readonly status, silently disallowed. */
if (undo && (attribute & att_readonly))
attribute &= ~att_readonly;
while (list)
{
register char *name = list->word->word;
name = list->word->word;
if (functions_only)
if (functions_only) /* xxx -f name */
{
var = find_function (name);
if (!var)
if (var == 0)
{
builtin_error ("%s: not a function", name);
any_failed++;
}
else
{
if (undo)
var->attributes &= ~attribute;
else
var->attributes |= attribute;
}
SETVARATTR (var, attribute, undo);
list = list->next;
if (attribute == att_exported)
array_needs_making++;
continue;
}
/* xxx [-np] name[=value] */
assign = assignment (name);
if (assign)
name[assign] = '\0';
if (legal_identifier (name) == 0)
{
builtin_error ("%s: not a legal variable name", name);
any_failed++;
builtin_error ("`%s': not a valid identifier", name);
assign_error++;
list = list->next;
continue;
}
if (assign)
if (assign) /* xxx [-np] name=value */
{
name[assign] = '=';
/* This word has already been expanded once with command
and parameter expansion. Call do_assignment_no_expand (),
which does not do command or parameter substitution. */
do_assignment_no_expand (name);
which does not do command or parameter substitution. If
the assignment is not performed correctly, flag an error. */
if (do_assignment_no_expand (name) == 0)
assign_error++;
name[assign] = '\0';
}
if (undo)
{
var = find_variable (name);
if (var)
var->attributes &= ~attribute;
}
else
{
SHELL_VAR *find_tempenv_variable (), *tv;
if (tv = find_tempenv_variable (name))
{
var = bind_variable (tv->name, tv->value);
dispose_variable (tv);
}
else
var = find_variable (name);
if (!var)
{
var = bind_variable (name, (char *)NULL);
var->attributes |= att_invisible;
}
var->attributes |= attribute;
}
array_needs_making++; /* XXX */
set_var_attribute (name, attribute, undo);
list = list->next;
}
}
@ -204,50 +194,133 @@ set_or_show_attributes (list, attribute)
else
variable_list = all_shell_variables ();
#if defined (ARRAY_VARS)
if (attribute & att_array)
{
arrays_only++;
if (attribute != att_array)
attribute &= ~att_array;
}
#endif
if (variable_list)
{
for (i = 0; var = variable_list[i]; i++)
{
if ((var->attributes & attribute) && !invisible_p (var))
{
char flags[6];
flags[0] = '\0';
if (exported_p (var))
strcat (flags, "x");
if (readonly_p (var))
strcat (flags, "r");
if (function_p (var))
strcat (flags, "f");
if (integer_p (var))
strcat (flags, "i");
if (flags[0])
{
printf ("declare -%s ", flags);
if (!function_p (var))
{
char *x = double_quote (value_cell (var));
printf ("%s=%s\n", var->name, x);
free (x);
}
else
{
char *named_function_string ();
printf ("%s\n", named_function_string
(var->name, function_cell (var), 1));
}
}
}
#if defined (ARRAY_VARS)
if (arrays_only && array_p (var) == 0)
continue;
#endif
if ((var->attributes & attribute) && invisible_p (var) == 0)
show_var_attributes (var, nodefs);
}
free (variable_list);
}
}
return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}
int
show_var_attributes (var, nodefs)
SHELL_VAR *var;
int nodefs;
{
char flags[6], *x;
int i;
i = 0;
#if defined (ARRAY_VARS)
if (array_p (var))
flags[i++] = 'a';
#endif
if (function_p (var))
flags[i++] = 'f';
if (integer_p (var))
flags[i++] = 'i';
if (readonly_p (var))
flags[i++] = 'r';
if (exported_p (var))
flags[i++] = 'x';
flags[i] = '\0';
printf ("declare -%s ", i ? flags : "-");
#if defined (ARRAY_VARS)
if (array_p (var))
print_array_assignment (var, 1);
else
#endif
if (nodefs)
printf ("%s\n", var->name);
else if (function_p (var))
printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
else
{
x = double_quote (value_cell (var));
printf ("%s=%s\n", var->name, x);
free (x);
}
return (0);
}
int
show_name_attributes (name, nodefs)
char *name;
int nodefs;
{
SHELL_VAR *var;
var = find_tempenv_variable (name);
if (var == 0)
var = find_variable (name);
if (var && invisible_p (var) == 0)
{
show_var_attributes (var, nodefs);
return (0);
}
else
return (1);
}
void
set_var_attribute (name, attribute, undo)
char *name;
int attribute, undo;
{
SHELL_VAR *var, *tv;
if (undo)
var = find_variable (name);
else
{
if (tv = find_tempenv_variable (name))
{
var = bind_variable (tv->name, tv->value);
dispose_variable (tv);
}
else
var = find_variable (name);
if (var == 0)
{
var = bind_variable (name, (char *)NULL);
var->attributes |= att_invisible;
}
}
if (var)
SETVARATTR (var, attribute, undo);
if (var && ((var->attributes & att_exported) || (attribute & att_exported)))
array_needs_making++; /* XXX */
}

View file

@ -21,13 +21,16 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES shift.c
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "common.h"
$BUILTIN shift
$FUNCTION shift_builtin
@ -36,6 +39,8 @@ The positional parameters from $N+1 ... are renamed to $1 ... If N is
not given, it is assumed to be 1.
$END
int print_shift_error;
/* Shift the arguments ``left''. Shift DOLLAR_VARS down then take one
off of REST_OF_ARGS and place it into DOLLAR_VARS[9]. If LIST has
anything in it, it is a number which says where to start the
@ -44,34 +49,28 @@ int
shift_builtin (list)
WORD_LIST *list;
{
int times, number;
WORD_LIST *args;
int times;
register int count;
WORD_LIST *temp;
times = get_numeric_arg (list);
if (!times)
if (times == 0)
return (EXECUTION_SUCCESS);
if (times < 0)
else if (times < 0)
{
builtin_error ("shift count must be >= 0");
return (EXECUTION_FAILURE);
}
args = list_rest_of_args ();
number = list_length (args);
dispose_words (args);
if (times > number)
else if (times > number_of_args ())
{
builtin_error ("shift count must be <= $#");
if (print_shift_error)
builtin_error ("shift count must be <= $#");
return (EXECUTION_FAILURE);
}
while (times-- > 0)
{
register int count;
if (dollar_vars[1])
free (dollar_vars[1]);
@ -80,8 +79,7 @@ shift_builtin (list)
if (rest_of_args)
{
WORD_LIST *temp = rest_of_args;
temp = rest_of_args;
dollar_vars[9] = savestring (temp->word->word);
rest_of_args = rest_of_args->next;
temp->next = (WORD_LIST *)NULL;
@ -90,6 +88,5 @@ shift_builtin (list)
else
dollar_vars[9] = (char *)NULL;
}
return (EXECUTION_SUCCESS);
}

343
builtins/shopt.def Normal file
View file

@ -0,0 +1,343 @@
This file is shopt.def, from which is created shopt.c.
It implements the Bash `shopt' builtin.
Copyright (C) 1994 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 1, 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; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES shopt.c
$BUILTIN shopt
$DOCNAME shopt_builtin
$FUNCTION shopt_builtin
$SHORT_DOC shopt [-pqsu] [-o long-option] optname [optname...]
Toggle the values of variables controlling optional behavior.
The -s flag means to enable (set) each OPTNAME; the -u flag
unsets each OPTNAME. The -q flag suppresses output; the exit
status indicates whether each OPTNAME is set or unset. The -o
option restricts the OPTNAMEs to those defined for use with
`set -o'. With no options, or with the -p option, a list of all
settable options is displayed, with an indication of whether or
not each is set.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../shell.h"
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
#define UNSETOPT 0
#define SETOPT 1
#define OPTFMT "%-15s\t%s\n"
extern int allow_null_glob_expansion, glob_dot_filenames;
extern int cdable_vars, mail_warning, source_uses_path;
extern int no_exit_on_failed_exec, print_shift_error;
extern int check_hashed_filenames, promptvars, interactive_comments;
extern int cdspelling, expand_aliases;
extern int check_window_size;
#if defined (HISTORY)
extern int hist_verify, literal_history, command_oriented_history;
extern int force_append_history;
#endif
#if defined (READLINE)
extern int history_reediting, perform_hostname_completion;
extern void enable_hostname_completion ();
#endif
static int set_interactive_comments ();
static struct {
char *name;
int *value;
Function *set_func;
} shopt_vars[] = {
{ "cdable_vars", &cdable_vars, (Function *)NULL },
{ "cdspell", &cdspelling, (Function *)NULL },
{ "checkhash", &check_hashed_filenames, (Function *)NULL },
{ "checkwinsize", &check_window_size, (Function *)NULL },
#if defined (HISTORY)
{ "cmdhist", &command_oriented_history, (Function *)NULL },
#endif
{ "dotglob", &glob_dot_filenames, (Function *)NULL },
{ "execfail", &no_exit_on_failed_exec, (Function *)NULL },
{ "expand_aliases", &expand_aliases, (Function *)NULL },
#if defined (READLINE)
{ "histreedit", &history_reediting, (Function *)NULL },
#endif
#if defined (HISTORY)
{ "histappend", &force_append_history, (Function *)NULL },
{ "histverify", &hist_verify, (Function *)NULL },
#endif
#if defined (READLINE)
{ "hostcomplete", &perform_hostname_completion, (Function *)enable_hostname_completion },
#endif
{ "interactive_comments", &interactive_comments, set_interactive_comments },
#if defined (HISTORY)
{ "lithist", &literal_history, (Function *)NULL },
#endif
{ "mailwarn", &mail_warning, (Function *)NULL },
{ "nullglob", &allow_null_glob_expansion, (Function *)NULL },
{ "promptvars", &promptvars, (Function *)NULL },
{ "shift_verbose", &print_shift_error, (Function *)NULL },
{ "sourcepath", &source_uses_path, (Function *)NULL },
{ (char *)0, (int *)0, (Function *)NULL }
};
static char *on = "on";
static char *off = "off";
static int list_shopt_o_options ();
static int list_some_o_options (), list_some_shopts ();
static int toggle_shopts (), list_shopts (), set_shopt_o_options ();
#define SFLAG 0x01
#define UFLAG 0x02
#define QFLAG 0x04
#define OFLAG 0x08
#define PFLAG 0x10
int
shopt_builtin (list)
WORD_LIST *list;
{
int opt, flags, rval;
flags = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "psuoq")) != -1)
{
switch (opt)
{
case 's':
flags |= SFLAG;
break;
case 'u':
flags |= UFLAG;
break;
case 'q':
flags |= QFLAG;
break;
case 'o':
flags |= OFLAG;
break;
case 'p':
flags |= PFLAG;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG))
{
builtin_error ("cannot set and unset shell options simultaneously");
return (EXECUTION_FAILURE);
}
rval = EXECUTION_SUCCESS;
if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */
rval = list_shopt_o_options (list, flags & QFLAG);
else if (list && (flags & OFLAG)) /* shopt -so args */
rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG);
else if (flags & OFLAG) /* shopt -so */
rval = list_some_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, flags & QFLAG);
else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */
rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG);
else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */
rval = list_shopts (list, flags & QFLAG);
else /* shopt -su */
rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags & QFLAG);
return (rval);
}
static int
find_shopt (name)
char *name;
{
int i;
for (i = 0; shopt_vars[i].name; i++)
if (STREQ (name, shopt_vars[i].name))
return i;
return -1;
}
#define SHOPT_ERROR(str) builtin_error ("%s: unknown shell option name", str)
static int
toggle_shopts (mode, list, quiet)
int mode;
WORD_LIST *list;
int quiet;
{
WORD_LIST *l;
int ind, rval;
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
{
ind = find_shopt (l->word->word);
if (ind < 0)
{
SHOPT_ERROR (l->word->word);
rval = EXECUTION_FAILURE;
}
else
{
*shopt_vars[ind].value = mode; /* 1 for set, 0 for unset */
if (shopt_vars[ind].set_func)
(*shopt_vars[ind].set_func) (mode);
}
}
return (rval);
}
/* List the values of all or any of the `shopt' options. Returns 0 if
all were listed or all variables queried were on; 1 otherwise. */
static int
list_shopts (list, quiet)
WORD_LIST *list;
int quiet;
{
WORD_LIST *l;
int i, val, rval;
if (list == 0)
{
for (i = 0; shopt_vars[i].name; i++)
{
val = *shopt_vars[i].value;
if (quiet == 0)
printf (OPTFMT, shopt_vars[i].name, val ? on : off);
}
return (EXECUTION_SUCCESS);
}
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
{
i = find_shopt (l->word->word);
if (i < 0)
{
SHOPT_ERROR (l->word->word);
rval = EXECUTION_FAILURE;
continue;
}
val = *shopt_vars[i].value;
if (val == 0)
rval = EXECUTION_FAILURE;
if (quiet == 0)
printf (OPTFMT, l->word->word, val ? on : off);
}
return (rval);
}
static int
list_some_shopts (mode, quiet)
int mode, quiet;
{
int val, i;
for (i = 0; shopt_vars[i].name; i++)
{
val = *shopt_vars[i].value;
if (quiet == 0 && mode == val)
printf (OPTFMT, shopt_vars[i].name, val ? on : off);
}
return (EXECUTION_SUCCESS);
}
static int
list_shopt_o_options (list, quiet)
WORD_LIST *list;
int quiet;
{
WORD_LIST *l;
int val, rval;
if (list == 0)
{
if (quiet == 0)
list_minus_o_opts (-1);
return (EXECUTION_SUCCESS);
}
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
{
val = minus_o_option_value (l->word->word);
if (val == -1)
{
builtin_error ("%s: unknown option name", l->word->word);
rval = EXECUTION_FAILURE;
continue;
}
if (val == 0)
rval = EXECUTION_FAILURE;
if (quiet == 0)
printf (OPTFMT, l->word->word, val ? "on" : "off");
}
return (rval);
}
static int
list_some_o_options (mode, quiet)
int mode, quiet;
{
if (quiet == 0)
list_minus_o_opts (mode);
return (EXECUTION_SUCCESS);
}
static int
set_shopt_o_options (mode, list, quiet)
int mode;
WORD_LIST *list;
int quiet;
{
WORD_LIST *l;
int rval;
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
{
if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE)
rval = EXECUTION_FAILURE;
}
set_shellopts ();
return rval;
}
/* If we set or unset interactive_comments with shopt, make sure the
change is reflected in $SHELLOPTS. */
static int
set_interactive_comments (mode)
int mode;
{
set_shellopts ();
return (0);
}

View file

@ -36,34 +36,34 @@ in $PATH are used to find the directory containing FILENAME.
$END
/* source.c - Implements the `.' and `source' builtins. */
#include <sys/types.h>
#include <config.h>
#include "../bashtypes.h"
#include "../posixstat.h"
#include "../filecntl.h"
#include <sys/file.h>
#include <errno.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "../posixstat.h"
#include "../filecntl.h"
#include "../execute_cmd.h"
#include "common.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
/* Variables used here but defined in other files. */
extern int return_catch_flag, return_catch_value;
extern jmp_buf return_catch;
extern int posixly_correct;
extern int interactive, interactive_shell, last_command_exit_value;
#if defined (RESTRICTED_SHELL)
extern int restricted;
#endif
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
/* If non-zero, `.' uses $PATH to look up the script to be sourced. */
int source_uses_path = 1;
/* If this . script is supplied arguments, we save the dollar vars and
replace them with the script arguments for the duration of the script's
@ -86,101 +86,51 @@ maybe_pop_dollar_vars ()
This cannot be done in a subshell, since things like variable assignments
take place in there. So, I open the file, place it into a large string,
close the file, and then execute the string. */
int
source_builtin (list)
WORD_LIST *list;
{
int result, return_val;
int result;
char *filename;
/* Assume the best. */
result = EXECUTION_SUCCESS;
if (list)
{
char *string, *filename;
struct stat finfo;
int fd, tt;
filename = find_path_file (list->word->word);
if (!filename)
filename = savestring (list->word->word);
if (((fd = open (filename, O_RDONLY)) < 0) || (fstat (fd, &finfo) < 0))
goto file_error_exit;
string = (char *)xmalloc (1 + (int)finfo.st_size);
tt = read (fd, string, finfo.st_size);
string[finfo.st_size] = '\0';
/* Close the open file, preserving the state of errno. */
{ int temp = errno; close (fd); errno = temp; }
if (tt != finfo.st_size)
{
free (string);
file_error_exit:
file_error (filename);
free (filename);
/* POSIX shells exit if non-interactive and file error. */
if (posixly_correct && !interactive_shell)
{
last_command_exit_value = 1;
longjmp (top_level, EXITPROG);
}
return (EXECUTION_FAILURE);
}
if (tt > 80)
tt = 80;
if (check_binary_file ((unsigned char *)string, tt))
{
free (string);
builtin_error ("%s: cannot execute binary file", filename);
free (filename);
return (EX_BINARY_FILE);
}
begin_unwind_frame ("File Sourcing");
if (list->next)
{
push_dollar_vars ();
add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
remember_args (list->next, 1);
}
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
add_unwind_protect ((Function *)xfree, filename);
interactive = 0;
sourcelevel++;
set_dollar_vars_unchanged ();
return_catch_flag++;
return_val = setjmp (return_catch);
if (return_val)
parse_and_execute_cleanup ();
else
result = parse_and_execute (string, filename, -1);
run_unwind_frame ("File Sourcing");
/* If RETURN_VAL is non-zero, then we return the value given
to return_builtin (), since that is how we got here. */
if (return_val)
result = return_catch_value;
}
else
if (list == 0)
{
builtin_error ("filename argument required");
result = EXECUTION_FAILURE;
builtin_usage ();
return (EX_USAGE);
}
if (no_options (list))
return (EX_USAGE);
#if defined (RESTRICTED_SHELL)
if (restricted && strchr (list->word->word, '/'))
{
builtin_error ("%s: restricted", list->word->word);
return (EXECUTION_FAILURE);
}
#endif
filename = (char *)NULL;
if (source_uses_path)
filename = find_path_file (list->word->word);
if (filename == 0)
filename = savestring (list->word->word);
begin_unwind_frame ("source");
add_unwind_protect ((Function *)xfree, filename);
if (list->next)
{
push_dollar_vars ();
add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
remember_args (list->next, 1);
}
set_dollar_vars_unchanged ();
result = source_file (filename);
run_unwind_frame ("source");
return (result);
}

View file

@ -30,15 +30,23 @@ signal. The `-f' if specified says not to complain about this
being a login shell if it is; just suspend anyway.
$END
#include <sys/types.h>
#include <config.h>
#if defined (JOB_CONTROL)
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include <signal.h>
#include "../shell.h"
#include "../jobs.h"
#include "common.h"
#include "bashgetopt.h"
#if defined (JOB_CONTROL)
extern int job_control;
static SigHandler *old_cont, *old_tstp;
static SigHandler *old_cont, *old_stop;
/* Continue handler. */
sighandler
@ -46,10 +54,10 @@ suspend_continue (sig)
int sig;
{
set_signal_handler (SIGCONT, old_cont);
set_signal_handler (SIGTSTP, old_tstp);
#if !defined (VOID_SIGHANDLER)
return (0);
#endif /* !VOID_SIGHANDLER */
#if 0
set_signal_handler (SIGSTOP, old_stop);
#endif
SIGRETURN (0);
}
/* Suspending the shell. If -f is the arg, then do the suspend
@ -58,28 +66,45 @@ int
suspend_builtin (list)
WORD_LIST *list;
{
if (!job_control)
int opt, force;
reset_internal_getopt ();
force = 0;
while ((opt = internal_getopt (list, "f")) != -1)
switch (opt)
{
case 'f':
force++;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
list = loptend;
if (job_control == 0)
{
builtin_error ("Cannot suspend a shell without job control");
builtin_error ("cannot suspend a shell without job control");
return (EXECUTION_FAILURE);
}
if (list)
if (strcmp (list->word->word, "-f") == 0)
goto do_suspend;
no_args (list);
if (login_shell)
if (force == 0)
{
builtin_error ("Can't suspend a login shell");
return (EXECUTION_FAILURE);
no_args (list);
if (login_shell)
{
builtin_error ("cannot suspend a login shell");
return (EXECUTION_FAILURE);
}
}
do_suspend:
old_cont = (SigHandler *)set_signal_handler (SIGCONT, suspend_continue);
old_tstp = (SigHandler *)set_signal_handler (SIGTSTP, SIG_DFL);
killpg (shell_pgrp, SIGTSTP);
#if 0
old_stop = (SigHandler *)set_signal_handler (SIGSTOP, SIG_DFL);
#endif
killpg (shell_pgrp, SIGSTOP);
return (EXECUTION_SUCCESS);
}

View file

@ -37,12 +37,12 @@ File operators:
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link. Use "-L".
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its "sticky" bit set.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file is not empty.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
@ -63,12 +63,16 @@ String operators:
-z STRING True if string is empty.
-n STRING
or STRING True if string is not empty.
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically
Other operators:
@ -88,18 +92,21 @@ $BUILTIN [
$DOCNAME test_bracket
$FUNCTION test_builtin
$SHORT_DOC [ arg... ]
This is a synonym for the "test" shell builtin, excepting that the
last argument must be literally `]', to match the `[' which invoked
the test.
This is a synonym for the "test" builtin, but the last
argument must be a literal `]', to match the opening `['.
$END
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../shell.h"
#include "common.h"
extern char *this_command_name;
/* TEST/[ builtin. */
@ -109,12 +116,11 @@ test_builtin (list)
{
char **argv;
int argc, result;
WORD_LIST *t = list;
/* We let Matthew Bradburn and Kevin Braunsdorf's code do the
actual test command. So turn the list of args into an array
of strings, since that is what his code wants. */
if (!list)
of strings, since that is what their code wants. */
if (list == 0)
{
if (this_command_name[0] == '[' && !this_command_name[1])
builtin_error ("missing `]'");
@ -122,23 +128,9 @@ test_builtin (list)
return (EXECUTION_FAILURE);
}
/* Get the length of the argument list. */
for (argc = 0; t; t = t->next, argc++);
/* Account for argv[0] being a command name. This makes our life easier. */
argc++;
argv = (char **)xmalloc ((1 + argc) * sizeof (char *));
argv[argc] = (char *)NULL;
/* this_command_name is the name of the command that invoked this
function. So you can't call test_builtin () directly from
within this code, there are too many things to worry about. */
argv[0] = savestring (this_command_name);
for (t = list, argc = 1; t; t = t->next, argc++)
argv[argc] = savestring (t->word->word);
argv = make_builtin_argv (list, &argc);
result = test_command (argc, argv);
free_array (argv);
free ((char *)argv);
return (result);
}

View file

@ -28,62 +28,79 @@ Print the accumulated user and system times for processes run from
the shell.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashtypes.h"
#include "../shell.h"
#include <sys/types.h>
#if defined (hpux) || defined (USGr4) || defined (XD88) || defined (USGr3)
# undef HAVE_RESOURCE
#endif /* hpux || USGr4 || XD88 || USGr3 */
#if defined (_POSIX_VERSION) || !defined (HAVE_RESOURCE)
# include <sys/times.h>
#else /* !_POSIX_VERSION && HAVE_RESOURCE */
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <sys/resource.h>
#endif /* !_POSIX_VERSION && HAVE_RESOURCE */
# include <time.h>
#else
# if defined (HAVE_SYS_TIME_H)
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
/* Print the totals for system and user time used. The
information comes from variables in jobs.c used to keep
track of this stuff. */
#if defined (HAVE_SYS_TIMES_H)
# include <sys/times.h>
#endif /* HAVE_SYS_TIMES_H */
#if defined (HAVE_SYS_RESOURCE_H)
# include <sys/resource.h>
#endif
#include "common.h"
/* Print the totals for system and user time used. */
int
times_builtin (list)
WORD_LIST *list;
{
#if !defined (_POSIX_VERSION) && defined (HAVE_RESOURCE) && defined (RUSAGE_SELF)
#if defined (HAVE_GETRUSAGE) && defined (HAVE_TIMEVAL) && defined (RUSAGE_SELF)
struct rusage self, kids;
getrusage (RUSAGE_SELF, &self);
getrusage (RUSAGE_CHILDREN, &kids); /* terminated child processes */
print_timeval (&self.ru_utime);
print_timeval (stdout, &self.ru_utime);
putchar (' ');
print_timeval (&self.ru_stime);
print_timeval (stdout, &self.ru_stime);
putchar ('\n');
print_timeval (&kids.ru_utime);
print_timeval (stdout, &kids.ru_utime);
putchar (' ');
print_timeval (&kids.ru_stime);
print_timeval (stdout, &kids.ru_stime);
putchar ('\n');
#else /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
# if !defined (BrainDeath)
struct tms t;
times (&t);
#else
# if defined (HAVE_TIMES)
/* As of System V.3, HP-UX 6.5, and other ATT-like systems, this stuff is
returned in terms of clock ticks (HZ from sys/param.h). C'mon, guys.
This kind of stupid clock-dependent stuff is exactly the reason 4.2BSD
introduced the `timeval' struct. */
struct tms t;
print_time_in_hz (t.tms_utime);
times (&t);
print_time_in_hz (stdout, t.tms_utime);
putchar (' ');
print_time_in_hz (t.tms_stime);
print_time_in_hz (stdout, t.tms_stime);
putchar ('\n');
print_time_in_hz (t.tms_cutime);
print_time_in_hz (stdout, t.tms_cutime);
putchar (' ');
print_time_in_hz (t.tms_cstime);
print_time_in_hz (stdout, t.tms_cstime);
putchar ('\n');
# endif /* BrainDeath */
#endif /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
# else /* !HAVE_TIMES */
printf ("0.00 0.00\n0.00 0.00\n");
# endif /* HAVE_TIMES */
#endif /* !HAVE_TIMES */
return (EXECUTION_SUCCESS);
}

View file

@ -23,30 +23,46 @@ $PRODUCES trap.c
$BUILTIN trap
$FUNCTION trap_builtin
$SHORT_DOC trap [arg] [signal_spec]
$SHORT_DOC trap [arg] [signal_spec] or trap -l
The command ARG is to be read and executed when the shell receives
signal(s) SIGNAL_SPEC. If ARG is absent all specified signals are
reset to their original values. If ARG is the null string this
signal is ignored by the shell and by the commands it invokes. If
SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
the shell. The trap command with no arguments prints the list of
commands associated with each signal number. SIGNAL_SPEC is either
a signal name in <signal.h>, or a signal number. The syntax `trap -l'
prints a list of signal names and their corresponding numbers.
Note that a signal can be sent to the shell with "kill -signal $$".
reset to their original values. If ARG is the null string each
SIGNAL_SPEC is ignored by the shell and by the commands it invokes.
If SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
the shell. If SIGNAL_SPEC is DEBUG, ARG is executed after every
command. If ARG is `-p' then the trap commands associated with
each SIGNAL_SPEC are displayed. If no arguments are supplied or if
only `-p' is given, trap prints the list of commands associated with
each signal number. SIGNAL_SPEC is either a signal name in <signal.h>
or a signal number. `trap -l' prints a list of signal names and their
corresponding numbers. Note that a signal can be sent to the shell
with "kill -signal $$".
$END
#include <sys/types.h>
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include <signal.h>
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../trap.h"
#include "common.h"
#include "bashgetopt.h"
static int display_traps ();
/* The trap command:
trap <arg> <signal ...>
trap <signal ...>
trap -l
trap -p [sigspec ...]
trap [--]
Set things up so that ARG is executed when SIGNAL(s) N is recieved.
@ -62,60 +78,44 @@ $END
extern int interactive;
int
trap_builtin (list)
WORD_LIST *list;
{
register int i;
int list_signal_names = 0;
int list_signal_names, display, result, opt;
while (list)
list_signal_names = display = 0;
result = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lp")) != -1)
{
if (ISOPTION (list->word->word, 'l'))
switch (opt)
{
case 'l':
list_signal_names++;
list = list->next;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if ((*list->word->word == '-') && list->word->word[1])
{
bad_option (list->word->word);
builtin_error ("usage: trap [-l] [arg] [sigspec]");
case 'p':
display++;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
else
break;
}
list = loptend;
if (list_signal_names)
return (display_signal_list ((WORD_LIST *)NULL, 1));
else if (display || list == 0)
return (display_traps (list));
else
{
int column = 0;
char *first_arg;
int operation, sig;
for (i = 0; i < NSIG; i++)
{
printf ("%2d) %s", i, signal_name (i));
if (++column < 4)
printf ("\t");
else
{
printf ("\n");
column = 0;
}
}
if (column != 0)
printf ("\n");
return (EXECUTION_SUCCESS);
}
if (list)
{
char *first_arg = list->word->word;
int operation = SET, any_failed = 0;
if (signal_object_p (first_arg))
operation = SET;
first_arg = list->word->word;
if (first_arg && *first_arg && signal_object_p (first_arg))
operation = REVERT;
else
{
@ -128,15 +128,13 @@ trap_builtin (list)
while (list)
{
int sig;
sig = decode_signal (list->word->word);
if (sig == NO_SIG)
{
builtin_error ("%s: not a signal specification",
list->word->word);
any_failed++;
result = EXECUTION_FAILURE;
}
else
{
@ -183,22 +181,52 @@ trap_builtin (list)
}
list = list->next;
}
return ((!any_failed) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
for (i = 0; i < NSIG; i++)
{
char *t, *p;
p = trap_list[i];
if (p == (char *)DEFAULT_SIG)
continue;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
if (t)
free (t);
}
return (EXECUTION_SUCCESS);
return (result);
}
static void
showtrap (i)
int i;
{
char *t, *p;
p = trap_list[i];
if (p == (char *)DEFAULT_SIG)
return;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
if (t)
free (t);
}
static int
display_traps (list)
WORD_LIST *list;
{
int result, i;
if (list == 0)
{
for (i = 0; i <= NSIG; i++)
showtrap (i);
return (EXECUTION_SUCCESS);
}
for (result = EXECUTION_SUCCESS; list; list = list->next)
{
i = decode_signal (list->word->word);
if (i == NO_SIG)
{
result = EXECUTION_FAILURE;
builtin_error ("%s: not a signal specification", list->word->word);
}
else
showtrap (i);
}
return (result);
}

View file

@ -23,26 +23,38 @@ $PRODUCES type.c
$BUILTIN type
$FUNCTION type_builtin
$SHORT_DOC type [-all] [-type | -path] [name ...]
$SHORT_DOC type [-apt] name [name ...]
For each NAME, indicate how it would be interpreted if used as a
command name.
If the -type flag is used, returns a single word which is one of
If the -t option is used, returns a single word which is one of
`alias', `keyword', `function', `builtin', `file' or `', if NAME is an
alias, shell reserved word, shell function, shell builtin, disk file,
or unfound, respectively.
If the -path flag is used, either returns the name of the disk file
that would be exec'ed, or nothing if -type wouldn't return `file'.
If the -p flag is used, either returns the name of the disk file
that would be executed, or nothing if -t would not return `file'.
If the -all flag is used, displays all of the places that contain an
If the -a flag is used, displays all of the places that contain an
executable named `file'. This includes aliases and functions, if and
only if the -path flag is not also used.
only if the -p flag is not also used.
Type accepts -all, -path, and -type in place of -a, -p, and -t,
respectively.
$END
#include <stdio.h>
#include <sys/types.h>
#include <config.h>
#include "../bashtypes.h"
#include "../posixstat.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../execute_cmd.h"
@ -52,7 +64,7 @@ $END
#include "common.h"
extern STRING_INT_ALIST word_token_alist[];
extern int find_reserved_word ();
/* For each word in LIST, find out what the shell is going to do with
it as a simple command. i.e., which file would this shell use to
@ -75,18 +87,19 @@ extern STRING_INT_ALIST word_token_alist[];
builtin
file
*/
int
type_builtin (list)
WORD_LIST *list;
{
int path_only, type_only, all, verbose;
int successful_finds;
if (list == 0)
return (EXECUTION_SUCCESS);
path_only = type_only = all = 0;
successful_finds = 0;
if (!list)
return (EXECUTION_SUCCESS);
while (list && *(list->word->word) == '-')
{
char *flag = &(list->word->word[1]);
@ -108,7 +121,7 @@ type_builtin (list)
else
{
bad_option (flag);
builtin_error ("usage: type [-all | -path | -type ] name [name ...]");
builtin_usage ();
return (EX_USAGE);
}
list = list->next;
@ -116,7 +129,7 @@ type_builtin (list)
if (type_only)
verbose = 1;
else if (!path_only)
else if (path_only == 0)
verbose = 2;
else if (path_only)
verbose = 3;
@ -156,22 +169,29 @@ type_builtin (list)
* ALL says whether or not to look for all occurrences of COMMAND, or
* return after finding it once.
*/
int
describe_command (command, verbose, all)
char *command;
int verbose, all;
{
int found = 0, i, found_file = 0;
char *full_path = (char *)NULL;
int found, i, found_file;
char *full_path;
SHELL_VAR *func;
#if defined (ALIAS)
alias_t *alias;
#endif
found = found_file = 0;
full_path = (char *)NULL;
#if defined (ALIAS)
/* Command is an alias? */
ASSOC *alias = find_alias (command);
alias = find_alias (command);
if (alias)
{
if (verbose == 1)
printf ("alias\n");
puts ("alias");
else if (verbose == 2)
printf ("%s is aliased to `%s'\n", command, alias->value);
else if (verbose == 4)
@ -193,7 +213,7 @@ describe_command (command, verbose, all)
if (i >= 0)
{
if (verbose == 1)
printf ("keyword\n");
puts ("keyword");
else if (verbose == 2)
printf ("%s is a shell keyword\n", command);
else if (verbose == 4)
@ -211,7 +231,7 @@ describe_command (command, verbose, all)
if (func)
{
if (verbose == 1)
printf ("function\n");
puts ("function");
else if (verbose == 2)
{
#define PRETTY_PRINT_FUNC 1
@ -240,7 +260,7 @@ describe_command (command, verbose, all)
if (find_shell_builtin (command))
{
if (verbose == 1)
printf ("builtin\n");
puts ("builtin");
else if (verbose == 2)
printf ("%s is a shell builtin\n", command);
else if (verbose == 4)
@ -261,7 +281,7 @@ describe_command (command, verbose, all)
if (f & FS_EXECABLE)
{
if (verbose == 1)
printf ("file\n");
puts ("file");
else if (verbose == 2)
printf ("%s is %s\n", command, command);
else if (verbose == 3 || verbose == 4)
@ -281,7 +301,7 @@ describe_command (command, verbose, all)
if ((full_path = find_hashed_filename (command)) != (char *)NULL)
{
if (verbose == 1)
printf ("file\n");
puts ("file");
else if (verbose == 2)
printf ("%s is hashed (%s)\n", command, full_path);
else if (verbose == 3 || verbose == 4)
@ -308,7 +328,7 @@ describe_command (command, verbose, all)
found = 1;
if (verbose == 1)
printf ("file\n");
puts ("file");
else if (verbose == 2)
printf ("%s is %s\n", command, full_path);
else if (verbose == 3 || verbose == 4)

File diff suppressed because it is too large Load diff

View file

@ -31,12 +31,22 @@ If MODE begins with a digit, it is interpreted as an octal number,
otherwise it is a symbolic mode string like that accepted by chmod(1).
$END
#include <stdio.h>
#include <sys/types.h>
#include <config.h>
#include "../bashtypes.h"
#include "../filecntl.h"
#include <sys/file.h>
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include "../shell.h"
#include "../posixstat.h"
#include "common.h"
#include "bashgetopt.h"
/* **************************************************************** */
/* */
@ -49,47 +59,40 @@ static int symbolic_umask ();
/* Set or display the mask used by the system when creating files. Flag
of -S means display the umask in a symbolic mode. */
int
umask_builtin (list)
WORD_LIST *list;
{
int print_symbolically = 0;
int print_symbolically, opt, umask_value;
while (list)
print_symbolically = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "S")) != -1)
{
if (ISOPTION (list->word->word, 'S'))
switch (opt)
{
list = list->next;
case 'S':
print_symbolically++;
continue;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (*(list->word->word) == '-')
{
bad_option (list->word->word);
builtin_error ("usage: umask [-S] [mode]");
default:
builtin_usage ();
return (EX_USAGE);
}
else
break;
}
list = loptend;
if (list)
{
int new_umask;
if (digit (*list->word->word))
{
new_umask = read_octal (list->word->word);
umask_value = read_octal (list->word->word);
/* Note that other shells just let you set the umask to zero
by specifying a number out of range. This is a problem
with those shells. We don't change the umask if the input
is lousy. */
if (new_umask == -1)
if (umask_value == -1)
{
builtin_error ("`%s' is not an octal number from 000 to 777",
list->word->word);
@ -98,26 +101,25 @@ umask_builtin (list)
}
else
{
new_umask = symbolic_umask (list);
if (new_umask == -1)
umask_value = symbolic_umask (list);
if (umask_value == -1)
return (EXECUTION_FAILURE);
}
umask (new_umask);
umask (umask_value);
if (print_symbolically)
print_symbolic_umask (new_umask);
print_symbolic_umask (umask_value);
}
else /* Display the UMASK for this user. */
{
int old_umask;
old_umask = umask (022);
umask (old_umask);
umask_value = umask (022);
umask (umask_value);
if (print_symbolically)
print_symbolic_umask (old_umask);
print_symbolic_umask (umask_value);
else
printf ("%03o\n", old_umask);
printf ("%03o\n", umask_value);
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}
@ -176,7 +178,7 @@ symbolic_umask (list)
um = umask (022);
umask (um);
/* All work below is done with the complement of the umask -- its
/* All work below is done with the complement of the umask -- it's
more intuitive and easier to deal with. It is complemented
again before being returned. */
umc = ~um;
@ -266,7 +268,7 @@ symbolic_umask (list)
break;
default:
builtin_error ("bad operation character: %c", op);
builtin_error ("bad symbolic mode operator: %c", op);
return (-1);
}

View file

@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$BUILTIN wait
$FUNCTION wait_builtin
$DEPENDS_ON JOB_CONTROL
@ -42,10 +41,18 @@ and the return code is zero. N is a process ID; if it is not given,
all child processes of the shell are waited for.
$END
#include <sys/types.h>
#include <config.h>
#include "../bashtypes.h"
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../shell.h"
#include "../jobs.h"
#include "common.h"
extern int interrupt_immediately;
@ -53,10 +60,17 @@ extern int interrupt_immediately;
wait for all of the active background processes of the shell and return
0. If a list of pids or job specs are given, return the exit status of
the last one waited for. */
#define WAIT_RETURN(s) do { run_unwind_frame ("wait_builtin"); return (s); } while (0)
int
wait_builtin (list)
WORD_LIST *list;
{
int status = EXECUTION_SUCCESS;
int status;
if (no_options (list))
return (EX_USAGE);
begin_unwind_frame ("wait_builtin");
unwind_protect_int (interrupt_immediately);
@ -67,13 +81,13 @@ wait_builtin (list)
/* But wait without any arguments means to wait for all of the shell's
currently active background processes. */
if (!list)
if (list == 0)
{
wait_for_background_pids ();
status = EXECUTION_SUCCESS;
goto return_status;
WAIT_RETURN (EXECUTION_SUCCESS);
}
status = EXECUTION_SUCCESS;
while (list)
{
pid_t pid;
@ -89,9 +103,8 @@ wait_builtin (list)
}
else
{
builtin_error ("`%s' is not a pid or legal job spec", w);
status = EXECUTION_FAILURE;
goto return_status;
builtin_error ("`%s' is not a pid or valid job spec", w);
WAIT_RETURN (EXECUTION_FAILURE);
}
}
#if defined (JOB_CONTROL)
@ -107,7 +120,7 @@ wait_builtin (list)
if (job < 0 || job >= job_slots || !jobs[job])
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list->word->word);
builtin_error ("%s: no such job", list->word->word);
UNBLOCK_CHILD (oset);
status = 127; /* As per Posix.2, section 4.70.2 */
list = list->next;
@ -121,12 +134,11 @@ wait_builtin (list)
#endif /* JOB_CONTROL */
else
{
builtin_error ("`%s' is not a pid or legal job spec", w);
builtin_error ("`%s' is not a pid or valid job spec", w);
status = EXECUTION_FAILURE;
}
list = list->next;
}
return_status:
run_unwind_frame ("wait_builtin");
return (status);
WAIT_RETURN (status);
}