Prompt in Midnight commander unter SuSe
Was mir unter SuSe hier in der Firma immer schon am Nerv ging:
Das Prompt in der Kommandozeile veränderte sich nie je nach Verzeichnis, in welchem man gerade war.
Folglich muss man dann immer pwd eingeben, um sicherzugehen, in welchem Pfad man ist.
Die Ursache ist das PROMPT_COMMAND in /etc/profile, welches nicht sehr mc-Kompatibel ist.
Lösung: einfach durch folgendes austauschen:
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'
strace für DOS
Auf der Suche nach einer Art strace
für DOS, also einem Tool, welches die DOS-Funktionsaufrufe trackt und in einer Protokolldatei mitschreibt, bin ich auf folgendes sehr Nützliches Tool gestoßen, welches ich meinen Blog-Lesern nicht vorenthalten möchte:
Trace: A tool for logging operating system call transactions
Messagebox mit Timeout
Nachdem Zeit Geld ist und jemand nicht unbedingt immer die Nerven hat eine Messagebox wegzuklicken habe ich heute mal schnell eine MessageBox mit Timeout programmiert.
Das Prinzip ist denkbar simpel: Messagebox Hooken, Windowhandle bei Initialisierung holen, Timer Setzen und bei Timeout default-Button drücken.
Dabei bin ich jedoch durch einen Programmierfehler (vergessen die Timerprozedur in SetTimer anzugeben) auf ein interessantes Verhalten gestoßen:
Scheinbar reicht es, einen Timer mit der ID 1 mit SetTimer
in der MessageBox anzulegen, der dann nach Ablauf der Zeit ein WM_TIMER an die Messagebox sendet. Vermutlich hat die Dialogprozedur des Systems schon von sich aus eine Logik dahinter, die die Box dann schließt.
Code siehe hier: MessageBox mit Timeout
Eine noch interessantere Lösung habe ich dann schließlich in der MSDN gefunden:
KB181934
Update (15.05.2009): Eine noch interessantere Lösung dafür ist die Verwendung der internen API, welche scheinbar auch von MessageBox verwendet wird. Siehe hierzu diesen CodeProject Artikel.
Empfangendes Interface bei UDP-Kommunikation finden
Ich schreibe zur Zeit privat an einer kleinen RIS (Remote-Installation)-Lösung, mit der man übe rPXE ein Betriebssystem bequem und einfach übers Netzwerk installieren kann.
Dafür wollte ich auch ein kleines Feature einbauen, mit welchem man Tokens (derzeit nur einen Token) im Textfile, welches die Menüstruktur des PXE-Menüs beschreibt, hinterlegen kann, welche dann entsprechend ersetzt werden.
Konkret handelte es sich um einen Token, welcher die IP-Adresse des TFTP-Servers angeben soll.
Um Knoppix über PXE zu booten, habe ich das gepatchte Koppix verwendet, welches statt über NFS auch über SMB booten kann. Hier der entsprechend gepatchte Knoppix-Kern.
Leider benötigt dieser bei der Pfadangabe des zu bootenden Servers unbedingt die IP und kann den Namen scheinbar nicht auflösen. Da ich den Server aber möglichst flexibel halten will, dachte ich mir, ich lasse meinen TFTPD einfach die IP des Interfaces einsetzen, über den der TFTP-Server den Client bedient.
Doch das herauszufinden gestaltet sich leider alles Andere als einfach.
Ich binde den TFTPD auf alle Interfaces (INADDR_ANY). Danach verwende ich recvfrom
und sendto
, um Requests zu erhalten bzw. zu beantworten. Damit funktioniert das Ganze ja recht einfach, beim recvfrom
erhalte ich die CLIENT-Adresse, die ich bei sendto
wieder angeben muss. Doch wie bekomme ich die IP des Interfaces?
Die erste Idee war, getsockname
nach dem ersten recvfrom
zu verwenden. Unter BSD-Artigen Systemen ist in der resultierenden Strutur dann die jeweils verwendete Adresse zu finden (sockaddr_in
). Groß war die Ernüchterung, als unter Windows jedoch 0.0.0.0
drinnen stand. Warum das so ist erklärt der Artikel Q129065 der Microsoft Knowledge Base.
Na prima, dort steht eindeutig: Applications should not assume that they can get the IP address of the interface.
. Damit wollte ich mich aber nicht zufrieden geben. Irgendwie muss es doch möglich sein, trotzdem das zuständige interface herauszufinden.
Schließlich kam ich auf folgende Idee, die als Workaround ganz gut funktioniert:
Von recvfrom
ist ja die IP des Clients bekannt. Also müssen wir Winsock einfach fragen, welches Interface die beste Route dorthin hat.
Mein Workaround:
DWORD br;
WSAIoctl (sock, SIO_ROUTING_INTERFACE_QUERY, &client, sizeof(client),
&server, sizeof(server), &br, 0, 0);
Gewinnt zwar keinen Schönheitspreis, aber mir ist auch keine bessere Lösung dafür bekannt.
6bit auf 8bit Farbpalette konvertieren
Der Maskenhandler für die Terminalausgabe von unserem Softwarepaket unterstützt auch ANSI-Color Farbterminals mit einer 6bit breiten Palette (sprich 64 Farben).
Hat man jedoch gerade kein Terminal bei der Hand, kann man auch einen Terminalemulator wie z.B. PuTTY verwenden.
Dieses unterstützt bereits 256 Farben nach der xterm-Emulation. Nun wollte ich also auch auf meinen xterm Farben haben und nicht immer nur mit vt100 herumzugrundeln.
Aus diesem Grund musste also die 6bit – Palette auf eine 8bit Palette gemappt werden. In unserem termcap-File konnte man auch die einzelnen Farbwerte definieren, bloß welche Werte nehmen, wenn man eine größere Palette hat als die verwendete EGA-Palette?
Ich habe im Internet nach einer Mapping-Tabelle oder einem kleinen Konvertierungsscript gesucht. Nach langem, vergeblichen Suchen habe ich dann schließlich beschlossen, selbst ein kleines Programm zu schreiben, welches die Konvertierung vornimmt:
Zuerst werden beide Paletten im Speicher angelegt, dann wird die 6bit-Palette durchgegangen und jeder Eintrag wird an den nähesten RGB-Wert der 8bit Palette angeglichen. Dieser Index wird dann genommen und siehe da: Die Palette ist konvertiert.
Das Programm schreibt einfach die einzelnen Farbstufen und den zugehörgen Palettenwert in unserem Termcap-Format auf stdout. Viell. kann es ja auch einer meiner Leser brauchen?
Quellcode gibt’s jedenfalls hier.
Compilieren einfach mit gcc -o palette palette.c
oder mit jedem beliebigen anderen C-Compiler.
Die Portnummern-Kopfnuss
Alles begann damit, dass Genosse Chefprogrammierer zu mir kam furchtbar schimpfend über unsere RPC-Library.
Als ich ihn fragte, was denn los sei, meinte er, dass bei einem unserer Kunden immer wieder die Portverbindung abreißt und der dortige Techniker von uns als Beweis, dass es nicht an unserer Software liegt, tcpdumps der Sessions wollte.
Faktisch kann es nicht an unserer SW liegen, weil wenn alle User gleichzeitig disconnectet werden, jedem User aber eine eigene Logon-Session mit eigener Socketverbindung zugeordnet ist, dann wäre das schon ein sehr merkwürdiger Zufall. Aber nachdem das Problem angeblich seit Versionseinspielung auftritt, sollten wir also den Beweis antreten.
Der Genosse hatte versucht, mithilfe von tethereal
die Datenströme je nach Ports zu filtern. Da kam aber nix. Gar nix. Nicht mal wenn man eine Verbindugn machte auf den Port. Kein SYN-Paket, einfach nix.
Also habe ich gemeint, man könnte es ja mal mit tcpdump
probieren. Selbes Resultat: Kein Mucks.
Das kam mir jetzt schon etwas spanisch vor.
Unsere Applikation startet über xinetd einen Hostextender (der rennt über stdio und wird über xinetd mittels tream eben durchgepiped). Der Hostextender läuft auf einem in /etc/services eingetragenen Port, der Port wird daher zu einem Namen aufgelöst.
Nun lag die Vermutung nahe, dass es sich viell. um ein xinetd-Problem handeln könnte (wenngleich tcpdump ja im promicious mode eigentlich alles mitkriegen sollte, was da so abläuft). Andere xinetd-Dienste belauscht, da funktionierte es problemlos.
Die nächste Strategie war, einmal mit iptraf
nachzusehen, wo denn nun der Traffic läuft, wenn man etwas im Terminalemulator tut. Da sah man, dass die Verbindung auf Port 3464 lief.
Suchte man im netstat nach dem Port, so fand man keine Verbindung gelistet. Gespenstisch. Und immer wenn man auf Port 3464 verband, erhielt man auch die freundliche Login-Hilfe des Hostextenders.
Wir habe ndann mal verifiziert, ob auf anderen Rechner auch auf diesem Port der Hostextender läuft. War überall dort anzutreffen. Mit tcpdump
auf 3464 konnte man auchdie Datenströme dumpen.
Nun war das Problem zwar eigenltihc gelöst, aber etwas mulmig war uns doch bei der Sache. woher kommt diese wundersame Portnummer, die wir noch nie gesehen haben. Laut /etc/services irgendein edm-mgr-sync. Merkwürdig.
Nach längerem Suchen und grübeln sah ich mir nochmals die Portnummer an: 69000.
Da fiel es mir wie Schuppen von den Augen, was neulich der neue Kollege aus der Technik bereits bei meiner Erklärung unseres Terminalemulator-Systems eingewandt hatte: Gibt’s net nur 65535 Ports?
Daran hatte bis jetzt niemand gedacht, weil wenn man das auf einen short
castet kommt immer der richtige Wert raus. tcpdump
und Konsorten haben aber scheinbar keine Bereichsüberprüfung und fressen alles 1:1, sie arbeiten ja im promicious mode und sich nicht gezwungen, das socket-Struct zu befüllen, welches als Datentyp short
vorgibt.
# tcpdump port 9999999094835023480523749807529304870592374895273405273489057029345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
funktioniert also genauso. Autsch!
Zwischen PuTTY Fenstern mittels Hotkey wie unter Unix wechseln
Wie ja schon in meinem Dualhead-Beitrag erwähnt, arbeite ich mit 2 Schirmen im Büro.. Links das Windows-Zeugs, rechts das Terminal auf Vollbild.
Das klappt soweit ganz gut, allerdings habe ich natürlich immer mind. 5 Terminals gleichzeitig offen, zwischen denen ich immer wieder hin- und herschalten muss. Das ist mühsam mit ALT+TAB, um immer das richtige Terminal zu suchen. Es wäre daher wünschenswert, dass man – wie unter Unix üblich – mittels ALT-F1 bis ALT-F10 zwischen den einzelnene offenen Konsolen herumwechseln kann.
Genau das habe ich mit einem kleinen Programm nun realisiert:
Es legt sich auf die Tastenkombinationen STRG + ALT + F[1..12] und öffnet das jeweilige PuttY-Fenster in der Reihenfolge, wie die Fenster geöffnet wurden.
Ich öffne also alle benötigten PuTTY-Fenster, gib sie am rechten Schirm auf Vollbild (in den Optionen unter Window/Behaviour auf [x] Full screen on ALT+Enter und dann am rechten Schirm ALT+ENTER).
Sobald mein Utility im Hintergrund läuft, kann ich nun mit den oben genannten Tastenkombinationen auf den Terminals hin- und herschalten.
Sourcecode gibts hier
Das fertige Kompilat als Mini-EXE (3k) gibts hier
Combobox mit Autocomplete
Um einer comobox Autocomplete-Funktionalität zu verleihen, muss man diese wie gewohnt Subclassen.
Allerdings ist zu beachten, dass man nicht in jedem Fall Autocomplete darf. Drückt der User z.B. Backspace oder ENTF, so darf die Routine dafür nicht anspringen, sonst könnte er ja nichts mehr löschen.
Um dies zu erreichen, muss auch das zur Combobox zugehörige Edit-Control gesubclassed werden.
Möchte man die Combobox während der Eingabe aufgeklappt lassen, so ist zu beachten, dass das Auf- und zuklappen mittels PostMessage() gesteuert werdenm uss, andernfalls befindet sich das Control in einem inkonsistenten Status, welcher glaubt, dass die linke Maustsate gedrückt ist und somit den Eingabefokus der Maus “stiehlt”.
Ein kleines Beispiel C-Modul gibts hier
Dualhead: Fenster nur auf erstem Schirm (Desktop) minimieren
Im Büro habe ich ja wie erwähnt einen neuen Rechner bekommen. Das Schöne ist: Er kann dualhead, das beduetet, ich kann 2 Monitore anschließen und habe daher einen erweiterten Desktop.
Sehr nett zum Entwickeln: Rechts auf Vollbild das Terminal, links die Windowsprogramme und unseren Terminalemulator. Dh: Testen links, entwickeln rechts.
Sehr praktisch ansich. Nur habe ich leider dummerweise die Angewohnheit, die Programme zum Testen immer über die Desktop-Icons aufzurufen und alte schlechte Gewohnheiten wird man schwer los wie es scheint.
Daher hat mich folgendes Windows-Verhalten sehr genervt:
Wenn man auf “Desktop anzeigen” klickt oder WIN+M oder WIN+D drückt, werden die Fenster auf allen Schirmen minimiert. Um hier Abhilfe zu schaffen habe ich mir daher ein kleines C-Programm geschrieben welches nur die Fenster am primary display (Desktop) minimiert:
Sourcecode gibts hier.
Das fertige Kompilat als Mini-Exe (3k) gibts hier.
Viell. kanns ja noch wer brauchen. Die .exe einfach irgendwo hinkopieren und dann in der Taskbar verknüpfen. Bei Ausführung werden alle Fenster am primary Display minimiert.
ALTGR – Tastenkombinationen (z.B. Backslash) mit Remotedesktopverbindung
Ich habe dieser Tage einen neuen Bürorechner bekommen und habe mir diesem mit Windows XP eingerichtet. Ich benutze den Rechner auch, um via Remotedesktopverbindung (RDP) auf meinen Rechner zuhause zuzugreifen. Mit dem alten Rechner hat dies wunderbar geklappt, mit dem neuen jedoch hatte ich Probleme bei Tastenkombinationen, welche mit ALT GR arbeiteten (z.B. Backspace eingeben). Das Ganze funktionierte mit Glück manchmal, meistens jedoch nicht. Im Internet wurde dazu geraten, statt ALT GR die Tastenkombination CRTL+ALT zu benutzen, damit funktioniert es. Das ist für mich aber keine befriedigende Lösung, da man beim Eintippen immer “umdenken” muss, was den Arbeitsfluss ziemlich stört.
Nach einiger Rercherche im Internet bin ich schließlich auf folgenden Newsgroup-Eintrag gestoßen, welcher eine befriedigende Lösung für das Problem aufzeigt:
Remote-Desktop und Systemtasten (Alt, Alt-Gr, Shift) + Lösungen
Um es kurz zusammenzufassen:
Man muss am lokalen Rechner (der,w elcher die RDP aufbaut) folgende einstellungen unter Systemsteuerung -> Regions- und Sprachoptionen ->
Registerkarte Sprachen -> Button Details tätigen:
1. Unter “Installierte Dienste” muss der Tastaturtreiber “Englisch
(USA)” / US installiert sein
2. Auf der Registerseite “Erweitert” muss unbedingt die Option “Alle
erweiterten Textdienste deaktivieren” deaktiviert sein (also eine
doppelte Verneinung -> die erweiterten Textdienste funktionieren)
Wen so wie mich das Weechseln des Layouts bei mehreren installierten Layouts mittels iener Tastenkombination stört (weil sich das Ganze ständig umschaltet), der kann noch unter dem Buton “Tastatur..” die Tastenkombination zum Wechsel des Eingabegebitssschemas abstellen.
Seitdem funktioniert mein Backspace wieder mit RDP.