Re: $HOME does not get abbreviated in prompt \w output when there is a trailing slash

2014-05-29 Thread Libor Pechacek
On Fri 23-05-14 06:13:13, Eric Blake wrote:
> On 05/23/2014 02:32 AM, Libor Pechacek wrote:
> 
> > +++ b/general.c
> > @@ -699,7 +699,10 @@ polite_directory_format (name)
> >int l;
> >  
> >home = get_string_value ("HOME");
> > -  l = home ? strlen (home) : 0;
> > +
> > +  /* remove trailing slashes from $HOME before comparisons */
> > +  for (l = home ? strlen (home) : 0; l > 1 && home[l-1] == '/'; l--);
> > +
> 
> Does this still work correctly on systems where / and // are distinct
> (as allowed by POSIX) and someone has set $HOME to //?

Good question.  The trimming should not be applied to paths shorter than two
characters.  As part of the testing, I've found another bug.  Updated patch
attached.

This is how Bash behaves without the patch:
bash-master-4.3$ cd
bash-master-4.3$ PS1='\w | \W \$ '
~ | ~ $ HOME=/home
/home.local/lpechacek | lpechacek $ cd
~ | ~ $ HOME=/home/
/home | home $ cd
/home | home $ HOME=//home
/home | home $ cd
~ | ~ $ HOME=//home/
//home | home $ cd
//home | home $ HOME=/
//home | home $ cd
/ | / $ HOME=//
/ | / $ cd
~ | ~ $ exit

and this is behavior with the patch:
bash-4.3$ cd
bash-4.3$ PS1='\w | \W \$ '
~ | ~ $ HOME=/home
/home.local/lpechacek | lpechacek $ cd
~ | ~ $ HOME=/home/
~ | ~ $ cd
~ | ~ $ HOME=//home
/home | home $ cd
~ | ~ $ HOME=//home/
~ | ~ $ cd
~ | ~ $ HOME=/
//home | home $ cd
/ | / $ HOME=//
/ | / $ cd
~ | ~ $ exit


>From ef9c5e823131098d90b3f2aabaf539df59a01cba Mon Sep 17 00:00:00 2001
From: Libor Pechacek 
Date: Fri, 23 May 2014 09:30:49 +0200
Subject: [PATCH] Make \w and \W tolerate trailing slash in $HOME

Currently \w and \W abbreviate $HOME into tilde only when it ends with a
character different from slash.  This patch makes them tolerate trailing
slashes.
---
 general.c |  5 -
 parse.y   | 10 --
 y.tab.c   | 10 --
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/general.c b/general.c
index 087689eb74cc..02163d3079c3 100644
--- a/general.c
+++ b/general.c
@@ -699,7 +699,10 @@ polite_directory_format (name)
   int l;
 
   home = get_string_value ("HOME");
