我想创建远程bash(通过tcp套接字),我写了这段代码:
// servfd is descriptor to server socket
int sockfd = accept(servfd,&addr,sizeof(addr));
dup2(sockfd,fileno(stdin));
dup2(sockfd,fileno(stdout));
dup2(sockfd,fileno(stderr));
setenv("PS1","# ",1);
execl("/system/bin/sh","sh",NULL);
并且提示没有打印到套接字,但是当我发送命令时:'echo test'它正在工作但没有提示打印。
我找到了一个必须使用/ dev / ptmx
的解决方案答案 0 :(得分:1)
再次编辑:我是傻瓜。问题是shell不是交互式的,因为std(in|out|err)
不再是ttys。使用
execl("/system/bin/sh", "sh", "-i", "NULL");
// along with the fork dance from below if you want to continue with the main
// program after this
强制mksh
具有交互性,在这种情况下,它应该每次都向stderr
打印提示。这也会使mksh
解释~/.mkshrc
,其中可能设置了PS1
。如果未在此处设置,则仍需导出PS1
,并且system()
的问题仍然存在。如果在那里设置,
system("sh -i");
system()
在其子shell的路上丢弃环境变量。这与它运行的事实有关(在这种情况下)
execl("/bin/sh", "sh", "-c", "sh", NULL);
(也就是说,即使使用export
编辑PS1
,也可以通过运行sh -c sh
来复制它。我不太清楚为什么sh -c sh
会丢弃PS1
;它不会对其他环境变量这样做。
通过使用system()
和fork
,可以在这种情况下模仿exec
调用而不会产生任何影响,如下面的代码所示。但是,PS1
仍然需要export
以便子进程查看它。
因此,原因很可能是PS1
不是export
而system()
丢弃了。运行这段代码来检查并生成shell PS1
,如果可用则继承:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t pid;
char const *ps1 = getenv("PS1");
if(ps1 != NULL) {
puts(ps1);
} else {
puts("PS1 is NULL");
}
pid = fork();
if(pid == -1) {
fputs("fork broke. Aborting.\n", stderr);
return -1;
} else if(pid == 0) {
execl("/bin/sh", "sh", NULL);
} else {
wait(NULL);
}
puts("Continuing here after the shell exited.");
return 0;
}
对我来说,如果PS1 is NULL
未导出,则打印PS1
并打开一个默认PS1
的shell,如果我在export PS1
之后再次运行它,则会保留提示。
export
区分了shell变量和环境变量。如果您希望子进程继承shell变量,请通过export
使其成为环境变量。