Hi all, Busybox's ash built-in commands -e.g. echo, printf, cd- returns an error if the stdout/stderr device is not available. In particular, I reached this behavior while debugging a Debian initramfs, where ash built-in commands are run during boot, before the console is available.
For example, Debian initramfs-tools handles this type of error on printf: https://salsa.debian.org/kernel-team/initramfs-tools/-/blob/master/scripts/functions#L8 ``` _log_msg() { if [ "${quiet?}" = "y" ]; then return; fi # shellcheck disable=SC2059 printf "$@" return 0 # Prevents error carry over in case of unavailable console } ``` * As I'm not sure if this is really a bug or not, I'm sending this as an RFC. So, the question of this RFC is: should this be considered a bug and get fixed properly? Note that running other commands from ash won't fail. Although I haven't checked the source code, that's probably due to the forking process handling stdout/stderr differently. The following straces were run from inside and initramfs, when the console device was still unavailable. Failing case,`cd /` runs silently, but `cd -` tries to print to stdout: ``` strace sh -c "cd / ; cd -" [...] chdir("/") = 0 wait4(-1, 0x7fff4d5351bc, WNOHANG, NULL) = -1 ECHILD (No child processes) chdir("/") = 0 newfstatat(1, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x5, 0x1), ...}, AT_EMPTY_PATH) = 0 ioctl(1, TCGETS, 0x7fff4d534880) = -1 EIO (Input/output error) write(1, "/\n", 2) = -1 EIO (Input/output error) getpid() = 223 exit_group(1) = ? +++ exited with 1 +++ ``` Success case, redirecting `cd -` stdout to /dev/null: ``` strace sh -c "cd / ; cd - >> /dev/null" [...] chdir("/") = 0 openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3 fcntl(1, F_DUPFD_CLOEXEC, 10) = 10 dup2(3, 1) = 1 close(3) = 0 wait4(-1, 0x7ffc316043cc, WNOHANG, NULL) = -1 ECHILD (No child processes) chdir("/") = 0 newfstatat(1, "", {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}, AT_EMPTY_PATH) = 0 ioctl(1, TCGETS, 0x7ffc31603a90) = -1 ENOTTY (Inappropriate ioctl for device) write(1, "/\n", 2) = 2 dup2(10, 1) = 1 close(10) = 0 getpid() = 219 exit_group(0) = ? +++ exited with 0 +++ ``` >From Busybox ash source code, it can be seen that the *lone-dash* case `cd -` tries to print to stdout. The other cd cases with the target directory explicitly set don't fail as they don't try to open the output device, which is unavailable at that point. >From https://git.busybox.net/busybox/tree/shell/ash.c#n2980: ``` static int FAST_FUNC cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { [...] else if (LONE_DASH(dest)) { dest = bltinlookup("OLDPWD"); flags |= CD_PRINT; } [...] out: if (flags & CD_PRINT) out1fmt("%s\n", curdir); return 0; } ``` Regards, Ariel D'Alessandro _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox