简体   繁体   English

无法在Linux中写入管道

[英]Unable to write to a pipe in Linux

I have a third party utility that I have to call from my application to initialize some of their stuff. 我有一个第三方实用程序,我必须从我的应用程序中调用它来初始化他们的一些东西。 I've chosen to call it by using popen because I need to write a password to stdin. 我选择使用popen进行调用,因为我需要为stdin写一个密码。

I's a simple use case: 我是一个简单的用例:

...
FILE *f = popen("utility-bin", "w");
fwrite(myPassword.c_str(), 1, myPassword.size(), f);
fflush(f);
pclose(f);
...

However, no matter how I try, the stream is never sent, and the utility remains blocked waiting for the password. 但是,无论我如何尝试,都不会发送该流,并且该实用程序将在等待密码时保持阻塞状态。

If I call the utility from a regular Linux shell, on the other hand, I can just type the password and everything works. 另一方面,如果我从常规的Linux Shell调用该实用程序,则只需输入密码即可。

So my question is: Is it possible for an application to block data from coming from pipes, but still accepting from a normal user shell? 所以我的问题是:应用程序是否有可能阻止来自管道的数据,但仍然可以接受普通用户的外壳程序? And, if that's the case, is there anything I can do to make it accept my pipe input? 而且,如果是这种情况,我可以做些什么使它接受我的管道输入吗?

PS: When I call the utility from the shell, many signals are beeing handled. PS:当我从外壳程序调用该实用程序时,会处理许多信号。 ctrl+c and ctrl+z , for example, do nothing. 例如, ctrl+cctrl+z不执行任何操作。

Is it possible for an application to block data from coming from pipes, but still accepting from a normal user shell 应用程序是否有可能阻止来自管道的数据,但仍然接受普通用户外壳程序的数据

It can call isatty which will tell it if input comes from a terminal or not. 它可以调用isatty ,它将告诉它输入是否来自终端。

if that's the case, is there anything I can do to make it accept my pipe input 如果是这样,我能做些什么使它接受我的管道输入吗?

There is a way, but you might not like it: 有一种方法,但是您可能不喜欢它:

  1. Open a pseudoterminal using posix_openpt grantpt and unlockpt . 使用posix_openpt grantptunlockpt打开一个伪unlockpt You now have the "master" fd 您现在拥有“大师” fd
  2. Fork a new process 分叉一个新过程
  3. Call setsid() in the new process to kill its terminal association 在新进程中调用setsid()以终止其终端关联
  4. In the child call ptsname on the fd obtained in step 1 在步骤1中获得的fd的子调用ptsname
  5. Open the name obtained from ptsname and call TIOCSTTY on it - it becomes the controlling terminal 打开从ptsname获得的名称并在其上调用TIOCSTTY它成为控制终端
  6. Duplicate the descriptor obtained in step 5 into STDIN_FILENO 将步骤5中获得的描述符复制到STDIN_FILENO
  7. Exec your program 执行您的程序

You can probably adapt the function ptyFork from TLPI for this or the function pty_fork from APUE . 您可能可以ptyFork修改ptyFork的ptyFork 函数APUE的pty_fork函数

At this point you can write into the master fd - as if it were a pipe - from your process and the child will think it comes from a terminal. 此时,您可以从您的进程中将其写入主fd(就像是管道一样),孩子会认为它来自终端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM