Pourquoi POSIX nécessite-t-il que certains shell intégrés aient une implémentation externe?

19

De cette question de savoir si printf est une fonction intégrée pour yash , vient cette réponse qui cite la norme POSIX .

La réponse souligne que la séquence de recherche POSIX consiste à trouver une implémentation externe de la commande souhaitée, puis, si le shell l'a implémentée en tant que fonction intégrée, exécutez la fonction intégrée. (Pour les éléments intégrés qui ne sont pas des éléments spéciaux .)

Pourquoi POSIX a-t-il cette exigence d'existence d'une implémentation externe avant d'autoriser l'exécution d'une implémentation interne?

Cela semble ... arbitraire, donc je suis curieux.

studog
la source
Je crois que c'est un moyen d'activer / désactiver les intégrés si vous le souhaitez / requis.
Isaac
2
Désactiver le intégré en supprimant l'implémentation externe? Désormais, aucune commande de nom n'est printfdisponible.
studog
@studog, créez donc un fichier vide avec le même nom que le intégré, activez le bit d'exécution et placez-le dans un répertoire de votre PATH. : P
Wildcard
@Wildcard Un shell strictement conforme verrait alors le nom lors de la recherche PATHpuis appellera l'utilitaire intégré, pas le script externe. Et si vous souhaitez appeler le script externe sur votre chemin? Hmm ... Cela semble appeler un tableau décrivant les différentes possibilités. Il y en a un ici , mais ça n'a pas de sens pour moi.
Kusalananda
@Kusalananda, re votre première phrase, c'était mon point. C'est pourquoi j'ai dit de créer un fichier vide .
Wildcard

Réponses:

15

Il s'agit d'une règle "comme si".

Autrement dit: le comportement du shell tel que les utilisateurs le voient ne devrait pas changer si une implémentation décide de rendre une commande externe standard également disponible en tant que shell intégré.

Le contraste que j'ai montré sur /unix//a/496291/5132 entre les comportements (d'une part) des obus PD Korn, MirBSD Korn et Heirloom Bourne; (d'autre part) les obus Z, 93 Korn, Bourne Again et Debian Almquist; et (sur la main agrippée) la coque Watanabe le souligne.

Pour les shells qui n'ont pas de printffonction intégrée, la suppression /usr/binde PATHfait appel à l' printfarrêt du fonctionnement. Le comportement conforme POSIX, présenté par le shell Watanabe dans son mode conforme, provoque le même résultat. Le comportement du shell qui a une fonction printfintégrée est comme s'il appelait une commande externe.

Alors que le comportement de tous les shells non conformes ne change pas s'il /usr/binest supprimé de PATH, et ils ne se comportent pas comme s'ils invoquaient une commande externe.

Ce que la norme essaie de vous garantir, c'est que les shells peuvent intégrer toutes sortes de commandes normalement externes (ou les implémenter comme ses propres fonctions shell), et vous obtiendrez toujours le même comportement des built-ins que vous l'avez fait avec les commandes externes si vous ajustez PATHpour empêcher la recherche des commandes. PATHreste votre outil pour sélectionner et contrôler les commandes que vous pouvez invoquer.

(Comme expliqué sur /unix//a/448799/5132 , il y a des années, les gens ont choisi la personnalité de leur Unix en changeant ce qui était allumé PATH.)

On pourrait penser que le fait de toujours faire fonctionner la commande, qu'elle soit trouvée ou non, PATH est en fait le point de rendre les commandes normalement externes intégrées. (C'est pourquoi mon jeu d'outils nosh vient de gagner une printenvcommande intégrée dans la version 1.38, en fait. Bien que ce ne soit pas un shell.)

Mais la norme vous donne la garantie que vous verrez le même comportement pour les commandes externes normales qui ne sont pas activées à PATHpartir du shell, comme vous le verrez à partir d'autres programmes non shell appelant la execvpe()fonction, et le shell ne pourra pas par magie exécuter (apparemment) des commandes externes ordinaires que d'autres programmes ne peuvent pas trouver avec les mêmes PATH. Tout fonctionne de manière cohérente du point de vue de l'utilisateur et PATHest l'outil pour contrôler son fonctionnement.

Lectures complémentaires

JdeBP
la source
13

C'est assez absurde et c'est pourquoi aucun shell ne l'implémente dans son mode par défaut.

La justification de la norme et son exemple illustratif suggèrent qu'il s'agissait d'une tentative bâclée d'avoir un intégré standard associé à un chemin, et de laisser l'utilisateur le remplacer en faisant apparaître son propre binaire devant lui PATH(par exemple, un printfintégré associé à /usr/bin/printfpourrait être remplacée par la /foo/bin/printfcommande externe en définissant PATH=/foo/bin:$PATH).

Cependant, la norme n'a pas fini par l'exiger, mais quelque chose de complètement différent (et aussi inutile et inattendu).

Vous pouvez en savoir plus à ce sujet dans ce rapport de bogue . Citant du texte final accepté :

De nombreuses implémentations existantes exécutent une fonction intégrée standard sans effectuer de recherche PATH. Ce comportement ne correspond pas au texte normatif et il ne permet pas aux auteurs de scripts de remplacer les utilitaires intégrés standard via un PATH spécialement conçu. De plus, la justification explique que l' intention est de permettre aux auteurs de remplacer les prédéfinis en modifiant PATH, mais ce n'est pas ce que dit le texte normatif .

FWIW, je ne pense pas non plus qu'un shell implémente les exigences révisées du texte accepté.

mosvy
la source
Voir également la discussion sur article.gmane.org/gmane.comp.standards.posix.austin.general/… (et il y en a eu plusieurs autres).
Stéphane Chazelas
Aussi github.com/att/ast/issues/370 (long)
Stéphane Chazelas
Non, (par exemple, un printf intégré associé à / usr / bin / printf pourrait être remplacé par la commande externe / foo / bin / printf en définissant PATH = / foo / bin: $ PATH). , c'est incorrect. L'existence de / both / any of /usr/bin/printfou /foo/bin/printfdans le PATH activera le printf intégré . La seule chose qu'un externe (manquant dans le CHEMIN) printffera est de désactiver le builtin. (Par la lettre de la spécification).
Isaac