Bash-4.3 distribution sources and documentation
This commit is contained in:
parent
4539d736f1
commit
ac50fbac37
497 changed files with 129395 additions and 87598 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
|
||||
#
|
||||
# Copyright (C) 1996-2009 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -67,8 +67,8 @@ LIBS = @LIBS@
|
|||
LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
|
||||
LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
|
||||
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
|
||||
#LIBS_FOR_BUILD = @LIBS_FOR_BUILD@
|
||||
LIBS_FOR_BUILD = $(LIBS)
|
||||
LIBS_FOR_BUILD = @LIBS_FOR_BUILD@
|
||||
#LIBS_FOR_BUILD = $(LIBS)
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
|
|
@ -85,6 +85,8 @@ LIBINTL_H = @LIBINTL_H@
|
|||
HELPDIR = @HELPDIR@
|
||||
MKDIRS = ${topdir}/support/mkdirs
|
||||
|
||||
HELPFILES_TARGET = @HELPFILES_TARGET@
|
||||
|
||||
INCLUDES = -I. -I.. @RL_INCLUDE@ -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib -I$(srcdir) ${INTL_INC}
|
||||
|
||||
BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
|
||||
|
|
@ -153,15 +155,33 @@ OFILES = builtins.o \
|
|||
suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
|
||||
wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
|
||||
|
||||
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h
|
||||
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
|
||||
tmpbuiltins.h
|
||||
CREATED_OBJECTS = tmpbuiltins.o gen-helpfiles.o mkbuiltins.o
|
||||
|
||||
all: $(MKBUILTINS) libbuiltins.a
|
||||
all: $(MKBUILTINS) libbuiltins.a $(HELPFILES_TARGET)
|
||||
targets: libbuiltins.a $(HELPFILES_TARGET)
|
||||
|
||||
libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o
|
||||
$(RM) $@
|
||||
$(AR) $(ARFLAGS) $@ $(OFILES)
|
||||
-$(RANLIB) $@
|
||||
|
||||
tmpbuiltins.c: $(MKBUILTINS) $(DEFSRC)
|
||||
./$(MKBUILTINS) -externfile tmpbuiltins.h -structfile $@ \
|
||||
-noproduction -nofunctions \
|
||||
$(DIRECTDEFINE) $(HELPSTRINGS) $(DEFSRC)
|
||||
|
||||
tmpbuiltins.h: tmpbuiltins.c
|
||||
|
||||
gen-helpfiles.o: ../config.h
|
||||
gen-helpfiles.o: gen-helpfiles.c
|
||||
$(RM) $@
|
||||
$(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
|
||||
|
||||
gen-helpfiles: tmpbuiltins.o gen-helpfiles.o
|
||||
$(CC_FOR_BUILD) ${CCFLAGS_FOR_BUILD} $(LDFLAGS_FOR_BUILD) -o $@ gen-helpfiles.o tmpbuiltins.o $(LIBS_FOR_BUILD)
|
||||
|
||||
builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
|
||||
@-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi
|
||||
@-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi
|
||||
|
|
@ -178,8 +198,8 @@ builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
|
|||
$(RM) old-builtins.c; \
|
||||
fi
|
||||
|
||||
helpdoc: $(MKBUILTINS) $(DEFSRC)
|
||||
./$(MKBUILTINS) ${HELPDIRDEFINE} -noproduction $(DIRECTDEFINE) $(DEFSRC)
|
||||
helpdoc: gen-helpfiles
|
||||
./gen-helpfiles ${HELPDIRDEFINE}
|
||||
|
||||
install-help:
|
||||
@-if test -n "${HELPDIR}" && test -d helpfiles ; then \
|
||||
|
|
@ -207,15 +227,20 @@ common.o: common.c
|
|||
bashgetopt.o: bashgetopt.c
|
||||
getopt.o: getopt.c
|
||||
evalstring.o: evalstring.c
|
||||
evalfile.o: evalfile.c
|
||||
evalfile.o: evalfile.c
|
||||
|
||||
tmpbuiltins.o: tmpbuiltins.c
|
||||
gen-helpfiles.o: gen-helpfiles.c
|
||||
|
||||
ulimit.o: pipesize.h
|
||||
|
||||
pipesize.h: psize.aux
|
||||
$(SHELL) $(srcdir)/psize.sh > $@
|
||||
|
||||
# Technically this is wrong; the pipe size should be for the target system,
|
||||
# not the build host.
|
||||
psize.aux: psize.c
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(srcdir)/psize.c
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(srcdir)/psize.c
|
||||
|
||||
documentation: builtins.texi
|
||||
|
||||
|
|
@ -223,7 +248,8 @@ builtins.texi: $(MKBUILTINS)
|
|||
./$(MKBUILTINS) -documentonly $(DEFSRC)
|
||||
|
||||
clean:
|
||||
$(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS) mkbuiltins.o libbuiltins.a
|
||||
$(RM) $(OFILES) $(CREATED_FILES) libbuiltins.a
|
||||
$(RM) $(MKBUILTINS) gen-helpfiles $(CREATED_OBJECTS)
|
||||
-test -d helpfiles && $(RM) -r helpfiles
|
||||
|
||||
mostlyclean:
|
||||
|
|
@ -547,7 +573,7 @@ shopt.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
|||
shopt.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
|
||||
shopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
shopt.o: $(srcdir)/common.h $(srcdir)/bashgetopt.h ../pathnames.h
|
||||
shopt.o: $(topdir)/bashhist.h
|
||||
shopt.o: $(topdir)/bashhist.h $(topdir)/bashline.h
|
||||
source.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/findcmd.h
|
||||
source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ $PRODUCES bind.c
|
|||
$BUILTIN bind
|
||||
$DEPENDS_ON READLINE
|
||||
$FUNCTION bind_builtin
|
||||
$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
|
||||
$SHORT_DOC bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
|
||||
Set Readline key bindings and variables.
|
||||
|
||||
Bind a key sequence to a Readline function or a macro, or set a
|
||||
|
|
@ -54,6 +54,8 @@ Options:
|
|||
-f filename Read key bindings from FILENAME.
|
||||
-x keyseq:shell-command Cause SHELL-COMMAND to be executed when
|
||||
KEYSEQ is entered.
|
||||
-X List key sequences bound with -x and associated commands
|
||||
in a form that can be reused as input.
|
||||
|
||||
Exit Status:
|
||||
bind returns 0 unless an unrecognized option is given or an error occurs.
|
||||
|
|
@ -104,6 +106,7 @@ extern int no_line_editing;
|
|||
#define SSFLAG 0x0400
|
||||
#define UFLAG 0x0800
|
||||
#define XFLAG 0x1000
|
||||
#define XXFLAG 0x2000
|
||||
|
||||
int
|
||||
bind_builtin (list)
|
||||
|
|
@ -138,7 +141,7 @@ bind_builtin (list)
|
|||
rl_outstream = stdout;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "lvpVPsSf:q:u:m:r:x:")) != EOF)
|
||||
while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
|
@ -187,6 +190,9 @@ bind_builtin (list)
|
|||
flags |= XFLAG;
|
||||
cmd_seq = list_optarg;
|
||||
break;
|
||||
case 'X':
|
||||
flags |= XXFLAG;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
BIND_RETURN (EX_USAGE);
|
||||
|
|
@ -201,7 +207,7 @@ bind_builtin (list)
|
|||
if ((flags & MFLAG) && map_name)
|
||||
{
|
||||
kmap = rl_get_keymap_by_name (map_name);
|
||||
if (!kmap)
|
||||
if (kmap == 0)
|
||||
{
|
||||
builtin_error (_("`%s': invalid keymap name"), map_name);
|
||||
BIND_RETURN (EXECUTION_FAILURE);
|
||||
|
|
@ -265,6 +271,9 @@ bind_builtin (list)
|
|||
if (flags & XFLAG)
|
||||
return_code = bind_keyseq_to_unix_command (cmd_seq);
|
||||
|
||||
if (flags & XXFLAG)
|
||||
return_code = print_unix_command_map ();
|
||||
|
||||
/* Process the rest of the arguments as binding specifications. */
|
||||
while (list)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ This file is caller.def, from which is created caller.c. It implements the
|
|||
builtin "caller" in Bash.
|
||||
|
||||
Copyright (C) 2002-2008 Rocky Bernstein for Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -121,7 +122,7 @@ caller_builtin (list)
|
|||
{
|
||||
sh_invalidnum (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
|
|
|||
163
builtins/cd.def
163
builtins/cd.def
|
|
@ -1,7 +1,7 @@
|
|||
This file is cd.def, from which is created cd.c. It implements the
|
||||
builtins "cd" and "pwd" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -31,9 +31,10 @@ $PRODUCES cd.c
|
|||
#include "../bashtypes.h"
|
||||
#include "posixdir.h"
|
||||
#include "posixstat.h"
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -60,7 +61,10 @@ extern const char * const bash_getcwd_errstr;
|
|||
static int bindpwd __P((int));
|
||||
static int setpwd __P((char *));
|
||||
static char *resetpwd __P((char *));
|
||||
static int change_to_directory __P((char *, int));
|
||||
static int change_to_directory __P((char *, int, int));
|
||||
|
||||
static int cdxattr __P((char *, char **));
|
||||
static void resetxattr __P((void));
|
||||
|
||||
/* Change this to 1 to get cd spelling correction by default. */
|
||||
int cdspelling = 0;
|
||||
|
|
@ -68,10 +72,12 @@ int cdspelling = 0;
|
|||
int cdable_vars;
|
||||
|
||||
static int eflag; /* file scope so bindpwd() can see it */
|
||||
static int xattrflag; /* O_XATTR support for openat */
|
||||
static int xattrfd = -1;
|
||||
|
||||
$BUILTIN cd
|
||||
$FUNCTION cd_builtin
|
||||
$SHORT_DOC cd [-L|[-P [-e]]] [dir]
|
||||
$SHORT_DOC cd [-L|[-P [-e]] [-@]] [dir]
|
||||
Change the shell working directory.
|
||||
|
||||
Change the current directory to DIR. The default DIR is the value of the
|
||||
|
|
@ -87,13 +93,21 @@ the word is assumed to be a variable name. If that variable has a value,
|
|||
its value is used for DIR.
|
||||
|
||||
Options:
|
||||
-L force symbolic links to be followed
|
||||
-L force symbolic links to be followed: resolve symbolic links in
|
||||
DIR after processing instances of `..'
|
||||
-P use the physical directory structure without following symbolic
|
||||
links
|
||||
links: resolve symbolic links in DIR before processing instances
|
||||
of `..'
|
||||
-e if the -P option is supplied, and the current working directory
|
||||
cannot be determined successfully, exit with a non-zero status
|
||||
#if defined (O_XATTR)
|
||||
-@ on systems that support it, present a file with extended attributes
|
||||
as a directory containing the file attributes
|
||||
#endif
|
||||
|
||||
The default is to follow symbolic links, as if `-L' were specified.
|
||||
`..' is processed by removing the immediately previous pathname component
|
||||
back to a slash or the beginning of DIR.
|
||||
|
||||
Exit Status:
|
||||
Returns 0 if the directory is changed, and if $PWD is set successfully when
|
||||
|
|
@ -173,6 +187,66 @@ resetpwd (caller)
|
|||
return (tdir);
|
||||
}
|
||||
|
||||
static int
|
||||
cdxattr (dir, ndirp)
|
||||
char *dir; /* don't assume we can always free DIR */
|
||||
char **ndirp; /* return new constructed directory name */
|
||||
{
|
||||
#if defined (O_XATTR)
|
||||
int apfd, fd, r, e;
|
||||
char buf[11+40+40]; /* construct new `fake' path for pwd */
|
||||
|
||||
apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK);
|
||||
if (apfd < 0)
|
||||
return -1;
|
||||
fd = openat (apfd, ".", O_XATTR);
|
||||
e = errno;
|
||||
close (apfd); /* ignore close error for now */
|
||||
errno = e;
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
r = fchdir (fd); /* assume fchdir exists everywhere with O_XATTR */
|
||||
if (r < 0)
|
||||
{
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
/* NFSv4 and ZFS extended attribute directories do not have names which are
|
||||
visible in the standard Unix directory tree structure. To ensure we have
|
||||
a valid name for $PWD, we synthesize one under /proc, but to keep that
|
||||
path valid, we need to keep the file descriptor open as long as we are in
|
||||
this directory. This imposes a certain structure on /proc. */
|
||||
if (ndirp)
|
||||
{
|
||||
sprintf (buf, "/proc/%d/fd/%d", getpid(), fd);
|
||||
*ndirp = savestring (buf);
|
||||
}
|
||||
|
||||
if (xattrfd >= 0)
|
||||
close (xattrfd);
|
||||
xattrfd = fd;
|
||||
|
||||
return r;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Clean up the O_XATTR baggage. Currently only closes xattrfd */
|
||||
static void
|
||||
resetxattr ()
|
||||
{
|
||||
#if defined (O_XATTR)
|
||||
if (xattrfd >= 0)
|
||||
{
|
||||
close (xattrfd);
|
||||
xattrfd = -1;
|
||||
}
|
||||
#else
|
||||
xattrfd = -1; /* not strictly necessary */
|
||||
#endif
|
||||
}
|
||||
|
||||
#define LCD_DOVARS 0x001
|
||||
#define LCD_DOSPELL 0x002
|
||||
#define LCD_PRINTPATH 0x004
|
||||
|
|
@ -199,8 +273,13 @@ cd_builtin (list)
|
|||
|
||||
eflag = 0;
|
||||
no_symlinks = no_symbolic_links;
|
||||
xattrflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "LP")) != -1)
|
||||
#if defined (O_XATTR)
|
||||
while ((opt = internal_getopt (list, "eLP@")) != -1)
|
||||
#else
|
||||
while ((opt = internal_getopt (list, "eLP")) != -1)
|
||||
#endif
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
|
@ -213,9 +292,14 @@ cd_builtin (list)
|
|||
case 'e':
|
||||
eflag = 1;
|
||||
break;
|
||||
#if defined (O_XATTR)
|
||||
case '@':
|
||||
xattrflag = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
|
@ -237,6 +321,13 @@ cd_builtin (list)
|
|||
}
|
||||
lflag = 0;
|
||||
}
|
||||
#if defined (CD_COMPLAINS)
|
||||
else if (list->next)
|
||||
{
|
||||
builtin_error (_("too many arguments"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
|
||||
{
|
||||
/* This is `cd -', equivalent to `cd $OLDPWD' */
|
||||
|
|
@ -268,7 +359,7 @@ cd_builtin (list)
|
|||
temp = sh_makepath (path, dirname, MP_DOTILDE);
|
||||
free (path);
|
||||
|
||||
if (change_to_directory (temp, no_symlinks))
|
||||
if (change_to_directory (temp, no_symlinks, xattrflag))
|
||||
{
|
||||
/* POSIX.2 says that if a nonempty directory from CDPATH
|
||||
is used to find the directory to change to, the new
|
||||
|
|
@ -290,7 +381,8 @@ cd_builtin (list)
|
|||
free (temp);
|
||||
}
|
||||
|
||||
#if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
|
||||
#if 0
|
||||
/* changed for bash-4.2 Posix cd description steps 5-6 */
|
||||
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
|
||||
try the current directory, so we just punt now with an error
|
||||
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
|
||||
|
|
@ -308,7 +400,7 @@ cd_builtin (list)
|
|||
|
||||
/* When we get here, DIRNAME is the directory to change to. If we
|
||||
chdir successfully, just return. */
|
||||
if (change_to_directory (dirname, no_symlinks))
|
||||
if (change_to_directory (dirname, no_symlinks, xattrflag))
|
||||
{
|
||||
if (lflag & LCD_PRINTPATH)
|
||||
printf ("%s\n", dirname);
|
||||
|
|
@ -321,7 +413,7 @@ cd_builtin (list)
|
|||
if (lflag & LCD_DOVARS)
|
||||
{
|
||||
temp = get_string_value (dirname);
|
||||
if (temp && change_to_directory (temp, no_symlinks))
|
||||
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
|
||||
{
|
||||
printf ("%s\n", temp);
|
||||
return (bindpwd (no_symlinks));
|
||||
|
|
@ -334,9 +426,10 @@ cd_builtin (list)
|
|||
if (lflag & LCD_DOSPELL)
|
||||
{
|
||||
temp = dirspell (dirname);
|
||||
if (temp && change_to_directory (temp, no_symlinks))
|
||||
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
|
||||
{
|
||||
printf ("%s\n", temp);
|
||||
free (temp);
|
||||
return (bindpwd (no_symlinks));
|
||||
}
|
||||
else
|
||||
|
|
@ -391,7 +484,7 @@ pwd_builtin (list)
|
|||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
|
@ -405,7 +498,11 @@ pwd_builtin (list)
|
|||
the file system has changed state underneath bash). */
|
||||
if ((tcwd && directory == 0) ||
|
||||
(posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
|
||||
directory = resetpwd ("pwd");
|
||||
{
|
||||
if (directory && directory != tcwd)
|
||||
free (directory);
|
||||
directory = resetpwd ("pwd");
|
||||
}
|
||||
|
||||
#undef tcwd
|
||||
|
||||
|
|
@ -431,11 +528,11 @@ pwd_builtin (list)
|
|||
to the working directory. Return 1 on success, 0 on failure. */
|
||||
|
||||
static int
|
||||
change_to_directory (newdir, nolinks)
|
||||
change_to_directory (newdir, nolinks, xattr)
|
||||
char *newdir;
|
||||
int nolinks;
|
||||
int nolinks, xattr;
|
||||
{
|
||||
char *t, *tdir;
|
||||
char *t, *tdir, *ndir;
|
||||
int err, canon_failed, r, ndlen, dlen;
|
||||
|
||||
tdir = (char *)NULL;
|
||||
|
|
@ -484,8 +581,34 @@ change_to_directory (newdir, nolinks)
|
|||
return (0);
|
||||
}
|
||||
|
||||
#if defined (O_XATTR)
|
||||
if (xattrflag)
|
||||
{
|
||||
r = cdxattr (nolinks ? newdir : tdir, &ndir);
|
||||
if (r >= 0)
|
||||
{
|
||||
canon_failed = 0;
|
||||
free (tdir);
|
||||
tdir = ndir;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = errno;
|
||||
free (tdir);
|
||||
errno = err;
|
||||
return (0); /* no xattr */
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
r = chdir (nolinks ? newdir : tdir);
|
||||
if (r >= 0)
|
||||
resetxattr ();
|
||||
}
|
||||
|
||||
/* If the chdir succeeds, update the_current_working_directory. */
|
||||
if (chdir (nolinks ? newdir : tdir) == 0)
|
||||
if (r == 0)
|
||||
{
|
||||
/* If canonicalization failed, but the chdir succeeded, reset the
|
||||
shell's idea of the_current_working_directory. */
|
||||
|
|
@ -494,6 +617,8 @@ change_to_directory (newdir, nolinks)
|
|||
t = resetpwd ("cd");
|
||||
if (t == 0)
|
||||
set_working_directory (tdir);
|
||||
else
|
||||
free (t);
|
||||
}
|
||||
else
|
||||
set_working_directory (tdir);
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ get_exitstat (list)
|
|||
if (arg == 0 || legal_number (arg, &sval) == 0)
|
||||
{
|
||||
sh_neednumarg (list->word->word ? list->word->word : "`'");
|
||||
return 255;
|
||||
return EX_BADUSAGE;
|
||||
}
|
||||
no_args (list->next);
|
||||
|
||||
|
|
@ -628,7 +628,7 @@ get_job_by_name (name, flags)
|
|||
if (this_shell_builtin)
|
||||
builtin_error (_("%s: ambiguous job spec"), name);
|
||||
else
|
||||
report_error (_("%s: ambiguous job spec"), name);
|
||||
internal_error (_("%s: ambiguous job spec"), name);
|
||||
return (DUP_JOB);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ extern void set_bashopts __P((void));
|
|||
extern void parse_bashopts __P((char *));
|
||||
extern void initialize_bashopts __P((int));
|
||||
|
||||
extern void set_compatibility_opts __P((void));
|
||||
|
||||
/* Functions from type.def */
|
||||
extern int describe_command __P((char *, int));
|
||||
|
||||
|
|
@ -153,6 +155,7 @@ extern int set_or_show_attributes __P((WORD_LIST *, int, int));
|
|||
extern int show_all_var_attributes __P((int, int));
|
||||
extern int show_var_attributes __P((SHELL_VAR *, int, int));
|
||||
extern int show_name_attributes __P((char *, int));
|
||||
extern int show_func_attributes __P((char *, int));
|
||||
extern void set_var_attribute __P((char *, int, int));
|
||||
|
||||
/* Functions from pushd.def */
|
||||
|
|
@ -163,6 +166,7 @@ extern WORD_LIST *get_directory_stack __P((int));
|
|||
|
||||
/* Functions from evalstring.c */
|
||||
extern int parse_and_execute __P((char *, const char *, int));
|
||||
extern int evalstring __P((char *, const char *, int));
|
||||
extern void parse_and_execute_cleanup __P((void));
|
||||
extern int parse_string __P((char *, const char *, int, char **));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is complete.def, from which is created complete.c.
|
||||
It implements the builtins "complete", "compgen", and "compopt" in Bash.
|
||||
|
||||
Copyright (C) 1999-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ static const struct _compacts {
|
|||
{ "export", CA_EXPORT, 'e' },
|
||||
{ "file", CA_FILE, 'f' },
|
||||
{ "function", CA_FUNCTION, 0 },
|
||||
{ "helptopic", CA_BUILTIN, 0 }, /* for now */
|
||||
{ "helptopic", CA_HELPTOPIC, 0 },
|
||||
{ "hostname", CA_HOSTNAME, 0 },
|
||||
{ "group", CA_GROUP, 'g' },
|
||||
{ "job", CA_JOB, 'j' },
|
||||
|
|
@ -129,7 +129,7 @@ static const struct _compacts {
|
|||
};
|
||||
|
||||
/* This should be a STRING_INT_ALIST */
|
||||
const static struct _compopt {
|
||||
static const struct _compopt {
|
||||
const char * const optname;
|
||||
int optflag;
|
||||
} compopts[] = {
|
||||
|
|
@ -137,6 +137,7 @@ const static struct _compopt {
|
|||
{ "default", COPT_DEFAULT },
|
||||
{ "dirnames", COPT_DIRNAMES },
|
||||
{ "filenames",COPT_FILENAMES},
|
||||
{ "noquote", COPT_NOQUOTE },
|
||||
{ "nospace", COPT_NOSPACE },
|
||||
{ "plusdirs", COPT_PLUSDIRS },
|
||||
{ (char *)NULL, 0 },
|
||||
|
|
@ -728,6 +729,7 @@ compgen_builtin (list)
|
|||
if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
|
||||
{
|
||||
matches = rl_completion_matches (word, rl_filename_completion_function);
|
||||
strlist_dispose (sl);
|
||||
sl = completions_to_stringlist (matches);
|
||||
strvec_dispose (matches);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is declare.def, from which is created declare.c.
|
||||
It implements the builtins "declare" and "local" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ $PRODUCES declare.c
|
|||
|
||||
$BUILTIN declare
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC declare [-aAfFgilrtux] [-p] [name[=value] ...]
|
||||
$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
|
||||
Set variable values and attributes.
|
||||
|
||||
Declare variables and give them attributes. If no NAMEs are given,
|
||||
|
|
@ -41,6 +41,7 @@ Options which set attributes:
|
|||
-A to make NAMEs associative arrays (if supported)
|
||||
-i to make NAMEs have the `integer' attribute
|
||||
-l to convert NAMEs to lower case on assignment
|
||||
-n make NAME a reference to the variable named by its value
|
||||
-r to make NAMEs readonly
|
||||
-t to make NAMEs have the `trace' attribute
|
||||
-u to convert NAMEs to upper case on assignment
|
||||
|
|
@ -55,7 +56,8 @@ When used in a function, `declare' makes NAMEs local, as with the `local'
|
|||
command. The `-g' option suppresses this behavior.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied or an error occurs.
|
||||
Returns success unless an invalid option is supplied or a variable
|
||||
assignment error occurs.
|
||||
$END
|
||||
|
||||
$BUILTIN typeset
|
||||
|
|
@ -110,8 +112,8 @@ Local variables can only be used within a function; they are visible
|
|||
only to the function where they are defined and its children.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied, an error occurs,
|
||||
or the shell is not executing a function.
|
||||
Returns success unless an invalid option is supplied, a variable
|
||||
assignment error occurs, or the shell is not executing a function.
|
||||
$END
|
||||
int
|
||||
local_builtin (list)
|
||||
|
|
@ -127,9 +129,9 @@ local_builtin (list)
|
|||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
# define DECLARE_OPTS "+acfgilprtuxAF"
|
||||
# define DECLARE_OPTS "+acfgilnprtuxAF"
|
||||
#else
|
||||
# define DECLARE_OPTS "+cfgilprtuxF"
|
||||
# define DECLARE_OPTS "+cfgilnprtuxF"
|
||||
#endif
|
||||
|
||||
/* The workhorse function. */
|
||||
|
|
@ -139,12 +141,13 @@ declare_internal (list, local_var)
|
|||
int local_var;
|
||||
{
|
||||
int flags_on, flags_off, *flags;
|
||||
int any_failed, assign_error, pflag, nodefs, opt, mkglobal;
|
||||
int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
|
||||
char *t, *subscript_start;
|
||||
SHELL_VAR *var;
|
||||
SHELL_VAR *var, *refvar, *v;
|
||||
FUNCTION_DEF *shell_fn;
|
||||
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
|
||||
refvar = (SHELL_VAR *)NULL;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
|
||||
{
|
||||
|
|
@ -186,6 +189,9 @@ declare_internal (list, local_var)
|
|||
case 'i':
|
||||
*flags |= att_integer;
|
||||
break;
|
||||
case 'n':
|
||||
*flags |= att_nameref;
|
||||
break;
|
||||
case 'r':
|
||||
*flags |= att_readonly;
|
||||
break;
|
||||
|
|
@ -258,7 +264,10 @@ declare_internal (list, local_var)
|
|||
{
|
||||
for (any_failed = 0; list; list = list->next)
|
||||
{
|
||||
pflag = show_name_attributes (list->word->word, nodefs);
|
||||
if (flags_on & att_function)
|
||||
pflag = show_func_attributes (list->word->word, nodefs);
|
||||
else
|
||||
pflag = show_name_attributes (list->word->word, nodefs);
|
||||
if (pflag)
|
||||
{
|
||||
sh_notfound (list->word->word);
|
||||
|
|
@ -296,6 +305,28 @@ declare_internal (list, local_var)
|
|||
else
|
||||
value = "";
|
||||
|
||||
/* Do some lexical error checking on the LHS and RHS of the assignment
|
||||
that is specific to nameref variables. */
|
||||
if (flags_on & att_nameref)
|
||||
{
|
||||
#if defined (ARRAY_VARIABLES)
|
||||
if (valid_array_reference (name))
|
||||
{
|
||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* disallow self references at global scope */
|
||||
if (STREQ (name, value) && variable_context == 0)
|
||||
{
|
||||
builtin_error (_("%s: nameref variable self references not allowed"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
compound_array_assign = simple_array_assign = 0;
|
||||
subscript_start = (char *)NULL;
|
||||
|
|
@ -334,16 +365,17 @@ declare_internal (list, local_var)
|
|||
/* XXX - this has consequences when we're making a local copy of a
|
||||
variable that was in the temporary environment. Watch out
|
||||
for this. */
|
||||
refvar = (SHELL_VAR *)NULL;
|
||||
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
var = make_local_assoc_variable (name);
|
||||
else if ((flags_on & att_array) || making_array_special)
|
||||
var = make_local_array_variable (name);
|
||||
var = make_local_array_variable (name, making_array_special);
|
||||
else
|
||||
#endif
|
||||
var = make_local_variable (name);
|
||||
var = make_local_variable (name); /* sets att_invisible for new vars */
|
||||
if (var == 0)
|
||||
{
|
||||
any_failed++;
|
||||
|
|
@ -415,6 +447,33 @@ declare_internal (list, local_var)
|
|||
else /* declare -[aAirx] name [name...] */
|
||||
{
|
||||
/* Non-null if we just created or fetched a local variable. */
|
||||
/* Here's what ksh93 seems to do. If we are modifying an existing
|
||||
nameref variable, we don't follow the nameref chain past the last
|
||||
nameref, and we set the nameref variable's value so future
|
||||
references to that variable will return the value of the variable
|
||||
we're assigning right now. */
|
||||
if (var == 0 && (flags_on & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
if (var && nameref_p (var) == 0)
|
||||
var = 0;
|
||||
}
|
||||
/* However, if we're turning off the nameref attribute on an existing
|
||||
nameref variable, we first follow the nameref chain to the end,
|
||||
modify the value of the variable this nameref variable references,
|
||||
*CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
|
||||
flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
|
||||
else if (var == 0 && (flags_off & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
if (refvar && nameref_p (refvar) == 0)
|
||||
refvar = 0;
|
||||
if (refvar)
|
||||
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
|
||||
}
|
||||
|
||||
if (var == 0)
|
||||
var = mkglobal ? find_global_variable (name) : find_variable (name);
|
||||
|
||||
|
|
@ -422,20 +481,40 @@ declare_internal (list, local_var)
|
|||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
var = make_new_assoc_variable (name);
|
||||
{
|
||||
var = make_new_assoc_variable (name);
|
||||
if (offset == 0)
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
else if ((flags_on & att_array) || making_array_special)
|
||||
var = make_new_array_variable (name);
|
||||
{
|
||||
var = make_new_array_variable (name);
|
||||
if (offset == 0)
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (offset)
|
||||
var = bind_variable (name, "", 0);
|
||||
var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
|
||||
else
|
||||
{
|
||||
var = bind_variable (name, (char *)NULL, 0);
|
||||
var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
}
|
||||
/* Can't take an existing array variable and make it a nameref */
|
||||
else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
|
||||
{
|
||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else if (flags_on & att_nameref)
|
||||
{
|
||||
/* ksh93 compat: turning on nameref attribute turns off -ilu */
|
||||
VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
|
||||
}
|
||||
|
||||
/* Cannot use declare +r to turn off readonly attribute. */
|
||||
if (readonly_p (var) && (flags_off & att_readonly))
|
||||
|
|
@ -501,6 +580,25 @@ declare_internal (list, local_var)
|
|||
var = convert_var_to_array (var);
|
||||
#endif /* ARRAY_VARS */
|
||||
|
||||
/* XXX - we note that we are turning on nameref attribute and defer
|
||||
setting it until the assignment has been made so we don't do an
|
||||
inadvertent nameref lookup. Might have to do the same thing for
|
||||
flags_off&att_nameref. */
|
||||
/* XXX - ksh93 makes it an error to set a readonly nameref variable
|
||||
using a single typeset command. */
|
||||
onref = (flags_on & att_nameref);
|
||||
flags_on &= ~att_nameref;
|
||||
#if defined (ARRAY_VARS)
|
||||
if (array_p (var) || assoc_p (var)
|
||||
|| (offset && compound_array_assign)
|
||||
|| simple_array_assign)
|
||||
onref = 0; /* array variables may not be namerefs */
|
||||
#endif
|
||||
|
||||
/* ksh93 seems to do this */
|
||||
offref = (flags_off & att_nameref);
|
||||
flags_off &= ~att_nameref;
|
||||
|
||||
VSETATTR (var, flags_on);
|
||||
VUNSETATTR (var, flags_off);
|
||||
|
||||
|
|
@ -516,6 +614,8 @@ declare_internal (list, local_var)
|
|||
if (var == 0) /* some kind of assignment error */
|
||||
{
|
||||
assign_error++;
|
||||
flags_on |= onref;
|
||||
flags_off |= offref;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
|
|
@ -532,7 +632,19 @@ declare_internal (list, local_var)
|
|||
/* bind_variable_value duplicates the essential internals of
|
||||
bind_variable() */
|
||||
if (offset)
|
||||
bind_variable_value (var, value, aflags);
|
||||
{
|
||||
if (onref)
|
||||
aflags |= ASS_NAMEREF;
|
||||
v = bind_variable_value (var, value, aflags);
|
||||
if (v == 0 && onref)
|
||||
{
|
||||
sh_invalidid (value);
|
||||
assign_error++;
|
||||
/* XXX - unset this variable? or leave it as normal var? */
|
||||
delete_var (var->name, mkglobal ? global_variables : shell_variables);
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found this variable in the temporary environment, as with
|
||||
`var=value declare -x var', make sure it is treated identically
|
||||
|
|
@ -562,6 +674,17 @@ declare_internal (list, local_var)
|
|||
}
|
||||
}
|
||||
|
||||
/* Turn on nameref attribute we deferred above. */
|
||||
/* XXX - should we turn on the noassign attribute for consistency with
|
||||
ksh93 when we turn on the nameref attribute? */
|
||||
VSETATTR (var, onref);
|
||||
flags_on |= onref;
|
||||
VUNSETATTR (var, offref);
|
||||
flags_off |= offref;
|
||||
/* Yuck. ksh93 compatibility */
|
||||
if (refvar)
|
||||
VUNSETATTR (refvar, flags_off);
|
||||
|
||||
stupidly_hack_special_variables (name);
|
||||
|
||||
NEXT_VARIABLE ();
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ $DEPENDS_ON V9_ECHO
|
|||
$SHORT_DOC echo [-neE] [arg ...]
|
||||
Write arguments to the standard output.
|
||||
|
||||
Display the ARGs on the standard output followed by a newline.
|
||||
Display the ARGs, separated by a single space character and followed by a
|
||||
newline, on the standard output.
|
||||
|
||||
Options:
|
||||
-n do not append a newline
|
||||
|
|
@ -50,6 +51,7 @@ Options:
|
|||
\b backspace
|
||||
\c suppress further output
|
||||
\e escape character
|
||||
\E escape character
|
||||
\f form feed
|
||||
\n new line
|
||||
\r carriage return
|
||||
|
|
|
|||
|
|
@ -53,6 +53,5 @@ eval_builtin (list)
|
|||
return (EX_USAGE);
|
||||
list = loptend; /* skip over possible `--' */
|
||||
|
||||
/* Note that parse_and_execute () frees the string it is passed. */
|
||||
return (list ? parse_and_execute (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS);
|
||||
return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,11 +109,16 @@ _evalfile (filename, flags)
|
|||
GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
fd = open (filename, O_RDONLY);
|
||||
|
||||
if (fd < 0 || (fstat (fd, &finfo) == -1))
|
||||
{
|
||||
i = errno;
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
errno = i;
|
||||
|
||||
file_error_and_exit:
|
||||
if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
|
||||
file_error (filename);
|
||||
|
|
@ -133,11 +138,13 @@ file_error_and_exit:
|
|||
if (S_ISDIR (finfo.st_mode))
|
||||
{
|
||||
(*errfunc) (_("%s: is a directory"), filename);
|
||||
close (fd);
|
||||
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
||||
}
|
||||
else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
|
||||
{
|
||||
(*errfunc) (_("%s: not a regular file"), filename);
|
||||
close (fd);
|
||||
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +153,7 @@ file_error_and_exit:
|
|||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
(*errfunc) (_("%s: file is too large"), filename);
|
||||
close (fd);
|
||||
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +259,7 @@ file_error_and_exit:
|
|||
if (flags & FEVAL_BUILTIN)
|
||||
result = EXECUTION_SUCCESS;
|
||||
|
||||
return_val = setjmp (return_catch);
|
||||
return_val = setjmp_nosigs (return_catch);
|
||||
|
||||
/* If `return' was seen outside of a function, but in the script, then
|
||||
force parse_and_execute () to clean up. */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* evalstring.c - evaluate a string as one or more shell commands. */
|
||||
|
||||
/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ extern int errno;
|
|||
#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
|
||||
|
||||
extern int indirection_level, subshell_environment;
|
||||
extern int line_number;
|
||||
extern int line_number, line_number_for_err_trap;
|
||||
extern int current_token, shell_eof_token;
|
||||
extern int last_command_exit_value;
|
||||
extern int running_trap;
|
||||
|
|
@ -69,7 +69,9 @@ extern int loop_level;
|
|||
extern int executing_list;
|
||||
extern int comsub_ignore_return;
|
||||
extern int posixly_correct;
|
||||
extern int return_catch_flag, return_catch_value;
|
||||
extern sh_builtin_func_t *this_shell_builtin;
|
||||
extern char *the_printed_command_except_trap;
|
||||
|
||||
int parse_and_execute_level = 0;
|
||||
|
||||
|
|
@ -86,6 +88,14 @@ set_history_remembering ()
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
restore_lastcom (x)
|
||||
char *x;
|
||||
{
|
||||
FREE (the_printed_command_except_trap);
|
||||
the_printed_command_except_trap = x;
|
||||
}
|
||||
|
||||
/* How to force parse_and_execute () to clean up after itself. */
|
||||
void
|
||||
parse_and_execute_cleanup ()
|
||||
|
|
@ -108,7 +118,7 @@ parse_prologue (string, flags, tag)
|
|||
int flags;
|
||||
char *tag;
|
||||
{
|
||||
char *orig_string;
|
||||
char *orig_string, *lastcom;
|
||||
int x;
|
||||
|
||||
orig_string = string;
|
||||
|
|
@ -118,6 +128,7 @@ parse_prologue (string, flags, tag)
|
|||
unwind_protect_jmp_buf (top_level);
|
||||
unwind_protect_int (indirection_level);
|
||||
unwind_protect_int (line_number);
|
||||
unwind_protect_int (line_number_for_err_trap);
|
||||
unwind_protect_int (loop_level);
|
||||
unwind_protect_int (executing_list);
|
||||
unwind_protect_int (comsub_ignore_return);
|
||||
|
|
@ -140,8 +151,17 @@ parse_prologue (string, flags, tag)
|
|||
x = get_current_prompt_level ();
|
||||
add_unwind_protect (set_current_prompt_level, x);
|
||||
}
|
||||
|
||||
|
||||
if (the_printed_command_except_trap)
|
||||
{
|
||||
lastcom = savestring (the_printed_command_except_trap);
|
||||
add_unwind_protect (restore_lastcom, lastcom);
|
||||
}
|
||||
|
||||
add_unwind_protect (pop_stream, (char *)NULL);
|
||||
if (parser_expanding_alias ())
|
||||
add_unwind_protect (parser_restore_alias, (char *)NULL);
|
||||
|
||||
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
|
||||
add_unwind_protect (xfree, orig_string);
|
||||
end_unwind_frame ();
|
||||
|
|
@ -175,6 +195,7 @@ parse_and_execute (string, from_file, flags)
|
|||
int code, lreset;
|
||||
volatile int should_jump_to_top_level, last_result;
|
||||
COMMAND *volatile command;
|
||||
volatile sigset_t pe_sigmask;
|
||||
|
||||
parse_prologue (string, flags, PE_TAG);
|
||||
|
||||
|
|
@ -182,11 +203,21 @@ parse_and_execute (string, from_file, flags)
|
|||
|
||||
lreset = flags & SEVAL_RESETLINE;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
/* If we longjmp and are going to go on, use this to restore signal mask */
|
||||
sigemptyset (&pe_sigmask);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &pe_sigmask);
|
||||
#endif
|
||||
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (lreset);
|
||||
if (parser_expanding_alias ())
|
||||
/* push current shell_input_line */
|
||||
parser_save_alias ();
|
||||
|
||||
if (lreset == 0)
|
||||
line_number--;
|
||||
|
||||
|
|
@ -209,15 +240,28 @@ parse_and_execute (string, from_file, flags)
|
|||
/* 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);
|
||||
code = setjmp_nosigs (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
should_jump_to_top_level = 0;
|
||||
switch (code)
|
||||
{
|
||||
case FORCE_EOF:
|
||||
case ERREXIT:
|
||||
/* variable_context -> 0 is what eval.c:reader_loop() does in
|
||||
these circumstances. Don't bother with cleanup here because
|
||||
we don't want to run the function execution cleanup stuff
|
||||
that will cause pop_context and other functions to run.
|
||||
XXX - change that if we want the function context to be
|
||||
unwound. */
|
||||
if (exit_immediately_on_error && variable_context)
|
||||
{
|
||||
discard_unwind_frame ("pe_dispose");
|
||||
variable_context = 0; /* not in a function */
|
||||
}
|
||||
should_jump_to_top_level = 1;
|
||||
goto out;
|
||||
case FORCE_EOF:
|
||||
case EXITPROG:
|
||||
if (command)
|
||||
run_unwind_frame ("pe_dispose");
|
||||
|
|
@ -239,6 +283,9 @@ parse_and_execute (string, from_file, flags)
|
|||
{
|
||||
#if 0
|
||||
dispose_command (command); /* pe_dispose does this */
|
||||
#endif
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &pe_sigmask, (sigset_t *)NULL);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
|
@ -308,7 +355,8 @@ parse_and_execute (string, from_file, flags)
|
|||
command->value.Simple->words == 0 &&
|
||||
command->value.Simple->redirects &&
|
||||
command->value.Simple->redirects->next == 0 &&
|
||||
command->value.Simple->redirects->instruction == r_input_direction)
|
||||
command->value.Simple->redirects->instruction == r_input_direction &&
|
||||
command->value.Simple->redirects->redirector.dest == 0)
|
||||
{
|
||||
int r;
|
||||
r = cat_file (command->value.Simple->redirects);
|
||||
|
|
@ -317,7 +365,6 @@ parse_and_execute (string, from_file, flags)
|
|||
else
|
||||
last_result = execute_command_internal
|
||||
(command, 0, NO_PIPE, NO_PIPE, bitmap);
|
||||
|
||||
dispose_command (command);
|
||||
dispose_fd_bitmap (bitmap);
|
||||
discard_unwind_frame ("pe_dispose");
|
||||
|
|
@ -377,15 +424,26 @@ parse_string (string, from_file, flags, endp)
|
|||
volatile int should_jump_to_top_level;
|
||||
COMMAND *volatile command, *oglobal;
|
||||
char *ostring;
|
||||
volatile sigset_t ps_sigmask;
|
||||
|
||||
parse_prologue (string, flags, PS_TAG);
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
/* If we longjmp and are going to go on, use this to restore signal mask */
|
||||
sigemptyset (&ps_sigmask);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &ps_sigmask);
|
||||
#endif
|
||||
|
||||
/* itrace("parse_string: `%s'", string); */
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (0);
|
||||
|
||||
if (parser_expanding_alias ())
|
||||
/* push current shell_input_line */
|
||||
parser_save_alias ();
|
||||
|
||||
code = should_jump_to_top_level = 0;
|
||||
oglobal = global_command;
|
||||
ostring = string;
|
||||
|
|
@ -402,7 +460,7 @@ parse_string (string, from_file, flags, endp)
|
|||
|
||||
/* Provide a location for functions which `longjmp (top_level)' to
|
||||
jump to. */
|
||||
code = setjmp (top_level);
|
||||
code = setjmp_nosigs (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
|
|
@ -424,6 +482,9 @@ itrace("parse_string: longjmp executed: code = %d", code);
|
|||
goto out;
|
||||
|
||||
default:
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &ps_sigmask, (sigset_t *)NULL);
|
||||
#endif
|
||||
command_error ("parse_string", CMDERR_BADJUMP, code, 0);
|
||||
break;
|
||||
}
|
||||
|
|
@ -506,3 +567,49 @@ cat_file (r)
|
|||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
int
|
||||
evalstring (string, from_file, flags)
|
||||
char *string;
|
||||
const char *from_file;
|
||||
int flags;
|
||||
{
|
||||
volatile int r, rflag, rcatch;
|
||||
|
||||
rcatch = 0;
|
||||
rflag = return_catch_flag;
|
||||
/* If we are in a place where `return' is valid, we have to catch
|
||||
`eval "... return"' and make sure parse_and_execute cleans up. Then
|
||||
we can trampoline to the previous saved return_catch location. */
|
||||
if (rflag)
|
||||
{
|
||||
begin_unwind_frame ("evalstring");
|
||||
|
||||
unwind_protect_int (return_catch_flag);
|
||||
unwind_protect_jmp_buf (return_catch);
|
||||
|
||||
return_catch_flag++; /* increment so we have a counter */
|
||||
rcatch = setjmp_nosigs (return_catch);
|
||||
}
|
||||
|
||||
if (rcatch)
|
||||
{
|
||||
parse_and_execute_cleanup ();
|
||||
r = return_catch_value;
|
||||
}
|
||||
else
|
||||
/* Note that parse_and_execute () frees the string it is passed. */
|
||||
r = parse_and_execute (string, from_file, flags);
|
||||
|
||||
if (rflag)
|
||||
{
|
||||
run_unwind_frame ("evalstring");
|
||||
if (rcatch && return_catch_flag)
|
||||
{
|
||||
return_catch_value = r;
|
||||
longjmp (return_catch, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is exec.def, from which is created exec.c.
|
||||
It implements the builtin "exec" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ exec_builtin (list)
|
|||
args = strvec_from_word_list (list, 1, 0, (int *)NULL);
|
||||
|
||||
/* 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 = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
|
||||
|
||||
if (command == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is fc.def, from which is created fc.c.
|
||||
It implements the builtin "fc" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ $END
|
|||
#include <config.h>
|
||||
|
||||
#if defined (HISTORY)
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include "../bashtypes.h"
|
||||
|
|
@ -85,7 +85,7 @@ $END
|
|||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int current_command_line_count, saved_command_line_count;
|
||||
extern int current_command_line_count;
|
||||
extern int literal_history;
|
||||
extern int posixly_correct;
|
||||
extern int subshell_environment, interactive_shell;
|
||||
|
|
@ -173,7 +173,7 @@ fc_builtin (list)
|
|||
register int i;
|
||||
register char *sep;
|
||||
int numbering, reverse, listing, execute;
|
||||
int histbeg, histend, last_hist, retval, opt, rh;
|
||||
int histbeg, histend, last_hist, retval, opt, rh, real_last;
|
||||
FILE *stream;
|
||||
REPL *rlist, *rl;
|
||||
char *ename, *command, *newcom, *fcedit;
|
||||
|
|
@ -303,6 +303,14 @@ fc_builtin (list)
|
|||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
||||
last_hist = i - rh - hist_last_line_added;
|
||||
|
||||
/* Make sure that real_last is calculated the same way here and in
|
||||
fc_gethnum. The return value from fc_gethnum is treated specially if
|
||||
it is == real_last and we are listing commands. */
|
||||
real_last = i;
|
||||
/* back up from the end to the last non-null history entry */
|
||||
while (hlist[real_last] == 0 && real_last > 0)
|
||||
real_last--;
|
||||
|
||||
/* XXX */
|
||||
if (i == last_hist && hlist[last_hist] == 0)
|
||||
while (last_hist >= 0 && hlist[last_hist] == 0)
|
||||
|
|
@ -320,6 +328,8 @@ fc_builtin (list)
|
|||
|
||||
if (list)
|
||||
histend = fc_gethnum (list->word->word, hlist);
|
||||
else if (histbeg == real_last)
|
||||
histend = listing ? real_last : histbeg;
|
||||
else
|
||||
histend = listing ? last_hist : histbeg;
|
||||
}
|
||||
|
|
@ -475,7 +485,7 @@ fc_gethnum (command, hlist)
|
|||
HIST_ENTRY **hlist;
|
||||
{
|
||||
int sign, n, clen, rh;
|
||||
register int i, j, last_hist;
|
||||
register int i, j, last_hist, real_last;
|
||||
register char *s;
|
||||
|
||||
sign = 1;
|
||||
|
|
@ -503,12 +513,17 @@ fc_gethnum (command, hlist)
|
|||
if (last_hist < 0)
|
||||
return (-1);
|
||||
|
||||
real_last = i;
|
||||
i = last_hist;
|
||||
|
||||
/* No specification defaults to most recent command. */
|
||||
if (command == NULL)
|
||||
return (i);
|
||||
|
||||
/* back up from the end to the last non-null history entry */
|
||||
while (hlist[real_last] == 0 && real_last > 0)
|
||||
real_last--;
|
||||
|
||||
/* Otherwise, there is a specification. It can be a number relative to
|
||||
the current position, or an absolute history number. */
|
||||
s = command;
|
||||
|
|
@ -533,7 +548,7 @@ fc_gethnum (command, hlist)
|
|||
return (n < 0 ? 0 : n);
|
||||
}
|
||||
else if (n == 0)
|
||||
return (i);
|
||||
return ((sign == -1) ? real_last : i);
|
||||
else
|
||||
{
|
||||
n -= history_base;
|
||||
|
|
|
|||
197
builtins/gen-helpfiles.c
Normal file
197
builtins/gen-helpfiles.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/* gen-helpfiles - create files containing builtin help text */
|
||||
|
||||
/* Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This links with a specially-generated version of builtins.c and takes
|
||||
the long_doc members of each struct builtin element and writes those to
|
||||
the file named by the `handle' member of the struct builtin element. */
|
||||
|
||||
#if !defined (CROSS_COMPILING)
|
||||
# include <config.h>
|
||||
#else /* CROSS_COMPILING */
|
||||
/* A conservative set of defines based on POSIX/SUS3/XPG6 */
|
||||
# define HAVE_UNISTD_H
|
||||
# define HAVE_STRING_H
|
||||
# define HAVE_STDLIB_H
|
||||
|
||||
# define HAVE_RENAME
|
||||
#endif /* CROSS_COMPILING */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MINIX
|
||||
# include "../bashtypes.h"
|
||||
# if defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "posixstat.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include "../builtins.h"
|
||||
#include "tmpbuiltins.h"
|
||||
|
||||
#if defined (USING_BASH_MALLOC)
|
||||
#undef xmalloc
|
||||
#undef xrealloc
|
||||
#undef xfree
|
||||
|
||||
#undef free /* defined in xmalloc.h */
|
||||
#endif
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if !defined (__STDC__) && !defined (strcpy)
|
||||
extern char *strcpy ();
|
||||
#endif /* !__STDC__ && !strcpy */
|
||||
|
||||
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
|
||||
|
||||
/* Flag values that builtins can have. */
|
||||
#define BUILTIN_FLAG_SPECIAL 0x01
|
||||
#define BUILTIN_FLAG_ASSIGNMENT 0x02
|
||||
#define BUILTIN_FLAG_POSIX_BUILTIN 0x04
|
||||
|
||||
#define BASE_INDENT 4
|
||||
|
||||
/* Non-zero means to produce separate help files for each builtin, named by
|
||||
the builtin name, in `./helpfiles'. */
|
||||
int separate_helpfiles = 0;
|
||||
|
||||
/* Non-zero means to create single C strings for each `longdoc', with
|
||||
embedded newlines, for ease of translation. */
|
||||
int single_longdoc_strings = 1;
|
||||
|
||||
/* The name of a directory into which the separate external help files will
|
||||
eventually be installed. */
|
||||
char *helpfile_directory;
|
||||
|
||||
/* Forward declarations. */
|
||||
|
||||
int write_helpfiles __P((struct builtin *));
|
||||
|
||||
/* 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;
|
||||
{
|
||||
int arg_index = 1;
|
||||
|
||||
while (arg_index < argc && argv[arg_index][0] == '-')
|
||||
{
|
||||
char *arg = argv[arg_index++];
|
||||
|
||||
if (strcmp (arg, "-noproduction") == 0)
|
||||
;
|
||||
else if (strcmp (arg, "-H") == 0)
|
||||
helpfile_directory = argv[arg_index++];
|
||||
else if (strcmp (arg, "-S") == 0)
|
||||
single_longdoc_strings = 0;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
|
||||
exit (2);
|
||||
}
|
||||
}
|
||||
|
||||
write_helpfiles(shell_builtins);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
|
||||
and quoting special characters in the string. Handle special things for
|
||||
internationalization (gettext) and the single-string vs. multiple-strings
|
||||
issues. */
|
||||
void
|
||||
write_documentation (stream, documentation, indentation)
|
||||
FILE *stream;
|
||||
char *documentation;
|
||||
int indentation;
|
||||
{
|
||||
if (stream == 0)
|
||||
return;
|
||||
|
||||
if (documentation)
|
||||
fprintf (stream, "%*s%s\n", indentation, " ", documentation);
|
||||
}
|
||||
|
||||
int
|
||||
write_helpfiles (builtins)
|
||||
struct builtin *builtins;
|
||||
{
|
||||
char *helpfile, *bname, *fname;
|
||||
FILE *helpfp;
|
||||
int i, hdlen;
|
||||
struct builtin b;
|
||||
|
||||
i = mkdir ("helpfiles", 0777);
|
||||
if (i < 0 && errno != EEXIST)
|
||||
{
|
||||
fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdlen = strlen ("helpfiles/");
|
||||
for (i = 0; i < num_shell_builtins; i++)
|
||||
{
|
||||
b = builtins[i];
|
||||
|
||||
fname = (char *)b.handle;
|
||||
helpfile = (char *)malloc (hdlen + strlen (fname) + 1);
|
||||
if (helpfile == 0)
|
||||
{
|
||||
fprintf (stderr, "gen-helpfiles: cannot allocate memory\n");
|
||||
exit (1);
|
||||
}
|
||||
sprintf (helpfile, "helpfiles/%s", fname);
|
||||
|
||||
helpfp = fopen (helpfile, "w");
|
||||
if (helpfp == 0)
|
||||
{
|
||||
fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
|
||||
free (helpfile);
|
||||
continue;
|
||||
}
|
||||
|
||||
write_documentation (helpfp, b.long_doc[0], 4);
|
||||
|
||||
fflush (helpfp);
|
||||
fclose (helpfp);
|
||||
free (helpfile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
This file is hash.def, from which is created hash.c.
|
||||
It implements the builtin "hash" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ no arguments are given, information about remembered commands is displayed.
|
|||
Options:
|
||||
-d forget the remembered location of each NAME
|
||||
-l display in a format that may be reused as input
|
||||
-p pathname use PATHNAME is the full pathname of NAME
|
||||
-p pathname use PATHNAME as the full pathname of NAME
|
||||
-r forget all remembered locations
|
||||
-t print the remembered location of each NAME, preceding
|
||||
each location with the corresponding NAME if multiple
|
||||
|
|
@ -276,6 +276,7 @@ list_hashed_filename_targets (list, fmt)
|
|||
printf ("%s\t", l->word->word);
|
||||
printf ("%s\n", target);
|
||||
}
|
||||
free (target);
|
||||
}
|
||||
|
||||
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is help.def, from which is created help.c.
|
||||
It implements the builtin "help" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ help_builtin (list)
|
|||
{
|
||||
register int i;
|
||||
char *pattern, *name;
|
||||
int plen, match_found, sflag, dflag, mflag;
|
||||
int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
|
||||
|
||||
dflag = sflag = mflag = 0;
|
||||
reset_internal_getopt ();
|
||||
|
|
@ -137,29 +137,43 @@ help_builtin (list)
|
|||
pattern = list->word->word;
|
||||
plen = strlen (pattern);
|
||||
|
||||
for (i = 0; name = shell_builtins[i].name; i++)
|
||||
for (pass = 1, this_found = 0; pass < 3; pass++)
|
||||
{
|
||||
QUIT;
|
||||
if ((strncmp (pattern, name, plen) == 0) ||
|
||||
(strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH))
|
||||
for (i = 0; name = shell_builtins[i].name; i++)
|
||||
{
|
||||
match_found++;
|
||||
if (dflag)
|
||||
{
|
||||
show_desc (name, i);
|
||||
continue;
|
||||
}
|
||||
else if (mflag)
|
||||
{
|
||||
show_manpage (name, i);
|
||||
continue;
|
||||
}
|
||||
QUIT;
|
||||
|
||||
printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
|
||||
/* First pass: look for exact string or pattern matches.
|
||||
Second pass: look for prefix matches like bash-4.2 */
|
||||
if (pass == 1)
|
||||
m = (strcmp (pattern, name) == 0) ||
|
||||
(strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
|
||||
else
|
||||
m = strncmp (pattern, name, plen) == 0;
|
||||
|
||||
if (sflag == 0)
|
||||
show_longdoc (i);
|
||||
if (m)
|
||||
{
|
||||
this_found = 1;
|
||||
match_found++;
|
||||
if (dflag)
|
||||
{
|
||||
show_desc (name, i);
|
||||
continue;
|
||||
}
|
||||
else if (mflag)
|
||||
{
|
||||
show_manpage (name, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
|
||||
|
||||
if (sflag == 0)
|
||||
show_longdoc (i);
|
||||
}
|
||||
}
|
||||
if (pass == 1 && this_found == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +223,7 @@ show_longdoc (i)
|
|||
zcatfd (fd, 1, doc[0]);
|
||||
close (fd);
|
||||
}
|
||||
else
|
||||
else if (doc)
|
||||
for (j = 0; doc[j]; j++)
|
||||
printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
|
||||
}
|
||||
|
|
@ -326,6 +340,140 @@ show_manpage (name, i)
|
|||
free (line);
|
||||
}
|
||||
|
||||
static void
|
||||
dispcolumn (i, buf, bufsize, width, height)
|
||||
int i;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
int width, height;
|
||||
{
|
||||
int j;
|
||||
int displen;
|
||||
char *helpdoc;
|
||||
|
||||
/* first column */
|
||||
helpdoc = _(shell_builtins[i].short_doc);
|
||||
|
||||
buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (buf + 1, helpdoc, width - 2);
|
||||
buf[width - 2] = '>'; /* indicate truncation */
|
||||
buf[width - 1] = '\0';
|
||||
printf ("%s", buf);
|
||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
||||
{
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
displen = strlen (buf);
|
||||
/* two spaces */
|
||||
for (j = displen; j < width; j++)
|
||||
putc (' ', stdout);
|
||||
|
||||
/* second column */
|
||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
||||
|
||||
buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (buf + 1, helpdoc, width - 3);
|
||||
buf[width - 3] = '>'; /* indicate truncation */
|
||||
buf[width - 2] = '\0';
|
||||
|
||||
printf ("%s\n", buf);
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static void
|
||||
wdispcolumn (i, buf, bufsize, width, height)
|
||||
int i;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
int width, height;
|
||||
{
|
||||
int j;
|
||||
int displen;
|
||||
char *helpdoc;
|
||||
wchar_t *wcstr;
|
||||
size_t slen, n;
|
||||
int wclen;
|
||||
|
||||
/* first column */
|
||||
helpdoc = _(shell_builtins[i].short_doc);
|
||||
|
||||
wcstr = 0;
|
||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
||||
if (slen == -1)
|
||||
{
|
||||
dispcolumn (i, buf, bufsize, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
/* No bigger than the passed max width */
|
||||
if (slen >= width)
|
||||
slen = width - 2;
|
||||
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
|
||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
||||
wcstr[n+1] = L'\0';
|
||||
|
||||
/* Turn tabs and newlines into spaces for column display, since wcwidth
|
||||
returns -1 for them */
|
||||
for (j = 1; j < n; j++)
|
||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
||||
wcstr[j] = L' ';
|
||||
|
||||
displen = wcsnwidth (wcstr+1, slen, width - 2) + 1; /* +1 for ' ' or '*' */
|
||||
|
||||
wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
||||
|
||||
/* This assumes each wide char takes up one column position when displayed */
|
||||
wcstr[width - 2] = L'>'; /* indicate truncation */
|
||||
wcstr[width - 1] = L'\0';
|
||||
|
||||
printf ("%ls", wcstr);
|
||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
||||
{
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* at least one space */
|
||||
for (j = displen; j < width; j++)
|
||||
putc (' ', stdout);
|
||||
|
||||
/* second column */
|
||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
||||
if (slen == -1)
|
||||
{
|
||||
/* for now */
|
||||
printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reuse wcstr since it is already width wide chars long */
|
||||
if (slen >= width)
|
||||
slen = width - 2;
|
||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
||||
wcstr[n+1] = L'\0'; /* make sure null-terminated */
|
||||
|
||||
/* Turn tabs and newlines into spaces for column display */
|
||||
for (j = 1; j < n; j++)
|
||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
||||
wcstr[j] = L' ';
|
||||
|
||||
displen = wcsnwidth (wcstr+1, slen, width - 2);
|
||||
|
||||
wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
||||
|
||||
/* This assumes each wide char takes up one column position when displayed */
|
||||
wcstr[width - 3] = L'>'; /* indicate truncation */
|
||||
wcstr[width - 2] = L'\0';
|
||||
|
||||
printf ("%ls\n", wcstr);
|
||||
|
||||
free (wcstr);
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
static void
|
||||
show_builtin_command_help ()
|
||||
{
|
||||
|
|
@ -358,28 +506,12 @@ A star (*) next to a name means that the command is disabled.\n\
|
|||
{
|
||||
QUIT;
|
||||
|
||||
/* first column */
|
||||
blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (blurb + 1, _(shell_builtins[i].short_doc), width - 2);
|
||||
blurb[width - 2] = '>'; /* indicate truncation */
|
||||
blurb[width - 1] = '\0';
|
||||
printf ("%s", blurb);
|
||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
||||
{
|
||||
printf ("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* two spaces */
|
||||
for (j = strlen (blurb); j < width; j++)
|
||||
putc (' ', stdout);
|
||||
|
||||
/* second column */
|
||||
blurb[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (blurb + 1, _(shell_builtins[i+height].short_doc), width - 3);
|
||||
blurb[width - 3] = '>'; /* indicate truncation */
|
||||
blurb[width - 2] = '\0';
|
||||
printf ("%s\n", blurb);
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1)
|
||||
wdispcolumn (i, blurb, sizeof (blurb), width, height);
|
||||
else
|
||||
#endif
|
||||
dispcolumn (i, blurb, sizeof (blurb), width, height);
|
||||
}
|
||||
}
|
||||
#endif /* HELP_BUILTIN */
|
||||
|
|
|
|||
|
|
@ -324,9 +324,10 @@ push_history (list)
|
|||
If you don't want history -s to remove the compound command from the
|
||||
history, change #if 0 to #if 1 below. */
|
||||
#if 0
|
||||
if (hist_last_line_pushed == 0 && hist_last_line_added && bash_delete_last_history () == 0)
|
||||
if (remember_on_history && hist_last_line_pushed == 0 &&
|
||||
hist_last_line_added && bash_delete_last_history () == 0)
|
||||
#else
|
||||
if (hist_last_line_pushed == 0 &&
|
||||
if (remember_on_history && hist_last_line_pushed == 0 &&
|
||||
(hist_last_line_added ||
|
||||
(current_command_line_count > 0 && current_command_first_line_saved && command_oriented_history))
|
||||
&& bash_delete_last_history () == 0)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Without options, the status of all active jobs is displayed.
|
|||
|
||||
Options:
|
||||
-l lists process IDs in addition to the normal information
|
||||
-n list only processes that have changed status since the last
|
||||
-n lists only processes that have changed status since the last
|
||||
notification
|
||||
-p lists process IDs only
|
||||
-r restrict output to running jobs
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ $END
|
|||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../trap.h"
|
||||
#include "../jobs.h"
|
||||
|
|
@ -92,7 +94,7 @@ kill_builtin (list)
|
|||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
any_succeeded = listing = saw_signal = 0;
|
||||
|
|
@ -137,7 +139,7 @@ kill_builtin (list)
|
|||
else if (ISOPTION (word, '?'))
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
/* If this is a signal specification then process it. We only process
|
||||
the first one seen; other arguments may signify process groups (e.g,
|
||||
|
|
@ -166,7 +168,7 @@ kill_builtin (list)
|
|||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
while (list)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ This file is mapfile.def, from which is created mapfile.c.
|
|||
It implements the builtin "mapfile" in Bash.
|
||||
|
||||
Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ run_callback (callback, curindex, curline)
|
|||
#endif
|
||||
snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
|
||||
free (qline);
|
||||
return parse_and_execute (execstr, NULL, flags);
|
||||
return evalstring (execstr, NULL, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -172,6 +172,8 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
|
|||
builtin_error (_("%s: not an indexed array"), array_name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else if (invisible_p (entry))
|
||||
VUNSETATTR (entry, att_invisible); /* no longer invisible */
|
||||
|
||||
if (flags & MAPF_CLEARARRAY)
|
||||
array_flush (array_cell (entry));
|
||||
|
|
@ -193,7 +195,6 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
|
|||
line_length = 0;
|
||||
|
||||
/* Reset the buffer for bash own stream */
|
||||
interrupt_immediately++;
|
||||
for (array_index = origin, line_count = 1;
|
||||
zgetline (fd, &line, &line_length, unbuffered_read) != -1;
|
||||
array_index++)
|
||||
|
|
@ -212,6 +213,8 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
|
|||
zsyncfd (fd);
|
||||
}
|
||||
|
||||
/* XXX - bad things can happen if the callback modifies ENTRY, e.g.,
|
||||
unsetting it or changing it to a non-indexed-array type. */
|
||||
bind_array_element (entry, array_index, line, 0);
|
||||
|
||||
/* Have we exceeded # of lines to store? */
|
||||
|
|
@ -225,7 +228,6 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
|
|||
if (unbuffered_read == 0)
|
||||
zsyncfd (fd);
|
||||
|
||||
interrupt_immediately--;
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
|
||||
a single source file called builtins.def. */
|
||||
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -85,6 +85,10 @@ int only_documentation = 0;
|
|||
/* Non-zero means to not do any productions. */
|
||||
int inhibit_production = 0;
|
||||
|
||||
/* Non-zero means to not add functions (xxx_builtin) to the members of the
|
||||
produced `struct builtin []' */
|
||||
int inhibit_functions = 0;
|
||||
|
||||
/* Non-zero means to produce separate help files for each builtin, named by
|
||||
the builtin name, in `./helpfiles'. */
|
||||
int separate_helpfiles = 0;
|
||||
|
|
@ -198,7 +202,7 @@ 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. */
|
||||
creating the production file if necessary. */
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
|
|
@ -222,6 +226,8 @@ main (argc, argv)
|
|||
struct_filename = argv[arg_index++];
|
||||
else if (strcmp (arg, "-noproduction") == 0)
|
||||
inhibit_production = 1;
|
||||
else if (strcmp (arg, "-nofunctions") == 0)
|
||||
inhibit_functions = 1;
|
||||
else if (strcmp (arg, "-document") == 0)
|
||||
documentation_file = fopen (documentation_filename, "w");
|
||||
else if (strcmp (arg, "-D") == 0)
|
||||
|
|
@ -322,10 +328,13 @@ main (argc, argv)
|
|||
fclose (externfile);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This is now done by a different program */
|
||||
if (separate_helpfiles)
|
||||
{
|
||||
write_helpfiles (saved_builtins);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (documentation_file)
|
||||
{
|
||||
|
|
@ -390,7 +399,7 @@ copy_string_array (array)
|
|||
return (copy);
|
||||
}
|
||||
|
||||
/* Add ELEMENT to ARRAY, growing the array if neccessary. */
|
||||
/* Add ELEMENT to ARRAY, growing the array if necessary. */
|
||||
void
|
||||
array_add (element, array)
|
||||
char *element;
|
||||
|
|
@ -519,6 +528,7 @@ extract_info (filename, structfile, externfile)
|
|||
if (nr == 0)
|
||||
{
|
||||
fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
|
||||
free (buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +547,7 @@ extract_info (filename, structfile, externfile)
|
|||
{
|
||||
array_add (&buffer[i], defs->lines);
|
||||
|
||||
while (buffer[i] != '\n' && i < file_size)
|
||||
while (i < file_size && buffer[i] != '\n')
|
||||
i++;
|
||||
buffer[i++] = '\0';
|
||||
}
|
||||
|
|
@ -1092,7 +1102,7 @@ char *structfile_header[] = {
|
|||
"/* This file is manufactured by ./mkbuiltins, and should not be",
|
||||
" edited by hand. See the source to mkbuiltins for details. */",
|
||||
"",
|
||||
"/* Copyright (C) 1987-2009 Free Software Foundation, Inc.",
|
||||
"/* Copyright (C) 1987-2012 Free Software Foundation, Inc.",
|
||||
"",
|
||||
" This file is part of GNU Bash, the Bourne Again SHell.",
|
||||
"",
|
||||
|
|
@ -1138,7 +1148,7 @@ char *structfile_footer[] = {
|
|||
(char *)NULL
|
||||
};
|
||||
|
||||
/* Write out any neccessary opening information for
|
||||
/* Write out any necessary opening information for
|
||||
STRUCTFILE and EXTERNFILE. */
|
||||
void
|
||||
write_file_headers (structfile, externfile)
|
||||
|
|
@ -1224,7 +1234,7 @@ write_builtins (defs, structfile, externfile)
|
|||
{
|
||||
fprintf (structfile, " { \"%s\", ", builtin->name);
|
||||
|
||||
if (builtin->function)
|
||||
if (builtin->function && inhibit_functions == 0)
|
||||
fprintf (structfile, "%s, ", builtin->function);
|
||||
else
|
||||
fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
|
||||
|
|
@ -1236,9 +1246,15 @@ write_builtins (defs, structfile, externfile)
|
|||
(builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
|
||||
document_name (builtin));
|
||||
|
||||
fprintf
|
||||
(structfile, " N_(\"%s\"), (char *)NULL },\n",
|
||||
builtin->shortdoc ? builtin->shortdoc : builtin->name);
|
||||
if (inhibit_functions)
|
||||
fprintf
|
||||
(structfile, " N_(\"%s\"), \"%s\" },\n",
|
||||
builtin->shortdoc ? builtin->shortdoc : builtin->name,
|
||||
document_name (builtin));
|
||||
else
|
||||
fprintf
|
||||
(structfile, " N_(\"%s\"), (char *)NULL },\n",
|
||||
builtin->shortdoc ? builtin->shortdoc : builtin->name);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1247,7 +1263,7 @@ write_builtins (defs, structfile, externfile)
|
|||
long documentation strings. */
|
||||
save_builtin (builtin);
|
||||
|
||||
/* Write out the matching #endif, if neccessary. */
|
||||
/* Write out the matching #endif, if necessary. */
|
||||
if (builtin->dependencies)
|
||||
{
|
||||
if (externfile)
|
||||
|
|
@ -1308,6 +1324,26 @@ write_longdocs (stream, builtins)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
write_dummy_declarations (stream, builtins)
|
||||
FILE *stream;
|
||||
ARRAY *builtins;
|
||||
{
|
||||
register int i;
|
||||
BUILTIN_DESC *builtin;
|
||||
|
||||
for (i = 0; structfile_header[i]; i++)
|
||||
fprintf (stream, "%s\n", structfile_header[i]);
|
||||
|
||||
for (i = 0; i < builtins->sindex; i++)
|
||||
{
|
||||
builtin = (BUILTIN_DESC *)builtins->array[i];
|
||||
|
||||
/* How to guarantee that no builtin is written more than once? */
|
||||
fprintf (stream, "int %s () { return (0); }\n", builtin->function);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write an #ifdef string saying what needs to be defined (or not defined)
|
||||
in order to allow compilation of the code that will follow.
|
||||
STREAM is the stream to write the information to,
|
||||
|
|
@ -1407,7 +1443,7 @@ write_documentation (stream, documentation, indentation, flags)
|
|||
|
||||
base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
|
||||
|
||||
for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
|
||||
for (i = 0, texinfo = (flags & TEXINFO); documentation && (line = documentation[i]); i++)
|
||||
{
|
||||
/* Allow #ifdef's to be written out verbatim, but don't put them into
|
||||
separate help files. */
|
||||
|
|
|
|||
|
|
@ -35,14 +35,19 @@ sequences, which are converted and copied to the standard output; and
|
|||
format specifications, each of which causes printing of the next successive
|
||||
argument.
|
||||
|
||||
In addition to the standard format specifications described in printf(1)
|
||||
and printf(3), printf interprets:
|
||||
In addition to the standard format specifications described in printf(1),
|
||||
printf interprets:
|
||||
|
||||
%b expand backslash escape sequences in the corresponding argument
|
||||
%q quote the argument in a way that can be reused as shell input
|
||||
%(fmt)T output the date-time string resulting from using FMT as a format
|
||||
string for strftime(3)
|
||||
|
||||
The format is re-used as necessary to consume all of the arguments. If
|
||||
there are fewer arguments than the format requires, extra format
|
||||
specifications behave as if a zero value or null string, as appropriate,
|
||||
had been supplied.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is given or a write or assignment
|
||||
error occurs.
|
||||
|
|
@ -158,7 +163,8 @@ extern int errno;
|
|||
else if (vbuf) \
|
||||
vbuf[0] = 0; \
|
||||
terminate_immediately--; \
|
||||
fflush (stdout); \
|
||||
if (ferror (stdout) == 0) \
|
||||
fflush (stdout); \
|
||||
if (ferror (stdout)) \
|
||||
{ \
|
||||
sh_wrerror (); \
|
||||
|
|
@ -460,7 +466,8 @@ printf_builtin (list)
|
|||
timefmt[2] = '\0';
|
||||
}
|
||||
/* argument is seconds since the epoch with special -1 and -2 */
|
||||
arg = getintmax ();
|
||||
/* default argument is equivalent to -1; special case */
|
||||
arg = garglist ? getintmax () : -1;
|
||||
if (arg == -1)
|
||||
secs = NOW; /* roughly date +%s */
|
||||
else if (arg == -2)
|
||||
|
|
@ -471,7 +478,12 @@ printf_builtin (list)
|
|||
sv_tz ("TZ"); /* XXX -- just make sure */
|
||||
#endif
|
||||
tm = localtime (&secs);
|
||||
n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
|
||||
if (tm == 0)
|
||||
{
|
||||
secs = 0;
|
||||
tm = localtime (&secs);
|
||||
}
|
||||
n = tm ? strftime (timebuf, sizeof (timebuf), timefmt, tm) : 0;
|
||||
free (timefmt);
|
||||
if (n == 0)
|
||||
timebuf[0] = '\0';
|
||||
|
|
@ -483,8 +495,11 @@ printf_builtin (list)
|
|||
n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
|
||||
if (n < 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
if (ferror (stdout) == 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
}
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
|
@ -524,8 +539,11 @@ printf_builtin (list)
|
|||
r = printstr (start, xp, rlen, fieldwidth, precision);
|
||||
if (r < 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
if (ferror (stdout) == 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
}
|
||||
retval = EXECUTION_FAILURE;
|
||||
}
|
||||
free (xp);
|
||||
|
|
@ -548,7 +566,7 @@ printf_builtin (list)
|
|||
else if (ansic_shouldquote (p))
|
||||
xp = ansic_quote (p, 0, (int *)0);
|
||||
else
|
||||
xp = sh_backslash_quote (p);
|
||||
xp = sh_backslash_quote (p, 0, 1);
|
||||
if (xp)
|
||||
{
|
||||
/* Use printstr to get fieldwidth and precision right. */
|
||||
|
|
@ -647,8 +665,7 @@ printf_builtin (list)
|
|||
|
||||
if (ferror (stdout))
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
/* PRETURN will print error message. */
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
@ -681,12 +698,9 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
#endif
|
||||
int padlen, nc, ljust, i;
|
||||
int fw, pr; /* fieldwidth and precision */
|
||||
intmax_t mfw, mpr;
|
||||
|
||||
#if 0
|
||||
if (string == 0 || *string == '\0')
|
||||
#else
|
||||
if (string == 0 || len == 0)
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
|
|
@ -697,6 +711,8 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
|
||||
ljust = fw = 0;
|
||||
pr = -1;
|
||||
mfw = 0;
|
||||
mpr = -1;
|
||||
|
||||
/* skip flags */
|
||||
while (strchr (SKIP1, *fmt))
|
||||
|
|
@ -706,7 +722,7 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
fmt++;
|
||||
}
|
||||
|
||||
/* get fieldwidth, if present */
|
||||
/* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
|
||||
if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
|
|
@ -719,9 +735,11 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
}
|
||||
else if (DIGIT (*fmt))
|
||||
{
|
||||
fw = *fmt++ - '0';
|
||||
mfw = *fmt++ - '0';
|
||||
while (DIGIT (*fmt))
|
||||
fw = (fw * 10) + (*fmt++ - '0');
|
||||
mfw = (mfw * 10) + (*fmt++ - '0');
|
||||
/* Error if fieldwidth > INT_MAX here? */
|
||||
fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
|
||||
}
|
||||
|
||||
/* get precision, if present */
|
||||
|
|
@ -735,9 +753,11 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
}
|
||||
else if (DIGIT (*fmt))
|
||||
{
|
||||
pr = *fmt++ - '0';
|
||||
mpr = *fmt++ - '0';
|
||||
while (DIGIT (*fmt))
|
||||
pr = (pr * 10) + (*fmt++ - '0');
|
||||
mpr = (mpr * 10) + (*fmt++ - '0');
|
||||
/* Error if precision > INT_MAX here? */
|
||||
pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -745,7 +765,7 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
/* If we remove this, get rid of `s'. */
|
||||
if (*fmt != 'b' && *fmt != 'q')
|
||||
{
|
||||
internal_error ("format parsing problem: %s", s);
|
||||
internal_error (_("format parsing problem: %s"), s);
|
||||
fw = pr = 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -861,7 +881,7 @@ tescape (estart, cp, lenp, sawc)
|
|||
*cp = '\\';
|
||||
return 0;
|
||||
}
|
||||
if (uvalue <= UCHAR_MAX)
|
||||
if (uvalue <= 0x7f) /* <= 0x7f translates directly */
|
||||
*cp = uvalue;
|
||||
else
|
||||
{
|
||||
|
|
@ -1089,6 +1109,9 @@ getint ()
|
|||
|
||||
ret = getintmax ();
|
||||
|
||||
if (garglist == 0)
|
||||
return ret;
|
||||
|
||||
if (ret > INT_MAX)
|
||||
{
|
||||
printf_erange (garglist->word->word);
|
||||
|
|
@ -1229,12 +1252,19 @@ bind_printf_variable (name, value, flags)
|
|||
char *value;
|
||||
int flags;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (name) == 0)
|
||||
return (bind_variable (name, value, flags));
|
||||
v = bind_variable (name, value, flags);
|
||||
else
|
||||
return (assign_array_element (name, value, flags));
|
||||
v = assign_array_element (name, value, flags);
|
||||
#else /* !ARRAY_VARS */
|
||||
return bind_variable (name, value, flags);
|
||||
v = bind_variable (name, value, flags);
|
||||
#endif /* !ARRAY_VARS */
|
||||
|
||||
if (v && readonly_p (v) == 0 && noassign_p (v) == 0)
|
||||
VUNSETATTR (v, att_invisible);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ echo ""
|
|||
|
||||
#
|
||||
# Try to avoid tempfile races. We can't really check for the file's
|
||||
# existance before we run psize.aux, because `test -e' is not portable,
|
||||
# existence before we run psize.aux, because `test -e' is not portable,
|
||||
# `test -h' (test for symlinks) is not portable, and `test -f' only
|
||||
# checks for regular files. If we used mktemp(1), we're ahead of the
|
||||
# game.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is pushd.def, from which is created pushd.c. It implements the
|
||||
builtins "pushd", "popd", and "dirs" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ $END
|
|||
|
||||
#if defined (PUSHD_AND_POPD)
|
||||
#include <stdio.h>
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ pushd_builtin (list)
|
|||
{
|
||||
sh_invalidnum (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (direction == '-')
|
||||
|
|
@ -245,7 +245,7 @@ pushd_builtin (list)
|
|||
{
|
||||
sh_invalidopt (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
|
@ -339,7 +339,7 @@ popd_builtin (list)
|
|||
{
|
||||
sh_invalidnum (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
which_word = list->word->word;
|
||||
}
|
||||
|
|
@ -347,7 +347,13 @@ popd_builtin (list)
|
|||
{
|
||||
sh_invalidopt (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
else if (*list->word->word)
|
||||
{
|
||||
builtin_error (_("%s: invalid argument"), list->word->word);
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
|
@ -426,7 +432,7 @@ dirs_builtin (list)
|
|||
{
|
||||
sh_invalidnum (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
sign = (*list->word->word == '+') ? 1 : -1;
|
||||
desired_index = get_dirstack_index (i, sign, &index_flag);
|
||||
|
|
@ -435,7 +441,7 @@ dirs_builtin (list)
|
|||
{
|
||||
sh_invalidopt (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -51,15 +51,17 @@ Options:
|
|||
-r do not allow backslashes to escape any characters
|
||||
-s do not echo input coming from a terminal
|
||||
-t timeout time out and return failure if a complete line of input is
|
||||
not read withint TIMEOUT seconds. The value of the TMOUT
|
||||
not read within TIMEOUT seconds. The value of the TMOUT
|
||||
variable is the default timeout. TIMEOUT may be a
|
||||
fractional number. If TIMEOUT is 0, read returns success only
|
||||
if input is available on the specified file descriptor. The
|
||||
fractional number. If TIMEOUT is 0, read returns immediately,
|
||||
without trying to read any data, returning success only if
|
||||
input is available on the specified file descriptor. The
|
||||
exit status is greater than 128 if the timeout is exceeded
|
||||
-u fd read from file descriptor FD instead of the standard input
|
||||
|
||||
Exit Status:
|
||||
The return code is zero, unless end-of-file is encountered, read times out,
|
||||
The return code is zero, unless end-of-file is encountered, read times out
|
||||
(in which case it's greater than 128), a variable assignment error occurs,
|
||||
or an invalid file descriptor is supplied as the argument to -u.
|
||||
$END
|
||||
|
||||
|
|
@ -101,10 +103,17 @@ $END
|
|||
# include "input.h"
|
||||
#endif
|
||||
|
||||
#include "shmbutil.h"
|
||||
|
||||
#if !defined(errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern void run_pending_traps __P((void));
|
||||
|
||||
extern int posixly_correct;
|
||||
extern int trapped_signal_received;
|
||||
|
||||
struct ttsave
|
||||
{
|
||||
int fd;
|
||||
|
|
@ -127,15 +136,26 @@ static void ttyrestore __P((struct ttsave *));
|
|||
static sighandler sigalrm __P((int));
|
||||
static void reset_alarm __P((void));
|
||||
|
||||
static procenv_t alrmbuf;
|
||||
/* Try this to see what the rest of the shell can do with the information. */
|
||||
procenv_t alrmbuf;
|
||||
int sigalrm_seen;
|
||||
|
||||
static int reading;
|
||||
static SigHandler *old_alrm;
|
||||
static unsigned char delim;
|
||||
|
||||
/* In all cases, SIGALRM just sets a flag that we check periodically. This
|
||||
avoids problems with the semi-tricky stuff we do with the xfree of
|
||||
input_string at the top of the unwind-protect list (see below). */
|
||||
|
||||
/* Set a flag that CHECK_ALRM can check. This relies on zread calling
|
||||
trap.c:check_signals_and_traps(), which knows about sigalrm_seen and
|
||||
alrmbuf. */
|
||||
static sighandler
|
||||
sigalrm (s)
|
||||
int s;
|
||||
{
|
||||
longjmp (alrmbuf, 1);
|
||||
sigalrm_seen = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -158,7 +178,7 @@ read_builtin (list)
|
|||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd;
|
||||
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd, lastsig, t_errno;
|
||||
unsigned int tmsec, tmusec;
|
||||
long ival, uval;
|
||||
intmax_t intval;
|
||||
|
|
@ -199,6 +219,9 @@ read_builtin (list)
|
|||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
USE_VAR(lastsig);
|
||||
|
||||
sigalrm_seen = reading = 0;
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
|
|
@ -306,6 +329,18 @@ read_builtin (list)
|
|||
return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
#endif
|
||||
|
||||
/* Convenience: check early whether or not the first of possibly several
|
||||
variable names is a valid identifier, and bail early if so. */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
|
||||
#else
|
||||
if (list && legal_identifier (list->word->word) == 0)
|
||||
#endif
|
||||
{
|
||||
sh_invalidid (list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* If we're asked to ignore the delimiter, make sure we do. */
|
||||
if (ignore_delim)
|
||||
delim = -1;
|
||||
|
|
@ -380,14 +415,15 @@ read_builtin (list)
|
|||
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
code = setjmp (alrmbuf);
|
||||
code = setjmp_nosigs (alrmbuf);
|
||||
if (code)
|
||||
{
|
||||
sigalrm_seen = 0;
|
||||
/* Tricky. The top of the unwind-protect stack is the free of
|
||||
input_string. We want to run all the rest and use input_string,
|
||||
so we have to save input_string temporarily, run the unwind-
|
||||
protects, then restore input_string so we can use it later. */
|
||||
|
||||
protects, then restore input_string so we can use it later */
|
||||
orig_input_string = 0;
|
||||
input_string[i] = '\0'; /* make sure it's terminated */
|
||||
if (i == 0)
|
||||
{
|
||||
|
|
@ -464,10 +500,12 @@ read_builtin (list)
|
|||
/* This *must* be the top unwind-protect on the stack, so the manipulation
|
||||
of the unwind-protect stack after the realloc() works right. */
|
||||
add_unwind_protect (xfree, input_string);
|
||||
interrupt_immediately++;
|
||||
terminate_immediately++;
|
||||
|
||||
unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
|
||||
CHECK_ALRM;
|
||||
if ((nchars > 0) && (input_is_tty == 0) && ignore_delim) /* read -N */
|
||||
unbuffered_read = 2;
|
||||
else if ((nchars > 0) || (delim != '\n') || input_is_pipe)
|
||||
unbuffered_read = 1;
|
||||
|
||||
if (prompt && edit == 0)
|
||||
{
|
||||
|
|
@ -482,6 +520,8 @@ read_builtin (list)
|
|||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
{
|
||||
|
|
@ -492,7 +532,9 @@ read_builtin (list)
|
|||
}
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
reading = 1;
|
||||
rlbuf = edit_line (prompt ? prompt : "", itext);
|
||||
reading = 0;
|
||||
rlind = 0;
|
||||
}
|
||||
if (rlbuf == 0)
|
||||
|
|
@ -515,26 +557,58 @@ read_builtin (list)
|
|||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
#if 0
|
||||
if (posixly_correct == 0)
|
||||
interrupt_immediately++;
|
||||
#endif
|
||||
reading = 1;
|
||||
if (unbuffered_read == 2)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
|
||||
else if (unbuffered_read)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
|
||||
else
|
||||
retval = zreadc (fd, &c);
|
||||
retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
|
||||
reading = 0;
|
||||
#if 0
|
||||
if (posixly_correct == 0)
|
||||
interrupt_immediately--;
|
||||
#endif
|
||||
|
||||
if (retval <= 0)
|
||||
{
|
||||
if (retval < 0 && errno == EINTR)
|
||||
{
|
||||
lastsig = LASTSIG();
|
||||
if (lastsig == 0)
|
||||
lastsig = trapped_signal_received;
|
||||
run_pending_traps (); /* because interrupt_immediately is not set */
|
||||
}
|
||||
else
|
||||
lastsig = 0;
|
||||
CHECK_TERMSIG;
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (READLINE)
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_ALRM;
|
||||
if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
|
||||
{
|
||||
input_string = (char *)xrealloc (input_string, size += 128);
|
||||
remove_unwind_protect ();
|
||||
add_unwind_protect (xfree, input_string);
|
||||
char *t;
|
||||
t = (char *)xrealloc (input_string, size += 128);
|
||||
|
||||
/* Only need to change unwind-protect if input_string changes */
|
||||
if (t != input_string)
|
||||
{
|
||||
input_string = t;
|
||||
remove_unwind_protect ();
|
||||
add_unwind_protect (xfree, input_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the next character is to be accepted verbatim, a backslash
|
||||
|
|
@ -565,9 +639,12 @@ read_builtin (list)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned char)c == delim)
|
||||
if (ignore_delim == 0 && (unsigned char)c == delim)
|
||||
break;
|
||||
|
||||
if (c == '\0' && delim != '\0')
|
||||
continue; /* skip NUL bytes in input */
|
||||
|
||||
if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
|
||||
{
|
||||
saw_escape++;
|
||||
|
|
@ -576,9 +653,10 @@ read_builtin (list)
|
|||
|
||||
add_char:
|
||||
input_string[i++] = c;
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (nchars > 0 && MB_CUR_MAX > 1)
|
||||
if (nchars > 0 && MB_CUR_MAX > 1 && is_basic (c) == 0)
|
||||
{
|
||||
input_string[i] = '\0'; /* for simplicity and debugging */
|
||||
i += read_mbchar (fd, input_string, i, c, unbuffered_read);
|
||||
|
|
@ -591,15 +669,16 @@ add_char:
|
|||
break;
|
||||
}
|
||||
input_string[i] = '\0';
|
||||
CHECK_ALRM;
|
||||
|
||||
#if 1
|
||||
if (retval < 0)
|
||||
{
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
t_errno = errno;
|
||||
if (errno != EINTR)
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
reset_alarm ();
|
||||
|
|
@ -631,9 +710,6 @@ add_char:
|
|||
|
||||
assign_vars:
|
||||
|
||||
interrupt_immediately--;
|
||||
terminate_immediately--;
|
||||
|
||||
#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. */
|
||||
|
|
@ -658,6 +734,8 @@ assign_vars:
|
|||
xfree (input_string);
|
||||
return EXECUTION_FAILURE; /* existing associative array */
|
||||
}
|
||||
else if (invisible_p (var))
|
||||
VUNSETATTR (var, att_invisible);
|
||||
array_flush (array_cell (var));
|
||||
|
||||
alist = list_string (input_string, ifs_chars, 0);
|
||||
|
|
@ -703,7 +781,7 @@ assign_vars:
|
|||
var = bind_variable ("REPLY", input_string, 0);
|
||||
VUNSETATTR (var, att_invisible);
|
||||
|
||||
free (input_string);
|
||||
xfree (input_string);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +907,7 @@ bind_read_variable (name, value)
|
|||
char *name, *value;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (name) == 0)
|
||||
v = bind_variable (name, value, 0);
|
||||
|
|
@ -867,6 +946,7 @@ read_mbchar (fd, string, ind, ch, unbuffered)
|
|||
if (ret == (size_t)-2)
|
||||
{
|
||||
ps = ps_back;
|
||||
/* We don't want to be interrupted during a multibyte char read */
|
||||
if (unbuffered)
|
||||
r = zread (fd, &c, 1);
|
||||
else
|
||||
|
|
@ -947,7 +1027,9 @@ edit_line (p, itext)
|
|||
rl_startup_hook = set_itext;
|
||||
deftext = itext;
|
||||
}
|
||||
|
||||
ret = readline (p);
|
||||
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
old_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,11 @@ int
|
|||
return_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
#if 0
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
list = loptend; /* skip over possible `--' */
|
||||
#endif
|
||||
|
||||
return_catch_value = get_exitstat (list);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is set.def, from which is created set.c.
|
||||
It implements the "set" and "unset" builtins in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -96,12 +96,16 @@ Options:
|
|||
interactive-comments
|
||||
allow comments to appear in interactive commands
|
||||
keyword same as -k
|
||||
#if defined (JOB_CONTROL)
|
||||
monitor same as -m
|
||||
#endif
|
||||
noclobber same as -C
|
||||
noexec same as -n
|
||||
noglob same as -f
|
||||
nolog currently accepted but ignored
|
||||
#if defined (JOB_CONTROL)
|
||||
notify same as -b
|
||||
#endif
|
||||
nounset same as -u
|
||||
onecmd same as -t
|
||||
physical same as -P
|
||||
|
|
@ -135,7 +139,7 @@ Options:
|
|||
-H Enable ! style history substitution. This flag is on
|
||||
by default when the shell is interactive.
|
||||
#endif /* BANG_HISTORY */
|
||||
-P If set, do not follow symbolic links when executing commands
|
||||
-P If set, do not resolve symbolic links when executing commands
|
||||
such as cd which change the current directory.
|
||||
-T If set, the DEBUG trap is inherited by shell functions.
|
||||
-- Assign any remaining arguments to the positional parameters.
|
||||
|
|
@ -205,7 +209,9 @@ const struct {
|
|||
{ "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
|
||||
{ "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
{ "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
#if defined (JOB_CONTROL)
|
||||
{ "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
#endif
|
||||
{ "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
{ "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
{ "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
|
||||
|
|
@ -718,7 +724,7 @@ set_builtin (list)
|
|||
|
||||
$BUILTIN unset
|
||||
$FUNCTION unset_builtin
|
||||
$SHORT_DOC unset [-f] [-v] [name ...]
|
||||
$SHORT_DOC unset [-f] [-v] [-n] [name ...]
|
||||
Unset values and attributes of shell variables and functions.
|
||||
|
||||
For each NAME, remove the corresponding variable or function.
|
||||
|
|
@ -726,6 +732,8 @@ For each NAME, remove the corresponding variable or function.
|
|||
Options:
|
||||
-f treat each NAME as a shell function
|
||||
-v treat each NAME as a shell variable
|
||||
-n treat each NAME as a name reference and unset the variable itself
|
||||
rather than the variable it references
|
||||
|
||||
Without options, unset first tries to unset a variable, and if that fails,
|
||||
tries to unset a function.
|
||||
|
|
@ -742,13 +750,13 @@ int
|
|||
unset_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int unset_function, unset_variable, unset_array, opt, any_failed;
|
||||
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
|
||||
char *name;
|
||||
|
||||
unset_function = unset_variable = unset_array = any_failed = 0;
|
||||
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "fv")) != -1)
|
||||
while ((opt = internal_getopt (list, "fnv")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
|
@ -758,6 +766,9 @@ unset_builtin (list)
|
|||
case 'v':
|
||||
unset_variable = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nameref = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
|
|
@ -771,6 +782,8 @@ unset_builtin (list)
|
|||
builtin_error (_("cannot simultaneously unset a function and a variable"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else if (unset_function && nameref)
|
||||
nameref = 0;
|
||||
|
||||
while (list)
|
||||
{
|
||||
|
|
@ -791,6 +804,8 @@ unset_builtin (list)
|
|||
unset_array++;
|
||||
}
|
||||
#endif
|
||||
/* Get error checking out of the way first. The low-level functions
|
||||
just perform the unset, relying on the caller to verify. */
|
||||
|
||||
/* Bash allows functions with names which are not valid identifiers
|
||||
to be created when not in posix mode, so check only when in posix
|
||||
|
|
@ -801,19 +816,32 @@ unset_builtin (list)
|
|||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
var = unset_function ? find_function (name) : find_variable (name);
|
||||
/* Only search for functions here if -f supplied. */
|
||||
var = unset_function ? find_function (name)
|
||||
: (nameref ? find_variable_last_nameref (name) : find_variable (name));
|
||||
|
||||
if (var && !unset_function && non_unsettable_p (var))
|
||||
/* Some variables (but not functions yet) cannot be unset, period. */
|
||||
if (var && unset_function == 0 && non_unsettable_p (var))
|
||||
{
|
||||
builtin_error (_("%s: cannot unset"), name);
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* Posix.2 says try variables first, then functions. If we would
|
||||
find a function after unsuccessfully searching for a variable,
|
||||
note that we're acting on a function now as if -f were
|
||||
supplied. The readonly check below takes care of it. */
|
||||
if (var == 0 && unset_variable == 0 && unset_function == 0)
|
||||
{
|
||||
if (var = find_function (name))
|
||||
unset_function = 1;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
var->name, unset_function ? "function" : "variable");
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
|
|
@ -823,7 +851,7 @@ unset_builtin (list)
|
|||
{
|
||||
if (array_p (var) == 0 && assoc_p (var) == 0)
|
||||
{
|
||||
builtin_error (_("%s: not an array variable"), name);
|
||||
builtin_error (_("%s: not an array variable"), var->name);
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else
|
||||
|
|
@ -835,13 +863,13 @@ unset_builtin (list)
|
|||
}
|
||||
else
|
||||
#endif /* ARRAY_VARS */
|
||||
tem = unset_function ? unbind_func (name) : unbind_variable (name);
|
||||
tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
|
||||
|
||||
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
|
||||
/* This is what Posix.2 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)
|
||||
if (tem == -1 && unset_function == 0 && unset_variable == 0)
|
||||
tem = unbind_func (name);
|
||||
|
||||
/* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is setattr.def, from which is created setattr.c.
|
||||
It implements the builtins "export" and "readonly", in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -93,7 +93,8 @@ Options:
|
|||
-a refer to indexed array variables
|
||||
-A refer to associative array variables
|
||||
-f refer to shell functions
|
||||
-p display a list of all readonly variables and functions
|
||||
-p display a list of all readonly variables or functions, depending on
|
||||
whether or not the -f option is given
|
||||
|
||||
An argument of `--' disables further option processing.
|
||||
|
||||
|
|
@ -368,6 +369,9 @@ show_var_attributes (var, pattr, nodefs)
|
|||
if (integer_p (var))
|
||||
flags[i++] = 'i';
|
||||
|
||||
if (nameref_p (var))
|
||||
flags[i++] = 'n';
|
||||
|
||||
if (readonly_p (var))
|
||||
flags[i++] = 'r';
|
||||
|
||||
|
|
@ -451,7 +455,11 @@ show_name_attributes (name, nodefs)
|
|||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_variable_internal (name, 1);
|
||||
#if 0
|
||||
var = find_variable_tempenv (name);
|
||||
#else
|
||||
var = find_variable_noref (name);
|
||||
#endif
|
||||
|
||||
if (var && invisible_p (var) == 0)
|
||||
{
|
||||
|
|
@ -462,12 +470,30 @@ show_name_attributes (name, nodefs)
|
|||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
show_func_attributes (name, nodefs)
|
||||
char *name;
|
||||
int nodefs;
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_function (name);
|
||||
|
||||
if (var)
|
||||
{
|
||||
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
set_var_attribute (name, attribute, undo)
|
||||
char *name;
|
||||
int attribute, undo;
|
||||
{
|
||||
SHELL_VAR *var, *tv;
|
||||
SHELL_VAR *var, *tv, *v;
|
||||
char *tvalue;
|
||||
|
||||
if (undo)
|
||||
|
|
@ -484,7 +510,18 @@ set_var_attribute (name, attribute, undo)
|
|||
|
||||
var = bind_variable (tv->name, tvalue, 0);
|
||||
var->attributes |= tv->attributes & ~att_tempvar;
|
||||
VSETATTR (tv, att_propagate);
|
||||
/* This avoids an error message when propagating a read-only var
|
||||
later on. */
|
||||
if (var->context == 0 && (attribute & att_readonly))
|
||||
{
|
||||
/* Don't bother to set the `propagate to the global variables
|
||||
table' flag if we've just bound the variable in that table */
|
||||
v = find_global_variable (tv->name);
|
||||
if (v != var)
|
||||
VSETATTR (tv, att_propagate);
|
||||
}
|
||||
else
|
||||
VSETATTR (tv, att_propagate);
|
||||
if (var->context != 0)
|
||||
VSETATTR (var, att_propagate);
|
||||
SETVARATTR (tv, attribute, undo); /* XXX */
|
||||
|
|
@ -495,7 +532,7 @@ set_var_attribute (name, attribute, undo)
|
|||
}
|
||||
else
|
||||
{
|
||||
var = find_variable_internal (name, 0);
|
||||
var = find_variable_notempenv (name);
|
||||
if (var == 0)
|
||||
{
|
||||
var = bind_variable (name, (char *)NULL, 0);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is shopt.def, from which is created shopt.c.
|
||||
It implements the Bash `shopt' builtin.
|
||||
|
||||
Copyright (C) 1994-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -88,6 +88,7 @@ extern int gnu_error_format;
|
|||
extern int check_jobs_at_exit;
|
||||
extern int autocd;
|
||||
extern int glob_star;
|
||||
extern int glob_asciirange;
|
||||
extern int lastpipe_opt;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
|
|
@ -99,6 +100,7 @@ extern int hist_verify, history_reediting, perform_hostname_completion;
|
|||
extern int no_empty_command_completion;
|
||||
extern int force_fignore;
|
||||
extern int dircomplete_spelling, dircomplete_expand;
|
||||
extern int complete_fullquote;
|
||||
|
||||
extern int enable_hostname_completion __P((int));
|
||||
#endif
|
||||
|
|
@ -134,6 +136,7 @@ static int shopt_compat31;
|
|||
static int shopt_compat32;
|
||||
static int shopt_compat40;
|
||||
static int shopt_compat41;
|
||||
static int shopt_compat42;
|
||||
|
||||
typedef int shopt_set_func_t __P((char *, int));
|
||||
|
||||
|
|
@ -157,7 +160,9 @@ static struct {
|
|||
{ "compat32", &shopt_compat32, set_compatibility_level },
|
||||
{ "compat40", &shopt_compat40, set_compatibility_level },
|
||||
{ "compat41", &shopt_compat41, set_compatibility_level },
|
||||
{ "compat42", &shopt_compat41, set_compatibility_level },
|
||||
#if defined (READLINE)
|
||||
{ "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL},
|
||||
{ "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
|
||||
{ "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
|
|
@ -176,6 +181,7 @@ static struct {
|
|||
{ "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "globstar", &glob_star, (shopt_set_func_t *)NULL },
|
||||
{ "globasciiranges", &glob_asciirange, (shopt_set_func_t *)NULL },
|
||||
{ "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "histappend", &force_append_history, (shopt_set_func_t *)NULL },
|
||||
|
|
@ -298,10 +304,12 @@ reset_shopt_options ()
|
|||
allow_null_glob_expansion = glob_dot_filenames = 0;
|
||||
cdable_vars = mail_warning = 0;
|
||||
no_exit_on_failed_exec = print_shift_error = 0;
|
||||
check_hashed_filenames = cdspelling = expand_aliases = check_window_size = 0;
|
||||
check_hashed_filenames = cdspelling = expand_aliases = 0;
|
||||
|
||||
source_uses_path = promptvars = 1;
|
||||
|
||||
check_window_size = CHECKWINSIZE_DEFAULT;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extended_glob = 0;
|
||||
#endif
|
||||
|
|
@ -521,16 +529,18 @@ set_compatibility_level (option_name, mode)
|
|||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
/* Need to change logic here as we add more compatibility levels */
|
||||
int ind;
|
||||
|
||||
/* First, check option_name so we can turn off other compat options when
|
||||
one is set. */
|
||||
if (mode && option_name[6] == '3' && option_name[7] == '1')
|
||||
shopt_compat32 = shopt_compat40 = 0;
|
||||
else if (mode && option_name[6] == '3' && option_name[7] == '2')
|
||||
shopt_compat31 = shopt_compat40 = 0;
|
||||
else if (mode && option_name[6] == '4' && option_name[7] == '0')
|
||||
shopt_compat31 = shopt_compat32 = 0;
|
||||
/* If we're setting something, redo some of the work we did above in
|
||||
toggle_shopt(). Unset everything and reset the appropriate option
|
||||
based on OPTION_NAME. */
|
||||
if (mode)
|
||||
{
|
||||
shopt_compat31 = shopt_compat32 = 0;
|
||||
shopt_compat40 = shopt_compat41 = shopt_compat42 = 0;
|
||||
ind = find_shopt (option_name);
|
||||
*shopt_vars[ind].value = mode;
|
||||
}
|
||||
|
||||
/* Then set shell_compatibility_level based on what remains */
|
||||
if (shopt_compat31)
|
||||
|
|
@ -539,11 +549,39 @@ set_compatibility_level (option_name, mode)
|
|||
shell_compatibility_level = 32;
|
||||
else if (shopt_compat40)
|
||||
shell_compatibility_level = 40;
|
||||
else if (shopt_compat41)
|
||||
shell_compatibility_level = 41;
|
||||
else if (shopt_compat42)
|
||||
shell_compatibility_level = 42;
|
||||
else
|
||||
shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set and unset the various compatibility options from the value of
|
||||
shell_compatibility_level; used by sv_shcompat */
|
||||
void
|
||||
set_compatibility_opts ()
|
||||
{
|
||||
shopt_compat31 = shopt_compat32 = shopt_compat40 = shopt_compat41 = shopt_compat42 = 0;
|
||||
switch (shell_compatibility_level)
|
||||
{
|
||||
case DEFAULT_COMPAT_LEVEL:
|
||||
break;
|
||||
case 42:
|
||||
shopt_compat42 = 1; break;
|
||||
case 41:
|
||||
shopt_compat41 = 1; break;
|
||||
case 40:
|
||||
shopt_compat40 = 1; break;
|
||||
case 32:
|
||||
shopt_compat32 = 1; break;
|
||||
case 31:
|
||||
shopt_compat31 = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
static int
|
||||
shopt_set_complete_direxpand (option_name, mode)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ Other operators:
|
|||
|
||||
-o OPTION True if the shell option OPTION is enabled.
|
||||
-v VAR True if the shell variable VAR is set
|
||||
-R VAR True if the shell variable VAR is set and is a name reference.
|
||||
! EXPR True if expr is false.
|
||||
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
|
||||
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is type.def, from which is created type.c.
|
||||
It implements the builtin "type" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -353,7 +353,7 @@ describe_command (command, dflags)
|
|||
user_command_matches (command, FS_EXEC_ONLY, found_file);
|
||||
/* XXX - should that be FS_EXEC_PREFERRED? */
|
||||
|
||||
if (!full_path)
|
||||
if (full_path == 0)
|
||||
break;
|
||||
|
||||
/* If we found the command as itself by looking through $PATH, it
|
||||
|
|
@ -375,7 +375,9 @@ describe_command (command, dflags)
|
|||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
|
||||
{
|
||||
f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
|
||||
full_path = sh_makepath ((char *)NULL, full_path, f);
|
||||
x = sh_makepath ((char *)NULL, full_path, f);
|
||||
free (full_path);
|
||||
full_path = x;
|
||||
}
|
||||
}
|
||||
/* If we require a full path and don't have one, make one */
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ $PRODUCES ulimit.c
|
|||
$BUILTIN ulimit
|
||||
$FUNCTION ulimit_builtin
|
||||
$DEPENDS_ON !_MINIX
|
||||
$SHORT_DOC ulimit [-SHacdefilmnpqrstuvx] [limit]
|
||||
$SHORT_DOC ulimit [-SHabcdefilmnpqrstuvxT] [limit]
|
||||
Modify shell resource limits.
|
||||
|
||||
Provides control over the resources available to the shell and processes
|
||||
|
|
@ -50,6 +50,9 @@ Options:
|
|||
-u the maximum number of user processes
|
||||
-v the size of virtual memory
|
||||
-x the maximum number of file locks
|
||||
-T the maximum number of threads
|
||||
|
||||
Not all options are available on all platforms.
|
||||
|
||||
If LIMIT is given, it is the new value of the specified resource; the
|
||||
special LIMIT values `soft', `hard', and `unlimited' stand for the
|
||||
|
|
@ -70,7 +73,7 @@ $END
|
|||
#include <config.h>
|
||||
|
||||
#include "../bashtypes.h"
|
||||
#ifndef _MINIX
|
||||
#if defined (HAVE_SYS_PARAM_H)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -167,6 +170,10 @@ extern int errno;
|
|||
# define RLIMIT_MAXUPROC 260
|
||||
#endif
|
||||
|
||||
#if !defined (RLIMIT_PTHREAD) && defined (RLIMIT_NTHR)
|
||||
# define RLIMIT_PTHREAD RLIMIT_NTHR
|
||||
#endif
|
||||
|
||||
#if !defined (RLIM_INFINITY)
|
||||
# define RLIM_INFINITY 0x7fffffff
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,10 +61,6 @@ $END
|
|||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#ifdef __LCC__
|
||||
#define mode_t int
|
||||
#endif
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* UMASK Builtin and Helpers */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
This file is wait.def, from which is created wait.c.
|
||||
It implements the builtin "wait" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -22,33 +22,36 @@ $BUILTIN wait
|
|||
$FUNCTION wait_builtin
|
||||
$DEPENDS_ON JOB_CONTROL
|
||||
$PRODUCES wait.c
|
||||
$SHORT_DOC wait [id]
|
||||
$SHORT_DOC wait [-n] [id ...]
|
||||
Wait for job completion and return exit status.
|
||||
|
||||
Waits for the process identified by ID, which may be a process ID or a
|
||||
Waits for each process identified by an ID, which may be a process ID or a
|
||||
job specification, and reports its termination status. If ID is not
|
||||
given, waits for all currently active child processes, and the return
|
||||
status is zero. If ID is a a job specification, waits for all processes
|
||||
in the job's pipeline.
|
||||
in that job's pipeline.
|
||||
|
||||
If the -n option is supplied, waits for the next job to terminate and
|
||||
returns its exit status.
|
||||
|
||||
Exit Status:
|
||||
Returns the status of ID; fails if ID is invalid or an invalid option is
|
||||
given.
|
||||
Returns the status of the last ID; fails if ID is invalid or an invalid
|
||||
option is given.
|
||||
$END
|
||||
|
||||
$BUILTIN wait
|
||||
$FUNCTION wait_builtin
|
||||
$DEPENDS_ON !JOB_CONTROL
|
||||
$SHORT_DOC wait [pid]
|
||||
$SHORT_DOC wait [pid ...]
|
||||
Wait for process completion and return exit status.
|
||||
|
||||
Waits for the specified process and reports its termination status. If
|
||||
PID is not given, all currently active child processes are waited for,
|
||||
and the return code is zero. PID must be a process ID.
|
||||
Waits for each process specified by a PID and reports its termination status.
|
||||
If PID is not given, waits for all currently active child processes,
|
||||
and the return status is zero. PID must be a process ID.
|
||||
|
||||
Exit Status:
|
||||
Returns the status of ID; fails if ID is invalid or an invalid option is
|
||||
given.
|
||||
Returns the status of the last PID; fails if PID is invalid or an invalid
|
||||
option is given.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
|
@ -82,6 +85,7 @@ procenv_t wait_intr_buf;
|
|||
do \
|
||||
{ \
|
||||
interrupt_immediately = old_interrupt_immediately;\
|
||||
wait_signal_received = 0; \
|
||||
return (s);\
|
||||
} \
|
||||
while (0)
|
||||
|
|
@ -90,17 +94,33 @@ int
|
|||
wait_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int status, code;
|
||||
int status, code, opt, nflag;
|
||||
volatile int old_interrupt_immediately;
|
||||
|
||||
USE_VAR(list);
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
nflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "n")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
#if defined (JOB_CONTROL)
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
old_interrupt_immediately = interrupt_immediately;
|
||||
#if 0
|
||||
interrupt_immediately++;
|
||||
#endif
|
||||
|
||||
/* POSIX.2 says: When the shell is waiting (by means of the wait utility)
|
||||
for asynchronous commands to complete, the reception of a signal for
|
||||
|
|
@ -120,6 +140,16 @@ wait_builtin (list)
|
|||
/* We support jobs or pids.
|
||||
wait <pid-or-job> [pid-or-job ...] */
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
if (nflag)
|
||||
{
|
||||
status = wait_for_any_job ();
|
||||
if (status < 0)
|
||||
status = 127;
|
||||
WAIT_RETURN (status);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* But wait without any arguments means to wait for all of the shell's
|
||||
currently active background processes. */
|
||||
if (list == 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue