¿POSIX garantiza las rutas a las utilidades estándar?

22

Desde C, ¿cuál es la forma más fácil de ejecutar una utilidad estándar (por ejemplo, ps) y ninguna otra?

¿Garantiza POSIX que, por ejemplo, un estándar psse encuentra en /bin/pso debería restablecer la variable de entorno PATH para lo que me pasa con confstr(_CS_PATH, pathbuf, n);y vuelva a ejecutar la utilidad de ruta de búsqueda?

PSkocik
fuente
Tengo en la parte posterior de mi cabeza que POSIX dice, para una serie de comandos, entre ellos ed (1) (que es importante para mksh ), que, si están disponibles, también deben ser accesibles desde /bin, es decir, /bin/eddeben ser utilizables si ed está instalado No puedo encontrarlo en este momento, pero sé que LSB depende de ello, y he defendido con éxito los informes de errores utilizando eso como justificación, por lo que al menos debe haber sido cierto en algún momento. (O era algo más que POSuX y lo recuerdo mal, pero el resto es cierto.)
mirabilos el

Respuestas:

33

No, no lo hace, principalmente por el hecho de que no requiere que los sistemas se ajusten de manera predeterminada o que cumplan solo con el estándar POSIX (con la exclusión de cualquier otro estándar).

Por ejemplo, Solaris (un sistema certificado compatible) eligió la compatibilidad con versiones anteriores para sus utilidades /bin, lo que explica por qué se comportan de manera arcana y proporciona utilidades compatibles con POSIX en ubicaciones separadas ( /usr/xpg4/bin, /usr/xpg6/bin... para diferentes versiones de XPG (ahora fusionadas en POSIX), que en realidad son parte de componentes opcionales en Solaris).

Incluso shno se garantiza que esté en /bin. En Solaris, /bin/shsolía ser el shell Bourne (por lo que no es compatible con POSIX) hasta Solaris 10, mientras que ahora es ksh93 en Solaris 11 (todavía no es totalmente compatible con POSIX, pero en la práctica es más que eso /usr/xpg4/bin/sh).

Desde C, puede usar exec*p()y asumir que está en un entorno POSIX (en particular con respecto a la PATHvariable de entorno).

También puede establecer la PATHvariable de entorno

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);

O puede determinar en el momento de la compilación la ruta de las utilidades POSIX que desea ejecutar (teniendo en cuenta que en algunos sistemas como los GNU, necesita más pasos, como establecer una POSIXLY_CORRECTvariable para garantizar el cumplimiento).

También puedes probar cosas como:

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);

Con la esperanza de que hay una shen $PATH, que es similar a Bourne, que también hay una getconfy que es el de la versión de POSIX Múdese interesados.

Stéphane Chazelas
fuente
Entonces, ¿qué haces por #?
Joshua
13
@ Joshua: Rezas para que /usr/bin/envexista y cumpla principalmente con POSIX.
Kevin
3
¡@Kevin o te familiarizarás con las peculiaridades de tu paleo-unix y ajustarás el #! línea para usar la ruta correcta.
cas
3
@Kevin: No. /usr/bin/enves un truco aún menos portátil (en la práctica) que /bin/sh. Según POSIX, la forma portátil de escribir un script de shell es sin ningún tipo #!de . Si un archivo es ejecutable pero ENOEXEC(no es un binario válido), execvpes ejecutarlo a través del shell estándar. :-) Por supuesto, en la práctica esta es una mala idea y solo debes usarla #!/bin/sh.
R ..
2
@ GeoffNixon, esa parte a la que te refieres es una alternativa para cuando no quieres, no puedes o no quieres usar _POSIX_C_SOURCE. Realiza la configuración $PATHdesde el caparazón en lugar de desde C.
Stéphane Chazelas
3

En realidad, respondería en gran medida que . POSIX garantiza:

  1. Que no es una ruta absoluta una a la versión compatible con los estándares de cada utilidad especificado,
  2. Y que debe poder encontrar esta ruta absoluta y poder ejecutar esta utilidad.

Aunque no se garantiza necesariamente que cada utilidad esté en un directorio particular en todos los sistemas ( /bin/ps), siempre se garantiza que se pueda encontrar en la RUTA predeterminada del sistema, como un archivo ejecutable.

De hecho, la única forma especificada por el estándar para hacer esto en el estándar es (en C) a través unistd.hde _CS_PATH, o en el shell, a través de una combinación de commandy getconfutilidades, es decir, PATH="$(command -p getconf PATH)" command -v pssiempre debe devolver la ruta absoluta única de los que cumplen con POSIX pssuministrado en un sistema particular. Es decir, si bien es definido por la implementación , que los caminos están incluidos en la variable PATH por defecto del sistema, estas utilidades debe siempre estar disponible, único y compatible, en una de las rutas especificadas en el mismo.

Ver: < unistd.h >, comando .

Geoff Nixon
fuente
Pero para sh, hay un problema de pollo y huevo. Eso PATH=$(command -p getconf PATH)solo funcionará desde un shell POSIX en un entorno POSIX. POSIX no especifica cómo ingresa a ese entorno, solo que esté documentado. Por ejemplo, en Solaris, tiene un /usr/xpg4/bin/getconfy un /usr/xpg6/bin/getconfque devolvería valores diferentes _CS_PATHpara las dos versiones diferentes del estándar y ninguno /usr/xpg4/binni /usr/xpg6/binestá en el valor predeterminado de $PATH. Hay un /usr/bin/getconfIIRC que le da conformidad con XPG4.
Stéphane Chazelas
¿Es eso cierto incluso para las versiones Solaris 11+ (certificado UNIX 03+)? Siempre he leído `` Las aplicaciones ... deben determinarse mediante el interrogatorio de la RUTA devuelta por getconf PATH, asegurando que el nombre de ruta devuelto sea un nombre de ruta absoluto y no un shell incorporado. Por ejemplo, para determinar la ubicación de la utilidad sh estándar: comando -v sh En algunas implementaciones, esto podría devolver: / usr / xpg4 / bin / sh `` `para significar que debe ser una entrada a un POSIX compatible shdesde cualquier shell predeterminado .
Geoff Nixon
1
No hay nada en POSIX que diga que debería haber un getconfcomando en el valor predeterminado $PATHde un sistema determinado. Por ejemplo, obtener un entorno POSIX puede implicar iniciar una capa de emulación, sin la cual no ejecutaría ningún comando similar a Unix (piense en Windows, por ejemplo). Una vez que se encuentre en un entorno compatible, getconf PATH obtendrá un $PATHacceso a las utilidades compatibles, pero si estuviera en un entorno POSIX, probablemente ese ya era el caso. Tenga en cuenta que getconf pspuede volver ps. Tener psincorporado está permitido.
Stéphane Chazelas