Tag Archives: Perl

Nicht mehr mein Betriebssystem

Gerade eben, Büro: Build-Umgebung für Mikrocontroller auf Embedded Device angeworfen. Dort holt ein selbst geschriebenes Perl-Skript die Versionsinformationen aus dem Mercurial und erzeugt daraus eine Datei version.h, die beim Build eingebunden ist, so dass eine Versionsnummer im fertigen Binary landet. Automatisch. Ging immer. Eben nicht.

Es hat mich eine halbe Stunde gekostet rauszufinden, dass nicht mehr wie üblich das von mir installierte Strawberry Perl aufgerufen wird, sondern ein von MinGW mitgeliefertes, dem (mindestens) ein Modul fehlt, welches in meinem Skript genutzt wird.

Abhilfe schaffte die Umsortierung der Einträge in einer der Variablen %PATH% in den Umgebungsvariablen, damit mein Perl vor dem von MinGW gefunden wird. Dass das zusätzliche Perl übrigens bei MinGW dabei war und nicht in einem der anderen Pfade versteckt war, war übrigens nur gut geraten. Vermutlich gibt es noch mehr Perl-Instanzen, die irgendwelche Software hier mitgebracht hat. Unter Windows muss ja jeder immer wieder extra seinen eigenen Scheiß mitbringen.

Mal sehen, an wieviel anderen Stellen das später knallt. Wer den entsprechenden Dialog in Windows XP sofort findet und bei der (unter Entwicklern) üblichen Anzahl von zweistelligen Einträgen auch noch ohne Copy’n’Paste in externen Editor bearbeitet, werfe den ersten Stein.

Bei Linux gibt es ein Perl und in $PATH stehen maximal 5 Ordner.

Understanding the Perl/UTF-8 Madness

Ich habe gerade eine halbe Stunde damit verbracht, mal wieder diesem grandiosen xkcd-Comic gerecht zu werden. Los ging das mit einem Link, den ich bei qbi im Blog gefunden habe: Surviving the Perl/UTF-8 Madness. Der Name des Autors kam mir bekannt vor, ich glaube Tux hat ab und zu mal Links von dessen privatem Blog fallen lassen. Ich war also gespannt, was da kommt und wurde dann leider enttäuscht.

Worum geht’s? Es geht um Perl und wie Perl mit Encodings umgeht. Seit Perl 5.8 gibt es da ein sinnvolles Vorgehen, das sich aber anscheinend noch nicht rumgesprochen hat. Nachlesen kann man das sehr gut zusammengefasst im Tutorial perlunitut. Ich fasse das hier nochmal auf deutsch zusammen, weil es da anscheinend immer noch Missverständnisse gibt.

Wichtig zu wissen: Perl unterscheidet text/character strings von byte/binary strings (und das wirkt sich auf bestimmte Befehle wie print, uc, length usw. aus). Es wird häufig behauptet, die text strings wären UTF-8. Das mag so sein, ist aber völlig irrelevant und geht am eigentlichen Problem vorbei. Wie Perl diese text strings intern darstellt, kann einem total egal sein. Wichtiger ist, wie man damit umgeht und das fasst auch perlunitut korrekt zusammen:

  1. Receive and decode
  2. Process
  3. Encode and output

D.h. alles, was von außen kommt, egal ob von Nutzereingaben, aus Dateien oder Datenbanken, ist zunächst mal ein binary string. Wenn das Zeichenketten sind, mit denen ich Zeichenkettenoperationen durchführen will, muss ich die als erstes von byte strings in character strings umwandeln. Dazu kann ich binmode setzen, einen encoding Parameter bei open nutzen oder die decode-Funktionen aus dem Module Encoding bemühen, das ist faktisch alles das selbe, Tim Toady halt.

Der zweite Schritt ist klar: process, irgendwie auf den character strings rumackern. Beim dritten Schritt, dem output aus Perl raus dann der umgekehrte Weg: ich wandle meine character strings zurück in byte strings mit dem entsprechenden Encoding meiner Zielplattform, sei es nun STDOUT, ein file oder eine Netzwerkverbindung, egal und ebenfalls egal, ob das iso8859* oder UTF-8 oder sonstwas ist. Wenn man diese drei Schritte im Kopf behält und Worte wie utf-8 flag aus seinem Hirn streicht, kommt man mit Perl und Zeichensätzen klar.

