Skip to content
Advertisement

reading from stdin after execl() bash return an eio(Input/output error)

The following code can act as expected if executed by a shell.

But if I set this program as a user’s shell and ssh into the host to execute this program as a shell, the read(0, &buf123, 1); will return an EIO(Input/output error):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <regex.h>
#include <curl/curl.h>
#include <readline/readline.h>

int main() {
    char *shell = "/bin/bash";

    pid_t child;
    if ((child = fork()) < 0) {
        perror("vfork");
        return;
    }
    if (child == 0) {
        execl(shell, shell + 5, "-c", "exec /bin/bash --login", NULL);
        perror("execl");
        return;
    }
    wait(NULL);

    char buf123[1024];
    read(0, &buf123, 1);
    printf("::%s::n", buf123);

}

But if a change execl(bash) into non-interactive bash execl(bash -c "id") or other program rather than bash, the read(0, &buf123, 1); will success.

So to reproduce this error, two conditions need to be met:

1. execvl() an interactive bash(system() can also reproduce this error)

2. run as a user's shell using ssh

Could anyone help me figure out why and how to avoid this?

The following is the strace result:

wait4(-1, NULL, 0, NULL)                = 2
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2, si_status=0, si_utime=0, si_stime=0} ---
read(0, 0x7fff7a4c8cb0, 1)              = -1 EIO (Input/output error)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcd281f3000
write(1, "::Xv37(315177::n", 11)    = 11
exit_group(11)                          = ?
+++ exited with 11 +++

Thanks in advance!

Advertisement

Answer

I happens because your sub-shell is a login interactive shell and so it took control over the terminal (set it as a its session control terminal). Then your process is disconnected from the terminal and cannot read on it anymore.

Of course if you use a non interactive shell, it don’t need the control over the terminal leaving it as is for your process.

Read about POSIX Terminal, sessions and processes group.

Advertisement