Open exalted opened 1 year ago
I believe this is due to the fact that the integrated terminal spawn in the working directory of your project not in $HOME
as it usually does. Try running the following in the root of your project:
$ touch .hushlogin
@hovsater thanks for the suggestion! However, I could only accept it only as a workaround. If possible, I think Zed Terminal should look for the presence of ~/.hushlogin
, regardless.
@exalted It's your shell (e.g., bash
or zsh
) that searches for the .hushlogin
file. So it's not something Zed can "load" for you. Perhaps some kind of workaround can be implemented, like first spawning the shell in $HOME
and then immediately execute a command to cd
into the project directory. I'm not sure. Someone from the Zed team would have to investigate that further.
Yup. Let's wait for someone to chime in. All other "expected" Bash initialization stuff (e.g., ~/.bash_profile
, ~.bashrc
, etc.) are loaded (inherited?) fine.
Thanks! 🙌
~/.bash_profile
and ~/.bashrc
are loaded from a statically known set of locations by your shell. .hushlogin
is only read from your current working directory upon shell start. 🙂
I think we are talking about the same thing, but I am not understanding why are you suggesting ~/.hushlogin
should have a different behavior than, say, ~/.bashrc
, for example. Both are very well known places.
Your shell (e.g., bash/zsh) have a set of statically known locations for where it will look for files such as .bash_profile
, .bashrc
and .profile
. To my knowledge, login
it does not have that for .hushlogin
. Upon login, it will look for .hushlogin
in the current working directory, which happens to be $HOME
the majority of the time. Now, in Zed, the current working directory isn't $HOME
but the root of your project, thus no .hushlogin
can be found. I don't believe login
fallbacks to $HOME
if it can not find a .hushlogin
inside the CWD.
For instance, try the following:
$ cd $HOME
$ login <username>
and
$ cd /tmp
$ login <username>
I get no prompt in the first example. I get the prompt in the second example.
I appreciate you @hovsater ! 🙇
From https://linux.die.net/sag/what-login-does.html:
Part of the initial setup is outputting the contents of the file /etc/motd (short for message of the day) and checking for electronic mail. These can be disabled by creating a file called .hushlogin in the user's home directory.
LOL. Let's wrap this with a link to a source code: https://github.com/util-linux/util-linux/blob/c7ffe0cf6b7bdf62db70bd7700d6ed40d9106ba9/lib/logindefs.c#L442-L452:
* Check the per-account or the global hush-login setting.
*
* Hushed mode is enabled:
*
* a) if a global (e.g. /etc/hushlogins) hush file exists:
* 1) for ALL ACCOUNTS if the file is empty
* 2) for the current user if the username or shell is found in the file
*
* b) if a ~/.hushlogin file exists
*
* The ~/.hushlogin file is ignored if the global hush file exists.
Interesting. The man page of login
states:
If the file .hushlogin exists in the user's home directory, all of these messages are suppressed. If -q is specified, all of these messages are suppressed.
While my example above clearly shows that's not the case. Further down in the man pages of login
you can see a list of files it respects:
FILES .hushlogin makes login quieter
which indicates it's loaded from the CWD, not $HOME/.hushlogin
. Perhaps this is broken on macOS, I could verify this on Linux, but I don't have a machine nearby right now.
Why are you assuming .hushlogin
's path refers to CWD
?
Because the path is not absolute. I dove into the source code of macOS and it does not look like they traverse any directories other than CWD.
The path to .hushlogin
is defined here:
And in login.c
they check for its existence here (note how they read the path as is, e.g., not respecting $HOME
):
So I guess the conclusion to all of this is: It's a bug in macOS? 😅
LOL. I don't know… All I know is that, I am using this config for as far back as I can remember, and FWIW, VSCode terminal honors it. So, I don't know. 🤷
VSCode uses Xterm.js. I don't believe you would see the message in VSCode even if you removed .hushlogin
completely. Given what I linked above it's clear that it will only check for a .hushlogin
in the current working directory. Given that the documentation says something else, I'd argue it's a bug in macOS and it should be adressed.
I too think Zed team has plenty of feedback at this point to come up with a solution they think is the right one. Thanks, @hovsater ! 🙏
Hi! Hi @hovsater long time no see 😉 I'm working on fixing this for Ghostty as well and wanted to share some of my own research and discoveries that I think were not covered above. You've already [correctly] established that hushlogin is handled automatically by login(1)
, not by the shell. I want to add more complications to this for y'all.
Relevant Ghostty issue with all the research: https://github.com/mitchellh/ghostty/issues/1074 (this is private at the time of writing this so I don't expect you to see it, although @hovsater is in the beta. But one day it will be public so preemptively linking it here). I'll repeat my findings below:
First off, macOS users expect their terminals to be login shells. This is, as far as I can tell, a purely macOS user behavior. Linux terminals in every terminal I tried are not login shells. I don't know how the macOS dev community got to this point but it is where we're at. I know Zed is macOS only at the moment but in case you get to Linux, I'm mentioning that now, because Linux is generally unaffected by this.
So let's assume we're on macOS from here on out. I'll repeat this issue will not affect Linux when you get there.
To make a login shell, the typical unix approach is to set the argv[0]
of the exec
sys call to -
. So for example if you're launching fish
you'd do -fish
, and the OS magically makes this a login environment. In fish that's status --is-login
(sorry I'm a fish user).
There are a couple issues with this approach on macOS. First, $SHELL
will not be properly set (this is also a responsibility of login(1)
). Second, libc getlogin()
of any process run within the shell will return "root" and not the correct logged in user. To fix both of these issues, you must use login(1)
. On the plus side, it doesn't go through login
so the login message doesn't show up.
So now we get to /usr/bin/login
. By opening up the shell via login
, $SHELL
will be set and getlogin()
will return the right thing. But now we have new problems: by default, the login
command will chdir to the user's home directory from /etc/passwd
(ignores $HOME) and will reset env vars. You can set the -p
flag to not reset the env vars and instead inherit them, but the chdir behavior still happens.
To fix the chdir behavior, you can specify -l
which will NOT automatically make the command a login shell. You must now manually insert the -
back into the argv0. But now it won't chdir to home. Awesome. But wait, now there's a new problem: login
only checks for hushlogin
in the working directory of the command. Since it isn't home anymore, it won't hush logins.
So how do we fix hushlogin? Well, there is ANOTHER flag -q
which behaves as if hushlogin was present. But it is entirely up to the caller to check for hushlogin. There is no way to have login
(1) not change chdir (2) make a login shell (3) honor hushlogin all at once. You have to do some manual work.
The way terminals such as Kitty or iTerm do this is by creating a wrapper program (iTerm calls this ShellLauncher
) which primarily sets the proper env vars and chdirs to the proper place before exec
-ing and replacing itself with the real shell. So the execution is Terminal => login(1) => ShellLauncher => shell
.
I think you can also replace the ShellLauncher by manually copying the hushlogin detection logic and using login -fqlp
, but I haven't 100% verified this yet. I'm going to try this first since I don't want to introduce that second step. In any case, the above should give you all the background you need on this topic.
@mitchellh - appreciate the super detailed write up here, thanks. :)
Also, as a side note, really digging what you're doing with the terminal - been in the beta pool for some time now - the new terminal inspector is a really cool addition! If you ever wanted to chat about terminal development, shoot us an email, Even though we are working in different languages, I'm sure there's a lot we could benefit from chatting with you. :)
I just want to add that as of right now, if one adds a .hushlogin
to the project root (not ~/.hushlogin), it suppress the Last login...
AND the You have mail.
message, in case one ends up here searching for that:
Last login: Fri Jan 26 12:20:53 on ttys009
You have mail.
I'm having an issue where my $PATH
is evaluated in the wrong order when running in the zed
terminal. This becomes an issue because /usr/bin:/bin
get appended (and duplicated) in front of things like /opt/homebrew/bin
and then bash scripts end up using the very old v3 bash shipped with macOS.
I'm not sure this is related, but based on @mitchellh's detailed explanation, it sounds like it could be related as a root cause. I do not have this problem in the native macOS terminal, iTerm, vscode, or IntelliJ.
Is there any news?
Vscode: Zed:
Check for existing issues
Describe the bug / provide steps to reproduce it
Zed will show the “last login” message (e.g., “Last login: Thu Apr 6 08:35:35 on ttys000”) although I have
~/.hushlogin
file in place. (I believe this is a standard Bash behavior?)Environment
Zed: v0.80.5 (stable) OS: macOS 13.3.0 Memory: 64 GiB Architecture: aarch64
If applicable, add mockups / screenshots to help explain present your vision of the feature
No response
If applicable, attach your
~/Library/Logs/Zed/Zed.log
file to this issue.If you only need the most recent lines, you can run the
zed: open log
command palette action to see the last 1000.No response