Bisschen aufpassen muss man bei Fremdmodulen, da muss man im Zweifelsfall mal genauer hinsehen, wie die das handhaben. Was man vermeiden sollte: einfach davon ausgehen, dass Perl intern UTF-8 zur Repräsentation von character strings verwendet. Damit wird man über kurz oder lang auf die Nase fallen.

Neben perlunitut gibt es noch weitere gute Quellen zum Nachlesen:

Wenn man tiefer eintauchen will, kann man auch noch perlunicode oder perluniintro lesen, aber das ist dann schon harter Stoff. ;-)

Farbige Nicknames in irssi

Als Fan von Programmen für die Konsole benutze ich natürlich irssi als IRC-Client. Für viele Funktionen, die im Standard-Umfang nicht vorhanden sind, gibt es Scripte, Tux hatte da ja auch selbst mal eins geschrieben und hier im Blog vorgestellt. Um den Chatverlauf einfacher verfolgen zu können, existiert beispielsweise das Skript nickcolor.pl, das die Nicknames der Nutzer einfärbt. Die Beschreibung in der Übersicht der Skripte ist kurz und knapp:

assign a different color for each nick

Das Skript bildet per Default einen simplen Hashwert über den Nickname, wählt anhand dessen eine Farbe aus und behält diese dann bei. Bei gleichen Nicks ist das dann immer die gleiche Farbe, was ja auch ganz sinnvoll ist.

Das Skript kann darüber hinaus noch mehr, um das rauszufinden, muss man aber einen Blick in den Quelltext werfen, entscheidend ist folgende Subroutine:

sub cmd_color {
  my ($data, $server, $witem) = @_;
  my ($op, $nick, $color) = split " ", $data;

  $op = lc $op;

  if (!$op) {
    Irssi::print ("No operation given");
  } elsif ($op eq "save") {
    save_colors;
  } elsif ($op eq "set") {
    if (!$nick) {
      Irssi::print ("Nick not given");
    } elsif (!$color) {
      Irssi::print ("Color not given");
    } elsif ($color < 2 || $color > 14) {
      Irssi::print ("Color must be between 2 and 14 inclusive");
    } else {
      $saved_colors{$nick} = $color;
    }
  } elsif ($op eq "clear") {
    if (!$nick) {
      Irssi::print ("Nick not given");
    } else {
      delete ($saved_colors{$nick});
    }
  } elsif ($op eq "list") {
    Irssi::print ("nSaved Colors:");
    foreach my $nick (keys %saved_colors) {
      Irssi::print (chr (3) . "$saved_colors{$nick}$nick" .
		    chr (3) . "1 ($saved_colors{$nick})");
    }
  } elsif ($op eq "preview") {
    Irssi::print ("nAvailable colors:");
    foreach my $i (2..14) {
      Irssi::print (chr (3) . "$i" . "Color #$i");
    }
  }
}

Hier wird für irssi ein Befehl /color definiert, den man mit folgendem ersten Argumenten bzw. weiteren Befehlen aufrufen kann:

  • save
  • set
  • clear
  • list
  • preview

Was kann man nun mit den einzelnen Befehlen anstellen? Ich gebe mal jeweils ein Beispiel mit der dazugehörigen Ausgabe, allerdings ohne Farben.

/color save gibt nichts weiter aus, speichert aber die mit set festgelegten Farben in der Datei ~/.irssi/saved_colors. Diese gespeicherten Farbzuordnungen werden beim Neustart von irssi bzw. Neuladen des Skripts wieder eingelesen.

/color set foo 7 gibt ebenfalls nichts aus, legt aber eine Zuordnung der Farbe 7 zum Nickname foo fest. 7 ist in dem Fall das, was in PuTTY gelb und auf der Konsole braun, in anderen Terminals eher orange aussieht. (Mehr zu diesem verwirrenden Thema in der englischen Wikipedia.)

