POSIX garantit-il les chemins vers les utilitaires standard?

22

À partir de C, quelle est la façon la plus simple d'exécuter un utilitaire standard (par exemple, ps) et aucun autre?

Est-ce que POSIX garantit que, par exemple, une norme psest dans /bin/psou dois-je réinitialiser la variable d'environnement PATH avec ce que j'obtiens confstr(_CS_PATH, pathbuf, n);, puis exécuter l'utilitaire via PATH-search?

PSkocik
la source
J'ai à l'arrière de ma tête que POSIX dit, pour un certain nombre de commandes, parmi lesquelles ed (1) (ce qui est important pour mksh ), que si elles sont disponibles, elles doivent également être accessibles sous /bin, c'est-à-dire qu'elles /bin/eddoivent être utilisables si ed est installé. Je ne le trouve pas pour le moment, mais je sais que LSB en dépend, et j'ai réussi à défendre les rapports de bogues en utilisant cela comme justification, donc cela doit au moins être vrai à un moment donné. (Ou c'était autre chose que POSuX et je me souviens mal, mais le reste est vrai.)
mirabilos

Réponses:

33

Non, ce n'est pas le cas, principalement parce qu'il n'exige pas que les systèmes soient conformes par défaut , ou uniquement à la norme POSIX (à l'exclusion de toute autre norme).

Par exemple, Solaris (un système conforme certifié) a choisi la compatibilité descendante pour ses utilitaires dans /bin, ce qui explique pourquoi ceux-ci se comportent de manière mystérieuse, et fournissent des utilitaires conformes POSIX dans des emplacements distincts ( /usr/xpg4/bin, /usr/xpg6/bin... pour différentes versions de XPG (maintenant fusionnées) en POSIX) standard, ceux-ci faisant en fait partie des composants optionnels de Solaris).

Même shn'est pas garanti d'être en/bin . Sous Solaris, /bin/shétait le shell Bourne (donc pas compatible POSIX) jusqu'à Solaris 10, alors qu'il est maintenant ksh93 dans Solaris 11 (toujours pas entièrement compatible POSIX, mais en pratique plus que /usr/xpg4/bin/sh).

De C, vous pouvez utiliser exec*p() et supposer que vous êtes dans un environnement POSIX (en particulier en ce qui concerne la PATHvariable d'environnement).

Vous pouvez également définir la PATHvariable d'environnement

#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"...);

Ou vous pouvez déterminer au moment de la construction le chemin des utilitaires POSIX que vous souhaitez exécuter (en gardant à l'esprit que sur certains systèmes comme GNU, vous avez besoin de plus d'étapes comme définir un POSIXLY_CORRECT variable pour garantir la conformité).

Vous pouvez également essayer des choses comme:

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

Dans l'espoir qu'il y ait un shin $PATH, qu'il ressemble à Bourne, qu'il y en ait aussi un getconfet que c'est celui de la version de POSIX qui vous intéresse.

Stéphane Chazelas
la source
Alors, que faites-vous pour # !?
Joshua
13
@Joshua: Vous priez pour que cela /usr/bin/envexiste et qu'il soit principalement conforme à POSIX.
Kevin
3
@Kevin ou vous vous familiarisez avec les caprices de votre paléo-unix et ajustez le #! pour utiliser le chemin correct.
ČAS
3
@Kevin: Non. /usr/bin/envC'est un hack encore moins portable (en pratique) que /bin/sh. Par Posix, la façon portable pour écrire un script shell est sans #!du tout . Si un fichier est exécutable mais ENOEXEC(pas un binaire valide), execvpc'est de l'exécuter via le shell standard. :-) Bien sûr, dans la pratique, c'est une mauvaise idée et vous devez simplement l'utiliser #!/bin/sh.
R ..
2
@GeoffNixon, cette partie à laquelle vous faites référence est une alternative lorsque vous ne pouvez pas, ne pouvez pas ou ne voulez pas utiliser _POSIX_C_SOURCE. Il fait le réglage de $PATHla coquille au lieu de C.
Stéphane Chazelas
3

En fait, je répondrais largement oui . POSIX garantit:

  1. Qu'il y a un chemin absolu une version conforme aux normes de chaque service spécifié,
  2. Et, que vous devez être capable de trouver ce chemin absolu et pouvoir exécuter cet utilitaire.

Bien qu'il ne soit pas nécessairement garanti que chaque utilitaire soit dans un répertoire particulier sur tous les systèmes ( /bin/ps), il est toujours garanti de pouvoir être trouvé dans le PATH par défaut du système, en tant que fichier exécutable.

En effet, la seule façon spécifiée par la norme de le faire dans la norme est (en C) via unistd.h_CS_PATH de, ou dans le shell, via une combinaison de commandet des getconfutilitaires, c'est-à-dire, PATH="$(command -p getconf PATH)" command -v psdoit toujours renvoyer le chemin absolu unique de la conformité POSIX psfourni sur un système particulier. Autrement dit, bien qu'il soit défini par l'implémentation quels chemins sont inclus dans la variable PATH par défaut du système, ces utilitaires doivent toujours être disponibles, uniques et conformes, dans l'un des chemins qui y sont spécifiés.

Voir: < unistd.h >, commande .

Geoff Nixon
la source
Mais pour sh, il y a un problème de poulet et d'oeuf. Cela PATH=$(command -p getconf PATH)ne fonctionnera qu'à partir d'un shell POSIX dans un environnement POSIX. POSIX ne spécifie pas comment vous entrez dans cet environnement, mais simplement qu'il soit documenté. Par exemple, sur Solaris, vous avez un /usr/xpg4/bin/getconfet un /usr/xpg6/bin/getconfqui renverraient des valeurs différentes _CS_PATHpour les deux versions différentes de la norme et ni l'un /usr/xpg4/binni l' autre ne /usr/xpg6/binsont dans la valeur par défaut de $PATH. Il y en a un /usr/bin/getconfqui IIRC vous donne la conformité XPG4.
Stéphane Chazelas
Est-ce vrai même pour les versions Solaris 11+ (certifiées UNIX 03+)? J'ai toujours lu `` Les applications ... devraient être déterminées en interrogeant le PATH retourné par getconf PATH, en veillant à ce que le chemin retourné soit un chemin absolu et non un shell intégré. Par exemple, pour déterminer l'emplacement de l'utilitaire sh standard: commande -v sh Sur certaines implémentations, cela peut renvoyer: / usr / xpg4 / bin / sh `` `pour signifier qu'il doit s'agir d'une entrée vers un POSIX conforme à shpartir de n'importe quel shell par défaut .
Geoff Nixon
1
Il n'y a rien dans POSIX qui dise qu'il devrait y avoir une getconfcommande par défaut $PATHd'un système donné. Par exemple, obtenir un environnement POSIX peut impliquer le démarrage d'une couche d'émulation, sans laquelle vous n'exécuteriez aucune commande de type Unix (pensez à Windows par exemple). Une fois que vous êtes dans un environnement conforme, getconf PATH vous obtiendrez un $PATHaccès à des utilitaires conformes, mais si vous étiez dans un environnement POSIX, c'était probablement déjà le cas. Notez que cela getconf pspeut revenir ps. Avoir psintégré est autorisé.
Stéphane Chazelas