Szukany tag: X Window System Susbsytem: Console ;-) Niekiedy spotykam się z "oskarżeniami" początkujących użytkowników, że muszą uruchomić konsolę, by wejść w nano lub mc. No cóż... Patrząc na ich doświadczenia z Windows, faktycznie mogą mieć pretensje. Tymczasem detekcja czy użytkownik może odbierać nasze komunikaty/wprowadzać informacje nie jest taka trudna. Każdy program mógłby mieć te kilka linijek kodu + trochę na utworzenie pseudoterminala i uruchomienie xterm-a.
W swoich podróżach zaczynałem od skryptów w Bash-u. Zauważyłem, że polecenie read, gdy nie może pobrać danych kończy się z kodem wyjątku. Problemem była jednak konieczność uruchomienia xterm-a z nową instancją naszej aplikacji(!!). Nie jest to bardzo złe, ale w niektórych przypadkach nasze rozwiązanie mogłoby zawieść. Zaraz po tym odkryłem, że programy w C przy read, jeżeli czytamy z wejścia nie kanonicznego zachowują się tak samo. Pozwoliło mi to na stosowanie podobnych praktyk w nich. Główną wadą wspomnianego rozwiązania jest zmuszanie użytkownika do podania jakiś znaków na samym początku działania aplikacji. Może da się skorzystać read z przełącznikiem timeout, lecz nie testowałem. W dodatku programista, chcąc przekazać jakieś dane naszemu programowi na samym początku musiałby wysyłać mu pustą linijkę.
Zaraz po tym dostrzegłem isatty, więc wszystkie programy dokonywały tego na standardowym wyjściu i wejściu, by odkryć prawdziwe swoje otoczenie(Bash 4, a może nawet i starsze korzysta z podobnej sztuczki, lecz w celu osiągnięcia innego celu - gdy wykryje, że nie ma dostępu do terminala, przełącza się w tryb nie interaktywny, lecz robił to na standardowym wyjściu i wyjściu błędów). Te rozwiązanie powoduje liczne problemy, gdy chcemy korzystać z narzędzia w jakimś skrypcie. Wystarczy tylko przekierować jeden z deskryptorów do wyjścia, aby program się zakończył i odpalił nową instancję w oknie.
Następnie odkryłem, że mamy szereg zmiennych środowiskowych pomocniczych, więc nowsze rozwiązania w Bash-u korzystały z nich. Jednak nadal uruchamiały swoją nową instancję w xterm-ie. Te rozwiązanie było już prawie idealne.
Z pomocą przyszedł mi przełącznik -S w xterm-ie. Na początku nie zrozumiałem jego znaczenia, więc nic mi nie wychodziło. Zamiast ładnego pseudoterminala, otrzymywałem pseudoterminal niepoprawnie obsługujący znak przejścia do nowej linii, wysyłający nadesłane mu dane, itd. Problem leżał w tym, że na siłę przekazywałem xterm-owi końcówkę slave(tak wydedukowałem ze strony man-a tego narzędzia), gdy chciał mieć końcówkę master. Jesteśmy już prawie u celu - wytrzymaj trochę ;-) .
Po zamianie master/slave i slave/master otrzymałem pięknie działający terminal... Jednak zaraz - w czym? No dobrze. Przed odkryciem, że mam mu dać master pracowałem nad dwoma rozwiązaniami tego samego problemu - jedno przez bibliotekę z własną procedurą init(więc działa tylko na Linuksie i może paru innych systemach), a drugie przez aplikację uruchamiającą dwa pseudoterminale. Te drugie rozwiązanie się nie sprawdziło, lecz jako pierwsze zaczęło działać.
Pierwsze rozwiązanie polegało/polega na detekcji przy pomocy odkrytych metody czy mamy dostęp do terminala. Jak to wygląda? Przede wszystkim stosujemy starą, sprawdzoną sztuczkę z isatty, a także zmiennymi środowiskowymi: is_x_server_up i WINDOWID. Po wykryciu, że dzieje się coś złego, otwieramy pseudoterminal, uruchamiamy xterm-a z końcówką master, a następnie podmieniamy otwarte deskryptory wejścia/wyjścia/błędów na slave. Jedynym problemem jest to, że nie ustawiamy zmiennej środowiskowej WINDOWID - nie wiem, skąd mam wziąć WINDOWID okna otwartego emulatora terminala(tzn. domyślam się, ale byłyby to sztuczki zakazane), a nie jestem maintainerem xterm-a. Rozwiązanie sprawdza się. Wiele programów w C zlinkowanych z moją bibliotekę po prostu działa. Bash 4 ładujący moją bibliotekę dynamicznie w trybie interaktywnym, a także po drobnych przeróbkach(usunięciu niewielkiej części - tego z detekcją czy ma dostęp do terminala) też działa. Nawet pokusiłem się o podmianę Bash-a w swoim systemie na ten zmodyfikowany, by ponownie się zalogować - okienko terminala nie wyświetliło mi się nawet na sekundę! Tak więc stworzyłem rozwiązanie nawet działające, które może umilić życie niektórym osobom. Wystarczy tylko zlinkować niektóre programy z moim rozwiązaniem(jak np. cat, mc, nano), niektóre powinny ładować moją bibliotekę dynamicznie w razie potrzeby(jak Bash, choć jemu nie jest to potrzebne), a inne lepiej zostawić w spokoju(jak cp, rm, mkdir, touch, itd. ).
Zdaję sobie sprawę, że pewnie jeszcze dużo pracy przede mną, lecz moja biblioteka powstawała bardziej dla zabawy. Dobrze byłoby, gdybym miał możliwość emisji jakiegoś sygnału, gdy aplikacja chce czytać ze standardowego wejścia(SIGSTOP w ustawieniach kontrolnych?) jednak sobie na razie odpuszczę. Czekam na wszelkie sugestie z waszej strony. Wiem, że mnie zabijecie za ten szatański pomysł - przecież jest opcja \"uruchom w terminalu\", ale nie odbierajcie mi radości z zabawy ;-).
Wyjaśnienie, co do tytułu. Rozwiązanie wygląda podobnie do tych z systemów Redmount. Mamy tam wartość w nagłówku pliku wykonywalnego, która określa podsystem(POSIX, GUI, Console, itd. ). W moim wypadku dodajemy nazwę mojej biblioteki do tabeli importów. Choć pierwotnie się na tym nie wzorowałem, to jednak mógłbym(aż dreszcz przechodzi po plecach, że jednak mają dosyć ładne rozwiązania niekiedy).
Pobierz źródła: http://slawek.lach.art.pl/cli2gui-lib.tar.gz
 | [1 - 1] |  |
|
|
| |