Imported from ../bash-2.0.tar.gz.
This commit is contained in:
parent
726f63884d
commit
ccc6cda312
502 changed files with 91988 additions and 69123 deletions
|
|
@ -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
375
builtins/Makefile.in
Normal 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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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') {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
{
|
||||
|
|
|
|||
892
builtins/cd.def
892
builtins/cd.def
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
211
builtins/evalfile.c
Normal 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
228
builtins/evalstring.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
}
|
||||
|
|
|
|||
233
builtins/fc.def
233
builtins/fc.def
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
604
builtins/pushd.def
Normal 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 */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
678
builtins/set.def
678
builtins/set.def
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
343
builtins/shopt.def
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue