/dev/stdin
Linuxにはソケットと機能しない迷惑な機能があります。 ENXIOを返すようにハードコードされています。この試み:
socat TCP-OPEN:localhost:1234 EXEC:cat\ /dev/stdin,nofork
これは機能すると予想される非常に合理的なコマンドであり、デフォルトではLinuxを除くすべてのシステムで機能します。 (cat
私は使用する特定のfdを指定する唯一の方法で、一般的な例としてファイル名を開くツールを使用しています。)
Linuxカーネルは、/dev/stdin
この方法で公正な使用を禁止するように明示的に書かれています。http://marc.info/?l=ast-users&m=120978595414993。
単方向機能のみが必要な場合は、別のプロセスでデータをバッファリングできます。
socat TCP-OPEN:localhost:1234 SYSTEM:'cat | thingy /dev/stdin'
thingy
Linuxのパイプは一方向であるため、同じfdを読み書きする場合は、これは無駄であり、悪いことは役に立ちません。
私たちは何をしますか?/dev/stdin
私が知っている限り、Linuxでは双方向パイプを使用してパイプラインを構築することはできません。ソケットは、読み取りと書き込みのために単一のfdを使用して双方向ストリームを生成するLinuxの唯一の基本的なメカニズムであるためです(パイプペアと比較)。 )。
答え1
LD_PRELOAD
LinuxにBSD方式を模倣させるには、いつでもトリックを使用できます。fddup.c
:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int whichfd(const char *pathname)
{
unsigned int fd;
if (sscanf(pathname, "/dev/fd/%u", &fd) == 1)
return fd;
else
return -1;
}
int open(const char *pathname, int flags, mode_t mode)
{
static int (*orig)(const char *, int, mode_t) = 0;
int fd = whichfd(pathname);
if (fd >= 0)
return dup(fd);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"open");
if (!orig) abort();
return orig(pathname, flags, mode);
}
}
FILE *fopen(const char *path, const char *mode)
{
static FILE *(*orig)(const char *, const char *) = 0;
int fd = whichfd(path);
if (fd >= 0)
return fdopen(dup(fd), mode);
else {
if (!orig)
orig = dlsym(RTLD_NEXT,"fopen");
if (!orig) abort();
return orig(path, mode);
}
}
(このようにもっと包装する必要があるかもしれませんfreopen()
)。
gcc -Wall -fPIC -shared -o fddup.so fddup.c -ldl
それから:
socat TCP:localhost:22 'EXEC:env LD_PRELOAD=./ddup.so cat /dev/fd/0,nofork'
LinuxとBSDは基本的に異なります。/dev/fd/0
ソケットの場合、開くことができないというのではなく、/dev/fd/x
fd xで開かれたファイルへのシンボリックリンクです。open()
ソケットではできません。それは言うべきではありません。 BSDとは全く異なりますopen("/dev/fd/x")
。dup(x)
ファイルがパイプの場合、このように感じますが、そうではありません。実際には名前付きパイプを開くのと同じです(他のモード(読み取りと書き込み)で開いてパイプのもう一方の端を取得することもできます)。
どちらの方法にも長所と短所があります。私の例では、アプリケーションがfd番号を使用するのではなく、パラメータとして使用する必要があるようです/dev/fd/x
。これは当初ハッキングであり、例えばfdを無駄にします。