POSIX garantisce i percorsi verso eventuali utility standard?


22

Da C, qual è il modo più semplice per eseguire un'utilità standard (ad esempio, ps) e nessun altro?

Non POSIX garanzia che, per esempio, uno standard psè in /bin/pso devo resettare la variabile d'ambiente PATH per quello che ottengo con confstr(_CS_PATH, pathbuf, n);e quindi eseguire l'utilità attraverso il percorso-ricerca?


Ho nella parte posteriore della mia testa che POSIX dice, per una serie di comandi, tra i quali Ed (1) (che è importante per mksh ), che, se sono disponibili, anche loro devono essere sotto raggiungibile /bin, cioè /bin/eddeve essere utilizzabile se ed è installato. Non riesco a trovarlo in questo momento, ma so che l'LSB dipende da questo, e ho difeso con successo i segnalazioni di bug usando quello come motivazione, quindi almeno deve essere stato vero ad un certo punto. (O era qualcosa di diverso da POSuX e mi ricordo male, ma il resto è vero.)
mirabilos

Risposte:


33

No, principalmente perché non richiede che i sistemi siano conformi per impostazione predefinita o conformi solo allo standard POSIX (ad esclusione di qualsiasi altro standard).

Ad esempio, Solaris (un sistema conforme certificato) ha scelto la retrocompatibilità per le sue utility in /bin, il che spiega perché si comportano in modo arcano e forniscono utility compatibili con POSIX in posizioni separate ( /usr/xpg4/bin, /usr/xpg6/bin... per diverse versioni di XPG (ora unite in POSIX) standard, quelli che fanno effettivamente parte di componenti opzionali in Solaris).

Anche shnon è garantito per essere in /bin. Su Solaris, /bin/shera la shell Bourne (quindi non conforme a POSIX) fino a Solaris 10, mentre ora è ksh93 in Solaris 11 (ancora non completamente conforme a POSIX, ma in pratica più di così /usr/xpg4/bin/sh).

Da C, puoi usare exec*p()e presumere che ti trovi in ​​un ambiente POSIX (in particolare per quanto riguarda la PATHvariabile d'ambiente).

È inoltre possibile impostare la PATHvariabile di ambiente

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

Oppure potresti determinare in fase di compilazione il percorso delle utility POSIX che vuoi eseguire (tenendo presente che su alcuni sistemi come quelli GNU, hai bisogno di più passaggi come impostare una POSIXLY_CORRECTvariabile per garantire la conformità).

Puoi anche provare cose come:

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

Nella speranza che ci sia un shin $PATH, che sia come Bourne, che ci sia anche un getconfe che sia quello per la versione di POSIX che ti interessa.


Quindi cosa fai per # !?
Joshua,

13
@Joshua: preghi che /usr/bin/envesista ed è per lo più conforme a POSIX.
Kevin,

3
@Kevin o ti familiarizzi con le stranezze del tuo palaeo-unix e regola il #! linea per utilizzare il percorso corretto.
Cas

3
@Kevin: No. /usr/bin/envè un hack ancora meno portatile (in pratica) di /bin/sh. Per POSIX, il modo portabile di scrivere uno script di shell è senza #!affatto . Se un file è eseguibile ma ENOEXEC(non un binario valido), execvpè eseguirlo tramite la shell standard. :-) Ovviamente in pratica questa è una cattiva idea e dovresti semplicemente usarla #!/bin/sh.
R ..

2
@GeoffNixon, quella parte a cui ti riferisci è un'alternativa per quando non puoi, non puoi o non vuoi usare _POSIX_C_SOURCE. Esegue l'impostazione $PATHdalla shell anziché da C.
Stéphane Chazelas

3

In realtà, risponderei in gran parte . POSIX garantisce:

  1. Che v'è un percorso un assoluto versione conforme agli standard di ogni utilità specificato,
  2. E che devi essere in grado di trovare questo percorso assoluto ed essere in grado di eseguire questa utility.

Sebbene non sia necessariamente garantito che ciascuna utility sia in una particolare directory su tutti i sistemi ( /bin/ps), è sempre garantita la possibilità di essere trovata nel PERCORSO predefinito del sistema, come file eseguibile.

Infatti, l'unico modo standard specificato farlo nel standard è (in C) via unistd.h's _CS_PATH, o nel guscio, tramite una combinazione di commande getconfutilità, cioè, PATH="$(command -p getconf PATH)" command -v psdevono sempre restituire il percorso assoluto unica della POSIX psfornito su un sistema particolare. Cioè, mentre è definito dall'implementazione quali percorsi sono inclusi nella variabile PATH predefinita del sistema, questi programmi di utilità devono essere sempre disponibili, univoci e conformi, in uno dei percorsi ivi specificati.

Vedi: < unistd.h >, comando .


Ma per sh, c'è un problema con pollo e uova. Funzionerà PATH=$(command -p getconf PATH)solo da una shell POSIX in un ambiente POSIX. POSIX non specifica come entrare in quell'ambiente, solo che deve essere documentato. Per esempio, su Solaris, si dispone di una /usr/xpg4/bin/getconfed una /usr/xpg6/bin/getconfche restituire valori diversi per _CS_PATHle due diverse versioni dello standard e né /usr/xpg4/bin, né /usr/xpg6/binè nel valore predefinito di $PATH. C'è un /usr/bin/getconfIIRC che ti dà la conformità XPG4.
Stéphane Chazelas,

È vero anche per le versioni Solaris 11+ (certificazione UNIX 03+)? Ho sempre letto `` Le applicazioni ... dovrebbero essere determinate dall'interrogazione del PERCORSO restituito da getconf PERCORSO, assicurando che il nome di ritorno restituito sia un nome di percorso assoluto e non una shell incorporata. Ad esempio, per determinare la posizione dell'utilità sh standard: comando -v sh In alcune implementazioni questo potrebbe restituire: / usr / xpg4 / bin / sh `` '' significa che deve essere una voce conforme a POSIX shda qualsiasi shell predefinita .
Geoff Nixon,

1
Non c'è nulla in POSIX che dice che dovrebbe esserci un getconfcomando nel default $PATHdi un dato sistema. Ad esempio, ottenere un ambiente POSIX può comportare l'avvio di un livello di emulazione, senza il quale non si eseguirà affatto un comando simile a Unix (si pensi ad esempio a Windows). Una volta che ti trovi in ​​un ambiente conforme, getconf PATH ti consentirà $PATHdi accedere a utility conformi, ma se ti trovassi in un ambiente POSIX, probabilmente era già così. Si noti che getconf pspotrebbe tornare ps. Avere psincorporato è permesso.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.