/color clear foo löscht die gesetzte Farbe für foo wieder, gibt aber ebenfalls keine Statusausgabe zurück. Interessant werden dann die letzten beiden Funktionen.

/color list zeigt die aktuell gesetzten Zuordnungen in einer Liste an, bei mir sieht das derzeit so aus, die Namen sind in den Farben, wie sie auch im Chat auftauchen, die Zahlen dahinter sind erst bei dem Kopieren aus der Konsole zum Vorschein gekommen, geben aber die Farben wieder:

Mo|23:06:25 -!- Irssi: Saved Colors:
Mo|23:06:25 -!- Irssi: An-Tet (9)
Mo|23:06:25 -!- Irssi: Fabian (7)
Mo|23:06:25 -!- Irssi: Ge0rG (12)
Mo|23:06:25 -!- Irssi: IseeU (13)
Mo|23:06:25 -!- Irssi: Mupfy (3)
Mo|23:06:25 -!- Irssi: priority (3)
Mo|23:06:25 -!- Irssi: schlotze (4)
Mo|23:06:25 -!- Irssi: StarWarsFan (12)
Mo|23:06:25 -!- Irssi: StefanG (3)
Mo|23:06:25 -!- Irssi: SvenG (13)
Mo|23:06:25 -!- Irssi: thndr (12)
Mo|23:06:25 -!- Irssi: thunder (12)
Mo|23:06:25 -!- Irssi: zozi (6)
Mo|23:06:25 -!- Irssi: _MrTux_ (7)
Mo|23:06:25 -!- Irssi: _Tux_ (7)

Last not least kann man sich mit /color preview auch noch eine Liste der verfügbaren Farben ausgeben lassen:

Mo|23:19:39 -!- Irssi: Available colors:
Mo|23:19:39 -!- Irssi: Color #2
Mo|23:19:39 -!- Irssi: Color #3
Mo|23:19:39 -!- Irssi: Color #4
Mo|23:19:39 -!- Irssi: Color #5
Mo|23:19:39 -!- Irssi: Color #6
Mo|23:19:39 -!- Irssi: Color #7
Mo|23:19:39 -!- Irssi: Color #8
Mo|23:19:39 -!- Irssi: Color #9
Mo|23:19:39 -!- Irssi: Color #10
Mo|23:19:39 -!- Irssi: Color #11
Mo|23:19:39 -!- Irssi: Color #12
Mo|23:19:39 -!- Irssi: Color #13
Mo|23:19:39 -!- Irssi: Color #14

Alles in allem eine sehr praktische Erweiterung für irssi, wenn man weiß, wie man sie bedienen muss. ;-)

Keys für Upgrade auf WordPress 2.6

Gestern kam mal wieder ein neues Update für WordPress. Wir setzen hier die DE-Edition ein und da gibt es auch eine detaillierte Anleitung zum Upgrade. Dort wird einem verraten, dass es für WordPress 2.6 neue Variablen in der Datei wp-config.php gibt. Der entsprechende Abschnitt in der wp-config-sample.php sieht so aus:

// Ändere jeden SECRET_KEY in eine beliebiege, möglichst einzigartige Phrase. Du brauchst dich später
// nicht mehr daran erinnern, also mache sie am besten möglichst lang und kompliziert.
// Auf der Seite https://www.grc.com/passwords.htm kannst du dir einen Ausdruck generieren lassen.
// Bitte trage für jeden SECRET_KEY eine eigene Phrase ein.
define('AUTH_KEY', 'put your unique phrase here'); // Trage hier eine beliebige, möglichst zufällige Phrase ein.
define('SECURE_AUTH_KEY', 'put your unique phrase here'); // Trage hier eine beliebige, möglichst zufällige Phrase ein.
define('LOGGED_IN_KEY', 'put your unique phrase here'); // Trage hier eine beliebige, möglichst zufällige Phrase ein.

Jetzt ist da eine Seite angegeben, auf der man sich diese Keys erzeugen lassen kann. Das ist für den DAU ganz nett, aber schrieb nicht fefe gerade die Tage:

