Re: PWD not made canonical on shell start
On Wed, May 24, 2017 at 11:53:45AM -0400, Chet Ramey wrote: [...] > It was changed back in 2015 as the result of > > http://lists.gnu.org/archive/html/bug-bash/2015-09/msg00053.html After reading POSIX's [1] (section 2.5.3 "Shell Variables"), I noticed that bash may not be following the specification. This is what the description of `PWD' says: | PWD | Set by the shell and by the cd utility. In the shell the value shall be | initialized from the environment as follows. If a value for PWD is passed to | the shell in the environment when it is executed, the value is an absolute | pathname of the current working directory that is no longer than {PATH_MAX} | bytes including the terminating null byte, and the value does not contain any | components that are dot or dot-dot, then the shell shall set PWD to the value | from the environment. Otherwise, if a value for PWD is passed to the shell in | the environment when it is executed, the value is an absolute pathname of the | current working directory, and the value does not contain any components that | are dot or dot-dot, then it is unspecified whether the shell sets PWD to the | value from the environment or sets PWD to the pathname that would be output by | pwd -P. Otherwise, the sh utility sets PWD to the pathname that would be output | by pwd -P. In cases where PWD is set to the value from the environment, the | value can contain components that refer to files of type symbolic link. In | cases where PWD is set to the pathname that would be output by pwd -P, if there | is insufficient permission on the current working directory, or on any parent | of that directory, to determine what that pathname would be, the value of PWD | is unspecified. Assignments to this variable may be ignored. If an application | sets or unsets the value of PWD, the behaviors of the cd and pwd utilities are | unspecified. My interpretation is the following: case 1) If PWD is passed through the environment, and the value is an absolute pathname of the CWD and the value is no longer than PATH_MAX and the value does not contain any components that are dot or dot-dot, then set PWD to the value from the environment. case 2) The same as case 1, except for the restriction on PATH_MAX. The result is unspecified. case 3) If case 1 and 2 do not apply, then set PWD=$(pwd -P) Bash doesn't really do that. What bash does is: case 1) If PWD is passed through the environment, and the value is an absolute pathname of the CWD, then set PWD to the current value from the environment case 2) If case 1 does not apply, and the shell is an interactive shell, and the shell is a login shell, and $HOME is the same as the CWD, then set PWD=$HOME case 3) If case 2 does not apply, then call getcwd() and sets PWD to the return value. The patch below makes bash behave as described by POSIX. diff --git a/variables.c b/variables.c index 944de86e..dbf21339 100644 --- a/variables.c +++ b/variables.c @@ -827,49 +827,39 @@ initialize_shell_level () /* If we got PWD from the environment, update our idea of the current working directory. In any case, make sure that PWD exists before checking it. It is possible for getcwd () to fail on shell startup, - and in that case, PWD would be undefined. If this is an interactive - login shell, see if $HOME is the current working directory, and if - that's not the same string as $PWD, set PWD=$HOME. */ - + and in that case, PWD would be undefined. */ void set_pwd () { SHELL_VAR *temp_var, *home_var; - char *temp_string, *home_string, *current_dir; - - home_var = find_variable ("HOME"); - home_string = home_var ? value_cell (home_var) : (char *)NULL; + char *temp_string, *current_dir, *last_component; temp_var = find_variable ("PWD"); /* Follow posix rules for importing PWD */ if (temp_var && imported_p (temp_var) && (temp_string = value_cell (temp_var)) && temp_string[0] == '/' && + !strstr(temp_string, "/./") && + !strstr(temp_string, "/../") && + (last_component=strrchr(temp_string, '/')) && + strcmp(last_component, ".") && + strcmp(last_component, "..") && same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL)) { - current_dir = sh_canonpath (temp_string, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); - if (current_dir == 0) - current_dir = get_working_directory ("shell_init"); - else - set_working_directory (current_dir); - free (current_dir); -} - else if (home_string && interactive_shell && login_shell && - same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL)) -{ - set_working_directory (home_string); - temp_var = bind_variable ("PWD", home_string, 0); - set_auto_export (temp_var); + set_working_directory (temp_string); } else { - temp_string = get_working_directory ("shell-init"); - if (t
Re: read -e allows execution of commands (edit-and-execute-command) as the shell's process user
On Mon, May 29, 2017 at 12:29:16AM -0400, George Caswell wrote: [...] > Bash's builtin function "read" has one simple job: read data, return > it to the caller. There shouldn't be anything in there about executing > commands. > > Why does read even need a function like this? Is it something that was > useful in the days before job control? ##SELECTION_END## The -e flag causes read to use GNU Readline if the input comes from a terminal. This is *very* useful, since Readline allows you to perform text manipulation functions, completion, advanced cursor movement, etc. Also, the likelyhood of this being a real security issue is very small. -- Eduardo Bustamante https://dualbus.me/
Re: {varname} redirection for a command or group leaves the file open
On 5/19/17 4:32 PM, tetsu...@scope-eye.net wrote: > > Well, that's disappointing. So there is no technical reason for > this behavior > > other than copying the behavior of ksh. BTW zsh does the right > thing and in the > > following scenario: > > > > ls -lh /proc/self/fd {fd}>/dev/null > > > > and it closes the file descriptor after the command has completed. Face it: there's no real reason to implement this construct, period, and especially little reason for the way the Korn shell does it. A script can trivially emulate the ksh usage by picking the file descriptor and performing the variable assignment itself; this construct is minimal syntactic sugar. I think Korn introduced it to overcome the traditional sh restriction of the user-modifiable file descriptors to the range 0-9. Bash doesn't have that limitation, so that's not enough of a reason to do it. The way bash implements it offers features that are not available in any other use. While the not-closing aspects can be emulated using `exec', a file descriptor manipulated with `exec' is close-on-exec. Bash offers a direct analogue to the open system call. Now, bash does implement some other constructs that are nothing but syntactic sugar (|&), but only after user requests. There aren't any user requests for this, so a purely syntactic sugar feature isn't any direct user benefit. There needs to be something that isn't otherwise available. It's kind of flip to recommend not using it if you don't like it, but that's pretty much the case here. Or accept the rationale and work around it. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Builtin history -r does not work with named pipes (i.e. GNU readline's histfile.c read_history_range)
On 5/23/17 11:32 AM, Eduardo Bustamante wrote: > (I think this is a good problem for Pranav to tackle if you consider > this to be a bug, Chet). > > The problem is that fstat(2) will return an st_size of 0 if the file > is non-regular. I think that the easiest path here is to goto > `error_and_exit' if `file' is not a regular file (and perhaps print a > useful error message?). So the bug is that readline doesn't print an error message if the history file isn't a regular file? -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Builtin history -r does not work with named pipes (i.e. GNU readline's histfile.c read_history_range)
On Mon, May 29, 2017 at 04:17:16PM -0400, Chet Ramey wrote: [...] > So the bug is that readline doesn't print an error message if the history > file isn't a regular file? Correct. Another problem is that the history builtin doesn't propagate back a meaningful return code indicating that there was a problem. A simple example is that you're trying to seed your history by appending the output of a command using `history -r'. So you might try: | $ history -cr <(echo a complex command); echo $?; history | 0 But for some reason that doesn't work and there is no apparent problem with it. Whereas the following does work: | $ history -cr /dev/stdin <<<'a complex command'; echo $?; history | 0 | 1 a complex command Or, which indicates that something went wrong: | $ history -cr /tmp; echo $?; history | 1 In my opinion it should at least return an error code. And if possible an error message. The other option is to implement support for reading from non-regular files, but I'm not sure if it's worth it. -- Eduardo Bustamante https://dualbus.me/
Re: Builtin history -r does not work with named pipes (i.e. GNU readline's histfile.c read_history_range)
On 5/29/17 4:40 PM, dualbus wrote: > On Mon, May 29, 2017 at 04:17:16PM -0400, Chet Ramey wrote: > [...] >> So the bug is that readline doesn't print an error message if the history >> file isn't a regular file? > > Correct. Another problem is that the history builtin doesn't propagate > back a meaningful return code indicating that there was a problem. OK, that's an easy fix. It wasn't clear whether this was the problem, or whether the original poster was complaining that the lack of support for non-regular files was the bug. Thanks. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: PWD not made canonical on shell start
On 5/29/17 12:22 PM, dualbus wrote: > Bash doesn't really do that. What bash does is: This isn't quite an accurate representation of the bash behavior. > > case 1) > > If PWD is passed through the environment, > and the value is an absolute pathname of the CWD, > then set PWD to the current value from the environment If PWD appears in the environment, and it is an absolute pathname of the CWD, set PWD to the canonicalized version of the environment value. The canonicalized version removes . and .., makes sure that the length is less than PATH_MAX, and validates that at each step, removing . and .. results in a valid pathname. If canonicalization fails, PWD gets the value that would be printed by pwd -P if PWD were not set. > > case 2) > > If case 1 does not apply, > and the shell is an interactive shell, > and the shell is a login shell, > and $HOME is the same as the CWD, > then set PWD=$HOME This is to avoid long NFS pathnames from the equivalent of pwd -P when the current directory is obviously the home directory. > > case 3) > > If case 2 does not apply, > then call getcwd() and sets PWD to the return value. That's the behavior of pwd -P when PWD is not set (which it obviously is not). > The patch below makes bash behave as described by POSIX. I'm comfortable with the bash behavior. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: PWD not made canonical on shell start
On Mon, May 29, 2017 at 06:25:06PM -0400, Chet Ramey wrote: [...] > If PWD appears in the environment, and it is an absolute pathname of the > CWD, set PWD to the canonicalized version of the environment value. The > canonicalized version removes . and .., makes sure that the length is > less than PATH_MAX, and validates that at each step, removing . and .. > results in a valid pathname. If canonicalization fails, PWD gets the value > that would be printed by pwd -P if PWD were not set. That's not quite true. In variables.c `set_pwd', there's the following: 843 temp_var = find_variable ("PWD"); 844 /* Follow posix rules for importing PWD */ 845 if (temp_var && imported_p (temp_var) && 846 (temp_string = value_cell (temp_var)) && 847 temp_string[0] == '/' && 848 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL)) 849 { 850 current_dir = sh_canonpath (temp_string, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); 851 if (current_dir == 0) 852 current_dir = get_working_directory ("shell_init"); 853 else 854 set_working_directory (current_dir); 855 free (current_dir); 856 } `current_dir' is a copy of `temp_string' which holds the canonicalized version of the environment value. That's true. *But* PWD is not re-set to the value of `current_dir'. Instead, it has the same value as passed through the environment (i.e. `temp_string'). For completeness, in builtins/common.c `set_working_directory' just updates a global variable, but doesn't touch the value of the PWD variable. 589 /* Make NAME our internal idea of the current working directory. */ 590 void 591 set_working_directory (name) 592 char *name; 593 { 594 FREE (the_current_working_directory); 595 the_current_working_directory = savestring (name); 596 } Hence, my initial patch: diff --git a/variables.c b/variables.c index 944de86e..62f9f229 100644 --- a/variables.c +++ b/variables.c @@ -852,6 +852,8 @@ set_pwd () current_dir = get_working_directory ("shell_init"); else set_working_directory (current_dir); + temp_var = bind_variable ("PWD", current_dir); + set_auto_export (temp_var); free (current_dir); } else if (home_string && interactive_shell && login_shell &&
Re: {varname} redirection for a command or group leaves the file open
On Mon, 2017-05-29 at 15:36 -0400, Chet Ramey wrote: > > > > > > Well, that's disappointing. So there is no technical reason for > > this behavior > > > other than copying the behavior of ksh. BTW zsh does the right > > thing and in the > > > following scenario: > > > > > > ls -lh /proc/self/fd {fd}>/dev/null > > > > > > and it closes the file descriptor after the command has completed. > Face it: there's no real reason to implement this construct, period, and > especially little reason for the way the Korn shell does it. A script > can trivially emulate the ksh usage by picking the file descriptor and > performing the variable assignment itself; this construct is minimal > syntactic sugar. The way Korn shell does it makes sense, it is consistent with the way other file redirections work. Normally redirecting any command applies just to that command, and not to surrounding code. "exec" is the exception to the rule, a redirection that stays open. (If there was no reason to implement the construct, why was it implemented?) And it is not "trivial" for a shell script to even find an unused file descriptor EXCEPT by using the dynamic FD assignment syntax, which does it for you. And even if your shell code could find a vacant file descriptor to use, you can't do this: $ fd=$(find_vacant_fd) $ exec $fd The way bash implements it offers features that are not available in any > other use. > It really doesn't. And Bash's behavior seems very inconsistent, even nonsensically so: "cmd --fd=$fd {fd} While the not-closing aspects can be emulated using `exec', a file descriptor > manipulated with `exec' is close-on-exec. Bash offers a direct analogue > to the open system call. > Even if that were true, it makes no sense. File redirections should not outlive the command they're attached to - unless the command is "exec". And files opened with "exec" are not close-on-exec: $ exec {fd} /home/tetsujin/src/bash-4.3/README The file was opened with "exec" and didn't close-on-exec when "ls" was run. (CLOEXEC files are almost useless in Bash, because you have no way in the shell to hand that file to another process. Even if you duplicate it with a redirection, the duplicate is set CLOEXEC as well.)
Re: read -e allows execution of commands (edit-and-execute-command) as the shell's process user
On Mon, 2017-05-29 at 11:37 -0500, dualbus wrote: > On Mon, May 29, 2017 at 12:29:16AM -0400, George Caswell wrote: > [...] > > > > Bash's builtin function "read" has one simple job: read data, return > > it to the caller. There shouldn't be anything in there about executing > > commands. > > > > Why does read even need a function like this? Is it something that was > > useful in the days before job control? ##SELECTION_END## > The -e flag causes read to use GNU Readline if the input comes from a > terminal. This is *very* useful You misunderstand. Being able to use Readline in "read" is great! And "edit-and-execute-command" may have its uses when invoked from an interactive shell session. But why is "edit-and-execute-command" useful or in any way desirable in "read"? If you were using "read -e" in a script, and someone wanted to run some commands, they could suspend the script with job control, or open another terminal window to run some commands. The feature is unnecessary, and has no business being a part of "read".
Re: Builtin history -r does not work with named pipes (i.e. GNU readline's histfile.c read_history_range)
So I can't take up this one? Regards, Pranav On May 30, 2017 2:35 AM, "Chet Ramey" wrote: > On 5/29/17 4:40 PM, dualbus wrote: > > On Mon, May 29, 2017 at 04:17:16PM -0400, Chet Ramey wrote: > > [...] > >> So the bug is that readline doesn't print an error message if the > history > >> file isn't a regular file? > > > > Correct. Another problem is that the history builtin doesn't propagate > > back a meaningful return code indicating that there was a problem. > > OK, that's an easy fix. It wasn't clear whether this was the problem, or > whether the original poster was complaining that the lack of support for > non-regular files was the bug. Thanks. > > Chet > > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~ > chet/ >