¿Por qué POSIX requiere ciertas funciones integradas de shell para tener una implementación externa?

18

A partir de esta pregunta sobre si printf está integrado en yash , viene esta respuesta que cita el estándar POSIX .

La respuesta señala que la secuencia de búsqueda POSIX es encontrar una implementación externa del comando deseado y luego, si el shell lo ha implementado como integrado, ejecute el incorporado. (Para incorporados que no son incorporados especiales ).

¿Por qué POSIX tiene este requisito para que exista una implementación externa antes de permitir que se ejecute una implementación interna?

Parece ... arbitrario, así que tengo curiosidad.

Studog
fuente
Creo que es una forma de habilitar / deshabilitar los builtins si se desea / requiere.
Isaac
2
¿Deshabilitar el incorporado eliminando la implementación externa? Ahora no hay comandos de nombre printfdisponibles.
Studog
@studog, por lo tanto, cree un archivo vacío con el mismo nombre que el incorporado, active el bit de ejecución y colóquelo en un directorio en su RUTA. : P
Comodín
@Wildcard Un shell estrictamente compatible vería el nombre mientras buscaba PATHy luego llamaría a la utilidad incorporada, no al script externo. ¿Qué sucede si desea llamar al script externo en su ruta? Hmm ... Esto parece requerir una tabla que describa las diferentes posibilidades. Hay uno aquí , pero no tiene sentido para mí.
Kusalananda
@ Kusalananda, re su primera oración, ese fue mi punto. Por eso dije que creara un archivo vacío .
Comodín el

Respuestas:

15

Esta es una regla de "como si".

En pocas palabras: el comportamiento del shell tal como lo ven los usuarios no debería cambiar si una implementación decide hacer que un comando externo estándar también esté disponible como shell incorporado.

El contraste que mostré en /unix//a/496291/5132 entre los comportamientos de (por un lado) los proyectiles PD Korn, MirBSD Korn y Heirloom Bourne; (por otro lado) los proyectiles Z, 93 Korn, Bourne Again y Debian Almquist; y (en la mano de agarre) el caparazón Watanabe resalta esto.

Para los shells que no tienen printfincorporado, la eliminación /usr/binde PATHhace una invocación de printfdejar de funcionar. El comportamiento conforme POSIX, exhibido por el shell Watanabe en su modo conforme, causa el mismo resultado. El comportamiento del shell que tiene printfincorporado es como si estuviera invocando un comando externo.

Mientras que el comportamiento de todos los shells no conformes no altera si /usr/binse elimina PATH, y no se comportan como si estuvieran invocando un comando externo.

Lo que el estándar intenta garantizarle es que los shells pueden incorporar todo tipo de comandos normalmente externos (o implementarlos como sus propias funciones de shell), y aún obtendrá el mismo comportamiento de los incorporados que lo hizo. con los comandos externos si se ajusta PATHpara evitar que se encuentren los comandos. PATHsigue siendo su herramienta para seleccionar y controlar qué comandos puede invocar.

(Como se explicó en /unix//a/448799/5132 , hace años la gente eligió la personalidad de su Unix cambiando lo que estaba funcionando PATH).

Uno podría decir que hacer que el comando siempre funcione independientemente de si se puede encontrar PATH es, de hecho, el punto de hacer que los comandos normalmente externos estén integrados. (Es por eso que mi conjunto de herramientas nosh acaba de obtener un printenvcomando incorporado en la versión 1.38, de hecho. Aunque esto no es un shell).

Pero el estándar le brinda la garantía de que verá el mismo comportamiento para los comandos externos regulares que no están activados PATHdesde el shell, como lo verá en otros programas que no son del shell que invocan la execvpe()función, y el shell no podrá mágicamente ejecutar (aparentemente) comandos externos ordinarios que otros programas no pueden encontrar con el mismo PATH. Todo funciona de forma coherente desde la perspectiva del usuario, y PATHes la herramienta para controlar cómo funciona.

Otras lecturas

JdeBP
fuente
13

Eso es bastante absurdo y es por eso que ningún shell lo está implementando en su modo predeterminado.

La justificación del estándar y su ejemplo ilustrativo sugieren que este fue un intento fallido de tener una función incorporada regular asociada a una ruta y dejar que el usuario la anule haciendo que su propio binario aparezca antes PATH(por ejemplo, una función printfincorporada asociada con /usr/bin/printfpodría ser anulado por el /foo/bin/printfcomando externo mediante la configuración PATH=/foo/bin:$PATH).

Sin embargo, el estándar no terminó requiriendo eso, sino algo completamente diferente (y también inútil e inesperado).

Puede leer más al respecto en este informe de error . Citando del texto final aceptado :

Muchas implementaciones existentes ejecutan una función integrada regular sin realizar una búsqueda PATH. Este comportamiento no coincide con el texto normativo y no permite a los autores de scripts anular las utilidades integradas habituales a través de una RUTA especialmente diseñada. Además, la justificación explica que la intención es permitir que los autores anulen las incorporaciones modificando PATH, pero esto no es lo que dice el texto normativo .

FWIW, tampoco creo que haya ningún shell que implemente los requisitos revisados ​​del texto aceptado.

Mosvy
fuente
Vea también la discusión en article.gmane.org/gmane.comp.standards.posix.austin.general/… (y ha habido varios otros).
Stéphane Chazelas
También github.com/att/ast/issues/370 (largo)
Stéphane Chazelas
No, (por ejemplo, un comando externo printf asociado con / usr / bin / printf podría ser anulado por el comando externo / foo / bin / printf configurando PATH = / foo / bin: $ PATH). , Eso es incorrecto. La existencia de cualquiera / ambos / cualquiera de /usr/bin/printfo /foo/bin/printfen la RUTA activará la impresión incorporada . Lo único que printfhará un externo faltante (en la RUTA) es deshabilitar el incorporado. (Por la letra de la especificación).
Isaac