为什么bash不打印PS1变量?

时间:2015-01-03 13:01:10

标签: 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

的解决方案

1 个答案:

答案 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不是exportsystem()丢弃了。运行这段代码来检查并生成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使其成为环境变量。