Por que o POSIX exige que certos shell internos tenham uma implementação externa?

18

A partir dessa pergunta sobre se printf é um built-in para yash , vem esta resposta que cita o padrão POSIX .

A resposta indica que a sequência de pesquisa POSIX é encontrar uma implementação externa do comando desejado e, se o shell o implementou como interno, execute o interno. (Para embutidos que não são embutidos especiais .)

Por que o POSIX tem esse requisito para que uma implementação externa exista antes de permitir que uma implementação interna seja executada?

Parece ... arbitrário, então estou curioso.

studog
fonte
Acredito que é uma maneira de ativar / desativar os recursos internos, se desejado / necessário.
Isaac
2
Desativando o interno removendo a implementação externa? Agora não há comandos de nome printfdisponíveis.
studog 23/01
@studog, então crie um arquivo vazio com o mesmo nome do built-in, ative o bit de execução e coloque-o em um diretório no seu PATH. : P
Wildcard
@Wildcard Um shell estritamente compatível veria o nome durante a pesquisa PATHe depois chamaria o utilitário interno , não o script externo. E se você quiser chamar o script externo no seu caminho? Hmm ... Isso parece exigir uma tabela descrevendo as diferentes possibilidades. Há um aqui , mas não faz sentido para mim.
Kusalananda
@ Kusalananda, re sua primeira frase, esse foi o meu ponto. Daí porque eu disse para criar um arquivo vazio .
Wildcard

Respostas:

15

Esta é uma regra "como se".

Simplificando: o comportamento do shell, como os usuários o vêem, não deve mudar se uma implementação decidir disponibilizar um comando externo padrão também como embutido no shell.

O contraste que mostrei em /unix//a/496291/5132 entre os comportamentos (por um lado) dos projéteis PD Korn, MirBSD Korn e Heirloom Bourne; (por outro lado) as conchas Z, 93 Korn, Bourne Again e Debian Almquist; e (na mão emocionante) a concha Watanabe destaca isso.

Para os shells que não têm printfcomo interno, a remoção /usr/binde PATHfaz uma invocação de printfparar de funcionar. O comportamento de conformidade POSIX, exibido pelo shell Watanabe em seu modo de conformidade, causa o mesmo resultado. O comportamento do shell que possui um printfbuilt-in é como se estivesse invocando um comando externo.

Enquanto o comportamento de todos os shells não-conformes não se altera se /usr/binfor removido PATHe eles não se comportam como se estivessem invocando um comando externo.

O que o padrão está tentando garantir a você é que os shells podem incorporar todos os tipos de comandos normalmente externos (ou implementá-los como suas próprias funções de shell), e você ainda terá o mesmo comportamento dos incorporados que fez. com os comandos externos se você ajustar PATHpara impedir que os comandos sejam encontrados. PATHcontinua sendo sua ferramenta para selecionar e controlar quais comandos você pode chamar.

(Como explicado em /unix//a/448799/5132 , anos atrás, as pessoas escolheram a personalidade de seu Unix alterando o que estava acontecendo PATH.)

Pode-se opinar que fazer o comando sempre funcionar, independentemente de poder ser encontrado, PATH é de fato o objetivo de criar comandos normalmente externos internos. (É por isso que meu conjunto de ferramentas nosh ganhou um printenvcomando interno na versão 1.38, de fato. Embora este não seja um shell.)

Mas o padrão está lhe dando a garantia de que você verá o mesmo comportamento para comandos externos regulares que não estão no PATHshell, como verá em outros programas não-shell que invocam a execvpe()função, e o shell não será capaz de magicamente execute (aparentemente) comandos externos comuns que outros programas não podem encontrar com o mesmo PATH. Tudo funciona de forma autônoma da perspectiva do usuário e PATHé a ferramenta para controlar como funciona.

Leitura adicional

JdeBP
fonte
13

Isso é um absurdo e é por isso que nenhum shell está implementando-o no modo padrão.

Do padrão de raciocínio e sua ilustrando exemplo sugerem que esta foi uma tentativa fracassada de ter um regulares built-in associada a um caminho, e deixar o usuário substituí-lo por ter o seu próprio binário comparecer perante ele em PATH(ex. Um printfbuilt-in associado com /usr/bin/printfpode ser substituído pelo /foo/bin/printfcomando externo, definindo PATH=/foo/bin:$PATH).

No entanto, o padrão não acabou exigindo isso, mas algo completamente diferente (e também inútil e inesperado).

Você pode ler mais sobre isso neste relatório de bug . Citação do texto final aceito :

Muitas implementações existentes executam um built-in regular sem executar uma pesquisa PATH. Esse comportamento não corresponde ao texto normativo e não permite que os autores de scripts substituam os utilitários internos regulares por meio de um PATH especialmente criado. Além disso, a lógica explica que a intenção é permitir que os autores substituam os incorporados modificando PATH, mas não é isso que diz o texto normativo .

FWIW, acho que também não há nenhum shell implementando os requisitos revisados ​​do texto aceito.

mosvy
fonte
Veja também a discussão em article.gmane.org/gmane.comp.standards.posix.austin.general/… (e houve várias outras).
Stéphane Chazelas 24/01
Também github.com/att/ast/issues/370 (long)
Stéphane Chazelas
Não, (por exemplo, um printf interno associado a / usr / bin / printf pode ser substituído pelo comando externo / foo / bin / printf configurando PATH = / foo / bin: $ PATH). , isso está incorreto. A existência de um / ambos / qualquer um /usr/bin/printfou /foo/bin/printfno PATH ativará o printf interno . A única coisa que um externo ausente (no PATH) printffará é desativar o builtin. (Pela letra da especificação).
Isaac