mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-02 01:40:49 +02:00
In posix mode, `command -v' should print absolute pathnames; sanitize command and filenames used in error messages so they don't contain non-printable characters
This commit is contained in:
@@ -13027,3 +13027,29 @@ arrayfunc.c
|
||||
- convert_var_to_{array,assoc}: only save the old value if the variable
|
||||
isn't an array; dispose old value appropriately
|
||||
Report and patch from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
6/15
|
||||
----
|
||||
builtins/type.def
|
||||
- describe_command: even if the command name contains a slash, if the
|
||||
flags include CDESC_ABSPATH, convert to an absolute pathname if it
|
||||
doesn't begin with a slash
|
||||
|
||||
builtins/command.def
|
||||
- command_builtin: in posix mode, `command -v' adds CDESC_ABSPATH
|
||||
to the flags passed to describe_command() so it prints as an
|
||||
absolute pathname
|
||||
From a discussion on the dash mailing list about POSIX requirements
|
||||
|
||||
redir.c
|
||||
- redirection_error: make sure to sanitize command names using
|
||||
printable_filename before printing error messages
|
||||
Report from Vincent Lefevre <vincent@vinc17.net>
|
||||
|
||||
execute_cmd.c,shell.c,variables.c
|
||||
builtins/evalfile.c,builtins/evalstring.c
|
||||
builtins/builtin.def,builtins/command.def,builtins/enable.def
|
||||
builtins/exec.def,builtins/hash.def,builtins/help.def,builtins/history.def
|
||||
builtins/source.def,builtins/type.def
|
||||
- sanitize command and file names used in error messages by calling
|
||||
printable_filename
|
||||
|
||||
@@ -53,7 +53,7 @@ int
|
||||
builtin_builtin (WORD_LIST *list)
|
||||
{
|
||||
sh_builtin_func_t *function;
|
||||
register char *command;
|
||||
char *command, *newname;
|
||||
int r;
|
||||
|
||||
if (r = no_options (list))
|
||||
@@ -72,7 +72,10 @@ builtin_builtin (WORD_LIST *list)
|
||||
|
||||
if (function == 0)
|
||||
{
|
||||
sh_notbuiltin (command);
|
||||
newname = printable_filename (command, 0);
|
||||
sh_notbuiltin (newname);
|
||||
if (newname != command)
|
||||
free (newname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -83,7 +83,7 @@ command_builtin (WORD_LIST *list)
|
||||
verbose = CDESC_SHORTDESC|CDESC_ABSPATH; /* look in common.h for constants */
|
||||
break;
|
||||
case 'v':
|
||||
verbose = CDESC_REUSABLE; /* ditto */
|
||||
verbose = CDESC_REUSABLE| (posixly_correct ? CDESC_ABSPATH : 0); /* ditto */
|
||||
break;
|
||||
CASE_HELPOPT;
|
||||
default:
|
||||
@@ -107,13 +107,19 @@ command_builtin (WORD_LIST *list)
|
||||
if (verbose)
|
||||
{
|
||||
int found, any_found;
|
||||
char *newfn;
|
||||
|
||||
for (any_found = 0; list; list = list->next)
|
||||
{
|
||||
found = describe_command (list->word->word, verbose|use_standard_path);
|
||||
|
||||
if (found == 0 && verbose != CDESC_REUSABLE)
|
||||
sh_notfound (list->word->word);
|
||||
{
|
||||
newfn = printable_filename (list->word->word, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != list->word->word)
|
||||
free (newfn);
|
||||
}
|
||||
|
||||
any_found += found;
|
||||
}
|
||||
|
||||
+22
-7
@@ -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-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -224,7 +224,7 @@ enable_builtin (WORD_LIST *list)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
char *command;
|
||||
char *command, *newname;
|
||||
|
||||
command = list->word->word;
|
||||
opt = enable_shell_command (command, flags & NFLAG);
|
||||
@@ -258,7 +258,10 @@ enable_builtin (WORD_LIST *list)
|
||||
|
||||
if (opt == EX_NOTFOUND)
|
||||
{
|
||||
sh_notbuiltin (command);
|
||||
newname = printable_filename (command, 0);
|
||||
sh_notbuiltin (newname);
|
||||
if (newname != command)
|
||||
free (newname);
|
||||
result = EXECUTION_FAILURE;
|
||||
}
|
||||
else if (opt != EXECUTION_SUCCESS)
|
||||
@@ -405,7 +408,10 @@ dyn_load_builtin (WORD_LIST *list, int flags, char *filename)
|
||||
name = list->word->word;
|
||||
if (absolute_program (name))
|
||||
{
|
||||
name = printable_filename (list->word->word, 0);
|
||||
builtin_error (_("%s: builtin names may not contain slashes"), name);
|
||||
if (name != list->word->word)
|
||||
free (name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -549,7 +555,7 @@ dyn_unload_builtin (char *name)
|
||||
{
|
||||
struct builtin *b;
|
||||
void *handle;
|
||||
char *funcname;
|
||||
char *funcname, *newname;
|
||||
sh_unload_func_t *unloadfunc;
|
||||
int ref, i;
|
||||
size_t size;
|
||||
@@ -557,12 +563,18 @@ dyn_unload_builtin (char *name)
|
||||
b = builtin_address_internal (name, 1);
|
||||
if (b == 0)
|
||||
{
|
||||
sh_notbuiltin (name);
|
||||
newname = printable_filename (name, 0);
|
||||
sh_notbuiltin (newname);
|
||||
if (newname != name)
|
||||
free (newname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
if (b->flags & STATIC_BUILTIN)
|
||||
{
|
||||
builtin_error (_("%s: not dynamically loaded"), name);
|
||||
newname = printable_filename (name, 0);
|
||||
builtin_error (_("%s: not dynamically loaded"), newname);
|
||||
if (newname != name)
|
||||
free (newname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
@@ -588,7 +600,10 @@ dyn_unload_builtin (char *name)
|
||||
using it drops to zero. */
|
||||
if (ref == 1 && local_dlclose (handle) != 0)
|
||||
{
|
||||
builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
|
||||
newname = printable_filename (name, 0);
|
||||
builtin_error (_("%s: cannot delete: %s"), newname, dlerror ());
|
||||
if (newname != name)
|
||||
free (newname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
+15
-4
@@ -1,6 +1,6 @@
|
||||
/* evalfile.c - read and evaluate commands from a file or file descriptor */
|
||||
|
||||
/* Copyright (C) 1996-2017,2022-2024 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -118,7 +118,12 @@ evalfile_internal (const char *filename, int flags)
|
||||
|
||||
file_error_and_exit:
|
||||
if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
|
||||
file_error (filename);
|
||||
{
|
||||
t = printable_filename ((char *)filename, 0);
|
||||
file_error (t);
|
||||
if (t != filename)
|
||||
free (t);
|
||||
}
|
||||
|
||||
if (flags & FEVAL_LONGJMP)
|
||||
{
|
||||
@@ -134,13 +139,19 @@ file_error_and_exit:
|
||||
|
||||
if (S_ISDIR (finfo.st_mode))
|
||||
{
|
||||
(*errfunc) (_("%s: is a directory"), filename);
|
||||
t = printable_filename ((char *)filename, 0);
|
||||
(*errfunc) (_("%s: is a directory"), t);
|
||||
if (t != filename)
|
||||
free (t);
|
||||
close (fd);
|
||||
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
||||
}
|
||||
else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
|
||||
{
|
||||
(*errfunc) (_("%s: not a regular file"), filename);
|
||||
t = printable_filename ((char *)filename, 0);
|
||||
(*errfunc) (_("%s: not a regular file"), t);
|
||||
if (t != filename)
|
||||
free (t);
|
||||
close (fd);
|
||||
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* evalstring.c - evaluate a string as one or more shell commands. */
|
||||
|
||||
/* Copyright (C) 1996-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -761,7 +761,7 @@ out:
|
||||
int
|
||||
open_redir_file (REDIRECT *r, char **fnp)
|
||||
{
|
||||
char *fn;
|
||||
char *fn, *newfn;
|
||||
int fd;
|
||||
|
||||
if (r->instruction != r_input_direction)
|
||||
@@ -783,7 +783,10 @@ open_redir_file (REDIRECT *r, char **fnp)
|
||||
fd = open(fn, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
internal_error ("%s: %s", fn, strerror (errno));
|
||||
newfn = printable_filename (fn, 0);
|
||||
internal_error ("%s: %s", newfn, strerror (errno));
|
||||
if (newfn != fn)
|
||||
free (newfn);
|
||||
free (fn);
|
||||
if (fnp)
|
||||
*fnp = 0;
|
||||
|
||||
+7
-4
@@ -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,2022,2024,2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2021,2022,2024-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -152,20 +152,23 @@ exec_builtin (WORD_LIST *list)
|
||||
|
||||
if (command == 0)
|
||||
{
|
||||
newname = printable_filename (args[0], 0);
|
||||
if (file_isdir (args[0]))
|
||||
{
|
||||
#if defined (EISDIR)
|
||||
builtin_error ("%s: %s: %s", args[0], _("cannot execute"), strerror (EISDIR));
|
||||
builtin_error ("%s: %s: %s", newname, _("cannot execute"), strerror (EISDIR));
|
||||
#else
|
||||
builtin_error ("%s: %s: %s", args[0], _("cannot execute"), strerror (errno));
|
||||
builtin_error ("%s: %s: %s", newname, _("cannot execute"), strerror (errno));
|
||||
#endif
|
||||
exit_value = EX_NOEXEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_notfound (args[0]);
|
||||
sh_notfound (newname);
|
||||
exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
|
||||
}
|
||||
if (newname != args[0])
|
||||
free (newname);
|
||||
goto failed_exec;
|
||||
}
|
||||
|
||||
|
||||
+42
-14
@@ -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-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -81,7 +81,7 @@ int
|
||||
hash_builtin (WORD_LIST *list)
|
||||
{
|
||||
int expunge_hash_table, list_targets, list_portably, delete, opt;
|
||||
char *w, *pathname;
|
||||
char *w, *pathname, *newfn;
|
||||
|
||||
if (hashing_enabled == 0)
|
||||
{
|
||||
@@ -158,15 +158,21 @@ hash_builtin (WORD_LIST *list)
|
||||
{
|
||||
if (absolute_program (pathname))
|
||||
{
|
||||
sh_restricted (pathname);
|
||||
return (EXECUTION_FAILURE);
|
||||
newfn = printable_filename (pathname, 0);
|
||||
sh_restricted (newfn);
|
||||
if (newfn != pathname)
|
||||
free (newfn);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
/* If we are changing the hash table in a restricted shell, make sure the
|
||||
target pathname can be found using a $PATH search. */
|
||||
w = find_user_command (pathname);
|
||||
if (w == 0 || *w == 0 || executable_file (w) == 0)
|
||||
{
|
||||
sh_notfound (pathname);
|
||||
newfn = printable_filename (pathname, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != pathname)
|
||||
free (newfn);
|
||||
free (w);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
@@ -184,11 +190,14 @@ hash_builtin (WORD_LIST *list)
|
||||
{
|
||||
if (file_isdir (pathname))
|
||||
{
|
||||
newfn = printable_filename (pathname, 0);
|
||||
#ifdef EISDIR
|
||||
builtin_error ("%s: %s", pathname, strerror (EISDIR));
|
||||
builtin_error ("%s: %s", newfn, strerror (EISDIR));
|
||||
#else
|
||||
builtin_error (_("%s: is a directory"), pathname);
|
||||
builtin_error (_("%s: is a directory"), newfn);
|
||||
#endif
|
||||
if (newfn != pathname)
|
||||
free (newfn);
|
||||
opt = EXECUTION_FAILURE;
|
||||
}
|
||||
else
|
||||
@@ -198,7 +207,10 @@ hash_builtin (WORD_LIST *list)
|
||||
{
|
||||
if (phash_remove (w))
|
||||
{
|
||||
sh_notfound (w);
|
||||
newfn = printable_filename (w, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != w)
|
||||
free (newfn);
|
||||
opt = EXECUTION_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -214,7 +226,7 @@ static int
|
||||
add_hashed_command (char *w, int quiet)
|
||||
{
|
||||
int rv;
|
||||
char *full_path;
|
||||
char *full_path, *newfn;
|
||||
|
||||
rv = 0;
|
||||
if (find_function (w) == 0 && find_shell_builtin (w) == 0)
|
||||
@@ -226,7 +238,12 @@ add_hashed_command (char *w, int quiet)
|
||||
else
|
||||
{
|
||||
if (quiet == 0)
|
||||
sh_notfound (w);
|
||||
{
|
||||
newfn = printable_filename (w, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != w)
|
||||
free (newfn);
|
||||
}
|
||||
rv++;
|
||||
}
|
||||
FREE (full_path);
|
||||
@@ -273,7 +290,7 @@ static int
|
||||
list_hashed_filename_targets (WORD_LIST *list, int fmt)
|
||||
{
|
||||
int all_found, multiple;
|
||||
char *target;
|
||||
char *target, *fp, *fn;
|
||||
WORD_LIST *l;
|
||||
|
||||
all_found = 1;
|
||||
@@ -281,21 +298,32 @@ list_hashed_filename_targets (WORD_LIST *list, int fmt)
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
fn = printable_filename (l->word->word, 1);
|
||||
target = phash_search (l->word->word);
|
||||
if (target == 0)
|
||||
{
|
||||
all_found = 0;
|
||||
sh_notfound (l->word->word);
|
||||
sh_notfound (fn);
|
||||
if (fn != l->word->word)
|
||||
free (fn);
|
||||
continue;
|
||||
}
|
||||
fp = printable_filename (target, 1);
|
||||
if (fp != target)
|
||||
{
|
||||
free (target);
|
||||
target = fp;
|
||||
}
|
||||
if (fmt)
|
||||
printf ("builtin hash -p %s %s\n", target, l->word->word);
|
||||
printf ("builtin hash -p %s %s\n", target, fn);
|
||||
else
|
||||
{
|
||||
if (multiple)
|
||||
printf ("%s\t", l->word->word);
|
||||
printf ("%s\t", fn);
|
||||
printf ("%s\n", target);
|
||||
}
|
||||
if (fn != l->word->word)
|
||||
free (fn);
|
||||
free (target);
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -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-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -207,11 +207,15 @@ static int
|
||||
open_helpfile (const char *name)
|
||||
{
|
||||
int fd;
|
||||
char *newfn;
|
||||
|
||||
fd = open (name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
builtin_error ("%s: %s: %s", name, _("cannot open"), strerror (errno));
|
||||
newfn = printable_filename (name, 0);
|
||||
builtin_error ("%s: %s: %s", newfn, _("cannot open"), strerror (errno));
|
||||
if (newfn != name)
|
||||
free (newfn);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
|
||||
+12
-4
@@ -132,7 +132,7 @@ int
|
||||
history_builtin (WORD_LIST *list)
|
||||
{
|
||||
int flags, opt, result, old_history_lines, obase, ind;
|
||||
char *filename, *delete_arg, *range;
|
||||
char *filename, *newfn, *delete_arg, *range;
|
||||
intmax_t delete_offset;
|
||||
|
||||
flags = 0;
|
||||
@@ -281,7 +281,10 @@ history_builtin (WORD_LIST *list)
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
if (restricted && absolute_program (filename))
|
||||
{
|
||||
sh_restricted (filename);
|
||||
newfn = printable_filename (filename, 0);
|
||||
sh_restricted (newfn);
|
||||
if (newfn != filename)
|
||||
free (newfn);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
@@ -351,6 +354,8 @@ history_builtin (WORD_LIST *list)
|
||||
static void
|
||||
history_error (const char *filename, int e, int r)
|
||||
{
|
||||
char *newfn;
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ENOENT:
|
||||
@@ -361,10 +366,13 @@ history_error (const char *filename, int e, int r)
|
||||
#if defined (EACCES)
|
||||
case EACCES:
|
||||
#endif
|
||||
newfn = printable_filename ((char *)filename, 0);
|
||||
if (r)
|
||||
builtin_error ("%s: %s: %s", filename, _("read error"), strerror (e));
|
||||
builtin_error ("%s: %s: %s", newfn, _("read error"), strerror (e));
|
||||
else
|
||||
builtin_error ("%s: %s: %s", filename, _("write error"), strerror (e));
|
||||
builtin_error ("%s: %s: %s", newfn, _("write error"), strerror (e));
|
||||
if (newfn != filename)
|
||||
free (newfn);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+4
-1
@@ -150,7 +150,10 @@ source_builtin (WORD_LIST *list)
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
if (restricted && (pathstring || absolute_program (list->word->word)))
|
||||
{
|
||||
sh_restricted (list->word->word);
|
||||
filename = printable_filename (list->word->word, 0);
|
||||
sh_restricted (filename);
|
||||
if (filename != list->word->word)
|
||||
free (filename);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
+19
-4
@@ -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-2023 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -176,11 +176,17 @@ type_builtin (WORD_LIST *list)
|
||||
while (list)
|
||||
{
|
||||
int found;
|
||||
char *newfn;
|
||||
|
||||
found = describe_command (list->word->word, dflags);
|
||||
|
||||
if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
|
||||
sh_notfound (list->word->word);
|
||||
{
|
||||
newfn = printable_filename (list->word->word, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != list->word->word)
|
||||
free (newfn);
|
||||
}
|
||||
|
||||
any_failed += found == 0;
|
||||
list = list->next;
|
||||
@@ -335,12 +341,21 @@ describe_command (char *command, int dflags)
|
||||
f = file_status (command);
|
||||
if (f & FS_EXECABLE)
|
||||
{
|
||||
/* convert to absolute pathname? */
|
||||
if ((dflags & CDESC_ABSPATH) && ABSPATH (command) == 0)
|
||||
full_path = sh_makepath ((char *)NULL, command, MP_DOCWD|MP_RMDOT);
|
||||
else
|
||||
full_path = command;
|
||||
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("file");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is %s\n"), command, command);
|
||||
printf (_("%s is %s\n"), command, full_path);
|
||||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
|
||||
printf ("%s\n", command);
|
||||
printf ("%s\n", full_path);
|
||||
|
||||
if (full_path != command)
|
||||
free (full_path);
|
||||
|
||||
/* There's no use looking in the hash table or in $PATH,
|
||||
because they're not consulted when an absolute program
|
||||
|
||||
+3
-1
@@ -6632,7 +6632,9 @@ A backslash.
|
||||
Begin a sequence of non-printing characters, which could be used to
|
||||
embed a terminal control sequence into the prompt.
|
||||
This escape is only useful when the prompt will be supplied to
|
||||
\fBreadline\fP, so it shouldn't be used in \fBPS0\fP or \fBPS4\fP
|
||||
\fBreadline\fP,
|
||||
and is ignored and removed otherwise,
|
||||
so it shouldn't be used in \fBPS0\fP or \fBPS4\fP
|
||||
or when line editing is not enabled.
|
||||
.TP
|
||||
.B \e]
|
||||
|
||||
+7
-1
@@ -9158,7 +9158,9 @@ Begin a sequence of non-printing characters.
|
||||
This could be used to
|
||||
embed a terminal control sequence into the prompt.
|
||||
This escape is only useful when the prompt will be supplied to
|
||||
Readline, so it shouldn't be used in @env{PS0} or @env{PS4},
|
||||
Readline,
|
||||
and is ignored and removed otherwise,
|
||||
so it shouldn't be used in @env{PS0} or @env{PS4},
|
||||
or when line editing is not enabled.
|
||||
|
||||
@item \]
|
||||
@@ -9613,6 +9615,10 @@ constructed from @code{$PWD} and the directory name supplied as an argument
|
||||
exceeds @code{PATH_MAX} when canonicalized, @code{cd} will
|
||||
attempt to use the supplied directory name.
|
||||
|
||||
@item
|
||||
The @code{command} builtin prints command name arguments containing a
|
||||
slash as full pathnames when the @option{-v} option is supplied.
|
||||
|
||||
@item
|
||||
When the @code{xpg_echo} option is enabled, Bash does not attempt to
|
||||
interpret any arguments to @code{echo} as options.
|
||||
|
||||
+25
-11
@@ -5915,8 +5915,13 @@ execute_disk_command (WORD_LIST *words, REDIRECT *redirects, char *command_line,
|
||||
command = (char *)NULL;
|
||||
if (restricted && mbschr (pathname, '/'))
|
||||
{
|
||||
char *newfn;
|
||||
|
||||
newfn = printable_filename (pathname, 0);
|
||||
internal_error (_("%s: restricted: cannot specify `/' in command names"),
|
||||
pathname);
|
||||
newfn);
|
||||
if (newfn != pathname)
|
||||
free (newfn);
|
||||
result = last_command_exit_value = EXECUTION_FAILURE;
|
||||
|
||||
/* If we're not going to fork below, we must already be in a child
|
||||
@@ -6291,7 +6296,7 @@ int
|
||||
shell_execve (char *command, char **args, char **env)
|
||||
{
|
||||
int i, fd, sample_len;
|
||||
char sample[HASH_BANG_BUFSIZ];
|
||||
char sample[HASH_BANG_BUFSIZ], *newfn;
|
||||
size_t larray;
|
||||
|
||||
SETOSTYPE (0); /* Some systems use for USG/POSIX semantics */
|
||||
@@ -6306,22 +6311,24 @@ shell_execve (char *command, char **args, char **env)
|
||||
{
|
||||
/* make sure this is set correctly for file_error/report_error */
|
||||
last_command_exit_value = (i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC; /* XXX Posix.2 says that exit status is 126 */
|
||||
newfn = printable_filename (command, 0);
|
||||
|
||||
if (file_isdir (command))
|
||||
#if defined (EISDIR)
|
||||
internal_error ("%s: %s", command, strerror (EISDIR));
|
||||
internal_error ("%s: %s", newfn, strerror (EISDIR));
|
||||
#else
|
||||
internal_error (_("%s: is a directory"), command);
|
||||
internal_error (_("%s: is a directory"), newfn);
|
||||
#endif
|
||||
else if (executable_file (command) == 0)
|
||||
{
|
||||
errno = i;
|
||||
file_error (command);
|
||||
file_error (newfn);
|
||||
}
|
||||
/* errors not involving the path argument to execve. */
|
||||
else if (i == E2BIG || i == ENOMEM)
|
||||
{
|
||||
errno = i;
|
||||
file_error (command);
|
||||
file_error (newfn);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6346,23 +6353,27 @@ shell_execve (char *command, char **args, char **env)
|
||||
interp[ilen] = 'M';
|
||||
interp[ilen + 1] = '\0';
|
||||
}
|
||||
sys_error ("%s: %s: %s", command, interp, _("bad interpreter"));
|
||||
sys_error ("%s: %s: %s", newfn, interp, _("bad interpreter"));
|
||||
FREE (interp);
|
||||
return (EX_NOEXEC);
|
||||
last_command_exit_value = EX_NOEXEC;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (i == ENOENT)
|
||||
{
|
||||
errno = i;
|
||||
internal_error (_("%s: cannot execute: required file not found"), command);
|
||||
internal_error (_("%s: cannot execute: required file not found"), newfn);
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = i;
|
||||
file_error (command);
|
||||
file_error (newfn);
|
||||
}
|
||||
}
|
||||
|
||||
if (newfn != command)
|
||||
free (newfn);
|
||||
|
||||
return (last_command_exit_value);
|
||||
}
|
||||
|
||||
@@ -6392,7 +6403,10 @@ shell_execve (char *command, char **args, char **env)
|
||||
#endif
|
||||
if (check_binary_file (sample, sample_len))
|
||||
{
|
||||
internal_error ("%s: %s: %s", command, _("cannot execute binary file"), strerror (i));
|
||||
newfn = printable_filename (command, 0);
|
||||
internal_error ("%s: %s: %s", newfn, _("cannot execute binary file"), strerror (i));
|
||||
if (newfn != command)
|
||||
free (newfn);
|
||||
errno = i;
|
||||
return (EX_BINARY_FILE);
|
||||
}
|
||||
|
||||
@@ -134,10 +134,11 @@ do { \
|
||||
void
|
||||
redirection_error (REDIRECT *temp, int error, char *fn)
|
||||
{
|
||||
char *filename, *allocname;
|
||||
char *filename, *allocname, *newfn;
|
||||
int oflags;
|
||||
|
||||
allocname = 0;
|
||||
allocname = newfn = 0;
|
||||
|
||||
if ((temp->rflags & REDIR_VARASSIGN) && error < 0)
|
||||
filename = allocname = savestring (temp->redirector.filename->word);
|
||||
else if ((temp->rflags & REDIR_VARASSIGN) == 0 && temp->redirector.dest < 0)
|
||||
@@ -195,19 +196,21 @@ redirection_error (REDIRECT *temp, int error, char *fn)
|
||||
else
|
||||
filename = allocname = itos (temp->redirectee.dest);
|
||||
|
||||
newfn = printable_filename (filename, 0);
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case AMBIGUOUS_REDIRECT:
|
||||
internal_error ("%s: %s", filename, _("ambiguous redirect"));
|
||||
internal_error ("%s: %s", newfn, _("ambiguous redirect"));
|
||||
break;
|
||||
|
||||
case NOCLOBBER_REDIRECT:
|
||||
internal_error ("%s: %s", filename, _("cannot overwrite existing file"));
|
||||
internal_error ("%s: %s", newfn, _("cannot overwrite existing file"));
|
||||
break;
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
case RESTRICTED_REDIRECT:
|
||||
internal_error ("%s: %s", filename, _("restricted: cannot redirect output"));
|
||||
internal_error ("%s: %s", newfn, _("restricted: cannot redirect output"));
|
||||
break;
|
||||
#endif /* RESTRICTED_SHELL */
|
||||
|
||||
@@ -216,14 +219,17 @@ redirection_error (REDIRECT *temp, int error, char *fn)
|
||||
break;
|
||||
|
||||
case BADVAR_REDIRECT:
|
||||
internal_error ("%s: %s", filename, _("cannot assign fd to variable"));
|
||||
internal_error ("%s: %s", newfn, _("cannot assign fd to variable"));
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error ("%s: %s", filename, strerror (error));
|
||||
internal_error ("%s: %s", newfn, strerror (error));
|
||||
break;
|
||||
}
|
||||
|
||||
if (newfn != filename)
|
||||
FREE (newfn);
|
||||
|
||||
FREE (allocname);
|
||||
}
|
||||
|
||||
|
||||
@@ -1605,7 +1605,7 @@ open_shell_script (char *script_name)
|
||||
if (fd < 0)
|
||||
{
|
||||
e = errno;
|
||||
file_error (filename);
|
||||
file_error (printable_filename (filename, 0));
|
||||
#if defined (JOB_CONTROL)
|
||||
end_job_control (); /* just in case we were run as bash -i script */
|
||||
#endif
|
||||
@@ -1627,7 +1627,7 @@ open_shell_script (char *script_name)
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
file_error (filename);
|
||||
file_error (printable_filename (filename, 0));
|
||||
#if defined (JOB_CONTROL)
|
||||
end_job_control (); /* just in case we were run as bash -i script */
|
||||
#endif
|
||||
@@ -1665,19 +1665,20 @@ open_shell_script (char *script_name)
|
||||
if (sample_len < 0)
|
||||
{
|
||||
e = errno;
|
||||
t = printable_filename (filename, 0);
|
||||
if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode))
|
||||
{
|
||||
#if defined (EISDIR)
|
||||
errno = EISDIR;
|
||||
file_error (filename);
|
||||
file_error (t);
|
||||
#else
|
||||
internal_error (_("%s: Is a directory"), filename);
|
||||
internal_error (_("%s: Is a directory"), t);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = e;
|
||||
file_error (filename);
|
||||
file_error (t);
|
||||
}
|
||||
#if defined (JOB_CONTROL)
|
||||
end_job_control (); /* just in case we were run as bash -i script */
|
||||
@@ -1686,7 +1687,8 @@ open_shell_script (char *script_name)
|
||||
}
|
||||
else if (sample_len > 0 && (check_binary_file (sample, sample_len)))
|
||||
{
|
||||
internal_error ("%s: %s", filename, _("cannot execute binary file"));
|
||||
t = printable_filename (filename, 0);
|
||||
internal_error ("%s: %s", t, _("cannot execute binary file"));
|
||||
#if defined (JOB_CONTROL)
|
||||
end_job_control (); /* just in case we were run as bash -i script */
|
||||
#endif
|
||||
|
||||
+9
-3
@@ -1719,13 +1719,16 @@ static SHELL_VAR *
|
||||
assign_hashcmd (SHELL_VAR *self, char *value, arrayind_t ind, char *key)
|
||||
{
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
char *full_path;
|
||||
char *full_path, *newfn;
|
||||
|
||||
if (restricted)
|
||||
{
|
||||
if (absolute_program (value))
|
||||
{
|
||||
sh_restricted (value);
|
||||
newfn = printable_filename (value, 0);
|
||||
sh_restricted (newfn);
|
||||
if (newfn != value)
|
||||
free (newfn);
|
||||
return (SHELL_VAR *)NULL;
|
||||
}
|
||||
/* If we are changing the hash table in a restricted shell, make sure the
|
||||
@@ -1733,7 +1736,10 @@ assign_hashcmd (SHELL_VAR *self, char *value, arrayind_t ind, char *key)
|
||||
full_path = find_user_command (value);
|
||||
if (full_path == 0 || *full_path == 0 || executable_file (full_path) == 0)
|
||||
{
|
||||
sh_notfound (value);
|
||||
newfn = printable_filename (value, 0);
|
||||
sh_notfound (newfn);
|
||||
if (newfn != value)
|
||||
free (newfn);
|
||||
free (full_path);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user