Gewährleistet POSIX die Pfade zu Standarddienstprogrammen?


22

Was ist in C der einfachste Weg, um ein Standarddienstprogramm (z. B. ps) und kein anderes auszuführen?

Gewährleistet POSIX, dass beispielsweise ein Standard vorhanden psist, /bin/psoder sollte ich die Umgebungsvariable PATH auf das zurücksetzen, was ich erhalte, confstr(_CS_PATH, pathbuf, n);und das Dienstprogramm dann über die PATH-Suche ausführen?


Ich habe im Hinterkopf, dass POSIX für eine Reihe von Befehlen, darunter ed (1) (was für mksh wichtig ist ), sagt , dass sie auch erreichbar sein müssen , dh verwendbar sein müssen , wenn sie verfügbar sind wenn ed installiert ist. Ich kann es momentan nicht finden, aber ich weiß, dass LSB davon abhängt, und ich habe Bugreports erfolgreich verteidigt, indem ich das als Begründung verwendet habe, also muss es zumindest irgendwann wahr gewesen sein. (Oder es war etwas anderes als POSuX und ich erinnere mich falsch, aber der Rest ist wahr.)/bin/bin/ed
Mirabilos

Antworten:


33

Nein, dies ist nicht der Fall, hauptsächlich aus dem Grund, dass für Systeme keine Standardkonformität oder nur die Einhaltung des POSIX-Standards (unter Ausschluss eines anderen Standards) erforderlich ist .

