[英]Why can the execve system call run “/bin/sh” without any argv arguments, but not “/bin/ls”?
[英]execve(“/bin/sh”, 0, 0); in a pipe
我有以下示例程序:
#include <stdio.h>
int
main(int argc, char ** argv){
char buf[100];
printf("Please enter your name: ");
fflush(stdout);
gets(buf);
printf("Hello \"%s\"\n", buf);
execve("/bin/sh", 0, 0);
}
我和我在没有任何管道的情况下运行它应该工作并返回一个sh
promt:
bash$ ./a.out
Please enter your name: warning: this program uses gets() which is unsafe.
testName
Hello "testName"
$ exit
bash$
但这不适用于管道,我想我知道为什么会这样,但我无法找到解决方案。 示例运行波纹管。
bash$ echo -e "testName\npwd" | ./a.out
Please enter your name: warning: this program uses gets() which is unsafe.
Hello "testName"
bash$
我想,这有什么做的事实gets
清空stdin
在这样/bin/sh
接收EOF和promtly退出而不错误消息。
但是我如何解决这个问题(如果可能的话,不修改程序,如果没有,则不删除gets
),即使我通过管道提供输入,我也得到了一个promt?
PS我在FreeBSD(4.8)机器DS上运行它
您可以在不进行任何修改的情况下运行程序:
(echo -e 'testName\n'; cat ) | ./a.out
这样,您可以确保程序的标准输入不会在echo
输出之后结束。 相反, cat
继续为您的程序提供输入。 后续输入的来源是您的终端,因为这是cat
读取的地方。
这是一个示例会话:
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$
请注意,由于shell的标准输入未连接到终端,因此sh
认为它不是以交互方式执行的,因此不会显示提示。 但是,您可以正常键入命令。
使用execve("/bin/sh", 0, 0);
贝壳是残酷和不寻常的惩罚。 它根本没有任何参数或环境 - 甚至没有它自己的程序名,甚至也没有像PATH或HOME这样的强制环境变量。
不是100%肯定这个(使用的精确shell和操作系统可能会抛出这些答案;我相信FreeBSD默认使用GNU bash
作为/bin/sh
?),但是
sh
可能检测到其输入不是tty。 要么
sh
版本可能会进入非交互模式,如果调用为sh
,期望login
会在它之前添加-
到argv[0]
。 设置execve ("/bin/sh", { "-sh", NULL}, NULL)
可能会说服它作为登录shell运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.