execve(“/bin/sh”, 0, 0); in a pipe

爷,独闯天下 提交于 2019-12-03 11:53:23

You can run your program without any modifications like this:

(echo -e 'testName\n'; cat ) | ./a.out

This way you ensure that your program's standard input doesn't end after what echo outputs. Instead, cat continues to supply input to your program. The source of that subsequent input is your terminal since this is where cat reads from.

Here's an example session:

bash-3.2$ cc stdin_shell.c 
bash-3.2$ (echo -e 'testName\n'; cat ) | ./a.out 
Please enter your name: warning: this program uses gets(), which is unsafe.
Hello "testName"
pwd
/home/user/stackoverflow/stdin_shell_question
ls -l
total 32
-rwxr-xr-x  1 user  group  9024 Dec 14 18:53 a.out
-rw-r--r--  1 user  group   216 Dec 14 18:52 stdin_shell.c
ps -p $$
  PID TTY           TIME CMD
93759 ttys000    0:00.01 (sh)
exit

bash-3.2$

Note that because shell's standard input is not connected to a terminal, sh thinks it is not executed interactively and hence does not display the prompt. You can type your commands normally, though.

Using execve("/bin/sh", 0, 0); is cruel and unusual punishment for the shell. It gives it no arguments or environment at all - not even its own program name, nor even such mandatory environment variables as PATH or HOME.

Not 100% sure of this (the precise shell being used and the OS might throw these answers a bit; I believe that FreeBSD uses GNU bash by default as /bin/sh?), but

  • sh may be detecting that its input is not a tty.

or

  • Your version of sh might go into non-interactive mode like that also if called as sh, expecting login will prepend a - onto argv[0] for it. Setting up execve ("/bin/sh", { "-sh", NULL}, NULL) might convince it that it's being run as a login shell.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!