Man sollte denken, niemand könnte je so unglaublich dämlich sein, sich einen Krypto-Schlüssel von jemand anderem generieren zu lassen

Glücklicherweise gibt es ja noch mehr Möglichkeiten zufällige Zeichenketten zu erzeugen. Eine davon habe ich vor einigen Monaten im Beitrag Kleiner Passwortgenerator in Perl vorgestellt. Was der Beitrag verschweigt: Ich hatte wenige Tage später noch eine kleine Anpassung an dem Skript vorgenommen, die es erlaubt, beim Aufruf die Anzahl der zurückzugebenden Zeichen als Parameter zu übergeben. So war es ein leichtes die nötigen Keys für die Konfigurationsdatei von WordPress zu generieren:

perl genpasswd.pl 64

Das veränderte Skript ist jetzt übrigens auch über Penguineering Tools abrufbar.

irssi-Hilight mit Jabber

Seit einigen Jahren läuft in meiner Screen-Session neben ICQ und anderen Tools auch ein irssi, um mich mit der Welt des IRC zu verbinden. In den meisten Channels bin ich einfach nur anwesend, gelegentlich spricht mich dann aber doch jemand an. Dank hilight im irssi wird man darüber ja eigentlich informiert. Nur leider schaue ich viel zu selten in das irssi-Fenster, um das dann letztendlich auch zu sehen. (Ja, screen informiert ueber Pings in anderen Fenstern, aber da guck ich doch erst Recht nicht hin …)

Da irssi eine schicke Perl-API hat, liegt es doch nahe, ein Perl-Script zu schreiben, mit dessen Hilfe ich mich anderweitig informieren lassen kann. Sehr nahe liegt da der Instant Messenger, der sowieso immer läuft, wenn ich am Rechner sitze – konkret Jabber.

Mit dem Perl-Modul Net::Jabber ist das alles kein Problem (abgesehen von den lückenhaften Dokumentationen, insbesondere in der irssi API) und so gibt es nun das Script irssi2jabber.pl, das als irssi-Script geladen werden kann und mir nun bei jedem Hilight oder jeder privaten Nachricht, die auftreten, während ich /away bin, eine Nachricht an meinen Jabber-Account schicken.

Das Script ist etwas kommentiert, die notwendigen Einstellungen stehen ganz am Anfang und müssen in die irssi-Config. Unter der GPLv3 darf es jeder weiterverwenden, natürlich nehme ich auch Patches an, die, wenn sie nützlich sind, eingepflegt werden.

Kleiner Passwortgenerator in Perl

Aus der Reihe »Schnelles Kamel-Gehacktes« heute der Beitrag, wie man quick’n’dirty einen Passwortgenerator in Perl schreibt. Anforderungen vorher: 8 Zeichen, weil viele Linuxe sowieso dahinter abhacken; nur Zeichen, die in den ersten 7 Bit der ASCII-Tabelle stehen und dann auch nur welche, die man direkt oder mit Umschalttaste (Shift) eingeben kann, nichts wozu man AltGr oder ähnliches bräuchte. Dazu braucht man eine ASCII-Tabelle und dann geht’s los:

#!/usr/bin/perl -w
# $Id: gen_passwd.pl 111 2008-02-06 13:45:24Z alex $
use strict;

my @allowed_chars;
# ASCII von 0x21 bis 0x3f
# das sind die meisten Sonderzeichen und die Ziffern
for (my $i=0x21; $i<=0x3f; $i++) {
	push @allowed_chars, chr($i);
}

# ASCII von A bis Z
for (my $i=0x41; $i<=0x5a; $i++) {
	push @allowed_chars, chr($i);
}

# ASCII von a bis z
for (my $i=0x61; $i<=0x7a; $i++) {
	push @allowed_chars, chr($i);
}

push @allowed_chars, chr(0x5f); # '_'

my $char_count = scalar @allowed_chars;

for (my $i=0; $i<8; $i++) {
	print $allowed_chars[int rand $char_count];
}

print "\n";

