2

I'm trying to make a shell for the desktop environment I'm designing which is just a configured Zsh, and I'm confused about how to pass along whether it's a login shell or not.

Here's my script:

#!/bin/sh
case "$0" in
-*) ZDOTDIR=/etc/tiles/zsh exec zsh -l "$@";;
*) ZDOTDIR=/etc/tiles/zsh exec zsh "$@";;
esac

I have installed it to /bin/tiles-shell, added that path to /etc/shells, and made it my shell with chsh.

The problem is it's never a login shell because $0 seems to always be /bin/tiles-shell. I thought it would start with - when it should be a login shell?

7
  • 1
    If it's for zsh why have you indicated it's a sh script (top line)? Commented Nov 7, 2022 at 13:19
  • @roaima A wrapper can use whatever works before replacing itself with the actual tool. Commented Nov 7, 2022 at 13:22
  • @KamilMaciorowski indeed it can, but I wanted to check it's what was intended Commented Nov 7, 2022 at 13:23
  • 1
    $0 would only start with - I think? So you'd want something more like case $0 in -*) Commented Nov 7, 2022 at 13:23
  • and shouldn't zsh recognize the - at the start of $0 itself anyway? is the wrapper really needed for that? Commented Nov 7, 2022 at 13:29

2 Answers 2

4

The shebang mechanism wipes the old value of argv[0]: the kernel replaces it by the path to the interpreter.

The shell does not expose the value of argv[0] as $0 when running a script from a file. $0 is the name of the script file. I don't think zsh exposes its argv[0] through any other interface.

Demonstration script (for Linux):

#!/bin/zsh
echo "argv[0]=$(</proc/$$/cmdline tr \\0 \\n | head -n 1)"
echo "\$0=$0"

Output:

% ARGV0=foo zsh -c "$(cat a)"
argv[0]=foo
$0=foo
% ARGV0=foo zsh ./a
argv[0]=foo
$0=./a
% ARGV0=foo ./a
argv[0]=/bin/zsh
$0=./a

If you really want your login shell to be a script, make it a script that is dedicated to being a login shell.

1

After Giles' answer I made it a binary and it works.

#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    putenv("ZDOTDIR=/etc/tiles/zsh");
    execv("/usr/bin/zsh", argv);
}
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.