Zum Beispiel Solaris (ein zertifiziertes konformes System) wählte die Abwärtskompatibilität für sein Dienstprogramme /bin, was erklärt , warum diejenigen , verhalten sie in obskuren Wegen und POSIX-konformen Dienstprogramme in getrennten Standorten bieten ( /usr/xpg4/bin, /usr/xpg6/bin... für verschiedene Versionen der XPG (jetzt verschmolzen im POSIX) -Standard, wobei diese Komponenten tatsächlich Teil optionaler Komponenten in Solaris sind.

Auch shist nicht garantiert, in zu sein /bin. Unter Solaris /bin/shfrüher das Bourne - Shell (also nicht POSIX - konform) bis Solaris 10, während es jetzt ksh93 in Solaris 11 (noch nicht vollständig POSIX - konform, aber in der Praxis mehr als /usr/xpg4/bin/sh).

Ab C können Sie verwenden exec*p()und davon ausgehen, dass Sie sich in einer POSIX-Umgebung befinden (insbesondere in Bezug auf die PATHUmgebungsvariable).

Sie können auch die PATHUmgebungsvariable festlegen

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

Oder Sie können zum Zeitpunkt der Erstellung den Pfad der POSIX-Dienstprogramme bestimmen, die Sie ausführen möchten (unter Berücksichtigung der Tatsache, dass auf einigen Systemen wie GNU weitere Schritte erforderlich sind, z. B. das Festlegen einer POSIXLY_CORRECTVariablen, um die Konformität sicherzustellen).

Sie können auch Folgendes ausprobieren:

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

In der Hoffnung, dass es ein shIn gibt $PATH, dass es Bourne-artig ist, dass es auch ein gibt getconfund dass es dasjenige für die Version von POSIX ist, an der Sie interessiert sind.


Also, was machst du für # !?
Joshua,

13
@Joshua: Du betest, dass /usr/bin/enves das gibt und es meistens POSIX-konform ist.
Kevin,

3
@ Kevin oder du machst dich mit den Macken deines Paläo-Unix vertraut und stell die #! Zeile, um den richtigen Pfad zu verwenden.
cas

3
@ Kevin: Nein, /usr/bin/envist ein noch weniger portabler (in der Praxis) Hack als /bin/sh. Per POSIX ist die tragbare Art und Weise einen Shell - Skript zu schreiben , ohne #!überhaupt . Wenn eine Datei aber ausführbar ist ENOEXEC(keine gültige Binärdatei), execvpsoll diese über die Standard-Shell ausgeführt werden. :-) Natürlich ist das in der Praxis eine schlechte Idee und du solltest es nur benutzen #!/bin/sh.
R ..

2
@GeoffNixon, der Teil, auf den Sie sich beziehen, ist eine Alternative für den Fall, dass Sie _POSIX_C_SOURCE nicht verwenden können oder möchten. Es macht die Einstellung von $PATHaus der Muschel anstelle von C.
Stéphane Chazelas

3

Eigentlich würde ich größtenteils ja antworten . POSIX garantiert:

  1. Daß es ist ein absoluter Pfad ein , um standardkonforme Version jedes angegebenen Dienstprogramm,
  2. Und dass Sie diesen absoluten Pfad finden und dieses Dienstprogramm ausführen können müssen.

Obwohl es nicht unbedingt gewährleistet , dass jedes Dienstprogramm über alle Systeme in einem bestimmten Verzeichnis sein soll ( /bin/ps), ist es immer garantiert der Lage sein , in den Systemstandard PATH gefunden werden, als eine ausführbare Datei.

Tatsächlich ist der einzige Standard festgelegten Weg , dies in der Norm zu tun ist (in C) über unistd.h‚s _CS_PATH oder in der Schale, über eine Kombination aus commandund getconfDienstprogramme, also PATH="$(command -p getconf PATH)" command -v psmuss immer den einzigartigen absoluten Pfad der Rückkehr des POSIX-konform psauf einem bestimmten System geliefert. Das heißt, während die Implementierung festlegt, welche Pfade in der Systemstandardvariablen PATH enthalten sind, müssen diese Utilities in einem der darin angegebenen Pfade immer verfügbar, eindeutig und konform sein.

Siehe: < unistd.h >, Befehl .


Aber für sie gibt es ein Henne-Ei-Problem. Das PATH=$(command -p getconf PATH)funktioniert nur von einer POSIX-Shell in einer POSIX-Umgebung. POSIX legt nicht fest, wie Sie in diese Umgebung gelangen, sondern nur, dass dies dokumentiert wird. Unter Solaris haben Sie beispielsweise ein /usr/xpg4/bin/getconfund ein, /usr/xpg6/bin/getconfdie unterschiedliche Werte für _CS_PATHdie beiden verschiedenen Versionen des Standards zurückgeben und weder den Standardwert von /usr/xpg4/binnoch /usr/xpg6/binden Standardwert von haben $PATH. Es gibt ein /usr/bin/getconfIIRC, mit dem Sie XPG4-Konformität erhalten.
Stéphane Chazelas

Gilt das auch für Solaris 11+ (UNIX 03+ -zertifiziert)? Ich habe immer gelesen, `` `Applications ... sollten durch Abfrage des von getconf PATH zurückgegebenen PATH ermittelt werden, wobei sicherzustellen ist, dass der zurückgegebene Pfadname ein absoluter Pfadname und keine eingebaute Shell ist. Um beispielsweise den Speicherort des Standard-Dienstprogramms sh zu ermitteln, geben Sie den folgenden Befehl ein: -v sh Bei einigen Implementierungen kann Folgendes zurückgegeben werden: / usr / xpg4 / bin / sh `` `Dies muss ein Eintrag in einer POSIX-kompatiblen shStandardshell sein .
Geoff Nixon

1
In POSIX gibt es nichts, was besagt, dass getconfder Standard $PATHeines bestimmten Systems einen Befehl enthalten sollte. Zum Abrufen einer POSIX-Umgebung muss möglicherweise eine Emulationsebene gestartet werden, ohne die Sie überhaupt keinen Unix-ähnlichen Befehl ausführen würden (z. B. Windows). Sobald Sie sich in einer kompatiblen Umgebung befinden, getconf PATH erhalten Sie einen $PATHZugang zu kompatiblen Dienstprogrammen. Wenn Sie sich jedoch in einer POSIX-Umgebung befinden, war dies wahrscheinlich bereits der Fall. Beachten Sie, dass getconf psmöglicherweise zurückkehren ps. Mit psbuiltin ist erlaubt.
Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.