我想创建远程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 的解决方案
最佳答案
再次编辑:我很愚蠢。问题是 shell 不是交互式的,因为 std(in|out|err) 不再是 tty。使用
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
ed PS1
也可以通过运行 sh -c sh
来重现)。我不太确定为什么 sh -c sh
丢弃 PS1
;它不会对其他环境变量执行此操作。
在这种情况下,可以使用 fork
和 exec
来模拟 system()
调用,但不会产生这种效果,如代码如下。但是,PS1
仍需要导出
以便子进程看到它。
因此,造成这种情况的原因很可能是 PS1
未导出
并且 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
未导出,则打印 PS1 is NULL
并使用默认 PS1
打开 shell,如果未导出,则保留提示我在导出 PS1
后再次运行它。
export
区分了 shell 变量和环境变量。如果您希望子进程继承 shell 变量,请通过导出
将其设为环境变量。
关于c - 为什么 bash 不打印 PS1 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27755138/