-  l = home ? strlen (home) : 0;
+
+  /* remove trailing slashes from $HOME before comparisons */
+  for (l = home ? strlen (home) : 0; l > 2 && home[l-1] == '/'; l--);
+
   if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
 {
   strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
diff --git a/parse.y b/parse.y
index 91bf3bf649bd..91fbaaa924de 100644
--- a/parse.y
+++ b/parse.y
@@ -5384,7 +5384,7 @@ decode_prompt_string (string)
  {
/* Use the value of PWD because it is much more efficient. */
char t_string[PATH_MAX];
-   int tlen;
+   int tlen, l;
 
temp = get_string_value ("PWD");
 
@@ -5415,7 +5415,13 @@ decode_prompt_string (string)
 #define ROOT_PATH(x)   ((x)[0] == '/' && (x)[1] == 0)
 #define DOUBLE_SLASH_ROOT(x)   ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
/* Abbreviate \W as ~ if $PWD == $HOME */
-   if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || 
STREQ (t, t_string) == 0))
+   /* remove trailing slashes from $HOME before comparisons */
+   t = get_string_value ("HOME");
+   for (l = t ? strlen (t) : 0; l > 2 && t[l-1] == '/'; l--);
+   if (l)
+ t[l] = 0;
+
+   if (c == 'W' && ((t == 0) || STREQ (t, t_string) == 0))
  {
if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT 
(t_string) == 0)
  {
diff --git a/y.tab.c b/y.tab.c
index 80fe9308398e..d9bf6b1d056a 100644
--- a/y.tab.c
+++ b/y.tab.c
@@ -7696,7 +7696,7 @@ decode_prompt_string (string)
  {
/* Use the value of PWD because it is much more efficient. */
char t_string[PATH_MAX];
-   int tlen;
+   int tlen, l;
 
temp = get_string_value ("PWD");
 
@@ -7727,7 +7727,13 @@ decode_prompt_string (string)
 #define ROOT_PATH(x)   ((x)[0] == '/' && (x)[1] == 0)
 #define DOUBLE_SLASH_ROOT(x)   ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
/* Abbreviate \W as ~ if $PWD == $HOME */
-   if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || 
STREQ (t, t_string) == 0))
+   /* remove trailing slashes from $HOME before comparisons */
+   t = get_string_value ("HOME");
+   for (l = t ? strlen (t) : 0; l > 2 && t[l-1] == '/'; l--);
+   if (l)
+ t[l] = 0;
+
+   if (c == 'W' && ((t == 0) || STREQ (t, t_string) == 0))
  {
if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT 
(t_string) == 0)
  {
-- 
1.7.12.4




bug-bash@gnu.org

2014-05-29 Thread Dale R. Worley
Version:  GNU bash, version 4.2.47(1)-release (x86_64-redhat-linux-gnu)

Problem:  Manual page does not describe the redirection form "n>&-".

The manual page section "Duplicating File Descriptors" is as follows:

   Duplicating File Descriptors
   The redirection operator

  [n]<&word

   is used to duplicate input file descriptors.  If word expands to one or
   more digits, the file descriptor denoted by n is made to be a  copy  of
   that  file  descriptor.   If  the  digits in word do not specify a file
   descriptor open for input, a redirection error occurs.  If word  evalu‐
   ates  to  -,  file  descriptor n is closed.  If n is not specified, the
   standard input (file descriptor 0) is used.

   The operator

  [n]>&word

   is used similarly to duplicate output file descriptors.  If  n  is  not
   specified,  the  standard  output  (file descriptor 1) is used.  If the
   digits in word do not specify a file descriptor open for output, a  re‐
   direction  error  occurs.  As a special case, if n is omitted, and word
   does not expand to one or more digits, the standard output and standard
   error are redirected as described previously.

However, the last paragraph does not describe the form "n>&-" (which
does close descriptor n).  Perhaps that is implied by "similarly", but
it would be better to spell it out:

   is used similarly to duplicate output file descriptors.  If
   word expands to one or more digits, the file descriptor denoted
   by n is made to be a copy of that file descriptor.  If the
   digits in word do not specify a file descriptor open for
   output, a redirection error occurs.  If word expands to -,
   file descriptor n is closed.  If n is not specified, the
   standard output (file descriptor 1) is used.  As a special
   case, if n is omitted, and word does not expand to one or more
   digits, the standard output and standard error are redirected
   as described previously.

In addition, the word "evaluates" in the first paragraph should be
"expands".

The change to file bash.1 is:

--- /home/worley/temp/b02014-05-29 14:56:17.631508858 -0400
+++ /home/worley/temp/b12014-05-29 14:59:00.596458326 -0400
@@ -17,7 +17,7 @@
 do not specify a file descriptor open for input, a redirection error occurs.
 If
 .I word
-evaluates to
+expands to
 .BR \- ,
 file descriptor
 .I n
@@ -31,12 +31,24 @@
 [\fIn\fP]\fB>&\fP\fIword\fP
 .RE
 .PP
-is used similarly to duplicate output file descriptors.  If
+is used similarly to duplicate output file descriptors.
+If
+.I word
+expands to one or more digits, the file descriptor denoted by
 .I n
-is not specified, the standard output (file descriptor 1) is used.
+is made to be a copy of that file descriptor.
 If the digits in
 .I word
 do not specify a file descriptor open for output, a redirection error occurs.
+If
+.I word
+expands to
+.BR \- ,
+file descriptor
+.I n
+is closed.  If
+.I n
+is not specified, the standard output (file descriptor 1) is used.
 As a special case, if \fIn\fP is omitted, and \fIword\fP does not
 expand to one or more digits, the standard output and standard
 error are redirected as described previously.

Dale



bug-bash@gnu.org

2014-05-29 Thread Eduardo A . Bustamante López
> However, the last paragraph does not describe the form "n>&-" (which
> does close descriptor n).  Perhaps that is implied by "similarly", but
> it would be better to spell it out:
> 
>is used similarly to duplicate output file descriptors.  If
>word expands to one or more digits, the file descriptor denoted
>by n is made to be a copy of that file descriptor.  If the
>digits in word do not specify a file descriptor open for
>output, a redirection error occurs.  If word expands to -,
>file descriptor n is closed.  If n is not specified, the
>standard output (file descriptor 1) is used.  As a special
>case, if n is omitted, and word does not expand to one or more
>digits, the standard output and standard error are redirected
>as described previously.
Hmm, I'd recommend to always check the most recent bash version. I
don't have the most recent, but I already have this:

|   Duplicating File Descriptors
|   The redirection operator
|
|  [n]<&word
|
|   is  used  to  duplicate input file descriptors.  If word expands to one 
or more digits, the file descriptor denoted by n is
|   made to be a copy of that file descriptor.  If the digits in word do 
not specify a file descriptor open for input, a  redi‐
|   rection  error  occurs.   If  word  evaluates to -, file descriptor n 
is closed.  If n is not specified, the standard input
|   (file descriptor 0) is used.
|
|   The operator
|
|  [n]>&word
|
|   is used similarly to duplicate output file descriptors.  If n is not 
specified, the standard output (file descriptor 1)  is
|   used.   If the digits in word do not specify a file descriptor open for 
output, a redirection error occurs.  If word evalu‐
|   ates to -, file descriptor n is closed.  As a special case, if n is 
omitted, and word does not expand to one or more digits
|   or -, the standard output and standard error are redirected as 
described previously.

Note the "If word evaluates to -," in both cases. Also, I wouldn't be
that picky on "evaluate" vs "expand", because they can be used
interchangeable here.