从c程序编写bash应用程序的STDIN

时间:2014-06-18 22:43:09

标签: c linux bash stdin

我想打开一个bash应用程序(prog1)并使用C程序向该应用程序发送命令。 我尝试并编写了以下代码。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    FILE * fp;
    char message[10] = "command1\n";
    fp = popen("sudo prog1","r");
    write(STDIN_FILENO, message, 10);
    pclose(fp);
    execlp("sudo prog1", "sudo prog1", "-l", NULL);
    return 0;
}

此代码提供输出:

Linux:~$ ./ prog 2 // running the code
command            // prints "command"
prog1->            // Then opens "prog1" (prog1 waits for user commands)

但我希望它是

Linux:~$ ./ prog 2 // running the code
prog1-> command    // open "prog1" and write command (instead of getting it from user)

退出 prog1 后或在开始 prog1 之前写入。请让我知道如何编写&#34;命令&#34;打开应用程序 prog1 后,在 prog1 中。谢谢。

注意:如果我做

fp = popen("sudo prog1","w");  //to write

它会抛出以下错误      tcgetattr:设备不适当的ioctl

1 个答案:

答案 0 :(得分:3)

您的主要错误是认为popen()以某种方式将您的子进程与您的STDIN_FILENO相关联。它没有。 STDIN_FILENO与您的“sudo prog1”孩子无关。你必须创建一个管道,将描述符复制到stdin / stdout,并使用fork + exec来做到这一点。但你使用popen()所以不要这样做。

相反,你应该从fp写作和阅读。

类似的东西:

  fprintf(fp, message);
  fgets(response, 100, fp);

由于fprintf()是缓冲的,你应该在行尾使用\ n,或者fflush()。

另外,当你已经调用了popen()时,最后使用exec / execlp是没有意义的。看起来您可能正在混合两种您通过示例看到的方法。

popen()实际上是(pipe,dup stdin / stdout / stderr,fork,execl)的组合来处理将子进程重定向到连接到父进程的文件流。因此,除非您需要与popen()不同的语义,否则无需重新实现。

您在技术上正在实现“期望”功能,因此您可能希望研究期望或期望不同语言的模块。 Expect包含在Linux发行版中,但通常是可选的。

http://expect.sourceforge.net/

http://search.cpan.org/~rgiersig/Expect-1.21/Expect.pod

更不用说,Perl已经有了一个Sudo模块。

http://search.cpan.org/~landman/Sudo-0.21/lib/Sudo.pm