Bash-5.3-alpha release

This commit is contained in:
Chet Ramey
2024-04-22 10:33:38 -04:00
parent f3b6bd1945
commit 622d318652
700 changed files with 136534 additions and 96420 deletions
+13 -1
View File
@@ -1,6 +1,6 @@
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
#
# Copyright (C) 1996-2022 Free Software Foundation, Inc.
# Copyright (C) 1996-2024 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
@@ -343,6 +343,7 @@ common.o: $(topdir)/builtins.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
common.o: $(topdir)/subst.h $(topdir)/execute_cmd.h $(topdir)/error.h
common.o: $(topdir)/externs.h ../pathnames.h ./builtext.h
common.o: $(BASHINCDIR)/chartypes.h
common.o: $(BASHINCDIR)/unlocked-io.h
evalfile.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h ${BASHINCDIR}/filecntl.h
evalfile.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
evalfile.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h
@@ -439,6 +440,7 @@ echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/
echo.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
echo.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
echo.o: $(srcdir)/common.h
echo.o: $(BASHINCDIR)/unlocked-io.h
enable.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
enable.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
enable.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -468,6 +470,7 @@ exit.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/jobs.h
exit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
exit.o: $(topdir)/execute_cmd.h
exit.o: $(BASHINCDIR)/maxpath.h ./builtext.h ../pathnames.h
exit.o: $(BASHINCDIR)/unlocked-io.h
fc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
fc.o: $(topdir)/builtins.h $(topdir)/command.h $(srcdir)/bashgetopt.h
fc.o: $(topdir)/bashhist.h $(topdir)/parser.h
@@ -478,6 +481,7 @@ fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h $(topdir)/syntax.h
fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
fc.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h $(BASHINCDIR)/chartypes.h
fc.o: ../pathnames.h
fc.o: $(BASHINCDIR)/unlocked-io.h
fg_bg.o: $(topdir)/bashtypes.h $(srcdir)/bashgetopt.h
fg_bg.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
@@ -498,6 +502,7 @@ hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h $(topdir)/sig.h
hash.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
hash.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
hash.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h
hash.o: $(BASHINCDIR)/unlocked-io.h
hash.o: $(topdir)/conftypes.h $(topdir)/execute_cmd.h
hash.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
help.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
@@ -507,6 +512,7 @@ help.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
help.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h
help.o: $(topdir)/conftypes.h $(topdir)/execute_cmd.h
help.o: ${srcdir}/common.h $(topdir)/sig.h ../pathnames.h
help.o: $(BASHINCDIR)/unlocked-io.h
history.o: $(topdir)/bashtypes.h
history.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
history.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
@@ -515,6 +521,7 @@ history.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h $(topdir)/pars
history.o: ${BASHINCDIR}/filecntl.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
history.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/bashhist.h $(BASHINCDIR)/maxpath.h
history.o: ../pathnames.h
history.o: $(BASHINCDIR)/unlocked-io.h
inlib.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
inlib.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
inlib.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
@@ -538,6 +545,7 @@ let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/s
let.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
let.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
let.o: ../pathnames.h
let.o: $(BASHINCDIR)/unlocked-io.h
printf.o: ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/bashjmp.h
printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -547,6 +555,7 @@ printf.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/stdc.h $(src
printf.o: $(topdir)/bashtypes.h ${srcdir}/common.h $(BASHINCDIR)/chartypes.h
printf.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
printf.o: ../pathnames.h
printf.o: $(BASHINCDIR)/unlocked-io.h
pushd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
pushd.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -554,6 +563,7 @@ pushd.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h
pushd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
pushd.o: $(BASHINCDIR)/maxpath.h $(srcdir)/common.h ./builtext.h
pushd.o: ../pathnames.h
pushd.o: $(BASHINCDIR)/unlocked-io.h
read.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
read.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
read.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -562,6 +572,7 @@ read.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/v
read.o: $(BASHINCDIR)/shtty.h $(topdir)/sig.h
read.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
read.o: $(topdir)/arrayfunc.h ../pathnames.h
read.o: $(BASHINCDIR)/unlocked-io.h
return.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
return.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
return.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/sig.h
@@ -622,6 +633,7 @@ times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)
times.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
times.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
times.o: $(BASHINCDIR)/posixtime.h ../pathnames.h
times.o: $(BASHINCDIR)/unlocked-io.h
trap.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
trap.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h $(topdir)/sig.h
+18 -22
View File
@@ -1,7 +1,7 @@
This file is alias.def, from which is created alias.c
It implements the builtins "alias" and "unalias" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -63,12 +63,11 @@ $END
/* Flags for print_alias */
#define AL_REUSABLE 0x01
static void print_alias PARAMS((alias_t *, int));
static int print_alias (alias_t *, int);
/* Hack the alias command in a Korn shell way. */
int
alias_builtin (list)
WORD_LIST *list;
alias_builtin (WORD_LIST *list)
{
int any_failed, offset, pflag, dflags;
alias_t **alias_list, *t;
@@ -104,13 +103,14 @@ alias_builtin (list)
if (alias_list == 0)
return (EXECUTION_SUCCESS);
any_failed = EXECUTION_SUCCESS;
for (offset = 0; alias_list[offset]; offset++)
print_alias (alias_list[offset], dflags);
if (any_failed = print_alias (alias_list[offset], dflags) != EXECUTION_SUCCESS)
break;
free (alias_list); /* XXX - Do not free the strings. */
if (list == 0)
return (sh_chkwrite (EXECUTION_SUCCESS));
return (any_failed != EXECUTION_SUCCESS ? EXECUTION_FAILURE : sh_chkwrite (EXECUTION_SUCCESS));
}
any_failed = 0;
@@ -126,7 +126,7 @@ alias_builtin (list)
name[offset] = '\0';
value = name + offset + 1;
if (legal_alias_name (name, 0) == 0)
if (valid_alias_name (name, 0) == 0)
{
builtin_error (_("`%s': invalid alias name"), name);
any_failed++;
@@ -138,7 +138,10 @@ alias_builtin (list)
{
t = find_alias (name);
if (t)
print_alias (t, dflags);
{
if (print_alias (t, dflags) != EXECUTION_SUCCESS)
return (EXECUTION_FAILURE);
}
else
{
sh_notfound (name);
@@ -167,10 +170,9 @@ $END
#if defined (ALIAS)
/* Remove aliases named in LIST from the aliases database. */
int
unalias_builtin (list)
register WORD_LIST *list;
unalias_builtin (WORD_LIST *list)
{
register alias_t *alias;
alias_t *alias;
int opt, aflag;
aflag = 0;
@@ -206,11 +208,7 @@ unalias_builtin (list)
aflag = 0;
while (list)
{
alias = find_alias (list->word->word);
if (alias)
remove_alias (alias->name);
else
if (remove_alias (list->word->word) < 0)
{
sh_notfound (list->word->word);
aflag++;
@@ -223,10 +221,8 @@ unalias_builtin (list)
}
/* Output ALIAS in such a way as to allow it to be read back in. */
static void
print_alias (alias, flags)
alias_t *alias;
int flags;
static int
print_alias (alias_t *alias, int flags)
{
char *value;
@@ -236,6 +232,6 @@ print_alias (alias, flags)
printf ("%s=%s\n", alias->name, value);
free (value);
fflush (stdout);
return (sh_chkwrite (EXECUTION_SUCCESS));
}
#endif /* ALIAS */
+4 -6
View File
@@ -1,6 +1,6 @@
/* bashgetopt.c -- `getopt' for use by the builtins. */
/* Copyright (C) 1992-2021 Free Software Foundation, Inc.
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -48,9 +48,7 @@ WORD_LIST *lcurrent = (WORD_LIST *)NULL;
WORD_LIST *loptend; /* Points to the first non-option argument in the list */
int
internal_getopt(list, opts)
WORD_LIST *list;
char *opts;
internal_getopt(WORD_LIST *list, char *opts)
{
register int c;
register char *cp;
@@ -154,7 +152,7 @@ char *opts;
list_optflags = 0;
}
} else {
if (lcurrent->next && legal_number(lcurrent->next->word->word, (intmax_t *)0)) {
if (lcurrent->next && valid_number(lcurrent->next->word->word, (intmax_t *)0)) {
lcurrent = lcurrent->next;
list_optarg = lcurrent->word->word;
list_optflags = lcurrent->word->flags;
@@ -187,7 +185,7 @@ char *opts;
*/
void
reset_internal_getopt ()
reset_internal_getopt (void)
{
lhead = lcurrent = loptend = (WORD_LIST *)NULL;
sp = 1;
+3 -3
View File
@@ -1,6 +1,6 @@
/* bashgetopt.h -- extern declarations for stuff defined in bashgetopt.c. */
/* Copyright (C) 1993-2021 Free Software Foundation, Inc.
/* Copyright (C) 1993-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -37,7 +37,7 @@ extern int list_opttype;
extern WORD_LIST *lcurrent;
extern WORD_LIST *loptend;
extern int internal_getopt PARAMS((WORD_LIST *, char *));
extern void reset_internal_getopt PARAMS((void));
extern int internal_getopt (WORD_LIST *, char *);
extern void reset_internal_getopt (void);
#endif /* !__BASH_GETOPT_H */
+41 -24
View File
@@ -1,7 +1,7 @@
This file is bind.def, from which is created bind.c.
It implements the builtin "bind" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -86,9 +86,9 @@ extern int errno;
#include "bashgetopt.h"
#include "common.h"
static int query_bindings PARAMS((char *));
static int unbind_command PARAMS((char *));
static int unbind_keyseq PARAMS((char *));
static int query_bindings (char *);
static int unbind_command (char *);
static int unbind_keyseq (char *);
#define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0)
@@ -108,8 +108,7 @@ static int unbind_keyseq PARAMS((char *));
#define XXFLAG 0x2000
int
bind_builtin (list)
WORD_LIST *list;
bind_builtin (WORD_LIST *list)
{
int return_code;
Keymap kmap, saved_keymap;
@@ -117,14 +116,7 @@ bind_builtin (list)
char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq, *t;
if (no_line_editing)
{
#if 0
builtin_error (_("line editing not enabled"));
return (EXECUTION_FAILURE);
#else
builtin_warning (_("line editing not enabled"));
#endif
}
builtin_warning (_("line editing not enabled"));
kmap = saved_keymap = (Keymap) NULL;
flags = 0;
@@ -192,7 +184,7 @@ bind_builtin (list)
case 'X':
flags |= XXFLAG;
break;
case GETOPT_HELP:
CASE_HELPOPT;
default:
builtin_usage ();
BIND_RETURN (EX_USAGE);
@@ -227,10 +219,37 @@ bind_builtin (list)
rl_list_funmap_names ();
if (flags & PFLAG)
rl_function_dumper (1);
{
#if 0 /* TAG:bash-5.3 */
if (list == 0)
rl_function_dumper (1);
else
while (list)
{
rl_print_keybinding (list->word->word, kmap, 1);
list = list->next;
}
#else
rl_function_dumper (1);
#endif
}
if (flags & PPFLAG)
rl_function_dumper (0);
{
#if 0 /* TAG:bash-5.3 */
if (list == 0)
rl_function_dumper (0);
else
while (list)
{
rl_print_keybinding (list->word->word, kmap, 0);
list = list->next;
}
#else
rl_function_dumper (0);
#endif
}
if (flags & SFLAG)
rl_macro_dumper (1);
@@ -277,7 +296,8 @@ bind_builtin (list)
/* Process the rest of the arguments as binding specifications. */
while (list)
{
int olen, nlen, d, i;
size_t olen, nlen;
int d, i;
char **obindings, **nbindings;
obindings = rl_invoking_keyseqs (bash_execute_unix_command);
@@ -315,8 +335,7 @@ bind_builtin (list)
}
static int
query_bindings (name)
char *name;
query_bindings (char *name)
{
rl_command_func_t *function;
char **keyseqs;
@@ -347,8 +366,7 @@ query_bindings (name)
}
static int
unbind_command (name)
char *name;
unbind_command (char *name)
{
rl_command_func_t *function;
@@ -364,8 +382,7 @@ unbind_command (name)
}
static int
unbind_keyseq (seq)
char *seq;
unbind_keyseq (char *seq)
{
char *kseq;
int kslen, type;
+15 -9
View File
@@ -1,7 +1,7 @@
This file is break.def, from which is created break.c.
It implements the builtins "break" and "continue" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -46,7 +46,7 @@ $END
#include "../execute_cmd.h"
#include "common.h"
static int check_loop_level PARAMS((void));
static int check_loop_level (void);
/* The depth of while's and until's. */
int loop_level = 0;
@@ -60,8 +60,7 @@ int continuing = 0;
/* Set up to break x levels, where x defaults to 1, but can be specified
as the first argument. */
int
break_builtin (list)
WORD_LIST *list;
break_builtin (WORD_LIST *list)
{
intmax_t newbreak;
@@ -70,10 +69,14 @@ break_builtin (list)
if (check_loop_level () == 0)
return (EXECUTION_SUCCESS);
(void)get_numeric_arg (list, 1, &newbreak);
/* This will not return if an error is encountered. */
(void)get_numeric_arg (list, interactive_shell ? 2 : 1, &newbreak);
if (newbreak <= 0)
{
/* skip over `--' option to get the right error message */
if (list && list->word && ISOPTION (list->word->word, '-'))
list = list->next;
sh_erange (list->word->word, _("loop count"));
breaking = loop_level;
return (EXECUTION_FAILURE);
@@ -102,8 +105,7 @@ $END
/* Set up to continue x levels, where x defaults to 1, but can be specified
as the first argument. */
int
continue_builtin (list)
WORD_LIST *list;
continue_builtin (WORD_LIST *list)
{
intmax_t newcont;
@@ -112,10 +114,14 @@ continue_builtin (list)
if (check_loop_level () == 0)
return (EXECUTION_SUCCESS);
(void)get_numeric_arg (list, 1, &newcont);
/* This will not return if an error is encountered. */
(void)get_numeric_arg (list, interactive_shell ? 2 : 1, &newcont);
if (newcont <= 0)
{
/* skip over `--' option to get the right error message */
if (list && list->word && ISOPTION (list->word->word, '-'))
list = list->next;
sh_erange (list->word->word, _("loop count"));
breaking = loop_level;
return (EXECUTION_FAILURE);
@@ -132,7 +138,7 @@ continue_builtin (list)
/* Return non-zero if a break or continue command would be okay.
Print an error message if break or continue is meaningless here. */
static int
check_loop_level ()
check_loop_level (void)
{
#if defined (BREAK_COMPLAINS)
if (loop_level == 0 && posixly_correct == 0)
+2 -3
View File
@@ -1,7 +1,7 @@
This file is builtin.def, from which is created builtin.c.
It implements the builtin "builtin" in Bash.
Copyright (C) 1987-2017 Free Software Foundation, Inc.
Copyright (C) 1987-2017,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -50,8 +50,7 @@ $END
/* Run the command mentioned in list directly, without going through the
normal alias/function/builtin/filename lookup process. */
int
builtin_builtin (list)
WORD_LIST *list;
builtin_builtin (WORD_LIST *list)
{
sh_builtin_func_t *function;
register char *command;
+9 -5
View File
@@ -2,7 +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-2019 Free Software Foundation, Inc.
Copyright (C) 2008-2019,2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -69,8 +69,7 @@ extern int errno;
#endif /* !errno */
int
caller_builtin (list)
WORD_LIST *list;
caller_builtin (WORD_LIST *list)
{
#if !defined (ARRAY_VARS)
printf ("1 NULL\n");
@@ -109,7 +108,7 @@ caller_builtin (list)
if (funcname_a == 0 || array_empty (funcname_a))
return (EXECUTION_FAILURE);
if (legal_number (list->word->word, &num))
if (valid_number (list->word->word, &num))
{
lineno_s = array_reference (bash_lineno_a, num);
source_s = array_reference (bash_source_a, num+1);
@@ -140,7 +139,12 @@ N_("Returns the context of the current subroutine call.\n\
provide a stack trace.\n\
\n\
The value of EXPR indicates how many call frames to go back before the\n\
current one; the top frame is frame 0."),
current one; the top frame is frame 0.\n\
\n\
Exit Status:\n\
Returns 0 unless the shell is not executing a shell function or EXPR\n\
is invalid."
),
(char *)NULL
};
+44 -63
View File
@@ -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-2022 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -56,13 +56,13 @@ extern int errno;
extern const char * const bash_getcwd_errstr;
static int bindpwd PARAMS((int));
static int setpwd PARAMS((char *));
static char *resetpwd PARAMS((char *));
static int change_to_directory PARAMS((char *, int, int));
static int bindpwd (int);
static int setpwd (char *);
static char *resetpwd (char *);
static int change_to_directory (char *, int, int);
static int cdxattr PARAMS((char *, char **));
static void resetxattr PARAMS((void));
static int cdxattr (char *, char **);
static void resetxattr (void);
/* Change this to 1 to get cd spelling correction by default. */
int cdspelling = 0;
@@ -75,7 +75,7 @@ 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
@@ -115,8 +115,7 @@ $END
/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
static int
setpwd (dirname)
char *dirname;
setpwd (char *dirname)
{
int old_anm;
SHELL_VAR *tvar;
@@ -134,8 +133,7 @@ setpwd (dirname)
}
static int
bindpwd (no_symlinks)
int no_symlinks;
bindpwd (int no_symlinks)
{
char *dirname, *pwdvar;
int old_anm, r, canon_failed;
@@ -160,10 +158,9 @@ bindpwd (no_symlinks)
pwdvar = get_string_value ("PWD");
tvar = bind_variable ("OLDPWD", pwdvar, 0);
if (tvar && readonly_p (tvar))
if (tvar == 0 || readonly_p (tvar))
r = EXECUTION_FAILURE;
if (old_anm == 0 && array_needs_making && exported_p (tvar))
else if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
array_needs_making = 0;
@@ -183,8 +180,7 @@ bindpwd (no_symlinks)
/* Call get_working_directory to reset the value of
the_current_working_directory () */
static char *
resetpwd (caller)
char *caller;
resetpwd (char *caller)
{
char *tdir;
@@ -194,10 +190,9 @@ resetpwd (caller)
return (tdir);
}
/* return new constructed directory name in *NDIRP */
static int
cdxattr (dir, ndirp)
char *dir; /* don't assume we can always free DIR */
char **ndirp; /* return new constructed directory name */
cdxattr (char *dir, char **ndirp)
{
#if defined (O_XATTR)
int apfd, fd, r, e;
@@ -241,7 +236,7 @@ cdxattr (dir, ndirp)
/* Clean up the O_XATTR baggage. Currently only closes xattrfd */
static void
resetxattr ()
resetxattr (void)
{
#if defined (O_XATTR)
if (xattrfd >= 0)
@@ -264,8 +259,7 @@ resetxattr ()
so the programming interface is simple, and it handles errors and
restrictions properly. */
int
cd_builtin (list)
WORD_LIST *list;
cd_builtin (WORD_LIST *list)
{
char *dirname, *cdpath, *path, *temp;
int path_index, no_symlinks, opt, lflag, e;
@@ -320,9 +314,9 @@ cd_builtin (list)
if (list == 0)
{
/* `cd' without arguments is equivalent to `cd $HOME' */
dirname = get_string_value ("HOME");
dirname = get_string_value ("HOME"); /* POSIX cd step 2 */
if (dirname == 0)
if (dirname == 0) /* POSIX cd step 1 */
{
builtin_error (_("HOME not set"));
return (EXECUTION_FAILURE);
@@ -333,13 +327,13 @@ cd_builtin (list)
else if (list->next)
{
builtin_error (_("too many arguments"));
return (EXECUTION_FAILURE);
return (EX_USAGE);
}
#endif
#if 0
else if (list->word->word[0] == '\0')
{
builtin_error (_("null directory"));
builtin_error (_("null directory")); /* POSIX cd implementation defined */
return (EXECUTION_FAILURE);
}
#endif
@@ -353,19 +347,14 @@ cd_builtin (list)
builtin_error (_("OLDPWD not set"));
return (EXECUTION_FAILURE);
}
#if 0
lflag = interactive ? LCD_PRINTPATH : 0;
#else
lflag = LCD_PRINTPATH; /* According to SUSv3 */
#endif
lflag = LCD_PRINTPATH; /* POSIX cd `-' operand */
}
else if (absolute_pathname (list->word->word))
else
dirname = list->word->word;
else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
{
dirname = list->word->word;
/* Find directory in $CDPATH. */
if (privileged_mode == 0 && absolute_pathname (dirname) == 0 && (cdpath = get_string_value ("CDPATH")))
{
/* Find directory in $CDPATH, POSIX cd step 5. */
path_index = 0;
while (path = extract_colon_unit (cdpath, &path_index))
{
@@ -395,23 +384,7 @@ cd_builtin (list)
else
free (temp);
}
#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]
is so we don't mistakenly treat a CDPATH value of "" as not
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
#endif
}
else
dirname = list->word->word;
/* When we get here, DIRNAME is the directory to change to. If we
chdir successfully, just return. */
@@ -482,8 +455,7 @@ static int verbatim_pwd;
/* Print the name of the current working directory. */
int
pwd_builtin (list)
WORD_LIST *list;
pwd_builtin (WORD_LIST *list)
{
char *directory;
int opt, pflag;
@@ -548,9 +520,7 @@ pwd_builtin (list)
to the working directory. Return 1 on success, 0 on failure. */
static int
change_to_directory (newdir, nolinks, xattr)
char *newdir;
int nolinks, xattr;
change_to_directory (char *newdir, int nolinks, int xattr)
{
char *t, *tdir, *ndir;
int err, canon_failed, r, ndlen;
@@ -568,8 +538,11 @@ change_to_directory (newdir, nolinks, xattr)
/* TDIR is either the canonicalized absolute pathname of NEWDIR
(nolinks == 0) or the absolute physical pathname of NEWDIR
(nolinks != 0). */
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
if (t && *t)
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
else
tdir = NULL;
ndlen = strlen (newdir);
@@ -662,9 +635,17 @@ change_to_directory (newdir, nolinks, xattr)
/* We're not in physical mode (nolinks == 0), but we failed to change to
the canonicalized directory name (TDIR). Try what the user passed
verbatim. If we succeed, reinitialize the_current_working_directory.
POSIX requires that we just fail here, so we do in posix mode. */
if (posixly_correct == 0 && chdir (newdir) == 0)
verbatim. If we succeed, reinitialize the_current_working_directory. */
/* The first block is step 9 in the POSIX cd algorithm. */
if (posixly_correct && ndlen < PATH_MAX && strlen (tdir) >= PATH_MAX)
r = chdir (newdir);
else if (posixly_correct == 0)
r = chdir (newdir);
else
r = -1;
if (r == 0)
{
t = resetpwd ("cd");
if (t == 0)
+3 -5
View File
@@ -1,7 +1,7 @@
This file is colon.def, from which is created colon.c.
It implements the builtin ":" in Bash.
Copyright (C) 1987-2019 Free Software Foundation, Inc.
Copyright (C) 1987-2019,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -61,16 +61,14 @@ $END
/* Return a successful result. */
int
colon_builtin (ignore)
WORD_LIST *ignore;
colon_builtin (WORD_LIST *ignore)
{
return (0);
}
/* Return an unsuccessful result. */
int
false_builtin (ignore)
WORD_LIST *ignore;
false_builtin (WORD_LIST *ignore)
{
return (1);
}
+11 -9
View File
@@ -1,7 +1,7 @@
This file is command.def, from which is created command.c.
It implements the builtin "command" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -53,18 +53,18 @@ $END
#include "../shell.h"
#include "../execute_cmd.h"
#include "../flags.h"
#include "../parser.h"
#include "bashgetopt.h"
#include "common.h"
#if defined (_CS_PATH) && defined (HAVE_CONFSTR) && !HAVE_DECL_CONFSTR
extern size_t confstr PARAMS((int, char *, size_t));
extern size_t confstr (int, char *, size_t);
#endif
/* Run the commands mentioned in LIST without paying attention to shell
functions. */
int
command_builtin (list)
WORD_LIST *list;
command_builtin (WORD_LIST *list)
{
int result, verbose, use_standard_path, opt;
COMMAND *command;
@@ -124,20 +124,22 @@ command_builtin (list)
#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN | (use_standard_path ? CMD_STDPATH : 0))
INTERNAL_DEBUG (("command_builtin: running execute_command for `%s'", list->word->word));
/* This code isn't executed any more; look at execute_cmd.c:execute_simple_command()
where command is treated as a pseudo-reserved prefix so we can optimize
away forks where possible. */
/* We don't want this to be reparsed (consider command echo 'foo &'), so
just make a simple_command structure and call execute_command with it. */
command = make_bare_simple_command ();
command = make_bare_simple_command (line_number);
command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= COMMAND_BUILTIN_FLAGS;
command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
add_unwind_protect ((char *)dispose_command, command);
add_unwind_protect (uw_dispose_command, command);
result = execute_command (command);
dispose_command (command);
run_unwind_frame ("command_builtin");
discard_unwind_frame ("command_builtin");
return (result);
}
+97 -165
View File
@@ -1,6 +1,6 @@
/* common.c - utility functions for all builtins */
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -34,12 +34,7 @@
#include <signal.h>
#include <errno.h>
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <stdarg.h>
#include "../bashansi.h"
#include "../bashintl.h"
@@ -85,7 +80,7 @@ sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
shell. */
static void
builtin_error_prolog ()
builtin_error_prolog (void)
{
char *name;
@@ -100,19 +95,13 @@ builtin_error_prolog ()
}
void
#if defined (PREFER_STDARG)
builtin_error (const char *format, ...)
#else
builtin_error (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
builtin_error_prolog ();
SH_VA_START (args, format);
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
@@ -120,20 +109,14 @@ builtin_error (format, va_alist)
}
void
#if defined (PREFER_STDARG)
builtin_warning (const char *format, ...)
#else
builtin_warning (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
builtin_error_prolog ();
fprintf (stderr, _("warning: "));
SH_VA_START (args, format);
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
@@ -142,7 +125,7 @@ builtin_warning (format, va_alist)
/* Print a usage summary for the currently-executing builtin command. */
void
builtin_usage ()
builtin_usage (void)
{
if (this_command_name && *this_command_name)
fprintf (stderr, _("%s: usage: "), this_command_name);
@@ -153,22 +136,25 @@ builtin_usage ()
/* Return if LIST is NULL else barf and jump to top_level. Used by some
builtins that do not accept arguments. */
void
no_args (list)
WORD_LIST *list;
no_args (WORD_LIST *list, int fatal)
{
if (list)
{
builtin_error (_("too many arguments"));
top_level_cleanup ();
jump_to_top_level (DISCARD);
set_exit_status (EX_BADUSAGE);
/* for now, the caller determines whether this is a fatal error */
if (interactive_shell == 0 && fatal)
jump_to_top_level (EXITPROG);
else
jump_to_top_level (DISCARD);
}
}
/* Check that no options were given to the currently-executing builtin,
and return 0 if there were options. */
int
no_options (list)
WORD_LIST *list;
no_options (WORD_LIST *list)
{
int opt;
@@ -187,22 +173,19 @@ no_options (list)
}
void
sh_needarg (s)
char *s;
sh_needarg (const char *s)
{
builtin_error (_("%s: option requires an argument"), s);
}
void
sh_neednumarg (s)
char *s;
sh_neednumarg (const char *s)
{
builtin_error (_("%s: numeric argument required"), s);
}
void
sh_notfound (s)
char *s;
sh_notfound (const char *s)
{
builtin_error (_("%s: not found"), s);
}
@@ -210,29 +193,25 @@ sh_notfound (s)
/* Function called when one of the builtin commands detects an invalid
option. */
void
sh_invalidopt (s)
char *s;
sh_invalidopt (const char *s)
{
builtin_error (_("%s: invalid option"), s);
}
void
sh_invalidoptname (s)
char *s;
sh_invalidoptname (const char *s)
{
builtin_error (_("%s: invalid option name"), s);
}
void
sh_invalidid (s)
char *s;
sh_invalidid (const char *s)
{
builtin_error (_("`%s': not a valid identifier"), s);
}
void
sh_invalidnum (s)
char *s;
sh_invalidnum (const char *s)
{
char *msg;
@@ -246,36 +225,31 @@ sh_invalidnum (s)
}
void
sh_invalidsig (s)
char *s;
sh_invalidsig (const char *s)
{
builtin_error (_("%s: invalid signal specification"), s);
}
void
sh_badpid (s)
char *s;
sh_badpid (const char *s)
{
builtin_error (_("`%s': not a pid or valid job spec"), s);
}
void
sh_readonly (s)
const char *s;
sh_readonly (const char *s)
{
builtin_error (_("%s: readonly variable"), s);
}
void
sh_noassign (s)
const char *s;
sh_noassign (const char *s)
{
internal_error (_("%s: cannot assign"), s); /* XXX */
}
void
sh_erange (s, desc)
char *s, *desc;
sh_erange (const char *s, const char *desc)
{
if (s)
builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument"));
@@ -285,15 +259,13 @@ sh_erange (s, desc)
#if defined (JOB_CONTROL)
void
sh_badjob (s)
char *s;
sh_badjob (const char *s)
{
builtin_error (_("%s: no such job"), s);
}
void
sh_nojobs (s)
char *s;
sh_nojobs (const char *s)
{
if (s)
builtin_error (_("%s: no job control"), s);
@@ -304,8 +276,7 @@ sh_nojobs (s)
#if defined (RESTRICTED_SHELL)
void
sh_restricted (s)
char *s;
sh_restricted (const char *s)
{
if (s)
builtin_error (_("%s: restricted"), s);
@@ -315,14 +286,13 @@ sh_restricted (s)
#endif
void
sh_notbuiltin (s)
char *s;
sh_notbuiltin (const char *s)
{
builtin_error (_("%s: not a shell builtin"), s);
}
void
sh_wrerror ()
sh_wrerror (void)
{
#if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE)
if (errno != EPIPE)
@@ -331,8 +301,7 @@ sh_wrerror ()
}
void
sh_ttyerror (set)
int set;
sh_ttyerror (int set)
{
if (set)
builtin_error (_("error setting terminal attributes: %s"), strerror (errno));
@@ -341,8 +310,7 @@ sh_ttyerror (set)
}
int
sh_chkwrite (s)
int s;
sh_chkwrite (int s)
{
QUIT;
fflush (stdout);
@@ -367,9 +335,7 @@ sh_chkwrite (s)
in the list in *IP, if IP is non-null. A convenience function for
loadable builtins; also used by `test'. */
char **
make_builtin_argv (list, ip)
WORD_LIST *list;
int *ip;
make_builtin_argv (WORD_LIST *list, int *ip)
{
char **argv;
@@ -383,9 +349,7 @@ make_builtin_argv (list, ip)
only discard the ones that are to be replaced. Set POSPARAM_COUNT
to the number of args assigned (length of LIST). */
void
remember_args (list, destructive)
WORD_LIST *list;
int destructive;
remember_args (WORD_LIST *list, int destructive)
{
register int i;
@@ -413,7 +377,7 @@ remember_args (list, destructive)
{
dispose_words (rest_of_args);
rest_of_args = copy_word_list (list);
posparam_count += list_length (list);
posparam_count += list_length ((GENERIC_LIST *)list);
}
if (destructive)
@@ -423,8 +387,7 @@ remember_args (list, destructive)
}
void
shift_args (times)
int times;
shift_args (int times)
{
WORD_LIST *temp;
int count;
@@ -456,7 +419,7 @@ shift_args (times)
}
int
number_of_args ()
number_of_args (void)
{
#if 0
register WORD_LIST *list;
@@ -479,19 +442,19 @@ static int changed_dollar_vars;
/* Have the dollar variables been reset to new values since we last
checked? */
int
dollar_vars_changed ()
dollar_vars_changed (void)
{
return (changed_dollar_vars);
}
void
set_dollar_vars_unchanged ()
set_dollar_vars_unchanged (void)
{
changed_dollar_vars = 0;
}
void
set_dollar_vars_changed ()
set_dollar_vars_changed (void)
{
if (variable_context)
changed_dollar_vars |= ARGS_FUNC;
@@ -515,10 +478,7 @@ set_dollar_vars_changed ()
current command; if FATAL is 0, return an indication of an invalid
number by setting *NUMOK == 0 and return -1. */
int
get_numeric_arg (list, fatal, count)
WORD_LIST *list;
int fatal;
intmax_t *count;
get_numeric_arg (WORD_LIST *list, int fatal, intmax_t *count)
{
char *arg;
@@ -531,20 +491,17 @@ get_numeric_arg (list, fatal, count)
if (list)
{
arg = list->word->word;
if (arg == 0 || (legal_number (arg, count) == 0))
if (arg == 0 || (valid_number (arg, count) == 0))
{
sh_neednumarg (list->word->word ? list->word->word : "`'");
if (fatal == 0)
return 0;
else if (fatal == 1) /* fatal == 1; abort */
throw_to_top_level ();
else /* fatal == 2; discard current command */
{
top_level_cleanup ();
jump_to_top_level (DISCARD);
}
set_exit_status (EX_BADUSAGE);
/* fatal == 1: abort; fatal == 2: discard current command */
top_level_cleanup ();
jump_to_top_level ((fatal == 1) ? EXITPROG : DISCARD);
}
no_args (list->next);
no_args (list->next, 0);
}
return (1);
@@ -552,8 +509,7 @@ get_numeric_arg (list, fatal, count)
/* Get an eight-bit status value from LIST */
int
get_exitstat (list)
WORD_LIST *list;
get_exitstat (WORD_LIST *list)
{
int status;
intmax_t sval;
@@ -564,24 +520,27 @@ get_exitstat (list)
if (list == 0)
{
/* If we're not running the DEBUG trap, the return builtin, when not
given any arguments, uses the value of $? before the trap ran. If
given an argument, return uses it. This means that the trap can't
change $?. The DEBUG trap gets to change $?, though, since that is
part of its reason for existing, and because the extended debug mode
does things with the return value. */
if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1)
/* If we're not running the DEBUG trap, and haven't executed a shell
function from the trap action, the return builtin, when not given
any arguments, uses the value of $? before the trap ran. The business
about executing a shell function from the trap action is from POSIX
interp 1602 (10/2022). If given an argument, return uses it
unconditionally. This means that the trap can't change $?. The DEBUG
trap gets to change $?, though, since that is part of its reason for
existing, and because the extended debug mode does things with the
return value. */
if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1 && trap_return_context == funcnest + sourcenest)
return (trap_saved_exit_value);
return (last_command_exit_value);
}
arg = list->word->word;
if (arg == 0 || legal_number (arg, &sval) == 0)
if (arg == 0 || valid_number (arg, &sval) == 0)
{
sh_neednumarg (list->word->word ? list->word->word : "`'");
return EX_BADUSAGE;
return EX_USAGE;
}
no_args (list->next);
no_args (list->next, 0);
status = sval & 255;
return status;
@@ -590,8 +549,7 @@ get_exitstat (list)
/* Return the octal number parsed from STRING, or -1 to indicate
that the string contained a bad number. */
int
read_octal (string)
char *string;
read_octal (char *string)
{
int result, digits;
@@ -621,8 +579,7 @@ read_octal (string)
char *the_current_working_directory = (char *)NULL;
char *
get_working_directory (for_whom)
char *for_whom;
get_working_directory (const char *for_whom)
{
if (no_symbolic_links)
{
@@ -651,8 +608,7 @@ get_working_directory (for_whom)
/* Make NAME our internal idea of the current working directory. */
void
set_working_directory (name)
char *name;
set_working_directory (const char *name)
{
FREE (the_current_working_directory);
the_current_working_directory = savestring (name);
@@ -666,13 +622,12 @@ set_working_directory (name)
#if defined (JOB_CONTROL)
int
get_job_by_name (name, flags)
const char *name;
int flags;
get_job_by_name (const char *name, int flags)
{
register int i, wl, cl, match, job;
register PROCESS *p;
register JOB *j;
int i, match, job;
size_t wl, cl;
PROCESS *p;
JOB *j;
job = NO_JOB;
wl = strlen (name);
@@ -721,8 +676,7 @@ get_job_by_name (name, flags)
/* Return the job spec found in LIST. */
int
get_job_spec (list)
WORD_LIST *list;
get_job_spec (WORD_LIST *list)
{
register char *word;
int job, jflags;
@@ -770,9 +724,7 @@ get_job_spec (list)
* NOTE: `kill' calls this function with forcecols == 0
*/
int
display_signal_list (list, forcecols)
WORD_LIST *list;
int forcecols;
display_signal_list (WORD_LIST *list, int forcecols)
{
register int i, column;
char *name;
@@ -818,7 +770,7 @@ display_signal_list (list, forcecols)
/* List individual signal names or numbers. */
while (list)
{
if (legal_number (list->word->word, &lsignum))
if (valid_number (list->word->word, &lsignum))
{
/* This is specified by Posix.2 so that exit statuses can be
mapped into signal numbers. */
@@ -875,9 +827,7 @@ display_signal_list (list, forcecols)
Return the address of the builtin.
DISABLED_OKAY means find it even if the builtin is disabled. */
struct builtin *
builtin_address_internal (name, disabled_okay)
char *name;
int disabled_okay;
builtin_address_internal (const char *name, int disabled_okay)
{
int hi, lo, mid, j;
@@ -915,8 +865,7 @@ builtin_address_internal (name, disabled_okay)
/* Return the pointer to the function implementing builtin command NAME. */
sh_builtin_func_t *
find_shell_builtin (name)
char *name;
find_shell_builtin (const char *name)
{
current_builtin = builtin_address_internal (name, 0);
return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
@@ -924,8 +873,7 @@ find_shell_builtin (name)
/* Return the address of builtin with NAME, whether it is enabled or not. */
sh_builtin_func_t *
builtin_address (name)
char *name;
builtin_address (const char *name)
{
current_builtin = builtin_address_internal (name, 1);
return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
@@ -934,8 +882,7 @@ builtin_address (name)
/* Return the function implementing the builtin NAME, but only if it is a
POSIX.2 special builtin. */
sh_builtin_func_t *
find_special_builtin (name)
char *name;
find_special_builtin (const char *name)
{
current_builtin = builtin_address_internal (name, 0);
return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
@@ -944,8 +891,7 @@ find_special_builtin (name)
}
static int
shell_builtin_compare (sbp1, sbp2)
struct builtin *sbp1, *sbp2;
shell_builtin_compare (const struct builtin *sbp1, const struct builtin *sbp2)
{
int result;
@@ -958,7 +904,7 @@ shell_builtin_compare (sbp1, sbp2)
/* Sort the table of shell builtins so that the binary search will work
in find_shell_builtin. */
void
initialize_shell_builtins ()
initialize_shell_builtins (void)
{
qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
(QSFUNC *)shell_builtin_compare);
@@ -966,7 +912,7 @@ initialize_shell_builtins ()
#if !defined (HELP_BUILTIN)
void
builtin_help ()
builtin_help (void)
{
printf ("%s: %s\n", this_command_name, _("help not available in this version"));
}
@@ -980,10 +926,7 @@ builtin_help ()
/* Assign NAME=VALUE, passing FLAGS to the assignment functions. */
SHELL_VAR *
builtin_bind_variable (name, value, flags)
char *name;
char *value;
int flags;
builtin_bind_variable (char *name, char *value, int flags)
{
SHELL_VAR *v;
int vflags, bindflags;
@@ -991,12 +934,11 @@ builtin_bind_variable (name, value, flags)
#if defined (ARRAY_VARS)
/* Callers are responsible for calling this with array references that have
already undergone valid_array_reference checks (read, printf). */
vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
bindflags = flags | (assoc_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
if (flags & ASS_NOEXPAND)
vflags |= VA_NOEXPAND;
if (flags & ASS_ONEWORD)
vflags |= VA_ONEWORD;
/* XXX - should we unconditionally set ASS_NOEXPAND if the shell
compatibility level is > 52? */
bindflags = flags | (array_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
vflags = convert_assign_flags_to_validarray_flags (flags);
vflags |= array_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
if (valid_array_reference (name, vflags) == 0)
v = bind_variable (name, value, flags);
@@ -1013,10 +955,7 @@ builtin_bind_variable (name, value, flags)
}
SHELL_VAR *
builtin_bind_var_to_int (name, val, flags)
char *name;
intmax_t val;
int flags;
builtin_bind_var_to_int (char *name, intmax_t val, int flags)
{
SHELL_VAR *v;
@@ -1026,13 +965,11 @@ builtin_bind_var_to_int (name, val, flags)
#if defined (ARRAY_VARS)
SHELL_VAR *
builtin_find_indexed_array (array_name, flags)
char *array_name;
int flags;
builtin_find_indexed_array (char *array_name, int flags)
{
SHELL_VAR *entry;
if ((flags & 2) && legal_identifier (array_name) == 0)
if ((flags & 2) && valid_identifier (array_name) == 0)
{
sh_invalidid (array_name);
return (SHELL_VAR *)NULL;
@@ -1061,8 +998,7 @@ builtin_find_indexed_array (array_name, flags)
/* Like check_unbind_variable, but for use by builtins (only matters for
error messages). */
int
builtin_unbind_variable (vname)
const char *vname;
builtin_unbind_variable (const char *vname)
{
SHELL_VAR *v;
@@ -1081,16 +1017,13 @@ builtin_unbind_variable (vname)
}
int
builtin_arrayref_flags (w, baseflags)
WORD_DESC *w;
int baseflags;
builtin_arrayref_flags (WORD_DESC *w, int baseflags)
{
char *t;
int vflags;
vflags = baseflags;
/* Don't require assoc_expand_once if we have an argument that's already
/* Don't require array_expand_once if we have an argument that's already
passed through valid_array_reference and been expanded once. That
doesn't protect it from normal expansions like word splitting, so
proper quoting is still required. */
@@ -1099,7 +1032,7 @@ builtin_arrayref_flags (w, baseflags)
# if 0
/* This is a little sketchier but handles quoted arguments. */
if (assoc_expand_once && (t = strchr (w->word, '[')) && t[strlen(t) - 1] == ']')
if (array_expand_once && (t = strchr (w->word, '[')) && t[strlen(t) - 1] == ']')
vflags |= VA_ONEWORD|VA_NOEXPAND;
# endif
@@ -1114,17 +1047,16 @@ builtin_arrayref_flags (w, baseflags)
#if defined (ARRAY_VARS)
int
set_expand_once (nval, uwp)
int nval, uwp;
set_expand_once (int nval, int uwp)
{
int oa;
oa = assoc_expand_once;
oa = array_expand_once;
if (shell_compatibility_level > 51) /* XXX - internal */
{
if (uwp)
unwind_protect_int (assoc_expand_once);
assoc_expand_once = nval;
unwind_protect_int (array_expand_once);
array_expand_once = nval;
}
return oa;
}
+107 -107
View File
@@ -81,163 +81,163 @@ do { \
#define MAX_ATTRIBUTES 16
/* Functions from common.c */
extern void builtin_error PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
extern void builtin_warning PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
extern void builtin_usage PARAMS((void));
extern void no_args PARAMS((WORD_LIST *));
extern int no_options PARAMS((WORD_LIST *));
extern void builtin_error (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
extern void builtin_warning (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
extern void builtin_usage (void);
extern void no_args (WORD_LIST *, int);
extern int no_options (WORD_LIST *);
/* common error message functions */
extern void sh_needarg PARAMS((char *));
extern void sh_neednumarg PARAMS((char *));
extern void sh_notfound PARAMS((char *));
extern void sh_invalidopt PARAMS((char *));
extern void sh_invalidoptname PARAMS((char *));
extern void sh_invalidid PARAMS((char *));
extern void sh_invalidnum PARAMS((char *));
extern void sh_invalidsig PARAMS((char *));
extern void sh_readonly PARAMS((const char *));
extern void sh_noassign PARAMS((const char *));
extern void sh_erange PARAMS((char *, char *));
extern void sh_badpid PARAMS((char *));
extern void sh_badjob PARAMS((char *));
extern void sh_nojobs PARAMS((char *));
extern void sh_restricted PARAMS((char *));
extern void sh_notbuiltin PARAMS((char *));
extern void sh_wrerror PARAMS((void));
extern void sh_ttyerror PARAMS((int));
extern int sh_chkwrite PARAMS((int));
extern void sh_needarg (const char *);
extern void sh_neednumarg (const char *);
extern void sh_notfound (const char *);
extern void sh_invalidopt (const char *);
extern void sh_invalidoptname (const char *);
extern void sh_invalidid (const char *);
extern void sh_invalidnum (const char *);
extern void sh_invalidsig (const char *);
extern void sh_readonly (const char *);
extern void sh_noassign (const char *);
extern void sh_erange (const char *, const char *);
extern void sh_badpid (const char *);
extern void sh_badjob (const char *);
extern void sh_nojobs (const char *);
extern void sh_restricted (const char *);
extern void sh_notbuiltin (const char *);
extern void sh_wrerror (void);
extern void sh_ttyerror (int);
extern int sh_chkwrite (int);
extern char **make_builtin_argv PARAMS((WORD_LIST *, int *));
extern void remember_args PARAMS((WORD_LIST *, int));
extern void shift_args PARAMS((int));
extern int number_of_args PARAMS((void));
extern char **make_builtin_argv (WORD_LIST *, int *);
extern void remember_args (WORD_LIST *, int);
extern void shift_args (int);
extern int number_of_args (void);
extern int dollar_vars_changed PARAMS((void));
extern void set_dollar_vars_unchanged PARAMS((void));
extern void set_dollar_vars_changed PARAMS((void));
extern int dollar_vars_changed (void);
extern void set_dollar_vars_unchanged (void);
extern void set_dollar_vars_changed (void);
extern int get_numeric_arg PARAMS((WORD_LIST *, int, intmax_t *));
extern int get_exitstat PARAMS((WORD_LIST *));
extern int read_octal PARAMS((char *));
extern int get_numeric_arg (WORD_LIST *, int, intmax_t *);
extern int get_exitstat (WORD_LIST *);
extern int read_octal (char *);
/* Keeps track of the current working directory. */
extern char *the_current_working_directory;
extern char *get_working_directory PARAMS((char *));
extern void set_working_directory PARAMS((char *));
extern char *get_working_directory (const char *);
extern void set_working_directory (const char *);
#if defined (JOB_CONTROL)
extern int get_job_by_name PARAMS((const char *, int));
extern int get_job_spec PARAMS((WORD_LIST *));
extern int get_job_by_name (const char *, int);
extern int get_job_spec (WORD_LIST *);
#endif
extern int display_signal_list PARAMS((WORD_LIST *, int));
extern int display_signal_list (WORD_LIST *, int);
/* It's OK to declare a function as returning a Function * without
providing a definition of what a `Function' is. */
extern struct builtin *builtin_address_internal PARAMS((char *, int));
extern sh_builtin_func_t *find_shell_builtin PARAMS((char *));
extern sh_builtin_func_t *builtin_address PARAMS((char *));
extern sh_builtin_func_t *find_special_builtin PARAMS((char *));
extern void initialize_shell_builtins PARAMS((void));
extern struct builtin *builtin_address_internal (const char *, int);
extern sh_builtin_func_t *find_shell_builtin (const char *);
extern sh_builtin_func_t *builtin_address (const char *);
extern sh_builtin_func_t *find_special_builtin (const char *);
extern void initialize_shell_builtins (void);
#if defined (ARRAY_VARS)
extern int set_expand_once PARAMS((int, int));
extern int set_expand_once (int, int);
#endif
/* Functions from exit.def */
extern void bash_logout PARAMS((void));
extern void bash_logout (void);
/* Functions from getopts.def */
extern void getopts_reset PARAMS((int));
extern void getopts_reset (int);
/* Functions from help.def */
extern void builtin_help PARAMS((void));
extern void builtin_help (void);
/* Functions from read.def */
extern void read_tty_cleanup PARAMS((void));
extern int read_tty_modified PARAMS((void));
extern void read_tty_cleanup (void);
extern int read_tty_modified (void);
extern int read_builtin_timeout PARAMS((int));
extern void check_read_timeout PARAMS((void));
extern int read_builtin_timeout (int);
extern void check_read_timeout (void);
/* Functions from set.def */
extern int minus_o_option_value PARAMS((char *));
extern void list_minus_o_opts PARAMS((int, int));
extern char **get_minus_o_opts PARAMS((void));
extern int set_minus_o_option PARAMS((int, char *));
extern int minus_o_option_value (char *);
extern void list_minus_o_opts (int, int);
extern char **get_minus_o_opts (void);
extern int set_minus_o_option (int, char *);
extern void set_shellopts PARAMS((void));
extern void parse_shellopts PARAMS((char *));
extern void initialize_shell_options PARAMS((int));
extern void set_shellopts (void);
extern void parse_shellopts (char *);
extern void initialize_shell_options (int);
extern void reset_shell_options PARAMS((void));
extern void reset_shell_options (void);
extern char *get_current_options PARAMS((void));
extern void set_current_options PARAMS((const char *));
extern char *get_current_options (void);
extern void set_current_options (const char *);
/* Functions from shopt.def */
extern void reset_shopt_options PARAMS((void));
extern char **get_shopt_options PARAMS((void));
extern void reset_shopt_options (void);
extern char **get_shopt_options (void);
extern int shopt_setopt PARAMS((char *, int));
extern int shopt_listopt PARAMS((char *, int));
extern int shopt_setopt (char *, int);
extern int shopt_listopt (char *, int);
extern int set_login_shell PARAMS((char *, int));
extern int set_login_shell (char *, int);
extern void set_bashopts PARAMS((void));
extern void parse_bashopts PARAMS((char *));
extern void initialize_bashopts PARAMS((int));
extern void set_bashopts (void);
extern void parse_bashopts (char *);
extern void initialize_bashopts (int);
extern void set_compatibility_opts PARAMS((void));
extern void set_compatibility_opts (void);
/* Functions from type.def */
extern int describe_command PARAMS((char *, int));
extern int describe_command (char *, int);
/* Functions from setattr.def */
extern int set_or_show_attributes PARAMS((WORD_LIST *, int, int));
extern int show_all_var_attributes PARAMS((int, int));
extern int show_local_var_attributes PARAMS((int, int));
extern int show_var_attributes PARAMS((SHELL_VAR *, int, int));
extern int show_name_attributes PARAMS((char *, int));
extern int show_localname_attributes PARAMS((char *, int));
extern int show_func_attributes PARAMS((char *, int));
extern void set_var_attribute PARAMS((char *, int, int));
extern int var_attribute_string PARAMS((SHELL_VAR *, int, char *));
extern int set_or_show_attributes (WORD_LIST *, int, int);
extern int show_all_var_attributes (int, int);
extern int show_local_var_attributes (int, int);
extern int show_var_attributes (SHELL_VAR *, int, int);
extern int show_name_attributes (char *, int);
extern int show_localname_attributes (char *, int);
extern int show_func_attributes (char *, int);
extern void set_var_attribute (char *, int, int);
extern int var_attribute_string (SHELL_VAR *, int, char *);
/* Functions from pushd.def */
extern char *get_dirstack_from_string PARAMS((char *));
extern char *get_dirstack_element PARAMS((intmax_t, int));
extern void set_dirstack_element PARAMS((intmax_t, int, char *));
extern WORD_LIST *get_directory_stack PARAMS((int));
extern char *get_dirstack_from_string (char *);
extern char *get_dirstack_element (intmax_t, int);
extern void set_dirstack_element (intmax_t, int, char *);
extern WORD_LIST *get_directory_stack (int);
/* Functions from evalstring.c */
extern int parse_and_execute PARAMS((char *, const char *, int));
extern int evalstring PARAMS((char *, const char *, int));
extern void parse_and_execute_cleanup PARAMS((int));
extern int parse_string PARAMS((char *, const char *, int, COMMAND **, char **));
extern int should_suppress_fork PARAMS((COMMAND *));
extern int can_optimize_connection PARAMS((COMMAND *));
extern int can_optimize_cat_file PARAMS((COMMAND *));
extern void optimize_connection_fork PARAMS((COMMAND *));
extern void optimize_subshell_command PARAMS((COMMAND *));
extern void optimize_shell_function PARAMS((COMMAND *));
extern int parse_and_execute (char *, const char *, int);
extern int evalstring (char *, const char *, int);
extern void parse_and_execute_cleanup (int);
extern int parse_string (char *, const char *, int, COMMAND **, char **);
extern int should_suppress_fork (COMMAND *);
extern int can_optimize_connection (COMMAND *);
extern int can_optimize_cat_file (COMMAND *);
extern void optimize_connection_fork (COMMAND *);
extern void optimize_subshell_command (COMMAND *);
extern void optimize_shell_function (COMMAND *);
/* Functions from evalfile.c */
extern int maybe_execute_file PARAMS((const char *, int));
extern int force_execute_file PARAMS((const char *, int));
extern int source_file PARAMS((const char *, int));
extern int fc_execute_file PARAMS((const char *));
extern int maybe_execute_file (const char *, int);
extern int force_execute_file (const char *, int);
extern int source_file (const char *, int);
extern int fc_execute_file (const char *);
/* variables from common.c */
extern sh_builtin_func_t *this_shell_builtin;
extern sh_builtin_func_t *last_shell_builtin;
extern SHELL_VAR *builtin_bind_variable PARAMS((char *, char *, int));
extern SHELL_VAR *builtin_bind_var_to_int PARAMS((char *, intmax_t, int));
extern int builtin_unbind_variable PARAMS((const char *));
extern SHELL_VAR *builtin_bind_variable (char *, char *, int);
extern SHELL_VAR *builtin_bind_var_to_int (char *, intmax_t, int);
extern int builtin_unbind_variable (const char *);
extern SHELL_VAR *builtin_find_indexed_array PARAMS((char *, int));
extern int builtin_arrayref_flags PARAMS((WORD_DESC *, int));
extern SHELL_VAR *builtin_find_indexed_array (char *, int);
extern int builtin_arrayref_flags (WORD_DESC *, int);
/* variables from evalfile.c */
extern int sourcelevel;
@@ -275,9 +275,9 @@ extern int wait_intr_flag;
#if defined (ARRAY_VARS)
#define SET_VFLAGS(wordflags, vflags, bindflags) \
do { \
vflags = assoc_expand_once ? VA_NOEXPAND : 0; \
bindflags = assoc_expand_once ? ASS_NOEXPAND : 0; \
if (assoc_expand_once && (wordflags & W_ARRAYREF)) \
vflags = array_expand_once ? VA_NOEXPAND : 0; \
bindflags = array_expand_once ? ASS_NOEXPAND : 0; \
if (array_expand_once && (wordflags & W_ARRAYREF)) \
vflags |= VA_ONEWORD|VA_NOEXPAND; \
if (vflags & VA_NOEXPAND) \
bindflags |= ASS_NOEXPAND; \
+91 -65
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1999-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -27,8 +27,8 @@ $SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DEI] [-o option] [-A action] [-G glo
Specify how arguments are to be completed by Readline.
For each NAME, specify how arguments are to be completed. If no options
are supplied, existing completion specifications are printed in a way that
allows them to be reused as input.
or NAMEs are supplied, display existing completion specifications in a way
that allows them to be reused as input.
Options:
-p print existing completion specifications in a reusable format
@@ -84,23 +84,23 @@ struct _optflags {
int Iflag;
};
static int find_compact PARAMS((char *));
static int find_compopt PARAMS((char *));
static int find_compact (char *);
static int find_compopt (char *);
static int build_actions PARAMS((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *));
static int build_actions (WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *, char **);
static int remove_cmd_completions PARAMS((WORD_LIST *));
static int remove_cmd_completions (WORD_LIST *);
static int print_one_completion PARAMS((char *, COMPSPEC *));
static int print_compitem PARAMS((BUCKET_CONTENTS *));
static void print_compopts PARAMS((const char *, COMPSPEC *, int));
static void print_all_completions PARAMS((void));
static int print_cmd_completions PARAMS((WORD_LIST *));
static int print_one_completion (char *, COMPSPEC *);
static int print_compitem (BUCKET_CONTENTS *);
static void print_compopts (const char *, COMPSPEC *, int);
static void print_all_completions (void);
static int print_cmd_completions (WORD_LIST *);
static void print_compoptions PARAMS((unsigned long, int));
static void print_compactions PARAMS((unsigned long));
static void print_arg PARAMS((const char *, const char *, int));
static void print_cmd_name PARAMS((const char *));
static void print_compoptions (unsigned long, int);
static void print_compactions (unsigned long);
static void print_arg (const char *, const char *, int);
static void print_cmd_name (const char *);
static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
@@ -145,6 +145,7 @@ static const struct _compopt {
{ "default", COPT_DEFAULT },
{ "dirnames", COPT_DIRNAMES },
{ "filenames",COPT_FILENAMES},
{ "fullquote",COPT_FULLQUOTE},
{ "noquote", COPT_NOQUOTE },
{ "nosort", COPT_NOSORT },
{ "nospace", COPT_NOSPACE },
@@ -153,8 +154,7 @@ static const struct _compopt {
};
static int
find_compact (name)
char *name;
find_compact (char *name)
{
register int i;
@@ -165,8 +165,7 @@ find_compact (name)
}
static int
find_compopt (name)
char *name;
find_compopt (char *name)
{
register int i;
@@ -182,6 +181,8 @@ find_compopt (name)
bitmap of compspec options (arguments to `-o'). PP, if non-null, gets 1
if -p is supplied; RP, if non-null, gets 1 if -r is supplied.
If either is null, the corresponding option generates an error.
VNAMEP is a pointer to a string to store the name of the output variable
supplied with the -V option.
This also sets variables corresponding to options that take arguments as
a side effect; the caller should ensure that those variables are set to
NULL before calling build_actions. Return value:
@@ -191,10 +192,7 @@ find_compopt (name)
*/
static int
build_actions (list, flagp, actp, optp)
WORD_LIST *list;
struct _optflags *flagp;
unsigned long *actp, *optp;
build_actions (WORD_LIST *list, struct _optflags *flagp, unsigned long *actp, unsigned long *optp, char **vnamep)
{
int opt, ind, opt_given;
unsigned long acts, copts;
@@ -204,7 +202,7 @@ build_actions (list, flagp, actp, optp)
opt_given = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI")) != -1)
while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:V:DEI")) != -1)
{
opt_given = 1;
switch (opt)
@@ -346,6 +344,25 @@ build_actions (list, flagp, actp, optp)
case 'S':
Sarg = list_optarg;
break;
case 'V':
#if defined (ARRAY_VARS)
if (vnamep)
{
*vnamep = list_optarg;
if (valid_identifier (list_optarg) == 0)
{
sh_invalidid (list_optarg);
return (EX_USAGE);
}
}
else
#endif
{
sh_invalidopt ("-V");
builtin_usage ();
return (EX_USAGE);
}
break;
case 'W':
Warg = list_optarg;
break;
@@ -367,8 +384,7 @@ build_actions (list, flagp, actp, optp)
/* Add, remove, and display completion specifiers. */
int
complete_builtin (list)
WORD_LIST *list;
complete_builtin (WORD_LIST *list)
{
int opt_given, rval;
unsigned long acts, copts;
@@ -391,7 +407,7 @@ complete_builtin (list)
/* Build the actions from the arguments. Also sets the [A-Z]arg variables
as a side effect if they are supplied as options. */
rval = build_actions (list, &oflags, &acts, &copts);
rval = build_actions (list, &oflags, &acts, &copts, (char **)NULL);
if (rval == EX_USAGE)
return (rval);
opt_given = rval != EXECUTION_FAILURE;
@@ -473,8 +489,7 @@ complete_builtin (list)
}
static int
remove_cmd_completions (list)
WORD_LIST *list;
remove_cmd_completions (WORD_LIST *list)
{
WORD_LIST *l;
int ret;
@@ -491,9 +506,7 @@ remove_cmd_completions (list)
}
static void
print_compoptions (copts, full)
unsigned long copts;
int full;
print_compoptions (unsigned long copts, int full)
{
const struct _compopt *co;
@@ -505,8 +518,7 @@ print_compoptions (copts, full)
}
static void
print_compactions (acts)
unsigned long acts;
print_compactions (unsigned long acts)
{
const struct _compacts *ca;
@@ -522,9 +534,7 @@ print_compactions (acts)
}
static void
print_arg (arg, flag, quote)
const char *arg, *flag;
int quote;
print_arg (const char *arg, const char *flag, int quote)
{
char *x;
@@ -538,8 +548,7 @@ print_arg (arg, flag, quote)
}
static void
print_cmd_name (cmd)
const char *cmd;
print_cmd_name (const char *cmd)
{
char *x;
@@ -562,9 +571,7 @@ print_cmd_name (cmd)
}
static int
print_one_completion (cmd, cs)
char *cmd;
COMPSPEC *cs;
print_one_completion (char *cmd, COMPSPEC *cs)
{
printf ("complete ");
@@ -592,10 +599,7 @@ print_one_completion (cmd, cs)
}
static void
print_compopts (cmd, cs, full)
const char *cmd;
COMPSPEC *cs;
int full;
print_compopts (const char *cmd, COMPSPEC *cs, int full)
{
printf ("compopt ");
@@ -606,8 +610,7 @@ print_compopts (cmd, cs, full)
}
static int
print_compitem (item)
BUCKET_CONTENTS *item;
print_compitem (BUCKET_CONTENTS *item)
{
COMPSPEC *cs;
char *cmd;
@@ -619,14 +622,13 @@ print_compitem (item)
}
static void
print_all_completions ()
print_all_completions (void)
{
progcomp_walk (print_compitem);
}
static int
print_cmd_completions (list)
WORD_LIST *list;
print_cmd_completions (WORD_LIST *list)
{
WORD_LIST *l;
COMPSPEC *cs;
@@ -650,20 +652,22 @@ print_cmd_completions (list)
$BUILTIN compgen
$DEPENDS_ON PROGRAMMABLE_COMPLETION
$FUNCTION compgen_builtin
$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
$SHORT_DOC compgen [-V varname] [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
Display possible completions depending on the options.
Intended to be used from within a shell function generating possible
completions. If the optional WORD argument is supplied, matches against
WORD are generated.
completions. If the optional WORD argument is present, generate matches
against WORD.
If the -V option is supplied, store the possible completions in the indexed
array VARNAME instead of printing them to the standard output.
Exit Status:
Returns success unless an invalid option is supplied or an error occurs.
$END
int
compgen_builtin (list)
WORD_LIST *list;
compgen_builtin (WORD_LIST *list)
{
int rval;
unsigned long acts, copts;
@@ -671,7 +675,9 @@ compgen_builtin (list)
STRINGLIST *sl;
char *word, **matches;
char *old_line;
int old_ind;
int old_ind, old_completion, old_quoting, old_suppress;
SHELL_VAR *var;
char *varname;
if (list == 0)
return (EXECUTION_SUCCESS);
@@ -679,10 +685,11 @@ compgen_builtin (list)
acts = copts = (unsigned long)0L;
Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
cs = (COMPSPEC *)NULL;
varname = 0;
/* Build the actions from the arguments. Also sets the [A-Z]arg variables
as a side effect if they are supplied as options. */
rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts);
rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts, &varname);
if (rval == EX_USAGE)
return (rval);
if (rval == EXECUTION_FAILURE)
@@ -713,6 +720,12 @@ compgen_builtin (list)
rval = EXECUTION_FAILURE;
old_completion = rl_filename_completion_desired;
old_quoting = rl_filename_quoting_desired;
old_suppress = rl_completion_suppress_append;
bashline_set_filename_hooks ();
/* probably don't have to save these, just being safe */
old_line = pcomp_line;
old_ind = pcomp_ind;
@@ -741,15 +754,29 @@ compgen_builtin (list)
strvec_dispose (matches);
}
if (sl)
rl_filename_completion_desired = old_completion;
rl_filename_quoting_desired = old_quoting;
rl_completion_suppress_append = old_suppress;
#if defined (ARRAY_VARS)
if (varname)
{
if (sl->list && sl->list_len)
var = builtin_find_indexed_array (varname, 1);
if (var && sl && sl->list && sl->list_len)
{
array_from_argv (array_cell (var), sl->list, sl->list_len);
rval = EXECUTION_SUCCESS;
strlist_print (sl, (char *)NULL);
}
strlist_dispose (sl);
}
else
#endif
if (sl && sl->list && sl->list_len)
{
rval = EXECUTION_SUCCESS;
strlist_print (sl, (char *)NULL);
}
if (sl)
strlist_dispose (sl);
compspec_dispose (cs);
return (rval);
@@ -787,8 +814,7 @@ have a completion specification defined.
$END
int
compopt_builtin (list)
WORD_LIST *list;
compopt_builtin (WORD_LIST *list)
{
int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag, Iflag;
WORD_LIST *l, *wl;
+120 -59
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -49,7 +49,8 @@ Options which set attributes:
-u to convert the value of each NAME to upper case on assignment
-x to make NAMEs export
Using `+' instead of `-' turns off the given attribute.
Using `+' instead of `-' turns off the given attribute, except for a,
A, and r.
Variables with the integer attribute have arithmetic evaluation (see
the `let' command) performed when the variable is assigned a value.
@@ -90,16 +91,15 @@ $END
#include "builtext.h"
#include "bashgetopt.h"
static SHELL_VAR *declare_find_variable PARAMS((const char *, int, int));
static char *declare_build_newname PARAMS((char *, char *, int, char *, int));
static char *declare_transform_name PARAMS((char *, int, int));
static SHELL_VAR *declare_find_variable (const char *, int, int);
static char *declare_build_newname (char *, char *, int, char *, int);
static char *declare_transform_name (char *, int, int);
static int declare_internal PARAMS((register WORD_LIST *, int));
static int declare_internal (register WORD_LIST *, int);
/* Declare or change variable attributes. */
int
declare_builtin (list)
register WORD_LIST *list;
declare_builtin (WORD_LIST *list)
{
return (declare_internal (list, 0));
}
@@ -120,8 +120,7 @@ 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)
register WORD_LIST *list;
local_builtin (WORD_LIST *list)
{
/* Catch a straight `local --help' before checking function context */
if (list && list->word && STREQ (list->word->word, "--help"))
@@ -146,9 +145,7 @@ local_builtin (list)
#endif
static SHELL_VAR *
declare_find_variable (name, mkglobal, chklocal)
const char *name;
int mkglobal, chklocal;
declare_find_variable (const char *name, int mkglobal, int chklocal)
{
SHELL_VAR *var;
@@ -169,11 +166,7 @@ declare_find_variable (name, mkglobal, chklocal)
NAME[SUBSCRIPT][[+]=VALUE]
from expanding a nameref into NAME */
static char *
declare_build_newname (name, subscript_start, offset, value, aflags)
char *name, *subscript_start;
int offset;
char *value;
int aflags;
declare_build_newname (char *name, char *subscript_start, int offset, char *value, int aflags)
{
size_t namelen, savelen;
char *ret;
@@ -203,9 +196,7 @@ declare_build_newname (name, subscript_start, offset, value, aflags)
}
static char *
declare_transform_name (name, flags_on, flags_off)
char *name;
int flags_on, flags_off;
declare_transform_name (char *name, int flags_on, int flags_off)
{
SHELL_VAR *var, *v;
char *newname;
@@ -227,11 +218,48 @@ declare_transform_name (name, flags_on, flags_off)
return (newname);
}
/* Some option combinations that don't make any sense */
static int
declare_invalid_opts (int flags_on, int flags_off)
{
if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
{
char *optchar;
if (flags_on & att_nameref)
optchar = "-n";
else if (flags_on & att_integer)
optchar = "-i";
else if (flags_on & att_assoc)
optchar = "-A";
else if (flags_on & att_array)
optchar = "-a";
sh_invalidopt (optchar);
return (EXECUTION_FAILURE);
}
else if ((flags_on & att_assoc) && (flags_off & att_assoc))
{
sh_invalidopt ("-A");
return (EX_BADUSAGE);
}
else if ((flags_on & att_array) && (flags_off & att_array))
{
sh_invalidopt ("-a");
return (EX_BADUSAGE);
}
else if ((flags_on & att_assoc) && (flags_on & att_array))
{
sh_invalidopt ("-a");
return (EX_BADUSAGE);
}
return 0;
}
/* The workhorse function. */
static int
declare_internal (list, local_var)
register WORD_LIST *list;
int local_var;
declare_internal (WORD_LIST *list, int local_var)
{
int flags_on, flags_off, *flags;
int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
@@ -255,6 +283,10 @@ declare_internal (list, local_var)
case 'a':
#if defined (ARRAY_VARS)
*flags |= att_array;
#if 0
if (flags == &flags_on)
*flags &= ~att_assoc; /* last one wins */
#endif
break;
#else
builtin_usage ();
@@ -263,6 +295,10 @@ declare_internal (list, local_var)
case 'A':
#if defined (ARRAY_VARS)
*flags |= att_assoc;
#if 0
if (flags == &flags_on)
*flags &= ~att_array; /* last one wins */
#endif
break;
#else
builtin_usage ();
@@ -370,24 +406,11 @@ declare_internal (list, local_var)
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
}
/* Some option combinations that don't make any sense */
if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
{
char *optchar;
if (flags_on & att_nameref)
optchar = "-n";
else if (flags_on & att_integer)
optchar = "-i";
else if (flags_on & att_assoc)
optchar = "-A";
else if (flags_on & att_array)
optchar = "-a";
sh_invalidopt (optchar);
return (EXECUTION_FAILURE);
}
/* check for some invalid option combinations that are usage errors */
opt = declare_invalid_opts (flags_on, flags_off);
if (opt != 0)
return (opt);
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
@@ -404,7 +427,7 @@ declare_internal (list, local_var)
name = savestring (list->word->word);
wflags = list->word->flags;
#if defined (ARRAY_VARS)
assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
assoc_noexpand = array_expand_once && (wflags & W_ASSIGNMENT);
#else
assoc_noexpand = 0;
#endif
@@ -442,9 +465,14 @@ declare_internal (list, local_var)
/* Can't define functions using assignment statements */
if (offset && (flags_on & att_function)) /* declare -f [-rix] foo=bar */
{
builtin_error (_("cannot use `-f' to make functions"));
free (name);
return (EXECUTION_FAILURE);
if (var = find_function (name))
offset = 0;
else
{
builtin_error (_("cannot use `-f' to make functions"));
free (name);
return (EXECUTION_FAILURE);
}
}
/* There should be a way, however, to let people look at a particular
@@ -456,7 +484,7 @@ declare_internal (list, local_var)
/* Should we restrict this when the shell is in posix mode even if
the function was created before the shell entered posix mode?
Previous versions of the shell enforced the restriction. */
if (posixly_correct && legal_identifier (name) == 0)
if (posixly_correct && valid_identifier (name) == 0)
{
sh_invalidid (name);
assign_error++;
@@ -583,7 +611,7 @@ restart_new_var_name:
#endif
/* Ensure the argument is a valid, well-formed shell identifier. */
if (legal_identifier (name) == 0)
if (valid_identifier (name) == 0)
{
sh_invalidid (name);
assign_error++;
@@ -644,6 +672,10 @@ restart_new_var_name:
any_failed++;
NEXT_VARIABLE ();
}
/* See below; ksh93 doesn't allow the nameref attribute to be removed
from a readonly nameref that has a value, even if it doesn't
reference an existing variable, so we don't allow it for
compatibility. */
if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
{
sh_readonly (name);
@@ -683,7 +715,7 @@ restart_new_var_name:
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
/* If the nameref is readonly but doesn't have a value, ksh93
allows the nameref attribute to be removed. If it's readonly
allows the nameref attribute to be removed. If it's readonly
and has a value, even if the value doesn't reference an
existing variable, we disallow the modification */
if (refvar && nameref_cell (refvar) && readonly_p (refvar))
@@ -850,10 +882,26 @@ restart_new_var_name:
else if ((readonly_p (var) || noassign_p (var)) && offset)
{
if (readonly_p (var))
sh_readonly (name);
assign_error++;
{
sh_readonly (name);
assign_error++;
}
/* just ignore attempts to assign to noassign variables; returning
EXECUTION_FAILURE would cause set -e to exit the shell. */
NEXT_VARIABLE ();
}
#if 1
/* TAG:bash-5.3 20240216 */
/* Cannot set or unset invalid attributes on readonly variables */
else if (readonly_p (var) && ((flags_on & invalid_readonly_attrs) || (flags_off & invalid_readonly_attrs)))
{
/* The restrictions on namerefs and readonly variables are handled
above. */
sh_readonly (name_cell (var));
any_failed++;
NEXT_VARIABLE ();
}
#endif
#if defined (ARRAY_VARS)
/* Array variable error checking. */
@@ -884,7 +932,7 @@ restart_new_var_name:
simple_array_assign = 1;
else if ((making_array_special || creating_array || array_exists) && offset)
{
int vlen;
size_t vlen;
vlen = STRLEN (value);
/*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/
@@ -1001,7 +1049,10 @@ restart_new_var_name:
/* If we found this variable in the temporary environment, as with
`var=value declare -x var', make sure it is treated identically
to `var=value export var'. Do the same for `declare -r' and
`readonly'. Preserve the attributes, except for att_tempvar. */
`readonly'. Preserve the attributes, except for att_tempvar.
This doesn't happen in functions, since declare in shell functions
always creates local variables (that inherit their value from the
tempenv variable). We don't check variable_context; maybe we should. */
/* XXX -- should this create a variable in the global scope, or
modify the local variable flags? ksh93 has it modify the
global scope.
@@ -1010,22 +1061,32 @@ restart_new_var_name:
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
{
SHELL_VAR *tv;
char *tvalue;
/* Temporary environment? Or in the local variable context? */
tv = find_tempenv_variable (name_cell (var));
if (tv)
{
tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
tv = bind_variable (name_cell (var), tvalue, 0);
/* We don't bother with modifying the temporary env because
we're already using it. */
tv = bind_variable (name_cell (var), value_cell (var), ASS_NOTEMPENV);
if (tv)
{
#if defined (ARRAY_VARS)
/* copy array value if array variable */
if ((array_p (var) || assoc_p (var)))
arrayvar_copyval (var, tv);
#endif
/* then copy attributes */
tv->attributes |= var->attributes & ~att_tempvar;
if (tv->context > 0)
if (tv->context > 0 && local_p (var) == 0) /* just paranoia here */
VSETATTR (tv, att_propagate);
}
free (tvalue);
}
VSETATTR (var, att_propagate);
/* XXX - don't propagate local variables back to a previous scope,
even in posix mode. */
if (local_p (var) == 0)
VSETATTR (var, att_propagate);
}
/* Turn on nameref attribute we deferred above. */
+4 -4
View File
@@ -1,7 +1,7 @@
This file is echo.def, from which is created echo.c.
It implements the builtin "echo" in Bash.
Copyright (C) 1987-2018 Free Software Foundation, Inc.
Copyright (C) 1987-2018,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -107,10 +107,10 @@ int xpg_echo = 0;
`-n', then don't print a trailing newline. We also support the
echo syntax from Version 9 Unix systems. */
int
echo_builtin (list)
WORD_LIST *list;
echo_builtin (WORD_LIST *list)
{
int display_return, do_v9, i, len;
int display_return, do_v9, i;
size_t len;
char *temp, *s;
do_v9 = xpg_echo;
+66 -56
View File
@@ -1,7 +1,7 @@
This file is enable.def, from which is created enable.c.
It implements the builtin "enable" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -41,6 +41,11 @@ Options controlling dynamic loading:
Without options, each NAME is enabled.
On systems with dynamic loading, the shell variable BASH_LOADABLES_PATH
defines a search path for the directory containing FILENAMEs that do
not contain a slash. It may include "." to force a search of the current
directory.
To use the `test' found in $PATH instead of the shell builtin
version, type `enable -n test'.
@@ -85,13 +90,13 @@ $END
#define SFLAG 0x20
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
static int dyn_load_builtin PARAMS((WORD_LIST *, int, char *));
static int dyn_load_builtin (WORD_LIST *, int, char *);
#endif
#if defined (HAVE_DLCLOSE)
static int dyn_unload_builtin PARAMS((char *));
static void delete_builtin PARAMS((struct builtin *));
static int local_dlclose PARAMS((void *));
static int dyn_unload_builtin (char *);
static void delete_builtin (struct builtin *);
static int local_dlclose (void *);
#endif
#define STRUCT_SUFFIX "_struct"
@@ -99,15 +104,14 @@ static int local_dlclose PARAMS((void *));
#define LOAD_SUFFIX "_builtin_load"
#define UNLOAD_SUFFIX "_builtin_unload"
static void list_some_builtins PARAMS((int));
static int enable_shell_command PARAMS((char *, int));
static void list_some_builtins (int);
static int enable_shell_command (char *, int);
/* Enable/disable shell commands present in LIST. If list is not specified,
then print out a list of shell commands showing which are enabled and
which are disabled. */
int
enable_builtin (list)
WORD_LIST *list;
enable_builtin (WORD_LIST *list)
{
int result, flags;
int opt, filter;
@@ -194,6 +198,8 @@ enable_builtin (list)
result = EXECUTION_FAILURE; /* normalize return value */
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_builtins);
set_itemlist_dirty (&it_enabled);
set_itemlist_dirty (&it_disabled);
#endif
}
#endif
@@ -209,6 +215,8 @@ enable_builtin (list)
}
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_builtins);
set_itemlist_dirty (&it_enabled);
set_itemlist_dirty (&it_disabled);
#endif
}
#endif
@@ -216,32 +224,37 @@ enable_builtin (list)
{
while (list)
{
opt = enable_shell_command (list->word->word, flags & NFLAG);
char *command;
command = list->word->word;
opt = enable_shell_command (command, flags & NFLAG);
next = list->next;
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
/* If we try to enable a non-existent builtin, and we have dynamic
loading, try the equivalent of `enable -f name name'. */
if (opt == EX_NOTFOUND)
if (*command && (flags & NFLAG) == 0 && opt == EX_NOTFOUND)
{
int dflags, r;
dflags = ENABLED|SILENT|((flags & SFLAG) ? SPECIAL : 0);
list->next = 0;
r = dyn_load_builtin (list, dflags, list->word->word);
r = dyn_load_builtin (list, dflags, command);
list->next = next;
if (r == EXECUTION_SUCCESS)
opt = r;
#if defined (PROGRAMMABLE_COMPLETION)
set_itemlist_dirty (&it_builtins);
set_itemlist_dirty (&it_enabled);
set_itemlist_dirty (&it_disabled);
#endif
}
#endif
if (opt == EX_NOTFOUND)
{
sh_notbuiltin (list->word->word);
sh_notbuiltin (command);
result = EXECUTION_FAILURE;
}
else if (opt != EXECUTION_SUCCESS)
@@ -254,10 +267,9 @@ enable_builtin (list)
}
/* List some builtins.
FILTER is a mask with two slots: ENABLED and DISABLED. */
FILTER is a mask with three slots: SPECIAL, ENABLED, and DISABLED. */
static void
list_some_builtins (filter)
int filter;
list_some_builtins (int filter)
{
register int i;
@@ -281,9 +293,7 @@ list_some_builtins (filter)
/* Enable the shell command NAME. If DISABLE_P is non-zero, then
disable NAME instead. */
static int
enable_shell_command (name, disable_p)
char *name;
int disable_p;
enable_shell_command (char *name, int disable_p)
{
struct builtin *b;
@@ -318,15 +328,13 @@ enable_shell_command (name, disable_p)
#endif
static int
dyn_load_builtin (list, flags, filename)
WORD_LIST *list;
int flags;
char *filename;
dyn_load_builtin (WORD_LIST *list, int flags, char *filename)
{
WORD_LIST *l;
void *handle;
int total, size, new, replaced, r;
int total, replaced, r;
size_t size, new;
char *struct_name, *name, *funcname;
sh_load_func_t *loadfunc;
struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
@@ -339,32 +347,33 @@ dyn_load_builtin (list, flags, filename)
#define RTLD_LAZY 1
#endif
handle = 0;
if (absolute_program (filename) == 0)
{
loadables_path = get_string_value ("BASH_LOADABLES_PATH");
if (loadables_path)
{
load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
if (load_path)
{
#if defined (_AIX)
handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL);
# define DLFLAGS (RTLD_NOW|RTLD_GLOBAL)
#else
handle = dlopen (load_path, RTLD_LAZY);
# define DLFLAGS RTLD_LAZY
#endif /* !_AIX */
free (load_path);
}
handle = 0;
if (absolute_program (filename))
handle = dlopen (filename, DLFLAGS);
else if (loadables_path = path_value ("BASH_LOADABLES_PATH", 1))
{
/* If we have a loadables path, don't fall back to the current directory. */
load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
if (load_path)
{
handle = dlopen (load_path, DLFLAGS);
free (load_path);
}
}
else /* no loadables path, look in current directory */
{
char *openname;
/* Fall back to current directory for now */
if (handle == 0)
#if defined (_AIX)
handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
#else
handle = dlopen (filename, RTLD_LAZY);
#endif /* !_AIX */
openname = make_absolute (filename, ".");
handle = dlopen (openname, DLFLAGS);
free (openname);
}
if (handle == 0)
{
@@ -387,9 +396,14 @@ dyn_load_builtin (list, flags, filename)
/* For each new builtin in the shared object, find it and its describing
structure. If this is overwriting an existing builtin, do so, otherwise
save the loaded struct for creating the new list of builtins. */
for (replaced = new = 0; list; list = list->next)
for (replaced = 0, new = 0; list; list = list->next)
{
name = list->word->word;
if (absolute_program (name))
{
builtin_error (_("%s: builtin names may not contain slashes"), name);
continue;
}
size = strlen (name);
struct_name = (char *)xmalloc (size + 8);
@@ -433,6 +447,8 @@ dyn_load_builtin (list, flags, filename)
b->flags &= ~STATIC_BUILTIN;
if (flags & SPECIAL)
b->flags |= SPECIAL_BUILTIN;
if (flags & DISABLED)
b->flags &= ~BUILTIN_ENABLED;
b->handle = handle;
if (old_builtin)
@@ -483,18 +499,13 @@ dyn_load_builtin (list, flags, filename)
#if defined (HAVE_DLCLOSE)
static void
delete_builtin (b)
struct builtin *b;
delete_builtin (struct builtin *b)
{
int ind, size;
struct builtin *new_shell_builtins;
/* XXX - funky pointer arithmetic - XXX */
#ifdef __STDC__
ind = b - shell_builtins;
#else
ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
#endif
size = num_shell_builtins * sizeof (struct builtin);
new_shell_builtins = (struct builtin *)xmalloc (size);
@@ -519,8 +530,7 @@ delete_builtin (b)
/* Tenon's MachTen has a dlclose that doesn't return a value, so we
finesse it with a local wrapper. */
static int
local_dlclose (handle)
void *handle;
local_dlclose (void *handle)
{
#if !defined (__MACHTEN__)
return (dlclose (handle));
@@ -531,14 +541,14 @@ local_dlclose (handle)
}
static int
dyn_unload_builtin (name)
char *name;
dyn_unload_builtin (char *name)
{
struct builtin *b;
void *handle;
char *funcname;
sh_unload_func_t *unloadfunc;
int ref, i, size;
int ref, i;
size_t size;
b = builtin_address_internal (name, 1);
if (b == 0)
+2 -3
View File
@@ -1,7 +1,7 @@
This file is eval.def, from which is created eval.c.
It implements the builtin "eval" in Bash.
Copyright (C) 1987-2016 Free Software Foundation, Inc.
Copyright (C) 1987-2016,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -46,8 +46,7 @@ $END
/* Parse the string that these words make, and execute the command found. */
int
eval_builtin (list)
WORD_LIST *list;
eval_builtin (WORD_LIST *list)
{
if (no_options (list))
return (EX_USAGE);
+36 -31
View File
@@ -1,6 +1,6 @@
/* evalfile.c - read and evaluate commands from a file or file descriptor */
/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
/* Copyright (C) 1996-2017,2022-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -68,14 +68,13 @@ extern int errno;
#define FEVAL_CHECKBINARY 0x040
#define FEVAL_REGFILE 0x080
#define FEVAL_NOPUSHARGS 0x100
#define FEVAL_RETRY 0x200
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
static int
_evalfile (filename, flags)
const char *filename;
int flags;
_evalfile (const char *filename, int flags)
{
volatile int old_interactive;
procenv_t old_return_catch;
@@ -98,17 +97,16 @@ _evalfile (filename, flags)
USE_VAR(pflags);
#if defined (ARRAY_VARS)
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
# if defined (DEBUGGER)
GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
# endif
#endif
fd = open (filename, O_RDONLY);
errno = 0;
do
{
fd = open (filename, O_RDONLY);
i = errno;
if (fd < 0 && i == EINTR)
QUIT;
errno = i;
}
while (fd < 0 && errno == EINTR && (flags & FEVAL_RETRY));
if (fd < 0 || (fstat (fd, &finfo) == -1))
{
@@ -153,7 +151,7 @@ file_error_and_exit:
(*errfunc) (_("%s: file is too large"), filename);
close (fd);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
}
if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
{
@@ -161,6 +159,8 @@ file_error_and_exit:
nr = read (fd, string, file_size);
if (nr >= 0)
string[nr] = '\0';
if (nr != file_size)
nr = -1; /* XXX - didn't get the whole file */
}
else
nr = zmapfd (fd, &string, 0);
@@ -218,6 +218,7 @@ file_error_and_exit:
if (flags & FEVAL_NONINT)
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
unwind_protect_int (retain_fifos);
}
else
{
@@ -232,7 +233,17 @@ file_error_and_exit:
return_catch_flag++;
sourcelevel++;
retain_fifos++; /* XXX */
#if defined (ARRAY_VARS)
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
# if defined (DEBUGGER)
GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
# endif
array_push (bash_source_a, (char *)filename);
t = itos (executing_line_number ());
array_push (bash_lineno_a, t);
@@ -247,7 +258,7 @@ file_error_and_exit:
fa->funcname_a = funcname_a;
fa->funcname_v = funcname_v;
if (flags & FEVAL_UNWINDPROT)
add_unwind_protect (restore_funcarray_state, fa);
add_unwind_protect (uw_restore_funcarray_state, fa);
# if defined (DEBUGGER)
/* Have to figure out a better way to do this when `source' is supplied
@@ -260,7 +271,7 @@ file_error_and_exit:
tt[0] = '1'; tt[1] = '\0';
array_push (bash_argc_a, tt);
if (flags & FEVAL_UNWINDPROT)
add_unwind_protect (pop_args, 0);
add_unwind_protect (uw_pop_args, 0);
}
# endif
#endif
@@ -304,6 +315,7 @@ file_error_and_exit:
#endif
return_catch_flag--;
sourcelevel--;
retain_fifos--;
COPY_PROCENV (old_return_catch, return_catch);
}
@@ -316,15 +328,13 @@ file_error_and_exit:
}
int
maybe_execute_file (fname, force_noninteractive)
const char *fname;
int force_noninteractive;
maybe_execute_file (const char *fname, int force_noninteractive)
{
char *filename;
int result, flags;
filename = bash_tilde_expand (fname, 0);
flags = FEVAL_ENOENTOK;
flags = FEVAL_ENOENTOK|FEVAL_RETRY;
if (force_noninteractive)
flags |= FEVAL_NONINT;
result = _evalfile (filename, flags);
@@ -333,15 +343,13 @@ maybe_execute_file (fname, force_noninteractive)
}
int
force_execute_file (fname, force_noninteractive)
const char *fname;
int force_noninteractive;
force_execute_file (const char *fname, int force_noninteractive)
{
char *filename;
int result, flags;
filename = bash_tilde_expand (fname, 0);
flags = 0;
flags = FEVAL_RETRY;
if (force_noninteractive)
flags |= FEVAL_NONINT;
result = _evalfile (filename, flags);
@@ -351,8 +359,7 @@ force_execute_file (fname, force_noninteractive)
#if defined (HISTORY)
int
fc_execute_file (filename)
const char *filename;
fc_execute_file (const char *filename)
{
int flags;
@@ -365,9 +372,7 @@ fc_execute_file (filename)
#endif /* HISTORY */
int
source_file (filename, sflags)
const char *filename;
int sflags;
source_file (const char *filename, int sflags)
{
int flags, rval;
+67 -58
View File
@@ -1,6 +1,6 @@
/* evalstring.c - evaluate a string as one or more shell commands. */
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -63,31 +63,47 @@ extern int errno;
int parse_and_execute_level = 0;
static int cat_file PARAMS((REDIRECT *));
static int cat_file (REDIRECT *);
#define PE_TAG "parse_and_execute top"
#define PS_TAG "parse_string top"
#if defined (HISTORY)
static void
set_history_remembering ()
uw_set_history_remembering (void *ignore)
{
remember_on_history = enable_history_list;
}
#endif
static void
restore_lastcom (x)
char *x;
uw_restore_lastcom (void *x)
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = x;
}
static void
uw_set_current_prompt_level (void *x)
{
set_current_prompt_level ((intptr_t) x);
}
static void
uw_pop_stream (void *x)
{
pop_stream ();
}
static void
uw_parser_restore_alias (void *x)
{
parser_restore_alias ();
}
int
should_optimize_fork (command, subshell)
COMMAND *command;
int subshell;
should_optimize_fork (COMMAND *command, int subshell)
{
return (running_trap == 0 &&
command->type == cm_simple &&
@@ -102,9 +118,10 @@ should_optimize_fork (command, subshell)
/* This has extra tests to account for STARTUP_STATE == 2, which is for
-c command but has been extended to command and process substitution
(basically any time you call parse_and_execute in a subshell). */
/* ssh_reading_startup_files will never be non-zero unless someone goes
and uncomments SSH_SOURCE_BASHRC in config-top.h */
int
should_suppress_fork (command)
COMMAND *command;
should_suppress_fork (COMMAND *command)
{
int subshell;
@@ -112,12 +129,13 @@ should_suppress_fork (command)
return (startup_state == 2 && parse_and_execute_level == 1 &&
*bash_input.location.string == '\0' &&
parser_expanding_alias () == 0 &&
job_control_active_p () == 0 &&
ssh_reading_startup_files == 0 &&
should_optimize_fork (command, subshell));
}
int
can_optimize_connection (command)
COMMAND *command;
can_optimize_connection (COMMAND *command)
{
return (*bash_input.location.string == '\0' &&
parser_expanding_alias () == 0 &&
@@ -126,8 +144,7 @@ can_optimize_connection (command)
}
void
optimize_connection_fork (command)
COMMAND *command;
optimize_connection_fork (COMMAND *command)
{
if (command->type == cm_connection &&
(command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
@@ -141,8 +158,7 @@ optimize_connection_fork (command)
}
void
optimize_subshell_command (command)
COMMAND *command;
optimize_subshell_command (COMMAND *command)
{
if (should_optimize_fork (command, 0))
{
@@ -160,8 +176,7 @@ optimize_subshell_command (command)
}
void
optimize_shell_function (command)
COMMAND *command;
optimize_shell_function (COMMAND *command)
{
COMMAND *fc;
@@ -180,8 +195,7 @@ optimize_shell_function (command)
}
int
can_optimize_cat_file (command)
COMMAND *command;
can_optimize_cat_file (COMMAND *command)
{
return (command->type == cm_simple && !command->redirects &&
(command->flags & CMD_TIME_PIPELINE) == 0 &&
@@ -194,8 +208,7 @@ can_optimize_cat_file (command)
/* How to force parse_and_execute () to clean up after itself. */
void
parse_and_execute_cleanup (old_running_trap)
int old_running_trap;
parse_and_execute_cleanup (int old_running_trap)
{
if (running_trap > 0)
{
@@ -215,10 +228,7 @@ parse_and_execute_cleanup (old_running_trap)
}
static void
parse_prologue (string, flags, tag)
char *string;
int flags;
char *tag;
parse_prologue (char *string, int flags, char *tag)
{
char *orig_string, *lastcom;
int x;
@@ -232,14 +242,15 @@ parse_prologue (string, flags, tag)
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 (interrupt_execution);
unwind_protect_int (comsub_ignore_return);
unwind_protect_int (builtin_ignoring_errexit);
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
unwind_protect_int (interactive);
#if defined (HISTORY)
if (parse_and_execute_level == 0)
add_unwind_protect (set_history_remembering, (char *)NULL);
add_unwind_protect (uw_set_history_remembering, (char *)NULL);
else
unwind_protect_int (remember_on_history); /* can be used in scripts */
# if defined (BANG_HISTORY)
@@ -250,18 +261,18 @@ parse_prologue (string, flags, tag)
if (interactive_shell)
{
x = get_current_prompt_level ();
add_unwind_protect (set_current_prompt_level, x);
add_unwind_protect (uw_set_current_prompt_level, (void *) (intptr_t) x);
}
if (the_printed_command_except_trap)
{
lastcom = savestring (the_printed_command_except_trap);
add_unwind_protect (restore_lastcom, lastcom);
add_unwind_protect (uw_restore_lastcom, lastcom);
}
add_unwind_protect (pop_stream, (char *)NULL);
add_unwind_protect (uw_pop_stream, (char *)NULL);
if (parser_expanding_alias ())
add_unwind_protect (parser_restore_alias, (char *)NULL);
add_unwind_protect (uw_parser_restore_alias, (char *)NULL);
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
add_unwind_protect (xfree, orig_string);
@@ -294,12 +305,9 @@ parse_prologue (string, flags, tag)
*/
int
parse_and_execute (string, from_file, flags)
char *string;
const char *from_file;
int flags;
parse_and_execute (char *string, const char *from_file, int flags)
{
int code, lreset;
int code, lreset, ignore_return;
volatile int should_jump_to_top_level, last_result;
COMMAND *volatile command;
volatile sigset_t pe_sigmask;
@@ -309,6 +317,8 @@ parse_and_execute (string, from_file, flags)
parse_and_execute_level++;
lreset = flags & SEVAL_RESETLINE;
ignore_return = (this_shell_builtin == eval_builtin || this_shell_builtin == source_builtin) &&
builtin_ignoring_errexit;
#if defined (HAVE_POSIX_SIGNALS)
/* If we longjmp and are going to go on, use this to restore signal mask */
@@ -408,6 +418,7 @@ parse_and_execute (string, from_file, flags)
run_unwind_frame ("pe_dispose");
last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
set_pipestatus_from_exit (last_command_exit_value);
if (subshell_environment)
{
should_jump_to_top_level = 1;
@@ -461,6 +472,8 @@ parse_and_execute (string, from_file, flags)
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
set_pipestatus_from_exit (last_command_exit_value);
dispose_command (command);
global_command = (COMMAND *)NULL;
reset_parser ();
break;
}
@@ -468,14 +481,17 @@ parse_and_execute (string, from_file, flags)
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
add_unwind_protect (dispose_command, command); /* XXX */
add_unwind_protect (uw_dispose_fd_bitmap, bitmap);
add_unwind_protect (uw_dispose_command, command); /* XXX */
global_command = (COMMAND *)NULL;
if ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return)
command->flags |= CMD_IGNORE_RETURN;
if (ignore_return)
command->flags |= CMD_IGNORE_RETURN;
#if defined (ONESHOT)
/*
* IF
@@ -522,7 +538,7 @@ parse_and_execute (string, from_file, flags)
the global value of the flag (expaliases_flag) changes). */
local_expalias = expand_aliases;
local_alflag = expaliases_flag;
if (subshell_environment & SUBSHELL_COMSUB)
if ((subshell_environment & SUBSHELL_COMSUB) || executing_funsub)
expand_aliases = expaliases_flag;
/* See if this is a candidate for $( <file ). */
@@ -543,7 +559,7 @@ parse_and_execute (string, from_file, flags)
discard_unwind_frame ("pe_dispose");
/* If the global value didn't change, we restore what we had. */
if ((subshell_environment & SUBSHELL_COMSUB) && local_alflag == expaliases_flag)
if (((subshell_environment & SUBSHELL_COMSUB) || executing_funsub) && local_alflag == expaliases_flag)
expand_aliases = local_expalias;
if (flags & SEVAL_ONECMD)
@@ -599,12 +615,7 @@ parse_and_execute (string, from_file, flags)
command substitutions during parsing to obey Posix rules about finding
the end of the command and balancing parens. */
int
parse_string (string, from_file, flags, cmdp, endp)
char *string;
const char *from_file;
int flags;
COMMAND **cmdp;
char **endp;
parse_string (char *string, const char *from_file, int flags, COMMAND **cmdp, char **endp)
{
int code, nc;
volatile int should_jump_to_top_level;
@@ -612,6 +623,7 @@ parse_string (string, from_file, flags, cmdp, endp)
char *ostring;
volatile sigset_t ps_sigmask;
/* unwind-protects common to this and parse_and_execute */
parse_prologue (string, flags, PS_TAG);
#if defined (HAVE_POSIX_SIGNALS)
@@ -727,12 +739,10 @@ out:
}
int
open_redir_file (r, fnp)
REDIRECT *r;
char **fnp;
open_redir_file (REDIRECT *r, char **fnp)
{
char *fn;
int fd, rval;
int fd;
if (r->instruction != r_input_direction)
return -1;
@@ -753,7 +763,7 @@ open_redir_file (r, fnp)
fd = open(fn, O_RDONLY);
if (fd < 0)
{
file_error (fn);
internal_error ("%s: %s", fn, strerror (errno));
free (fn);
if (fnp)
*fnp = 0;
@@ -762,6 +772,9 @@ open_redir_file (r, fnp)
if (fnp)
*fnp = fn;
else
free (fn);
return fd;
}
@@ -769,8 +782,7 @@ open_redir_file (r, fnp)
returning errors as appropriate, then just cats the file to the standard
output. */
static int
cat_file (r)
REDIRECT *r;
cat_file (REDIRECT *r)
{
char *fn;
int fd, rval;
@@ -788,10 +800,7 @@ cat_file (r)
}
int
evalstring (string, from_file, flags)
char *string;
const char *from_file;
int flags;
evalstring (char *string, const char *from_file, int flags)
{
volatile int r, rflag, rcatch;
volatile int was_trap;
+7 -8
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2021,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -85,8 +85,7 @@ int no_exit_on_failed_exec;
/* If the user wants this to look like a login shell, then
prepend a `-' onto NAME and return the new name. */
static char *
mkdashname (name)
char *name;
mkdashname (char *name)
{
char *ret;
@@ -97,15 +96,15 @@ mkdashname (name)
}
int
exec_builtin (list)
WORD_LIST *list;
exec_builtin (WORD_LIST *list)
{
int exit_value = EXECUTION_FAILURE;
int exit_value;
int cleanenv, login, opt, orig_job_control;
char *argv0, *command, **args, **env, *newname, *com2;
cleanenv = login = orig_job_control = 0;
exec_argv0 = argv0 = (char *)NULL;
exit_value = EXECUTION_FAILURE;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "cla:")) != -1)
@@ -225,12 +224,11 @@ exec_builtin (list)
default_tty_job_signals (); /* undo initialize_job_signals */
#endif /* JOB_CONTROL */
#if defined (BUFFERED_INPUT)
if (default_buffered_input >= 0)
sync_buffered_stream (default_buffered_input);
#endif
exit_value = shell_execve (command, args, env);
opt = errno;
/* We have to set this to NULL because shell_execve has called realloc()
to stuff more items at the front of the array, which may have caused
@@ -243,6 +241,7 @@ exec_builtin (list)
goto failed_exec;
else if (executable_file (command) == 0)
{
errno = opt;
builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
}
+8 -11
View File
@@ -1,7 +1,7 @@
This file is exit.def, from which is created exit.c.
It implements the builtins "exit", and "logout" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -48,14 +48,11 @@ $END
#include "common.h"
#include "builtext.h" /* for jobs_builtin */
extern int check_jobs_at_exit;
static int exit_or_logout PARAMS((WORD_LIST *));
static int exit_or_logout (WORD_LIST *);
static int sourced_logout;
int
exit_builtin (list)
WORD_LIST *list;
exit_builtin (WORD_LIST *list)
{
CHECK_HELPOPT (list);
@@ -79,8 +76,7 @@ $END
/* How to logout. */
int
logout_builtin (list)
WORD_LIST *list;
logout_builtin (WORD_LIST *list)
{
CHECK_HELPOPT (list);
@@ -94,8 +90,7 @@ logout_builtin (list)
}
static int
exit_or_logout (list)
WORD_LIST *list;
exit_or_logout (WORD_LIST *list)
{
int exit_value;
@@ -145,6 +140,8 @@ exit_or_logout (list)
(list == 0), use the exit status we saved before running the trap
commands (trap_saved_exit_value). */
exit_value = (running_trap == 1 && list == 0) ? trap_saved_exit_value : get_exitstat (list);
if (exit_value > EX_SHERRBASE) /* some kind of error */
return (exit_value);
bash_logout ();
@@ -156,7 +153,7 @@ exit_or_logout (list)
}
void
bash_logout ()
bash_logout (void)
{
/* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
if (login_shell && sourced_logout++ == 0 && subshell_environment == 0)
+58 -39
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -45,6 +45,8 @@ A useful alias to use with this is r='fc -s', so that typing `r cc'
runs the last command beginning with `cc' and typing `r' re-executes
the last command.
The history builtin also operates on the history list.
Exit Status:
Returns success or status of executed command; non-zero if an error occurs.
$END
@@ -94,9 +96,11 @@ extern int errno;
#define HN_LISTING 0x01
#define HN_FIRST 0x02
extern int unlink PARAMS((const char *));
#ifndef HAVE_UNISTD_H
extern int unlink (const char *);
#endif
extern FILE *sh_mktmpfp PARAMS((char *, int, char **));
extern FILE *sh_mktmpfp (char *, int, char **);
extern int suppress_debug_trap_verbose;
@@ -154,22 +158,28 @@ typedef struct repl {
} \
} while (0)
static char *fc_dosubs PARAMS((char *, REPL *));
static char *fc_gethist PARAMS((char *, HIST_ENTRY **, int));
static int fc_gethnum PARAMS((char *, HIST_ENTRY **, int));
static int fc_number PARAMS((WORD_LIST *));
static void fc_replhist PARAMS((char *));
static char *fc_dosubs (char *, REPL *);
static char *fc_gethist (char *, HIST_ENTRY **, int);
static int fc_gethnum (char *, HIST_ENTRY **, int);
static int fc_number (WORD_LIST *);
static void fc_replhist (char *);
#ifdef INCLUDE_UNUSED
static char *fc_readline PARAMS((FILE *));
static void fc_addhist PARAMS((char *));
static char *fc_readline (FILE *);
static void fc_addhist (char *);
#endif
static void
set_verbose_flag ()
uw_set_verbose_flag (void *ignore)
{
echo_input_at_read = verbose_flag;
}
static void
uw_unlink (void *fn)
{
unlink ((const char *)fn);
}
/* String to execute on a file that we want to edit. */
#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
#if defined (STRICT_POSIX)
@@ -179,8 +189,7 @@ set_verbose_flag ()
#endif
int
fc_builtin (list)
WORD_LIST *list;
fc_builtin (WORD_LIST *list)
{
register int i;
register char *sep;
@@ -279,6 +288,15 @@ fc_builtin (list)
return (EXECUTION_FAILURE);
}
if (posixly_correct && list && list->next)
{
builtin_error (_("too many arguments"));
if (rlist)
FREE_RLIST ();
return (EXECUTION_FAILURE);
}
if (rlist)
{
newcom = fc_dosubs (command, rlist);
@@ -515,8 +533,8 @@ fc_builtin (list)
will be echoed as they are read by the parser. */
begin_unwind_frame ("fc builtin");
add_unwind_protect (xfree, fn);
add_unwind_protect (unlink, fn);
add_unwind_protect (set_verbose_flag, (char *)NULL);
add_unwind_protect (uw_unlink, fn);
add_unwind_protect (uw_set_verbose_flag, (char *)NULL);
unwind_protect_int (suppress_debug_trap_verbose);
echo_input_at_read = 1;
suppress_debug_trap_verbose = 1;
@@ -529,8 +547,7 @@ fc_builtin (list)
/* Return 1 if LIST->word->word is a legal number for fc's use. */
static int
fc_number (list)
WORD_LIST *list;
fc_number (WORD_LIST *list)
{
char *s;
@@ -539,7 +556,7 @@ fc_number (list)
s = list->word->word;
if (*s == '-')
s++;
return (legal_number (s, (intmax_t *)NULL));
return (valid_number (s, (intmax_t *)NULL));
}
/* Return an absolute index into HLIST which corresponds to COMMAND. If
@@ -549,14 +566,12 @@ fc_number (list)
are executing them. If MODE includes HN_FIRST we are looking for the
first history number specification. */
static int
fc_gethnum (command, hlist, mode)
char *command;
HIST_ENTRY **hlist;
int mode;
fc_gethnum (char *command, HIST_ENTRY **hlist, int mode)
{
int sign, n, clen, rh;
register int i, j, last_hist, real_last, listing;
register char *s;
int sign, n, rh;
size_t clen;
int i, j, last_hist, real_last, listing;
char *s;
listing = mode & HN_LISTING;
sign = 1;
@@ -654,10 +669,7 @@ fc_gethnum (command, hlist, mode)
COMMAND in HLIST, and return a malloc()'ed copy of it.
MODE is 1 if we are listing commands, 0 if we are executing them. */
static char *
fc_gethist (command, hlist, mode)
char *command;
HIST_ENTRY **hlist;
int mode;
fc_gethist (char *command, HIST_ENTRY **hlist, int mode)
{
int i;
@@ -677,10 +689,12 @@ fc_gethist (command, hlist, mode)
one at a time. This can read unlimited length lines. The
caller should free the storage. */
static char *
fc_readline (stream)
FILE *stream;
fc_readline (FILE *stream)
{
register int c;
#ifdef __MSYS__
register int d;
#endif
int line_len = 0, lindex = 0;
char *line = (char *)NULL;
@@ -689,6 +703,11 @@ fc_readline (stream)
if ((lindex + 2) >= line_len)
line = (char *)xrealloc (line, (line_len += 128));
#ifdef __MSYS__
if (d == '\r')
lindex--;
#endif
if (c == '\n')
{
line[lindex++] = '\n';
@@ -697,6 +716,10 @@ fc_readline (stream)
}
else
line[lindex++] = c;
#ifdef __MSYS__
d = c;
#endif
}
if (!lindex)
@@ -721,9 +744,7 @@ fc_readline (stream)
Return a pointer to a malloc'ed string which contains the substituted
command. */
static char *
fc_dosubs (command, subs)
char *command;
REPL *subs;
fc_dosubs (char *command, REPL *subs)
{
register char *new, *t;
register REPL *r;
@@ -742,10 +763,9 @@ fc_dosubs (command, subs)
become the history entry, and that `fc' should never appear in the
history list. This way you can do `r' to your heart's content. */
static void
fc_replhist (command)
char *command;
fc_replhist (char *command)
{
int n;
size_t n;
if (command == 0 || *command == '\0')
return;
@@ -764,8 +784,7 @@ fc_replhist (command)
#ifdef INCLUDE_UNUSED
/* Add LINE to the history, after removing a single trailing newline. */
static void
fc_addhist (line)
char *line;
fc_addhist (char *line)
{
register int n;
+5 -9
View File
@@ -1,7 +1,7 @@
This file is fg_bg.def, from which is created fg_bg.c.
It implements the builtins "bg" and "fg" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -52,12 +52,11 @@ $END
#include "bashgetopt.h"
#if defined (JOB_CONTROL)
static int fg_bg PARAMS((WORD_LIST *, int));
static int fg_bg (WORD_LIST *, int);
/* How to bring a job into the foreground. */
int
fg_builtin (list)
WORD_LIST *list;
fg_builtin (WORD_LIST *list)
{
int fg_bit;
register WORD_LIST *t;
@@ -101,8 +100,7 @@ $END
#if defined (JOB_CONTROL)
/* How to put a job into the background. */
int
bg_builtin (list)
WORD_LIST *list;
bg_builtin (WORD_LIST *list)
{
int r;
@@ -135,9 +133,7 @@ bg_builtin (list)
/* How to put a job into the foreground/background. */
static int
fg_bg (list, foreground)
WORD_LIST *list;
int foreground;
fg_bg (WORD_LIST *list, int foreground)
{
sigset_t set, oset;
int job, status, old_async_pid;
+5 -15
View File
@@ -1,6 +1,6 @@
/* gen-helpfiles - create files containing builtin help text */
/* Copyright (C) 2012-2021 Free Software Foundation, Inc.
/* Copyright (C) 2012-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -72,10 +72,6 @@
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. */
@@ -99,15 +95,13 @@ char *helpfile_directory;
/* Forward declarations. */
int write_helpfiles PARAMS((struct builtin *));
int write_helpfiles (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 necessary. */
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int arg_index = 1;
@@ -138,10 +132,7 @@ main (argc, argv)
internationalization (gettext) and the single-string vs. multiple-strings
issues. */
void
write_documentation (stream, documentation, indentation)
FILE *stream;
char *documentation;
int indentation;
write_documentation (FILE *stream, char *documentation, int indentation)
{
if (stream == 0)
return;
@@ -151,8 +142,7 @@ write_documentation (stream, documentation, indentation)
}
int
write_helpfiles (builtins)
struct builtin *builtins;
write_helpfiles (struct builtin *builtins)
{
char *helpfile, *bname, *fname;
FILE *helpfp;
+9 -18
View File
@@ -1,6 +1,6 @@
/* getopt.c - getopt for Bash. Used by the getopt builtin. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
/* Copyright (C) 1993-2009,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -111,10 +111,7 @@ int sh_badopt = 0;
#define NEEDARG(x) fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], x)
int
sh_getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
sh_getopt (int argc, char *const *argv, const char *optstring)
{
char c, *temp;
@@ -216,10 +213,9 @@ sh_getopt (argc, argv, optstring)
}
void
sh_getopt_restore_state (argv)
char **argv;
sh_getopt_restore_state (char **argv)
{
if (nextchar)
if (nextchar && argv && argv[sh_curopt])
nextchar = argv[sh_curopt] + sh_charindex;
}
@@ -233,14 +229,13 @@ sh_getopt_alloc_istate ()
}
void
sh_getopt_dispose_istate (gs)
sh_getopt_state_t *gs;
sh_getopt_dispose_istate (sh_getopt_state_t *gs)
{
free (gs);
}
sh_getopt_state_t *
sh_getopt_save_istate ()
sh_getopt_save_istate (void)
{
sh_getopt_state_t *ret;
@@ -257,8 +252,7 @@ sh_getopt_save_istate ()
}
void
sh_getopt_restore_istate (state)
sh_getopt_state_t *state;
sh_getopt_restore_istate (sh_getopt_state_t *state)
{
sh_optarg = state->gs_optarg;
sh_optind = state->gs_optind;
@@ -271,8 +265,7 @@ sh_getopt_restore_istate (state)
#if 0
void
sh_getopt_debug_restore_state (argv)
char **argv;
sh_getopt_debug_restore_state (char **argv)
{
if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
{
@@ -288,9 +281,7 @@ sh_getopt_debug_restore_state (argv)
the above definition of `sh_getopt'. */
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int c;
int digit_sh_optind = 0;
+7 -7
View File
@@ -1,6 +1,6 @@
/* getopt.h - declarations for getopt. */
/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
/* Copyright (C) 1989-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -59,7 +59,7 @@ extern int sh_optopt;
/* Set to 1 when an unrecognized option is encountered. */
extern int sh_badopt;
extern int sh_getopt PARAMS((int, char *const *, const char *));
extern int sh_getopt (int, char *const *, const char *);
typedef struct sh_getopt_state
{
@@ -71,12 +71,12 @@ typedef struct sh_getopt_state
int gs_flags;
} sh_getopt_state_t;
extern void sh_getopt_restore_state PARAMS((char **));
extern void sh_getopt_restore_state (char **);
extern sh_getopt_state_t *sh_getopt_alloc_istate PARAMS((void));
extern void sh_getopt_dispose_istate PARAMS((sh_getopt_state_t *));
extern sh_getopt_state_t *sh_getopt_alloc_istate (void);
extern void sh_getopt_dispose_istate (sh_getopt_state_t *);
extern sh_getopt_state_t *sh_getopt_save_istate PARAMS((void));
extern void sh_getopt_restore_istate PARAMS((sh_getopt_state_t *));
extern sh_getopt_state_t *sh_getopt_save_istate (void);
extern void sh_getopt_restore_istate (sh_getopt_state_t *);
#endif /* _SH_GETOPT_H */
+14 -27
View File
@@ -1,7 +1,7 @@
This file is getopts.def, from which is created getopts.c.
It implements the builtin "getopts" in Bash.
Copyright (C) 1987-2019 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -86,23 +86,21 @@ $END
#define G_INVALID_OPT -2
#define G_ARG_MISSING -3
static int getopts_unbind_variable PARAMS((char *));
static int getopts_bind_variable PARAMS((char *, char *));
static int dogetopts PARAMS((int, char **));
static int getopts_unbind_variable (char *);
static int getopts_bind_variable (char *, char *);
static int dogetopts (int, char **);
/* getopts_reset is magic code for when OPTIND is reset. N is the
value that has just been assigned to OPTIND. */
void
getopts_reset (newind)
int newind;
getopts_reset (int newind)
{
sh_optind = newind;
sh_badopt = 0;
}
static int
getopts_unbind_variable (name)
char *name;
getopts_unbind_variable (char *name)
{
#if 0
return (unbind_variable (name));
@@ -112,12 +110,11 @@ getopts_unbind_variable (name)
}
static int
getopts_bind_variable (name, value)
char *name, *value;
getopts_bind_variable (char *name, char *value)
{
SHELL_VAR *v;
if (legal_identifier (name))
if (valid_identifier (name))
{
v = bind_variable (name, value, 0);
if (v && (readonly_p (v) || noassign_p (v)))
@@ -159,9 +156,7 @@ getopts_bind_variable (name, value)
*/
static int
dogetopts (argc, argv)
int argc;
char **argv;
dogetopts (int argc, char **argv)
{
int ret, special_error, old_opterr, i, n;
char strval[2], numval[16];
@@ -312,29 +307,21 @@ dogetopts (argc, argv)
/* The getopts builtin. Build an argv, and call dogetopts with it. */
int
getopts_builtin (list)
WORD_LIST *list;
getopts_builtin (WORD_LIST *list)
{
char **av;
int ac, ret;
if (no_options (list))
return (EX_USAGE);
list = loptend; /* skip over possible `--' */
if (list == 0)
{
builtin_usage ();
return EX_USAGE;
}
reset_internal_getopt ();
if ((ret = internal_getopt (list, "")) != -1)
{
if (ret == GETOPT_HELP)
builtin_help ();
else
builtin_usage ();
return (EX_USAGE);
}
list = loptend;
av = make_builtin_argv (list, &ac);
ret = dogetopts (ac, av);
free ((char *)av);
+23 -25
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -68,20 +68,17 @@ $END
#include "common.h"
#include "bashgetopt.h"
extern int dot_found_in_search;
static int add_hashed_command PARAMS((char *, int));
static int print_hash_info PARAMS((BUCKET_CONTENTS *));
static int print_portable_hash_info PARAMS((BUCKET_CONTENTS *));
static int print_hashed_commands PARAMS((int));
static int list_hashed_filename_targets PARAMS((WORD_LIST *, int));
static int add_hashed_command (char *, int);
static int print_hash_info (BUCKET_CONTENTS *);
static int print_portable_hash_info (BUCKET_CONTENTS *);
static int print_hashed_commands (int);
static int list_hashed_filename_targets (WORD_LIST *, int);
/* Print statistics on the current state of hashed commands. If LIST is
not empty, then rehash (or hash in the first place) the specified
commands. */
int
hash_builtin (list)
WORD_LIST *list;
hash_builtin (WORD_LIST *list)
{
int expunge_hash_table, list_targets, list_portably, delete, opt;
char *w, *pathname;
@@ -126,11 +123,19 @@ hash_builtin (list)
if (list == 0 && (delete || list_targets))
{
sh_needarg (delete ? "-d" : "-t");
return (EXECUTION_FAILURE);
return (sh_chkwrite (EXECUTION_FAILURE));
}
/* It's an error to specify a pathname to hash to, but no name to hash. */
if (pathname && list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
/* We want hash -r to be silent, but hash -- to print hashing info, so
we test expunge_hash_table. */
if (list == 0 && expunge_hash_table == 0)
{
opt = print_hashed_commands (list_portably);
@@ -147,7 +152,7 @@ hash_builtin (list)
/* If someone runs `hash -r -t xyz' he will be disappointed. */
if (list_targets)
return (list_hashed_filename_targets (list, list_portably));
#if defined (RESTRICTED_SHELL)
if (restricted && pathname)
{
@@ -206,9 +211,7 @@ hash_builtin (list)
}
static int
add_hashed_command (w, quiet)
char *w;
int quiet;
add_hashed_command (char *w, int quiet)
{
int rv;
char *full_path;
@@ -233,16 +236,14 @@ add_hashed_command (w, quiet)
/* Print information about current hashed info. */
static int
print_hash_info (item)
BUCKET_CONTENTS *item;
print_hash_info (BUCKET_CONTENTS *item)
{
printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
return 0;
}
static int
print_portable_hash_info (item)
BUCKET_CONTENTS *item;
print_portable_hash_info (BUCKET_CONTENTS *item)
{
char *fp, *fn;
@@ -257,8 +258,7 @@ print_portable_hash_info (item)
}
static int
print_hashed_commands (fmt)
int fmt;
print_hashed_commands (int fmt)
{
if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
return (0);
@@ -270,9 +270,7 @@ print_hashed_commands (fmt)
}
static int
list_hashed_filename_targets (list, fmt)
WORD_LIST *list;
int fmt;
list_hashed_filename_targets (WORD_LIST *list, int fmt)
{
int all_found, multiple;
char *target;
@@ -301,5 +299,5 @@ list_hashed_filename_targets (list, fmt)
free (target);
}
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
return (sh_chkwrite (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE));
}
+26 -47
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -58,7 +58,7 @@ $END
#include <errno.h>
#include <filecntl.h>
#include <stddef.h>
#include "../bashansi.h"
#include "../bashintl.h"
@@ -79,22 +79,22 @@ extern int errno;
extern const char * const bash_copyright;
extern const char * const bash_license;
static void show_builtin_command_help PARAMS((void));
static int open_helpfile PARAMS((char *));
static void show_desc PARAMS((char *, int));
static void show_manpage PARAMS((char *, int));
static void show_longdoc PARAMS((int));
static void show_builtin_command_help (void);
static int open_helpfile (const char *);
static void show_desc (char *, int);
static void show_manpage (char *, int);
static void show_longdoc (int);
/* Print out a list of the known functions in the shell, and what they do.
If LIST is supplied, print out the list which matches for each pattern
specified. */
int
help_builtin (list)
WORD_LIST *list;
help_builtin (WORD_LIST *list)
{
register int i;
char *pattern, *name;
int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
int match_found, sflag, dflag, mflag, m, pass, this_found;
size_t plen;
dflag = sflag = mflag = 0;
reset_internal_getopt ();
@@ -190,30 +190,21 @@ help_builtin (list)
}
void
builtin_help ()
builtin_help (void)
{
int ind;
ptrdiff_t d;
current_builtin = builtin_address_internal (this_command_name, 0);
if (current_builtin == 0)
return;
d = current_builtin - shell_builtins;
#if defined (__STDC__)
ind = (int)d;
#else
ind = (int)d / sizeof (struct builtin);
#endif
ind = current_builtin - shell_builtins;
printf ("%s: %s\n", this_command_name, _(shell_builtins[ind].short_doc));
show_longdoc (ind);
}
static int
open_helpfile (name)
char *name;
open_helpfile (const char *name)
{
int fd;
@@ -230,8 +221,7 @@ open_helpfile (name)
used, the long_doc array contains one string -- the full pathname of the
help file for this builtin. */
static void
show_longdoc (i)
int i;
show_longdoc (int i)
{
register int j;
char * const *doc;
@@ -253,15 +243,13 @@ show_longdoc (i)
}
static void
show_desc (name, i)
char *name;
int i;
show_desc (char *name, int i)
{
register int j, r;
char **doc, *line;
char * const *doc, *line;
int fd, usefile;
doc = (char **)shell_builtins[i].long_doc;
doc = shell_builtins[i].long_doc;
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
if (usefile)
@@ -292,15 +280,14 @@ show_desc (name, i)
/* Print builtin help in pseudo-manpage format. */
static void
show_manpage (name, i)
char *name;
int i;
show_manpage (char *name, int i)
{
register int j;
char **doc, *line;
char * const *doc;
char *line;
int fd, usefile;
doc = (char **)shell_builtins[i].long_doc;
doc = shell_builtins[i].long_doc;
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
if (usefile)
@@ -366,14 +353,10 @@ show_manpage (name, i)
}
static void
dispcolumn (i, buf, bufsize, width, height)
int i;
char *buf;
size_t bufsize;
int width, height;
dispcolumn (int i, char *buf, size_t bufsize, int width, int height)
{
int j;
int dispcols;
size_t dispcols;
char *helpdoc;
/* first column */
@@ -408,11 +391,7 @@ dispcolumn (i, buf, bufsize, width, height)
#if defined (HANDLE_MULTIBYTE)
static void
wdispcolumn (i, buf, bufsize, width, height)
int i;
char *buf;
size_t bufsize;
int width, height;
wdispcolumn (int i, char *buf, size_t bufsize, int width, int height)
{
int j;
int dispcols, dispchars;
@@ -513,9 +492,9 @@ wdispcolumn (i, buf, bufsize, width, height)
#endif /* HANDLE_MULTIBYTE */
static void
show_builtin_command_help ()
show_builtin_command_help (void)
{
int i, j;
int i;
int height, width;
char *t, blurb[128];
+29 -21
View File
@@ -1,7 +1,7 @@
This file is history.def, from which is created history.c.
It implements the builtin "history" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -46,7 +46,11 @@ Options:
-s append the ARGs to the history list as a single entry
If FILENAME is given, it is used as the history file. Otherwise,
if HISTFILE has a value, that is used, else ~/.bash_history.
if HISTFILE has a value, that is used. If FILENAME is not supplied
and HISTFILE is unset or null, the -a, -n, -r, and -w options have
no effect and return success.
The fc builtin also operates on the history list.
If the HISTTIMEFORMAT variable is set and not null, its value is used
as a format string for strftime(3) to print the time stamp associated
@@ -86,10 +90,10 @@ $END
extern int errno;
#endif
static char *histtime PARAMS((HIST_ENTRY *, const char *));
static int display_history PARAMS((WORD_LIST *));
static void push_history PARAMS((WORD_LIST *));
static int expand_and_print_history PARAMS((WORD_LIST *));
static char *histtime (HIST_ENTRY *, const char *);
static int display_history (WORD_LIST *);
static void push_history (WORD_LIST *);
static int expand_and_print_history (WORD_LIST *);
#define AFLAG 0x01
#define RFLAG 0x02
@@ -105,8 +109,7 @@ static int expand_and_print_history PARAMS((WORD_LIST *));
#endif
int
history_builtin (list)
WORD_LIST *list;
history_builtin (WORD_LIST *list)
{
int flags, opt, result, old_history_lines, obase, ind;
char *filename, *delete_arg, *range;
@@ -186,7 +189,7 @@ history_builtin (list)
{
intmax_t delete_start, delete_end;
*range++ = '\0';
if (legal_number (delete_arg, &delete_start) == 0 || legal_number (range, &delete_end) == 0)
if (valid_number (delete_arg, &delete_start) == 0 || valid_number (range, &delete_end) == 0)
{
range[-1] = '-';
sh_erange (delete_arg, _("history position"));
@@ -223,9 +226,9 @@ history_builtin (list)
}
else if (flags & DFLAG)
{
if (legal_number (delete_arg, &delete_offset) == 0)
if (valid_number (delete_arg, &delete_offset) == 0)
{
sh_erange (delete_arg, _("history position"));
sh_invalidnum (delete_arg);
return (EXECUTION_FAILURE);
}
/* check for negative offsets, count back from end of list */
@@ -268,6 +271,16 @@ history_builtin (list)
filename = list ? list->word->word : get_string_value ("HISTFILE");
result = EXECUTION_SUCCESS;
if (filename == 0 || *filename == 0)
{
if (interactive_shell == 0 || interactive)
if (list && filename == list->word->word)
builtin_error (_("empty filename"));
else
builtin_error (_("%s: parameter null or not set"), "HISTFILE");
return (interactive ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
#if defined (RESTRICTED_SHELL)
if (restricted && strchr (filename, '/'))
{
@@ -322,9 +335,7 @@ history_builtin (list)
#define histdata(i) (hlist[(i)]->data)
static char *
histtime (hlist, histtimefmt)
HIST_ENTRY *hlist;
const char *histtimefmt;
histtime (HIST_ENTRY *hlist, const char *histtimefmt)
{
static char timestr[TIMELEN_MAX];
time_t t;
@@ -343,8 +354,7 @@ histtime (hlist, histtimefmt)
}
static int
display_history (list)
WORD_LIST *list;
display_history (WORD_LIST *list)
{
register int i;
intmax_t limit;
@@ -354,7 +364,7 @@ display_history (list)
if (list)
{
if (get_numeric_arg (list, 0, &limit) == 0)
return (EXECUTION_FAILURE);
return (EX_USAGE);
if (limit < 0)
limit = -limit;
@@ -395,8 +405,7 @@ display_history (list)
/* Remove the last entry in the history list and add each argument in
LIST to the history. */
static void
push_history (list)
WORD_LIST *list;
push_history (WORD_LIST *list)
{
char *s;
@@ -432,8 +441,7 @@ push_history (list)
#if defined (BANG_HISTORY)
static int
expand_and_print_history (list)
WORD_LIST *list;
expand_and_print_history (WORD_LIST *list)
{
char *s;
int r, result;
+16 -11
View File
@@ -1,7 +1,7 @@
This file is jobs.def, from which is created jobs.c.
It implements the builtins "jobs" and "disown" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -61,6 +61,7 @@ $END
#include "../shell.h"
#include "../jobs.h"
#include "../execute_cmd.h"
#include "../parser.h"
#include "bashgetopt.h"
#include "common.h"
@@ -68,7 +69,7 @@ $END
#define JSTATE_RUNNING 0x1
#define JSTATE_STOPPED 0x2
static int execute_list_with_replacements PARAMS((WORD_LIST *));
static int execute_list_with_replacements (WORD_LIST *);
/* The `jobs' command. Prints outs a list of active jobs. If the
argument `-l' is given, then the process id's are printed also.
@@ -79,8 +80,7 @@ static int execute_list_with_replacements PARAMS((WORD_LIST *));
group leader and execute the command. The -r and -s options mean
to print info about running and stopped jobs only, respectively. */
int
jobs_builtin (list)
WORD_LIST *list;
jobs_builtin (WORD_LIST *list)
{
int form, execute, state, opt, any_failed, job;
sigset_t set, oset;
@@ -136,6 +136,9 @@ jobs_builtin (list)
{
case JSTATE_ANY:
list_all_jobs (form);
/* POSIX says to remove terminated jobs from the list after the jobs
builtin reports their status. */
notify_and_cleanup (); /* the notify part will be a no-op */
break;
case JSTATE_RUNNING:
list_running_jobs (form);
@@ -163,12 +166,15 @@ jobs_builtin (list)
UNBLOCK_CHILD (oset);
list = list->next;
}
/* POSIX says to remove terminated jobs from the list after the jobs
builtin reports their status. */
notify_and_cleanup ();
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
static int
execute_list_with_replacements (list)
WORD_LIST *list;
execute_list_with_replacements (WORD_LIST *list)
{
register WORD_LIST *l;
int job, result;
@@ -195,13 +201,13 @@ execute_list_with_replacements (list)
/* Next make a new simple command and execute it. */
begin_unwind_frame ("jobs_builtin");
command = make_bare_simple_command ();
command = make_bare_simple_command (line_number);
command->value.Simple->words = copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= CMD_INHIBIT_EXPANSION;
command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
add_unwind_protect (dispose_command, command);
add_unwind_protect (uw_dispose_command, command);
result = execute_command (command);
dispose_command (command);
@@ -231,8 +237,7 @@ $END
#if defined (JOB_CONTROL)
int
disown_builtin (list)
WORD_LIST *list;
disown_builtin (WORD_LIST *list)
{
int opt, job, retval, nohup_only, running_jobs, all_jobs;
sigset_t set, oset;
@@ -275,7 +280,7 @@ disown_builtin (list)
do
{
BLOCK_CHILD (set, oset);
job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
job = (list && valid_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
? get_job_by_pid ((pid_t) pid_value, 0, 0)
: get_job_spec (list);
+5 -8
View File
@@ -1,7 +1,7 @@
This file is kill.def, from which is created kill.c.
It implements the builtin "kill" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -70,7 +70,7 @@ $END
extern int errno;
#endif /* !errno */
static void kill_error PARAMS((pid_t, int));
static void kill_error (pid_t, int);
#if !defined (CONTINUE_AFTER_KILL_ERROR)
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
@@ -82,8 +82,7 @@ static void kill_error PARAMS((pid_t, int));
kill -KILL %1? No, if you fill up the process table this way you
can still kill some. */
int
kill_builtin (list)
WORD_LIST *list;
kill_builtin (WORD_LIST *list)
{
int sig, any_succeeded, listing, saw_signal, dflags;
char *sigspec, *word;
@@ -190,7 +189,7 @@ use_sigspec:
word++;
/* Use the entire argument in case of minus sign presence. */
if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
if (*word && valid_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
{
pid = (pid_t) pid_value;
@@ -263,9 +262,7 @@ use_sigspec:
}
static void
kill_error (pid, e)
pid_t pid;
int e;
kill_error (pid_t pid, int e)
{
char *x;
+2 -4
View File
@@ -80,8 +80,7 @@ $END
/* Arithmetic LET function. */
int
let_builtin (list)
WORD_LIST *list;
let_builtin (WORD_LIST *list)
{
intmax_t ret;
int expok;
@@ -110,8 +109,7 @@ let_builtin (list)
#ifdef INCLUDE_UNUSED
int
exp_builtin (list)
WORD_LIST *list;
exp_builtin (WORD_LIST *list)
{
char *exp;
intmax_t ret;
+15 -28
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 2008-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -92,7 +92,7 @@ extern int errno;
#if defined (ARRAY_VARS)
static int run_callback PARAMS((const char *, unsigned int, const char *));
static int run_callback (const char *, unsigned int, const char *);
#define DEFAULT_ARRAY_NAME "MAPFILE"
#define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */
@@ -104,13 +104,8 @@ static int run_callback PARAMS((const char *, unsigned int, const char *));
#define MAPF_CLEARARRAY 0x01
#define MAPF_CHOP 0x02
static int delim;
static int
run_callback (callback, curindex, curline)
const char *callback;
unsigned int curindex;
const char *curline;
run_callback (const char *callback, unsigned int curindex, const char *curline)
{
unsigned int execlen;
char *execstr, *qline;
@@ -134,9 +129,7 @@ run_callback (callback, curindex, curline)
}
static void
do_chop(line, delim)
char *line;
unsigned char delim;
do_chop(char *line, unsigned char delim)
{
int length;
@@ -146,12 +139,8 @@ do_chop(line, delim)
}
static int
mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, delim, flags)
int fd;
long line_count_goal, origin, nskip, callback_quantum;
char *callback, *array_name;
int delim;
int flags;
mapfile (int fd, long line_count_goal, long origin, long nskip, long callback_quantum,
char *callback, char *array_name, int delim, int flags)
{
char *line;
size_t line_length;
@@ -231,10 +220,9 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
}
int
mapfile_builtin (list)
WORD_LIST *list;
mapfile_builtin (WORD_LIST *list)
{
int opt, code, fd, flags;
int opt, code, fd, flags, delim;
intmax_t intval;
long lines, origin, nskip, callback_quantum;
char *array_name, *callback;
@@ -255,7 +243,7 @@ mapfile_builtin (list)
delim = *list_optarg;
break;
case 'u':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (int)intval)
{
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
@@ -272,7 +260,7 @@ mapfile_builtin (list)
break;
case 'n':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (unsigned)intval)
{
builtin_error (_("%s: invalid line count"), list_optarg);
@@ -283,7 +271,7 @@ mapfile_builtin (list)
break;
case 'O':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (unsigned)intval)
{
builtin_error (_("%s: invalid array origin"), list_optarg);
@@ -300,7 +288,7 @@ mapfile_builtin (list)
callback = list_optarg;
break;
case 'c':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval <= 0 || intval != (unsigned)intval)
{
builtin_error (_("%s: invalid callback quantum"), list_optarg);
@@ -310,7 +298,7 @@ mapfile_builtin (list)
callback_quantum = intval;
break;
case 's':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (unsigned)intval)
{
builtin_error (_("%s: invalid line count"), list_optarg);
@@ -342,7 +330,7 @@ mapfile_builtin (list)
else
array_name = list->word->word;
if (legal_identifier (array_name) == 0)
if (valid_identifier (array_name) == 0)
{
sh_invalidid (array_name);
return (EXECUTION_FAILURE);
@@ -354,8 +342,7 @@ mapfile_builtin (list)
#else
int
mapfile_builtin (list)
WORD_LIST *list;
mapfile_builtin (WORD_LIST *list)
{
builtin_error (_("array variable support required"));
return (EXECUTION_FAILURE);
+99 -177
View File
@@ -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-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -59,11 +59,8 @@
extern int errno;
#endif
static char *xmalloc (), *xrealloc ();
#if !defined (__STDC__) && !defined (strcpy)
extern char *strcpy ();
#endif /* !__STDC__ && !strcpy */
static void *xmalloc (size_t);
static void *xrealloc (void *, size_t);
#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
@@ -175,13 +172,14 @@ char *localvar_builtins[] =
/* The builtin commands that are special to the POSIX search order. */
char *posix_builtins[] =
{
"alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs",
"kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait",
"alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "hash",
"jobs", "kill", "newgrp", "pwd", "read", "true", "type", "ulimit",
"umask", "unalias", "wait",
(char *)NULL
};
/* The builtin commands that can take array references as arguments and pay
attention to `assoc_expand_once'. These are the ones that don't assign
attention to `array_expand_once'. These are the ones that don't assign
values, but need to avoid double expansions. */
char *arrayvar_builtins[] =
{
@@ -191,47 +189,47 @@ char *arrayvar_builtins[] =
};
/* Forward declarations. */
static int is_special_builtin ();
static int is_assignment_builtin ();
static int is_localvar_builtin ();
static int is_posix_builtin ();
static int is_arrayvar_builtin ();
static int is_special_builtin (char *);
static int is_assignment_builtin (char *);
static int is_localvar_builtin (char *);
static int is_posix_builtin (char *);
static int is_arrayvar_builtin (char *);
#if !defined (HAVE_RENAME)
static int rename ();
static int rename (char *, char *);
#endif
void extract_info ();
void extract_info (char *, FILE *, FILE *);
void file_error ();
void line_error ();
void file_error (char *);
void line_error (DEF_FILE *, char *, char *, char *);
void write_file_headers ();
void write_file_footers ();
void write_ifdefs ();
void write_endifs ();
void write_documentation ();
void write_longdocs ();
void write_builtins ();
void write_file_headers (FILE *, FILE *);
void write_file_footers (FILE *, FILE *);
void write_ifdefs (FILE *, char **);
void write_endifs (FILE *, char **);
void write_documentation (FILE *, char **, int, int);
void write_dummy_declarations (FILE *, ARRAY *);
void write_longdocs (FILE *, ARRAY *);
void write_builtins (DEF_FILE *, FILE *, FILE *);
int write_helpfiles ();
int write_helpfiles (ARRAY *);
void free_defs ();
void add_documentation ();
static int _find_in_table (char *, char **);
void must_be_building ();
void remove_trailing_whitespace ();
void free_defs (DEF_FILE *);
void add_documentation (DEF_FILE *, char *);
void must_be_building (char *, DEF_FILE *);
void remove_trailing_whitespace (char *);
#define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
/* For each file mentioned on the command line, process it and
write the information to STRUCTFILE and EXTERNFILE, while
creating the production file if necessary. */
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int arg_index = 1;
FILE *structfile, *externfile;
@@ -384,8 +382,7 @@ main (argc, argv)
/* Make a new array, and return a pointer to it. The array will
contain elements of size WIDTH, and is initialized to no elements. */
ARRAY *
array_create (width)
int width;
array_create (int width)
{
ARRAY *array;
@@ -404,8 +401,7 @@ array_create (width)
/* Copy the array of strings in ARRAY. */
ARRAY *
copy_string_array (array)
ARRAY *array;
copy_string_array (ARRAY *array)
{
register int i;
ARRAY *copy;
@@ -431,9 +427,7 @@ copy_string_array (array)
/* Add ELEMENT to ARRAY, growing the array if necessary. */
void
array_add (element, array)
char *element;
ARRAY *array;
array_add (char *element, ARRAY *array)
{
if (array->sindex + 2 > array->size)
array->array = (char **)xrealloc
@@ -445,8 +439,7 @@ array_add (element, array)
/* Free an allocated array and data pointer. */
void
array_free (array)
ARRAY *array;
array_free (ARRAY *array)
{
if (array->array)
free (array->array);
@@ -461,8 +454,7 @@ array_free (array)
/* **************************************************************** */
/* The definition of a function. */
typedef int Function ();
typedef int mk_handler_func_t PARAMS((char *, DEF_FILE *, char *));
typedef int mk_handler_func_t (char *, DEF_FILE *, char *);
/* Structure handles processor directives. */
typedef struct {
@@ -470,14 +462,14 @@ typedef struct {
mk_handler_func_t *function;
} HANDLER_ENTRY;
extern int builtin_handler PARAMS((char *, DEF_FILE *, char *));
extern int function_handler PARAMS((char *, DEF_FILE *, char *));
extern int short_doc_handler PARAMS((char *, DEF_FILE *, char *));
extern int comment_handler PARAMS((char *, DEF_FILE *, char *));
extern int depends_on_handler PARAMS((char *, DEF_FILE *, char *));
extern int produces_handler PARAMS((char *, DEF_FILE *, char *));
extern int end_handler PARAMS((char *, DEF_FILE *, char *));
extern int docname_handler PARAMS((char *, DEF_FILE *, char *));
extern int builtin_handler (char *, DEF_FILE *, char *);
extern int function_handler (char *, DEF_FILE *, char *);
extern int short_doc_handler (char *, DEF_FILE *, char *);
extern int comment_handler (char *, DEF_FILE *, char *);
extern int depends_on_handler (char *, DEF_FILE *, char *);
extern int produces_handler (char *, DEF_FILE *, char *);
extern int end_handler (char *, DEF_FILE *, char *);
extern int docname_handler (char *, DEF_FILE *, char *);
HANDLER_ENTRY handlers[] = {
{ "BUILTIN", builtin_handler },
@@ -494,8 +486,7 @@ HANDLER_ENTRY handlers[] = {
/* Return the entry in the table of handlers for NAME. */
HANDLER_ENTRY *
find_directive (directive)
char *directive;
find_directive (char *directive)
{
register int i;
@@ -524,9 +515,7 @@ int output_cpp_line_info = 0;
builtins found in each $BUILTIN. Plain text found before the $PRODUCES
is ignored, as is "$$ comment text". */
void
extract_info (filename, structfile, externfile)
char *filename;
FILE *structfile, *externfile;
extract_info (char *filename, FILE *structfile, FILE *externfile)
{
register int i;
DEF_FILE *defs;
@@ -609,7 +598,7 @@ extract_info (filename, structfile, externfile)
if (!handler)
{
line_error (defs, "Unknown directive `%s'", directive);
line_error (defs, "Unknown directive `%s'", directive, "");
free (directive);
continue;
}
@@ -666,8 +655,7 @@ extract_info (filename, structfile, externfile)
#define free_safely(x) if (x) free (x)
static void
free_builtin (builtin)
BUILTIN_DESC *builtin;
free_builtin (BUILTIN_DESC *builtin)
{
register int i;
@@ -689,8 +677,7 @@ free_builtin (builtin)
/* Free all of the memory allocated to a DEF_FILE. */
void
free_defs (defs)
DEF_FILE *defs;
free_defs (DEF_FILE *defs)
{
register int i;
register BUILTIN_DESC *builtin;
@@ -722,8 +709,7 @@ free_defs (defs)
/* Strip surrounding whitespace from STRING, and
return a pointer to the start of it. */
char *
strip_whitespace (string)
char *string;
strip_whitespace (char *string)
{
while (whitespace (*string))
string++;
@@ -734,8 +720,7 @@ strip_whitespace (string)
/* Remove only the trailing whitespace from STRING. */
void
remove_trailing_whitespace (string)
char *string;
remove_trailing_whitespace (char *string)
{
register int i;
@@ -752,35 +737,29 @@ remove_trailing_whitespace (string)
DEFS is the DEF_FILE in which the directive is found.
If there is no argument, produce an error. */
char *
get_arg (for_whom, defs, string)
char *for_whom, *string;
DEF_FILE *defs;
get_arg (char *for_whom, DEF_FILE *defs, char *string)
{
char *new;
new = strip_whitespace (string);
if (!*new)
line_error (defs, "%s requires an argument", for_whom);
line_error (defs, "%s requires an argument", for_whom, "");
return (savestring (new));
}
/* Error if not building a builtin. */
void
must_be_building (directive, defs)
char *directive;
DEF_FILE *defs;
must_be_building (char *directive, DEF_FILE *defs)
{
if (!building_builtin)
line_error (defs, "%s must be inside of a $BUILTIN block", directive);
line_error (defs, "%s must be inside of a $BUILTIN block", directive, "");
}
/* Return the current builtin. */
BUILTIN_DESC *
current_builtin (directive, defs)
char *directive;
DEF_FILE *defs;
current_builtin (char *directive, DEF_FILE *defs)
{
must_be_building (directive, defs);
if (defs->builtins)
@@ -792,9 +771,7 @@ current_builtin (directive, defs)
/* Add LINE to the long documentation for the current builtin.
Ignore blank lines until the first non-blank line has been seen. */
void
add_documentation (defs, line)
DEF_FILE *defs;
char *line;
add_documentation (DEF_FILE *defs, char *line)
{
register BUILTIN_DESC *builtin;
@@ -813,10 +790,7 @@ add_documentation (defs, line)
/* How to handle the $BUILTIN directive. */
int
builtin_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
builtin_handler (char *self, DEF_FILE *defs, char *arg)
{
BUILTIN_DESC *new;
char *name;
@@ -824,7 +798,7 @@ builtin_handler (self, defs, arg)
/* If we are already building a builtin, we cannot start a new one. */
if (building_builtin)
{
line_error (defs, "%s found before $END", self);
line_error (defs, "%s found before $END", self, "");
return (-1);
}
@@ -865,10 +839,7 @@ builtin_handler (self, defs, arg)
/* How to handle the $FUNCTION directive. */
int
function_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
function_handler (char *self, DEF_FILE *defs, char *arg)
{
register BUILTIN_DESC *builtin;
@@ -876,7 +847,7 @@ function_handler (self, defs, arg)
if (builtin == 0)
{
line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
line_error (defs, "syntax error: no current builtin for $FUNCTION directive", "", "");
exit (1);
}
if (builtin->function)
@@ -890,10 +861,7 @@ function_handler (self, defs, arg)
/* How to handle the $DOCNAME directive. */
int
docname_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
docname_handler (char *self, DEF_FILE *defs, char *arg)
{
register BUILTIN_DESC *builtin;
@@ -910,10 +878,7 @@ docname_handler (self, defs, arg)
/* How to handle the $SHORT_DOC directive. */
int
short_doc_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
short_doc_handler (char *self, DEF_FILE *defs, char *arg)
{
register BUILTIN_DESC *builtin;
@@ -930,20 +895,14 @@ short_doc_handler (self, defs, arg)
/* How to handle the $COMMENT directive. */
int
comment_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
comment_handler (char *self, DEF_FILE *defs, char *arg)
{
return (0);
}
/* How to handle the $DEPENDS_ON directive. */
int
depends_on_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
depends_on_handler (char *self, DEF_FILE *defs, char *arg)
{
register BUILTIN_DESC *builtin;
char *dependent;
@@ -961,10 +920,7 @@ depends_on_handler (self, defs, arg)
/* How to handle the $PRODUCES directive. */
int
produces_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
produces_handler (char *self, DEF_FILE *defs, char *arg)
{
/* If just hacking documentation, don't change any of the production
files. */
@@ -995,10 +951,7 @@ produces_handler (self, defs, arg)
/* How to handle the $END directive. */
int
end_handler (self, defs, arg)
char *self;
DEF_FILE *defs;
char *arg;
end_handler (char *self, DEF_FILE *defs, char *arg)
{
must_be_building (self, defs);
building_builtin = 0;
@@ -1013,9 +966,7 @@ end_handler (self, defs, arg)
/* Produce an error for DEFS with FORMAT and ARGS. */
void
line_error (defs, format, arg1, arg2)
DEF_FILE *defs;
char *format, *arg1, *arg2;
line_error (DEF_FILE *defs, char *format, char *arg1, char *arg2)
{
if (defs->filename[0] != '/')
fprintf (stderr, "%s", error_directory ? error_directory : "./");
@@ -1027,8 +978,7 @@ line_error (defs, format, arg1, arg2)
/* Print error message for FILENAME. */
void
file_error (filename)
char *filename;
file_error (char *filename)
{
perror (filename);
exit (2);
@@ -1040,30 +990,27 @@ file_error (filename)
/* */
/* **************************************************************** */
static void memory_error_and_abort ();
static void memory_error_and_abort (void);
static char *
xmalloc (bytes)
int bytes;
static void *
xmalloc (size_t bytes)
{
char *temp = (char *)malloc (bytes);
void *temp = malloc (bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}
static char *
xrealloc (pointer, bytes)
char *pointer;
int bytes;
static void *
xrealloc (void *pointer, size_t bytes)
{
char *temp;
void *temp;
if (!pointer)
temp = (char *)malloc (bytes);
temp = malloc (bytes);
else
temp = (char *)realloc (pointer, bytes);
temp = realloc (pointer, bytes);
if (!temp)
memory_error_and_abort ();
@@ -1072,7 +1019,7 @@ xrealloc (pointer, bytes)
}
static void
memory_error_and_abort ()
memory_error_and_abort (void)
{
fprintf (stderr, "mkbuiltins: out of virtual memory\n");
abort ();
@@ -1087,8 +1034,7 @@ memory_error_and_abort ()
/* Return a pointer to a newly allocated builtin which is
an exact copy of BUILTIN. */
BUILTIN_DESC *
copy_builtin (builtin)
BUILTIN_DESC *builtin;
copy_builtin (BUILTIN_DESC *builtin)
{
BUILTIN_DESC *new;
@@ -1109,8 +1055,7 @@ copy_builtin (builtin)
/* How to save away a builtin. */
void
save_builtin (builtin)
BUILTIN_DESC *builtin;
save_builtin (BUILTIN_DESC *builtin)
{
BUILTIN_DESC *newbuiltin;
@@ -1187,8 +1132,7 @@ char *structfile_footer[] = {
/* Write out any necessary opening information for
STRUCTFILE and EXTERNFILE. */
void
write_file_headers (structfile, externfile)
FILE *structfile, *externfile;
write_file_headers (FILE *structfile, FILE *externfile)
{
register int i;
@@ -1214,8 +1158,7 @@ write_file_headers (structfile, externfile)
/* Write out any necessary closing information for
STRUCTFILE and EXTERNFILE. */
void
write_file_footers (structfile, externfile)
FILE *structfile, *externfile;
write_file_footers (FILE *structfile, FILE *externfile)
{
register int i;
@@ -1230,9 +1173,7 @@ write_file_footers (structfile, externfile)
/* Write out the information accumulated in DEFS to
STRUCTFILE and EXTERNFILE. */
void
write_builtins (defs, structfile, externfile)
DEF_FILE *defs;
FILE *structfile, *externfile;
write_builtins (DEF_FILE *defs, FILE *structfile, FILE *externfile)
{
register int i;
@@ -1258,7 +1199,7 @@ write_builtins (defs, structfile, externfile)
if (externfile)
{
if (builtin->function)
fprintf (externfile, "extern int %s PARAMS((WORD_LIST *));\n",
fprintf (externfile, "extern int %s (WORD_LIST *);\n",
builtin->function);
fprintf (externfile, "extern char * const %s_doc[];\n",
@@ -1336,9 +1277,7 @@ write_builtins (defs, structfile, externfile)
/* Write out the long documentation strings in BUILTINS to STREAM. */
void
write_longdocs (stream, builtins)
FILE *stream;
ARRAY *builtins;
write_longdocs (FILE *stream, ARRAY *builtins)
{
register int i;
register BUILTIN_DESC *builtin;
@@ -1375,9 +1314,7 @@ write_longdocs (stream, builtins)
}
void
write_dummy_declarations (stream, builtins)
FILE *stream;
ARRAY *builtins;
write_dummy_declarations (FILE *stream, ARRAY *builtins)
{
register int i;
BUILTIN_DESC *builtin;
@@ -1401,9 +1338,7 @@ write_dummy_declarations (stream, builtins)
If a define is preceded by an `!', then the sense of the test is
reversed. */
void
write_ifdefs (stream, defines)
FILE *stream;
char **defines;
write_ifdefs (FILE *stream, char **defines)
{
register int i;
@@ -1432,9 +1367,7 @@ write_ifdefs (stream, defines)
STREAM is the stream to write the information to.
DEFINES is a null terminated array of define names. */
void
write_endifs (stream, defines)
FILE *stream;
char **defines;
write_endifs (FILE *stream, char **defines)
{
register int i;
@@ -1459,10 +1392,7 @@ write_endifs (stream, defines)
internationalization (gettext) and the single-string vs. multiple-strings
issues. */
void
write_documentation (stream, documentation, indentation, flags)
FILE *stream;
char **documentation;
int indentation, flags;
write_documentation (FILE *stream, char **documentation, int indentation, int flags)
{
register int i, j;
register char *line;
@@ -1590,8 +1520,7 @@ write_documentation (stream, documentation, indentation, flags)
}
int
write_helpfiles (builtins)
ARRAY *builtins;
write_helpfiles (ARRAY *builtins)
{
char *helpfile, *bname;
FILE *helpfp;
@@ -1632,8 +1561,7 @@ write_helpfiles (builtins)
}
static int
_find_in_table (name, name_table)
char *name, *name_table[];
_find_in_table (char *name, char **name_table)
{
register int i;
@@ -1644,44 +1572,38 @@ _find_in_table (name, name_table)
}
static int
is_special_builtin (name)
char *name;
is_special_builtin (char *name)
{
return (_find_in_table (name, special_builtins));
}
static int
is_assignment_builtin (name)
char *name;
is_assignment_builtin (char *name)
{
return (_find_in_table (name, assignment_builtins));
}
static int
is_localvar_builtin (name)
char *name;
is_localvar_builtin (char *name)
{
return (_find_in_table (name, localvar_builtins));
}
static int
is_posix_builtin (name)
char *name;
is_posix_builtin (char *name)
{
return (_find_in_table (name, posix_builtins));
}
static int
is_arrayvar_builtin (name)
char *name;
is_arrayvar_builtin (char *name)
{
return (_find_in_table (name, arrayvar_builtins));
}
#if !defined (HAVE_RENAME)
static int
rename (from, to)
char *from, *to;
rename (char *from, char *to)
{
unlink (to);
if (link (from, to) < 0)
+547 -246
View File
File diff suppressed because it is too large Load Diff
+3 -6
View File
@@ -1,6 +1,6 @@
/* psize.c - Find pipe size. */
/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
/* Copyright (C) 1987, 1991, 2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -48,17 +48,14 @@ extern int errno;
int nw;
sighandler
sigpipe (sig)
int sig;
sigpipe (int sig)
{
fprintf (stderr, "%d\n", nw);
exit (0);
}
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
char buf[128];
register int i;
+53 -46
View File
@@ -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-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -116,6 +116,10 @@ $END
#include <config.h>
#if defined (PUSHD_AND_POPD)
#ifdef LOADABLE_BUILTIN
# include "builtins.h"
#endif
#include <stdio.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
@@ -140,10 +144,6 @@ $END
#include "common.h"
#include "builtext.h"
#ifdef LOADABLE_BUILTIN
# include "builtins.h"
#endif
#if !defined (errno)
extern int errno;
#endif /* !errno */
@@ -152,17 +152,17 @@ extern int errno;
static char **pushd_directory_list = (char **)NULL;
/* Number of existing slots in this list. */
static int directory_list_size;
static size_t directory_list_size;
/* Offset to the end of the list. */
static int directory_list_offset;
static void pushd_error PARAMS((int, char *));
static void clear_directory_stack PARAMS((void));
static int cd_to_string PARAMS((char *));
static int change_to_temp PARAMS((char *));
static void add_dirstack_element PARAMS((char *));
static int get_dirstack_index PARAMS((intmax_t, int, int *));
static void pushd_error (int, char *);
static void clear_directory_stack (void);
static int cd_to_string (char *);
static int change_to_temp (char *);
static void add_dirstack_element (char *);
static int get_dirstack_index (intmax_t, int, int *);
#define NOCD 0x01
#define ROTATE 0x02
@@ -170,8 +170,7 @@ static int get_dirstack_index PARAMS((intmax_t, int, int *));
#define CLEARSTAK 0x08
int
pushd_builtin (list)
WORD_LIST *list;
pushd_builtin (WORD_LIST *list)
{
WORD_LIST *orig_list;
char *temp, *current_directory, *top;
@@ -228,7 +227,7 @@ pushd_builtin (list)
break;
else if (((direction = list->word->word[0]) == '+') || direction == '-')
{
if (legal_number (list->word->word + 1, &num) == 0)
if (valid_number (list->word->word + 1, &num) == 0)
{
sh_invalidnum (list->word->word);
builtin_usage ();
@@ -316,8 +315,7 @@ pushd_builtin (list)
If LIST is non-null it should consist of a word +N or -N, which says
what element to delete from the stack. The default is the top one. */
int
popd_builtin (list)
WORD_LIST *list;
popd_builtin (WORD_LIST *list)
{
register int i;
intmax_t which;
@@ -341,7 +339,7 @@ popd_builtin (list)
}
else if (((direction = list->word->word[0]) == '+') || direction == '-')
{
if (legal_number (list->word->word + 1, &which) == 0)
if (valid_number (list->word->word + 1, &which) == 0)
{
sh_invalidnum (list->word->word);
builtin_usage ();
@@ -365,6 +363,30 @@ popd_builtin (list)
break;
}
#if 0
/* If we didn't find `which' but there are arguments remaining, assume we
got `--' */
if (which_word == 0 && list)
{
if (((direction = list->word->word[0]) == '+') || direction == '-')
{
if (valid_number (list->word->word + 1, &which) == 0)
{
sh_invalidnum (list->word->word);
builtin_usage ();
return (EX_USAGE);
}
which_word = list->word->word;
}
else
{
builtin_error (_("%s: invalid argument"), list->word->word);
builtin_usage ();
return (EX_USAGE);
}
}
#endif
if (which > directory_list_offset || (which < -directory_list_offset) || (directory_list_offset == 0 && which == 0))
{
pushd_error (directory_list_offset, which_word ? which_word : "");
@@ -406,8 +428,7 @@ popd_builtin (list)
/* Print the current list of directories on the directory stack. */
int
dirs_builtin (list)
WORD_LIST *list;
dirs_builtin (WORD_LIST *list)
{
int flags, desired_index, index_flag, vflag;
intmax_t i;
@@ -440,7 +461,7 @@ dirs_builtin (list)
else if (*list->word->word == '+' || *list->word->word == '-')
{
int sign;
if (legal_number (w = list->word->word + 1, &i) == 0)
if (valid_number (w = list->word->word + 1, &i) == 0)
{
sh_invalidnum (list->word->word);
builtin_usage ();
@@ -516,9 +537,7 @@ dirs_builtin (list)
}
static void
pushd_error (offset, arg)
int offset;
char *arg;
pushd_error (int offset, char *arg)
{
if (offset == 0)
builtin_error (_("directory stack empty"));
@@ -527,7 +546,7 @@ pushd_error (offset, arg)
}
static void
clear_directory_stack ()
clear_directory_stack (void)
{
register int i;
@@ -540,8 +559,7 @@ clear_directory_stack ()
so if the result is EXECUTION_FAILURE then an error message has already
been printed. */
static int
cd_to_string (name)
char *name;
cd_to_string (char *name)
{
WORD_LIST *tlist;
WORD_LIST *dir;
@@ -555,8 +573,7 @@ cd_to_string (name)
}
static int
change_to_temp (temp)
char *temp;
change_to_temp (char *temp)
{
int tt;
@@ -569,8 +586,7 @@ change_to_temp (temp)
}
static void
add_dirstack_element (dir)
char *dir;
add_dirstack_element (char *dir)
{
if (directory_list_offset == directory_list_size)
pushd_directory_list = strvec_resize (pushd_directory_list, directory_list_size += 10);
@@ -578,9 +594,7 @@ add_dirstack_element (dir)
}
static int
get_dirstack_index (ind, sign, indexp)
intmax_t ind;
int sign, *indexp;
get_dirstack_index (intmax_t ind, int sign, int *indexp)
{
if (indexp)
*indexp = sign > 0 ? 1 : 2;
@@ -603,8 +617,7 @@ get_dirstack_index (ind, sign, indexp)
/* Used by the tilde expansion code. */
char *
get_dirstack_from_string (string)
char *string;
get_dirstack_from_string (char *string)
{
int ind, sign, index_flag;
intmax_t i;
@@ -615,7 +628,7 @@ get_dirstack_from_string (string)
sign = (*string == '-') ? -1 : 1;
string++;
}
if (legal_number (string, &i) == 0)
if (valid_number (string, &i) == 0)
return ((char *)NULL);
index_flag = 0;
@@ -630,9 +643,7 @@ get_dirstack_from_string (string)
#ifdef INCLUDE_UNUSED
char *
get_dirstack_element (ind, sign)
intmax_t ind;
int sign;
get_dirstack_element (intmax_t ind, int sign)
{
int i;
@@ -643,10 +654,7 @@ get_dirstack_element (ind, sign)
#endif
void
set_dirstack_element (ind, sign, value)
intmax_t ind;
int sign;
char *value;
set_dirstack_element (intmax_t ind, int sign, char *value)
{
int i;
@@ -658,8 +666,7 @@ set_dirstack_element (ind, sign, value)
}
WORD_LIST *
get_directory_stack (flags)
int flags;
get_directory_stack (int flags)
{
register int i;
WORD_LIST *ret;
+143 -101
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -22,7 +22,7 @@ $PRODUCES read.c
$BUILTIN read
$FUNCTION read_builtin
$SHORT_DOC read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
$SHORT_DOC read [-Eers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descriptor FD
@@ -41,6 +41,8 @@ Options:
-d delim continue until the first character of DELIM is read, rather
than newline
-e use Readline to obtain the line
-E use Readline to obtain the line and use the bash default
completion instead of Readline's default completion
-i text use TEXT as the initial text for Readline
-n nchars return after reading NCHARS characters rather than waiting
for a newline, but honor a delimiter if fewer than
@@ -86,7 +88,6 @@ $END
#ifdef __CYGWIN__
# include <fcntl.h>
# include <io.h>
#endif
#include "../bashintl.h"
@@ -103,9 +104,7 @@ $END
#include <readline/readline.h>
#endif
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
#include "shmbutil.h"
#include "timer.h"
@@ -121,28 +120,29 @@ struct ttsave
};
#if defined (READLINE)
static void reset_attempted_completion_function PARAMS((char *));
static int set_itext PARAMS((void));
static char *edit_line PARAMS((char *, char *));
static void set_eol_delim PARAMS((int));
static void reset_eol_delim PARAMS((char *));
static void set_readline_timeout PARAMS((sh_timer *t, time_t, long));
static void uw_reset_attempted_completion_function (void *);
static int set_itext (void);
static char *edit_line (char *, char *, unsigned char, int);
static void set_eol_delim (int);
static void reset_eol_delim (void *);
static void set_readline_timeout (sh_timer *t, time_t, long);
static void uw_bashline_reset_event_hook (void *);
#endif
static SHELL_VAR *bind_read_variable PARAMS((char *, char *, int));
static SHELL_VAR *bind_read_variable (char *, char *, int);
#if defined (HANDLE_MULTIBYTE)
static int read_mbchar PARAMS((int, char *, int, int, int));
static int read_mbchar (int, char *, int, int, int);
#endif
static void ttyrestore PARAMS((struct ttsave *));
static void ttyrestore (struct ttsave *);
static void uw_ttyrestore (void *);
static sighandler sigalrm PARAMS((int));
static void reset_timeout PARAMS((void));
static sighandler sigalrm (int);
static void reset_timeout (void);
static void uw_reset_timeout (void *);
/* Try this to see what the rest of the shell can do with the information. */
sh_timer *read_timeout;
static int reading, tty_modified;
static SigHandler *old_alrm;
static unsigned char delim;
static struct ttsave termsave;
@@ -153,8 +153,7 @@ static struct ttsave termsave;
/* Set a flag that check_read_timeout can check. This relies on zread or
read_builtin calling trap.c:check_signals() (which calls check_read_timeout()) */
static sighandler
sigalrm (s)
int s;
sigalrm (int s)
{
/* Display warning if this is called without read_timeout set? */
if (read_timeout)
@@ -162,7 +161,7 @@ sigalrm (s)
}
static void
reset_timeout ()
reset_timeout (void)
{
/* Cancel alarm before restoring signal handler. */
if (read_timeout)
@@ -173,24 +172,33 @@ reset_timeout ()
read_timeout = 0;
}
static void
uw_reset_timeout (void *ignore)
{
reset_timeout ();
}
void
check_read_timeout ()
check_read_timeout (void)
{
if (read_timeout && shtimer_chktimeout (read_timeout))
sh_longjmp (read_timeout->jmpenv, 1);
}
int
read_builtin_timeout (fd)
int fd;
read_builtin_timeout (int fd)
{
if ((read_timeout == 0) ||
(read_timeout->fd != fd) ||
(read_timeout->tmout.tv_sec == 0 && read_timeout->tmout.tv_usec == 0))
return 0;
#if defined (HAVE_SELECT)
return ((read_timeout->flags & SHTIMER_ALARM) ? shtimer_alrm (read_timeout)
: shtimer_select (read_timeout));
#else
return (shtimer_alrm (read_timeout));
#endif
}
/* Read the value of the shell variables whose names follow.
@@ -200,20 +208,23 @@ read_builtin_timeout (fd)
gets the remainder of the words on the line. If no variables
are mentioned in LIST, then the default variable is $REPLY. */
int
read_builtin (list)
WORD_LIST *list;
read_builtin (WORD_LIST *list)
{
register char *varname;
int size, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2, nflag;
char *varname;
int nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2, nflag;
size_t size;
volatile int i;
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd;
int edit, use_bash_completion;
int raw, nchars, silent, have_timeout, ignore_delim, fd;
int free_ifs;
int lastsig, t_errno;
int mb_cur_max;
unsigned int tmsec, tmusec;
long ival, uval;
intmax_t intval;
char c;
unsigned char delim;
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
char *e, *t, *t1, *ps2, *tofree;
struct stat tsb;
@@ -239,6 +250,8 @@ read_builtin (list)
USE_VAR(input_is_pipe);
/* USE_VAR(raw); */
USE_VAR(edit);
USE_VAR(use_bash_completion);
USE_VAR(delim);
USE_VAR(tmsec);
USE_VAR(tmusec);
USE_VAR(nchars);
@@ -260,6 +273,7 @@ read_builtin (list)
i = 0; /* Index into the string that we are reading. */
raw = edit = 0; /* Not reading raw input by default. */
use_bash_completion = 0;
silent = 0;
arrayname = prompt = (char *)NULL;
fd = 0; /* file descriptor to read from */
@@ -276,7 +290,7 @@ read_builtin (list)
ignore_delim = nflag = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1)
while ((opt = internal_getopt (list, "Eersa:d:i:n:p:t:u:N:")) != -1)
{
switch (opt)
{
@@ -294,6 +308,12 @@ read_builtin (list)
edit = 1;
#endif
break;
case 'E':
#if defined (READLINE)
edit = use_bash_completion = 1;
#endif
break;
case 'i':
#if defined (READLINE)
itext = list_optarg;
@@ -323,7 +343,7 @@ read_builtin (list)
delim = -1;
case 'n':
nflag = 1;
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (int)intval)
{
sh_invalidnum (list_optarg);
@@ -333,7 +353,7 @@ read_builtin (list)
nchars = intval;
break;
case 'u':
code = legal_number (list_optarg, &intval);
code = valid_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (int)intval)
{
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
@@ -368,10 +388,10 @@ read_builtin (list)
#if defined (ARRAY_VARS)
if (list)
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
if (list && valid_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
#else
bindflags = 0;
if (list && legal_identifier (list->word->word) == 0)
if (list && valid_identifier (list->word->word) == 0)
#endif
{
sh_invalidid (list->word->word);
@@ -383,18 +403,27 @@ read_builtin (list)
delim = -1;
/* IF IFS is unset, we use the default of " \t\n". */
ifs_chars = getifs ();
if (ifs_chars == 0) /* XXX - shouldn't happen */
ifs_chars = "";
free_ifs = 0;
/* If we want to read exactly NCHARS chars, don't split on IFS */
if (ignore_delim)
ifs_chars = "";
else
{
ifs_chars = getifs ();
if (ifs_chars == 0) /* XXX - shouldn't happen */
ifs_chars = "";
else
free_ifs = 1;
}
for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
input_string[0] = '\0';
pass_next = 0; /* Non-zero signifies last char was backslash. */
saw_escape = 0; /* Non-zero is count of escape chars we added */
/* More input and options validation */
if (nflag == 1 && nchars == 0)
{
@@ -420,14 +449,14 @@ read_builtin (list)
sigemptyset (&chldset);
sigprocmask (SIG_BLOCK, (sigset_t *)0, &chldset);
sigaddset (&chldset, SIGCHLD);
sigemptyset (&prevset);
sigprocmask (SIG_SETMASK, (sigset_t *)0, &prevset);
#endif
begin_unwind_frame ("read_builtin");
#if defined (BUFFERED_INPUT)
if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
sync_buffered_stream (default_buffered_input);
#endif
#if 1
input_is_tty = isatty (fd);
@@ -436,7 +465,7 @@ read_builtin (list)
#endif
if (input_is_tty == 0)
#ifndef __CYGWIN__
input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
input_is_pipe = fd_ispipe (fd);
#else
input_is_pipe = 1;
#endif
@@ -457,9 +486,6 @@ read_builtin (list)
add_unwind_protect (xfree, rlbuf);
#endif
pass_next = 0; /* Non-zero signifies last char was backslash. */
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
if (tmsec > 0 || tmusec > 0)
{
/* Turn off the timeout if stdin is a regular file (e.g. from
@@ -473,7 +499,7 @@ read_builtin (list)
read_timeout = shtimer_alloc ();
read_timeout->flags = SHTIMER_LONGJMP;
#if defined (HAVE_SELECT)
#if defined (HAVE_SELECT) || defined (HAVE_PSELECT)
read_timeout->flags |= (edit || posixly_correct) ? SHTIMER_ALARM : SHTIMER_SELECT;
#else
read_timeout->flags |= SHTIMER_ALARM;
@@ -489,7 +515,9 @@ read_builtin (list)
if (code)
{
reset_timeout ();
#if defined (SIGCHLD)
sigprocmask (SIG_SETMASK, &prevset, (sigset_t *)0);
#endif
/* 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,
@@ -512,12 +540,12 @@ read_builtin (list)
}
if (interactive_shell == 0)
initialize_terminating_signals ();
add_unwind_protect (reset_timeout, (char *)NULL);
add_unwind_protect (uw_reset_timeout, NULL);
#if defined (READLINE)
if (edit)
{
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
add_unwind_protect (bashline_reset_event_hook, (char *)NULL);
add_unwind_protect (uw_reset_attempted_completion_function, NULL);
add_unwind_protect (uw_bashline_reset_event_hook, NULL);
set_readline_timeout (read_timeout, tmsec, tmusec);
}
else
@@ -541,7 +569,7 @@ read_builtin (list)
if (delim != '\n')
{
set_eol_delim (delim);
add_unwind_protect (reset_eol_delim, (char *)NULL);
add_unwind_protect (reset_eol_delim, NULL);
}
}
else
@@ -558,7 +586,7 @@ read_builtin (list)
if (i < 0)
sh_ttyerror (1);
tty_modified = 1;
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
add_unwind_protect (uw_ttyrestore, &termsave);
if (interactive_shell == 0)
initialize_terminating_signals ();
}
@@ -576,7 +604,7 @@ read_builtin (list)
sh_ttyerror (1);
tty_modified = 1;
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
add_unwind_protect (uw_ttyrestore, &termsave);
if (interactive_shell == 0)
initialize_terminating_signals ();
}
@@ -614,10 +642,6 @@ read_builtin (list)
fflush (stderr);
}
#if defined (__CYGWIN__) && defined (O_TEXT)
setmode (0, O_TEXT);
#endif
ps2 = 0;
for (print_ps2 = eof = retval = 0;;)
{
@@ -639,7 +663,7 @@ read_builtin (list)
if (rlbuf == 0)
{
reading = 1;
rlbuf = edit_line (prompt ? prompt : "", itext);
rlbuf = edit_line (prompt ? prompt : "", itext, delim, use_bash_completion);
reading = 0;
rlind = 0;
}
@@ -690,9 +714,9 @@ read_builtin (list)
if (retval <= 0)
{
int t;
int x;
t = errno;
x = errno;
if (retval < 0 && errno == EINTR)
{
check_signals (); /* in case we didn't call zread via zreadc */
@@ -709,7 +733,7 @@ read_builtin (list)
ttyrestore (&termsave); /* fix terminal before exiting */
CHECK_TERMSIG;
eof = 1;
errno = t; /* preserve it for the error message below */
errno = x; /* preserve it for the error message below */
break;
}
@@ -724,13 +748,13 @@ read_builtin (list)
/* XXX -- use i + mb_cur_max (at least 4) for multibyte/read_mbchar */
if (i + (mb_cur_max > 4 ? mb_cur_max : 4) >= size)
{
char *t;
t = (char *)xrealloc (input_string, size += 128);
char *x;
x = (char *)xrealloc (input_string, size += 128);
/* Only need to change unwind-protect if input_string changes */
if (t != input_string)
if (x != input_string)
{
input_string = t;
input_string = x;
remove_unwind_protect ();
add_unwind_protect (xfree, input_string);
}
@@ -741,11 +765,14 @@ read_builtin (list)
if (pass_next)
{
pass_next = 0;
if (c == '\n')
if (c == '\n' || c == '\0')
{
if (skip_ctlesc == 0 && i > 0)
i--; /* back up over the CTLESC */
if (interactive && input_is_tty && raw == 0)
{
i--; /* back up over the CTLESC */
saw_escape--; /* one fewer CTLESC in the input */
}
if (interactive && input_is_tty && raw == 0 && c == '\n')
print_ps2 = 1;
}
else
@@ -815,6 +842,17 @@ add_char:
if (nchars > 0 && nr >= nchars)
break;
}
/* Back up over trailing CTLESC if the input ends with an unescaped
backslash */
if (pass_next && skip_ctlesc == 0)
{
i--;
saw_escape--; /* that CTLESC is no longer in the input */
}
/* I don't think this clause ever tests true. */
if (skip_ctlnul && saw_escape && i == 1 && input_string[0] == CTLNUL)
saw_escape = 0; /* Avoid dequoting bare CTLNUL */
input_string[i] = '\0';
check_read_timeout ();
@@ -843,7 +881,7 @@ add_char:
if (nchars > 0)
rl_num_chars_to_read = 0;
if (delim != '\n')
reset_eol_delim ((char *)NULL);
reset_eol_delim (NULL);
}
else
#endif
@@ -923,7 +961,7 @@ assign_vars:
else
var = bind_variable ("REPLY", input_string, 0);
if (var == 0 || readonly_p (var) || noassign_p (var))
retval = EXECUTION_FAILURE;
retval = EX_MISCERROR;
else
VUNSETATTR (var, att_invisible);
@@ -945,9 +983,9 @@ assign_vars:
varname = list->word->word;
#if defined (ARRAY_VARS)
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (legal_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0)
if (valid_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0)
#else
if (legal_identifier (varname) == 0)
if (valid_identifier (varname) == 0)
#endif
{
sh_invalidid (varname);
@@ -984,7 +1022,7 @@ assign_vars:
if (var == 0)
{
free (orig_input_string);
return (EXECUTION_FAILURE);
return (EX_MISCERROR);
}
stupidly_hack_special_variables (varname);
@@ -994,9 +1032,9 @@ assign_vars:
/* Now assign the rest of the line to the last variable argument. */
#if defined (ARRAY_VARS)
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
if (valid_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
#else
if (legal_identifier (list->word->word) == 0)
if (valid_identifier (list->word->word) == 0)
#endif
{
sh_invalidid (list->word->word);
@@ -1044,6 +1082,8 @@ assign_vars:
else
retval = EXECUTION_FAILURE;
if (free_ifs)
free (ifs_chars);
FREE (tofree);
free (orig_input_string);
@@ -1051,9 +1091,7 @@ assign_vars:
}
static SHELL_VAR *
bind_read_variable (name, value, flags)
char *name, *value;
int flags;
bind_read_variable (char *name, char *value, int flags)
{
SHELL_VAR *v;
@@ -1064,10 +1102,7 @@ bind_read_variable (name, value, flags)
#if defined (HANDLE_MULTIBYTE)
static int
read_mbchar (fd, string, ind, ch, unbuffered)
int fd;
char *string;
int ind, ch, unbuffered;
read_mbchar (int fd, char *string, int ind, int ch, int unbuffered)
{
char mbchar[MB_LEN_MAX + 1];
int i, n, r;
@@ -1116,22 +1151,27 @@ mbchar_return:
static void
ttyrestore (ttp)
struct ttsave *ttp;
ttyrestore (struct ttsave *ttp)
{
ttsetattr (ttp->fd, &(ttp->attrs));
tty_modified = 0;
}
static void
uw_ttyrestore (void *ttp)
{
ttyrestore (ttp);
}
void
read_tty_cleanup ()
read_tty_cleanup (void)
{
if (tty_modified)
ttyrestore (&termsave);
}
int
read_tty_modified ()
read_tty_modified (void)
{
return (tty_modified);
}
@@ -1142,15 +1182,20 @@ static rl_hook_func_t *old_startup_hook;
static char *deftext;
static void
reset_attempted_completion_function (cp)
char *cp;
uw_reset_attempted_completion_function (void *cp)
{
if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
rl_attempted_completion_function = old_attempted_completion_function;
}
static void
uw_bashline_reset_event_hook (void *ignore)
{
bashline_reset_event_hook ();
}
static int
set_itext ()
set_itext (void)
{
int r1, r2;
@@ -1168,18 +1213,19 @@ set_itext ()
}
static char *
edit_line (p, itext)
char *p;
char *itext;
edit_line (char *p, char *itext, unsigned char delim, int keep_completion_func)
{
char *ret;
int len;
size_t len;
if (bash_readline_initialized == 0)
initialize_readline ();
old_attempted_completion_function = rl_attempted_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
/* If we don't indicate that we want to keep the attempted completion
function, reset it so we use the default readline word completion. */
if (keep_completion_func == 0)
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
bashline_set_event_hook ();
if (itext)
{
@@ -1190,7 +1236,8 @@ edit_line (p, itext)
ret = readline (p);
rl_attempted_completion_function = old_attempted_completion_function;
if (keep_completion_func == 0)
rl_attempted_completion_function = old_attempted_completion_function;
old_attempted_completion_function = (rl_completion_func_t *)NULL;
bashline_reset_event_hook ();
@@ -1212,10 +1259,7 @@ edit_line (p, itext)
}
static void
set_readline_timeout (t, sec, usec)
sh_timer *t;
time_t sec;
long usec;
set_readline_timeout (sh_timer *t, time_t sec, long usec)
{
t->tmout.tv_sec = sec;
t->tmout.tv_usec = usec;
@@ -1230,8 +1274,7 @@ static rl_command_func_t *old_newline_func;
static unsigned char delim_char;
static void
set_eol_delim (c)
int c;
set_eol_delim (int c)
{
Keymap cmap;
@@ -1257,8 +1300,7 @@ set_eol_delim (c)
}
static void
reset_eol_delim (cp)
char *cp;
reset_eol_delim (void *ignore)
{
Keymap cmap;
+10
View File
@@ -19,6 +19,16 @@ 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/>.
$BUILTIN !
$DOCNAME bang
$SHORT_DOC ! PIPELINE
Execute PIPELINE, which can be a simple command, and negate PIPELINE's
return status.
Exit Status:
The logical negation of PIPELINE's return status.
$END
$BUILTIN for
$SHORT_DOC for NAME [in WORDS ... ] ; do COMMANDS; done
Execute commands for each member in a list.
+8 -3
View File
@@ -1,7 +1,7 @@
This file is return.def, from which is created return.c.
It implements the builtin "return" in Bash.
Copyright (C) 1987-2015 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -54,12 +54,17 @@ $END
specified as an argument. if no argument is given, then the last
exit status is used. */
int
return_builtin (list)
WORD_LIST *list;
return_builtin (WORD_LIST *list)
{
CHECK_HELPOPT (list);
return_catch_value = get_exitstat (list);
/* return is a special builtin, so non-interactive shells in posix mode
exit on an invalid numeric argument. We have to do it this way because
the return_catch targets aren't set up to deal with EXITSHELL, so we
just jump_to_top_level directly. */
if (interactive_shell == 0 && posixly_correct && executing_command_builtin == 0 && return_catch_value > EX_SHERRBASE)
return (return_catch_value);
if (return_catch_flag)
sh_longjmp (return_catch, 1);
+96 -77
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -141,6 +141,10 @@ Options:
- Assign any remaining arguments to the positional parameters.
The -x and -v options are turned off.
If -o is supplied with no option-name, set prints the current shell
option settings. If +o is supplied with no option-name, set prints a
series of set commands to recreate the current option settings.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
@@ -151,24 +155,24 @@ Exit Status:
Returns success unless an invalid option is given.
$END
typedef int setopt_set_func_t PARAMS((int, char *));
typedef int setopt_get_func_t PARAMS((char *));
typedef int setopt_set_func_t (int, char *);
typedef int setopt_get_func_t (char *);
static int find_minus_o_option PARAMS((char *));
static int find_minus_o_option (char *);
static void print_minus_o_option PARAMS((char *, int, int));
static void print_all_shell_variables PARAMS((void));
static void print_minus_o_option (char *, int, int);
static void print_all_shell_variables (void);
static int set_ignoreeof PARAMS((int, char *));
static int set_posix_mode PARAMS((int, char *));
static int set_ignoreeof (int, char *);
static int set_posix_mode (int, char *);
#if defined (READLINE)
static int set_edit_mode PARAMS((int, char *));
static int get_edit_mode PARAMS((char *));
static int set_edit_mode (int, char *);
static int get_edit_mode (char *);
#endif
#if defined (HISTORY)
static int bash_set_history PARAMS((int, char *));
static int bash_set_history (int, char *);
#endif
static const char * const on = "on";
@@ -245,8 +249,7 @@ const struct {
: (*o_options[i].variable = (onoff == FLAG_ON)))
static int
find_minus_o_option (name)
char *name;
find_minus_o_option (char *name)
{
register int i;
@@ -257,8 +260,7 @@ find_minus_o_option (name)
}
int
minus_o_option_value (name)
char *name;
minus_o_option_value (char *name)
{
register int i;
int *on_or_off;
@@ -279,9 +281,7 @@ minus_o_option_value (name)
#define MINUS_O_FORMAT "%-15s\t%s\n"
static void
print_minus_o_option (name, value, pflag)
char *name;
int value, pflag;
print_minus_o_option (char *name, int value, int pflag)
{
if (pflag == 0)
printf (MINUS_O_FORMAT, name, value ? on : off);
@@ -290,8 +290,7 @@ print_minus_o_option (name, value, pflag)
}
void
list_minus_o_opts (mode, reusable)
int mode, reusable;
list_minus_o_opts (int mode, int reusable)
{
register int i;
int *on_or_off, value;
@@ -317,7 +316,7 @@ list_minus_o_opts (mode, reusable)
}
char **
get_minus_o_opts ()
get_minus_o_opts (void)
{
char **ret;
int i;
@@ -330,10 +329,11 @@ get_minus_o_opts ()
}
char *
get_current_options ()
get_current_options (void)
{
char *temp;
int i, posixopts;
int i;
size_t posixopts;
posixopts = num_posix_options (); /* shopts modified by posix mode */
/* Make the buffer big enough to hold the set -o options and the shopt
@@ -355,8 +355,7 @@ get_current_options ()
}
void
set_current_options (bitmap)
const char *bitmap;
set_current_options (const char *bitmap)
{
int i, v, cv, *on_or_off;
@@ -388,9 +387,7 @@ set_current_options (bitmap)
}
static int
set_ignoreeof (on_or_off, option_name)
int on_or_off;
char *option_name;
set_ignoreeof (int on_or_off, char *option_name)
{
ignoreeof = on_or_off == FLAG_ON;
unbind_variable_noref ("ignoreeof");
@@ -403,9 +400,7 @@ set_ignoreeof (on_or_off, option_name)
}
static int
set_posix_mode (on_or_off, option_name)
int on_or_off;
char *option_name;
set_posix_mode (int on_or_off, char *option_name)
{
/* short-circuit on no-op */
if ((on_or_off == FLAG_ON && posixly_correct) ||
@@ -424,9 +419,7 @@ set_posix_mode (on_or_off, option_name)
#if defined (READLINE)
/* Magic. This code `knows' how readline handles rl_editing_mode. */
static int
set_edit_mode (on_or_off, option_name)
int on_or_off;
char *option_name;
set_edit_mode (int on_or_off, char *option_name)
{
int isemacs;
@@ -434,7 +427,7 @@ set_edit_mode (on_or_off, option_name)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
if (interactive && command_execution_string == 0)
with_input_from_stdin ();
no_line_editing = 0;
}
@@ -443,7 +436,7 @@ set_edit_mode (on_or_off, option_name)
isemacs = rl_editing_mode == 1;
if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
{
if (interactive)
if (interactive && command_execution_string == 0)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
@@ -452,8 +445,7 @@ set_edit_mode (on_or_off, option_name)
}
static int
get_edit_mode (name)
char *name;
get_edit_mode (char *name)
{
return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
: no_line_editing == 0 && rl_editing_mode == 0);
@@ -462,9 +454,7 @@ get_edit_mode (name)
#if defined (HISTORY)
static int
bash_set_history (on_or_off, option_name)
int on_or_off;
char *option_name;
bash_set_history (int on_or_off, char *option_name)
{
if (on_or_off == FLAG_ON)
{
@@ -483,9 +473,7 @@ bash_set_history (on_or_off, option_name)
#endif
int
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
set_minus_o_option (int on_or_off, char *option_name)
{
register int i;
@@ -515,7 +503,7 @@ set_minus_o_option (on_or_off, option_name)
}
static void
print_all_shell_variables ()
print_all_shell_variables (void)
{
SHELL_VAR **vars;
@@ -540,11 +528,12 @@ print_all_shell_variables ()
}
void
set_shellopts ()
set_shellopts (void)
{
char *value;
char tflag[N_O_OPTIONS];
int vsize, i, vptr, *ip, exported;
int i, *ip, exported;
size_t vsize, vptr;
SHELL_VAR *v;
for (vsize = i = 0; o_options[i].name; i++)
@@ -584,17 +573,12 @@ set_shellopts ()
v = find_variable ("SHELLOPTS");
/* Turn off the read-only attribute so we can bind the new value, and
note whether or not the variable was exported. */
if (v)
{
VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
/* Note whether or not the variable was exported so we can adjust after the
assignment. */
exported = v ? exported_p (v) : 0;
v = bind_variable ("SHELLOPTS", value, 0);
/* ASS_FORCE so we don't have to temporarily turn off readonly */
v = bind_variable ("SHELLOPTS", value, ASS_FORCE);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
@@ -607,8 +591,7 @@ set_shellopts ()
}
void
parse_shellopts (value)
char *value;
parse_shellopts (char *value)
{
char *vname;
int vptr;
@@ -622,8 +605,7 @@ parse_shellopts (value)
}
void
initialize_shell_options (no_shellopts)
int no_shellopts;
initialize_shell_options (int no_shellopts)
{
char *temp;
SHELL_VAR *var;
@@ -651,11 +633,13 @@ initialize_shell_options (no_shellopts)
called from execute_cmd.c:initialize_subshell() when setting up a subshell
to run an executable shell script without a leading `#!'. */
void
reset_shell_options ()
reset_shell_options (void)
{
pipefail_opt = 0;
ignoreeof = 0;
interactive_comments = 1;
#if defined (STRICT_POSIX)
posixly_correct = 1;
#else
@@ -671,8 +655,7 @@ reset_shell_options ()
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
int
set_builtin (list)
WORD_LIST *list;
set_builtin (WORD_LIST *list)
{
int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
register char *arg;
@@ -830,15 +813,26 @@ $END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
#define RESTORE_NAME() \
do { \
tname = name + strlen (name); \
if (tname == t - 1) /* probably a paranoid check */ \
{ \
tname[0] = '['; \
t[strlen (t)] = ']'; \
} \
} while (0)
int
unset_builtin (list)
WORD_LIST *list;
unset_builtin (WORD_LIST *list)
{
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
int global_unset_func, global_unset_var, vflags, base_vflags, valid_id;
int posix_utility_error;
char *name, *tname;
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
unset_function = unset_variable = unset_array = nameref = 0;
posix_utility_error = any_failed = 0;
global_unset_func = global_unset_var = 0;
reset_internal_getopt ();
@@ -873,7 +867,7 @@ unset_builtin (list)
nameref = 0;
#if defined (ARRAY_VARS)
base_vflags = assoc_expand_once ? VA_NOEXPAND : 0;
base_vflags = array_expand_once ? VA_NOEXPAND : 0;
#endif
while (list)
@@ -891,23 +885,26 @@ unset_builtin (list)
#if defined (ARRAY_VARS)
vflags = builtin_arrayref_flags (list->word, base_vflags);
#endif
#if defined (ARRAY_VARS)
unset_array = 0;
/* XXX valid array reference second arg was 0 */
if (!unset_function && nameref == 0 && tokenize_array_reference (name, vflags, &t))
/* XXX tokenize_array_reference modifies NAME if it succeeds */
if (unset_function == 0 && nameref == 0 && tokenize_array_reference (name, vflags, &t))
unset_array = 1;
#endif
/* Get error checking out of the way first. The low-level functions
just perform the unset, relying on the caller to verify. */
valid_id = legal_identifier (name);
valid_id = valid_identifier (name);
/* Whether or not we are in posix mode, if neither -f nor -v appears,
skip over trying to unset variables with invalid names and just
treat them as potential shell function names. */
if (global_unset_func == 0 && global_unset_var == 0 && valid_id == 0)
{
#if defined (ARRAY_VARS)
if (unset_array)
RESTORE_NAME ();
#endif
unset_variable = unset_array = 0;
unset_function = 1;
}
@@ -918,6 +915,7 @@ unset_builtin (list)
if (unset_function == 0 && valid_id == 0)
{
sh_invalidid (name);
posix_utility_error++;
NEXT_VARIABLE ();
}
@@ -930,6 +928,7 @@ unset_builtin (list)
if (var && unset_function == 0 && non_unsettable_p (var))
{
builtin_error (_("%s: cannot unset"), name);
posix_utility_error++;
NEXT_VARIABLE ();
}
@@ -941,8 +940,20 @@ unset_builtin (list)
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 && nameref == 0 && unset_variable == 0 && unset_function == 0)
if (var == 0 && nameref == 0 && unset_variable == 0 && unset_function == 0)
{
#if defined (ARRAY_VARS)
/* We modified NAME in the call to tokenize_array_reference, so we
need to restore it here. We turned the original `[' and `]' into
NULL, to isolate the array name and subscript. This only happens
if tokenize_array_reference succeeds with a non-NULL subscript
pointer, and UNSET_ARRAY is set to 1 only in this case. */
if (unset_array)
{
RESTORE_NAME();
unset_array = 0;
}
#endif
if (var = find_function (name))
unset_function = 1;
}
@@ -952,6 +963,7 @@ unset_builtin (list)
{
builtin_error (_("%s: cannot unset: readonly %s"),
var->name, unset_function ? "function" : "variable");
posix_utility_error++;
NEXT_VARIABLE ();
}
@@ -987,6 +999,7 @@ unset_builtin (list)
int len;
tname = savestring (nameref_cell (var));
tem = 0;
if (var = array_variable_part (tname, 0, &t, &len))
{
/* change to what unbind_array_element now expects */
@@ -1000,16 +1013,22 @@ unset_builtin (list)
#endif
tem = unbind_variable (nameref_cell (var));
}
else if (posixly_correct && var && tempvar_p (var))
tem = posix_unbind_tempvar (name);
else
tem = unbind_variable (name);
}
else if (posixly_correct && unset_function == 0 && nameref == 0 && var && tempvar_p (var))
tem = posix_unbind_tempvar (name);
else
tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
/* 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.'' */
that name does not exist, it is unspecified whether a function
by that name, if any, shall be unset.'' The unspecified part is a
recent addition, so we continue to try to unset a shell function if
we don't find a variable named NAME. */
if (tem == -1 && nameref == 0 && unset_function == 0 && unset_variable == 0)
tem = unbind_func (name);
@@ -1024,5 +1043,5 @@ unset_builtin (list)
list = list->next;
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
return (any_failed ? (posix_utility_error ? EX_UTILERROR : EXECUTION_FAILURE) : EXECUTION_SUCCESS);
}
+54 -46
View File
@@ -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-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -38,16 +38,16 @@ $PRODUCES setattr.c
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
#include "builtext.h"
extern sh_builtin_func_t *this_shell_builtin;
#ifdef ARRAY_VARS
extern int declare_builtin PARAMS((WORD_LIST *));
#endif
#define READONLY_OR_EXPORT \
(this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
#define SPECIAL_LOCAL(n) \
(this_shell_builtin == local_builtin && n[0] == '-' && n[1] == 0)
$BUILTIN export
$FUNCTION export_builtin
$SHORT_DOC export [-fn] [name[=value] ...] or export -p
@@ -73,8 +73,7 @@ $END
exported attribute from variables named in LIST. An argument of
-f indicates that the names present in LIST refer to functions. */
int
export_builtin (list)
register WORD_LIST *list;
export_builtin (WORD_LIST *list)
{
return (set_or_show_attributes (list, att_exported, 0));
}
@@ -104,8 +103,7 @@ $END
/* For each variable name in LIST, make that variable readonly. Given an
empty LIST, print out all existing readonly variables. */
int
readonly_builtin (list)
register WORD_LIST *list;
readonly_builtin (WORD_LIST *list)
{
return (set_or_show_attributes (list, att_readonly, 0));
}
@@ -120,12 +118,10 @@ readonly_builtin (list)
ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
remaining names in LIST (doesn't work for readonly). */
int
set_or_show_attributes (list, attribute, nodefs)
register WORD_LIST *list;
int attribute, nodefs;
set_or_show_attributes (WORD_LIST *list, int attribute, int nodefs)
{
register SHELL_VAR *var;
int assign, undo, any_failed, assign_error, opt;
int assign, undo, any_failed, assign_error, util_error, opt, retval;
int functions_only, arrays_only, assoc_only;
int aflags;
char *name;
@@ -137,7 +133,9 @@ set_or_show_attributes (list, attribute, nodefs)
#endif
functions_only = arrays_only = assoc_only = 0;
undo = any_failed = assign_error = 0;
undo = any_failed = assign_error = util_error = 0;
retval = EXECUTION_SUCCESS;
/* Read arguments from the front of the list. */
reset_internal_getopt ();
while ((opt = internal_getopt (list, ATTROPTS)) != -1)
@@ -215,11 +213,16 @@ set_or_show_attributes (list, attribute, nodefs)
}
}
if (legal_identifier (name) == 0)
if (valid_identifier (name) == 0)
{
sh_invalidid (name);
if (assign)
assign_error++;
else if (posixly_correct)
{
util_error++;
break; /* exit immediately on bad identifier */
}
else
any_failed++;
list = list->next;
@@ -342,16 +345,21 @@ set_or_show_attributes (list, attribute, nodefs)
}
}
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
/* various failure modes */
if (assign_error)
retval = EX_BADASSIGN;
else if (util_error) /* only posix mode sets this */
retval = EX_UTILERROR;
else if (any_failed)
retval = EXECUTION_FAILURE;
return (retval);
}
/* Show all variable variables (v == 1) or functions (v == 0) with
attributes. */
int
show_all_var_attributes (v, nodefs)
int v, nodefs;
show_all_var_attributes (int v, int nodefs)
{
SHELL_VAR **variable_list, *var;
int any_failed;
@@ -378,8 +386,7 @@ show_all_var_attributes (v, nodefs)
/* Show all local variable variables with their attributes. This shows unset
local variables (all_local_variables called with 0 argument). */
int
show_local_var_attributes (v, nodefs)
int v, nodefs;
show_local_var_attributes (int v, int nodefs)
{
SHELL_VAR **variable_list, *var;
int any_failed;
@@ -403,11 +410,9 @@ show_local_var_attributes (v, nodefs)
return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
/* Fill in FLAGS with attribute characters */
int
var_attribute_string (var, pattr, flags)
SHELL_VAR *var;
int pattr;
char *flags; /* filled in with attributes */
var_attribute_string (SHELL_VAR *var, int pattr, char *flags)
{
int i;
@@ -476,9 +481,7 @@ var_attribute_string (var, pattr, flags)
or `readonly') instead of `declare', and doesn't print function defs
when called by `export' or `readonly'. */
int
show_var_attributes (var, pattr, nodefs)
SHELL_VAR *var;
int pattr, nodefs;
show_var_attributes (SHELL_VAR *var, int pattr, int nodefs)
{
char flags[MAX_ATTRIBUTES], *x;
int i;
@@ -533,9 +536,7 @@ show_var_attributes (var, pattr, nodefs)
}
int
show_name_attributes (name, nodefs)
char *name;
int nodefs;
show_name_attributes (char *name, int nodefs)
{
SHELL_VAR *var;
@@ -551,9 +552,7 @@ show_name_attributes (name, nodefs)
}
int
show_localname_attributes (name, nodefs)
char *name;
int nodefs;
show_localname_attributes (char *name, int nodefs)
{
SHELL_VAR *var;
@@ -561,7 +560,11 @@ show_localname_attributes (name, nodefs)
if (var && local_p (var) && var->context == variable_context) /* show every variable with attributes, even unset ones */
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
/* There is no equivalent `declare -'. */
if (STREQ (var->name, "-"))
printf ("local -\n");
else
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
return (0);
}
else
@@ -569,9 +572,7 @@ show_localname_attributes (name, nodefs)
}
int
show_func_attributes (name, nodefs)
char *name;
int nodefs;
show_func_attributes (char *name, int nodefs)
{
SHELL_VAR *var;
@@ -586,10 +587,10 @@ show_func_attributes (name, nodefs)
return (1);
}
/* This is only called by readonly/export, so we can implement posix-mode
semantics for special variables. */
void
set_var_attribute (name, attribute, undo)
char *name;
int attribute, undo;
set_var_attribute (char *name, int attribute, int undo)
{
SHELL_VAR *var, *tv, *v, *refvar;
char *tvalue;
@@ -598,10 +599,8 @@ set_var_attribute (name, attribute, undo)
var = find_variable (name);
else
{
/* var=value readonly var */
tv = find_tempenv_variable (name);
/* XXX -- need to handle case where tv is a temp variable in a
function-scope context, since function_env has been merged into
the local variables table. */
if (tv && tempvar_p (tv))
{
tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
@@ -640,6 +639,9 @@ set_var_attribute (name, attribute, undo)
}
else
{
/* Handle case where var is a temp variable in a function-scope
context, since function_env has been merged into the local
variables table (see below). */
var = find_variable_notempenv (name);
if (var == 0)
{
@@ -659,7 +661,13 @@ set_var_attribute (name, attribute, undo)
if (var)
VSETATTR (var, att_invisible);
}
else if (var->context != 0)
/* We don't want to do this for local variables or variables we found
in previous temporary environment contexts. */
#if 0
else if (var->context != 0 && local_p (var) == 0)
#else
else if (var->context != 0 && local_p (var) == 0 && tempvar_p (var) == 0)
#endif
VSETATTR (var, att_propagate);
}
}
+13 -5
View File
@@ -1,7 +1,7 @@
This file is shift.def, from which is created shift.c.
It implements the builtin "shift" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -54,8 +54,7 @@ int print_shift_error;
anything in it, it is a number which says where to start the
shifting. Return > 0 if `times' > $#, otherwise 0. */
int
shift_builtin (list)
WORD_LIST *list;
shift_builtin (WORD_LIST *list)
{
intmax_t times;
int itimes, nargs;
@@ -63,12 +62,15 @@ shift_builtin (list)
CHECK_HELPOPT (list);
if (get_numeric_arg (list, 0, &times) == 0)
return (EXECUTION_FAILURE);
return (EX_USAGE);
if (times == 0)
return (EXECUTION_SUCCESS);
else if (times < 0)
{
/* skip over `--' option to get the right error message */
if (list && list->word && ISOPTION (list->word->word, '-'))
list = list->next;
sh_erange (list ? list->word->word : NULL, _("shift count"));
return (EXECUTION_FAILURE);
}
@@ -76,7 +78,13 @@ shift_builtin (list)
if (times > nargs)
{
if (print_shift_error)
sh_erange (list ? list->word->word : NULL, _("shift count"));
{
/* skip over `--' option to get the right error message */
if (list && list->word && ISOPTION (list->word->word, '-'))
list = list->next;
sh_erange (list ? list->word->word : NULL, _("shift count"));
}
return (EXECUTION_FAILURE);
}
else if (times == nargs)
+69 -111
View File
@@ -1,7 +1,7 @@
This file is shopt.def, from which is created shopt.c.
It implements the Bash `shopt' builtin.
Copyright (C) 1994-2021 Free Software Foundation, Inc.
Copyright (C) 1994-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -109,7 +109,7 @@ extern int force_fignore;
extern int dircomplete_spelling, dircomplete_expand;
extern int complete_fullquote;
extern int enable_hostname_completion PARAMS((int));
extern int enable_hostname_completion (int);
#endif
#if defined (PROGRAMMABLE_COMPLETION)
@@ -122,7 +122,6 @@ extern int debugging_mode;
#endif
#if defined (ARRAY_VARS)
extern int assoc_expand_once;
extern int array_expand_once;
int expand_once_flag;
#endif
@@ -131,33 +130,33 @@ int expand_once_flag;
extern int syslog_history;
#endif
static void shopt_error PARAMS((char *));
static void shopt_error (char *);
static int set_shellopts_after_change PARAMS((char *, int));
static int set_compatibility_level PARAMS((char *, int));
static int set_shellopts_after_change (char *, int);
static int set_compatibility_level (char *, int);
#if defined (RESTRICTED_SHELL)
static int set_restricted_shell PARAMS((char *, int));
static int set_restricted_shell (char *, int);
#endif
#if defined (READLINE)
static int shopt_enable_hostname_completion PARAMS((char *, int));
static int shopt_set_complete_direxpand PARAMS((char *, int));
static int shopt_enable_hostname_completion (char *, int);
static int shopt_set_complete_direxpand (char *, int);
#endif
#if defined (ARRAY_VARS)
static int set_assoc_expand PARAMS((char *, int));
static int set_array_expand (char *, int);
#endif
#if defined (EXTENDED_GLOB)
int extglob_flag = EXTGLOB_DEFAULT;
static int shopt_set_extglob PARAMS((char *, int));
static int shopt_set_extglob (char *, int);
#endif
int expaliases_flag = 0;
static int shopt_set_expaliases PARAMS((char *, int));
static int shopt_set_expaliases (char *, int);
static int shopt_set_debug_mode PARAMS((char *, int));
static int shopt_set_debug_mode (char *, int);
static int shopt_login_shell;
static int shopt_compat31;
@@ -168,7 +167,7 @@ static int shopt_compat42;
static int shopt_compat43;
static int shopt_compat44;
typedef int shopt_set_func_t PARAMS((char *, int));
typedef int shopt_set_func_t (char *, int);
/* If you add a new variable name here, make sure to set the default value
appropriately in reset_shopt_options. */
@@ -180,7 +179,8 @@ static struct {
} shopt_vars[] = {
{ "autocd", &autocd, (shopt_set_func_t *)NULL },
#if defined (ARRAY_VARS)
{ "assoc_expand_once", &expand_once_flag, set_assoc_expand },
{ "array_expand_once", &expand_once_flag, set_array_expand },
{ "assoc_expand_once", &expand_once_flag, set_array_expand },
#endif
{ "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL },
{ "cdspell", &cdspelling, (shopt_set_func_t *)NULL },
@@ -276,14 +276,14 @@ static struct {
static const char * const on = "on";
static const char * const off = "off";
static int find_shopt PARAMS((char *));
static int toggle_shopts PARAMS((int, WORD_LIST *, int));
static void print_shopt PARAMS((char *, int, int));
static int list_shopts PARAMS((WORD_LIST *, int));
static int list_some_shopts PARAMS((int, int));
static int list_shopt_o_options PARAMS((WORD_LIST *, int));
static int list_some_o_options PARAMS((int, int));
static int set_shopt_o_options PARAMS((int, WORD_LIST *, int));
static int find_shopt (char *);
static int toggle_shopts (int, WORD_LIST *, int);
static void print_shopt (char *, int, int);
static int list_shopts (WORD_LIST *, int);
static int list_some_shopts (int, int);
static int list_shopt_o_options (WORD_LIST *, int);
static int list_some_o_options (int, int);
static int set_shopt_o_options (int, WORD_LIST *, int);
#define SFLAG 0x01
#define UFLAG 0x02
@@ -292,8 +292,7 @@ static int set_shopt_o_options PARAMS((int, WORD_LIST *, int));
#define PFLAG 0x10
int
shopt_builtin (list)
WORD_LIST *list;
shopt_builtin (WORD_LIST *list)
{
int opt, flags, rval;
@@ -351,7 +350,7 @@ shopt_builtin (list)
/* Reset the options managed by `shopt' to the values they would have at
shell startup. Variables from shopt_vars. */
void
reset_shopt_options ()
reset_shopt_options (void)
{
autocd = cdable_vars = cdspelling = 0;
check_hashed_filenames = CHECKHASH_DEFAULT;
@@ -375,7 +374,7 @@ reset_shopt_options ()
source_uses_path = promptvars = 1;
varassign_redir_autoclose = 0;
singlequote_translations = 0;
patsub_replacement = 1;
patsub_replacement = PATSUB_REPLACE_DEFAULT;
#if defined (JOB_CONTROL)
check_jobs_at_exit = 0;
@@ -384,9 +383,10 @@ reset_shopt_options ()
#if defined (EXTENDED_GLOB)
extended_glob = extglob_flag = EXTGLOB_DEFAULT;
#endif
glob_always_skip_dot_and_dotdot = 1; /* new default as of bash-5.2 */
#if defined (ARRAY_VARS)
expand_once_flag = assoc_expand_once = 0;
expand_once_flag = array_expand_once = 0;
#endif
#if defined (HISTORY)
@@ -430,12 +430,15 @@ reset_shopt_options ()
xpg_echo = 0;
#endif /* DEFAULT_ECHO_TO_XPG */
#if defined (DEBUGGER)
debugging_mode = 0;
#endif
shopt_login_shell = login_shell;
}
static int
find_shopt (name)
char *name;
find_shopt (char *name)
{
int i;
@@ -446,17 +449,13 @@ find_shopt (name)
}
static void
shopt_error (s)
char *s;
shopt_error (char *s)
{
builtin_error (_("%s: invalid shell option name"), s);
}
static int
toggle_shopts (mode, list, quiet)
int mode;
WORD_LIST *list;
int quiet;
toggle_shopts (int mode, WORD_LIST *list, int quiet)
{
WORD_LIST *l;
int ind, rval;
@@ -485,9 +484,7 @@ toggle_shopts (mode, list, quiet)
}
static void
print_shopt (name, val, flags)
char *name;
int val, flags;
print_shopt (char *name, int val, int flags)
{
if (flags & PFLAG)
printf ("shopt %s %s\n", val ? "-s" : "-u", name);
@@ -498,9 +495,7 @@ print_shopt (name, val, flags)
/* List the values of all or any of the `shopt' options. Returns 0 if
all were listed or all variables queried were on; 1 otherwise. */
static int
list_shopts (list, flags)
WORD_LIST *list;
int flags;
list_shopts (WORD_LIST *list, int flags)
{
WORD_LIST *l;
int i, val, rval;
@@ -536,8 +531,7 @@ list_shopts (list, flags)
}
static int
list_some_shopts (mode, flags)
int mode, flags;
list_some_shopts (int mode, int flags)
{
int val, i;
@@ -551,9 +545,7 @@ list_some_shopts (mode, flags)
}
static int
list_shopt_o_options (list, flags)
WORD_LIST *list;
int flags;
list_shopt_o_options (WORD_LIST *list, int flags)
{
WORD_LIST *l;
int val, rval;
@@ -588,8 +580,7 @@ list_shopt_o_options (list, flags)
}
static int
list_some_o_options (mode, flags)
int mode, flags;
list_some_o_options (int mode, int flags)
{
if ((flags & QFLAG) == 0)
list_minus_o_opts (mode, (flags & PFLAG));
@@ -597,10 +588,7 @@ list_some_o_options (mode, flags)
}
static int
set_shopt_o_options (mode, list, quiet)
int mode;
WORD_LIST *list;
int quiet;
set_shopt_o_options (int mode, WORD_LIST *list, int quiet)
{
WORD_LIST *l;
int rval;
@@ -617,18 +605,14 @@ set_shopt_o_options (mode, list, quiet)
/* If we set or unset interactive_comments with shopt, make sure the
change is reflected in $SHELLOPTS. */
static int
set_shellopts_after_change (option_name, mode)
char *option_name;
int mode;
set_shellopts_after_change (char *option_name, int mode)
{
set_shellopts ();
return (0);
}
static int
shopt_set_debug_mode (option_name, mode)
char *option_name;
int mode;
shopt_set_debug_mode (char *option_name, int mode)
{
#if defined (DEBUGGER)
error_trace_mode = function_trace_mode = debugging_mode;
@@ -640,9 +624,7 @@ shopt_set_debug_mode (option_name, mode)
}
static int
shopt_set_expaliases (option_name, mode)
char *option_name;
int mode;
shopt_set_expaliases (char *option_name, int mode)
{
expand_aliases = expaliases_flag;
return 0;
@@ -650,9 +632,7 @@ shopt_set_expaliases (option_name, mode)
#if defined (EXTENDED_GLOB)
static int
shopt_set_extglob (option_name, mode)
char *option_name;
int mode;
shopt_set_extglob (char *option_name, int mode)
{
extended_glob = extglob_flag;
return 0;
@@ -661,26 +641,21 @@ shopt_set_extglob (option_name, mode)
#if defined (READLINE)
static int
shopt_enable_hostname_completion (option_name, mode)
char *option_name;
int mode;
shopt_enable_hostname_completion (char *option_name, int mode)
{
return (enable_hostname_completion (mode));
}
#endif
static int
set_compatibility_level (option_name, mode)
char *option_name;
int mode;
set_compatibility_level (char *option_name, int mode)
{
int ind, oldval;
char *rhs;
/* If we're unsetting one of the compatibility options, make sure the
current value is in the range of the compatNN space. */
if (mode == 0)
oldval = shell_compatibility_level;
oldval = (mode == 0) ? shell_compatibility_level : 0;
/* If we're setting something, redo some of the work we did above in
toggle_shopt(). Unset everything and reset the appropriate option
@@ -725,7 +700,7 @@ set_compatibility_level (option_name, mode)
/* Set and unset the various compatibility options from the value of
shell_compatibility_level; used by sv_shcompat */
void
set_compatibility_opts ()
set_compatibility_opts (void)
{
shopt_compat31 = shopt_compat32 = 0;
shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0;
@@ -755,9 +730,7 @@ set_compatibility_opts ()
#if defined (READLINE)
static int
shopt_set_complete_direxpand (option_name, mode)
char *option_name;
int mode;
shopt_set_complete_direxpand (char *option_name, int mode)
{
set_directory_hook ();
return 0;
@@ -768,9 +741,7 @@ shopt_set_complete_direxpand (option_name, mode)
/* Don't allow the value of restricted_shell to be modified. */
static int
set_restricted_shell (option_name, mode)
char *option_name;
int mode;
set_restricted_shell (char *option_name, int mode)
{
static int save_restricted = -1;
@@ -784,19 +755,18 @@ set_restricted_shell (option_name, mode)
/* Not static so shell.c can call it to initialize shopt_login_shell */
int
set_login_shell (option_name, mode)
char *option_name;
int mode;
set_login_shell (char *option_name, int mode)
{
shopt_login_shell = login_shell != 0;
return (0);
}
char **
get_shopt_options ()
get_shopt_options (void)
{
char **ret;
int n, i;
int i;
size_t n;
n = sizeof (shopt_vars) / sizeof (shopt_vars[0]);
ret = strvec_create (n + 1);
@@ -812,9 +782,7 @@ get_shopt_options ()
* REUSABLE is 1 if we want to print output in a form that may be reused.
*/
int
shopt_setopt (name, mode)
char *name;
int mode;
shopt_setopt (char *name, int mode)
{
WORD_LIST *wl;
int r;
@@ -826,9 +794,7 @@ shopt_setopt (name, mode)
}
int
shopt_listopt (name, reusable)
char *name;
int reusable;
shopt_listopt (char *name, int reusable)
{
int i;
@@ -847,11 +813,12 @@ shopt_listopt (name, reusable)
}
void
set_bashopts ()
set_bashopts (void)
{
char *value;
char tflag[N_SHOPT_OPTIONS];
int vsize, i, vptr, *ip, exported;
int i, exported;
size_t vsize, vptr;
SHELL_VAR *v;
for (vsize = i = 0; shopt_vars[i].name; i++)
@@ -882,17 +849,12 @@ set_bashopts ()
v = find_variable ("BASHOPTS");
/* Turn off the read-only attribute so we can bind the new value, and
note whether or not the variable was exported. */
if (v)
{
VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
/* Note whether or not the variable was exported so we can adjust after the
assignment. */
exported = v ? exported_p (v) : 0;
v = bind_variable ("BASHOPTS", value, 0);
/* ASS_FORCE so we don't have to temporarily turn off readonly */
v = bind_variable ("BASHOPTS", value, ASS_FORCE);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
@@ -905,8 +867,7 @@ set_bashopts ()
}
void
parse_bashopts (value)
char *value;
parse_bashopts (char *value)
{
char *vname;
int vptr, ind;
@@ -926,8 +887,7 @@ parse_bashopts (value)
}
void
initialize_bashopts (no_bashopts)
int no_bashopts;
initialize_bashopts (int no_bashopts)
{
char *temp;
SHELL_VAR *var;
@@ -953,14 +913,12 @@ initialize_bashopts (no_bashopts)
#if defined (ARRAY_VARS)
static int
set_assoc_expand (option_name, mode)
char *option_name;
int mode;
set_array_expand (char *option_name, int mode)
{
#if 0 /* leave this disabled */
if (shell_compatibility_level <= 51)
#endif
assoc_expand_once = expand_once_flag;
array_expand_once = expand_once_flag;
return 0;
}
#endif
+6 -7
View File
@@ -1,7 +1,7 @@
This file is source.def, from which is created source.c.
It implements the builtins "." and "source" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -80,7 +80,7 @@ $END
extern int errno;
#endif /* !errno */
static void maybe_pop_dollar_vars PARAMS((void));
static void uw_maybe_pop_dollar_vars (void *);
/* If non-zero, `.' uses $PATH to look up the script to be sourced. */
int source_uses_path = 1;
@@ -96,7 +96,7 @@ int source_searches_cwd = 1;
not executing a shell function, we leave the new values alone and free
the saved values. */
static void
maybe_pop_dollar_vars ()
uw_maybe_pop_dollar_vars (void *ignore)
{
if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN))
dispose_saved_dollar_vars ();
@@ -113,8 +113,7 @@ maybe_pop_dollar_vars ()
take place in there. So, I open the file, place it into a large string,
close the file, and then execute the string. */
int
source_builtin (list)
WORD_LIST *list;
source_builtin (WORD_LIST *list)
{
int result;
char *filename, *debug_trap, *x;
@@ -171,7 +170,7 @@ source_builtin (list)
if (list->next)
{
push_dollar_vars ();
add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
add_unwind_protect (uw_maybe_pop_dollar_vars, NULL);
if (debugging_mode || shell_compatibility_level <= 44)
init_bash_argv (); /* Initialize BASH_ARGV and BASH_ARGC */
remember_args (list->next, 1);
@@ -188,7 +187,7 @@ source_builtin (list)
{
debug_trap = savestring (debug_trap);
add_unwind_protect (xfree, debug_trap);
add_unwind_protect (maybe_set_debug_trap, debug_trap);
add_unwind_protect (uw_maybe_set_debug_trap, debug_trap);
restore_default_signal (DEBUG_TRAP);
}
+4 -6
View File
@@ -56,7 +56,7 @@ $END
#include "common.h"
#include "bashgetopt.h"
static sighandler suspend_continue PARAMS((int));
static sighandler suspend_continue (int);
static SigHandler *old_cont;
#if 0
@@ -65,8 +65,7 @@ static SigHandler *old_stop;
/* Continue handler. */
static sighandler
suspend_continue (sig)
int sig;
suspend_continue (int sig)
{
set_signal_handler (SIGCONT, old_cont);
#if 0
@@ -78,8 +77,7 @@ suspend_continue (sig)
/* Suspending the shell. If -f is the arg, then do the suspend
no matter what. Otherwise, complain if a login shell. */
int
suspend_builtin (list)
WORD_LIST *list;
suspend_builtin (WORD_LIST *list)
{
int opt, force;
@@ -98,7 +96,7 @@ suspend_builtin (list)
}
list = loptend;
no_args (list);
no_args (list, 0);
if (force == 0)
{
+2 -3
View File
@@ -1,7 +1,7 @@
This file is test.def, from which is created test.c.
It implements the builtin "test" in Bash.
Copyright (C) 1987-2015 Free Software Foundation, Inc.
Copyright (C) 1987-2015,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -131,8 +131,7 @@ $END
/* TEST/[ builtin. */
int
test_builtin (list)
WORD_LIST *list;
test_builtin (WORD_LIST *list)
{
char **argv;
int argc, result;
+6 -4
View File
@@ -1,7 +1,7 @@
This file is times.def, from which is created times.c.
It implements the builtin "times" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
Copyright (C) 1987-2009,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -43,7 +43,6 @@ $END
#include <stdio.h>
#include "../bashtypes.h"
#include "../shell.h"
#include <posixtime.h>
@@ -55,12 +54,15 @@ $END
# include <sys/resource.h>
#endif
#define NEED_CLOCK_FUNCS_DECL
#define NEED_TIMEVAL_FUNCS_DECL
#include "../shell.h"
#include "common.h"
/* Print the totals for system and user time used. */
int
times_builtin (list)
WORD_LIST *list;
times_builtin (WORD_LIST *list)
{
#if defined (HAVE_GETRUSAGE) && defined (HAVE_TIMEVAL) && defined (RUSAGE_SELF)
struct rusage self, kids;
+90 -38
View File
@@ -1,7 +1,7 @@
This file is trap.def, from which is created trap.c.
It implements the builtin "trap" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -22,31 +22,38 @@ $PRODUCES trap.c
$BUILTIN trap
$FUNCTION trap_builtin
$SHORT_DOC trap [-lp] [[arg] signal_spec ...]
$SHORT_DOC trap [-Plp] [[action] signal_spec ...]
Trap signals and other events.
Defines and activates handlers to be run when the shell receives signals
or other conditions.
ARG is a command to be read and executed when the shell receives the
signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC
ACTION is a command to be read and executed when the shell receives the
signal(s) SIGNAL_SPEC. If ACTION is absent (and a single SIGNAL_SPEC
is supplied) or `-', each specified signal is reset to its original
value. If ARG is the null string each SIGNAL_SPEC is ignored by the
value. If ACTION is the null string each SIGNAL_SPEC is ignored by the
shell and by the commands it invokes.
If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If
a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a
script run by the . or source builtins finishes executing. A SIGNAL_SPEC
of ERR means to execute ARG each time a command's failure would cause the
shell to exit when the -e option is enabled.
If a SIGNAL_SPEC is EXIT (0) ACTION is executed on exit from the shell.
If a SIGNAL_SPEC is DEBUG, ACTION is executed before every simple command
and selected other commands. If a SIGNAL_SPEC is RETURN, ACTION is
executed each time a shell function or a script run by the . or source
builtins finishes executing. A SIGNAL_SPEC of ERR means to execute ACTION
each time a command's failure would cause the shell to exit when the -e
option is enabled.
If no arguments are supplied, trap prints the list of commands associated
with each signal.
with each trapped signal in a form that may be reused as shell input to
restore the same signal dispositions.
Options:
-l print a list of signal names and their corresponding numbers
-p display the trap commands associated with each SIGNAL_SPEC
-p display the trap commands associated with each SIGNAL_SPEC in a
form that may be reused as shell input; or for all trapped
signals if no arguments are supplied
-P display the trap commands associated with each SIGNAL_SPEC. At least
one SIGNAL_SPEC must be supplied. -P and -p cannot be used
together.
Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.
Signal names are case insensitive and the SIG prefix is optional. A
@@ -75,13 +82,13 @@ $END
#include "common.h"
#include "bashgetopt.h"
static void showtrap PARAMS((int, int));
static int display_traps PARAMS((WORD_LIST *, int));
static void showtrap (int, int);
static int display_traps (WORD_LIST *, int);
/* The trap command:
trap <arg> <signal ...>
trap <signal ...>
trap <action> <sigspec ...>
trap <signum ...>
trap -l
trap -p [sigspec ...]
trap [--]
@@ -97,17 +104,21 @@ static int display_traps PARAMS((WORD_LIST *, int));
#define REVERT 1 /* Revert to this signals original value. */
#define IGNORE 2 /* Ignore this signal. */
int
trap_builtin (list)
WORD_LIST *list;
{
int list_signal_names, display, result, opt;
/* Flags saying how to display the trap list. */
#define DISP_TRAPCMD 1
#define DISP_ALLSIGS 2
#define DISP_ACTIONONLY 4
list_signal_names = display = 0;
int
trap_builtin (WORD_LIST *list)
{
int list_signal_names, result, opt, dflags;
list_signal_names = dflags = 0;
result = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lp")) != -1)
while ((opt = internal_getopt (list, "lpP")) != -1)
{
switch (opt)
{
@@ -115,7 +126,10 @@ trap_builtin (list)
list_signal_names++;
break;
case 'p':
display++;
dflags |= DISP_TRAPCMD;
break;
case 'P':
dflags |= DISP_ACTIONONLY;
break;
CASE_HELPOPT;
default:
@@ -127,13 +141,26 @@ trap_builtin (list)
opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
if ((dflags & DISP_TRAPCMD) && (dflags & DISP_ACTIONONLY))
{
builtin_error ("cannot specify both -p and -P");
return EX_USAGE;
}
if ((dflags & DISP_ACTIONONLY) && list == 0)
{
builtin_error ("-P requires at least one signal name");
return EX_USAGE;
}
if (list_signal_names)
return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
else if (display || list == 0)
else if (dflags || list == 0)
{
initialize_terminating_signals ();
get_all_original_signals ();
return (sh_chkwrite (display_traps (list, display && posixly_correct)));
if (dflags & DISP_TRAPCMD)
dflags |= posixly_correct ? DISP_ALLSIGS : 0;
return (sh_chkwrite (display_traps (list, dflags)));
}
else
{
@@ -207,7 +234,13 @@ trap_builtin (list)
{
case SIGINT:
/* XXX - should we do this if original disposition
was SIG_IGN? */
was SIG_IGN? Yes, because setup_async_signals can
set the original disposition to SIG_IGN to keep
restore_signal from restoring the SIGINT
disposition from when the shell was invoked, and
we want to allow an asynchronous subshell to
use `trap' to restore the default disposition or
set a trap command. */
if (interactive)
set_signal_handler (SIGINT, sigint_sighandler);
/* special cases for interactive == 0 */
@@ -218,8 +251,13 @@ trap_builtin (list)
break;
case SIGQUIT:
/* Always ignore SIGQUIT. */
set_signal_handler (SIGQUIT, SIG_IGN);
/* Always ignore SIGQUIT, but allow a posix-mode shell
that is running asynchronously and has ignored
SIGQUIT to reset it to the default. POSIX interp 751. */
if (posixly_correct && signal_is_async_ignored (SIGQUIT))
set_signal_handler (SIGQUIT, termsig_sighandler);
else
set_signal_handler (SIGQUIT, SIG_IGN);
break;
case SIGTERM:
#if defined (JOB_CONTROL)
@@ -246,8 +284,7 @@ trap_builtin (list)
}
static void
showtrap (i, show_default)
int i, show_default;
showtrap (int i, int show_default)
{
char *t, *p, *sn;
int free_t;
@@ -286,13 +323,18 @@ showtrap (i, show_default)
FREE (t);
}
static int
display_traps (list, show_all)
WORD_LIST *list;
int show_all;
{
int result, i;
/* Flags saying how to display the trap list. */
#define DISP_TRAPCMD 1
#define DISP_ALLSIGS 2
#define DISP_ACTIONONLY 4
static int
display_traps (WORD_LIST *list, int flags)
{
int result, i, show_all;
show_all = flags & DISP_ALLSIGS;
if (list == 0)
{
for (i = 0; i < BASH_NSIG; i++)
@@ -308,6 +350,16 @@ display_traps (list, show_all)
sh_invalidsig (list->word->word);
result = EXECUTION_FAILURE;
}
else if (flags & DISP_ACTIONONLY)
{
char *t;
t = trap_list[i];
if (t == (char *)DEFAULT_SIG || signal_is_hard_ignored (i))
continue;
else if (t == (char *)IGNORE_SIG)
t = "";
printf ("%s\n", t);
}
else
showtrap (i, show_all);
}
+31 -14
View File
@@ -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-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -64,6 +64,7 @@ $END
#include "../bashintl.h"
#include "../shell.h"
#include "../builtins.h"
#include "../parser.h"
#include "../execute_cmd.h"
#include "../findcmd.h"
@@ -76,8 +77,6 @@ $END
#include "common.h"
#include "bashgetopt.h"
extern int find_reserved_word PARAMS((char *));
/* For each word in LIST, find out what the shell is going to do with
it as a simple command. i.e., which file would this shell use to
execve, or if it is a builtin command, or an alias. Possible flag
@@ -107,8 +106,7 @@ extern int find_reserved_word PARAMS((char *));
*/
int
type_builtin (list)
WORD_LIST *list;
type_builtin (WORD_LIST *list)
{
int dflags, any_failed, opt;
WORD_LIST *this;
@@ -163,7 +161,7 @@ type_builtin (list)
dflags |= CDESC_TYPE;
dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
break;
case 'P': /* shorthand for type -ap */
case 'P': /* force path search only plus hash table lookup */
dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
break;
@@ -210,11 +208,9 @@ type_builtin (list)
* return after finding it once.
*/
int
describe_command (command, dflags)
char *command;
int dflags;
describe_command (char *command, int dflags)
{
int found, i, found_file, f, all;
int found, i, found_file, f, all, skipbuiltin;
char *full_path, *x, *pathlist;
SHELL_VAR *func;
#if defined (ALIAS)
@@ -242,7 +238,7 @@ describe_command (command, dflags)
found = 1;
if (all == 0)
if (all == 0) /* type -p returns, any executable file would not have precedence */
return (1);
}
#endif /* ALIAS */
@@ -263,6 +259,24 @@ describe_command (command, dflags)
return (1);
}
/* In posix mode, we find special builtins before shell functions. */
/* find_shell_builtin sets current_builtin as a side effect */
skipbuiltin = 0;
if (posixly_correct && (dflags & CDESC_FORCE_PATH) == 0 && find_shell_builtin (command) != 0 && (current_builtin->flags & SPECIAL_BUILTIN))
{
if (dflags & CDESC_TYPE)
puts ("builtin");
else if (dflags & CDESC_SHORTDESC)
printf (_("%s is a special shell builtin\n"), command);
else if (dflags & CDESC_REUSABLE)
printf ("%s\n", command);
skipbuiltin = found = 1;
if (all == 0)
return (1);
}
/* Command is a function? */
if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
{
@@ -289,13 +303,14 @@ describe_command (command, dflags)
}
/* Command is a builtin? */
if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
/* find_shell_builtin sets current_builtin as a side effect */
if (skipbuiltin == 0 && ((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
{
if (dflags & CDESC_TYPE)
puts ("builtin");
else if (dflags & CDESC_SHORTDESC)
{
if (posixly_correct && find_special_builtin (command) != 0)
if (posixly_correct && (current_builtin->flags & SPECIAL_BUILTIN))
printf (_("%s is a special shell builtin\n"), command);
else
printf (_("%s is a shell builtin\n"), command);
@@ -345,7 +360,8 @@ describe_command (command, dflags)
printf ("%s\n", full_path);
free (full_path);
return (1);
if (all == 0)
return (1);
}
}
@@ -371,6 +387,7 @@ describe_command (command, dflags)
probably doesn't exist. Check whether or not the command is an
executable file. If it's not, don't report a match. This is
the default posix mode behavior */
/* This code path isn't executed any more as of 3/2023. */
if (STREQ (full_path, command) || posixly_correct)
{
f = file_status (full_path);
+44 -55
View File
@@ -1,7 +1,7 @@
This file is ulimit.def, from which is created ulimit.c.
It implements the builtin "ulimit" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -63,9 +63,10 @@ current soft limit, the current hard limit, and no limit, respectively.
Otherwise, the current value of the specified resource is printed. If
no option is given, then -f is assumed.
Values are in 1024-byte increments, except for -t, which is in seconds,
-p, which is in increments of 512 bytes, and -u, which is an unscaled
number of processes.
Values are in 1024-byte increments, except for -t, which is in seconds;
-p, which is in increments of 512 bytes; -R, which is in microseconds;
-b, which is in bytes; and -e, -i, -k, -n, -q, -r, -u, -x, and -P,
which accept unscaled values.
Exit Status:
Returns success unless an invalid option is supplied or an error occurs.
@@ -93,6 +94,7 @@ $END
#include "common.h"
#include "bashgetopt.h"
#include "pipesize.h"
#include <chartypes.h>
#if !defined (errno)
extern int errno;
@@ -130,7 +132,7 @@ extern int errno;
#if !defined (RLIMTYPE)
# define RLIMTYPE long
# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
# define string_to_rlimtype(s, ep) strtol(s, ep, 10)
# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
#endif
@@ -204,22 +206,22 @@ extern int errno;
#define BLOCKSIZE(x) (((x) == POSIXBLK) ? (posixly_correct ? 512 : 1024) : (x))
static int _findlim PARAMS((int));
static int _findlim (int);
static int ulimit_internal PARAMS((int, char *, int, int));
static int ulimit_internal (int, char *, int, int);
static int get_limit PARAMS((int, RLIMTYPE *, RLIMTYPE *));
static int set_limit PARAMS((int, RLIMTYPE, int));
static int get_limit (int, RLIMTYPE *, RLIMTYPE *);
static int set_limit (int, RLIMTYPE, int);
static void printone PARAMS((int, RLIMTYPE, int));
static void print_all_limits PARAMS((int));
static void printone (int, RLIMTYPE, int);
static void print_all_limits (int);
static int set_all_limits PARAMS((int, RLIMTYPE));
static int set_all_limits (int, RLIMTYPE);
static int filesize PARAMS((RLIMTYPE *));
static int pipesize PARAMS((RLIMTYPE *));
static int getmaxuprc PARAMS((RLIMTYPE *));
static int getmaxvm PARAMS((RLIMTYPE *, RLIMTYPE *));
static int filesize (RLIMTYPE *);
static int pipesize (RLIMTYPE *);
static int getmaxuprc (RLIMTYPE *);
static int getmaxvm (RLIMTYPE *, RLIMTYPE *);
typedef struct {
int option; /* The ulimit option for this limit. */
@@ -299,13 +301,11 @@ typedef struct _cmd {
static ULCMD *cmdlist;
static int ncmd;
static int cmdlistsz;
static size_t cmdlistsz;
#if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
long
ulimit (cmd, newlim)
int cmd;
long newlim;
ulimit (int cmd, long newlim)
{
errno = EINVAL;
return -1;
@@ -313,8 +313,7 @@ ulimit (cmd, newlim)
#endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
static int
_findlim (opt)
int opt;
_findlim (int opt)
{
register int i;
@@ -329,8 +328,7 @@ static char optstring[4 + 2 * NCMDS];
/* Report or set limits associated with certain per-process resources.
See the help documentation in builtins.c for a full description. */
int
ulimit_builtin (list)
register WORD_LIST *list;
ulimit_builtin (WORD_LIST *list)
{
register char *s;
int c, limind, mode, opt, all_limits;
@@ -441,14 +439,11 @@ ulimit_builtin (list)
if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
return (EXECUTION_FAILURE);
return (EXECUTION_SUCCESS);
return (sh_chkwrite (EXECUTION_SUCCESS));
}
static int
ulimit_internal (cmd, cmdarg, mode, multiple)
int cmd;
char *cmdarg;
int mode, multiple;
ulimit_internal (int cmd, char *cmdarg, int mode, int multiple)
{
int opt, limind, setting;
int block_factor;
@@ -479,9 +474,16 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
real_limit = soft_limit;
else if (STREQ (cmdarg, "unlimited"))
real_limit = RLIM_INFINITY;
else if (all_digits (cmdarg))
else if (DIGIT (*cmdarg) && (cmdarg[1] == 0 || DIGIT (cmdarg[1])))
{
limit = string_to_rlimtype (cmdarg);
char *endp;
limit = string_to_rlimtype (cmdarg, &endp);
if (*endp != '\0')
{
sh_invalidnum (cmdarg);
return (EXECUTION_FAILURE);
}
block_factor = BLOCKSIZE(limits[limind].block_factor);
real_limit = limit * block_factor;
@@ -508,9 +510,7 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
}
static int
get_limit (ind, softlim, hardlim)
int ind;
RLIMTYPE *softlim, *hardlim;
get_limit (int ind, RLIMTYPE *softlim, RLIMTYPE *hardlim)
{
RLIMTYPE value;
#if defined (HAVE_RESOURCE)
@@ -569,10 +569,7 @@ get_limit (ind, softlim, hardlim)
}
static int
set_limit (ind, newlim, mode)
int ind;
RLIMTYPE newlim;
int mode;
set_limit (int ind, RLIMTYPE newlim, int mode)
{
#if defined (HAVE_RESOURCE)
struct rlimit limit;
@@ -634,8 +631,7 @@ set_limit (ind, newlim, mode)
}
static int
getmaxvm (softlim, hardlim)
RLIMTYPE *softlim, *hardlim;
getmaxvm (RLIMTYPE *softlim, RLIMTYPE *hardlim)
{
#if defined (HAVE_RESOURCE)
struct rlimit datalim, stacklim;
@@ -657,8 +653,7 @@ getmaxvm (softlim, hardlim)
}
static int
filesize(valuep)
RLIMTYPE *valuep;
filesize (RLIMTYPE *valuep)
{
#if !defined (HAVE_RESOURCE)
long result;
@@ -674,8 +669,7 @@ filesize(valuep)
}
static int
pipesize (valuep)
RLIMTYPE *valuep;
pipesize (RLIMTYPE *valuep)
{
#if defined (PIPE_BUF)
/* This is defined on Posix systems. */
@@ -699,8 +693,7 @@ pipesize (valuep)
}
static int
getmaxuprc (valuep)
RLIMTYPE *valuep;
getmaxuprc (RLIMTYPE *valuep)
{
long maxchild;
@@ -718,8 +711,7 @@ getmaxuprc (valuep)
}
static void
print_all_limits (mode)
int mode;
print_all_limits (int mode)
{
register int i;
RLIMTYPE softlim, hardlim;
@@ -738,10 +730,7 @@ print_all_limits (mode)
}
static void
printone (limind, curlim, pdesc)
int limind;
RLIMTYPE curlim;
int pdesc;
printone (int limind, RLIMTYPE curlim, int pdesc)
{
char unitstr[64];
int factor;
@@ -766,6 +755,7 @@ printone (limind, curlim, pdesc)
print_rlimtype ((curlim / factor), 1);
}
#ifdef NOTYET
/* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which
causes all limits to be set as high as possible depending on mode (like
csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits
@@ -780,9 +770,7 @@ printone (limind, curlim, pdesc)
*/
static int
set_all_limits (mode, newlim)
int mode;
RLIMTYPE newlim;
set_all_limits (int mode, RLIMTYPE newlim)
{
register int i;
int retval = 0;
@@ -805,5 +793,6 @@ set_all_limits (mode, newlim)
}
return retval;
}
#endif /* NOTYET */
#endif /* !_MINIX */
+104 -50
View File
@@ -1,7 +1,7 @@
This file is umask.def, from which is created umask.c.
It implements the builtin "umask" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -67,14 +67,13 @@ $END
/* */
/* **************************************************************** */
static void print_symbolic_umask PARAMS((mode_t));
static int symbolic_umask PARAMS((WORD_LIST *));
static void print_symbolic_umask (mode_t);
static int symbolic_umask (WORD_LIST *);
/* Set or display the mask used by the system when creating files. Flag
of -S means display the umask in a symbolic mode. */
int
umask_builtin (list)
WORD_LIST *list;
umask_builtin (WORD_LIST *list)
{
int print_symbolically, opt, umask_value, pflag;
mode_t umask_arg;
@@ -146,12 +145,7 @@ umask_builtin (list)
/* Print the umask in a symbolic form. In the output, a letter is
printed if the corresponding bit is clear in the umask. */
static void
#if defined (__STDC__)
print_symbolic_umask (mode_t um)
#else
print_symbolic_umask (um)
mode_t um;
#endif
{
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
int i;
@@ -186,17 +180,41 @@ print_symbolic_umask (um)
printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
}
int
parse_symbolic_mode (mode, initial_bits)
char *mode;
int initial_bits;
static inline mode_t
copyuser (mode_t mask)
{
int who, op, perm, bits, c;
return ((mask & S_IRUSR) ? S_IRUGO : 0) |
((mask & S_IWUSR) ? S_IWUGO : 0) |
((mask & S_IXUSR) ? S_IXUGO : 0);
}
static inline mode_t
copygroup (mode_t mask)
{
return ((mask & S_IRGRP) ? S_IRUGO : 0) |
((mask & S_IWGRP) ? S_IWUGO : 0) |
((mask & S_IXGRP) ? S_IXUGO : 0);
}
static inline mode_t
copyother (mode_t mask)
{
return ((mask & S_IROTH) ? S_IRUGO : 0) |
((mask & S_IWOTH) ? S_IWUGO : 0) |
((mask & S_IXOTH) ? S_IXUGO : 0);
}
int
parse_symbolic_mode (char *mode, mode_t initial_bits)
{
char op, c;
mode_t who, perm, bits;
char *s;
for (s = mode, bits = initial_bits;;)
{
who = op = perm = 0;
who = 0;
op = 0;
/* Parse the `who' portion of the symbolic mode clause. */
while (member (*s, "agou"))
@@ -220,7 +238,13 @@ parse_symbolic_mode (mode, initial_bits)
}
}
/* default `who' is `a' */
if (who == 0)
who = S_IRWXU | S_IRWXG | S_IRWXO;
/* The operation is now sitting in *s. */
start_op:
perm = 0;
op = *s++;
switch (op)
{
@@ -233,57 +257,87 @@ parse_symbolic_mode (mode, initial_bits)
return (-1);
}
/* Parse out the `perm' section of the symbolic mode clause. */
while (member (*s, "rwx"))
/* Parse out the `action' section of the symbolic mode clause. An
action can be a set of permissions (rwxXst), a copy specification
(ugo), or another op (+-=). */
while (member (*s, "rwxXstugo"))
{
c = *s++;
switch (c)
switch (*s)
{
/* First the copy specification */
case 'u':
perm = copyuser (initial_bits);
break;
case 'g':
perm = copygroup (initial_bits);
break;
case 'o':
perm = copyother (initial_bits);
break;
/* Then the permissions. */
case 'r':
perm |= S_IRUGO;
break;
case 'w':
perm |= S_IWUGO;
break;
case 'X':
/* for chmod, this includes S_ISDIR but that doesn't make sense here */
if ((initial_bits & S_IXUGO) == 0)
break; /* no-op if original mask doesn't include execute bits */
/* FALLTHROUGH */
case 'x':
perm |= S_IXUGO;
break;
case 's':
#ifdef S_ISUID
perm |= S_ISUID | S_ISGID;
break;
#else
goto spec_error;
#endif
case 't':
#ifdef S_ISVTX
perm |= S_ISVTX;
break;
#else
goto spec_error;
#endif
}
s++;
}
/* Now perform the operation or return an error for a
bad permission string. */
if (!*s || *s == ',')
perm &= who;
switch (op)
{
if (who)
perm &= who;
switch (op)
{
case '+':
bits |= perm;
break;
case '-':
bits &= ~perm;
break;
case '=':
if (who == 0)
who = S_IRWXU | S_IRWXG | S_IRWXO;
bits &= ~who;
bits |= perm;
break;
/* No other values are possible. */
}
if (*s == '\0')
break;
else
s++; /* skip past ',' */
case '+':
bits |= perm;
break;
case '-':
bits &= ~perm;
break;
case '=':
bits &= ~who;
bits |= perm;
break;
}
/* Break if the end of the action string, loop if we're going to parse
another `who', go back to parsing another op if we have an op spec
(+-=). Return an invalid mode character error for everything else. */
if (*s == '\0')
break;
else if (*s == ',')
s++; /* skip past ',' */
else if (*s == '+' || *s == '-' || *s == '=')
goto start_op;
else
{
spec_error:
builtin_error (_("`%c': invalid symbolic mode character"), *s);
return (-1);
}
@@ -296,10 +350,10 @@ parse_symbolic_mode (mode, initial_bits)
by chmod. If the -S argument is given, then print the umask in a
symbolic form. */
static int
symbolic_umask (list)
WORD_LIST *list;
symbolic_umask (WORD_LIST *list)
{
int um, bits;
mode_t um;
int bits;
/* Get the initial umask. Don't change it yet. */
um = umask (022);
+65 -14
View File
@@ -1,7 +1,7 @@
'This file is wait.def, from which is created wait.c.
This file is wait.def, from which is created wait.c.
It implements the builtin "wait" in Bash.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -90,8 +90,9 @@ extern int wait_signal_received;
procenv_t wait_intr_buf;
int wait_intr_flag;
static int set_waitlist PARAMS((WORD_LIST *));
static void unset_waitlist PARAMS((void));
static int set_waitlist (WORD_LIST *);
static void unset_waitlist (void);
static int check_bgpids (WORD_LIST *, struct procstat *);
/* Wait for the pid in LIST to stop or die. If no arguments are given, then
wait for all of the active background processes of the shell and return
@@ -108,8 +109,7 @@ static void unset_waitlist PARAMS((void));
while (0)
int
wait_builtin (list)
WORD_LIST *list;
wait_builtin (WORD_LIST *list)
{
int status, code, opt, nflag, vflags, bindflags;
volatile int wflags;
@@ -154,10 +154,10 @@ wait_builtin (list)
int arrayflags;
SET_VFLAGS (vflags, arrayflags, bindflags);
if (legal_identifier (vname) == 0 && valid_array_reference (vname, arrayflags) == 0)
if (valid_identifier (vname) == 0 && valid_array_reference (vname, arrayflags) == 0)
#else
bindflags = 0;
if (legal_identifier (vname) == 0)
if (valid_identifier (vname) == 0)
#endif
{
sh_invalidid (vname);
@@ -211,6 +211,21 @@ wait_builtin (list)
#if defined (JOB_CONTROL)
if (nflag)
{
#if 0 /* TAG:bash-5.3 stevenpelley@gmail.com 01/22/2024 */
/* First let's see if there are any requested pids that have already
been removed from the jobs list and saved on bgpids. */
if (list)
{
status = check_bgpids (list, &pstat);
if (status != -1)
{
if (vname)
builtin_bind_var_to_int (vname, pstat.pid, bindflags);
WAIT_RETURN (status);
}
}
#endif
if (list)
{
opt = set_waitlist (list);
@@ -255,7 +270,7 @@ wait_builtin (list)
w = list->word->word;
if (DIGIT (*w))
{
if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value)
if (valid_number (w, &pid_value) && pid_value == (pid_t)pid_value)
{
pid = (pid_t)pid_value;
status = wait_for_single_pid (pid, wflags|JWAIT_PERROR);
@@ -331,11 +346,10 @@ wait_builtin (list)
J_WAITING, so wait -n knows which jobs to wait for. Return the number of
jobs we found. */
static int
set_waitlist (list)
WORD_LIST *list;
set_waitlist (WORD_LIST *list)
{
sigset_t set, oset;
int job, r, njob;
int job, njob;
intmax_t pid;
WORD_LIST *l;
@@ -344,7 +358,7 @@ set_waitlist (list)
for (l = list; l; l = l->next)
{
job = NO_JOB;
job = (l && legal_number (l->word->word, &pid) && pid == (pid_t) pid)
job = (l && l->word && valid_number (l->word->word, &pid) && pid == (pid_t) pid)
? get_job_by_pid ((pid_t) pid, 0, 0)
: get_job_spec (l);
if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
@@ -367,7 +381,7 @@ set_waitlist (list)
/* Clean up after a call to wait -n jobs */
static void
unset_waitlist ()
unset_waitlist (void)
{
int i;
sigset_t set, oset;
@@ -378,4 +392,41 @@ unset_waitlist ()
jobs[i]->flags &= ~J_WAITING;
UNBLOCK_CHILD (oset);
}
#if 0 /* TAG:bash-5.3 */
static int
check_bgpids (WORD_LIST *list, struct procstat *pstat)
{
sigset_t set, oset;
pid_t pid;
intmax_t ipid;
WORD_LIST *l;
int r, s;
r = -1;
BLOCK_CHILD (set, oset);
for (l = list; l; l = l->next)
{
if (l && valid_number (l->word->word, &ipid) && ipid == (pid_t) ipid)
pid = ipid;
else
continue; /* skip job ids for now */
if ((s = retrieve_proc_status (pid, 0)) != -1)
{
pstat->pid = pid;
pstat->status = r = s;
/* If running in posix mode, `wait -n pid' deletes pid from bgpids,
just like `wait pid'. */
if (posixly_correct)
delete_proc_status (pid, 0);
break;
}
}
UNBLOCK_CHILD (oset);
return r;
}
#endif
#endif