Apakah POSIX menjamin jalur ke utilitas standar apa pun?

22

Dari C, apa cara termudah untuk menjalankan utilitas standar (mis. Ps) dan tidak ada yang lain?

Apakah POSIX menjamin bahwa, misalnya, suatu standar psada /bin/psatau haruskah saya mereset variabel lingkungan PATH dengan apa yang saya dapatkan confstr(_CS_PATH, pathbuf, n);dan kemudian menjalankan utilitas melalui pencarian PATH?

PSkocik
sumber
Saya memiliki di belakang kepala saya bahwa POSIX mengatakan, untuk sejumlah perintah, di antaranya ed (1) (yang penting untuk mksh ), bahwa, jika tersedia, mereka juga harus dapat dijangkau di bawah /bin, yaitu /bin/edharus dapat digunakan jika ed diinstal. Saya tidak dapat menemukannya sekarang, tetapi saya tahu LSB bergantung padanya, dan saya telah berhasil membela laporan bug menggunakan itu sebagai alasan, jadi setidaknya itu benar pada beberapa titik. (Atau itu sesuatu selain POSUX dan saya salah ingat, tetapi sisanya benar.)
mirabilos

Jawaban:

33

Tidak, itu tidak, terutama karena itu tidak mengharuskan sistem untuk menyesuaikan secara default , atau hanya mematuhi standar POSIX (dengan mengesampingkan standar lain).

Misalnya, Solaris (sistem yang memenuhi syarat sertifikasi) memilih kompatibilitas ke belakang untuk utilitasnya /bin, yang menjelaskan mengapa mereka berperilaku misterius, dan menyediakan utilitas yang sesuai dengan POSIX di lokasi yang berbeda ( /usr/xpg4/bin, /usr/xpg6/bin... untuk versi XPG yang berbeda (sekarang digabung ke dalam POSIX) standar, yang sebenarnya merupakan bagian dari komponen opsional di Solaris).

Bahkan shtidak dijamin masuk /bin. Pada Solaris, /bin/shdulu merupakan Bourne shell (jadi bukan POSIX compliant) hingga Solaris 10, sementara itu sekarang ksh93 di Solaris 11 (masih belum sepenuhnya memenuhi POSIX, tetapi dalam praktiknya lebih dari itu /usr/xpg4/bin/sh).

Dari C, Anda bisa menggunakan exec*p()dan menganggap Anda berada dalam lingkungan POSIX (khususnya terkait PATHvariabel lingkungan).

Anda juga bisa mengatur PATHvariabel lingkungan

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

Atau Anda bisa menentukan pada saat membangun jalur utilitas POSIX yang ingin Anda jalankan (mengingat bahwa pada beberapa sistem seperti yang GNU, Anda memerlukan langkah-langkah lebih lanjut seperti mengatur POSIXLY_CORRECTvariabel untuk memastikan kepatuhan).

Anda juga dapat mencoba hal-hal seperti:

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

Dengan harapan ada shdi $PATHdalamnya, seperti Bourne, ada juga di getconfdalamnya dan itu untuk versi POSIX yang Anda minati.

Stéphane Chazelas
sumber
Jadi apa yang kamu lakukan untuk # !?
Joshua
13
@ Yosua: Anda berdoa yang /usr/bin/envada dan sebagian besar sesuai dengan POSIX
Kevin
3
@Kevin atau Anda membiasakan diri dengan kebiasaan palaeo-unix Anda dan sesuaikan #! baris untuk menggunakan jalur yang benar.
cas
3
@Kevin: Tidak. Ini /usr/bin/envadalah retasan yang bahkan lebih portabel (dalam praktiknya) daripada /bin/sh. Per POSIX, cara portabel untuk menulis skrip shell adalah tanpa #!sama sekali . Jika suatu file dapat dieksekusi tetapi ENOEXEC(bukan biner yang valid), execvpharus dijalankan melalui shell standar. :-) Tentu saja dalam praktiknya ini adalah ide yang buruk dan sebaiknya Anda gunakan saja #!/bin/sh.
R ..
2
@ GeoffNixon, bagian yang Anda maksud adalah alternatif ketika Anda tidak, tidak bisa atau tidak ingin menggunakan _POSIX_C_SOURCE. Itu pengaturan dari $PATHshell bukannya dari C.
Stéphane Chazelas
3

