What Shell Am I Using?
nil.wallyjones.com
nil.wallyjones.com
One advantage is testing. To test fish, it first must be installed into a directory tree, but relative paths are preferred over build-time paths, so there is no special "build for test" mode. Also this makes it easier for fish to invoke itself as part of a test.
A second advantage is embedding. GNU encourages supporting relocation [1], and fish also provides a Mac app which can be run from anywhere, no installation.
Anyways there's a lot of benefits if a shell can find itself.
1: https://www.gnu.org/software/gnulib/manual/html_node/Support...
I'm not familiar with zsh, perhaps it also has some built-in commands that would report the release version?
% help
zsh: command not found: help
Well, it kinda works. Just not in the way you might have hoped :P But the output lets you know that you are running zsh.And to find out the version:
% echo $ZSH_VERSION
5.7.1
(Assuming no-one has been silly and overridden the value of said environment variable in their zshenv file or something. But if we assumed that to be likely then we should also assume that someone using bash had aliased 'help' to something else too, so I think it is fair to assume that no-one had done that.) ╰─>$ help
(firefox:42227): Gtk-WARNING **: 11:46:58.100: Locale not supported by C library.
Using the fallback 'C' locale(Not sure it macOS has as much info in /proc?)
macOS does not have procfs
https://en.wikipedia.org/wiki/Procfs
It also got dropped from OpenBSD:
> It was removed from OpenBSD in version 5.7, which was released in May 2015, because it "always suffered from race conditions and is now unused".[2]
The OpenBSD people don't say what you should replace it with, but backing up in the paragraph, the FreeBSD people do:
> As of February 2011, procfs is gradually becoming phased out in FreeBSD.[1]
Chasing that reference:
https://lists.freebsd.org/pipermail/freebsd-fs/2011-February...
> Why is procfs deprecated in favor of procstat?
[snip]
> The security issues are long-standing and there have been many over the years, but the real reason is something that's less evident (or at least less directly apparent):
> Simply put, procfs on FreeBSD has been neglected. There isn't a lot of attention being given to it, and the only modifications in recent months/years have been generally minor compared to the rest of the tree. You can review some of the commits yourself:
> http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/fs/procfs/
> Others like yourself have asked what the state of procfs is, going back as far as 2005. Be sure to read the reply as well:
> http://unix.derkeiler.com/Mailing-Lists/FreeBSD/questions/20...
Here's the FreeBSD procstat manpage:
https://www.freebsd.org/cgi/man.cgi?procstat
Aside from bitrot, is there a reason to prefer procstat over procfs?
/proc is Linux specific, but it's extremely useful. A lot of tools are actually built on top of it, for example ps.
ngarvey@cheapo:~$ strace ps aux |& grep cmdline | head
openat(AT_FDCWD, "/proc/1/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/2/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/3/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/4/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/9/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/10/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/11/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/12/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/13/cmdline", O_RDONLY) = 6
openat(AT_FDCWD, "/proc/14/cmdline", O_RDONLY) = 6 fish: $$ is not the pid. In fish, please use $fish_pid.
readlink -e /proc/$$/exe
^Is it a hangover from the days when mainframes charged $0.12 per command?
When a user logs in, you somehow need to know what to do next. What does it even mean "to log in" if not "run a program with my uid".
Typically,you want to spawn a process that would allow the user to in turn run other processes. That's what the user default shell is.
Trivia: changing the user default shell to /bin/false has been used quite a bit as a way to disallow a user from ssh into a machine (there are specific other steps to take into account when doing that which I won't cover here)
* nologin: https://man7.org/linux/man-pages/man8/nologin.8.html
* scponly: https://linux.die.net/man/8/scponly
* git-shell: https://git-scm.com/docs/git-shell
If your policy is instead to fire up a full blown unrestricted bash shell, then hope the user doesn't exit your script before you swap it with a restricted shell, I've got some surprises for you.
Even if you trust your users, every one of them is a potential doormat for a malicious user to wipe their feet on as they use leaked credentials.
Moral of the story: the stuff is there for a reason and it's easy to use. Might as well do it. Most of the vintage useless stuff is long gone, if it's there it's probably still important.
These days we'd probably also think about reducing 'attack surface' by not giving that kind of special purpose user a real shell even in passing (if a bug let them write to the shell's init files that turns write-file-as-user into remote-shell), but they wouldn't have been considering that in the early 70s...
Being able to assign a login shell to an account is an important security feature. It's not simply a user preference mechanism. It can be used to bind an account to a "restricted shell":
https://en.wikipedia.org/wiki/Restricted_shell
When people use remote execution tools like (historically) rsh or ssh, the remote account's login shell is used.
You can replace an account's login shell with a program that parses the commands and allows only very limited access.
Here is an example such a script which I used for an account that accepted SSH tunnel connections for a remote desktop. (The remote Windows machine contained a "service" that called back to this machine via SSH, setting up a tunnel for accessing that Windows machine in the reverse direction.)
#!/bin/bash
if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
echo interactive login not permitted
echo "$@" >> ~/.log
exit 1
fi
case "$2" in
rdp )
while true ; do sleep 3600 ; done
;;
* )
echo that command is not allowed
exit 1
;;
esac
The only command allowed is "rdp", and what it does is put this "shell" to sleep, to keep the connection open. It's implemented as a built-in, right in the above case statement.If this script exits, the login session or remote command is terminated.
The reason I did this is that the Windows machine held an unprotected SSH private key to be able to perform a password-less login to that Linux box. (This ran as a service, so even if the Windows machine were power-cycled, it would reconnect.)
If someone got into the Windows box and discovered and understood the setup, and the Linux account were not protected by this script, they would be able to use the unprotected private key to ssh into it, or run ssh commands, or scp files, etc.
This sort of thing has other applications; for instance, it could be used to give people real SSH git access, without shell access.
Not true: you can be in a shell not in $PATH, and if you executed it from a relative path, which $0 will not find it if you cd to a different location.
That is likely not the case there, and any such file names are unlikely to exist. Just say: which "$0"
$ which "$(echo $0)"
which: illegal option -- b
usage: which [-as] program ...
$ echo $0
-bash
OSX. True story.fish: $(...) is not supported. In fish, please use '(echo)'. which "$(echo $0)" ^
;)
~ % which fstat
fstat not found $ readlink /proc/$$/exe
/bin/bash (deleted)
$ sha256sum /proc/$$/exe $(readlink /proc/$$/exe)
16a94220a1cf204076640914f09cf0af59da07771819e7eb9671216643296d73 /proc/665119/exe
16a94220a1cf204076640914f09cf0af59da07771819e7eb9671216643296d73 /bin/bash
sha256sum: '(deleted)': No such file or directory
If the unlinked executable has been replaced by a new executable with the same content, they will have the same checksum, this could possibly happen if the package has been reinstalled, which is unlikely to occur. If the original executable is nowhere to be found on the disk, at least you can... $ cp /proc/$$/exe shell_bin_under_analysis
$ strings shell_bin_under_analysis | grep version
GNU bash, version %s-(%s)
GNU bash, version %s (%s)
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
@(#)Bash version 5.0.16(1) release GNU
$ strings shell_bin_under_analysis | grep zsh
# [...]
zsh-5.8-0-g77d203f
# [...]Eh, why not remove it from PATH then ?
PATH= /path/to/command
That will run /path/to/command with the PATH variable unset.