]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix for $_ when executing $PROMPT_COMMAND; fix for extra line in history after here...
authorChet Ramey <chet.ramey@case.edu>
Mon, 13 Feb 2023 15:48:05 +0000 (10:48 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 13 Feb 2023 15:48:05 +0000 (10:48 -0500)
CWRU/CWRU.chlog
bashline.c
builtins/declare.def
doc/bash.1
doc/bashref.texi
examples/loadables/mkdir.c
execute_cmd.c
execute_cmd.h
parse.y
po/zh_TW.gmo
po/zh_TW.po

index 51dbb384b85084255d092e7ef6b9271bd489d134..8f41fe846be9af8391fc8d071bd02eb660447be8 100644 (file)
@@ -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>
index f46657593145f04dcb94e2010e8ff7e781e87d65..dfe5ab9bf913e6069365453b616a01b667a2ea74 100644 (file)
@@ -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);
index f7dac7287509824cbfe53585a3fcb6e405289532..28100de1b858e8204626b395504edfcf3867a076 100644 (file)
@@ -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 ();
        }
 
index 4efb67652ea11d3bf5a4ace0487bf62002fbdb74..376e347e0add7a8073bfd2cc59ce733f9e9bfa4c 100644 (file)
@@ -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.
index 5b44ce74e20bdbcfeba1924135ca6dc57ba5d912..bd24d7151a775dc4f2f2ae8c4696cedbc633f03a 100644 (file)
@@ -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.
index b0df8f0d66a183668872b72c0ae18d48b5280fc8..55ffbd07d3704e79a656f11a09b3625225633a8b 100644 (file)
@@ -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)
            {
-             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;
index d4c082d044591a933f08bdb6a2c4fa0c9c528163..18540409968977dc156c315fd101639c4a86f922 100644 (file)
@@ -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;
index 37e386ab1e8cf116f31ae8a52ebb128f6ef0c192..d9c3e7b13d7ae1195d21544f140a0a30bf5d567f 100644 (file)
@@ -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_ */
diff --git a/parse.y b/parse.y
index 379fdaadb8790da6c3b4fa53aa438cdf239335d8..9178e9a7d3bf26d0eb74566d2d4c624bfe36f14b 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -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
index 9dd7546f07248c44a395e1f7799c47f982dd372b..a56fe55c75266bcd659458f9740b30e4b2516bf1 100644 (file)
Binary files a/po/zh_TW.gmo and b/po/zh_TW.gmo differ
index 91724f83ea164f5f0c6c3e2f1c1b7fe279d0480c..cae8439204e87a283f5c81879e9977f64c183346 100644 (file)
@@ -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"
-"    è\91\97å\88\86號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n"
+"    è\91\97å\86\92號,則該選項需要一個參數,這個參數應利用空格與選項分開。\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以å\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"