Sebenarnya, saya sebagian besar akan menjawab ya . POSIX tidak menjamin:

  1. Yang ada adalah sebuah jalan mutlak untuk versi standar-compliant setiap utilitas yang ditentukan,
  2. Dan, Anda harus dapat menemukan jalur absolut ini, dan dapat menjalankan utilitas ini.

Meskipun tidak selalu dijamin bahwa setiap utilitas harus berada dalam direktori tertentu di semua sistem ( /bin/ps), selalu dijamin dapat ditemukan di PATH default sistem, sebagai file yang dapat dieksekusi.

Memang, satu-satunya cara standar yang ditentukan untuk melakukan ini dalam standar adalah (dalam C) melalui unistd.h_CS_PATH, atau dalam shell, melalui kombinasi commanddan getconfutilitas, yaitu, PATH="$(command -p getconf PATH)" command -v psharus selalu mengembalikan jalur absolut unik dari yang kompatibel dengan POSIX psdipasok pada sistem tertentu. Yaitu, ketika implementasi-didefinisikan jalur mana yang termasuk dalam variabel PATH standar sistem, utiliti ini harus selalu tersedia, unik, dan sesuai, di salah satu jalur yang ditentukan di dalamnya.

Lihat: < unistd.h >, perintah .

Geoff Nixon
sumber
Tapi untuk sh, ada masalah ayam dan telur. Itu PATH=$(command -p getconf PATH)hanya akan bekerja dari shell POSIX di lingkungan POSIX. POSIX tidak menentukan bagaimana Anda masuk ke lingkungan itu, hanya saja itu didokumentasikan. Misalnya, pada Solaris, Anda memiliki a /usr/xpg4/bin/getconfdan a /usr/xpg6/bin/getconfyang akan mengembalikan nilai yang berbeda untuk _CS_PATHuntuk dua versi standar yang berbeda dan tidak /usr/xpg4/binjuga tidak /usr/xpg6/binada dalam nilai default $PATH. Ada /usr/bin/getconfyang IIRC memberi Anda kesesuaian XPG4.
Stéphane Chazelas
Apakah itu berlaku untuk versi Solaris 11+ (bersertifikat UNIX 03+)? Saya selalu membaca `` `Aplikasi ... harus ditentukan dengan interogasi PATH yang dikembalikan oleh getconf PATH, memastikan bahwa pathname yang dikembalikan adalah pathname absolut dan bukan shell built-in. Misalnya, untuk menentukan lokasi utilitas standar sh: perintah -v sh Pada beberapa implementasi ini mungkin kembali: / usr / xpg4 / bin / sh `` berarti ini harus menjadi entri ke compliant POSIX shdari setiap shell default .
Geoff Nixon
1
Tidak ada dalam POSIX yang mengatakan bahwa harus ada getconfperintah di default $PATHsistem yang diberikan. Sebagai contoh, mendapatkan lingkungan POSIX mungkin melibatkan memulai lapisan emulasi, tanpanya Anda tidak akan menjalankan perintah seperti Unix sama sekali (pikirkan Windows misalnya). Setelah Anda berada di lingkungan yang patuh, getconf PATH akan membuat Anda mendapatkan $PATHuntuk mencapai utilitas yang patuh, tetapi jika Anda berada di lingkungan POSIX, itu mungkin sudah menjadi masalahnya. Perhatikan bahwa getconf psmungkin kembali ps. Memiliki psbuiltin diperbolehkan.
Stéphane Chazelas