Re: 'cd' if HOME is unset
On Sun, 25 Dec 2022, Michael Cheponis wrote: > Maybe it should print "$HOME is not set" in that case? Some shells do just that, some fail silently, and some figure it out w/o $HOME set: $ for s in /bin/{sh,csh,ksh} /usr/pkg/bin/{bash,zsh}; do \ echo "### ${s}"; ${s} -c "cd /tmp; unset HOME; cd; pwd"; echo; done ### /bin/sh cd: HOME not set /tmp ### /bin/csh /home/dummy ### /bin/ksh /bin/ksh: cd: no home directory (HOME not set) /tmp ### /usr/pkg/bin/bash /usr/pkg/bin/bash: line 1: cd: HOME not set /tmp ### /usr/pkg/bin/zsh /tmp Oh, csh is special and it uses "home" instead of "HOME", and fails hard when it's unset: $ /bin/csh -c "cd /tmp; unset HOME home; cd; pwd" cd: No home directory. (NB: there's nothing NetBSD specific here, the same happens on other platforms too) C. -- BOFH excuse #240: Too many little pins on CPU confusing it, bend back and forth until 10-20% are neatly removed. Do _not_ leave metal bits visible!
Re: 'cd' if HOME is unset
Date:Mon, 26 Dec 2022 10:41:25 -0800 From:Michael Cheponis Message-ID: | Well, as a zsh user: What zsh does you'd need to take up with zsh developers. But it is one of 2 shells I tested which don't require HOME to be set for "cd". zsh I am not all that surprised about. It tends not to concentrate a lot on conformance with other shells, but rather on what its designers believe is better for its users.(The other that does not error is dash). | $ echo $HOME | /usr/mac | $ unset HOME | $ echo $HOME | | $ zsh -c cd | $(no change in directory, no error msg) No error message, yes, but are you sure there was no change in directory? (Even if that change was into the directory it started from). jacaranda$ (cd /; unset HOME; zsh -c 'cd; pwd') /home/kre Looks like it changed directory to me (from / to /home/kre - my normal home). | in all cases, directory does not change when HOME is not defined. Note that in the test cases (like "(unset HOME; zsh -c cd)") the subshell (parentheses) are so the "unset HOME" doesn't affect the shell from which the command is run (you won't need to set HOME again after the test), and the cd is run only in the context of the shell that runs it, so only that process has its directory changed - in this test, that shell exits immediately after, so doing the change this way is normally pointless, here, it was done solely for the purpose of viewing the error message (if any). In the form I use above, rather than simply exit, the shell that ran the "cd" then ran "pwd" after, to reveal what its directory was now. You could change the command string to "pwd; cd; pwd" to see before and after directories. kre
Re: 'cd' if HOME is unset
Well, as a zsh user: $ echo $HOME /usr/mac $ unset HOME $ echo $HOME $ zsh -c cd $(no change in directory, no error msg) also: $ HOME=/usr/mac $ echo $HOME /usr/mac $ (unset HOME; zsh -c cd) $ (no error msg) in all cases, directory does not change when HOME is not defined. On Mon, Dec 26, 2022 at 9:47 AM Robert Elz wrote: > Date:Sun, 25 Dec 2022 15:33:57 -0800 > From:Michael Cheponis > Message-ID: 5rw...@mail.gmail.com> > > | Maybe it should print "$HOME is not set" in that case? > > Did you try it? > > It is easy... > > (unset HOME; sh -c cd) > > or use ksh (or some other shell) instead of sh to test it. > > Script started on Tue Dec 27 00:01:34 2022 > jacaranda$ (unset HOME; sh -c cd) > cd: HOME not set > jacaranda$ (unset HOME; ksh -c cd) > ksh: cd: no home directory (HOME not set) > jacaranda$ exit > > Script done on Tue Dec 27 00:03:06 2022 > > > Note HOME not $HOME is not set, $HOME is, if > HOME is set, a pathname, or if HOME is not set, "", > neither of which makes any sense to describe as 'not set'. > > kre >
Re: 'cd' if HOME is unset
Date:Sun, 25 Dec 2022 15:33:57 -0800 From:Michael Cheponis Message-ID: | Maybe it should print "$HOME is not set" in that case? Did you try it? It is easy... (unset HOME; sh -c cd) or use ksh (or some other shell) instead of sh to test it. Script started on Tue Dec 27 00:01:34 2022 jacaranda$ (unset HOME; sh -c cd) cd: HOME not set jacaranda$ (unset HOME; ksh -c cd) ksh: cd: no home directory (HOME not set) jacaranda$ exit Script done on Tue Dec 27 00:03:06 2022 Note HOME not $HOME is not set, $HOME is, if HOME is set, a pathname, or if HOME is not set, "", neither of which makes any sense to describe as 'not set'. kre
Re: 'cd' if HOME is unset
Maybe it should print "$HOME is not set" in that case? On Sun, Dec 25, 2022 at 2:52 PM Valery Ushakov wrote: > On Sat, Dec 24, 2022 at 22:32:22 -0500, Jan Schaumann wrote: > > > Robert Elz wrote: > > > Why bother? > > > > I happily admit that it's a rare edge case. I simply > > find it surprising that 'cd' gives up if HOME is > > unset. Seems unintuitive to me. > > Some would say, "gives up", some would say it makes you aware you have > a problem. :) > > DWIM is enticing, sure, but at some point it trasmutes into that > JavaScript "WAT" talk moment. > > -uwe >
Re: 'cd' if HOME is unset
On Sat, Dec 24, 2022 at 22:32:22 -0500, Jan Schaumann wrote: > Robert Elz wrote: > > Why bother? > > I happily admit that it's a rare edge case. I simply > find it surprising that 'cd' gives up if HOME is > unset. Seems unintuitive to me. Some would say, "gives up", some would say it makes you aware you have a problem. :) DWIM is enticing, sure, but at some point it trasmutes into that JavaScript "WAT" talk moment. -uwe
Re: 'cd' if HOME is unset
Date:Sat, 24 Dec 2022 22:32:22 -0500 From:Jan Schaumann Message-ID: | I happily admit that it's a rare edge case. I simply | find it surprising that 'cd' gives up if HOME is | unset. Seems unintuitive to me. It is how it is defined to work, and always has been. Only dash and zsh seem to handle that case, no other shells bother. (I am a little surprised that dash does, their general philosophy tends towards minimalist implementation, with almost nothing that isn't required). Better is just to always have HOME set. For /bin/sh ~ works without HOME, so you could define cd() { case "$#" in 0) set -- ~ ;; esac command cd "$@" } if you wanted to. But that's not required to work either (I'm not surprised that dash doesn't expand ~ when HOME is not set, that's more in line with what I'd expect ... though tilde expansion working is, in general, more useful, than cd with no args when HOME is unset, so if a shell was to do just one, I'd generally do it the way we do (as does bash)). kre ps: I am a little surprised that csh acts this way though, it started from the Thompson sh (ie: pre 7th edition) and back then there was no environment, and while csh had vars (incl home) it couldn't have cd depend upon what was in the environment, and had to either use the passwd db, either for "cd" or to init "home" or both. I guess that has been changed since.
Re: 'cd' if HOME is unset
Robert Elz wrote: > Why bother? I happily admit that it's a rare edge case. I simply find it surprising that 'cd' gives up if HOME is unset. Seems unintuitive to me. -Jan
Re: 'cd' if HOME is unset
Why bother?It is already clear that one cannot depend upon this working, and nothing normally should ever have HOME unset, unless that is done deliberately (perhaps even to prevent a simple "cd" from going there). kre
Re: 'cd' if HOME is unset
Jan Schaumann wrote: > "A common extension when HOME is undefined is to get > the login directory from the user database for the > invoking user. This does not occur on System V > implementations." > > I'm surprised that /bin/sh does not use the user's > home directory from getpwuid() in that case Attached is a proposed patch to change this such that /bin/sh and /bin/ksh would fall back to getpwuid()->pw_dir if HOME is unset as suggested by POSIX as a "common extension". What do you think? -Jan Index: ksh/c_ksh.c === RCS file: /cvsroot/src/bin/ksh/c_ksh.c,v retrieving revision 1.29 diff -u -p -r1.29 c_ksh.c --- ksh/c_ksh.c 3 Jun 2018 12:18:29 - 1.29 +++ ksh/c_ksh.c 24 Dec 2022 23:01:47 - @@ -10,6 +10,7 @@ __RCSID("$NetBSD: c_ksh.c,v 1.29 2018/06 #endif #include +#include #include #include "sh.h" @@ -30,6 +31,7 @@ c_cd(wp) int phys_path; char *cdpath; char *fdir = NULL; + struct passwd *p; while ((optc = ksh_getopt(wp, _opt, "LP")) != EOF) switch (optc) { @@ -55,8 +57,12 @@ c_cd(wp) if (!wp[0]) { /* No arguments - go home */ if ((dir = str_val(global("HOME"))) == null) { - bi_errorf("no home directory (HOME not set)"); - return 1; + if ((p = getpwuid(getuid())) == NULL) { + bi_errorf("getpwuid() failed: %s", strerror(errno)); + return 1; + } else { + dir = p->pw_dir; + } } } else if (!wp[1]) { /* One argument: - or dir */ Index: ksh/ksh.Man === RCS file: /cvsroot/src/bin/ksh/ksh.Man,v retrieving revision 1.26 diff -u -p -r1.26 ksh.Man --- ksh/ksh.Man 26 Aug 2018 22:52:34 - 1.26 +++ ksh/ksh.Man 24 Dec 2022 23:01:48 - @@ -1739,7 +1739,9 @@ An empty entry in the \fBCDPATH\fP entry If a non-empty directory from \fBCDPATH\fP is used, the resulting full path is printed to standard output. If \fIdir\fP is -missing, the home directory \fB$HOME\fP is used. +missing, the home directory \fB$HOME\fP is used; +if \fB$HOME\fP is unset, the user's home directory is +determined from the password database. If \fIdir\fP is \fB\-\fP, the previous working directory is used (see OLDPWD parameter). If \fB\-L\fP option (logical path) is used or if the \fBphysical\fP option Index: sh/cd.c === RCS file: /cvsroot/src/bin/sh/cd.c,v retrieving revision 1.50 diff -u -p -r1.50 cd.c --- sh/cd.c 5 Jul 2017 20:00:27 - 1.50 +++ sh/cd.c 24 Dec 2022 23:01:48 - @@ -43,6 +43,7 @@ __RCSID("$NetBSD: cd.c,v 1.50 2017/07/05 #include #include +#include #include #include #include @@ -83,6 +84,7 @@ cdcmd(int argc, char **argv) const char *path, *cp; char *p; char *d; + struct passwd *pwd; struct stat statb; int print = cdprint;/* set -o cdprint to enable */ @@ -97,8 +99,13 @@ cdcmd(int argc, char **argv) dest = *argptr; if (dest == NULL) { dest = bltinlookup("HOME", 1); - if (dest == NULL) - error("HOME not set"); + if (dest == NULL) { + if ((pwd = getpwuid(getuid())) == NULL) { + error("getpwuid() failed: %s", strerror(errno)); + } else { + dest = pwd->pw_dir; + } + } } else if (argptr[1]) { /* Do 'ksh' style substitution */ if (!curdir) Index: sh/sh.1 === RCS file: /cvsroot/src/bin/sh/sh.1,v retrieving revision 1.229 diff -u -p -r1.229 sh.1 --- sh/sh.1 18 Sep 2020 07:21:26 - 1.229 +++ sh/sh.1 24 Dec 2022 23:01:50 - @@ -31,7 +31,7 @@ .\" .\"@(#)sh.18.6 (Berkeley) 5/4/95 .\" -.Dd September 18, 2020 +.Dd December 24, 2022 .Dt SH 1 .\" everything except c o and s (keep them ordered) .ds flags abCEeFfhIiLmnpquVvXx @@ -2431,7 +2431,9 @@ of utilities, the name for built-ins or .\" .It Ic cd Oo Fl P Oc Op Ar directory Op Ar replace Switch to the specified directory (default -.Ev $HOME ) . +.Ev $HOME , +or, if unset, the home directory of the current user +as specified in the password database). If .Ar replace is specified, then the new directory name is generated by replacing
'cd' if HOME is unset
Hello, POSIX requires that the 'cd' command use the $HOME environment variable (if that is set) when no operand is given. It explicitly notes that behavior of 'cd' with no operand when $HOME is unset is implementation defined. It then notes: "A common extension when HOME is undefined is to get the login directory from the user database for the invoking user. This does not occur on System V implementations." I'm surprised that /bin/sh does not use the user's home directory from getpwuid() in that case: $ pwd /tmp $ unset HOME $ cd cd: HOME not set $ pwd /tmp $ This is the same for /bin/ksh and /bin/csh as well. Did all these somehow inherit this from System V or was there a reason why this wasn't implemented? -Jan