【问题标题】:writing STDIN of bash application from c program从 c 程序编写 bash 应用程序的 STDIN
【发布时间】:2014-06-18 22:43:08
【问题描述】:

我想打开一个 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 之前写入。打开应用程序prog1后,请告诉我如何在prog1中编写“命令”。谢谢。

注意:如果我做

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

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

【问题讨论】:

  • 写入你启动的程序的标准输入,而不是你自己的怎么样?那应该这样做。另外,我认为你的execlp 是一个孤儿,除了你给它不好的论据。或者你有一个名为“sudo prog1”的程序?
  • 我有一个名为“prog1”的程序,但如果我不包含“sudo”,它会显示“无法打开文件:权限被拒绝”
  • 这是一个权限问题,与您提出的问题无关。在开始以普通用户身份工作之前,您是否以 root 身份创建了 prog1? sudo 为您提供命令范围的 root 权限。您可能需要“sudo chown prog1”,其中 是您的用户名。
  • @user2216209:请仔细阅读。 execlp 期望你解析命令行,所以如果你问它,它会尝试执行名为“sudo prog1”的程序。也就是说,程序名称中包含一个空格!
  • @Deduplicator:我从程序中删除了“execlp”。

标签: c linux bash stdin


【解决方案1】:

您的主要错误是认为 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”功能,因此您可能想要研究 expect 或期望不同语言的模块。 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

【讨论】:

  • 感谢您快速详细的回复。我删除了“execlp”。该程序的工作原理相同。我正在使用C语言。 fprintf 和 fgets 没有帮助。如果 popen() 负责 dup 和管道。请让我知道我应该如何将命令传递给 prog1?
猜你喜欢
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多