Em
./binary < file
O stdin de binary é o arquivo aberto no modo somente leitura. Note que bash não lê o arquivo, apenas o abre para leitura no descritor de arquivo 0 (stdin) do processo que executa binary in.
Em:
./binary << EOF
test
EOF
Dependendo do shell, o stdin de binary será um arquivo temporário excluído (AT & T ksh, zsh, bash ...) que contém test\n como colocado lá pelo shell ou o final de leitura de um pipe ( dash , yash ; e o shell grava test\n em paralelo na outra extremidade do pipe). No seu caso, se você estiver usando bash , seria um arquivo temporário.
Em:
cat file | ./binary
Dependendo do shell, o stdin de binary será o final de leitura de um pipe ou uma extremidade de um par de soquetes onde a direção de escrita foi encerrada (ksh93) e cat está gravando o conteúdo de file no outro extremo.
Quando stdin é um arquivo regular (temporário ou não), é procurado. binary pode ir para o início ou fim, retroceder, etc. Ele também pode mapear, fazer alguns ioctl()s como FIEMAP / FIBMAP (se usar <> em vez de < , ele poderá truncar / furar nele , etc).
pipes e pares de soquetes, por outro lado, são meios de comunicação entre processos, não há muito binary a fazer além de read ing os dados (embora também existam algumas operações como ioctl() s específicas de canal que poderia fazer com eles e não em arquivos regulares).
Na maioria das vezes, é a capacidade perdida de seek que faz com que os aplicativos falhem / reclamem ao trabalhar com pipes, mas poderia ser qualquer outra chamada de sistema válida em arquivos regulares, mas não em tipos diferentes de arquivos (como mmap() , ftruncate() , fallocate() ). No Linux, também há uma grande diferença no comportamento quando você abre /dev/stdin enquanto o fd 0 está em um canal ou em um arquivo regular.
Existem muitos comandos por aí que só podem lidar com arquivos buscáveis , mas quando esse é o caso, geralmente não são os arquivos abertos no stdin.
$ unzip -l file.zip
Archive: file.zip
Length Date Time Name
--------- ---------- ----- ----
11 2016-12-21 14:43 file
--------- -------
11 1 file
$ unzip -l <(cat file.zip)
# more or less the same as cat file.zip | unzip -l /dev/stdin
Archive: /proc/self/fd/11
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of /proc/self/fd/11 or
/proc/self/fd/11.zip, and cannot find /proc/self/fd/11.ZIP, period.
unzip precisa ler o índice armazenado no final do arquivo e, em seguida, procurar dentro do arquivo para ler os membros do arquivo. Mas aqui, o arquivo (regular no primeiro caso, pipe no segundo) é dado como um argumento de caminho para unzip e unzip abre ele mesmo (normalmente em fd diferente de 0) em vez de herdar um fd já aberto pelo pai. Não lê arquivos zip de seu stdin. O stdin é usado principalmente para interação do usuário.
Se você executar esse binary do seu sem redirecionamento no prompt de um shell interativo em execução em um emulador de terminal, então o stdin de binary será herdado de seu pai do shell, que por sua vez o herdará de seu pai, o emulador de terminal, e será um dispositivo pty aberto no modo de leitura + gravação (algo como /dev/pts/n ).
Esses dispositivos também não são procurados. Portanto, se binary funcionar bem ao receber entradas do terminal, talvez o problema não seja a busca.
Se esse 14 for um errno (um código de erro definido por chamadas de sistema com falha), então, na maioria dos sistemas, isso seria EFAULT ( Endereço incorreto ). A chamada do sistema read() falharia com esse erro se solicitada a leitura em um endereço de memória que não seja gravável. Isso seria independente do fato de o fd ler os dados de pontos para um pipe ou arquivo regular e geralmente indicaria um bug 1 .
binary possivelmente determina o tipo de arquivo aberto em seu stdin (com fstat() ) e é executado em um bug quando não é um arquivo regular nem um dispositivo tty.
Difícil dizer sem saber mais sobre o aplicativo. Executá-lo em strace (ou truss / tusc equivalente em seu sistema) pode nos ajudar a ver qual é a chamada do sistema, se houver alguma falha aqui.
1 O cenário imaginado por Matthew Ife em um comentário à sua pergunta parece bastante plausível aqui. Citando ele:
I suspect it is seeking to the end of file to get a buffer size for reading the data, badly handling the fact that seek doesn't work and attempting to allocate a negative size (not handling a bad malloc). Passing the buffer to read which faults given the buffer is not valid.