1

I want a command to be excuted after busybox ash starts.
I saw here that busybox ash is debian ash variant, and after seeing here, tried setting

ENV=$HOME/.shinit; export ENV

in file /etc/profile, and adding (BTW, this is to make Ctrl-C work in the shell)

setsid cttyhack sh

in file /.shinit.
But when I entered the shell, the 'ENV' variable is not set. (echo $ENV shows nothing).
How should I do it? By the way, my shell doesn't ask for loging(no login shell).

ADD :
This is my /init script.

#!/bin/sh
echo "### INIT SCRIPT ###"
mkdir /proc /sys /tmp
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /tmp
echo -e "\nThis boot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
mknod /dev/virtual_buffer c 125 0

#ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up
#route add default gw 10.0.2.2
echo "### calling /bin/sh ###"
exec /bin/sh
Chan Kim
  • 5,177
  • 12
  • 57
  • 112
  • Have a look at the [ash man-page](https://linux.die.net/man/1/ash): `/etc/profile` is processed only for login shells. Aside from this, consider using `~/.profile` instead of `/etc/profile`, since you want to enable this only for your account, don't you? – user1934428 Nov 07 '22 at 10:59

1 Answers1

0

After seeing your boot script, and duplicating exactly what you present above I experienced the joys of infinite sh# prompts.

Your problem is that you're entering an infinite loop. To explain what's happening, we follow the logic in your script.

When you invoke the shell with the --login option, it reads /etc/profile. This has a line reading:

ENV=$HOME/.shinit; export ENV

which, at the end of processing the profile is sourced.

This file contains the line: setsid cttyhack sh

This launches a new copy of sh, which has been pre-armed with an ENV variable, which causes it to issue setsid cttyhack sh… repeat until your screen is covered in shell prompts and you're scratching your head.

The solution is even simpler than you think. Rather than getting the ENV file to load that cttyhack, move it into the init script, i.e. at the bottom of the init script, instead of just sh do:

exec setsid cttyhack sh --login

Don't add the line to the .shinit with the setsid cttyhack sh, and you don't end up with an infinite loop.

TLDR - Below is for loading /etc/profile initially

You pretty much answered the issue in your question, when you mentioned:

By the way, my shell doesn't ask for loging(no login shell)

So I'm guessing that you're launching it with something like: busybox ash, without any arguments.

There are two modes for launching a shell - as a 'login' type shell and as a 'non-login' type shell. This governs the launch behavior.

When you invoke a login-type shell, it will read the /etc/profile file and the ~/.profile files. This can be seen in the source -

behavior on isloginsh:

    if (argv[0] && argv[0][0] == '-')
        isloginsh = 1;
    if (isloginsh) {
        const char *hp;

        state = 1;
        read_profile("/etc/profile");
 state1:
        state = 2;
        hp = lookupvar("HOME");
        if (hp)
            read_profile("$HOME/.profile");
    }

The detection of isloginsh can also be set by passing in the -l or --login options, where the argument parser checks if the -l or --login options are passed:

} else if (cmdline && (c == 'l')) { /* -l or +l == --login */
    isloginsh = 1;
Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • Thanks for the answer, but I started the sh by putting `exec /bin/sh` in the /init script in busybox filesystem. When I add `-l` or `--login`, the shell endlessly prints `/ #`. I don't know why.. Besides, automatically running this command is not a high priority so I want to stay with non-login shell that's why I didn't try login shell before. I'll wait for more answers. Thank you! – Chan Kim Nov 07 '22 at 09:51
  • @ChanKim : How about removing the `exec`? BTW, the [ash-manpage](https://linux.die.net/man/1/ash) does not mention the options `-l` or `--login`, so I consider their use questionable. Maybe it's an undocumented feature, since Anya Shenanigans found it in the sources. Can't you use `dash` instead, which, according to its man-page, has `-l`, and therefore is at least documented? – user1934428 Nov 07 '22 at 11:04
  • @ChanKim maybe seeing the rest of your init script would help here - I've been unable to repro the issue using tinycorelinux, where the /init script has been replaced with a single command of: `exec /bin/sh` or `exec/bin/sh --login`, and with the exception of the error about no controlling tty because /dev/pts isn't mounted, it doesn't go into an infinite prompt loop. I do recognize that this isn't the same environment as you're using, so more details would definitely help. – Anya Shenanigans Nov 07 '22 at 12:02
  • @ChanKim the issue is reproducible - you end up in an infinite loop because of the presence of `setsid cttyhack sh` in the `.shinit` file. I've posited a solution above, which is probably easier than what you were trying to accomplish – Anya Shenanigans Nov 09 '22 at 20:05
  • @AnyaShenanigans Sorry for late reponse. That's strange, I tried your new suggestion, the entless printing stops, but still Ctrl-C doesn't work. (But after I explicitly execute `setsid cttyhack sh` in the shell, ctrl-C works.). I also tried https://unix.stackexchange.com/questions/425389/how-to-autorun-a-program-using-busybox-after-boot but ctrl-C doesn't work. Sorry but I'll try waiting for an working answer. Thank you for giving me some information though. – Chan Kim Nov 11 '22 at 08:28