In the package app-shells/dash, in the function setjobctl (src/jobs.c) there exists code to gracefully handle situations, where no /dev/tty node exists. However in such situations the file descriptor 2 will be closed unintentionally (after mapping it to a higher file descriptor). This is probably a bug as a lot of routines (e.g. in output.c rely on the open file descriptors 0-2) The consequence is that on systems where /dev/tty is missing, no shell prompt can be seen (dash uses the error stream to output the prompt). For comparison: The busybox shell "sh" neither does close fd 2 when /dev/tty is missing, nor does it output the prompt on fd=2, so it is robust in that sense. The solution would be to only close a file descriptor, if it is greater than 2 (file redir.c): # diff redir_old.c redir.c 410c410,411 < close(from); --- > if(from > 2 ) > close(from); Here some straces for clarification: strace for current dash (/dev/tty does not exist): -------------------------------------------------- [...] open("/dev/tty", O_RDWR) = -1 ENOENT (No such file or directory) ioctl(2, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 fcntl(2, F_DUPFD, 10) = 10 close(2) = 0 <<== This should not happen! fcntl(10, F_SETFD, FD_CLOEXEC) = 0 ioctl(10, TIOCGPGRP, [859]) = 0 getpgrp() = 859 rt_sigaction(SIGTSTP, NULL, {SIG_DFL}, 8) = 0 rt_sigaction(SIGTSTP, {SIG_IGN}, NULL, 8) = 0 rt_sigaction(SIGTTOU, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, {SIG_DFL}, NULL, 8) = 0 setpgid(0, 860) = 0 ioctl(10, TIOCSPGRP, [860]) = 0 wait4(-1, 0xbfca82e8, WNOHANG|WUNTRACED, NULL) = -1 ECHILD (No child processes) write(2, "# ", 2) = -1 EBADF (Bad file descriptor) <== Writing the prompt fails. read(0, 0x80595e0, 4096) = ? ERESTARTSYS (To be restarted) --- SIGINT (Interrupt) @ 0 (0) --- strace for busybox-sh (/dev/tty) does not exist): ------------------------------------------------- [...] open("/dev/tty", O_RDWR|O_LARGEFILE) = -1 ENOENT (No such file or directory) ioctl(2, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 fcntl64(2, F_DUPFD, 10) = 10 close(-1) = -1 EBADF (Bad file descriptor) fcntl64(10, F_SETFD, FD_CLOEXEC) = 0 ioctl(10, TIOCGPGRP, [861]) = 0 getpgrp() = 861 rt_sigaction(SIGTSTP, NULL, {SIG_DFL}, 8) = 0 rt_sigaction(SIGTSTP, {SIG_IGN}, NULL, 8) = 0 rt_sigaction(SIGTTOU, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, {SIG_DFL}, NULL, 8) = 0 setpgid(0, 862) = 0 ioctl(10, TIOCSPGRP, [862]) = 0 brk(0x80fa000) = 0x80fa000 ioctl(2147483647, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb21cc4) = -1 EBADF (Bad file descriptor) brk(0x80fb000) = 0x80fb000 wait4(-1, 0xbfb21d98, WNOHANG|WUNTRACED, NULL) = -1 ECHILD (No child processes) ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 open("/root/.ash_history", O_RDONLY|O_LARGEFILE) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb21c34) = -1 ENOTTY (Inappropriate ioctl for device) read(3, "echo Hallo >&2\necho Hallo\ndash\nd"..., 4096) = 156 close(3) = 0 ioctl(0, SNDCTL_TMR_START or TCSETS, {B115200 opost -isig -icanon -echo ...}) = 0 ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost -isig -icanon -echo ...}) = 0 rt_sigaction(SIGWINCH, {0x80cb7cd, [WINCH], SA_RESTORER|SA_RESTART, 0xb7eef338}, {SIG_DFL}, 8) = 0 ioctl(0, TIOCGWINSZ, {ws_row=0, ws_col=0, ws_xpixel=0, ws_ypixel=0}) = 0 geteuid() = 0 open("/etc/passwd", O_RDONLY|O_LARGEFILE) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb21bc4) = -1 ENOTTY (Inappropriate ioctl for device) read(3, "root:x:0:0:root:/root:/bin/sh\nbi"..., 4096) = 515 close(3) = 0 getcwd("/", 192) = 2 geteuid() = 0 write(1, "/ # ", 4/ # ) = 4 read(0, "\4", 1) = 1 strace of current dash startup with /dev/tty -------------------------------------------- [...] open("/dev/tty", O_RDWR) = 3 fcntl(3, F_DUPFD, 10) = 10 close(3) = 0 fcntl(10, F_SETFD, FD_CLOEXEC) = 0 ioctl(10, TIOCGPGRP, [894]) = 0 getpgrp() = 894 rt_sigaction(SIGTSTP, NULL, {SIG_DFL}, 8) = 0 rt_sigaction(SIGTSTP, {SIG_IGN}, NULL, 8) = 0 rt_sigaction(SIGTTOU, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, NULL, {SIG_IGN}, 8) = 0 rt_sigaction(SIGTTIN, {SIG_DFL}, NULL, 8) = 0 setpgid(0, 895) = 0 ioctl(10, TIOCSPGRP, [895]) = 0 wait4(-1, 0xbfc3a838, WNOHANG|WUNTRACED, NULL) = -1 ECHILD (No child processes) write(2, "root@ellipseC $ ", 16root@ellipseC $ ) = 16 read(0, 0x80595e0, 4096) = ? ERESTARTSYS (To be restarted) [...] Reproducible: Always Steps to Reproduce: 1. Install app-shells/dash on a system, where no /dev/tty exists (e.g. Gentoo embedded) 2. 3. Actual Results: The prompt cannot be seen. (Everything else works) Expected Results: Prompt should be shown
We are going to copy upstream on this bugreport and if they acknowledge a bug, we will import the patch. Please tell us which version of dash you're using.
Sorry for the delay, the verion is 0.5.4.11