---
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
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>
{
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;
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);
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);
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 ();
}
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.
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.
/* 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
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)
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)
{
- builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
- umask (original_umask);
- free (npath);
- return 1;
+ 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;
+ }
}
- if (chmod (npath, parent_mode) != 0)
+ else
{
- builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno));
+ builtin_error ("cannot create 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;
/* 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 *);
}
#endif /* COND_COMMAND */
-static void
+void
bind_lastarg (char *arg)
{
SHELL_VAR *var;
extern void restore_funcarray_state (struct func_array_state *);
#endif
+extern void bind_lastarg (char *);
#endif /* _EXECUTE_CMD_H_ */
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 */
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
"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"
"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"
" 變更目前目錄至 <目錄>。預設的 <目錄> 是 shell 變數 HOME\n"
" 的值。\n"
" \n"
-" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:)分隔。\n"
+" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:) 分隔。\n"
" 一個空的目錄名稱表示目前目錄。如果要切換到的 <目錄> 由斜線 (/) 開頭,則 CDPATH\n"
" 變數不會被使用。\n"
" \n"
" Getopts 被 shell 過程用來將可定位的參數解析為選項。\n"
" \n"
" <選項字串> 字串包含待識別的選項字母。如果一個字母後面跟\n"
-" è\91\97å\88\86號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n"
+" è\91\97å\86\92號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n"
" \n"
" 每次呼叫時,getopts 會將下一個選項放到 shell 變數 $name\n"
" 中,如果 name 變數不存在則先將其初始化,而下一個待處\n"
"常用 shell 變數名稱和使用。\n"
" \n"
" BASH_VERSION\t目前 Bash 的版本資訊。\n"
-" CDPATH\t用於「cd」指令參數搜尋分號分隔的目錄列表\n"
+" CDPATH\t傳入「cd」作為引數,冒號分隔的欲搜尋目錄清單\n"
" GLOBIGNORE\t路徑擴充套件時忽略的檔名符合模式列表,\n"
-" \t\t以å\88\86號分隔。\n"
-" HISTFILE\t您的指令歷史記錄存放的檔案名稱。\n"
+" \t\t以å\86\92號分隔。\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æ\9cªè¨å®\9aæ\99\82ï¼\8cæª\94æ¡\88çµ\90æ\9d\9f符æ¨\99èª\8c著輸入的結束。\n"
+" \t\tæ\9cªè¨å®\9aæ\99\82ï¼\8cæª\94æ¡\88çµ\90æ\9d\9f符æ\97\97æ¨\99著輸入的結束。\n"
" MACHTYPE\t描述目前執行 Bash 的系統字串。\n"
" MAILCHECK\tBash 檢測新郵件的頻率,以秒為單位。\n"
-" MAILPATH\tBash å¾\9e䏿ª¢æ¸¬æ\96°é\83µä»¶ç\9a\84æª\94æ¡\88å\88\97表ï¼\8c以å\88\86號分隔。\n"
+" MAILPATH\tBash å¾\9e䏿ª¢æ¸¬æ\96°é\83µä»¶ç\9a\84æª\94æ¡\88å\88\97表ï¼\8c以å\86\92號分隔。\n"
" OSTYPE\t執行 Bash 的 Unix 版本。\n"
" PATH\t當尋找指令時搜尋的目錄列表,以冒號分隔。\n"
" PROMPT_COMMAND\t印出每一個主提示符之前執行的命\n"