c - 为什么 bash 不打印 PS1 变量?

标签 c bash

我想创建远程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);

(也就是说,即使使用 exported PS1 也可以通过运行 sh -c sh 来重现)。我不太确定为什么 sh -c sh 丢弃 PS1;它不会对其他环境变量执行此操作。

在这种情况下,可以使用 forkexec 来模拟 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/

相关文章:

c - 将输出通过管道传递给 cat

c - Linux 中是否有 API 可以从语言环境中获取完整的语言名称?

C——基本结构问题

c++ - 通过多个 fork 管道标准输入/输出

java - 在 Java 或 C 中 append 两个十六进制 long 值

linux - 计算输出的尝试次数

json - 在 shell 中解析 JSON

linux - 如何使用 bash 获取字符串中函数的内容?

postgresql - 如何以非交互方式为 'psql' 指定密码?

bash - 使用 xargs 和 xargs -i 的细微差别