Słowo aplikacja nie bez powodu jest w cudzysłowiu. Tak naprawdę to bash-owy skrypt umieszczony w odpowiedniej strukturze katalogowej wykorzystujący narzędzie Pashua. W sumie najbardziej mi odpowiada ten sposób ale pomyślałem sobie, że w ramach ćwiczeń spróbuje zrobić jak najprostsze ale w miarę funkcjonalne GUI do xfreerdp. Stąd cała zabawa z Pashua.
Aplikacje w OSX są aplikacjami dzięki rozszerzeniu .app, tak naprawdę to katalog w którym są umieszczone pliki i zasoby niezbędne do działania programu. Moją “aplikację” postanowiłem nazwać “XFreerdp Client”. Jej zawartość wygląda następująco (“Show package content” z menu podręcznego):
Info.plist - to plik zawierający informacje o aplikacji. Zdefiniowana jest w nim nazwa pliku, który ma byc uruchomiony, ikony, wersji, architektury itp.
rdp_connect - to skrypt, który jest uruchamiany
rdp_connect_image.png - obraz który jest wyświetlany w oknie Pashua
Klucz LSUIElement z wartością ustawioną na 1 powoduje, że aplikacja nie pojawia się w Dock-u, co ma sens bo i tak po kliknięciu OK uruchamia się xfreerdp. Modyfikację powyższego klucza można wykorzystać w dowolnym programie, którego nie chcemy widzieć w Dock-u.
Pashua daje całkiem spore możliwości jeżeli chodzi o wprowadzanie danych. Może to być pole tekstowe, pole hasła, check box, lista rozwijana, przycisk.
#!/bin/bash -lxfreerdp=`which xfreerdp`if[ ! -f $HOME/.serverauth.* ]then osascript -e 'launch application "Xquartz"'fiif[ ! "$DISPLAY"]thenexport DISPLAY=:0
fipashua_run(){# Write config filepashua_configfile=`/usr/bin/mktemp /tmp/pashua_XXXXXXXXX`echo"$1" > $pashua_configfilebundlepath="Pashua.app/Contents/MacOS/Pashua"if["$3"=""]thenmypath=`dirname "$0"`for searchpath in "$mypath/Pashua""$mypath/$bundlepath""./$bundlepath"\"/Applications/$bundlepath""$HOME/Applications/$bundlepath"doif[ -f "$searchpath" -a -x "$searchpath"]thenpashuapath=$searchpathbreakfidoneelse# Directory given as argumentpashuapath="$3/$bundlepath"fiif[ ! "$pashuapath"]thenecho"Error: Pashua could not be found"exit 1
fi# Manage encodingif["$2"=""]thenencoding=""elseencoding="-e $2"fi# Get resultresult=`"$pashuapath"$encoding$pashua_configfile| sed 's/ /;;;/g'`# Remove config file rm $pashua_configfile# Parse resultfor line in $resultdokey=`echo$line| sed 's/^\([^=]*\)=.*$/\1/'`value=`echo$line| sed 's/^[^=]*=\(.*\)$/\1/'| sed 's/;;;/ /g'`varname=$keyvarvalue="$value"eval$varname='$varvalue'done}# pashua_run()conf="# Set transparency: 0 is transparent, 1 is opaque*.transparency=1# Set window title*.title = Xfreerdp Client# Hosttxh.type = textfieldtxh.label = Host:Porttxh.default = 192.168.1.1:8403txh.width = 150# User nametxu.type = textfieldtxu.label = Usertxu.default = itoutline.metxu.width = 120# Passwordpw.type = passwordpw.label = Passwordpw.default = Secret!pw.width = 120# Resolution - radiobuttonsres.type = radiobuttonres.label = Resolutionres.option = 1024x768res.option = 1280x800res.option = 1440x900res.option = 1920x1080res.option = fullscreenres.default = 1280x800# Connection Speed - popup menupopspeed.type = popuppopspeed.label = Connection Speedpopspeed.width = 100popspeed.option = lanpopspeed.option = broadbandpopspeed.option = modempopspeed.default = lan# Console sessioncons.type = checkboxcons.label = Connect to console sessioncons.rely = -18cons.default = 0# Compressioncompres.type = checkboxcompres.label = Enable compressioncompres.rely = -18compres.default = 1# desktop compositioncompos.type = checkboxcompos.label = Enable desktop compositioncompos.rely = -18compos.default = 0# kill x after dissconectionkillx.type = checkboxkillx.label = Exit Xquartz after disconnectionkillx.rely = -18killx.default = 0# Add a cancel button with default labelcb.type=cancelbutton"# Set the images' paths relative to this file's path /# skip images if they can not be found in this file's pathbgimg=$(dirname "$0")'/rdp_connect_image.png'if[ -e "$bgimg"]then# Display background imageconf="$conf bg.type = image bg.x = 70 bg.y = 40 bg.path = $bgimg"fipashua_run "$conf"if[[$cons==1]];thencons="-0"elsecons=""fiif[[$res== fullscreen ]];thenres="-f"elseres="-g $res"fiif[[$compres==1]];thencompres="-z"elsecompres=""fiif[[$compos==1]];thencompos="--composition"elsecompos=""fiif[[$cb !=1]];then$xfreerdp -u $txu -p $pw$res$cons$compres --no-rdp -x $popspeed$compos --plugin cliprdr --plugin rdpdr --data disk:HDD:$HOME -- $txhif[[$killx==1]];then osascript -e 'tell application "Xquartz" to quit'fifi
W powyższym skrypcie wart wspomnienia jest sposób w jaki uruchamiany jest serwer X. Wykorzystałem do tego osascript i przyznam, że nie znalazłem jakiegoś lepszego rozwiązania.
Uruchomienie serwera X:
osascript -e 'launch application "Xquartz"'
Zatrzymanie:
osascript -e 'tell application "Xquartz" to quit'
W poleceniu xfreerdp automatycznie ładowane są pluginy opowiedzialne za funkcjonalność schowka i dostępu do lokalnych dysków (--plugin rdpdr --data disk:HDD:$HOME), na Windowsie montowany jest katalog domowy.
Konieczne jest również zainstalowanie aplikacji Pashua. Można tego nie robić i umieść tylko binarkę (Pashua) w katalogu XFreerdp Client.app/Contents/MacOS. Ma to sens kiedy chcemy wykorzystać tylko do jednej “aplikacji” narzędzie Pashua ale jeśli chcemy przygotować więcej tego typu rozwiązań to nie najlepszym pomysłem jest umieszczanie w każdej paczce wspomnianej binarki.
Po skopiowaniu Xfreerdp Ciient.app do katalogu /Applications w Launchpadzie wygląda bardzo dobrze:
Okno generowane przez Pashua, w przypadku kiedy nie działa serwer X trzeba chwilę na nie poczekać. Pojawi się dopiero po zainicjowaniu serwera:
Nawiązana sesja:
Jeśli ktoś nie przepada za shellem albo musi pomóc komuś kto tak ma, może w całkiem prosty sposób zrobić sobie nakładkę graficzną na dowolny program, który po uruchomieniu wymaga jakichś parametrów. Rozwiązanie jest bardzo proste i oczywiście ma w związku z tym swoje ograniczenia (np. kiepska obsługa błędów a w zasadzie jej brak).