Dass die "60 Sekunden" Verzögerung im Timer-Dialog beim Abschalten von Karmic Koala (und wohl auch Lucid Lynx)
sich nicht einfach anpassen lassen hat ja schon verschiedene Leute geärgert.
Die Lösung für dies Problem war bisher entweder, das betreffende Programm neu zu kompilieren:
http://wiki.ubuntuusers.de/GNOME_Logouttimer_entfernen_oder_anpassen#Timer-anpassen
oder mit dem HEX- Editor die Binärdatei mit Hand zu patchen: http://forum.ubuntuusers.de/topic/moeglichkeit-um-in-60-sekunden-ausschalten-zu/
Beides ist nicht wirklich bequem.
Logouttimer patchen per Skript¶
Deshalb habe ich für das Patchen der Binärdatei jetzt ein Skript gebaut: timer60patch
Im Wesentlichen macht das Skript nicht viel anderes als beim manuellen Patchen auch,
allerdings wird hier direkt der CPU-Befehl für die Zuweisung der "60" gesucht und angepasst.
Installieren¶
Das Skript timer60patch einfach hier herunterladen: http://media.ubuntuusers.de/wiki/attachments/19/06/timer60patch ⮷
und ausführbar machen. Am einfachsten per Rechtsklick auf die Datei, bei "Eigenschaften" - [Rechte] mit dem Häkchen bei [√] ausführbar.
Ausführen¶
Das Skript muss auf jeden Fall im Terminal ausgeführt werden, am besten bei Gnome mit (Doppel-) Klick auf die Datei - [im Terminal ausführen].
Das Passwort [Enter] muss man wie immer im Terminal "blind" eintippen, der Rest erklärt sich von selbst:
- Es wird einmalig ein Backup angelegt.
- Die Zeit wird mit [+] und [-] zwischen 1 und 999 Sekunden eingestellt und mit [Enter] übernommen.
- Nachkontrolle der gepatchten Datei - danach schließen mit irgend einer Taste. Fertig.
Funktion¶
Zuerst fragt das Skript natürlich ab, ob es die Datei /usr/lib/indicator-session/gtk-logout-helper überhaupt existiert.
(sonst ist das womöglich gar kein Karmic oder Lucid ...)
Dann sichert es die Originaldatei (incl. Rechte und Zeitstempel) als /usr/lib/indicator-session/gtk-logout-helper0 .
Danach kann man die vorgeschlagene Zeit von 10 Sekunden mit [+] und [-] ändern und mit [Enter] übernehmen.
Diese Zahl wird byteweise zerlegt (schließlich arbeitet der PC mit der "Little Endian"-Bytefolge,
also 1-er zuerst, dann 256-er, 65536-er, usw., siehe http://de.wikipedia.org/wiki/Byte-Reihenfolge )
und hexadezimal für den Patch formatiert.
Dann erfolgt das Patchen der binären Datei.
Dazu wird die Orignaldatei mit xxd
in Hexadezimaldarstellung umgewandelt, die störenden Zeilenumbrüche mit tr
entfernt,
das gesuchte Muster mit sed
ersetzt und schließlich alles wieder mit xxd
in die neue Binärdatei zurückgewandelt.
(siehe dazu auch http://forum.ubuntuusers.de/topic/ersetzen-von-codemustern-in-einer-binaerdatei/ )
Zum Abschluss wird durch einen Binärvergleich mit der gesicherten Originaldatei überprüft was verändert wurde.
Das Ergebnis sollte in etwa so aussehen:
11603 74 12
Wenn hier etwas ganz anderes erscheinen würde, oder größere Unterschiede, würde man das sofort merken.
Dies ist eine sehr effektive Kontrolle ob das Skript einwandfrei funktioniert hat.
Das Skript schließt erst nach einem Tastendruck,
damit man die Ausgabe und eventuelle Fehlermeldungen auf jeden Fall lesen kann.
CPU-Befehle¶
Das Suchmuster für sed
ergibt sich aus dem, was der Compiler an Binärcode aus dem Quelltext
logout_dialog->timeout = 60;
erzeugt. Dies ist ja die direkte Zuweisung einer Konstanten an eine 32 Bit Integer-Variable (die auf dem Stack liegt).
Der Compiler setzt dies üblicherweise um in einen MOV-Befehl mit relativem Offset, bezogen auf das Register EBX, ESI oder EDI,
der die Zahl "60" (= hex "3C") direkt lädt.
Tatsächlich erscheint hier in der Binärdatei dieses Bytemuster (32-Bit Karmic):
Dieses Makro ist nicht verfügbar
C7 83 CC 00 00 00 3C 00 00 00 = mov DS:[ebx+000000CC],0000003C
( Bei 64-Bit Karmic, wie erwartet mit einem anderen Offset, und sogar auf ein anderes Register bezogen. Dort erscheint:
C7 87 60 01 00 00 3C 00 00 00 = mov DS:[edi+00000160],0000003C )
Allgemein also: C7 8y xx xx xx xx 3C 00 00 00
mit y = Registerkennung (3,6 oder 7) und xxxxxxxx = Offset
(→ zum ausprobieren: online-Disassembler: http://pvdasm.reverse-engineering.net/PVPHP.php )
Dies ist dann also das Suchmuster für sed
.
Hier das komplette Skript:
#! /bin/bash # timer60patch # patcht ab Ubuntu 9.10 den fest codierten Logoutzähler von 60 Sekunden auf einen einstellbaren Wert im Binärfile. # Autor: [track] sec=10 name=timer60patch fpath=/usr/lib/indicator-session/ fname=gtk-logout-helper # Datei vohanden ? if [ -f "$fpath$fname" ]; then echo ">$name: == Das Skript kann jederzeit mit [Strg]-C abgebrochen werden. ==" else echo ">$name: Wo ist die Datei $fname ?" echo "> Dieses Skript funktioniert erst ab Ubuntu 9.10 (Karmic). [Taste]" read -sn1 exit 1 fi # Kopie schon vohanden ? if [ -f "$fpath$fname"0 ]; then echo echo "Kopie ist vorhanden: $fpath$fname""0" echo else echo " ( Kopie sichern, das Passwort bitte )" sudo cp -p $fpath$fname $fpath$fname""0 if [ $? -gt 0 ]; then echo "Abbruch, kopieren nicht möglich. [Taste]" read -sn1 exit 2 fi echo "Kopie wurde gesichert: $fpath$fname""0" echo fi # Zeit einstellen: kb=0 until [ "$kb" == "" ]; do echo -en "\rCountdown: [$sec]sec bitte einstellen: [+][-] und bestätigen: [Enter]" read -akb -sn1 if [ "$kb" == "+" ]; then if [ $sec -lt 999 ]; then sec=$(( $sec + 1 )) ; fi elif [ "$kb" == "-" ]; then if [ $sec -gt 1 ]; then sec=$(( $sec - 1 )) ; fi fi done echo sec1=$(( $sec % 256 )) sec2=$(( $sec / 256 )) # echo [ $sec1 / $sec2 ] # optional: Anzeige der Byte-Zuordnung # Patchmuster: # Der Zahlenwert "60" wird direkt auf einer 32 bit Stack-Variablen abgelegt # bei 64-Bit System Uby 9.10: # C7 87 60 01 00 00 3C 00 00 00 = mov DS:[edi+00000160],0000003C # bei 32-Bit System Uby 9.10: # C7 83 CC 00 00 00 3C 00 00 00 = mov DS:[ebx+000000CC],0000003C # Es kann aber je nach Compilerlauf auch anders aussehen: # C7 83 xx xx xx xx 3C 00 00 00 = mov DS:[ebx+xxxxxxxx],0000003C # oder: C7 86 xx xx xx xx 3C 00 00 00 = mov DS:[esi+xxxxxxxx],0000003C # oder: C7 87 xx xx xx xx 3C 00 00 00 = mov DS:[edi+xxxxxxxx],0000003C p0=c78\\\([367]........\\\)3c00 # allgemeines Suchmuster p2=$( printf "c78\\\1%2.2x%2.2x" $sec1 $sec2 ) # Zielmuster # Patch anwenden: # (perl -pi -e 's/pattern/replacement/g' file funktioniert nicht bei binären Ausdrücken) # Andere Idee: http://www.mail-archive.com/peterboro@mailman.lug.org.uk/msg00204.html # (+ mod.: die Zeilenbegrenzung mit "tr -d \n" beseitigt.) echo echo " ( zum patchen das Passwort bitte )" # echo "sed \"s/$p0/$p2/\"" # optional: Anzeige des sed-Befehls xxd -p $fpath$fname""0 | tr -d "\n" | sed "s/$p0/$p2/" | sudo xxd -r -p - $fpath$fname if [ $? -gt 0 ]; then echo "Abbruch, patchen geht nicht. Passwort falsch ? [Taste]" read -sn1 exit 3 else echo " .. gepatcht." echo fi # nochmal binär vergleichen: cmp -l $fpath$fname""0 $fpath$fname | head echo "Der Countdown ist jetzt auf $sec Sekunden eingestellt. [Taste]" read -sn1 exit 0
track
p.s.: Ergänzungen, Korrekturen, Kommentare willkommen !