mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
fix for $_ when executing $PROMPT_COMMAND; fix for extra line in history after here-document in command substitution
This commit is contained in:
+31
-6
@@ -5272,8 +5272,9 @@ arrayfunc.c
|
||||
---
|
||||
parse.y
|
||||
- discard_until: now returns the last character read. If we get an
|
||||
EOF while processing a comment, return EOF
|
||||
- shell_getc: if discard_until returns EOF, return yacc_EOF
|
||||
EOF while processing a comment, return EOF (rarely happens;
|
||||
shell_getc returns EOF only under certain circumstances)
|
||||
- read_token: if discard_until returns EOF, return yacc_EOF
|
||||
|
||||
input.h
|
||||
- bclearerror: new macro, clears the B_ERROR flag in the buffered
|
||||
@@ -5294,7 +5295,31 @@ doc/{bash.1,bashref.texi}
|
||||
2/8
|
||||
---
|
||||
bashline.c
|
||||
- alias_expand_line: if alias_expand doesn't change rl_line_buffer,
|
||||
just return right away without changing rl_point. Inspired by a
|
||||
report from Addison Brendtro <addison.brendtro@gmail.com>
|
||||
- history_expand_line: ditto
|
||||
- set_up_new__line: if the new line doesn't change rl_line_buffer,
|
||||
just return right away without changing rl_point. Affects
|
||||
alias-expand-line, history-expand-line, and history-and-alias-expand-line.
|
||||
Inspired by a report from
|
||||
Addison Brendtro <addison.brendtro@gmail.com>
|
||||
|
||||
builtins/declare.def
|
||||
- declare_internal: make multiple calls to `local -' at the same
|
||||
context have no effect after the first one. That way we don't keep
|
||||
overwriting the saved option set. Report and fix from
|
||||
Emanuele Torre <torreemanuele6@gmail.com>
|
||||
|
||||
2/10
|
||||
----
|
||||
execute_cmd.[ch]
|
||||
- bind_lastarg: now a public function
|
||||
|
||||
parse.y
|
||||
- execute_variable_command: call bind_lastarg instead of bind_variable
|
||||
to avoid exporting $_ if allexport is set. Fix from
|
||||
Emanuele Torre <torreemanuele6@gmail.com>
|
||||
|
||||
bashhist.c
|
||||
- history_delimiting_chars: if we're parsing some kind of delimited
|
||||
construct that's *not* a quoted string, don't bother adding an extra
|
||||
newline to the history if the current history entry already ends in
|
||||
a newline. From https://savannah.gnu.org/support/?110838 via
|
||||
Ganapathi Kamath <hgkamath@hotmail.com>
|
||||
|
||||
+7
-14
@@ -2713,6 +2713,13 @@ set_up_new_line (char *new_line)
|
||||
{
|
||||
int old_point, at_end;
|
||||
|
||||
/* If we didn't expand anything, don't change anything. */
|
||||
if (STREQ (new_line, rl_line_buffer))
|
||||
{
|
||||
free (new_line);
|
||||
return;
|
||||
}
|
||||
|
||||
old_point = rl_point;
|
||||
at_end = rl_point == rl_end;
|
||||
|
||||
@@ -2741,13 +2748,6 @@ alias_expand_line (int count, int ignore)
|
||||
|
||||
new_line = alias_expand (rl_line_buffer);
|
||||
|
||||
/* If we didn't expand anything, don't change anything. */
|
||||
if (new_line && STREQ (new_line, rl_line_buffer))
|
||||
{
|
||||
free (new_line);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (new_line)
|
||||
{
|
||||
set_up_new_line (new_line);
|
||||
@@ -2770,13 +2770,6 @@ history_expand_line (int count, int ignore)
|
||||
|
||||
new_line = history_expand_line_internal (rl_line_buffer);
|
||||
|
||||
/* If we didn't expand anything, don't change anything. */
|
||||
if (new_line && STREQ (new_line, rl_line_buffer))
|
||||
{
|
||||
free (new_line);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (new_line)
|
||||
{
|
||||
set_up_new_line (new_line);
|
||||
|
||||
+12
-4
@@ -409,11 +409,19 @@ declare_internal (WORD_LIST *list, int local_var)
|
||||
|
||||
if (local_var && variable_context && STREQ (name, "-"))
|
||||
{
|
||||
int o;
|
||||
|
||||
o = localvar_inherit;
|
||||
localvar_inherit = 0;
|
||||
var = make_local_variable ("-", 0);
|
||||
FREE (value_cell (var)); /* just in case */
|
||||
value = get_current_options ();
|
||||
var_setvalue (var, value);
|
||||
VSETATTR (var, att_invisible);
|
||||
localvar_inherit = o;
|
||||
|
||||
if (value_cell (var) == NULL) /* no duplicate instances */
|
||||
{
|
||||
value = get_current_options ();
|
||||
var_setvalue (var, value);
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -9278,7 +9278,9 @@ is used within a function, it causes the variable
|
||||
to have a visible scope restricted to that function and its children.
|
||||
If \fIname\fP is \-, the set of shell options is made local to the function
|
||||
in which \fBlocal\fP is invoked: shell options changed using the
|
||||
\fBset\fP builtin inside the function are restored to their original values
|
||||
\fBset\fP builtin inside the function
|
||||
after the call to \fBlocal\fP
|
||||
are restored to their original values
|
||||
when the function returns.
|
||||
The restore is effected as if a series of \fBset\fP commands were executed
|
||||
to restore the values that were in place before the function.
|
||||
|
||||
+3
-1
@@ -4787,7 +4787,9 @@ The @var{option} can be any of the options accepted by @code{declare}.
|
||||
children.
|
||||
If @var{name} is @samp{-}, the set of shell options is made local to the
|
||||
function in which @code{local} is invoked: shell options changed using
|
||||
the @code{set} builtin inside the function are restored to their original
|
||||
the @code{set} builtin inside the function
|
||||
after the call to @code{local}
|
||||
are restored to their original
|
||||
values when the function returns.
|
||||
The restore is effected as if a series of @code{set} commands were executed
|
||||
to restore the values that were in place before the function.
|
||||
|
||||
+50
-32
@@ -3,7 +3,7 @@
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009,2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2009,2022-2023 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
@@ -135,10 +135,12 @@ mkdir_builtin (WORD_LIST *list)
|
||||
static int
|
||||
make_path (char *path, int user_mode, int nmode, int parent_mode)
|
||||
{
|
||||
int oumask;
|
||||
mode_t oumask;
|
||||
struct stat sb;
|
||||
char *p, *npath;
|
||||
int tail;
|
||||
|
||||
/* If we don't have to do any work, don't do any work. */
|
||||
if (stat (path, &sb) == 0)
|
||||
{
|
||||
if (S_ISDIR (sb.st_mode) == 0)
|
||||
@@ -166,48 +168,64 @@ make_path (char *path, int user_mode, int nmode, int parent_mode)
|
||||
while (*p == '/')
|
||||
p++;
|
||||
|
||||
while (p = strchr (p, '/'))
|
||||
tail = 0;
|
||||
while (tail == 0)
|
||||
{
|
||||
*p = '\0';
|
||||
if (stat (npath, &sb) != 0)
|
||||
if (*p == '\0')
|
||||
tail = 1;
|
||||
else
|
||||
p = strchr (p, '/');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
else
|
||||
tail = 1;
|
||||
if (mkdir (npath, 0) < 0)
|
||||
{
|
||||
if (mkdir (npath, 0))
|
||||
/* "Each dir operand that names an existing directory shall be
|
||||
ignored without error." */
|
||||
if (errno == EEXIST || errno == EISDIR)
|
||||
{
|
||||
int e = errno;
|
||||
int fail = 0;
|
||||
|
||||
if (stat (npath, &sb) != 0)
|
||||
{
|
||||
fail = 1;
|
||||
builtin_error ("cannot create directory `%s': %s", npath, strerror (e));
|
||||
}
|
||||
else if (e == EEXIST && S_ISDIR (sb.st_mode) == 0)
|
||||
{
|
||||
fail = 1;
|
||||
builtin_error ("`%s': file exists but is not a directory", npath);
|
||||
}
|
||||
if (fail)
|
||||
{
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
if (chmod (npath, parent_mode) != 0)
|
||||
{
|
||||
builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno));
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (S_ISDIR (sb.st_mode) == 0)
|
||||
{
|
||||
builtin_error ("`%s': file exists but is not a directory", npath);
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*p++ = '/'; /* restore slash */
|
||||
while (*p == '/')
|
||||
if (chmod (npath, (tail == 0) ? parent_mode : nmode) != 0)
|
||||
{
|
||||
builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno));
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
if (tail == 0)
|
||||
*p++ = '/'; /* restore slash */
|
||||
while (p && *p == '/') /* skip consecutive slashes or trailing slash */
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Create the final directory component. */
|
||||
if (stat (npath, &sb) && mkdir (npath, nmode))
|
||||
{
|
||||
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
umask (original_umask);
|
||||
free (npath);
|
||||
return 0;
|
||||
|
||||
+1
-2
@@ -121,7 +121,6 @@ extern int close (int);
|
||||
/* Static functions defined and used in this file. */
|
||||
static void close_pipes (int, int);
|
||||
static void do_piping (int, int);
|
||||
static void bind_lastarg (char *);
|
||||
static int shell_control_structure (enum command_type);
|
||||
static void cleanup_redirects (REDIRECT *);
|
||||
|
||||
@@ -4000,7 +3999,7 @@ execute_cond_command (COND_COM *cond_command)
|
||||
}
|
||||
#endif /* COND_COMMAND */
|
||||
|
||||
static void
|
||||
void
|
||||
bind_lastarg (char *arg)
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
@@ -120,4 +120,5 @@ extern void close_all_files (void);
|
||||
extern void restore_funcarray_state (struct func_array_state *);
|
||||
#endif
|
||||
|
||||
extern void bind_lastarg (char *);
|
||||
#endif /* _EXECUTE_CMD_H_ */
|
||||
|
||||
@@ -2849,7 +2849,7 @@ execute_variable_command (const char *command, const char *vname)
|
||||
parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE);
|
||||
|
||||
restore_parser_state (&ps);
|
||||
bind_variable ("_", last_lastarg, 0);
|
||||
bind_lastarg (last_lastarg);
|
||||
FREE (last_lastarg);
|
||||
|
||||
if (token_to_read == '\n') /* reset_parser was called */
|
||||
@@ -5636,7 +5636,27 @@ history_delimiting_chars (const char *line)
|
||||
last_was_heredoc = 0;
|
||||
|
||||
if (dstack.delimiter_depth != 0)
|
||||
return ("\n");
|
||||
{
|
||||
char ch;
|
||||
HIST_ENTRY *current;
|
||||
size_t curlen;
|
||||
|
||||
ch = current_delimiter(dstack);
|
||||
if (shellquote(ch))
|
||||
return ("\n");
|
||||
else if (ch == '(') /* ) and maybe for other non-quote-char delimiters */
|
||||
{
|
||||
using_history ();
|
||||
current = previous_history ();
|
||||
curlen = current ? strlen (current->line) : 0;
|
||||
/* If we're not reading some kind of quoted string, don't bother
|
||||
adding a newline if the current history entry already ends in a
|
||||
newline. It's just extra. */
|
||||
return ((curlen > 0 && current->line[curlen - 1] == '\n') ? "" : "\n");
|
||||
}
|
||||
else
|
||||
return ("\n");
|
||||
}
|
||||
|
||||
/* We look for current_command_line_count == 2 because we are looking to
|
||||
add the first line of the body of the here document (the second line
|
||||
|
||||
Binary file not shown.
+10
-10
@@ -11,7 +11,7 @@ msgstr ""
|
||||
"Project-Id-Version: bash 5.2-rc1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-11 14:50-0500\n"
|
||||
"PO-Revision-Date: 2022-07-28 01:08+0800\n"
|
||||
"PO-Revision-Date: 2023-02-09 00:40+0800\n"
|
||||
"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
|
||||
"Language-Team: Chinese (traditional) <zh-l10n@lists.linux.org.tw>\n"
|
||||
"Language: zh_TW\n"
|
||||
@@ -20,7 +20,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Bugs: Report translation errors to the Language-Team address.\n"
|
||||
"X-Generator: Poedit 3.1.1\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: arrayfunc.c:66
|
||||
msgid "bad array subscript"
|
||||
@@ -2762,7 +2762,7 @@ msgstr ""
|
||||
" 變更目前目錄至 <目錄>。預設的 <目錄> 是 shell 變數 HOME\n"
|
||||
" 的值。\n"
|
||||
" \n"
|
||||
" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:)分隔。\n"
|
||||
" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:) 分隔。\n"
|
||||
" 一個空的目錄名稱表示目前目錄。如果要切換到的 <目錄> 由斜線 (/) 開頭,則 CDPATH\n"
|
||||
" 變數不會被使用。\n"
|
||||
" \n"
|
||||
@@ -3188,7 +3188,7 @@ msgstr ""
|
||||
" Getopts 被 shell 過程用來將可定位的參數解析為選項。\n"
|
||||
" \n"
|
||||
" <選項字串> 字串包含待識別的選項字母。如果一個字母後面跟\n"
|
||||
" 著分號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n"
|
||||
" 著冒號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n"
|
||||
" \n"
|
||||
" 每次呼叫時,getopts 會將下一個選項放到 shell 變數 $name\n"
|
||||
" 中,如果 name 變數不存在則先將其初始化,而下一個待處\n"
|
||||
@@ -5007,22 +5007,22 @@ msgstr ""
|
||||
"常用 shell 變數名稱和使用。\n"
|
||||
" \n"
|
||||
" BASH_VERSION\t目前 Bash 的版本資訊。\n"
|
||||
" CDPATH\t用於「cd」指令參數搜尋分號分隔的目錄列表\n"
|
||||
" CDPATH\t傳入「cd」作為引數,冒號分隔的欲搜尋目錄清單\n"
|
||||
" GLOBIGNORE\t路徑擴充套件時忽略的檔名符合模式列表,\n"
|
||||
" \t\t以分號分隔。\n"
|
||||
" HISTFILE\t您的指令歷史記錄存放的檔案名稱。\n"
|
||||
" \t\t以冒號分隔。\n"
|
||||
" HISTFILE\t您的命令歷史記錄存放的檔案名稱。\n"
|
||||
" HISTFILESIZE\t歷史記錄檔案最多可以儲存的列數。\n"
|
||||
" HISTSIZE\t一個執行的 shell 最多可以訪問的歷史記錄指令列數。\n"
|
||||
" HISTSIZE\t一個執行的 shell 最多可以存取的歷史記錄命令列數。\n"
|
||||
" HOME\t您登入目錄的完整路徑。\n"
|
||||
" HOSTNAME\t目前主機的主機名稱。\n"
|
||||
" HOSTTYPE\t目前版本的 BASH 在其之上執行的 CPU 類型。\n"
|
||||
" IGNOREEOF\t控制 shell 收到檔案結束符做為單一輸入後的\n"
|
||||
" \t\t動作。如果設定這個變數,則它的值是 shell 結束之前在\n"
|
||||
" \t\t一個空列上可以連續看到的檔案結束符數量(預設為 10)。\n"
|
||||
" \t\t未設定時,檔案結束符標誌著輸入的結束。\n"
|
||||
" \t\t未設定時,檔案結束符旗標著輸入的結束。\n"
|
||||
" MACHTYPE\t描述目前執行 Bash 的系統字串。\n"
|
||||
" MAILCHECK\tBash 檢測新郵件的頻率,以秒為單位。\n"
|
||||
" MAILPATH\tBash 從中檢測新郵件的檔案列表,以分號分隔。\n"
|
||||
" MAILPATH\tBash 從中檢測新郵件的檔案列表,以冒號分隔。\n"
|
||||
" OSTYPE\t執行 Bash 的 Unix 版本。\n"
|
||||
" PATH\t當尋找指令時搜尋的目錄列表,以冒號分隔。\n"
|
||||
" PROMPT_COMMAND\t印出每一個主提示符之前執行的命\n"
|
||||
|
||||
Reference in New Issue
Block a user