Sua pergunta parecia exigir uma resposta da floresta, e as respostas aqui parecem respostas de árvores, então pensei em fornecer uma resposta da floresta.
É muito raramente como os programas em C são gravados. É sempre como os scripts de shell são escritos e, às vezes, como os programas Python, perl ou Ruby são escritos.
As pessoas normalmente escrevem em C para facilitar o uso das bibliotecas do sistema e o acesso direto de baixo nível às chamadas do sistema OS, bem como a velocidade. E C é uma linguagem difícil de escrever, portanto, se as pessoas não precisam dessas coisas, elas não usam C. Também se espera que os programas em C tenham dependências apenas de bibliotecas compartilhadas e arquivos de configuração.
Descascar para um subprocesso não é particularmente rápido e não requer acesso refinado e controlado a instalações de sistema de baixo nível, e introduz uma dependência possivelmente surpreendente de um executável externo, portanto, é incomum ver em programas C.
Existem algumas preocupações adicionais. As preocupações de segurança e portabilidade mencionadas pelas pessoas são completamente válidas. Eles são igualmente válidos para scripts de shell, é claro, mas as pessoas esperam esses tipos de problemas nos scripts de shell. Porém, normalmente não se espera que os programas C tenham essa classe de preocupação com segurança, o que a torna mais perigosa.
Mas, na minha opinião, as maiores preocupações têm a ver com a maneira como ele popenirá interagir com o restante do seu programa. popenprecisa criar um processo filho, ler sua saída e coletar seu status de saída. Enquanto isso, o stderr desse processo será conectado ao mesmo stderr do seu programa, o que pode causar resultados confusos, e o stdin será o mesmo do seu programa, o que pode causar outros problemas interessantes. Você pode resolver isso incluindo </dev/null 2>/dev/nulla string para a qual você passa, uma popenvez que é interpretada pelo shell.
E popencria um processo filho. Se você fizer alguma coisa com os processos de manipulação ou bifurcação de SIGCHLDsinais, poderá receber sinais estranhos . Suas chamadas para waitpodem interagir de maneira estranha popene possivelmente criar condições de corrida estranhas.
As preocupações de segurança e portabilidade estão aí, é claro. Como eles são para scripts de shell ou qualquer coisa que inicie outros executáveis no sistema. E você deve ter cuidado para que as pessoas que usam o seu programa não consigam colocar metacaracteres de shell na string que você passa, popenporque essa string é fornecida diretamente shcom sh -c <string from popen as a single argument>.
Mas não acho que sejam por isso que é estranho ver um programa em C usando popen. O motivo é estranho, porque C é tipicamente uma linguagem de baixo nível e popennão é de baixo nível. E porque o uso de popenrestrições de design coloca em seu programa, porque ele irá interagir estranhamente com a entrada e saída padrão do seu programa e dificulta o gerenciamento de processos ou a manipulação de sinais. E porque normalmente não se espera que os programas em C tenham dependências em executáveis externos.