C程序execve启动sh shell时管道传输入致shell无法启动问题
问题根因
- 直接运行
./myexec时,进程标准输入默认绑定当前控制终端,execve拉起的/bin/sh会继承该输入描述符,可正常从终端读取交互指令,因此能正常进入shell交互流程。 - 执行
python -c 'print "someinput"' | ./myexec这类管道命令时,myexec的标准输入绑定的是管道读端,而非终端。管道内仅包含Python输出的someinput字符串和末尾换行符,scanf("%s", buff)读完这段内容后,管道就已经到达EOF(输入结束状态)。 - 后续
execve拉起的sh会继承这个已处于EOF状态的标准输入,sh启动后尝试读取输入指令时直接读到EOF,会按默认逻辑立刻退出,既不会进入交互界面,也不会长期驻留。你用ps查询时进程已经执行完毕退出,自然查不到对应的sh进程。 - 未查询到errno报错属于正常现象:
execve系统调用本身执行成功,没有触发任何错误,问题出在sh继承的输入流状态上,和myexec本身的系统调用异常无关。
验证方式
执行以下命令即可验证sh实际是正常启动过,只是启动后立刻退出:
python -c 'print "echo verify_sh_start"' | ./myexec
执行后终端会输出verify_sh_start,说明sh成功启动、读取了管道内的echo命令并执行,执行完成后因无后续输入直接退出。
修复方案
如果需要通过管道传入scanf读取的内容后,仍然让sh正常进入终端交互,可以在调用execve前将标准输入重新绑定到当前控制终端,核心修改点如下:
printf("\n Enter the password : \n"); scanf("%s",buff); // 将标准输入重新指向当前进程的控制终端 freopen("/dev/tty", "r", stdin); execve("/bin/sh", args, NULL);
另外补充代码的一个疏漏:你调用了printf、scanf标准库函数,但代码中未包含<stdio.h>头文件,部分编译环境下会触发隐式声明警告,建议补充该头文件引用。
内容的提问来源于stack exchange,提问作者Ilie Tudor
相关产品推荐
相关产品推荐