Diese Passwörter eignen sich gut als initiale Passwörter für neue Nutzer. Die Nutzer sollten sodann aufgefordert werden, sich mit passwd ein neues zu setzen. Da so ein zufälliges Passwort mit Zahlen und Sonderzeichen sehr schwer zu merken ist, werden sie dieser Aufforderung sicher nachkommen.

Binary H(e)art

binary heart Heute schrieb die ettercat einen Link auf nebenstehenden Comic von xkcd.com ins IRC. Die Seite hat mich schon des öfteren mit wirklich lustigen Comics begeistert, zumal einige nur mit entsprechendem Geek-Hintergrundwissen wirklich lustig sind. Nummer 99 – »binary heart« – trifft vom Untertitel der Seite (»A webcomic of romance,
sarcasm, math, and language.«) klar den romantischen Teil. Aber ganz ehrlich, seid Ihr nicht auch total neugierig, ob sich hinter den Nullen und Einsen im Bild nicht noch eine zusätzliche Botschaft verbirgt? Ich war es jedenfalls und da nur selbst dekodieren schlau macht, hab ich frei nach dem Perl-Motto »Es gibt mehr als einen Weg, etwas zu tun« die Zeichen einzeln abgetippt und ein kleines Skript geschrieben.

Hart (siehe Titel ;-)) war da dran einerseits das Abtippen vom Comic – man verrutscht schon sehr leicht in Zeile und Spalte – und andererseits um Mitternacht die eingerosteten Perl-Kenntnisse zu reaktivieren. Wer sich gern selbst an einem Progrämmchen in beliebiger Sprache probieren will, kann sich die binär codierte Nachricht runterladen, die Textdatei, wo ich mal die Einsen und Nullen abgetippt habe.

Ach und für die ganz Neugierigen oder zur Kontrolle des eigenen Programms hier noch die Auflösung:

iloveyOuilOveyouiloveyOuilOveyOuiloveyouilOveyouilOveyOuilOv

Fangen und Werfen

Als heute im Büro zwischenzeitlich der Subversion-Server nicht erreichbar war, so dass ich meinen Commit nicht machen konnte, unternahm ich einen Spaziergang im Haus zum verantwortlichen Admin. Der war zwar nicht da, aber im gleichen Büro unterhielt ich mich dann mit einem großen Fan von Python. Ich habe dann mal bei Wikipedia nachgelesen und bin über folgenden Satz gestolpert:

Python unterstützt (und nutzt ausgiebig) die Ausnahmebehandlung (engl. exception handling) als ein Mittel, um Fehlerbedingungen zu testen. Dies ist so weit in Python integriert, dass es sogar möglich ist, Syntaxfehler abzufangen und zur Laufzeit zu behandeln.

Das fand ich schon ziemlich krass. Das Programm kann also stellenweise syntaktisch fehlerhaft geschrieben sein, der Compiler meckert nicht und ich kann das selbst abfangen – coole Sache. Weil ich das ganze sowieso noch für die Arbeit mit .NET und C# brauche und mich das auch für den Perl-Parser für IMPULS interessiert, habe ich mich dann mal ganz allgemein mit Exceptions beschäftigt. Richtig schmunzeln musste ich als alter Handballer über die verwendeten Begriffe. Die Exception wird geworfen und irgendwo sitzt ein Catch-Block, der die irgendwann auffängt. Bildlich vorgestellt kann ich da beim Schreiben dieses Satzes gerade immernoch lachen. happy

Meine Glaskoogle hat mir dann für Exceptionhandling mit Perl die Seite Object Oriented Exception Handling in Perl ausgespuckt, wo das alles schön erklärt ist. Jetzt ratet doch mal, was bei der Ausführung des folgenden leicht abgewandelten Beispiels von jener Seite passiert:

#/usr/bin/perl -w
use Error qw(:try);
try {
	some code;
	code that might throw an exception;
	more code;
	return;
}
catch Error with {
	my $ex = shift;	# Get hold of the exception object
	print "handle the exception\n";
}
finally {
	print "do some more cleanup\n";
};	# < -- Remember the semicolon

lol2